Graying out skills with insufficient energy no longer dependent on hard-coded values

This commit is contained in:
Samuel Keiffer 2020-11-27 16:27:09 +00:00 committed by Marcel
parent 19eee6dad3
commit 352917d9cb
10 changed files with 115 additions and 104 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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" => {

View File

@ -1927,6 +1927,7 @@ impl Hud {
let character_states = ecs.read_storage::<comp::CharacterState>();
let controllers = ecs.read_storage::<comp::Controller>();
let inventories = ecs.read_storage::<comp::Inventory>();
let ability_map = ecs.fetch::<comp::item::tool::AbilityMap>();
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);
}

View File

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

View File

@ -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<HotbarSource<'a>, HotbarImageSource<'a>> for HotbarSlot {
@ -98,57 +104,49 @@ impl<'a> SlotKey<HotbarSource<'a>, 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<Color>)> {
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<u32> {
fn amount(&self, (hotbar, inventory, _, _, _): &HotbarSource<'a>) -> Option<u32> {
hotbar
.get(*self)
.and_then(|content| match content {

View File

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

View File

@ -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
};