From 53fa9e451a842f5cfe8f746da5ffd2a1f4ef4bb9 Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Mon, 3 Aug 2020 21:42:06 +0200 Subject: [PATCH] overhead info improvements overhead improvements --- voxygen/src/hud/group.rs | 2 + voxygen/src/hud/overhead.rs | 208 +++++++++++++++++++++--------------- voxygen/src/hud/skillbar.rs | 36 ++++--- voxygen/src/hud/social.rs | 14 +-- 4 files changed, 154 insertions(+), 106 deletions(-) diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index c39dbb9301..63c70bb2dc 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -173,6 +173,7 @@ impl<'a> Widget for Group<'a> { let in_group = !group_members.is_empty(); if !in_group { self.show.group_menu = false; + self.show.group = false; } // Helper @@ -207,6 +208,7 @@ impl<'a> Widget for Group<'a> { // Frame Rectangle::fill_with([220.0, 165.0], color::Color::Rgba(0.0, 0.0, 0.0, 0.8)) .bottom_left_with_margins_on(ui.window, 220.0, 10.0) + .crop_kids() .set(state.ids.bg, ui); } if open_invite.is_some() { diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs index abcf9ebdd5..f3079b1630 100644 --- a/voxygen/src/hud/overhead.rs +++ b/voxygen/src/hud/overhead.rs @@ -42,6 +42,7 @@ widget_ids! { level_skull, health_bar, health_bar_bg, + health_txt, mana_bar, health_bar_fg, } @@ -62,6 +63,7 @@ pub struct Overhead<'a> { voxygen_i18n: &'a std::sync::Arc, imgs: &'a Imgs, fonts: &'a ConrodVoxygenFonts, + #[conrod(common_builder)] common: widget::CommonBuilder, } @@ -107,13 +109,20 @@ impl<'a> Ingameable for Overhead<'a> { // Number of conrod primitives contained in the overhead display. TODO maybe // this could be done automatically? // - 2 Text::new for name + // If HP Info is shown + 6 // - 1 for level: either Text or Image // - 4 for HP + mana + fg + bg - // If there's a speech bubble - // - 2 Text::new for speech bubble + // - 1 for HP Text + // If there's a speech bubble + 13 + // - 2 Text::new for speec8 bubble // - 1 Image::new for icon // - 10 Image::new for speech bubble (9-slice + tail) - 7 + if self.bubble.is_some() { 13 } else { 0 } + 2 + if self.bubble.is_some() { 13 } else { 0 } + + if (self.stats.health.current() as f64 / self.stats.health.maximum() as f64) < 1.0 { + 6 + } else { + 0 + } } } @@ -137,23 +146,32 @@ impl<'a> Widget for Overhead<'a> { const BARSIZE: f64 = 2.0; const MANA_BAR_HEIGHT: f64 = BARSIZE * 1.5; const MANA_BAR_Y: f64 = MANA_BAR_HEIGHT / 2.0; - + let hp_percentage = + self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0; + let name_y = if hp_percentage == 100.0 { + MANA_BAR_Y + 10.0 + } else { + MANA_BAR_Y + 32.0 + }; + let font_size = if hp_percentage == 100.0 { 24 } else { 20 }; // Name Text::new(&self.name) .font_id(self.fonts.cyri.conrod_id) - .font_size(30) + .font_size(font_size) .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .x_y(-1.0, MANA_BAR_Y + 48.0) + .x_y(-1.0, name_y) + .parent(id) .set(state.ids.name_bg, ui); Text::new(&self.name) .font_id(self.fonts.cyri.conrod_id) - .font_size(30) + .font_size(font_size) .color(if self.in_group { GROUP_MEMBER } else { DEFAULT_NPC }) - .x_y(0.0, MANA_BAR_Y + 50.0) + .x_y(0.0, name_y + 1.0) + .parent(id) .set(state.ids.name, ui); // Speech bubble @@ -167,7 +185,7 @@ impl<'a> Widget for Overhead<'a> { .color(text_color) .font_id(self.fonts.cyri.conrod_id) .font_size(18) - .up_from(state.ids.name, 20.0) + .up_from(state.ids.name, 26.0) .x_align_to(state.ids.name, Align::Middle) .parent(id); @@ -302,101 +320,121 @@ impl<'a> Widget for Overhead<'a> { .set(state.ids.speech_bubble_icon, ui); } - let hp_percentage = - self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0; - let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 1.0; //Animation timer - let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); + if hp_percentage < 100.0 { + // Show HP Bar + let hp_percentage = + self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0; + let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 1.0; //Animation timer + let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); - // Background - Image::new(self.imgs.enemy_health_bg) + // Background + Image::new(self.imgs.enemy_health_bg) .w_h(84.0 * BARSIZE, 10.0 * BARSIZE) .x_y(0.0, MANA_BAR_Y + 6.5) //-25.5) .color(Some(Color::Rgba(0.1, 0.1, 0.1, 0.8))) .parent(id) .set(state.ids.health_bar_bg, ui); - // % HP Filling - Image::new(self.imgs.enemy_bar) - .w_h(73.0 * (hp_percentage / 100.0) * BARSIZE, 6.0 * BARSIZE) - .x_y( - (4.5 + (hp_percentage / 100.0 * 36.45 - 36.45)) * BARSIZE, - MANA_BAR_Y + 7.5, - ) - .color(Some(if hp_percentage <= 25.0 { - crit_hp_color - } else if hp_percentage <= 50.0 { - LOW_HP_COLOR - } else { - HP_COLOR - })) - .parent(id) - .set(state.ids.health_bar, ui); + // % HP Filling + Image::new(self.imgs.enemy_bar) + .w_h(73.0 * (hp_percentage / 100.0) * BARSIZE, 6.0 * BARSIZE) + .x_y( + (4.5 + (hp_percentage / 100.0 * 36.45 - 36.45)) * BARSIZE, + MANA_BAR_Y + 7.5, + ) + .color(Some(if hp_percentage <= 25.0 { + crit_hp_color + } else if hp_percentage <= 50.0 { + LOW_HP_COLOR + } else { + HP_COLOR + })) + .parent(id) + .set(state.ids.health_bar, ui); + // TODO Only show health values for entities below 100% health + let mut txt = format!( + "{}/{}", + self.stats.health.current().max(1) / 10 as u32, /* Don't show 0 health for + * living entities */ + self.stats.health.maximum() / 10 as u32, + ); + if self.stats.is_dead { + txt = self.voxygen_i18n.get("hud.group.dead").to_string() + }; + Text::new(&txt) + .mid_top_with_margin_on(state.ids.health_bar_bg, 2.0) + .font_size(10) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .parent(id) + .set(state.ids.health_txt, ui); - // % Mana Filling - if let Some(energy) = self.energy { - let energy_factor = energy.current() as f64 / energy.maximum() as f64; + // % Mana Filling + if let Some(energy) = self.energy { + let energy_factor = energy.current() as f64 / energy.maximum() as f64; - Rectangle::fill_with( - [72.0 * energy_factor * BARSIZE, MANA_BAR_HEIGHT], - MANA_COLOR, - ) - .x_y( - ((3.5 + (energy_factor * 36.5)) - 36.45) * BARSIZE, - MANA_BAR_Y, //-32.0, - ) - .parent(id) - .set(state.ids.mana_bar, ui); - } + Rectangle::fill_with( + [72.0 * energy_factor * BARSIZE, MANA_BAR_HEIGHT], + MANA_COLOR, + ) + .x_y( + ((3.5 + (energy_factor * 36.5)) - 36.45) * BARSIZE, + MANA_BAR_Y, //-32.0, + ) + .parent(id) + .set(state.ids.mana_bar, ui); + } - // Foreground - Image::new(self.imgs.enemy_health) + // Foreground + Image::new(self.imgs.enemy_health) .w_h(84.0 * BARSIZE, 10.0 * BARSIZE) .x_y(0.0, MANA_BAR_Y + 6.5) //-25.5) .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.99))) .parent(id) .set(state.ids.health_bar_fg, ui); - // Level - const LOW: Color = Color::Rgba(0.54, 0.81, 0.94, 0.4); - const HIGH: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0); - const EQUAL: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); - // Change visuals of the level display depending on the player level/opponent - // level - let level_comp = self.stats.level.level() as i64 - self.own_level as i64; - // + 10 level above player -> skull - // + 5-10 levels above player -> high - // -5 - +5 levels around player level -> equal - // - 5 levels below player -> low - if level_comp > 9 { - let skull_ani = ((self.pulse * 0.7/* speed factor */).cos() * 0.5 + 0.5) * 10.0; //Animation timer - Image::new(if skull_ani as i32 == 1 && rand::random::() < 0.9 { - self.imgs.skull_2 - } else { - self.imgs.skull - }) - .w_h(18.0 * BARSIZE, 18.0 * BARSIZE) - .x_y(-39.0 * BARSIZE, MANA_BAR_Y + 7.0) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) - .parent(id) - .set(state.ids.level_skull, ui); - } else { - Text::new(&format!("{}", self.stats.level.level())) - .font_id(self.fonts.cyri.conrod_id) - .font_size(if self.stats.level.level() > 9 && level_comp < 10 { - 14 + // Level + const LOW: Color = Color::Rgba(0.54, 0.81, 0.94, 0.4); + const HIGH: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0); + const EQUAL: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); + // Change visuals of the level display depending on the player level/opponent + // level + let level_comp = self.stats.level.level() as i64 - self.own_level as i64; + // + 10 level above player -> skull + // + 5-10 levels above player -> high + // -5 - +5 levels around player level -> equal + // - 5 levels below player -> low + if level_comp > 9 { + let skull_ani = ((self.pulse * 0.7/* speed factor */).cos() * 0.5 + 0.5) * 10.0; //Animation timer + Image::new(if skull_ani as i32 == 1 && rand::random::() < 0.9 { + self.imgs.skull_2 } else { - 15 + self.imgs.skull }) - .color(if level_comp > 4 { - HIGH - } else if level_comp < -5 { - LOW - } else { - EQUAL - }) - .x_y(-37.0 * BARSIZE, MANA_BAR_Y + 9.0) + .w_h(18.0 * BARSIZE, 18.0 * BARSIZE) + .x_y(-39.0 * BARSIZE, MANA_BAR_Y + 7.0) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) .parent(id) - .set(state.ids.level, ui); + .set(state.ids.level_skull, ui); + } else { + Text::new(&format!("{}", self.stats.level.level())) + .font_id(self.fonts.cyri.conrod_id) + .font_size(if self.stats.level.level() > 9 && level_comp < 10 { + 14 + } else { + 15 + }) + .color(if level_comp > 4 { + HIGH + } else if level_comp < -5 { + LOW + } else { + EQUAL + }) + .x_y(-37.0 * BARSIZE, MANA_BAR_Y + 9.0) + .parent(id) + .set(state.ids.level, ui); + } } } } diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index f365473e1d..9b0654eb91 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -219,10 +219,14 @@ impl<'a> Widget for Skillbar<'a> { let exp_percentage = (self.stats.exp.current() as f64) / (self.stats.exp.maximum() as f64); - let hp_percentage = + let mut hp_percentage = self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0; - let energy_percentage = self.energy.current() as f64 / self.energy.maximum() as f64 * 100.0; - + let mut energy_percentage = + self.energy.current() as f64 / self.energy.maximum() as f64 * 100.0; + if self.stats.is_dead { + hp_percentage = 0.0; + energy_percentage = 0.0; + }; let scale = 2.0; let bar_values = self.global_state.settings.gameplay.bar_numbers; @@ -1160,14 +1164,14 @@ impl<'a> Widget for Skillbar<'a> { }; Image::new(self.imgs.bar_content) .w_h(97.0 * scale * hp_percentage / 100.0, 16.0 * scale) - .color(Some(health_col)) + .color(Some(health_col)) .top_right_with_margins_on(state.ids.healthbar_bg, 2.0 * scale, 1.0 * scale) .set(state.ids.healthbar_filling, ui); // Energybar Image::new(self.imgs.energybar_bg) .w_h(100.0 * scale, 20.0 * scale) .top_right_with_margins_on(state.ids.m2_slot, 0.0, -100.0 * scale) - .set(state.ids.energybar_bg, ui); + .set(state.ids.energybar_bg, ui); Image::new(self.imgs.bar_content) .w_h(97.0 * scale * energy_percentage / 100.0, 16.0 * scale) .top_left_with_margins_on(state.ids.energybar_bg, 2.0 * scale, 1.0 * scale) @@ -1180,11 +1184,21 @@ impl<'a> Widget for Skillbar<'a> { // Bar Text // Values if let BarNumbers::Values = bar_values { - let hp_text = format!( + let mut hp_text = format!( "{}/{}", - (self.stats.health.current() / 10) as u32, + (self.stats.health.current() / 10).max(1) as u32, // Don't show 0 health for living players (self.stats.health.maximum() / 10) as u32 ); + let mut energy_text = format!( + "{}/{}", + self.energy.current() as u32 / 10, /* TODO Fix regeneration with smaller energy + * numbers instead of dividing by 10 here */ + self.energy.maximum() as u32 / 10 + ); + if self.stats.is_dead { + hp_text = self.localized_strings.get("hud.group.dead").to_string(); + energy_text = self.localized_strings.get("hud.group.dead").to_string(); + }; Text::new(&hp_text) .mid_top_with_margin_on(state.ids.healthbar_bg, 6.0 * scale) .font_size(self.fonts.cyri.scale(14)) @@ -1196,13 +1210,7 @@ impl<'a> Widget for Skillbar<'a> { .font_size(self.fonts.cyri.scale(14)) .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) - .set(state.ids.health_text, ui); - let energy_text = format!( - "{}/{}", - self.energy.current() as u32 / 10, /* TODO Fix regeneration with smaller energy - * numbers instead of dividing by 10 here */ - self.energy.maximum() as u32 / 10 - ); + .set(state.ids.health_text, ui); Text::new(&energy_text) .mid_top_with_margin_on(state.ids.energybar_bg, 6.0 * scale) .font_size(self.fonts.cyri.scale(14)) diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index b340db8440..ee875b26e5 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -262,15 +262,15 @@ impl<'a> Widget for Social<'a> { .mid_top_with_margin_on(state.ids.frame, 74.0) .scroll_kids_vertically() .set(state.ids.online_align, ui); - Rectangle::fill_with([133.0, 370.0], color::TRANSPARENT) + Rectangle::fill_with([133.0, 346.0], color::TRANSPARENT) .top_left_with_margins_on(state.ids.online_align, 0.0, 0.0) .crop_kids() .set(state.ids.names_align, ui); - Rectangle::fill_with([39.0, 370.0], color::TRANSPARENT) + Rectangle::fill_with([39.0, 346.0], color::TRANSPARENT) .right_from(state.ids.names_align, 2.0) .crop_kids() .set(state.ids.levels_align, ui); - Rectangle::fill_with([94.0, 370.0], color::TRANSPARENT) + Rectangle::fill_with([94.0, 346.0], color::TRANSPARENT) .right_from(state.ids.levels_align, 2.0) .crop_kids() .set(state.ids.zones_align, ui); @@ -423,9 +423,9 @@ impl<'a> Widget for Social<'a> { .was_clicked() {}; let level_txt = if i == 0 { - Text::new(&level).mid_top_with_margin_on(state.ids.levels_align, 2.0) + Text::new(&level).mid_top_with_margin_on(state.ids.levels_align, 4.0) } else { - Text::new(&level).down_from(state.ids.player_levels[i - 1], 2.0) + Text::new(&level).down_from(state.ids.player_levels[i - 1], 4.0) }; level_txt .font_size(self.fonts.cyri.scale(14)) @@ -433,9 +433,9 @@ impl<'a> Widget for Social<'a> { .color(TEXT_COLOR) .set(state.ids.player_levels[i], ui); let zone_txt = if i == 0 { - Text::new(&zone_name).mid_top_with_margin_on(state.ids.zones_align, 2.0) + Text::new(&zone_name).mid_top_with_margin_on(state.ids.zones_align, 4.0) } else { - Text::new(&zone_name).down_from(state.ids.player_zones[i - 1], 2.0) + Text::new(&zone_name).down_from(state.ids.player_zones[i - 1], 4.0) }; zone_txt .font_size(self.fonts.cyri.scale(14))