rpgmxp_types/
system.rs

1use crate::AudioFile;
2use crate::SystemTestBattler;
3use crate::SystemWords;
4use ruby_marshal::FromValue;
5use ruby_marshal::FromValueContext;
6use ruby_marshal::FromValueError;
7use ruby_marshal::IntoValue;
8use ruby_marshal::IntoValueError;
9use ruby_marshal::ObjectValue;
10use ruby_marshal::StringValue;
11use ruby_marshal::SymbolValue;
12use ruby_marshal::Value;
13use ruby_marshal::ValueArena;
14use ruby_marshal::ValueHandle;
15
16const OBJECT_NAME: &[u8] = b"RPG::System";
17
18const VARIABLES_FIELD: &[u8] = b"@variables";
19const CANCEL_SE_FIELD: &[u8] = b"@cancel_se";
20const MAGIC_NUMBER_FIELD: &[u8] = b"@magic_number";
21const ESCAPE_SE_FIELD: &[u8] = b"@escape_se";
22const BATTLE_END_ME_FIELD: &[u8] = b"@battle_end_me";
23const START_MAP_ID_FIELD: &[u8] = b"@start_map_id";
24const SHOP_SE_FIELD: &[u8] = b"@shop_se";
25const GAMEOVER_NAME_FIELD: &[u8] = b"@gameover_name";
26const WORDS_FIELD: &[u8] = b"@words";
27const SWITCHES_FIELD: &[u8] = b"@switches";
28const DECISION_SE_FIELD: &[u8] = b"@decision_se";
29const EDIT_MAP_ID_FIELD: &[u8] = b"@edit_map_id";
30const BATTLE_START_SE_FIELD: &[u8] = b"@battle_start_se";
31const BATTLE_BGM_FIELD: &[u8] = b"@battle_bgm";
32const TEST_TROOP_ID_FIELD: &[u8] = b"@test_troop_id";
33const EQUIP_SE_FIELD: &[u8] = b"@equip_se";
34const TITLE_NAME_FIELD: &[u8] = b"@title_name";
35const ENEMY_COLLAPSE_SE_FIELD: &[u8] = b"@enemy_collapse_se";
36const CURSOR_SE_FIELD: &[u8] = b"@cursor_se";
37const ELEMENTS_FIELD: &[u8] = b"@elements";
38const UNDERSCORE_FIELD: &[u8] = b"@_";
39const START_Y_FIELD: &[u8] = b"@start_y";
40const BATTLER_HUE_FIELD: &[u8] = b"@battler_hue";
41const LOAD_SE_FIELD: &[u8] = b"@load_se";
42const TITLE_BGM_FIELD: &[u8] = b"@title_bgm";
43const BUZZER_SE_FIELD: &[u8] = b"@buzzer_se";
44const WINDOWSKIN_NAME_FIELD: &[u8] = b"@windowskin_name";
45const TEST_BATTLERS_FIELD: &[u8] = b"@test_battlers";
46const BATTLEBACK_NAME_FIELD: &[u8] = b"@battleback_name";
47const PARTY_MEMBERS_FIELD: &[u8] = b"@party_members";
48const ACTOR_COLLAPSE_SE_FIELD: &[u8] = b"@actor_collapse_se";
49const GAMEOVER_ME_FIELD: &[u8] = b"@gameover_me";
50const BATTLER_NAME_FIELD: &[u8] = b"@battler_name";
51const SAVE_SE_FIELD: &[u8] = b"@save_se";
52const BATTLE_TRANSITION_FIELD: &[u8] = b"@battle_transition";
53const START_X_FIELD: &[u8] = b"@start_x";
54
55#[derive(Debug, serde::Serialize, serde::Deserialize)]
56pub struct System {
57    pub variables: Vec<Option<String>>,
58    pub cancel_se: AudioFile,
59    pub magic_number: i32,
60    pub escape_se: AudioFile,
61    pub battle_end_me: AudioFile,
62    pub start_map_id: i32,
63    pub shop_se: AudioFile,
64    pub gameover_name: String,
65    pub words: SystemWords,
66    pub switches: Vec<Option<String>>,
67    pub decision_se: AudioFile,
68    pub edit_map_id: i32,
69    pub battle_start_se: AudioFile,
70    pub battle_bgm: AudioFile,
71    pub test_troop_id: i32,
72    pub equip_se: AudioFile,
73    pub title_name: String,
74    pub enemy_collapse_se: AudioFile,
75    pub cursor_se: AudioFile,
76    pub elements: Vec<String>,
77    pub underscore: i32,
78    pub start_y: i32,
79    pub battler_hue: i32,
80    pub load_se: AudioFile,
81    pub title_bgm: AudioFile,
82    pub buzzer_se: AudioFile,
83    pub windowskin_name: String,
84    pub test_battlers: Vec<SystemTestBattler>,
85    pub battleback_name: String,
86    pub party_members: Vec<i32>,
87    pub actor_collapse_se: AudioFile,
88    pub gameover_me: AudioFile,
89    pub battler_name: String,
90    pub save_se: AudioFile,
91    pub battle_transition: String,
92    pub start_x: i32,
93}
94
95impl<'a> FromValue<'a> for System {
96    fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
97        let object: &ObjectValue = FromValue::from_value(ctx, value)?;
98        let name = object.name();
99        let name: &SymbolValue = ctx.from_value(name.into())?;
100        let name = name.value();
101
102        if name != OBJECT_NAME {
103            return Err(FromValueError::UnexpectedObjectName { name: name.into() });
104        }
105
106        let instance_variables = object.instance_variables();
107
108        let mut variables_field = None;
109        let mut cancel_se_field = None;
110        let mut magic_number_field = None;
111        let mut escape_se_field = None;
112        let mut battle_end_me_field = None;
113        let mut start_map_id_field = None;
114        let mut shop_se_field = None;
115        let mut gameover_name_field = None;
116        let mut words_field = None;
117        let mut switches_field = None;
118        let mut decision_se_field = None;
119        let mut edit_map_id_field = None;
120        let mut battle_start_se_field = None;
121        let mut battle_bgm_field = None;
122        let mut test_troop_id_field = None;
123        let mut equip_se_field = None;
124        let mut title_name_field = None;
125        let mut enemy_collapse_se_field = None;
126        let mut cursor_se_field = None;
127        let mut elements_field = None;
128        let mut underscore_field = None;
129        let mut start_y_field = None;
130        let mut battler_hue_field = None;
131        let mut load_se_field = None;
132        let mut title_bgm_field = None;
133        let mut buzzer_se_field = None;
134        let mut windowskin_name_field = None;
135        let mut test_battlers_field = None;
136        let mut battleback_name_field = None;
137        let mut party_members_field = None;
138        let mut actor_collapse_se_field = None;
139        let mut gameover_me_field = None;
140        let mut battler_name_field = None;
141        let mut save_se_field = None;
142        let mut battle_transition_field = None;
143        let mut start_x_field = None;
144
145        for (key, value) in instance_variables.iter().copied() {
146            let key: &SymbolValue = ctx.from_value(key.into())?;
147            let key = key.value();
148
149            match key {
150                VARIABLES_FIELD => {
151                    if variables_field.is_some() {
152                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
153                    }
154
155                    let variables: Vec<Option<&StringValue>> = ctx.from_value(value)?;
156                    let variables = variables
157                        .into_iter()
158                        .map(|value| {
159                            value
160                                .map(|value| {
161                                    std::str::from_utf8(value.value())
162                                        .map(|value| value.to_string())
163                                })
164                                .transpose()
165                        })
166                        .collect::<Result<_, _>>()
167                        .map_err(FromValueError::new_other)?;
168
169                    variables_field = Some(variables);
170                }
171                CANCEL_SE_FIELD => {
172                    if cancel_se_field.is_some() {
173                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
174                    }
175
176                    let cancel_se: AudioFile = ctx.from_value(value)?;
177                    cancel_se_field = Some(cancel_se);
178                }
179                MAGIC_NUMBER_FIELD => {
180                    if magic_number_field.is_some() {
181                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
182                    }
183
184                    let magic_number: i32 = ctx.from_value(value)?;
185                    magic_number_field = Some(magic_number);
186                }
187                ESCAPE_SE_FIELD => {
188                    if escape_se_field.is_some() {
189                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
190                    }
191
192                    let escape_se: AudioFile = ctx.from_value(value)?;
193                    escape_se_field = Some(escape_se);
194                }
195                BATTLE_END_ME_FIELD => {
196                    if battle_end_me_field.is_some() {
197                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
198                    }
199
200                    let battle_end_me: AudioFile = ctx.from_value(value)?;
201                    battle_end_me_field = Some(battle_end_me);
202                }
203                START_MAP_ID_FIELD => {
204                    if start_map_id_field.is_some() {
205                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
206                    }
207
208                    let start_map_id: i32 = ctx.from_value(value)?;
209                    start_map_id_field = Some(start_map_id);
210                }
211                SHOP_SE_FIELD => {
212                    if shop_se_field.is_some() {
213                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
214                    }
215
216                    let shop_se: AudioFile = ctx.from_value(value)?;
217                    shop_se_field = Some(shop_se);
218                }
219                GAMEOVER_NAME_FIELD => {
220                    if gameover_name_field.is_some() {
221                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
222                    }
223
224                    let gameover_name: &StringValue = ctx.from_value(value)?;
225                    let gameover_name = std::str::from_utf8(gameover_name.value())
226                        .map_err(FromValueError::new_other)?
227                        .to_string();
228                    gameover_name_field = Some(gameover_name);
229                }
230                WORDS_FIELD => {
231                    if words_field.is_some() {
232                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
233                    }
234
235                    let words: SystemWords = ctx.from_value(value)?;
236                    words_field = Some(words);
237                }
238                SWITCHES_FIELD => {
239                    if switches_field.is_some() {
240                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
241                    }
242
243                    let switches: Vec<Option<&StringValue>> = ctx.from_value(value)?;
244                    let switches = switches
245                        .into_iter()
246                        .map(|value| {
247                            value
248                                .map(|value| {
249                                    std::str::from_utf8(value.value())
250                                        .map(|value| value.to_string())
251                                })
252                                .transpose()
253                        })
254                        .collect::<Result<_, _>>()
255                        .map_err(FromValueError::new_other)?;
256
257                    switches_field = Some(switches);
258                }
259                DECISION_SE_FIELD => {
260                    if decision_se_field.is_some() {
261                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
262                    }
263
264                    let decision_se: AudioFile = ctx.from_value(value)?;
265                    decision_se_field = Some(decision_se);
266                }
267                EDIT_MAP_ID_FIELD => {
268                    if edit_map_id_field.is_some() {
269                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
270                    }
271
272                    let edit_map_id: i32 = ctx.from_value(value)?;
273                    edit_map_id_field = Some(edit_map_id);
274                }
275                BATTLE_START_SE_FIELD => {
276                    if battle_start_se_field.is_some() {
277                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
278                    }
279
280                    let battle_start_se: AudioFile = ctx.from_value(value)?;
281                    battle_start_se_field = Some(battle_start_se);
282                }
283                BATTLE_BGM_FIELD => {
284                    if battle_bgm_field.is_some() {
285                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
286                    }
287
288                    let battle_bgm: AudioFile = ctx.from_value(value)?;
289                    battle_bgm_field = Some(battle_bgm);
290                }
291                TEST_TROOP_ID_FIELD => {
292                    if test_troop_id_field.is_some() {
293                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
294                    }
295
296                    let test_troop_id: i32 = ctx.from_value(value)?;
297                    test_troop_id_field = Some(test_troop_id);
298                }
299                EQUIP_SE_FIELD => {
300                    if equip_se_field.is_some() {
301                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
302                    }
303
304                    let equip_se: AudioFile = ctx.from_value(value)?;
305                    equip_se_field = Some(equip_se);
306                }
307                TITLE_NAME_FIELD => {
308                    if title_name_field.is_some() {
309                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
310                    }
311
312                    let title_name: &StringValue = ctx.from_value(value)?;
313                    let title_name = std::str::from_utf8(title_name.value())
314                        .map_err(FromValueError::new_other)?
315                        .to_string();
316                    title_name_field = Some(title_name);
317                }
318                ENEMY_COLLAPSE_SE_FIELD => {
319                    if enemy_collapse_se_field.is_some() {
320                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
321                    }
322
323                    let enemy_collapse_se: AudioFile = ctx.from_value(value)?;
324                    enemy_collapse_se_field = Some(enemy_collapse_se);
325                }
326                CURSOR_SE_FIELD => {
327                    if cursor_se_field.is_some() {
328                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
329                    }
330
331                    let cursor_se: AudioFile = ctx.from_value(value)?;
332                    cursor_se_field = Some(cursor_se);
333                }
334                ELEMENTS_FIELD => {
335                    if elements_field.is_some() {
336                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
337                    }
338
339                    let elements: Vec<&StringValue> = ctx.from_value(value)?;
340                    let elements = elements
341                        .into_iter()
342                        .map(|value| {
343                            std::str::from_utf8(value.value()).map(|value| value.to_string())
344                        })
345                        .collect::<Result<_, _>>()
346                        .map_err(FromValueError::new_other)?;
347
348                    elements_field = Some(elements);
349                }
350                UNDERSCORE_FIELD => {
351                    if underscore_field.is_some() {
352                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
353                    }
354
355                    let underscore: i32 = ctx.from_value(value)?;
356                    underscore_field = Some(underscore);
357                }
358                START_Y_FIELD => {
359                    if start_y_field.is_some() {
360                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
361                    }
362
363                    let start_y: i32 = ctx.from_value(value)?;
364                    start_y_field = Some(start_y);
365                }
366                BATTLER_HUE_FIELD => {
367                    if battler_hue_field.is_some() {
368                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
369                    }
370
371                    let battler_hue: i32 = ctx.from_value(value)?;
372                    battler_hue_field = Some(battler_hue);
373                }
374                LOAD_SE_FIELD => {
375                    if load_se_field.is_some() {
376                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
377                    }
378
379                    let load_se: AudioFile = ctx.from_value(value)?;
380                    load_se_field = Some(load_se);
381                }
382                TITLE_BGM_FIELD => {
383                    if title_bgm_field.is_some() {
384                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
385                    }
386
387                    let title_bgm: AudioFile = ctx.from_value(value)?;
388                    title_bgm_field = Some(title_bgm);
389                }
390                BUZZER_SE_FIELD => {
391                    if buzzer_se_field.is_some() {
392                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
393                    }
394
395                    let buzzer_se: AudioFile = ctx.from_value(value)?;
396                    buzzer_se_field = Some(buzzer_se);
397                }
398                WINDOWSKIN_NAME_FIELD => {
399                    if windowskin_name_field.is_some() {
400                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
401                    }
402
403                    let windowskin_name: &StringValue = ctx.from_value(value)?;
404                    let windowskin_name = std::str::from_utf8(windowskin_name.value())
405                        .map_err(FromValueError::new_other)?
406                        .to_string();
407                    windowskin_name_field = Some(windowskin_name);
408                }
409                TEST_BATTLERS_FIELD => {
410                    if test_battlers_field.is_some() {
411                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
412                    }
413
414                    let test_battlers: Vec<SystemTestBattler> = ctx.from_value(value)?;
415                    test_battlers_field = Some(test_battlers);
416                }
417                BATTLEBACK_NAME_FIELD => {
418                    if battleback_name_field.is_some() {
419                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
420                    }
421
422                    let battleback_name: &StringValue = ctx.from_value(value)?;
423                    let battleback_name = std::str::from_utf8(battleback_name.value())
424                        .map_err(FromValueError::new_other)?
425                        .to_string();
426                    battleback_name_field = Some(battleback_name);
427                }
428                PARTY_MEMBERS_FIELD => {
429                    if party_members_field.is_some() {
430                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
431                    }
432
433                    let party_members: Vec<i32> = ctx.from_value(value)?;
434                    party_members_field = Some(party_members);
435                }
436                ACTOR_COLLAPSE_SE_FIELD => {
437                    if actor_collapse_se_field.is_some() {
438                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
439                    }
440
441                    let actor_collapse_se: AudioFile = ctx.from_value(value)?;
442                    actor_collapse_se_field = Some(actor_collapse_se);
443                }
444                GAMEOVER_ME_FIELD => {
445                    if gameover_me_field.is_some() {
446                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
447                    }
448
449                    let gameover_me: AudioFile = ctx.from_value(value)?;
450                    gameover_me_field = Some(gameover_me);
451                }
452                BATTLER_NAME_FIELD => {
453                    if battler_name_field.is_some() {
454                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
455                    }
456
457                    let battler_name: &StringValue = ctx.from_value(value)?;
458                    let battler_name = std::str::from_utf8(battler_name.value())
459                        .map_err(FromValueError::new_other)?
460                        .to_string();
461                    battler_name_field = Some(battler_name);
462                }
463                SAVE_SE_FIELD => {
464                    if save_se_field.is_some() {
465                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
466                    }
467
468                    let save_se: AudioFile = ctx.from_value(value)?;
469                    save_se_field = Some(save_se);
470                }
471                BATTLE_TRANSITION_FIELD => {
472                    if battle_transition_field.is_some() {
473                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
474                    }
475
476                    let battle_transition: &StringValue = ctx.from_value(value)?;
477                    let battle_transition = std::str::from_utf8(battle_transition.value())
478                        .map_err(FromValueError::new_other)?
479                        .to_string();
480                    battle_transition_field = Some(battle_transition);
481                }
482                START_X_FIELD => {
483                    if start_x_field.is_some() {
484                        return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
485                    }
486
487                    let start_x: i32 = ctx.from_value(value)?;
488                    start_x_field = Some(start_x);
489                }
490                _ => {
491                    return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
492                }
493            }
494        }
495
496        let variables = variables_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
497            name: VARIABLES_FIELD.into(),
498        })?;
499        let cancel_se = cancel_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
500            name: CANCEL_SE_FIELD.into(),
501        })?;
502        let magic_number =
503            magic_number_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
504                name: MAGIC_NUMBER_FIELD.into(),
505            })?;
506        let escape_se = escape_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
507            name: ESCAPE_SE_FIELD.into(),
508        })?;
509        let battle_end_me =
510            battle_end_me_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
511                name: BATTLE_END_ME_FIELD.into(),
512            })?;
513        let start_map_id =
514            start_map_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
515                name: START_MAP_ID_FIELD.into(),
516            })?;
517        let shop_se = shop_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
518            name: SHOP_SE_FIELD.into(),
519        })?;
520        let gameover_name =
521            gameover_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
522                name: GAMEOVER_NAME_FIELD.into(),
523            })?;
524        let words = words_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
525            name: WORDS_FIELD.into(),
526        })?;
527        let switches = switches_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
528            name: SWITCHES_FIELD.into(),
529        })?;
530        let decision_se =
531            decision_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
532                name: DECISION_SE_FIELD.into(),
533            })?;
534        let edit_map_id =
535            edit_map_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
536                name: EDIT_MAP_ID_FIELD.into(),
537            })?;
538        let battle_start_se =
539            battle_start_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
540                name: BATTLE_START_SE_FIELD.into(),
541            })?;
542        let battle_bgm =
543            battle_bgm_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
544                name: BATTLE_BGM_FIELD.into(),
545            })?;
546        let test_troop_id =
547            test_troop_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
548                name: TEST_TROOP_ID_FIELD.into(),
549            })?;
550        let equip_se = equip_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
551            name: EQUIP_SE_FIELD.into(),
552        })?;
553        let title_name =
554            title_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
555                name: TITLE_NAME_FIELD.into(),
556            })?;
557        let enemy_collapse_se =
558            enemy_collapse_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
559                name: ENEMY_COLLAPSE_SE_FIELD.into(),
560            })?;
561        let cursor_se = cursor_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
562            name: CURSOR_SE_FIELD.into(),
563        })?;
564        let elements = elements_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
565            name: ELEMENTS_FIELD.into(),
566        })?;
567        let underscore =
568            underscore_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
569                name: UNDERSCORE_FIELD.into(),
570            })?;
571        let start_y = start_y_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
572            name: START_Y_FIELD.into(),
573        })?;
574        let battler_hue =
575            battler_hue_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
576                name: BATTLER_HUE_FIELD.into(),
577            })?;
578        let load_se = load_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
579            name: LOAD_SE_FIELD.into(),
580        })?;
581        let title_bgm = title_bgm_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
582            name: TITLE_BGM_FIELD.into(),
583        })?;
584        let buzzer_se = buzzer_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
585            name: BUZZER_SE_FIELD.into(),
586        })?;
587        let windowskin_name =
588            windowskin_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
589                name: WINDOWSKIN_NAME_FIELD.into(),
590            })?;
591        let test_battlers =
592            test_battlers_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
593                name: TEST_BATTLERS_FIELD.into(),
594            })?;
595        let battleback_name =
596            battleback_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
597                name: BATTLEBACK_NAME_FIELD.into(),
598            })?;
599        let party_members =
600            party_members_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
601                name: PARTY_MEMBERS_FIELD.into(),
602            })?;
603        let actor_collapse_se =
604            actor_collapse_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
605                name: ACTOR_COLLAPSE_SE_FIELD.into(),
606            })?;
607        let gameover_me =
608            gameover_me_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
609                name: GAMEOVER_ME_FIELD.into(),
610            })?;
611        let battler_name =
612            battler_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
613                name: BATTLER_NAME_FIELD.into(),
614            })?;
615        let save_se = save_se_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
616            name: SAVE_SE_FIELD.into(),
617        })?;
618        let battle_transition =
619            battle_transition_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
620                name: BATTLE_TRANSITION_FIELD.into(),
621            })?;
622        let start_x = start_x_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
623            name: START_X_FIELD.into(),
624        })?;
625
626        Ok(Self {
627            variables,
628            cancel_se,
629            magic_number,
630            escape_se,
631            battle_end_me,
632            start_map_id,
633            shop_se,
634            gameover_name,
635            words,
636            switches,
637            decision_se,
638            edit_map_id,
639            battle_start_se,
640            battle_bgm,
641            test_troop_id,
642            equip_se,
643            title_name,
644            enemy_collapse_se,
645            cursor_se,
646            elements,
647            underscore,
648            start_y,
649            battler_hue,
650            load_se,
651            title_bgm,
652            buzzer_se,
653            windowskin_name,
654            test_battlers,
655            battleback_name,
656            party_members,
657            actor_collapse_se,
658            gameover_me,
659            battler_name,
660            save_se,
661            battle_transition,
662            start_x,
663        })
664    }
665}
666
667impl IntoValue for System {
668    fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
669        let object_name = arena.create_symbol(OBJECT_NAME.into());
670
671        let variables_field_key = arena.create_symbol(VARIABLES_FIELD.into());
672        let cancel_se_field_key = arena.create_symbol(CANCEL_SE_FIELD.into());
673        let magic_number_field_key = arena.create_symbol(MAGIC_NUMBER_FIELD.into());
674        let escape_se_field_key = arena.create_symbol(ESCAPE_SE_FIELD.into());
675        let battle_end_me_field_key = arena.create_symbol(BATTLE_END_ME_FIELD.into());
676        let start_map_id_field_key = arena.create_symbol(START_MAP_ID_FIELD.into());
677        let shop_se_field_key = arena.create_symbol(SHOP_SE_FIELD.into());
678        let gameover_name_field_key = arena.create_symbol(GAMEOVER_NAME_FIELD.into());
679        let words_field_key = arena.create_symbol(WORDS_FIELD.into());
680        let switches_field_key = arena.create_symbol(SWITCHES_FIELD.into());
681        let decision_se_field_key = arena.create_symbol(DECISION_SE_FIELD.into());
682        let edit_map_id_field_key = arena.create_symbol(EDIT_MAP_ID_FIELD.into());
683        let battle_start_se_field_key = arena.create_symbol(BATTLE_START_SE_FIELD.into());
684        let battle_bgm_field_key = arena.create_symbol(BATTLE_BGM_FIELD.into());
685        let test_troop_id_field_key = arena.create_symbol(TEST_TROOP_ID_FIELD.into());
686        let equip_se_field_key = arena.create_symbol(EQUIP_SE_FIELD.into());
687        let title_name_field_key = arena.create_symbol(TITLE_NAME_FIELD.into());
688        let enemy_collapse_se_field_key = arena.create_symbol(ENEMY_COLLAPSE_SE_FIELD.into());
689        let cursor_se_field_key = arena.create_symbol(CURSOR_SE_FIELD.into());
690        let elements_field_key = arena.create_symbol(ELEMENTS_FIELD.into());
691        let underscore_field_key = arena.create_symbol(UNDERSCORE_FIELD.into());
692        let start_y_field_key = arena.create_symbol(START_Y_FIELD.into());
693        let battler_hue_field_key = arena.create_symbol(BATTLER_HUE_FIELD.into());
694        let load_se_field_key = arena.create_symbol(LOAD_SE_FIELD.into());
695        let title_bgm_field_key = arena.create_symbol(TITLE_BGM_FIELD.into());
696        let buzzer_se_field_key = arena.create_symbol(BUZZER_SE_FIELD.into());
697        let windowskin_name_field_key = arena.create_symbol(WINDOWSKIN_NAME_FIELD.into());
698        let test_battlers_field_key = arena.create_symbol(TEST_BATTLERS_FIELD.into());
699        let battleback_name_field_key = arena.create_symbol(BATTLEBACK_NAME_FIELD.into());
700        let party_members_field_key = arena.create_symbol(PARTY_MEMBERS_FIELD.into());
701        let actor_collapse_se_field_key = arena.create_symbol(ACTOR_COLLAPSE_SE_FIELD.into());
702        let gameover_me_field_key = arena.create_symbol(GAMEOVER_ME_FIELD.into());
703        let battler_name_field_key = arena.create_symbol(BATTLER_NAME_FIELD.into());
704        let save_se_field_key = arena.create_symbol(SAVE_SE_FIELD.into());
705        let battle_transition_field_key = arena.create_symbol(BATTLE_TRANSITION_FIELD.into());
706        let start_x_field_key = arena.create_symbol(START_X_FIELD.into());
707
708        let variables_field_value = {
709            let mut variables = Vec::with_capacity(self.variables.len());
710            for variable in self.variables {
711                let handle = match variable {
712                    Some(variable) => arena.create_string(variable.into()).into(),
713                    None => arena.create_nil().into(),
714                };
715                variables.push(handle);
716            }
717
718            arena.create_array(variables).into()
719        };
720        let cancel_se_field_value = self.cancel_se.into_value(arena)?;
721        let magic_number_field_value = self.magic_number.into_value(arena)?;
722        let escape_se_field_value = self.escape_se.into_value(arena)?;
723        let battle_end_me_field_value = self.battle_end_me.into_value(arena)?;
724        let start_map_id_field_value = self.start_map_id.into_value(arena)?;
725        let shop_se_field_value = self.shop_se.into_value(arena)?;
726        let gameover_name_field_value = arena.create_string(self.gameover_name.into()).into();
727        let words_field_value = self.words.into_value(arena)?;
728        let switches_field_value = {
729            let mut switches = Vec::with_capacity(self.switches.len());
730            for switch in self.switches {
731                let handle = match switch {
732                    Some(switch) => arena.create_string(switch.into()).into(),
733                    None => arena.create_nil().into(),
734                };
735                switches.push(handle);
736            }
737
738            arena.create_array(switches).into()
739        };
740        let decision_se_field_value = self.decision_se.into_value(arena)?;
741        let edit_map_id_field_value = self.edit_map_id.into_value(arena)?;
742        let battle_start_se_field_value = self.battle_start_se.into_value(arena)?;
743        let battle_bgm_field_value = self.battle_bgm.into_value(arena)?;
744        let test_troop_id_field_value = self.test_troop_id.into_value(arena)?;
745        let equip_se_field_value = self.equip_se.into_value(arena)?;
746        let title_name_field_value = arena.create_string(self.title_name.into()).into();
747        let enemy_collapse_se_field_value = self.enemy_collapse_se.into_value(arena)?;
748        let cursor_se_field_value = self.cursor_se.into_value(arena)?;
749        let elements_field_value = {
750            let mut elements = Vec::with_capacity(self.elements.len());
751            for element in self.elements {
752                let handle = arena.create_string(element.into()).into();
753                elements.push(handle);
754            }
755            arena.create_array(elements).into()
756        };
757        let underscore_field_value = self.underscore.into_value(arena)?;
758        let start_y_field_value = self.start_y.into_value(arena)?;
759        let battler_hue_field_value = self.battler_hue.into_value(arena)?;
760        let load_se_field_value = self.load_se.into_value(arena)?;
761        let title_bgm_field_value = self.title_bgm.into_value(arena)?;
762        let buzzer_se_field_value = self.buzzer_se.into_value(arena)?;
763        let windowskin_name_field_value = arena.create_string(self.windowskin_name.into()).into();
764        let test_battlers_field_value = self.test_battlers.into_value(arena)?;
765        let battleback_name_field_value = arena.create_string(self.battleback_name.into()).into();
766        let party_members_field_value = self.party_members.into_value(arena)?;
767        let actor_collapse_se_field_value = self.actor_collapse_se.into_value(arena)?;
768        let gameover_me_field_value = self.gameover_me.into_value(arena)?;
769        let battler_name_field_value = arena.create_string(self.battler_name.into()).into();
770        let save_se_field_value = self.save_se.into_value(arena)?;
771        let battle_transition_field_value =
772            arena.create_string(self.battle_transition.into()).into();
773        let start_x_field_value = self.start_x.into_value(arena)?;
774
775        let fields = vec![
776            (variables_field_key, variables_field_value),
777            (cancel_se_field_key, cancel_se_field_value),
778            (magic_number_field_key, magic_number_field_value),
779            (escape_se_field_key, escape_se_field_value),
780            (battle_end_me_field_key, battle_end_me_field_value),
781            (start_map_id_field_key, start_map_id_field_value),
782            (shop_se_field_key, shop_se_field_value),
783            (gameover_name_field_key, gameover_name_field_value),
784            (words_field_key, words_field_value),
785            (switches_field_key, switches_field_value),
786            (decision_se_field_key, decision_se_field_value),
787            (edit_map_id_field_key, edit_map_id_field_value),
788            (battle_start_se_field_key, battle_start_se_field_value),
789            (battle_bgm_field_key, battle_bgm_field_value),
790            (test_troop_id_field_key, test_troop_id_field_value),
791            (equip_se_field_key, equip_se_field_value),
792            (title_name_field_key, title_name_field_value),
793            (enemy_collapse_se_field_key, enemy_collapse_se_field_value),
794            (cursor_se_field_key, cursor_se_field_value),
795            (elements_field_key, elements_field_value),
796            (underscore_field_key, underscore_field_value),
797            (start_y_field_key, start_y_field_value),
798            (battler_hue_field_key, battler_hue_field_value),
799            (load_se_field_key, load_se_field_value),
800            (title_bgm_field_key, title_bgm_field_value),
801            (buzzer_se_field_key, buzzer_se_field_value),
802            (windowskin_name_field_key, windowskin_name_field_value),
803            (test_battlers_field_key, test_battlers_field_value),
804            (battleback_name_field_key, battleback_name_field_value),
805            (party_members_field_key, party_members_field_value),
806            (actor_collapse_se_field_key, actor_collapse_se_field_value),
807            (gameover_me_field_key, gameover_me_field_value),
808            (battler_name_field_key, battler_name_field_value),
809            (save_se_field_key, save_se_field_value),
810            (battle_transition_field_key, battle_transition_field_value),
811            (start_x_field_key, start_x_field_value),
812        ];
813
814        let object = arena.create_object(object_name, fields);
815
816        Ok(object.into())
817    }
818}