"Updated" by : "Fleshfest" Youtube : @gustru2078

For Unreal Tournament v469e. Untested in Unreal / other versions of UT.

I took the old MonsterSpawn304.u and used ScriptRays inside UnRealED to recover the code from every single class in the package.
My employer pays for copilot so I used it to fix some long-standing issues with this mutator as well as adding some quality of life to it (hopefully)

- FIXED A CRASH THAT WOULD OCCUR UPON LOADING MAPS WITH BAD PATHING // THAT HAVE THOUSANDS OF PATHNODES
	You can reproduce this crash by loading the 221beta version of CTF-LavaGiant into UnrealED And having it generate a new path network. 
	It will generate over 4000 pathnodes and the game will immediately crash upon loading it with the old non-fixed MonsterSpawn304. It won't crash with this fixed version.

- FIXED lists 20 to 99 being useless (the code only had them until 19...). You can now use ALL 100 lists (tested)

- Made teleport FX and sound togglable. You can have them if you want them, you can turn them off if you don't. The teleport FX will be replaced by a fade in / fade out.

- Made MinutesTillRespawn accept decimals (0.25 or one quarter of a minute corresponds to 15 seconds)

- Added a toggle that will allow you to prevent the despawning of monsters between each wave. 
  If enabled, the next wave will only spawn monsters up to its own allowed maximum. 
  Example : If there are 10 monsters (spawned by MonsterSpawn) left in the map when it's time for a new wave to spawn and MaxMonstersFromList[x]=20 in the .ini, 
            the game will spawn 10 new monsters from the newly chosen list without despawning or touching the remaining survivors. Other settings allow you to do it SILENTLY as well :)

- There used to be a small freeze at each wave spawn. This should also be fixed (hopefully) at the expense of a longer freeze at the very first spawn when you load a map.

Installation : 
- Remove MonsterSpawn304.u and MonsterSpawn.int from the System folder if you have them (to avoid any conflicts or overwriting the .int should you want to go back to the old version)
- Backup your current MonsterSpawn.ini just in case or drop the one that is included in the .zip into your UnrealTournament\System folder if you don't already have one.
- Drop MonsterSpawn304_fixed.u, MonsterSpawn.ini and MonsterSpawn.int from the .zip file into your system folder.
- YES, you can just use the .ini provided in the download and copy / paste your own lists into it if you were already using MonsterSpawn304 before 
  BUT you have to update your references with those in the summons section below. Calling for a non-existent package is no good.

Explanations of the new settings are further down below and in the .ini file.

Summons : 

************************
Default Unreal Monsters 
************************

MonsterSpawn304_fixed.MSBabyCow (harmless)
MonsterSpawn304_fixed.MSBrute 
MonsterSpawn304_fixed.MSCow     (harmless)
MonsterSpawn304_fixed.MSFly 
MonsterSpawn304_fixed.MSLesserBrute 
MonsterSpawn304_fixed.MSManta 
MonsterSpawn304_fixed.MSNali     (harmless)  
MonsterSpawn304_fixed.MSNaliPriest (harmless)
UnrealShare.NaliRabbit (harmless)
UnrealShare.Bird1 (harmless)
MonsterSpawn304_fixed.MSSkaarjScout 
MonsterSpawn304_fixed.MSSkaarjWarrior 
MonsterSpawn304_fixed.MSSlith 
MonsterSpawn304_fixed.MSBehemoth
MonsterSpawn304_fixed.MSGasbag 
MonsterSpawn304_fixed.MSGiantManta
MonsterSpawn304_fixed.MSGiantGasbag 
MonsterSpawn304_fixed.MSIceSkaarj
MonsterSpawn304_fixed.MSKrall 
MonsterSpawn304_fixed.MSKrallElite 
MonsterSpawn304_fixed.MSMercenary
MonsterSpawn304_fixed.MSMercenaryElite 
MonsterSpawn304_fixed.MSPupae 
MonsterSpawn304_fixed.MSQueen   
MonsterSpawn304_fixed.MSSkaarjAssassin 
MonsterSpawn304_fixed.MSSkaarjBerserker 
MonsterSpawn304_fixed.MSSkaarjLord 
MonsterSpawn304_fixed.MSStoneTitan 
MonsterSpawn304_fixed.MSTitan 
MonsterSpawn304_fixed.MSWarlord 

--Monsters with Unreal 1 weapons (It is recommended to use Loathsome's UT Tweak for these) :

MonsterSpawn304_fixed.MSSkaarjTrooper
MonsterSpawn304_fixed.MSSkaarjGunner
MonsterSpawn304_fixed.MSSkaarjInfantry 
MonsterSpawn304_fixed.MSSkaarjOfficer  
MonsterSpawn304_fixed.MSSkaarjSniper 

--Monsters that "require" water : 
Don't add these to lists as they require a waterzone, but can be summoned
 and monsterspawn will replace the default Devilfish and Squid with these

MonsterSpawn304_fixed.MSDevilfish
MonsterSpawn304_fixed.MSSquid

----Here's what's new in the .ini file : -------

bUseTeleportFX=False                  ; On spawn, play Teleport1 sound + spawn QueenTeleportEffect. False = silent/clean spawn.
bUseDespawnSound=False                ; On despawn (cleanup), optionally play DespawnSound once per pawn.
DespawnSound=none                     ; Sound to use if bUseDespawnSound=True. Use 'None' (or 'none') for no sound.
;DespawnSound=Sound'UnrealShare.Generic.Teleport1'  ; Example sound reference (commented out).

bCleanupBetweenWaves=false            ; True = classic waves: cleanup old pawns, wait, then spawn new wave. False = Fill mode (no cleanup).
bSpawnOnlyMissingFromPrevious=True    ; Only useful when bCleanupBetweenWaves=false. THIS IS WHAT ALLOWS YOU TO FILL THE "EMPTY SLOTS" WITH NEW MONSTERS WITHOUT DESPAWNING THE OLD ONES!
SpawnDelayAfterCleanupSeconds=2.0     ; In cleanup mode, delay (seconds) between despawn and the next wave’s spawn.

bFadeInSpawn=True                     ; New spawns fade in (unlit/translucent → normal). Cosmetic only.
FadeInSeconds=1.0                     ; Fade-in duration in seconds.
WaveSpawnBatchSize=8                  ; Slice size per tick when spawning a wave (reduces 1s hitch). 0 or <0 = spawn all at once.
WaveSpawnSliceSeconds=0.05            ; Time gap between spawn slices (seconds).
bFadeOutDespawn=True                  ; On cleanup, fade out before destroy (if enabled).
FadeOutSeconds=0.25                   ; Fade-out duration in seconds.

AlwaysSafeNavBuild=False              ; True = build spawn spots by enumerating PathNodes (safe). False = use engine list (faster), fall back if corrupt.
bLogSpawnedMonsters=True              ; Verbose logging: spawn attempts, successes, fill/cadence math, safe spot counts, etc.

The config options below already existed. Added Descriptions to all and moved the scoring stuff at the top with the rest for convenience.

AllowBosses=True                      ; Boss monsters with several thousand health may gain well over an extra 1000 health depending on difficulty. This *ONLY* effects boss monsters in the lists. Example bosses Titan, Walord, Queen, Jurassic Trexes, jurassic Triceratops, etc.
AllowQueensXtraTeleports=True         ; Allows MSqueens the ability to teleport in any level. In some extremely large levels you might want to set this to false if the map requires killing the queen to end. Otherwise you may have to hunt the queen down. For most maps i'd suggest leaving this as true
AllowRespawns=True                    ; If False, only do the initial wave (SpawnAtStart) and never schedule another.
AllowMonsterReplacement=True          ; Replace map-placed Unreal/UT pawns with their MS* variants at startup (style/parity fixes). If you want monsters to be able to attack bots this value should be left as true. Otherwise only the monsters added to the lists will be able to do this (if theyre monsterspawn monsters).
MinutesTillRespawn=1.25               ; Period between waves or fill ticks, in minutes. 0.25 = 15 seconds.
HowManyLists=100                      ; How many MonsterListN arrays are considered (1..100). Values >100 are clamped for safety.

UseUTMonsterspawnScoring=False        ; If True, adjusts player score on killing ScriptedPawns using the UTScore* values below.
UTScoreMonstersHealth100=1            ; Score for killing monsters with default.Health <= 100.
UTScoreMonstersHealth101to500=2       ; Score for killing monsters with 101..500 health.
UTScoreMonstersHealth501to1000=3      ; Score for killing monsters with 501..1000 health.
UTScoreMonstersHealth1001to1500=4     ; Score for killing monsters with 1001..1500 health.
UTScoreMonstersHealth1501to2000=5     ; Score for killing monsters with 1501..2000 health.
UTScoreMonstersHealthOver2000=6       ; Score for killing monsters with >2000 health.
UTScoreMonsterBossBonus=5             ; Extra score if the killed monster had bIsBoss=True (unless disabled by AllowBosses=False).
UTScoreKillingFriemdliesLOSS=5        ; Score penalty for killing friendlies (typo preserved from original var name).

SpawnAtStart=True   		      ; Spawns an initial wave ~5s after match start using a random MonsterList, up to that list’s Max cap (respecting safe spawn spots, slice/batch, and fade-in).
                   		      ; False = wait for the first scheduled respawn/fill tick instead. 
                   		      ; Tip: If AllowRespawns=False, this initial wave will be the only one.

SPawnSkill=3			      ; 0=Easy, 1=Medium, 2=hard, 3=Unreal. Anything above 3 or below 0 defaults to 3 (Unreal difficulty).
damageScale=1.000000                  ; GLOBAL damage scaling. Per-list damage scaling is further down below. It is recommended to leave this option at 1.00000 if you intend to use those.

DamageScaleForList[0]=1.00
DamageScaleForList[1]=1.00
DamageScaleForList[2]=1.00
DamageScaleForList[3]=1.00
DamageScaleForList[4]=1.00
DamageScaleForList[5]=1.00
DamageScaleForList[6]=1.00
DamageScaleForList[7]=1.00
DamageScaleForList[8]=1.00
DamageScaleForList[9]=1.00
DamageScaleForList[10]=1.00
DamageScaleForList[11]=1.00
DamageScaleForList[12]=1.00
DamageScaleForList[13]=1.00
DamageScaleForList[14]=1.00
DamageScaleForList[15]=1.00
DamageScaleForList[16]=1.00
DamageScaleForList[17]=1.00
DamageScaleForList[18]=1.00
DamageScaleForList[19]=1.00
DamageScaleForList[20]=1.00
DamageScaleForList[21]=1.00
DamageScaleForList[22]=1.00
DamageScaleForList[23]=1.00
DamageScaleForList[24]=1.00
DamageScaleForList[25]=1.00
DamageScaleForList[26]=1.00
DamageScaleForList[27]=1.00
DamageScaleForList[28]=1.00
DamageScaleForList[29]=1.00
DamageScaleForList[30]=1.00
DamageScaleForList[31]=1.00
DamageScaleForList[32]=1.00
DamageScaleForList[33]=1.00
DamageScaleForList[34]=1.00
DamageScaleForList[35]=1.00
DamageScaleForList[36]=1.00
DamageScaleForList[37]=1.00
DamageScaleForList[38]=1.00
DamageScaleForList[39]=1.00
DamageScaleForList[40]=1.00
DamageScaleForList[41]=1.00
DamageScaleForList[42]=1.00
DamageScaleForList[43]=1.00
DamageScaleForList[44]=1.00
DamageScaleForList[45]=1.00
DamageScaleForList[46]=1.00
DamageScaleForList[47]=1.00
DamageScaleForList[48]=1.00
DamageScaleForList[49]=1.00
DamageScaleForList[50]=1.00
DamageScaleForList[51]=1.00
DamageScaleForList[52]=1.00
DamageScaleForList[53]=1.00
DamageScaleForList[54]=1.00
DamageScaleForList[55]=1.00
DamageScaleForList[56]=1.00
DamageScaleForList[57]=1.00
DamageScaleForList[58]=1.00
DamageScaleForList[59]=1.00
DamageScaleForList[60]=1.00
DamageScaleForList[61]=1.00
DamageScaleForList[62]=1.00
DamageScaleForList[63]=1.00
DamageScaleForList[64]=1.00
DamageScaleForList[65]=1.00
DamageScaleForList[66]=1.00
DamageScaleForList[67]=1.00
DamageScaleForList[68]=1.00
DamageScaleForList[69]=1.00
DamageScaleForList[70]=1.00
DamageScaleForList[71]=1.00
DamageScaleForList[72]=1.00
DamageScaleForList[73]=1.00
DamageScaleForList[74]=1.00
DamageScaleForList[75]=1.00
DamageScaleForList[76]=1.00
DamageScaleForList[77]=1.00
DamageScaleForList[78]=1.00
DamageScaleForList[79]=1.00
DamageScaleForList[80]=1.00
DamageScaleForList[81]=1.00
DamageScaleForList[82]=1.00
DamageScaleForList[83]=1.00
DamageScaleForList[84]=1.00
DamageScaleForList[85]=1.00
DamageScaleForList[86]=1.00
DamageScaleForList[87]=1.00
DamageScaleForList[88]=1.00
DamageScaleForList[89]=1.00
DamageScaleForList[90]=1.00
DamageScaleForList[91]=1.00
DamageScaleForList[92]=1.00
DamageScaleForList[93]=1.00
DamageScaleForList[94]=1.00
DamageScaleForList[95]=1.00
DamageScaleForList[96]=1.00
DamageScaleForList[97]=1.00
DamageScaleForList[98]=1.00
DamageScaleForList[99]=1.00

