#include <obj_parser.h>
#include <move_failures.h>
// These were determined empirically (with my hand :) -- Jeremy
#define DROP_H 40
#define PINCH_H 120
#define MAX_GET_NUMBER 20
inherit COMMAND_BASE;
mixed cmd( object *obs, string dir, string indir, mixed *args ) {
object *dest;
object ob;
object dob;
object *fail_dest;
object *too_many;
mixed *fail;
mixed *ret;
mixed *stuff;
mixed amt;
string sh;
string hand_unit;
string match_str;
int i;
int num;
int cap;
int perc;
int handful;
int total_num;
mixed we;
object env;
object *bing;
class obj_match result;
if( indir && sizeof(obs) > 10 ) {
add_failed_mess("Please be more specific as to what you want "
"to get from.\n");
return 0;
}
if( indir ) {
match_str = args[0];
dest = obs;
} else {
dest = ( ENV(TP)->query_mirror_room() ?
({ ENV(TP), ENV(TP)->query_mirror_room() }) : ({ ENV(TP) }) );
}
cap = (int)TP->query_max_weight();
fail_dest = ({ });
too_many = ({ });
foreach( dob in dest ) {
if( !is_in_me_or_environment( dob, TP ) )
continue;
if( dob->cannot_get_stuff() || dob->query_closed() || living(dob) ) {
fail_dest += ({ dob });
continue;
}
// Containers only.
if( indir ) {
result = match_objects_in_environments( match_str, dob );
if( result->result != OBJ_PARSER_SUCCESS ) {
add_failed_mess( match_objects_failed_mess( result ) );
continue;
}
obs = result->objects;
}
// Containers only.
if( living(dob) && !dob->allowed_to_loot(TP) ) {
// Do basically the same check here as is done in the
// match_objects_for_existence code.
obs = filter( obs, (:
$(dob)->can_find_match_reference_inside_object( $1, TP ) :) );
obs = filter( obs, (: member_array( $1,
$(dob)->query_holding() ) == -1 :) );
if( !sizeof(obs) ) {
fail_dest += ({ dob });
continue;
}
}
if( total_num + sizeof(obs) > MAX_GET_NUMBER ) {
if( total_num > MAX_GET_NUMBER ) {
too_many += obs;
obs = ({ });
} else {
too_many += obs[MAX_GET_NUMBER - total_num..];
obs = obs[0..MAX_GET_NUMBER - total_num - 1];
}
}
total_num += sizeof(obs);
ret = ({ ([ ]), ([ ]), ([ ]), ([ ]), ([ ]), });
fail = ({ });
foreach( ob in obs ) {
if( ( living(dob) && !dob->allowed_to_loot( TP, ob ) ) ||
( ob->query_liquid() && ob->query_food_object() ) ||
( ENV(ob) && living( ENV(ob) ) ) ) {
fail += ({ ob });
num++;
continue;
}
if( ob->query_continuous() ) {
amt = ob->query_amount_types();
if( amt["handful"] ) {
hand_unit = "handful";
handful = amt["handful"][0];
} else if( amt["drop"] && ob->query_liquid() ) {
hand_unit = "drops";
handful = amt["drop"][0] * DROP_H;
} else if( amt["pinch"] ) {
hand_unit = "pinches";
handful = amt["pinch"][0] * PINCH_H;
} else { // Dunno what to do here - I guess give it to them.
handful = ob->query_amount();
}
if( ob->query_amount() > handful ) {
// Knock it down to a carryable amount.
// (I hope this is right...)
if( !match_str )
match_str = ob->query_name();
if( i = strsrch( match_str, "of" ) >= 0 )
i += 3;
if( hand_unit == "handful" )
handful = 1;
match_str = handful+" "+hand_unit+" of "+match_str[i..];
if( !ob = ob->query_parse_id(({ handful, match_str })) )
continue;
}
}
env = ENV(ob);
if( function_exists("do_get", ob ) ||
function_exists("command_control", ob ) ) {
if( function_exists("do_get", ob ) ) {
we = (int)call_other( ob, "do_get", dob, 0, match_str,
({ 0, match_str }),
"<direct:object> from <indirect:object>");
} else {
we = ob->command_control("get", dob, 0, match_str,
({ 0, match_str }),
"<direct:object> from <indirect:object>");
}
if( !objectp(we) ) {
if( we ) {
we = (int)ob->query_weight();
perc = ( we * 100 ) / cap;
i = ( perc >= 95 ? 4 : perc / 25 );
if( !ret[i][env] )
ret[i][env] = ({ ob });
else
ret[i][env] += ({ ob });
} else {
if( member_array( ob,
TP->query_succ_mess_indir() ) == -1 &&
!query_notify_fail() && !living(ob) ) {
fail += ({ ob });
}
num++;
}
continue;
} else {
ob = we;
}
}
if( (int)ob->move(TP) == MOVE_OK ) {
we = (int)ob->query_weight();
perc = ( we * 100 ) / cap;
i = ( perc >= 95 ? 4 : perc / 25 );
if( !ret[i][env] )
ret[i][env] = ({ ob });
else
ret[i][env] += ({ ob });
if( interactive(TP) && ob->query_property("dropped") ) {
stuff = ob->query_property("dropped");
if( TP->query_name() != stuff[0] &&
query_ip_number(TP) == stuff[1] &&
sizeof( (HANDLER_DIR+"/multiplayer")->
check_allowed( TP, ({ stuff[0] }) ) ) ) {
sh = TP->query_cap_name()+" got "+
ob->query_short()+" from "+stuff[0]+" who "
"logged in from the same IP address.";
user_event("inform", sh, "multiplayer");
log_file("MULTIPLAYERS", ctime(time())+": "+
TP->convert_message(sh)+"\n");
} else if( TP->query_name() == stuff[0] &&
TP->query_refresh_time() > stuff[2] ) {
sh = TP->query_cap_name()+" picked up "+
TP->HIS+" equipment after a refresh.";
user_event("inform", sh, "multiplayer");
log_file("MULTIPLAYERS", ctime(time())+": "+
TP->convert_message(sh));
}
}
} else {
fail += ({ ob });
num++;
}
}
/* Print out the different weight messages */
for( i = 0; i < sizeof(ret); i++ ) {
if( sizeof(ret[i]) ) {
/* Print out the different environments for the weights. */
foreach( env, bing in ret[i] ) {
if( TP->query_succ_mess_dir() )
bing -= TP->query_succ_mess_dir();
if( sizeof(bing) ) {
sh = query_multiple_short(bing);
write("You "+({"get", "get with a bit of difficulty",
"struggle somewhat to get", "find it very "
"difficult to get", "use all your strength and "
"just barely manage to get"})[i]+" "+sh+" from "+
inside_the_short(env)+".\n" );
say( (string)TP->one_short()+" "+({ "gets", "gets "
"with a bit of difficulty", "struggles somewhat "
"to get", "finds it very difficult to get",
"uses all "+TP->HIS+" strength and just barely "
"manages to get" })[i]+" "+sh+" from "+
inside_a_short(env)+".\n");
}
}
}
}
if( sizeof(fail) )
add_failed_mess("You cannot get $I.\n", fail );
}
// This means everything failed.
if( num == total_num ) {
if( query_notify_fail() )
return 0;
if( indir ) {
if( !num )
add_failed_mess("There is no "+match_str+" in $I.\n", dest );
if( sizeof(fail_dest) )
add_failed_mess("You cannot get anything from $I.\n", fail_dest );
}
return -1;
} else {
// Success!
if( sizeof(too_many) ) {
add_succeeded_mess( ({ "You cannot pick up more than "+
query_num(MAX_GET_NUMBER)+" objects at a time; "
"discarding $I.\n", "" }), too_many );
}
}
return 1;
} /* cmd() */
/** @ignore yes */
mixed query_patterns() {
return ({
"<indirect:object:here>", (: cmd( $1, 0, 0, 0 ) :),
"<string> from <indirect:object>", (: cmd($1, $2, $3, $4) :),
});
} /* query_patterns() */