mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 23:01:50 +00:00
- Added ACS function IsTIDUsed(tid): It returns whether any actors using the given TID exist. This
is more efficient than ThingCount(tid, T_NONE), because it only needs to check for one actor with the TID and not all of them. It also makes no distinction between dead things and live things like ThingCount does. - Added ACS function UniqueTID(tid, limit): It returns a new TID that is not currently used by any actors. It has two modes of operation. If tid is non-zero, then it checks TIDs one-by-one starting at the given tid until if finds a free one. If tid is zero, then it returns a completely random TID. If limit is non-zero, then it will only check that many times for a free TID, so it might not find a free one. If no free TID is found, 0 is returned. If limit is zero, then the search is effectively unlimited. SVN r3798 (trunk)
This commit is contained in:
parent
67f64081d0
commit
8c465df44e
3 changed files with 103 additions and 4 deletions
|
@ -976,6 +976,7 @@ private:
|
|||
static FSharedStringArena mStringPropertyData;
|
||||
|
||||
friend class FActorIterator;
|
||||
friend bool P_IsTIDUsed(int tid);
|
||||
|
||||
sector_t *LinkToWorldForMapThing ();
|
||||
|
||||
|
@ -1070,6 +1071,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool P_IsTIDUsed(int tid);
|
||||
int P_FindUniqueTID(int start_tid, int limit);
|
||||
|
||||
inline AActor *Spawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
|
||||
{
|
||||
return AActor::StaticSpawn (type, x, y, z, allowreplacement);
|
||||
|
|
|
@ -3363,6 +3363,8 @@ enum EACSFunctions
|
|||
ACSF_ACS_NamedLockedExecuteDoor,
|
||||
ACSF_ACS_NamedExecuteWithResult,
|
||||
ACSF_ACS_NamedExecuteAlways,
|
||||
ACSF_UniqueTID,
|
||||
ACSF_IsTIDUsed,
|
||||
|
||||
// ZDaemon
|
||||
ACSF_GetTeamScore = 19620,
|
||||
|
@ -3879,6 +3881,14 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
}
|
||||
break;
|
||||
|
||||
case ACSF_UniqueTID:
|
||||
return P_FindUniqueTID(argCount > 0 ? args[0] : 0, argCount > 1 ? args[1] : 0);
|
||||
break;
|
||||
|
||||
case ACSF_IsTIDUsed:
|
||||
return P_IsTIDUsed(args[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "v_video.h"
|
||||
#include "c_cvars.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "b_bot.h" //Added by MC:
|
||||
#include "stats.h"
|
||||
#include "a_hexenglobal.h"
|
||||
|
@ -107,6 +108,7 @@ static FRandom pr_missiledamage ("MissileDamage");
|
|||
FRandom pr_slam ("SkullSlam");
|
||||
static FRandom pr_multiclasschoice ("MultiClassChoice");
|
||||
static FRandom pr_rockettrail("RocketTrail");
|
||||
static FRandom pr_uniquetid("UniqueTID");
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
|
@ -2612,10 +2614,7 @@ AActor *AActor::TIDHash[128];
|
|||
|
||||
void AActor::ClearTIDHashes ()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
TIDHash[i] = NULL;
|
||||
memset(TIDHash, NULL, sizeof(TIDHash));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2666,6 +2665,92 @@ void AActor::RemoveFromHash ()
|
|||
tid = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_IsTIDUsed
|
||||
//
|
||||
// Returns true if there is at least one actor with the specified TID
|
||||
// (dead or alive).
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool P_IsTIDUsed(int tid)
|
||||
{
|
||||
AActor *probe = AActor::TIDHash[tid & 127];
|
||||
while (probe != NULL)
|
||||
{
|
||||
if (probe->tid == tid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
probe = probe->inext;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_FindUniqueTID
|
||||
//
|
||||
// Returns an unused TID. If start_tid is 0, then a random TID will be
|
||||
// chosen. Otherwise, it will perform a linear search starting from
|
||||
// start_tid. If limit is non-0, then it will not check more than <limit>
|
||||
// number of TIDs. Returns 0 if no suitable TID was found.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int P_FindUniqueTID(int start_tid, int limit)
|
||||
{
|
||||
int tid;
|
||||
|
||||
if (start_tid != 0)
|
||||
{ // Do a linear search.
|
||||
limit = start_tid + limit - 1;
|
||||
if (limit < start_tid)
|
||||
{ // If it overflowed, clamp to INT_MAX
|
||||
limit = INT_MAX;
|
||||
}
|
||||
for (tid = start_tid; tid <= limit; ++tid)
|
||||
{
|
||||
if (tid != 0 && !P_IsTIDUsed(tid))
|
||||
{
|
||||
return tid;
|
||||
}
|
||||
}
|
||||
// Nothing free found.
|
||||
return 0;
|
||||
}
|
||||
// Do a random search. To try and be a bit more performant, this
|
||||
// actually does several linear searches. In the case of *very*
|
||||
// dense TID usage, this could potentially perform worse than doing
|
||||
// a complete linear scan starting at 1. However, you would need
|
||||
// to use an absolutely ridiculous number of actors before this
|
||||
// becomes a real concern.
|
||||
if (limit == 0)
|
||||
{
|
||||
limit = INT_MAX;
|
||||
}
|
||||
for (int i = 0; i < limit; i += 5)
|
||||
{
|
||||
// Use a positive starting TID.
|
||||
tid = pr_uniquetid.GenRand32() & INT_MAX;
|
||||
tid = P_FindUniqueTID(tid == 0 ? 1 : tid, 5);
|
||||
if (tid != 0)
|
||||
{
|
||||
return tid;
|
||||
}
|
||||
}
|
||||
// Nothing free found.
|
||||
return 0;
|
||||
}
|
||||
|
||||
CCMD(utid)
|
||||
{
|
||||
Printf("%d\n",
|
||||
P_FindUniqueTID(argv.argc() > 1 ? atoi(argv[1]) : 0,
|
||||
argv.argc() > 2 ? atoi(argv[2]) : 0));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// AActor :: GetMissileDamage
|
||||
|
|
Loading…
Reference in a new issue