- Ensure that only actor with positive SpawnIDs get added to the SpawnableThings map, so there will

be no conflicts with recently-added named arguments for spawnable things on UDMF maps.
- Change the SpawnableThings array into a map, so there is no longer any particular upper limit on an actor's SpawnID. Also fixes a possible exploit, since an actor's SpawnID was never checked to make sure it was within range.

SVN r3959 (trunk)
This commit is contained in:
Randy Heit 2012-11-09 23:53:58 +00:00
parent 3c54047b9f
commit 955d929d5e
5 changed files with 40 additions and 30 deletions

View file

@ -141,7 +141,7 @@ void FActorInfo::StaticInit ()
void FActorInfo::StaticSetActorNums () void FActorInfo::StaticSetActorNums ()
{ {
memset (SpawnableThings, 0, sizeof(SpawnableThings)); SpawnableThings.Clear();
DoomEdMap.Empty (); DoomEdMap.Empty ();
for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i) for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
@ -162,7 +162,7 @@ void FActorInfo::RegisterIDs ()
if (GameFilter == GAME_Any || (GameFilter & gameinfo.gametype)) if (GameFilter == GAME_Any || (GameFilter & gameinfo.gametype))
{ {
if (SpawnID != 0) if (SpawnID > 0)
{ {
SpawnableThings[SpawnID] = cls; SpawnableThings[SpawnID] = cls;
if (cls != Class) if (cls != Class)

View file

@ -2283,13 +2283,9 @@ int DLevelScript::ThingCount (int type, int stringid, int tid, int tag)
int count = 0; int count = 0;
bool replacemented = false; bool replacemented = false;
if (type >= MAX_SPAWNABLES) if (type > 0)
{ {
return 0; kind = P_GetSpawnableType(type);
}
else if (type > 0)
{
kind = SpawnableThings[type];
if (kind == NULL) if (kind == NULL)
return 0; return 0;
} }

View file

@ -155,8 +155,7 @@ void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheigh
// //
// [RH] P_THINGS // [RH] P_THINGS
// //
#define MAX_SPAWNABLES (256) extern TMap<int, const PClass *> SpawnableThings;
extern const PClass *SpawnableThings[MAX_SPAWNABLES];
bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, int newtid); bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, int newtid);
bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_name, angle_t angle, bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_name, angle_t angle,

View file

@ -76,12 +76,7 @@ void ATeleportFog::PostBeginPlay ()
void P_SpawnTeleportFog(fixed_t x, fixed_t y, fixed_t z, int spawnid) void P_SpawnTeleportFog(fixed_t x, fixed_t y, fixed_t z, int spawnid)
{ {
const PClass *fog=NULL; const PClass *fog = P_GetSpawnableType(spawnid);
if (spawnid > 0 && spawnid < MAX_SPAWNABLES && SpawnableThings[spawnid] != NULL)
{
fog = SpawnableThings[spawnid];
}
if (fog == NULL) if (fog == NULL)
{ {

View file

@ -46,8 +46,8 @@
#include "templates.h" #include "templates.h"
#include "g_level.h" #include "g_level.h"
// List of spawnable things for the Thing_Spawn and Thing_Projectile specials. // Set of spawnable things for the Thing_Spawn and Thing_Projectile specials.
const PClass *SpawnableThings[MAX_SPAWNABLES]; TMap<int, const PClass *> SpawnableThings;
static FRandom pr_leadtarget ("LeadTarget"); static FRandom pr_leadtarget ("LeadTarget");
@ -494,23 +494,43 @@ const PClass *P_GetSpawnableType(int spawnnum)
return PClass::FindClass(spawnname); return PClass::FindClass(spawnname);
} }
} }
else if (spawnnum < countof(SpawnableThings)) else
{ // A numbered arg from a Hexen or UDMF map { // A numbered arg from a Hexen or UDMF map
return SpawnableThings[spawnnum]; const PClass **type = SpawnableThings.CheckKey(spawnnum);
if (type != NULL)
{
return *type;
}
} }
return NULL; return NULL;
} }
CCMD (dumpspawnables) typedef TMap<int, const PClass *>::Pair SpawnablePair;
{
int i;
for (i = 0; i < MAX_SPAWNABLES; i++) static int STACK_ARGS SpawnableSort(const void *a, const void *b)
{ {
if (SpawnableThings[i] != NULL) return (*((SpawnablePair **)a))->Key - (*((SpawnablePair **)b))->Key;
{ }
Printf ("%d %s\n", i, SpawnableThings[i]->TypeName.GetChars());
} CCMD (dumpspawnables)
} {
TMapIterator<int, const PClass *> it(SpawnableThings);
SpawnablePair *pair, **allpairs;
int i = 0;
// Sort into numerical order, since their arrangement in the map can
// be in an unspecified order.
allpairs = new TMap<int, const PClass *>::Pair *[SpawnableThings.CountUsed()];
while (it.NextPair(pair))
{
allpairs[i++] = pair;
}
qsort(allpairs, i, sizeof(*allpairs), SpawnableSort);
for (int j = 0; j < i; ++j)
{
pair = allpairs[j];
Printf ("%d %s\n", pair->Key, pair->Value->TypeName.GetChars());
}
delete[] allpairs;
} }