mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Wired up skill UI to check for prerequisites being met and sufficient skill points.
available SP check in general HUD, more skill icons Trimmed 2000 lines from a file. UI tweaks
This commit is contained in:
parent
4b52574750
commit
986c05621a
BIN
assets/voxygen/element/buttons/arrow_down_gold.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/buttons/arrow_down_gold.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/leap_cost.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/leap_cost.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/leap_damage.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/leap_damage.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/leap_distance.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/leap_distance.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/leap_knockback.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/leap_knockback.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/leap_radius.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/leap_radius.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/spin_amount.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/spin_amount.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/spin_cost.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/spin_cost.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/spin_damage.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/spin_damage.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/spin_helicopter.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/spin_helicopter.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/spin_infinite.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/spin_infinite.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/spin_speed.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/skilltree/spin_speed.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/skilltree/unlock_bow.png
(Stored with Git LFS)
BIN
assets/voxygen/element/icons/skilltree/unlock_bow.png
(Stored with Git LFS)
Binary file not shown.
@ -280,11 +280,7 @@ magically infused items?"#,
|
||||
"hud.bag.feet": "Feet",
|
||||
"hud.bag.mainhand": "Mainhand",
|
||||
"hud.bag.offhand": "Offhand",
|
||||
|
||||
// Diary
|
||||
"hud.diary": "Diary",
|
||||
|
||||
|
||||
|
||||
// Map and Questlog
|
||||
"hud.map.map_title": "Map",
|
||||
"hud.map.qlog_title": "Quests",
|
||||
@ -397,7 +393,7 @@ magically infused items?"#,
|
||||
"hud.crafting.recipes": "Recipes",
|
||||
"hud.crafting.ingredients": "Ingredients:",
|
||||
"hud.crafting.craft": "Craft",
|
||||
"hud.crafting.tool_cata": "Requires:",
|
||||
"hud.crafting.tool_cata": "Requires:",
|
||||
|
||||
"hud.group": "Group",
|
||||
"hud.group.invite_to_join": "{name} invited you to their group!",
|
||||
|
@ -8,6 +8,7 @@
|
||||
"hud.quests": "Quests",
|
||||
"hud.you_died": "You Died",
|
||||
"hud.waypoint_saved": "Waypoint Saved",
|
||||
"hud.sp_arrow_txt": "SP",
|
||||
|
||||
"hud.press_key_to_show_keybindings_fmt": "[{key}] Keybindings",
|
||||
"hud.press_key_to_toggle_lantern_fmt": "[{key}] Lantern",
|
||||
@ -64,6 +65,8 @@ Maybe you can even obtain one of their
|
||||
magically infused items?"#,
|
||||
|
||||
"hud.spell": "Spells",
|
||||
// Diary
|
||||
"hud.diary": "Diary",
|
||||
|
||||
"hud.free_look_indicator": "Free look active. Press {key} to disable.",
|
||||
"hud.auto_walk_indicator": "Auto walk active",
|
||||
|
@ -6,7 +6,7 @@ use hashbrown::{HashMap, HashSet};
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::hash::Hash;
|
||||
use tracing::warn;
|
||||
use tracing::{trace, warn};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct SkillTreeMap(HashMap<SkillGroupType, HashSet<Skill>>);
|
||||
@ -338,8 +338,8 @@ impl SkillSet {
|
||||
} else {
|
||||
skill.get_max_level().map(|_| 1)
|
||||
};
|
||||
let prerequisites_met = self.prerequisites_met(skill, next_level);
|
||||
if !matches!(self.skills.get(&skill), Some(&None)) {
|
||||
let prerequisites_met = self.prerequisites_met(skill);
|
||||
if !matches!(self.skills.get(&skill), Some(level) if *level == skill.get_max_level()) {
|
||||
if let Some(mut skill_group) = self
|
||||
.skill_groups
|
||||
.iter_mut()
|
||||
@ -359,16 +359,16 @@ impl SkillSet {
|
||||
}
|
||||
self.skills.insert(skill, next_level);
|
||||
} else {
|
||||
warn!("Tried to unlock skill for skill group with insufficient SP");
|
||||
trace!("Tried to unlock skill for skill group with insufficient SP");
|
||||
}
|
||||
} else {
|
||||
warn!("Tried to unlock skill without meeting prerequisite skills");
|
||||
trace!("Tried to unlock skill without meeting prerequisite skills");
|
||||
}
|
||||
} else {
|
||||
warn!("Tried to unlock skill for a skill group that player does not have");
|
||||
trace!("Tried to unlock skill for a skill group that player does not have");
|
||||
}
|
||||
} else {
|
||||
warn!("Tried to unlock skill the player already has")
|
||||
trace!("Tried to unlock skill the player already has")
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
@ -488,8 +488,13 @@ impl SkillSet {
|
||||
|
||||
/// Checks that the skill set contains all prerequisite skills for a
|
||||
/// particular skill
|
||||
pub fn prerequisites_met(&self, skill: Skill, level: Level) -> bool {
|
||||
skill.prerequisite_skills(level).iter().all(|(s, l)| {
|
||||
pub fn prerequisites_met(&self, skill: Skill) -> bool {
|
||||
let next_level = if self.skills.contains_key(&skill) {
|
||||
self.skills.get(&skill).copied().flatten().map(|l| l + 1)
|
||||
} else {
|
||||
skill.get_max_level().map(|_| 1)
|
||||
};
|
||||
skill.prerequisite_skills(next_level).iter().all(|(s, l)| {
|
||||
self.skills.contains_key(s) && self.skills.get(s).map_or(false, |l_b| l_b >= l)
|
||||
})
|
||||
}
|
||||
@ -520,6 +525,37 @@ impl SkillSet {
|
||||
.filter(|s_g| s_g.skill_group_type == skill_group);
|
||||
skill_groups.next().map_or(0, |s_g| s_g.exp)
|
||||
}
|
||||
|
||||
/// Checks if player has sufficient skill points to purchase a skill
|
||||
pub fn sufficient_skill_points(&self, skill: Skill) -> bool {
|
||||
if let Some(skill_group_type) = SkillSet::get_skill_group_type_for_skill(&skill) {
|
||||
if let Some(skill_group) = self
|
||||
.skill_groups
|
||||
.iter()
|
||||
.find(|x| x.skill_group_type == skill_group_type)
|
||||
{
|
||||
let next_level = if self.skills.contains_key(&skill) {
|
||||
self.skills.get(&skill).copied().flatten().map(|l| l + 1)
|
||||
} else {
|
||||
skill.get_max_level().map(|_| 1)
|
||||
};
|
||||
let needed_sp = skill.skill_cost(next_level);
|
||||
skill_group.available_sp > needed_sp
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the player has available SP to spend
|
||||
pub fn has_available_sp(&self) -> bool {
|
||||
self.skill_groups.iter().any(|sg| {
|
||||
sg.available_sp > 0
|
||||
&& (sg.earned_sp - sg.available_sp) < sg.skill_group_type.get_max_skill_points()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Skill {
|
||||
@ -528,10 +564,7 @@ impl Skill {
|
||||
pub fn prerequisite_skills(self, level: Level) -> HashMap<Skill, Level> {
|
||||
let mut prerequisites = HashMap::new();
|
||||
if let Some(level) = level {
|
||||
if level > self.get_max_level().unwrap_or(0) {
|
||||
// Sets a prerequisite of itself for skills beyond the max level
|
||||
prerequisites.insert(self, Some(level));
|
||||
} else if level > 1 {
|
||||
if level > 1 {
|
||||
// For skills above level 1, sets prerequisite of skill of lower level
|
||||
prerequisites.insert(self, Some(level - 1));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
img_ids::{Imgs, ImgsRot},
|
||||
BLACK, CRITICAL_HP_COLOR, LOW_HP_COLOR, TEXT_COLOR,
|
||||
BLACK, CRITICAL_HP_COLOR, LOW_HP_COLOR, QUALITY_LEGENDARY, TEXT_COLOR,
|
||||
};
|
||||
use crate::{
|
||||
i18n::Localization,
|
||||
@ -11,10 +11,10 @@ use crate::{
|
||||
use client::Client;
|
||||
use common::comp::Stats;
|
||||
use conrod_core::{
|
||||
widget::{self, Button, Text},
|
||||
widget::{self, Button, Image, Text},
|
||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
|
||||
use inline_tweak::*;
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
bag,
|
||||
@ -42,6 +42,9 @@ widget_ids! {
|
||||
crafting_text,
|
||||
crafting_text_bg,
|
||||
group_button,
|
||||
sp_arrow,
|
||||
sp_arrow_txt_bg,
|
||||
sp_arrow_txt,
|
||||
}
|
||||
}
|
||||
#[derive(WidgetCommon)]
|
||||
@ -57,6 +60,7 @@ pub struct Buttons<'a> {
|
||||
tooltip_manager: &'a mut TooltipManager,
|
||||
localized_strings: &'a Localization,
|
||||
stats: &'a Stats,
|
||||
pulse: f32,
|
||||
}
|
||||
|
||||
impl<'a> Buttons<'a> {
|
||||
@ -71,6 +75,7 @@ impl<'a> Buttons<'a> {
|
||||
tooltip_manager: &'a mut TooltipManager,
|
||||
localized_strings: &'a Localization,
|
||||
stats: &'a Stats,
|
||||
pulse: f32,
|
||||
) -> Self {
|
||||
Self {
|
||||
client,
|
||||
@ -83,6 +88,7 @@ impl<'a> Buttons<'a> {
|
||||
tooltip_manager,
|
||||
localized_strings,
|
||||
stats,
|
||||
pulse,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,6 +128,9 @@ impl<'a> Widget for Buttons<'a> {
|
||||
None => return None,
|
||||
};
|
||||
let localized_strings = self.localized_strings;
|
||||
let arrow_ani =
|
||||
(self.pulse * tweak!(4.0)/* speed factor */).cos() * tweak!(0.5) + tweak!(0.8); //Animation timer
|
||||
|
||||
let button_tooltip = Tooltip::new({
|
||||
// Edge images [t, b, r, l]
|
||||
// Corner images [tr, tl, br, bl]
|
||||
@ -326,22 +335,26 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.map_text, ui);
|
||||
}
|
||||
|
||||
// Spellbook
|
||||
if Button::image(self.imgs.spellbook_button)
|
||||
.w_h(28.0, 25.0)
|
||||
.left_from(state.ids.map_button, 10.0)
|
||||
.hover_image(self.imgs.spellbook_hover)
|
||||
.press_image(self.imgs.spellbook_press)
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
&localized_strings.get("hud.diary"),
|
||||
"",
|
||||
&button_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.spellbook_button, ui)
|
||||
.was_clicked()
|
||||
// Diary
|
||||
let unspent_sp = self.stats.skill_set.has_available_sp();
|
||||
if Button::image(if !unspent_sp {
|
||||
self.imgs.spellbook_button
|
||||
} else {
|
||||
self.imgs.spellbook_hover
|
||||
})
|
||||
.w_h(28.0, 25.0)
|
||||
.left_from(state.ids.map_button, 10.0)
|
||||
.hover_image(self.imgs.spellbook_hover)
|
||||
.press_image(self.imgs.spellbook_press)
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
&localized_strings.get("hud.diary"),
|
||||
"",
|
||||
&button_tooltip,
|
||||
TEXT_COLOR,
|
||||
)
|
||||
.set(state.ids.spellbook_button, ui)
|
||||
.was_clicked()
|
||||
{
|
||||
return Some(Event::ToggleSpell);
|
||||
}
|
||||
@ -364,7 +377,32 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.spellbook_text, ui);
|
||||
}
|
||||
|
||||
// Unspent SP indicator
|
||||
if unspent_sp {
|
||||
Image::new(self.imgs.sp_indicator_arrow)
|
||||
.w_h(20.0, 11.0)
|
||||
.graphics_for(state.ids.spellbook_button)
|
||||
.mid_top_with_margin_on(
|
||||
state.ids.spellbook_button,
|
||||
tweak!(-12.0) + arrow_ani as f64,
|
||||
)
|
||||
.color(Some(QUALITY_LEGENDARY))
|
||||
.set(state.ids.sp_arrow, ui);
|
||||
Text::new(&localized_strings.get("hud.sp_arrow_txt"))
|
||||
.mid_top_with_margin_on(state.ids.sp_arrow, tweak!(-18.0))
|
||||
.graphics_for(state.ids.spellbook_button)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(tweak!(14)))
|
||||
.color(BLACK)
|
||||
.set(state.ids.sp_arrow_txt_bg, ui);
|
||||
Text::new(&localized_strings.get("hud.sp_arrow_txt"))
|
||||
.graphics_for(state.ids.spellbook_button)
|
||||
.bottom_right_with_margins_on(state.ids.sp_arrow_txt_bg, 1.0, 1.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(tweak!(14)))
|
||||
.color(QUALITY_LEGENDARY)
|
||||
.set(state.ids.sp_arrow_txt, ui);
|
||||
}
|
||||
// Crafting
|
||||
if Button::image(self.imgs.crafting_icon)
|
||||
.w_h(25.0, 25.0)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -71,27 +71,47 @@ impl State {
|
||||
use specs::WorldExt;
|
||||
let inventories = client.state().ecs().read_storage::<Inventory>();
|
||||
let inventory = inventories.get(client.entity());
|
||||
let should_be_present = if let Some(inventory) = inventory {
|
||||
let stats = client.state().ecs().read_storage::<common::comp::Stats>();
|
||||
let stat = stats.get(client.entity());
|
||||
let should_be_present = if let (Some(inventory), Some(stat)) = (inventory, stat) {
|
||||
inventory
|
||||
.equipped(EquipSlot::Mainhand)
|
||||
.map(|i| i.kind())
|
||||
.filter(|kind| {
|
||||
use common::comp::item::{
|
||||
tool::{ToolKind, UniqueKind},
|
||||
ItemKind,
|
||||
use common::comp::{
|
||||
item::{
|
||||
tool::{ToolKind, UniqueKind},
|
||||
ItemKind,
|
||||
},
|
||||
skills::{self, Skill},
|
||||
};
|
||||
if let ItemKind::Tool(kind) = kind {
|
||||
matches!(
|
||||
&kind.kind,
|
||||
ToolKind::Staff
|
||||
| ToolKind::Debug
|
||||
| ToolKind::Sword
|
||||
| ToolKind::Hammer
|
||||
| ToolKind::Axe
|
||||
| ToolKind::Bow
|
||||
| ToolKind::Unique(UniqueKind::QuadMedQuick)
|
||||
| ToolKind::Unique(UniqueKind::QuadLowBreathe)
|
||||
)
|
||||
if let ItemKind::Tool(tool) = kind {
|
||||
match tool.kind {
|
||||
ToolKind::Sword => stat
|
||||
.skill_set
|
||||
.skills
|
||||
.contains_key(&Skill::Sword(skills::SwordSkill::SUnlockSpin)),
|
||||
ToolKind::Axe => stat
|
||||
.skill_set
|
||||
.skills
|
||||
.contains_key(&Skill::Axe(skills::AxeSkill::LUnlockLeap)),
|
||||
ToolKind::Hammer => stat
|
||||
.skill_set
|
||||
.skills
|
||||
.contains_key(&Skill::Hammer(skills::HammerSkill::LUnlockLeap)),
|
||||
ToolKind::Bow => stat
|
||||
.skill_set
|
||||
.skills
|
||||
.contains_key(&Skill::Bow(skills::BowSkill::UnlockRepeater)),
|
||||
ToolKind::Staff => stat
|
||||
.skill_set
|
||||
.skills
|
||||
.contains_key(&Skill::Staff(skills::StaffSkill::UnlockShockwave)),
|
||||
ToolKind::Debug
|
||||
| ToolKind::Unique(UniqueKind::QuadMedQuick)
|
||||
| ToolKind::Unique(UniqueKind::QuadLowBreathe) => true,
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -147,6 +147,8 @@ image_ids! {
|
||||
group_icon_hover: "voxygen.element.buttons.group_hover",
|
||||
group_icon_press: "voxygen.element.buttons.group_press",
|
||||
|
||||
sp_indicator_arrow: "voxygen.element.buttons.arrow_down_gold",
|
||||
|
||||
// Skill Icons
|
||||
twohsword_m1: "voxygen.element.icons.2hsword_m1",
|
||||
twohsword_m2: "voxygen.element.icons.2hsword_m2",
|
||||
|
@ -1895,6 +1895,7 @@ impl Hud {
|
||||
tooltip_manager,
|
||||
i18n,
|
||||
&player_stats,
|
||||
self.pulse,
|
||||
)
|
||||
.set(self.ids.buttons, ui_widgets)
|
||||
{
|
||||
|
@ -37,6 +37,8 @@ use iced::{
|
||||
};
|
||||
use vek::Rgba;
|
||||
|
||||
use inline_tweak::*;
|
||||
|
||||
pub const TEXT_COLOR: iced::Color = iced::Color::from_rgb(1.0, 1.0, 1.0);
|
||||
pub const DISABLED_TEXT_COLOR: iced::Color = iced::Color::from_rgba(1.0, 1.0, 1.0, 0.2);
|
||||
pub const TOOLTIP_BACK_COLOR: Rgba<u8> = Rgba::new(20, 18, 10, 255);
|
||||
@ -444,7 +446,7 @@ impl Controls {
|
||||
select_button,
|
||||
Column::with_children(vec![
|
||||
Text::new(&character.character.alias)
|
||||
.size(fonts.cyri.scale(30))
|
||||
.size(fonts.cyri.scale(tweak!(26)))
|
||||
.into(),
|
||||
// TODO: only construct string once when characters
|
||||
// are
|
||||
|
Loading…
Reference in New Issue
Block a user