I have no idea what would cause this. I'll see if I can grab any logs when I have more time later.The ScrN Balance V5 (Server), Server Veterancy Handler V6, ScrN Voting Handler, Kill Messages V2, Doom 3 Monsters Mode - ScrN Edition
Noticed a couple of strange bugs running ServerPerksX:
- Players start out with 'No perk available', and have to re-select a perk from the menu to fix.
- Started a game, players spawned with no weapons whatsoever (not even knife), could pick up weapons but were unable to use/access them.
- When using the Say command, player names appear twice in chat.
Download ServerPerksX v1.32
Custom Monster Collection
ServerPerksX can now dynamically create and load in a Monster Collection at runtime, which allows you, the modder, to specify new or replacement monsters by simply changing a line in the ServerPerksX.ini file. Monster Collections are the basic list of zombies used by both game modes to spawn waves of zeds in the game, and any modifications to this will be global. The ServerPerksX Monster Collection replacement module lets you selectively specify replacements, or completely override the default MonsterCollectionClass. Default values in ServerPerksX.ini represent the vanilla KFMod version of the Monster Collection, with all the classic zeds.
class KFMonstersCollection extends Object;
struct MClassTypes
{
var() config string MClassName, MID;
};
var() globalconfig array<MClassTypes> MonsterClasses;
var() array<MClassTypes> StandardMonsterClasses; // The standard monster classed
// Store info for a special squad we want to spawn outside of the normal wave system
struct SpecialSquad
{
var array<string> ZedClass;
var array<int> NumZeds;
};
// Special squads are used to spawn a squad outside of the normal wave system so
// we have a bit more control. Basically. these will only spawn towards the
// end of the normal squad list. This way you don't end up with a bunch of really
// beast Zeds spawning one right after the other> It also guarantees that this
// squad will always get used - Ramm
var array<SpecialSquad> SpecialSquads; // The currently used SpecialSquad array
var array<SpecialSquad> ShortSpecialSquads; // The special squad array for a short game
var array<SpecialSquad> NormalSpecialSquads; // The special squad array for a normal game
var array<SpecialSquad> LongSpecialSquads; // The special squad array for a long game
var array<SpecialSquad> FinalSquads; // Squads that spawn with the Patriarch
var config string FallbackMonsterClass;
var() string EndGameBossClass; // class of the end game boss, moved to non config - Ramm
static function PreLoadAssets()
{
local int i;
for(i=0;i<default.MonsterClasses.Length;i++)
{
class<KFMonster>(DynamicLoadObject(default.MonsterClasses[i].MClassName, Class'class')).static.PreCacheAssets(none);
}
}
defaultproperties
{
MonsterClasses(0)=(MClassName="KFChar.ZombieClot",MID="A")
MonsterClasses(1)=(MClassName="KFChar.ZombieCrawler",MID="B")
MonsterClasses(2)=(MClassName="KFChar.ZombieGoreFast",MID="C")
MonsterClasses(3)=(MClassName="KFChar.ZombieStalker",MID="D")
MonsterClasses(4)=(MClassName="KFChar.ZombieScrake",MID="E")
MonsterClasses(5)=(MClassName="KFChar.ZombieFleshpound",MID="F")
MonsterClasses(6)=(MClassName="KFChar.ZombieBloat",MID="G")
MonsterClasses(7)=(MClassName="KFChar.ZombieSiren",MID="H")
MonsterClasses(8)=(MClassName="KFChar.ZombieHusk",MID="I")
StandardMonsterClasses(0)=(MClassName="KFChar.ZombieClot",MID="A")
StandardMonsterClasses(1)=(MClassName="KFChar.ZombieCrawler",MID="B")
StandardMonsterClasses(2)=(MClassName="KFChar.ZombieGoreFast",MID="C")
StandardMonsterClasses(3)=(MClassName="KFChar.ZombieStalker",MID="D")
StandardMonsterClasses(4)=(MClassName="KFChar.ZombieScrake",MID="E")
StandardMonsterClasses(5)=(MClassName="KFChar.ZombieFleshpound",MID="F")
StandardMonsterClasses(6)=(MClassName="KFChar.ZombieBloat",MID="G")
StandardMonsterClasses(7)=(MClassName="KFChar.ZombieSiren",MID="H")
StandardMonsterClasses(8)=(MClassName="KFChar.ZombieHusk",MID="I")
FinalSquads(0)=(ZedClass=("KFChar.ZombieClot"),NumZeds=(4))
FinalSquads(1)=(ZedClass=("KFChar.ZombieClot","KFChar.ZombieCrawler"),NumZeds=(3,1))
FinalSquads(2)=(ZedClass=("KFChar.ZombieClot","KFChar.ZombieStalker","KFChar.ZombieCrawler"),NumZeds=(3,1,1))
ShortSpecialSquads(2)=(ZedClass=("KFChar.ZombieCrawler","KFChar.ZombieGorefast","KFChar.ZombieStalker","KFChar.ZombieScrake"),NumZeds=(2,2,1,1))
ShortSpecialSquads(3)=(ZedClass=("KFChar.ZombieBloat","KFChar.ZombieSiren","KFChar.ZombieFleshPound"),NumZeds=(1,2,1))
NormalSpecialSquads(3)=(ZedClass=("KFChar.ZombieCrawler","KFChar.ZombieGorefast","KFChar.ZombieStalker","KFChar.ZombieScrake"),NumZeds=(2,2,1,1))
NormalSpecialSquads(4)=(ZedClass=("KFChar.ZombieFleshPound"),NumZeds=(1))
NormalSpecialSquads(5)=(ZedClass=("KFChar.ZombieBloat","KFChar.ZombieSiren","KFChar.ZombieFleshPound"),NumZeds=(1,1,1))
NormalSpecialSquads(6)=(ZedClass=("KFChar.ZombieBloat","KFChar.ZombieSiren","KFChar.ZombieFleshPound"),NumZeds=(1,1,2))
LongSpecialSquads(4)=(ZedClass=("KFChar.ZombieCrawler","KFChar.ZombieGorefast","KFChar.ZombieStalker","KFChar.ZombieScrake"),NumZeds=(2,2,1,1))
LongSpecialSquads(6)=(ZedClass=("KFChar.ZombieFleshPound"),NumZeds=(1))
LongSpecialSquads(7)=(ZedClass=("KFChar.ZombieBloat","KFChar.ZombieSiren","KFChar.ZombieFleshPound"),NumZeds=(1,1,1))
LongSpecialSquads(8)=(ZedClass=("KFChar.ZombieBloat","KFChar.ZombieSiren","KFChar.ZombieScrake","KFChar.ZombieFleshPound"),NumZeds=(1,2,1,1))
LongSpecialSquads(9)=(ZedClass=("KFChar.ZombieBloat","KFChar.ZombieSiren","KFChar.ZombieScrake","KFChar.ZombieFleshPound"),NumZeds=(1,2,1,2))
FallbackMonsterClass="KFChar.ZombieStalker"
EndGameBossClass="KFChar.ZombieBoss"
}
[ServerPerksXMut.SRZombieList]
bCustomMonsterCollection=true
Monster=(Letter="A",MClass="Survival.SZombieClot")
Monster=(Letter="B",MClass="Survival.SZombieCrawler")
Monster=(Letter="C",MClass="Survival.SZombieGoreFast")
Monster=(Letter="D",MClass="Survival.SZombieStalker")
Monster=(Letter="E",MClass="Survival.SZombieScrake")
Monster=(Letter="F",MClass="Survival.SZombieFleshpound")
Monster=(Letter="G",MClass="Survival.SZombieBloat")
Monster=(Letter="H",MClass="Survival.SZombieSiren")
Monster=(Letter="I",MClass="Survival.SZombieHusk")
Monster=(Letter="J",MClass="Survival.SZombieMiniScrake")
Monster=(Letter="K",MClass="Survival.SZombieRocketHusk")
Monster=(Letter="L",MClass="Survival.SZombieMegaPound")
Monster=(Letter="M",MClass="Survival.SZombieSnatch")
Monster=(Letter="N",MClass="Survival.SZombieSmoker")
Monster=(Letter="O",MClass="Survival.SZombieGhost")
Monster=(Letter="P",MClass="Survival.SZombieHalfBreed")
Monster=(Letter="Q",MClass="Survival.SZombieArachna")
BossMonster="Survival.SHardPat"
FallbackMonster="Survival.SZombieStalker"
Squad=(SquadName="FodderWeak1",Zeds="3A1M")
Squad=(SquadName="FodderWeak2",Zeds="4A1M")
Squad=(SquadName="FodderMedium1",Zeds="2A2M1G")
Squad=(SquadName="FodderMedium2",Zeds="3A1M2G")
Squad=(SquadName="FodderStrong1",Zeds="1A2M1C1J1Q")
Squad=(SquadName="FodderStrong2",Zeds="2A2M1C1G")
Squad=(SquadName="AttackWeak",Zeds="2M4C")
Squad=(SquadName="AttackMedium",Zeds="2M3C1J1H")
Squad=(SquadName="AttackStrong",Zeds="1M3C2J1H1N")
Squad=(SquadName="CrawlerWeak",Zeds="2B1Q")
Squad=(SquadName="CrawlerMedium",Zeds="3B3Q1P")
Squad=(SquadName="CrawlerStrong",Zeds="1B4Q2P")
Squad=(SquadName="StalkerWeak",Zeds="3D")
Squad=(SquadName="StalkerMedium",Zeds="3D1O")
Squad=(SquadName="StalkerStrong",Zeds="3D3O1H1Q")
Squad=(SquadName="CrawlerApocalypse",Zeds="9B9B9Q4P")
Squad=(SquadName="BloatHusk",Zeds="2G1I1H1A1C")
Squad=(SquadName="BloatHuskScreen",Zeds="3G2I1H1N1A")
Squad=(SquadName="HuskScreen",Zeds="2I1N2C")
Squad=(SquadName="Husk",Zeds="1I")
Squad=(SquadName="RangedWeak",Zeds="1H1I1G1C")
Squad=(SquadName="RangedMedium",Zeds="2H1I1N")
Squad=(SquadName="RangedStrong",Zeds="2H1I1K1N")
Squad=(SquadName="RocketScreen",Zeds="2K1N2H")
Squad=(SquadName="MiniScrakes",Zeds="3J2C")
Squad=(SquadName="ScrakeFodderWeak",Zeds="1E2A2C1H")
Squad=(SquadName="ScrakeFodderMedium",Zeds="1E2M2C1J1H1N")
Squad=(SquadName="ScrakeFodderStrong",Zeds="1E2M1G2J1N1K")
Squad=(SquadName="ScrakeFamily",Zeds="2E4J")
Squad=(SquadName="BulletSponge1",Zeds="1E2G1P1N")
Squad=(SquadName="BulletSponge2",Zeds="1E3G1H1N")
Squad=(SquadName="BulletSponge3",Zeds="2E2G1K1N")
Squad=(SquadName="Pounder",Zeds="1F")
Squad=(SquadName="DoublePounder",Zeds="2F")
Squad=(SquadName="TriplePounder",Zeds="3F")
Squad=(SquadName="ScreamCity",Zeds="4H1N")
Squad=(SquadName="HardAttack",Zeds="3C3O1P2Q")
Squad=(SquadName="Megapound",Zeds="1L")
bOverrideInvasionSquads=true
bOverrideInvasionWaves=true
SquadSet=(SetName="Starters",Squads=("FodderWeak1","FodderWeak2","FodderMedium1","AttackWeak","StalkerWeak"))
SquadSet=(SetName="StrongFodder",Squads=("AttackMedium","FodderStrong2","FodderStrong1"))
SquadSet=(SetName="MediumFodder",Squads=("FodderMedium1","FodderMedium2"))
SquadSet=(SetName="Attack",Squads=("AttackMedium","AttackStrong"))
SquadSet=(SetName="StartersOpener",Squads=("FodderStrong1","CrawlerMedium"))
SquadSet=(SetName="CrawlerSet",Squads=("CrawlerStrong","CrawlerMedium"))
SquadSet=(SetName="CrawlerStalkerSet",Squads=("CrawlerStrong","StalkerMedium"))
SquadSet=(SetName="CrawlerApocalypse",Squads=("CrawlerApocalypse"))
SquadSet=(SetName="SirenMix",Squads=("RangedMedium","StalkerStrong"))
SquadSet=(SetName="GhostMix",Squads=("StalkerStrong","HardAttack"))
SquadSet=(SetName="BossHelpers",Squads=("FodderStrong1","StalkerMedium","MiniScrakes"))
SquadSet=(SetName="HardFodder",Squads=("AttackStrong","CrawlerStrong","StalkerMedium"))
SquadSet=(SetName="ScrakeWeak",Squads=("ScrakeFodderWeak"))
SquadSet=(SetName="ScrakeMedium",Squads=("ScrakeFodderMedium"))
SquadSet=(SetName="ScrakeHard",Squads=("ScrakeFodderStrong"))
SquadSet=(SetName="ScrakeFamily",Squads=("ScrakeFamily"))
SquadSet=(SetName="WeakPounder",Squads=("Pounder","FodderWeak"))
SquadSet=(SetName="TwoPoundOpener",Squads=("DoublePounder","AttackMedium","BloatHusk"))
SquadSet=(SetName="BulletSponges",Squads=("BulletSponge1","BulletSponge2","BulletSponge3"))
SquadSet=(SetName="MegaPoundOpener",Squads=("MegaPound"))
SquadSet=(SetName="UltraHard",Squads=("TriplePounder","Pounder","ScreamCity","RocketScreen","ScrakeFamily","CrawlerApocalypse"))
SquadSet=(SetName="WeakRanged",Squads=("Husk","HuskScreen","RangedWeak"))
SquadSet=(SetName="StrongRanged",Squads=("HuskScreen","RangedMedium","RangedStrong"))
SquadSet=(SetName="RocketMix",Squads=("RangedStrong","BloatHusk","RocketScreen"))
SquadSet=(Setname="LateWaveFodder",Squads=("BulletSponge1","HardAttack","RangedStrong"))
SquadSet=(SetName="RocketOpener",Squads=("RocketScreen","BloatHusk","ScreamCity"))
Wave=(WaveName="Wave1",Sets=("Starters"),OpeningSet="StartersOpener")
Wave=(WaveName="Wave2",Sets=("CrawlerStalkerSet","Attack"),Squads=("Husk"),OpeningSet="CrawlerStalkerSet")
Wave=(WaveName="Wave3",Sets=("MediumFodder","Attack","GhostMix","SirenMix"),Squads=("Husk"),OpeningSet="CrawlerApocalypse")
Wave=(WaveName="Wave4",Sets=("ScrakeWeak","SirenMix","CrawlerStalkerSet","MediumFodder"),OpeningSet="ScrakeMedium")
Wave=(WaveName="Wave5",Sets=("ScrakeWeak","ScrakeMedium","CrawlerSet","StrongFodder","WeakRanged"),Squads=("RangedWeak"),OpeningSet="ScrakeFamily")
Wave=(WaveName="Wave6",Sets=("StrongFodder","SirenMix","WeakRanged","CrawlerStalkerSet","ScrakeHard","ScrakeWeak"),OpeningSet="WeakPounder")
Wave=(WaveName="Wave7",Sets=("HardFodder","MediumFodder","SirenMix","ScrakeMedium","ScrakeHard","WeakRanged"),OpeningSet="WeakPounder")
Wave=(WaveName="Wave8",Sets=("ScrakeFamily","StrongRanged","ScrakeMedium","WeakPounder","StrongFodder","HardFodder"),Squads=("BulletSponge1"),OpeningSet="RocketOpener")
Wave=(WaveName="Wave9",Sets=("Pounder","ScrakeFamily","RocketMix","StrongFodder","ScrakeWeak","LateWaveFodder","CrawlerSet"),OpeningSet="TwoPoundOpener")
Wave=(WaveName="Wave10",Sets=("GhostMix","SirenMix","ScrakeFamily","ScrakeHard","BulletSponges","StrongRanged","LateWaveFodder","MediumFodder","Attack"),OpeningSet="MegaPoundOpener")
Wave=(WaveName="London10",Sets=("UltraHard"),OpeningSet="MegaPoundOpener")
Wave=(WaveName="BossHelpers",OpeningSet="BossHelpers")
GlobalWaves=(WaveNum=1,Short="Wave1",Normal="Wave1",Long="Wave1")
GlobalWaves=(WaveNum=2,Short="Wave3",Normal="Wave3",Long="Wave2")
GlobalWaves=(WaveNum=3,Short="Wave5",Normal="Wave4",Long="Wave3")
GlobalWaves=(WaveNum=4,Short="Wave9",Normal="Wave6",Long="Wave4")
GlobalWaves=(WaveNum=5,Normal="Wave7",Long="Wave5")
GlobalWaves=(WaveNum=6,Normal="Wave9",Long="Wave6")
GlobalWaves=(WaveNum=7,Normal="Wave10",Long="Wave7",NumZeds=40)
GlobalWaves=(WaveNum=8,Long="Wave8",NumZeds=45)
GlobalWaves=(WaveNum=9,Long="Wave9",NumZeds=48)
GlobalWaves=(WaveNum=10,Long="Wave10",NumZeds=50)
GlobalWaves=(WaveNum=0,Short="BossHelpers",Normal="BossHelpers",Long="BossHelpers")
MapWaves=(MapName="KF-WestLondon",WaveNum=10,Long="London10",MinDifficulty=4,NumZeds=30)
StorySquadReplacements=(ReplaceClass="Survival.SZombieSnatch",ZedTypeToReplace="clot",PercentReplaced=0.5)
StorySquadReplacements=(ReplaceClass="Survival.SZombieHalfBreed",ZedTypeToReplace="crawler",PercentReplaced=0.25)
StorySquadReplacements=(ReplaceClass="Survival.SZombieGhost",ZedTypeToReplace="stalker",PercentReplaced=0.40)
StorySquadReplacements=(ReplaceClass="Survival.SZombieRocketHusk",ZedTypeToReplace="husk",PercentReplaced=0.35)
StorySquadReplacements=(ReplaceClass="Survival.SZombieMiniScrake",ZedTypeToReplace="scrake",PercentReplaced=0.20)
StorySquadAdditions=(SpawnsWithClass="Survival.SZombieSnatch",SpawnClass="Survival.SZombieMiniScrake",NumToSpawn=1,PercentChance=0.5)
StorySquadAdditions=(SpawnsWithClass="Survival.SZombieScrake",SpawnClass="Survival.SZombieMiniScrake",NumToSpawn=2,PercentChance=0.8)
StorySquadAdditions=(SpawnsWithClass="Survival.SZombieHusk",SpawnClass="Survival.SZombieSmoker",NumToSpawn=1,PercentChance=0.8)
StorySquadAdditions=(SpawnsWithClass="Survival.SZombieFleshpound",SpawnClass="Survival.SZombieRocketHusk",NumToSpawn=1,PercentChance=0.8)
;StorySquadAdditions=(SpawnsWithClass="Survival.SZombieFleshpound",SpawnClass="Survival.SZombieMegaPound",NumToSpawn=1,PercentChance=0.2)
StorySquadAdditions=(SpawnsWithClass="Survival.SZombieRocketHusk",SpawnClass="Survival.SZombieSmoker",NumToSpawn=1,PercentChance=0.8)
I could not replicate this problem, is anyone else having an archive damaged issue with this?Download ServerPerksX v1.32 archive is damaged
Yes, you can do that if you already have a Monster Collection class made, and you don't need to do anything else to get the monster list to work properly. Simply set the MonsterCollectionClass variable in the [ServerPerksXMut.ServerPerksMut] section to the "Package.ClassName" of that monster collection. By leaving that blank, it will use the defaults.
Note: Your MonsterCollection must extend KFMonstersCollection to be valid! You should use one of the Event Zed collections as your template (all they have in them is default properties, no need to write any of the other stuff).
Alternatively OR additionally, you can also have the ZedList create a monster class dynamically by specifying it in the .ini file under the [ServerPerksXMut.SRZombieList] section. The Monster Collection it creates will use the monster collection defined by the MonsterCollectionClass as its base (or the defaults if it is undefined). Set the bCustomMonsterCollection variable to true, and it'll activate the monster definitions. When you change that variable to true, any Monster=(XXX) definitions you add will be APPENDED to your monster collection, and if you specify any monster definitions with a letter ID which is the same as one that is in the defined monster list, it will simply replace them. Otherwise, it'll add them to it.
I find this method better because it allows you to add, or change, zeds on the fly. For instance, if you do not define a MonsterCollectionClass in the .ini file, it will always use the base zeds as its defaults. This allows Killing Floor event zeds to be used whenever an event is going on, and you will always add your new zeds on top of them. So if the summer sideshow event is going on, those zeds will show up in addition to yours. (but if you replace any of the default zeds, yours will show up instead for those defined).
For reference, here's a fully created monster wave definition I've made for another mod I'm working on:
Spoiler!
Code:[ServerPerksXMut.SRZombieList] bCustomMonsterCollection=true Monster=(Letter="A",MClass="Survival.SZombieClot") Monster=(Letter="B",MClass="Survival.SZombieCrawler") Monster=(Letter="C",MClass="Survival.SZombieGoreFast") Monster=(Letter="D",MClass="Survival.SZombieStalker") Monster=(Letter="E",MClass="Survival.SZombieScrake") Monster=(Letter="F",MClass="Survival.SZombieFleshpound") Monster=(Letter="G",MClass="Survival.SZombieBloat") Monster=(Letter="H",MClass="Survival.SZombieSiren") Monster=(Letter="I",MClass="Survival.SZombieHusk") Monster=(Letter="J",MClass="Survival.SZombieMiniScrake") Monster=(Letter="K",MClass="Survival.SZombieRocketHusk") Monster=(Letter="L",MClass="Survival.SZombieMegaPound") Monster=(Letter="M",MClass="Survival.SZombieSnatch") Monster=(Letter="N",MClass="Survival.SZombieSmoker") Monster=(Letter="O",MClass="Survival.SZombieGhost") Monster=(Letter="P",MClass="Survival.SZombieHalfBreed") Monster=(Letter="Q",MClass="Survival.SZombieArachna") BossMonster="Survival.SHardPat" FallbackMonster="Survival.SZombieStalker" Squad=(SquadName="FodderWeak1",Zeds="3A1M") Squad=(SquadName="FodderWeak2",Zeds="4A1M") Squad=(SquadName="FodderMedium1",Zeds="2A2M1G") Squad=(SquadName="FodderMedium2",Zeds="3A1M2G") Squad=(SquadName="FodderStrong1",Zeds="1A2M1C1J1Q") Squad=(SquadName="FodderStrong2",Zeds="2A2M1C1G") Squad=(SquadName="AttackWeak",Zeds="2M4C") Squad=(SquadName="AttackMedium",Zeds="2M3C1J1H") Squad=(SquadName="AttackStrong",Zeds="1M3C2J1H1N") Squad=(SquadName="CrawlerWeak",Zeds="2B1Q") Squad=(SquadName="CrawlerMedium",Zeds="3B3Q1P") Squad=(SquadName="CrawlerStrong",Zeds="1B4Q2P") Squad=(SquadName="StalkerWeak",Zeds="3D") Squad=(SquadName="StalkerMedium",Zeds="3D1O") Squad=(SquadName="StalkerStrong",Zeds="3D3O1H1Q") Squad=(SquadName="CrawlerApocalypse",Zeds="9B9B9Q4P") Squad=(SquadName="BloatHusk",Zeds="2G1I1H1A1C") Squad=(SquadName="BloatHuskScreen",Zeds="3G2I1H1N1A") Squad=(SquadName="HuskScreen",Zeds="2I1N2C") Squad=(SquadName="Husk",Zeds="1I") Squad=(SquadName="RangedWeak",Zeds="1H1I1G1C") Squad=(SquadName="RangedMedium",Zeds="2H1I1N") Squad=(SquadName="RangedStrong",Zeds="2H1I1K1N") Squad=(SquadName="RocketScreen",Zeds="2K1N2H") Squad=(SquadName="MiniScrakes",Zeds="3J2C") Squad=(SquadName="ScrakeFodderWeak",Zeds="1E2A2C1H") Squad=(SquadName="ScrakeFodderMedium",Zeds="1E2M2C1J1H1N") Squad=(SquadName="ScrakeFodderStrong",Zeds="1E2M1G2J1N1K") Squad=(SquadName="ScrakeFamily",Zeds="2E4J") Squad=(SquadName="BulletSponge1",Zeds="1E2G1P1N") Squad=(SquadName="BulletSponge2",Zeds="1E3G1H1N") Squad=(SquadName="BulletSponge3",Zeds="2E2G1K1N") Squad=(SquadName="Pounder",Zeds="1F") Squad=(SquadName="DoublePounder",Zeds="2F") Squad=(SquadName="TriplePounder",Zeds="3F") Squad=(SquadName="ScreamCity",Zeds="4H1N") Squad=(SquadName="HardAttack",Zeds="3C3O1P2Q") Squad=(SquadName="Megapound",Zeds="1L") bOverrideInvasionSquads=true bOverrideInvasionWaves=true SquadSet=(SetName="Starters",Squads=("FodderWeak1","FodderWeak2","FodderMedium1","AttackWeak","StalkerWeak")) SquadSet=(SetName="StrongFodder",Squads=("AttackMedium","FodderStrong2","FodderStrong1")) SquadSet=(SetName="MediumFodder",Squads=("FodderMedium1","FodderMedium2")) SquadSet=(SetName="Attack",Squads=("AttackMedium","AttackStrong")) SquadSet=(SetName="StartersOpener",Squads=("FodderStrong1","CrawlerMedium")) SquadSet=(SetName="CrawlerSet",Squads=("CrawlerStrong","CrawlerMedium")) SquadSet=(SetName="CrawlerStalkerSet",Squads=("CrawlerStrong","StalkerMedium")) SquadSet=(SetName="CrawlerApocalypse",Squads=("CrawlerApocalypse")) SquadSet=(SetName="SirenMix",Squads=("RangedMedium","StalkerStrong")) SquadSet=(SetName="GhostMix",Squads=("StalkerStrong","HardAttack")) SquadSet=(SetName="BossHelpers",Squads=("FodderStrong1","StalkerMedium","MiniScrakes")) SquadSet=(SetName="HardFodder",Squads=("AttackStrong","CrawlerStrong","StalkerMedium")) SquadSet=(SetName="ScrakeWeak",Squads=("ScrakeFodderWeak")) SquadSet=(SetName="ScrakeMedium",Squads=("ScrakeFodderMedium")) SquadSet=(SetName="ScrakeHard",Squads=("ScrakeFodderStrong")) SquadSet=(SetName="ScrakeFamily",Squads=("ScrakeFamily")) SquadSet=(SetName="WeakPounder",Squads=("Pounder","FodderWeak")) SquadSet=(SetName="TwoPoundOpener",Squads=("DoublePounder","AttackMedium","BloatHusk")) SquadSet=(SetName="BulletSponges",Squads=("BulletSponge1","BulletSponge2","BulletSponge3")) SquadSet=(SetName="MegaPoundOpener",Squads=("MegaPound")) SquadSet=(SetName="UltraHard",Squads=("TriplePounder","Pounder","ScreamCity","RocketScreen","ScrakeFamily","CrawlerApocalypse")) SquadSet=(SetName="WeakRanged",Squads=("Husk","HuskScreen","RangedWeak")) SquadSet=(SetName="StrongRanged",Squads=("HuskScreen","RangedMedium","RangedStrong")) SquadSet=(SetName="RocketMix",Squads=("RangedStrong","BloatHusk","RocketScreen")) SquadSet=(Setname="LateWaveFodder",Squads=("BulletSponge1","HardAttack","RangedStrong")) SquadSet=(SetName="RocketOpener",Squads=("RocketScreen","BloatHusk","ScreamCity")) Wave=(WaveName="Wave1",Sets=("Starters"),OpeningSet="StartersOpener") Wave=(WaveName="Wave2",Sets=("CrawlerStalkerSet","Attack"),Squads=("Husk"),OpeningSet="CrawlerStalkerSet") Wave=(WaveName="Wave3",Sets=("MediumFodder","Attack","GhostMix","SirenMix"),Squads=("Husk"),OpeningSet="CrawlerApocalypse") Wave=(WaveName="Wave4",Sets=("ScrakeWeak","SirenMix","CrawlerStalkerSet","MediumFodder"),OpeningSet="ScrakeMedium") Wave=(WaveName="Wave5",Sets=("ScrakeWeak","ScrakeMedium","CrawlerSet","StrongFodder","WeakRanged"),Squads=("RangedWeak"),OpeningSet="ScrakeFamily") Wave=(WaveName="Wave6",Sets=("StrongFodder","SirenMix","WeakRanged","CrawlerStalkerSet","ScrakeHard","ScrakeWeak"),OpeningSet="WeakPounder") Wave=(WaveName="Wave7",Sets=("HardFodder","MediumFodder","SirenMix","ScrakeMedium","ScrakeHard","WeakRanged"),OpeningSet="WeakPounder") Wave=(WaveName="Wave8",Sets=("ScrakeFamily","StrongRanged","ScrakeMedium","WeakPounder","StrongFodder","HardFodder"),Squads=("BulletSponge1"),OpeningSet="RocketOpener") Wave=(WaveName="Wave9",Sets=("Pounder","ScrakeFamily","RocketMix","StrongFodder","ScrakeWeak","LateWaveFodder","CrawlerSet"),OpeningSet="TwoPoundOpener") Wave=(WaveName="Wave10",Sets=("GhostMix","SirenMix","ScrakeFamily","ScrakeHard","BulletSponges","StrongRanged","LateWaveFodder","MediumFodder","Attack"),OpeningSet="MegaPoundOpener") Wave=(WaveName="London10",Sets=("UltraHard"),OpeningSet="MegaPoundOpener") Wave=(WaveName="BossHelpers",OpeningSet="BossHelpers") GlobalWaves=(WaveNum=1,Short="Wave1",Normal="Wave1",Long="Wave1") GlobalWaves=(WaveNum=2,Short="Wave3",Normal="Wave3",Long="Wave2") GlobalWaves=(WaveNum=3,Short="Wave5",Normal="Wave4",Long="Wave3") GlobalWaves=(WaveNum=4,Short="Wave9",Normal="Wave6",Long="Wave4") GlobalWaves=(WaveNum=5,Normal="Wave7",Long="Wave5") GlobalWaves=(WaveNum=6,Normal="Wave9",Long="Wave6") GlobalWaves=(WaveNum=7,Normal="Wave10",Long="Wave7",NumZeds=40) GlobalWaves=(WaveNum=8,Long="Wave8",NumZeds=45) GlobalWaves=(WaveNum=9,Long="Wave9",NumZeds=48) GlobalWaves=(WaveNum=10,Long="Wave10",NumZeds=50) GlobalWaves=(WaveNum=0,Short="BossHelpers",Normal="BossHelpers",Long="BossHelpers") MapWaves=(MapName="KF-WestLondon",WaveNum=10,Long="London10",MinDifficulty=4,NumZeds=30) StorySquadReplacements=(ReplaceClass="Survival.SZombieSnatch",ZedTypeToReplace="clot",PercentReplaced=0.5) StorySquadReplacements=(ReplaceClass="Survival.SZombieHalfBreed",ZedTypeToReplace="crawler",PercentReplaced=0.25) StorySquadReplacements=(ReplaceClass="Survival.SZombieGhost",ZedTypeToReplace="stalker",PercentReplaced=0.40) StorySquadReplacements=(ReplaceClass="Survival.SZombieRocketHusk",ZedTypeToReplace="husk",PercentReplaced=0.35) StorySquadReplacements=(ReplaceClass="Survival.SZombieMiniScrake",ZedTypeToReplace="scrake",PercentReplaced=0.20) StorySquadAdditions=(SpawnsWithClass="Survival.SZombieSnatch",SpawnClass="Survival.SZombieMiniScrake",NumToSpawn=1,PercentChance=0.5) StorySquadAdditions=(SpawnsWithClass="Survival.SZombieScrake",SpawnClass="Survival.SZombieMiniScrake",NumToSpawn=2,PercentChance=0.8) StorySquadAdditions=(SpawnsWithClass="Survival.SZombieHusk",SpawnClass="Survival.SZombieSmoker",NumToSpawn=1,PercentChance=0.8) StorySquadAdditions=(SpawnsWithClass="Survival.SZombieFleshpound",SpawnClass="Survival.SZombieRocketHusk",NumToSpawn=1,PercentChance=0.8) ;StorySquadAdditions=(SpawnsWithClass="Survival.SZombieFleshpound",SpawnClass="Survival.SZombieMegaPound",NumToSpawn=1,PercentChance=0.2) StorySquadAdditions=(SpawnsWithClass="Survival.SZombieRocketHusk",SpawnClass="Survival.SZombieSmoker",NumToSpawn=1,PercentChance=0.8)
This particular configuration replaces all of the default zeds, adds more, and defines a bunch of waves, wave sets, squads, and basically everything else that can be done. And it's all done without a MonsterCollection class (as it allows ServerPerksX to create one when the server launches).
As far as the letter ID goes, it's best (for simplicity's sake) to just stick with A, B, C, D, E, F etc. And if you go all the way through to Z, start again in lower cases (it's case sensitive). There's probably never going to be a need to do anything else, but if you find yourself running out... basically, ANY character can be used here which is supported by Unreal's native code. Parentheses, asterixes, Cyrillic letters, foreign language characters etc. If you want a useful list of what you can use, go to Start Menu -> Accessories -> System Tools -> Character map. Then select the "advanced view" check box, and make sure Unicode is selected (this will make the character map show all valid unicode characters for the selected font which have a graphic character defined). Then select the font Courier New, since of the default fonts it has the most graphic characters. Everything that shows up there is valid here. And that's a ****ing ****load of characters. Basically, if you can make your keyboard spit it out, you can use it as a monster ID. Hell, you can even use numbers... but then your squad definitions would get really confusing to look at, since you'd use a number followed by a number to define a squad.This is awesome, thank you! I hadn't even considered using the Event Zed collections as a template. I was just going to make several subclasses of the KFMonstersCollection and load them as I saw fit (as my own 'events', for example), but this should save me a lot of time.
This might be a stupid question, but I'm rather new to UnrealScript. If I wanted to write a mutator that allowed random bosses to be spawned mid-game (similar to the Doom 3 mod), would this sort of thing be compatible with ServerPerksX?
Also, I don't suppose anyone has a reference to which unicode characters are valid for defining the monster array (or a list of invalid characters, as the case may be)?
As far as the letter ID goes, it's best (for simplicity's sake) to just stick with A, B, C, D, E, F etc. And if you go all the way through to Z, start again in lower cases (it's case sensitive). There's probably never going to be a need to do anything else, but if you find yourself running out... basically, ANY character can be used here which is supported by Unreal's native code. Parentheses, asterixes, Cyrillic letters, foreign language characters etc. If you want a useful list of what you can use, go to Start Menu -> Accessories -> System Tools -> Character map. Then select the "advanced view" check box, and make sure Unicode is selected (this will make the character map show all valid unicode characters for the selected font which have a graphic character defined). Then select the font Courier New, since of the default fonts it has the most graphic characters. Everything that shows up there is valid here. And that's a ****ing ****load of characters. Basically, if you can make your keyboard spit it out, you can use it as a monster ID. Hell, you can even use numbers... but then your squad definitions would get really confusing to look at, since you'd use a number followed by a number to define a squad.
Just stick to letters, if you ask me. Note: I have not tested the use of all unicode characters, but it should work theoretically, provided you stick to the actual, encoded characters in Unicode 4.0 (of which there are like 190,000).
Basically, I'm looking for there to be a chance of a random boss spawning on any wave after a certain wave. It doesn't really matter at what point in the wave they spawn, but I don't want it to be predictable. So, after Wave X there's a % chance that each wave could include a boss.As far as random bosses go... hmm. Well, that's interesting. How do you want the bosses to show up? Just in the middle of the wave? At the beginning? KF's spawning routine doesn't really support special mechanics for bosses, but one thing you CAN do is define an "OpeningSet" for a wave that has your boss in it, which will make him show up on whatever wave has that opening set. Heck, you can even shove the patriarch into the normal rotation (but do note that the vanilla patriarch will trigger the end of the game if he dies).
If you let me know exactly what you want I can try to think up a way to get it to work with this and maybe put it in an update.
bSpawnSuperMonsters=True
# E.g. 10*0.4 = wave 4 in long game, 7*0.4 = wave 3 in medium game etc.
BossStartWaves=0.500000
# 0.45 = 45%
BossWaveRate=0.500000
BossWaveReduction=0.400000
# For example, Maledict has 4000hp (on Normal difficulty). If BossPerPlayerHP=0.4
# 4000 + 4000*0.4*(6-1) = 12000
BossPerPlayerHP=0.400000
# For example, if PatBossMult=3.0, then Maledict's health will be
# 12000 * 3 = 36000hp (6 players, Normal difficulty).
PatBossMult=3.000000
#PatReplacement=KFChar.ZombieBoss
#PatReplacement=ScrnMonstersMut.HardPat
#LargePatReplacement=KFChar.ZombieBoss
#LargePatReplacement=ScrnMonstersMut.HardPat
LargeMaps=KF-WestLondon
LargeMaps=KF-Manor
LargeMaps=KF-Farm
LargeMaps=KF-MountainPass
LargeMaps=KF-MountainPassNight
LargeMaps=kf-abusementpark
LargeMaps=kf-icebreaker
LargeMaps=kf-suburbia
LargeMaps=kf-wyre
LargeMaps=KF-ArenaWars
LargeMaps=KF-Afghanistan
LargeMaps=KF-DeathBasinSands
LargeMaps=KF-DeathBasinSandsNight
LargeMaps=KF-Dust_Nightmare
LargeMaps=KF-ElecFields-V1_2
LargeMaps=KF-HellGateFinal1-2
LargeMaps=KF-Helms_Deep
LargeMaps=KF-Hyperblast2-V1_2
LargeMaps=Kf-SilentHillBeta2-0
LargeBosses=Guardian
LargeBosses=HunterHellTime
LargeBosses=Maledict
LargeBosses=Cyberdemon
NormalBosses=Sabaoth
NormalBosses=Vagary
NormalBosses=HunterBerserk
NormalBosses=HunterInvul
Auto state EndGameTracker
{
Begin:
while( !Level.Game.bGameEnded )
{
[COLOR="Lime"]Sleep(1.f);[/COLOR]
if( MidGameSaveWaves>0 && KFGT!=None && KFGT.WaveNum!=LastSavedWave )
{
LastSavedWave = KFGT.WaveNum;
InitNextWave();
}
}
CheckWinOrLose();
SaveStats();
}
state SaveStats
{
Begin:
SaveStats();
if ( !Level.Game.bGameEnded )
GotoState('EndGameTracker');
}
state SaveStatsState
{
Begin:
SaveStats();
if ( !Level.Game.bGameEnded )
GotoState('EndGameTracker');
}
I'm loving the mutator so far; the custom spawns and waves are gonna be fun when I get it all set. But I'm wondering why after installing this mutator, no one can buy things like the thompson, or the flare revolvers, or basically any of the newer items, DLC included. I stumbled on a thread mentioning KF_DLC.utx for a similar problem last night. I checked my server and sure enough the file was tiny compared the the one I had on my home PC, so I uploaded the bigger one, hoping it would fix the issue, and it didn't, at least for the flares. I don't have many DLC packs so I can't say for sure what's fixed and what isn't. But then, didn't I read somewhere that these mutators are unable to check if a user has the rights to the DLC weapons, only the DLC characters?
Thanks PotentiaLeaena, but they are listed in the config correctly. A helpful modder told me the problem is basically that servers running non-whitelisted content can't lookup whether or not a user has purchased the DLC, and just assumes no one has. There is a fix, but not sure if tripwire-sanctioned per se, so I won't mention, but it is indeed in the source code files in KFMod.