Engine
Class PlayerController

source: C:\XIII\Engine\Classes\PlayerController.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Controller
         |
         +--Engine.PlayerController
Direct Known Subclasses:Admin, Camera, MessagingSpectator, XIIIPlayerController

class PlayerController
extends Engine.Controller

//============================================================================= // PlayerController // // PlayerControllers are used by human players to control pawns. // // This is a built-in Unreal class and it shouldn't be modified. // CHANGENOTE: All Changes since v739 in this class are related to the Weapon code update, except // for the change in Possess(). //=============================================================================
Variables
 vector AdjustedAimForFiring
           Aim to use when firing Projectiles (because display don't show anticipation
 int AnnouncerVolume
           heads up display info
 LandBob, AppliedBob
           Used to store everything that should be usefull for on-line ladder/rankings
 Actor BestTarget
           to memorize the best target and use it in interaction
 float Bob
           Used to store everything that should be usefull for on-line ladder/rankings
 float CameraDist
           multiplier for behindview camera dist
 class CheatClass
           class of my CheatManager
 CheatManager CheatManager
           Object within playercontroller that manages "cheat" commands
 CurrentTimeStamp,LastUpdateTime,ServerTimeStamp,TimeMargin, ClientUpdateTime
           freed moves, available for buffering
 eConfigType ConfigType
           auto center view afer walking a while
 float DefaultFOV
           multiplier for behindview camera dist
 float DeltaT
           to enable using it anywhere (needed for death camera sfxs at least)
 int DemoViewPitch
           class of my PlayerInput
 int DemoViewYaw
           class of my PlayerInput
 float DesiredFOV
           multiplier for behindview camera dist
 EDoubleClickDir DoubleClickDir
           direction of movement key double click (for special moves)
 int EnemyTurnSpeed
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 color FilterColor
           multiplier for behindview camera dist
 float FilterColorSpeed
           multiplier for behindview camera dist
 color FilterColorWanted
           multiplier for behindview camera dist
 int FilterInternalInc
           multiplier for behindview camera dist
 FlashScale, FlashFog
           multiplier for behindview camera dist
 SavedMove FreeMoves
           freed moves, available for buffering
 GameReplicationInfo GameReplicationInfo
           freed moves, available for buffering
 int GroundPitch
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 class InputClass
           class of my PlayerInput
 ConstantGlowScale, InstantFlash
           multiplier for behindview camera dist
 ConstantGlowFog, InstantFog
           multiplier for behindview camera dist
 float LastPlaySound
           heads up display info
 class LocalMessageClass
           Used to store everything that should be usefull for on-line ladder/rankings
 vector MaxShakeOffset
           max magnitude to offset camera position
 float MaxShakeRoll
           max magnitude to roll camera
 float MaxTimeMargin
           freed moves, available for buffering
 vector MemAim
           memorize aim when switching bLocked
 int Misc1,Misc2
           direction of movement key double click (for special moves)
 string NoPauseMessage
           freed moves, available for buffering
 vector OldAdjustAim
           Used to smooth autoaim, Aim to use when firing non-projectiles
 Actor OldBestTarget
           to memorize the best target and use it in interaction
 Weapon OldClientWeapon
           freed moves, available for buffering
 vector OldFloor
           used by PlayerSpider mode - floor for which old rotation was based;
 float OrthoZoom
           Orthogonal/map view zoom factor.
 string OwnCamera
           freed moves, available for buffering
 SavedMove PendingMove
           freed moves, available for buffering
 Player Player
 PlayerInput PlayerInput
           Object within playercontroller that manages player input.
 PlayerStats PlayerStat
           Used to store everything that should be usefull for on-line ladder/rankings
 color ProgressColor[4]
           freed moves, available for buffering
 string ProgressMessage[4]
           freed moves, available for buffering
 float ProgressTimeOut
           freed moves, available for buffering
 string QuickSaveString
           freed moves, available for buffering
 bool ReceivedSecretChecksum
           freed moves, available for buffering
 int RendMap
           direction of movement key double click (for special moves)
 SavedMove SavedMoves
           buffered moves pending position updates
 ShakeFrame, ShakeFrameRate
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 float ShakeFrameTime
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 vector ShakeOffset
           current magnitude to offset camera from shake
 vector ShakeOffsetRate
           rate to change roll
 vector ShakeOffsetTime
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 float ShakeRollRate
           rate to change roll
 float ShakeRollTime
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 int ShowFlags
           direction of movement key double click (for special moves)
 float TargetEyeHeight
           multiplier for behindview camera dist
 rotator TargetViewRotation
           multiplier for behindview camera dist
 vector TargetWeaponViewOffset
           multiplier for behindview camera dist
 rotator TurnRot180
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 Pawn TurnTarget
           how long to roll. if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
 byte UseVignetteFilter
           class of my PlayerInput
 byte UseVignetteFilter
           class of my PlayerInput
 byte UseVignetteHighlight
           class of my PlayerInput
 byte UseVignetteHighlight
           class of my PlayerInput
 int UserPadConfig
           auto center view afer walking a while
 vector ViewAdjustAim
           Used to smooth Weapon rot on screen
 Actor ViewTarget
           Orthogonal/map view zoom factor.
 string ViewingFrom
           freed moves, available for buffering
 color VignetteColor
           class of my PlayerInput
 color VignetteColor
           class of my PlayerInput
 float VignetteHighLight
           class of my PlayerInput
 float VignetteHighLight
           class of my PlayerInput
 Material VignetteMaterial
           class of my PlayerInput
 Material VignetteMaterial
           class of my PlayerInput
 float WaitDelay
           Delay time until can restart
 vector WalkBob
           Used to store everything that should be usefull for on-line ladder/rankings
 int WeaponUpdate
           freed moves, available for buffering
 float ZoomLevel
           multiplier for behindview camera dist
 b90Right, b180Turn
           To make us turn fast to left or right.
 byte bAltDuck
           To enable the AltDuck Mode
 byte bAltJump
           To be used for Hook Mode using Duck/Jump
 byte bAltRun
          
 bool bAlwaysLevel
           This controller is not allowed to possess pawns
 bool bAlwaysMouseLook
           Snap to level eyeheight when not mouselooking
 bool bAutoPickup
           AutoPickup objects.
 bool bBehindView
           Outside-the-player view.
 bool bCenterView
           no snapping when true
 bool bCheatFlying
           instantly stop in flying mode
 bool bDontUseVolumeFog
           adjustaim locked someone (to handle transitions between crosshair pos
 bool bFixedCamera
           used to fix camera in position (to view animations)
 bool bFreeCamera
           free camera when in behindview mode (for checking out player models and animations)
 bool bFrozen
           set when game ends or player dies to temporarily prevent player from restarting (until cleared by timer)
 bool bInverseLook
           Inverse FlightSim/Std Pad look axis
 bool bIsInMenu
           adjustaim locked someone (to handle transitions between crosshair pos
 bool bIsTyping
           set when game ends or player dies to temporarily prevent player from restarting (until cleared by timer)
 bool bJumpStatus
           used in net games
 bool bKeyboardLook
           no snapping when true
 bool bLocked
           adjustaim locked someone (to handle transitions between crosshair pos
 bool bLookUpStairs
           look up/down stairs (player)
 bool bNeverSwitchOnPickup
           if true, don't automatically switch to picked up weapon
 bool bOnlySpectator
           This controller is not allowed to possess pawns
 bool bPressedJump
           set when game ends or player dies to temporarily prevent player from restarting (until cleared by timer)
 bLeft, bRight
           check if KEYs are pressed and not pad.
 bool bSetTurnRot
           This controller is not allowed to possess pawns
 bool bSnapToLevel
           Snap to level eyeheight when not mouselooking
 bool bUpdatePosition
           set when game ends or player dies to temporarily prevent player from restarting (until cleared by timer)
 bool bUpdating
           used in net games
 bool bUseRumble
           auto center view afer walking a while
 bool bWalkCenterView
           auto center view afer walking a while
 bool bZeroRoll
           free camera when in behindview mode (for checking out player models and animations)
 bool bZooming
           if true, don't automatically switch to picked up weapon
 float bobtime
           Used to store everything that should be usefull for on-line ladder/rankings
 input byte
           Delay time until can restart
 float fAdjustAimTrans
           to handle crosshair/Adjust aim transition
 float fLookSpeed
           auto center view afer walking a while
 input float
           Delay time until can restart
 int iAutoAimMode
           0 = off, 1 = on.
 HUD myHUD
           heads up display info
 bool ngSecretSet
           freed moves, available for buffering
 string ngWorldSecret
           freed moves, available for buffering

States
Dead, GameEnded, WaitingForPawn, Player, Player, PlayerWaiting, PlayerWaiting, Spectating, BaseSpectating, PlayerHelicoptering, PlayerFlying, PlayerSwimming, PlayerSpidering, PlayerClimbing, PlayerWalking

Function Summary
 void ActivateInventoryItem(class InvItem)
     
// Activate specific inventory item
 void ActivateItem()
     
// The player wants to active selected item
 rotator AdjustAim(Ammunition FiredAmmunition, vector projStart, int aimerror)
     
/* AdjustAim()
Calls this version for player aiming help.
Aimerror not used in this version.
Only adjusts aiming at pawns
*/
 rotator AdjustAimForDisplay(Ammunition FiredAmmunition, vector projStart)
     
// if not leading, add slight random error ( significant at long distances )
		if ( !bNoZAdjust )
		{
			AimRot = rotator(AimSpot - projStart);
			if ( FOVAngle < DefaultFOV - 8 )
				AimRot.Yaw = AimRot.Yaw + 200 - Rand(400);
			else
				AimRot.Yaw = AimRot.Yaw + 375 - Rand(750);
			return AimRot;
		}
	}
	else if ( !FastTrace(projStart + 0.9 * bestDist * Normal(FireDir), projStart) )
	{
		FireDir = BestTarget.Location - projStart;
		AimSpot = projStart + bestDist * Normal(FireDir);
	}

	return rotator(AimSpot - projStart);
}
*/
 void AdjustRadius(float MaxMove)
 void AdjustView(float DeltaTime)
     
// Player view.
// Compute the rendering viewpoint for the player.
//
 void AltFire(optional float)
     
// The player wants to alternate-fire.
 void AskForPawn()
 eAttitude AttitudeTo(Pawn Other)
 void AttribPadToViewport()
 void BehindView(Bool B)
 void CalcBehindView(out vector, out rotator, float Dist)
 void CalcFirstPersonView(out vector, out rotator)
     
// First-person view.
	CameraRotation = Rotation;
	CameraLocation = CameraLocation + Pawn.EyePosition() + WalkBob + ShakeOffset;
}*/
 void CalcFirstPersonView(out vector, out rotator)
     
// First-person view.
	CameraRotation = Rotation;
	CameraLocation = CameraLocation + Pawn.EyePosition() + WalkBob + ShakeOffset;
}*/
 void ChangeName(string S)
 void ChangeSetHand(string S)
 void ChangeTeam(int N)
 void ChangedWeapon()
     
// Just changed to pendingWeapon
 void CheckBob(float DeltaTime, float Speed2D, vector Y)
     
{
	if ( Speed2D < 10 )
		BobTime += 0.2 * DeltaTime;
	else
		BobTime += DeltaTime * (0.3 + 0.7 * Speed2D/Pawn.GroundSpeed);
	WalkBob = Y * 0.4 * Bob * Speed2D * sin(8 * BobTime);
	AppliedBob = AppliedBob * (1 - FMin(1, 16 * deltatime));
	if ( Speed2D < 10 )
		WalkBob.Z = AppliedBob;
	else
		WalkBob.Z = AppliedBob + 0.3 * Bob * Speed2D * sin(16 * BobTime);
	if ( LandBob > 0.01 )
	{
		AppliedBob += FMin(1, 16 * deltatime) * LandBob;
		LandBob *= (1 - 8*Deltatime);
	}
}*/
 void CheckBob(float DeltaTime, float Speed2D, vector Y)
     
{
	if ( Speed2D < 10 )
		BobTime += 0.2 * DeltaTime;
	else
		BobTime += DeltaTime * (0.3 + 0.7 * Speed2D/Pawn.GroundSpeed);
	WalkBob = Y * 0.4 * Bob * Speed2D * sin(8 * BobTime);
	AppliedBob = AppliedBob * (1 - FMin(1, 16 * deltatime));
	if ( Speed2D < 10 )
		WalkBob.Z = AppliedBob;
	else
		WalkBob.Z = AppliedBob + 0.3 * Bob * Speed2D * sin(16 * BobTime);
	if ( LandBob > 0.01 )
	{
		AppliedBob += FMin(1, 16 * deltatime) * LandBob;
		LandBob *= (1 - 8*Deltatime);
	}
}*/
 void CheckShake(out float, out float, out float, out float)
     
/*
 void ClearProgressMessages()
 void ClientAdjustGlow(float scale, vector fog)
 void ClientAdjustPosition(float TimeStamp, name newState, EPhysics newPhysics, float NewLocX, float NewLocY, float NewLocZ, float NewVelX, float NewVelY, float NewVelZ, Actor NewBase)
     
/* ClientAdjustPosition
- pass newloc and newvel in components so they don't get rounded
*/
 void ClientFilter(Color FC, color FCW, float FCS)
 void ClientFlash(float scale, vector fog)
 void ClientGotoState(name NewState, name NewLabel)
     
/* ClientGotoState()
server uses this to force client into NewState
*/
 void ClientHighLight(color TargetColor, float TargetHighLight, optional Material)
 void ClientInstantFlash(float scale, vector fog)
 
simulated
ClientPlaySound(sound ASound, optional bool)
     
//Play a sound client side (so only client will hear it
 
simulated
ClientReliablePlaySound(sound ASound, optional bool)
 void ClientReplicateSkins(Material Skin1, optional Material, optional Material, optional Material)
 void ClientRestart()
 void ClientSetBehindView(bool B)
 void ClientSetFixedCamera(bool B)
 void ClientShake(vector ShakeRoll, vector OffsetMag, vector ShakeRate, float OffsetTime)
     
/* ClientShake()
Function called on client to shake view.
Only ShakeView() should call ClientShake()
*/
 event ClientTravel(string URL, ETravelType TravelType, bool bItems)
 void ClientUpdatePosition()
 void ClientVoiceMessage(PlayerReplicationInfo Sender, PlayerReplicationInfo Recipient, name messagetype, byte messageID)
     
{
	Local Vector WBob;

	WBob = BobDamping * WalkBob;
	WBob.Z = (0.45 + 0.55 * BobDamping) * WalkBob.Z;

	return (WBob + 0.9 * ShakeOffset);
}*/
 int CompressAccel(int C)
 string ConsoleCommand(string Command)
 void CopyToClipboard(string Text)
     
// Execute a console command in the context of this player, then forward to Actor.ConsoleCommand.
 void EndZoom()
 void EnterStartState()
 void FOV(float F)
 int FindStairRotation(float DeltaTime)
     
/* FindStairRotation()
returns an integer to use as a pitch to orient player view along current ground (flat, up, or down)
*/
 void Fire(optional float)
     
// The player wants to fire.
 void FixFOV()
 void ForceDeathUpdate()
     
/* ForceDeathUpdate()
Make sure ClientAdjustPosition immediately informs client of pawn's death
*/
 void ForceReload()
 string GetDefaultURL(string Option)
 LevelInfo GetEntryLevel()
 int GetFacingDirection()
     
/* GetFacingDirection()
returns direction faced relative to movement dir
0 = forward
16384 = right
32768 = back
49152 = left
*/
 SavedMove GetFreeMove()
 int GetPadNumber()
     
// Pad management
 string GetPlayerNetworkAddress()
 void GivePawn(Pawn NewPawn)
 void HandlePickup(Pickup pick)
 void HandleWalking()
     
{
	if ( Pawn != None )
		Pawn.SetWalking(((bRun != 0) || (bDuck != 0)) && !Region.Zone.IsA('WarpZoneInfo'));
}*/
 void HandleWalking()
     
{
	if ( Pawn != None )
		Pawn.SetWalking(((bRun != 0) || (bDuck != 0)) && !Region.Zone.IsA('WarpZoneInfo'));
}*/
 void Jump(optional float)
     
//*************************************************************************************
// Normal gameplay execs
// Type the name of the exec function at the console to execute it
 void LocalTravel(string URL)
 void LongClientAdjustPosition(float TimeStamp, name newState, EPhysics newPhysics, float NewLocX, float NewLocY, float NewLocZ, float NewVelX, float NewVelY, float NewVelZ, Actor NewBase, float NewFloorX, float NewFloorY, float NewFloorZ)
     
/* LongClientAdjustPosition
long version, when care about pawn's floor normal
*/
 void MoveAutonomous(float DeltaTime, bool NewbRun, bool NewbDuck, bool NewbPressedJump, eDoubleClickDir DoubleClickMove, vector newAccel, rotator DeltaRot)
 void Name(string S)
 void NextWeapon()
     
/* NextWeapon()
- switch to next inventory group weapon
*/
 bool NotifyLanded(vector HitNormal)
 void OptimizeInputBindings()
     
// "Compile" the commands associated with each input key
 string PasteFromClipboard()
 void Pause()
     
/* Pause()
Command to try to pause the game.
*/
 void PawnDied()
     
// unpossessed a pawn (because pawn was killed)
 
simulated
PlayBeepSound()
 void PlayerMove(float DeltaTime)
 void Possess(Pawn aPawn)
     
// Possess a pawn
 void PrevItem()
     
// The player wants to select previous item
 void PrevWeapon()
     
/* PrevWeapon()
- switch to previous inventory group weapon
*/
 void ProcessMove(float DeltaTime, vector newAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
 void QuickLoad()
     
/* QuickLoad()
Load game from slot 9
*/
 void QuickSave()
     
/* QuickSave()
Save game to slot 9
*/
 void ReplicateMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
     
//
// Replicate this client's desired movement to the server.
//
 void Reset()
     
/* Reset()
reset actor to initial state - used when restarting level without reloading.
*/
 void ResetFOV()
 void ResetKeyboard()
 void Restart()
 void RestartLevel()
 void Say(string Msg)
     
// Send a message to all players.
 void ServerMove()
     
/*
========================================================================
Here's how player movement prediction, replication and correction works in network games:

Every tick, the PlayerTick() function is called.  It calls the PlayerMove() function (which is implemented
in various states).  PlayerMove() figures out the acceleration and rotation, and then calls ProcessMove()
(for single player or listen servers), or ReplicateMove() (if its a network client).

ReplicateMove() saves the move (in the PendingMove list), calls ProcessMove(), and then replicates the move
to the server by calling the replicated 
 void ServerMove()
     
/*
========================================================================
Here's how player movement prediction, replication and correction works in network games:

Every tick, the PlayerTick() function is called.  It calls the PlayerMove() function (which is implemented
in various states).  PlayerMove() figures out the acceleration and rotation, and then calls ProcessMove()
(for single player or listen servers), or ReplicateMove() (if its a network client).

ReplicateMove() saves the move (in the PendingMove list), calls ProcessMove(), and then replicates the move
to the server by calling the replicated 
 void ServerRestartGame()
 void ServerSetHandedness(float hand)
     
// ------------------------------------------------------------------------
 void SetFOV(float NewFOV)
 void SetFOVAngle(float newFOV)
 void SetHand()
 bool SetPause(BOOL bPause)
     
/* SetPause()
 Try to pause game; returns success indicator.
 Replicated to server in network games.
 */
 void SetViewTarget(Actor NewViewTarget)
 void ShakeView(float shaketime, float RollMag, vector OffsetMag, float RollRate, vector OffsetRate, float OffsetTime)
     
/* ShakeView()
Call this function to shake the player's view
shaketime = how long to roll view
RollMag = how far to roll view as it shakes
OffsetMag = max view offset
RollRate = how fast to roll view
OffsetRate = how fast to offset view
OffsetTime = how long to offset view (number of shakes)
*/
 void ShortClientAdjustPosition(float TimeStamp, name newState, EPhysics newPhysics, float NewLocX, float NewLocY, float NewLocZ, Actor NewBase)
     
/* ShortClientAdjustPosition
bandwidth saving version, when velocity is zeroed
*/
 void ShortServerMove(float TimeStamp, vector ClientLoc, bool NewbRun, bool NewbDuck, bool NewbJumpStatus, byte ClientRoll, int View)
     
/* ShortServerMove()
compressed version of server move for bandwidth saving
*/
 void SpawnDefaultHUD()
     
/* SpawnDefaultHUD()
Spawn a HUD (make sure that PlayerController always has valid HUD, even if \
ClientSetHUD() hasn't been called\
*/
 void Speech(int Type, int Index, int Callsign)
     
// Send a voice message of a certain type to a certain player.
 void StartZoom()
 void StopZoom()
 void Suicide()
 void SwitchLevel(string URL)
 void SwitchTeam()
 void SwitchWeapon(byte F)
     
// The player wants to switch to weapon group number F.
 void TeamSay(string Msg)
 void ThrowWeapon()
     
/* ThrowWeapon()
Throw out current weapon, and switch to a new weapon
*/
 void ToggleZoom()
     
// ------------------------------------------------------------------------
// Zooming/FOV change functions
 void TurnAround()
 bool TurnTowardNearestEnemy()
 void Typing(bool bTyping)
 void UnPossess()
     
// unpossessed a pawn (not because pawn was killed)
 void UpdateBob(float F)
 void UpdateRotation(float DeltaTime, float maxPitch)
 void UpdateURL(string NewOption, string NewValue, bool bSaveDefault)
 void Use()
     
// The player wants to use something in the level.
 void VeryShortClientAdjustPosition(float TimeStamp, float NewLocX, float NewLocY, float NewLocZ, Actor NewBase)
     
/* VeryShortClientAdjustPosition
bandwidth saving version, when velocity is zeroed, and pawn is walking
*/
 void ViewFlash(float DeltaTime)
     
{
	local vector goalFog;
	local float goalscale, delta;

	delta = FMin(0.1, DeltaTime);
	goalScale = 1 + DesiredFlashScale + ConstantGlowScale;
	goalFog = DesiredFlashFog + ConstantGlowFog;

	if ( Pawn != None )
	{
		goalScale += Pawn.HeadVolume.ViewFlash.X;
		goalFog += Pawn.HeadVolume.ViewFog;
	}

	DesiredFlashScale -= DesiredFlashScale * 2 * delta;
	DesiredFlashFog -= DesiredFlashFog * 2 * delta;
	FlashScale.X += (goalScale - FlashScale.X + InstantFlash) * 10 * delta;
	FlashFog += (goalFog - FlashFog + InstantFog) * 10 * delta;
	InstantFlash = 0;
	InstantFog = vect(0,0,0);

	if ( FlashScale.X > 0.981 )
		FlashScale.X = 1;
	FlashScale = FlashScale.X * vect(1,1,1);

	if ( FlashFog.X < 0.019 )
		FlashFog.X = 0;
	if ( FlashFog.Y < 0.019 )
		FlashFog.Y = 0;
	if ( FlashFog.Z < 0.019 )
		FlashFog.Z = 0;
}*/
 void ViewFlash(float DeltaTime)
     
{
	local vector goalFog;
	local float goalscale, delta;

	delta = FMin(0.1, DeltaTime);
	goalScale = 1 + DesiredFlashScale + ConstantGlowScale;
	goalFog = DesiredFlashFog + ConstantGlowFog;

	if ( Pawn != None )
	{
		goalScale += Pawn.HeadVolume.ViewFlash.X;
		goalFog += Pawn.HeadVolume.ViewFog;
	}

	DesiredFlashScale -= DesiredFlashScale * 2 * delta;
	DesiredFlashFog -= DesiredFlashFog * 2 * delta;
	FlashScale.X += (goalScale - FlashScale.X + InstantFlash) * 10 * delta;
	FlashFog += (goalFog - FlashFog + InstantFog) * 10 * delta;
	InstantFlash = 0;
	InstantFog = vect(0,0,0);

	if ( FlashScale.X > 0.981 )
		FlashScale.X = 1;
	FlashScale = FlashScale.X * vect(1,1,1);

	if ( FlashFog.X < 0.019 )
		FlashFog.X = 0;
	if ( FlashFog.Y < 0.019 )
		FlashFog.Y = 0;
	if ( FlashFog.Z < 0.019 )
		FlashFog.Z = 0;
}*/
 void ViewShake(float DeltaTime)
     
// modify shake offset
		ShakeOffset.X += DeltaTime * ShakeOffsetRate.X;
		CheckShake(MaxShakeOffset.X, ShakeOffset.X, ShakeOffsetRate.X, ShakeOffsetTime.X);

		ShakeOffset.Y += DeltaTime * ShakeOffsetRate.Y;
		CheckShake(MaxShakeOffset.Y, ShakeOffset.Y, ShakeOffsetRate.Y, ShakeOffsetTime.Y);

		ShakeOffset.Z += DeltaTime * ShakeOffsetRate.Z;
		CheckShake(MaxShakeOffset.Z, ShakeOffset.Z, ShakeOffsetRate.Z, ShakeOffsetTime.Z);
	}

	ViewRotation = Rotation;

	if ( ShakeRollRate != 0 )
	{
		ViewRotation.Roll = ((ViewRotation.Roll & 65535) + ShakeRollRate * DeltaTime) & 65535;
		if ( ViewRotation.Roll > 32768 )
			ViewRotation.Roll -= 65536;
		FRoll = ViewRotation.Roll;
		CheckShake(MaxShakeRoll, FRoll, ShakeRollRate, ShakeRollTime);
		ViewRotation.Roll = FRoll;
	}
	else if ( bZeroRoll )
		ViewRotation.Roll = 0;
	SetRotation(ViewRotation);
}*/
 void ViewShake(float DeltaTime)
     
// modify shake offset
		ShakeOffset.X += DeltaTime * ShakeOffsetRate.X;
		CheckShake(MaxShakeOffset.X, ShakeOffset.X, ShakeOffsetRate.X, ShakeOffsetTime.X);

		ShakeOffset.Y += DeltaTime * ShakeOffsetRate.Y;
		CheckShake(MaxShakeOffset.Y, ShakeOffset.Y, ShakeOffsetRate.Y, ShakeOffsetTime.Y);

		ShakeOffset.Z += DeltaTime * ShakeOffsetRate.Z;
		CheckShake(MaxShakeOffset.Z, ShakeOffset.Z, ShakeOffsetRate.Z, ShakeOffsetTime.Z);
	}

	ViewRotation = Rotation;

	if ( ShakeRollRate != 0 )
	{
		ViewRotation.Roll = ((ViewRotation.Roll & 65535) + ShakeRollRate * DeltaTime) & 65535;
		if ( ViewRotation.Roll > 32768 )
			ViewRotation.Roll -= 65536;
		FRoll = ViewRotation.Roll;
		CheckShake(MaxShakeRoll, FRoll, ShakeRollRate, ShakeRollTime);
		ViewRotation.Roll = FRoll;
	}
	else if ( bZeroRoll )
		ViewRotation.Roll = 0;
	SetRotation(ViewRotation);
}*/
 vector WeaponBob(float BobDamping)
     
/* --> Become a 100% C++ virtual function
 void damageAttitudeTo(Pawn Other, float Damage)


State Dead Function Summary
 void ChangeAlwaysMouseLook(Bool B)
 void ChangeStairLook(bool B)
     
//------------------------------------------------------------------------------
// Control options
 void SetNGSecret(string newSecret)
 string GetNGSecret()
     
//------------------------------------------------------------------------------
// ngStats Accessors
 void EndState()
 void BeginState()
 void Timer2()
 void Timer()
 void FindGoodView()
 void PlayerMove(float DeltaTime)
 void ServerMove(float TimeStamp, vector Accel, vector ClientLoc, bool NewbRun, bool NewbDuck, bool NewbJumpStatus, eDoubleClickDir DoubleClickMove, byte ClientRoll, int View, optional byte, optional int)
 void AltFire(optional float)
 void Fire(optional float)
 void ServerRestartPlayer()


State GameEnded Function Summary
 void BeginState()
 void Timer()
 void FindGoodView()
 void ServerMove(float TimeStamp, vector InAccel, vector ClientLoc, bool NewbRun, bool NewbDuck, bool NewbJumpStatus, eDoubleClickDir DoubleClickMove, byte ClientRoll, int View, optional byte, optional int)
 void PlayerMove(float DeltaTime)
 void AltFire(optional float)
 void Fire(optional float)
 void ServerReStartGame()
 void ThrowWeapon()


State WaitingForPawn Function Summary
 void EndState()
 void BeginState()
 void Timer()
 void PlayerTick(float DeltaTime)
 void LongClientAdjustPosition(float TimeStamp, Name newState, EPhysics newPhysics, float NewLocX, float NewLocY, float NewLocZ, float NewVelX, float NewVelY, float NewVelZ, Actor NewBase, float NewFloorX, float NewFloorY, float NewFloorZ)
 void AltFire(optional float)
 void Fire(optional float)


State Player Function Summary
 void UnFire(optional float)
     
    {
      if (!Player.LocalInteractions[0].IsInState('UWindows'))
        ServerReStartPlayer();
    }
    exec 
 void Fire(optional float)
     
="$player);
    }
    exec 


State Player Function Summary
 void BeginState()
     
="$player);
    }

    


State PlayerWaiting Function Summary
 void EndState()
     
{
    


State PlayerWaiting Function Summary
 void BeginState()
 void EndState()
 void AltFire(optional float)
 void Fire(optional float)
 void ServerReStartPlayer()
 void ChangeTeam(int N)
 void Suicide()
 void Jump(optional float)
 void PlayerMove(float DeltaTime)
 void ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)


State Spectating Function Summary
 void EndState()
 void BeginState()
 void AltFire(optional float)
     
// Return to spectator's own camera.
 void Fire(optional float)
 void PrevWeapon()
 void NextWeapon()


State BaseSpectating Function Summary
 void PlayerMove(float DeltaTime)
 void ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)


State PlayerHelicoptering Function Summary
 void PlayerMove(float DeltaTime)


State PlayerFlying Function Summary
 void BeginState()
 void PlayerMove(float DeltaTime)


State PlayerSwimming Function Summary
 void BeginState()
 void Timer()
 void PlayerMove(float DeltaTime)
 void ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
 bool NotifyPhysicsVolumeChange(PhysicsVolume NewVolume)
 bool NotifyLanded(vector HitNormal)
 bool WantsSmoothedView()


State PlayerSpidering Function Summary
 void EndState()
 void BeginState()
 void PlayerMove(float DeltaTime)
 void ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
 bool NotifyPhysicsVolumeChange(PhysicsVolume NewVolume)
 bool NotifyLanded(vector HitNormal)
 void UpdateRotation(float DeltaTime, float maxPitch)
     
// if spider mode, update rotation based on floor


State PlayerClimbing Function Summary
 void EndState()
 void BeginState()
 void PlayerMove(float DeltaTime)
 void ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
 bool NotifyPhysicsVolumeChange(PhysicsVolume NewVolume)


State PlayerWalking Function Summary
 void EndState()
 void BeginState()
 void PlayerMove(float DeltaTime)
 void ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
 bool NotifyPhysicsVolumeChange(PhysicsVolume NewVolume)



Source Code


00001	//=============================================================================
00002	// PlayerController
00003	//
00004	// PlayerControllers are used by human players to control pawns.
00005	//
00006	// This is a built-in Unreal class and it shouldn't be modified.
00007	// CHANGENOTE: All Changes since v739 in this class are related to the Weapon code update, except
00008	// for the change in Possess().
00009	//=============================================================================
00010	class PlayerController extends Controller
00011	  config(user)
00012	  native
00013	  nativereplication;
00014	
00015	// Player info.
00016	var const player Player;
00017	
00018	// player input control
00019	var globalconfig bool bLookUpStairs;  // look up/down stairs (player)
00020	var globalconfig bool bSnapToLevel;   // Snap to level eyeheight when not mouselooking
00021	var globalconfig bool bAlwaysMouseLook;
00022	var globalconfig bool bKeyboardLook;  // no snapping when true
00023	var bool bCenterView;
00024	
00025	// Player control flags
00026	var bool bBehindView;                 // Outside-the-player view.
00027	var bool bFrozen;                     // set when game ends or player dies to temporarily prevent player from restarting (until cleared by timer)
00028	var bool bPressedJump;
00029	var bool bUpdatePosition;
00030	var bool bIsTyping;
00031	var bool bFixedCamera;                // used to fix camera in position (to view animations)
00032	var bool bJumpStatus;                 // used in net games
00033	var bool bUpdating;
00034	var globalconfig bool bNeverSwitchOnPickup;  // if true, don't automatically switch to picked up weapon
00035	
00036	var bool bZooming;
00037	var bool bOnlySpectator;              // This controller is not allowed to possess pawns
00038	
00039	var globalconfig bool bAlwaysLevel;
00040	var bool bSetTurnRot;
00041	var bool bCheatFlying;                // instantly stop in flying mode
00042	var bool bFreeCamera;                 // free camera when in behindview mode (for checking out player models and animations)
00043	var bool bZeroRoll;
00044	
00045	// XIII Added
00046	//var config bool bAltDuckMode;         // True = Crouch toggle, False = Crouch on/off
00047	var bool bLocked;                     // adjustaim locked someone (to handle transitions between crosshair pos
00048	
00049	var bool bDontUseVolumeFog;
00050	var bool bIsInMenu;
00051	
00052	var globalconfig bool bAutoPickup;    // AutoPickup objects.
00053	var globalconfig int iAutoAimMode;    // 0 = off, 1 = on.
00054	
00055	// XIIIUNUSED var float AimingHelp;
00056	var float WaitDelay;                  // Delay time until can restart
00057	
00058	var input float
00059	  aBaseX, aBaseY, aBaseZ,  aMouseX, aMouseY,
00060	  aForward, aTurn, aStrafe, aUp, aLookUp;
00061	
00062	var input byte
00063	  bStrafe, bSnapLevel, bLook, bFreeLook, bTurn180, bTurnToNearest;
00064	
00065	// XIII Additional inputs
00066	var input byte bUp, bDown, bLeft, bRight;   // check if KEYs are pressed and not pad.
00067	var input byte b90Left, b90Right, b180Turn; // To make us turn fast to left or right.
00068	var input byte bAltDuck;                    // To enable the AltDuck Mode
00069	var input byte bAltJump;                    // To be used for Hook Mode using Duck/Jump
00070	var input byte bAltRun;                     //
00071	var globalconfig bool bInverseLook;   // Inverse FlightSim/Std Pad look axis
00072	var globalconfig bool bWalkCenterView;// auto center view afer walking a while
00073	//var float Ym,Lm,Sm,Tm;  // DBUG used to check max value of inputs
00074	enum eConfigType
00075	{
00076	  CT_StrafeLookSameAxis,
00077	  CT_StrafeLookNotSameAxis,
00078	};
00079	var config eConfigType ConfigType;
00080	var config float fLookSpeed;
00081	var config bool bUseRumble;
00082	var config int UserPadConfig;
00083	//
00084	var EDoubleClickDir DoubleClickDir;   // direction of movement key double click (for special moves)
00085	
00086	// Camera info.
00087	var int ShowFlags;
00088	var int Misc1,Misc2;
00089	var int RendMap;
00090	var float OrthoZoom;                  // Orthogonal/map view zoom factor.
00091	var const actor ViewTarget;
00092	var float CameraDist;                 // multiplier for behindview camera dist
00093	
00094	var float DesiredFOV;
00095	var globalconfig float DefaultFOV;
00096	var float ZoomLevel;
00097	
00098	// Screen flashes
00099	var vector FlashScale, FlashFog;
00100	var float DesiredFlashScale, ConstantGlowScale, InstantFlash;
00101	var vector DesiredFlashFog, ConstantGlowFog, InstantFog;
00102	
00103	// Filter.
00104	var color FilterColor;
00105	var color FilterColorWanted;
00106	var float FilterColorSpeed;
00107	var int FilterInternalInc;
00108	
00109	// Remote Pawn ViewTargets
00110	var rotator TargetViewRotation;
00111	var float TargetEyeHeight;
00112	var vector TargetWeaponViewOffset;
00113	
00114	var HUD myHUD;  // heads up display info
00115	
00116	var float LastPlaySound;
00117	var globalconfig int AnnouncerVolume;
00118	
00119	// Move buffering for network games.  Clients save their un-acknowledged moves in order to replay them
00120	// when they get position updates from the server.
00121	var SavedMove SavedMoves;  // buffered moves pending position updates
00122	var SavedMove FreeMoves;  // freed moves, available for buffering
00123	var SavedMove PendingMove;
00124	var float CurrentTimeStamp,LastUpdateTime,ServerTimeStamp,TimeMargin, ClientUpdateTime;
00125	var globalconfig float MaxTimeMargin;
00126	var Weapon OldClientWeapon;
00127	var int WeaponUpdate;
00128	
00129	// Progess Indicator - used by the engine to provide status messages (HUD is responsible for displaying these).
00130	var string ProgressMessage[4];
00131	var color ProgressColor[4];
00132	var float ProgressTimeOut;
00133	
00134	// Localized strings
00135	var localized string QuickSaveString;
00136	var localized string NoPauseMessage;
00137	var localized string ViewingFrom;
00138	var localized string OwnCamera;
00139	
00140	// ReplicationInfo
00141	var GameReplicationInfo GameReplicationInfo;
00142	
00143	// ngWorldStats Logging
00144	var globalconfig private string ngWorldSecret;
00145	var globalconfig bool ngSecretSet;
00146	var bool ReceivedSecretChecksum;
00147	var PlayerStats PlayerStat;   // Used to store everything that should be usefull for on-line ladder/rankings
00148	                              // Server side only (no replication).
00149	
00150	var class<LocalMessage> LocalMessageClass;
00151	
00152	var globalconfig float Bob;
00153	var float LandBob, AppliedBob;
00154	var float bobtime;
00155	var vector WalkBob;
00156	
00157	// view shaking (affects roll, and offsets camera position)
00158	var float MaxShakeRoll; // max magnitude to roll camera
00159	var vector MaxShakeOffset; // max magnitude to offset camera position
00160	var float ShakeRollRate;  // rate to change roll
00161	var vector ShakeOffsetRate;
00162	var vector ShakeOffset; //current magnitude to offset camera from shake
00163	var float ShakeRollTime; // how long to roll.  if value is < 1.0, then MaxShakeOffset gets damped by this, else if > 1 then its the number of times to repeat undamped
00164	var vector ShakeOffsetTime;
00165	/* iKi=> */
00166	var vector MaxShakeFrame, ShakeFrame, ShakeFrameRate;
00167	var float ShakeFrameTime;
00168	/* <=iKi */
00169	
00170	var Pawn TurnTarget;
00171	var config int EnemyTurnSpeed;
00172	var int GroundPitch;
00173	var rotator TurnRot180;
00174	
00175	var vector OldFloor;    // used by PlayerSpider mode - floor for which old rotation was based;
00176	
00177	// Components ( inner classes )
00178	var CheatManager  CheatManager;  // Object within playercontroller that manages "cheat" commands
00179	var class<CheatManager> CheatClass;    // class of my CheatManager
00180	var transient PlayerInput PlayerInput;  // Object within playercontroller that manages player input.
00181	var class<PlayerInput> InputClass;    // class of my PlayerInput
00182	
00183	// Demo recording view rotation
00184	var int DemoViewPitch;
00185	var int DemoViewYaw;
00186	
00187	// Use alpha filter.
00188	var byte UseVignetteFilter;
00189	// Use highlight filter.
00190	var byte UseVignetteHighlight;
00191	// Alpha filter color.
00192	var color VignetteColor;
00193	// Highlight intensity.
00194	var float VignetteHighLight;
00195	// Alpha filter texture.
00196	var material VignetteMaterial;
00197	
00198	var vector OldAdjustAim;          // Used to smooth autoaim, Aim to use when firing non-projectiles
00199	var vector ViewAdjustAim;         // Used to smooth Weapon rot on screen
00200	//var float LastOldAdjustAimUpdate; // to update it only once per frame (if called by interaction and weapon at the same frame don't update twice)
00201	var float fAdjustAimTrans;        // to handle crosshair/Adjust aim transition
00202	var vector MemAim;                // memorize aim when switching bLocked
00203	var vector AdjustedAimForFiring;  // Aim to use when firing Projectiles (because display don't show anticipation
00204	var actor BestTarget;             // to memorize the best target and use it in interaction
00205	var actor OldBestTarget;          // to memorize the best target and use it in interaction
00206	
00207	var float DeltaT;                 // to enable using it anywhere (needed for death camera sfxs  at least)
00208	
00209	replication
00210	{
00211		// Things the server should send to the client.
00212		reliable if( bNetDirty && bNetOwner && Role==ROLE_Authority )
00213			ViewTarget, GameReplicationInfo;
00214		unreliable if ( bNetOwner && Role==ROLE_Authority && (ViewTarget != Pawn) && (Pawn(ViewTarget) != None) )
00215			TargetViewRotation, TargetEyeHeight, TargetWeaponViewOffset;
00216		reliable if( bDemoRecording && Role==ROLE_Authority )
00217			DemoViewPitch, DemoViewYaw;
00218	
00219		// Functions server can call.
00220		reliable if( Role==ROLE_Authority )
00221			ClientSetHUD,ClientReliablePlaySound, FOV, StartZoom,
00222			ToggleZoom, StopZoom, EndZoom, ClientRestart,
00223			ClientReplicateSkins, ClientAdjustGlow,
00224			ClientSetBehindView, ClientSetFixedCamera, ClearProgressMessages,
00225			SetProgressMessage, SetProgressTime,
00226			GivePawn, ClientGotoState;
00227		reliable if ( (Role == ROLE_Authority) && (!bDemoRecording || (bClientDemoRecording && bClientDemoNetFunc)) )
00228			ClientMessage, TeamMessage, ReceiveLocalizedMessage;
00229		unreliable if( Role==ROLE_Authority && !bDemoRecording )
00230			ClientPlaySound;
00231		reliable if( Role==ROLE_Authority && !bDemoRecording )
00232			ClientTravel;
00233		unreliable if( Role==ROLE_Authority )
00234			SetFOVAngle, ClientShake, ClientFlash, ClientInstantFlash, ClientFilter, ClientHighLight,
00235			ClientAdjustPosition, ShortClientAdjustPosition, VeryShortClientAdjustPosition, LongClientAdjustPosition;
00236	
00237		// Functions client can call.
00238		unreliable if( Role<ROLE_Authority )
00239			ShortServerMove, ServerMove, Say, TeamSay, ServerSetHandedness;
00240		reliable if( Role<ROLE_Authority )
00241			Speech, Pause, SetPause,
00242			PrevItem, ActivateItem, ServerReStartGame, AskForPawn,
00243			ChangeName, ChangeTeam, Suicide,
00244			ThrowWeapon, BehindView, Typing;
00245	}
00246	
00247	// Pad management
00248	native(538) static final function int GetPadNumber();
00249	native(537) static final function AttribPadToViewport();
00250	
00251	// "Compile" the commands associated with each input key
00252	native(535) static final function OptimizeInputBindings();
00253	
00254	native(519) static final function string GetPlayerNetworkAddress();
00255	native static function string ConsoleCommand( string Command );
00256	native(515) static final function LevelInfo GetEntryLevel();
00257	native(544) static final function ResetKeyboard();
00258	native(513) static final function SetViewTarget(Actor NewViewTarget);
00259	native static function event ClientTravel( string URL, ETravelType TravelType, bool bItems );
00260	native(546) static final function UpdateURL(string NewOption, string NewValue, bool bSaveDefault);
00261	native(510) static final function string GetDefaultURL(string Option);
00262	// Execute a console command in the context of this player, then forward to Actor.ConsoleCommand.
00263	native(507) static final function CopyToClipboard( string Text );
00264	native(506) static final function string PasteFromClipboard();
00265	
00266	/* FindStairRotation()
00267	returns an integer to use as a pitch to orient player view along current ground (flat, up, or down)
00268	*/
00269	native(524) static final function int FindStairRotation(float DeltaTime);
00270	
00271	event PostBeginPlay()
00272	{
00273		Super.PostBeginPlay();
00274		SpawnDefaultHUD();
00275		if (Level.LevelEnterText != "" )
00276			ClientMessage(Level.LevelEnterText);
00277	
00278		DesiredFOV = DefaultFOV;
00279		SetViewTarget(self);  // MUST have a view target!
00280		if ( Level.NetMode == NM_Standalone )
00281			CheatManager = new CheatClass;
00282	}
00283	
00284	/* SpawnDefaultHUD()
00285	Spawn a HUD (make sure that PlayerController always has valid HUD, even if \
00286	ClientSetHUD() hasn't been called\
00287	*/
00288	function SpawnDefaultHUD()
00289	{
00290		myHUD = spawn(class'HUD',self);
00291	}
00292	
00293	/* Reset()
00294	reset actor to initial state - used when restarting level without reloading.
00295	*/
00296	function Reset()
00297	{
00298		PawnDied();
00299		Super.Reset();
00300		SetViewTarget(self);
00301		bBehindView = false;
00302		WaitDelay = Level.TimeSeconds + 2;
00303		GotoState('PlayerWaiting');
00304	}
00305	
00306	/* InitInputSystem()
00307	Spawn the appropriate class of PlayerInput
00308	Only called for playercontrollers that belong to local players
00309	*/
00310	event InitInputSystem()
00311	{
00312		PlayerInput = new InputClass;
00313	}
00314	
00315	/* ClientGotoState()
00316	server uses this to force client into NewState
00317	*/
00318	function ClientGotoState(name NewState, name NewLabel)
00319	{
00320		GotoState(NewState,NewLabel);
00321	}
00322	
00323	function AskForPawn()
00324	{
00325	  Log(self@"AskForPawn"@Pawn@"InState"@GetStateName());
00326		if ( Pawn != None )
00327			GivePawn(Pawn);
00328		else if ( IsInState('GameEnded') )
00329			ClientGotoState('GameEnded', 'Begin');
00330		else if ( IsInState('Dead') )
00331		{
00332			bFrozen = false;
00333			ServerRestartPlayer();
00334		}
00335	}
00336	
00337	function GivePawn(Pawn NewPawn)
00338	{
00339		if ( NewPawn == None )
00340			return;
00341		Pawn = NewPawn;
00342		NewPawn.Controller = self;
00343		ClientRestart();
00344	}
00345	
00346	/* GetFacingDirection()
00347	returns direction faced relative to movement dir
00348	0 = forward
00349	16384 = right
00350	32768 = back
00351	49152 = left
00352	*/
00353	function int GetFacingDirection()
00354	{
00355		local vector X,Y,Z, Dir;
00356	
00357		GetAxes(Pawn.Rotation, X,Y,Z);
00358		Dir = Normal(Pawn.Acceleration);
00359		if ( Y Dot Dir > 0 )
00360			return ( 49152 + 16384 * (X Dot Dir) );
00361		else
00362			return ( 16384 - 16384 * (X Dot Dir) );
00363	}
00364	
00365	// Possess a pawn
00366	function Possess(Pawn aPawn)
00367	{
00368		if ( bOnlySpectator )
00369			return;
00370	
00371		SetRotation(aPawn.Rotation);
00372		aPawn.PossessedBy(self);
00373		Pawn = aPawn;
00374		Pawn.bStasis = false;
00375		PlayerReplicationInfo.bIsFemale = Pawn.bIsFemale;
00376		ServerSetHandedness(Handedness);
00377		Restart();
00378	}
00379	
00380	// unpossessed a pawn (not because pawn was killed)
00381	function UnPossess()
00382	{
00383		if ( Pawn != None )
00384		{
00385			SetLocation(Pawn.Location);
00386			Pawn.RemoteRole = ROLE_SimulatedProxy;
00387			Pawn.UnPossessed();
00388			if ( Viewtarget == Pawn )
00389				SetViewTarget(self);
00390		}
00391		Pawn = None;
00392		GotoState('Spectating');
00393	}
00394	
00395	// unpossessed a pawn (because pawn was killed)
00396	function PawnDied()
00397	{
00398		StopZoom();
00399		if ( Pawn != None )
00400			Pawn.RemoteRole = ROLE_SimulatedProxy;
00401		if ( ViewTarget == Pawn )
00402			bBehindView = true;
00403	
00404		Super.PawnDied();
00405	}
00406	
00407	// called when kicked 
00408	simulated event IAmKicked();
00409	
00410	
00411	function ClientSetHUD(class<HUD> newHUDType, class<Scoreboard> newScoringType)
00412	{
00413		local HUD NewHUD;
00414	
00415		if ( (myHUD == None) || ((newHUDType != None) && (newHUDType != myHUD.Class)) )
00416		{
00417			NewHUD = spawn(newHUDType, self);
00418			if ( NewHUD != None )
00419			{
00420				if ( myHUD != None )
00421					myHUD.Destroy();
00422				myHUD = NewHUD;
00423			}
00424		}
00425		if ( (myHUD != None) && (newScoringType != None) )
00426			MyHUD.SpawnScoreBoard(newScoringType);
00427	}
00428	
00429	function HandlePickup(Pickup pick)
00430	{
00431		ReceiveLocalizedMessage( pick.MessageClass, 0, None, None, pick.Class );
00432	}
00433	
00434	/*function ViewFlash(float DeltaTime)
00435	{
00436		local vector goalFog;
00437		local float goalscale, delta;
00438	
00439		delta = FMin(0.1, DeltaTime);
00440		goalScale = 1 + DesiredFlashScale + ConstantGlowScale;
00441		goalFog = DesiredFlashFog + ConstantGlowFog;
00442	
00443		if ( Pawn != None )
00444		{
00445			goalScale += Pawn.HeadVolume.ViewFlash.X;
00446			goalFog += Pawn.HeadVolume.ViewFog;
00447		}
00448	
00449		DesiredFlashScale -= DesiredFlashScale * 2 * delta;
00450		DesiredFlashFog -= DesiredFlashFog * 2 * delta;
00451		FlashScale.X += (goalScale - FlashScale.X + InstantFlash) * 10 * delta;
00452		FlashFog += (goalFog - FlashFog + InstantFog) * 10 * delta;
00453		InstantFlash = 0;
00454		InstantFog = vect(0,0,0);
00455	
00456		if ( FlashScale.X > 0.981 )
00457			FlashScale.X = 1;
00458		FlashScale = FlashScale.X * vect(1,1,1);
00459	
00460		if ( FlashFog.X < 0.019 )
00461			FlashFog.X = 0;
00462		if ( FlashFog.Y < 0.019 )
00463			FlashFog.Y = 0;
00464		if ( FlashFog.Z < 0.019 )
00465			FlashFog.Z = 0;
00466	}*/
00467	native(505) static final function ViewFlash(float DeltaTime);
00468	
00469	event ReceiveLocalizedMessage( class<LocalMessage> Message, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject )
00470	{
00471		Message.Static.ClientReceive( Self, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject );
00472	}
00473	
00474	event ClientMessage( coerce string S, optional Name Type )
00475	{
00476		if (Type == '')
00477			Type = 'Event';
00478		TeamMessage(PlayerReplicationInfo, S, Type);
00479	}
00480	
00481	event TeamMessage( PlayerReplicationInfo PRI, coerce string S, name Type  )
00482	{
00483		local string ConsoleString;
00484	
00485		//log("Teammessage with PRI "$PRI$" hud "$myHud$" Player "$Player$" console "$Player.console$" string "$S);
00486		ConsoleString = S;
00487		if ( (Type == 'Say') || (Type == 'TeamSay') )
00488			ConsoleString = PRI.PlayerName$": "$ConsoleString;
00489	
00490		Player.Console.Message( ConsoleString, 6.0 );
00491		myHUD.Message( PRI, S, Type );
00492	}
00493	
00494	simulated function PlayBeepSound();
00495	
00496	//Play a sound client side (so only client will hear it
00497	simulated function ClientPlaySound(sound ASound, optional bool bVolumeControl )
00498	{
00499		local int i;
00500	
00501		if ( !bVolumeControl )
00502			ViewTarget.PlaySound(ASound);
00503		else
00504			for ( i=0; i<AnnouncerVolume; i++ )
00505				ViewTarget.PlaySound(ASound);
00506	}
00507	
00508	simulated function ClientReliablePlaySound(sound ASound, optional bool bVolumeControl )
00509	{
00510		ClientPlaySound(ASound, bVolumeControl);
00511	}
00512	
00513	simulated event Destroyed()
00514	{
00515		local SavedMove Next;
00516	
00517		if ( Pawn != None )
00518		{
00519			Pawn.Health = 0;
00520			Pawn.Died( self, class'Suicided', Pawn.Location );
00521		}
00522		Super.Destroyed();
00523		myHud.Destroy();
00524	
00525		while ( FreeMoves != None )
00526		{
00527			Next = FreeMoves.NextMove;
00528			FreeMoves.Destroy();
00529			FreeMoves = Next;
00530		}
00531		while ( SavedMoves != None )
00532		{
00533			Next = SavedMoves.NextMove;
00534			SavedMoves.Destroy();
00535			SavedMoves = Next;
00536		}
00537	}
00538	
00539	// ------------------------------------------------------------------------
00540	// Zooming/FOV change functions
00541	
00542	function ToggleZoom()
00543	{
00544		if ( DefaultFOV != DesiredFOV )
00545			EndZoom();
00546		else
00547			StartZoom();
00548	}
00549	
00550	function StartZoom()
00551	{
00552		ZoomLevel = 0.0;
00553		bZooming = true;
00554	}
00555	
00556	function StopZoom()
00557	{
00558		bZooming = false;
00559	}
00560	
00561	function EndZoom()
00562	{
00563		bZooming = false;
00564		DesiredFOV = DefaultFOV;
00565	}
00566	
00567	function FixFOV()
00568	{
00569		FOVAngle = Default.DefaultFOV;
00570		DesiredFOV = Default.DefaultFOV;
00571		DefaultFOV = Default.DefaultFOV;
00572	}
00573	
00574	function SetFOV(float NewFOV)
00575	{
00576		DesiredFOV = NewFOV;
00577		FOVAngle = NewFOV;
00578	}
00579	
00580	function ResetFOV()
00581	{
00582		DesiredFOV = DefaultFOV;
00583		FOVAngle = DefaultFOV;
00584	}
00585	
00586	exec function FOV(float F)
00587	{
00588		if( (F >= 80.0) || (Level.Netmode==NM_Standalone) )
00589		{
00590			DefaultFOV = FClamp(F, 1, 170);
00591			DesiredFOV = DefaultFOV;
00592			SaveConfig();
00593		}
00594	}
00595	
00596	exec function ForceReload()
00597	{
00598		if ( (Pawn != None) && (Pawn.Weapon != None) )
00599			Pawn.Weapon.ForceReload();
00600	}
00601	
00602	// ------------------------------------------------------------------------
00603	// Messaging functions
00604	
00605	// Send a message to all players.
00606	exec function Say( string Msg )
00607	{
00608		Level.Game.Broadcast(self, Msg, 'Say');
00609	}
00610	
00611	exec function TeamSay( string Msg )
00612	{
00613		Level.Game.BroadcastTeam(self, Msg, 'Say');
00614	}
00615	// ------------------------------------------------------------------------
00616	
00617	function ServerSetHandedness( float hand)
00618	{
00619		Handedness = hand;
00620		if ( Pawn.Weapon != None )
00621			Pawn.Weapon.SetHand(Handedness);
00622	}
00623	
00624	function SetHand()
00625	{
00626		Pawn.Weapon.SetHand(Handedness);
00627		ServerSetHandedness(Handedness);
00628	}
00629	
00630	function ChangeSetHand( string S )
00631	{
00632		if ( S ~= "Left" )
00633			Handedness = -1;
00634		else if ( S~= "Right" )
00635			Handedness = 1;
00636		else if ( S ~= "Center" )
00637			Handedness = 0;
00638		else if ( S ~= "Hidden" )
00639			Handedness = 2;
00640		SetHand();
00641	}
00642	
00643	event PreClientTravel()
00644	{
00645	}
00646	
00647	function ClientSetFixedCamera(bool B)
00648	{
00649		bFixedCamera = B;
00650	}
00651	
00652	function ClientSetBehindView(bool B)
00653	{
00654		bBehindView = B;
00655	}
00656	
00657	function ClientReplicateSkins(Material Skin1, optional Material Skin2, optional Material Skin3, optional Material Skin4)
00658	{
00659		// do nothing (just loading other player skins onto client)
00660		log("Getting "$Skin1$", "$Skin2$", "$Skin3$", "$Skin4);
00661		return;
00662	}
00663	
00664	/*function CheckBob(float DeltaTime, float Speed2D, vector Y)
00665	{
00666		if ( Speed2D < 10 )
00667			BobTime += 0.2 * DeltaTime;
00668		else
00669			BobTime += DeltaTime * (0.3 + 0.7 * Speed2D/Pawn.GroundSpeed);
00670		WalkBob = Y * 0.4 * Bob * Speed2D * sin(8 * BobTime);
00671		AppliedBob = AppliedBob * (1 - FMin(1, 16 * deltatime));
00672		if ( Speed2D < 10 )
00673			WalkBob.Z = AppliedBob;
00674		else
00675			WalkBob.Z = AppliedBob + 0.3 * Bob * Speed2D * sin(16 * BobTime);
00676		if ( LandBob > 0.01 )
00677		{
00678			AppliedBob += FMin(1, 16 * deltatime) * LandBob;
00679			LandBob *= (1 - 8*Deltatime);
00680		}
00681	}*/
00682	native(504) static final function CheckBob(float DeltaTime, float Speed2D, vector Y);
00683	
00684	
00685	/* --> Become a 100% C++ virtual function
00686	function vector WeaponBob(float BobDamping)
00687	{
00688		Local Vector WBob;
00689	
00690		WBob = BobDamping * WalkBob;
00691		WBob.Z = (0.45 + 0.55 * BobDamping) * WalkBob.Z;
00692	
00693		return (WBob + 0.9 * ShakeOffset);
00694	}*/
00695	
00696	
00697	function ClientVoiceMessage(PlayerReplicationInfo Sender, PlayerReplicationInfo Recipient, name messagetype, byte messageID)
00698	{
00699		local VoicePack V;
00700	
00701		if ( (Sender == None) || (Sender.voicetype == None) || (Player.Console == None) )
00702			return;
00703	
00704		V = Spawn(Sender.voicetype, self);
00705		if ( V != None )
00706			V.ClientInitialize(Sender, Recipient, messagetype, messageID);
00707	}
00708	
00709	/* ForceDeathUpdate()
00710	Make sure ClientAdjustPosition immediately informs client of pawn's death
00711	*/
00712	function ForceDeathUpdate()
00713	{
00714		LastUpdateTime = Level.TimeSeconds - 10;
00715	}
00716	
00717	/* ShortServerMove()
00718	compressed version of server move for bandwidth saving
00719	*/
00720	function ShortServerMove
00721	(
00722		float TimeStamp,
00723		vector ClientLoc,
00724		bool NewbRun,
00725		bool NewbDuck,
00726		bool NewbJumpStatus,
00727		byte ClientRoll,
00728		int View
00729	)
00730	{
00731		ServerMove(TimeStamp,vect(0,0,0),ClientLoc,NewbRun,NewbDuck,NewbJumpStatus,DCLICK_None,ClientRoll,View);
00732	}
00733	
00734	/* ServerMove()
00735	- replicated function sent by client to server - contains client movement and firing info
00736	Passes acceleration in components so it doesn't get rounded.
00737	*/
00738	function ServerMove
00739	(
00740		float TimeStamp,
00741		vector InAccel,
00742		vector ClientLoc,
00743		bool NewbRun,
00744		bool NewbDuck,
00745		bool NewbJumpStatus,
00746		eDoubleClickDir DoubleClickMove,
00747		byte ClientRoll,
00748		int View,
00749		optional byte OldTimeDelta,
00750		optional int OldAccel
00751	)
00752	{
00753		local float DeltaTime, clientErr, OldTimeStamp;
00754		local rotator DeltaRot, Rot, ViewRot;
00755		local vector Accel, LocDiff, ClientVel, ClientFloor;
00756		local int maxPitch, ViewPitch, ViewYaw;
00757		local bool NewbPressedJump, OldbRun, OldbDuck;
00758		local eDoubleClickDir OldDoubleClickMove;
00759		local actor ClientBase;
00760		local ePhysics ClientPhysics;
00761	
00762		// If this move is outdated, discard it.
00763		if ( CurrentTimeStamp >= TimeStamp )
00764			return;
00765	
00766		// if OldTimeDelta corresponds to a lost packet, process it first
00767		if (  OldTimeDelta != 0 )
00768		{
00769			OldTimeStamp = TimeStamp - float(OldTimeDelta)/500 - 0.001;
00770			if ( CurrentTimeStamp < OldTimeStamp - 0.001 )
00771			{
00772				// split out components of lost move (approx)
00773				Accel.X = OldAccel >>> 23;
00774				if ( Accel.X > 127 )
00775					Accel.X = -1 * (Accel.X - 128);
00776				Accel.Y = (OldAccel >>> 15) & 255;
00777				if ( Accel.Y > 127 )
00778					Accel.Y = -1 * (Accel.Y - 128);
00779				Accel.Z = (OldAccel >>> 7) & 255;
00780				if ( Accel.Z > 127 )
00781					Accel.Z = -1 * (Accel.Z - 128);
00782				Accel *= 20;
00783	
00784				OldbRun = ( (OldAccel & 64) != 0 );
00785				OldbDuck = ( (OldAccel & 32) != 0 );
00786				NewbPressedJump = ( (OldAccel & 16) != 0 );
00787				if ( NewbPressedJump )
00788					bJumpStatus = NewbJumpStatus;
00789	
00790				switch (OldAccel & 7)
00791				{
00792					case 0:
00793						OldDoubleClickMove = DCLICK_None;
00794						break;
00795					case 1:
00796						OldDoubleClickMove = DCLICK_Left;
00797						break;
00798					case 2:
00799						OldDoubleClickMove = DCLICK_Right;
00800						break;
00801					case 3:
00802						OldDoubleClickMove = DCLICK_Forward;
00803						break;
00804					case 4:
00805						OldDoubleClickMove = DCLICK_Back;
00806						break;
00807				}
00808				//log("Recovered move from "$OldTimeStamp$" acceleration "$Accel$" from "$OldAccel);
00809				MoveAutonomous(OldTimeStamp - CurrentTimeStamp, OldbRun, OldbDuck, NewbPressedJump, OldDoubleClickMove, Accel, rot(0,0,0));
00810				CurrentTimeStamp = OldTimeStamp;
00811			}
00812		}
00813	
00814		// View components
00815		ViewPitch = View/32768;
00816		ViewYaw = 2 * (View - 32768 * ViewPitch);
00817		ViewPitch *= 2;
00818		// Make acceleration.
00819		Accel = InAccel/10;
00820	
00821		NewbPressedJump = (bJumpStatus != NewbJumpStatus);
00822		bJumpStatus = NewbJumpStatus;
00823	
00824		// Save move parameters.
00825		DeltaTime = TimeStamp - CurrentTimeStamp;
00826		if ( ServerTimeStamp > 0 )
00827		{
00828			// allow 1% error
00829			TimeMargin += DeltaTime - 1.01 * (Level.TimeSeconds - ServerTimeStamp);
00830			if ( TimeMargin > MaxTimeMargin )
00831			{
00832				// player is too far ahead
00833				TimeMargin -= DeltaTime;
00834				if ( TimeMargin < 0.5 )
00835					MaxTimeMargin = Default.MaxTimeMargin;
00836				else
00837					MaxTimeMargin = 0.5;
00838				DeltaTime = 0;
00839			}
00840		}
00841	
00842		CurrentTimeStamp = TimeStamp;
00843		ServerTimeStamp = Level.TimeSeconds;
00844		ViewRot.Pitch = ViewPitch;
00845		ViewRot.Yaw = ViewYaw;
00846		ViewRot.Roll = 0;
00847		SetRotation(ViewRot);
00848	
00849		if ( Pawn != None )
00850		{
00851			Rot.Roll = 256 * ClientRoll;
00852			Rot.Yaw = ViewYaw;
00853			if ( (Pawn.Physics == PHYS_Swimming) || (Pawn.Physics == PHYS_Flying) )
00854				maxPitch = 2;
00855			else
00856				maxPitch = 1;
00857			If ( (ViewPitch > maxPitch * RotationRate.Pitch) && (ViewPitch < 65536 - maxPitch * RotationRate.Pitch) )
00858			{
00859				If (ViewPitch < 32768)
00860					Rot.Pitch = maxPitch * RotationRate.Pitch;
00861				else
00862					Rot.Pitch = 65536 - maxPitch * RotationRate.Pitch;
00863			}
00864			else
00865				Rot.Pitch = ViewPitch;
00866			DeltaRot = (Rotation - Rot);
00867			Pawn.SetRotation(Rot);
00868	    if ( Pawn.ControllerPitch != Rotation.Pitch / 256 ) // test to avoid bNetDirtied by useless change
00869	  		Pawn.ControllerPitch = ViewPitch / 256;
00870	//		Log("Setting Pawn.controllerPitch="$Pawn.ControllerPitch);
00871		}
00872	
00873		// Perform actual movement.
00874		if ( (Level.Pauser == None) && (DeltaTime > 0) )
00875			MoveAutonomous(DeltaTime, NewbRun, NewbDuck, NewbPressedJump, DoubleClickMove, Accel, DeltaRot);
00876	
00877		// Accumulate movement error.
00878		if ( Level.TimeSeconds - LastUpdateTime > 0.3 )
00879			ClientErr = 10000;
00880		else if ( Level.TimeSeconds - LastUpdateTime > 180.0/Player.CurrentNetSpeed )
00881		{
00882			if ( Pawn == None )
00883				LocDiff = Location - ClientLoc;
00884			else
00885				LocDiff = Pawn.Location - ClientLoc;
00886			ClientErr = LocDiff Dot LocDiff;
00887		}
00888	
00889		// If client has accumulated a noticeable positional error, correct him.
00890		if ( ClientErr > 3 )
00891		{
00892			if ( Pawn == None )
00893			{
00894				ClientPhysics = Physics;
00895				ClientLoc = Location;
00896				ClientVel = Velocity;
00897			}
00898			else
00899			{
00900				ClientPhysics = Pawn.Physics;
00901				ClientVel = Pawn.Velocity;
00902				ClientBase = Pawn.Base;
00903				if ( Mover(Pawn.Base) != None )
00904					ClientLoc = Pawn.Location - Pawn.Base.Location;
00905				else
00906					ClientLoc = Pawn.Location;
00907				ClientFloor = Pawn.Floor;
00908			}
00909			//log("Client Error at "$TimeStamp$" is "$ClientErr$" with acceleration "$Accel$" LocDiff "$LocDiff$" Physics "$Pawn.Physics);
00910			LastUpdateTime = Level.TimeSeconds;
00911	
00912			if ( (Pawn == None) || (Pawn.Physics != PHYS_Spider) )
00913			{
00914				if ( ClientVel == vect(0,0,0) )
00915				{
00916					if ( IsInState('PlayerWalking') && (Pawn != None) && (Pawn.Physics == PHYS_Walking) )
00917					{
00918						VeryShortClientAdjustPosition
00919						(
00920							TimeStamp,
00921							ClientLoc.X,
00922							ClientLoc.Y,
00923							ClientLoc.Z,
00924							ClientBase
00925						);
00926					}
00927					else
00928						ShortClientAdjustPosition
00929						(
00930							TimeStamp,
00931							GetStateName(),
00932							ClientPhysics,
00933							ClientLoc.X,
00934							ClientLoc.Y,
00935							ClientLoc.Z,
00936							ClientBase
00937						);
00938				}
00939				else
00940					ClientAdjustPosition
00941					(
00942						TimeStamp,
00943						GetStateName(),
00944						ClientPhysics,
00945						ClientLoc.X,
00946						ClientLoc.Y,
00947						ClientLoc.Z,
00948						ClientVel.X,
00949						ClientVel.Y,
00950						ClientVel.Z,
00951						ClientBase
00952					);
00953			}
00954			else
00955				LongClientAdjustPosition
00956				(
00957					TimeStamp,
00958					GetStateName(),
00959					ClientPhysics,
00960					ClientLoc.X,
00961					ClientLoc.Y,
00962					ClientLoc.Z,
00963					ClientVel.X,
00964					ClientVel.Y,
00965					ClientVel.Z,
00966					ClientBase,
00967					ClientFloor.X,
00968					ClientFloor.Y,
00969					ClientFloor.Z
00970				);
00971		}
00972		//log("Server moved stamp "$TimeStamp$" location "$Pawn.Location$" Acceleration "$Pawn.Acceleration$" Velocity "$Pawn.Velocity);
00973	
00974	    /*  To track down some multiplayer problems...
00975	    //debuglog("In ServerMove()");
00976	    //DumpContent(TimeStamp, 2);
00977	    DumpChosenContent(TimeStamp);
00978	    */
00979	}
00980	
00981	function ProcessMove ( float DeltaTime, vector newAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
00982	{
00983		if ( Pawn != None )
00984			Pawn.Acceleration = newAccel;
00985	}
00986	
00987	final function MoveAutonomous
00988	(
00989		float DeltaTime,
00990		bool NewbRun,
00991		bool NewbDuck,
00992		bool NewbPressedJump,
00993		eDoubleClickDir DoubleClickMove,
00994		vector newAccel,
00995		rotator DeltaRot
00996	)
00997	{
00998		if ( NewbRun )
00999			bRun = 1;
01000		else
01001			bRun = 0;
01002	
01003		if ( NewbDuck )
01004			bDuck = 1;
01005		else
01006			bDuck = 0;
01007		bPressedJump = NewbPressedJump;
01008	
01009		HandleWalking();
01010		ProcessMove(DeltaTime, newAccel, DoubleClickMove, DeltaRot);
01011		if ( Pawn != None )
01012			Pawn.AutonomousPhysics(DeltaTime);
01013		else
01014			AutonomousPhysics(DeltaTime);
01015		//log("Role "$Role$" moveauto time "$100 * DeltaTime$" ("$Level.TimeDilation$")");
01016	}
01017	
01018	/* VeryShortClientAdjustPosition
01019	bandwidth saving version, when velocity is zeroed, and pawn is walking
01020	*/
01021	function VeryShortClientAdjustPosition
01022	(
01023		float TimeStamp,
01024		float NewLocX,
01025		float NewLocY,
01026		float NewLocZ,
01027		Actor NewBase
01028	)
01029	{
01030		local vector Floor;
01031	
01032		if ( Pawn != None )
01033			Floor = Pawn.Floor;
01034		LongClientAdjustPosition(TimeStamp,'PlayerWalking',PHYS_Walking,NewLocX,NewLocY,NewLocZ,0,0,0,NewBase,Floor.X,Floor.Y,Floor.Z);
01035	}
01036	
01037	/* ShortClientAdjustPosition
01038	bandwidth saving version, when velocity is zeroed
01039	*/
01040	function ShortClientAdjustPosition
01041	(
01042		float TimeStamp,
01043		name newState,
01044		EPhysics newPhysics,
01045		float NewLocX,
01046		float NewLocY,
01047		float NewLocZ,
01048		Actor NewBase
01049	)
01050	{
01051		local vector Floor;
01052	
01053		if ( Pawn != None )
01054			Floor = Pawn.Floor;
01055		LongClientAdjustPosition(TimeStamp,newState,newPhysics,NewLocX,NewLocY,NewLocZ,0,0,0,NewBase,Floor.X,Floor.Y,Floor.Z);
01056	}
01057	
01058	/* ClientAdjustPosition
01059	- pass newloc and newvel in components so they don't get rounded
01060	*/
01061	function ClientAdjustPosition
01062	(
01063		float TimeStamp,
01064		name newState,
01065		EPhysics newPhysics,
01066		float NewLocX,
01067		float NewLocY,
01068		float NewLocZ,
01069		float NewVelX,
01070		float NewVelY,
01071		float NewVelZ,
01072		Actor NewBase
01073	)
01074	{
01075		local vector Floor;
01076	
01077		if ( Pawn != None )
01078			Floor = Pawn.Floor;
01079		LongClientAdjustPosition(TimeStamp,newState,newPhysics,NewLocX,NewLocY,NewLocZ,NewVelX,NewVelY,NewVelZ,NewBase,Floor.X,Floor.Y,Floor.Z);
01080	}
01081	
01082	/* LongClientAdjustPosition
01083	long version, when care about pawn's floor normal
01084	*/
01085	function LongClientAdjustPosition
01086	(
01087		float TimeStamp,
01088		name newState,
01089		EPhysics newPhysics,
01090		float NewLocX,
01091		float NewLocY,
01092		float NewLocZ,
01093		float NewVelX,
01094		float NewVelY,
01095		float NewVelZ,
01096		Actor NewBase,
01097		float NewFloorX,
01098		float NewFloorY,
01099		float NewFloorZ
01100	)
01101	{
01102		local vector NewLocation, NewFloor;
01103		local Actor MoveActor;
01104	
01105		if ( Pawn != None )
01106		{
01107			if ( Pawn.bTearOff )
01108			{
01109				Pawn = None;
01110				GotoState('Dead');
01111				return;
01112			}
01113			MoveActor = Pawn;
01114		}
01115		else
01116			MoveActor = self;
01117	
01118		if ( CurrentTimeStamp > TimeStamp )
01119			return;
01120		CurrentTimeStamp = TimeStamp;
01121	
01122		NewLocation.X = NewLocX;
01123		NewLocation.Y = NewLocY;
01124		NewLocation.Z = NewLocZ;
01125		MoveActor.Velocity.X = NewVelX;
01126		MoveActor.Velocity.Y = NewVelY;
01127		MoveActor.Velocity.Z = NewVelZ;
01128	
01129		NewFloor.X = NewFloorX;
01130		NewFloor.Y = NewFloorY;
01131		NewFloor.Z = NewFloorZ;
01132		MoveActor.SetBase(NewBase, NewFloor);
01133		if ( Mover(NewBase) != None )
01134			NewLocation += NewBase.Location;
01135	
01136		//log("Client "$Role$" adjust "$self$" stamp "$TimeStamp$" location "$MoveActor.Location);
01137		MoveActor.bCanTeleport = false;
01138		MoveActor.SetLocation(NewLocation);
01139		MoveActor.bCanTeleport = true;
01140		MoveActor.SetPhysics(newPhysics);
01141	
01142		if( GetStateName() != newstate )
01143			GotoState(newstate);
01144	
01145		bUpdatePosition = true;
01146	
01147	    /*  To track down some multiplayer problems...
01148	    //debuglog("In LongClientAdjustPosition():");
01149	    //DumpContent(TimeStamp, 2);
01150	    DumpChosenContent(TimeStamp);
01151	    */
01152	}
01153	
01154	function ClientUpdatePosition()
01155	{
01156		local SavedMove CurrentMove;
01157		local int realbRun, realbDuck;
01158		local bool bRealJump;
01159		local float TotalTime;
01160	
01161		bUpdatePosition = false;
01162		realbRun= bRun;
01163		realbDuck = bDuck;
01164		bRealJump = bPressedJump;
01165		CurrentMove = SavedMoves;
01166		bUpdating = true;
01167		while ( CurrentMove != None )
01168		{
01169			if ( CurrentMove.TimeStamp <= CurrentTimeStamp )
01170			{
01171				SavedMoves = CurrentMove.NextMove;
01172				CurrentMove.NextMove = FreeMoves;
01173				FreeMoves = CurrentMove;
01174				FreeMoves.Clear();
01175				CurrentMove = SavedMoves;
01176			}
01177			else
01178			{
01179				if ( (TotalTime > 0) && (Pawn != None) )
01180					AdjustRadius(CurrentMove.Delta * Pawn.GroundSpeed);
01181				TotalTime += CurrentMove.Delta;
01182				MoveAutonomous(CurrentMove.Delta, CurrentMove.bRun, CurrentMove.bDuck, CurrentMove.bPressedJump, CurrentMove.DoubleClickMove, CurrentMove.Acceleration, rot(0,0,0));
01183				CurrentMove = CurrentMove.NextMove;
01184			}
01185		}
01186		//log("Client updated position to "$Pawn.Location);
01187		bUpdating = false;
01188		bDuck = realbDuck;
01189		bRun = realbRun;
01190		bPressedJump = bRealJump;
01191	}
01192	
01193	function AdjustRadius(float MaxMove)
01194	{
01195		local Pawn P;
01196		local vector Dir;
01197	
01198		// if other pawn moving away from player, push it away if its close
01199		// since the client-side position is behind the server side position
01200		ForEach DynamicActors(class'Pawn', P)
01201			if ( (P != Pawn) && (P.Velocity != vect(0,0,0)) && P.bBlockPlayers )
01202			{
01203				Dir = Normal(P.Location - Pawn.Location);
01204				if ( (Pawn.Velocity Dot Dir > 0) && (P.Velocity Dot Dir > 0) )
01205				{
01206					if ( VSize(P.Location - Pawn.Location) < P.CollisionRadius + Pawn.CollisionRadius + MaxMove )
01207						P.MoveSmooth(P.Velocity * 0.5 * PlayerReplicationInfo.Ping);
01208				}
01209			}
01210	}
01211	
01212	final function SavedMove GetFreeMove()
01213	{
01214		local SavedMove s, first;
01215		local int i;
01216	
01217		if ( FreeMoves == None )
01218		{
01219			// don't allow more than 30 saved moves
01220			For ( s=SavedMoves; s!=None; s=s.NextMove )
01221			{
01222				i++;
01223				if ( i > 30 )
01224				{
01225					first = SavedMoves;
01226					SavedMoves = SavedMoves.NextMove;
01227					first.Clear();
01228					first.NextMove = None;
01229					// clear out all the moves
01230					While ( SavedMoves != None )
01231					{
01232						s = SavedMoves;
01233						SavedMoves = SavedMoves.NextMove;
01234						s.Clear();
01235						s.NextMove = FreeMoves;
01236						FreeMoves = s;
01237					}
01238					return first;
01239				}
01240			}
01241			return Spawn(class'SavedMove');
01242		}
01243		else
01244		{
01245			s = FreeMoves;
01246			FreeMoves = FreeMoves.NextMove;
01247			s.NextMove = None;
01248			return s;
01249		}
01250	}
01251	
01252	function int CompressAccel(int C)
01253	{
01254		if ( C >= 0 )
01255			C = Min(C, 127);
01256		else
01257			C = Min(abs(C), 127) + 128;
01258		return C;
01259	}
01260	
01261	/*
01262	========================================================================
01263	Here's how player movement prediction, replication and correction works in network games:
01264	
01265	Every tick, the PlayerTick() function is called.  It calls the PlayerMove() function (which is implemented
01266	in various states).  PlayerMove() figures out the acceleration and rotation, and then calls ProcessMove()
01267	(for single player or listen servers), or ReplicateMove() (if its a network client).
01268	
01269	ReplicateMove() saves the move (in the PendingMove list), calls ProcessMove(), and then replicates the move
01270	to the server by calling the replicated function ServerMove() - passing the movement parameters, the client's
01271	resultant position, and a timestamp.
01272	
01273	ServerMove() is executed on the server.  It decodes the movement parameters and causes the appropriate movement
01274	to occur.  It then looks at the resulting position and if enough time has passed since the last response, or the
01275	position error is significant enough, the server calls ClientAdjustPosition(), a replicated function.
01276	
01277	ClientAdjustPosition() is executed on the client.  The client sets its position to the servers version of position,
01278	and sets the bUpdatePosition flag to true.
01279	
01280	When PlayerTick() is called on the client again, if bUpdatePosition is true, the client will call
01281	ClientUpdatePosition() before calling PlayerMove().  ClientUpdatePosition() replays all the moves in the pending
01282	move list which occured after the timestamp of the move the server was adjusting.
01283	*/
01284	
01285	//
01286	// Replicate this client's desired movement to the server.
01287	//
01288	function ReplicateMove
01289	(
01290		float DeltaTime,
01291		vector NewAccel,
01292		eDoubleClickDir DoubleClickMove,
01293		rotator DeltaRot
01294	)
01295	{
01296		local SavedMove NewMove, OldMove, LastMove;
01297		local byte ClientRoll;
01298		local float OldTimeDelta, NetMoveDelta;
01299		local int i, OldAccel;
01300		local vector BuildAccel, AccelNorm, MoveLoc;
01301	
01302		// Get a SavedMove actor to store the movement in.
01303		if ( PendingMove != None )
01304			PendingMove.SetMoveFor(self, DeltaTime, NewAccel, DoubleClickMove);
01305	
01306		if ( SavedMoves != None )
01307		{
01308			NewMove = SavedMoves;
01309			AccelNorm = Normal(NewAccel);
01310			while ( NewMove.NextMove != None )
01311			{
01312				// find most recent interesting move to send redundantly
01313				if ( NewMove.bPressedJump || ((NewMove.DoubleClickMove != DCLICK_NONE) && (NewMove.DoubleClickMove < 5))
01314					|| ((NewMove.Acceleration != NewAccel) && ((normal(NewMove.Acceleration) Dot AccelNorm) < 0.95)) )
01315					OldMove = NewMove;
01316				NewMove = NewMove.NextMove;
01317			}
01318			if ( NewMove.bPressedJump || ((NewMove.DoubleClickMove != DCLICK_NONE) && (NewMove.DoubleClickMove < 5))
01319				|| ((NewMove.Acceleration != NewAccel) && ((normal(NewMove.Acceleration) Dot AccelNorm) < 0.95)) )
01320				OldMove = NewMove;
01321		}
01322	
01323		LastMove = NewMove;
01324		NewMove = GetFreeMove();
01325		if ( NewMove == None )
01326			return;
01327		NewMove.SetMoveFor(self, DeltaTime, NewAccel, DoubleClickMove);
01328	
01329		// adjust radius of nearby players with uncertain location
01330		if ( Pawn != None )
01331			AdjustRadius(NewMove.Delta * Pawn.GroundSpeed);
01332	
01333		// Simulate the movement locally.
01334		ProcessMove(NewMove.Delta, NewMove.Acceleration, NewMove.DoubleClickMove, DeltaRot);
01335		if ( Pawn != None )
01336			Pawn.AutonomousPhysics(NewMove.Delta);
01337		else
01338			AutonomousPhysics(DeltaTime);
01339	
01340		//log("Role "$Role$" repmove at "$Level.TimeSeconds$" Move time "$100 * DeltaTime$" ("$Level.TimeDilation$")");
01341	
01342		// Decide whether to hold off on move
01343		// send if double click move, jump, or fire unless really too soon, or if newmove.delta big enough
01344		// on client side, save extra buffered time in LastUpdateTime
01345		if ( PendingMove == None )
01346			PendingMove = NewMove;
01347		else
01348		{
01349			NewMove.NextMove = FreeMoves;
01350			FreeMoves = NewMove;
01351			FreeMoves.Clear();
01352			NewMove = PendingMove;
01353		}
01354		NetMoveDelta = FMax(64.0/Player.CurrentNetSpeed, 0.011);
01355	
01356		if ( !PendingMove.bPressedJump && (PendingMove.Delta < NetMoveDelta - ClientUpdateTime) )
01357		{
01358			// save as pending move
01359			return;
01360		}
01361		else if ( (ClientUpdateTime < 0) && (PendingMove.Delta < NetMoveDelta - ClientUpdateTime) )
01362			return;
01363		else
01364		{
01365			ClientUpdateTime = PendingMove.Delta - NetMoveDelta;
01366			if ( SavedMoves == None )
01367				SavedMoves = PendingMove;
01368			else
01369				LastMove.NextMove = PendingMove;
01370			PendingMove = None;
01371		}
01372	
01373		// check if need to redundantly send previous move
01374		if ( OldMove != None )
01375		{
01376			// log("Redundant send timestamp "$OldMove.TimeStamp$" accel "$OldMove.Acceleration$" at "$Level.Timeseconds$" New accel "$NewAccel);
01377			// old move important to replicate redundantly
01378			OldTimeDelta = FMin(255, (Level.TimeSeconds - OldMove.TimeStamp) * 500);
01379			BuildAccel = 0.05 * OldMove.Acceleration + vect(0.5, 0.5, 0.5);
01380			OldAccel = (CompressAccel(BuildAccel.X) << 23)
01381						+ (CompressAccel(BuildAccel.Y) << 15)
01382						+ (CompressAccel(BuildAccel.Z) << 7);
01383			if ( OldMove.bRun )
01384				OldAccel += 64;
01385			if ( OldMove.bDuck )
01386				OldAccel += 32;
01387			if ( OldMove.bPressedJump )
01388				OldAccel += 16;
01389			OldAccel += OldMove.DoubleClickMove;
01390		}
01391		//else
01392		//	log("No redundant timestamp at "$Level.TimeSeconds$" with accel "$NewAccel);
01393		//log("Replicate move at "$NewMove.TimeStamp$" location "$Pawn.Location);
01394		// Send to the server
01395		ClientRoll = (Rotation.Roll >> 8) & 255;
01396		if ( NewMove.bPressedJump )
01397			bJumpStatus = !bJumpStatus;
01398	
01399		if ( Pawn == None )
01400			MoveLoc = Location;
01401		else
01402			MoveLoc = Pawn.Location;
01403	
01404		if ( (NewMove.Acceleration == vect(0,0,0)) && (NewMove.DoubleClickMove == DCLICK_None) )
01405			ShortServerMove
01406			(
01407				NewMove.TimeStamp,
01408				MoveLoc,
01409				NewMove.bRun,
01410				NewMove.bDuck,
01411				bJumpStatus,
01412				ClientRoll,
01413				(32767 & (Rotation.Pitch/2)) * 32768 + (32767 & (Rotation.Yaw/2))
01414			);
01415		else
01416			ServerMove
01417			(
01418				NewMove.TimeStamp,
01419				NewMove.Acceleration * 10,
01420				MoveLoc,
01421				NewMove.bRun,
01422				NewMove.bDuck,
01423				bJumpStatus,
01424				NewMove.DoubleClickMove,
01425				ClientRoll,
01426				(32767 & (Rotation.Pitch/2)) * 32768 + (32767 & (Rotation.Yaw/2)),
01427				OldTimeDelta,
01428				OldAccel
01429			);
01430	}
01431	
01432	/*function HandleWalking()
01433	{
01434		if ( Pawn != None )
01435			Pawn.SetWalking(((bRun != 0) || (bDuck != 0)) && !Region.Zone.IsA('WarpZoneInfo'));
01436	}*/
01437	native(499) static final function HandleWalking();
01438	
01439	function ServerRestartGame()
01440	{
01441	}
01442	
01443	function SetFOVAngle(float newFOV)
01444	{
01445		FOVAngle = newFOV;
01446	}
01447	
01448	function ClientFlash( float scale, vector fog )
01449	{
01450		DesiredFlashScale = scale;
01451		DesiredFlashFog = 0.001 * fog;
01452	}
01453	
01454	function ClientInstantFlash( float scale, vector fog )
01455	{
01456		InstantFlash = scale;
01457		InstantFog = 0.001 * fog;
01458	}
01459	
01460	function ClientAdjustGlow( float scale, vector fog )
01461	{
01462		ConstantGlowScale = scale;
01463		ConstantGlowFog = 0.001 * fog;
01464	}
01465	
01466	function ClientFilter( Color FC, color FCW, float FCS )
01467	{
01468		FilterColor = FC;
01469		FilterColorWanted = FCW;
01470		FilterColorSpeed = FCS;
01471	}
01472	
01473	function ClientHighLight( color TargetColor, float TargetHighLight, optional Material Mat )
01474	{
01475	/*
01476	var byte UseVignetteFilter;
01477	var byte UseVignetteHighlight;
01478	var color VignetteColor;
01479	var float VignetteHighLight;
01480	var material VignetteMaterial;
01481	*/
01482	    if (TargetHighLight != 0)
01483	    {
01484	      UseVignetteFilter = 1;
01485	      UseVignetteHighlight = 1;
01486	      VignetteColor = TargetColor;
01487	      VignetteHighLight = TargetHighLight;
01488	      VignetteMaterial = Mat;
01489	    }
01490	    else
01491	    {
01492	      UseVignetteFilter = 0;
01493	      UseVignetteHighlight = 0;
01494	    }
01495	}
01496	
01497	/* ClientShake()
01498	Function called on client to shake view.
01499	Only ShakeView() should call ClientShake()
01500	*/
01501	private function ClientShake(vector ShakeRoll, vector OffsetMag, vector ShakeRate, float OffsetTime)
01502	{
01503		if ( (MaxShakeRoll < ShakeRoll.X) || (ShakeRollTime < 0.01 * ShakeRoll.Y) )
01504		{
01505			MaxShakeRoll = ShakeRoll.X;
01506			ShakeRollTime = 0.01 * ShakeRoll.Y;
01507			ShakeRollRate = 0.01 * ShakeRoll.Z;
01508		}
01509		if ( VSize(OffsetMag) > VSize(MaxShakeOffset) )
01510		{
01511			ShakeOffsetTime = OffsetTime * vect(1,1,1);
01512			MaxShakeOffset = OffsetMag;
01513			ShakeOffsetRate = ShakeRate;
01514		}
01515	//	if (MaxShakeFrame < ShakeFrameMag)
01516	//	{
01517	/*		MaxShakeFrame.X = 0.08;
01518			MaxShakeFrame.Y = 0.06;
01519			ShakeFrameTime = 10;
01520			ShakeFrameRate.X = 0.4;
01521			ShakeFrameRate.Y = 0.25;*/
01522	//	}
01523	
01524	}
01525	
01526	
01527	/* ShakeView()
01528	Call this function to shake the player's view
01529	shaketime = how long to roll view
01530	RollMag = how far to roll view as it shakes
01531	OffsetMag = max view offset
01532	RollRate = how fast to roll view
01533	OffsetRate = how fast to offset view
01534	OffsetTime = how long to offset view (number of shakes)
01535	*/
01536	function ShakeView( float shaketime, float RollMag, vector OffsetMag, float RollRate, vector OffsetRate, float OffsetTime)
01537	{
01538		local vector ShakeRoll;
01539	
01540		ShakeRoll.X = RollMag;
01541		ShakeRoll.Y = 100 * shaketime;
01542		ShakeRoll.Z = 100 * rollrate;
01543		ClientShake(ShakeRoll, OffsetMag, OffsetRate, OffsetTime);
01544	}
01545	
01546	function damageAttitudeTo(pawn Other, float Damage)
01547	{
01548		if ( (Other != None) && (Other != Pawn) && (Damage > 0) )
01549			Enemy = Other;
01550	}
01551	
01552	function Typing( bool bTyping )
01553	{
01554		bIsTyping = bTyping;
01555		if ( bTyping && (Pawn != None) && !Pawn.bTearOff )
01556			Pawn.ChangeAnimation();
01557	
01558		if (Level.Game.StatLog != None)
01559			Level.Game.StatLog.LogTypingEvent(bTyping, Self);
01560	}
01561	
01562	//*************************************************************************************
01563	// Normal gameplay execs
01564	// Type the name of the exec function at the console to execute it
01565	
01566	exec function Jump( optional float F )
01567	{
01568		if ( Level.Pauser == PlayerReplicationInfo )
01569			SetPause(False);
01570		else
01571			bPressedJump = true;
01572	}
01573	
01574	// Send a voice message of a certain type to a certain player.
01575	exec function Speech( int Type, int Index, int Callsign )
01576	{
01577		local VoicePack V;
01578	
01579		V = Spawn( PlayerReplicationInfo.VoiceType, Self );
01580		if (V != None)
01581			V.PlayerSpeech( Type, Index, Callsign );
01582	}
01583	
01584	exec function RestartLevel()
01585	{
01586		if( Level.Netmode==NM_Standalone )
01587			ClientTravel( "?restart", TRAVEL_Relative, false );
01588	}
01589	
01590	exec function LocalTravel( string URL )
01591	{
01592		if( Level.Netmode==NM_Standalone )
01593			ClientTravel( URL, TRAVEL_Relative, true );
01594	}
01595	
01596	// ------------------------------------------------------------------------
01597	// Loading and saving
01598	
01599	/* QuickSave()
01600	Save game to slot 9
01601	*/
01602	exec function QuickSave()
01603	{
01604		if ( (Pawn.Health > 0)
01605			&& (Level.NetMode == NM_Standalone) )
01606		{
01607			ClientMessage(QuickSaveString);
01608			ConsoleCommand("SaveGame 9");
01609		}
01610	}
01611	
01612	/* QuickLoad()
01613	Load game from slot 9
01614	*/
01615	exec function QuickLoad()
01616	{
01617		if ( Level.NetMode == NM_Standalone )
01618			ClientTravel( "?load=9", TRAVEL_Absolute, false);
01619	}
01620	
01621	/* SetPause()
01622	 Try to pause game; returns success indicator.
01623	 Replicated to server in network games.
01624	 */
01625	function bool SetPause( BOOL bPause )
01626	{
01627		local bool ret;
01628	
01629		if( bPause )
01630			ret = Level.Game.SetPause(True, self);
01631		else
01632			ret = Level.Game.SetPause(False, self);
01633		return ret;
01634	}
01635	
01636	/* Pause()
01637	Command to try to pause the game.
01638	*/
01639	exec function Pause()
01640	{
01641		if( !SetPause(Level.Pauser==None) )
01642			ClientMessage(NoPauseMessage);
01643	}
01644	
01645	// Activate specific inventory item
01646	exec function ActivateInventoryItem( class InvItem )
01647	{
01648		local Powerups Inv;
01649	
01650		Inv = Powerups(Pawn.FindInventoryType(InvItem));
01651		if ( Inv != None )
01652			Inv.Activate();
01653	}
01654	
01655	// ------------------------------------------------------------------------
01656	// Weapon changing functions
01657	
01658	/* ThrowWeapon()
01659	Throw out current weapon, and switch to a new weapon
01660	*/
01661	exec function ThrowWeapon()
01662	{
01663		if( Level.NetMode == NM_Client )
01664			return;
01665		if( Pawn.Weapon==None || !Pawn.Weapon.bCanThrow )
01666			return;
01667		Pawn.Weapon.bTossedOut = true;
01668		Pawn.TossWeapon(Vector(Rotation) * 500 + vect(0,0,220));
01669		if ( Pawn.Weapon == None )
01670			SwitchToBestWeapon();
01671	}
01672	
01673	/* PrevWeapon()
01674	- switch to previous inventory group weapon
01675	*/
01676	exec function PrevWeapon()
01677	{
01678		if( Level.Pauser!=None )
01679			return;
01680		if ( Pawn.Weapon == None )
01681		{
01682			SwitchToBestWeapon();
01683			return;
01684		}
01685		if ( Pawn.PendingWeapon != None )
01686			Pawn.PendingWeapon = Pawn.Inventory.PrevWeapon(None, Pawn.PendingWeapon);
01687		else
01688			Pawn.PendingWeapon = Pawn.Inventory.PrevWeapon(None, Pawn.Weapon);
01689	
01690		if ( Pawn.PendingWeapon != None )
01691			Pawn.Weapon.PutDown();
01692	}
01693	
01694	/* NextWeapon()
01695	- switch to next inventory group weapon
01696	*/
01697	exec function NextWeapon()
01698	{
01699		if( Level.Pauser!=None )
01700			return;
01701		if ( Pawn.Weapon == None )
01702		{
01703			SwitchToBestWeapon();
01704			return;
01705		}
01706		if ( Pawn.PendingWeapon != None )
01707			Pawn.PendingWeapon = Pawn.Inventory.NextWeapon(None, Pawn.PendingWeapon);
01708		else
01709			Pawn.PendingWeapon = Pawn.Inventory.NextWeapon(None, Pawn.Weapon);
01710	
01711		if ( Pawn.PendingWeapon != None )
01712			Pawn.Weapon.PutDown();
01713	}
01714	
01715	// The player wants to switch to weapon group number F.
01716	exec function SwitchWeapon (byte F )
01717	{
01718		local weapon newWeapon;
01719	
01720		if ( (Level.Pauser!=None) || (Pawn == None) || (Pawn.Inventory == None) )
01721			return;
01722		if ( (Pawn.Weapon != None) && (Pawn.Weapon.Inventory != None) )
01723			newWeapon = Pawn.Weapon.Inventory.WeaponChange(F);
01724		else
01725			newWeapon = None;
01726		if ( newWeapon == None )
01727			newWeapon = Pawn.Inventory.WeaponChange(F);
01728	
01729		if ( newWeapon == None )
01730			return;
01731	
01732		if ( Pawn.Weapon == None )
01733		{
01734			Pawn.PendingWeapon = newWeapon;
01735			Pawn.ChangedWeapon();
01736		}
01737		else if ( Pawn.Weapon != newWeapon )
01738		{
01739			Pawn.PendingWeapon = newWeapon;
01740			if ( !Pawn.Weapon.PutDown() )
01741				Pawn.PendingWeapon = None;
01742		}
01743	}
01744	
01745	exec function GetWeapon(class<Weapon> NewWeaponClass )
01746	{
01747		local Inventory Inv;
01748	
01749		if ( (Pawn.Inventory == None) || (NewWeaponClass == None)
01750			|| ((Pawn.Weapon != None) && (Pawn.Weapon.Class == NewWeaponClass)) )
01751			return;
01752	
01753		for ( Inv=Pawn.Inventory; Inv!=None; Inv=Inv.Inventory )
01754			if ( Inv.Class == NewWeaponClass )
01755			{
01756				Pawn.PendingWeapon = Weapon(Inv);
01757				if ( !Pawn.PendingWeapon.HasAmmo() )
01758				{
01759					ClientMessage( Pawn.PendingWeapon.ItemName$Pawn.PendingWeapon.MessageNoAmmo );
01760					Pawn.PendingWeapon = None;
01761					return;
01762				}
01763				Pawn.Weapon.PutDown();
01764				return;
01765			}
01766	}
01767	
01768	// The player wants to select previous item
01769	exec function PrevItem()
01770	{
01771		local Inventory Inv;
01772		local Powerups LastItem;
01773	
01774		if ( Level.Pauser!=None )
01775			return;
01776		if (Pawn.SelectedItem==None)
01777		{
01778			Pawn.SelectedItem = Inventory.SelectNext();
01779			Return;
01780		}
01781		if (Pawn.SelectedItem.Inventory!=None)
01782			for( Inv=Pawn.SelectedItem.Inventory; Inv!=None; Inv=Inv.Inventory )
01783			{
01784				if (Inv==None) Break;
01785				if ( Inv.IsA('Powerups') && Powerups(Inv).bActivatable) LastItem=Powerups(Inv);
01786			}
01787		for( Inv=Pawn.Inventory; Inv!=Pawn.SelectedItem; Inv=Inv.Inventory )
01788		{
01789			if (Inv==None) Break;
01790			if ( Inv.IsA('Powerups') && Powerups(Inv).bActivatable) LastItem=Powerups(Inv);
01791		}
01792		if (LastItem!=None)
01793			Pawn.SelectedItem = LastItem;
01794	}
01795	
01796	// The player wants to active selected item
01797	exec function ActivateItem()
01798	{
01799		if( Level.Pauser!=None )
01800			return;
01801		if ( (Pawn != None) && (Pawn.SelectedItem!=None) )
01802			Pawn.SelectedItem.Activate();
01803	}
01804	
01805	// The player wants to fire.
01806	exec function Fire( optional float F )
01807	{
01808		if ( Level.Pauser == PlayerReplicationInfo )
01809		{
01810			SetPause(false);
01811			return;
01812		}
01813		if( Pawn.Weapon!=None )
01814			Pawn.Weapon.Fire(F);
01815	}
01816	
01817	// The player wants to alternate-fire.
01818	exec function AltFire( optional float F )
01819	{
01820		if ( Level.Pauser == PlayerReplicationInfo )
01821		{
01822			SetPause(false);
01823			return;
01824		}
01825		if( Pawn.Weapon!=None )
01826			Pawn.Weapon.AltFire(F);
01827	}
01828	
01829	// The player wants to use something in the level.
01830	exec function Use()
01831	{
01832		local Actor A;
01833	
01834		if ( Level.Pauser == PlayerReplicationInfo )
01835		{
01836			SetPause(false);
01837			return;
01838		}
01839	
01840		// Send the 'DoUse' event to each actor player is touching.
01841		ForEach Pawn.TouchingActors(class'Actor', A)
01842		{
01843			A.UsedBy(Pawn);
01844		}
01845	}
01846	
01847	exec function Suicide()
01848	{
01849		Pawn.KilledBy( Pawn );
01850	}
01851	
01852	function Name( coerce string S )
01853	{
01854		S = Left(S,15);
01855	
01856	    ChangeName(S);
01857		UpdateURL("Name", S, true);
01858		SaveConfig();
01859	}
01860	
01861	function ChangeName( coerce string S )
01862	{
01863		if ( Len(S) > 28 )
01864			S = left(S,28);
01865		ReplaceText(S, " ", "_");
01866		Level.Game.ChangeName( self, S, false );
01867	}
01868	
01869	exec function SwitchTeam()
01870	{
01871		if ( (PlayerReplicationInfo.Team == None) || (PlayerReplicationInfo.Team.TeamIndex == 1) )
01872			ChangeTeam(0);
01873		else
01874			ChangeTeam(1);
01875	}
01876	
01877	function ChangeTeam( int N )
01878	{
01879		local TeamInfo OldTeam;
01880	
01881		OldTeam = PlayerReplicationInfo.Team;
01882		Level.Game.ChangeTeam(self, N);
01883		if ( Level.Game.bTeamGame && (PlayerReplicationInfo.Team != OldTeam) )
01884			Pawn.Died( self, class'DamageType', Pawn.Location );
01885	}
01886	
01887	
01888	exec function SwitchLevel( string URL )
01889	{
01890		if( Level.NetMode==NM_Standalone || Level.netMode==NM_ListenServer )
01891			Level.ServerTravel( URL, false );
01892	}
01893	
01894	exec function ClearProgressMessages()
01895	{
01896		local int i;
01897	
01898		for (i=0; i<ArrayCount(ProgressMessage); i++)
01899		{
01900			ProgressMessage[i] = "";
01901			ProgressColor[i] = class'Canvas'.Static.MakeColor(255,255,255);
01902		}
01903	}
01904	
01905	exec event SetProgressMessage( int Index, string S, color C )
01906	{
01907		if ( Index < ArrayCount(ProgressMessage) )
01908		{
01909			ProgressMessage[Index] = S;
01910			ProgressColor[Index] = C;
01911		}
01912	}
01913	
01914	exec event SetProgressTime( float T )
01915	{
01916		ProgressTimeOut = T + Level.TimeSeconds;
01917	}
01918	
01919	function Restart()
01920	{
01921		ServerTimeStamp = 0;
01922		TimeMargin = 0;
01923		Enemy = None;
01924		EnterStartState();
01925		SetViewTarget(Pawn);
01926		bBehindView = Pawn.PointOfView();
01927		ClientRestart();
01928	}
01929	
01930	function EnterStartState()
01931	{
01932		local name NewState;
01933	
01934		if ( Pawn.PhysicsVolume.bWaterVolume )
01935		{
01936			if ( Pawn.HeadVolume.bWaterVolume )
01937				Pawn.BreathTime = Pawn.UnderWaterTime;
01938			NewState = Pawn.WaterMovementState;
01939		}
01940		else
01941			NewState = Pawn.LandMovementState;
01942	
01943		if ( IsInState(NewState) )
01944			BeginState();
01945		else
01946			GotoState(NewState);
01947	}
01948	
01949	function ClientRestart()
01950	{
01951	/*
01952		if ( Pawn == None )
01953		{
01954			GotoState('WaitingForPawn');
01955			return;
01956		}
01957		Pawn.ClientRestart();
01958		SetViewTarget(Pawn);
01959		bBehindView = Pawn.PointOfView();
01960		EnterStartState();
01961	*/
01962	}
01963	
01964	exec function BehindView( Bool B )
01965	{
01966		bBehindView = B;
01967		ClientSetBehindView(bBehindView);
01968	}
01969	
01970	function UpdateBob(float F)
01971	{
01972		Bob = FClamp(F,0,0.032);
01973	}
01974	
01975	
01976	//=============================================================================
01977	// functions.
01978	
01979	// Just changed to pendingWeapon
01980	function ChangedWeapon()
01981	{
01982		if ( Pawn.PendingWeapon != None )
01983			Pawn.PendingWeapon.SetHand(Handedness);
01984	}
01985	
01986	event TravelPostAccept()
01987	{
01988		if ( Pawn.Health <= 0 )
01989			Pawn.Health = Pawn.Default.Health;
01990	}
01991	
01992	event PlayerTick( float DeltaTime )
01993	{
01994		if ( bUpdatePosition )
01995			ClientUpdatePosition();
01996	
01997		PlayerMove(DeltaTime);
01998	}
01999	
02000	function PlayerMove(float DeltaTime);
02001	
02002	
02003	//
02004	/* AdjustAim()
02005	Calls this version for player aiming help.
02006	Aimerror not used in this version.
02007	Only adjusts aiming at pawns
02008	*/
02009	function rotator AdjustAim(Ammunition FiredAmmunition, vector projStart, int aimerror);
02010	/*
02011	{
02012		local vector FireDir, AimSpot, HitNormal, HitLocation, OldAim, AimOffset;
02013		local actor BestTarget;
02014		local float bestAim, bestDist, projspeed;
02015		local actor HitActor;
02016		local bool bNoZAdjust, bLeading;
02017		local rotator AimRot;
02018	
02019		FireDir = vector(Rotation);
02020		if ( FiredAmmunition.bInstantHit )
02021			HitActor = Trace(HitLocation, HitNormal, projStart + 10000 * FireDir, projStart, true);
02022		else
02023			HitActor = Trace(HitLocation, HitNormal, projStart + 4000 * FireDir, projStart, true);
02024		if ( (HitActor != None) && HitActor.bProjTarget )
02025		{
02026			FiredAmmunition.WarnTarget(Target,Pawn,FireDir);
02027			BestTarget = HitActor;
02028			bNoZAdjust = true;
02029			OldAim = HitLocation;
02030			BestDist = VSize(BestTarget.Location - Pawn.Location);
02031		}
02032		else
02033		{
02034			// adjust aim based on FOV
02035			bestAim = 0.95;
02036			if ( AimingHelp == 1 )
02037			{
02038				bestAim = 0.93;
02039				if ( FiredAmmunition.bInstantHit )
02040					bestAim = 0.97;
02041				if ( FOVAngle < DefaultFOV - 8 )
02042					bestAim = 0.99;
02043			}
02044			else
02045			{
02046				if ( FiredAmmunition.bInstantHit )
02047					bestAim = 0.98;
02048				if ( FOVAngle != DefaultFOV )
02049					bestAim = 0.995;
02050			}
02051			BestTarget = PickTarget(bestAim, bestDist, FireDir, projStart);
02052			if ( BestTarget == None )
02053				return Rotation;
02054			FiredAmmunition.WarnTarget(Target,Pawn,FireDir);
02055			OldAim = projStart + FireDir * bestDist;
02056		}
02057		if ( AimingHelp == 0 )
02058			return Rotation;
02059	
02060		// aim at target - help with leading also
02061		if ( !FiredAmmunition.bInstantHit )
02062		{
02063			projspeed = FiredAmmunition.ProjectileClass.default.speed;
02064			BestDist = vsize(BestTarget.Location + BestTarget.Velocity * FMin(2, 0.02 + BestDist/projSpeed) - projStart);
02065			bLeading = true;
02066			FireDir = BestTarget.Location + BestTarget.Velocity * FMin(2, 0.02 + BestDist/projSpeed) - projStart;
02067			AimSpot = projStart + bestDist * Normal(FireDir);
02068			// if splash damage weapon, try aiming at feet - trace down to find floor
02069		}
02070		else
02071		{
02072			FireDir = BestTarget.Location - projStart;
02073			AimSpot = projStart + bestDist * Normal(FireDir);
02074		}
02075		AimOffset = AimSpot - OldAim;
02076	
02077		// adjust Z of shooter if necessary
02078		if ( bNoZAdjust || (bLeading && (Abs(AimOffset.Z) < BestTarget.CollisionHeight)) )
02079			AimSpot.Z = OldAim.Z;
02080		else if ( AimOffset.Z < 0 )
02081			AimSpot.Z = BestTarget.Location.Z + 0.4 * BestTarget.CollisionHeight;
02082		else
02083			AimSpot.Z = BestTarget.Location.Z - 0.7 * BestTarget.CollisionHeight;
02084	
02085		if ( !bLeading )
02086		{
02087			// if not leading, add slight random error ( significant at long distances )
02088			if ( !bNoZAdjust )
02089			{
02090				AimRot = rotator(AimSpot - projStart);
02091				if ( FOVAngle < DefaultFOV - 8 )
02092					AimRot.Yaw = AimRot.Yaw + 200 - Rand(400);
02093				else
02094					AimRot.Yaw = AimRot.Yaw + 375 - Rand(750);
02095				return AimRot;
02096			}
02097		}
02098		else if ( !FastTrace(projStart + 0.9 * bestDist * Normal(FireDir), projStart) )
02099		{
02100			FireDir = BestTarget.Location - projStart;
02101			AimSpot = projStart + bestDist * Normal(FireDir);
02102		}
02103	
02104		return rotator(AimSpot - projStart);
02105	}
02106	*/
02107	
02108	native(498) static final function rotator AdjustAimForDisplay(Ammunition FiredAmmunition, vector projStart);
02109	
02110	function bool NotifyLanded(vector HitNormal)
02111	{
02112		if ( bUpdating )
02113			return true;
02114		LandBob = FMin(50, 0.055 * Pawn.Velocity.Z);
02115		return false;
02116	}
02117	
02118	function eAttitude AttitudeTo(Pawn Other)
02119	{
02120		if ( Other.Controller == None )
02121			return ATTITUDE_Ignore;
02122		if ( Other.IsPlayerPawn() )
02123			return AttitudeToPlayer;
02124		return Other.Controller.AttitudeToPlayer;
02125	}
02126	
02127	//=============================================================================
02128	// Player Control
02129	
02130	// Player view.
02131	// Compute the rendering viewpoint for the player.
02132	//
02133	
02134	function AdjustView(float DeltaTime )
02135	{
02136		// teleporters affect your FOV, so adjust it back down
02137		if ( FOVAngle != DesiredFOV )
02138		{
02139			if ( FOVAngle > DesiredFOV )
02140				FOVAngle = FOVAngle - FMax(7, 0.9 * DeltaTime * (FOVAngle - DesiredFOV));
02141			else
02142				FOVAngle = FOVAngle - FMin(-7, 0.9 * DeltaTime * (FOVAngle - DesiredFOV));
02143			if ( Abs(FOVAngle - DesiredFOV) <= 10 )
02144				FOVAngle = DesiredFOV;
02145		}
02146	
02147		// adjust FOV for weapon zooming
02148		if ( bZooming )
02149		{
02150			ZoomLevel += DeltaTime * 1.0;
02151			if (ZoomLevel > 0.9)
02152				ZoomLevel = 0.9;
02153			DesiredFOV = FClamp(90.0 - (ZoomLevel * 88.0), 1, 170);
02154		}
02155	}
02156	
02157	function CalcBehindView(out vector CameraLocation, out rotator CameraRotation, float Dist)
02158	{
02159		local vector View,HitLocation,HitNormal;
02160		local float ViewDist;
02161	
02162		CameraRotation = Rotation;
02163		View = vect(1,0,0) >> CameraRotation;
02164		if( Trace( HitLocation, HitNormal, CameraLocation - (Dist + 30) * vector(CameraRotation), CameraLocation ) != None )
02165			ViewDist = FMin( (CameraLocation - HitLocation) Dot View, Dist );
02166		else
02167			ViewDist = Dist;
02168		CameraLocation -= (ViewDist - 30) * View;
02169	}
02170	
02171	/*function CalcFirstPersonView( out vector CameraLocation, out rotator CameraRotation )
02172	{
02173		// First-person view.
02174		CameraRotation = Rotation;
02175		CameraLocation = CameraLocation + Pawn.EyePosition() + WalkBob + ShakeOffset;
02176	}*/
02177	native(497) static final function CalcFirstPersonView( out vector CameraLocation, out rotator CameraRotation );
02178	
02179	event PlayerCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation )
02180	{
02181		local Pawn PTarget;
02182	
02183		if ( (ViewTarget == None) || ViewTarget.bDeleteMe )
02184		{
02185			if ( (Pawn != None) && !Pawn.bDeleteMe )
02186				SetViewTarget(Pawn);
02187			else
02188				SetViewTarget(self);
02189		}
02190	
02191		ViewActor = ViewTarget;
02192		CameraLocation = ViewTarget.Location;
02193	
02194		if ( ViewTarget == Pawn )
02195		{
02196			if( bBehindView ) //up and behind
02197				CalcBehindView(CameraLocation, CameraRotation, CameraDist * Pawn.Default.CollisionRadius);
02198			else
02199				CalcFirstPersonView( CameraLocation, CameraRotation );
02200			return;
02201		}
02202		if ( ViewTarget == self )
02203		{
02204			CameraRotation = Rotation;
02205			return;
02206		}
02207		CameraRotation = ViewTarget.Rotation;
02208		PTarget = Pawn(ViewTarget);
02209		if ( PTarget != None )
02210		{
02211			if ( Level.NetMode == NM_Client )
02212			{
02213				if ( PTarget.IsPlayerPawn() )
02214				{
02215					PTarget.SetViewRotation(TargetViewRotation);
02216					CameraRotation = TargetViewRotation;
02217				}
02218				PTarget.EyeHeight = TargetEyeHeight;
02219				if ( PTarget.Weapon != None )
02220					PTarget.Weapon.PlayerViewOffset = TargetWeaponViewOffset;
02221			}
02222			else if ( PTarget.IsPlayerPawn() )
02223				CameraRotation = PTarget.GetViewRotation();
02224			if ( !bBehindView )
02225				CameraLocation += PTarget.EyePosition();
02226		}
02227		if ( bBehindView )
02228		{
02229			CameraLocation = CameraLocation + (ViewTarget.Default.CollisionHeight - ViewTarget.CollisionHeight) * vect(0,0,1);
02230			CalcBehindView(CameraLocation, CameraRotation, CameraDist * ViewTarget.Default.CollisionRadius);
02231		}
02232	}
02233	
02234	/*function CheckShake(out float MaxOffset, out float Offset, out float Rate, out float Time)
02235	{
02236		if ( abs(Offset) < abs(MaxOffset) )
02237			return;
02238	
02239		Offset = MaxOffset;
02240		if ( Time > 1 )
02241		{
02242			if ( Time * abs(MaxOffset/Rate) <= 1 )
02243				MaxOffset = MaxOffset * (1/Time - 1);
02244			else
02245				MaxOffset *= -1;
02246			Time -= 1;
02247			Rate *= -1;
02248		}
02249		else
02250		{
02251			MaxOffset = 0;
02252			Offset = 0;
02253			Rate = 0;
02254		}
02255	}
02256	
02257	function ViewShake(float DeltaTime)
02258	{
02259		local Rotator ViewRotation;
02260		local float FRoll;
02261	
02262		if ( ShakeOffsetRate != vect(0,0,0) )
02263		{
02264			// modify shake offset
02265			ShakeOffset.X += DeltaTime * ShakeOffsetRate.X;
02266			CheckShake(MaxShakeOffset.X, ShakeOffset.X, ShakeOffsetRate.X, ShakeOffsetTime.X);
02267	
02268			ShakeOffset.Y += DeltaTime * ShakeOffsetRate.Y;
02269			CheckShake(MaxShakeOffset.Y, ShakeOffset.Y, ShakeOffsetRate.Y, ShakeOffsetTime.Y);
02270	
02271			ShakeOffset.Z += DeltaTime * ShakeOffsetRate.Z;
02272			CheckShake(MaxShakeOffset.Z, ShakeOffset.Z, ShakeOffsetRate.Z, ShakeOffsetTime.Z);
02273		}
02274	
02275		ViewRotation = Rotation;
02276	
02277		if ( ShakeRollRate != 0 )
02278		{
02279			ViewRotation.Roll = ((ViewRotation.Roll & 65535) + ShakeRollRate * DeltaTime) & 65535;
02280			if ( ViewRotation.Roll > 32768 )
02281				ViewRotation.Roll -= 65536;
02282			FRoll = ViewRotation.Roll;
02283			CheckShake(MaxShakeRoll, FRoll, ShakeRollRate, ShakeRollTime);
02284			ViewRotation.Roll = FRoll;
02285		}
02286		else if ( bZeroRoll )
02287			ViewRotation.Roll = 0;
02288		SetRotation(ViewRotation);
02289	}*/
02290	native(496) static final function ViewShake(float DeltaTime);
02291	
02292	function bool TurnTowardNearestEnemy();
02293	
02294	function TurnAround()
02295	{
02296		if ( !bSetTurnRot )
02297		{
02298			TurnRot180 = Rotation;
02299			TurnRot180.Yaw += 32768;
02300			bSetTurnRot = true;
02301		}
02302	
02303		DesiredRotation = TurnRot180;
02304		bRotateToDesired = ( DesiredRotation.Yaw != Rotation.Yaw );
02305	}
02306	
02307	function UpdateRotation(float DeltaTime, float maxPitch)
02308	{
02309		local rotator newRotation, ViewRotation;
02310	
02311		if ( bInterpolating || ((Pawn != None) && Pawn.bInterpolating) )
02312		{
02313			ViewShake(deltaTime);
02314			return;
02315		}
02316		ViewRotation = Rotation;
02317		DesiredRotation = ViewRotation; //save old rotation
02318		if ( bTurnToNearest != 0 )
02319			TurnTowardNearestEnemy();
02320		else if ( bTurn180 != 0 )
02321			TurnAround();
02322		else
02323		{
02324			TurnTarget = None;
02325			bRotateToDesired = false;
02326			bSetTurnRot = false;
02327			ViewRotation.Yaw += 32.0 * DeltaTime * aTurn;
02328			ViewRotation.Pitch += 32.0 * DeltaTime * aLookUp;
02329		}
02330		ViewRotation.Pitch = ViewRotation.Pitch & 65535;
02331		If ((ViewRotation.Pitch > 18000) && (ViewRotation.Pitch < 49152))
02332		{
02333			If (aLookUp > 0)
02334				ViewRotation.Pitch = 18000;
02335			else
02336				ViewRotation.Pitch = 49152;
02337		}
02338	
02339		SetRotation(ViewRotation);
02340		ViewShake(deltaTime);
02341		ViewFlash(deltaTime);
02342	
02343		NewRotation = ViewRotation;
02344		NewRotation.Roll = Rotation.Roll;
02345	
02346		if ( !bRotateToDesired && (Pawn != None) && (!bFreeCamera || !bBehindView) )
02347			Pawn.FaceRotation(NewRotation, deltatime);
02348	}
02349	
02350	// Player movement.
02351	// Player Standing, walking, running, falling.
02352	state PlayerWalking
02353	{
02354	ignores SeePlayer, Bump;
02355	
02356		function bool NotifyPhysicsVolumeChange( PhysicsVolume NewVolume )
02357		{
02358			if ( NewVolume.bWaterVolume )
02359				GotoState(Pawn.WaterMovementState);
02360			return false;
02361		}
02362	
02363		function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
02364		{
02365			local vector OldAccel;
02366			local bool OldCrouch;
02367	
02368			OldAccel = Pawn.Acceleration;
02369			Pawn.Acceleration = NewAccel;
02370			if ( bPressedJump )
02371				Pawn.DoJump(bUpdating);
02372			if ( Pawn.Physics != PHYS_Falling )
02373			{
02374				OldCrouch = Pawn.bWantsToCrouch;
02375				if (bDuck == 0)
02376					Pawn.ShouldCrouch(false);
02377				else if ( Pawn.bCanCrouch )
02378					Pawn.ShouldCrouch(true);
02379			}
02380		}
02381	
02382		function PlayerMove( float DeltaTime )
02383		{
02384			local vector X,Y,Z, NewAccel;
02385			local eDoubleClickDir DoubleClickMove;
02386			local rotator OldRotation, ViewRotation;
02387			local float Speed2D;
02388			local bool	bSaveJump;
02389	
02390			GetAxes(Pawn.Rotation,X,Y,Z);
02391	
02392			// Update acceleration.
02393			NewAccel = aForward*X + aStrafe*Y;
02394			NewAccel.Z = 0;
02395			if ( VSize(NewAccel) < 1.0 )
02396				NewAccel = vect(0,0,0);
02397			DoubleClickMove = PlayerInput.CheckForDoubleClickMove(DeltaTime);
02398	
02399			GroundPitch = 0;
02400			ViewRotation = Rotation;
02401			if ( Pawn.Physics == PHYS_Walking )
02402			{
02403				// tell pawn about any direction changes to give it a chance to play appropriate animation
02404				//if walking, look up/down stairs - unless player is rotating view
02405				GroundPitch = FindStairRotation(deltaTime);
02406				if ( (bLook == 0)
02407					&& (((Pawn.Acceleration != Vect(0,0,0)) && bAlwaysLevel && bSnapToLevel) || !bKeyboardLook) )
02408				{
02409					if ( bLookUpStairs || bSnapToLevel )
02410					{
02411						ViewRotation.Pitch = GroundPitch;
02412					}
02413					else if ( bCenterView )
02414					{
02415						ViewRotation.Pitch = ViewRotation.Pitch & 65535;
02416						if (ViewRotation.Pitch > 32768)
02417							ViewRotation.Pitch -= 65536;
02418						ViewRotation.Pitch = ViewRotation.Pitch * (1 - 12 * FMin(0.0833, deltaTime));
02419						if ( Abs(ViewRotation.Pitch) < 1000 )
02420							ViewRotation.Pitch = 0;
02421					}
02422				}
02423	
02424				Speed2D = Sqrt(Pawn.Velocity.X * Pawn.Velocity.X + Pawn.Velocity.Y * Pawn.Velocity.Y);
02425				//add bobbing when walking
02426				CheckBob(DeltaTime, Speed2D, Y);
02427			}
02428			else
02429			{
02430				if ( !bKeyboardLook && (bLook == 0) && bCenterView )
02431				{
02432					ViewRotation.Pitch = ViewRotation.Pitch & 65535;
02433					if (ViewRotation.Pitch > 32768)
02434						ViewRotation.Pitch -= 65536;
02435					ViewRotation.Pitch = ViewRotation.Pitch * (1 - 12 * FMin(0.0833, deltaTime));
02436					if ( Abs(ViewRotation.Pitch) < 1000 )
02437						ViewRotation.Pitch = 0;
02438				}
02439				BobTime = 0;
02440				WalkBob = WalkBob * (1 - FMin(1, 8 * deltatime));
02441			}
02442	
02443			// Update rotation.
02444			SetRotation(ViewRotation);
02445			OldRotation = Rotation;
02446			UpdateRotation(DeltaTime, 1);
02447	
02448			if ( bPressedJump && Pawn.CannotJumpNow() )
02449			{
02450				bSaveJump = true;
02451				bPressedJump = false;
02452			}
02453			else
02454				bSaveJump = false;
02455	
02456			if ( Role < ROLE_Authority ) // then save this move and replicate it
02457				ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
02458			else
02459				ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
02460			bPressedJump = bSaveJump;
02461		}
02462	
02463		function BeginState()
02464		{
02465			if ( Pawn.Mesh == None )
02466				Pawn.SetMesh();
02467			WalkBob = vect(0,0,0);
02468			DoubleClickDir = DCLICK_None;
02469			Pawn.ShouldCrouch(false);
02470			bPressedJump = false;
02471			if (Pawn.Physics != PHYS_Falling)
02472				Pawn.SetPhysics(PHYS_Walking);
02473			GroundPitch = 0;
02474		}
02475	
02476		function EndState()
02477		{
02478			GroundPitch = 0;
02479			WalkBob = vect(0,0,0);
02480			if ( Pawn != None )
02481				Pawn.ShouldCrouch(false);
02482		}
02483	}
02484	
02485	// player is climbing ladder
02486	state PlayerClimbing
02487	{
02488	ignores SeePlayer, Bump;
02489	
02490		function bool NotifyPhysicsVolumeChange( PhysicsVolume NewVolume )
02491		{
02492			if ( NewVolume.bWaterVolume )
02493				GotoState(Pawn.WaterMovementState);
02494			else
02495				GotoState(Pawn.LandMovementState);
02496			return false;
02497		}
02498	
02499		function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
02500		{
02501			local vector OldAccel;
02502	
02503			OldAccel = Pawn.Acceleration;
02504			Pawn.Acceleration = NewAccel;
02505	
02506			if ( bPressedJump )
02507			{
02508				Pawn.DoJump(bUpdating);
02509				if ( Pawn.Physics == PHYS_Falling )
02510					GotoState('PlayerWalking');
02511			}
02512		}
02513	
02514		function PlayerMove( float DeltaTime )
02515		{
02516			local vector X,Y,Z, NewAccel;
02517			local eDoubleClickDir DoubleClickMove;
02518			local rotator OldRotation, ViewRotation;
02519			local float Speed2D;
02520			local bool	bSaveJump;
02521	
02522			GetAxes(Rotation,X,Y,Z);
02523	
02524			// Update acceleration.
02525			//if ( Pawn.OnLadder != None )
02526			//	NewAccel = aForward*Pawn.OnLadder.ClimbDir;
02527			//else
02528				NewAccel = aForward*X + aStrafe*Y;
02529			if ( VSize(NewAccel) < 1.0 )
02530				NewAccel = vect(0,0,0);
02531	
02532			ViewRotation = Rotation;
02533	
02534			// Update rotation.
02535			SetRotation(ViewRotation);
02536			OldRotation = Rotation;
02537			UpdateRotation(DeltaTime, 1);
02538	
02539			if ( Role < ROLE_Authority ) // then save this move and replicate it
02540				ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
02541			else
02542				ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
02543			bPressedJump = bSaveJump;
02544		}
02545	
02546		function BeginState()
02547		{
02548			Pawn.ShouldCrouch(false);
02549			bPressedJump = false;
02550		}
02551	
02552		function EndState()
02553		{
02554			if ( Pawn != None )
02555				Pawn.ShouldCrouch(false);
02556		}
02557	}
02558	
02559	
02560	// Player movement.
02561	// Player walking on walls
02562	state PlayerSpidering
02563	{
02564	ignores SeePlayer, Bump;
02565	
02566		event bool NotifyHitWall(vector HitNormal, actor HitActor)
02567		{
02568			// FIXME - pawn should have bool identifying if this was a voluntary jump
02569			Pawn.SetPhysics(PHYS_Spider);
02570			Pawn.SetBase(HitActor, HitNormal);
02571			return true;
02572		}
02573	
02574		// if spider mode, update rotation based on floor
02575		function UpdateRotation(float DeltaTime, float maxPitch)
02576		{
02577			local rotator TempRot, ViewRotation;
02578			local vector MyFloor, CrossDir, FwdDir, OldFwdDir, OldX, RealFloor;
02579	
02580			if ( bInterpolating || Pawn.bInterpolating )
02581			{
02582				ViewShake(deltaTime);
02583				return;
02584			}
02585	
02586			TurnTarget = None;
02587			bRotateToDesired = false;
02588			bSetTurnRot = false;
02589	
02590			if ( (Pawn.Base == None) || (Pawn.Floor == vect(0,0,0)) )
02591				MyFloor = vect(0,0,1);
02592			else
02593				MyFloor = Pawn.Floor;
02594	
02595			if ( MyFloor != OldFloor )
02596			{
02597				// smoothly change floor
02598				RealFloor = MyFloor;
02599				MyFloor = Normal(6*DeltaTime * MyFloor + (1 - 6*DeltaTime) * OldFloor);
02600				if ( (RealFloor Dot MyFloor) > 0.999 )
02601					MyFloor = RealFloor;
02602	
02603				// translate view direction
02604				CrossDir = Normal(RealFloor Cross OldFloor);
02605				FwdDir = CrossDir Cross MyFloor;
02606				OldFwdDir = CrossDir Cross OldFloor;
02607				ViewX = MyFloor * (OldFloor Dot ViewX)
02608							+ CrossDir * (CrossDir Dot ViewX)
02609							+ FwdDir * (OldFwdDir Dot ViewX);
02610				ViewX = Normal(ViewX);
02611	
02612				ViewZ = MyFloor * (OldFloor Dot ViewZ)
02613							+ CrossDir * (CrossDir Dot ViewZ)
02614							+ FwdDir * (OldFwdDir Dot ViewZ);
02615				ViewZ = Normal(ViewZ);
02616				OldFloor = MyFloor;
02617				ViewY = Normal(MyFloor Cross ViewX);
02618			}
02619	
02620			if ( (aTurn != 0) || (aLookUp != 0) )
02621			{
02622				// adjust Yaw based on aTurn
02623				if ( aTurn != 0 )
02624					ViewX = Normal(ViewX + 2 * ViewY * Sin(0.0005*DeltaTime*aTurn));
02625	
02626				// adjust Pitch based on aLookUp
02627				if ( aLookUp != 0 )
02628				{
02629					OldX = ViewX;
02630					ViewX = Normal(ViewX + 2 * ViewZ * Sin(0.0005*DeltaTime*aLookUp));
02631					ViewZ = Normal(ViewX Cross ViewY);
02632	
02633					// bound max pitch
02634					if ( (ViewZ Dot MyFloor) < 0.707   )
02635					{
02636						OldX = Normal(OldX - MyFloor * (MyFloor Dot OldX));
02637						if ( (ViewX Dot MyFloor) > 0)
02638							ViewX = Normal(OldX + MyFloor);
02639						else
02640							ViewX = Normal(OldX - MyFloor);
02641	
02642						ViewZ = Normal(ViewX Cross ViewY);
02643					}
02644				}
02645	
02646				// calculate new Y axis
02647				ViewY = Normal(MyFloor Cross ViewX);
02648			}
02649			ViewRotation =  OrthoRotation(ViewX,ViewY,ViewZ);
02650			SetRotation(ViewRotation);
02651			ViewShake(deltaTime);
02652			ViewFlash(deltaTime);
02653			Pawn.FaceRotation(ViewRotation, deltaTime );
02654		}
02655	
02656		function bool NotifyLanded(vector HitNormal)
02657		{
02658			Pawn.SetPhysics(PHYS_Spider);
02659			if ( bUpdating )
02660				return true;
02661			LandBob = FMin(50, 0.055 * Pawn.Velocity.Z);
02662			return false;
02663		}
02664	
02665		function bool NotifyPhysicsVolumeChange( PhysicsVolume NewVolume )
02666		{
02667			if ( NewVolume.bWaterVolume )
02668				GotoState(Pawn.WaterMovementState);
02669			return false;
02670		}
02671	
02672		function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
02673		{
02674			local vector OldAccel;
02675	
02676			OldAccel = Pawn.Acceleration;
02677			Pawn.Acceleration = NewAccel;
02678	
02679			if ( bPressedJump )
02680				Pawn.DoJump(bUpdating);
02681		}
02682	
02683		function PlayerMove( float DeltaTime )
02684		{
02685			local vector NewAccel;
02686			local eDoubleClickDir OldDoubleClick;
02687			local eDoubleClickDir DoubleClickMove;
02688			local rotator OldRotation, ViewRotation;
02689			local float Speed2D;
02690			local bool	bSaveJump;
02691	
02692			GroundPitch = 0;
02693			ViewRotation = Rotation;
02694	
02695			if ( !bKeyboardLook && (bLook == 0) && bCenterView )
02696			{
02697				// FIXME - center view rotation based on current floor
02698			}
02699			BobTime = 0;
02700			WalkBob = WalkBob * (1 - FMin(1, 8 * deltatime));
02701	
02702			// Update rotation.
02703			SetRotation(ViewRotation);
02704			OldRotation = Rotation;
02705			UpdateRotation(DeltaTime, 1);
02706	
02707			// Update acceleration.
02708			NewAccel = aForward*Normal(ViewX - OldFloor * (OldFloor Dot ViewX)) + aStrafe*ViewY;
02709			if ( VSize(NewAccel) < 1.0 )
02710				NewAccel = vect(0,0,0);
02711	
02712			if ( bPressedJump && Pawn.CannotJumpNow() )
02713			{
02714				bSaveJump = true;
02715				bPressedJump = false;
02716			}
02717			else
02718				bSaveJump = false;
02719	
02720			if ( Role < ROLE_Authority ) // then save this move and replicate it
02721				ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
02722			else
02723				ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
02724			bPressedJump = bSaveJump;
02725		}
02726	
02727		function BeginState()
02728		{
02729			local Rotator NewRot;
02730	
02731			if ( Pawn.Mesh == None )
02732				Pawn.SetMesh();
02733			OldFloor = vect(0,0,1);
02734			GetAxes(Rotation,ViewX,ViewY,ViewZ);
02735			WalkBob = vect(0,0,0);
02736			DoubleClickDir = DCLICK_None;
02737			Pawn.ShouldCrouch(false);
02738			bPressedJump = false;
02739			if (Pawn.Physics != PHYS_Falling)
02740				Pawn.SetPhysics(PHYS_Spider);
02741			GroundPitch = 0;
02742			Pawn.bCrawler = true;
02743			Pawn.SetCollisionSize(Pawn.Default.CollisionHeight,Pawn.Default.CollisionHeight);
02744		}
02745	
02746		function EndState()
02747		{
02748			GroundPitch = 0;
02749			WalkBob = vect(0,0,0);
02750			if ( Pawn != None )
02751			{
02752				Pawn.SetCollisionSize(Pawn.Default.CollisionRadius,Pawn.Default.CollisionHeight);
02753				Pawn.ShouldCrouch(false);
02754				Pawn.bCrawler = Pawn.Default.bCrawler;
02755			}
02756		}
02757	}
02758	
02759	// Player movement.
02760	// Player Swimming
02761	state PlayerSwimming
02762	{
02763	ignores SeePlayer, Bump;
02764	
02765		function bool WantsSmoothedView()
02766		{
02767			return ( !Pawn.bJustLanded );
02768		}
02769	
02770		function bool NotifyLanded(vector HitNormal)
02771		{
02772			if ( Pawn.PhysicsVolume.bWaterVolume )
02773				Pawn.SetPhysics(PHYS_Swimming);
02774			else
02775				GotoState(Pawn.LandMovementState);
02776			return bUpdating;
02777		}
02778	
02779		function bool NotifyPhysicsVolumeChange( PhysicsVolume NewVolume )
02780		{
02781			local actor HitActor;
02782			local vector HitLocation, HitNormal, checkpoint;
02783	
02784			if ( !NewVolume.bWaterVolume )
02785			{
02786				Pawn.SetPhysics(PHYS_Falling);
02787				if (Pawn.bUpAndOut && Pawn.CheckWaterJump(HitNormal)) //check for waterjump
02788				{
02789					Pawn.velocity.Z = 330 + 2 * Pawn.CollisionRadius; //set here so physics uses this for remainder of tick
02790					GotoState(Pawn.LandMovementState);
02791				}
02792				else if ( (Pawn.Velocity.Z > 160) || !Pawn.TouchingWaterVolume() )
02793					GotoState(Pawn.LandMovementState);
02794				else //check if in deep water
02795				{
02796					checkpoint = Pawn.Location;
02797					checkpoint.Z -= (Pawn.CollisionHeight + 6.0);
02798					HitActor = Trace(HitLocation, HitNormal, checkpoint, Pawn.Location, false);
02799					if (HitActor != None)
02800						GotoState(Pawn.LandMovementState);
02801					else
02802					{
02803						Enable('Timer');
02804						SetTimer(0.7,false);
02805					}
02806				}
02807			}
02808			else
02809			{
02810				Disable('Timer');
02811				Pawn.SetPhysics(PHYS_Swimming);
02812			}
02813			return false;
02814		}
02815	
02816		function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
02817		{
02818			local vector X,Y,Z, OldAccel;
02819	
02820			GetAxes(Rotation,X,Y,Z);
02821			OldAccel = Pawn.Acceleration;
02822			Pawn.Acceleration = NewAccel;
02823			Pawn.bUpAndOut = ((X Dot Pawn.Acceleration) > 0) && ((Pawn.Acceleration.Z > 0) || (Rotation.Pitch > 2048));
02824			if ( !Pawn.PhysicsVolume.bWaterVolume ) //check for waterjump
02825				NotifyPhysicsVolumeChange(Pawn.PhysicsVolume);
02826		}
02827	
02828		function PlayerMove(float DeltaTime)
02829		{
02830			local rotator oldRotation;
02831			local vector X,Y,Z, NewAccel;
02832			local float Speed2D;
02833	
02834			GetAxes(Rotation,X,Y,Z);
02835	
02836			NewAccel = aForward*X + aStrafe*Y + aUp*vect(0,0,1);
02837			if ( VSize(NewAccel) < 1.0 )
02838				NewAccel = vect(0,0,0);
02839	
02840			//add bobbing when swimming
02841			Speed2D = Sqrt(Pawn.Velocity.X * Pawn.Velocity.X + Pawn.Velocity.Y * Pawn.Velocity.Y);
02842			WalkBob = Y * Bob *  0.5 * Speed2D * sin(4.0 * Level.TimeSeconds);
02843			WalkBob.Z = Bob * 1.5 * Speed2D * sin(8.0 * Level.TimeSeconds);
02844	
02845			// Update rotation.
02846			oldRotation = Rotation;
02847			UpdateRotation(DeltaTime, 2);
02848	
02849			if ( Role < ROLE_Authority ) // then save this move and replicate it
02850				ReplicateMove(DeltaTime, NewAccel, DCLICK_None, OldRotation - Rotation);
02851			else
02852				ProcessMove(DeltaTime, NewAccel, DCLICK_None, OldRotation - Rotation);
02853			bPressedJump = false;
02854		}
02855	
02856		function Timer()
02857		{
02858			if ( !Pawn.PhysicsVolume.bWaterVolume && (Role == ROLE_Authority) )
02859				GotoState(Pawn.LandMovementState);
02860	
02861			Disable('Timer');
02862		}
02863	
02864		function BeginState()
02865		{
02866			Disable('Timer');
02867			Pawn.SetPhysics(PHYS_Swimming);
02868		}
02869	}
02870	
02871	state PlayerFlying
02872	{
02873	ignores SeePlayer, Bump;
02874	
02875		function PlayerMove(float DeltaTime)
02876		{
02877			local rotator newRotation;
02878			local vector X,Y,Z;
02879	
02880			GetAxes(Rotation,X,Y,Z);
02881	
02882			Pawn.Acceleration = aForward*X + aStrafe*Y;
02883			if ( VSize(Pawn.Acceleration) < 1.0 )
02884				Pawn.Acceleration = vect(0,0,0);
02885			if ( bCheatFlying && (Pawn.Acceleration == vect(0,0,0)) )
02886				Pawn.Velocity = vect(0,0,0);
02887			// Update rotation.
02888			UpdateRotation(DeltaTime, 2);
02889	
02890			if ( Role < ROLE_Authority ) // then save this move and replicate it
02891				ReplicateMove(DeltaTime, Pawn.Acceleration, DCLICK_None, rot(0,0,0));
02892			else
02893				ProcessMove(DeltaTime, Pawn.Acceleration, DCLICK_None, rot(0,0,0));
02894		}
02895	
02896		function BeginState()
02897		{
02898			Pawn.SetPhysics(PHYS_Flying);
02899		}
02900	}
02901	
02902	state PlayerHelicoptering extends PlayerFlying
02903	{
02904		function PlayerMove(float DeltaTime)
02905		{
02906			local rotator newRotation;
02907			local vector X,Y,Z;
02908	
02909			GetAxes(Rotation,X,Y,Z);
02910	
02911			Pawn.Acceleration = aForward*X + aStrafe*Y + aUp*vect(0,0,1);
02912			if ( VSize(Pawn.Acceleration) < 1.0 )
02913				Pawn.Acceleration = vect(0,0,0);
02914			if ( bCheatFlying && (Pawn.Acceleration == vect(0,0,0)) )
02915				Pawn.Velocity = vect(0,0,0);
02916			// Update rotation.
02917			UpdateRotation(DeltaTime, 2);
02918	
02919			if ( Role < ROLE_Authority ) // then save this move and replicate it
02920				ReplicateMove(DeltaTime, Pawn.Acceleration, DCLICK_None, rot(0,0,0));
02921			else
02922				ProcessMove(DeltaTime, Pawn.Acceleration, DCLICK_None, rot(0,0,0));
02923		}
02924	}
02925	
02926	state BaseSpectating
02927	{
02928		function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
02929		{
02930			Acceleration = NewAccel;
02931			MoveSmooth(Acceleration * DeltaTime);
02932		}
02933	
02934		function PlayerMove(float DeltaTime)
02935		{
02936			local rotator newRotation;
02937			local vector X,Y,Z;
02938	
02939			GetAxes(Rotation,X,Y,Z);
02940	
02941			Acceleration = 0.02 * (aForward*X + aStrafe*Y + aUp*vect(0,0,1));
02942	
02943			UpdateRotation(DeltaTime, 1);
02944	
02945			if ( Role < ROLE_Authority ) // then save this move and replicate it
02946				ReplicateMove(DeltaTime, Acceleration, DCLICK_None, rot(0,0,0));
02947			else
02948				ProcessMove(DeltaTime, Acceleration, DCLICK_None, rot(0,0,0));
02949		}
02950	}
02951	
02952	state Spectating extends BaseSpectating
02953	{
02954		ignores SwitchWeapon, RestartLevel, ClientRestart, Suicide,
02955		 ThrowWeapon, NotifyPhysicsVolumeChange, NotifyHeadVolumeChange;
02956	
02957		exec function NextWeapon()
02958		{
02959			Fire();
02960		}
02961	
02962		exec function PrevWeapon()
02963		{
02964			if ( ViewTarget == self )
02965				bBehindView = false;
02966			else
02967				bBehindView = true; //bChaseCam;
02968		}
02969	
02970		exec function Fire( optional float F )
02971		{
02972			local Controller C, Pick;
02973			local bool bFound;
02974	
02975			if ( Role == ROLE_Authority )
02976			{
02977				// view next player
02978				for ( C=Level.ControllerList; C!=None; C=C.NextController )
02979					if ( (C.Pawn != None) && Level.Game.CanSpectate(self,C.Pawn) )
02980					{
02981						if ( Pick == None )
02982							Pick = C;
02983						if ( bFound )
02984						{
02985							Pick = C;
02986							break;
02987						}
02988						else
02989							bFound = ( ViewTarget == C.Pawn );
02990					}
02991				SetViewTarget(Pick.Pawn);
02992				if ( ViewTarget == self )
02993					bBehindView = false;
02994				else
02995					bBehindView = true; //bChaseCam;
02996			}
02997		}
02998	
02999		// Return to spectator's own camera.
03000		exec function AltFire( optional float F )
03001		{
03002			bBehindView = false;
03003			SetViewtarget(self);
03004			ClientMessage(OwnCamera, 'Event');
03005		}
03006	
03007		function BeginState()
03008		{
03009			if ( Pawn != None )
03010			{
03011				SetLocation(Pawn.Location);
03012				UnPossess();
03013			}
03014			bCollideWorld = true;
03015		}
03016	
03017		function EndState()
03018		{
03019			PlayerReplicationInfo.bIsSpectator = false;
03020			bCollideWorld = false;
03021		}
03022	}
03023	
03024	//_____________________________________________________________________________
03025	auto state PlayerWaiting extends BaseSpectating
03026	{
03027	    ignores SeePlayer, NotifyBump, TakeDamage, PhysicsVolumeChange;
03028	    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot);
03029	    function PlayerMove(float DeltaTime);
03030	    exec function Jump( optional float F );
03031	    exec function Suicide();
03032	
03033	    function ChangeTeam( int N )
03034	    {
03035	      Level.Game.ChangeTeam(self, N);
03036	    }
03037	
03038	    function ServerReStartPlayer()
03039	    {
03040	      Log("PlayerWaiting ServerReStartPlayer"@self);
03041	      if ( Level.TimeSeconds < WaitDelay )
03042	      {
03043	        Log("  Cancel ServerReStartPlayer because WaitDelay"@WaitDelay@">Level.TimeSeconds"@Level.TimeSeconds);
03044	        return;
03045	      }
03046	      if ( Level.NetMode == NM_Client )
03047	      {
03048	        Log("  Cancel ServerReStartPlayer because Client");
03049	        return;
03050	      }
03051	      if ( Level.Game.bWaitingToStartMatch )
03052	      {
03053	        Log("  Set PRI"@PlayerReplicationInfo@"ReadyToPlay");
03054	        PlayerReplicationInfo.bReadyToPlay = true;
03055	      }
03056	      else
03057	      {
03058	        Log("  Restart Player"@self);
03059	        Level.Game.RestartPlayer(self);
03060	      }
03061	    }
03062	
03063	    exec function Fire(optional float F)
03064	    {
03065	      Log("PlayerWaiting Fire"@self);
03066	      ServerReStartPlayer();
03067	    }
03068	
03069	    exec function AltFire(optional float F);
03070	
03071	    function EndState()
03072	    {
03073	      if ( Pawn != None )
03074	        Pawn.SetMesh();
03075	      PlayerReplicationInfo.SetWaitingPlayer(false);
03076	      bCollideWorld = false;
03077	      Log("PlayerWaiting EndState"@self);
03078	    }
03079	
03080	    function BeginState()
03081	    {
03082	      if ( PlayerReplicationInfo != None )
03083	        PlayerReplicationInfo.SetWaitingPlayer(true);
03084	      bCollideWorld = true;
03085	      myHUD.bShowScores = false;
03086	      Log("PlayerWaiting BeginState"@self);
03087	    }
03088	}
03089	/*
03090	auto state PlayerWaiting
03091	{
03092	    function EndState()
03093	    {
03094	      if ( Pawn != None )
03095	        Pawn.SetMesh();
03096	      PlayerReplicationInfo.SetWaitingPlayer(false);
03097	      bCollideWorld = false;
03098	      Log("PlayerWaiting EndState Player="$player);
03099	    }
03100	
03101	    function BeginState()
03102	    {
03103	      Super.BeginState();
03104	      Log("PlayerWaiting BeginState Player="$player);
03105	    }
03106	    exec function Fire(optional float F)
03107	    {
03108	      if (!Player.LocalInteractions[0].IsInState('UWindows'))
03109	        ServerReStartPlayer();
03110	    }
03111	    exec function UnFire(optional float F);
03112	}*/
03113	
03114	state WaitingForPawn extends BaseSpectating
03115	{
03116	ignores SeePlayer, HearNoise, KilledBy, SwitchWeapon;
03117	
03118		exec function Fire( optional float F )
03119		{
03120		}
03121	
03122		exec function AltFire( optional float F )
03123		{
03124		}
03125	
03126		function LongClientAdjustPosition
03127		(
03128			float TimeStamp,
03129			name newState,
03130			EPhysics newPhysics,
03131			float NewLocX,
03132			float NewLocY,
03133			float NewLocZ,
03134			float NewVelX,
03135			float NewVelY,
03136			float NewVelZ,
03137			Actor NewBase,
03138			float NewFloorX,
03139			float NewFloorY,
03140			float NewFloorZ
03141		)
03142		{
03143		}
03144	
03145		function PlayerTick(float DeltaTime)
03146		{
03147	//    Log(self@"WaitingForPawn PlayerTick");
03148			Global.PlayerTick(DeltaTime);
03149	
03150	    if ( !bTimerLoop )
03151	    {
03152	      Log("   WaitingForPawn PlayerTick, Timer not activated ?");
03153	      SetTimer(0.2, true);
03154	    }
03155	
03156			if ( Pawn != None )
03157			{
03158	      Log("   WaitingForPawn PlayerTick, Found Pawn");
03159				Pawn.Controller = self;
03160				ClientRestart();
03161			}
03162		}
03163	
03164		function Timer()
03165		{
03166	    Log(self@"WaitingForPawn Timer");
03167			AskForPawn();
03168			MyHud.bShowScores = true;
03169		}
03170	
03171		function BeginState()
03172		{
03173	    Log(self@"WaitingForPawn BeginState");
03174			SetTimer(0.2, true);
03175			MyHud.bShowScores = true;
03176		}
03177	
03178		function EndState()
03179		{
03180	    Log(self@"WaitingForPawn EndState");
03181			SetTimer(0.0, false);
03182			MyHud.bShowScores = false;
03183		}
03184	}
03185	
03186	state GameEnded
03187	{
03188	ignores SeePlayer, HearNoise, KilledBy, NotifyBump, HitWall, NotifyHeadVolumeChange, NotifyPhysicsVolumeChange, Falling, TakeDamage, Suicide;
03189	
03190		exec function ThrowWeapon()
03191		{
03192		}
03193	
03194		function ServerReStartGame()
03195		{
03196			Level.Game.RestartGame();
03197		}
03198	
03199		exec function Fire( optional float F )
03200		{
03201			if ( Role < ROLE_Authority)
03202				return;
03203			if ( !bFrozen )
03204				ServerReStartGame();
03205			else if ( TimerRate <= 0 )
03206				SetTimer(1.5, false);
03207		}
03208	
03209		exec function AltFire( optional float F )
03210		{
03211			Fire(F);
03212		}
03213	
03214		function PlayerMove(float DeltaTime)
03215		{
03216			local vector X,Y,Z;
03217			local Rotator ViewRotation;
03218	
03219			GetAxes(Rotation,X,Y,Z);
03220			// Update view rotation.
03221	
03222			if ( !bFixedCamera )
03223			{
03224				ViewRotation = Rotation;
03225				ViewRotation.Yaw += 32.0 * DeltaTime * aTurn;
03226				ViewRotation.Pitch += 32.0 * DeltaTime * aLookUp;
03227				ViewRotation.Pitch = ViewRotation.Pitch & 65535;
03228				If ((ViewRotation.Pitch > 18000) && (ViewRotation.Pitch < 49152))
03229				{
03230					If (aLookUp > 0)
03231						ViewRotation.Pitch = 18000;
03232					else
03233						ViewRotation.Pitch = 49152;
03234				}
03235				SetRotation(ViewRotation);
03236			}
03237			else if ( ViewTarget != None )
03238				SetRotation(ViewTarget.Rotation);
03239	
03240			ViewShake(DeltaTime);
03241			ViewFlash(DeltaTime);
03242	
03243			if ( Role < ROLE_Authority ) // then save this move and replicate it
03244				ReplicateMove(DeltaTime, vect(0,0,0), DCLICK_None, rot(0,0,0));
03245			else
03246				ProcessMove(DeltaTime, vect(0,0,0), DCLICK_None, rot(0,0,0));
03247			bPressedJump = false;
03248		}
03249	
03250		function ServerMove
03251		(
03252			float TimeStamp,
03253			vector InAccel,
03254			vector ClientLoc,
03255			bool NewbRun,
03256			bool NewbDuck,
03257			bool NewbJumpStatus,
03258			eDoubleClickDir DoubleClickMove,
03259			byte ClientRoll,
03260			int View,
03261			optional byte OldTimeDelta,
03262			optional int OldAccel
03263		)
03264		{
03265			Global.ServerMove(TimeStamp, InAccel, ClientLoc, NewbRun, NewbDuck, NewbJumpStatus,
03266								DoubleClickMove, ClientRoll, (32767 & (Rotation.Pitch/2)) * 32768 + (32767 & (Rotation.Yaw/2)) );
03267	
03268		}
03269	
03270		function FindGoodView()
03271		{
03272			local vector cameraLoc;
03273			local rotator cameraRot, ViewRotation;
03274			local int tries, besttry;
03275			local float bestdist, newdist;
03276			local int startYaw;
03277			local actor ViewActor;
03278	
03279			ViewRotation = Rotation;
03280			ViewRotation.Pitch = 56000;
03281			tries = 0;
03282			besttry = 0;
03283			bestdist = 0.0;
03284			startYaw = ViewRotation.Yaw;
03285	
03286			for (tries=0; tries<16; tries++)
03287			{
03288				cameraLoc = ViewTarget.Location;
03289				PlayerCalcView(ViewActor, cameraLoc, cameraRot);
03290				newdist = VSize(cameraLoc - ViewTarget.Location);
03291				if (newdist > bestdist)
03292				{
03293					bestdist = newdist;
03294					besttry = tries;
03295				}
03296				ViewRotation.Yaw += 4096;
03297			}
03298	
03299			ViewRotation.Yaw = startYaw + besttry * 4096;
03300			SetRotation(ViewRotation);
03301		}
03302	
03303		function Timer()
03304		{
03305			bFrozen = false;
03306		}
03307	
03308		function BeginState()
03309		{
03310			local Pawn P;
03311	
03312			EndZoom();
03313			bFire = 0;
03314			bAltFire = 0;
03315			if ( Pawn != None )
03316			{
03317				Pawn.SimAnim.AnimRate = 0;
03318				Pawn.bPhysicsAnimUpdate = false;
03319				Pawn.StopAnimating();
03320				Pawn.SetCollision(false,false,false);
03321			}
03322			myHUD.bShowScores = true;
03323			bFrozen = true;
03324			if ( !bFixedCamera )
03325			{
03326				FindGoodView();
03327				bBehindView = true;
03328			}
03329			SetTimer(1.5, false);
03330			SetPhysics(PHYS_None);
03331			ForEach DynamicActors(class'Pawn', P)
03332			{
03333				P.Velocity = vect(0,0,0);
03334				P.SetPhysics(PHYS_None);
03335			}
03336		}
03337	}
03338	
03339	state Dead
03340	{
03341	ignores SeePlayer, HearNoise, KilledBy, SwitchWeapon;
03342	
03343		function ServerRestartPlayer()
03344		{
03345			if ( bFrozen )
03346				return;
03347			Super.ServerRestartPlayer();
03348		}
03349	
03350		exec function Fire( optional float F )
03351		{
03352			if ( !bFrozen )
03353				ServerReStartPlayer();
03354		}
03355	
03356		exec function AltFire( optional float F )
03357		{
03358			Fire(F);
03359		}
03360	
03361		function ServerMove
03362		(
03363			float TimeStamp,
03364			vector Accel,
03365			vector ClientLoc,
03366			bool NewbRun,
03367			bool NewbDuck,
03368			bool NewbJumpStatus,
03369			eDoubleClickDir DoubleClickMove,
03370			byte ClientRoll,
03371			int View,
03372			optional byte OldTimeDelta,
03373			optional int OldAccel
03374		)
03375		{
03376			Global.ServerMove(
03377						TimeStamp,
03378						Accel,
03379						ClientLoc,
03380						false,
03381						false,
03382						false,
03383						DoubleClickMove,
03384						ClientRoll,
03385						View);
03386		}
03387	
03388		function PlayerMove(float DeltaTime)
03389		{
03390			local vector X,Y,Z;
03391			local rotator ViewRotation;
03392	
03393	        if ( !bFrozen )
03394			{
03395				if ( bPressedJump )
03396				{
03397					Fire(0);
03398					bPressedJump = false;
03399				}
03400				GetAxes(Rotation,X,Y,Z);
03401				// Update view rotation.
03402				ViewRotation = Rotation;
03403				ViewRotation.Yaw += 32.0 * DeltaTime * aTurn;
03404				ViewRotation.Pitch += 32.0 * DeltaTime * aLookUp;
03405				ViewRotation.Pitch = ViewRotation.Pitch & 65535;
03406				If ((ViewRotation.Pitch > 18000) && (ViewRotation.Pitch < 49152))
03407				{
03408					If (aLookUp > 0)
03409						ViewRotation.Pitch = 18000;
03410					else
03411						ViewRotation.Pitch = 49152;
03412				}
03413				SetRotation(ViewRotation);
03414				if ( Role < ROLE_Authority ) // then save this move and replicate it
03415					ReplicateMove(DeltaTime, vect(0,0,0), DCLICK_None, rot(0,0,0));
03416			}
03417			ViewShake(DeltaTime);
03418			ViewFlash(DeltaTime);
03419		}
03420	
03421		function FindGoodView()
03422		{
03423			local vector cameraLoc;
03424			local rotator cameraRot, ViewRotation;
03425			local int tries, besttry;
03426			local float bestdist, newdist;
03427			local int startYaw;
03428			local actor ViewActor;
03429	
03430			////log("Find good death scene view");
03431			ViewRotation = Rotation;
03432			ViewRotation.Pitch = 56000;
03433			tries = 0;
03434			besttry = 0;
03435			bestdist = 0.0;
03436			startYaw = ViewRotation.Yaw;
03437	
03438			for (tries=0; tries<16; tries++)
03439			{
03440				cameraLoc = ViewTarget.Location;
03441				PlayerCalcView(ViewActor, cameraLoc, cameraRot);
03442				newdist = VSize(cameraLoc - ViewTarget.Location);
03443				if (newdist > bestdist)
03444				{
03445					bestdist = newdist;
03446					besttry = tries;
03447				}
03448				ViewRotation.Yaw += 4096;
03449			}
03450	
03451			ViewRotation.Yaw = startYaw + besttry * 4096;
03452			SetRotation(ViewRotation);
03453		}
03454	
03455		function Timer()
03456		{
03457			myHUD.bShowScores = true;
03458			bPressedJump = false;
03459	//		SetTimer2(5.0,false);
03460			bFrozen = false;
03461		}
03462	
03463		function Timer2()
03464		{
03465	    	bFrozen = false;
03466		}
03467	
03468		function BeginState()
03469		{
03470			local SavedMove Next;
03471	
03472			Enemy = None;
03473			bBehindView = true;
03474			bFrozen = true;
03475			bPressedJump = false;
03476			FindGoodView();
03477			SetTimer(1.0, false);
03478	
03479			// clean out saved moves
03480			while ( SavedMoves != None )
03481			{
03482				Next = SavedMoves.NextMove;
03483				SavedMoves.Destroy();
03484				SavedMoves = Next;
03485			}
03486			if ( PendingMove != None )
03487			{
03488				PendingMove.Destroy();
03489				PendingMove = None;
03490			}
03491		}
03492	
03493		function EndState()
03494		{
03495			local SavedMove Next;
03496	
03497			// clean out saved moves
03498			while ( SavedMoves != None )
03499			{
03500				Next = SavedMoves.NextMove;
03501				SavedMoves.Destroy();
03502				SavedMoves = Next;
03503			}
03504			if ( PendingMove != None )
03505			{
03506				PendingMove.Destroy();
03507				PendingMove = None;
03508			}
03509			Velocity = vect(0,0,0);
03510			Acceleration = vect(0,0,0);
03511			bBehindView = false;
03512			myHUD.bShowScores = false;
03513			bPressedJump = false;
03514			//Log(self$" exiting dying with remote role "$RemoteRole$" and role "$Role);
03515		}
03516	}
03517	
03518	//------------------------------------------------------------------------------
03519	// ngStats Accessors
03520	function string GetNGSecret()
03521	{
03522		return ngWorldSecret;
03523	}
03524	
03525	function SetNGSecret(string newSecret)
03526	{
03527		ngWorldSecret = newSecret;
03528	}
03529	
03530	//------------------------------------------------------------------------------
03531	// Control options
03532	function ChangeStairLook( bool B )
03533	{
03534		bLookUpStairs = B;
03535		if ( bLookUpStairs )
03536			bAlwaysMouseLook = false;
03537	}
03538	
03539	function ChangeAlwaysMouseLook(Bool B)
03540	{
03541		bAlwaysMouseLook = B;
03542		if ( bAlwaysMouseLook )
03543			bLookUpStairs = false;
03544	}
03545	
03546	debugonly simulated function DumpContent(float TimeStamp, int tabulation)
03547	{
03548	    local int j;
03549	    local string Tab;
03550	
03551	    for (j=0; j<tabulation; j++) Tab = Tab$" ";
03552	
03553	    log(Tab$"PlayerController's dump at "$TimeStamp$":");
03554	    //log(Tab$"  bLookUpStairs:"$bLookUpStairs$" bSnapToLevel:"$bSnapToLevel$" bAlwaysMouseLook:"$bAlwaysMouseLook$" bKeyboardLook:"$bKeyboardLook$" bCenterView:"$bCenterView);
03555	    //log(Tab$"  bBehindView:"$bBehindView$" bFrozen:"$bFrozen$" bPressedJump:"$bPressedJump$" bUpdatePosition:"$bUpdatePosition$" bIsTyping:"$bIsTyping);
03556	    //log(Tab$"  bFixedCamera:"$bFixedCamera$" bJumpStatus:"$bJumpStatus$" bUpdating:"$bUpdating$" bNeverSwitchOnPickup:"$bNeverSwitchOnPickup);
03557	    //log(Tab$"  bZooming:"$bZooming$" bOnlySpectator:"$bOnlySpectator$" bAlwaysLevel:"$bAlwaysLevel$" bSetTurnRot:"$bSetTurnRot);
03558	    //log(Tab$"  bCheatFlying:"$bCheatFlying$" bFreeCamera:"$bFreeCamera$" bZeroRoll:"$bZeroRoll);
03559	    //log(Tab$"  AimingHelp:"$AimingHelp$" WaitDelay:"$WaitDelay);
03560	    //log(Tab$"  aBaseX:"$aBaseX$" aBaseY:"$aBaseY$" aBaseZ:"$aBaseZ$" aMouseX:"$aMouseX$" aMouseY:"$aMouseY$" aForward:"$aForward$" aTurn:"$aTurn$" aStrafe:"$aStrafe$" aUp:"$aUp$" aLookUp:"$aLookUp);
03561	    //log(Tab$"  bStrafe:"$bStrafe$" bSnapLevel:"$bSnapLevel$" bLook:"$bLook$" bFreeLook:"$bFreeLook$" bTurn180:"$bTurn180$" bTurnToNearest:"$bTurnToNearest);
03562	    //log(Tab$"  DoubleClickDir:"$DoubleClickDir);
03563	    //log(Tab$"  ShowFlags:"$ShowFlags$" Misc1:"$Misc1$" Misc2:"$Misc2$" RendMap:"$RendMap$" OrthoZoom:"$OrthoZoom$" ViewTarget:"$ViewTarget$" CameraDist:"$CameraDist);
03564	    //log(Tab$"  DesiredFOV:"$DesiredFOV$" DefaultFOV:"$DefaultFOV$" ZoomLevel:"$ZoomLevel);
03565	    //log(Tab$"  FlashScale:"$FlashScale$" FlashFog:"$FlashFog);
03566	    //log(Tab$"  DesiredFlashScale:"$DesiredFlashScale$" ConstantGlowScale:"$ConstantGlowScale);
03567	    //log(Tab$"  InstantFlash:"$InstantFlash$" DesiredFlashFog:"$DesiredFlashFog$" ConstantGlowFog:"$ConstantGlowFog$" InstantFog:"$InstantFog);
03568	    //log(Tab$"  FilterColor:"$FilterColor.B$","$FilterColor.G$","$FilterColor.R$","$FilterColor.A$" FilterColorWanted:"$FilterColorWanted.B$","$FilterColorWanted.G$","$FilterColorWanted.R$","$FilterColorWanted.A$" FilterColorSpeed:"$FilterColorSpeed$" FilterInternalInc:"$FilterInternalInc);
03569	    //log(Tab$"  TargetViewRotation:"$TargetViewRotation$" TargetEyeHeight:"$TargetEyeHeight$" TargetWeaponViewOffset:"$TargetWeaponViewOffset);
03570	    //log(Tab$"  myHUD:"$myHUD$" LastPlaySound:"$LastPlaySound$" AnnouncerVolume:"$AnnouncerVolume);
03571	    //log(Tab$"  SavedMoves:"$SavedMoves$" FreeMoves:"$FreeMoves$" PendingMove:"$PendingMove);
03572	    //log(Tab$"  CurrentTimeStamp:"$CurrentTimeStamp$" LastUpdateTime:"$LastUpdateTime$" ServerTimeStamp:"$ServerTimeStamp$" TimeMargin:"$TimeMargin$" ClientUpdateTime:"$ClientUpdateTime$" MaxTimeMargin:"$MaxTimeMargin);
03573	        log(Tab$"  LastUpdateTime:"$LastUpdateTime$" ServerTimeStamp:"$ServerTimeStamp$" TimeMargin:"$TimeMargin$" ClientUpdateTime:"$ClientUpdateTime);
03574	    //log(Tab$"  OldClientWeapon:"$OldClientWeapon$" WeaponUpdate:"$WeaponUpdate);
03575	    //log(Tab$"  ProgressMessage[0]:"$ProgressMessage[0]$" ProgressMessage[1]:"$ProgressMessage[1]$" ProgressMessage[2]:"$ProgressMessage[2]$" ProgressMessage[3]:"$ProgressMessage[3]);
03576	    // discarded log(Tab$"  ProgressColor[0]:"$ProgressColor[0]$" ProgressColor[1]:"$ProgressColor[1]$" ProgressColor[2]:"$ProgressColor[2]$" ProgressColor[3]:"$ProgressColor[3]);
03577	    //log(Tab$"  ProgressTimeOut:"$ProgressTimeOut$" QuickSaveString:"$QuickSaveString$" NoPauseMessage:"$NoPauseMessage$" ViewingFrom:"$ViewingFrom$" OwnCamera:"$OwnCamera);
03578	    //log(Tab$"  QuickSaveString:"$QuickSaveString$" NoPauseMessage:"$NoPauseMessage$" ViewingFrom:"$ViewingFrom$" OwnCamera:"$OwnCamera);
03579	    //log(Tab$"  ngWorldSecret:"$ngWorldSecret$" ngSecretSet:"$ngSecretSet$" ReceivedSecretChecksum:"$ReceivedSecretChecksum$" LocalMessageClass:"$LocalMessageClass);
03580	    log(Tab$"  Bob:"$Bob$" LandBob:"$LandBob$" AppliedBob:"$AppliedBob$" bobtime:"$bobtime$" WalkBob:"$WalkBob);
03581	    //log(Tab$"  MaxShakeRoll:"$MaxShakeRoll$" MaxShakeOffset:"$MaxShakeOffset$" ShakeRollRate:"$ShakeRollRate$" ShakeOffsetRate:"$ShakeOffsetRate);
03582	    //log(Tab$"  ShakeOffset:"$ShakeOffset$" ShakeRollTime:"$ShakeRollTime$" ShakeOffsetTime:"$ShakeOffsetTime);
03583	    //log(Tab$"  TurnTarget:"$TurnTarget$" EnemyTurnSpeed:"$EnemyTurnSpeed$" GroundPitch:"$GroundPitch$" TurnRot180:"$TurnRot180);
03584	    //log(Tab$"  OldFloor:"$OldFloor);
03585	    //log(Tab$"  CheatManager:"$CheatManager$" CheatClass:"$CheatClass$" PlayerInput:"$PlayerInput$" InputClass:"$InputClass);
03586	    //log(Tab$"  DemoViewPitch:"$DemoViewPitch$" DemoViewYaw:"$DemoViewYaw);
03587	    //log(Tab$"  GameReplicationInfo:"$GameReplicationInfo);
03588	    //log(Tab$"  GameReplicationInfo:");
03589	    //GameReplicationInfo.DumpContent(TimeStamp, tabulation)
03590	
03591	    Super.DumpContent(TimeStamp, tabulation);
03592	}
03593	
03594	
03595	debugonly simulated function DumpChosenContent(float TimeStamp)
03596	{
03597	    log("At "$TimeStamp$":");
03598	    if (pawn!=none)
03599	    {
03600	        if (pawn.velocity.z>0.0)
03601	        {
03602	            log("GroundSpeed:"$pawn.GroundSpeed$"  jumping:"$pawn.velocity.z);
03603	        }
03604	        else
03605	        {
03606	            log("GroundSpeed:"$pawn.GroundSpeed);
03607	        }
03608	    }
03609	}
03610	
03611	//    AimingHelp=0.0
03612	
03613	defaultproperties
03614	{
03615	     bAlwaysMouseLook=True
03616	     bKeyboardLook=True
03617	     bZeroRoll=True
03618	     bAutoPickup=True
03619	     ConfigType=CT_StrafeLookNotSameAxis
03620	     OrthoZoom=40000.000000
03621	     CameraDist=9.000000
03622	     DesiredFOV=85.000000
03623	     DefaultFOV=85.000000
03624	     FlashScale=(X=1.000000,Y=1.000000,Z=1.000000)
03625	     FilterColor=(B=128,G=128,R=128)
03626	     FilterColorWanted=(B=128,G=128,R=128)
03627	     FilterColorSpeed=1.000000
03628	     AnnouncerVolume=4
03629	     MaxTimeMargin=1.000000
03630	     QuickSaveString="Quick Saving"
03631	     NoPauseMessage="Game is not pauseable"
03632	     ViewingFrom="Now viewing from"
03633	     OwnCamera="Now viewing from own camera"
03634	     LocalMessageClass=Class'Engine.LocalMessage'
03635	     Bob=0.016000
03636	     EnemyTurnSpeed=45000
03637	     CheatClass=Class'Engine.CheatManager'
03638	     InputClass=Class'Engine.PlayerInput'
03639	     FovAngle=85.000000
03640	     Handedness=1.000000
03641	     bIsPlayer=True
03642	     bCanOpenDoors=True
03643	     bCanDoSpecial=True
03644	     bTravel=True
03645	     NetPriority=3.000000
03646	}

End Source Code