- fix handling of the global script in FraggleScript.

Depending on serialization order is not a good idea here, so now it's no longer stored as a parent in the main level script but explicitly checked for when looking for a variable.
This commit is contained in:
Christoph Oelckers 2019-01-27 21:03:25 +01:00
parent 4d98c10ea3
commit 11c453a71f
5 changed files with 25 additions and 22 deletions

View file

@ -31,6 +31,7 @@
/* includes ************************/ /* includes ************************/
#include "t_script.h" #include "t_script.h"
#include "g_levellocals.h"
#define evaluate_leftnright(a, b, c) {\ #define evaluate_leftnright(a, b, c) {\
@ -84,7 +85,7 @@ void FParser::OPequals(svalue_t &result, int start, int n, int stop)
{ {
DFsVariable *var; DFsVariable *var;
var = Script->FindVariable(Tokens[start]); var = Script->FindVariable(Tokens[start], Level->FraggleScriptThinker->GlobalScript);
if(var) if(var)
{ {
@ -478,7 +479,7 @@ void FParser::OPincrement(svalue_t &result, int start, int n, int stop)
{ {
DFsVariable *var; DFsVariable *var;
var = Script->FindVariable(Tokens[stop]); var = Script->FindVariable(Tokens[stop], Level->FraggleScriptThinker->GlobalScript);
if(!var) if(!var)
{ {
script_error("unknown variable '%s'\n", Tokens[stop]); script_error("unknown variable '%s'\n", Tokens[stop]);
@ -503,7 +504,7 @@ void FParser::OPincrement(svalue_t &result, int start, int n, int stop)
svalue_t newvalue; svalue_t newvalue;
DFsVariable *var; DFsVariable *var;
var = Script->FindVariable(Tokens[start]); var = Script->FindVariable(Tokens[start], Level->FraggleScriptThinker->GlobalScript);
if(!var) if(!var)
{ {
script_error("unknown variable '%s'\n", Tokens[start]); script_error("unknown variable '%s'\n", Tokens[start]);
@ -541,7 +542,7 @@ void FParser::OPdecrement(svalue_t &result, int start, int n, int stop)
{ {
DFsVariable *var; DFsVariable *var;
var = Script->FindVariable(Tokens[stop]); var = Script->FindVariable(Tokens[stop], Level->FraggleScriptThinker->GlobalScript);
if(!var) if(!var)
{ {
script_error("unknown variable '%s'\n", Tokens[stop]); script_error("unknown variable '%s'\n", Tokens[stop]);
@ -567,7 +568,7 @@ void FParser::OPdecrement(svalue_t &result, int start, int n, int stop)
svalue_t newvalue; svalue_t newvalue;
DFsVariable *var; DFsVariable *var;
var = Script->FindVariable(Tokens[start]); var = Script->FindVariable(Tokens[start], Level->FraggleScriptThinker->GlobalScript);
if(!var) if(!var)
{ {
script_error("unknown variable '%s'\n", Tokens[start]); script_error("unknown variable '%s'\n", Tokens[start]);

View file

@ -34,7 +34,7 @@
#include <stdarg.h> #include <stdarg.h>
#include "t_script.h" #include "t_script.h"
#include "v_text.h" #include "v_text.h"
#include "g_levellocals.h"""
CVAR(Bool, script_debug, false, 0) CVAR(Bool, script_debug, false, 0)
@ -561,7 +561,7 @@ void FParser::SimpleEvaluate(svalue_t &returnvar, int n)
break; break;
case name_: case name_:
var = Script->FindVariable(Tokens[n]); var = Script->FindVariable(Tokens[n], Level->FraggleScriptThinker->GlobalScript);
if(!var) if(!var)
{ {
script_error("unknown variable '%s'\n", Tokens[n]); script_error("unknown variable '%s'\n", Tokens[n]);

View file

@ -176,8 +176,6 @@ void DFsScript::OnDestroy()
void DFsScript::Serialize(FSerializer &arc) void DFsScript::Serialize(FSerializer &arc)
{ {
Super::Serialize(arc); Super::Serialize(arc);
// don't save a reference to the global script, which contains unserializable data.
if (parent == level.FraggleScriptThinker->GlobalScript) parent = nullptr;
arc("data", data) arc("data", data)
("scriptnum", scriptnum) ("scriptnum", scriptnum)
@ -188,8 +186,6 @@ void DFsScript::Serialize(FSerializer &arc)
.Array("sections", sections, SECTIONSLOTS) .Array("sections", sections, SECTIONSLOTS)
.Array("variables", variables, VARIABLESLOTS) .Array("variables", variables, VARIABLESLOTS)
.Array("children", children, MAXSCRIPTS); .Array("children", children, MAXSCRIPTS);
if (parent == nullptr) parent = level.FraggleScriptThinker->GlobalScript;
} }
//========================================================================== //==========================================================================
@ -200,7 +196,7 @@ void DFsScript::Serialize(FSerializer &arc)
// //
//========================================================================== //==========================================================================
void DFsScript::ParseScript(char *position) void DFsScript::ParseScript(char *position, AActor **pTrigger)
{ {
if (position == nullptr) if (position == nullptr)
{ {
@ -215,7 +211,7 @@ void DFsScript::ParseScript(char *position)
return; return;
} }
level.FraggleScriptThinker->trigger_obj = trigger; // set trigger *pTrigger = trigger; // set trigger variable.
try try
{ {
@ -387,7 +383,7 @@ void DFraggleThinker::Construct()
RunningScripts = Create<DRunningScript>(); RunningScripts = Create<DRunningScript>();
GC::WriteBarrier(this, RunningScripts); GC::WriteBarrier(this, RunningScripts);
LevelScript = Create<DFsScript>(); LevelScript = Create<DFsScript>();
LevelScript->parent = GlobalScript; LevelScript->parent = nullptr;
GC::WriteBarrier(this, LevelScript); GC::WriteBarrier(this, LevelScript);
} }
@ -465,10 +461,10 @@ bool DFraggleThinker::wait_finished(DRunningScript *script)
case wt_tagwait: case wt_tagwait:
{ {
int secnum; int secnum;
auto itr = level.GetSectorTagIterator(script->wait_data); auto itr = Level->GetSectorTagIterator(script->wait_data);
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
sector_t *sec = &level.sectors[secnum]; sector_t *sec = &Level->sectors[secnum];
if(sec->floordata || sec->ceilingdata || sec->lightingdata) if(sec->floordata || sec->ceilingdata || sec->lightingdata)
return false; // not finished return false; // not finished
} }
@ -532,7 +528,7 @@ void DFraggleThinker::Tick()
next = current->next; // save before freeing next = current->next; // save before freeing
// continue the script // continue the script
current->script->ParseScript (current->script->data + current->save_point); current->script->ParseScript (current->script->data + current->save_point, &trigger_obj);
// free // free
current->Destroy(); current->Destroy();
@ -623,7 +619,7 @@ void T_PreprocessScripts(FLevelLocals *Level)
th->LevelScript->trigger = players[0].mo; th->LevelScript->trigger = players[0].mo;
th->LevelScript->Preprocess(); th->LevelScript->Preprocess();
th->LevelScript->ParseScript(); th->LevelScript->ParseScript(nullptr, &th->trigger_obj);
} }
} }

View file

@ -341,7 +341,7 @@ public:
void NewFunction(const char *name, void (FParser::*handler)()); void NewFunction(const char *name, void (FParser::*handler)());
DFsVariable *VariableForName(const char *name); DFsVariable *VariableForName(const char *name);
DFsVariable *FindVariable(const char *name); DFsVariable *FindVariable(const char *name, DFsScript *global);
void ClearVariables(bool complete= false); void ClearVariables(bool complete= false);
DFsVariable *NewLabel(char *labelptr); DFsVariable *NewLabel(char *labelptr);
char *LabelValue(const svalue_t &v); char *LabelValue(const svalue_t &v);
@ -363,7 +363,7 @@ public:
void DryRunScript(); void DryRunScript();
void Preprocess(); void Preprocess();
void ParseInclude(char *lumpname); void ParseInclude(char *lumpname);
void ParseScript(char *rover = NULL); void ParseScript(char *rover, AActor **pTrigger);
void ParseData(char *rover, char *data, char *end); void ParseData(char *rover, char *data, char *end);
}; };

View file

@ -364,7 +364,7 @@ DFsVariable *DFsScript::VariableForName(const char *name)
// //
//========================================================================== //==========================================================================
DFsVariable *DFsScript::FindVariable(const char *name) DFsVariable *DFsScript::FindVariable(const char *name, DFsScript *GlobalScript)
{ {
DFsVariable *var; DFsVariable *var;
DFsScript *current = this; DFsScript *current = this;
@ -374,7 +374,13 @@ DFsVariable *DFsScript::FindVariable(const char *name)
// check this script // check this script
if ((var = current->VariableForName(name))) if ((var = current->VariableForName(name)))
return var; return var;
current = current->parent; // try the parent of this one
// Since the global script cannot be serialized, we cannot store a pointer to it, because this cannot be safely restored during deserialization.
// To compensate we need to check the relationship explicitly here.
if (current->parent == nullptr && current != GlobalScript)
current = GlobalScript;
else
current = current->parent; // try the parent of this one
} }
return NULL; // no variable return NULL; // no variable