mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 14:22:13 +00:00
- reworked the lock code to remove the 255 locks limit and to allow it to automatically deinitialize.
This commit is contained in:
parent
982c622367
commit
17e053499e
5 changed files with 81 additions and 93 deletions
|
@ -4048,8 +4048,6 @@ void FParser::SF_ScriptRunning()
|
||||||
|
|
||||||
void DFraggleThinker::InitFunctions()
|
void DFraggleThinker::InitFunctions()
|
||||||
{
|
{
|
||||||
cycle_t clock;
|
|
||||||
|
|
||||||
for(unsigned i=0;i<countof(ActorNames_init);i++)
|
for(unsigned i=0;i<countof(ActorNames_init);i++)
|
||||||
{
|
{
|
||||||
ActorTypes[i]=PClass::FindActor(ActorNames_init[i]);
|
ActorTypes[i]=PClass::FindActor(ActorNames_init[i]);
|
||||||
|
|
|
@ -104,22 +104,11 @@ struct Keygroup
|
||||||
|
|
||||||
struct Lock
|
struct Lock
|
||||||
{
|
{
|
||||||
TArray<Keygroup *> keylist;
|
TArray<Keygroup> keylist;
|
||||||
TArray<FSoundID> locksound;
|
TArray<FSoundID> locksound;
|
||||||
FString Message;
|
FString Message;
|
||||||
FString RemoteMsg;
|
FString RemoteMsg;
|
||||||
int rgb;
|
int rgb = 0;
|
||||||
|
|
||||||
Lock()
|
|
||||||
{
|
|
||||||
rgb=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Lock()
|
|
||||||
{
|
|
||||||
for(unsigned int i=0;i<keylist.Size();i++) delete keylist[i];
|
|
||||||
keylist.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check(AActor * owner)
|
bool check(AActor * owner)
|
||||||
{
|
{
|
||||||
|
@ -138,25 +127,21 @@ struct Lock
|
||||||
}
|
}
|
||||||
else for(unsigned int i=0;i<keylist.Size();i++)
|
else for(unsigned int i=0;i<keylist.Size();i++)
|
||||||
{
|
{
|
||||||
if (!keylist[i]->check(owner)) return false;
|
if (!keylist[i].check(owner)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static TMap<int, Lock> Locks;
|
||||||
|
static bool keysdone = false; // have the locks been initialized?
|
||||||
|
static TArray<PClassActor *> KeyTypes; // List of all keys sorted by lock. This is for use by the status bar to draw ordered key lists.
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
static Lock *locks[256]; // all valid locks
|
|
||||||
static bool keysdone=false; // have the locks been initialized?
|
|
||||||
static int currentnumber; // number to be assigned to next key
|
|
||||||
static bool ignorekey; // set to true when the current lock is not being used
|
|
||||||
static TArray<PClassActor *> KeyTypes; // List of all keys sorted by lock.
|
|
||||||
|
|
||||||
static void ClearLocks();
|
|
||||||
|
|
||||||
static const char * keywords_lock[]={
|
static const char * keywords_lock[]={
|
||||||
"ANY",
|
"ANY",
|
||||||
"MESSAGE",
|
"MESSAGE",
|
||||||
|
@ -171,7 +156,7 @@ static const char * keywords_lock[]={
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc)
|
static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc, bool ignorekey, int ¤tnumber)
|
||||||
{
|
{
|
||||||
if (mi)
|
if (mi)
|
||||||
{
|
{
|
||||||
|
@ -208,26 +193,18 @@ static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
static Keygroup *ParseKeygroup(FScanner &sc)
|
static void ParseKeygroup(Keygroup *keygroup, FScanner &sc, bool ignorekey, int ¤tnumber)
|
||||||
{
|
{
|
||||||
Keygroup *keygroup;
|
|
||||||
PClassActor *mi;
|
PClassActor *mi;
|
||||||
|
|
||||||
sc.MustGetStringName("{");
|
sc.MustGetStringName("{");
|
||||||
keygroup = new Keygroup;
|
|
||||||
while (!sc.CheckString("}"))
|
while (!sc.CheckString("}"))
|
||||||
{
|
{
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
mi = PClass::FindActor(sc.String);
|
mi = PClass::FindActor(sc.String);
|
||||||
AddOneKey(keygroup, mi, sc);
|
AddOneKey(keygroup, mi, sc, ignorekey, currentnumber);
|
||||||
}
|
|
||||||
if (keygroup->anykeylist.Size() == 0)
|
|
||||||
{
|
|
||||||
delete keygroup;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
keygroup->anykeylist.ShrinkToFit();
|
keygroup->anykeylist.ShrinkToFit();
|
||||||
return keygroup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -257,8 +234,6 @@ static void ParseLock(FScanner &sc)
|
||||||
int i,r,g,b;
|
int i,r,g,b;
|
||||||
int keynum;
|
int keynum;
|
||||||
Lock sink;
|
Lock sink;
|
||||||
Lock *lock = &sink;
|
|
||||||
Keygroup *keygroup;
|
|
||||||
PClassActor *mi;
|
PClassActor *mi;
|
||||||
|
|
||||||
sc.MustGetNumber();
|
sc.MustGetNumber();
|
||||||
|
@ -271,23 +246,17 @@ static void ParseLock(FScanner &sc)
|
||||||
sc.MustGetStringName("{");
|
sc.MustGetStringName("{");
|
||||||
}
|
}
|
||||||
|
|
||||||
ignorekey = true;
|
int currentnumber = 0;
|
||||||
if (keynum > 0 && keynum <= 255)
|
if (keynum == 0 || keynum < -1)
|
||||||
{
|
|
||||||
lock = new Lock;
|
|
||||||
if (locks[keynum])
|
|
||||||
{
|
|
||||||
delete locks[keynum];
|
|
||||||
}
|
|
||||||
locks[keynum] = lock;
|
|
||||||
locks[keynum]->locksound.Push("*keytry");
|
|
||||||
locks[keynum]->locksound.Push("misc/keytry");
|
|
||||||
ignorekey=false;
|
|
||||||
}
|
|
||||||
else if (keynum != -1)
|
|
||||||
{
|
{
|
||||||
sc.ScriptError("Lock index %d out of range", keynum);
|
sc.ScriptError("Lock index %d out of range", keynum);
|
||||||
}
|
}
|
||||||
|
bool ignorekey = keynum == -1; // tell the parsing functions to ignore what they read for other games' keys.
|
||||||
|
|
||||||
|
auto lock = keynum == -1? &sink : &Locks.InsertNew(keynum);
|
||||||
|
|
||||||
|
lock->locksound.Push("*keytry");
|
||||||
|
lock->locksound.Push("misc/keytry");
|
||||||
|
|
||||||
while (!sc.CheckString("}"))
|
while (!sc.CheckString("}"))
|
||||||
{
|
{
|
||||||
|
@ -295,12 +264,15 @@ static void ParseLock(FScanner &sc)
|
||||||
switch(i = sc.MatchString(keywords_lock))
|
switch(i = sc.MatchString(keywords_lock))
|
||||||
{
|
{
|
||||||
case 0: // Any
|
case 0: // Any
|
||||||
keygroup = ParseKeygroup(sc);
|
{
|
||||||
if (keygroup)
|
lock->keylist.Reserve(1);
|
||||||
|
ParseKeygroup(&lock->keylist.Last(), sc, ignorekey, currentnumber);
|
||||||
|
if (lock->keylist.Last().anykeylist.Size() == 0)
|
||||||
{
|
{
|
||||||
lock->keylist.Push(keygroup);
|
lock->keylist.Pop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 1: // message
|
case 1: // message
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
|
@ -344,12 +316,11 @@ static void ParseLock(FScanner &sc)
|
||||||
mi = PClass::FindActor(sc.String);
|
mi = PClass::FindActor(sc.String);
|
||||||
if (mi)
|
if (mi)
|
||||||
{
|
{
|
||||||
keygroup = new Keygroup;
|
lock->keylist.Reserve(1);
|
||||||
AddOneKey(keygroup, mi, sc);
|
AddOneKey(&lock->keylist.Last(), mi, sc, ignorekey, currentnumber);
|
||||||
if (keygroup)
|
if (lock->keylist.Last().anykeylist.Size() == 0)
|
||||||
{
|
{
|
||||||
keygroup->anykeylist.ShrinkToFit();
|
lock->keylist.Pop();
|
||||||
lock->keylist.Push(keygroup);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -389,15 +360,7 @@ static void ClearLocks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i = 0; i < 256; i++)
|
Locks.Clear();
|
||||||
{
|
|
||||||
if (locks[i] != NULL)
|
|
||||||
{
|
|
||||||
delete locks[i];
|
|
||||||
locks[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentnumber = 0;
|
|
||||||
keysdone = false;
|
keysdone = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,17 +448,6 @@ void P_InitKeyMessages()
|
||||||
keysdone = true;
|
keysdone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// P_DeinitKeyMessages
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void P_DeinitKeyMessages()
|
|
||||||
{
|
|
||||||
ClearLocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// P_CheckKeys
|
// P_CheckKeys
|
||||||
|
@ -513,13 +465,14 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
|
||||||
int numfailsounds;
|
int numfailsounds;
|
||||||
|
|
||||||
if (owner == NULL) return false;
|
if (owner == NULL) return false;
|
||||||
if (keynum<=0 || keynum>255) return true;
|
if (keynum<=0) return true;
|
||||||
// Just a safety precaution. The messages should have been initialized upon game start.
|
// Just a safety precaution. The messages should have been initialized upon game start.
|
||||||
if (!keysdone) P_InitKeyMessages();
|
if (!keysdone) P_InitKeyMessages();
|
||||||
|
|
||||||
FSoundID failage[2] = { "*keytry", "misc/keytry" };
|
FSoundID failage[2] = { "*keytry", "misc/keytry" };
|
||||||
|
|
||||||
if (!locks[keynum])
|
auto lock = Locks.CheckKey(keynum);
|
||||||
|
if (!lock)
|
||||||
{
|
{
|
||||||
if (quiet) return false;
|
if (quiet) return false;
|
||||||
if (keynum == 103 && (gameinfo.flags & GI_SHAREWARE))
|
if (keynum == 103 && (gameinfo.flags & GI_SHAREWARE))
|
||||||
|
@ -532,11 +485,11 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (locks[keynum]->check(owner)) return true;
|
if (lock->check(owner)) return true;
|
||||||
if (quiet) return false;
|
if (quiet) return false;
|
||||||
failtext = remote? locks[keynum]->RemoteMsg : locks[keynum]->Message;
|
failtext = remote? lock->RemoteMsg : lock->Message;
|
||||||
failsound = &locks[keynum]->locksound[0];
|
failsound = &lock->locksound[0];
|
||||||
numfailsounds = locks[keynum]->locksound.Size();
|
numfailsounds = lock->locksound.Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, that means the actor isn't holding an appropriate key.
|
// If we get here, that means the actor isn't holding an appropriate key.
|
||||||
|
@ -570,11 +523,13 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int P_GetMapColorForLock (int lock)
|
int P_GetMapColorForLock (int locknum)
|
||||||
{
|
{
|
||||||
if (lock > 0 && lock < 256)
|
if (locknum > 0)
|
||||||
{
|
{
|
||||||
if (locks[lock]) return locks[lock]->rgb;
|
auto lock = Locks.CheckKey(locknum);
|
||||||
|
|
||||||
|
if (lock) return lock->rgb;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -587,11 +542,18 @@ int P_GetMapColorForLock (int lock)
|
||||||
|
|
||||||
int P_GetMapColorForKey (AActor * key)
|
int P_GetMapColorForKey (AActor * key)
|
||||||
{
|
{
|
||||||
int i;
|
decltype(Locks)::Iterator it(Locks);
|
||||||
|
decltype(Locks)::Pair *pair;
|
||||||
|
|
||||||
for (i = 0; i < 256; i++)
|
int foundlock = INT_MAX;
|
||||||
|
int rgb = 0;
|
||||||
|
while (it.NextPair(pair))
|
||||||
{
|
{
|
||||||
if (locks[i] && locks[i]->check(key)) return locks[i]->rgb;
|
if (pair->Key < foundlock && pair->Value.check(key))
|
||||||
|
{
|
||||||
|
rgb = pair->Value.rgb;
|
||||||
|
foundlock = pair->Key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ class PClassActor;
|
||||||
|
|
||||||
int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet = false);
|
int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet = false);
|
||||||
void P_InitKeyMessages ();
|
void P_InitKeyMessages ();
|
||||||
void P_DeinitKeyMessages ();
|
|
||||||
int P_GetMapColorForLock (int lock);
|
int P_GetMapColorForLock (int lock);
|
||||||
int P_GetMapColorForKey (AActor *key);
|
int P_GetMapColorForKey (AActor *key);
|
||||||
int P_GetKeyTypeCount();
|
int P_GetKeyTypeCount();
|
||||||
|
|
|
@ -507,7 +507,6 @@ void P_Init ()
|
||||||
static void P_Shutdown ()
|
static void P_Shutdown ()
|
||||||
{
|
{
|
||||||
DThinker::DestroyThinkersInList(STAT_STATIC);
|
DThinker::DestroyThinkersInList(STAT_STATIC);
|
||||||
P_DeinitKeyMessages ();
|
|
||||||
P_FreeLevelData ();
|
P_FreeLevelData ();
|
||||||
// [ZZ] delete global event handlers
|
// [ZZ] delete global event handlers
|
||||||
E_Shutdown(false);
|
E_Shutdown(false);
|
||||||
|
|
30
src/tarray.h
30
src/tarray.h
|
@ -943,6 +943,36 @@ public:
|
||||||
return n->Pair.Value;
|
return n->Pair.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VT &Insert(const KT key, VT &&value)
|
||||||
|
{
|
||||||
|
Node *n = FindKey(key);
|
||||||
|
if (n != NULL)
|
||||||
|
{
|
||||||
|
n->Pair.Value = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = NewKey(key);
|
||||||
|
::new(&n->Pair.Value) VT(value);
|
||||||
|
}
|
||||||
|
return n->Pair.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT &InsertNew(const KT key)
|
||||||
|
{
|
||||||
|
Node *n = FindKey(key);
|
||||||
|
if (n != NULL)
|
||||||
|
{
|
||||||
|
n->Pair.Value.~VT();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = NewKey(key);
|
||||||
|
}
|
||||||
|
::new(&n->Pair.Value) VT;
|
||||||
|
return n->Pair.Value;
|
||||||
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
//
|
//
|
||||||
// Remove
|
// Remove
|
||||||
|
|
Loading…
Reference in a new issue