Imminuty updates (#925)

* WIP Immunities

* Immunity getters

* remove redundent variable
replace it use with it's equivalent

* remove unused lookups, fix typos

* fix tests

* added imunity test

* address feedback

* more immunity tests

* explicit this
This commit is contained in:
Aaron Kimbrell 2023-01-06 23:59:19 -06:00 committed by GitHub
parent 1ac898ba00
commit 80f8dd8003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 681 additions and 99 deletions

View File

@ -366,7 +366,7 @@ enum eControlSceme {
SCHEME_WEAR_A_ROBOT //== freecam? SCHEME_WEAR_A_ROBOT //== freecam?
}; };
enum eStunState { enum class eStateChangeType : uint32_t {
PUSH, PUSH,
POP POP
}; };

View File

@ -293,6 +293,7 @@ enum GAME_MSG : unsigned short {
GAME_MSG_POP_EQUIPPED_ITEMS_STATE = 192, GAME_MSG_POP_EQUIPPED_ITEMS_STATE = 192,
GAME_MSG_SET_GM_LEVEL = 193, GAME_MSG_SET_GM_LEVEL = 193,
GAME_MSG_SET_STUNNED = 198, GAME_MSG_SET_STUNNED = 198,
GAME_MSG_SET_STUN_IMMUNITY = 200,
GAME_MSG_KNOCKBACK = 202, GAME_MSG_KNOCKBACK = 202,
GAME_MSG_REBUILD_CANCEL = 209, GAME_MSG_REBUILD_CANCEL = 209,
GAME_MSG_ENABLE_REBUILD = 213, GAME_MSG_ENABLE_REBUILD = 213,
@ -512,6 +513,7 @@ enum GAME_MSG : unsigned short {
GAME_MSG_UPDATE_CHAT_MODE = 1395, GAME_MSG_UPDATE_CHAT_MODE = 1395,
GAME_MSG_VEHICLE_NOTIFY_FINISHED_RACE = 1396, GAME_MSG_VEHICLE_NOTIFY_FINISHED_RACE = 1396,
GAME_MSG_SET_CONSUMABLE_ITEM = 1409, GAME_MSG_SET_CONSUMABLE_ITEM = 1409,
GAME_MSG_SET_STATUS_IMMUNITY = 1435,
GAME_MSG_SET_PET_NAME_MODERATED = 1448, GAME_MSG_SET_PET_NAME_MODERATED = 1448,
GAME_MSG_MODIFY_LEGO_SCORE = 1459, GAME_MSG_MODIFY_LEGO_SCORE = 1459,
GAME_MSG_RESTORE_TO_POST_LOAD_STATS = 1468, GAME_MSG_RESTORE_TO_POST_LOAD_STATS = 1468,

View File

@ -6,28 +6,47 @@
#include "Game.h" #include "Game.h"
#include "dLogger.h" #include "dLogger.h"
#include "DestroyableComponent.h" #include "DestroyableComponent.h"
#include "ControllablePhysicsComponent.h"
void ImmunityBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) { void ImmunityBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
auto* target = EntityManager::Instance()->GetEntity(branch.target); auto* target = EntityManager::Instance()->GetEntity(branch.target);
if (target == nullptr) { if (!target) {
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target); Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
return; return;
} }
auto* destroyable = static_cast<DestroyableComponent*>(target->GetComponent(COMPONENT_TYPE_DESTROYABLE)); auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
if (destroyableComponent) {
if (destroyable == nullptr) { destroyableComponent->SetStatusImmunity(
return; eStateChangeType::PUSH,
this->m_ImmuneToBasicAttack,
this->m_ImmuneToDamageOverTime,
this->m_ImmuneToKnockback,
this->m_ImmuneToInterrupt,
this->m_ImmuneToSpeed,
this->m_ImmuneToImaginationGain,
this->m_ImmuneToImaginationLoss,
this->m_ImmuneToQuickbuildInterrupt,
this->m_ImmuneToPullToPoint
);
} }
if (!this->m_immuneBasicAttack) { auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
return; if (controllablePhysicsComponent) {
controllablePhysicsComponent->SetStunImmunity(
eStateChangeType::PUSH,
context->caster,
this->m_ImmuneToStunAttack,
this->m_ImmuneToStunEquip,
this->m_ImmuneToStunInteract,
this->m_ImmuneToStunJump,
this->m_ImmuneToStunMove,
this->m_ImmuneToStunTurn,
this->m_ImmuneToStunUseItem
);
} }
destroyable->PushImmunity();
context->RegisterTimerBehavior(this, branch, target->GetObjectID()); context->RegisterTimerBehavior(this, branch, target->GetObjectID());
} }
@ -38,21 +57,60 @@ void ImmunityBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bi
void ImmunityBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) { void ImmunityBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) {
auto* target = EntityManager::Instance()->GetEntity(second); auto* target = EntityManager::Instance()->GetEntity(second);
if (target == nullptr) { if (!target) {
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", second); Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", second);
return; return;
} }
auto* destroyable = static_cast<DestroyableComponent*>(target->GetComponent(COMPONENT_TYPE_DESTROYABLE)); auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
if (destroyableComponent) {
if (destroyable == nullptr) { destroyableComponent->SetStatusImmunity(
return; eStateChangeType::POP,
this->m_ImmuneToBasicAttack,
this->m_ImmuneToDamageOverTime,
this->m_ImmuneToKnockback,
this->m_ImmuneToInterrupt,
this->m_ImmuneToSpeed,
this->m_ImmuneToImaginationGain,
this->m_ImmuneToImaginationLoss,
this->m_ImmuneToQuickbuildInterrupt,
this->m_ImmuneToPullToPoint
);
}
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
if (controllablePhysicsComponent) {
controllablePhysicsComponent->SetStunImmunity(
eStateChangeType::POP,
context->caster,
this->m_ImmuneToStunAttack,
this->m_ImmuneToStunEquip,
this->m_ImmuneToStunInteract,
this->m_ImmuneToStunJump,
this->m_ImmuneToStunMove,
this->m_ImmuneToStunTurn,
this->m_ImmuneToStunUseItem
);
} }
destroyable->PopImmunity();
} }
void ImmunityBehavior::Load() { void ImmunityBehavior::Load() {
this->m_immuneBasicAttack = GetBoolean("immune_basic_attack"); //Stun
this->m_ImmuneToStunAttack = GetBoolean("immune_stun_attack", false);
this->m_ImmuneToStunEquip = GetBoolean("immune_stun_equip", false);
this->m_ImmuneToStunInteract = GetBoolean("immune_stun_interact", false);
this->m_ImmuneToStunMove = GetBoolean("immune_stun_move", false);
this->m_ImmuneToStunTurn = GetBoolean("immune_stun_rotate", false);
// Status
this->m_ImmuneToBasicAttack = GetBoolean("immune_basic_attack", false);
this->m_ImmuneToDamageOverTime = GetBoolean("immune_damage_over_time", false);
this->m_ImmuneToKnockback = GetBoolean("immune_knockback", false);
this->m_ImmuneToInterrupt = GetBoolean("immune_interrupt", false);
this->m_ImmuneToSpeed = GetBoolean("immune_speed", false);
this->m_ImmuneToImaginationGain = GetBoolean("immune_imagination_gain", false);
this->m_ImmuneToImaginationLoss = GetBoolean("immune_imagination_loss", false);
this->m_ImmuneToQuickbuildInterrupt = GetBoolean("immune_quickbuild_interrupts", false);
this->m_ImmuneToPullToPoint = GetBoolean("immune_pulltopoint", false);
} }

View File

@ -4,8 +4,6 @@
class ImmunityBehavior final : public Behavior class ImmunityBehavior final : public Behavior
{ {
public: public:
uint32_t m_immuneBasicAttack;
/* /*
* Inherited * Inherited
*/ */
@ -20,4 +18,25 @@ public:
void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override; void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
void Load() override; void Load() override;
private:
// stuns
bool m_ImmuneToStunAttack = false;
bool m_ImmuneToStunEquip = false;
bool m_ImmuneToStunInteract = false;
bool m_ImmuneToStunJump = false; // Unused
bool m_ImmuneToStunMove = false;
bool m_ImmuneToStunTurn = false;
bool m_ImmuneToStunUseItem = false; // Unused
//status
bool m_ImmuneToBasicAttack = false;
bool m_ImmuneToDamageOverTime = false;
bool m_ImmuneToKnockback = false;
bool m_ImmuneToInterrupt = false;
bool m_ImmuneToSpeed = false;
bool m_ImmuneToImaginationGain = false;
bool m_ImmuneToImaginationLoss = false;
bool m_ImmuneToQuickbuildInterrupt = false;
bool m_ImmuneToPullToPoint = false; // Unused in cdclient, but used in client
}; };

View File

@ -35,6 +35,14 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Com
m_DirtyPickupRadiusScale = true; m_DirtyPickupRadiusScale = true;
m_IsTeleporting = false; m_IsTeleporting = false;
m_ImmuneToStunAttackCount = 0;
m_ImmuneToStunEquipCount = 0;
m_ImmuneToStunInteractCount = 0;
m_ImmuneToStunJumpCount = 0;
m_ImmuneToStunMoveCount = 0;
m_ImmuneToStunTurnCount = 0;
m_ImmuneToStunUseItemCount = 0;
if (entity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI if (entity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI
return; return;
@ -71,7 +79,14 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bo
outBitStream->Write(m_JetpackBypassChecks); outBitStream->Write(m_JetpackBypassChecks);
} }
outBitStream->Write0(); //This contains info about immunities, but for now I'm leaving it out. outBitStream->Write1(); // always write these on construction
outBitStream->Write(m_ImmuneToStunMoveCount);
outBitStream->Write(m_ImmuneToStunJumpCount);
outBitStream->Write(m_ImmuneToStunTurnCount);
outBitStream->Write(m_ImmuneToStunAttackCount);
outBitStream->Write(m_ImmuneToStunUseItemCount);
outBitStream->Write(m_ImmuneToStunEquipCount);
outBitStream->Write(m_ImmuneToStunInteractCount);
} }
if (m_IgnoreMultipliers) m_DirtyCheats = false; if (m_IgnoreMultipliers) m_DirtyCheats = false;
@ -298,3 +313,44 @@ void ControllablePhysicsComponent::RemoveSpeedboost(float value) {
SetSpeedMultiplier(m_SpeedBoost / 500.0f); // 500 being the base speed SetSpeedMultiplier(m_SpeedBoost / 500.0f); // 500 being the base speed
EntityManager::Instance()->SerializeEntity(m_Parent); EntityManager::Instance()->SerializeEntity(m_Parent);
} }
void ControllablePhysicsComponent::SetStunImmunity(
const eStateChangeType state,
const LWOOBJID originator,
const bool bImmuneToStunAttack,
const bool bImmuneToStunEquip,
const bool bImmuneToStunInteract,
const bool bImmuneToStunJump,
const bool bImmuneToStunMove,
const bool bImmuneToStunTurn,
const bool bImmuneToStunUseItem){
if (state == eStateChangeType::POP){
if (bImmuneToStunAttack && m_ImmuneToStunAttackCount > 0) m_ImmuneToStunAttackCount -= 1;
if (bImmuneToStunEquip && m_ImmuneToStunEquipCount > 0) m_ImmuneToStunEquipCount -= 1;
if (bImmuneToStunInteract && m_ImmuneToStunInteractCount > 0) m_ImmuneToStunInteractCount -= 1;
if (bImmuneToStunJump && m_ImmuneToStunJumpCount > 0) m_ImmuneToStunJumpCount -= 1;
if (bImmuneToStunMove && m_ImmuneToStunMoveCount > 0) m_ImmuneToStunMoveCount -= 1;
if (bImmuneToStunTurn && m_ImmuneToStunTurnCount > 0) m_ImmuneToStunTurnCount -= 1;
if (bImmuneToStunUseItem && m_ImmuneToStunUseItemCount > 0) m_ImmuneToStunUseItemCount -= 1;
} else if (state == eStateChangeType::PUSH) {
if (bImmuneToStunAttack) m_ImmuneToStunAttackCount += 1;
if (bImmuneToStunEquip) m_ImmuneToStunEquipCount += 1;
if (bImmuneToStunInteract) m_ImmuneToStunInteractCount += 1;
if (bImmuneToStunJump) m_ImmuneToStunJumpCount += 1;
if (bImmuneToStunMove) m_ImmuneToStunMoveCount += 1;
if (bImmuneToStunTurn) m_ImmuneToStunTurnCount += 1;
if (bImmuneToStunUseItem) m_ImmuneToStunUseItemCount += 1;
}
GameMessages::SendSetStunImmunity(
m_Parent->GetObjectID(), state, m_Parent->GetSystemAddress(), originator,
bImmuneToStunAttack,
bImmuneToStunEquip,
bImmuneToStunInteract,
bImmuneToStunJump,
bImmuneToStunMove,
bImmuneToStunTurn,
bImmuneToStunUseItem
);
}

View File

@ -264,6 +264,30 @@ public:
std::vector<float> GetActiveSpeedboosts() { return m_ActivePickupRadiusScales; }; std::vector<float> GetActiveSpeedboosts() { return m_ActivePickupRadiusScales; };
/**
* Push or Pop a layer of stun immunity to this entity
*/
void SetStunImmunity(
const eStateChangeType state,
const LWOOBJID originator = LWOOBJID_EMPTY,
const bool bImmuneToStunAttack = false,
const bool bImmuneToStunEquip = false,
const bool bImmuneToStunInteract = false,
const bool bImmuneToStunJump = false,
const bool bImmuneToStunMove = false,
const bool bImmuneToStunTurn = false,
const bool bImmuneToStunUseItem = false
);
// getters for stun immunities
const bool GetImmuneToStunAttack() { return m_ImmuneToStunAttackCount > 0;};
const bool GetImmuneToStunEquip() { return m_ImmuneToStunEquipCount > 0;};
const bool GetImmuneToStunInteract() { return m_ImmuneToStunInteractCount > 0;};
const bool GetImmuneToStunJump() { return m_ImmuneToStunJumpCount > 0;};
const bool GetImmuneToStunMove() { return m_ImmuneToStunMoveCount > 0;};
const bool GetImmuneToStunTurn() { return m_ImmuneToStunTurnCount > 0;};
const bool GetImmuneToStunUseItem() { return m_ImmuneToStunUseItemCount > 0;};
private: private:
/** /**
* The entity that owns this component * The entity that owns this component
@ -389,6 +413,17 @@ private:
* The active speed boost for this entity * The active speed boost for this entity
*/ */
float m_SpeedBoost; float m_SpeedBoost;
/**
* stun immunity counters
*/
int32_t m_ImmuneToStunAttackCount;
int32_t m_ImmuneToStunEquipCount;
int32_t m_ImmuneToStunInteractCount;
int32_t m_ImmuneToStunJumpCount;
int32_t m_ImmuneToStunMoveCount;
int32_t m_ImmuneToStunTurnCount;
int32_t m_ImmuneToStunUseItemCount;
}; };
#endif // CONTROLLABLEPHYSICSCOMPONENT_H #endif // CONTROLLABLEPHYSICSCOMPONENT_H

View File

@ -55,8 +55,17 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
m_LootMatrixID = 0; m_LootMatrixID = 0;
m_MinCoins = 0; m_MinCoins = 0;
m_MaxCoins = 0; m_MaxCoins = 0;
m_ImmuneStacks = 0;
m_DamageReduction = 0; m_DamageReduction = 0;
m_ImmuneToBasicAttackCount = 0;
m_ImmuneToDamageOverTimeCount = 0;
m_ImmuneToKnockbackCount = 0;
m_ImmuneToInterruptCount = 0;
m_ImmuneToSpeedCount = 0;
m_ImmuneToImaginationGainCount = 0;
m_ImmuneToImaginationLossCount = 0;
m_ImmuneToQuickbuildInterruptCount = 0;
m_ImmuneToPullToPointCount = 0;
} }
DestroyableComponent::~DestroyableComponent() { DestroyableComponent::~DestroyableComponent() {
@ -106,7 +115,16 @@ void DestroyableComponent::Reinitialize(LOT templateID) {
void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) { void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
if (bIsInitialUpdate) { if (bIsInitialUpdate) {
outBitStream->Write0(); //Contains info about immunities this object has, but it's left out for now. outBitStream->Write1(); // always write these on construction
outBitStream->Write(m_ImmuneToBasicAttackCount);
outBitStream->Write(m_ImmuneToDamageOverTimeCount);
outBitStream->Write(m_ImmuneToKnockbackCount);
outBitStream->Write(m_ImmuneToInterruptCount);
outBitStream->Write(m_ImmuneToSpeedCount);
outBitStream->Write(m_ImmuneToImaginationGainCount);
outBitStream->Write(m_ImmuneToImaginationLossCount);
outBitStream->Write(m_ImmuneToQuickbuildInterruptCount);
outBitStream->Write(m_ImmuneToPullToPointCount);
} }
outBitStream->Write(m_DirtyHealth || bIsInitialUpdate); outBitStream->Write(m_DirtyHealth || bIsInitialUpdate);
@ -336,7 +354,7 @@ void DestroyableComponent::SetDamageReduction(int32_t value) {
void DestroyableComponent::SetIsImmune(bool value) { void DestroyableComponent::SetIsImmune(bool value) {
m_DirtyHealth = true; m_DirtyHealth = true;
m_ImmuneStacks = value ? 1 : 0; m_ImmuneToBasicAttackCount = value ? 1 : 0;
} }
void DestroyableComponent::SetIsGMImmune(bool value) { void DestroyableComponent::SetIsGMImmune(bool value) {
@ -439,7 +457,7 @@ void DestroyableComponent::SetAttacksToBlock(const uint32_t value) {
} }
bool DestroyableComponent::IsImmune() const { bool DestroyableComponent::IsImmune() const {
return m_ImmuneStacks > 0 || m_IsGMImmune; return m_IsGMImmune || m_ImmuneToBasicAttackCount > 0;
} }
bool DestroyableComponent::IsKnockbackImmune() const { bool DestroyableComponent::IsKnockbackImmune() const {
@ -804,12 +822,53 @@ void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) {
AddFaction(factionID, ignoreChecks); AddFaction(factionID, ignoreChecks);
} }
void DestroyableComponent::PushImmunity(int32_t stacks) { void DestroyableComponent::SetStatusImmunity(
m_ImmuneStacks += stacks; const eStateChangeType state,
const bool bImmuneToBasicAttack,
const bool bImmuneToDamageOverTime,
const bool bImmuneToKnockback,
const bool bImmuneToInterrupt,
const bool bImmuneToSpeed,
const bool bImmuneToImaginationGain,
const bool bImmuneToImaginationLoss,
const bool bImmuneToQuickbuildInterrupt,
const bool bImmuneToPullToPoint) {
if (state == eStateChangeType::POP) {
if (bImmuneToBasicAttack && m_ImmuneToBasicAttackCount > 0) m_ImmuneToBasicAttackCount -= 1;
if (bImmuneToDamageOverTime && m_ImmuneToDamageOverTimeCount > 0) m_ImmuneToDamageOverTimeCount -= 1;
if (bImmuneToKnockback && m_ImmuneToKnockbackCount > 0) m_ImmuneToKnockbackCount -= 1;
if (bImmuneToInterrupt && m_ImmuneToInterruptCount > 0) m_ImmuneToInterruptCount -= 1;
if (bImmuneToSpeed && m_ImmuneToSpeedCount > 0) m_ImmuneToSpeedCount -= 1;
if (bImmuneToImaginationGain && m_ImmuneToImaginationGainCount > 0) m_ImmuneToImaginationGainCount -= 1;
if (bImmuneToImaginationLoss && m_ImmuneToImaginationLossCount > 0) m_ImmuneToImaginationLossCount -= 1;
if (bImmuneToQuickbuildInterrupt && m_ImmuneToQuickbuildInterruptCount > 0) m_ImmuneToQuickbuildInterruptCount -= 1;
if (bImmuneToPullToPoint && m_ImmuneToPullToPointCount > 0) m_ImmuneToPullToPointCount -= 1;
} else if (state == eStateChangeType::PUSH){
if (bImmuneToBasicAttack) m_ImmuneToBasicAttackCount += 1;
if (bImmuneToDamageOverTime) m_ImmuneToDamageOverTimeCount += 1;
if (bImmuneToKnockback) m_ImmuneToKnockbackCount += 1;
if (bImmuneToInterrupt) m_ImmuneToInterruptCount += 1;
if (bImmuneToSpeed) m_ImmuneToSpeedCount += 1;
if (bImmuneToImaginationGain) m_ImmuneToImaginationGainCount += 1;
if (bImmuneToImaginationLoss) m_ImmuneToImaginationLossCount += 1;
if (bImmuneToQuickbuildInterrupt) m_ImmuneToQuickbuildInterruptCount += 1;
if (bImmuneToPullToPoint) m_ImmuneToPullToPointCount += 1;
} }
void DestroyableComponent::PopImmunity(int32_t stacks) { GameMessages::SendSetStatusImmunity(
m_ImmuneStacks -= stacks; m_Parent->GetObjectID(), state, m_Parent->GetSystemAddress(),
bImmuneToBasicAttack,
bImmuneToDamageOverTime,
bImmuneToKnockback,
bImmuneToInterrupt,
bImmuneToSpeed,
bImmuneToImaginationGain,
bImmuneToImaginationLoss,
bImmuneToQuickbuildInterrupt,
bImmuneToPullToPoint
);
} }
void DestroyableComponent::FixStats() { void DestroyableComponent::FixStats() {

View File

@ -396,16 +396,31 @@ public:
void Smash(LWOOBJID source, eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u"", uint32_t skillID = 0); void Smash(LWOOBJID source, eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u"", uint32_t skillID = 0);
/** /**
* Pushes a layer of immunity to this entity, making it immune for longer * Push or Pop a layer of status immunity to this entity
* @param stacks the amount of immunity to add
*/ */
void PushImmunity(int32_t stacks = 1); void SetStatusImmunity(
const eStateChangeType state,
const bool bImmuneToBasicAttack = false,
const bool bImmuneToDamageOverTime = false,
const bool bImmuneToKnockback = false,
const bool bImmuneToInterrupt = false,
const bool bImmuneToSpeed = false,
const bool bImmuneToImaginationGain = false,
const bool bImmuneToImaginationLoss = false,
const bool bImmuneToQuickbuildInterrupt = false,
const bool bImmuneToPullToPoint = false
);
/** // Getters for status immunities
* Pops layers of immunity, making it immune for less longer const bool GetImmuneToBasicAttack() {return m_ImmuneToBasicAttackCount > 0;};
* @param stacks the number of layers of immunity to remove const bool GetImmuneToDamageOverTime() {return m_ImmuneToDamageOverTimeCount > 0;};
*/ const bool GetImmuneToKnockback() {return m_ImmuneToKnockbackCount > 0;};
void PopImmunity(int32_t stacks = 1); const bool GetImmuneToInterrupt() {return m_ImmuneToInterruptCount > 0;};
const bool GetImmuneToSpeed() {return m_ImmuneToSpeedCount > 0;};
const bool GetImmuneToImaginationGain() {return m_ImmuneToImaginationGainCount > 0;};
const bool GetImmuneToImaginationLoss() {return m_ImmuneToImaginationLossCount > 0;};
const bool GetImmuneToQuickbuildInterrupt() {return m_ImmuneToQuickbuildInterruptCount > 0;};
const bool GetImmuneToPullToPoint() {return m_ImmuneToPullToPointCount > 0;};
/** /**
* Utility to reset all stats to the default stats based on items and completed missions * Utility to reset all stats to the default stats based on items and completed missions
@ -493,11 +508,6 @@ private:
*/ */
uint32_t m_AttacksToBlock; uint32_t m_AttacksToBlock;
/**
* The layers of immunity this entity has left
*/
int32_t m_ImmuneStacks;
/** /**
* The amount of damage that should be reduced from every attack * The amount of damage that should be reduced from every attack
*/ */
@ -577,6 +587,19 @@ private:
* The list of scripts subscribed to this components actions * The list of scripts subscribed to this components actions
*/ */
std::map<LWOOBJID, CppScripts::Script*> m_SubscribedScripts; std::map<LWOOBJID, CppScripts::Script*> m_SubscribedScripts;
/**
* status immunity counters
*/
uint32_t m_ImmuneToBasicAttackCount;
uint32_t m_ImmuneToDamageOverTimeCount;
uint32_t m_ImmuneToKnockbackCount;
uint32_t m_ImmuneToInterruptCount;
uint32_t m_ImmuneToSpeedCount;
uint32_t m_ImmuneToImaginationGainCount;
uint32_t m_ImmuneToImaginationLossCount;
uint32_t m_ImmuneToQuickbuildInterruptCount;
uint32_t m_ImmuneToPullToPointCount;
}; };
#endif // DESTROYABLECOMPONENT_H #endif // DESTROYABLECOMPONENT_H

View File

@ -959,7 +959,7 @@ void InventoryComponent::HandlePossession(Item* item) {
return; return;
} }
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStunState::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
// Set the mount Item ID so that we know what were handling // Set the mount Item ID so that we know what were handling
possessorComponent->SetMountItemID(item->GetId()); possessorComponent->SetMountItemID(item->GetId());

View File

@ -54,7 +54,7 @@ void PossessorComponent::Mount(Entity* mount) {
// GM's to send // GM's to send
GameMessages::SendSetJetPackMode(m_Parent, false); GameMessages::SendSetJetPackMode(m_Parent, false);
GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress()); GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress());
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStunState::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
EntityManager::Instance()->SerializeEntity(m_Parent); EntityManager::Instance()->SerializeEntity(m_Parent);
EntityManager::Instance()->SerializeEntity(mount); EntityManager::Instance()->SerializeEntity(mount);

View File

@ -95,7 +95,7 @@ void RailActivatorComponent::OnUse(Entity* originator) {
void RailActivatorComponent::OnRailMovementReady(Entity* originator) const { void RailActivatorComponent::OnRailMovementReady(Entity* originator) const {
// Stun the originator // Stun the originator
GameMessages::SendSetStunned(originator->GetObjectID(), PUSH, originator->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(originator->GetObjectID(), eStateChangeType::PUSH, originator->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );
@ -123,7 +123,7 @@ void RailActivatorComponent::OnRailMovementReady(Entity* originator) const {
void RailActivatorComponent::OnCancelRailMovement(Entity* originator) { void RailActivatorComponent::OnCancelRailMovement(Entity* originator) {
// Remove the stun from the originator // Remove the stun from the originator
GameMessages::SendSetStunned(originator->GetObjectID(), POP, originator->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(originator->GetObjectID(), eStateChangeType::POP, originator->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );

View File

@ -2904,7 +2904,7 @@ void GameMessages::HandleCinematicUpdate(RakNet::BitStream* inStream, Entity* en
} }
} }
void GameMessages::SendSetStunned(LWOOBJID objectId, eStunState stateChangeType, const SystemAddress& sysAddr, void GameMessages::SendSetStunned(LWOOBJID objectId, eStateChangeType stateChangeType, const SystemAddress& sysAddr,
LWOOBJID originator, bool bCantAttack, bool bCantEquip, LWOOBJID originator, bool bCantAttack, bool bCantEquip,
bool bCantInteract, bool bCantJump, bool bCantMove, bool bCantTurn, bool bCantInteract, bool bCantJump, bool bCantMove, bool bCantTurn,
bool bCantUseItem, bool bDontTerminateInteract, bool bIgnoreImmunity, bool bCantUseItem, bool bDontTerminateInteract, bool bIgnoreImmunity,
@ -2952,6 +2952,69 @@ void GameMessages::SendSetStunned(LWOOBJID objectId, eStunState stateChangeType,
SEND_PACKET; SEND_PACKET;
} }
void GameMessages::SendSetStunImmunity(LWOOBJID target, eStateChangeType state, const SystemAddress& sysAddr,
LWOOBJID originator,
bool bImmuneToStunAttack,
bool bImmuneToStunEquip,
bool bImmuneToStunInteract,
bool bImmuneToStunJump,
bool bImmuneToStunMove,
bool bImmuneToStunTurn,
bool bImmuneToStunUseItem) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(target);
bitStream.Write(GAME_MSG::GAME_MSG_SET_STUN_IMMUNITY);
bitStream.Write(originator != LWOOBJID_EMPTY);
if (originator != LWOOBJID_EMPTY) bitStream.Write(originator);
bitStream.Write(state);
bitStream.Write(bImmuneToStunAttack);
bitStream.Write(bImmuneToStunEquip);
bitStream.Write(bImmuneToStunInteract);
bitStream.Write(bImmuneToStunJump);
bitStream.Write(bImmuneToStunMove);
bitStream.Write(bImmuneToStunTurn);
bitStream.Write(bImmuneToStunUseItem);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
SEND_PACKET;
}
void GameMessages::SendSetStatusImmunity(LWOOBJID objectId, eStateChangeType state, const SystemAddress& sysAddr,
bool bImmuneToBasicAttack,
bool bImmuneToDamageOverTime,
bool bImmuneToKnockback,
bool bImmuneToInterrupt,
bool bImmuneToSpeed,
bool bImmuneToImaginationGain,
bool bImmuneToImaginationLoss,
bool bImmuneToQuickbuildInterrupt,
bool bImmuneToPullToPoint) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectId);
bitStream.Write(GAME_MSG::GAME_MSG_SET_STATUS_IMMUNITY);
bitStream.Write(state);
bitStream.Write(bImmuneToBasicAttack);
bitStream.Write(bImmuneToDamageOverTime);
bitStream.Write(bImmuneToKnockback);
bitStream.Write(bImmuneToInterrupt);
bitStream.Write(bImmuneToSpeed);
bitStream.Write(bImmuneToImaginationGain);
bitStream.Write(bImmuneToImaginationLoss);
bitStream.Write(bImmuneToQuickbuildInterrupt);
bitStream.Write(bImmuneToPullToPoint);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
SEND_PACKET;
}
void GameMessages::SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent, float fAngle, const SystemAddress& sysAddr) { void GameMessages::SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent, float fAngle, const SystemAddress& sysAddr) {
CBITSTREAM; CBITSTREAM;
@ -3991,7 +4054,7 @@ void GameMessages::HandleDismountComplete(RakNet::BitStream* inStream, Entity* e
EntityManager::Instance()->SerializeEntity(entity); EntityManager::Instance()->SerializeEntity(entity);
// We aren't mounted so remove the stun // We aren't mounted so remove the stun
GameMessages::SendSetStunned(entity->GetObjectID(), eStunState::POP, UNASSIGNED_SYSTEM_ADDRESS, LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); GameMessages::SendSetStunned(entity->GetObjectID(), eStateChangeType::POP, UNASSIGNED_SYSTEM_ADDRESS, LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
} }
} }
} }

View File

@ -268,7 +268,7 @@ namespace GameMessages {
float leadOut = -1.0f, bool leavePlayerLocked = false); float leadOut = -1.0f, bool leavePlayerLocked = false);
void HandleCinematicUpdate(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); void HandleCinematicUpdate(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
void SendSetStunned(LWOOBJID objectId, eStunState stateChangeType, const SystemAddress& sysAddr, void SendSetStunned(LWOOBJID objectId, eStateChangeType stateChangeType, const SystemAddress& sysAddr,
LWOOBJID originator = LWOOBJID_EMPTY, bool bCantAttack = false, bool bCantEquip = false, LWOOBJID originator = LWOOBJID_EMPTY, bool bCantAttack = false, bool bCantEquip = false,
bool bCantInteract = false, bool bCantJump = false, bool bCantMove = false, bool bCantTurn = false, bool bCantInteract = false, bool bCantJump = false, bool bCantMove = false, bool bCantTurn = false,
bool bCantUseItem = false, bool bDontTerminateInteract = false, bool bIgnoreImmunity = true, bool bCantUseItem = false, bool bDontTerminateInteract = false, bool bIgnoreImmunity = true,
@ -277,6 +277,35 @@ namespace GameMessages {
bool bCantMoveOutChangeWasApplied = false, bool bCantTurnOutChangeWasApplied = false, bool bCantMoveOutChangeWasApplied = false, bool bCantTurnOutChangeWasApplied = false,
bool bCantUseItemOutChangeWasApplied = false); bool bCantUseItemOutChangeWasApplied = false);
void SendSetStunImmunity(
LWOOBJID target,
eStateChangeType state,
const SystemAddress& sysAddr,
LWOOBJID originator = LWOOBJID_EMPTY,
bool bImmuneToStunAttack = false,
bool bImmuneToStunEquip = false,
bool bImmuneToStunInteract = false,
bool bImmuneToStunJump = false,
bool bImmuneToStunMove = false,
bool bImmuneToStunTurn = false,
bool bImmuneToStunUseItem = false
);
void SendSetStatusImmunity(
LWOOBJID objectId,
eStateChangeType state,
const SystemAddress& sysAddr,
bool bImmuneToBasicAttack = false,
bool bImmuneToDamageOverTime = false,
bool bImmuneToKnockback = false,
bool bImmuneToInterrupt = false,
bool bImmuneToSpeed = false,
bool bImmuneToImaginationGain = false,
bool bImmuneToImaginationLoss = false,
bool bImmuneToQuickbuildInterrupt = false,
bool bImmuneToPullToPoint = false
);
void SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent, float fAngle, const SystemAddress& sysAddr); void SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent, float fAngle, const SystemAddress& sysAddr);
void SendAddRunSpeedModifier(LWOOBJID objectId, LWOOBJID caster, uint32_t modifier, const SystemAddress& sysAddr); void SendAddRunSpeedModifier(LWOOBJID objectId, LWOOBJID caster, uint32_t modifier, const SystemAddress& sysAddr);

View File

@ -131,7 +131,7 @@ void BaseEnemyApe::StunApe(Entity* self, bool stunState) {
skillComponent->Interrupt(); skillComponent->Interrupt();
} }
GameMessages::SendSetStunned(self->GetObjectID(), stunState ? PUSH : POP, UNASSIGNED_SYSTEM_ADDRESS, self->GetObjectID(), GameMessages::SendSetStunned(self->GetObjectID(), stunState ? eStateChangeType::PUSH : eStateChangeType::POP, UNASSIGNED_SYSTEM_ADDRESS, self->GetObjectID(),
true, true, true, true, true, true, true, true, true, true,
true, true, true, true); true, true, true, true);

View File

@ -147,21 +147,21 @@ void AmSkullkinDrill::OnUse(Entity* self, Entity* user) {
} }
void AmSkullkinDrill::FreezePlayer(Entity* self, Entity* player, bool bFreeze) { void AmSkullkinDrill::FreezePlayer(Entity* self, Entity* player, bool bFreeze) {
eStunState eChangeType = POP; auto StateChangeType = eStateChangeType::POP;
if (bFreeze) { if (bFreeze) {
if (player->GetIsDead()) { if (player->GetIsDead()) {
return; return;
} }
eChangeType = PUSH; StateChangeType = eStateChangeType::PUSH;
} else { } else {
if (player->GetIsDead()) { if (player->GetIsDead()) {
// //
} }
} }
GameMessages::SendSetStunned(player->GetObjectID(), eChangeType, player->GetSystemAddress(), self->GetObjectID(), GameMessages::SendSetStunned(player->GetObjectID(), StateChangeType, player->GetSystemAddress(), self->GetObjectID(),
true, false, true, false, true, false, true true, false, true, false, true, false, true
); );
} }

View File

@ -13,7 +13,7 @@ void GfCaptainsCannon::OnUse(Entity* self, Entity* user) {
self->SetVar<bool>(u"bIsInUse", true); self->SetVar<bool>(u"bIsInUse", true);
self->SetNetworkVar<bool>(u"bIsInUse", true); self->SetNetworkVar<bool>(u"bIsInUse", true);
GameMessages::SendSetStunned(user->GetObjectID(), PUSH, user->GetSystemAddress(), GameMessages::SendSetStunned(user->GetObjectID(), eStateChangeType::PUSH, user->GetSystemAddress(),
LWOOBJID_EMPTY, true, true, true, true, true, true, true, true LWOOBJID_EMPTY, true, true, true, true, true, true, true, true
); );
@ -63,7 +63,7 @@ void GfCaptainsCannon::OnTimerDone(Entity* self, std::string timerName) {
GameMessages::SendPlay2DAmbientSound(player, "{7457d85c-4537-4317-ac9d-2f549219ea87}"); GameMessages::SendPlay2DAmbientSound(player, "{7457d85c-4537-4317-ac9d-2f549219ea87}");
} else if (timerName == "cinematicTimer") { } else if (timerName == "cinematicTimer") {
GameMessages::SendSetStunned(playerId, POP, player->GetSystemAddress(), GameMessages::SendSetStunned(playerId, eStateChangeType::POP, player->GetSystemAddress(),
LWOOBJID_EMPTY, true, true, true, true, true, true, true, true LWOOBJID_EMPTY, true, true, true, true, true, true, true, true
); );

View File

@ -16,7 +16,7 @@ void MastTeleport::OnRebuildComplete(Entity* self, Entity* target) {
if (Preconditions::Check(target, 154) && Preconditions::Check(target, 44)) { if (Preconditions::Check(target, 154) && Preconditions::Check(target, 44)) {
self->SetVar<LWOOBJID>(u"userID", target->GetObjectID()); self->SetVar<LWOOBJID>(u"userID", target->GetObjectID());
GameMessages::SendSetStunned(target->GetObjectID(), PUSH, target->GetSystemAddress(), GameMessages::SendSetStunned(target->GetObjectID(), eStateChangeType::PUSH, target->GetSystemAddress(),
LWOOBJID_EMPTY, true, true, true, true, true, true, true LWOOBJID_EMPTY, true, true, true, true, true, true, true
); );
@ -81,7 +81,7 @@ void MastTeleport::OnTimerDone(Entity* self, std::string timerName) {
GameMessages::SendTeleport(playerId, position, NiQuaternion::IDENTITY, player->GetSystemAddress()); GameMessages::SendTeleport(playerId, position, NiQuaternion::IDENTITY, player->GetSystemAddress());
GameMessages::SendSetStunned(playerId, POP, player->GetSystemAddress(), GameMessages::SendSetStunned(playerId, eStateChangeType::POP, player->GetSystemAddress(),
LWOOBJID_EMPTY, true, true, true, true, true, true, true LWOOBJID_EMPTY, true, true, true, true, true, true, true
); );
} }

View File

@ -36,7 +36,7 @@ void NtAssemblyTubeServer::RunAssemblyTube(Entity* self, Entity* player) {
if (player->IsPlayer() && !bPlayerBeingTeleported) { if (player->IsPlayer() && !bPlayerBeingTeleported) {
auto teleCinematic = self->GetVar<std::u16string>(u"Cinematic"); auto teleCinematic = self->GetVar<std::u16string>(u"Cinematic");
GameMessages::SendSetStunned(playerID, PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(playerID, eStateChangeType::PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );
@ -108,7 +108,7 @@ void NtAssemblyTubeServer::UnlockPlayer(Entity* self, Entity* player) {
m_TeleportingPlayerTable[playerID] = false; m_TeleportingPlayerTable[playerID] = false;
GameMessages::SendSetStunned(playerID, POP, player->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(playerID, eStateChangeType::POP, player->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );
} }

View File

@ -34,11 +34,11 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) {
GameMessages::SendPlayAnimation(player, u"rebuild-celebrate"); GameMessages::SendPlayAnimation(player, u"rebuild-celebrate");
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SparkStop", 0, 0, player->GetObjectID(), "", player->GetSystemAddress()); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SparkStop", 0, 0, player->GetObjectID(), "", player->GetSystemAddress());
GameMessages::SendSetStunned(player->GetObjectID(), eStunState::POP, player->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true); GameMessages::SendSetStunned(player->GetObjectID(), eStateChangeType::POP, player->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true);
self->SetVar(u"bActive", false); self->SetVar(u"bActive", false);
}); });
GameMessages::SendPlayAnimation(user, u"nexus-powerpanel", 6.0f); GameMessages::SendPlayAnimation(user, u"nexus-powerpanel", 6.0f);
GameMessages::SendSetStunned(user->GetObjectID(), eStunState::PUSH, user->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true); GameMessages::SendSetStunned(user->GetObjectID(), eStateChangeType::PUSH, user->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true);
return; return;
} }

View File

@ -22,7 +22,7 @@ void NtParadoxTeleServer::OnProximityUpdate(Entity* self, Entity* entering, std:
const auto bPlayerBeingTeleported = m_TeleportingPlayerTable[playerID]; const auto bPlayerBeingTeleported = m_TeleportingPlayerTable[playerID];
if (player->IsPlayer() && !bPlayerBeingTeleported) { if (player->IsPlayer() && !bPlayerBeingTeleported) {
GameMessages::SendSetStunned(playerID, PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(playerID, eStateChangeType::PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );
@ -100,7 +100,7 @@ void NtParadoxTeleServer::UnlockPlayer(Entity* self, Entity* player) {
m_TeleportingPlayerTable[playerID] = false; m_TeleportingPlayerTable[playerID] = false;
GameMessages::SendSetStunned(playerID, POP, player->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(playerID, eStateChangeType::POP, player->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );

View File

@ -14,7 +14,7 @@ void NtVentureCannonServer::OnUse(Entity* self, Entity* user) {
self->SetNetworkVar(u"bIsInUse", true); self->SetNetworkVar(u"bIsInUse", true);
GameMessages::SendSetStunned(playerID, PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(playerID, eStateChangeType::PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );
@ -92,7 +92,7 @@ void NtVentureCannonServer::ExitCannonEnded(Entity* self, Entity* player) {
} }
void NtVentureCannonServer::UnlockCannonPlayer(Entity* self, Entity* player) { void NtVentureCannonServer::UnlockCannonPlayer(Entity* self, Entity* player) {
GameMessages::SendSetStunned(player->GetObjectID(), POP, player->GetSystemAddress(), LWOOBJID_EMPTY, GameMessages::SendSetStunned(player->GetObjectID(), eStateChangeType::POP, player->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );

View File

@ -15,7 +15,8 @@ void BaseConsoleTeleportServer::BaseOnMessageBoxResponse(Entity* self, Entity* s
if (button == 1) { if (button == 1) {
GameMessages::SendSetStunned(player->GetObjectID(), PUSH, player->GetSystemAddress(), player->GetObjectID(), GameMessages::SendSetStunned(
player->GetObjectID(), eStateChangeType::PUSH, player->GetSystemAddress(), player->GetObjectID(),
true, true, true, true, true, true, true true, true, true, true, true, true, true
); );
@ -82,11 +83,10 @@ void BaseConsoleTeleportServer::TransferPlayer(Entity* self, Entity* player, int
return; return;
} }
// Ignoring extra effects for now GameMessages::SendSetStunned(
player->GetObjectID(), eStateChangeType::POP, player->GetSystemAddress(), player->GetObjectID(),
/*GameMessages::SendSetStunned(player->GetObjectID(), POP, player->GetSystemAddress(), player->GetObjectID(),
true, true, true, true, true, true, true true, true, true, true, true, true, true
);*/ );
GameMessages::SendTerminateInteraction(player->GetObjectID(), FROM_INTERACTION, player->GetObjectID()); GameMessages::SendTerminateInteraction(player->GetObjectID(), FROM_INTERACTION, player->GetObjectID());

View File

@ -2,49 +2,56 @@
#include "GameMessages.h" #include "GameMessages.h"
#include "SkillComponent.h" #include "SkillComponent.h"
#include "DestroyableComponent.h" #include "DestroyableComponent.h"
#include "ControllablePhysicsComponent.h"
#include "EntityManager.h" #include "EntityManager.h"
void PersonalFortress::OnStartup(Entity* self) { void PersonalFortress::OnStartup(Entity* self) {
auto* owner = self->GetOwner(); auto* owner = self->GetOwner();
self->AddTimer("FireSkill", 1.5); self->AddTimer("FireSkill", 1.5);
GameMessages::SendSetStunned(owner->GetObjectID(), PUSH, owner->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true, true, true
);
auto* destroyableComponent = owner->GetComponent<DestroyableComponent>(); auto* destroyableComponent = owner->GetComponent<DestroyableComponent>();
if (destroyableComponent) destroyableComponent->SetStatusImmunity(
eStateChangeType::PUSH,
true, true, true, true, true, false, true, false, false
);
if (destroyableComponent != nullptr) { auto* controllablePhysicsComponent = owner->GetComponent<ControllablePhysicsComponent>();
destroyableComponent->PushImmunity(); if (controllablePhysicsComponent) controllablePhysicsComponent->SetStunImmunity(
} eStateChangeType::PUSH, LWOOBJID_EMPTY,
true, true, true, true, true, true
);
GameMessages::SendSetStunned(owner->GetObjectID(), eStateChangeType::PUSH, owner->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true, true, true
);
EntityManager::Instance()->SerializeEntity(owner); EntityManager::Instance()->SerializeEntity(owner);
} }
void PersonalFortress::OnDie(Entity* self, Entity* killer) { void PersonalFortress::OnDie(Entity* self, Entity* killer) {
auto* owner = self->GetOwner(); auto* owner = self->GetOwner();
GameMessages::SendSetStunned(owner->GetObjectID(), POP, owner->GetSystemAddress(), LWOOBJID_EMPTY, auto* destroyableComponent = owner->GetComponent<DestroyableComponent>();
true, true, true, true, true, true, true, true, true if (destroyableComponent) destroyableComponent->SetStatusImmunity(
eStateChangeType::POP,
true, true, true, true, true, false, true, false, false
); );
auto* destroyableComponent = owner->GetComponent<DestroyableComponent>(); auto* controllablePhysicsComponent = owner->GetComponent<ControllablePhysicsComponent>();
if (controllablePhysicsComponent) controllablePhysicsComponent->SetStunImmunity(
eStateChangeType::POP, LWOOBJID_EMPTY,
true, true, true, true, true, true
);
if (destroyableComponent != nullptr) { GameMessages::SendSetStunned(owner->GetObjectID(), eStateChangeType::POP, owner->GetSystemAddress(), LWOOBJID_EMPTY,
destroyableComponent->PopImmunity(); true, true, true, true, true, true, true, true, true
} );
EntityManager::Instance()->SerializeEntity(owner); EntityManager::Instance()->SerializeEntity(owner);
} }
void PersonalFortress::OnTimerDone(Entity* self, std::string timerName) { void PersonalFortress::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "FireSkill") { if (timerName == "FireSkill") {
auto* owner = self->GetOwner();
auto* skillComponent = self->GetComponent<SkillComponent>(); auto* skillComponent = self->GetComponent<SkillComponent>();
if (skillComponent) skillComponent->CalculateBehavior(650, 13364, LWOOBJID_EMPTY, true, false);
if (skillComponent == nullptr) {
return;
}
skillComponent->CalculateBehavior(650, 13364, LWOOBJID_EMPTY, true, false);
} }
} }

View File

@ -77,7 +77,7 @@ void SGCannon::OnActivityStateChangeRequest(Entity* self, LWOOBJID senderID, int
auto* player = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable)); auto* player = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
if (player != nullptr) { if (player != nullptr) {
Game::logger->Log("SGCannon", "Player is ready"); Game::logger->Log("SGCannon", "Player is ready");
/*GameMessages::SendSetStunned(player->GetObjectID(), PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY, /*GameMessages::SendSetStunned(player->GetObjectID(), eStateChangeType::PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY,
true, true, true, true, true, true, true);*/ true, true, true, true, true, true, true);*/
Game::logger->Log("SGCannon", "Sending ActivityEnter"); Game::logger->Log("SGCannon", "Sending ActivityEnter");

View File

@ -41,10 +41,19 @@ protected:
TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) { TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) {
destroyableComponent->Serialize(&bitStream, true, flags); destroyableComponent->Serialize(&bitStream, true, flags);
// Assert that the full number of bits are present // Assert that the full number of bits are present
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 460); ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 748);
{ {
// Now read in the full serialized construction BitStream // Now read in the full serialized construction BitStream
bool optionStatusImmunityInfo{}; // Values under this option are unused. bool optionStatusImmunityInfo{};
uint32_t ImmuneToBasicAttackCount{};
uint32_t ImmuneToDamageOverTimeCount{};
uint32_t ImmuneToKnockbackCount{};
uint32_t ImmuneToInterruptCount{};
uint32_t ImmuneToSpeedCount{};
uint32_t ImmuneToImaginationGainCount{};
uint32_t ImmuneToImaginationLossCount{};
uint32_t ImmuneToQuickbuildInterruptCount{};
uint32_t ImmuneToPullToPointCount{};
bool optionStatsInfo{}; bool optionStatsInfo{};
uint32_t currentHealth{}; uint32_t currentHealth{};
float maxHealth{}; float maxHealth{};
@ -70,7 +79,15 @@ TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) {
bool optionIsOnThreatList{}; bool optionIsOnThreatList{};
bool isThreatened{}; bool isThreatened{};
bitStream.Read(optionStatusImmunityInfo); bitStream.Read(optionStatusImmunityInfo);
bitStream.Read(ImmuneToBasicAttackCount);
bitStream.Read(ImmuneToDamageOverTimeCount);
bitStream.Read(ImmuneToKnockbackCount);
bitStream.Read(ImmuneToInterruptCount);
bitStream.Read(ImmuneToSpeedCount);
bitStream.Read(ImmuneToImaginationGainCount);
bitStream.Read(ImmuneToImaginationLossCount);
bitStream.Read(ImmuneToQuickbuildInterruptCount);
bitStream.Read(ImmuneToPullToPointCount);
bitStream.Read(optionStatsInfo); bitStream.Read(optionStatsInfo);
bitStream.Read(currentHealth); bitStream.Read(currentHealth);
bitStream.Read(maxHealth); bitStream.Read(maxHealth);
@ -101,7 +118,16 @@ TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) {
bitStream.Read(optionIsOnThreatList); bitStream.Read(optionIsOnThreatList);
bitStream.Read(isThreatened); bitStream.Read(isThreatened);
EXPECT_EQ(optionStatusImmunityInfo, false); EXPECT_EQ(optionStatusImmunityInfo, true);
EXPECT_EQ(ImmuneToBasicAttackCount, 0);
EXPECT_EQ(ImmuneToDamageOverTimeCount, 0);
EXPECT_EQ(ImmuneToKnockbackCount, 0);
EXPECT_EQ(ImmuneToInterruptCount, 0);
EXPECT_EQ(ImmuneToSpeedCount, 0);
EXPECT_EQ(ImmuneToImaginationGainCount, 0);
EXPECT_EQ(ImmuneToImaginationLossCount, 0);
EXPECT_EQ(ImmuneToQuickbuildInterruptCount, 0);
EXPECT_EQ(ImmuneToPullToPointCount, 0);
EXPECT_EQ(optionStatsInfo, true); EXPECT_EQ(optionStatsInfo, true);
EXPECT_EQ(currentHealth, 23); EXPECT_EQ(currentHealth, 23);
@ -298,3 +324,208 @@ TEST_F(DestroyableTest, DestroyableComponentValiditiyTest) {
EXPECT_FALSE(destroyableComponent->IsFriend(enemyEntity)); EXPECT_FALSE(destroyableComponent->IsFriend(enemyEntity));
delete enemyEntity; delete enemyEntity;
} }
TEST_F(DestroyableTest, DestroyableComponentImmunityTest) {
// assert to show that they are empty
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
// set them all to true (count 1) and check
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, true, true, true, true, true, true, true, true, true);
ASSERT_TRUE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_TRUE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_TRUE(destroyableComponent->GetImmuneToKnockback());
ASSERT_TRUE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_TRUE(destroyableComponent->GetImmuneToSpeed());
ASSERT_TRUE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_TRUE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_TRUE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_TRUE(destroyableComponent->GetImmuneToPullToPoint());
// remove them to check that they get removed properly
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, true, true, true, true, true, true, true, true, true);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
// should not crash to remove them again
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, true, true, true, true, true, true, true, true, true);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
// just do one
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, true);
ASSERT_TRUE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
// now stack it to 2 on basic attack
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, true);
ASSERT_TRUE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
// remove one and still shoudl be true
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, true);
ASSERT_TRUE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
// go back to 0
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, true);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
// check individual ones now
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, true, false, false, false, false, false, false, false, false);
ASSERT_TRUE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, true, false, false, false, false, false, false, false, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, true, false, false, false, false, false, false, false);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_TRUE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, true, false, false, false, false, false, false, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, false, true, false, false, false, false, false, false);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_TRUE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, false, true, false, false, false, false, false, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, false, false, true, false, false, false, false, false);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_TRUE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, false, false, true, false, false, false, false, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, false, false, false, true, false, false, false, false);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_TRUE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, false, false, false, true, false, false, false, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, false, false, false, false, true, false, false, false);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_TRUE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, false, false, false, false, true, false, false, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, false, false, false, false, false, true, false, false);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_TRUE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, false, false, false, false, false, true, false, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, false, false, false, false, false, false, true, false);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_TRUE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, false, false, false, false, false, false, true, false);
destroyableComponent->SetStatusImmunity(eStateChangeType::PUSH, false, false, false, false, false, false, false, false, true);
ASSERT_FALSE(destroyableComponent->GetImmuneToBasicAttack());
ASSERT_FALSE(destroyableComponent->GetImmuneToDamageOverTime());
ASSERT_FALSE(destroyableComponent->GetImmuneToKnockback());
ASSERT_FALSE(destroyableComponent->GetImmuneToInterrupt());
ASSERT_FALSE(destroyableComponent->GetImmuneToSpeed());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationGain());
ASSERT_FALSE(destroyableComponent->GetImmuneToImaginationLoss());
ASSERT_FALSE(destroyableComponent->GetImmuneToQuickbuildInterrupt());
ASSERT_TRUE(destroyableComponent->GetImmuneToPullToPoint());
destroyableComponent->SetStatusImmunity(eStateChangeType::POP, false, false, false, false, false, false, false, false, true);
}