Complete item attribute bonus system, finishing section 5.23

This commit is contained in:
Timothy Warren 2022-01-24 11:19:31 -05:00
parent ee5db23f6b
commit 0353c658aa
6 changed files with 88 additions and 9 deletions

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use ::specs::prelude::*; use ::specs::prelude::*;
use crate::components::{ use crate::components::{
AttributeBonus, Attributes, EquipmentChanged, Equipped, InBackpack, Item, Pools, AttributeBonus, Attributes, EquipmentChanged, Equipped, InBackpack, Item, Pools, StatusEffect,
}; };
use crate::game_log::GameLog; use crate::game_log::GameLog;
use crate::gamesystem::attr_bonus; use crate::gamesystem::attr_bonus;
@ -23,6 +23,7 @@ impl<'a> System<'a> for EncumbranceSystem {
ReadExpect<'a, Entity>, ReadExpect<'a, Entity>,
WriteExpect<'a, GameLog>, WriteExpect<'a, GameLog>,
ReadStorage<'a, AttributeBonus>, ReadStorage<'a, AttributeBonus>,
ReadStorage<'a, StatusEffect>,
); );
fn run(&mut self, data: Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
@ -37,6 +38,7 @@ impl<'a> System<'a> for EncumbranceSystem {
player, player,
mut gamelog, mut gamelog,
attrbonus, attrbonus,
statuses,
) = data; ) = data;
if equip_dirty.is_empty() { if equip_dirty.is_empty() {
@ -86,6 +88,17 @@ impl<'a> System<'a> for EncumbranceSystem {
} }
} }
// Total up status effect modifiers
for (status, attr) in (&statuses, &attrbonus).join() {
if to_update.contains_key(&status.target) {
let totals = to_update.get_mut(&status.target).unwrap();
totals.might += attr.might.unwrap_or(0);
totals.fitness += attr.fitness.unwrap_or(0);
totals.quickness += attr.quickness.unwrap_or(0);
totals.intelligence += attr.intelligence.unwrap_or(0);
}
}
// Apply the data to Pools // Apply the data to Pools
for (entity, item) in to_update.iter() { for (entity, item) in to_update.iter() {
if let Some(pool) = pools.get_mut(*entity) { if let Some(pool) = pools.get_mut(*entity) {

View File

@ -12,7 +12,7 @@ use ::rltk::{FontCharType, RGB};
use ::specs::prelude::*; use ::specs::prelude::*;
pub use targeting::*; pub use targeting::*;
use crate::spatial; use crate::{spatial, AttributeBonus};
lazy_static! { lazy_static! {
/// The shared queue of effects /// The shared queue of effects
@ -51,6 +51,11 @@ pub enum EffectType {
depth: i32, depth: i32,
player_only: bool, player_only: bool,
}, },
AttributeEffect {
bonus: AttributeBonus,
name: String,
duration: i32,
},
} }
/// Who, or what the effect should affect. /// Who, or what the effect should affect.
@ -117,6 +122,7 @@ fn tile_effect_hits_entities(effect: &EffectType) -> bool {
| EffectType::Healing { .. } | EffectType::Healing { .. }
| EffectType::Confusion { .. } | EffectType::Confusion { .. }
| EffectType::TeleportTo { .. } | EffectType::TeleportTo { .. }
| EffectType::AttributeEffect { .. }
) )
} }
@ -152,6 +158,7 @@ fn affect_entity(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
EffectType::Healing { .. } => damage::heal_damage(ecs, effect, target), EffectType::Healing { .. } => damage::heal_damage(ecs, effect, target),
EffectType::Confusion { .. } => damage::add_confusion(ecs, effect, target), EffectType::Confusion { .. } => damage::add_confusion(ecs, effect, target),
EffectType::TeleportTo { .. } => movement::apply_teleport(ecs, effect, target), EffectType::TeleportTo { .. } => movement::apply_teleport(ecs, effect, target),
EffectType::AttributeEffect { .. } => damage::attribute_effect(ecs, effect, target),
_ => {} _ => {}
} }
} }

View File

@ -5,7 +5,7 @@ use ::specs::saveload::{MarkedBuilder, SimpleMarker};
use super::{add_effect, entity_position, EffectSpawner, EffectType, Targets}; use super::{add_effect, entity_position, EffectSpawner, EffectType, Targets};
use crate::components::{Attributes, Confusion, Duration, Name, Player, Pools, SerializeMe}; use crate::components::{Attributes, Confusion, Duration, Name, Player, Pools, SerializeMe};
use crate::gamesystem::{mana_at_level, player_hp_at_level}; use crate::gamesystem::{mana_at_level, player_hp_at_level};
use crate::{colors, GameLog, Map, StatusEffect}; use crate::{colors, EquipmentChanged, GameLog, Map, StatusEffect};
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) { pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
let mut pools = ecs.write_storage::<Pools>(); let mut pools = ecs.write_storage::<Pools>();
@ -140,3 +140,24 @@ pub fn add_confusion(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
.build(); .build();
} }
} }
pub fn attribute_effect(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
if let EffectType::AttributeEffect {
bonus,
name,
duration,
} = &effect.effect_type
{
ecs.create_entity()
.with(StatusEffect { target })
.with(bonus.clone())
.with(Duration { turns: *duration })
.with(Name::from(name.clone()))
.marked::<SimpleMarker<SerializeMe>>()
.build();
ecs.write_storage::<EquipmentChanged>()
.insert(target, EquipmentChanged {})
.expect("Failed to insert EquipmentChanged tag");
}
}

View File

@ -2,9 +2,9 @@ use ::specs::prelude::*;
use super::{add_effect, EffectType, Targets}; use super::{add_effect, EffectType, Targets};
use crate::components::{ use crate::components::{
Confusion, Consumable, Duration, Hidden, InflictsDamage, MagicMapper, Name, ProvidesFood, AttributeBonus, Confusion, Consumable, Duration, Hidden, InflictsDamage, MagicMapper, Name,
ProvidesHealing, ProvidesRemoveCurse, SingleActivation, SpawnParticleBurst, SpawnParticleLine, ProvidesFood, ProvidesHealing, ProvidesRemoveCurse, SingleActivation, SpawnParticleBurst,
TeleportTo, TownPortal, SpawnParticleLine, TeleportTo, TownPortal,
}; };
use crate::effects::{entity_position, targeting}; use crate::effects::{entity_position, targeting};
use crate::{colors, GameLog, Map, RunState}; use crate::{colors, GameLog, Map, RunState};
@ -209,6 +209,21 @@ fn event_trigger(
did_something = true; did_something = true;
} }
// Attribute Modifiers
if let Some(attr) = ecs.read_storage::<AttributeBonus>().get(entity) {
add_effect(
creator,
EffectType::AttributeEffect {
bonus: attr.clone(),
duration: 10,
name: ecs.read_storage::<Name>().get(entity).unwrap().name.clone(),
},
targets.clone(),
);
did_something = true;
}
did_something did_something
} }

View File

@ -248,10 +248,19 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
let hunger = ecs.read_storage::<HungerClock>(); let hunger = ecs.read_storage::<HungerClock>();
let hc = hunger.get(*player_entity).unwrap(); let hc = hunger.get(*player_entity).unwrap();
match hc.state { match hc.state {
HungerState::WellFed => ctx.print_color(50, 44, colors::GREEN, colors::BLACK, "Well Fed"), HungerState::WellFed => {
ctx.print_color(50, y, colors::GREEN, colors::BLACK, "Well Fed");
y -= 1;
}
HungerState::Normal => {} HungerState::Normal => {}
HungerState::Hungry => ctx.print_color(50, 44, colors::ORANGE, colors::BLACK, "Hungry"), HungerState::Hungry => {
HungerState::Starving => ctx.print_color(50, 44, colors::RED, colors::BLACK, "Starving"), ctx.print_color(50, y, colors::ORANGE, colors::BLACK, "Hungry");
y -= 1;
}
HungerState::Starving => {
ctx.print_color(50, y, colors::RED, colors::BLACK, "Starving");
y -= 1;
}
} }
let statuses = ecs.read_storage::<StatusEffect>(); let statuses = ecs.read_storage::<StatusEffect>();
let durations = ecs.read_storage::<Duration>(); let durations = ecs.read_storage::<Duration>();

View File

@ -96,6 +96,20 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
SpawnType::Equipped { by: player }, SpawnType::Equipped { by: player },
); );
// Starting hangover
ecs.create_entity()
.with(StatusEffect { target: player })
.with(Duration { turns: 10 })
.with(Name::from("Hangover"))
.with(AttributeBonus {
might: Some(-1),
fitness: None,
quickness: Some(-1),
intelligence: Some(-1),
})
.marked::<SimpleMarker<SerializeMe>>()
.build();
player player
} }