@@ -57,8 +57,6 @@ BSTEventResult QuestService::OnEvent(const TESQuestStartStopEvent* apEvent, cons
5757 if (ScopedQuestOverride::IsOverriden () || !m_world.Get ().GetPartyService ().IsInParty ())
5858 return BSTEventResult::kOk ;
5959
60- spdlog::info (" Quest start/stop event: {:X}" , apEvent->formId );
61-
6260 if (TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById (apEvent->formId )))
6361 {
6462 if (IsNonSyncableQuest (pQuest))
@@ -72,15 +70,21 @@ BSTEventResult QuestService::OnEvent(const TESQuestStartStopEvent* apEvent, cons
7270 auto & modSys = m_world.GetModSystem ();
7371 if (modSys.GetServerModId (pQuest->formID , Id))
7472 {
75- spdlog::info (__FUNCTION__ " : queuing type none/misc quest gameId {:X} questStage {} questStatus {} questType {} formId {:X} name {}" ,
76- Id.LogFormat (), pQuest->currentStage , pQuest->IsStopped () ? RequestQuestUpdate::Stopped : RequestQuestUpdate::Started,
77- static_cast <std::underlying_type_t <TESQuest::Type>>(pQuest->type ),
78- pQuest->formID , pQuest->fullName .value .AsAscii ());
73+ spdlog::info (__FUNCTION__ " : queuing type none/misc quest {} gameId {:X} questStage {} questType {} formId {:X} name {}" ,
74+ pQuest->IsStopped () ? " stop" : " start" , Id.LogFormat (), pQuest->currentStage ,
75+ static_cast <std::underlying_type_t <TESQuest::Type>>(pQuest->type ), pQuest->formID , pQuest->fullName .value .AsAscii ());
7976 }
8077 }
81-
82- m_world.GetRunner ().Queue (
83- [&, formId = pQuest->formID , stageId = pQuest->currentStage , stopped = pQuest->IsStopped (), type = pQuest->type ]()
78+
79+ spdlog::info (__FUNCTION__ " : quest {} formId: {:X}, questStage: {}, questType: {}, name: {}" ,
80+ pQuest->IsStopped () ? " stopped" : " started" ,
81+ pQuest->formID ,
82+ pQuest->currentStage ,
83+ static_cast <std::underlying_type_t <TESQuest::Type>>(pQuest->type ),
84+ pQuest->fullName .value .AsAscii ());
85+
86+ m_world.GetRunner ().Queue ([&, formId = pQuest->formID , stageId = pQuest->currentStage ,
87+ stopped = pQuest->IsStopped (), type = pQuest->type ]()
8488 {
8589 GameId Id;
8690 auto & modSys = m_world.GetModSystem ();
@@ -91,7 +95,6 @@ BSTEventResult QuestService::OnEvent(const TESQuestStartStopEvent* apEvent, cons
9195 update.Stage = stageId;
9296 update.Status = stopped ? RequestQuestUpdate::Stopped : RequestQuestUpdate::Started;
9397 update.ClientQuestType = static_cast <std::underlying_type_t <TESQuest::Type>>(type);
94-
9598 m_world.GetTransport ().Send (update);
9699 }
97100 });
@@ -105,9 +108,6 @@ BSTEventResult QuestService::OnEvent(const TESQuestStageEvent* apEvent, const Ev
105108 if (ScopedQuestOverride::IsOverriden () || !m_world.Get ().GetPartyService ().IsInParty ())
106109 return BSTEventResult::kOk ;
107110
108- spdlog::info (" Quest stage event: {:X}, stage: {}" , apEvent->formId , apEvent->stageId );
109-
110- // there is no reason to even fetch the quest object, since the event provides everything already....
111111 if (TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById (apEvent->formId )))
112112 {
113113 if (IsNonSyncableQuest (pQuest))
@@ -121,14 +121,15 @@ BSTEventResult QuestService::OnEvent(const TESQuestStageEvent* apEvent, const Ev
121121 auto & modSys = m_world.GetModSystem ();
122122 if (modSys.GetServerModId (pQuest->formID , Id))
123123 {
124- spdlog::info (__FUNCTION__ " : queuing type none/misc quest gameId {:X} questStage {} questStatus {} questType {} formId {:X} name {}" ,
125- Id.LogFormat (), pQuest->currentStage ,
126- RequestQuestUpdate::StageUpdate,
127- static_cast <std::underlying_type_t <TESQuest::Type>>(pQuest->type ),
124+ spdlog::info (__FUNCTION__ " : queuing type none/misc quest update gameId {:X} questStage {} questType {} formId {:X} name {}" ,
125+ Id.LogFormat (), pQuest->currentStage , static_cast <std::underlying_type_t <TESQuest::Type>>(pQuest->type ),
128126 pQuest->formID , pQuest->fullName .value .AsAscii ());
129127 }
130128 }
131129
130+ spdlog::info (__FUNCTION__ " : quest updated formId: {:X}, questStage: {}, questType: {}, name: {}" ,
131+ pQuest->formID , pQuest->currentStage , static_cast <std::underlying_type_t <TESQuest::Type>>(pQuest->type ), pQuest->fullName .value .AsAscii ());
132+
132133 m_world.GetRunner ().Queue (
133134 [&, formId = apEvent->formId , stageId = apEvent->stageId , type = pQuest->type ]()
134135 {
@@ -141,7 +142,6 @@ BSTEventResult QuestService::OnEvent(const TESQuestStageEvent* apEvent, const Ev
141142 update.Stage = stageId;
142143 update.Status = RequestQuestUpdate::StageUpdate;
143144 update.ClientQuestType = static_cast <std::underlying_type_t <TESQuest::Type>>(type);
144-
145145 m_world.GetTransport ().Send (update);
146146 }
147147 });
@@ -157,7 +157,7 @@ void QuestService::OnQuestUpdate(const NotifyQuestUpdate& aUpdate) noexcept
157157 TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById (formId));
158158 if (!pQuest)
159159 {
160- spdlog::error (" Failed to find quest, base id : {:X}, mod id : {:X }" , aUpdate.Id .BaseId , aUpdate.Id . ModId );
160+ spdlog::error (__FUNCTION__ " : failed to find quest, gameId : {:X}, stage : {}" , aUpdate.Id .LogFormat () , aUpdate.Stage );
161161 return ;
162162 }
163163
@@ -169,39 +169,64 @@ void QuestService::OnQuestUpdate(const NotifyQuestUpdate& aUpdate) noexcept
169169 }
170170
171171 bool bResult = false ;
172+ bool bRunning = pQuest->getState () == TESQuest::State::Running;
172173 switch (aUpdate.Status )
173174 {
174175 case NotifyQuestUpdate::Started:
175- {
176- pQuest->ScriptSetStage (aUpdate.Stage );
177- pQuest->SetActive (true );
176+ if (bRunning)
177+ {
178+ spdlog::info (__FUNCTION__ " : suppressing duplicate quest start gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}" ,
179+ aUpdate.Id .LogFormat (), aUpdate.Stage , aUpdate.Status , aUpdate.ClientQuestType , formId, pQuest->fullName .value .AsAscii ());
180+ }
181+ else
182+ {
183+ spdlog::info (__FUNCTION__ " : quest started remotely gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}" ,
184+ aUpdate.Id .LogFormat (), aUpdate.Stage , aUpdate.Status , aUpdate.ClientQuestType , formId, pQuest->fullName .value .AsAscii ());
185+ pQuest->ScriptSetStage (aUpdate.Stage );
186+ pQuest->SetActive (true );
187+ }
178188 bResult = true ;
179189 spdlog::info (" Remote quest started: {:X}, stage: {}" , formId, aUpdate.Stage );
180190 break ;
181- }
191+
182192 case NotifyQuestUpdate::StageUpdate:
193+ spdlog::info (__FUNCTION__ " : quest updated remotely gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}" ,
194+ aUpdate.Id .LogFormat (), aUpdate.Stage , aUpdate.Status , aUpdate.ClientQuestType , formId, pQuest->fullName .value .AsAscii ());
195+
183196 pQuest->ScriptSetStage (aUpdate.Stage );
184197 bResult = true ;
185- spdlog::info (" Remote quest updated: {:X}, stage: {}" , formId, aUpdate.Stage );
186198 break ;
199+
187200 case NotifyQuestUpdate::Stopped:
201+ spdlog::info (__FUNCTION__ " : quest stopped remotely gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}" ,
202+ aUpdate.Id .LogFormat (), aUpdate.Stage , aUpdate.Status , aUpdate.ClientQuestType , formId, pQuest->fullName .value .AsAscii ());
188203 bResult = StopQuest (formId);
189- spdlog::info (" Remote quest stopped: {:X}, stage: {}" , formId, aUpdate.Stage );
190204 break ;
205+
191206 default : break ;
192207 }
193208
194209 if (!bResult)
195- spdlog::error (" Failed to update the client quest state, quest: {:X}, stage: {}, status: {}" , formId, aUpdate.Stage , aUpdate.Status );
210+ spdlog::error (__FUNCTION__ " : failed to update the client quest state gameId: {:X}, questStage: {}, questStatus: {}, questType: {}, formId: {:X}, name: {}" ,
211+ aUpdate.Id .LogFormat (), aUpdate.Stage , aUpdate.Status , aUpdate.ClientQuestType , formId, pQuest->fullName .value .AsAscii ());
196212}
197213
198214bool QuestService::StopQuest (uint32_t aformId)
199215{
200216 TESQuest* pQuest = Cast<TESQuest>(TESForm::GetById (aformId));
201217 if (pQuest)
202218 {
203- pQuest->SetActive (false );
204- pQuest->SetStopped ();
219+ if (pQuest->getState () == TESQuest::State::Stopped) // Supress duplicate or loopback quest stop
220+ {
221+ spdlog::info (__FUNCTION__ " : suppressing duplicate quest stop formId: {:X}, questStage: {}, questFlags: {:X}, questType: {}, formId: {:X}, name: {}" ,
222+ aformId, pQuest->currentStage , static_cast <uint8_t >(pQuest->flags ), static_cast <uint16_t >(pQuest->type ), aformId, pQuest->fullName .value .AsAscii ());
223+ }
224+ else
225+ {
226+ pQuest->SetActive (false );
227+ pQuest->SetStopped ();
228+ }
229+
205230 return true ;
206231 }
207232
0 commit comments