Engine
Class Pawn

source: c:\runehov\Engine\Classes\Pawn.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Pawn
Direct Known Subclasses:PlayerPawn, Scout, FlockMasterPawn, FlockPawn, Mount, ScriptPawn

class Pawn
extends Engine.Actor

//============================================================================= // Pawn. //=============================================================================
Variables
 float AvgPhysicsTime
           RUNE: Align this pawn to the floor below it (only when in PHYS_Walking)
 float BaseEyeHeight
           Base eye height above collision center.
 int BloodSteps
           Use existing targetangle for looking
 int BodyPartHealth[15]
           RUNE: Health of bodyparts
 class CarcassType
 int ClassID
           ID determining same family of creatures
 int CurrentSkin
           Index of skin currently being used
 float DamageScaling
           for queueing states
 int DesiredMouthRot
           Use existing targetangle for looking
 class DropWhenKilled
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 float EyeHeight
           Current eye height, adjusted for bobbing and stairs.
 PointRegion FootRegion
           RUNE: Align this pawn to the floor below it (only when in PHYS_Walking)
 float FovAngle
           X field of view angle in degrees, usually 90.
 class GibClass
           RUNE: Gib to spew out
 int GibCount
           RUNE: Number of normal gibs to spew out
 vector GrabLocationIn
           RUNE: Push-in location of grab
 vector GrabLocationUp
           RUNE: Pull-up location of grab
 PointRegion HeadRegion
           RUNE: Align this pawn to the floor below it (only when in PHYS_Walking)
 int Health
           Health:
 rotator LookAngle
           Angle currently looking
 vector LookSpot
           Position pawn is interested in
 Actor LookTarget
           Actor pawn is interested in
 int MaxHealth
           RUNE: Maximum health: 100 = normal
 int MaxPower
           RUNE: Maximum power. 100 = normal
 int MaxStrength
           RUNE: Maximum strength, 100 = normal
 string MenuName
           Name used for this pawn type in menus (e.g. player selection)
 int MouthRot
           Use existing targetangle for looking
 int MouthRotRate
           Use existing targetangle for looking
 Actor MoveTarget
           set by movement natives
 float MoveTimer
           RUNE: Align this pawn to the floor below it (only when in PHYS_Walking)
 float MovementSpeed
           RUNE: Current speed modifier 0..1 (Set by UpdateMovementSpeed())
 string NameArticle
           article used in conjunction with this class (e.g. "a", "an")
 name NextLabel
           for queueing states
 name NextState
           for queueing states
 name NextStateAfterPain
           for queueing states
 float OldMessageTime
           to limit frequency of voice messages
 float OrthoZoom
           Orthogonal/map view zoom factor.
 float PainDelay
           RUNE: Time to delay when in the pain state (if negative, does a FinishAnim())
 Weapon PendingWeapon
           Will become weapon once current weapon is put down
 Name PlayerReStartState
           for queueing states
 PlayerReplicationInfo PlayerReplicationInfo
           to limit frequency of voice messages
 class PlayerReplicationInfoClass
           to limit frequency of voice messages
 float ReducedDamagePct
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 name ReducedDamageType
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 NavigationPoint RouteCache[16]
           to limit frequency of voice messages
 int RunePower
           RUNE: Current amount of RunePower
 Inventory SelectedItem
           currently selected inventory item
 string SelectionMesh
           RUNE: Pawn is invisible to others
 Decal Shadow
           to limit frequency of voice messages
 Shield Shield
           The pawn's current shield
 string SkinDefaultText
           Text describing Default Skin
 float SoundDampening
           for queueing states
 string SpecialMesh
           RUNE: Pawn is invisible to others
 ESpeedScale SpeedScale
           RUNE: Handles the movement type (circular, elliptical, etc)
 float SplashTime
           time of last splash
 SecretCount, Spree
           X field of view angle in degrees, usually 90.
 name StartEvent
           Event of PlayerStart (temp storage)
 int Strength
           RUNE: Strength damage modifier
 name UninterruptedAnim
           RUNE: Used specifically in the Uninterrupted state
 Actor UseActor
           RUNE: Used by Use functionality
 vector ViewLocation
           RUNE: To cache camera location for PlayerCanSeeMe()
 rotator ViewRotation
           View rotation.
 byte Visibility
           How visible is the pawn? 0 = invisible.
 byte VoicePitch
           for speech
 string VoiceType
           for speech
 vector WalkBob
           RUNE: To cache camera location for PlayerCanSeeMe()
 int WaterSteps
           Use existing targetangle for looking
 Weapon Weapon
           The pawn's current weapon.
 bool bAlignToFloor
           RUNE: Align this pawn to the floor below it (only when in PHYS_Walking)
 bool bBehindView
           Outside-the-player view.
 bool bCanGrabEdges
           Can grab edges: bCanStrafe must also be set to true
 bool bFromWall
           used for alternating LineOfSight traces
 bool bGibbable
           RUNE: Can be gibbed
 bool bHitSlopedWall
           used by Physics
 bool bHurrying
           RUNE: Whether running or walking
 bool bInvisible
           RUNE: Pawn is invisible to others
 bool bIsPlayer
           Pawn is a player or a player-bot.
 bool bIsWalking
           used by swimming
 bool bJustLanded
           used by eyeheight adjustment
 bool bLOSflag
           used for alternating LineOfSight traces
 bool bNeverSwitchOnPickup
           if true, don't automatically switch to picked up weapon
 bool bOverrideLookTarget
           Use existing targetangle for looking
 bool bReducedSpeed
           used by movement natives
 bool bStopMoveIfCombatRange
           RUNE: a moveToward latent function will exit if the enemy is within CombatRange
 bool bSwingingHigh
           Currently swinging high (used to warn targets)
 bool bSwingingLow
           Currently swinging low
 bool bUpAndOut
           used by swimming
 bool bUpdatingDisplay
           to avoid infinite recursion through inventory setdisplay
 bool bWarping
           Set when travelling through warpzone (so shouldn't telefrag)
 input byte
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 Pawn nextPawn
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 float noise1loudness
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 Pawn noise1other
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 vector noise1spot
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 float noise1time
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 float noise2loudness
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 Pawn noise2other
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 vector noise2spot
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 float noise2time
           Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
 rotator targetangle
           Only used when bOverrideLookTarget

States
GameEnded, Dying, Dying, Pain, Uninterrupted

Function Summary
 void AcquireInventory(Inventory item)
     
//------------------------------------------------------------
//
// AcquireInventory
//
// Called when inventory item is acquired
//------------------------------------------------------------
 void ActivateShield(bool bOn)
     
//------------------------------------------------------------
//
// ActivateShield
//
// Changes the state of current shield (in case needed later)
//------------------------------------------------------------
 Actor ActorTagged(name tag)
 bool AddInventory(Inventory NewItem)
     
// Add Item to this pawn's inventory. 
// Returns true if successfully added, false if not.
 void AddPawn()
 void AddVelocity(vector NewVelocity)
 rotator AdjustAim(float projSpeed, vector projStart, int aimerror, bool bLeadTarget, bool bWarnTarget)
     
//------------------------------------------------------------
//
// AdjustAim()
//
// ScriptedPawn version does adjustment for non-controlled pawns. 
// PlayerPawn version does the adjustment for player aiming help.
// Only adjusts aiming at pawns
// allows more error in Z direction (full as defined by AutoAim - only half that difference for XY)
//------------------------------------------------------------
 float AdjustDesireFor(Inventory Inv)
 rotator AdjustToss(float projSpeed, vector projStart, int aimerror, bool bLeadTarget, bool bWarnTarget)
 bool AllowWeaponToHitActor(Weapon W, Actor A)
     
//------------------------------------------------------------
//
// AllowWeaponToHitActor
//
// Event to notify pawn when weapon hits something
//------------------------------------------------------------
 int AngleTo(vector pos)
     
//------------------------------------------------------------
//
// AngleTo
//
// Returns absolute value of yaw angle to a location
//------------------------------------------------------------
 void ApplyPainToJoint(int joint, vector Momentum)
     
//------------------------------------------------------------
//
// ApplyPainToJoint
//
//------------------------------------------------------------
 void BecomeViewTarget()
     
//=============================================================================
// Messaging functions
//=============================================================================
 void BodyPartCollision(int BodyPart, bool on)
     
//------------------------------------------------------------
//
// BodyPartCollision
//
// Turn collision on or off on a body part
//------------------------------------------------------------
 bool BodyPartCritical(int BodyPart)
 int BodyPartForJoint(int joint)
     
//=============================================================================
// Localized Damage Support functions
//=============================================================================
 int BodyPartForPolyGroup(int polygroup)
 bool BodyPartMissing(int BodyPart)
     
//------------------------------------------------------------
//
// BodyPartMissing
//
//------------------------------------------------------------
 bool BodyPartSeverable(int BodyPart)
 void BodyPartVisibility(int BodyPart, bool on)
     
//------------------------------------------------------------
//
// BodyPartVisibility
//
// Turn visibility on or off on a body part
//------------------------------------------------------------
 void BoostStrength(int amount)
 void BotVoiceMessage(name messagetype, byte MessageID, Pawn Sender)
 void CalcLookAngle()
 bool CanBeStatued()
 bool CanGotoPainState()
     
//------------------------------------------------------------
//
// CanGotoPainState
//
// True if the actor is allowed to enter it's painstate
// This is overriden in some substates
//------------------------------------------------------------
 bool CanPickup(Inventory item)
     
//------------------------------------------------------------
//
// CanPickup
//
// Let's pawn dictate what it can pick up
//------------------------------------------------------------
 bool CanSee(Actor Other)
     
// CanSee() similar to line of sight, but also takes into account Pawn's peripheral vision
 bool CanStabActor()
     
//------------------------------------------------------------
//
// CanStabActor
//
// If the actor can be stabbed by a weapon
//------------------------------------------------------------
 void ChangedWeapon()
     
// Just changed to pendingWeapon
 bool CheckDefending()
     
//------------------------------------------------------------
//
// CheckDefending
//
// Checks if the Pawn is defending 
//------------------------------------------------------------
 bool CheckWaterJump(out vector)
 void ClearPaths()
     
// clear all temporary path variables used in routing
 void ClearSwipeArray()
     
//------------------------------------------------------------
//
// ClearSwipeArray
//
//------------------------------------------------------------
 void ClientDying(name DamageType, vector HitLocation)
 void ClientGameEnded()
 void ClientPutDown(Weapon Current, Weapon Next)
 void ClientReStart()
 void ClientSetLocation(vector NewLocation, rotator NewRotation)
     
//=============================================================================
// Client-side functions
//=============================================================================
 void ClientSetRotation(rotator NewRotation)
 void ClientVoiceMessage(PlayerReplicationInfo Sender, PlayerReplicationInfo Recipient, name messagetype, byte messageID)
 NavigationPoint CloserNavPointTo(Actor Other)
 bool DamageBodyPart(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, name DamageType, int bodypart)
     
//------------------------------------------------------------
//
// DamageBodyPart
//
//------------------------------------------------------------
 bool DeleteInventory(Inventory Item)
     
// Remove Item from this pawn's inventory, if it exists.
// Returns true if it existed and was deleted, false if it did not exist.
 void Died(Pawn Killer, name damageType, vector HitLocation)
     
//------------------------------------------------------------
//
// Died
//
// Pawn has run out of health, kill him properly
//------------------------------------------------------------
 void DoThrow()
     
//=========================================================================
//
// DoThrow
// 
// Throw weapon notify
//=========================================================================
 void DropShield()
     
//------------------------------------------------------------
//
// DropShield
//
//------------------------------------------------------------
 void DropWeapon()
     
//------------------------------------------------------------
//
// DropWeapon
//
//------------------------------------------------------------
 vector EAdjustJump()
 void Falling()
 void FearThisSpot(Actor aSpot)
 Actor FindBestInventoryPath(out float, bool bPredictRespawns)
 bool FindBestPathToward(Actor desired)
     
//------------------------------------------------
//
// FindBestPathToward
//
// Assumes the desired destination is not directly reachable, 
// it tries to set Destination to the location of the best
// waypoint, and returns true if successful
//------------------------------------------------
 Inventory FindInventoryType(class DesiredClass)
     
// FindInventoryType()
// returns the inventory item of the requested class
// if it exists in this pawn's inventory 
 Actor FindPathAwayFrom(Actor anActor, optional actor)
 Actor FindPathTo(vector aPoint, optional bool, optional bool)
 Actor FindPathToward(Actor anActor, optional bool, optional bool)
 NavigationPoint FindRandomDest(optional bool)
     
// returns a random pathnode which is reachable from the creature's location
 int FindStairRotation(float DeltaTime)
 vector FindWaterLine(vector Start, vector End)
 bool FollowOrders(name order, name tag)
 
simulated
FootStep()
 
simulated
FootStepLeft()
 
simulated
FootStepPrint(int footjoint)
 
simulated
FootStepRight()
     
//=============================================================================
//
// FootSteps/Notifies
// 
//=============================================================================
 void Gasp()
 Sound GetFootstepSound(EMatterType matter)
 String GetHumanName()
 void GetMultiSkin(Actor SkinActor, out string, out string)
     
{
	local Texture NewSkin;

	if(SkinName != "")
	{
		NewSkin = texture(DynamicLoadObject(SkinName, class'Texture'));
		if ( NewSkin != None )
			SkinActor.Skin = NewSkin;
	}
}

static 
 void HandleHelpMessageFrom(Pawn Other)
 void HidePlayer()
 void InitPlayerReplicationInfo()
 
simulated
Jaw(float DeltaSeconds)
     
//------------------------------------------------------------
//
// Jaw
//
// Takes care of moving the jaw smoothly
//------------------------------------------------------------
 bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
     
//------------------------------------------------------------
//
// JointDamaged
//
//------------------------------------------------------------
 void JumpOffPawn()
     
//Base change - if new base is pawn or decoration,
// damage based on relative mass and old velocity
// Also, non-players will jump off pawns immediately
 string KillMessage(name damageType, Pawn Other)
 void Killed(Pawn Killer, Pawn Other, name damageType)
     
// Pawn just grabbed an edge
 int LimbPassThrough(int BodyPart, out int, out int)
     
//------------------------------------------------------------
//
// LimbPassThrough
//
// Determines what damage is passed through to body
//------------------------------------------------------------
 void LimbSevered(int bodypart, vector Momentum)
 bool LineOfSightTo(Actor Other)
     
// LineOfSightTo() returns true if any of several points of Other is visible (origin, top, bottom)
 
simulated
Look(float DeltaTime)
     
//------------------------------------------------------------
//
// Look
//
// Make pawn look around
//------------------------------------------------------------
 void LookAt(Actor A, optional bool)
     
//------------------------------------------------------------
//
// LookAt
//
// Look at an actor if not looking at a location
//------------------------------------------------------------
 void LookToward(vector pos, optional bool)
     
//------------------------------------------------------------
//
// LookToward
//
// Set a spot to be looked at when not looking at an actor
//------------------------------------------------------------
 void MakeTwitchable()
     
//------------------------------------------------------------
//
// MakeTwitchable
//
// TODO: Move this logic to carcass
//------------------------------------------------------------
 EMatterType MatterForJoint(int joint)
     
//------------------------------------------------------------
//
// MatterForJoint
//
// Returns what kind of material joint is associated with
//------------------------------------------------------------
 void MoveTo(vector NewDestination, optional float)
     
//Note that MoveTo sets the actor's Destination, and MoveToward sets the
//actor's MoveTarget.  Actor will rotate towards destination
 void MoveToward(Actor NewTarget, optional float)
 bool NearWall(float walldist)
     
//------------------------------------------------------------
//
// NearWall
//
// Returns true if there is a nearby barrier at eyeheight and
// changes focus to a suggested value
//------------------------------------------------------------
 NavigationPoint NearestNavPoint()
 bool NeedToTurn(vector targ)
     
//------------------------------------------------------------
//
// NeedToTurn
//
// Returns whether I need to turn to see a location
//------------------------------------------------------------
 void NextItem()
     
// The player/bot wants to select next item
 void OpenMouth(float amount, float rate)
     
//------------------------------------------------------------
//
// OpenMouth
//
// Changes pawn's jaw openness if capable
//  amount[0..1] 0 is completely closed, 1 is completely open
//  rate[0..1]   0 is not moving, 1 is move at max rate
//------------------------------------------------------------
 float PawnDamageModifier(Weapon w)
     
//------------------------------------------------------------
//
// PawnDamageModifier
//
// Returns the modification of the damage amount 
// Used to increase damage for special attacks, or reduce damage
// for simple attack types
//------------------------------------------------------------
 Actor PickAnyTarget(out float, out float, vector FireDir, vector projStart)
 Pawn PickTarget(out float, out float, vector FireDir, vector projStart)
     
// Pick best pawn target
 bool PickWallAdjust()
     
//------------------------------------------------------------
//
// PickWallAdjust()
//
// Check if could jump up over obstruction (only if there is a knee height obstruction)
// If so, start jump, and return current destination
// Else, try to step around - return a destination 90 degrees right or left depending on traces
// out and floor checks
//------------------------------------------------------------
 void PlayBackDeath(name DamageType)
     
// hit from front
 void PlayBackHit(optional float)
 void PlayCrawling(optional float)
 void PlayDeath(name DamageType)
     
// Deaths
 void PlayDive(optional float)
 void PlayDrownDeath(name DamageType)
     
// decapitated
 void PlayDrowning(optional float)
 void PlayDuck(optional float)
 void PlayDying(name DamageType, vector HitLoc)
 void PlayDyingSound(name damageType)
 void PlayFrontHit(optional float)
     
// Pain
 void PlayGibDeath(name DamageType)
     
// hit by thrown sword
 void PlayHeadDeath(name DamageType)
     
// fall to his right
 void PlayHeadHit(optional float)
 void PlayInAir(optional float)
 void PlayJumping(optional float)
 void PlayLandSound(EMatterType matter, float impactVel)
 void PlayLanded(float impactVel)
 void PlayLanding(optional float)
 void PlayLeftDeath(name DamageType)
     
// hit from behind
 void PlayLeftHit(optional float)
 void PlayMoving(optional float)
     
// These are required
 void PlayMovingAttack(optional float)
 void PlayOutOfWater(optional float)
 void PlayPullUp(optional float)
 void PlayRightDeath(name DamageType)
     
// fall to his left
 void PlayRightHit(optional float)
 void PlaySkewerDeath(name DamageType)
     
// drown
 void PlayStepUp(optional float)
 void PlayTakeHit(float tweentime, int damage, vector HitLoc, name damageType, vector Momentum, int BodyPart)
 void PlayTakeHitSound(int Damage, name damageType, int Mult)
     
//=============================================================================
// Sound functions
//=============================================================================
 void PlayThreatening(optional float)
 void PlayTurning(optional float)
 void PlayUninterruptedAnim(name Anim)
     
//------------------------------------------------------------
//
// Uninterrupted
//
// This state does not allow the pawn to be interrupted while
// the pawn is performing a specific action.  Note that the pawn
// will still take pain (but not enter the painstate) and die (and WILL
// go into the death state) while in this state.
//------------------------------------------------------------
 void PlayWaiting(optional float)
     
//=============================================================================
// Animation functions - should be implemented in subclass, 
//=============================================================================
 void PlayWeaponSwitch(Weapon NewWeapon)
 void PowerUpWeapon()
 void PreSetMovement()
 void RemovePawn()
 void RestartPlayer()
     
//=============================================================================
// Game Events
//=============================================================================
 void RestoreBodyPart(int BodyPart)
     
//------------------------------------------------------------
//
// RestoreBodyPart
//
// Restore a bodypart to full health, visibility, collision
//------------------------------------------------------------
 void SendGlobalMessage(PlayerReplicationInfo Recipient, name MessageType, byte MessageID, float Wait)
     
//------------------------------------------------------------------------------
// Speech related
 void SendTeamMessage(PlayerReplicationInfo Recipient, name MessageType, byte MessageID, float Wait)
 void SendVoiceMessage(PlayerReplicationInfo Sender, PlayerReplicationInfo Recipient, name messagetype, byte messageID, name broadcasttype)
 void SetDefaultDisplayProperties()
 void SetDisplayProperties(ERenderStyle NewStyle, Texture NewTexture, bool bLighting, bool bEnviroMap)
 
simulated
SetMesh()
 void SetMovementPhysics()
 void SetMultiSkin(Actor SkinActor, string SkinName, string FaceName, byte TeamNum)
     
/*
static 
 bool SetSkinElement(Actor SkinActor, int SkinNo, string SkinName, string DefaultSkinName)
     
{
	SkinName = String(SkinActor.Skin);
	FaceName = "";
}
*/
 void SkeletonLook(float DeltaTime)
 void SpawnBodyGibs(vector momentum)
     
//------------------------------------------------------------
//
// SpawnBodyGibs
// 
// Subclass this to spawn specific gibs for a given creature
//------------------------------------------------------------
 Carcass SpawnCarcass()
     
//------------------------------------------------------------
//
// SpawnCarcass
// 
//------------------------------------------------------------
 void StopAttack()
     
//------------------------------------------------------------
//
// StopAttack
//
//------------------------------------------------------------
 void StopFiring()
 void StopLookingToward()
     
//------------------------------------------------------------
//
// StopLookingToward
//
//------------------------------------------------------------
 void StopWaiting()
     
// Force end to sleep
 void StrafeFacing(vector NewDestination, Actor NewTarget)
 void StrafeTo(vector NewDestination, vector NewFocus)
 void SwipeEffectEnd()
     
//=============================================================================
//
// SwipeEffectEnd
//
// Swipe Effect Notify
//=============================================================================
 void SwipeEffectStart()
     
//=============================================================================
//
// SwipeEffectStart
//
// Swipe Effect Notify
//=============================================================================
 bool SwitchToBestWeapon()
 void TeamBroadcast(string Msg)
     
// Broadcast a text message to all players, or all on the same team.
 void ThrowWeapon()
     
//=============================================================================
//
// ThrowWeapon
//
// RUNE:  Throw the current weapon
//=============================================================================
 
simulated
Tick(float DeltaTime)
     
//------------------------------------------------------------
//
// Tick
//
//------------------------------------------------------------
 void TossWeapon()
     
// toss out the weapon currently held
 void TurnTo(vector NewFocus)
 void TurnToward(Actor NewTarget)
 void TweenToMoving(float tweentime)
 void TweenToWaiting(float tweentime)
 void UnderLift(Mover M)
 void UpdateMovementSpeed()
     
//=============================================================================
// Utility functions
//=============================================================================
 void UseNotify()
     
//=============================================================================
//
// UseNotify
//
// Notify used by animations to specify when the use should occur
//=============================================================================
 void WaitForLanding()
     
// Wait until physics is not PHYS_Falling
 bool WantsToPickUp(Inventory item)
     
//------------------------------------------------------------
//
// WantsToPickup
//
// Returns whether the item is desired
//------------------------------------------------------------
 void WarnTarget(Pawn shooter, float projSpeed, vector FireDir)
 void WeaponActivate()
     
//------------------------------------------------------------
//
// WeaponActivate
//
//------------------------------------------------------------
 void WeaponDeactivate()
     
//------------------------------------------------------------
//
// WeaponDeactivate
//
//------------------------------------------------------------
 bool actorReachable(Actor anActor)
 void damageAttitudeTo(Pawn Other)
 bool pointReachable(vector aPoint)
     
//Reachable returns what part of direct path from Actor to aPoint is traversable
//using the current locomotion method


State GameEnded Function Summary
 void PowerupElectricity(Pawn EventInstigator)
 void PowerupFriend(Pawn EventInstigator)
 void PowerupBlaze(Pawn EventInstigator)
 void PowerupFire(Pawn EventInstigator)
 void PowerupIce(Pawn EventInstigator)
 void PowerupStone(Pawn EventInstigator)
     
// Powerup support
 void SpecialPainSkin(int BodyPart)
 void SetSkinActor(Actor SkinActor, int NewSkin)
 string GetSkinName(int Skin)
 int GetNumSkins()
     
//=============================================================================
// Skin support
//=============================================================================
 void BeginState()


State Dying Function Summary
 void Timer()
     
	{
		LookTarget=None;
		LookSpot=vect(0,0,0);
		SetTimer(0.3, false);
	}

	event Landed(vector HitNormal, actor HitActor)
	{
		SetPhysics(PHYS_None);
	}

	
 void BeginState()
     
// Do spasm
		ApplyPainToJoint(joint, Momentum);
		Super(Actor).JointDamaged(Damage, EventInstigator, HitLoc, Momentum, DamageType, joint);
	}

	
 bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
     
//slog("moving"@GetJointName(joint));
			ApplyJointForce(joint, Momentum);
		}
	}

	
 void ApplyPainToJoint(int joint, vector momentum)
     
// Allow to clip through other corpses
		bCollideWorld = true;
		bAllowStandOn=true;
	}

	
 void ShrinkCollisionHeight()
     
// Allow to clip through other corpses
		bCollideWorld = true;
	}

	
 void ExpandCollisionRadius()
     
// Remove a stabbed weapon if one exists

			if (bIsPlayer)
			{
				HidePlayer();
			}
			else
			{
				bHidden=true;
				Destroy();
			}
		}
	}

	
 void ReplaceWithCarcass()
     
{
ignores SeePlayer, EnemyNotVisible, HearNoise, KilledBy, Trigger, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, Died, LongFall, PainTimer, Landed;

	


State Dying Function Summary
 void Done()
 bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
 void ApplyPainToJoint(int joint, vector momentum)
 void ShrinkCollisionHeight()
 void ExpandCollisionRadius()
 void ReplaceWithCarcass()
 void PowerupElectricity(Pawn EventInstigator)
 void PowerupFriend(Pawn EventInstigator)
 void PowerupBlaze(Pawn EventInstigator)
 void PowerupFire(Pawn EventInstigator)
 void PowerupIce(Pawn EventInstigator)
 void PowerupStone(Pawn EventInstigator)
 bool CanBeStatued()


State Pain Function Summary
 void EndState()
 bool CanGotoPainState()


State Uninterrupted Function Summary
 void Tick(float DeltaSeconds)
 void AnimEnd()
 void EndState()
 void BeginState()
 bool CanGotoPainState()



Source Code


00001	//=============================================================================
00002	// Pawn.
00003	//=============================================================================
00004	
00005	class Pawn extends Actor
00006		abstract
00007		native;
00008	//	nativereplication;
00009	
00010	#exec Texture Import File=Textures\Pawn.pcx Name=S_Pawn Mips=Off Flags=2
00011	
00012	// Pawn Variables -------------------------------------------------------------
00013	
00014	enum ESpeedScale
00015	{
00016		SS_Circular,
00017		SS_Elliptical,
00018		SS_Other,
00019	};
00020	
00021	var() class<carcass> CarcassType;
00022	
00023	// General flags.
00024	var bool		bBehindView;    // Outside-the-player view.
00025	var bool        bIsPlayer;      // Pawn is a player or a player-bot.
00026	var bool		bJustLanded;	// used by eyeheight adjustment
00027	var bool		bUpAndOut;		// used by swimming
00028	var bool		bIsWalking;
00029	var const bool	bHitSlopedWall;	// used by Physics
00030	var globalconfig bool	bNeverSwitchOnPickup;	// if true, don't automatically switch to picked up weapon
00031	var bool		bWarping;		// Set when travelling through warpzone (so shouldn't telefrag)
00032	var bool		bUpdatingDisplay; // to avoid infinite recursion through inventory setdisplay
00033	
00034	// AI flags
00035	var(Combat) bool	bCanStrafe;			//can move in different directions than current rotation
00036	var(Orders) bool	bFixedStart;
00037	var const bool		bReducedSpeed;		//used by movement natives
00038	var		bool		bCanJump;
00039	var		bool 		bCanWalk;
00040	var		bool		bCanSwim;
00041	var		bool		bCanFly;
00042	var		bool		bCanOpenDoors;
00043	var		bool		bCanDoSpecial;
00044	var		bool		bDrowning;
00045	var const bool		bLOSflag;			// used for alternating LineOfSight traces
00046	var 	bool 		bFromWall;
00047	var		bool		bHunting;			// tells navigation code that pawn is hunting another pawn,
00048											//	so fall back to finding a path to a visible pathnode if none
00049											//	are reachable
00050	var		bool		bAvoidLedges;		// don't get too close to ledges
00051	var		bool		bStopAtLedges;		// if bAvoidLedges and bStopAtLedges, Pawn doesn't try to walk along the edge at all
00052	var		bool		bJumpOffPawn;
00053	var		bool		bShootSpecial;
00054	var		bool		bAutoActivate;
00055	var		bool		bIsHuman;			// for games which care about whether a pawn is a human
00056	var		bool		bIsFemale;
00057	var		bool		bIsMultiSkinned;
00058	var		bool		bCountJumps;
00059	var		bool		bAdvancedTactics;	// used during movement between pathnodes
00060	var		bool		bViewTarget;
00061	
00062	var()	bool		bCanGrabEdges;		// Can grab edges: bCanStrafe must also be set to true
00063	var()	bool		bAlignToFloor;		// RUNE:  Align this pawn to the floor below it (only when in PHYS_Walking)
00064	
00065	// Ticked pawn timers
00066	var		float		SightCounter;	//Used to keep track of when to check player visibility
00067	var		float       PainTime;		//used for getting PainTimer() messages (for Lava, no air, etc.)
00068	var		float		SpeechTime;	
00069	var		float		AmbientSoundTime;	// Used to generate ambient sound events
00070	
00071	// Physics updating time monitoring (for AI monitoring reaching destinations)
00072	var const	float		AvgPhysicsTime;
00073	
00074	// Additional pawn region information.
00075	var PointRegion FootRegion;
00076	var PointRegion HeadRegion;
00077	
00078	// Navigation AI
00079	var 	float		MoveTimer;
00080	var 	Actor		MoveTarget;		// set by movement natives
00081	var		Actor		FaceTarget;		// set by strafefacing native
00082	var		vector	 	Destination;	// set by Movement natives
00083	var	 	vector		Focus;			// set by Movement natives
00084	var		float		DesiredSpeed;
00085	var		float		MaxDesiredSpeed;
00086	var(Combat) float	MeleeRange; // Max range for melee attack (not including collision radii)
00087	
00088	var(Combat) float	CombatRange; // RUNE:  Range the creature tries to stay within during his fighting state
00089									 // CombatRange is usually further than meleerange (which is the range in which he actually can attack)
00090	var bool bStopMoveIfCombatRange; // RUNE:  a moveToward latent function will exit if the enemy is within CombatRange
00091	
00092	// Player and enemy movement.
00093	var(Movement) float		GroundSpeed;	// The maximum ground speed.
00094	var(Movement) float		WaterSpeed;		// The maximum swimming speed.
00095	var(Movement) float		AirSpeed;		// The maximum flying speed.
00096	var(Movement) float		AccelRate;		// max acceleration rate
00097	var(Movement) float		JumpZ;      	// vertical acceleration w/ jump
00098	var(Movement) float		MaxStepHeight;	// Maximum size of upward/downward step.
00099	var(Movement) float		AirControl;		// amount of AirControl available to the pawn
00100	var(Movement) float		WalkingSpeed;	// RUNE:  Speed creature walks
00101	var float				MovementSpeed;	// RUNE:  Current speed modifier 0..1 (Set by UpdateMovementSpeed())
00102	var bool				bHurrying;		// RUNE:  Whether running or walking
00103	
00104	var ESpeedScale SpeedScale;				// RUNE:  Handles the movement type (circular, elliptical, etc)
00105	var int					ClassID;			// ID determining same family of creatures
00106	
00107	// AI basics.
00108	var	 	float		MinHitWall;		// Minimum HitNormal dot Velocity.Normal to get a HitWall from the
00109										// physics
00110	var() 	byte       	Visibility;      //How visible is the pawn? 0 = invisible. 
00111										// 128 = normal.  255 = highly visible.
00112	var		float		Alertness; // -1 to 1 ->Used within specific states for varying reaction to stimuli 
00113	var		float 		Stimulus; // Strength of stimulus - Set when stimulus happens, used in Acquisition state 
00114	var(AI) float		SightRadius;     //Maximum seeing distance.
00115	var(AI) float		PeripheralVision;	//Cosine of limits of peripheral vision. (-1..1)
00116	var(AI) float		HearingThreshold;  //Minimum noise loudness for hearing
00117	var		vector		LastSeenPos; 		// enemy position when I last saw enemy (auto updated if EnemyNotVisible() enabled)
00118	var		vector		LastSeeingPos;		// position where I last saw enemy (auto updated if EnemyNotVisible enabled)
00119	var		float		LastSeenTime;
00120	var	 	Pawn    	Enemy;
00121	
00122	// Player info.
00123	var travel Weapon       Weapon;			// The pawn's current weapon.
00124	var travel Shield		Shield;			// The pawn's current shield
00125	var Weapon				PendingWeapon;	// Will become weapon once current weapon is put down
00126	var travel Inventory	SelectedItem;	// currently selected inventory item
00127	var name				StartEvent;		// Event of PlayerStart (temp storage)
00128	var int					CurrentSkin;	// Index of skin currently being used
00129	
00130	// Movement.
00131	var rotator     	ViewRotation;  	// View rotation.
00132	var vector			ViewLocation;	// RUNE: To cache camera location for PlayerCanSeeMe()
00133	var vector			WalkBob;
00134	var() float      	BaseEyeHeight; 	// Base eye height above collision center.
00135	var float        	EyeHeight;     	// Current eye height, adjusted for bobbing and stairs.
00136	var	const	vector	Floor;			// Normal of floor pawn is standing on (only used
00137										//	by PHYS_Spider)
00138	var float			SplashTime;		// time of last splash
00139	
00140	var vector GrabLocationUp; // RUNE:  Pull-up location of grab
00141	var vector GrabLocationIn; // RUNE:  Push-in location of grab
00142	
00143	// View
00144	var float        OrthoZoom;     // Orthogonal/map view zoom factor.
00145	var() float      FovAngle;      // X field of view angle in degrees, usually 90.
00146	
00147	// Player game statistics.
00148	var int			DieCount, ItemCount, KillCount, SecretCount, Spree;
00149	
00150	// Pawn Attributes
00151	var() travel int	Health;				// Health:
00152	var() travel int	Strength;			// RUNE:  Strength damage modifier
00153	var() travel int	RunePower;			// RUNE:  Current amount of RunePower
00154	var() travel int	MaxHealth;			// RUNE:  Maximum health: 100 = normal
00155	var() travel int	MaxStrength;		// RUNE:  Maximum strength, 100 = normal
00156	var() travel int	MaxPower;			// RUNE:  Maximum power.  100 = normal
00157	
00158	var() int BodyPartHealth[15];			// RUNE:  Health of bodyparts
00159	var() int GibCount;						// RUNE:  Number of normal gibs to spew out
00160	var() class<Debris> GibClass;			// RUNE:  Gib to spew out
00161	var() float	PainDelay;					// RUNE:  Time to delay when in the pain state (if negative, does a FinishAnim())
00162	var() bool bGibbable;					// RUNE:  Can be gibbed
00163	var bool bInvisible;					// RUNE:  Pawn is invisible to others
00164	
00165	// Selection Mesh
00166	var() string			SelectionMesh;
00167	var() string			SpecialMesh;
00168	
00169	// Inherent Armor (for creatures).
00170	var() name	ReducedDamageType; //Either a damagetype name or 'All', 'AllEnvironment' (Burned, Corroded, Frozen)
00171	var() float ReducedDamagePct;
00172	
00173	// Inventory to drop when killed (for creatures)
00174	var() class<inventory> DropWhenKilled;
00175	
00176	// Zone pain
00177	var(Movement) float		UnderWaterTime;  	//how much time pawn can go without air (in seconds)
00178	
00179	var(AI) enum EAttitude  //important - order in decreasing importance
00180	{
00181		ATTITUDE_Fear,		//will try to run away
00182		ATTITUDE_Hate,		// will attack enemy
00183		ATTITUDE_Frenzy,	//will attack anything, indiscriminately
00184		ATTITUDE_Threaten,	// animations, but no attack
00185		ATTITUDE_Ignore,
00186		ATTITUDE_Friendly,
00187		ATTITUDE_Follow 	//accepts player as leader
00188	} AttitudeToPlayer;	//determines how creature will react on seeing player (if in human form)
00189	
00190	var(AI) enum EIntelligence //important - order in increasing intelligence
00191	{
00192		BRAINS_NONE, //only reacts to immediate stimulus
00193		BRAINS_REPTILE, //follows to last seen position
00194		BRAINS_MAMMAL, //simple navigation (limited path length)
00195		BRAINS_HUMAN   //complex navigation, team coordination, use environment stuff (triggers, etc.)
00196	}	Intelligence;
00197	
00198	var(AI) float		Skill;			// skill, scaled by game difficulty (add difficulty to this value)	
00199	var		actor		SpecialGoal;	// used by navigation AI
00200	var		float		SpecialPause;
00201	
00202	// Sound and noise management
00203	var const 	vector 		noise1spot;
00204	var const 	float 		noise1time;
00205	var const	pawn		noise1other;
00206	var const	float		noise1loudness;
00207	var const 	vector 		noise2spot;
00208	var const 	float 		noise2time;
00209	var const	pawn		noise2other;
00210	var const	float		noise2loudness;
00211	var			float		LastPainSound;
00212	
00213	// chained pawn list
00214	var const	pawn		nextPawn;
00215	
00216	// Common sounds
00217	var(Sounds)	sound	HitSound1;
00218	var(Sounds)	sound	HitSound2;
00219	var(Sounds) sound	HitSound3;
00220	var(Sounds)	sound	Die;
00221	var(Sounds) sound	Die2;
00222	var(Sounds) sound	Die3;
00223	var(Sounds) sound	WaterStep;
00224	var(Sounds) sound	GibSound;
00225	//var(Sounds)	sound	Land;
00226	var(Sounds) float	FootstepVolume;
00227	
00228	var(Sounds) sound	LandGrunt;
00229	var(Sounds) sound	FootStepWood[3];
00230	var(Sounds) sound	FootStepMetal[3];
00231	var(Sounds) sound	FootStepStone[3];
00232	var(Sounds) sound	FootStepFlesh[3];
00233	var(Sounds) sound	FootStepIce[3];
00234	var(Sounds) sound	FootStepEarth[3];
00235	var(Sounds) sound	FootStepSnow[3];
00236	var(Sounds) sound	FootStepBreakableWood[3];
00237	var(Sounds) sound	FootStepBreakableStone[3];
00238	var(Sounds) sound	FootStepWater[3];
00239	var(Sounds) sound	FootStepMud[3];
00240	var(Sounds) sound	FootStepLava[3];
00241	var(Sounds) sound	LandSoundWood;
00242	var(Sounds) sound	LandSoundMetal;
00243	var(Sounds) sound	LandSoundStone;
00244	var(Sounds) sound	LandSoundFlesh;
00245	var(Sounds) sound	LandSoundIce;
00246	var(Sounds) sound	LandSoundSnow;
00247	var(Sounds) sound	LandSoundEarth;
00248	var(Sounds) sound	LandSoundBreakableWood;
00249	var(Sounds) sound	LandSoundBreakableStone;
00250	var(Sounds) sound	LandSoundWater;
00251	var(Sounds) sound	LandSoundMud;
00252	var(Sounds) sound	LandSoundLava;
00253	
00254	// Input buttons.
00255	var input byte
00256		bZoom, bRun, bLook, bDuck, bSnapLevel,
00257		bStrafe, bFire, bAltFire, bFreeLook,
00258		bExtra0, bExtra1, bExtra2, bExtra3;
00259	
00260	var(Combat) float CombatStyle; // -1 to 1 = low means tends to stay off and snipe, high means tends to charge and melee
00261	//var NavigationPoint home; //set when begin play, used for retreating and attitude checks
00262	
00263	var name NextState; //for queueing states
00264	var name NextLabel; //for queueing states
00265	var name NextStateAfterPain;
00266	
00267	var float SoundDampening;
00268	var float DamageScaling;
00269	
00270	var Name PlayerReStartState;
00271	
00272	var() localized  string MenuName; //Name used for this pawn type in menus (e.g. player selection) 
00273	var() localized  string NameArticle; //article used in conjunction with this class (e.g. "a", "an")
00274	
00275	var() byte VoicePitch; //for speech
00276	var() string VoiceType; //for speech
00277	var float OldMessageTime; //to limit frequency of voice messages
00278	
00279	var(Skeleton) name		WeaponJoint;		// Name of weapon attachment joint
00280	var(Skeleton) name		ShieldJoint;		// Name of weapon attachment joint
00281	
00282	var(Skeleton) name		StabJoint;			// RUNE:  Name of joint a weapon can be stuck into the actor
00283	 
00284	// Route Cache for Navigation
00285	var NavigationPoint RouteCache[16];
00286	
00287	// Replication Info
00288	var() class<PlayerReplicationInfo> PlayerReplicationInfoClass;
00289	var PlayerReplicationInfo PlayerReplicationInfo;
00290	
00291	// shadow decal
00292	var Decal Shadow;
00293	
00294	
00295	// ** Stuff added for RUNE (don't cull) **
00296	
00297	var(Look) bool bCanLook;		// Pawn has base_ joints..  can look around
00298	var(Look) rotator MaxBodyAngle;	// Max angles on each axis for body turning
00299	var(Look) rotator MaxHeadAngle;	// Max angles on each axis for head turning
00300	var(Look) bool bRotateHead;
00301	var(Look) bool bRotateTorso;	// Torso turns during look
00302	var(Look) bool bHeadLookUpDouble; // RUNE:  Allow the head to look up double the MaxHeadAngle Pitch
00303	var(Look) float LookDegPerSec;	// Degrees/Second velocity for turning to look
00304	var actor LookTarget;			// Actor pawn is interested in
00305	var vector LookSpot;			// Position pawn is interested in
00306	var rotator LookAngle;			// Angle currently looking
00307	var rotator targetangle;		// Only used when bOverrideLookTarget
00308	var bool bOverrideLookTarget;	// Use existing targetangle for looking
00309	
00310	var int MouthRot;
00311	var int DesiredMouthRot;
00312	var int MouthRotRate;
00313	var(Look) int MaxMouthRot;			// 16000 for goblin
00314	var(Look) int MaxMouthRotRate;		// 65535 for goblin
00315	
00316	// Footsteps
00317	var(Footsteps) class<Decal>	FootprintClass;
00318	var(Footsteps) class<Decal>	WetFootprintClass;
00319	var(Footsteps) class<Decal>	BloodyFootprintClass;
00320	var(Footsteps) int			LFootJoint;
00321	var(Footsteps) int			RFootJoint;
00322	var(Footsteps) bool			bFootsteps;
00323	var int						WaterSteps;
00324	var int						BloodSteps;
00325	
00326	var bool bSwingingHigh;				// Currently swinging high (used to warn targets)
00327	var bool bSwingingLow;				// Currently swinging low
00328	
00329	var(Collision) float DeathRadius;	// Collision Radius upon death
00330	var(Collision) float DeathHeight;	// Collision Height upon death
00331	var(Collision) bool bAllowStandOn;	// Allow actors to stand on top of instead of throwing off
00332	
00333	var(Combat) bool bLeadEnemy;		// Actor will lead the enemy when charging, instead of charging straight at them
00334	
00335	var name UninterruptedAnim;			// RUNE: Used specifically in the Uninterrupted state
00336	var Actor UseActor;					// RUNE: Used by Use functionality
00337	var() localized  string SkinDefaultText;	//Text describing Default Skin
00338	
00339	event ShadowUpdate(int ShadowType); // RUNE:  Update shadow
00340	
00341	
00342	
00343	//------------------------------------------------------------
00344	//
00345	// PreBeginPlay
00346	//
00347	// Called immediately before gameplay begins.
00348	//------------------------------------------------------------
00349	event PreBeginPlay()
00350	{
00351		AddPawn();
00352		Super.PreBeginPlay();
00353		if ( bDeleteMe )
00354			return;
00355	
00356		// Set instigator to self.
00357		Instigator = Self;
00358		DesiredRotation = Rotation;
00359		SightCounter = 0.2 * FRand();  //offset randomly 
00360		if ( Level.Game != None )
00361			Skill += Level.Game.Difficulty; 
00362		Skill = FClamp(Skill, 0, 3);
00363		PreSetMovement();
00364		
00365		if ( DrawScale != Default.Drawscale )
00366		{
00367			// Collision moved to actor
00368			//SetCollisionSize(CollisionRadius*DrawScale/Default.DrawScale, CollisionHeight*DrawScale/Default.DrawScale);
00369			Health = Health * DrawScale/Default.DrawScale;
00370			GroundSpeed = GroundSpeed * DrawScale/Default.DrawScale;
00371		}
00372		
00373		if (bIsPlayer)
00374		{
00375			if (PlayerReplicationInfoClass != None)
00376				PlayerReplicationInfo = Spawn(PlayerReplicationInfoClass, Self,,vect(0,0,0),rot(0,0,0));
00377			else
00378				PlayerReplicationInfo = Spawn(class'PlayerReplicationInfo', Self,,vect(0,0,0),rot(0,0,0));
00379			InitPlayerReplicationInfo();
00380	
00381			switch(Level.Game.Difficulty)
00382			{
00383				case 0:
00384					UnderWaterTime *= 3;
00385					break;
00386				case 1:
00387					UnderWaterTime *= 2;
00388					break;
00389				case 2:
00390				default:
00391					break;
00392			}
00393		}
00394	
00395		if (!bIsPlayer) 
00396		{
00397			if ( BaseEyeHeight == 0 )
00398				BaseEyeHeight = 0.8 * CollisionHeight;
00399			EyeHeight = BaseEyeHeight;
00400			if (Fatness == 0) //vary monster fatness slightly if at default
00401				Fatness = 120 + Rand(8) + Rand(8);
00402		}
00403	
00404		if ( menuname == "" )
00405			menuname = GetItemName(string(class));
00406	
00407		if (SelectionMesh == "")
00408			SelectionMesh = string(Skeletal);
00409	}
00410	
00411	event PostBeginPlay()
00412	{
00413		Super.PostBeginPlay();
00414		SplashTime = 0;
00415	}
00416	
00417	// called after PostBeginPlay on net client
00418	event PostNetBeginPlay()
00419	{
00420		if ( Role != ROLE_SimulatedProxy )
00421			return;
00422	/*	if ( bIsMultiSkinned && bIsPlayer )
00423		{
00424			if ( MultiSkins[0] == None )
00425			{
00426				if ( bIsPlayer )
00427					SetMultiSkin(self, "","", PlayerReplicationInfo.team);
00428				else
00429					SetMultiSkin(self, "","", 0);
00430			}
00431		}
00432		else if ( Skin == None )
00433			Skin = Default.Skin;
00434	*/
00435	
00436		if ( (PlayerReplicationInfo != None) 
00437			&& (PlayerReplicationInfo.Owner == None) )
00438			PlayerReplicationInfo.SetOwner(self);
00439	}
00440	
00441	
00442	//=============================================================================
00443	// Network related
00444	//=============================================================================
00445	
00446	replication
00447	{
00448		// Variables the server should send to the client.
00449		reliable if( Role==ROLE_Authority )
00450			Weapon, PlayerReplicationInfo, Health, bCanFly,
00451			MaxHealth, MaxStrength, MaxPower, Strength, RunePower;
00452		reliable if( bNetOwner && Role==ROLE_Authority )
00453			bIsPlayer, SelectedItem,
00454			GroundSpeed, WaterSpeed, AirSpeed, AccelRate, JumpZ, AirControl,
00455			PlayerRestartState,
00456			CurrentSkin,
00457			SpeedScale;
00458		unreliable if( (bNetOwner && bIsPlayer && bNetInitial && Role==ROLE_Authority) || bDemoRecording )
00459			ViewRotation;
00460		unreliable if( bNetOwner && Role==ROLE_Authority )
00461	        MoveTarget;
00462	
00463		reliable if( bDemoRecording )
00464			EyeHeight;
00465	
00466		// Functions the server calls on the client side.
00467		reliable if( RemoteRole==ROLE_AutonomousProxy ) 
00468			ClientDying, ClientReStart, ClientGameEnded, ClientSetRotation, ClientSetLocation, ClientPutDown;
00469		unreliable if( (!bDemoRecording || bClientDemoRecording && bClientDemoNetFunc) && Role==ROLE_Authority )
00470			ClientHearSound;
00471		reliable if ( (!bDemoRecording || (bClientDemoRecording && bClientDemoNetFunc)) && Role == ROLE_Authority )
00472			ClientVoiceMessage;
00473		reliable if ( (!bDemoRecording || (bClientDemoRecording && bClientDemoNetFunc) || (Level.NetMode==NM_Standalone && IsA('PlayerPawn'))) && Role == ROLE_Authority )
00474			ClientMessage, TeamMessage, ReceiveLocalizedMessage;
00475	
00476		// Functions the client calls on the server.
00477		unreliable if( Role<ROLE_Authority )
00478			SendVoiceMessage, NextItem, SwitchToBestWeapon, TeamBroadcast;
00479	
00480		// RUNE:
00481		unreliable if ( Role==ROLE_Authority )
00482			bCanLook, bRotateHead, bRotateTorso, bAlignToFloor, Shield;
00483	}
00484	
00485	function InitPlayerReplicationInfo()
00486	{
00487		if (PlayerReplicationInfo.PlayerName == "")
00488			PlayerReplicationInfo.PlayerName = class'GameInfo'.Default.DefaultPlayerName;
00489	}
00490	
00491	simulated event Destroyed()
00492	{
00493		local Inventory Inv, nextInv;
00494		local Pawn OtherPawn;
00495	
00496		if ( Shadow != None )
00497			Shadow.Destroy();
00498		if ( Role < ROLE_Authority )
00499			return;
00500	
00501		RemovePawn();
00502	
00503		for(Inv = Inventory; Inv != None; Inv = nextInv)
00504		{
00505			nextInv = Inv.Inventory;
00506			Inv.Destroy();
00507		}
00508	
00509		Weapon = None;
00510		Shield = None;
00511		Inventory = None;
00512		if ( bIsPlayer && (Level.Game != None) )
00513			Level.Game.logout(self);
00514		if ( PlayerReplicationInfo != None )
00515			PlayerReplicationInfo.Destroy();
00516	
00517		for ( OtherPawn=Level.PawnList; OtherPawn!=None; OtherPawn=OtherPawn.nextPawn )
00518			OtherPawn.Killed(None, self, '');
00519	
00520		Super.Destroyed();
00521	}
00522	
00523	event PlayerTimeOut()
00524	{
00525		if (Health > 0)
00526			Died(None, 'suicided', Location);
00527	}
00528	
00529	
00530	//=============================================================================
00531	// Messaging functions
00532	//=============================================================================
00533	
00534	event ClientMessage( coerce string S, optional name Type, optional bool bBeep );
00535	event TeamMessage( PlayerReplicationInfo PRI, coerce string S, name Type, optional bool bBeep );
00536	event ReceiveLocalizedMessage( class<LocalMessage> Message, optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject );
00537	
00538	function BecomeViewTarget()
00539	{
00540		bViewTarget = true;
00541	}
00542	
00543	function HandleHelpMessageFrom(Pawn Other);
00544	
00545	function ClientVoiceMessage(PlayerReplicationInfo Sender, PlayerReplicationInfo Recipient, name messagetype, byte messageID);
00546	function BotVoiceMessage(name messagetype, byte MessageID, Pawn Sender);
00547	
00548	function string KillMessage( name damageType, pawn Other )
00549	{
00550		local string message;
00551	
00552		message = Level.Game.CreatureKillMessage(damageType, Other);
00553		return (Other.PlayerReplicationInfo.PlayerName$message$namearticle$menuname);
00554	}
00555	
00556	//------------------------------------------------------------------------------
00557	// Speech related
00558	
00559	function SendGlobalMessage(PlayerReplicationInfo Recipient, name MessageType, byte MessageID, float Wait)
00560	{
00561		SendVoiceMessage(PlayerReplicationInfo, Recipient, MessageType, MessageID, 'GLOBAL');
00562	}
00563	
00564	
00565	function SendTeamMessage(PlayerReplicationInfo Recipient, name MessageType, byte MessageID, float Wait)
00566	{
00567		SendVoiceMessage(PlayerReplicationInfo, Recipient, MessageType, MessageID, 'TEAM');
00568	}
00569	
00570	function SendVoiceMessage(PlayerReplicationInfo Sender, PlayerReplicationInfo Recipient, name messagetype, byte messageID, name broadcasttype)
00571	{
00572		local Pawn P;
00573		local bool bNoSpeak;
00574	
00575		if ( Level.TimeSeconds - OldMessageTime < 2.5 )
00576			bNoSpeak = true;
00577		else
00578			OldMessageTime = Level.TimeSeconds;
00579	
00580		for ( P=Level.PawnList; P!=None; P=P.NextPawn )
00581		{
00582			if ( P.IsA('PlayerPawn') )
00583			{  
00584				if ( !bNoSpeak )
00585				{
00586					if ( (broadcasttype == 'GLOBAL') || !Level.Game.bTeamGame )
00587						P.ClientVoiceMessage(Sender, Recipient, messagetype, messageID);
00588					else if ( Sender.Team == P.PlayerReplicationInfo.Team )
00589						P.ClientVoiceMessage(Sender, Recipient, messagetype, messageID);
00590				}
00591			}
00592			else if ( (P.PlayerReplicationInfo == Recipient) || ((messagetype == 'ORDER') && (Recipient == None)) )
00593				P.BotVoiceMessage(messagetype, messageID, self);
00594		}
00595	}
00596	
00597	
00598	
00599	// Broadcast a text message to all players, or all on the same team.
00600	function TeamBroadcast( coerce string Msg)
00601	{
00602		local Pawn P;
00603		local bool bGlobal;
00604	
00605		if ( Left(Msg, 1) ~= "@" )
00606		{
00607			Msg = Right(Msg, Len(Msg)-1);
00608			bGlobal = true;
00609		}
00610	
00611		if ( Left(Msg, 1) ~= "." )
00612			Msg = "."$VoicePitch$Msg;
00613	
00614		if ( bGlobal || !Level.Game.bTeamGame )
00615		{
00616			if ( Level.Game.AllowsBroadcast(self, Len(Msg)) )
00617				for( P=Level.PawnList; P!=None; P=P.nextPawn )
00618					if( P.bIsPlayer  || P.IsA('MessagingSpectator') )
00619						P.TeamMessage( PlayerReplicationInfo, Msg, 'Say' );
00620			return;
00621		}
00622			
00623		if ( Level.Game.AllowsBroadcast(self, Len(Msg)) )
00624			for( P=Level.PawnList; P!=None; P=P.nextPawn )
00625				if( P.bIsPlayer && (P.PlayerReplicationInfo.Team == PlayerReplicationInfo.Team) )
00626				{
00627					if ( P.IsA('PlayerPawn') )
00628						P.TeamMessage( PlayerReplicationInfo, Msg, 'TeamSay' );
00629				}
00630	}
00631	
00632	
00633	//=============================================================================
00634	// Client-side functions
00635	//=============================================================================
00636	
00637	function ClientSetLocation( vector NewLocation, rotator NewRotation )
00638	{
00639		local Pawn P;
00640	
00641		ViewRotation      = NewRotation;
00642		If ( (ViewRotation.Pitch > RotationRate.Pitch) && (ViewRotation.Pitch < 65536 - RotationRate.Pitch) )
00643		{
00644			If (ViewRotation.Pitch < 32768) 
00645				NewRotation.Pitch = RotationRate.Pitch;
00646			else
00647				NewRotation.Pitch = 65536 - RotationRate.Pitch;
00648		}
00649		NewRotation.Roll  = 0;
00650		SetRotation( NewRotation );
00651		SetLocation( NewLocation );
00652	}
00653	
00654	function ClientSetRotation( rotator NewRotation )
00655	{
00656		local Pawn P;
00657	
00658		ViewRotation      = NewRotation;
00659		NewRotation.Pitch = 0;
00660		NewRotation.Roll  = 0;
00661		SetRotation( NewRotation );
00662	}
00663	
00664	native simulated event ClientHearSound ( 
00665		actor Actor, 
00666		int Id, 
00667		sound S, 
00668		vector SoundLocation, 
00669		vector Parameters 
00670	);
00671	
00672	function ClientDying(name DamageType, vector HitLocation)
00673	{
00674		PlayDying(DamageType, HitLocation);
00675		GotoState('Dying');
00676	}
00677	
00678	function ClientReStart()
00679	{
00680	//	local rotator r;
00681	
00682		Velocity = vect(0,0,0);
00683		Acceleration = vect(0,0,0);
00684		BaseEyeHeight = Default.BaseEyeHeight;
00685		EyeHeight = BaseEyeHeight;
00686	
00687	//	r = Rotation;
00688	//	r.Pitch = 0;
00689	//	r.Roll = 0;
00690	//	SetRotation(r);
00691	
00692		// Reset cache to idle pose, then actually play it since, reset sets it back for next frame
00693		ResetAnimationCache('neutral_idle');
00694		LoopAnim('neutral_idle', 1.0, 0.0);
00695		if (AnimProxy != None)
00696			AnimProxy.LoopAnim('neutral_idle', 1.0, 0.0);
00697	
00698		if ( Region.Zone.bWaterZone && (PlayerRestartState == 'PlayerWalking') )
00699		{
00700			if (HeadRegion.Zone.bWaterZone)
00701				PainTime = UnderWaterTime;
00702			setPhysics(PHYS_Swimming);
00703			GotoState('PlayerSwimming');
00704		}
00705		else
00706			GotoState(PlayerReStartState);
00707	}
00708	
00709	function ClientGameEnded()
00710	{
00711		GotoState('GameEnded');
00712	}
00713	
00714	
00715	
00716	
00717	//=============================================================================
00718	// Latent Movement.
00719	//=============================================================================
00720	
00721	//Note that MoveTo sets the actor's Destination, and MoveToward sets the
00722	//actor's MoveTarget.  Actor will rotate towards destination
00723	
00724	native(500) final latent function MoveTo( vector NewDestination, optional float speed);
00725	native(502) final latent function MoveToward(actor NewTarget, optional float speed);
00726	native(504) final latent function StrafeTo(vector NewDestination, vector NewFocus);
00727	native(506) final latent function StrafeFacing(vector NewDestination, actor NewTarget);
00728	native(508) final latent function TurnTo(vector NewFocus);
00729	native(510) final latent function TurnToward(actor NewTarget);
00730	
00731	
00732	//=============================================================================
00733	// AI functions
00734	//=============================================================================
00735	
00736	// LineOfSightTo() returns true if any of several points of Other is visible (origin, top, bottom)
00737	native(514) final function bool LineOfSightTo(actor Other); 
00738	
00739	// CanSee() similar to line of sight, but also takes into account Pawn's peripheral vision
00740	native(533) final function bool CanSee(actor Other); 
00741	native(518) final function Actor FindPathTo(vector aPoint, optional bool bSinglePath, 
00742													optional bool bClearPaths);
00743	native(517) final function Actor FindPathToward(actor anActor, optional bool bSinglePath, 
00744													optional bool bClearPaths);
00745	
00746	// returns a random pathnode which is reachable from the creature's location
00747	native(525) final function NavigationPoint FindRandomDest(optional bool bClearPaths);
00748	
00749	// clear all temporary path variables used in routing
00750	native(522) final function ClearPaths();
00751	
00752	native(523) final function vector EAdjustJump();
00753	
00754	//Reachable returns what part of direct path from Actor to aPoint is traversable
00755	//using the current locomotion method
00756	native(521) final function bool pointReachable(vector aPoint);
00757	native(520) final function bool actorReachable(actor anActor);
00758	
00759	native(664) final function NavigationPoint NearestNavPoint();
00760	native(665) final function NavigationPoint CloserNavPointTo(actor Other);
00761	
00762	final function Actor FindPathAwayFrom(actor anActor, optional actor justvisited)
00763	{
00764		local float distsquared, furthestdistsquared;
00765		local NavigationPoint N;
00766		local actor A, furthestpoint;
00767		local vector topoint;
00768		local int i, numpaths;
00769	
00770		N = NearestNavPoint();
00771		if (N == None)
00772			return N;
00773	
00774		numpaths = N.NumPaths();
00775		for (i=0; i<numpaths; i++)
00776		{
00777			A = N.PathEndPoint(i);
00778			if (A == justvisited)
00779				continue;
00780			topoint = A.Location - anActor.Location;
00781			distsquared = topoint dot topoint;
00782			if (distsquared > furthestdistsquared)
00783			{
00784				furthestdistsquared = distsquared;
00785				furthestpoint = A;
00786			}
00787		}
00788		return furthestpoint;
00789	}
00790	
00791	//------------------------------------------------
00792	//
00793	// FindBestPathToward
00794	//
00795	// Assumes the desired destination is not directly reachable, 
00796	// it tries to set Destination to the location of the best
00797	// waypoint, and returns true if successful
00798	//------------------------------------------------
00799	function bool FindBestPathToward(actor desired)
00800	{
00801		local Actor path;
00802		local bool success;
00803		
00804		path = None;
00805		if (Intelligence <= BRAINS_Reptile)
00806			path = FindPathToward(desired, true);
00807		else 
00808			path = FindPathToward(desired); 
00809			
00810		success = (path != None);
00811		if (success)
00812		{
00813			MoveTarget = path; 
00814			Destination = path.Location;
00815		}
00816	//slog("findbestpathtoward"@desired.name@"="$success);
00817		return success;
00818	}
00819	
00820	
00821	//------------------------------------------------------------
00822	//
00823	// PickWallAdjust()
00824	//
00825	// Check if could jump up over obstruction (only if there is a knee height obstruction)
00826	// If so, start jump, and return current destination
00827	// Else, try to step around - return a destination 90 degrees right or left depending on traces
00828	// out and floor checks
00829	//------------------------------------------------------------
00830	native(526) final function bool PickWallAdjust();
00831	native(524) final function int FindStairRotation(float DeltaTime);
00832	
00833	// Wait until physics is not PHYS_Falling
00834	native(527) final latent function WaitForLanding();
00835	
00836	native(540) final function actor FindBestInventoryPath(out float MinWeight, bool bPredictRespawns);
00837	
00838	native(529) final function AddPawn();
00839	native(530) final function RemovePawn();
00840	
00841	// Pick best pawn target
00842	native(531) final function pawn PickTarget(out float bestAim, out float bestDist, vector FireDir, vector projStart);
00843	native(534) final function actor PickAnyTarget(out float bestAim, out float bestDist, vector FireDir, vector projStart);
00844	
00845	native(535) final function vector FindWaterLine(vector Start, vector End); // RUNE
00846	
00847	// Force end to sleep
00848	native function StopWaiting();
00849	
00850	
00851	//=============================================================================
00852	// Display
00853	//=============================================================================
00854	
00855	simulated event RenderOverlays( canvas Canvas )
00856	{
00857		if ( Weapon != None )
00858			Weapon.RenderOverlays(Canvas);
00859	}
00860	
00861	/*
00862	static function SetMultiSkin( actor SkinActor, string SkinName, string FaceName, byte TeamNum )
00863	{
00864		local Texture NewSkin;
00865	
00866		if(SkinName != "")
00867		{
00868			NewSkin = texture(DynamicLoadObject(SkinName, class'Texture'));
00869			if ( NewSkin != None )
00870				SkinActor.Skin = NewSkin;
00871		}
00872	}
00873	
00874	static function GetMultiSkin( Actor SkinActor, out string SkinName, out string FaceName )
00875	{
00876		SkinName = String(SkinActor.Skin);
00877		FaceName = "";
00878	}
00879	*/
00880	
00881	static function bool SetSkinElement(Actor SkinActor, int SkinNo, string SkinName, string DefaultSkinName)
00882	{
00883		local Texture NewSkin;
00884	
00885		NewSkin = Texture(DynamicLoadObject(SkinName, class'Texture'));
00886		if ( NewSkin != None )
00887		{
00888			SkinActor.Multiskins[SkinNo] = NewSkin;
00889			return True;
00890		}
00891		else
00892		{
00893			log("Failed to load "$SkinName);
00894			if(DefaultSkinName != "")
00895			{
00896				NewSkin = Texture(DynamicLoadObject(DefaultSkinName, class'Texture'));
00897				SkinActor.Multiskins[SkinNo] = NewSkin;
00898			}
00899			return False;
00900		}
00901	}
00902	
00903	function SetDisplayProperties(ERenderStyle NewStyle, texture NewTexture, bool bLighting, bool bEnviroMap )
00904	{
00905		Style = NewStyle;
00906		texture = NewTexture;
00907		bUnlit = bLighting;
00908		bMeshEnviromap = bEnviromap;
00909		if ( Weapon != None )
00910			Weapon.SetDisplayProperties(Style, Texture, bUnlit, bMeshEnviromap);
00911	
00912		if ( !bUpdatingDisplay && (Inventory != None) )
00913		{
00914			bUpdatingDisplay = true;
00915			Inventory.SetOwnerDisplay();
00916		}
00917		bUpdatingDisplay = false;
00918	}
00919	
00920	function SetDefaultDisplayProperties()
00921	{
00922		Style = Default.Style;
00923		texture = Default.Texture;
00924		bUnlit = Default.bUnlit;
00925		bMeshEnviromap = Default.bMeshEnviromap;
00926		if ( Weapon != None )
00927			Weapon.SetDisplayProperties(Weapon.Default.Style, Weapon.Default.Texture, Weapon.Default.bUnlit, Weapon.Default.bMeshEnviromap);
00928	
00929		if ( !bUpdatingDisplay && (Inventory != None) )
00930		{
00931			bUpdatingDisplay = true;
00932			Inventory.SetOwnerDisplay();
00933		}
00934		bUpdatingDisplay = false;
00935	}
00936	
00937	
00938	
00939	//=============================================================================
00940	// Game Events
00941	//=============================================================================
00942	function RestartPlayer();
00943	
00944	
00945	//=============================================================================
00946	// Stimulus events
00947	//=============================================================================
00948	event MayFall(); //return true if allowed to fall - called by engine when pawn is about to fall
00949	event AlterDestination(); // called when using movetoward with bAdvancedTactics true to temporarily modify destination
00950	event HearNoise( float Loudness, Actor NoiseMaker);
00951	event SeePlayer( actor Seen );
00952	event UpdateEyeHeight( float DeltaTime );
00953	event UpdateTactics(float DeltaTime); // for advanced tactics
00954	event EnemyNotVisible();
00955	event LongFall();
00956	event bool GrabEdge(float grabDistance, vector grabNormal);	// Pawn just grabbed an edge
00957	
00958	function Killed(pawn Killer, pawn Other, name damageType)
00959	{
00960		if ( Enemy == Other )
00961			Enemy = None;
00962	
00963	}
00964	
00965	function Falling()
00966	{
00967		local vector end;
00968	
00969		end = Location;
00970		end.Z -= CollisionHeight * 2.5;
00971	
00972		if(FastTrace(end, Location))
00973			PlayInAir(0.1);
00974	
00975	//	if (Velocity.Z < -JumpZ)
00976	//		PlayInAir(0.1);
00977	}
00978	
00979	event FellOutOfWorld()
00980	{
00981		if ( Role < ROLE_Authority )
00982			return;
00983		Health = -1;
00984		SetPhysics(PHYS_None);
00985		Weapon = None;
00986		Died(None, 'Fell', Location);
00987	}
00988	
00989	// Pawn interface called while PHYS_Walking and PHYS_Swimming to update the pawn with 
00990	// the latest information about the walk surface
00991	event WalkTexture( texture Texture, vector StepLocation, vector StepNormal )
00992	{
00993	}
00994	
00995	event Landed(vector HitNormal, actor HitActor)
00996	{
00997		local int damage;
00998	
00999		//Note - physics changes type to PHYS_Walking by default for landed pawns
01000	//	SetMovementPhysics();
01001		PlayLanded(Velocity.Z);
01002		if (Velocity.Z < -1.4 * JumpZ)
01003		{
01004			MakeNoise(-0.5 * Velocity.Z/(FMax(JumpZ, 150.0)));
01005	
01006			// Damage whatever the pawn landed on (if the pawn fell far enough)
01007			if(Velocity.Z <= -400 && HitActor != None)
01008			{
01009				// Don't hurt players in neutral zones
01010				if(Region.Zone.bNeutralZone || HitActor.Region.Zone.bNeutralZone)
01011					damage = 0;
01012				else if(Level.Game.bTeamGame && Pawn(HitActor) != None && self != None 
01013					&& Pawn(HitActor).PlayerReplicationInfo.Team != 255 
01014					&& Pawn(HitActor).PlayerReplicationInfo.Team == self.PlayerReplicationInfo.Team)
01015					damage = 0; // Don't hurt the victim if on the same team
01016				else if(!HitActor.IsA('LevelInfo'))
01017				{ // RUNE:  Damage anything the actor fell on
01018					if(HitActor.Mass > 0)	
01019						damage = -0.1 * (Velocity.Z) * Mass / HitActor.Mass;
01020					else
01021						damage = -0.1 * (Velocity.Z) * Mass / 100;
01022					HitActor.JointDamaged(damage, None, HitActor.Location, vect(0, 0, 0), 'blunt', 0);
01023				}
01024			}
01025	
01026			// Falling damage
01027			if (Velocity.Z <= -1100 && !HitActor.bJointsBlock)
01028			{
01029				if((Velocity.Z < -2000) && (ReducedDamageType != 'All'))
01030				{
01031					JointDamaged(1000, None, Location, vect(0,0,0), 'fell', 0);
01032				}
01033				else if ( Role == ROLE_Authority )
01034				{
01035					JointDamaged(-0.15 * (Velocity.Z + 1050), None, Location, vect(0,0,0), 'fell', 0);
01036				}
01037			}
01038		}
01039		bJustLanded = true;
01040	}
01041	
01042	//=============================================================================
01043	//
01044	// FootSteps/Notifies
01045	// 
01046	//=============================================================================
01047	
01048	simulated function FootStepRight()
01049	{
01050		if(!bFootsteps || RFootJoint==0)
01051			return;
01052	
01053		FootStepPrint(RFootJoint);
01054	}
01055	
01056	simulated function FootStepLeft()
01057	{
01058		if(!bFootsteps || LFootJoint==0)
01059			return;
01060	
01061		FootStepPrint(LFootJoint);
01062	}
01063	
01064	simulated function FootStepPrint(int footjoint)
01065	{
01066		local EMatterType matter;
01067		local sound snd;
01068		local vector footpos;
01069		local Decal d;
01070		local float sndVol;
01071		local bool bStealth;
01072		local int slot;
01073		
01074		footpos = GetJointPos(footjoint);
01075	
01076		if(FootRegion.Zone.bPainZone)
01077			matter = MATTER_LAVA;
01078		else if(FootRegion.Zone.bWaterZone)
01079			matter = MATTER_WATER;
01080		else
01081			matter = MatterTrace(footpos-vect(0,0,20), footpos+vect(0,0,20), 10);
01082	
01083		if (Physics == PHYS_Walking)
01084		{
01085			if(self.IsA('PlayerPawn') && PlayerPawn(self).bIsCrouching)
01086				bStealth = true; // Player is crouching, and hence being stealthy
01087			else
01088				bStealth = false;
01089	
01090			snd = GetFootstepSound(matter);
01091			if(snd != None)
01092			{
01093				if(bStealth)
01094					sndVol = 0.2;
01095				else
01096					sndVol = 0.33;
01097	
01098				// RUNE:  Allow player footstep sounds to overlap
01099				if(self.IsA('PlayerPawn'))
01100					PlaySound(snd, SLOT_None, sndVol, false,, 0.95 + (FRand() * 0.1));
01101				else
01102					PlaySound(snd, SLOT_Interact, sndVol, false,, 0.95 + (FRand() * 0.1));
01103			}		
01104			if(!bStealth && matter == MATTER_METAL || matter == MATTER_WATER || matter == MATTER_LAVA)
01105				MakeNoise(1.0);
01106		}
01107	
01108		// See if we're stepping in blood
01109		foreach RadiusActors(class'Decal', d, CollisionRadius, footpos)
01110		{
01111			if (d.bBloodyDecal)
01112				BloodSteps += 5;
01113		}
01114	
01115		if (matter==MATTER_WATER || matter==MATTER_LAVA)
01116			return;
01117	
01118		footpos.Z = Location.Z - CollisionHeight + 10;
01119		if (WaterSteps > 0)
01120		{	// Make water footprint
01121			WaterSteps--;
01122			d = Spawn(WetFootprintClass,self,,footpos);
01123			if (d!=None)
01124				d.DirectionalAttach(Velocity, Floor);
01125		}
01126		else if (BloodSteps > 0)
01127		{	// Make blood footprint
01128			BloodSteps--;
01129			d = Spawn(BloodyFootprintClass,self,,footpos);
01130			if (d!=None)
01131				d.DirectionalAttach(Velocity, Floor);
01132		}
01133		else if ((matter==MATTER_SNOW || matter==MATTER_EARTH) && FootprintClass!=None)
01134		{	// Make normal footprint
01135			d = Spawn(FootprintClass,self,,footpos);
01136			if (d!=None)
01137				d.DirectionalAttach(Velocity, Floor);
01138		}
01139	}
01140	
01141	simulated function Sound GetFootstepSound(EMatterType matter)
01142	{
01143		local int i;
01144		local sound snd;
01145	
01146		i = Rand(3);
01147		switch(matter)
01148		{
01149		case MATTER_FLESH:
01150			snd = FootStepFlesh[i];
01151			break;
01152		case MATTER_WOOD:
01153			snd = FootStepWood[i];
01154			break;
01155		case MATTER_STONE:
01156			snd = FootStepStone[i];
01157			break;
01158		case MATTER_METAL:
01159			snd = FootStepMetal[i];
01160			break;
01161		case MATTER_EARTH:
01162			snd = FootStepEarth[i];
01163			break;
01164		case MATTER_BREAKABLEWOOD:
01165			snd = FootStepBreakableWood[i];
01166			break;
01167		case MATTER_BREAKABLESTONE:
01168			snd = FootStepBreakableStone[i];
01169			break;
01170		case MATTER_ICE:
01171			snd = FootStepIce[i];
01172			break;
01173		case MATTER_SNOW:
01174			snd = FootStepSnow[i];
01175			break;
01176		case MATTER_WATER:
01177			snd = FootStepWater[i];
01178			break;
01179		case MATTER_MUD:
01180			snd = FootStepMud[i];
01181			break;
01182		case MATTER_LAVA:
01183			snd = FootStepLava[i];
01184			break;
01185		default:
01186			snd = None;
01187		}
01188	
01189		return snd;
01190	}
01191	
01192	simulated function FootStep()
01193	{
01194		local EMatterType matter;
01195		local vector end;
01196		local sound snd;
01197	
01198		if(bFootsteps && Physics == PHYS_Walking)
01199		{
01200			if(FootRegion.Zone.bPainZone)
01201				matter = MATTER_LAVA;
01202			else if(FootRegion.Zone.bWaterZone)
01203				matter = MATTER_WATER;
01204			else
01205			{
01206				end = Location;
01207				end.Z -= CollisionHeight + 8;
01208				matter = MatterTrace(end, Location, 10);
01209			}
01210	
01211			snd = GetFootstepSound(matter);
01212			if(snd != None)
01213			{
01214				PlaySound(snd, SLOT_Interact, FootstepVolume, false,, 0.95 + (FRand() * 0.1));
01215			}
01216		}
01217	}
01218	
01219	//------------------------------------------------------------
01220	//
01221	// FootZoneChange
01222	//
01223	//------------------------------------------------------------
01224	event FootZoneChange(ZoneInfo newFootZone)
01225	{
01226		local actor HitActor;
01227		local vector HitNormal, HitLocation;
01228		local float splashSize;
01229		local actor splash;
01230	
01231		// Handle footprints
01232		if ( FootRegion.Zone.bWaterZone )
01233		{
01234			WaterSteps = 15;
01235			BloodSteps = 0;
01236		}
01237	
01238		if ( Level.NetMode == NM_Client )
01239			return;
01240		if ( Level.TimeSeconds - SplashTime > 0.25 ) 
01241		{
01242			SplashTime = Level.TimeSeconds;
01243			if (Physics == PHYS_Falling)
01244				MakeNoise(1.0);
01245			else
01246				MakeNoise(0.3);
01247			if ( FootRegion.Zone.bWaterZone )
01248			{
01249				if ( !newFootZone.bWaterZone && (Role==ROLE_Authority) )
01250				{
01251					if ( FootRegion.Zone.ExitSound != None )
01252						PlaySound(FootRegion.Zone.ExitSound, SLOT_Misc, 1); 
01253					if ( FootRegion.Zone.ExitActor != None )
01254						Spawn(FootRegion.Zone.ExitActor,,,Location - CollisionHeight * vect(0,0,1));
01255				}
01256			}
01257			else if ( newFootZone.bWaterZone && (Role==ROLE_Authority) )
01258			{
01259				splashSize = FClamp(0.000025 * Mass * (300 - 0.5 * FMax(-500, Velocity.Z)), 1.0, 4.0 );
01260				if ( newFootZone.EntrySoundBig != None && Velocity.Z < -600)
01261				{
01262					HitActor = Trace(HitLocation, HitNormal, 
01263							Location - (CollisionHeight + 40) * vect(0,0,0.8),
01264							Location - CollisionHeight * vect(0,0,0.8), false);
01265					if ( HitActor == None )
01266						PlaySound(newFootZone.EntrySoundBig, SLOT_Misc, 2 * splashSize);
01267					else 
01268						PlaySound(WaterStep, SLOT_Misc, 1.5 + 0.5 * splashSize);
01269				}
01270				else if ( newFootZone.EntrySound != None )
01271				{
01272					HitActor = Trace(HitLocation, HitNormal, 
01273							Location - (CollisionHeight + 40) * vect(0,0,0.8),
01274							Location - CollisionHeight * vect(0,0,0.8), false);
01275					if ( HitActor == None )
01276						PlaySound(newFootZone.EntrySound, SLOT_Misc, 2 * splashSize);
01277					else 
01278						PlaySound(WaterStep, SLOT_Misc, 1.5 + 0.5 * splashSize);
01279				}
01280				if( newFootZone.EntryActor != None )
01281				{
01282					splash = Spawn(newFootZone.EntryActor,,,Location - CollisionHeight * vect(0,0,1));
01283					if ( splash != None )
01284						splash.DrawScale = splashSize;
01285				}
01286			}
01287		}
01288		
01289		if (FootRegion.Zone.bPainZone)
01290		{
01291			if ( !newFootZone.bPainZone && !HeadRegion.Zone.bWaterZone )
01292				PainTime = -1.0;
01293		}
01294		else if (newFootZone.bPainZone)
01295			PainTime = 0.01;
01296	}
01297	
01298	//------------------------------------------------------------
01299	//
01300	// HeadZoneChange
01301	//
01302	//------------------------------------------------------------
01303	event HeadZoneChange(ZoneInfo newHeadZone)
01304	{
01305		local int dummy1, dummy2;
01306	
01307		if ( Level.NetMode == NM_Client )
01308			return;
01309		if (HeadRegion.Zone.bWaterZone)
01310		{
01311			if (!newHeadZone.bWaterZone)
01312			{
01313				if ( bIsPlayer && (PainTime > 0) && (PainTime < 8) )
01314					Gasp();
01315				if ( Inventory != None )
01316					Inventory.ReduceDamage(dummy1, dummy2, 'Breathe', Location); //inform inventory of zone change
01317				bDrowning = false;
01318				if ( !FootRegion.Zone.bPainZone )
01319					PainTime = -1.0;
01320			}
01321		}
01322		else
01323		{
01324			if (newHeadZone.bWaterZone)
01325			{
01326				if ( !FootRegion.Zone.bPainZone )
01327					PainTime = UnderWaterTime;
01328				if ( Inventory != None )
01329					Inventory.ReduceDamage(dummy1, dummy2, 'Drowned', Location); //inform inventory of zone change
01330			}
01331		}
01332	}
01333	
01334	
01335	
01336	//=============================================================================
01337	// Timers
01338	//=============================================================================
01339	event SpeechTimer();
01340	event AmbientSoundTimer();
01341	event PainTimer()
01342	{
01343		local float depth;
01344	
01345		// Pain timer just expired:
01346		//  Check what zone I'm in (and which parts are)
01347		//  based on that cause damage, and reset PainTime
01348	
01349		if ( (Health < 0) || (Level.NetMode == NM_Client) )
01350			return;
01351			
01352		if ( FootRegion.Zone.bPainZone )
01353		{
01354			depth = 0.4;
01355			if (Region.Zone.bPainZone)
01356				depth += 0.4;
01357			if (HeadRegion.Zone.bPainZone)
01358				depth += 0.2;
01359	
01360			if (FootRegion.Zone.DamagePerSec > 0)
01361			{
01362				if ( IsA('PlayerPawn') )
01363					Level.Game.SpecialDamageString = FootRegion.Zone.DamageString;
01364				JointDamaged(int(float(FootRegion.Zone.DamagePerSec) * depth), None, Location, vect(0,0,0), FootRegion.Zone.DamageType, 0);
01365			}
01366			else if ( Health < Default.Health )
01367				Health = Min(Default.Health, Health - depth * FootRegion.Zone.DamagePerSec);
01368	
01369			if (Health > 0)
01370				PainTime = 1.0;
01371		}
01372		else if ( HeadRegion.Zone.bWaterZone )
01373		{
01374			bDrowning = true;
01375			JointDamaged(0.2*Default.Health, None, Location, vect(0,0,0), 'drowned', 0);
01376			if ( Health > 0 )
01377				PainTime = 2.0;
01378		}
01379	}
01380	
01381	
01382	
01383	//=============================================================================
01384	// Encroachment
01385	//=============================================================================
01386	
01387	event bool EncroachingOn( actor Other )
01388	{
01389		if ( (Other.Brush != None) || (Brush(Other) != None) )
01390			return true;
01391			
01392		if ( (!bIsPlayer || bWarping) && (Pawn(Other) != None))
01393			return true;
01394			
01395		return false;
01396	}
01397	
01398	event EncroachedBy( actor Other )
01399	{
01400		if ( Pawn(Other) != None )
01401		{
01402			health = -1000; //make sure gibs
01403			Died(pawn(Other), 'gibbed', Location);
01404		}
01405	}
01406	
01407	//Base change - if new base is pawn or decoration,
01408	// damage based on relative mass and old velocity
01409	// Also, non-players will jump off pawns immediately
01410	function JumpOffPawn()
01411	{
01412		Velocity += 60 * VRand();
01413		Velocity.Z = 180;
01414		SetPhysics(PHYS_Falling);
01415	}
01416	
01417	function UnderLift(Mover M);
01418	
01419	singular event BaseChange()
01420	{
01421		local float decorMass;
01422		local EMatterType matter;
01423		local int damage;
01424	
01425		if ( (base == None) && (Physics == PHYS_None) )
01426			SetPhysics(PHYS_Falling);
01427		else if (Pawn(Base) != None)
01428		{
01429	/* This functionality moved to Landed()
01430			damage = (1-Velocity.Z/400)* Mass/Base.Mass;
01431			if (damage > 0)
01432				Base.JointDamaged(damage, Self, Location, 0.5*Velocity, 'stomped', 0);
01433	*/
01434			if (Pawn(Base).bAllowStandOn)
01435				SetPhysics(PHYS_Walking);
01436			else
01437				JumpOffPawn();
01438		}
01439		else if ( (Decoration(Base) != None) )
01440		{
01441			if (Velocity.Z < -1.4*JumpZ)
01442			{
01443				matter=Base.MatterForJoint(0);
01444				PlayLandSound(matter, Velocity.Z);
01445			}
01446			if (Velocity.Z < -400)
01447			{
01448				decorMass = FMax(Decoration(Base).Mass, 1);
01449				Base.JointDamaged(-2* Mass/decorMass * Velocity.Z/400, Self, Location, 0.5*Velocity, 'stomped', 0);
01450			}
01451		}
01452	}
01453	
01454	
01455	//=============================================================================
01456	// Animation functions - should be implemented in subclass, 
01457	//=============================================================================
01458	function PlayWaiting		(optional float tween){}	// These are required
01459	function PlayMoving			(optional float tween){}
01460	function PlayJumping		(optional float tween){}
01461	function PlayTurning		(optional float tween){}
01462	function PlayMovingAttack	(optional float tween){}
01463	function PlayInAir			(optional float tween){}
01464	function PlayDuck			(optional float tween){}
01465	function PlayCrawling		(optional float tween){}
01466	
01467	function PlayThreatening	(optional float tween)		{	PlayWaiting(tween);	}
01468	function PlayOutOfWater		(optional float tween)		{	PlayJumping(tween);	}
01469	function PlayDive			(optional float tween)		{	PlayInAir(tween);	}
01470	function PlayPullUp			(optional float tween)		{	PlayJumping(tween);	}
01471	function PlayStepUp			(optional float tween)		{	PlayPullUp(tween);	}
01472	function PlayLanding		(optional float tween)		{}
01473	function PlayLanded(float impactVel)
01474	{
01475		local EMatterType matter;
01476		local vector end;
01477	
01478		if (impactVel < -JumpZ)
01479			PlayLanding(0.1);
01480	
01481		impactVel = impactVel/JumpZ;
01482		impactVel = 0.005 * Mass * impactVel * impactVel;
01483	
01484		if ( Role == ROLE_Authority )
01485		{
01486			if ( impactVel > 0.17 )
01487				PlaySound(LandGrunt, SLOT_Talk, FMin(5, 5 * impactVel),false,1200,FRand()*0.4+0.8);
01488	
01489			if(impactVel > 0.01)
01490			{ // Play Land Sound			
01491				if(FootRegion.Zone.bPainZone)
01492					matter = MATTER_LAVA;
01493				else if(FootRegion.Zone.bWaterZone)
01494					matter = MATTER_WATER;
01495				else
01496				{
01497					end = Location;
01498					end.Z -= CollisionHeight;
01499					matter = MatterTrace(end, Location, 10);
01500				}
01501	
01502				PlayLandSound(matter, impactVel);
01503			}
01504		}
01505	}
01506	
01507	
01508	function TweenToWaiting		(float tweentime){}
01509	function TweenToMoving		(float tweentime){}
01510	
01511	// Deaths
01512	function PlayDeath(name DamageType);										// hit from front
01513	function PlayBackDeath(name DamageType)		{ PlayDeath(DamageType);	}	// hit from behind
01514	function PlayLeftDeath(name DamageType)		{ PlayDeath(DamageType);	}	// fall to his left
01515	function PlayRightDeath(name DamageType)	{ PlayDeath(DamageType);	}	// fall to his right
01516	function PlayHeadDeath(name DamageType)		{ PlayDeath(DamageType);	}	// decapitated
01517	function PlayDrownDeath(name DamageType)	{ PlayDeath(DamageType);	}	// drown
01518	function PlaySkewerDeath(name DamageType)	{ PlayDeath(DamageType);	}	// hit by thrown sword
01519	function PlayGibDeath(name DamageType)
01520	{
01521	//	PlayDeath(DamageType);
01522		if (bIsPlayer)
01523			bHidden=true;
01524		else
01525			Destroy();
01526		SpawnBodyGibs(Velocity);
01527	}
01528	function PlayDying(name DamageType, vector HitLoc)
01529	{
01530		local vector X,Y,Z,HitVec,HitVec2D;
01531		local float dotp;
01532	
01533		// Handle special damage types here
01534		if ( DamageType == 'drowned' )
01535		{
01536			PlayDrownDeath(DamageType);
01537			return;
01538		}
01539		else if ( DamageType == 'decapitated' )
01540		{
01541			PlayHeadDeath(DamageType);
01542			return;
01543		}
01544		else if ( DamageType == 'gibbed')
01545		{
01546			PlayGibDeath(DamageType);
01547			return;
01548		}
01549		else if( DamageType == 'thrownweaponsever')
01550		{
01551			PlaySkewerDeath(DamageType);
01552			return;
01553		}
01554	
01555		GetAxes(Rotation,X,Y,Z);
01556		X.Z = 0;
01557		HitVec = Normal(HitLoc - Location);
01558		HitVec2D= HitVec;
01559		HitVec2D.Z = 0;
01560		dotp = HitVec2D dot X;
01561	
01562		//first check for head hit
01563		if ( HitLoc.Z - Location.Z > 0.5 * CollisionHeight && (dotp > 0) )
01564		{
01565			PlayHeadDeath(DamageType);
01566			return;
01567		}
01568		
01569		if (dotp > 0.71) //then hit in front
01570			PlayDeath(DamageType);
01571		else if (dotp < -0.71)
01572			PlayBackDeath(DamageType);
01573		else
01574		{
01575			dotp = HitVec dot Y;
01576			if (dotp > 0.0)
01577			{
01578				if (!bMirrored)
01579					PlayLeftDeath(DamageType);
01580				else
01581					PlayRightDeath(DamageType);
01582			}
01583			else
01584			{
01585				if (!bMirrored)
01586					PlayRightDeath(DamageType);
01587				else
01588					PlayLeftDeath(DamageType);
01589			}
01590		}
01591	}
01592	
01593	// Pain
01594	function PlayFrontHit	(optional float tweentime)	{}
01595	function PlayBackHit	(optional float tweentime)	{ PlayFrontHit(tweentime);	}
01596	function PlayLeftHit	(optional float tweentime)	{ PlayFrontHit(tweentime);	}
01597	function PlayRightHit	(optional float tweentime)	{ PlayFrontHit(tweentime);	}
01598	function PlayHeadHit	(optional float tweentime)	{ PlayFrontHit(tweentime);	}
01599	function PlayDrowning	(optional float tweentime)	{ PlayFrontHit(tweentime);	}
01600	function PlayTakeHit	(float tweentime, int damage, vector HitLoc, name damageType, vector Momentum, int BodyPart)
01601	{
01602		local vector X,Y,Z, HitVec, HitVec2D;
01603		local float dotp;
01604	
01605		GetAxes(Rotation,X,Y,Z);
01606		X.Z = 0;
01607		HitVec = Normal(HitLoc - Location);
01608		HitVec2D= HitVec;
01609		HitVec2D.Z = 0;
01610		dotp = HitVec2D dot X;
01611	
01612		if(damageType == 'Drowned')
01613		{
01614			PlayDrowning(tweentime);
01615			return;
01616		}
01617	
01618		//first check for head hit
01619		if ( HitLoc.Z - Location.Z > 0.5 * CollisionHeight )
01620		{
01621			if (dotp > 0)
01622			{
01623				PlayHeadHit(tweentime);
01624				return;
01625			}
01626		}
01627		
01628		if (dotp > 0.71) //then hit in front
01629			PlayFrontHit( tweentime);
01630		else if (dotp < -0.71) // then hit in back
01631			PlayBackHit(tweentime);
01632		else
01633		{
01634			dotp = HitVec dot Y;
01635			if (dotp > 0.0)
01636			{
01637				if (!bMirrored)
01638					PlayLeftHit(tweentime);
01639				else
01640					PlayRightHit(tweentime);
01641			}
01642			else
01643			{
01644				if (!bMirrored)
01645					PlayRightHit(tweentime);
01646				else
01647					PlayLeftHit(tweentime);
01648			}
01649		}
01650	}
01651	
01652	function PlayWeaponSwitch(Weapon NewWeapon);
01653	
01654	
01655	//=============================================================================
01656	// Sound functions
01657	//=============================================================================
01658	function PlayTakeHitSound(int Damage, name damageType, int Mult)
01659	{
01660		if ( Level.TimeSeconds - LastPainSound < 0.25 )
01661			return;
01662	
01663		if (HitSound1 == None)
01664			return;
01665		LastPainSound = Level.TimeSeconds;
01666		if (Damage < 10)
01667			PlaySound(HitSound1, SLOT_Pain, FMax(Mult * TransientSoundVolume, Mult * 2.0));
01668		else if (Damage < 25)
01669			PlaySound(HitSound2, SLOT_Pain, FMax(Mult * TransientSoundVolume, Mult * 2.0));
01670		else
01671			PlaySound(HitSound3, SLOT_Pain, FMax(Mult * TransientSoundVolume, Mult * 2.0));
01672	}
01673	
01674	function PlayDyingSound(name damageType)
01675	{
01676		local float rnd;
01677	
01678		if ( HeadRegion.Zone.bWaterZone )
01679		{
01680	/*		if ( FRand() < 0.5 )
01681				PlaySound(UWHit1, SLOT_Pain,,,,Frand()*0.2+0.9);
01682			else
01683				PlaySound(UWHit2, SLOT_Pain,,,,Frand()*0.2+0.9);
01684			return;*/
01685		}
01686	
01687		if (damageType == 'gibbed')
01688		{
01689			PlaySound(GibSound, SLOT_Talk);
01690		}
01691		else
01692		{
01693			rnd = FRand();
01694			if (rnd < 0.33)
01695				PlaySound(Die, SLOT_Talk);
01696			else if (rnd < 0.66)
01697				PlaySound(Die2, SLOT_Talk);
01698			else 
01699				PlaySound(Die3, SLOT_Talk);
01700		}
01701	}
01702	
01703	function PlayLandSound(EMatterType matter, float impactVel)
01704	{
01705		local sound snd;
01706	
01707		switch(matter)
01708		{
01709		case MATTER_FLESH:
01710			snd = LandSoundFlesh;
01711			break;
01712		case MATTER_WOOD:
01713			snd = LandSoundWood;
01714			break;
01715		case MATTER_STONE:
01716			snd = LandSoundStone;
01717			break;
01718		case MATTER_METAL:
01719			snd = LandSoundMetal;
01720			break;
01721		case MATTER_EARTH:
01722			snd = LandSoundEarth;
01723			break;
01724		case MATTER_BREAKABLEWOOD:
01725			snd = LandSoundBreakableWood;
01726			break;
01727		case MATTER_BREAKABLESTONE:
01728			snd = LandSoundBreakableStone;
01729			break;
01730		case MATTER_ICE:
01731			snd = LandSoundIce;
01732			break;
01733		case MATTER_SNOW:
01734			snd = LandSoundSnow;
01735			break;
01736		case MATTER_WATER:
01737			snd = LandSoundWater;
01738			break;
01739		case MATTER_MUD:
01740			snd = LandSoundMud;
01741			break;
01742		case MATTER_LAVA:
01743			snd = LandSoundLava;
01744			break;
01745		default:
01746			snd = None;
01747		}
01748	
01749		if(snd != None)
01750		{
01751			PlaySound(snd, SLOT_Interact, FClamp(4 * impactVel, 0.5, 2), false, 1000, 0.95 + (FRand() * 0.1));
01752		}
01753	}
01754	
01755	function Gasp();
01756	function StopFiring();
01757	
01758	
01759	//=============================================================================
01760	// Utility functions
01761	//=============================================================================
01762	
01763	function UpdateMovementSpeed()
01764	{
01765		if (Region.Zone.bWaterZone)
01766		{
01767			if (bHurrying || WaterSpeed==0)
01768				MovementSpeed = 1;
01769			else
01770				MovementSpeed = WalkingSpeed/WaterSpeed;
01771		}
01772		else if (Physics == PHYS_Flying)
01773		{
01774			if (bHurrying || AirSpeed==0)
01775				MovementSpeed = 1;
01776			else
01777				MovementSpeed = WalkingSpeed/AirSpeed;
01778		}
01779		else
01780		{
01781			if (bHurrying || GroundSpeed==0)
01782				MovementSpeed = 1;
01783			else
01784				MovementSpeed = WalkingSpeed/GroundSpeed;
01785		}
01786	}
01787	
01788	function AddVelocity( vector NewVelocity)
01789	{
01790		if (Physics == PHYS_Walking)
01791			SetPhysics(PHYS_Falling);
01792	//	if ( (Velocity.Z > 380) && (NewVelocity.Z > 0) )
01793	//		NewVelocity.Z *= 0.5;
01794		Velocity += NewVelocity;
01795	}
01796	
01797	function actor ActorTagged(name tag)
01798	{
01799		local actor A;
01800		foreach AllActors(class'actor', A, tag)
01801		{
01802			return A;
01803		}
01804	}
01805	
01806	function String GetHumanName()
01807	{
01808		if ( PlayerReplicationInfo != None )
01809			return PlayerReplicationInfo.PlayerName;
01810		return NameArticle$MenuName;
01811	}
01812	
01813	function ClientPutDown(Weapon Current, Weapon Next)
01814	{
01815	//	Current.ClientPutDown(Next);
01816	}
01817	
01818	function BoostStrength(int amount)
01819	{
01820		Strength += amount;
01821		if (Strength > MaxStrength)
01822			Strength = MaxStrength;
01823	}
01824	
01825	function bool CanBeStatued()
01826	{	// Pawn can be turned into a statue
01827		return true;
01828	}
01829	
01830	//------------------------------------------------------------
01831	//
01832	// AdjustAim()
01833	//
01834	// ScriptedPawn version does adjustment for non-controlled pawns. 
01835	// PlayerPawn version does the adjustment for player aiming help.
01836	// Only adjusts aiming at pawns
01837	// allows more error in Z direction (full as defined by AutoAim - only half that difference for XY)
01838	//------------------------------------------------------------
01839	function rotator AdjustAim(float projSpeed, vector projStart, int aimerror, bool bLeadTarget, bool bWarnTarget)
01840	{
01841		return ViewRotation;
01842	}
01843	
01844	function rotator AdjustToss(float projSpeed, vector projStart, int aimerror, bool bLeadTarget, bool bWarnTarget)
01845	{
01846		return ViewRotation;
01847	}
01848	
01849	function WarnTarget(Pawn shooter, float projSpeed, vector FireDir)
01850	{
01851		// AI controlled creatures may duck
01852		// if not falling, and projectile time is long enough
01853		// often pick opposite to current direction (relative to shooter axis)
01854	}
01855	
01856	function SetMovementPhysics()
01857	{
01858		//implemented in sub-class
01859	}
01860	
01861	function PreSetMovement()
01862	{
01863		if(JumpZ > 0)
01864			bCanJump = true;
01865		bCanWalk = GroundSpeed > 0;
01866		bCanSwim = false;
01867		bCanFly = false;
01868	//	MinHitWall = -0.6;
01869		MinHitWall = -0.835;	//RUNE
01870		if(Intelligence > BRAINS_Reptile)
01871			bCanOpenDoors = true;
01872		if(Intelligence == BRAINS_Human)
01873			bCanDoSpecial = true;
01874	}
01875	
01876	simulated function SetMesh()
01877	{
01878		mesh = default.mesh;
01879	}
01880	
01881	function HidePlayer()
01882	{
01883		SetCollision(false, false, false);
01884		TweenToWaiting(0.01);
01885		bHidden = true;
01886	}
01887	
01888	function damageAttitudeTo(pawn Other);
01889	function bool FollowOrders(name order, name tag)	{	return false;	}
01890	function FearThisSpot(Actor aSpot);
01891	
01892	function bool CheckWaterJump(out vector WallNormal)
01893	{
01894		local actor HitActor;
01895		local vector HitLocation, HitNormal, checkpoint, start, checkNorm, Extent;
01896	
01897		checkpoint = vector(Rotation);
01898		checkpoint.Z = 0.0;
01899		checkNorm = Normal(checkpoint);
01900		checkPoint = Location + CollisionRadius * checkNorm;
01901		Extent = CollisionRadius * vect(1,1,0);
01902		Extent.Z = CollisionHeight;
01903		HitActor = Trace(HitLocation, HitNormal, checkpoint, Location, true, Extent);
01904		if ( (HitActor != None) && (Pawn(HitActor) == None) )
01905		{
01906			WallNormal = -1 * HitNormal;
01907			start = Location;
01908			start.Z += 1.1 * MaxStepHeight;
01909			checkPoint = start + 2 * CollisionRadius * checkNorm;
01910			HitActor = Trace(HitLocation, HitNormal, checkpoint, start, true);
01911			if (HitActor == None)
01912				return true;
01913		}
01914	
01915		return false;
01916	}
01917	
01918	//------------------------------------------------------------
01919	//
01920	// NearWall
01921	//
01922	// Returns true if there is a nearby barrier at eyeheight and
01923	// changes focus to a suggested value
01924	//------------------------------------------------------------
01925	function bool NearWall(float walldist)
01926	{
01927		local actor HitActor;
01928		local vector HitLocation, HitNormal, ViewSpot, ViewDist, LookDir;
01929	
01930		LookDir = vector(Rotation);
01931		ViewSpot = Location + BaseEyeHeight * vect(0,0,1);
01932		ViewDist = LookDir * walldist; 
01933		HitActor = Trace(HitLocation, HitNormal, ViewSpot + ViewDist, ViewSpot, false);
01934		if ( HitActor == None )
01935			return false;
01936	
01937		ViewDist = Normal(HitNormal Cross vect(0,0,1)) * walldist;
01938		if (FRand() < 0.5)
01939			ViewDist *= -1;
01940	
01941		HitActor = Trace(HitLocation, HitNormal, ViewSpot + ViewDist, ViewSpot, false);
01942		if ( HitActor == None )
01943		{
01944			Focus = Location + ViewDist;
01945			return true;
01946		}
01947	
01948		ViewDist *= -1;
01949	
01950		HitActor = Trace(HitLocation, HitNormal, ViewSpot + ViewDist, ViewSpot, false);
01951		if ( HitActor == None )
01952		{
01953			Focus = Location + ViewDist;
01954			return true;
01955		}
01956	
01957		Focus = Location - LookDir * 300;
01958		return true;
01959	}
01960	
01961	
01962	//=============================================================================
01963	// Inventory related functions.
01964	//=============================================================================
01965	
01966	//------------------------------------------------------------
01967	//
01968	// WantsToPickup
01969	//
01970	// Returns whether the item is desired
01971	//------------------------------------------------------------
01972	function bool WantsToPickUp(Inventory item)
01973	{
01974		return false;
01975	}
01976	
01977	
01978	//------------------------------------------------------------
01979	//
01980	// CanPickup
01981	//
01982	// Let's pawn dictate what it can pick up
01983	//------------------------------------------------------------
01984	function bool CanPickup(Inventory item)
01985	{
01986		return false;
01987	}
01988	
01989	
01990	//------------------------------------------------------------
01991	//
01992	// AcquireInventory
01993	//
01994	// Called when inventory item is acquired
01995	//------------------------------------------------------------
01996	function AcquireInventory(Inventory item)
01997	{
01998		if (item.IsA('Weapon'))
01999		{
02000			DropWeapon();
02001			AttachActorToJoint(item, JointNamed(WeaponJoint));
02002			Weapon = Weapon(item);
02003			Weapon.GotoState('Active');
02004		}
02005		else if (item.IsA('Shield'))
02006		{
02007			DropShield();
02008			AttachActorToJoint(item, JointNamed(ShieldJoint));
02009			Shield = Shield(item);
02010			Shield.GotoState('Active');
02011		}
02012	}
02013	
02014	
02015	//------------------------------------------------------------
02016	//
02017	// DropWeapon
02018	//
02019	//------------------------------------------------------------
02020	function DropWeapon()
02021	{
02022		local vector X,Y,Z;
02023		local int joint;
02024		
02025		if(Weapon == None)
02026			return;
02027	
02028		if(Weapon.bPoweredUp)
02029			Weapon.PowerupEnd();
02030	
02031		joint = JointNamed(WeaponJoint);
02032		if (joint != 0)
02033		{
02034			DetachActorFromJoint(joint);
02035			
02036			GetAxes(Rotation, X, Y, Z);
02037			Weapon.DropFrom(GetJointPos(joint));
02038	
02039			if (Weapon != None)	// Invisible weapons get destroyed at DropFrom()
02040			{
02041				Weapon.SetPhysics(PHYS_Falling);
02042				Weapon.Velocity = Y * 100 + X * 75;
02043				Weapon.Velocity.Z = 50;
02044				Weapon.GotoState('Drop');
02045				Weapon.DisableSwipeTrail();
02046	
02047				DeleteInventory( Weapon );
02048			}
02049		}
02050	}	
02051	
02052	
02053	//------------------------------------------------------------
02054	//
02055	// DropShield
02056	//
02057	//------------------------------------------------------------
02058	function DropShield()
02059	{
02060		local vector X,Y,Z;
02061		local int joint;
02062		
02063		if(Shield == None)
02064			return;
02065		
02066		joint = JointNamed(ShieldJoint);
02067		if (joint != 0)
02068		{
02069			DetachActorFromJoint(joint);
02070			
02071			GetAxes(Rotation, X, Y, Z);
02072			Shield.DropFrom(GetJointPos(joint));
02073		
02074			Shield.SetPhysics(PHYS_Falling);
02075			Shield.Velocity = Y * 100 + X * 75;
02076			Shield.Velocity.Z = 50;
02077			Shield.GotoState('Drop');
02078	
02079			DeleteInventory( Shield );
02080		}
02081	}
02082	
02083	//=============================================================================
02084	//
02085	// ThrowWeapon
02086	//
02087	// RUNE:  Throw the current weapon
02088	//=============================================================================
02089	
02090	function ThrowWeapon()
02091	{
02092		local vector X,Y,Z;
02093		local float xMag, zMag;
02094		local int joint;
02095		local Weapon theWeapon;
02096		local vector extent;
02097		local vector weaponLoc;
02098		local vector HitLocation, HitNormal;
02099		
02100		if(Weapon == None)
02101		{
02102			return;
02103		}
02104		
02105		joint = JointNamed(WeaponJoint);
02106		DetachActorFromJoint(joint);
02107		
02108		if(self.IsA('PlayerPawn'))
02109			GetAxes(ViewRotation, X, Y, Z); // Players throw in the direction they are looking
02110		else
02111			GetAxes(Rotation, X, Y, Z); // Creatures throw in the direction they are facing
02112	
02113		// Check if weapon will fit in intended location (trace from center to weapon location)
02114		extent.X = Weapon.CollisionRadius;
02115		extent.Y = Weapon.CollisionRadius;
02116		extent.Z = Weapon.CollisionHeight;
02117		weaponLoc = GetJointPos(joint);
02118	
02119		if(Trace(HitLocation, HitNormal, weaponLoc, Location, true, Extent) != None)
02120		{ // Struck something along the way, spawn the weapon at the player location
02121			weaponLoc = Location;
02122		}
02123		
02124		Weapon.SetLocation(weaponLoc);
02125		theWeapon = Weapon;
02126		DeleteInventory( theWeapon );
02127		theWeapon.SetOwner(self); // Guarantee that the owner is set for the throwing weapon (not needed anymore)
02128	
02129		xMag = 7500 / theWeapon.Mass;
02130		if(xMag > 750)
02131			xmag = 750;
02132	
02133		zMag = 2000 / theWeapon.Mass;
02134		if(zMag > 200)
02135			zMag = 200;
02136	
02137		theWeapon.Velocity = X * xMag + Z * zMag;
02138		theWeapon.GotoState('Throw');
02139	}	
02140	
02141	
02142	// toss out the weapon currently held
02143	function TossWeapon()
02144	{
02145		local vector X,Y,Z;
02146		if ( Weapon == None )
02147			return;
02148		GetAxes(Rotation,X,Y,Z);
02149	//	Weapon.DropFrom(Location + 0.8 * CollisionRadius * X + - 0.5 * CollisionRadius * Y);
02150		DetachActorFromJoint(JointNamed(WeaponJoint));
02151		Weapon.Velocity = Y * 100 - X * 50;
02152		Weapon.DropFrom(Weapon.Location); 
02153	}	
02154	
02155	exec function bool SwitchToBestWeapon()
02156	{
02157		local float rating;
02158		local int usealt;
02159	
02160		if ( Inventory == None )
02161			return false;
02162	
02163		PendingWeapon = Inventory.RecommendWeapon(rating, usealt);
02164		if ( PendingWeapon == Weapon )
02165			PendingWeapon = None;
02166	
02167		if ( PendingWeapon == None )
02168			return false;
02169	
02170		if ( Weapon == None )
02171			ChangedWeapon();
02172	
02173		return (usealt > 0);
02174	}
02175	
02176	function float AdjustDesireFor(Inventory Inv)
02177	{
02178		return 0;
02179	}
02180	
02181	// The player/bot wants to select next item
02182	exec function NextItem()
02183	{
02184		local Inventory Inv;
02185	
02186		if (SelectedItem==None) {
02187			SelectedItem = Inventory.SelectNext();
02188			Return;
02189		}
02190		if (SelectedItem.Inventory!=None)
02191			SelectedItem = SelectedItem.Inventory.SelectNext(); 
02192		else
02193			SelectedItem = Inventory.SelectNext();
02194	
02195		if ( SelectedItem == None )
02196			SelectedItem = Inventory.SelectNext();
02197	}
02198	
02199	// FindInventoryType()
02200	// returns the inventory item of the requested class
02201	// if it exists in this pawn's inventory 
02202	
02203	function Inventory FindInventoryType( class DesiredClass )
02204	{
02205		local Inventory Inv;
02206	
02207		for( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )   
02208			if ( Inv.class == DesiredClass )
02209				return Inv;
02210		return None;
02211	} 
02212	
02213	// Add Item to this pawn's inventory. 
02214	// Returns true if successfully added, false if not.
02215	function bool AddInventory( inventory NewItem )
02216	{
02217		// Skip if already in the inventory.
02218		local inventory Inv;
02219		
02220		// The item should not have been destroyed if we get here.
02221		if (NewItem ==None )
02222			log("tried to add none inventory to "$self);
02223	
02224		for( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )
02225			if( Inv == NewItem )
02226				return false;
02227	
02228	
02229		// Add to front of inventory chain.
02230		NewItem.SetOwner(Self);
02231		NewItem.Inventory = Inventory;
02232		Inventory = NewItem;
02233		return true;
02234	}
02235	
02236	// Remove Item from this pawn's inventory, if it exists.
02237	// Returns true if it existed and was deleted, false if it did not exist.
02238	function bool DeleteInventory( inventory Item )
02239	{
02240		// If this item is in our inventory chain, unlink it.
02241		local actor Link;
02242		if ( Item == Weapon )
02243			Weapon = None;
02244		if ( Item == Shield )
02245			Shield = None;
02246		if ( Item == SelectedItem )
02247			SelectedItem = None;
02248		for( Link = Self; Link!=None; Link=Link.Inventory )
02249		{
02250			if( Link.Inventory == Item )
02251			{
02252				Link.Inventory = Item.Inventory;
02253				Item.Inventory = None;
02254				break;
02255			}
02256		}
02257		Item.SetOwner(None);
02258	}
02259	
02260	// Just changed to pendingWeapon
02261	function ChangedWeapon()
02262	{
02263		local Weapon OldWeapon;
02264	
02265		OldWeapon = Weapon;
02266	
02267		if (Weapon == PendingWeapon)
02268		{
02269			if ( Weapon == None )
02270				SwitchToBestWeapon();
02271			if ( Weapon != None )
02272				Weapon.SetDefaultDisplayProperties();
02273			Inventory.ChangedWeapon(); // tell inventory that weapon changed (in case any effect was being applied)
02274			PendingWeapon = None;
02275			return;
02276		}
02277		if ( PendingWeapon == None )
02278			PendingWeapon = Weapon;
02279		PlayWeaponSwitch(PendingWeapon);
02280		if ( Weapon != None )
02281			Weapon.SetDefaultDisplayProperties();
02282		Weapon = PendingWeapon;
02283		Inventory.ChangedWeapon(); // tell inventory that weapon changed (in case any effect was being applied)
02284	
02285		PendingWeapon = None;
02286	}
02287	
02288	function PowerUpWeapon()
02289	{
02290		if(Weapon == None)
02291			return;
02292	
02293		if (RunePower >= Weapon.RunePowerRequired && !Weapon.bPoweredUp)
02294		{
02295			RunePower -= Weapon.RunePowerRequired;
02296			Weapon.PowerUp();
02297		}
02298	}
02299	
02300	
02301	
02302	//=============================================================================
02303	// Localized Damage Support functions
02304	//=============================================================================
02305	
02306	function int BodyPartForJoint(int joint)			{ return BODYPART_BODY; }
02307	function int BodyPartForPolyGroup(int polygroup)	{ return BODYPART_BODY; }
02308	function bool BodyPartSeverable(int BodyPart)		{ return false; }
02309	function bool BodyPartCritical(int BodyPart)		{ return false; }
02310	function LimbSevered(int bodypart, vector Momentum) { }
02311	
02312	//------------------------------------------------------------
02313	//
02314	// RestoreBodyPart
02315	//
02316	// Restore a bodypart to full health, visibility, collision
02317	//------------------------------------------------------------
02318	function RestoreBodyPart(int BodyPart)
02319	{
02320		BodyPartHealth[BodyPart] = Default.BodyPartHealth[BodyPart];
02321		BodyPartCollision(BodyPart, true);
02322		BodyPartVisibility(BodyPart, true);
02323	}
02324	
02325	//------------------------------------------------------------
02326	//
02327	// MatterForJoint
02328	//
02329	// Returns what kind of material joint is associated with
02330	//------------------------------------------------------------
02331	function EMatterType MatterForJoint(int joint)
02332	{
02333		return MATTER_FLESH;
02334	}
02335	
02336	//------------------------------------------------------------
02337	//
02338	// BodyPartMissing
02339	//
02340	//------------------------------------------------------------
02341	function bool BodyPartMissing(int BodyPart)
02342	{
02343		return BodyPartHealth[BodyPart] <= 0;
02344	}
02345	
02346	//------------------------------------------------------------
02347	//
02348	// BodyPartCollision
02349	//
02350	// Turn collision on or off on a body part
02351	//------------------------------------------------------------
02352	function BodyPartCollision(int BodyPart, bool on)
02353	{
02354		local int i,num;
02355	
02356		num = NumJoints();
02357		for (i=0; i<num; i++)
02358		{
02359			if (BodyPartForJoint(i) == BodyPart)
02360			{
02361				if (on)
02362					JointFlags[i] = JointFlags[i] | JOINT_FLAG_COLLISION;
02363				else
02364					JointFlags[i] = JointFlags[i] & ~JOINT_FLAG_COLLISION;
02365			}
02366		}
02367	}
02368	
02369	//------------------------------------------------------------
02370	//
02371	// BodyPartVisibility
02372	//
02373	// Turn visibility on or off on a body part
02374	//------------------------------------------------------------
02375	function BodyPartVisibility(int BodyPart, bool on)
02376	{
02377		local int i,num;
02378	
02379		for (i=0; i<16; i++)
02380		{
02381			if (BodyPartForPolygroup(i) == BodyPart)
02382			{
02383				if (on)
02384					SkelGroupFlags[i] = SkelGroupFlags[i] & ~POLYFLAG_INVISIBLE;
02385				else
02386					SkelGroupFlags[i] = SkelGroupFlags[i] | POLYFLAG_INVISIBLE;
02387			}
02388		}
02389	}
02390	
02391	
02392	//------------------------------------------------------------
02393	//
02394	// LimbPassThrough
02395	//
02396	// Determines what damage is passed through to body
02397	//------------------------------------------------------------
02398	function int LimbPassThrough(int BodyPart, out int Blunt, out int Sever)
02399	{
02400		return Blunt+Sever;
02401	}
02402	
02403	//------------------------------------------------------------
02404	//
02405	// ApplyPainToJoint
02406	//
02407	//------------------------------------------------------------
02408	function ApplyPainToJoint(int joint, vector Momentum)
02409	{
02410	}
02411	
02412	//------------------------------------------------------------
02413	//
02414	// JointDamaged
02415	//
02416	//------------------------------------------------------------
02417	function bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
02418	{
02419		ApplyPainToJoint(joint, Momentum);
02420	
02421		// Allow mutators to change stuff around
02422		if ( Level.Game.DamageMutator != None )
02423			Level.Game.DamageMutator.MutatorJointDamaged( Damage, Self, EventInstigator, HitLoc, Momentum, DamageType, joint);
02424	
02425		return Super.JointDamaged(Damage, EventInstigator, HitLoc, Momentum, DamageType, joint);
02426	}
02427	
02428	//------------------------------------------------------------
02429	//
02430	// CanGotoPainState
02431	//
02432	// True if the actor is allowed to enter it's painstate
02433	// This is overriden in some substates
02434	//------------------------------------------------------------
02435	
02436	function bool CanGotoPainState()
02437	{
02438		return(true);
02439	}
02440	
02441	//================================================
02442	//
02443	// SeveredLimbClass
02444	//
02445	// Override in subclasses
02446	//================================================
02447	function class<Actor> SeveredLimbClass(int BodyPart)
02448	{
02449		return None;
02450	}
02451	
02452	//------------------------------------------------------------
02453	//
02454	// DamageBodyPart
02455	//
02456	//------------------------------------------------------------
02457	function bool DamageBodyPart(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, name DamageType, int bodypart)
02458	{
02459		local int PassThrough;
02460		local int SeverDamage;
02461		local int BluntDamage;
02462		local bool bAlreadyDead;
02463		local int AppliedDamage;
02464		local Debris Gib;
02465		local float scale;
02466		local int i, NumChunks;
02467	
02468		local vector AdjMomentum;
02469	
02470		if(!class'GameInfo'.Default.bVeryLowGore)
02471		{
02472			if (CurrentSkin != 0)
02473				SpecialPainSkin(BodyPart);
02474			else
02475				PainSkin(BodyPart);
02476		}
02477	
02478		GetDamageValues(Damage, DamageType, BluntDamage, SeverDamage);
02479		Level.Game.ReduceDamage(BluntDamage, SeverDamage, DamageType, self, EventInstigator);
02480		PassThrough = LimbPassThrough(BodyPart, BluntDamage, SeverDamage);
02481	
02482		// Give instigator strength boost if deserving
02483		if(EventInstigator!=None && EventInstigator.IsA('PlayerPawn') && Health>0 &&
02484			(DamageType=='blunt' || DamageType=='sever' || DamageType=='bluntsever') &&
02485			EventInstigator.Weapon!=None && !EventInstigator.Weapon.bPoweredUp &&
02486			(PassThrough>0) )
02487		{ // Boost the player's strength/bloodlust for successful conventional attacks
02488			EventInstigator.BoostStrength(0.2 * Damage);
02489		}
02490	
02491		if (BodyPart != BODYPART_BODY)
02492		{
02493			if (BodyPartSeverable(BodyPart) && (BodyPartHealth[BodyPart] > 0))
02494			{
02495				BodyPartHealth[BodyPart] -= SeverDamage;
02496		
02497				if(BodyPartHealth[BodyPart] <= 0)
02498				{	// Body Part was killed
02499					if (BodyPartCritical(BodyPart))
02500					{
02501						PassThrough = Max(Health, Damage);
02502						DamageType = 'decapitated';
02503					}
02504	
02505					// Sever the limb
02506					if(!class'GameInfo'.Default.bLowGore)
02507					{
02508						BodyPartVisibility(BodyPart, false);
02509						BodyPartCollision(BodyPart, false);
02510						LimbSevered(BodyPart, Momentum);
02511					}
02512				}
02513			}
02514		}
02515	
02516		if (DamageType=='sever' || DamageType=='bluntsever')
02517		{	// spawn chunks
02518			NumChunks = (Damage / 15) + 1;
02519			NumChunks = NumChunks * Level.Game.DebrisPercentage;
02520			for(i = 0; i < NumChunks; i++)
02521			{
02522				Gib = spawn(GibClass,,, HitLocation + VRand() * 2,);
02523				if (Gib != None)
02524				{
02525					Gib.SetSize(RandRange(0.1, 0.4));
02526					Gib.SetMomentum((-0.08 * Momentum));
02527				}
02528			}
02529		}
02530		else if (DamageType == 'crushed')
02531		{	// Force the gib when crushed
02532			PassThrough = Default.Health*3;
02533			bGibbable = true;
02534		}
02535	
02536		// Apply damage to body
02537		if (PassThrough != 0)
02538		{
02539			bAlreadyDead = (Health <= 0);
02540	
02541	//		AppliedDamage = Level.Game.ReduceDamage(PassThrough, DamageType, self, EventInstigator);
02542			AppliedDamage = PassThrough;
02543	
02544			Health -= AppliedDamage;
02545	
02546			if (Health > 0)
02547			{
02548				// Apply momentum
02549				// NOTE:  This code is duplicated in Shield.Active and Shield.Idle states
02550				AdjMomentum = momentum / Mass;
02551				if(Mass < VSize(AdjMomentum) && Velocity.Z <= 0)
02552				{			
02553					AdjMomentum.Z += (VSize(AdjMomentum) - Mass) * 0.5;
02554				}
02555				AddVelocity(AdjMomentum);
02556	//			if (Velocity.Z == 0)
02557	//				AddVelocity(momentum / Mass);
02558	
02559				if(CanGotoPainState())
02560				{ // Only goto the painstate if the pawn allows it 
02561					PlayTakeHitSound(AppliedDamage, DamageType, 1);
02562	
02563					if(PassThrough > 5) // DAMAGE_EPSILON = 5
02564					{ // Only go to the painstate if the damage is over a given level
02565						if (GetStateName() != 'Pain' && GetStateName() != 'pain')
02566						{
02567							NextStateAfterPain = GetStateName();
02568	
02569							// Play pain anim
02570							PlayTakeHit(0.1, AppliedDamage, HitLocation, DamageType, Momentum, BodyPart);
02571							GotoState('Pain');
02572						}
02573						return(false);
02574					}
02575				}
02576			}
02577			else if (bAlreadyDead)
02578			{	// Twitch corpse or Gib
02579				if(Health < -Default.Health && bGibbable && !bHidden)
02580				{ // Gib if beaten down far enough
02581					SpawnBodyGibs(Momentum);
02582					PlayDyingSound('gibbed');
02583					if (bIsPlayer)
02584						bHidden=true;
02585					else
02586						Destroy();
02587				}
02588			}
02589			else
02590			{ // Kill the creature
02591				AddVelocity(momentum * 2 / Mass);
02592				if(Health < -Default.Health && bGibbable)
02593				{ // Gib if beaten down far enough
02594					Died(EventInstigator, 'gibbed', HitLocation);
02595	//				if (bIsPlayer)	// moved to died
02596	//					bHidden=true;
02597	//				else
02598	//					Destroy();
02599				}
02600				else
02601				{
02602					// Apply momentum
02603					Died(EventInstigator, DamageType, HitLocation);
02604				}
02605			}
02606			MakeNoise(1.0);
02607		}
02608	
02609		return(false);
02610	}
02611	
02612	
02613	//------------------------------------------------------------
02614	//
02615	// SpawnCarcass
02616	// 
02617	//------------------------------------------------------------
02618	function Carcass SpawnCarcass()
02619	{
02620		local carcass carc;
02621	
02622		carc = Spawn(CarcassType,,,Location,Rotation);
02623		if (carc != None)
02624		{
02625			carc.Initfor(self);
02626		}
02627	
02628		return carc;
02629	}
02630	
02631	
02632	//------------------------------------------------------------
02633	//
02634	// SpawnBodyGibs
02635	// 
02636	// Subclass this to spawn specific gibs for a given creature
02637	//------------------------------------------------------------
02638	
02639	function SpawnBodyGibs(vector momentum)
02640	{
02641		local int i, NumSourceGroups, numgibs;
02642		local Debris Gib;
02643		local vector loc;
02644		local float scale;
02645		local class<actor> partclass;
02646		local actor part;
02647	
02648		if (class'GameInfo'.Default.bLowGore )
02649			return;
02650	
02651		for (NumSourceGroups=1; NumSourceGroups<16; NumSourceGroups++)
02652		{
02653			if (SkelGroupSkins[NumSourceGroups] == None)
02654				break;
02655		}
02656	
02657		numgibs = GibCount;
02658		if (Level.Game != None)	//fixme: should be class'GameInfo'.default.DebrisPercentage
02659			numgibs = numgibs*Level.Game.DebrisPercentage;
02660	
02661		// Spawn some real body parts
02662		for (i=0; i<NUM_BODYPARTS; i++)
02663		{
02664			if (BodyPartMissing(i))
02665				continue;
02666	
02667			partclass = SeveredLimbClass(i);
02668			if (partclass != None)
02669			{
02670				numgibs--;
02671				BodyPartHealth[i] = 0;
02672	
02673				loc = VRand();
02674				loc.X *= CollisionRadius;
02675				loc.Y *= CollisionRadius;
02676				loc.Z *= CollisionHeight;
02677				loc += Location;
02678				part = Spawn(partclass, self,, loc, Rotation);
02679				if(part != None)
02680				{
02681					if (Momentum != vect(0,0,0))
02682						Velocity = (Normal(Momentum)*2 + VRand() + vect(0,0,1)) * RandRange(50,300);
02683					else
02684						Velocity = (VRand()*2+vect(0,0,2)) * RandRange(50,400);
02685					if (part.IsA('Weapon'))
02686						part.GotoState('Drop');
02687				}
02688			}
02689		}
02690	
02691		if (GibClass != None)
02692		{
02693			// Find appropriate size of chunks
02694			scale = (CollisionRadius*CollisionRadius*CollisionHeight) / (numgibs*600);
02695			scale = 0.8 * (scale ** 0.3333333);
02696	
02697			for (i = 0; i < numgibs; i++)
02698			{
02699				loc = VRand();
02700				loc.X *= CollisionRadius;
02701				loc.Y *= CollisionRadius;
02702				loc.Z *= CollisionHeight;
02703				loc += Location;
02704	
02705				Gib = spawn(GibClass,,, loc,);
02706				if (Gib != None)
02707				{
02708					Gib.SetSize(scale);
02709					Gib.SetMomentum(Momentum);
02710					if (FRand()<0.3)
02711						Gib.SetTexture(SkelGroupSkins[i%NumSourceGroups]);
02712				}
02713			}
02714		}
02715	}
02716	
02717	
02718	//------------------------------------------------------------
02719	//
02720	// MakeTwitchable
02721	//
02722	// TODO: Move this logic to carcass
02723	//------------------------------------------------------------
02724	function MakeTwitchable()
02725	{
02726	/*	local int j;
02727	
02728		// Turn all collision joints accelerative
02729		for (j=0; j<NumJoints(); j++)
02730		{
02731			if ((JointFlags[j] & JOINT_FLAG_COLLISION)==0)
02732				continue;
02733	
02734			JointFlags[j] = JointFlags[j] | JOINT_FLAG_ACCELERATIVE;
02735	//		SetJointRotThreshold(j, 16000);
02736	//		SetJointDampFactor(j, 0.025);
02737	//		SetAccelMagnitude(j, 8000);
02738		}
02739	*/
02740	}
02741	
02742	
02743	//------------------------------------------------------------
02744	//
02745	// Died
02746	//
02747	// Pawn has run out of health, kill him properly
02748	//------------------------------------------------------------
02749	function Died(pawn Killer, name damageType, vector HitLocation)
02750	{
02751		local actor A;
02752	
02753		if ( bDeleteMe ) return; //already destroyed
02754		Health = Min(0, Health);
02755		Strength = 0; // Remove any bloodlust that has accumulated
02756	
02757		if(IsA('PlayerPawn') && PlayerPawn(self).bBloodlust)
02758		{ // Player is bloodlusting and was killed by the world, or suicided, remove bloodlust
02759			Strength = 1;
02760			PlayerPawn(self).StrengthDecay(1); // Force bloodlust off
02761		}
02762		
02763		if (Killer != None)
02764			Killer.Killed(Killer, self, damageType);
02765		Level.Game.Killed(Killer, self, damageType);
02766	
02767		// RUNE:  Guarantee that the powerup turns off when a player dies
02768		if(Weapon != None && Weapon.bPoweredUp)
02769			Weapon.PowerupEnd();
02770	
02771		if (Weapon!=None && Weapon.Class!=Level.Game.DefaultWeapon && Level.Game.AllowWeaponDrop())
02772			DropWeapon();
02773		if (Shield!=None && Shield.Class!=Level.Game.DefaultShield && Level.Game.AllowShieldDrop())
02774			DropShield();
02775		Level.Game.DiscardInventory(self);	// Delete the rest of the inventory
02776	
02777		// No longer make this a player look target
02778		bLookFocusPlayer = false;
02779		
02780		// Trigger any events
02781		if( Event != '' )
02782			foreach AllActors( class 'Actor', A, Event )
02783				A.Trigger( Self, Killer );
02784	
02785		// Play death animation for this type of death (head hit, gut hit, etc.)
02786		PlayDying(DamageType, HitLocation);
02787		PlayDyingSound(damageType);
02788	
02789		if (!bIsPlayer)
02790			bAlignToFloor = true;
02791	
02792		MakeTwitchable();
02793	
02794		if ( RemoteRole == ROLE_AutonomousProxy )
02795			ClientDying(DamageType, HitLocation);
02796	
02797		if(AnimProxy != None)
02798			AnimProxy.GotoState('Dying'); // RUNE:  Make sure the animproxy is in death state as well
02799		GotoState('Dying');
02800	}
02801	
02802	
02803	//------------------------------------------------------------
02804	//
02805	// WeaponActivate
02806	//
02807	//------------------------------------------------------------
02808	function WeaponActivate()
02809	{
02810		if(Weapon != None)
02811		{
02812			Weapon.StartAttack();
02813		}
02814	}
02815	
02816	//------------------------------------------------------------
02817	//
02818	// WeaponDeactivate
02819	//
02820	//------------------------------------------------------------
02821	function WeaponDeactivate()
02822	{
02823		if(Weapon != None)
02824		{
02825			Weapon.FinishAttack();
02826		}
02827	}
02828	
02829	//=============================================================================
02830	//
02831	// SwipeEffectStart
02832	//
02833	// Swipe Effect Notify
02834	//=============================================================================
02835	
02836	function SwipeEffectStart()
02837	{
02838		if(Weapon != None)
02839		{
02840			Weapon.EnableSwipeTrail();
02841		}
02842	}
02843	
02844	//=============================================================================
02845	//
02846	// SwipeEffectEnd
02847	//
02848	// Swipe Effect Notify
02849	//=============================================================================
02850	
02851	function SwipeEffectEnd()
02852	{
02853		if(Weapon != None)
02854		{
02855			Weapon.DisableSwipeTrail();
02856		}
02857	}
02858	
02859	
02860	//------------------------------------------------------------
02861	//
02862	// StopAttack
02863	//
02864	//------------------------------------------------------------
02865	function StopAttack()
02866	{
02867		WeaponDeactivate();
02868	}
02869	
02870	//------------------------------------------------------------
02871	//
02872	// ClearSwipeArray
02873	//
02874	//------------------------------------------------------------
02875	
02876	function ClearSwipeArray()
02877	{
02878		if(Weapon != None)
02879		{
02880			Weapon.ClearSwipeArray();
02881			Weapon.PlaySwipeSound();
02882		}
02883	}
02884	
02885	//=========================================================================
02886	//
02887	// DoThrow
02888	// 
02889	// Throw weapon notify
02890	//=========================================================================
02891		
02892	function DoThrow()
02893	{
02894		if(Weapon != None)
02895			ThrowWeapon();
02896	}
02897	
02898	//------------------------------------------------------------
02899	//
02900	// ActivateShield
02901	//
02902	// Changes the state of current shield (in case needed later)
02903	//------------------------------------------------------------
02904	function ActivateShield(bool bOn)
02905	{
02906		if (Shield == None)
02907			return;
02908	
02909		if (bOn)
02910		{
02911			Shield.GotoState('Active');
02912		}
02913		else
02914		{
02915			Shield.GotoState('Idle');
02916		}
02917	}
02918	
02919	
02920	//------------------------------------------------------------
02921	//
02922	// AllowWeaponToHitActor
02923	//
02924	// Event to notify pawn when weapon hits something
02925	//------------------------------------------------------------
02926	function bool AllowWeaponToHitActor(Weapon W, Actor A)
02927	{
02928		return true;
02929	}
02930	
02931	
02932	//------------------------------------------------------------
02933	//
02934	// CanStabActor
02935	//
02936	// If the actor can be stabbed by a weapon
02937	//------------------------------------------------------------
02938	
02939	function bool CanStabActor()
02940	{
02941		if(StabJoint == '')
02942			return(false);
02943	
02944		if(ActorAttachedTo(JointNamed(StabJoint)) != None)
02945			return(false);
02946	
02947		return(true);
02948	}
02949	
02950	//------------------------------------------------------------
02951	//
02952	// CheckDefending
02953	//
02954	// Checks if the Pawn is defending 
02955	//------------------------------------------------------------
02956	
02957	function bool CheckDefending()
02958	{
02959		if(Shield != None)
02960		{ // Creature has a shield
02961			if(Shield.GetStateName() == 'Active')
02962			{ // The creature is defending
02963				return(true);
02964			}
02965		}
02966	
02967		return(false);
02968	}
02969	
02970	//------------------------------------------------------------
02971	//
02972	// PawnDamageModifier
02973	//
02974	// Returns the modification of the damage amount 
02975	// Used to increase damage for special attacks, or reduce damage
02976	// for simple attack types
02977	//------------------------------------------------------------
02978	
02979	function float PawnDamageModifier(Weapon w)
02980	{
02981		return(1.0);
02982	}
02983	
02984	//=============================================================================
02985	// Dynamic joint turning (head, jaw)
02986	//=============================================================================
02987	
02988	//------------------------------------------------------------
02989	//
02990	// AngleTo
02991	//
02992	// Returns absolute value of yaw angle to a location
02993	//------------------------------------------------------------
02994	function int AngleTo(vector pos)
02995	{
02996		local int YawErr;
02997		local rotator targetangle;
02998	
02999		targetangle = rotator(pos - location);
03000		YawErr = targetangle.Yaw - Rotation.Yaw;
03001		
03002		// Fix angles (0..180,0..-180)
03003		while (YawErr > 32768)
03004			YawErr -= 65535;
03005		while (YawErr < -32768)
03006			YawErr += 65535;
03007	
03008		return( Abs(YawErr) );
03009	}
03010	
03011	
03012	//------------------------------------------------------------
03013	//
03014	// NeedToTurn
03015	//
03016	// Returns whether I need to turn to see a location
03017	//------------------------------------------------------------
03018	function bool NeedToTurn(vector targ)
03019	{
03020		local int MaxYaw;
03021	
03022		MaxYaw = 1000;	// Tolerance for looking
03023		if (bRotateHead)
03024			MaxYaw += MaxHeadAngle.Yaw;
03025		if (bRotateTorso)
03026			MaxYaw += MaxBodyAngle.Yaw;
03027	
03028		return (AngleTo(targ) > MaxYaw);
03029	}
03030	
03031	
03032	//------------------------------------------------------------
03033	//
03034	// Tick
03035	//
03036	//------------------------------------------------------------
03037	simulated function Tick(float DeltaTime)
03038	{
03039		SkeletonLook(DeltaTime);
03040	//	Look(DeltaTime);
03041		Jaw (DeltaTime);
03042	}
03043	
03044	//------------------------------------------------------------
03045	//
03046	// OpenMouth
03047	//
03048	// Changes pawn's jaw openness if capable
03049	//  amount[0..1] 0 is completely closed, 1 is completely open
03050	//  rate[0..1]   0 is not moving, 1 is move at max rate
03051	//------------------------------------------------------------
03052	function OpenMouth(float amount, float rate)
03053	{
03054		DesiredMouthRot = MaxMouthRot * amount;
03055		MouthRotRate    = MaxMouthRotRate * rate;
03056	}
03057	
03058	
03059	//------------------------------------------------------------
03060	//
03061	// Jaw
03062	//
03063	// Takes care of moving the jaw smoothly
03064	//------------------------------------------------------------
03065	simulated function Jaw(float DeltaSeconds)
03066	{
03067		local rotator r;
03068	
03069		if (MaxMouthRotRate > 0)
03070		{
03071			if (MouthRot < DesiredMouthRot)
03072			{
03073				MouthRot += MouthRotRate * DeltaSeconds;
03074				if (MouthRot > DesiredMouthRot)
03075					MouthRot = DesiredMouthRot;
03076			}
03077			else if (MouthRot > DesiredMouthRot)
03078			{
03079				MouthRot -= MouthRotRate * DeltaSeconds;
03080				if (MouthRot < DesiredMouthRot)
03081					MouthRot = DesiredMouthRot;
03082			}
03083			r.Yaw = 0;
03084			r.Roll = 0;
03085			r.Pitch = MouthRot;
03086			SetJointRot(JointNamed('jaw'), r);
03087		}
03088	}
03089	
03090	
03091	//------------------------------------------------------------
03092	//
03093	// LookAt
03094	//
03095	// Look at an actor if not looking at a location
03096	//------------------------------------------------------------
03097	function LookAt(actor A, optional bool force)
03098	{
03099		if (bCanLook)
03100		{
03101			if (force || LookSpot == vect(0,0,0))
03102				LookTarget = A;
03103		}
03104	}
03105	
03106	//------------------------------------------------------------
03107	//
03108	// LookToward
03109	//
03110	// Set a spot to be looked at when not looking at an actor
03111	//------------------------------------------------------------
03112	function LookToward(vector pos, optional bool force)
03113	{
03114		if (bCanLook)
03115		{
03116			if (force)
03117				LookTarget = None;
03118			LookSpot = pos;
03119		}
03120	}
03121	
03122	//------------------------------------------------------------
03123	//
03124	// StopLookingToward
03125	//
03126	//------------------------------------------------------------
03127	function StopLookingToward()
03128	{
03129		lookspot = vect(0,0,0);
03130	}
03131	
03132	function CalcLookAngle()
03133	{
03134	}
03135	
03136	
03137	native(670) final function SkeletonLook(float DeltaTime);
03138	/*
03139	//------------------------------------------------------------
03140	//
03141	// Look
03142	//
03143	// Make pawn look around
03144	//------------------------------------------------------------
03145	simulated function Look(float DeltaTime)
03146	{
03147		local int head,body;
03148		local float headdeg,bodydeg,rotvel;
03149		local rotator headangle, bodyangle;
03150		local rotator ragnarRot;
03151		local float headPitchUp;
03152		local int joint;
03153		
03154		if (!bCanLook)
03155			return;
03156	
03157		if(Health <= 0)
03158			return;
03159	
03160		ragnarRot = Rotation;
03161		ragnarRot.Pitch = 0;
03162		
03163		if (bOverrideLookTarget)
03164		{
03165			// Use existing targetangle
03166		}
03167		else if (LookTarget != None)
03168		{	// Look at LookTarget
03169			targetangle = rotator(LookTarget.Location - Location);
03170			targetangle -= ragnarRot;
03171		}
03172		else if (LookSpot.X!=0 || LookSpot.Y!=0 || LookSpot.Z!=0)
03173		{	// Look at LookSpot
03174			targetangle = rotator(LookSpot - Location);
03175			targetangle -= ragnarRot;
03176		}
03177		else
03178		{	// Look straight ahead
03179			targetangle = rot(0,0,0);
03180		}
03181	
03182		// Fix angles (0..180,0..-180)
03183		while (targetangle.Yaw > 32768)
03184			targetangle.Yaw = targetangle.Yaw - 65535;
03185		while (targetangle.Yaw < -32768)
03186			targetangle.Yaw = targetangle.Yaw + 65535;
03187		while (targetangle.Pitch > 32768)
03188			targetangle.Pitch = targetangle.Pitch - 65535;
03189		while (targetangle.Pitch < -32768)
03190			targetangle.Pitch = targetangle.Pitch + 65535;
03191	
03192		rotvel = LookDegPerSec * 65535.0 / 360.0;
03193			
03194		// If target is in dead zone, return to looking forward
03195		if (cos(targetangle.Yaw*2.0*Pi/65535.0) < PeripheralVision)
03196		{
03197			targetangle = rot(0,0,0);
03198			rotvel *= 0.5;				// slower rate when returning to straight
03199		}
03200	
03201		// Yaw towards target angle
03202		if (targetangle.Yaw < LookAngle.Yaw)
03203		{	// Turning left
03204			LookAngle.Yaw -= rotvel * DeltaTime;
03205			if (LookAngle.Yaw < targetangle.Yaw)	// Disallow overshoot
03206				LookAngle.Yaw = targetangle.Yaw;
03207		}
03208		else
03209		{	// Turning right
03210			LookAngle.Yaw += rotvel * DeltaTime;
03211			if (LookAngle.Yaw > targetangle.Yaw)	// Disallow overshoot
03212				LookAngle.Yaw = targetangle.Yaw;
03213		}
03214	
03215		// Pitch towards target angle
03216		rotvel = 0.5 * LookDegPerSec * 65535.0 / 360.0;
03217		if (targetangle.Pitch < LookAngle.Pitch)
03218		{	// Pitching Up
03219			LookAngle.Pitch -= rotvel * DeltaTime;
03220			if (LookAngle.Pitch < targetangle.Pitch)
03221				LookAngle.Pitch = targetangle.Pitch;
03222		}
03223		else
03224		{	// Pitching Down
03225			LookAngle.Pitch += rotvel * DeltaTime;
03226			if (LookAngle.Pitch > targetangle.Pitch)
03227				LookAngle.Pitch = targetangle.Pitch;
03228		}
03229	
03230		if(bHeadLookUpDouble)
03231		{
03232			headPitchUp = MaxHeadAngle.Pitch * 2;
03233		}
03234		else
03235		{
03236			headPitchUp = MaxHeadAngle.Pitch;
03237		}
03238	
03239		// Now translate LookAngle.Yaw into head and body angles
03240		if (bRotateHead)
03241		{
03242			headangle = LookAngle;
03243	
03244	
03245			// Overflow any extra angle beyond head maximums into body
03246			if (headangle.Yaw > MaxHeadAngle.Yaw)
03247			{
03248				bodyangle.Yaw = headangle.Yaw - MaxHeadAngle.Yaw;
03249				headangle.Yaw = MaxHeadAngle.Yaw;
03250			}
03251			else if (headangle.Yaw < -MaxHeadAngle.Yaw)
03252			{
03253				bodyangle.Yaw = headangle.Yaw + MaxHeadAngle.Yaw;
03254				headangle.Yaw = -MaxHeadAngle.Yaw;
03255			}
03256	
03257			if (headangle.Pitch > headPitchUp)
03258			{
03259				bodyangle.Pitch = headangle.Pitch - headPitchUp;
03260				headangle.Pitch = headPitchUp;
03261			}
03262			else if (headangle.Pitch < -MaxHeadAngle.Pitch)
03263			{
03264				bodyangle.Pitch = headangle.Pitch + MaxHeadAngle.Pitch;
03265				headangle.Pitch = -MaxHeadAngle.Pitch;
03266			}
03267		}
03268		else if (bRotateTorso)
03269		{
03270			bodyangle = LookAngle;
03271		}
03272		
03273		// Do head roll
03274		if (MaxHeadAngle.Roll > 0)	// TODO: Make proportional
03275			headangle.Roll = headangle.Yaw / 2;
03276		if (MaxBodyAngle.Roll > 0)  // TODO: Make proportional
03277			bodyangle.Roll = bodyangle.Yaw / 2;
03278	
03279		// Clamp to max angles
03280		bodyangle.Yaw   = Clamp(bodyangle.Yaw,   -MaxBodyAngle.Yaw,   MaxBodyAngle.Yaw);
03281		bodyangle.Pitch = Clamp(bodyangle.Pitch, -MaxBodyAngle.Pitch, MaxBodyAngle.Pitch);
03282		bodyangle.Roll  = Clamp(bodyangle.Roll,  -MaxBodyAngle.Roll,  MaxBodyAngle.Roll);
03283		headangle.Yaw   = Clamp(headangle.Yaw,   -MaxHeadAngle.Yaw,   MaxHeadAngle.Yaw);
03284		headangle.Pitch = Clamp(headangle.Pitch, -MaxHeadAngle.Pitch, headPitchUp);
03285		headangle.Roll  = Clamp(headangle.Roll,  -MaxHeadAngle.Roll,  MaxHeadAngle.Roll);
03286	
03287	//headdeg = headangle.Yaw * 360.0 / 65536.0;
03288	//bodydeg = bodyangle.Yaw * 360.0 / 65536.0;
03289	//SLog("Head="$headdeg$" Body="$bodydeg);
03290	
03291		headangle += Rotation;
03292		bodyangle += Rotation;
03293	
03294		joint = JointNamed('torso');
03295		if (joint != 0)
03296		{
03297			if (bRotateTorso)
03298				TurnJointTo(joint, bodyangle);
03299			else
03300				TurnJointTo(joint, Rotation); // No extra rotation
03301		}
03302	
03303		joint = JointNamed('head');
03304		if (joint != 0)
03305		{
03306			if (bRotateHead)
03307				TurnJointTo(joint, headangle);
03308			else
03309				TurnJointTo(joint, Rotation); // No extra rotation
03310		}
03311	}
03312	*/
03313	
03314	//=============================================================================
03315	//
03316	// UseNotify
03317	//
03318	// Notify used by animations to specify when the use should occur
03319	//=============================================================================
03320	
03321	function UseNotify()
03322	{
03323		if(UseActor != None)
03324			UseActor.UseTrigger(self);
03325	
03326		UseActor = None;
03327	}
03328	
03329	//------------------------------------------------------------
03330	//
03331	// Uninterrupted
03332	//
03333	// This state does not allow the pawn to be interrupted while
03334	// the pawn is performing a specific action.  Note that the pawn
03335	// will still take pain (but not enter the painstate) and die (and WILL
03336	// go into the death state) while in this state.
03337	//------------------------------------------------------------
03338	
03339	function PlayUninterruptedAnim(name Anim)
03340	{
03341		if(GetStateName() != 'Uninterrupted')
03342		{
03343			Velocity.X = 0;
03344			Velocity.Y = 0;
03345			Acceleration = vect(0, 0, 0);
03346			
03347			UninterruptedAnim = Anim;
03348			NextState = GetStateName();
03349			GotoState('Uninterrupted');
03350			
03351			if(AnimProxy != None)
03352				AnimProxy.GotoState('Uninterrupted');
03353		}
03354	}
03355	
03356	state Uninterrupted
03357	{
03358	ignores SeePlayer, EnemyNotVisible, HearNoise, Trigger, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, LongFall, Landed;
03359	
03360		function bool CanGotoPainState()
03361		{ // Do not allow the actor to enter the painstate when in uninterrupted mode
03362			return(false);
03363		}
03364	
03365		function BeginState()
03366		{
03367			if(UninterruptedAnim != 'None')
03368			{
03369				PlayAnim(UninterruptedAnim, 1.0, 0.1);
03370				if(AnimProxy != None)
03371					AnimProxy.PlayAnim(UninterruptedAnim, 1.0, 0.1);
03372			}
03373		}
03374	
03375		function EndState()
03376		{
03377			UninterruptedAnim = 'None';
03378		}
03379	
03380		function AnimEnd()
03381		{
03382			// Clear out any blending information (if it exists)
03383			BlendAnimSequence = 'None';
03384			if(AnimProxy != None)
03385			{
03386				AnimProxy.BlendAnimSequence = 'None';			
03387				AnimProxy.GotoState('Idle');
03388			}
03389	
03390			if(Weapon != None)
03391			{ // If there is a weapon, make the weapon go cold if it was hot during this animation
03392				Weapon.FinishAttack();
03393				Weapon.DisableSwipeTrail();
03394			}
03395	
03396			GotoState(NextState);
03397		}
03398	
03399		function Tick(float DeltaSeconds)
03400		{
03401			Global.Tick(DeltaSeconds);
03402		}
03403	}
03404	
03405	
03406	//------------------------------------------------------------
03407	//
03408	// Pain
03409	//
03410	//------------------------------------------------------------
03411	state Pain
03412	{
03413		function bool CanGotoPainState()
03414		{ // Do not allow the actor to enter the painstate when already in pain
03415			return(false);
03416		}
03417	
03418		function EndState()
03419		{
03420			NextStateAfterPain = '';
03421		}
03422	
03423	Begin:
03424	
03425		if(PainDelay < 0)
03426		{ // If PainDelay is negative, the painstate waits until the anim has completed
03427			FinishAnim();
03428		}
03429		else
03430		{ // Otherwise, just use the PainDelay
03431			Sleep(PainDelay);
03432		}
03433	//slog(name@"in painstate: going to"@NextStateAfterPain);
03434		if (NextStateAfterPain == '' && !bIsPlayer)	// hack for dwarf stuck in pain bug
03435			GotoState('Charging');
03436		else
03437			GotoState(NextStateAfterPain);
03438	}
03439	
03440	
03441	//------------------------------------------------------------
03442	//
03443	// STATE Dying
03444	//
03445	//------------------------------------------------------------
03446	state Dying
03447	{
03448	ignores SeePlayer, EnemyNotVisible, HearNoise, KilledBy, Trigger, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, Died, LongFall, PainTimer, Landed;
03449	
03450		function bool CanBeStatued()						{	return false;	}
03451		function PowerupStone(Pawn EventInstigator)			{}
03452		function PowerupIce(Pawn EventInstigator)			{}
03453		function PowerupFire(Pawn EventInstigator)			{}
03454		function PowerupBlaze(Pawn EventInstigator)			{}
03455		function PowerupFriend(Pawn EventInstigator)		{}
03456		function PowerupElectricity(Pawn EventInstigator)	{}
03457	
03458		function ReplaceWithCarcass()
03459		{
03460			local Carcass C;
03461	
03462			// Replace with a carcass if there is one
03463			if (!bHidden && CarcassType != None)
03464			{
03465				C = SpawnCarcass();
03466				if (C!=None)
03467				{
03468					C.RemovedStabbedWeapon(); // Remove a stabbed weapon if one exists
03469					C.SetBase(Base);
03470				}
03471	
03472				if (bIsPlayer)
03473				{
03474					HidePlayer();
03475				}
03476				else
03477				{
03478					bHidden=true;
03479					Destroy();
03480				}
03481			}
03482		}
03483	
03484		function ExpandCollisionRadius()
03485		{
03486			SetCollision(false, false, false);
03487			bCollideWorld = false;
03488	
03489			SetCollisionSize(DeathRadius, CollisionHeight);
03490	
03491			SetCollision(true, false, false);	// Allow to clip through other corpses
03492			bCollideWorld = true;
03493		}
03494	
03495		function ShrinkCollisionHeight()
03496		{
03497			local vector newloc;
03498			local float offset;
03499	
03500			SetCollision(false, false, false);
03501			bCollideWorld = false;
03502	
03503			SetCollisionSize(CollisionRadius, DeathHeight);
03504	
03505			// Adjust so corpse is lying on ground
03506			offset = default.CollisionHeight - default.DeathHeight;
03507			newloc = Location;
03508			newloc.Z -= offset;
03509			SetLocation(newloc);
03510			PrePivot.Z += offset;
03511	
03512			SetCollision(true, false, false);	// Allow to clip through other corpses
03513			bCollideWorld = true;
03514			bAllowStandOn=true;
03515		}
03516	
03517		function ApplyPainToJoint(int joint, vector momentum)
03518		{
03519			if ((JointFlags[joint] & JOINT_FLAG_ACCELERATIVE) != 0)
03520			{
03521				//slog("moving"@GetJointName(joint));
03522				ApplyJointForce(joint, Momentum);
03523			}
03524		}
03525	
03526		function bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
03527		{	// Do spasm
03528			ApplyPainToJoint(joint, Momentum);
03529			Super(Actor).JointDamaged(Damage, EventInstigator, HitLoc, Momentum, DamageType, joint);
03530		}
03531	
03532		function Done()
03533		{
03534			SetPhysics(PHYS_None);
03535			bCollideWorld = false;
03536			ReplaceWithCarcass();
03537		}
03538	
03539	Begin:
03540		LookTarget=None;
03541		LookSpot=vect(0,0,0);
03542		Goto('PreDeath');
03543	
03544	PreDeath:
03545		Goto('Death');
03546	
03547	Death:
03548		ExpandCollisionRadius();
03549		SetPhysics(PHYS_Falling);
03550	
03551		WaitForLanding();
03552		FinishAnim();
03553	
03554		ShrinkCollisionHeight();
03555		Done();
03556		Goto('PostDeath');
03557	
03558	PostDeath:
03559	}
03560	
03561	/*
03562	state Dying
03563	{
03564	ignores SeePlayer, EnemyNotVisible, HearNoise, KilledBy, Trigger, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, Died, LongFall, PainTimer, Landed;
03565	
03566		function ReplaceWithCarcass()
03567		{
03568			local Carcass C;
03569	
03570			ShrinkCollisionHeight();
03571	
03572			// Replace with a carcass if there is one
03573			if (!bHidden && CarcassType != None)
03574			{
03575				C = SpawnCarcass();
03576				C.RemovedStabbedWeapon(); // Remove a stabbed weapon if one exists
03577	
03578				if (bIsPlayer)
03579				{
03580					HidePlayer();
03581				}
03582				else
03583				{
03584					bHidden=true;
03585					Destroy();
03586				}
03587			}
03588		}
03589	
03590		function ExpandCollisionRadius()
03591		{
03592			SetCollision(false, false, false);
03593			bCollideWorld = false;
03594	
03595			SetCollisionSize(DeathRadius, CollisionHeight);
03596	
03597			SetCollision(true, false, true);	// Allow to clip through other corpses
03598			bCollideWorld = true;
03599		}
03600	
03601		function ShrinkCollisionHeight()
03602		{
03603			local vector newloc;
03604			local float offset;
03605	
03606			SetCollision(false, false, false);
03607			bCollideWorld = false;
03608	
03609			SetCollisionSize(CollisionRadius, DeathHeight);
03610	
03611			// Adjust so corpse is lying on ground
03612			offset = default.CollisionHeight - default.DeathHeight;
03613			newloc = Location;
03614			newloc.Z -= offset;
03615			SetLocation(newloc);
03616			PrePivot.Z += offset;
03617	
03618			SetCollision(true, false, true);	// Allow to clip through other corpses
03619			bCollideWorld = true;
03620			bAllowStandOn=true;
03621		}
03622	
03623		function ApplyPainToJoint(int joint, vector momentum)
03624		{
03625			if ((JointFlags[joint] & JOINT_FLAG_ACCELERATIVE) != 0)
03626			{
03627				//slog("moving"@GetJointName(joint));
03628				ApplyJointForce(joint, Momentum);
03629			}
03630		}
03631	
03632		function bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
03633		{	// Do spasm
03634			ApplyPainToJoint(joint, Momentum);
03635			Super(Actor).JointDamaged(Damage, EventInstigator, HitLoc, Momentum, DamageType, joint);
03636		}
03637	
03638		function BeginState()
03639		{
03640			LookTarget=None;
03641			LookSpot=vect(0,0,0);
03642			SetTimer(0.3, false);
03643		}
03644	
03645		event Landed(vector HitNormal, actor HitActor)
03646		{
03647			SetPhysics(PHYS_None);
03648		}
03649	
03650		function Timer()
03651		{
03652			ReplaceWithCarcass();
03653		}
03654	
03655	Begin:
03656		Goto('PreDeath');
03657	
03658	PreDeath:
03659		Goto('Death');
03660	
03661	Death:
03662		Goto('PostDeath');
03663	
03664	PostDeath:
03665	}
03666	*/
03667	
03668	
03669	
03670	//------------------------------------------------------------
03671	//
03672	// STATE GameEnded
03673	//
03674	//------------------------------------------------------------
03675	state GameEnded
03676	{
03677	ignores SeePlayer, HearNoise, KilledBy, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, JointDamaged, WarnTarget, Died;
03678	
03679		function BeginState()
03680		{
03681			SetPhysics(PHYS_None);
03682			HidePlayer();
03683		}
03684	}
03685	
03686	
03687	//=============================================================================
03688	// Skin support
03689	//=============================================================================
03690	static function int GetNumSkins()
03691	{
03692		return 1;
03693	}
03694	
03695	static function string GetSkinName(int Skin)
03696	{
03697		switch(Skin)
03698		{
03699			case 0:		return default.SkinDefaultText;
03700		}
03701		return "";
03702	}
03703	
03704	static function SetSkinActor(actor SkinActor, int NewSkin)
03705	{
03706		local int i;
03707	
03708		switch(NewSkin)
03709		{
03710			case 0:
03711			default:
03712				for (i=0; i<16; i++)
03713				{
03714					SkinActor.SkelGroupSkins[i] = Default.SkelGroupSkins[i];
03715				}
03716				break;
03717		}
03718	}
03719	
03720	function SpecialPainSkin(int BodyPart)
03721	{
03722	}
03723	
03724	
03725	// Powerup support
03726	function PowerupStone(Pawn EventInstigator);
03727	function PowerupIce(Pawn EventInstigator);
03728	function PowerupFire(Pawn EventInstigator);
03729	function PowerupBlaze(Pawn EventInstigator);
03730	function PowerupFriend(Pawn EventInstigator);
03731	function PowerupElectricity(Pawn EventInstigator);
03732	
03733	
03734	simulated function Debug(Canvas canvas, int mode)
03735	{
03736		Super.Debug(canvas, mode);
03737		
03738		Canvas.DrawText("Pawn:");
03739		Canvas.CurY -= 8;
03740		Canvas.DrawText("  Health:     " $ Health);
03741		Canvas.CurY -= 8;
03742		Canvas.DrawText("  Weapon:     " $ Weapon);
03743		Canvas.CurY -= 8;
03744		Canvas.DrawText("  Shield:     " $ Shield);
03745		Canvas.CurY -= 8;
03746		Canvas.DrawText("  Enemy:      " $ Enemy);
03747		Canvas.CurY -= 8;
03748		Canvas.DrawText("  LookTarget: " $ LookTarget);
03749		Canvas.CurY -= 8;
03750		Canvas.DrawText("  LookSpot:   " $ LookSpot);
03751		Canvas.CurY -= 8;
03752		Canvas.DrawText("  bOverrideLookTarget: " $ bOverrideLookTarget);
03753		Canvas.CurY -= 8;
03754		Canvas.DrawText("  HighSwing:  " $ bSwingingHigh);
03755		Canvas.CurY -= 8;
03756		Canvas.DrawText("  LowSwing:   " $ bSwingingLow);
03757		Canvas.CurY -= 8;
03758		Canvas.DrawText("  NextState:  " $ NextState);
03759		Canvas.CurY -= 8;
03760		Canvas.DrawText("  NextStateAfterPain: " $ NextStateAfterPain);
03761		Canvas.CurY -= 8;
03762		Canvas.DrawText("  intelligence: "$ intelligence);
03763		Canvas.CurY -= 8;
03764	
03765	/*
03766		Canvas.DrawText("  Cos(LookAngle): " $ cos(LookAngle.Yaw*2.0*Pi/65535.0));
03767		Canvas.CurY -= 8;
03768		Canvas.DrawText("  PeriphVision:   " $ PeripheralVision);
03769		Canvas.CurY -= 8;
03770		Canvas.DrawText("  LookYaw:    " $ LookAngle.Yaw);
03771		Canvas.CurY -= 8;
03772		Canvas.DrawText("  LookPitch:  " $ LookAngle.Pitch);
03773		Canvas.CurY -= 8;
03774	*/
03775	}
03776	
03777	defaultproperties
03778	{
03779	     AvgPhysicsTime=0.100000
03780	     MaxDesiredSpeed=1.000000
03781	     GroundSpeed=320.000000
03782	     WaterSpeed=200.000000
03783	     AccelRate=500.000000
03784	     JumpZ=325.000000
03785	     MaxStepHeight=25.000000
03786	     AirControl=0.050000
03787	     Visibility=128
03788	     SightRadius=2500.000000
03789	     HearingThreshold=1.000000
03790	     OrthoZoom=40000.000000
03791	     FovAngle=75.000000
03792	     Health=100
03793	     MaxHealth=100
03794	     MaxStrength=100
03795	     MaxPower=100
03796	     PainDelay=0.300000
03797	     bGibbable=True
03798	     AttitudeToPlayer=ATTITUDE_Hate
03799	     Intelligence=BRAINS_MAMMAL
03800	     noise1time=-10.000000
03801	     noise2time=-10.000000
03802	     FootstepVolume=0.330000
03803	     SoundDampening=1.000000
03804	     DamageScaling=1.000000
03805	     PlayerReStartState=PlayerWalking
03806	     NameArticle=" a "
03807	     PlayerReplicationInfoClass=Class'Engine.PlayerReplicationInfo'
03808	     MaxBodyAngle=(Yaw=8192)
03809	     MaxHeadAngle=(Pitch=4096,Yaw=8192)
03810	     bRotateHead=True
03811	     bRotateTorso=True
03812	     LookDegPerSec=360.000000
03813	     DeathRadius=22.000000
03814	     DeathHeight=22.000000
03815	     SkinDefaultText="Default"
03816	     bCanTeleport=True
03817	     bStasis=True
03818	     bIsPawn=True
03819	     bLookFocusPlayer=True
03820	     RemoteRole=ROLE_SimulatedProxy
03821	     AnimSequence=Fighter
03822	     bDirectional=True
03823	     Texture=Texture'Engine.S_Pawn'
03824	     bIsKillGoal=True
03825	     SoundRadius=9
03826	     SoundVolume=240
03827	     TransientSoundVolume=2.000000
03828	     bCollideActors=True
03829	     bCollideWorld=True
03830	     bBlockActors=True
03831	     bBlockPlayers=True
03832	     bProjTarget=True
03833	     bSweepable=True
03834	     bRotateToDesired=True
03835	     RotationRate=(Pitch=4096,Yaw=50000,Roll=3072)
03836	     NetPriority=2.000000
03837	}

End Source Code