SarkBall
Class SarkBallBotDwarf

source: c:\runehov\SarkBall\Classes\SarkBallBotDwarf.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Pawn
         |
         +--RuneI.ScriptPawn
            |
            +--SarkBall.SarkBallBot
               |
               +--SarkBall.SarkBallBotDwarf
Direct Known Subclasses:None

class SarkBallBotDwarf
extends SarkBall.SarkBallBot

//----------------------------------------------------------- // SarkBallBotDwarf //-----------------------------------------------------------
Variables
 int BashDamage
 float MaxBashThrust
 bool bShieldBashing
 vector bashVelocity
 int breathcounter
 float decision

States
Fighting, KnockedDown

Function Summary
 void ApplyGoreCap(int BodyPart)
     
//============================================================
//
// ApplyGoreCap
//
//============================================================
 eAttitude AttitudeToCreature(Pawn Other)
     
//------------------------------------------------
//
// AttitudeToCreature
//
//------------------------------------------------
 bool BodyPartCritical(int BodyPart)
     
//================================================
//
// BodyPartCritical
//
//================================================
 int BodyPartForJoint(int joint)
     
//================================================
//
// BodyPartForJoint
//
// Returns the body part a joint is associated with
//================================================
 int BodyPartForPolyGroup(int polygroup)
     
//================================================
//
// BodyPartForPolyGroup
//
//================================================
 bool BodyPartSeverable(int BodyPart)
     
//================================================
//
// BodyPartSeverable
//
//================================================
 void Breath()
     
//------------------------------------------------
//
// Breath
//
//------------------------------------------------
 bool CanPickup(Inventory item)
     
//================================================
//
// CanPickup
//
// Let's pawn dictate what it can pick up
//================================================
 void DoStow()
     
//------------------------------------------------
//
// DoStow(notify)
//
// Creates a new weapon for the Dwarf (if he has already thrown his weapon)
//------------------------------------------------
 bool InAttackRange(Actor Other)
     
//================================================
//
// InAttackRange
//
//================================================
 bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
     
//================================================
//
// JointDamaged
//
//================================================
 void LimbSevered(int BodyPart, vector Momentum)
     
//================================================
//
// LimbSevered
//
//================================================
 void LongFall()
 Texture PainSkin(int BodyPart)
     
//================================================
//
// PainSkin
//
// returns the pain skin for a given polygroup
//================================================
 void PlayAttack1(optional float)
 void PlayAttack2(optional float)
 void PlayAttack3(optional float)
 void PlayBackDeath(name DamageType)
 void PlayBackup(optional float)
 void PlayBlockHigh(optional float)
 void PlayBlockLow(optional float)
 void PlayBodyHit(optional float)
 void PlayCower(optional float)
 void PlayDeath(name DamageType)
 void PlayDodgeBack(optional float)
 void PlayDodgeBackflip(optional float)
 void PlayDodgeDuck(optional float)
 void PlayDodgeForward(optional float)
 void PlayDodgeLeft(optional float)
 void PlayDodgeRight(optional float)
 void PlayDrownDeath(name DamageType)
 void PlayDrowning(optional float)
 void PlayFrontHit(float tweentime)
 void PlayHeadDeath(name DamageType)
 void PlayHeadHit(optional float)
 void PlayHuntStop(optional float)
 void PlayInAir(optional float)
 void PlayJumping(optional float)
 void PlayLArmHit(optional float)
 void PlayLLegHit(optional float)
 void PlayLanding(optional float)
 void PlayLeftDeath(name DamageType)
 void PlayMoving(optional float)
 void PlayRArmHit(optional float)
 void PlayRLegHit(optional float)
 void PlayRightDeath(name DamageType)
 void PlaySkewerDeath(name DamageType)
 void PlayStrafeLeft(optional float)
 void PlayStrafeRight(optional float)
 void PlayTaunting(optional float)
 void PlayThrowing(optional float)
 void PlayTurning(optional float)
 void PlayWaiting(optional float)
     
//-----------------------------------------------------------------------------
// Animation functions
//-----------------------------------------------------------------------------
 void PostBeginPlay()
     
//===================================================================
//
// PostBeginPlay
// 
//===================================================================
 void TweenToHuntStop(float time)
 void TweenToJumping(float time)
 void TweenToMeleeHigh(float time)
 void TweenToMeleeLow(float time)
 void TweenToMoving(float time)
 void TweenToThrowing(float time)
 void TweenToTurning(float time)
 void TweenToWaiting(float time)
     
// Tween functions


State Fighting Function Summary
 void CreatureStatue()
     
//================================================
//
// Statue
//
//================================================
 void CalcLunge()
     
//===============================================================
 void Timer()
     
// Determine AttackAction based upon enemy movement and position
 void PickDestinationBackup()
 void PickStrafeDestination()
 void SpeechTimer()
 void Bump(Actor Other)
 void AmbientSoundTimer()
 void EndState()
 void BeginState()


State KnockedDown Function Summary



Source Code


00001	//-----------------------------------------------------------
00002	//     SarkBallBotDwarf
00003	//-----------------------------------------------------------
00004	class SarkBallBotDwarf expands SarkBallBot;
00005	
00006	
00007	   /*
00008	     Description:
00009	
00010	     Types:
00011	          Woodland Dwarf (same as generic Dwarf)
00012	          Woodland Dwarf Small
00013	          Woodland Dwarf Big
00014	          Underground Dwarf1
00015	          Underground Dwarf2
00016	          Underground Dwarf3
00017	          Underground Dwarf4
00018	          Underground Dwarf5
00019	          Underground Dwarf6
00020	          Dark Dwarf
00021	*/
00022	
00023	var(Combat) bool     bThrowWeapon;
00024	var(Combat) float     ThrowRange;
00025	var() float     MaxBashThrust;
00026	var() int BashDamage;
00027	
00028	var bool bShieldBashing;
00029	var vector bashVelocity;
00030	var float decision;
00031	var private int breathcounter;
00032	
00033	var(Sounds) sound     BashSound;
00034	
00035	
00036	//===================================================================
00037	//
00038	// PostBeginPlay
00039	// 
00040	//===================================================================
00041	
00042	function PostBeginPlay()
00043	{
00044	     Super.PostBeginPlay();
00045	
00046	     switch(Level.Game.Difficulty)
00047	     {
00048	     case 0: // Easy
00049	          BashDamage = Default.BashDamage * 0.5;
00050	          break;
00051	     case 2: // Hard
00052	          BashDamage = Default.BashDamage * 1.5;
00053	          break;
00054	     }
00055	}
00056	
00057	//------------------------------------------------
00058	//
00059	// AttitudeToCreature
00060	//
00061	//------------------------------------------------
00062	function eAttitude AttitudeToCreature(Pawn Other)
00063	{
00064	     if (Other.IsA('Goblin'))
00065	          return ATTITUDE_Hate;
00066	     else
00067	          return Super.AttitudeToCreature(Other);
00068	}
00069	
00070	
00071	//================================================
00072	//
00073	// CanPickup
00074	//
00075	// Let's pawn dictate what it can pick up
00076	//================================================
00077	function bool CanPickup(Inventory item)
00078	{
00079	     if (Health <= 0)
00080	          return false;
00081	
00082	     if (item.IsA('Weapon') && (BodyPartHealth[BODYPART_RARM1] > 0) && (Weapon == None))
00083	     {
00084	          return (item.IsA('axe') || item.IsA('hammer') || item.IsA('Sword') || item.IsA('Torch'));
00085	     }
00086	     else if (item.IsA('Shield') && (BodyPartHealth[BODYPART_LARM1] > 0) && (Shield == None))
00087	     {
00088	          return item.IsA('Shield');
00089	     }
00090	     return(false);
00091	}
00092	
00093	
00094	//================================================
00095	//
00096	// InAttackRange
00097	//
00098	//================================================
00099	function bool InAttackRange(Actor Other)
00100	{
00101	     local float range;
00102	
00103	     if (Pawn(Other) == None)
00104	          return false;
00105	
00106	     range = VSize(Location-Other.Location);
00107	
00108	     if (range < CollisionRadius + Other.CollisionRadius + MeleeRange)
00109	          return true;
00110	
00111	     if (bLungeAttack && FRand()<0.1 && range < LungeRange)
00112	          return true;
00113	
00114	     if (bThrowWeapon && Weapon!=None && Pawn(Other).Health<20 && range<ThrowRange)
00115	          return true;
00116	
00117	     return false;
00118	}
00119	
00120	
00121	//------------------------------------------------
00122	//
00123	// Breath
00124	//
00125	//------------------------------------------------
00126	function Breath()
00127	{
00128	     local int joint;
00129	     local vector l;
00130	
00131	     if (++breathcounter > 1)
00132	     {
00133	          breathcounter = 0;
00134	          OpenMouth(0.5, 0.5);
00135	
00136	          if (HeadRegion.Zone.bWaterZone)
00137	          {
00138	               // Spawn Bubbles
00139	               joint = JointNamed('jaw');
00140	               if (joint != 0)
00141	               {
00142	                    l = GetJointPos(joint);
00143	                    if(FRand() < 0.3)
00144	                    {
00145	                         Spawn(class'BubbleSystemOneShot',,, l,);
00146	                    }
00147	               }
00148	          }
00149	          else
00150	          {
00151	               PlaySound(BreathSound, SLOT_Interface,,,, 1.0 + FRand()*0.2-0.1);
00152	          }
00153	     }
00154	     else
00155	     {
00156	          OpenMouth(0.0, 0.3);
00157	     }
00158	}
00159	
00160	
00161	//================================================
00162	//
00163	// PainSkin
00164	//
00165	// returns the pain skin for a given polygroup
00166	//================================================
00167	function Texture PainSkin(int BodyPart)
00168	{
00169	     switch(BodyPart)
00170	     {
00171	          case BODYPART_TORSO:
00172	               SkelGroupSkins[1] = Texture'creatures.dwarfw_bodypain';
00173	               SkelGroupSkins[4] = Texture'creatures.dwarfw_bodypain';
00174	               SkelGroupSkins[7] = Texture'creatures.dwarfw_bodypain';
00175	               break;
00176	          case BODYPART_HEAD:
00177	               SkelGroupSkins[2]  = Texture'creatures.dwarfw_bodypain';
00178	               SkelGroupSkins[12] = Texture'creatures.dwarfw_facepain';
00179	               break;
00180	          case BODYPART_LARM1:
00181	               SkelGroupSkins[11] = Texture'creatures.dwarfw_armpain';
00182	               break;
00183	          case BODYPART_RARM1:
00184	               SkelGroupSkins[3] = Texture'creatures.dwarfw_armpain';
00185	               break;
00186	          case BODYPART_LLEG1:
00187	               SkelGroupSkins[10] = Texture'creatures.dwarfw_legpain';
00188	               break;
00189	          case BODYPART_RLEG1:
00190	               SkelGroupSkins[9] = Texture'creatures.dwarfw_legpain';
00191	               break;
00192	     }
00193	     return None;
00194	}
00195	
00196	//================================================
00197	//
00198	// BodyPartForJoint
00199	//
00200	// Returns the body part a joint is associated with
00201	//================================================
00202	function int BodyPartForJoint(int joint)
00203	{
00204	     switch(joint)
00205	     {
00206	          case 2: case 3:     case 4: case 5:          return BODYPART_LLEG1;
00207	          case 6: case 7:     case 8: case 9:          return BODYPART_RLEG1;
00208	          case 17:                                   return BODYPART_HEAD;
00209	          case 20: case 21: case 22:               return BODYPART_LARM1;
00210	          case 26: case 27: case 28:               return BODYPART_RARM1;
00211	          case 11:                                   return BODYPART_TORSO;
00212	          default:                                   return BODYPART_BODY;
00213	     }
00214	}
00215	
00216	//================================================
00217	//
00218	// BodyPartForPolyGroup
00219	//
00220	//================================================
00221	function int BodyPartForPolyGroup(int polygroup)
00222	{
00223	     switch(polygroup)
00224	     {
00225	          case 1: case 4: case 7:
00226	          case 5: case 6:     case 8:     return BODYPART_TORSO;
00227	          case 2: case 12:          return BODYPART_HEAD;
00228	          case 3:                         return BODYPART_RARM1;
00229	          case 11:                    return BODYPART_LARM1;
00230	          case 9:                         return BODYPART_RLEG1;
00231	          case 10:                    return BODYPART_LLEG1;
00232	          default:                    return BODYPART_BODY;
00233	     }
00234	}
00235	
00236	
00237	//================================================
00238	//
00239	// BodyPartSeverable
00240	//
00241	//================================================
00242	function bool BodyPartSeverable(int BodyPart)
00243	{
00244	     switch(BodyPart)
00245	     {
00246	          case BODYPART_LARM1:
00247	          case BODYPART_RARM1:
00248	          case BODYPART_LLEG1:
00249	          case BODYPART_RLEG1:
00250	          case BODYPART_HEAD:
00251	               return true;
00252	     }
00253	     return false;
00254	}
00255	
00256	
00257	//================================================
00258	//
00259	// BodyPartCritical
00260	//
00261	//================================================
00262	function bool BodyPartCritical(int BodyPart)
00263	{
00264	     return (BodyPart==BODYPART_LLEG1 || BodyPart==BODYPART_RLEG1 || BodyPart==BODYPART_HEAD);
00265	}
00266	
00267	
00268	//============================================================
00269	//
00270	// ApplyGoreCap
00271	//
00272	//============================================================
00273	function ApplyGoreCap(int BodyPart)
00274	{
00275	     switch(BodyPart)
00276	     {
00277	          case BODYPART_LARM1:
00278	               SkelGroupSkins[6] = Texture'runefx.gore_bone';
00279	               SkelGroupFlags[6] = SkelGroupFlags[6] & ~POLYFLAG_INVISIBLE;
00280	               break;
00281	          case BODYPART_RARM1:
00282	               SkelGroupSkins[5] = Texture'runefx.gore_bone';
00283	               SkelGroupFlags[5] = SkelGroupFlags[5] & ~POLYFLAG_INVISIBLE;
00284	               break;
00285	          case BODYPART_HEAD:
00286	               SkelGroupSkins[8] = Texture'runefx.w_neckgore';
00287	               SkelGroupFlags[8] = SkelGroupFlags[8] & ~POLYFLAG_INVISIBLE;
00288	               break;
00289	     }
00290	}
00291	
00292	
00293	//================================================
00294	//
00295	// SeveredLimbClass
00296	//
00297	//================================================
00298	function class<Actor> SeveredLimbClass(int BodyPart)
00299	{
00300	     switch(BodyPart)
00301	     {
00302	          case BODYPART_LLEG1:
00303	          case BODYPART_RLEG1:
00304	               //TODO: Don't sever legs
00305	               break;
00306	          case BODYPART_LARM1:
00307	               return class'WoodDwarfLArm';
00308	               break;
00309	          case BODYPART_RARM1:
00310	               return class'WoodDwarfRArm';
00311	               break;
00312	          case BODYPART_HEAD:
00313	               return class'WoodDwarfAHead';
00314	               break;
00315	     }
00316	
00317	     return None;
00318	}
00319	
00320	
00321	//================================================
00322	//
00323	// LimbSevered
00324	//
00325	//================================================
00326	function LimbSevered(int BodyPart, vector Momentum)
00327	{
00328	     local int joint;
00329	     local vector X,Y,Z,pos;
00330	     local actor part;
00331	     local class<actor> partclass;
00332	     
00333	     Super.LimbSevered(BodyPart, Momentum);
00334	
00335	     ApplyGoreCap(BodyPart);
00336	     partclass = SeveredLimbClass(BodyPart);
00337	
00338	     part = None;
00339	     switch(BodyPart)
00340	     {
00341	          case BODYPART_LLEG1:
00342	               joint = JointNamed('lhip');
00343	               pos = GetJointPos(joint);
00344	               GetAxes(Rotation, X, Y, Z);
00345	               part = Spawn(partclass,,, pos, Rotation);
00346	               if(part != None)
00347	               {
00348	                    part.Velocity = -Y * 100 + vect(0, 0, 175);
00349	                    part.GotoState('Drop');
00350	               }
00351	               part = Spawn(class'BloodSpurt', self,, pos, Rotation);
00352	               if(part != None)
00353	               {
00354	                    AttachActorToJoint(part, joint);
00355	               }
00356	               break;
00357	          case BODYPART_RLEG1:
00358	               joint = JointNamed('rhip');
00359	               pos = GetJointPos(joint);
00360	               GetAxes(Rotation, X, Y, Z);
00361	               part = Spawn(partclass,,, pos, Rotation);
00362	               if(part != None)
00363	               {
00364	                    part.Velocity = -Y * 100 + vect(0, 0, 175);
00365	                    part.GotoState('Drop');
00366	               }
00367	               part = Spawn(class'BloodSpurt', self,, pos, Rotation);
00368	               if(part != None)
00369	               {
00370	                    AttachActorToJoint(part, joint);
00371	               }
00372	               break;
00373	          case BODYPART_LARM1:
00374	               joint = JointNamed('lshoulda');
00375	               pos = GetJointPos(joint);
00376	               part = Spawn(partclass,,, pos, Rotation);
00377	               if(part != None)
00378	               {
00379	                    part.Velocity = Y * 100 + vect(0, 0, 175);
00380	                    part.GotoState('Drop');
00381	               }
00382	               part = Spawn(class'BloodSpurt', self,, pos, Rotation);
00383	               if(part != None)
00384	               {
00385	                    AttachActorToJoint(part, joint);
00386	               }
00387	               break;
00388	          case BODYPART_RARM1:
00389	               joint = JointNamed('rshoulda');
00390	               pos = GetJointPos(joint);
00391	               part = Spawn(partclass,,, pos, Rotation);
00392	               if(part != None)
00393	               {
00394	                    part.Velocity = Y * 100 + vect(0, 0, 175);
00395	                    part.GotoState('Drop');
00396	               }
00397	               part = Spawn(class'BloodSpurt', self,, pos, Rotation);
00398	               if(part != None)
00399	               {
00400	                    AttachActorToJoint(part, joint);
00401	               }
00402	               break;
00403	          case BODYPART_HEAD:
00404	               joint = JointNamed('head');
00405	               pos = GetJointPos(joint);
00406	               part = Spawn(partclass,,, pos, Rotation);
00407	               if(part != None)
00408	               {
00409	                    part.Velocity = 0.75 * (momentum / Mass) + vect(0, 0, 300);
00410	                    part.GotoState('Drop');
00411	               }
00412	               part = Spawn(class'BloodSpurt', self,, pos, Rotation);
00413	               if(part != None)
00414	               {
00415	                    AttachActorToJoint(part, joint);
00416	               }
00417	               break;
00418	     }
00419	}
00420	
00421	//================================================
00422	//
00423	// JointDamaged
00424	//
00425	//================================================
00426	function bool JointDamaged(int Damage, Pawn EventInstigator, vector HitLoc, vector Momentum, name DamageType, int joint)
00427	{
00428	     local vector vel;
00429	     local bool rtn;
00430	     if((DamageType == 'thrownweaponblunt' && FRand() < 0.4) 
00431	          || (DamageType == 'blunt' && Damage > 30 && FRand() < 0.5))
00432	     {
00433	          vel = Momentum/Mass;
00434	          vel.Z = 50;
00435	          Velocity = vel;
00436	          SetPhysics(PHYS_Falling);
00437	
00438	          GotoState('KnockedDown');
00439	     }
00440	     rtn = Super.JointDamaged(Damage, EventInstigator, HitLoc, Momentum, DamageType, joint);
00441	     return rtn;
00442	}
00443	
00444	
00445	
00446	//-----------------------------------------------------------------------------
00447	// Animation functions
00448	//-----------------------------------------------------------------------------
00449	function PlayWaiting(optional float tween)
00450	{
00451	     LoopAnim  ('idleA',    RandRange(0.8, 1.2), tween);
00452	}
00453	function PlayMoving(optional float tween)
00454	{
00455	     if (bHurrying)
00456	     {
00457	          LoopAnim  ('runA',     1.0, tween);
00458	     }
00459	     else
00460	     {
00461	          if (Weapon==None)                              LoopAnim  ('walk',     1.0, tween);
00462	          else if (Weapon.IsA('Torch'))               LoopAnim  ('walktorch',1.0, tween);
00463	          else                                             LoopAnim  ('walk',     1.0, tween);
00464	     }
00465	}
00466	function PlayStrafeLeft(optional float tween) { LoopAnim  ('strafeleft',     1.0, tween);     }
00467	function PlayStrafeRight(optional float tween){ LoopAnim  ('straferight',     1.0, tween);     }
00468	function PlayBackup(optional float tween)       { LoopAnim  ('backupA',          1.0, tween);     }
00469	function PlayJumping(optional float tween)    { PlayAnim  ('jump',          1.0, tween);     }
00470	function PlayHuntStop(optional float tween)   { LoopAnim  ('idleA',          1.0, tween);     }
00471	function PlayTurning(optional float tween)
00472	{
00473	                                                            PlayAnim  ('runA',          1.0, tween);
00474	}
00475	function PlayAttack1(optional float tween)     { PlayAnim('attackA',     1.0, tween);     }
00476	function PlayAttack2(optional float tween)     { PlayAnim('attackB',     1.0, tween);     }
00477	function PlayAttack3(optional float tween)     { PlayAnim('attackC',     1.0, tween);     }
00478	
00479	function PlayCower(optional float tween)      { LoopAnim  ('cower',          1.0, tween);   }
00480	function PlayThrowing(optional float tween)       { PlayAnim  ('throwB',   1.0, tween); }
00481	function PlayTaunting(optional float tween)   { PlayAnim  ('pain',      1.0, tween);   }
00482	function PlayInAir(optional float tween)
00483	{
00484	     LoopAnim  ('fallingA',     1.0, tween);
00485	}
00486	function LongFall()
00487	{
00488	     if (AnimSequence != 'fallingC')
00489	          LoopAnim  ('fallingC',     1.0, 0.1);
00490	}
00491	function PlayLanding(optional float tween)
00492	{
00493	     if (AnimSequence == 'fallingC')
00494	          PlayAnim('landingC', 1.0, 0.1);
00495	     else if (AnimSequence == 'fallingB')
00496	          PlayAnim('landingB', 1.0, 0.1);
00497	     else
00498	          PlayAnim('landingA', 1.0, 0.1);
00499	}
00500	
00501	function PlayDodgeLeft(optional float tween)  { PlayAnim  ('runA',   1.0, tween);   }
00502	function PlayDodgeRight(optional float tween) { PlayAnim  ('runA',   1.0, tween);   }
00503	function PlayDodgeForward(optional float tween){PlayAnim  ('runA',   1.0, tween);   }
00504	function PlayDodgeBack(optional float tween)  { PlayAnim  ('runA',   1.0, tween);   }
00505	function PlayDodgeBackflip(optional float tween){PlayAnim ('jump',   1.0, tween);   }
00506	function PlayDodgeDuck(optional float tween)  { PlayAnim  ('duck',   1.0, tween);   }
00507	function PlayBlockHigh(optional float tween)  { LoopAnim  ('duck',   1.0, tween);   }
00508	function PlayBlockLow(optional float tween)   { LoopAnim  ('block',  1.0, tween);   }
00509	
00510	function PlayFrontHit(float tweentime){}
00511	function PlayHeadHit(optional float tween)    { PlayAnim  ('damage',   1.0, tween);   }
00512	function PlayBodyHit(optional float tween)    { PlayAnim  ('damage',   1.0, tween);   }
00513	function PlayLArmHit(optional float tween)    { PlayAnim  ('damage',   1.0, tween);   }
00514	function PlayRArmHit(optional float tween)    { PlayAnim  ('damage',   1.0, tween);   }
00515	function PlayLLegHit(optional float tween)    { PlayAnim  ('damage',   1.0, tween);   }
00516	function PlayRLegHit(optional float tween)    { PlayAnim  ('damage',   1.0, tween);   }
00517	function PlayDrowning(optional float tween)   { LoopAnim  ('drown',  1.0, tween);     }
00518	
00519	function PlayBackDeath(name DamageType)       { PlayAnim  ('deathf', 1.0, 0.1);          }
00520	function PlayLeftDeath(name DamageType)       { PlayAnim  ('deathl', 1.0, 0.1);          }
00521	function PlayRightDeath(name DamageType)      { PlayAnim  ('deathr', 1.0, 0.1);          }
00522	function PlayHeadDeath(name DamageType)       { PlayAnim  ('deathf', 1.0, 0.1);          }
00523	function PlayDeath(name DamageType)                 {     PlayAnim  ('deatha', 1.0, 0.1);          }
00524	function PlayDrownDeath(name DamageType)      { PlayAnim  ('drown_death', 1.0, 0.1);}
00525	function PlaySkewerDeath(name DamageType)       { PlayAnim  ('deaths', 1.0, 0.1);          }
00526	
00527	// Tween functions
00528	function TweenToWaiting(float time)
00529	{
00530	     TweenAnim ('idleA',          time);
00531	}
00532	function TweenToMoving(float time)
00533	{
00534	     if (bHurrying)
00535	     {
00536	          TweenAnim ('runA',   time);
00537	     }
00538	     else
00539	     {
00540	          if (Weapon==None)                              TweenAnim ('walk',     time);
00541	          else if (Weapon.IsA('Torch'))               TweenAnim ('walktorch',time);
00542	          else                                             TweenAnim ('walk',     time);
00543	     }
00544	}
00545	function TweenToTurning(float time)           {     TweenAnim ('runA',    time);         }
00546	function TweenToJumping(float time)           {     TweenAnim ('jump',    time);         }
00547	function TweenToHuntStop(float time)          { TweenAnim ('idleA',   time);         }
00548	function TweenToMeleeHigh(float time)
00549	{
00550	                                                            TweenAnim ('attackA', time);
00551	}
00552	function TweenToMeleeLow(float time)
00553	{
00554	                                                            TweenAnim ('attackA', time);
00555	}
00556	function TweenToThrowing(float time)          { TweenAnim ('throwA',  time);         }
00557	
00558	//------------------------------------------------
00559	//
00560	// DoStow(notify)
00561	//
00562	// Creates a new weapon for the Dwarf (if he has already thrown his weapon)
00563	//------------------------------------------------
00564	
00565	function DoStow()
00566	{
00567	     local Weapon w;
00568	
00569	     w = Spawn(StartWeapon, self,, Location);
00570	     w.Touch(self);
00571	}
00572	
00573	
00574	
00575	//-----------------------------------------------------------------------------
00576	// Sound Functions
00577	//-----------------------------------------------------------------------------
00578	
00579	
00580	//-----------------------------------------------------------------------------
00581	// States
00582	//-----------------------------------------------------------------------------
00583	
00584	//================================================
00585	//
00586	// KnockedDown
00587	//
00588	//================================================
00589	State KnockedDown
00590	{
00591	     ignores EnemyAcquired, SeePlayer, HearNoise;
00592	
00593	Begin:
00594	     PlayAnim('deatha', 1.0, 0.1);     // Fall down
00595	     FinishAnim();
00596	
00597	     Sleep(0.5);     // Stun Time
00598	     WaitForLanding();
00599	
00600	GettingUp:
00601	     PlayAnim('getup', 1.0, 0.7);
00602	     FinishAnim();
00603	     GotoState('TacticalDecision');
00604	}
00605	
00606	
00607	//================================================
00608	//
00609	// Fighting
00610	//
00611	//================================================
00612	State Fighting
00613	{
00614	ignores EnemyAcquired;
00615	
00616	     function BeginState()
00617	     {
00618	          LookAt(Enemy);
00619	          bHurrying = true;
00620	          UpdateMovementSpeed();
00621	          bAvoidLedges=true;
00622	          SetTimer(0.1, true);
00623	          AttackAction = AA_LUNGE;
00624	          bStopMoveIfCombatRange = true;
00625	     }
00626	
00627	     function EndState()
00628	     {
00629	          Super.WeaponDeactivate();
00630	          bAvoidLedges=false;
00631	          SetTimer(0, false);
00632	          if (Weapon!=None)
00633	               Weapon.FinishAttack();
00634	          LookAt(None);
00635	          bStopMoveIfCombatRange = false;
00636	     }
00637	
00638	     function AmbientSoundTimer()
00639	     {
00640	          PlayAmbientFightSound();
00641	     }
00642	
00643	     function Bump(actor Other)
00644	     {
00645	          local vector thrust;
00646	
00647	          if (bShieldBashing)
00648	          {
00649	               if (Pawn(Other)!=None)
00650	               {
00651	                    bashVelocity = Velocity;
00652	                    Velocity.Z = 5;
00653	                    thrust = (Velocity * 5 * Mass + Other.Velocity*Other.Mass)/(Mass+Other.Mass);
00654	                    if (VSize(thrust) > MaxBashThrust)
00655	                         thrust = Normal(thrust)*MaxBashThrust;
00656	                    Pawn(Other).AddVelocity(thrust);
00657	
00658	                    // Do bash damage if velocity > some amount                    
00659	                    Other.JointDamaged(BashDamage, self, Other.Location, thrust, 'blunt', 0);
00660	
00661	                    //TODO: If velocity > some amount, knock enemy down
00662	
00663	                    // throw back, need to use timer because bump zeros velocity upon returning
00664	                    SpeechTime = 0.1;
00665	               }
00666	
00667	               bShieldBashing = false;     // Don't bash again
00668	          }
00669	     }
00670	
00671	     function SpeechTimer()
00672	     {
00673	          SetPhysics(PHYS_Falling);
00674	          Velocity = -bashVelocity*0.2;
00675	     }
00676	
00677	     function PickStrafeDestination()
00678	     {          
00679	          local vector V;
00680	          local rotator R;
00681	          local vector temp;
00682	          
00683	          V = Location - Enemy.Location;
00684	          R = rotator(V);
00685	          
00686	          if (AttackAction == AA_STRAFE_LEFT)
00687	               R.Yaw += 2000;
00688	          else
00689	               R.Yaw -= 2000;
00690	
00691	          // Strafe using the enemy's XY location, but the viking's location ground plane          
00692	          temp = Enemy.Location;
00693	          temp.Z = Location.Z;
00694	
00695	          Destination = temp + vector(R) * CombatRange;
00696	     }
00697	     
00698	     function PickDestinationBackup()
00699	     {
00700	          local vector ToEnemy;
00701	
00702	          ToEnemy = Normal(Enemy.Location - Location);
00703	          Destination = Enemy.Location - ToEnemy * CombatRange;
00704	
00705	     }
00706	
00707	     // Determine AttackAction based upon enemy movement and position
00708	     function Timer()
00709	     {
00710	          GetEnemyProximity();
00711	
00712	          LastAction = AttackAction;
00713	
00714	          if(Weapon != None && InMeleeRange(Enemy) || (EnemyMovement == MOVE_CLOSER && EnemyDist < MeleeRange * 2.5))
00715	          {
00716	               if (Shield != None && FRand()<0.1)
00717	               {
00718	                    AttackAction = AA_BLOCK;
00719	               }
00720	               else if (Health < Default.Health*0.5)
00721	               {
00722	                    AttackAction = AA_BACKUP;
00723	               }
00724	               else if (EnemyIncidence == INC_LEFT)
00725	               {     // Swing left
00726	                    AttackAction = AA_ATTACKMELEE2;
00727	               }
00728	               else if (EnemyIncidence == INC_RIGHT)
00729	               {
00730	                    AttackAction = AA_ATTACKMELEE3;
00731	               }
00732	               else if (FRand() < 0.2)
00733	               {
00734	                    AttackAction = AA_ATTACKMELEE1;
00735	               }
00736	               else if (FRand() < 0.5)
00737	               {
00738	                    AttackAction = AA_ATTACKMELEE2;
00739	               }
00740	               else
00741	               {
00742	                    AttackAction = AA_ATTACKMELEE2;
00743	               }
00744	          }
00745	          else if(Weapon == None && StartWeapon != None)
00746	          { // Grab a new weapon
00747	               AttackAction = AA_RETRIEVE_WEAPON;
00748	          }
00749	          else if ((EnemyMovement == MOVE_STRAFE_LEFT || EnemyMovement == MOVE_STRAFE_RIGHT) &&
00750	               !InRange(Enemy, MeleeRange * 3) && (FRand() < 0.9))
00751	          {
00752	               if(EnemyMovement == MOVE_STRAFE_LEFT)
00753	               {
00754	                    AttackAction = AA_STRAFE_LEFT;
00755	               }
00756	               else
00757	               {
00758	                    AttackAction = AA_STRAFE_RIGHT;
00759	               }
00760	          }
00761	          else if(InRange(Enemy, MeleeRange * 5) && (FRand() < 0.6))
00762	          {
00763	               AttackAction = AA_STRAFE_LEFT;
00764	          }
00765	          else if(EnemyMovement == MOVE_STANDING && FRand() < 0.3)
00766	          {
00767	               if (!InRange(Enemy, MeleeRange) && FRand() < 0.19452) // Carefully tweaked value -cjr
00768	                    AttackAction = AA_LUNGE;
00769	               else
00770	                    AttackAction = AA_WAIT;
00771	          }
00772	          else if(Weapon != None && bThrowWeapon && EnemyMovement == MOVE_FARTHER && FRand() < 0.7)
00773	          {
00774	               AttackAction = AA_THROW;
00775	          }
00776	          else
00777	          {
00778	               AttackAction = AA_WAIT;
00779	          }
00780	     }
00781	
00782	     //===============================================================
00783	     //
00784	     // CalcLunge
00785	     //
00786	     // Calculates a lunge for the Dwarf
00787	     //===============================================================
00788	
00789	     function CalcLunge()
00790	     {
00791	          local vector dest;
00792	
00793	          if(Enemy == None)
00794	               return;
00795	
00796	          dest = Enemy.Location;
00797	          AddVelocity(CalcArcVelocity(4000, Location, dest));
00798	     }
00799	
00800	Begin:
00801	     if(debugstates) SLog(name@"Fighting");
00802	     Acceleration = vect(0,0,0);
00803	
00804	Fight:
00805	     if ( !ValidEnemy() )
00806	          Goto('Finished');
00807	
00808	     // Turn to face enemy
00809	     if (NeedToTurn(Enemy.Location))
00810	     {
00811	          DesiredRotation.Yaw = rotator(Enemy.Location-Location).Yaw;
00812	     }
00813	
00814	     switch(AttackAction)
00815	     {
00816	     case AA_WAIT:
00817	          PlayWaiting(0.1);
00818	          Sleep(0.2);
00819	          break;
00820	
00821	     case AA_LUNGE:
00822	          bStopMoveIfCombatRange = false;
00823	
00824	          TweenAnim('shieldbash', 0.3);
00825	bashturn:
00826	          DesiredRotation = rotator(Enemy.Location-Location);
00827	
00828	          if(Level.Game.Difficulty == 0) // Easy mode
00829	               Sleep(0.75);
00830	          else if(Level.Game.Difficulty == 1) // Medium mode
00831	               Sleep(0.5);
00832	          else // Hard mode
00833	               Sleep(0.25);
00834	
00835	          if (IsAnimating())
00836	               Goto('bashturn');
00837	
00838	          bShieldBashing = true;
00839	          switch(Rand(4))
00840	          {
00841	               case 0:
00842	                    PlayAnim('AttackA', 1.0, 0.1);
00843	                    break;
00844	               case 1:
00845	                    PlayAnim('AttackB', 1.0, 0.1);
00846	                    break;
00847	               case 2:
00848	                    PlayAnim('AttackC', 1.0, 0.1);
00849	                    break;
00850	               case 3:     // Normal lunge
00851	                    PlayAnim('shieldbash', 1.0, 0.1);
00852	                    Sleep(0.28);
00853	                    PlaySound(BashSound, SLOT_Interact,,,, 1.0 + FRand()*0.2-0.1);
00854	                    break;
00855	          }
00856	          CalcLunge();
00857	          FinishAnim();
00858	          WaitForLanding();
00859	          Sleep(TimeBetweenAttacks);
00860	          bShieldBashing = false;
00861	          bStopMoveIfCombatRange = true;
00862	          break;
00863	
00864	     case AA_STRAFE_LEFT:
00865	          bHurrying = false;
00866	          UpdateMovementSpeed();
00867	          PickStrafeDestination();
00868	          PlayStrafeLeft(0.1);
00869	          StrafeFacing(Destination, Enemy);
00870	          bHurrying = true;
00871	          UpdateMovementSpeed();
00872	          break;
00873	
00874	     case AA_STRAFE_RIGHT:
00875	          bHurrying = false;
00876	          UpdateMovementSpeed();
00877	          PickStrafeDestination();
00878	          PlayStrafeRight(0.1);
00879	          StrafeFacing(Destination, Enemy);
00880	          bHurrying = true;
00881	          UpdateMovementSpeed();
00882	          break;
00883	
00884	     case AA_CHARGE:
00885	          PlayMoving(0.1);
00886	          MoveTo(Enemy.Location - VecToEnemy * MeleeRange, MovementSpeed);
00887	          break;
00888	
00889	     case AA_BACKUP:
00890	          bHurrying = false;
00891	          UpdateMovementSpeed();
00892	          DesiredRotation = rotator(Enemy.Location-Location);
00893	          PlayBackup(0.1);
00894	          PickDestinationBackup();
00895	          StrafeFacing(Destination, Enemy);
00896	          bHurrying = true;
00897	          UpdateMovementSpeed();
00898	          PlayWaiting();
00899	          break;
00900	
00901	     case AA_ATTACKMELEE1:
00902	          PlayAttack1(0.1);
00903	          FinishAnim();
00904	          Sleep(TimeBetweenAttacks);
00905	          break;
00906	
00907	     case AA_ATTACKMELEE2:
00908	          PlayAttack2(0.1);
00909	          FinishAnim();
00910	          Sleep(TimeBetweenAttacks);
00911	          break;
00912	
00913	     case AA_ATTACKMELEE3:
00914	          PlayAttack3(0.1);
00915	          FinishAnim();
00916	          Sleep(TimeBetweenAttacks);
00917	          break;
00918	
00919	     case AA_THROW:
00920	          DesiredRotation = rotator(Enemy.Location-Location);
00921	          Sleep(0.1);
00922	          PlayThrowing();
00923	          FinishAnim();
00924	          break;
00925	
00926	     case AA_BLOCK:
00927	          ActivateShield(true);
00928	          PlayBlockHigh(0.1);
00929	          Sleep(RandRange(0.2, 1));
00930	          FinishAnim();
00931	          ActivateShield(false);
00932	          break;
00933	
00934	     case AA_RETRIEVE_WEAPON:
00935	          PlayAnim('GetWeapon', 1.0, 0.1);
00936	          FinishAnim();
00937	          break;
00938	     }
00939	
00940	     if (InRange(Enemy, CombatRange))
00941	     {
00942	          Sleep(0.05);
00943	          Goto('Begin');
00944	     }
00945	
00946	Finished:
00947	     GotoState('Charging', 'ResumeFromFighting');
00948	}
00949	
00950	
00951	//================================================
00952	//
00953	// Statue
00954	//
00955	//================================================
00956	State() Statue
00957	{
00958	ignores HearNoise, EnemyAcquired, Bump;
00959	
00960	     function CreatureStatue()
00961	     {
00962	          SkelGroupSkins[0] = texture'statues.sb_body_stone';
00963	          SkelGroupSkins[1] = texture'statues.sb_armleg_stone';
00964	          SkelGroupSkins[2] = texture'statues.sb_body_stone';
00965	          SkelGroupSkins[3] = texture'statues.sb_armleg_stone';
00966	          SkelGroupSkins[4] = texture'statues.sb_body_stone';
00967	          SkelGroupSkins[5] = texture'statues.sb_body_stone';
00968	          SkelGroupSkins[6] = texture'statues.sb_body_stone';
00969	          SkelGroupSkins[7] = texture'statues.sb_body_stone';
00970	          SkelGroupSkins[8] = texture'statues.sb_armleg_stone';
00971	          SkelGroupSkins[9] = texture'statues.sb_body_stone';
00972	          SkelGroupSkins[10] = texture'statues.sb_armleg_stone';
00973	          SkelGroupSkins[11] = texture'statues.sb_armleg_stone';
00974	          SkelGroupSkins[12] = texture'statues.sb_armleg_stone';
00975	          SkelGroupSkins[13] = texture'statues.sb_body_stone';
00976	          SkelGroupSkins[14] = texture'statues.sb_body_stone';
00977	          SkelGroupSkins[15] = texture'statues.sb_body_stone';
00978	     }
00979	}
00980	
00981	defaultproperties
00982	{
00983	    bThrowWeapon=True
00984	    ThrowRange=140.00
00985	    MaxBashThrust=750.00
00986	    BashDamage=10
00987	    BashSound=Sound'CreaturesSnd.Dwarves.attack12'
00988	    bLungeAttack=True
00989	    FightOrDefend=0.20
00990	    LatOrVertDodge=0.50
00991	    LungeRange=140.00
00992	    ThrowTrajectory=2500
00993	    BreathSound=Sound'CreaturesSnd.Dwarves.breath06'
00994	    AcquireSound=Sound'CreaturesSnd.Dwarves.word23'
00995	    AmbientWaitSounds(0)=Sound'CreaturesSnd.Dwarves.word36'
00996	    AmbientWaitSounds(1)=Sound'CreaturesSnd.Dwarves.word04'
00997	    AmbientWaitSounds(2)=Sound'CreaturesSnd.Dwarves.word27'
00998	    AmbientFightSounds(0)=Sound'CreaturesSnd.Dwarves.attack14'
00999	    AmbientFightSounds(1)=Sound'CreaturesSnd.Dwarves.attack13'
01000	    AmbientFightSounds(2)=Sound'CreaturesSnd.Dwarves.attack15'
01001	    AmbientWaitSoundDelay=12.00
01002	    AmbientFightSoundDelay=6.00
01003	    StartWeapon=Class'RuneI.DwarfWorkSword'
01004	    StartShield=Class'RuneI.DwarfWoodShield'
01005	    MinStopWait=0.40
01006	    MaxStopWait=1.00
01007	    A_StepUp=pullupB
01008	    CombatRange=200.00
01009	    GroundSpeed=240.00
01010	    JumpZ=400.00
01011	    WalkingSpeed=160.00
01012	    ClassID=2
01013	    Health=130
01014	    BodyPartHealth(6)=100
01015	    BodyPartHealth(8)=100
01016	    UnderWaterTime=2.00
01017	    HitSound1=Sound'CreaturesSnd.Dwarves.hit02'
01018	    HitSound2=Sound'CreaturesSnd.Dwarves.word26'
01019	    HitSound3=Sound'CreaturesSnd.Dwarves.hit07'
01020	    Die=Sound'CreaturesSnd.Dwarves.death09'
01021	    Die2=Sound'CreaturesSnd.Dwarves.death10'
01022	    Die3=Sound'CreaturesSnd.Dwarves.death12'
01023	    FootStepMetal(0)=Sound'FootstepsSnd.Metal.footmetal10'
01024	    FootStepMetal(1)=Sound'FootstepsSnd.Metal.footmetal11'
01025	    FootStepMetal(2)=Sound'FootstepsSnd.Metal.footmetal12'
01026	    FootStepStone(0)=Sound'FootstepsSnd.Earth.footgravel13'
01027	    FootStepStone(1)=Sound'FootstepsSnd.Earth.footgravel12'
01028	    FootStepStone(2)=Sound'FootstepsSnd.Earth.footgravel13'
01029	    FootStepIce(0)=Sound'FootstepsSnd.Ice.footice04'
01030	    FootStepIce(1)=Sound'FootstepsSnd.Ice.footice05'
01031	    FootStepIce(2)=Sound'FootstepsSnd.Ice.footice06'
01032	    FootStepEarth(0)=Sound'FootstepsSnd.Earth.footgravel03'
01033	    FootStepEarth(1)=Sound'FootstepsSnd.Earth.footgravel05'
01034	    FootStepEarth(2)=Sound'FootstepsSnd.Earth.footgravel06'
01035	    FootStepSnow(0)=Sound'FootstepsSnd.Snow.footsnow10'
01036	    FootStepSnow(1)=Sound'FootstepsSnd.Snow.footsnow11'
01037	    FootStepSnow(2)=Sound'FootstepsSnd.Snow.footsnow12'
01038	    PlayerReplicationInfoClass=Class'Engine.PlayerReplicationInfo'
01039	    MaxMouthRot=5000
01040	    MaxMouthRotRate=65535
01041	    DeathRadius=40.00
01042	    DeathHeight=8.00
01043	    AnimSequence=idleA
01044	    TransientSoundRadius=1200.00
01045	    CollisionRadius=35.00
01046	    CollisionHeight=33.00
01047	    Mass=250.00
01048	    Buoyancy=200.00
01049	    Skeletal=SkelModel'creatures.Dwarf'
01050	}

End Source Code