diff options
| -rw-r--r-- | content/encyclopediae/default_encyclopedia.json | 20 | ||||
| -rw-r--r-- | content/maps/room.json | 4 | ||||
| -rw-r--r-- | src/assemblage.rs | 8 | ||||
| -rw-r--r-- | src/components/equipment.rs | 4 | ||||
| -rw-r--r-- | src/components/interactable.rs | 9 | ||||
| -rw-r--r-- | src/components/mod.rs | 7 | ||||
| -rw-r--r-- | src/componentwrapper.rs | 7 | ||||
| -rw-r--r-- | src/room.rs | 4 | ||||
| -rw-r--r-- | src/systems/interact.rs | 35 |
9 files changed, 78 insertions, 20 deletions
diff --git a/content/encyclopediae/default_encyclopedia.json b/content/encyclopediae/default_encyclopedia.json index b4007d5..5f127cd 100644 --- a/content/encyclopediae/default_encyclopedia.json +++ b/content/encyclopediae/default_encyclopedia.json @@ -413,6 +413,17 @@ ]]}] ], "flags": ["Occupied"] + }, + "quarry": { + "sprite": "quarry", + "height": 2, + "components": [ + ["Interactable", {"action": ["interaction", ["mine", "mining"]]}], + ["Minable", {"total": 20, "trigger": "loot"}], + ["Loot", {"spread": true, "loot": ["list", [ + ["list", [{"type": "stone"}, 1.0]] + ]]}] + ] } }, "items": { @@ -442,7 +453,14 @@ "armour": {"action": ["equip", { "slot": "body", "stats": {"defence": 3} - }]} + }]}, + "pickaxe": { + "sprite": "sword", + "action": ["equip", { + "slot": "hand", + "stats": {"mining": 5} + }] + } }, "templates":{ "plantedcarrotseed": ["plantedseed", {"delay": 60, "next": "carrotseedling"}], diff --git a/content/maps/room.json b/content/maps/room.json index 052e65b..853e7a3 100644 --- a/content/maps/room.json +++ b/content/maps/room.json @@ -23,7 +23,7 @@ " X,,*,,.,,,,,,,,,,,~~~''''''''''''''''f'''X", " X*,,,,.,,,d,VVV,,,~~~'''''''''''f''''f'''X", "1.......,,,,,VVV,,,~~~'''''''''''ffffff'''X", - " X/,,,,.,,,,,VVV,,,~~~''''''''''''''''''''X", + " X/,,,,.,P,Q,VVV,,,~~~''''''''''''''''''''X", " XXXXX,.,XXXXXXXXXX~~~XXXXXXXXXXXXXXXXXXXXX", " %%% " ], @@ -51,6 +51,8 @@ "s": ["ground", "sign"], "u": ["ground", "dude"], "t": ["ground", "trader"], + "P": ["ground", "pickaxe"], + "Q": "quarry", " ": [] } } diff --git a/src/assemblage.rs b/src/assemblage.rs index d572c7f..2ef62f0 100644 --- a/src/assemblage.rs +++ b/src/assemblage.rs @@ -51,12 +51,12 @@ impl Assemblage { let mut components = Vec::new(); for tup in comps { if let Some(name) = tup.as_str() { - components.push((ComponentType::from_str(name).ok_or(perr!("not a valid componenttype"))?, HashMap::new())); + components.push((ComponentType::from_str(name).ok_or(perr!("{} not a valid componenttype", name))?, HashMap::new())); } else { - let comptype = ComponentType::from_str(tup + let name = tup .get(0).ok_or(perr!("index 0 not in component"))? - .as_str().ok_or(perr!("component name not a string"))? - ).ok_or(perr!("not a valid componenttype"))?; + .as_str().ok_or(perr!("component name not a string"))?; + let comptype = ComponentType::from_str(name).ok_or(perr!("{} not a valid componenttype", name))?; let mut parameters: HashMap<String, ComponentParameter> = HashMap::new(); for (key, value) in tup.get(1).ok_or(perr!("index 1 not in component"))?.as_object().ok_or(perr!("component parameters not a json object"))? { let param = ComponentParameter::from_json(value)?; diff --git a/src/components/equipment.rs b/src/components/equipment.rs index 386ef38..ab573d8 100644 --- a/src/components/equipment.rs +++ b/src/components/equipment.rs @@ -27,7 +27,8 @@ impl Slot { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Stat { Strength, - Defence + Defence, + Mining } impl Stat { @@ -35,6 +36,7 @@ impl Stat { match txt { "strength" => Some(Self::Strength), "defence" => Some(Self::Defence), + "mining" => Some(Self::Mining), _ => None } } diff --git a/src/components/interactable.rs b/src/components/interactable.rs index f1f0508..f48fb9d 100644 --- a/src/components/interactable.rs +++ b/src/components/interactable.rs @@ -8,7 +8,7 @@ use specs::{ use crate::{ exchange::Exchange, ItemId, - components::Trigger, + components::{Trigger, equipment::Stat}, RoomId }; @@ -19,7 +19,8 @@ pub enum Interactable { Say(String), Reply(String), Exchange(String, HashMap<String, Exchange>), - Visit(RoomId) + Visit(RoomId), + Mine(Stat) } use Interactable::*; @@ -47,6 +48,7 @@ impl Interactable { .collect::<Option<HashMap<String, Exchange>>>()? ), "visit" => Visit(RoomId::from_str(arg.as_str()?)), + "mine" => Mine(Stat::from_str(arg.as_str()?)?), _ => None? }) } @@ -62,7 +64,7 @@ impl Interactable { } else { true } - } + }, Visit(_) => { if let Some(txt) = arg { txt.starts_with("visit ") || txt.starts_with("disallow ") || txt.starts_with("allow ") || txt.starts_with("whitelist") @@ -70,6 +72,7 @@ impl Interactable { false } } + Mine(_) => arg.is_none() } } } diff --git a/src/components/mod.rs b/src/components/mod.rs index 64fa717..8ffe30d 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -240,3 +240,10 @@ pub struct Dedup { pub priority: i64 } + +#[derive(Component, Debug, Clone)] +pub struct Minable { + pub progress: i64, + pub total: i64, + pub trigger: Trigger +} diff --git a/src/componentwrapper.rs b/src/componentwrapper.rs index ecc8227..0eca576 100644 --- a/src/componentwrapper.rs +++ b/src/componentwrapper.rs @@ -284,6 +284,13 @@ components!(all: } }; Dedup (id: String, priority: Int); + Minable (trigger: String, total: Int) { + Minable { + trigger: Trigger::from_str(&trigger).ok_or(aerr!("invalid trigger name {}", trigger))?, + progress: 0, + total + } + }; ); diff --git a/src/room.rs b/src/room.rs index 01a299a..3020241 100644 --- a/src/room.rs +++ b/src/room.rs @@ -120,9 +120,9 @@ 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, Dedup), + (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, Dedup, Minable), (Ground, Input, Output, Size, Spawn, Players, Emigration, Time) - ); + ); Room { world, diff --git a/src/systems/interact.rs b/src/systems/interact.rs index d00f3d7..ff41b71 100644 --- a/src/systems/interact.rs +++ b/src/systems/interact.rs @@ -1,5 +1,7 @@ use std::collections::HashSet; +use rand::Rng; + use specs::{ Entities, ReadStorage, @@ -22,7 +24,8 @@ use crate::{ Inventory, Visible, Player, - Whitelist + Whitelist, + Minable }, controls::{Control}, resources::{Ground, NewEntities, Emigration}, @@ -47,13 +50,14 @@ impl <'a> System<'a> for Interact { ReadStorage<'a, Visible>, ReadStorage<'a, Player>, Write<'a, Emigration>, - WriteStorage<'a, Whitelist> + WriteStorage<'a, Whitelist>, + WriteStorage<'a, Minable> ); - fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut triggerbox, new, mut ears, mut inventories, visibles, players, mut emigration, mut whitelists): Self::SystemData) { - for (entity, controller, position) in (&entities, &controllers, &positions).join(){ + fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut triggerbox, new, mut ears, mut inventories, visibles, players, mut emigration, mut whitelists, mut minables): Self::SystemData) { + for (actor, controller, position) in (&entities, &controllers, &positions).join(){ let mut target = None; - let ear = ears.get_mut(entity); + let ear = ears.get_mut(actor); match &controller.control { Control::Interact(directions, arg) => { 'targets: for direction in directions { @@ -71,6 +75,7 @@ impl <'a> System<'a> for Interact { _ => {} } if let Some((ent, interactable, arg)) = target { + let mut cooldown = 2; let name = visibles.get(ent).map(|v| v.name.as_str()); match interactable { Interactable::Trigger(trigger) => { @@ -84,7 +89,7 @@ impl <'a> System<'a> for Interact { } Interactable::Exchange(prefix, exchanges) => { if let Some(txt) = arg { - if let Some(inventory) = inventories.get_mut(entity) { + if let Some(inventory) = inventories.get_mut(actor) { if txt.starts_with(prefix){ let action = txt.split_at(prefix.len()).1; if let Some(exchange) = exchanges.get(action) { @@ -110,7 +115,7 @@ impl <'a> System<'a> for Interact { } } Interactable::Visit(dest) => { - if let (Some(player), Some(whitelist)) = (players.get(entity), whitelists.get_mut(ent)){ + if let (Some(player), Some(whitelist)) = (players.get(actor), whitelists.get_mut(ent)){ let argument = arg.unwrap(); if argument.starts_with("visit ") { let playername = argument.split_at("visit ".len()).1; @@ -141,8 +146,22 @@ 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) { + // todo: give player feedback + cooldown = 20; + minable.progress += rand::thread_rng().gen_range(0, skill_value+1); + if minable.progress >= minable.total { + TriggerBox::add_message(&mut triggerbox, ent, minable.trigger); + minable.progress = 0; + } + } + } + } } - cooldowns.insert(entity, ControlCooldown{amount: 2}).unwrap(); + cooldowns.insert(actor, ControlCooldown{amount: cooldown}).unwrap(); } } } |
