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,
TakingTurn,
Confusion,
Intrinsics,
};
use bracket_lib::prelude::*;
use specs::prelude::*;
@ -36,6 +37,7 @@ impl<'a> System<'a> for EnergySystem {
ReadStorage<'a, Name>,
ReadExpect<'a, Point>,
ReadStorage<'a, Confusion>,
ReadStorage<'a, Intrinsics>,
);
fn run(&mut self, data: Self::SystemData) {
@ -53,6 +55,7 @@ impl<'a> System<'a> for EnergySystem {
names,
player_pos,
confusion,
intrinsics,
) = data;
// If not ticking, do nothing.
if *runstate != RunState::Ticking {
@ -89,10 +92,12 @@ impl<'a> System<'a> for EnergySystem {
).join() {
let burden_modifier = get_burden_modifier(&burdens, entity);
let overmap_mod = get_overmap_modifier(&map);
let intrinsic_speed = get_intrinsic_speed(&intrinsics, entity);
// Every entity has a POTENTIAL equal to their speed.
let mut energy_potential: i32 = ((energy.speed as f32) *
burden_modifier *
overmap_mod) as i32;
overmap_mod *
intrinsic_speed) as i32;
// Increment current energy by NORMAL_SPEED for every
// whole number of NORMAL_SPEEDS in their POTENTIAL.
while energy_potential >= NORMAL_SPEED {
@ -162,3 +167,12 @@ fn cull_turn_by_distance(player_pos: &Point, pos: &Position) -> bool {
}
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,
RandomNumberGenerator,
TakingTurn,
Intrinsics,
};
use specs::prelude::*;
use crate::data::events::*;
@ -36,10 +37,24 @@ impl<'a> System<'a> for RegenSystem {
ReadStorage<'a, HasClass>,
ReadStorage<'a, Attributes>,
WriteExpect<'a, RandomNumberGenerator>,
ReadStorage<'a, Intrinsics>,
ReadExpect<'a, Entity>,
);
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;
for (_e, _c, _t) in (&entities, &clock, &turns).join() {
clock_turn = true;
@ -56,19 +71,29 @@ impl<'a> System<'a> for RegenSystem {
}
// Player HP regen
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() {
try_hp_regen_tick(pool, get_player_hp_regen_per_tick(level));
}
}
// Both MP regen
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 multiplier: f32 = (numerator as f32) / (MP_REGEN_DIVISOR as f32);
let mp_regen_tick = (((MP_REGEN_BASE - pool.level) as f32) * multiplier) as i32;
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::saveload::{ ConvertSaveload, Marker };
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
// 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)]
pub struct InflictsDamage {
pub damage_type: DamageType,

View file

@ -6,6 +6,7 @@ use super::{
HungerState,
TakingTurn,
DamageType,
Intrinsics,
};
use bracket_lib::prelude::*;
use specs::prelude::*;
@ -53,10 +54,11 @@ impl<'a> System<'a> for HungerSystem {
ReadExpect<'a, Entity>,
ReadStorage<'a, Clock>,
ReadStorage<'a, TakingTurn>,
ReadStorage<'a, Intrinsics>,
);
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.
let mut ticked = false;
@ -72,7 +74,16 @@ impl<'a> System<'a> for HungerSystem {
if hunger_clock.duration >= MAX_SATIATION {
hunger_clock.duration = MAX_SATIATION;
} 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;
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::<SpawnParticleLine>();
gs.ecs.register::<HasDamageModifiers>();
gs.ecs.register::<Intrinsics>();
gs.ecs.register::<SimpleMarker<SerializeMe>>();
gs.ecs.register::<SerializationHelper>();
gs.ecs.register::<DMSerializationHelper>();

View file

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

View file

@ -25,6 +25,8 @@ use super::{
Viewshed,
BlocksTile,
Bleeds,
HasDamageModifiers,
Intrinsics,
};
use crate::data::entity;
use crate::data::visuals::BLOODSTAIN_COLOUR;
@ -32,7 +34,7 @@ use crate::gamesystem::*;
use bracket_lib::prelude::*;
use specs::prelude::*;
use specs::saveload::{ MarkedBuilder, SimpleMarker };
use std::collections::HashMap;
use std::collections::{ HashMap, HashSet };
/// Spawns the player and returns his/her entity object.
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,
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(Energy { current: 0, speed: entity::NORMAL_SPEED })
.marked::<SimpleMarker<SerializeMe>>()