* Updated to ZDoom 3959:

- 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.
- Added "Using arg*str instead of SpawnID" patch, with modifications.
- Fix spelling errors spotted in a few comments.
- Added FDARI's get actor height and radius patch.
- Enable Doom 1.1 status bar support.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@1468 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
gez 2012-11-10 00:23:04 +00:00
parent 53a16bd3a1
commit 481a6e4886
15 changed files with 122 additions and 56 deletions

View file

@ -357,8 +357,8 @@ unsigned int PClass::Extend(unsigned int extension)
}
// Like FindClass but creates a placeholder if no class
// is found. CreateDerivedClass will automatcally fill in
// the placeholder when the actual class is defined.
// is found. CreateDerivedClass will automatically fill
// in the placeholder when the actual class is defined.
const PClass *PClass::FindClassTentative (FName name)
{
if (name == NAME_None)

View file

@ -70,13 +70,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode)
}
}
S_Sound (mo, CHAN_BODY, "PotteryExplode", 1, ATTN_NORM);
if (self->args[0]>=0 && self->args[0]<=255 && SpawnableThings[self->args[0]])
{ // Spawn an item
// Spawn an item?
const PClass *type = P_GetSpawnableType(self->args[0]);
if (type != NULL)
{
if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS))
|| !(GetDefaultByType (SpawnableThings[self->args[0]])->flags3 & MF3_ISMONSTER))
|| !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER))
{ // Only spawn monsters if not -nomonsters
Spawn (SpawnableThings[self->args[0]],
self->x, self->y, self->z, ALLOW_REPLACE);
Spawn (type, self->x, self->y, self->z, ALLOW_REPLACE);
}
}
}
@ -288,13 +289,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode)
mo->vely = pr_soaexplode.Random2()<<(FRACBITS-6);
}
}
if (self->args[0]>=0 && self->args[0]<=255 && SpawnableThings[self->args[0]])
{ // Spawn an item
// Spawn an item?
const PClass *type = P_GetSpawnableType(self->args[0]);
if (type != NULL)
{
if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS))
|| !(GetDefaultByType (SpawnableThings[self->args[0]])->flags3 & MF3_ISMONSTER))
|| !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER))
{ // Only spawn monsters if not -nomonsters
Spawn (SpawnableThings[self->args[0]],
self->x, self->y, self->z, ALLOW_REPLACE);
Spawn (type, self->x, self->y, self->z, ALLOW_REPLACE);
}
}
S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_NORM);

View file

@ -141,7 +141,7 @@ void FActorInfo::StaticInit ()
void FActorInfo::StaticSetActorNums ()
{
memset (SpawnableThings, 0, sizeof(SpawnableThings));
SpawnableThings.Clear();
DoomEdMap.Empty ();
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 (SpawnID != 0)
if (SpawnID > 0)
{
SpawnableThings[SpawnID] = cls;
if (cls != Class)

View file

@ -299,6 +299,7 @@ xx(Arg2)
xx(Arg3)
xx(Arg4)
xx(Arg0Str)
xx(Arg1Str)
xx(Id)
xx(V1)
xx(V2)

View file

@ -2283,13 +2283,9 @@ int DLevelScript::ThingCount (int type, int stringid, int tid, int tag)
int count = 0;
bool replacemented = false;
if (type >= MAX_SPAWNABLES)
if (type > 0)
{
return 0;
}
else if (type > 0)
{
kind = SpawnableThings[type];
kind = P_GetSpawnableType(type);
if (kind == NULL)
return 0;
}
@ -2766,6 +2762,8 @@ enum
APROP_Mass = 32,
APROP_Accuracy = 33,
APROP_Stamina = 34,
APROP_Height = 35,
APROP_Radius = 36,
};
// These are needed for ACS's APROP_RenderStyle
@ -3045,6 +3043,8 @@ int DLevelScript::GetActorProperty (int tid, int property)
case APROP_Mass: return actor->Mass;
case APROP_Accuracy: return actor->accuracy;
case APROP_Stamina: return actor->stamina;
case APROP_Height: return actor->height;
case APROP_Radius: return actor->radius;
default: return 0;
}
@ -3085,6 +3085,8 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value)
case APROP_Mass:
case APROP_Accuracy:
case APROP_Stamina:
case APROP_Height:
case APROP_Radius:
return (GetActorProperty(tid, property) == value);
// Boolean values need to compare to a binary version of value

View file

@ -155,8 +155,7 @@ void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheigh
//
// [RH] P_THINGS
//
#define MAX_SPAWNABLES (256)
extern const PClass *SpawnableThings[MAX_SPAWNABLES];
extern TMap<int, const PClass *> SpawnableThings;
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,
@ -168,7 +167,7 @@ int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type);
void P_Thing_SetVelocity(AActor *actor, fixed_t vx, fixed_t vy, fixed_t vz, bool add, bool setbob);
void P_RemoveThing(AActor * actor);
bool P_Thing_Raise(AActor *thing);
const PClass *P_GetSpawnableType(int spawnnum);
//
// P_MAPUTL

View file

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

View file

@ -46,8 +46,8 @@
#include "templates.h"
#include "g_level.h"
// List of spawnable things for the Thing_Spawn and Thing_Projectile specials.
const PClass *SpawnableThings[MAX_SPAWNABLES];
// Set of spawnable things for the Thing_Spawn and Thing_Projectile specials.
TMap<int, const PClass *> SpawnableThings;
static FRandom pr_leadtarget ("LeadTarget");
@ -58,10 +58,9 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog,
AActor *spot, *mobj;
FActorIterator iterator (tid);
if (type >= MAX_SPAWNABLES)
return false;
kind = P_GetSpawnableType(type);
if ( (kind = SpawnableThings[type]) == NULL)
if (kind == NULL)
return false;
// Handle decorate replacements.
@ -182,18 +181,16 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char *type_nam
if (type_name == NULL)
{
if (type >= MAX_SPAWNABLES)
return false;
if ((kind = SpawnableThings[type]) == NULL)
return false;
kind = P_GetSpawnableType(type);
}
else
{
if ((kind = PClass::FindClass(type_name)) == NULL || kind->ActorInfo == NULL)
return false;
kind = PClass::FindClass(type_name);
}
if (kind == NULL || kind->ActorInfo == NULL)
{
return false;
}
// Handle decorate replacements.
kind = kind->GetReplacement();
@ -487,17 +484,53 @@ void P_Thing_SetVelocity(AActor *actor, fixed_t vx, fixed_t vy, fixed_t vz, bool
}
}
const PClass *P_GetSpawnableType(int spawnnum)
{
if (spawnnum < 0)
{ // A named arg from a UDMF map
FName spawnname = FName(ENamedName(-spawnnum));
if (spawnname.IsValidName())
{
return PClass::FindClass(spawnname);
}
}
else
{ // A numbered arg from a Hexen or UDMF map
const PClass **type = SpawnableThings.CheckKey(spawnnum);
if (type != NULL)
{
return *type;
}
}
return NULL;
}
typedef TMap<int, const PClass *>::Pair SpawnablePair;
static int STACK_ARGS SpawnableSort(const void *a, const void *b)
{
return (*((SpawnablePair **)a))->Key - (*((SpawnablePair **)b))->Key;
}
CCMD (dumpspawnables)
{
int i;
TMapIterator<int, const PClass *> it(SpawnableThings);
SpawnablePair *pair, **allpairs;
int i = 0;
for (i = 0; i < MAX_SPAWNABLES; i++)
// 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))
{
if (SpawnableThings[i] != NULL)
{
Printf ("%d %s\n", i, SpawnableThings[i]->TypeName.GetChars());
}
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;
}

View file

@ -98,6 +98,11 @@ static char HexenSectorSpecialOk[256]={
1,1,1,1,1,
};
static inline bool P_IsThingSpecial(int specnum)
{
return (specnum >= Thing_Projectile && specnum <= Thing_SpawnNoFog) ||
specnum == Thing_SpawnFacing || Thing_ProjectileIntercept || Thing_ProjectileAimed;
}
enum
{
@ -467,7 +472,7 @@ public:
void ParseThing(FMapThing *th)
{
FString arg0str;
FString arg0str, arg1str;
memset(th, 0, sizeof(*th));
sc.MustGetToken('{');
@ -524,6 +529,11 @@ public:
arg0str = CheckString(key);
break;
case NAME_Arg1Str:
CHECK_N(Zd);
arg1str = CheckString(key);
break;
case NAME_Skill1:
case NAME_Skill2:
case NAME_Skill3:
@ -624,10 +634,14 @@ public:
break;
}
}
if (arg0str.IsNotEmpty() && P_IsACSSpecial(th->special))
if (arg0str.IsNotEmpty() && (P_IsACSSpecial(th->special) || th->special == 0))
{
th->args[0] = -FName(arg0str);
}
if (arg1str.IsNotEmpty() && (P_IsThingSpecial(th->special) || th->special == 0))
{
th->args[1] = -FName(arg1str);
}
// Thing specials are only valid in namespaces with Hexen-type specials
// and in ZDoomTranslated - which will use the translator on them.
if (namespc == NAME_ZDoomTranslated)
@ -663,7 +677,7 @@ public:
{
bool passuse = false;
bool strifetrans = false;
FString arg0str;
FString arg0str, arg1str;
memset(ld, 0, sizeof(*ld));
ld->Alpha = FRACUNIT;
@ -724,6 +738,11 @@ public:
arg0str = CheckString(key);
continue;
case NAME_Arg1Str:
CHECK_N(Zd);
arg1str = CheckString(key);
continue;
case NAME_Blocking:
Flag(ld->flags, ML_BLOCKING, key);
continue;
@ -938,10 +957,14 @@ public:
ld->sidedef[0] = (side_t*)(intptr_t)(1);
Printf("Line %d has no first side.\n", index);
}
if (arg0str.IsNotEmpty() && P_IsACSSpecial(ld->special))
if (arg0str.IsNotEmpty() && (P_IsACSSpecial(ld->special) || ld->special == 0))
{
ld->args[0] = -FName(arg0str);
}
if (arg1str.IsNotEmpty() && (P_IsThingSpecial(ld->special) || ld->special == 0))
{
ld->args[1] = -FName(arg1str);
}
}
//===========================================================================

View file

@ -982,7 +982,7 @@ struct line_t
slopetype_t slopetype; // To aid move clipping.
sector_t *frontsector, *backsector;
int validcount; // if == validcount, already checked
int locknumber; // [Dusk] lock number for special
int locknumber; // [Dusk] lock number for special
};
// phares 3/14/98

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the
// updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "3953"
#define ZD_SVN_REVISION_NUMBER 3953
#define ZD_SVN_REVISION_STRING "3959"
#define ZD_SVN_REVISION_NUMBER 3959

View file

@ -84,6 +84,9 @@ DEFINE_MEMBER_VARIABLE(Damage, AActor)
DEFINE_MEMBER_VARIABLE(Score, AActor)
DEFINE_MEMBER_VARIABLE(accuracy, AActor)
DEFINE_MEMBER_VARIABLE(stamina, AActor)
DEFINE_MEMBER_VARIABLE(height, AActor)
DEFINE_MEMBER_VARIABLE(radius, AActor)
//==========================================================================
//

View file

@ -491,7 +491,7 @@ int V_GetColorFromString (const DWORD *palette, const char *cstr)
else
{
normal:
// Treat it as a space-delemited hexadecimal string
// Treat it as a space-delimited hexadecimal string
for (i = 0; i < 3; ++i)
{
// Skip leading whitespace

View file

@ -56,6 +56,8 @@ ACTOR Actor native //: Thinker
native int score;
native int accuracy;
native int stamina;
native fixed_t height;
native fixed_t radius;
// Meh, MBF redundant functions. Only for DeHackEd support.
action native A_Turn(float angle = 0);

View file

@ -71,3 +71,9 @@ Graphic optional P_MWALK4, 112, 136
Graphic "M_MBOX", 0, 0
Graphic "M_MWALK4", 24, 12 { useoffsets }
}
Graphic optional STBAR, 320, 32
{
Graphic "STMBARL", 0, 0
Graphic "STMBARR", 104, 0
}