Add rations, and the ability to eat them

This commit is contained in:
Timothy Warren 2021-11-18 15:25:29 -05:00
parent 7b93ecc26c
commit 81f64b07a6
6 changed files with 67 additions and 15 deletions

View File

@ -48,7 +48,7 @@ pub struct Name {
}
impl Name {
pub fn new<S: ToString>(s: S) -> Self {
pub fn from<S: ToString>(s: S) -> Self {
Name {
name: s.to_string(),
}
@ -193,6 +193,9 @@ pub struct HungerClock {
pub duration: i32,
}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct ProvidesFood {}
// Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an
// Entity.

View File

@ -8,4 +8,8 @@ impl GameLog {
entries: vec![first_entry.to_string()],
}
}
pub fn log<S: ToString>(&mut self, s: S) {
self.entries.push(s.to_string());
}
}

View File

@ -66,6 +66,8 @@ impl<'a> System<'a> for ItemUseSystem {
WriteStorage<'a, InBackpack>,
WriteExpect<'a, ParticleBuilder>,
ReadStorage<'a, Position>,
ReadStorage<'a, ProvidesFood>,
WriteStorage<'a, HungerClock>,
);
#[allow(clippy::cognitive_complexity)]
@ -89,6 +91,8 @@ impl<'a> System<'a> for ItemUseSystem {
mut backpack,
mut particle_builder,
positions,
provides_food,
mut hunger_clocks,
) = data;
for (entity, useitem) in (&entities, &wants_use).join() {
@ -184,6 +188,25 @@ impl<'a> System<'a> for ItemUseSystem {
}
}
// If it is edible, eat it!
match provides_food.get(useitem.item) {
None => {}
Some(_) => {
used_item = true;
let target = targets[0];
if let Some(hc) = hunger_clocks.get_mut(target) {
hc.state = HungerState::WellFed;
hc.duration = 20;
gamelog.entries.push(format!(
"You eat the {}.",
names.get(useitem.item).unwrap().name
));
}
}
}
// If the item heals, apply the healing
match healing.get(useitem.item) {
None => {}

View File

@ -495,6 +495,7 @@ fn main() -> rltk::BError {
WantsToRemoveItem,
ParticleLifetime,
HungerClock,
ProvidesFood,
);
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());

View File

@ -9,7 +9,7 @@ use std::fs::File;
use std::path::Path;
macro_rules! serialize_individually {
($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*) => {
($ecs:expr, $ser:expr, $data:expr, $( $type:ty),*,) => {
$(
SerializeComponents::<NoError, SimpleMarker<SerializeMe>>::serialize(
&( $ecs.read_storage::<$type>(), ),
@ -76,7 +76,8 @@ pub fn save_game(ecs: &mut World) {
DefenseBonus,
WantsToRemoveItem,
ParticleLifetime,
HungerClock
HungerClock,
ProvidesFood,
);
}
@ -90,7 +91,7 @@ pub fn does_save_exist() -> bool {
}
macro_rules! deserialize_individually {
($ecs:expr, $de:expr, $data:expr, $( $type:ty),*) => {
($ecs:expr, $de:expr, $data:expr, $( $type:ty),*,) => {
$(
DeserializeComponents::<NoError, _>::deserialize(
&mut ( &mut $ecs.write_storage::<$type>(), ),
@ -159,7 +160,8 @@ pub fn load_game(ecs: &mut World) {
DefenseBonus,
WantsToRemoveItem,
ParticleLifetime,
HungerClock
HungerClock,
ProvidesFood,
);
}

View File

@ -20,7 +20,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
})
.with(Player {})
.with(Viewshed::default())
.with(Name::new("Player"))
.with(Name::from("Player"))
.with(CombatStats {
max_hp: 30,
hp: 30,
@ -49,6 +49,7 @@ fn room_table(map_depth: i32) -> RandomTable {
.add("Shield", 3)
.add("Longsword", map_depth - 1)
.add("Tower Shield", map_depth - 1)
.add("Rations", 10)
}
/// fills a room with stuff!
@ -97,6 +98,7 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) {
"Shield" => shield(ecs, x, y),
"Longsword" => longsword(ecs, x, y),
"Tower Shield" => tower_shield(ecs, x, y),
"Rations" => rations(ecs, x, y),
_ => {}
}
}
@ -121,7 +123,7 @@ fn monster<S: ToString>(ecs: &mut World, x: i32, y: i32, glyph: rltk::FontCharTy
})
.with(Viewshed::default())
.with(Monster {})
.with(Name::new(name))
.with(Name::from(name))
.with(BlocksTile {})
.with(CombatStats {
max_hp: 16,
@ -142,7 +144,7 @@ fn health_potion(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Health Potion"))
.with(Name::from("Health Potion"))
.with(Item {})
.with(Consumable {})
.with(ProvidesHealing { heal_amount: 8 })
@ -159,7 +161,7 @@ fn magic_missile_scroll(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Magic Missile Scroll"))
.with(Name::from("Magic Missile Scroll"))
.with(Item {})
.with(Consumable {})
.with(Ranged { range: 6 })
@ -177,7 +179,7 @@ fn fireball_scroll(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Fireball Scroll"))
.with(Name::from("Fireball Scroll"))
.with(Item {})
.with(Consumable {})
.with(Ranged { range: 6 })
@ -196,7 +198,7 @@ fn confusion_scroll(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Confusion Scroll"))
.with(Name::from("Confusion Scroll"))
.with(Item {})
.with(Consumable {})
.with(Ranged { range: 6 })
@ -214,7 +216,7 @@ fn dagger(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Dagger"))
.with(Name::from("Dagger"))
.with(Item {})
.with(Equippable {
slot: EquipmentSlot::Melee,
@ -233,7 +235,7 @@ fn shield(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Shield"))
.with(Name::from("Shield"))
.with(Item {})
.with(Equippable {
slot: EquipmentSlot::Shield,
@ -252,7 +254,7 @@ fn longsword(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Longsword"))
.with(Name::from("Longsword"))
.with(Item {})
.with(Equippable {
slot: EquipmentSlot::Melee,
@ -271,7 +273,7 @@ fn tower_shield(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::new("Tower Shield"))
.with(Name::from("Tower Shield"))
.with(Item {})
.with(Equippable {
slot: EquipmentSlot::Shield,
@ -280,3 +282,20 @@ fn tower_shield(ecs: &mut World, x: i32, y: i32) {
.marked::<SimpleMarker<SerializeMe>>()
.build();
}
fn rations(ecs: &mut World, x: i32, y: i32) {
ecs.create_entity()
.with(Position { x, y })
.with(Renderable {
glyph: rltk::to_cp437('%'),
fg: RGB::named(rltk::GREEN),
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name::from("Rations"))
.with(Item {})
.with(ProvidesFood {})
.with(Consumable {})
.marked::<SimpleMarker<SerializeMe>>()
.build();
}