Add "on-demand" option to only spawn ammo for available weapons.

Add dedicated "Ammo Spawner" class to simplify code.
Small code duplication cleanup.
This commit is contained in:
Mari the Deer 2021-06-23 01:00:53 +02:00
commit fb0e8c45f3
14 changed files with 349 additions and 276 deletions

View file

@ -111,6 +111,7 @@ server bool swwm_usetopickup = false; // allow item pickup only by pressing use
server bool swwm_meleepickup = false; // allow picking up items through melee
nosave bool swwm_buttsfx = true; // buttslam homerun SFX
nosave int swwm_sewercount = 0; // I'm sorry Civvie
server bool swwm_ondemandammo = false; // don't spawn ammo for unavailable weapons
// minimap settings
nosave bool swwm_mm_enable = true; // show a minimap below the score counter

View file

@ -191,6 +191,7 @@ SWWM_SELFLIGHT = "Self-Lighting";
SWWM_USETOPICKUP = "Exclusive Use To Pickup";
SWWM_MELEEPICKUP = "Allow Item Pickup Through Melee";
SWWM_BUTTSFX = "Clapping Buttcheeks";
SWWM_ONDEMANDAMMO = "On Demand Ammo Placement";
SWWM_MMTITLE = "Minimap Settings";
SWWM_MM_ENABLE = "Show Minimap";
SWWM_MM_ROTATE = "Rotate Minimap";
@ -330,6 +331,7 @@ TOOLTIP_SWWM_SELFLIGHT = "Emit blue light from the player's face. Disable if thi
TOOLTIP_SWWM_USETOPICKUP = "Prevents picking up mod items through touch, exclusively requiring a use action instead.";
TOOLTIP_SWWM_MELEEPICKUP = "Allows picking up items though melee attacks. Do note that some weapons have an extended melee range, allowing you to grab things from farther away.";
TOOLTIP_SWWM_BUTTSFX = "The Demolitionist's buttcheeks will VERY AUDIBLY clap upon executing a successful buttslam.";
TOOLTIP_SWWM_ONDEMANDAMMO = "Only ammo for weapons that are currently available (either in the player's inventory or in the map) will spawn in the map. May cause long load times on large maps.";
TOOLTIP_SWWM_MM_ENABLE = "Displays a minimap under the score counter.";
TOOLTIP_SWWM_MM_ROTATE = "Rotates the minimap view.";
TOOLTIP_SWWM_MM_GRID = "Shows a 128x128 grid on the minimap.";

View file

@ -190,6 +190,7 @@ SWWM_SELFLIGHT = "Luz Propia";
SWWM_USETOPICKUP = "Uso Exclusivo para Recoger";
SWWM_MELEEPICKUP = "Permitir Recoger Ítems con Melé";
SWWM_BUTTSFX = "Azote de Nalgas";
SWWM_ONDEMANDAMMO = "Colocar Munición por Demanda";
SWWM_MMTITLE = "Opciones de Minimapa";
SWWM_MM_ENABLE = "Mostrar Minimapa";
SWWM_MM_ROTATE = "Rotar Minimapa";
@ -329,6 +330,7 @@ TOOLTIP_SWWM_SELFLIGHT = "Emite luz azul desde la cara del jugador. Desactiva si
TOOLTIP_SWWM_USETOPICKUP = "Evita recoger ítems del mod al tocarlos, en su lugar requiriendo exclusivamente una acción de uso.";
TOOLTIP_SWWM_MELEEPICKUP = "Permite recoger ítems por medio de ataques a melé. Ten en cuenta que algunas armas tienen un rango de melé extendido, permitiéndote alcanzar cosas desde una mayor distancia.";
TOOLTIP_SWWM_BUTTSFX = "Las nalgas de la Demolicionista emitiran un azote MUY SONORO al ejecutar exitosamente un golpe de culo.";
TOOLTIP_SWWM_ONDEMANDAMMO = "Solo coloca en el mapa munición para armas que estén actualmente disponibles (tanto en el inventario del jugador como en el mapa). Puede causar tiempos de carga largos en mapas grandes.";
TOOLTIP_SWWM_MM_ENABLE = "Muestra un minimapa bajo el contador de puntuación.";
TOOLTIP_SWWM_MM_ROTATE = "Gira la vista del minimapa.";
TOOLTIP_SWWM_MM_GRID = "Muestra una cuadrícula de 128x128 en el minimapa.";

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r553 \cu(Wed 23 Jun 01:00:39 CEST 2021)\c-";
SWWM_SHORTVER="\cw0.9.11b-pre r553 \cu(2021-06-23 01:00:39)\c-";
SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r555 \cu(Wed 23 Jun 01:06:21 CEST 2021)\c-";
SWWM_SHORTVER="\cw0.9.11b-pre r555 \cu(2021-06-23 01:06:21)\c-";

View file

@ -152,6 +152,7 @@ OptionMenu "SWWMOptionMenu"
StaticText "$SWWM_BTITLE", "Blue"
Option "$SWWM_PISTOLSTART", "swwm_pistolstart", "YesNo"
Option "$SWWM_ENEMYDROPS", "swwm_enemydrops", "SWWMEnemyDropType"
Option "$SWWM_ONDEMANDAMMO", "swwm_ondemandammo", "YesNo"
Option "$SWWM_RESETSCORE", "swwm_resetscore", "YesNo"
Option "$SWWM_EXTRAALERT", "swwm_extraalert", "YesNo"
Option "$SWWM_BOSSENHANCE", "swwm_upgradebosses", "YesNo"

View file

@ -70,6 +70,7 @@ version "4.6"
#include "zscript/items/swwm_powerups.zsc"
#include "zscript/items/swwm_ammoitems.zsc"
#include "zscript/items/swwm_ammoextra.zsc"
#include "zscript/items/swwm_ammospawn.zsc"
#include "zscript/items/swwm_funstuff.zsc"
#include "zscript/items/swwm_collectibles.zsc"
#include "zscript/items/swwm_collectibles_gesture.zsc"

View file

@ -34,26 +34,17 @@ Class SMW05Ammo : Ammo
}
}
Class SMW05BundleSpawn : Actor
Class SMW05BundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("SMW05Ammo",Vec3Angle(4,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}
@ -201,27 +192,17 @@ Class QuadravolAmmo : Ammo
}
}
Class QuadravolAmmoBundleSpawn : Actor
Class QuadravolAmmoBundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("QuadravolAmmo",Vec3Angle(6,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}
@ -302,27 +283,17 @@ Class EMPCore : Ammo
}
}
Class EMPCoreBundleSpawn : Actor
Class EMPCoreBundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<3; i++ )
{
let a = Spawn("EMPCore",Vec3Angle(6,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}
@ -351,26 +322,17 @@ Class RayBolt : MagAmmo
}
}
Class RayBoltBundleSpawn : Actor
Class RayBoltBundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,5);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("RayBolt",Vec3Angle(6,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}

View file

@ -555,12 +555,6 @@ extend Class SWWMHandler
if ( profiling ) checkreplacement_ms += MSTime()-curms;
return;
}
// shell types (sorted by rarity
static const Class<Actor> redpool[] = {'RedShell','RedShell2','RedShell4'};
static const Class<Actor> greenpool[] = {'GreenShell','GreenShell2','GreenShell4'};
static const Class<Actor> whitepool[] = {'WhiteShell','WhiteShell2'};
static const Class<Actor> purplepool[] = {'PurpleShell','PurpleShell2','PurpleShell4'};
static const Class<Actor> bluepool[] = {'BlueShell','BlueShell2','BlueShell4'};
// DRLA Monsters stuff
if ( hasdrlamonsters )
{
@ -611,7 +605,7 @@ extend Class SWWMHandler
}
e.Replacement = 'SWWMBossBrain';
}
else if ( e.Replacee is 'RedCard' )
else if ( (e.Replacee is 'RedCard') && !(e.Replacee is 'ChexRedCard') )
{
if ( level.GetChecksum() ~== "3805A661D5C4523AFF7BF86991071043" )
{
@ -620,8 +614,8 @@ extend Class SWWMHandler
}
e.Replacement = 'SWWMRedCard';
}
else if ( e.Replacee is 'BlueCard' ) e.Replacement = 'SWWMBlueCard';
else if ( e.Replacee is 'YellowCard' ) e.Replacement = 'SWWMYellowCard';
else if ( (e.Replacee is 'BlueCard') && !(e.Replacee is 'ChexBlueCard') ) e.Replacement = 'SWWMBlueCard';
else if ( (e.Replacee is 'YellowCard') && !(e.Replacee is 'ChexYellowCard') ) e.Replacement = 'SWWMYellowCard';
else if ( e.Replacee.GetClassName() == 'GreenCard' ) e.Replacement = 'SWWMGreenCard';
else if ( e.Replacee is 'RedSkull' ) e.Replacement = iskdizd?'SWWMSilverCardKDiZD':'SWWMRedSkull';
else if ( e.Replacee is 'BlueSkull' ) e.Replacement = iskdizd?'SWWMGreenCardKDiZD':'SWWMBlueSkull';
@ -646,144 +640,49 @@ extend Class SWWMHandler
else if ( e.Replacee is 'MWeaponPiece1' ) e.Replacement = SWWMUtility.PickSWWMSlot0();
else if ( (e.Replacee is 'ShellBox') || (e.Replacee is 'CrossbowHefty') )
{
/*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SMW05SmallAmmo':'SMW05BigAmmo';
else */switch( Random[Replacements](0,20) )
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
e.Replacement = redpool[Random[Replacements](1,2)];
break;
case 6:
case 7:
case 8:
case 9:
case 10:
e.Replacement = greenpool[Random[Replacements](1,2)];
break;
case 11:
case 12:
case 13:
case 14:
e.Replacement = purplepool[Random[Replacements](0,2)];
break;
case 15:
case 16:
case 17:
e.Replacement = bluepool[Random[Replacements](0,2)];
break;
case 18:
case 19:
e.Replacement = whitepool[Random[Replacements](0,1)];
break;
case 20:
e.Replacement = 'BlackShell';
break;
}
if ( swwm_ondemandammo ) e.Replacement = 'SWWMShellAmmoBig';
else e.Replacement = SWWMShellAmmoBig.PickAmmo(true);
}
else if ( (e.Replacee is 'Shell') || (e.Replacee is 'CrossbowAmmo') )
{
/*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SMW05SmallAmmo':'SMW05BundleSpawn';
else */switch( Random[Replacements](0,9) )
{
case 0:
case 1:
case 2:
case 3:
e.Replacement = redpool[0];
break;
case 4:
case 5:
case 6:
e.Replacement = greenpool[0];
break;
case 7:
case 8:
e.Replacement = purplepool[0];
break;
case 9:
e.Replacement = bluepool[0];
break;
}
if ( swwm_ondemandammo ) e.Replacement = 'SWWMShellAmmoSmall';
else e.Replacement = SWWMShellAmmoSmall.PickAmmo(true);
}
else if ( e.Replacee is 'ClipBox' )
{
/*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SheenSmallAmmo':'SheenBigAmmo';
else */e.Replacement = Random[Replacements](0,5)?'EvisceratorShell':Random[Replacements](0,9)?'EvisceratorTrioSpawn':'EvisceratorSixPack';
if ( swwm_ondemandammo ) e.Replacement = 'SWWMClipAmmoBig';
else e.Replacement = SWWMClipAmmoBig.PickAmmo(true);
}
else if ( (e.Replacee is 'Clip') || (e.Replacee is 'GoldWandAmmo') ) e.Replacement = /*(e.Replacee is 'GoldWandHefty')?'SheenSmallAmmo':'SheenTinyAmmo'*/'SWWMNothing';
else if ( (e.Replacee is 'Clip') || (e.Replacee is 'GoldWandAmmo') ) e.Replacement = 'SWWMNothing';
else if ( e.Replacee is 'BlasterHefty' )
{
/*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SheenBigAmmo':'SheenSmallAmmo';
else */e.Replacement = Random[Replacements](0,6)?'EvisceratorTrioSpawn':'EvisceratorSixPack';
if ( swwm_ondemandammo ) e.Replacement = 'SWWMBlastAmmoBig';
else e.Replacement = SWWMBlastAmmoBig.PickAmmo(true);
}
else if ( e.Replacee is 'BlasterAmmo' )
{
/*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'SheenSmallAmmo':'SheenTinyAmmo';
else */e.Replacement = 'EvisceratorShell';
if ( swwm_ondemandammo ) e.Replacement = 'SWWMBlastAmmoSmall';
else e.Replacement = SWWMBlastAmmoSmall.PickAmmo(true);
}
else if ( (e.Replacee is 'RocketBox') || (e.Replacee is 'PhoenixRodHefty') || (e.Replacee is 'MaceHefty') )
{
/*if ( Random[Replacements](0,1) ) e.Replacement = Random[Replacements](0,2)?'QuadravolAmmo':'QuadravolAmmoBundleSpawn';
else */switch ( Random[Replacements](0,11) )
{
case 0:
case 1:
case 2:
case 3:
case 4:
if ( Random[Replacements](0,5) ) e.Replacement = 'HellblazerMissiles';
else if ( Random[Replacements](0,4) ) e.Replacement = 'HellblazerMissileTrioSpawn';
else e.Replacement = 'HellblazerMissileMag';
break;
case 5:
case 6:
case 7:
case 8:
if ( Random[Replacements](0,6) ) e.Replacement = 'HellblazerCrackshots';
else e.Replacement = 'HellblazerCrackshotMag';
break;
case 9:
case 10:
if ( Random[Replacements](0,8) ) e.Replacement = 'HellblazerRavagers';
else e.Replacement = 'HellblazerRavagerMag';
break;
case 11:
if ( Random[Replacements](0,10) ) e.Replacement = 'HellblazerWarheads';
else e.Replacement = 'HellblazerWarheadMag';
break;
}
if ( swwm_ondemandammo ) e.Replacement = 'SWWMRocketAmmoBig';
else e.Replacement = SWWMRocketAmmoBig.PickAmmo(true);
}
else if ( (e.Replacee is 'RocketAmmo') || (e.Replacee is 'PhoenixRodAmmo') || (e.Replacee is 'MaceAmmo') )
{
/*if ( Random[Replacements](0,1) ) e.Replacement = 'QuadravolAmmo';
else */e.Replacement = Random[Replacements](0,2)?'HellblazerMissiles':'HellblazerCrackshots';
if ( swwm_ondemandammo ) e.Replacement = 'SWWMRocketAmmoSmall';
else e.Replacement = SWWMRocketAmmoSmall.PickAmmo(true);
}
else if ( (e.Replacee is 'CellPack') || (e.Replacee is 'SkullRodHefty') )
{
/*if ( Random[Replacements](0,1) )
{
if ( !Random[Replacements](0,2) ) e.Replacement = Random[Replacements](0,3)?'EMPCoreBundleSpawn':'EMPCore';
else if ( Random[Replacements](0,2) ) e.Replacement = 'RayBoltBundleSpawn';
else e.Replacement = 'RayAmmo';
}
else */if ( !Random[Replacements](0,2) )
{
if ( Random[Replacements](0,3) ) e.Replacement = Random[Replacements](0,2)?'SilverBulletsBundleSpawn':'SilverBullets2BundleSpawn';
else e.Replacement = Random[Replacements](0,2)?'SilverBulletAmmo':'SilverBulletAmmo2';
}
else if ( Random[Replacements](0,2) ) e.Replacement = 'CandyGunBulletsBundleSpawn';
else e.Replacement = 'CandyGunAmmo';
if ( swwm_ondemandammo ) e.Replacement = 'SWWMCellAmmoBig';
else e.Replacement = SWWMCellAmmoBig.PickAmmo(true);
}
else if ( (e.Replacee is 'Cell') || (e.Replacee is 'SkullRodAmmo') )
{
if ( !Random[Replacements](0,2) ) e.Replacement = /*!Random[Replacements](0,2)?'RayBattery':*/Random[Replacements](0,2)?'HellblazerRavagers':'HellblazerWarheads';
else if ( Random[Replacements](0,2) ) e.Replacement = /*Random[Replacements](0,1)?'DarkCanister':*/'SparkUnit';
else if ( !Random[Replacements](0,3) ) e.Replacement = /*Random[Replacements](0,1)?'RayBolt':*/'CandyGunBullets';
else e.Replacement = /*Random[Replacements](0,1)?'EMPCore':*/Random[Replacements](0,2)?'SilverBullets':'SilverBullets2';
if ( swwm_ondemandammo ) e.Replacement = 'SWWMCellAmmoSmall';
else e.Replacement = SWWMCellAmmoSmall.PickAmmo(true);
}
else if ( e.Replacee is 'Mana1' ) e.Replacement = 'FabricatorTier1';
else if ( e.Replacee is 'Mana2' ) e.Replacement = 'FabricatorTier2';

View file

@ -500,25 +500,7 @@ Class HammerspaceEmbiggener : Inventory
}
let n = Spawn("BulkHammerspaceEmbiggener",pos);
Inventory(n).Amount = min(tamount,MaxAmount);
n.spawnpoint = spawnpoint;
n.spawnangle = spawnangle;
n.angle = angle;
n.pitch = pitch;
n.roll = roll;
n.special = special;
for ( int i=0; i<5; i++ ) n.args[i] = args[i];
n.special1 = special1;
n.special2 = special2;
n.spawnflags = spawnflags&~MTF_SECRET;
n.HandleSpawnFlags();
n.spawnflags = spawnflags;
n.bCountSecret = spawnflags&MTF_SECRET;
n.ChangeTid(tid);
n.vel = vel;
n.master = master;
n.tracer = tracer;
n.target = target;
if ( !bDROPPED ) n.bDROPPED = false;
SWWMUtility.TransferItemProp(self,n);
ClearCounters();
Destroy();
}

View file

@ -522,26 +522,17 @@ Class EvisceratorSixPack : EvisceratorShell
}
}
Class EvisceratorTrioSpawn : Actor
Class EvisceratorBundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
for ( int i=0; i<3; i++ )
int bnd = Random[Bundle](3,4);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("EvisceratorShell",Vec3Angle(12,i*120));
a.special = special;
a.angle = i*120;
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
let a = Spawn("EvisceratorShell",Vec3Angle(12,i*(360/bnd)));
a.angle = i*(360/bnd);
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}
@ -604,26 +595,17 @@ Class HellblazerMissileMag : HellblazerMissiles
Height 26;
}
}
Class HellblazerMissileTrioSpawn : Actor
Class HellblazerMissileBundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
for ( int i=0; i<3; i++ )
int bnd = Random[Bundle](2,4);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("HellblazerMissiles",Vec3Angle(8,i*120));
a.special = special;
a.angle = i*120;
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
let a = Spawn("HellblazerMissiles",Vec3Angle(8,i*(360/bnd)));
a.angle = i*(360/bnd);
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}
@ -682,6 +664,19 @@ Class HellblazerCrackshotMag : HellblazerCrackshots
Height 26;
}
}
Class HellblazerCrackshotBundleSpawn : SWWMAmmoSpawner
{
override void SpawnAmmo()
{
int bnd = Random[Bundle](2,3);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("HellblazerCrackshots",Vec3Angle(8,i*(360/bnd)));
a.angle = i*(360/bnd);
SWWMUtility.TransferItemProp(self,a,true);
}
}
}
Class HellblazerRavagers : Ammo
{
@ -839,6 +834,20 @@ Class SparkUnit : Ammo
Stop;
}
}
Class SparkUnitBundleSpawn : SWWMAmmoSpawner
{
override void SpawnAmmo()
{
int bnd = Random[Bundle](2,3);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("SparkUnit",Vec3Angle(8,i*(360/bnd)));
a.angle = i*(360/bnd);
SWWMUtility.TransferItemProp(self,a,true);
}
}
}
// ============================================================================
// Silver Bullet ammo
@ -1001,50 +1010,30 @@ Class SilverBullets2 : MagAmmo
}
}
Class SilverBulletsBundleSpawn : Actor
Class SilverBulletsBundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("SilverBullets",Vec3Angle(6,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}
Class SilverBullets2BundleSpawn : Actor
Class SilverBullets2BundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("SilverBullets2",Vec3Angle(6,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
a.FloatBobPhase = FloatBobPhase;
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}
@ -1131,26 +1120,17 @@ Class CandyGunBullets : MagAmmo
}
}
Class CandyGunBulletsBundleSpawn : Actor
Class CandyGunBulletsBundleSpawn : SWWMAmmoSpawner
{
override void PostBeginPlay()
override void SpawnAmmo()
{
if ( bCOUNTSECRET ) level.total_secrets--;
int bnd = Random[Bundle](2,3);
for ( int i=0; i<bnd; i++ )
{
let a = Spawn("CandyGunBullets",Vec3Angle(4,i*(360/bnd)));
a.special = special;
a.angle = i*(360/bnd);
for ( int j=0; j<5; j++ ) a.args[j] = args[j];
if ( bCOUNTSECRET )
{
a.bCOUNTSECRET = true;
level.total_secrets++;
}
a.bDROPPED = bDROPPED;
SWWMUtility.TransferItemProp(self,a,true);
}
Destroy();
}
}

View file

@ -0,0 +1,199 @@
// on-demand ammo spawners
Mixin Class SWWMOndemandAmmoSpawner
{
override void SpawnAmmo()
{
let ac = PickAmmo();
if ( !ac ) return;
let a = Spawn(ac,pos);
SWWMUtility.TransferItemProp(self,a);
}
}
Class SWWMShellAmmoSmall : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('PuntzerBeta') || SWWMUtility.ItemExists('PuntzerGamma')) )
return Random[Replacements](0,2)?'SMW05SmallAmmo':'SMW05BundleSpawn';*/
switch( Random[Replacements](0,9) )
{
case 0:
case 1:
case 2:
case 3:
return 'RedShell';
case 4:
case 5:
case 6:
return 'GreenShell';
case 7:
case 8:
return 'PurpleShell';
}
// case 9
return 'BlueShell';
}
}
Class SWWMShellAmmoBig : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
// shell types (sorted by rarity)
static const Class<Actor> redpool[] = {'RedShell','RedShell2','RedShell4'};
static const Class<Actor> greenpool[] = {'GreenShell','GreenShell2','GreenShell4'};
static const Class<Actor> whitepool[] = {'WhiteShell','WhiteShell2'};
static const Class<Actor> purplepool[] = {'PurpleShell','PurpleShell2','PurpleShell4'};
static const Class<Actor> bluepool[] = {'BlueShell','BlueShell2','BlueShell4'};
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('PuntzerBeta') || SWWMUtility.ItemExists('PuntzerGamma')) )
return Random[Replacements](0,2)?'SMW05SmallAmmo':'SMW05BigAmmo';*/
switch( Random[Replacements](0,20) )
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
return redpool[Random[Replacements](0,2)];
case 6:
case 7:
case 8:
case 9:
case 10:
return greenpool[Random[Replacements](0,2)];
case 11:
case 12:
case 13:
case 14:
return purplepool[Random[Replacements](0,2)];
case 15:
case 16:
case 17:
return bluepool[Random[Replacements](0,2)];
case 18:
case 19:
return whitepool[Random[Replacements](0,1)];
}
// case 20
return 'BlackShell';
}
}
Class SWWMClipAmmoBig : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('HeavyMahsheenGun')) )
return Random[Replacements](0,2)?'SheenSmallAmmo':'SheenBigAmmo';*/
return Random[Replacements](0,5)?'EvisceratorShell':'EvisceratorBundleSpawn';
}
}
Class SWWMBlastAmmoSmall : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('HeavyMahsheenGun')) )
return Random[Replacements](0,2)?'SheenSmallAmmo':'SheenTinyAmmo';*/
return 'EvisceratorShell';
}
}
Class SWWMBlastAmmoBig : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('HeavyMahsheenGun')) )
return Random[Replacements](0,2)?'SheenBigAmmo':'SheenSmallAmmo';*/
return 'EvisceratorBundleSpawn';
}
}
Class SWWMRocketAmmoSmall : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('Quadravol')) ) return 'QuadravolAmmo';*/
return Random[Replacements](0,2)?'HellblazerMissiles':'HellblazerCrackshots';
}
}
Class SWWMRocketAmmoBig : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('Quadravol')) )
return Random[Replacements](0,2)?'QuadravolAmmo':'QuadravolAmmoBundleSpawn';*/
switch ( Random[Replacements](0,11) )
{
case 0:
case 1:
case 2:
case 3:
case 4:
return Random[Replacements](0,2)?'HellblazerMissiles':'HellblazerMissileBundleSpawn';
case 5:
case 6:
case 7:
case 8:
return Random[Replacements](0,3)?'HellblazerCrackshots':'HellblazerCrackshotBundleSpawn';
case 9:
case 10:
return 'HellblazerRavagers';
}
// case 11
return 'HellblazerWarheads';
}
}
Class SWWMCellAmmoSmall : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( !Random[Replacements](0,2) && (notondemand || SWWMUtility.ItemExists('RayKhom') || SWWMUtility.ItemExists('GrandLance')) ) return 'RayBattery';*/
if ( !Random[Replacements](0,2) )
{
if ( !Random[Replacements](0,3) )
{
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('RayKhom')) ) return 'RayBolt';*/
if ( notondemand || SWWMUtility.ItemExists('CandyGun') ) return 'CandyGunBullets';
}
/*if ( Random[Replacements](0,1) && (notondemand || SWWMUtility.ItemExists('EMPCarbine')) ) return 'EMPCore';*/
if ( notondemand || SWWMUtility.ItemExists('SilverBullet') ) return Random[Replacements](0,2)?'SilverBullets':'SilverBullets2';
}
/*if ( !Random[Replacements](0,4) && (notondemand || SWWMUtility.ItemExists('BlackfireIgniter')) ) return 'DarkCanister';*/
return 'SparkUnit';
}
}
Class SWWMCellAmmoBig : SWWMAmmoSpawner
{
Mixin SWWMOndemandAmmoSpawner;
static Class<Actor> PickAmmo( bool notondemand = false )
{
/*if ( Random[Replacements](0,1) )
{
if ( !Random[Replacements](0,2) && (notondemand || SWWMUtility.ItemExists('EMPCarbine')) ) return Random[Replacements](0,3)?'EMPCoreBundleSpawn':'EMPCore';
if ( notondemand || SWWMUtility.ItemExists('RayKhom') ) return Random[Replacements](0,2)?'RayBoltBundleSpawn':'RayAmmo';
}*/
if ( !Random[Replacements](0,2) && (notondemand || SWWMUtility.ItemExists('SilverBullet')) )
{
if ( Random[Replacements](0,3) ) return Random[Replacements](0,2)?'SilverBulletsBundleSpawn':'SilverBullets2BundleSpawn';
return Random[Replacements](0,2)?'SilverBulletAmmo':'SilverBulletAmmo2';
}
if ( notondemand || SWWMUtility.ItemExists('CandyGun') ) return Random[Replacements](0,2)?'CandyGunBulletsBundleSpawn':'CandyGunAmmo';
/*if ( !Random[Replacements](0,2) && (notondemand || SWWMUtility.ItemExists('BlackfireIgniter')) ) return 'DarkCanister';*/
return Random[Replacements](0,2)?'SparkUnit':'SparkUnitBundleSpawn';
}
}

View file

@ -380,3 +380,25 @@ Mixin Class SWWMShellAmmo
Amount = Random[ShellDrop](1,clamp(dropamount,1,4));
}
}
// Ref class for ammo spawners, used by both on-demand replacers and bundles
Class SWWMAmmoSpawner : Actor abstract
{
virtual void SpawnAmmo() {}
override void PostBeginPlay()
{
SpawnAmmo();
ClearCounters();
Destroy();
}
default
{
+NOGRAVITY;
+NOBLOCKMAP;
+NOINTERACTION;
+NOTELEPORT;
+DONTSPLASH;
}
}

View file

@ -735,18 +735,8 @@ Class ChanceboxSpawner : Actor
}
let b = Spawn("Chancebox",pos);
// copy all our stuff
b.spawnangle = spawnangle;
b.angle = angle;
b.pitch = pitch;
b.roll = roll;
b.spawnpoint = spawnpoint;
b.special = special;
for ( int i=0; i<5; i++ )
b.Args[i] = Args[i];
b.spawnflags = spawnflags&~MTF_SECRET;
b.HandleSpawnFlags();
b.bCOUNTSECRET = spawnflags&MTF_SECRET;
b.ChangeTid(tid);
SWWMUtility.TransferItemProp(self,b);
ClearCounters();
Destroy();
}

View file

@ -2099,6 +2099,38 @@ Class SWWMUtility
if ( level.maptime ) return PickSWWMSlot3(); // always slot 3 after map start, prevents shotgun guys from dropping wallbusters
return PickPair(PickSWWMSlot3(),PickSWWMSlot4(),2);
}
// what RandomSpawner does, basically (simplified for items)
static play void TransferItemProp( Actor a, Actor b, bool bundlehack = false )
{
if ( bundlehack )
{
b.spawnpoint = b.pos;
b.spawnangle = int(b.angle);
}
else
{
b.spawnpoint = a.spawnpoint;
b.spawnangle = a.spawnangle;
b.angle = a.angle;
b.pitch = a.pitch;
b.roll = a.roll;
}
b.special = a.special;
b.FloatBobPhase = a.FloatBobPhase; // important
for ( int i=0; i<5; i++ ) b.args[i] = a.args[i];
b.special1 = a.special1;
b.special2 = a.special2;
b.spawnflags = a.spawnflags&~MTF_SECRET;
b.HandleSpawnFlags();
b.spawnflags = a.spawnflags;
b.bCountSecret = a.spawnflags&MTF_SECRET;
b.ChangeTid(a.tid);
b.vel = b.vel;
b.master = b.master;
b.tracer = b.tracer;
b.target = b.target;
b.bDROPPED = a.bDROPPED;
}
}
Class RadiusDebugSphere : Actor