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 {
|
} else {
|
||||||
LogicObjectBody::Character(Box::new(character))
|
LogicObjectBody::Character(Box::new(character))
|
||||||
};
|
};
|
||||||
LogicGameObjectEntry {
|
LogicGameObjectEntry::new(
|
||||||
data,
|
data,
|
||||||
global_id: LogicGameObjectRef::of(CHARACTER_OBJECT_TYPE + 1, instance),
|
LogicGameObjectRef::of(CHARACTER_OBJECT_TYPE + 1, instance),
|
||||||
body,
|
body,
|
||||||
components: [
|
[
|
||||||
Some(LogicComponent::Combat(LogicCombatComponent::default())),
|
Some(LogicComponent::Combat(LogicCombatComponent::default())),
|
||||||
None,
|
None,
|
||||||
Some(LogicComponent::Hitpoint(LogicHitpointComponent::healthy(
|
Some(LogicComponent::Hitpoint(LogicHitpointComponent::healthy(
|
||||||
|
|
@ -124,7 +124,7 @@ impl BattleBuilder {
|
||||||
self.buff_type_count,
|
self.buff_type_count,
|
||||||
))),
|
))),
|
||||||
],
|
],
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
pub fn build(
|
pub fn build(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub const DEFAULT_SIZE: i32 = 100;
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct LogicCharacter {
|
pub struct LogicCharacter {
|
||||||
pub level_index: i32,
|
pub level_index: i32,
|
||||||
pub flag_160: bool,
|
pub is_destroyed: bool,
|
||||||
pub is_leader: bool,
|
pub is_leader: bool,
|
||||||
pub base: LogicGameObject,
|
pub base: LogicGameObject,
|
||||||
pub direction: LogicVector2,
|
pub direction: LogicVector2,
|
||||||
|
|
@ -29,7 +29,7 @@ impl Default for LogicCharacter {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
level_index: 0,
|
level_index: 0,
|
||||||
flag_160: false,
|
is_destroyed: false,
|
||||||
is_leader: false,
|
is_leader: false,
|
||||||
base: LogicGameObject::default(),
|
base: LogicGameObject::default(),
|
||||||
direction: LogicVector2::new(0, DIRECTION_BOTTOM),
|
direction: LogicVector2::new(0, DIRECTION_BOTTOM),
|
||||||
|
|
@ -53,7 +53,7 @@ impl Default for LogicCharacter {
|
||||||
impl LogicCharacter {
|
impl LogicCharacter {
|
||||||
pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> {
|
pub fn encode(&self, writer: &mut ByteStreamWriter) -> Result<()> {
|
||||||
writer.write_vint(self.level_index);
|
writer.write_vint(self.level_index);
|
||||||
writer.write_boolean(self.flag_160);
|
writer.write_boolean(self.is_destroyed);
|
||||||
writer.write_boolean(self.is_leader);
|
writer.write_boolean(self.is_leader);
|
||||||
self.base.encode_base(writer)?;
|
self.base.encode_base(writer)?;
|
||||||
writer.write_vint(self.direction.x);
|
writer.write_vint(self.direction.x);
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@ impl LogicVector2 {
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Payload)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Payload)]
|
||||||
pub struct LogicGameObject {
|
pub struct LogicGameObject {
|
||||||
#[codec(vint)]
|
#[codec(vint)]
|
||||||
pub field_28: i32,
|
pub owner_index: i32,
|
||||||
#[codec(vint)]
|
#[codec(vint)]
|
||||||
pub field_56: i32,
|
pub component_mask: i32,
|
||||||
pub position: LogicVector2,
|
pub position: LogicVector2,
|
||||||
#[codec(vint)]
|
#[codec(vint)]
|
||||||
pub owner_index: i32,
|
pub z: i32,
|
||||||
}
|
}
|
||||||
impl LogicGameObject {
|
impl LogicGameObject {
|
||||||
pub fn encode_base(&self, writer: &mut titan::ByteStreamWriter) -> titan::Result<()> {
|
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>),
|
Summoner(Box<crate::battle::logic_character::LogicSummoner>),
|
||||||
}
|
}
|
||||||
impl LogicObjectBody {
|
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<()> {
|
pub fn encode(&self, writer: &mut titan::ByteStreamWriter) -> titan::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
LogicObjectBody::Character(character) => character.encode(writer),
|
LogicObjectBody::Character(character) => character.encode(writer),
|
||||||
|
|
@ -52,6 +58,26 @@ pub struct LogicGameObjectEntry {
|
||||||
pub components: [Option<crate::battle::logic_component::LogicComponent>; COMPONENT_PASSES],
|
pub components: [Option<crate::battle::logic_component::LogicComponent>; COMPONENT_PASSES],
|
||||||
}
|
}
|
||||||
impl LogicGameObjectEntry {
|
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 {
|
pub fn object_type(&self) -> i32 {
|
||||||
self.global_id.0.map(|id| id.class_id - 1).unwrap_or(-1)
|
self.global_id.0.map(|id| id.class_id - 1).unwrap_or(-1)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue