/***************************************************************************** * ScrN Total Game Balance * @author [ScrN]PooSH, contact via steam: http://steamcommunity.com/id/scrn-poosh/ * Copyright (c) 2012-2018 PU Developing IK, All Rights Reserved. *****************************************************************************/ class ScrnBalance extends Mutator Config(ScrnBalanceSrv); #exec OBJ LOAD FILE=ScrnAnims.ukx #exec OBJ LOAD FILE=ScrnTex.utx #exec OBJ LOAD FILE=ScrnAch_T.utx const VERSION = 96106; var ScrnBalance Mut; // pointer to self to use in static functions, i.e class'ScrnBalance'.default.Mut var const string BonusCapGroup; var localized string strBonusLevel; var localized string strVersion; var localized string strStatus, strStatus2; var localized string strSrvWarning, strSrvWarning2; var localized string strBetaOnly; // SRVFLAGS var transient int SrvFlags; // used for network replication of the values below var globalconfig bool bSpawn0, bNoStartCashToss, bMedicRewardFromTeam; var globalconfig bool bAltBurnMech, bDoubleDoT; var globalconfig bool bReplaceNades, bShieldWeight, bHardcore, bBeta; var globalconfig bool bShowDamages, bManualReload, bForceManualReload, bAllowWeaponLock; var globalconfig bool bNoPerkChanges, bPerkChangeBoss, bPerkChangeDead, b10Stars; VAR globalconfig bool bTraderSpeedBoost; // END OF SRVFLAGS var transient byte HardcoreLevel; // set from ScrnGameRules. Used for replication purposes only. var deprecated byte ReqBalanceMode; var transient byte SrvReqBalanceMode; var globalconfig int ForcedMaxPlayers; var globalconfig int BonusLevelNormalMax , BonusLevelHardMin, BonusLevelHardMax , BonusLevelSuiMin, BonusLevelSuiMax , BonusLevelHoeMin, BonusLevelHoeMax; var globalconfig float Post6RequirementScaling, WeldingRequirementScaling, StalkerRequirementScaling; var transient int MinLevel, MaxLevel; // Changing default value of variable disables its replication, cuz engine thinks it wasn't changed var transient int SrvMinLevel, SrvMaxLevel; var transient bool bInitialized; var KFGameType KF; var ScrnGameType ScrnGT; var bool bStoryMode; // Objective Game mode (KFStoryGameInfo) var bool bTSCGame; // Team Survival Competition (TSCGame) struct SPickupReplacement { var class oldClass; var class newClass; }; var array pickupReplaceArray; var const int FragReplacementIndex; var globalconfig bool bReplacePickups, bReplacePickupsStory; var class Functions; var protected byte GameStartCountDown; //v3 /** * PerkedWeapons is a list of weapons, which gets bonuses of specified perk * PerkedAmmo: list of WEAPONS, which gets bonuses for primary ammo (count, mag. size etc.) * PerkedSecondaryAmmo: list of WEAPONS, which gets bonuses for secondary ammo (count) * * All 3 lists have the same format: * PerkedWeapons|PerkedAmmo|PerkedSecondaryAmmo=:: * , where * Perk index is an index in Perks array, 0-7. * weapon class name: class name of custom weapon without package name, e.g. G36CAssaultRifle * Bonuses: string of bonus letters: * A - primary ammo bonuses (count, magazine size, discounts) * B - secondary ammo bonuses * P - primary fire bonuses (damage, headshot multiplier, fire rate) * S - secondary fire bonuses * $ - discount * D - change primary fire's damage type to perk's default one * d - change secondary fire's damage type to perk's default one * * - add to special weapons list * If bonuses aren't specified, all of them will be applied, except Dd* */ var globalconfig array PerkedWeapons, CustomPerks; //var StringReplicationInfo ClientPerkedWeaponsSRI, ClientPerksSRI; var array< class > Perks; /* // removed because array replication doesn't wort in unreal engine 2 struct CustomPerkedClass { var int PerkIndex; var class BonusClass; }; var array CustomPerkedClassArray; */ var ScrnBurnMech BurnMech; // Alternate Burning Mechanism // v9.05: replaced ammo spawn behavior. // Now ammo boxes are spawned only once per wave (at the beginning). // When picked up, another box will spawn somewhere else on the map (after some cooldown time). // When wave is near the end (TotalMaxMonsters == 0 and NumMonsters < 10), ammo box count is lowered // 5 times. var transient byte PickupSetupMonsters; var transient bool bPickupSetupReduced; var ScrnMapInfo MapInfo; var ScrnGameRules GameRules; var ScrnSrvReplInfo SrvInfo; var localized string strAchEarn; var globalconfig bool bBroadcastAchievementEarn; //tell other players that somebody earned an achievement (excluding map achs) var globalconfig int AchievementFlags; var transient int SrvAchievementFlags; // used for network replication var bool bUseAchievements; const ACH_ALLFLAGS = 0xFFFFFFFF; const ACH_ENABLE = 0x0001; const ACH_HARD = 0x0002; const ACH_SUI = 0x0004; const ACH_HOE = 0x0008; const ACH_SCRNZEDS = 0x0010; const ACH_WPCZEDS = 0x0020; const ACH_HARDPAT = 0x0040; const ACH_DOOM3 = 0x0080; const ACH_TOURNEY = 0x1000; var globalconfig bool bSaveStatsOnAchievementEarned; //save stats to serverpeprks database every time an achievement is earned var transient bool bNeedToSaveStats; var transient float NextStatSaveTime; var protected bool bTradingDoorsOpen; // used to check wave start / end var protected transient byte CurWave; // used to check wave start / end var ScrnCustomWeaponLink CustomWeaponLink; var transient float FirstTickTime; var transient bool bTickExecuted; var transient bool bInitReplicationReceived; var Mutator ServerPerksMut; var transient bool bAllowAlwaysPerkChanges; // value replicated from ServerPerksMut var globalconfig bool bAllowVoting; var ScrnBalanceVoting MyVotingOptions; var globalconfig bool bPauseTraderOnly; //game can be vote-paused in trader time only var globalconfig float SkippedTradeTimeMult; //how much of the skipped trader time (mvote ENDTRADE) to add to the next one (0 - don't add, 1 - full, 0.5 - half of the skipped time) var transient int TradeTimeAddSeconds; //amount of seconds to add to the next trader time var globalconfig bool bAllowBlameVote, bAllowKickVote; var globalconfig int BlameVoteCoolDown; var globalconfig bool bAllowPauseVote, bAllowLockPerkVote, bAllowBoringVote; var globalconfig byte MaxVoteKillMonsters; var globalconfig int MaxVoteKillHP; var globalconfig bool bVoteKillCheckVisibility; var globalconfig float VoteKillPenaltyMult; var globalconfig byte MinVoteFF, MaxVoteFF; var globalconfig byte MinVoteDifficulty; var ScrnBalancePersistence Persistence; var globalconfig bool bDynamicLevelCap; var int OriginalMaxLevel; var globalconfig string ServerPerksPkgName; // if user didn't added SP mut before ScrnBalance - do it for him! var globalconfig array AutoLoadMutators; var globalconfig bool bReplaceHUD, bReplaceScoreBoard; var globalconfig float Post6ZedSpawnInc, Post6AmmoSpawnInc; var globalconfig float Post6ZedsPerPlayer; var globalconfig bool bAlterWaveSize; var globalconfig int MaxWaveSize; var globalconfig int MaxZombiesOnce; var globalconfig float EndGameStatBonus; var globalconfig float FirstStatBonusMult; var globalconfig bool bStatBonusUsesHL; var globalconfig int StatBonusMinHL; var globalconfig int SharpProgMinDmg; // if headshot damage dealth with Sharpshooter's weapon exceeds this, then SS gets +1 to perk progression var globalconfig bool bBroadcastPickups; // broadcast weapon pickups var globalconfig String BroadcastPickupText; // broadcast weapon pickups var protected globalconfig byte EventNum; var transient byte CurrentEventNum; var globalconfig bool bForceEvent; var globalconfig bool bAutoKickOffPerkPlayers; var localized String strAutoKickOffPerk; struct SSquadConfig { var String SquadName; var string MonsterClass; var byte NumMonsters; }; var globalconfig array VoteSquad; var globalconfig bool bResetSquadsAtStart; // calls ScrnGameRules.ResetSquads() at map start struct SSquad { var String SquadName; var array < class > Monsters; }; var array Squads; // KF.WaveMonsters value after all zeds added by SpawnSquad() are spawned // if ( SquadSpawnedMonsters > 0 && KF.WaveMonsters < SquadSpawnedMonsters ) // then those zeds are still waiting in spawn queue var int SquadSpawnedMonsters; var globalconfig bool bNoRequiredEquipment; var globalconfig bool bUseExpLevelForSpawnInventory; var globalconfig array SpawnInventory; var globalconfig int StartCashNormal, StartCashHard, StartCashSui, StartCashHoE; var globalconfig int MinRespawnCashNormal, MinRespawnCashHard, MinRespawnCashSui, MinRespawnCashHoE; var globalconfig int TraderTimeNormal, TraderTimeHard, TraderTimeSui, TraderTimeHoE; var globalconfig bool bLeaveCashOnDisconnect, bPlayerZEDTime; struct SColorTag { var string T; var byte R, G, B; }; var array ColorTags; var globalconfig string ColoredServerName; var float OriginalWaveSpawnPeriod; var globalconfig float MinZedSpawnPeriod; var globalconfig bool bSpawnRateFix; var globalconfig bool bServerInfoVeterancy; var transient array DoorKeys; var transient array DoubleDoorKeys; // keys with at least 2 doors var StaticMesh AmmoBoxMesh; var float AmmoBoxDrawScale; var vector AmmoBoxDrawScale3D; struct SSpecialPlayers { var int SteamID32; var string AvatarRef, ClanIconRef, PreNameIconRef, PostNameIconRef; var Material Avatar, ClanIcon, PreNameIcon, PostNameIcon; var Color PrefixIconColor, PostfixIconColor; var int Playoffs, TourneyWon; }; var const private array HighlyDecorated; var globalconfig string MySteamID64; enum ECustomLockType { LOCK_Level, LOCK_Ach, LOCK_AchGroup }; var name NameOfString; // used in StringToName() struct SDLCLock { var String Item; var byte Group; var ECustomLockType Type; var name ID; var byte Value; // non-config stuff var transient class PickupClass; }; var globalconfig array DLCLocks; // replicated via ScrnClientPerkRepLink var globalconfig bool bUseDLCLocks,bUseDLCLevelLocks; var protected transient int LockCount; var globalconfig bool bBuyPerkedWeaponsOnly, bPickPerkedWeaponsOnly; struct SNameValuePair { var name ID; var int Value; }; var globalconfig bool bFixMusic; var globalconfig bool bRespawnDoors; var transient bool bTeamsLocked; // Set by ScrnGameType. Used for replication purposes. var globalconfig float LockTeamMinWave, LockTeamAutoWave; var globalconfig bool bForceSteamNames; var globalconfig bool bLogObjectsAtMapStart, bLogObjectsAtMapEnd; // MutateCommands must be in UPPERCASE and sorted var const array MutateCommands; enum EMutateCommand { MUTATE_ACCURACY, MUTATE_CHECK, MUTATE_CMDLINE, MUTATE_DEBUGGAME, MUTATE_DEBUGPICKUPS, MUTATE_DEBUGSPI, MUTATE_ENEMIES, MUTATE_GIMMECOOKIES, MUTATE_HELP, MUTATE_HL, MUTATE_LEVEL, MUTATE_MAPDIFF, MUTATE_MAPZEDS, MUTATE_MUTLIST, MUTATE_PERKSTATS, MUTATE_PLAYERLIST, MUTATE_STATUS, MUTATE_VERSION, MUTATE_ZED, MUTATE_ZEDLIST }; var globalconfig bool bScrnWaves; // TSC stuff var globalconfig bool bNoTeamSkins; // SrvTourneyMode should be used for informative purposes only. // All real checks must be done server-side only to prevent cheating. var transient byte SrvTourneyMode; // END OF TSC STUFF replication { reliable if ( (bNetInitial || bNetDirty) && Role == ROLE_Authority ) SrvMinLevel, SrvMaxLevel, HardcoreLevel, bTeamsLocked; // flags to replicate config variables reliable if ( bNetInitial && Role == ROLE_Authority ) SrvFlags, SrvAchievementFlags, SrvReqBalanceMode; // non-config vars and configs vars which seem to replicate fine reliable if ( bNetInitial && Role == ROLE_Authority ) CustomWeaponLink, SrvTourneyMode, bTSCGame, Post6RequirementScaling, WeldingRequirementScaling, StalkerRequirementScaling; } // ======================================= FUNCTIONS ======================================= simulated function PostNetReceive() { super.PostNetReceive(); if ( bInitReplicationReceived && Role < ROLE_Authority ) { TimeLog("Additional Settings received from a server."); ClientInitSettings(); } } simulated function PostNetBeginPlay() { super.PostNetBeginPlay(); if ( Role < ROLE_Authority ) { TimeLog("Initial Settings received from a server."); ClientInitSettings(); bInitReplicationReceived = true; } } // client-side only simulated function ClientInitSettings() { local ScrnPlayerController LocalPlayer; // setting default settings on server screws up repliction if ( Role == ROLE_Authority ) return; Mut = self; default.Mut = self; class'ScrnBalance'.default.Mut = self; bStoryMode = KF_StoryGRI(Level.GRI) != none; LoadReplicationData(); LocalPlayer = ScrnPlayerController(Level.GetLocalPlayerController()); if ( LocalPlayer != none && LocalPlayer.Mut == none ) { LocalPlayer.Mut = self; LocalPlayer.LoadMutSettings(); } InitSettings(); } // v8: no more using default settings // use class'ScrnBalance'.default.Mut. instead of class'ScrnBalance'.default. /* simulated function ClientInitStaticSettings(class MyBalanceClass) { } */ // client & server side simulated function InitSettings() { ApplySpawnBalance(); ApplyWeaponFix(); class'ScrnVetSupportSpec'.default.progressArray1[0]=1000.0 * WeldingRequirementScaling; class'ScrnVetSupportSpec'.default.progressArray1[1]=2000.0 * WeldingRequirementScaling; class'ScrnVetSupportSpec'.default.progressArray1[2]=7000.0 * WeldingRequirementScaling; class'ScrnVetSupportSpec'.default.progressArray1[3]=33500.0 * WeldingRequirementScaling; class'ScrnVetSupportSpec'.default.progressArray1[4]=120000.0 * WeldingRequirementScaling; class'ScrnVetSupportSpec'.default.progressArray1[5]=250000.0 * WeldingRequirementScaling; class'ScrnVetSupportSpec'.default.progressArray1[6]=370000.0 * WeldingRequirementScaling; class'ScrnVetCommando'.default.progressArray0[0]=10.0 * StalkerRequirementScaling; class'ScrnVetCommando'.default.progressArray0[1]=30.0 * StalkerRequirementScaling; class'ScrnVetCommando'.default.progressArray0[2]=100.0 * StalkerRequirementScaling; class'ScrnVetCommando'.default.progressArray0[3]=325.0 * StalkerRequirementScaling; class'ScrnVetCommando'.default.progressArray0[4]=1200.0 * StalkerRequirementScaling; class'ScrnVetCommando'.default.progressArray0[5]=2400.0 * StalkerRequirementScaling; class'ScrnVetCommando'.default.progressArray0[6]=3600.0 * StalkerRequirementScaling; if (bShieldWeight) { bReplaceNades = true; default.bReplaceNades = true; class'ScrnBalance'.default.bReplaceNades = true; class'ScrnFrag'.default.Weight = 0; class'ScrnBalanceSrv.ScrnHumanPawn'.default.StandardVestClass.default.Weight = 1; } else { class'ScrnFrag'.default.Weight = 1; class'ScrnBalanceSrv.ScrnHumanPawn'.default.StandardVestClass.default.Weight = 0; } class'ScrnFragPickup'.default.Weight = class'ScrnFrag'.default.Weight; RecalcAllPawnWeight(); class'KFMod.CrossbowArrow'.default.DamageRadius = 0; // isn't used anywhere. Set to 0 to fix description // Achievements bUseAchievements = bool(AchievementFlags & ACH_ENABLE); default.bUseAchievements = bUseAchievements; default.bStoryMode = bStoryMode; default.bTSCGame = bTSCGame; // fixes critical bug: // Assertion failed: inst->KPhysRootIndex != INDEX_NONE && inst->KPhysLastIndex != INDEX_NONE [File:.\KSkeletal.cpp] [Line: 595] class'FellLava'.default.bSkeletize = false; // Fix missing textures class'Welder'.default.TraderInfoTexture = texture(class'Welder'.default.SelectedHudImage); class'Syringe'.default.TraderInfoTexture = texture(class'Syringe'.default.SelectedHudImage); EventZedNames(); bInitialized = true; } simulated function EventZedNames() { class'KFChar.ZombieClot_CIRCUS'.default.MenuName = "Strange Little Clot"; class'KFChar.ZombieBloat_CIRCUS'.default.MenuName = "Pukey the Clown"; class'KFChar.ZombieStalker_CIRCUS'.default.MenuName = "Assistant"; class'KFChar.ZombieCrawler_CIRCUS'.default.MenuName = "Two-Head Girl"; class'KFChar.ZombieGorefast_CIRCUS'.default.MenuName = "Sword Polisher"; class'KFChar.ZombieHusk_CIRCUS'.default.MenuName = "Mecha-Man"; class'KFChar.ZombieSiren_CIRCUS'.default.MenuName = "Bearded Beauty"; class'KFChar.ZombieScrake_CIRCUS'.default.MenuName = "Man Monkey"; class'KFChar.ZombieFleshpound_CIRCUS'.default.MenuName = "Flesh Clown"; class'KFChar.ZombieBoss_CIRCUS'.default.MenuName = "Ring Leader"; class'KFChar.ZombieClot_HALLOWEEN'.default.MenuName = "Honey Biscuit"; class'KFChar.ZombieBloat_HALLOWEEN'.default.MenuName = "Mama Bessie"; class'KFChar.ZombieStalker_HALLOWEEN'.default.MenuName = "Maggie May"; class'KFChar.ZombieCrawler_HALLOWEEN'.default.MenuName = "Half of Uncle Pervis"; class'KFChar.ZombieGorefast_HALLOWEEN'.default.MenuName = "Banjo Chewey"; class'KFChar.ZombieHusk_HALLOWEEN'.default.MenuName = "Brother Sparky"; class'KFChar.ZombieSiren_HALLOWEEN'.default.MenuName = "Granny Crystal May"; class'KFChar.ZombieScrake_HALLOWEEN'.default.MenuName = "Cousin Otis"; class'KFChar.ZombieFleshpound_HALLOWEEN'.default.MenuName = "Bubba"; class'KFChar.ZombieBoss_HALLOWEEN'.default.MenuName = "Sheriff Wade"; class'KFChar.ZombieClot_XMAS'.default.MenuName = "Elf"; class'KFChar.ZombieBloat_XMAS'.default.MenuName = "Fake Santa"; class'KFChar.ZombieStalker_XMAS'.default.MenuName = "Mrs. Claws"; class'KFChar.ZombieCrawler_XMAS'.default.MenuName = "Reindeer"; class'KFChar.ZombieGorefast_XMAS'.default.MenuName = "Gingerfast"; class'KFChar.ZombieHusk_XMAS'.default.MenuName = "Snow Husk"; class'KFChar.ZombieSiren_XMAS'.default.MenuName = "Screaming Tree"; class'KFChar.ZombieScrake_XMAS'.default.MenuName = "Jack Frost"; class'KFChar.ZombieFleshpound_XMAS'.default.MenuName = "Nutcracker"; class'KFChar.ZombieBoss_XMAS'.default.MenuName = "Santriarch"; } simulated function TimeLog(coerce string s) { log("["$Level.TimeSeconds$"s]" @ s, 'ScrnBalance'); } static function MessageBonusLevel(PlayerController KPC) { local String msg; if ( KPC == none ) return; msg = default.strBonusLevel; ReplaceText(msg, "%s", String(class'ScrnBalanceSrv.ScrnVeterancyTypes'.static.GetClientVeteranSkillLevel(KFPlayerReplicationInfo(KPC.PlayerReplicationInfo)))); KPC.ClientMessage(msg); } static final function string GetVersionStr() { local String msg; local int v; local byte major, minor, patch; msg = default.strVersion; v = VERSION; // for some reason, UnrealScript has operator % declared only for float not for int. // So we can't use % here do to precision major = v / 10000; v -= major * 10000; minor = v / 100; v -= minor * 100; patch = v; ReplaceText(msg, "%m", string(major)); ReplaceText(msg, "%n", class'ScrnFunctions'.static.LPad(minor, 2, "0")); ReplaceText(msg, "%p", string(patch)); return msg; } static function MessageVersion(PlayerController PC) { if ( PC != none ) PC.ClientMessage(default.FriendlyName @ GetVersionStr()); } function MessageStatus(PlayerController PC) { local String msg; local KFPlayerReplicationInfo KFPRI; local ClientPerkRepLink R; local int i, j; local array WeaponPackages; local name pkg; if ( PC == none ) return; KFPRI = KFPlayerReplicationInfo(PC.PlayerReplicationInfo); if ( ScrnGT != none && ScrnGT.IsTourney() ) PC.ClientMessage("*** TOURNEY MODE ***", 'Log'); msg = strStatus; ReplaceText(msg, "%v", String(KFPRI.ClientVeteranSkillLevel)); ReplaceText(msg, "%b", String(class'ScrnBalanceSrv.ScrnVeterancyTypes'.static.GetClientVeteranSkillLevel(KFPRI))); ReplaceText(msg, "%n", String(MinLevel)); ReplaceText(msg, "%x", String(MaxLevel)); PC.ClientMessage(msg, 'Log'); msg = strStatus2; ReplaceText(msg, "%a", String(bAltBurnMech)); ReplaceText(msg, "%m", String(KF.MaxZombiesOnce)); PC.ClientMessage(msg, 'Log'); R = SRStatsBase(PC.SteamStatsAndAchievements).Rep; if ( R != none ) { msg = "Weapon Packages:"; for ( i=0; i=0 ) { s = left(s,p)$mid(S,p+4); p = InStr(s,Chr(27)); } return s; } // returns first i amount of characters excluding escape color codes static final function string LeftCol(string ColoredString, int i) { local string s; local int p, c; if ( Len(ColoredString) <= i ) return ColoredString; c = i; s = ColoredString; p = InStr(s,chr(27)); while ( p >=0 && p < i ) { c+=4; // add 4 more characters due to color code s = left(s, p) $ mid(s, p+4); p = InStr(s,Chr(27)); } return Left(ColoredString, c); } simulated function string ParseColorTags(string ColoredText, optional PlayerReplicationInfo PRI) { local int i; local string s; s = ColoredText; if ( PRI != none && PRI.Team != none ) ReplaceText(s, "^t", ColorStringC("", class'ScrnHUD'.default.TextColors[PRI.Team.TeamIndex])); else ReplaceText(s, "^t", ""); if ( KFPlayerReplicationInfo(PRI) != none ) ReplaceText(s, "^p", ColorStringC("", class'ScrnHUD'.static.PerkColor(KFPlayerReplicationInfo(PRI).ClientVeteranSkillLevel))); else ReplaceText(s, "^p", ""); for ( i=0; i= 5.0 ) { // Suicidal and Hell on Earth W = 0.15; A = 0.35; } else if ( KF.GameDifficulty >= 4.0 ) { // Hard W = 0.25; A = 0.50; } else { // Normal W = 0.35; A = 0.50; } if ( KF.NumPlayers > 6 ) { A *= 1.0 + float(KF.NumPlayers - 6)*Post6AmmoSpawnInc; } if ( KF.WeaponPickups.Length > 0 ) { for ( i = 0; i < KF.WeaponPickups.Length ; i++ ) { if ( frand() < W ) { if ( !KF.WeaponPickups[i].bIsEnabledNow ) KF.WeaponPickups[i].EnableMe(); bSpawned = true; } else if ( KF.WeaponPickups[i].bIsEnabledNow ) KF.WeaponPickups[i].DisableMe(); } if ( !bSpawned ) KF.WeaponPickups[rand(KF.WeaponPickups.Length)].EnableMe(); } AdjustAmmoBoxCount(ceil(A * KF.AmmoPickups.Length)); } function AdjustAmmoBoxCount(int DesiredAmmoBoxCount) { local int i; local array AvailableAmmoBoxes; local int CurrentAmmoBoxCount; for ( i = 0; i < KF.AmmoPickups.Length ; i++ ) { if ( !KF.AmmoPickups[i].bSleeping ) ++CurrentAmmoBoxCount; } if ( CurrentAmmoBoxCount < DesiredAmmoBoxCount ) { // not enough ammo on the map - spawn more for ( i = 0; i < KF.AmmoPickups.Length ; i++ ) { if ( KF.AmmoPickups[i].bSleeping ) AvailableAmmoBoxes[AvailableAmmoBoxes.Length] = KF.AmmoPickups[i]; } while ( CurrentAmmoBoxCount < DesiredAmmoBoxCount && AvailableAmmoBoxes.Length > 0 ) { i = rand(AvailableAmmoBoxes.Length); AvailableAmmoBoxes[i].GotoState('Pickup'); AvailableAmmoBoxes.remove(i, 1); ++CurrentAmmoBoxCount; } } else if ( CurrentAmmoBoxCount > DesiredAmmoBoxCount ) { // too many ammo boxes - remove those which are not seen by players for ( i = 0; i < KF.AmmoPickups.Length ; i++ ) { if ( !KF.AmmoPickups[i].bSleeping && !KF.AmmoPickups[i].PlayerCanSeeMe() ) AvailableAmmoBoxes[AvailableAmmoBoxes.Length] = KF.AmmoPickups[i]; } while ( CurrentAmmoBoxCount > DesiredAmmoBoxCount && AvailableAmmoBoxes.Length > 0 ) { i = rand(AvailableAmmoBoxes.Length); AvailableAmmoBoxes[i].GotoState('Sleeping', 'Begin'); AvailableAmmoBoxes.remove(i, 1); --CurrentAmmoBoxCount; } } if ( ScrnGT != none ) { ScrnGT.DesiredAmmoBoxCount = DesiredAmmoBoxCount; } } function MessagePickups(PlayerController Sender) { local int i, a, w; local String msg; a = KF.AmmoPickups.length; for ( i = 0; i < KF.AmmoPickups.length; ++i ) { if ( KF.AmmoPickups[i].bSleeping ) --a; } w = KF.WeaponPickups.length; for ( i = 0; i < KF.WeaponPickups.length; ++i ) { if ( !KF.WeaponPickups[i].bIsEnabledNow ) --w; } msg = "Ammo boxes Spawned/Total: " $ a $ "/" $ KF.AmmoPickups.length; if ( ScrnGT != none ) { msg $= "; Current/Desired: " $ ScrnGT.CurrentAmmoBoxCount $ "/" $ ScrnGT.DesiredAmmoBoxCount; msg $= "; In queue: " $ ScrnGT.SleepingAmmo.length; } msg $= ". Weapons Spawned/Total: " $ w $ "/" $ KF.WeaponPickups.length; Sender.ClientMessage(msg); } function ForceMaxPlayers() { if ( ForcedMaxPlayers > 0 && ForcedMaxPlayers != Level.Game.MaxPlayers ) { Log("Forcing server max players from " $ Level.Game.MaxPlayers $ " to " $ ForcedMaxPlayers,'ScrnBalance'); Level.Game.MaxPlayers = ForcedMaxPlayers; Level.Game.Default.MaxPlayers = ForcedMaxPlayers; } } function AchievementEarned(ScrnAchievements AchHandler, int AchIndex) { if ( bSaveStatsOnAchievementEarned && AchHandler.AchDefs[AchIndex].bUnlockedJustNow ) bNeedToSaveStats = true; NextStatSaveTime = Level.TimeSeconds + 5; // wait a bit - maybe other achievements will be earned soon if ( bBroadcastAchievementEarn ) BroadcastAchEarn(AchHandler, AchIndex); } function BroadcastAchEarn(ScrnAchievements AchHandler, int AchIndex) { local Controller C; local ScrnPlayerController ScrnPlayer; local string s; if ( PlayerController(AchHandler.Owner) == none || PlayerController(AchHandler.Owner).PlayerReplicationInfo == none ) return; s = strAchEarn; ReplaceText(s, "%p", PlayerController(AchHandler.Owner).PlayerReplicationInfo.PlayerName); ReplaceText(s, "%a", AchHandler.AchDefs[AchIndex].DisplayName); for (C = Level.ControllerList; C != None; C = C.NextController) { if ( !C.bIsPlayer ) continue; ScrnPlayer = ScrnPlayerController(C); if ( ScrnPlayer != None && ScrnPlayer != AchHandler.Owner ) { ScrnPlayer.ClientMessage(ColorString(s, 1, 150, 255)); } } } function BroadcastFakedAchievement(int AchIndex) { local Controller C; for (C = Level.ControllerList; C != None; C = C.NextController) { if ( !C.bIsPlayer ) continue; if ( PlayerController(C) != none) PlayerController(C).ReceiveLocalizedMessage(class'ScrnBalanceSrv.ScrnFakedAchMsg', AchIndex); } } function Mutator FindServerPerksMut() { local Mutator M; if ( ServerPerksMut != none ) return ServerPerksMut; for ( M = KF.BaseMutator; M != None; M = M.NextMutator ) { if ( M.IsA('ServerPerksMut') ) { ServerPerksMut = M; break; } } if ( ServerPerksMut == none ) { log("ServerPerksMut not found!", 'ScrnBalance'); } return ServerPerksMut; } // do everything possible to find ScrnBalance mutator static final function ScrnBalance Myself(LevelInfo Level) { local Mutator M; local ScrnBalance SBM; if ( default.Mut != none ) return default.Mut; // shouldn't reach here // server-side if ( Level.Game != none ) { for ( M = Level.Game.BaseMutator; M != None; M = M.NextMutator ) { SBM = ScrnBalance(M); if ( SBM != none ) { default.Mut = SBM; return SBM; } } } // clien-side foreach Level.DynamicActors(class'ScrnBalance', SBM) { default.Mut = SBM; return SBM; } log("Unable to find myself :(", 'ScrnBalance'); return none; } final function GetRidOfMut(name MutatorName) { local Mutator M; for ( M = KF.BaseMutator; M != None; M = M.NextMutator ) { if ( M.IsA(MutatorName) ) { M.Destroy(); return; } } } //can't statically link to ServerPerksMut, cuz it is server-side only function SaveStats() { bNeedToSaveStats = false; if ( ServerPerksMut == none ) FindServerPerksMut(); if ( ServerPerksMut == none ) return; if ( Level.Game.bGameEnded ) { // v8.18 - do nothing, Serverperks will save game itself // GotoState('StatsSaving'); // goto EndGameTracker state again to force save perks // doing so will increment win/loose counter extra time - need to contact Marco about this } else { // adjust variables of ServerPerksMut to force saving ServerPerksMut.SetPropertyText("WaveCounter", "100"); ServerPerksMut.SetPropertyText("LastSavedWave", "-1"); } } /* state StatsSaving { Begin: log("Saving stats...", 'ScrnBalance'); ServerPerksMut.GotoState(''); sleep(1.0); if ( ServerPerksMut.IsInState('EndGameTracker') ) { log("Can't save stats!", 'ScrnBalance'); } else { ServerPerksMut.GotoState('EndGameTracker'); } GotoState(''); } */ function DynamicLevelCap() { local int num, m; if ( !bDynamicLevelCap ) return; m = OriginalMaxLevel; if ( bTSCGame ) num = max(KF.Teams[0].Size, KF.Teams[1].Size); else num = KF.NumPlayers; if (num > 6) m += num-6; //extra level per player if ( MaxLevel != m) { MaxLevel = m; default.MaxLevel = m; SrvMaxLevel = m; //send value to clients } } // kick players, who have no perk function KickOffPerkPlayers() { local Controller C; local KFPlayerController KFPC; local KFPlayerReplicationInfo KFPRI; for ( C = Level.ControllerList; C != none; C = C.nextController ) { if ( !C.bIsPlayer ) continue; KFPC = KFPlayerController(C); KFPRI = KFPlayerReplicationInfo(C.PlayerReplicationInfo); if ( KFPC != none && KFPC.Pawn != none && NetConnection(KFPC.Player)!=None && KFPRI != none && KFPRI.ClientVeteranSkill == none && !KFPRI.bOnlySpectator && !KFPRI.bIsSpectator ) { KFPC.ClientNetworkMessage("AC_Kicked", strAutoKickOffPerk); if ( KFPC.Pawn != none && Vehicle(KFPC.Pawn) == none ) KFPC.Pawn.Destroy(); KFPC.Destroy(); } } } // executes each second while match is in progress function GameTimer() { if ( bStoryMode ) { KF.bWaveInProgress = !KFStoryGameInfo(KF).IsTraderTime(); KFGameReplicationInfo(Level.GRI).bWaveInProgress = KF.bWaveInProgress; } // check for wave start/end if ( bTradingDoorsOpen != KF.bTradingDoorsOpen ) { bTradingDoorsOpen = KF.bTradingDoorsOpen; if ( bTradingDoorsOpen ) { // Trader Time if ( bStoryMode && KF.WaveNum == CurWave ) { // seems like story game doesn't increment wave counter KF.WaveNum++; } GameRules.WaveEnded(); KF.WaveCountDown += TradeTimeAddSeconds; TradeTimeAddSeconds = 0; } else { // Wave in Progress CurWave = KF.WaveNum; if ( bAutoKickOffPerkPlayers ) KickOffPerkPlayers(); SquadSpawnedMonsters = 0; GameRules.WaveStarted(); if ( MyVotingOptions != none && MyVotingOptions.VotingHandler.IsMyVotingRunning(MyVotingOptions, MyVotingOptions.VOTE_ENDTRADE) ) MyVotingOptions.VotingHandler.VoteFailed(); DestroyExtraPipebombs(); // call SetupPickups only when playing non-ScrnGameType mode. // ScrnGameType automatically calls SetupPickups() during wave begin. if ( ScrnGT == none && !bStoryMode ) SetupPickups(false); } if ( bDynamicLevelCap ) DynamicLevelCap(); } if ( !bStoryMode ) { CheckDoors(); if ( !bPickupSetupReduced && KF.TotalMaxMonsters <= 0 && KF.NumMonsters < PickupSetupMonsters ) SetupPickups(true); } } function Timer() { // todo - talk to Marco about forcing game saving if ( bNeedToSaveStats && Level.TimeSeconds > NextStatSaveTime ) { SaveStats(); } if ( KF.IsInState('MatchInProgress') ) { if ( GameStartCountDown > 0) GameStartCountDown--; // wait for 10 seconds for game to be started and set up first wave else GameTimer(); } } function FixMusic() { if ( KF.MapSongHandler == none ) KF.MapSongHandler = spawn(class'ScrnMusicTrigger'); // Allow L.D. to set boss battle song. // Don't use Dirge music as boss battle, because default KF_Abandon better. if ( left(KF.MonsterCollection.default.EndGameBossClass, InStr(KF.MonsterCollection.default.EndGameBossClass,".")) ~= "ScrnDoom3KF" ) KF.BossBattleSong = "EGT-SignOfEvil"; // try this. If client doesn't have that song, then KF_Abandon will be played else if ( KF.MapSongHandler.WaveBasedSongs.Length > 10 && KF.MapSongHandler.WaveBasedSongs[10].CombatSong != "" && !(left(KF.MapSongHandler.WaveBasedSongs[10].CombatSong, 5) ~= "Dirge") ) KF.BossBattleSong = KF.MapSongHandler.WaveBasedSongs[10].CombatSong; } simulated function Tick( float DeltaTime ) { if ( !bTickExecuted ) { bTickExecuted = true; FirstTickTime = Level.TimeSeconds; } if ( Role == ROLE_Authority ) { OriginalWaveSpawnPeriod = KF.KFLRules.WaveSpawnPeriod; if ( OriginalWaveSpawnPeriod < MinZedSpawnPeriod ) { OriginalWaveSpawnPeriod = MinZedSpawnPeriod; KF.KFLRules.WaveSpawnPeriod = MinZedSpawnPeriod; } ForceMaxPlayers(); if ( !bStoryMode ) { if ( ScrnGT != none ) { ScrnGT.CheckZedSpawnList(); } InitDoors(); SetStartCash(); if ( bFixMusic ) FixMusic(); } if ( bTSCGame ) { Level.GRI.bNoTeamSkins = bNoTeamSkins && !ScrnGT.IsTourney(); } if ( ColoredServerName != "" ) { Level.GRI.ServerName = ParseColorTags(ColoredServerName); } SetTimer(1, true); Disable('Tick'); } else if ( bInitialized ) { Disable('Tick'); } else if ( Level.TimeSeconds - FirstTickTime > 5 ) { // this shouldn't happen Timelog("Settings receiving timeout failed - initializing with default settings"); InitSettings(); Disable('Tick'); } } function SetStartCash() { local Controller C; if ( KF.GameDifficulty >= 7 ) // HoE { KF.TimeBetweenWaves = TraderTimeHoE; KF.StartingCash = StartCashHoE; KF.MinRespawnCash = MinRespawnCashHoE; } else if (KF.GameDifficulty >= 5 ) // Suicidal { KF.TimeBetweenWaves = TraderTimeSui; KF.StartingCash = StartCashSui; KF.MinRespawnCash = MinRespawnCashSui; } else if ( KF.GameDifficulty >= 4 ) // Hard { KF.TimeBetweenWaves = TraderTimeHard; KF.StartingCash = StartCashHard; KF.MinRespawnCash = MinRespawnCashHard; } else { KF.TimeBetweenWaves = TraderTimeNormal; KF.StartingCash = StartCashNormal; KF.MinRespawnCash = MinRespawnCashNormal; } for ( C = Level.ControllerList; C != none; C = C.nextController ) { if ( C.PlayerReplicationInfo != none ) { if ( ScrnGT != none && PlayerController(C) != none ) ScrnGT.GiveStartingCash(PlayerController(C)); else C.PlayerReplicationInfo.Score = KF.StartingCash; } } } function DebugArmor(PlayerController Sender) { local Controller P; local ScrnHumanPawn ScrnPawn; for ( P = Level.ControllerList; P != none; P = P.nextController ) { ScrnPawn = ScrnHumanPawn(P.Pawn); if ( ScrnPawn != none ) { Sender.ClientMessage(ScrnPawn.PlayerReplicationInfo.PlayerName @ GetItemName(String(ScrnPawn.GetCurrentVestClass())) @ int(ScrnPawn.ShieldStrength)$"/"$int(ScrnPawn.ShieldStrengthMax)); } } } function MessagePerkStats(PlayerController Sender) { local ScrnPlayerInfo SPI; SPI = GameRules.GetPlayerInfo(Sender); if ( SPI == none ) Sender.ClientMessage("No player info record found"); else { Sender.ClientMessage(ColorString("Initial Perk Stats: " $ SPI.PerkStatStr(SPI.GameStartStats), 255, 1, 200)); Sender.ClientMessage(ColorString("Perk Progression: " $ SPI.PerkProgressStr(SPI.GameStartStats), 255, 1, 200)); } } // returns number of zeds, which have Other as enemy function MsgEnemies(PlayerController Sender) { local Controller C; local PlayerController PC; local array Players; local array Enemies; local int i; for ( C = Level.ControllerList; C != none; C = C.nextController ) { if ( !C.bIsPlayer && C.Enemy != none ) { PC = PlayerController(C.Enemy.Controller); if ( PC != none ) { for ( i=0; i MaxLen ) { pos = InStr(S, Divider); if ( pos == -1 ) break; // no more dividers if ( part != "" && len(part) + pos + 1 > MaxLen) { Sender.ClientMessage(part); part = ""; } part $= Left(S, pos + 1); S = Mid(S, pos+1); } part $= S; if ( part != "" ) Sender.ClientMessage(part); } function bool CheckAdmin(PlayerController Sender) { if ( (Sender.PlayerReplicationInfo != none && Sender.PlayerReplicationInfo.bAdmin) || Level.NetMode == NM_Standalone || Level.NetMode == NM_ListenServer ) return true; Sender.ClientMessage("Requires ADMIN priviledges"); return false; } function bool CheckScrnGT(PlayerController Sender) { if ( ScrnGT != none ) return true; Sender.ClientMessage("Avaliable in ScrnGameType only!"); return false; } function bool CheckNotTourney(PlayerController Sender) { if ( ScrnGT == none || !ScrnGT.IsTourney() ) return true; Sender.ClientMessage("Not Available in TOURNEY mode"); return false; } function Mutate(string MutateString, PlayerController Sender) { local string Value; local int cmd; if ( MutateString == "" ) return; super.Mutate(MutateString, Sender); Divide(MutateString, " ", MutateString, Value); MutateString = caps(MutateString); cmd = BinarySearchStr(MutateCommands, MutateString); if ( cmd == -1 ) return; //unknown command switch ( EMutateCommand(cmd) ) { case MUTATE_ACCURACY: SendAccuracy(Sender); break; case MUTATE_CHECK: Sender.ClientMessage(FriendlyName); break; case MUTATE_CMDLINE: if ( CheckAdmin(Sender) && CheckScrnGT(Sender) ) LongMessage(Sender, ScrnGT.GetCmdLine(), 80, "?"); break; case MUTATE_DEBUGGAME: if ( CheckAdmin(Sender) ) Sender.ClientMessage("Game=" $ KF.class.name @ "EventNum=" $ CurrentEventNum @ "MonsterCollection=" $ KF.MonsterCollection @ "Boss=" $ KF.MonsterCollection.default.EndGameBossClass); break; case MUTATE_DEBUGPICKUPS: MessagePickups(Sender); break; case MUTATE_DEBUGSPI: GameRules.DebugSPI(Sender); break; case MUTATE_ENEMIES: if ( CheckAdmin(Sender) ) MsgEnemies(Sender); break; case MUTATE_GIMMECOOKIES: XPBoost(Sender, 'TSCT', 6); break; case MUTATE_HELP: MessageMutateCommands(Sender); break; case MUTATE_HL: Sender.ClientMessage("Hardcore Level = " $ GameRules.HardcoreLevel); break; case MUTATE_LEVEL: MessageBonusLevel(Sender); break; case MUTATE_MAPDIFF: if ( CheckAdmin(Sender) ) MapInfo.SetMapDifficulty(Value, Sender); break; case MUTATE_MAPZEDS: if ( CheckAdmin(Sender) && CheckNotTourney(Sender) ) { if ( MapInfo.SetMapZeds(int(Value), Sender) ) { SetMaxZombiesOnce(); BroadcastMessage("Max zeds at once set to " $ KF.MaxZombiesOnce); } } break; case MUTATE_MUTLIST: Sender.ClientMessage(MutatorList()); break; case MUTATE_PERKSTATS: MessagePerkStats(Sender); break; case MUTATE_PLAYERLIST: SendPlayerList(Sender); break; case MUTATE_STATUS: MessageStatus(Sender); break; case MUTATE_VERSION: MessageVersion(Sender); break; case MUTATE_ZED: if ( ScrnGT == none || ScrnGT.ScrnGameLength == none ) Sender.ClientMessage("Avaliable only in ScrnGameType + bScrnWaves"); else if ( CheckAdmin(Sender) ) { ScrnGT.ScrnGameLength.ZedCmd(Sender, Value); } break; case MUTATE_ZEDLIST: if ( ScrnGT == none || ScrnGT.ScrnGameLength == none ) SendZedList(Sender); else ScrnGT.ScrnGameLength.ZedCmd(Sender, "LIST"); break; } } // for debug purposes only /* private final function DebugDoors(PlayerController Sender) { local KFDoorMover door; local Inventory I; local int c; foreach DynamicActors(class'KFDoorMover', door) door.RespawnDoor(); if ( Sender.Pawn != none ) { for ( I = Sender.Pawn.Inventory; I != none; I = I.Inventory ) { if ( Single(I) != none ) { KFFire(Single(I).GetFireMode(0)).DamageType = class'DamTypeFrag'; KFFire(Single(I).GetFireMode(0)).DamageMax = 1000; return; } if ( ++c > 1000 ) return; //circular link prevention } } } */ function MessageMutateCommands(PlayerController Sender) { local int i; Sender.ClientMessage("ScrN Mutate Commands"); Sender.ClientMessage("===================="); for ( i = 0; i < MutateCommands.length; ++i ) { Sender.ClientMessage(MutateCommands[i]); } } function XPBoost(PlayerController Sender, name Achievement, byte Level) { local ScrnCustomPRI ScrnPRI; local SRStatsBase SteamStats; local ScrnPlayerInfo SPI; local SRCustomProgress S; local int v; ScrnPRI = class'ScrnCustomPRI'.static.FindMe(Sender.PlayerReplicationInfo); if ( ScrnPRI == none || !ScrnPRI.IsTourneyMember() ) return; SteamStats = SRStatsBase(Sender.SteamStatsAndAchievements); SPI = GameRules.GetPlayerInfo(Sender); if ( SPI == none || SteamStats == none ) { Sender.ClientMessage("Player achievements are not loaded yet. Try again later."); return; } // ProgressAchievement() returns true if progress has been made, i.e. // achievement wasn't achieved before if ( Achievement == '' || SPI.ProgressAchievement(Achievement, 1) ) { SteamStats.AddDamageHealed(class'ScrnVetFieldMedic'.default.progressArray0[Level]); SteamStats.AddShotgunDamage(class'ScrnVetSupportSpec'.default.progressArray0[Level]); SteamStats.AddWeldingPoints(class'ScrnVetSupportSpec'.default.progressArray1[Level]); v = class'ScrnVetSharpshooter'.default.progressArray0[Level]; while ( v-- > 0 ) SteamStats.AddHeadshotKill(false); v = class'ScrnVetCommando'.default.progressArray0[Level]; while ( v-- > 0 ) SteamStats.AddStalkerKill(); SteamStats.AddBullpupDamage(class'ScrnVetCommando'.default.progressArray1[Level]); SteamStats.AddMeleeDamage(class'ScrnVetBerserker'.default.progressArray0[Level]); SteamStats.AddFlameThrowerDamage(class'ScrnVetFirebug'.default.progressArray0[Level]); SteamStats.AddExplosivesDamage(class'ScrnVetDemolitions'.default.progressArray0[Level]); for ( S = SteamStats.Rep.CustomLink; S!=none; S=S.NextLink ) { if ( ScrnPistolKillProgress(S) != none ) S.IncrementProgress(class'ScrnVetGunslinger'.default.progressArray0[Level]); else if ( ScrnPistolDamageProgress(S) != none ) S.IncrementProgress(class'ScrnVetGunslinger'.default.progressArray1[Level]); } SaveStats(); // for ServerPerks to write stats // ensure that xp boost won't be multiplied by end-game bonus SPI.GameStartStats.bSet = false; SPI.BackupStats(SPI.GameStartStats); } } function string MutatorList() { local Mutator M; local string result; result = string(KF.BaseMutator.class); for ( M = KF.BaseMutator.NextMutator; M != None; M = M.NextMutator ) { result $= ","$string(M.class); } return result; } function SendZedList(PlayerController Sender) { local int i, j, k, NumZeds; local string str, ZedClass; Sender.ClientMessage("Collection: " $ KF.MonsterCollection); Sender.ClientMessage("Boss: " $ KF.MonsterCollection.default.EndGameBossClass); for ( k=0; k< KF.MonsterCollection.default.MonsterClasses.Length; ++k ) { Sender.ClientMessage( ColorString(KF.MonsterCollection.default.MonsterClasses[k].MID, 1, 100, 200) $ ColorString(": "$KF.MonsterCollection.default.MonsterClasses[k].MClassName, 200, 200, 200)); } Sender.ClientMessage("SpecialSquads:"); for ( i=0; i< KF.MonsterCollection.default.SpecialSquads.Length; ++i ) { if ( KF.MonsterCollection.default.SpecialSquads[i].ZedClass.Length > 0 ) { str = ""; for( j=0; j AllPRI; local PlayerController PC; local int i; Level.Game.GameReplicationInfo.GetPRIArray(AllPRI); for (i = 0; i= 0.90 ) return ColorString(s,1,100,200); // light blue else if ( Pct >= 0.75 ) return ColorString(s,1,200,1); // green else if ( Pct >= 0.50 ) return ColorString(s,200,200,1); // yellow return ColorString(s,200,1,1); // red } function SendAccuracy(PlayerController Sender) { local ScrnPlayerInfo SPI; local string msg; for ( SPI=GameRules.PlayerInfo; SPI!=none; SPI=SPI.NextPlayerInfo ) { if ( SPI.PlayerOwner == none || SPI.PlayerOwner.PlayerReplicationInfo == none || SPI.HeadshotsPerGame == 0 ) continue; msg = ColoredPlayerName(SPI.PlayerOwner.PlayerReplicationInfo) $ ": " @ "Wave: "$GetColoredPercent(SPI.GetAccuracyWave(), false) @ ColorString("("$SPI.HeadshotsPerWave,1,220,1)$ColorString("/"$SPI.BodyShotsPerWave,200,200,200)$")" @ " Game: "$GetColoredPercent(SPI.GetAccuracyGame(), false) @ ColorString("("$SPI.HeadshotsPerGame,1,220,1)$ColorString("/"$SPI.BodyshotsPerGame,200,200,200)$")"; if ( ScrnPlayerController(SPI.PlayerOwner) != none && ScrnPlayerController(SPI.PlayerOwner).ab_warning > 0 ) msg @= ColorString("AB="$ScrnPlayerController(SPI.PlayerOwner).ab_warning$"%", 255, 200, 1); Sender.ClientMessage(msg); } } static final function String FormatTime( int Seconds ) { local int Minutes, Hours; local String Time; if( Seconds > 3600 ) { Hours = Seconds / 3600; Seconds -= Hours * 3600; Time = Hours$":"; } Minutes = Seconds / 60; Seconds -= Minutes * 60; if( Minutes >= 10 || Hours == 0 ) Time = Time $ Minutes $ ":"; else Time = Time $ "0" $ Minutes $ ":"; if( Seconds >= 10 ) Time = Time $ Seconds; else Time = Time $ "0" $ Seconds; return Time; } static function FillPlayInfo(PlayInfo PlayInfo) { Super.FillPlayInfo(PlayInfo); PlayInfo.AddSetting(default.BonusCapGroup,"BonusLevelNormalMax","2.Normal Max Bonus Level ",1,0, "Text", "4;0:70",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"BonusLevelHardMin","4.Hard Min Bonus Level",1,0, "Text", "4;0:70",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"BonusLevelHardMax","4.Hard Max Bonus Level",1,0, "Text", "4;0:70",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"BonusLevelSuiMin","5.Suicidal Min Bonus Level",1,0, "Text", "4;0:70",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"BonusLevelSuiMax","5.Suicidal Max Bonus Level",1,0, "Text", "4;0:70",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"BonusLevelHoeMin","7.HoE Min Bonus Level",1,0, "Text", "4;0:70",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"BonusLevelHoeMax","7.HoE Max Bonus Level",1,0, "Text", "4;0:70",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"Post6RequirementScaling","Level 7+ Scaling",1,0, "Text", "6;0.01:4.00",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"MaxZombiesOnce","Max Specimens At Once",1,0, "Text", "4;8:254",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"bSpawn0","Zero Cost of Initial Inventory",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bHardcore","Hardcore Mode",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bReplacePickups","Replace Pickups",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bReplacePickupsStory","Replace Pickups (Story)",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bReplaceNades","Replace Grenades",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bShieldWeight","Armor Has Weight",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bAltBurnMech","Alternate Burning Mechanism",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bShowDamages","Show Damages",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bReplaceHUD","Replace HUD",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bNoPerkChanges","No Perk Changes",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"EventNum","Event", 0, 1, "Select", "0;Autodetect;255;Normal;1;Summer;2;Halloween;3;Xmas;254;Random",,,True); PlayInfo.AddSetting(default.BonusCapGroup,"bForceEvent","Force Event",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bUseDLCLocks","Trader Requirements",1,0, "Check"); PlayInfo.AddSetting(default.BonusCapGroup,"bUseDLCLevelLocks","Perk Level Requirements",1,0, "Check"); //PlayInfo.AddSetting(default.BonusCapGroup,"PerkedWeapons","Custom Perked Weapons",1,1,"Text","42",,,True); //PlayInfo.AddSetting(default.BonusCapGroup,"CustomPerks","Custom Perks",1,1,"Text","42",,,True); } static function string GetDescriptionText(string PropName) { switch (PropName) { case "BonusLevelNormalMax": return "Maximum perk level, which bonuses can be applied on difficulty. Perk levels above this won't have any extra bonuses."; case "BonusLevelHardMin": return "Minimum perk level, which bonuses can be applied on Hard difficulty. Perk levels below will be granted with minimal bonus anyway."; case "BonusLevelHardMax": return "Maximum perk level, which bonuses can be applied on Hard difficulty. Perk levels above this won't have any extra bonuses."; case "BonusLevelSuiMin": return "Minimum perk level, which bonuses can be applied on Suicidal difficulty. Perk levels below will be granted with minimal bonus anyway."; case "BonusLevelSuiMax": return "Maximum perk level, which bonuses can be applied on Suicidal difficulty. Perk levels above this won't have any extra bonuses."; case "BonusLevelHoeMin": return "Minimum perk level, which bonuses can be applied on HoE difficulty. Perk levels below will be granted with minimal bonus anyway."; case "BonusLevelHoeMax": return "Maximum perk level, which bonuses can be applied on HoE difficulty. Perk levels above this won't have any extra bonuses."; case "BonusLevelHoeMax": return "Maximum perk level, which bonuses can be applied on HoE difficulty. Perk levels above this won't have any extra bonuses."; case "Post6RequirementScaling": return "Additional requirement scaling after reaching level 6"; case "MaxZombiesOnce": return "Maximum specimens at once on playtime, note that high values will LAG when theres a lot of them."; case "bHardcore": return "For those who still think game is too easy..."; case "bSpawn0": return "All initial weapons costs nothing"; case "bReplacePickups": return "Replaces weapon pickups on a map with their Scrn Editon (SE) versions."; case "bReplacePickupsStory": return "Replaces weapon pickups in Objective Mode with their Scrn Editon (SE) versions."; case "bReplaceNades": return "Replaces hand grenades with 'coockable' ScrN version. Players can disable grenade cooking in ScrN Settings menu anyway. Disabling it here removes this ability from the server."; case "bShieldWeight": return "Kevlar Vest weights 1 block instead of hand grenades. Players without vest can carry more. Automatically enables hand grenade replacing with ScrN version"; case "bAltBurnMech": return "Use Alternate Burning Mechanism. Shorter burning period, but higher damage at the begining. Also fixes many bugs, including Crawler Infinite Burning."; case "bShowDamages": return "Allows showing damage values on the HUD. Clients will still be able to turn it off in their User.ini"; case "bReplaceHUD": return "Replace heads-up display with ScrN version (recommended). Disable only if you have compatibility issues with other mods!"; case "bNoPerkChanges": return "Disables perk changes during the game."; case "EventNum": return "Setup KF event zeds"; case "bForceEvent": return "Check it to force selected event"; case "bUseDLCLocks": return "If checked, then trader items may have perk level or/and achievement requirements."; case "bUseDLCLevelLocks": return "Uncheck this to leave only achievement-specific trader requirements."; //case "PerkedWeapons": return "List of perked custom weapons for perk bonuses in format '::'"; //case "CustomPerks": return "List of custom perks. Perks should be defined the same way as in Serverperks.ini"; } return Super.GetDescriptionText(PropName); } function GetServerDetails( out GameInfo.ServerResponseLine ServerState ) { // append the mutator name. local int i; local string wave_status; super.GetServerDetails(ServerState); if ( !bServerInfoVeterancy ) { for ( i=0; i= 7 ) // HoE { MinLevel = BonusLevelHoeMin; MaxLevel = BonusLevelHoeMax; } else if (Level.Game.GameDifficulty >= 5 ) // Suicidal { MinLevel = BonusLevelSuiMin; MaxLevel = BonusLevelSuiMax; } else if ( Level.Game.GameDifficulty >= 4 ) // Hard { MinLevel = BonusLevelHardMin; MaxLevel = BonusLevelHardMax; } else { MinLevel = -1; MaxLevel = BonusLevelNormalMax; } if ( ScrnGT != none && ScrnGT.IsTourney() ) { MaxLevel = clamp(MaxLevel, 0, 6); MinLevel = MaxLevel; } if ( MinLevel > MaxLevel ) MinLevel = MaxLevel; OriginalMaxLevel = MaxLevel; //for the replication SrvMinLevel = MinLevel; SrvMaxLevel = MaxLevel; } function SetReplicationData() { SrvMinLevel = MinLevel; SrvMaxLevel = MaxLevel; SrvAchievementFlags = AchievementFlags; SrvFlags = 0; // if ( bSpawnBalance ) SrvFlags = SrvFlags | 0x00000001; if ( bSpawn0 ) SrvFlags = SrvFlags | 0x00000002; if ( bNoStartCashToss ) SrvFlags = SrvFlags | 0x00000004; if ( bMedicRewardFromTeam ) SrvFlags = SrvFlags | 0x00000008; // if ( bWeaponFix ) SrvFlags = SrvFlags | 0x00000010; if ( bAltBurnMech ) SrvFlags = SrvFlags | 0x00000020; // if ( bGunslinger ) SrvFlags = SrvFlags | 0x00000040; if ( bTraderSpeedBoost ) SrvFlags = SrvFlags | 0x00000080; if ( bReplaceNades ) SrvFlags = SrvFlags | 0x00000100; if ( bShieldWeight ) SrvFlags = SrvFlags | 0x00000200; if ( bHardcore ) SrvFlags = SrvFlags | 0x00000400; if ( bBeta ) SrvFlags = SrvFlags | 0x00000800; if ( bShowDamages ) SrvFlags = SrvFlags | 0x00001000; if ( bManualReload ) SrvFlags = SrvFlags | 0x00002000; if ( bForceManualReload ) SrvFlags = SrvFlags | 0x00004000; if ( bAllowWeaponLock ) SrvFlags = SrvFlags | 0x00008000; if ( bNoPerkChanges ) SrvFlags = SrvFlags | 0x00010000; if ( bPerkChangeBoss ) SrvFlags = SrvFlags | 0x00020000; if ( b10Stars ) SrvFlags = SrvFlags | 0x00040000; if ( bBuyPerkedWeaponsOnly ) SrvFlags = SrvFlags | 0x00080000; } simulated function LoadReplicationData() { if ( Role == ROLE_Authority ) return; MinLevel = SrvMinLevel; MaxLevel = SrvMaxLevel; AchievementFlags = SrvAchievementFlags; // bSpawnBalance = (SrvFlags & 0x00000001) > 0; bSpawn0 = (SrvFlags & 0x00000002) > 0; bNoStartCashToss = (SrvFlags & 0x00000004) > 0; bMedicRewardFromTeam = (SrvFlags & 0x00000008) > 0; // bWeaponFix = (SrvFlags & 0x00000010) > 0; bAltBurnMech = (SrvFlags & 0x00000020) > 0; // bGunslinger = (SrvFlags & 0x00000040) > 0; bTraderSpeedBoost = (SrvFlags & 0x00000080) > 0; bReplaceNades = (SrvFlags & 0x00000100) > 0; bShieldWeight = (SrvFlags & 0x00000200) > 0; bHardcore = (SrvFlags & 0x00000400) > 0; bBeta = (SrvFlags & 0x00000800) > 0; bShowDamages = (SrvFlags & 0x00001000) > 0; bManualReload = (SrvFlags & 0x00002000) > 0; bForceManualReload = (SrvFlags & 0x00004000) > 0; bAllowWeaponLock = (SrvFlags & 0x00008000) > 0; bNoPerkChanges = (SrvFlags & 0x00010000) > 0; bPerkChangeBoss = (SrvFlags & 0x00020000) > 0; b10Stars = (SrvFlags & 0x00040000) > 0; bBuyPerkedWeaponsOnly = (SrvFlags & 0x00080000) > 0; bPerkChangeDead = (SrvFlags & 0x00100000) > 0; // = (SrvFlags & 0x00200000) > 0; // = (SrvFlags & 0x00400000) > 0; // = (SrvFlags & 0x00800000) > 0; } simulated function ApplySpawnBalance() { // nothing left here } simulated function ApplyWeaponFix() { class'KFMod.ZEDGun'.default.UnlockedByAchievement = -1; class'KFMod.ZEDGun'.default.AppID = 0; class'KFMod.DwarfAxe'.default.UnlockedByAchievement = -1; class'KFMod.DwarfAxe'.default.AppID = 0; // fix missing references class'KFMod.Shotgun'.default.HudImageRef="KillingFloorHUD.WeaponSelect.combat_shotgun_unselected"; class'KFMod.Shotgun'.default.SelectedHudImageRef="KillingFloorHUD.WeaponSelect.combat_shotgun"; class'KFMod.Shotgun'.default.SelectSoundRef="KF_PumpSGSnd.SG_Select"; class'KFMod.Shotgun'.default.MeshRef="KF_Weapons_Trip.Shotgun_Trip"; class'KFMod.Shotgun'.default.SkinRefs[0]="KF_Weapons_Trip_T.Shotguns.shotgun_cmb"; class'KFMod.ShotgunAttachment'.default.MeshRef="KF_Weapons3rd_Trip.Shotgun_3rd"; class'KFMod.DualDeagle'.default.HudImageRef="KillingFloorHUD.WeaponSelect.dual_handcannon_unselected"; class'KFMod.DualDeagle'.default.SelectedHudImageRef="KillingFloorHUD.WeaponSelect.dual_handcannon"; class'KFMod.DualDeagle'.default.SelectSoundRef="KF_HandcannonSnd.50AE_Select"; class'KFMod.DualDeagle'.default.MeshRef="KF_Weapons_Trip.Dual50_Trip"; class'KFMod.DualDeagle'.default.SkinRefs[0]="KF_Weapons_Trip_T.Pistols.deagle_cmb"; class'KFMod.GoldenDualDeagle'.default.HudImageRef="KillingFloor2HUD.WeaponSelect.Gold_Dual_Deagle_unselected"; class'KFMod.GoldenDualDeagle'.default.SelectedHudImageRef="KillingFloor2HUD.WeaponSelect.Gold_Dual_Deagle"; class'KFMod.GoldenDualDeagle'.default.SelectSoundRef="KF_HandcannonSnd.50AE_Select"; class'KFMod.GoldenDualDeagle'.default.MeshRef="KF_Weapons_Trip.Dual50_Trip"; class'KFMod.GoldenDualDeagle'.default.SkinRefs[0]="KF_Weapons_Gold_T.Weapons.Gold_deagle_cmb"; // prevent weapons from dropping on death class'Knife'.default.bCanThrow = bStoryMode; class'Syringe'.default.bCanThrow = bStoryMode; class'Welder'.default.bCanThrow = bStoryMode; } /* Weapon bonuses' letters: W - weapon bonuses (reload, recoil) $ - discount (weapon, ammo) A - primary ammo bonuses (count, magazine size) B - secondary ammo bonuses (count) D - Override damage type with perk's default one (to enable leveling). d - Override secondary fire's damage type P - primary fire bonuses (damage, headshot multiplier, fire rate) S - secondary fire bonuses (damage, headshot multiplier, fire rate) * - Special weapon */ function LoadCustomWeapons() { local string S, WeaponClassStr, WeaponBonusStr, PriceStr; local int i,j; local int PerkIndex, MaxPerkIndex; local bool AllBonuses; local class W; local class ScrnPerk; local ScrnCustomWeaponLink ClientLink; local int ForcePrice; // Load custom perks first MaxPerkIndex = 9; for( i = 0; i < CustomPerks.Length; i++ ) { S = CustomPerks[i]; j = InStr(S,":"); if ( j > 0 ) { PerkIndex = int(Left(S, j)); if ( PerkIndex < 10 || PerkIndex > 255 ) { log("Custom Perk index must be between 10 and 255! Perk '"$S$"' ignored", 'ScrnBalance'); continue; } S = Mid(S, j+1); } else { PerkIndex = MaxPerkIndex + 1; } ScrnPerk = class(DynamicLoadObject(S, Class'Class')); if( ScrnPerk != None ) { Perks[PerkIndex] = ScrnPerk; AddToPackageMap(String(ScrnPerk.Outer.Name)); MaxPerkIndex = max(MaxPerkIndex, PerkIndex); log("Perk: '" $ S $"' loaded with index = " $ String(PerkIndex), 'ScrnBalance'); } else log("Unable to load custom perk: '" $ S $"'.", 'ScrnBalance'); } // Load weapon bonuses for( i=0; i < PerkedWeapons.Length; i++ ) { PriceStr = ""; WeaponBonusStr = ""; S = PerkedWeapons[i]; j = InStr(S,":"); if( j <= 0 ) { log("Illegal Custom Weapon definition: '" $ S $"'! Wrong perk index.", 'ScrnBalance'); continue; } PerkIndex = int(Left(S, j)); if ( PerkIndex < 0 || PerkIndex >= Perks.length || Perks[PerkIndex] == none ) { log("Illegal Custom Weapon definition: '" $ S $"'! Wrong perk index.", 'ScrnBalance'); continue; } ScrnPerk = Perks[PerkIndex]; WeaponClassStr = Mid(S, j+1); // bonuses j = InStr(WeaponClassStr,":"); if ( j >= 0 ) { WeaponBonusStr = Mid(WeaponClassStr, j+1); WeaponClassStr = Left(WeaponClassStr, j); // price j = InStr(WeaponBonusStr,":"); if ( j >= 0 ) { PriceStr = Mid(WeaponBonusStr, j+1); WeaponBonusStr = Left(WeaponBonusStr, j); } } AllBonuses = WeaponBonusStr == ""; ForcePrice = int(PriceStr); //log("WeaponBonusStr="$WeaponBonusStr @ "ForcePrice="$ForcePrice , 'ScrnBalance'); W = class(DynamicLoadObject(WeaponClassStr, Class'Class')); if( W == none ) { log("Can't load Custom Weapon: '" $ WeaponClassStr $"'!", 'ScrnBalance'); continue; } ClientLink = spawn(class'ScrnBalanceSrv.ScrnCustomWeaponLink'); if ( ClientLink == none ) { log("Can't load Client Replication Link for a Custom Weapon: '" $ W $"'!", 'ScrnBalance'); continue; } //add to the begining ClientLink.NextReplicationInfo = CustomWeaponLink; CustomWeaponLink = ClientLink; ClientLink.Perk = ScrnPerk; ClientLink.WeaponClass = W; if ( AllBonuses ) { ClientLink.bWeapon = true; ClientLink.bDiscount = true; ClientLink.bFire = true; ClientLink.bFireAlt = true; ClientLink.bAmmo = true; ClientLink.bAmmoAlt = true; } else { ClientLink.bWeapon = InStr(WeaponBonusStr,"W") != -1; ClientLink.bDiscount = InStr(WeaponBonusStr,"$") != -1; ClientLink.bFire = InStr(WeaponBonusStr,"P") != -1; ClientLink.bFireAlt = InStr(WeaponBonusStr,"S") != -1; ClientLink.bAmmo = InStr(WeaponBonusStr,"A") != -1; ClientLink.bAmmoAlt = InStr(WeaponBonusStr,"B") != -1; } ClientLink.bOverrideDamType = InStr(WeaponBonusStr,"D") != -1; ClientLink.bOverrideDamTypeAlt = InStr(WeaponBonusStr,"d") != -1; ClientLink.bSpecial = InStr(WeaponBonusStr,"*") != -1; ClientLink.ForcePrice = ForcePrice; ClientLink.LoadWeaponBonuses(); } } function LoadSpawnInventory() { local int i, j, index, k; local byte X; local string S, PickupStr, LevelStr, AmmoStr, SellStr, AchStr; local int PerkIndex; local class ScrnPerk; local class Pickup; local bool bAllPerks; local bool bTourney; bTourney = ScrnGT != none && ScrnGT.IsTourney(); // clear old inventory left from previous map for ( j=0; j 0 ) { X = int(Mid(S, j+1)); S = Left(S, j); } if ( S == "*" ) { bAllPerks = true; PerkIndex = 0; } else PerkIndex = int(S); if ( PerkIndex < 0 || PerkIndex >= Perks.length || Perks[PerkIndex] == none ) { log("Illegal Spawn Inventory definition: '" $ S $"'! Wrong perk index.", 'ScrnBalance'); continue; } ScrnPerk = Perks[PerkIndex]; //pickup j = InStr(PickupStr,":"); if ( j >= 0 ) { LevelStr = Mid(PickupStr, j+1); PickupStr = Left(PickupStr, j); // ammo j = InStr(LevelStr,":"); if ( j >= 0 ) { AmmoStr = Mid(LevelStr, j+1); LevelStr = Left(LevelStr, j); // sell value j = InStr(AmmoStr,":"); if ( j >= 0 ) { SellStr = Mid(AmmoStr, j+1); AmmoStr = Left(AmmoStr, j); } // Achievement j = InStr(SellStr,":"); if ( j >= 0 ) { AchStr = Mid(SellStr, j+1); SellStr = Left(SellStr, j); } } } if ( bTourney && AchStr != "" ) continue; // do not allow achievement-specific inventory in tournaments Pickup = class(DynamicLoadObject(PickupStr, Class'Class')); if( Pickup == none ) { log("Can't load Spawn Inventory: '" $ PickupStr $"'!", 'ScrnBalance'); continue; } index = ScrnPerk.default.DefaultInventory.length; ScrnPerk.default.DefaultInventory.insert(index, 1); ScrnPerk.default.DefaultInventory[index].PickupClass = Pickup; // LevelStr in format [-] j = InStr(LevelStr,"-"); if ( j > 0 ) { ScrnPerk.default.DefaultInventory[index].MinPerkLevel = byte(Left(LevelStr, j)); ScrnPerk.default.DefaultInventory[index].MaxPerkLevel = byte(Mid(LevelStr, j+1)); } else { ScrnPerk.default.DefaultInventory[index].MinPerkLevel = byte(LevelStr); ScrnPerk.default.DefaultInventory[index].MaxPerkLevel = ScrnPerk.default.DefaultInventory[index].MinPerkLevel; } // AmmoStr in format [+] if ( AmmoStr != "" ) { ScrnPerk.default.DefaultInventory[index].bSetAmmo = true; j = InStr(AmmoStr,"+"); if ( j > 0 ) { ScrnPerk.default.DefaultInventory[index].AmmoAmount = int(Left(AmmoStr, j)); ScrnPerk.default.DefaultInventory[index].AmmoPerLevel = int(Mid(AmmoStr, j+1)); } else { ScrnPerk.default.DefaultInventory[index].AmmoAmount = int(AmmoStr); } } // SellValue if ( SellStr != "" ) ScrnPerk.default.DefaultInventory[index].SellValue = int(SellStr); if ( AchStr != "" ) ScrnPerk.default.DefaultInventory[index].Achievement = StringToName(AchStr); ScrnPerk.default.DefaultInventory[index].X = X; if ( bAllPerks ) { for ( j=1; j OldInv; for( i=0; i= 1000 ) KFMonster(Other).ZapThreshold = 1.75; GameRules.RegisterMonster(KFMonster(Other)); } else if ( SRStatsBase(Other) != none ) { SetupRepLink(SRStatsBase(Other).Rep); } else if ( Other.class == class'ScrnAmmoPickup' ) { Other.SetStaticMesh(AmmoBoxMesh); Other.SetDrawScale(AmmoBoxDrawScale); Other.SetDrawScale3D(AmmoBoxDrawScale3D); } else if ( bStoryMode ) { if ( KFLevelRules_Story(Other) != none ) { if ( bReplacePickupsStory ) SetupStoryRules(KFLevelRules_Story(Other)); } else if ( KF_StoryNPC(Other) != none ) { if ( Other.class == class'KF_BreakerBoxNPC' ) // don't alter subclasses KF_StoryNPC(Other).BaseAIThreatRating = 20; else if ( Other.class == class'KF_RingMasterNPC' ) KF_StoryNPC(Other).BaseAIThreatRating = 40; } } return true; } function SetupRepLink(ClientPerkRepLink R) { local ScrnClientPerkRepLink ScrnRep; local int i, j; if ( R == none ) return; // replace with ScrnClientPerkRepLink if ( ScrnClientPerkRepLink(R) != none ) return; // already set up ScrnRep = Spawn(Class'ScrnClientPerkRepLink',R.Owner); ScrnRep.StatObject = R.StatObject; ScrnRep.StatObject.Rep = ScrnRep; ScrnRep.ServerWebSite = R.ServerWebSite; ScrnRep.MinimumLevel = R.MinimumLevel; ScrnRep.MaximumLevel = R.MaximumLevel; ScrnRep.RequirementScaling = R.RequirementScaling; ScrnRep.CachePerks = R.CachePerks; // remove non-scrn perks for( i=0; i(ScrnRep.CachePerks[i].PerkClass) == none ) ScrnRep.CachePerks.remove(i--, 1); } ScrnRep.OwnerPC = ScrnPlayerController(R.Owner); ScrnRep.OwnerPRI = KFPlayerReplicationInfo(ScrnRep.OwnerPC.PlayerReplicationInfo); log("Creating ScrnClientPerkRepLink for player " $ ScrnRep.OwnerPRI.PlayerName, 'ScrnBalance'); R.GotoState(''); R.Destroy(); R = ScrnRep; class'ScrnAchievements'.static.InitAchievements(ScrnRep); if ( bUseDLCLocks && !bTSCGame && (ScrnGT == none || !ScrnGT.IsTourney()) ) { ScrnRep.Locks.Length = LockCount; for( i=0; i 250 ) ScrnRep.ShopCategories.Length = 250; //wtf? ScrnRep.TotalCategories = ScrnRep.ShopCategories.Length; ScrnRep.TotalWeapons = ScrnRep.ShopInventory.Length; ScrnRep.TotalLocks = ScrnRep.Locks.Length; ScrnRep.TotalChars = ScrnRep.CustomChars.Length; } function ForceEvent() { local int i; local class MC; i = MapInfo.FindMapInfo(false); if ( i != -1 && MapInfo.MapInfo[i].ForceEventNum > 0 ) CurrentEventNum = MapInfo.MapInfo[i].ForceEventNum; else if ( EventNum == 0 ) CurrentEventNum = int(KF.GetSpecialEventType()); // autodetect event else CurrentEventNum = EventNum; if ( CurrentEventNum == 254 ) { // 254 - random event CurrentEventNum = 1 + rand(4); } if (bScrnWaves) { return; // all we need for ScrnWaves is to load CurrentEventNum. ScrnGameLength will handle everything else. } if ( MC == none ) { switch (CurrentEventNum) { case 0: case 4: case 255: // force regular zeds log("Normal zeds forced for this map", 'ScrnBalance'); KF.MonsterCollection = class'KFMod.KFMonstersCollection'; CurrentEventNum = 0; break; case 1: log("Summer zeds forced for this map", 'ScrnBalance'); KF.MonsterCollection = class'KFMod.KFMonstersSummer'; break; case 2: log("Halloween zeds forced for this map", 'ScrnBalance'); KF.MonsterCollection = class'KFMod.KFMonstersHalloween'; break; case 3: log("Xmas zeds forced for this map", 'ScrnBalance'); KF.MonsterCollection = class'KFMod.KFMonstersXmas'; break; default: log("Unknown Event Number: "$CurrentEventNum, 'ScrnBalance'); CurrentEventNum = EventNum; return; } } KF.SpecialEventMonsterCollections[KF.GetSpecialEventType()] = KF.MonsterCollection; class'ScrnGameRules'.static.ResetGameSquads(KF, CurrentEventNum); KF.PrepareSpecialSquads(); KF.LoadUpMonsterList(); } // returns index from Squads array or -1, if squad is not found and bCreateNew=false // quad is not found and bCreateNew=true, new squad will be added with a given name function int FindSquad(String SquadName, optional bool bCreateNew) { local int i; for ( i=0; i MC; local name pkg; for ( i=0; i(DynamicLoadObject(VoteSquad[i].MonsterClass,Class'Class')); if ( MC == none ) { log("SetupVoteSquad: Unable to load monster '"$VoteSquad[i].MonsterClass, 'ScrnBalance'); continue; } MC.static.PreCacheAssets(Level); pkg = MC.outer.name; if ( pkg != 'KFChar' ) { AddToPackageMap(String(pkg)); log(pkg $ " added to ServerPackages", 'ScrnBalance'); } q = FindSquad(VoteSquad[i].SquadName, true); j = VoteSquad[i].NumMonsters; while ( j-- > 0 ) Squads[q].Monsters[Squads[q].Monsters.length] = MC; } } function bool IsSquadWaitingToSpawn() { return SquadSpawnedMonsters > 0 && KF.WaveMonsters < SquadSpawnedMonsters; } function SpawnSquad(String SquadName) { local int q, count, i; if ( KF.bTradingDoorsOpen || KF.TotalMaxMonsters <= 0 || IsSquadWaitingToSpawn() ) return; q = FindSquad(SquadName); if ( q == -1 ) return; count = Squads[q].Monsters.length; if ( count == 0 || count > KF.TotalMaxMonsters - KF.NextSpawnSquad.Length ) return; SquadSpawnedMonsters = KF.WaveMonsters + count; KF.NextSpawnSquad.insert(0, count); for ( i=0; i 6 ) // KF.NextSpawnSquad.Remove(6, KF.NextSpawnSquad.length - 6); KF.LastZVol = KF.FindSpawningVolume(); KF.LastSpawningVolume = KF.LastZVol; } function SetMaxZombiesOnce() { local int i, value; i = MapInfo.FindMapInfo(false); if ( i != -1 && MapInfo.MapInfo[i].MaxZombiesOnce >= 16 ) value = MapInfo.MapInfo[i].MaxZombiesOnce; else value = MaxZombiesOnce; value = clamp(value, 16, 254); KF.StandardMaxZombiesOnce = value; KF.MaxZombiesOnce = value; KF.MaxMonsters = Clamp(KF.TotalMaxMonsters,5,value); } function LogObjects() { log("LIST OF LOADED OBJECTS:"); ConsoleCommand("OBJ LIST", true); } function PostBeginPlay() { local ScrnVotingHandlerMut VH; local ScrnAchHandler AchHandler; local int i; local KFGameReplicationInfo KFGRI; KF = KFGameType(Level.Game); if (KF == none) { Log("ERROR: Wrong GameType (requires KFGameType)", 'ScrnBalance'); Destroy(); return; } KFGRI = KFGameReplicationInfo(Level.Game.GameReplicationInfo); if ( bLogObjectsAtMapStart ) LogObjects(); if ( Mut != none && Mut != self ) Mut.Destroy(); Mut = self; default.Mut = self; class'ScrnBalance'.default.Mut = self; // in case of classes extended from ScrnBalance KF.MonsterCollection = KF.SpecialEventMonsterCollections[KF.GetSpecialEventType()]; // v1061 fix KF.bUseZEDThreatAssessment = true; // always use ScrnHumanPawn.AssessThreatTo() bStoryMode = KFStoryGameInfo(KF) != none; bTSCGame = TSCGame(KF) != none && !TSCGame(KF).bSingleTeamGame; ScrnGT = ScrnGameType(KF); if ( ScrnGT != none ) { ScrnGT.ScrnBalanceMut = self; } else if ( ScrnStoryGameInfo(KF) != none ) { ScrnStoryGameInfo(KF).ScrnBalanceMut = self; } MapInfo = Spawn(Class'ScrnBalanceSrv.ScrnMapInfo'); if ( bForceEvent ) ForceEvent(); else CurrentEventNum = int(KF.GetSpecialEventType()); // autodetect event AddToPackageMap("ScrnAnims.ukx"); AddToPackageMap("ScrnSnd.uax"); // Promoted!!!!!!!!!! :) if ( !bStoryMode ) { SetMaxZombiesOnce(); } // CHECK & LOAD SERVERPERKS GetRidOfMut('AliensKFServerPerksMut'); FindServerPerksMut(); if ( ServerPerksMut == none ) { log("ServerPerksMut must be loaded before ScrN Balance! Loading it now...", 'ScrnBalance'); Level.Game.AddMutator(ServerPerksPkgName, false); //check again FindServerPerksMut(); if ( ServerPerksMut == none ) log("Unable to spawn " $ ServerPerksPkgName, 'ScrnBalance'); } bAllowAlwaysPerkChanges = ServerPerksMut.GetPropertyText("bAllowAlwaysPerkChanges") ~= "True"; bNoPerkChanges = bNoPerkChanges && !bAllowAlwaysPerkChanges; if ( !ClassIsChildOf(KF.PlayerControllerClass, class'ScrnBalanceSrv.ScrnPlayerController') ) { KF.PlayerControllerClass = class'ScrnBalanceSrv.ScrnPlayerController'; KF.PlayerControllerClassName = string(Class'ScrnBalanceSrv.ScrnPlayerController'); } if ( bReplaceHUD ) KF.HUDType = string(Class'ScrnBalanceSrv.ScrnHUD'); if ( bReplaceScoreBoard ) Level.Game.ScoreBoardType = string(Class'ScrnBalanceSrv.ScrnScoreBoard'); KF.LoginMenuClass = string(Class'ScrnBalanceSrv.ScrnInvasionLoginMenu'); Persistence = new class'ScrnBalancePersistence'; if ( Persistence.Difficulty > 0 ) { if ( Persistence.Difficulty == 6 || Persistence.Difficulty == 8 ) { bHardcore = true; KF.GameDifficulty = Persistence.Difficulty - 1; log("Game difficulty: " $ string(KF.GameDifficulty) $ " + Hardcore", 'ScrnBalance'); } else { bHardcore = false; KF.GameDifficulty = Persistence.Difficulty; log("Game difficulty: " $ string(KF.GameDifficulty), 'ScrnBalance'); } KFGRI.GameDiff = KF.GameDifficulty; KFGRI.BaseDifficulty = KF.GameDifficulty; } SetLevels(); SetReplicationData(); //exec this on server side only ApplySpawnBalance(); ApplyWeaponFix(); bUseAchievements = bool(AchievementFlags & ACH_ENABLE); GameRules = Spawn(Class'ScrnBalanceSrv.ScrnGameRules'); if ( GameRules != none ) { GameRules.Mut = self; GameRules.bShowDamages = bShowDamages; GameRules.bUseAchievements = bUseAchievements && KF.GameDifficulty >= 2; if ( GameRules.bUseAchievements ) { // spawn achievement handlers AchHandler = GameRules.Spawn(Class'ScrnBalanceSrv.ScrnAchHandler'); } if ( !bScrnWaves && (bResetSquadsAtStart || EventNum == 254) ) { GameRules.ResetGameSquads(KF, CurrentEventNum); } } else { log("Unable to spawn Game Rules!", 'ScrnBalance'); } if (bAltBurnMech) { BurnMech = spawn(class'ScrnBalanceSrv.ScrnBurnMech'); default.BurnMech = BurnMech; if ( bDoubleDoT ) { BurnMech.BurnPeriod = 0.5; BurnMech.BurnDuration = 16; BurnMech.BurnInCount = 4; if ( AchHandler != none ) AchHandler.iDoT_Damage = 150; } } if ( bAllowVoting ) { VH = class'ScrnVotingHandlerMut'.static.GetVotingHandler(Level.Game); if ( VH == none ) { Level.Game.AddMutator(string(class'ScrnVotingHandlerMut'), false); VH = class'ScrnVotingHandlerMut'.static.GetVotingHandler(Level.Game); } if ( VH != none ) { MyVotingOptions = ScrnBalanceVoting(VH.AddVotingOptions(class'ScrnBalanceSrv.ScrnBalanceVoting')); if ( MyVotingOptions != none ) { MyVotingOptions.Mut = self; } } else log("Unable to spawn voting handler mutator", 'ScrnBalance'); } LoadCustomWeapons(); // proceed DLCLocks LockCount = 0; for ( i=0; i(DynamicLoadObject(DLCLocks[i].Item, Class'Class')); if ( DLCLocks[i].PickupClass != none && (bUseDLCLevelLocks || DLCLocks[i].Type != LOCK_Level) ) ++LockCount; } InitSettings(); LoadSpawnInventory(); SetupVoteSquads(); SetupSrvInfo(); if ( bStoryMode ) { class'ScrnAchievements'.static.RegisterAchievements(class'AchObjMaps'); } Log(FriendlyName @ GetVersionStr()$" loaded", 'ScrnBalance'); for ( i=0; i= 2 ) DoubleDoorKeys[DoubleDoorKeys.Length] = t; } } function CheckDoors() { local int i, j; local bool bBlowDoors; local KFUseTrigger key; for ( i=0; i 0.505 ) { // weld key.WeldStrength = (f - 0.5) * 2.0; for ( j = 0; j < key.DoorOwners.Length; ++j ) { key.DoorOwners[j].bShouldBeOpen = false; key.DoorOwners[j].RespawnDoor(); key.DoorOwners[j].DoClose(); if ( !key.DoorOwners[j].bNoSeal ) { key.DoorOwners[j].SetWeldStrength(key.WeldStrength); } } } else if ( f > 0.25 ) { // unweld or respawn key.WeldStrength = 0; for ( j = 0; j < key.DoorOwners.Length; ++j ) { key.DoorOwners[j].RespawnDoor(); key.DoorOwners[j].SetWeldStrength(0); } } else { // blow for ( j = 0; j < key.DoorOwners.Length; ++j ) { if ( !key.DoorOwners[j].bDoorIsDead ) { key.DoorOwners[j].GoBang(none, vect(0,0,0), vect(0,0,0), none); } } } } } static function class PickRandomPerk(ScrnClientPerkRepLink L) { local array< class > CA; local int i; local class Perk; for ( i=0; i < L.CachePerks.length; ++i ) { if ( L.CachePerks[i].CurrentLevel > 0 ) { Perk = class(L.CachePerks[i].PerkClass); if ( Perk != none && !Perk.default.bLocked ) CA[CA.Length] = Perk; } } if ( CA.Length > 0 ) return CA[rand(CA.Length)]; return none; } function LockPerk(class Perk, bool bLock) { local Controller C; local PlayerController Player; local ClientPerkRepLink L; local int i; local class RandomPerk; Perk.default.bLocked = bLock; for ( C = Level.ControllerList; C != none; C = C.nextController ) { Player = PlayerController(C); if ( Player != none && SRStatsBase(Player.SteamStatsAndAchievements) != none ) { L = SRStatsBase(Player.SteamStatsAndAchievements).Rep; if ( L != none ) { for ( i=0; i < L.CachePerks.length; ++i ) { if ( L.CachePerks[i].PerkClass == Perk ) { if ( bLock ) { L.ClientPerkLevel(i, 255); // mark perk as locked if ( KFPlayerReplicationInfo(Player.PlayerReplicationInfo).ClientVeteranSkill == Perk ) { RandomPerk = PickRandomPerk(ScrnClientPerkRepLink(L)); if ( RandomPerk != none ) ScrnClientPerkRepLink(L).ServerSelectPerkSE(RandomPerk); } } else { // set highest bit to 1 (128 = 10000000b) to notify client // that perk has been unlocked L.ClientPerkLevel(i, 0x80 | L.CachePerks[i].PerkClass.static.PerkIsAvailable(L)); } break; } } } } } } function bool ShouldReplacePickups() { if ( bStoryMode ) return bReplacePickupsStory; return bReplacePickups; } // replaces weapon pickup's inventory type with ScrN version of that weapon // returns true of replacement was made function bool ReplacePickup( Pickup item ) { local int i; if ( FragPickup(item) != none ) { if ( !bReplaceNades || ScrnFragPickup(item) != none ) return false; i = FragReplacementIndex; // index of frag replacement } else { if ( !ShouldReplacePickups() ) return false; i = FindPickupReplacementIndex(item); if ( i == -1 ) return false; } item.InventoryType = pickupReplaceArray[i].NewClass.default.InventoryType; item.default.InventoryType = pickupReplaceArray[i].NewClass.default.InventoryType; // pistols reset they inventory type to default if ( KFWeaponPickup(item) != none ) { KFWeaponPickup(item).Weight = class(pickupReplaceArray[i].NewClass).default.Weight; KFWeaponPickup(item).default.Weight = class(pickupReplaceArray[i].NewClass).default.Weight; } return true; } // returns -1, if not found function int FindPickupReplacementIndex( Pickup item ) { local int i; for ( i=0; i 0; } static function DestroyLinkedInfo( LinkedReplicationInfo EntryLink ) { local LinkedReplicationInfo CurrentLink, NextLink; for ( CurrentLink = EntryLink; CurrentLink != none; CurrentLink = NextLink ) { NextLink = CurrentLink.NextReplicationInfo; CurrentLink.Destroy(); } EntryLink = none; } function ServerTraveling(string URL, bool bItems) { local int j; log("ServerTraveling", 'ScrnBalance'); if ( bLogObjectsAtMapEnd ) LogObjects(); if (NextMutator != None) NextMutator.ServerTraveling(URL,bItems); if ( ScrnGT == none || ScrnGT.ScrnGameLength == none ) class'ScrnGameRules'.static.ResetGameSquads(KF, CurrentEventNum); class'ScrnAchievements'.static.ResetAchList(); if ( Level.NetMode == NM_DedicatedServer ) { // break links to self Mut = none; default.Mut = none; class'ScrnBalance'.default.Mut = none; } for ( j=0; j KFPRIArray; local array PipeBombCapacity; local int i; foreach DynamicActors(Class'PipeBombProjectile',P) { if( !P.bHidden && P.Instigator != none ) { KFPRI = KFPlayerReplicationInfo(P.Instigator.PlayerReplicationInfo); if ( KFPRI == none || KFPRI.ClientVeteranSkill == none ) continue; for ( i=0; i 0 ) PipeBombCapacity[i]--; else P.bEnemyDetected = true; // blow up } } } function BlamePlayer(ScrnPlayerController PC, string Reason, optional int BlameInc) { local ScrnCustomPRI ScrnPRI; if ( PC == none ) return; ScrnPRI = class'ScrnCustomPRI'.static.FindMe(PC.PlayerReplicationInfo); if ( ScrnPRI == none ) return; if ( BlameInc == 0 ) BlameInc = 1; ScrnPRI.BlameCounter += BlameInc; PC.ReceiveLocalizedMessage(class'ScrnBlamedMsg', ScrnPRI.BlameCounter); ReplaceText(Reason, "%p", PC.GetHumanReadableName()); BroadcastMessage(ColorString(Reason, 200, 200, 1), false); } final static function bool GetHighlyDecorated(int SteamID32, out material Avatar, out material ClanIcon, out material PreNameIcon, out Color PrefixIconColor, out material PostNameIcon, out Color PostfixIconColor, out int Playoffs, out int TourneyWon) { local int start, end, i; start = 0; end = default.HighlyDecorated.length; while ( start < end ) { i = start + ((end - start)>>1); if ( SteamID32 == default.HighlyDecorated[i].SteamID32 ) { if ( default.HighlyDecorated[i].Avatar == none && default.HighlyDecorated[i].AvatarRef != "" ) default.HighlyDecorated[i].Avatar = Material(DynamicLoadObject(default.HighlyDecorated[i].AvatarRef, class'Material')); if ( default.HighlyDecorated[i].ClanIcon == none && default.HighlyDecorated[i].ClanIconRef != "" ) default.HighlyDecorated[i].ClanIcon = Material(DynamicLoadObject(default.HighlyDecorated[i].ClanIconRef, class'Material')); if ( default.HighlyDecorated[i].PreNameIcon == none && default.HighlyDecorated[i].PreNameIconRef != "" ) default.HighlyDecorated[i].PreNameIcon = Material(DynamicLoadObject(default.HighlyDecorated[i].PreNameIconRef, class'Material')); if ( default.HighlyDecorated[i].PostNameIcon == none && default.HighlyDecorated[i].PostNameIconRef != "" ) default.HighlyDecorated[i].PostNameIcon = Material(DynamicLoadObject(default.HighlyDecorated[i].PostNameIconRef, class'Material')); Avatar = default.HighlyDecorated[i].Avatar; ClanIcon = default.HighlyDecorated[i].ClanIcon; PreNameIcon = default.HighlyDecorated[i].PreNameIcon; PrefixIconColor = default.HighlyDecorated[i].PrefixIconColor; PostNameIcon = default.HighlyDecorated[i].PostNameIcon; PostfixIconColor = default.HighlyDecorated[i].PostfixIconColor; Playoffs = default.HighlyDecorated[i].Playoffs; TourneyWon = default.HighlyDecorated[i].TourneyWon; return true; } else if ( SteamID32 < default.HighlyDecorated[i].SteamID32 ) end = i; else start = i + 1; } Avatar = none; ClanIcon = none; PreNameIcon = none; PostNameIcon = none; Playoffs = 0; TourneyWon = 0; return false; } /** Performs binary search on sorted array. * @param arr : array of sorted items (in ascending order). Array will not be modified. * out modifier is used just for performance purpose (pass by reference). * @param val : value to search * @return array index or -1, if value not found. */ final static function int BinarySearch(out array arr, int val) { local int start, end, i; start = 0; end = arr.length; while ( start < end ) { i = start + ((end - start)>>1); if ( arr[i] == val ) return i; else if ( val < arr[i] ) end = i; else start = i + 1; } return -1; } final static function int BinarySearchStr(out array arr, string val) { local int start, end, i; start = 0; end = arr.length; while ( start < end ) { i = start + ((end - start)>>1); if ( arr[i] == val ) return i; else if ( val < arr[i] ) end = i; else start = i + 1; } return -1; } defaultproperties { BonusCapGroup="ScrnBalance" strBonusLevel="Your effective perk bonus level is [%s]" strVersion="v%m.%n.%p" strStatus="Your perk level: Visual=%v, Effective=[%b]. Server perk range is [%n..%x]." strStatus2="Alt.Burn=%a. MaxZombiesOnce=%m." strSrvWarning="You are using dedicated server version of ScrnBalance that shouldn't be installed on local machines! Please Obtain client version from Steam Workshop." strSrvWarning2="If you are getting version mismatch erros, delete KillingFloorSystemScrnBalanceSrv.u file." strBetaOnly="Only avaliable during Beta testing (bBeta=True)" bAltBurnMech=True bReplaceNades=True bShowDamages=True bAllowWeaponLock=True bTraderSpeedBoost=True BonusLevelNormalMax=4 BonusLevelHardMax=5 BonusLevelSuiMin=4 BonusLevelSuiMax=6 BonusLevelHoeMin=6 BonusLevelHoeMax=6 Post6RequirementScaling=1.000000 WeldingRequirementScaling=1.000000 StalkerRequirementScaling=1.000000 pickupReplaceArray(0)=(oldClass=Class'KFMod.MP7MPickup',NewClass=Class'ScrnBalanceSrv.ScrnMP7MPickup') pickupReplaceArray(1)=(oldClass=Class'KFMod.MP5MPickup',NewClass=Class'ScrnBalanceSrv.ScrnMP5MPickup') pickupReplaceArray(2)=(oldClass=Class'KFMod.KrissMPickup',NewClass=Class'ScrnBalanceSrv.ScrnKrissMPickup') pickupReplaceArray(3)=(oldClass=Class'KFMod.M7A3MPickup',NewClass=Class'ScrnBalanceSrv.ScrnM7A3MPickup') pickupReplaceArray(4)=(oldClass=Class'KFMod.ShotgunPickup',NewClass=Class'ScrnBalanceSrv.ScrnShotgunPickup') pickupReplaceArray(5)=(oldClass=Class'KFMod.BoomStickPickup',NewClass=Class'ScrnBalanceSrv.ScrnBoomStickPickup') pickupReplaceArray(6)=(oldClass=Class'KFMod.NailGunPickup',NewClass=Class'ScrnBalanceSrv.ScrnNailGunPickup') pickupReplaceArray(7)=(oldClass=Class'KFMod.KSGPickup',NewClass=Class'ScrnBalanceSrv.ScrnKSGPickup') pickupReplaceArray(8)=(oldClass=Class'KFMod.BenelliPickup',NewClass=Class'ScrnBalanceSrv.ScrnBenelliPickup') pickupReplaceArray(9)=(oldClass=Class'KFMod.AA12Pickup',NewClass=Class'ScrnBalanceSrv.ScrnAA12Pickup') pickupReplaceArray(10)=(oldClass=Class'KFMod.SinglePickup',NewClass=Class'ScrnBalanceSrv.ScrnSinglePickup') pickupReplaceArray(11)=(oldClass=Class'KFMod.Magnum44Pickup',NewClass=Class'ScrnBalanceSrv.ScrnMagnum44Pickup') pickupReplaceArray(12)=(oldClass=Class'KFMod.MK23Pickup',NewClass=Class'ScrnBalanceSrv.ScrnMK23Pickup') pickupReplaceArray(13)=(oldClass=Class'KFMod.DeaglePickup',NewClass=Class'ScrnBalanceSrv.ScrnDeaglePickup') pickupReplaceArray(14)=(oldClass=Class'KFMod.WinchesterPickup',NewClass=Class'ScrnBalanceSrv.ScrnWinchesterPickup') pickupReplaceArray(15)=(oldClass=Class'KFMod.SPSniperPickup',NewClass=Class'ScrnBalanceSrv.ScrnSPSniperPickup') pickupReplaceArray(16)=(oldClass=Class'KFMod.M14EBRPickup',NewClass=Class'ScrnBalanceSrv.ScrnM14EBRPickup') pickupReplaceArray(17)=(oldClass=Class'KFMod.M99Pickup',NewClass=Class'ScrnBalanceSrv.ScrnM99Pickup') pickupReplaceArray(18)=(oldClass=Class'KFMod.BullpupPickup',NewClass=Class'ScrnBalanceSrv.ScrnBullpupPickup') pickupReplaceArray(19)=(oldClass=Class'KFMod.AK47Pickup',NewClass=Class'ScrnBalanceSrv.ScrnAK47Pickup') pickupReplaceArray(20)=(oldClass=Class'KFMod.M4Pickup',NewClass=Class'ScrnBalanceSrv.ScrnM4Pickup') pickupReplaceArray(21)=(oldClass=Class'KFMod.SPThompsonPickup',NewClass=Class'ScrnBalanceSrv.ScrnSPThompsonPickup') pickupReplaceArray(22)=(oldClass=Class'KFMod.ThompsonDrumPickup',NewClass=Class'ScrnBalanceSrv.ScrnThompsonDrumPickup') pickupReplaceArray(23)=(oldClass=Class'KFMod.SCARMK17Pickup',NewClass=Class'ScrnBalanceSrv.ScrnSCARMK17Pickup') pickupReplaceArray(24)=(oldClass=Class'KFMod.FNFAL_ACOG_Pickup',NewClass=Class'ScrnBalanceSrv.ScrnFNFAL_ACOG_Pickup') pickupReplaceArray(25)=(oldClass=Class'KFMod.MachetePickup',NewClass=Class'ScrnBalanceSrv.ScrnMachetePickup') pickupReplaceArray(26)=(oldClass=Class'KFMod.AxePickup',NewClass=Class'ScrnBalanceSrv.ScrnAxePickup') pickupReplaceArray(27)=(oldClass=Class'KFMod.ChainsawPickup',NewClass=Class'ScrnBalanceSrv.ScrnChainsawPickup') pickupReplaceArray(28)=(oldClass=Class'KFMod.KatanaPickup',NewClass=Class'ScrnBalanceSrv.ScrnKatanaPickup') pickupReplaceArray(29)=(oldClass=Class'KFMod.ScythePickup',NewClass=Class'ScrnBalanceSrv.ScrnScythePickup') pickupReplaceArray(30)=(oldClass=Class'KFMod.ClaymoreSwordPickup',NewClass=Class'ScrnBalanceSrv.ScrnClaymoreSwordPickup') pickupReplaceArray(31)=(oldClass=Class'KFMod.CrossbuzzsawPickup',NewClass=Class'ScrnBalanceSrv.ScrnCrossbuzzsawPickup') pickupReplaceArray(32)=(oldClass=Class'KFMod.MAC10Pickup',NewClass=Class'ScrnBalanceSrv.ScrnMAC10Pickup') pickupReplaceArray(33)=(oldClass=Class'KFMod.FlareRevolverPickup',NewClass=Class'ScrnBalanceSrv.ScrnFlareRevolverPickup') pickupReplaceArray(34)=(oldClass=Class'KFMod.DualFlareRevolverPickup',NewClass=Class'ScrnBalanceSrv.ScrnDualFlareRevolverPickup') pickupReplaceArray(35)=(oldClass=Class'KFMod.FlameThrowerPickup',NewClass=Class'ScrnBalanceSrv.ScrnFlameThrowerPickup') pickupReplaceArray(36)=(oldClass=Class'KFMod.HuskGunPickup',NewClass=Class'ScrnBalanceSrv.ScrnHuskGunPickup') pickupReplaceArray(37)=(oldClass=Class'KFMod.PipeBombPickup',NewClass=Class'ScrnBalanceSrv.ScrnPipeBombPickup') pickupReplaceArray(38)=(oldClass=Class'KFMod.M4203Pickup',NewClass=Class'ScrnBalanceSrv.ScrnM4203Pickup') pickupReplaceArray(39)=(oldClass=Class'KFMod.M32Pickup',NewClass=Class'ScrnBalanceSrv.ScrnM32Pickup') pickupReplaceArray(40)=(oldClass=Class'KFMod.LAWPickup',NewClass=Class'ScrnBalanceSrv.ScrnLAWPickup') pickupReplaceArray(41)=(oldClass=Class'KFMod.Dual44MagnumPickup',NewClass=Class'ScrnBalanceSrv.ScrnDual44MagnumPickup') pickupReplaceArray(42)=(oldClass=Class'KFMod.DualMK23Pickup',NewClass=Class'ScrnBalanceSrv.ScrnDualMK23Pickup') pickupReplaceArray(43)=(oldClass=Class'KFMod.DualDeaglePickup',NewClass=Class'ScrnBalanceSrv.ScrnDualDeaglePickup') pickupReplaceArray(44)=(oldClass=Class'KFMod.SyringePickup',NewClass=Class'ScrnBalanceSrv.ScrnSyringePickup') pickupReplaceArray(45)=(oldClass=Class'KFMod.FragPickup',NewClass=Class'ScrnBalanceSrv.ScrnFragPickup') pickupReplaceArray(46)=(oldClass=Class'KFMod.M79Pickup',NewClass=Class'ScrnBalanceSrv.ScrnM79Pickup') pickupReplaceArray(47)=(oldClass=Class'KFMod.CrossbowPickup',NewClass=Class'ScrnBalanceSrv.ScrnCrossbowPickup') pickupReplaceArray(48)=(oldClass=Class'KFMod.KnifePickup',NewClass=Class'ScrnBalanceSrv.ScrnKnifePickup') FragReplacementIndex=45 bReplacePickups=True bReplacePickupsStory=True Functions=Class'ScrnBalanceSrv.ScrnFunctions' GameStartCountDown=12 Perks(0)=Class'ScrnBalanceSrv.ScrnVetFieldMedic' Perks(1)=Class'ScrnBalanceSrv.ScrnVetSupportSpec' Perks(2)=Class'ScrnBalanceSrv.ScrnVetSharpshooter' Perks(3)=Class'ScrnBalanceSrv.ScrnVetCommando' Perks(4)=Class'ScrnBalanceSrv.ScrnVetBerserker' Perks(5)=Class'ScrnBalanceSrv.ScrnVetFirebug' Perks(6)=Class'ScrnBalanceSrv.ScrnVetDemolitions' Perks(7)=Class'ScrnBalanceSrv.ScrnVeterancyTypes' Perks(8)=Class'ScrnBalanceSrv.ScrnVetGunslinger' Perks(9)=Class'ScrnBalanceSrv.ScrnVetCombatMedic' strAchEarn="%p earned an achievement: %a" bBroadcastAchievementEarn=True AchievementFlags=255 bSaveStatsOnAchievementEarned=True bTradingDoorsOpen=True bAllowVoting=True bPauseTraderOnly=True SkippedTradeTimeMult=1.000000 bAllowBlameVote=True bAllowKickVote=True BlameVoteCoolDown=60 bAllowPauseVote=True bAllowLockPerkVote=True bAllowBoringVote=True MaxVoteKillMonsters=5 MaxVoteKillHP=2000 bVoteKillCheckVisibility=True VoteKillPenaltyMult=5.000000 MinVoteDifficulty=2 ServerPerksPkgName="ScrnSP.ServerPerksMutSE" bReplaceHUD=True bReplaceScoreBoard=True Post6ZedSpawnInc=0.250000 Post6AmmoSpawnInc=0.200000 Post6ZedsPerPlayer=0.400000 bAlterWaveSize=True MaxWaveSize=800 MaxZombiesOnce=48 EndGameStatBonus=0.500000 FirstStatBonusMult=2.000000 bStatBonusUsesHL=True SharpProgMinDmg=1000 bBroadcastPickups=True BroadcastPickupText="%p picked up %o's %w ($%$)." bAutoKickOffPerkPlayers=True strAutoKickOffPerk="You have been auto kicked from the server for playing without a perk. Type RECONNECT in the console to join the server again and choose a perk." SpawnInventory(0)="0:ScrnBalanceSrv.ScrnCombatVestPickup:5-255:100" SpawnInventory(1)="0:ScrnBalanceSrv.ScrnMP7MPickup:6-255:200+20:157" SpawnInventory(2)="1:ScrnBalanceSrv.ScrnShotgunPickup:5:24:150" SpawnInventory(3)="1:ScrnBalanceSrv.ScrnBoomStickPickup:6-255:24+6:225" SpawnInventory(4)="2:ScrnBalanceSrv.ScrnWinchesterPickup:5:40:150" SpawnInventory(5)="2:ScrnBalanceSrv.ScrnCrossbowPickup:6-255:12+3:225" SpawnInventory(6)="3:ScrnBalanceSrv.ScrnBullpupPickup:5:200:150" SpawnInventory(7)="3:ScrnBalanceSrv.ScrnAK47Pickup:6-255:150+30:225" SpawnInventory(8)="4:ScrnBalanceSrv.ScrnAxePickup:5::150" SpawnInventory(9)="4:ScrnBalanceSrv.ScrnChainsawPickup:6-255:500+50:225" SpawnInventory(10)="5:ScrnBalanceSrv.ScrnMAC10Pickup:5:200:150" SpawnInventory(11)="5:ScrnBalanceSrv.ScrnFlameThrowerPickup:6-255:320+80:225" SpawnInventory(12)="6:ScrnBalanceSrv.ScrnFragPickup:5:10" SpawnInventory(13)="6:ScrnBalanceSrv.ScrnM79Pickup:6-255:12+2:225" SpawnInventory(14)="8:ScrnBalanceSrv.ScrnDualiesPickup:5:150:150" SpawnInventory(15)="8:ScrnBalanceSrv.ScrnDual44MagnumPickup:6-255:66+12:225" StartCashNormal=250 StartCashHard=250 StartCashSui=200 StartCashHoE=200 MinRespawnCashNormal=200 MinRespawnCashHard=200 MinRespawnCashSui=150 MinRespawnCashHoE=100 TraderTimeNormal=60 TraderTimeHard=60 TraderTimeSui=60 TraderTimeHoE=60 bLeaveCashOnDisconnect=True bPlayerZEDTime=True ColorTags(0)=(t="^0",R=1,G=1,B=1) ColorTags(1)=(t="^1",R=200,G=1,B=1) ColorTags(2)=(t="^2",R=1,G=200,B=1) ColorTags(3)=(t="^3",R=200,G=200,B=1) ColorTags(4)=(t="^4",R=1,G=1,B=255) ColorTags(5)=(t="^5",R=1,G=255,B=255) ColorTags(6)=(t="^6",R=200,G=1,B=200) ColorTags(7)=(t="^7",R=200,G=200,B=200) ColorTags(8)=(t="^8",R=255,G=127) ColorTags(9)=(t="^9",R=128,G=128,B=128) ColorTags(10)=(t="^w$",R=255,G=255,B=255) ColorTags(11)=(t="^r$",R=255,G=1,B=1) ColorTags(12)=(t="^g$",R=1,G=255,B=1) ColorTags(13)=(t="^b$",R=1,G=1,B=255) ColorTags(14)=(t="^y$",R=255,G=255,B=1) ColorTags(15)=(t="^c$",R=1,G=255,B=255) ColorTags(16)=(t="^o$",R=255,G=140,B=1) ColorTags(17)=(t="^u$",R=255,G=20,B=147) ColorTags(18)=(t="^s$",R=1,G=192,B=255) ColorTags(19)=(t="^n$",R=139,G=69,B=19) ColorTags(20)=(t="^W$",R=112,G=138,B=144) ColorTags(21)=(t="^R$",R=132,G=1,B=1) ColorTags(22)=(t="^G$",R=1,G=132,B=1) ColorTags(23)=(t="^B$",R=1,G=1,B=132) ColorTags(24)=(t="^Y$",R=255,G=192,B=1) ColorTags(25)=(t="^C$",R=1,G=160,B=192) ColorTags(26)=(t="^O$",R=255,G=69,B=1) ColorTags(27)=(t="^U$",R=160,G=32,B=240) ColorTags(28)=(t="^S$",R=65,G=105,B=225) ColorTags(29)=(t="^N$",R=80,G=40,B=20) MinZedSpawnPeriod=2.000000 bSpawnRateFix=True bServerInfoVeterancy=True AmmoBoxMesh=StaticMesh'kf_generic_sm.pickups.Metal_Ammo_Box' AmmoBoxDrawScale=1.000000 AmmoBoxDrawScale3D=(X=1.000000,Y=1.000000,Z=1.000000) HighlyDecorated(0)=(SteamID32=3907835,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(1)=(SteamID32=4787302,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(2)=(SteamID32=15243342,ClanIconRef="ScrnTex.Players.Code",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Medic_Grey") HighlyDecorated(3)=(SteamID32=18524053,AvatarRef="ScrnTex.Players.FabZen",ClanIconRef="ScrnTex.Players.SALTY",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Commander_Grey",PostNameIconRef="KillingFloor2HUD.PerkReset.PReset_Commander_Grey") HighlyDecorated(4)=(SteamID32=18871148,ClanIconRef="ScrnTex.Players.SALTY",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Berserker_Grey") HighlyDecorated(5)=(SteamID32=20530727,AvatarRef="ScrnTex.Players.LazyBunta") HighlyDecorated(6)=(SteamID32=21825964,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(7)=(SteamID32=25188900,AvatarRef="ScrnTex.Players.Scuddles",PreNameIconRef="ScrnTex.Perks.Hud_Perk_Star_Gray",PostNameIconRef="ScrnTex.Perks.Hud_Perk_Star_Gray") HighlyDecorated(8)=(SteamID32=26505257,AvatarRef="ScrnTex.Players.Duckbuster",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Support_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(9)=(SteamID32=27263782,AvatarRef="ScrnTex.Players.Termcat",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(10)=(SteamID32=27784497,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(11)=(SteamID32=32271863,AvatarRef="ScrnTex.Players.PooSH",PreNameIconRef="ScrnTex.Perks.Hud_Perk_Star_Gray",PostNameIconRef="ScrnTex.Perks.Hud_Perk_Star_Gray") HighlyDecorated(12)=(SteamID32=32279441,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(13)=(SteamID32=32708029,ClanIconRef="ScrnTex.Players.Dosh",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Firebug_Grey") HighlyDecorated(14)=(SteamID32=32779545,ClanIconRef="ScrnTex.Players.SALTY",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Support_Grey") HighlyDecorated(15)=(SteamID32=32976519,ClanIconRef="ScrnTex.Players.Dosh",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey",Playoffs=1) HighlyDecorated(16)=(SteamID32=34308728,AvatarRef="ScrnTex.Players.Janitor",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Firebug_Grey",PostNameIconRef="KillingFloor2HUD.PerkReset.PReset_Firebug_Grey") HighlyDecorated(17)=(SteamID32=37444251,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(18)=(SteamID32=41734606,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(19)=(SteamID32=43087787,AvatarRef="ScrnTex.Players.Chaos",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(20)=(SteamID32=43944237,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(21)=(SteamID32=44141219,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(22)=(SteamID32=44328745,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(23)=(SteamID32=44388687,AvatarRef="ScrnTex.Players.Aze",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Commander_Grey") HighlyDecorated(24)=(SteamID32=45006648,ClanIconRef="ScrnTex.Players.SALTY",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey") HighlyDecorated(25)=(SteamID32=45088649,AvatarRef="ScrnTex.Players.Joe",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Berserker_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',PrefixIconColor=(B=255,G=255,R=255),Playoffs=1) HighlyDecorated(26)=(SteamID32=45352894,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(27)=(SteamID32=45594574,AvatarRef="ScrnTex.Players.CodeReaper",PreNameIconRef="ScrnTex.Players.BowieKnifeLeft",PostNameIconRef="ScrnTex.Players.BowieKnifeRight") HighlyDecorated(28)=(SteamID32=46023864,AvatarRef="ScrnTex.Players.Baron",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Medic_Grey",PostNameIconRef="ScrnAch_T.Achievements.Baron",PostfixIconColor=(B=255,G=255,R=255,A=255)) HighlyDecorated(29)=(SteamID32=47199674,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(30)=(SteamID32=47820768,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(31)=(SteamID32=49361376,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(32)=(SteamID32=51667940,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(33)=(SteamID32=52109233,PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Support_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(34)=(SteamID32=53781980,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(35)=(SteamID32=54179805,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(36)=(SteamID32=54471316,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(37)=(SteamID32=57193815,ClanIconRef="ScrnTex.Players.Dosh",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey") HighlyDecorated(38)=(SteamID32=58813412,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(39)=(SteamID32=59018230,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(40)=(SteamID32=59344954,PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Support_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(41)=(SteamID32=59865355,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(42)=(SteamID32=61480134,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(43)=(SteamID32=61647562,ClanIconRef="ScrnTex.Players.Dosh",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Demolition_Grey") HighlyDecorated(44)=(SteamID32=63934831,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(45)=(SteamID32=64861994,AvatarRef="ScrnTex.Players.dkanus",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(46)=(SteamID32=66725591,ClanIconRef="ScrnTex.Players.SALTY",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Medic_Grey") HighlyDecorated(47)=(SteamID32=66767874,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(48)=(SteamID32=67141366,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(49)=(SteamID32=68703215,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(50)=(SteamID32=68932148,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(51)=(SteamID32=70606615,AvatarRef="ScrnTex.Players.aaa") HighlyDecorated(52)=(SteamID32=71427768,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(53)=(SteamID32=71462150,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey") HighlyDecorated(54)=(SteamID32=72523409,AvatarRef="ScrnTex.Players.Candybee",PreNameIconRef="ScrnTex.Players.Mudflapgirl_left",PostNameIconRef="ScrnTex.Players.Mudflapgirl_right") HighlyDecorated(55)=(SteamID32=75600845,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(56)=(SteamID32=76661591,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(57)=(SteamID32=77967745,ClanIconRef="ScrnTex.Players.SALTY",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Demolition_Grey") HighlyDecorated(58)=(SteamID32=81279347,ClanIconRef="ScrnTex.Players.Dosh") HighlyDecorated(59)=(SteamID32=81947447,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(60)=(SteamID32=82239578,AvatarRef="ScrnTex.Players.Toaste",PreNameIconRef="ScrnTex.Players.Yinyang",PostNameIconRef="ScrnTex.Players.Yinyang") HighlyDecorated(61)=(SteamID32=83417929,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(62)=(SteamID32=84050600,AvatarRef="ScrnTex.Players.NikC",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Demolition_Grey") HighlyDecorated(63)=(SteamID32=84652399,AvatarRef="ScrnTex.Players.Droop",PreNameIconRef="ScrnTex.Players.Batman",PostNameIconRef="ScrnTex.Players.Batman") HighlyDecorated(64)=(SteamID32=85142081,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(65)=(SteamID32=87647886,ClanIconRef="ScrnTex.Players.Dosh") HighlyDecorated(66)=(SteamID32=89323130,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(67)=(SteamID32=93919492,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(68)=(SteamID32=95752287,AvatarRef="ScrnTex.Players.FosterKF2",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey",PostNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey",PrefixIconColor=(A=1)) HighlyDecorated(69)=(SteamID32=99293732,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(70)=(SteamID32=102203653,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_chicken") HighlyDecorated(71)=(SteamID32=102496714,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(72)=(SteamID32=106835439,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(73)=(SteamID32=107039826,AvatarRef="ScrnTex.Players.Seely",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(74)=(SteamID32=109654784,AvatarRef="ScrnTex.Players.BertieDastard",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Support_Grey") HighlyDecorated(75)=(SteamID32=110496233,AvatarRef="ScrnTex.Players.VP",ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_dragon") HighlyDecorated(76)=(SteamID32=112564543,ClanIconRef="ScrnTex.Players.Dosh",PreNameIconRef="ScrnTex.Perks.Hud_Perk_Star_Gray",PostNameIconRef="ScrnTex.Perks.Hud_Perk_Star_Gray") HighlyDecorated(77)=(SteamID32=113961551,AvatarRef="ScrnTex.Players.Baffi",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Demolition_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(78)=(SteamID32=114826433,AvatarRef="ScrnTex.Players.nmm",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey",ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(79)=(SteamID32=121550025,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(80)=(SteamID32=124874371,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(81)=(SteamID32=127624729,AvatarRef="ScrnTex.Players.Scrublord") HighlyDecorated(82)=(SteamID32=128107383,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(83)=(SteamID32=128199891,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(84)=(SteamID32=134825301,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(85)=(SteamID32=136078273,ClanIconRef="ScrnTex.Players.SALTY",PreNameIconRef="KillingFloor2HUD.PerkReset.PReset_Firebug_Grey") HighlyDecorated(86)=(SteamID32=139723798,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(87)=(SteamID32=143999622,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(88)=(SteamID32=150832205,AvatarRef="ScrnTex.Players.Taloril") HighlyDecorated(89)=(SteamID32=152138369,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(90)=(SteamID32=152983683,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(91)=(SteamID32=153788974,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(92)=(SteamID32=160715546,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(93)=(SteamID32=162712343,ClanIcon=Texture'ScrnTex.Tourney.TourneyMember',Playoffs=1) HighlyDecorated(94)=(SteamID32=173722095,AvatarRef="ScrnTex.Players.catcat",PreNameIconRef="ScrnTex.Players.RadioActive",PostNameIconRef="ScrnTex.Players.RadioActive") HighlyDecorated(95)=(SteamID32=182247922,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_kom") HighlyDecorated(96)=(SteamID32=190669364,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_doll") HighlyDecorated(97)=(SteamID32=192070782,ClanIconRef="ScrnTex.Tourney.TBN",Playoffs=1,TourneyWon=1) HighlyDecorated(98)=(SteamID32=319278244,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_doll") HighlyDecorated(99)=(SteamID32=359866000,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_kom") HighlyDecorated(100)=(SteamID32=374934166,AvatarRef="ScrnTex.Players.Bligiet",PreNameIconRef="ScrnTex.Players.BowieKnifeLeft",PostNameIconRef="ScrnTex.Players.BowieKnifeRight") HighlyDecorated(101)=(SteamID32=378534555,AvatarRef="ScrnTex.Players.BossRoss",PreNameIconRef="ScrnTex.Players.BossRossNameIcon",PostNameIconRef="ScrnTex.Players.BossRossNameIcon") HighlyDecorated(102)=(SteamID32=389474897,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_homer") HighlyDecorated(103)=(SteamID32=391528064,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_doll") HighlyDecorated(104)=(SteamID32=397272710,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_doll") HighlyDecorated(105)=(SteamID32=403136595,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="ScrnTex.Players.Medal_f") HighlyDecorated(106)=(SteamID32=405312393,ClanIconRef="ScrnTex.Players.VP",PreNameIconRef="ScrnTex.Players.Medal_VP",PostNameIconRef="KillingFloor2HUD.PerkReset.PReset_Sharpshooter_Grey") bUseDLCLevelLocks=True bFixMusic=True LockTeamMinWave=7.000000 LockTeamAutoWave=8.500000 bForceSteamNames=True MutateCommands(0)="ACCURACY" MutateCommands(1)="CHECK" MutateCommands(2)="CMDLINE" MutateCommands(3)="DEBUGGAME" MutateCommands(4)="DEBUGPICKUPS" MutateCommands(5)="DEBUGSPI" MutateCommands(6)="ENEMIES" MutateCommands(7)="GIMMECOOKIES" MutateCommands(8)="HELP" MutateCommands(9)="HL" MutateCommands(10)="LEVEL" MutateCommands(11)="MAPDIFF" MutateCommands(12)="MAPZEDS" MutateCommands(13)="MUTLIST" MutateCommands(14)="PERKSTATS" MutateCommands(15)="PLAYERLIST" MutateCommands(16)="STATUS" MutateCommands(17)="VERSION" MutateCommands(18)="ZED" MutateCommands(19)="ZEDLIST" bScrnWaves=True bAddToServerPackages=True GroupName="KF-Scrn" FriendlyName="The ScrN Balance Server" Description="This Mutator must be used only on servers. Clients should use workshop version" bAlwaysRelevant=True bOnlyDirtyReplication=False RemoteRole=ROLE_SimulatedProxy bNetNotify=True }