RuneI
Class SpiderBot

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

class SpiderBot
extends RuneI.ScriptPawn

//============================================================================= // SpiderBot. //=============================================================================
Variables
 int BettyDamage
 float BettyRange
 int BombCount
 ParticleSystem BombFire
 float BounceZ
 vector Direction
 vector HomeLocation
 float HorizontalThrust

States
SteamerAttack, BomberAttack, ReturnToWaiting, Bouncing, BettyAttack, Fighting

Function Summary
 void Died(Pawn Killer, name damageType, vector HitLocation)
     
//============================================================
//
// Died
// 
// TODO:  Spawn out metal spiderbot gibs
//============================================================
 EMatterType MatterForJoint(int joint)
     
//============================================================
//
// MatterForJoint
//
// Returns what kind of material joint is associated with
//============================================================
 Texture PainSkin(int BodyPart)
     
//============================================================
//
// PainSkin
//
//============================================================
 void PlayHitMatterSound(EMatterType matter)
     
//============================================================
//
// PlayHitMatterSound
//
//============================================================
 void PlayMoving(optional float)
 void PlayTurning(optional float)
 void PlayWaiting(optional float)
     
//------------------------------------------------
//
// Animation Functions
//
//------------------------------------------------
 void SpawnHitEffect(vector HitLoc, vector HitNorm, Actor HitActor)
     
//=============================================================================
//
// SpawnHitEffect
//
// Spawns an effect based upon what was struck
//=============================================================================
 void TweenToMoving(float time)
 void TweenToWaiting(float time)
     
// Tween functions


State SteamerAttack Function Summary
 void BeginState()
 void AmbientSoundTimer()


State BomberAttack Function Summary
 void ExplodeBot()
 void CatchFire()
 void LaunchBomb()
     
//--------------------------------------------------------
 void BeginState()
     
//--------------------------------------------------------
 void AmbientSoundTimer()


State ReturnToWaiting Function Summary


State Bouncing Function Summary
 void PickDirection()
     
//--------------------------------------------------------
 void HitWall(vector HitNormal, Actor HitWall)
     
//--------------------------------------------------------
 void Landed(vector HitNormal, Actor HitActor)
     
//--------------------------------------------------------
 void ThrustUp()
     
//--------------------------------------------------------
 void EndState()
     
//--------------------------------------------------------
 void BeginState()
     
//--------------------------------------------------------
 void AmbientSoundTimer()


State BettyAttack Function Summary
 void BeginState()
 void AmbientSoundTimer()


State Fighting Function Summary
 void ChooseBotType()
 void AmbientSoundTimer()



Source Code


00001	//=============================================================================
00002	// SpiderBot.
00003	//=============================================================================
00004	class SpiderBot expands ScriptPawn;
00005	
00006	/*
00007	// TODO:
00008	
00009	- Finish SteamerBot!
00010	- If the player is too far, retract the blades and follow
00011	
00012	
00013	// ANIMATION FUNCTIONS
00014	
00015	XSI LOAD betty_antic
00016	XSI LOAD betty_antic_spin
00017	XSI LOAD betty_attack
00018	XSI LOAD betty_attack_ready
00019	XSI LOAD bomber_antic
00020	XSI LOAD bomber_attack
00021	XSI LOAD idleA
00022	XSI LOAD steamer_antic
00023	XSI LOAD steamer_attack
00024	XSI LOAD steamer_return
00025	XSI LOAD walkA
00026	*/
00027	
00028	// Betty Vars
00029	var() float BounceZ;
00030	var() float HorizontalThrust;
00031	var() float BettyRange;
00032	var() int BettyDamage;
00033	var vector Direction;
00034	var vector HomeLocation;
00035	var(Sounds) Sound	SpinSoundLOOP;
00036	var(Sounds) Sound	BounceSound;
00037	
00038	// Bomber Vars
00039	var int BombCount;
00040	var ParticleSystem BombFire;
00041	var(Sounds) Sound	LaunchFireSound;
00042	
00043	var(Sounds) Sound	LaunchSpin;
00044	var(Sounds) Sound	BurnOut;
00045	
00046	// Generic sounds
00047	var(Sounds) Sound	HitFlesh;
00048	var(Sounds) Sound	HitWood;
00049	var(Sounds) Sound	HitStone;
00050	var(Sounds) Sound	HitMetal;
00051	var(Sounds) Sound	HitDirt;
00052	var(Sounds) Sound	HitShield;
00053	var(Sounds) Sound	HitWeapon;
00054	var(Sounds) Sound	HitBreakableWood;
00055	var(Sounds) Sound	HitBreakableStone;
00056	
00057	var(Sounds) float	PitchDeviation;		// Vary pitch of sounds by +/- this percentage
00058	
00059	//============================================================
00060	//
00061	// MatterForJoint
00062	//
00063	// Returns what kind of material joint is associated with
00064	//============================================================
00065	function EMatterType MatterForJoint(int joint)
00066	{
00067		return MATTER_WEAPON;
00068	}
00069	
00070	//============================================================
00071	//
00072	// PainSkin
00073	//
00074	//============================================================
00075	function Texture PainSkin(int BodyPart)
00076	{
00077		return None;
00078	}
00079	
00080	//============================================================
00081	//
00082	// Died
00083	// 
00084	// TODO:  Spawn out metal spiderbot gibs
00085	//============================================================
00086	
00087	function Died(pawn Killer, name damageType, vector HitLocation)
00088	{
00089		PlaySound(Die, SLOT_Talk,,,, 1.0 + FRand()*0.2-0.1);
00090		Spawn(class'SpiderBotExplosion',,, Location);
00091		Destroy();
00092	}
00093	
00094	//------------------------------------------------
00095	//
00096	// Animation Functions
00097	//
00098	//------------------------------------------------
00099	function PlayWaiting(optional float tween)
00100	{
00101		LoopAnim('idleA', 1.0, tween);
00102	}
00103	function PlayMoving(optional float tween)
00104	{
00105		LoopAnim('walkA', 1.0, tween);	
00106	}
00107	function PlayTurning(optional float tween)
00108	{
00109		PlayAnim('walkA', 1.0, tween);
00110	}
00111	
00112	// Tween functions
00113	function TweenToWaiting(float time)
00114	{
00115		TweenAnim ('idleA', time);
00116	}
00117	function TweenToMoving(float time)
00118	{
00119		TweenAnim ('walkA', time);
00120	}
00121	
00122	//=============================================================================
00123	//
00124	// SpawnHitEffect
00125	//
00126	// Spawns an effect based upon what was struck
00127	//=============================================================================
00128	
00129	function SpawnHitEffect(vector HitLoc, vector HitNorm, Actor HitActor)
00130	{	
00131		local int i,j;
00132		local EMatterType matter;
00133		local vector traceEnd, traceStart;
00134		local float traceDist;
00135		local rotator rot;
00136	
00137		if(HitActor == None)
00138			return;
00139	
00140		// Determine what kind of matter was hit
00141		if(HitActor.IsA('LevelInfo'))
00142		{
00143			matter = HitActor.MatterTrace(HitLoc, Location, 20);
00144		}
00145		else
00146		{
00147			matter = HitActor.MatterForJoint(0);
00148		}
00149	
00150		PlayHitMatterSound(matter);
00151	
00152		// Create effects
00153		switch(matter)
00154		{
00155			case MATTER_FLESH:
00156				if(HitActor.IsA('Sark') || HitActor.IsA('SarkRagnar'))
00157					Spawn(class'SarkBloodMist',,, HitLoc, rotator(HitNorm)); // Sark blood
00158				else
00159					Spawn(class'BloodMist',,, HitLoc, rotator(HitNorm));
00160	
00161				break;
00162			case MATTER_WOOD:
00163				break;
00164			case MATTER_STONE:
00165				Spawn(class'HitStone',,, HitLoc, rotator(HitNorm));
00166				break;
00167			case MATTER_METAL:
00168				break;
00169			case MATTER_EARTH:
00170				Spawn(class'GroundDust',,, HitLoc, rotator(HitNorm));
00171				break;
00172			case MATTER_BREAKABLEWOOD:
00173				break;
00174			case MATTER_BREAKABLESTONE:
00175				break;
00176			case MATTER_WEAPON:
00177				break;
00178			case MATTER_SHIELD:
00179				break;
00180			case MATTER_ICE:
00181				break;
00182			case MATTER_WATER:
00183				break;
00184			case MATTER_SNOW:
00185				break;
00186		}
00187	}
00188	
00189	//============================================================
00190	//
00191	// PlayHitMatterSound
00192	//
00193	//============================================================
00194	
00195	function PlayHitMatterSound(EMatterType matter)
00196	{
00197		switch(matter)
00198		{
00199			case MATTER_FLESH:
00200				PlaySound(HitFlesh, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00201				break;
00202			case MATTER_WOOD:
00203				PlaySound(HitWood, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00204				break;
00205			case MATTER_STONE:
00206				PlaySound(HitStone, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00207				break;
00208			case MATTER_METAL:
00209				PlaySound(HitMetal, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00210				break;
00211			case MATTER_EARTH:
00212				PlaySound(HitDirt, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00213				break;
00214			case MATTER_BREAKABLEWOOD:
00215				PlaySound(HitBreakableWood, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00216				break;
00217			case MATTER_BREAKABLESTONE:
00218				PlaySound(HitBreakableStone, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00219				break;
00220			case MATTER_WEAPON:
00221				PlaySound(HitWeapon, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00222				break;
00223			case MATTER_SHIELD:
00224				PlaySound(HitShield, SLOT_Misc,,,, 1.0 + (FRand()-0.5)*2.0*PitchDeviation);
00225				break;
00226			case MATTER_ICE:
00227			case MATTER_WATER:
00228				break;
00229		}
00230	
00231		MakeNoise(1.0);
00232	}
00233	
00234	//============================================================
00235	//
00236	// Fighting
00237	//
00238	//============================================================
00239	
00240	state Fighting
00241	{
00242		function AmbientSoundTimer()
00243		{
00244			PlayAmbientFightSound();
00245		}
00246	
00247		function ChooseBotType()
00248		{
00249			local float f;
00250			
00251			f = FRand();
00252	
00253			if(f < 0.5)
00254			{ // Betty Bot
00255				NextState = 'BettyAttack';
00256				SkelMesh = 0;
00257			}
00258			else
00259			{ // Bomber Bot
00260				NextState = 'BomberAttack';
00261				SkelMesh = 1;
00262			}
00263	/* NOTE:  For now, Steamer bot does nothing until we further design it		
00264			else
00265			{ // Steamer Bot
00266				NextState = 'SteamerAttack';
00267				SkelMesh = 2;
00268			}
00269	*/		
00270		}
00271		
00272	begin:
00273		ChooseBotType();
00274		GotoState(NextState);
00275	}
00276	
00277	// ===== BETTY BOT =====
00278	
00279	//============================================================
00280	//
00281	// BettyAttack
00282	//
00283	//============================================================
00284	
00285	state BettyAttack
00286	{	
00287		function AmbientSoundTimer()
00288		{
00289			PlayAmbientFightSound();
00290		}
00291	
00292		function BeginState()
00293		{
00294			Acceleration = vect(0, 0, 0);
00295			Velocity = vect(0, 0, 0);
00296		}
00297		
00298	begin:
00299		PlayAnim('betty_antic', 1.0, 0.1);
00300		FinishAnim();
00301		
00302		PlayAnim('betty_attack', 1.0, 0.2);
00303		FinishAnim();
00304		GotoState('Bouncing');
00305	}
00306	
00307	//============================================================
00308	//
00309	// Bouncing
00310	//
00311	//============================================================
00312	
00313	state Bouncing
00314	{	
00315		function AmbientSoundTimer()
00316		{
00317			PlayAmbientFightSound();
00318		}
00319	
00320		//--------------------------------------------------------
00321		//
00322		// BeginState
00323		//
00324		//--------------------------------------------------------
00325	
00326		function BeginState()
00327		{	
00328			AmbientSound = SpinSoundLOOP;
00329			HomeLocation = Location;	
00330			bBounce = true;
00331			ThrustUp();
00332		}		
00333	
00334		//--------------------------------------------------------
00335		//
00336		// EndState
00337		//
00338		//--------------------------------------------------------
00339	
00340		function EndState()
00341		{	// Stop looping sound
00342			AmbientSound = None;
00343		}
00344	
00345		//--------------------------------------------------------
00346		//
00347		// ThrustUp
00348		//
00349		//--------------------------------------------------------
00350			
00351		function ThrustUp()
00352		{
00353			local float speed;
00354			local vector dist;
00355			
00356			SetPhysics(PHYS_Falling);
00357			Velocity.Z = BounceZ + FRand() * (BounceZ * 0.25);
00358	
00359			// Bounce the BettyBot towards its target, or if
00360			// the bot doesn't have a target, return it to waiting
00361			speed = FRand() * HorizontalThrust;
00362	
00363			if(Enemy == None)
00364			{
00365				GotoState('ReturnToWaiting');
00366			}
00367			else
00368			{
00369				dist = Enemy.Location - Location;
00370				
00371				// If the enemy is too far away, return the bot to 
00372				// Charging
00373				if(VSize(dist) > BettyRange)
00374				{
00375					GotoState('ReturnToWaiting');
00376				}
00377				
00378				dist.Z = 0;
00379				dist = Normal(dist);
00380				
00381				Velocity.X = dist.X * speed;
00382				Velocity.Y = dist.Y * speed;
00383			}
00384		}
00385	
00386		//--------------------------------------------------------
00387		//
00388		// Landed
00389		//
00390		//--------------------------------------------------------
00391	
00392		function Landed(vector HitNormal, actor HitActor)
00393		{
00394			HitWall(HitNormal, HitActor);
00395		}
00396	
00397		//--------------------------------------------------------
00398		//
00399		// HitWall
00400		//
00401		//--------------------------------------------------------
00402		
00403		function HitWall(vector HitNormal, actor HitWall)
00404		{	
00405			PlaySound(BounceSound, SLOT_Talk,,,, 1.0 + FRand()*0.2-0.1);
00406	
00407			if(HitNormal.Z > 0.5)
00408			{
00409				ThrustUp();
00410			}
00411			else
00412			{
00413				Velocity = HitNormal * 100;
00414				SetPhysics(PHYS_Falling);
00415			}
00416	
00417			if(HitWall != None && !HitWall.IsA('SpiderBot'))
00418			{
00419				HitWall.JointDamaged(BettyDamage, self, Location, Velocity * 0.5, 'bluntsever', 0);
00420				SpawnHitEffect(Location, HitNormal, HitWall);			
00421			}
00422		}
00423	
00424		//--------------------------------------------------------
00425		//
00426		// PickDirection
00427		//
00428		//--------------------------------------------------------
00429	
00430		function PickDirection()
00431		{
00432			local vector X, Y, Z;
00433			
00434			GetAxes(Rotation, X, Y, Z);
00435			
00436			Direction = Location - (X * 10) - (Y * 10);
00437		}
00438		
00439	begin:
00440	
00441	spin:
00442		PickDirection();
00443		TurnTo(Direction);
00444		Goto('begin');
00445	}
00446	
00447	//============================================================
00448	//
00449	// ReturnToWaiting
00450	//
00451	//============================================================
00452	
00453	state ReturnToWaiting
00454	{
00455	begin:
00456		PlayWaiting(0.1);
00457		SetPhysics(PHYS_Falling);
00458		GotoState('Waiting');
00459	}
00460	
00461	// ===== BOMBER BOT =====
00462	
00463	//============================================================
00464	//
00465	// BomberAttack
00466	//
00467	//============================================================
00468	
00469	state BomberAttack
00470	{		
00471		function AmbientSoundTimer()
00472		{
00473			PlayAmbientFightSound();
00474		}
00475	
00476		//--------------------------------------------------------
00477		//
00478		// BeginState
00479		//
00480		//--------------------------------------------------------
00481	
00482		function BeginState()
00483		{
00484			Acceleration = vect(0, 0, 0);
00485			Velocity = vect(0, 0, 0);
00486		}
00487	
00488		//--------------------------------------------------------
00489		//
00490		// LaunchBomb
00491		//
00492		//--------------------------------------------------------
00493		
00494		function LaunchBomb()
00495		{
00496			local int traj;
00497			local vector adjust;
00498			local actor bomb;
00499			
00500			bomb = Spawn(class'SpiderBomb', self,, Location, Rotation);
00501			bomb.SetPhysics(PHYS_Falling);
00502			bomb.bCollideWorld = true;
00503			
00504			if(Enemy != None)
00505			{ // Throw bombs directly at enemy
00506				traj = (45 + Rand(25)) * 65536 / 360;
00507				adjust = VRand() * 10; // Random adjustment to compensate for perfect accuracy
00508				bomb.Velocity = CalcArcVelocity(traj, Location, Enemy.Location + adjust);
00509			}
00510			else
00511			{ // No enemy, so randomly emit bombs		
00512				bomb.Velocity.Z = 250 + FRand() * 250;
00513				bomb.Velocity.X = (FRand() - 0.5) * 250;
00514				bomb.Velocity.Y = (FRand() - 0.5) * 250;
00515			}
00516		}
00517	
00518		function CatchFire()
00519		{
00520			BombFire = Spawn(class'fire',,, Location,);		
00521			AttachActorToJoint(BombFire, JointNamed('offset'));
00522		}	
00523		
00524		function ExplodeBot()
00525		{
00526			// Set up the fire to remove itself
00527			BombFire.bSystemOneShot = true;
00528			BombFire.bOneShot = true;
00529			
00530			Died(None, '', Location);
00531		}
00532		
00533	begin:
00534		PlaySound(LaunchSpin, SLOT_Interface,,,, 1.0 + FRand()*0.2-0.1);
00535	
00536		PlayAnim('bomber_antic', 1.0, 0.1);
00537		FinishAnim();
00538		PlayAnim('bomber_attack', 1.0, 0.1);
00539		FinishAnim();
00540		
00541		BombCount = 6 + Rand(6);
00542	
00543		while(BombCount-- > 0)
00544		{
00545			if ((BombCount & 1)==0)
00546				PlaySound(LaunchFireSound, SLOT_Talk,,,, 1.0 + FRand()*0.2-0.1);
00547			else
00548				PlaySound(LaunchFireSound, SLOT_Misc,,,, 1.0 + FRand()*0.2-0.1);
00549	
00550			LaunchBomb();
00551			Sleep(0.2);
00552		}
00553		
00554		Sleep(0.3);
00555		CatchFire();
00556		PlaySound(BurnOut, SLOT_Interface,,,, 1.0 + FRand()*0.2-0.1);
00557		Sleep(4.0);
00558		ExplodeBot();
00559	}
00560	
00561	
00562	// ===== STEAMER BOT =====
00563	
00564	//============================================================
00565	//
00566	// SteamerAttack
00567	//
00568	//============================================================
00569	
00570	state SteamerAttack
00571	{	
00572		function AmbientSoundTimer()
00573		{
00574			PlayAmbientFightSound();
00575		}
00576	
00577		function BeginState()
00578		{
00579			Acceleration = vect(0, 0, 0);
00580			Velocity = vect(0, 0, 0);
00581		}
00582		
00583	begin:	
00584		PlayAnim('steamer_antic', 1.0, 0.1);
00585		FinishAnim();
00586		PlayAnim('steamer_attack', 1.0, 0.1);
00587		FinishAnim();
00588		Sleep(3.0);
00589		PlayAnim('steamer_return', 1.0, 0.1);
00590		FinishAnim();
00591		GotoState('Waiting');
00592	}
00593	
00594	defaultproperties
00595	{
00596	     BounceZ=260.000000
00597	     HorizontalThrust=140.000000
00598	     BettyRange=800.000000
00599	     BettyDamage=8
00600	     SpinSoundLOOP=Sound'CreaturesSnd.SpiderBot.spiderspin01L'
00601	     BounceSound=Sound'CreaturesSnd.SpiderBot.spiderbounce01'
00602	     LaunchFireSound=Sound'CreaturesSnd.SpiderBot.spiderlaunch01'
00603	     LaunchSpin=Sound'CreaturesSnd.SpiderBot.spidergear02'
00604	     BurnOut=Sound'CreaturesSnd.SpiderBot.spiderburn01'
00605	     HitFlesh=Sound'WeaponsSnd.ImpFlesh.impfleshsword07'
00606	     HitWood=Sound'WeaponsSnd.ImpWood.impactwood15'
00607	     HitStone=Sound'WeaponsSnd.ImpStone.impactstone07'
00608	     HitMetal=Sound'WeaponsSnd.ImpMetal.impactmetal17'
00609	     HitDirt=Sound'WeaponsSnd.ImpEarth.impactearth03'
00610	     HitShield=Sound'WeaponsSnd.Shields.shield03'
00611	     HitWeapon=Sound'WeaponsSnd.Swords.sword03'
00612	     HitBreakableWood=Sound'WeaponsSnd.ImpWood.impactwood12'
00613	     HitBreakableStone=Sound'WeaponsSnd.ImpStone.impactstone11'
00614	     PitchDeviation=0.090000
00615	     FightOrFlight=1.000000
00616	     FightOrDefend=1.000000
00617	     ShadowScale=0.750000
00618	     bCanStrafe=True
00619	     bAlignToFloor=True
00620	     MeleeRange=160.000000
00621	     GroundSpeed=160.000000
00622	     JumpZ=290.000000
00623	     MaxStepHeight=10.000000
00624	     ClassID=13
00625	     SightRadius=1500.000000
00626	     PeripheralVision=-1.000000
00627	     Health=50
00628	     Intelligence=BRAINS_REPTILE
00629	     Die=Sound'OtherSnd.Explosions.explosion12'
00630	     SoundRadius=50
00631	     TransientSoundRadius=1200.000000
00632	     CollisionRadius=18.000000
00633	     CollisionHeight=8.000000
00634	     Mass=30.000000
00635	     RotationRate=(Pitch=0,Yaw=150000,Roll=0)
00636	     Skeletal=SkelModel'creatures.SpiderBot'
00637	}

End Source Code