overhead info improvements

overhead improvements
This commit is contained in:
Monty Marz 2020-08-03 21:42:06 +02:00
parent 1eb671e1a6
commit 3da7e27a7c
4 changed files with 154 additions and 106 deletions

View File

@ -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() {

View File

@ -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<VoxygenLocalization>,
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::<f32>() < 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::<f32>() < 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);
}
}
}
}

View File

@ -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))

View File

@ -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))