use titan::{ByteStreamWriter, Payload, Result}; use crate::battle::logic_game_object::LogicVector2; use crate::battle::logic_game_object_ref::LogicGameObjectRef; pub const COMPONENT_COMBAT: usize = 0; pub const COMPONENT_MOVEMENT: usize = 1; pub const COMPONENT_HITPOINT: usize = 2; pub const COMPONENT_BUFF: usize = 3; #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct LogicCombatComponent { pub flag_72: bool, pub flag_73: bool, pub field_48: i32, pub field_52: i32, pub field_60: i32, pub field_64: i32, pub field_68: i32, pub target: LogicGameObjectRef, pub attackers: Vec<(LogicGameObjectRef, i32)>, pub observers: Vec, pub target_index: Option, pub hit_timer: i32, } impl LogicCombatComponent { pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { writer.write_boolean(self.flag_72); writer.write_boolean(self.flag_73); writer.write_vint(self.hit_timer); writer.write_vint(self.field_52); writer.write_vint(self.field_60); writer.write_vint(self.field_64); writer.write_vint(self.field_68); writer.write_vint(self.attackers.len() as i32); writer.write_vint(self.observers.len() as i32); self.target.encode(writer)?; for (reference, value) in &self.attackers { reference.encode(writer)?; writer.write_vint(*value); } for reference in &self.observers { reference.encode(writer)?; } Ok(()) } } pub const CHARGE_TIME_DISABLED: i32 = -1; #[derive(Debug, Clone, PartialEq, Eq)] pub struct LogicMovementComponent { pub is_pushed_back: bool, pub is_stopped: bool, pub is_panicking: bool, pub path_node_reached: bool, pub path: Vec, pub collision_push_count: i32, pub collision_push_sum_x: i32, pub collision_push_sum_y: i32, pub panic_timer: i32, pub panic_target_x: i32, pub panic_target_y: i32, pub panic_origin_x: i32, pub panic_origin_y: i32, pub charge_time: i32, pub pushback_target: LogicVector2, pub avoidance_side_step: i32, pub path_target_normal: LogicVector2, pub pushback_speed: i32, pub move_timer: i32, pub jump_distance: i32, pub goal: Option<(i32, i32)>, pub route: Vec<(i32, i32)>, } impl Default for LogicMovementComponent { fn default() -> Self { Self { is_pushed_back: false, is_stopped: false, is_panicking: false, path_node_reached: false, path: Vec::new(), collision_push_count: 0, collision_push_sum_x: 0, collision_push_sum_y: 0, panic_timer: 0, panic_target_x: 0, panic_target_y: 0, panic_origin_x: 0, panic_origin_y: 0, charge_time: CHARGE_TIME_DISABLED, pushback_target: LogicVector2::default(), avoidance_side_step: 0, path_target_normal: LogicVector2::default(), pushback_speed: 0, move_timer: 0, jump_distance: 0, goal: None, route: Vec::new(), } } } impl LogicMovementComponent { pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { writer.write_boolean(self.is_pushed_back); writer.write_boolean(self.is_stopped); writer.write_boolean(self.is_panicking); writer.write_boolean(self.path_node_reached); writer.write_vint(self.path.len() as i32); for node in &self.path { writer.write_vint(*node); } writer.write_vint(self.collision_push_count); writer.write_vint(self.collision_push_sum_x); writer.write_vint(self.collision_push_sum_y); writer.write_vint(self.panic_timer); writer.write_vint(self.panic_target_x); writer.write_vint(self.panic_target_y); writer.write_vint(self.panic_origin_x); writer.write_vint(self.panic_origin_y); writer.write_vint(self.charge_time); writer.write_vint(self.pushback_target.x); writer.write_vint(self.pushback_target.y); writer.write_vint(self.avoidance_side_step); writer.write_vint(self.path_target_normal.x); writer.write_vint(self.path_target_normal.y); writer.write_vint(self.pushback_speed); writer.write_vint(self.move_timer); writer.write_vint(self.jump_distance); Ok(()) } } #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct LogicHitpointComponent { pub hitpoints: i32, pub base_hitpoints: i32, pub lifetime_damage: i32, pub lifetime_accumulator: i32, pub death_hit_angle: i32, } impl LogicHitpointComponent { pub fn healthy(hitpoints: i32) -> Self { Self { hitpoints, base_hitpoints: hitpoints, ..Self::default() } } pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { writer.write_vint(self.hitpoints); writer.write_vint(self.base_hitpoints); writer.write_vint(self.lifetime_damage); if self.lifetime_damage != 0 { writer.write_vint(self.lifetime_accumulator); } if self.hitpoints <= 0 { writer.write_vint(self.death_hit_angle); } Ok(()) } } #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct LogicCharacterBuffComponent { pub field_32: i32, pub field_36: i32, pub field_40: i32, pub buff_type_count: usize, pub field_52: i32, pub field_56: i32, pub field_60: i32, pub field_64: i32, pub field_68: i32, pub field_72: i32, } impl LogicCharacterBuffComponent { pub fn empty(buff_type_count: usize) -> Self { Self { buff_type_count, ..Self::default() } } pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { writer.write_vint(0); writer.write_vint(0); writer.write_vint(self.field_32); writer.write_vint(self.field_36); writer.write_vint(self.field_40); for _ in 0..self.buff_type_count { writer.write_vint(0); } for _ in 0..self.buff_type_count { writer.write_boolean(false); } writer.write_vint(self.field_52); writer.write_vint(self.field_56); writer.write_vint(self.field_60); writer.write_vint(self.field_64); writer.write_vint(self.field_68); writer.write_vint(self.field_72); Ok(()) } } #[derive(Debug, Clone, PartialEq, Eq)] pub enum LogicComponent { Combat(LogicCombatComponent), Movement(LogicMovementComponent), Hitpoint(LogicHitpointComponent), Buff(LogicCharacterBuffComponent), } impl LogicComponent { pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> { match self { LogicComponent::Combat(component) => component.encode(writer), LogicComponent::Movement(component) => component.encode(writer), LogicComponent::Hitpoint(component) => component.encode(writer), LogicComponent::Buff(component) => component.encode(writer), } } }