1use anyhow::Result;
8
9use super::prop_access;
10use crate::runtime::forms::codes::int_event_op;
11use crate::runtime::globals::{ScreenEffectState, ScreenFormState, ScreenQuakeState};
12use crate::runtime::{CommandContext, Value};
13
14const EFFECTLIST_RESIZE_OP: i32 = 1;
15const EFFECTLIST_GET_SIZE_OP: i32 = 2;
16
17const QUAKE_START_OP: i32 = 0;
18const QUAKE_START_WAIT_OP: i32 = 1;
19const QUAKE_START_WAIT_KEY_OP: i32 = 2;
20const QUAKE_START_NOWAIT_OP: i32 = 3;
21const QUAKE_START_ALL_OP: i32 = 4;
22const QUAKE_START_ALL_WAIT_OP: i32 = 5;
23const QUAKE_START_ALL_WAIT_KEY_OP: i32 = 6;
24const QUAKE_START_ALL_NOWAIT_OP: i32 = 7;
25const QUAKE_END_OP: i32 = 8;
26const QUAKE_CHECK_OP: i32 = 9;
27const QUAKE_WAIT_OP: i32 = 10;
28const QUAKE_WAIT_KEY_OP: i32 = 11;
29
30fn as_i64(v: &Value) -> Option<i64> {
31 match v {
32 Value::Int(n) => Some(*n),
33 Value::NamedArg { value, .. } => value.as_i64(),
34 _ => None,
35 }
36}
37
38fn default_for_ret_form(ret_form: i64) -> Value {
39 if prop_access::ret_form_is_string(ret_form) {
40 Value::Str(String::new())
41 } else {
42 Value::Int(0)
43 }
44}
45
46fn anim_skip_trace_enabled() -> bool {
47 env_is_set!("SG_DEBUG")
48}
49
50fn screen_event_state(ev: &crate::runtime::int_event::IntEvent) -> String {
51 format!(
52 "value={} cur={} start={} end={} cur_time={} end_time={} delay={} loop_type={} speed={} real={} active={}",
53 ev.value,
54 ev.cur_value,
55 ev.start_value,
56 ev.end_value,
57 ev.cur_time,
58 ev.end_time,
59 ev.delay_time,
60 ev.loop_type,
61 ev.speed_type,
62 ev.real_flag,
63 ev.check_event()
64 )
65}
66
67fn effect_prop_ref_mut<'a>(
68 ids: &crate::runtime::constants::RuntimeConstants,
69 effect: &'a mut ScreenEffectState,
70 op: i32,
71) -> Option<&'a mut i32> {
72 match op {
73 s if s == ids.effect_wipe_copy => Some(&mut effect.wipe_copy),
74 s if s == ids.effect_wipe_erase => Some(&mut effect.wipe_erase),
75 s if s == ids.effect_begin_order => Some(&mut effect.begin_order),
76 s if s == ids.effect_begin_layer => Some(&mut effect.begin_layer),
77 s if s == ids.effect_end_order => Some(&mut effect.end_order),
78 s if s == ids.effect_end_layer => Some(&mut effect.end_layer),
79 _ => None,
80 }
81}
82
83fn effect_prop_value(
84 ids: &crate::runtime::constants::RuntimeConstants,
85 effect: &ScreenEffectState,
86 op: i32,
87) -> Option<i64> {
88 match op {
89 s if s == ids.effect_wipe_copy => Some(effect.wipe_copy as i64),
90 s if s == ids.effect_wipe_erase => Some(effect.wipe_erase as i64),
91 s if s == ids.effect_begin_order => Some(effect.begin_order as i64),
92 s if s == ids.effect_begin_layer => Some(effect.begin_layer as i64),
93 s if s == ids.effect_end_order => Some(effect.end_order as i64),
94 s if s == ids.effect_end_layer => Some(effect.end_layer as i64),
95 _ => None,
96 }
97}
98
99fn effect_event_mut<'a>(
100 ids: &crate::runtime::constants::RuntimeConstants,
101 effect: &'a mut ScreenEffectState,
102 op: i32,
103) -> Option<&'a mut crate::runtime::int_event::IntEvent> {
104 match op {
105 s if s == ids.effect_x || s == ids.effect_x_eve => Some(&mut effect.x),
106 s if s == ids.effect_y || s == ids.effect_y_eve => Some(&mut effect.y),
107 s if s == ids.effect_z || s == ids.effect_z_eve => Some(&mut effect.z),
108 s if s == ids.effect_mono || s == ids.effect_mono_eve => Some(&mut effect.mono),
109 s if s == ids.effect_reverse || s == ids.effect_reverse_eve => Some(&mut effect.reverse),
110 s if s == ids.effect_bright || s == ids.effect_bright_eve => Some(&mut effect.bright),
111 s if s == ids.effect_dark || s == ids.effect_dark_eve => Some(&mut effect.dark),
112 s if s == ids.effect_color_r || s == ids.effect_color_r_eve => Some(&mut effect.color_r),
113 s if s == ids.effect_color_g || s == ids.effect_color_g_eve => Some(&mut effect.color_g),
114 s if s == ids.effect_color_b || s == ids.effect_color_b_eve => Some(&mut effect.color_b),
115 s if s == ids.effect_color_rate || s == ids.effect_color_rate_eve => {
116 Some(&mut effect.color_rate)
117 }
118 s if s == ids.effect_color_add_r || s == ids.effect_color_add_r_eve => {
119 Some(&mut effect.color_add_r)
120 }
121 s if s == ids.effect_color_add_g || s == ids.effect_color_add_g_eve => {
122 Some(&mut effect.color_add_g)
123 }
124 s if s == ids.effect_color_add_b || s == ids.effect_color_add_b_eve => {
125 Some(&mut effect.color_add_b)
126 }
127 _ => None,
128 }
129}
130
131fn run_int_event_command(
132 ctx: &mut CommandContext,
133 ev: &mut crate::runtime::int_event::IntEvent,
134 form_id: u32,
135 effect_index: usize,
136 effect_op: i32,
137 subop: i32,
138 params: &[Value],
139 ret_form: i64,
140) {
141 match subop {
142 int_event_op::SET | int_event_op::SET_REAL => {
143 let value = params.first().and_then(as_i64).unwrap_or(0) as i32;
144 let total_time = params.get(1).and_then(as_i64).unwrap_or(0) as i32;
145 let delay_time = params.get(2).and_then(as_i64).unwrap_or(0) as i32;
146 let speed_type = params.get(3).and_then(as_i64).unwrap_or(0) as i32;
147 let real_flag = if subop == int_event_op::SET_REAL {
148 1
149 } else {
150 0
151 };
152 ev.set_event(value, total_time, delay_time, speed_type, real_flag);
153 if anim_skip_trace_enabled() {
154 eprintln!(
155 "[SG_DEBUG][ANIM_SKIP_TRACE][SCREEN] INTEVENT.SET subop={} value={} total_time={} delay={} speed={} real={} state=[{}]",
156 subop,
157 value,
158 total_time,
159 delay_time,
160 speed_type,
161 real_flag,
162 screen_event_state(ev)
163 );
164 }
165 ctx.stack.push(default_for_ret_form(ret_form));
166 }
167 int_event_op::LOOP | int_event_op::LOOP_REAL => {
168 let start_value = params.first().and_then(as_i64).unwrap_or(0) as i32;
169 let end_value = params.get(1).and_then(as_i64).unwrap_or(0) as i32;
170 let loop_time = params.get(2).and_then(as_i64).unwrap_or(0) as i32;
171 let delay_time = params.get(3).and_then(as_i64).unwrap_or(0) as i32;
172 let speed_type = params.get(4).and_then(as_i64).unwrap_or(0) as i32;
173 let real_flag = if subop == int_event_op::LOOP_REAL {
174 1
175 } else {
176 0
177 };
178 ev.loop_event(
179 start_value,
180 end_value,
181 loop_time,
182 delay_time,
183 speed_type,
184 real_flag,
185 );
186 if anim_skip_trace_enabled() {
187 eprintln!(
188 "[SG_DEBUG][ANIM_SKIP_TRACE][SCREEN] INTEVENT.LOOP subop={} start={} end={} loop_time={} delay={} speed={} real={} state=[{}]",
189 subop,
190 start_value,
191 end_value,
192 loop_time,
193 delay_time,
194 speed_type,
195 real_flag,
196 screen_event_state(ev)
197 );
198 }
199 ctx.stack.push(default_for_ret_form(ret_form));
200 }
201 int_event_op::TURN | int_event_op::TURN_REAL => {
202 let start_value = params.first().and_then(as_i64).unwrap_or(0) as i32;
203 let end_value = params.get(1).and_then(as_i64).unwrap_or(0) as i32;
204 let loop_time = params.get(2).and_then(as_i64).unwrap_or(0) as i32;
205 let delay_time = params.get(3).and_then(as_i64).unwrap_or(0) as i32;
206 let speed_type = params.get(4).and_then(as_i64).unwrap_or(0) as i32;
207 let real_flag = if subop == int_event_op::TURN_REAL {
208 1
209 } else {
210 0
211 };
212 ev.turn_event(
213 start_value,
214 end_value,
215 loop_time,
216 delay_time,
217 speed_type,
218 real_flag,
219 );
220 if anim_skip_trace_enabled() {
221 eprintln!(
222 "[SG_DEBUG][ANIM_SKIP_TRACE][SCREEN] INTEVENT.TURN subop={} start={} end={} loop_time={} delay={} speed={} real={} state=[{}]",
223 subop,
224 start_value,
225 end_value,
226 loop_time,
227 delay_time,
228 speed_type,
229 real_flag,
230 screen_event_state(ev)
231 );
232 }
233 ctx.stack.push(default_for_ret_form(ret_form));
234 }
235 int_event_op::END => {
236 if anim_skip_trace_enabled() {
237 eprintln!(
238 "[SG_DEBUG][ANIM_SKIP_TRACE][SCREEN] INTEVENT.END before state=[{}]",
239 screen_event_state(ev)
240 );
241 }
242 ev.end_event();
243 if anim_skip_trace_enabled() {
244 eprintln!(
245 "[SG_DEBUG][ANIM_SKIP_TRACE][SCREEN] INTEVENT.END after state=[{}]",
246 screen_event_state(ev)
247 );
248 }
249 ctx.stack.push(default_for_ret_form(ret_form));
250 }
251 int_event_op::WAIT => {
252 ctx.wait
253 .wait_screen_effect(form_id, effect_index, effect_op, false, false)
254 }
255 int_event_op::WAIT_KEY => {
256 ctx.wait
257 .wait_screen_effect(form_id, effect_index, effect_op, true, true)
258 }
259 int_event_op::CHECK => ctx
260 .stack
261 .push(Value::Int(if ev.check_event() { 1 } else { 0 })),
262 _ => ctx.stack.push(default_for_ret_form(ret_form)),
263 }
264}
265
266fn screen_to_effect_prop(
267 ids: &crate::runtime::constants::RuntimeConstants,
268 selector: i32,
269) -> Option<i32> {
270 match selector {
271 s if ids.screen_x != 0 && s == ids.screen_x => Some(ids.effect_x),
272 s if ids.screen_y != 0 && s == ids.screen_y => Some(ids.effect_y),
273 s if ids.screen_z != 0 && s == ids.screen_z => Some(ids.effect_z),
274 s if ids.screen_mono != 0 && s == ids.screen_mono => Some(ids.effect_mono),
275 s if ids.screen_reverse != 0 && s == ids.screen_reverse => Some(ids.effect_reverse),
276 s if ids.screen_bright != 0 && s == ids.screen_bright => Some(ids.effect_bright),
277 s if ids.screen_dark != 0 && s == ids.screen_dark => Some(ids.effect_dark),
278 s if ids.screen_color_r != 0 && s == ids.screen_color_r => Some(ids.effect_color_r),
279 s if ids.screen_color_g != 0 && s == ids.screen_color_g => Some(ids.effect_color_g),
280 s if ids.screen_color_b != 0 && s == ids.screen_color_b => Some(ids.effect_color_b),
281 s if ids.screen_color_rate != 0 && s == ids.screen_color_rate => {
282 Some(ids.effect_color_rate)
283 }
284 s if ids.screen_color_add_r != 0 && s == ids.screen_color_add_r => {
285 Some(ids.effect_color_add_r)
286 }
287 s if ids.screen_color_add_g != 0 && s == ids.screen_color_add_g => {
288 Some(ids.effect_color_add_g)
289 }
290 s if ids.screen_color_add_b != 0 && s == ids.screen_color_add_b => {
291 Some(ids.effect_color_add_b)
292 }
293 _ => None,
294 }
295}
296
297fn screen_to_effect_event(
298 ids: &crate::runtime::constants::RuntimeConstants,
299 selector: i32,
300) -> Option<i32> {
301 match selector {
302 s if ids.screen_x_eve != 0 && s == ids.screen_x_eve => Some(ids.effect_x_eve),
303 s if ids.screen_y_eve != 0 && s == ids.screen_y_eve => Some(ids.effect_y_eve),
304 s if ids.screen_z_eve != 0 && s == ids.screen_z_eve => Some(ids.effect_z_eve),
305 s if ids.screen_mono_eve != 0 && s == ids.screen_mono_eve => Some(ids.effect_mono_eve),
306 s if ids.screen_reverse_eve != 0 && s == ids.screen_reverse_eve => {
307 Some(ids.effect_reverse_eve)
308 }
309 s if ids.screen_bright_eve != 0 && s == ids.screen_bright_eve => {
310 Some(ids.effect_bright_eve)
311 }
312 s if ids.screen_dark_eve != 0 && s == ids.screen_dark_eve => Some(ids.effect_dark_eve),
313 s if ids.screen_color_r_eve != 0 && s == ids.screen_color_r_eve => {
314 Some(ids.effect_color_r_eve)
315 }
316 s if ids.screen_color_g_eve != 0 && s == ids.screen_color_g_eve => {
317 Some(ids.effect_color_g_eve)
318 }
319 s if ids.screen_color_b_eve != 0 && s == ids.screen_color_b_eve => {
320 Some(ids.effect_color_b_eve)
321 }
322 s if ids.screen_color_rate_eve != 0 && s == ids.screen_color_rate_eve => {
323 Some(ids.effect_color_rate_eve)
324 }
325 s if ids.screen_color_add_r_eve != 0 && s == ids.screen_color_add_r_eve => {
326 Some(ids.effect_color_add_r_eve)
327 }
328 s if ids.screen_color_add_g_eve != 0 && s == ids.screen_color_add_g_eve => {
329 Some(ids.effect_color_add_g_eve)
330 }
331 s if ids.screen_color_add_b_eve != 0 && s == ids.screen_color_add_b_eve => {
332 Some(ids.effect_color_add_b_eve)
333 }
334 _ => None,
335 }
336}
337
338struct ScreenCall {
339 chain: Vec<i32>,
340 al_id: i32,
341 ret_form: i64,
342 rhs: Option<Value>,
343 script_args: Vec<Value>,
344}
345
346fn parse_screen_call(ctx: &CommandContext, args: &[Value]) -> Option<ScreenCall> {
347 let vm_call = ctx.vm_call.as_ref()?;
348 if vm_call.element.is_empty() {
349 return None;
350 }
351 let (al_id, ret_form) = prop_access::current_vm_meta(ctx);
352 let al_id = al_id.unwrap_or(-1) as i32;
353 let ret_form = ret_form.unwrap_or(0);
354 let rhs = if al_id == 1 {
355 args.first().cloned()
356 } else {
357 None
358 };
359 Some(ScreenCall {
360 chain: vm_call.element.clone(),
361 al_id,
362 ret_form,
363 rhs,
364 script_args: args.to_vec(),
365 })
366}
367
368fn last_list_arg(script_args: &[Value]) -> Option<&Vec<Value>> {
369 script_args.last().and_then(|v| match v.unwrap_named() {
370 Value::List(list) => Some(list),
371 _ => None,
372 })
373}
374
375fn quake_start_flags(op: i32) -> Option<(bool, bool, bool)> {
376 match op {
377 QUAKE_START_OP => Some((false, false, false)),
378 QUAKE_START_WAIT_OP => Some((false, true, false)),
379 QUAKE_START_WAIT_KEY_OP => Some((false, true, true)),
380 QUAKE_START_NOWAIT_OP => Some((false, false, false)),
381 QUAKE_START_ALL_OP => Some((true, false, false)),
382 QUAKE_START_ALL_WAIT_OP => Some((true, true, false)),
383 QUAKE_START_ALL_WAIT_KEY_OP => Some((true, true, true)),
384 QUAKE_START_ALL_NOWAIT_OP => Some((true, false, false)),
385 _ => None,
386 }
387}
388
389fn parse_quake_command(
390 item: &mut ScreenQuakeState,
391 form_id: u32,
392 index: usize,
393 op: i32,
394 script_args: &[Value],
395 ctx: &mut CommandContext,
396) -> bool {
397 if let Some((all_range, wait_flag, key_flag)) = quake_start_flags(op) {
398 let quake_type = script_args.first().and_then(as_i64).unwrap_or(0) as i32;
399 let time = script_args.get(1).and_then(as_i64).unwrap_or(1000);
400 let cnt = script_args.get(2).and_then(as_i64).unwrap_or(0) as i32;
401 let end_cnt = script_args.get(3).and_then(as_i64).unwrap_or(0) as i32;
402 item.begin_order = if all_range {
403 script_args
404 .get(4)
405 .and_then(as_i64)
406 .unwrap_or(i32::MIN as i64) as i32
407 } else {
408 script_args.get(4).and_then(as_i64).unwrap_or(0) as i32
409 };
410 item.end_order = if all_range {
411 script_args
412 .get(5)
413 .and_then(as_i64)
414 .unwrap_or(i32::MAX as i64) as i32
415 } else {
416 script_args.get(5).and_then(as_i64).unwrap_or(0) as i32
417 };
418
419 let opt = last_list_arg(script_args);
420 item.power = opt
421 .and_then(|list| list.first())
422 .and_then(as_i64)
423 .unwrap_or(0) as i32;
424 if quake_type == 2 {
425 item.vec = 0;
426 item.center_x = opt
427 .and_then(|list| list.get(1))
428 .and_then(as_i64)
429 .unwrap_or(0) as i32;
430 item.center_y = opt
431 .and_then(|list| list.get(2))
432 .and_then(as_i64)
433 .unwrap_or(0) as i32;
434 } else {
435 item.vec = opt
436 .and_then(|list| list.get(1))
437 .and_then(as_i64)
438 .unwrap_or(0) as i32;
439 item.center_x = 0;
440 item.center_y = 0;
441 }
442 item.start_kind(quake_type, time, cnt, end_cnt);
443 if wait_flag {
444 ctx.wait.wait_quake(
445 crate::runtime::wait::QuakeWait::Screen { form_id, index },
446 key_flag,
447 );
448 }
449 ctx.stack.push(Value::Int(0));
450 return true;
451 }
452
453 match op {
454 QUAKE_END_OP => {
455 item.end_ms(script_args.first().and_then(as_i64).unwrap_or(0));
456 ctx.stack.push(Value::Int(0));
457 true
458 }
459 QUAKE_WAIT_OP => {
460 ctx.wait.wait_quake(
461 crate::runtime::wait::QuakeWait::Screen { form_id, index },
462 false,
463 );
464 ctx.stack.push(Value::Int(0));
465 true
466 }
467 QUAKE_WAIT_KEY_OP => {
468 ctx.wait.wait_quake(
469 crate::runtime::wait::QuakeWait::Screen { form_id, index },
470 true,
471 );
472 ctx.stack.push(Value::Int(0));
473 true
474 }
475 QUAKE_CHECK_OP => {
476 ctx.stack.push(Value::Int(item.check_value() as i64));
477 true
478 }
479 _ => false,
480 }
481}
482
483fn get_or_set_effect_scalar(
484 ctx: &mut CommandContext,
485 effect: &mut ScreenEffectState,
486 ids: &crate::runtime::constants::RuntimeConstants,
487 op: i32,
488 al_id: i32,
489 rhs: Option<&Value>,
490 ret_form: i64,
491) -> bool {
492 if let Some(ev) = effect_event_mut(ids, effect, op) {
493 match al_id {
494 0 => {
495 ctx.stack.push(Value::Int(ev.get_total_value() as i64));
496 true
497 }
498 1 => {
499 let value = crate::runtime::globals::normalize_screen_effect_scalar(
500 ids,
501 op,
502 rhs.and_then(as_i64).unwrap_or(0) as i32,
503 );
504 ev.set_value(value);
505 ev.frame();
506 ctx.stack.push(default_for_ret_form(ret_form));
507 true
508 }
509 _ => false,
510 }
511 } else if let Some(slot) = effect_prop_ref_mut(ids, effect, op) {
512 match al_id {
513 0 => {
514 ctx.stack.push(Value::Int(*slot as i64));
515 true
516 }
517 1 => {
518 let value = rhs.and_then(as_i64).unwrap_or(0) as i32;
519 *slot = if op == ids.effect_wipe_copy || op == ids.effect_wipe_erase {
520 if value != 0 { 1 } else { 0 }
521 } else {
522 value
523 };
524 ctx.stack.push(default_for_ret_form(ret_form));
525 true
526 }
527 _ => false,
528 }
529 } else if let Some(value) = effect_prop_value(ids, effect, op) {
530 if al_id == 0 {
531 ctx.stack.push(Value::Int(value));
532 true
533 } else {
534 false
535 }
536 } else {
537 false
538 }
539}
540
541pub fn dispatch(ctx: &mut CommandContext, args: &[Value]) -> Result<bool> {
542 let Some(call) = parse_screen_call(ctx, args) else {
543 return Ok(false);
544 };
545 let chain = call.chain;
546 let form_id = chain[0] as u32;
547 let mut st = ctx
548 .globals
549 .screen_forms
550 .remove(&form_id)
551 .unwrap_or_default();
552 let result = (|| {
553 if chain.len() == 1 {
554 if call.ret_form != 0 {
555 ctx.stack.push(default_for_ret_form(call.ret_form));
556 }
557 return Ok(true);
558 }
559
560 let selector = chain[1];
561 let ids = ctx.ids.clone();
562
563 if selector == ids.screen_sel_effect {
564 if chain.len() == 3 {
565 match chain[2] {
566 EFFECTLIST_RESIZE_OP => {
567 st.ensure_effect_len(
568 args.first().and_then(as_i64).unwrap_or(0).max(0) as usize
569 );
570 ctx.stack.push(Value::Int(0));
571 return Ok(true);
572 }
573 EFFECTLIST_GET_SIZE_OP => {
574 ctx.stack.push(Value::Int(st.effect_list.len() as i64));
575 return Ok(true);
576 }
577 _ => return Ok(false),
578 }
579 }
580 if chain.len() < 4 || chain[2] != ids.elm_array {
581 return Ok(false);
582 }
583 let idx = chain[3].max(0) as usize;
584 st.ensure_effect_len(idx + 1);
585 let effect = &mut st.effect_list[idx];
586 if chain.len() == 4 {
587 if call.ret_form != 0 {
588 ctx.stack.push(default_for_ret_form(call.ret_form));
589 }
590 return Ok(true);
591 }
592 let op = chain[4];
593 if op == ids.effect_init && call.script_args.is_empty() && call.ret_form == 0 {
594 effect.reinit();
595 ctx.stack.push(Value::Int(0));
596 return Ok(true);
597 }
598 if chain.len() >= 6 {
599 if let Some(ev) = effect_event_mut(&ids, effect, op) {
600 run_int_event_command(
601 ctx,
602 ev,
603 form_id,
604 idx,
605 op,
606 chain[5],
607 &call.script_args,
608 call.ret_form,
609 );
610 return Ok(true);
611 }
612 return Ok(false);
613 }
614 return Ok(get_or_set_effect_scalar(
615 ctx,
616 effect,
617 &ids,
618 op,
619 call.al_id,
620 call.rhs.as_ref(),
621 call.ret_form,
622 ));
623 }
624
625 if selector == ids.screen_sel_quake {
626 if chain.len() < 4 || chain[2] != ids.elm_array {
627 return Ok(false);
628 }
629 let idx = chain[3].max(0) as usize;
630 st.ensure_quake_len(idx + 1);
631 let quake = &mut st.quake_list[idx];
632 if chain.len() == 4 {
633 if call.ret_form != 0 {
634 ctx.stack.push(default_for_ret_form(call.ret_form));
635 }
636 return Ok(true);
637 }
638 return Ok(parse_quake_command(
639 quake,
640 form_id,
641 idx,
642 chain[4],
643 &call.script_args,
644 ctx,
645 ));
646 }
647
648 if selector == ids.screen_sel_shake {
649 if !call.script_args.is_empty() {
650 let shake_no = call.script_args[0].as_i64().unwrap_or(0);
651 let _ = st.shake.start(shake_no, ctx.tables.shake_templates.len());
652 ctx.stack.push(Value::Int(0));
653 return Ok(true);
654 }
655 return Ok(false);
656 }
657
658 if let Some(effect_op) = screen_to_effect_prop(&ids, selector) {
659 st.ensure_effect_len(1);
660 let effect = &mut st.effect_list[0];
661 return Ok(get_or_set_effect_scalar(
662 ctx,
663 effect,
664 &ids,
665 effect_op,
666 call.al_id,
667 call.rhs.as_ref(),
668 call.ret_form,
669 ));
670 }
671
672 if let Some(effect_event_op) = screen_to_effect_event(&ids, selector) {
673 if chain.len() != 3 {
674 return Ok(false);
675 }
676 st.ensure_effect_len(1);
677 let effect = &mut st.effect_list[0];
678 if let Some(ev) = effect_event_mut(&ids, effect, effect_event_op) {
679 run_int_event_command(
680 ctx,
681 ev,
682 form_id,
683 0,
684 effect_event_op,
685 chain[2],
686 &call.script_args,
687 call.ret_form,
688 );
689 return Ok(true);
690 }
691 return Ok(false);
692 }
693
694 Ok(false)
695 })();
696 ctx.globals.screen_forms.insert(form_id, st);
697 result
698}