void mon_break_armor(struct monst *mon, boolean polyspot) { struct obj *otmp; const struct permonst *mdat = mon->data; boolean vis = cansee(mon->mx, mon->my); boolean handless_or_tiny = (nohands(mdat) || verysmall(mdat)); const char *pronoun = mhim(mon), *ppronoun = mhis(mon); if (breakarm(mdat)) { if ((otmp = which_armor(mon, W_ARM)) != 0) { if ((Is_dragon_scales(otmp) && mdat == Dragon_scales_to_pm(otmp)) || (Is_dragon_mail(otmp) && mdat == Dragon_mail_to_pm(otmp))) ; /* no message here; "the dragon merges with his scaly armor" is odd and the monster's previous form is already gone */ else if (vis) pline("%s breaks out of %s armor!", Monnam(mon), ppronoun); else You_hear("a cracking sound."); m_useup(mon, otmp); } if ((otmp = which_armor(mon, W_ARMC)) != 0) { if (otmp->oartifact) { if (vis) pline("%s %s falls off!", s_suffix(Monnam(mon)), cloak_simple_name(otmp)); if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } else { if (vis) pline("%s %s tears apart!", s_suffix(Monnam(mon)), cloak_simple_name(otmp)); else You_hear("a ripping sound."); m_useup(mon, otmp); } } if ((otmp = which_armor(mon, W_ARMU)) != 0) { if (vis) pline("%s shirt rips to shreds!", s_suffix(Monnam(mon))); else You_hear("a ripping sound."); m_useup(mon, otmp); } } else if (sliparm(mdat)) { if ((otmp = which_armor(mon, W_ARM)) != 0) { if (vis) pline("%s armor falls around %s!", s_suffix(Monnam(mon)), pronoun); else You_hear("a thud."); if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } if ((otmp = which_armor(mon, W_ARMC)) != 0) { if (vis) { if (is_whirly(mon->data)) pline("%s %s falls, unsupported!", s_suffix(Monnam(mon)), cloak_simple_name(otmp)); else pline("%s shrinks out of %s %s!", Monnam(mon), ppronoun, cloak_simple_name(otmp)); } if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } if ((otmp = which_armor(mon, W_ARMU)) != 0) { if (vis) { if (sliparm(mon->data)) pline("%s seeps right through %s shirt!", Monnam(mon), ppronoun); else pline("%s becomes much too small for %s shirt!", Monnam(mon), ppronoun); } if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } } if (handless_or_tiny) { /* [caller needs to handle weapon checks] */ if ((otmp = which_armor(mon, W_ARMG)) != 0) { if (vis) pline("%s drops %s gloves%s!", Monnam(mon), ppronoun, MON_WEP(mon) ? " and weapon" : ""); if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } if ((otmp = which_armor(mon, W_ARMS)) != 0) { if (vis) pline("%s can no longer hold %s shield!", Monnam(mon), ppronoun); else You_hear("a clank."); if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } } if (handless_or_tiny || has_horns(mdat)) { if ((otmp = which_armor(mon, W_ARMH)) != 0 && /* flimsy test for horns matches polyself handling */ (handless_or_tiny || !is_flimsy(otmp))) { if (vis) pline("%s helmet falls to the %s!", s_suffix(Monnam(mon)), surface(mon->mx, mon->my)); else You_hear("a clank."); if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } } if (handless_or_tiny || slithy(mdat) || mdat->mlet == S_CENTAUR) { if ((otmp = which_armor(mon, W_ARMF)) != 0) { if (vis) { if (is_whirly(mon->data)) pline("%s boots fall away!", s_suffix(Monnam(mon))); else pline("%s boots %s off %s feet!", s_suffix(Monnam(mon)), verysmall(mdat) ? "slide" : "are pushed", ppronoun); } if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } } if (!can_saddle(mon)) { if ((otmp = which_armor(mon, W_SADDLE)) != 0) { if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); if (vis) pline("%s saddle falls off.", s_suffix(Monnam(mon))); } if (mon == u.usteed) goto noride; } else if (mon == u.usteed && !can_ride(mon)) { noride: pline("You can no longer ride %s.", mon_nam(mon)); if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) { char buf[BUFSZ]; pline("You touch %s.", mon_nam(u.usteed)); sprintf(buf, "falling off %s", an(u.usteed->data->mname)); instapetrify(buf); } dismount_steed(DISMOUNT_FELL); } return; }
static void m_dowear_type(struct monst *mon, long flag, boolean creation, boolean racialexception) { struct obj *old, *best, *obj; int m_delay = 0; int unseen = !canseemon(mon); char nambuf[BUFSZ]; if (mon->mfrozen) return; /* probably putting previous item on */ /* Get a copy of monster's name before altering its visibility */ strcpy(nambuf, See_invisible ? Monnam(mon) : mon_nam(mon)); old = which_armor(mon, flag); if (old && old->cursed) return; if (old && flag == W_AMUL) return; /* no such thing as better amulets */ best = old; for (obj = mon->minvent; obj; obj = obj->nobj) { switch(flag) { case W_AMUL: if (obj->oclass != AMULET_CLASS || (obj->otyp != AMULET_OF_LIFE_SAVING && obj->otyp != AMULET_OF_REFLECTION)) continue; best = obj; goto outer_break; /* no such thing as better amulets */ case W_ARMU: if (!is_shirt(obj)) continue; break; case W_ARMC: if (!is_cloak(obj)) continue; break; case W_ARMH: if (!is_helmet(obj)) continue; /* (flimsy exception matches polyself handling) */ if (has_horns(mon->data) && !is_flimsy(obj)) continue; break; case W_ARMS: if (!is_shield(obj)) continue; break; case W_ARMG: if (!is_gloves(obj)) continue; break; case W_ARMF: if (!is_boots(obj)) continue; break; case W_ARM: if (!is_suit(obj)) continue; if (racialexception && (racial_exception(mon, obj) < 1)) continue; break; } if (obj->owornmask) continue; /* I'd like to define a VISIBLE_ARM_BONUS which doesn't assume the * monster knows obj->spe, but if I did that, a monster would keep * switching forever between two -2 caps since when it took off one * it would forget spe and once again think the object is better * than what it already has. */ if (best && (ARM_BONUS(best) + extra_pref(mon,best) >= ARM_BONUS(obj) + extra_pref(mon,obj))) continue; best = obj; } outer_break: if (!best || best == old) return; /* if wearing a cloak, account for the time spent removing and re-wearing it when putting on a suit or shirt */ if ((flag == W_ARM || flag == W_ARMU) && (mon->misc_worn_check & W_ARMC)) m_delay += 2; /* when upgrading a piece of armor, account for time spent taking off current one */ if (old) m_delay += objects[old->otyp].oc_delay; if (old) /* do this first to avoid "(being worn)" */ old->owornmask = 0L; if (!creation) { if (canseemon(mon)) { char buf[BUFSZ]; if (old) sprintf(buf, " removes %s and", distant_name(old, doname)); else buf[0] = '\0'; pline("%s%s puts on %s.", Monnam(mon), buf, distant_name(best,doname)); } /* can see it */ m_delay += objects[best->otyp].oc_delay; mon->mfrozen = m_delay; if (mon->mfrozen) mon->mcanmove = 0; } if (old) update_mon_intrinsics(mon, old, FALSE, creation); mon->misc_worn_check |= flag; best->owornmask |= flag; update_mon_intrinsics(mon, best, TRUE, creation); /* if couldn't see it but now can, or vice versa, */ if (!creation && (unseen ^ !canseemon(mon))) { if (mon->minvis && !See_invisible) { pline("Suddenly you cannot see %s.", nambuf); makeknown(best->otyp); } /* else if (!mon->minvis) pline("%s suddenly appears!", Amonnam(mon)); */ } }
/* * See if this armor is better than what we're wearing. */ static boolean is_better_armor(struct monst *mtmp, struct obj *otmp) { struct obj *obj; struct obj *best = (struct obj *)0; if (otmp->oclass != ARMOR_CLASS) return FALSE; if (mtmp->data == &mons[PM_KI_RIN] || mtmp->data == &mons[PM_COUATL]) return FALSE; if (cantweararm(mtmp->data) && !(is_cloak(otmp) && mtmp->data->msize == MZ_SMALL)) return FALSE; if (is_shirt(otmp) && (mtmp->misc_worn_check & W_ARM)) return FALSE; if (is_shield(otmp) && (mtmp == &youmonst) ? (uwep && bimanual(uwep)) : (MON_WEP(mtmp) && bimanual(MON_WEP(mtmp)))) return FALSE; if (is_gloves(otmp) && nohands(mtmp->data)) return FALSE; if (is_boots(otmp) && (slithy(mtmp->data) || mtmp->data->mlet == S_CENTAUR)) return FALSE; if (is_helmet(otmp) && !is_flimsy(otmp) && num_horns(mtmp->data) > 0) return FALSE; obj = (mtmp == &youmonst) ? invent : mtmp->minvent; for (; obj; obj = obj->nobj) { if (is_cloak(otmp) && !is_cloak(obj)) continue; if (is_suit(otmp) && !is_suit(obj)) continue; if (is_shirt(otmp) && !is_shirt(obj)) continue; if (is_boots(otmp) && !is_boots(obj)) continue; if (is_shield(otmp) && !is_shield(obj)) continue; if (is_helmet(otmp) && !is_helmet(obj)) continue; if (is_gloves(otmp) && !is_gloves(obj)) continue; if (!obj->owornmask) continue; if (best && (ARM_BONUS(obj) + extra_pref(mtmp, obj) >= ARM_BONUS(best) + extra_pref(mtmp, best))) best = obj; } return ((best == (struct obj *)0) || (ARM_BONUS(otmp) + extra_pref(mtmp, otmp) > ARM_BONUS(best) + extra_pref(mtmp, best))); }
static void break_armor(void) { struct obj *otmp; if (breakarm(youmonst.data)) { if ((otmp = uarm) != 0) { if (donning(otmp)) cancel_don(); pline("You break out of your armor!"); exercise(A_STR, FALSE); Armor_gone(); useup(otmp); } if ((otmp = uarmc) != 0) { if (otmp->oartifact) { pline("Your %s falls off!", cloak_simple_name(otmp)); Cloak_off(); dropx(otmp); } else { pline("Your %s tears apart!", cloak_simple_name(otmp)); Cloak_off(); useup(otmp); } } if (uarmu) { pline("Your shirt rips to shreds!"); useup(uarmu); } } else if (sliparm(youmonst.data)) { if (((otmp = uarm) != 0) && (racial_exception(&youmonst, otmp) < 1)) { if (donning(otmp)) cancel_don(); pline("Your armor falls around you!"); Armor_gone(); dropx(otmp); } if ((otmp = uarmc) != 0) { if (is_whirly(youmonst.data)) pline("Your %s falls, unsupported!", cloak_simple_name(otmp)); else pline("You shrink out of your %s!", cloak_simple_name(otmp)); Cloak_off(); dropx(otmp); } if ((otmp = uarmu) != 0) { if (is_whirly(youmonst.data)) pline("You seep right through your shirt!"); else pline("You become much too small for your shirt!"); setworn(NULL, otmp->owornmask & W_ARMU); dropx(otmp); } } if (has_horns(youmonst.data)) { if ((otmp = uarmh) != 0) { if (is_flimsy(otmp) && !donning(otmp)) { char hornbuf[BUFSZ], yourbuf[BUFSZ]; /* Future possiblities: This could damage/destroy helmet */ sprintf(hornbuf, "horn%s", plur(num_horns(youmonst.data))); pline("Your %s %s through %s %s.", hornbuf, vtense(hornbuf, "pierce"), shk_your(yourbuf, otmp), xname(otmp)); } else { if (donning(otmp)) cancel_don(); pline("Your helmet falls to the %s!", surface(u.ux, u.uy)); Helmet_off(); dropx(otmp); } } } if (nohands(youmonst.data) || verysmall(youmonst.data)) { if ((otmp = uarmg) != 0) { if (donning(otmp)) cancel_don(); /* Drop weapon along with gloves */ pline("You drop your gloves%s!", uwep ? " and weapon" : ""); drop_weapon(0); Gloves_off(); dropx(otmp); } if ((otmp = uarms) != 0) { pline("You can no longer hold your shield!"); Shield_off(); dropx(otmp); } if ((otmp = uarmh) != 0) { if (donning(otmp)) cancel_don(); pline("Your helmet falls to the %s!", surface(u.ux, u.uy)); Helmet_off(); dropx(otmp); } } if (nohands(youmonst.data) || verysmall(youmonst.data) || slithy(youmonst.data) || youmonst.data->mlet == S_CENTAUR) { if ((otmp = uarmf) != 0) { if (donning(otmp)) cancel_don(); if (is_whirly(youmonst.data)) pline("Your boots fall away!"); else pline("Your boots %s off your feet!", verysmall(youmonst.data) ? "slide" : "are pushed"); Boots_off(); dropx(otmp); } } }
static void break_armor (void) { struct obj *otmp; if (breakarm(youmonst.data)) { if ((otmp = uarm) != 0) { if (donning(otmp)) cancel_don(); You("break out of your armor!"); exercise(A_STR, false); (void) Armor_gone(); useup(otmp); } if ((otmp = uarmc) != 0) { if(otmp->oartifact) { Your("%s falls off!", cloak_simple_name(otmp)); (void) Cloak_off(); dropx(otmp); } else { Your("%s tears apart!", cloak_simple_name(otmp)); (void) Cloak_off(); useup(otmp); } } if (uarmu) { Your("shirt rips to shreds!"); useup(uarmu); } } else if (sliparm(youmonst.data)) { if (((otmp = uarm) != 0) && (racial_exception(&youmonst, otmp) < 1)) { if (donning(otmp)) cancel_don(); Your("armor falls around you!"); (void) Armor_gone(); dropx(otmp); } if ((otmp = uarmc) != 0) { if (is_whirly(youmonst.data)) Your("%s falls, unsupported!", cloak_simple_name(otmp)); else You("shrink out of your %s!", cloak_simple_name(otmp)); (void) Cloak_off(); dropx(otmp); } if ((otmp = uarmu) != 0) { if (is_whirly(youmonst.data)) You("seep right through your shirt!"); else You("become much too small for your shirt!"); setworn((struct obj *)0, otmp->owornmask & W_ARMU); dropx(otmp); } } if (has_horns(youmonst.data)) { if ((otmp = uarmh) != 0) { if (is_flimsy(otmp) && !donning(otmp)) { /* Future possiblities: This could damage/destroy helmet */ message_object(MSG_YOUR_HORNS_PIERCE_O, otmp); } else { if (donning(otmp)) cancel_don(); Your("helmet falls to the %s!", surface(u.ux, u.uy)); (void) Helmet_off(); dropx(otmp); } } } if (nohands(youmonst.data) || verysmall(youmonst.data)) { if ((otmp = uarmg) != 0) { if (donning(otmp)) cancel_don(); /* Drop weapon along with gloves */ You("drop your gloves%s!", uwep ? " and weapon" : ""); drop_weapon(0); (void) Gloves_off(); dropx(otmp); } if ((otmp = uarms) != 0) { You("can no longer hold your shield!"); (void) Shield_off(); dropx(otmp); } if ((otmp = uarmh) != 0) { if (donning(otmp)) cancel_don(); Your("helmet falls to the %s!", surface(u.ux, u.uy)); (void) Helmet_off(); dropx(otmp); } } if (nohands(youmonst.data) || verysmall(youmonst.data) || slithy(youmonst.data) || youmonst.data->mlet == S_CENTAUR) { if ((otmp = uarmf) != 0) { if (donning(otmp)) cancel_don(); if (is_whirly(youmonst.data)) Your("boots fall away!"); else Your("boots %s off your feet!", verysmall(youmonst.data) ? "slide" : "are pushed"); (void) Boots_off(); dropx(otmp); } } }