Skip to content

Commit c20d5c2

Browse files
author
Tomasz Sterna
committed
Gaining experience points
1 parent ce3c18b commit c20d5c2

File tree

7 files changed

+84
-22
lines changed

7 files changed

+84
-22
lines changed

src/components.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,24 @@ pub struct WantsToMelee {
5454
#[derive(TypeUuid, Clone, Debug, PartialEq, Serialize, Deserialize)]
5555
#[uuid = "56a6359c-d947-438a-a13f-dfe65174cb6d"]
5656
pub struct SufferDamage {
57-
pub amount: Vec<i32>,
57+
pub amount: Vec<(i32, bool)>,
5858
}
5959

6060
impl SufferDamage {
61-
pub fn new_damage(command_buffer: &CommandBuffer, victim: Entity, amount: i32) {
61+
pub fn new_damage(
62+
command_buffer: &CommandBuffer,
63+
victim: Entity,
64+
amount: i32,
65+
from_player: bool,
66+
) {
6267
command_buffer.exec_mut(move |world| {
6368
let mut dmg = if let Some(suffering) = world.get_component::<SufferDamage>(victim) {
6469
(*suffering).clone()
6570
} else {
6671
SufferDamage { amount: Vec::new() }
6772
};
6873

69-
dmg.amount.push(amount);
74+
dmg.amount.push((amount, from_player));
7075
world
7176
.add_component(victim, dmg)
7277
.expect("Unable to insert damage");

src/damage_system.rs

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{
2-
gamelog::GameLog, Equipped, InBackpack, LootTable, Map, Name, Player, Pools, Position,
3-
RunState, SufferDamage,
2+
gamelog::GameLog, mana_at_level, player_hp_at_level, Attributes, Equipped, InBackpack,
3+
LootTable, Map, Name, Player, Pools, Position, RunState, SufferDamage,
44
};
55
use crate::prefabs::{get_item_drop, spawn_named_item, SpawnType, PREFABS};
66
use legion::prelude::*;
@@ -11,21 +11,55 @@ pub fn build() -> Box<(dyn Schedulable + 'static)> {
1111
.write_component::<Pools>()
1212
.read_component::<Position>()
1313
.write_resource::<Map>()
14-
.build(|command_buffer, world, map, query| unsafe {
15-
for (entity, mut damage) in query.iter_entities_unchecked(world) {
16-
if let Some(mut stats) = world.get_component_mut_unchecked::<Pools>(entity) {
17-
stats.hit_points.current -= damage.amount.iter().sum::<i32>();
18-
}
14+
.read_resource::<Entity>()
15+
.read_component::<Attributes>()
16+
.build(
17+
|command_buffer, world, (map, player_entity), query| unsafe {
18+
let mut xp_gain = 0;
19+
for (entity, mut damage) in query.iter_entities_unchecked(world) {
20+
if let Some(mut stats) = world.get_component_mut_unchecked::<Pools>(entity) {
21+
for (dmg, from_player) in damage.amount.iter() {
22+
stats.hit_points.current -= dmg;
23+
24+
if stats.hit_points.current < 1 && *from_player {
25+
xp_gain += stats.level * 100;
26+
}
27+
}
28+
29+
if let Some(pos) = world.get_component::<Position>(entity) {
30+
let idx = map.xy_idx(pos.x, pos.y);
31+
map.bloodstains.insert(idx);
32+
}
33+
}
1934

20-
if let Some(pos) = world.get_component::<Position>(entity) {
21-
let idx = map.xy_idx(pos.x, pos.y);
22-
map.bloodstains.insert(idx);
35+
damage.amount.clear();
36+
command_buffer.remove_component::<SufferDamage>(entity);
2337
}
2438

25-
damage.amount.clear();
26-
command_buffer.remove_component::<SufferDamage>(entity);
27-
}
28-
})
39+
if xp_gain != 0 {
40+
let player_attributes =
41+
*(world.get_component::<Attributes>(**player_entity).unwrap());
42+
let mut player_stats =
43+
world.get_component_mut::<Pools>(**player_entity).unwrap();
44+
player_stats.experience += xp_gain;
45+
if player_stats.experience >= player_stats.level * 1000 {
46+
// We've gone up a level!
47+
player_stats.level = player_stats.experience / 1000 + 1;
48+
player_stats.hit_points.max = player_hp_at_level(
49+
player_attributes.fitness.base + player_attributes.fitness.modifiers,
50+
player_stats.level,
51+
);
52+
player_stats.hit_points.current = player_stats.hit_points.max;
53+
player_stats.mana.max = mana_at_level(
54+
player_attributes.intelligence.base
55+
+ player_attributes.intelligence.modifiers,
56+
player_stats.level,
57+
);
58+
player_stats.mana.current = player_stats.mana.max;
59+
}
60+
}
61+
},
62+
)
2963
}
3064

3165
pub fn delete_the_dead(world: &mut World, resources: &mut Resources) {

src/gui.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ pub fn draw_ui(world: &World, resources: &Resources, ctx: &mut Rltk) {
6464
stats.hit_points.current, stats.hit_points.max
6565
);
6666
let mana = format!("Mana: {}/{}", stats.mana.current, stats.mana.max);
67+
let xp = format!("Level: {}", stats.level);
6768
ctx.print_color(50, 1, white, black, &health);
6869
ctx.print_color(50, 2, white, black, &mana);
70+
ctx.print_color(50, 3, white, black, &xp);
6971
ctx.draw_bar_horizontal(
7072
64,
7173
1,
@@ -84,6 +86,16 @@ pub fn draw_ui(world: &World, resources: &Resources, ctx: &mut Rltk) {
8486
RGB::named(rltk::BLUE),
8587
RGB::named(rltk::BLACK),
8688
);
89+
let xp_level_start = (stats.level - 1) * 1000;
90+
ctx.draw_bar_horizontal(
91+
64,
92+
3,
93+
14,
94+
stats.experience - xp_level_start,
95+
1000,
96+
RGB::named(rltk::GOLD),
97+
RGB::named(rltk::BLACK),
98+
);
8799

88100
// Attributes
89101
let attr = world.get_component::<Attributes>(*player).unwrap();

src/hunger_system.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub fn build() -> Box<(dyn Schedulable + 'static)> {
5151
.to_string(),
5252
);
5353
}
54-
SufferDamage::new_damage(command_buffer, entity, 1);
54+
SufferDamage::new_damage(command_buffer, entity, 1, false);
5555
}
5656
}
5757
}

src/inventory_system.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ pub fn item_use() -> Box<(dyn Schedulable + 'static)> {
216216
for (target_entity, target_name) in targets.iter() {
217217
let target_entity = *target_entity;
218218
let damage = damages.damage;
219-
SufferDamage::new_damage(command_buffer, target_entity, damage);
219+
SufferDamage::new_damage(command_buffer, target_entity, damage, true);
220220
if let Some(pos) = world.get_component::<Position>(target_entity) {
221221
particle_builder.request(
222222
pos.x,

src/melee_combat_system.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ pub fn build() -> Box<(dyn Schedulable + 'static)> {
1919
.write_resource::<GameLog>()
2020
.write_resource::<ParticleBuilder>()
2121
.write_resource::<RandomNumberGenerator>()
22+
.read_resource::<Entity>()
2223
.build(
2324
|command_buffer,
2425
world,
25-
(log, particle_builder, rng),
26+
(log, particle_builder, rng, player_entity),
2627
(query, query_melee, query_defense)| {
2728
for (entity, (wants_melee, attacker_attributes, attacker_skills, attacker_pools)) in
2829
query.iter_entities(world)
@@ -158,7 +159,12 @@ pub fn build() -> Box<(dyn Schedulable + 'static)> {
158159
+ skill_damage_bonus
159160
+ weapon_damage_bonus,
160161
);
161-
SufferDamage::new_damage(&command_buffer, target, damage);
162+
SufferDamage::new_damage(
163+
&command_buffer,
164+
target,
165+
damage,
166+
entity == **player_entity,
167+
);
162168
log.entries.push(format!(
163169
"{} hits {}, for {} hp.",
164170
&attacker_name, &target_name, damage

src/trigger_system.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ pub fn build() -> Box<(dyn Schedulable + 'static)> {
4040
rltk::to_cp437('‼'),
4141
200.0,
4242
);
43-
SufferDamage::new_damage(command_buffer, entity, damage.damage);
43+
SufferDamage::new_damage(
44+
command_buffer,
45+
entity,
46+
damage.damage,
47+
false,
48+
);
4449
}
4550

4651
// If it is single activation, it needs to be removed

0 commit comments

Comments
 (0)