SarkBall
Class SarkBallBot

source: c:\runehov\SarkBall\Classes\SarkBallBot.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Pawn
         |
         +--RuneI.ScriptPawn
            |
            +--SarkBall.SarkBallBot
Direct Known Subclasses:SarkBallBotAlric, SarkBallBotBerserker, SarkBallBotConrack, SarkBallBotDwarf, SarkBallBotElder, SarkBallBotGoblin, SarkBallBotKarl, SarkBallBotLokiGuard, SarkBallBotSigurd, SarkBallBotSnowBeast, SarkBallBotSven, SarkBallBotUlf, SarkBallBotValkyrie, SarkBallBotZombie

class SarkBallBot
extends RuneI.ScriptPawn

//----------------------------------------------------------- // //-----------------------------------------------------------
Variables
 vector Belowme
           RUNE: Stow Spots
 vector DebugJumpApex
           RUNE: Stow Spots
 vector DebugJumpLand
           RUNE: Stow Spots
 SarkBallGameReplicationInfo GR
 Int GameJumpZ
           RUNE: Stow Spots
 vector JumpDestination
           RUNE: Stow Spots
 Weapon LastHeldWeapon
           RUNE: Stow Spots
 Pawn LeadingPlayer
           RUNE: Stow Spots
 Pawn NearestFriendly
           RUNE: Stow Spots
 vector OldSchoolDestination
           RUNE: Stow Spots
 PlayerReplicationInfo PlayerReplicationInfo
 Int SarkBallTeam
 vector SchoolOffset
           RUNE: Stow Spots
 Weapon StowSpot[3]
           RUNE: Stow Spots
 Weapon StowWeapon2
           RUNE: Stow Spots
 Pawn TargetPlayer
 Actor TeamGoal
           RUNE: Stow Spots
 vector TeamGoalLocation
           RUNE: Stow Spots
 Y, Z
           RUNE: Stow Spots
 bool bAxeUsed
           RUNE: Stow Spots
 bool bDead
           RUNE: Stow Spots
 Bool bHasSarkBall
 Bool bIsCrouching
 bool bJumping
           RUNE: Stow Spots
 bool bThrowing
           RUNE: Stow Spots
 Float fMaxGroundSpeedScale
           RUNE: Stow Spots
 rotator rot
           RUNE: Stow Spots
 vector vec
           RUNE: Stow Spots

States
WaitForPass, SpreadLeft, GetOpenForPass, TacticalDecision, Acquisition, Uninterrupted, Fleeing, Dying, Hunting, IHaveTheBall, ThrowTheBall, EnemyHasBall, LooseBall, Startup, Fighting, Pain, Waiting, Charging, Dead

Function Summary
 eAttitude AttitudeToCreature(Pawn Other)
 void CalcJumpVelocity()
 void CalcStrafePosition()
 void CalcStrafePosition2()
 bool CanDirectlyThreaten()
     
//------------------------------------------------
//
// CanDirectlyThreaten
//
//------------------------------------------------
 bool CanPickup(Inventory item)
     
//============================================================
//
// CanPickup
//
// Let's pawn dictate what it can pick up
//============================================================
 void ChangeInPossession(Pawn Other)
 void CheckForEnemies()
     
// CheckForEnemies
//
// Allows scriptpawns to target other scriptpawns, as well as
// Could be changed to a radius actors check
 Pawn CheckForPlayerInFront(Actor Target)
 bool CheckForThrowAtGoal()
 bool CheckStrafeLeft()
 bool CheckStrafeRight()
 bool DamageBodyPart(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, name DamageType, int bodypart)
     
//------------------------------------------------------------
//
// DamageBodyPart
//
//------------------------------------------------------------
 void Died(Pawn Killer, name damagetype, vector HitLocation)
 bool DoIHaveTheBall()
 void DoJump(optional float)
     
//Player Jumped
 void DoThrow()
     
//------------------------------------------------
//
// DoThrow (notify)
//
// Throws actor attached to weapon joint at
// Enemy or OrderObject
//------------------------------------------------
 void DrawPrimaryWeapon()
 void DropWeapon()
     
//------------------------------------------------------------
//
// DropWeapon
//
//------------------------------------------------------------
 Actor GetGreenGong()
 Name GetGroup(Name AnimSequence)
     
//=============================================================================
//
// GetGroup
//
//=============================================================================
 Actor GetRedGong()
 Actor GetTeamGong()
 vector GoalLocation()
 bool HasSarkBall(Pawn Other)
 void HearNoise(float Loudness, Actor NoiseMaker)
     
//------------------------------------------------
//
// HearNoise
//
//------------------------------------------------
 String IdentifyMe()
 bool InCombatRange(Actor Other)
     
//============================================================
//
// InCombatRange
//
//============================================================
 bool InDangerFromAttack()
 void InstantStow()
 bool IsSameTeam(Pawn OtherPawn)
 bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
 void Landed(vector HitNormal, Actor HitActor)
     
//------------------------------------------------
//
// Global Landed
//
//------------------------------------------------
 SarkBall LocateSarkBall()
 void MyDebug(String psFunction, String psTest)
 Texture PainSkin(int BodyPart)
     
//============================================================
//
// PainSkin
//
// returns the pain skin for a given polygroup
//============================================================
 void PlayJumping(optional float)
 void PostBeginPlay()
     
//============================================================
//
// PostBeginPlay
//
//============================================================
 void PreBeginPlay()
 bool SetEnemy(Actor NewEnemy)
 void SetStowedWeapon(int stowindex, Weapon w)
     
//=============================================================================
//
// SetStowedWeapon
//
//=============================================================================
 bool ShouldDefend()
 void Spawned()
 void StowWeapon(Weapon oldWeapon)
     
//=============================================================================
//
// StowWeapon
//
//=============================================================================
 void SwitchToBattleAxe()
 bool ValidEnemy()
     
// Used to stop attacking when conditions are met


State WaitForPass Function Summary
 bool AddDefaultInventory()
 bool BodyPartSeverable(int BodyPart)
     
//================================================
//
// BodyPartSeverable
//
//================================================
 void Touch(Actor Other)
 void LookAtEndPoint(int index)
 Bool IsEnemyInProximity()
 void Tick(float DeltaTime)
 void EndState()
 void BeginState()


State SpreadLeft Function Summary
 void BeginState()


State GetOpenForPass Function Summary
 void HitWall(vector HitNormal, Actor Wall)
 void PickDestination()
 void PickStrafeDestination(Actor Friendly)
 void Timer()
 void SeePlayer(Actor seen)
     
//------------------------------------------------
 void Tick(float DeltaSeconds)
 void EndState()
 void BeginState()


State TacticalDecision Function Summary
 Bool BallCloserToGoalThanMe()
 Float DistanceToPlayerWithBall()
 void Tick(float DeltaTime)
 void BeginState()


State Acquisition Function Summary
 void InformTeammates()
 void BeginState()


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


State Fleeing Function Summary
 void Bump(Actor Other)
 void PickDestination()
 void BeginState()


State Dying Function Summary
 void BeginState()


State Hunting Function Summary
 bool WantsToPickUp(Inventory item)
     
//------------------------------------------------
//
// WantsToPickup
//
// Returns whether the item is desired
//------------------------------------------------
 void SeePlayer(Actor seen)
     
//------------------------------------------------
//
// Global SeePlayer
//
//------------------------------------------------
 Bool CheckForThrowToPlayer(Pawn Other)
 Bool IsPlayerOpen(Pawn Other)
 void CheckForThrowing(Pawn Other)
 void PlayMoving(optional float)
     
//=============================================================================
//
// PlayMoving
//
//=============================================================================
 void PlayTaunting(optional float)
 void PlayJump()
     
//=============================================================================
//
// PlayJump
//
//=============================================================================
 void Tick(float DeltaTime)
 void CalcJumpVelocity()
 bool CheckJumpLocation()
 void PickDestination()
 void MayFall()
 void HitWall(vector HitNormal, Actor Wall)
 void TryChargeEnemy()
 void HearNoise(float Loudness, Actor NoiseMaker)
 void EndState()
 void BeginState()


State IHaveTheBall Function Summary
 void HitWall(vector HitNormal, Actor Wall)
 void SeePlayer(Actor seen)
     
//------------------------------------------------
 void Landed(vector HitNormal, Actor HitActor)
     
//------------------------------------------------
//
// Global Landed
//
//------------------------------------------------
 void PickDestination()
 void Tick(float DeltaTime)
 bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
 void EndState()
 void BeginState()


State ThrowTheBall Function Summary
 void EndState()
 void BeginState()


State EnemyHasBall Function Summary
 void PickDestination()
 void CheckForThrowing(Pawn Other)
 void HitWall(vector HitNormal, Actor Wall)
 void Timer()
 void EndState()
 void BeginState()
     
//ignores SetEnemy, SeePlayer, EnemyNotVisible, HearNoise, Trigger, HeadZoneChange, FootZoneChange, ZoneChange, WarnTarget, LongFall;


State LooseBall Function Summary
 void HitWall(vector HitNormal, Actor Wall)
 void Timer()
 void PickDestination()
 void EndState()
 void BeginState()


State Startup Function Summary
 void EndState()
 void BeginState()


State Fighting Function Summary
 void HitWall(vector HitNormal, Actor Wall)
 void Timer()
     
// Determine AttackAction based upon enemy movement and position
 bool CanGotoPainState()
 void EndState()
 void BeginState()


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


State Waiting Function Summary
 void Bump(Actor Other)
 void BeginState()


State Charging Function Summary
 void HitWall(vector HitNormal, Actor Wall)
 void Tick(float DeltaTime)
 void BeginState()


State Dead Function Summary



Source Code


00001	//-----------------------------------------------------------
00002	//
00003	//-----------------------------------------------------------
00004	class SarkBallBot expands ScriptPawn;    //SarkConrack
00005	
00006	
00007	const TEAM_RED = 0;
00008	const TEAM_GREEN = 2;
00009	
00010	Var Bool bIsCrouching;
00011	Var Bool bHasSarkBall;
00012	Var PlayerReplicationInfo PlayerReplicationInfo;
00013	Var Int SarkBallTeam;
00014	var SarkBallGameReplicationInfo GR;
00015	Var Pawn TargetPlayer;
00016	
00017	var travel Weapon StowSpot[3]; // RUNE:  Stow Spots
00018	
00019	var Weapon LastHeldWeapon;
00020	
00021	var vector Belowme;
00022	
00023	Var Float fMaxGroundSpeedScale;
00024	
00025	var vector vec;
00026	var rotator rot;
00027	var vector X, Y, Z;
00028	
00029	var bool bAxeUsed;
00030	var bool bThrowing;
00031	var bool bDead;
00032	var bool bJumping;
00033	Var Int GameJumpZ;
00034	
00035	//From Sark
00036	Var Weapon StowWeapon2;
00037	var vector JumpDestination;
00038	var vector DebugJumpApex;
00039	var vector DebugJumpLand;
00040	
00041	var Pawn NearestFriendly;
00042	
00043	Var vector TeamGoalLocation;
00044	Var Actor TeamGoal;
00045	Var Pawn LeadingPlayer;
00046	var vector OldSchoolDestination;
00047	var vector SchoolOffset;
00048	
00049	
00050	enum MovementDir_e
00051	{
00052	     MD_FORWARD,
00053	     MD_BACKWARD,
00054	     MD_LEFT,
00055	     MD_RIGHT,
00056	     MD_FORWARDLEFT,
00057	     MD_FORWARDRIGHT,
00058	     MD_BACKWARDLEFT,
00059	     MD_BACKWARDRIGHT
00060	};
00061	
00062	
00063	//=============================================================================
00064	//
00065	// StowWeapon
00066	//
00067	//=============================================================================
00068	
00069	function StowWeapon(Weapon oldWeapon)
00070	{
00071	     local int joint;
00072	     local int handJoint;
00073	     local int stowIndex;
00074	     
00075	     if(Weapon == None)
00076	     {
00077	          return;
00078	     }
00079	
00080	     switch(Weapon.MeleeType)
00081	     {
00082	     case MELEE_SWORD:     
00083	          joint = JointNamed('attatch_sword'); // Compensate for a spelling error...  for now.
00084	          break;
00085	     case MELEE_AXE:
00086	          joint = JointNamed('attach_axe');
00087	          break;
00088	     case MELEE_HAMMER:
00089	          joint = JointNamed('attach_hammer');
00090	          break;
00091	     default:
00092	          joint = 0;
00093	          break;
00094	     }
00095	
00096	     handJoint = JointNamed(WeaponJoint);
00097	          
00098	     if(joint != 0 && handJoint != 0)
00099	     {
00100	          DetachActorFromJoint(handJoint);
00101	          AttachActorToJoint(Weapon, joint);
00102	          SetStowedWeapon(stowIndex, Weapon);
00103	          Weapon.GotoState('Stow');
00104	          Weapon = None;
00105	     }
00106	}
00107	
00108	
00109	function InstantStow()
00110	{
00111	     LastHeldWeapon = None;
00112	     if(Weapon != None)
00113	     { // Handle the current weapon (drop it, do nothing, or stow it)          
00114	          if(Weapon.IsA('NonStow'))
00115	               DropWeapon();
00116	          else
00117	          {
00118	               LastHeldWeapon = Weapon;
00119	               WeaponDeactivate();
00120	               Weapon.DisableSwipeTrail();
00121	               StowWeapon(None);
00122	          }
00123	
00124	          //SetMovementMode(); // Set combat or exploration mode
00125	     }
00126	}
00127	
00128	Function DrawPrimaryWeapon(){
00129	  local Weapon PendingWeapon;
00130	
00131	  //If (SarkBallGame(level.Game).bRoundOver) Return;
00132	  PendingWeapon=Spawn(Class'RuneI.SarkBallBroadSword');
00133	  AddInventory(PendingWeapon);
00134	  AcquireInventory(PendingWeapon);
00135	  ChangedWeapon();
00136	
00137	}
00138	
00139	//=============================================================================
00140	//
00141	// SetStowedWeapon
00142	//
00143	//=============================================================================
00144	
00145	function SetStowedWeapon(int stowindex, Weapon w)
00146	{
00147	     if (stowindex>=0 && stowindex<=2)
00148	     {
00149	          StowSpot[stowindex] = w;
00150	     }
00151	}
00152	
00153	function bool InDangerFromAttack()
00154	     {
00155	          if ((!Enemy.bSwingingHigh) && (!Enemy.bSwingingLow))
00156	               return false;
00157	
00158	          GetEnemyProximity();
00159	               
00160	          if (EnemyDist>CollisionRadius+Enemy.CollisionRadius+Enemy.MeleeRange)
00161	               return false;
00162	
00163	          return (EnemyVertical==VERT_LEVEL && EnemyFacing==FACE_FRONT);
00164	     }
00165	
00166	function bool ShouldDefend()
00167	     {
00168	          return (FRand() > FightOrDefend && InDangerFromAttack());
00169	     }
00170	
00171	function PlayJumping(optional float tween)    { PlayAnim  ('MOV_ALL_jump1_AA0S',      1.0, tween);   }
00172	
00173	//=============================================================================
00174	//
00175	// GetGroup
00176	//
00177	//=============================================================================
00178	
00179	function Name GetGroup(Name AnimSequence)
00180	{
00181	     //TODO: Order these by how often they are playing for speed (waiting/running first)
00182	     if(AnimSequence == 'MOV_ALL_jump1_AA0S')               return('Moving');
00183	     else if(AnimSequence == 'MOV_ALL_run1_AA0N')          return('Moving');
00184	     else if(AnimSequence == 'MOV_ALL_run1_AA0S')          return('Moving');
00185	     else if(AnimSequence == 'MOV_ALL_run1_AN0N')          return('Moving');
00186	     else if(AnimSequence == 'MOV_ALL_run1_AN0S')          return('Moving');
00187	     else if(AnimSequence == 'MOV_ALL_lstrafe1_AA0S')     return('Moving');
00188	     else if(AnimSequence == 'MOV_ALL_lstrafe1_AN0N')     return('Moving');
00189	     else if(AnimSequence == 'MOV_ALL_rstrafe1_AA0S')     return('Moving');
00190	     else if(AnimSequence == 'MOV_ALL_rstrafe1_AN0N')     return('Moving');
00191	     else if(AnimSequence == 'MOV_ALL_runback1_AA0S')     return('Moving');
00192	     else if(AnimSequence == 'MOV_ALL_pullup1_AA0N')          return('Moving');
00193	     else if(AnimSequence == 'pullup')                         return('Moving');
00194	     else if(AnimSequence == 'ropetest')                         return('Moving');
00195	
00196	     // Waiting
00197	     else if(AnimSequence == 'neutral_defend')               return('Waiting');
00198	     else if(AnimSequence == 'neutral_idle')                    return('Waiting');
00199	     else if(AnimSequence == 'Neutral_kick')                    return('Waiting');
00200	     else if(AnimSequence == 's1_defendPose')               return('Waiting');
00201	     else if(AnimSequence == 'IDL_ALL_crbreathe1_AN0N')     return('Waiting');
00202	     else if(AnimSequence == 'IDL_ALL_crbreathe1_AA0N')     return('Waiting');
00203	     else if(AnimSequence == 'IDL_ALL_crbreathe1_AN0S')     return('Waiting');
00204	     else if(AnimSequence == 'IDL_ALL_crbreathe1_AA0S')     return('Waiting');
00205	
00206	     else if(AnimSequence == 'S1_Throw')          return('Throwing');
00207	     else if(AnimSequence == 'S2_Throw')          return('Throwing');
00208	     else if(AnimSequence == 'S3_Throw')          return('Throwing');
00209	     else if(AnimSequence == 'S4_Throw')          return('Throwing');
00210	     else if(AnimSequence == 'S5_Throw')          return('Throwing');
00211	
00212	     else if(AnimSequence == 'H1_Throw')          return('Throwing');
00213	     else if(AnimSequence == 'H2_Throw')          return('Throwing');
00214	     else if(AnimSequence == 'H3_Throw')          return('Throwing');
00215	     else if(AnimSequence == 'H4_Throw')          return('Throwing');
00216	     else if(AnimSequence == 'H5_Throw')          return('Throwing');
00217	
00218	     else if(AnimSequence == 'X1_Throw')          return('Throwing');
00219	     else if(AnimSequence == 'X2_Throw')          return('Throwing');
00220	     else if(AnimSequence == 'X3_Throw')          return('Throwing');
00221	     else if(AnimSequence == 'X4_Throw')          return('Throwing');
00222	     else if(AnimSequence == 'X5_Throw')          return('Throwing');
00223	
00224	     if(Weapon != None)
00225	     { // TODO!  Check weapon anims versus AnimSequence to see if Ragnar is moving
00226	          if(AnimSequence == Weapon.A_Forward
00227	               || AnimSequence == Weapon.A_Backward
00228	               || AnimSequence == Weapon.A_StrafeLeft
00229	               || AnimSequence == Weapon.A_StrafeRight
00230	               || AnimSequence == Weapon.A_Forward45Left
00231	               || AnimSequence == Weapon.A_Forward45Right
00232	               || AnimSequence == Weapon.A_Backward45Left
00233	               || AnimSequence == Weapon.A_Backward45Right
00234	               || AnimSequence == Weapon.A_Jump)
00235	          { // Playing a movement attack animation
00236	               return('Moving');          
00237	          }
00238	          else if(AnimSequence == Weapon.A_AttackA
00239	               || AnimSequence == Weapon.A_AttackAReturn
00240	               || AnimSequence == Weapon.A_AttackB
00241	               || AnimSequence == Weapon.A_AttackBReturn
00242	               || AnimSequence == Weapon.A_AttackC
00243	               || AnimSequence == Weapon.A_AttackCReturn
00244	               || AnimSequence == Weapon.A_AttackD
00245	               || AnimSequence == Weapon.A_AttackDReturn
00246	               || AnimSequence == Weapon.A_AttackBackupA
00247	               || AnimSequence == Weapon.A_AttackBackupAReturn
00248	               || AnimSequence == Weapon.A_AttackBackupB
00249	               || AnimSequence == Weapon.A_AttackBackupAReturn)
00250	          { // Playing a movement attack animation
00251	               return('AttackMoving');          
00252	          }
00253	          else if(AnimSequence == Weapon.A_AttackStandA
00254	               || AnimSequence == Weapon.A_AttackStandAReturn
00255	               || AnimSequence == Weapon.A_AttackStandB
00256	               || AnimSequence == Weapon.A_AttackStandBReturn)
00257	          { // Playing a standing attack animation
00258	               return('AttackStanding');          
00259	          }
00260	          else if(AnimSequence == Weapon.A_Throw)          return('Throwing');
00261	          else if(AnimSequence == Weapon.A_Idle)          return('Waiting');
00262	          else if(AnimSequence == Weapon.A_Powerup)     return('Powerup');
00263	          else if(AnimSequence == Weapon.A_JumpAttack) return('JumpAttack');
00264	     }
00265	
00266	     return('None');     
00267	}
00268	
00269	function CalcJumpVelocity()
00270	     {
00271	          local float traj;
00272	          local vector arcVel;
00273	
00274	          traj = 70 * 65536 / 360;
00275	
00276	          // JumpDestination is calculated in CheckJumpLocation
00277	          arcVel = CalcArcVelocity(traj, Location, JumpDestination);
00278	
00279	          AddVelocity(arcVel);
00280	     }
00281	
00282	//============================================================
00283	//
00284	// InCombatRange
00285	//
00286	//============================================================
00287	
00288	function bool InCombatRange(Actor Other)
00289	{
00290	     if(Other == None)
00291	          return(false);
00292	
00293	     return (VSize(Location - Other.Location) < CollisionRadius + Other.CollisionRadius + CombatRange);
00294	}
00295	
00296	Function ChangeInPossession(Pawn Other){
00297	  local vector V;
00298	  local rotator R;
00299	  local vector temp;
00300	
00301	  If (Other==None){
00302	    //BroadcastMessage("Change in possession to NONE",True);
00303	    MoveTarget=GR.CurrentSarkBall;
00304	    //GotoState('Hunting','Follow');
00305	    GotoState('LooseBall','Begin');
00306	  }else if (Other==self){
00307	    //ignore self
00308	  }else{
00309	    //BroadcastMessage("Change in possession to:"$Other.PlayerReplicationInfo.PlayerName$",Team:"$Other.PlayerReplicationInfo.Team,True);
00310	    If (IsSameTeam(Other)){
00311	      //BroadcastMessage("My Guy has the ball:"$GR.PlayerWithPossession.PlayerReplicationInfo.PlayerName,True);
00312	      If (VSize(TeamGoalLocation-Location)>300){
00313	        //BroadcastMessage("Going for the Goal!$"$Self.PlayerReplicationInfo.PlayerName,True);
00314	        Enemy=None;
00315	        GotoState('GetOpenForPass','Begin');
00316	
00317	        //MoveTarget=TeamGoal;
00318	        //GotoState('Hunting','SpecialNavigation');
00319	      }else{
00320	        //BroadcastMessage("ChangeInPossession_GoingToWaiting:"$Self.PlayerReplicationInfo.PlayerName,True);
00321	        GotoState('WaitForPass','Begin');
00322	      }
00323	    }else{
00324	      //Enemy has the ball
00325	      //BroadcastMessage("Notified of Enemy having the ball:"$Other.PlayerReplicationInfo.PlayerName,True);
00326	      //Enemy=Other;
00327	      //MoveTarget=Enemy;
00328	      GotoState('EnemyHasBall','Begin');
00329	
00330	    }
00331	
00332	  }
00333	}
00334	
00335	
00336	Function Spawned(){
00337	  //BroadcastMessage("Spawned!",True);
00338	  GameJumpZ=SarkBallGame(level.game).GameJumpZ;
00339	  //TeamGoal=GetTeamGong();
00340	  //TeamGoalLocation=TeamGoal.Location;
00341	
00342	  //BroadcastMessage("SpawnBot:GameJumpZ:"$GameJumpZ,True);
00343	  //BroadcastMessage("SpawnBot:TeamGoal:"$TeamGoalLocation,True);
00344	}
00345	
00346	//============================================================
00347	//
00348	// PostBeginPlay
00349	//
00350	//============================================================
00351	
00352	function PostBeginPlay()
00353	{
00354	     //local actor f;
00355	
00356	     //Super.PostBeginPlay();
00357	
00358	     //f = Spawn(Class'SarkEyeConrack');
00359	     //AttachActorToJoint(f, JointNamed('head'));
00360	}
00361	
00362	
00363	function CalcStrafePosition()
00364	  {
00365	  local vector V;
00366	  local rotator R;
00367	  local vector temp;
00368	
00369	  If (Enemy==None){
00370	    If (GR.CurrentSarkBall!=None){
00371	    Destination=GR.CurrentSarkBall.Location;
00372	    }else{
00373	    Destination=TeamGoalLocation;
00374	    }
00375	    Return;
00376	  }
00377	
00378	  V = Location - Enemy.Location;
00379	  R = rotator(V);
00380	          
00381	  R.Yaw += 2000;
00382	
00383	  // Strafe using the enemy's XY location, but the viking's location ground plane
00384	  temp = Enemy.Location;
00385	  temp.Z = Location.Z;
00386	
00387	  Destination = temp + vector(R) * CombatRange;
00388	  }
00389	
00390	function CalcStrafePosition2()
00391	  {
00392	  local vector V;
00393	  local rotator R;
00394	  local vector temp;
00395	          
00396	  V = Location - Enemy.Location;
00397	  R = rotator(V);
00398	          
00399	  R.Yaw -= 2000;
00400	
00401	  // Strafe using the enemy's XY location, but the viking's location ground plane
00402	  temp = Enemy.Location;
00403	  temp.Z = Location.Z;
00404	
00405	  Destination = temp + vector(R) * CombatRange;
00406	  }
00407	
00408	function bool CheckStrafeLeft()
00409	  { // Checks if the left strafe move is valid (not going to strafe into a wall)
00410	  local vector HitLocation, HitNormal;
00411	  local vector extent, end;
00412	
00413	  extent.X = CollisionRadius;
00414	  extent.Y = CollisionRadius;
00415	  extent.Z = CollisionHeight * 0.5;
00416	
00417	  CalcStrafePosition();
00418	
00419	  end = Normal(Destination - Location) * 75;
00420	
00421	  if(Trace(HitLocation, HitNormal, end, Location, true, extent) == None)
00422	    return(true); // Nothing in the way
00423	  else
00424	    return(false);
00425	  }
00426	
00427	function bool CheckStrafeRight()
00428	  { // Checks if the right strafe move is valid (not going to strafe into a wall)
00429	  local vector HitLocation, HitNormal;
00430	  local vector extent, end;
00431	
00432	  extent.X = CollisionRadius;
00433	  extent.Y = CollisionRadius;
00434	  extent.Z = CollisionHeight * 0.5;
00435	
00436	  CalcStrafePosition2();
00437	
00438	  end = Normal(Destination - Location) * 75;
00439	
00440	  if(Trace(HitLocation, HitNormal, end, Location, true, extent) == None)
00441	    return(true); // Nothing in the way
00442	  else
00443	    return(false);
00444	  }
00445	
00446	
00447	//============================================================
00448	//
00449	// PainSkin
00450	//
00451	// returns the pain skin for a given polygroup
00452	//============================================================
00453	function Texture PainSkin(int BodyPart)
00454	  {
00455	  switch(BodyPart)
00456	    {
00457	          case BODYPART_TORSO:
00458	               SkelGroupSkins[1] = Texture'players.ragnarsig_bodypain';
00459	               break;
00460	          case BODYPART_HEAD:
00461	               SkelGroupSkins[11] = Texture'players.ragnarsig_headpain';
00462	               break;
00463	          case BODYPART_LARM1:
00464	               SkelGroupSkins[9] = Texture'players.ragnarsig_armlegpain';
00465	               SkelGroupSkins[10] = Texture'players.ragnarsig_armlegpain';
00466	               break;
00467	          case BODYPART_RARM1:
00468	               SkelGroupSkins[6] = Texture'players.ragnarsig_armlegpain';
00469	               SkelGroupSkins[5] = Texture'players.ragnarsig_armlegpain';
00470	               break;
00471	          case BODYPART_LLEG1:
00472	               SkelGroupSkins[3] = Texture'players.ragnarsig_armlegpain';
00473	               SkelGroupSkins[13] = Texture'players.ragnarsig_armlegpain';
00474	               break;
00475	          case BODYPART_RLEG1:
00476	               SkelGroupSkins[4] = Texture'players.ragnarsig_armlegpain';
00477	               SkelGroupSkins[14] = Texture'players.ragnarsig_armlegpain';
00478	               break;
00479	     }
00480	  return None;
00481	}
00482	
00483	Function bool DoIHaveTheBall(){
00484	  If (Weapon==None) Return False;
00485	
00486	    If (Weapon.ISA('SarkBall')){
00487	      Return True;
00488	    }else{
00489	      Return False;
00490	    }
00491	}
00492	
00493	Function bool CheckForThrowAtGoal(){
00494	    local Actor Goal;
00495	    local float Dist;
00496	
00497	    //BroadcastMessage("CheckForThrowAtGoal:"$AnimSequence,True);
00498	    If (Instr(AnimSequence,"throw")>0){
00499	      //BroadcastMessage("LeavingBecauseAlreadyThrowing:"$AnimSequence,True);
00500	      Return False;
00501	    }
00502	
00503	    //Goal=GetTeamGong();
00504	    Dist = VSize(TeamGoalLocation-Location);
00505	
00506	    //BroadcastMessage("Dist:"$Dist$",CanSee:"$CanSee(Goal),True);
00507	
00508	
00509	    if (Dist<1000 && CanSee(TeamGoal)){
00510	      //BroadcastMessage("Going to State Throw",True);
00511	      If (AngleTo(TeamGoalLocation) < 2000){
00512	        GotoState('ThrowTheBall','ThrowBallAtGoal');
00513	        Return True;
00514	      }
00515	    }
00516	
00517	    //BroadcastMessage("BotDiff:"$abs(TeamGoal.Location.X-Location.X)$","$abs(TeamGoal.Location.Y-Location.Y)$","$abs(TeamGoal.Location.Z-Location.Z),True);
00518	    If (AngleTo(TeamGoalLocation) < 2000 && abs(TeamGoal.Location.X-Location.X)<=400 && abs(TeamGoal.Location.Y-Location.Y)<=400 && abs(TeamGoal.Location.Z-Location.Z)<=750){
00519	      GotoState('ThrowTheBall','ThrowBallAtGoal');
00520	      Return True;
00521	    }
00522	    Return False;
00523	}
00524	
00525	
00526	
00527	
00528	
00529	Function vector GoalLocation(){
00530	  //BroadcastMessage("Location of Goal "$GetTeamGong().Name$" is "$GetTeamGong().Location,True);
00531	  Return GetTeamGong().Location;
00532	
00533	}
00534	
00535	
00536	Function SwitchToBattleAxe(){
00537	  local Inventory Inv, nextInv;
00538	  local Weapon newWeapon;
00539	  //Return;
00540	  /*
00541	  for(Inv = Inventory; Inv != None; Inv = nextInv)
00542	     {
00543	     BroadcastMessage("Inventory:"$Inv.Name,True);
00544	     If (Inv.ISA('Axe')){
00545	      BroadcastMessage("Found Goblin Axe!",True);
00546	      PendingWeapon = Weapon(Inv);
00547	      ChangedWeapon();
00548	      Return;
00549	     }
00550	  }
00551	  */
00552	  //newWeapon=Spawn(Class'SarkBall.SarkBallHandAxe',,,Location);
00553	  //newWeapon=Spawn(Class'RuneI.HandAxe',,,Location);
00554	  newWeapon=Spawn(Class'SarkBall.SarkBallHandAxe',,,Location);
00555	   //newWeapon=Spawn(Class'RuneI.DwarfBattleHammer',,,Location);
00556	  AddInventory(newWeapon);
00557	  AcquireInventory(newWeapon);
00558	
00559	
00560	
00561	}
00562	
00563	//------------------------------------------------------------
00564	//
00565	// DamageBodyPart
00566	//
00567	//------------------------------------------------------------
00568	function bool DamageBodyPart(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, name DamageType, int bodypart)
00569	{
00570	     local int PassThrough;
00571	     local int SeverDamage;
00572	     local int BluntDamage;
00573	     local bool bAlreadyDead;
00574	     local int AppliedDamage;
00575	     local Debris Gib;
00576	     local float scale;
00577	     local int i, NumChunks;
00578	
00579	     local vector AdjMomentum;
00580	
00581	     //BroadcastMessage("DamageBodyPart"$Damage,True);
00582	
00583	     if(!class'GameInfo'.Default.bVeryLowGore)
00584	     {
00585	          if (CurrentSkin != 0)
00586	               SpecialPainSkin(BodyPart);
00587	          else
00588	               PainSkin(BodyPart);
00589	     }
00590	
00591	     GetDamageValues(Damage, DamageType, BluntDamage, SeverDamage);
00592	     Level.Game.ReduceDamage(BluntDamage, SeverDamage, DamageType, self, EventInstigator);
00593	     PassThrough = LimbPassThrough(BodyPart, BluntDamage, SeverDamage);
00594	
00595	     //BroadcastMessage("Passthrough:"$PassThrough,True);
00596	     // Give instigator strength boost if deserving
00597	     if(EventInstigator!=None && EventInstigator.IsA('PlayerPawn') && Health>0 &&
00598	          (DamageType=='blunt' || DamageType=='sever' || DamageType=='bluntsever') &&
00599	          EventInstigator.Weapon!=None && !EventInstigator.Weapon.bPoweredUp &&
00600	          (PassThrough>0) )
00601	     { // Boost the player's strength/bloodlust for successful conventional attacks
00602	          EventInstigator.BoostStrength(0.2 * Damage);
00603	     }
00604	
00605	     if (BodyPart != BODYPART_BODY){
00606	          if (BodyPartSeverable(BodyPart) && (BodyPartHealth[BodyPart] > 0)){
00607	               BodyPartHealth[BodyPart] -= SeverDamage;
00608	     
00609	               if(BodyPartHealth[BodyPart] <= 0){
00610	                // Body Part was killed
00611	                    if (BodyPartCritical(BodyPart)){
00612	                         PassThrough = Max(Health, Damage);
00613	                         DamageType = 'decapitated';
00614	                    }
00615	
00616	                    // Sever the limb
00617	                    if(!class'GameInfo'.Default.bLowGore){
00618	                         BodyPartVisibility(BodyPart, false);
00619	                         BodyPartCollision(BodyPart, false);
00620	                         LimbSevered(BodyPart, Momentum);
00621	                    }
00622	               }
00623	          }
00624	     }
00625	
00626	     if (DamageType=='sever' || DamageType=='bluntsever'){
00627	      // spawn chunks
00628	          NumChunks = (Damage / 15) + 1;
00629	          NumChunks = NumChunks * Level.Game.DebrisPercentage;
00630	          for(i = 0; i < NumChunks; i++){
00631	               Gib = spawn(GibClass,,, HitLocation + VRand() * 2,);
00632	               if (Gib != None){
00633	                    Gib.SetSize(RandRange(0.1, 0.4));
00634	                    Gib.SetMomentum((-0.08 * Momentum));
00635	               }
00636	          }
00637	     }
00638	     else if (DamageType == 'crushed'){
00639	      // Force the gib when crushed
00640	          PassThrough = Default.Health*3;
00641	          bGibbable = true;
00642	     }
00643	
00644	     // Apply damage to body
00645	     if (PassThrough != 0){
00646	          bAlreadyDead = (Health <= 0);
00647	          AppliedDamage = PassThrough;
00648	          Health -= AppliedDamage;
00649	
00650	          if (Health > 0){
00651	               // Apply momentum
00652	               // NOTE:  This code is duplicated in Shield.Active and Shield.Idle states
00653	               AdjMomentum = momentum / Mass;
00654	               if(Mass < VSize(AdjMomentum) && Velocity.Z <= 0){
00655	                    AdjMomentum.Z += (VSize(AdjMomentum) - Mass) * 0.5;
00656	               }
00657	               AddVelocity(AdjMomentum);
00658	//               if (Velocity.Z == 0)
00659	//                    AddVelocity(momentum / Mass);
00660	
00661	               if(CanGotoPainState()){
00662	                // Only goto the painstate if the pawn allows it
00663	                    PlayTakeHitSound(AppliedDamage, DamageType, 1);
00664	
00665	                    if(PassThrough > 5) // DAMAGE_EPSILON = 5
00666	                    { // Only go to the painstate if the damage is over a given level
00667	                         if (GetStateName() != 'Pain' && GetStateName() != 'pain')
00668	                         {
00669	                              NextStateAfterPain = GetStateName();
00670	
00671	                              // Play pain anim
00672	                              //BroadcastMessage("PlayPainAnim",True);
00673	                              PlayTakeHit(5, AppliedDamage, HitLocation, DamageType, Momentum, BodyPart);
00674	                              GotoState('Pain');
00675	                         }
00676	                         return(false);
00677	                    }
00678	               }
00679	          }
00680	          else if (bAlreadyDead)
00681	          {     // Twitch corpse or Gib
00682	               if(Health < -Default.Health && bGibbable && !bHidden)
00683	               { // Gib if beaten down far enough
00684	                    SpawnBodyGibs(Momentum);
00685	                    PlayDyingSound('gibbed');
00686	                    if (bIsPlayer)
00687	                         bHidden=true;
00688	                    else
00689	                         Destroy();
00690	               }
00691	          }
00692	          else
00693	          { // Kill the creature
00694	               AddVelocity(momentum * 2 / Mass);
00695	               if(Health < -Default.Health && bGibbable)
00696	               { // Gib if beaten down far enough
00697	                    Died(EventInstigator, 'gibbed', HitLocation);
00698	//                    if (bIsPlayer)     // moved to died
00699	//                         bHidden=true;
00700	//                    else
00701	//                         Destroy();
00702	               }
00703	               else
00704	               {
00705	                    // Apply momentum
00706	                    Died(EventInstigator, DamageType, HitLocation);
00707	               }
00708	          }
00709	          MakeNoise(1.0);
00710	     }
00711	
00712	     return(false);
00713	}
00714	
00715	
00716	//------------------------------------------------
00717	//
00718	// HearNoise
00719	//
00720	//------------------------------------------------
00721	function HearNoise(float Loudness, Actor NoiseMaker)
00722	{
00723	     //MyDebug("HearNoise",String(NoiseMaker.Name));
00724	     //Super.HearNoise(Loudness,NoiseMaker);
00725	}
00726	
00727	
00728	
00729	Function String IdentifyMe(){
00730	  local string lsIdentity;
00731	  local Pawn Other;
00732	
00733	  Other=Self;
00734	  lsIdentity="("$Other.Name;
00735	
00736	  If (Other.PlayerReplicationInfo!=None){
00737	    lsIdentity=lsIdentity$"/"$Other.PlayerReplicationInfo.PlayerName$"/"$Other.PlayerReplicationInfo.Team;
00738	
00739	
00740	  }
00741	  lsIdentity=lsIdentity$")";
00742	  Return lsIdentity;
00743	
00744	}
00745	
00746	Function MyDebug(String psFunction,String psTest){
00747	
00748	  Log(psFunction$IdentifyMe()$"_"$psTest);
00749	  //BroadcastMessage(psFunction$IdentifyMe()$"_"$psTest,True);
00750	
00751	
00752	}
00753	
00754	
00755	//------------------------------------------------------------
00756	//
00757	// DropWeapon
00758	//
00759	//------------------------------------------------------------
00760	function DropWeapon()
00761	{
00762	     local vector X,Y,Z;
00763	     local int joint;
00764	     
00765	     //BroadcastMessage("DropWeapon("$self.name$"-->"$Weapon.Name$")",True);
00766	
00767	     if(Weapon == None)
00768	          return;
00769	
00770	     If (DoIHaveTheBall()){
00771	      //BroadcastMessage("Not Destroying SarkBall...",True);
00772	     }else{
00773	     Weapon.Destroy();
00774	     return;
00775	     }
00776	
00777	
00778	
00779	     if(Weapon.bPoweredUp)
00780	      Weapon.PowerupEnd();
00781	
00782	     joint = JointNamed(WeaponJoint);
00783	     if (joint != 0)
00784	     {
00785	          DetachActorFromJoint(joint);
00786	          
00787	          GetAxes(Rotation, X, Y, Z);
00788	          Weapon.DropFrom(GetJointPos(joint));
00789	
00790	          if (Weapon != None)     // Invisible weapons get destroyed at DropFrom()
00791	          {
00792	               Weapon.SetPhysics(PHYS_Falling);
00793	               Weapon.Velocity = Y * 100 + X * 75;
00794	               Weapon.Velocity.Z = 50;
00795	               Weapon.GotoState('Drop');
00796	               Weapon.DisableSwipeTrail();
00797	
00798	               DeleteInventory( Weapon );
00799	          }
00800	     }
00801	}  
00802	
00803	function Died(pawn Killer, name damagetype, vector HitLocation){
00804	
00805	
00806	  //BroadcastMessage("Died("$Self.Name$")",True);
00807	
00808	
00809	
00810	  Super.Died(Killer, damageType, HitLocation);
00811	
00812	}
00813	
00814	
00815	// CheckForEnemies
00816	//
00817	// Allows scriptpawns to target other scriptpawns, as well as
00818	// Could be changed to a radius actors check
00819	function CheckForEnemies()
00820	{
00821	
00822	  local Pawn P, ClosestEnemy;
00823	  local eAttitude att;
00824	  local float Dist,LeastDist;
00825	  local float radius;
00826	  local SarkBall TheSarkBall;
00827	
00828	
00829	  //MyDebug("CheckForEnemies","Start");
00830	
00831	
00832	  ClosestEnemy=None;
00833	  LeastDist=9999999.0;
00834	
00835	  //Do I have the SarkBall?
00836	  If (HasSarkBall(Self)){
00837	    //MyDebug("CheckForEnemies","I have the Sarkball!");
00838	    //SetEnemy(GetTeamGong());
00839	    Destination=TeamGoalLocation;
00840	    SetEnemy(None);
00841	    return;
00842	  }
00843	  //MyDebug("CheckForEnemies","Does anyone else have the Sarkball");
00844	  //Does anyone else have the SarkBall?
00845	  If (GR.PlayerWithPossession!=None){
00846	    //MyDebug("CheckForEnemies","Someone Else Has Possession!");
00847	    If (!IsSameTeam(GR.PlayerWithPossession)){
00848	    //MyDebug("CheckForEnemies","Attack Player With Ball");
00849	    SetEnemy(GR.PlayerWithPossession);
00850	    }else{
00851	    //MyDebug("CheckForEnemies","Player With Ball is on my team!");
00852	    }
00853	    Return;
00854	  }
00855	
00856	  //Otherwise go after the SarkBall
00857	  //MyDebug("CheckForEnemies","Get Sarkball!");
00858	
00859	
00860	  If (LocateSarkBall()!=None){
00861	    TheSarkBall=LocateSarkBall();
00862	    Destination=TheSarkBall.Location;
00863	  }
00864	
00865	  Return;
00866	
00867	  // Should never get down here
00868	
00869	     if (HuntDistance>0)
00870	          radius = Min(HuntDistance, SightRadius);
00871	     else
00872	          radius = SightRadius;
00873	
00874	     foreach RadiusActors(class'Pawn', P, radius){
00875	          if (P==self)
00876	               continue;
00877	
00878	          if (IsSameTeam(P)){
00879	            //MyDebug("CheckForEnemies","DisregardingSAMETEAM");
00880	            continue;
00881	          }
00882	
00883	          dist = VSize(P.Location-Location);
00884	
00885	          if (HuntDistance>0 && (dist > 2*HuntDistance || VSize(HomeBase-P.Location)>2*HuntDistance))
00886	               continue;
00887	
00888	
00889	          if (dist<LeastDist)
00890	          {
00891	               if (actorReachable(P) || FindBestPathToward(P))
00892	               {
00893	                    LeastDist=Dist;
00894	                    ClosestEnemy=P;
00895	                    //MyDebug("CheckForEnemies","ClosestEnemy:"$P.Name);
00896	               }
00897	          }
00898	     }
00899	
00900	     if (ClosestEnemy != None)
00901	     {
00902	        //MyDebug("CheckForEnemies","Setting Enemy To Closest:"$ClosestEnemy);
00903	          SetEnemy(ClosestEnemy);
00904	
00905	     }
00906	
00907	
00908	//BroadcastMessage("CheckForEnemies("$Name$")_END",True);
00909	
00910	}
00911	
00912	function bool IsSameTeam(Pawn OtherPawn){
00913	  //Log("IsSameTeam");
00914	
00915	  If (OtherPawn==None) Return False;
00916	
00917	  If (OtherPawn.ISA('SarkBallBot')){
00918	    //MyDebug("IsSameTeam","IsSarkBallBot");
00919	    If (SarkBallBot(OtherPawn).SarkBallTeam==SarkBallTeam){
00920	      //Log("IsSameTeam_Yes");
00921	      //MyDebug("ISSAMETEAM","sarkballbot SAMETEAM");
00922	      return True;
00923	      }
00924	  }else{
00925	    //MyDebug("IsSameTeam",string(OtherPawn.Name));
00926	    If (OtherPawn.PlayerReplicationInfo==None)
00927	      MyDebug("IsSameTeam","PlayerReplicationInfo is NONE");
00928	
00929	     If (OtherPawn.PlayerReplicationInfo.Team==SarkBallTeam){
00930	      //MyDebug("ISSAMETEAM","same SAMETEAM");
00931	      return True;
00932	      }
00933	  }
00934	  return False;
00935	}
00936	
00937	// Used to stop attacking when conditions are met
00938	function bool ValidEnemy()
00939	{
00940	  //BroadcastMessage("ValidEnemy: Does "$Name$" Like "$Enemy.Name,True);
00941	
00942	
00943	  //Do I have the SarkBall?
00944	  If (DoIHaveTheBall()){
00945	    Return False;
00946	  }
00947	
00948	  //Does someone else have the SarkBall?
00949	  If (GR.PlayerWithPossession!=None){
00950	
00951	    If (!IsSameTeam(GR.PlayerWithPossession)){
00952	      //BroadcastMessage("Directing to Attack Player With Ball",True);
00953	      SetEnemy(GR.PlayerWithPossession);
00954	
00955	    }
00956	
00957	  }
00958	
00959	  If (GR.PlayerWithPossession==None || GR.ThrowingPlayer!=None){
00960	    //BroadcastMessage("ValidEnemy...SarkBall is Loose",True);
00961	    If (actorReachable(GR.CurrentSarkBall))
00962	      {
00963	        //BroadcastMessage("ValidEnemy("$Self.Name$"-->"$Enemy.Name$")...SarkBall is Reachable",True);
00964	        Destination=GR.CurrentSarkBall.Location;
00965	        Return False;
00966	      }
00967	  };
00968	
00969	  If (IsSameTeam(Enemy)){
00970	      //BroadcastMessage("Not enemy...same SAMETEAM",True);
00971	      return False;
00972	  }
00973	
00974	
00975	     return (Enemy!=None && Enemy.Health>0 && !Enemy.bInvisible);
00976	}
00977	
00978	//------------------------------------------------
00979	//
00980	// CanDirectlyThreaten
00981	//
00982	//------------------------------------------------
00983	function bool CanDirectlyThreaten()
00984	{
00985	  //BroadcastMessage("CanDirectlyThreaten",True);
00986	  if (Enemy==None){
00987	    //BroadcastMessage("Can not threaten...no enemy",True);
00988	    return false;
00989	  };
00990	
00991	     if (Enemy.Region.Zone.bWaterZone && !bCanSwim && !bCanFly)
00992	          //BroadcastMessage("Can not waterzone",True);
00993	          return false;
00994	     if ( !Enemy.Region.Zone.bWaterZone && !bCanWalk && !bCanFly)
00995	        //BroadcastMessage("Can not can't walk or fly",True);
00996	          return false;
00997	     return ( ActorReachable(Enemy) );
00998	}
00999	
01000	
01001	//============================================================
01002	//
01003	// CanPickup
01004	//
01005	// Let's pawn dictate what it can pick up
01006	//============================================================
01007	function bool CanPickup(Inventory item)
01008	{
01009	  //BroadcastMessage("CanPickup("$self.Name$"-->"$item.name$") Weapon:"$Weapon,True);
01010	
01011	  If (DoIHaveTheBall())
01012	    Return False;
01013	
01014	    return true;
01015	
01016	     if (Health <= 0)
01017	          return false;
01018	
01019	     if (item.IsA('Weapon') && (BodyPartHealth[BODYPART_RARM1] > 0) )
01020	     {
01021	          return True;
01022	     }
01023	     else if (item.IsA('Shield') && (BodyPartHealth[BODYPART_LARM1] > 0) && (Shield == None))
01024	     {
01025	          return item.IsA('Shield');
01026	     }
01027	     return(false);
01028	}
01029	
01030	
01031	function eAttitude AttitudeToCreature(Pawn Other)
01032	{
01033	  //BroadcastMessage("AttitudeToCreature:"$Other.Name,True);
01034	  return ATTITUDE_Hate;
01035	
01036	}
01037	
01038	function PreBeginPlay()
01039	{
01040	  //BroadcastMessage("SarBallBot_PreBeginPlay_Team:"$PlayerReplicationInfo.Team,True);
01041	
01042	  Super.PreBeginPlay();
01043	
01044	}
01045	
01046	function bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
01047	{
01048	  local bool rtn;
01049	
01050	  //BroadcastMessage("Global_SarkBallBot_JointDamaged By:"$EventInstigator.Name,True);
01051	  rtn=Super.JointDamaged(Damage,EventInstigator,HitLoc,Momentum,DamageType,joint);
01052	  If (Health<=0) {
01053	    //BroadcastMessage("Ok! I'm Dead Already!",True);
01054	    //bDead=True;
01055	    //GotoState('Dead','Restart');
01056	     //SarkBallGame(level.game).RelocateSarkBallBot(Self);
01057	     //Sleep(60);
01058	    //Destroy();
01059	    //SarkBallGame(level.game).BuildSarkBallBot(SarkBallTeam,"Foo");
01060	  };
01061	
01062	  Return(rtn);
01063	}
01064	function Pawn CheckForPlayerInFront(actor Target){
01065	  local Pawn P;
01066	  local float Dist;
01067	
01068	  foreach RadiusActors(class'Pawn', P, VSize(Target.Location-Location)){
01069	      if (P==self)  continue;
01070	
01071	      if (IsSameTeam(P)){
01072	        //MyDebug("CheckForEnemies","DisregardingSAMETEAM");
01073	        continue;
01074	      }
01075	      If (AngleTo(P.Location)<=1000){
01076	        dist = VSize(P.Location-Location);
01077	        //BroadcastMessage("CheckInFront:"$P.PlayerReplicationInfo.PlayerName$",Angle:"$AngleTo(P.Location)$",Dist:"$dist,True);
01078	        Return P;
01079	      }
01080	  }
01081	
01082	
01083	}
01084	
01085	//Player Jumped
01086	function DoJump( optional float F ){
01087	  //BroadcastMessage("DoJump",True);
01088	  if ( !bIsCrouching && (Physics == PHYS_Walking) ){
01089	    //if ( !bUpdating )
01090	    //     PlayOwnedSound(JumpSound, SLOT_Talk, 1.5, true, 1200, 1.0 );
01091	    if ( (Level.Game != None) && (Level.Game.Difficulty > 0) )
01092	      MakeNoise(0.1 * Level.Game.Difficulty);
01093	
01094	      PlayInAir(0.1);
01095	    if ( bCountJumps && (Role == ROLE_Authority) && (Inventory != None) )
01096	      Inventory.OwnerJumped();
01097	
01098	    If (FRand() < 0.30){
01099	      AddVelocity(vect(200,0,0));
01100	    }Else If (FRand() < 0.30){
01101	      AddVelocity(vect(0,200,0));
01102	    }Else If (FRand() < 0.30){
01103	      AddVelocity(vect(0,200,0));
01104	    }else{
01105	      AddVelocity(vect(200,200,0));
01106	    }
01107	
01108	    Velocity.Z = JumpZ;
01109	    if ( (Base != Level) && (Base != None) )
01110	      Velocity.Z += Base.Velocity.Z;
01111	    SetPhysics(PHYS_Falling);
01112	  }
01113	}
01114	
01115	
01116	//------------------------------------------------
01117	//
01118	// DoThrow (notify)
01119	//
01120	// Throws actor attached to weapon joint at
01121	// Enemy or OrderObject
01122	//------------------------------------------------
01123	function DoThrow(){
01124	  local actor throwitem;
01125	  local int traj;
01126	  local vector throwloc;
01127	  local Weapon NewWeapon;
01128	  local vector extent;
01129	  local vector weaponLoc;
01130	  local vector HitLocation, HitNormal;
01131	  local vector X,Y,Z;
01132	  local int joint;
01133	  local vector end;
01134	  local vector ThrowVelocity;
01135	  local float fHightAdjustment;
01136	  local float fThrowDistance;
01137	  local vector ThrowToLocation;
01138	  local Actor HitActor;
01139	  local Pawn P;
01140	  local float Dist;
01141	
01142	  //BroadcastMessage("DoThrow_Begin",True);
01143	
01144	  If (Weapon==None) {
01145	    //BroadcastMessage("DoThrow_Returning due to None Weapon",True);
01146	    Return;
01147	  }
01148	
01149	  If (OrderObject==None){
01150	    //BroadcastMessage("DoThrow_Returning due to None OrderObject",True);
01151	    Return;
01152	  }
01153	
01154	  bJointsTouch=False;
01155	
01156	  GetAxes(ViewRotation, X, Y, Z); // Players throw in the direction they are looking
01157	
01158	  // Check if weapon will fit in intended location (trace from center to weapon location)
01159	  extent.X = Weapon.CollisionRadius;
01160	  extent.Y = Weapon.CollisionRadius;
01161	  extent.Z = Weapon.CollisionHeight;
01162	  weaponLoc = GetJointPos(joint);
01163	  //MyDebug("DoThrow","BeforeTrace");
01164	
01165	  end = Normal(OrderObject.location - Location) * 75;
01166	  //end = OrderObject.location;
01167	
01168	
01169	  //Check in front of OrderObject
01170	
01171	
01172	  /*
01173	  if(FastTrace(end, Location)){
01174	    BroadcastMessage("FastTrace_Throw would be blocked",True);
01175	
01176	  }
01177	
01178	  HitActor=Trace(HitLocation, HitNormal, end, Location, true, Extent);
01179	  If (HitActor!=None){
01180	    BroadcastMessage("TraceHit:"$HitActor.name,true);
01181	  }
01182	
01183	  if(Trace(HitLocation, HitNormal, end, Location, true, Extent) != None){
01184	    // Struck something along the way, spawn the weapon at the player location
01185	     If (Weapon!=None && Weapon.ISA('SarkBall')){
01186	      BroadcastMessage("Throw would be blocked",True);
01187	      bJointsTouch=True;
01188	      Return;
01189	     }
01190	
01191	     //weaponLoc = Location;
01192	  }
01193	  //MyDebug("DoThrow","AfterTrace");
01194	
01195	  */
01196	
01197	  bHasSarkBall=False;
01198	
01199	  throwloc = GetJointPos(JointNamed(WeaponJoint));
01200	  throwitem = DetachActorFromJoint(JointNamed(WeaponJoint));
01201	
01202	  if (throwitem != None){
01203	
01204	    If (throwitem.ISA('SarkBall')){
01205	      //MyDebug("DoThrow","Throwing a SarkBall");
01206	      GR.ThrowingPlayer=Self;
01207	      GR.PlayerWithPossession=Self;
01208	      GR.PlayerWithBall=Self;
01209	    };
01210	
01211	    //MyDebug("DoThrow","Preparing To Throw");
01212	    If (throwitem.ISA('Axe')){
01213	      traj = 8192;
01214	      throwitem.bBlockActors=True;
01215	      throwitem.bcollideworld=True;
01216	      //throwitem.bCollideActors=True;
01217	    }else{
01218	      traj = ThrowTrajectory;
01219	      //BroadcastMessage("ThrowTrajectory:"$ThrowTrajectory,True);
01220	      //traj=8192;
01221	    }
01222	    // Throw the item
01223	    throwitem.SetPhysics(PHYS_Falling);
01224	    throwitem.Acceleration = vect(0,0,0);
01225	    //throwitem.velocity.z-=400;
01226	    If (throwitem.ISA('Axe')){
01227	      ThrowToLocation=OrderObject.Location+(OrderObject.Velocity*1.5);
01228	      ThrowVelocity = CalcArcVelocity(traj, throwloc, ThrowToLocation);
01229	
01230	      //BroadcastMessage("Skipping vertical compensation for axe",True);
01231	
01232	      ThrowVelocity.z-=400;
01233	      throwitem.Velocity = ThrowVelocity;
01234	      //throwitem.velocity.y=throwitem.velocity.y*2;
01235	      //throwitem.velocity.x=throwitem.velocity.x*2;
01236	    }else{
01237	      ThrowToLocation=OrderObject.Location+(OrderObject.Velocity);
01238	      ThrowVelocity = CalcArcVelocity(traj, throwloc, ThrowToLocation);
01239	
01240	      fThrowDistance=VSize(ThrowToLocation-throwloc);
01241	
01242	      //BroadcastMessage(self.playerreplicationinfo.playername$",ThrowDistance:"$fThrowDistance,True);
01243	      //Base Throw Z Velocity
01244	      ThrowVelocity.z=200;
01245	
01246	      //BroadcastMessage("ThrowVelocityBefore:"$ThrowVelocity,True);
01247	
01248	      fHightAdjustment=abs(throwloc.Z-OrderObject.Location.Z);
01249	      //BroadcastMessage("Height Adjustment:"$fHightAdjustment,True);
01250	      //If (ThrowVelocity.z>=450){
01251	        //BroadcastMessage("ThrowZ:"$throwitem.velocity.z,True);
01252	        //ThrowVelocity.z-=300+(100-fHightAdjustment);
01253	
01254	      //}
01255	      //BroadcastMessage("OriginalZ:"$ThrowVelocity.z,True);
01256	      If (fThrowDistance>200){
01257	        //BroadcastMessage("Adjusting Throw For Distance:"$(fThrowDistance-220) * 0.2,True);
01258	      ThrowVelocity.z+=(fThrowDistance-200) * 0.15;
01259	
01260	      }
01261	      If (throwloc.Z<=OrderObject.Location.Z){
01262	        //BroadcastMessage("Adjusting Throw Up:"$fHightAdjustment * 1.1,True);
01263	        ThrowVelocity.z+=fHightAdjustment * 1.1;
01264	      }else{
01265	        //BroadcastMessage("Adjusting Throw Down:"$fHightAdjustment * 1.1,True);
01266	        ThrowVelocity.z-=fHightAdjustment * 1.1;
01267	      }
01268	      //BroadcastMessage("ThrowVelocityAfter:"$ThrowVelocity,True);
01269	      throwitem.Velocity = ThrowVelocity;
01270	
01271	      //Back out my velocity since the ball will add it.
01272	      If (SarkBallGame(level.game).bAdvancedThrowing){
01273	      throwitem.velocity=throwitem.velocity-self.velocity;
01274	      //BroadcastMessage("MyRotation:"$Rotation,True);
01275	      throwitem.velocity=throwitem.velocity+OrderObject.velocity;
01276	      }
01277	
01278	      /*
01279	      // Add some error in
01280	      If (FRand() < 0.05){
01281	         throwitem.velocity.x = throwitem.velocity.x + (FRand() * 0.2);
01282	      }else If(FRand() < 0.05){
01283	         throwitem.velocity.y = throwitem.velocity.y + (FRand() * 0.2);
01284	      }else If(FRand() < 0.05){
01285	         throwitem.velocity.z = throwitem.velocity.z + (FRand() * 0.2);
01286	      }
01287	      */
01288	
01289	    }
01290	    //BroadcastMessage("Velocity:"$CalcArcVelocity(traj, throwloc, OrderObject.Location),True);
01291	    throwitem.GotoState('Throw');
01292	
01293	    if(throwItem.IsA('inventory'))
01294	      DeleteInventory(Inventory(throwItem));
01295	
01296	    if (Weapon==throwitem)
01297	      Weapon=None;
01298	    }
01299	
01300	    //Destination=LocateSarkBall().Location;
01301	    //Enemy=None;
01302	
01303	    //bJointsTouch=True;
01304	
01305	    //BroadcastMessage("DoThrow_End",True);
01306	}
01307	
01308	function Actor GetTeamGong(){
01309	  If (SarkBallTeam==TEAM_RED){
01310	     return GetGreenGong();
01311	  }else{
01312	     return GetRedGong();
01313	  };
01314	}
01315	
01316	
01317	//------------------------------------------------
01318	//
01319	// Global Landed
01320	//
01321	//------------------------------------------------
01322	function Landed(vector HitNormal, actor HitActor){
01323	  local Actor Gong;
01324	
01325	  //BroadcastMessage("SarkBallBot_Global_Landed:"$HitActor.name$"State:"$GetStateName(),true);
01326	  Super.Landed(HitNormal, HitActor);
01327	
01328	  //If (SarkBallTeam==TEAM_RED){
01329	  //  Gong=GetGreenGong();
01330	  //}else{
01331	  //  Gong=GetRedGong();
01332	  //};
01333	  //HomeBase=Gong.Location;
01334	
01335	  bJumping=False;
01336	
01337	  //BroadcastMessage("Landed_Gotostate_Hunting",True);
01338	  If (Weapon!=None && Weapon.ISA('SarkBall')){
01339	    //BroadcastMessage("Landed_Gotostate_IHaveTheBall_LookForGoal"$Self.PlayerReplicationInfo.PlayerName,True);
01340	    GotoState('IHaveTheBall','LookForGoal');
01341	  }else{
01342	    //BroadcastMessage("Landed_AddingDefaultInventory:"$self.PlayerReplicationInfo.PlayerName,true);
01343	    sarkballgame(level.game).AddDefaultInventory(self);
01344	    //BroadcastMessage("Landed_GotoState_Hunting:"$self.playerreplicationinfo.playername,True);
01345	    GotoState('Hunting','Hunt');
01346	  }
01347	}
01348	
01349	function bool HasSarkBall(pawn Other){
01350	  If (Other.Weapon==None) Return False;
01351	
01352	  If (Other.Weapon.ISA('SarkBall')){
01353	    //BroadcastMessage("HasSarkBall_True",true);
01354	    return true;
01355	  }else{
01356	    //BroadcastMessage("HasSarkBall_False",true);
01357	    return false;
01358	  }
01359	}
01360	
01361	function bool SetEnemy( Actor NewEnemy )
01362	{
01363	  local SarkBall P;
01364	  local Actor Gong;
01365	  local string CurrentState;
01366	  local Pawn OtherPlayer;
01367	
01368	  //BroadcastMessage("Global_SetEnemy:"$NewEnemy.Name$",State:"$GetStateName(),True);
01369	  //MyDebug("SetEnemy",string(NewEnemy.Name));
01370	  //Log("SetEnemy("$Self.Name$"-->"$NewEnemy.Name$")");
01371	
01372	  If (SarkBallGame(level.game).bRoundOver){
01373	    //BroadcastMessage("Ignoring Enemy...round over",True);
01374	    Enemy=None;
01375	    Return False;
01376	  }
01377	
01378	  If (SarkBallGame(level.game).bGameOver){
01379	    //BroadcastMessage("Ignoring Enemy...GAME over",True);
01380	    Enemy=None;
01381	    Return False;
01382	  }
01383	
01384	  If (IsSameTeam(Pawn(NewEnemy))){
01385	    //MyDebug("SetEnemy","Aborting SetEnemy due to SameTeam");
01386	    Return False;
01387	    }
01388	
01389	
01390	  If (NewEnemy.ISA('SarkBall')){
01391	    //BroadcastMessage("Setting Enemy as SarkBall...",True);
01392	    //Log("Setting Enemy as SarkBall...");
01393	    //Enemy=NewEnemy;
01394	    //BroadcastMessage("SetEnemy_Final:"$Enemy.Name,True);
01395	    Return True;
01396	  };
01397	
01398	  P=LocateSarkBall();
01399	
01400	  If (DoIHaveTheBall()){
01401	    //Log("Weapon_ISA_Sarkball");
01402	     //NewEnemy=GetTeamGong();
01403	     //Gong=GetTeamGong();
01404	     //Destination=GoalLocation();
01405	     //Log("Found Destination");
01406	     //LookToward(Gong.Location);
01407	     //BroadcastMessage("SetEnemy_Gotostate_IHaveTheBall_LookForGoal"$Self.PlayerReplicationInfo.PlayerName,True);
01408	
01409	     GotoState('IHaveTheBall','LookForGoal');
01410	     bHasSarkBall=True;
01411	     Enemy=None;
01412	     Return False;
01413	  }else{
01414	     bHasSarkBall=False;
01415	  };
01416	
01417	
01418	  If (GR.CurrentSarkBall!=None && GR.CurrentSarkBall.CarriedBy!=None){
01419	      If (IsSameTeam(GR.CurrentSarkBall.CarriedBy)){
01420	        //BroadcastMessage("SetEnemy_My Team Has Ball",True);
01421	        If (Vsize(GR.CurrentSarkBall.CarriedBy.Location-TeamGoalLocation)<Vsize(Self.Location-TeamGoalLocation)){
01422	          //BroadcastMessage("SetEnemy_My guy has the ball and he is closer to goal than me",True);
01423	          Enemy=None;
01424	          Return False;
01425	        }
01426	      }else{
01427	        //BroadcastMessage("SetEnemy_Enemy Has Ball",True);
01428	      }
01429	  }
01430	
01431	  Enemy = Pawn(NewEnemy);
01432	  Return True;
01433	
01434	}
01435	
01436	
01437	function Actor GetGreenGong(){
01438	   local GreenSarkBallGong P;
01439	
01440	    foreach AllActors( class'GreenSarkBallGong', P ){
01441	      //BroadcastMessage("GreenGong:"$P.Name,True);
01442	      Return P;
01443	    };
01444	}
01445	
01446	function Actor GetRedGong(){
01447	   local RedSarkBallGong P;
01448	
01449	    foreach AllActors( class'RedSarkBallGong', P ){
01450	      //BroadcastMessage("RedGong:"$P.Name,True);
01451	      Return P;
01452	    };
01453	}
01454	
01455	function SarkBall LocateSarkBall(){
01456	   local SarkBall P;
01457	
01458	    foreach AllActors( class'SarkBall', P ){
01459	      //BroadcastMessage("GreenGong:"$P.Name,True);
01460	      Return P;
01461	    };
01462	}
01463	
01464	State Dead{
01465	
01466	Restart:
01467	     bThrowing=False;
01468	     PlayDeath('');
01469	     Sleep(0.4);
01470	     //SetTimer(0.25, true);
01471	     //Disintegrate();
01472	
01473	  //bInVisible=True;
01474	  //Sleep(10);
01475	
01476	  //Log("SarkballBot_Dead_GoingToRelocate");
01477	  SarkBallGame(level.game).RelocateSarkBallBot(Self);
01478	  bDead=False;
01479	  //bInVisible=False;
01480	}
01481	
01482	state Charging{
01483	
01484	  Function BeginState(){
01485	    Super.BeginState();
01486	    bThrowing=False;
01487	  }
01488	
01489	  function Tick(float DeltaTime){
01490	    local Actor P;
01491	    local float Dist;
01492	    local Actor PlayerWhoHasTheBall;
01493	
01494	    If (bHidden) bHidden=False;
01495	
01496	    PlayerWhoHasTheBall=GR.PlayerWithPossession;
01497	
01498	    If (Enemy==None){
01499	      If (PlayerWhoHasTheBall!=None){
01500	        If (IsSameTeam(Pawn(PlayerWhoHasTheBall))){
01501	          //BroadcastMessage("My Guy has the ball:"$GR.PlayerWithPossession.PlayerReplicationInfo.PlayerName,True);
01502	          If (VSize(TeamGoalLocation-Location)>300){
01503	            Destination=GoalLocation();
01504	          }else{
01505	            GotoState('Waiting');
01506	          }
01507	        }else{
01508	          //BroadcastMessage("Look:"$GR.PlayerWithPossession.PlayerReplicationInfo.Team,True);
01509	          CheckForThrowing(Pawn(PlayerWhoHasTheBall));
01510	        }
01511	      }
01512	    }
01513	
01514	    Super.Tick(DeltaTime);
01515	  }
01516	
01517	  Function HitWall(vector HitNormal, actor Wall){
01518	    //BroadcastMessage("Charging_HitWall",True);
01519	    Super.Hitwall(HitNormal,Wall);
01520	  }
01521	
01522	}
01523	
01524	
01525	
01526	
01527	
01528	State Waiting{
01529	  Function BeginState(){
01530	    Super.BeginState();
01531	    bThrowing=False;
01532	
01533	  }
01534	
01535	  function Bump(actor Other){
01536	    //MyDebug("Waiting.Bump",String(Other.Name));
01537	    Super.Bump(Other);
01538	  }
01539	
01540	Begin:
01541	
01542	    If (DoIHaveTheBall()){
01543	      //BroadcastMessage("Waiting_BeginState_Alreadyhaveball:"$PlayerReplicationInfo.PlayerName,True);
01544	      sleep(0.1);
01545	      //BroadcastMessage("Waiting_GoingTo_PickedUp",True);
01546	      GotoState('IHaveTheBall','PickedUp');
01547	    }else if(GR.CurrentSarkBall.AttachParent==None){
01548	      sleep(0.1);
01549	      //Log("Waiting_GoingTo_LooseBall");
01550	      GotoState('LooseBall','Begin');
01551	    }else{
01552	      sleep(0.1);
01553	      //Log("Waiting_GoingTo_Hunting");
01554	      GotoState('Hunting','Begin');
01555	    }
01556	}
01557	
01558	
01559	//------------------------------------------------------------
01560	//
01561	// Pain
01562	//
01563	//------------------------------------------------------------
01564	state Pain{
01565	  function bool CanGotoPainState(){
01566	    // Do not allow the actor to enter the painstate when already in pain
01567	    return(false);
01568	  }
01569	
01570	  function BeginState(){
01571	    //BroadcastMessage("Pain_BeginState",True);
01572	
01573	    NextStateAfterPain = '';
01574	    bThrowing=False;
01575	  }
01576	
01577	  function EndState(){
01578	    //BroadcastMessage("Pain_EndState",True);
01579	    NextStateAfterPain = '';
01580	  }
01581	
01582	Begin:
01583	
01584	     if(PainDelay < 0)
01585	     { // If PainDelay is negative, the painstate waits until the anim has completed
01586	          //BroadcastMessage("Skipping Pain due to negative PainDelay",True);
01587	          FinishAnim();
01588	     }
01589	     else
01590	     { // Otherwise, just use the PainDelay
01591	          Sleep(PainDelay);
01592	     }
01593	//slog(name@"in painstate: going to"@NextStateAfterPain);
01594	     if (NextStateAfterPain == '' && !bIsPlayer)     // hack for dwarf stuck in pain bug
01595	          GotoState('Charging');
01596	     else
01597	          GotoState(NextStateAfterPain);
01598	}
01599	
01600	//================================================
01601	//
01602	// Fighting
01603	//
01604	//================================================
01605	State Fighting{
01606	
01607	  ignores EnemyAcquired;
01608	
01609	  Function BeginState(){
01610	    //Log("Fighting_BeginState");
01611	    Super.BeginState();
01612	    bThrowing=False;
01613	  }
01614	
01615	  Function EndState(){
01616	    //Log("Fighting_BeginState");
01617	    Super.EndState();
01618	  }
01619	
01620	  function bool CanGotoPainState(){
01621	    //BroadcastMessage("Can go to Pain State",True);
01622	    return(true);
01623	  }
01624	
01625	     // Determine AttackAction based upon enemy movement and position
01626	  function Timer(){
01627	    //BroadcastMessage("Fighting_Timer",True);
01628	    If (Enemy==None){
01629	      //BroadcastMessage("Fighting_Timer_GoingToHunting:"$self.PlayerReplicationInfo.PlayerName,True);
01630	      GotoState('Hunting','Hunt');
01631	      Return;
01632	    }
01633	
01634	    If (GR.ThrowingPlayer!=None && MoveTarget!=GR.CurrentSarkBall && GR.ThrowingPlayer!=Self){
01635	        //BroadcastMessage(Self.Name$":Fighting_ThrowingPlayer!=None and MoveTarget not SarkBall",True);
01636	        //MoveTarget=GR.CurrentSarkBall;
01637	        Enemy=None;
01638	        //BroadcastMessage("Fighting_Timer_GoingToHunting2:"$self.PlayerReplicationInfo.PlayerName,True);
01639	        GotoState('LooseBall','Begin');
01640	    }
01641	
01642	    GetEnemyProximity();
01643	    CheckForThrowing(Enemy);
01644	
01645	    LastAction = AttackAction;
01646	                    
01647	    if(EnemyMovement == MOVE_STRAFE_LEFT && FRand() < 0.65 && CheckStrafeLeft()){
01648	      AttackAction = AA_STRAFE_LEFT;
01649	    }else if(EnemyMovement == MOVE_STRAFE_RIGHT && FRand() < 0.65 && CheckStrafeRight()){
01650	      AttackAction = AA_STRAFE_RIGHT;
01651	    }
01652	          else if(FRand() < 0.08 && Physics == PHYS_Walking )
01653	          { // Sark jump
01654	            //BroadcastMessage("botJumpwhilefighting",True);
01655	               AttackAction = AA_JUMP;
01656	          }
01657	          else if(EnemyMovement == MOVE_STANDING && FRand() < 0.9 || FRand() < 0.35)
01658	          {
01659	               AttackAction = AA_LUNGE;
01660	          }          
01661	           else if(FRand() < 0.9)
01662	           {
01663	                if(FRand() < 0.5 && LastAction != AA_STRAFE_RIGHT || LastAction == AA_STRAFE_LEFT
01664	                    && CheckStrafeLeft())
01665	                {
01666	                     AttackAction = AA_STRAFE_LEFT;
01667	                }
01668	                else if(LastAction != AA_STRAFE_LEFT || LastAction == AA_STRAFE_RIGHT && CheckStrafeRight())
01669	                {
01670	                     AttackAction = AA_STRAFE_RIGHT;
01671	                }
01672	               else
01673	               {
01674	                    AttackAction = AA_WAIT;
01675	               }
01676	           }
01677	          else
01678	          {
01679	               AttackAction = AA_WAIT;
01680	          }
01681	          
01682	
01683	          if (ShouldDefend()){
01684	            //BroadcastMessage("Fighting_Defending",True);
01685	          //  GotoState('Fighting', 'Defend');
01686	          }
01687	
01688	     }
01689	
01690	  Function HitWall(vector HitNormal, actor Wall){
01691	
01692	    If (ActorReachable(Enemy)){
01693	      //BroadcastMessage("Fighting_HitWall_GoingTo_Charging",True);
01694	      GotoState('Charging','Begin');
01695	    }else{
01696	      //BroadcastMessage("Fighting_HitWall_GoingTo_Hunting",True);
01697	      GotoState('Hunting','Begin');
01698	    }
01699	
01700	    Super.Hitwall(HitNormal,Wall);
01701	  }
01702	
01703	Begin:
01704	  //Log("State_Fighting_Begin");
01705	  //BroadcastMessage("State_Fighting_Begin",True);
01706	  SetTimer(0.25, true);
01707	     If (Enemy==None){
01708	      //BroadcastMessage("Fighting_Begin:_GoingToHunting:"$self.PlayerReplicationInfo.PlayerName,True);
01709	      GotoState('Hunting','Begin');
01710	     }
01711	     Acceleration = vect(0,0,0);
01712	     GetEnemyProximity();
01713	
01714	     // Turn to face enemy
01715	     DesiredRotation.Yaw = rotator(Enemy.Location-Location).Yaw;
01716	  //Log("State_Fighting_Begin_End");
01717	          
01718	Fight:
01719	  //Log("State_Fighting_Fight:"$name);
01720	  If (Weapon==None){
01721	    GotoState('Hunting','DrawBroadSword');
01722	
01723	  }
01724	  if(!ValidEnemy())
01725	    Goto('BackFromSubState');
01726	
01727	  //If (Enemy==None)
01728	    //Log("Found Enemy None");
01729	
01730	  GetEnemyProximity();
01731	
01732	
01733	     // Attack if close enough
01734	     if(Weapon != None && InMeleeRange(Enemy) || (EnemyMovement == MOVE_CLOSER && EnemyDist < MeleeRange * 2.5)){
01735	          //Log("State_Fighting_EnemyInRange:"$name);
01736	          PlayAnim(Weapon.A_AttackA, 1.5, 0.1);
01737	          Sleep(0.1);
01738	          WeaponActivate();
01739	          Weapon.EnableSwipeTrail();
01740	          FinishAnim();
01741	
01742	          if(Weapon.A_AttackB != 'None' && FRand() < 0.7)
01743	          {
01744	             //Log("State_Fighting_EnemyInRange_1:"$name);
01745	               PlayAnim(Weapon.A_AttackB, 1.5, 0.01);
01746	               if(Enemy != None)
01747	                    TurnToward(Enemy);
01748	               FinishAnim();
01749	
01750	               // B-Return
01751	               WeaponDeactivate();
01752	
01753	               if(Weapon.A_AttackBReturn != 'None')
01754	               {
01755	                    PlayAnim(Weapon.A_AttackBReturn, 1.5, 0.1);
01756	                    FinishAnim();
01757	               }
01758	          }else{
01759	            //Log("State_Fighting_EnemyInRange_2:"$name);
01760	          // A-Return
01761	               WeaponDeactivate();
01762	
01763	               if(Weapon.A_AttackAReturn != 'None')
01764	               {
01765	                    PlayAnim(Weapon.A_AttackAReturn, 1.5, 0.1);
01766	                    FinishAnim();
01767	               }
01768	          }
01769	
01770	          Weapon.DisableSwipeTrail();
01771	
01772	          Sleep(TimeBetweenAttacks);
01773	     }
01774	     else if(AttackAction == AA_LUNGE){
01775	      //Log("State_Fighting_RandomLunge");
01776	     // Random lunge
01777	          PlayMoving();
01778	          bStopMoveIfCombatRange = false;
01779	          MoveTo(Enemy.Location - VecToEnemy * MeleeRange, MovementSpeed);
01780	          bStopMoveIfCombatRange = true;
01781	     }
01782	     else if(AttackAction == AA_STRAFE_LEFT){
01783	      //Log("State_Fighting_StrafeLeft");
01784	     // Strafe - Position is calculated in Timer, when the strafe is chosen
01785	          PlayStrafeLeft();
01786	          bStopMoveIfCombatRange = false;
01787	          StrafeFacing(Destination, Enemy);
01788	          If (DoIHaveTheBall()){
01789	            //Ignore attacks
01790	            //BroadcastMessage("Ignoring attacks in strafing Left",True);
01791	          }else{
01792	          bStopMoveIfCombatRange = true;
01793	          }
01794	     }
01795	     else if(AttackAction == AA_STRAFE_RIGHT){
01796	      //Log("State_Fighting_StrafeRight");
01797	     // Strafe - Position is calculated in Timer, when the strafe is chosen
01798	          PlayStrafeRight();
01799	          bStopMoveIfCombatRange = false;
01800	          StrafeFacing(Destination, Enemy);
01801	          If (DoIHaveTheBall()){
01802	            //Ignore attacks
01803	            //BroadcastMessage("Ignoring attacks in strafing Right",True);
01804	          }else{
01805	          bStopMoveIfCombatRange = true;
01806	          }
01807	          //bStopMoveIfCombatRange = true;
01808	     }else if(AttackAction == AA_JUMP){
01809	      //Log("State_Fighting_Jump");
01810	          //PlayFlip(0.1);
01811	          Sleep(0.05); // Sleep for a bit before making the leap
01812	          //PlaySound(JumpSound);
01813	          PlayJumping();
01814	          DoJump();
01815	          //CalcJumpVelocity();
01816	          WaitForLanding();
01817	
01818	          //RotateSark();
01819	          PlayLanded(Velocity.Z);
01820	          FinishAnim();
01821	          //PlayAnim('sark_land', 0.5, 0.0);
01822	          if(Enemy != None)
01823	            TurnToward(Enemy);
01824	          FinishAnim();
01825	     }else{
01826	      PlayWaiting();
01827	     }
01828	
01829	     if(InCombatRange(Enemy)){
01830	      Sleep(0.05);
01831	      Goto('Begin');
01832	     }
01833	  //Log("State_Fighting_Fight_End");
01834	
01835	BackFromSubState:
01836	  //Log("State Fighting_BackFromSubState");
01837	  GotoState('Charging', 'ResumeFromFighting');
01838	
01839	}
01840	
01841	
01842	
01843	
01844	
01845	//================================================
01846	//
01847	// Startup
01848	//
01849	//================================================
01850	auto State Startup{
01851	
01852	  function BeginState(){
01853	    //BroadcastMessage("Startup_BeginState",True);
01854	    //BroadcastMessage("Team:"$PlayerReplicationInfo.Team,True);
01855	    Super.BeginState();
01856	    bThrowing=False;
01857	  }
01858	     
01859	  function EndState(){
01860	    PlayerReplicationInfo.Team=SarkBallTeam;
01861	    //BroadcastMessage("Startup_EndState",True);
01862	    //BroadcastMessage("Team:"$SarkBallTeam,True);
01863	
01864	    If (SarkBallTeam==TEAM_RED){
01865	      //Red
01866	      DesiredColorAdjust.X = 128;
01867	      DesiredColorAdjust.Y = 0;
01868	      DesiredColorAdjust.Z = 0;
01869	    }else{
01870	      //Green
01871	      DesiredColorAdjust.X = 0;
01872	      DesiredColorAdjust.Y = 128;
01873	      DesiredColorAdjust.Z = 0;
01874	    }
01875	
01876	    TeamGoal=GetTeamGong();
01877	    TeamGoalLocation=TeamGoal.Location;
01878	
01879	    Super.EndState();
01880	  }
01881	
01882	
01883	}
01884	
01885	
01886	
01887	State LooseBall{
01888	  ignores SetEnemy, SeePlayer, EnemyNotVisible, HearNoise, Trigger, HeadZoneChange, FootZoneChange, ZoneChange, WarnTarget, LongFall;
01889	
01890	  Function BeginState(){
01891	    //BroadcastMessage("LooseBall_BeginState:"$Self.PlayerReplicationInfo.PlayerName,True);
01892	    bThrowing=False;
01893	  }
01894	
01895	  Function EndState(){
01896	    //BroadcastMessage("LooseBall_EndState"$Self.PlayerReplicationInfo.PlayerName,True);
01897	
01898	  }
01899	
01900	  function PickDestination(){
01901	    //MyDebug("PickDestination","Begin");
01902	    If (GR.CurrentSarkBall==None){
01903	      GotoState('Hunting','Begin');
01904	      Return;
01905	    }
01906	
01907	    //BroadcastMessage("GetOpenForPass_PickDestination:"$PlayerReplicationInfo.PlayerName,True);
01908	    IF (GR.CurrentSarkBall.CarriedBy!=None){
01909	      If (IsSameTeam(GR.CurrentSarkBall.CarriedBy)){
01910	        //BroadcastMessage(PlayerReplicationInfo.PlayerName$":Looseball_PickDestination_Goingto_GetOpenForPass",True);
01911	        GotoState('GetOpenForPass','Begin');
01912	        Return;
01913	      }else{
01914	        //BroadcastMessage(PlayerReplicationInfo.PlayerName$":Looseball_PickDestination_Goingto_EnemyHasBall",True);
01915	        GotoState('EnemyHasBall','Begin');
01916	        Return;
01917	      }
01918	
01919	    }
01920	    //BroadcastMessage("SarkBallBot_Hunting_PickDestination:"$P.Name,True);
01921	    If(ActorReachable(GR.CurrentSarkBall)){
01922	      //BroadcastMessage(PlayerReplicationInfo.PlayerName$":LooseBall_PickDestination_MovingToward_Ball",True);
01923	      MoveTarget=GR.CurrentSarkBall;
01924	    }else{
01925	      //BroadcastMessage(PlayerReplicationInfo.PlayerName$":LooseBall_PickDestination_MovingToward_BestPath",True);
01926	      If (ActorReachable(GR.CurrentSarkBall)){
01927	        MoveTarget=GR.CurrentSarkBall;
01928	        Destination=MoveTarget.Location;
01929	      }else{
01930	        If (!FindBestPathToward(GR.CurrentSarkBall)){
01931	          //BroadcastMessage("SarkBallBot_IHaveTheBall_NoBestPath:"$PlayerReplicationInfo.PlayerName,True);
01932	          MoveTarget=GR.CurrentSarkBall;
01933	          Destination=GR.CurrentSarkBall.Location;
01934	        }
01935	      }
01936	    }
01937	
01938	    //BroadcastMessage("Setting MoveTarget as gong",True);
01939	    //MoveTarget=TeamGoal;
01940	
01941	  }
01942	
01943	  function Timer(){
01944	    //BroadcastMessage("LooseBall_Timer",True);
01945	    IF (GR.CurrentSarkBall!=None && GR.CurrentSarkBall.CarriedBy!=None){
01946	      If (IsSameTeam(GR.CurrentSarkBall.CarriedBy)){
01947	        //BroadcastMessage(PlayerReplicationInfo.PlayerName$":Looseball_Goingto_GetOpenForPass",True);
01948	        GotoState('GetOpenForPass','Begin');
01949	        Return;
01950	      }else{
01951	        //BroadcastMessage(PlayerReplicationInfo.PlayerName$":Looseball_Goingto_EnemyHasBall",True);
01952	        GotoState('EnemyHasBall','Begin');
01953	        Return;
01954	      }
01955	
01956	    }
01957	  }
01958	
01959	  Function HitWall(vector HitNormal, actor Wall){
01960	    //BroadcastMessage("LooseBall_HitWall",True);
01961	    Super.Hitwall(HitNormal,Wall);
01962	    GotoState('LooseBall','GoAfterBall');
01963	  }
01964	
01965	
01966	Begin:
01967	  //BroadcastMessage("LooseBall_Begin:"$Self.PlayerReplicationInfo.PlayerName,True);
01968	  SetTimer(0.25, true);
01969	
01970	
01971	GoAfterBall:
01972	  //BroadcastMessage("LooseBall_GoAfterBall:"$Self.PlayerReplicationInfo.PlayerName,True);
01973	  //Log("LooseBall_GoAfterBall");
01974	  PickDestination();
01975	  PlayTurning();
01976	  TurnToward(MoveTarget);
01977	  PlayMoving();
01978	  //MoveTarget=GR.CurrentSarkBall;
01979	  MoveToward(MoveTarget);
01980	  Sleep(0.1);
01981	  Goto('Begin');
01982	
01983	
01984	}
01985	
01986	
01987	State EnemyHasBall{
01988	  //ignores SetEnemy, SeePlayer, EnemyNotVisible, HearNoise, Trigger, HeadZoneChange, FootZoneChange, ZoneChange, WarnTarget, LongFall;
01989	
01990	  Function BeginState(){
01991	    //BroadcastMessage("EnemyHasBall_BeginState:"$Self.PlayerReplicationInfo.PlayerName,True);
01992	    bThrowing=False;
01993	
01994	  }
01995	
01996	  Function EndState(){
01997	    //BroadcastMessage("EnemyHasBall_EndState:"$Self.PlayerReplicationInfo.PlayerName,True);
01998	  }
01999	
02000	  function Timer(){
02001	    //BroadcastMessage("EnemyHasBall_Timer:"$Self.PlayerReplicationInfo.PlayerName,True);
02002	
02003	    //GetEnemyProximity();
02004	    CheckForThrowing(Enemy);
02005	
02006	    If (InCombatRange(Enemy)){
02007	      //BroadcastMessage("EnemyHasBall_InRange_Goto_Fighting",True);
02008	      GotoState('Fighting','Begin');
02009	    }
02010	  }
02011	
02012	  Function HitWall(vector HitNormal, actor Wall){
02013	    //BroadcastMessage("EnemyHasBall_HitWall",True);
02014	
02015	    Super.Hitwall(HitNormal,Wall);
02016	    GotoState('EnemyHasBall','GoAfterPlayerWithBall');
02017	  }
02018	
02019	  Function CheckForThrowing(Pawn Other){
02020	
02021	    If (bThrowing) Return;
02022	    If (Other==None) Return;
02023	    If (Weapon==None) Return;
02024	
02025	    //BroadcastMessage("CheckForThrowing_Name:"$Other.PlayerReplicationInfo.PlayerName$",MeleeRange:"$MeleeRange,True);
02026	    If (VSize(Other.Location-Location)>CombatRange){
02027	      //MyDebug("CheckForThrowing","Other is Far Enough Away");
02028	      If (Weapon.ISA('Axe') || Weapon.ISA('DwarfBattleHammer')){
02029	        //MyDebug("CheckForThrowing","I Have an Axe");
02030	        //BroadcastMessage("Hunting_CheckForThrowing_Throwing Axe at player with SarkBall",True);
02031	        //BroadcastMessage("CheckForThrowing_GoingToHunting:"$self.PlayerReplicationInfo.PlayerName,True);
02032	        GotoState('EnemyHasBall','ThrowWeaponAtPlayer');
02033	        Return;
02034	        //OrderObject=Other;
02035	        //DoThrow();
02036	      }else{
02037	        //If (!bAxeUsed){
02038	        //MyDebug("CheckForThrowing","Need to Switch to an Axe");
02039	        SwitchToBattleAxe();
02040	        // bAxeUsed=True;
02041	        //}
02042	      }
02043	    }else{
02044	      If (!Weapon.ISA('BroadSword')){
02045	        GotoState('EnemyHasBall','DrawBroadSword');
02046	        Return;
02047	      }
02048	    }
02049	  }
02050	
02051	  function PickDestination(){
02052	    local Actor P;
02053	    local float Dist;
02054	    local Pawn PlayerWithTheBall;
02055	    local Pawn Other;
02056	
02057	    //MyDebug("PickDestination","Begin");
02058	
02059	    //BroadcastMessage("EnemyHasBall_PickDestination:"$PlayerReplicationInfo.PlayerName,True);
02060	    HuntTime = 9999;
02061	
02062	    If (GR.CurrentSarkBall==None){
02063	      GotoState('Hunting','Begin');
02064	      Return;
02065	    }
02066	
02067	    //BroadcastMessage("SarkBallBot_Hunting_PickDestination:"$P.Name,True);
02068	    If (ActorReachable(GR.CurrentSarkBall)){
02069	        MoveTarget=GR.CurrentSarkBall;
02070	        Destination=MoveTarget.Location;
02071	    }else{
02072	      If (!FindBestPathToward(GR.CurrentSarkBall)){
02073	          //BroadcastMessage("SarkBallBot_IHaveTheBall_NoBestPath:"$PlayerReplicationInfo.PlayerName,True);
02074	          MoveTarget=GR.CurrentSarkBall;
02075	          Destination=GR.CurrentSarkBall.Location;
02076	      }
02077	    }
02078	  }
02079	
02080	
02081	Begin:
02082	
02083	  //BroadcastMessage("EnemyHasBall_Begin:"$Self.PlayerReplicationInfo.PlayerName,True);
02084	  SetTimer(0.25, true);
02085	  SetEnemy(GR.CurrentSarkBall.CarriedBy);
02086	  //BroadcastMessage("EnemyHasBall_NewEnemy:"$Enemy.PlayerReplicationInfo.PlayerName,True);
02087	
02088	
02089	GoAfterPlayerWithBall:
02090	  //BroadcastMessage("EnemyHasBall_GoAfterBall:"$Self.PlayerReplicationInfo.PlayerName,True);
02091	  //Log("EnemyHasBall_GoAfterPlayerWithBall");
02092	  PlayTurning(0.1);
02093	  TurnToward(Enemy);
02094	  PlayMoving();
02095	  PickDestination();
02096	  //MoveTarget=Enemy;
02097	  bStopMoveIfCombatRange=True;
02098	  MoveToward(MoveTarget);
02099	  Sleep(0.1);
02100	  Goto('GoAfterPlayerWithBall');
02101	
02102	ThrowWeaponAtPlayer:
02103	  //Log("State_Hunting_ThrowWeaponAtPlayer");
02104	  bThrowing=True;
02105	  //BroadcastMessage("Throw Axe at Player With Ball",True);
02106	  PlayTurning();
02107	  TurnToward(GR.CurrentSarkBall.CarriedBy);
02108	  PlayThrowing();
02109	  //PlayAnim(self.weapon.A_Throw, 1.0, 0.1);
02110	  Sleep(0.2);
02111	  OrderObject=GR.CurrentSarkBall.CarriedBy;
02112	  ThrowWeapon();
02113	  //DoThrow();
02114	  FinishAnim();
02115	  bThrowing=False;
02116	  Sleep(0.1);
02117	  //BroadcastMessage("Done Throwing Axe at Player With Ball",True);
02118	  Goto('DrawBroadsword');
02119	
02120	DrawBroadsword:
02121	  //log("State_Hunting_DrawBroadsword");
02122	  //BroadcastMessage("Draw Broadsword",True);
02123	  If (Weapon!=None && Weapon.ISA('SarkBall')){
02124	    //BroadcastMessage("DrawBroadSword_Still Have Ball!",True);
02125	  }
02126	
02127	  //If (!SarkBallGame(level.Game).bRoundOver){
02128	  //PendingWeapon=Spawn(Class'RuneI.SarkBallBroadSword');
02129	  //AddInventory(PendingWeapon);
02130	  //AcquireInventory(PendingWeapon);
02131	  //ChangedWeapon();
02132	
02133	  DrawPrimaryWeapon();
02134	  //}
02135	
02136	  //Weapon=NewWeapon;
02137	  //Weapon.GotoState('Active');
02138	  bThrowing=False;
02139	  Goto('Begin');
02140	
02141	}
02142	
02143	State ThrowTheBall{
02144	  ignores SetEnemy, SeePlayer, EnemyNotVisible, HearNoise, Trigger, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, LongFall, Landed;
02145	
02146	  Function BeginState(){
02147	    //BroadcastMessage("ThrowTheBall_BeginState:"$Self.PlayerReplicationInfo.PlayerName,True);
02148	    bThrowing=False;
02149	  }
02150	
02151	  Function EndState(){
02152	    //BroadcastMessage("ThrowTheBall_EndState:"$Self.PlayerReplicationInfo.PlayerName,True);
02153	
02154	  }
02155	
02156	ThrowBallAtGoal:
02157	
02158	  If (CheckForPlayerInFront(TeamGoal)!=None){
02159	    //BroadcastMessage("ThrowBallAtGoal_PlayerWouldBlockShot",True);
02160	    //Sleep(0.1);
02161	    GotoState('IHaveTheBall','EnemyInProximity');
02162	
02163	  }
02164	  bThrowing=True;
02165	  //BroadcastMessage("ThrowTheBall_Throw Ball at Goal",True);
02166	  //PlayThrowing();
02167	  PlayAnim(Weapon.A_Throw, 1.0, 0.1);
02168	
02169	  bHasSarkBall=False;
02170	  GR.ThrowingPlayer=Self;
02171	
02172	  Sleep(0.2);
02173	  OrderObject=TeamGoal;
02174	  DoThrow();
02175	
02176	  FinishAnim();
02177	  bThrowing=False;
02178	  Sleep(0.2);
02179	  //BroadcastMessage("ThrowBallAtGoal_GotoHunting_DrawBroadSword",True);
02180	  GotoState('Hunting','DrawBroadsword');
02181	
02182	}
02183	
02184	
02185	State IHaveTheBall{
02186	  ignores Touch,SetEnemy;
02187	
02188	  Function BeginState(){
02189	    //BroadcastMessage("IHaveTheBall_BeginState:"$self.playerreplicationinfo.playername,True);
02190	    bThrowing=False;
02191	  }
02192	
02193	  Function EndState(){
02194	   //BroadcastMessage("IHaveTheBall_EndState:"$self.playerreplicationinfo.playername,True);
02195	
02196	
02197	  }
02198	
02199	  function bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint){
02200	    local bool rtn;
02201	
02202	    //BroadcastMessage("SarkBallBot_IHaveTheBall_JointDamaged By:"$EventInstigator.Name,True);
02203	    NextStateAfterPain='EnemyInProximity';
02204	    rtn=Super.JointDamaged(Damage,EventInstigator,HitLoc,Momentum,DamageType,joint);
02205	
02206	
02207	    //GotoState('IHaveTheBall','EnemyInProximity');
02208	    Return(rtn);
02209	
02210	  }
02211	
02212	  function Tick(float DeltaTime){
02213	    Super.Tick(DeltaTime);
02214	    CheckForThrowAtGoal();
02215	
02216	    If (bHidden) bHidden=False;
02217	  }
02218	
02219	
02220	
02221	  function PickDestination(){
02222	    local Actor P;
02223	    local float Dist;
02224	    local Pawn PlayerWithTheBall;
02225	    local Pawn Other;
02226	
02227	    //MyDebug("PickDestination","Begin");
02228	
02229	    //BroadcastMessage("IHaveTheBall_PickDestination:"$Name$":PickDestination",True);
02230	    HuntTime = 9999;
02231	
02232	      //MyDebug("PickDestination","I Have The Ball");
02233	      CheckForThrowAtGoal();
02234	
02235	       //BroadcastMessage("SarkBallBot_Hunting_PickDestination:"$P.Name,True);
02236	     If (ActorReachable(TeamGoal) || CanSee(TeamGoal)){
02237	        //BroadcastMessage("SarkBallBot_IHaveTheBall_PickDestination:"$PlayerReplicationInfo.PlayerName,True);
02238	        MoveTarget=TeamGoal;
02239	        Destination=TeamGoal.Location;
02240	      }else{
02241	        //BroadcastMessage("SarkBallBot_IHaveTheBall_BestPath:"$PlayerReplicationInfo.PlayerName,True);
02242	        If (!FindBestPathToward(TeamGoal)){
02243	          //BroadcastMessage("SarkBallBot_IHaveTheBall_NoBestPath:"$PlayerReplicationInfo.PlayerName,True);
02244	          MoveTarget=TeamGoal;
02245	          Destination=TeamGoal.Location;
02246	        }
02247	      }
02248	  }
02249	
02250	  //------------------------------------------------
02251	//
02252	// Global Landed
02253	//
02254	//------------------------------------------------
02255	  function Landed(vector HitNormal, actor HitActor){
02256	  local Actor Gong;
02257	  If (HitActor.ISA('LevelInfo')){
02258	    //BroadcastMessage("SarkBallBot_IHaveTheBall_Landed onlevel info:"$HitActor.name$"State:"$GetStateName(),true);
02259	    SetPhysics(Phys_Falling);
02260	  }else{
02261	    //BroadcastMessage("SarkBallBot_IHaveTheBall_Landed:"$HitActor.name$"State:"$GetStateName(),true);
02262	    Super.Landed(HitNormal, HitActor);
02263	    bJumping=False;
02264	    GotoState('IHaveTheBall','LookForGoal');
02265	  }
02266	
02267	
02268	
02269	
02270	  }
02271	
02272	  //------------------------------------------------
02273	  //
02274	  // IHaveTheBall_SeePlayer
02275	  //
02276	  //------------------------------------------------
02277	  function SeePlayer(actor seen){
02278	    local float dist;
02279	    local Pawn SeenPawn;
02280	    local Actor TeamGong;
02281	
02282	    //MyDebug("SeePlayer",string(seen.Name));
02283	    SeenPawn=Pawn(seen);
02284	    If (IsSameTeam(SeenPawn)){
02285	      CheckForThrowToPlayer(SeenPawn);
02286	      Return;
02287	    }
02288	
02289	    if (AngleTo(seen.Location) < ANGLE_45){
02290	      //DesiredRotation.Yaw = Rotator(Destination - Location).Yaw;
02291	      //PlayTurning();
02292	      //FinishAnim();
02293	        //BroadcastMessage("In front of me:"$seen.name$",Angle:"$AngleTo(seen.Location),True);
02294	      If (!IsSameTeam(Pawn(Seen)) && VSize(self.location-seen.location)<300){
02295	        If (!bJumping && !bThrowing){
02296	        //BroadcastMessage("GOTO EnemyInProximity:"$AngleTo(seen.Location),True);
02297	        GotoState('IHaveTheBall','EnemyInProximity');
02298	        }
02299	      }
02300	    }
02301	
02302	  }
02303	
02304	  Function HitWall(vector HitNormal, actor Wall){
02305	    //BroadcastMessage("IHaveBall_HitWall",True);
02306	
02307	    Super.Hitwall(HitNormal,Wall);
02308	    GotoState('IHaveTheBall','DriveForGoal');
02309	  }
02310	
02311	
02312	Begin:
02313	
02314	PickedUp:
02315	  //BroadcastMessage("IHaveTheBall_PickedUp",True);
02316	  bHasSarkBall=True;
02317	
02318	  Sleep(0.1);
02319	  Goto('LookForGoal');
02320	
02321	
02322	AvoidEnemies:
02323	
02324	DriveForGoal:
02325	 //BroadcastMessage("IHaveTheBall_DriveForGoal:"$self.PlayerReplicationInfo.PlayerName,True);
02326	
02327	  //If (IsEnemyInProximity())
02328	  //  Goto('EnemyInProximity');
02329	
02330	  //PlayTurning();
02331	  //TurnToward(TeamGoal);
02332	
02333	  PickDestination();
02334	
02335	  //LookToward(TeamGoal);
02336	
02337	  // Turn to Destination
02338	  //BroadcastMessage("Before Check Turning Toward Team",True);
02339	  if (AngleTo(Destination) > ANGLE_45){
02340	    //BroadcastMessage("Turning Toward Team",True);
02341	    //DesiredRotation.Yaw = Rotator(Destination - Location).Yaw;
02342	    PlayTurning();
02343	    TurnToward(TeamGoal);
02344	    FinishAnim();
02345	  }
02346	
02347	
02348	  //If (!ActorReachable(TeamGoal)){
02349	    //BroadcastMessage("Goal not reachable:"$self.playerreplicationinfo.playername,True);
02350	    //Goto('EnemyInProximity');
02351	  //}
02352	  //TweenToMoving(0.05);
02353	  //WaitForLanding();
02354	  //FinishAnim();
02355	
02356	  //BroadcastMessage("Base.z:"$Base.location.Z$","$self.playerreplicationinfo.playername,True);
02357	  //BroadcastMessage("me.z"$location.z$","$self.playerreplicationinfo.playername,True);
02358	
02359	  Belowme.X=location.x;
02360	  Belowme.Y=location.y;
02361	  Belowme.Z=location.z-50;
02362	
02363	  //If (FastTrace(Belowme,Location)){
02364	  //  BroadcastMessage("Not on ground:"$self.playerreplicationinfo.playername,True);
02365	 //   SetPhysics(PHYS_Falling);
02366	  //  WaitForLanding();
02367	  //}
02368	
02369	
02370	  if ( (Base != Level) && (Base != None) ){
02371	    //BroadcastMessage("Base != Level:"$self.playerreplicationinfo.playername,True);
02372	    //SetPhysics(PHYS_Falling);
02373	  }
02374	
02375	      //Velocity.Z += Base.Velocity.Z;
02376	
02377	
02378	
02379	  //BroadcastMessage("Before PlayMoving",True);
02380	  PlayMoving();
02381	  //StopLookingToward();
02382	  //BroadcastMessage("After PlayMoving",True);
02383	  Goto('SpecialNavig');
02384	
02385	SpecialNavig:
02386	  //BroadcastMessage("IHaveTheBall_SpecialNavig:"$MoveTarget,True);
02387	
02388	  if (MoveTarget == None){
02389	    //BroadcastMessage("IHaveTheBall_SpecialNavig_MoveTo:"$MoveTarget,True);
02390	    MoveTo(Destination, MovementSpeed);
02391	  }else{
02392	    //BroadcastMessage("IHaveTheBall_SpecialNavig_MoveToward:"$MoveTarget$",StopMoving:"$bStopMoveIfCombatRange$",Speed:"$MovementSpeed,True);
02393	
02394	    bStopMoveIfCombatRange=False;
02395	    MoveToward(MoveTarget, MovementSpeed);
02396	          
02397	    // Look down some paths if not a straight shot
02398	    if ((!bGlider) &&
02399	      MaxStopWait > 0 &&
02400	      NavigationPoint(MoveTarget) != None &&
02401	      NavigationPoint(MoveTarget).NumPaths() > 2 &&
02402	      NavigationPoint(MoveTarget) != LastNodeVisited &&
02403	      FRand() > 0.8){
02404	
02405	      //BroadcastMessage("IHaveTheBall_SpecialNavig_LookDownPaths:"$MoveTarget,True);
02406	      TweenToHuntStop(0.3);
02407	      Acceleration = vect(0,0,0);
02408	      FinishAnim();
02409	          
02410	      lookindex = 0;
02411	      while (lookIndex < NavigationPoint(MoveTarget).NumPaths()){
02412	        //BroadcastMessage("IHaveTheBall_SpecialNavig_NumPaths:"$MoveTarget,True);
02413	        PlayHuntStop();
02414	        SoundChance(RoamSound, 0.3);
02415	        LookAtEndPoint(lookIndex);
02416	        lookIndex++;
02417	        Sleep(RandRange(MinStopWait, MaxStopWait));
02418	        FinishAnim();
02419	      }
02420	    }
02421	    LastNodeVisited     = NavigationPoint(MoveTarget);
02422	  }
02423	     
02424	
02425	LookForGoal:
02426	
02427	  //BroadcastMessage("IHaveTheBall_LookForGoal",True);
02428	
02429	  CheckForThrowAtGoal();
02430	
02431	  Sleep(0.05);
02432	  //BroadcastMessage("IHaveTheBall_GoingTo_DriveForGoal",True);
02433	  //GotoState('Hunting','Hunt');
02434	  Goto('DriveForGoal');
02435	
02436	ThrowBallAtGoal:
02437	  //BroadcastMessage("IHaveTheBall_Throw Ball at Goal",True);
02438	  bThrowing=True;
02439	
02440	  PlayTurning();
02441	  TurnToward(TargetPlayer);
02442	  PlayAnim(Weapon.A_Throw, 1.0, 0.1);
02443	
02444	  bHasSarkBall=False;
02445	  GR.ThrowingPlayer=Self;
02446	
02447	  Sleep(0.1);
02448	  OrderObject=TeamGoal;
02449	  DoThrow();
02450	
02451	  FinishAnim();
02452	  bThrowing=False;
02453	  //BroadcastMessage("IHaveTheBall_Goto_Hunting_DrawBroadsword",True);
02454	  GotoState('Hunting','DrawBroadsword');
02455	
02456	
02457	ThrowBallToPlayer:
02458	  bThrowing=True;
02459	  //BroadcastMessage("Throw Ball at Player",True);
02460	  PlayTurning();
02461	  TurnToward(TargetPlayer);
02462	  PlayAnim(Weapon.A_Throw, 1.0, 0.1);
02463	
02464	  bHasSarkBall=False;
02465	  GR.ThrowingPlayer=Self;
02466	
02467	  Sleep(0.1);
02468	  OrderObject=TargetPlayer;
02469	  DoThrow();
02470	
02471	  FinishAnim();
02472	  bThrowing=False;
02473	  //Log("Hunting_Throwballtoplayer_DrawBroadSword");
02474	  GotoState('Hunting','DrawBroadsword');
02475	
02476	EnemyInProximity:
02477	  If (bJumping) {
02478	    //BroadcastMessage("IHaveTheBall_EnemyInProximity_Detected already jumping_goingto_lookforgoal",True);
02479	    Goto('LookForGoal');
02480	  }
02481	
02482	  //BroadcastMessage("EnemyInProximity_Anim:"$AnimSequence,True);
02483	  //BroadcastMessage("Performing Enemy in Proximity:"$self.playerreplicationinfo.playername,True);
02484	  //PlayJump();
02485	  bJumping=True;
02486	  PlayJumping();
02487	  //Sleep(0.1); // Sleep for a bit before making the leap
02488	  //PlaySound(JumpSound);
02489	  //CalcJumpVelocity();
02490	  //Velocity.Z = 1000;
02491	  bThrowing=False;
02492	
02493	  DoJump();
02494	
02495	
02496	  WaitForLanding();
02497	  bJumping=False;
02498	  //Log("IHaveTheBall_EnemyInProximity_AfterWaitForLanding");
02499	
02500	  //RotateSark();
02501	  //PlayAnim('sark_land', 0.1, 0.0);
02502	  //if(Enemy != None)
02503	
02504	
02505	
02506	
02507	  //TurnToward(GetTeamGong());
02508	  //Destination=GoalLocation();
02509	
02510	  //FinishAnim();
02511	  //BroadcastMessage("IHaveTheBall_EnemyInProximity_GoingTo_LookForGoal",True);
02512	  Goto('LookForGoal');
02513	
02514	
02515	
02516	}
02517	
02518	
02519	
02520	//================================================
02521	//
02522	// Hunting
02523	//
02524	//================================================
02525	State Hunting{
02526	
02527	  function BeginState(){
02528	    bThrowing=False;
02529	    If (Weapon!=None && Weapon.ISA('SarkBall') && GR.CurrentSarkBall!=None && GR.ThrowingPlayer!=Self){
02530	      //BroadcastMessage("Hunting_BeginState_WithBall:"$self.playerreplicationinfo.playername,True);
02531	      GotoState('IHaveTheBall','LookForGoal');
02532	      Return;
02533	    }
02534	    bHurrying = true;
02535	    UpdateMovementSpeed();
02536	    bAvoidLedges = true;
02537	
02538	  }
02539	
02540	  function EndState(){
02541	    bHunting = false;
02542	    bAvoidLedges = false;
02543	    if ( JumpZ > 0 )
02544	      bCanJump = true;
02545	  }
02546	
02547	  function HearNoise(float Loudness, Actor NoiseMaker){
02548	    if ( SetEnemy(NoiseMaker.instigator) )
02549	      LastSeenPos = Enemy.Location;
02550	  }
02551	
02552	  function TryChargeEnemy(){
02553	    DesiredRotation = Rotator(Enemy.Location - Location);
02554	    if (actorReachable(Enemy))
02555	      GotoState('Charging');
02556	    }
02557	
02558	  function HitWall(vector HitNormal, actor Wall){
02559	    //BroadcastMessage("Hunting_HitWall",True);
02560	
02561	    global.HitWall(HitNormal, Wall);
02562	    if (Physics == PHYS_Falling)
02563	      return;
02564	    if ( Wall.IsA('Mover') && Mover(Wall).HandleDoor(self) ){
02565	      GotoState('Hunting', 'SpecialNavig');
02566	      return;
02567	    }
02568	    If (GR.CurrentSarkBall==None){
02569	      GotoState('Hunting','Begin');
02570	      Return;
02571	    }
02572	
02573	    //Log("Hunting_HitWall_Check1");
02574	    If (GR.CurrentSarkBall.CarriedBy==None){
02575	        //BroadcastMessage("Hunting_HitWall_GoingTo_LooseBall",True);
02576	        GotoState('LooseBall','Begin');
02577	        Return;
02578	    }else{
02579	      IF (IsSameTeam(GR.CurrentSarkBall.CarriedBy)){
02580	        //BroadcastMessage("Hunting_HitWall_GoingTo_GetOpenForPass",True);
02581	        GotoState('GetOpenForPass','Begin');
02582	        Return;
02583	      }else{
02584	        //BroadcastMessage("Hunting_HitWall_GoingTo_EnemyHasBall",True);
02585	        GotoState('EnemyHasBall','Begin');
02586	        Return;
02587	      }
02588	    }
02589	    //Log("Hunting_HitWall_AfterCheckBall");
02590	
02591	    Focus = Destination;
02592	    if (PickWallAdjust())
02593	      GotoState('Hunting', 'AdjustFromWall');
02594	    else
02595	      MoveTimer = -1.0;
02596	
02597	  }
02598	
02599	  function MayFall(){
02600	    // Only jump if reachable
02601	    if (intelligence==BRAINS_None)
02602	      bCanJump = true;
02603	    else if (MoveTarget!=None)
02604	      bCanJump = actorReachable(MoveTarget);
02605	    else if (Enemy!=None)
02606	      bCanJump = actorReachable(Enemy);
02607	//          if (bFrustrated)
02608	//               bCanJump = true;
02609	     }
02610	
02611	
02612	  function PickDestination(){
02613	    local Actor P;
02614	    local float Dist;
02615	    local Pawn PlayerWithTheBall;
02616	    local Pawn Other;
02617	
02618	    //MyDebug("PickDestination","Begin");
02619	
02620	    //BroadcastMessage(PlayerReplicationInfo.PlayerName$":Hunting_PickDestination",True);
02621	    HuntTime = 9999;
02622	    If (GR.CurrentSarkBall!=None){
02623	      PlayerWithTheBall=GR.CurrentSarkBall.CarriedBy;
02624	      //MyDebug("PickDestination","After Getting PlayerWithPossession");
02625	      If (PlayerWithTheBall!=None){
02626	        If (IsSameTeam(PlayerWithTheBall)){
02627	          GotoState('GetOpenForPass','Begin');
02628	          Return;
02629	        }else{
02630	          GotoState('EnemyHasBall','Begin');
02631	          Return;
02632	        }
02633	      }else{
02634	        GotoState('LooseBall','Begin');
02635	        Return;
02636	      }
02637	    }
02638	
02639	
02640	  }
02641	
02642	  function bool CheckJumpLocation()
02643	     {          
02644	          local vector start, end;
02645	          local vector extent;
02646	          local vector HitLocation, HitNormal;
02647	
02648	          if(Enemy == None)
02649	               return(false);
02650	
02651	          extent.X = CollisionRadius;
02652	          extent.Y = CollisionRadius;
02653	          extent.Z = CollisionHeight * 0.5;
02654	
02655	          JumpDestination = Enemy.Location - Location;
02656	          JumpDestination.Z = 0;
02657	          JumpDestination = Enemy.Location + Normal(JumpDestination);
02658	
02659	          start = Location;
02660	          end = ((JumpDestination + start) / 2) + vect(0, 0, 280);
02661	
02662	          DebugJumpApex = end;
02663	          DebugJumpLand = JumpDestination;
02664	
02665	          // Trace to check if the jump is valid
02666	          if(Trace(HitLocation, HitNormal, end, start, true, extent) == None)
02667	          { // Nothing on the way up, check going down
02668	               start = end;
02669	               end = JumpDestination;
02670	
02671	               if(Trace(HitLocation, HitNormal, end, start, true, extent) == None)
02672	               { // Nothing on the way back down, check to make sure that the Sark will land on valid ground
02673	                    start = JumpDestination;
02674	                    end = JumpDestination - vect(0, 0, 100);
02675	
02676	                    if(Trace(HitLocation, HitNormal, end, start, false) == None)
02677	                    { // Not going to land on anything, so don't do the jump
02678	                         return(false);
02679	                    }
02680	
02681	                    // Otherwise, the jump is good!
02682	                    return(true);
02683	               }
02684	               DebugJumpLand = HitLocation;
02685	          }
02686	
02687	          return(false);
02688	     }
02689	
02690	  function CalcJumpVelocity(){
02691	          local float traj;
02692	          local vector arcVel;
02693	
02694	          traj = 70 * 65536 / 360;
02695	
02696	          // JumpDestination is calculated in CheckJumpLocation
02697	          arcVel = CalcArcVelocity(traj, Location, JumpDestination);
02698	
02699	          AddVelocity(arcVel);
02700	  }
02701	
02702	  function Tick(float DeltaTime){
02703	    local Actor P;
02704	    local float Dist;
02705	    local Pawn PlayerWhoHasTheBall;
02706	    local Pawn ThrowingPlayer;
02707	
02708	    If (bHidden) bHidden=False;
02709	
02710	    If (Weapon!=None){
02711	      If (Weapon.ISA('SarkBall')){
02712	        //BroadcastMessage("Tick1_Gotostate_IHaveTheBall_PickedUp"$Self.PlayerReplicationInfo.PlayerName,True);
02713	        GotoState('IHaveTheBall','PickedUp');
02714	        Return;
02715	      }
02716	    }
02717	
02718	
02719	    PlayerWhoHasTheBall=GR.PlayerWithPossession;
02720	
02721	      If (Enemy==None && PlayerWhoHasTheBall!=None){
02722	          If (!IsSameTeam(PlayerWhoHasTheBall)){
02723	            //BroadcastMessage("My Guy has the ball:"$GR.PlayerWithPossession.PlayerReplicationInfo.PlayerName,True);
02724	            //If (VSize(TeamGoalLocation-Location)>300){
02725	              //Destination=TeamGoalLocation;
02726	            //}else{
02727	              //GotoState('Hunt');
02728	            //}
02729	          //}else{
02730	            //BroadcastMessage("Look:"$GR.PlayerWithPossession.PlayerReplicationInfo.Team,True);
02731	            CheckForThrowing(PlayerWhoHasTheBall);
02732	            SetEnemy(PlayerWhoHasTheBall);
02733	          }
02734	      }
02735	
02736	      Super.Tick(DeltaTime);
02737	
02738	      ThrowingPlayer=Pawn(GR.ThrowingPlayer);
02739	      If (ThrowingPlayer!=None && MoveTarget!=GR.CurrentSarkBall && GR.ThrowingPlayer!=Self){
02740	        //Log(Self.Name$":Hunting_ThrowingPlayer!=None and MoveTarget not SarkBall");
02741	
02742	        GotoState('LooseBall','Begin');
02743	        Return;
02744	      }
02745	
02746	  }
02747	
02748	
02749	
02750	
02751	
02752	  //BroadcastMessage("SarkBallBot_Hunting_Tick:"$GetStateName(),True);
02753	
02754	
02755	
02756	
02757	 //function TouchSurroundingObjects(Actor Other)
02758	   //  {
02759	     //BroadcastMessage("SarkBallBot_TouchSurroundigObjects:"$Other.Name,True);
02760	     //Super.TouchSurroundingObjects(Actor Other);
02761	     //}
02762	
02763	AdjustFromWall:
02764	  //Log("State_Hunting_AdjustFromWall:");
02765	     PlayMoving();     //todo: determine direction and play strafing
02766	     StrafeTo(Destination, Focus);
02767	     Destination = Focus;
02768	     if ( MoveTarget != None )
02769	          Goto('SpecialNavig');
02770	     else
02771	          Goto('Follow');
02772	
02773	Begin:
02774	  //Log("State_Hunting_Begin:");
02775	     if(debugstates) SLog(name@"Hunting");
02776	     Acceleration=vect(0,0,0);
02777	
02778	Hunt:
02779	  //Log("State_Hunting_Hunt:");
02780	     numHuntPaths = 0;
02781	     HuntStartTime = Level.TimeSeconds;
02782	
02783	AfterFall:
02784	  //Log("State_Hunting_AfterFall:");
02785	     TweenToMoving(0.15);
02786	     bFromWall = false;
02787	     FinishAnim();
02788	  //Log("State_Hunting_AfterFall_END:");
02789	
02790	Follow:
02791	  //Log("State_Hunting_Follow");
02792	  If (Weapon==None){
02793	    //Log("Hunting_Follow_Goto_DrawBroadsword");
02794	    Goto('DrawBroadSword');
02795	  }
02796	
02797	  //WaitForLanding();
02798	  If (Enemy==None){
02799	    //BroadcastMessage("Hunting_Follow_NoEnemy",True);
02800	  }else{
02801	    //BroadcastMessage("Hunting_Follow_Enemy:"$Enemy.Name,True);
02802	    if ( CanSee(Enemy) )
02803	      TryChargeEnemy();     // Exit to charge
02804	  }
02805	
02806	  PickDestination();
02807	
02808	  //pointReachable(Destination)
02809	  //actorReachable(MoveTarget)
02810	
02811	  //MyDebug("State Hunting_Follow","After PickDestination");
02812	  LookToward(Destination);
02813	
02814	     // Turn to Destination
02815	     if (AngleTo(Destination) > ANGLE_45){
02816	          DesiredRotation.Yaw = Rotator(Destination - Location).Yaw;
02817	          PlayTurning();
02818	          FinishAnim();
02819	     }
02820	
02821	
02822	     TweenToMoving(0.15);
02823	     WaitForLanding();
02824	     FinishAnim();
02825	     PlayMoving();
02826	     StopLookingToward();
02827	
02828	SpecialNavig:
02829	  //Log("State_Hunting_SpecialNavig");
02830	     if (MoveTarget == None){
02831	      //Log("State_Hunting_MoveTarget is none");
02832	      MoveTo(Destination, MovementSpeed);
02833	     }else{
02834	      //Log("State_Hunting_MoveToward");
02835	      MoveToward(MoveTarget, MovementSpeed);
02836	          
02837	          // Look down some paths if not a straight shot
02838	          if ((!bGlider) &&
02839	               MaxStopWait > 0 &&
02840	               NavigationPoint(MoveTarget) != None &&
02841	               NavigationPoint(MoveTarget).NumPaths() > 2 &&
02842	               NavigationPoint(MoveTarget) != LastNodeVisited &&
02843	               FRand() > 0.8)
02844	          {
02845	               TweenToHuntStop(0.3);
02846	               Acceleration = vect(0,0,0);
02847	               FinishAnim();
02848	          
02849	               lookindex = 0;
02850	               while (lookIndex < NavigationPoint(MoveTarget).NumPaths())
02851	               {
02852	                    PlayHuntStop();
02853	                    SoundChance(RoamSound, 0.3);
02854	                    LookAtEndPoint(lookIndex);
02855	                    lookIndex++;
02856	                    Sleep(RandRange(MinStopWait, MaxStopWait));
02857	                    FinishAnim();
02858	               }
02859	          }
02860	          
02861	          LastNodeVisited     = NavigationPoint(MoveTarget);
02862	     }
02863	     
02864	     //Log("State_Hunting_SpecialNavig_End");
02865	     Goto('Follow');
02866	
02867	
02868	DrawBroadsword:
02869	  //log("State_Hunting_DrawBroadsword");
02870	  //BroadcastMessage("Draw Broadsword",True);
02871	  If (Weapon!=None && Weapon.ISA('SarkBall')){
02872	    //BroadcastMessage("DrawBroadSword_Still Have Ball!",True);
02873	  }
02874	
02875	  //If (!SarkBallGame(level.Game).bRoundOver){
02876	  //PendingWeapon=Spawn(Class'RuneI.SarkBallBroadSword');
02877	  //AddInventory(PendingWeapon);
02878	  //AcquireInventory(PendingWeapon);
02879	  //ChangedWeapon();
02880	
02881	  DrawPrimaryWeapon();
02882	  //}
02883	
02884	  //Weapon=NewWeapon;
02885	  //Weapon.GotoState('Active');
02886	  bThrowing=False;
02887	  Goto('Hunt');
02888	
02889	
02890	
02891	ThrowWeaponAtPlayer:
02892	  //Log("State_Hunting_ThrowWeaponAtPlayer");
02893	  bThrowing=True;
02894	  //BroadcastMessage("Throw Axe at Player",True);
02895	  PlayAnim(Weapon.A_Throw, 1.0, 0.1);
02896	  Sleep(0.2);
02897	  OrderObject=GR.PlayerWithPossession;
02898	  DoThrow();
02899	  FinishAnim();
02900	  bThrowing=False;
02901	
02902	  Goto('DrawBroadsword');
02903	Finish:
02904	  //Log("State_Hunting_Finish");
02905	}
02906	
02907	//=============================================================================
02908	//
02909	// PlayJump
02910	//
02911	//=============================================================================
02912	
02913	function PlayJump()
02914	{
02915	     local name anim;
02916	
02917	     if(Weapon != None && Weapon.A_Jump != '')
02918	          anim = Weapon.A_Jump;
02919	     else
02920	          anim = 'MOV_ALL_jump1_AA0S';
02921	     
02922	     PlayAnim(anim, 1.0, 0.1);
02923	
02924	     if(AnimProxy != None)
02925	          AnimProxy.TryPlayAnim(anim, 1.0, 0.1);
02926	
02927	     // Play Jump Grunt Sound
02928	     //PlaySoun(JumpGruntSound[Rand(3)], SLOT_Talk, 1.0, false, 1200, FRand() * 0.08 + 0.96);
02929	}
02930	
02931	Function PlayTaunting(optional float tween)   { PlayAnim  ('s3_taunt',               1.0, tween);   }
02932	
02933	//=============================================================================
02934	//
02935	// PlayMoving
02936	//
02937	//=============================================================================
02938	
02939	function PlayMoving(optional float tween){
02940	     local name LowerName, UpperName;
02941	     local bool bDefending;
02942	     local float dp;
02943	     local vector X, Y, Z;
02944	     local bool bRight;
02945	     local MovementDir_e dir;
02946	
02947	     if (health <= 0)
02948	          return;
02949	     
02950	     if(AnimProxy != None)
02951	          bDefending = (AnimProxy.GetStateName() == 'Defending');
02952	     else
02953	          bDefending = false;
02954	
02955	     // Determine the direction the player is attempting to move
02956	     GetAxes(Rotation, X, Y, Z);
02957	     dp = vector(Rotation) dot Normal(Acceleration);
02958	
02959	     if(Normal(Acceleration) dot Y >= 0){
02960	      bRight = true;
02961	     }
02962	     //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",PlayMoving_DP:"$dp,True);
02963	
02964	     If (dp==0.00){
02965	      //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",forward:"$dp,True);
02966	          dir = MD_FORWARD;
02967	     }else if(dp > 0.9){
02968	     // Distinctly forward
02969	      //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",Distinctly forward:"$dp,True);
02970	          dir = MD_FORWARD;
02971	     }else if(dp > 0.5){
02972	      //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",PlayMoving_forward left/right:"$dp,True);
02973	     // forward left/right
02974	          if(bRight)
02975	          {
02976	               if (!bMirrored)
02977	                    dir = MD_FORWARDRIGHT;
02978	               else
02979	                    dir = MD_FORWARDLEFT;
02980	          }
02981	          else
02982	          {
02983	               if (!bMirrored)
02984	                    dir = MD_FORWARDLEFT;
02985	               else
02986	                    dir = MD_FORWARDRIGHT;
02987	          }
02988	     }else if(dp < -0.9){
02989	     // Distinctly backward
02990	      //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",Distinctly backward:"$dp,True);
02991	          dir = MD_BACKWARD;          
02992	     }else if(dp < -0.5){
02993	      // backward left/right
02994	      //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",PlayMoving_backward left/right:"$dp,True);
02995	          if(bRight)
02996	          {
02997	               if (!bMirrored)
02998	                    dir = MD_BACKWARDRIGHT;
02999	               else
03000	                    dir = MD_BACKWARDLEFT;
03001	          }
03002	          else
03003	          {
03004	               if (!bMirrored)
03005	                    dir = MD_BACKWARDLEFT;
03006	               else
03007	                    dir = MD_BACKWARDRIGHT;
03008	          }
03009	     }else if(bRight){
03010	     // Strafe right
03011	     //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",Strafe right:"$dp,True);
03012	          if (!bMirrored)
03013	               dir = MD_RIGHT;
03014	          else
03015	               dir = MD_LEFT;
03016	     }else{
03017	     //BroadcastMessage(self.PlayerReplicationInfo.PlayerName$",Strafe left:"$dp,True);
03018	     // Strafe left
03019	          if (!bMirrored)
03020	               dir = MD_LEFT;
03021	          else
03022	               dir = MD_RIGHT;
03023	     }
03024	
03025	     // If Attacking and running foward or backward, then let the upper body handle the leg motion
03026	     if(AnimProxy != None && AnimProxy.GetStateName() == 'Attacking')
03027	     {
03028	          if(GetGroup(AnimSequence) == 'JumpAttack')
03029	               return;
03030	          if((dir == MD_FORWARD || dir == MD_BACKWARD) && (GetGroup(AnimSequence) == 'AttackMoving'
03031	               && AnimSequence != 'ghostthrow'))
03032	               return;
03033	     }
03034	
03035	     // Set the proper animation based upon the motion
03036	     LowerName = 'MOV_ALL_run1_AA0N';
03037	
03038	     //Log("SarkBallBot_LowerName:"$LowerName);
03039	     if(Weapon == None)
03040	     { // Explore mode
03041	          if(!bIsCrouching)
03042	          {
03043	               switch(dir)
03044	               {
03045	               case MD_FORWARD:
03046	                    LowerName = 'MOV_ALL_run1_AA0N';
03047	                    break;
03048	               case MD_FORWARDRIGHT:
03049	                    LowerName = 'MOV_ALL_rstrafe1_AA0S';
03050	                    break;
03051	               case MD_FORWARDLEFT:
03052	                    LowerName = 'MOV_ALL_lstrafe1_AA0S';
03053	                    break;
03054	               case MD_BACKWARD:
03055	                    LowerName = 'MOV_ALL_runback1_AA0S';
03056	                    break;
03057	               case MD_BACKWARDRIGHT:
03058	                    LowerName = 'MOV_ALL_lstrafe1_AA0S';
03059	                    break;
03060	               case MD_BACKWARDLEFT:
03061	                    LowerName = 'MOV_ALL_rstrafe1_AA0S';
03062	                    break;
03063	               case MD_RIGHT:
03064	                    LowerName = 'MOV_ALL_rstrafe1_AN0N';
03065	                    break;
03066	               case MD_LEFT:
03067	                    LowerName = 'MOV_ALL_lstrafe1_AN0N';
03068	                    break;
03069	               default:
03070	                    break;
03071	               }
03072	
03073	               if(LowerName == 'MOV_ALL_run1_AA0N')
03074	               {
03075	                    // Upper-body animation
03076	                    if(Shield == None)
03077	                    {
03078	                         UpperName = 'MOV_ALL_run1_AN0N'; 
03079	                    }
03080	                    else
03081	                    {
03082	                         UpperName = 'MOV_ALL_run1_AN0S';
03083	                    }
03084	               }
03085	               else
03086	               { // Strafing, so match the upper-body with the lower-body
03087	                    UpperName = LowerName;
03088	               }
03089	          }
03090	          else
03091	          { // Crouching
03092	               switch(dir)
03093	               {
03094	               case MD_FORWARD:
03095	                    LowerName = 'crouch_walkforward';
03096	                    break;
03097	               case MD_FORWARDRIGHT:
03098	                    LowerName = 'crouch_walkforward45Right';
03099	                    break;
03100	               case MD_FORWARDLEFT:
03101	                    LowerName = 'crouch_walkforward45Left';
03102	                    break;
03103	               case MD_BACKWARD:
03104	                    LowerName = 'crouch_walkbackward';
03105	                    break;
03106	               case MD_BACKWARDRIGHT:
03107	                    LowerName = 'crouch_walkbackward45Right';
03108	                    break;
03109	               case MD_BACKWARDLEFT:
03110	                    LowerName = 'crouch_walkbackward45Left';
03111	                    break;
03112	               case MD_RIGHT:
03113	                    LowerName = 'crouch_straferight';
03114	                    break;
03115	               case MD_LEFT:
03116	                    LowerName = 'crouch_strafeleft';
03117	                    break;
03118	               default:
03119	                    break;
03120	               }
03121	
03122	               UpperName = LowerName;
03123	          }
03124	     }else{
03125	     // Combat Mode
03126	          if(!bIsCrouching){
03127	            //Log("SarkBallBot_CombatMode:"$Self.PlayerReplicationInfo.PlayerName);
03128	               switch(dir){
03129	               case MD_FORWARD:
03130	                //Log("SarkBallBot_CombatMode_Forward:"$Self.PlayerReplicationInfo.PlayerName);
03131	                    if(!bDefending && Weapon!=None){
03132	                         if(AnimProxy!=None && AnimProxy.GetStateName() == 'Attacking'){
03133	                              LowerName = Weapon.A_ForwardAttack;
03134	                         }
03135	                         else
03136	                         {
03137	                              LowerName = Weapon.A_Forward;
03138	                         }
03139	                    }
03140	                    else
03141	                         LowerName = 'weapon_DefendWalk'; //Weapon.ForwardAnim;
03142	                    break;
03143	               case MD_FORWARDRIGHT:
03144	                //Log("SarkBallBot_CombatMode_ForwardRight:"$Self.PlayerReplicationInfo.PlayerName);
03145	                    if(!bDefending)
03146	                         LowerName = Weapon.A_Forward45Right;
03147	                    else
03148	                         LowerName = 'weapon_DefendWalk45Right';
03149	                    break;
03150	               case MD_FORWARDLEFT:
03151	                //Log("SarkBallBot_CombatMode_ForwardLeft:"$Self.PlayerReplicationInfo.PlayerName);
03152	                    if(!bDefending)
03153	                         LowerName = Weapon.A_Forward45Left;
03154	                    else
03155	                         LowerName = 'weapon_DefendWalk45Left';
03156	                    break;
03157	               case MD_BACKWARD:
03158	                //Log("SarkBallBot_CombatMode_Backward:"$Self.PlayerReplicationInfo.PlayerName);
03159	                    if(!bDefending)
03160	                         LowerName = Weapon.A_Backward;
03161	                    else
03162	                         LowerName = 'weapon_DefendBackup';
03163	                    break;
03164	               case MD_BACKWARDRIGHT:
03165	                //Log("SarkBallBot_CombatMode_BackwardRight:"$Self.PlayerReplicationInfo.PlayerName);
03166	                    if(!bDefending)
03167	                         LowerName = Weapon.A_Backward45Right;
03168	                    else
03169	                         LowerName = 'weapon_DefendBackup45Right';
03170	                    break;
03171	               case MD_BACKWARDLEFT:
03172	                //Log("SarkBallBot_CombatMode_BackwardLeft:"$Self.PlayerReplicationInfo.PlayerName);
03173	                    if(!bDefending)
03174	                         LowerName = Weapon.A_Backward45Left;
03175	                    else
03176	                         LowerName = 'weapon_DefendBackup45Left';
03177	                    break;
03178	               case MD_RIGHT:
03179	                //Log("SarkBallBot_CombatMode_Right:"$Self.PlayerReplicationInfo.PlayerName);
03180	                    if(!bDefending)
03181	                         LowerName = Weapon.A_StrafeRight;
03182	                    else
03183	                         LowerName = Weapon.A_StrafeRight;
03184	                    break;
03185	               case MD_LEFT:
03186	                //Log("SarkBallBot_CombatMode_Left:"$Self.PlayerReplicationInfo.PlayerName);
03187	                    if(!bDefending)
03188	                         LowerName = Weapon.A_StrafeLeft;
03189	                    else
03190	                         LowerName = Weapon.A_StrafeLeft;
03191	                    break;
03192	               default:
03193	                    break;
03194	               }
03195	          }else{
03196	          // Crouch
03197	               switch(dir)
03198	               {
03199	               case MD_FORWARD:
03200	                    if(Weapon!=None && Weapon.bCrouchTwoHands)
03201	                         LowerName = 'crouch_walkforward2hands';
03202	                    else
03203	                         LowerName = 'crouch_walkforward';
03204	                    break;
03205	               case MD_FORWARDRIGHT:
03206	                    if(Weapon!=None && Weapon.bCrouchTwoHands)
03207	                         LowerName = 'crouch_walkforward45Right2hands';
03208	                    else
03209	                         LowerName = 'crouch_walkforward45Right';
03210	                    break;
03211	               case MD_FORWARDLEFT:
03212	                    if(Weapon!=None && Weapon.bCrouchTwoHands)
03213	                         LowerName = 'crouch_walkforward45Left2hands';
03214	                    else
03215	                         LowerName = 'crouch_walkforward45Left';
03216	                    break;
03217	               case MD_BACKWARD:
03218	                    if(Weapon!=None && Weapon.bCrouchTwoHands)
03219	                         LowerName = 'crouch_walkbackward2hands';
03220	                    else
03221	                         LowerName = 'crouch_walkbackward';
03222	                    break;
03223	               case MD_BACKWARDRIGHT:
03224	                    if(Weapon.bCrouchTwoHands)
03225	                         LowerName = 'crouch_walkbackward45Right2hands';
03226	                    else
03227	                         LowerName = 'crouch_walkbackward45Right';
03228	                    break;
03229	               case MD_BACKWARDLEFT:
03230	                    if(Weapon.bCrouchTwoHands)
03231	                         LowerName = 'crouch_walkbackward45Left2hands';
03232	                    else
03233	                         LowerName = 'crouch_walkbackward45Left';
03234	                    break;
03235	               case MD_RIGHT:
03236	                    if(Weapon.bCrouchTwoHands)
03237	                         LowerName = 'crouch_straferight2hands';
03238	                    else
03239	                         LowerName = 'crouch_straferight';
03240	                    break;
03241	               case MD_LEFT:
03242	                    if(Weapon.bCrouchTwoHands)
03243	                         LowerName = 'crouch_strafeleft2hands';
03244	                    else
03245	                         LowerName = 'crouch_strafeleft';
03246	                    break;
03247	               default:
03248	                    break;
03249	               }
03250	          }
03251	
03252	          UpperName = LowerName;
03253	     }
03254	
03255	     LoopAnim(LowerName, 1.0, 0.1);
03256	
03257	     if(AnimProxy != None)
03258	          AnimProxy.TryLoopAnim(UpperName, 1.0, 0.1);
03259	}
03260	
03261	
03262	Function CheckForThrowing(Pawn Other){
03263	
03264	  If (bThrowing) Return;
03265	  If (Other==None) Return;
03266	  If (Weapon==None) Return;
03267	
03268	  //MyDebug("CheckForThrowing","Name:"$Other.Name);
03269	  If (VSize(Other.Location-Location)>MeleeRange){
03270	    //MyDebug("CheckForThrowing","Other is Far Enough Away");
03271	    If (Weapon.ISA('Axe') || Weapon.ISA('DwarfBattleHammer')){
03272	      //MyDebug("CheckForThrowing","I Have an Axe");
03273	      //BroadcastMessage("Hunting_CheckForThrowing_Throwing Axe at player with SarkBall",True);
03274	      //BroadcastMessage("CheckForThrowing_GoingToHunting:"$self.PlayerReplicationInfo.PlayerName,True);
03275	      GotoState('Hunting','ThrowWeaponAtPlayer');
03276	      //OrderObject=Other;
03277	      //DoThrow();
03278	    }else{
03279	      //If (!bAxeUsed){
03280	        //MyDebug("CheckForThrowing","Need to Switch to an Axe");
03281	        SwitchToBattleAxe();
03282	       // bAxeUsed=True;
03283	      //}
03284	    }
03285	  }
03286	}
03287	
03288	Function Bool IsPlayerOpen(Pawn Other){
03289	  local Pawn P;
03290	
03291	  foreach RadiusActors(class'Pawn', P, 100,Other.Location)
03292	    {
03293	    If (P.PlayerReplicationInfo.Team!=Other.PlayerReplicationInfo.Team){
03294	      //BroadcastMessage("IsPlayerOpen"$Other.Name$" NO",True);
03295	      Return False;
03296	
03297	    }
03298	  }
03299	  //BroadcastMessage("IsPlayerOpen"$Other.Name$" YES",True);
03300	  Return True;
03301	}
03302	
03303	Function Bool CheckForThrowToPlayer(Pawn Other){
03304	  local float dist;
03305	  dist = VSize(Other.Location-Location);
03306	  If (dist>200 && dist<1500 && DoIHaveTheBall()){
03307	    If (VSize(Other.Location-TeamGoalLocation)+200<VSize(Location-TeamGoalLocation)){
03308	      If (IsPlayerOpen(Other) && !bThrowing){
03309	        TargetPlayer=Other;
03310	        //BroadcastMessage("CheckforThrowToPlayer_GotoState_IHaveTheBall_ThrowBallToPlayer");
03311	        GotoState('IHaveTheBall','ThrowBallToPlayer');
03312	      }
03313	        //ThrowToPlayer(Other);
03314	    }
03315	  }
03316	}
03317	
03318	//------------------------------------------------
03319	//
03320	// Global SeePlayer
03321	//
03322	//------------------------------------------------
03323	function SeePlayer(actor seen)
03324	{
03325	  local float dist;
03326	  local Pawn SeenPawn;
03327	  local Actor TeamGong;
03328	
03329	  //MyDebug("SeePlayer",string(seen.Name));
03330	  SeenPawn=Pawn(seen);
03331	  If (IsSameTeam(SeenPawn)){
03332	    CheckForThrowToPlayer(SeenPawn);
03333	    Return;
03334	  }
03335	
03336	  If (DoIHaveTheBall())
03337	    Return;
03338	
03339	  If (GR.PlayerWithPossession==None && actorReachable(GR.CurrentSarkBall) || GR.ThrowingPlayer!=None)
03340	    {
03341	    //BroadcastMessage("SeePlayer:"$GetStateName()$",Going After Loose SarkBall");
03342	    GotoState('LooseBall','Begin');
03343	    //Destination=GR.CurrentSarkBall.Location;
03344	    Return;
03345	    }
03346	
03347	
03348	  If (Pawn(seen).Weapon!=None && Pawn(seen).Weapon.ISA('SarkBall')){
03349	    If (seen!=Enemy){
03350	    //MyDebug("SeePlayer","Redirecting to attack an Enemy Who has SarkBall");
03351	    SetEnemy(seen);
03352	    }else{
03353	    //MyDebug("SeePlayer","Skipping setenemy,already attacking this guy");
03354	    }
03355	    Return;
03356	
03357	  }
03358	
03359	  If (Enemy==None){
03360	    //MyDebug("SeePlayer_SetEnemy",string(seen.Name));
03361	    SetEnemy(seen);
03362	    Return;
03363	  }
03364	  //BroadcastMessage("SarkBallBot_SeePlayer:"$seen.name,true);
03365	
03366	     //Super.SeePlayer(seen);
03367	     //GotoState('Fleeing','Move');
03368	
03369	}
03370	
03371	
03372	//------------------------------------------------
03373	//
03374	// WantsToPickup
03375	//
03376	// Returns whether the item is desired
03377	//------------------------------------------------
03378	function bool WantsToPickUp(Inventory item)
03379	{
03380	  //BroadcastMessage("SarkBallBot_WantsToPickUp:"$item.name,true);
03381	     Super.WantsToPickUp(item);
03382	}
03383	
03384	
03385	//================================================
03386	//
03387	// Dying
03388	//
03389	//================================================
03390	
03391	state Dying{
03392	
03393	  function BeginState(){
03394	
03395	    local int joint;
03396	    local vector X, Y, Z;
03397	    local Inventory Inv, nextInv;
03398	
03399	    bThrowing=False;
03400	    for(Inv = Inventory; Inv != None; Inv = nextInv)
03401	     {
03402	          nextInv = Inv.Inventory;
03403	          //BroadcastMessage("Destroying("$self.name$"-->"$Inv.Name$")",True);
03404	          Inv.Destroy();
03405	     }
03406	     Return;
03407	
03408	    //BroadcastMessage("Dying_BeginState("$Self.Name$")",True);
03409	          // Drop any stowed weapons
03410	          if(StowWeapon2 != None)
03411	          {          
03412	               switch(StowWeapon2.MeleeType)
03413	               {
03414	               case MELEE_SWORD:
03415	                    joint = JointNamed('attatch_sword');
03416	                    break;
03417	               case MELEE_AXE:
03418	                    joint = JointNamed('attach_axe');
03419	                    break;
03420	               case MELEE_AXE:
03421	                    joint = JointNamed('attach_hammer');
03422	                    break;
03423	               default:
03424	                    // Unknown or non-stow item
03425	                    //return;
03426	               }
03427	
03428	               DetachActorFromJoint(joint);
03429	                    
03430	               GetAxes(Rotation, X, Y, Z);
03431	
03432	               StowWeapon2.Destroy();
03433	
03434	               //StowWeapon.DropFrom(GetJointPos(joint));
03435	          
03436	               //StowWeapon.SetPhysics(PHYS_Falling);
03437	               //StowWeapon.Velocity = Y * 100 + X * 75;
03438	               //StowWeapon.Velocity.Z = 50;
03439	               
03440	               //StowWeapon.GotoState('Drop');
03441	               //StowWeapon.DisableSwipeTrail();
03442	
03443	               StowWeapon2 = None; // Remove the StowWeapon from the actor
03444	          }
03445	
03446	
03447	
03448	     }
03449	}
03450	
03451	
03452	//================================================
03453	//
03454	// Fleeing
03455	//
03456	//================================================
03457	State Fleeing{
03458	
03459	  Function BeginState(){
03460	    Super.BeginState();
03461	    bThrowing=False;
03462	
03463	  }
03464	
03465	   function PickDestination(){
03466	     local Actor Gong;
03467	     local float Dist;
03468	     local Weapon SarkBall;
03469	     //BroadcastMessage("PickDestination",True);
03470	
03471	     if (DoIHaveTheBall()){
03472	        bHasSarkBall=True;
03473	        CheckForThrowAtGoal();
03474	
03475	     }else{
03476	        //BroadcastMessage("Fleeing_PickDestionation_GotoState_Hunting",True);
03477	        GotoState('Hunting','Hunt');
03478	     }
03479	  }
03480	
03481	
03482	  function Bump( Actor Other ){
03483	
03484	   //BroadcastMessage("Bump:"$Other.Name,True);
03485	    Super.Bump(Other);
03486	    //Velocity.X=Other.Velocity.X*10;
03487	    //Velocity.Y=Other.Velocity.Y*10;
03488	    //Velocity.Z=Other.Velocity.Z*10;
03489	
03490	
03491	  }
03492	
03493	}
03494	
03495	state Uninterrupted
03496	{
03497	ignores Touch, SeePlayer, EnemyNotVisible, HearNoise, Trigger, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, LongFall, Landed;
03498	
03499	     function bool CanGotoPainState()
03500	     { // Do not allow the actor to enter the painstate when in uninterrupted mode
03501	          return(false);
03502	     }
03503	
03504	     function BeginState()
03505	     {
03506	          if(UninterruptedAnim != 'None')
03507	          {
03508	               PlayAnim(UninterruptedAnim, 1.0, 0.1);
03509	               if(AnimProxy != None)
03510	                    AnimProxy.PlayAnim(UninterruptedAnim, 1.0, 0.1);
03511	          }
03512	     }
03513	
03514	     function EndState()
03515	     {
03516	          UninterruptedAnim = 'None';
03517	     }
03518	
03519	     function AnimEnd()
03520	     {
03521	          // Clear out any blending information (if it exists)
03522	          BlendAnimSequence = 'None';
03523	          if(AnimProxy != None)
03524	          {
03525	               AnimProxy.BlendAnimSequence = 'None';               
03526	               AnimProxy.GotoState('Idle');
03527	          }
03528	
03529	          if(Weapon != None)
03530	          { // If there is a weapon, make the weapon go cold if it was hot during this animation
03531	               Weapon.FinishAttack();
03532	               Weapon.DisableSwipeTrail();
03533	          }
03534	
03535	          GotoState(NextState);
03536	     }
03537	
03538	     function Tick(float DeltaSeconds)
03539	     {
03540	          Global.Tick(DeltaSeconds);
03541	          If (bHidden) bHidden=False;
03542	     }
03543	}
03544	
03545	
03546	State Acquisition
03547	{
03548	  function BeginState()
03549	    {
03550	    //BroadcastMessage("SarkBallBot_BeginState_Acquisition",True);
03551	    Super.BeginState();
03552	    bThrowing=False;
03553	    }
03554	
03555	  function InformTeammates()
03556	     {
03557	     //MyDebug("InformTeammates","setting enemy");
03558	     Super.InformTeammates();
03559	
03560	     }
03561	}
03562	
03563	
03564	State TacticalDecision{
03565	
03566	  function BeginState(){
03567	    //BroadcastMessage("SarkBallBot_BeginState_TacticalDecision",True);
03568	    Super.BeginState();
03569	    bThrowing=False;
03570	  }
03571	
03572	  function Tick(float DeltaTime){
03573	    //BroadcastMessage("SarkBallBot_SarkBallBot_TacticalDecision",True);
03574	    Super.Tick(DeltaTime);
03575	  }
03576	
03577	  Begin:
03578	
03579	
03580	  Think:
03581	  //BroadcastMessage(Name$"(Thinking)",True);
03582	  /*     if ( IAmLeader())
03583	     {
03584	          if (Intelligence > BRAINS_REPTILE)
03585	          {
03586	               // If any non-team members of my class around, comandeer them for my team
03587	               AssimilateVagrants();
03588	               
03589	               DecideOrders();
03590	          }
03591	          else
03592	          {     // Stupid creatures blindly attack
03593	               GiveAttackOrders(1);
03594	          }
03595	     }
03596	     else     // I am a follower
03597	     {
03598	          // If there is no leader elect one
03599	          CheckElectLeader();
03600	     }*/
03601	     //Paul: Test attempt at speedup
03602	     If (Enemy==None){
03603	      MyDebug("TacticalDecision_SetEnemy","Enemy:"$LocateSarkBall());
03604	      SetEnemy(LocateSarkBall());
03605	      };
03606	
03607	     if ( CanDirectlyThreaten() ){
03608	      //BroadcastMessage("CanDirectlyThreaten goto Charging",True);
03609	          AttackOrders = 'Charging';
03610	      }else{
03611	      //BroadcastMessage("Can not directly threaten, goto Hunting",True);
03612	          AttackOrders = 'Hunting';
03613	     };
03614	
03615	     if (FRand() > FightOrFlight)
03616	          GotoState('Fleeing');
03617	
03618	Wait:
03619	     if (AttackOrders == '')
03620	     {
03621	        //BroadcastMessage("No attack orders...goto sleep",True);
03622	          Sleep(1);
03623	          Goto('Think');
03624	     }
03625	     GotoState(AttackOrders);
03626	
03627	}
03628	
03629	
03630	
03631	
03632	Function Float DistanceToPlayerWithBall(){
03633	  If (GR.CurrentSarkBall==None) Return 9999;
03634	  If (GR.CurrentSarkBall.CarriedBy==None) Return 9999;
03635	
03636	  Return VSize(Location-GR.CurrentSarkBall.CarriedBy.Location);
03637	
03638	}
03639	
03640	Function Bool BallCloserToGoalThanMe(){
03641	  If (GR.CurrentSarkBall==None) Return False;
03642	
03643	  If (VSize(GR.CurrentSarkBall.Location-Location)<=VSize(Self.Location-TeamGoalLocation)){
03644	    Return True;
03645	  }else{
03646	    Return False;
03647	  }
03648	
03649	}
03650	
03651	State GetOpenForPass{
03652	
03653	  function BeginState(){
03654	    //BroadcastMessage("SarkBallBot_GetOpenForPass_BeginState:"$PlayerReplicationInfo.PlayerName,True);
03655	    bThrowing=False;
03656	  }
03657	
03658	  function EndState(){
03659	    //BroadcastMessage("SarkBallBot_GetOpenForPass_EndState",True);
03660	  }
03661	
03662	  function Tick(float DeltaSeconds){
03663	    Super.Tick(DeltaSeconds);
03664	    If (GR.CurrentSarkBall==None){
03665	      GotoState('Hunting','Begin');
03666	      Return;
03667	    }
03668	    If (GR.CurrentSarkBall.CarriedBy==None){
03669	      GotoState('LooseBall','Begin');
03670	      Return;
03671	    }
03672	
03673	    If (DistanceToPlayerWithBall()>=300 && !BallCloserToGoalThanMe() && AngleTo(GR.CurrentSarkBall.CarriedBy.Location) > ANGLE_45){
03674	      GotoState('WaitForPass','Begin');
03675	      Return;
03676	    }
03677	  }
03678	
03679	   //------------------------------------------------
03680	  //
03681	  // GetOpenForPass_SeePlayer
03682	  //
03683	  //------------------------------------------------
03684	  function SeePlayer(actor seen){
03685	
03686	    If (IsSameTeam(Pawn(seen)) && VSize(seen.location-location)<500){
03687	      If (AngleTo(seen.location) < 2000){
03688	        //BroadcastMessage("Seen:"$Pawn(seen).PlayerReplicationInfo.PlayerName$":"$AngleTo(seen.location),True);
03689	        PickStrafeDestination(seen);
03690	        LeadingPlayer=Pawn(seen);
03691	        GotoState('SpreadLeft','Begin');
03692	      }
03693	    }
03694	
03695	  }
03696	
03697	  function Timer(){
03698	
03699	
03700	  }
03701	
03702	  function PickStrafeDestination(actor Friendly)
03703	     {          
03704	          local vector V;
03705	          local rotator R;
03706	          local vector temp;
03707	          
03708	          V = Location - Friendly.Location;
03709	          R = rotator(V);
03710	          
03711	          if (AttackAction == AA_STRAFE_LEFT)
03712	               R.Yaw += 2000;
03713	          else
03714	               R.Yaw -= 2000;
03715	
03716	          // Strafe using the enemy's XY location, but the viking's location ground plane          
03717	          temp = Friendly.Location;
03718	          temp.Z = Location.Z;
03719	
03720	          Destination = temp + vector(R) * MeleeRange;
03721	          NearestFriendly=Pawn(Friendly);
03722	     }
03723	
03724	  function PickDestination(){
03725	    local Actor P;
03726	    local float Dist;
03727	    local Pawn PlayerWithTheBall;
03728	    local Pawn Other;
03729	
03730	    //MyDebug("PickDestination","Begin");
03731	
03732	    //BroadcastMessage("GetOpenForPass_PickDestination:"$PlayerReplicationInfo.PlayerName,True);
03733	    HuntTime = 9999;
03734	
03735	    //BroadcastMessage("SarkBallBot_Hunting_PickDestination:"$P.Name,True);
03736	    If (ActorReachable(TeamGoal)){
03737	      MoveTarget=TeamGoal;
03738	      Destination=TeamGoal.Location;
03739	    }else{
03740	      If (!FindBestPathToward(TeamGoal)){
03741	          //BroadcastMessage("SarkBallBot_IHaveTheBall_NoBestPath:"$PlayerReplicationInfo.PlayerName,True);
03742	          MoveTarget=TeamGoal;
03743	          Destination=TeamGoal.Location;
03744	        }
03745	    }
03746	    //BroadcastMessage("Setting MoveTarget as gong",True);
03747	    //MoveTarget=TeamGoal;
03748	
03749	  }
03750	
03751	  Function HitWall(vector HitNormal, actor Wall){
03752	    //BroadcastMessage("GetOpenForPass_HitWall",True);
03753	    GotoState('GetOpenForPass','HeadForGoal');
03754	    Super.Hitwall(HitNormal,Wall);
03755	  }
03756	
03757	
03758	Begin:
03759	  SchoolOffset.X = -FRand() * 500;
03760	  SchoolOffset.Y = (FRand() - 0.5) * 500;
03761	  SchoolOffset.Z = (FRand() - 0.5) * 500;
03762	  //BroadcastMessage("SarkBallBot_GetOpenForPass:"$PlayerReplicationInfo.PlayerName,True);
03763	  //Log("GetOpenForPass_PlayMoving");
03764	HeadForGoal:
03765	  PickDestination();
03766	  PlayTurning();
03767	  TurnToward(MoveTarget);
03768	  PlayMoving();
03769	
03770	  MoveToward(MoveTarget);
03771	  Sleep(0.01);
03772	  Goto('HeadForGoal');
03773	
03774	FaceYourPlayer:
03775	  //BroadcastMessage("Face Your player:"$PlayerReplicationInfo.PlayerName,True);
03776	  MoveTarget=None;
03777	  Destination=Location;
03778	  Velocity.X=0;
03779	  Velocity.Y=0;
03780	  Velocity.Z=0;
03781	  PlayTurning();
03782	  TurnToward(GR.CurrentSarkBall.CarriedBy);
03783	  PlayMoving();
03784	
03785	  MoveTo(Destination);
03786	  Sleep(0.1);
03787	  Goto('Begin');
03788	
03789	DriveInFormation:
03790	  //BroadcastMessage("DriveInFormation:"$PlayerReplicationInfo.PlayerName,True);
03791	
03792	
03793	SpreadLeft:
03794	  //BroadcastMessage("SpreadLeft:"$self.playerreplicationinfo.playername,True);
03795	  //PickStrafeDestination();
03796	  PlayStrafeLeft(0.1);
03797	  //StrafeFacing(TeamGoalLocation, TeamGoal);
03798	  bStopMoveIfCombatRange = false;
03799	  //StrafeFacing(Destination, NearestFriendly);
03800	  Log("SpreadLeft_PlayMoving");
03801	  PlayMoving();
03802	  //Destination.X=location.X;
03803	  //Destination.Y=location.y-1000;
03804	  //Destination.Z=location.z;
03805	  MoveTo(Destination);
03806	
03807	
03808	  Sleep(0.1);
03809	  //StrafeTo(Destination,TeamGoalLocation);
03810	  Goto('Begin');
03811	
03812	}
03813	
03814	State SpreadLeft{
03815	
03816	
03817	
03818	  Function BeginState(){
03819	    Super.BeginState();
03820	    bThrowing=False;
03821	  }
03822	
03823	Begin:
03824	  //BroadcastMessage("SpreadLeft:"$self.playerreplicationinfo.playername,True);
03825	  //PickStrafeDestination();
03826	  //PlayStrafeLeft(0.1);
03827	  //StrafeFacing(TeamGoalLocation, TeamGoal);
03828	  //bStopMoveIfCombatRange = false;
03829	  //StrafeFacing(Destination, NearestFriendly);
03830	  //PlayMoving();
03831	  //MoveTo(Destination);
03832	
03833	
03834	  bStopMoveIfCombatRange = false;
03835	
03836	  SchoolOffset.X = -FRand() * 500;
03837	  SchoolOffset.Y = (FRand() - 0.5) * 500;
03838	  SchoolOffset.Z = (FRand() - 0.5) * 500;
03839	
03840	  vec = Normal(LeadingPlayer.Location - OldSchoolDestination);
03841	  rot = rotator(vec);
03842	  OldSchoolDestination = LeadingPlayer.Location;
03843	
03844	  GetAxes(rot, X, Y, Z);
03845	  Destination = LeadingPlayer.Location + X * SchoolOffset.X + Y * SchoolOffset.Y + Z * SchoolOffset.Z;
03846	
03847	  PlayMoving();
03848	  MoveTo(Destination);
03849	  Sleep(0.2);
03850	  //Destination.X=location.X;
03851	  //Destination.Y=location.y-500;
03852	  //Destination.Z=location.z;
03853	  //StrafeTo(Destination,TeamGoalLocation);
03854	  GotoState('GetOpenForPass','HeadForGoal');
03855	
03856	}
03857	
03858	
03859	State WaitForPass{
03860	  function BeginState(){
03861	    //BroadcastMessage("SarkBallBot_WaitForPass_BeginState:"$PlayerReplicationInfo.PlayerName,True);
03862	    bThrowing=False;
03863	  }
03864	
03865	  function EndState(){
03866	    //BroadcastMessage("SarkBallBot_WaitForPass_EndState",True);
03867	  }
03868	
03869	  Begin:
03870	    //Log("WaitForPass_Begin");
03871	    //BroadcastMessage("WaitForPass_Begin:"$PlayerReplicationInfo.PlayerName,True);
03872	    MoveTarget=None;
03873	    Destination=Location;
03874	    Velocity.X=0;
03875	    Velocity.Y=0;
03876	    Velocity.Z=0;
03877	    If (GR.CurrentSarkBall==None){
03878	      GotoState('Hunting','Begin');
03879	    }
03880	    If (GR.CurrentSarkBall.CarriedBy==None){
03881	      GotoState('LooseBall','Begin');
03882	    }
03883	
03884	    PlayTurning();
03885	    TurnToward(GR.CurrentSarkBall.CarriedBy);
03886	    //LoopAnim('RunA', 4.0, 0.1);
03887	    PlayMoving();
03888	    MoveTo(Destination);
03889	
03890	  WaitForPass:
03891	    //Log("WaitForPass_Begin");
03892	    //BroadcastMessage("WaitForPass_WaitForPass:"$PlayerReplicationInfo.PlayerName,True);
03893	    PlayTaunting();
03894	    FinishAnim();
03895	    //TurnToward(GR.CurrentSarkBall.CarriedBy);
03896	
03897	    If (DistanceToPlayerWithBall()<=200 || BallCloserToGoalThanMe())
03898	      GotoState('GetOpenForPass','HeadForGoal');
03899	    If (GR.CurrentSarkBall.ThrowingPlayer!=None){
03900	      //BroadcastMessage("Detected ThrowingPlayer:"$GR.CurrentSarkBall.ThrowingPlayer.Name,True);
03901	      //MoveTarget=GR.CurrentSarkBall;
03902	      GotoState('LooseBall','Begin');
03903	    }
03904	    If (GR.CurrentSarkBall.CarriedBy==None){
03905	      //BroadcastMessage("Detected CarriedBy is none!",True);
03906	      //MoveTarget=GR.CurrentSarkBall;
03907	      GotoState('LooseBall','Begin');
03908	    }
03909	
03910	    Sleep(0.2);
03911	    Goto('WaitForPass');
03912	
03913	}
03914	
03915	//================================================
03916	// Debug
03917	//================================================
03918	simulated function Debug(canvas Canvas, int mode){
03919	    Canvas.CurX+=100;
03920	    //If (GetStateName()!='Hunting'){
03921	    Canvas.DrawText("Destination:"$Destination);
03922	
03923	    //};
03924	    //Canvas.CurX-=100;
03925	    Super.Debug(Canvas,mode);
03926	
03927	}
03928	
03929	
03930	function Tick(float DeltaTime){
03931	  //BroadcastMessage("SarkBallBot_Tick",True);
03932	  If (bHidden) bHidden=False;
03933	  If (GetStateName()=='SARKBALLBOT' || GetStateName()=='Waiting'){
03934	    //BroadcastMessage("GlobalTick_State:"$GetStateName()$" GOtostate_hunting:"$self.PlayerReplicationInfo.PlayerName,True);
03935	    gotostate('Hunting','Hunt');
03936	  }
03937	
03938	  //}
03939	  Super.Tick(DeltaTime);
03940	
03941	}
03942	
03943	
03944	Function Bool IsEnemyInProximity(){
03945	  local Pawn Other;
03946	
03947	  foreach RadiusActors(class'Pawn', Other, 200,Self.Location)
03948	    {
03949	    //BroadcastMessage("See:"$Other.Name,True);
03950	    if (Other==self)
03951	      continue;
03952	    if (!IsSameTeam(Other))
03953	      Return True;
03954	    }
03955	}
03956	
03957	
03958	function LookAtEndPoint(int index){
03959	  local actor endpoint;
03960	
03961	  endpoint = NavigationPoint(MoveTarget).PathEndPoint(index);
03962	  LookToward(endpoint.Location);
03963	}
03964	
03965	
03966	function Touch(Actor Other){
03967	    //Log("SarkBallBot_Touch:"$Self.PlayerReplicationInfo.PlayerName$"->"$Other.Name);
03968	    //Log("SarkBallBot_Touch_State:"$Other.GetStateName());
03969	    Super.Touch(Other);
03970	    //Log("SarkBallBot_AfterTouch:"$Other.Name);
03971	}
03972	
03973	//================================================
03974	//
03975	// BodyPartSeverable
03976	//
03977	//================================================
03978	function bool BodyPartSeverable(int BodyPart)
03979	{
03980	     switch(BodyPart)
03981	     {
03982	          case BODYPART_LARM1:
03983	          case BODYPART_RARM1:
03984	          case BODYPART_LLEG1:
03985	          case BODYPART_RLEG1:
03986	          case BODYPART_HEAD:
03987	               return true;
03988	     }
03989	     return false;
03990	}
03991	
03992	Function bool AddDefaultInventory(){
03993	  Return True;
03994	
03995	
03996	}
03997	
03998	defaultproperties
03999	{
04000	    fMaxGroundSpeedScale=1.00
04001	    bMoveWhenUnreachable=True
04002	    bPaceAttack=True
04003	    FightOrFlight=1.00
04004	    FightOrDefend=1.00
04005	    HighOrLow=0.50
04006	    HighOrLowBlock=0.50
04007	    BlockChance=1.00
04008	    LungeRange=100.00
04009	    PaceRange=100.00
04010	    ShadowScale=2.00
04011	    A_PullUp=intropullupA
04012	    A_StepUp=pullupTest
04013	    bIsPlayer=True
04014	    bCanStrafe=True
04015	    bCanGrabEdges=True
04016	    MeleeRange=40.00
04017	    CombatRange=175.00
04018	    GroundSpeed=250.00
04019	    AccelRate=1000.00
04020	    JumpZ=425.00
04021	    MaxStepHeight=30.00
04022	    AirControl=0.10
04023	    ClassID=6
04024	    BodyPartHealth(1)=100
04025	    BodyPartHealth(3)=100
04026	    BodyPartHealth(5)=100
04027	    PainDelay=1.30
04028	    Intelligence=BRAINS_HUMAN
04029	    FootStepWood(0)=Sound'FootstepsSnd.Wood.footlandwood02'
04030	    FootStepWood(1)=Sound'FootstepsSnd.Wood.footwood02'
04031	    FootStepMetal(2)=Sound'FootstepsSnd.Metal.footmetal04'
04032	    FootStepStone(0)=Sound'FootstepsSnd.Earth.footgravel01'
04033	    FootStepStone(1)=Sound'FootstepsSnd.Earth.footgravel02'
04034	    FootStepStone(2)=Sound'FootstepsSnd.Earth.footgravel03'
04035	    FootStepFlesh(0)=Sound'FootstepsSnd.Mud.footmud01'
04036	    FootStepFlesh(1)=Sound'FootstepsSnd.Mud.footmud02'
04037	    FootStepFlesh(2)=Sound'FootstepsSnd.Mud.footmud03'
04038	    FootStepEarth(0)=Sound'FootstepsSnd.Earth.footlandearth01'
04039	    FootStepEarth(1)=Sound'FootstepsSnd.Earth.footlandearth02'
04040	    FootStepEarth(2)=None
04041	    FootStepSnow(1)=None
04042	    FootStepSnow(2)=None
04043	    WeaponJoint=attach_hand
04044	    ShieldJoint=attach_shielda
04045	    StabJoint=spineb
04046	    PlayerReplicationInfoClass=Class'SarkBallPlayerReplicationInfo'
04047	    bCanLook=True
04048	    bHeadLookUpDouble=True
04049	    LFootJoint=5
04050	    RFootJoint=9
04051	    bLeadEnemy=True
04052	    CollisionRadius=20.00
04053	    CollisionHeight=40.00
04054	    bJointsTouch=True
04055	    Buoyancy=400.00
04056	    RotationRate=(Pitch=0,Yaw=50000,Roll=0)
04057	    SkelMesh=6
04058	    Skeletal=SkelModel'Players.Ragnar'
04059	    SkelGroupSkins(1)=Texture'Players.Ragnarsig_body'
04060	    SkelGroupSkins(2)=Texture'Players.Ragnarsig_head'
04061	    SkelGroupSkins(3)=Texture'Players.Ragnarsig_armleg'
04062	    SkelGroupSkins(4)=Texture'Players.Ragnarsig_armleg'
04063	    SkelGroupSkins(5)=Texture'Players.Ragnarsig_armleg'
04064	    SkelGroupSkins(6)=Texture'Players.Ragnarsig_armleg'
04065	    SkelGroupSkins(7)=Texture'Players.Ragnarragd_arms'
04066	    SkelGroupSkins(8)=Texture'Players.Ragnarragd_arms'
04067	    SkelGroupSkins(9)=Texture'Players.Ragnarsig_armleg'
04068	    SkelGroupSkins(10)=Texture'Players.Ragnarsig_armleg'
04069	    SkelGroupSkins(11)=Texture'Players.Ragnarsig_head'
04070	    SkelGroupSkins(12)=Texture'Players.Ragnarsig_neckgore'
04071	    SkelGroupSkins(13)=Texture'Players.Ragnarsig_armleg'
04072	    SkelGroupSkins(14)=Texture'Players.Ragnarsig_armleg'
04073	    SkelGroupSkins(15)=Texture'Players.Ragnarragd_arms'
04074	}

End Source Code