- 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)
This commit is contained in:
Randy Heit 2006-07-13 03:34:50 +00:00
parent 56427d1b1c
commit 38a073626f
8 changed files with 52 additions and 26 deletions

View File

@ -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().

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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

View File

@ -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<AActor *>(const_cast<PClass *>(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)

View File

@ -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;

View File

@ -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

View File

@ -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;