refactor: death, stun, buff and knockback game messages as structs

Converts the combat messages to NetGameMsgs in CombatMessages.{h,cpp}:
Die, Resurrect, SetResurrectRestoreValues, SetPlayerAllowedRespawn
(SendToClient, as before), Knockback, SetStunned, SetStunImmunity,
SetStatusImmunity, AddBuff, RemoveBuff, AddRunSpeedModifier,
RemoveRunSpeedModifier and DeactivateBubbleBuffFromServer, and the
received RequestDie, RequestSmashPlayer, RequestResurrect, Resurrect,
ActivateBubbleBuff and DeactivateBubbleBuff. Smash and UnSmash move
here from GameMessages.h (Smash's ghostCapacity is ghostOpacity, the
client's name) and gain a Deserialize.

The callers (DestroyableComponent, BuffComponent,
ControllablePhysicsComponent, QuickBuildComponent, RacingControl,
RailActivator and the scripts) build the structs. SendResurrect's
respawn timer moves to DestroyableComponent::Resurrect. The received
messages are registered in GameMessageHandler's map and their switch
cases are deleted, along with the unused HandleRequestDie overload and
the Send* functions nothing called (SendSmash, SendUnSmash, the run
speed modifiers, SendActivateBubbleBuffFromServer). Handler logic is
unchanged.

No wire change and no change in recipients. Verified byte for byte
against a frozen verbatim copy of the old functions over an input grid
(every optional field, bool patterns, empty and long strings), received
messages compared with the old handlers' read sequences and truncated
payloads rejected, hand computed golden bytes, round trips, and a
deliberate width mutation made the tests fail.

Known difference from the client, not changed here: DLU writes
SetStatusImmunity's nine flags in its own order; the client reads them
alphabetically (GameMessage::SetStatusImmunity::Serialize @ 00d8f140).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-27 00:01:18 -05:00
parent 27de0cf268
commit f7f5d304d0
38 changed files with 2002 additions and 808 deletions

View File

@@ -172,17 +172,6 @@ void GameMessages::SendPlayerReady(Entity* entity, const SystemAddress& sysAddr)
SEND_PACKET;
}
void GameMessages::SendPlayerAllowedRespawn(LWOOBJID entityID, bool doNotPromptRespawn, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entityID);
bitStream.Write(MessageType::Game::SET_PLAYER_ALLOWED_RESPAWN);
bitStream.Write(doNotPromptRespawn);
SEND_PACKET;
}
void GameMessages::SendInvalidZoneTransferList(Entity* entity, const SystemAddress& sysAddr, const std::u16string& feedbackURL, const std::u16string& invalidMapTransferList, bool feedbackOnExit, bool feedbackOnInvalidTransfer) {
CBITSTREAM;
CMSGHEADER;
@@ -208,28 +197,6 @@ void GameMessages::SendInvalidZoneTransferList(Entity* entity, const SystemAddre
SEND_PACKET;
}
void GameMessages::SendKnockback(const LWOOBJID& objectID, const LWOOBJID& caster, const LWOOBJID& originator, int knockBackTimeMS, const NiPoint3& vector) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectID);
bitStream.Write(MessageType::Game::KNOCKBACK);
bool casterFlag = caster != LWOOBJID_EMPTY;
bool originatorFlag = originator != LWOOBJID_EMPTY;
bool knockBackTimeMSFlag = knockBackTimeMS != 0;
bitStream.Write(casterFlag);
if (casterFlag) bitStream.Write(caster);
bitStream.Write(originatorFlag);
if (originatorFlag) bitStream.Write(originator);
bitStream.Write(knockBackTimeMSFlag);
if (knockBackTimeMSFlag) bitStream.Write(knockBackTimeMS);
bitStream.Write(vector);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendPlayerSetCameraCyclingMode(const LWOOBJID& objectID, const SystemAddress& sysAddr,
bool bAllowCyclingWhileDeadOnly, eCyclingMode cyclingMode) {
CBITSTREAM;
@@ -452,70 +419,6 @@ void GameMessages::SendTerminateInteraction(const LWOOBJID& objectID, eTerminate
SEND_PACKET_BROADCAST;
}
void GameMessages::SendDieNoImplCode(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(MessageType::Game::DIE);
bitStream.Write(bClientDeath);
bitStream.Write(bSpawnLoot);
bitStream.Write<uint32_t>(deathType.size());
bitStream.Write(deathType);
bitStream.Write(directionRelative_AngleXZ);
bitStream.Write(directionRelative_AngleY);
bitStream.Write(directionRelative_Force);
bitStream.Write(killType != eKillType::VIOLENT);
if (killType != eKillType::VIOLENT) bitStream.Write(killType);
bitStream.Write(killerID);
bitStream.Write(lootOwnerID != LWOOBJID_EMPTY);
if (lootOwnerID != LWOOBJID_EMPTY) {
bitStream.Write(lootOwnerID);
}
SEND_PACKET_BROADCAST;
}
void GameMessages::SendDie(Entity* entity, const LWOOBJID& killerID, const LWOOBJID& lootOwnerID, bool bDieAccepted, eKillType killType, std::u16string deathType, float directionRelative_AngleY, float directionRelative_AngleXZ, float directionRelative_Force, bool bClientDeath, bool bSpawnLoot, float coinSpawnTime) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(MessageType::Game::DIE);
bitStream.Write(bClientDeath);
bitStream.Write(bSpawnLoot);
//bitStream.Write(coinSpawnTime != -1.0f);
//if (coinSpawnTime != -1.0f) bitStream.Write(coinSpawnTime);
uint32_t deathTypeLength = deathType.size();
bitStream.Write(deathTypeLength);
for (uint32_t k = 0; k < deathTypeLength; k++) {
bitStream.Write<uint16_t>(deathType[k]);
}
bitStream.Write(directionRelative_AngleXZ);
bitStream.Write(directionRelative_AngleY);
bitStream.Write(directionRelative_Force);
bitStream.Write(killType != eKillType::VIOLENT);
if (killType != eKillType::VIOLENT) bitStream.Write(killType);
bitStream.Write(killerID);
bitStream.Write(lootOwnerID != LWOOBJID_EMPTY);
if (lootOwnerID != LWOOBJID_EMPTY) {
bitStream.Write(lootOwnerID);
}
SEND_PACKET_BROADCAST;
}
void GameMessages::SendSetJetPackMode(Entity* entity, bool use, bool bypassChecks, bool doHover, int effectID, float airspeed, float maxAirspeed, float verticalVelocity, int warningEffectID) {
/* historical jamesster jetpack values
if (bIsJamessterPhysics) {
@@ -553,44 +456,6 @@ void GameMessages::SendSetJetPackMode(Entity* entity, bool use, bool bypassCheck
SEND_PACKET_BROADCAST;
}
void GameMessages::SendResurrect(Entity* entity) {
// Restore the players health after the animation for respawning has finished.
// This is when the health appered back in live, not immediately upon requesting respawn
// Add a half second in case someone decides to cheat and move during the death animation
// and just make sure the client has time to be ready.
constexpr float respawnTime = 3.66700005531311f + 0.5f;
entity->AddCallbackTimer(respawnTime, [=]() {
GameMessages::PlayerResurrectionFinished msg;
entity->NotifyPlayerResurrectionFinished(msg);
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent != nullptr && entity->GetLOT() == 1) {
destroyableComponent->SetIsDead(false);
auto* levelComponent = entity->GetComponent<LevelProgressionComponent>();
if (levelComponent) {
int32_t healthToRestore = levelComponent->GetLevel() >= 45 ? 8 : 4;
if (healthToRestore > destroyableComponent->GetMaxHealth()) healthToRestore = destroyableComponent->GetMaxHealth();
destroyableComponent->SetHealth(healthToRestore);
int32_t imaginationToRestore = levelComponent->GetLevel() >= 45 ? 20 : 6;
if (imaginationToRestore > destroyableComponent->GetMaxImagination()) imaginationToRestore = destroyableComponent->GetMaxImagination();
destroyableComponent->SetImagination(imaginationToRestore);
}
}
});
CBITSTREAM;
CMSGHEADER;
bool bRezImmediately = false;
bitStream.Write(entity->GetObjectID());
bitStream.Write(MessageType::Game::RESURRECT);
bitStream.Write(bRezImmediately);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendSetNetworkScriptVar(Entity* entity, const SystemAddress& sysAddr, std::string data) {
CBITSTREAM;
CMSGHEADER;
@@ -1062,149 +927,6 @@ void GameMessages::SendLockNodeRotation(Entity* entity, std::string nodeName) {
SEND_PACKET_BROADCAST;
}
void GameMessages::SendSmash(Entity* entity, float force, float ghostOpacity, LWOOBJID killerID, bool ignoreObjectVisibility) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(MessageType::Game::SMASH);
bitStream.Write(ignoreObjectVisibility);
bitStream.Write(force);
bitStream.Write(ghostOpacity);
bitStream.Write(killerID);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendUnSmash(Entity* entity, LWOOBJID builderID, float duration) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(MessageType::Game::UN_SMASH);
bitStream.Write(builderID != LWOOBJID_EMPTY);
if (builderID != LWOOBJID_EMPTY) bitStream.Write(builderID);
bitStream.Write(duration != 3.0f);
if (duration != 3.0f) bitStream.Write(duration);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendSetStunned(LWOOBJID objectId, eStateChangeType stateChangeType, const SystemAddress& sysAddr,
LWOOBJID originator, bool bCantAttack, bool bCantEquip,
bool bCantInteract, bool bCantJump, bool bCantMove, bool bCantTurn,
bool bCantUseItem, bool bDontTerminateInteract, bool bIgnoreImmunity,
bool bCantAttackOutChangeWasApplied, bool bCantEquipOutChangeWasApplied,
bool bCantInteractOutChangeWasApplied, bool bCantJumpOutChangeWasApplied,
bool bCantMoveOutChangeWasApplied, bool bCantTurnOutChangeWasApplied,
bool bCantUseItemOutChangeWasApplied) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectId);
bitStream.Write(MessageType::Game::SET_STUNNED);
bitStream.Write(originator != LWOOBJID_EMPTY);
if (originator != LWOOBJID_EMPTY) bitStream.Write(originator);
bitStream.Write(stateChangeType);
bitStream.Write(bCantAttack);
bitStream.Write(bCantAttackOutChangeWasApplied);
bitStream.Write(bCantEquip);
bitStream.Write(bCantEquipOutChangeWasApplied);
bitStream.Write(bCantInteract);
bitStream.Write(bCantInteractOutChangeWasApplied);
bitStream.Write(bCantJump);
bitStream.Write(bCantJumpOutChangeWasApplied);
bitStream.Write(bCantMove);
bitStream.Write(bCantMoveOutChangeWasApplied);
bitStream.Write(bCantTurn);
bitStream.Write(bCantTurnOutChangeWasApplied);
bitStream.Write(bCantUseItem);
bitStream.Write(bCantUseItemOutChangeWasApplied);
bitStream.Write(bDontTerminateInteract);
bitStream.Write(bIgnoreImmunity);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
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(MessageType::Game::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(MessageType::Game::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) {
CBITSTREAM;
CMSGHEADER;
@@ -1220,37 +942,6 @@ void GameMessages::SendOrientToAngle(LWOOBJID objectId, bool bRelativeToCurrent,
}
void GameMessages::SendAddRunSpeedModifier(LWOOBJID objectId, LWOOBJID caster, uint32_t modifier, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectId);
bitStream.Write(MessageType::Game::ADD_RUN_SPEED_MODIFIER);
bitStream.Write(caster != LWOOBJID_EMPTY);
if (caster != LWOOBJID_EMPTY) bitStream.Write(caster);
bitStream.Write(modifier != 500);
if (modifier != 500) bitStream.Write(modifier);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
SEND_PACKET;
}
void GameMessages::SendRemoveRunSpeedModifier(LWOOBJID objectId, uint32_t modifier, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectId);
bitStream.Write(MessageType::Game::REMOVE_RUN_SPEED_MODIFIER);
bitStream.Write(modifier != 500);
if (modifier != 500) bitStream.Write(modifier);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
SEND_PACKET;
}
void GameMessages::SendNotifyObject(LWOOBJID objectId, LWOOBJID objIDSender, std::u16string name, const SystemAddress& sysAddr, int param1, int param2) {
CBITSTREAM;
CMSGHEADER;
@@ -1308,21 +999,6 @@ void GameMessages::SendTeamPickupItem(LWOOBJID objectId, LWOOBJID lootID, LWOOBJ
//Pets:
void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(MessageType::Game::REMOVE_BUFF);
bitStream.Write(false); // bFromRemoveBehavior but setting this to true makes the GM not do anything on the client?
bitStream.Write(fromUnEquip);
bitStream.Write(removeImmunity);
bitStream.Write(buffId);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendDisplayZoneSummary(LWOOBJID objectId, const SystemAddress& sysAddr, bool isPropertyMap, bool isZoneStart, LWOOBJID sender) {
CBITSTREAM;
CMSGHEADER;
@@ -1426,74 +1102,6 @@ void GameMessages::HandleAcknowledgePossession(RakNet::BitStream& inStream, Enti
void GameMessages::HandleRequestDie(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
bool bClientDeath;
bool bSpawnLoot;
std::u16string deathType;
float directionRelativeAngleXZ;
float directionRelativeAngleY;
float directionRelativeForce;
eKillType killType = eKillType::VIOLENT;
LWOOBJID killerID;
LWOOBJID lootOwnerID = LWOOBJID_EMPTY;
bClientDeath = inStream.ReadBit();
bSpawnLoot = inStream.ReadBit();
uint32_t deathTypeLength = 0;
inStream.Read(deathTypeLength);
for (size_t i = 0; i < deathTypeLength; i++) {
char16_t character;
inStream.Read(character);
deathType.push_back(character);
}
inStream.Read(directionRelativeAngleXZ);
inStream.Read(directionRelativeAngleY);
inStream.Read(directionRelativeForce);
if (inStream.ReadBit()) {
inStream.Read(killType);
}
inStream.Read(killerID);
if (inStream.ReadBit()) {
inStream.Read(lootOwnerID);
}
auto* zoneController = Game::zoneManager->GetZoneControlObject();
auto* racingControlComponent = zoneController->GetComponent<RacingControlComponent>();
LOG("Got die request: %i", entity->GetLOT());
if (racingControlComponent != nullptr) {
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
if (possessableComponent != nullptr) {
entity = Game::entityManager->GetEntity(possessableComponent->GetPossessor());
if (entity == nullptr) {
return;
}
}
racingControlComponent->OnRequestDie(entity);
} else {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->Smash(killerID, killType, deathType);
}
}
void GameMessages::SendUpdateReputation(const LWOOBJID objectId, const int64_t reputation, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
@@ -1506,71 +1114,6 @@ void GameMessages::SendUpdateReputation(const LWOOBJID objectId, const int64_t r
SEND_PACKET;
}
void GameMessages::SendSetResurrectRestoreValues(Entity* targetEntity, int32_t armorRestore, int32_t healthRestore, int32_t imaginationRestore) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(targetEntity->GetObjectID());
bitStream.Write(MessageType::Game::SET_RESURRECT_RESTORE_VALUES);
bitStream.Write(armorRestore != -1);
if (armorRestore != -1) bitStream.Write(armorRestore);
bitStream.Write(healthRestore != -1);
if (healthRestore != -1) bitStream.Write(healthRestore);
bitStream.Write(imaginationRestore != -1);
if (imaginationRestore != -1) bitStream.Write(imaginationRestore);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendAddBuff(LWOOBJID& objectID, const LWOOBJID& casterID, uint32_t buffID, uint32_t msDuration,
bool addImmunity, bool cancelOnDamaged, bool cancelOnDeath, bool cancelOnLogout,
bool cancelOnRemoveBuff, bool cancelOnUi, bool cancelOnUnequip, bool cancelOnZone, bool addedByTeammate, bool applyOnTeammates,
const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectID);
bitStream.Write(MessageType::Game::ADD_BUFF);
bitStream.Write(addedByTeammate); // Added by teammate
bitStream.Write(applyOnTeammates); // Apply on teammates
bitStream.Write(cancelOnDamaged);
bitStream.Write(cancelOnDeath);
bitStream.Write(cancelOnLogout);
bitStream.Write(false); // Cancel on move
bitStream.Write(cancelOnRemoveBuff);
bitStream.Write(cancelOnUi);
bitStream.Write(cancelOnUnequip);
bitStream.Write(cancelOnZone);
bitStream.Write(false); // Ignore immunities
bitStream.Write(addImmunity);
bitStream.Write(false); // Use ref count
bitStream.Write(casterID != LWOOBJID_EMPTY);
if (casterID != LWOOBJID_EMPTY) bitStream.Write(casterID);
bitStream.Write(buffID);
bitStream.Write(msDuration != 0);
if (msDuration != 0) bitStream.Write(msDuration);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
SEND_PACKET;
}
// NT
//-----------------------------------------------------------------------------------------------------------------------------------------------
@@ -1800,45 +1343,6 @@ void GameMessages::HandlePickupCurrency(RakNet::BitStream& inStream, Entity* ent
}
}
void GameMessages::HandleRequestDie(RakNet::BitStream& inStream, Entity* entity) {
LWOOBJID killerID;
LWOOBJID lootOwnerID;
bool bDieAccepted = false;
eKillType killType;
std::u16string deathType;
float directionRelative_AngleY;
float directionRelative_AngleXZ;
float directionRelative_Force;
bool bClientDeath = false;
bool bSpawnLoot = true;
float coinSpawnTime = -1.0f;
inStream.Read(bClientDeath);
inStream.Read(bDieAccepted);
inStream.Read(bSpawnLoot);
bool coinSpawnTimeIsDefault{};
inStream.Read(coinSpawnTimeIsDefault);
if (coinSpawnTimeIsDefault != 0) inStream.Read(coinSpawnTime);
/*uint32_t deathTypeLength = deathType.size();
inStream.Read(deathTypeLength);
for (uint32_t k = 0; k < deathTypeLength; k++) {
inStream.Read<uint16_t>(deathType[k]);
}*/
inStream.Read(directionRelative_AngleXZ);
inStream.Read(directionRelative_AngleY);
inStream.Read(directionRelative_Force);
bool killTypeIsDefault{};
inStream.Read(killTypeIsDefault);
if (killTypeIsDefault != 0) inStream.Read(killType);
inStream.Read(lootOwnerID);
inStream.Read(killerID);
}
void GameMessages::SendSetGravityScale(const LWOOBJID& target, const float effectScale, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
@@ -1851,22 +1355,6 @@ void GameMessages::SendSetGravityScale(const LWOOBJID& target, const float effec
SEND_PACKET;
}
void GameMessages::HandleResurrect(RakNet::BitStream& inStream, Entity* entity) {
bool immediate = inStream.ReadBit();
Entity* zoneControl = Game::entityManager->GetZoneControlEntity();
if (zoneControl) {
zoneControl->GetScript()->OnPlayerResurrected(zoneControl, entity);
}
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
for (Entity* scriptEntity : scriptedActs) {
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
scriptEntity->GetScript()->OnPlayerResurrected(scriptEntity, entity);
}
}
}
void GameMessages::HandleMatchRequest(RakNet::BitStream& inStream, Entity* entity) {
LWOOBJID activator;
uint32_t playerChoicesLen;
@@ -2055,47 +1543,6 @@ void GameMessages::HandleUpdatePlayerStatistic(RakNet::BitStream& inStream, Enti
}
}
void GameMessages::HandleDeactivateBubbleBuff(RakNet::BitStream& inStream, Entity* entity) {
auto controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>();
if (controllablePhysicsComponent) controllablePhysicsComponent->DeactivateBubbleBuff();
GameMessages::SendDeactivateBubbleBuffFromServer(entity->GetObjectID(), entity->GetSystemAddress());
}
void GameMessages::HandleActivateBubbleBuff(RakNet::BitStream& inStream, Entity* entity) {
bool specialAnimations;
if (!inStream.Read(specialAnimations)) return;
std::u16string type = GeneralUtils::ReadWString(inStream);
auto bubbleType = eBubbleType::DEFAULT;
if (type == u"skunk") bubbleType = eBubbleType::SKUNK;
else if (type == u"energy") bubbleType = eBubbleType::ENERGY;
auto controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>();
if (controllablePhysicsComponent) controllablePhysicsComponent->ActivateBubbleBuff(bubbleType, specialAnimations);
}
void GameMessages::SendActivateBubbleBuffFromServer(LWOOBJID objectId, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectId);
bitStream.Write(MessageType::Game::ACTIVATE_BUBBLE_BUFF_FROM_SERVER);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
SEND_PACKET;
}
void GameMessages::SendDeactivateBubbleBuffFromServer(LWOOBJID objectId, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(objectId);
bitStream.Write(MessageType::Game::DEACTIVATE_BUBBLE_BUFF_FROM_SERVER);
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
SEND_PACKET;
}
void GameMessages::HandleZoneSummaryDismissed(RakNet::BitStream& inStream, Entity* entity) {
LWOOBJID player_id;
inStream.Read<LWOOBJID>(player_id);
@@ -2292,24 +1739,6 @@ namespace GameMessages {
missionComponent->Progress(eMissionTaskType::INTERACT, interactedObject->GetLOT(), interactedObject->GetObjectID());
}
void Smash::Serialize(RakNet::BitStream& stream) const {
stream.Write(bIgnoreObjectVisibility);
stream.Write(force);
stream.Write(ghostCapacity);
stream.Write(killerID);
}
void UnSmash::Serialize(RakNet::BitStream& stream) const {
// Both fields are optional with a default, like the client's GameMessage::UnSmash::Serialize.
BitStreamUtils::WriteOptional(stream, builderID, LWOOBJID_EMPTY);
BitStreamUtils::WriteOptional(stream, duration, 3.0f);
}
bool UnSmash::Deserialize(RakNet::BitStream& stream) {
VALIDATE_READ(BitStreamUtils::ReadOptional(stream, builderID, LWOOBJID_EMPTY));
VALIDATE_READ(BitStreamUtils::ReadOptional(stream, duration, 3.0f));
return true;
}
void PlayBehaviorSound::Serialize(RakNet::BitStream& stream) const {
stream.Write(soundID != -1);
if (soundID != -1) stream.Write(soundID);