mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
Move RandomSpawner's random selection logic into a virtual method.
With this, one can use its self-replacement code (which copies a bunch of its state into the replacement actor, and monitors for boss death if appropriate), but select the replacement class based on some other criteria (map number, the player's RPG stats, the player's class, etc).
This commit is contained in:
parent
6239796b92
commit
ce1aa7e962
1 changed files with 63 additions and 37 deletions
|
@ -27,18 +27,16 @@ class RandomSpawner : Actor
|
|||
|
||||
return GetDefaultByType(pclass).bIsMonster;
|
||||
}
|
||||
|
||||
// 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.
|
||||
override void BeginPlay()
|
||||
|
||||
// Override this to decide what to spawn in some other way.
|
||||
// Return the class name, or 'None' to spawn nothing, or 'Unknown' to spawn an error marker.
|
||||
virtual Name ChooseSpawn()
|
||||
{
|
||||
DropItem di; // di will be our drop item list iterator
|
||||
DropItem drop; // while drop stays as the reference point.
|
||||
int n = 0;
|
||||
bool nomonsters = sv_nomonsters || level.nomonsters;
|
||||
|
||||
Super.BeginPlay();
|
||||
drop = di = GetDropItems();
|
||||
if (di != null)
|
||||
{
|
||||
|
@ -57,8 +55,7 @@ class RandomSpawner : Actor
|
|||
}
|
||||
if (n == 0)
|
||||
{ // Nothing left to spawn. They must have all been monsters, and monsters are disabled.
|
||||
Destroy();
|
||||
return;
|
||||
return 'None';
|
||||
}
|
||||
// Then we reset the iterator to the start position...
|
||||
di = drop;
|
||||
|
@ -83,40 +80,69 @@ class RandomSpawner : Actor
|
|||
di = di.Next;
|
||||
}
|
||||
}
|
||||
// So now we can spawn the dropped item.
|
||||
if (di == null)
|
||||
{
|
||||
Spawn("Unknown", Pos, NO_REPLACE); // Show that there's a problem.
|
||||
Destroy();
|
||||
return;
|
||||
return 'Unknown';
|
||||
}
|
||||
else if (random[randomspawn]() <= di.Probability) // prob 255 = always spawn, prob 0 = almost never spawn.
|
||||
{
|
||||
// Handle replacement here so as to get the proper speed and flags for missiles
|
||||
Class<Actor> cls = di.Name;
|
||||
if (cls != null)
|
||||
return di.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'None';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'None';
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
override void BeginPlay()
|
||||
{
|
||||
Super.BeginPlay();
|
||||
let s = ChooseSpawn();
|
||||
|
||||
if (s == 'Unknown') // Spawn error markers immediately.
|
||||
{
|
||||
Spawn(s, Pos, NO_REPLACE);
|
||||
Destroy();
|
||||
}
|
||||
else if (s == 'None') // ChooseSpawn chose to spawn nothing.
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
// So now we can spawn the dropped item.
|
||||
// Handle replacement here so as to get the proper speed and flags for missiles
|
||||
Class<Actor> cls = s;
|
||||
if (cls != null)
|
||||
{
|
||||
Class<Actor> rep = GetReplacement(cls);
|
||||
if (rep != null)
|
||||
{
|
||||
Class<Actor> rep = GetReplacement(cls);
|
||||
if (rep != null)
|
||||
{
|
||||
cls = rep;
|
||||
}
|
||||
}
|
||||
if (cls != null)
|
||||
{
|
||||
Species = Name(cls);
|
||||
readonly<Actor> defmobj = GetDefaultByType(cls);
|
||||
Speed = defmobj.Speed;
|
||||
bMissile |= defmobj.bMissile;
|
||||
bSeekerMissile |= defmobj.bSeekerMissile;
|
||||
bSpectral |= defmobj.bSpectral;
|
||||
}
|
||||
else
|
||||
{
|
||||
A_Log(TEXTCOLOR_RED .. "Unknown item class ".. di.Name .." to drop from a random spawner\n");
|
||||
Species = 'None';
|
||||
cls = rep;
|
||||
}
|
||||
}
|
||||
if (cls != null)
|
||||
{
|
||||
Species = Name(cls);
|
||||
readonly<Actor> defmobj = GetDefaultByType(cls);
|
||||
Speed = defmobj.Speed;
|
||||
bMissile |= defmobj.bMissile;
|
||||
bSeekerMissile |= defmobj.bSeekerMissile;
|
||||
bSpectral |= defmobj.bSpectral;
|
||||
}
|
||||
else
|
||||
{
|
||||
A_Log(TEXTCOLOR_RED .. "Unknown item class ".. s .." to drop from a random spawner\n");
|
||||
Species = 'None';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,9 +154,6 @@ class RandomSpawner : Actor
|
|||
{
|
||||
Super.PostBeginPlay();
|
||||
|
||||
Actor newmobj = null;
|
||||
bool boss = false;
|
||||
|
||||
if (bouncecount >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions
|
||||
{
|
||||
Spawn("Unknown", Pos, NO_REPLACE); // Show that there's a problem.
|
||||
|
@ -138,6 +161,9 @@ class RandomSpawner : Actor
|
|||
return;
|
||||
}
|
||||
|
||||
Actor newmobj = null;
|
||||
bool boss = false;
|
||||
|
||||
if (Species == 'None')
|
||||
{
|
||||
Destroy();
|
||||
|
|
Loading…
Reference in a new issue