intrinsic speed + regeneration

This commit is contained in:
Llywelwyn 2023-09-21 05:06:52 +01:00
parent e8b5f6d997
commit 921fee2ecc
7 changed files with 78 additions and 10 deletions

View file

@ -10,6 +10,7 @@ use crate::{
Map, Map,
TakingTurn, TakingTurn,
Confusion, Confusion,
Intrinsics,
}; };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
@ -36,6 +37,7 @@ impl<'a> System<'a> for EnergySystem {
ReadStorage<'a, Name>, ReadStorage<'a, Name>,
ReadExpect<'a, Point>, ReadExpect<'a, Point>,
ReadStorage<'a, Confusion>, ReadStorage<'a, Confusion>,
ReadStorage<'a, Intrinsics>,
); );
fn run(&mut self, data: Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
@ -53,6 +55,7 @@ impl<'a> System<'a> for EnergySystem {
names, names,
player_pos, player_pos,
confusion, confusion,
intrinsics,
) = data; ) = data;
// If not ticking, do nothing. // If not ticking, do nothing.
if *runstate != RunState::Ticking { if *runstate != RunState::Ticking {
@ -89,10 +92,12 @@ impl<'a> System<'a> for EnergySystem {
).join() { ).join() {
let burden_modifier = get_burden_modifier(&burdens, entity); let burden_modifier = get_burden_modifier(&burdens, entity);
let overmap_mod = get_overmap_modifier(&map); let overmap_mod = get_overmap_modifier(&map);
let intrinsic_speed = get_intrinsic_speed(&intrinsics, entity);
// Every entity has a POTENTIAL equal to their speed. // Every entity has a POTENTIAL equal to their speed.
let mut energy_potential: i32 = ((energy.speed as f32) * let mut energy_potential: i32 = ((energy.speed as f32) *
burden_modifier * burden_modifier *
overmap_mod) as i32; overmap_mod *
intrinsic_speed) as i32;
// Increment current energy by NORMAL_SPEED for every // Increment current energy by NORMAL_SPEED for every
// whole number of NORMAL_SPEEDS in their POTENTIAL. // whole number of NORMAL_SPEEDS in their POTENTIAL.
while energy_potential >= NORMAL_SPEED { while energy_potential >= NORMAL_SPEED {
@ -162,3 +167,12 @@ fn cull_turn_by_distance(player_pos: &Point, pos: &Position) -> bool {
} }
return false; return false;
} }
fn get_intrinsic_speed(intrinsics: &ReadStorage<Intrinsics>, entity: Entity) -> f32 {
if let Some(intrinsics) = intrinsics.get(entity) {
if intrinsics.list.contains(&crate::Intrinsic::Speed) {
return 4.0 / 3.0;
}
}
return 1.0;
}

View file

@ -9,6 +9,7 @@ use crate::{
Position, Position,
RandomNumberGenerator, RandomNumberGenerator,
TakingTurn, TakingTurn,
Intrinsics,
}; };
use specs::prelude::*; use specs::prelude::*;
use crate::data::events::*; use crate::data::events::*;
@ -36,10 +37,24 @@ impl<'a> System<'a> for RegenSystem {
ReadStorage<'a, HasClass>, ReadStorage<'a, HasClass>,
ReadStorage<'a, Attributes>, ReadStorage<'a, Attributes>,
WriteExpect<'a, RandomNumberGenerator>, WriteExpect<'a, RandomNumberGenerator>,
ReadStorage<'a, Intrinsics>,
ReadExpect<'a, Entity>,
); );
fn run(&mut self, data: Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
let (clock, entities, positions, mut pools, turns, player, classes, attributes, mut rng) = data; let (
clock,
entities,
positions,
mut pools,
turns,
player,
classes,
attributes,
mut rng,
intrinsics,
player_entity,
) = data;
let mut clock_turn = false; let mut clock_turn = false;
for (_e, _c, _t) in (&entities, &clock, &turns).join() { for (_e, _c, _t) in (&entities, &clock, &turns).join() {
clock_turn = true; clock_turn = true;
@ -56,19 +71,29 @@ impl<'a> System<'a> for RegenSystem {
} }
// Player HP regen // Player HP regen
let level = gamelog::get_event_count(EVENT::COUNT_LEVEL); let level = gamelog::get_event_count(EVENT::COUNT_LEVEL);
if current_turn % get_player_hp_regen_turn(level) == 0 { if
current_turn % get_player_hp_regen_turn(level) == 0 ||
intrinsics.get(*player_entity).unwrap().list.contains(&crate::Intrinsic::Regeneration)
{
for (_e, _p, pool, _player) in (&entities, &positions, &mut pools, &player).join() { for (_e, _p, pool, _player) in (&entities, &positions, &mut pools, &player).join() {
try_hp_regen_tick(pool, get_player_hp_regen_per_tick(level)); try_hp_regen_tick(pool, get_player_hp_regen_per_tick(level));
} }
} }
// Both MP regen // Both MP regen
for (e, _p, pool) in (&entities, &positions, &mut pools).join() { for (e, _p, pool) in (&entities, &positions, &mut pools).join() {
let is_wizard = if let Some(class) = classes.get(e) { class.name == Class::Wizard } else { false }; let is_wizard = if let Some(class) = classes.get(e) {
class.name == Class::Wizard
} else {
false
};
let numerator = if is_wizard { WIZARD_MP_REGEN_MOD } else { NONWIZARD_MP_REGEN_MOD }; let numerator = if is_wizard { WIZARD_MP_REGEN_MOD } else { NONWIZARD_MP_REGEN_MOD };
let multiplier: f32 = (numerator as f32) / (MP_REGEN_DIVISOR as f32); let multiplier: f32 = (numerator as f32) / (MP_REGEN_DIVISOR as f32);
let mp_regen_tick = (((MP_REGEN_BASE - pool.level) as f32) * multiplier) as i32; let mp_regen_tick = (((MP_REGEN_BASE - pool.level) as f32) * multiplier) as i32;
if current_turn % mp_regen_tick == 0 { if current_turn % mp_regen_tick == 0 {
try_mana_regen_tick(pool, rng.roll_dice(1, get_mana_regen_per_tick(e, &attributes))); try_mana_regen_tick(
pool,
rng.roll_dice(1, get_mana_regen_per_tick(e, &attributes))
);
} }
} }
} }

View file

@ -6,7 +6,7 @@ use specs::error::NoError;
use specs::prelude::*; use specs::prelude::*;
use specs::saveload::{ ConvertSaveload, Marker }; use specs::saveload::{ ConvertSaveload, Marker };
use specs_derive::*; use specs_derive::*;
use std::collections::HashMap; use std::collections::{ HashMap, HashSet };
// 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.
@ -418,6 +418,17 @@ impl HasDamageModifiers {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Intrinsic {
Regeneration, // Regenerate 1 HP on every tick
Speed, // 4/3x speed multiplier
}
#[derive(Component, Serialize, Deserialize, Debug, Clone)]
pub struct Intrinsics {
pub list: HashSet<Intrinsic>,
}
#[derive(Component, Debug, ConvertSaveload, Clone)] #[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct InflictsDamage { pub struct InflictsDamage {
pub damage_type: DamageType, pub damage_type: DamageType,

View file

@ -6,6 +6,7 @@ use super::{
HungerState, HungerState,
TakingTurn, TakingTurn,
DamageType, DamageType,
Intrinsics,
}; };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
@ -53,10 +54,11 @@ impl<'a> System<'a> for HungerSystem {
ReadExpect<'a, Entity>, ReadExpect<'a, Entity>,
ReadStorage<'a, Clock>, ReadStorage<'a, Clock>,
ReadStorage<'a, TakingTurn>, ReadStorage<'a, TakingTurn>,
ReadStorage<'a, Intrinsics>,
); );
fn run(&mut self, data: Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
let (entities, mut hunger_clock, player_entity, turn_clock, turns) = data; let (entities, mut hunger_clock, player_entity, turn_clock, turns, intrinsics) = data;
// If the turn clock isn't taking a turn this tick, don't bother ticking hunger. // If the turn clock isn't taking a turn this tick, don't bother ticking hunger.
let mut ticked = false; let mut ticked = false;
@ -72,7 +74,16 @@ impl<'a> System<'a> for HungerSystem {
if hunger_clock.duration >= MAX_SATIATION { if hunger_clock.duration >= MAX_SATIATION {
hunger_clock.duration = MAX_SATIATION; hunger_clock.duration = MAX_SATIATION;
} else { } else {
hunger_clock.duration -= BASE_CLOCK_DECREMENT_PER_TURN; let mut modifier = 0;
let intrinsic_regen = if let Some(i) = intrinsics.get(entity) {
i.list.contains(&crate::Intrinsic::Regeneration)
} else {
false
};
if intrinsic_regen {
modifier += 1;
}
hunger_clock.duration -= BASE_CLOCK_DECREMENT_PER_TURN + modifier;
} }
let initial_state = hunger_clock.state; let initial_state = hunger_clock.state;
hunger_clock.state = get_hunger_state(hunger_clock.duration); hunger_clock.state = get_hunger_state(hunger_clock.duration);

View file

@ -110,6 +110,7 @@ fn main() -> BError {
gs.ecs.register::<SpawnParticleBurst>(); gs.ecs.register::<SpawnParticleBurst>();
gs.ecs.register::<SpawnParticleLine>(); gs.ecs.register::<SpawnParticleLine>();
gs.ecs.register::<HasDamageModifiers>(); gs.ecs.register::<HasDamageModifiers>();
gs.ecs.register::<Intrinsics>();
gs.ecs.register::<SimpleMarker<SerializeMe>>(); gs.ecs.register::<SimpleMarker<SerializeMe>>();
gs.ecs.register::<SerializationHelper>(); gs.ecs.register::<SerializationHelper>();
gs.ecs.register::<DMSerializationHelper>(); gs.ecs.register::<DMSerializationHelper>();

View file

@ -95,6 +95,7 @@ pub fn save_game(ecs: &mut World) {
IdentifiedItem, IdentifiedItem,
InBackpack, InBackpack,
InflictsDamage, InflictsDamage,
Intrinsics,
Item, Item,
KnownSpells, KnownSpells,
LootTable, LootTable,
@ -226,6 +227,7 @@ pub fn load_game(ecs: &mut World) {
IdentifiedItem, IdentifiedItem,
InBackpack, InBackpack,
InflictsDamage, InflictsDamage,
Intrinsics,
Item, Item,
KnownSpells, KnownSpells,
LootTable, LootTable,

View file

@ -25,6 +25,8 @@ use super::{
Viewshed, Viewshed,
BlocksTile, BlocksTile,
Bleeds, Bleeds,
HasDamageModifiers,
Intrinsics,
}; };
use crate::data::entity; use crate::data::entity;
use crate::data::visuals::BLOODSTAIN_COLOUR; use crate::data::visuals::BLOODSTAIN_COLOUR;
@ -32,7 +34,7 @@ use crate::gamesystem::*;
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
use specs::saveload::{ MarkedBuilder, SimpleMarker }; use specs::saveload::{ MarkedBuilder, SimpleMarker };
use std::collections::HashMap; use std::collections::{ HashMap, HashSet };
/// Spawns the player and returns his/her entity object. /// Spawns the player and returns his/her entity object.
pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity { pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
@ -86,7 +88,9 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
weight: 0.0, weight: 0.0,
god: false, god: false,
}) })
.with(EquipmentChanged {}) .with(HasDamageModifiers { modifiers: HashMap::new() })
.with(Intrinsics { list: HashSet::new() })
.with(EquipmentChanged {}) // To force re-calc of equipment bonuses.
.with(skills) .with(skills)
.with(Energy { current: 0, speed: entity::NORMAL_SPEED }) .with(Energy { current: 0, speed: entity::NORMAL_SPEED })
.marked::<SimpleMarker<SerializeMe>>() .marked::<SimpleMarker<SerializeMe>>()