diff options
author | Alexander Foremny <aforemny@posteo.de> | 2024-03-20 07:09:22 +0100 |
---|---|---|
committer | Alexander Foremny <aforemny@posteo.de> | 2024-03-20 07:09:22 +0100 |
commit | 445a51c344ecea346051cf59d03b95c98bb28e75 (patch) | |
tree | 33f0327659b9f8ea0422b2452c8ec48e532cef3c /src | |
parent | 716bd0618308d6100556d1231b0b156f48c64778 (diff) |
feat: flash ability
Diffstat (limited to 'src')
-rw-r--r-- | src/client.rs | 29 | ||||
-rw-r--r-- | src/shared/ability.rs | 35 | ||||
-rw-r--r-- | src/shared/champion.rs | 6 |
3 files changed, 56 insertions, 14 deletions
diff --git a/src/client.rs b/src/client.rs index b4213a2..ce48b4f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -295,9 +295,7 @@ fn buffer_input( let Some(position) = player_position(&client_id, &players) else { return; }; - let Some(direction) = (world_position - position.0).try_normalize() else { - return; - }; + let direction = world_position - position.0; client.add_input(Inputs::Imperative(Imperative::AttackDirection( ability_slot, direction, @@ -340,6 +338,7 @@ fn buffer_input( fn choose_attack( champion: Res<MyChampion>, keyboard_input: Res<ButtonInput<KeyCode>>, + mouse_input: Res<ButtonInput<MouseButton>>, mut attack: ResMut<Attack>, mut client: ClientMut, ) { @@ -359,7 +358,9 @@ fn choose_attack( attack.0 = Some(AbilitySlot::G); } else if keyboard_input.just_pressed(KeyCode::Escape) { attack.0 = None; - } else if keyboard_input.just_pressed(KeyCode::ShiftLeft) { + } else if keyboard_input.just_pressed(KeyCode::CapsLock) { + attack.0 = None; + } else if mouse_input.just_pressed(MouseButton::Right) { attack.0 = None; } match attack.0 { @@ -459,20 +460,26 @@ fn gizmos_attack_indicator( let Some(world_position) = cursor_world_position(&windows, &cameras) else { return; }; - let Some(direction) = (world_position - position.0).try_normalize() else { - return; - }; + let direction = world_position - position.0; match ability { DirectionalAbility::Dash(Dash { max_distance, .. }) => { let DashCollisionResult { dash_end, .. } = dash_collision( PlayerId(client_id.0), position.0, - direction, + direction.normalize_or_zero(), max_distance, &player_positions, ); gizmos.arrow_2d(position.0, dash_end, Color::YELLOW); } + DirectionalAbility::Flash(Flash { max_distance, .. }) => { + gizmos.arrow_2d( + position.0, + position.0 + + direction.length().min(max_distance) * direction.normalize_or_zero(), + Color::YELLOW, + ); + } DirectionalAbility::Pull(Pull { max_distance, .. }) => { let Some(PullCollision { pull_end, @@ -481,12 +488,12 @@ fn gizmos_attack_indicator( }) = pull_collision( PlayerId(client_id.0), position.0, - direction, + direction.normalize_or_zero(), max_distance, &player_positions, ) else { - let pull_direction = -max_distance * direction; + let pull_direction = -max_distance * direction.normalize_or_zero(); let pull_start = position.0 - pull_direction; let pull_end = pull_start + (pull_direction.length() - 2. * PLAYER_RADIUS) @@ -499,7 +506,7 @@ fn gizmos_attack_indicator( DirectionalAbility::Spear(Spear { max_distance, .. }) => { gizmos.arrow_2d( position.0, - position.0 + max_distance * direction, + position.0 + max_distance * direction.normalize_or_zero(), Color::YELLOW, ); } diff --git a/src/shared/ability.rs b/src/shared/ability.rs index 8decfc6..b7b3664 100644 --- a/src/shared/ability.rs +++ b/src/shared/ability.rs @@ -180,6 +180,7 @@ fn speed_activation(speed: Speed) -> ActivatedAbilityActivation { #[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)] pub enum DirectionalAbility { Dash(Dash), + Flash(Flash), Pull(Pull), Spear(Spear), } @@ -191,6 +192,11 @@ pub struct Dash { } #[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)] +pub struct Flash { + pub max_distance: f32, +} + +#[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)] pub struct Pull { pub max_distance: f32, pub damage: f32, @@ -202,18 +208,41 @@ pub struct Spear { pub damage: f32, } +// `direction: Vec2` is NOT normalized (cf. `Flash`)! pub type DirectionalAbilityActivation = Box<dyn FnOnce(&mut Commands, PlayerId, Vec2) -> ()>; impl DirectionalAbility { pub fn activate(self) -> DirectionalAbilityActivation { match self { DirectionalAbility::Dash(dash) => dash_activation(dash), + DirectionalAbility::Flash(flash) => flash_activation(flash), DirectionalAbility::Pull(pull) => pull_activation(pull), DirectionalAbility::Spear(spear) => spear_activation(spear), } } } +fn flash_activation(flash: Flash) -> DirectionalAbilityActivation { + Box::new( + move |commands: &mut Commands, source_player: PlayerId, direction: Vec2| { + commands.add(move |world: &mut World| { + world.run_system_once( + move |entity_map: Res<EntityMap>, mut positions: Query<&mut PlayerPosition>| { + let Some(entity_id) = entity_map.0.get(&source_player.0) else { + return; + }; + let Ok(mut position) = positions.get_mut(*entity_id) else { + return; + }; + position.0 += direction.length().min(flash.max_distance) + * direction.normalize_or_zero(); + }, + ); + }); + }, + ) +} + fn dash_activation(dash: Dash) -> DirectionalAbilityActivation { Box::new( move |commands: &mut Commands, source_player: PlayerId, direction: Vec2| { @@ -259,7 +288,7 @@ fn dash_activation(dash: Dash) -> DirectionalAbilityActivation { dash_collision( source_player, source_position.0, - direction, + direction.normalize_or_zero(), dash.max_distance, &dash_targets, ) @@ -409,7 +438,7 @@ fn pull_activation(pull: Pull) -> DirectionalAbilityActivation { pull_collision( source_player, source_position.0, - direction, + direction.normalize_or_zero(), pull.max_distance, &pull_targets, ) @@ -520,7 +549,7 @@ fn spear_activation(spear: Spear) -> DirectionalAbilityActivation { commands.spawn(ProjectileBundle::new(Projectile { type_: ProjectileType::Free(FreeProjectile { position: position.0, - direction, + direction: direction.normalize_or_zero(), starting_position: position.0, max_distance: spear.max_distance, scale_damage: Some((0.75, 2.5)), diff --git a/src/shared/champion.rs b/src/shared/champion.rs index ecd6e10..f48faa1 100644 --- a/src/shared/champion.rs +++ b/src/shared/champion.rs @@ -64,6 +64,9 @@ impl Champion { AbilitySlot::R => { Ability::Targeted(TargetedAbility::MeeleAttack(MeeleAttack { damage: 45. })) } + AbilitySlot::F => { + Ability::Directional(DirectionalAbility::Flash(Flash { max_distance: 100. })) + } AbilitySlot::G => { Ability::Activated(ActivatedAbility::Speed(Speed { duration: 2.5 })) } @@ -77,6 +80,9 @@ impl Champion { AbilitySlot::R => { Ability::Activated(ActivatedAbility::Focus(Focus { duration: 5. })) } + AbilitySlot::F => { + Ability::Directional(DirectionalAbility::Flash(Flash { max_distance: 100. })) + } AbilitySlot::G => { Ability::Activated(ActivatedAbility::Speed(Speed { duration: 2.5 })) } |