mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-14 07:47:13 +00:00
refactor(component): use is a RequestUse message handler
Components no longer have a virtual OnUse; each component that reacts to a use registers a RequestUse handler, like the client's components. The entity runs the INTERACT trigger and the script, then delivers a RequestUseEvent (carrying the user) to the handlers. The mission choice of a multi-interact use goes only to the mission offer, as before. Switches keep a direct EnterIfResponding for touches and pets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1565,7 +1565,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
|
||||
|
||||
SwitchComponent* const switchComp = GetComponent<SwitchComponent>();
|
||||
if (switchComp) {
|
||||
switchComp->OnUse(other);
|
||||
switchComp->EnterIfResponding(other);
|
||||
}
|
||||
|
||||
TriggerEvent(eTriggerEventType::ENTER, other);
|
||||
@@ -1635,16 +1635,21 @@ void Entity::OnEmoteReceived(const int32_t emote, Entity* target) {
|
||||
GetScript()->OnEmoteReceived(this, emote, target);
|
||||
}
|
||||
|
||||
void Entity::OnUse(Entity* originator) {
|
||||
TriggerEvent(eTriggerEventType::INTERACT, originator);
|
||||
|
||||
GetScript()->OnUse(this, originator);
|
||||
|
||||
for (const auto& component : m_Components | std::views::values) {
|
||||
if (!component) continue;
|
||||
|
||||
component->OnUse(originator);
|
||||
void Entity::RequestUse(const GameMessages::RequestUse& msg, Entity& user) {
|
||||
if (!msg.IsMissionChoice()) {
|
||||
TriggerEvent(eTriggerEventType::INTERACT, &user);
|
||||
GetScript()->OnUse(this, &user);
|
||||
}
|
||||
|
||||
GameMessages::RequestUseEvent event(msg, user);
|
||||
HandleMsg(event);
|
||||
}
|
||||
|
||||
void Entity::OnUse(Entity* originator) {
|
||||
GameMessages::RequestUse msg;
|
||||
msg.target = originator->GetObjectID();
|
||||
msg.object = m_ObjectID;
|
||||
RequestUse(msg, *originator);
|
||||
}
|
||||
|
||||
void Entity::OnHitOrHealResult(Entity* attacker, int32_t damage) {
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace GameMessages {
|
||||
struct GetFlag;
|
||||
struct GetFactionTokenType;
|
||||
struct PickupItem;
|
||||
struct RequestUse;
|
||||
struct ChildRemoved;
|
||||
};
|
||||
|
||||
@@ -247,6 +248,10 @@ public:
|
||||
void NotifyObject(Entity* sender, const std::string& name, int32_t param1 = 0, int32_t param2 = 0);
|
||||
void OnEmoteReceived(int32_t emote, Entity* target);
|
||||
|
||||
// The client's RequestUse of this object by user: the INTERACT trigger and the script's OnUse (not for the mission
|
||||
// choice of a multi-interact use), then the components' RequestUse handlers.
|
||||
void RequestUse(const GameMessages::RequestUse& msg, Entity& user);
|
||||
// originator uses this object as if their client had sent RequestUse
|
||||
void OnUse(Entity* originator);
|
||||
|
||||
void OnHitOrHealResult(Entity* attacker, int32_t damage);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "BuildBorderComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
@@ -11,12 +12,15 @@
|
||||
#include "PropertyManagementComponent.h"
|
||||
|
||||
BuildBorderComponent::BuildBorderComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&BuildBorderComponent::OnRequestUse);
|
||||
}
|
||||
|
||||
BuildBorderComponent::~BuildBorderComponent() {
|
||||
}
|
||||
|
||||
void BuildBorderComponent::OnUse(Entity* originator) {
|
||||
bool BuildBorderComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
if (originator->GetCharacter()) {
|
||||
const auto& entities = Game::entityManager->GetEntitiesInGroup("PropertyPlaque");
|
||||
|
||||
@@ -31,13 +35,13 @@ void BuildBorderComponent::OnUse(Entity* originator) {
|
||||
auto* inventoryComponent = originator->GetComponent<InventoryComponent>();
|
||||
|
||||
if (inventoryComponent == nullptr) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto* thinkingHat = inventoryComponent->FindItemByLot(6086);
|
||||
|
||||
if (thinkingHat == nullptr) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
inventoryComponent->PushEquippedItems();
|
||||
@@ -69,7 +73,8 @@ void BuildBorderComponent::OnUse(Entity* originator) {
|
||||
}
|
||||
|
||||
InventoryComponent* inv = m_Parent->GetComponent<InventoryComponent>();
|
||||
if (!inv) return;
|
||||
if (!inv) return true;
|
||||
inv->PushEquippedItems(); // technically this is supposed to happen automatically... but it doesnt? so just keep this here
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
* Causes the originator to start build with this entity as a reference point
|
||||
* @param originator the entity (probably a player) that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace RakNet {
|
||||
|
||||
namespace GameMessages {
|
||||
struct GameMsg;
|
||||
struct RequestUseEvent;
|
||||
}
|
||||
|
||||
class Entity;
|
||||
@@ -61,7 +62,6 @@ public:
|
||||
* Event called when this component is being used, e.g. when some entity interacted with it
|
||||
* @param originator
|
||||
*/
|
||||
virtual void OnUse(Entity* originator) {}
|
||||
|
||||
// A character's save (its XML): read on load, written on save
|
||||
virtual void LoadFromSaveData(const tinyxml2::XMLDocument& doc) {}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <sstream>
|
||||
#include "MissionOfferComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "CDClientManager.h"
|
||||
#include "CDMissionsTable.h"
|
||||
#include "CDMissionNPCComponentTable.h"
|
||||
@@ -41,6 +42,7 @@ bool OfferedMission::GetAcceptsMission() const {
|
||||
//------------------------ MissionOfferComponent below ------------------------
|
||||
|
||||
MissionOfferComponent::MissionOfferComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&MissionOfferComponent::OnRequestUse);
|
||||
if (componentID != -1) {
|
||||
// Now lookup the missions in the MissionNPCComponent table
|
||||
auto* missionNpcComponentTable = CDClientManager::GetTable<CDMissionNPCComponentTable>();
|
||||
@@ -73,8 +75,10 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
void MissionOfferComponent::OnUse(Entity* originator) {
|
||||
OfferMissions(originator);
|
||||
bool MissionOfferComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) OfferMissions(event.user, event.msg.multiInteractID);
|
||||
else OfferMissions(event.user);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifiedMissionId) {
|
||||
|
||||
@@ -66,11 +66,11 @@ public:
|
||||
MissionOfferComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
/**
|
||||
* Handles the OnUse event triggered by some entity, determines which missions to show based on what they may
|
||||
* Handles a RequestUse triggered by some entity, determines which missions to show based on what they may
|
||||
* hand in now and what they may start based on their mission history.
|
||||
* @param originator the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Offers all the missions an entity can accept to said entity
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include "MultiZoneEntranceComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "PropertyMessages.h"
|
||||
#include "RocketLaunchpadControlComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "CharacterComponent.h"
|
||||
|
||||
MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&MultiZoneEntranceComponent::OnRequestUse);
|
||||
m_Parent = parent;
|
||||
std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar<std::u16string>(u"MultiZoneIDs"));
|
||||
std::stringstream ss(zoneString);
|
||||
@@ -17,17 +19,20 @@ MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent, const int
|
||||
|
||||
MultiZoneEntranceComponent::~MultiZoneEntranceComponent() {}
|
||||
|
||||
void MultiZoneEntranceComponent::OnUse(Entity* originator) {
|
||||
bool MultiZoneEntranceComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
auto* const characterComponent = originator->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
if (!characterComponent) return true;
|
||||
|
||||
auto* rocket = characterComponent->RocketEquip(originator);
|
||||
if (!rocket) return;
|
||||
if (!rocket) return true;
|
||||
|
||||
// the LUP world menu is just the property menu, the client knows how to handle it
|
||||
GameMessages::PropertyEntranceBegin msg;
|
||||
msg.target = m_Parent->GetObjectID();
|
||||
msg.Send(originator->GetSystemAddress());
|
||||
return true;
|
||||
}
|
||||
|
||||
void MultiZoneEntranceComponent::OnSelectWorld(Entity* originator, uint32_t index) {
|
||||
|
||||
@@ -20,13 +20,13 @@ public:
|
||||
~MultiZoneEntranceComponent() override;
|
||||
|
||||
/**
|
||||
* Handles an OnUse event from some entity, preparing it for launch to some other world
|
||||
* Handles a RequestUse from some entity, preparing it for launch to some other world
|
||||
* @param originator the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Handles an OnUse event from some entity, preparing it for launch to some other world
|
||||
* Handles a RequestUse from some entity, preparing it for launch to some other world
|
||||
* @param originator the entity that triggered the event
|
||||
* @param index index of the world that was selected
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,7 @@ std::unordered_map<LWOOBJID, LWOOBJID> PetComponent::activePets{};
|
||||
*/
|
||||
|
||||
PetComponent::PetComponent(Entity* parentEntity, const int32_t componentID) : Component{ parentEntity, componentID } {
|
||||
RegisterMsg(&PetComponent::OnRequestUse);
|
||||
m_PetInfo = CDClientManager::GetTable<CDPetComponentTable>()->GetByID(componentID); // TODO: Make reference when safe
|
||||
|
||||
m_Interaction = LWOOBJID_EMPTY;
|
||||
@@ -120,19 +121,21 @@ void PetComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpd
|
||||
}
|
||||
}
|
||||
|
||||
void PetComponent::OnUse(Entity* originator) {
|
||||
bool PetComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
if (m_Owner != LWOOBJID_EMPTY) {
|
||||
// The owner uses their pet with SHIFT or the pet menu's action button: the client sends RequestUse on the pet
|
||||
// (LWOPetControlComponent::msgPetCommand, "contextAction")
|
||||
if (originator->GetObjectID() == m_Owner) UseAbility();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_Tamer != LWOOBJID_EMPTY) {
|
||||
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||
|
||||
if (tamer != nullptr) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_Tamer = LWOOBJID_EMPTY;
|
||||
@@ -140,11 +143,11 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
|
||||
auto* const inventoryComponent = originator->GetComponent<InventoryComponent>();
|
||||
if (inventoryComponent == nullptr) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_Preconditions.has_value()) {
|
||||
if (!m_Preconditions->Check(originator)) return;
|
||||
if (!m_Preconditions->Check(originator)) return true;
|
||||
// Taming uses up the items its preconditions ask for
|
||||
for (const auto& cost : m_Preconditions->GetItemCosts(originator)) {
|
||||
inventoryComponent->RemoveItem(cost.lot, cost.count, eInventoryType::ALL);
|
||||
@@ -161,17 +164,17 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
const auto* const entry = CDClientManager::GetTable<CDTamingBuildPuzzleTable>()->GetByLOT(m_Parent->GetLOT());
|
||||
if (!entry) {
|
||||
ChatPackets::SendSystemMessage(originator->GetSystemAddress(), u"Failed to find the puzzle minigame for this pet.");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto* const destroyableComponent = originator->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent == nullptr) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto imagination = destroyableComponent->GetImagination();
|
||||
if (imagination < entry->imaginationCost) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto& bricks = BrickDatabase::GetBricks(entry->validPieces);
|
||||
@@ -179,7 +182,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
ChatPackets::SendSystemMessage(originator->GetSystemAddress(), u"Failed to load the puzzle minigame for this pet.");
|
||||
LOG("Couldn't find %s for minigame!", entry->validPieces.c_str());
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Where live put the minigame (2014 captures, the same for every try at a pet): the pet goes back to where it
|
||||
@@ -254,6 +257,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
characterComponent->SetCurrentActivity(eGameActivity::PET_TAMING);
|
||||
Game::entityManager->SerializeEntity(originator);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PetComponent::Run(float deltaTime) {
|
||||
@@ -1251,7 +1255,7 @@ void PetComponent::UseAbility() {
|
||||
SendHelp(eHelpType::PR_TOOLTIP_1ST_PET_JUMPED_ON_SWITCH);
|
||||
|
||||
auto* const switchComponent = object->GetComponent<SwitchComponent>();
|
||||
if (switchComponent) switchComponent->OnUse(m_Parent);
|
||||
if (switchComponent) switchComponent->EnterIfResponding(m_Parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,10 @@ public:
|
||||
void Run(float deltaTime) override;
|
||||
|
||||
/**
|
||||
* Handles an OnUse event from another entity, initializing the pet taming minigame if this pet is untamed.
|
||||
* Handles a RequestUse from another entity, initializing the pet taming minigame if this pet is untamed.
|
||||
* @param originator the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Attempts to complete the pet minigame by passing a list of bricks to build the minigame model.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include "PossessableComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Inventory.h"
|
||||
#include "Item.h"
|
||||
|
||||
PossessableComponent::PossessableComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&PossessableComponent::OnRequestUse);
|
||||
m_Possessor = LWOOBJID_EMPTY;
|
||||
CDItemComponent item = Inventory::FindItemComponent(m_Parent->GetLOT());
|
||||
m_AnimationFlag = static_cast<eAnimationFlags>(item.animationFlag);
|
||||
@@ -48,9 +50,12 @@ void PossessableComponent::Dismount() {
|
||||
if (m_ItemSpawned) m_Parent->ScheduleKillAfterUpdate();
|
||||
}
|
||||
|
||||
void PossessableComponent::OnUse(Entity* originator) {
|
||||
bool PossessableComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
auto* possessor = originator->GetComponent<PossessorComponent>();
|
||||
if (possessor) {
|
||||
possessor->Mount(m_Parent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -79,11 +79,11 @@ public:
|
||||
LWOOBJID GetIsItemSpawned() const { return m_ItemSpawned; };
|
||||
|
||||
/**
|
||||
* Handles an OnUsed event by some other entity, if said entity has a Possessor it becomes the possessor
|
||||
* Handles a RequestUse by some other entity, if said entity has a Possessor it becomes the possessor
|
||||
* of this entity
|
||||
* @param originator the entity that caused the event to trigger
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "PropertyEntranceComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
|
||||
#include "CDPropertyEntranceComponentTable.h"
|
||||
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "User.h"
|
||||
|
||||
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&PropertyEntranceComponent::OnRequestUse);
|
||||
this->propertyQueries = {};
|
||||
|
||||
auto table = CDClientManager::GetTable<CDPropertyEntranceComponentTable>();
|
||||
@@ -28,12 +30,14 @@ PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, const int32
|
||||
this->m_PropertyName = entry.propertyName;
|
||||
}
|
||||
|
||||
void PropertyEntranceComponent::OnUse(Entity* entity) {
|
||||
bool PropertyEntranceComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const entity = event.user;
|
||||
auto* characterComponent = entity->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
if (!characterComponent) return true;
|
||||
|
||||
auto* rocket = entity->GetComponent<CharacterComponent>()->RocketEquip(entity);
|
||||
if (!rocket) return;
|
||||
if (!rocket) return true;
|
||||
|
||||
GameMessages::PropertyEntranceBegin msg;
|
||||
msg.target = m_Parent->GetObjectID();
|
||||
@@ -48,6 +52,7 @@ void PropertyEntranceComponent::OnUse(Entity* entity) {
|
||||
uiMessage.strMessageName = "pushGameState";
|
||||
uiMessage.args = std::move(args);
|
||||
uiMessage.SendToClient(entity->GetSystemAddress());
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr) {
|
||||
|
||||
@@ -18,10 +18,10 @@ public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
|
||||
|
||||
/**
|
||||
* Handles an OnUse request for some other entity, rendering the property browse menu
|
||||
* Handles a RequestUse for some other entity, rendering the property browse menu
|
||||
* @param entity the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* entity) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Handles the event triggered when the entity selects a property to visit and makes the entity to there
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "PropertyManagementComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "PropertyRent.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "DashboardNotify.h"
|
||||
@@ -41,6 +42,7 @@
|
||||
PropertyManagementComponent* PropertyManagementComponent::instance = nullptr;
|
||||
|
||||
PropertyManagementComponent::PropertyManagementComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&PropertyManagementComponent::OnRequestUse);
|
||||
this->owner = LWOOBJID_EMPTY;
|
||||
this->templateId = 0;
|
||||
this->propertyId = LWOOBJID_EMPTY;
|
||||
@@ -978,11 +980,14 @@ void PropertyManagementComponent::SendPropertyData(const Entity& player, const G
|
||||
forPlayer.Send(player.GetSystemAddress());
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::OnUse(Entity* originator) {
|
||||
bool PropertyManagementComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
OnQueryPropertyData(originator, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::OpenPropertyManagement msg;
|
||||
msg.target = PropertyManagementComponent::Instance()->GetParent()->GetObjectID();
|
||||
msg.Send(originator->GetSystemAddress());
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::SetOwnerId(const LWOOBJID value) {
|
||||
|
||||
@@ -49,10 +49,10 @@ public:
|
||||
void OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author = LWOOBJID_EMPTY);
|
||||
|
||||
/**
|
||||
* Handles an OnUse event, telling the client who owns this property, etc.
|
||||
* Handles a RequestUse, telling the client who owns this property, etc.
|
||||
* @param originator the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Sets the owner of this property
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "PropertyVendorComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
|
||||
#include "PropertyMessages.h"
|
||||
#include "GameMessages.h"
|
||||
@@ -11,10 +12,13 @@
|
||||
#include "UserManager.h"
|
||||
|
||||
PropertyVendorComponent::PropertyVendorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&PropertyVendorComponent::OnRequestUse);
|
||||
}
|
||||
|
||||
void PropertyVendorComponent::OnUse(Entity* originator) {
|
||||
if (PropertyManagementComponent::Instance() == nullptr) return;
|
||||
bool PropertyVendorComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
if (PropertyManagementComponent::Instance() == nullptr) return true;
|
||||
|
||||
OnQueryPropertyData(originator, originator->GetSystemAddress());
|
||||
|
||||
@@ -25,8 +29,9 @@ void PropertyVendorComponent::OnUse(Entity* originator) {
|
||||
msg.target = m_Parent->GetObjectID();
|
||||
msg.Send(originator->GetSystemAddress());
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertyVendorComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr) {
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
* Handles a use event from some entity, if the property is cleared this allows the entity to claim it
|
||||
* @param originator the entity that triggered this event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Handles a property data query after the property has been claimed, sending information about the property to the
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "EconomyLedger.h"
|
||||
|
||||
QuickBuildComponent::QuickBuildComponent(Entity* const entity, const int32_t componentID) : Component{ entity, componentID } {
|
||||
RegisterMsg(&QuickBuildComponent::OnRequestUse);
|
||||
std::u16string checkPreconditions = entity->GetVar<std::u16string>(u"CheckPrecondition");
|
||||
|
||||
if (!checkPreconditions.empty()) {
|
||||
@@ -246,16 +247,19 @@ void QuickBuildComponent::Run(float deltaTime) {
|
||||
}
|
||||
}
|
||||
|
||||
void QuickBuildComponent::OnUse(Entity* originator) {
|
||||
bool QuickBuildComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
if (GetBuilder() != nullptr || m_State == eQuickBuildState::COMPLETED) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_Precondition != nullptr && !m_Precondition->Check(originator)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
StartQuickBuild(originator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QuickBuildComponent::SpawnActivator() {
|
||||
|
||||
@@ -31,10 +31,10 @@ public:
|
||||
void Run(float deltaTime) override;
|
||||
|
||||
/**
|
||||
* Handles a OnUse event from some entity, initiating the quick build
|
||||
* Handles a RequestUse from some entity, initiating the quick build
|
||||
* @param originator the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Spawns the activator that can be used to initiate the quickbuild
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <algorithm>
|
||||
#include "RailActivatorComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "CDClientManager.h"
|
||||
#include "CDRailActivatorComponent.h"
|
||||
#include "Entity.h"
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "eStateChangeType.h"
|
||||
|
||||
RailActivatorComponent::RailActivatorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&RailActivatorComponent::OnRequestUse);
|
||||
const auto tableData = CDClientManager::GetTable<CDRailActivatorComponentTable>()->GetEntryByID(componentID);
|
||||
|
||||
m_Path = parent->GetVar<std::u16string>(u"rail_path");
|
||||
@@ -51,10 +53,12 @@ RailActivatorComponent::RailActivatorComponent(Entity* parent, const int32_t com
|
||||
|
||||
RailActivatorComponent::~RailActivatorComponent() = default;
|
||||
|
||||
void RailActivatorComponent::OnUse(Entity* originator) {
|
||||
bool RailActivatorComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
auto* quickBuildComponent = m_Parent->GetComponent<QuickBuildComponent>();
|
||||
if (quickBuildComponent != nullptr && quickBuildComponent->GetState() != eQuickBuildState::COMPLETED)
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (quickBuildComponent != nullptr) {
|
||||
// Don't want it to be destroyed while a player is using it
|
||||
@@ -101,6 +105,7 @@ void RailActivatorComponent::OnUse(Entity* originator) {
|
||||
startRail.railActivatorObjectID = m_Parent->GetObjectID();
|
||||
startRail.Send(originator->GetSystemAddress());
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
void RailActivatorComponent::OnRailMovementReady(Entity* originator) const {
|
||||
|
||||
@@ -18,10 +18,10 @@ public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
|
||||
|
||||
/**
|
||||
* Handles the OnUse event from some entity, initiates the rail movement
|
||||
* Handles a RequestUse from some entity, initiates the rail movement
|
||||
* @param originator the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Event handler that's called when some entity has played the start animation for rail movement and now wants to
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "MessageType/Master.h"
|
||||
|
||||
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&RocketLaunchpadControlComponent::OnRequestUse);
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;");
|
||||
query.bind(1, componentID);
|
||||
@@ -92,27 +93,30 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOMAPID mapId,
|
||||
Game::entityManager->SerializeEntity(originator);
|
||||
}
|
||||
|
||||
void RocketLaunchpadControlComponent::OnUse(Entity* originator) {
|
||||
bool RocketLaunchpadControlComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
// If we are have the property or the LUP component, we don't want to immediately launch
|
||||
// instead we let their OnUse handlers do their things
|
||||
// which components of an Object have their OnUse called when using them
|
||||
// so we don't need to call it here
|
||||
auto* propertyEntrance = m_Parent->GetComponent<PropertyEntranceComponent>();
|
||||
if (propertyEntrance) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto* rocketLaunchLUP = m_Parent->GetComponent<MultiZoneEntranceComponent>();
|
||||
if (rocketLaunchLUP) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// No rocket no launch
|
||||
auto* rocket = originator->GetComponent<CharacterComponent>()->RocketEquip(originator);
|
||||
if (!rocket) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
Launch(originator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RocketLaunchpadControlComponent::OnProximityUpdate(Entity* entering, std::string name, std::string status) {
|
||||
|
||||
@@ -45,10 +45,10 @@ public:
|
||||
static GameMessages::FireEventClientSide MakeRocketEquipped(LWOOBJID launchpad, LWOOBJID rocket, LWOOBJID player, LWOCLONEID cloneId, int32_t worldIndex);
|
||||
|
||||
/**
|
||||
* Handles an OnUse event from some entity, preparing it for launch to some other world
|
||||
* Handles a RequestUse from some entity, preparing it for launch to some other world
|
||||
* @param originator the entity that triggered the event
|
||||
*/
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
/**
|
||||
* Currently unused
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "SwitchComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "eTriggerEventType.h"
|
||||
#include "RenderComponent.h"
|
||||
@@ -8,6 +9,7 @@
|
||||
std::vector<SwitchComponent*> SwitchComponent::petSwitches;
|
||||
|
||||
SwitchComponent::SwitchComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&SwitchComponent::OnRequestUse);
|
||||
m_Active = false;
|
||||
|
||||
m_ResetTime = m_Parent->GetVarAs<int32_t>(u"switch_reset_time");
|
||||
@@ -34,7 +36,7 @@ void SwitchComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitial
|
||||
outBitStream.Write(m_Active);
|
||||
}
|
||||
|
||||
void SwitchComponent::OnUse(Entity* originator) {
|
||||
void SwitchComponent::EnterIfResponding(Entity* originator) {
|
||||
const auto* const destroyableComponent = originator->GetComponent<DestroyableComponent>();
|
||||
if (!destroyableComponent) return;
|
||||
for (const auto faction : m_FactionsToRespondTo) {
|
||||
@@ -45,6 +47,12 @@ void SwitchComponent::OnUse(Entity* originator) {
|
||||
}
|
||||
}
|
||||
|
||||
bool SwitchComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
EnterIfResponding(event.user);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SwitchComponent::SetActive(bool active) {
|
||||
m_Active = active;
|
||||
|
||||
|
||||
@@ -22,7 +22,10 @@ public:
|
||||
~SwitchComponent() override;
|
||||
|
||||
void Run(float deltaTime) override;
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
|
||||
// Enters the switch if entity has one of the factions it responds to (a use, a touch or a pet on it)
|
||||
void EnterIfResponding(Entity* entity);
|
||||
|
||||
Entity* GetParentEntity() const;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "VendorComponent.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "BitStream.h"
|
||||
#include "dServer.h"
|
||||
#include "dZoneManager.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include <ranges>
|
||||
|
||||
VendorComponent::VendorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
RegisterMsg(&VendorComponent::OnRequestUse);
|
||||
m_HasStandardCostItems = false;
|
||||
m_HasMultiCostItems = false;
|
||||
SetupConstants();
|
||||
@@ -36,7 +38,9 @@ void VendorComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitial
|
||||
}
|
||||
}
|
||||
|
||||
void VendorComponent::OnUse(Entity* originator) {
|
||||
bool VendorComponent::OnRequestUse(GameMessages::RequestUseEvent& event) {
|
||||
if (event.msg.IsMissionChoice()) return false;
|
||||
auto* const originator = event.user;
|
||||
GameMessages::VendorOpenWindow openWindow;
|
||||
openWindow.target = m_Parent->GetObjectID();
|
||||
openWindow.SendToClient(originator->GetSystemAddress());
|
||||
@@ -44,6 +48,7 @@ void VendorComponent::OnUse(Entity* originator) {
|
||||
// Only the entity's VENDOR component sends its stock (achievement and donation vendors never did).
|
||||
auto* vendor = static_cast<VendorComponent*>(m_Parent->GetComponent(eReplicaComponentType::VENDOR));
|
||||
if (vendor) vendor->SendStatusUpdate(originator->GetSystemAddress());
|
||||
return true;
|
||||
}
|
||||
|
||||
void VendorComponent::RefreshInventory(bool isCreation) {
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
void OnUse(Entity* originator) override;
|
||||
bool OnRequestUse(GameMessages::RequestUseEvent& event);
|
||||
virtual void RefreshInventory(bool isCreation = false);
|
||||
void SetupConstants();
|
||||
bool SellsItem(const LOT item) const;
|
||||
|
||||
@@ -250,22 +250,7 @@ namespace GameMessages {
|
||||
entity.GetCharacter()->SetBuildMode(true);
|
||||
}
|
||||
|
||||
if (bIsMultiInteractUse) {
|
||||
if (multiInteractType == 0) {
|
||||
auto* missionOfferComponent = static_cast<MissionOfferComponent*>(interactedObject->GetComponent(eReplicaComponentType::MISSION_OFFER));
|
||||
|
||||
if (missionOfferComponent != nullptr) {
|
||||
missionOfferComponent->OfferMissions(&entity, multiInteractID);
|
||||
}
|
||||
} else {
|
||||
interactedObject->OnUse(&entity);
|
||||
}
|
||||
} else {
|
||||
interactedObject->OnUse(&entity);
|
||||
}
|
||||
|
||||
RequestUseEvent event(*this);
|
||||
interactedObject->HandleMsg(event);
|
||||
interactedObject->RequestUse(*this, entity);
|
||||
|
||||
//Perform use task if possible:
|
||||
auto missionComponent = entity.GetComponent<MissionComponent>();
|
||||
|
||||
@@ -168,8 +168,19 @@ namespace GameMessages {
|
||||
LWOOBJID object{};
|
||||
|
||||
bool secondary{ false };
|
||||
|
||||
// The mission choice of a multi-interact use: only the mission offer handles it.
|
||||
bool IsMissionChoice() const { return bIsMultiInteractUse && multiInteractType == 0; }
|
||||
};
|
||||
|
||||
// A use of an object, delivered to its components' RequestUse handlers. user is who used it: the sender of the
|
||||
// RequestUse, or whoever the server makes use it. Only dispatch RequestUse locally as this event.
|
||||
struct RequestUseEvent : public NetGameMsgEvent<RequestUse> {
|
||||
RequestUseEvent() = default;
|
||||
RequestUseEvent(const RequestUse& message, Entity& user) : NetGameMsgEvent(message), user{ &user } {}
|
||||
|
||||
Entity* user{};
|
||||
};
|
||||
using RequestUseEvent = NetGameMsgEvent<RequestUse>;
|
||||
|
||||
// Client -> server. Developer only.
|
||||
struct RequestServerObjectInfo : public NetGameMsg {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "InventoryMessages.h"
|
||||
#include "Item.h"
|
||||
#include "LootMetrics.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "QuickBuildComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
@@ -233,7 +234,7 @@ TEST_F(LootMetricsTests, QuickbuildTakesItsCostAsTheSource) {
|
||||
quickBuild->SetCompleteTime(10.0f);
|
||||
ClearSent();
|
||||
|
||||
quickBuild->OnUse(entity.get());
|
||||
{ GameMessages::RequestUseEvent use(GameMessages::RequestUse{}, *entity); quickBuild->OnRequestUse(use); }
|
||||
EXPECT_EQ(quickBuild->GetState(), eQuickBuildState::BUILDING);
|
||||
const auto removed = Removed();
|
||||
ASSERT_EQ(removed.size(), 1u);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Entity.h"
|
||||
#include "PlayerMessages.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "QuickBuildComponent.h"
|
||||
#include "QuickBuildMessages.h"
|
||||
#include "eQuickBuildState.h"
|
||||
@@ -60,7 +61,7 @@ protected:
|
||||
|
||||
// Starts the build and runs updates until it completes (the first update only sets up the imagination drain).
|
||||
std::vector<CapturedPacket> Build() {
|
||||
quickBuild->OnUse(player.get());
|
||||
{ GameMessages::RequestUseEvent use(GameMessages::RequestUse{}, *player); quickBuild->OnRequestUse(use); }
|
||||
return Capture([&] {
|
||||
for (int i = 0; i < 3 && quickBuild->GetState() != eQuickBuildState::COMPLETED; i++) quickBuild->Run(0.1f);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user