diff options
author | Alexander Foremny <aforemny@posteo.de> | 2024-03-22 15:53:45 +0100 |
---|---|---|
committer | Alexander Foremny <aforemny@posteo.de> | 2024-03-22 16:42:41 +0100 |
commit | 7f962b034f888135ce618e03bea40a08b57a68c7 (patch) | |
tree | c9038a12b2712690a2e96a526814dc2ba1c0e9e4 /src/server.rs | |
parent | 2d8740b1e29fc356fbe88cea21059ec83d8c0cf0 (diff) |
feat: nexuses
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 182 |
1 files changed, 147 insertions, 35 deletions
diff --git a/src/server.rs b/src/server.rs index fa761fa..b09e96b 100644 --- a/src/server.rs +++ b/src/server.rs @@ -7,11 +7,13 @@ use crate::shared::area_of_effect::*; use crate::shared::buffs::*; use crate::shared::champion::*; use crate::shared::cooldown::*; +use crate::shared::faction::*; use crate::shared::health::*; use crate::shared::health_event::*; use crate::shared::immovable::*; use crate::shared::imperative::*; use crate::shared::minion::*; +use crate::shared::nexus::*; use crate::shared::player::*; use crate::shared::projectile::*; use crate::shared::shape::*; @@ -94,42 +96,66 @@ impl Plugin for ServerPlugin { .add_systems(FixedUpdate, player_input) .add_systems( FixedUpdate, - (tower_ai, minion_ai).before(imperative_attack_approach), + (tower_ai, (minion_ai_attack, minion_ai_walk).chain()) + .before(imperative_attack_approach), ) - .add_systems(FixedUpdate, minion_despawn); + .add_systems(FixedUpdate, minion_despawn) + .add_systems(FixedUpdate, (nexus_tick, nexus_spawn_minions)); } } fn setup(mut commands: Commands, mut entity_map: ResMut<EntityMap>) { { - 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 client_id = 1; + let entity = commands.spawn(TowerBundle::new( + client_id, + Vec2::new(0., 100.), + Faction::Blue, + )); + entity_map.0.insert(client_id, entity.id()); } { - let entity_id = 2; + let client_id = 2; let entity = commands.spawn(TowerBundle::new( - entity_id, + client_id, Vec2::new(0., -100.), - Color::BLUE, + Faction::Red, )); - entity_map.0.insert(entity_id, entity.id()); + entity_map.0.insert(client_id, entity.id()); } - for entity_id in 3..=8 { + for client_id in 3..=8 { let entity = commands.spawn(MinionBundle::new( - entity_id, - Vec2::new((entity_id - 2) as f32 * 25., 0.), - Color::BLUE, + client_id, + Vec2::new((client_id - 2) as f32 * 25., 0.), + Faction::Blue, )); - entity_map.0.insert(entity_id, entity.id()); + entity_map.0.insert(client_id, entity.id()); } - for entity_id in 9..=14 { + for client_id in 9..=14 { let entity = commands.spawn(MinionBundle::new( - entity_id, - Vec2::new((entity_id - 8) as f32 * -25., 0.), - Color::RED, + client_id, + Vec2::new((client_id - 8) as f32 * -25., 0.), + Faction::Red, )); - entity_map.0.insert(entity_id, entity.id()); + entity_map.0.insert(client_id, entity.id()); + } + { + let client_id = 15; + let entity = commands.spawn(NexusBundle::new( + client_id, + Vec2::new(100., 100.0), + Faction::Blue, + )); + entity_map.0.insert(client_id, entity.id()); + } + { + let client_id = 16; + let entity = commands.spawn(NexusBundle::new( + client_id, + Vec2::new(-100., -100.0), + Faction::Red, + )); + entity_map.0.insert(client_id, entity.id()); } } @@ -698,14 +724,26 @@ fn tower_ai( &mut Imperative, &PlayerPosition, &EffectiveStats, + &Faction, )>, - targets: Query<(&PlayerId, &PlayerPosition, &Shape), Without<Tower>>, + targets: Query<(&PlayerId, &PlayerPosition, &Shape, &Faction), Without<Tower>>, ) { - for (mut tower_tower, mut tower_imperative, tower_player_position, tower_effective_stats) in - towers.iter_mut() + for ( + mut tower_tower, + mut tower_imperative, + tower_player_position, + tower_effective_stats, + tower_faction, + ) in towers.iter_mut() { let mut closest_target = None; - for (target_player_id, target_player_position, target_shape) in targets.iter() { + for (target_player_id, target_player_position, target_shape, target_faction) in + targets.iter() + { + if target_faction == tower_faction { + continue; + } + let target_in_range = tower_player_position.0.distance(target_player_position.0) < tower_effective_stats.0.attack_range + target_shape.radius; @@ -737,19 +775,46 @@ fn tower_ai( } } -fn minion_ai( - mut minions: Query< - (&PlayerId, &mut Imperative, &PlayerPosition, &EffectiveStats), - With<Minion>, - >, - targets: Query<(&PlayerId, &PlayerPosition, &Shape)>, +fn minion_ai_walk( + mut minions: Query<(&mut Imperative, &PlayerPosition, &Faction), With<Minion>>, + nexuses: Query<(&PlayerPosition, &Faction), With<Nexus>>, ) { - for (minion_player_id, mut minion_imperative, minion_player_position, minion_effective_stats) in + for (mut minion_imperative, minion_player_position, minion_faction) in minions.iter_mut() { + if *minion_imperative != Imperative::Idle { + continue; + } + let mut closest_target = None; + for (nexus_player_position, nexus_faction) in nexuses.iter() { + if nexus_faction == minion_faction { + continue; + } + let target_distance = minion_player_position.0.distance(nexus_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((nexus_player_position.0, target_distance)); + } + } + let Some((target_player_position, _)) = closest_target else { + *minion_imperative = Imperative::Idle; + continue; + }; + *minion_imperative = Imperative::WalkTo(target_player_position); + } +} +fn minion_ai_attack( + mut minions: Query<(&mut Imperative, &PlayerPosition, &EffectiveStats, &Faction), With<Minion>>, + targets: Query<(&PlayerId, &PlayerPosition, &Shape, &Faction)>, +) { + for (mut minion_imperative, minion_player_position, minion_effective_stats, minion_faction) 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 { + for (target_player_id, target_player_position, target_shape, target_faction) in + targets.iter() + { + if target_faction == minion_faction { continue; } let target_in_range = minion_player_position.0.distance(target_player_position.0) @@ -773,10 +838,57 @@ fn minion_ai( } } -fn minion_despawn(minions: Query<(Entity, &Health), With<Minion>>, mut commands: Commands) { - for (minion_entity, minion_health) in minions.iter() { +fn minion_despawn( + minions: Query<(Entity, &PlayerId, &Health), With<Minion>>, + mut commands: Commands, + mut entity_map: ResMut<EntityMap>, +) { + for (minion_entity, minion_player_id, minion_health) in minions.iter() { if minion_health.health <= 0. { - commands.entity(minion_entity).despawn() + commands.entity(minion_entity).despawn(); + entity_map.0.remove(&minion_player_id.0); + } + } +} + +fn nexus_spawn_minions( + nexuses: Query<(&Nexus, &PlayerPosition, &Faction)>, + mut commands: Commands, + mut entity_map: ResMut<EntityMap>, +) { + for (nexus_nexus, nexus_player_position, nexus_faction) in nexuses.iter() { + if nexus_nexus.spawn_minions.just_finished() { + let client_ids = generate_client_ids(5, &entity_map); + for client_id in client_ids { + let entity = commands.spawn(MinionBundle::new( + client_id, + nexus_player_position.0, + *nexus_faction, + )); + entity_map.0.insert(client_id, entity.id()); + } + } + } +} + +fn generate_client_ids(n: u64, entity_map: &ResMut<EntityMap>) -> Vec<u64> { + let mut rng = rand::thread_rng(); + let mut k = 0; + let mut client_ids = vec![]; + while k < n { + let client_id = rng.gen(); + if entity_map.0.contains_key(&client_id) { + continue; } + client_ids.push(client_id); + k += 1; + } + client_ids +} + +fn nexus_tick(mut nexuses: Query<&mut Nexus>, time: Res<Time>) { + let dt = time.delta(); + for mut nexus in nexuses.iter_mut() { + nexus.spawn_minions.tick(dt); } } |