1use rakata_formats::{
4 gff_schema::{AbsentDefault, FieldLife, FieldSchema, GffType},
5 GffLocalizedString, GffStruct, GffValue,
6};
7
8use super::object_id_or_invalid;
9use crate::gff_helpers::{get_bool, get_f32, get_locstring, get_string, upsert_field};
10use crate::shared::ObjectId;
11
12#[derive(Debug, Clone, PartialEq, Default)]
50pub struct GitWaypoint {
51 pub tag: String,
53 pub object_id: ObjectId,
55 pub localized_name: GffLocalizedString,
57 pub commandable: bool,
59 pub map_note: Option<GitMapNote>,
61
62 pub x_position: f32,
64 pub y_position: f32,
66 pub z_position: f32,
68 pub x_orientation: f32,
70 pub y_orientation: f32,
72 pub z_orientation: f32,
74}
75
76#[derive(Debug, Clone, PartialEq, Default)]
78pub struct GitMapNote {
79 pub text: GffLocalizedString,
81 pub enabled: bool,
83}
84
85impl GitWaypoint {
86 pub fn from_gff_struct(s: &GffStruct) -> Self {
88 Self {
89 tag: get_string(s, "Tag").unwrap_or_default(),
90 object_id: object_id_or_invalid(s),
91 localized_name: get_locstring(s, "LocalizedName")
92 .cloned()
93 .unwrap_or_default(),
94 commandable: get_bool(s, "Commandable").unwrap_or(false),
95 map_note: get_locstring(s, "MapNote").cloned().map(|text| GitMapNote {
98 text,
99 enabled: get_bool(s, "MapNoteEnabled").unwrap_or(false),
100 }),
101
102 x_position: get_f32(s, "XPosition").unwrap_or(0.0),
103 y_position: get_f32(s, "YPosition").unwrap_or(0.0),
104 z_position: get_f32(s, "ZPosition").unwrap_or(0.0),
105 x_orientation: get_f32(s, "XOrientation").unwrap_or(0.0),
106 y_orientation: get_f32(s, "YOrientation").unwrap_or(0.0),
107 z_orientation: get_f32(s, "ZOrientation").unwrap_or(0.0),
108 }
109 }
110
111 pub fn to_gff_struct(&self) -> GffStruct {
113 let mut s = GffStruct::new(5);
114 upsert_field(&mut s, "Tag", GffValue::String(self.tag.clone()));
115 upsert_field(&mut s, "ObjectId", GffValue::UInt32(self.object_id.get()));
116 upsert_field(
117 &mut s,
118 "LocalizedName",
119 GffValue::LocalizedString(self.localized_name.clone()),
120 );
121 upsert_field(
122 &mut s,
123 "Commandable",
124 GffValue::UInt8(self.commandable.into()),
125 );
126
127 upsert_field(
128 &mut s,
129 "HasMapNote",
130 GffValue::UInt8(self.map_note.is_some().into()),
131 );
132 if let Some(note) = &self.map_note {
133 upsert_field(
134 &mut s,
135 "MapNote",
136 GffValue::LocalizedString(note.text.clone()),
137 );
138 upsert_field(
139 &mut s,
140 "MapNoteEnabled",
141 GffValue::UInt8(note.enabled.into()),
142 );
143 }
144
145 upsert_field(&mut s, "XPosition", GffValue::Single(self.x_position));
146 upsert_field(&mut s, "YPosition", GffValue::Single(self.y_position));
147 upsert_field(&mut s, "ZPosition", GffValue::Single(self.z_position));
148 upsert_field(&mut s, "XOrientation", GffValue::Single(self.x_orientation));
149 upsert_field(&mut s, "YOrientation", GffValue::Single(self.y_orientation));
150 upsert_field(&mut s, "ZOrientation", GffValue::Single(self.z_orientation));
151 s
152 }
153}
154
155pub(crate) static WAYPOINT_LIST_CHILDREN: &[FieldSchema] = &[
157 FieldSchema {
161 label: "Appearance",
162 expected_type: GffType::UInt8,
163 life: FieldLife::ReadOnlyDead(
164 "a waypoint has no rendered model to select, and no waypoint load path reads the field",
165 ),
166 required: false,
167 absent: AbsentDefault::Unverified,
168 children: None,
169 constraint: None,
170 },
171 FieldSchema {
176 label: "Description",
177 expected_type: GffType::LocalizedString,
178 life: FieldLife::ReadOnlyDead(
179 "a waypoint resolves no template, so this value has no source anywhere rather than one that goes unread",
180 ),
181 required: false,
182 absent: AbsentDefault::Unverified,
183 children: None,
184 constraint: None,
185 },
186 FieldSchema {
187 label: "Tag",
188 expected_type: GffType::String,
189 life: FieldLife::Live,
190 required: false,
191 absent: AbsentDefault::Unverified,
192 children: None,
193 constraint: None,
194 },
195 FieldSchema {
196 label: "LocalizedName",
197 expected_type: GffType::LocalizedString,
198 life: FieldLife::Live,
199 required: false,
200 absent: AbsentDefault::Unverified,
201 children: None,
202 constraint: None,
203 },
204 FieldSchema {
205 label: "Commandable",
206 expected_type: GffType::UInt8,
207 life: FieldLife::Live,
208 required: false,
209 absent: AbsentDefault::Unverified,
210 children: None,
211 constraint: None,
212 },
213 FieldSchema {
214 label: "HasMapNote",
215 expected_type: GffType::UInt8,
216 life: FieldLife::Live,
217 required: false,
218 absent: AbsentDefault::Unverified,
219 children: None,
220 constraint: None,
221 },
222 FieldSchema {
223 label: "MapNote",
224 expected_type: GffType::LocalizedString,
225 life: FieldLife::Live,
226 required: false,
227 absent: AbsentDefault::Unverified,
228 children: None,
229 constraint: None,
230 },
231 FieldSchema {
232 label: "MapNoteEnabled",
233 expected_type: GffType::UInt8,
234 life: FieldLife::Live,
235 required: false,
236 absent: AbsentDefault::Unverified,
237 children: None,
238 constraint: None,
239 },
240 FieldSchema {
241 label: "XOrientation",
242 expected_type: GffType::Single,
243 life: FieldLife::Live,
244 required: false,
245 absent: AbsentDefault::Unverified,
246 children: None,
247 constraint: None,
248 },
249 FieldSchema {
250 label: "YOrientation",
251 expected_type: GffType::Single,
252 life: FieldLife::Live,
253 required: false,
254 absent: AbsentDefault::Unverified,
255 children: None,
256 constraint: None,
257 },
258 FieldSchema {
259 label: "ZOrientation",
260 expected_type: GffType::Single,
261 life: FieldLife::Live,
262 required: false,
263 absent: AbsentDefault::Unverified,
264 children: None,
265 constraint: None,
266 },
267 FieldSchema {
271 label: "LinkedTo",
272 expected_type: GffType::String,
273 life: FieldLife::ReadOnlyDead(
274 "a waypoint has no transition capability, so there is nothing for a destination tag to name",
275 ),
276 required: false,
277 absent: AbsentDefault::Unverified,
278 children: None,
279 constraint: None,
280 },
281 FieldSchema {
285 label: "TemplateResRef",
286 expected_type: GffType::ResRef,
287 life: FieldLife::ReadOnlyDead(
288 "no waypoint load path reads it, including the script-spawn fallback, where the resref comes from the script call",
289 ),
290 required: false,
291 absent: AbsentDefault::Unverified,
292 children: None,
293 constraint: None,
294 },
295 FieldSchema {
296 label: "ObjectId",
297 expected_type: GffType::UInt32,
298 life: FieldLife::Live,
299 required: false,
300 absent: AbsentDefault::Unverified,
301 children: None,
302 constraint: None,
303 },
304 FieldSchema {
305 label: "XPosition",
306 expected_type: GffType::Single,
307 life: FieldLife::Live,
308 required: false,
309 absent: AbsentDefault::Unverified,
310 children: None,
311 constraint: None,
312 },
313 FieldSchema {
314 label: "YPosition",
315 expected_type: GffType::Single,
316 life: FieldLife::Live,
317 required: false,
318 absent: AbsentDefault::Unverified,
319 children: None,
320 constraint: None,
321 },
322 FieldSchema {
323 label: "ZPosition",
324 expected_type: GffType::Single,
325 life: FieldLife::Live,
326 required: false,
327 absent: AbsentDefault::Unverified,
328 children: None,
329 constraint: None,
330 },
331];