From ce1aa7e96220ee69431a576225e87a7a711c18e9 Mon Sep 17 00:00:00 2001 From: argv-minus-one Date: Sun, 8 Jul 2018 17:29:35 -0700 Subject: [PATCH] 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). --- .../static/zscript/shared/randomspawner.txt | 100 +++++++++++------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/wadsrc/static/zscript/shared/randomspawner.txt b/wadsrc/static/zscript/shared/randomspawner.txt index 28313bbb7..be7118c5c 100644 --- a/wadsrc/static/zscript/shared/randomspawner.txt +++ b/wadsrc/static/zscript/shared/randomspawner.txt @@ -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 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 cls = s; + if (cls != null) + { + Class rep = GetReplacement(cls); + if (rep != null) { - Class rep = GetReplacement(cls); - if (rep != null) - { - cls = rep; - } - } - if (cls != null) - { - Species = Name(cls); - readonly 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 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();