HOOKS - A Tutorial by Lathander ------------------------------- Prototypes ---------- varargs mixed call_hooks (string tag, mixed kind, mixed start, array args...); void add_hook (string tag, function hook); void remove_hook (string tag, function hook); Headers ---------- inherit "/std/object/hooks"; #include <hooks.h> This is just going to be a quick run through the concept and use of hooks. I hope to make it clear, but if its not, let me know and I'll see if I can clarify it. After inheriting the hooks file, your object now contains a mapping of hooks. There can be as many hooks as you like. However, all of the hooks are grouped into sets with similar 'tag' names. The first step to setting up a hook is to establish what it will do in its local code. You do this by adding a call_hooks() function. In our example, we'll do a hook that modify's a player's strength. // Example Code in a player object. // This code does not really exist. int get_strength() { int strength; strength = 100; ... strength = call_hooks("modify_strength",HOOK_FILTER,0,strength); ... return strength; } In this example we're giving each function that has hooked the "modify_strength" tag in this object a chance to modify the player's strength. This gives us the power of letting other objects modify this object's strength, without them having to touch this object's code. Once a hook is in place, it rarely has to be changed. Whenever call_hooks() is called, it, in turn, calls every hook that has been put into this object with a particular tag. The second step is to insert the actual hook into the object. In this case, we'll have a set of Guantlets of Ogre Power which will insert a hook into a player to make them stronger when they wear it. Here's an example for a set of Gauntlets of Ogre Power. void eventWear() { ::eventWear(); environment(this())->add_hook("modify_strength", (: ogre_strength :)); message("event","You feel power course throu your muscles!\n",you()); } int ogre_strength(int strength) { return strength*11/10; } void eventRemove() { ::eventRemove(); environment( this() )-> remove_hook("modify_strength",(: ogre_strength :)); message("event","You suddenly feel wimpy.\n",you()); } Now, whenever the player puts on the Gauntlets, the add_hook() is called on them. The add_hook() links the tag "modify_strength" in the wearer with the function ogre_strength() in the gauntlets. Whenever the wearer's object executes a call_hooks() with the tag "modify_strength" then the ogre_strength() function will get called with the args specified in the call_hooks() function. Note that I called remove_hook() when the player took off the guantlets. Don't forget to remove the hook or you may get very strange results. mixed kind ---------- Now, the call_hooks() function is much more complicated than I made it first appear. The mixed kind parameter to call_hooks() is the key to that. Here's the possible values of kind, and a description of what they make call_hooks() do. HOOK_IGNORE - Calls all hooks, but call_hooks() always returns zero. HOOK_SUM - Calls all hooks and adds their return values. The return value of call_hooks() is the sum of the return values. HOOK_LAND - Calls the hooks in a random order. If *any* of the hooks returns a zero, then call_hooks() returns a zero. (Logical And) HOOK_LOR - Calls the hooks in a random order. If *any* of the hooks returns a one, then call_hooks() returns a one. (Logical Or) HOOK_FILTER - Calls all of the hooks in a random order. The first hook gets the regular args. For successive functions, however, the first argument is the return value of the previous hook. call_hooks() returns the value of the last hook. HOOK_YES_OR_NO - Calls all of the hooks in a random order. If any function returns a zero or a string, then call_hooks() returns that value and does not process any further hooks. If all hooks are processed without returning a zero or a string, then a one is returned. a string - 'kind' can also be a string. If it is a string, then the return value of the call_hooks() will be a string with all of the return values of all of the hooks concatenated. The value of 'kind' will act as a delimiter between strings. Return value if there are no hooks. ----------------------------------- If call_hooks() is called, but there are currently no hooks into that object with the given tag value, then the return value is the same as 'start'. In other words, start is the defult return value. 9/96 Lathander@Accursed Lands