[FIX] Multiple TAKE quests on the same NPC – wrong QUEST_SELECT / stuck cinematic bars
Scris: Mie Sep 30, 2026 7:13 pm
Descrierea problemei
Problema apare atunci când avem două sau mai multe questuri compilate pentru același eveniment take al unui NPC.
Exemplu:
Unul dintre questuri deschide un dialog folosind select(), însă după el motorul de quest execută și următorul fișier .start.
Clientul continuă să afișeze întrebarea, dar serverul nu mai are questul suspendat în SUSPEND_STATE_SELECT.
La apăsarea unei opțiuni apare:
În anumite cazuri, fereastra dispare, dar benzile cinematice negre rămân pe ecran până la un click pe NPC sau până la relog.
Cauza
În NPC::HandleEvent(), toate questurile asociate evenimentului sunt executate succesiv:
Dacă primul quest ajunge la:
ExecuteQuestScript() întoarce true, indicând că questul a rămas suspendat și așteaptă răspunsul jucătorului.
Valoarea returnată este însă ignorată, iar motorul execută următorul handler take.
Al doilea quest înlocuiește starea questului activ. Chiar dacă nu îndeplinește nicio condiție și se termină imediat, dialogul primului quest rămâne afișat pe client.
Rezultatul este o desincronizare:
Rezolvare
Deschide:
Caută funcția:
Modificarea buclei fMatch
Caută:
Înlocuiește cu:
Modificarea buclei fMiss
Caută:
Înlocuiește cu:
Trebuie modificate ambele bucle.
fMatch tratează questurile deja existente în starea jucătorului, iar fMiss tratează questurile pornite pentru prima dată. Dacă este modificată doar una dintre ele, problema poate apărea diferit după relog sau după prima utilizare.
Cum funcționează fixul
ExecuteQuestScript() întoarce true atunci când questul rămâne suspendat într-una dintre următoarele stări:
În acel moment, HandleEvent() se oprește și nu mai execută alte questuri pentru aceeași acțiune.
Scripturile care se termină imediat și nu așteaptă un răspuns întorc false, iar procesarea poate continua către următorul handler.
Prin urmare, fixul:
- permite mai multor questuri take să fie înregistrate pe același NPC;
- protejează questul care a deschis un dialog interactiv;
- previne suprascrierea stării active;
- elimină eroarea wrong QUEST_SELECT request;
- previne blocarea interfeței cinematice.
Dupa modificarea sursei, nu uitati sa o recompilati. Mult succes!
Problema apare atunci când avem două sau mai multe questuri compilate pentru același eveniment take al unui NPC.
Exemplu:
Cod: Selectaţi tot
object/9009/take/fisher.start
object/9009/take/eveniment_pescar.startClientul continuă să afișeze întrebarea, dar serverul nu mai are questul suspendat în SUSPEND_STATE_SELECT.
La apăsarea unei opțiuni apare:
Cod: Selectaţi tot
QUEST ScriptAnswer pid 11475 answer 0
Select: wrong QUEST_SELECT request! : 11475Cauza
În NPC::HandleEvent(), toate questurile asociate evenimentului sunt executate succesiv:
Cod: Selectaţi tot
CQuestManager::ExecuteQuestScript(...);Cod: Selectaţi tot
select(...)Valoarea returnată este însă ignorată, iar motorul execută următorul handler take.
Al doilea quest înlocuiește starea questului activ. Chiar dacă nu îndeplinește nicio condiție și se termină imediat, dialogul primului quest rămâne afișat pe client.
Rezultatul este o desincronizare:
Cod: Selectaţi tot
Client: așteaptă alegerea din select()
Server: nu mai are un quest în SUSPEND_STATE_SELECTDeschide:
Cod: Selectaţi tot
game/src/questnpc.cppCod: Selectaţi tot
bool NPC::HandleEvent(PC& pc, int EventIndex)Caută:
Cod: Selectaţi tot
CQuestManager::ExecuteQuestScript(pc, fMatch.vdwQuesIndices[i], fMatch.viPCStates[i],
fMatch.vcodes[i], fMatch.vcode_sizes[i]);Cod: Selectaţi tot
if (CQuestManager::ExecuteQuestScript(
pc,
fMatch.vdwQuesIndices[i],
fMatch.viPCStates[i],
fMatch.vcodes[i],
fMatch.vcode_sizes[i]))
{
return true;
}Caută:
Cod: Selectaţi tot
CQuestManager::ExecuteQuestScript(
pc,
fMiss.vdwNewStartQuestIndices[i],
0,
script.GetCode(),
script.GetSize());Cod: Selectaţi tot
if (CQuestManager::ExecuteQuestScript(
pc,
fMiss.vdwNewStartQuestIndices[i],
0,
script.GetCode(),
script.GetSize()))
{
return true;
}fMatch tratează questurile deja existente în starea jucătorului, iar fMiss tratează questurile pornite pentru prima dată. Dacă este modificată doar una dintre ele, problema poate apărea diferit după relog sau după prima utilizare.
Cum funcționează fixul
ExecuteQuestScript() întoarce true atunci când questul rămâne suspendat într-una dintre următoarele stări:
Cod: Selectaţi tot
select
wait
input
confirm
select_itemScripturile care se termină imediat și nu așteaptă un răspuns întorc false, iar procesarea poate continua către următorul handler.
Prin urmare, fixul:
- permite mai multor questuri take să fie înregistrate pe același NPC;
- protejează questul care a deschis un dialog interactiv;
- previne suprascrierea stării active;
- elimină eroarea wrong QUEST_SELECT request;
- previne blocarea interfeței cinematice.
Dupa modificarea sursei, nu uitati sa o recompilati. Mult succes!