Game Development Community

dev|Pro Game Development Curriculum

Faking Aircraft and Real Airstrikes In T3D - Part Two of two

by Steve Acaster · 04/15/2011 (1:32 pm) · 17 comments

Part 2!

if you missed it - part ONE was here

So we're going to have clusterbombs spawn after the aircraft passes, and rain down from a right angle, 100 units along the aircraft's flight path, and "saturate" the target area, where our smoke has popped up to mark. For this tutorial, we'll be using the stock particleFX/exposion data of the rocket launcher.

//bombs
function dropBomblets(%start, %vector)
{
	%bombMask = 
  $TypeMasks::VehicleObjectType |      
  $TypeMasks::TerrainObjectType |     
  $TypeMasks::StaticTSObjectType |   
  $TypeMasks::StaticShapeObjectType |
  $TypeMasks::WaterObjectType |
   $TypeMasks::ForestObjectType;//forest replaces obsolete interior


	echo("dropBomblets");
	echo("start = " @ %start);
	%bombarray = new arrayobject();
	MissionCleanup.add(%bombarray);

	//bomblet accuracy
	%spread = 8/800;
	%spread = %spread $= "" ? 0.001 : %spread;
	%spread = %spread <= 0 ? 0.001 : %spread;

	//how many bomblets?
	%Bombloop = 10;
	%Bombcount = 0;	

	// Create each projectile and send it on its way 
	for(%bomb=0; %bomb<%bombloop; %bomb++)
	{
		%velocity = VectorScale(%vector, 500);//500 is the length of checking for an impact - alter to taste

		%x = (getRandom() - 0.5) * 4 * 3.1415926 * %spread * 2.00;
		%y = (getRandom() - 0.5) * 4 * 3.1415926 * %spread * 2.00;
		%z = (getRandom() - 0.5) * 4 * 3.1415926 * %spread * 2.00;
		%mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);

		%velocity = MatrixMulVector(%mat, %velocity);
		%aimpoint = VectorAdd(%start, %velocity);
	
		%targetSearch = containerRayCast(%start, %aimpoint, %bombMask);

		%hit = firstword(%targetSearch);

		if(%hit != 0)
		{
			%impactpoint = getWords(%targetSearch, 1, 3);
			
			echo("hit classname = " @ %hit.getClassname());
			if(%hit.getType() == $TypeMasks::waterObjectType)
			{
				echo("WET!");
				%impactPoint = %impactPoint @ " 1";
			}
		
			%dist = vectorDist(%start, %impactpoint);
		
			%bombarray.add(%impactPoint, %dist);
		
		//	debugdraw.togglefreeze();
		//	debugdraw.drawline(%start, %velocity, "0 0 1");

			%Bombcount++;
		}

	}
	
	%bombarray.sortd();
	%bombarray.moveFirst();
	%bombarray.echo();
	
	//bombletStrike(%bombarray, 10);
	
	//%array = %bombarray.getID();
	//echo("array ID = " @ %array);
	schedule(4000, 0, "BombletStrike", %bombarray, %bombcount);
}

function BombletStrike(%array, %bombs)
{
	echo("Bomblet strikes!");
	%total = %array.count();
	echo("array count = " @ %total);
	
	%i = %array.getcurrent();
	%origin = %array.getKey(%i);
	
	%wet = getWordCount(%origin);
	if(%wet == 4)
	{
		echo("wet wordcount = " @ %wet);
		echo("wet1 = " @ %origin);
	
		%origin = getWords(%origin, 0, 2);
		
		echo("wet2 = " @ %origin);
		
		%blast = new explosion()
		{
			dataBlock = RocketLauncherWaterExplosion;
			position = %origin;
		};
		MissionCleanup.add(%blast);
	
	}
	else
	{
		%blast = new explosion()
		{
			dataBlock = RocketLauncherExplosion;
			position = %origin;
		};
		MissionCleanup.add(%blast);
	}
	
	%bombs--;
	
//let's not use standard radiusDamage - let's make a custom!	
	//radiusDamage(%sourceObject, %position, %radius, %damage, %damageType, %impulse)
			airStrikeDamage(0, %origin, 15, 100, "radius", 100 * 10);
		
	if(%bombs < 1)
	{
		%array.empty();
		%array.delete();
	}
	else
	{
		%array.moveNext();
		schedule(200, 0, "bombletStrike", %array, %bombs);
	}
}
Note that bombs will explode on the surface of water, giving the waterExplosion.
When the airstrike hits, it will explode the clusterbombs one at a time, starting with the nearest strike to the point of launch.
Rather than use a standard "radiusDamage" - to show that bombs have much more penetrative power than normal projectiles and can thus punch through walls and obstacles, we're going to use a custom damage function that will ignore all cover.

Finally add:
function AirStrikeDamage(%sourceObject, %position, %radius, %damage, %damageType, %impulse)
{
   InitContainerRadiusSearch(%position, %radius, $TypeMasks::ShapeBaseObjectType);

   	%outerRadius = %radius /1.3;//yorks
     %halfRadius = %radius / 2;
   %quarterRadius = %radius /4;//yorks

   while ((%targetObject = containerSearchNext()) != 0)
   {
	  %range=vectorDist(%targetObject.getposition(), %position);
	  
	if(%range <= %quarterradius)
	{
		%mydamage = %damage * 2;//* 0
		%rangedam ="high - " @ %mydamage/2;
	}
	else
	{
		if(%range <= %halfradius && %range > %quarterradius)
		{
			%mydamage = %damage;// /2
			%rangedam ="medium - " @ %mydamage/2;
		}
		else
		{
			if(%range <= %outerradius && %range > %halfradius)
			{
				%mydamage = %damage /2;// /4
				%rangedam ="low - " @ %mydamage/2;
			}
			else
			{
					%mydamage = %damage /3;// /6
					%rangedam ="lowest - " @ %mydamage/2;
			}
		}
	}
      // Apply the damage
 //     %targetObject.damage(%sourceObject, %position, %damage * %coverage * %distScale, %damageType);
	%targetObject.damage(%sourceObject, %position, %mydamage, %damageType);//damage has to be x2 now ... why
		
		// Apply the impulse
		if (%impulse)
		{
			%impulseVec = VectorSub(%targetObject.getWorldBoxCenter(), %position);//note getPosition can cause a random headshot wtf?
			%impulseVec = VectorNormalize(%impulseVec);

			if(%targetObject.getClassName() $= "AIPlayer" || %targetObject.getClassName() $= "Player")
			{
				%impulseVec = VectorScale(%impulseVec, %impulse);
				%targetObject.applyImpulse(%position, %impulseVec);	
			}
			else
			{
					%impulseVec = VectorScale(%impulseVec, %impulse);
							%targetObject.applyImpulse(%position, %impulseVec);	
			}
		}
	}
}

And that should be that!

Now when you aim the player at a point and enter the command into the console:
airstrike();
A cloud of smoke should mark the target area, an aircraft should spawn 2k units out to the left of the player's view, race across infront of the player in 8 seconds, and 10 bomblets impact on the target zone.

And it should look something like this (only without my custom art assets obviously):


[edit] Loaded the correct video now - doh!
Apologies for the annoying "pings" as I swap camera/player control :P

Enjoy!

" I love the smell of Dual Purpose Improved Conventional Munitions in the morning!"



Thanks to TRON and Silent Mike for their help in finding the old math functions with the wayback machine, and the various people who contributed to those functions back in the day when trolling meant something ...

#1
04/15/2011 (2:03 pm)
Very nice, Steve - once again, something very fun! Thanks man!
#2
04/15/2011 (2:42 pm)
Clusterbombs for the win!
#3
04/15/2011 (7:49 pm)
did you have to get an 8 killstreak for that? =P
great resource!
#4
04/15/2011 (8:03 pm)
Doh! Guess which derptard embedded the wrong video - that was my first test with the bad rotations and out of order bomb impacts. Fixed!
#5
04/16/2011 (5:58 am)
nice resource!
#6
04/16/2011 (6:52 am)
Awesome effects Steve.
#7
04/16/2011 (7:17 am)
nice work Steve. You've saved me some time.. for my ole parachute cargo drops, I used a twist of lime... I meant AFX 8)

edit: for a minute there I thought that was a Klingon Warbird!
#8
04/16/2011 (11:50 am)
Nice Steve ... thanks again for a great tutorial. :)
#9
04/16/2011 (6:30 pm)
I should post my airstrike code sometime :)

@Jordan: mine does :D
#10
04/17/2011 (12:38 pm)
Thanks for a great tutorial. Nice work Steve.:)
#11
04/18/2011 (6:42 pm)
Steve thanks again for another awsome tutorial. You are making tutorials of topics that make sense and can be used for many different things. Awsome!
#12
04/21/2011 (6:38 pm)
That's some really cool effect there.
#13
11/18/2011 (1:28 pm)
Steve, Thanks for the great resource, its exactly what I was looking for!! Got a couple of questions I was hoping you or someone on the forums could help me with.

1) I got my laser designator working kind-of anyways. I point the weapon or laser at the area I want for destruction, I see the ammo counter drop one, but for the life of me I cant seem to call in the airstrike when I press the left mouse button. I thought I'd use it, the laser, to fire a laser projectile at the target and ativate the airstrike in the weapons onfire function, but I cant seem to call it. The airstrike works great in console, just need to understand how you did it with your weapon or if im even going in the right direction to call it in the onfire function???

2)If I can get some help with calling a console command in script, I'm hoping on making a second call for airstrike using a heicopter to come in and hover above the player and spray the area with bullets, thought it would be cool to see a bunch of hot shells falling around the player, like it did on me when I was in the Army.

Thanks again Steve for all your help and resources in the past and look forward to many more, you should write an updated book on Torque, lord knows we need one and I'd buy it.......Donnie
#14
11/26/2011 (7:56 am)
Ok I went a different route, I'm using the L key to activate the Airstrike. Trying to make it like my health kits where I pickup a sat phone, giving me access to use the L key for one call for fire mission. I have three different jet aircraft models I wanna use to randomly fly in when called upon also. Still haven't figured out how to call in the airstrike via the onfire function or if thats even where I should???? Thanks again steve for all your hard work!!
#15
02/25/2012 (10:35 pm)
Steve@ makes it look easy! Had a free SR71 model from turbosquid dropping bomblets in a short amount of time ... bombs are not leaving decals and cant hear the jet sound - but thats all minor.

Donnie@ It should work by just calling airStrike() from where ever you want. If you need an example of custom onFire functions ... see steves post on how to use ray casts for melee weapons ... it uses a unique onFire function.
#16
02/26/2012 (3:59 pm)
Hey Jeff, I already got it working great except for the bombs leaving decals......Gonna try soon....thanks

FIXED:: actually thanks to steve and his bombardment resource, I got the decals working with this;

under MissionCleanup.add(%blast); for the ground explosions, add this and save.....

//and finally, slap on the stock decal at the impact site
%decalObj = decalManagerAddDecal(%origin, "0.0 0.0 1.0",0,1, "ScorchRXDecal", false);

run and watch your bomblets explode with decals working!!! Again, Steve your the man brother!!! Thank You



#17
02/07/2014 (9:15 pm)
great resource....