use ::specs::prelude::*; use crate::components::{ ApplyTeleport, EntityMoved, EntryTrigger, Hidden, InflictsDamage, Name, Position, SingleActivation, SufferDamage, TeleportTo, }; use crate::game_log::GameLog; use crate::particle_system::ParticleBuilder; use crate::{colors, spatial, Map}; pub struct TriggerSystem {} impl<'a> System<'a> for TriggerSystem { #[allow(clippy::type_complexity)] type SystemData = ( ReadExpect<'a, Map>, WriteStorage<'a, EntityMoved>, ReadStorage<'a, Position>, ReadStorage<'a, EntryTrigger>, WriteStorage<'a, Hidden>, ReadStorage<'a, Name>, Entities<'a>, WriteExpect<'a, GameLog>, ReadStorage<'a, InflictsDamage>, WriteExpect<'a, ParticleBuilder>, WriteStorage<'a, SufferDamage>, ReadStorage<'a, SingleActivation>, ReadStorage<'a, TeleportTo>, WriteStorage<'a, ApplyTeleport>, ReadExpect<'a, Entity>, ); fn run(&mut self, data: Self::SystemData) { let ( map, mut entity_moved, position, entry_trigger, mut hidden, names, entities, mut log, inflicts_damage, mut particle_builder, mut inflict_damage, single_activation, teleporters, mut apply_teleport, player_entity, ) = data; // Iterate the entities that moved and their final position let mut remove_entities: Vec = Vec::new(); for (entity, mut _entity_moved, pos) in (&entities, &mut entity_moved, &position).join() { let idx = map.xy_idx(pos.x, pos.y); spatial::for_each_tile_content(idx, |entity_id| { // Do not bother to check yourself for being a trap! if entity != entity_id { match entry_trigger.get(entity_id) { None => {} Some(_trigger) => { // We triggered it if let Some(name) = names.get(entity_id) { log.append(format!("{} triggers!", &name.name)); } // The trap is no longer hidden hidden.remove(entity_id); // If the trap is damage inflicting, do it if let Some(damage) = inflicts_damage.get(entity_id) { particle_builder.request( pos.x, pos.y, colors::ORANGE, colors::BLACK, rltk::to_cp437('‼'), 200.0, ); SufferDamage::new_damage( &mut inflict_damage, entity, damage.damage, false, ); } // If it's a teleporter, then do that if let Some(teleport) = teleporters.get(entity_id) { if (teleport.player_only && entity == *player_entity) || !teleport.player_only { apply_teleport .insert( entity, ApplyTeleport { dest_x: teleport.x, dest_y: teleport.y, dest_depth: teleport.depth, }, ) .expect("Unable to insert intent to teleport"); } } // If it is single activation, it needs to be removed if single_activation.get(entity_id).is_some() { remove_entities.push(entity_id); } } } } }); } // Remove any single activation traps for trap in remove_entities.iter() { entities .delete(*trap) .expect("Unable to remove single activation entity"); } // Remove all entity movement markers entity_moved.clear(); } }