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
|
// Iterates through all active buffs (the most powerful buff of each
|
||||||
// non-stacking kind, and all of the stacking ones)
|
// non-stacking kind, and all of the stacking ones)
|
||||||
pub fn iter_active(&self) -> impl Iterator<Item = &Buff> + '_ {
|
pub fn iter_active(&self) -> impl Iterator<Item = impl Iterator<Item = &Buff>> + '_ {
|
||||||
self.kinds.iter().flat_map(move |(kind, ids)| {
|
self.kinds.iter().map(move |(kind, ids)| {
|
||||||
if kind.stacks() {
|
if kind.stacks() {
|
||||||
Either::Left(ids.iter().filter_map(|id| self.buffs.get(id)))
|
Either::Left(ids.iter().filter_map(|id| self.buffs.get(id)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -28,6 +28,8 @@ widget_ids! {
|
|||||||
debuffs[],
|
debuffs[],
|
||||||
debuff_timers[],
|
debuff_timers[],
|
||||||
buff_txts[],
|
buff_txts[],
|
||||||
|
buff_multiplicities[],
|
||||||
|
debuff_multiplicities[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +183,12 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
if state.ids.debuff_timers.len() < debuff_count {
|
if state.ids.debuff_timers.len() < debuff_count {
|
||||||
state.update(|state| state.ids.debuff_timers.resize(debuff_count, gen));
|
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
|
// Create Buff Widgets
|
||||||
let mut buff_vec = state
|
let mut buff_vec = state
|
||||||
@ -189,16 +197,18 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.zip(state.ids.buff_timers.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))
|
.zip(buff_icons.iter().filter(|info| info.is_buff))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Sort the buffs by kind
|
// 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
|
buff_vec
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.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 max_duration = buff.kind.max_duration();
|
||||||
let current_duration = buff.dur;
|
let current_duration = buff.dur;
|
||||||
let duration_percentage = current_duration.map_or(1000.0, |cur| {
|
let duration_percentage = current_duration.map_or(1000.0, |cur| {
|
||||||
@ -225,6 +235,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.set(*id, ui);
|
.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
|
// Create Buff tooltip
|
||||||
let (title, desc_txt) = buff.kind.title_description(localized_strings);
|
let (title, desc_txt) = buff.kind.title_description(localized_strings);
|
||||||
let remaining_time = buff.get_buff_time();
|
let remaining_time = buff.get_buff_time();
|
||||||
@ -259,16 +278,17 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.zip(state.ids.debuff_timers.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))
|
.zip(buff_icons.iter().filter(|info| !info.is_buff))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Sort the debuffs by kind
|
// 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
|
debuff_vec
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.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 max_duration = debuff.kind.max_duration();
|
||||||
let current_duration = debuff.dur;
|
let current_duration = debuff.dur;
|
||||||
let duration_percentage = current_duration.map_or(1000.0, |cur| {
|
let duration_percentage = current_duration.map_or(1000.0, |cur| {
|
||||||
@ -295,6 +315,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.set(*id, ui);
|
.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
|
// Create Debuff tooltip
|
||||||
let (title, desc_txt) = debuff.kind.title_description(localized_strings);
|
let (title, desc_txt) = debuff.kind.title_description(localized_strings);
|
||||||
let remaining_time = debuff.get_buff_time();
|
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 {
|
if state.ids.buff_txts.len() < buff_count {
|
||||||
state.update(|state| state.ids.buff_txts.resize(buff_count, gen));
|
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
|
// Create Buff Widgets
|
||||||
|
|
||||||
@ -344,16 +376,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
.copied()
|
.copied()
|
||||||
.zip(state.ids.buff_timers.iter().copied())
|
.zip(state.ids.buff_timers.iter().copied())
|
||||||
.zip(state.ids.buff_txts.iter().copied())
|
.zip(state.ids.buff_txts.iter().copied())
|
||||||
|
.zip(state.ids.buff_multiplicities.iter().copied())
|
||||||
.zip(buff_icons.iter())
|
.zip(buff_icons.iter())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Sort the buffs by kind
|
// Sort the buffs by kind
|
||||||
buff_vec.sort_by_key(|((_id, _timer_id), txt_id)| std::cmp::Reverse(txt_id.kind));
|
buff_vec.sort_by_key(|((_id, _timer_id), txt_id)| std::cmp::Reverse(txt_id.kind));
|
||||||
|
|
||||||
buff_vec
|
buff_vec.iter().enumerate().for_each(
|
||||||
.iter()
|
|(i, ((((id, timer_id), txt_id), mult_id), buff))| {
|
||||||
.enumerate()
|
|
||||||
.for_each(|(i, (((id, timer_id), txt_id), buff))| {
|
|
||||||
let max_duration = buff.kind.max_duration();
|
let max_duration = buff.kind.max_duration();
|
||||||
let current_duration = buff.dur;
|
let current_duration = buff.dur;
|
||||||
// Percentage to determine which frame of the timer overlay is displayed
|
// Percentage to determine which frame of the timer overlay is displayed
|
||||||
@ -380,6 +411,15 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.set(*id, ui);
|
.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
|
// Create Buff tooltip
|
||||||
let (title, desc_txt) = buff.kind.title_description(localized_strings);
|
let (title, desc_txt) = buff.kind.title_description(localized_strings);
|
||||||
let remaining_time = buff.get_buff_time();
|
let remaining_time = buff.get_buff_time();
|
||||||
@ -420,7 +460,8 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
.graphics_for(*timer_id)
|
.graphics_for(*timer_id)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(*txt_id, ui);
|
.set(*txt_id, ui);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
event
|
event
|
||||||
}
|
}
|
||||||
|
@ -454,8 +454,14 @@ impl<W: Positionable> Position for W {
|
|||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum BuffIconKind<'a> {
|
pub enum BuffIconKind<'a> {
|
||||||
Buff { kind: BuffKind, data: BuffData },
|
Buff {
|
||||||
Ability { ability_id: &'a str },
|
kind: BuffKind,
|
||||||
|
data: BuffData,
|
||||||
|
multiplicity: usize,
|
||||||
|
},
|
||||||
|
Ability {
|
||||||
|
ability_id: &'a str,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BuffIconKind<'a> {
|
impl<'a> BuffIconKind<'a> {
|
||||||
@ -478,7 +484,11 @@ impl<'a> BuffIconKind<'a> {
|
|||||||
localized_strings: &'b Localization,
|
localized_strings: &'b Localization,
|
||||||
) -> (Cow<'b, str>, Cow<'b, str>) {
|
) -> (Cow<'b, str>, Cow<'b, str>) {
|
||||||
match self {
|
match self {
|
||||||
Self::Buff { kind, data } => (
|
Self::Buff {
|
||||||
|
kind,
|
||||||
|
data,
|
||||||
|
multiplicity: _,
|
||||||
|
} => (
|
||||||
get_buff_title(*kind, localized_strings),
|
get_buff_title(*kind, localized_strings),
|
||||||
get_buff_desc(*kind, *data, localized_strings),
|
get_buff_desc(*kind, *data, localized_strings),
|
||||||
),
|
),
|
||||||
@ -548,6 +558,13 @@ pub struct BuffIcon<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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 {
|
pub fn get_buff_time(&self) -> String {
|
||||||
if let Some(dur) = self.dur {
|
if let Some(dur) = self.dur {
|
||||||
format!("{:.0}s", dur.as_secs_f32())
|
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> {
|
pub fn icons_vec(buffs: &comp::Buffs, char_state: &comp::CharacterState) -> Vec<Self> {
|
||||||
buffs
|
buffs
|
||||||
.iter_active()
|
.iter_active()
|
||||||
.map(BuffIcon::from_buff)
|
.filter_map(BuffIcon::from_buffs)
|
||||||
.chain(BuffIcon::from_char_state(char_state).into_iter())
|
.chain(BuffIcon::from_char_state(char_state).into_iter())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
@ -581,15 +598,20 @@ impl<'a> BuffIcon<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_buff(buff: &comp::Buff) -> Self {
|
fn from_buffs<'b, I: Iterator<Item = &'b comp::Buff>>(buffs: I) -> Option<Self> {
|
||||||
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: BuffIconKind::Buff {
|
||||||
kind: buff.kind,
|
kind: buff.kind,
|
||||||
data: buff.data,
|
data: buff.data,
|
||||||
|
multiplicity: count,
|
||||||
},
|
},
|
||||||
is_buff: buff.kind.is_buff(),
|
is_buff: buff.kind.is_buff(),
|
||||||
dur: buff.time,
|
dur: buff.time,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,13 +1158,31 @@ impl ParticleMgr {
|
|||||||
{
|
{
|
||||||
let pos = interp.map_or(pos.0, |i| i.pos);
|
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;
|
use buff::BuffKind;
|
||||||
match buff_kind {
|
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.resize_with(
|
||||||
self.particles.len()
|
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
|
let start_pos = pos
|
||||||
+ Vec3::unit_z() * body.height() * 0.25
|
+ Vec3::unit_z() * body.height() * 0.25
|
||||||
@ -1180,10 +1198,10 @@ impl ParticleMgr {
|
|||||||
Particle::new_directed(
|
Particle::new_directed(
|
||||||
Duration::from_secs(1),
|
Duration::from_secs(1),
|
||||||
time,
|
time,
|
||||||
if matches!(buff_kind, buff::BuffKind::Cursed) {
|
match buff_kind {
|
||||||
ParticleMode::CultistFlame
|
BuffKind::Cursed => ParticleMode::CultistFlame,
|
||||||
} else {
|
BuffKind::PotionSickness => ParticleMode::Blood,
|
||||||
ParticleMode::FlameThrower
|
_ => ParticleMode::FlameThrower,
|
||||||
},
|
},
|
||||||
start_pos,
|
start_pos,
|
||||||
end_pos,
|
end_pos,
|
||||||
|
Loading…
Reference in New Issue
Block a user