From 0353c658aa1d316e73df700cdc72caa9a39dad4c Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Mon, 24 Jan 2022 11:19:31 -0500 Subject: [PATCH] Complete item attribute bonus system, finishing section 5.23 --- src/ai/encumbrance_system.rs | 15 ++++++++++++++- src/effects.rs | 9 ++++++++- src/effects/damage.rs | 23 ++++++++++++++++++++++- src/effects/triggers.rs | 21 ++++++++++++++++++--- src/gui.rs | 15 ++++++++++++--- src/spawner.rs | 14 ++++++++++++++ 6 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/ai/encumbrance_system.rs b/src/ai/encumbrance_system.rs index 5c660a4..e3693c5 100644 --- a/src/ai/encumbrance_system.rs +++ b/src/ai/encumbrance_system.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use ::specs::prelude::*; 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::gamesystem::attr_bonus; @@ -23,6 +23,7 @@ impl<'a> System<'a> for EncumbranceSystem { ReadExpect<'a, Entity>, WriteExpect<'a, GameLog>, ReadStorage<'a, AttributeBonus>, + ReadStorage<'a, StatusEffect>, ); fn run(&mut self, data: Self::SystemData) { @@ -37,6 +38,7 @@ impl<'a> System<'a> for EncumbranceSystem { player, mut gamelog, attrbonus, + statuses, ) = data; 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 for (entity, item) in to_update.iter() { if let Some(pool) = pools.get_mut(*entity) { diff --git a/src/effects.rs b/src/effects.rs index 8b5058d..34395ef 100644 --- a/src/effects.rs +++ b/src/effects.rs @@ -12,7 +12,7 @@ use ::rltk::{FontCharType, RGB}; use ::specs::prelude::*; pub use targeting::*; -use crate::spatial; +use crate::{spatial, AttributeBonus}; lazy_static! { /// The shared queue of effects @@ -51,6 +51,11 @@ pub enum EffectType { depth: i32, player_only: bool, }, + AttributeEffect { + bonus: AttributeBonus, + name: String, + duration: i32, + }, } /// Who, or what the effect should affect. @@ -117,6 +122,7 @@ fn tile_effect_hits_entities(effect: &EffectType) -> bool { | EffectType::Healing { .. } | EffectType::Confusion { .. } | 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::Confusion { .. } => damage::add_confusion(ecs, effect, target), EffectType::TeleportTo { .. } => movement::apply_teleport(ecs, effect, target), + EffectType::AttributeEffect { .. } => damage::attribute_effect(ecs, effect, target), _ => {} } } diff --git a/src/effects/damage.rs b/src/effects/damage.rs index 9093a09..23391d0 100644 --- a/src/effects/damage.rs +++ b/src/effects/damage.rs @@ -5,7 +5,7 @@ use ::specs::saveload::{MarkedBuilder, SimpleMarker}; use super::{add_effect, entity_position, EffectSpawner, EffectType, Targets}; use crate::components::{Attributes, Confusion, Duration, Name, Player, Pools, SerializeMe}; 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) { let mut pools = ecs.write_storage::(); @@ -140,3 +140,24 @@ pub fn add_confusion(ecs: &mut World, effect: &EffectSpawner, target: Entity) { .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::>() + .build(); + + ecs.write_storage::() + .insert(target, EquipmentChanged {}) + .expect("Failed to insert EquipmentChanged tag"); + } +} diff --git a/src/effects/triggers.rs b/src/effects/triggers.rs index 2968e38..a460e6a 100644 --- a/src/effects/triggers.rs +++ b/src/effects/triggers.rs @@ -2,9 +2,9 @@ use ::specs::prelude::*; use super::{add_effect, EffectType, Targets}; use crate::components::{ - Confusion, Consumable, Duration, Hidden, InflictsDamage, MagicMapper, Name, ProvidesFood, - ProvidesHealing, ProvidesRemoveCurse, SingleActivation, SpawnParticleBurst, SpawnParticleLine, - TeleportTo, TownPortal, + AttributeBonus, Confusion, Consumable, Duration, Hidden, InflictsDamage, MagicMapper, Name, + ProvidesFood, ProvidesHealing, ProvidesRemoveCurse, SingleActivation, SpawnParticleBurst, + SpawnParticleLine, TeleportTo, TownPortal, }; use crate::effects::{entity_position, targeting}; use crate::{colors, GameLog, Map, RunState}; @@ -209,6 +209,21 @@ fn event_trigger( did_something = true; } + // Attribute Modifiers + if let Some(attr) = ecs.read_storage::().get(entity) { + add_effect( + creator, + EffectType::AttributeEffect { + bonus: attr.clone(), + duration: 10, + name: ecs.read_storage::().get(entity).unwrap().name.clone(), + }, + targets.clone(), + ); + + did_something = true; + } + did_something } diff --git a/src/gui.rs b/src/gui.rs index 585996f..a4e14a2 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -248,10 +248,19 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { let hunger = ecs.read_storage::(); let hc = hunger.get(*player_entity).unwrap(); 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::Hungry => ctx.print_color(50, 44, colors::ORANGE, colors::BLACK, "Hungry"), - HungerState::Starving => ctx.print_color(50, 44, colors::RED, colors::BLACK, "Starving"), + HungerState::Hungry => { + 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::(); let durations = ecs.read_storage::(); diff --git a/src/spawner.rs b/src/spawner.rs index 6636db9..80b0903 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -96,6 +96,20 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity { 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::>() + .build(); + player }