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!
