mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-14 08:30:49 +00:00
- Added support for loading named ACS scripts. You can't run them directly at the moment, but
you can still use them for automatically executed script types (like open and enter). - Change the DACSThinker::RunningScripts array into a TMap so that it can catalog the new range of ACS scripts (up to 32767). SVN r3359 (trunk)
This commit is contained in:
parent
ebd115e7ca
commit
9ffb4c40ac
2 changed files with 109 additions and 28 deletions
128
src/p_acs.cpp
128
src/p_acs.cpp
|
@ -1544,6 +1544,27 @@ void FBehavior::LoadScriptsDirectory ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load script names (if any)
|
||||||
|
scripts.b = FindChunk(MAKE_ID('S','N','A','M'));
|
||||||
|
if (scripts.dw != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; i < NumScripts; ++i)
|
||||||
|
{
|
||||||
|
// ACC stores script names as an index into the SNAM chunk, with the first index as
|
||||||
|
// -1 and counting down from there. We convert this from an index into SNAM into
|
||||||
|
// a negative index into the global name table.
|
||||||
|
if (Scripts[i].Number < 0)
|
||||||
|
{
|
||||||
|
const char *str = (const char *)(scripts.b + 8 + scripts.dw[3 + (-Scripts[i].Number - 1)]);
|
||||||
|
FName name(str);
|
||||||
|
Scripts[i].Number = -name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We need to resort scripts, because the new numbers for named scripts likely
|
||||||
|
// do not match the order they were originally in.
|
||||||
|
qsort (Scripts, NumScripts, sizeof(ScriptPtr), SortScripts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int STACK_ARGS FBehavior::SortScripts (const void *a, const void *b)
|
int STACK_ARGS FBehavior::SortScripts (const void *a, const void *b)
|
||||||
|
@ -1621,8 +1642,8 @@ bool FBehavior::IsGood ()
|
||||||
|
|
||||||
const ScriptPtr *FBehavior::FindScript (int script) const
|
const ScriptPtr *FBehavior::FindScript (int script) const
|
||||||
{
|
{
|
||||||
const ScriptPtr *ptr = BinarySearch<ScriptPtr, WORD>
|
const ScriptPtr *ptr = BinarySearch<ScriptPtr, int>
|
||||||
((ScriptPtr *)Scripts, NumScripts, &ScriptPtr::Number, (WORD)script);
|
((ScriptPtr *)Scripts, NumScripts, &ScriptPtr::Number, script);
|
||||||
|
|
||||||
// If the preceding script has the same number, return it instead.
|
// If the preceding script has the same number, return it instead.
|
||||||
// See the note by the script sorting above for why.
|
// See the note by the script sorting above for why.
|
||||||
|
@ -1859,6 +1880,50 @@ void FBehavior::StaticStopMyScripts (AActor *actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// SerializeScriptNumber
|
||||||
|
//
|
||||||
|
// Serializes a script number. If it's negative, it's really a name, so
|
||||||
|
// that will get serialized after it.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static void SerializeScriptNumber(FArchive &arc, int &scriptnum, bool was2byte)
|
||||||
|
{
|
||||||
|
if (SaveVersion < 3359)
|
||||||
|
{
|
||||||
|
if (was2byte)
|
||||||
|
{
|
||||||
|
WORD oldver;
|
||||||
|
arc << oldver;
|
||||||
|
scriptnum = oldver;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arc << scriptnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arc << scriptnum;
|
||||||
|
// If the script number is negative, then it's really a name.
|
||||||
|
// So read/store the name after it.
|
||||||
|
if (scriptnum < 0)
|
||||||
|
{
|
||||||
|
if (arc.IsStoring())
|
||||||
|
{
|
||||||
|
arc.WriteName(FName(ENamedName(-scriptnum)).GetChars());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *nam = arc.ReadName();
|
||||||
|
scriptnum = -FName(nam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- The ACS Interpreter ----//
|
//---- The ACS Interpreter ----//
|
||||||
|
|
||||||
IMPLEMENT_POINTY_CLASS (DACSThinker)
|
IMPLEMENT_POINTY_CLASS (DACSThinker)
|
||||||
|
@ -1880,8 +1945,7 @@ DACSThinker::DACSThinker ()
|
||||||
ActiveThinker = this;
|
ActiveThinker = this;
|
||||||
Scripts = NULL;
|
Scripts = NULL;
|
||||||
LastScript = NULL;
|
LastScript = NULL;
|
||||||
for (int i = 0; i < 1000; i++)
|
RunningScripts.Clear();
|
||||||
RunningScripts[i] = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1893,27 +1957,34 @@ DACSThinker::~DACSThinker ()
|
||||||
|
|
||||||
void DACSThinker::Serialize (FArchive &arc)
|
void DACSThinker::Serialize (FArchive &arc)
|
||||||
{
|
{
|
||||||
|
int scriptnum;
|
||||||
|
|
||||||
Super::Serialize (arc);
|
Super::Serialize (arc);
|
||||||
arc << Scripts << LastScript;
|
arc << Scripts << LastScript;
|
||||||
if (arc.IsStoring ())
|
if (arc.IsStoring ())
|
||||||
{
|
{
|
||||||
WORD i;
|
ScriptMap::Iterator it(RunningScripts);
|
||||||
for (i = 0; i < 1000; i++)
|
ScriptMap::Pair *pair;
|
||||||
|
|
||||||
|
while (it.NextPair(pair))
|
||||||
{
|
{
|
||||||
if (RunningScripts[i])
|
assert(pair->Value != NULL);
|
||||||
arc << RunningScripts[i] << i;
|
arc << pair->Value;
|
||||||
|
scriptnum = pair->Key;
|
||||||
|
SerializeScriptNumber(arc, scriptnum, true);
|
||||||
}
|
}
|
||||||
DLevelScript *nilptr = NULL;
|
DLevelScript *nilptr = NULL;
|
||||||
arc << nilptr;
|
arc << nilptr;
|
||||||
}
|
}
|
||||||
else
|
else // Loading
|
||||||
{
|
{
|
||||||
WORD scriptnum;
|
|
||||||
DLevelScript *script = NULL;
|
DLevelScript *script = NULL;
|
||||||
|
RunningScripts.Clear();
|
||||||
|
|
||||||
arc << script;
|
arc << script;
|
||||||
while (script)
|
while (script)
|
||||||
{
|
{
|
||||||
arc << scriptnum;
|
SerializeScriptNumber(arc, scriptnum, true);
|
||||||
RunningScripts[scriptnum] = script;
|
RunningScripts[scriptnum] = script;
|
||||||
arc << script;
|
arc << script;
|
||||||
}
|
}
|
||||||
|
@ -1975,8 +2046,9 @@ void DLevelScript::Serialize (FArchive &arc)
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
Super::Serialize (arc);
|
Super::Serialize (arc);
|
||||||
arc << next << prev
|
arc << next << prev;
|
||||||
<< script;
|
|
||||||
|
SerializeScriptNumber(arc, script, false);
|
||||||
|
|
||||||
arc << state
|
arc << state
|
||||||
<< statedata
|
<< statedata
|
||||||
|
@ -3713,13 +3785,13 @@ int DLevelScript::RunScript ()
|
||||||
|
|
||||||
case SCRIPT_ScriptWaitPre:
|
case SCRIPT_ScriptWaitPre:
|
||||||
// Wait for a script to start running, then enter state scriptwait
|
// Wait for a script to start running, then enter state scriptwait
|
||||||
if (controller->RunningScripts[statedata])
|
if (controller->RunningScripts.CheckKey(statedata) != NULL)
|
||||||
state = SCRIPT_ScriptWait;
|
state = SCRIPT_ScriptWait;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCRIPT_ScriptWait:
|
case SCRIPT_ScriptWait:
|
||||||
// Wait for a script to stop running, then enter state running
|
// Wait for a script to stop running, then enter state running
|
||||||
if (controller->RunningScripts[statedata])
|
if (controller->RunningScripts.CheckKey(statedata) != NULL)
|
||||||
return resultValue;
|
return resultValue;
|
||||||
|
|
||||||
state = SCRIPT_Running;
|
state = SCRIPT_Running;
|
||||||
|
@ -5016,7 +5088,7 @@ int DLevelScript::RunScript ()
|
||||||
|
|
||||||
case PCD_SCRIPTWAIT:
|
case PCD_SCRIPTWAIT:
|
||||||
statedata = STACK(1);
|
statedata = STACK(1);
|
||||||
if (controller->RunningScripts[statedata])
|
if (controller->RunningScripts.CheckKey(statedata) != NULL)
|
||||||
state = SCRIPT_ScriptWait;
|
state = SCRIPT_ScriptWait;
|
||||||
else
|
else
|
||||||
state = SCRIPT_ScriptWaitPre;
|
state = SCRIPT_ScriptWaitPre;
|
||||||
|
@ -6960,8 +7032,12 @@ int DLevelScript::RunScript ()
|
||||||
if (state == SCRIPT_PleaseRemove)
|
if (state == SCRIPT_PleaseRemove)
|
||||||
{
|
{
|
||||||
Unlink ();
|
Unlink ();
|
||||||
if (controller->RunningScripts[script] == this)
|
DLevelScript **running;
|
||||||
controller->RunningScripts[script] = NULL;
|
if ((running = controller->RunningScripts.CheckKey(script)) != NULL &&
|
||||||
|
*running == this)
|
||||||
|
{
|
||||||
|
controller->RunningScripts.Remove(script);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -6977,13 +7053,14 @@ static DLevelScript *P_GetScriptGoing (AActor *who, line_t *where, int num, cons
|
||||||
bool backSide, int arg0, int arg1, int arg2, int always)
|
bool backSide, int arg0, int arg1, int arg2, int always)
|
||||||
{
|
{
|
||||||
DACSThinker *controller = DACSThinker::ActiveThinker;
|
DACSThinker *controller = DACSThinker::ActiveThinker;
|
||||||
|
DLevelScript **running;
|
||||||
|
|
||||||
if (controller && !always && controller->RunningScripts[num])
|
if (controller && !always && (running = controller->RunningScripts.CheckKey(num)) != NULL)
|
||||||
{
|
{
|
||||||
if (controller->RunningScripts[num]->GetState () == DLevelScript::SCRIPT_Suspended)
|
if ((*running)->GetState() == DLevelScript::SCRIPT_Suspended)
|
||||||
{
|
{
|
||||||
controller->RunningScripts[num]->SetState (DLevelScript::SCRIPT_Running);
|
(*running)->SetState(DLevelScript::SCRIPT_Running);
|
||||||
return controller->RunningScripts[num];
|
return *running;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -7044,9 +7121,12 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr
|
||||||
static void SetScriptState (int script, DLevelScript::EScriptState state)
|
static void SetScriptState (int script, DLevelScript::EScriptState state)
|
||||||
{
|
{
|
||||||
DACSThinker *controller = DACSThinker::ActiveThinker;
|
DACSThinker *controller = DACSThinker::ActiveThinker;
|
||||||
|
DLevelScript **running;
|
||||||
|
|
||||||
if (controller != NULL && controller->RunningScripts[script])
|
if (controller != NULL && (running = controller->RunningScripts.CheckKey(script)) != NULL)
|
||||||
controller->RunningScripts[script]->SetState (state);
|
{
|
||||||
|
(*running)->SetState (state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_DoDeferedScripts ()
|
void P_DoDeferedScripts ()
|
||||||
|
|
|
@ -76,18 +76,18 @@ void P_ClearACSVars(bool);
|
||||||
// The in-memory version
|
// The in-memory version
|
||||||
struct ScriptPtr
|
struct ScriptPtr
|
||||||
{
|
{
|
||||||
WORD Number;
|
int Number;
|
||||||
|
DWORD Address;
|
||||||
BYTE Type;
|
BYTE Type;
|
||||||
BYTE ArgCount;
|
BYTE ArgCount;
|
||||||
WORD VarCount;
|
WORD VarCount;
|
||||||
WORD Flags;
|
WORD Flags;
|
||||||
DWORD Address;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The present ZDoom version
|
// The present ZDoom version
|
||||||
struct ScriptPtr3
|
struct ScriptPtr3
|
||||||
{
|
{
|
||||||
WORD Number;
|
SWORD Number;
|
||||||
BYTE Type;
|
BYTE Type;
|
||||||
BYTE ArgCount;
|
BYTE ArgCount;
|
||||||
DWORD Address;
|
DWORD Address;
|
||||||
|
@ -747,7 +747,8 @@ public:
|
||||||
void Serialize (FArchive &arc);
|
void Serialize (FArchive &arc);
|
||||||
void Tick ();
|
void Tick ();
|
||||||
|
|
||||||
DLevelScript *RunningScripts[1000]; // Array of all synchronous scripts
|
typedef TMap<int, DLevelScript *> ScriptMap;
|
||||||
|
ScriptMap RunningScripts; // Array of all synchronous scripts
|
||||||
static TObjPtr<DACSThinker> ActiveThinker;
|
static TObjPtr<DACSThinker> ActiveThinker;
|
||||||
|
|
||||||
void DumpScriptStatus();
|
void DumpScriptStatus();
|
||||||
|
|
Loading…
Reference in a new issue