371 lines
9.9 KiB
Ucode
371 lines
9.9 KiB
Ucode
|
//=============================================================================
|
||
|
// KFPlayerControllerVersus
|
||
|
//=============================================================================
|
||
|
// Versus playercontroller class
|
||
|
//=============================================================================
|
||
|
// Killing Floor 2
|
||
|
// Copyright (C) 2016 Tripwire Interactive LLC
|
||
|
//=============================================================================
|
||
|
class KFPlayerControllerVersus extends KFPlayerController;
|
||
|
|
||
|
var string BossName;
|
||
|
|
||
|
/** Array of zed classes spawned by this player */
|
||
|
var array<bool> HasSpawnedZeds;
|
||
|
|
||
|
/************************************
|
||
|
* Zed XP
|
||
|
************************************/
|
||
|
var int ZedXPAmount;
|
||
|
var byte ZedXPLevel;
|
||
|
|
||
|
/************************************
|
||
|
* Replication
|
||
|
************************************/
|
||
|
replication
|
||
|
{
|
||
|
if ( bNetDirty )
|
||
|
ZedXPAmount, ZedXPLevel;
|
||
|
}
|
||
|
|
||
|
function Restart(bool bVehicleTransition)
|
||
|
{
|
||
|
super.Restart( bVehicleTransition );
|
||
|
|
||
|
if( GetTeamNum() == 255 )
|
||
|
{
|
||
|
KFThirdPersonCamera(KFPlayerCamera(PlayerCamera).ThirdPersonCam).SetViewOffset( KFPawn_Monster(Pawn).ThirdPersonViewOffset );
|
||
|
|
||
|
if( PlayerCamera.CameraStyle != 'Boss' )
|
||
|
{
|
||
|
ServerCamera('ThirdPerson');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
reliable client function ClientRestart(Pawn NewPawn)
|
||
|
{
|
||
|
Super.ClientRestart(NewPawn);
|
||
|
|
||
|
if(NewPawn == none)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( Role < ROLE_Authority && GetTeamNum() == 255 )
|
||
|
{
|
||
|
KFThirdPersonCamera(KFPlayerCamera(PlayerCamera).ThirdPersonCam).SetViewOffset( KFPawn_Monster(Pawn).ThirdPersonViewOffset );
|
||
|
|
||
|
if( PlayerCamera.CameraStyle != 'Boss' )
|
||
|
{
|
||
|
SetCameraMode('ThirdPerson');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** GBA_SwitchAltFire */
|
||
|
exec function StartAltFire(optional Byte FireModeNum )
|
||
|
{
|
||
|
if( Pawn != none && (Pawn.Weapon == none || Pawn.Weapon.ShouldWeaponIgnoreStartFire()) )
|
||
|
{
|
||
|
Pawn.StartFire(4);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
super.StartAltFire();
|
||
|
}
|
||
|
|
||
|
/** GBA_SwitchAltFire
|
||
|
* Weapons that override AltFireMode (e.g. welder) and call StartFire
|
||
|
* also need to call StopFire. For most weapons this is unnecessary.
|
||
|
*/
|
||
|
exec function StopAltFire(optional Byte FireModeNum )
|
||
|
{
|
||
|
if( Pawn != none && (Pawn.Weapon == none || Pawn.Weapon.ShouldWeaponIgnoreStartFire()) )
|
||
|
{
|
||
|
Pawn.StopFire(4);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
super.StopAltFire();
|
||
|
}
|
||
|
|
||
|
function AwardZedDamage( int DamageAmount, bool bDamagerIsMe )
|
||
|
{
|
||
|
// Ramm Versus TODO: Finish this zed damage reward stuff
|
||
|
ZedXPAmount += DamageAmount;
|
||
|
//SetRTPCValue( 'R_Method', 7, true );
|
||
|
//PlayAKEvent( AkEvent'WW_UI_PlayerCharacter.Play_R_Method_Top' );
|
||
|
|
||
|
//
|
||
|
// if( !bDamagerIsMe )
|
||
|
// {
|
||
|
// ClientMessage("Got ZedXP for nearby zed damage. ZedXP = "$ZedXPAmount);
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// ClientMessage("Got ZedXP for my zed damage. ZedXP = "$ZedXPAmount);
|
||
|
// }
|
||
|
//
|
||
|
// if( ZedXPAmount > 50 && ZedXPLevel < 1 )
|
||
|
// {
|
||
|
// ZedXPLevel = 1;
|
||
|
// class'KFMusicStingerHelper'.static.PlayLevelUpStinger( self );
|
||
|
// ClientMessage("Unlocked Level 1 Zeds!!!");
|
||
|
// }
|
||
|
//
|
||
|
// `log("ZedXPAmount = "$ZedXPAmount$" ZedXPLevel = "$ZedXPLevel);
|
||
|
}
|
||
|
|
||
|
function AddTrackedDamage(int Amount, class<DamageType> DamageType, class<Pawn> DamagerClass, class<Pawn> VictimClass)
|
||
|
{
|
||
|
if (VictimClass == class'KFPawn_Human_Versus')
|
||
|
{
|
||
|
AddTrackedVsDamage(Amount, DamagerClass);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Super.AddTrackedDamage(Amount, DamageType, DamagerClass, VictimClass);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** @return TRUE if any of the gameplay post process effects have a strength greater than 0.
|
||
|
Append to this list if additional effects are added. */
|
||
|
function bool ShouldDisplayGameplayPostProcessFX()
|
||
|
{
|
||
|
// Overridden because the zeds health vary so much, it needs to be a percentage of max health - Ramm
|
||
|
return super.ShouldDisplayGameplayPostProcessFX()
|
||
|
|| (GetTeamNum() == 255 && Pawn != none && (Pawn.Health / float(Pawn.HealthMax)) * 100.f <= default.LowHealthThreshold);
|
||
|
}
|
||
|
|
||
|
function RecieveChatMessage(PlayerReplicationInfo PRI, string ChatMessage, name Type, optional float MsgLifeTime)
|
||
|
{
|
||
|
if(PRI.bAdmin)
|
||
|
{
|
||
|
ChatMessage = class'KFLocalMessage'.default.AdminString$ChatMessage;
|
||
|
MyGFxHUD.HudChatBox.AddChatMessage(ChatMessage, class 'KFLocalMessage'.default.PriorityColor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(Type == 'TeamSay')
|
||
|
{
|
||
|
MyGFxHUD.HudChatBox.AddChatMessage(ChatMessage, class 'KFLocalMessage'.default.TeamSayColor);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MyGFxHUD.HudChatBox.AddChatMessage(ChatMessage, class 'KFLocalMessage'.default.SayColor);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unreliable client function NotifyOfAutoBalance()
|
||
|
{
|
||
|
MyGFxManager.DelayedOpenPopup(ENotification, EDPPID_Misc, Class'KFCommon_LocalizedStrings'.default.NoticeString, Class'KFCommon_LocalizedStrings'.default.TeamSwappedString, Class'KFCommon_LocalizedStrings'.default.OKString);
|
||
|
MyGFxHUD.ShowNonCriticalMessage(Class'KFCommon_LocalizedStrings'.default.TeamSwappedString);
|
||
|
}
|
||
|
|
||
|
//override from base PlayerController
|
||
|
exec function ChangeTeam( optional string TeamName )
|
||
|
{
|
||
|
RequestSwitchTeam();
|
||
|
}
|
||
|
|
||
|
exec function RequestSwitchTeam()
|
||
|
{
|
||
|
local KFPlayerReplicationInfo KFPRI;
|
||
|
|
||
|
KFPRI = KFPlayerReplicationInfo(PlayerReplicationInfo);
|
||
|
if ( KFPRI != None && !KFPRI.bOnlySpectator )
|
||
|
{
|
||
|
KFPRI.ServerSwitchTeam();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** We have to change perks when players team switch */
|
||
|
function ServerNotifyTeamChanged()
|
||
|
{
|
||
|
if( Role == ROLE_Authority && MonsterPerkClass != None )
|
||
|
{
|
||
|
/*if ( CurrentPerk == None )
|
||
|
{
|
||
|
// If we get here without a perk via the normal path, we're in trouble.
|
||
|
// SavedPerkIndex may not have been updated (config loaded) which will
|
||
|
// cause team switch to get you the wrong perk.
|
||
|
`warn("Versus: ServerNotifyTeamChanged called before client has assigned a SavedPerkIndex!");
|
||
|
}*/
|
||
|
|
||
|
if( GetTeamNum() > 0 )
|
||
|
{
|
||
|
ServerSelectPerk( 255, 0, 0, true );
|
||
|
}
|
||
|
else if( CurrentPerk != none && CurrentPerk.Class == MonsterPerkClass )
|
||
|
{
|
||
|
ServerSelectPerk( SavedPerkIndex, Perklist[SavedPerkIndex].PerkLevel, Perklist[SavedPerkIndex].PrestigeLevel, true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function ClientRecieveNewTeam()
|
||
|
{
|
||
|
if(MyGFxManager != none)
|
||
|
{
|
||
|
MyGFxManager.ClientRecieveNewTeam();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
state Dead
|
||
|
{
|
||
|
event BeginState(Name PreviousStateName)
|
||
|
{
|
||
|
super.BeginState( PreviousStateName );
|
||
|
|
||
|
// Reset camera offset
|
||
|
if( GetTeamNum() == 255 )
|
||
|
{
|
||
|
KFThirdPersonCamera(KFPlayerCamera(PlayerCamera).ThirdPersonCam).SetViewOffset( class'KFThirdPersonCameraMode'.static.GetDefaultOffset() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Called when view target is changed while in spectating state */
|
||
|
function NotifyChangeSpectateViewTarget()
|
||
|
{
|
||
|
local KFPawn_Monster KFPM;
|
||
|
|
||
|
super.NotifyChangeSpectateViewTarget();
|
||
|
|
||
|
KFPM = KFPawn_Monster( ViewTarget );
|
||
|
if( KFPM != none )
|
||
|
{
|
||
|
KFThirdPersonCamera(KFPlayerCamera(PlayerCamera).ThirdPersonCam).SetViewOffset( KFPM.default.ThirdPersonViewOffset );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Level was reset without reloading
|
||
|
* NOTE: We can't call the super because it does a lot of things we don't want it to do. -MattF
|
||
|
*/
|
||
|
function Reset()
|
||
|
{
|
||
|
// Only reset active players!
|
||
|
if( CanRestartPlayer() )
|
||
|
{
|
||
|
SetViewTarget( self );
|
||
|
ResetCameraMode();
|
||
|
FixFOV();
|
||
|
|
||
|
// This is necessary because the server will try to synchronize pawns with the client when the client
|
||
|
// is in the middle of trying to clean its pawn reference up. The ClientRestart() function sends the
|
||
|
// client into a state (WaitingForPawn) where it thinks the server is about to replicate a new pawn,
|
||
|
// but it isn't, so the client gets stuck there forever.
|
||
|
AcknowledgedPawn = none;
|
||
|
|
||
|
PlayerZedSpawnInfo.PendingZedPawnClass = none;
|
||
|
PlayerZedSpawnInfo.PendingZedSpawnLocation = vect( 0,0,0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Level was reset without reloading */
|
||
|
reliable client function ClientReset()
|
||
|
{
|
||
|
local Actor A;
|
||
|
local array<Actor> BloodSplatActors;
|
||
|
local int i;
|
||
|
|
||
|
// Ensures this only runs once on listen servers
|
||
|
if( !IsLocalPlayerController() )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Reset all actors (except controllers and blood splats)
|
||
|
foreach AllActors( class'Actor', A )
|
||
|
{
|
||
|
if( A.IsA('KFPersistentBloodActor') )
|
||
|
{
|
||
|
BloodSplatActors.AddItem( A );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if( WorldInfo.NetMode == NM_Client && !A.IsA('Controller') )
|
||
|
{
|
||
|
A.Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Reset blood splat actors after everything else
|
||
|
for( i = 0; i < BloodSplatActors.Length; ++i )
|
||
|
{
|
||
|
BloodSplatActors[i].Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* InitInputSystem()
|
||
|
* Spawn the appropriate class of PlayerInput
|
||
|
* Only called for playercontrollers that belong to local players
|
||
|
*/
|
||
|
event InitInputSystem()
|
||
|
{
|
||
|
Super.InitInputSystem();
|
||
|
|
||
|
KFPlayerInput(PlayerInput).bVersusInput = true;
|
||
|
}
|
||
|
|
||
|
/** Overridden to allow perk changes during the end of the round */
|
||
|
event SetHaveUpdatePerk( bool bUsedUpdate )
|
||
|
{
|
||
|
super.SetHaveUpdatePerk( KFGameReplicationInfoVersus(WorldInfo.GRI).bRoundIsOver ? false : bUsedUpdate );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Mixer Integration
|
||
|
//-----------------------------------------------------------------------------
|
||
|
//Do nothing for versus controllers. Mixer will startup with other spots on pawn receive
|
||
|
reliable client function ClientMatchStarted()
|
||
|
{}
|
||
|
|
||
|
reliable client function GivePawn(Pawn NewPawn)
|
||
|
{
|
||
|
super.GivePawn(NewPawn);
|
||
|
|
||
|
if (NewPawn == none)
|
||
|
{
|
||
|
MixerCurrentDefaultScene = "default";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MixerCurrentDefaultScene = GetPawnBasedMixerScene(NewPawn);
|
||
|
}
|
||
|
|
||
|
MixerMoveUsersToDefaultGroup();
|
||
|
}
|
||
|
|
||
|
simulated protected function MixerStartupComplete()
|
||
|
{
|
||
|
MixerCurrentDefaultScene = GetPawnBasedMixerScene(Pawn);
|
||
|
SetTimer(1.f, false, nameof(MixerMoveUsersToDefaultGroup));
|
||
|
}
|
||
|
|
||
|
simulated final function string GetPawnBasedMixerScene(Pawn InPawn)
|
||
|
{
|
||
|
if (InPawn != none)
|
||
|
{
|
||
|
if (InPawn.IsA('KFPawn_Monster'))
|
||
|
{
|
||
|
return "VersusZed";
|
||
|
}
|
||
|
else if (!InPawn.IsA('KFPawn_Customization'))
|
||
|
{
|
||
|
return "SelectSide";
|
||
|
}
|
||
|
}
|
||
|
return "default";
|
||
|
}
|
||
|
|
||
|
DefaultProperties
|
||
|
{
|
||
|
CameraClass=class'KFPlayerCamera_Versus'
|
||
|
MonsterPerkClass=class'KFPerk_Monster'
|
||
|
PostRoundMenuClass=class'KFGFxMoviePlayer_PostRoundMenu'
|
||
|
}
|