RuneI
Class Dwarf

source: c:\runehov\RuneI\Classes\Dwarf.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Pawn
         |
         +--RuneI.ScriptPawn
            |
            +--RuneI.Dwarf
Direct Known Subclasses:DwarfBlack, DwarfUnderground, DwarfWarA, DwarfWarB, DwarfWarC, DwarfWarD, DwarfWarE, DwarfWarF, DwarfWoodland, DwarfWoodlandBig, DwarfWoodlandSmall

class Dwarf
extends RuneI.ScriptPawn

//============================================================================= // Dwarf. //=============================================================================
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)
//------------------------------------------------
 void DoThrow()
     
//------------------------------------------------
//
// DoThrow (notify)
//
// Throws actor attached to weapon joint at
// Enemy or OrderObject
//------------------------------------------------
 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	// Dwarf.
00003	//=============================================================================
00004	class Dwarf expands ScriptPawn;
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	// DoThrow (notify)
00576	//
00577	// Throws actor attached to weapon joint at
00578	// Enemy or OrderObject
00579	//------------------------------------------------
00580	function DoThrow()
00581	{
00582		local actor throwitem;
00583		local int traj;
00584		local vector throwloc;
00585		local vector dest;
00586	
00587		if (Enemy!=None)
00588			OrderObject = Enemy;
00589		
00590		throwloc = GetJointPos(JointNamed(WeaponJoint));
00591		throwitem = DetachActorFromJoint(JointNamed(WeaponJoint));
00592		if (throwitem != None && OrderObject != None)
00593		{
00594			if(throwItem.IsA('inventory'))
00595				DeleteInventory(Inventory(throwItem));
00596	
00597			traj = ThrowTrajectory;
00598			dest = OrderObject.Location + OrderObject.Velocity * 0.1; // Lead the enemy a bit with the throw
00599			// Throw the item
00600			throwitem.SetPhysics(PHYS_Falling);
00601	//			throwitem.SetLocation(throwloc);	// More accurate this way for some reason
00602			throwitem.Acceleration = vect(0,0,0);
00603			throwitem.Velocity = CalcArcVelocity(traj, throwloc, dest);
00604			throwitem.GotoState('Throw');
00605	
00606			throwitem.SetOwner(self);
00607	
00608			if(Weapon == throwitem)
00609			{
00610				Weapon = None;
00611			}
00612		}
00613	}
00614	
00615	//-----------------------------------------------------------------------------
00616	// Sound Functions
00617	//-----------------------------------------------------------------------------
00618	
00619	
00620	//-----------------------------------------------------------------------------
00621	// States
00622	//-----------------------------------------------------------------------------
00623	
00624	//================================================
00625	//
00626	// KnockedDown
00627	//
00628	//================================================
00629	State KnockedDown
00630	{
00631		ignores EnemyAcquired, SeePlayer, HearNoise;
00632	
00633	Begin:
00634		PlayAnim('deatha', 1.0, 0.1);	// Fall down
00635		FinishAnim();
00636	
00637		Sleep(0.5);	// Stun Time
00638		WaitForLanding();
00639	
00640	GettingUp:
00641		PlayAnim('getup', 1.0, 0.7);
00642		FinishAnim();
00643		GotoState('TacticalDecision');
00644	}
00645	
00646	
00647	//================================================
00648	//
00649	// Fighting
00650	//
00651	//================================================
00652	State Fighting
00653	{
00654	ignores EnemyAcquired;
00655	
00656		function BeginState()
00657		{
00658			LookAt(Enemy);
00659			bHurrying = true;
00660			UpdateMovementSpeed();
00661			bAvoidLedges=true;
00662			SetTimer(0.1, true);
00663			AttackAction = AA_LUNGE;
00664			bStopMoveIfCombatRange = true;
00665		}
00666	
00667		function EndState()
00668		{
00669			Super.WeaponDeactivate();
00670			bAvoidLedges=false;
00671			SetTimer(0, false);
00672			if (Weapon!=None)
00673				Weapon.FinishAttack();
00674			LookAt(None);
00675			bStopMoveIfCombatRange = false;
00676		}
00677	
00678		function AmbientSoundTimer()
00679		{
00680			PlayAmbientFightSound();
00681		}
00682	
00683		function Bump(actor Other)
00684		{
00685			local vector thrust;
00686	
00687			if (bShieldBashing)
00688			{
00689				if (Pawn(Other)!=None)
00690				{
00691					bashVelocity = Velocity;
00692					Velocity.Z = 5;
00693					thrust = (Velocity * 5 * Mass + Other.Velocity*Other.Mass)/(Mass+Other.Mass);
00694					if (VSize(thrust) > MaxBashThrust)
00695						thrust = Normal(thrust)*MaxBashThrust;
00696					Pawn(Other).AddVelocity(thrust);
00697	
00698					// Do bash damage if velocity > some amount				
00699					Other.JointDamaged(BashDamage, self, Other.Location, thrust, 'blunt', 0);
00700	
00701					//TODO: If velocity > some amount, knock enemy down
00702	
00703					// throw back, need to use timer because bump zeros velocity upon returning
00704					SpeechTime = 0.1;
00705				}
00706	
00707				bShieldBashing = false;	// Don't bash again
00708			}
00709		}
00710	
00711		function SpeechTimer()
00712		{
00713			SetPhysics(PHYS_Falling);
00714			Velocity = -bashVelocity*0.2;
00715		}
00716	
00717		function PickStrafeDestination()
00718		{		
00719			local vector V;
00720			local rotator R;
00721			local vector temp;
00722			
00723			V = Location - Enemy.Location;
00724			R = rotator(V);
00725			
00726			if (AttackAction == AA_STRAFE_LEFT)
00727				R.Yaw += 2000;
00728			else
00729				R.Yaw -= 2000;
00730	
00731			// Strafe using the enemy's XY location, but the viking's location ground plane		
00732			temp = Enemy.Location;
00733			temp.Z = Location.Z;
00734	
00735			Destination = temp + vector(R) * CombatRange;
00736		}
00737		
00738		function PickDestinationBackup()
00739		{
00740			local vector ToEnemy;
00741	
00742			ToEnemy = Normal(Enemy.Location - Location);
00743			Destination = Enemy.Location - ToEnemy * CombatRange;
00744	
00745		}
00746	
00747		// Determine AttackAction based upon enemy movement and position
00748		function Timer()
00749		{
00750			GetEnemyProximity();
00751	
00752			LastAction = AttackAction;
00753	
00754			if(Weapon != None && InMeleeRange(Enemy) || (EnemyMovement == MOVE_CLOSER && EnemyDist < MeleeRange * 2.5))
00755			{
00756				if (Shield != None && FRand()<0.1)
00757				{
00758					AttackAction = AA_BLOCK;
00759				}
00760				else if (Health < Default.Health*0.5)
00761				{
00762					AttackAction = AA_BACKUP;
00763				}
00764				else if (EnemyIncidence == INC_LEFT)
00765				{	// Swing left
00766					AttackAction = AA_ATTACKMELEE2;
00767				}
00768				else if (EnemyIncidence == INC_RIGHT)
00769				{
00770					AttackAction = AA_ATTACKMELEE3;
00771				}
00772				else if (FRand() < 0.2)
00773				{
00774					AttackAction = AA_ATTACKMELEE1;
00775				}
00776				else if (FRand() < 0.5)
00777				{
00778					AttackAction = AA_ATTACKMELEE2;
00779				}
00780				else
00781				{
00782					AttackAction = AA_ATTACKMELEE2;
00783				}
00784			}
00785			else if(Weapon == None && StartWeapon != None)
00786			{ // Grab a new weapon
00787				AttackAction = AA_RETRIEVE_WEAPON;
00788			}
00789			else if ((EnemyMovement == MOVE_STRAFE_LEFT || EnemyMovement == MOVE_STRAFE_RIGHT) &&
00790				!InRange(Enemy, MeleeRange * 3) && (FRand() < 0.9))
00791			{
00792				if(EnemyMovement == MOVE_STRAFE_LEFT)
00793				{
00794					AttackAction = AA_STRAFE_LEFT;
00795				}
00796				else
00797				{
00798					AttackAction = AA_STRAFE_RIGHT;
00799				}
00800			}
00801			else if(InRange(Enemy, MeleeRange * 5) && (FRand() < 0.6))
00802			{
00803				AttackAction = AA_STRAFE_LEFT;
00804			}
00805			else if(EnemyMovement == MOVE_STANDING && FRand() < 0.3)
00806			{
00807				if (!InRange(Enemy, MeleeRange) && FRand() < 0.19452) // Carefully tweaked value -cjr
00808					AttackAction = AA_LUNGE;
00809				else
00810					AttackAction = AA_WAIT;
00811			}
00812			else if(Weapon != None && bThrowWeapon && EnemyMovement == MOVE_FARTHER && FRand() < 0.7)
00813			{
00814				AttackAction = AA_THROW;
00815			}
00816			else
00817			{
00818				AttackAction = AA_WAIT;
00819			}
00820		}
00821	
00822		//===============================================================
00823		//
00824		// CalcLunge
00825		//
00826		// Calculates a lunge for the Dwarf
00827		//===============================================================
00828	
00829		function CalcLunge()
00830		{
00831			local vector dest;
00832	
00833			if(Enemy == None)
00834				return;
00835	
00836			dest = Enemy.Location;
00837			AddVelocity(CalcArcVelocity(4000, Location, dest));
00838		}
00839	
00840	Begin:
00841		if(debugstates) SLog(name@"Fighting");
00842		Acceleration = vect(0,0,0);
00843	
00844	Fight:
00845		if ( !ValidEnemy() )
00846			Goto('Finished');
00847	
00848		// Turn to face enemy
00849		if (NeedToTurn(Enemy.Location))
00850		{
00851			DesiredRotation.Yaw = rotator(Enemy.Location-Location).Yaw;
00852		}
00853	
00854		switch(AttackAction)
00855		{
00856		case AA_WAIT:
00857			PlayWaiting(0.1);
00858			Sleep(0.2);
00859			break;
00860	
00861		case AA_LUNGE:
00862			bStopMoveIfCombatRange = false;
00863	
00864			TweenAnim('shieldbash', 0.3);
00865	bashturn:
00866			DesiredRotation = rotator(Enemy.Location-Location);
00867	
00868			if(Level.Game.Difficulty == 0) // Easy mode
00869				Sleep(0.75);
00870			else if(Level.Game.Difficulty == 1) // Medium mode
00871				Sleep(0.5);
00872			else // Hard mode
00873				Sleep(0.25);
00874	
00875			if (IsAnimating())
00876				Goto('bashturn');
00877	
00878			bShieldBashing = true;
00879			switch(Rand(4))
00880			{
00881				case 0:
00882					PlayAnim('AttackA', 1.0, 0.1);
00883					break;
00884				case 1:
00885					PlayAnim('AttackB', 1.0, 0.1);
00886					break;
00887				case 2:
00888					PlayAnim('AttackC', 1.0, 0.1);
00889					break;
00890				case 3:	// Normal lunge
00891					PlayAnim('shieldbash', 1.0, 0.1);
00892					Sleep(0.28);
00893					PlaySound(BashSound, SLOT_Interact,,,, 1.0 + FRand()*0.2-0.1);
00894					break;
00895			}
00896			CalcLunge();
00897			FinishAnim();
00898			WaitForLanding();
00899			Sleep(TimeBetweenAttacks);
00900			bShieldBashing = false;
00901			bStopMoveIfCombatRange = true;
00902			break;
00903	
00904		case AA_STRAFE_LEFT:
00905			bHurrying = false;
00906			UpdateMovementSpeed();
00907			PickStrafeDestination();
00908			PlayStrafeLeft(0.1);
00909			StrafeFacing(Destination, Enemy);
00910			bHurrying = true;
00911			UpdateMovementSpeed();
00912			break;
00913	
00914		case AA_STRAFE_RIGHT:
00915			bHurrying = false;
00916			UpdateMovementSpeed();
00917			PickStrafeDestination();
00918			PlayStrafeRight(0.1);
00919			StrafeFacing(Destination, Enemy);
00920			bHurrying = true;
00921			UpdateMovementSpeed();
00922			break;
00923	
00924		case AA_CHARGE:
00925			PlayMoving(0.1);
00926			MoveTo(Enemy.Location - VecToEnemy * MeleeRange, MovementSpeed);
00927			break;
00928	
00929		case AA_BACKUP:
00930			bHurrying = false;
00931			UpdateMovementSpeed();
00932			DesiredRotation = rotator(Enemy.Location-Location);
00933			PlayBackup(0.1);
00934			PickDestinationBackup();
00935			StrafeFacing(Destination, Enemy);
00936			bHurrying = true;
00937			UpdateMovementSpeed();
00938			PlayWaiting();
00939			break;
00940	
00941		case AA_ATTACKMELEE1:
00942			PlayAttack1(0.1);
00943			FinishAnim();
00944			Sleep(TimeBetweenAttacks);
00945			break;
00946	
00947		case AA_ATTACKMELEE2:
00948			PlayAttack2(0.1);
00949			FinishAnim();
00950			Sleep(TimeBetweenAttacks);
00951			break;
00952	
00953		case AA_ATTACKMELEE3:
00954			PlayAttack3(0.1);
00955			FinishAnim();
00956			Sleep(TimeBetweenAttacks);
00957			break;
00958	
00959		case AA_THROW:
00960			DesiredRotation = rotator(Enemy.Location-Location);
00961			Sleep(0.1);
00962			PlayThrowing();
00963			FinishAnim();
00964			break;
00965	
00966		case AA_BLOCK:
00967			ActivateShield(true);
00968			PlayBlockHigh(0.1);
00969			Sleep(RandRange(0.2, 1));
00970			FinishAnim();
00971			ActivateShield(false);
00972			break;
00973	
00974		case AA_RETRIEVE_WEAPON:
00975			PlayAnim('GetWeapon', 1.0, 0.1);
00976			FinishAnim();
00977			break;
00978		}
00979	
00980		if (InRange(Enemy, CombatRange))
00981		{
00982			Sleep(0.05);
00983			Goto('Begin');
00984		}
00985	
00986	Finished:
00987		GotoState('Charging', 'ResumeFromFighting');
00988	}
00989	
00990	
00991	//================================================
00992	//
00993	// Statue
00994	//
00995	//================================================
00996	State() Statue
00997	{
00998	ignores HearNoise, EnemyAcquired, Bump;
00999	
01000		function CreatureStatue()
01001		{
01002			SkelGroupSkins[0] = texture'statues.sb_body_stone';
01003			SkelGroupSkins[1] = texture'statues.sb_armleg_stone';
01004			SkelGroupSkins[2] = texture'statues.sb_body_stone';
01005			SkelGroupSkins[3] = texture'statues.sb_armleg_stone';
01006			SkelGroupSkins[4] = texture'statues.sb_body_stone';
01007			SkelGroupSkins[5] = texture'statues.sb_body_stone';
01008			SkelGroupSkins[6] = texture'statues.sb_body_stone';
01009			SkelGroupSkins[7] = texture'statues.sb_body_stone';
01010			SkelGroupSkins[8] = texture'statues.sb_armleg_stone';
01011			SkelGroupSkins[9] = texture'statues.sb_body_stone';
01012			SkelGroupSkins[10] = texture'statues.sb_armleg_stone';
01013			SkelGroupSkins[11] = texture'statues.sb_armleg_stone';
01014			SkelGroupSkins[12] = texture'statues.sb_armleg_stone';
01015			SkelGroupSkins[13] = texture'statues.sb_body_stone';
01016			SkelGroupSkins[14] = texture'statues.sb_body_stone';
01017			SkelGroupSkins[15] = texture'statues.sb_body_stone';
01018		}
01019	}
01020	
01021	defaultproperties
01022	{
01023	     bThrowWeapon=True
01024	     ThrowRange=140.000000
01025	     MaxBashThrust=750.000000
01026	     BashDamage=10
01027	     BashSound=Sound'CreaturesSnd.Dwarves.attack12'
01028	     bLungeAttack=True
01029	     FightOrFlight=1.000000
01030	     FightOrDefend=0.200000
01031	     HighOrLow=0.500000
01032	     LatOrVertDodge=0.500000
01033	     HighOrLowBlock=0.500000
01034	     BlockChance=1.000000
01035	     LungeRange=140.000000
01036	     ThrowTrajectory=2500
01037	     BreathSound=Sound'CreaturesSnd.Dwarves.breath06'
01038	     AcquireSound=Sound'CreaturesSnd.Dwarves.word23'
01039	     AmbientWaitSounds(0)=Sound'CreaturesSnd.Dwarves.word36'
01040	     AmbientWaitSounds(1)=Sound'CreaturesSnd.Dwarves.word04'
01041	     AmbientWaitSounds(2)=Sound'CreaturesSnd.Dwarves.word27'
01042	     AmbientFightSounds(0)=Sound'CreaturesSnd.Dwarves.attack14'
01043	     AmbientFightSounds(1)=Sound'CreaturesSnd.Dwarves.attack13'
01044	     AmbientFightSounds(2)=Sound'CreaturesSnd.Dwarves.attack15'
01045	     AmbientWaitSoundDelay=12.000000
01046	     AmbientFightSoundDelay=6.000000
01047	     StartWeapon=Class'RuneI.DwarfWorkSword'
01048	     StartShield=Class'RuneI.DwarfWoodShield'
01049	     MinStopWait=0.400000
01050	     MaxStopWait=1.000000
01051	     ShadowScale=2.000000
01052	     A_StepUp=pullupB
01053	     bCanStrafe=True
01054	     bCanGrabEdges=True
01055	     MeleeRange=40.000000
01056	     CombatRange=200.000000
01057	     GroundSpeed=240.000000
01058	     AccelRate=1000.000000
01059	     JumpZ=400.000000
01060	     MaxStepHeight=30.000000
01061	     WalkingSpeed=160.000000
01062	     ClassID=2
01063	     Health=130
01064	     BodyPartHealth(1)=100
01065	     BodyPartHealth(3)=100
01066	     BodyPartHealth(5)=100
01067	     BodyPartHealth(6)=100
01068	     BodyPartHealth(8)=100
01069	     UnderWaterTime=2.000000
01070	     Intelligence=BRAINS_HUMAN
01071	     HitSound1=Sound'CreaturesSnd.Dwarves.hit02'
01072	     HitSound2=Sound'CreaturesSnd.Dwarves.word26'
01073	     HitSound3=Sound'CreaturesSnd.Dwarves.hit07'
01074	     Die=Sound'CreaturesSnd.Dwarves.death09'
01075	     Die2=Sound'CreaturesSnd.Dwarves.death10'
01076	     Die3=Sound'CreaturesSnd.Dwarves.death12'
01077	     FootStepWood(0)=None
01078	     FootStepWood(1)=None
01079	     FootStepWood(2)=None
01080	     FootStepMetal(0)=Sound'FootstepsSnd.Metal.footmetal10'
01081	     FootStepMetal(1)=Sound'FootstepsSnd.Metal.footmetal11'
01082	     FootStepMetal(2)=Sound'FootstepsSnd.Metal.footmetal12'
01083	     FootStepStone(0)=Sound'FootstepsSnd.Earth.footgravel13'
01084	     FootStepStone(1)=Sound'FootstepsSnd.Earth.footgravel12'
01085	     FootStepStone(2)=Sound'FootstepsSnd.Earth.footgravel13'
01086	     FootStepIce(0)=Sound'FootstepsSnd.Ice.footice04'
01087	     FootStepIce(1)=Sound'FootstepsSnd.Ice.footice05'
01088	     FootStepIce(2)=Sound'FootstepsSnd.Ice.footice06'
01089	     FootStepEarth(0)=Sound'FootstepsSnd.Earth.footgravel03'
01090	     FootStepEarth(1)=Sound'FootstepsSnd.Earth.footgravel05'
01091	     FootStepEarth(2)=Sound'FootstepsSnd.Earth.footgravel06'
01092	     FootStepSnow(0)=Sound'FootstepsSnd.Snow.footsnow10'
01093	     FootStepSnow(1)=Sound'FootstepsSnd.Snow.footsnow11'
01094	     FootStepSnow(2)=Sound'FootstepsSnd.Snow.footsnow12'
01095	     WeaponJoint=attach_hand
01096	     ShieldJoint=attach_shielda
01097	     bCanLook=True
01098	     bHeadLookUpDouble=True
01099	     MaxMouthRot=5000
01100	     MaxMouthRotRate=65535
01101	     DeathRadius=40.000000
01102	     DeathHeight=8.000000
01103	     bLeadEnemy=True
01104	     AnimSequence=idleA
01105	     TransientSoundRadius=1200.000000
01106	     CollisionRadius=35.000000
01107	     CollisionHeight=33.000000
01108	     Mass=250.000000
01109	     Buoyancy=200.000000
01110	     RotationRate=(Pitch=0,Roll=0)
01111	     Skeletal=SkelModel'creatures.Dwarf'
01112	}

End Source Code