Add experience and leveling up, completing section 5.11
This commit is contained in:
parent
c787ccfd25
commit
dd894452f3
@ -83,16 +83,21 @@ pub struct WantsToMelee {
|
||||
|
||||
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
||||
pub struct SufferDamage {
|
||||
pub amount: Vec<i32>,
|
||||
pub amount: Vec<(i32, bool)>,
|
||||
}
|
||||
|
||||
impl SufferDamage {
|
||||
pub fn new_damage(store: &mut WriteStorage<SufferDamage>, victim: Entity, amount: i32) {
|
||||
pub fn new_damage(
|
||||
store: &mut WriteStorage<SufferDamage>,
|
||||
victim: Entity,
|
||||
amount: i32,
|
||||
from_player: bool,
|
||||
) {
|
||||
if let Some(suffering) = store.get_mut(victim) {
|
||||
suffering.amount.push(amount);
|
||||
suffering.amount.push((amount, from_player));
|
||||
} else {
|
||||
let dmg = SufferDamage {
|
||||
amount: vec![amount],
|
||||
amount: vec![(amount, from_player)],
|
||||
};
|
||||
store.insert(victim, dmg).expect("Unable to insert damage");
|
||||
}
|
||||
|
@ -1,33 +1,96 @@
|
||||
use ::rltk::RandomNumberGenerator;
|
||||
use ::rltk::{Point, RandomNumberGenerator};
|
||||
use ::specs::prelude::*;
|
||||
use rltk::RGB;
|
||||
|
||||
use crate::components::{
|
||||
Equipped, InBackpack, LootTable, Name, Player, Pools, Position, SufferDamage,
|
||||
Attributes, Equipped, InBackpack, LootTable, Name, Player, Pools, Position, SufferDamage,
|
||||
};
|
||||
use crate::game_log::GameLog;
|
||||
use crate::gamesystem::{mana_at_level, player_hp_at_level};
|
||||
use crate::particle_system::ParticleBuilder;
|
||||
use crate::raws::{get_item_drop, spawn_named_item, SpawnType, RAWS};
|
||||
use crate::{Map, RunState};
|
||||
|
||||
pub struct DamageSystem {}
|
||||
|
||||
impl<'a> System<'a> for DamageSystem {
|
||||
#[allow(clippy::type_complexity)]
|
||||
type SystemData = (
|
||||
WriteStorage<'a, Pools>,
|
||||
WriteStorage<'a, SufferDamage>,
|
||||
ReadStorage<'a, Position>,
|
||||
WriteExpect<'a, Map>,
|
||||
Entities<'a>,
|
||||
ReadExpect<'a, Entity>,
|
||||
ReadStorage<'a, Attributes>,
|
||||
WriteExpect<'a, GameLog>,
|
||||
WriteExpect<'a, ParticleBuilder>,
|
||||
ReadExpect<'a, Point>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (mut stats, mut damage, positions, mut map, entities) = data;
|
||||
let (
|
||||
mut stats,
|
||||
mut damage,
|
||||
positions,
|
||||
mut map,
|
||||
entities,
|
||||
player,
|
||||
attributes,
|
||||
mut log,
|
||||
mut particles,
|
||||
player_pos,
|
||||
) = data;
|
||||
let mut xp_gain = 0;
|
||||
|
||||
for (entity, mut stats, damage) in (&entities, &mut stats, &damage).join() {
|
||||
stats.hit_points.current -= damage.amount.iter().sum::<i32>();
|
||||
for dmg in damage.amount.iter() {
|
||||
stats.hit_points.current -= dmg.0;
|
||||
if let Some(pos) = positions.get(entity) {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
map.bloodstains.insert(idx);
|
||||
}
|
||||
|
||||
if let Some(pos) = positions.get(entity) {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
map.bloodstains.insert(idx);
|
||||
if stats.hit_points.current < 1 && dmg.1 {
|
||||
xp_gain += stats.level * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if xp_gain != 0 {
|
||||
let mut player_stats = stats.get_mut(*player).unwrap();
|
||||
let player_attributes = attributes.get(*player).unwrap();
|
||||
player_stats.xp += xp_gain;
|
||||
if player_stats.xp >= player_stats.level * 1000 {
|
||||
// We've gone up a level!
|
||||
player_stats.level += 1;
|
||||
log.append(format!(
|
||||
"Congratulations, you are now level {}",
|
||||
player_stats.level
|
||||
));
|
||||
player_stats.hit_points.max = player_hp_at_level(
|
||||
player_attributes.fitness.base + player_attributes.fitness.modifiers,
|
||||
player_stats.level,
|
||||
);
|
||||
player_stats.hit_points.current = player_stats.hit_points.max;
|
||||
player_stats.mana.max = mana_at_level(
|
||||
player_attributes.intelligence.base + player_attributes.intelligence.modifiers,
|
||||
player_stats.level,
|
||||
);
|
||||
player_stats.mana.current = player_stats.mana.max;
|
||||
|
||||
for i in 0..10 {
|
||||
if player_pos.y - i > 1 {
|
||||
particles.request(
|
||||
player_pos.x,
|
||||
player_pos.y - 1,
|
||||
RGB::named(rltk::GOLD),
|
||||
RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('░'),
|
||||
400.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
12
src/gui.rs
12
src/gui.rs
@ -82,8 +82,10 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||
"Mana: {}/{}",
|
||||
player_pools.mana.current, player_pools.mana.max
|
||||
);
|
||||
let xp = format!("Level: {}", player_pools.level);
|
||||
ctx.print_color(50, 1, white, black, &health);
|
||||
ctx.print_color(50, 2, white, black, &mana);
|
||||
ctx.print_color(50, 3, white, black, &xp);
|
||||
ctx.draw_bar_horizontal(
|
||||
64,
|
||||
1,
|
||||
@ -102,6 +104,16 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||
RGB::named(rltk::BLUE),
|
||||
RGB::named(rltk::BLACK),
|
||||
);
|
||||
let xp_level_start = (player_pools.level - 1) * 1000;
|
||||
ctx.draw_bar_horizontal(
|
||||
64,
|
||||
3,
|
||||
14,
|
||||
player_pools.xp - xp_level_start,
|
||||
1000,
|
||||
RGB::named(rltk::GOLD),
|
||||
black,
|
||||
);
|
||||
|
||||
// Attributes
|
||||
let attributes = ecs.read_storage::<Attributes>();
|
||||
|
@ -73,7 +73,7 @@ impl<'a> System<'a> for HungerSystem {
|
||||
log.append("Your hunger pangs are getting painful!");
|
||||
}
|
||||
|
||||
SufferDamage::new_damage(&mut inflict_damage, entity, 1);
|
||||
SufferDamage::new_damage(&mut inflict_damage, entity, 1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
||||
used_item = false;
|
||||
|
||||
for mob in targets.iter() {
|
||||
SufferDamage::new_damage(&mut suffer_damage, *mob, damage.damage);
|
||||
SufferDamage::new_damage(&mut suffer_damage, *mob, damage.damage, true);
|
||||
if entity == *player_entity {
|
||||
let mob_name = names.get(*mob).unwrap();
|
||||
let item_name = names.get(useitem.item).unwrap();
|
||||
|
@ -31,6 +31,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||
ReadStorage<'a, MeleeWeapon>,
|
||||
ReadStorage<'a, Wearable>,
|
||||
ReadStorage<'a, NaturalAttackDefense>,
|
||||
ReadExpect<'a, Entity>,
|
||||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
@ -51,6 +52,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||
meleeweapons,
|
||||
wearables,
|
||||
natural,
|
||||
player_entity,
|
||||
) = data;
|
||||
|
||||
for (entity, wants_melee, name, attacker_attributes, attacker_skills, attacker_pools) in (
|
||||
@ -154,7 +156,12 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
||||
+ skill_damage_bonus
|
||||
+ weapon_damage_bonus,
|
||||
);
|
||||
SufferDamage::new_damage(&mut inflict_damage, wants_melee.target, damage);
|
||||
SufferDamage::new_damage(
|
||||
&mut inflict_damage,
|
||||
wants_melee.target,
|
||||
damage,
|
||||
entity == *player_entity,
|
||||
);
|
||||
log.append(format!(
|
||||
"{} hits {} for {} hp.",
|
||||
&name.name, &target_name.name, damage
|
||||
|
@ -77,6 +77,7 @@ impl<'a> System<'a> for TriggerSystem {
|
||||
&mut inflict_damage,
|
||||
entity,
|
||||
damage.damage,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user