use bevy_derive::Deref; use bevy_ecs::prelude::*; use tracing::debug; use trigger_fileconfig::main_city_script::*; define_actions! { ActionCreateNpcCfg, ActionChangeInteractCfg, ActionSetMainCityObjectState, ActionOpenUI, ActionSwitchSection } #[derive(Component)] pub struct EventGraph { pub interaction: String, // ENPCInteraction pub actions: Vec, } pub fn sync_event_info( interacting_units: Query<(&SceneUnitTag, &InteractContainer, &EventGraph), Changed>, mut listener: ResMut, ) { for (unit_tag, interact_container, event_graph) in interacting_units.iter() { listener.add(SyncEventInfoScNotify { owner_id: interact_container.cur_interaction() as u32, tag: **unit_tag as u32, owner_type: EEventGraphOwnerType::SceneUnit.into(), event_graph_uid: interact_container.cur_interaction() as u32, npc_interaction: event_graph.interaction.clone(), action_list: event_graph.actions.clone(), }); } } pub fn advance_through_event_graph( mut commands: Commands, mut run_events: EventReader, mut listener: ResMut, mut interacting_units: Query<(Entity, &mut InteractContainer, &EventGraph)>, ) { for event in run_events.read() { debug!("{event:?}"); if let Some((entity_id, mut interact_container, event_graph)) = interacting_units .iter_mut() .find(|(_, interact_container, _)| { interact_container.cur_interaction() == event.event_graph_uid as i32 }) { listener.add(UpdateEventGraphScNotify { tag: event.tag, event_graph_owner_uid: event.owner_id, owner_type: event.owner_type, npc_interaction: event_graph.interaction.clone(), is_event_success: true, }); interact_container.finish_interaction(); commands.entity(entity_id).remove::(); listener.emit_callback(GameStateCallback::ClientCmdProcessed { ack_request_id: event.request_id, response: Some(RunEventGraphScRsp { retcode: 0 }.into()), }); } } } macro_rules! define_actions { ($($name:ident),*) => { paste::paste!($( #[derive(Event, Deref)] pub struct [<$name Event>](&'static $name); )*); #[derive(Event, Deref)] pub struct GraphEvent(pub &'static ConfigEvent); pub struct MainCityScriptPlugin; impl bevy_app::Plugin for MainCityScriptPlugin { fn build(&self, app: &mut bevy_app::App) { $(paste::paste!(app.add_event::<[<$name Event>]>());)* app.add_event::(); app.add_systems(bevy_app::PreUpdate, tick_emit_event_actions); } } paste::paste! { pub fn tick_emit_event_actions(mut events: EventReader, $(mut [<$name:snake>]: EventWriter<[<$name Event>]>),*) { for event in events.read() { for action in event.actions.iter() { match action { $(ConfigEventAction::$name(data) => { [<$name:snake>].send([<$name Event>](data)); })* } } } }} }; } use define_actions; use trigger_logic::scene::EEventGraphOwnerType; use trigger_protocol::{ ActionInfo, RunEventGraphScRsp, SyncEventInfoScNotify, UpdateEventGraphScNotify, }; use trigger_sv::message::GameStateCallback; use crate::logic::{GameStateListener, message::RunEventGraphEvent}; use super::scene_unit::{InteractContainer, SceneUnitTag};