- added RandomSpawner update from Gez's experimental build.
- added thing activation types for BUMPSPECIAL and USESPECIAL. Also added a new ClearSpecial flag to the activation type. - added MBF's code for dogs jumping down, controlled by the MF6_JUMPDOWN flag. SVN r1835 (trunk)
This commit is contained in:
parent
f2a122e076
commit
5910d90a19
9 changed files with 222 additions and 81 deletions
|
|
@ -1,6 +1,8 @@
|
|||
/*
|
||||
** a_randomspawner.cpp
|
||||
** A thing that randomly spawns one item in a list of many, before disappearing.
|
||||
** bouncecount is used to keep track of recursions (so as to prevent infinite loops).
|
||||
** Species is used to store the index of the spawned actor's name.
|
||||
*/
|
||||
|
||||
#include "actor.h"
|
||||
|
|
@ -21,14 +23,16 @@ class ARandomSpawner : public AActor
|
|||
{
|
||||
DECLARE_CLASS (ARandomSpawner, AActor)
|
||||
|
||||
void PostBeginPlay()
|
||||
// To handle "RandomSpawning" missiles, the code has to be split in two parts.
|
||||
// If the following code is not done in BeginPlay, missiles will use the
|
||||
// random spawner's velocity (0...) instead of their own.
|
||||
void BeginPlay()
|
||||
{
|
||||
AActor *newmobj = NULL;
|
||||
FDropItem *di; // di will be our drop item list iterator
|
||||
FDropItem *drop; // while drop stays as the reference point.
|
||||
int n=0;
|
||||
|
||||
Super::PostBeginPlay();
|
||||
Super::BeginPlay();
|
||||
drop = di = GetDropItems();
|
||||
if (di != NULL)
|
||||
{
|
||||
|
|
@ -46,7 +50,7 @@ class ARandomSpawner : public AActor
|
|||
// Take a random number...
|
||||
n = pr_randomspawn(n);
|
||||
// And iterate in the array up to the random number chosen.
|
||||
while (n > 0)
|
||||
while (n > -1)
|
||||
{
|
||||
if (di->Name != NAME_None)
|
||||
{
|
||||
|
|
@ -55,64 +59,109 @@ class ARandomSpawner : public AActor
|
|||
}
|
||||
}
|
||||
// So now we can spawn the dropped item.
|
||||
if (special1 >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions
|
||||
if (bouncecount >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions
|
||||
{
|
||||
Spawn("Unknown", x, y, z, NO_REPLACE); // Show that there's a problem.
|
||||
Destroy(); return;
|
||||
}
|
||||
else if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn.
|
||||
{
|
||||
newmobj = Spawn(di->Name, x, y, z, ALLOW_REPLACE);
|
||||
// copy everything relevant
|
||||
newmobj->SpawnAngle = newmobj->angle = angle;
|
||||
newmobj->special = special;
|
||||
newmobj->args[0] = args[0];
|
||||
newmobj->args[1] = args[1];
|
||||
newmobj->args[2] = args[2];
|
||||
newmobj->args[3] = args[3];
|
||||
newmobj->args[4] = args[4];
|
||||
newmobj->SpawnFlags = SpawnFlags;
|
||||
newmobj->HandleSpawnFlags();
|
||||
newmobj->tid = tid;
|
||||
newmobj->AddToHash();
|
||||
newmobj->velx = velx;
|
||||
newmobj->vely = vely;
|
||||
newmobj->velz = velz;
|
||||
newmobj->master = master; // For things such as DamageMaster/DamageChildren, transfer mastery.
|
||||
newmobj->target = target;
|
||||
newmobj->tracer = tracer;
|
||||
newmobj->CopyFriendliness(this, false);
|
||||
if (!(flags & MF_DROPPED)) newmobj->flags &= ~MF_DROPPED;
|
||||
|
||||
// Handle special altitude flags
|
||||
if (newmobj->flags & MF_SPAWNCEILING)
|
||||
// Handle replacement here so as to get the proper speed and flags for missiles
|
||||
const PClass * cls; PClass * rep;
|
||||
cls = PClass::FindClass(di->Name);
|
||||
if (cls) rep = cls->ActorInfo->GetReplacement()->Class;
|
||||
if (rep) cls = rep;
|
||||
if (cls)
|
||||
{
|
||||
newmobj->z = newmobj->ceilingz - newmobj->height;
|
||||
Species = cls->TypeName;
|
||||
AActor * defmobj = GetDefaultByType(cls);
|
||||
this->Speed = defmobj->Speed;
|
||||
this->flags |= (defmobj->flags & MF_MISSILE);
|
||||
this->flags2 |= (defmobj->flags2 & MF2_SEEKERMISSILE);
|
||||
this->flags4 |= (defmobj->flags4 & MF4_SPECTRAL);
|
||||
}
|
||||
else if (newmobj->flags2 & MF2_SPAWNFLOAT)
|
||||
{
|
||||
fixed_t space = newmobj->ceilingz - newmobj->height - newmobj->floorz;
|
||||
if (space > 48*FRACUNIT)
|
||||
{
|
||||
space -= 40*FRACUNIT;
|
||||
newmobj->z = MulScale8 (space, pr_randomspawn()) + newmobj->floorz + 40*FRACUNIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Special1 is used to count how many recursions we're in.
|
||||
if (newmobj->IsKindOf(PClass::FindClass("RandomSpawner")))
|
||||
newmobj->special1 = ++special1;
|
||||
|
||||
else Species = NAME_None;
|
||||
}
|
||||
}
|
||||
if ((newmobj != NULL) && ((newmobj->flags4 & MF4_BOSSDEATH) || (newmobj->flags2 & MF2_BOSS)))
|
||||
this->target = newmobj; // If the spawned actor has either of those flags, it's a boss.
|
||||
}
|
||||
|
||||
// The second half of random spawning. Now that the spawner is initialized, the
|
||||
// real actor can be created. If the following code were in BeginPlay instead,
|
||||
// missiles would not have yet obtained certain information that is absolutely
|
||||
// necessary to them -- such as their source and destination.
|
||||
void PostBeginPlay()
|
||||
{
|
||||
AActor * newmobj = NULL;
|
||||
bool boss = false;
|
||||
if (Species == NAME_None) { Destroy(); return; }
|
||||
const PClass * cls = PClass::FindClass(Species);
|
||||
if (this->flags & MF_MISSILE && target && target->target) // Attempting to spawn a missile.
|
||||
{
|
||||
if ((tracer == NULL) && (flags2 & MF2_SEEKERMISSILE)) tracer = target->target;
|
||||
newmobj = P_SpawnMissileXYZ(x, y, z, target, target->target, cls, false);
|
||||
}
|
||||
else newmobj = Spawn(cls, x, y, z, NO_REPLACE);
|
||||
if (newmobj != NULL)
|
||||
{
|
||||
// copy everything relevant
|
||||
newmobj->SpawnAngle = newmobj->angle = angle;
|
||||
newmobj->special = special;
|
||||
newmobj->args[0] = args[0];
|
||||
newmobj->args[1] = args[1];
|
||||
newmobj->args[2] = args[2];
|
||||
newmobj->args[3] = args[3];
|
||||
newmobj->args[4] = args[4];
|
||||
newmobj->SpawnFlags = SpawnFlags;
|
||||
newmobj->HandleSpawnFlags();
|
||||
newmobj->tid = tid;
|
||||
newmobj->AddToHash();
|
||||
newmobj->velx = velx;
|
||||
newmobj->vely = vely;
|
||||
newmobj->velz = velz;
|
||||
newmobj->master = master; // For things such as DamageMaster/DamageChildren, transfer mastery.
|
||||
newmobj->target = target;
|
||||
newmobj->tracer = tracer;
|
||||
newmobj->CopyFriendliness(this, false);
|
||||
// This handles things such as projectiles with the MF4_SPECTRAL flag that have
|
||||
// a health set to -2 after spawning, for internal reasons.
|
||||
if (health != SpawnHealth()) newmobj->health = health;
|
||||
if (!(flags & MF_DROPPED)) newmobj->flags &= ~MF_DROPPED;
|
||||
// Handle special altitude flags
|
||||
if (newmobj->flags & MF_SPAWNCEILING)
|
||||
{
|
||||
newmobj->z = newmobj->ceilingz - newmobj->height;
|
||||
}
|
||||
else if (newmobj->flags2 & MF2_SPAWNFLOAT)
|
||||
{
|
||||
fixed_t space = newmobj->ceilingz - newmobj->height - newmobj->floorz;
|
||||
if (space > 48*FRACUNIT)
|
||||
{
|
||||
space -= 40*FRACUNIT;
|
||||
newmobj->z = MulScale8 (space, pr_randomspawn()) + newmobj->floorz + 40*FRACUNIT;
|
||||
}
|
||||
}
|
||||
if (newmobj->flags & MF_MISSILE)
|
||||
P_CheckMissileSpawn(newmobj);
|
||||
// Bouncecount is used to count how many recursions we're in.
|
||||
if (newmobj->IsKindOf(PClass::FindClass("RandomSpawner")))
|
||||
newmobj->bouncecount = ++bouncecount;
|
||||
// If the spawned actor has either of those flags, it's a boss.
|
||||
if ((newmobj->flags4 & MF4_BOSSDEATH) || (newmobj->flags2 & MF2_BOSS))
|
||||
boss = true;
|
||||
// If a replaced actor has either of those same flags, it's also a boss.
|
||||
AActor * rep = GetDefaultByType(GetClass()->ActorInfo->GetReplacee()->Class);
|
||||
if (rep && (rep->flags4 & MF4_BOSSDEATH) || (rep->flags2 & MF2_BOSS))
|
||||
boss = true;
|
||||
}
|
||||
if (boss) this->tracer = newmobj;
|
||||
else Destroy(); // "else" because a boss-replacing spawner must wait until it can call A_BossDeath.
|
||||
}
|
||||
|
||||
void Tick() // This function is needed for handling boss replacers
|
||||
{
|
||||
Super::Tick();
|
||||
if (target == NULL || target->health <= 0)
|
||||
if (tracer == NULL || tracer->health <= 0)
|
||||
{
|
||||
health = 0;
|
||||
CALL_ACTION(A_BossDeath, this);
|
||||
Destroy();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue