aboutsummaryrefslogtreecommitdiffstats
path: root/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.rs')
-rw-r--r--src/server.rs87
1 files changed, 80 insertions, 7 deletions
diff --git a/src/server.rs b/src/server.rs
index 4da2253..fa761fa 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -11,6 +11,7 @@ use crate::shared::health::*;
use crate::shared::health_event::*;
use crate::shared::immovable::*;
use crate::shared::imperative::*;
+use crate::shared::minion::*;
use crate::shared::player::*;
use crate::shared::projectile::*;
use crate::shared::shape::*;
@@ -91,17 +92,45 @@ impl Plugin for ServerPlugin {
.add_systems(FixedUpdate, cooldown_decrement)
.add_systems(FixedUpdate, (buffs_despawn, buffs_tick).chain())
.add_systems(FixedUpdate, player_input)
- .add_systems(FixedUpdate, tower_ai);
+ .add_systems(
+ FixedUpdate,
+ (tower_ai, minion_ai).before(imperative_attack_approach),
+ )
+ .add_systems(FixedUpdate, minion_despawn);
}
}
fn setup(mut commands: Commands, mut entity_map: ResMut<EntityMap>) {
- let entity = commands.spawn(PlayerBundle::new(1, Vec2::ZERO, Color::GRAY));
- entity_map.0.insert(1, entity.id());
- let entity = commands.spawn(TowerBundle::new(2, Vec2::new(0., 100.), Color::RED));
- entity_map.0.insert(2, entity.id());
- let entity = commands.spawn(TowerBundle::new(3, Vec2::new(0., -100.), Color::BLUE));
- entity_map.0.insert(3, entity.id());
+ {
+ let entity_id = 1;
+ let entity = commands.spawn(TowerBundle::new(entity_id, Vec2::new(0., 100.), Color::RED));
+ entity_map.0.insert(entity_id, entity.id());
+ }
+ {
+ let entity_id = 2;
+ let entity = commands.spawn(TowerBundle::new(
+ entity_id,
+ Vec2::new(0., -100.),
+ Color::BLUE,
+ ));
+ entity_map.0.insert(entity_id, entity.id());
+ }
+ for entity_id in 3..=8 {
+ let entity = commands.spawn(MinionBundle::new(
+ entity_id,
+ Vec2::new((entity_id - 2) as f32 * 25., 0.),
+ Color::BLUE,
+ ));
+ entity_map.0.insert(entity_id, entity.id());
+ }
+ for entity_id in 9..=14 {
+ let entity = commands.spawn(MinionBundle::new(
+ entity_id,
+ Vec2::new((entity_id - 8) as f32 * -25., 0.),
+ Color::RED,
+ ));
+ entity_map.0.insert(entity_id, entity.id());
+ }
}
fn connects(
@@ -707,3 +736,47 @@ fn tower_ai(
tower_tower.last_target_player_id = Some(*target_player_id);
}
}
+
+fn minion_ai(
+ mut minions: Query<
+ (&PlayerId, &mut Imperative, &PlayerPosition, &EffectiveStats),
+ With<Minion>,
+ >,
+ targets: Query<(&PlayerId, &PlayerPosition, &Shape)>,
+) {
+ for (minion_player_id, mut minion_imperative, minion_player_position, minion_effective_stats) in
+ minions.iter_mut()
+ {
+ let mut closest_target = None;
+ for (target_player_id, target_player_position, target_shape) in targets.iter() {
+ if target_player_id == minion_player_id {
+ continue;
+ }
+ let target_in_range = minion_player_position.0.distance(target_player_position.0)
+ < minion_effective_stats.0.attack_range + target_shape.radius;
+ if !target_in_range {
+ continue;
+ }
+ let target_distance = minion_player_position.0.distance(target_player_position.0);
+ let target_is_closer = closest_target
+ .map(|(_, closest_target_distance)| target_distance < closest_target_distance)
+ .unwrap_or(true);
+ if target_is_closer {
+ closest_target = Some((target_player_id, target_distance));
+ }
+ }
+ let Some((target_player_id, _)) = closest_target else {
+ *minion_imperative = Imperative::Idle;
+ continue;
+ };
+ *minion_imperative = Imperative::AttackTarget(AbilitySlot::A, *target_player_id);
+ }
+}
+
+fn minion_despawn(minions: Query<(Entity, &Health), With<Minion>>, mut commands: Commands) {
+ for (minion_entity, minion_health) in minions.iter() {
+ if minion_health.health <= 0. {
+ commands.entity(minion_entity).despawn()
+ }
+ }
+}