diff options
author | Alexander Foremny <aforemny@posteo.de> | 2024-03-19 07:36:54 +0100 |
---|---|---|
committer | Alexander Foremny <aforemny@posteo.de> | 2024-03-19 07:36:54 +0100 |
commit | 2e39423d11a6cd1e25b54c30d9afd22e8eff9dfe (patch) | |
tree | 204e0bfc8f69c1ca57daa449b1eed723e43ef40c /src | |
parent | 9d8bf0fde7b12fa77569333d17f310e55df58db9 (diff) |
feat: shield ability
Diffstat (limited to 'src')
-rw-r--r-- | src/client.rs | 12 | ||||
-rw-r--r-- | src/server.rs | 19 | ||||
-rw-r--r-- | src/shared/ability.rs | 42 | ||||
-rw-r--r-- | src/shared/buffs.rs | 1 | ||||
-rw-r--r-- | src/shared/champion.rs | 4 | ||||
-rw-r--r-- | src/shared/health.rs | 18 | ||||
-rw-r--r-- | src/shared/player.rs | 5 |
7 files changed, 85 insertions, 16 deletions
diff --git a/src/client.rs b/src/client.rs index 5084eaa..8da77dc 100644 --- a/src/client.rs +++ b/src/client.rs @@ -522,11 +522,13 @@ fn render_health(players: Query<(&Health, &PlayerPosition, &EffectiveStats)>, mu for (health, position, effective_stats) in players.iter() { let start = position.0 + Vec2::new(-PLAYER_RADIUS, PLAYER_RADIUS + HEALTH_OFFSET); let end = position.0 + Vec2::new(PLAYER_RADIUS, PLAYER_RADIUS + HEALTH_OFFSET); - gizmos.line_2d( - start, - start.lerp(end, health.0 / effective_stats.0.max_health), - Color::RED, - ); + let health_start = start; + let health_end = start.lerp(end, health.health / effective_stats.0.max_health); + let px_per_health = (end.x - start.x) / effective_stats.0.max_health; + let shield_start = health_end; + let shield_end = health_end + Vec2::new(health.shield * px_per_health, 0.); + gizmos.line_2d(health_start, health_end, Color::RED); + gizmos.line_2d(shield_start, shield_end, Color::GRAY); } } diff --git a/src/server.rs b/src/server.rs index 483314d..fc44120 100644 --- a/src/server.rs +++ b/src/server.rs @@ -55,7 +55,7 @@ impl Plugin for ServerPlugin { .add_systems(Update, (connects, disconnects)) .add_systems(Update, receive_message) .add_systems(FixedUpdate, timers_tick) - .add_systems(FixedUpdate, effective_stats) + .add_systems(FixedUpdate, effective_stats.after(buffs_despawn)) .add_systems(FixedUpdate, health_regen.after(timers_tick)) .add_systems( FixedUpdate, @@ -466,7 +466,7 @@ fn projectile_despawn( if let Some(target_player) = maybe_target_player { if let Some(target_entity) = entity_map.0.get(&target_player.0) { if let Ok(mut health) = healths.get_mut(*target_entity) { - health.0 = (health.0 - projectile.damage).max(0.); + health.apply_damage(projectile.damage); let _ = connection_manager .send_message_to_target::<Channel1, HealthChanged>( HealthChanged(HealthEvent { @@ -504,7 +504,7 @@ fn health_regen( ) { if health_regen_timer.0.just_finished() { for (target_player, mut health, effective_stats) in healths.iter_mut() { - health.0 = (health.0 + HEALTH_REGEN).min(effective_stats.0.max_health); + health.heal(HEALTH_REGEN, effective_stats.0.max_health); let _ = connection_manager.send_message_to_target::<Channel1, HealthChanged>( HealthChanged(HealthEvent { target_player: *target_player, @@ -531,7 +531,10 @@ fn effective_stats( stats.attack_speed *= 0.5; } effective_stats.0 = stats; - health.0 = health.0.min(effective_stats.0.max_health); + health.health = health.health.min(effective_stats.0.max_health); + if buffs.shield.is_none() { + health.shield = 0.; + } } } @@ -541,6 +544,9 @@ fn buffs_tick(mut buffses: Query<&mut Buffs>, time: Res<Time>) { if let Some(ref mut timer) = &mut buffs.haste { timer.tick(dt); } + if let Some(ref mut timer) = &mut buffs.shield { + timer.tick(dt); + } if let Some(ref mut timer) = &mut buffs.slow { timer.tick(dt); } @@ -557,6 +563,11 @@ fn buffs_despawn(mut buffses: Query<&mut Buffs>) { buffs.haste = None; } } + if let Some(timer) = &buffs.shield { + if timer.finished() { + buffs.shield = None; + } + } if let Some(timer) = &buffs.slow { if timer.finished() { buffs.slow = None; diff --git a/src/shared/ability.rs b/src/shared/ability.rs index b841661..80c74b2 100644 --- a/src/shared/ability.rs +++ b/src/shared/ability.rs @@ -59,6 +59,7 @@ impl TargetedAbility { pub enum ActivatedAbility { Focus(Focus), Haste(Haste), + Shield(Shield), Speed(Speed), } @@ -73,6 +74,12 @@ pub struct Haste { } #[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)] +pub struct Shield { + pub duration: f32, + pub blocked_damage: f32, +} + +#[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)] pub struct Speed { pub duration: f32, } @@ -84,12 +91,13 @@ impl ActivatedAbility { match self { ActivatedAbility::Focus(focus) => focus_activation(focus), ActivatedAbility::Haste(haste) => haste_activation(haste), + ActivatedAbility::Shield(shield) => shield_activation(shield), ActivatedAbility::Speed(speed) => speed_activation(speed), } } } -fn speed_activation(speed: Speed) -> ActivatedAbilityActivation { +fn focus_activation(focus: Focus) -> ActivatedAbilityActivation { Box::new(move |commands: &mut Commands, source_id: PlayerId| { commands.add(move |world: &mut World| { world.run_system_once( @@ -100,7 +108,8 @@ fn speed_activation(speed: Speed) -> ActivatedAbilityActivation { let Ok(mut buffs) = buffses.get_mut(*entity_id) else { return; }; - buffs.speed = Some(Timer::from_seconds(speed.duration, TimerMode::Once)); + buffs.haste = Some(Timer::from_seconds(focus.duration, TimerMode::Once)); + buffs.speed = Some(Timer::from_seconds(focus.duration, TimerMode::Once)); }, ) }); @@ -125,7 +134,31 @@ fn haste_activation(haste: Haste) -> ActivatedAbilityActivation { }) } -fn focus_activation(focus: Focus) -> ActivatedAbilityActivation { +fn shield_activation(shield: Shield) -> ActivatedAbilityActivation { + Box::new(move |commands: &mut Commands, source_id: PlayerId| { + commands.add(move |world: &mut World| { + world.run_system_once( + move |entity_map: Res<EntityMap>, + mut healths: Query<&mut Health>, + mut buffses: Query<&mut Buffs>| { + let Some(entity_id) = entity_map.0.get(&source_id.0) else { + return; + }; + let Ok(mut health) = healths.get_mut(*entity_id) else { + return; + }; + let Ok(mut buffs) = buffses.get_mut(*entity_id) else { + return; + }; + health.shield = health.shield + shield.blocked_damage; + buffs.shield = Some(Timer::from_seconds(shield.duration, TimerMode::Once)); + }, + ) + }); + }) +} + +fn speed_activation(speed: Speed) -> ActivatedAbilityActivation { Box::new(move |commands: &mut Commands, source_id: PlayerId| { commands.add(move |world: &mut World| { world.run_system_once( @@ -136,8 +169,7 @@ fn focus_activation(focus: Focus) -> ActivatedAbilityActivation { let Ok(mut buffs) = buffses.get_mut(*entity_id) else { return; }; - buffs.haste = Some(Timer::from_seconds(focus.duration, TimerMode::Once)); - buffs.speed = Some(Timer::from_seconds(focus.duration, TimerMode::Once)); + buffs.speed = Some(Timer::from_seconds(speed.duration, TimerMode::Once)); }, ) }); diff --git a/src/shared/buffs.rs b/src/shared/buffs.rs index e8992d5..6b518a5 100644 --- a/src/shared/buffs.rs +++ b/src/shared/buffs.rs @@ -3,6 +3,7 @@ use crate::shared::*; #[derive(Clone, Component, Default, Debug)] pub struct Buffs { pub haste: Option<Timer>, + pub shield: Option<Timer>, pub slow: Option<Timer>, pub speed: Option<Timer>, } diff --git a/src/shared/champion.rs b/src/shared/champion.rs index da63664..86bd41e 100644 --- a/src/shared/champion.rs +++ b/src/shared/champion.rs @@ -55,6 +55,10 @@ impl Champion { AbilitySlot::W => { Ability::Directional(DirectionalAbility::Pull(Pull { max_distance: 60. })) } + AbilitySlot::E => Ability::Activated(ActivatedAbility::Shield(Shield { + blocked_damage: 35., + duration: 2., + })), AbilitySlot::R => { Ability::Targeted(TargetedAbility::MeeleAttack(MeeleAttack { damage: 45. })) } diff --git a/src/shared/health.rs b/src/shared/health.rs index b88f19c..f9cc300 100644 --- a/src/shared/health.rs +++ b/src/shared/health.rs @@ -1,4 +1,20 @@ use crate::shared::*; #[derive(Component, Message, Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] -pub struct Health(pub f32); +pub struct Health { + pub health: f32, + pub shield: f32, +} + +impl Health { + pub fn apply_damage(&mut self, damage: f32) { + let shield_damage = damage.min(self.shield); + let health_damage = damage - shield_damage; + self.shield = self.shield - shield_damage; + self.health = (self.health - health_damage).max(0.); + } + + pub fn heal(&mut self, health: f32, max_health: f32) { + self.health = (self.health + health).min(max_health); + } +} diff --git a/src/shared/player.rs b/src/shared/player.rs index d1df3af..3805969 100644 --- a/src/shared/player.rs +++ b/src/shared/player.rs @@ -37,7 +37,10 @@ impl PlayerBundle { color: PlayerColor(color), imperative: Imperative::Idle, cooldown: Cooldown::default(), - health: Health(effective_stats.0.max_health), + health: Health { + health: effective_stats.0.max_health, + shield: 0., + }, champion, effective_stats, buffs: Buffs::default(), |