send units at the nearest tower when nothing is in sight
units stood still all battle. a unit only moved if it had a combat target, and targets are only found inside SightRange - six thousand units for a knight - while the enemy tower sits twenty thousand away. so nothing ever walked, nothing was ever hit, no tower fell, crowns stayed at nothing and the battle could only end on the clock. a unit with no target now walks at the nearest enemy building, which is the default target the client falls back to. once the tower comes inside sight the ordinary search picks it up and the attack timer takes over. the battle turn log carries the standing tower count per side so damage is visible before it becomes a crown.
This commit is contained in:
parent
9084163f71
commit
d1cc829623
3 changed files with 34 additions and 3 deletions
|
|
@ -209,6 +209,12 @@ impl BattleSession {
|
||||||
pub fn stars(&self) -> (i32, i32) {
|
pub fn stars(&self) -> (i32, i32) {
|
||||||
(self.mode.battle.stars(0), self.mode.battle.stars(1))
|
(self.mode.battle.stars(0), self.mode.battle.stars(1))
|
||||||
}
|
}
|
||||||
|
pub fn towers_standing(&self) -> (usize, usize) {
|
||||||
|
(
|
||||||
|
self.mode.battle.leader_towers[0].len(),
|
||||||
|
self.mode.battle.leader_towers[1].len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
pub fn owner_of(&self, account: LogicLong) -> Option<i32> {
|
pub fn owner_of(&self, account: LogicLong) -> Option<i32> {
|
||||||
self.mode
|
self.mode
|
||||||
.battle
|
.battle
|
||||||
|
|
@ -312,6 +318,7 @@ impl BattleRegistry {
|
||||||
finished: session.is_finished(),
|
finished: session.is_finished(),
|
||||||
stars: session.stars(),
|
stars: session.stars(),
|
||||||
objects: session.object_count(),
|
objects: session.object_count(),
|
||||||
|
towers: session.towers_standing(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub async fn play<F>(
|
pub async fn play<F>(
|
||||||
|
|
@ -348,4 +355,5 @@ pub struct BattleProgress {
|
||||||
pub finished: bool,
|
pub finished: bool,
|
||||||
pub stars: (i32, i32),
|
pub stars: (i32, i32),
|
||||||
pub objects: usize,
|
pub objects: usize,
|
||||||
|
pub towers: (usize, usize),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,7 @@ impl GameApi for GameService {
|
||||||
finished = progress.map(|state| state.finished),
|
finished = progress.map(|state| state.finished),
|
||||||
stars = ?progress.map(|state| state.stars),
|
stars = ?progress.map(|state| state.stars),
|
||||||
objects = progress.map(|state| state.objects),
|
objects = progress.map(|state| state.objects),
|
||||||
|
towers = ?progress.map(|state| state.towers),
|
||||||
spawned,
|
spawned,
|
||||||
commands = ?turn
|
commands = ?turn
|
||||||
.commands
|
.commands
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,24 @@ impl LogicBattle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn default_target(&self, index: usize) -> Option<usize> {
|
||||||
|
let owner = self.objects.objects[index].owner_index();
|
||||||
|
let from = self.objects.objects[index].position();
|
||||||
|
let mut best: Option<(i32, usize)> = None;
|
||||||
|
for (other, entry) in self.objects.objects.iter().enumerate() {
|
||||||
|
if other == index || entry.owner_index() == owner || !entry.is_alive() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if !entry.stats().is_building() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let distance = distance_squared(from, entry.position());
|
||||||
|
if best.map(|(closest, _)| distance < closest).unwrap_or(true) {
|
||||||
|
best = Some((distance, other));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best.map(|(_, other)| other)
|
||||||
|
}
|
||||||
fn move_objects(&mut self) {
|
fn move_objects(&mut self) {
|
||||||
let positions: Vec<(i32, i32)> = self
|
let positions: Vec<(i32, i32)> = self
|
||||||
.objects
|
.objects
|
||||||
|
|
@ -199,11 +217,15 @@ impl LogicBattle {
|
||||||
if stats.speed < 1 || !self.objects.objects[index].is_alive() {
|
if stats.speed < 1 || !self.objects.objects[index].is_alive() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let Some(target) = self.objects.objects[index]
|
let target = match self.objects.objects[index]
|
||||||
.combat_mut()
|
.combat_mut()
|
||||||
.and_then(|component| component.target_index)
|
.and_then(|component| component.target_index)
|
||||||
else {
|
{
|
||||||
continue;
|
Some(target) => target,
|
||||||
|
None => match self.default_target(index) {
|
||||||
|
Some(target) => target,
|
||||||
|
None => continue,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let Some(goal) = positions.get(target).copied() else {
|
let Some(goal) = positions.get(target).copied() else {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue