diff --git a/src/ai/energy_system.rs b/src/ai/energy_system.rs new file mode 100644 index 0000000..68238dd --- /dev/null +++ b/src/ai/energy_system.rs @@ -0,0 +1,51 @@ +use crate::{Energy, Position, RunState, TakingTurn}; +use rltk::prelude::*; +use specs::prelude::*; + +pub struct EnergySystem {} + +const NORMAL_SPEED: i32 = 12; +const TURN_COST: i32 = NORMAL_SPEED * 4; + +impl<'a> System<'a> for EnergySystem { + #[allow(clippy::type_complexity)] + type SystemData = ( + WriteStorage<'a, Energy>, + ReadStorage<'a, Position>, + WriteStorage<'a, TakingTurn>, + Entities<'a>, + WriteExpect<'a, RandomNumberGenerator>, + WriteExpect<'a, RunState>, + ReadExpect<'a, Entity>, + ); + + fn run(&mut self, data: Self::SystemData) { + let (mut energies, positions, mut turns, entities, mut rng, mut runstate, player) = data; + + if *runstate != RunState::MonsterTurn { + return; + } + + turns.clear(); + + for (entity, energy, _pos) in (&entities, &mut energies, &positions).join() { + let mut energy_potential: i32 = energy.speed; + while energy_potential >= NORMAL_SPEED { + energy_potential -= NORMAL_SPEED; + energy.current += NORMAL_SPEED; + } + if energy_potential > 0 { + if rng.roll_dice(1, NORMAL_SPEED) <= energy_potential { + energy.current += NORMAL_SPEED; + } + } + if energy.current >= TURN_COST { + turns.insert(entity, TakingTurn {}).expect("Unable to insert turn."); + energy.current -= TURN_COST; + if entity == *player { + *runstate = RunState::AwaitingInput; + } + } + } + } +} diff --git a/src/ai/mod.rs b/src/ai/mod.rs new file mode 100644 index 0000000..efa6f52 --- /dev/null +++ b/src/ai/mod.rs @@ -0,0 +1,2 @@ +mod energy_system; +pub use energy_system::EnergySystem; diff --git a/src/components.rs b/src/components.rs index 00d17c0..3ff6930 100644 --- a/src/components.rs +++ b/src/components.rs @@ -46,6 +46,15 @@ pub struct LootTable { pub chance: f32, } +#[derive(Component, Debug, Serialize, Deserialize, Clone)] +pub struct Energy { + pub current: i32, + pub speed: i32, +} + +#[derive(Component, Debug, Serialize, Deserialize, Clone)] +pub struct TakingTurn {} + #[derive(Component, Debug, Serialize, Deserialize, Clone)] pub struct Bystander {} diff --git a/src/main.rs b/src/main.rs index a2e90d4..57ab534 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ mod inventory_system; use inventory_system::*; mod particle_system; use particle_system::{ParticleBuilder, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME}; +mod ai; mod gamesystem; mod random_table; mod rex_assets; @@ -533,6 +534,8 @@ 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::(); gs.ecs.register::(); diff --git a/src/raws/mob_structs.rs b/src/raws/mob_structs.rs index 656e69c..68f0ab3 100644 --- a/src/raws/mob_structs.rs +++ b/src/raws/mob_structs.rs @@ -10,6 +10,7 @@ pub struct Mob { pub flags: Option>, pub level: Option, pub bac: Option, + pub speed: Option, pub attacks: Option>, pub attributes: Option, pub skills: Option>, diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index 6892012..87b3d71 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -276,6 +276,9 @@ pub fn spawn_named_mob( } eb = eb.with(attr); + let speed = if mob_template.speed.is_some() { mob_template.speed.unwrap() } else { 12 }; + eb = eb.with(Energy { current: 0, speed: speed }); + let base_mob_level = if mob_template.level.is_some() { mob_template.level.unwrap() } else { 0 }; let mut mob_level = base_mob_level; // If the level difficulty is smaller than the mob's base level, subtract 1; @@ -347,8 +350,11 @@ pub fn spawn_named_mob( } xp_value += mob_level * mob_level; - // if speed > 18, +5 - // if speed > 12, +3 + if speed > 18 { + xp_value += 5; + } else if speed > 12 { + xp_value += 3; + } if mob_bac < 0 { xp_value += 14 + 2 * mob_bac; } else if mob_bac == 0 { diff --git a/src/saveload_system.rs b/src/saveload_system.rs index a53e3da..bf9f90a 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -59,6 +59,7 @@ pub fn save_game(ecs: &mut World) { Destructible, Digger, Door, + Energy, EntityMoved, EntryTrigger, Equippable, @@ -90,6 +91,7 @@ pub fn save_game(ecs: &mut World) { SingleActivation, Skills, SufferDamage, + TakingTurn, Telepath, Viewshed, Wand, @@ -163,6 +165,7 @@ pub fn load_game(ecs: &mut World) { Destructible, Digger, Door, + Energy, EntityMoved, EntryTrigger, Equippable, @@ -194,6 +197,7 @@ pub fn load_game(ecs: &mut World) { SingleActivation, Skills, SufferDamage, + TakingTurn, Telepath, Viewshed, Wand, diff --git a/src/spawner.rs b/src/spawner.rs index 67dd1c9..49fb102 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -1,5 +1,5 @@ use super::{ - gamesystem, gamesystem::attr_bonus, random_table::RandomTable, raws, Attribute, Attributes, HungerClock, + gamesystem, gamesystem::attr_bonus, random_table::RandomTable, raws, Attribute, Attributes, Energy, HungerClock, HungerState, Map, Name, Player, Pool, Pools, Position, Rect, Renderable, SerializeMe, Skill, Skills, TileType, Viewshed, }; @@ -54,6 +54,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity { bac: 10, }) .with(skills) + .with(Energy { current: 0, speed: 12 }) .marked::>() .build();