Geas MUD, enter the Aventure!
Geas Home | Play the Game

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 Masking functions in runtime, part 2

The idea with the shadow functionality is to mask one or more functions in a target object with others having the same name in a shadow object The purpose of this procedure is usually to modify the behaviour of the target object in some way.

Shadows are tricky in the respect that they are managed in runtime and not during compile time. This means that not only may shadows fail for various reasons which I'll go in to later, but they also unintentionally may cause the target object to stop working.

The basic rule is not to use shadows unless you really have to; they often are more trouble than they are worth. With that dire warning in mind, let us go on to the subject of creating and using them.

This in turn means that all functions in the shadowing object either has to be unique to the object itself, or be shadowable in the target object. Now, shadowing isn't completely without conditions:

There's a few consequences of the above that are worth remembering. As you already know, any object you want to bring into the game proper has to be a derivate of the /std/object.c object. If you create an object without inheriting /std/object.c or one of its derivates, that object can never be inserted in to the inventory of any other object, which in turn means that it never can appear in the game. Since the /std/object.c object contains a number of unmaskable functions, this means that a shadow as such never can be inserted into the game. Well, unless it inherits /std/object.c itself, and only shadows some kind of non-insertable object, of course. I suppose that this isn't impossible as such, just rather unlikely.

Assume that an object has been shadowed by several objects, and that the same function is shadowed in all objects, which shadow finally gets the call? This is not an impossible situation if you're thinking that I'm posing a trick question; since you're not shadowing a shadow, but the original object, and since the function is shadowable there's no preventing this from happening. The answer is that it's the last function to shadow the object that 'wins'. Obviously this is not a very good situation, so often the best way of making sure that your object is the only final object to shadow another is to define the function query_prevent_shadow() to return 1. However, this obviously makes it impossible for all other objects to shadow any other function as well, so one has to be careful lest one interrupts some other object from working.

By far the easiest way of creating a working shadow object is to inherit the standard shadow object /std/shadow.c and use the functionality provided there. With that module you're not only getting a standardized way of dealing with shadows that most other object-managing objects recognize and can use, you're also getting a number of handy functions that make sure that the shadow doesn't shadow the same object twice by mistake, that autoloading shadows on players automatically latch on to the player on login again as well as provide a mechanism for removing the shadow.

Assume for example that you want to redefine the gender of a player who's been affected by an evil spell of some kind. The function you want to shadow is called query_gender_string() and can be found in /std/living/gender.c. This is how you do it:

 
inherit "/std/shadow";

int
start(string pl_name)
{
    return(objectp(shadow_me(pl_name)));
}

int
stop()
{
    remove_shadow();
}

string
query_gender_string()
{
    return "xxx";
}

Please notice that I've added both a start and a stop function for easy testing; these really aren't necessary as long as the shadow somehow calls shadow_me() with the target (either as a name or an object reference) as argument.

The standard shadow module also provides easy access to the original object. The variable shadow_who is set to the original object, so in the shadow object any call on the form shadow_who->function() goes to the original object function, even if it is shadowed in the shadow object.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated by Ronny Wikh on July, 8 2003 using texi2html