Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::fmt::format;
use bevy::prelude::{Component, EventReader, Query};
use bevy::utils::HashMap;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use crate::world::travel::WorldTickEvent;
use crate::world::TradingState;
#[derive(Clone, Debug, Default, Component, Serialize, Deserialize)]
pub struct CraftSpecialism {
pub requirements: HashMap<String, usize>,
pub production: HashMap<String, usize>,
}
lazy_static! {
static ref REQUIREMENT_TEMPLATES: Vec<String> = {
let mut items = Vec::with_capacity(4);
items.push(String::from("I hear that the artisans at [[TOWN]] are pretty good at working with [[ITEMS]]. A wonder to behold!",));
items.push(String::from("I remember the last time I was at [[TOWN]]. I saw a craftsman making something with [[ITEMS]]. I hope I get to see that again one day...",));
items.push(String::from("If you happen to have [[ITEMS]], consider popping over to [[TOWN]]. I hear there's high demand there!",));
items.push(String::from("I've heard that there are a lot of folk able to make use of [[ITEMS]] over in [[TOWN]]."));
items
};
static ref PRODUCTION_TEMPLATES: Vec<String> = {
let mut items = Vec::with_capacity(3);
items.push(String::from("Have you ever seen the craftsfolk over in [[TOWN]] making [[ITEMS]]? It's a wonder to see. I heard they need a few bits and bobs to get going though."));
items.push(String::from("Got a hankering for [[ITEMS]]? If you can get some supplies to [[TOWN]], you might be in luck."));
items.push(String::from("My cousin over in [[TOWN]] is a dab hand at making [[ITEMS]]. Doesn't usually have the supplies for it, though."));
items
};
}
impl CraftSpecialism {
pub fn requirements_satisfied(&self, inventory: &TradingState) -> bool {
self.requirements.iter().all(|(name, amount)| {
inventory
.items
.get(name)
.map(|quantity| quantity >= amount)
.unwrap_or(false)
})
}
pub fn apply_to_inventory(&self, inventory: &mut TradingState) -> bool {
if self.requirements_satisfied(inventory) {
for (name, amount) in self.requirements.iter() {
inventory.remove_items(name, *amount);
}
for (name, amount) in self.production.iter() {
inventory.add_items(name, *amount);
}
true
} else {
false
}
}
fn format_item_map(map: &HashMap<String, usize>) -> String {
match map.len() {
0 => "...oh, I forget".to_string(),
1 => format!("an {}", map.keys().next().unwrap()),
2 => format!(
"{} and {}",
map.keys().nth(0).unwrap(),
map.keys().nth(1).unwrap()
),
_ => {
let first = fastrand::usize(0..map.len());
let mut second = fastrand::usize(0..map.len());
while second == first {
second = fastrand::usize(0..map.len());
}
format!(
"{}, {}, and...some other things, I think",
map.keys().nth(first).unwrap(),
map.keys().nth(second).unwrap()
)
}
}
}
pub fn format_requirements(&self) -> String {
Self::format_item_map(&self.requirements)
}
pub fn format_production(&self) -> String {
Self::format_item_map(&self.production)
}
pub fn format_rumour(&self, town_name: impl ToString) -> String {
let is_production = fastrand::bool();
if is_production {
let stub = &PRODUCTION_TEMPLATES[fastrand::usize(0..PRODUCTION_TEMPLATES.len())];
let output = stub
.replace("[[TOWN]]", town_name.to_string().as_str())
.replace("[[ITEMS]]", self.format_production().as_str());
output
} else {
let stub = &REQUIREMENT_TEMPLATES[fastrand::usize(0..REQUIREMENT_TEMPLATES.len())];
let output = stub
.replace("[[TOWN]]", town_name.to_string().as_str())
.replace("[[ITEMS]]", self.format_requirements().as_str());
output
}
}
}
pub fn check_specialisms(
mut query: Query<(&mut TradingState, &CraftSpecialism)>,
events: EventReader<WorldTickEvent>,
) {
if !events.is_empty() {
for (mut trading_state, specialism) in &mut query {
specialism.apply_to_inventory(&mut trading_state);
}
}
}