match the client's collision cap, move cap, and overtime mana

three more confirmed divergences, all in the sim math.

collision: the client normalises the averaged shove to a fixed 150
(updateMovementTowards), not to a fraction of the unit's speed. we had
capped it at speed/2 - a value i introduced to stop crowds shoving
troops off the map; 150 does the same job and is what the client hashes.

movement: the client steps min(speed, 250) toward the waypoint each
tick. we used raw speed with no per-tick cap, so any unit faster than
250 or buffed drifted ahead of the client. the 250 cap is in now; the
buff multiplier is a no-op until a buff system exists.

mana: past the match length the client flips to overtime - getSecondsLeft
adds the overtime length and getRegenRate switches to MANA_REGEN_MS
_OVERTIME. we never set is_on_overtime and had no overtime branch, so
mana regen diverged for the whole of overtime. it now flips the flag and
selects the overtime rate.

harness still green, crowd still cannot shove a troop past the towers.
This commit is contained in:
WiseDev 2026-08-24 09:42:26 +03:00
parent 7f78fd5104
commit a9a2e048ee

View file

@ -13,6 +13,9 @@ pub const MANA_RATE_SCALE: i32 = 100;
pub const GLOBAL_MAX_MANA: &str = "MAX_MANA"; pub const GLOBAL_MAX_MANA: &str = "MAX_MANA";
pub const GLOBAL_MANA_REGEN: &str = "MANA_REGEN_MS"; pub const GLOBAL_MANA_REGEN: &str = "MANA_REGEN_MS";
pub const GLOBAL_MANA_REGEN_END: &str = "MANA_REGEN_MS_END"; pub const GLOBAL_MANA_REGEN_END: &str = "MANA_REGEN_MS_END";
pub const GLOBAL_MANA_REGEN_OVERTIME: &str = "MANA_REGEN_MS_OVERTIME";
pub const MAX_MOVE_STEP: i64 = 250;
pub const COLLISION_PUSH_LIMIT: i64 = 150;
pub const GLOBAL_MANA_SPEED_UP_SECONDS: &str = "MANA_SPEED_UP_WHEN_REMAINING_SECONDS"; pub const GLOBAL_MANA_SPEED_UP_SECONDS: &str = "MANA_SPEED_UP_WHEN_REMAINING_SECONDS";
pub const GLOBAL_KING_ACTIVATE_TIME_MS: &str = "KING_ACTIVATE_TIME_MS"; pub const GLOBAL_KING_ACTIVATE_TIME_MS: &str = "KING_ACTIVATE_TIME_MS";
pub const KING_ACTIVATION_STEP: i32 = 50; pub const KING_ACTIVATION_STEP: i32 = 50;
@ -181,12 +184,23 @@ struct CollisionBody {
impl LogicBattle { impl LogicBattle {
fn regenerate_mana(&mut self, tick: i32) { fn regenerate_mana(&mut self, tick: i32) {
let max_mana = crate::LogicGlobals::number(GLOBAL_MAX_MANA).max(1); let max_mana = crate::LogicGlobals::number(GLOBAL_MAX_MANA).max(1);
let seconds_left = (self.match_length_seconds() - tick / BATTLE_TICKS_PER_SECOND).max(0); let elapsed = tick / BATTLE_TICKS_PER_SECOND;
if elapsed >= self.match_length_seconds() {
self.is_on_overtime = true;
}
let speed_up = crate::LogicGlobals::number(GLOBAL_MANA_SPEED_UP_SECONDS); let speed_up = crate::LogicGlobals::number(GLOBAL_MANA_SPEED_UP_SECONDS);
let regen = if seconds_left <= speed_up { let regen = if self.is_on_overtime {
let seconds_left =
(self.match_length_seconds() + self.overtime_length_seconds() - elapsed).max(0);
let _ = seconds_left;
crate::LogicGlobals::number(GLOBAL_MANA_REGEN_OVERTIME)
} else {
let seconds_left = (self.match_length_seconds() - elapsed).max(0);
if seconds_left <= speed_up {
crate::LogicGlobals::number(GLOBAL_MANA_REGEN_END) crate::LogicGlobals::number(GLOBAL_MANA_REGEN_END)
} else { } else {
crate::LogicGlobals::number(GLOBAL_MANA_REGEN) crate::LogicGlobals::number(GLOBAL_MANA_REGEN)
}
}; };
let step = regen.saturating_mul(MANA_RATE_SCALE) / max_mana; let step = regen.saturating_mul(MANA_RATE_SCALE) / max_mana;
if step < 1 { if step < 1 {
@ -440,6 +454,7 @@ impl LogicBattle {
continue; continue;
} }
let step = (stats.speed as i64) let step = (stats.speed as i64)
.min(MAX_MOVE_STEP)
.min(straight - stand_off as i64) .min(straight - stand_off as i64)
.min(leg); .min(leg);
let base = self.objects.objects[index].body.base_mut(); let base = self.objects.objects[index].body.base_mut();
@ -516,7 +531,7 @@ impl LogicBattle {
continue; continue;
} }
let mut shove = (push.0 / push.2 as i64, push.1 / push.2 as i64); let mut shove = (push.0 / push.2 as i64, push.1 / push.2 as i64);
let allowance = (stats.speed / 2).max(1) as i64; let allowance = COLLISION_PUSH_LIMIT;
let travelled = let travelled =
crate::logic_sqrt(distance_squared((0, 0), (shove.0 as i32, shove.1 as i32))) crate::logic_sqrt(distance_squared((0, 0), (shove.0 as i32, shove.1 as i32)))
as i64; as i64;