feat: make gm registration simpler and safer (#1932)

* gm registration re-work

* fix errors

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* remove duplicate message

* Remove duplicate function

* add null check

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
David Markowitz
2026-05-19 11:42:56 -07:00
committed by GitHub
parent f3a5add038
commit 4ef9f43266
40 changed files with 232 additions and 186 deletions

View File

@@ -198,11 +198,12 @@ Entity::~Entity() {
}
void Entity::Initialize() {
RegisterMsg<GameMessages::RequestServerObjectInfo>(this, &Entity::MsgRequestServerObjectInfo);
RegisterMsg<GameMessages::DropClientLoot>(this, &Entity::MsgDropClientLoot);
RegisterMsg<GameMessages::GetFactionTokenType>(this, &Entity::MsgGetFactionTokenType);
RegisterMsg<GameMessages::PickupItem>(this, &Entity::MsgPickupItem);
RegisterMsg<GameMessages::ChildRemoved>(this, &Entity::MsgChildRemoved);
RegisterMsg(&Entity::MsgRequestServerObjectInfo);
RegisterMsg(&Entity::MsgDropClientLoot);
RegisterMsg(&Entity::MsgGetFactionTokenType);
RegisterMsg(&Entity::MsgPickupItem);
RegisterMsg(&Entity::MsgChildRemoved);
RegisterMsg(&Entity::MsgGetFlag);
/**
* Setup trigger
*/
@@ -2251,8 +2252,7 @@ void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameM
m_MsgHandlers.emplace(msgId, handler);
}
bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
auto& requestInfo = static_cast<GameMessages::RequestServerObjectInfo&>(msg);
bool Entity::MsgRequestServerObjectInfo(GameMessages::RequestServerObjectInfo& requestInfo) {
AMFArrayValue response;
response.Insert("visible", true);
response.Insert("objectID", std::to_string(m_ObjectID));
@@ -2288,9 +2288,7 @@ bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
return true;
}
bool Entity::MsgDropClientLoot(GameMessages::GameMsg& msg) {
auto& dropLootMsg = static_cast<GameMessages::DropClientLoot&>(msg);
bool Entity::MsgDropClientLoot(GameMessages::DropClientLoot& dropLootMsg) {
if (dropLootMsg.item != LOT_NULL && dropLootMsg.item != 0) {
Loot::Info info{
.id = dropLootMsg.lootID,
@@ -2307,13 +2305,11 @@ bool Entity::MsgDropClientLoot(GameMessages::GameMsg& msg) {
return true;
}
bool Entity::MsgGetFlag(GameMessages::GameMsg& msg) {
auto& flagMsg = static_cast<GameMessages::GetFlag&>(msg);
bool Entity::MsgGetFlag(GameMessages::GetFlag& flagMsg) {
if (m_Character) flagMsg.flag = m_Character->GetPlayerFlag(flagMsg.flagID);
return true;
}
bool Entity::MsgGetFactionTokenType(GameMessages::GameMsg& msg) {
auto& tokenMsg = static_cast<GameMessages::GetFactionTokenType&>(msg);
bool Entity::MsgGetFactionTokenType(GameMessages::GetFactionTokenType& tokenMsg) {
GameMessages::GetFlag getFlagMsg{};
getFlagMsg.flagID = ePlayerFlag::ASSEMBLY_FACTION;
@@ -2336,8 +2332,7 @@ bool Entity::MsgGetFactionTokenType(GameMessages::GameMsg& msg) {
return tokenMsg.tokenType != LOT_NULL;
}
bool Entity::MsgPickupItem(GameMessages::GameMsg& msg) {
auto& pickupItemMsg = static_cast<GameMessages::PickupItem&>(msg);
bool Entity::MsgPickupItem(GameMessages::PickupItem& pickupItemMsg) {
if (GetObjectID() == pickupItemMsg.lootOwnerID) {
PickupItem(pickupItemMsg.lootID);
} else {
@@ -2358,7 +2353,7 @@ bool Entity::MsgPickupItem(GameMessages::GameMsg& msg) {
return true;
}
bool Entity::MsgChildRemoved(GameMessages::GameMsg& msg) {
GetScript()->OnChildRemoved(*this, static_cast<GameMessages::ChildRemoved&>(msg));
bool Entity::MsgChildRemoved(GameMessages::ChildRemoved& msg) {
GetScript()->OnChildRemoved(*this, msg);
return true;
}

View File

@@ -20,6 +20,12 @@ namespace GameMessages {
struct ShootingGalleryFire;
struct ChildLoaded;
struct PlayerResurrectionFinished;
struct RequestServerObjectInfo;
struct DropClientLoot;
struct GetFlag;
struct GetFactionTokenType;
struct PickupItem;
struct ChildRemoved;
};
namespace MessageType {
@@ -175,12 +181,12 @@ public:
void AddComponent(eReplicaComponentType componentId, Component* component);
bool MsgRequestServerObjectInfo(GameMessages::GameMsg& msg);
bool MsgDropClientLoot(GameMessages::GameMsg& msg);
bool MsgGetFlag(GameMessages::GameMsg& msg);
bool MsgGetFactionTokenType(GameMessages::GameMsg& msg);
bool MsgPickupItem(GameMessages::GameMsg& msg);
bool MsgChildRemoved(GameMessages::GameMsg& msg);
bool MsgRequestServerObjectInfo(GameMessages::RequestServerObjectInfo& msg);
bool MsgDropClientLoot(GameMessages::DropClientLoot& msg);
bool MsgGetFlag(GameMessages::GetFlag& msg);
bool MsgGetFactionTokenType(GameMessages::GetFactionTokenType& msg);
bool MsgPickupItem(GameMessages::PickupItem& msg);
bool MsgChildRemoved(GameMessages::ChildRemoved& msg);
// This is expceted to never return nullptr, an assert checks this.
CppScripts::Script* const GetScript() const;
@@ -343,14 +349,19 @@ public:
bool HandleMsg(GameMessages::GameMsg& msg) const;
void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
}
template<typename T>
inline void RegisterMsg(auto* self, const auto handler) {
T msg;
RegisterMsg(msg.msgId, self, handler);
// Provided a function that has a derived GameMessage as its only argument and returns a boolean,
// this will register it as a handler for that message type. Casting is done automatically to the type
// of the message in the first argument. This object is expected to exist as long as the handler can be called.
template<typename DerivedGameMsg>
inline void RegisterMsg(bool (Entity::* handler)(DerivedGameMsg&)) {
static_assert(std::is_base_of_v<GameMessages::GameMsg, DerivedGameMsg>, "DerivedGameMsg must inherit from GameMsg");
const auto boundFunction = std::bind(handler, this, std::placeholders::_1);
// This is the actual function that will be registered, which casts the base GameMsg to the derived type
const auto castWrapper = [boundFunction](GameMessages::GameMsg& msg) {
return boundFunction(static_cast<DerivedGameMsg&>(msg));
};
DerivedGameMsg msg;
RegisterMsg(msg.msgId, castWrapper);
}
/**

View File

@@ -31,8 +31,7 @@
#include "Amf3.h"
ActivityComponent::ActivityComponent(Entity* parent, int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
RegisterMsg<GetObjectReportInfo>(this, &ActivityComponent::OnGetObjectReportInfo);
RegisterMsg(&ActivityComponent::OnGetObjectReportInfo);
/*
* This is precisely what the client does functionally
* Use the component id as the default activity id and load its data from the database
@@ -590,9 +589,7 @@ Entity* LobbyPlayer::GetEntity() const {
return Game::entityManager->GetEntity(entityID);
}
bool ActivityComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool ActivityComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& activityInfo = reportInfo.info->PushDebug("Activity");
auto& instances = activityInfo.PushDebug("Instances: " + std::to_string(m_Instances.size()));

View File

@@ -347,7 +347,7 @@ public:
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& msg);
/**
* The database information for this activity
*/

View File

@@ -30,10 +30,7 @@
#include "Amf3.h"
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
{
using namespace GameMessages;
RegisterMsg<GetObjectReportInfo>(this, &BaseCombatAIComponent::MsgGetObjectReportInfo);
}
RegisterMsg(&BaseCombatAIComponent::MsgGetObjectReportInfo);
m_Target = LWOOBJID_EMPTY;
m_DirtyStateOrTarget = true;
m_State = AiState::spawn;
@@ -845,10 +842,9 @@ void BaseCombatAIComponent::IgnoreThreat(const LWOOBJID threat, const float valu
m_Target = LWOOBJID_EMPTY;
}
bool BaseCombatAIComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
bool BaseCombatAIComponent::MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
using enum AiState;
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
auto& cmptType = reportMsg.info->PushDebug("Base Combat AI");
auto& cmptType = reportInfo.info->PushDebug("Base Combat AI");
cmptType.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
auto& targetInfo = cmptType.PushDebug("Current Target Info");
targetInfo.PushDebug<AMFStringValue>("Current Target ID") = std::to_string(m_Target);

View File

@@ -234,7 +234,7 @@ public:
// Ignore a threat for a certain amount of time
void IgnoreThreat(const LWOOBJID target, const float time);
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
bool MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
private:
/**

View File

@@ -31,10 +31,7 @@ BouncerComponent::BouncerComponent(Entity* parent, const int32_t componentID) :
LookupPetSwitch();
}
{
using namespace GameMessages;
RegisterMsg<GetObjectReportInfo>(this, &BouncerComponent::MsgGetObjectReportInfo);
}
RegisterMsg(&BouncerComponent::MsgGetObjectReportInfo);
}
BouncerComponent::~BouncerComponent() {
@@ -113,9 +110,8 @@ void BouncerComponent::LookupPetSwitch() {
}
}
bool BouncerComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
auto& cmptType = reportMsg.info->PushDebug("Bouncer");
bool BouncerComponent::MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& cmptType = reportInfo.info->PushDebug("Bouncer");
cmptType.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
auto& destPos = cmptType.PushDebug("Destination Position");
if (m_Destination != NiPoint3Constant::ZERO) {

View File

@@ -51,7 +51,7 @@ public:
*/
void LookupPetSwitch();
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
bool MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
private:
/**

View File

@@ -49,11 +49,10 @@ CharacterComponent::CharacterComponent(Entity* parent, const int32_t componentID
m_LastUpdateTimestamp = std::time(nullptr);
m_SystemAddress = systemAddress;
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &CharacterComponent::OnGetObjectReportInfo);
RegisterMsg(&CharacterComponent::OnGetObjectReportInfo);
}
bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& cmptType = reportInfo.info->PushDebug("Character");

View File

@@ -17,6 +17,10 @@ enum class eGameActivity : uint32_t;
class Item;
namespace GameMessages {
struct GetObjectReportInfo;
}
/**
* The statistics that can be achieved per zone
*/
@@ -331,7 +335,7 @@ public:
void LoadVisitedLevelsXml(const tinyxml2::XMLElement& doc);
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
/**
* The map of active venture vision effects

View File

@@ -6,16 +6,14 @@
CollectibleComponent::CollectibleComponent(Entity* parentEntity, const int32_t componentID, const int32_t collectibleId) :
Component(parentEntity, componentID), m_CollectibleId(collectibleId) {
using namespace GameMessages;
RegisterMsg<GetObjectReportInfo>(this, &CollectibleComponent::MsgGetObjectReportInfo);
RegisterMsg(&CollectibleComponent::MsgGetObjectReportInfo);
}
void CollectibleComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
outBitStream.Write(GetCollectibleId());
}
bool CollectibleComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool CollectibleComponent::MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportMsg) {
auto& cmptType = reportMsg.info->PushDebug("Collectible");
auto collectibleID = static_cast<uint32_t>(m_CollectibleId) + static_cast<uint32_t>(Game::server->GetZoneID() << 8);

View File

@@ -12,7 +12,7 @@ public:
int16_t GetCollectibleId() const { return m_CollectibleId; }
void Serialize(RakNet::BitStream& outBitStream, bool isConstruction) override;
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
bool MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
private:
int16_t m_CollectibleId = 0;
};

View File

@@ -55,17 +55,18 @@ public:
virtual void LoadFromXml(const tinyxml2::XMLDocument& doc) {}
virtual void Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {}
protected:
template<typename GameObjClass, typename DerivedMsg>
inline void RegisterMsg(bool (GameObjClass::*handler)(DerivedMsg&)) {
static_assert(std::is_base_of_v<GameMessages::GameMsg, DerivedMsg>, "DerivedMsg must inherit from GameMsg");
static_assert(std::is_base_of_v<Component, GameObjClass>, "GameObjClass must inherit from Component");
const auto handlerBound = std::bind(handler, static_cast<GameObjClass*>(this), std::placeholders::_1);
const auto castWrapper = [handlerBound](GameMessages::GameMsg& msg) {
return handlerBound(static_cast<DerivedMsg&>(msg));
};
inline void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
m_Parent->RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
}
template<typename T>
inline void RegisterMsg(auto* self, const auto handler) {
T msg;
RegisterMsg(msg.msgId, self, handler);
DerivedMsg msg;
m_Parent->RegisterMsg(msg.msgId, castWrapper);
}
/**

View File

@@ -18,7 +18,7 @@
#include "Amf3.h"
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, const int32_t componentID) : PhysicsComponent(entity, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &ControllablePhysicsComponent::OnGetObjectReportInfo);
RegisterMsg(&ControllablePhysicsComponent::OnGetObjectReportInfo);
m_Velocity = {};
m_AngularVelocity = {};
@@ -359,9 +359,8 @@ void ControllablePhysicsComponent::SetStunImmunity(
);
}
bool ControllablePhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
PhysicsComponent::OnGetObjectReportInfo(msg);
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool ControllablePhysicsComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
PhysicsComponent::OnGetObjectReportInfo(reportInfo);
auto& info = reportInfo.subCategory->PushDebug("Controllable Info");
auto& vel = info.PushDebug("Velocity");

View File

@@ -284,7 +284,7 @@ public:
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
/**
* The entity that owns this component
*/

View File

@@ -48,7 +48,6 @@ Implementation<bool, const Entity*> DestroyableComponent::IsEnemyImplentation;
Implementation<bool, const Entity*> DestroyableComponent::IsFriendImplentation;
DestroyableComponent::DestroyableComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
m_iArmor = 0;
m_fMaxArmor = 0.0f;
m_iImagination = 0;
@@ -86,9 +85,9 @@ DestroyableComponent::DestroyableComponent(Entity* parent, const int32_t compone
m_DamageCooldownTimer = 0.0f;
RegisterMsg<GetObjectReportInfo>(this, &DestroyableComponent::OnGetObjectReportInfo);
RegisterMsg<GameMessages::SetFaction>(this, &DestroyableComponent::OnSetFaction);
RegisterMsg<GameMessages::IsDead>(this, &DestroyableComponent::OnIsDead);
RegisterMsg(&DestroyableComponent::OnGetObjectReportInfo);
RegisterMsg(&DestroyableComponent::OnSetFaction);
RegisterMsg(&DestroyableComponent::OnIsDead);
}
DestroyableComponent::~DestroyableComponent() {
@@ -1061,8 +1060,7 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
}
}
bool DestroyableComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool DestroyableComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& destroyableInfo = reportInfo.info->PushDebug("Destroyable");
destroyableInfo.PushDebug<AMFIntValue>("DestructibleComponent DB Table Template ID") = m_ComponentID;
@@ -1184,16 +1182,14 @@ bool DestroyableComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
return true;
}
bool DestroyableComponent::OnSetFaction(GameMessages::GameMsg& msg) {
auto& modifyFaction = static_cast<GameMessages::SetFaction&>(msg);
bool DestroyableComponent::OnSetFaction(GameMessages::SetFaction& setFaction) {
m_DirtyHealth = true;
Game::entityManager->SerializeEntity(m_Parent);
SetFaction(modifyFaction.factionID, modifyFaction.bIgnoreChecks);
SetFaction(setFaction.factionID, setFaction.bIgnoreChecks);
return true;
}
bool DestroyableComponent::OnIsDead(GameMessages::GameMsg& msg) {
auto& isDeadMsg = static_cast<GameMessages::IsDead&>(msg);
isDeadMsg.bDead = m_IsDead || (GetHealth() == 0 && GetArmor() == 0);
bool DestroyableComponent::OnIsDead(GameMessages::IsDead& isDead) {
isDead.bDead = m_IsDead || (GetHealth() == 0 && GetArmor() == 0);
return true;
}

View File

@@ -11,6 +11,8 @@
namespace GameMessages {
struct GetObjectReportInfo;
struct SetFaction;
struct IsDead;
};
namespace CppScripts {
@@ -470,9 +472,9 @@ public:
// handle hardcode mode drops
void DoHardcoreModeDrops(const LWOOBJID source);
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnSetFaction(GameMessages::GameMsg& msg);
bool OnIsDead(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
bool OnSetFaction(GameMessages::SetFaction& setFaction);
bool OnIsDead(GameMessages::IsDead& isDead);
void SetIsDead(const bool value) { m_IsDead = value; }

View File

@@ -13,9 +13,9 @@ GhostComponent::GhostComponent(Entity* parent, const int32_t componentID) : Comp
m_GhostOverridePoint = NiPoint3Constant::ZERO;
m_GhostOverride = false;
RegisterMsg<GameMessages::ToggleGMInvis>(this, &GhostComponent::OnToggleGMInvis);
RegisterMsg<GameMessages::GetGMInvis>(this, &GhostComponent::OnGetGMInvis);
RegisterMsg<GameMessages::GetObjectReportInfo>(this, &GhostComponent::MsgGetObjectReportInfo);
RegisterMsg(&GhostComponent::OnToggleGMInvis);
RegisterMsg(&GhostComponent::OnGetGMInvis);
RegisterMsg(&GhostComponent::MsgGetObjectReportInfo);
}
GhostComponent::~GhostComponent() {
@@ -88,15 +88,17 @@ void GhostComponent::GhostEntity(LWOOBJID id) {
m_ObservedEntities.erase(id);
}
bool GhostComponent::OnToggleGMInvis(GameMessages::GameMsg& msg) {
// TODO: disabled for now while bugs are fixed
return false;
auto& gmInvisMsg = static_cast<GameMessages::ToggleGMInvis&>(msg);
bool GhostComponent::OnToggleGMInvis(GameMessages::ToggleGMInvis& gmInvisMsg) {
gmInvisMsg.bStateOut = !m_IsGMInvisible;
m_IsGMInvisible = !m_IsGMInvisible;
LOG_DEBUG("GM Invisibility toggled to: %s", m_IsGMInvisible ? "true" : "false");
gmInvisMsg.Send(UNASSIGNED_SYSTEM_ADDRESS);
auto* thisUser = UserManager::Instance()->GetUser(m_Parent->GetSystemAddress());
if (!thisUser) {
LOG("Unable to find user for entity %llu when toggling GM invisibility!", m_Parent->GetObjectID());
return false;
}
for (const auto& player : PlayerManager::GetAllPlayers()) {
if (!player || player->GetObjectID() == m_Parent->GetObjectID()) continue;
auto* toUser = UserManager::Instance()->GetUser(player->GetSystemAddress());
@@ -117,9 +119,8 @@ bool GhostComponent::OnToggleGMInvis(GameMessages::GameMsg& msg) {
return true;
}
bool GhostComponent::OnGetGMInvis(GameMessages::GameMsg& msg) {
bool GhostComponent::OnGetGMInvis(GameMessages::GetGMInvis& gmInvisMsg) {
LOG_DEBUG("GM Invisibility requested: %s", m_IsGMInvisible ? "true" : "false");
auto& gmInvisMsg = static_cast<GameMessages::GetGMInvis&>(msg);
// TODO: disabled for now while bugs are fixed
// gmInvisMsg.bGMInvis = m_IsGMInvisible;
// return gmInvisMsg.bGMInvis;
@@ -127,8 +128,7 @@ bool GhostComponent::OnGetGMInvis(GameMessages::GameMsg& msg) {
return false;
}
bool GhostComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool GhostComponent::MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportMsg) {
auto& cmptType = reportMsg.info->PushDebug("Ghost");
cmptType.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
cmptType.PushDebug<AMFBoolValue>("Is GM Invis") = false;

View File

@@ -45,11 +45,11 @@ public:
void GhostEntity(const LWOOBJID id);
bool OnToggleGMInvis(GameMessages::GameMsg& msg);
bool OnToggleGMInvis(GameMessages::ToggleGMInvis& msg);
bool OnGetGMInvis(GameMessages::GameMsg& msg);
bool OnGetGMInvis(GameMessages::GetGMInvis& msg);
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
bool MsgGetObjectReportInfo(GameMessages::GetObjectReportInfo& msg);
private:

View File

@@ -3,7 +3,7 @@
#include "Amf3.h"
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &HavokVehiclePhysicsComponent::OnGetObjectReportInfo);
RegisterMsg(&HavokVehiclePhysicsComponent::OnGetObjectReportInfo);
m_Velocity = NiPoint3Constant::ZERO;
m_AngularVelocity = NiPoint3Constant::ZERO;
@@ -102,9 +102,8 @@ void HavokVehiclePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
outBitStream.Write0();
}
bool HavokVehiclePhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
PhysicsComponent::OnGetObjectReportInfo(msg);
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool HavokVehiclePhysicsComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
PhysicsComponent::OnGetObjectReportInfo(reportInfo);
if (!reportInfo.subCategory) {
return false;
}

View File

@@ -68,7 +68,7 @@ public:
void SetRemoteInputInfo(const RemoteInputInfo&);
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
NiPoint3 m_Velocity;
NiPoint3 m_AngularVelocity;

View File

@@ -44,8 +44,7 @@
#include <ranges>
InventoryComponent::InventoryComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
RegisterMsg<GetObjectReportInfo>(this, &InventoryComponent::OnGetObjectReportInfo);
RegisterMsg(&InventoryComponent::OnGetObjectReportInfo);
this->m_Dirty = true;
this->m_Equipped = {};
this->m_Pushed = {};
@@ -1847,9 +1846,8 @@ std::string DebugInvToString(const eInventoryType inv, bool verbose) {
return "";
}
bool InventoryComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& report = static_cast<GameMessages::GetObjectReportInfo&>(msg);
auto& cmpt = report.info->PushDebug("Inventory");
bool InventoryComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& cmpt = reportInfo.info->PushDebug("Inventory");
cmpt.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
uint32_t numItems = 0;
for (auto* inventory : m_Inventories | std::views::values) numItems += inventory->GetItems().size();
@@ -1859,7 +1857,7 @@ bool InventoryComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
for (const auto& [id, inventoryMut] : m_Inventories) {
if (!inventoryMut) continue;
const auto* const inventory = inventoryMut;
auto& curInv = itemsInBags.PushDebug(DebugInvToString(id, report.bVerbose) + " - " + std::to_string(id));
auto& curInv = itemsInBags.PushDebug(DebugInvToString(id, reportInfo.bVerbose) + " - " + std::to_string(id));
for (uint32_t i = 0; i < inventory->GetSize(); i++) {
const auto* const item = inventory->FindItemBySlot(i);
if (!item) continue;

View File

@@ -31,6 +31,10 @@ typedef std::map<std::string, EquippedItem> EquipmentMap;
enum class eItemType : int32_t;
namespace GameMessages {
struct GetObjectReportInfo;
}
/**
* Handles the inventory of entity, including the items they possess and have equipped. An entity can have inventories
* of different types, each type representing a different group of items, see `eInventoryType` for a list of
@@ -411,7 +415,7 @@ public:
// Used to migrate a character version, no need to call outside of that context
void RegenerateItemIDs();
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
~InventoryComponent() override;

View File

@@ -28,12 +28,11 @@ std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> MissionComponent:
//! Initializer
MissionComponent::MissionComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
m_LastUsedMissionOrderUID = Game::zoneManager->GetUniqueMissionIdStartingValue();
RegisterMsg<GetObjectReportInfo>(this, &MissionComponent::OnGetObjectReportInfo);
RegisterMsg<GameMessages::GetMissionState>(this, &MissionComponent::OnGetMissionState);
RegisterMsg<GameMessages::MissionNeedsLot>(this, &MissionComponent::OnMissionNeedsLot);
RegisterMsg(&MissionComponent::OnGetObjectReportInfo);
RegisterMsg(&MissionComponent::OnGetMissionState);
RegisterMsg(&MissionComponent::OnMissionNeedsLot);
}
//! Destructor
@@ -649,9 +648,8 @@ void PushMissions(const std::map<uint32_t, Mission*>& missions, AMFArrayValue& V
}
}
bool MissionComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
auto& missionInfo = reportMsg.info->PushDebug("Mission (Laggy)");
bool MissionComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& missionInfo = reportInfo.info->PushDebug("Mission (Laggy)");
missionInfo.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
// Sort the missions so they are easier to parse and present to the end user
std::map<uint32_t, Mission*> achievements;
@@ -667,28 +665,26 @@ bool MissionComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
// None of these should be empty, but if they are dont print the field
if (!achievements.empty() || !missions.empty()) {
auto& incompleteMissions = missionInfo.PushDebug("Incomplete Missions");
PushMissions(achievements, incompleteMissions, reportMsg.bVerbose);
PushMissions(missions, incompleteMissions, reportMsg.bVerbose);
PushMissions(achievements, incompleteMissions, reportInfo.bVerbose);
PushMissions(missions, incompleteMissions, reportInfo.bVerbose);
}
if (!doneMissions.empty()) {
auto& completeMissions = missionInfo.PushDebug("Completed Missions");
PushMissions(doneMissions, completeMissions, reportMsg.bVerbose);
PushMissions(doneMissions, completeMissions, reportInfo.bVerbose);
}
return true;
}
bool MissionComponent::OnGetMissionState(GameMessages::GameMsg& msg) {
auto misState = static_cast<GameMessages::GetMissionState&>(msg);
misState.missionState = GetMissionState(misState.missionID);
bool MissionComponent::OnGetMissionState(GameMessages::GetMissionState& getMissionState) {
getMissionState.missionState = GetMissionState(getMissionState.missionID);
return true;
}
bool MissionComponent::OnMissionNeedsLot(GameMessages::GameMsg& msg) {
const auto& needMsg = static_cast<GameMessages::MissionNeedsLot&>(msg);
return RequiresItem(needMsg.item);
bool MissionComponent::OnMissionNeedsLot(GameMessages::MissionNeedsLot& missionNeedsLot) {
return RequiresItem(missionNeedsLot.item);
}
void MissionComponent::FixRacingMetaMissions() {

View File

@@ -172,9 +172,9 @@ public:
void FixRacingMetaMissions();
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetMissionState(GameMessages::GameMsg& msg);
bool OnMissionNeedsLot(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
bool OnGetMissionState(GameMessages::GetMissionState& getMissionState);
bool OnMissionNeedsLot(GameMessages::MissionNeedsLot& missionNeedsLot);
/**
* All the missions owned by this entity, mapped by mission ID
*/

View File

@@ -17,20 +17,18 @@
#include "DluAssert.h"
ModelComponent::ModelComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
using namespace GameMessages;
m_OriginalPosition = m_Parent->GetDefaultPosition();
m_OriginalRotation = m_Parent->GetDefaultRotation();
m_IsPaused = false;
m_NumListeningInteract = 0;
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
RegisterMsg<RequestUse>(this, &ModelComponent::OnRequestUse);
RegisterMsg<ResetModelToDefaults>(this, &ModelComponent::OnResetModelToDefaults);
RegisterMsg<GetObjectReportInfo>(this, &ModelComponent::OnGetObjectReportInfo);
RegisterMsg(&ModelComponent::OnRequestUse);
RegisterMsg(&ModelComponent::OnResetModelToDefaults);
RegisterMsg(&ModelComponent::OnGetObjectReportInfo);
}
bool ModelComponent::OnResetModelToDefaults(GameMessages::GameMsg& msg) {
auto& reset = static_cast<GameMessages::ResetModelToDefaults&>(msg);
bool ModelComponent::OnResetModelToDefaults(GameMessages::ResetModelToDefaults& reset) {
if (reset.bResetBehaviors) for (auto& behavior : m_Behaviors) behavior.HandleMsg(reset);
if (reset.bUnSmash) {
@@ -61,10 +59,9 @@ bool ModelComponent::OnResetModelToDefaults(GameMessages::GameMsg& msg) {
return true;
}
bool ModelComponent::OnRequestUse(GameMessages::GameMsg& msg) {
bool ModelComponent::OnRequestUse(GameMessages::RequestUse& requestUse) {
bool toReturn = false;
if (!m_IsPaused) {
auto& requestUse = static_cast<GameMessages::RequestUse&>(msg);
for (auto& behavior : m_Behaviors) behavior.HandleMsg(requestUse);
toReturn = true;
}
@@ -351,10 +348,9 @@ void ModelComponent::RemoveAttack() {
}
}
bool ModelComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
if (!reportMsg.info) return false;
auto& cmptInfo = reportMsg.info->PushDebug("Model Behaviors (Mutable)");
bool ModelComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
if (!reportInfo.info) return false;
auto& cmptInfo = reportInfo.info->PushDebug("Model Behaviors (Mutable)");
cmptInfo.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
cmptInfo.PushDebug<AMFStringValue>("Name") = "Objects_" + std::to_string(m_Parent->GetLOT()) + "_name";

View File

@@ -32,9 +32,9 @@ public:
void LoadBehaviors();
void Update(float deltaTime) override;
bool OnRequestUse(GameMessages::GameMsg& msg);
bool OnResetModelToDefaults(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnRequestUse(GameMessages::RequestUse& requestUse);
bool OnResetModelToDefaults(GameMessages::ResetModelToDefaults& resetModelToDefaults);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -16,6 +16,7 @@
#include "CDComponentsRegistryTable.h"
#include "QuickBuildComponent.h"
#include "CDPhysicsComponentTable.h"
#include "Amf3.h"
#include "dNavMesh.h"
@@ -57,6 +58,8 @@ MovementAIComponent::MovementAIComponent(Entity* parent, const int32_t component
m_SavedVelocity = NiPoint3Constant::ZERO;
m_IsBounced = false;
RegisterMsg(&MovementAIComponent::OnGetObjectReportInfo);
if (!m_Parent->GetComponent<BaseCombatAIComponent>()) SetPath(m_Parent->GetVarAsString(u"attached_path"));
}
@@ -422,3 +425,63 @@ void MovementAIComponent::SetMaxSpeed(const float value) {
m_MaxSpeed = value;
m_Acceleration = value / 5;
}
bool MovementAIComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& movementInfo = reportInfo.info->PushDebug("MovementAI");
if (m_Path) {
movementInfo.PushDebug<AMFStringValue>("Path") = m_Path->pathName;
}
auto& movementAiInfo = movementInfo.PushDebug("Movement AI Info");
movementAiInfo.PushDebug<AMFStringValue>("Movement Type") = m_Info.movementType;
movementAiInfo.PushDebug<AMFDoubleValue>("Wander Radius") = m_Info.wanderRadius;
movementAiInfo.PushDebug<AMFDoubleValue>("Wander Speed") = m_Info.wanderSpeed;
movementAiInfo.PushDebug<AMFDoubleValue>("Wander Chance") = m_Info.wanderChance;
movementAiInfo.PushDebug<AMFDoubleValue>("Wander Delay Min") = m_Info.wanderDelayMin;
movementAiInfo.PushDebug<AMFDoubleValue>("Wander Delay Max") = m_Info.wanderDelayMax;
auto& speedInfo = movementInfo.PushDebug("Speed Info");
speedInfo.PushDebug<AMFDoubleValue>("Base Speed") = m_BaseSpeed;
speedInfo.PushDebug<AMFDoubleValue>("Max Speed") = m_MaxSpeed;
speedInfo.PushDebug<AMFDoubleValue>("Current Speed") = m_CurrentSpeed;
speedInfo.PushDebug<AMFDoubleValue>("Acceleration") = m_Acceleration;
movementInfo.PushDebug<AMFDoubleValue>("Halt Distance") = m_HaltDistance;
movementInfo.PushDebug<AMFDoubleValue>("Time To Travel") = m_TimeToTravel;
movementInfo.PushDebug<AMFDoubleValue>("Time Travelled") = m_TimeTravelled;
movementInfo.PushDebug<AMFBoolValue>("Lock Rotation") = m_LockRotation;
movementInfo.PushDebug<AMFBoolValue>("Paused") = m_Paused;
movementInfo.PushDebug<AMFDoubleValue>("Pulling To Point") = m_PullingToPoint;
auto& pullPointInfo = movementInfo.PushDebug("Pull Point");
pullPointInfo.PushDebug<AMFDoubleValue>("X") = m_PullPoint.x;
pullPointInfo.PushDebug<AMFDoubleValue>("Y") = m_PullPoint.y;
pullPointInfo.PushDebug<AMFDoubleValue>("Z") = m_PullPoint.z;
// movementInfo.PushDebug<AMFDoubleValue>("Delay") = m_Delay;
auto& waypoints = movementInfo.PushDebug("Interpolated Waypoints");
int i = 0;
for (const auto& point : m_InterpolatedWaypoints) {
auto& waypoint = waypoints.PushDebug("Waypoint " + std::to_string(++i));
waypoint.PushDebug<AMFDoubleValue>("X") = point.x;
waypoint.PushDebug<AMFDoubleValue>("Y") = point.y;
waypoint.PushDebug<AMFDoubleValue>("Z") = point.z;
}
i = 0;
auto& currentPath = movementInfo.PushDebug("Current Path");
auto pathCopy = m_CurrentPath; // Copy to avoid modifying the original stack
while (!pathCopy.empty()) {
const auto& waypoint = pathCopy.top();
auto& pathWaypoint = currentPath.PushDebug("Waypoint " + std::to_string(++i));
pathWaypoint.PushDebug<AMFDoubleValue>("X") = waypoint.position.x;
pathWaypoint.PushDebug<AMFDoubleValue>("Y") = waypoint.position.y;
pathWaypoint.PushDebug<AMFDoubleValue>("Z") = waypoint.position.z;
pathCopy.pop();
}
return true;
}

View File

@@ -211,6 +211,7 @@ public:
bool IsPaused() const { return m_Paused; }
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
private:
/**

View File

@@ -29,7 +29,7 @@
#include "dpShapeSphere.h"
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &PhantomPhysicsComponent::OnGetObjectReportInfo);
RegisterMsg(&PhantomPhysicsComponent::OnGetObjectReportInfo);
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
@@ -242,9 +242,8 @@ void PhantomPhysicsComponent::SetRotation(const NiQuaternion& rot) {
if (m_dpEntity) m_dpEntity->SetRotation(rot);
}
bool PhantomPhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
PhysicsComponent::OnGetObjectReportInfo(msg);
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool PhantomPhysicsComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
PhysicsComponent::OnGetObjectReportInfo(reportInfo);
if (!reportInfo.subCategory) {
return false;
}

View File

@@ -116,7 +116,7 @@ public:
void SetMax(uint32_t max);
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
/**
* A scale to apply to the size of the physics object

View File

@@ -31,11 +31,11 @@ PhysicsComponent::PhysicsComponent(Entity* parent, const int32_t componentID) :
if (m_Parent->HasVar(u"CollisionGroupID")) m_CollisionGroup = m_Parent->GetVar<int32_t>(u"CollisionGroupID");
RegisterMsg(MessageType::Game::GET_POSITION, this, &PhysicsComponent::OnGetPosition);
RegisterMsg(&PhysicsComponent::OnGetPosition);
}
bool PhysicsComponent::OnGetPosition(GameMessages::GameMsg& msg) {
static_cast<GameMessages::GetPosition&>(msg).pos = GetPosition();
bool PhysicsComponent::OnGetPosition(GameMessages::GetPosition& msg) {
msg.pos = GetPosition();
return true;
}
@@ -245,8 +245,7 @@ void PhysicsComponent::SpawnVertices(dpEntity* entity) const {
}
}
bool PhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool PhysicsComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& info = reportInfo.info->PushDebug("Physics");
reportInfo.subCategory = &info;

View File

@@ -7,6 +7,7 @@
namespace GameMessages {
struct GetObjectReportInfo;
struct GetPosition;
};
namespace Raknet {
@@ -33,7 +34,7 @@ public:
int32_t GetCollisionGroup() const noexcept { return m_CollisionGroup; }
void SetCollisionGroup(int32_t group) noexcept { m_CollisionGroup = group; }
protected:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& msg);
dpEntity* CreatePhysicsEntity(eReplicaComponentType type);
@@ -41,7 +42,7 @@ protected:
void SpawnVertices(dpEntity* entity) const;
bool OnGetPosition(GameMessages::GameMsg& msg);
bool OnGetPosition(GameMessages::GetPosition& msg);
NiPoint3 m_Position;

View File

@@ -14,7 +14,7 @@
#include "Amf3.h"
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo);
RegisterMsg(&RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo);
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
@@ -59,9 +59,8 @@ void RigidbodyPhantomPhysicsComponent::SpawnVertices() const {
PhysicsComponent::SpawnVertices(m_dpEntity);
}
bool RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
PhysicsComponent::OnGetObjectReportInfo(msg);
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
PhysicsComponent::OnGetObjectReportInfo(reportInfo);
auto& info = reportInfo.subCategory->PushDebug("Rigidbody Phantom Info");
info.PushDebug<AMFDoubleValue>("Scale") = m_Scale;
return true;

View File

@@ -29,7 +29,7 @@ public:
void SpawnVertices() const;
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
float m_Scale{};

View File

@@ -9,13 +9,12 @@
#include "Amf3.h"
ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client) : Component(parent, componentID) {
using namespace GameMessages;
m_Serialized = serialized;
m_Client = client;
m_ScriptName = scriptName;
SetScript(scriptName);
RegisterMsg<GetObjectReportInfo>(this, &ScriptComponent::OnGetObjectReportInfo);
RegisterMsg(&ScriptComponent::OnGetObjectReportInfo);
}
void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
@@ -52,10 +51,9 @@ void ScriptComponent::SetScript(const std::string& scriptName) {
m_Script = CppScripts::GetScript(m_Parent, scriptName);
}
bool ScriptComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
auto& infoMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool ScriptComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
auto& scriptInfo = infoMsg.info->PushDebug("Script");
auto& scriptInfo = reportInfo.info->PushDebug("Script");
scriptInfo.PushDebug<AMFStringValue>("Script Name") = m_ScriptName.empty() ? "None" : m_ScriptName;
auto& networkSettings = scriptInfo.PushDebug("Network Settings");
for (const auto* const setting : m_Parent->GetNetworkSettings()) {

View File

@@ -43,7 +43,7 @@ public:
*/
void SetScript(const std::string& scriptName);
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
private:

View File

@@ -16,7 +16,7 @@
#include "Amf3.h"
SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &SimplePhysicsComponent::OnGetObjectReportInfo);
RegisterMsg(&SimplePhysicsComponent::OnGetObjectReportInfo);
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
@@ -76,9 +76,8 @@ void SimplePhysicsComponent::SetPhysicsMotionState(uint32_t value) {
m_PhysicsMotionState = value;
}
bool SimplePhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
PhysicsComponent::OnGetObjectReportInfo(msg);
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
bool SimplePhysicsComponent::OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo) {
PhysicsComponent::OnGetObjectReportInfo(reportInfo);
auto& info = reportInfo.subCategory->PushDebug("Simple Physics Info");
auto& velocity = info.PushDebug("Velocity");
velocity.PushDebug<AMFDoubleValue>("x") = m_Velocity.x;

View File

@@ -86,7 +86,7 @@ public:
void SetClimbableType(const eClimbableType& value) { m_ClimbableType = value; }
private:
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
/**
* The current velocity of the entity

View File

@@ -936,6 +936,12 @@ namespace GameMessages {
LWOOBJID lootOwnerID{};
};
struct IsDead : public GameMsg {
IsDead() : GameMsg(MessageType::Game::IS_DEAD) {}
bool bDead{};
};
struct ToggleGMInvis : public GameMsg {
ToggleGMInvis() : GameMsg(MessageType::Game::TOGGLE_GM_INVIS) {}
@@ -955,11 +961,5 @@ namespace GameMessages {
LWOOBJID childID{};
};
struct IsDead : public GameMsg {
IsDead() : GameMsg(MessageType::Game::IS_DEAD) {}
bool bDead{};
};
};
#endif // GAMEMESSAGES_H