mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Addressed more comments. Changed how buffs were sorted so that duration was also taken into account.
This commit is contained in:
@ -2,7 +2,7 @@ use crate::sync::Uid;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, FlaggedStorage};
|
use specs::{Component, FlaggedStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use std::{collections::HashMap, time::Duration};
|
use std::{cmp::Ordering, collections::HashMap, time::Duration};
|
||||||
|
|
||||||
/// De/buff Kind.
|
/// De/buff Kind.
|
||||||
/// This is used to determine what effects a buff will have, as well as
|
/// This is used to determine what effects a buff will have, as well as
|
||||||
@ -132,7 +132,7 @@ impl Buff {
|
|||||||
),
|
),
|
||||||
BuffKind::Cursed => (
|
BuffKind::Cursed => (
|
||||||
vec![BuffEffect::MaxHealthModifier {
|
vec![BuffEffect::MaxHealthModifier {
|
||||||
value: -100.,
|
value: -100. * data.strength,
|
||||||
kind: ModifierKind::Additive,
|
kind: ModifierKind::Additive,
|
||||||
}],
|
}],
|
||||||
data.duration,
|
data.duration,
|
||||||
@ -149,6 +149,34 @@ impl Buff {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Buff {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
if self.data.strength > other.data.strength {
|
||||||
|
Some(Ordering::Greater)
|
||||||
|
} else if self.data.strength < other.data.strength {
|
||||||
|
Some(Ordering::Less)
|
||||||
|
} else if compare_duration(self.time, other.time) {
|
||||||
|
Some(Ordering::Greater)
|
||||||
|
} else if compare_duration(other.time, self.time) {
|
||||||
|
Some(Ordering::Less)
|
||||||
|
} else if self == other {
|
||||||
|
Some(Ordering::Equal)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_duration(a: Option<Duration>, b: Option<Duration>) -> bool {
|
||||||
|
a.map_or(true, |dur_a| b.map_or(false, |dur_b| dur_a > dur_b))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Buff {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.data.strength == other.data.strength || self.time == other.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Source of the de/buff
|
/// Source of the de/buff
|
||||||
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
|
||||||
pub enum BuffSource {
|
pub enum BuffSource {
|
||||||
@ -190,17 +218,13 @@ pub struct Buffs {
|
|||||||
impl Buffs {
|
impl Buffs {
|
||||||
fn sort_kind(&mut self, kind: BuffKind) {
|
fn sort_kind(&mut self, kind: BuffKind) {
|
||||||
if let Some(buff_order) = self.kinds.get_mut(&kind) {
|
if let Some(buff_order) = self.kinds.get_mut(&kind) {
|
||||||
if buff_order.len() == 0 {
|
if buff_order.is_empty() {
|
||||||
self.kinds.remove(&kind);
|
self.kinds.remove(&kind);
|
||||||
} else {
|
} else {
|
||||||
let buffs = &self.buffs;
|
let buffs = &self.buffs;
|
||||||
buff_order.sort_by(|a, b| {
|
// Intentionally sorted in reverse so that the strongest buffs are earlier in
|
||||||
buffs[&b]
|
// the vector
|
||||||
.data
|
buff_order.sort_by(|a, b| buffs[&b].partial_cmp(&buffs[&a]).unwrap());
|
||||||
.strength
|
|
||||||
.partial_cmp(&buffs[&a].data.strength)
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,7 +257,7 @@ impl Buffs {
|
|||||||
self.kinds
|
self.kinds
|
||||||
.get(&kind)
|
.get(&kind)
|
||||||
.map(|ids| ids.iter())
|
.map(|ids| ids.iter())
|
||||||
.unwrap_or((&[]).iter())
|
.unwrap_or_else(|| (&[]).iter())
|
||||||
.map(move |id| (*id, &self.buffs[id]))
|
.map(move |id| (*id, &self.buffs[id]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ pub enum ServerEvent {
|
|||||||
/// Send a chat message to the player from an npc or other player
|
/// Send a chat message to the player from an npc or other player
|
||||||
Chat(comp::UnresolvedChatMsg),
|
Chat(comp::UnresolvedChatMsg),
|
||||||
Buff {
|
Buff {
|
||||||
uid: Uid,
|
entity: EcsEntity,
|
||||||
buff_change: comp::BuffChange,
|
buff_change: comp::BuffChange,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,14 @@ use crate::{
|
|||||||
state::DeltaTime,
|
state::DeltaTime,
|
||||||
sync::Uid,
|
sync::Uid,
|
||||||
};
|
};
|
||||||
use specs::{Join, Read, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
|
Entities<'a>,
|
||||||
Read<'a, DeltaTime>,
|
Read<'a, DeltaTime>,
|
||||||
Read<'a, EventBus<ServerEvent>>,
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
ReadStorage<'a, Uid>,
|
ReadStorage<'a, Uid>,
|
||||||
@ -21,11 +22,11 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Buffs>,
|
WriteStorage<'a, Buffs>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, (dt, server_bus, uids, mut stats, mut buffs): Self::SystemData) {
|
fn run(&mut self, (entities, dt, server_bus, uids, mut stats, mut buffs): Self::SystemData) {
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
// Set to false to avoid spamming server
|
// Set to false to avoid spamming server
|
||||||
// buffs.set_event_emission(false);
|
buffs.set_event_emission(false);
|
||||||
for (buff_comp, uid, stat) in (&mut buffs, &uids, &mut stats).join() {
|
for (entity, buff_comp, uid, stat) in (&entities, &mut buffs, &uids, &mut stats).join() {
|
||||||
let mut expired_buffs = Vec::<BuffId>::new();
|
let mut expired_buffs = Vec::<BuffId>::new();
|
||||||
for (id, buff) in buff_comp.buffs.iter_mut() {
|
for (id, buff) in buff_comp.buffs.iter_mut() {
|
||||||
// Tick the buff and subtract delta from it
|
// Tick the buff and subtract delta from it
|
||||||
@ -63,7 +64,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Now, execute the buff, based on it's delta
|
// Now, execute the buff, based on it's delta
|
||||||
for effect in &mut buff.effects {
|
for effect in &mut buff.effects {
|
||||||
match effect {
|
match effect {
|
||||||
// Only add an effect here if it is continuous or it is not immediate
|
|
||||||
BuffEffect::HealthChangeOverTime { rate, accumulated } => {
|
BuffEffect::HealthChangeOverTime { rate, accumulated } => {
|
||||||
*accumulated += *rate * dt.0;
|
*accumulated += *rate * dt.0;
|
||||||
// Apply damage only once a second (with a minimum of 1 damage), or
|
// Apply damage only once a second (with a minimum of 1 damage), or
|
||||||
@ -106,7 +106,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Remove buffs that expire
|
// Remove buffs that expire
|
||||||
if !expired_buffs.is_empty() {
|
if !expired_buffs.is_empty() {
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
uid: *uid,
|
entity,
|
||||||
buff_change: BuffChange::RemoveById(expired_buffs),
|
buff_change: BuffChange::RemoveById(expired_buffs),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Remove stats that don't persist on death
|
// Remove stats that don't persist on death
|
||||||
if stat.is_dead {
|
if stat.is_dead {
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
uid: *uid,
|
entity,
|
||||||
buff_change: BuffChange::RemoveByCategory {
|
buff_change: BuffChange::RemoveByCategory {
|
||||||
all_required: vec![],
|
all_required: vec![],
|
||||||
any_required: vec![],
|
any_required: vec![],
|
||||||
@ -123,6 +123,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// buffs.set_event_emission(true);
|
buffs.set_event_emission(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,25 +153,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
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
|
// Apply bleeding buff on melee hits with 10% chance
|
||||||
// TODO: Don't have buff uniformly applied on all melee attacks
|
// TODO: Don't have buff uniformly applied on all melee attacks
|
||||||
if thread_rng().gen::<f32>() < 0.1 {
|
if thread_rng().gen::<f32>() < 0.1 {
|
||||||
|
use buff::*;
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
uid: *uid_b,
|
entity: b,
|
||||||
buff_change: BuffChange::Add(Buff::new(
|
buff_change: BuffChange::Add(Buff::new(
|
||||||
BuffKind::Bleeding,
|
BuffKind::Bleeding,
|
||||||
BuffData {
|
BuffData {
|
||||||
|
@ -51,7 +51,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
span!(_guard, "run", "controller::Sys::run");
|
span!(_guard, "run", "controller::Sys::run");
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
|
|
||||||
for (entity, uid, controller, character_state) in
|
for (entity, _uid, controller, character_state) in
|
||||||
(&entities, &uids, &mut controllers, &mut character_states).join()
|
(&entities, &uids, &mut controllers, &mut character_states).join()
|
||||||
{
|
{
|
||||||
let mut inputs = &mut controller.inputs;
|
let mut inputs = &mut controller.inputs;
|
||||||
@ -85,7 +85,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
},
|
},
|
||||||
ControlEvent::RemoveBuff(buff_id) => {
|
ControlEvent::RemoveBuff(buff_id) => {
|
||||||
server_emitter.emit(ServerEvent::Buff {
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
uid: *uid,
|
entity,
|
||||||
buff_change: BuffChange::RemoveFromController(buff_id),
|
buff_change: BuffChange::RemoveFromController(buff_id),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -699,10 +699,9 @@ pub fn handle_level_up(server: &mut Server, entity: EcsEntity, new_level: u32) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange) {
|
pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::BuffChange) {
|
||||||
let ecs = &server.state.ecs();
|
let ecs = &server.state.ecs();
|
||||||
let mut buffs_all = ecs.write_storage::<comp::Buffs>();
|
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) {
|
if let Some(buffs) = buffs_all.get_mut(entity) {
|
||||||
use buff::BuffChange;
|
use buff::BuffChange;
|
||||||
match buff_change {
|
match buff_change {
|
||||||
@ -760,5 +759,4 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,10 @@ impl Server {
|
|||||||
ServerEvent::Chat(msg) => {
|
ServerEvent::Chat(msg) => {
|
||||||
chat_messages.push(msg);
|
chat_messages.push(msg);
|
||||||
},
|
},
|
||||||
ServerEvent::Buff { uid, buff_change } => handle_buff(self, uid, buff_change),
|
ServerEvent::Buff {
|
||||||
|
entity,
|
||||||
|
buff_change,
|
||||||
|
} => handle_buff(self, entity, buff_change),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user