129 lines
4.8 KiB
Rust
129 lines
4.8 KiB
Rust
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<Entity> = 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();
|
|
}
|
|
}
|