mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-13 00:00:54 +01:00
98 lines
3.4 KiB
C++
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());
|
|
}
|