Game Development Community

dev|Pro Game Development Curriculum

CoD Style MineField Triggers

by Steve Acaster · 03/18/2012 (9:55 am) · 13 comments

Creating a "Ball of Fruity" style minefield.

This is a great way of creating an obstacle that the player cannot pass instead of using another wall or cliff as an element to contain the arena of gameplay.


FIRST UP, CREATE A NEW CS FILE IN SCRIPTS/SERVER FOLDER AND CALL IT

minefield.cs

We are going to use the stock explosion for the rocketlauncher as our minefield blast that can be found in "game/art/datablocks/weapons/rocketLauncher.cs"

datablock ExplosionData(RocketLauncherExplosion)
{
   soundProfile = RocketLauncherExplosionSound;
   lifeTimeMS = 200; // I want a quick bang and dissipation, not a slow burn-out

   // Volume particles
   particleEmitter = RocketExpSmokeEmitter;
   particleDensity = 10;//20;
   particleRadius = 1;//2;

   // Point emission
   emitter[0] = RocketExpFireEmitter;
   emitter[1] = RocketExpSparksEmitter;
   emitter[2] = RocketExpSparksEmitter;
   emitter[3] = RocketExpFireballEmitter;

   // Sub explosion objects
   subExplosion[0] = RocketSubExplosion;

   // Camera Shaking
   shakeCamera = true;
   camShakeFreq = "10.0 11.0 9.0";
   camShakeAmp = "15.0 15.0 15.0";
   camShakeDuration = 1.5;
   camShakeRadius = 20;

   // Exploding debris
   debris = RocketDebris;
   debrisThetaMin = 0;//10;
   debrisThetaMax = 90;//80;
   debrisNum = 5;
   debrisNumVariance = 2;
   debrisVelocity = 1;//2;
   debrisVelocityVariance = 0.2;//0.5;

   lightStartRadius = 6.0;
   lightEndRadius = 0.0;
   lightStartColor = "1.0 0.7 0.2";
   lightEndColor = "0.9 0.7 0.0";
   lightStartBrightness = 2.5;
   lightEndBrightness = 0.0;
   lightNormalOffset = 3.0;
};

We're going to make a trigger, and when a player runs into it, it's going to "spoil his day". For this, we need a dedicated trigger type. (Technically you could just make the trigger call a function but then you'd have to type that into every minefield trigger and that would be boring and time consuming)

Rather than have the player fatally stopped on touching the trigger, we can "randomize" it by using onTick. The player can enter teh trigger at any part of the trigger's tick, making the final explosion any time between 0 and 1000m/s, this can let them run a little way inside before having the explosion go off.

For this to happen, we'll use the onTick function rather than the onEnter function and set it to 1000m/s = 1 second. If you have a very deep minefield trigger you could set it to longer - just don't set it to a length that the player can run all the way through it and escape.

datablock TriggerData(MineFieldTrigger)
{
   // The period is value is used to control how often the console
   // onTriggerTick callback is called while there are any objects
   // in the trigger.  The default value is 100 MS.
   tickPeriodMS = 1000;
};

function MineFieldTrigger::onTickTrigger(%this,%trigger)
{
   // This method is called every tickPerioMS, as long as any
   // objects intersect the trigger.

   // You can iterate through the objects in the list by using these
   // methods:
   //    %trigger.getNumObjects();
   //    %trigger.getObject(n);
   
    %poor_fools = %trigger.getNumObjects();
	for(%x=0; %x < %poor_fools; %x++)
	{
		%mr_unlucky = %trigger.getObject(%x);
		
		//check it's a player! Also check it's not already dead - shouldn't be re-exploding on corpses
		//No point trying to blow up something we can't blow up
		//there are other things with trigger callbacks which may not be damageable
		//eg: items 
		//player classname is good for Ai too
		if(%mr_unlucky.getClassName() $="Player" && %mr_unlucky.getState() !$="Dead")
		{
		    //and spawn the stock grenadelauncher explosion
			%blast = new explosion()
			{
				dataBlock = "RocketLauncherExplosion";
				position = %mr_unlucky.getPosition();
			};
			MissionCleanup.add(%blast);
			
			//and kill the player outright
			%mr_unlucky.kill();
		}
	}
}

And lastly - for the scripting at least - we need to exec our new file
Open up scripts/server/scriptExec.cs
And right at the bottom add:

//...
	// Load our gametypes
	exec("./gameCore.cs"); // This is the 'core' of the gametype functionality.
	exec("./gameDM.cs"); // Overrides GameCore with DeathMatch functionality.

	exec("./minefield.cs"); // yorks new, right at the end

Boot up Torque3D and open the editor. Go into camera mode to make things easier.
Place a trigger via "Scene Tree -> Library -> Level -> Level -> Trigger", and for datablock choose our new "minefieldTrigger". Hit "create new" and then scale it in the inspector any way you like, it's best not to make it too high as you don't want explosions in midair.

As a final addition you'll need to make some models for signposts, informing the player that there is a minefield there ... or else they're going to get a great big WTF of a surprise and wonder why they died. Liberally place these warning signs outside your minefield trigger so that they can always be clearly seen. If a player runs into a minefield it should be because of their personal negligence and not because it was impossible for them to tell that there was a minefield there.


www.sciencephoto.com/image/341942/large/T1670207-Minefield_road_sign-SPL.jpg
Maybe it should say "Don't Step Off The Road" instead of "slow" ...


Back when I was modding my own single player levels and campaigns for "Ball of Fruity 1 and 2" I'd often have a friendly Ai run into the minefield as an extra method of warning the player not to go into it.

Anyhow, here is what it'll look like without any signs, but with the trigger visible for debug.


#1
03/18/2012 (10:45 am)
Too cool Steve. . . Great idea! Thanks for sharing! :)
#2
03/18/2012 (10:53 am)
Long ago in an engine that birthed Torque we used to set up random minefields, artillery bombardments, airstrikes, and sometimes giant critters that would kill people who strayed beyond the MissionArea. You've got me reminiscing :D
#3
03/18/2012 (4:52 pm)
thats a funny resource:) ty Steve
#4
03/18/2012 (9:22 pm)
Good resource as always Steve pretty standard for FPS games now :-)
#5
03/23/2012 (8:21 am)
Very cool indeed steve...... I have a dts model of a minefield warning sign that I just made if anyone would like it, use it for what ever you guys want. If anyone knows where I can upload the file for anyone who wants it, please let me know... Thanks again and as always steve, your the bloke...
#6
03/23/2012 (10:37 am)
@Donnie
Try abighole.hngamers.com/, the sort of unofficial Torque stuff site hosted courtesy of Sean Rice.
#7
03/23/2012 (3:06 pm)
Thanks steve, I'll upload that as soon as I get home this evening....

Here we go....

abighole.hngamers.com/1U0kp?do=download
#8
05/21/2012 (3:49 pm)
Quick question for ya steve or those interested to help??? I have it working to kill player and aiplayer just fine, my problem is i added it to kill any wheeledvehicle that enters the minefield and everything works except, my vehicle isnt taking damage!! I can shot the vehicle and it takes damage just fine, including explosion damage. Do I have to add something in the ondamage area of the wheeledvehicle, but still confused as to where I go or actually do to get my vehicle to blowup in the minefield!!! Thanks for any help in advance......
#9
05/21/2012 (4:09 pm)
@Donnie: since you say that your vehicle receives damage from weapons, it looks like you'll have to add a check for vehicles in the trigger code, as well as implement a Vehicle class kill() function (or call the ShapeBase damage method directly on the found object) since the one this Resource utilizes is for the Player class.

I never actually used this Resource so Steve would have to confirm/correct my guess but here is some untested and possibly unworking quick-n-dirty code:
if(%mr_unlucky.getClassName() $="WheeledVehicle" && %mr_unlucky.getDamageState() !$="Destroyed")  
{  
   //and spawn the stock grenadelauncher explosion  
   %blast = new explosion()  
   {  
      dataBlock = "RocketLauncherExplosion";  
      position = %mr_unlucky.getPosition();  
   };  
   MissionCleanup.add(%blast);  
              
   //and kill the player outright  
   %mr_unlucky.damage(0, %mr_unlucky.getPosition(), 10000, "MineFieldDamage");  
}
#10
05/22/2012 (6:05 am)
Michael, That did it all the way!! Thank you so very much and for those who want to add AIPlayer and Vehicle to the minefield destruction, heres what I have.....

if(%mr_unlucky.getClassName() $="Player" && %mr_unlucky.getState() !$="Dead" ||
		   %mr_unlucky.getClassName() $="AIPlayer" && %mr_unlucky.getState() !$="Dead" ||
		   %mr_unlucky.getClassName() $="WheeledVehicle" && %mr_unlucky.getState() !$="Destroyed")
		{
		    //and spawn the stock grenadelauncher explosion
			%blast = new explosion()
			{
				dataBlock = "GroundMajorExplosion";
				position = %mr_unlucky.getPosition();
			};
			MissionCleanup.add(%blast);
			
			//and finally, slap on the stock decal at the impact site
	   %decalObj = decalManagerAddDecal(%mr_unlucky.getPosition(), "0.0 0.0 1.0", 0, 1, "ScorchRXDecal", false);
			
			//and kill the player outright
			%mr_unlucky.kill();
			%mr_unlucky.damage(0, %mr_unlucky.getPosition(), 10000, "MineFieldDamage");

Hope it helps and thanks again for a great resource steve and your help michael......
#11
01/14/2013 (7:37 am)
I want to give kill credits to the player who deployed the mine for my Legions Overdrive mod.
I Know how to set the trigger client.owner or object.client, when the mine is deployed. How would I add them as the damage source for kill credits in the line below?

%mr_unlucky.damage(0, %mr_unlucky.getPosition(), 10000, "MineFieldDamage");
#12
01/15/2013 (12:19 am)
"How would I add them as the damage source for kill credits in the line below?"

u can put a damageType check in this function.
"function GameCore::onDeath(%game, %client, %sourceObject, %sourceClient, %damageType, %damLoc)"


something like this:
if(%damageType == "MineFieldDamage")
{
%game.incDeaths( %client, 1, false );
%game.incScore( %sourceClient, 1, true );
%game.incKills( %sourceClient, 1, false );

}

not tested but i am sure that is the way to give credit to rigger client.owner or object.client.
#13
03/31/2013 (8:50 pm)
Steve, I think I did something wierd, my hard drive crashed but before it died, poor thing, when my player or ai entered the mine field and yes it worked great, but when the died sometimes their med pack i had them drop got stuck in the air?? could it be i need to raise my box of death higher in height, just thought of it, but cant try it or anyone else get this and know??