mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'kitswas/poise-indicator' into 'master'
Poise Indicator See merge request veloren/veloren!3582
This commit is contained in:
commit
5ad84b7fca
@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Water will now move according to its apparent flow direction
|
||||
- Added screen-space reflection and refraction shaders
|
||||
- Added reflection quality setting
|
||||
- UI: Added a poise indicator to the player's status bars
|
||||
|
||||
### Changed
|
||||
- Use fluent for translations
|
||||
|
BIN
assets/voxygen/element/ui/skillbar/poise_bg.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/skillbar/poise_bg.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/ui/skillbar/poise_frame.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/ui/skillbar/poise_frame.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -29,6 +29,7 @@ hud-settings-speech_bubble_dark_mode = Speech Bubble Dark Mode
|
||||
hud-settings-speech_bubble_icon = Speech Bubble Icon
|
||||
hud-settings-energybar_numbers = Energybar Numbers
|
||||
hud-settings-always_show_bars = Always show Energybars
|
||||
hud-settings-enable_poise_bar = Enable Poise bar
|
||||
hud-settings-experience_numbers = Experience Numbers
|
||||
hud-settings-accumulate_experience = Accumulate Experience Numbers
|
||||
hud-settings-values = Values
|
||||
|
@ -55,6 +55,8 @@ pub struct Poise {
|
||||
pub regen_rate: f32,
|
||||
/// Time that entity was last in a poise state
|
||||
last_stun_time: Option<Time>,
|
||||
/// The previous poise state
|
||||
pub previous_state: PoiseState,
|
||||
}
|
||||
|
||||
/// States to define effects of a poise change
|
||||
@ -146,11 +148,13 @@ impl Poise {
|
||||
const MAX_SCALED_POISE: u32 = Self::MAX_POISE as u32 * Self::SCALING_FACTOR_INT;
|
||||
/// The amount of time after being in a poise state before you can take
|
||||
/// poise damage again
|
||||
const POISE_BUFFER_TIME: f64 = 1.0;
|
||||
pub const POISE_BUFFER_TIME: f64 = 1.0;
|
||||
/// Used when comparisons to poise are needed outside this module.
|
||||
// This value is chosen as anything smaller than this is more precise than our
|
||||
// units of poise.
|
||||
pub const POISE_EPSILON: f32 = 0.5 / Self::MAX_SCALED_POISE as f32;
|
||||
/// The thresholds where poise changes to a different state
|
||||
pub const POISE_THRESHOLDS: [f32; 4] = [50.0, 30.0, 15.0, 5.0];
|
||||
/// The amount poise is scaled by within this module
|
||||
const SCALING_FACTOR_FLOAT: f32 = 256.;
|
||||
const SCALING_FACTOR_INT: u32 = Self::SCALING_FACTOR_FLOAT as u32;
|
||||
@ -187,6 +191,7 @@ impl Poise {
|
||||
last_change: Dir::default(),
|
||||
regen_rate: 0.0,
|
||||
last_stun_time: None,
|
||||
previous_state: PoiseState::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,6 +199,9 @@ impl Poise {
|
||||
match self.last_stun_time {
|
||||
Some(last_time) if last_time.0 + Poise::POISE_BUFFER_TIME > change.time.0 => {},
|
||||
_ => {
|
||||
// if self.previous_state != self.poise_state() {
|
||||
self.previous_state = self.poise_state();
|
||||
// };
|
||||
self.current = (((self.current() + change.amount)
|
||||
.clamp(0.0, f32::from(Self::MAX_POISE))
|
||||
* Self::SCALING_FACTOR_FLOAT) as u32)
|
||||
@ -216,10 +224,10 @@ impl Poise {
|
||||
/// Defines the poise states based on current poise value
|
||||
pub fn poise_state(&self) -> PoiseState {
|
||||
match self.current() {
|
||||
x if x > 50.0 => PoiseState::Normal,
|
||||
x if x > 30.0 => PoiseState::Interrupted,
|
||||
x if x > 15.0 => PoiseState::Stunned,
|
||||
x if x > 5.0 => PoiseState::Dazed,
|
||||
x if x > Self::POISE_THRESHOLDS[0] => PoiseState::Normal,
|
||||
x if x > Self::POISE_THRESHOLDS[1] => PoiseState::Interrupted,
|
||||
x if x > Self::POISE_THRESHOLDS[2] => PoiseState::Stunned,
|
||||
x if x > Self::POISE_THRESHOLDS[3] => PoiseState::Dazed,
|
||||
_ => PoiseState::KnockedDown,
|
||||
}
|
||||
}
|
||||
|
@ -339,6 +339,9 @@ image_ids! {
|
||||
decayed_bg: "voxygen.element.ui.skillbar.decayed_bg",
|
||||
energy_bg: "voxygen.element.ui.skillbar.energy_bg",
|
||||
energy_frame: "voxygen.element.ui.skillbar.energy_frame",
|
||||
poise_bg: "voxygen.element.ui.skillbar.poise_bg",
|
||||
poise_frame: "voxygen.element.ui.skillbar.poise_frame",
|
||||
poise_tick: "voxygen.element.ui.skillbar.bar_content",
|
||||
m1_ico: "voxygen.element.ui.generic.icons.m1",
|
||||
m2_ico: "voxygen.element.ui.generic.icons.m2",
|
||||
m_scroll_ico: "voxygen.element.ui.generic.icons.m_scroll",
|
||||
|
@ -145,6 +145,8 @@ const CRITICAL_HP_COLOR: Color = Color::Rgba(0.79, 0.19, 0.17, 1.0);
|
||||
const STAMINA_COLOR: Color = Color::Rgba(0.29, 0.62, 0.75, 0.9);
|
||||
const ENEMY_HP_COLOR: Color = Color::Rgba(0.93, 0.1, 0.29, 1.0);
|
||||
const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0);
|
||||
const POISE_COLOR: Color = Color::Rgba(0.70, 0.0, 0.60, 1.0);
|
||||
const POISEBAR_TICK_COLOR: Color = Color::Rgba(0.70, 0.90, 0.0, 1.0);
|
||||
//const TRANSPARENT: Color = Color::Rgba(0.0, 0.0, 0.0, 0.0);
|
||||
//const FOCUS_COLOR: Color = Color::Rgba(1.0, 0.56, 0.04, 1.0);
|
||||
//const RAGE_COLOR: Color = Color::Rgba(0.5, 0.04, 0.13, 1.0);
|
||||
@ -2727,10 +2729,18 @@ impl Hud {
|
||||
});
|
||||
self.floaters.combo_floater = self.floaters.combo_floater.filter(|f| f.timer > 0_f64);
|
||||
|
||||
if let (Some(health), Some(inventory), Some(energy), Some(skillset), Some(body)) = (
|
||||
if let (
|
||||
Some(health),
|
||||
Some(inventory),
|
||||
Some(energy),
|
||||
Some(poise),
|
||||
Some(skillset),
|
||||
Some(body),
|
||||
) = (
|
||||
healths.get(entity),
|
||||
inventories.get(entity),
|
||||
energies.get(entity),
|
||||
poises.get(entity),
|
||||
skillsets.get(entity),
|
||||
bodies.get(entity),
|
||||
) {
|
||||
@ -2745,6 +2755,7 @@ impl Hud {
|
||||
health,
|
||||
inventory,
|
||||
energy,
|
||||
poise,
|
||||
skillset,
|
||||
active_abilities.get(entity),
|
||||
body,
|
||||
|
@ -66,6 +66,8 @@ widget_ids! {
|
||||
show_bar_numbers_percentage_text,
|
||||
always_show_bars_button,
|
||||
always_show_bars_label,
|
||||
enable_poise_bar_button,
|
||||
enable_poise_bar_label,
|
||||
//
|
||||
show_shortcuts_button,
|
||||
show_shortcuts_text,
|
||||
@ -1153,13 +1155,41 @@ impl<'a> Widget for Interface<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.always_show_bars_label, ui);
|
||||
|
||||
// Enable poise bar
|
||||
let enable_poise_bar = ToggleButton::new(
|
||||
self.global_state.settings.interface.enable_poise_bar,
|
||||
self.imgs.checkbox,
|
||||
self.imgs.checkbox_checked,
|
||||
)
|
||||
.w_h(18.0, 18.0)
|
||||
.down_from(state.ids.always_show_bars_button, 20.0)
|
||||
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
.set(state.ids.enable_poise_bar_button, ui);
|
||||
|
||||
if enable_poise_bar != self.global_state.settings.interface.enable_poise_bar {
|
||||
events.push(TogglePoiseBar(enable_poise_bar));
|
||||
}
|
||||
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-enable_poise_bar"),
|
||||
)
|
||||
.right_from(state.ids.enable_poise_bar_button, 10.0)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.graphics_for(state.ids.enable_poise_bar_button)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.enable_poise_bar_label, ui);
|
||||
|
||||
// Experience Numbers
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-settings-experience_numbers"),
|
||||
)
|
||||
.down_from(state.ids.always_show_bars_button, 20.0)
|
||||
.down_from(state.ids.enable_poise_bar_button, 20.0)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
|
@ -3,7 +3,8 @@ use super::{
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
item_imgs::ItemImgs,
|
||||
slots, util, BarNumbers, HudInfo, ShortcutNumbers, BLACK, CRITICAL_HP_COLOR, HP_COLOR,
|
||||
LOW_HP_COLOR, QUALITY_EPIC, STAMINA_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0,
|
||||
LOW_HP_COLOR, POISEBAR_TICK_COLOR, POISE_COLOR, QUALITY_EPIC, STAMINA_COLOR, TEXT_COLOR,
|
||||
UI_HIGHLIGHT_0,
|
||||
};
|
||||
use crate::{
|
||||
game_input::GameInput,
|
||||
@ -24,7 +25,7 @@ use common::comp::{
|
||||
self,
|
||||
ability::AbilityInput,
|
||||
item::{ItemDesc, MaterialStatManifest},
|
||||
Ability, ActiveAbilities, Body, Energy, Health, Inventory, SkillSet,
|
||||
Ability, ActiveAbilities, Body, Energy, Health, Inventory, Poise, PoiseState, SkillSet,
|
||||
};
|
||||
use conrod_core::{
|
||||
color,
|
||||
@ -57,6 +58,8 @@ widget_ids! {
|
||||
frame_health,
|
||||
bg_energy,
|
||||
frame_energy,
|
||||
bg_poise,
|
||||
frame_poise,
|
||||
m1_ico,
|
||||
m2_ico,
|
||||
// Level
|
||||
@ -79,6 +82,13 @@ widget_ids! {
|
||||
energy_txt_alignment,
|
||||
energy_txt_bg,
|
||||
energy_txt,
|
||||
// Poise-Bar
|
||||
poise_alignment,
|
||||
poise_filling,
|
||||
poise_ticks[],
|
||||
poise_txt_alignment,
|
||||
poise_txt_bg,
|
||||
poise_txt,
|
||||
// Combo Counter
|
||||
combo_align,
|
||||
combo_bg,
|
||||
@ -251,6 +261,7 @@ pub struct Skillbar<'a> {
|
||||
health: &'a Health,
|
||||
inventory: &'a Inventory,
|
||||
energy: &'a Energy,
|
||||
poise: &'a Poise,
|
||||
skillset: &'a SkillSet,
|
||||
active_abilities: Option<&'a ActiveAbilities>,
|
||||
body: &'a Body,
|
||||
@ -281,6 +292,7 @@ impl<'a> Skillbar<'a> {
|
||||
health: &'a Health,
|
||||
inventory: &'a Inventory,
|
||||
energy: &'a Energy,
|
||||
poise: &'a Poise,
|
||||
skillset: &'a SkillSet,
|
||||
active_abilities: Option<&'a ActiveAbilities>,
|
||||
body: &'a Body,
|
||||
@ -306,6 +318,7 @@ impl<'a> Skillbar<'a> {
|
||||
health,
|
||||
inventory,
|
||||
energy,
|
||||
poise,
|
||||
skillset,
|
||||
active_abilities,
|
||||
body,
|
||||
@ -365,14 +378,16 @@ impl<'a> Skillbar<'a> {
|
||||
}
|
||||
|
||||
fn show_stat_bars(&self, state: &State, ui: &mut UiCell) {
|
||||
let (hp_percentage, energy_percentage): (f64, f64) = if self.health.is_dead {
|
||||
(0.0, 0.0)
|
||||
let (hp_percentage, energy_percentage, poise_percentage): (f64, f64, f64) =
|
||||
if self.health.is_dead {
|
||||
(0.0, 0.0, 0.0)
|
||||
} else {
|
||||
let max_hp = f64::from(self.health.base_max().max(self.health.maximum()));
|
||||
let current_hp = f64::from(self.health.current());
|
||||
(
|
||||
current_hp / max_hp * 100.0,
|
||||
f64::from(self.energy.fraction() * 100.0),
|
||||
f64::from(self.poise.fraction() * 100.0),
|
||||
)
|
||||
};
|
||||
|
||||
@ -384,6 +399,9 @@ impl<'a> Skillbar<'a> {
|
||||
|| (self.health.current() - self.health.maximum()).abs() > Health::HEALTH_EPSILON;
|
||||
let show_energy = self.global_state.settings.interface.always_show_bars
|
||||
|| (self.energy.current() - self.energy.maximum()).abs() > Energy::ENERGY_EPSILON;
|
||||
let show_poise = self.global_state.settings.interface.enable_poise_bar
|
||||
&& (self.global_state.settings.interface.always_show_bars
|
||||
|| (self.poise.current() - self.poise.maximum()).abs() > Poise::POISE_EPSILON);
|
||||
let decayed_health = 1.0 - self.health.maximum() as f64 / self.health.base_max() as f64;
|
||||
|
||||
if show_health && !self.health.is_dead || decayed_health > 0.0 {
|
||||
@ -452,6 +470,46 @@ impl<'a> Skillbar<'a> {
|
||||
.middle_of(state.ids.bg_energy)
|
||||
.set(state.ids.frame_energy, ui);
|
||||
}
|
||||
if show_poise && !self.health.is_dead {
|
||||
let offset = 17.0;
|
||||
|
||||
let poise_colour = match self.poise.previous_state {
|
||||
self::PoiseState::KnockedDown => BLACK,
|
||||
self::PoiseState::Dazed => Color::Rgba(0.25, 0.0, 0.15, 1.0),
|
||||
self::PoiseState::Stunned => Color::Rgba(0.40, 0.0, 0.30, 1.0),
|
||||
self::PoiseState::Interrupted => Color::Rgba(0.55, 0.0, 0.45, 1.0),
|
||||
_ => POISE_COLOR,
|
||||
};
|
||||
|
||||
Image::new(self.imgs.poise_bg)
|
||||
.w_h(323.0, 14.0)
|
||||
.mid_top_with_margin_on(state.ids.frame, -offset)
|
||||
.set(state.ids.bg_poise, ui);
|
||||
Rectangle::fill_with([319.0, 10.0], color::TRANSPARENT)
|
||||
.top_left_with_margins_on(state.ids.bg_poise, 2.0, 2.0)
|
||||
.set(state.ids.poise_alignment, ui);
|
||||
Image::new(self.imgs.bar_content)
|
||||
.w_h(319.0 * poise_percentage / 100.0, 10.0)
|
||||
.color(Some(poise_colour))
|
||||
.top_left_with_margins_on(state.ids.poise_alignment, 0.0, 0.0)
|
||||
.set(state.ids.poise_filling, ui);
|
||||
for i in 0..state.ids.poise_ticks.len() {
|
||||
Image::new(self.imgs.poise_tick)
|
||||
.w_h(3.0, 10.0)
|
||||
.color(Some(POISEBAR_TICK_COLOR))
|
||||
.top_left_with_margins_on(
|
||||
state.ids.poise_alignment,
|
||||
0.0,
|
||||
319.0f64 * (self::Poise::POISE_THRESHOLDS[i] / self.poise.maximum()) as f64,
|
||||
)
|
||||
.set(state.ids.poise_ticks[i], ui);
|
||||
}
|
||||
Image::new(self.imgs.poise_frame)
|
||||
.w_h(323.0, 16.0)
|
||||
.color(Some(UI_HIGHLIGHT_0))
|
||||
.middle_of(state.ids.bg_poise)
|
||||
.set(state.ids.frame_poise, ui);
|
||||
}
|
||||
// Bar Text
|
||||
let bar_text = if self.health.is_dead {
|
||||
Some((
|
||||
@ -461,6 +519,9 @@ impl<'a> Skillbar<'a> {
|
||||
self.localized_strings
|
||||
.get_msg("hud-group-dead")
|
||||
.into_owned(),
|
||||
self.localized_strings
|
||||
.get_msg("hud-group-dead")
|
||||
.into_owned(),
|
||||
))
|
||||
} else if let BarNumbers::Values = bar_values {
|
||||
Some((
|
||||
@ -475,16 +536,18 @@ impl<'a> Skillbar<'a> {
|
||||
self.energy.current().round() as u32,
|
||||
self.energy.maximum().round() as u32
|
||||
),
|
||||
String::new(), // Don't obscure the tick mark
|
||||
))
|
||||
} else if let BarNumbers::Percent = bar_values {
|
||||
Some((
|
||||
format!("{}%", hp_percentage as u32),
|
||||
format!("{}%", energy_percentage as u32),
|
||||
String::new(), // Don't obscure the tick mark
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some((hp_txt, energy_txt)) = bar_text {
|
||||
if let Some((hp_txt, energy_txt, poise_txt)) = bar_text {
|
||||
Text::new(&hp_txt)
|
||||
.middle_of(state.ids.frame_health)
|
||||
.font_size(self.fonts.cyri.scale(12))
|
||||
@ -510,6 +573,19 @@ impl<'a> Skillbar<'a> {
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.energy_txt, ui);
|
||||
|
||||
Text::new(&poise_txt)
|
||||
.middle_of(state.ids.frame_poise)
|
||||
.font_size(self.fonts.cyri.scale(12))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
|
||||
.set(state.ids.poise_txt_bg, ui);
|
||||
Text::new(&poise_txt)
|
||||
.bottom_left_with_margins_on(state.ids.poise_txt_bg, 2.0, 2.0)
|
||||
.font_size(self.fonts.cyri.scale(12))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.poise_txt, ui);
|
||||
}
|
||||
}
|
||||
|
||||
@ -811,13 +887,22 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
}
|
||||
|
||||
// Skillbar
|
||||
|
||||
// Poise bar ticks
|
||||
state.update(|s| {
|
||||
s.ids.poise_ticks.resize(
|
||||
self::Poise::POISE_THRESHOLDS.len(),
|
||||
&mut ui.widget_id_generator(),
|
||||
)
|
||||
});
|
||||
|
||||
// Alignment and BG
|
||||
let alignment_size = 40.0 * 12.0 + slot_offset * 11.0;
|
||||
Rectangle::fill_with([alignment_size, 80.0], color::TRANSPARENT)
|
||||
.mid_bottom_with_margin_on(ui.window, 10.0)
|
||||
.set(state.ids.frame, ui);
|
||||
|
||||
// Health and Energy bar
|
||||
// Health, Energy and Poise bars
|
||||
self.show_stat_bars(state, ui);
|
||||
|
||||
// Slots
|
||||
|
@ -122,6 +122,7 @@ pub enum Interface {
|
||||
ToggleXpBar(XpBar),
|
||||
ToggleBarNumbers(BarNumbers),
|
||||
ToggleAlwaysShowBars(bool),
|
||||
TogglePoiseBar(bool),
|
||||
ToggleShortcutNumbers(ShortcutNumbers),
|
||||
BuffPosition(BuffPosition),
|
||||
|
||||
@ -571,6 +572,9 @@ impl SettingsChange {
|
||||
Interface::ToggleAlwaysShowBars(always_show_bars) => {
|
||||
settings.interface.always_show_bars = always_show_bars;
|
||||
},
|
||||
Interface::TogglePoiseBar(enable_poise_bar) => {
|
||||
settings.interface.enable_poise_bar = enable_poise_bar;
|
||||
},
|
||||
Interface::ToggleShortcutNumbers(shortcut_numbers) => {
|
||||
settings.interface.shortcut_numbers = shortcut_numbers;
|
||||
},
|
||||
|
@ -30,6 +30,7 @@ pub struct InterfaceSettings {
|
||||
pub buff_position: BuffPosition,
|
||||
pub bar_numbers: BarNumbers,
|
||||
pub always_show_bars: bool,
|
||||
pub enable_poise_bar: bool,
|
||||
pub ui_scale: ScaleMode,
|
||||
pub map_zoom: f64,
|
||||
pub map_show_topo_map: bool,
|
||||
@ -73,6 +74,7 @@ impl Default for InterfaceSettings {
|
||||
buff_position: BuffPosition::Bar,
|
||||
bar_numbers: BarNumbers::Values,
|
||||
always_show_bars: false,
|
||||
enable_poise_bar: false,
|
||||
ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()),
|
||||
map_zoom: 10.0,
|
||||
map_show_topo_map: true,
|
||||
|
Loading…
Reference in New Issue
Block a user