mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Show buff multiplicities as a number instead of duplicate icons. Add particle effects for the beginning of potion sickness.
This commit is contained in:
parent
a871d3880b
commit
1b00b18a7b
@ -559,8 +559,8 @@ impl Buffs {
|
||||
|
||||
// Iterates through all active buffs (the most powerful buff of each
|
||||
// non-stacking kind, and all of the stacking ones)
|
||||
pub fn iter_active(&self) -> impl Iterator<Item = &Buff> + '_ {
|
||||
self.kinds.iter().flat_map(move |(kind, ids)| {
|
||||
pub fn iter_active(&self) -> impl Iterator<Item = impl Iterator<Item = &Buff>> + '_ {
|
||||
self.kinds.iter().map(move |(kind, ids)| {
|
||||
if kind.stacks() {
|
||||
Either::Left(ids.iter().filter_map(|id| self.buffs.get(id)))
|
||||
} else {
|
||||
|
@ -28,6 +28,8 @@ widget_ids! {
|
||||
debuffs[],
|
||||
debuff_timers[],
|
||||
buff_txts[],
|
||||
buff_multiplicities[],
|
||||
debuff_multiplicities[],
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,6 +183,12 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
if state.ids.debuff_timers.len() < debuff_count {
|
||||
state.update(|state| state.ids.debuff_timers.resize(debuff_count, gen));
|
||||
};
|
||||
if state.ids.buff_multiplicities.len() < buff_count {
|
||||
state.update(|state| state.ids.buff_multiplicities.resize(buff_count, gen));
|
||||
};
|
||||
if state.ids.debuff_multiplicities.len() < debuff_count {
|
||||
state.update(|state| state.ids.debuff_multiplicities.resize(debuff_count, gen));
|
||||
};
|
||||
|
||||
// Create Buff Widgets
|
||||
let mut buff_vec = state
|
||||
@ -189,16 +197,18 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
.iter()
|
||||
.copied()
|
||||
.zip(state.ids.buff_timers.iter().copied())
|
||||
.zip(state.ids.buff_multiplicities.iter().copied())
|
||||
.zip(buff_icons.iter().filter(|info| info.is_buff))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Sort the buffs by kind
|
||||
buff_vec.sort_by_key(|((_id, _timer_id), buff)| std::cmp::Reverse(buff.kind));
|
||||
buff_vec
|
||||
.sort_by_key(|(((_id, _timer_id), _mult_id), buff)| std::cmp::Reverse(buff.kind));
|
||||
|
||||
buff_vec
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(i, ((id, timer_id), buff))| {
|
||||
.for_each(|(i, (((id, timer_id), mult_id), buff))| {
|
||||
let max_duration = buff.kind.max_duration();
|
||||
let current_duration = buff.dur;
|
||||
let duration_percentage = current_duration.map_or(1000.0, |cur| {
|
||||
@ -225,6 +235,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
},
|
||||
)
|
||||
.set(*id, ui);
|
||||
if buff.multiplicity() > 1 {
|
||||
Text::new(&format!("{}", buff.multiplicity()))
|
||||
.bottom_right_with_margins_on(*id, 1.0, 1.0)
|
||||
.graphics_for(*id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(*mult_id, ui);
|
||||
}
|
||||
// Create Buff tooltip
|
||||
let (title, desc_txt) = buff.kind.title_description(localized_strings);
|
||||
let remaining_time = buff.get_buff_time();
|
||||
@ -259,16 +278,17 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
.iter()
|
||||
.copied()
|
||||
.zip(state.ids.debuff_timers.iter().copied())
|
||||
.zip(state.ids.debuff_multiplicities.iter().copied())
|
||||
.zip(buff_icons.iter().filter(|info| !info.is_buff))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Sort the debuffs by kind
|
||||
debuff_vec.sort_by_key(|((_id, _timer_id), debuff)| debuff.kind);
|
||||
debuff_vec.sort_by_key(|(((_id, _timer_id), _mult_id), debuff)| debuff.kind);
|
||||
|
||||
debuff_vec
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(i, ((id, timer_id), debuff))| {
|
||||
.for_each(|(i, (((id, timer_id), mult_id), debuff))| {
|
||||
let max_duration = debuff.kind.max_duration();
|
||||
let current_duration = debuff.dur;
|
||||
let duration_percentage = current_duration.map_or(1000.0, |cur| {
|
||||
@ -295,6 +315,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
},
|
||||
)
|
||||
.set(*id, ui);
|
||||
if debuff.multiplicity() > 1 {
|
||||
Text::new(&format!("{}", debuff.multiplicity()))
|
||||
.bottom_right_with_margins_on(*id, 1.0, 1.0)
|
||||
.graphics_for(*id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(*mult_id, ui);
|
||||
}
|
||||
// Create Debuff tooltip
|
||||
let (title, desc_txt) = debuff.kind.title_description(localized_strings);
|
||||
let remaining_time = debuff.get_buff_time();
|
||||
@ -334,6 +363,9 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
if state.ids.buff_txts.len() < buff_count {
|
||||
state.update(|state| state.ids.buff_txts.resize(buff_count, gen));
|
||||
};
|
||||
if state.ids.buff_multiplicities.len() < buff_count {
|
||||
state.update(|state| state.ids.buff_multiplicities.resize(buff_count, gen));
|
||||
};
|
||||
|
||||
// Create Buff Widgets
|
||||
|
||||
@ -344,16 +376,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
.copied()
|
||||
.zip(state.ids.buff_timers.iter().copied())
|
||||
.zip(state.ids.buff_txts.iter().copied())
|
||||
.zip(state.ids.buff_multiplicities.iter().copied())
|
||||
.zip(buff_icons.iter())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Sort the buffs by kind
|
||||
buff_vec.sort_by_key(|((_id, _timer_id), txt_id)| std::cmp::Reverse(txt_id.kind));
|
||||
|
||||
buff_vec
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(i, (((id, timer_id), txt_id), buff))| {
|
||||
buff_vec.iter().enumerate().for_each(
|
||||
|(i, ((((id, timer_id), txt_id), mult_id), buff))| {
|
||||
let max_duration = buff.kind.max_duration();
|
||||
let current_duration = buff.dur;
|
||||
// Percentage to determine which frame of the timer overlay is displayed
|
||||
@ -380,6 +411,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
},
|
||||
)
|
||||
.set(*id, ui);
|
||||
if buff.multiplicity() > 1 {
|
||||
Text::new(&format!("{}", buff.multiplicity()))
|
||||
.bottom_right_with_margins_on(*id, 1.0, 1.0)
|
||||
.graphics_for(*id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(*mult_id, ui);
|
||||
}
|
||||
// Create Buff tooltip
|
||||
let (title, desc_txt) = buff.kind.title_description(localized_strings);
|
||||
let remaining_time = buff.get_buff_time();
|
||||
@ -420,7 +460,8 @@ impl<'a> Widget for BuffsBar<'a> {
|
||||
.graphics_for(*timer_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(*txt_id, ui);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
event
|
||||
}
|
||||
|
@ -454,8 +454,14 @@ impl<W: Positionable> Position for W {
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum BuffIconKind<'a> {
|
||||
Buff { kind: BuffKind, data: BuffData },
|
||||
Ability { ability_id: &'a str },
|
||||
Buff {
|
||||
kind: BuffKind,
|
||||
data: BuffData,
|
||||
multiplicity: usize,
|
||||
},
|
||||
Ability {
|
||||
ability_id: &'a str,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> BuffIconKind<'a> {
|
||||
@ -478,7 +484,11 @@ impl<'a> BuffIconKind<'a> {
|
||||
localized_strings: &'b Localization,
|
||||
) -> (Cow<'b, str>, Cow<'b, str>) {
|
||||
match self {
|
||||
Self::Buff { kind, data } => (
|
||||
Self::Buff {
|
||||
kind,
|
||||
data,
|
||||
multiplicity: _,
|
||||
} => (
|
||||
get_buff_title(*kind, localized_strings),
|
||||
get_buff_desc(*kind, *data, localized_strings),
|
||||
),
|
||||
@ -548,6 +558,13 @@ pub struct BuffIcon<'a> {
|
||||
}
|
||||
|
||||
impl<'a> BuffIcon<'a> {
|
||||
pub fn multiplicity(&self) -> usize {
|
||||
match self.kind {
|
||||
BuffIconKind::Buff { multiplicity, .. } => multiplicity,
|
||||
BuffIconKind::Ability { .. } => 1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_buff_time(&self) -> String {
|
||||
if let Some(dur) = self.dur {
|
||||
format!("{:.0}s", dur.as_secs_f32())
|
||||
@ -559,7 +576,7 @@ impl<'a> BuffIcon<'a> {
|
||||
pub fn icons_vec(buffs: &comp::Buffs, char_state: &comp::CharacterState) -> Vec<Self> {
|
||||
buffs
|
||||
.iter_active()
|
||||
.map(BuffIcon::from_buff)
|
||||
.filter_map(BuffIcon::from_buffs)
|
||||
.chain(BuffIcon::from_char_state(char_state).into_iter())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
@ -581,15 +598,20 @@ impl<'a> BuffIcon<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn from_buff(buff: &comp::Buff) -> Self {
|
||||
Self {
|
||||
fn from_buffs<'b, I: Iterator<Item = &'b comp::Buff>>(buffs: I) -> Option<Self> {
|
||||
let (buff, count) = buffs.fold((None, 0), |(strongest, count), buff| {
|
||||
(strongest.or(Some(buff)), count + 1)
|
||||
});
|
||||
let buff = buff?;
|
||||
Some(Self {
|
||||
kind: BuffIconKind::Buff {
|
||||
kind: buff.kind,
|
||||
data: buff.data,
|
||||
multiplicity: count,
|
||||
},
|
||||
is_buff: buff.kind.is_buff(),
|
||||
dur: buff.time,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1158,13 +1158,31 @@ impl ParticleMgr {
|
||||
{
|
||||
let pos = interp.map_or(pos.0, |i| i.pos);
|
||||
|
||||
for (buff_kind, _) in buffs.kinds.iter() {
|
||||
for (buff_kind, buff_ids) in buffs.kinds.iter() {
|
||||
use buff::BuffKind;
|
||||
match buff_kind {
|
||||
BuffKind::Cursed | BuffKind::Burning => {
|
||||
BuffKind::Cursed | BuffKind::Burning | BuffKind::PotionSickness => {
|
||||
let mut multiplicity = if buff_kind.stacks() {
|
||||
buff_ids.len()
|
||||
} else {
|
||||
1
|
||||
};
|
||||
if let BuffKind::PotionSickness = buff_kind {
|
||||
// Only show particles for potion sickness at the beginning
|
||||
if buff_ids
|
||||
.iter()
|
||||
.filter_map(|id| buffs.buffs.get(id))
|
||||
.all(|buff| buff.delay.is_none())
|
||||
{
|
||||
multiplicity = 0;
|
||||
}
|
||||
}
|
||||
self.particles.resize_with(
|
||||
self.particles.len()
|
||||
+ usize::from(self.scheduler.heartbeats(Duration::from_millis(15))),
|
||||
+ multiplicity
|
||||
* usize::from(
|
||||
self.scheduler.heartbeats(Duration::from_millis(15)),
|
||||
),
|
||||
|| {
|
||||
let start_pos = pos
|
||||
+ Vec3::unit_z() * body.height() * 0.25
|
||||
@ -1180,10 +1198,10 @@ impl ParticleMgr {
|
||||
Particle::new_directed(
|
||||
Duration::from_secs(1),
|
||||
time,
|
||||
if matches!(buff_kind, buff::BuffKind::Cursed) {
|
||||
ParticleMode::CultistFlame
|
||||
} else {
|
||||
ParticleMode::FlameThrower
|
||||
match buff_kind {
|
||||
BuffKind::Cursed => ParticleMode::CultistFlame,
|
||||
BuffKind::PotionSickness => ParticleMode::Blood,
|
||||
_ => ParticleMode::FlameThrower,
|
||||
},
|
||||
start_pos,
|
||||
end_pos,
|
||||
|
Loading…
Reference in New Issue
Block a user