Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Code/client/Games/Skyrim/Forms/TESQuest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ bool TESQuest::SetStage(uint16_t newStage)
return SetStage(this, newStage);
}

void TESQuest::ScriptSetStage(uint16_t stageIndex)
void TESQuest::ScriptSetStage(uint16_t stageIndex, bool bForce)
{
if (currentStage == stageIndex || IsStageDone(stageIndex))
if ((currentStage == stageIndex || IsStageDone(stageIndex)) && !bForce)
return;

using Quest = TESQuest;
Expand Down
2 changes: 1 addition & 1 deletion Code/client/Games/Skyrim/Forms/TESQuest.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ struct TESQuest : BGSStoryManagerTreeForm
bool EnsureQuestStarted(bool& succeded, bool force);

bool SetStage(uint16_t stage);
void ScriptSetStage(uint16_t stage);
void ScriptSetStage(uint16_t stage, bool bForce = false);
void SetStopped();
};

Expand Down
2 changes: 1 addition & 1 deletion Code/client/Services/Debug/Views/QuestDebugView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ void DebugService::DrawQuestDebugView()
sprintf_s(setStage, std::size(setStage), "Set stage (%d)", pStage->stageIndex);

if (ImGui::Button(setStage))
pQuest->ScriptSetStage(pStage->stageIndex);
pQuest->ScriptSetStage(pStage->stageIndex, true);
}
}

Expand Down
58 changes: 43 additions & 15 deletions Code/client/Services/Generic/QuestService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ BSTEventResult QuestService::OnEvent(const TESQuestStartStopEvent* apEvent, cons
if (ScopedQuestOverride::IsOverriden() || !m_world.Get().GetPartyService().IsInParty())
return BSTEventResult::kOk;

spdlog::info("Quest start/stop event: {:X}", apEvent->formId);
spdlog::info(__FUNCTION__ ": quest start/stop event formId: {:X}", apEvent->formId);

if (TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById(apEvent->formId)))
{
Expand Down Expand Up @@ -105,7 +105,7 @@ BSTEventResult QuestService::OnEvent(const TESQuestStageEvent* apEvent, const Ev
if (ScopedQuestOverride::IsOverriden() || !m_world.Get().GetPartyService().IsInParty())
return BSTEventResult::kOk;

spdlog::info("Quest stage event: {:X}, stage: {}", apEvent->formId, apEvent->stageId);
spdlog::info(__FUNCTION__ ": quest stage formId: {:X}, stage: {}", apEvent->formId, apEvent->stageId);

// there is no reason to even fetch the quest object, since the event provides everything already....
if (TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById(apEvent->formId)))
Expand Down Expand Up @@ -157,13 +157,13 @@ void QuestService::OnQuestUpdate(const NotifyQuestUpdate& aUpdate) noexcept
TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById(formId));
if (!pQuest)
{
spdlog::error("Failed to find quest, base id: {:X}, mod id: {:X}", aUpdate.Id.BaseId, aUpdate.Id.ModId);
spdlog::error(__FUNCTION__ ": failed to find quest, gameId: {:X}, stage: {}", aUpdate.Id.LogFormat(), aUpdate.Stage);
return;
}

if (pQuest->type == TESQuest::Type::None || pQuest->type == TESQuest::Type::Miscellaneous)
{
spdlog::info(__FUNCTION__ ": receiving type none/misc quest update gameId {:X} questStage {} questStatus {} questType {} formId {:X} name {}",
spdlog::info(__FUNCTION__ ": receiving type none/misc quest update gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}",
aUpdate.Id.LogFormat(), aUpdate.Stage, aUpdate.Status,
aUpdate.ClientQuestType, formId, pQuest->fullName.value.AsAscii());
}
Expand All @@ -172,36 +172,64 @@ void QuestService::OnQuestUpdate(const NotifyQuestUpdate& aUpdate) noexcept
switch (aUpdate.Status)
{
case NotifyQuestUpdate::Started:
{
pQuest->ScriptSetStage(aUpdate.Stage);
pQuest->SetActive(true);
if (pQuest->getState() == TESQuest::State::Running) // Supress duplicate or loopback quest starts
{
spdlog::info(__FUNCTION__ ": suppressing duplicate quest start gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}",
aUpdate.Id.LogFormat(), aUpdate.Stage, aUpdate.Status, aUpdate.ClientQuestType, formId, pQuest->fullName.value.AsAscii());
}
else
{
pQuest->ScriptSetStage(aUpdate.Stage);
pQuest->SetActive(true);
spdlog::info(__FUNCTION__ ": remote quest started gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}",
aUpdate.Id.LogFormat(), aUpdate.Stage, aUpdate.Status, aUpdate.ClientQuestType, formId, pQuest->fullName.value.AsAscii());
}
bResult = true;
spdlog::info("Remote quest started: {:X}, stage: {}", formId, aUpdate.Stage);
break;
}
case NotifyQuestUpdate::StageUpdate:
pQuest->ScriptSetStage(aUpdate.Stage);
bResult = true;
spdlog::info("Remote quest updated: {:X}, stage: {}", formId, aUpdate.Stage);
spdlog::info(__FUNCTION__ ": remote quest updated gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}",
aUpdate.Id.LogFormat(), aUpdate.Stage, aUpdate.Status, aUpdate.ClientQuestType, formId, pQuest->fullName.value.AsAscii());
break;
case NotifyQuestUpdate::Stopped:
bResult = StopQuest(formId);
spdlog::info("Remote quest stopped: {:X}, stage: {}", formId, aUpdate.Stage);
if (pQuest->getState() == TESQuest::State::Stopped) // Supress duplicate or loopback quest stop
{
spdlog::info(__FUNCTION__ ": suppressing duplicate quest stop gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}",
aUpdate.Id.LogFormat(), aUpdate.Stage, aUpdate.Status, aUpdate.ClientQuestType, formId, pQuest->fullName.value.AsAscii());
}
else
{
bResult = StopQuest(formId);
spdlog::info(__FUNCTION__ ": remote quest stopped gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}",
aUpdate.Id.LogFormat(), aUpdate.Stage, aUpdate.Status, aUpdate.ClientQuestType, formId, pQuest->fullName.value.AsAscii());
}
bResult = true;
break;
default: break;
}

if (!bResult)
spdlog::error("Failed to update the client quest state, quest: {:X}, stage: {}, status: {}", formId, aUpdate.Stage, aUpdate.Status);
spdlog::error(__FUNCTION__ ": failed to update the client quest state gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}",
aUpdate.Id.LogFormat(), aUpdate.Stage, aUpdate.Status, aUpdate.ClientQuestType, formId, pQuest->fullName.value.AsAscii());
}

bool QuestService::StopQuest(uint32_t aformId)
{
TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById(aformId));
if (pQuest)
{
pQuest->SetActive(false);
pQuest->SetStopped();
if (pQuest->getState() == TESQuest::State::Stopped) // Supress duplicate or loopback quest stop
{
spdlog::info(__FUNCTION__ ": suppressing duplicate quest stop formId: {:X}, questStage: {}, questFlags: {:X}, questType: {}, formId: {:X}, name: {}",
aformId, pQuest->currentStage, static_cast<uint8_t>(pQuest->flags), static_cast<uint16_t>(pQuest->type), aformId, pQuest->fullName.value.AsAscii());
}
else
{
pQuest->SetActive(false);
pQuest->SetStopped();
}

return true;
}

Expand Down
10 changes: 5 additions & 5 deletions Code/server/Services/QuestService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void QuestService::OnQuestChanges(const PacketEvent<RequestQuestUpdate>& acMessa
{
if (!bEnableMiscQuestSync)
return;
spdlog::info("{}: syncing type none/misc quest to party, gameId {:X} questStage {} questStatus {} questType {}",
spdlog::info("{}: syncing type none/misc quest to party, gameId: {:X}, questStage: {}, questStatus: {}; questType: {}",
__FUNCTION__, notify.Id.LogFormat(), notify.Stage, notify.Status, notify.ClientQuestType);
}

Expand All @@ -58,7 +58,7 @@ void QuestService::OnQuestChanges(const PacketEvent<RequestQuestUpdate>& acMessa

if (message.Status == RequestQuestUpdate::Started)
{
spdlog::debug("Started quest: {:X} stage: {}", message.Id.LogFormat(), message.Stage);
spdlog::info("{}: started quest: {:X}, stage: {}", __FUNCTION__, message.Id.LogFormat(), message.Stage);

notify.Status = NotifyQuestUpdate::Started;
}
Expand All @@ -69,7 +69,7 @@ void QuestService::OnQuestChanges(const PacketEvent<RequestQuestUpdate>& acMessa
}
else
{
spdlog::debug("Updated quest: {:X}, stage: {}", message.Id.LogFormat(), message.Id.BaseId, message.Stage);
spdlog::info("{}: updated quest: {:X}, stage: {}", __FUNCTION__, message.Id.LogFormat(), message.Stage);

auto& record = *questIt;
record.Id = message.Id;
Expand All @@ -80,12 +80,12 @@ void QuestService::OnQuestChanges(const PacketEvent<RequestQuestUpdate>& acMessa
}
else if (message.Status == RequestQuestUpdate::Stopped)
{
spdlog::debug("Stopped quest: {:X}, stage: {}", message.Id.LogFormat(), message.Id.BaseId, message.Stage);
spdlog::info("{}: stopped quest: {:X}, stage: {}", __FUNCTION__, message.Id.LogFormat(), message.Stage);

if (questIt != entries.end())
entries.erase(questIt);
else
spdlog::warn("Unable to delete quest object {:X}", message.Id.LogFormat(), message.Id.BaseId);
spdlog::warn("{}: unable to delete quest object {:X}", __FUNCTION__, message.Id.LogFormat());

notify.Status = NotifyQuestUpdate::Stopped;
}
Expand Down
Loading