Server event used to deal damage/heal with buffs. Buff kills now award xp.

This commit is contained in:
Sam 2020-10-03 13:48:56 -05:00
parent de7191b985
commit 1a1ceb54bc
11 changed files with 102 additions and 25 deletions

View File

@ -184,6 +184,7 @@ https://account.veloren.net."#,
"hud.chat.pvp_ranged_kill_msg": "[{attacker}] shot [{victim}]",
"hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]",
"hud.chat.pvp_energy_kill_msg": "[{attacker}] used magic to kill [{victim}]",
"hud.chat.pvp_buff_kill_msg": "[{attacker}] killed [{victim}]",
"hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]",
"hud.chat.npc_ranged_kill_msg": "{attacker} shot [{victim}]",

View File

@ -1715,6 +1715,11 @@ impl Client {
alias_of_uid(attacker_uid),
alias_of_uid(victim)
),
KillSource::Player(attacker_uid, KillType::Buff) => format!(
"[{}] killed [{}]",
alias_of_uid(attacker_uid),
alias_of_uid(victim)
),
KillSource::NonPlayer(attacker_name, KillType::Melee) => {
format!("{} killed [{}]", attacker_name, alias_of_uid(victim))
},
@ -1729,6 +1734,9 @@ impl Client {
attacker_name,
alias_of_uid(victim)
),
KillSource::NonPlayer(attacker_name, KillType::Buff) => {
format!("{} killed [{}]", attacker_name, alias_of_uid(victim))
},
KillSource::Environment(environment) => {
format!("[{}] died in {}", alias_of_uid(victim), environment)
},
@ -1754,6 +1762,9 @@ impl Client {
KillSource::Player(attacker_uid, KillType::Energy) => message
.replace("{attacker}", &alias_of_uid(attacker_uid))
.replace("{victim}", &alias_of_uid(victim)),
KillSource::Player(attacker_uid, KillType::Buff) => message
.replace("{attacker}", &alias_of_uid(attacker_uid))
.replace("{victim}", &alias_of_uid(victim)),
KillSource::NonPlayer(attacker_name, KillType::Melee) => message
.replace("{attacker}", attacker_name)
.replace("{victim}", &alias_of_uid(victim)),
@ -1766,6 +1777,9 @@ impl Client {
KillSource::NonPlayer(attacker_name, KillType::Energy) => message
.replace("{attacker}", attacker_name)
.replace("{victim}", &alias_of_uid(victim)),
KillSource::NonPlayer(attacker_name, KillType::Buff) => message
.replace("{attacker}", attacker_name)
.replace("{victim}", &alias_of_uid(victim)),
KillSource::Environment(environment) => message
.replace("{name}", &alias_of_uid(victim))
.replace("{environment}", environment),

View File

@ -16,11 +16,9 @@ use std::time::Duration;
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
pub enum BuffId {
/// Restores health/time for some period
/// Has fields: strength (f32)
Regeneration(f32),
Regeneration { strength: f32 },
/// Lowers health over time for some duration
/// Has fields: strength (f32)
Bleeding(f32),
Bleeding { strength: f32 },
/// Prefixes an entity's name with "Cursed"
/// Currently placeholder buff to show other stuff is possible
Cursed,
@ -73,6 +71,7 @@ pub struct Buff {
pub cat_ids: Vec<BuffCategoryId>,
pub time: Option<Duration>,
pub effects: Vec<BuffEffect>,
pub source: BuffSource,
}
/// Information about whether buff addition or removal was requested.
@ -144,9 +143,14 @@ impl Buffs {
}
impl Buff {
pub fn new(id: BuffId, time: Option<Duration>, cat_ids: Vec<BuffCategoryId>) -> Self {
pub fn new(
id: BuffId,
time: Option<Duration>,
cat_ids: Vec<BuffCategoryId>,
source: BuffSource,
) -> Self {
let effects = match id {
BuffId::Bleeding(strength) => vec![
BuffId::Bleeding { strength } => vec![
BuffEffect::HealthChangeOverTime {
rate: -strength,
accumulated: 0.0,
@ -156,7 +160,7 @@ impl Buff {
prefix: String::from("Injured "),
},
],
BuffId::Regeneration(strength) => vec![BuffEffect::HealthChangeOverTime {
BuffId::Regeneration { strength } => vec![BuffEffect::HealthChangeOverTime {
rate: strength,
accumulated: 0.0,
}],
@ -169,6 +173,7 @@ impl Buff {
cat_ids,
time,
effects,
source,
}
}
}

View File

@ -51,6 +51,7 @@ pub enum KillType {
Projectile,
Explosion,
Energy,
Buff,
// Projectile(String), TODO: add projectile name when available
}

View File

@ -32,7 +32,7 @@ pub use body::{
biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, golem, humanoid, object,
quadruped_low, quadruped_medium, quadruped_small, theropod, AllBodies, Body, BodyData,
};
pub use buff::{Buff, BuffCategoryId, BuffChange, BuffEffect, BuffId, Buffs};
pub use buff::{Buff, BuffCategoryId, BuffChange, BuffEffect, BuffId, BuffSource, Buffs};
pub use character_state::{Attacking, CharacterState, StateUpdate};
pub use chat::{
ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg,

View File

@ -20,6 +20,7 @@ pub enum HealthSource {
Projectile { owner: Option<Uid> },
Explosion { owner: Option<Uid> },
Energy { owner: Option<Uid> },
Buff { owner: Option<Uid> },
Suicide,
World,
Revive,

View File

@ -601,6 +601,7 @@ impl<'a> System<'a> for Sys {
if let comp::HealthSource::Attack { by }
| comp::HealthSource::Projectile { owner: Some(by) }
| comp::HealthSource::Energy { owner: Some(by) }
| comp::HealthSource::Buff { owner: Some(by) }
| comp::HealthSource::Explosion { owner: Some(by) } =
my_stats.health.last_change.1.cause
{

View File

@ -1,10 +1,10 @@
use crate::{
comp::{BuffChange, BuffEffect, Buffs, HealthChange, HealthSource, Stats},
comp::{BuffChange, BuffEffect, BuffSource, Buffs, HealthChange, HealthSource},
event::{EventBus, ServerEvent},
state::DeltaTime,
sync::Uid,
};
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
use specs::{Join, Read, ReadStorage, System, WriteStorage};
use std::time::Duration;
/// This system modifies entity stats, changing them using buffs
@ -16,17 +16,15 @@ pub struct Sys;
impl<'a> System<'a> for Sys {
#[allow(clippy::type_complexity)]
type SystemData = (
Entities<'a>,
Read<'a, DeltaTime>,
Read<'a, EventBus<ServerEvent>>,
ReadStorage<'a, Uid>,
WriteStorage<'a, Stats>,
WriteStorage<'a, Buffs>,
);
fn run(&mut self, (entities, dt, server_bus, uids, mut stats, mut buffs): Self::SystemData) {
fn run(&mut self, (dt, server_bus, uids, mut buffs): Self::SystemData) {
let mut server_emitter = server_bus.emitter();
for (entity, uid, mut buffs) in (&entities, &uids, &mut buffs.restrict_mut()).join() {
for (uid, mut buffs) in (&uids, &mut buffs.restrict_mut()).join() {
let buff_comp = buffs.get_mut_unchecked();
let (mut active_buff_indices_for_removal, mut inactive_buff_indices_for_removal) =
(Vec::<usize>::new(), Vec::<usize>::new());
@ -56,6 +54,12 @@ impl<'a> System<'a> for Sys {
dt.0
};
let buff_owner =
if let BuffSource::Character { by: owner } = buff_comp.active_buffs[i].source {
Some(owner)
} else {
None
};
// Now, execute the buff, based on it's delta
for effect in &mut buff_comp.active_buffs[i].effects {
#[allow(clippy::single_match)]
@ -66,13 +70,18 @@ impl<'a> System<'a> for Sys {
*accumulated += *rate * buff_delta;
// Apply only 0.5 or higher damage
if accumulated.abs() > 5.0 {
if let Some(stats) = stats.get_mut(entity) {
let change = HealthChange {
let cause = if *accumulated > 0.0 {
HealthSource::Healing { by: buff_owner }
} else {
HealthSource::Buff { owner: buff_owner }
};
server_emitter.emit(ServerEvent::Damage {
uid: *uid,
change: HealthChange {
amount: *accumulated as i32,
cause: HealthSource::Unknown,
};
stats.health.change_by(change);
}
cause,
},
});
*accumulated = 0.0;
};
},

View File

@ -155,9 +155,12 @@ impl<'a> System<'a> for Sys {
server_emitter.emit(ServerEvent::Buff {
uid: *uid_b,
buff_change: buff::BuffChange::Add(buff::Buff::new(
buff::BuffId::Bleeding(-damage.healthchange),
buff::BuffId::Bleeding {
strength: -damage.healthchange,
},
Some(Duration::from_millis(10000)),
vec![buff::BuffCategoryId::Physical],
buff::BuffSource::Character { by: *uid },
)),
});
attack.hit_count += 1;

View File

@ -166,11 +166,34 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
KillSource::NonPlayer("<?>".to_string(), KillType::Energy)
}
},
HealthSource::Buff { owner: Some(by) } => {
// Get energy owner entity
if let Some(char_entity) = state.ecs().entity_from_uid(by.into()) {
// Check if attacker is another player or entity with stats (npc)
if state
.ecs()
.read_storage::<Player>()
.get(char_entity)
.is_some()
{
KillSource::Player(by, KillType::Buff)
} else if let Some(stats) =
state.ecs().read_storage::<Stats>().get(char_entity)
{
KillSource::NonPlayer(stats.name.clone(), KillType::Buff)
} else {
KillSource::NonPlayer("<?>".to_string(), KillType::Buff)
}
} else {
KillSource::NonPlayer("<?>".to_string(), KillType::Buff)
}
},
HealthSource::World => KillSource::FallDamage,
HealthSource::Suicide => KillSource::Suicide,
HealthSource::Projectile { owner: None }
| HealthSource::Explosion { owner: None }
| HealthSource::Energy { owner: None }
| HealthSource::Buff { owner: None }
| HealthSource::Revive
| HealthSource::Command
| HealthSource::LevelUp
@ -190,6 +213,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
let by = if let HealthSource::Attack { by }
| HealthSource::Projectile { owner: Some(by) }
| HealthSource::Energy { owner: Some(by) }
| HealthSource::Buff { owner: Some(by) }
| HealthSource::Explosion { owner: Some(by) } = cause
{
by
@ -836,15 +860,25 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
fn determine_replace_active_buff(active_buff: buff::Buff, new_buff: buff::Buff) -> bool {
use buff::BuffId;
match new_buff.id {
BuffId::Bleeding(new_strength) => {
if let BuffId::Bleeding(active_strength) = active_buff.id {
BuffId::Bleeding {
strength: new_strength,
} => {
if let BuffId::Bleeding {
strength: active_strength,
} = active_buff.id
{
new_strength > active_strength
} else {
false
}
},
BuffId::Regeneration(new_strength) => {
if let BuffId::Regeneration(active_strength) = active_buff.id {
BuffId::Regeneration {
strength: new_strength,
} => {
if let BuffId::Regeneration {
strength: active_strength,
} = active_buff.id
{
new_strength > active_strength
} else {
false

View File

@ -373,6 +373,10 @@ impl<'a> Widget for Chat<'a> {
.localized_strings
.get("hud.chat.pvp_energy_kill_msg")
.to_string(),
KillSource::Player(_, KillType::Buff) => self
.localized_strings
.get("hud.chat.pvp_buff_kill_msg")
.to_string(),
KillSource::NonPlayer(_, KillType::Melee) => self
.localized_strings
.get("hud.chat.npc_melee_kill_msg")
@ -389,6 +393,10 @@ impl<'a> Widget for Chat<'a> {
.localized_strings
.get("hud.chat.npc_energy_kill_msg")
.to_string(),
KillSource::NonPlayer(_, KillType::Buff) => self
.localized_strings
.get("hud.chat.npc_buff_kill_msg")
.to_string(),
KillSource::Environment(_) => self
.localized_strings
.get("hud.chat.environmental_kill_msg")