@create #18181 named Slither's Feature Object:Slither's Feature Object,sfo
@prop #62557."rakshasa" #60388 r
"#62557.("usage") => E_PERM (Permission denied)
;;#62557.("users") = {#121188, #121865, #109911, #121895, #106468, #121918, #121816, #121931, #121976, #121965, #121852, #115805, #116276, #122047, #121386, #48961, #114701, #114072, #106189, #120045, #122104, #122359, #119265, #122354, #122410, #110582, #122428, #122423, #118977, #42395, #122453, #122460, #122491, #122525, #122614, #122644}
;;#62557.("help_msg") = {"This feature object contains a couple of commands to tell you the", "weight of things in the RPG.  More commands might be added to it in", "the future.  Any comments and suggestions are welcome, and should be sent", "to Slither.", "Two notes about weights are probably appropriate.  Firstly, there are", "objects in the game that weigh different amounts depending on who is carrying", "them.  This commands give you the weights that apply to YOU.  Secondly,", "the RPG calculates weights slightly differently than these commands -- this", "is because the RPG's calculation is more expensive, and (I think) buggy,", "but be warned.", "   -- Slither"}
;;#62557.("feature_verbs") = {"weigh", "weights", "@trainable", "@read-scrolls", "loc", "@rak"}
;;#62557.("guest_ok") = 1
"#62557.("key") => E_PERM (Permission denied)
;;#62557.("aliases") = {"Slither's Feature Object", "sfo"}
;;#62557.("description") = "This feature currently contains a couple verbs to show the weights of things in the RPG game (so you can tell WHY you are overloaded).  Send comments and suggestions to Slither."
;;#62557.("object_size") = {10543, 1141286888}

@verb #62557:"weights" none none none rxd
@program #62557:weights
"`weights` prints out a list of all your items, and how much they weigh.";
"If one of your objects contains others, the contents will also be";
"printed, indented.";
this:update_usage(verb, player);
if (!valid(doll = $local.rpg:get_doll(player)))
  player:tell("Sorry, you aren't in the RPG, so this command can't work.");
endif
if (player.contents)
  output = this:weights_help(player, 0, doll);
  player:tell("Inventory, with weights:");
  player:tell_lines(output[2]);
  player:tell("");
  player:tell("Total weight: " + tostr(output[1]));
else
  player:tell("You have no inventory");
endif
.

@verb #62557:"weights_help" this none this
@program #62557:weights_help
total = 0;
item = args[1];
indent = args[2];
doll = args[3];
output = {};
for i in (item.contents)
  if (i.contents)
    subitemresults = this:weights_help(i, indent + 2, doll);
  else
    subitemresults = {0, {}};
  endif
  if ($object_utils:isa(i, #517))
    subitemresults[1] = subitemresults[1] + i:encumbrance(doll);
  endif
  total = total + subitemresults[1];
  output = {@output, ($string_utils:space(indent) + $string_utils:left(subitemresults[1] ? tostr(subitemresults[1]) | "  ", 4)) + i.name, @subitemresults[2]};
endfor
return {total, output};
.

@verb #62557:"weigh load" any none none rxd
@program #62557:weigh
"This command returns either the weight of a RPG object, or the weights";
"of all the objects that the player is carrying.";
"`weigh <item>` returns the weight of that item.";
"`weigh` or `weigh me` returns the weights of all carried objects";
"This command also goes by the name `load`, to avoid conflict with another";
"feature object.";
this:update_usage(verb, player);
doll = $local.rpg:get_doll(player);
if (!valid(doll))
  player:tell("Sorry, you aren't in the RPG, and so weights can't be calculated.");
  return;
endif
if ((dobj == player) || (dobj == $nothing))
  "do player inventory";
  player:tell("Weights of your objects:");
  player:tell_lines($list_utils:map_arg(this, "calc_weight_str", player.contents, doll));
elseif (dobj == $ambiguous_match)
  player:tell(("Sorry, there are several things named '" + dobjstr) + "' around.");
elseif (dobj == $failed_match)
  player:tell(("Sorry, there is no object named '" + dobjstr) + "' around.");
else
  if ($object_utils:isa(dobj, #517))
    "do object inventory";
    total = 0;
    for i in ($list_utils:map_arg(this, "calc_weight_num", {dobj, @$object_utils:all_contents(dobj)}, doll))
      total = total + i;
    endfor
    player:tell(((("The " + dobj.name) + " weighs ") + tostr(total)) + " units.");
  else
    player:tell("Sorry, that is not an RPG item.");
  endif
endif
.

@verb #62557:"calc_weight_num" this none this
@program #62557:calc_weight_num
"This is a helping function.  It returns the weight of args[1] using the doll";
"which should be passed as args[2]";
item = args[1];
if ($object_utils:isa(item, #517))
  return item:encumbrance(args[2]);
else
  return 0;
endif
.

@verb #62557:"calc_weight_str" this none this
@program #62557:calc_weight_str
"This is a helping function.  It returns a string with the weight and the";
"name of the object args[1], using the doll which should be args[2]";
item = args[1];
doll = args[2];
if ($object_utils:isa(item, #517))
  return ($string_utils:right(tostr(item:encumbrance(doll)), 3) + " ") + item.name;
else
  return " -- " + item.name;
endif
.

@verb #62557:"@trainable" any none none rxd
@program #62557:@trainable
"Usage:  @trainable [player]";
"This command returns the list of RPG stats that the given player";
"(or you, if no player is given) is able to successfully train at";
"the academy.  You may only see this information for another player";
"if you are a GM.";
this:update_usage(verb, player);
if (!$local.rpg:trusted(player))
  player:tell("Mirror, mirror, in the hall, what stats are trainable... if any at all?");
  return;
endif
person = (valid(dobj) && is_player(dobj)) ? dobj | (dobjstr ? $string_utils:match_player(dobjstr) | player);
if (!valid(person))
  player:tell("Sorry, can't find anyone with that name.");
  return;
endif
if ((player != person) && (!$local.rpg:trusted(player)))
  player:tell("Sorry, only GMs can get info about other people.");
  return;
endif
doll = $local.rpg:get_doll(person);
if (!valid(doll))
  player:tell("Sorry, that person isn't in the RPG.");
  return;
endif
"Finally, we get to do something!";
pot = this:get_att("pot", doll);
trainable = {};
allskills = {{"Str", "Strength"}, {"End", "Endurance"}, {"Dex", "Dexterity"}, {"Agl", "Agility"}, {"Int", "Intelligence"}, {"Emp", "Empathy"}, {"Wil", "Willpower"}, {"Pcn", "Perception"}, {"App", "Appearance"}};
for skill in (allskills)
  if ($local.rpg.costs[min(this:get_att(skill[1], doll), 25) + 1] <= pot)
    trainable = {@trainable, skill[2]};
  endif
endfor
if (trainable)
  player:tell($string_utils:pronoun_sub(("%N is currently able to train the stats " + $string_utils:english_list(trainable, "", " or ")) + ".", person));
else
  player:tell($string_utils:pronoun_sub("%N is not able to train any stats at the moment.", person));
endif
.

@verb #62557:"get_att" this none this
@program #62557:get_att
if (caller != this)
  return E_PERM;
endif
return args[2]:get_unmod_att(args[1]);
.

@verb #62557:"ms loc ml" any none none rxd
@program #62557:ms
"This verb returns information on the location and health of a particular monster.";
critters = $match_utils:match_list(dobjstr, $local.rpg.vacuum.monsters);
if ((dobjstr && ((theobj = toobj(dobjstr)) != #0)) && (theobj in $local.rpg.vacuum.monsters))
  critters = setadd(critters, theobj);
endif
if (!critters)
  player:tell("No RPG monster found matching \"", dobjstr, "\".");
  return;
elseif (length(critters) > 1)
  player:tell("There is more than one RPG monster matching \"", dobjstr, "\": ", $string_utils:nn(critters), ".");
else
  player:tell($string_utils:nn(c = critters[1], ""));
  c:look_health();
  $local.rpg:look_gear(c);
  $local.rpg:look_encumbrance(c);
  player:tell(c.psc, " is ", c.alive ? "currently at " + $string_utils:nn(c.location) | "** DEAD **");
endif
.

@verb #62557:"@rak @rrak" none none none rxd
@program #62557:@rak
"This verb shows the location and current disguise of the rakshasas.";
"I'm really against this verb, but it is still on Krystia's mostly broken FO";
"and people have their own copies anyway, so here it is in the interest";
"of getting the bad FO out of circulation.";
for target in (children(this.rakshasa))
  for subtarg in (children(target))
    player:tell(#20:left(target.name, 6), " is disguised as ", subtarg.name, " (", subtarg, ") at ", valid(subtarg.location) ? subtarg.location.name | "Nowhere", " (", subtarg.location, ").");
  endfor
endfor
.

"***finished***