F4MP/tiltedcode/Code/server/Services/QuestService.cpp
Jous99 37b16f1547 code upload
codigo original de f4mp y tilted para referencias
2026-01-06 18:45:00 +01:00

98 lines
3.4 KiB
C++

#include <GameServer.h>
#include <Components.h>
#include <World.h>
#include <Services/QuestService.h>
#include <Messages/RequestQuestUpdate.h>
#include <Messages/NotifyQuestUpdate.h>
#include <Setting.h>
namespace
{
Console::Setting bEnableMiscQuestSync{"Gameplay:bEnableMiscQuestSync", "(Experimental) Syncs miscellaneous quests when possible", false};
}
QuestService::QuestService(World& aWorld, entt::dispatcher& aDispatcher)
: m_world(aWorld)
{
m_questUpdateConnection = aDispatcher.sink<PacketEvent<RequestQuestUpdate>>().connect<&QuestService::OnQuestChanges>(this);
}
void QuestService::OnQuestChanges(const PacketEvent<RequestQuestUpdate>& acMessage) noexcept
{
const auto& message = acMessage.Packet;
auto* pPlayer = acMessage.pPlayer;
auto& questComponent = pPlayer->GetQuestLogComponent();
auto& entries = questComponent.QuestContent.Entries;
auto questIt = std::find_if(entries.begin(), entries.end(), [&message](const auto& e) { return e.Id == message.Id; });
NotifyQuestUpdate notify{};
notify.Id = message.Id;
notify.Stage = message.Stage;
notify.Status = message.Status;
notify.ClientQuestType = message.ClientQuestType;
if (notify.ClientQuestType == 0 || notify.ClientQuestType == 6) // Types None or Miscellaneous. Hard-coded to avoid client header file.
{
if (!bEnableMiscQuestSync)
return;
spdlog::info("{}: syncing type none/misc quest to party, gameId {:X} questStage {} questStatus {} questType {}",
__FUNCTION__, notify.Id.LogFormat(), notify.Stage, notify.Status, notify.ClientQuestType);
}
if (message.Status == RequestQuestUpdate::Started || message.Status == RequestQuestUpdate::StageUpdate)
{
// in order to prevent bugs when a quest is in progress
// and being updated we add it as a new quest record to
// maintain a proper remote questlog state.
if (questIt == entries.end())
{
auto& newQuest = entries.emplace_back();
newQuest.Id = message.Id;
newQuest.Stage = message.Stage;
if (message.Status == RequestQuestUpdate::Started)
{
spdlog::debug("Started quest: {:X} stage: {}", message.Id.LogFormat(), message.Stage);
notify.Status = NotifyQuestUpdate::Started;
}
else
{
notify.Status = NotifyQuestUpdate::StageUpdate;
}
}
else
{
spdlog::debug("Updated quest: {:X}, stage: {}", message.Id.LogFormat(), message.Id.BaseId, message.Stage);
auto& record = *questIt;
record.Id = message.Id;
record.Stage = message.Stage;
notify.Status = NotifyQuestUpdate::StageUpdate;
}
}
else if (message.Status == RequestQuestUpdate::Stopped)
{
spdlog::debug("Stopped quest: {:X}, stage: {}", message.Id.LogFormat(), message.Id.BaseId, message.Stage);
if (questIt != entries.end())
entries.erase(questIt);
else
spdlog::warn("Unable to delete quest object {:X}", message.Id.LogFormat(), message.Id.BaseId);
notify.Status = NotifyQuestUpdate::Stopped;
}
const auto& partyComponent = acMessage.pPlayer->GetParty();
if (!partyComponent.JoinedPartyId.has_value())
return;
GameServer::Get()->SendToParty(notify, partyComponent, acMessage.GetSender());
}