Add Exp-Bar

This commit is contained in:
Monty Marz 2022-11-22 11:52:39 +00:00
parent 1a92bd7fe1
commit 3abfa4d2cc
12 changed files with 179 additions and 12 deletions

View File

@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Doors now animate opening when entities are near them.
- Musical instruments can now be crafted, looted and played
- NPCs now move to their target's last known position.
- Experience bar below the hotbar
### Changed

BIN
assets/voxygen/element/ui/skillbar/exp_frame.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/ui/skillbar/exp_frame_bg.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/ui/skillbar/selected_exp_frame.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/ui/skillbar/selected_exp_frame_bg.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -4,6 +4,7 @@ hud-skill-not_unlocked = Not yet unlocked
hud-skill-req_sp ={"\u000A"}
Requires { $number } SP
hud-skill-set_as_exp_bar = Set as Experience Bar
hud-skill-inc_health_title = Increase Health
hud-skill-inc_health = Increases max health by { $boost }{ $SP }
hud-skill-inc_energy_title = Increase Energy

View File

@ -20,6 +20,7 @@ use crate::{
};
use conrod_core::{
color, image,
position::Relative,
widget::{self, Button, Image, Rectangle, State, Text},
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, WidgetCommon,
};
@ -70,6 +71,7 @@ widget_ids! {
exp_bar_content,
exp_bar_rank,
exp_bar_txt,
active_bar_checkbox,
tree_title_txt,
lock_imgs[],
available_pts_txt,
@ -341,6 +343,7 @@ pub enum Event {
ChangeSkillTree(SelectedSkillTree),
UnlockSkill(Skill),
ChangeSection(DiarySection),
SelectExpBar(Option<SkillGroupKind>),
}
#[derive(PartialEq, Eq)]
@ -672,6 +675,42 @@ impl<'a> Widget for Diary<'a> {
.color(Some(UI_HIGHLIGHT_0))
.middle_of(state.ids.exp_bar_bg)
.set(state.ids.exp_bar_frame, ui);
// Show as Exp bar below skillbar
let exp_selected =
self.global_state.settings.interface.xp_bar_skillgroup == Some(*sel_tab);
if Button::image(if !exp_selected {
self.imgs.checkbox
} else {
self.imgs.checkbox_checked
})
.w_h(24.0, 25.0)
.hover_image(if !exp_selected {
self.imgs.checkbox_mo
} else {
self.imgs.checkbox_checked_mo
})
.press_image(if !exp_selected {
self.imgs.checkbox_press
} else {
self.imgs.checkbox_checked
})
.top_right_with_margins_on(state.ids.exp_bar_frame, 50.0, -40.0)
.label(&self.localized_strings.get_msg("hud-skill-set_as_exp_bar"))
.label_font_size(self.fonts.cyri.scale(14))
.label_color(TEXT_COLOR)
.label_font_id(self.fonts.cyri.conrod_id)
.label_x(Relative::Scalar(87.0))
.label_y(Relative::Scalar(2.0))
.set(state.ids.active_bar_checkbox, ui)
.was_clicked()
{
if self.global_state.settings.interface.xp_bar_skillgroup != Some(*sel_tab) {
events.push(Event::SelectExpBar(Some(*sel_tab)));
} else {
events.push(Event::SelectExpBar(None));
}
}
// Show EXP bar text on hover
if ui
.widget_input(state.ids.exp_bar_frame)

View File

@ -367,6 +367,10 @@ image_ids! {
skillbar_frame: "voxygen.element.ui.skillbar.frame",
health_bg: "voxygen.element.ui.skillbar.health_bg",
health_frame: "voxygen.element.ui.skillbar.health_frame",
exp_frame: "voxygen.element.ui.skillbar.exp_frame",
exp_frame_bg: "voxygen.element.ui.skillbar.exp_frame_bg",
selected_exp: "voxygen.element.ui.skillbar.selected_exp_frame",
selected_exp_bg: "voxygen.element.ui.skillbar.selected_exp_frame_bg",
decayed_bg: "voxygen.element.ui.skillbar.decayed_bg",
energy_bg: "voxygen.element.ui.skillbar.energy_bg",
energy_frame: "voxygen.element.ui.skillbar.energy_frame",
@ -380,6 +384,7 @@ image_ids! {
m_click_ico: "voxygen.element.ui.generic.icons.m_click",
skillbar_slot: "voxygen.element.ui.skillbar.slot",
// Other Icons/Art
skull: "voxygen.element.ui.generic.icons.skull",
skull_2: "voxygen.element.ui.generic.icons.skull_2",

View File

@ -708,6 +708,8 @@ pub enum Event {
AssignLeader(Uid),
RemoveBuff(BuffKind),
UnlockSkill(Skill),
SelectExpBar(Option<SkillGroupKind>),
RequestSiteInfo(SiteId),
ChangeAbility(usize, AuxiliaryAbility),
@ -2887,7 +2889,7 @@ impl Hud {
bodies.get(entity),
) {
let context = AbilityContext::try_from(char_states.get(entity));
Skillbar::new(
match Skillbar::new(
client,
&info,
global_state,
@ -2916,7 +2918,14 @@ impl Hud {
combos.get(entity),
char_states.get(entity),
)
.set(self.ids.skillbar, ui_widgets);
.set(self.ids.skillbar, ui_widgets)
{
Some(skillbar::Event::OpenDiary(skillgroup)) => {
self.show.diary(true);
self.show.open_skill_tree(skillgroup);
},
None => {},
}
}
// Bag contents
if self.show.bag {
@ -3357,6 +3366,9 @@ impl Hud {
diary::Event::ChangeSection(section) => {
self.show.diary_fields.section = section;
},
diary::Event::SelectExpBar(xp_bar) => {
events.push(Event::SelectExpBar(xp_bar))
},
}
}
}

View File

@ -3,8 +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, POISEBAR_TICK_COLOR, POISE_COLOR, QUALITY_EPIC, STAMINA_COLOR, TEXT_COLOR,
UI_HIGHLIGHT_0,
LOW_HP_COLOR, POISEBAR_TICK_COLOR, POISE_COLOR, QUALITY_EPIC, QUALITY_LEGENDARY, STAMINA_COLOR,
TEXT_COLOR, UI_HIGHLIGHT_0, XP_COLOR,
};
use crate::{
game_input::GameInput,
@ -24,7 +24,11 @@ use client::{self, Client};
use common::comp::{
self,
ability::AbilityInput,
item::{tool::AbilityContext, ItemDesc, MaterialStatManifest},
item::{
tool::{AbilityContext, ToolKind},
ItemDesc, MaterialStatManifest,
},
skillset::SkillGroupKind,
Ability, ActiveAbilities, Body, CharacterState, Combo, Energy, Health, Inventory, Poise,
PoiseState, SkillSet,
};
@ -66,9 +70,6 @@ widget_ids! {
// Level
level_bg,
level,
// Exp-Bar
exp_alignment,
exp_filling,
// HP-Bar
hp_alignment,
hp_filling,
@ -90,6 +91,14 @@ widget_ids! {
poise_txt_alignment,
poise_txt_bg,
poise_txt,
// Exp-Bar
exp_frame_bg,
exp_frame,
exp_filling,
exp_img_frame_bg,
exp_img_frame,
exp_img,
exp_lvl,
// Combo Counter
combo_align,
combo_bg,
@ -250,6 +259,10 @@ fn slot_entries(state: &State, slot_offset: f64) -> [SlotEntry; 10] {
]
}
pub enum Event {
OpenDiary(SkillGroupKind),
}
#[derive(WidgetCommon)]
pub struct Skillbar<'a> {
client: &'a Client,
@ -387,7 +400,7 @@ impl<'a> Skillbar<'a> {
}
}
fn show_stat_bars(&self, state: &State, ui: &mut UiCell) {
fn show_stat_bars(&self, state: &State, ui: &mut UiCell) -> Option<Event> {
let (hp_percentage, energy_percentage, poise_percentage): (f64, f64, f64) =
if self.health.is_dead {
(0.0, 0.0, 0.0)
@ -520,6 +533,83 @@ impl<'a> Skillbar<'a> {
.middle_of(state.ids.bg_poise)
.set(state.ids.frame_poise, ui);
}
if self
.global_state
.settings
.interface
.xp_bar_skillgroup
.is_some()
{
let offset = -81.0;
let selected_experience = &self
.global_state
.settings
.interface
.xp_bar_skillgroup
.unwrap_or(SkillGroupKind::General);
let current_exp = self.skillset.available_experience(*selected_experience) as f64;
let max_exp = self.skillset.skill_point_cost(*selected_experience) as f64;
let exp_percentage = current_exp / max_exp.max(1.0);
let level = self.skillset.earned_sp(*selected_experience).to_string();
// Exp Bar
Image::new(self.imgs.exp_frame_bg)
.w_h(594.0, 8.0)
.mid_top_with_margin_on(state.ids.frame, -offset)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.9)))
.set(state.ids.exp_frame_bg, ui);
Image::new(self.imgs.exp_frame)
.w_h(594.0, 8.0)
.middle_of(state.ids.exp_frame_bg)
.set(state.ids.exp_frame, ui);
Image::new(self.imgs.bar_content)
.w_h(590.0 * exp_percentage, 4.0)
.color(Some(XP_COLOR))
.top_left_with_margins_on(state.ids.exp_frame, 2.0, 2.0)
.set(state.ids.exp_filling, ui);
// Exp Type and Level Display
Image::new(self.imgs.selected_exp_bg)
.w_h(34.0, 38.0)
.top_left_with_margins_on(state.ids.exp_frame, -39.0, 3.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.9)))
.set(state.ids.exp_img_frame_bg, ui);
if Button::image(self.imgs.selected_exp)
.w_h(34.0, 38.0)
.middle_of(state.ids.exp_img_frame_bg)
.set(state.ids.exp_img_frame, ui)
.was_clicked()
{
return Some(Event::OpenDiary(*selected_experience));
}
Text::new(&level)
.mid_bottom_with_margin_on(state.ids.exp_img_frame, 2.0)
.font_size(11)
.font_id(self.fonts.cyri.conrod_id)
.color(QUALITY_LEGENDARY)
.graphics_for(state.ids.exp_img_frame)
.set(state.ids.exp_lvl, ui);
Image::new(match selected_experience {
SkillGroupKind::General => self.imgs.swords_crossed,
SkillGroupKind::Weapon(ToolKind::Sword) => self.imgs.sword,
SkillGroupKind::Weapon(ToolKind::Hammer) => self.imgs.hammer,
SkillGroupKind::Weapon(ToolKind::Axe) => self.imgs.axe,
SkillGroupKind::Weapon(ToolKind::Sceptre) => self.imgs.sceptre,
SkillGroupKind::Weapon(ToolKind::Bow) => self.imgs.bow,
SkillGroupKind::Weapon(ToolKind::Staff) => self.imgs.staff,
SkillGroupKind::Weapon(ToolKind::Pick) => self.imgs.mining,
_ => self.imgs.nothing,
})
.w_h(24.0, 24.0)
.graphics_for(state.ids.exp_img_frame)
.mid_bottom_with_margin_on(state.ids.exp_img_frame, 13.0)
.set(state.ids.exp_img, ui);
}
// Bar Text
let bar_text = if self.health.is_dead {
Some((
@ -597,6 +687,7 @@ impl<'a> Skillbar<'a> {
.color(TEXT_COLOR)
.set(state.ids.poise_txt, ui);
}
None
}
fn show_slotbar(&mut self, state: &State, ui: &mut UiCell, slot_offset: f64) {
@ -910,7 +1001,7 @@ pub struct State {
}
impl<'a> Widget for Skillbar<'a> {
type Event = ();
type Event = Option<Event>;
type State = State;
type Style = ();
@ -950,7 +1041,7 @@ impl<'a> Widget for Skillbar<'a> {
.set(state.ids.frame, ui);
// Health, Energy and Poise bars
self.show_stat_bars(state, ui);
let event = self.show_stat_bars(state, ui);
// Slots
self.show_slotbar(state, ui, slot_offset);
@ -959,5 +1050,6 @@ impl<'a> Widget for Skillbar<'a> {
if let Some(combo_floater) = self.combo_floater {
self.show_combo_counter(combo_floater, state, ui);
}
event
}
}

View File

@ -1474,6 +1474,9 @@ impl PlayState for SessionState {
self.client.borrow_mut().swap_slots(slot_a, slot_b);
}
},
HudEvent::SelectExpBar(skillgroup) => {
global_state.settings.interface.xp_bar_skillgroup = skillgroup;
},
HudEvent::SplitSwapSlots {
slot_a,
slot_b,

View File

@ -2,7 +2,7 @@ use crate::{
hud::{BarNumbers, BuffPosition, CrosshairType, Intro, ShortcutNumbers, XpBar},
ui::ScaleMode,
};
use common::comp::skillset::SkillGroupKind;
use serde::{Deserialize, Serialize};
/// `InterfaceSettings` contains UI, HUD and Map options.
@ -48,6 +48,7 @@ pub struct InterfaceSettings {
pub minimap_face_north: bool,
pub minimap_zoom: f64,
pub accum_experience: bool,
pub xp_bar_skillgroup: Option<SkillGroupKind>,
}
impl Default for InterfaceSettings {
@ -92,6 +93,7 @@ impl Default for InterfaceSettings {
minimap_face_north: true,
minimap_zoom: 160.0,
accum_experience: true,
xp_bar_skillgroup: Some(SkillGroupKind::General),
}
}
}