refactors hunger system

still works the same way, just cleaner
This commit is contained in:
Llywelwyn 2023-08-20 17:27:11 +01:00
parent 23a6d5e025
commit 454a8c7028
4 changed files with 120 additions and 53 deletions

View file

@ -130,6 +130,7 @@ pub enum HungerState {
Hungry,
Weak,
Fainting,
Starving,
}
#[derive(Component, Serialize, Deserialize, Clone)]

View file

@ -1,8 +1,8 @@
use super::{
ai::CARRY_CAPACITY_PER_STRENGTH, camera, gamelog, gamesystem, rex_assets::RexAssets, ArmourClassBonus, Attributes,
Burden, Charges, Equipped, Hidden, HungerClock, HungerState, InBackpack, MagicItem, MagicItemClass, Map,
MasterDungeonMap, Name, ObfuscatedName, Player, Point, Pools, Position, Prop, Renderable, RunState, Skill, Skills,
State, Viewshed,
ai::CARRY_CAPACITY_PER_STRENGTH, camera, gamelog, gamesystem, hunger_system::get_hunger_colour,
hunger_system::get_hunger_state, rex_assets::RexAssets, ArmourClassBonus, Attributes, Burden, Charges, Equipped,
Hidden, HungerClock, HungerState, InBackpack, MagicItem, MagicItemClass, Map, MasterDungeonMap, Name,
ObfuscatedName, Player, Point, Pools, Position, Prop, Renderable, RunState, Skill, Skills, State, Viewshed,
};
use rltk::prelude::*;
use specs::prelude::*;
@ -113,17 +113,20 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
// Draw hunger
match hunger.state {
HungerState::Satiated => {
ctx.print_color_right(70, 53, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), "Satiated")
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Satiated")
}
HungerState::Normal => {}
HungerState::Hungry => {
ctx.print_color_right(70, 53, RGB::named(rltk::BROWN1), RGB::named(rltk::BLACK), "Hungry")
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Hungry")
}
HungerState::Weak => {
ctx.print_color_right(70, 53, RGB::named(rltk::ORANGE), RGB::named(rltk::BLACK), "Weak")
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Weak")
}
HungerState::Fainting => {
ctx.print_color_right(70, 53, RGB::named(rltk::RED), RGB::named(rltk::BLACK), "Fainting")
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Fainting")
}
HungerState::Starving => {
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Starving")
}
}
// Burden

View file

@ -1,62 +1,125 @@
use super::{
effects::{add_effect, EffectType, Targets},
gamelog, HungerClock, HungerState, LOG_TICKS,
gamelog, Clock, HungerClock, HungerState, TakingTurn, LOG_TICKS,
};
use rltk::prelude::*;
use specs::prelude::*;
/// HungerSystem is in charge of ticking down the hunger clock for entities with a hunger clock,
/// every time the turn clock ticks.
pub struct HungerSystem {}
const MAX_SATIATION: i32 = 2000;
const HUNGER_BREAKPOINTS: [(i32, HungerState); 5] = [
(1000, HungerState::Satiated),
(600, HungerState::Normal),
(400, HungerState::Hungry),
(200, HungerState::Weak),
(0, HungerState::Fainting),
];
const BASE_CLOCK_DECREMENT_PER_TURN: i32 = 4;
pub fn get_hunger_state(duration: i32) -> HungerState {
for (threshold, state) in HUNGER_BREAKPOINTS.iter() {
if duration > *threshold {
return *state;
}
}
return HungerState::Starving;
}
pub fn get_hunger_colour(state: HungerState) -> (u8, u8, u8) {
match state {
HungerState::Satiated => GREEN,
HungerState::Normal => WHITE,
HungerState::Hungry => BROWN1,
HungerState::Weak => ORANGE,
HungerState::Fainting => RED3,
HungerState::Starving => RED,
}
}
impl<'a> System<'a> for HungerSystem {
#[allow(clippy::type_complexity)]
type SystemData = (Entities<'a>, WriteStorage<'a, HungerClock>, ReadExpect<'a, Entity>);
type SystemData = (
Entities<'a>,
WriteStorage<'a, HungerClock>,
ReadExpect<'a, Entity>,
ReadStorage<'a, Clock>,
ReadStorage<'a, TakingTurn>,
);
fn run(&mut self, data: Self::SystemData) {
let (entities, mut hunger_clock, player_entity) = data;
let (entities, mut hunger_clock, player_entity, turn_clock, turns) = data;
for (entity, mut clock) in (&entities, &mut hunger_clock).join() {
// If the turn clock isn't taking a turn this tick, don't bother ticking hunger.
let mut ticked = false;
for (_e, _c, _t) in (&entities, &turn_clock, &turns).join() {
ticked = true;
break;
}
if !ticked {
return;
}
// Otherwise, tick down the hunger clock for all entities with one.
for (entity, mut hunger_clock) in (&entities, &mut hunger_clock).join() {
if hunger_clock.duration >= MAX_SATIATION {
hunger_clock.duration = MAX_SATIATION;
} else {
hunger_clock.duration -= BASE_CLOCK_DECREMENT_PER_TURN;
}
let initial_state = hunger_clock.state;
hunger_clock.state = get_hunger_state(hunger_clock.duration);
if hunger_clock.state == HungerState::Starving {
add_effect(None, EffectType::Damage { amount: 1 }, Targets::Entity { target: entity });
}
if LOG_TICKS && entity == *player_entity {
rltk::console::log(format!("HUNGER SYSTEM: Ticked for player entity. [clock: {}]", clock.duration));
rltk::console::log(format!(
"HUNGER SYSTEM: Ticked for player entity. [clock: {}]",
hunger_clock.duration
));
}
clock.duration -= 1;
if clock.duration > 0 {
return;
if hunger_clock.state == initial_state {
continue;
}
match clock.state {
HungerState::Satiated => {
clock.state = HungerState::Normal;
clock.duration = 1200;
if entity == *player_entity {
gamelog::Logger::new().append("You are no longer satiated.").log();
}
}
HungerState::Normal => {
clock.state = HungerState::Hungry;
clock.duration = 400;
if entity == *player_entity {
gamelog::Logger::new().colour(rltk::BROWN1).append("You feel hungry.").log();
}
}
HungerState::Hungry => {
clock.state = HungerState::Weak;
clock.duration = 200;
if entity == *player_entity {
gamelog::Logger::new().colour(rltk::ORANGE).append("You feel weak with hunger.").log();
}
}
HungerState::Weak => {
clock.state = HungerState::Fainting;
clock.duration = 200;
if entity == *player_entity {
gamelog::Logger::new().colour(rltk::RED).append("You feel hungry enough to faint.").log();
}
}
HungerState::Fainting => {
add_effect(None, EffectType::Damage { amount: 1 }, Targets::Entity { target: entity });
if entity == *player_entity {
gamelog::Logger::new().colour(rltk::RED).append("You can't go on without food...").log();
}
}
if entity != *player_entity {
continue;
}
// Things which only happen to the player.
match hunger_clock.state {
HungerState::Satiated => gamelog::Logger::new()
.append("You feel")
.colour(get_hunger_colour(hunger_clock.state))
.append("satiated")
.colour(WHITE)
.period()
.log(),
HungerState::Normal => {}
HungerState::Hungry => gamelog::Logger::new()
.append("You feel")
.colour(get_hunger_colour(hunger_clock.state))
.append("hungry")
.colour(WHITE)
.period()
.log(),
HungerState::Weak => gamelog::Logger::new()
.append("You feel")
.colour(get_hunger_colour(hunger_clock.state))
.append("weak with hunger")
.colour(WHITE)
.period()
.log(),
HungerState::Fainting => gamelog::Logger::new()
.append("You feel")
.colour(get_hunger_colour(hunger_clock.state))
.append("hungry enough to faint")
.colour(WHITE)
.period()
.log(),
_ => gamelog::Logger::new()
.colour(get_hunger_colour(hunger_clock.state))
.append("You can't go on without food!")
.log(),
}
}
}

View file

@ -39,7 +39,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
.with(Faction { name: "player".to_string() })
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
.with(Name { name: "you".to_string(), plural: "you".to_string() })
.with(HungerClock { state: HungerState::Satiated, duration: 200 })
.with(HungerClock { state: HungerState::Satiated, duration: 1200 })
.with(Attributes {
strength: Attribute { base: str, modifiers: 0, bonus: attr_bonus(str) },
dexterity: Attribute { base: dex, modifiers: 0, bonus: attr_bonus(dex) },