From b8c12cd00bc14d6f10842510118225a82e18c280 Mon Sep 17 00:00:00 2001 From: WiseDev <83840010+wisedevik@users.noreply.github.com> Date: Sun, 23 Aug 2026 16:40:47 +0300 Subject: [PATCH] count a spawned character up to its deploy time first, a correction: the towers do have models. the king tower shows its cannon and the princess towers carry health bars, and health bars are built inside Character::Character. so objects from the opening state get their models after all, and the listener theory that sent me around the houses was wrong. only troops are missing. the difference is one field. LogicCharacter::getDeployT is clamp(DeployTime - this[47], 0, DeployTime) and field 47 is our deploy_timer, which we set to zero and never moved. so every troop reads as still coming down, for the whole battle: it keeps the spawn effect and the sound the user could hear, and never gets a body. towers are unaffected - their deploy time is zero. the counter now climbs a tick at a time, the way the client's own simulation would, and a moving character starts in state 1 as LogicCharacter::setDefaultState leaves it. widening the push interval to ten seconds changed nothing, so the tear-down theory is out too. --- crates/game-service/src/battle.rs | 5 +++++ crates/logic/src/battle/logic_simulation.rs | 18 ++++++++++++++++++ crates/logic/src/battle/mod.rs | 4 +++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/game-service/src/battle.rs b/crates/game-service/src/battle.rs index 614b5d4..11d272b 100644 --- a/crates/game-service/src/battle.rs +++ b/crates/game-service/src/battle.rs @@ -133,6 +133,11 @@ impl BattleBuilder { DIRECTION_BOTTOM }, ), + state: if moves { + logic::battle::CHARACTER_STATE_MOVING + } else { + 0 + }, ..LogicCharacter::default() }; let components = self.components_for(hitpoints, moves); diff --git a/crates/logic/src/battle/logic_simulation.rs b/crates/logic/src/battle/logic_simulation.rs index 5ad0377..d06132c 100644 --- a/crates/logic/src/battle/logic_simulation.rs +++ b/crates/logic/src/battle/logic_simulation.rs @@ -5,6 +5,8 @@ use crate::battle::logic_battle::BATTLE_TICKS_PER_SECOND; use crate::battle::logic_tilemap::SUBTILE_UNITS; use crate::data::LogicDataRef; pub const TICK_MILLISECONDS: i32 = 50; +pub const CHARACTER_DEPLOY_TIME_COLUMN: &str = "DeployTime"; +pub const CHARACTER_STATE_MOVING: i32 = 1; pub const MANA_ACCUMULATOR_STEP: i32 = 5000; pub const MANA_RATE_SCALE: i32 = 100; pub const GLOBAL_MAX_MANA: &str = "MAX_MANA"; @@ -189,6 +191,7 @@ impl LogicBattle { } } pub fn tick(&mut self, tick: i32) { + self.advance_deploy(); self.regenerate_mana(tick); self.retarget(); self.resolve_collisions(); @@ -196,6 +199,21 @@ impl LogicBattle { self.resolve_attacks(); self.remove_dead(); } + fn advance_deploy(&mut self) { + for entry in self.objects.objects.iter_mut() { + let deploy_time = entry + .data + .data() + .map(|row| row.int(CHARACTER_DEPLOY_TIME_COLUMN)) + .unwrap_or(0); + let LogicObjectBody::Character(character) = &mut entry.body else { + continue; + }; + if character.deploy_timer < deploy_time { + character.deploy_timer += 1; + } + } + } fn retarget(&mut self) { let snapshot: Vec<(i32, (i32, i32), LogicCharacterStats, bool)> = self .objects diff --git a/crates/logic/src/battle/mod.rs b/crates/logic/src/battle/mod.rs index 265d922..6c49329 100644 --- a/crates/logic/src/battle/mod.rs +++ b/crates/logic/src/battle/mod.rs @@ -33,7 +33,9 @@ pub use logic_game_object::{ pub use logic_game_object_manager::LogicGameObjectManager; pub use logic_game_object_ref::LogicGameObjectRef; pub use logic_pathfinder::find_path; -pub use logic_simulation::{LogicCharacterStats, TICK_MILLISECONDS}; +pub use logic_simulation::{ + LogicCharacterStats, CHARACTER_DEPLOY_TIME_COLUMN, CHARACTER_STATE_MOVING, TICK_MILLISECONDS, +}; pub use logic_tilemap::{LogicTilemap, OBJECT_KING_TOWER, OBJECT_PRINCESS_TOWER, SUBTILE_UNITS}; pub use logic_time::LogicTime; pub use logic_tutorial_manager::LogicTutorialManager;