diff --git a/.gitignore b/.gitignore index bd8e6be..1125e13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /target .rustfmt.toml .vscode/* -.gifs/* +docs/gifs/* .savegames/* savegame.json \ No newline at end of file diff --git a/docs/components-list.txt b/docs/components-list.txt new file mode 100644 index 0000000..25063b0 --- /dev/null +++ b/docs/components-list.txt @@ -0,0 +1,33 @@ +AOE { radius: i32 } +BlocksTile {} +CombatStats { max_hp: i32, hp: i32, defence: i32, power: i32 } +Confusion { turns: i32 } +Consumable {} +Cursed {} +DefenceBonus { amount: i32 } +Destructible {} +Equippable { slot: EquipmentSlot } +Equipped { owner: Entity, slot: EquipmentSlot } +HungerClock { state: HungerState, duration: i32 } +InBackpack { owner: Entity } +InflictsDamage { amount: i32 } +Item {} +MagicMapper {} +MeleePowerBonus { amount: i32 } +Mind {} +Monster {} +Name { name: String } +ParticleLifetime { lifetime_ms: f32 } +Player {} +Position { x: i32, y: i32} +ProvidesHealing { amount: i32 } +Ranged { range: i32 } +Renderable { glyph: rltk::FontCharType, fg: RGB, bg: RGB, render_order: i32 } +SufferDamage { amount: i32 } +Telepath { telepath_tiles: Vec, range: i32, dirty: bool } +Viewshed { visible_tiles: Vec, range: i32, dirty: bool } +WantsToDropItem { item: Entity } +WantsToMelee { target: Entity } +WantsToPickupItem { collected_by: Entity, item: Entity } +WantsToRemoveItem { item: Entity } +WantsToUseItem { item: Entity, target: Option(); let players = ecs.read_storage::(); - for (_player, stats) in (&players, &combat_stats).join() { + let hunger = ecs.read_storage::(); + for (_player, stats, hunger) in (&players, &combat_stats, &hunger).join() { let health = format!(" HP {}/{} ", stats.hp, stats.max_hp); ctx.print_color_right(36, 43, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), &health); ctx.draw_bar_horizontal(38, 43, 34, stats.hp, stats.max_hp, RGB::named(rltk::RED), RGB::named(rltk::BLACK)); + match hunger.state { + HungerState::Satiated => { + ctx.print_color_right(72, 42, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "Satiated") + } + HungerState::Normal => {} + HungerState::Hungry => { + ctx.print_color_right(72, 42, RGB::named(rltk::BROWN1), RGB::named(rltk::BLACK), "Hungry") + } + HungerState::Weak => { + ctx.print_color_right(72, 42, RGB::named(rltk::ORANGE), RGB::named(rltk::BLACK), "Weak") + } + HungerState::Fainting => { + ctx.print_color_right(72, 42, RGB::named(rltk::RED), RGB::named(rltk::BLACK), "Fainting") + } + } } // Render the message log at [1, 46], descending, with 6 lines. @@ -36,7 +52,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { // Render mouse cursor let mouse_pos = ctx.mouse_pos(); - ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::MAGENTA)); + ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::YELLOW)); draw_tooltips(ecs, ctx); } diff --git a/src/hunger_system.rs b/src/hunger_system.rs new file mode 100644 index 0000000..fcc0a3a --- /dev/null +++ b/src/hunger_system.rs @@ -0,0 +1,82 @@ +use super::{gamelog, HungerClock, HungerState, RunState, SufferDamage}; +use specs::prelude::*; + +pub struct HungerSystem {} + +impl<'a> System<'a> for HungerSystem { + #[allow(clippy::type_complexity)] + type SystemData = ( + Entities<'a>, + WriteStorage<'a, HungerClock>, + ReadExpect<'a, Entity>, + ReadExpect<'a, RunState>, + WriteStorage<'a, SufferDamage>, + ); + + fn run(&mut self, data: Self::SystemData) { + let (entities, mut hunger_clock, player_entity, runstate, mut inflict_damage) = data; + + for (entity, mut clock) in (&entities, &mut hunger_clock).join() { + let mut proceed = false; + + match *runstate { + RunState::PlayerTurn => { + if entity == *player_entity { + proceed = true; + } + } + RunState::MonsterTurn => { + if entity != *player_entity { + proceed = true; + } + } + _ => proceed = false, + } + + if !proceed { + return; + } + clock.duration -= 1; + if clock.duration > 0 { + return; + } + + match clock.state { + HungerState::Satiated => { + clock.state = HungerState::Normal; + clock.duration = 300; + if entity == *player_entity { + gamelog::Logger::new().append("You are no longer satiated.").log(); + } + } + HungerState::Normal => { + clock.state = HungerState::Hungry; + clock.duration = 100; + if entity == *player_entity { + gamelog::Logger::new().colour(rltk::RED).append("You feel hungry.").log(); + } + } + HungerState::Hungry => { + clock.state = HungerState::Weak; + clock.duration = 50; + if entity == *player_entity { + gamelog::Logger::new().colour(rltk::RED).append("You feel weak with hunger.").log(); + } + } + HungerState::Weak => { + clock.state = HungerState::Fainting; + clock.duration = 50; + if entity == *player_entity { + gamelog::Logger::new().colour(rltk::RED).append("You feel hungry enough to faint.").log(); + } + } + HungerState::Fainting => { + SufferDamage::new_damage(&mut inflict_damage, entity, 1); + if entity == *player_entity { + gamelog::Logger::new().colour(rltk::RED).append("You can't go on without food...").log(); + } + } + } + } + } +} diff --git a/src/inventory_system.rs b/src/inventory_system.rs index d0d8ed6..79d23c0 100644 --- a/src/inventory_system.rs +++ b/src/inventory_system.rs @@ -1,8 +1,8 @@ use super::{ - gamelog, CombatStats, Confusion, Consumable, Cursed, Destructible, Equippable, Equipped, InBackpack, - InflictsDamage, MagicMapper, Map, Name, ParticleBuilder, Point, Position, ProvidesHealing, RunState, SufferDamage, - WantsToDropItem, WantsToPickupItem, WantsToRemoveItem, WantsToUseItem, AOE, DEFAULT_PARTICLE_LIFETIME, - LONG_PARTICLE_LIFETIME, + gamelog, CombatStats, Confusion, Consumable, Cursed, Destructible, Equippable, Equipped, HungerClock, HungerState, + InBackpack, InflictsDamage, MagicMapper, Map, Name, ParticleBuilder, Point, Position, ProvidesHealing, + ProvidesNutrition, RunState, SufferDamage, WantsToDropItem, WantsToPickupItem, WantsToRemoveItem, WantsToUseItem, + AOE, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME, }; use specs::prelude::*; @@ -51,6 +51,8 @@ impl<'a> System<'a> for ItemUseSystem { ReadStorage<'a, Destructible>, ReadStorage<'a, Cursed>, ReadStorage<'a, ProvidesHealing>, + ReadStorage<'a, ProvidesNutrition>, + WriteStorage<'a, HungerClock>, WriteStorage<'a, CombatStats>, WriteStorage<'a, SufferDamage>, WriteExpect<'a, ParticleBuilder>, @@ -76,6 +78,8 @@ impl<'a> System<'a> for ItemUseSystem { destructibles, cursed_items, provides_healing, + provides_nutrition, + mut hunger_clock, mut combat_stats, mut suffer_damage, mut particle_builder, @@ -97,8 +101,19 @@ impl<'a> System<'a> for ItemUseSystem { let is_cursed = cursed_items.get(wants_to_use.item); + let mut verb = "use"; + + let is_edible = provides_nutrition.get(wants_to_use.item); + if let Some(_) = is_edible { + verb = "eat"; + } + let item_equippable = equippable.get(wants_to_use.item); + if let Some(_) = item_equippable { + verb = "equip" + } + gamelog::Logger::new() - .append("You use the") + .append(format!("You {} the", verb)) .item_name_n(format!("{}", &item_being_used.name)) .period() .log(); @@ -133,8 +148,7 @@ impl<'a> System<'a> for ItemUseSystem { .append("The") .item_name(&item_being_used.name) .colour(rltk::WHITE) - .append("disobeys!") - .log(); + .append("disobeys!"); } } // AOE @@ -160,15 +174,28 @@ impl<'a> System<'a> for ItemUseSystem { } } + // EDIBLE + match is_edible { + None => {} + Some(_) => { + let target = targets[0]; + let hc = hunger_clock.get_mut(target); + if let Some(hc) = hc { + hc.state = HungerState::Satiated; + hc.duration = 50; + gamelog::Logger::new().append("You eat the").item_name_n(&item_being_used.name).period().log(); + } + } + } + // EQUIPMENT - let item_equippable = equippable.get(wants_to_use.item); match item_equippable { None => {} Some(can_equip) => { let target_slot = can_equip.slot; let target = targets[0]; - // Room any items target has in item's slot + // Remove any items target has in item's slot let mut to_unequip: Vec = Vec::new(); for (item_entity, already_equipped, _name) in (&entities, &equipped, &names).join() { if already_equipped.owner == target && already_equipped.slot == target_slot { @@ -177,8 +204,7 @@ impl<'a> System<'a> for ItemUseSystem { gamelog::Logger::new() .append("You unequip the") .item_name_n(&item_being_used.name) - .period() - .log(); + .period(); } } } @@ -192,13 +218,6 @@ impl<'a> System<'a> for ItemUseSystem { .insert(wants_to_use.item, Equipped { owner: target, slot: target_slot }) .expect("Unable to insert equipped component"); backpack.remove(wants_to_use.item); - if target == *player_entity { - gamelog::Logger::new() - .append("You equip the") - .item_name_n(&item_being_used.name) - .period() - .log(); - } } } diff --git a/src/main.rs b/src/main.rs index adefbbe..61e3cd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ mod map_indexing_system; use map_indexing_system::MapIndexingSystem; mod damage_system; use damage_system::*; +mod hunger_system; mod melee_combat_system; use melee_combat_system::MeleeCombatSystem; mod inventory_system; @@ -81,6 +82,8 @@ impl State { melee_system.run_now(&self.ecs); let mut damage_system = DamageSystem {}; damage_system.run_now(&self.ecs); + let mut hunger_clock = hunger_system::HungerSystem {}; + hunger_clock.run_now(&self.ecs); let mut particle_system = particle_system::ParticleSpawnSystem {}; particle_system.run_now(&self.ecs); self.ecs.maintain(); @@ -484,6 +487,7 @@ fn main() -> rltk::BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); @@ -504,6 +508,7 @@ fn main() -> rltk::BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::>(); diff --git a/src/melee_combat_system.rs b/src/melee_combat_system.rs index 4a35275..a990815 100644 --- a/src/melee_combat_system.rs +++ b/src/melee_combat_system.rs @@ -1,6 +1,6 @@ use super::{ - gamelog, CombatStats, DefenceBonus, Equipped, MeleePowerBonus, Name, ParticleBuilder, Position, SufferDamage, - WantsToMelee, + gamelog, CombatStats, DefenceBonus, Equipped, HungerClock, HungerState, MeleePowerBonus, Name, ParticleBuilder, + Position, SufferDamage, WantsToMelee, }; use specs::prelude::*; @@ -19,6 +19,7 @@ impl<'a> System<'a> for MeleeCombatSystem { ReadStorage<'a, Equipped>, ReadStorage<'a, DefenceBonus>, ReadStorage<'a, MeleePowerBonus>, + ReadStorage<'a, HungerClock>, ); fn run(&mut self, data: Self::SystemData) { @@ -34,6 +35,7 @@ impl<'a> System<'a> for MeleeCombatSystem { equipped, defence_bonuses, melee_power_bonuses, + hunger_clock, ) = data; for (entity, wants_melee, name, stats) in (&entities, &wants_melee, &names, &combat_stats).join() { @@ -59,6 +61,22 @@ impl<'a> System<'a> for MeleeCombatSystem { defensive_bonus += defence_bonus.amount; } } + let hc = hunger_clock.get(entity); + if let Some(hc) = hc { + match hc.state { + HungerState::Satiated => { + offensive_bonus += 1; + } + HungerState::Weak => { + offensive_bonus -= 1; + } + HungerState::Fainting => { + offensive_bonus -= 1; + defensive_bonus -= 1; + } + _ => {} + } + } let damage = i32::max(0, (stats.power + offensive_bonus) - (target_stats.defence + defensive_bonus)); if damage == 0 { diff --git a/src/player.rs b/src/player.rs index e3c768d..bf45278 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,6 +1,6 @@ use super::{ - gamelog, CombatStats, Item, Map, Monster, Name, Player, Position, RunState, State, Telepath, TileType, Viewshed, - WantsToMelee, WantsToPickupItem, MAPHEIGHT, MAPWIDTH, + gamelog, CombatStats, HungerClock, HungerState, Item, Map, Monster, Name, Player, Position, RunState, State, + Telepath, TileType, Viewshed, WantsToMelee, WantsToPickupItem, MAPHEIGHT, MAPWIDTH, }; use rltk::{Point, RandomNumberGenerator, Rltk, VirtualKeyCode}; use specs::prelude::*; @@ -172,8 +172,12 @@ fn skip_turn(ecs: &mut World) -> RunState { let viewshed_components = ecs.read_storage::(); let monsters = ecs.read_storage::(); let worldmap_resource = ecs.fetch::(); + let hunger_clocks = ecs.read_storage::(); + // Default to being able to heal by waiting. let mut can_heal = true; + + // Check viewshed for monsters nearby. If we can see a monster, we can't heal. let viewshed = viewshed_components.get(*player_entity).unwrap(); for tile in viewshed.visible_tiles.iter() { let idx = worldmap_resource.xy_idx(tile.x, tile.y); @@ -188,6 +192,17 @@ fn skip_turn(ecs: &mut World) -> RunState { } } + // Check player's hunger state - if we're hungry or worse, we can't heal. + let player_hunger_clock = hunger_clocks.get(*player_entity); + if let Some(clock) = player_hunger_clock { + match clock.state { + HungerState::Hungry => can_heal = false, + HungerState::Weak => can_heal = false, + HungerState::Fainting => can_heal = false, + _ => {} + } + } + let mut did_heal = false; if can_heal { let mut health_components = ecs.write_storage::(); diff --git a/src/saveload_system.rs b/src/saveload_system.rs index 4c2820c..e72f3fb 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -47,37 +47,40 @@ pub fn save_game(ecs: &mut World) { ecs, serializer, data, - Position, - Renderable, - Player, - Viewshed, - Telepath, - Monster, - Mind, - Name, + AOE, BlocksTile, CombatStats, - SufferDamage, - WantsToMelee, - Item, + Confusion, + Consumable, + Cursed, + DefenceBonus, + Destructible, Equippable, Equipped, - MeleePowerBonus, - DefenceBonus, - Cursed, - Consumable, - Destructible, - Ranged, - InflictsDamage, - AOE, - Confusion, - MagicMapper, - ProvidesHealing, + HungerClock, InBackpack, - WantsToPickupItem, - WantsToUseItem, + InflictsDamage, + Item, + MagicMapper, + MeleePowerBonus, + Mind, + Monster, + Name, + ParticleLifetime, + Player, + Position, + ProvidesHealing, + ProvidesNutrition, + Ranged, + Renderable, + SufferDamage, + Telepath, + Viewshed, WantsToDropItem, + WantsToMelee, + WantsToPickupItem, WantsToRemoveItem, + WantsToUseItem, SerializationHelper ); } @@ -131,37 +134,40 @@ pub fn load_game(ecs: &mut World) { ecs, de, d, - Position, - Renderable, - Player, - Viewshed, - Telepath, - Monster, - Mind, - Name, + AOE, BlocksTile, CombatStats, - SufferDamage, - WantsToMelee, - Item, + Confusion, + Consumable, + Cursed, + DefenceBonus, + Destructible, Equippable, Equipped, - MeleePowerBonus, - DefenceBonus, - Cursed, - Consumable, - Destructible, - Ranged, - InflictsDamage, - AOE, - Confusion, - MagicMapper, - ProvidesHealing, + HungerClock, InBackpack, - WantsToPickupItem, - WantsToUseItem, + InflictsDamage, + Item, + MagicMapper, + MeleePowerBonus, + Mind, + Monster, + Name, + ParticleLifetime, + Player, + Position, + ProvidesHealing, + ProvidesNutrition, + Ranged, + Renderable, + SufferDamage, + Telepath, + Viewshed, WantsToDropItem, + WantsToMelee, + WantsToPickupItem, WantsToRemoveItem, + WantsToUseItem, SerializationHelper ); } diff --git a/src/spawner.rs b/src/spawner.rs index 47884f0..d55a3b3 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -1,7 +1,8 @@ use super::{ random_table::RandomTable, BlocksTile, CombatStats, Confusion, Consumable, Cursed, DefenceBonus, Destructible, - EquipmentSlot, Equippable, InflictsDamage, Item, MagicMapper, MeleePowerBonus, Mind, Monster, Name, Player, - Position, ProvidesHealing, Ranged, Rect, Renderable, SerializeMe, Telepath, Viewshed, AOE, MAPWIDTH, + EquipmentSlot, Equippable, HungerClock, HungerState, InflictsDamage, Item, MagicMapper, MeleePowerBonus, Mind, + Monster, Name, Player, Position, ProvidesHealing, ProvidesNutrition, Ranged, Rect, Renderable, SerializeMe, + Viewshed, AOE, MAPWIDTH, }; use rltk::{console, RandomNumberGenerator, RGB}; use specs::prelude::*; @@ -23,6 +24,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32, player_name: String .with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true }) .with(Name { name: player_name }) .with(CombatStats { max_hp: 8, hp: 8, defence: 0, power: 4 }) + .with(HungerClock { state: HungerState::Satiated, duration: 50 }) .marked::>() .build() } @@ -96,6 +98,7 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) { match category.as_ref() { "mob" => spawn_table = mob_table(map_depth), "item" => spawn_table = item_table(map_depth), + "food" => spawn_table = food_table(map_depth), _ => spawn_table = debug_table(), } spawn_points.insert(idx, spawn_table.roll(&mut rng)); @@ -132,14 +135,16 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) { "magic missile scroll" => magic_missile_scroll(ecs, x, y), "magic map scroll" => magic_map_scroll(ecs, x, y), "cursed magic map scroll" => cursed_magic_map_scroll(ecs, x, y), + // Food + "rations" => rations(ecs, x, y), _ => console::log("Tried to spawn nothing. Bugfix needed!"), } } } -// 3 mobs : 1 item +// 10 mobs : 3 items : 1 food fn category_table() -> RandomTable { - return RandomTable::new().add("mob", 3).add("item", 1); + return RandomTable::new().add("mob", 9).add("item", 3).add("food", 1); } fn debug_table() -> RandomTable { @@ -156,18 +161,18 @@ fn mob_table(map_depth: i32) -> RandomTable { } // 6 equipment : 10 potions : 10 scrolls : 2 cursed scrolls -fn item_table(map_depth: i32) -> RandomTable { +fn item_table(_map_depth: i32) -> RandomTable { return RandomTable::new() // Equipment .add("dagger", 2) - .add("shortsword", map_depth - 1) + .add("shortsword", 2) .add("buckler", 2) .add("shield", 1) // Potions .add("weak health potion", 7) .add("health potion", 3) // Scrolls - .add("fireball scroll", map_depth - 1) + .add("fireball scroll", 1) .add("cursed fireball scroll", 1) .add("confusion scroll", 2) .add("magic missile scroll", 5) @@ -175,12 +180,16 @@ fn item_table(map_depth: i32) -> RandomTable { .add("cursed magic map scroll", 1); } +fn food_table(_map_depth: i32) -> RandomTable { + return RandomTable::new().add("rations", 1); +} + fn health_potion(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437('I'), - fg: RGB::named(rltk::MAGENTA), + glyph: rltk::to_cp437('!'), + fg: RGB::named(rltk::MAGENTA2), bg: RGB::named(rltk::BLACK), render_order: 2, }) @@ -197,7 +206,7 @@ fn weak_health_potion(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437('i'), + glyph: rltk::to_cp437('!'), fg: RGB::named(rltk::MAGENTA), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -237,7 +246,7 @@ fn magic_missile_scroll(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437(')'), + glyph: rltk::to_cp437('?'), fg: RGB::named(rltk::BLUE), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -256,7 +265,7 @@ fn fireball_scroll(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437(')'), + glyph: rltk::to_cp437('?'), fg: RGB::named(rltk::ORANGE), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -276,7 +285,7 @@ fn cursed_fireball_scroll(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437(')'), + glyph: rltk::to_cp437('?'), fg: RGB::named(rltk::ORANGE), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -297,7 +306,7 @@ fn confusion_scroll(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437(')'), + glyph: rltk::to_cp437('?'), fg: RGB::named(rltk::PURPLE), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -316,7 +325,7 @@ fn magic_map_scroll(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437(')'), + glyph: rltk::to_cp437('?'), fg: RGB::named(rltk::ROYALBLUE), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -334,7 +343,7 @@ fn cursed_magic_map_scroll(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437(')'), + glyph: rltk::to_cp437('?'), fg: RGB::named(rltk::ROYALBLUE), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -354,7 +363,7 @@ fn dagger(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437('/'), + glyph: rltk::to_cp437(')'), fg: RGB::named(rltk::GREY), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -370,8 +379,8 @@ fn shortsword(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437('/'), - fg: RGB::named(rltk::GREY), + glyph: rltk::to_cp437(')'), + fg: RGB::named(rltk::LIGHTGREY), bg: RGB::named(rltk::BLACK), render_order: 2, }) @@ -387,7 +396,7 @@ fn buckler(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437('('), + glyph: rltk::to_cp437('['), fg: RGB::named(rltk::GREY), bg: RGB::named(rltk::BLACK), render_order: 2, @@ -404,8 +413,8 @@ fn shield(ecs: &mut World, x: i32, y: i32) { ecs.create_entity() .with(Position { x, y }) .with(Renderable { - glyph: rltk::to_cp437('('), - fg: RGB::named(rltk::GREY), + glyph: rltk::to_cp437('['), + fg: RGB::named(rltk::LIGHTGREY), bg: RGB::named(rltk::BLACK), render_order: 2, }) @@ -417,3 +426,22 @@ fn shield(ecs: &mut World, x: i32, y: i32) { .marked::>() .build(); } + +// FOOD + +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::LIGHT_SALMON), + bg: RGB::named(rltk::BLACK), + render_order: 2, + }) + .with(Name { name: "rations".to_string() }) + .with(Item {}) + .with(ProvidesNutrition {}) + .with(Consumable {}) + .marked::>() + .build(); +}