fix the LogicGameObject field mapping
the base object writes owner index, component mask, position and z, in that order. we had the first field unnamed and were writing the owner into the z slot, so every object belonged to player 0, and the mask slot carried a zero. the mask matters: getHitpointComponent tests bit 2 of it before touching components[2], so a zero mask made every tower report no hitpoints, LogicCharacter::isAlive fell through to the z field, shouldDestruct went true and the towers were destroyed on the first tick - which then hit "cant find summoner tower" in LogicBattle::removeGameObjectReferences. entries are built through LogicGameObjectEntry::new now so the mask is derived from the component array and cannot drift from it. also rename the first character flag after what sets it: kamikaze death and morph both raise it right before the object is removed.
This commit is contained in:
parent
bc04651a73
commit
6c5295bc07
3 changed files with 36 additions and 10 deletions
|
|
@ -110,11 +110,11 @@ impl BattleBuilder {
|
|||
} else {
|
||||
LogicObjectBody::Character(Box::new(character))
|
||||
};
|
||||
LogicGameObjectEntry {
|
||||
LogicGameObjectEntry::new(
|
||||
data,
|
||||
global_id: LogicGameObjectRef::of(CHARACTER_OBJECT_TYPE + 1, instance),
|
||||
LogicGameObjectRef::of(CHARACTER_OBJECT_TYPE + 1, instance),
|
||||
body,
|
||||
components: [
|
||||
[
|
||||
Some(LogicComponent::Combat(LogicCombatComponent::default())),
|
||||
None,
|
||||
Some(LogicComponent::Hitpoint(LogicHitpointComponent::healthy(
|
||||
|
|
@ -124,7 +124,7 @@ impl BattleBuilder {
|
|||
self.buff_type_count,
|
||||
))),
|
||||
],
|
||||
}
|
||||
)
|
||||
}
|
||||
pub fn build(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ pub const DEFAULT_SIZE: i32 = 100;
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct LogicCharacter {
|
||||
pub level_index: i32,
|
||||
pub flag_160: bool,
|
||||
pub is_destroyed: bool,
|
||||
pub is_leader: bool,
|
||||
pub base: LogicGameObject,
|
||||
pub direction: LogicVector2,
|
||||
|
|
@ -29,7 +29,7 @@ impl Default for LogicCharacter {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
level_index: 0,
|
||||
flag_160: false,
|
||||
is_destroyed: false,
|
||||
is_leader: false,
|
||||
base: LogicGameObject::default(),
|
||||
direction: LogicVector2::new(0, DIRECTION_BOTTOM),
|
||||
|
|
@ -53,7 +53,7 @@ impl Default for LogicCharacter {
|
|||
impl LogicCharacter {
|
||||
pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> {
|
||||
writer.write_vint(self.level_index);
|
||||
writer.write_boolean(self.flag_160);
|
||||
writer.write_boolean(self.is_destroyed);
|
||||
writer.write_boolean(self.is_leader);
|
||||
self.base.encode_base(writer)?;
|
||||
writer.write_vint(self.direction.x);
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ impl LogicVector2 {
|
|||
#[derive(Debug, Default, Clone, PartialEq, Eq, Payload)]
|
||||
pub struct LogicGameObject {
|
||||
#[codec(vint)]
|
||||
pub field_28: i32,
|
||||
pub owner_index: i32,
|
||||
#[codec(vint)]
|
||||
pub field_56: i32,
|
||||
pub component_mask: i32,
|
||||
pub position: LogicVector2,
|
||||
#[codec(vint)]
|
||||
pub owner_index: i32,
|
||||
pub z: i32,
|
||||
}
|
||||
impl LogicGameObject {
|
||||
pub fn encode_base(&self, writer: &mut titan::ByteStreamWriter) -> titan::Result<()> {
|
||||
|
|
@ -37,6 +37,12 @@ pub enum LogicObjectBody {
|
|||
Summoner(Box<crate::battle::logic_character::LogicSummoner>),
|
||||
}
|
||||
impl LogicObjectBody {
|
||||
pub fn base_mut(&mut self) -> &mut LogicGameObject {
|
||||
match self {
|
||||
LogicObjectBody::Character(character) => &mut character.base,
|
||||
LogicObjectBody::Summoner(summoner) => &mut summoner.character.base,
|
||||
}
|
||||
}
|
||||
pub fn encode(&self, writer: &mut titan::ByteStreamWriter) -> titan::Result<()> {
|
||||
match self {
|
||||
LogicObjectBody::Character(character) => character.encode(writer),
|
||||
|
|
@ -52,6 +58,26 @@ pub struct LogicGameObjectEntry {
|
|||
pub components: [Option<crate::battle::logic_component::LogicComponent>; COMPONENT_PASSES],
|
||||
}
|
||||
impl LogicGameObjectEntry {
|
||||
pub fn new(
|
||||
data: LogicDataRef,
|
||||
global_id: LogicGameObjectRef,
|
||||
mut body: LogicObjectBody,
|
||||
components: [Option<crate::battle::logic_component::LogicComponent>; COMPONENT_PASSES],
|
||||
) -> Self {
|
||||
let mut component_mask = 0;
|
||||
for (index, component) in components.iter().enumerate() {
|
||||
if component.is_some() {
|
||||
component_mask |= 1 << index;
|
||||
}
|
||||
}
|
||||
body.base_mut().component_mask = component_mask;
|
||||
Self {
|
||||
data,
|
||||
global_id,
|
||||
body,
|
||||
components,
|
||||
}
|
||||
}
|
||||
pub fn object_type(&self) -> i32 {
|
||||
self.global_id.0.map(|id| id.class_id - 1).unwrap_or(-1)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue