Tactics-Action Hybrid Game Tutorial Part12: Finale
by Steve Acaster · 05/13/2011 (4:14 pm) · 6 comments
Back to Part Eleven: Ai Paths
It's time to complete our game Tutorial and finish this working level.
Near the rock where out two paths end, create a new trigger and call it "trig3" and scale it so it stretches over the route. We'll have two more Enemy Ai spawn at the starting markers of the two paths, but this time these Ai will just be static. Well also have a third Ai spawn, so place a spawnSphere or wayPoint halfway down the dead-end alley which this rock is outside the entrance of, and call it "botspawn3". Put the trigger in the appropriate folder/simGroup and in the enterCommand:
Notice that we are missing the "paths" variable from the spawn functions - thus there are no paths for these new Ai to follow and they will reamin stationary.
Next go to the last rock on the route and place waypoints at either side of it, call them "botspawn3" and "botspawn4". Create a trigger called "trig4", and position it across the route just behind the penultimate rock where our two paths start.
They will be one more enemy engagement for our Ally Team before the "Finale" at the station01 model. Halfway down the final dead-end alley place a spawnSphere and call it "botspawn6", we'll give this Ai a "goal", somewhere to run to in a straight line with nothing in the way, and thus save ourselves the time of creating a path. Just outside the entrance to this last dead-end alley, in direct view of the spawnSphere, create a wayPoint or spawnSphere and call it "bot6goal" which goes in the "bot_paths" folder in the "Scene Inspector".
Now create two new paths, have them start in our large, circular area with the station, just inside of the entrance way, and so that they cannot be seen from the last corner of the route. Call these paths "botpath3" and "botpath4", and call their starting nodes "path3start" and "path4start" respectively. Remember to add all paths to their "bot_paths" folder/simGroup or the Ai will not follow them.
Create a new trigger called "trig5" and place it at the final corner, past the last rock but before the last dead-end alley. make it a big square to fill the route at the corner.
Save and save often - remember, if you have been playtesting whilst building a level, some of your triggers may have been "turned off", so you need to edit their "triggerOff" variable and reset it to "0".
Now let's make our "finale". Outside the station01, on either side of it (looking from the route the Ally Team will approach) add spawnspheres called "botspawn7" and "botspawn8". Move them so that they have the entrance to the final area in view. Create two more called "botspawn9" and "botspawn10" and place one in each of the lower towers of station01 model, near to the doorway (they won't be able to see the entrance to the final area directly but will be able to see close to it).
Create two new paths, "botpath5" and "botpath6" with their starting markers called "path5start" and "path6start" respectively. Both of these paths should start behind one of the station01 towers - where it cannot be seen from the entrance route to the final area, and then have a trial of "path nodes/markers" which run underneath the bridge of station01 and come to a stop just a little way in front of the station01 model.
Now we need our final trigger to spawn these Enemy Team defenders, as well as to check for "victory conditions" (we created the variable "vitory = 0" when the "turnManager" spawned at "startGame"). Place a new trigger called "final_trig", down the route leading to the final area with the station01 model, between the entrance to this final area and the entrance to the last dead-end alley and make it large so that it covers most of this part of the route (scale = 30 30 5). It is highly likely that in-game an Enemy Team member will move through this trigger and start it off before a member of Ally Team does, so we'll need some script to make certain that only Ally Team members can cause this trigger to fire. For this we need to identify which object has entered the trigger and for this we use the "tickCommand".
How it works: the trigger counts all of the objects inside it every "tick" (500m/s for stock defaultTrigger datablock), if that playerObject is not of "team = 1" it aborts before the main body of the trigger is reached. When an Ally playerObject is inside the trigger it will start the function "final_spawn()" and then set the "triggerOff" to "true", effectively disabling the trigger. In scripts/server/gameTorqueTactics.cs add the new function at the bottom.
The object of the game we are creating in this Tutorial is to capture the station01 model, so the Ally Team will have to kill all of the Enemy Team which defend it - but don't have to kill all of the Enemy Team in the level (though due to the linear nature of the mission route, it is likely that they did). We need to check when this "victory condition" has been met and for this purpose we will have a function which will loop until the defending Ai members are deceased. "Final_Spawn" calls, "start_Victory_Check()" to begin this function, and this in turn loops "victory_Check()".
Make sure that this new arrayObject get's deleted when the game ends.
When the victory condition has been met, it will be used when we the Turn changes in "TurnOver" Server Command which we made earlier.
You should now have a functioning 3rd person, turnbased squad tactics/action hybrid similar in gameplay style to "Valkyria Chronicles" ... because Torque3D is not just for Tribes style First Person Shooters - but anything which you have the will to create.
It's time to complete our game Tutorial and finish this working level.
Near the rock where out two paths end, create a new trigger and call it "trig3" and scale it so it stretches over the route. We'll have two more Enemy Ai spawn at the starting markers of the two paths, but this time these Ai will just be static. Well also have a third Ai spawn, so place a spawnSphere or wayPoint halfway down the dead-end alley which this rock is outside the entrance of, and call it "botspawn3". Put the trigger in the appropriate folder/simGroup and in the enterCommand:
if(trig3.triggerOff == 1) return; if(!isObject(bot5)) aiplayer::tacticsSpawn(bot5, path1start, 0); if(!isObject(bot6)) aiplayer::tacticsSpawn(bot6, path2start, 0); if(!isObject(bot7)) aiplayer::tacticsSpawn(bot7, botspawn3, 0); trig3.triggerOff = 1;
Notice that we are missing the "paths" variable from the spawn functions - thus there are no paths for these new Ai to follow and they will reamin stationary.
Next go to the last rock on the route and place waypoints at either side of it, call them "botspawn3" and "botspawn4". Create a trigger called "trig4", and position it across the route just behind the penultimate rock where our two paths start.
if(trig4.triggerOff == 1) return; if(!isObject(bot8)) aiplayer::tacticsSpawn(bot8,botspawn4, 0); if(!isObject(bot9)) aiplayer::tacticsSpawn(bot9, botspawn5, 0); trig4.triggerOff = 1;
They will be one more enemy engagement for our Ally Team before the "Finale" at the station01 model. Halfway down the final dead-end alley place a spawnSphere and call it "botspawn6", we'll give this Ai a "goal", somewhere to run to in a straight line with nothing in the way, and thus save ourselves the time of creating a path. Just outside the entrance to this last dead-end alley, in direct view of the spawnSphere, create a wayPoint or spawnSphere and call it "bot6goal" which goes in the "bot_paths" folder in the "Scene Inspector".
Now create two new paths, have them start in our large, circular area with the station, just inside of the entrance way, and so that they cannot be seen from the last corner of the route. Call these paths "botpath3" and "botpath4", and call their starting nodes "path3start" and "path4start" respectively. Remember to add all paths to their "bot_paths" folder/simGroup or the Ai will not follow them.
Create a new trigger called "trig5" and place it at the final corner, past the last rock but before the last dead-end alley. make it a big square to fill the route at the corner.
if(trig5.triggerOff == 1)
return;
if(!isObject(bot10))
{
aiplayer::tacticsSpawn(bot10, botspawn6 , 0);
bot10.goal=bot6goal;
}
if(!isObject(bot11))
aiplayer::tacticsSpawn(bot11, path3start, 0, botpath3);
if(!isObject(bot12))
aiplayer::tacticsSpawn(bot12, path4start, 0, botpath4);
trig5.triggerOff = 1;Save and save often - remember, if you have been playtesting whilst building a level, some of your triggers may have been "turned off", so you need to edit their "triggerOff" variable and reset it to "0".
Now let's make our "finale". Outside the station01, on either side of it (looking from the route the Ally Team will approach) add spawnspheres called "botspawn7" and "botspawn8". Move them so that they have the entrance to the final area in view. Create two more called "botspawn9" and "botspawn10" and place one in each of the lower towers of station01 model, near to the doorway (they won't be able to see the entrance to the final area directly but will be able to see close to it).
Create two new paths, "botpath5" and "botpath6" with their starting markers called "path5start" and "path6start" respectively. Both of these paths should start behind one of the station01 towers - where it cannot be seen from the entrance route to the final area, and then have a trial of "path nodes/markers" which run underneath the bridge of station01 and come to a stop just a little way in front of the station01 model.
Now we need our final trigger to spawn these Enemy Team defenders, as well as to check for "victory conditions" (we created the variable "vitory = 0" when the "turnManager" spawned at "startGame"). Place a new trigger called "final_trig", down the route leading to the final area with the station01 model, between the entrance to this final area and the entrance to the last dead-end alley and make it large so that it covers most of this part of the route (scale = 30 30 5). It is highly likely that in-game an Enemy Team member will move through this trigger and start it off before a member of Ally Team does, so we'll need some script to make certain that only Ally Team members can cause this trigger to fire. For this we need to identify which object has entered the trigger and for this we use the "tickCommand".
if(final_trig.triggerOff == 1)
return;
for(%x=0; %x < final_trig.getNumObjects(); %x++)
{
%obj = final_trig.getObject(%x);
if(%obj.team != 1)
return;
final_spawn();
final_trig.triggerOff = 1;
}How it works: the trigger counts all of the objects inside it every "tick" (500m/s for stock defaultTrigger datablock), if that playerObject is not of "team = 1" it aborts before the main body of the trigger is reached. When an Ally playerObject is inside the trigger it will start the function "final_spawn()" and then set the "triggerOff" to "true", effectively disabling the trigger. In scripts/server/gameTorqueTactics.cs add the new function at the bottom.
final_Spawn()
{
if(!isObject(bot13))
aiplayer::tacticsSpawn(bot13, botspawn7 , 0);
if(!isObject(bot14))
aiplayer::tacticsSpawn(bot14, botspawn8 , 0);
if(!isObject(bot15))
aiplayer::tacticsSpawn(bot15, botspawn9 , 0);
if(!isObject(bot16))
aiplayer::tacticsSpawn(bot16, botspawn10, 0);
if(!isObject(bot17))
aiplayer::tacticsSpawn(bot17, path3start, 0);
if(!isObject(bot18))
aiplayer::tacticsSpawn(bot18, path4start, 0);
if(!isObject(bot19))
aiplayer::tacticsSpawn(bot19, path5start, 0, botpath5);
if(!isObject(bot20))
aiplayer::tacticsSpawn(bot20, path6start, 0, botpath6);
start_victory_check();
}The object of the game we are creating in this Tutorial is to capture the station01 model, so the Ally Team will have to kill all of the Enemy Team which defend it - but don't have to kill all of the Enemy Team in the level (though due to the linear nature of the mission route, it is likely that they did). We need to check when this "victory condition" has been met and for this purpose we will have a function which will loop until the defending Ai members are deceased. "Final_Spawn" calls, "start_Victory_Check()" to begin this function, and this in turn loops "victory_Check()".
function start_Victory_Check()
{
if(!isObject($Defend))
{
$Defend = new arrayobject();
if(isObject(bot13))
$Defend.add(bot13, bot13.getID());
if(isObject(bot14))
$Defend.add(bot14, bot14.getID());
if(isObject(bot15))
$Defend.add(bot15, bot15.getID());
if(isObject(bot16))
$Defend.add(bot16, bot16.getID());
if(isObject(bot17))
$Defend.add(bot17, bot17.getID());
if(isObject(bot18))
$Defend.add(bot18, bot18.getID());
if(isObject(bot19))
$Defend.add(bot19, bot19.getID());
if(isObject(bot20))
$Defend.add(bot20, bot20.getID());
MissionCleanup.add($EnemyManager);
}
schedule(1000, turnManager, "victory_Check");
}
function victory_Check()
{
%count = $Defend.count();
if(%count > 0)
{
for(%i=0; %i < %count; %i++)
{
%bot = $Defend.getkey(%i);
if(!isObject(%bot))
{
%k = $Defend.getindexfromkey(%bot);
$Defend.erase(%k);
}
else
{
if(%bot.getState() $= "Dead")
{
%k = $Defend.getindexfromkey(%bot);
$Defend.erase(%k);
}
}
}
schedule(2000, turnManager, "victory_Check");
}
else
{
echo("Victory Conditions have been met! No Defenders left!");
turnManager.victory = 1;
}
}Make sure that this new arrayObject get's deleted when the game ends.
function TorqueTacticsGame::endGame(%game)
{
//...
if(isObject(turnManager))
{
TurnManager.delete();
echo("Deleting Turn Management System");
}
if(isObject($Defend))//<--- yorks
$Defend.delete();//yorks <---
parent::endGame(%game);
//...When the victory condition has been met, it will be used when we the Turn changes in "TurnOver" Server Command which we made earlier.
You should now have a functioning 3rd person, turnbased squad tactics/action hybrid similar in gameplay style to "Valkyria Chronicles" ... because Torque3D is not just for Tribes style First Person Shooters - but anything which you have the will to create.
About the author
One Bloke ... In His Bedroom ... Making Indie Games ...
#2
05/13/2011 (7:58 pm)
Many thanks for this series, it covers many aspects of T3D, and it's really great to have something working nicely at the end. Very helpful.
#3
05/13/2011 (10:57 pm)
Thanks for this Steve. I have the last two sections to do, then it is time to put my custom art and assets in with a nice shiny new GUI ... :)
#4
05/15/2011 (11:07 pm)
I would honestly pay for a book once you make one. Very good!
#5
Am definately thinking about reserecting one I had on in mind and put on the back burner years ago.
As for a book, I would buy it as well, can't wait for 1.1 Final to use all the funky new stock objects
05/16/2011 (3:07 pm)
I wonder how many turn based action/stratergy games you just spawned Steve?Am definately thinking about reserecting one I had on in mind and put on the back burner years ago.
As for a book, I would buy it as well, can't wait for 1.1 Final to use all the funky new stock objects
#6
This would be a great interface for the rebirth of X-COM 2012!!
05/22/2011 (4:37 am)
Just finished it up with no problem - This was a great help Steve!This would be a great interface for the rebirth of X-COM 2012!!

Associate Konrad Kiss
Bitgap Games