/* CODE BREAKING WARNING in v5.16 Beta 12 Removed AchInfo objects. Used AchDef.CurrentProgress instead Changed variables and functions: + AchStrInfo ! PendingAchievements - CurrentAchievement + CurrentAchHandler, CurrentAchIndex; ! DisplayAchievementStatus(), DisplayCurrentAchievement(), PlayerTick() ScrnAchievementEarnedMsg - requires ScrnAchievement object to be passed as optional object, switch now indicates ach index */ class ScrnPlayerController extends KFPCServ; var ScrnBalance Mut; var transient bool bHadPawn; var byte VeterancyChangeWave; // wave number, when player has changed his perk var globalconfig bool bManualReload, bOtherPlayerLasersBlue; var globalconfig bool bAlwaysDisplayAchProgression; // always display a message on any achievement progress var globalconfig int AchGroupIndex; var globalconfig int Custom3DScopeSens; var globalconfig bool bSpeechVote; //allow using speeches Yes and No in voting struct SWeaponSetting { var globalconfig class Weapon; var globalconfig byte SkinIndex; var transient class SkinnedWeapon; //used on server-side only var transient KFWeapon LastWeapon; // last weapon on which skin was used }; var globalconfig array WeaponSettings; var transient arrayPendingAchievements; //earned achievements waiting to be displayed on the HUD //current achievement object and index to display on the HUD var transient ScrnAchievements CurrentAchHandler; var transient int CurrentAchIndex; var float AchievementDisplayCooldown; // time to wait between displaying achievements, if multiple achievements were earned var transient class InitialPerkClass; var bool bChangedPerkDuringGame; // player changed his perk during a game var transient bool bCowboyForWave; var transient byte BeggingForMoney; // how many times player asked for money during this wave var transient bool bShoppedThisWave; var byte PathDestination; // 0 - trader, 255 - TSC base var byte MaxVoiceMsgIn10s; // maximum number of voice messages during 10 seconds var bool bZEDTimeActive; var bool bHadArmor; //player had armor during the game var bool bWeaponsLocked; // disables player's weapons pick up by other players var localized string strLocked, strUnlocked, strLockDisabled; var transient float LastLockMsgTime; // last time when player received a message that weapon is locked var localized string strAlreadySpectating; var globalconfig bool bPrioritizePerkedWeapons, bPrioritizeBoomstick; var int StartCash; // amount of cash given to this pawn on game/wave start struct SDualWieldable { var class Single, Dual; }; var array DualWieldables; var private transient bool bDualWieldablesLoaded; // TSC var string ProfilePageClassString; var string TSCLobbyMenuClassString; var config bool bTSCAdvancedKeyBindings; // pressing altfire while carrying the guardian gnome, sets up the base var config bool bTSCAutoDetectKeys; // turns off bTSCAdvancedKeyBindings if a dedicated key is bound for SetupBase var config string RedCharacter, BlueCharacter; // not replicated yet // todo: find an efficient way to replicate var array RedCharacters, BlueCharacters; var class CustomPlayerReplicationInfoClass; var ScrnCustomPRI ScrnCustomPRI; var transient bool bDestroying; // indicates that Destroyed() is executing var bool bDamageAck; // does server needs to acknowledge client of damages he made? var transient byte PerkChangeWave; // wave num, when perk was changed last time var localized string strNoPerkChanges, strPerkLocked; var transient Controller FavoriteSpecs[2]; var localized string strSpecFavoriteAssigned, strSpecNoFavorites; var transient Actor OldViewTarget; var transient rotator PrevRot; var transient int ab_warning; var globalconfig bool bDebugRepLink, bWaveGarbageCollection; var globalconfig string PlayerName; // DLC checks struct SDLC { var int AppID; var bool bOwnsDLC; var bool bChecked; }; var array DLC; var transient int AchResetPassword; struct SMusicRecord { var byte PL, Wave; var bool bTrader; var string Song; var string Artist, Title; }; var globalconfig byte ActiveMusicPlaylist; var globalconfig array MusicPlaylistNames; var globalconfig array MyMusic; var private transient array MusicPlaylistIndex; // MusicPlaylistIndex[PL] = index of first playlist entry in MyMusic var private transient bool bMusicPlaylistIndexReady; var private transient int ActiveMusicSongIndex; var private transient string PendingSong; var localized string strPlayingSong; var class FlareCloudClass; replication { reliable if ( Role == ROLE_Authority ) ClientMonsterBlamed, ClientPostLogin; unreliable if ( bDamageAck && Role == ROLE_Authority ) ClientPlayerDamaged; unreliable if ( Role == ROLE_Authority ) ClientFlareDamage; reliable if ( Role < ROLE_Authority ) SrvAchReset, ResetMyAchievements, ResetMapAch, ServerDropAllWeapons, ServerLockWeapons, ServerGunSkin, ServerAcknowledgeDamages, ServerShowPathTo, ServerDebugRepLink, ServerFixQuickMelee, ServerTourneyCheck, ServerKillMut, ServerKillRules, ServerSwitchViewMode, ServerSetViewTarget; reliable if ( bNetOwner && (bNetDirty || bNetInitial) && Role < ROLE_Authority ) bPrioritizePerkedWeapons, StartCash; // TSC stuff reliable if ( Role < ROLE_Authority ) ServerScoreFlag; } simulated function PreBeginPlay() { super.PreBeginPlay(); class'ScrnMagnum44Fire'.static.PreloadAssets(Level); class'ScrnDual44MagnumFire'.static.PreloadAssets(Level); class'ScrnMAC10Fire'.static.PreloadAssets(Level); class'KFMod.M79Fire'.static.PreloadAssets(Level); } // this function is called on on server side only // and only if using ScrnGameType, ScrnStoryGameInfo or descendants function PostLogin() { ClientPostLogin(); ScrnCustomPRI.GotoState(''); if ( Level.NetMode == NM_Standalone || (Level.NetMode == NM_ListenServer && Viewport(Player) != None) ) ScrnCustomPRI.SetSteamID64(Mut.MySteamID64); else ScrnCustomPRI.SetSteamID64(GetPlayerIDHash()); ScrnCustomPRI.NetUpdateTime = Level.TimeSeconds - 1; if ( PlayerName != "" ) SetName(PlayerName); Mut.GameRules.PlayerEntering(self); } simulated function ClientPostLogin() { // DLC check moved to ScrnClientPerkRepLink // if ( Viewport(Player) != None ) { // CheckDLC(); // } } simulated function LoadMutSettings() { if ( Mut != none ) { if ( Mut.bForceManualReload) bManualReload = Mut.bManualReload; if ( Mut.bHardCore ) bOtherPlayerLasersBlue = false; if ( ScrnHumanPawn(Pawn) != none ) ScrnHumanPawn(Pawn).bTraderSpeedBoost = Mut.bTraderSpeedBoost; } else { //this shouldn't happen log("Player Controller can not find ScrnBalance!", 'ScrnBalance'); if ( class'ScrnBalance'.default.Mut.bForceManualReload) bManualReload = class'ScrnBalance'.default.bManualReload; if ( class'ScrnBalance'.default.Mut.bHardcore ) bOtherPlayerLasersBlue = false; } } function InitPlayerReplicationInfo() { local LinkedReplicationInfo L; super.InitPlayerReplicationInfo(); for( L=PlayerReplicationInfo.CustomReplicationInfo; L!=None; L=L.NextReplicationInfo ) { if ( ScrnCustomPRI(L) != none ) return; // wtf? if( L.NextReplicationInfo==None ) break; } ScrnCustomPRI = spawn(CustomPlayerReplicationInfoClass, self); if ( ScrnCustomPRI != none ) { if ( PlayerReplicationInfo.CustomReplicationInfo != none ) ScrnCustomPRI.NextReplicationInfo = PlayerReplicationInfo.CustomReplicationInfo; PlayerReplicationInfo.CustomReplicationInfo = ScrnCustomPRI; } else warn("Can not create ScrnCustomPRI: " $ CustomPlayerReplicationInfoClass); } //copypaste from KFPlayerController with constant value of 24 replaced by Custom3DScopeSens to set custom sensitivity for 3D scopes function float GetMouseModifier() { local KFWeapon weap; if (Pawn == none || Pawn.Weapon == none) return -1.0; weap = KFWeapon(Pawn.Weapon); if (weap== none ) return -1.0; if(weap.KFScopeDetail == KF_ModelScope && weap.ShouldDrawPortal()) { return Custom3DScopeSens; } else if(weap.KFScopeDetail == KF_ModelScopeHigh && weap.ShouldDrawPortal()) { return Custom3DScopeSens; } else { return -1.0; } } simulated function ClientForceCollectGarbage() { ConsoleCommand("MEMSTAT", true); // write memory stats into log if ( bWaveGarbageCollection ) { super.ClientForceCollectGarbage(); ConsoleCommand("MEMSTAT", true); } } simulated function PreloadFireModeAssetsSE(class WF, optional WeaponFire SpawnedFire) { local class P;//log("ScrnPlayerController.PreloadFireModeAssets()" @ WF, 'ScrnBalance'); if ( WF == none || WF == Class'KFMod.NoFire' ) return; if ( class(WF) != none && class(WF).default.FireSoundRef != "" ) class(WF).static.PreloadAssets(Level, KFFire(SpawnedFire)); else if ( class(WF) != none && class(WF).default.FireSoundRef != "" ) class(WF).static.PreloadAssets(KFMeleeFire(SpawnedFire)); else if ( class(WF) != none && class(WF).default.FireSoundRef != "" ) class(WF).static.PreloadAssets(Level, KFShotgunFire(SpawnedFire)); // preload projectile assets P = WF.default.ProjectileClass; //log("Projectile =" @ P, 'ScrnBalance'); if ( P == none ) return; if ( class(P) != none ) class(P).static.PreloadAssets(); else if ( class(P) != none ) class(P).static.PreloadAssets(); else if ( class(P) != none && class(P).default.StaticMeshRef != "" ) class(P).static.PreloadAssets(); else if ( class(P) != none && class(P).default.StaticMeshRef != "" ) class(P).static.PreloadAssets(); else if ( class(P) != none && class(P).default.StaticMeshRef != "" ) class(P).static.PreloadAssets(); else if ( class(P) != none && class(P).default.StaticMeshRef != "" ) class(P).static.PreloadAssets(); else if ( class(P) != none && class(P).default.MeshRef != "" ) class(P).static.PreloadAssets(); else if ( class(P) != none ) class(P).static.PreloadAssets(); else if ( class(P) != none && class(P).default.StaticMeshRef != "" ) class(P).static.PreloadAssets(); // More DLC else if ( class(P) != none && class(P).default.StaticMeshRef != "" ) class(P).static.PreloadAssets(); } simulated function ClientWeaponSpawned(class WClass, Inventory Inv) { local class W; local class Att; local Weapon Spawned; //log("ScrnPlayerController.ClientWeaponSpawned()" @ WClass $ ". Default Mesh = " $ WClass.default.Mesh, 'ScrnBalance'); //super.ClientWeaponSpawned(WClass, Inv); W = class(WClass); // preload assets only for weapons that have no static ones // damned Tripwire's code doesn't bother for cheking is there ref set or not! if ( W != none) { //preload weapon assets if ( W.default.Mesh == none ) W.static.PreloadAssets(Inv); Att = class(W.default.AttachmentClass); // 2013/01/22 EDIT: bug fix if ( Att != none && Att.default.Mesh == none ) { if ( Inv != none ) Att.static.PreloadAssets(KFWeaponAttachment(Inv.ThirdPersonActor)); else Att.static.PreloadAssets(); } // 2014-11-23 fix Spawned = Weapon(Inv); if ( Spawned != none ) { PreloadFireModeAssetsSE(W.default.FireModeClass[0], Spawned.GetFireMode(0)); PreloadFireModeAssetsSE(W.default.FireModeClass[1], Spawned.GetFireMode(0)); } else { PreloadFireModeAssetsSE(W.default.FireModeClass[0]); PreloadFireModeAssetsSE(W.default.FireModeClass[1]); } } } /* function AcknowledgePossession(Pawn P) { // make sure old pawn controller is right if ( Pawn != AcknowledgedPawn ) { if( ScrnHumanPawn(AcknowledgedPawn) != none ) ScrnHumanPawn(AcknowledgedPawn).ScrnPlayer = none; } if( ScrnHumanPawn(P) != none ) { ScrnHumanPawn(P).ScrnPlayer = self; } super.AcknowledgePossession(P); } function ServerAcknowledgePossession(Pawn P, float NewHand, bool bNewAutoTaunt) { // make sure old pawn controller is right if ( Pawn != AcknowledgedPawn ) { if( ScrnHumanPawn(AcknowledgedPawn) != none ) ScrnHumanPawn(AcknowledgedPawn).ScrnPlayer = none; } if( ScrnHumanPawn(P) != none ) { ScrnHumanPawn(P).ScrnPlayer = self; } super.ServerAcknowledgePossession(P, NewHand, bNewAutoTaunt); } */ function PawnDied(Pawn P) { ServerDropFlag(); super.PawnDied(P); } function ShowBuyMenu(string wlTag,float maxweight) { StopForceFeedback(); ClientOpenMenu(string(Class'ScrnGUIBuyMenu'),,wlTag,string(maxweight)); } exec function CookGrenade() { if ( ScrnHumanPawn(Pawn) != none ) ScrnHumanPawn(Pawn).CookGrenade(); } exec function ThrowCookedGrenade() { if ( ScrnHumanPawn(Pawn) != none ) ScrnHumanPawn(Pawn).ThrowCookedGrenade(); } exec function QuickMelee() { if ( ScrnHumanPawn(Pawn) != none ) ScrnHumanPawn(Pawn).QuickMelee(); } /** * DamTypeNum: * 0 - normal * 1 - headshot * 2 - fire DoT */ function DamageMade(int Damage, vector HitLocation, byte DamTypeNum) { local ScrnPlayerController ScrnPC; local int i; ClientPlayerDamaged(Damage, HitLocation, DamTypeNum); if ( Role == ROLE_Authority && ScrnHumanPawn(Pawn) != none && ScrnHumanPawn(Pawn).bViewTarget ) { // show damage popups on spectating players for ( i=0; i BlamedMonsterClass) { local ScrnHUD hud; hud = ScrnHUD(myHUD); if ( hud != none ) { hud.BlameCountdown = hud.default.BlameCountdown; hud.BlamedMonsterClass = BlamedMonsterClass; } } exec function ScrnInit() { local LinkedReplicationInfo L; // reload ScrnBalance settings Mut.InitSettings(); // reload custom weapon bonuses for ( L = Mut.CustomWeaponLink; L != none; L = L.NextReplicationInfo ) { ScrnCustomWeaponLink(L).LoadWeaponBonuses(); } } simulated function PlayerTick( float DeltaTime ) { local float y, p; super.PlayerTick(DeltaTime); //log("Player Controller Tick", 'ScrnBalance'); if ( Viewport(Player) != None ) { AchievementDisplayCooldown -= DeltaTime; if ( PendingAchievements.Length > 0 && AchievementDisplayCooldown <= 0 ) { CurrentAchHandler = PendingAchievements[0].AchHandler; CurrentAchIndex = PendingAchievements[0].AchIndex; PendingAchievements.remove(0, 1); DisplayCurrentAchievement(); } if ( Pawn != none && Pawn.Health > 0 ) { if ( PrevRot.Yaw != 0 ) { y = abs(Rotation.Yaw - PrevRot.Yaw); p = abs(Rotation.Yaw - PrevRot.Yaw); if ( y<10000 && p<10000 && p+y>2500 /*&& (p*p + y*y) > 4000000*/ ) { if ( IsAimingToZedHead() ) ab_warning+=10; // you made inssanely quick mouse movement and pointed exactly into enemy head. What are you, aimbot?.. else ab_warning--; // nah, seems like you need to reduce mouse sensitivity... } } PrevRot = Rotation; } // set typing to true also when console is open if ( Player.Console != none ) { bIsTyping = Player.Console.bVisible || Player.Console.bTyping || Player.GUIController.bActive; if ( Pawn != none && bIsTyping != Pawn.bIsTyping ) Typing(bIsTyping); // replicate state to server } if ( KFInterAct != none && PendingSong != "" && PendingSong == KFInterAct.ActiveSong ) { // don't bother with this, if player has turned off music if ( GetMusicVolume() > 0 ) { if ( KFInterAct.ActiveHandel == 0) { // unable to start song - play default one ClientMessage("Unable to play music file: '"$PendingSong$".ogg'. Playing default song instead.", 'Log'); PlayDefaultMusic(class'ScrnMusicTrigger'); } else SongPlaying(PendingSong, ActiveMusicSongIndex); } PendingSong = ""; } } } // TraderMenuOpened and TraderMenuClosed execute on client-side only simulated function TraderMenuOpened() { bShopping = true; } simulated function TraderMenuClosed() { if ( Mut.bTSCGame ) ServerShowPathTo(1); // go to TSC base bShopping = false; } function SetShowPathToTrader(bool bShouldShowPath) { if ( bShouldShowPath ) PathDestination = 0; // trader else if ( PathDestination == 0) PathDestination = 255; // turn off only if we are showing path to trader (PathDestination = 0) ServerShowPathTo(PathDestination); } exec function TogglePathToTrader() { switch (PathDestination) { case 0: PathDestination = 1; // TSC base if ( Mut.bTSCGame ) break; // otherwise go to next steap case 1: PathDestination = 255; // hide break; default: PathDestination = 0; // trader } ServerShowPathTo(PathDestination); } function ServerShowPathTo(byte NewDestination) { PathDestination = NewDestination; SetTimer(TraderPathInterval, true); Timer(); } // Show the path the trader function Timer() { if( Role < ROLE_Authority ) { SetTimer(0, false); } else if ( bWantsTraderPath && PathDestination != 255 ) { UnrealMPGameInfo(Level.Game).ShowPathTo(Self, PathDestination); } else { bShowTraderPath = false; SetTimer(0, false); } } event SongPlaying(String Song, int MyIndex) { if ( Song == "" ) return; if ( MyIndex >=0 && MyIndex < MyMusic.length && MyMusic[MyIndex].Song == Song ) { if ( MyMusic[MyIndex].Title == "" ) MyMusic[MyIndex].Title = MyMusic[MyIndex].Song; ClientMessage(strPlayingSong $ ConsoleColorString(MyMusic[MyIndex].Artist, 192, 1, 192) @ ConsoleColorString(MyMusic[MyIndex].Title, 255, 255, 1) ); } else { for ( MyIndex = 0; MyIndex < MyMusic.length; ++MyIndex ) { if ( MyMusic[MyIndex].Song == Song ) SongPlaying(Song, MyIndex); } } } function UpdateMusicPlaylistIndex() { local int i, prev_pl; bMusicPlaylistIndexReady = true; for ( i=0; i= MyMusic.Length ) { ClientMessage("Music Playlist #"$PL $" has no songs or MyMusic is not sorted", 'Log'); return -1; } if ( (PL+1) == MusicPlaylistIndex.Length ) end = MyMusic.length; else end = MusicPlaylistIndex[PL+1]; for ( i = start; i < end; ++i ) { if ( bFound ) { if ( MyMusic[i].Wave != Wave || MyMusic[i].bTrader != bTrader ) { end = i; break; } } else if ( MyMusic[i].Wave == Wave && MyMusic[i].bTrader == bTrader ) { bFound = true; start = i; } } if ( bFound ) { if ( start + 1 == end ) return start; else return start + Rand(end-start); } else if ( Wave > 0) return GetMySongIndex(PL, 0, bTrader); // no songs defined for given wave. return default return -1; } function int GetMyActiveSongIndex() { local KFGameReplicationInfo KFGRI; local byte w; KFGRI = KFGameReplicationInfo(Level.GRI); if ( KFGRI == none ) return -1; // wtf? if ( KF_StoryGRI(KFGRI) != none ) { // story mode return -1; // story music must be set explicitly by L.D. } w = KFGRI.WaveNumber; if ( KFGRI.bWaveInProgress ) { if ( w == KFGRI.FinalWave && TSCGameReplicationInfo(KFGRI) == none ) w = 10; // boss battle song } return GetMySongIndex(ActiveMusicPlaylist, w+1, !KFGRI.bWaveInProgress); } function PlayDefaultMusic(class M) { local string sng; if ( KFInterAct == none ) return; sng = GetSongFromMusicTrigger(M); if ( sng != "" ) KFInterAct.SetSong(sng, M.default.FadeInTime, M.default.FadeOutTime); } function string GetSongFromMusicTrigger(class M) { local KFGameReplicationInfo KFGRI; local string sng; local int w; KFGRI = KFGameReplicationInfo(Level.GRI); if ( KFGRI == none ) return sng; // wtf? if ( KF_StoryGRI(KFGRI) != none ) return sng; // story music must be set explicitly by L.D. w = KFGRI.WaveNumber; if ( KFGRI.bWaveInProgress ) { if ( w == KFGRI.FinalWave && M.default.WaveBasedSongs.length > 10 && TSCGameReplicationInfo(KFGRI) == none ) sng = M.default.WaveBasedSongs[10].CombatSong; // boss battle song else if ( w < M.default.WaveBasedSongs.length ) sng = M.default.WaveBasedSongs[w].CombatSong; else sng = M.default.CombatSong; } else { if ( KFGRI.TimeToNextWave > 10 ) w++; // KFGRI.WaveNumber is updated only at the end of the trader time if ( w < M.default.WaveBasedSongs.length ) sng = M.default.WaveBasedSongs[w].CalmSong; else sng = M.default.Song; } return sng; } function int GetActiveMusicSongIndex() { return ActiveMusicSongIndex; } function NetPlayMusic( string Song, float FadeInTime, float FadeOutTime ) { if ( ActiveMusicPlaylist > 0 ) { ActiveMusicSongIndex = GetMyActiveSongIndex(); if ( ActiveMusicSongIndex != -1 ) Song = MyMusic[ActiveMusicSongIndex].Song; } else ActiveMusicSongIndex = -1; PendingSong = Song; super.NetPlayMusic(Song, FadeInTime, FadeOutTime); } exec function PlayMyMusic(int PL) { local int i; if ( !bMusicPlaylistIndexReady ) UpdateMusicPlaylistIndex(); if ( MusicPlaylistIndex.length <= 1 ) { ConsoleMessage("No user-defined music available", 0, 255, 1, 1); return; } if ( PL >= MusicPlaylistIndex.length ) { ConsoleMessage("Wrong playlist number!", 0, 255, 1, 1); PL = 0; } if ( PL == 0) { ConsoleMessage("Available music playlists:"); ConsoleMessage("---------------------------------------------"); for ( i=1; i 0 ) { ActiveMusicPlaylist = 0; ClientMessage("User-defined music disabled. Map-specific music will be restored next wave."); SaveConfig(); } } function float GetMusicVolume() { return float(ConsoleCommand("get ini:Engine.Engine.AudioDevice MusicVolume")); } exec function MusicVolume(coerce string vol) { if ( vol == "" ) ClientMessage("Music Volume = " $ ConsoleCommand("get ini:Engine.Engine.AudioDevice MusicVolume")); else { ConsoleCommand("set ini:Engine.Engine.AudioDevice MusicVolume" @ vol); ClientMessage("Music Volume set to " $ ConsoleCommand("get ini:Engine.Engine.AudioDevice MusicVolume")); } } exec function SoundVolume(coerce string vol) { if ( vol == "" ) ClientMessage("Sound Volume = " $ ConsoleCommand("get ini:Engine.Engine.AudioDevice SoundVolume")); else { ConsoleCommand("set ini:Engine.Engine.AudioDevice SoundVolume" @ vol); ClientMessage("Sound Volume set to " $ ConsoleCommand("get ini:Engine.Engine.AudioDevice SoundVolume")); } } function bool IsAimingToZedHead() { local Vector vNull, StartTrace, HeadLoc, LookDir, HeadDir; local KFMonster HitMonster; local float cosine; if ( Pawn == none ) return false; StartTrace = Pawn.Location + Pawn.EyePosition(); // A LookDir = Normal(Vector(Rotation)); // B-A foreach CollidingActors(class'KFMonster', HitMonster, 2500, StartTrace) { HeadLoc = HitMonster.GetBoneCoords('head').Origin; if ( HeadLoc == vNull ) continue; // no head if ( !FastTrace(HeadLoc, StartTrace) ) continue; // head isn't visible // I should have better learned geometry in school. It'd really helped :) // LookDir - direction where player is lookin // HeadDir - direction to the zed's head (HeadLoc) // We need to get a distance between HeadLoc and our LookDir line, // i.e. perpenducular line from HeadLoc to LookDir line. // We get right-angled triangle, where (HeadLoc-StartTrace) is Hypotenuse, // LookDir line - Adjacent side and perpendicular line - opposite side. // Opposite = Hypotenuse * sin, where sin = 1 - cos, // and cos = dot product of two normalized direction vectors. HeadDir = normal(HeadLoc - StartTrace); // cos=1.0 - target in front of us // cos=0.0 - target is at side (left or right) // cos=0.5 - target is 45 degrees from our looking direction cosine = LookDir dot HeadDir; if ( cosine > 0.9 && VSizeSquared(HeadLoc - StartTrace) * (1.0-cosine) < 25 ) return true; } return false; } simulated function DisplayCurrentAchievement() { if ( Viewport(Player) == None ) return; //log("DisplayCurrentAchievement:" @CurrentAchievement.ID @ CurrentAchievement.CurrentProgress$"/"$ CurrentAchievement.MaxProgress ,'ScrnBalance'); if ( CurrentAchHandler != none ) { if ( CurrentAchHandler.AchDefs[CurrentAchIndex].bUnlockedJustNow ) { //set cooldown only for earned achievements. Status updates can be immediately overrided AchievementDisplayCooldown = default.AchievementDisplayCooldown; ClientPlaySound(Sound'KF_InterfaceSnd.Perks.PerkAchieved',true,2.f,SLOT_Talk); ClientPlaySound(Sound'KF_InterfaceSnd.Perks.PerkAchieved',true,2.f,SLOT_Interface); } else { AchievementDisplayCooldown = fmax(0, AchievementDisplayCooldown); } CurrentAchHandler.AchDefs[CurrentAchIndex].bUnlockedJustNow = false; ReceiveLocalizedMessage(Class'ScrnAchievementEarnedMsg',CurrentAchIndex,self.PlayerReplicationInfo,,CurrentAchHandler); } } //inform client that he earned an achievement simulated function DisplayAchievementStatus(ScrnAchievements AchHandler, int AchIndex) { if ( Viewport(Player) == None || AchHandler == none || !AchHandler.IsAchievementIndexValid(AchIndex) ) return; if ( AchHandler.AchDefs[AchIndex].CurrentProgress > 0 ) { if ( AchHandler.AchDefs[AchIndex].bUnlockedJustNow ) ConsoleMessage(Class'ScrnAchievementEarnedMsg'.default.EarnedString $ ": " $ AchHandler.AchDefs[AchIndex].DisplayName, 0, 1, 200, 1); if ( PendingAchievements.Length == 0 && AchievementDisplayCooldown <= 0 ) { // no need to use a queue for a single achievement CurrentAchHandler = AchHandler; CurrentAchIndex = AchIndex; DisplayCurrentAchievement(); } else if ( AchHandler.AchDefs[AchIndex].bUnlockedJustNow ){ //don't bother player with status updates, when other achievements have been really earned PendingAchievements.insert(PendingAchievements.Length, 1); PendingAchievements[PendingAchievements.Length-1].AchHandler = AchHandler; PendingAchievements[PendingAchievements.Length-1].AchIndex = AchIndex; } } } static final function string ConsoleColorString(string s, byte R, byte G, byte B) { return chr(27)$chr(max(R,1))$chr(max(G,1))$chr(max(B,1))$s; } simulated function ConsoleMessage(string Msg, optional float MsgLife, optional byte R, optional byte G, optional byte B) { if ( Player != none && Player.Console != none ) { if ( R != 0 || G != 0 || B != 0 ) Msg = ConsoleColorString(Msg, R, G, B); Player.Console.Message(Msg, MsgLife); } } simulated function string MyColoredName() { return Mut.ColoredPlayerName(PlayerReplicationInfo); } event ClientMessage( coerce string S, optional Name Type ) { if ( Level.NetMode == NM_DedicatedServer || GameReplicationInfo == None ) return; if ( Type == 'Log' ) { log(S, 'ScrnBalance'); Type = ''; } if ( Mut != none ) super.ClientMessage(Mut.ParseColorTags(S, PlayerReplicationInfo), Type); else super.ClientMessage(S, Type); } function LongMessage(string S, optional int MaxLen, optional string Divider) { class'ScrnBalance'.static.LongMessage(self, S, MaxLen, Divider); } event TeamMessage( PlayerReplicationInfo PRI, coerce string S, name Type ) { local string c; // Wait for player to be up to date with replication when joining a server, before stacking up messages if ( Level.NetMode == NM_DedicatedServer || GameReplicationInfo == None ) return; if( AllowTextToSpeech(PRI, Type) ) TextToSpeech( S, TextToSpeechVoiceVolume ); if ( Type == 'TeamSayQuiet' ) Type = 'TeamSay'; if ( myHUD != None ) myHUD.Message( PRI, c$S, Type ); if ( (Player != None) && (Player.Console != None) ) { if ( PRI!=None ) { if ( PRI.Team!=None && GameReplicationInfo.bTeamGame) { if (PRI.Team.TeamIndex==0) c = chr(27)$chr(200)$chr(1)$chr(1); else if (PRI.Team.TeamIndex==1) c = chr(27)$chr(75)$chr(139)$chr(198); } S = Mut.ColoredPlayerName(PRI)$c$": "$ Mut.ParseColorTags(S, PRI); } Player.Console.Chat( c$s, 6.0, PRI ); } } simulated function ReceiveLocalizedMessage( class Message, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject ) { if ( Message == class'KFVetEarnedMessageSR' || Message == class'ScrnPromotedMessage' || (Message == class'KFVetEarnedMessagePL' && RelatedPRI_1 == PlayerReplicationInfo) ) { Message = class'ScrnPromotedMessage'; } else if ( Message == class'TSCMessages' ) { switch (Switch) { case 300: // trying to shop in enemy trader ClientCloseMenu(true, true); break; case 311: // loosing base means wipe if ( ScrnHUD(myHUD) != none ) ScrnHUD(myHUD).CriticalOverlayTimer = Level.TimeSeconds + 3.0; break; } } super.ReceiveLocalizedMessage(Message, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject); } function ResetWaveStats() { local KFPlayerReplicationInfo KFPRI; KFPRI = KFPlayerReplicationInfo(PlayerReplicationInfo); bCowboyForWave = true; BeggingForMoney = 0; bShoppedThisWave = false; bHadArmor = bHadArmor || (KFPRI != none && KFPRI.ClientVeteranSkill != none && KFPRI.ClientVeteranSkill.static.ReduceDamage(KFPRI, KFPawn(Pawn), none, 100, none) < 100); if ( ScrnHumanPawn(Pawn) != none ) ScrnHumanPawn(Pawn).ApplyWeaponStats(Pawn.Weapon); } exec function LogAch() { local ClientPerkRepLink L; local SRCustomProgress S; local ScrnAchievements A; local int i, c; L = class'ScrnClientPerkRepLink'.static.FindMe(self); log("#;GROUP;ID;TITLE;DESCRIPTION", 'Achievement'); log("============================", 'Achievement'); for( S = L.CustomLink; S != none; S = S.NextLink ) { A = ScrnAchievements(S); if( A != none ) { //log(A.class, 'Package'); for ( i = 0; i < A.AchDefs.length; ++i ) { log(string(++c) $";"$ A.AchDefs[i].Group $";"$ A.AchDefs[i].ID $";"$ A.AchDefs[i].DisplayName $";"$ A.AchDefs[i].Description , 'Achievement'); } } } ConsoleMessage("Achievement list has been printed to the log file.", 0, 1, 200, 1); } exec function AchReset(optional int password) { if ( class'ScrnAchievements'.static.IsAchievementUnlocked(class'ScrnClientPerkRepLink'.static.FindMe(self), 'AchReset') ) { if ( AchResetPassword == 0 ) { AchResetPassword = 10000 + rand(90000); ConsoleMessage("You already have 'AchReset' achievement!", 0, 200, 100, 1); ConsoleMessage("If sure you want to do this again, then enter the following command:", 0, 200, 100, 1); ConsoleMessage("AchReset " $ AchResetPassword, 0, 200, 200, 1); return; } else if ( AchResetPassword != password ) { ConsoleMessage("Wrong reset password!", 0, 200, 100, 1); return; } } SrvAchReset(); } function SrvAchReset() { local ClientPerkRepLink L; local array GroupNames; local array GroupCaptions; local int i; L = Class'ScrnClientPerkRepLink'.Static.FindMe(self); class'ScrnAchievements'.static.RetrieveGroups(L, GroupNames, GroupCaptions); for ( i=0; i WP; local class W; local int i; L = class'ScrnClientPerkRepLink'.static.FindMe(self); if( L==None || L.ShopInventory.Length == 0 ) return; // Hmmmm? for ( i=0; i(L.ShopInventory[i].PC); if ( WP == none ) continue; W = class(WP.default.InventoryType); if ( W != none && W.Default.DemoReplacement != none ) AddDualWieldable(class(W.Default.DemoReplacement), W); } bDualWieldablesLoaded = L.PendingWeapons == 0; } final function AddDualWieldable(class SingleWeapon, class DualWeapon) { local int i; if ( SingleWeapon == none || DualWeapon == none ) return; for ( i=0; i Weapon) { local int i; if ( !bDualWieldablesLoaded ) LoadDualWieldables(); if ( Weapon == none ) return false; for ( i=0; i Weapon) { local int i; if ( !bDualWieldablesLoaded ) LoadDualWieldables(); if ( Weapon == none ) return false; for ( i=0; i PickupToCheck, bool bCheckForEquivalent, bool bCheckForVariant) { local Inventory CurInv; local class InvPickupClass; local class WeaponPickupToCheck; local int i; if ( PickupToCheck == none ) return false; WeaponPickupToCheck = class(PickupToCheck); for ( CurInv = Pawn.Inventory; CurInv != none; CurInv = CurInv.Inventory ) { if ( /* bCheckForEquivalent && */ CurInv.default.PickupClass == PickupToCheck ) { if ( !bCheckForEquivalent && IsSinglePistol(class(CurInv.class)) ) return false; // allow picking up a second pistol return true; } if( !bCheckForVariant ) continue; // check if Item is variant of normal inventory item InvPickupClass = class(CurInv.default.PickupClass); if( InvPickupClass != none ) { for( i = 0; i < InvPickupClass.default.VariantClasses.Length; ++i ) { if( InvPickupClass.default.VariantClasses[i] == PickupToCheck ) return true; } } // check if Item is normal version of variant inventory item if( WeaponPickupToCheck != none && CurInv.default.PickupClass != none ) { for( i = 0; i < WeaponPickupToCheck.default.VariantClasses.Length; ++i ) { if( WeaponPickupToCheck.default.VariantClasses[i] == CurInv.default.PickupClass ) return true; } } } return false; } exec function SetName(coerce string S) { if ( S == "#" ) S = PlayerName; if ( S == "" || (class'ScrnSrvReplInfo'.static.Instance().bForceSteamNames && Player.GUIController.SteamGetUserName() != Mut.StripColorTags(S)) ) { S = Player.GUIController.SteamGetUserName(); if ( S == "" ) PlayerName = ""; } else { PlayerName = S; } ChangeName(S); UpdateURL("Name", S, true); SaveConfig(); } function ChangeName( coerce string S ) { local string PlainName; ReplaceText(S, " ", "_"); ReplaceText(S, "\"", ""); PlainName = Mut.StripColorTags(S); if ( len(PlainName) > 20 ) S = left(PlainName, 20); Level.Game.ChangeName( self, S, true ); } // TSC stuff exec function SwitchTeam() { if ( PlayerReplicationInfo == none || PlayerReplicationInfo.Team == None || PlayerReplicationInfo.Team.TeamIndex == 1 ) ServerChangeTeam(0); else ServerChangeTeam(1); } exec function ChangeTeam( int N ) { ServerChangeTeam(N); } function ServerChangeTeam( int N ) { super.ServerChangeTeam(N); if ( Mut.bDynamicLevelCap && Mut.KF.bTradingDoorsOpen ) Mut.DynamicLevelCap(); } exec function SetupBase() { ServerScoreFlag(); } function ServerScoreFlag() { local GameObject Flag; Flag = GameObject(PlayerReplicationInfo.HasFlag); if ( Flag != none ) { if ( Flag.bHeld ) Flag.Score(); else Flag.ClearHolder(); // shouldn't happen } } exec function AltFire( optional float F ) { if ( Level.Pauser == PlayerReplicationInfo ) { SetPause(false); return; } if( bDemoOwner || (Pawn == None) ) return; if ( !bTSCAdvancedKeyBindings && PlayerReplicationInfo.HasFlag != none && GameObject(PlayerReplicationInfo.HasFlag) != none && TSCGameReplicationInfo(Level.GRI) != none ) { if ( bTSCAutoDetectKeys ) bTSCAdvancedKeyBindings = ConsoleCommand("BINDINGTOKEY SetupBase") != ""; if ( !bTSCAdvancedKeyBindings ) { SetupBase(); return; } } super.AltFire(F); } exec function ThrowWeapon() { if ( !bTSCAdvancedKeyBindings && GameObject(PlayerReplicationInfo.HasFlag) != none ) { if ( bTSCAutoDetectKeys ) bTSCAdvancedKeyBindings = ConsoleCommand("BINDINGTOKEY DropFlag") != ""; if ( !bTSCAdvancedKeyBindings ) { DropFlag(); return; } } ServerThrowWeapon(); } // character selection simulated function bool IsTeamCharacter(string CharacterName) { if ( CharacterName == "" ) return false; if ( Level.GRI.bNoTeamSkins || TSCGameReplicationInfo(Level.GRI) == none || PlayerReplicationInfo == none || PlayerReplicationInfo.Team == none ) return true; // no team = any character can be used if ( PlayerReplicationInfo.Team.TeamIndex == 0 ) return IsRedCharacter(CharacterName); else if ( PlayerReplicationInfo.Team.TeamIndex == 1 ) return IsBlueCharacter(CharacterName); return false; } simulated function bool IsRedCharacter(string CharacterName) { local int i; if ( CharacterName == "" ) return false; for ( i=0; i OldPerk; if( Level.NetMode!=NM_Client && SRStatsBase(SteamStatsAndAchievements)!=none ) { OldPerk = KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill; SRStatsBase(SteamStatsAndAchievements).WaveEnded(); if ( OldPerk != KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill ) PerkChangeWave = KFGameType(Level.Game).WaveNum; } } function SelectVeterancy(class VetSkill, optional bool bForceChange) { local ClientPerkRepLink L; if( SRStatsBase(SteamStatsAndAchievements)!=none ) L = Class'ScrnClientPerkRepLink'.Static.FindMe(self); if ( L != none ) { if ( ScrnClientPerkRepLink(L) != none ) ScrnClientPerkRepLink(L).ServerSelectPerkSE(Class(VetSkill)); else L.ServerSelectPerk(Class(VetSkill)); } } exec final function TourneyCheck() { ServerTourneyCheck(); } final function ServerTourneyCheck() { local ScrnGameType GT; local Mutator M; local GameRules G; local string s; ClientMessage(string(Level.Game.class)); GT = ScrnGameType(Level.Game); if ( GT == none ) ClientMessage("Current game type doesn't support Tourney Mode"); else { if ( GT.IsTourney() ) ClientMessage("Tourney Mode: " $ GT.GetTourneyMode()); else ClientMessage("Tourney Mode DISABLED"); } s = "Mutators:"; for ( M = Level.Game.BaseMutator; M != None; M = M.NextMutator ) s @= string(M.class); LongMessage(s, 80, " "); s = "Rules:"; for ( G=Level.Game.GameRulesModifiers; G!=None; G=G.NextGameRules ) s @= string(G.class); LongMessage(s, 80, " "); } exec final function AdminKillMut(string MutName) { if ( Level.NetMode == NM_Standalone || (PlayerReplicationInfo != none && PlayerReplicationInfo.bAdmin) ) ServerKillMut(MutName); } final function ServerKillMut(string MutatorName) { local Mutator M; local ScrnBalance SBM; if ( Level.NetMode != NM_Standalone && (PlayerReplicationInfo == none || !PlayerReplicationInfo.bAdmin) ) return; if ( MutatorName ~= "KillingFloorMut" || MutatorName ~= "ScrnBalance" || MutatorName ~= "ServerPerksMut" ) return; SBM = class'ScrnBalance'.static.Myself(Level); if ( SBM == none || GetItemName(string(SBM.class)) ~= MutatorName || GetItemName(string(SBM.FindServerPerksMut().class)) ~= MutatorName ) return; // can't kill ScrnBalance or ServerPerks for ( M = Level.Game.BaseMutator; M != None; M = M.NextMutator ) { if ( GetItemName(string(M.class)) ~= MutatorName ) { ClientMessage("Mutator '"$string(M.Class)$"' destroyed"); M.Destroy(); return; } } } exec final function AdminKillRules(string RuleName) { if ( Level.NetMode == NM_Standalone || (PlayerReplicationInfo != none && PlayerReplicationInfo.bAdmin) ) ServerKillRules(RuleName); } final function ServerKillRules(string RuleName) { local GameRules G, PrevG; if ( Level.NetMode != NM_Standalone && (PlayerReplicationInfo == none || !PlayerReplicationInfo.bAdmin) ) return; if ( RuleName ~= "SRGameRules" || RuleName ~= "ScrnGameRules" ) return; // can't kill ScrnGameRules PrevG = Level.Game.GameRulesModifiers; if ( GetItemName(string(PrevG.class)) ~= RuleName ) { ClientMessage("Game Rules '"$string(PrevG.Class)$"' destroyed"); Level.Game.GameRulesModifiers = PrevG.NextGameRules; PrevG.Destroy(); } else { for ( G=PrevG.NextGameRules; G!=None; PrevG=G ) { if ( GetItemName(string(G.class)) ~= RuleName ) { PrevG.NextGameRules = G.NextGameRules; ClientMessage("Game Rules '"$string(G.Class)$"' destroyed"); G.Destroy(); return; } } } } function CheckDLC() { local ScrnSteamStatsGetter A; foreach AllActors(class'ScrnSteamStatsGetter', A) return; // do not allow duplicates spawn(class'ScrnSteamStatsGetter',self); } // returns true if players owns DLC function bool OwnsDLC(int AppID) { local int i; local bool bNeedCheck; for ( i=0; i P; local int i; local class SkinnedWeaponClass; local byte k; if ( Pawn == none || Pawn.Weapon == none ) return; W = KFWeapon(Pawn.Weapon); P = class(Pawn.Weapon.PickupClass); if ( W == none || P == none || P.default.VariantClasses.Length == 0 ) return; if ( W.SleeveNum == 0 ) k = 1; // for weapons where hand skin is first in array if ( k >= W.Skins.length ) { warn(W.class $ " has no skins"); return; } if ( index == 0 ) { bTryNext = true; // find out current skin if ( W.Skins[k] == W.default.Skins[k] ) index = 1; // default skin else { for ( i=0; i= P.default.VariantClasses.Length+2 ) index = 1; if ( index == 1 ) { // load default skin SkinnedWeaponClass = W.class; } else { // load skin from variant class SkinnedWeaponClass = class(P.default.VariantClasses[index-2].default.InventoryType); // DLC check if ( SkinnedWeaponClass == none || (!Mut.bBeta && SkinnedWeaponClass.default.AppID > 0 && !OwnsDLC(SkinnedWeaponClass.default.AppID)) ) { // this skin is locked if ( bTryNext ) GunSkin(index+1, true); // try next one return; } } if ( SkinnedWeaponClass == none ) return; ClientWeaponSpawned(SkinnedWeaponClass, none); // preload assets SkinnedWeaponClass.static.PreloadAssets(W); W.HandleSleeveSwapping(); // restore proper arms ServerGunSkin(SkinnedWeaponClass); // save skin in user.ini for ( i=0; i SkinnedWeaponClass) { local Controller C; local int i; local KFWeapon W; // preload assets for ( C = Level.ControllerList; C != none; C = C.nextController ) { if ( C != self && KFPlayerController(C) != none ) KFPlayerController(C).ClientWeaponSpawned(SkinnedWeaponClass, none); } if ( Pawn != none ) W = KFWeapon(Pawn.Weapon); if ( W != none && W.AttachmentClass != SkinnedWeaponClass.default.AttachmentClass ) { W.ThirdPersonActor.Destroy(); W.ThirdPersonActor = none; W.AttachmentClass = SkinnedWeaponClass.default.AttachmentClass; W.AttachToPawn(Pawn); //remember weapon choise for ( i=0; i 0) ) return; ScrnVT = ScrnHumanPawn(OldViewTarget); if ( ScrnVT != none && ScrnVT != ViewTarget ) { // check if somebody else is spectating our old target for ( C=Level.ControllerList; C!=None; C=C.NextController ) { if ( C.Pawn != ScrnVT && PlayerController(C) != none && PlayerController(C).ViewTarget == ScrnVT ) break; } ScrnVT.bViewTarget = C!=none; } ScrnVT = ScrnHumanPawn(ViewTarget); if ( ScrnVT != none ) ScrnVT.bViewTarget = true; // tell pawn that we are watching him OldViewTarget = ViewTarget; } function ClientSetBehindView(bool B) { super.ClientSetBehindView(B); if ( PlayerReplicationInfo != none && PlayerReplicationInfo.bOnlySpectator ) { // auto show crosshair in first person spectator mode if ( ScrnHUD(MyHUD) != none ) ScrnHUD(MyHUD).DebugCrosshair(!bBehindView); } else if ( B == false ) { bFreeCamera = false; } } exec function FreeCamera( bool B ) { ClientMessage("FreeCamera is blocked due to exploits. Use ToggleBehindView instead"); // free roaming is prohibited in tourney mode // if ( B && !PlayerReplicationInfo.bOnlySpectator && Mut.SrvTourneyMode != 0 ) // return; // super.FreeCamera(B); } state Spectating { // Return to spectator's own camera. exec function AltFire( optional float F ) { // free roaming is prohibited in tourney mode if ( !PlayerReplicationInfo.bOnlySpectator && Mut.SrvTourneyMode != 0 ) Fire(F); else super.AltFire(F); } exec function SwitchWeapon(byte T) { if ( PlayerReplicationInfo.bOnlySpectator ) ServerSwitchViewMode(T); } exec function Use() { local vector HitLocation, HitNormal, TraceEnd, TraceStart; local rotator R; local Actor A; PlayerCalcView(A, TraceStart, R); TraceEnd = TraceStart + 1000 * Vector(R); A = Trace(HitLocation, HitNormal, TraceEnd, TraceStart, true); if ( Pawn(A) != none) ServerSetViewTarget(A); } } // ============================== DEBUG STUFF ============================== // ========================== UNHARMFUL FUNCTIONS ========================== exec function TestColorTags(coerce string ColorTagString, optional int i) { local string c, s; c = class'ScrnBalance'.default.Mut.ParseColorTags(ColorTagString, PlayerReplicationInfo); s = class'ScrnBalance'.default.Mut.StripColorTags(ColorTagString); if ( i > 0) { c = class'ScrnBalance'.static.LeftCol(c, i); s = left(s, i); } ConsoleMessage(c); ConsoleMessage(s); } exec function MyTeam() { if ( PlayerReplicationInfo == none ) ClientMessage("No PlayerReplicationInfo received yet"); else if ( PlayerReplicationInfo.Team == none ) ClientMessage("Team is not selected"); else ClientMessage("My Team Index = " $ PlayerReplicationInfo.Team.TeamIndex $ " ("$ PlayerReplicationInfo.Team.class$")"); } function DebugRepLink(string S) { local ClientPerkRepLink L; local ScrnClientPerkRepLink SL; local int count; if ( Role < ROLE_Authority ) { foreach DynamicActors(Class'ClientPerkRepLink',L) { ++count; } if ( count != 1 ) { if ( count == 0 ) ClientMessage(S @ "WARNING! No RepLink objects found!", 'Log'); else ClientMessage(S @ "WARNING! Multiple RepLink objects found! ("$count$")", 'Log'); } L = Class'ScrnClientPerkRepLink'.Static.FindMe(self); ClientMessage(S @ "RepLink: " $ L, 'Log'); } else { L = SRStatsBase(SteamStatsAndAchievements).Rep; ClientMessage(S @ "Stats: " $ SteamStatsAndAchievements, 'Log'); ClientMessage(S @ "Stats.Rep: " $ L, 'Log'); } ClientMessage(S @ "Categories ACK/TOTAL: " $ L.ClientAccknowledged[1]$"/"$L.ShopCategories.Length, 'Log'); ClientMessage(S @ "Weapons ACK/TOTAL: " $ L.ClientAccknowledged[0]$"/"$L.ShopInventory.Length, 'Log'); ClientMessage(S @ "Characters ACK/TOTAL: " $ L.ClientAckSkinNum$"/"$L.CustomChars.Length, 'Log'); SL = ScrnClientPerkRepLink(L); if ( SL != none ) { ClientMessage(S @ "Job: " $ SL.CurrentJob, 'Log'); } } function ServerDebugRepLink() { if ( Role == ROLE_Authority ) DebugRepLink("Server"); } exec function TestRepLink() { DebugRepLink("Client"); if ( Role < ROLE_Authority ) ServerDebugRepLink(); } exec function RestartRepLink() { local ScrnClientPerkRepLink L; if ( KFGameReplicationInfo(Level.GRI).EndGameType > 0 ) { ClientMessage("Unable to restart replication when game ended."); return; } L = Class'ScrnClientPerkRepLink'.Static.FindMe(self); if ( L == none ) { ClientMessage("ScrnClientPerkRepLink not found"); return; } bDebugRepLink = true; L.StartClientInitialReplication(); } exec function RepLinkMessages(bool value) { bDebugRepLink = value; Class'ScrnClientPerkRepLink'.Static.FindMe(self).bClientDebug = bDebugRepLink; } exec function TestQuickMelee() { local Inventory inv; local KFWeapon W; local string s; local int c; if ( Pawn == none ) return; for ( inv = Pawn.Inventory; inv != none && ++c < 1000 ; inv = inv.Inventory ) { W = KFWeapon(inv); if ( W != none ) { if ( W == Pawn.Weapon ) s = "[CURRENT]"; else s = ""; s @= W.ItemName $ ": ClientState=" $ GetEnum(Enum'EWeaponClientState', W.ClientState); s @= "ClientGrenadeState=" $ GetEnum(Enum'EClientGrenadeState', W.ClientGrenadeState); ClientMessage(s, 'log'); } } ClientMessage("SecondaryItem: " $ ScrnHumanPawn(Pawn).SecondaryItem, 'log'); } exec function FixQuickMelee() { local Inventory inv; local KFWeapon W; local int c; if ( Pawn == none ) return; if ( Level.NetMode == NM_Client ) { ServerFixQuickMelee(); // do the same on server } KFPawn(Pawn).SecondaryItem = none; KFPawn(Pawn).bThrowingNade = false; for ( inv = Pawn.Inventory; inv != none && ++c < 1000 ; inv = inv.Inventory ) { W = KFWeapon(inv); if ( W != none ) { if ( W != Pawn.Weapon ) { W.ClientState = WS_Hidden; W.ClientGrenadeState = GN_None; } W.SetTimer(0, false); W.GotoState(''); } } if ( Pawn.Weapon != none && Pawn.Weapon.ClientState != WS_ReadyToFire ) { Pawn.Weapon.ClientState = WS_Hidden; KFWeapon(Pawn.Weapon).ClientGrenadeState = GN_BringUp; Pawn.Weapon.BringUp(); } } function ServerFixQuickMelee() { if ( Level.NetMode != NM_Client ) { FixQuickMelee(); } } // ======================== COMMENT BEFORE RELEASE !!! ===================== // exec function SetSID64(coerce string SteamID64) // { // //if ( Level.NetMode == NM_Standalone ) // if ( Role == ROLE_Authority ) // class'ScrnCustomPRI'.static.FindMe(PlayerReplicationInfo).SetSteamID64(SteamID64); // } // // exec function TestSID() // { // SetSID64("76561197992537591"); // } // // exec function PerkLevel(int L) // { // if ( Role == ROLE_Authority ) // KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkillLevel = L; // } // // exec function TestZedTime(optional float DesiredZedTimeDuration) // { // if ( Role == ROLE_Authority ) // KFGameType(Level.Game).DramaticEvent(1.0, DesiredZedTimeDuration); // } // // exec function IncAch(name AchID) // { // if ( Level.NetMode == NM_Standalone ) // class'ScrnAchievements'.static.ProgressAchievementByID(Class'ScrnClientPerkRepLink'.Static.FindMe(self), AchID, 1); // } // // exec function GiveAch(name AchID) // { // if ( Level.NetMode == NM_Standalone ) // class'ScrnAchievements'.static.ProgressAchievementByID(Class'ScrnClientPerkRepLink'.Static.FindMe(self), AchID, 1000); // } // // exec function BuyAll() // { // local int i; // local ScrnClientPerkRepLink L; // local ScrnHumanPawn ScrnPawn; // // if ( Role != ROLE_Authority ) // return; // // PlayerReplicationInfo.Score = 1000000; // ScrnPawn = ScrnHumanPawn(Pawn); // L = class'ScrnClientPerkRepLink'.static.FindMe(self); // for ( i=0; i(L.ShopInventory[i].PC.default.InventoryType), 0); // } // } // // // exec function GiveSpawnInv() // { // if ( Role != ROLE_Authority ) // return; // // KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.AddDefaultInventory(KFPlayerReplicationInfo(PlayerReplicationInfo), Pawn); // } // // exec function TestEndGame() // { // if ( Role != ROLE_Authority ) // return; // // Mut.GameRules.bSuperPat = true; // Mut.GameRules.bHasCustomZeds = true; // Mut.GameRules.GameDoom3Kills = 100; // Mut.GameRules.HardcoreLevel = 15; // Mut.KF.WaveNum = Mut.KF.FinalWave + 1; // Mut.KF.CheckEndGame(PlayerReplicationInfo, "Test"); // } defaultproperties { bManualReload=True bOtherPlayerLasersBlue=True bAlwaysDisplayAchProgression=True Custom3DScopeSens=24 bSpeechVote=True AchievementDisplayCooldown=5.000000 bChangedPerkDuringGame=True MaxVoiceMsgIn10s=5 strLocked="Weapon pickups LOCKED" strUnlocked="Weapon pickups UNLOCKED" strLockDisabled="Weapon lock is disabled by server" strAlreadySpectating="Already spectating. Type READY, if you want to join the game." DualWieldables(0)=(Single=Class'KFMod.Single',Dual=Class'KFMod.Dualies') DualWieldables(1)=(Single=Class'KFMod.Deagle',Dual=Class'KFMod.DualDeagle') DualWieldables(2)=(Single=Class'KFMod.GoldenDeagle',Dual=Class'KFMod.GoldenDualDeagle') DualWieldables(3)=(Single=Class'KFMod.Magnum44Pistol',Dual=Class'KFMod.Dual44Magnum') DualWieldables(4)=(Single=Class'KFMod.MK23Pistol',Dual=Class'KFMod.DualMK23Pistol') DualWieldables(5)=(Single=Class'KFMod.FlareRevolver',Dual=Class'KFMod.DualFlareRevolver') ProfilePageClassString="ScrnBalanceSrv.ScrnProfilePage" TSCLobbyMenuClassString="ScrnBalanceSrv.TSCLobbyMenu" bTSCAutoDetectKeys=True RedCharacter="Pyro_Red" BlueCharacter="Pyro_Blue" RedCharacters(0)="Pyro_Red" RedCharacters(1)="Agent_Wilkes" RedCharacters(2)="Ash_Harding" RedCharacters(3)="Chopper_Harris" RedCharacters(4)="Corporal_Lewis" RedCharacters(5)="Dave_The_Butcher_Roberts" RedCharacters(6)="DJ_Scully" RedCharacters(7)="Dr_Gary_Glover" RedCharacters(8)="FoundryWorker_Aldridge" RedCharacters(9)="Harold_Hunt" RedCharacters(10)="Harold_Lott" RedCharacters(11)="Kerry_Fitzpatrick" RedCharacters(12)="Kevo_Chav" RedCharacters(13)="KF_Soviet" RedCharacters(14)="Lieutenant_Masterson" RedCharacters(15)="Mrs_Foster" RedCharacters(16)="Mr_Foster" RedCharacters(17)="Paramedic_Alfred_Anderson" RedCharacters(18)="Police_Constable_Briar" RedCharacters(19)="Police_Sergeant_Davin" RedCharacters(20)="Private_Schnieder" RedCharacters(21)="Reverend_Alberts" RedCharacters(22)="Ricky_Vegas" RedCharacters(23)="Samuel_Avalon" RedCharacters(24)="Security_Officer_Thorne" RedCharacters(25)="Sergeant_Powers" RedCharacters(26)="Shadow_Ferret" RedCharacters(27)="Trooper_Clive_Jenkins" RedCharacters(28)="Mr_Magma" RedCharacters(29)="Ms_Clamley" BlueCharacters(0)="Pyro_Blue" BlueCharacters(1)="Baddest_Santa" BlueCharacters(2)="Captian_Wiggins" BlueCharacters(3)="ChickenNator" BlueCharacters(4)="Commando_Chicken" BlueCharacters(5)="Dr_Jeffrey_Tamm" BlueCharacters(6)="DAR" BlueCharacters(7)="Harchier_Spebbington" BlueCharacters(8)="Harchier_Spebbington_II" BlueCharacters(9)="Hayato_Tanaka" BlueCharacters(10)="KF_German" BlueCharacters(11)="LanceCorporal_Lee_Baron" BlueCharacters(12)="Mike_Noble" BlueCharacters(13)="Reaper" BlueCharacters(14)="Reggie" BlueCharacters(15)="Steampunk_Berserker" BlueCharacters(16)="Steampunk_Commando" BlueCharacters(17)="Steampunk_Demolition" BlueCharacters(18)="Steampunk_DJ_Scully" BlueCharacters(19)="Steampunk_Firebug" BlueCharacters(20)="Steampunk_Medic" BlueCharacters(21)="Steampunk_MrFoster" BlueCharacters(22)="Steampunk_Mrs_Foster" BlueCharacters(23)="Steampunk_Sharpshooter" BlueCharacters(24)="Steampunk_Support_Specialist" BlueCharacters(25)="Voltage" CustomPlayerReplicationInfoClass=Class'ScrnBalanceSrv.ScrnCustomPRI' bDamageAck=True strNoPerkChanges="Mid-game perk changes disabled" strPerkLocked="Perk is locked" strSpecFavoriteAssigned="View target marked as favorite" strSpecNoFavorites="No favorite view targets! Press '4' to assign favorite." DLC(0)=(AppID=210934) DLC(1)=(AppID=210938) DLC(2)=(AppID=210939) DLC(3)=(AppID=210942) DLC(4)=(AppID=210943) DLC(5)=(AppID=210944) DLC(6)=(AppID=258751) DLC(7)=(AppID=258752) DLC(8)=(AppID=309991) MusicPlaylistNames(0)="" MusicPlaylistNames(1)="KF1 Classic Soundtrack" MusicPlaylistNames(2)="DooM Metal Soundtrack" MyMusic(0)=(PL=1,bTrader=True,Song="KF_Defection",Artist="zYnthetic",Title="Defection") MyMusic(1)=(PL=1,bTrader=True,Song="KF_Harm",Artist="zYnthetic",Title="Harm Intended") MyMusic(2)=(PL=1,bTrader=True,Song="KF_Insect",Artist="zYnthetic",Title="Insect Wings") MyMusic(3)=(PL=1,bTrader=True,Song="KF_Mutagen",Artist="zYnthetic",Title="Mutagen") MyMusic(4)=(PL=1,bTrader=True,Song="KF_Neurotoxin",Artist="zYnthetic",Title="Neurotoxin") MyMusic(5)=(PL=1,bTrader=True,Song="KF_Peripheral",Artist="zYnthetic",Title="Peripheral") MyMusic(6)=(PL=1,bTrader=True,Song="KF_SinSoma",Artist="zYnthetic",Title="Sin Soma and the Masquerade") MyMusic(7)=(PL=1,bTrader=True,Song="KF_Smolder",Artist="zYnthetic",Title="Smolder") MyMusic(8)=(PL=1,bTrader=True,Song="KF_SurfaceTension",Artist="zYnthetic",Title="Surface Tension") MyMusic(9)=(PL=1,bTrader=True,Song="KF_TheEdge",Artist="zYnthetic",Title="The Edge Of The Abyss") MyMusic(10)=(PL=1,bTrader=True,Song="KF_TheStitches",Artist="zYnthetic",Title="The Stitches Are A Reminder") MyMusic(11)=(PL=1,bTrader=True,Song="KF_Treatments",Artist="zYnthetic",Title="Treatments Are More Profitable Than Cures") MyMusic(12)=(PL=1,bTrader=True,Song="KF_Vapour",Artist="zYnthetic",Title="Vapour") MyMusic(13)=(PL=1,bTrader=True,Song="KF_Wading",Artist="zYnthetic",Title="Wading Through The Bodies") MyMusic(14)=(PL=1,Song="DirgeDefective1",Artist="Dirge",Title="Defective") MyMusic(15)=(PL=1,Song="DirgeDefective2",Artist="Dirge",Title="Defective") MyMusic(16)=(PL=1,Song="DirgeDisunion1",Artist="Dirge",Title="Disunion") MyMusic(17)=(PL=1,Song="DirgeDisunion2",Artist="Dirge",Title="Disunion") MyMusic(18)=(PL=1,Song="DirgeRepulse1",Artist="Dirge",Title="Repulse") MyMusic(19)=(PL=1,Song="DirgeRepulse2",Artist="Dirge",Title="Repulse") MyMusic(20)=(PL=1,Song="KF_Infectious_Cadaver",Artist="Six Feet of Foreplay",Title="Infectious Cadaver") MyMusic(21)=(PL=1,Song="KF_BledDry",Artist="zYnthetic",Title="Bled Dry") MyMusic(22)=(PL=1,Song="KF_Containment",Artist="zYnthetic",Title="Containment Breach") MyMusic(23)=(PL=1,Song="KF_Hunger",Artist="zYnthetic",Title="Hunger") MyMusic(24)=(PL=1,Song="KF_Pathogen",Artist="zYnthetic",Title="Pathogen") MyMusic(25)=(PL=1,Song="KF_WPrevention",Artist="zYnthetic",Title="Witness Prevention") MyMusic(26)=(PL=1,Wave=11,Song="KF_Abandon",Artist="zYnthetic",Title="Abandon All") MyMusic(27)=(PL=2,bTrader=True,Song="EGT-ThisLove",Artist="elguitarTom",Title="Waiting For Romero To Play") MyMusic(28)=(PL=2,bTrader=True,Song="EGT-Interlevel",Artist="elguitarTom",Title="Interlevel") MyMusic(29)=(PL=2,Wave=1,Song="EGT-Entryway",Artist="elguitarTom",Title="Entryway") MyMusic(30)=(PL=2,Wave=2,Song="EGT-E1M1",Artist="elguitarTom",Title="E1M1") MyMusic(31)=(PL=2,Wave=3,Song="EGT-Demon1",Artist="elguitarTom",Title="The Demon's Dead, Part 1") MyMusic(32)=(PL=2,Wave=4,Song="EGT-Shawn",Artist="elguitarTom",Title="Shawn's Got The Shotgun") MyMusic(33)=(PL=2,Wave=5,Song="EGT-ToxinRefinery",Artist="elguitarTom",Title="Toxin Refinery") MyMusic(34)=(PL=2,Wave=6,Song="EGT-Entryway",Artist="elguitarTom",Title="Entryway") MyMusic(35)=(PL=2,Wave=7,Song="EGT-Demon2",Artist="elguitarTom",Title="The Demon's Dead, Part 2") MyMusic(36)=(PL=2,Wave=8,Song="EGT-PhobosLab",Artist="elguitarTom",Title="Phobos Lab") MyMusic(37)=(PL=2,Wave=9,Song="EGT-E1M1",Artist="elguitarTom",Title="E1M1") MyMusic(38)=(PL=2,Wave=10,Song="EGT-Shawn",Artist="elguitarTom",Title="Shawn's Got The Shotgun") MyMusic(39)=(PL=2,Wave=11,Song="EGT-SignOfEvil",Artist="elguitarTom",Title="Sign Of Evil") strPlayingSong="Now playing: " FlareCloudClass=Class'ScrnBalanceSrv.ScrnFlareCloud' LobbyMenuClassString="ScrnBalanceSrv.ScrnLobbyMenu" PawnClass=Class'ScrnBalanceSrv.ScrnHumanPawn' bNotifyLocalPlayerTeamReceived=True }