diff options
| author | troido <troido@protonmail.com> | 2020-10-03 15:20:52 +0200 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-10-03 15:20:52 +0200 |
| commit | fa5ddaa570473ece02e0a3bfb35702211d21ce12 (patch) | |
| tree | 501498c9db9d7d2c985f86272b3405c98301556f /src | |
| parent | 5af83beb6f10023cef7eba192a0b190518fe967b (diff) | |
added dense grass; home is now part of monsterAI component
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/equipment.rs | 12 | ||||
| -rw-r--r-- | src/components/faction.rs | 15 | ||||
| -rw-r--r-- | src/components/mod.rs | 17 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 11 | ||||
| -rw-r--r-- | src/fromtoparameter.rs | 5 | ||||
| -rw-r--r-- | src/item.rs | 2 | ||||
| -rw-r--r-- | src/playerstate.rs | 12 | ||||
| -rw-r--r-- | src/room.rs | 6 | ||||
| -rw-r--r-- | src/systems/controlai.rs | 11 | ||||
| -rw-r--r-- | src/systems/interact.rs | 20 | ||||
| -rw-r--r-- | src/systems/mod.rs | 2 | ||||
| -rw-r--r-- | src/systems/spawn.rs | 2 | ||||
| -rw-r--r-- | src/systems/spawncheck.rs | 39 |
13 files changed, 98 insertions, 56 deletions
diff --git a/src/components/equipment.rs b/src/components/equipment.rs index e07aa0b..008e0c6 100644 --- a/src/components/equipment.rs +++ b/src/components/equipment.rs @@ -1,10 +1,6 @@ use std::collections::HashMap; use serde::{Serialize, Deserialize}; -use specs::{ - Component, - HashMapStorage -}; use strum_macros::{EnumString, Display}; use crate::{ Sprite @@ -27,7 +23,8 @@ pub enum Slot { pub enum Stat { Strength, Defence, - Mining + Mining, + Gathering } @@ -40,11 +37,6 @@ pub struct Equippable { -#[derive(Component, Debug, Clone)] -#[storage(HashMapStorage)] -pub struct Equipment { - pub slots: Vec<Slot> -} #[cfg(test)] mod tests { diff --git a/src/components/faction.rs b/src/components/faction.rs index 5fc02a2..32184d5 100644 --- a/src/components/faction.rs +++ b/src/components/faction.rs @@ -1,4 +1,5 @@ +use strum_macros::{EnumString, Display}; use specs::{ Component, HashMapStorage, @@ -6,7 +7,8 @@ use specs::{ Entity, }; -#[derive(Component, Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Component, Debug, Clone, Copy, PartialEq, Eq, Hash, EnumString, Display)] +#[strum(serialize_all = "lowercase")] #[storage(HashMapStorage)] pub enum Faction { Neutral, @@ -19,17 +21,6 @@ use Faction::{Neutral, Good, Evil, None}; impl Faction { - pub fn from_str(name: &str) -> Option<Faction> { - match name.to_lowercase().as_str() { - "neutral" => Some(Neutral), - "good" => Some(Good), - "evil" => Some(Evil), - "none" => Some(None), - "" => Some(None), - _ => Option::None - } - } - pub fn is_enemy(&self, other: Faction) -> bool { match self { Neutral => false, diff --git a/src/components/mod.rs b/src/components/mod.rs index f3a91d5..d462fef 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -17,7 +17,7 @@ pub use messages::{ }; pub use faction::Faction; pub use interactable::{Interactable}; -pub use equipment::Equipment; +pub use equipment::{Equippable, Stat, Slot}; pub use inventory::Inventory; pub use serialise::Serialise; pub use flags::{ @@ -173,11 +173,6 @@ pub struct MonsterAI { pub home: Option<Pos> } -#[derive(Component, Debug, Clone, Default)] -#[storage(HashMapStorage)] -pub struct Home { - pub home: Pos -} #[derive(Component, Debug, Clone)] #[storage(HashMapStorage)] @@ -259,3 +254,13 @@ pub struct Substitute { pub into: Template } +#[derive(Component, Debug, Clone)] +pub struct Stats { + pub skills: HashMap<Stat, i64> +} + +#[derive(Component, Debug, Clone)] +pub struct Requirements { + pub required_flags: HashSet<Flag>, + pub blocking_flags: HashSet<Flag> +} diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index 2f12a42..a45f3c0 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -15,7 +15,8 @@ use crate::{ AttackType, Clan, Flag, - Trigger + Trigger, + Stat }, parameter::{Parameter}, fromtoparameter::FromToParameter, @@ -170,14 +171,12 @@ components!(all: } }; Clan (name: String); - Home (home: Pos); - Faction (faction: String) {Faction::from_str(faction.as_str()).ok_or(aerr!("invalid faction name"))?}; + Faction (faction: String) {Faction::from_str(faction.as_str()).map_err(|_|aerr!("invalid faction name '{}'", faction))?}; Interactable (typ: String, arg: Parameter) { - Interactable::parse_from_parameter(&typ, &arg).ok_or(aerr!("invalid interaction {:?} {:?}", typ, arg))? + Interactable::parse_from_parameter(&typ, &arg).ok_or(aerr!("invalid interaction {} {:?}", typ, arg))? }; Loot (loot: Vec<(Template, f64)>); Timer (trigger: Trigger, delay: i64, spread: f64, target_time: Option<Timestamp>); - Equipment () {panic!("equipment from parameters not implemented")}; TimeOffset (dtime: i64); Flags (flags: Vec<String>) { Flags( @@ -212,6 +211,8 @@ components!(all: ).collect::<std::result::Result<Vec<Trigger>, std::boxed::Box<errors::AError>>>()? } }; + Stats (skills: HashMap<Stat, i64>); + Requirements (required_flags: HashSet<Flag>, blocking_flags: HashSet<Flag>); ); diff --git a/src/fromtoparameter.rs b/src/fromtoparameter.rs index 180632f..41665f4 100644 --- a/src/fromtoparameter.rs +++ b/src/fromtoparameter.rs @@ -10,7 +10,7 @@ use crate::{ Sprite, ItemId, RoomId, - components::{Trigger}, + components::{Trigger, Stat, Faction, Flag}, Timestamp }; @@ -102,6 +102,9 @@ macro_rules! fromtostr { } fromtostr!(Trigger); +fromtostr!(Stat); +fromtostr!(Faction); +fromtostr!(Flag); impl<T> FromToParameter for Vec<T> where T: FromToParameter { diff --git a/src/item.rs b/src/item.rs index c8337f9..7a494b7 100644 --- a/src/item.rs +++ b/src/item.rs @@ -7,7 +7,7 @@ use crate::{ Template, components::{ Flag, - equipment::Equippable + Equippable } }; diff --git a/src/playerstate.rs b/src/playerstate.rs index 658aeb2..2bc0456 100644 --- a/src/playerstate.rs +++ b/src/playerstate.rs @@ -18,15 +18,17 @@ use crate::{ AttackType, Autofight, Faction, - Equipment, - equipment::Slot, - Ear + Slot, + Ear, + Stats, + Stat }, Result, aerr, Sprite, Encyclopedia, Pos, + hashmap }; #[allow(non_upper_case_globals)] @@ -96,8 +98,8 @@ impl PlayerState { ComponentWrapper::Movable(Movable{cooldown: 2}), ComponentWrapper::Autofight(Autofight::default()), ComponentWrapper::Faction(Faction::Good), - ComponentWrapper::Equipment(Equipment{slots: vec!(Slot::Hand, Slot::Body)}), - ComponentWrapper::Ear(Ear::default()) + ComponentWrapper::Ear(Ear::default()), + ComponentWrapper::Stats(Stats{skills: hashmap!{Stat::Gathering => 10}}) ]) } } diff --git a/src/room.rs b/src/room.rs index 400dfa2..4f0aa47 100644 --- a/src/room.rs +++ b/src/room.rs @@ -71,6 +71,7 @@ use crate::{ Building, SpawnTrigger, Replace, + SpawnCheck, } }; @@ -80,12 +81,13 @@ pub fn default_dispatcher<'a, 'b>() -> Dispatcher<'a, 'b> { .with(Timeout, "timeout", &[]) .with(UpdateCooldowns, "cool_down", &[]) .with(Spawn, "spawn", &[]) + .with(SpawnCheck, "spawncheck", &["spawn"]) .with(ControlInput, "controlinput", &["cool_down"]) .with(ControlAI, "controlai", &["cool_down"]) .with(Take, "take", &["controlinput", "controlai"]) .with(Use, "use", &["controlinput", "controlai"]) .with(Interact, "interact", &["controlinput", "controlai"]) - .with(SpawnTrigger, "spawntrigger", &["spawn", "replace"]) + .with(SpawnTrigger, "spawntrigger", &["spawncheck", "replace"]) .with(Move, "move", &["controlinput", "controlai"]) .with(Trapping, "trapping", &["move"]) .with(Fight, "fight", &["move"]) @@ -124,7 +126,7 @@ impl <'a, 'b>Room<'a, 'b> { world.insert(NewEntities::new(encyclopedia)); register_insert!( world, - (Position, Visible, Controller, Movable, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, TriggerBox, Trap, Fighter, Healing, ControlCooldown, Autofight, MonsterAI, Home, AttackInbox, Item, Spawner, Clan, Faction, Interactable, Loot, Timer, Equipment, TimeOffset, Flags, Ear, Build, Whitelist, Minable, LootHolder, OnSpawn, Substitute), + (Position, Visible, Controller, Movable, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, TriggerBox, Trap, Fighter, Healing, ControlCooldown, Autofight, MonsterAI, AttackInbox, Item, Spawner, Clan, Faction, Interactable, Loot, Timer, TimeOffset, Flags, Ear, Build, Whitelist, Minable, LootHolder, OnSpawn, Substitute, Stats, Requirements), (Ground, Input, Output, Size, Spawn, Players, Emigration, Time, RoomFlags) ); diff --git a/src/systems/controlai.rs b/src/systems/controlai.rs index ab72f77..5032cc4 100644 --- a/src/systems/controlai.rs +++ b/src/systems/controlai.rs @@ -11,7 +11,7 @@ use specs::{ }; use crate::{ - components::{Controller, ControlCooldown, Fighter, MonsterAI, Home, Health, Position, Faction}, + components::{Controller, ControlCooldown, Fighter, MonsterAI, Health, Position, Faction}, controls::{Control, Direction::{self, North, South, East, West}}, Pos }; @@ -25,12 +25,11 @@ impl <'a> System<'a> for ControlAI { ReadStorage<'a, ControlCooldown>, ReadStorage<'a, MonsterAI>, ReadStorage<'a, Fighter>, - ReadStorage<'a, Home>, ReadStorage<'a, Health>, ReadStorage<'a, Position>, ReadStorage<'a, Faction> ); - fn run(&mut self, (entities, mut controllers, cooldowns, ais, fighters, homes, healths, positions, factions): Self::SystemData) { + fn run(&mut self, (entities, mut controllers, cooldowns, ais, fighters, healths, positions, factions): Self::SystemData) { for (entity, ai, position, ()) in (&entities, &ais, &positions, !&cooldowns).join() { if let Some(fighter) = fighters.get(entity) { @@ -60,9 +59,9 @@ impl <'a> System<'a> for ControlAI { } } if rand::thread_rng().gen_range(0.0, 1.0) < ai.move_chance { - if let Some(home) = homes.get(entity) { - if rand::thread_rng().gen_range(0.0, 1.0) < ai.homesickness * (position.pos.distance_to(home.home) as f64) { - let direction = step_to(position.pos, home.home).unwrap(); + if let Some(home) = ai.home { + if rand::thread_rng().gen_range(0.0, 1.0) < ai.homesickness * (position.pos.distance_to(home) as f64) { + let direction = step_to(position.pos, home).unwrap(); controllers.insert(entity, Controller{control: Control::Move(direction)}).unwrap(); return; } diff --git a/src/systems/interact.rs b/src/systems/interact.rs index 81563e8..204cd86 100644 --- a/src/systems/interact.rs +++ b/src/systems/interact.rs @@ -1,5 +1,5 @@ -use std::collections::HashSet; +use std::collections::{HashSet, HashMap}; use rand::Rng; use specs::{ @@ -25,7 +25,8 @@ use crate::{ Visible, Player, Whitelist, - Minable + Minable, + Stats }, controls::{Control}, resources::{Ground, Emigration, NewEntities}, @@ -52,10 +53,11 @@ impl <'a> System<'a> for Interact { Write<'a, Emigration>, WriteStorage<'a, Whitelist>, WriteStorage<'a, Minable>, + ReadStorage<'a, Stats>, Read<'a, NewEntities> ); - fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut triggerbox, mut ears, mut inventories, visibles, players, mut emigration, mut whitelists, mut minables, new): Self::SystemData) { + fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut triggerbox, mut ears, mut inventories, visibles, players, mut emigration, mut whitelists, mut minables, stats, new): Self::SystemData) { for (actor, controller, position) in (&entities, &controllers, &positions).join(){ let mut target = None; let ear = ears.get_mut(actor); @@ -121,9 +123,15 @@ impl <'a> System<'a> for Interact { } } Interactable::Mine(skill) => { - if let (Some(inventory), Some(minable)) = (inventories.get(actor), minables.get_mut(ent)) { - let stats = inventory.equipment_bonuses(); - if let Some(skill_value) = stats.get(skill) { + if let Some(minable) = minables.get_mut(ent) { + let mut skills = inventories.get(actor).map(Inventory::equipment_bonuses).unwrap_or_else(HashMap::new); + if let Some(skillset) = stats.get(actor) { + for (skill, val) in skillset.skills.iter() { + *skills.entry(*skill).or_insert(0) += val; + } + } + if let Some(skill_value) = skills.get(skill) { + println!("{:?} {:?}", skill, skill_value); // todo: give player feedback cooldown = 20; minable.progress += rand::thread_rng().gen_range(0, skill_value+1); diff --git a/src/systems/mod.rs b/src/systems/mod.rs index e0ae2e8..598feaa 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -23,6 +23,7 @@ mod clear; mod building; mod spawntrigger; mod replace; +mod spawncheck; pub use self::{ controlinput::ControlInput, @@ -49,4 +50,5 @@ pub use self::{ building::Building, spawntrigger::SpawnTrigger, replace::Replace, + spawncheck::SpawnCheck }; diff --git a/src/systems/spawn.rs b/src/systems/spawn.rs index da0735d..c6db0e4 100644 --- a/src/systems/spawn.rs +++ b/src/systems/spawn.rs @@ -17,7 +17,6 @@ use crate::{ Position, Spawner, Clan, - Home, TriggerBox, Trigger, TimeOffset @@ -62,7 +61,6 @@ impl <'a> System<'a> for Spawn { match new.encyclopedia.construct(&spawner.template) { Ok(mut preent) => { preent.push(ComponentWrapper::Clan(spawner.clan.clone())); - preent.push(ComponentWrapper::Home(Home{home: position.pos})); let offset = Pos::new( rng.gen::<i64>()%(spawner.radius*2+1)-spawner.radius, rng.gen::<i64>()%(spawner.radius*2+1)-spawner.radius); diff --git a/src/systems/spawncheck.rs b/src/systems/spawncheck.rs new file mode 100644 index 0000000..52ff38e --- /dev/null +++ b/src/systems/spawncheck.rs @@ -0,0 +1,39 @@ + +use std::collections::HashSet; +use specs::{ + WriteStorage, + ReadStorage, + Entities, + System, + Join, + Read +}; + +use crate::{ + components::{Removed, Requirements, New, Position, Flag, Flags}, + resources::{Ground, RoomFlags} +}; + + +pub struct SpawnCheck; +impl <'a> System<'a> for SpawnCheck { + type SystemData = ( + Entities<'a>, + ReadStorage<'a, Requirements>, + ReadStorage<'a, New>, + WriteStorage<'a, Removed>, + Read<'a, Ground>, + Read<'a, RoomFlags>, + ReadStorage<'a, Position>, + ReadStorage<'a, Flags> + ); + fn run(&mut self, (entities, requirements, new, mut removeds, ground, roomflags, positions, flags): Self::SystemData) { + for (entity, requirements, _new, position) in (&entities, &requirements, &new, &positions).join() { + let ground_flags: HashSet<Flag> = ground.flags_on(position.pos, &flags).union(&roomflags.0).cloned().collect(); + if !(requirements.required_flags.is_subset(&ground_flags) && requirements.blocking_flags.is_disjoint(&ground_flags)){ + removeds.insert(entity, Removed).unwrap(); + } + } + } +} + |
