use bevy::{ ecs::query::QueryFilter, prelude::*, }; use bevy_rapier2d::prelude::*; use crate::{ meters, item::lockpick::lockpick_bundle, player::{ Player, player_bundle, }, }; use super::*; fn get_interactive_id( tested_id: Entity, interactive_query: Query<(), F>, parent_query: Query<&ChildOf, With>, ) -> Option { if interactive_query.get(tested_id).is_ok() { return Some(tested_id); } let Ok(parent_id) = parent_query.get(tested_id) else { return None; }; match interactive_query.get(parent_id.0) { Ok(_) => Some(parent_id.0), Err(_) => None, } } pub fn detect_interact_collisions( mut commands: Commands, mut collision_events: MessageReader, player_query: Query<(), With>, interactive_query1: Query<(), (With, Without)>, interactive_query2: Query<(), (With, With)>, parent_query: Query<&ChildOf, With>, ) { for collision_event in collision_events.read() { match collision_event { CollisionEvent::Started(first, second, _) => { let Some(interactive_id) = get_interactive_id(*first, interactive_query1, parent_query) else { continue; }; if player_query.get(*second).is_err() { continue; } commands.entity(interactive_id).insert(MayInteract); }, CollisionEvent::Stopped(first, second, _) => { let Some(interactive_id) = get_interactive_id(*first, interactive_query2, parent_query) else { continue; }; if player_query.get(*second).is_err() { continue; } commands.entity(interactive_id).remove::(); }, } } } pub fn lock_door( mut commands: Commands, query: Query<&ChildOf, Added>, ) { for parent in query { commands.entity(parent.0).insert(Locked); } } pub fn setup_world( mut commands: Commands, asset_server: Res, ) { let tiles = [ ( 0, ( 0, 0, 16, 1 )), // 1F floor ( 0, ( 0, 4, 16, 1 )), // 1F ceiling / 2F floor ( 0, ( 0, 8, 16, 1 )), // 2F ceiling ( 1, ( 0, 1, 1, 3 )), // 1F left wall ( 1, ( 0, 5, 1, 3 )), // 2F left wall ( 1, ( 15, 1, 1, 3 )), // 1F right wall ( 1, ( 15, 5, 1, 3 )), // 2F right wall ( 2, ( 4, 3, 1, 1 )), // 1F left door connector ( 2, ( 4, 7, 1, 1 )), // 2F left door connector ( 2, ( 11, 3, 1, 1 )), // 1F right door connector ( 2, ( 11, 7, 1, 1 )), // 2F right door connector ].into_iter().map(|(id, (x, y, w, h))| { (id, URect::from_corners(uvec2(x, y), uvec2(x + w - 1, y + h - 1))) }).collect::>(); commands.spawn(tilemap::tilemap_bundle(&asset_server, tiles)); commands.spawn(player_bundle(&asset_server, vec2(meters(1.5), meters(1.)))); commands.spawn(door::door_bundle(&asset_server, vec2(meters(4.5), meters(1.)), false)); commands.spawn(door::door_bundle(&asset_server, vec2(meters(4.5), meters(5.)), false)) .with_child(lock::padlock_bundle(&asset_server, false)); commands.spawn(door::door_bundle(&asset_server, vec2(meters(11.5), meters(1.)), true)) .with_child(lock::padlock_bundle(&asset_server, true)); commands.spawn(door::door_bundle(&asset_server, vec2(meters(11.5), meters(5.)), true)); commands.spawn(stairs::stairs_bundle( &asset_server, vec2(meters(8.), meters(1.)), Some(vec2(meters(2.), meters(4.))), None, )); commands.spawn(stairs::stairs_bundle( &asset_server, vec2(meters(8.), meters(5.)), None, Some(vec2(meters(-2.), meters(-4.))), )); commands.spawn(container::container_bundle( &asset_server, vec2(meters(2.), meters(1.)), uvec2(1, 1), )); commands.spawn(container::container_bundle( &asset_server, vec2(meters(14.), meters(1.)), uvec2(1, 1), )); commands.spawn(container::container_bundle( &asset_server, vec2(meters(2.), meters(5.)), uvec2(4, 4), )).with_child(lockpick_bundle(&asset_server, uvec2(2, 2), false)); commands.spawn(container::container_bundle( &asset_server, vec2(meters(14.), meters(5.)), uvec2(2, 2), )).with_child(lockpick_bundle(&asset_server, UVec2::ZERO, true)); }