Game Development Community

Favorite TGE Tips and Tricks.

by Clint S. Brewer · in Torque Game Engine · 03/26/2005 (3:14 pm) · 22 replies

I thought it would be educational if everyone could share some of their favorite torque tips and tricks they've come across.

everything is game.
Map making, scripting, coding, modelling, specific resources you like, etc

as long as it's related to TGE



there are a couple that come right to my mind.

=========================
Tip: Use tree();

This handy script function gives you a peek at everything accesible from script.

For a quick tour.
open up the console,
type
"tree();"
close the console.
expand the RootGroup
expand the MainInstantGroup
there you'll find your MissionGroup and the MissionCleanup group.
browse arround.

This is great for peeking at where an object lives in the group hierarchy and looking at all it's dynamic fields.
Page «Previous 1 2
#1
03/26/2005 (3:24 pm)
edit: this tip is not a good one, see the discussion in the next few posts for why -csb
=========================
Tip: use datablocks where you might use a new ScriptObject

background. I was making a spell system, and the first way I tried to do it was by making a spell script object class. when you ready the spell I would make a new script object and store the id in a player variable....something like
%player.currspell = new ScriptObject ....etc

This worked, but you run into problems down the line. What if you want to save the player and load him...now you have a number id for the currspell.. when you save him you will have to make sure that you replace that number with some sort of reference to the proper type of spell. When you load him you will have to make sure to make a new script object again.

an alternate way of doing this is to use a simple datablock for your spell class
something like
datablock GameBaseData(PushSpell)
{
	className = "Spell";

	displayname= "Force of Nature";
	description= "Summoning upon the strong wind of the forrest this spell will push things away from you.";
	school = "Nature";
	manacost = 1;
	requiredEntities = 0;
	castAnimation = "castEH2";

    chargeEmitter = ChimneySmokeEmitter;
    castEmitter = Emitter_SpellPush;

};

then when the player readys a spell, you don't need to create any new objects, you just specify the datablock like so

%player.currspell = PushSpell;

you can add functions to your datablock like any other and use
%player.currspell.MySpellFunction(%player);

If the spell needs object specific data stored then store it in the %player object. like so

%player.PushSpell[customeData] = blahblah;


that turned out a bit longer than expected, but this same concept can be used and is used all over the place. it was not obvious in the beginning for me.
#2
03/26/2005 (3:41 pm)
=========================
Tip: get warnings about your undefined script variables
add the following to your server/defaults.cs
$Con::warnUndefinedVariables = 1; //warn us when we access undefined variables

now whenever you attempt to use a variable that has not been defined you'll get a warning message about it. This is very helpful in tracking down those slight mispellings.
one I just ran into was: %index vs. %indx

those types of things happen all the time. When you first set warnUndefinedVariables you will probably see tons of warnings, take the time to fix the ones that you can to clean up the console so it's easier to see the real problems from your code. You'll also learn a bit about different parts of the scripting engine and about what sorts of settings might be available that you aren't using when you get warnings about various $pref variables.
#3
03/26/2005 (5:08 pm)
ScriptObjects can be named just like a datablock can. So in your spell example you could still have used a ScriptObject in the same manner.


new ScriptObject(PushSpell)
{
    // Blah Blah
};

%player.currSpell = PushSpell;
#4
03/26/2005 (5:20 pm)
Very true.
then what's the only difference? :
the scriptobject spells info will not be easily readable on the client. But with the datablock it would be auto transmitted at game start?

now I know you of all people have some other good tips for us.
#5
03/26/2005 (8:58 pm)
Great thread idea. Fill this up and we can add it to TDN when it comes on-line.
#6
03/27/2005 (2:59 am)
Clint,

Using a datablock, the fields from GameBaseData will be transmitted to clients when they join, however any fields you've added in script won't be. I would say that using a ScriptObject would be a lot better in the example above as you don't need the extra features of a datablock, and indeed using a datablock causes more network traffic when a client connects.

If you want a custom datablock you need to define it in C++. The reason for this is datablocks optimise the number of bits required to represent the data. For example, an int that will only ever need to hold a maximum of 4 would be represented with 2 bits in the network stream. Although you could in theory automatically transmit dynamic fields added in script, it would not be possible to automatically optimise them as the script compiler has no knowledge of the size of the data. The bitStream class (the class that datablocks use for their networking) packs data such that the minimum number of bits neccessary gets transmitted, so if you have two ints, one of 2 bits and one of 6 bits, the bitStream would transmit 1 byte. If it was automatically done by the datablock, in the worst case it would have to assume they were both 32 bit ints and thus transmit 8 bytes. That's a bit of a contrived example, but hopefully it illustrates the point.

T.

Edit: Edited to make more sense.
#7
03/27/2005 (5:09 am)
Export only the bare minimum in your sequences
Don't include any mountpoints or any other non directly animated nodes in your sequence exports. This makes later additions to your character much simpler, as well as cutting down the size. For example, the position of mount0 never changes, it's always tied to your hand. If you inlude it, and later your programmer wants to rename all the mounts to tag_, you would have to reexport all your animations. If you haven't included it, then you simply have to reexport the main dts.
The default animations are all wrong, in that they include useless nodes such as ski and light. So if you want to borrow them temporarily, you _must_ include those nodes in your dts as well. If they hadn't been included in the sequences, then your dts could have followed a standard biped, and been used much more universally.
#8
03/27/2005 (5:45 am)
Not to mention that the spell datablock on the client wouldn't be of much use since you can't access it using the name on the client, so it's kinda like a waste to have it there.
#9
03/27/2005 (12:19 pm)
Script object vs datablock, Thanks to All for your help, looks like I have some script cleaning up to do. I was under the impression (for no good reason) that the dynamic fields would be sent to the client as well. Thanks for going into that in particular Tom.
#10
03/27/2005 (12:43 pm)
In adition to Harold's simple snip above, the only other thing I had to do to convert my datablocks to scriptobjects was change
className = "Spell"
to
class = "Spell"

then all worked fine.
#11
03/27/2005 (12:44 pm)
@ Erik, great tip thanks.
#12
03/27/2005 (1:03 pm)
TIP

When Using the HttpObject to pass multiple variables into a script (such as php) you need to change httpobject.cc

if(asciiEscapeTable[c])      { 
        dest[destIndex++] = '%';
         dest[destIndex++] = getHex((c >> 4) & 0xF);
         dest[destIndex++] = getHex(c & 0xF); 
     }      
else 
        dest[destIndex++] = c;
To This
if(asciiEscapeTable[c])      {
       if(c == 9)       {
         dest[destIndex++] = '&';
       }       else       {  
       dest[destIndex++] = '%';
         dest[destIndex++] = getHex((c >> 4) & 0xF);
         dest[destIndex++] = getHex(c & 0xF);
       } 
     }
     else 
        dest[destIndex++] = c;
and concatinate the string with the "\t".

Finally the HttpObject can recieve from data from a script via the ::online method. but each "line" must be denoted with a new line charecture

Example of php :
echo("This line will be recieved\n");

As found in This Resource
#13
03/27/2005 (2:02 pm)
@Anthony, very nice one.

tip: Keep a history of your console entries from run to run

As Discussed in this thread

It could use a little tweaking still but I use this constantly. Saves a lot of time typing in those long path names if you are working on a single script over and over again...or remembering what that esoteric command you typed last run was.
#14
03/28/2005 (5:03 am)
Instead of keeping a history, I have a .cs file called "helperFunctions.cs" Anytime I know I'll be needing to type in a long command or series of commands to test something I simply make a new function in "helperFunctions.cs" and enter the data in there. It can stay there forever and when I'm ready to release anything I simply remove the file and the exec line and it's gone. Here's a few example functions...


function fps()
{
	metrics("FPS");
}



function vars()
{
	export("*", "Shared/Temp/Variables.cs", 0);
}



function sav()
{
	$Game.save("Shared/Temp/testing.cs", 1);
}



Also, if you get involved in something and realize you are going to be typing the same line over and over, you can simply copy/paste the line you entered into the console or get it later from the console log.
#15
03/28/2005 (5:23 am)
TIP: Need to track some variables while you play and don't want to load up debuggers or keep switching back and forth from the console gui?


Then insert this function and echo that data right into your chatHud and console at the same time...

function gtcdb(%message)  //  GTC DeBug
{
	messageall(1, %message);

	error(%message);
}


And then you can just change a line like this...

echo("Client = " @ %client @ "   Player = " @ %client.player);

to this...

gtcdb("Client = " @ %client @ "   Player = " @ %client.player);





TIP: Want to easily enable and disable echo and error code without having to scroll through files and delete or comment them out?


Then assign a global debug variable...

$gtcdb = 1; // 1/0 - ON/OFF


And then as you write, or come across debug code just alter it like so...


if($gtcdb){ gtcdb("Client = " @ %client @ "   Player = " @ %client.player); }
 
or...
 
if($gtcdb){ echo("Client = " @ %client @ "   Player = " @ %client.player); }




And if you wanted to use my GTC DeBug in the same fashion you could leave all your lines alone and just do this...

function gtcdb(%message)  //  GTC DeBug
{ 
	if($gtcdb)
	{
		messageall(1, %message);

		error(%message);
	}
}


That way you don't have to type out the "if($gtcdb)" in front of every "gtcdb();" function call. Saves mucho time and time is definately money. I could write an entire book about debugging and timesaving tricks, but you'll have to take my online classes to get that info. [/shamelessPlug]




EDIT: IMPORTANT!!!! - DO NOT put ANY tagged strings through your chatHud because the chatHud will get caught in an infinate loop and you will be chat spammed so hard you'll barely be able to quit the game.
#16
03/28/2005 (12:59 pm)
@Gonzo, nice ones
Quote:you'll have to take my online classes to get that info. [/shamelessPlug]
it's not much of a plug without a link to your classes or one in your profile :) didn't see it but maybe I missed it.

speaking of debugging...I could have sworn I've seen some script functions about a script debugger, if someone has some tips on that 't'would interesting.
#17
03/28/2005 (1:20 pm)
For any TGE newbs out there.

echo(); is your friend.

Echo statements are very good to put in your script functions when you are trying to figure out what the hell is going on. I also think it is a good thing to do in order to figure out what a specific function is doing that you are unfamiliar with.

Resource. http://winmerge.sourceforge.net WinMerge
for all of you Windows developers. It's a great tool to merge your code and saves you a tremendous amount of time.
#18
03/28/2005 (1:27 pm)
TelnetDebugger rocks, especially with dual monitors.

One one monitor start Torque.
Start it doing whatever, then in the console do:
dbgSetParameters(port, pass);

On the other monitor, start torque again, and in the console do:
exec("common/debugger/debugger.cs");

Gary (-;
#19
03/29/2005 (3:08 pm)
Scripting:
- enableWinConsole(true);
- setLogMode(6); - logging = good
- trace(True); - TGE will show you every function it is entering and leaving in the console
- use RELEASE version of the TGE executable, not the DEBUG. There is no reason I can think of to use DEBUG if you are just scripting, and it causes a few problems anyway.

Tribal IDE:
- use your functions and current file functions windows. This is better than combing through your scripts looking for them when you forget the exact name.
- make a backup of the untouched scripts from the tge source, as well as a backup of your functional error-free last saves, save them as new projects in seperate folders, and use file->reopen to refer to them when you are having problems.
- use a grep program (google "wingrep") to search for text within all the files in a given folder.
#20
03/30/2005 (8:23 am)
Along the lines of what entropy stated
Quote:- make a backup of the untouched scripts from the tge source, as well as a backup of your functional error-free last saves, save them as new projects in seperate folders, and use file->reopen to refer to them when you are having problems.

Without getting into a debate on which source control to use, I highly recommend everyone use something. There are plenty out there that you can get for free. It may seem like overkill but if you have ever had those times when you accidentally blew away something you shouldn't have or had one of those "hmm this just worked last week" moments you will be glad you used one.
Page «Previous 1 2