Developer Store
Support
Member Forums

Screenshots
FAQ
Documentation
License
Known Issues
Downloads

MMOWorkshop.com Store Opened!
Torque MMO Kit - Open Sourced!
Torque MMO Kit - 1.5.2 Port Alpha Test
Torque MMO Kit - OSX Status

GarageGames.com irc.prairiegames.com
#mmoworkshop

PyTorque
TGB Web Browser


Boaal

hallsofvalhalla - After a long epiphany
Leathel - FoHO pre-Alpha 2.42
OldRod - More Musings on the MMO Industry
xapken - nice
J.C. Smith - 0.0.4.1 Build Notes
Wolf Dreamer - Pointless blog of pointless things
AthlonJedi2 - Server Nuked !!!!!
gamer_goof - New character model GIRL1 available only $4
... MORE BLOGS!

Lets talk skills.
Mob chase range?
Auction House + Internal Mail Sy...
Crafting Wiki
Every Day a new question... :)
Web Host
Seeking experienced programmer
Integrating Green-Ear SDK (paid)
where character information is s...
Spells Problem...

Working with Python and Torque Script

So you're new to Python and/or new to Torque Script and definitely new to the two languages working together. This page is all about illustrating and demonstrating how the two work together. The individual languages themselves are beyond the scope of this document.

Theory and Background

Python is a powerful programming language that stands on it's own two feet. Torque Script on the other hand is strictly dependant on the Torque Game Engine (which is the underlying engine used in the MMO Kit). So how do the two work together? Well, there have been modifications made to the game engine which embeds a Python interpreter into the game itself. Essentially, the game engine (and Torque Script) has been extended to resemble a puppet and Python has been granted the role of puppeteer. So, from within Python we can create, delete and in general manipulate any Torque Script object and/or global variable.

So how do we actually do all this? ...

Hello World: PyExec and TGEPrint

In the wide world of programming, there is the venerable "Hello World" programs. These programs typically illustrate the simpliest and most basic functionality of the programming language in order to provide a learning path for teaching other programmers.

Let's look at the code for a Hello World example using Python and Torque Script.

from tgenative import TGEPrint

def PyExec():
    TGEPrint( "Python says: Hello World." )

If you copy and paste that code into a file and save that file into mud/client/helloWorld.py and then load up the game and type PyExec( "mud/client/helloWorld.py" ); into the ~ console you'll see the words "Python says: Hello World." printed out in the console.

Let's break down what just happened.

  1. We created a Python script and placed it somewhere accessible to the game engine. Iniside that script we loaded a module to provide us with a TGEPrint function and then defined a "PyExec" function that simply calls TGEPrint with a string.
  2. We loaded up the game, which in itself includes a Python interpreter. We opened up our ~ console and typed out the command: PyExec( "mud/client/helloWorld.py" );
  3. The game engine provides the PyExec function which first loads the file given and looks for a "PyExec" definition within that given file and once found, calls the function via the built-in Python interpreter. (Note that if that function definition does not exist, nothing would happen when loaded through the Torque Script PyExec.)
  4. Upon calling the PyExec function through the built-in Python interpreter, the TGEPrint call is made. TGEPrint( string ) in turn calls the Torque Script echo( string ); function to print out the string given.

This all looks like a lot of running around in circles with no benefit. Meaning, why not just echo( "Python says: Hello World." ); rather than run around all over the place. Well, this case is an example and not meant to be immediately useful but rather demonstrate some basics.

Hello World: TGEExport

Alrighty let's take a look at another version of the Hello World example.

from tgenative import TGEPrint
from mud.tgepython.console import TGEExport

def hello_world():
    TGEPrint( "Python says: Hello World." )

def PyExec():
    TGEExport( hello_world, None, "hello_world", "hello_world();", 1, 1 )

In this example we can see that we're importing an new function called TGEExport. This allows us to export a defined Python function (or method) into the world of Torque Script. As you can see, in the PyExec definition, we're exporting our hello_world() function. If you save that example and run it in the ~ console with PyExec, nothing visibly will happen, however, you'll now be able to run hello_world(); in the ~ console and then you'd see our lovely "Python says: Hello World." string.

So, let's take appart the TGEExport function call.

  1. The first argument is the actual Python definition of the function we're exporting.
  2. The second argument is the class or object we want to tie this function to (in which case it'd become a method). For this example, we're making a standard function so we put "None" as the class/object.
  3. Next up is the third argument which is the Torque Script function name we want to export our Python function as. This does not have to be the same as the Python definition but it typically is.
  4. The fourth argument is the description/help string of the function. All Torque Script functions have this so that if the function is used improperly, the end-user can be informed of how to correctly use it.
  5. The fifth argument is the minimum number of arguments required by our newly exported function. The lowest you can specify is 1 and this is interpreted as "no arguments required". So, when you call our hello_world(); function from Torque Script, you don't need to specify anything.
  6. The sixth argument is the maximum number of arguments required by our newly exported function. There is no real upper limit on how many arguments can be accepted, however, if you specify 1 (as we've done in the above example) you'll get an error stating that too many arguments were supplied to the hello_world(); function if you pass any to the function at all.

Hello World: TGEExport With Arguments

Alrighty! Let's look at another example which demonstrates how to pass arguments to our Python functions and how to read those arguments from within our Python function definition.

from tgenative import TGEPrint
from mud.tgepython.console import TGEExport

def argv_demo(argv):
    for id in range( 0, len(argv) ):
        TGEPrint( "argv_demo received: #%d -> %s" % ( id, argv[id] ) )

def PyExec():
    TGEExport( argv_demo, None, "argv_demo", "argv_demo( ... );", 1, 9 )

Now you can see a few differences right away. The first would be that the argv_demo definition requires one argument and the TGEExport call allows up to 9 arguments to be passed to the argv_demo function. So, if you were to PyExec this script like the previous examples and then execute argv_demo( "one", "two", "three", "four" ); from the ~ console you'd see the following output in the console window.

argv_demo received: #0 -> argv_demo
argv_demo received: #1 -> one
argv_demo received: #2 -> two
argv_demo received: #3 -> three
argv_demo received: #4 -> four

Wait a second... What the?! What is that first argument? "argv_demo"? ... Well, the first argument given to any function is the name of the function itself being called. That is actually useful however is also beyond the scope of this document.

Hello World: TGEExport Methods With Arguments

So, let's take a look at the previous example but let's just change one thing...

from tgenative import TGEPrint
from mud.tgepython.console import TGEExport

def argv_demo(argv):
    for id in range( 0, len(argv) ):
        TGEPrint( "argv_demo received: #%d -> %s" % ( id, argv[id] ) )

def PyExec():
    TGEExport( argv_demo, "GuiControl", "argv_demo", "argv_demo( ... );", 1, 9 )

The change we've made is that instead of "None" being the second argument to the TGEExport call, we've now put in "GuiControl". So, if we load things up again and try to execute the argv_demo(); as we did before, we'd get an error indicating that the function does not exist. Now, let's think about this for a second... in Torque Script, just about every GUI widget/element inherits from the GuiControl engine class. So what we've enabled is for just about every UI element to have the argv_demo function as a Torque Script method. Ok, let's see it in action... fire up the game, PyExec the file and then type optionsDlg.argv_demo( "one", "two", "three", "four" ); and let's see what we get...

argv_demo received: #0 -> argv_demo
argv_demo received: #1 -> optionsDlg
argv_demo received: #2 -> one
argv_demo received: #3 -> two
argv_demo received: #4 -> three
argv_demo received: #5 -> four

Wow, again some strangeness... that second argument... it's the object we ran argv_demo on. This allows us to do some interesting things with the object itself. Now that we've got it's name, we can fetch a reference to it and manipulate it as we see fit and all from within Python. Yay!

Hello World: TGEObject

Alrighty! Let's look at what we can do with the name of the object in Python...

from tgenative import TGEPrint, TGEObject
from mud.tgepython.console import TGEExport

def argv_demo(argv):
    for id in range( 0, len(argv) ):
        TGEPrint( "argv_demo received: #%d -> %s" % ( id, argv[id] ) )
    obj_name = argv[1]
    object = TGEObject( obj_name )
    TGEPrint( "argv_demo: %s is also know by Torque object id %s." % ( obj_name, object.getId() ) )

def PyExec():
    TGEExport( argv_demo, "GuiControl", "argv_demo", "argv_demo( ... );", 1, 9 )

Ok, so what's different here? Well, we know that the second argument will always be a reference to the object that this method is being called on so we tuck that away in a more conveniently named variable (obj_name) for the sake of clarity. Next up is the call to TGEObject(). It's pretty simple really. Just pass in the name (or id) of a Torque Script object and it'll return a Python object that wraps the Torque Script one. This Python object works in all the same ways as the actual Torque Script one. Take for example the line after our TGEObject() call, we are using the Torque Script getId() object method. The getId() function isn't actually declared anywhere in the Python sources. This right here is part of the real shining beauty of the system.

Alright, let's take a look at this code in action. If we fire up the game,PyExec our file and execute: optionsDlg.argv_demo( "one", "two", "three", "four" ); let's see what we get...

argv_demo received: #0 -> argv_demo
argv_demo received: #1 -> optionsDlg
argv_demo received: #2 -> one
argv_demo received: #3 -> two
argv_demo received: #4 -> three
argv_demo received: #5 -> four
argv_demo: optionsDlg is also know by Torque object id 4743.

Interesting. So our optionsDlg is the Torque object 4743 (in your case this number may very well be different, which is just fine and is exactly how Torque is supposed to work).

Let's backtrack for a second. The result of the object.getId() call in Python is a number but if you'll notice in the string it's being substituted as a string with %s (sprintf-style Python strings and they're usage are beyond the scope of this document, please see the Python Tutorial and general Documentation for more info). What we're seeing here is that all methods run on TGEObjects within Python will return strings as they're results. This is due to the fact that in Torque Script, everything (including numbers) are just plain old strings.

Ok! Back to the topic at hand... working with objects... let's try running that same command again but this time let's use the object id indicated in the output rather than the object's name. So, type in the following (changing the number for whatever id was given to your instance of the optionsDlg object): 4743.argv_demo( "one", "two", "three", "four" ); and let's see what we get...

argv_demo received: #0 -> argv_demo
argv_demo received: #1 -> 4743
argv_demo received: #2 -> one
argv_demo received: #3 -> two
argv_demo received: #4 -> three
argv_demo received: #5 -> four
argv_demo: 4743 is also know by Torque object id 4743.

Neato! Everything works exactly the same. So what we've learned is that whether it's an object id or an object by name, TGEObject() will work with what you give it.

Hello World: TGEGetGlobal and TGESetGlobal

Moving right along we now touch upon another set of functions imported from our loverly tgenative module; TGEGetGlobal() and TGESetGlobal(). These two functions are pretty simple. What they enable you to do is to get and set global Torque Script variables. With these two functions and a little Python glue it's quite possible to do something like obsoleting the traditional Torque Script prefs.cs system. Something as elaborate as that is beyond the scope of this document however, here's how you'd use these functions.

import from tgenative TGEGetGlobal, TGESetGlobal, TGEPrint

def PyExec():
    TGESetGlobal( "$this_is_a_test", "success" )
    result = TGEGetGlobal( "$this_is_a_test" )
    TGEPrint( "This test of setting and getting a global variable was a %s." % result )

Alrighty, nothing fancy. We set a global variable and then get it's value immediately after and print it on the console. Load up the game, PyExec the file and you should see the following printed in the console:

This test of setting and getting a global variable was a success.

Appendix: TGE Python Reference

The following is a listing of all the functions available to Python via the tgenative and mud.tgepython.console modules.

TGEPrint

Usage: TGEPrint( "string" )
Import from: tgenative
Description: Requires a single string argument and prints the string onto the console.

TGEExport

Usage: TGEExport( python_definition, "object_or_class", "torque_script_name", "help string", min_args, max_args )
Import from: mud.tgepython.console
Description: Requires five arguments and exports a Python definition as a Torque Script method or unbound function (depending on the value of the second argument). The arguments are described as follows:

  1. Python def name: The actual Python definition of the function we're exporting.
  2. string: The class or object we want to tie this function to (in which case it'd become a method). If you pass None, TGEExport will create an unbound Torque Script function rather than a class/object method.
  3. string: The Torque Script function name we want to export our Python function as. This does not have to be the same as the Python definition but it typically is.
  4. string: The description/help string of the function. All Torque Script functions have this so that if the function is used improperly, the end-user can be informed of how to correctly use it.
  5. integer: The minimum number of arguments required by our newly exported function. The lowest you can specify is 1 and this is interpreted as "no arguments required". So, when you call our hello_world(); function from Torque Script, you don't need to specify anything.
  6. integer: The maximum number of arguments required by our newly exported function. If you specify 1 you'll get an error stating that too many arguments were supplied if you pass any arguments to the function at all.

TGEObject

Usage: object = TGEObject( "torque_object_name_or_id" )
Import from: tgenative
Description: Requires one argument and returns a Python object tied to the actual Torque Script one. If you specify an object name or id that does not exist in Torque Script, the TGEObject call will raise an exception with something to the effect of "Unable to find TGEObject with name blah".

TGEGetGlobal

Usage: value = TGEGetGlobal( "$global_var_name" )
Import from: tgenative
Description: Requires a single argument and returns the value of the global Torque Script variable referenced. If the global variable specified does not in fact exist in Torque Script, Python's None is the value returned.

TGESetGlobal

Usage: TGESetGlobal( "$global_var_name", "some value" )
Import from: tgenative
Description: Requires two arguments and set's the global Torque Script variable specified as the first argument to the value of the second argument. Note that the second argument does not need to be a string.

TGECall

Usage: value = TGECall( "torque_script_function_name", ... )
Import from: tgenative
Description: Requires at least one argument which is the Torque Script function to call. Any further arguments specified are passed as arguments to the Torque Script function specified. The return value is whatever is returned from the Torque Script function. Note that this return value is always a string, if there's anything returned at all that is.

TGEEval

Usage: value = TGEEval( "torque_scripting" )
Import from: tgenative
Description: Requires one string argument and evaluates the string using the Torque Script engine. The return value is whatever is returned from the evaluation process (if anything at all). Again, all return values are in string form.

Final Notes

Please note that there is one particularly awesome feature that has been totally ignored with this document and that's the whole deal of the SimObject in Python. Most likely there will be a whole separate document on just that topic alone as the power within that is immense.