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 { impl Name {
pub fn new<S: ToString>(s: S) -> Self { pub fn from<S: ToString>(s: S) -> Self {
Name { Name {
name: s.to_string(), name: s.to_string(),
} }
@ -193,6 +193,9 @@ pub struct HungerClock {
pub duration: i32, 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 // Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an
// Entity. // Entity.

View File

@ -8,4 +8,8 @@ impl GameLog {
entries: vec![first_entry.to_string()], 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>, WriteStorage<'a, InBackpack>,
WriteExpect<'a, ParticleBuilder>, WriteExpect<'a, ParticleBuilder>,
ReadStorage<'a, Position>, ReadStorage<'a, Position>,
ReadStorage<'a, ProvidesFood>,
WriteStorage<'a, HungerClock>,
); );
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
@ -89,6 +91,8 @@ impl<'a> System<'a> for ItemUseSystem {
mut backpack, mut backpack,
mut particle_builder, mut particle_builder,
positions, positions,
provides_food,
mut hunger_clocks,
) = data; ) = data;
for (entity, useitem) in (&entities, &wants_use).join() { 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 // If the item heals, apply the healing
match healing.get(useitem.item) { match healing.get(useitem.item) {
None => {} None => {}

View File

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

View File

@ -9,7 +9,7 @@ use std::fs::File;
use std::path::Path; use std::path::Path;
macro_rules! serialize_individually { 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( SerializeComponents::<NoError, SimpleMarker<SerializeMe>>::serialize(
&( $ecs.read_storage::<$type>(), ), &( $ecs.read_storage::<$type>(), ),
@ -76,7 +76,8 @@ pub fn save_game(ecs: &mut World) {
DefenseBonus, DefenseBonus,
WantsToRemoveItem, WantsToRemoveItem,
ParticleLifetime, ParticleLifetime,
HungerClock HungerClock,
ProvidesFood,
); );
} }
@ -90,7 +91,7 @@ pub fn does_save_exist() -> bool {
} }
macro_rules! deserialize_individually { macro_rules! deserialize_individually {
($ecs:expr, $de:expr, $data:expr, $( $type:ty),*) => { ($ecs:expr, $de:expr, $data:expr, $( $type:ty),*,) => {
$( $(
DeserializeComponents::<NoError, _>::deserialize( DeserializeComponents::<NoError, _>::deserialize(
&mut ( &mut $ecs.write_storage::<$type>(), ), &mut ( &mut $ecs.write_storage::<$type>(), ),
@ -159,7 +160,8 @@ pub fn load_game(ecs: &mut World) {
DefenseBonus, DefenseBonus,
WantsToRemoveItem, WantsToRemoveItem,
ParticleLifetime, 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(Player {})
.with(Viewshed::default()) .with(Viewshed::default())
.with(Name::new("Player")) .with(Name::from("Player"))
.with(CombatStats { .with(CombatStats {
max_hp: 30, max_hp: 30,
hp: 30, hp: 30,
@ -49,6 +49,7 @@ fn room_table(map_depth: i32) -> RandomTable {
.add("Shield", 3) .add("Shield", 3)
.add("Longsword", map_depth - 1) .add("Longsword", map_depth - 1)
.add("Tower Shield", map_depth - 1) .add("Tower Shield", map_depth - 1)
.add("Rations", 10)
} }
/// fills a room with stuff! /// 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), "Shield" => shield(ecs, x, y),
"Longsword" => longsword(ecs, x, y), "Longsword" => longsword(ecs, x, y),
"Tower Shield" => tower_shield(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(Viewshed::default())
.with(Monster {}) .with(Monster {})
.with(Name::new(name)) .with(Name::from(name))
.with(BlocksTile {}) .with(BlocksTile {})
.with(CombatStats { .with(CombatStats {
max_hp: 16, max_hp: 16,
@ -142,7 +144,7 @@ fn health_potion(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Health Potion")) .with(Name::from("Health Potion"))
.with(Item {}) .with(Item {})
.with(Consumable {}) .with(Consumable {})
.with(ProvidesHealing { heal_amount: 8 }) .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), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Magic Missile Scroll")) .with(Name::from("Magic Missile Scroll"))
.with(Item {}) .with(Item {})
.with(Consumable {}) .with(Consumable {})
.with(Ranged { range: 6 }) .with(Ranged { range: 6 })
@ -177,7 +179,7 @@ fn fireball_scroll(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Fireball Scroll")) .with(Name::from("Fireball Scroll"))
.with(Item {}) .with(Item {})
.with(Consumable {}) .with(Consumable {})
.with(Ranged { range: 6 }) .with(Ranged { range: 6 })
@ -196,7 +198,7 @@ fn confusion_scroll(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Confusion Scroll")) .with(Name::from("Confusion Scroll"))
.with(Item {}) .with(Item {})
.with(Consumable {}) .with(Consumable {})
.with(Ranged { range: 6 }) .with(Ranged { range: 6 })
@ -214,7 +216,7 @@ fn dagger(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Dagger")) .with(Name::from("Dagger"))
.with(Item {}) .with(Item {})
.with(Equippable { .with(Equippable {
slot: EquipmentSlot::Melee, slot: EquipmentSlot::Melee,
@ -233,7 +235,7 @@ fn shield(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Shield")) .with(Name::from("Shield"))
.with(Item {}) .with(Item {})
.with(Equippable { .with(Equippable {
slot: EquipmentSlot::Shield, slot: EquipmentSlot::Shield,
@ -252,7 +254,7 @@ fn longsword(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Longsword")) .with(Name::from("Longsword"))
.with(Item {}) .with(Item {})
.with(Equippable { .with(Equippable {
slot: EquipmentSlot::Melee, slot: EquipmentSlot::Melee,
@ -271,7 +273,7 @@ fn tower_shield(ecs: &mut World, x: i32, y: i32) {
bg: RGB::named(rltk::BLACK), bg: RGB::named(rltk::BLACK),
render_order: 2, render_order: 2,
}) })
.with(Name::new("Tower Shield")) .with(Name::from("Tower Shield"))
.with(Item {}) .with(Item {})
.with(Equippable { .with(Equippable {
slot: EquipmentSlot::Shield, slot: EquipmentSlot::Shield,
@ -280,3 +282,20 @@ fn tower_shield(ecs: &mut World, x: i32, y: i32) {
.marked::<SimpleMarker<SerializeMe>>() .marked::<SimpleMarker<SerializeMe>>()
.build(); .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();
}