RuneI
Class Sark

source: c:\runehov\RuneI\Classes\Sark.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Pawn
         |
         +--RuneI.ScriptPawn
            |
            +--RuneI.Sark
Direct Known Subclasses:SarkAxe, SarkConrack, SarkHammer, SarkSpawn, SarkSword

class Sark
extends RuneI.ScriptPawn

//============================================================================= // Sark. //=============================================================================
Variables
 vector DebugJumpApex
 vector DebugJumpLand
 string EnemyStr
 vector JumpDestination
 name PreUninterrupedState
 Weapon StowWeapon
 int breathcounter

States
Dying, Fighting, Startup
State Dying Function Summary
 void Bump(Actor Other)
 void Disintegrate()
 void Timer()
 void FallBack()
 void BeginState()


State Fighting Function Summary
 void Died(Pawn Killer, name damageType, vector HitLocation)
     
//============================================================
//
// Died
//
//============================================================
 void DoStow()
 void RotateSark()
 bool CheckJumpLocation()
 void CalcJumpVelocity()
 void CalcStrafePosition2()
 void CalcStrafePosition()
 bool InDangerFromAttack()
 bool ShouldDefend()
 void Timer()
     
// Determine AttackAction based upon enemy movement and position
 bool CheckStrafeRight()
 bool CheckStrafeLeft()
 bool BlockRatherThanDodge()
 void AmbientSoundTimer()
 void EndState()
 void BeginState()


State Startup Function Summary
 void TweenToThrowing(float time)
 void TweenToMeleeLow(float time)
 void TweenToMeleeHigh(float time)
 void TweenToJumping(float time)
 void TweenToTurning(float time)
 void TweenToMoving(float time)
 void TweenToWaiting(float time)
     
// Tween functions
 void PlayDeath(name DamageType)
 void PlayRightHit(float tweentime)
 void PlayLeftHit(float tweentime)
 void PlayBackHit(float tweentime)
 void PlayFrontHit(float tweentime)
     
// Pains
 void PlayBlockLow(optional float)
 void PlayBlockHigh(optional float)
 void PlayInAir(optional float)
 void PlayTaunting(optional float)
 void PlayThrowing(optional float)
 void PlayTurning(optional float)
 void PlayMeleeLow(optional float)
 void PlayMeleeHigh(optional float)
 void PlayFlip(optional float)
 void PlayJumping(optional float)
 void PlayBackup(optional float)
     
//============================================================
//
// PlayBackup
//
//============================================================
 void PlayStrafeRight(optional float)
     
//============================================================
//
// PlayStrafeRight
//
//============================================================
 void PlayStrafeLeft(optional float)
     
//============================================================
//
// PlayStrafeLeft
//
//============================================================
 void PlayMoving(optional float)
     
//============================================================
//
// PlayMoving
//
//============================================================
 void PlayWaiting(optional float)
     
//============================================================
// Animation functions
//============================================================
 bool InCombatRange(Actor Other)
     
//============================================================
//
// InCombatRange
//
//============================================================
 bool BodyPartCritical(int BodyPart)
     
//============================================================
//
// BodyPartCritical
//
//============================================================
 bool BodyPartSeverable(int BodyPart)
     
//============================================================
//
// BodyPartSeverable
//
//============================================================
 int BodyPartForPolyGroup(int polygroup)
     
//============================================================
//
// BodyPartForPolyGroup
//
//============================================================
 int BodyPartForJoint(int joint)
     
//============================================================
//
// BodyPartForJoint
//
// Returns the body part a joint is associated with
//============================================================
 bool CanPickup(Inventory item)
     
//============================================================
//
// CanPickup
//
// Let's pawn dictate what it can pick up
//============================================================
 eAttitude AttitudeToCreature(Pawn Other)
     
//------------------------------------------------
//
// AttitudeToCreature
//
//------------------------------------------------
 void PainTimer()
     
//===================================================================
//
// PainTimer
//
//===================================================================
 void JumpOutOfBlood()
 bool CanGotoPainState()



Source Code


00001	//=============================================================================
00002	// Sark.
00003	//=============================================================================
00004	class Sark expands ScriptPawn
00005		abstract;
00006	
00007	
00008	const DEFAULT_TWEEN = 0.15;
00009	
00010	
00011	var(AI) class<Weapon>	StartStowWeapon;		// Startup stow weapon
00012	var(Sounds) sound		PaceSound;
00013	var(Sounds) sound		JumpSound;
00014	
00015	var string EnemyStr;
00016	var Weapon StowWeapon;
00017	var private int breathcounter;
00018	var name PreUninterrupedState;
00019	
00020	var	bool bDisintegrating;
00021	
00022	var vector JumpDestination;
00023	
00024	var vector DebugJumpApex;
00025	var vector DebugJumpLand;
00026	
00027	//================================================
00028	//
00029	// Startup
00030	//
00031	//================================================
00032	auto state Startup
00033	{	
00034	ignores EnemyAcquired, SeePlayer, HearNoise;
00035	
00036		function bool CanGotoPainState()
00037		{
00038			return(false);
00039		}
00040	
00041		function JumpOutOfBlood()
00042		{
00043			local vector vel;
00044	
00045			// If a Sark starts in Loki Blood, make it immediate jump out
00046			vel = 200 * vector(Rotation);
00047			vel.Z = 625;
00048			AddVelocity(vel);		
00049			SetPhysics(PHYS_Falling);
00050		}
00051	
00052	Begin:
00053		if(debugstates) slog(name@"Starting");
00054		if (!bCanFly && bFallAtStartup)
00055			SetPhysics(PHYS_Falling);
00056		SetHome();
00057		SpawnStartInventory();
00058		TouchSurroundingObjects();
00059		AfterSpawningInventory();
00060	
00061		if(Region.Zone.bLokiBloodZone)
00062		{		
00063			JumpOutOfBlood();
00064			PlayJumping(DEFAULT_TWEEN);
00065			WaitForLanding();
00066			
00067			// Randomly play "I kick ass!" Taunt after the Sark has exited Loki Blood
00068			if(FRand() < 0.5)
00069			{
00070				// TODO:  Play Hellish scream here
00071				PlayAnim('s3_taunt', 1.0, 0.1);
00072				FinishAnim();
00073			}		
00074		}	
00075	
00076		GotoState('Startup', 'Restart');
00077	}
00078	
00079	//===================================================================
00080	//
00081	// PainTimer
00082	//
00083	//===================================================================
00084	
00085	function PainTimer()
00086	{
00087		if((Health < 0) || (Level.NetMode == NM_Client))
00088			return;
00089			
00090		if(FootRegion.Zone.bPainZone && FootRegion.Zone.bLokiBloodZone)
00091		{ // Sark is standing in a LokiBlood pool, don't let him take any damage from it
00092			return;
00093		}
00094	
00095		Super.PainTimer();
00096	}
00097	
00098	//------------------------------------------------
00099	//
00100	// AttitudeToCreature
00101	//
00102	//------------------------------------------------
00103	function eAttitude AttitudeToCreature(Pawn Other)
00104	{
00105		if (Other.IsA('Goblin') || Other.IsA('Viking'))
00106			return ATTITUDE_Hate;
00107		else
00108			return Super.AttitudeToCreature(Other);
00109	}
00110	
00111	//============================================================
00112	//
00113	// CanPickup
00114	//
00115	// Let's pawn dictate what it can pick up
00116	//============================================================
00117	function bool CanPickup(Inventory item)
00118	{
00119		if (Health <= 0)
00120			return false;
00121	
00122		if (item.IsA('Weapon') && (BodyPartHealth[BODYPART_RARM1] > 0) && (Weapon == None))
00123		{
00124			return (item.IsA('axe') || item.IsA('hammer') || item.IsA('Sword') || item.IsA('Torch')
00125				|| item.IsA('SarkClaw'));
00126		}
00127		else if (item.IsA('Shield') && (BodyPartHealth[BODYPART_LARM1] > 0) && (Shield == None))
00128		{
00129			return item.IsA('Shield');
00130		}
00131		return(false);
00132	}
00133	
00134	//============================================================
00135	//
00136	// BodyPartForJoint
00137	//
00138	// Returns the body part a joint is associated with
00139	//============================================================
00140	function int BodyPartForJoint(int joint)
00141	{
00142		switch(joint)
00143		{
00144			case 24:					return BODYPART_LARM1;
00145			case 31:					return BODYPART_RARM1;
00146			case 6:  case 7:			return BODYPART_RLEG1;
00147			case 2:  case 3:			return BODYPART_LLEG1;
00148			case 17:					return BODYPART_HEAD;
00149			case 11:					return BODYPART_TORSO;
00150			default:					return BODYPART_BODY;
00151		}
00152	}
00153	
00154	//============================================================
00155	//
00156	// BodyPartForPolyGroup
00157	//
00158	//============================================================
00159	function int BodyPartForPolyGroup(int polygroup)
00160	{
00161		return BODYPART_BODY;
00162	}
00163	
00164	//============================================================
00165	//
00166	// BodyPartSeverable
00167	//
00168	//============================================================
00169	function bool BodyPartSeverable(int BodyPart)
00170	{
00171		switch(BodyPart)
00172		{
00173			case BODYPART_HEAD:
00174			case BODYPART_LARM1:
00175			case BODYPART_RARM1:
00176				return false;
00177		}
00178		return false;
00179	}
00180	
00181	//============================================================
00182	//
00183	// BodyPartCritical
00184	//
00185	//============================================================
00186	function bool BodyPartCritical(int BodyPart)
00187	{
00188		return (BodyPart == BODYPART_HEAD);
00189	}
00190	
00191	//============================================================
00192	//
00193	// InCombatRange
00194	//
00195	//============================================================
00196	
00197	function bool InCombatRange(Actor Other)
00198	{
00199		if(Other == None)
00200			return(false);
00201	
00202		return (VSize(Location - Other.Location) < CollisionRadius + Other.CollisionRadius + CombatRange);
00203	}
00204	
00205	//============================================================
00206	// Animation functions
00207	//============================================================
00208	
00209	function PlayWaiting(optional float tween)
00210	{
00211		if(Weapon != None)
00212		{
00213			LoopAnim(Weapon.A_Idle, RandRange(0.8, 1.2), 0.2);
00214		}
00215		else
00216		{
00217			LoopAnim('sark_idle', RandRange(0.8, 1.2), 0.2);
00218		}
00219	}
00220	
00221	//============================================================
00222	//
00223	// PlayMoving
00224	//
00225	//============================================================
00226	
00227	function PlayMoving(optional float tween)
00228	{
00229	//	LoopAnim('Sark_Run', 1.0, DEFAULT_TWEEN);
00230	
00231		if (Weapon == None)
00232			LoopAnim('MOV_ALL_run1_AA0N', 1.0, DEFAULT_TWEEN);
00233		else									
00234			LoopAnim(Weapon.A_Forward, 1.0, DEFAULT_TWEEN);
00235	}
00236	
00237	//============================================================
00238	//
00239	// PlayStrafeLeft
00240	//
00241	//============================================================
00242	
00243	function PlayStrafeLeft(optional float tween)
00244	{
00245		if (Weapon == None)
00246			LoopAnim('MOV_ALL_lstrafe1_AN0N', 1.0, DEFAULT_TWEEN);
00247		else									
00248			LoopAnim(Weapon.A_StrafeLeft, 1.0, DEFAULT_TWEEN);
00249	}
00250	
00251	//============================================================
00252	//
00253	// PlayStrafeRight
00254	//
00255	//============================================================
00256	
00257	function PlayStrafeRight(optional float tween)
00258	{
00259		if (Weapon == None)
00260			LoopAnim('MOV_ALL_rstrafe1_AN0N', 1.0, DEFAULT_TWEEN);
00261		else									
00262			LoopAnim(Weapon.A_StrafeRight, 1.0, DEFAULT_TWEEN);
00263	}
00264	
00265	//============================================================
00266	//
00267	// PlayBackup
00268	//
00269	//============================================================
00270	
00271	function PlayBackup(optional float tween)
00272	{
00273		if (Weapon == None)
00274			LoopAnim('MOV_ALL_runback1_AA0S', 1.0, DEFAULT_TWEEN);
00275		else									
00276			LoopAnim(Weapon.A_Backward, 1.0, DEFAULT_TWEEN);
00277	}
00278	
00279	function PlayJumping(optional float tween)    { PlayAnim  ('MOV_ALL_jump1_AA0S',      1.0, tween);   }
00280	function PlayFlip(optional float tween)    { PlayAnim ('sark_flip', 1.0, tween);   }
00281	
00282	function PlayMeleeHigh(optional float tween)
00283	{
00284		if(Weapon != None)
00285		{
00286			PlayAnim(Weapon.A_AttackStandA, 1.3, tween);
00287		}
00288	}
00289	function PlayMeleeLow(optional float tween)
00290	{
00291		if(Weapon==None)							PlayAnim  ('swipe',     1.0, tween);
00292		else										PlayAnim  ('attackb',   1.0, tween);
00293	}
00294	
00295	function PlayTurning(optional float tween)
00296	{
00297		if(Weapon != None)
00298			LoopAnim(Weapon.A_Idle, 1.0, tween);
00299		else
00300			LoopAnim('neutral_idle', 1.0, tween);
00301	}
00302	
00303	function PlayThrowing(optional float tween)   { PlayAnim('throwA',    1.0, tween); }
00304	function PlayTaunting(optional float tween)   { PlayAnim('s3_taunt', 1.0, tween); }
00305	function PlayInAir(optional float tween) 
00306	{
00307		PlayAnim('MOV_ALL_jump1_AA0S', 1.0, tween);
00308	}
00309	
00310	function PlayBlockHigh(optional float tween)  { LoopAnim  ('blocklow',  1.0, tween);   }
00311	function PlayBlockLow(optional float tween)   { LoopAnim  ('blocklow',  1.0, tween);   }
00312	
00313	// Pains
00314	function PlayFrontHit(float tweentime)        
00315	{
00316		if(Weapon == None)
00317		{ // Neutral anims
00318			PlayAnim('n_painFront', 1.0, 0.1);
00319		}
00320		else
00321		{ // Weapon-specific
00322			PlayAnim(Weapon.A_PainFront, 1.0, 0.1);
00323		}
00324	}
00325	
00326	function PlayBackHit(float tweentime)
00327	{
00328		if(Weapon == None)
00329		{ // Neutral anims
00330			PlayAnim('n_painBack', 1.0, 0.1);
00331		}
00332		else
00333		{ // Weapon-specific
00334			PlayAnim(Weapon.A_PainBack, 1.0, 0.1);
00335		}
00336	}
00337	
00338	function PlayLeftHit(float tweentime)         { PlayAnim('S1_painLeft', 1.0, 0.08); }
00339	function PlayRightHit(float tweentime)         { PlayAnim('S1_painRight', 1.0, 0.08); }
00340	
00341	function PlayDeath(name DamageType)           
00342	{ 
00343		PlayAnim('sark_DeathV', 0.5, DEFAULT_TWEEN);
00344	
00345	/*
00346		if(DamageType == 'thrownweaponsever')
00347			PlayAnim('deathb', 1.0, DEFAULT_TWEEN);  
00348		else
00349			PlayAnim('DTH_ALL_death1_AN0N', 1.0, DEFAULT_TWEEN);  
00350	*/
00351	}
00352	
00353	// Tween functions
00354	function TweenToWaiting(float time)
00355	{
00356		if(Weapon != None)
00357			TweenAnim(Weapon.A_Idle, time);
00358		else
00359			LoopAnim('neutral_idle', time);
00360	}
00361	
00362	function TweenToMoving(float time)
00363	{
00364		if(Weapon != None)
00365			TweenAnim(Weapon.A_Forward, time);
00366		else									
00367			TweenAnim('MOV_ALL_run1_AA0N', time);
00368	}
00369	
00370	function TweenToTurning(float time)
00371	{ // TODO:  Need turning anims
00372		if(Weapon != None)
00373			TweenAnim(Weapon.A_Idle, time);
00374		else
00375			TweenAnim('neutral_idle', time);
00376	}
00377	
00378	function TweenToJumping(float time)           {	TweenAnim ('MOV_ALL_jump1_AA0S', time); }
00379	function TweenToMeleeHigh(float time)
00380	{
00381	/*
00382		if (Weapon==None)							TweenAnim ('swipe',     time);
00383		else										TweenAnim ('attackb',   time);
00384	*/
00385	}
00386	function TweenToMeleeLow(float time)
00387	{
00388	/*
00389		if (Weapon==None)							TweenAnim ('swipe',     time);
00390		else										TweenAnim ('attackb',   time);
00391	*/
00392	}
00393	function TweenToThrowing(float time)          { TweenAnim ('throwA',    time);         }
00394	
00395	
00396	//===================================================================
00397	//					States
00398	//===================================================================
00399	
00400	//================================================
00401	//
00402	// Fighting
00403	//
00404	//================================================
00405	State Fighting
00406	{
00407	ignores EnemyAcquired;
00408	
00409		function BeginState()
00410		{
00411			bAvoidLedges = true;
00412			LookAt(Enemy);
00413			SetTimer(0.1, true);
00414		}
00415	
00416		function EndState()
00417		{
00418			bAvoidLedges = false;
00419	
00420			bSwingingHigh = false;
00421			bSwingingLow  = false;
00422	
00423			if(Weapon != None)
00424			{
00425				Weapon.FinishAttack();
00426				Weapon.DisableSwipeTrail();
00427			}
00428	
00429			LookAt(None);
00430			SetTimer(0, false);
00431		}
00432		
00433		function AmbientSoundTimer()
00434		{
00435			PlayAmbientFightSound();
00436		}
00437	
00438		function bool BlockRatherThanDodge()
00439		{
00440			if (Shield == None)
00441				return false;
00442	
00443			if (EnemyIncidence != INC_FRONT)
00444				return false;
00445	
00446			return (FRand() < BlockChance);
00447		}
00448	
00449		function bool CheckStrafeLeft()
00450		{ // Checks if the left strafe move is valid (not going to strafe into a wall)
00451			local vector HitLocation, HitNormal;
00452			local vector extent, end;
00453	
00454			extent.X = CollisionRadius;
00455			extent.Y = CollisionRadius;
00456			extent.Z = CollisionHeight * 0.5;
00457	
00458			CalcStrafePosition();
00459	
00460			end = Normal(Destination - Location) * 75;
00461	
00462			if(Trace(HitLocation, HitNormal, end, Location, true, extent) == None)
00463				return(true); // Nothing in the way
00464			else
00465				return(false);
00466		}
00467	
00468		function bool CheckStrafeRight()
00469		{ // Checks if the right strafe move is valid (not going to strafe into a wall)
00470			local vector HitLocation, HitNormal;
00471			local vector extent, end;
00472	
00473			extent.X = CollisionRadius;
00474			extent.Y = CollisionRadius;
00475			extent.Z = CollisionHeight * 0.5;
00476	
00477			CalcStrafePosition2();
00478	
00479			end = Normal(Destination - Location) * 75;
00480	
00481			if(Trace(HitLocation, HitNormal, end, Location, true, extent) == None)
00482				return(true); // Nothing in the way
00483			else
00484				return(false);
00485		}
00486	
00487	
00488		// Determine AttackAction based upon enemy movement and position
00489		function Timer()
00490		{
00491			GetEnemyProximity();
00492	
00493			LastAction = AttackAction;
00494					
00495			if(EnemyMovement == MOVE_STRAFE_LEFT && FRand() < 0.7 && CheckStrafeLeft())
00496			{
00497				AttackAction = AA_STRAFE_LEFT;
00498			}
00499			else if(EnemyMovement == MOVE_STRAFE_RIGHT && FRand() < 0.7 && CheckStrafeRight())
00500			{
00501				AttackAction = AA_STRAFE_RIGHT;
00502			}
00503			else if(FRand() < 0.2 && Physics == PHYS_Walking && CheckJumpLocation())
00504			{
00505				AttackAction = AA_JUMP;
00506			}
00507			else if(EnemyMovement == MOVE_STANDING && FRand() < 0.85)
00508			{
00509				AttackAction = AA_LUNGE;
00510			}		
00511		 	else if(FRand() < 0.75)
00512		 	{
00513		 		if(FRand() < 0.5 && LastAction != AA_STRAFE_RIGHT || LastAction == AA_STRAFE_LEFT
00514					&& CheckStrafeLeft())
00515		 		{
00516		 			AttackAction = AA_STRAFE_LEFT;
00517		 		}
00518		 		else if(LastAction != AA_STRAFE_LEFT || LastAction == AA_STRAFE_RIGHT && CheckStrafeRight())
00519		 		{
00520		 			AttackAction = AA_STRAFE_RIGHT;
00521		 		}
00522				else
00523				{
00524					AttackAction = AA_WAIT;
00525				}
00526		 	}
00527			else
00528			{
00529				AttackAction = AA_WAIT;
00530			}
00531			
00532	/*	
00533			if (ShouldDefend())
00534			{
00535				GotoState('Fighting', 'Defend');
00536			}
00537	*/		
00538		}
00539	
00540		function bool ShouldDefend()
00541		{
00542			return (FRand() > FightOrDefend && InDangerFromAttack());
00543		}
00544		
00545		function bool InDangerFromAttack()
00546		{
00547			if ((!Enemy.bSwingingHigh) && (!Enemy.bSwingingLow))
00548				return false;
00549	
00550			GetEnemyProximity();
00551				
00552			if (EnemyDist>CollisionRadius+Enemy.CollisionRadius+Enemy.MeleeRange)
00553				return false;
00554	
00555			return (EnemyVertical==VERT_LEVEL && EnemyFacing==FACE_FRONT);
00556		}
00557	
00558		function CalcStrafePosition()
00559		{		
00560			local vector V;
00561			local rotator R;
00562			local vector temp;
00563			
00564			V = Location - Enemy.Location;
00565			R = rotator(V);
00566			
00567			R.Yaw += 2000;
00568	
00569			// Strafe using the enemy's XY location, but the viking's location ground plane		
00570			temp = Enemy.Location;
00571			temp.Z = Location.Z;
00572	
00573			Destination = temp + vector(R) * CombatRange;
00574		}
00575		
00576		function CalcStrafePosition2()
00577		{		
00578			local vector V;
00579			local rotator R;
00580			local vector temp;
00581			
00582			V = Location - Enemy.Location;
00583			R = rotator(V);
00584			
00585			R.Yaw -= 2000;
00586	
00587			// Strafe using the enemy's XY location, but the viking's location ground plane		
00588			temp = Enemy.Location;
00589			temp.Z = Location.Z;
00590	
00591			Destination = temp + vector(R) * CombatRange;
00592		}
00593	
00594		function CalcJumpVelocity()
00595		{
00596			local float traj;
00597			local vector arcVel;
00598	
00599			traj = 70 * 65536 / 360;
00600	
00601			// JumpDestination is calculated in CheckJumpLocation
00602			arcVel = CalcArcVelocity(traj, Location, JumpDestination);
00603	
00604			AddVelocity(arcVel);
00605		}
00606	
00607		function bool CheckJumpLocation()
00608		{		
00609			local vector start, end;
00610			local vector extent;
00611			local vector HitLocation, HitNormal;
00612	
00613			if(Enemy == None)
00614				return(false);
00615	
00616			extent.X = CollisionRadius;
00617			extent.Y = CollisionRadius;
00618			extent.Z = CollisionHeight * 0.5;
00619	
00620			JumpDestination = Enemy.Location - Location;
00621			JumpDestination.Z = 0;
00622			JumpDestination = Enemy.Location + Normal(JumpDestination) * 200;
00623	
00624			start = Location;
00625			end = ((JumpDestination + start) / 2) + vect(0, 0, 280);
00626	
00627			DebugJumpApex = end;
00628			DebugJumpLand = JumpDestination;
00629	
00630			// Trace to check if the jump is valid
00631			if(Trace(HitLocation, HitNormal, end, start, true, extent) == None)
00632			{ // Nothing on the way up, check going down
00633				start = end;
00634				end = JumpDestination;
00635	
00636				if(Trace(HitLocation, HitNormal, end, start, true, extent) == None)
00637				{ // Nothing on the way back down, check to make sure that the Sark will land on valid ground
00638					start = JumpDestination;
00639					end = JumpDestination - vect(0, 0, 100);
00640	
00641					if(Trace(HitLocation, HitNormal, end, start, false) == None)
00642					{ // Not going to land on anything, so don't do the jump
00643						return(false);
00644					}
00645	
00646					// Otherwise, the jump is good!
00647					return(true);
00648				}
00649				DebugJumpLand = HitLocation;
00650			}
00651	
00652			return(false);
00653		}
00654	
00655		function RotateSark()
00656		{
00657			local rotator rot;
00658			rot = Rotation;
00659			rot.Yaw = Rotation.Yaw + 32768;
00660			SetRotation(rot);
00661		}
00662	
00663		function DoStow()
00664		{
00665			if(Weapon != None && Weapon.MeleeType == MELEE_NON_STOW)
00666			{ // Drop the weapon
00667				DropWeapon();
00668				Weapon = None;
00669				return;
00670			}
00671	
00672			Weapon = StowWeapon;
00673			
00674			switch(Weapon.MeleeType)
00675			{
00676			case MELEE_SWORD:
00677				DetachActorFromJoint(JointNamed('attatch_sword'));
00678				break;
00679			case MELEE_AXE:
00680				DetachActorFromJoint(JointNamed('attach_axe'));
00681				break;
00682			case MELEE_AXE:
00683				DetachActorFromJoint(JointNamed('attach_hammer'));
00684				break;
00685			case MELEE_NON_STOW:
00686				DropWeapon();
00687				break;
00688			}
00689			
00690			AttachActorToJoint(Weapon, JointNamed(WeaponJoint));
00691			Weapon.GotoState('Active');
00692			StowWeapon = None;
00693		}
00694			
00695	Begin:
00696		if(Enemy == None)
00697			Goto('BackFromSubState');
00698	
00699		Acceleration = vect(0,0,0);
00700	
00701		// Turn to face enemy
00702		DesiredRotation.Yaw = rotator(Enemy.Location-Location).Yaw;
00703	
00704		if(Weapon.MeleeType == MELEE_NON_STOW && StowWeapon != None)
00705		{ // The creature is carrying a non-stow (probably a torch), but 
00706			// has a weapon stowed, ditch the non-stow in favor of the stowed weapon
00707			PlayAnim('IDL_ALL_drop1_AA0S', 1.0, DEFAULT_TWEEN);
00708			FinishAnim();
00709		}
00710	
00711		// If the creature has a weapon stowed, unsheath it before attacking
00712		if(Weapon == None && StowWeapon != None)
00713		{ // Unsheath the stow weapon
00714			switch(StowWeapon.MeleeType)
00715			{
00716			case MELEE_SWORD:
00717				PlayAnim('IDL_ALL_sstow1_AA0S', 1.0, DEFAULT_TWEEN);
00718				break;
00719			case MELEE_AXE:
00720				PlayAnim('IDL_ALL_xstow1_AA0S', 1.0, DEFAULT_TWEEN);
00721				break;
00722			case MELEE_HAMMER:
00723				PlayAnim('IDL_ALL_hstow1_AA0S', 1.0, DEFAULT_TWEEN);
00724				break;
00725			}
00726			
00727			FinishAnim();	
00728		}
00729	
00730	//	PlayWaiting();
00731	
00732	Fight:
00733		if ( !ValidEnemy() )
00734			Goto('BackFromSubState');
00735	
00736		GetEnemyProximity();
00737		
00738		// Attack if close enough
00739		if(Weapon != None && InMeleeRange(Enemy) || (EnemyMovement == MOVE_CLOSER && EnemyDist < MeleeRange * 2.5))
00740		{
00741			if(LastAction != AA_LUNGE && FRand() < 0.2)
00742			{ // Random chance that the creature will dodge
00743				PlayMoving();
00744				if(FRand() < 0.7)
00745				{ // Either jump to the side, or back up
00746					// Back up
00747					bStopMoveIfCombatRange = false;
00748					ActivateShield(true);
00749					PlayBackup();
00750					StrafeFacing(Location - vector(Rotation) * (CombatRange - EnemyDist), Enemy);
00751					ActivateShield(false);
00752					bStopMoveIfCombatRange = true;
00753				}
00754				else
00755				{ // Dodge to the side
00756					bStopMoveIfCombatRange = false;
00757					ActivateShield(true);
00758					PlayStrafeRight();
00759					StrafeFacing(Location + vector(Rotation + rot(0, 16384, 0)) * CombatRange, Enemy);
00760					ActivateShield(false);
00761					bStopMoveIfCombatRange = true;				
00762				}
00763			}		
00764			else
00765			{
00766				PlayAnim(Weapon.A_AttackA, 1.3, 0.1);
00767				Sleep(0.1);
00768				WeaponActivate();
00769				Weapon.EnableSwipeTrail();
00770				FinishAnim();
00771	
00772				if(Weapon.A_AttackB != 'None' && FRand() < 0.5)
00773				{
00774	//				ClearSwipeArray();
00775					PlayAnim(Weapon.A_AttackB, 1.3, 0.01);
00776					if(Enemy != None)
00777						TurnToward(Enemy);
00778					FinishAnim();
00779	
00780					// B-Return
00781					WeaponDeactivate();
00782	
00783					if(Weapon.A_AttackBReturn != 'None')
00784					{
00785						PlayAnim(Weapon.A_AttackBReturn, 1.3, 0.1);
00786						FinishAnim();
00787					}
00788				}
00789				else
00790				{ // A-Return
00791					WeaponDeactivate();
00792	
00793					if(Weapon.A_AttackAReturn != 'None')
00794					{
00795						PlayAnim(Weapon.A_AttackAReturn, 1.3, 0.1);
00796						FinishAnim();
00797					}
00798				}
00799	
00800				Weapon.DisableSwipeTrail();
00801			}
00802			
00803			Sleep(TimeBetweenAttacks);
00804		}
00805		else if(AttackAction == AA_LUNGE)
00806		{ // Random lunge
00807			PlayMoving();
00808			bStopMoveIfCombatRange = false;
00809			MoveTo(Enemy.Location - VecToEnemy * MeleeRange, MovementSpeed);
00810			bStopMoveIfCombatRange = true;
00811		}
00812		else if(AttackAction == AA_STRAFE_LEFT)
00813		{ // Strafe - Position is calculated in Timer, when the strafe is chosen
00814			PlayStrafeLeft();
00815			bStopMoveIfCombatRange = false;
00816			StrafeFacing(Destination, Enemy);
00817			bStopMoveIfCombatRange = true;
00818		}
00819		else if(AttackAction == AA_STRAFE_RIGHT)
00820		{ // Strafe - Position is calculated in Timer, when the strafe is chosen
00821			PlayStrafeRight();
00822			bStopMoveIfCombatRange = false;
00823			StrafeFacing(Destination, Enemy);
00824			bStopMoveIfCombatRange = true;
00825		}
00826		else if(AttackAction == AA_JUMP)
00827		{
00828			PlayFlip(0.1);
00829			Sleep(0.4); // Sleep for a bit before making the leap
00830			PlaySound(JumpSound);
00831			CalcJumpVelocity();
00832			WaitForLanding();
00833	
00834			RotateSark();
00835			PlayAnim('sark_land', 1.0, 0.0);
00836			if(Enemy != None)
00837				TurnToward(Enemy);
00838			FinishAnim();
00839		}
00840		else
00841		{
00842			PlayWaiting();
00843		}
00844	
00845		if(InCombatRange(Enemy))
00846		{
00847			Sleep(0.05);
00848			Goto('Begin');
00849		}
00850		
00851	BackFromSubState:
00852		GotoState('Charging', 'ResumeFromFighting');
00853	}
00854	
00855	//============================================================
00856	//
00857	// Died
00858	//
00859	//============================================================
00860	
00861	function Died(pawn Killer, name damageType, vector HitLocation)
00862	{
00863		local actor eyes;
00864	
00865		eyes = DetachActorFromJoint(JointNamed('head'));
00866		if(eyes != None)
00867			eyes.Destroy();
00868	
00869		Super.Died(Killer, damageType, HitLocation);
00870	}
00871	
00872	//================================================
00873	//
00874	// Dying
00875	//
00876	//================================================
00877	
00878	state Dying
00879	{
00880		function BeginState()
00881		{
00882			local int joint;
00883			local vector X, Y, Z;
00884	
00885			// Drop any stowed weapons
00886			if(StowWeapon != None)
00887			{		
00888				switch(StowWeapon.MeleeType)
00889				{
00890				case MELEE_SWORD:
00891					joint = JointNamed('attatch_sword');
00892					break;
00893				case MELEE_AXE:
00894					joint = JointNamed('attach_axe');
00895					break;
00896				case MELEE_AXE:
00897					joint = JointNamed('attach_hammer');
00898					break;
00899				default:
00900					// Unknown or non-stow item
00901					return;
00902				}
00903	
00904				DetachActorFromJoint(joint);
00905					
00906				GetAxes(Rotation, X, Y, Z);
00907				StowWeapon.DropFrom(GetJointPos(joint));
00908			
00909				StowWeapon.SetPhysics(PHYS_Falling);
00910				StowWeapon.Velocity = Y * 100 + X * 75;
00911				StowWeapon.Velocity.Z = 50;
00912				
00913				StowWeapon.GotoState('Drop');
00914				StowWeapon.DisableSwipeTrail();
00915	
00916				StowWeapon = None; // Remove the StowWeapon from the actor
00917			}		
00918		}
00919	
00920		function FallBack()
00921		{
00922			local vector vel;
00923			local vector X, Y, Z;
00924	
00925			GetAxes(Rotation, X, Y, Z);
00926	
00927			vel = -200 * X + vect(0, 0, 75);
00928			AddVelocity(vel);
00929			SetPhysics(PHYS_Falling);
00930		}
00931	
00932		function Timer()
00933		{
00934			FallBack();
00935		}
00936		
00937		function Disintegrate()
00938		{		
00939			local int i;
00940			local vector v;
00941			local rotator r;
00942			local actor puff;
00943			
00944			bDisintegrating = true;
00945			LifeSpan = 1.0;
00946			ShadowScale = 0; // Turn off any shadow on the creature
00947	
00948	/*		
00949			for(i = 0; i < Rand(5); i++)
00950			{
00951				v = VRand();
00952				r = Rotator(v);
00953				puff = Spawn(class'ZombieBreath', self,, Location, r);			
00954				puff.Velocity = v * 75;
00955				puff.SetPhysics(PHYS_Projectile);			
00956			}
00957	*/
00958		}
00959		
00960	begin:
00961		PlayDeath('');
00962		Sleep(0.4);
00963		SetTimer(0.25, true);
00964		Disintegrate();
00965	}
00966	
00967	
00968	function Bump(Actor Other)
00969	{
00970		if(Other.IsA('Keg') || Other.IsA('Stool') || Other.IsA('Bucket'))
00971		{ // Vikings will smash kegs that are in the way
00972			UseActor = Other;
00973	
00974			if(FRand() < 0.2 || Other.Location.Z < Location.Z || Weapon == None)
00975			{
00976				PlayUninterruptedAnim(UseActor.GetUseAnim());
00977			}
00978			else
00979			{
00980				PlayUninterruptedAnim(Weapon.A_AttackA);
00981			}
00982		}
00983		else
00984		{
00985			Super.Bump(Other);
00986		}
00987	}
00988	
00989	simulated function Debug(Canvas canvas, int mode)
00990	{
00991		local vector offset;
00992		
00993		Super.Debug(canvas, mode);
00994		
00995		Canvas.DrawText("Sark:");
00996		Canvas.CurY -= 8;
00997		Canvas.DrawText("	PreUninterrupt: " $ PreUninterrupedState);
00998		Canvas.CurY -= 8;
00999		Canvas.DrawText("	NextOrder/Tag: " $ NextState@NextLabel);
01000		Canvas.CurY -= 8;
01001		Canvas.DrawText("	Enemy String: " $ EnemyStr);
01002		EnemyStr = "None";
01003	
01004		Canvas.CurY -= 8;
01005		if(EnemyFacing == FACE_FRONT)
01006		{
01007			Canvas.DrawText("	Enemy Facing:  FRONT");		
01008		}
01009		else if(EnemyFacing == FACE_BACK)
01010		{
01011			Canvas.DrawText("	Enemy Facing:  BACK");		
01012		}
01013		else
01014		{
01015			Canvas.DrawText("	Enemy Facing:  SIDE");		
01016		}
01017		
01018		Canvas.CurY -= 8;
01019		if(EnemyVertical == VERT_ABOVE)
01020		{
01021			Canvas.DrawText("	Enemy Vertical:  ABOVE");		
01022		}
01023		else if(EnemyVertical == VERT_BELOW)
01024		{
01025			Canvas.DrawText("	Enemy Vertical:  BELOW");		
01026		}
01027		else
01028		{
01029			Canvas.DrawText("	Enemy Vertical:  LEVEL");		
01030		}
01031	
01032		Canvas.CurY -= 8;
01033		if(EnemyMovement == MOVE_CLOSER)
01034		{
01035			Canvas.DrawText("	Enemy Movement:  CLOSER");		
01036		}
01037		else if(EnemyMovement == MOVE_FARTHER)
01038		{
01039			Canvas.DrawText("	Enemy Movement:  FARTHER");		
01040		}
01041		else if(EnemyMovement == MOVE_STRAFE_LEFT)
01042		{
01043			Canvas.DrawText("	Enemy Movement:  STRAFE_LEFT");		
01044		}
01045		else if(EnemyMovement == MOVE_STRAFE_RIGHT)
01046		{
01047			Canvas.DrawText("	Enemy Movement:  STRAFE_RIGHT");		
01048		}
01049		else
01050		{
01051			Canvas.DrawText("	Enemy Movement:  STANDING");				
01052		}
01053		
01054		Canvas.CurY -= 8;
01055		Canvas.DrawText("   AttackAction:  " $ AttackAction);
01056		
01057		offset = Destination;
01058		Canvas.DrawLine3D(offset + vect(10, 0, 0), offset + vect(-10, 0, 0), 255, 0, 0);
01059		Canvas.DrawLine3D(offset + vect(0, 10, 0), offset + vect(0, -10, 0), 255, 0, 0);	
01060		Canvas.DrawLine3D(offset + vect(0, 0, 10), offset+ vect(0, 0, -10), 255, 0, 0);
01061	
01062		offset = DebugJumpApex;
01063		Canvas.DrawLine3D(offset + vect(10, 0, 0), offset + vect(-10, 0, 0), 0, 255, 0);
01064		Canvas.DrawLine3D(offset + vect(0, 10, 0), offset + vect(0, -10, 0), 0, 255, 0);	
01065		Canvas.DrawLine3D(offset + vect(0, 0, 10), offset+ vect(0, 0, -10), 0, 255, 0);
01066	
01067		offset = DebugJumpLand;
01068		Canvas.DrawLine3D(offset + vect(10, 0, 0), offset + vect(-10, 0, 0), 255, 255, 0);
01069		Canvas.DrawLine3D(offset + vect(0, 10, 0), offset + vect(0, -10, 0), 255, 255, 0);	
01070		Canvas.DrawLine3D(offset + vect(0, 0, 10), offset+ vect(0, 0, -10), 255, 255, 0);
01071	}
01072	
01073	defaultproperties
01074	{
01075	     bPaceAttack=True
01076	     FightOrFlight=1.000000
01077	     FightOrDefend=1.000000
01078	     HighOrLow=0.500000
01079	     HighOrLowBlock=0.500000
01080	     BlockChance=1.000000
01081	     LungeRange=100.000000
01082	     PaceRange=100.000000
01083	     ShadowScale=2.000000
01084	     A_PullUp=intropullupA
01085	     A_StepUp=pullupTest
01086	     bCanStrafe=True
01087	     bCanGrabEdges=True
01088	     MeleeRange=40.000000
01089	     CombatRange=175.000000
01090	     GroundSpeed=250.000000
01091	     AccelRate=1000.000000
01092	     JumpZ=425.000000
01093	     MaxStepHeight=30.000000
01094	     AirControl=0.100000
01095	     WalkingSpeed=250.000000
01096	     ClassID=6
01097	     Health=250
01098	     BodyPartHealth(1)=250
01099	     BodyPartHealth(3)=250
01100	     BodyPartHealth(5)=250
01101	     Intelligence=BRAINS_HUMAN
01102	     FootStepWood(0)=Sound'CreaturesSnd.Sark.sarkfootstep01'
01103	     FootStepWood(1)=Sound'CreaturesSnd.Sark.sarkfootstep02'
01104	     FootStepWood(2)=Sound'CreaturesSnd.Sark.sarkfootstep03'
01105	     FootStepMetal(0)=Sound'CreaturesSnd.Sark.sarkfootstep01'
01106	     FootStepMetal(1)=Sound'CreaturesSnd.Sark.sarkfootstep02'
01107	     FootStepMetal(2)=Sound'CreaturesSnd.Sark.sarkfootstep03'
01108	     FootStepStone(0)=Sound'CreaturesSnd.Sark.sarkfootstep01'
01109	     FootStepStone(1)=Sound'CreaturesSnd.Sark.sarkfootstep02'
01110	     FootStepStone(2)=Sound'CreaturesSnd.Sark.sarkfootstep03'
01111	     FootStepFlesh(0)=Sound'CreaturesSnd.Sark.sarkfootstep01'
01112	     FootStepFlesh(1)=Sound'CreaturesSnd.Sark.sarkfootstep02'
01113	     FootStepFlesh(2)=Sound'CreaturesSnd.Sark.sarkfootstep03'
01114	     FootStepIce(0)=Sound'CreaturesSnd.Sark.sarkfootstep01'
01115	     FootStepIce(1)=Sound'CreaturesSnd.Sark.sarkfootstep02'
01116	     FootStepIce(2)=Sound'CreaturesSnd.Sark.sarkfootstep03'
01117	     FootStepEarth(0)=Sound'CreaturesSnd.Sark.sarkfootstep01'
01118	     FootStepEarth(1)=Sound'CreaturesSnd.Sark.sarkfootstep02'
01119	     FootStepEarth(2)=Sound'CreaturesSnd.Sark.sarkfootstep03'
01120	     FootStepSnow(0)=Sound'CreaturesSnd.Sark.sarkfootstep01'
01121	     FootStepSnow(1)=Sound'CreaturesSnd.Sark.sarkfootstep02'
01122	     FootStepSnow(2)=Sound'CreaturesSnd.Sark.sarkfootstep03'
01123	     WeaponJoint=attach_hand
01124	     ShieldJoint=attach_shielda
01125	     StabJoint=spineb
01126	     bCanLook=True
01127	     bHeadLookUpDouble=True
01128	     LFootJoint=5
01129	     RFootJoint=9
01130	     bLeadEnemy=True
01131	     DrawScale=1.500000
01132	     CollisionRadius=27.000000
01133	     CollisionHeight=63.000000
01134	     Buoyancy=400.000000
01135	     RotationRate=(Pitch=0,Roll=0)
01136	     Skeletal=SkelModel'Players.Ragnar'
01137	}

End Source Code