1use std::collections::{HashMap, HashSet};
2
3use crate::assets::RgbaImage;
4use crate::runtime::gan::GanState;
5use crate::runtime::int_event::IntEvent;
6use crate::platform_time::{Duration, Instant};
7
8use crate::image_manager::ImageId;
9use crate::layer::{LayerId, SpriteId};
10
11#[derive(Debug, Clone)]
17pub struct WipeState {
18 pub mask_file: Option<String>,
19 pub mask_image_id: Option<ImageId>,
20 pub wipe_type: i32,
21 pub wipe_time_ms: i32,
22 pub speed_mode: i32,
23 pub start_time_ms: i32,
24 pub option: Vec<i32>,
25
26 pub begin_order: i32,
27 pub end_order: i32,
28 pub begin_layer: i32,
29 pub end_layer: i32,
30
31 pub wait_flag: bool,
32 pub key_wait_mode: i32,
33 pub with_low_order: i32,
34
35 pub mask_cache: HashMap<(ImageId, u64, ImageId, u64, u16), ImageId>,
36
37 started_at: Instant,
38 end_at: Instant,
39}
40
41impl WipeState {
42 #[allow(clippy::too_many_arguments)]
43 pub fn new(
44 mask_file: Option<String>,
45 mask_image_id: Option<ImageId>,
46 wipe_type: i32,
47 wipe_time_ms: i32,
48 start_time_ms: i32,
49 speed_mode: i32,
50 option: Vec<i32>,
51 begin_order: i32,
52 end_order: i32,
53 begin_layer: i32,
54 end_layer: i32,
55 wait_flag: bool,
56 key_wait_mode: i32,
57 with_low_order: i32,
58 ) -> Self {
59 let now = Instant::now();
60 let wipe_time_ms_u = wipe_time_ms.max(0) as u64;
61 let start_ms_u = start_time_ms.max(0) as u64;
62 let start_adv = start_ms_u.min(wipe_time_ms_u);
63
64 let started_at = now
65 .checked_sub(Duration::from_millis(start_adv))
66 .unwrap_or(now);
67 let end_at = started_at + Duration::from_millis(wipe_time_ms_u);
68
69 Self {
70 mask_file,
71 mask_image_id,
72 wipe_type,
73 wipe_time_ms,
74 speed_mode,
75 start_time_ms,
76 option,
77 begin_order,
78 end_order,
79 begin_layer,
80 end_layer,
81 wait_flag,
82 key_wait_mode,
83 with_low_order,
84 mask_cache: HashMap::new(),
85 started_at,
86 end_at,
87 }
88 }
89
90 pub fn is_done(&self) -> bool {
91 Instant::now() >= self.end_at
92 }
93
94 pub fn progress(&self) -> f32 {
95 let total = self
96 .end_at
97 .saturating_duration_since(self.started_at)
98 .as_secs_f32();
99 if total <= 0.0 {
100 return 1.0;
101 }
102 let elapsed = Instant::now()
103 .saturating_duration_since(self.started_at)
104 .as_secs_f32();
105 (elapsed / total).clamp(0.0, 1.0)
106 }
107
108 #[allow(dead_code)]
109 pub fn remaining_ms(&self) -> u64 {
110 if self.is_done() {
111 0
112 } else {
113 self.end_at.duration_since(Instant::now()).as_millis() as u64
114 }
115 }
116}
117
118#[derive(Debug, Clone)]
119pub struct ScriptRuntimeState {
120 pub dont_set_save_point: bool,
121 pub skip_disable: bool,
122 pub ctrl_disable: bool,
123 pub not_stop_skip_by_click: bool,
124 pub not_skip_msg_by_click: bool,
125 pub skip_unread_message: bool,
126
127 pub auto_mode_flag: bool,
128 pub auto_mode_moji_wait: i64,
129 pub auto_mode_min_wait: i64,
130 pub auto_mode_moji_cnt: i64,
131
132 pub mouse_cursor_hide_onoff: i64,
133 pub mouse_cursor_hide_time: i64,
134
135 pub msg_speed: i64,
136 pub msg_nowait: bool,
137 pub async_msg_mode: bool,
138 pub async_msg_mode_once: bool,
139
140 pub hide_mwnd_disable: bool,
141 pub msg_back_disable: bool,
142 pub msg_back_off: bool,
143 pub msg_back_disp_off: bool,
144
145 pub cursor_disp_off: bool,
146 pub cursor_move_by_key_disable: bool,
147 pub cursor_runtime_visible: bool,
148 pub key_disable: HashSet<u8>,
149
150 pub mwnd_anime_off_flag: bool,
151 pub mwnd_anime_on_flag: bool,
152 pub mwnd_disp_off_flag: bool,
153
154 pub koe_dont_stop_on_flag: bool,
155 pub koe_dont_stop_off_flag: bool,
156
157 pub shortcut_disable: bool,
158 pub quake_stop_flag: bool,
159 pub emote_mouth_stop_flag: bool,
160 pub bgmfade_flag: bool,
161 pub wait_display_vsync_off_flag: bool,
162 pub skip_trigger: bool,
163 pub ignore_r_flag: bool,
164 pub cursor_no: i64,
165
166 pub time_stop_flag: bool,
167 pub counter_time_stop_flag: bool,
168 pub frame_action_time_stop_flag: bool,
169 pub stage_time_stop_flag: bool,
170
171 pub font_name: String,
172 pub font_bold: i64,
173 pub font_shadow: i64,
174}
175
176impl Default for ScriptRuntimeState {
177 fn default() -> Self {
178 Self {
179 dont_set_save_point: false,
180 skip_disable: false,
181 ctrl_disable: false,
182 not_stop_skip_by_click: false,
183 not_skip_msg_by_click: false,
184 skip_unread_message: false,
185 auto_mode_flag: false,
186 auto_mode_moji_wait: -1,
187 auto_mode_min_wait: -1,
188 auto_mode_moji_cnt: 0,
189 mouse_cursor_hide_onoff: -1,
190 mouse_cursor_hide_time: -1,
191 msg_speed: -1,
192 msg_nowait: false,
193 async_msg_mode: false,
194 async_msg_mode_once: false,
195 hide_mwnd_disable: false,
196 msg_back_disable: false,
197 msg_back_off: false,
198 msg_back_disp_off: false,
199 cursor_disp_off: false,
200 cursor_move_by_key_disable: false,
201 cursor_runtime_visible: true,
202 key_disable: HashSet::new(),
203 mwnd_anime_off_flag: false,
204 mwnd_anime_on_flag: false,
205 mwnd_disp_off_flag: false,
206 koe_dont_stop_on_flag: false,
207 koe_dont_stop_off_flag: false,
208 shortcut_disable: false,
209 quake_stop_flag: false,
210 emote_mouth_stop_flag: false,
211 bgmfade_flag: false,
212 wait_display_vsync_off_flag: false,
213 skip_trigger: false,
214 ignore_r_flag: false,
215 cursor_no: -1,
216 time_stop_flag: false,
217 counter_time_stop_flag: false,
218 frame_action_time_stop_flag: false,
219 stage_time_stop_flag: false,
220 font_name: String::new(),
221 font_bold: -1,
222 font_shadow: -1,
223 }
224 }
225}
226
227#[derive(Debug, Clone, Default)]
228pub struct SystemMessageBoxRecord {
229 pub kind: i32,
230 pub text: String,
231 pub debug_only: bool,
232}
233
234#[derive(Debug, Clone)]
235pub struct SystemMessageBoxButton {
236 pub label: String,
237 pub value: i64,
238}
239
240#[derive(Debug, Clone)]
241pub struct SystemMessageBoxModalState {
242 pub request_id: u64,
243 pub kind: i32,
244 pub text: String,
245 pub debug_only: bool,
246 pub buttons: Vec<SystemMessageBoxButton>,
247 pub cursor: usize,
248 pub native_pending: bool,
249 pub complete_wait_with_value: bool,
250}
251
252impl SystemMessageBoxModalState {
253 pub fn selected_value(&self) -> i64 {
254 self.buttons
255 .get(self.cursor.min(self.buttons.len().saturating_sub(1)))
256 .map(|b| b.value)
257 .unwrap_or(0)
258 }
259
260 pub fn cancel_value(&self) -> i64 {
261 self.buttons
262 .last()
263 .map(|b| b.value)
264 .unwrap_or_else(|| self.selected_value())
265 }
266}
267
268#[derive(Debug, Clone)]
269pub struct SystemRuntimeState {
270 pub active_flag: bool,
271 pub debug_flag: bool,
272 pub language_code: String,
273 pub debug_logs: Vec<String>,
274 pub dummy_checks: HashSet<String>,
275 pub bench_dialogs: Vec<String>,
276 pub messagebox_history: Vec<SystemMessageBoxRecord>,
277 pub messagebox_response_queue: Vec<i64>,
278 pub messagebox_modal: Option<SystemMessageBoxModalState>,
279 pub messagebox_modal_result: Option<i64>,
280 pub spec_info: String,
281}
282
283impl Default for SystemRuntimeState {
284 fn default() -> Self {
285 Self {
286 active_flag: true,
287 debug_flag: false,
288 language_code: std::env::var("SIGLUS_LANGUAGE").unwrap_or_else(|_| "JP".to_string()),
289 debug_logs: Vec::new(),
290 dummy_checks: HashSet::new(),
291 bench_dialogs: Vec::new(),
292 messagebox_history: Vec::new(),
293 messagebox_response_queue: Vec::new(),
294 messagebox_modal: None,
295 messagebox_modal_result: None,
296 spec_info: "siglus_scene_vm".to_string(),
297 }
298 }
299}
300
301#[derive(Debug, Clone, Copy, Default)]
302pub struct ToggleFeatureState {
303 pub onoff: bool,
304 pub enable: bool,
305 pub exist: bool,
306}
307
308impl ToggleFeatureState {
309 pub fn check_enabled(&self) -> i64 {
310 if self.enable && self.exist {
311 1
312 } else {
313 0
314 }
315 }
316}
317
318#[derive(Debug, Clone, Copy, Default)]
319pub struct ValueFeatureState {
320 pub value: i64,
321 pub enable: bool,
322 pub exist: bool,
323}
324
325impl ValueFeatureState {
326 pub fn check_enabled(&self) -> i64 {
327 if self.enable && self.exist {
328 1
329 } else {
330 0
331 }
332 }
333}
334
335#[derive(Debug, Clone, Default)]
336pub struct SaveSlotState {
337 pub exist: bool,
338 pub year: i64,
339 pub month: i64,
340 pub day: i64,
341 pub weekday: i64,
342 pub hour: i64,
343 pub minute: i64,
344 pub second: i64,
345 pub millisecond: i64,
346 pub title: String,
347 pub message: String,
348 pub full_message: String,
349 pub comment: String,
350 pub append_dir: String,
351 pub append_name: String,
352 pub values: HashMap<i32, i64>,
353}
354
355#[derive(Debug, Clone, Copy, PartialEq, Eq)]
356pub enum SyscomPendingProcKind {
357 EndGame,
358 ReturnToSel,
359 ReturnToMenu,
360 Save,
361 Load,
362 QuickSave,
363 QuickLoad,
364 BacklogLoad,
365 MsgBack,
366 OpenSyscomMenu,
367 OpenSave,
368 OpenLoad,
369 OpenConfig,
370}
371
372#[derive(Debug, Clone)]
373pub struct SyscomPendingProc {
374 pub kind: SyscomPendingProcKind,
375 pub warning: bool,
376 pub se_play: bool,
377 pub fade_out: bool,
378 pub leave_msgbk: bool,
379 pub save_id: i64,
380}
381
382#[derive(Debug, Clone)]
383pub struct SyscomRuntimeState {
384 pub syscom_menu_disable: bool,
385 pub menu_open: bool,
386 pub menu_kind: Option<i32>,
387 pub menu_result: Option<i64>,
388 pub menu_cursor: usize,
389 pub font_list: Vec<String>,
390 pub mwnd_btn_disable_all: bool,
391 pub mwnd_btn_touch_disable: bool,
392 pub mwnd_btn_disable: HashMap<i64, bool>,
393 pub read_skip: ToggleFeatureState,
394 pub auto_skip: ToggleFeatureState,
395 pub auto_mode: ToggleFeatureState,
396 pub hide_mwnd: ToggleFeatureState,
397 pub local_extra_switch: ToggleFeatureState,
398 pub local_extra_mode: ValueFeatureState,
399 pub local_extra_switches: [ToggleFeatureState; 4],
400 pub local_extra_modes: [ValueFeatureState; 4],
401 pub msg_back: ToggleFeatureState,
402 pub msg_back_open: bool,
403 pub msg_back_view_pos: usize,
404 pub msg_back_scroll_pos: i32,
405 pub msg_back_slider_pos: i32,
406 pub msg_back_target_no: isize,
407 pub msg_back_mouse_target_no: isize,
408 pub msg_back_msg_total_height: i32,
409 pub msg_back_proc_initialized: bool,
410 pub msg_back_slider_dragging: bool,
411 pub msg_back_slider_drag_start_mouse: i32,
412 pub msg_back_slider_drag_start_pos: i32,
413 pub msg_back_content_dragging: bool,
414 pub msg_back_content_drag_start_mouse: i32,
415 pub msg_back_content_drag_start_scroll_pos: i32,
416 pub return_to_sel: ToggleFeatureState,
417 pub return_to_menu: ToggleFeatureState,
418 pub end_game: ToggleFeatureState,
419 pub save_feature: ToggleFeatureState,
420 pub load_feature: ToggleFeatureState,
421 pub replay_koe: Option<(i64, i64)>,
422 pub current_save_scene_title: String,
423 pub current_save_message: String,
424 pub current_save_full_message: String,
425 pub total_play_time: i64,
426 pub save_slots: Vec<SaveSlotState>,
427 pub quick_save_slots: Vec<SaveSlotState>,
428 pub inner_save_exists: bool,
429 pub inner_save_streams: Vec<Vec<u8>>,
430 pub sel_save_stock_stream: Vec<u8>,
431 pub sel_save_ids: Vec<[u16; 7]>,
432 pub end_save_exists: bool,
433 pub last_menu_call: i32,
434 pub system_extra_int_value: i64,
435 pub system_extra_str_value: String,
436 pub config_int: HashMap<i32, i64>,
437 pub config_str: HashMap<i32, String>,
438 pub capture_buffer: Option<RgbaImage>,
439 pub capture_size: Option<(u32, u32)>,
440 pub return_scene_once: Option<(String, i64)>,
441 pub pending_proc: Option<SyscomPendingProc>,
442 pub msg_back_load_tid: i64,
443}
444
445
446impl Default for SyscomRuntimeState {
447 fn default() -> Self {
448 Self {
449 syscom_menu_disable: false,
450 menu_open: false,
451 menu_kind: None,
452 menu_result: None,
453 menu_cursor: 0,
454 font_list: Vec::new(),
455 mwnd_btn_disable_all: false,
456 mwnd_btn_touch_disable: false,
457 mwnd_btn_disable: HashMap::new(),
458 read_skip: ToggleFeatureState { onoff: false, enable: true, exist: true },
459 auto_skip: ToggleFeatureState { onoff: false, enable: true, exist: true },
460 auto_mode: ToggleFeatureState { onoff: false, enable: true, exist: true },
461 hide_mwnd: ToggleFeatureState { onoff: false, enable: true, exist: true },
462 local_extra_switch: ToggleFeatureState { onoff: false, enable: true, exist: true },
463 local_extra_mode: ValueFeatureState { value: 0, enable: true, exist: true },
464 local_extra_switches: [ToggleFeatureState { onoff: false, enable: true, exist: true }; 4],
465 local_extra_modes: [ValueFeatureState { value: 0, enable: true, exist: true }; 4],
466 msg_back: ToggleFeatureState { onoff: false, enable: true, exist: true },
467 msg_back_open: false,
468 msg_back_view_pos: 0,
469 msg_back_scroll_pos: 0,
470 msg_back_slider_pos: 0,
471 msg_back_target_no: -1,
472 msg_back_mouse_target_no: -1,
473 msg_back_msg_total_height: 0,
474 msg_back_proc_initialized: false,
475 msg_back_slider_dragging: false,
476 msg_back_slider_drag_start_mouse: 0,
477 msg_back_slider_drag_start_pos: 0,
478 msg_back_content_dragging: false,
479 msg_back_content_drag_start_mouse: 0,
480 msg_back_content_drag_start_scroll_pos: 0,
481 return_to_sel: ToggleFeatureState { onoff: false, enable: true, exist: true },
482 return_to_menu: ToggleFeatureState { onoff: false, enable: true, exist: true },
483 end_game: ToggleFeatureState { onoff: false, enable: true, exist: true },
484 save_feature: ToggleFeatureState { onoff: false, enable: true, exist: true },
485 load_feature: ToggleFeatureState { onoff: false, enable: true, exist: true },
486 replay_koe: None,
487 current_save_scene_title: String::new(),
488 current_save_message: String::new(),
489 current_save_full_message: String::new(),
490 total_play_time: 0,
491 save_slots: Vec::new(),
492 quick_save_slots: Vec::new(),
493 inner_save_exists: false,
494 inner_save_streams: Vec::new(),
495 sel_save_stock_stream: Vec::new(),
496 sel_save_ids: Vec::new(),
497 end_save_exists: false,
498 last_menu_call: 0,
499 system_extra_int_value: 0,
500 system_extra_str_value: String::new(),
501 config_int: HashMap::new(),
502 config_str: HashMap::new(),
503 capture_buffer: None,
504 capture_size: None,
505 return_scene_once: None,
506 pending_proc: None,
507 msg_back_load_tid: 0,
508 }
509 }
510}
511#[derive(Debug, Clone, Copy, PartialEq, Eq)]
516pub enum LightType {
517 None = -1,
518 Directional = 0,
519 Point = 1,
520 Spot = 2,
521 ShadowMapSpot = 3,
522}
523
524pub const WORLD_LIGHT_MAX: usize = 128;
525pub const OBJ_DIRECTIONAL_LIGHT_MAX: usize = 4;
526pub const OBJ_POINT_LIGHT_MAX: usize = 4;
527pub const OBJ_SPOT_LIGHT_MAX: usize = 4;
528
529#[derive(Debug, Clone)]
530pub struct LightState {
531 pub id: i32,
532 pub kind: LightType,
533 pub diffuse: [f32; 4],
534 pub ambient: [f32; 4],
535 pub specular: [f32; 4],
536 pub pos: [f32; 3],
537 pub dir: [f32; 3],
538 pub attenuation0: f32,
539 pub attenuation1: f32,
540 pub attenuation2: f32,
541 pub range: f32,
542 pub theta_deg: f32,
543 pub phi_deg: f32,
544 pub falloff: f32,
545}
546
547impl LightState {
548 pub fn directional(id: i32, dir: [f32; 3]) -> Self {
549 Self {
550 id,
551 kind: LightType::Directional,
552 diffuse: [1.0, 1.0, 1.0, 1.0],
553 ambient: [0.18, 0.18, 0.18, 1.0],
554 specular: [0.0, 0.0, 0.0, 1.0],
555 pos: [0.0, 0.0, 0.0],
556 dir,
557 attenuation0: 1.0,
558 attenuation1: 0.0,
559 attenuation2: 0.0,
560 range: 5000.0,
561 theta_deg: 20.0,
562 phi_deg: 40.0,
563 falloff: 1.0,
564 }
565 }
566}
567
568impl Default for LightState {
569 fn default() -> Self {
570 Self::directional(0, [0.0, 0.0, -1.0])
571 }
572}
573
574#[derive(Debug, Clone)]
575pub struct FogGlobalState {
576 pub enabled: bool,
577 pub name: String,
578 pub near: f32,
579 pub far: f32,
580 pub color: [f32; 4],
581 pub scroll_x: f32,
582 pub x_event: IntEvent,
583 pub texture_image_id: Option<ImageId>,
584}
585
586impl Default for FogGlobalState {
587 fn default() -> Self {
588 Self {
589 enabled: false,
590 name: String::new(),
591 near: 0.0,
592 far: 0.0,
593 color: [0.62, 0.62, 0.62, 1.0],
594 scroll_x: 0.0,
595 x_event: IntEvent::new(0),
596 texture_image_id: None,
597 }
598 }
599}
600
601impl FogGlobalState {
602 pub fn set_x(&mut self, x: i32) {
603 self.x_event.set_value(x);
604 self.x_event.frame();
605 self.scroll_x = self.x_event.get_total_value() as f32;
606 }
607
608 pub fn update_time(&mut self, past_game_time: i32, past_real_time: i32) {
609 self.x_event.update_time(past_game_time, past_real_time);
610 }
611
612 pub fn frame(&mut self) {
613 self.x_event.frame();
614 self.scroll_x = self.x_event.get_total_value() as f32;
615 }
616}
617
618#[derive(Debug, Clone)]
619pub struct GlobalState {
620 pub int_lists: HashMap<u32, Vec<i64>>,
622 pub str_lists: HashMap<u32, Vec<String>>,
624 pub counter_lists: HashMap<u32, Vec<Counter>>,
626 pub pcm_event_lists: HashMap<u32, Vec<PcmEventState>>,
628
629 pub int_event_roots: HashMap<u32, IntEvent>,
631 pub int_event_lists: HashMap<u32, Vec<IntEvent>>,
633
634 pub int_props: HashMap<u32, HashMap<i32, i64>>,
636 pub str_props: HashMap<u32, HashMap<i32, String>>,
638
639 pub intlist_bit_widths: HashMap<(u32, i32), i32>,
641 pub intlist_bit_order: HashMap<u32, Vec<i32>>,
643
644 pub cg_table_off: bool,
646
647 pub database_off: bool,
649
650 pub g00buf: Vec<Option<ImageId>>,
652 pub g00buf_names: Vec<Option<String>>,
654
655 pub rng_state: u32,
657
658 pub mask_lists: HashMap<u32, MaskListState>,
660 pub editbox_lists: HashMap<u32, EditBoxListState>,
662 pub focused_editbox: Option<(u32, usize)>,
664 pub change_display_mode_proc_cnt: i32,
666
667 pub frame_actions: HashMap<u32, ObjectFrameActionState>,
669 pub frame_action_lists: HashMap<u32, Vec<ObjectFrameActionState>>,
671 pub pending_frame_action_finishes: Vec<PendingFrameActionFinish>,
673 pub pending_button_actions: Vec<PendingButtonAction>,
675
676 pub stage_forms: HashMap<u32, StageFormState>,
678 pub focused_stage_group: Option<(u32, i64, usize)>,
680 pub focused_stage_mwnd: Option<(u32, i64, usize)>,
682 pub current_mwnd_no: Option<usize>,
685 pub current_mwnd_stage_idx: i64,
686 pub current_sel_mwnd_no: Option<usize>,
687 pub current_sel_mwnd_stage_idx: i64,
688 pub last_mwnd_no: Option<usize>,
689 pub last_mwnd_stage_idx: i64,
690
691 pub local_real_time: i64,
693 pub local_game_time: i64,
694 pub local_wipe_time: i64,
695
696 pub local_flag_h: Vec<i64>,
698 pub local_flag_i: Vec<i64>,
699 pub local_flag_j: Vec<i64>,
700 pub selbtn: BtnSelectRuntimeState,
702 pub current_stage_object: Option<(i64, usize)>,
705 pub current_object_chain: Option<Vec<i32>>,
706
707 pub screen_forms: HashMap<u32, ScreenFormState>,
709
710 pub msgbk_forms: HashMap<u32, MsgBackState>,
712
713 pub script: ScriptRuntimeState,
715
716 pub system: SystemRuntimeState,
718
719 pub syscom: SyscomRuntimeState,
721 pub mov: GlobalMovieState,
723
724 pub capture_image: Option<RgbaImage>,
726 pub capture_for_object_image: Option<RgbaImage>,
728 pub save_thumb_capture_image: Option<RgbaImage>,
730
731 pub append_dir: String,
733 pub append_name: String,
735
736 pub bgm_table_listened: HashMap<String, bool>,
738 pub bgm_table_flags: Vec<bool>,
740 pub bgm_table_all_flag: bool,
742
743 pub wipe: Option<WipeState>,
745
746 pub lights: HashMap<i32, LightState>,
748 pub fog_global: FogGlobalState,
750
751 pub render_frame: u64,
753}
754
755impl Default for GlobalState {
756 fn default() -> Self {
757 Self {
758 int_lists: HashMap::new(),
759 str_lists: HashMap::new(),
760 counter_lists: HashMap::new(),
761 pcm_event_lists: HashMap::new(),
762 int_event_roots: HashMap::new(),
763 int_event_lists: HashMap::new(),
764 int_props: HashMap::new(),
765 str_props: HashMap::new(),
766 intlist_bit_widths: HashMap::new(),
767 intlist_bit_order: HashMap::new(),
768 cg_table_off: false,
769 database_off: false,
770 g00buf: Vec::new(),
771 g00buf_names: Vec::new(),
772 rng_state: 0,
773 mask_lists: HashMap::new(),
774 editbox_lists: HashMap::new(),
775 focused_editbox: None,
776 change_display_mode_proc_cnt: 0,
777
778 frame_actions: HashMap::new(),
779 frame_action_lists: HashMap::new(),
780 pending_frame_action_finishes: Vec::new(),
781 pending_button_actions: Vec::new(),
782 stage_forms: HashMap::new(),
783 focused_stage_group: None,
784 focused_stage_mwnd: None,
785 current_mwnd_no: Some(0),
786 current_mwnd_stage_idx: 1,
787 current_sel_mwnd_no: Some(1),
788 current_sel_mwnd_stage_idx: 1,
789 last_mwnd_no: Some(0),
790 last_mwnd_stage_idx: 1,
791 local_real_time: 0,
792 local_game_time: 0,
793 local_wipe_time: 0,
794 local_flag_h: Vec::new(),
795 local_flag_i: Vec::new(),
796 local_flag_j: Vec::new(),
797 selbtn: BtnSelectRuntimeState::default(),
798 current_stage_object: None,
799 current_object_chain: None,
800
801 screen_forms: HashMap::new(),
802 msgbk_forms: HashMap::new(),
803
804 script: ScriptRuntimeState::default(),
805 system: SystemRuntimeState::default(),
806 syscom: SyscomRuntimeState::default(),
807 mov: GlobalMovieState::default(),
808 capture_image: None,
809 capture_for_object_image: None,
810 save_thumb_capture_image: None,
811 append_dir: String::new(),
812 append_name: String::new(),
813
814 bgm_table_listened: HashMap::new(),
815 bgm_table_flags: Vec::new(),
816 bgm_table_all_flag: false,
817
818 wipe: None,
819 lights: HashMap::new(),
820 fog_global: FogGlobalState::default(),
821 render_frame: 0,
822 }
823 }
824}
825
826#[derive(Debug, Clone, Default)]
827pub struct BtnSelectChoiceState {
828 pub text: String,
829 pub item_type: i64,
830 pub color: i64,
831 pub pos: (i64, i64),
832 pub size: (i64, i64),
833}
834
835#[derive(Debug, Clone, Default)]
836pub struct BtnSelectRuntimeState {
837 pub template_no: i64,
838 pub choices: Vec<BtnSelectChoiceState>,
839 pub cursor: usize,
840 pub cancel_enable: bool,
841 pub capture_flag: bool,
842 pub started: bool,
843 pub result: i64,
844 pub sync_type: i64,
845 pub read_flag_scene_no: i64,
846 pub read_flag_flag_no: i64,
847 pub sel_start_call_scn: String,
848 pub sel_start_call_z_no: i64,
849}
850
851#[derive(Debug, Clone, Default)]
852pub struct PendingFrameActionFinish {
853 pub frame_action_chain: Vec<i32>,
854 pub object_chain: Option<Vec<i32>>,
855 pub scn_name: String,
856 pub cmd_name: String,
857 pub end_time: i64,
858 pub args: Vec<crate::runtime::Value>,
859}
860
861#[derive(Debug, Clone)]
862pub enum PendingButtonActionKind {
863 UserCall {
864 scn_name: String,
865 cmd_name: String,
866 z_no: i64,
867 },
868 Syscom {
869 sys_type: i64,
870 sys_type_opt: i64,
871 mode: i64,
872 },
873}
874
875impl Default for PendingButtonActionKind {
876 fn default() -> Self {
877 Self::UserCall {
878 scn_name: String::new(),
879 cmd_name: String::new(),
880 z_no: -1,
881 }
882 }
883}
884
885#[derive(Debug, Clone, Default)]
886pub struct PendingButtonAction {
887 pub kind: PendingButtonActionKind,
888}
889
890#[derive(Debug, Clone)]
896pub struct GlobalMovieState {
897 pub file_name: Option<String>,
898 pub playing: bool,
899 pub key_skip_flag: bool,
900 pub timer_ms: u64,
901 pub total_ms: Option<u64>,
902 pub x: i32,
903 pub y: i32,
904 pub width: u32,
905 pub height: u32,
906 pub layer_id: Option<LayerId>,
907 pub sprite_id: Option<SpriteId>,
908 pub image_id: Option<ImageId>,
909 pub last_frame_idx: Option<usize>,
910 pub audio_id: Option<u64>,
911 pub audio_start_attempted: bool,
912}
913
914impl Default for GlobalMovieState {
915 fn default() -> Self {
916 Self {
917 file_name: None,
918 playing: false,
919 key_skip_flag: false,
920 timer_ms: 0,
921 total_ms: None,
922 x: 0,
923 y: 0,
924 width: 0,
925 height: 0,
926 layer_id: None,
927 sprite_id: None,
928 image_id: None,
929 last_frame_idx: None,
930 audio_id: None,
931 audio_start_attempted: false,
932 }
933 }
934}
935
936impl GlobalMovieState {
937 pub fn start(
938 &mut self,
939 file_name: String,
940 x: i32,
941 y: i32,
942 width: u32,
943 height: u32,
944 total_ms: Option<u64>,
945 key_skip_flag: bool,
946 ) {
947 self.file_name = Some(file_name);
948 self.playing = true;
949 self.key_skip_flag = key_skip_flag;
950 self.timer_ms = 0;
951 self.total_ms = total_ms;
952 self.x = x;
953 self.y = y;
954 self.width = width;
955 self.height = height;
956 self.last_frame_idx = None;
957 self.audio_id = None;
958 self.audio_start_attempted = false;
959 }
960
961 pub fn stop(&mut self) {
962 self.file_name = None;
963 self.playing = false;
964 self.key_skip_flag = false;
965 self.timer_ms = 0;
966 self.total_ms = None;
967 self.last_frame_idx = None;
968 self.audio_id = None;
969 self.audio_start_attempted = false;
970 }
971
972 pub fn tick(&mut self, past_real_time: i32) {
973 if !self.playing {
974 return;
975 }
976 let add = past_real_time.max(0) as u64;
977 if add == 0 {
978 return;
979 }
980 self.timer_ms = self.timer_ms.saturating_add(add);
981 if let Some(total) = self.total_ms {
982 if total > 0 && self.timer_ms >= total {
983 self.timer_ms = total;
984 self.playing = false;
985 }
986 }
987 }
988}
989
990#[derive(Debug, Clone, Copy)]
991pub struct Counter {
992 cur_time: i64,
993 is_running: bool,
994 real_flag: bool,
995 frame_mode: bool,
996 frame_loop_flag: bool,
997 frame_start_value: i64,
998 frame_end_value: i64,
999 frame_time: i64,
1000}
1001
1002impl Default for Counter {
1003 fn default() -> Self {
1004 Self {
1005 cur_time: 0,
1006 is_running: false,
1007 real_flag: false,
1008 frame_mode: false,
1009 frame_loop_flag: false,
1010 frame_start_value: 0,
1011 frame_end_value: 0,
1012 frame_time: 0,
1013 }
1014 }
1015}
1016
1017impl Counter {
1018 fn limit(min: i64, value: i64, max: i64) -> i64 {
1019 if value < min {
1020 min
1021 } else if value > max {
1022 max
1023 } else {
1024 value
1025 }
1026 }
1027
1028 pub fn reinit(&mut self) {
1029 *self = Self::default();
1030 }
1031
1032 pub fn reset(&mut self) {
1033 self.is_running = false;
1034 self.real_flag = false;
1035 self.frame_mode = false;
1036 self.cur_time = 0;
1037 }
1038
1039 pub fn set_count(&mut self, value: i64) {
1040 if self.frame_mode {
1041 if self.frame_end_value == self.frame_start_value {
1042 self.cur_time = 0;
1043 return;
1044 }
1045
1046 let denom = self.frame_end_value - self.frame_start_value;
1047 let frame_time = self.frame_time;
1048 let mut cur_time = (value - self.frame_start_value) * frame_time / denom;
1049 if self.frame_loop_flag {
1050 cur_time = Self::limit(0, cur_time, frame_time - 1);
1051 } else {
1052 cur_time = Self::limit(0, cur_time, frame_time);
1053 }
1054 self.cur_time = cur_time;
1055 } else {
1056 self.cur_time = value;
1057 }
1058 }
1059
1060 pub fn start(&mut self) {
1061 self.is_running = true;
1062 self.real_flag = false;
1063 self.frame_mode = false;
1064 self.cur_time = 0;
1065 }
1066
1067 pub fn start_real(&mut self) {
1068 self.is_running = true;
1069 self.real_flag = true;
1070 self.frame_mode = false;
1071 self.cur_time = 0;
1072 }
1073
1074 pub fn start_frame(&mut self, from: i64, to: i64, frame_time: i64) {
1075 self.is_running = true;
1076 self.real_flag = false;
1077 self.frame_mode = true;
1078 self.frame_loop_flag = false;
1079 self.frame_start_value = from;
1080 self.frame_end_value = to;
1081 self.frame_time = frame_time;
1082 self.cur_time = 0;
1083 }
1084
1085 pub fn start_frame_real(&mut self, from: i64, to: i64, frame_time: i64) {
1086 self.is_running = true;
1087 self.real_flag = true;
1088 self.frame_mode = true;
1089 self.frame_loop_flag = false;
1090 self.frame_start_value = from;
1091 self.frame_end_value = to;
1092 self.frame_time = frame_time;
1093 self.cur_time = 0;
1094 }
1095
1096 pub fn start_frame_loop(&mut self, from: i64, to: i64, frame_time: i64) {
1097 self.is_running = true;
1098 self.real_flag = false;
1099 self.frame_mode = true;
1100 self.frame_loop_flag = true;
1101 self.frame_start_value = from;
1102 self.frame_end_value = to;
1103 self.frame_time = frame_time;
1104 self.cur_time = 0;
1105 }
1106
1107 pub fn start_frame_loop_real(&mut self, from: i64, to: i64, frame_time: i64) {
1108 self.is_running = true;
1109 self.real_flag = true;
1110 self.frame_mode = true;
1111 self.frame_loop_flag = true;
1112 self.frame_start_value = from;
1113 self.frame_end_value = to;
1114 self.frame_time = frame_time;
1115 self.cur_time = 0;
1116 }
1117
1118 pub fn stop(&mut self) {
1119 self.is_running = false;
1120 }
1121
1122 pub fn resume(&mut self) {
1123 self.is_running = true;
1124 }
1125
1126 pub fn update_time(&mut self, past_game_time: i32, past_real_time: i32) {
1127 if self.is_running {
1128 let add = if self.real_flag {
1129 past_real_time
1130 } else {
1131 past_game_time
1132 };
1133 self.cur_time = self.cur_time.saturating_add(add as i64);
1134 }
1135
1136 if self.frame_mode && !self.frame_loop_flag && self.cur_time >= self.frame_time {
1137 self.is_running = false;
1138 }
1139 }
1140
1141 pub fn get_count(&self) -> i64 {
1142 if self.frame_mode {
1143 if self.frame_time <= 0 {
1144 return self.frame_end_value;
1145 }
1146 if self.frame_start_value == self.frame_end_value {
1147 return self.frame_end_value;
1148 }
1149
1150 let span = self.frame_end_value - self.frame_start_value;
1151 let mut value = span * self.cur_time / self.frame_time;
1152 if self.frame_loop_flag {
1153 value %= span;
1154 value += self.frame_start_value;
1155 } else {
1156 value += self.frame_start_value;
1157 if self.frame_start_value > self.frame_end_value {
1158 value = Self::limit(self.frame_end_value, value, self.frame_start_value);
1159 } else {
1160 value = Self::limit(self.frame_start_value, value, self.frame_end_value);
1161 }
1162 }
1163 value
1164 } else {
1165 self.cur_time
1166 }
1167 }
1168
1169 pub fn get_count_with_frame(&self, _current_frame: i64) -> i64 {
1170 self.get_count()
1171 }
1172
1173 pub fn is_running(&self) -> bool {
1174 self.is_running
1175 }
1176
1177 pub(crate) fn save_parts(&self) -> (bool, bool, bool, bool, i64, i64, i64, i64) {
1178 (
1179 self.is_running,
1180 self.real_flag,
1181 self.frame_mode,
1182 self.frame_loop_flag,
1183 self.frame_start_value,
1184 self.frame_end_value,
1185 self.frame_time,
1186 self.cur_time,
1187 )
1188 }
1189
1190 pub(crate) fn from_save_parts(
1191 is_running: bool,
1192 real_flag: bool,
1193 frame_mode: bool,
1194 frame_loop_flag: bool,
1195 frame_start_value: i64,
1196 frame_end_value: i64,
1197 frame_time: i64,
1198 cur_time: i64,
1199 ) -> Self {
1200 Self {
1201 cur_time,
1202 is_running,
1203 real_flag,
1204 frame_mode,
1205 frame_loop_flag,
1206 frame_start_value,
1207 frame_end_value,
1208 frame_time,
1209 }
1210 }
1211}
1212
1213#[derive(Debug, Clone, Default)]
1214pub struct PcmEventLine {
1215 pub file_name: String,
1216 pub probability: i32,
1217 pub min_time: i32,
1218 pub max_time: i32,
1219}
1220
1221#[derive(Debug, Clone, Default)]
1222pub struct PcmEventState {
1223 pub active: bool,
1224 pub looped: bool,
1225 pub random: bool,
1226 pub volume_type: i32,
1227 pub chara_no: i32,
1228 pub bgm_fade_target_flag: bool,
1229 pub bgm_fade2_target_flag: bool,
1230 pub bgm_fade2_source_flag: bool,
1231 pub real_flag: bool,
1232 pub time_type: bool,
1233 pub lines: Vec<PcmEventLine>,
1234}
1235
1236impl PcmEventState {
1237 pub fn reinit(&mut self) {
1238 *self = Self::default();
1239 }
1240}
1241
1242#[derive(Debug, Clone)]
1244pub struct MaskState {
1245 pub name: Option<String>,
1246 pub x_event: IntEvent,
1247 pub y_event: IntEvent,
1248 pub extra_int: HashMap<i32, i32>,
1249 pub script_events: HashMap<i32, IntEvent>,
1250}
1251
1252impl MaskState {
1253 pub fn new() -> Self {
1254 Self {
1255 name: None,
1256 x_event: IntEvent::new(0),
1257 y_event: IntEvent::new(0),
1258 extra_int: HashMap::new(),
1259 script_events: HashMap::new(),
1260 }
1261 }
1262
1263 pub fn reinit(&mut self) {
1264 self.name = None;
1265 self.x_event.reinit();
1266 self.y_event.reinit();
1267 self.extra_int.clear();
1268 self.script_events.clear();
1269 }
1270}
1271
1272#[derive(Debug, Clone)]
1273pub struct MaskListState {
1274 pub masks: Vec<MaskState>,
1275}
1276
1277#[derive(Debug, Clone)]
1278pub struct MaskedSpriteCache {
1279 pub base_image_id: ImageId,
1280 pub base_version: u64,
1281 pub mask_image_id: ImageId,
1282 pub mask_version: u64,
1283 pub mask_x: i32,
1284 pub mask_y: i32,
1285 pub masked_image_id: ImageId,
1286}
1287
1288pub const EDITBOX_ACTION_NOT_DECIDED: i32 = 0;
1289pub const EDITBOX_ACTION_DECIDED: i32 = 1;
1290pub const EDITBOX_ACTION_CANCELED: i32 = -1;
1291
1292#[derive(Debug, Clone)]
1293pub struct EditBoxState {
1294 pub created: bool,
1295 pub visible: bool,
1296 pub text: String,
1297 pub cursor_pos: usize,
1298 pub action_flag: i32,
1299 pub moji_size: i32,
1300 pub rect_x: i32,
1301 pub rect_y: i32,
1302 pub rect_w: i32,
1303 pub rect_h: i32,
1304 pub design_screen_w: i32,
1305 pub design_screen_h: i32,
1306 pub window_x: i32,
1307 pub window_y: i32,
1308 pub window_w: i32,
1309 pub window_h: i32,
1310 pub window_moji_size: i32,
1311}
1312
1313impl Default for EditBoxState {
1314 fn default() -> Self {
1315 Self {
1316 created: false,
1317 visible: false,
1318 text: String::new(),
1319 cursor_pos: 0,
1320 action_flag: EDITBOX_ACTION_NOT_DECIDED,
1321 moji_size: 0,
1322 rect_x: 0,
1323 rect_y: 0,
1324 rect_w: 0,
1325 rect_h: 0,
1326 design_screen_w: 0,
1327 design_screen_h: 0,
1328 window_x: 0,
1329 window_y: 0,
1330 window_w: 0,
1331 window_h: 0,
1332 window_moji_size: 0,
1333 }
1334 }
1335}
1336
1337impl EditBoxState {
1338 pub fn create_like(
1339 &mut self,
1340 x: i32,
1341 y: i32,
1342 w: i32,
1343 h: i32,
1344 moji_size: i32,
1345 design_screen_w: i32,
1346 design_screen_h: i32,
1347 ) {
1348 self.created = true;
1349 self.visible = false;
1350 self.text.clear();
1351 self.cursor_pos = 0;
1352 self.action_flag = EDITBOX_ACTION_NOT_DECIDED;
1353 self.rect_x = x;
1354 self.rect_y = y;
1355 self.rect_w = w;
1356 self.rect_h = h;
1357 self.moji_size = moji_size;
1358 self.design_screen_w = design_screen_w.max(1);
1359 self.design_screen_h = design_screen_h.max(1);
1360 self.window_x = 0;
1361 self.window_y = 0;
1362 self.window_w = 0;
1363 self.window_h = 0;
1364 self.window_moji_size = 0;
1365 }
1366
1367 pub fn destroy_like(&mut self) {
1368 self.created = false;
1369 self.visible = false;
1370 self.text.clear();
1371 self.cursor_pos = 0;
1372 self.action_flag = EDITBOX_ACTION_NOT_DECIDED;
1373 self.rect_x = 0;
1374 self.rect_y = 0;
1375 self.rect_w = 0;
1376 self.rect_h = 0;
1377 self.moji_size = 0;
1378 self.design_screen_w = 0;
1379 self.design_screen_h = 0;
1380 self.window_x = 0;
1381 self.window_y = 0;
1382 self.window_w = 0;
1383 self.window_h = 0;
1384 self.window_moji_size = 0;
1385 }
1386
1387 pub fn set_text_like(&mut self, text: String) {
1388 self.text = text;
1389 self.cursor_pos = self.text.len();
1390 }
1391
1392 pub fn insert_text_at_cursor(&mut self, text: &str) {
1393 if text.is_empty() {
1394 return;
1395 }
1396 let pos = self.cursor_pos.min(self.text.len());
1397 self.text.insert_str(pos, text);
1398 self.cursor_pos = pos.saturating_add(text.len()).min(self.text.len());
1399 }
1400
1401 pub fn backspace_like(&mut self) {
1402 if self.cursor_pos == 0 || self.text.is_empty() {
1403 return;
1404 }
1405 let mut prev = 0usize;
1406 for (i, _) in self.text.char_indices() {
1407 if i >= self.cursor_pos {
1408 break;
1409 }
1410 prev = i;
1411 }
1412 self.text.drain(prev..self.cursor_pos.min(self.text.len()));
1413 self.cursor_pos = prev;
1414 }
1415
1416 pub fn update_rect(&mut self, screen_w: i32, screen_h: i32) {
1417 let base_w = self.design_screen_w.max(1);
1418 let base_h = self.design_screen_h.max(1);
1419 let sw = screen_w.max(1);
1420 let sh = screen_h.max(1);
1421 self.window_x = self.rect_x.saturating_mul(sw) / base_w;
1422 self.window_y = self.rect_y.saturating_mul(sh) / base_h;
1423 self.window_w = self.rect_w.saturating_mul(sw) / base_w;
1424 self.window_h = self.rect_h.saturating_mul(sh) / base_h;
1425 self.window_moji_size = self.moji_size.saturating_mul(sh) / base_h;
1426 }
1427
1428 pub fn frame(&mut self, display_mode_change_proc_cnt: i32) {
1429 self.visible = self.created && display_mode_change_proc_cnt == 0;
1430 }
1431
1432 pub fn clear_input(&mut self) {
1433 self.action_flag = EDITBOX_ACTION_NOT_DECIDED;
1434 }
1435
1436 pub fn is_decided(&self) -> bool {
1437 self.action_flag == EDITBOX_ACTION_DECIDED
1438 }
1439
1440 pub fn is_canceled(&self) -> bool {
1441 self.action_flag == EDITBOX_ACTION_CANCELED
1442 }
1443
1444 pub fn contains_point(&self, x: i32, y: i32) -> bool {
1445 self.created
1446 && self.visible
1447 && self.window_w > 0
1448 && self.window_h > 0
1449 && x >= self.window_x
1450 && y >= self.window_y
1451 && x < self.window_x.saturating_add(self.window_w)
1452 && y < self.window_y.saturating_add(self.window_h)
1453 }
1454}
1455
1456#[derive(Debug, Clone)]
1457pub struct EditBoxListState {
1458 pub boxes: Vec<EditBoxState>,
1459}
1460
1461impl EditBoxListState {
1462 pub fn new(cnt: usize) -> Self {
1463 Self {
1464 boxes: vec![EditBoxState::default(); cnt],
1465 }
1466 }
1467
1468 pub fn ensure_size(&mut self, cnt: usize) {
1469 if self.boxes.len() < cnt {
1470 self.boxes
1471 .extend((0..(cnt - self.boxes.len())).map(|_| EditBoxState::default()));
1472 } else if self.boxes.len() > cnt {
1473 self.boxes.truncate(cnt);
1474 }
1475 }
1476}
1477
1478#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1483pub enum WorldListOpKind {
1484 GetSize,
1485 Create,
1486 Destroy,
1487 Unknown,
1488}
1489
1490#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1491pub enum WorldOpKind {
1492 Init,
1493 GetNo,
1494 CameraEyeX,
1495 CameraEyeY,
1496 CameraEyeZ,
1497 CameraPintX,
1498 CameraPintY,
1499 CameraPintZ,
1500 CameraUpX,
1501 CameraUpY,
1502 CameraUpZ,
1503 CameraEyeXEve,
1504 CameraEyeYEve,
1505 CameraEyeZEve,
1506 CameraPintXEve,
1507 CameraPintYEve,
1508 CameraPintZEve,
1509 CameraUpXEve,
1510 CameraUpYEve,
1511 CameraUpZEve,
1512 CameraViewAngle,
1513 SetCameraEye,
1514 CalcCameraEye,
1515 SetCameraPint,
1516 CalcCameraPint,
1517 SetCameraUp,
1518 Mono,
1519 SetCameraEveXzRotate,
1520 Order,
1521 Layer,
1522 WipeCopy,
1523 WipeErase,
1524 Unknown,
1525}
1526
1527#[derive(Debug, Clone, Copy)]
1528pub struct WorldRotateEvent {
1529 pub loop_type: i32,
1530 pub cur_time: i32,
1531 pub end_time: i32,
1532 pub delay_time: i32,
1533 pub speed_type: i32,
1534 pub start_x: i32,
1535 pub start_z: i32,
1536 pub end_x: i32,
1537 pub end_z: i32,
1538}
1539
1540impl WorldRotateEvent {
1541 pub fn new() -> Self {
1542 Self {
1543 loop_type: -1,
1544 cur_time: 0,
1545 end_time: 0,
1546 delay_time: 0,
1547 speed_type: 0,
1548 start_x: 0,
1549 start_z: 0,
1550 end_x: 0,
1551 end_z: 0,
1552 }
1553 }
1554
1555 pub fn is_active(&self) -> bool {
1556 self.loop_type != -1
1557 }
1558}
1559
1560#[derive(Debug, Clone)]
1561pub struct WorldState {
1562 pub world_no: i32,
1563 pub mode: i32,
1564 pub camera_eye_x: IntEvent,
1565 pub camera_eye_y: IntEvent,
1566 pub camera_eye_z: IntEvent,
1567 pub camera_pint_x: IntEvent,
1568 pub camera_pint_y: IntEvent,
1569 pub camera_pint_z: IntEvent,
1570 pub camera_up_x: IntEvent,
1571 pub camera_up_y: IntEvent,
1572 pub camera_up_z: IntEvent,
1573 pub camera_view_angle: i32,
1574 pub mono: i32,
1575 pub order: i32,
1576 pub layer: i32,
1577 pub wipe_copy: i32,
1578 pub wipe_erase: i32,
1579 pub camera_eye_xz_eve: WorldRotateEvent,
1580 pub script_events: HashMap<i32, IntEvent>,
1581 pub extra_int: HashMap<i32, i64>,
1582 pub extra_str: HashMap<i32, String>,
1583}
1584
1585impl WorldState {
1586 pub fn new(world_no: i32) -> Self {
1587 let mut out = Self {
1588 world_no,
1589 mode: 1,
1590 camera_eye_x: IntEvent::new(0),
1591 camera_eye_y: IntEvent::new(0),
1592 camera_eye_z: IntEvent::new(-1000),
1593 camera_pint_x: IntEvent::new(0),
1594 camera_pint_y: IntEvent::new(0),
1595 camera_pint_z: IntEvent::new(0),
1596 camera_up_x: IntEvent::new(0),
1597 camera_up_y: IntEvent::new(1),
1598 camera_up_z: IntEvent::new(0),
1599 camera_view_angle: 450,
1600 mono: 0,
1601 order: 0,
1602 layer: 0,
1603 wipe_copy: 0,
1604 wipe_erase: 0,
1605 camera_eye_xz_eve: WorldRotateEvent::new(),
1606 script_events: HashMap::new(),
1607 extra_int: HashMap::new(),
1608 extra_str: HashMap::new(),
1609 };
1610 out.reinit();
1611 out
1612 }
1613
1614 pub fn reinit(&mut self) {
1615 self.mode = 1;
1616 self.camera_eye_x = IntEvent::new(0);
1617 self.camera_eye_y = IntEvent::new(0);
1618 self.camera_eye_z = IntEvent::new(-1000);
1619 self.camera_pint_x = IntEvent::new(0);
1620 self.camera_pint_y = IntEvent::new(0);
1621 self.camera_pint_z = IntEvent::new(0);
1622 self.camera_up_x = IntEvent::new(0);
1623 self.camera_up_y = IntEvent::new(1);
1624 self.camera_up_z = IntEvent::new(0);
1625 self.camera_view_angle = 450;
1626 self.mono = 0;
1627 self.order = 0;
1628 self.layer = 0;
1629 self.wipe_copy = 0;
1630 self.wipe_erase = 0;
1631 self.camera_eye_xz_eve = WorldRotateEvent::new();
1632 }
1633
1634 pub fn update_time(&mut self, past_game_time: i32, past_real_time: i32) {
1635 self.camera_eye_x
1636 .update_time(past_game_time, past_real_time);
1637 self.camera_eye_y
1638 .update_time(past_game_time, past_real_time);
1639 self.camera_eye_z
1640 .update_time(past_game_time, past_real_time);
1641 self.camera_pint_x
1642 .update_time(past_game_time, past_real_time);
1643 self.camera_pint_y
1644 .update_time(past_game_time, past_real_time);
1645 self.camera_pint_z
1646 .update_time(past_game_time, past_real_time);
1647 self.camera_up_x.update_time(past_game_time, past_real_time);
1648 self.camera_up_y.update_time(past_game_time, past_real_time);
1649 self.camera_up_z.update_time(past_game_time, past_real_time);
1650 if self.camera_eye_xz_eve.is_active() {
1651 self.camera_eye_xz_eve.cur_time = self
1652 .camera_eye_xz_eve
1653 .cur_time
1654 .saturating_add(past_game_time);
1655 }
1656 }
1657
1658 pub fn frame(&mut self) {
1659 self.camera_eye_x.frame();
1660 self.camera_eye_y.frame();
1661 self.camera_eye_z.frame();
1662 self.camera_pint_x.frame();
1663 self.camera_pint_y.frame();
1664 self.camera_pint_z.frame();
1665 self.camera_up_x.frame();
1666 self.camera_up_y.frame();
1667 self.camera_up_z.frame();
1668
1669 if self.camera_eye_xz_eve.is_active() {
1670 self.frame_xz_rotate();
1671 }
1672 }
1673
1674 fn frame_xz_rotate(&mut self) {
1675 let mut cur_time = self.camera_eye_xz_eve.cur_time - self.camera_eye_xz_eve.delay_time;
1676 let end_time = self.camera_eye_xz_eve.end_time;
1677
1678 if self.camera_eye_xz_eve.loop_type == 0 && cur_time - end_time >= 0 {
1679 self.camera_eye_xz_eve.loop_type = -1;
1680 return;
1681 }
1682
1683 if cur_time <= 0 {
1684 self.camera_eye_x.cur_value = self.camera_eye_x.start_value;
1685 self.camera_eye_z.cur_value = self.camera_eye_z.start_value;
1686 return;
1687 }
1688
1689 if end_time <= 0 {
1690 return;
1691 }
1692
1693 if self.camera_eye_xz_eve.loop_type == 1 {
1694 cur_time %= end_time;
1695 }
1696 if self.camera_eye_xz_eve.loop_type == 2 {
1697 cur_time %= end_time * 2;
1698 if cur_time - end_time > 0 {
1699 cur_time = end_time - (cur_time - end_time);
1700 }
1701 }
1702
1703 match self.camera_eye_xz_eve.speed_type {
1704 1 => {
1705 cur_time = (cur_time as f64 * cur_time as f64 / end_time as f64) as i32;
1706 }
1707 2 => {
1708 let ct = (cur_time - end_time) as f64;
1709 let et = end_time as f64;
1710 cur_time = (-ct * ct / et + et) as i32;
1711 }
1712 _ => {}
1713 }
1714
1715 let px = self.camera_pint_x.get_total_value() as f64;
1716 let pz = self.camera_pint_z.get_total_value() as f64;
1717 let sx = self.camera_eye_x.start_value as f64;
1718 let sz = self.camera_eye_z.start_value as f64;
1719 let ex = self.camera_eye_x.end_value as f64;
1720 let ez = self.camera_eye_z.end_value as f64;
1721
1722 let sdx = sx - px;
1723 let sdz = sz - pz;
1724 let edx = ex - px;
1725 let edz = ez - pz;
1726
1727 let s_len = (sdx * sdx + sdz * sdz).sqrt();
1728 let e_len = (edx * edx + edz * edz).sqrt();
1729 let t_len = linear(cur_time, s_len, end_time, e_len);
1730
1731 let mut s_theta = sdz.atan2(sdx);
1732 let mut e_theta = edz.atan2(edx);
1733 if (s_theta - e_theta).abs() > std::f64::consts::PI {
1734 if e_theta < 0.0 {
1735 e_theta += std::f64::consts::PI * 2.0;
1736 } else {
1737 e_theta -= std::f64::consts::PI * 2.0;
1738 }
1739 }
1740 let t_theta = linear(cur_time, s_theta, end_time, e_theta);
1741
1742 let tmp_x = t_len * t_theta.cos() + px;
1743 let tmp_z = t_len * t_theta.sin() + pz;
1744
1745 self.camera_eye_x.cur_value = tmp_x as i32;
1746 self.camera_eye_z.cur_value = tmp_z as i32;
1747 }
1748}
1749
1750fn linear(cur: i32, start_value: f64, end_time: i32, end_value: f64) -> f64 {
1751 if end_time <= 0 {
1752 return end_value;
1753 }
1754 let t = cur as f64 / end_time as f64;
1755 start_value + (end_value - start_value) * t
1756}
1757
1758#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1759pub enum ObjectListOpKind {
1760 GetSize,
1761 Resize,
1762 Unknown,
1763}
1764
1765#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1766pub enum ObjectOpKind {
1767 Init,
1768 Free,
1769 InitParam,
1770 CreatePct,
1771 CreateRect,
1772 CreateString,
1773 CreateCopyFrom,
1775 SetPos,
1777 SetCenter,
1779 SetScale,
1781 SetRotate,
1783 SetClip,
1785 SetSrcClip,
1787 ClearButton,
1789 SetButton,
1791 SetButtonGroup,
1793 RepIntList,
1795 Unknown,
1796}
1797
1798#[derive(Debug, Clone, PartialEq, Eq)]
1799pub enum ObjectBackend {
1800 None,
1801 Gfx,
1803 Rect {
1805 layer_id: LayerId,
1806 sprite_id: SpriteId,
1807 width: u32,
1808 height: u32,
1809 },
1810 String {
1812 layer_id: LayerId,
1813 sprite_id: SpriteId,
1814 image_id: Option<ImageId>,
1815 width: u32,
1816 height: u32,
1817 },
1818 Number {
1820 layer_id: LayerId,
1821 sprite_ids: Vec<SpriteId>,
1822 },
1823 Weather {
1825 layer_id: LayerId,
1826 sprite_ids: Vec<SpriteId>,
1827 },
1828 Movie {
1830 layer_id: LayerId,
1831 sprite_id: SpriteId,
1832 image_id: Option<ImageId>,
1833 width: u32,
1834 height: u32,
1835 },
1836}
1837
1838impl Default for ObjectBackend {
1839 fn default() -> Self {
1840 Self::None
1841 }
1842}
1843
1844pub const OBJECT_NESTED_SLOT_KEY: i32 = i32::MIN + 1;
1845
1846#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1847pub enum ObjectEventTarget {
1848 X,
1849 Y,
1850 XRep,
1851 YRep,
1852 ZRep,
1853 Alpha,
1854 Patno,
1855 Order,
1856 Layer,
1857 Z,
1858 CenterX,
1859 CenterY,
1860 CenterZ,
1861 CenterRepX,
1862 CenterRepY,
1863 CenterRepZ,
1864 ScaleX,
1865 ScaleY,
1866 ScaleZ,
1867 RotateX,
1868 RotateY,
1869 RotateZ,
1870 TrRep,
1871 ClipLeft,
1872 ClipTop,
1873 ClipRight,
1874 ClipBottom,
1875 SrcClipLeft,
1876 SrcClipTop,
1877 SrcClipRight,
1878 SrcClipBottom,
1879 Tr,
1880 Mono,
1881 Reverse,
1882 Bright,
1883 Dark,
1884 ColorRate,
1885 ColorAddR,
1886 ColorAddG,
1887 ColorAddB,
1888 ColorR,
1889 ColorG,
1890 ColorB,
1891 Unknown,
1892}
1893
1894#[derive(Debug, Clone)]
1895pub struct ObjectButtonState {
1896 pub enabled: bool,
1897 pub button_no: i64,
1898 pub group_no: i64,
1899 pub cut_no: i64,
1905 pub group_idx_override: Option<usize>,
1907 pub action_no: i64,
1908 pub se_no: i64,
1909 pub sys_type: i64,
1910 pub sys_type_opt: i64,
1911 pub mode: i64,
1912 pub push_keep: bool,
1913 pub alpha_test: bool,
1914 pub state: i64,
1916 pub hit: bool,
1917 pub pushed: bool,
1918
1919 pub decided_action_scn_name: String,
1921 pub decided_action_cmd_name: String,
1922 pub decided_action_z_no: i64,
1923 pub last_hit: bool,
1925 pub last_pushed: bool,
1927}
1928
1929impl Default for ObjectButtonState {
1930 fn default() -> Self {
1931 Self {
1932 enabled: false,
1933 button_no: 0,
1934 group_no: -1,
1935 cut_no: 0,
1936 group_idx_override: None,
1937 action_no: -1,
1938 se_no: -1,
1939 sys_type: 0,
1940 sys_type_opt: 0,
1941 mode: 0,
1942 push_keep: false,
1943 alpha_test: false,
1944 state: 0,
1945 hit: false,
1946 pushed: false,
1947 decided_action_scn_name: String::new(),
1948 decided_action_cmd_name: String::new(),
1949 decided_action_z_no: -1,
1950 last_hit: false,
1951 last_pushed: false,
1952 }
1953 }
1954}
1955
1956impl ObjectButtonState {
1957 pub fn clear(&mut self) {
1958 *self = Self::default();
1959 }
1960
1961 pub fn group_idx(&self) -> Option<usize> {
1962 if !self.enabled {
1963 return None;
1964 }
1965 if let Some(i) = self.group_idx_override {
1966 return Some(i);
1967 }
1968 if self.group_no < 0 {
1969 return None;
1970 }
1971 Some(self.group_no as usize)
1972 }
1973
1974 pub fn is_disabled(&self) -> bool {
1975 self.enabled && self.state == 4
1976 }
1977}
1978
1979#[derive(Debug, Clone)]
1980pub struct ObjectStringParam {
1981 pub moji_size: i64,
1982 pub moji_space_x: i64,
1983 pub moji_space_y: i64,
1984 pub moji_cnt: i64,
1985 pub moji_color: i64,
1986 pub shadow_color: i64,
1987 pub fuchi_color: i64,
1988 pub shadow_mode: i64,
1990}
1991
1992impl Default for ObjectStringParam {
1993 fn default() -> Self {
1994 Self {
1995 moji_size: 12,
1996 moji_space_x: 0,
1997 moji_space_y: 0,
1998 moji_cnt: 0,
1999 moji_color: 0,
2000 shadow_color: 1,
2001 fuchi_color: 1,
2002 shadow_mode: -1,
2003 }
2004 }
2005}
2006
2007#[derive(Debug, Default, Clone)]
2008pub struct ObjectNumberParam {
2009 pub keta_max: i64,
2010 pub disp_zero: i64,
2011 pub disp_sign: i64,
2012 pub tumeru_sign: i64,
2013 pub space_mod: i64,
2014 pub space: i64,
2015}
2016
2017#[derive(Debug, Default, Clone)]
2018pub struct ObjectWeatherParam {
2019 pub weather_type: i64,
2021 pub cnt: i64,
2022 pub pat_mode: i64,
2023 pub pat_no_00: i64,
2024 pub pat_no_01: i64,
2025 pub pat_time: i64,
2026 pub move_time_x: i64,
2027 pub move_time_y: i64,
2028 pub sin_time_x: i64,
2029 pub sin_power_x: i64,
2030 pub sin_time_y: i64,
2031 pub sin_power_y: i64,
2032 pub center_x: i64,
2033 pub center_y: i64,
2034 pub appear_range: i64,
2035 pub move_time: i64,
2036 pub center_rotate: i64,
2037 pub zoom_min: i64,
2038 pub zoom_max: i64,
2039 pub scale_x: i64,
2040 pub scale_y: i64,
2041 pub active_time: i64,
2042 pub real_time_flag: bool,
2043}
2044
2045#[derive(Debug, Default, Clone)]
2046pub struct ObjectWeatherWorkSub {
2047 pub state: i64,
2048 pub state_cur_time: i64,
2049 pub state_time_len: i64,
2050 pub move_start_pos_x: i64,
2051 pub move_start_pos_y: i64,
2052 pub move_start_distance: i64,
2053 pub move_start_degree: i64,
2054 pub move_time_x: i64,
2055 pub move_time_y: i64,
2056 pub move_cur_time: i64,
2057 pub sin_time_x: i64,
2058 pub sin_time_y: i64,
2059 pub sin_power_x: i64,
2060 pub sin_power_y: i64,
2061 pub sin_cur_time: i64,
2062 pub center_rotate: i64,
2063 pub zoom_min: i64,
2064 pub zoom_max: i64,
2065 pub scale_x: i64,
2066 pub scale_y: i64,
2067 pub active_time_len: i64,
2068 pub real_time_flag: bool,
2069 pub restruct_flag: bool,
2070}
2071
2072#[derive(Debug, Clone)]
2073pub struct ObjectWeatherWorkState {
2074 pub cnt_max: usize,
2075 pub sub: Vec<ObjectWeatherWorkSub>,
2076 rand_seed: u32,
2077}
2078
2079impl Default for ObjectWeatherWorkState {
2080 fn default() -> Self {
2081 Self {
2082 cnt_max: 0,
2083 sub: Vec::new(),
2084 rand_seed: 0x1234_abcd,
2085 }
2086 }
2087}
2088
2089impl ObjectWeatherWorkState {
2090 fn next_rand(&mut self) -> i64 {
2091 self.rand_seed = self.rand_seed.wrapping_mul(1103515245).wrapping_add(12345);
2092 ((self.rand_seed >> 16) & 0x7fff) as i64
2093 }
2094
2095 pub fn rand_mod(&mut self, modulo: i64) -> i64 {
2096 if modulo <= 0 {
2097 0
2098 } else {
2099 self.next_rand() % modulo
2100 }
2101 }
2102}
2103
2104#[derive(Debug, Clone)]
2105pub struct ObjectMovieState {
2106 pub loop_flag: bool,
2107 pub auto_free_flag: bool,
2108 pub real_time_flag: bool,
2109 pub pause_flag: bool,
2110
2111 pub timer_ms: u64,
2113 pub total_ms: Option<u64>,
2115
2116 pub playing: bool,
2117 pub last_tick: Option<Instant>,
2118 pub last_frame_idx: Option<usize>,
2119 pub audio_id: Option<u64>,
2120 pub audio_started_once: bool,
2121 pub frame_image_ids: [Option<ImageId>; 2],
2124 pub frame_image_cursor: usize,
2125 pub just_finished: bool,
2126 pub just_looped: bool,
2127 pub seeked: bool,
2128}
2129
2130impl Default for ObjectMovieState {
2131 fn default() -> Self {
2132 Self {
2133 loop_flag: false,
2134 auto_free_flag: true,
2135 real_time_flag: true,
2136 pause_flag: false,
2137 timer_ms: 0,
2138 total_ms: None,
2139 playing: false,
2140 last_tick: None,
2141 last_frame_idx: None,
2142 audio_id: None,
2143 audio_started_once: false,
2144 frame_image_ids: [None, None],
2145 frame_image_cursor: 0,
2146 just_finished: false,
2147 just_looped: false,
2148 seeked: false,
2149 }
2150 }
2151}
2152
2153impl ObjectMovieState {
2154 pub fn reset(&mut self) {
2155 *self = Self::default();
2156 }
2157
2158 pub fn start(
2159 &mut self,
2160 total_ms: Option<u64>,
2161 loop_flag: bool,
2162 auto_free_flag: bool,
2163 real_time_flag: bool,
2164 ready_only: bool,
2165 ) {
2166 self.total_ms = total_ms;
2167 self.loop_flag = loop_flag;
2168 self.auto_free_flag = auto_free_flag;
2169 self.real_time_flag = real_time_flag;
2170 self.pause_flag = ready_only;
2171 self.timer_ms = 0;
2172 self.playing = !ready_only;
2173 self.last_tick = Some(Instant::now());
2174 self.last_frame_idx = None;
2175 self.audio_id = None;
2176 self.audio_started_once = false;
2177 self.frame_image_ids = [None, None];
2178 self.frame_image_cursor = 0;
2179 self.just_finished = false;
2180 self.just_looped = false;
2181 self.seeked = false;
2182 }
2183
2184 pub fn tick(&mut self, past_game_time: i32, past_real_time: i32) {
2185 self.just_finished = false;
2186 self.just_looped = false;
2187 if !self.playing || self.pause_flag {
2188 return;
2189 }
2190 let add = if self.real_time_flag {
2191 past_real_time.max(0) as u64
2192 } else {
2193 past_game_time.max(0) as u64
2194 };
2195 if add == 0 {
2196 return;
2197 }
2198 self.timer_ms = self.timer_ms.saturating_add(add);
2199 if let Some(total) = self.total_ms {
2200 if total > 0 && self.timer_ms >= total {
2201 if self.loop_flag {
2202 self.timer_ms %= total;
2203 self.just_looped = true;
2204 } else {
2205 self.playing = false;
2206 self.just_finished = true;
2207 }
2208 }
2209 }
2210 }
2211
2212 pub fn seek(&mut self, time_ms: u64) {
2213 self.timer_ms = time_ms;
2214 if let Some(total) = self.total_ms {
2215 if total > 0 {
2216 self.timer_ms %= total;
2217 }
2218 }
2219 self.last_tick = Some(Instant::now());
2220 self.last_frame_idx = None;
2221 self.audio_started_once = false;
2222 self.seeked = true;
2223 }
2224
2225 pub fn get_seek_time(&self) -> u64 {
2226 if let Some(total) = self.total_ms {
2227 if total > 0 {
2228 return self.timer_ms % total;
2229 }
2230 }
2231 0
2232 }
2233
2234 pub fn check_movie(&self) -> bool {
2235 self.playing
2236 }
2237}
2238
2239#[derive(Debug, Default, Clone)]
2240pub struct ObjectEmoteParam {
2241 pub width: i64,
2242 pub height: i64,
2243 pub file_name: Option<String>,
2244 pub rep_x: i64,
2245 pub rep_y: i64,
2246}
2247
2248#[derive(Debug, Clone, Default)]
2249pub struct ObjectFrameActionState {
2250 pub scn_name: String,
2251 pub cmd_name: String,
2252 pub counter: Counter,
2253 pub end_time: i64,
2254 pub real_time_flag: bool,
2255 pub end_flag: bool,
2256 pub args: Vec<crate::runtime::Value>,
2257}
2258
2259#[derive(Debug, Clone)]
2260pub struct ObjectBaseState {
2261 pub wipe_copy: i64,
2262 pub wipe_erase: i64,
2263 pub click_disable: i64,
2264 pub disp: i64,
2265 pub patno: i64,
2266 pub world: i64,
2267 pub order: i64,
2268 pub layer: i64,
2269 pub x: i64,
2270 pub y: i64,
2271 pub z: i64,
2272 pub center_x: i64,
2273 pub center_y: i64,
2274 pub center_z: i64,
2275 pub center_rep_x: i64,
2276 pub center_rep_y: i64,
2277 pub center_rep_z: i64,
2278 pub scale_x: i64,
2279 pub scale_y: i64,
2280 pub scale_z: i64,
2281 pub rotate_x: i64,
2282 pub rotate_y: i64,
2283 pub rotate_z: i64,
2284 pub clip_use: i64,
2285 pub clip_left: i64,
2286 pub clip_top: i64,
2287 pub clip_right: i64,
2288 pub clip_bottom: i64,
2289 pub src_clip_use: i64,
2290 pub src_clip_left: i64,
2291 pub src_clip_top: i64,
2292 pub src_clip_right: i64,
2293 pub src_clip_bottom: i64,
2294 pub alpha: i64,
2295 pub tr: i64,
2296 pub mono: i64,
2297 pub reverse: i64,
2298 pub bright: i64,
2299 pub dark: i64,
2300 pub color_r: i64,
2301 pub color_g: i64,
2302 pub color_b: i64,
2303 pub color_rate: i64,
2304 pub color_add_r: i64,
2305 pub color_add_g: i64,
2306 pub color_add_b: i64,
2307 pub mask_no: i64,
2308 pub tonecurve_no: i64,
2309 pub light_no: i64,
2310 pub fog_use: i64,
2311 pub culling: i64,
2312 pub alpha_test: i64,
2313 pub alpha_blend: i64,
2314 pub blend: i64,
2315 pub child_sort_type: i64,
2316 pub no_event_hint: bool,
2317}
2318
2319impl Default for ObjectBaseState {
2320 fn default() -> Self {
2321 Self {
2322 wipe_copy: 0,
2323 wipe_erase: 0,
2324 click_disable: 0,
2325 disp: 0,
2326 patno: 0,
2327 world: -1,
2328 order: 0,
2329 layer: 0,
2330 x: 0,
2331 y: 0,
2332 z: 0,
2333 center_x: 0,
2334 center_y: 0,
2335 center_z: 0,
2336 center_rep_x: 0,
2337 center_rep_y: 0,
2338 center_rep_z: 0,
2339 scale_x: 1000,
2340 scale_y: 1000,
2341 scale_z: 1000,
2342 rotate_x: 0,
2343 rotate_y: 0,
2344 rotate_z: 0,
2345 clip_use: 0,
2346 clip_left: 0,
2347 clip_top: 0,
2348 clip_right: 0,
2349 clip_bottom: 0,
2350 src_clip_use: 0,
2351 src_clip_left: 0,
2352 src_clip_top: 0,
2353 src_clip_right: 0,
2354 src_clip_bottom: 0,
2355 alpha: 255,
2356 tr: 255,
2357 mono: 0,
2358 reverse: 0,
2359 bright: 0,
2360 dark: 0,
2361 color_r: 0,
2362 color_g: 0,
2363 color_b: 0,
2364 color_rate: 0,
2365 color_add_r: 0,
2366 color_add_g: 0,
2367 color_add_b: 0,
2368 mask_no: -1,
2369 tonecurve_no: -1,
2370 light_no: -1,
2371 fog_use: 0,
2372 culling: 0,
2373 alpha_test: 1,
2374 alpha_blend: 1,
2375 blend: 0,
2376 child_sort_type: 0,
2377 no_event_hint: false,
2378 }
2379 }
2380}
2381
2382#[derive(Debug, Clone)]
2383pub struct ObjectPropEvents {
2384 pub patno: IntEvent,
2385 pub x: IntEvent,
2386 pub y: IntEvent,
2387 pub z: IntEvent,
2388 pub center_x: IntEvent,
2389 pub center_y: IntEvent,
2390 pub center_z: IntEvent,
2391 pub center_rep_x: IntEvent,
2392 pub center_rep_y: IntEvent,
2393 pub center_rep_z: IntEvent,
2394 pub scale_x: IntEvent,
2395 pub scale_y: IntEvent,
2396 pub scale_z: IntEvent,
2397 pub rotate_x: IntEvent,
2398 pub rotate_y: IntEvent,
2399 pub rotate_z: IntEvent,
2400 pub clip_left: IntEvent,
2401 pub clip_top: IntEvent,
2402 pub clip_right: IntEvent,
2403 pub clip_bottom: IntEvent,
2404 pub src_clip_left: IntEvent,
2405 pub src_clip_top: IntEvent,
2406 pub src_clip_right: IntEvent,
2407 pub src_clip_bottom: IntEvent,
2408 pub tr: IntEvent,
2409 pub mono: IntEvent,
2410 pub reverse: IntEvent,
2411 pub bright: IntEvent,
2412 pub dark: IntEvent,
2413 pub color_r: IntEvent,
2414 pub color_g: IntEvent,
2415 pub color_b: IntEvent,
2416 pub color_rate: IntEvent,
2417 pub color_add_r: IntEvent,
2418 pub color_add_g: IntEvent,
2419 pub color_add_b: IntEvent,
2420}
2421
2422impl Default for ObjectPropEvents {
2423 fn default() -> Self {
2424 Self {
2425 patno: IntEvent::new(0),
2426 x: IntEvent::new(0),
2427 y: IntEvent::new(0),
2428 z: IntEvent::new(0),
2429 center_x: IntEvent::new(0),
2430 center_y: IntEvent::new(0),
2431 center_z: IntEvent::new(0),
2432 center_rep_x: IntEvent::new(0),
2433 center_rep_y: IntEvent::new(0),
2434 center_rep_z: IntEvent::new(0),
2435 scale_x: IntEvent::new(1000),
2436 scale_y: IntEvent::new(1000),
2437 scale_z: IntEvent::new(1000),
2438 rotate_x: IntEvent::new(0),
2439 rotate_y: IntEvent::new(0),
2440 rotate_z: IntEvent::new(0),
2441 clip_left: IntEvent::new(0),
2442 clip_top: IntEvent::new(0),
2443 clip_right: IntEvent::new(0),
2444 clip_bottom: IntEvent::new(0),
2445 src_clip_left: IntEvent::new(0),
2446 src_clip_top: IntEvent::new(0),
2447 src_clip_right: IntEvent::new(0),
2448 src_clip_bottom: IntEvent::new(0),
2449 tr: IntEvent::new(255),
2450 mono: IntEvent::new(0),
2451 reverse: IntEvent::new(0),
2452 bright: IntEvent::new(0),
2453 dark: IntEvent::new(0),
2454 color_r: IntEvent::new(0),
2455 color_g: IntEvent::new(0),
2456 color_b: IntEvent::new(0),
2457 color_rate: IntEvent::new(0),
2458 color_add_r: IntEvent::new(0),
2459 color_add_g: IntEvent::new(0),
2460 color_add_b: IntEvent::new(0),
2461 }
2462 }
2463}
2464
2465impl ObjectPropEvents {
2466 pub fn clear(&mut self) {
2467 self.patno.reinit();
2468 self.x.reinit();
2469 self.y.reinit();
2470 self.z.reinit();
2471 self.center_x.reinit();
2472 self.center_y.reinit();
2473 self.center_z.reinit();
2474 self.center_rep_x.reinit();
2475 self.center_rep_y.reinit();
2476 self.center_rep_z.reinit();
2477 self.scale_x.reinit();
2478 self.scale_y.reinit();
2479 self.scale_z.reinit();
2480 self.rotate_x.reinit();
2481 self.rotate_y.reinit();
2482 self.rotate_z.reinit();
2483 self.clip_left.reinit();
2484 self.clip_top.reinit();
2485 self.clip_right.reinit();
2486 self.clip_bottom.reinit();
2487 self.src_clip_left.reinit();
2488 self.src_clip_top.reinit();
2489 self.src_clip_right.reinit();
2490 self.src_clip_bottom.reinit();
2491 self.tr.reinit();
2492 self.mono.reinit();
2493 self.reverse.reinit();
2494 self.bright.reinit();
2495 self.dark.reinit();
2496 self.color_r.reinit();
2497 self.color_g.reinit();
2498 self.color_b.reinit();
2499 self.color_rate.reinit();
2500 self.color_add_r.reinit();
2501 self.color_add_g.reinit();
2502 self.color_add_b.reinit();
2503 }
2504
2505 pub fn update_time(&mut self, past_game_time: i32, past_real_time: i32) {
2506 self.patno.update_time(past_game_time, past_real_time);
2507 self.x.update_time(past_game_time, past_real_time);
2508 self.y.update_time(past_game_time, past_real_time);
2509 self.z.update_time(past_game_time, past_real_time);
2510 self.center_x.update_time(past_game_time, past_real_time);
2511 self.center_y.update_time(past_game_time, past_real_time);
2512 self.center_z.update_time(past_game_time, past_real_time);
2513 self.center_rep_x
2514 .update_time(past_game_time, past_real_time);
2515 self.center_rep_y
2516 .update_time(past_game_time, past_real_time);
2517 self.center_rep_z
2518 .update_time(past_game_time, past_real_time);
2519 self.scale_x.update_time(past_game_time, past_real_time);
2520 self.scale_y.update_time(past_game_time, past_real_time);
2521 self.scale_z.update_time(past_game_time, past_real_time);
2522 self.rotate_x.update_time(past_game_time, past_real_time);
2523 self.rotate_y.update_time(past_game_time, past_real_time);
2524 self.rotate_z.update_time(past_game_time, past_real_time);
2525 self.clip_left.update_time(past_game_time, past_real_time);
2526 self.clip_top.update_time(past_game_time, past_real_time);
2527 self.clip_right.update_time(past_game_time, past_real_time);
2528 self.clip_bottom.update_time(past_game_time, past_real_time);
2529 self.src_clip_left
2530 .update_time(past_game_time, past_real_time);
2531 self.src_clip_top
2532 .update_time(past_game_time, past_real_time);
2533 self.src_clip_right
2534 .update_time(past_game_time, past_real_time);
2535 self.src_clip_bottom
2536 .update_time(past_game_time, past_real_time);
2537 self.tr.update_time(past_game_time, past_real_time);
2538 self.mono.update_time(past_game_time, past_real_time);
2539 self.reverse.update_time(past_game_time, past_real_time);
2540 self.bright.update_time(past_game_time, past_real_time);
2541 self.dark.update_time(past_game_time, past_real_time);
2542 self.color_r.update_time(past_game_time, past_real_time);
2543 self.color_g.update_time(past_game_time, past_real_time);
2544 self.color_b.update_time(past_game_time, past_real_time);
2545 self.color_rate.update_time(past_game_time, past_real_time);
2546 self.color_add_r.update_time(past_game_time, past_real_time);
2547 self.color_add_g.update_time(past_game_time, past_real_time);
2548 self.color_add_b.update_time(past_game_time, past_real_time);
2549 }
2550
2551 pub fn frame(&mut self) {
2552 self.patno.frame();
2553 self.x.frame();
2554 self.y.frame();
2555 self.z.frame();
2556 self.center_x.frame();
2557 self.center_y.frame();
2558 self.center_z.frame();
2559 self.center_rep_x.frame();
2560 self.center_rep_y.frame();
2561 self.center_rep_z.frame();
2562 self.scale_x.frame();
2563 self.scale_y.frame();
2564 self.scale_z.frame();
2565 self.rotate_x.frame();
2566 self.rotate_y.frame();
2567 self.rotate_z.frame();
2568 self.clip_left.frame();
2569 self.clip_top.frame();
2570 self.clip_right.frame();
2571 self.clip_bottom.frame();
2572 self.src_clip_left.frame();
2573 self.src_clip_top.frame();
2574 self.src_clip_right.frame();
2575 self.src_clip_bottom.frame();
2576 self.tr.frame();
2577 self.mono.frame();
2578 self.reverse.frame();
2579 self.bright.frame();
2580 self.dark.frame();
2581 self.color_r.frame();
2582 self.color_g.frame();
2583 self.color_b.frame();
2584 self.color_rate.frame();
2585 self.color_add_r.frame();
2586 self.color_add_g.frame();
2587 self.color_add_b.frame();
2588 }
2589
2590 pub fn tick(&mut self, delta: i32) {
2591 self.update_time(delta, delta);
2592 self.frame();
2593 }
2594
2595 pub fn any_active(&self) -> bool {
2596 self.patno.check_event()
2597 || self.x.check_event()
2598 || self.y.check_event()
2599 || self.z.check_event()
2600 || self.center_x.check_event()
2601 || self.center_y.check_event()
2602 || self.center_z.check_event()
2603 || self.center_rep_x.check_event()
2604 || self.center_rep_y.check_event()
2605 || self.center_rep_z.check_event()
2606 || self.scale_x.check_event()
2607 || self.scale_y.check_event()
2608 || self.scale_z.check_event()
2609 || self.rotate_x.check_event()
2610 || self.rotate_y.check_event()
2611 || self.rotate_z.check_event()
2612 || self.clip_left.check_event()
2613 || self.clip_top.check_event()
2614 || self.clip_right.check_event()
2615 || self.clip_bottom.check_event()
2616 || self.src_clip_left.check_event()
2617 || self.src_clip_top.check_event()
2618 || self.src_clip_right.check_event()
2619 || self.src_clip_bottom.check_event()
2620 || self.tr.check_event()
2621 || self.mono.check_event()
2622 || self.reverse.check_event()
2623 || self.bright.check_event()
2624 || self.dark.check_event()
2625 || self.color_r.check_event()
2626 || self.color_g.check_event()
2627 || self.color_b.check_event()
2628 || self.color_rate.check_event()
2629 || self.color_add_r.check_event()
2630 || self.color_add_g.check_event()
2631 || self.color_add_b.check_event()
2632 }
2633
2634 pub fn end_all(&mut self) {
2635 self.patno.end_event();
2636 self.x.end_event();
2637 self.y.end_event();
2638 self.z.end_event();
2639 self.center_x.end_event();
2640 self.center_y.end_event();
2641 self.center_z.end_event();
2642 self.center_rep_x.end_event();
2643 self.center_rep_y.end_event();
2644 self.center_rep_z.end_event();
2645 self.scale_x.end_event();
2646 self.scale_y.end_event();
2647 self.scale_z.end_event();
2648 self.rotate_x.end_event();
2649 self.rotate_y.end_event();
2650 self.rotate_z.end_event();
2651 self.clip_left.end_event();
2652 self.clip_top.end_event();
2653 self.clip_right.end_event();
2654 self.clip_bottom.end_event();
2655 self.src_clip_left.end_event();
2656 self.src_clip_top.end_event();
2657 self.src_clip_right.end_event();
2658 self.src_clip_bottom.end_event();
2659 self.tr.end_event();
2660 self.mono.end_event();
2661 self.reverse.end_event();
2662 self.bright.end_event();
2663 self.dark.end_event();
2664 self.color_r.end_event();
2665 self.color_g.end_event();
2666 self.color_b.end_event();
2667 self.color_rate.end_event();
2668 self.color_add_r.end_event();
2669 self.color_add_g.end_event();
2670 self.color_add_b.end_event();
2671 }
2672
2673 pub fn get(&self, target: ObjectEventTarget) -> Option<&IntEvent> {
2674 match target {
2675 ObjectEventTarget::Patno => Some(&self.patno),
2676 ObjectEventTarget::X => Some(&self.x),
2677 ObjectEventTarget::Y => Some(&self.y),
2678 ObjectEventTarget::Z => Some(&self.z),
2679 ObjectEventTarget::CenterX => Some(&self.center_x),
2680 ObjectEventTarget::CenterY => Some(&self.center_y),
2681 ObjectEventTarget::CenterZ => Some(&self.center_z),
2682 ObjectEventTarget::CenterRepX => Some(&self.center_rep_x),
2683 ObjectEventTarget::CenterRepY => Some(&self.center_rep_y),
2684 ObjectEventTarget::CenterRepZ => Some(&self.center_rep_z),
2685 ObjectEventTarget::ScaleX => Some(&self.scale_x),
2686 ObjectEventTarget::ScaleY => Some(&self.scale_y),
2687 ObjectEventTarget::ScaleZ => Some(&self.scale_z),
2688 ObjectEventTarget::RotateX => Some(&self.rotate_x),
2689 ObjectEventTarget::RotateY => Some(&self.rotate_y),
2690 ObjectEventTarget::RotateZ => Some(&self.rotate_z),
2691 ObjectEventTarget::ClipLeft => Some(&self.clip_left),
2692 ObjectEventTarget::ClipTop => Some(&self.clip_top),
2693 ObjectEventTarget::ClipRight => Some(&self.clip_right),
2694 ObjectEventTarget::ClipBottom => Some(&self.clip_bottom),
2695 ObjectEventTarget::SrcClipLeft => Some(&self.src_clip_left),
2696 ObjectEventTarget::SrcClipTop => Some(&self.src_clip_top),
2697 ObjectEventTarget::SrcClipRight => Some(&self.src_clip_right),
2698 ObjectEventTarget::SrcClipBottom => Some(&self.src_clip_bottom),
2699 ObjectEventTarget::Tr => Some(&self.tr),
2700 ObjectEventTarget::Mono => Some(&self.mono),
2701 ObjectEventTarget::Reverse => Some(&self.reverse),
2702 ObjectEventTarget::Bright => Some(&self.bright),
2703 ObjectEventTarget::Dark => Some(&self.dark),
2704 ObjectEventTarget::ColorR => Some(&self.color_r),
2705 ObjectEventTarget::ColorG => Some(&self.color_g),
2706 ObjectEventTarget::ColorB => Some(&self.color_b),
2707 ObjectEventTarget::ColorRate => Some(&self.color_rate),
2708 ObjectEventTarget::ColorAddR => Some(&self.color_add_r),
2709 ObjectEventTarget::ColorAddG => Some(&self.color_add_g),
2710 ObjectEventTarget::ColorAddB => Some(&self.color_add_b),
2711 ObjectEventTarget::XRep
2712 | ObjectEventTarget::YRep
2713 | ObjectEventTarget::ZRep
2714 | ObjectEventTarget::TrRep
2715 | ObjectEventTarget::Alpha
2716 | ObjectEventTarget::Order
2717 | ObjectEventTarget::Layer
2718 | ObjectEventTarget::Unknown => None,
2719 }
2720 }
2721
2722 pub fn get_mut(&mut self, target: ObjectEventTarget) -> Option<&mut IntEvent> {
2723 match target {
2724 ObjectEventTarget::Patno => Some(&mut self.patno),
2725 ObjectEventTarget::X => Some(&mut self.x),
2726 ObjectEventTarget::Y => Some(&mut self.y),
2727 ObjectEventTarget::Z => Some(&mut self.z),
2728 ObjectEventTarget::CenterX => Some(&mut self.center_x),
2729 ObjectEventTarget::CenterY => Some(&mut self.center_y),
2730 ObjectEventTarget::CenterZ => Some(&mut self.center_z),
2731 ObjectEventTarget::CenterRepX => Some(&mut self.center_rep_x),
2732 ObjectEventTarget::CenterRepY => Some(&mut self.center_rep_y),
2733 ObjectEventTarget::CenterRepZ => Some(&mut self.center_rep_z),
2734 ObjectEventTarget::ScaleX => Some(&mut self.scale_x),
2735 ObjectEventTarget::ScaleY => Some(&mut self.scale_y),
2736 ObjectEventTarget::ScaleZ => Some(&mut self.scale_z),
2737 ObjectEventTarget::RotateX => Some(&mut self.rotate_x),
2738 ObjectEventTarget::RotateY => Some(&mut self.rotate_y),
2739 ObjectEventTarget::RotateZ => Some(&mut self.rotate_z),
2740 ObjectEventTarget::ClipLeft => Some(&mut self.clip_left),
2741 ObjectEventTarget::ClipTop => Some(&mut self.clip_top),
2742 ObjectEventTarget::ClipRight => Some(&mut self.clip_right),
2743 ObjectEventTarget::ClipBottom => Some(&mut self.clip_bottom),
2744 ObjectEventTarget::SrcClipLeft => Some(&mut self.src_clip_left),
2745 ObjectEventTarget::SrcClipTop => Some(&mut self.src_clip_top),
2746 ObjectEventTarget::SrcClipRight => Some(&mut self.src_clip_right),
2747 ObjectEventTarget::SrcClipBottom => Some(&mut self.src_clip_bottom),
2748 ObjectEventTarget::Tr => Some(&mut self.tr),
2749 ObjectEventTarget::Mono => Some(&mut self.mono),
2750 ObjectEventTarget::Reverse => Some(&mut self.reverse),
2751 ObjectEventTarget::Bright => Some(&mut self.bright),
2752 ObjectEventTarget::Dark => Some(&mut self.dark),
2753 ObjectEventTarget::ColorR => Some(&mut self.color_r),
2754 ObjectEventTarget::ColorG => Some(&mut self.color_g),
2755 ObjectEventTarget::ColorB => Some(&mut self.color_b),
2756 ObjectEventTarget::ColorRate => Some(&mut self.color_rate),
2757 ObjectEventTarget::ColorAddR => Some(&mut self.color_add_r),
2758 ObjectEventTarget::ColorAddG => Some(&mut self.color_add_g),
2759 ObjectEventTarget::ColorAddB => Some(&mut self.color_add_b),
2760 ObjectEventTarget::XRep
2761 | ObjectEventTarget::YRep
2762 | ObjectEventTarget::ZRep
2763 | ObjectEventTarget::TrRep
2764 | ObjectEventTarget::Alpha
2765 | ObjectEventTarget::Order
2766 | ObjectEventTarget::Layer
2767 | ObjectEventTarget::Unknown => None,
2768 }
2769 }
2770}
2771
2772#[derive(Debug, Default, Clone)]
2773pub struct ObjectPropEventLists {
2774 pub x_rep: Vec<IntEvent>,
2775 pub y_rep: Vec<IntEvent>,
2776 pub z_rep: Vec<IntEvent>,
2777 pub tr_rep: Vec<IntEvent>,
2778}
2779
2780impl ObjectPropEventLists {
2781 pub fn clear(&mut self) {
2782 self.x_rep.clear();
2783 self.y_rep.clear();
2784 self.z_rep.clear();
2785 self.tr_rep.clear();
2786 }
2787
2788 pub fn update_time(&mut self, past_game_time: i32, past_real_time: i32) {
2789 for ev in &mut self.x_rep {
2790 ev.update_time(past_game_time, past_real_time);
2791 }
2792 for ev in &mut self.y_rep {
2793 ev.update_time(past_game_time, past_real_time);
2794 }
2795 for ev in &mut self.z_rep {
2796 ev.update_time(past_game_time, past_real_time);
2797 }
2798 for ev in &mut self.tr_rep {
2799 ev.update_time(past_game_time, past_real_time);
2800 }
2801 }
2802
2803 pub fn frame(&mut self) {
2804 for ev in &mut self.x_rep {
2805 ev.frame();
2806 }
2807 for ev in &mut self.y_rep {
2808 ev.frame();
2809 }
2810 for ev in &mut self.z_rep {
2811 ev.frame();
2812 }
2813 for ev in &mut self.tr_rep {
2814 ev.frame();
2815 }
2816 }
2817
2818 pub fn tick(&mut self, delta: i32) {
2819 self.update_time(delta, delta);
2820 self.frame();
2821 }
2822
2823 pub fn any_active(&self) -> bool {
2824 self.x_rep.iter().any(|e| e.check_event())
2825 || self.y_rep.iter().any(|e| e.check_event())
2826 || self.z_rep.iter().any(|e| e.check_event())
2827 || self.tr_rep.iter().any(|e| e.check_event())
2828 }
2829
2830 pub fn end_all(&mut self) {
2831 for ev in &mut self.x_rep {
2832 ev.end_event();
2833 }
2834 for ev in &mut self.y_rep {
2835 ev.end_event();
2836 }
2837 for ev in &mut self.z_rep {
2838 ev.end_event();
2839 }
2840 for ev in &mut self.tr_rep {
2841 ev.end_event();
2842 }
2843 }
2844}
2845
2846#[derive(Debug, Clone)]
2847pub struct ObjectPropLists {
2848 pub x_rep: Vec<i64>,
2849 pub y_rep: Vec<i64>,
2850 pub z_rep: Vec<i64>,
2851 pub tr_rep: Vec<i64>,
2852 pub f: Vec<i64>,
2853}
2854
2855impl Default for ObjectPropLists {
2856 fn default() -> Self {
2857 Self {
2858 x_rep: Vec::new(),
2859 y_rep: Vec::new(),
2860 z_rep: Vec::new(),
2861 tr_rep: Vec::new(),
2862 f: vec![0; 32],
2863 }
2864 }
2865}
2866
2867impl ObjectPropLists {
2868 pub fn clear(&mut self) {
2869 self.x_rep.clear();
2870 self.y_rep.clear();
2871 self.z_rep.clear();
2872 self.tr_rep.clear();
2873 self.f.fill(0);
2874 }
2875}
2876
2877#[derive(Debug, Default, Clone)]
2878pub struct ObjectRuntimeState {
2879 pub explicit_int_props: HashSet<i32>,
2880 pub explicit_str_props: HashSet<i32>,
2881 pub prop_events: ObjectPropEvents,
2882 pub prop_event_lists: ObjectPropEventLists,
2883 pub prop_lists: ObjectPropLists,
2884 pub child_objects: Vec<ObjectState>,
2885}
2886
2887#[derive(Debug, Default, Clone)]
2888pub struct ObjectState {
2889 pub used: bool,
2890 pub backend: ObjectBackend,
2891 pub file_name: Option<String>,
2892 pub string_value: Option<String>,
2893
2894 pub object_type: i64,
2896
2897 pub number_value: i64,
2899
2900 pub string_param: ObjectStringParam,
2902
2903 pub number_param: ObjectNumberParam,
2905
2906 pub weather_param: ObjectWeatherParam,
2908 pub weather_work: ObjectWeatherWorkState,
2909
2910 pub thumb_save_no: i64,
2912
2913 pub movie: ObjectMovieState,
2915
2916 pub emote: ObjectEmoteParam,
2918
2919 pub gan_file: Option<String>,
2921 pub gan: GanState,
2923
2924 pub frame_action: ObjectFrameActionState,
2926 pub frame_action_ch: Vec<ObjectFrameActionState>,
2928
2929 pub mask_cache: HashMap<(LayerId, SpriteId), MaskedSpriteCache>,
2931
2932 pub base: ObjectBaseState,
2933
2934 pub button: ObjectButtonState,
2935
2936 pub runtime: ObjectRuntimeState,
2937
2938 pub mesh_animation_state: crate::mesh3d::MeshAnimationState,
2939 pub nested_runtime_slot: Option<usize>,
2940}
2941
2942impl ObjectState {
2943 fn sync_event_backed_prop_value(
2944 &mut self,
2945 ids: &crate::runtime::constants::RuntimeConstants,
2946 op: i32,
2947 value: i64,
2948 ) {
2949 let target = if ids.obj_patno != 0 && op == ids.obj_patno {
2950 ObjectEventTarget::Patno
2951 } else if ids.obj_x != 0 && op == ids.obj_x {
2952 ObjectEventTarget::X
2953 } else if ids.obj_y != 0 && op == ids.obj_y {
2954 ObjectEventTarget::Y
2955 } else if ids.obj_z != 0 && op == ids.obj_z {
2956 ObjectEventTarget::Z
2957 } else if ids.obj_center_x != 0 && op == ids.obj_center_x {
2958 ObjectEventTarget::CenterX
2959 } else if ids.obj_center_y != 0 && op == ids.obj_center_y {
2960 ObjectEventTarget::CenterY
2961 } else if ids.obj_center_z != 0 && op == ids.obj_center_z {
2962 ObjectEventTarget::CenterZ
2963 } else if ids.obj_center_rep_x != 0 && op == ids.obj_center_rep_x {
2964 ObjectEventTarget::CenterRepX
2965 } else if ids.obj_center_rep_y != 0 && op == ids.obj_center_rep_y {
2966 ObjectEventTarget::CenterRepY
2967 } else if ids.obj_center_rep_z != 0 && op == ids.obj_center_rep_z {
2968 ObjectEventTarget::CenterRepZ
2969 } else if ids.obj_scale_x != 0 && op == ids.obj_scale_x {
2970 ObjectEventTarget::ScaleX
2971 } else if ids.obj_scale_y != 0 && op == ids.obj_scale_y {
2972 ObjectEventTarget::ScaleY
2973 } else if ids.obj_scale_z != 0 && op == ids.obj_scale_z {
2974 ObjectEventTarget::ScaleZ
2975 } else if ids.obj_rotate_x != 0 && op == ids.obj_rotate_x {
2976 ObjectEventTarget::RotateX
2977 } else if ids.obj_rotate_y != 0 && op == ids.obj_rotate_y {
2978 ObjectEventTarget::RotateY
2979 } else if ids.obj_rotate_z != 0 && op == ids.obj_rotate_z {
2980 ObjectEventTarget::RotateZ
2981 } else if ids.obj_clip_left != 0 && op == ids.obj_clip_left {
2982 ObjectEventTarget::ClipLeft
2983 } else if ids.obj_clip_top != 0 && op == ids.obj_clip_top {
2984 ObjectEventTarget::ClipTop
2985 } else if ids.obj_clip_right != 0 && op == ids.obj_clip_right {
2986 ObjectEventTarget::ClipRight
2987 } else if ids.obj_clip_bottom != 0 && op == ids.obj_clip_bottom {
2988 ObjectEventTarget::ClipBottom
2989 } else if ids.obj_src_clip_left != 0 && op == ids.obj_src_clip_left {
2990 ObjectEventTarget::SrcClipLeft
2991 } else if ids.obj_src_clip_top != 0 && op == ids.obj_src_clip_top {
2992 ObjectEventTarget::SrcClipTop
2993 } else if ids.obj_src_clip_right != 0 && op == ids.obj_src_clip_right {
2994 ObjectEventTarget::SrcClipRight
2995 } else if ids.obj_src_clip_bottom != 0 && op == ids.obj_src_clip_bottom {
2996 ObjectEventTarget::SrcClipBottom
2997 } else if ids.obj_tr != 0 && op == ids.obj_tr {
2998 ObjectEventTarget::Tr
2999 } else if ids.obj_mono != 0 && op == ids.obj_mono {
3000 ObjectEventTarget::Mono
3001 } else if ids.obj_reverse != 0 && op == ids.obj_reverse {
3002 ObjectEventTarget::Reverse
3003 } else if ids.obj_bright != 0 && op == ids.obj_bright {
3004 ObjectEventTarget::Bright
3005 } else if ids.obj_dark != 0 && op == ids.obj_dark {
3006 ObjectEventTarget::Dark
3007 } else if ids.obj_color_r != 0 && op == ids.obj_color_r {
3008 ObjectEventTarget::ColorR
3009 } else if ids.obj_color_g != 0 && op == ids.obj_color_g {
3010 ObjectEventTarget::ColorG
3011 } else if ids.obj_color_b != 0 && op == ids.obj_color_b {
3012 ObjectEventTarget::ColorB
3013 } else if ids.obj_color_rate != 0 && op == ids.obj_color_rate {
3014 ObjectEventTarget::ColorRate
3015 } else if ids.obj_color_add_r != 0 && op == ids.obj_color_add_r {
3016 ObjectEventTarget::ColorAddR
3017 } else if ids.obj_color_add_g != 0 && op == ids.obj_color_add_g {
3018 ObjectEventTarget::ColorAddG
3019 } else if ids.obj_color_add_b != 0 && op == ids.obj_color_add_b {
3020 ObjectEventTarget::ColorAddB
3021 } else {
3022 self.event_target(ids, op)
3023 };
3024
3025 let Some(ev) = self.runtime.prop_events.get_mut(target) else {
3026 return;
3027 };
3028 ev.set_value(value as i32);
3029 if !ev.check_event() {
3030 ev.cur_value = value as i32;
3031 }
3032 }
3033
3034 pub fn init_type_like(&mut self) {
3038 self.backend = ObjectBackend::None;
3039 self.file_name = None;
3040 self.string_value = None;
3041 self.object_type = 0;
3042
3043 self.number_value = 0;
3044 self.string_param = ObjectStringParam::default();
3045 self.number_param = ObjectNumberParam::default();
3046 self.weather_param = ObjectWeatherParam::default();
3047 self.weather_work = ObjectWeatherWorkState::default();
3048 self.thumb_save_no = -1;
3049
3050 self.movie.reset();
3051 self.emote = ObjectEmoteParam::default();
3052
3053 self.gan_file = None;
3054 self.gan.reset();
3055 self.mask_cache.clear();
3056 self.mesh_animation_state = crate::mesh3d::MeshAnimationState::default();
3057 }
3058
3059 fn weather_rand_percent(&mut self, base: i64, span: i64) -> i64 {
3060 base + self.weather_work.rand_mod(span)
3061 }
3062
3063 fn setup_weather_sub(&mut self, idx: usize, init_state: i64, screen_w: i64, screen_h: i64) {
3064 if idx >= self.weather_work.sub.len() {
3065 return;
3066 }
3067 let param = self.weather_param.clone();
3068 let screen_w = screen_w.max(1);
3069 let screen_h = screen_h.max(1);
3070 let mut sub = ObjectWeatherWorkSub::default();
3071 sub.state = init_state;
3072
3073 if param.weather_type == 1 {
3074 sub.move_start_pos_x = self.weather_work.rand_mod(screen_w);
3075 sub.move_start_pos_y = self.weather_work.rand_mod(screen_h);
3076 sub.move_time_x = param.move_time_x * self.weather_rand_percent(90, 20) / 100;
3077 sub.move_time_y = param.move_time_y * self.weather_rand_percent(90, 20) / 100;
3078 sub.move_cur_time = self.weather_work.next_rand();
3079 sub.sin_time_x = param.sin_time_x * self.weather_rand_percent(90, 20) / 100;
3080 sub.sin_time_y = param.sin_time_y * self.weather_rand_percent(90, 20) / 100;
3081 sub.sin_power_x = param.sin_power_x * self.weather_rand_percent(90, 20) / 100;
3082 sub.sin_power_y = param.sin_power_y * self.weather_rand_percent(90, 20) / 100;
3083 sub.sin_cur_time = self.weather_work.next_rand();
3084 sub.scale_x = param.scale_x;
3085 sub.scale_y = param.scale_y;
3086 sub.active_time_len = param.active_time * self.weather_rand_percent(80, 40) / 100;
3087 sub.state_time_len = if init_state == 0 {
3088 self.weather_work.rand_mod(3000)
3089 } else {
3090 sub.active_time_len
3091 };
3092 sub.real_time_flag = param.real_time_flag;
3093 } else if param.weather_type == 2 {
3094 let max_distance_x = if param.center_x > screen_w / 2 {
3095 param.center_x
3096 } else {
3097 screen_w - param.center_x
3098 };
3099 let max_distance_y = if param.center_y > screen_h / 2 {
3100 param.center_y
3101 } else {
3102 screen_h - param.center_y
3103 };
3104 let max_distance =
3105 (((max_distance_x * max_distance_x + max_distance_y * max_distance_y) as f64)
3106 .sqrt()) as i64;
3107 sub.move_start_distance =
3108 self.weather_work.rand_mod(max_distance.max(1)) * param.appear_range / 100;
3109 sub.move_start_degree = self.weather_work.rand_mod(3600);
3110 sub.move_time_x = param.move_time_x.abs() * self.weather_rand_percent(80, 40) / 100;
3111 sub.move_time_y = param.move_time_y.abs() * self.weather_rand_percent(80, 40) / 100;
3112 sub.sin_time_x = param.sin_time_x * self.weather_rand_percent(90, 20) / 100;
3113 sub.sin_time_y = param.sin_time_y * self.weather_rand_percent(90, 20) / 100;
3114 sub.sin_power_x = param.sin_power_x * self.weather_rand_percent(90, 20) / 100;
3115 sub.sin_power_y = param.sin_power_y * self.weather_rand_percent(90, 20) / 100;
3116 sub.sin_cur_time = self.weather_work.next_rand();
3117 sub.center_rotate = param.center_rotate * self.weather_rand_percent(90, 20) / 100;
3118 sub.zoom_min = param.zoom_min;
3119 sub.zoom_max = param.zoom_max;
3120 sub.scale_x = param.scale_x;
3121 sub.scale_y = param.scale_y;
3122 sub.active_time_len = param.move_time_x.abs() * max_distance / 1000 - 1000;
3123 sub.state_time_len = if init_state == 0 {
3124 self.weather_work
3125 .rand_mod((1000 + sub.active_time_len + 1000).max(1))
3126 } else {
3127 sub.active_time_len
3128 };
3129 sub.move_cur_time = if sub.state_time_len == 0 {
3130 0
3131 } else {
3132 self.weather_work.rand_mod(sub.state_time_len.abs().max(1))
3133 };
3134 sub.real_time_flag = param.real_time_flag;
3135 }
3136 sub.restruct_flag = false;
3137 self.weather_work.sub[idx] = sub;
3138 }
3139
3140 pub fn weather_sprite_count(&self) -> usize {
3141 match self.weather_param.weather_type {
3142 1 => self.weather_work.cnt_max.saturating_mul(4),
3143 2 => self.weather_work.cnt_max,
3144 _ => 0,
3145 }
3146 }
3147
3148 pub fn restruct_weather_work(&mut self, screen_w: i64, screen_h: i64) {
3149 if self.object_type != 4 {
3150 return;
3151 }
3152 for sub in &mut self.weather_work.sub {
3153 sub.restruct_flag = true;
3154 }
3155 let cnt = self.weather_param.cnt.max(0) as usize;
3156 let old_cnt = self.weather_work.sub.len();
3157 if cnt > old_cnt {
3158 self.weather_work
3159 .sub
3160 .resize_with(cnt, ObjectWeatherWorkSub::default);
3161 for idx in old_cnt..cnt {
3162 self.setup_weather_sub(idx, 0, screen_w, screen_h);
3163 }
3164 }
3165 if cnt > self.weather_work.cnt_max {
3166 self.weather_work.cnt_max = cnt;
3167 }
3168 }
3169
3170 pub fn init_param_like(&mut self) {
3171 self.base = ObjectBaseState::default();
3172 self.button.clear();
3173 self.runtime.explicit_int_props.clear();
3174 self.runtime.explicit_str_props.clear();
3175 self.runtime.prop_events.clear();
3176 self.runtime.prop_lists.clear();
3177 self.runtime.prop_event_lists.clear();
3178 self.frame_action = ObjectFrameActionState::default();
3179 self.frame_action_ch.clear();
3180 self.gan_file = None;
3181 self.gan.reset();
3182 }
3183
3184 pub fn clear_runtime_only(&mut self) {
3185 self.runtime.explicit_int_props.clear();
3186 self.runtime.explicit_str_props.clear();
3187 self.runtime.prop_events.clear();
3188 self.runtime.prop_lists.clear();
3189 self.runtime.prop_event_lists.clear();
3190 self.frame_action = ObjectFrameActionState::default();
3191 self.frame_action_ch.clear();
3192 }
3193
3194 pub fn set_int_prop(
3195 &mut self,
3196 ids: &crate::runtime::constants::RuntimeConstants,
3197 op: i32,
3198 value: i64,
3199 ) {
3200 self.runtime.explicit_int_props.insert(op);
3201 let ok =
3202 self.sync_fixed_int_prop(ids, op, value) || self.sync_special_int_prop(ids, op, value);
3203 assert!(ok, "unknown object int property op {}", op);
3204 }
3205
3206 pub fn set_int_prop_from_event_frame(
3207 &mut self,
3208 ids: &crate::runtime::constants::RuntimeConstants,
3209 op: i32,
3210 value: i64,
3211 ) {
3212 self.runtime.explicit_int_props.insert(op);
3213 macro_rules! set_if {
3214 ($id:expr, $field:ident) => {
3215 if $id != 0 && op == $id {
3216 self.base.$field = value;
3217 return;
3218 }
3219 };
3220 }
3221 set_if!(ids.obj_patno, patno);
3222 set_if!(ids.obj_x, x);
3223 set_if!(ids.obj_y, y);
3224 set_if!(ids.obj_z, z);
3225 set_if!(ids.obj_center_x, center_x);
3226 set_if!(ids.obj_center_y, center_y);
3227 set_if!(ids.obj_center_z, center_z);
3228 set_if!(ids.obj_center_rep_x, center_rep_x);
3229 set_if!(ids.obj_center_rep_y, center_rep_y);
3230 set_if!(ids.obj_center_rep_z, center_rep_z);
3231 set_if!(ids.obj_scale_x, scale_x);
3232 set_if!(ids.obj_scale_y, scale_y);
3233 set_if!(ids.obj_scale_z, scale_z);
3234 set_if!(ids.obj_rotate_x, rotate_x);
3235 set_if!(ids.obj_rotate_y, rotate_y);
3236 set_if!(ids.obj_rotate_z, rotate_z);
3237 set_if!(ids.obj_clip_left, clip_left);
3238 set_if!(ids.obj_clip_top, clip_top);
3239 set_if!(ids.obj_clip_right, clip_right);
3240 set_if!(ids.obj_clip_bottom, clip_bottom);
3241 set_if!(ids.obj_src_clip_left, src_clip_left);
3242 set_if!(ids.obj_src_clip_top, src_clip_top);
3243 set_if!(ids.obj_src_clip_right, src_clip_right);
3244 set_if!(ids.obj_src_clip_bottom, src_clip_bottom);
3245 set_if!(ids.obj_alpha, alpha);
3246 set_if!(ids.obj_tr, tr);
3247 set_if!(ids.obj_mono, mono);
3248 set_if!(ids.obj_reverse, reverse);
3249 set_if!(ids.obj_bright, bright);
3250 set_if!(ids.obj_dark, dark);
3251 set_if!(ids.obj_color_r, color_r);
3252 set_if!(ids.obj_color_g, color_g);
3253 set_if!(ids.obj_color_b, color_b);
3254 set_if!(ids.obj_color_rate, color_rate);
3255 set_if!(ids.obj_color_add_r, color_add_r);
3256 set_if!(ids.obj_color_add_g, color_add_g);
3257 set_if!(ids.obj_color_add_b, color_add_b);
3258 assert!(false, "unknown object event-backed int property op {}", op);
3259 }
3260
3261 pub fn has_int_prop(&self, op: i32) -> bool {
3262 self.runtime.explicit_int_props.contains(&op)
3263 }
3264
3265 pub fn remove_int_prop(&mut self, op: i32) {
3266 self.runtime.explicit_int_props.remove(&op);
3267 }
3268
3269 pub fn set_str_prop(
3270 &mut self,
3271 ids: &crate::runtime::constants::RuntimeConstants,
3272 op: i32,
3273 value: String,
3274 ) {
3275 self.runtime.explicit_str_props.insert(op);
3276 let ok = self.sync_special_str_prop(ids, op, value);
3277 assert!(ok, "unknown object string property op {}", op);
3278 }
3279
3280 pub fn lookup_str_prop(
3281 &self,
3282 ids: &crate::runtime::constants::RuntimeConstants,
3283 op: i32,
3284 ) -> Option<String> {
3285 self.special_str_prop(ids, op)
3286 }
3287
3288 pub fn has_str_prop(&self, op: i32) -> bool {
3289 self.runtime.explicit_str_props.contains(&op)
3290 }
3291
3292 pub fn remove_str_prop(&mut self, ids: &crate::runtime::constants::RuntimeConstants, op: i32) {
3293 self.runtime.explicit_str_props.remove(&op);
3294 if ids.obj_mesh_anim_clip_name != 0 && op == ids.obj_mesh_anim_clip_name {
3295 let mut next = self.mesh_animation_state.clone();
3296 next.clip_name = None;
3297 self.set_mesh_animation_state(next);
3298 } else if ids.obj_mesh_anim_blend_clip_name != 0 && op == ids.obj_mesh_anim_blend_clip_name
3299 {
3300 let mut next = self.mesh_animation_state.clone();
3301 next.blend_clip_name = None;
3302 self.set_mesh_animation_state(next);
3303 }
3304 }
3305
3306 pub fn lookup_int_prop(
3307 &self,
3308 ids: &crate::runtime::constants::RuntimeConstants,
3309 op: i32,
3310 ) -> Option<i64> {
3311 self.fixed_int_prop(ids, op)
3312 .or_else(|| self.special_int_prop(ids, op))
3313 }
3314
3315 pub fn get_int_prop(&self, ids: &crate::runtime::constants::RuntimeConstants, op: i32) -> i64 {
3316 self.lookup_int_prop(ids, op).unwrap_or(0)
3317 }
3318
3319 pub fn runtime_slot_or(&self, fallback: usize) -> usize {
3320 self.nested_runtime_slot.unwrap_or(fallback)
3321 }
3322
3323 pub fn ensure_runtime_slot(&mut self, next_slot: &mut usize) -> usize {
3324 if let Some(slot) = self.nested_runtime_slot {
3325 return slot;
3326 }
3327 let slot = *next_slot;
3328 *next_slot += 1;
3329 self.nested_runtime_slot = Some(slot);
3330 slot
3331 }
3332
3333 pub fn int_list_by_op<'a>(
3334 &'a self,
3335 ids: &crate::runtime::constants::RuntimeConstants,
3336 op: i32,
3337 ) -> Option<&'a Vec<i64>> {
3338 if ids.obj_f != 0 && op == ids.obj_f {
3339 Some(&self.runtime.prop_lists.f)
3340 } else {
3341 None
3342 }
3343 }
3344
3345 pub fn int_list_by_op_mut<'a>(
3346 &'a mut self,
3347 ids: &crate::runtime::constants::RuntimeConstants,
3348 op: i32,
3349 ) -> Option<&'a mut Vec<i64>> {
3350 if ids.obj_f != 0 && op == ids.obj_f {
3351 Some(&mut self.runtime.prop_lists.f)
3352 } else {
3353 None
3354 }
3355 }
3356
3357 pub fn rep_int_event_list_by_rep_op<'a>(
3358 &'a self,
3359 ids: &crate::runtime::constants::RuntimeConstants,
3360 op: i32,
3361 ) -> Option<&'a Vec<IntEvent>> {
3362 if ids.obj_x_rep != 0 && op == ids.obj_x_rep {
3363 Some(&self.runtime.prop_event_lists.x_rep)
3364 } else if ids.obj_y_rep != 0 && op == ids.obj_y_rep {
3365 Some(&self.runtime.prop_event_lists.y_rep)
3366 } else if ids.obj_z_rep != 0 && op == ids.obj_z_rep {
3367 Some(&self.runtime.prop_event_lists.z_rep)
3368 } else if ids.obj_tr_rep != 0 && op == ids.obj_tr_rep {
3369 Some(&self.runtime.prop_event_lists.tr_rep)
3370 } else {
3371 None
3372 }
3373 }
3374
3375 pub fn rep_int_event_list_by_rep_op_mut<'a>(
3376 &'a mut self,
3377 ids: &crate::runtime::constants::RuntimeConstants,
3378 op: i32,
3379 ) -> Option<&'a mut Vec<IntEvent>> {
3380 if ids.obj_x_rep != 0 && op == ids.obj_x_rep {
3381 Some(&mut self.runtime.prop_event_lists.x_rep)
3382 } else if ids.obj_y_rep != 0 && op == ids.obj_y_rep {
3383 Some(&mut self.runtime.prop_event_lists.y_rep)
3384 } else if ids.obj_z_rep != 0 && op == ids.obj_z_rep {
3385 Some(&mut self.runtime.prop_event_lists.z_rep)
3386 } else if ids.obj_tr_rep != 0 && op == ids.obj_tr_rep {
3387 Some(&mut self.runtime.prop_event_lists.tr_rep)
3388 } else {
3389 None
3390 }
3391 }
3392
3393 pub fn int_event_by_op<'a>(
3394 &'a self,
3395 ids: &crate::runtime::constants::RuntimeConstants,
3396 op: i32,
3397 ) -> Option<&'a IntEvent> {
3398 self.runtime.prop_events.get(self.event_target(ids, op))
3399 }
3400
3401 pub fn int_event_by_op_mut<'a>(
3402 &'a mut self,
3403 ids: &crate::runtime::constants::RuntimeConstants,
3404 op: i32,
3405 ) -> Option<&'a mut IntEvent> {
3406 let target = self.event_target(ids, op);
3407 self.runtime.prop_events.get_mut(target)
3408 }
3409
3410 pub fn int_event_list_by_op<'a>(
3411 &'a self,
3412 ids: &crate::runtime::constants::RuntimeConstants,
3413 op: i32,
3414 ) -> Option<&'a Vec<IntEvent>> {
3415 if ids.obj_x_rep_eve != 0 && op == ids.obj_x_rep_eve {
3416 Some(&self.runtime.prop_event_lists.x_rep)
3417 } else if ids.obj_y_rep_eve != 0 && op == ids.obj_y_rep_eve {
3418 Some(&self.runtime.prop_event_lists.y_rep)
3419 } else if ids.obj_z_rep_eve != 0 && op == ids.obj_z_rep_eve {
3420 Some(&self.runtime.prop_event_lists.z_rep)
3421 } else if ids.obj_tr_rep_eve != 0 && op == ids.obj_tr_rep_eve {
3422 Some(&self.runtime.prop_event_lists.tr_rep)
3423 } else {
3424 None
3425 }
3426 }
3427
3428 pub fn int_event_list_by_op_mut<'a>(
3429 &'a mut self,
3430 ids: &crate::runtime::constants::RuntimeConstants,
3431 op: i32,
3432 ) -> Option<&'a mut Vec<IntEvent>> {
3433 if ids.obj_x_rep_eve != 0 && op == ids.obj_x_rep_eve {
3434 Some(&mut self.runtime.prop_event_lists.x_rep)
3435 } else if ids.obj_y_rep_eve != 0 && op == ids.obj_y_rep_eve {
3436 Some(&mut self.runtime.prop_event_lists.y_rep)
3437 } else if ids.obj_z_rep_eve != 0 && op == ids.obj_z_rep_eve {
3438 Some(&mut self.runtime.prop_event_lists.z_rep)
3439 } else if ids.obj_tr_rep_eve != 0 && op == ids.obj_tr_rep_eve {
3440 Some(&mut self.runtime.prop_event_lists.tr_rep)
3441 } else {
3442 None
3443 }
3444 }
3445
3446 fn sync_fixed_int_prop(
3447 &mut self,
3448 ids: &crate::runtime::constants::RuntimeConstants,
3449 op: i32,
3450 value: i64,
3451 ) -> bool {
3452 macro_rules! set_if {
3453 ($id:expr, $field:ident) => {
3454 if $id != 0 && op == $id {
3455 self.base.$field = value;
3456 self.sync_event_backed_prop_value(ids, op, value);
3457 return true;
3458 }
3459 };
3460 }
3461 if op == ids.obj_disp {
3462 self.base.disp = value;
3463 return true;
3464 }
3465 set_if!(ids.obj_wipe_copy, wipe_copy);
3466 set_if!(ids.obj_wipe_erase, wipe_erase);
3467 set_if!(ids.obj_click_disable, click_disable);
3468 set_if!(ids.obj_patno, patno);
3469 set_if!(ids.obj_world, world);
3470 set_if!(ids.obj_order, order);
3471 set_if!(ids.obj_layer, layer);
3472 set_if!(ids.obj_x, x);
3473 set_if!(ids.obj_y, y);
3474 set_if!(ids.obj_z, z);
3475 set_if!(ids.obj_center_x, center_x);
3476 set_if!(ids.obj_center_y, center_y);
3477 set_if!(ids.obj_center_z, center_z);
3478 set_if!(ids.obj_center_rep_x, center_rep_x);
3479 set_if!(ids.obj_center_rep_y, center_rep_y);
3480 set_if!(ids.obj_center_rep_z, center_rep_z);
3481 set_if!(ids.obj_scale_x, scale_x);
3482 set_if!(ids.obj_scale_y, scale_y);
3483 set_if!(ids.obj_scale_z, scale_z);
3484 set_if!(ids.obj_rotate_x, rotate_x);
3485 set_if!(ids.obj_rotate_y, rotate_y);
3486 set_if!(ids.obj_rotate_z, rotate_z);
3487 set_if!(ids.obj_clip_use, clip_use);
3488 set_if!(ids.obj_clip_left, clip_left);
3489 set_if!(ids.obj_clip_top, clip_top);
3490 set_if!(ids.obj_clip_right, clip_right);
3491 set_if!(ids.obj_clip_bottom, clip_bottom);
3492 set_if!(ids.obj_src_clip_use, src_clip_use);
3493 set_if!(ids.obj_src_clip_left, src_clip_left);
3494 set_if!(ids.obj_src_clip_top, src_clip_top);
3495 set_if!(ids.obj_src_clip_right, src_clip_right);
3496 set_if!(ids.obj_src_clip_bottom, src_clip_bottom);
3497 set_if!(ids.obj_alpha, alpha);
3498 set_if!(ids.obj_tr, tr);
3499 set_if!(ids.obj_mono, mono);
3500 set_if!(ids.obj_reverse, reverse);
3501 set_if!(ids.obj_bright, bright);
3502 set_if!(ids.obj_dark, dark);
3503 set_if!(ids.obj_color_r, color_r);
3504 set_if!(ids.obj_color_g, color_g);
3505 set_if!(ids.obj_color_b, color_b);
3506 set_if!(ids.obj_color_rate, color_rate);
3507 set_if!(ids.obj_color_add_r, color_add_r);
3508 set_if!(ids.obj_color_add_g, color_add_g);
3509 set_if!(ids.obj_color_add_b, color_add_b);
3510 set_if!(ids.obj_mask_no, mask_no);
3511 set_if!(ids.obj_tonecurve_no, tonecurve_no);
3512 set_if!(ids.obj_light_no, light_no);
3513 set_if!(ids.obj_fog_use, fog_use);
3514 set_if!(ids.obj_culling, culling);
3515 set_if!(ids.obj_alpha_test, alpha_test);
3516 set_if!(ids.obj_alpha_blend, alpha_blend);
3517 set_if!(ids.obj_blend, blend);
3518 false
3519 }
3520
3521 fn sync_special_int_prop(
3522 &mut self,
3523 ids: &crate::runtime::constants::RuntimeConstants,
3524 op: i32,
3525 value: i64,
3526 ) -> bool {
3527 if op == OBJECT_NESTED_SLOT_KEY {
3528 self.nested_runtime_slot = (value >= 0).then_some(value as usize);
3529 return true;
3530 }
3531 if ids.obj_x_rep != 0 && op == ids.obj_x_rep {
3532 if self.runtime.prop_event_lists.x_rep.is_empty() {
3533 self.runtime.prop_event_lists.x_rep.push(IntEvent::new(0));
3534 }
3535 self.runtime.prop_event_lists.x_rep[0].set_value(value as i32);
3536 return true;
3537 }
3538 if ids.obj_y_rep != 0 && op == ids.obj_y_rep {
3539 if self.runtime.prop_event_lists.y_rep.is_empty() {
3540 self.runtime.prop_event_lists.y_rep.push(IntEvent::new(0));
3541 }
3542 self.runtime.prop_event_lists.y_rep[0].set_value(value as i32);
3543 return true;
3544 }
3545 if ids.obj_z_rep != 0 && op == ids.obj_z_rep {
3546 if self.runtime.prop_event_lists.z_rep.is_empty() {
3547 self.runtime.prop_event_lists.z_rep.push(IntEvent::new(0));
3548 }
3549 self.runtime.prop_event_lists.z_rep[0].set_value(value as i32);
3550 return true;
3551 }
3552 if ids.obj_tr_rep != 0 && op == ids.obj_tr_rep {
3553 if self.runtime.prop_event_lists.tr_rep.is_empty() {
3554 self.runtime
3555 .prop_event_lists
3556 .tr_rep
3557 .push(IntEvent::new(255));
3558 }
3559 self.runtime.prop_event_lists.tr_rep[0].set_value(value as i32);
3560 return true;
3561 }
3562 if ids.obj_mesh_anim_clip != 0 && op == ids.obj_mesh_anim_clip {
3563 let mut next = self.mesh_animation_state.clone();
3564 next.change_animation_clip(None, (value >= 0).then_some(value as usize));
3565 self.set_mesh_animation_state(next);
3566 return true;
3567 }
3568 if ids.obj_mesh_anim_rate != 0 && op == ids.obj_mesh_anim_rate {
3569 let mut next = self.mesh_animation_state.clone();
3570 next.rate = (value as f32) / 1000.0;
3571 self.set_mesh_animation_state(next);
3572 return true;
3573 }
3574 if ids.obj_mesh_anim_time_offset != 0 && op == ids.obj_mesh_anim_time_offset {
3575 let mut next = self.mesh_animation_state.clone();
3576 next.time_offset_sec = (value as f32) / 1000.0;
3577 self.set_mesh_animation_state(next);
3578 return true;
3579 }
3580 if ids.obj_mesh_anim_pause != 0 && op == ids.obj_mesh_anim_pause {
3581 let mut next = self.mesh_animation_state.clone();
3582 next.paused = value != 0;
3583 next.is_anim = !next.paused;
3584 self.set_mesh_animation_state(next);
3585 return true;
3586 }
3587 if ids.obj_mesh_anim_hold_time != 0 && op == ids.obj_mesh_anim_hold_time {
3588 let mut next = self.mesh_animation_state.clone();
3589 next.hold_time_sec = ((value as f32) / 1000.0).max(0.0);
3590 next.time_sec = if next.rate > 0.0 {
3591 next.hold_time_sec / next.rate.max(0.000_001)
3592 } else {
3593 0.0
3594 };
3595 self.set_mesh_animation_state(next);
3596 return true;
3597 }
3598 if ids.obj_mesh_anim_shift_time != 0 && op == ids.obj_mesh_anim_shift_time {
3599 let mut next = self.mesh_animation_state.clone();
3600 next.set_anim_shift_time_sec(((value as f32) / 1000.0).max(0.0));
3601 self.set_mesh_animation_state(next);
3602 return true;
3603 }
3604 if ids.obj_mesh_anim_loop != 0 && op == ids.obj_mesh_anim_loop {
3605 let mut next = self.mesh_animation_state.clone();
3606 next.looped = value != 0;
3607 self.set_mesh_animation_state(next);
3608 return true;
3609 }
3610 if ids.obj_mesh_anim_blend_clip != 0 && op == ids.obj_mesh_anim_blend_clip {
3611 let mut next = self.mesh_animation_state.clone();
3612 next.blend_clip_index = (value >= 0).then_some(value as usize);
3613 next.blend_clip_name = None;
3614 self.set_mesh_animation_state(next);
3615 return true;
3616 }
3617 if ids.obj_mesh_anim_blend_weight != 0 && op == ids.obj_mesh_anim_blend_weight {
3618 let mut next = self.mesh_animation_state.clone();
3619 next.blend_weight = ((value as f32) / 1000.0).clamp(0.0, 1.0);
3620 self.set_mesh_animation_state(next);
3621 return true;
3622 }
3623 false
3624 }
3625
3626 fn special_int_prop(
3627 &self,
3628 ids: &crate::runtime::constants::RuntimeConstants,
3629 op: i32,
3630 ) -> Option<i64> {
3631 if op == OBJECT_NESTED_SLOT_KEY {
3632 return self.nested_runtime_slot.map(|v| v as i64);
3633 }
3634 if ids.obj_x_rep != 0 && op == ids.obj_x_rep {
3635 return self
3636 .runtime
3637 .prop_event_lists
3638 .x_rep
3639 .first()
3640 .map(|ev| ev.get_value() as i64);
3641 }
3642 if ids.obj_y_rep != 0 && op == ids.obj_y_rep {
3643 return self
3644 .runtime
3645 .prop_event_lists
3646 .y_rep
3647 .first()
3648 .map(|ev| ev.get_value() as i64);
3649 }
3650 if ids.obj_z_rep != 0 && op == ids.obj_z_rep {
3651 return self
3652 .runtime
3653 .prop_event_lists
3654 .z_rep
3655 .first()
3656 .map(|ev| ev.get_value() as i64);
3657 }
3658 if ids.obj_tr_rep != 0 && op == ids.obj_tr_rep {
3659 return self
3660 .runtime
3661 .prop_event_lists
3662 .tr_rep
3663 .first()
3664 .map(|ev| ev.get_value() as i64);
3665 }
3666 if ids.obj_mesh_anim_clip != 0 && op == ids.obj_mesh_anim_clip {
3667 return Some(
3668 self.mesh_animation_state
3669 .clip_index
3670 .map(|v| v as i64)
3671 .unwrap_or(-1),
3672 );
3673 }
3674 if ids.obj_mesh_anim_rate != 0 && op == ids.obj_mesh_anim_rate {
3675 return Some((self.mesh_animation_state.rate * 1000.0).round() as i64);
3676 }
3677 if ids.obj_mesh_anim_time_offset != 0 && op == ids.obj_mesh_anim_time_offset {
3678 return Some((self.mesh_animation_state.time_offset_sec * 1000.0).round() as i64);
3679 }
3680 if ids.obj_mesh_anim_pause != 0 && op == ids.obj_mesh_anim_pause {
3681 return Some(if self.mesh_animation_state.paused {
3682 1
3683 } else {
3684 0
3685 });
3686 }
3687 if ids.obj_mesh_anim_hold_time != 0 && op == ids.obj_mesh_anim_hold_time {
3688 return Some((self.mesh_animation_state.hold_time_sec * 1000.0).round() as i64);
3689 }
3690 if ids.obj_mesh_anim_shift_time != 0 && op == ids.obj_mesh_anim_shift_time {
3691 return Some((self.mesh_animation_state.anim_shift_time_sec * 1000.0).round() as i64);
3692 }
3693 if ids.obj_mesh_anim_loop != 0 && op == ids.obj_mesh_anim_loop {
3694 return Some(if self.mesh_animation_state.looped {
3695 1
3696 } else {
3697 0
3698 });
3699 }
3700 if ids.obj_mesh_anim_blend_clip != 0 && op == ids.obj_mesh_anim_blend_clip {
3701 return Some(
3702 self.mesh_animation_state
3703 .blend_clip_index
3704 .map(|v| v as i64)
3705 .unwrap_or(-1),
3706 );
3707 }
3708 if ids.obj_mesh_anim_blend_weight != 0 && op == ids.obj_mesh_anim_blend_weight {
3709 return Some((self.mesh_animation_state.blend_weight * 1000.0).round() as i64);
3710 }
3711 None
3712 }
3713
3714 fn sync_special_str_prop(
3715 &mut self,
3716 ids: &crate::runtime::constants::RuntimeConstants,
3717 op: i32,
3718 value: String,
3719 ) -> bool {
3720 if ids.obj_mesh_anim_clip_name != 0 && op == ids.obj_mesh_anim_clip_name {
3721 let mut next = self.mesh_animation_state.clone();
3722 next.change_animation_clip(Some(value), None);
3723 self.set_mesh_animation_state(next);
3724 return true;
3725 }
3726 if ids.obj_mesh_anim_blend_clip_name != 0 && op == ids.obj_mesh_anim_blend_clip_name {
3727 let mut next = self.mesh_animation_state.clone();
3728 next.blend_clip_name = Some(value);
3729 next.blend_clip_index = None;
3730 self.set_mesh_animation_state(next);
3731 return true;
3732 }
3733 false
3734 }
3735
3736 fn special_str_prop(
3737 &self,
3738 ids: &crate::runtime::constants::RuntimeConstants,
3739 op: i32,
3740 ) -> Option<String> {
3741 if ids.obj_mesh_anim_clip_name != 0 && op == ids.obj_mesh_anim_clip_name {
3742 return self.mesh_animation_state.clip_name.clone();
3743 }
3744 if ids.obj_mesh_anim_blend_clip_name != 0 && op == ids.obj_mesh_anim_blend_clip_name {
3745 return self.mesh_animation_state.blend_clip_name.clone();
3746 }
3747 None
3748 }
3749
3750 fn fixed_int_prop(
3751 &self,
3752 ids: &crate::runtime::constants::RuntimeConstants,
3753 op: i32,
3754 ) -> Option<i64> {
3755 macro_rules! get_base_if {
3756 ($id:expr, $field:ident) => {
3757 if $id != 0 && op == $id {
3758 return Some(self.base.$field);
3759 }
3760 };
3761 }
3762 macro_rules! get_event_total_if {
3763 ($id:expr, $target:expr) => {
3764 if $id != 0 && op == $id {
3765 return self
3766 .runtime
3767 .prop_events
3768 .get($target)
3769 .map(|ev| ev.get_total_value() as i64);
3770 }
3771 };
3772 }
3773 if op == ids.obj_disp {
3774 return Some(self.base.disp);
3775 }
3776 get_base_if!(ids.obj_wipe_copy, wipe_copy);
3777 get_base_if!(ids.obj_wipe_erase, wipe_erase);
3778 get_base_if!(ids.obj_click_disable, click_disable);
3779 get_event_total_if!(ids.obj_patno, ObjectEventTarget::Patno);
3780 get_base_if!(ids.obj_world, world);
3781 get_base_if!(ids.obj_order, order);
3782 get_base_if!(ids.obj_layer, layer);
3783 get_event_total_if!(ids.obj_x, ObjectEventTarget::X);
3784 get_event_total_if!(ids.obj_y, ObjectEventTarget::Y);
3785 get_event_total_if!(ids.obj_z, ObjectEventTarget::Z);
3786 get_event_total_if!(ids.obj_center_x, ObjectEventTarget::CenterX);
3787 get_event_total_if!(ids.obj_center_y, ObjectEventTarget::CenterY);
3788 get_event_total_if!(ids.obj_center_z, ObjectEventTarget::CenterZ);
3789 get_event_total_if!(ids.obj_center_rep_x, ObjectEventTarget::CenterRepX);
3790 get_event_total_if!(ids.obj_center_rep_y, ObjectEventTarget::CenterRepY);
3791 get_event_total_if!(ids.obj_center_rep_z, ObjectEventTarget::CenterRepZ);
3792 get_event_total_if!(ids.obj_scale_x, ObjectEventTarget::ScaleX);
3793 get_event_total_if!(ids.obj_scale_y, ObjectEventTarget::ScaleY);
3794 get_event_total_if!(ids.obj_scale_z, ObjectEventTarget::ScaleZ);
3795 get_event_total_if!(ids.obj_rotate_x, ObjectEventTarget::RotateX);
3796 get_event_total_if!(ids.obj_rotate_y, ObjectEventTarget::RotateY);
3797 get_event_total_if!(ids.obj_rotate_z, ObjectEventTarget::RotateZ);
3798 get_base_if!(ids.obj_clip_use, clip_use);
3799 get_event_total_if!(ids.obj_clip_left, ObjectEventTarget::ClipLeft);
3800 get_event_total_if!(ids.obj_clip_top, ObjectEventTarget::ClipTop);
3801 get_event_total_if!(ids.obj_clip_right, ObjectEventTarget::ClipRight);
3802 get_event_total_if!(ids.obj_clip_bottom, ObjectEventTarget::ClipBottom);
3803 get_base_if!(ids.obj_src_clip_use, src_clip_use);
3804 get_event_total_if!(ids.obj_src_clip_left, ObjectEventTarget::SrcClipLeft);
3805 get_event_total_if!(ids.obj_src_clip_top, ObjectEventTarget::SrcClipTop);
3806 get_event_total_if!(ids.obj_src_clip_right, ObjectEventTarget::SrcClipRight);
3807 get_event_total_if!(ids.obj_src_clip_bottom, ObjectEventTarget::SrcClipBottom);
3808 get_base_if!(ids.obj_alpha, alpha);
3809 get_event_total_if!(ids.obj_tr, ObjectEventTarget::Tr);
3810 get_event_total_if!(ids.obj_mono, ObjectEventTarget::Mono);
3811 get_event_total_if!(ids.obj_reverse, ObjectEventTarget::Reverse);
3812 get_event_total_if!(ids.obj_bright, ObjectEventTarget::Bright);
3813 get_event_total_if!(ids.obj_dark, ObjectEventTarget::Dark);
3814 get_event_total_if!(ids.obj_color_r, ObjectEventTarget::ColorR);
3815 get_event_total_if!(ids.obj_color_g, ObjectEventTarget::ColorG);
3816 get_event_total_if!(ids.obj_color_b, ObjectEventTarget::ColorB);
3817 get_event_total_if!(ids.obj_color_rate, ObjectEventTarget::ColorRate);
3818 get_event_total_if!(ids.obj_color_add_r, ObjectEventTarget::ColorAddR);
3819 get_event_total_if!(ids.obj_color_add_g, ObjectEventTarget::ColorAddG);
3820 get_event_total_if!(ids.obj_color_add_b, ObjectEventTarget::ColorAddB);
3821 get_base_if!(ids.obj_mask_no, mask_no);
3822 get_base_if!(ids.obj_tonecurve_no, tonecurve_no);
3823 get_base_if!(ids.obj_light_no, light_no);
3824 get_base_if!(ids.obj_fog_use, fog_use);
3825 get_base_if!(ids.obj_culling, culling);
3826 get_base_if!(ids.obj_alpha_test, alpha_test);
3827 get_base_if!(ids.obj_alpha_blend, alpha_blend);
3828 get_base_if!(ids.obj_blend, blend);
3829 None
3830 }
3831
3832 pub fn set_mesh_animation_state(&mut self, next: crate::mesh3d::MeshAnimationState) {
3833 self.apply_mesh_animation_state(next, None);
3834 }
3835
3836 fn apply_mesh_animation_state(
3837 &mut self,
3838 next: crate::mesh3d::MeshAnimationState,
3839 explicit_hold_override: Option<f32>,
3840 ) {
3841 let prev = self.mesh_animation_state.clone();
3842 let mut merged = next.sanitized();
3843 let clip_changed =
3844 prev.clip_name != merged.clip_name || prev.clip_index != merged.clip_index;
3845 let pause_enter = !prev.paused && merged.paused;
3846 let pause_exit = prev.paused && !merged.paused;
3847 let prev_base = prev.current_sample_base_sec();
3848
3849 merged.anim_track_no = prev.anim_track_no;
3850 merged.is_anim = !merged.paused;
3851 merged.time_sec = prev.time_sec.max(0.0);
3852 merged.hold_time_sec = prev.hold_time_sec.max(0.0);
3853 merged.prev_clip_name = prev.prev_clip_name.clone();
3854 merged.prev_clip_index = prev.prev_clip_index;
3855 merged.prev_time_sec = prev.prev_time_sec.max(0.0);
3856 merged.prev_time_offset_sec = prev.prev_time_offset_sec.max(0.0);
3857 merged.prev_rate = prev.prev_rate.max(0.0);
3858 merged.transition_elapsed_sec = prev.transition_elapsed_sec.max(0.0);
3859
3860 if clip_changed {
3861 merged.change_animation_clip(merged.clip_name.clone(), merged.clip_index);
3862 }
3863
3864 if let Some(hold_sec) = explicit_hold_override {
3865 let hold_sec = hold_sec.max(0.0);
3866 merged.hold_time_sec = hold_sec;
3867 merged.time_sec = if merged.rate > 0.0 {
3868 hold_sec / merged.rate.max(0.000_001)
3869 } else {
3870 0.0
3871 };
3872 } else if pause_enter {
3873 merged.hold_time_sec = prev_base;
3874 } else if pause_exit {
3875 merged.time_sec = if merged.rate > 0.0 {
3876 prev.hold_time_sec.max(0.0) / merged.rate.max(0.000_001)
3877 } else {
3878 prev.time_sec.max(0.0)
3879 };
3880 } else if merged.paused {
3881 merged.hold_time_sec = prev.hold_time_sec.max(0.0);
3882 } else if !clip_changed && (prev.rate - merged.rate).abs() > 0.000_001 {
3883 merged.time_sec = if merged.rate > 0.0 {
3884 prev_base / merged.rate.max(0.000_001)
3885 } else {
3886 prev.time_sec.max(0.0)
3887 };
3888 }
3889
3890 self.mesh_animation_state = merged.sanitized();
3891 }
3892
3893 pub fn sync_mesh_animation_state_from_props(
3894 &mut self,
3895 ids: &super::constants::RuntimeConstants,
3896 ) {
3897 let int_prop = |id: i32, default: i64| -> i64 {
3898 if id != 0 {
3899 self.lookup_int_prop(ids, id).unwrap_or(default)
3900 } else {
3901 default
3902 }
3903 };
3904 let str_prop = |id: i32| -> Option<String> {
3905 if id != 0 {
3906 self.lookup_str_prop(ids, id)
3907 } else {
3908 None
3909 }
3910 };
3911 let explicit_hold =
3912 ids.obj_mesh_anim_hold_time != 0 && self.has_int_prop(ids.obj_mesh_anim_hold_time);
3913 let requested_hold_sec = (int_prop(ids.obj_mesh_anim_hold_time, 0) as f32) / 1000.0;
3914 let requested_shift_sec = (int_prop(
3915 ids.obj_mesh_anim_shift_time,
3916 (self.mesh_animation_state.anim_shift_time_sec * 1000.0).round() as i64,
3917 ) as f32)
3918 / 1000.0;
3919 let next = crate::mesh3d::MeshAnimationState {
3920 clip_name: str_prop(ids.obj_mesh_anim_clip_name),
3921 clip_index: (int_prop(ids.obj_mesh_anim_clip, -1) >= 0).then_some(int_prop(
3922 ids.obj_mesh_anim_clip,
3923 -1,
3924 )
3925 as usize),
3926 blend_clip_name: str_prop(ids.obj_mesh_anim_blend_clip_name),
3927 blend_clip_index: (int_prop(ids.obj_mesh_anim_blend_clip, -1) >= 0)
3928 .then_some(int_prop(ids.obj_mesh_anim_blend_clip, -1) as usize),
3929 blend_weight: ((int_prop(ids.obj_mesh_anim_blend_weight, 0) as f32) / 1000.0)
3930 .clamp(0.0, 1.0),
3931 time_sec: self.mesh_animation_state.time_sec,
3932 rate: (int_prop(ids.obj_mesh_anim_rate, 1000) as f32) / 1000.0,
3933 time_offset_sec: (int_prop(ids.obj_mesh_anim_time_offset, 0) as f32) / 1000.0,
3934 hold_time_sec: if explicit_hold {
3935 requested_hold_sec
3936 } else {
3937 self.mesh_animation_state.hold_time_sec
3938 },
3939 paused: int_prop(ids.obj_mesh_anim_pause, 0) != 0,
3940 looped: int_prop(ids.obj_mesh_anim_loop, 1) != 0,
3941 anim_track_no: self.mesh_animation_state.anim_track_no,
3942 anim_shift_time_sec: requested_shift_sec.max(0.0),
3943 is_anim: !(int_prop(ids.obj_mesh_anim_pause, 0) != 0),
3944 prev_clip_name: self.mesh_animation_state.prev_clip_name.clone(),
3945 prev_clip_index: self.mesh_animation_state.prev_clip_index,
3946 prev_time_sec: self.mesh_animation_state.prev_time_sec,
3947 prev_time_offset_sec: self.mesh_animation_state.prev_time_offset_sec,
3948 prev_rate: self.mesh_animation_state.prev_rate,
3949 transition_elapsed_sec: self.mesh_animation_state.transition_elapsed_sec,
3950 };
3951 self.apply_mesh_animation_state(next, explicit_hold.then_some(requested_hold_sec));
3952 }
3953
3954 pub fn uses_mesh_animation_bridge_op(
3955 ids: &super::constants::RuntimeConstants,
3956 op: i32,
3957 ) -> bool {
3958 [
3959 ids.obj_mesh_anim_clip,
3960 ids.obj_mesh_anim_clip_name,
3961 ids.obj_mesh_anim_rate,
3962 ids.obj_mesh_anim_time_offset,
3963 ids.obj_mesh_anim_pause,
3964 ids.obj_mesh_anim_hold_time,
3965 ids.obj_mesh_anim_shift_time,
3966 ids.obj_mesh_anim_loop,
3967 ids.obj_mesh_anim_blend_clip,
3968 ids.obj_mesh_anim_blend_clip_name,
3969 ids.obj_mesh_anim_blend_weight,
3970 ]
3971 .into_iter()
3972 .any(|id| id != 0 && op == id)
3973 }
3974
3975 pub fn tick(&mut self, past_game_time: i32, past_real_time: i32) {
3976 let delta = past_game_time.max(0);
3977 self.runtime
3978 .prop_events
3979 .update_time(past_game_time, past_real_time);
3980 self.runtime.prop_events.frame();
3981 self.runtime
3982 .prop_event_lists
3983 .update_time(past_game_time, past_real_time);
3984 self.runtime.prop_event_lists.frame();
3985 self.frame_action
3986 .counter
3987 .update_time(past_game_time, past_real_time);
3988 for fa in &mut self.frame_action_ch {
3989 fa.counter.update_time(past_game_time, past_real_time);
3990 }
3991 for child in &mut self.runtime.child_objects {
3992 child.tick(past_game_time, past_real_time);
3993 }
3994 self.movie.tick(past_game_time, past_real_time);
3995 self.gan.update_time(past_game_time, past_real_time);
3996 if matches!(self.object_type, 6 | 7) {
3997 self.mesh_animation_state.advance_controller_frames(delta);
3998 }
3999
4000 if self.object_type == 9 && self.movie.just_finished && !self.movie.auto_free_flag {
4001 self.movie.pause_flag = true;
4002 }
4003 }
4004
4005 pub fn update_weather_time(
4006 &mut self,
4007 past_game_time: i32,
4008 past_real_time: i32,
4009 screen_w: i64,
4010 screen_h: i64,
4011 ) {
4012 if self.object_type != 4 || !matches!(self.weather_param.weather_type, 1 | 2) {
4013 return;
4014 }
4015 let cnt = self.weather_param.cnt.max(0) as usize;
4016 let cnt_max = self.weather_work.cnt_max.min(self.weather_work.sub.len());
4017 for idx in 0..cnt_max {
4018 let mut setup_after_sleep = false;
4019 {
4020 let sub = &mut self.weather_work.sub[idx];
4021 if idx >= cnt && sub.state == 0 {
4022 continue;
4023 }
4024 let past_time = if sub.real_time_flag {
4025 past_real_time.max(0) as i64
4026 } else {
4027 past_game_time.max(0) as i64
4028 };
4029 sub.state_cur_time = sub.state_cur_time.saturating_add(past_time);
4030 sub.move_cur_time = sub.move_cur_time.saturating_add(past_time);
4031 sub.sin_cur_time = sub.sin_cur_time.saturating_add(past_time);
4032
4033 if (idx >= cnt || sub.restruct_flag)
4034 && sub.state == 2
4035 && sub.state_time_len - sub.state_cur_time >= 3000
4036 {
4037 sub.state_cur_time = sub.state_time_len.saturating_sub(1500);
4038 }
4039
4040 while sub.state_cur_time - sub.state_time_len > 0 {
4041 let amari_time = sub.state_cur_time - sub.state_time_len;
4042 sub.state = (sub.state + 1) % 4;
4043 if sub.state == 0 {
4044 if idx >= cnt {
4045 break;
4046 }
4047 setup_after_sleep = true;
4048 break;
4049 }
4050 if sub.state == 1 {
4051 sub.move_cur_time = amari_time;
4052 }
4053 sub.state_time_len = match sub.state {
4054 1 => 1000,
4055 2 => sub.active_time_len,
4056 3 => 1000,
4057 _ => sub.state_time_len,
4058 };
4059 sub.state_cur_time = amari_time;
4060 }
4061 }
4062 if setup_after_sleep {
4063 self.setup_weather_sub(idx, 1, screen_w, screen_h);
4064 }
4065 }
4066 }
4067
4068 pub fn any_event_active(&self) -> bool {
4069 self.runtime.prop_events.any_active() || self.runtime.prop_event_lists.any_active()
4070 }
4071
4072 pub fn end_all_events(&mut self) {
4073 self.runtime.prop_events.end_all();
4074 self.runtime.prop_event_lists.end_all();
4075 }
4076
4077 pub fn event_target(
4078 &self,
4079 ids: &super::constants::RuntimeConstants,
4080 op: i32,
4081 ) -> ObjectEventTarget {
4082 if ids.obj_x_eve != 0 && op == ids.obj_x_eve {
4083 ObjectEventTarget::X
4084 } else if ids.obj_y_eve != 0 && op == ids.obj_y_eve {
4085 ObjectEventTarget::Y
4086 } else if ids.obj_x_rep_eve != 0 && op == ids.obj_x_rep_eve {
4087 ObjectEventTarget::XRep
4088 } else if ids.obj_y_rep_eve != 0 && op == ids.obj_y_rep_eve {
4089 ObjectEventTarget::YRep
4090 } else if ids.obj_z_rep_eve != 0 && op == ids.obj_z_rep_eve {
4091 ObjectEventTarget::ZRep
4092 } else if ids.obj_tr_eve != 0 && op == ids.obj_tr_eve {
4093 ObjectEventTarget::Tr
4094 } else if ids.obj_tr_rep_eve != 0 && op == ids.obj_tr_rep_eve {
4095 ObjectEventTarget::TrRep
4096 } else if ids.obj_patno_eve != 0 && op == ids.obj_patno_eve {
4097 ObjectEventTarget::Patno
4098 } else if ids.obj_z_eve != 0 && op == ids.obj_z_eve {
4099 ObjectEventTarget::Z
4100 } else if ids.obj_center_x_eve != 0 && op == ids.obj_center_x_eve {
4101 ObjectEventTarget::CenterX
4102 } else if ids.obj_center_y_eve != 0 && op == ids.obj_center_y_eve {
4103 ObjectEventTarget::CenterY
4104 } else if ids.obj_center_z_eve != 0 && op == ids.obj_center_z_eve {
4105 ObjectEventTarget::CenterZ
4106 } else if ids.obj_center_rep_x_eve != 0 && op == ids.obj_center_rep_x_eve {
4107 ObjectEventTarget::CenterRepX
4108 } else if ids.obj_center_rep_y_eve != 0 && op == ids.obj_center_rep_y_eve {
4109 ObjectEventTarget::CenterRepY
4110 } else if ids.obj_center_rep_z_eve != 0 && op == ids.obj_center_rep_z_eve {
4111 ObjectEventTarget::CenterRepZ
4112 } else if ids.obj_scale_x_eve != 0 && op == ids.obj_scale_x_eve {
4113 ObjectEventTarget::ScaleX
4114 } else if ids.obj_scale_y_eve != 0 && op == ids.obj_scale_y_eve {
4115 ObjectEventTarget::ScaleY
4116 } else if ids.obj_scale_z_eve != 0 && op == ids.obj_scale_z_eve {
4117 ObjectEventTarget::ScaleZ
4118 } else if ids.obj_rotate_x_eve != 0 && op == ids.obj_rotate_x_eve {
4119 ObjectEventTarget::RotateX
4120 } else if ids.obj_rotate_y_eve != 0 && op == ids.obj_rotate_y_eve {
4121 ObjectEventTarget::RotateY
4122 } else if ids.obj_rotate_z_eve != 0 && op == ids.obj_rotate_z_eve {
4123 ObjectEventTarget::RotateZ
4124 } else if ids.obj_clip_left_eve != 0 && op == ids.obj_clip_left_eve {
4125 ObjectEventTarget::ClipLeft
4126 } else if ids.obj_clip_top_eve != 0 && op == ids.obj_clip_top_eve {
4127 ObjectEventTarget::ClipTop
4128 } else if ids.obj_clip_right_eve != 0 && op == ids.obj_clip_right_eve {
4129 ObjectEventTarget::ClipRight
4130 } else if ids.obj_clip_bottom_eve != 0 && op == ids.obj_clip_bottom_eve {
4131 ObjectEventTarget::ClipBottom
4132 } else if ids.obj_src_clip_left_eve != 0 && op == ids.obj_src_clip_left_eve {
4133 ObjectEventTarget::SrcClipLeft
4134 } else if ids.obj_src_clip_top_eve != 0 && op == ids.obj_src_clip_top_eve {
4135 ObjectEventTarget::SrcClipTop
4136 } else if ids.obj_src_clip_right_eve != 0 && op == ids.obj_src_clip_right_eve {
4137 ObjectEventTarget::SrcClipRight
4138 } else if ids.obj_src_clip_bottom_eve != 0 && op == ids.obj_src_clip_bottom_eve {
4139 ObjectEventTarget::SrcClipBottom
4140 } else if ids.obj_mono_eve != 0 && op == ids.obj_mono_eve {
4141 ObjectEventTarget::Mono
4142 } else if ids.obj_reverse_eve != 0 && op == ids.obj_reverse_eve {
4143 ObjectEventTarget::Reverse
4144 } else if ids.obj_bright_eve != 0 && op == ids.obj_bright_eve {
4145 ObjectEventTarget::Bright
4146 } else if ids.obj_dark_eve != 0 && op == ids.obj_dark_eve {
4147 ObjectEventTarget::Dark
4148 } else if ids.obj_color_rate_eve != 0 && op == ids.obj_color_rate_eve {
4149 ObjectEventTarget::ColorRate
4150 } else if ids.obj_color_add_r_eve != 0 && op == ids.obj_color_add_r_eve {
4151 ObjectEventTarget::ColorAddR
4152 } else if ids.obj_color_add_g_eve != 0 && op == ids.obj_color_add_g_eve {
4153 ObjectEventTarget::ColorAddG
4154 } else if ids.obj_color_add_b_eve != 0 && op == ids.obj_color_add_b_eve {
4155 ObjectEventTarget::ColorAddB
4156 } else if ids.obj_color_r_eve != 0 && op == ids.obj_color_r_eve {
4157 ObjectEventTarget::ColorR
4158 } else if ids.obj_color_g_eve != 0 && op == ids.obj_color_g_eve {
4159 ObjectEventTarget::ColorG
4160 } else if ids.obj_color_b_eve != 0 && op == ids.obj_color_b_eve {
4161 ObjectEventTarget::ColorB
4162 } else {
4163 ObjectEventTarget::Unknown
4164 }
4165 }
4166}
4167
4168#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4169pub enum GroupListOpKind {
4170 Alloc,
4171 Free,
4172 Unknown,
4173}
4174
4175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4176pub enum GroupOpKind {
4177 Sel,
4178 SelCancel,
4179 Init,
4180 Start,
4181 StartCancel,
4182 End,
4183 GetHitNo,
4184 GetPushedNo,
4185 GetDecidedNo,
4186 GetResult,
4187 GetResultButtonNo,
4188 Order,
4189 Layer,
4190 CancelPriority,
4191 Unknown,
4192}
4193
4194#[derive(Debug, Clone)]
4195pub struct GroupState {
4196 pub wait_flag: bool,
4197 pub cancel_flag: bool,
4198 pub cancel_se_no: i64,
4199 pub started: bool,
4200
4201 pub hit_button_no: i64,
4202 pub pushed_button_no: i64,
4203 pub decided_button_no: i64,
4204 pub hit_runtime_slot: Option<usize>,
4205 pub pushed_runtime_slot: Option<usize>,
4206
4207 pub result: i64,
4208 pub result_button_no: i64,
4209
4210 pub order: i64,
4211 pub layer: i64,
4212 pub cancel_priority: i64,
4213 pub props: HashMap<i32, i64>,
4214 pub aux_str_props: HashMap<i32, String>,
4215}
4216
4217impl Default for GroupState {
4218 fn default() -> Self {
4219 let mut state = Self {
4220 wait_flag: false,
4221 cancel_flag: false,
4222 cancel_se_no: -1,
4223 started: false,
4224 hit_button_no: -1,
4225 pushed_button_no: -1,
4226 decided_button_no: TNM_GROUP_NOT_DECIDED,
4227 hit_runtime_slot: None,
4228 pushed_runtime_slot: None,
4229 result: TNM_GROUP_RESULT_NONE,
4230 result_button_no: 0,
4231 order: 0,
4232 layer: 0,
4233 cancel_priority: 0,
4234 props: HashMap::new(),
4235 aux_str_props: HashMap::new(),
4236 };
4237 state.reinit();
4238 state
4239 }
4240}
4241
4242pub const TNM_GROUP_NOT_DECIDED: i64 = -2;
4243pub const TNM_GROUP_CANCELED: i64 = -1;
4244pub const TNM_GROUP_RESULT_DECIDED: i64 = 1;
4245pub const TNM_GROUP_RESULT_NONE: i64 = 0;
4246pub const TNM_GROUP_RESULT_CANCELLED: i64 = -1;
4247
4248impl GroupState {
4249 pub fn reinit(&mut self) {
4250 self.order = 0;
4251 self.layer = 0;
4252 self.cancel_priority = 0;
4253 self.cancel_se_no = -1;
4254 self.decided_button_no = TNM_GROUP_NOT_DECIDED;
4255 self.result = TNM_GROUP_RESULT_NONE;
4256 self.result_button_no = 0;
4257 self.started = false;
4258 self.wait_flag = false;
4259 self.cancel_flag = false;
4260 self.hit_button_no = -1;
4261 self.pushed_button_no = -1;
4262 self.hit_runtime_slot = None;
4263 self.pushed_runtime_slot = None;
4264 }
4265
4266 pub fn init_sel(&mut self) {
4267 self.cancel_priority = 0;
4268 self.cancel_se_no = -1;
4269 self.decided_button_no = TNM_GROUP_NOT_DECIDED;
4270 self.result = TNM_GROUP_RESULT_NONE;
4271 self.result_button_no = 0;
4272 self.started = false;
4273 self.wait_flag = false;
4274 self.cancel_flag = false;
4275 self.hit_button_no = -1;
4276 self.pushed_button_no = -1;
4277 self.hit_runtime_slot = None;
4278 self.pushed_runtime_slot = None;
4279 }
4280
4281 pub fn start(&mut self) {
4282 self.started = true;
4283 self.decided_button_no = TNM_GROUP_NOT_DECIDED;
4284 }
4285
4286 pub fn end(&mut self) {
4287 self.started = false;
4288 self.decided_button_no = TNM_GROUP_NOT_DECIDED;
4289 }
4290
4291 pub fn decide(&mut self, button_no: i64) -> bool {
4292 if !self.started {
4293 return false;
4294 }
4295 self.started = false;
4296 self.decided_button_no = button_no;
4297 self.result = TNM_GROUP_RESULT_DECIDED;
4298 self.result_button_no = button_no;
4299 self.hit_button_no = -1;
4300 self.pushed_button_no = -1;
4301 self.hit_runtime_slot = None;
4302 self.pushed_runtime_slot = None;
4303 true
4304 }
4305
4306 pub fn cancel(&mut self) -> Option<i64> {
4307 if !self.started {
4308 return None;
4309 }
4310 let hit_button_no = self.hit_button_no;
4311 self.started = false;
4312 self.decided_button_no = TNM_GROUP_CANCELED;
4313 self.result = TNM_GROUP_RESULT_CANCELLED;
4314 self.result_button_no = hit_button_no;
4315 self.hit_button_no = -1;
4316 self.pushed_button_no = -1;
4317 self.hit_runtime_slot = None;
4318 self.pushed_runtime_slot = None;
4319 Some(hit_button_no)
4320 }
4321}
4322
4323#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4324pub enum MwndListOpKind {
4325 CloseAll,
4326 CloseAllWait,
4327 CloseAllNowait,
4328 Unknown,
4329}
4330
4331#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4332pub enum MwndOpKind {
4333 MsgBlock,
4334 OpenWait,
4335 OpenNowait,
4336 CloseWait,
4337 CloseNowait,
4338 EndClose,
4339 CheckOpen,
4340 Clear,
4341 NovelClear,
4342 Print,
4344 NewLineNoIndent,
4346 NewLineIndent,
4348 WaitMsg,
4350 Pp,
4352 R,
4354 PageWait,
4356
4357 SetName,
4358 ClearName,
4359 GetName,
4360 NextMsg,
4361 MultiMsg,
4362 Ruby,
4363 Koe,
4364 KoePlayWait,
4365 KoePlayWaitKey,
4366 Layer,
4367 World,
4368 SetMojiSize,
4369 SetMojiColor,
4370 SetIndent,
4371 ClearIndent,
4372 StartSlideMsg,
4373 EndSlideMsg,
4374 SlideMsg,
4375 InitOpenAnimeType,
4376 InitOpenAnimeTime,
4377 InitCloseAnimeType,
4378 InitCloseAnimeTime,
4379 SetOpenAnimeType,
4380 SetOpenAnimeTime,
4381 SetCloseAnimeType,
4382 SetCloseAnimeTime,
4383 GetOpenAnimeType,
4384 GetOpenAnimeTime,
4385 GetCloseAnimeType,
4386 GetCloseAnimeTime,
4387 GetDefaultOpenAnimeType,
4388 GetDefaultOpenAnimeTime,
4389 GetDefaultCloseAnimeType,
4390 GetDefaultCloseAnimeTime,
4391 Sel,
4392 SelCancel,
4393 SelMsg,
4394 SelMsgCancel,
4395
4396 AddMsgCheck,
4398 AddMsg,
4400
4401 SetWaku,
4402 InitWakuFile,
4403 SetWakuFile,
4404 GetWakuFile,
4405 InitFilterFile,
4406 SetFilterFile,
4407 GetFilterFile,
4408
4409 ClearFace,
4410 SetFace,
4411 SetRepPos,
4412 MsgBtn,
4413 InitWindowPos,
4414 InitWindowSize,
4415 SetWindowPos,
4416 SetWindowSize,
4417 GetWindowPosX,
4418 GetWindowPosY,
4419 GetWindowSizeX,
4420 GetWindowSizeY,
4421 InitWindowMojiCnt,
4422 SetWindowMojiCnt,
4423 GetWindowMojiCntX,
4424 GetWindowMojiCntY,
4425 Unknown,
4426}
4427
4428#[derive(Debug, Default, Clone)]
4429pub struct MwndSelectionChoice {
4430 pub text: String,
4431 pub kind: i64,
4432 pub color: i64,
4433}
4434
4435#[derive(Debug, Default, Clone)]
4436pub struct MwndSelectionState {
4437 pub choices: Vec<MwndSelectionChoice>,
4438 pub cursor: usize,
4439 pub cancel_enable: bool,
4440 pub close_mwnd: bool,
4441 pub result: i64,
4443}
4444
4445#[derive(Debug, Default, Clone)]
4446pub struct BtnSelItemState {
4447 pub generated_objects: Vec<ObjectState>,
4448 pub object_list: Vec<ObjectState>,
4449 pub strict: bool,
4450 pub text: String,
4451 pub item_type: i64,
4452 pub color: i64,
4453 pub pos: (i64, i64),
4454 pub size: (i64, i64),
4455 pub visible: bool,
4456 pub selected: bool,
4457 pub button_action_no: i64,
4458 pub button_state: i64,
4459}
4460
4461#[derive(Debug, Default, Clone)]
4462pub struct MwndState {
4463 pub initialized_from_gameexe: bool,
4464 pub open: bool,
4465 pub name_text: String,
4466 pub msg_text: String,
4467 pub msg_waku_no: Option<i64>,
4468 pub waku_file: String,
4469 pub filter_file: String,
4470 pub filter_margin: Option<(i64, i64, i64, i64)>,
4471 pub filter_color: Option<(u8, u8, u8, u8)>,
4472 pub filter_config_color: bool,
4473 pub filter_config_tr: bool,
4474 pub waku_extend_type: i64,
4475 pub icon_no: i64,
4476 pub page_icon_no: i64,
4477 pub key_icon_appear: bool,
4478 pub key_icon_mode: i64,
4479 pub key_icon_pos: Option<(i64, i64)>,
4480 pub icon_pos_type: i64,
4481 pub icon_pos_base: i64,
4482 pub icon_pos: Option<(i64, i64, i64)>,
4483 pub waku_button_layout: Vec<(i64, i64, i64)>,
4485 pub waku_face_pos: Vec<(i64, i64)>,
4487 pub face_file: String,
4488 pub face_no: i64,
4489 pub rep_pos: Option<(i64, i64)>,
4490 pub msgbtn: Option<(i64, i64, i64, i64)>,
4491 pub window_pos: Option<(i64, i64)>,
4492 pub window_size: Option<(i64, i64)>,
4493 pub message_pos: Option<(i64, i64)>,
4494 pub message_margin: Option<(i64, i64, i64, i64)>,
4495 pub window_moji_cnt: Option<(i64, i64)>,
4496 pub moji_space: Option<(i64, i64)>,
4497 pub mwnd_extend_type: i64,
4498 pub multi_msg: bool,
4499 pub ruby_text: Option<String>,
4500 pub koe: Option<(i64, i64)>,
4501 pub order: i64,
4507 pub layer: i64,
4508 pub world: i64,
4509 pub moji_size: Option<i64>,
4510 pub moji_color: Option<i64>,
4511 pub shadow_color: Option<i64>,
4512 pub fuchi_color: Option<i64>,
4513 pub chara_color_mod: Option<i64>,
4514 pub chara_moji_color: Option<i64>,
4515 pub chara_shadow_color: Option<i64>,
4516 pub chara_fuchi_color: Option<i64>,
4517 pub name_moji_color: Option<i64>,
4518 pub name_shadow_color: Option<i64>,
4519 pub name_fuchi_color: Option<i64>,
4520 pub indent: bool,
4521 pub slide_msg: bool,
4522 pub slide_time: i64,
4523 pub open_anime_type: i64,
4524 pub open_anime_time: i64,
4525 pub close_anime_type: i64,
4526 pub close_anime_time: i64,
4527 pub selection: Option<MwndSelectionState>,
4528
4529 pub text_dirty: bool,
4530 pub clear_ready: bool,
4531 pub msg_block_started: bool,
4532
4533 pub button_list: Vec<ObjectState>,
4534 pub button_list_strict: bool,
4535 pub face_list: Vec<ObjectState>,
4536 pub face_list_strict: bool,
4537 pub object_list: Vec<ObjectState>,
4538 pub object_list_strict: bool,
4539 pub props: HashMap<i32, i64>,
4540 pub aux_str_props: HashMap<i32, String>,
4541}
4542
4543#[derive(Debug, Default, Clone)]
4544pub struct StageFormState {
4545 pub initialized_from_gameexe: bool,
4547 pub group_lists: HashMap<i64, Vec<GroupState>>,
4549 pub btnselitem_lists: HashMap<i64, Vec<BtnSelItemState>>,
4551 pub mwnd_lists: HashMap<i64, Vec<MwndState>>,
4553 pub world_lists: HashMap<i64, Vec<WorldState>>,
4555 pub effect_lists: HashMap<i64, Vec<ScreenEffectState>>,
4557 pub quake_lists: HashMap<i64, Vec<ScreenQuakeState>>,
4559 pub object_lists: HashMap<i64, Vec<ObjectState>>,
4562 pub object_slot_use: HashMap<i64, Vec<bool>>,
4566 pub object_list_strict: HashMap<i64, bool>,
4568 pub rect_layers: HashMap<i64, LayerId>,
4570
4571 pub embedded_object_slots: HashMap<String, usize>,
4573 pub next_embedded_object_slot: HashMap<i64, usize>,
4574 pub next_nested_object_slot: HashMap<i64, usize>,
4575}
4576
4577#[derive(Debug, Clone)]
4582pub struct ScreenEffectState {
4583 pub x: IntEvent,
4584 pub y: IntEvent,
4585 pub z: IntEvent,
4586 pub mono: IntEvent,
4587 pub reverse: IntEvent,
4588 pub bright: IntEvent,
4589 pub dark: IntEvent,
4590 pub color_r: IntEvent,
4591 pub color_g: IntEvent,
4592 pub color_b: IntEvent,
4593 pub color_rate: IntEvent,
4594 pub color_add_r: IntEvent,
4595 pub color_add_g: IntEvent,
4596 pub color_add_b: IntEvent,
4597 pub begin_order: i32,
4598 pub begin_layer: i32,
4599 pub end_order: i32,
4600 pub end_layer: i32,
4601 pub wipe_copy: i32,
4602 pub wipe_erase: i32,
4603}
4604
4605impl Default for ScreenEffectState {
4606 fn default() -> Self {
4607 Self {
4608 x: IntEvent::new(0),
4609 y: IntEvent::new(0),
4610 z: IntEvent::new(0),
4611 mono: IntEvent::new(0),
4612 reverse: IntEvent::new(0),
4613 bright: IntEvent::new(0),
4614 dark: IntEvent::new(0),
4615 color_r: IntEvent::new(0),
4616 color_g: IntEvent::new(0),
4617 color_b: IntEvent::new(0),
4618 color_rate: IntEvent::new(0),
4619 color_add_r: IntEvent::new(0),
4620 color_add_g: IntEvent::new(0),
4621 color_add_b: IntEvent::new(0),
4622 begin_order: 0,
4623 begin_layer: i32::MIN,
4624 end_order: 0,
4625 end_layer: i32::MAX,
4626 wipe_copy: 0,
4627 wipe_erase: 0,
4628 }
4629 }
4630}
4631impl ScreenEffectState {
4632 pub fn reinit(&mut self) {
4633 *self = Self::default();
4634 }
4635
4636 pub fn tick(&mut self, delta: i32) {
4637 self.x.tick(delta);
4638 self.y.tick(delta);
4639 self.z.tick(delta);
4640 self.mono.tick(delta);
4641 self.reverse.tick(delta);
4642 self.bright.tick(delta);
4643 self.dark.tick(delta);
4644 self.color_r.tick(delta);
4645 self.color_g.tick(delta);
4646 self.color_b.tick(delta);
4647 self.color_rate.tick(delta);
4648 self.color_add_r.tick(delta);
4649 self.color_add_g.tick(delta);
4650 self.color_add_b.tick(delta);
4651 }
4652}
4653
4654#[derive(Debug, Clone)]
4655pub struct ScreenQuakeState {
4656 pub until: Option<Instant>,
4657 pub quake_type: i32,
4658 pub power: i32,
4659 pub vec: i32,
4660 pub center_x: i32,
4661 pub center_y: i32,
4662 pub begin_order: i32,
4663 pub end_order: i32,
4664 pub ending: bool,
4665}
4666
4667impl Default for ScreenQuakeState {
4668 fn default() -> Self {
4669 Self {
4670 until: None,
4671 quake_type: -1,
4672 power: 0,
4673 vec: 0,
4674 center_x: 0,
4675 center_y: 0,
4676 begin_order: 0,
4677 end_order: 0,
4678 ending: false,
4679 }
4680 }
4681}
4682
4683impl ScreenQuakeState {
4684 pub fn reinit(&mut self) {
4685 *self = Self::default();
4686 }
4687
4688 pub fn start_kind(&mut self, quake_type: i32, time_ms: i64) {
4689 self.ending = false;
4690 self.quake_type = quake_type;
4691 let ms = time_ms.max(0) as u64;
4692 self.until = if ms == 0 {
4693 None
4694 } else {
4695 Some(Instant::now() + Duration::from_millis(ms))
4696 };
4697 if ms == 0 {
4698 self.reinit();
4699 }
4700 }
4701
4702 pub fn end_ms(&mut self, time_ms: i64) {
4703 self.ending = true;
4704 let ms = time_ms.max(0) as u64;
4705 self.until = if ms == 0 {
4706 None
4707 } else {
4708 Some(Instant::now() + Duration::from_millis(ms))
4709 };
4710 if ms == 0 {
4711 self.reinit();
4712 }
4713 }
4714
4715 pub fn check_value(&mut self) -> i32 {
4716 let _ = self.is_active();
4717 if self.quake_type < 0 {
4718 0
4719 } else if self.ending {
4720 2
4721 } else {
4722 1
4723 }
4724 }
4725
4726 pub fn is_active(&mut self) -> bool {
4727 if let Some(t) = self.until {
4728 if Instant::now() >= t {
4729 self.reinit();
4730 return false;
4731 }
4732 }
4733 self.quake_type >= 0 && self.until.is_some()
4734 }
4735
4736 pub fn remaining_ms(&mut self) -> u64 {
4737 let Some(t) = self.until else {
4738 return 0;
4739 };
4740 if Instant::now() >= t {
4741 self.reinit();
4742 return 0;
4743 }
4744 t.duration_since(Instant::now()).as_millis() as u64
4745 }
4746}
4747
4748#[derive(Debug, Default, Clone)]
4749pub struct ScreenShakeState {
4750 pub last_value: i64,
4751 pub until: Option<Instant>,
4752}
4753
4754impl ScreenShakeState {
4755 pub fn set_ms(&mut self, time_ms: i64) {
4756 self.last_value = time_ms;
4757 let ms = time_ms.max(0) as u64;
4758 self.until = if ms == 0 {
4759 None
4760 } else {
4761 Some(Instant::now() + Duration::from_millis(ms))
4762 };
4763 }
4764
4765 pub fn tick(&mut self) {
4766 if let Some(t) = self.until {
4767 if Instant::now() >= t {
4768 self.until = None;
4769 }
4770 }
4771 }
4772}
4773
4774#[derive(Debug, Default, Clone)]
4775pub struct ScreenFormState {
4776 pub effect_list: Vec<ScreenEffectState>,
4777 pub quake_list: Vec<ScreenQuakeState>,
4778 pub shake: ScreenShakeState,
4779}
4780
4781impl ScreenFormState {
4782 pub fn ensure_effect_len(&mut self, n: usize) {
4783 if self.effect_list.len() < n {
4784 self.effect_list
4785 .extend((0..(n - self.effect_list.len())).map(|_| ScreenEffectState::default()));
4786 } else if self.effect_list.len() > n {
4787 self.effect_list.truncate(n);
4788 }
4789 }
4790
4791 pub fn ensure_quake_len(&mut self, n: usize) {
4792 if self.quake_list.len() < n {
4793 self.quake_list
4794 .extend((0..(n - self.quake_list.len())).map(|_| ScreenQuakeState::default()));
4795 } else if self.quake_list.len() > n {
4796 self.quake_list.truncate(n);
4797 }
4798 }
4799
4800 pub fn tick(&mut self, delta: i32) {
4801 for effect in &mut self.effect_list {
4802 effect.tick(delta);
4803 }
4804 for quake in &mut self.quake_list {
4805 let _ = quake.is_active();
4806 }
4807 self.shake.tick();
4808 }
4809}
4810
4811#[derive(Debug, Default, Clone)]
4816pub struct MsgBackEntry {
4817 pub pct_flag: bool,
4818 pub msg_str: String,
4819 pub original_name: String,
4820 pub disp_name: String,
4821 pub pct_pos_x: i32,
4822 pub pct_pos_y: i32,
4823 pub koe_no_list: Vec<i64>,
4824 pub chr_no_list: Vec<i64>,
4825 pub koe_play_no: i64,
4826 pub debug_msg: String,
4827 pub scn_no: i64,
4828 pub line_no: i64,
4829 pub save_id: i64,
4830 pub save_id_check_flag: bool,
4831}
4832
4833#[derive(Debug, Clone)]
4834pub struct MsgBackState {
4835 pub history: Vec<MsgBackEntry>,
4836 pub history_cnt_max: usize,
4837 pub history_cnt: usize,
4838 pub history_start_pos: usize,
4839 pub history_insert_pos: usize,
4840 pub history_last_pos: usize,
4841 pub new_msg_flag: bool,
4842}
4843
4844impl Default for MsgBackState {
4845 fn default() -> Self {
4846 let history_cnt_max = 256usize;
4847 Self {
4848 history: vec![MsgBackEntry { scn_no: -1, line_no: -1, ..MsgBackEntry::default() }; history_cnt_max],
4849 history_cnt_max,
4850 history_cnt: 0,
4851 history_start_pos: 0,
4852 history_insert_pos: 0,
4853 history_last_pos: 0,
4854 new_msg_flag: true,
4855 }
4856 }
4857}
4858
4859impl MsgBackState {
4860 fn reset_entry(entry: &mut MsgBackEntry) {
4861 *entry = MsgBackEntry {
4862 scn_no: -1,
4863 line_no: -1,
4864 ..MsgBackEntry::default()
4865 };
4866 }
4867
4868 fn ensure_capacity(&mut self) {
4869 if self.history_cnt_max == 0 {
4870 self.history_cnt_max = 256;
4871 }
4872 if self.history.len() != self.history_cnt_max {
4873 self.history.resize_with(self.history_cnt_max, || MsgBackEntry {
4874 scn_no: -1,
4875 line_no: -1,
4876 ..MsgBackEntry::default()
4877 });
4878 }
4879 self.history_insert_pos %= self.history_cnt_max;
4880 self.history_start_pos %= self.history_cnt_max;
4881 self.history_last_pos %= self.history_cnt_max;
4882 }
4883
4884 pub fn set_history_cnt_max(&mut self, max_count: usize) {
4885 let max_count = max_count.max(1);
4886 if max_count == self.history_cnt_max {
4887 self.ensure_capacity();
4888 return;
4889 }
4890 let mut ordered = self
4891 .ordered_history_indices()
4892 .into_iter()
4893 .filter_map(|idx| self.history.get(idx).cloned())
4894 .collect::<Vec<_>>();
4895 if ordered.len() > max_count {
4896 let drop_count = ordered.len() - max_count;
4897 ordered.drain(0..drop_count);
4898 }
4899 self.history_cnt_max = max_count;
4900 self.history = vec![MsgBackEntry { scn_no: -1, line_no: -1, ..MsgBackEntry::default() }; max_count];
4901 self.history_cnt = ordered.len();
4902 self.history_start_pos = 0;
4903 for (i, entry) in ordered.into_iter().enumerate() {
4904 self.history[i] = entry;
4905 }
4906 self.history_insert_pos = self.history_cnt % self.history_cnt_max;
4907 self.history_last_pos = self.history_cnt.saturating_sub(1).min(self.history_cnt_max - 1);
4908 self.new_msg_flag = true;
4909 }
4910
4911 fn ready_msg(&mut self) -> &mut MsgBackEntry {
4912 self.ensure_capacity();
4913 if self.new_msg_flag {
4914 if self.history_cnt < self.history_cnt_max {
4915 self.history_cnt += 1;
4916 } else {
4917 self.history_start_pos = (self.history_start_pos + 1) % self.history_cnt_max;
4918 }
4919 Self::reset_entry(&mut self.history[self.history_insert_pos]);
4920 self.new_msg_flag = false;
4921 }
4922 &mut self.history[self.history_insert_pos]
4923 }
4924
4925 pub fn clear(&mut self) {
4926 self.ensure_capacity();
4927 for entry in &mut self.history {
4928 Self::reset_entry(entry);
4929 }
4930 self.history_cnt = 0;
4931 self.history_start_pos = 0;
4932 self.history_insert_pos = 0;
4933 self.history_last_pos = 0;
4934 self.new_msg_flag = true;
4935 }
4936
4937 pub fn ordered_history_indices(&self) -> Vec<usize> {
4938 if self.history_cnt_max == 0 || self.history_cnt == 0 {
4939 return Vec::new();
4940 }
4941 (0..self.history_cnt)
4942 .map(|i| (self.history_start_pos + i) % self.history_cnt_max)
4943 .collect()
4944 }
4945
4946 pub fn next(&mut self) {
4947 self.ensure_capacity();
4948 if self.new_msg_flag {
4949 return;
4950 }
4951 let Some(cur) = self.history.get(self.history_insert_pos) else {
4952 self.new_msg_flag = true;
4953 return;
4954 };
4955 if !cur.pct_flag && cur.msg_str.is_empty() {
4956 return;
4957 }
4958 self.history_insert_pos = (self.history_insert_pos + 1) % self.history_cnt_max;
4959 self.new_msg_flag = true;
4960 }
4961
4962 pub fn add_koe(&mut self, koe_no: i64, chara_no: i64, scn_no: i64, line_no: i64) -> bool {
4963 if koe_no < 0 {
4964 return true;
4965 }
4966 let insert_pos = self.history_insert_pos;
4967 let entry = self.ready_msg();
4968 entry.koe_no_list.push(koe_no);
4969 entry.chr_no_list.push(chara_no);
4970 entry.scn_no = scn_no;
4971 entry.line_no = line_no;
4972 self.history_last_pos = insert_pos;
4973 true
4974 }
4975
4976 pub fn add_name(
4977 &mut self,
4978 original_name: &str,
4979 disp_name: &str,
4980 scn_no: i64,
4981 line_no: i64,
4982 ) -> bool {
4983 if disp_name.is_empty() {
4984 return true;
4985 }
4986 let insert_pos = self.history_insert_pos;
4987 let entry = self.ready_msg();
4988 entry.original_name.clear();
4989 entry.original_name.push_str(original_name);
4990 entry.disp_name.clear();
4991 entry.disp_name.push_str(disp_name);
4992 entry.scn_no = scn_no;
4993 entry.line_no = line_no;
4994 self.history_last_pos = insert_pos;
4995 true
4996 }
4997
4998 pub fn add_msg(&mut self, msg: &str, debug_msg: &str, scn_no: i64, line_no: i64) -> bool {
4999 if msg.is_empty() {
5000 return true;
5001 }
5002 let insert_pos = self.history_insert_pos;
5003 let entry = self.ready_msg();
5004 entry.msg_str.push_str(msg);
5005 entry.debug_msg.clear();
5006 entry.debug_msg.push_str(debug_msg);
5007 entry.scn_no = scn_no;
5008 entry.line_no = line_no;
5009 self.history_last_pos = insert_pos;
5010 true
5011 }
5012
5013 pub fn add_new_line_indent(&mut self, scn_no: i64, line_no: i64) -> bool {
5014 let insert_pos = self.history_insert_pos;
5015 let entry = self.ready_msg();
5016 entry.msg_str.push('\n');
5017 entry.scn_no = scn_no;
5018 entry.line_no = line_no;
5019 self.history_last_pos = insert_pos;
5020 true
5021 }
5022
5023 pub fn add_new_line_no_indent(&mut self, scn_no: i64, line_no: i64) -> bool {
5024 let insert_pos = self.history_insert_pos;
5025 let entry = self.ready_msg();
5026 entry.msg_str.push('\u{0007}');
5027 entry.scn_no = scn_no;
5028 entry.line_no = line_no;
5029 self.history_last_pos = insert_pos;
5030 true
5031 }
5032
5033 pub fn add_pct(&mut self, file_name: &str, x: i32, y: i32) -> bool {
5034 if file_name.is_empty() {
5035 return false;
5036 }
5037 self.next();
5038 let insert_pos = self.history_insert_pos;
5039 let entry = self.ready_msg();
5040 entry.pct_flag = true;
5041 entry.pct_pos_x = x;
5042 entry.pct_pos_y = y;
5043 entry.msg_str.clear();
5044 entry.msg_str.push_str(file_name);
5045 self.history_last_pos = insert_pos;
5046 self.next();
5047 true
5048 }
5049
5050 pub fn current_entry(&self) -> Option<&MsgBackEntry> {
5051 self.history.get(self.history_insert_pos)
5052 }
5053}
5054
5055impl StageFormState {
5056 pub fn ensure_group_list(&mut self, stage_idx: i64, cnt: usize) {
5057 let entry = self.group_lists.entry(stage_idx).or_default();
5058 if entry.len() < cnt {
5059 entry.extend((0..(cnt - entry.len())).map(|_| GroupState::default()));
5060 } else if entry.len() > cnt {
5061 entry.truncate(cnt);
5062 }
5063 }
5064
5065 pub fn clear_group_list(&mut self, stage_idx: i64) {
5066 self.group_lists.insert(stage_idx, Vec::new());
5067 }
5068
5069 pub fn ensure_mwnd_list(&mut self, stage_idx: i64, cnt: usize) {
5070 let entry = self.mwnd_lists.entry(stage_idx).or_default();
5071 if entry.len() < cnt {
5072 entry.extend((0..(cnt - entry.len())).map(|_| MwndState::default()));
5073 } else if entry.len() > cnt {
5074 entry.truncate(cnt);
5075 }
5076 }
5077
5078 pub fn ensure_effect_list(&mut self, stage_idx: i64, cnt: usize) {
5079 let entry = self.effect_lists.entry(stage_idx).or_default();
5080 if entry.len() < cnt {
5081 entry.extend((0..(cnt - entry.len())).map(|_| ScreenEffectState::default()));
5082 } else if entry.len() > cnt {
5083 entry.truncate(cnt);
5084 }
5085 }
5086
5087 pub fn ensure_quake_list(&mut self, stage_idx: i64, cnt: usize) {
5088 let entry = self.quake_lists.entry(stage_idx).or_default();
5089 if entry.len() < cnt {
5090 entry.extend((0..(cnt - entry.len())).map(|_| ScreenQuakeState::default()));
5091 } else if entry.len() > cnt {
5092 entry.truncate(cnt);
5093 }
5094 }
5095
5096 pub fn close_all_mwnd(&mut self, stage_idx: i64) {
5097 if let Some(list) = self.mwnd_lists.get_mut(&stage_idx) {
5098 for (idx, m) in list.iter_mut().enumerate() {
5099 let old_open = m.open;
5100 m.open = false;
5101 if std::env::var_os("SG_DEBUG").is_some() {
5102 eprintln!(
5103 "[SG_DEBUG][MWND_STATE_TRACE] scene=<runtime> scene_no=- line=- reason=STAGE_CLOSE_ALL_MWND stage={} mwnd={} old_open={} new_open={} buttons={} faces={} objects={} waku={} filter={} pos={:?} size={:?} open_anim=({}, {}) close_anim=({}, {}) selection={} msg_len={} name_len={}",
5104 stage_idx,
5105 idx,
5106 old_open,
5107 m.open,
5108 m.button_list.len(),
5109 m.face_list.len(),
5110 m.object_list.len(),
5111 if m.waku_file.is_empty() { "-" } else { m.waku_file.as_str() },
5112 if m.filter_file.is_empty() { "-" } else { m.filter_file.as_str() },
5113 m.window_pos,
5114 m.window_size,
5115 m.open_anime_type,
5116 m.open_anime_time,
5117 m.close_anime_type,
5118 m.close_anime_time,
5119 m.selection.is_some(),
5120 m.msg_text.len(),
5121 m.name_text.len(),
5122 );
5123 }
5124 }
5125 }
5126 }
5127
5128 pub fn ensure_object_list(&mut self, stage_idx: i64, cnt: usize) {
5129 let entry = self.object_lists.entry(stage_idx).or_default();
5130 if entry.len() < cnt {
5131 entry.extend((0..(cnt - entry.len())).map(|_| ObjectState::default()));
5132 } else if entry.len() > cnt {
5133 entry.truncate(cnt);
5134 }
5135
5136 let slot_use = self.object_slot_use.entry(stage_idx).or_default();
5137 if slot_use.len() < cnt {
5138 slot_use.extend((0..(cnt - slot_use.len())).map(|_| true));
5139 } else if slot_use.len() > cnt {
5140 slot_use.truncate(cnt);
5141 }
5142 }
5143
5144 pub fn set_object_list_len_strict(&mut self, stage_idx: i64, cnt: usize) {
5145 self.ensure_object_list(stage_idx, cnt);
5146 self.object_list_strict.insert(stage_idx, true);
5147 }
5148
5149 pub fn object_list_len(&self, stage_idx: i64) -> usize {
5150 self.object_lists
5151 .get(&stage_idx)
5152 .map(|v| v.len())
5153 .unwrap_or(0)
5154 }
5155
5156 pub fn is_embedded_object_slot(&self, stage_idx: i64, slot: usize) -> bool {
5157 let prefix = format!("{stage_idx}:");
5158 self.embedded_object_slots
5159 .iter()
5160 .any(|(key, &mapped_slot)| mapped_slot == slot && key.starts_with(&prefix))
5161 }
5162}
5163
5164impl MaskListState {
5165 pub fn new(mask_cnt: usize) -> Self {
5166 let mut masks = Vec::with_capacity(mask_cnt);
5167 for _ in 0..mask_cnt {
5168 masks.push(MaskState::new());
5169 }
5170 Self { masks }
5171 }
5172
5173 pub fn ensure_size(&mut self, mask_cnt: usize) {
5174 if self.masks.len() < mask_cnt {
5175 self.masks.reserve(mask_cnt - self.masks.len());
5176 while self.masks.len() < mask_cnt {
5177 self.masks.push(MaskState::new());
5178 }
5179 } else if self.masks.len() > mask_cnt {
5180 self.masks.truncate(mask_cnt);
5181 }
5182 }
5183
5184 pub fn tick_frame(&mut self, delta: i32) {
5185 for m in &mut self.masks {
5186 m.x_event.tick(delta);
5187 m.y_event.tick(delta);
5188 for ev in m.script_events.values_mut() {
5189 ev.tick(delta);
5190 }
5191 }
5192 }
5193}
5194
5195impl GlobalState {
5196 pub fn start_wipe(&mut self, w: WipeState) {
5197 self.wipe = Some(w);
5198 }
5199
5200 pub fn finish_wipe(&mut self) {
5201 self.wipe = None;
5202 }
5203
5204 pub fn wipe_done(&self) -> bool {
5205 self.wipe.as_ref().map(|w| w.is_done()).unwrap_or(true)
5206 }
5207
5208 pub fn tick_frame(&mut self, past_game_time: i32, past_real_time: i32) {
5209 self.render_frame = self.render_frame.wrapping_add(1);
5210 self.local_real_time = self
5211 .local_real_time
5212 .saturating_add(past_real_time.max(0) as i64);
5213 self.local_game_time = self
5214 .local_game_time
5215 .saturating_add(past_game_time.max(0) as i64);
5216 self.local_wipe_time = self
5217 .local_wipe_time
5218 .saturating_add(past_game_time.max(0) as i64);
5219 if self.wipe_done() {
5220 self.wipe = None;
5221 }
5222 if self.change_display_mode_proc_cnt > 0 {
5223 self.change_display_mode_proc_cnt -= 1;
5224 }
5225 self.mov.tick(past_real_time);
5226 self.fog_global.update_time(past_game_time, past_real_time);
5227 self.fog_global.frame();
5228
5229 if !self.script.counter_time_stop_flag {
5230 let mut counter_ids: Vec<u32> = self.counter_lists.keys().copied().collect();
5231 counter_ids.sort_unstable();
5232 for counter_id in counter_ids {
5233 let Some(counters) = self.counter_lists.get_mut(&counter_id) else {
5234 continue;
5235 };
5236 for counter in counters {
5237 counter.update_time(past_game_time, past_real_time);
5238 }
5239 }
5240 }
5241
5242 if !self.script.frame_action_time_stop_flag {
5243 let mut frame_action_ids: Vec<u32> = self.frame_actions.keys().copied().collect();
5244 frame_action_ids.sort_unstable();
5245 for frame_action_id in frame_action_ids {
5246 let Some(fa) = self.frame_actions.get_mut(&frame_action_id) else {
5247 continue;
5248 };
5249 fa.counter.update_time(past_game_time, past_real_time);
5250 }
5251 let mut frame_action_list_ids: Vec<u32> =
5252 self.frame_action_lists.keys().copied().collect();
5253 frame_action_list_ids.sort_unstable();
5254 for frame_action_list_id in frame_action_list_ids {
5255 let Some(list) = self.frame_action_lists.get_mut(&frame_action_list_id) else {
5256 continue;
5257 };
5258 for fa in list {
5259 fa.counter.update_time(past_game_time, past_real_time);
5260 }
5261 }
5262 }
5263
5264 let mut mask_list_ids: Vec<u32> = self.mask_lists.keys().copied().collect();
5265 mask_list_ids.sort_unstable();
5266 for mask_list_id in mask_list_ids {
5267 let Some(ml) = self.mask_lists.get_mut(&mask_list_id) else {
5268 continue;
5269 };
5270 ml.tick_frame(past_game_time.max(0));
5271 }
5272
5273 let mut screen_form_ids: Vec<u32> = self.screen_forms.keys().copied().collect();
5274 screen_form_ids.sort_unstable();
5275 for screen_form_id in screen_form_ids {
5276 let Some(sc) = self.screen_forms.get_mut(&screen_form_id) else {
5277 continue;
5278 };
5279 sc.tick(past_game_time.max(0));
5280 }
5281
5282 let mut int_event_root_ids: Vec<u32> = self.int_event_roots.keys().copied().collect();
5283 int_event_root_ids.sort_unstable();
5284 for int_event_root_id in int_event_root_ids {
5285 let Some(ev) = self.int_event_roots.get_mut(&int_event_root_id) else {
5286 continue;
5287 };
5288 ev.update_time(past_game_time, past_real_time);
5289 ev.frame();
5290 }
5291 let mut int_event_list_ids: Vec<u32> = self.int_event_lists.keys().copied().collect();
5292 int_event_list_ids.sort_unstable();
5293 for int_event_list_id in int_event_list_ids {
5294 let Some(events) = self.int_event_lists.get_mut(&int_event_list_id) else {
5295 continue;
5296 };
5297 for ev in events {
5298 ev.update_time(past_game_time, past_real_time);
5299 ev.frame();
5300 }
5301 }
5302
5303 let mut stage_form_ids: Vec<u32> = self.stage_forms.keys().copied().collect();
5304 stage_form_ids.sort_unstable();
5305 for stage_form_id in stage_form_ids {
5306 let Some(st) = self.stage_forms.get_mut(&stage_form_id) else {
5307 continue;
5308 };
5309 let mut object_stage_ids: Vec<i64> = st.object_lists.keys().copied().collect();
5310 object_stage_ids.sort_unstable();
5311 for object_stage_id in object_stage_ids {
5312 let embedded_prefix = format!("{object_stage_id}:");
5313 let embedded_slots: HashSet<usize> = st
5314 .embedded_object_slots
5315 .iter()
5316 .filter_map(|(key, &slot)| key.starts_with(&embedded_prefix).then_some(slot))
5317 .collect();
5318 let Some(objs) = st.object_lists.get_mut(&object_stage_id) else {
5319 continue;
5320 };
5321 for (obj_idx, obj) in objs.iter_mut().enumerate() {
5322 if embedded_slots.contains(&obj_idx) {
5323 continue;
5324 }
5325 obj.tick(past_game_time, past_real_time);
5326 }
5327 }
5328
5329 let mut mwnd_stage_ids: Vec<i64> = st.mwnd_lists.keys().copied().collect();
5330 mwnd_stage_ids.sort_unstable();
5331 for mwnd_stage_id in mwnd_stage_ids {
5332 let Some(mwnds) = st.mwnd_lists.get_mut(&mwnd_stage_id) else {
5333 continue;
5334 };
5335 for mwnd in mwnds {
5336 for obj in &mut mwnd.button_list {
5337 obj.tick(past_game_time, past_real_time);
5338 }
5339 for obj in &mut mwnd.face_list {
5340 obj.tick(past_game_time, past_real_time);
5341 }
5342 for obj in &mut mwnd.object_list {
5343 obj.tick(past_game_time, past_real_time);
5344 }
5345 }
5346 }
5347 let mut world_stage_ids: Vec<i64> = st.world_lists.keys().copied().collect();
5348 world_stage_ids.sort_unstable();
5349 for world_stage_id in world_stage_ids {
5350 let Some(worlds) = st.world_lists.get_mut(&world_stage_id) else {
5351 continue;
5352 };
5353 for w in worlds {
5354 w.update_time(past_game_time, past_real_time);
5355 w.frame();
5356 }
5357 }
5358
5359 let mut effect_stage_ids: Vec<i64> = st.effect_lists.keys().copied().collect();
5360 effect_stage_ids.sort_unstable();
5361 for effect_stage_id in effect_stage_ids {
5362 let Some(effects) = st.effect_lists.get_mut(&effect_stage_id) else {
5363 continue;
5364 };
5365 for effect in effects {
5366 effect.tick(past_game_time.max(0));
5367 }
5368 }
5369
5370 let mut quake_stage_ids: Vec<i64> = st.quake_lists.keys().copied().collect();
5371 quake_stage_ids.sort_unstable();
5372 for quake_stage_id in quake_stage_ids {
5373 let Some(quakes) = st.quake_lists.get_mut(&quake_stage_id) else {
5374 continue;
5375 };
5376 for quake in quakes {
5377 let _ = quake.is_active();
5378 }
5379 }
5380 }
5381 }
5382}