Event and Command Handlers - by Dr. Mike 9/30/2004
##############################################
A new mini tutorial, prompted by a friend here:
EVENTS IN FREEDOM FORCE
by Dr Mike
Pyhton code often appears disconnected, as various events are set up and handled elsewhere.
This covers the basics of handling such events.
BUILT_IN HANDLERS
def OnPostInit():
...
This is always called at the start of a mission. Everything else should spring from here.
def OnMissionWon():
Called when a mission is won. This should be the only place where you put Campaign_ commands, eg adding prestige or XP to characters,
or recruiting them.
-------------------------------------<>---------------------------------------------------
CUSTOM ACTIONS
A custom action gets handled by a function with two parameters, which are the object names of the
used object (the one clicked on) and the user (the hero who triggers the action).
Mission_CustomAction(actionName, heroFilter, objFilter, funcName, radius, oneShot)
heroFilter can be the object name of a hero (eg. if you have a hero called 'hero_1' in your level with
the template 'minute_man', then this should be 'hero_1'.
Leave it empty i.e. '', and all heroes get the action on their menu.
The objFilter can be either the name of a specific object or an object template, in which case the action
appears on all templates. e.g. if you have three objects of template 'tree' called 'tree1','tree2','tree3'
and want to set an action for a hero on all of them, you can either use the template:
Mission_CustomAction('CUSTOM_TREECOMMAND',hero,'tree','OnUseTree',30,0)
or loop over all of them.
trees=('tree1','tree2','tree3')
for tree in trees:
Mission_CustomAction('CUSTOM_TREECOMMAND',hero,tree,'OnUseTree',30,0)
The second one is longer, but has an advantage - you can remove actions on an individual tree this way.
If you did the first case above, and then called
Mission_RemoveCustomAction('CUSTOM_TREECOMMAND',hero,'tree1')
It wouldn't work. Similarly:
Mission_CustomAction('CUSTOM_TREECOMMAND','','tree1','OnUseTree',30,0)
Mission_RemoveCustomAction('CUSTOM_TREECOMMAND','hero_1','tree1')
will not add the command for everyone except 'hero_1', although it appears that it might.
Think of it this way: internally there's a big list of custom actions with user and target names defined for them.
WHen you add a cutsom action it adds an entry to the list. When you remove one it looks for entries with exactly the
same filters and removes them. It doesn't know if 'hero_1' is part of the '' set defining all heroes, or that 'tree1'
is part of the set defined by the template 'tree'.
Back to
trees=('tree1','tree2','tree3')
I did this because getAll('tree') wont work. getAll and its cousins (defined in cshelper.py) use Mission_GetDynamicObjects,
which only returns characters, vehicles, projectiles, and any props currently undergoing physics from knockback.
The safe rule is to only use it for character templates.
Finally, the handler.
For the custom actions above, define a handler to be called as:
def OnUseTree(target,char):
target will be the object name of the object clicked on, char will be the object name of the character who did the action.
Say I have 'hero_1' who's of type 'minute_man' and 'hero_2' of type 'liberty_lad' and the three trees.
If Liberty Lad clicks on tree2, then target will be 'tree2', and char will be 'hero_2', even if I used the '' filter for heroes and the 'tree' filter by template for the targets when I set up the command.
----------------------------------<>-------------------------------------
REG FUNCTIONS AND EVENTS
A different kind of handler is used for the reg family of functions.
The event structure is detailed in the scripting guide:
object object filter as per registration
string string filter (or object name if class filter used)
float float filter
data extra internal float data
user optional user data
The meaning of these members of the event depends on the event used.
e.g. with regTimer, you can specify the values of user, object and string, as so:
delay=5
user=3
object='hero_1'
string='tree'
regTimer('timeFunction',delay,user,0,object,string)
or
regTimer('timeFunction',5,3,0,'hero_1','tree')
for short.
in 5 seconds (the delay variable passed in) the function get called, and you can retrieve these values as follows:
def timeFunction(event):
user=event.user
object=event.object
string=event.string
Trigger_Power(object,string,'default punch','',user)
-here causing the character 'hero_1' to punch the object called 'tree' REALLY hard! (user is being passed as an intensity to Trigger_Power, causing 3 levels of overpowering!)
The menaing of event.object and event.string vary from event type to event.
One of the best debugging tricks is just to print them out, Say I call
regProximityEnter('hero_1','tree',20,'OnNearTree')
I could write a handler to begin with that goes:
def OnNearTree(event):
print 'OnNearTree'
print event.object
print event.string
This leaves a clear indication of which is which (one is 'hero_1' and one is 'tree' but I cant remember which way round it goes)
in the log file, and I can check this, then write in the intended code and restart the level to test it fully.
While useful, this is in the wrong forum. It should be in scripting.
my bad...
perhaps a mod can move it to the proper location
JM