diff --git a/src/ai/encumbrance_system.rs b/src/ai/encumbrance_system.rs index 2974ebe..5c660a4 100644 --- a/src/ai/encumbrance_system.rs +++ b/src/ai/encumbrance_system.rs @@ -2,8 +2,11 @@ use std::collections::HashMap; use ::specs::prelude::*; -use crate::components::{Attributes, EquipmentChanged, Equipped, InBackpack, Item, Pools}; +use crate::components::{ + AttributeBonus, Attributes, EquipmentChanged, Equipped, InBackpack, Item, Pools, +}; use crate::game_log::GameLog; +use crate::gamesystem::attr_bonus; pub struct EncumbranceSystem {} @@ -16,9 +19,10 @@ impl<'a> System<'a> for EncumbranceSystem { ReadStorage<'a, InBackpack>, ReadStorage<'a, Equipped>, WriteStorage<'a, Pools>, - ReadStorage<'a, Attributes>, + WriteStorage<'a, Attributes>, ReadExpect<'a, Entity>, WriteExpect<'a, GameLog>, + ReadStorage<'a, AttributeBonus>, ); fn run(&mut self, data: Self::SystemData) { @@ -29,30 +33,47 @@ impl<'a> System<'a> for EncumbranceSystem { backpacks, wielded, mut pools, - attributes, + mut attributes, player, mut gamelog, + attrbonus, ) = data; if equip_dirty.is_empty() { return; } + #[derive(Default)] + struct ItemUpdate { + weight: f32, + initiative: f32, + might: i32, + fitness: i32, + quickness: i32, + intelligence: i32, + } + // Build the map of who needs updating - let mut to_update: HashMap = HashMap::new(); // (weight, initiative) + let mut to_update: HashMap = HashMap::new(); for (entity, _dirty) in (&entities, &equip_dirty).join() { - to_update.insert(entity, (0., 0.)); + to_update.insert(entity, ItemUpdate::default()); } // Remove all dirty statements equip_dirty.clear(); // Total up equipped items - for (item, equipped) in (&items, &wielded).join() { + for (item, equipped, entity) in (&items, &wielded, &entities).join() { if to_update.contains_key(&equipped.owner) { let totals = to_update.get_mut(&equipped.owner).unwrap(); - totals.0 += item.weight_lbs; - totals.1 += item.initiative_penalty; + totals.weight += item.weight_lbs; + totals.initiative += item.initiative_penalty; + if let Some(attr) = attrbonus.get(entity) { + 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); + } } } @@ -60,18 +81,29 @@ impl<'a> System<'a> for EncumbranceSystem { for (item, carried) in (&items, &backpacks).join() { if to_update.contains_key(&carried.owner) { let totals = to_update.get_mut(&carried.owner).unwrap(); - totals.0 += item.weight_lbs; - totals.1 += item.initiative_penalty; + totals.weight += item.weight_lbs; + totals.initiative += item.initiative_penalty; } } // Apply the data to Pools - for (entity, (weight, initiative)) in to_update.iter() { + for (entity, item) in to_update.iter() { if let Some(pool) = pools.get_mut(*entity) { - pool.total_weight = *weight; - pool.total_initiative_penalty = *initiative; + pool.total_weight = item.weight; + pool.total_initiative_penalty = item.initiative; + + if let Some(attr) = attributes.get_mut(*entity) { + attr.might.modifiers = item.might; + attr.fitness.modifiers = item.fitness; + attr.quickness.modifiers = item.quickness; + attr.intelligence.modifiers = item.intelligence; + attr.might.bonus = attr_bonus(attr.might.base + attr.might.modifiers); + attr.fitness.bonus = attr_bonus(attr.fitness.base + attr.fitness.modifiers); + attr.quickness.bonus = + attr_bonus(attr.quickness.base + attr.quickness.modifiers); + attr.intelligence.bonus = + attr_bonus(attr.intelligence.base + attr.intelligence.modifiers); - if let Some(attr) = attributes.get(*entity) { let carry_capacity_lbs = (attr.might.base + attr.might.modifiers) * 15; if pool.total_weight as i32 > carry_capacity_lbs { // Overburdened diff --git a/src/components.rs b/src/components.rs index 4fdbaac..f75e38c 100644 --- a/src/components.rs +++ b/src/components.rs @@ -382,3 +382,11 @@ pub struct SpawnParticleBurst { pub color: RGB, pub lifetime_ms: f32, } + +#[derive(Component, Debug, Serialize, Deserialize, Clone)] +pub struct AttributeBonus { + pub might: Option, + pub fitness: Option, + pub quickness: Option, + pub intelligence: Option, +} diff --git a/src/main.rs b/src/main.rs index e816aa2..9864be2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,6 +84,7 @@ fn init_state() -> State { ApplyMove, ApplyTeleport, AreaOfEffect, + AttributeBonus, Attributes, BlocksTile, BlocksVisibility, diff --git a/src/raws/item_structs.rs b/src/raws/item_structs.rs index b3af073..ffcb118 100644 --- a/src/raws/item_structs.rs +++ b/src/raws/item_structs.rs @@ -14,6 +14,7 @@ pub struct Item { pub base_value: Option, pub vendor_category: Option, pub magic: Option, + pub attributes: Option, } #[derive(Deserialize, Debug)] @@ -49,3 +50,11 @@ pub struct MagicItem { pub naming: String, pub cursed: Option, } + +#[derive(Deserialize, Debug)] +pub struct ItemAttributeBonus { + pub might: Option, + pub fitness: Option, + pub quickness: Option, + pub intelligence: Option, +} diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index ba34ec9..2edcc81 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -438,6 +438,15 @@ pub fn spawn_named_item( } } + if let Some(ab) = &item_template.attributes { + eb = eb.with(AttributeBonus { + might: ab.might, + fitness: ab.fitness, + quickness: ab.quickness, + intelligence: ab.intelligence, + }) + } + return Some(eb.build()); } diff --git a/src/saveload_system.rs b/src/saveload_system.rs index ed6f0af..5b3b0ab 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -63,6 +63,7 @@ pub fn save_game(ecs: &mut World) { ApplyMove, ApplyTeleport, AreaOfEffect, + AttributeBonus, Attributes, BlocksTile, BlocksVisibility, @@ -183,6 +184,7 @@ pub fn load_game(ecs: &mut World) { ApplyMove, ApplyTeleport, AreaOfEffect, + AttributeBonus, Attributes, BlocksTile, BlocksVisibility,