// stub KFPlayerController for hooks
class repl_PC extends KFPlayerController_Story;


// =========================================================
// empty function stub
simulated function noop(){}


// always true bool
simulated function bool bTrue()
{
  return true;
}


// =========================================================
// auto netspeed 10001
simulated event PostNetReceive()
{
  local xUtil.PlayerRecord rec;

  super(UnrealPlayer).PostNetReceive();

  if (PlayerReplicationInfo != none && bWaitingForPRI)
  {
    bWaitingForPRI = false;

    rec = class'xUtil'.static.FindPlayerRecord(PlayerReplicationInfo.CharacterName);

    if (rec.Species != none)
    {
      if (PlayerReplicationInfo.Team == none)
        rec.Species.static.LoadResources(rec, Level, PlayerReplicationInfo, 255);
      else
        rec.Species.static.LoadResources(rec, Level, PlayerReplicationInfo, PlayerReplicationInfo.Team.TeamIndex);
    }

    // ADDITION!!! fps unlock
    Player.Console.DelayedConsoleCommand("netspeed " $ 10001);
    // auto `stat fps` / `stat net`
    if (class'Settings'.default.bDeduceAdvancedInfo)
    {
      Player.Console.DelayedConsoleCommand("stat fps");
      Player.Console.DelayedConsoleCommand("stat net");
    }

    // Handle auto Demo Recording
    if (bAutoDemoRec && level.NetMode == NM_Client && !bDemoOwner)
      Player.Console.DelayedConsoleCommand("demorec");
  }

  if (VoiceReplicationInfo != none && bWaitingForVRI)
  {
    if (PlayerReplicationInfo != none && !PlayerReplicationInfo.NeedNetNotify())
    {
      bWaitingForVRI = VoiceReplicationInfo.GetPublicChannelCount(true) == 0;
      if (!bWaitingForVRI)
      {
        VoiceReplicationInfo.SetOwner(self);
        if (bVoiceChatEnabled)
          InitializeVoiceChat();
        else
          DisableVoiceChat();
      }
    }
  }

  bNetNotify = NeedNetNotify();
}


// change the HUD
// Engine.PlayerController
simulated function ClientSetHUD(class<HUD> newHUDClass, class<Scoreboard> newScoringClass)
{
  if (myHUD != none)
    myHUD.Destroy();

  if (newHUDClass == none)
    myHUD = none;
  else
  {
    // inject our HUD class
    class'repl_PC'.static.ReplaceHUDClass(newHUDClass);

    myHUD = spawn(newHUDClass, self);

    if (myHUD == none)
      log ("PlayerController::ClientSetHUD(): Could not spawn a HUD of class "$newHUDClass, 'Error');
    else
      myHUD.SetScoreBoardClass( newScoringClass );
  }

  if (Level.Song != "" && Level.Song != "none")
    ClientSetInitialMusic(Level.Song, MTRAN_Fade);
}


// currently only vanilla hud and steamy test map supported
final static function ReplaceHUDClass(out class<HUD> hud)
{
  if (string(hud) ~= "KFMod.HUDKillingFloor" || string(hud) ~= "PerkTestMutV3.PTHUD")
  {
    hud = class'HideHUD';
    // hud = class'SkeletonHUD';
    log("HideHUD injected and active!!!");
  }
}

// =========================================================
// zed time sound effect switch
simulated function CheckZEDMessage()
{
  if (!bHadZED && !class'Settings'.default.bHideZedTimeSounds)
  {
    ReceiveLocalizedMessage(class'KFMod.WaitingMessage', 5);
    bHadZED = true;
    SaveConfig();
  }
}


simulated function ClientEnterZedTime()
{
  if (class'Settings'.default.bHideZedTimeSounds)
    return;

  CheckZEDMessage();

  if ( Pawn != none && Pawn.Weapon != none )
    Pawn.Weapon.PlaySound(Sound'KF_PlayerGlobalSnd.Zedtime_Enter', SLOT_Talk, 2.0,false,500.0,1.1/Level.TimeDilation,false);
  else
    PlaySound(Sound'KF_PlayerGlobalSnd.Zedtime_Enter', SLOT_Talk, 2.0,false,500.0,1.1/Level.TimeDilation,false);
}


simulated function ClientExitZedTime()
{
  if (class'Settings'.default.bHideZedTimeSounds)
    return;

  if ( Pawn != none && Pawn.Weapon != none )
    Pawn.Weapon.PlaySound(Sound'KF_PlayerGlobalSnd.Zedtime_Exit', SLOT_Talk, 2.0,false,500.0,1.1/Level.TimeDilation,false);
  else
    PlaySound(Sound'KF_PlayerGlobalSnd.Zedtime_Exit', SLOT_Talk, 2.0,false,500.0,1.1/Level.TimeDilation,false);
}


// =========================================================
// show lobby menu if we press Esc during pending game state
// Playercontroller
exec function ShowMenu()
{
  local bool bCloseHUDScreen;

  if (Level.GRI.bMatchHasBegun || PlayerReplicationInfo.bOnlySpectator)
  {
    if (MyHUD != None)
    {
      bCloseHUDScreen = MyHUD.bShowScoreboard || MyHUD.bShowLocalStats;
      if (MyHUD.bShowScoreboard)
        MyHUD.bShowScoreboard = false;
      if (MyHUD.bShowLocalStats)
        MyHUD.bShowLocalStats = false;
      if (bCloseHUDScreen)
        return;
    }

    ShowMidGameMenu(true);
  }
  // ADDITION!!! Open lobby menu at same time!
  else
  {
    StopForceFeedback();
    // this shit is an issue, find a way to set this
    bPendingLobbyDisplay = false;
    // ClientOpenMenu(LobbyMenuClassString);
    if (Player != none)
      ClientOpenMenu(LobbyMenuClassString);
  }
}

// motherfucking idiots in TWI
// yet another <pawn is none> log spam fix
simulated function ShowLoginMenu()
{
  // FIXED!!!
  if (Pawn != none && ((Pawn.Health > 0) || (Pawn.PlayerReplicationInfo != none && Pawn.PlayerReplicationInfo.bReadyToPlay)))
    return;

  if (GameReplicationInfo != none)
  {
    // Open menu
    ClientReplaceMenu(LobbyMenuClassString);
  }
}


// The player wants to switch to weapon group number F.
exec function SwitchWeapon(byte F)
{
  if (Pawn == none)
    return;

  if (class'a_WeaponManager'.default.bUseVanillaManagement)
    Pawn.SwitchWeapon(F);
  else
    ConsoleCommand("hide_getWeapon " $ F);
}


// remove ambient shake
event SetAmbientShake(float FalloffStartTime, float FalloffTime, vector OffsetMag, float OffsetFreq, rotator RotMag, float RotFreq)
{
  local float FalloffScaling;
  local float CurrentOffsetMag;

  // on-off switch
  if (class'Settings'.default.bRemoveAmbientShake)
    return;

  // Calculate current shake's magnitude
  if (AmbientShakeFalloffStartTime > 0)
  {
    FalloffScaling = 1.0 - ((Level.TimeSeconds - AmbientShakeFalloffStartTime) / AmbientShakeFalloffTime);
    FalloffScaling = FClamp(FalloffScaling, 0.0, 1.0);
  }
  else
  {
    FalloffScaling = 1.0;
  }
  CurrentOffsetMag = VSize(AmbientShakeOffsetMag * FalloffScaling);

  // If new shake is less than old shake just ignore it
  if (VSize(OffsetMag) < CurrentOffsetMag)
  {
    return;
  }

  bEnableAmbientShake = true;
  AmbientShakeFalloffStartTime = FalloffStartTime;
  AmbientShakeFalloffTime = FalloffTime;
  AmbientShakeOffsetMag = OffsetMag;
  AmbientShakeOffsetFreq = OffsetFreq;
  AmbientShakeRotMag = RotMag;
  AmbientShakeRotFreq = RotFreq;
}


// remove whole shaking effect
function ShakeView(vector shRotMag, vector shRotRate, float shRotTime, vector shOffsetMag, vector shOffsetRate, float shOffsetTime)
{
  // on-off switch
  if (class'Settings'.default.bRemoveShakeView)
    return;

  if (VSize(shRotMag) > VSize(ShakeRotMax))
  {
    ShakeRotMax  = shRotMag;
    ShakeRotRate = shRotRate;
    ShakeRotTime = shRotTime * vect(1,1,1);
  }

  if (VSize(shOffsetMag) > VSize(ShakeOffsetMax))
  {
    ShakeOffsetMax  = shOffsetMag;
    ShakeOffsetRate = shOffsetRate;
    ShakeOffsetTime = shOffsetTime * vect(1,1,1);
  }
}


function WeaponShakeView(vector shRotMag, vector shRotRate, float shRotTime, vector shOffsetMag, vector shOffsetRate, float shOffsetTime)
{
  if (!class'Settings'.default.bRemoveWeaponShakeView && bWeaponViewShake)
    ShakeView(shRotMag * (1.0 - ZoomLevel), shRotRate, shRotTime, shOffsetMag * (1.0 - ZoomLevel), shOffsetRate, shOffsetTime);
}


exec function ToggleBehindView()
{
  local bool bWasBehindView;

  bWasBehindView = bBehindView;

  CameraDist = default.CameraDist;
  if (bBehindView != bWasBehindView)
    ViewTarget.POVChanged(self, true);

  if (Vehicle(Pawn) != none)
  {
    Vehicle(Pawn).bDesiredBehindView = bWasBehindView;
    Pawn.SaveConfig();
  }

  bBehindView = !bBehindView;
}

defaultproperties
{
}
