A dump of #418 (Armor)

@create #112297 named armour:armour
@prop #418."size" 10 rc
@prop #418."cover" {} r
;;#418.("cover") = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@prop #418."protection" 0 r
@prop #418."bulk" 1 r
@prop #418."body_areas" {} rc
;;#418.("body_areas") = {#39284, #60746, #61688, #61605, #9655, #51172, #75697, #38715, #52374, #47817, #33584, #54898}
@prop #418."leather" 0 r
"#418.("absorption") => E_PERM (Permission denied)
"#418.("worn_area") => E_PERM (Permission denied)
@prop #418."wear_msg" "%N %<puts> on %p %t." rc
@prop #418."remove_msg" "%N %<takes> off %p %t." rc
@prop #418."custom" {} rc
@prop #418."break_msg" "%T shatters into slivers." rc
@prop #418."announce_clang_msgs" {} r
;;#418.("announce_clang_msgs") = {"%N's armoured %locstr %clanged the blow.", "The blow is %clanged by the armour on %n's %locstr."}
@prop #418."clang_verbs" {} r
;;#418.("clang_verbs") = {"deflected", "stopped", "repelled", "deflected", "blocked", "deflected", "absorbed", "deflected", "stopped", "diverted", "deflected"}
"#418.("can_degrade") => E_PERM (Permission denied)
@prop #418."too_small_msg" "The %t appears to be too small for you to wear." r
@prop #418."layers" 0 r
;;#418.("manufactured") = 923451666
;;#418.("worth") = -1
;;#418.("condition") = 100
;;#418.("last_action") = 1102246102
;;#418.("odrop_failed_msg") = "%<tries> to drop %t but fails!"
;;#418.("odrop_succeeded_msg") = "%<drops> %t."
;;#418.("otake_succeeded_msg") = "%<picks> up %t."
"#418.("key") => E_PERM (Permission denied)
;;#418.("aliases") = {"armour"}
;;#418.("description") = "Something to watch over you."
;;#418.("object_size") = {21406, 1141286558}

@verb #418:"wear" this none none rxd
@program #418:wear
if (!(rpg = $local.rpg):trust($nothing, player))
  return E_PERM;
elseif (this.location != player)
  rpg:playertell(player, "You don't have ", this.name, ".");
elseif (!valid(doll = rpg:get_doll(player)))
  rpg:playertell(player, "You can't work out which way round it goes. Perhaps some training at the Bovine Illuminati would help.");
elseif (p = doll.paralyzed)
  return rpg:playertell(player, (typeof(p) == STR) ? p | "Trying to adjust your fashion statement while paralyzed is just about close to impossible.");
elseif (rpg.magic_db.en_combat_effect in doll.combat_effects)
  return rpg:playertell(player, "The vines entangling you make that just a wee bit difficult.");
elseif (this in doll.wearing)
  rpg:playertell(player, "You're already wearing ", this.name, ".");
elseif (doll:aggressor() && (!(this.worn_area in {"ring"})))
  rpg:playertell(player, "Getting dressed in the middle of battle is sort of hard; try putting your armour on BEFORE you pick a fight.");
elseif (!this:may_wear(player))
  return;
elseif (fits = this:fits(player))
  "doll.wearing = listappend(doll.wearing, this);";
  "this:do_wear(player);";
  rpg:say_action(this.wear_msg, player, this, player.location);
  "rpg:playertell(player, \"You are now wearing \", $string_utils:title_list(doll.wearing), \".\");";
  "return 1;";
  return this:_wear(doll);
elseif (fits != doll)
  rpg:playertell(player, "You try to put on your ", this.name, " but your ", fits.name, " keeps getting in the way.");
else
  rpg:playertell(player, this.name, (this.size < doll.size) ? " is too small for you." | " doesn't seem to fit you.");
endif
"Hydros (#106189) - Tue Jul 5, 2005 - Commented out the hard code grunt work and moved it to :_wear().  The same done for :remove => :_remove.";
"Hydros(#106189) - Sat Jul 9, 2005 - Moved messaging from :_wear back into this verb. :_* verbs should be programmatic, sans messaging.  Silly me.";
.

@verb #418:"rem*ove" this none none rxd
@program #418:remove
if (!(rpg = $local.rpg):trust($nothing, player))
  return E_PERM;
elseif ((!valid(doll = rpg:get_doll(player))) || (!(this in doll.wearing)))
  rpg:playertell(player, "You're not wearing ", this.name, ".");
elseif (p = doll:cannot_move())
  rpg:playertell(player, (typeof(p) == STR) ? p | "Hahahha.  Take that off?  While paralyzed?  Good one.");
elseif (rpg.magic_db.en_combat_effect in doll.combat_effects)
  rpg:playertell(player, "The vines entangling you make that just a wee bit difficult.");
elseif (`player.location:sleeping(player) ! ANY => 0')
  return rpg:playertell(player, "You dream of removing your ", this.name, ".");
elseif (!doll:hands_free())
  rpg:playertell(player, "You'll need to have your hands free to get undressed.");
elseif (doll:aggressor())
  rpg:playertell(player, "Getting undressed in the middle of battle is kind of hard; who wants to see your ugly bod anyway?");
elseif (this:may_remove(player))
  "doll.wearing = setremove(doll.wearing, this);";
  "this:do_remove(player);";
  rpg:say_action(this.remove_msg, player, this, player.location);
  "text = $string_utils:english_list($list_utils:map_prop(doll.wearing, \"name\"));";
  "rpg:playertell(player, \"You are now wearing \", text, \".\");";
  this:_remove(doll);
endif
"Hydros (#106189) - Tue Jul 5, 2005 - Commented out the hard code grunt work and moved it to :_remove().  The same done for :wear => :_wear.";
"Hydros(#106189) - Sat Jul 9, 2005 - Moved messaging from :_remove back into this verb. :_* verbs should be programmatic, sans messaging.  Silly me.";
.

@verb #418:"encumbrance" this none this
@program #418:encumbrance
enc = this.encumbrance;
if (valid(doll = $local.rpg:get_doll(this.location)))
  enc = (this in doll.wearing) ? (enc * 8) / 9 | (enc + 1);
endif
return (this.size * enc) / 10;
.

@verb #418:"fits" this none this
@program #418:fits
":fits(who) => True if armour will fit on given character. --Quinn (08-MAR-93)";
{who} = args;
if (!valid(doll = $local.rpg:get_doll(who)))
  return E_INVARG;
elseif ((body_size = doll.size) > (new_armour_size = this.size))
  return doll;
endif
coverage = this:coverage();
for area in (this.body_areas)
  if ((!(area in doll.body_areas)) && (cover = coverage[area in this.body_areas]))
    return doll;
  endif
  if (cover = coverage[area in this.body_areas])
    for armour in (doll.wearing)
      narea = area in armour.body_areas;
      if ((narea && (nac = armour.cover[narea])) && ((nac == cover) || (((nac + cover) - (doll.agl * 2)) > (100 + random(50)))))
        body_size = armour.size + armour.bulk;
        if ((new_armour_size <= body_size) || ((new_armour_size * 5) > (body_size * 6)))
          return armour;
        endif
      endif
    endfor
  endif
endfor
num_worn = 0;
warea = this.worn_area;
max_worn = {99, 1, 1, 1, doll.hands}[(warea in {"necklace", "amulet", "nose ring", "ring"}) + 1];
for armour in (doll.wearing)
  if (warea == armour.worn_area)
    num_worn = num_worn + 1;
    if (num_worn >= max_worn)
      return armour;
    endif
  endif
endfor
return 1;
"Profane 20-JAN-96 1523EST: Added check to make sure body areas covered are same as on doll.";
"Irin Sun Sep 29 15:19:01 1996 PDT -- Added check for worn area.";
"Irin Thu Oct 10 13:51:40 1996 PDT -- Rewrite to allow items with non-identical .cover property to be used.";
"Profane (#30788) - Sun Aug  5, 2001 - Deny fitting in case of missing body area only if .cover is positive.";
.

@verb #418:"protection" this none this rx
@program #418:protection
":protection(attacker, target, weapon, hit-location, penetration, damage)";
"=> Protection this armour affords from an attack with the given stats.";
"Note that 'target' will be the wearer of the armour.";
prot = this.protection;
return max(((prot * this.condition) / 100) || 0, prot / 2);
"Quinn 11-AUG-93 1012: Added.";
"Profane 2-17-95 23:18EST - Modified for condition of armour.";
.

@verb #418:"cover" this none this
@program #418:cover
":cover(LIST body_areas)";
"-> Percentage chance of the armour affording protection to the given body areas.  The final coverage factor is that of the area least protected.";
targs1 = typeof(areas = args[1]);
cover = this.cover;
this.last_action && this:do_update();
if (targs1 == NUM)
  return cover[areas];
endif
coverage = 0;
covered = this.body_areas;
areas = (targs1 == LIST) ? areas | {areas};
for area in (areas)
  if (i = area in covered)
    coverage = coverage + cover[i];
  endif
endfor
return coverage ? coverage / length(areas) | 0;
"Quinn 18-NOV-93 0402: Added.";
.

@verb #418:"check_degrade" this none this rx
@program #418:check_degrade
":check_degrade(OBJ attacker, OBJ victim, location, OBJ other weapon/armour, NUM qual of attack)";
{attacker, victim, loc, weapon, qual} = args;
if (typeof(condition = this.condition) == NUM)
  if ((this.unique || children(this)) || (qual < 1))
    return;
  endif
  "Chance of breaking: 1% for every 5 condition points we are below 50. e.g. .condition 40 == 2% chance of breaking.";
  break_chance = max((50 - condition) / 5, 0);
  if (random(99) <= break_chance)
    $local.rpg:secure();
    this:("break")();
    kill_task(task_id());
  else
    chance = (5 + (5 * (this.leather && (!weapon.blunt)))) + (qual / 99);
    "Base chance = .5%, 1% if this is a piece of leather armour and the attacking weapon is sharp (!blunt). Add in quality of attack expressed as a percentage. For yer average attack, this works out to be ~.8% or ~1.3%, respectively.";
    if (random(999) <= chance)
      "Alright, real simple formula since old one was tick-intensive and people whined it did too much damage.";
      amt = (5 * qual) / 99;
      amt = random(max(amt, 1));
      (rpg = $local.rpg):secure();
      this.condition = max(condition - amt, 0);
      rpg:playertell(victim, "Your ", this.name, " seems a little worse for wear.");
    endif
  endif
endif
"Profane 2-17-95 23:50EST - Added.";
"THX (#105941) - Tue Dec 21, 1999 - Put security in _only_ if the armour degrades or breaks.";
.

@verb #418:"break" this none this
@program #418:break
":break() -- Make the armour break. Instead of recycling it, we just move it to the cemetery and let the regular reaping take care of it.";
if (!(rpg = $local.rpg):trusted(caller_perms()))
  return E_PERM;
elseif ((((this.owner != rpg.owner) || this.unique) || (typeof(condition = this.condition) != NUM)) || children(this))
  return E_NACC;
else
  if (valid(doll = rpg:get_doll(who = this.location)) && (this in doll.wearing))
    rpg:s_i_n(0);
    rpg:playertell(who, "Your ", this.name, " disintegrates from the abuse it has taken!");
    rpg:rpg_announce_all_but(who.location, {who}, who.name, "'s ", this.name, " disintegrates from the abuse it has taken!");
    doll.wearing = setremove(doll.wearing, this);
  else
    rpg:say_action(this.break_msg, who, this, who);
  endif
  this:unclaim_for(this.claimed_by);
  this:moveto(rpg.cemetery);
endif
"Profane 2-17-95 23:55EST - Added.";
"Hydros (#106189) - Tue Jul 12, 2005 - Inserted a :s_i_n() call because the sweep task exploded.";
.

@verb #418:"absorption" this none this rx
@program #418:absorption
":absorption(attacker, target, weapon, hit-location, concussion, damage)";
a = this.absorption;
return max(0, ((this.condition || 100) > 50) ? a | (a - 1));
"Irin Sept 16 1996 -- added.";
"THX (#105941) - Fri May  5, 2000 - Fixed for 0 absorption.";
.

@verb #418:"do_move" this none this
@program #418:do_move
":do_move(oldloc, newloc) => remove this from oldloc.wielding.";
rpg = $local.rpg;
if (rpg:trusted(caller_perms()))
  if (valid(doll = rpg:get_doll(args[1])))
    doll.wearing = setremove(doll.wearing, this);
    this:do_remove(args[1]);
  endif
  pass(@args);
else
  return E_PERM;
endif
.

@verb #418:"may_wear" this none this
@program #418:may_wear
":may_wear(who) => Who is allowed to wear armour.";
{who} = args;
if (valid(doll = (rpg = $local.rpg):get_doll(who)))
  if (msg = doll:immobilized())
    rpg:playertell(who, msg);
    return 0;
  elseif (`who.location:sleeping(who) ! E_VERBNF => 0')
    rpg:playertell(who, "You are asleep and cannot do that.");
    return 0;
  endif
  return 1;
else
  return 0;
endif
.

@verb #418:"do_wear" this none this
@program #418:do_wear
":do_wear(who) => Perform whatever additional tasks are required to allow 'who' to wear the armour.";
if ((!(this.owner in $local.rpg.gms)) && `verb_info(this, "0") ! E_VERBNF')
  raise(E_PERM, "Sorry, but non-gms may not own armour objects. Thanks for playing.");
else
  this.last_action && this:do_update();
  return 1;
endif
.

@verb #418:"do_remove" this none this
@program #418:do_remove
":do_remove(who) => Perform whatever tasks are necessary to remove the armour from who...";
this.last_action && this:do_update();
return 1;
.

@verb #418:"may_remove" this none this
@program #418:may_remove
":may_remove(who) => Who is allowed to take off the armour.";
{who} = args;
if (valid(doll = (rpg = $local.rpg):get_doll(who)))
  if (msg = doll:immobilized())
    rpg:playertell(who, msg);
    return 0;
  endif
  return 1;
else
  return 0;
endif
.

@verb #418:"custom modified off_the_shelf" this none this
@program #418:custom
$local.rpg:secure();
{?who} = args;
if (verb == "off_the_shelf")
  clear_property(this.custom);
else
  this.custom = {who, verb};
endif
.

@verb #418:"hidden_verbs" this none this
@program #418:hidden_verbs
{who} = args;
prev = pass(who);
armour = (rpg = $local.rpg).armour;
if (((!valid(doll = rpg:get_doll(who))) || (this in doll.wearing)) || (who != this.location))
  prev = {@prev, {armour, "wear", {"this", "none", "none"}}};
endif
if (((!valid(doll)) || (!(this in doll.wearing))) || (who != this.location))
  prev = {@prev, {armour, "rem*ove", {"this", "none", "none"}}};
endif
return prev;
.

@verb #418:"description" this none this
@program #418:description
desc = pass(@args);
if (valid(doll = $local.rpg:get_doll(player)) && (this.size < doll.size))
  desc = (typeof(desc) == LIST) ? desc | {desc};
  desc = setadd(desc, strsub(this.too_small_msg, "%t", this.name));
endif
return desc;
.

@verb #418:"announce_clang" this none this rx
@program #418:announce_clang
":announce_clang(attacker, target, location-string, clanging weapon, quality of attack)";
"Announce that this armour has deflected a blow from `attacker' to `location-string' while being worn by `target'.";
{attacker, defender, locstr, weapon, qual} = args;
string = this.announce_clang_msgs[random($)];
string = strsub(string, "%locstr", locstr);
weap = weapon:used_title();
string = strsub(string, "%weapon is ", weap + ((weap[$] == "s") ? " are " | " is "));
string = strsub(string, "%weapon", weap);
string = strsub(string, "%clanged", this.clang_verbs[random($)]);
dobj = attacker;
(rpg = $local.rpg):say_action(string, defender);
if (attacker.location != defender.location)
  rpg:playertell(attacker, $string_utils:pronoun_sub(string, defender));
endif
.

@verb #418:"announce_clang(old)" this none this rx
@program #418:announce_clang(old)
":announce_clang(attacker, target, location-string, clanging weapon, quality of attack)";
"Announce that this armour has deflected a blow from `attacker' to `location-string' while being worn by `target'.";
{attacker, defender, locstr, weapon, qual} = args;
(rpg = $local.rpg):playertell(defender, "Your armoured ", locstr, " deflected the blow.");
rpg:rpg_announce_all_but(defender.location, {defender}, "The blow is stopped by the armour on ", defender.name, "'s ", locstr, ".");
this.last_action && this:do_update();
.

@verb #418:"can_degrade" this none this
@program #418:can_degrade
return this.(verb);
.

@verb #418:"coverage" this none this
@program #418:coverage
return this.cover;
.

@verb #418:"_wear" this none this
@program #418:_wear
"This does the grunt work of :wear.";
(rpg = $local.rpg):secure();
{doll} = args;
who = doll.character;
doll.wearing = listappend(doll.wearing, this);
this:do_wear(who);
rpg:playertell(who, "You are now wearing ", $string_utils:title_list(doll.wearing), ".");
for eq in (setremove({@doll.wearing, @doll.wielding}, this))
  fork (0)
    `rpg:trusted_verb(eq, "notify_equip") ! E_VERBNF => 0' && eq:notify_equip(doll, this);
  endfork
endfor
"Hydros (#106189) - Tue Jul 5, 2005 - Added, including a check of all your current equipment for :notify_equip.";
"Hydros(#106189) - Sat Jul 9, 2005 - Moved messaging back into :wear. :_* verbs should be programmatic, sans messaging.  Silly me.";
.

@verb #418:"_remove" this none this
@program #418:_remove
"This does the grunt work of :remove.";
(rpg = $local.rpg):secure();
{doll} = args;
who = doll.character;
doll.wearing = setremove(doll.wearing, this);
this:do_remove(who);
text = $string_utils:english_list($list_utils:map_prop(doll.wearing, "name"));
rpg:playertell(who, "You are now wearing ", text, ".");
for eq in (setremove({@doll.wearing, @doll.wielding}, this))
  fork (0)
    `rpg:trusted_verb(eq, "notify_unequip") ! E_VERBNF => 0' && eq:notify_unequip(doll, this);
  endfork
endfor
"Hydros (#106189) - Tue Jul 5, 2005 - Added, including a check of all your current equipment for :notify_unequip.";
"Hydros(#106189) - Sat Jul 9, 2005 - Moved messaging back into :remove. :_* verbs should be programmatic, sans messaging.  Silly me.";
.

"***finished***