mp regeneration
using nethack calcs as a placeholder for now
This commit is contained in:
parent
c46e302274
commit
4118783597
6 changed files with 64 additions and 11 deletions
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::{gamelog, Clock, Player, Pools, Position, TakingTurn};
|
use crate::{
|
||||||
|
gamelog, gui::Class, Attributes, Clock, HasClass, Player, Pools, Position, RandomNumberGenerator, TakingTurn,
|
||||||
|
};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub struct RegenSystem {}
|
pub struct RegenSystem {}
|
||||||
|
|
@ -6,6 +8,12 @@ pub struct RegenSystem {}
|
||||||
const MONSTER_HP_REGEN_TURN: i32 = 20;
|
const MONSTER_HP_REGEN_TURN: i32 = 20;
|
||||||
const MONSTER_HP_REGEN_PER_TICK: i32 = 1;
|
const MONSTER_HP_REGEN_PER_TICK: i32 = 1;
|
||||||
|
|
||||||
|
const WIZARD_MP_REGEN_MOD: i32 = 3;
|
||||||
|
const NONWIZARD_MP_REGEN_MOD: i32 = 4;
|
||||||
|
const MP_REGEN_BASE: i32 = 38;
|
||||||
|
const MP_REGEN_DIVISOR: i32 = 6;
|
||||||
|
const MIN_MP_REGEN_PER_TURN: i32 = 1;
|
||||||
|
|
||||||
impl<'a> System<'a> for RegenSystem {
|
impl<'a> System<'a> for RegenSystem {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
|
|
@ -15,10 +23,13 @@ impl<'a> System<'a> for RegenSystem {
|
||||||
WriteStorage<'a, Pools>,
|
WriteStorage<'a, Pools>,
|
||||||
ReadStorage<'a, TakingTurn>,
|
ReadStorage<'a, TakingTurn>,
|
||||||
ReadStorage<'a, Player>,
|
ReadStorage<'a, Player>,
|
||||||
|
ReadStorage<'a, HasClass>,
|
||||||
|
ReadStorage<'a, Attributes>,
|
||||||
|
WriteExpect<'a, RandomNumberGenerator>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
let (clock, entities, positions, mut pools, turns, player) = data;
|
let (clock, entities, positions, mut pools, turns, player, classes, attributes, mut rng) = 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;
|
||||||
|
|
@ -26,18 +37,30 @@ impl<'a> System<'a> for RegenSystem {
|
||||||
if !clock_turn {
|
if !clock_turn {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Monster HP regen
|
||||||
let current_turn = gamelog::get_event_count("turns");
|
let current_turn = gamelog::get_event_count("turns");
|
||||||
if current_turn % MONSTER_HP_REGEN_TURN == 0 {
|
if current_turn % MONSTER_HP_REGEN_TURN == 0 {
|
||||||
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, MONSTER_HP_REGEN_PER_TICK);
|
try_hp_regen_tick(pool, MONSTER_HP_REGEN_PER_TICK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Player HP regen
|
||||||
let level = gamelog::get_event_count("player_level");
|
let level = gamelog::get_event_count("player_level");
|
||||||
if current_turn % get_player_hp_regen_turn(level) == 0 {
|
if current_turn % get_player_hp_regen_turn(level) == 0 {
|
||||||
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
|
||||||
|
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 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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,3 +83,15 @@ fn get_player_hp_regen_per_tick(level: i32) -> i32 {
|
||||||
fn try_hp_regen_tick(pool: &mut Pools, amount: i32) {
|
fn try_hp_regen_tick(pool: &mut Pools, amount: i32) {
|
||||||
pool.hit_points.current = i32::min(pool.hit_points.current + amount, pool.hit_points.max);
|
pool.hit_points.current = i32::min(pool.hit_points.current + amount, pool.hit_points.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_mana_regen_per_tick(e: Entity, attributes: &ReadStorage<Attributes>) -> i32 {
|
||||||
|
return if let Some(attributes) = attributes.get(e) {
|
||||||
|
((attributes.intelligence.bonus + attributes.wisdom.bonus) / 2) + MIN_MP_REGEN_PER_TURN
|
||||||
|
} else {
|
||||||
|
MIN_MP_REGEN_PER_TURN
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_mana_regen_tick(pool: &mut Pools, amount: i32) {
|
||||||
|
pool.mana.current = i32::min(pool.mana.current + amount, pool.mana.max);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,17 @@ pub struct Skills {
|
||||||
pub skills: HashMap<Skill, i32>,
|
pub skills: HashMap<Skill, i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct KnownSpell {
|
||||||
|
pub display_name: String,
|
||||||
|
pub mana_cost: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct KnownSpells {
|
||||||
|
pub spells: Vec<KnownSpell>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Attributes {
|
pub struct Attributes {
|
||||||
pub strength: Attribute,
|
pub strength: Attribute,
|
||||||
|
|
|
||||||
|
|
@ -284,8 +284,8 @@ pub fn setup_player_class(ecs: &mut World, class: Class, ancestry: Ancestry) {
|
||||||
.insert(
|
.insert(
|
||||||
player,
|
player,
|
||||||
Pools {
|
Pools {
|
||||||
hit_points: Pool { current: 10 + attr_bonus(con), max: 10 + attr_bonus(con) },
|
hit_points: Pool { current: 8 + attr_bonus(con), max: 8 + attr_bonus(con) },
|
||||||
mana: Pool { current: 2 + attr_bonus(int), max: 2 + attr_bonus(int) },
|
mana: Pool { current: 1 + attr_bonus(int), max: 1 + attr_bonus(int) },
|
||||||
xp: 0,
|
xp: 0,
|
||||||
level: 1,
|
level: 1,
|
||||||
bac: 10,
|
bac: 10,
|
||||||
|
|
|
||||||
|
|
@ -659,6 +659,7 @@ fn main() -> rltk::BError {
|
||||||
gs.ecs.register::<MultiAttack>();
|
gs.ecs.register::<MultiAttack>();
|
||||||
gs.ecs.register::<ProvidesRemoveCurse>();
|
gs.ecs.register::<ProvidesRemoveCurse>();
|
||||||
gs.ecs.register::<ProvidesIdentify>();
|
gs.ecs.register::<ProvidesIdentify>();
|
||||||
|
gs.ecs.register::<KnownSpells>();
|
||||||
gs.ecs.register::<ParticleLifetime>();
|
gs.ecs.register::<ParticleLifetime>();
|
||||||
gs.ecs.register::<SpawnParticleSimple>();
|
gs.ecs.register::<SpawnParticleSimple>();
|
||||||
gs.ecs.register::<SpawnParticleBurst>();
|
gs.ecs.register::<SpawnParticleBurst>();
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ pub fn save_game(ecs: &mut World) {
|
||||||
InBackpack,
|
InBackpack,
|
||||||
InflictsDamage,
|
InflictsDamage,
|
||||||
Item,
|
Item,
|
||||||
|
KnownSpells,
|
||||||
LootTable,
|
LootTable,
|
||||||
MagicItem,
|
MagicItem,
|
||||||
MagicMapper,
|
MagicMapper,
|
||||||
|
|
@ -209,6 +210,7 @@ pub fn load_game(ecs: &mut World) {
|
||||||
InBackpack,
|
InBackpack,
|
||||||
InflictsDamage,
|
InflictsDamage,
|
||||||
Item,
|
Item,
|
||||||
|
KnownSpells,
|
||||||
LootTable,
|
LootTable,
|
||||||
MagicItem,
|
MagicItem,
|
||||||
MagicMapper,
|
MagicMapper,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use super::{
|
use super::{
|
||||||
ai::NORMAL_SPEED, random_table::RandomTable, raws, Clock, Energy, EquipmentChanged, Faction, HungerClock,
|
ai::NORMAL_SPEED, random_table::RandomTable, raws, Attribute, Attributes, Clock, Energy, EquipmentChanged, Faction,
|
||||||
HungerState, Map, Mind, Name, Player, Position, Rect, Renderable, SerializeMe, Skill, Skills, TileType, Viewshed,
|
HungerClock, HungerState, Map, Mind, Name, Player, Pool, Pools, Position, Rect, Renderable, SerializeMe, Skill,
|
||||||
|
Skills, TileType, Viewshed,
|
||||||
};
|
};
|
||||||
|
use crate::gamesystem::*;
|
||||||
use rltk::{RandomNumberGenerator, RGB};
|
use rltk::{RandomNumberGenerator, RGB};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{MarkedBuilder, SimpleMarker};
|
use specs::saveload::{MarkedBuilder, SimpleMarker};
|
||||||
|
|
@ -13,7 +15,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
skills.skills.insert(Skill::Melee, 0);
|
skills.skills.insert(Skill::Melee, 0);
|
||||||
skills.skills.insert(Skill::Defence, 0);
|
skills.skills.insert(Skill::Defence, 0);
|
||||||
skills.skills.insert(Skill::Magic, 0);
|
skills.skills.insert(Skill::Magic, 0);
|
||||||
|
let (int, con) = (10, 10);
|
||||||
// We only create the player once, so create the Clock here for counting turns too.
|
// We only create the player once, so create the Clock here for counting turns too.
|
||||||
ecs.create_entity().with(Clock {}).with(Energy { current: 0, speed: NORMAL_SPEED }).build();
|
ecs.create_entity().with(Clock {}).with(Energy { current: 0, speed: NORMAL_SPEED }).build();
|
||||||
let player = ecs
|
let player = ecs
|
||||||
|
|
@ -31,7 +33,8 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
|
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
|
||||||
.with(Name { name: "you".to_string(), plural: "you".to_string() })
|
.with(Name { name: "you".to_string(), plural: "you".to_string() })
|
||||||
.with(HungerClock { state: HungerState::Satiated, duration: 1200 })
|
.with(HungerClock { state: HungerState::Satiated, duration: 1200 })
|
||||||
/*.with(Attributes {
|
.with(Attributes {
|
||||||
|
// These are overwritten with chargen later -- placeholders.
|
||||||
strength: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
strength: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
dexterity: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
dexterity: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
constitution: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
constitution: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
|
|
@ -40,14 +43,15 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
charisma: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
charisma: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
})
|
})
|
||||||
.with(Pools {
|
.with(Pools {
|
||||||
hit_points: Pool { current: 10 + attr_bonus(con), max: 10 + attr_bonus(con) },
|
// These are overwritten with chargen later -- placeholders.
|
||||||
mana: Pool { current: 2 + attr_bonus(int), max: 2 + attr_bonus(int) },
|
hit_points: Pool { current: 8 + attr_bonus(con), max: 8 + attr_bonus(con) },
|
||||||
|
mana: Pool { current: 1 + attr_bonus(int), max: 1 + attr_bonus(int) },
|
||||||
xp: 0,
|
xp: 0,
|
||||||
level: 1,
|
level: 1,
|
||||||
bac: 10,
|
bac: 10,
|
||||||
weight: 0.0,
|
weight: 0.0,
|
||||||
god: false,
|
god: false,
|
||||||
})*/
|
})
|
||||||
.with(EquipmentChanged {})
|
.with(EquipmentChanged {})
|
||||||
.with(skills)
|
.with(skills)
|
||||||
.with(Energy { current: 0, speed: NORMAL_SPEED })
|
.with(Energy { current: 0, speed: NORMAL_SPEED })
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue