mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Skill point gains are displayed in hud.
level up message visuals and functionality Handles simultaneous skill point gains in UI.
This commit is contained in:
parent
cb3e44a811
commit
4b52574750
BIN
assets/voxygen/element/buttons/slot_skilltree.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/buttons/slot_skilltree.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/misc_bg/level_down.png
(Stored with Git LFS)
BIN
assets/voxygen/element/misc_bg/level_down.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/element/misc_bg/level_up.png
(Stored with Git LFS)
BIN
assets/voxygen/element/misc_bg/level_up.png
(Stored with Git LFS)
Binary file not shown.
@ -100,6 +100,7 @@
|
||||
"common.weapons.bow": "Bogen",
|
||||
"common.weapons.hammer": "Hammer",
|
||||
"common.weapons.sceptre": "Druiden Szepter",
|
||||
"common.weapons.general": "Kampf",
|
||||
/// End Common section
|
||||
|
||||
|
||||
@ -205,6 +206,7 @@ https://veloren.net/account/.
|
||||
// SCT outputs
|
||||
"hud.sct.experience": "{amount} Erf",
|
||||
"hud.sct.block": "GEBLOCKT",
|
||||
"hud.rank_up": "Neuer Rang",
|
||||
|
||||
/// Respawn message
|
||||
"hud.press_key_to_respawn": r#"Drückt {key} um am letzten Lagerfeuer wiederbelebt zu werden."#,
|
||||
|
@ -62,6 +62,7 @@ Is the client up to date?"#,
|
||||
"common.weapons.staff": "Staff",
|
||||
"common.weapons.bow": "Bow",
|
||||
"common.weapons.hammer": "Hammer",
|
||||
"common.weapons.general": "General Combat",
|
||||
"common.weapons.sceptre": "Healing Sceptre",
|
||||
"common.rand_appearance": "Random appearance and name",
|
||||
},
|
||||
|
@ -6,6 +6,7 @@
|
||||
// SCT outputs
|
||||
"hud.sct.experience": "{amount} Exp",
|
||||
"hud.sct.block": "BLOCKED",
|
||||
"hud.rank_up": "New Rank",
|
||||
},
|
||||
|
||||
|
||||
|
@ -544,11 +544,8 @@ impl Skill {
|
||||
|
||||
/// Returns the cost in skill points of unlocking a particular skill
|
||||
pub fn skill_cost(self, level: Level) -> u16 {
|
||||
use Skill::*;
|
||||
match self {
|
||||
General(GeneralSkill::HealthIncrease) => 1,
|
||||
_ => level.unwrap_or(1),
|
||||
}
|
||||
// TODO: Better balance the costs later
|
||||
level.unwrap_or(1)
|
||||
}
|
||||
|
||||
/// Returns the maximum level a skill can reach, returns None if the skill
|
||||
|
@ -33,6 +33,11 @@ pub enum Outcome {
|
||||
uid: Uid,
|
||||
exp: i32,
|
||||
},
|
||||
SkillPointGain {
|
||||
uid: Uid,
|
||||
skill_tree: comp::skills::SkillGroupType,
|
||||
total_points: u16,
|
||||
},
|
||||
}
|
||||
|
||||
impl Outcome {
|
||||
@ -43,6 +48,7 @@ impl Outcome {
|
||||
Outcome::LevelUp { pos } => Some(*pos),
|
||||
Outcome::Beam { pos, .. } => Some(*pos),
|
||||
Outcome::ExpChange { .. } => None,
|
||||
Outcome::SkillPointGain { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,13 @@ use common::{
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
metrics::SysMetrics,
|
||||
outcome::Outcome,
|
||||
resources::DeltaTime,
|
||||
span,
|
||||
uid::Uid,
|
||||
};
|
||||
use hashbrown::HashSet;
|
||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
|
||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage};
|
||||
|
||||
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
||||
|
||||
@ -26,6 +28,8 @@ impl<'a> System<'a> for Sys {
|
||||
WriteStorage<'a, Stats>,
|
||||
WriteStorage<'a, Health>,
|
||||
WriteStorage<'a, Energy>,
|
||||
ReadStorage<'a, Uid>,
|
||||
Write<'a, Vec<Outcome>>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
@ -39,6 +43,8 @@ impl<'a> System<'a> for Sys {
|
||||
mut stats,
|
||||
mut healths,
|
||||
mut energies,
|
||||
uids,
|
||||
mut outcomes,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let start_time = std::time::Instant::now();
|
||||
@ -53,8 +59,9 @@ impl<'a> System<'a> for Sys {
|
||||
healths.set_event_emission(true);
|
||||
|
||||
// Update stats
|
||||
for (entity, mut stats, mut health) in (
|
||||
for (entity, uid, mut stats, mut health) in (
|
||||
&entities,
|
||||
&uids,
|
||||
&mut stats.restrict_mut(),
|
||||
&mut healths.restrict_mut(),
|
||||
)
|
||||
@ -91,6 +98,11 @@ impl<'a> System<'a> for Sys {
|
||||
stat.skill_set
|
||||
.change_experience(skill_group, -(skill_group.skill_point_cost() as i32));
|
||||
stat.skill_set.add_skill_points(skill_group, 1);
|
||||
outcomes.push(Outcome::SkillPointGain {
|
||||
uid: *uid,
|
||||
skill_tree: skill_group,
|
||||
total_points: stat.skill_set.get_earned_sp(skill_group),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ impl SfxMgr {
|
||||
audio.play_sfx(file_ref, *pos, None);
|
||||
}
|
||||
},
|
||||
Outcome::ExpChange { .. } => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,7 @@ image_ids! {
|
||||
diary_exp_frame: "voxygen.element.misc_bg.diary_exp_frame",
|
||||
|
||||
// Skill Trees
|
||||
slot_skills: "voxygen.element.buttons.slot_skilltree",
|
||||
swords_crossed: "voxygen.element.icons.swords_crossed",
|
||||
sceptre: "voxygen.element.icons.sceptre",
|
||||
sword: "voxygen.element.icons.sword",
|
||||
@ -179,7 +180,6 @@ image_ids! {
|
||||
|
||||
// Skillbar
|
||||
level_up: "voxygen.element.misc_bg.level_up",
|
||||
level_down:"voxygen.element.misc_bg.level_down",
|
||||
bar_content: "voxygen.element.skillbar.bar_content",
|
||||
skillbar_bg: "voxygen.element.skillbar.bg",
|
||||
skillbar_frame: "voxygen.element.skillbar.frame",
|
||||
|
@ -56,11 +56,12 @@ use crate::{
|
||||
GlobalState,
|
||||
};
|
||||
use client::Client;
|
||||
|
||||
use common::{
|
||||
comp,
|
||||
comp::{
|
||||
item::{ItemDesc, Quality},
|
||||
skills::Skill,
|
||||
item::{tool::ToolKind, ItemDesc, Quality},
|
||||
skills::{Skill, SkillGroupType},
|
||||
BuffKind,
|
||||
},
|
||||
outcome::Outcome,
|
||||
@ -77,6 +78,7 @@ use conrod_core::{
|
||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use inline_tweak::*;
|
||||
use rand::Rng;
|
||||
use specs::{Join, WorldExt};
|
||||
use std::{
|
||||
@ -177,6 +179,13 @@ widget_ids! {
|
||||
// SCT
|
||||
player_scts[],
|
||||
player_sct_bgs[],
|
||||
player_rank_up,
|
||||
player_rank_up_txt_number,
|
||||
player_rank_up_txt_0,
|
||||
player_rank_up_txt_0_bg,
|
||||
player_rank_up_txt_1,
|
||||
player_rank_up_txt_1_bg,
|
||||
player_rank_up_icon,
|
||||
sct_exp_bgs[],
|
||||
sct_exps[],
|
||||
sct_lvl_bg,
|
||||
@ -293,6 +302,13 @@ pub struct ExpFloater {
|
||||
pub rand_offset: (f32, f32),
|
||||
}
|
||||
|
||||
pub struct SkillPointGain {
|
||||
pub owner: Uid,
|
||||
pub skill_tree: SkillGroupType,
|
||||
pub total_points: u16,
|
||||
pub timer: f32,
|
||||
}
|
||||
|
||||
pub struct DebugInfo {
|
||||
pub tps: f64,
|
||||
pub frame_time: Duration,
|
||||
@ -690,6 +706,7 @@ pub struct Hud {
|
||||
events: Vec<Event>,
|
||||
crosshair_opacity: f32,
|
||||
exp_floaters: Vec<ExpFloater>,
|
||||
skill_point_displays: Vec<SkillPointGain>,
|
||||
}
|
||||
|
||||
impl Hud {
|
||||
@ -789,6 +806,7 @@ impl Hud {
|
||||
events: Vec::new(),
|
||||
crosshair_opacity: 0.0,
|
||||
exp_floaters: Vec::new(),
|
||||
skill_point_displays: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -868,8 +886,7 @@ impl Hud {
|
||||
.graphics_for(ui_widgets.window)
|
||||
.color(Some(Color::Rgba(0.0, 0.0, 0.0, 1.0)))
|
||||
.set(self.ids.death_bg, ui_widgets);
|
||||
}
|
||||
// Crosshair
|
||||
} // Crosshair
|
||||
let show_crosshair = (info.is_aiming || info.is_first_person) && !health.is_dead;
|
||||
self.crosshair_opacity = Lerp::lerp(
|
||||
self.crosshair_opacity,
|
||||
@ -1084,17 +1101,16 @@ impl Hud {
|
||||
);
|
||||
// Increase font size based on fraction of maximum health
|
||||
// "flashes" by having a larger size in the first 100ms
|
||||
let font_size_xp = 30
|
||||
+ ((floater.exp_change as f32 / 300.0).min(1.0) * 50.0) as u32
|
||||
+ if floater.timer < 0.1 {
|
||||
FLASH_MAX * (((1.0 - floater.timer / 0.1) * 10.0) as u32)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let font_size_xp =
|
||||
30 + ((floater.exp_change as f32 / 300.0).min(1.0) * 50.0) as u32;
|
||||
let y = floater.timer as f64 * number_speed; // Timer sets the widget offset
|
||||
let fade = ((4.0 - floater.timer as f32) * 0.25) + 0.2; // Timer sets text transparency
|
||||
|
||||
//let fade = ((4.0 - floater.timer as f32) * 0.25) + 0.2; // Timer sets
|
||||
// text transparency
|
||||
let fade = if floater.timer < 1.0 {
|
||||
floater.timer as f32
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
Text::new(&format!("{} Exp", floater.exp_change))
|
||||
.font_size(font_size_xp)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -1116,6 +1132,90 @@ impl Hud {
|
||||
floater.timer -= dt.as_secs_f32();
|
||||
}
|
||||
}
|
||||
// Skill points
|
||||
self.skill_point_displays.retain(|d| d.timer > 0_f32);
|
||||
if let Some(uid) = uids.get(me) {
|
||||
if let Some(display) = self
|
||||
.skill_point_displays
|
||||
.iter_mut()
|
||||
.find(|d| d.owner == *uid)
|
||||
{
|
||||
let fade = if display.timer < 1.0 {
|
||||
display.timer as f32
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
// Background image
|
||||
Image::new(self.imgs.level_up)
|
||||
.w_h(328.0, 126.0)
|
||||
.mid_top_with_margin_on(ui_widgets.window, tweak!(300.0))
|
||||
.graphics_for(ui_widgets.window)
|
||||
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade)))
|
||||
.set(self.ids.player_rank_up, ui_widgets);
|
||||
// Rank Number
|
||||
let rank = display.total_points;
|
||||
Text::new(&format!("{}", rank))
|
||||
.font_size(tweak!(20))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(1.0, 1.0, 1.0, fade))
|
||||
.mid_top_with_margin_on(self.ids.player_rank_up, tweak!(8.0))
|
||||
.set(self.ids.player_rank_up_txt_number, ui_widgets);
|
||||
// Static "New Rank!" text
|
||||
Text::new(&i18n.get("hud.rank_up"))
|
||||
.font_size(tweak!(40))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
|
||||
.mid_bottom_with_margin_on(self.ids.player_rank_up, tweak!(20.0))
|
||||
.set(self.ids.player_rank_up_txt_0_bg, ui_widgets);
|
||||
Text::new(&i18n.get("hud.rank_up"))
|
||||
.font_size(tweak!(40))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(1.0, 1.0, 1.0, fade))
|
||||
.bottom_left_with_margins_on(self.ids.player_rank_up_txt_0_bg, 2.0, 2.0)
|
||||
.set(self.ids.player_rank_up_txt_0, ui_widgets);
|
||||
// Variable skilltree text
|
||||
let skill = match display.skill_tree {
|
||||
General => &i18n.get("common.weapons.general"),
|
||||
Weapon(ToolKind::Hammer) => &i18n.get("common.weapons.hammer"),
|
||||
Weapon(ToolKind::Axe) => &i18n.get("common.weapons.axe"),
|
||||
Weapon(ToolKind::Sword) => &i18n.get("common.weapons.sword"),
|
||||
Weapon(ToolKind::Sceptre) => &i18n.get("common.weapons.sceptre"),
|
||||
Weapon(ToolKind::Bow) => &i18n.get("common.weapons.bow"),
|
||||
Weapon(ToolKind::Staff) => &i18n.get("common.weapons.staff"),
|
||||
_ => "Unknown",
|
||||
};
|
||||
Text::new(skill)
|
||||
.font_size(tweak!(20))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
|
||||
.mid_top_with_margin_on(self.ids.player_rank_up, tweak!(45.0))
|
||||
.set(self.ids.player_rank_up_txt_1_bg, ui_widgets);
|
||||
Text::new(skill)
|
||||
.font_size(tweak!(20))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(Color::Rgba(1.0, 1.0, 1.0, fade))
|
||||
.bottom_left_with_margins_on(self.ids.player_rank_up_txt_1_bg, 2.0, 2.0)
|
||||
.set(self.ids.player_rank_up_txt_1, ui_widgets);
|
||||
// Variable skilltree icon
|
||||
use crate::hud::SkillGroupType::{General, Weapon};
|
||||
Image::new(match display.skill_tree {
|
||||
General => self.imgs.swords_crossed,
|
||||
Weapon(ToolKind::Hammer) => self.imgs.hammer,
|
||||
Weapon(ToolKind::Axe) => self.imgs.axe,
|
||||
Weapon(ToolKind::Sword) => self.imgs.sword,
|
||||
Weapon(ToolKind::Sceptre) => self.imgs.sceptre,
|
||||
Weapon(ToolKind::Bow) => self.imgs.bow,
|
||||
Weapon(ToolKind::Staff) => self.imgs.staff,
|
||||
_ => self.imgs.swords_crossed,
|
||||
})
|
||||
.w_h(tweak!(20.0), tweak!(20.0))
|
||||
.left_from(self.ids.player_rank_up_txt_1_bg, tweak!(5.0))
|
||||
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade)))
|
||||
.set(self.ids.player_rank_up_icon, ui_widgets);
|
||||
|
||||
display.timer -= dt.as_secs_f32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pop speech bubbles
|
||||
@ -2782,6 +2882,16 @@ impl Hud {
|
||||
timer: 4.0,
|
||||
rand_offset: rand::thread_rng().gen::<(f32, f32)>(),
|
||||
}),
|
||||
Outcome::SkillPointGain {
|
||||
uid,
|
||||
skill_tree,
|
||||
total_points,
|
||||
} => self.skill_point_displays.push(SkillPointGain {
|
||||
owner: *uid,
|
||||
skill_tree: *skill_tree,
|
||||
total_points: *total_points,
|
||||
timer: 5.0,
|
||||
}),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user