@create #18181 named RPG info FO:RPG info FO
@prop #55248."other_people" {} rc
;;#55248.("other_people") = {#109723, #101111, #106308, #101711}
@prop #55248."words" {} r
;;#55248.("words") = {{"minimal", "very low", "low", "moderate", "high", "very high", "incredible"}, {"none", "poor", "moderate", "good", "excellent", "complete"}, {"none", "low", "moderate", "high", "very high"}, {"very fast", "fast", "medium", "slow", "very slow"}, {"complete", "excellent", "good", "moderate", "poor", "lousy"}}
@prop #55248."armour_data" {} r
;;#55248.("armour_data") = {{"protection", "Protection", 0, {3, 0, 4, 10, 20}}, {"absorption", "Absorption", 0, {2, 1, 2, 3, 4, 6}}, {"leather", "Type", "Leather/Metallic", "Leather/Metallic"}, {"condition", "Condition", 0, 0}, {"encumbrance", "Weight", 0, 0}}
@prop #55248."weapon_data" {} rc
;;#55248.("weapon_data") = {{"encumbrance", "Weight", 0, 0}, {"condition", "Condition", 0, 0}, {"length", "Length", 0, 0}, {"slowness", "Slowness", 0, {4, 5, 9, 13, 18}}, {"hands", "Hands", 0, 0}, {"dam", "Damage", 0, {1, 7, 12, 17, 22, 26, 32}}, {"max_str_bonus", "Strength Bonus", 0, {1, 4, 8, 15, 23, 30, 40}}, {"pen", "Penetration", 0, {5, 4, 8, 14, 22, 28}}, {"con", "Concussion", 0, {5, 1, 2, 3, 5, 8}}, {"pierce", "Pierce", 0, {3, -5, -2, 2, 5}}, {"attack", "Attack", 0, {1, -30, -15, -5, 5, 15, 25}}, {"parry", "Parry", 0, {1, -50, -20, -5, 10, 30, 70}}, {"dodgable", "Dodgable", 0, {1, -50, -20, -5, 5, 15, 40}}, {"parryable", "Parryable", 0, {1, -50, -20, -5, 5, 15, 40}}, {"special_damage", "Special Damage", 0, "Yes/No"}, {"wooden", "Wooden", "Yes/No", "Yes/No"}, {"blunt", "Blunt", "Yes/No", "Yes/No"}, {"skill", "Skill", 0, 0}}
@prop #55248."bracers" #58725 rc
@prop #55248."squat" #8185 rc
@prop #55248."fo" #88922 rc
"#55248.("usage") => E_PERM (Permission denied)
;;#55248.("users") = {#2693, #21077, #31829, #37972, #38441, #47818, #50290, #58026, #58091, #59447, #62713, #63625, #69513, #71111, #71781, #78041, #82267, #85077, #85431, #86275, #87010, #88076, #89391, #90323, #90331, #91098, #93228, #94368, #94456, #96788, #97170, #97613, #98263, #98325, #99949, #100314, #100674, #100806, #102292, #103158, #103523, #103615, #103911, #103920, #104202, #104417, #104762, #105159, #105941, #106308, #106469, #106487, #106488, #106854, #106938, #107509, #107629, #107682, #107730, #108140, #108147, #108294, #108850, #109048, #109567, #109600, #109723, #110199, #110215, #110565, #112651, #112743, #112823, #112968, #100173, #108263, #72264, #109030, #112997, #113549, #101594, #113588, #112527, #64729, #59254, #113803, #113862, #106541, #113391, #81934, #113937, #109506, #87951, #98232, #113841, #111023, #89395, #114382, #101651, #101504, #112837, #103689, #110586, #114019, #103703, #114702, #114518, #56568, #113418, #112478, #113800, #108108, #110805, #115109, #105473, #113235, #106273, #98705, #114874, #113955, #91113, #115359, #114928, #115342, #105539, #112190, #113956, #92475, #114774, #107610, #87340, #107413, #115124, #107807, #80422, #108590, #114859, #116200, #64985, #110077, #113686, #57658, #116385, #115381, #87593, #116358, #116342, #116339, #116031, #116369, #107998, #91798, #107189, #107985, #114652, #116694, #115432, #116729, #115595, #116473, #88395, #115937, #116886, #115200, #115922, #64299, #117236, #117139, #116305, #117283, #109546, #117389, #117381, #112886, #117470, #117004, #117552, #117048, #109271, #58806, #77500, #43860, #116601, #114430, #116883, #12399, #87146, #90731, #96778, #118143, #117486, #50367, #92476, #118362, #90723, #116875, #118526, #115397, #118248, #94965, #109395, #118720, #118328, #89455, #35076, #117766, #118487, #118672, #118864, #118890, #118654, #117345, #118973, #118740, #117038, #118034, #112529, #114413, #119269, #59424, #119177, #86050, #103685, #118018, #118153, #119429, #109615, #119469, #112473, #30788, #117837, #88098, #118948, #115729, #86197, #119554, #116580, #65101, #115366, #112971, #118985, #115390, #87760, #119257, #119116, #111890, #119884, #111987, #119940, #119957, #107618, #119958, #119492, #120046, #114174, #118360, #115834, #119594, #120227, #118730, #118861, #120260, #120144, #120239, #120283, #114206, #119899, #117100, #120420, #118824, #116376, #120376, #120546, #109288, #120070, #120749, #119906, #105408, #57402, #78837, #120783, #114670, #120997, #121000, #121077, #121095, #121070, #120201, #121104, #121149, #121164, #121241, #121383, #121332, #114539, #120791, #121456, #121464, #113754, #120804, #121358, #121648, #121651, #87625, #121758, #121188, #121865, #109911, #121895, #106468, #121918, #121816, #121976, #121965, #121852, #115805, #122047, #122205, #121386, #48961, #114072, #122104, #122359, #119265, #122354, #122379, #122410, #110582, #122428, #106189, #122423, #118977, #42395, #122453, #122460, #122491, #102427, #100752, #122485, #121946, #122525, #122644}
;;#55248.("users_last_updated") = 938327628
;;#55248.("help_msg") = "A feature object that can help LRPG players analyze and compare RPG equipment or opponents.  @irin was originally written by Irin and @ri was added by Hannibal."
;;#55248.("feature_verbs") = {"@irin", "@ri"}
;;#55248.("guest_ok") = 1
"#55248.("key") => E_PERM (Permission denied)
;;#55248.("aliases") = {"RPG info FO"}
;;#55248.("description") = "A FO that helps analyze RPG objects."
;;#55248.("object_size") = {19030, 1141286957}

@verb #55248:"@info*rmation @stat @data @whatever @irin" any none none rxd
@program #55248:@information
"@info/@stat/@data/@whatever <weapon/armour/creature>   Returns verbal ratings of equipment.";
if (caller != player)
  return E_PERM;
elseif (!argstr)
  return player:tell("Usage:  @info/@stat/@data/@whatever  <weapon/armour/creature>");
endif
this:update_usage(verb, player);
su = $string_utils;
rpg = $local.rpg;
thing = dobj;
if (!valid(thing))
  thing = $match_utils:match(dobjstr, {@player.contents, @player.location.contents});
endif
if (!valid(thing))
  thing = $match_utils:match(dobjstr, rpg.dispenser.dispenses);
endif
if (!valid(thing))
  thing = $string_utils:match_player(dobjstr);
endif
if ($command_utils:object_match_failed(thing, dobjstr))
  return;
endif
permed = rpg:trusted(caller_perms()) || (player in this.other_people);
player:tell(su:space(60, "-"));
player:tell(("Displaying information on " + su:nn(thing)) + ".");
if ((ou = $object_utils):isa(thing, rpg.armour))
  this:display_armour(thing, permed);
elseif (ou:isa(thing, rpg.weapon))
  this:display_weapon(thing, permed);
elseif (valid(doll = rpg:get_doll(thing)))
  this:display_creature(thing, doll, permed);
elseif (ou:isa(thing, $local.puppet))
  player:tell("This is a type of puppet.  Parent: ", su:nn(parent(thing)), "  Owner: ", su:nn(thing.owner));
  this:tell_contents(thing);
else
  player:tell(("No information available.  Please contact " + su:nn(this.owner)) + " if you think there should be.");
endif
player:tell(su:space(60, "-"));
.

@verb #55248:"display_armour" this none this
@program #55248:display_armour
":display_armour(OBJ thing, FLAG permed) => Displays information about the specified armour.";
(rpg = $local.rpg):secure();
{armour, permed} = args;
{msg, display_type, extra_data} = {"", "full", {}};
data = {};
stuff = {@this.armour_data, @extra_data};
if ((display_type == "full") || (display_type == "partial"))
  for item in (stuff)
    {verb_name, display_name, permed_rate, unpermed_rate} = item;
    try
      value = armour:(verb_name)(player, player, rpg.weapon, 6, 0, 0);
    except (E_ARGS)
      value = armour:(verb_name)();
    except (E_VERBNF)
      value = armour.(verb_name);
    except (ANY)
      value = "unknown";
    endtry
    data = {@data, (display_name + ": ") + this:rate(value, permed ? permed_rate | unpermed_rate)};
  endfor
endif
data = $string_utils:columnize(data, 2);
data2 = {};
if (display_type == "full")
  for area in (armour.body_areas)
    data2 = {@data2, (area.name + ": ") + this:rate(armour:cover(area), permed ? 0 | {2, 0, 25, 50, 75, 99})};
  endfor
endif
data2 = $string_utils:columnize(data2, 2);
data = {@data, "", "Coverage:", @data2};
for line in (data)
  player:tell(line);
endfor
if (msg)
  player:tell(msg);
endif
.

@verb #55248:"rate" this none this
@program #55248:rate
":rate(value, specifier) => Converts value to a string, modified by appropriate specifier.";
"If specifier is a string, treat value as a boolean, with first value being true, second false, with a '/' separator.  I.e. \"yes/no\".";
"If specifier is a list, it is of the form {<word list to use>, <1 or more values to compare the given value, in order to find out which word on the list to use.>}.";
"Otherwise, return tostr(value)";
{value, specifier} = args;
if ((typeof(specifier) == LIST) && (typeof(value) == NUM))
  {x, @numbers} = specifier;
  for n in [1..length(numbers)]
    if (value <= numbers[n])
      return this.words[x][n];
    endif
  endfor
  return this.words[x][n + 1];
elseif (typeof(specifier) == STR)
  i = index(specifier, "/");
  return value ? specifier[1..i - 1] | specifier[i + 1..$];
elseif (typeof(value) == OBJ)
  return $string_utils:nn(value);
else
  return tostr(value);
endif
.

@verb #55248:"weapon_brief" this none this
@program #55248:weapon_brief
":weapon_brief(weapon, permed) => returns a string with basics on the weapon.";
$local.rpg:secure();
{weapon, permed, ?dude = player} = args;
p = {dude, dude};
dam = weapon:dam(@p);
strength = weapon:max_str_bonus(@p);
pen = weapon:pen(@p);
con = weapon:con(@p);
drlow = (4 * dam) + ((strength * 16) / 10);
drhi = (8 * dam) + (4 * strength);
wrate = {1, 5, 10, 15, 21, 28, 40};
maxpen = (pen > 0) ? drhi / pen | "Unlimited";
return (((("damage range: " + this:rate(drlow / 10, permed ? 0 | wrate)) + "-") + this:rate(drhi / 10, permed ? 0 | wrate)) + "  max armour penetration: ") + this:rate(maxpen, permed ? 0 | {3, 0, 7, 15, 25});
.

@verb #55248:"display_creature" this none this
@program #55248:display_creature
":display_creature(OBJ creature, OBJ doll, FLAG permed) => Display information on critter.";
$local.rpg:secure();
{critter, doll, permed} = args;
su = $string_utils;
stuff = {su:nn(critter) + (is_player(critter) ? " is a player character." | " is a living RPG monster."), ""};
weapons = doll:wielding();
nat_weapons = (typeof(doll.natural_weapons) == LIST) ? doll.natural_weapons | {};
if (weapons && (weapons == nat_weapons))
  stuff = {@stuff, "Armed with natural weapons:"};
  for weapon in (weapons)
    stuff = {@stuff, (su:nn(weapon) + " ") + this:weapon_brief(weapon, permed, critter)};
  endfor
else
  stuff = {@stuff, "Wielding:"};
  for weapon in (weapons)
    stuff = {@stuff, (su:nn(weapon) + " ") + this:weapon_brief(weapon, permed, critter)};
  endfor
  stuff = {@stuff, "Natural Weapons:"};
  for weapon in (nat_weapons)
    stuff = {@stuff, (su:nn(weapon) + " ") + this:weapon_brief(weapon, permed, critter)};
  endfor
endif
stuff = {@stuff, "", "Armour analysis:"};
armours = doll:wearing();
stuff = {@stuff, "Natural protection: " + tostr(`critter.nat_prot ! ANY => 0'), "Magic resistance: " + tostr(`critter.magic_resist ! ANY => 0')};
stuff2 = stuff3 = {};
areas = doll.body_areas;
for armour in (armours)
  stuff2 = {@stuff2, su:nn(armour)};
endfor
ad = this.armour_data;
for area in (areas)
  bc = bp = ba = 0;
  for armour in (armours)
    bc = $object_utils:isa(armour, #28148) ? 98 | max(bc, armour:cover(area));
    a = {player, critter, $local.rpg.weapon, area, 10, 20};
    bp = max(bp, armour:protection(@a));
    ba = max(ba, armour:absorption(@a));
  endfor
  stuff3 = {@stuff3, (((((area.name + ": ") + this:rate(bc, ad[2][3 + (permed ? 0 | 1)])) + "/") + this:rate(bp, ad[1][3 + (permed ? 0 | 1)])) + "/") + this:rate(ba, ad[2][3 + (permed ? 0 | 1)])};
endfor
stuff = {@stuff, "Wearing:", @su:columnize(stuff2, 2), "Maximum coverage/protection/absorption:", @su:columnize(stuff3, 2)};
for line in (stuff)
  player:tell(line);
endfor
.

@verb #55248:"display_weapon" this none this
@program #55248:display_weapon
":display_weapon(OBJ thing, FLAG permed) => Displays information about the specified weapon.";
$local.rpg:secure();
{weapon, permed, ?dude = player} = args;
{msg, display_type, extra_data} = {"", "full", {}};
data = {};
stuff = {@this.weapon_data, @extra_data};
if (display_type == "full")
  for item in (stuff)
    {verb_name, display_name, permed_rate, unpermed_rate} = item;
    try
      value = weapon:(verb_name)(dude, dude);
    except (E_ARGS)
      value = `weapon:(verb_name)(dude, dude, weapon) ! E_ARGS => "unknown"';
    except (E_VERBNF)
      value = weapon.(verb_name);
    except (ANY)
      value = "unknown";
    endtry
    data = {@data, (display_name + ":  ") + this:rate(value, permed ? permed_rate | unpermed_rate)};
  endfor
endif
data = $string_utils:columnize(data, 2);
data = {@data, this:weapon_brief(weapon, permed)};
for line in (data)
  player:tell(line);
endfor
if (msg)
  player:tell(msg);
endif
.

@verb #55248:"health" this none this
@program #55248:health
rpg = $local.rpg;
player:tell();
rpg:look_health(dobj);
rpg:look_gear(dobj);
rpg:look_encumbrance(dobj);
return;
.

@verb #55248:"tell_contents" this none this
@program #55248:tell_contents
{thing} = args;
player:tell();
player:tell("*** Contents ***");
su = $string_utils;
if (!thing.contents)
  return player:tell("empty");
endif
unclaimed = 0;
claimed = 0;
nonrpg = 0;
for object in ($object_utils:all_contents(thing))
  if ($object_utils:isa(object, $local.rpg.thing))
    if (valid(claim = object.claimed_by))
      player:tell(su:nn(object), " is claimed by ", su:nn(claim));
      claimed = claimed + 1;
    else
      player:tell(su:nn(object));
      unclaimed = unclaimed + 1;
    endif
  else
    nonrpg = nonrpg + 1;
    player:tell(su:nn(object));
  endif
endfor
return player:tell("Total claimed: ", claimed, "   Total unclaimed: ", unclaimed, "   Total non-RPG items: ", nonrpg);
.

@verb #55248:"@rpg-info @rpginfo @ri" any none none rxd
@program #55248:@rpg-info
"Usage: @ri <thing> Returns extensive numeric info on RPG items, players, monsters, and also handles containers.";
if (!(caller in {player, this.fo}))
  return E_PERM;
endif
if (!argstr)
  return player:tell_lines($code_utils:verb_documentation());
endif
thing = dobj;
{su, ou, mu, rpg} = {$string_utils, $object_utils, $match_utils, $local.rpg};
if (!valid(thing))
  thing = mu:match(dobjstr, {@player.contents, @player.location.contents});
endif
if (!valid(thing))
  thing = mu:match(dobjstr, rpg.dispenser.dispenses);
endif
if (!valid(thing))
  thing = su:match_player(dobjstr);
endif
if ($command_utils:object_match_failed(thing, dobjstr))
  return;
endif
this:update_usage(verb, player);
player:tell("*** ", su:nn(thing), " ***");
player:tell("Owned by: ", su:nn(thing.owner));
player:tell("Child of: ", su:nn(x = parent(thing)), " owned by ", su:nn(x.owner));
player:tell("Location: ", su:nn(thing.location));
if (`thing.unique ! ANY => 0')
  player:tell("This item is unique.");
endif
if (is_player(thing))
  if (valid(doll = rpg:get_doll(thing)))
    this:display_creature(thing, doll, 1);
    this:health();
    this:tell_contents(thing);
    player:tell("Total RPG encumbrance ", rpg:weight(thing), " units.");
    return;
  else
    player:tell("This player does not have an RPG doll.");
    this:tell_contents(thing);
    return;
  endif
elseif (ou:isa(thing, rpg.monster))
  if (valid(doll = rpg:get_doll(thing)))
    this:display_creature(thing, doll, 1);
    this:health();
    this:tell_contents(thing);
  elseif (ou:isa(thing, this.squat))
    player:tell("This is an RPG squat.");
    this:tell_contents(thing);
    return;
  else
    player:tell("This monster does not appear to have a doll.");
    return;
  endif
  return;
elseif (ou:isa(thing, $local.puppet))
  player:tell("This is a type of puppet.");
  this:tell_contents(thing);
  return;
elseif (ou:isa(thing, $container) || ou:isa(thing, rpg.container))
  player:tell("This is a type of container.");
  this:tell_contents(thing);
  return;
elseif (ou:isa(thing, rpg.thing))
  if (valid(claim = thing.claimed_by))
    player:tell("This object is currently claimed by ", su:nn(claim));
  else
    player:tell("This object is not claimed.");
  endif
else
  player:tell("This verb has no further information about this object.");
  return;
endif
if (ou:isa(thing, rpg.weapon))
  player:tell("*** Weapon Stats ***");
  this:display_weapon(thing, 1);
  if (ou:isa(thing, rpg.weapon_spell_focus))
    player:tell("*** This object also has magical properties, try examine <object> to see which spells. ***");
  endif
  return;
elseif (ou:isa(thing, rpg.armour))
  if (ou:isa(thing, this.bracers))
    player:tell("These are magical focii used by members of the Arcanum Magus, they provide full body protection dependant on the wearers rank in the guild.  You can see the current rankings by typing ->look #98608<-.  The bracers also can deflect lightning from an attackers storm back at the attacker, the higher circles have a better chance of doing this.");
    player:tell();
    player:tell("*** Force sphere levels ***");
    player:tell("5th circle: 22,  6th circle: 26,  7th circle: 29,  8th circle:  33,  Archmage: 36");
    player:tell("Type @ri <player> to see the players actual protection.");
  endif
  player:tell("*** Armour Stats ***");
  this:display_armour(thing, 1);
  if (ou:isa(thing, rpg.armour_spell_focus))
    player:tell("*** This armour has magical properties, try examine <object> to see which spells. ***");
  endif
endif
.

"***finished***