Merge remote-tracking branch 'origin/main' into dCinema

This commit is contained in:
Wincent
2025-04-18 14:49:18 +00:00
351 changed files with 175610 additions and 46883 deletions

View File

@@ -24,7 +24,7 @@
#include "eTriggerEventType.h"
#include "eObjectBits.h"
#include "PositionUpdate.h"
#include "eChatMessageType.h"
#include "MessageType/Chat.h"
#include "PlayerManager.h"
//Component includes:
@@ -84,6 +84,7 @@
#include "GhostComponent.h"
#include "Recorder.h"
#include "AchievementVendorComponent.h"
#include "VanityUtilities.h"
// Table includes
#include "CDComponentsRegistryTable.h"
@@ -97,6 +98,10 @@
#include "CDSkillBehaviorTable.h"
#include "CDZoneTableTable.h"
#include <ranges>
Observable<Entity*, const PositionUpdate&> Entity::OnPlayerPositionUpdate;
Entity::Entity(const LWOOBJID& objectID, EntityInfo info, User* parentUser, Entity* parentEntity) {
m_ObjectID = objectID;
m_TemplateID = info.lot;
@@ -284,8 +289,9 @@ void Entity::Initialize() {
AddComponent<PropertyEntranceComponent>(propertyEntranceComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS) > 0) {
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>();
const int32_t controllablePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS);
if (controllablePhysicsComponentID > 0) {
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>(controllablePhysicsComponentID);
if (m_Character) {
controllablePhysics->LoadFromXml(m_Character->GetXMLDoc());
@@ -328,16 +334,19 @@ void Entity::Initialize() {
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS) > 0) {
AddComponent<RigidbodyPhantomPhysicsComponent>();
const int32_t rigidBodyPhantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS);
if (rigidBodyPhantomPhysicsComponentID > 0) {
AddComponent<RigidbodyPhantomPhysicsComponent>(rigidBodyPhantomPhysicsComponentID);
}
if (markedAsPhantom || compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS) > 0) {
AddComponent<PhantomPhysicsComponent>()->SetPhysicsEffectActive(false);
const int32_t phantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS);
if (markedAsPhantom || phantomPhysicsComponentID > 0) {
AddComponent<PhantomPhysicsComponent>(phantomPhysicsComponentID)->SetPhysicsEffectActive(false);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS) > 0) {
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>();
const int32_t havokVehiclePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS);
if (havokVehiclePhysicsComponentID > 0) {
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>(havokVehiclePhysicsComponentID);
havokVehiclePhysicsComponent->SetPosition(m_DefaultPosition);
havokVehiclePhysicsComponent->SetRotation(m_DefaultRotation);
}
@@ -378,6 +387,9 @@ void Entity::Initialize() {
if (m_Character) {
comp->LoadFromXml(m_Character->GetXMLDoc());
} else {
// extraInfo overrides. Client ORs the database smashable and the luz smashable.
comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable);
if (componentID > 0) {
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
@@ -412,9 +424,6 @@ void Entity::Initialize() {
comp->SetMinCoins(currencyValues[0].minvalue);
comp->SetMaxCoins(currencyValues[0].maxvalue);
}
// extraInfo overrides. Client ORs the database smashable and the luz smashable.
comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable);
}
} else {
comp->SetHealth(1);
@@ -767,6 +776,12 @@ void Entity::Initialize() {
// Hacky way to trigger these when the object has had a chance to get constructed
AddCallbackTimer(0, [this]() {
this->GetScript()->OnStartup(this);
if (this->m_ParentEntity) {
GameMessages::ChildLoaded childLoaded;
childLoaded.childID = this->m_ObjectID;
childLoaded.templateID = this->GetLOT();
this->m_ParentEntity->OnChildLoaded(childLoaded);
}
});
if (!m_Character && Game::entityManager->GetGhostingEnabled()) {
@@ -846,6 +861,9 @@ void Entity::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, co
auto* destroyableComponent = GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->Subscribe(scriptObjId, scriptToAdd);
} else if (notificationName == "PlayerResurrectionFinished") {
LOG("Subscribing to PlayerResurrectionFinished");
m_Subscriptions[scriptObjId][notificationName] = scriptToAdd;
}
}
@@ -854,6 +872,9 @@ void Entity::Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationNa
auto* destroyableComponent = GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->Unsubscribe(scriptObjId);
} else if (notificationName == "PlayerResurrectionFinished") {
LOG("Unsubscribing from PlayerResurrectionFinished");
m_Subscriptions[scriptObjId].erase(notificationName);
}
}
@@ -882,7 +903,7 @@ void Entity::SetGMLevel(eGameMasterLevel value) {
// Update the chat server of our GM Level
{
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GMLEVEL_UPDATE);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GMLEVEL_UPDATE);
bitStream.Write(m_ObjectID);
bitStream.Write(m_GMLevel);
@@ -1270,6 +1291,7 @@ void Entity::Update(const float deltaTime) {
auto timerName = timer.GetName();
m_Timers.erase(m_Timers.begin() + timerPosition);
GetScript()->OnTimerDone(this, timerName);
VanityUtilities::OnTimerDone(this, timerName);
TriggerEvent(eTriggerEventType::TIMER_DONE, this);
} else {
@@ -1333,6 +1355,7 @@ void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxN
if (!other) return;
GetScript()->OnProximityUpdate(this, other, proxName, status);
VanityUtilities::OnProximityUpdate(this, other, proxName, status);
RocketLaunchpadControlComponent* rocketComp = GetComponent<RocketLaunchpadControlComponent>();
if (!rocketComp) return;
@@ -1352,7 +1375,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
SwitchComponent* switchComp = GetComponent<SwitchComponent>();
if (switchComp) {
switchComp->EntityEnter(other);
switchComp->OnUse(other);
}
TriggerEvent(eTriggerEventType::ENTER, other);
@@ -1483,6 +1506,27 @@ void Entity::OnChoiceBoxResponse(Entity* sender, int32_t button, const std::u16s
GetScript()->OnChoiceBoxResponse(this, sender, button, buttonIdentifier, identifier);
}
void Entity::OnActivityNotify(GameMessages::ActivityNotify& notify) {
GetScript()->OnActivityNotify(this, notify);
}
void Entity::OnShootingGalleryFire(GameMessages::ShootingGalleryFire& fire) {
GetScript()->OnShootingGalleryFire(*this, fire);
}
void Entity::OnChildLoaded(GameMessages::ChildLoaded& childLoaded) {
GetScript()->OnChildLoaded(*this, childLoaded);
}
void Entity::NotifyPlayerResurrectionFinished(GameMessages::PlayerResurrectionFinished& msg) {
for (const auto& [id, scriptList] : m_Subscriptions) {
auto it = scriptList.find("PlayerResurrectionFinished");
if (it == scriptList.end()) continue;
it->second->NotifyPlayerResurrectionFinished(*this, msg);
}
}
void Entity::RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled) {
GetScript()->OnRequestActivityExit(sender, player, canceled);
}
@@ -1522,7 +1566,7 @@ void Entity::Kill(Entity* murderer, const eKillType killType) {
m_DieCallbacks.clear();
//OMAI WA MOU, SHINDERIU
//お前はもう死んでいる
GetScript()->OnDie(this, murderer);
@@ -2148,6 +2192,8 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
update.angularVelocity != NiPoint3Constant::ZERO
));
}
OnPlayerPositionUpdate.Notify(this, update);
}
const SystemAddress& Entity::GetSystemAddress() const {
@@ -2169,7 +2215,33 @@ void Entity::SetRespawnPos(const NiPoint3& position) {
auto* characterComponent = GetComponent<CharacterComponent>();
if (characterComponent) characterComponent->SetRespawnPos(position);
}
void Entity::SetRespawnRot(const NiQuaternion& rotation) {
auto* characterComponent = GetComponent<CharacterComponent>();
if (characterComponent) characterComponent->SetRespawnRot(rotation);
}
int32_t Entity::GetCollisionGroup() const {
for (const auto* component : m_Components | std::views::values) {
auto* compToCheck = dynamic_cast<const PhysicsComponent*>(component);
if (compToCheck) {
return compToCheck->GetCollisionGroup();
}
}
return 0;
}
bool Entity::HandleMsg(GameMessages::GameMsg& msg) const {
bool handled = false;
const auto [beg, end] = m_MsgHandlers.equal_range(msg.msgId);
for (auto it = beg; it != end; ++it) {
if (it->second) handled |= it->second(msg);
}
return handled;
}
void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler) {
m_MsgHandlers.emplace(msgId, handler);
}