mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Server event used to deal damage/heal with buffs. Buff kills now award xp.
This commit is contained in:
parent
de7191b985
commit
1a1ceb54bc
@ -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}]",
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ pub enum KillType {
|
||||
Projectile,
|
||||
Explosion,
|
||||
Energy,
|
||||
Buff,
|
||||
// Projectile(String), TODO: add projectile name when available
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
};
|
||||
},
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user