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;