T3D/Tutorials/SimpleFPSTutorial/Part11

From TDN

SIMPLE FPS TUTORIAL for Torque 3D



Back to Part Ten: Simple Pathed Bots

Part Eleven




GamePlay, Challenge, Variation and Set-Pieces:


Modern single player FPS tends to follow a fairly linear route, and for interest in it's gameplay relies on rising difficulty, variation of action, and "set pieces".

We moved from a static enemy, to an enemy which runs out of cover, to dual enemies, with short and long ranged weapons. From this brief description, you can see the rising level of difficulty and basic variations.

Add 3 new bots, 2 will be short range and the third long. We'll also return to the static method of not using a path. (re)Start up T3D and load the tutorial level. Go into camera mode and open the World Editor. At the 2nd side-alley with the rock outside, place a spawnSphere on either side of that rock. Rotating them so that they are both pointing in the direction that the player will come from. Name them "botspawn2" and "botspawn3". Add a third spawnsphere at the far turn (left turn 3 which is turn 5 in total of our route), directly in line with the big rock at the side-alley entrance and name this "botspawn4". Rotate it to face the direction the player will come from. Drag/drop the new spawnSpheres into "botDropPoints".

Create a "TutorialTrigger" between the third rock and the 2nd left turn (4th overall), and scale to fit. Call this "trig4". We're going to spawn 3 static enemies, the closer 2 having "fullauto" weapons and the third at the back spawnsphere (botspawn4) have a longer ranged "semiauto" weapon. The "commandEnter" should look like this:

%checkclass = %obj.getClassName();
if(%checkclass $= "Player")
{
     if(!isObject(bot2))
         aiplayer::spawnBot(bot2, botspawn2, fullauto);

     if(!isObject(bot3))
         aiplayer::spawnBot(bot3, botspawn3, fullauto);

     if(!isObject(bot4))
         aiplayer::spawnBot(bot4, botspawn4, semiauto);
}


Third Wave Spawns

In-game the player will face 2 bots close up, the third in the distance shooting down the sides of the rock. Apart from increasing difficulty by sheer numbers, variation is also important, so our next bot will do something new.

Outside of our route, beyond the third left turn, on top of the terrain, create a spawnSphere that is aligned with "botspawn4". Place it on top of the raised terrain, a some way back. Rotate it to face "botspawn4", then name this "botspawn5". Create a new "TutorialTrigger" named "trig5", and place it across our route, after the entrance to the second side-alley.

Over Terrain Bot

We're going to make a moving bot, but not one that is using a path. The basic function for moving a bot is called "setMoveDestination" and gives the bot an XYZ location to move to, usually derived from the position of an object like a "marker". This function will send a bot to a location. There are no checks for obstacle avoidance, it just moves straight.

Select "trig5" and in "commandEnter" type this script:

%checkclass = %obj.getclassname();

if(%checkclass $="Player")
   if(!isObject(bot5))
   {
      %shockbot = aiplayer::spawnbot(bot5, botspawn5, semiauto);
      %shockbot.setMoveDestination(botspawn4.getPosition());
   }

Using "setMoveDestination" we give the position of "botspawn4" as our destination.

2 Over Terrain Bot Spawns

Save and save often. Play through to test.

Do this again, but double the challenge with 2 bots. At the final rock, on the raised terrain near the the third side-alley place a new "spawnsphere" - not too close to the side-alley - we don't want our bot to accidentally fall in, we just want to obscure the Player's view of the spawning --- spawning out of thin air in front of the player looks bad. Every care should be made to prevent it, and yet this continues to happen in "triple A game franchises that have cost tens of millions of dollars to develop".

Call this spawnsphere "botspawn6", and rotate it to face the rock. On the other side of the rock, upon the raised terrain and at a similar distance from the edge create another spawnsphere named "botspawn7".

Now create 2 spawnspheres, one on either side of the rock down in our lower route. Call the one closest to "botspawn6", "bot6goal" and the one closest to "botspawn7", "bot7goal". Create a new "TutorialTrigger" just round the corner of the third turn and call it "trig6". In "commandEnter":

%checkclass = %obj.getclassname();

if(%checkclass $="Player")
{
      if(!isObject(bot6))
      {
         %newbot6 = aiplayer::spawnbot(bot6, botspawn6, semiauto);
         %newbot6.setMoveDestination(bot6goal.getPosition());
      }

      if(!isObject(bot7))
      {
         %newbot7 = aiplayer::spawnbot(bot7, botspawn7, semiauto);
         %newbot7.setMoveDestination(bot7goal.getPosition());
      }
}


Save, and test.

Let's create a "mini set-piece", something that the player hasn't encountered yet that will add to the drama of gameplay. When the player is at the next corner, a bot will rush around it suddenly - and to distract the player, we're going to script an explosion, using the stock explosion of T3D's stock rocketLauncher. This explosion won't do any damage, it's just to distract and startle the Player.

Create a new "Path" and name it "botPath4", setting the "isLooping" to unchecked. Create a "Path Node" (now called "marker" in "missiongroup"), and place it around the corner close inside of the terrain wall. Call this marker "path4start". Create another "path Node/marker" at the apex of the corner and call this "boomMarker". Create a final "path Node" and place it a some way around the corner, in the middle of the route. You don't have to name this "marker". Now drag/drop all three "markers" into"botPath4" and drag/drop that into it's relevant Simgroup/folder. Now check that the "markers" are visualizing the path in the correct order by selecting "botPath4" and looking at the green path of arrows. If they are not, change the order manually in the Object Inspector for each "marker's" "seqNum". Rename if necessary so that "path4start" is the first marker and "boomMarker" is the second at the apex of the corner.

Create a "TutorialTrigger", scale it across the width of the route and place it down from the last rock but up from the turn, just in front of the last "marker" for "botPath4".

Explosion Trigger

Name this trigger "trig7" and script the "commandEnter":

%checkclass = %obj.getClassname();

if(%checkclass $="Player")
   if(!isObject(pathbot4))
   {
      %newbot4 = aiplayer::spawnBot(pathbot4, path4start, fullauto);
      %newbot4.followpath("MissionGroup/botpaths/botPath4", 2);
      %markerPos = boomMarker.getPosition();

      %ied = new explosion()
      {
          datablock = rocketLauncherExplosion;
          Position = %markerPos;
      };

   }


When the player activates the trigger an explosion will occur at "boomMarker" and a bot will rush out to attack the player . The explosion uses all of the properties of the stock datablock "rocketLauncherExplosion" including particles, debris, and camera shake. Remember, there is no damage because damage is a variable of projectiles, not explosions.

Save and test it in-game.

Let's have more explosions. But rather than typing in the explosion parameters each time, let's make a function to do that for us. Remember the custom file we made to share particles and effects for our custom weapons in Part Four of this tutorial series? Quit T3D and in an external text editor or IDE, load up "weaponEffects.cs". Below everything add:

function SpawnBang(%xyz)
{
      %explode = new explosion()
      {
          datablock = rocketLauncherExplosion;
          Position = %xyz;
      };
}


Restart T3D, and our Tutorial level. We will script FIVE explosions, and have them go off one after another. In the World Editor, place a "TutorialTrigger" across the route, half-way between the entrance of the third side-alley and the final corner (turn 6). Scale it so it fills the width of the route and cannot be avoided. Name this "trig8" and place it in "level_Triggers".

Create SpawnSphereMarkers to reference the positions. At the far end of the route, where it meets the large circle with the station model, place a spawnsphere by the the left side of the circle entrance. Next place one on top of the raised terrain (near the edge) on the left side, halfway between the circle entrance and the side-alley entrance . On the raised terrain right next to the side-alley entrance (on the side nearest the station model) add another. In front of the side-alley entrance in our lower game area add another, and finally, in front of "trig8" and to the left side, add the fifth. Name these "blast1" to "blast5", in the order that you created them (furthest from "trig8" first). Createa a new "simGroup" named "blastMarkers" and drag/drop all five new spawnPointMarkers into it to tidy up.

Select "trig8" and in the "commandEnter",inside the usual Player check add:

%checkclass = %obj.getClassname();

if(%checkclass $="Player")
{
   spawnBang(blast1.getTransform());
   schedule(600, 0, "spawnbang", blast2.getTransform());
   schedule(1100, 0, "spawnbang", blast3.getTransform());
   schedule(1500, 0, "spawnbang", blast4.getTransform());
   schedule(1900, 0, "spawnbang", blast5.getTransform());
}


Serialized Explosions Trigger

Save, return to player mode and test the trigger, the blasts should move forwards rapidly one after another.

Enemies have always appeared as the player has progressed, but now we are going to spawn one behind him, and have it follow a path around the last turn to attack.

Create a new "path" and place a "path node" near the left wall just next to "trig7". Place another at the apex of the corner near, near where you earlier placed "boomMarker". Place a final "path node" outside the entrance to the final side-alley. Drag/drop all three new "markers "into the new "path" object. Rename this "botPath5", disable "isLooping" and make certain that the nodes are in the correct order with the path running from "trig7" towards the station model. If they are not, either swap them around or alter the "marker's" "seqNum". Select the first "marker" on the path near "trig7" and name it "path5start".

Bushwacker Path

An ambush wouldn't be an ambush without a crossfire. Add a path for a second bot to spawn and help our bushwacker. Create a new "path" called "botPath6" and disable "isLooping". Add a "path node" just round the left corner inside the large circle with the station, add another at the apex near "blast1", and a final "path node" halfway between the entrance to the big circle and the entrance to the last side-alley. Collect the "markers" into the new "path", check that the path is running in the correct order, and call the first "marker "path6start". Drop the path into "botPaths".

Bushwacker 2 Path

Inside "trig8's" "commandEnter", inside the "check for Player", below the functions for our explosions, add the spawning for our ambushing bots.

     if(!isObject(bushWack1))
      {
         %ambush1= aiplayer::spawnBot(bushWack1, path5start, semiauto);
         %ambush1.followpath("MissionGroup/botpaths/botPath5", 2);
      }

     if(!isObject(bushWack2))
      {
         %ambush2= aiplayer::spawnBot(bushWack2, path6start, semiauto);
         %ambush2.followpath("MissionGroup/botpaths/botPath6", 2);
      }


Save, and test.

Our game route is complete, all that remains is the finale.



Part Twelve: Finale