/** * A nice file to allow you to setup an object as being holdable. To deal * with this inheritable you only need to define the method held_this_item * if you wish to do anything when the item is held. * @author Pinkfish * @started Wed Feb 2 15:38:10 PST 2000 */ #include <move_failures.h> private int _my_limb; private nosave int _no_limbs; private object _holder; int held_this_item(int held, object holder, mixed arg); void set_no_limbs(int num); void create() { _no_limbs = 1; } /* create() */ /** @ignore yes */ mixed query_static_auto_load() { return ([ "no limbs" : _no_limbs ]); } /* query_static_auto_load() */ /** @ignore yes */ void init_static_arg( mapping arg ) { if (!arg) { return ; } if (arg["no limbs"]) { set_no_limbs(arg["no limbs"]); } } /* init_static_arg() */ /** @ignore yes */ mixed query_dynamic_auto_load() { return ([ "limb" : (_holder ? _my_limb : -1), "limbs used" : (_holder ? sizeof(find_member(this_object(), _holder->query_holding())) : 0) ]); } /* query_dynamic_auto_load() */ /** @ignore yes */ void init_dynamic_arg( mapping arg, mixed new_arg ) { if (!arg) { return ; } if (arg["limb"] != -1) { call_out( function( int pos, mapping arg, mixed new_arg ) { if ( environment() ) { environment()->set_hold(this_object(), pos, arg["limbs used"]); } held_this_item(2, environment(), new_arg); }, 0, arg["limb"], arg, new_arg); } } /* init_dynamic_arg() */ /** * This method is called by the inheritable when the object is change from * being held to unheld, or vica versa. This should be used to turn on * and off light sources and so on. The method will also be called with * a 2 if the object was held and we are doing an initialisation sequence. * @param held 1 if the item is held, 0 if not, 2 if held on init * @param holder this is person already holding it when removed, new holder when held * @param arg an argument use in the autoloading, passed into init_dynamic_arg * @return 1 if the hold/remove was successful */ int held_this_item(int held, object holder, mixed arg) { return 1; } /* held_this_item() */ /** * This method is called from the living object when we are held or * unheld. * @param ob the person holding us * @param limb the limb we are being held in */ int set_holder(object ob, int limb) { /* No!! We -unhold- items by setting ob to 0! */ if (ob && environment() != ob) { // Only allow us to hold things in our environment. return 0; } this_object()->remove_hide_invis( "concealed" ); if ( !ob || ob != _holder) { if (!held_this_item(0, _holder, 0)) { return 0; } } if (ob) { if (!held_this_item(1, ob, 0)) { return 0; } } _holder = ob; _my_limb = limb; return 1; } /* set_holder() */ /** * This method returns the current limb the object is being * held in. * @return the number limb the object is held in */ int query_my_limb() { return _my_limb; } /** * This method returns the number of limbs that the object uses. * @return the number of limbs the object uses when held */ int query_no_limbs() { return _no_limbs; } /** * This method sets the number of limbs the object uses when held. * @param num the number of limbs */ void set_no_limbs(int num) { if (num < 0) { return ; } _no_limbs = num; } /* set_no_limbs() */ /** * This method should be called by the upper level moves. The result * needs to be check, if it is not MOVE_OK then the move should be * stopped. * @param ob the object to move */ int move( mixed ob) { if ( ob != _holder && _holder ) { if ( !sizeof( _holder->set_unhold( this_object() ) ) ) { return MOVE_NO_UNHOLD; } } return MOVE_OK; } /* move() */ /** * This method returns the person who is holding the object. * @return the person holding the object * @ignore yes */ object query_wielded() { return _holder; } /** * This method returns the person who is holding the object. * @return the person holding the object */ object query_holder() { return _holder; } /** * This method deals with removing ourselves as a holder when dested. * @ignore yes */ void dest_me() { if (_holder) { _holder->set_unhold(this_object()); } } /* dest_me() */ /** * * Attempts to free up enough limbs for this_object to be held. If * items are dropped to make this possible, who is notified. If * enough limbs are freed, attempts to hold this_object. If the position * is undefined (ie: not specified) then it will try and choose a limb * by itself. * <p> * The return numbers are the limb numbers that were used by holding the * item. * <p> * hold_item: As designed by Tannah! * @param who The living object trying to hold this one. * @param pos the position to hold the item in * @return the an (int *) if successful or ({ }) if not enough limbs are freed */ varargs int *hold_item( object who, int pos ) { object ob; object *held_things; object *dropped_things = ({ }); int num_limbs; /* If a particular position is specified, put that position at * the front of the queueueue, continue from it to the end, then * start at the beginning */ if( !undefinedp( pos ) && pos != -1 ) { /* is the position number valid? */ if( pos < 0 || pos >= sizeof( who->query_holding() ) ) return ({}); /* is there already something in that hand that can't be put down? */ ob = who->query_holding()[ pos ]; if( ob ) { if( !sizeof( who->set_unhold( ob ) ) ) return ({}); else dropped_things += ({ ob }); } /* all is well...continue on */ held_things = who->query_holding()[pos..] + who->query_holding()[0..pos-1]; } /* Otherwise use the standard order */ else { held_things = who->query_holding(); pos = -1; } if (pos == -1) num_limbs = this_object()->query_no_limbs(); else num_limbs = 1; tell_creator( who, "FL: %d, NL: %d, ob: %O\n", who->query_free_limbs(), num_limbs, this_object() ); tell_creator( who, "Dropped things: %O\n", dropped_things ); /* Try to put down enough things to hold this object */ for( int i = 0; who->query_free_limbs() < num_limbs && i < sizeof( held_things ); i++ ) { tell_creator( who, "freeing limbs\n" ); ob = held_things[i]; //We stopped holding something if( ob && sizeof( who->set_unhold( ob ) ) ) dropped_things += ({ ob }); } /* Tell the player what he's put down: */ if ( sizeof( dropped_things ) ) tell_object( who, "You put down " + query_multiple_short( dropped_things ) + ".\n" ); /* Can he hold the item now? */ if( who->query_free_limbs() >= num_limbs ) { //Excellent! return who->set_hold( this_object(), pos, num_limbs ); } tell_object( who, "You can't free up enough limbs to use "+ this_object()->a_short() + ".\n" ); return ({ }); // Nope, he can't. } /* hold_item() */