summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-04-05 23:22:36 +0200
committertroido <troido@protonmail.com>2020-04-05 23:22:36 +0200
commitff457701ff56072914acb8a7160cd02c2a07095a (patch)
treea9f7c9130ce274887924ee140824dc15af061b73
parent48c24ec8b011d081550dc78329cbe61de67b30e9 (diff)
trading now works
-rw-r--r--content/encyclopediae/default_encyclopedia.json14
-rw-r--r--content/maps/room.json3
-rw-r--r--src/components/interactable.rs29
-rw-r--r--src/components/inventory.rs9
-rw-r--r--src/exchange.rs45
-rw-r--r--src/item.rs1
-rw-r--r--src/main.rs1
-rw-r--r--src/playerstate.rs2
-rw-r--r--src/systems/interact.rs70
-rw-r--r--src/systems/take.rs7
10 files changed, 147 insertions, 34 deletions
diff --git a/content/encyclopediae/default_encyclopedia.json b/content/encyclopediae/default_encyclopedia.json
index 1c48a6b..b7364d5 100644
--- a/content/encyclopediae/default_encyclopedia.json
+++ b/content/encyclopediae/default_encyclopedia.json
@@ -227,13 +227,23 @@
"components": [
["Interactable", {"action": ["interaction", ["reply", "did you say '{}'?"]]}]
]
+ },
+ "trader": {
+ "sprite": "human",
+ "height": 1.5,
+ "components": [
+ ["Interactable", {"action": ["interaction", ["exchange", ["buy ", {
+ "pebble": [["radish", "radish"], ["pebble"]],
+ "radishseed": [["radish"], ["radishseed", "radishseed"]]
+ }]]]}]
+ ]
}
},
"items": {
"pebble": {},
"stone": {"action": ["build", ["builtwall", ["Floor"], ["Blocking"]]]},
- "radishseed": {"action": ["build", ["plantedradishseed", ["Floor", "Soil"], ["Occupied", "Blocking"]]]},
- "radish": {"action": ["eat", 3]},
+ "radishseed": {"sprite": "seed", "action": ["build", ["plantedradishseed", ["Floor", "Soil"], ["Occupied", "Blocking"]]]},
+ "radish": {"sprite": "food", "action": ["eat", 3]},
"sword": {"action": ["equip", {
"slot": "hand",
"stats": {"strength": 50}
diff --git a/content/maps/room.json b/content/maps/room.json
index ca50eff..5d69b72 100644
--- a/content/maps/room.json
+++ b/content/maps/room.json
@@ -15,7 +15,7 @@
"X,,,,,.,,,,,,,,,,,,~~~,,,,,,,,,,,,,,,,,,,X",
"X,^,,,.,,,,,,,,,,,,~~~,,,,,T,,,,######,,,X",
"X,^,,,.,,,,,,,,,,,,bbb,,,,,,,,,,#++++#,,,X",
- "X,,,,,.............bbb..........D++++#,,,X",
+ "X,,,t..............bbb..........D++++#,,,X",
"X,**,,.,,,,,,,,,,,,bbb,,,,,,,,,,#++++#,,,X",
"X,*,*,.,u,,,V,,V,,,~~~,,,T,,,T,,#++++#,,,X",
"X,,*,,.,,,,,,,,,,,,~~~,,,,,,,,,,######,,,X",
@@ -50,6 +50,7 @@
"D": ["ground", "closeddoor"],
"s": ["ground", "sign"],
"u": ["ground", "dude"],
+ "t": ["ground", "trader"],
" ": []
}
}
diff --git a/src/components/interactable.rs b/src/components/interactable.rs
index a59cc90..33e3a12 100644
--- a/src/components/interactable.rs
+++ b/src/components/interactable.rs
@@ -1,11 +1,14 @@
+use std::collections::HashMap;
use serde_json::{Value};
use specs::{
Component,
HashMapStorage
};
use crate::{
- Template
+ Template,
+ exchange::Exchange,
+ ItemId
};
#[derive(Component, Debug, Clone, PartialEq)]
@@ -14,7 +17,8 @@ pub enum Interactable {
Harvest,
Change(Template),
Say(String),
- Reply(String)
+ Reply(String),
+ Exchange(String, HashMap<String, Exchange>)
}
use Interactable::*;
@@ -28,6 +32,20 @@ impl Interactable {
"change" => Change(Template::from_json(arg).ok()?),
"say" => Say(arg.as_str()?.to_string()),
"reply" => Reply(arg.as_str()?.to_string()),
+ "exchange" => Exchange(
+ arg.get(0)?.as_str()?.to_string(),
+ arg.get(1)?
+ .as_object()?
+ .iter()
+ .map(|(id, ex)| {
+ let exchange = Exchange {
+ cost: ex.get(0)?.as_array()?.iter().map(|i| Some(ItemId(i.as_str()?.to_string()))).collect::<Option<Vec<ItemId>>>()?,
+ offer: ex.get(1)?.as_array()?.iter().map(|i| Some(ItemId(i.as_str()?.to_string()))).collect::<Option<Vec<ItemId>>>()?
+ };
+ Some((id.clone(), exchange))
+ })
+ .collect::<Option<HashMap<String, Exchange>>>()?
+ ),
_ => None?
})
}
@@ -38,6 +56,13 @@ impl Interactable {
Change(_) => arg.is_none(),
Say(_) => arg.is_none(),
Reply(_) => arg.is_some(),
+ Exchange(prefix, _exchanges) => {
+ if let Some(txt) = arg {
+ txt.starts_with(prefix)
+ } else {
+ true
+ }
+ }
}
}
}
diff --git a/src/components/inventory.rs b/src/components/inventory.rs
index c3282e9..fa65b03 100644
--- a/src/components/inventory.rs
+++ b/src/components/inventory.rs
@@ -5,6 +5,7 @@ use crate::{
ItemId,
item::{Item, ItemAction},
components::equipment::{Stat, Equippable},
+ Encyclopedia
};
#[derive(Debug, Clone)]
@@ -25,6 +26,14 @@ impl Component for Inventory {
impl Inventory {
+ pub fn add_item(&mut self, itemid: ItemId, enc: &Encyclopedia) {
+ self.items.insert(0, InventoryEntry{
+ itemid: itemid.clone(),
+ item: enc.get_item(&itemid).unwrap(),
+ is_equipped: false
+ });
+ }
+
fn equipped(&self) -> Vec<Equippable> {
let mut equippables = Vec::new();
for entry in self.items.iter() {
diff --git a/src/exchange.rs b/src/exchange.rs
new file mode 100644
index 0000000..5e87ef2
--- /dev/null
+++ b/src/exchange.rs
@@ -0,0 +1,45 @@
+
+use crate::{
+ components::Inventory,
+ ItemId,
+ Encyclopedia
+};
+
+#[derive(Debug, Clone, PartialEq)]
+pub struct Exchange {
+ pub cost: Vec<ItemId>,
+ pub offer: Vec<ItemId>
+}
+
+impl Exchange {
+ pub fn show(&self) -> String {
+ format!(
+ "offer: [{}], price: [{}]",
+ self.offer.iter().map(|i| i.0.clone()).collect::<Vec<String>>().join(", "),
+ self.cost.iter().map(|i| i.0.clone()).collect::<Vec<String>>().join(", ")
+ )
+ }
+
+ pub fn can_trade(&self, inventory: &Inventory) -> bool {
+ if self.offer.len() as isize - self.cost.len() as isize > inventory.capacity as isize - inventory.items.len() as isize{
+ return false;
+ }
+ let mut costs = self.cost.clone();
+ for entry in inventory.items.iter() {
+ if let Some(pos) = costs.iter().position(|x| *x == entry.itemid){
+ costs.remove(pos);
+ }
+ }
+ costs.is_empty()
+ }
+
+ pub fn trade(&self, inventory: &mut Inventory, enc: &Encyclopedia) {
+ for item in self.cost.iter() {
+ let pos = inventory.items.iter().position(|entry| entry.itemid == item.clone()).unwrap();
+ inventory.items.remove(pos);
+ }
+ for item in self.offer.iter() {
+ inventory.add_item(item.clone(), enc);
+ }
+ }
+}
diff --git a/src/item.rs b/src/item.rs
index d5ffaa1..420f341 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -2,7 +2,6 @@
use std::collections::HashSet;
use serde_json::{Value};
-use specs::{Component, DenseVecStorage};
use crate::{
Template,
components::{
diff --git a/src/main.rs b/src/main.rs
index 34819e3..21d3ccc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -36,6 +36,7 @@ mod timestamp;
mod purgatory;
mod config;
mod item;
+mod exchange;
use self::{
pos::Pos,
diff --git a/src/playerstate.rs b/src/playerstate.rs
index 852c04f..9dec879 100644
--- a/src/playerstate.rs
+++ b/src/playerstate.rs
@@ -149,7 +149,7 @@ impl PlayerState {
pub fn construct(&self, encyclopedia: &Encyclopedia) -> PreEntity {
vec![
- ComponentWrapper::Visible(Visible{sprite: Sprite{name: "player".to_string()}, height: 1.2, name: self.id.name.clone()}),
+ ComponentWrapper::Visible(Visible{sprite: Sprite{name: "player".to_string()}, height: 1.75, name: self.id.name.clone()}),
ComponentWrapper::Player(Player::new(self.id.clone())),
ComponentWrapper::Inventory(Inventory{
items: self.inventory.iter().map( |(itemid, is_equipped)| {
diff --git a/src/systems/interact.rs b/src/systems/interact.rs
index 4bf2e4c..43c355d 100644
--- a/src/systems/interact.rs
+++ b/src/systems/interact.rs
@@ -10,22 +10,22 @@ use specs::{
Write
};
-use crate::components::{
- Controller,
- Position,
- ControlCooldown,
- Interactable,
- Dead,
- Removed,
- Sound,
- Ear
+use crate::{
+ components::{
+ Controller,
+ Position,
+ ControlCooldown,
+ Interactable,
+ Dead,
+ Removed,
+ Sound,
+ Ear,
+ Inventory
+ },
+ controls::{Control},
+ resources::{Ground, NewEntities}
};
-use crate::controls::{Control};
-use crate::resources::{Ground, NewEntities};
-
-
-
pub struct Interact;
impl <'a> System<'a> for Interact {
type SystemData = (
@@ -38,12 +38,14 @@ impl <'a> System<'a> for Interact {
WriteStorage<'a, Dead>,
WriteStorage<'a, Removed>,
Write<'a, NewEntities>,
- WriteStorage<'a, Ear>
+ WriteStorage<'a, Ear>,
+ WriteStorage<'a, Inventory>
);
- fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut deads, mut removeds, mut new, mut ears): Self::SystemData) {
+ fn run(&mut self, (entities, controllers, positions, ground, mut cooldowns, interactables, mut deads, mut removeds, mut new, mut ears, mut inventories): Self::SystemData) {
for (entity, controller, position) in (&entities, &controllers, &positions).join(){
let mut target = None;
+ let ear = ears.get_mut(entity);
match &controller.control {
Control::Interact(directions, arg) => {
'targets: for direction in directions {
@@ -70,13 +72,33 @@ impl <'a> System<'a> for Interact {
removeds.insert(ent, Removed).unwrap();
}
Interactable::Say(text) => {
- if let Some(ear) = ears.get_mut(entity) {
- ear.sounds.push(Sound{source: None, text: text.clone()});
- }
+ say(ear, text.clone());
}
Interactable::Reply(text) => {
- if let Some(ear) = ears.get_mut(entity) {
- ear.sounds.push(Sound{source: None, text: text.replace("{}", &arg.unwrap())});
+ say(ear, text.replace("{}", &arg.unwrap()));
+ }
+ Interactable::Exchange(prefix, exchanges) => {
+ if let Some(txt) = arg {
+ if let Some(inventory) = inventories.get_mut(entity) {
+ if txt.starts_with(prefix){
+ let action = txt.split_at(prefix.len()).1;
+ if let Some(exchange) = exchanges.get(action) {
+ if exchange.can_trade(inventory){
+ exchange.trade(inventory, &new.encyclopedia);
+ say(ear, format!("Success! '{}' ({})", txt, exchange.show()));
+ } else {
+ say(ear, format!("You do not have the required items or inventory space for '{}' ({})", txt, exchange.show()));
+ }
+ } else {
+ say(ear, format!("Invalid option: {}", action));
+ }
+ }
+ }
+ } else {
+ say(ear, format!("options: {:?}", exchanges.iter().map(|(id, exchange)|
+ format!("{}{}: {}", prefix, id, exchange.show())
+ ).collect::<Vec<String>>())
+ );
}
}
}
@@ -85,3 +107,9 @@ impl <'a> System<'a> for Interact {
}
}
}
+
+fn say(maybe_ear: Option<&mut Ear>, text: String){
+ if let Some(ear) = maybe_ear {
+ ear.sounds.push(Sound{source: None, text});
+ }
+}
diff --git a/src/systems/take.rs b/src/systems/take.rs
index 5a86269..7781445 100644
--- a/src/systems/take.rs
+++ b/src/systems/take.rs
@@ -14,7 +14,6 @@ use crate::components::{
Position,
Removed,
Inventory,
- inventory::InventoryEntry,
Item,
Visible
};
@@ -51,11 +50,7 @@ impl <'a> System<'a> for Take {
}
for ent in ents {
if let Some(item) = items.get(ent) {
- inventory.items.insert(0, InventoryEntry{
- itemid: item.0.clone(),
- item: new.encyclopedia.get_item(&item.0).unwrap(),
- is_equipped: false
- });
+ inventory.add_item(item.0.clone(), &new.encyclopedia);
if let Err(msg) = removed.insert(ent, Removed) {
println!("{:?}", msg);
}