/* Command to hold weapons. This _should_ be fairly simple, however it is */ /* complicated by dealing with 1. a variable number of limbs and 2. printing */ /* out all the appropriate holding/unholding/failing/suceeding messages. */ inherit COMMAND_BASE; int no_limbs( object *obs ){ int ret = 0; foreach( object ob in obs ) ret += ob->query_no_limbs(); return ret; } /* no_limbs() */ int cmd(object *obs, string str) { int num_limbs; // this players limb count int avail; // limbs available int old_avail; // old limbs available, used for sanity checking int reqd; // limbs required int i; // general counter int pos; // which limb position int success; // did we succeed int *used; // limbs used by set_hold or set_unhold object ob; object weapon; object *using; // limbs currently in use object *fails; // weapons we failed to hold object *unfails; // weapons we failed to unhold object *holds; // weapons we sucessfully held object *unholds; // weapons we successfully unheld object *holding; // the things we're already holding. object *tmp; // the things we won't try to hold. string *limbs; // limb names; string *hhands; // hands we successfully held weapons in string *uhands; // hands we successfully unheld weapons from tmp = ({ }); foreach( object wep in obs ){ if( !wep->query_no_limbs() ){ obs -= ({ wep }); tmp += ({ wep }); } } if( sizeof( tmp ) && !sizeof( obs ) ){ add_failed_mess(query_multiple_short( tmp ) +" can't be held.\n"); return 0; } else if( sizeof(tmp) ) write( query_multiple_short( tmp )+" can't be held, ignoring...\n"); if( !sizeof( obs ) ){ add_failed_mess("Hold what?\n"); return 0; } using = TP->query_holding(); holding = obs & ( using - ({ 0 }) ); obs -= holding; if( !sizeof(obs) ) { add_failed_mess("You are already holding $I.\n", holding ); return 0; } fails = filter( obs, (: ENV($1) != TP :) ); obs -= fails; if( !sizeof(obs) ) { add_failed_mess("$I "+({"is","are"})[query_group(fails)]+" not in " "your inventory, so you cannot hold "+({"it","them"}) [query_group(fails)]+".\n", fails ); return 0; } // calc how many hands will be needed limbs = TP->query_limbs(); num_limbs = sizeof(limbs); avail = TP->query_free_limbs(); fails = holds = unholds = hhands = uhands = unfails = ({ }); // deal with specific hands first if( str && obs[0] ) { if( obs[0]->query_no_limbs() > 1 ) { add_failed_mess("That weapon requires more than one hand!\n"); return 0; } if( ( pos = member_array(str, limbs) ) == -1 ) { if( !sizeof(limbs) ) { add_failed_mess("You seem to have a singular lack of limbs.\n"); return 0; } add_failed_mess("Incorrect limb type, must be one of "+ query_multiple_short(limbs)+".\n"); return 0; } // clear the appropriate hand if (using[pos]) { used = TP->set_unhold(using[pos]); if (!sizeof(used)) { /* This means we cannot hold the object for sure. */ unfails += ({ using[pos] }); uhands += ({ limbs[pos] }); } else { for (i=0;i<sizeof(used) && i<sizeof(limbs);i++) { uhands += ({ limbs[used[i]] }); } unholds += ({ using[pos] }); } } if (!sizeof(unfails)) { // hold in the appropriate hand used = TP->set_hold(obs[0], pos); if (!sizeof(used)) { fails += ({ obs[0] }); } else { for (i=0;i<sizeof(used) && i<sizeof(limbs);i++) { hhands += ({ limbs[used[i]] }); } holds += ({ obs[0] }); success = 1; } } } else { // now deal with normal holding foreach(ob in obs) { reqd += ob->query_no_limbs(); } if (reqd > num_limbs) { tmp = ({ }); while( no_limbs( obs ) > num_limbs ){ tmp += ({ obs[sizeof( obs )-1] }); obs -= ({ obs[sizeof( obs )-1] }); } write( "Can't hold everything, ignoring "+ query_multiple_short( tmp )+".\n"); } old_avail = -1; // if necessary put down items until the required hands are available // No need for a while, if it cannot be done. It cannot be done. // If nothign was able to be put down after one sweep through, we are // out of luck. while ((avail < reqd) && (avail < num_limbs)) { if ((reqd > num_limbs - sizeof(unfails)) || (old_avail == avail)) { if (sizeof(unfails)) { add_failed_mess("You do not have enough limbs to hold $I, since " + query_multiple_short(unfails) + " failed " "to unhold.\n", obs); } else { add_failed_mess("Not able to free up enough limbs to hold $I.\n", obs); } return 0; } old_avail = avail; using = TP->query_holding(); for (i = 0; i < sizeof(using); i++) { weapon = using[i]; if(weapon) { used = TP->set_unhold(weapon); if (sizeof(used)) { for (i=0; i < sizeof(used) && used[i] < sizeof(limbs); i++) { uhands += ({ limbs[used[i]] }); } unholds += ({ weapon }); avail = TP->query_free_limbs(); break; } else { if (member_array(weapon, unfails) == -1) { unfails += ({ weapon }); } uhands += ({ limbs[i] }); } } } } if (!sizeof(unfails)) { // now try holding the new items foreach(ob in obs) { using = TP->query_holding(); pos = 0; if(!ob->query_no_limbs() || avail < ob->query_no_limbs()) { fails += ({ ob }); break; } // hold the new items while((using[pos]) && (pos < num_limbs)) { pos++; } used = TP->set_hold(ob, pos); if(used == ({ })) { fails += ({ ob }); } else { for (i=0;i<sizeof(used) && i<sizeof(limbs);i++) { hhands += ({ limbs[used[i]] }); } holds += ({ ob }); success = 1; avail = TP->query_free_limbs(); } } } } if( sizeof(holding) && !sizeof(holds) ) write( "You are already holding "+query_multiple_short(holding)+".\n" ); if( sizeof(unfails) ) { write( TP, "You fail to put down "+query_multiple_short(unfails)+ " from your "+query_multiple_short(uhands)+".\n"); say( TP->one_short()+" fails to put down "+ query_multiple_short(unholds)+" from "+ TP->query_possessive()+" "+query_multiple_short(uhands)+".\n"); } if( sizeof(unholds) ) { write( "You put down "+query_multiple_short(unholds)+" from your "+ query_multiple_short(uhands)+".\n"); say( TP->one_short()+" puts down "+query_multiple_short(unholds)+ " from "+TP->query_possessive()+" "+ query_multiple_short(uhands)+".\n"); } if( sizeof(holds) ) { write( "You hold "+query_multiple_short(holds)+" in your "+ query_multiple_short(hhands)+".\n"); say( TP->one_short()+" holds "+query_multiple_short(holds)+ " in "+TP->query_possessive()+" "+ query_multiple_short(hhands)+".\n"); } // don't print the failed to hold messages if we managed to hold stuff. if( !success && sizeof(fails) ) { write( "You fail to hold "+query_multiple_short(fails)+".\n"); say( TP->one_short()+" fails to hold "+ query_multiple_short(fails)+".\n"); } // We don't add a succeeded mess at all, this will break things when // certain objects call cmd() directly. return 1; } /* cmd() */ mixed *query_patterns() { return ({ "<indirect:object:me>",(: cmd($1,0 ) :), "<indirect:object:me> in [my] {" + implode( TP->query_limbs(), "|") + "}", (: cmd( $1,implode( $4[1..], " ")) :) }); } /* query_patterns() */