Skip to main content

siglus_scene_vm/runtime/forms/
msgbk.rs

1//! Global MSGBK form, aligned to `cmd_mwnd.cpp::tnm_command_proc_msgbk()`.
2
3use anyhow::Result;
4
5use crate::runtime::globals::MsgBackState;
6use crate::runtime::{CommandContext, Value};
7
8use super::prop_access;
9
10struct Call<'a> {
11    op: i32,
12    params: &'a [Value],
13}
14
15fn msgbk_state_mut(ctx: &mut CommandContext, form_id: u32) -> &mut MsgBackState {
16    ctx.globals.msgbk_forms.entry(form_id).or_default()
17}
18
19fn parse_call<'a>(ctx: &CommandContext, args: &'a [Value]) -> Option<(u32, Call<'a>)> {
20    let form_id = ctx.ids.form_global_msgbk;
21    if form_id == 0 {
22        return None;
23    }
24    let (chain_pos, chain) = prop_access::parse_element_chain_ctx(ctx, form_id, args)?;
25    if chain.len() < 2 {
26        return None;
27    }
28    Some((
29        form_id,
30        Call {
31            op: chain[1],
32            params: prop_access::script_args(args, chain_pos),
33        },
34    ))
35}
36
37fn arg_i64(args: &[Value], idx: usize) -> Option<i64> {
38    args.get(idx).and_then(Value::as_i64)
39}
40
41fn arg_str<'a>(args: &'a [Value], idx: usize) -> Option<&'a str> {
42    args.get(idx).and_then(Value::as_str)
43}
44
45fn named_i64(args: &[Value], id: i32) -> Option<i64> {
46    args.iter()
47        .find(|v| v.named_id() == Some(id))
48        .and_then(Value::as_i64)
49}
50
51fn named_str<'a>(args: &'a [Value], id: i32) -> Option<&'a str> {
52    args.iter()
53        .find(|v| v.named_id() == Some(id))
54        .and_then(Value::as_str)
55}
56
57fn resolve_debug_open_scene(ctx: &CommandContext, params: &[Value]) -> Result<(i64, i64)> {
58    let scene_name = named_str(params, 0).unwrap_or("");
59    let mut scene_no = if !scene_name.is_empty() {
60        ctx.lookup_scene_no(scene_name)?
61    } else {
62        ctx.current_scene_no.unwrap_or(-1)
63    };
64    let mut line_no = named_i64(params, 1).unwrap_or(0);
65    if line_no <= 0 {
66        line_no = ctx.current_line_no;
67    }
68    if scene_no < 0 {
69        scene_no = -1;
70    }
71    Ok((scene_no, line_no))
72}
73
74pub fn dispatch(ctx: &mut CommandContext, args: &[Value]) -> Result<bool> {
75    let Some((form_id, call)) = parse_call(ctx, args) else {
76        return Ok(false);
77    };
78
79    match call.op {
80        op if op == crate::runtime::constants::MSGBK_INSERT_IMG => {
81            let file = arg_str(call.params, 0).unwrap_or("");
82            let x = arg_i64(call.params, 1).unwrap_or(0) as i32;
83            let y = arg_i64(call.params, 2).unwrap_or(0) as i32;
84            if !file.is_empty() {
85                msgbk_state_mut(ctx, form_id).add_pct(file, x, y);
86            }
87            ctx.push(Value::Int(0));
88            Ok(true)
89        }
90        op if op == crate::runtime::constants::MSGBK_INSERT_MSG => {
91            let msg = arg_str(call.params, 0).unwrap_or("");
92            let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
93            if scene_no >= 0 {
94                let st = msgbk_state_mut(ctx, form_id);
95                st.next();
96                st.add_msg(msg, msg, scene_no, line_no);
97            }
98            ctx.push(Value::Int(0));
99            Ok(true)
100        }
101        op if op == crate::runtime::constants::MSGBK_ADD_KOE => {
102            let koe_no = arg_i64(call.params, 0).unwrap_or(0);
103            let chara_no = arg_i64(call.params, 1).unwrap_or(-1);
104            let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
105            if scene_no >= 0 {
106                msgbk_state_mut(ctx, form_id).add_koe(koe_no, chara_no, scene_no, line_no);
107            }
108            ctx.push(Value::Int(0));
109            Ok(true)
110        }
111        op if op == crate::runtime::constants::MSGBK_ADD_NAMAE => {
112            let name = arg_str(call.params, 0).unwrap_or("");
113            let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
114            if scene_no >= 0 {
115                msgbk_state_mut(ctx, form_id).add_name(name, name, scene_no, line_no);
116            }
117            ctx.push(Value::Int(0));
118            Ok(true)
119        }
120        op if op == crate::runtime::constants::MSGBK_ADD_MSG => {
121            let msg = arg_str(call.params, 0).unwrap_or("");
122            let (scene_no, line_no) = resolve_debug_open_scene(ctx, call.params)?;
123            if scene_no >= 0 {
124                msgbk_state_mut(ctx, form_id).add_msg(msg, msg, scene_no, line_no);
125            }
126            ctx.push(Value::Int(0));
127            Ok(true)
128        }
129        op if op == crate::runtime::constants::MSGBK_GO_NEXT_MSG => {
130            msgbk_state_mut(ctx, form_id).next();
131            ctx.push(Value::Int(0));
132            Ok(true)
133        }
134        _ => Ok(false),
135    }
136}