UnrealShare
Class DevilFish

source: e:\games\UnrealTournament\UnrealShare\Classes\Devilfish.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Pawn
         |
         +--UnrealShare.ScriptedPawn
            |
            +--UnrealShare.DevilFish
Direct Known Subclasses:None

class DevilFish
extends UnrealShare.ScriptedPawn

//============================================================================= // DevilFish. //=============================================================================
Variables
 float AirTime
 bool bAttackBump
 var() byte

States
TacticalMove, Flopping, MeleeAttack, Ambushing, FallingState, TakeHit, Waiting

Function Summary
 eAttitude AttitudeToCreature(Pawn Other)
 void Landed(vector HitNormal)
 void PlayDying(name DamageType, vector HitLocation)
 void PlayInAir()
 void PlayLanded(float impactVel)
 void PlayMeleeAttack()
 void PlayPatrolStop()
 void PlayRunning()
 void PlayTakeHit(float tweentime, vector HitLoc, int damage)
 void PlayThreatening()
 void PlayTurning()
 void PlayVictoryDance()
 void PlayWaiting()
 void PlayWaitingAmbush()
 void PlayWalking()
 void PreSetMovement()
 void SetMovementPhysics()
 void TweenToFalling()
 void TweenToFighter(float tweentime)
 void TweenToPatrolStop(float tweentime)
 void TweenToRunning(float tweentime)
 void TweenToWaiting(float tweentime)
 void TweenToWalking(float tweentime)
 void WhatToDoNext(name LikelyState, name LikelyLabel)
     
//-----------------------------------------------------------------------------
// RazorFish functions.
 void ZoneChange(ZoneInfo newZone)


State TacticalMove Function Summary
 void Bump(Actor Other)
 void PickDestination(bool bNoCharge)


State Flopping Function Summary
 void AnimEnd()
 void Landed(vector HitNormal)
 void ZoneChange(ZoneInfo NewZone)
 void Timer()


State MeleeAttack Function Summary
 void KeepAttacking()
 void Bump(Actor Other)


State Ambushing Function Summary
 void Landed(vector HitNormal)


State FallingState Function Summary
 void Landed(vector HitNormal)


State TakeHit Function Summary
 void Landed(vector HitNormal)


State Waiting Function Summary
 void Landed(vector HitNormal)



Source Code


00001	//=============================================================================
00002	// DevilFish.
00003	//=============================================================================
00004	class DevilFish extends ScriptedPawn;
00005	
00006	#exec MESH IMPORT MESH=fish ANIVFILE=MODELS\fish_a.3D DATAFILE=MODELS\fish_d.3D X=0 Y=0 Z=0
00007	#exec MESH ORIGIN MESH=fish X=0 Y=30 Z=0 YAW=64 PITCH=0 ROLL=-64 
00008	
00009	#exec MESH SEQUENCE MESH=fish SEQ=All          STARTFRAME=0   NUMFRAMES=102
00010	#exec MESH SEQUENCE MESH=fish SEQ=bite1        STARTFRAME=0   NUMFRAMES=10	RATE=45	Group=Attack
00011	#exec MESH SEQUENCE MESH=fish SEQ=bite2        STARTFRAME=10  NUMFRAMES=10	RATE=45	Group=Attack
00012	#exec MESH SEQUENCE MESH=fish SEQ=bite3        STARTFRAME=20  NUMFRAMES=10	RATE=45	Group=Attack
00013	#exec MESH SEQUENCE MESH=fish SEQ=breathing    STARTFRAME=30  NUMFRAMES=6	RATE=6
00014	#exec MESH SEQUENCE MESH=fish SEQ=dead1        STARTFRAME=36  NUMFRAMES=18	RATE=15
00015	#exec MESH SEQUENCE MESH=fish SEQ=flopping     STARTFRAME=54  NUMFRAMES=20
00016	#exec MESH SEQUENCE MESH=fish SEQ=grab1        STARTFRAME=74  NUMFRAMES=5			Group=Attack
00017	#exec MESH SEQUENCE MESH=fish SEQ=ripper       STARTFRAME=79  NUMFRAMES=13  RATE=25	Group=Attack
00018	#exec MESH SEQUENCE MESH=fish SEQ=Swimming     STARTFRAME=92  NUMFRAMES=10	RATE=20
00019	#exec MESH SEQUENCE MESH=fish SEQ=fighter	   STARTFRAME=0   NUMFRAMES=10
00020	#exec MESH SEQUENCE MESH=fish SEQ=takehit      STARTFRAME=36  NUMFRAMES=1
00021	
00022	#exec TEXTURE IMPORT NAME=Jfish1 FILE=MODELS\shark.PCX GROUP=Skins 
00023	#exec MESHMAP SCALE MESHMAP=fish X=0.085 Y=0.085 Z=0.17
00024	#exec MESHMAP SETTEXTURE MESHMAP=fish NUM=1 TEXTURE=Jfish1
00025	
00026	#exec AUDIO IMPORT FILE="Sounds\Devilfish\ambfs.WAV" NAME="ambfs" GROUP="Razorfish"
00027	#exec AUDIO IMPORT FILE="Sounds\Devilfish\chomp1fs.WAV" NAME="chomp1fs" GROUP="Razorfish"
00028	#exec AUDIO IMPORT FILE="Sounds\Devilfish\death1fs.WAV" NAME="death1fs" GROUP="Razorfish"
00029	#exec AUDIO IMPORT FILE="Sounds\Devilfish\flop1fs.WAV" NAME="flop1fs" GROUP="Razorfish"
00030	#exec AUDIO IMPORT FILE="Sounds\Devilfish\tear1fs.WAV" NAME="tear1fs" GROUP="Razorfish"
00031	#exec AUDIO IMPORT FILE="Sounds\Devilfish\miss1fs.WAV" NAME="miss1fs" GROUP="Razorfish"
00032	#exec AUDIO IMPORT FILE="Sounds\Devilfish\breath1fs.WAV" NAME="breath1fs" GROUP="Razorfish"
00033	
00034	//-----------------------------------------------------------------------------
00035	// RazorFish variables.
00036	
00037	// Attack damage.
00038	var() byte
00039		BiteDamage,		// Basic damage done by bite.
00040		RipDamage;
00041	var bool bAttackBump;
00042	var(Sounds) sound bite;
00043	var(Sounds) sound rip;
00044	var float	AirTime;
00045	
00046	//-----------------------------------------------------------------------------
00047	// RazorFish functions.
00048	
00049	function WhatToDoNext(name LikelyState, name LikelyLabel)
00050	{
00051		bStasis = true;
00052		Super.WhatToDoNext(LikelyState, LikelyLabel);
00053	}
00054	
00055	function ZoneChange(ZoneInfo newZone)
00056	{
00057		local vector start, checkpoint, HitNormal, HitLocation;
00058		local actor HitActor;
00059		
00060		if ( newZone.bWaterZone )
00061		{
00062			AirTime = 0;
00063			setPhysics(PHYS_Swimming);
00064		}
00065		else
00066		{
00067			SetPhysics(PHYS_Falling);
00068			MoveTimer = -1.0;
00069		}
00070	}
00071	
00072	function Landed(vector HitNormal)
00073	{
00074		GotoState('Flopping');
00075		Landed(HitNormal);
00076	}
00077	
00078	function PreSetMovement()
00079	{
00080		bCanJump = true;
00081		bCanWalk = false;
00082		bCanSwim = true;
00083		bCanFly = false;
00084		MinHitWall = -0.6;
00085		bCanOpenDoors = false;
00086		bCanDoSpecial = false;
00087	}
00088	
00089	function SetMovementPhysics()
00090	{
00091		if (Region.Zone.bWaterZone)
00092			SetPhysics(PHYS_Swimming);
00093		else
00094		{
00095			SetPhysics(PHYS_Falling);
00096			MoveTimer = -1.0;
00097			GotoState('Flopping');
00098		} 
00099	}
00100	
00101	function eAttitude AttitudeToCreature(Pawn Other)
00102	{
00103		if ( Other.IsA('Devilfish') )
00104			return ATTITUDE_Friendly;
00105		else if ( Other.IsA('ScriptedPawn') )
00106			return ATTITUDE_Hate;
00107		else
00108			return ATTITUDE_Ignore;
00109	}
00110	
00111	function PlayWaiting()
00112	{
00113		LoopAnim('Swimming', 0.1 + 0.3 * FRand());
00114	}
00115	
00116	function PlayPatrolStop()
00117	{
00118		LoopAnim('Swimming', 0.1 + 0.3 * FRand());
00119	}
00120	
00121	function PlayWaitingAmbush()
00122	{
00123		LoopAnim('Swimming', 0.1 + 0.3 * FRand());
00124	}
00125	
00126	function TweenToFighter(float tweentime)
00127	{
00128		TweenAnim('Fighter', tweentime);
00129	}
00130	
00131	function TweenToRunning(float tweentime)
00132	{
00133		if ( (AnimSequence != 'Swimming') || !bAnimLoop )
00134			TweenAnim('Swimming', tweentime);
00135	}
00136	
00137	function TweenToWalking(float tweentime)
00138	{
00139		if ( (AnimSequence != 'Swimming') || !bAnimLoop )
00140			TweenAnim('Swimming', tweentime);
00141	}
00142	
00143	function TweenToWaiting(float tweentime)
00144	{
00145		PlayAnim('Swimming', 0.2 + 0.8 * FRand());
00146	}
00147	
00148	function TweenToPatrolStop(float tweentime)
00149	{
00150		TweenAnim('Swimming', tweentime);
00151	}
00152	
00153	function PlayRunning()
00154	{
00155		LoopAnim('Swimming', -0.8/WaterSpeed,, 0.4);
00156	}
00157	
00158	function PlayWalking()
00159	{
00160		LoopAnim('Swimming', -0.8/WaterSpeed,, 0.4);
00161	}
00162	
00163	function PlayThreatening()
00164	{
00165		if ( FRand() < 0.5 )
00166			PlayAnim('Swimming', 0.4);
00167		else
00168			PlayAnim('Fighter', 0.4);
00169	}
00170	
00171	function PlayTurning()
00172	{
00173		LoopAnim('Swimming', 0.8);
00174	}
00175	
00176	function PlayDying(name DamageType, vector HitLocation)
00177	{
00178		if ( Region.Zone.bWaterZone )
00179		{
00180			PlaySound(Die, SLOT_Talk, 4 * TransientSoundVolume);
00181			PlayAnim('Dead1', 0.7, 0.1);
00182		}
00183		else
00184			TweenAnim('Breathing', 0.35);
00185	}
00186	
00187	function PlayTakeHit(float tweentime, vector HitLoc, int damage)
00188	{
00189		TweenAnim('TakeHit', tweentime);
00190	}
00191	
00192	function TweenToFalling()
00193	{
00194		TweenAnim('Flopping', 0.2);
00195	}
00196	
00197	function PlayInAir()
00198	{
00199		LoopAnim('Flopping', 0.7);
00200	}
00201	
00202	function PlayLanded(float impactVel)
00203	{
00204		TweenAnim('breathing', 0.2);
00205	}
00206	
00207	
00208	function PlayVictoryDance()
00209	{
00210		PlayAnim('ripper', 0.6, 0.1);
00211	}
00212		
00213	function PlayMeleeAttack()
00214	{
00215		local vector adjust;
00216		local float decision;
00217		adjust = vect(0,0,0.5) * FRand() * Target.CollisionHeight;
00218		Acceleration = AccelRate * Normal(Target.Location - Location + adjust);
00219		bAttackBump = false;
00220		if (AnimSequence == 'Grab1')
00221		{
00222			PlayAnim('ripper', 0.5 + 0.5 * FRand());
00223			PlaySound(rip,SLOT_Interact,,,500);
00224			MeleeDamageTarget(RipDamage, vect(0,0,0));
00225			Disable('Bump');
00226			return;
00227		}
00228		decision = FRand();
00229		PlaySound(bite,SLOT_Interact,,,500);
00230		if (decision < 0.3)
00231		{
00232			Disable('Bump');
00233			PlayAnim('Grab1', 0.3);
00234			return;
00235		}
00236		
00237		Enable('Bump');
00238		//log("Start Melee Attack");
00239		if (decision < 0.55)
00240		{
00241			PlayAnim('Bite1', 0.3);
00242		}
00243		else if (decision < 0.8)
00244		{
00245	 		PlayAnim('Bite2', 0.3); 
00246	 	}
00247	 	else 
00248	 	{
00249	 		PlayAnim('Bite3', 0.3);
00250	 	}
00251	}
00252	
00253	state Waiting
00254	{
00255		function Landed(vector HitNormal)
00256		{
00257			GotoState('Flopping');
00258			Landed(HitNormal);
00259		}
00260	}
00261	
00262	state TakeHit 
00263	{
00264	ignores seeplayer, hearnoise, bump, hitwall;
00265	
00266		function Landed(vector HitNormal)
00267		{
00268			GotoState('Flopping');
00269			Landed(HitNormal);
00270		}
00271	}
00272	
00273	state FallingState 
00274	{
00275	ignores Bump, Hitwall, HearNoise, WarnTarget;
00276	
00277		function Landed(vector HitNormal)
00278		{
00279			GotoState('Flopping');
00280			Landed(HitNormal);
00281		}
00282	}
00283	
00284	state Ambushing
00285	{
00286		function Landed(vector HitNormal)
00287		{
00288			GotoState('Flopping');
00289			Landed(HitNormal);
00290		}
00291	}
00292	
00293	state MeleeAttack
00294	{
00295	ignores SeePlayer, HearNoise;
00296	
00297		singular function Bump(actor Other)
00298		{
00299			Disable('Bump');
00300			if ( (AnimSequence == 'Bite1') || (AnimSequence == 'Bite2') || (AnimSequence == 'Bite3') )
00301				MeleeDamageTarget(BiteDamage, (BiteDamage * 1000.0 * Normal(Target.Location - Location)));
00302			else 
00303				return;
00304			bAttackBump = true;
00305			Velocity *= -0.5;
00306			Acceleration *= -1;
00307			if (Acceleration.Z < 0)
00308				Acceleration.Z *= -1;
00309		}
00310	
00311		function KeepAttacking()
00312		{
00313			if ( (Target == None) ||
00314				((Pawn(Target) != None) && (Pawn(Target).Health == 0)) )
00315				GotoState('Attacking');
00316			else if ( bAttackBump && (FRand() < 0.5) )
00317			{
00318				SetTimer(TimeBetweenAttacks, false);
00319				GotoState('TacticalMove', 'NoCharge');
00320			}
00321		}
00322	}		
00323	
00324	
00325	State Flopping
00326	{
00327	ignores seeplayer, hearnoise, enemynotvisible, hitwall; 	
00328	
00329		function Timer()
00330		{
00331			AirTime += 1;
00332			if ( AirTime > 25 + 15 * FRand() )
00333			{
00334				Health = -1;
00335				Died(None, 'suffocated', Location);
00336				return;
00337			}	
00338			SetPhysics(PHYS_Falling);
00339			Velocity = 200 * VRand();
00340			Velocity.Z = 170 + 200 * FRand();
00341			DesiredRotation.Pitch = Rand(8192) - 4096;
00342			DesiredRotation.Yaw = Rand(65535);
00343			TweenAnim('Flopping', 0.1);
00344		}
00345		
00346		function ZoneChange( ZoneInfo NewZone )
00347		{
00348			local rotator newRotation;
00349			if (NewZone.bWaterZone)
00350			{
00351				newRotation = Rotation;
00352				newRotation.Roll = 0;
00353				SetRotation(newRotation);
00354				SetPhysics(PHYS_Swimming);
00355				AirTime = 0;
00356				GotoState('Attacking');
00357			}
00358			else
00359				SetPhysics(PHYS_Falling);
00360		}
00361		
00362		function Landed(vector HitNormal)
00363		{
00364			local rotator newRotation;
00365			SetPhysics(PHYS_None);
00366			SetTimer(0.3 + 0.3 * AirTime * FRand(), false);
00367			newRotation = Rotation;
00368			newRotation.Pitch = 0;
00369			newRotation.Roll = Rand(16384) - 8192;
00370			DesiredRotation.Pitch = 0;
00371			SetRotation(newRotation);
00372			PlaySound(land,SLOT_Interact,,,400);
00373			TweenAnim('Breathing', 0.3);
00374		}
00375		
00376		function AnimEnd()
00377		{
00378			if (Physics == PHYS_None)
00379			{
00380				if (AnimSequence == 'Breathing')
00381				{
00382					PlaySound(sound'breath1fs',SLOT_Interact,,,300);
00383					PlayAnim('Breathing');
00384				}
00385				else 
00386					TweenAnim('Breathing', 0.2);
00387			}
00388			else
00389				PlayAnim('Flopping', 0.7);
00390		}
00391	}
00392	
00393	
00394	state TacticalMove
00395	{
00396		function PickDestination(bool bNoCharge)
00397		{
00398			local vector pick, pickdir, enemydir,Y, minDest;
00399			local float Aggression, enemydist, minDist, strafeSize;
00400			local bool success;
00401		
00402			success = false;
00403			enemyDist = VSize(Location - Enemy.Location);
00404			Aggression = 2 * (CombatStyle + FRand()) - 1.0;
00405	
00406			if (enemyDist < CollisionRadius + Enemy.CollisionRadius + MeleeRange)
00407				Aggression -= 1;	
00408			else if (enemyDist > FMax(VSize(OldLocation - Enemy.OldLocation), 240))
00409				Aggression += 0.4 * FRand();
00410			
00411			enemydir = (Enemy.Location - Location)/enemyDist;
00412			if ( !enemy.Region.Zone.bWaterZone )
00413				enemydir.Z *= 0.5;
00414			minDist = FMin(160.0, 3*CollisionRadius);
00415				
00416			Y = (enemydir Cross vect(0,0,1));
00417			
00418			strafeSize = FMin(1.0, (2 * Abs(Aggression) * FRand() - 0.2));
00419			if (Aggression < 0)
00420				strafeSize *= -1;
00421			enemydir = enemydir * strafeSize;
00422			enemydir.Z = FMax(0,enemydir.Z);
00423			strafeSize = FMax(0.0, 1 - Abs(strafeSize));
00424			pickdir = strafeSize * Y;
00425			pick = Location + (pickdir + enemydir) * (minDist + 500 * FRand());
00426			minDest = Location + minDist * (pickdir + enemydir); 
00427			if (pointReachable(minDest))
00428			{
00429				success = true;
00430				Destination = pick;	
00431			}
00432							
00433			if (!success)
00434			{
00435				pick = Location + (enemydir - pickdir) * (minDist + 500 * FRand());
00436				pick.Z = Location.Z;
00437				minDest = Location + minDist * (enemydir - pickdir); 
00438				if (pointReachable(minDest))
00439				{
00440					success = true;
00441					Destination = pick;	
00442				}
00443			}
00444			
00445			if (!success)
00446			{
00447				pick = Location - enemydir * (minDist + 500 * FRand());
00448				pick.Z = Location.Z + 200 * FRand() - 100;
00449			}
00450		}
00451	
00452	
00453		function Bump(Actor Other)
00454		{
00455			Disable('Bump');
00456			if (bAttackBump == true)
00457				bAttackBump = false;
00458			else if (Other == Enemy)
00459			{
00460				bReadyToAttack = true;
00461				Target = Enemy;
00462				GotoState('MeleeAttack');
00463			}
00464			else if (Enemy.Health <= 0)
00465				GotoState('Attacking');
00466		}
00467	}
00468	
00469	defaultproperties
00470	{
00471	     BiteDamage=15
00472	     RipDamage=25
00473	     rip=Sound'UnrealShare.Razorfish.tear1fs'
00474	     CarcassType=Class'UnrealShare.DevilfishCarcass'
00475	     TimeBetweenAttacks=0.500000
00476	     Aggressiveness=1.000000
00477	     MeleeRange=40.000000
00478	     WaterSpeed=250.000000
00479	     Visibility=120
00480	     SightRadius=1250.000000
00481	     Health=70
00482	     UnderWaterTime=-1.000000
00483	     Intelligence=BRAINS_NONE
00484	     HitSound1=Sound'UnrealShare.Razorfish.chomp1fs'
00485	     HitSound2=Sound'UnrealShare.Razorfish.miss1fs'
00486	     Land=Sound'UnrealShare.Razorfish.flop1fs'
00487	     Die=Sound'UnrealShare.Razorfish.death1fs'
00488	     CombatStyle=1.000000
00489	     AmbientSound=Sound'UnrealShare.Razorfish.ambfs'
00490	     DrawType=DT_Mesh
00491	     Mesh=LodMesh'UnrealShare.fish'
00492	     CollisionRadius=35.000000
00493	     CollisionHeight=20.000000
00494	     Mass=60.000000
00495	     Buoyancy=60.000000
00496	     RotationRate=(Pitch=8192,Roll=8192)
00497	}

End Source Code