From f6ac9b43b50f1cabf7b4351c543188421610c36a Mon Sep 17 00:00:00 2001 From: Samuel Keiffer Date: Fri, 27 Nov 2020 16:27:09 +0000 Subject: [PATCH] Graying out skills with insufficient energy no longer dependent on hard-coded values --- .../common/abilities/staff/flamethrower.ron | 2 +- common/src/comp/ability.rs | 18 +++++ common/src/comp/inventory/item/tool.rs | 4 +- .../src/audio/sfx/event_mapper/combat/mod.rs | 6 +- voxygen/src/audio/sfx/mod.rs | 2 +- voxygen/src/hud/mod.rs | 2 + voxygen/src/hud/skillbar.rs | 70 ++++++++-------- voxygen/src/hud/slots.rs | 80 +++++++++---------- voxygen/src/scene/figure/mod.rs | 31 +++---- voxygen/src/scene/simple.rs | 4 +- 10 files changed, 115 insertions(+), 104 deletions(-) diff --git a/assets/common/abilities/staff/flamethrower.ron b/assets/common/abilities/staff/flamethrower.ron index 1fccd24fe3..bc63f1d9a9 100644 --- a/assets/common/abilities/staff/flamethrower.ron +++ b/assets/common/abilities/staff/flamethrower.ron @@ -9,6 +9,6 @@ BasicBeam( max_angle: 22.5, lifesteal_eff: 0.0, energy_regen: 0, - energy_cost: 0, + energy_cost: 1, energy_drain: 350, ) \ No newline at end of file diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 3c67571651..fc151b4f11 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -480,6 +480,24 @@ impl CharacterAbility { } self } + + pub fn get_energy_cost(&self) -> u32 { + use CharacterAbility::*; + match self { + BasicMelee { energy_cost, .. } + | BasicRanged { energy_cost, .. } + | RepeaterRanged { energy_cost, .. } + | DashMelee { energy_cost, .. } + | Roll { energy_cost, .. } + | LeapMelee { energy_cost, .. } + | SpinMelee { energy_cost, .. } + | ChargedMelee { energy_cost, .. } + | ChargedRanged { energy_cost, .. } + | Shockwave { energy_cost, .. } + | BasicBeam { energy_cost, .. } => *energy_cost, + _ => 0, + } + } } #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 296bdd9795..497e40f0c9 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fs::File, io::BufReader, time::Duration}; use tracing::error; -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ToolKind { Sword, Axe, @@ -168,7 +168,7 @@ impl Asset for AbilityMap { } } -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum UniqueKind { StoneGolemFist, BeastClaws, diff --git a/voxygen/src/audio/sfx/event_mapper/combat/mod.rs b/voxygen/src/audio/sfx/event_mapper/combat/mod.rs index 87345fa4cf..99e0a58e6b 100644 --- a/voxygen/src/audio/sfx/event_mapper/combat/mod.rs +++ b/voxygen/src/audio/sfx/event_mapper/combat/mod.rs @@ -146,15 +146,15 @@ impl CombatEventMapper { if character_state.is_attack() { return SfxEvent::Attack( CharacterAbilityType::from(character_state), - data.kind.clone(), + data.kind, ); } else if let Some(wield_event) = match ( previous_state.weapon_drawn, character_state.is_dodge(), Self::weapon_drawn(character_state), ) { - (false, false, true) => Some(SfxEvent::Wield(data.kind.clone())), - (true, false, false) => Some(SfxEvent::Unwield(data.kind.clone())), + (false, false, true) => Some(SfxEvent::Wield(data.kind)), + (true, false, false) => Some(SfxEvent::Unwield(data.kind)), _ => None, } { return wield_event; diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index 719e31578b..0f6a22b594 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -191,7 +191,7 @@ impl From<&InventoryUpdateEvent> for SfxEvent { // back to the default Collected event match &item.kind() { ItemKind::Tool(tool) => { - SfxEvent::Inventory(SfxInventoryEvent::CollectedTool(tool.kind.clone())) + SfxEvent::Inventory(SfxInventoryEvent::CollectedTool(tool.kind)) }, ItemKind::Ingredient { kind } => match &kind[..] { "ShinyGem" => { diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 62a253d72f..c6a1452f97 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -1927,6 +1927,7 @@ impl Hud { let character_states = ecs.read_storage::(); let controllers = ecs.read_storage::(); let inventories = ecs.read_storage::(); + let ability_map = ecs.fetch::(); if let ( Some(stats), Some(health), @@ -1963,6 +1964,7 @@ impl Hud { &mut self.slot_manager, &self.i18n, &self.show, + &ability_map, ) .set(self.ids.skillbar, ui_widgets); } diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 1f8a48eda0..3102f09dfe 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -17,7 +17,7 @@ use crate::{ }; use common::comp::{ item::{ - tool::{Tool, ToolKind}, + tool::{AbilityMap, Tool, ToolKind}, Hands, ItemKind, }, Energy, Health, Inventory, Loadout, Stats, @@ -138,6 +138,7 @@ pub struct Skillbar<'a> { #[conrod(common_builder)] common: widget::CommonBuilder, show: &'a Show, + ability_map: &'a AbilityMap, } impl<'a> Skillbar<'a> { @@ -161,6 +162,7 @@ impl<'a> Skillbar<'a> { slot_manager: &'a mut slots::SlotManager, localized_strings: &'a Localization, show: &'a Show, + ability_map: &'a AbilityMap, ) -> Self { Self { global_state, @@ -182,6 +184,7 @@ impl<'a> Skillbar<'a> { slot_manager, localized_strings, show, + ability_map, } } } @@ -470,7 +473,13 @@ impl<'a> Widget for Skillbar<'a> { .set(state.ids.stamina_txt, ui); } // Slots - let content_source = (self.hotbar, self.inventory, self.loadout, self.energy); // TODO: avoid this + let content_source = ( + self.hotbar, + self.inventory, + self.loadout, + self.energy, + self.ability_map, + ); // TODO: avoid this let image_source = (self.item_imgs, self.imgs); let mut slot_maker = SlotMaker { // TODO: is a separate image needed for the frame? @@ -646,22 +655,22 @@ impl<'a> Widget for Skillbar<'a> { .right_from(state.ids.m1_slot_bg, 0.0) .set(state.ids.m2_slot, ui); - let active_tool_kind = match self.loadout.active_item.as_ref().map(|i| i.item.kind()) { - Some(ItemKind::Tool(Tool { kind, .. })) => Some(kind), + let active_tool = match self.loadout.active_item.as_ref().map(|i| i.item.kind()) { + Some(ItemKind::Tool(tool)) => Some(tool), _ => None, }; - let second_tool_kind = match self.loadout.second_item.as_ref().map(|i| i.item.kind()) { - Some(ItemKind::Tool(Tool { kind, .. })) => Some(kind), + let second_tool = match self.loadout.second_item.as_ref().map(|i| i.item.kind()) { + Some(ItemKind::Tool(tool)) => Some(tool), _ => None, }; - let tool_kind = match ( - active_tool_kind.map(|tk| tk.hands()), - second_tool_kind.map(|tk| tk.hands()), + let tool = match ( + active_tool.map(|t| t.kind.hands()), + second_tool.map(|t| t.kind.hands()), ) { - (Some(Hands::TwoHand), _) => active_tool_kind, - (_, Some(Hands::OneHand)) => second_tool_kind, + (Some(Hands::TwoHand), _) => active_tool, + (_, Some(Hands::OneHand)) => second_tool, (_, _) => None, }; @@ -669,7 +678,7 @@ impl<'a> Widget for Skillbar<'a> { .w_h(40.0, 40.0) .middle_of(state.ids.m2_slot) .set(state.ids.m2_slot_bg, ui); - Button::image(match tool_kind { + Button::image(match tool.map(|t| t.kind) { Some(ToolKind::Sword) => self.imgs.twohsword_m2, Some(ToolKind::Dagger) => self.imgs.onehdagger_m2, Some(ToolKind::Shield) => self.imgs.onehshield_m2, @@ -683,30 +692,19 @@ impl<'a> Widget for Skillbar<'a> { }) .w_h(36.0, 36.0) .middle_of(state.ids.m2_slot_bg) - .image_color(match tool_kind { - // TODO Automate this to grey out unavailable M2 skills - Some(ToolKind::Sword) => { - if self.energy.current() as f64 >= 200.0 { - Color::Rgba(1.0, 1.0, 1.0, 1.0) - } else { - Color::Rgba(0.3, 0.3, 0.3, 0.8) - } - }, - Some(ToolKind::Sceptre) => { - if self.energy.current() as f64 >= 400.0 { - Color::Rgba(1.0, 1.0, 1.0, 1.0) - } else { - Color::Rgba(0.3, 0.3, 0.3, 0.8) - } - }, - Some(ToolKind::Axe) => { - if self.energy.current() as f64 >= 100.0 { - Color::Rgba(1.0, 1.0, 1.0, 1.0) - } else { - Color::Rgba(0.3, 0.3, 0.3, 0.8) - } - }, - _ => Color::Rgba(1.0, 1.0, 1.0, 1.0), + .image_color(if let Some(tool) = tool { + if self.energy.current() + >= tool + .get_abilities(self.ability_map) + .secondary + .get_energy_cost() + { + Color::Rgba(1.0, 1.0, 1.0, 1.0) + } else { + Color::Rgba(0.3, 0.3, 0.3, 0.8) + } + } else { + Color::Rgba(1.0, 1.0, 1.0, 1.0) }) .set(state.ids.m2_content, ui); // Slot 6-10 diff --git a/voxygen/src/hud/slots.rs b/voxygen/src/hud/slots.rs index f6ae54482c..f14f633921 100644 --- a/voxygen/src/hud/slots.rs +++ b/voxygen/src/hud/slots.rs @@ -6,7 +6,7 @@ use super::{ use crate::ui::slot::{self, SlotKey, SumSlot}; use common::comp::{ item::{ - tool::{Tool, ToolKind}, + tool::{AbilityMap, ToolKind}, ItemKind, }, Energy, Inventory, Loadout, @@ -90,7 +90,13 @@ pub enum HotbarImage { BowJumpBurst, } -type HotbarSource<'a> = (&'a hotbar::State, &'a Inventory, &'a Loadout, &'a Energy); +type HotbarSource<'a> = ( + &'a hotbar::State, + &'a Inventory, + &'a Loadout, + &'a Energy, + &'a AbilityMap, +); type HotbarImageSource<'a> = (&'a ItemImgs, &'a img_ids::Imgs); impl<'a> SlotKey, HotbarImageSource<'a>> for HotbarSlot { @@ -98,57 +104,49 @@ impl<'a> SlotKey, HotbarImageSource<'a>> for HotbarSlot { fn image_key( &self, - (hotbar, inventory, loadout, energy): &HotbarSource<'a>, + (hotbar, inventory, loadout, energy, ability_map): &HotbarSource<'a>, ) -> Option<(Self::ImageKey, Option)> { hotbar.get(*self).and_then(|contents| match contents { hotbar::SlotContents::Inventory(idx) => inventory .get(idx) .map(|item| HotbarImage::Item(item.into())) .map(|i| (i, None)), - hotbar::SlotContents::Ability3 => loadout - .active_item - .as_ref() - .map(|i| i.item.kind()) - .and_then(|kind| { - match kind { - ItemKind::Tool(Tool { kind, .. }) => match kind { - ToolKind::Staff => Some(HotbarImage::FireAoe), - ToolKind::Hammer => Some(HotbarImage::HammerLeap), - ToolKind::Axe => Some(HotbarImage::AxeLeapSlash), - ToolKind::Bow => Some(HotbarImage::BowJumpBurst), - ToolKind::Debug => Some(HotbarImage::SnakeArrow), - ToolKind::Sword => Some(HotbarImage::SwordWhirlwind), - _ => None, - }, + hotbar::SlotContents::Ability3 => { + let tool = match loadout.active_item.as_ref().map(|i| i.item.kind()) { + Some(ItemKind::Tool(tool)) => Some(tool), + _ => None, + }; + + tool.and_then(|tool| { + match tool.kind { + ToolKind::Staff => Some(HotbarImage::FireAoe), + ToolKind::Hammer => Some(HotbarImage::HammerLeap), + ToolKind::Axe => Some(HotbarImage::AxeLeapSlash), + ToolKind::Bow => Some(HotbarImage::BowJumpBurst), + ToolKind::Debug => Some(HotbarImage::SnakeArrow), + ToolKind::Sword => Some(HotbarImage::SwordWhirlwind), _ => None, } - .map(|image_key| match image_key { - HotbarImage::FireAoe => ( - image_key, - (energy.current() < 600).then_some(Color::Rgba(0.3, 0.3, 0.3, 0.8)), - ), - HotbarImage::HammerLeap => ( - image_key, - (energy.current() < 700).then_some(Color::Rgba(0.3, 0.3, 0.3, 0.8)), - ), - HotbarImage::AxeLeapSlash => ( - image_key, - (energy.current() < 450).then_some(Color::Rgba(0.3, 0.3, 0.3, 0.8)), - ), - HotbarImage::BowJumpBurst => ( - image_key, - (energy.current() < 450).then_some(Color::Rgba(0.3, 0.3, 0.3, 0.8)), - ), - _ => ( - image_key, - (energy.current() < 1000).then_some(Color::Rgba(1.0, 1.0, 1.0, 1.0)), - ), + .map(|i| { + ( + i, + if let Some(skill) = tool.get_abilities(ability_map).skills.get(0) { + if energy.current() >= skill.get_energy_cost() { + Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)) + } else { + Some(Color::Rgba(0.3, 0.3, 0.3, 0.8)) + } + } else { + Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)) + }, + ) }) - }), + }) + }, }) } - fn amount(&self, (hotbar, inventory, _, _): &HotbarSource<'a>) -> Option { + fn amount(&self, (hotbar, inventory, _, _, _): &HotbarSource<'a>) -> Option { hotbar .get(*self) .and_then(|content| match content { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index d1a5048653..d4e8f3372e 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -688,7 +688,7 @@ impl FigureMgr { .and_then(|l| l.active_item.as_ref()) .map(|i| i.item.kind()); let active_tool_kind = if let Some(ItemKind::Tool(tool)) = active_item_kind { - Some(tool.kind.clone()) + Some(tool.kind) } else { None }; @@ -698,7 +698,7 @@ impl FigureMgr { .map(|i| i.item.kind()); let second_tool_kind = if let Some(ItemKind::Tool(tool)) = second_item_kind { - Some(tool.kind.clone()) + Some(tool.kind) } else { None }; @@ -740,12 +740,7 @@ impl FigureMgr { // Standing (true, false, false) => anim::character::StandAnimation::update_skeleton( &CharacterSkeleton::default(), - ( - active_tool_kind.clone(), - second_tool_kind.clone(), - time, - state.avg_vel, - ), + (active_tool_kind, second_tool_kind, time, state.avg_vel), state.state_time, &mut state_animation_rate, skeleton_attr, @@ -754,8 +749,8 @@ impl FigureMgr { (true, true, false) => anim::character::RunAnimation::update_skeleton( &CharacterSkeleton::default(), ( - active_tool_kind.clone(), - second_tool_kind.clone(), + active_tool_kind, + second_tool_kind, vel.0, ori, state.last_ori, @@ -770,8 +765,8 @@ impl FigureMgr { (false, _, false) => anim::character::JumpAnimation::update_skeleton( &CharacterSkeleton::default(), ( - active_tool_kind.clone(), - second_tool_kind.clone(), + active_tool_kind, + second_tool_kind, ori, state.last_ori, time, @@ -784,8 +779,8 @@ impl FigureMgr { (_, _, true) => anim::character::SwimAnimation::update_skeleton( &CharacterSkeleton::default(), ( - active_tool_kind.clone(), - second_tool_kind.clone(), + active_tool_kind, + second_tool_kind, vel.0, ori, state.last_ori, @@ -2669,8 +2664,8 @@ impl FigureMgr { (true, true, false) => anim::biped_large::RunAnimation::update_skeleton( &BipedLargeSkeleton::default(), ( - active_tool_kind.clone(), - second_tool_kind.clone(), + active_tool_kind, + second_tool_kind, vel.0.magnitude(), ori, state.last_ori, @@ -2684,14 +2679,14 @@ impl FigureMgr { // In air (false, _, false) => anim::biped_large::JumpAnimation::update_skeleton( &BipedLargeSkeleton::default(), - (active_tool_kind.clone(), second_tool_kind.clone(), time), + (active_tool_kind, second_tool_kind, time), state.state_time, &mut state_animation_rate, skeleton_attr, ), _ => anim::biped_large::IdleAnimation::update_skeleton( &BipedLargeSkeleton::default(), - (active_tool_kind.clone(), second_tool_kind.clone(), time), + (active_tool_kind, second_tool_kind, time), state.state_time, &mut state_animation_rate, skeleton_attr, diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 30381a2beb..e1783f237c 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -299,7 +299,7 @@ impl Scene { .map(|i| i.item.kind()); let active_tool_kind = if let Some(ItemKind::Tool(tool)) = active_item_kind { - Some(tool.kind.clone()) + Some(tool.kind) } else { None }; @@ -309,7 +309,7 @@ impl Scene { .map(|i| i.item.kind()); let second_tool_kind = if let Some(ItemKind::Tool(tool)) = second_item_kind { - Some(tool.kind.clone()) + Some(tool.kind) } else { None };