aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Alexander Foremny <aforemny@posteo.de>2024-03-18 04:19:34 +0100
committerLibravatar Alexander Foremny <aforemny@posteo.de>2024-03-18 04:19:34 +0100
commit937e1ed8d240c1a5b42f5b8cf1104321b9d79c4a (patch)
treec9cc6f8ec35e3e9b1ba97b5fd42091cf0ab2afb6
parentab675360c0005718a3c9b8b5e7962af897269c04 (diff)
fix: fix abilities selecting the right cooldown
-rw-r--r--src/client.rs98
-rw-r--r--src/server.rs42
-rw-r--r--src/shared/ability.rs53
-rw-r--r--src/shared/champion.rs10
-rw-r--r--src/shared/cooldown.rs17
-rw-r--r--src/shared/imperative.rs15
6 files changed, 118 insertions, 117 deletions
diff --git a/src/client.rs b/src/client.rs
index e3c4594..7ccced7 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -47,7 +47,7 @@ struct ClientId(pub u64);
struct MyChampion(pub Champion);
#[derive(Resource)]
-struct Attack(Option<AttackKey>);
+struct Attack(Option<AbilitySlot>);
struct ClientPlugin {
pub server_addr: Option<SocketAddr>,
@@ -100,26 +100,10 @@ impl Plugin for ClientPlugin {
}
#[derive(Component, PartialEq, Eq, Debug)]
-pub enum Hotbar {
- A,
- Q,
- W,
- E,
- R,
- F,
- G,
-}
+pub struct Hotbar(AbilitySlot);
#[derive(Component, PartialEq, Eq, Debug)]
-pub enum HotbarCooldown {
- A,
- Q,
- W,
- E,
- R,
- F,
- G,
-}
+pub struct HotbarCooldown(AbilitySlot);
fn setup(mut client: ClientMut, mut commands: Commands, champion: Res<MyChampion>) {
commands.spawn(Camera2dBundle::default());
@@ -137,7 +121,10 @@ fn setup(mut client: ClientMut, mut commands: Commands, champion: Res<MyChampion
..Default::default()
})
.with_children(|builder| {
- let mut hotkey = |label, hotbar, hotbar_cooldown| {
+ let mut hotkey = |ability_slot: AbilitySlot| {
+ let label = ability_slot.to_label();
+ let hotbar = Hotbar(ability_slot);
+ let hotbar_cooldown = HotbarCooldown(ability_slot);
builder
.spawn(NodeBundle {
style: Style {
@@ -186,13 +173,9 @@ fn setup(mut client: ClientMut, mut commands: Commands, champion: Res<MyChampion
));
});
};
- hotkey("A", Hotbar::A, HotbarCooldown::A);
- hotkey("Q", Hotbar::Q, HotbarCooldown::Q);
- hotkey("W", Hotbar::W, HotbarCooldown::W);
- hotkey("E", Hotbar::E, HotbarCooldown::E);
- hotkey("R", Hotbar::R, HotbarCooldown::R);
- hotkey("F", Hotbar::F, HotbarCooldown::F);
- hotkey("G", Hotbar::G, HotbarCooldown::G);
+ for ability_slot in AbilitySlot::all() {
+ hotkey(ability_slot);
+ }
});
client.connect().unwrap();
client
@@ -273,7 +256,7 @@ fn buffer_input(
if mouse_input.just_pressed(MouseButton::Left) {
match attack.0 {
Some(attack_key) => match champion.0.to_ability(attack_key) {
- Ability::Directional(ability) => {
+ Ability::Directional(_) => {
let Some(world_position) = cursor_world_position(&windows, &cameras) else {
return;
};
@@ -284,18 +267,18 @@ fn buffer_input(
return;
};
client.add_input(Inputs::Imperative(Imperative::AttackDirection(
- ability, direction,
+ attack_key, direction,
)));
attack.0 = None;
}
- Ability::Targeted(ability) => {
+ Ability::Targeted(_) => {
let Some((target_player, _)) =
hovered_other_player(&cameras, &client_id, &players, &windows)
else {
return;
};
client.add_input(Inputs::Imperative(Imperative::AttackTarget(
- ability,
+ attack_key,
target_player,
)));
attack.0 = None;
@@ -306,7 +289,7 @@ fn buffer_input(
hovered_other_player(&cameras, &client_id, &players, &windows)
{
client.add_input(Inputs::Imperative(Imperative::AttackTarget(
- TargetedAbility::MeeleAttack,
+ AbilitySlot::A,
target_player,
)));
} else {
@@ -321,19 +304,19 @@ fn buffer_input(
fn choose_attack(keyboard_input: Res<ButtonInput<KeyCode>>, mut attack_key: ResMut<Attack>) {
if keyboard_input.just_pressed(KeyCode::KeyA) {
- attack_key.0 = Some(AttackKey::A);
+ attack_key.0 = Some(AbilitySlot::A);
} else if keyboard_input.just_pressed(KeyCode::KeyQ) {
- attack_key.0 = Some(AttackKey::Q);
+ attack_key.0 = Some(AbilitySlot::Q);
} else if keyboard_input.just_pressed(KeyCode::KeyW) {
- attack_key.0 = Some(AttackKey::W);
+ attack_key.0 = Some(AbilitySlot::W);
} else if keyboard_input.just_pressed(KeyCode::KeyE) {
- attack_key.0 = Some(AttackKey::E);
+ attack_key.0 = Some(AbilitySlot::E);
} else if keyboard_input.just_pressed(KeyCode::KeyR) {
- attack_key.0 = Some(AttackKey::R);
+ attack_key.0 = Some(AbilitySlot::R);
} else if keyboard_input.just_pressed(KeyCode::KeyF) {
- attack_key.0 = Some(AttackKey::F);
+ attack_key.0 = Some(AbilitySlot::F);
} else if keyboard_input.just_pressed(KeyCode::KeyG) {
- attack_key.0 = Some(AttackKey::G);
+ attack_key.0 = Some(AbilitySlot::G);
} else if keyboard_input.just_pressed(KeyCode::Escape) {
attack_key.0 = None;
}
@@ -413,7 +396,7 @@ fn gizmos_attack_indicator(
return;
};
let Some(attack_key) = attack.0.or_else(|| {
- hovered_other_player(&cameras, &client_id, &hoverables, &windows).map(|_| AttackKey::A)
+ hovered_other_player(&cameras, &client_id, &hoverables, &windows).map(|_| AbilitySlot::A)
}) else {
return;
};
@@ -480,16 +463,7 @@ fn hotbar_cooldown(
return;
};
for (hotbar_cooldown, mut text, mut style) in hotbar_cooldowns.iter_mut() {
- let cooldown = (match hotbar_cooldown {
- HotbarCooldown::A => cooldown.a_cooldown,
- HotbarCooldown::Q => cooldown.q_cooldown,
- HotbarCooldown::W => cooldown.w_cooldown,
- HotbarCooldown::E => cooldown.e_cooldown,
- HotbarCooldown::R => cooldown.r_cooldown,
- HotbarCooldown::F => cooldown.f_cooldown,
- HotbarCooldown::G => cooldown.g_cooldown,
- })
- .as_secs_f32();
+ let cooldown = cooldown.0[hotbar_cooldown.0].as_secs_f32();
if text.sections.len() <= 0 {
continue;
}
@@ -523,17 +497,7 @@ fn hotbar_hotbar_display(
return;
};
for (hotbar, mut style) in hotbars.iter_mut() {
- let cooldown = (match hotbar {
- Hotbar::A => cooldown.a_cooldown,
- Hotbar::Q => cooldown.q_cooldown,
- Hotbar::W => cooldown.w_cooldown,
- Hotbar::E => cooldown.e_cooldown,
- Hotbar::R => cooldown.r_cooldown,
- Hotbar::F => cooldown.f_cooldown,
- Hotbar::G => cooldown.g_cooldown,
- })
- .as_secs_f32();
- if cooldown <= 0. {
+ if cooldown.0[hotbar.0].as_secs_f32() <= 0. {
style.display = Display::Flex;
} else {
style.display = Display::None;
@@ -542,19 +506,11 @@ fn hotbar_hotbar_display(
}
fn hotbar_hotbar_highlight(attack: Res<Attack>, mut hotbars: Query<(&Hotbar, &mut Text)>) {
- let Some(attack_key) = attack.0 else {
+ let Some(ability_slot) = attack.0 else {
return;
};
for (hotbar, mut text) in hotbars.iter_mut() {
- let is_highlighted = match attack_key {
- AttackKey::A => *hotbar == Hotbar::A,
- AttackKey::Q => *hotbar == Hotbar::Q,
- AttackKey::W => *hotbar == Hotbar::W,
- AttackKey::E => *hotbar == Hotbar::E,
- AttackKey::R => *hotbar == Hotbar::R,
- AttackKey::F => *hotbar == Hotbar::F,
- AttackKey::G => *hotbar == Hotbar::G,
- };
+ let is_highlighted = ability_slot == hotbar.0;
if text.sections.len() <= 0 {
continue;
}
diff --git a/src/server.rs b/src/server.rs
index 165c5f0..038f854 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -1,5 +1,6 @@
use crate::protocol::*;
use crate::server::network::*;
+use crate::shared::ability::*;
use crate::shared::champion::*;
use crate::shared::cooldown::*;
use crate::shared::health::*;
@@ -9,7 +10,6 @@ use crate::shared::player::*;
use crate::shared::projectile::*;
use crate::shared::*;
use bevy::prelude::*;
-use bevy::utils::Duration;
use bevy::utils::HashMap;
use lightyear::prelude::*;
use lightyear::server::events::MessageEvent;
@@ -247,13 +247,17 @@ fn imperative_attack_attack(
champions: Query<&Champion>,
) {
for (id, mut imperative) in players.iter_mut() {
+ let Some(entity) = entity_map.0.get(&id.0) else {
+ *imperative = Imperative::Idle;
+ return;
+ };
+ let Ok(champion) = champions.get(*entity) else {
+ *imperative = Imperative::Idle;
+ return;
+ };
match *imperative {
- Imperative::AttackTarget(ability, target_player) => {
- let Some(entity) = entity_map.0.get(&id.0) else {
- *imperative = Imperative::Idle;
- return;
- };
- let Ok(champion) = champions.get(*entity) else {
+ Imperative::AttackTarget(ability_slot, target_player) => {
+ let Ability::Targeted(ability) = champion.to_ability(ability_slot) else {
*imperative = Imperative::Idle;
return;
};
@@ -273,8 +277,9 @@ fn imperative_attack_attack(
*imperative = Imperative::Idle;
return;
};
- if cooldown.a_cooldown.is_zero() {
- cooldown.a_cooldown = Duration::from_secs_f32(1.5);
+ let base_cooldown = BaseCooldown::from_champion(*champion);
+ if cooldown.0[ability_slot].is_zero() {
+ cooldown.0[ability_slot] = base_cooldown.0[ability_slot];
commands.spawn(ProjectileBundle::new(ability.to_projectile(
*id,
position.0,
@@ -283,8 +288,8 @@ fn imperative_attack_attack(
}
}
}
- Imperative::AttackDirection(ability, direction) => {
- let Some(entity) = entity_map.0.get(&id.0) else {
+ Imperative::AttackDirection(ability_slot, direction) => {
+ let Ability::Directional(ability) = champion.to_ability(ability_slot) else {
*imperative = Imperative::Idle;
return;
};
@@ -296,8 +301,9 @@ fn imperative_attack_attack(
*imperative = Imperative::Idle;
return;
};
- if cooldown.a_cooldown.is_zero() {
- cooldown.a_cooldown = Duration::from_secs_f32(1.5);
+ let base_cooldown = BaseCooldown::from_champion(*champion);
+ if cooldown.0[ability_slot].is_zero() {
+ cooldown.0[ability_slot] = base_cooldown.0[ability_slot];
commands.spawn(ProjectileBundle::new(
ability.to_projectile(*id, position.0, direction),
));
@@ -435,13 +441,11 @@ fn projectile_despawn(
}
fn cooldown_decrement(mut cooldowns: Query<&mut Cooldown>, time: Res<Time>) {
+ let dt = time.delta();
for mut cooldown in cooldowns.iter_mut() {
- cooldown.a_cooldown = cooldown.a_cooldown.saturating_sub(time.delta());
- cooldown.q_cooldown = cooldown.q_cooldown.saturating_sub(time.delta());
- cooldown.w_cooldown = cooldown.w_cooldown.saturating_sub(time.delta());
- cooldown.e_cooldown = cooldown.e_cooldown.saturating_sub(time.delta());
- cooldown.d_cooldown = cooldown.d_cooldown.saturating_sub(time.delta());
- cooldown.f_cooldown = cooldown.f_cooldown.saturating_sub(time.delta());
+ for ability_slot in AbilitySlot::all() {
+ cooldown.0[ability_slot] = cooldown.0[ability_slot].saturating_sub(dt);
+ }
}
}
diff --git a/src/shared/ability.rs b/src/shared/ability.rs
index 9639afe..cab7ae6 100644
--- a/src/shared/ability.rs
+++ b/src/shared/ability.rs
@@ -1,6 +1,8 @@
use crate::shared::player::*;
use crate::shared::projectile::*;
use crate::shared::*;
+use bevy::utils::Duration;
+use std::ops::*;
#[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)]
pub enum Ability {
@@ -64,3 +66,54 @@ impl DirectionalAbility {
}
}
}
+
+#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+pub enum AbilitySlot {
+ A,
+ Q,
+ W,
+ E,
+ R,
+ F,
+ G,
+}
+
+impl AbilitySlot {
+ pub fn to_label(self) -> &'static str {
+ match self {
+ AbilitySlot::A => "A",
+ AbilitySlot::Q => "Q",
+ AbilitySlot::W => "W",
+ AbilitySlot::E => "E",
+ AbilitySlot::R => "R",
+ AbilitySlot::F => "F",
+ AbilitySlot::G => "G",
+ }
+ }
+
+ pub fn all() -> Vec<Self> {
+ vec![
+ AbilitySlot::A,
+ AbilitySlot::Q,
+ AbilitySlot::W,
+ AbilitySlot::E,
+ AbilitySlot::R,
+ AbilitySlot::F,
+ AbilitySlot::G,
+ ]
+ }
+}
+
+impl Index<AbilitySlot> for [Duration; 7] {
+ type Output = Duration;
+
+ fn index(&self, ability_slot: AbilitySlot) -> &Self::Output {
+ &self[ability_slot as usize]
+ }
+}
+
+impl IndexMut<AbilitySlot> for [Duration; 7] {
+ fn index_mut(&mut self, ability_slot: AbilitySlot) -> &mut Self::Output {
+ &mut self[ability_slot as usize]
+ }
+}
diff --git a/src/shared/champion.rs b/src/shared/champion.rs
index 8de12a5..28d1ff2 100644
--- a/src/shared/champion.rs
+++ b/src/shared/champion.rs
@@ -40,14 +40,14 @@ impl Stats {
}
impl Champion {
- pub fn to_ability(self, attack_key: AttackKey) -> Ability {
+ pub fn to_ability(self, ability_slot: AbilitySlot) -> Ability {
match self {
- Champion::Meele => match attack_key {
- AttackKey::Q => Ability::Directional(DirectionalAbility::Spear),
+ Champion::Meele => match ability_slot {
+ AbilitySlot::Q => Ability::Directional(DirectionalAbility::Spear),
_ => Ability::Targeted(TargetedAbility::MeeleAttack),
},
- Champion::Ranged => match attack_key {
- AttackKey::Q => Ability::Directional(DirectionalAbility::Spear),
+ Champion::Ranged => match ability_slot {
+ AbilitySlot::Q => Ability::Directional(DirectionalAbility::Spear),
_ => Ability::Targeted(TargetedAbility::RangedAttack),
},
}
diff --git a/src/shared/cooldown.rs b/src/shared/cooldown.rs
index f27d7fc..2d6b6ae 100644
--- a/src/shared/cooldown.rs
+++ b/src/shared/cooldown.rs
@@ -5,13 +5,12 @@ use serde::Serialize;
use std::default::Default;
#[derive(Component, Message, Serialize, Deserialize, Clone, Copy, PartialEq, Debug, Default)]
-pub struct Cooldown {
- pub a_cooldown: Duration,
- pub q_cooldown: Duration,
- pub w_cooldown: Duration,
- pub e_cooldown: Duration,
- pub r_cooldown: Duration,
- pub d_cooldown: Duration,
- pub f_cooldown: Duration,
- pub g_cooldown: Duration,
+pub struct Cooldown(pub [Duration; 7]);
+
+pub struct BaseCooldown(pub [Duration; 7]);
+
+impl BaseCooldown {
+ pub fn from_champion(_champion: Champion) -> Self {
+ BaseCooldown([1., 5., 5., 10., 25., 50., 50.].map(Duration::from_secs_f32))
+ }
}
diff --git a/src/shared/imperative.rs b/src/shared/imperative.rs
index afdf244..44a0e43 100644
--- a/src/shared/imperative.rs
+++ b/src/shared/imperative.rs
@@ -8,17 +8,6 @@ use serde::Serialize;
pub enum Imperative {
Idle,
WalkTo(Vec2),
- AttackTarget(TargetedAbility, PlayerId),
- AttackDirection(DirectionalAbility, Vec2),
-}
-
-#[derive(Resource, Copy, Clone, PartialEq, Debug, Deserialize, Serialize)]
-pub enum AttackKey {
- A,
- Q,
- W,
- E,
- R,
- F,
- G,
+ AttackTarget(AbilitySlot, PlayerId),
+ AttackDirection(AbilitySlot, Vec2),
}