From 38a073626ff98d84f6816020bbbc9afeaa2deb91 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 13 Jul 2006 03:34:50 +0000 Subject: [PATCH] - Changed decorate replacement to be opt-in instead of opt-out. This allows for greater flexibility in what can be replaced (replaced actors need not be ancestors of actors that replace them) at the expense of not having universal actor replacement. Instances where replacements work: - Line specials that spawn things (Thing_Spawn and related) - ACS spawning commands (SpawnSpot and the like) - Spawning mapthings at level load time in P_SpawnMapThing() - Spawning items off of dead dudes in P_DropItem() - The A_SpawnItem decorate function - The summon and summonfriend console commands - ThingCount will count both original actors and their replacements as the same things. TBD: Should the ACS inventory functions use replacements too, or not? SVN r249 (trunk) --- docs/rh-log.txt | 13 +++++++++++++ src/d_net.cpp | 3 +++ src/p_acs.cpp | 19 +++++++++++++++++-- src/p_enemy.cpp | 3 +++ src/p_mobj.cpp | 21 +++------------------ src/p_things.cpp | 10 +++++++++- src/thingdef.cpp | 4 ---- src/thingdef_codeptr.cpp | 5 ++++- 8 files changed, 52 insertions(+), 26 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 00e20695d..8c7a5fc0c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,17 @@ July 12, 2006 +- Changed decorate replacement to be opt-in instead of opt-out. This allows for + greater flexibility in what can be replaced (replaced actors need not be ancestors + of actors that replace them) at the expense of not having universal actor + replacement. Instances where replacements work: + - Line specials that spawn things (Thing_Spawn and related) + - ACS spawning commands (SpawnSpot and the like) + - Spawning mapthings at level load time in P_SpawnMapThing() + - Spawning items off of dead dudes in P_DropItem() + - The A_SpawnItem decorate function + - The summon and summonfriend console commands + - ThingCount will count both original actors and their replacements as the same + things. + TBD: Should the ACS inventory functions use replacements too, or not? - Fixed: The game would crash after informing you of a duplicate class registration because PClass::CreateDerivedClass() did not initialize everything before calling InsertIntoHash(). diff --git a/src/d_net.cpp b/src/d_net.cpp index 0e581b4b1..36860135d 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2112,6 +2112,9 @@ void Net_DoCommand (int type, byte **stream, int player) typeinfo = PClass::FindClass (s); if (typeinfo != NULL && typeinfo->ActorInfo != NULL) { + // Handle decorate replacements. + typeinfo = typeinfo->ActorInfo->GetReplacement()->Class; + AActor *source = players[player].mo; if (source != NULL) { diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 96a87cdd3..007d97c9e 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1680,6 +1680,7 @@ int DLevelScript::ThingCount (int type, int stringid, int tid) AActor *actor; const PClass *kind; int count = 0; + bool replacemented = false; if (type >= MAX_SPAWNABLES) { @@ -1698,7 +1699,7 @@ int DLevelScript::ThingCount (int type, int stringid, int tid) return 0; kind = PClass::FindClass (type_name); - if (kind == NULL) + if (kind == NULL || kind->ActorInfo == NULL) return 0; } @@ -1706,7 +1707,8 @@ int DLevelScript::ThingCount (int type, int stringid, int tid) { kind = NULL; } - + +do_count: if (tid) { FActorIterator iterator (tid); @@ -1741,6 +1743,17 @@ int DLevelScript::ThingCount (int type, int stringid, int tid) } } } + if (!replacemented && kind != NULL) + { + // Again, with decorate replacements + replacemented = true; + PClass *newkind = kind->ActorInfo->GetReplacement()->Class; + if (newkind != kind) + { + kind = newkind; + goto do_count; + } + } return count; } @@ -1827,6 +1840,8 @@ int DLevelScript::DoSpawn (int type, fixed_t x, fixed_t y, fixed_t z, int tid, i if (info != NULL) { + // Handle decorate replacements. + info = info->ActorInfo->GetReplacement()->Class; actor = Spawn (info, x, y, z); if (actor != NULL) { diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index e5cf442bd..8f0041115 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2210,6 +2210,9 @@ AInventory *P_DropItem (AActor *source, const PClass *type, int special, int cha spawnz += source->height / 2; } } + // Handle decorate replacements. + type = type->ActorInfo->GetReplacement()->Class; + mo = Spawn (type, source->x, source->y, spawnz); mo->flags |= MF_DROPPED; mo->flags &= ~MF_NOGRAVITY; // [RH] Make sure it is affected by gravity diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2c5f631c4..18d4ca389 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -795,21 +795,6 @@ AInventory *AActor::FindInventory (const PClass *type) const break; } } - if (item == NULL && type->ActorInfo->Replacement != NULL) - { // Try again with a replacement type - PClass *newtype = type->ActorInfo->GetReplacement()->Class; - - if (newtype != type) - { - for (item = Inventory; item != NULL; item = item->Inventory) - { - if (item->GetClass() == newtype) - { - break; - } - } - } - } return item; } @@ -3036,9 +3021,6 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t I_Error ("%s is not an actor\n", type->TypeName.GetChars()); } - // Handle decorate replacements. - type = type->ActorInfo->GetReplacement()->Class; - AActor *actor; actor = static_cast(const_cast(type)->CreateNew ()); @@ -3729,6 +3711,9 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position) // it to the unknown thing. else { + // Handle decorate replacements. + i = i->ActorInfo->GetReplacement()->Class; + const AActor *defaults = GetDefaultByType (i); if (defaults->SpawnState == NULL || sprites[defaults->SpawnState->sprite.index].numframes == 0) diff --git a/src/p_things.cpp b/src/p_things.cpp index d3732764a..37d518c59 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -64,6 +64,10 @@ bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid) if ( (kind = SpawnableThings[type]) == NULL) return false; + + // Handle decorate replacements. + kind = kind->ActorInfo->GetReplacement()->Class; + if ((GetDefaultByType (kind)->flags3 & MF3_ISMONSTER) && (dmflags & DF_NO_MONSTERS)) return false; @@ -176,10 +180,14 @@ bool P_Thing_Projectile (int tid, int type, const char * type_name, angle_t angl } else { - if ((kind = PClass::FindClass(type_name)) == NULL) + if ((kind = PClass::FindClass(type_name)) == NULL || kind->ActorInfo == NULL) return false; } + + // Handle decorate replacements. + kind = kind->ActorInfo->GetReplacement()->Class; + defflags3 = GetDefaultByType (kind)->flags3; if ((defflags3 & MF3_ISMONSTER) && (dmflags & DF_NO_MONSTERS)) return false; diff --git a/src/thingdef.cpp b/src/thingdef.cpp index cce554d4d..07ff28424 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -1305,10 +1305,6 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag) { SC_ScriptError ("Replaced type '%s' is not an actor", sc_String); } - else if (!ti->IsDescendantOf (replacee)) - { - SC_ScriptError ("'%s' must be derived from '%s' to replace it", typeName.GetChars(), sc_String); - } replacee->ActorInfo->Replacement = ti->ActorInfo; } else diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp index 96ad2c5f1..5ee1040c1 100644 --- a/src/thingdef_codeptr.cpp +++ b/src/thingdef_codeptr.cpp @@ -1143,12 +1143,15 @@ void A_SpawnItem(AActor * self) if (useammo && !weapon->DepleteAmmo(weapon->bAltFire)) return; } + // Handle decorate replacements. + missile = missile->ActorInfo->GetReplacement()->Class; + AActor * mo = Spawn( missile, self->x + FixedMul(distance, finecosine[self->angle>>ANGLETOFINESHIFT]), self->y + FixedMul(distance, finesine[self->angle>>ANGLETOFINESHIFT]), self->z - self->floorclip + zheight); - if (mo) + if (mo) { AActor * originator = self;