scroll.server/crates/logic/src/battle/logic_game_object.rs
WiseDev 774e7c60cf build and send the battle sector state
npc missions used to get a ServerErrorMessage back. now StartMission builds a
LogicGameMode snapshot off the arena tilemap and answers 21903.

towers come from assets/locations/*.csv the way initDefaultSector does it: tile
coordinates times 500, leader index decided by which half of the map the tower
sits in. the two king towers must be there, the client dereferences them without
a null check. they live in buildings.csv, not characters.csv.

LogicCharacter puts the base object fields fourth, not first. the buff component
writes a fixed array sized by the character_buffs row count even with no buffs.

training_arena parses to 2 kings, 4 princess towers, 36x64 subtiles. snapshot is
602 bytes over 6 objects. the real client has not seen it yet.
2026-08-23 10:24:20 +03:00

58 lines
1.8 KiB
Rust

use titan::Payload;
use crate::battle::logic_game_object_ref::LogicGameObjectRef;
use crate::data::LogicDataRef;
pub const COMPONENT_PASSES: usize = 4;
pub const OBJECT_TYPE_COUNT: usize = 6;
pub const CHARACTER_OBJECT_TYPE: i32 = 5;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Payload)]
pub struct LogicVector2 {
#[codec(vint)]
pub x: i32,
#[codec(vint)]
pub y: i32,
}
impl LogicVector2 {
pub fn new(x: i32, y: i32) -> Self {
Self { x, y }
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Payload)]
pub struct LogicGameObject {
#[codec(vint)]
pub field_28: i32,
#[codec(vint)]
pub field_56: i32,
pub position: LogicVector2,
#[codec(vint)]
pub owner_index: i32,
}
impl LogicGameObject {
pub fn encode_base(&self, writer: &mut titan::ByteStreamWriter) -> titan::Result<()> {
<Self as Payload>::encode(self, writer)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LogicObjectBody {
Character(Box<crate::battle::logic_character::LogicCharacter>),
Summoner(Box<crate::battle::logic_character::LogicSummoner>),
}
impl LogicObjectBody {
pub fn encode(&self, writer: &mut titan::ByteStreamWriter) -> titan::Result<()> {
match self {
LogicObjectBody::Character(character) => character.encode(writer),
LogicObjectBody::Summoner(summoner) => summoner.encode(writer),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LogicGameObjectEntry {
pub data: LogicDataRef,
pub global_id: LogicGameObjectRef,
pub body: LogicObjectBody,
pub components: [Option<crate::battle::logic_component::LogicComponent>; COMPONENT_PASSES],
}
impl LogicGameObjectEntry {
pub fn object_type(&self) -> i32 {
self.global_id.0.map(|id| id.class_id - 1).unwrap_or(-1)
}
}