diff --git a/main_game/assets/maps/downtown.ron b/main_game/assets/maps/downtown.ron index 39dce92b..91b7d462 100644 --- a/main_game/assets/maps/downtown.ron +++ b/main_game/assets/maps/downtown.ron @@ -1,6 +1,6 @@ ( zones: ( - inner: {Zone(Building1Entrance): (zone_group: (12), zone_size: 33, zone_successors: []), Zone(ClinicEntrance): (zone_group: (13), zone_size: 6, zone_successors: []), Zone(ClinicWardEntrance): (zone_group: (14), zone_size: 6, zone_successors: []), Zone(CompoundEntrance): (zone_group: (15), zone_size: 405, zone_successors: []), Zone(MallEntrance): (zone_group: (25), zone_size: 165, zone_successors: []), Zone(PlantShopEntrance): (zone_group: (27), zone_size: 44, zone_successors: []), Zone(SewersEntrance): (zone_group: (30), zone_size: 60, zone_successors: []), Zone(TwinpeaksApartmentEntrance): (zone_group: (32), zone_size: 44, zone_successors: [])}, + inner: {Zone(Building1Entrance): (zone_group: (11), zone_size: 33, zone_successors: []), Zone(ClinicEntrance): (zone_group: (12), zone_size: 6, zone_successors: []), Zone(ClinicWardEntrance): (zone_group: (13), zone_size: 6, zone_successors: []), Zone(CompoundEntrance): (zone_group: (14), zone_size: 405, zone_successors: []), Zone(MallEntrance): (zone_group: (24), zone_size: 165, zone_successors: []), Zone(PlantShopEntrance): (zone_group: (26), zone_size: 44, zone_successors: []), Zone(SewersEntrance): (zone_group: (29), zone_size: 60, zone_successors: []), Zone(TwinpeaksApartmentEntrance): (zone_group: (31), zone_size: 44, zone_successors: [])}, ), squares: { (x: -263, y: -291): [Wall], diff --git a/main_game/assets/maps/mall.ron b/main_game/assets/maps/mall.ron index 28e472ff..5d24a918 100644 --- a/main_game/assets/maps/mall.ron +++ b/main_game/assets/maps/mall.ron @@ -1,6 +1,6 @@ ( zones: ( - inner: {Zone(Exit): (zone_group: (19), zone_size: 153, zone_successors: [])}, + inner: {Zone(Exit): (zone_group: (18), zone_size: 153, zone_successors: [])}, ), squares: { (x: -43, y: -19): [Empty, Trail], diff --git a/main_game_lib/src/lib.rs b/main_game_lib/src/lib.rs index e498a182..e145571d 100644 --- a/main_game_lib/src/lib.rs +++ b/main_game_lib/src/lib.rs @@ -18,7 +18,6 @@ pub mod vec2_ext; use bevy::{app::AppExit, prelude::*}; use bevy_pixel_camera::PixelCameraPlugin; pub use common_ext; -use prelude::rscn::TscnInBevy; use crate::prelude::*; @@ -142,9 +141,3 @@ fn begin_loading_static_assets_on_startup( fn exit(mut exit: EventWriter) { exit.send(AppExit::Success); } - -impl TscnInBevy for T { - fn tscn_asset_path() -> String { - format!("scenes/{}.tscn", T::name()) - } -} diff --git a/main_game_lib/src/state.rs b/main_game_lib/src/state.rs index 1a702321..fe2f114f 100644 --- a/main_game_lib/src/state.rs +++ b/main_game_lib/src/state.rs @@ -184,19 +184,19 @@ pub fn in_scene_leaving_state( /// Helper to check if the state is in _any_ top down scene loading state. pub fn in_top_down_loading_state( ) -> impl FnMut(Option>>) -> bool + Clone { - in_state(InTopDownScene(TopDownSceneState::Loading)) + in_state(InTopDownScene::loading()) } /// Helper to check if the state is in _any_ top down scene running state. pub fn in_top_down_running_state( ) -> impl FnMut(Option>>) -> bool + Clone { - in_state(InTopDownScene(TopDownSceneState::Running)) + in_state(InTopDownScene::running()) } /// Helper to check if the state is in _any_ top down scene leaving state. pub fn in_top_down_leaving_state( ) -> impl FnMut(Option>>) -> bool + Clone { - in_state(InTopDownScene(TopDownSceneState::Leaving)) + in_state(InTopDownScene::leaving()) } impl GlobalGameStateTransition { @@ -274,13 +274,13 @@ impl ComputedStates for InTopDownScene { fn compute(sources: Self::SourceStates) -> Option { match sources { Some(GlobalGameState::LoadingTopDownScene(_)) => { - Some(InTopDownScene(TopDownSceneState::Loading)) + Some(InTopDownScene::loading()) } Some(GlobalGameState::RunningTopDownScene(_)) => { - Some(InTopDownScene(TopDownSceneState::Running)) + Some(InTopDownScene::running()) } Some(GlobalGameState::LeavingTopDownScene(_)) => { - Some(InTopDownScene(TopDownSceneState::Leaving)) + Some(InTopDownScene::leaving()) } _ => None, } @@ -307,6 +307,21 @@ impl InTopDownScene { pub fn is_running(self) -> bool { matches!(self.0, TopDownSceneState::Running) } + + /// Constructs this state in running variant. + pub fn running() -> Self { + Self(TopDownSceneState::Running) + } + + /// Constructs this state in loading variant. + pub fn loading() -> Self { + Self(TopDownSceneState::Loading) + } + + /// Constructs this state in leaving variant. + pub fn leaving() -> Self { + Self(TopDownSceneState::Leaving) + } } impl WhichTopDownScene { diff --git a/main_game_lib/src/top_down.rs b/main_game_lib/src/top_down.rs index af8ffac5..06952dfa 100644 --- a/main_game_lib/src/top_down.rs +++ b/main_game_lib/src/top_down.rs @@ -28,10 +28,10 @@ use leafwing_input_manager::plugin::InputManagerSystem; use self::inspect_and_interact::ChangeHighlightedInspectLabelEvent; use crate::{ - cutscene::in_cutscene, in_scene_loading_state, in_scene_running_state, + cutscene::in_cutscene, in_top_down_loading_state, in_top_down_running_state, top_down::inspect_and_interact::ChangeHighlightedInspectLabelEventConsumer, - InTopDownScene, TopDownSceneState, WhichTopDownScene, + InTopDownScene, }; /// Does not add any systems, only registers generic-less types. @@ -48,26 +48,84 @@ impl bevy::app::Plugin for Plugin { // Assets // + app.init_asset_loader::>() + .init_asset::(); + app.add_systems( - OnEnter(InTopDownScene(TopDownSceneState::Loading)), + OnEnter(InTopDownScene::loading()), common_assets::store::insert_as_resource::, ) .add_systems( - OnExit(InTopDownScene(TopDownSceneState::Leaving)), + OnExit(InTopDownScene::leaving()), common_assets::store::remove_as_resource::, ); + // + // TileMap + // + + app.add_systems( + OnExit(InTopDownScene::running()), + layout::systems::remove_resources, + ) + .add_systems( + OnEnter(InTopDownScene::loading()), + layout::systems::start_loading_map, + ) + .add_systems( + First, + layout::systems::try_insert_map_as_resource + .run_if(in_top_down_loading_state()), + ) + .add_systems( + FixedUpdate, + actor::animate_movement.run_if(in_top_down_running_state()), + ) + .add_systems( + Update, + actor::emit_movement_events + .run_if(in_top_down_running_state()) + // so that we can emit this event on current frame + .after(actor::player::move_around), + ) + .add_systems( + Update, + actor::player::move_around + .run_if(in_top_down_running_state()) + .run_if(common_action::move_action_pressed()) + .run_if(not(crate::dialog::fe::portrait::in_portrait_dialog())), + ) + .add_systems( + Update, + ( + actor::npc::drive_behavior, + actor::npc::plan_path + .run_if(on_event::()), + actor::npc::run_path, + ) + .chain() + .run_if(in_top_down_running_state()), + ); + // // Camera // app.add_systems( - OnEnter(InTopDownScene(TopDownSceneState::Loading)), + OnEnter(InTopDownScene::loading()), common_visuals::camera::spawn, ) .add_systems( - OnExit(InTopDownScene(TopDownSceneState::Leaving)), + OnExit(InTopDownScene::leaving()), common_visuals::camera::despawn, + ) + .add_systems( + FixedUpdate, + cameras::track_player_with_main_camera + .after(actor::animate_movement) + .run_if(in_top_down_running_state()) + .run_if(not(in_cutscene())) + .run_if(not(crate::dialog::fe::portrait::in_portrait_dialog())), ); // @@ -122,6 +180,13 @@ impl bevy::app::Plugin for Plugin { )), ) .run_if(in_top_down_running_state()), + ) + .add_systems( + Update, + inspect_and_interact::match_interact_label_with_action_event + .run_if(in_top_down_running_state()) + .run_if(on_event::()) + .after(emit_movement_events), ); // @@ -129,11 +194,11 @@ impl bevy::app::Plugin for Plugin { // app.add_systems( - OnEnter(InTopDownScene(TopDownSceneState::Running)), + OnEnter(InTopDownScene::running()), (crate::hud::daybar::spawn, crate::hud::notification::spawn), ) .add_systems( - OnExit(InTopDownScene(TopDownSceneState::Running)), + OnExit(InTopDownScene::running()), ( crate::hud::daybar::despawn, crate::hud::notification::despawn, @@ -159,6 +224,7 @@ impl bevy::app::Plugin for Plugin { .register_type::() .register_type::() .register_type::() + .register_type::() .register_type::() .register_type::(); @@ -166,120 +232,34 @@ impl bevy::app::Plugin for Plugin { ResourceInspectorPlugin::::new() .run_if(resource_exists::), ); + + // You can press `Enter` to export the map. + // This will overwrite the RON file. + // We draw an overlay with tiles that you can edit with left and + // right mouse buttons. + app.add_systems( + OnEnter(InTopDownScene::running()), + layout::map_maker::spawn_debug_grid_root, + ) + .add_systems( + Update, + layout::map_maker::show_tiles_around_cursor + .run_if(in_top_down_running_state()), + ) + .add_systems( + Update, + ( + layout::map_maker::change_square_kind, + layout::map_maker::recolor_squares, + layout::map_maker::update_ui, + ) + .run_if(in_top_down_running_state()) + .chain(), + ) + .add_systems( + OnExit(InTopDownScene::leaving()), + layout::map_maker::destroy_map, + ); } } } - -/// Registers unique `T` types, asset loader for the map RON file, and systems -/// including from other packages: -/// - [`crate::top_down::actor::animate_movement`] -/// - [`crate::top_down::actor::emit_movement_events`] -/// - [`crate::top_down::actor::npc::drive_behavior`] -/// - [`crate::top_down::actor::npc::plan_path`] -/// - [`crate::top_down::actor::npc::run_path`] -/// - [`crate::top_down::actor::player::move_around`] -pub fn default_setup_for_scene(app: &mut App, scene: WhichTopDownScene) -where - T: TopDownScene, -{ - debug!("Adding map layout for {}", T::type_path()); - - app.init_asset_loader::>>() - .init_asset::>(); - - app.add_systems( - OnEnter(scene.loading()), - layout::systems::start_loading_map::, - ) - .add_systems( - First, - layout::systems::try_insert_map_as_resource:: - .run_if(in_scene_loading_state(scene)), - ) - .add_systems( - FixedUpdate, - actor::animate_movement::.run_if(in_scene_running_state(scene)), - ) - .add_systems( - Update, - actor::emit_movement_events:: - .run_if(in_scene_running_state(scene)) - // so that we can emit this event on current frame - .after(actor::player::move_around::), - ) - .add_systems( - Update, - actor::player::move_around:: - .run_if(in_scene_running_state(scene)) - .run_if(common_action::move_action_pressed()) - .run_if(not(crate::dialog::fe::portrait::in_portrait_dialog())), - ) - .add_systems( - Update, - ( - actor::npc::drive_behavior, - actor::npc::plan_path:: - .run_if(on_event::()), - actor::npc::run_path::, - ) - .chain() - .run_if(in_scene_running_state(scene)), - ) - .add_systems( - OnExit(scene.running()), - layout::systems::remove_resources::, - ); - - debug!("Adding interaction systems for {}", T::type_path()); - app.add_systems( - Update, - inspect_and_interact::match_interact_label_with_action_event - .run_if(in_scene_running_state(scene)) - .run_if(on_event::()) - .after(emit_movement_events::), - ); - - debug!("Adding camera"); - - app.add_systems( - FixedUpdate, - cameras::track_player_with_main_camera - .after(actor::animate_movement::) - .run_if(in_scene_running_state(scene)) - .run_if(not(in_cutscene())) - .run_if(not(crate::dialog::fe::portrait::in_portrait_dialog())), - ); -} - -/// You can press `Enter` to export the map. -/// This will overwrite the RON file. -/// We draw an overlay with tiles that you can edit with left and right mouse -/// buttons. -#[cfg(feature = "devtools")] -pub fn dev_default_setup_for_scene(app: &mut App, scene: WhichTopDownScene) -where - T: TopDownScene, -{ - app.register_type::>(); - - app.add_systems( - OnEnter(scene.running()), - layout::map_maker::spawn_debug_grid_root::, - ) - .add_systems( - Update, - layout::map_maker::show_tiles_around_cursor:: - .run_if(in_scene_running_state(scene)), - ) - .add_systems( - Update, - ( - layout::map_maker::change_square_kind::, - layout::map_maker::recolor_squares::, - layout::map_maker::update_ui::, - ) - .run_if(in_scene_running_state(scene)) - .chain(), - ) - .add_systems(OnExit(scene.leaving()), layout::map_maker::destroy_map::); -} diff --git a/main_game_lib/src/top_down/actor.rs b/main_game_lib/src/top_down/actor.rs index 8b68ec74..a8e237dd 100644 --- a/main_game_lib/src/top_down/actor.rs +++ b/main_game_lib/src/top_down/actor.rs @@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize}; use self::npc::BehaviorTree; use crate::top_down::{ - layout::{ysort, TileIndex, TopDownScene, LAYOUT}, + layout::{ysort, TileIndex, LAYOUT}, npc::NpcInTheMap, InspectLabelCategory, Player, TileKind, TileMap, }; @@ -181,16 +181,14 @@ pub enum ActorOrCharacter { } /// Sends events when an actor does something interesting. -/// This system is registered on call to -/// [`crate::top_down::default_setup_for_scene`]. /// /// If you listen to this event then condition your system to run on /// `run_if(on_event::)` and -/// `after(actor::emit_movement_events::)`. +/// `after(actor::emit_movement_events)`. /// /// We also emit a zone left event when an actor is despawned. -pub fn emit_movement_events( - tilemap: Res>, +pub fn emit_movement_events( + tilemap: Res, mut actor_zone_map: ResMut, mut event: EventWriter, mut removed: RemovedComponents, @@ -290,9 +288,9 @@ pub fn emit_movement_events( /// /// The z is based off y. /// See the [`ysort`] for more info. -pub fn animate_movement( +pub fn animate_movement( time: Res