diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp index afca4f190..5485d8d1f 100644 --- a/src/g_hexen/a_hexenspecialdecs.cpp +++ b/src/g_hexen/a_hexenspecialdecs.cpp @@ -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); diff --git a/src/namedef.h b/src/namedef.h index 34f9b7235..18fdc0adb 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -299,6 +299,7 @@ xx(Arg2) xx(Arg3) xx(Arg4) xx(Arg0Str) +xx(Arg1Str) xx(Id) xx(V1) xx(V2) diff --git a/src/p_local.h b/src/p_local.h index 4c57ef099..bf7861561 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -168,7 +168,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 diff --git a/src/p_things.cpp b/src/p_things.cpp index e0f3936b7..74a6f0bcb 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -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,6 +484,22 @@ 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 if (spawnnum < countof(SpawnableThings)) + { // A numbered arg from a Hexen or UDMF map + return SpawnableThings[spawnnum]; + } + return NULL; +} CCMD (dumpspawnables) { diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 5abe40908..e087834b1 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -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); + } } //===========================================================================