aboutsummaryrefslogtreecommitdiffstats
path: root/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.rs')
-rw-r--r--src/server.rs174
1 files changed, 135 insertions, 39 deletions
diff --git a/src/server.rs b/src/server.rs
index e3d5a72..b2f22b3 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -189,6 +189,10 @@ fn move_to_target(position: Vec2, target_position: Vec2, max_distance: f32) -> (
}
}
+fn move_along_direction(position: Vec2, direction: Vec2, distance: f32) -> Vec2 {
+ position + distance * direction
+}
+
fn imperative_attack_approach(
entity_map: Res<EntityMap>,
mut players: Query<(&PlayerId, &mut Imperative)>,
@@ -198,7 +202,7 @@ fn imperative_attack_approach(
) {
for (id, mut imperative) in players.iter_mut() {
match *imperative {
- Imperative::Attack(AttackKey::A, target_player) => {
+ Imperative::AttackTarget(_, target_player) => {
let Some(entity) = entity_map.0.get(&id.0) else {
*imperative = Imperative::Idle;
return;
@@ -242,7 +246,7 @@ fn imperative_attack_attack(
) {
for (id, mut imperative) in players.iter_mut() {
match *imperative {
- Imperative::Attack(AttackKey::A, target_player) => {
+ Imperative::AttackTarget(_, target_player) => {
let Some(entity) = entity_map.0.get(&id.0) else {
*imperative = Imperative::Idle;
return;
@@ -269,24 +273,54 @@ fn imperative_attack_attack(
};
if cooldown.a_cooldown.is_zero() {
cooldown.a_cooldown = Duration::from_secs_f32(1.5);
- let instant = *champion == Champion::Meele;
+ let projectile_type = if *champion == Champion::Meele {
+ ProjectileType::Instant(InstantProjectile { target_player })
+ } else {
+ ProjectileType::Targeted(TargetedProjectile {
+ target_player,
+ position: position.0,
+ })
+ };
commands.spawn(ProjectileBundle {
projectile: Projectile {
- target_player,
source_player: *id,
damage: 4.,
- instant,
+ type_: projectile_type,
},
- position: ProjectilePosition(if instant {
- target_position.0
- } else {
- position.0
- }),
replicate: Replicate::default(),
});
}
}
}
+ Imperative::AttackDirection(_, direction) => {
+ let Some(entity) = entity_map.0.get(&id.0) else {
+ *imperative = Imperative::Idle;
+ return;
+ };
+ let Ok(position) = positions.get_mut(*entity) else {
+ *imperative = Imperative::Idle;
+ return;
+ };
+ let Ok(mut cooldown) = cooldowns.get_mut(*entity) else {
+ *imperative = Imperative::Idle;
+ return;
+ };
+ if cooldown.a_cooldown.is_zero() {
+ cooldown.a_cooldown = Duration::from_secs_f32(1.5);
+ commands.spawn(ProjectileBundle {
+ projectile: Projectile {
+ source_player: *id,
+ damage: 4.,
+ type_: ProjectileType::Free(FreeProjectile {
+ position: position.0,
+ direction,
+ starting_position: position.0,
+ }),
+ },
+ replicate: Replicate::default(),
+ });
+ }
+ }
_ => {}
}
}
@@ -296,24 +330,40 @@ const PROJECTILE_SPEED: f32 = 150.;
fn projectile_move(
entity_map: Res<EntityMap>,
- mut projectile_positions: Query<&mut ProjectilePosition>,
player_positions: Query<&PlayerPosition>,
- projectiles: Query<(Entity, &mut Projectile)>,
+ mut projectiles: Query<&mut Projectile>,
time: Res<Time>,
) {
- for (entity, projectile) in projectiles.iter() {
- if let Some(target_entity) = entity_map.0.get(&projectile.target_player.0) {
- if let Ok(mut position) = projectile_positions.get_mut(entity) {
- if let Ok(target_position) = player_positions.get(*target_entity) {
- let (new_position, _) = move_to_target(
- position.0,
- target_position.0,
- PROJECTILE_SPEED * time.delta().as_secs_f32(),
- );
- position.0 = new_position;
+ for mut projectile in projectiles.iter_mut() {
+ let new_type = match projectile.type_.clone() {
+ ProjectileType::Free(mut free_projectile) => {
+ let new_position = move_along_direction(
+ free_projectile.position,
+ free_projectile.direction,
+ PROJECTILE_SPEED * time.delta().as_secs_f32(),
+ );
+ free_projectile.position = new_position;
+ ProjectileType::Free(free_projectile)
+ }
+ ProjectileType::Instant(instant_projectile) => {
+ ProjectileType::Instant(instant_projectile)
+ }
+ ProjectileType::Targeted(mut targeted_projectile) => {
+ if let Some(target_entity) = entity_map.0.get(&targeted_projectile.target_player.0)
+ {
+ if let Ok(target_position) = player_positions.get(*target_entity) {
+ let (new_position, _) = move_to_target(
+ targeted_projectile.position.clone(),
+ target_position.0,
+ PROJECTILE_SPEED * time.delta().as_secs_f32(),
+ );
+ targeted_projectile.position = new_position;
+ }
}
+ ProjectileType::Targeted(targeted_projectile)
}
- }
+ };
+ projectile.type_ = new_type;
}
}
@@ -322,25 +372,71 @@ fn projectile_despawn(
mut commands: Commands,
mut healths: Query<&mut Health>,
player_positions: Query<&PlayerPosition>,
- projectile_positions: Query<&ProjectilePosition>,
+ projectile_targets: Query<(&PlayerId, &PlayerPosition)>,
projectiles: Query<(Entity, &mut Projectile)>,
) {
for (entity, projectile) in projectiles.iter() {
- let Some(target_entity) = entity_map.0.get(&projectile.target_player.0) else {
- commands.entity(entity).despawn();
- return;
- };
- let Ok(position) = projectile_positions.get(entity) else {
- commands.entity(entity).despawn();
- return;
- };
- let Ok(target_position) = player_positions.get(*target_entity) else {
- commands.entity(entity).despawn();
- return;
- };
- if position.0.distance(target_position.0) <= f32::EPSILON {
- if let Ok(mut health) = healths.get_mut(*target_entity) {
- health.0 = (health.0 - projectile.damage).max(0.);
+ let (despawn, maybe_target_player): (bool, Option<PlayerId>) = (|| match &projectile.type_ {
+ ProjectileType::Free(free_projectile) => {
+ let mut maybe_target_player = None;
+ let mut maybe_target_distance = None;
+ for (player, position) in projectile_targets.iter() {
+ if *player == projectile.source_player {
+ continue;
+ }
+ let distance = free_projectile.position.distance(position.0);
+ if distance > PLAYER_RADIUS {
+ continue;
+ }
+ match maybe_target_distance {
+ Some(old_distance) => {
+ if distance < old_distance {
+ maybe_target_player = Some(player);
+ maybe_target_distance = Some(distance);
+ }
+ }
+ None => {
+ maybe_target_player = Some(player);
+ maybe_target_distance = Some(distance);
+ }
+ }
+ }
+ if let Some(target_player) = maybe_target_player {
+ (true, Some(*target_player))
+ } else {
+ (
+ free_projectile
+ .position
+ .distance(free_projectile.starting_position)
+ >= 10000.0,
+ None,
+ )
+ }
+ }
+ ProjectileType::Instant(instant_projectile) => {
+ (true, Some(instant_projectile.target_player))
+ }
+ ProjectileType::Targeted(targeted_projectile) => {
+ let Some(target_entity) = entity_map.0.get(&targeted_projectile.target_player.0)
+ else {
+ return (true, None);
+ };
+ let Ok(target_position) = player_positions.get(*target_entity) else {
+ return (true, None);
+ };
+ (
+ targeted_projectile.position.distance(target_position.0) <= f32::EPSILON,
+ Some(targeted_projectile.target_player),
+ )
+ }
+ })();
+ if 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.);
+ }
+ }
}
commands.entity(entity).despawn();
}