Complete Section 5.21
This commit is contained in:
parent
1cbb70f294
commit
03a90aba44
@ -47,7 +47,7 @@ pub fn death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
||||
|
||||
let mut pools = ecs.write_storage::<Pools>();
|
||||
let attributes = ecs.read_storage::<Attributes>();
|
||||
let map = ecs.fetch_mut::<Map>();
|
||||
let map = ecs.fetch::<Map>();
|
||||
|
||||
if let Some(pos) = entity_position(ecs, target) {
|
||||
crate::spatial::remove_entity(target, pos as usize);
|
||||
|
@ -22,3 +22,30 @@ pub fn aoe_tiles(map: &Map, target: ::rltk::Point, radius: i32) -> Vec<i32> {
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn find_item_position(ecs: &World, target: Entity) -> Option<i32> {
|
||||
let positions = ecs.read_storage::<Position>();
|
||||
let map = ecs.fetch::<Map>();
|
||||
|
||||
// Easy - it has a position
|
||||
if let Some(pos) = positions.get(target) {
|
||||
return Some(map.xy_idx(pos.x, pos.y) as i32);
|
||||
}
|
||||
|
||||
// Maybe it is carried?
|
||||
if let Some(carried) = ecs.read_storage::<InBackpack>().get(target) {
|
||||
if let Some(pos) = positions.get(carried.owner) {
|
||||
return Some(map.xy_idx(pos.x, pos.y) as i32);
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe it is equipped?
|
||||
if let Some(equipped) = ecs.read_storage::<Equipped>().get(target) {
|
||||
if let Some(pos) = positions.get(equipped.owner) {
|
||||
return Some(map.xy_idx(pos.x, pos.y) as i32);
|
||||
}
|
||||
}
|
||||
|
||||
// No idea - give up
|
||||
None
|
||||
}
|
||||
|
@ -3,9 +3,11 @@ use ::specs::prelude::*;
|
||||
use super::{add_effect, EffectType, Targets};
|
||||
use crate::components::{
|
||||
Confusion, Consumable, Hidden, InflictsDamage, MagicMapper, Name, ProvidesFood,
|
||||
ProvidesHealing, SingleActivation, TeleportTo, TownPortal,
|
||||
ProvidesHealing, SingleActivation, SpawnParticleBurst, SpawnParticleLine, TeleportTo,
|
||||
TownPortal,
|
||||
};
|
||||
use crate::{GameLog, Map, RunState};
|
||||
use crate::effects::{entity_position, targeting};
|
||||
use crate::{colors, GameLog, Map, RunState};
|
||||
|
||||
pub fn item_trigger(creator: Option<Entity>, item: Entity, targets: &Targets, ecs: &mut World) {
|
||||
// Use the item via the generic system
|
||||
@ -48,6 +50,44 @@ fn event_trigger(
|
||||
let mut did_something = false;
|
||||
let mut gamelog = ecs.fetch_mut::<GameLog>();
|
||||
|
||||
// Simple particle spawn
|
||||
if let Some(part) = ecs.read_storage::<SpawnParticleBurst>().get(entity) {
|
||||
add_effect(
|
||||
creator,
|
||||
EffectType::Particle {
|
||||
glyph: part.glyph,
|
||||
fg: part.color,
|
||||
bg: colors::BLACK,
|
||||
lifespan: part.lifetime_ms,
|
||||
},
|
||||
targets.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
// Line particle spawn
|
||||
if let Some(part) = ecs.read_storage::<SpawnParticleLine>().get(entity) {
|
||||
if let Some(start_pos) = targeting::find_item_position(ecs, entity) {
|
||||
match targets {
|
||||
Targets::Tile { tile_idx } => spawn_line_particles(ecs, start_pos, *tile_idx, part),
|
||||
Targets::Tiles { tiles } => tiles
|
||||
.iter()
|
||||
.for_each(|tile_idx| spawn_line_particles(ecs, start_pos, *tile_idx, part)),
|
||||
Targets::Single { target } => {
|
||||
if let Some(end_pos) = entity_position(ecs, *target) {
|
||||
spawn_line_particles(ecs, start_pos, end_pos, part);
|
||||
}
|
||||
}
|
||||
Targets::TargetList { targets } => {
|
||||
targets.iter().for_each(|target| {
|
||||
if let Some(end_pos) = entity_position(ecs, *target) {
|
||||
spawn_line_particles(ecs, start_pos, end_pos, part);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Providing food
|
||||
if ecs.read_storage::<ProvidesFood>().get(entity).is_some() {
|
||||
add_effect(creator, EffectType::WellFed, targets.clone());
|
||||
@ -137,3 +177,26 @@ fn event_trigger(
|
||||
|
||||
did_something
|
||||
}
|
||||
|
||||
fn spawn_line_particles(ecs: &World, start: i32, end: i32, part: &SpawnParticleLine) {
|
||||
use ::rltk::{LineAlg, Point};
|
||||
|
||||
let map = ecs.fetch::<Map>();
|
||||
let start_pt = Point::new(start % map.width, end / map.width);
|
||||
let end_pt = Point::new(end % map.width, end / map.width);
|
||||
let line = ::rltk::line2d(LineAlg::Bresenham, start_pt, end_pt);
|
||||
for pt in line.iter() {
|
||||
add_effect(
|
||||
None,
|
||||
EffectType::Particle {
|
||||
glyph: part.glyph,
|
||||
fg: part.color,
|
||||
bg: colors::BLACK,
|
||||
lifespan: part.lifetime_ms,
|
||||
},
|
||||
Targets::Tile {
|
||||
tile_idx: map.xy_idx(pt.x, pt.y) as i32,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -268,6 +268,24 @@ pub fn string_to_slot(slot: &str) -> EquipmentSlot {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_particle_line(n: &str) -> SpawnParticleLine {
|
||||
let tokens: Vec<_> = n.split(';').collect();
|
||||
SpawnParticleLine {
|
||||
glyph: rltk::to_cp437(tokens[0].chars().next().unwrap()),
|
||||
color: RGB::from_hex(tokens[1]).expect("Invalid hex rgb color"),
|
||||
lifetime_ms: tokens[2].parse::<f32>().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_particle(n: &str) -> SpawnParticleBurst {
|
||||
let tokens: Vec<_> = n.split(';').collect();
|
||||
SpawnParticleBurst {
|
||||
glyph: rltk::to_cp437(tokens[0].chars().next().unwrap()),
|
||||
color: RGB::from_hex(tokens[1]).expect("Invalid hex rgb color"),
|
||||
lifetime_ms: tokens[2].parse::<f32>().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! apply_effects {
|
||||
($effects:expr, $eb:expr) => {
|
||||
for effect in $effects.iter() {
|
||||
@ -302,6 +320,8 @@ macro_rules! apply_effects {
|
||||
"town_portal" => $eb = $eb.with(TownPortal {}),
|
||||
"food" => $eb = $eb.with(ProvidesFood {}),
|
||||
"single_activation" => $eb = $eb.with(SingleActivation {}),
|
||||
"particle_line" => $eb = $eb.with(parse_particle_line(&effect.1)),
|
||||
"particle" => $eb = $eb.with(parse_particle(&effect.1)),
|
||||
_ => {
|
||||
::rltk::console::log(format!(
|
||||
"Warning: consumable effect {} not implemented.",
|
||||
|
Loading…
Reference in New Issue
Block a user