diff options
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 153 |
1 files changed, 121 insertions, 32 deletions
diff --git a/src/server.rs b/src/server.rs index 038f854..0b15c5f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,6 +1,8 @@ use crate::protocol::*; use crate::server::network::*; use crate::shared::ability::*; +use crate::shared::activation::*; +use crate::shared::buffs::*; use crate::shared::champion::*; use crate::shared::cooldown::*; use crate::shared::health::*; @@ -8,6 +10,7 @@ use crate::shared::health_event::*; use crate::shared::imperative::*; use crate::shared::player::*; use crate::shared::projectile::*; +use crate::shared::stats::*; use crate::shared::*; use bevy::prelude::*; use bevy::utils::HashMap; @@ -53,13 +56,15 @@ 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, health_regen.after(timers_tick)) .add_systems( FixedUpdate, ( (imperative_attack_approach, imperative_attack_attack) .chain() - .after(cooldown_decrement), + .after(activation), + activation.after(cooldown_decrement), imperative_walk_to, ) .after(player_input), @@ -73,6 +78,7 @@ impl Plugin for ServerPlugin { .chain(), ) .add_systems(FixedUpdate, cooldown_decrement) + .add_systems(FixedUpdate, (buffs_despawn, buffs_tick).chain()) .add_systems(FixedUpdate, player_input); } } @@ -110,7 +116,7 @@ fn receive_message( let client_id = event.context(); let SelectChampion(champion) = event.message(); let Some(entity) = entity_map.0.get(client_id) else { - return; + continue; }; commands.entity(*entity).insert(*champion); } @@ -133,6 +139,7 @@ fn player_input( entity_map: Res<EntityMap>, mut input_reader: EventReader<server::InputEvent<Inputs>>, mut imperatives: Query<&mut Imperative>, + mut activations: Query<&mut Activation>, ) { for input in input_reader.read() { let client_id = input.context(); @@ -144,28 +151,31 @@ fn player_input( *imperative = *new_imperative; } } - _ => {} + Inputs::Activation(new_activation) => { + if let Ok(mut activation) = activations.get_mut(*entity_id) { + *activation = *new_activation; + } + } + Inputs::None => {} } } } } } -const MOVEMENT_SPEED: f32 = 80.; - fn imperative_walk_to( - mut players: Query<(Entity, &mut Imperative)>, + mut players: Query<(Entity, &mut Imperative, &EffectiveStats)>, mut positions: Query<&mut PlayerPosition>, time: Res<Time>, ) { - for (entity, mut imperative) in players.iter_mut() { + for (entity, mut imperative, effective_stats) in players.iter_mut() { match *imperative { Imperative::WalkTo(target_position) => { if let Ok(mut position) = positions.get_mut(entity) { let (new_position, target_reached) = move_to_target( position.0, target_position, - MOVEMENT_SPEED * time.delta().as_secs_f32(), + effective_stats.0.movement_speed * time.delta().as_secs_f32(), ); position.0 = new_position; if target_reached { @@ -197,38 +207,33 @@ fn move_along_direction(position: Vec2, direction: Vec2, distance: f32) -> Vec2 fn imperative_attack_approach( entity_map: Res<EntityMap>, - mut players: Query<(&PlayerId, &mut Imperative)>, + mut players: Query<(&PlayerId, &mut Imperative, &EffectiveStats)>, mut positions: Query<&mut PlayerPosition>, - champions: Query<&Champion>, time: Res<Time>, ) { - for (id, mut imperative) in players.iter_mut() { + for (id, mut imperative, effective_stats) in players.iter_mut() { match *imperative { Imperative::AttackTarget(_, target_player) => { 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; + continue; }; let Some(target_entity) = entity_map.0.get(&target_player.0) else { *imperative = Imperative::Idle; - return; + continue; }; let Ok([mut position, target_position]) = positions.get_many_mut([*entity, *target_entity]) else { *imperative = Imperative::Idle; - return; + continue; }; let distance = target_position.0.distance(position.0); - if distance > Stats::from_champion(*champion).attack_range { + if distance > effective_stats.0.attack_range { let (new_position, _) = move_to_target( position.0, target_position.0, - MOVEMENT_SPEED * time.delta().as_secs_f32(), + effective_stats.0.movement_speed * time.delta().as_secs_f32(), ); position.0 = new_position; } @@ -242,40 +247,40 @@ fn imperative_attack_attack( entity_map: Res<EntityMap>, mut commands: Commands, mut cooldowns: Query<&mut Cooldown>, - mut players: Query<(&PlayerId, &mut Imperative)>, + mut players: Query<(&PlayerId, &mut Imperative, &EffectiveStats)>, mut positions: Query<&mut PlayerPosition>, champions: Query<&Champion>, ) { - for (id, mut imperative) in players.iter_mut() { + for (id, mut imperative, effective_stats) in players.iter_mut() { let Some(entity) = entity_map.0.get(&id.0) else { *imperative = Imperative::Idle; - return; + continue; }; let Ok(champion) = champions.get(*entity) else { *imperative = Imperative::Idle; - return; + continue; }; match *imperative { Imperative::AttackTarget(ability_slot, target_player) => { let Ability::Targeted(ability) = champion.to_ability(ability_slot) else { *imperative = Imperative::Idle; - return; + continue; }; let Some(target_entity) = entity_map.0.get(&target_player.0) else { *imperative = Imperative::Idle; - return; + continue; }; let Ok([position, target_position]) = positions.get_many_mut([*entity, *target_entity]) else { *imperative = Imperative::Idle; - return; + continue; }; let distance = target_position.0.distance(position.0); - if distance <= Stats::from_champion(*champion).attack_range { + if distance <= effective_stats.0.attack_range { let Ok(mut cooldown) = cooldowns.get_mut(*entity) else { *imperative = Imperative::Idle; - return; + continue; }; let base_cooldown = BaseCooldown::from_champion(*champion); if cooldown.0[ability_slot].is_zero() { @@ -285,21 +290,24 @@ fn imperative_attack_attack( position.0, target_player, ))); + if ability_slot != AbilitySlot::A { + *imperative = Imperative::Idle; + } } } } Imperative::AttackDirection(ability_slot, direction) => { let Ability::Directional(ability) = champion.to_ability(ability_slot) else { *imperative = Imperative::Idle; - return; + continue; }; let Ok(position) = positions.get_mut(*entity) else { *imperative = Imperative::Idle; - return; + continue; }; let Ok(mut cooldown) = cooldowns.get_mut(*entity) else { *imperative = Imperative::Idle; - return; + continue; }; let base_cooldown = BaseCooldown::from_champion(*champion); if cooldown.0[ability_slot].is_zero() { @@ -307,6 +315,7 @@ fn imperative_attack_attack( commands.spawn(ProjectileBundle::new( ability.to_projectile(*id, position.0, direction), )); + *imperative = Imperative::Idle; } } _ => {} @@ -314,6 +323,46 @@ fn imperative_attack_attack( } } +fn activation( + entity_map: Res<EntityMap>, + mut cooldowns: Query<&mut Cooldown>, + mut players: Query<(&PlayerId, &mut Activation, &mut Buffs)>, + champions: Query<&Champion>, +) { + for (id, mut activation, mut buffs) in players.iter_mut() { + let Some(entity) = entity_map.0.get(&id.0) else { + *activation = Activation::None; + continue; + }; + let Ok(champion) = champions.get(*entity) else { + *activation = Activation::None; + continue; + }; + let Activation::Activate(ability_slot) = *activation else { + *activation = Activation::None; + continue; + }; + let Ability::Activated(ability) = champion.to_ability(ability_slot) else { + *activation = Activation::None; + continue; + }; + let Ok(mut cooldown) = cooldowns.get_mut(*entity) else { + *activation = Activation::None; + continue; + }; + match ability { + ActivatedAbility::Speed => { + let base_cooldown = BaseCooldown::from_champion(*champion); + if cooldown.0[ability_slot].is_zero() { + cooldown.0[ability_slot] = base_cooldown.0[ability_slot]; + buffs.speed = Some(Timer::from_seconds(2., TimerMode::Once)); + *activation = Activation::None; + } + } + } + } +} + const PROJECTILE_SPEED: f32 = 150.; fn projectile_move( @@ -460,3 +509,43 @@ fn health_regen(health_regen_timer: Res<HealthRegenTimer>, mut healths: Query<&m } } } + +fn effective_stats(mut effective_statses: Query<(&Champion, &mut EffectiveStats, &Buffs)>) { + for (champion, mut effective_stats, buffs) in effective_statses.iter_mut() { + let mut stats = BaseStats::from_champion(*champion).0; + if buffs.slow.is_some() { + stats.movement_speed *= 0.85; + } + if buffs.speed.is_some() { + stats.movement_speed *= 1.25; + } + effective_stats.0 = stats; + } +} + +fn buffs_tick(mut buffses: Query<&mut Buffs>, time: Res<Time>) { + let dt = time.delta(); + for mut buffs in buffses.iter_mut() { + if let Some(ref mut timer) = &mut buffs.slow { + timer.tick(dt); + } + if let Some(ref mut timer) = &mut buffs.speed { + timer.tick(dt); + } + } +} + +fn buffs_despawn(mut buffses: Query<&mut Buffs>) { + for mut buffs in buffses.iter_mut() { + if let Some(timer) = &buffs.slow { + if timer.finished() { + buffs.slow = None; + } + } + if let Some(timer) = &buffs.speed { + if timer.finished() { + buffs.speed = None; + } + } + } +} |