mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
add maxhealthmodifier
oops variable
This commit is contained in:
parent
8aad7adab8
commit
f759895d63
@ -49,13 +49,19 @@ pub enum BuffCategory {
|
||||
PersistOnDeath,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ModifierKind {
|
||||
Additive,
|
||||
Multiplicative,
|
||||
}
|
||||
|
||||
/// Data indicating and configuring behaviour of a de/buff.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum BuffEffect {
|
||||
/// Periodically damages or heals entity
|
||||
HealthChangeOverTime { rate: f32, accumulated: f32 },
|
||||
/// Changes name on_add/on_remove
|
||||
NameChange { prefix: String },
|
||||
/// Changes maximum health by a certain amount
|
||||
MaxHealthModifier { value: f32, kind: ModifierKind },
|
||||
}
|
||||
|
||||
/// Actual de/buff.
|
||||
@ -125,8 +131,9 @@ impl Buff {
|
||||
data.duration,
|
||||
),
|
||||
BuffKind::Cursed => (
|
||||
vec![BuffEffect::NameChange {
|
||||
prefix: String::from("Cursed "),
|
||||
vec![BuffEffect::MaxHealthModifier {
|
||||
value: -100.,
|
||||
kind: ModifierKind::Additive,
|
||||
}],
|
||||
data.duration,
|
||||
),
|
||||
|
@ -34,6 +34,7 @@ pub use body::{
|
||||
};
|
||||
pub use buff::{
|
||||
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs,
|
||||
ModifierKind,
|
||||
};
|
||||
pub use character_state::{Attacking, CharacterState, StateUpdate};
|
||||
pub use chat::{
|
||||
|
@ -8,6 +8,7 @@ use specs::{Component, FlaggedStorage};
|
||||
use specs_idvs::IdvStorage;
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
/// Specifies what and how much changed current health
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct HealthChange {
|
||||
pub amount: i32,
|
||||
@ -33,6 +34,7 @@ pub enum HealthSource {
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub struct Health {
|
||||
base_max: u32,
|
||||
current: u32,
|
||||
maximum: u32,
|
||||
pub last_change: (f64, HealthChange),
|
||||
@ -69,10 +71,18 @@ impl Health {
|
||||
}
|
||||
|
||||
// This is private because max hp is based on the level
|
||||
fn set_maximum(&mut self, amount: u32) {
|
||||
pub fn set_maximum(&mut self, amount: u32) {
|
||||
self.maximum = amount;
|
||||
self.current = self.current.min(self.maximum);
|
||||
}
|
||||
|
||||
// This is private because max hp is based on the level
|
||||
fn set_base_max(&mut self, amount: u32) {
|
||||
self.base_max = amount;
|
||||
self.current = self.current.min(self.maximum);
|
||||
}
|
||||
|
||||
pub fn reset_max(&mut self) { self.maximum = self.base_max; }
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub enum StatChangeError {
|
||||
@ -149,6 +159,8 @@ impl Stats {
|
||||
|
||||
// TODO: Delete this once stat points will be a thing
|
||||
pub fn update_max_hp(&mut self, body: Body) {
|
||||
self.health
|
||||
.set_base_max(body.base_health() + body.base_health_increase() * self.level.amount);
|
||||
self.health
|
||||
.set_maximum(body.base_health() + body.base_health_increase() * self.level.amount);
|
||||
}
|
||||
@ -180,6 +192,7 @@ impl Stats {
|
||||
health: Health {
|
||||
current: 0,
|
||||
maximum: 0,
|
||||
base_max: 0,
|
||||
last_change: (0.0, HealthChange {
|
||||
amount: 0,
|
||||
cause: HealthSource::Revive,
|
||||
@ -199,6 +212,7 @@ impl Stats {
|
||||
};
|
||||
|
||||
stats.update_max_hp(body);
|
||||
|
||||
stats
|
||||
.health
|
||||
.set_to(stats.health.maximum(), HealthSource::Revive);
|
||||
@ -214,6 +228,7 @@ impl Stats {
|
||||
health: Health {
|
||||
current: 0,
|
||||
maximum: 0,
|
||||
base_max: 0,
|
||||
last_change: (0.0, HealthChange {
|
||||
amount: 0,
|
||||
cause: HealthSource::Revive,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
BuffCategory, BuffChange, BuffEffect, BuffId, BuffSource, Buffs, HealthChange,
|
||||
HealthSource, Stats,
|
||||
HealthSource, ModifierKind, Stats,
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
state::DeltaTime,
|
||||
@ -17,15 +17,15 @@ impl<'a> System<'a> for Sys {
|
||||
Read<'a, DeltaTime>,
|
||||
Read<'a, EventBus<ServerEvent>>,
|
||||
ReadStorage<'a, Uid>,
|
||||
ReadStorage<'a, Stats>,
|
||||
WriteStorage<'a, Stats>,
|
||||
WriteStorage<'a, Buffs>,
|
||||
);
|
||||
|
||||
fn run(&mut self, (dt, server_bus, uids, stats, mut buffs): Self::SystemData) {
|
||||
fn run(&mut self, (dt, server_bus, uids, mut stats, mut buffs): Self::SystemData) {
|
||||
let mut server_emitter = server_bus.emitter();
|
||||
// Set to false to avoid spamming server
|
||||
buffs.set_event_emission(false);
|
||||
for (buff_comp, uid, stat) in (&mut buffs, &uids, &stats).join() {
|
||||
// buffs.set_event_emission(false);
|
||||
for (buff_comp, uid, stat) in (&mut buffs, &uids, &mut stats).join() {
|
||||
let mut expired_buffs = Vec::<BuffId>::new();
|
||||
for (id, buff) in buff_comp.buffs.iter_mut() {
|
||||
// Tick the buff and subtract delta from it
|
||||
@ -36,6 +36,9 @@ impl<'a> System<'a> for Sys {
|
||||
// The buff still continues.
|
||||
*remaining_time = new_duration;
|
||||
} else {
|
||||
// checked_sub returns None when remaining time
|
||||
// went below 0, so set to 0
|
||||
*remaining_time = Duration::default();
|
||||
// The buff has expired.
|
||||
// Remove it.
|
||||
expired_buffs.push(*id);
|
||||
@ -43,14 +46,20 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
|
||||
// Call to reset stats to base values
|
||||
stat.health.reset_max();
|
||||
|
||||
// Iterator over the lists of buffs by kind
|
||||
for buff_ids in buff_comp.kinds.values() {
|
||||
// Get the strongest of this buff kind
|
||||
if let Some(buff) = buff_comp.buffs.get_mut(&buff_ids[0]) {
|
||||
// Get buff owner
|
||||
// Get buff owner?
|
||||
let buff_owner = if let BuffSource::Character { by: owner } = buff.source {
|
||||
Some(owner)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Now, execute the buff, based on it's delta
|
||||
for effect in &mut buff.effects {
|
||||
match effect {
|
||||
@ -77,7 +86,18 @@ impl<'a> System<'a> for Sys {
|
||||
*accumulated = 0.0;
|
||||
};
|
||||
},
|
||||
BuffEffect::NameChange { .. } => {},
|
||||
BuffEffect::MaxHealthModifier { value, kind } => match kind {
|
||||
ModifierKind::Multiplicative => {
|
||||
stat.health.set_maximum(
|
||||
(stat.health.maximum() as f32 * *value) as u32,
|
||||
);
|
||||
},
|
||||
ModifierKind::Additive => {
|
||||
stat.health.set_maximum(
|
||||
(stat.health.maximum() as f32 + *value) as u32,
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -103,6 +123,6 @@ impl<'a> System<'a> for Sys {
|
||||
});
|
||||
}
|
||||
}
|
||||
buffs.set_event_emission(true);
|
||||
// buffs.set_event_emission(true);
|
||||
}
|
||||
}
|
||||
|
@ -152,19 +152,34 @@ impl<'a> System<'a> for Sys {
|
||||
cause,
|
||||
},
|
||||
});
|
||||
|
||||
use buff::*;
|
||||
server_emitter.emit(ServerEvent::Buff {
|
||||
uid: *uid_b,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Cursed,
|
||||
BuffData {
|
||||
strength: attack.base_damage as f32 / 10.0,
|
||||
duration: Some(Duration::from_secs(10)),
|
||||
},
|
||||
vec![BuffCategory::Physical],
|
||||
BuffSource::Character { by: *uid },
|
||||
)),
|
||||
});
|
||||
|
||||
// Apply bleeding buff on melee hits with 10% chance
|
||||
// TODO: Don't have buff uniformly applied on all melee attacks
|
||||
if thread_rng().gen::<f32>() < 0.1 {
|
||||
server_emitter.emit(ServerEvent::Buff {
|
||||
uid: *uid_b,
|
||||
buff_change: buff::BuffChange::Add(buff::Buff::new(
|
||||
buff::BuffKind::Bleeding,
|
||||
buff::BuffData {
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Bleeding,
|
||||
BuffData {
|
||||
strength: attack.base_damage as f32 / 10.0,
|
||||
duration: Some(Duration::from_secs(10)),
|
||||
},
|
||||
vec![buff::BuffCategory::Physical],
|
||||
buff::BuffSource::Character { by: *uid },
|
||||
vec![BuffCategory::Physical],
|
||||
BuffSource::Character { by: *uid },
|
||||
)),
|
||||
});
|
||||
}
|
||||
|
@ -704,7 +704,6 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
|
||||
let mut buffs_all = ecs.write_storage::<comp::Buffs>();
|
||||
if let Some(entity) = ecs.entity_from_uid(uid.into()) {
|
||||
if let Some(buffs) = buffs_all.get_mut(entity) {
|
||||
let mut stats = ecs.write_storage::<comp::Stats>();
|
||||
use buff::BuffChange;
|
||||
match buff_change {
|
||||
BuffChange::Add(new_buff) => {
|
||||
@ -763,36 +762,3 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_buff_effects(buff: buff::Buff, mut stats: Option<&mut Stats>) {
|
||||
for effect in &buff.effects {
|
||||
use buff::BuffEffect;
|
||||
match effect {
|
||||
// Only add an effect here if it is immediate and is not continuous
|
||||
BuffEffect::NameChange { prefix } => {
|
||||
if let Some(ref mut stats) = stats {
|
||||
let mut pref = String::from(prefix);
|
||||
pref.push_str(&stats.name);
|
||||
stats.name = pref;
|
||||
}
|
||||
},
|
||||
BuffEffect::HealthChangeOverTime { .. } => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_buff_effects(buff: buff::Buff, mut stats: Option<&mut Stats>) {
|
||||
for effect in &buff.effects {
|
||||
#[allow(clippy::single_match)] // Remove clippy when there are more buff effects here
|
||||
match effect {
|
||||
// Only remove an effect here if its effect was not continuously
|
||||
// applied
|
||||
buff::BuffEffect::NameChange { prefix } => {
|
||||
if let Some(ref mut stats) = stats {
|
||||
stats.name = stats.name.replacen(prefix, "", 1);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user