static void chest_shatter_msg(struct obj *otmp) { const char *disposition; const char *thing; long save_Blinded; if (otmp->oclass == POTION_CLASS) { pline(msgc_itemloss, "You %s %s shatter!", Blind ? "hear" : "see", an(bottlename())); if (!breathless(youmonst.data) || haseyes(youmonst.data)) potionbreathe(&youmonst, otmp); return; } /* We have functions for distant and singular names, but not one which does _both_... TODO: fix this blindness kludge (it doesn't even work -- see eoto) */ save_Blinded = property_timeout(&youmonst, BLINDED); set_property(&youmonst, BLINDED, 1, TRUE); thing = singular(otmp, xname); if (save_Blinded) set_property(&youmonst, BLINDED, save_Blinded, TRUE); switch (objects[otmp->otyp].oc_material) { case PAPER: disposition = "is torn to shreds"; break; case WAX: disposition = "is crushed"; break; case VEGGY: disposition = "is pulped"; break; case FLESH: disposition = "is mashed"; break; case GLASS: disposition = "shatters"; break; case WOOD: disposition = "splinters to fragments"; break; default: disposition = "is destroyed"; break; } pline(msgc_itemloss, "%s %s!", An(thing), disposition); }
int dothrow() { struct obj *obj; struct monst *mon; int tmp; obj = getobj("#)", "throw"); /* it is also possible to throw food */ /* (or jewels, or iron balls ... ) */ if(!obj || !getdir(1)) /* ask "in what direction?" */ return(0); if(obj->owornmask & (W_ARMOR | W_RING)){ pline("You can't throw something you are wearing."); return(0); } u_wipe_engr(2); if(obj == uwep){ if(obj->cursed){ pline("Your weapon is welded to your hand."); return(1); } if(obj->quan > 1) setuwep(splitobj(obj, 1)); else setuwep((struct obj *) 0); } else if(obj->quan > 1) (void) splitobj(obj, 1); freeinv(obj); if(u.uswallow) { mon = u.ustuck; bhitpos.x = mon->mx; bhitpos.y = mon->my; } else if(u.dz) { if(u.dz < 0) { pline("%s hits the ceiling, then falls back on top of your head.", Doname(obj)); /* note: obj->quan == 1 */ if(obj->olet == POTION_SYM) potionhit(&youmonst, obj); else { if(uarmh) pline("Fortunately, you are wearing a helmet!"); losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object"); dropy(obj); } } else { pline("%s hits the floor.", Doname(obj)); if(obj->otyp == EXPENSIVE_CAMERA) { pline("It is shattered in a thousand pieces!"); obfree(obj, Null(obj)); } else if(obj->otyp == EGG) { pline("\"Splash!\""); obfree(obj, Null(obj)); } else if(obj->olet == POTION_SYM) { pline("The flask breaks, and you smell a peculiar odor ..."); potionbreathe(obj); obfree(obj, Null(obj)); } else { dropy(obj); } } return(1); } else if(obj->otyp == BOOMERANG) { mon = boomhit(u.dx, u.dy); if(mon == &youmonst) { /* the thing was caught */ (void) addinv(obj); return(1); } } else { if(obj->otyp == PICK_AXE && shkcatch(obj)) return(1); mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 : (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1, obj->olet, NULL, NULL, obj); } if(mon) { /* awake monster if sleeping */ wakeup(mon); if(obj->olet == WEAPON_SYM) { tmp = -1+u.ulevel+mon->data->ac+abon(); if(obj->otyp < ROCK) { if(!uwep || uwep->otyp != obj->otyp+(BOW-ARROW)) tmp -= 4; else { tmp += uwep->spe; } } else if(obj->otyp == BOOMERANG) tmp += 4; tmp += obj->spe; if(u.uswallow || tmp >= rnd(20)) { if(hmon(mon,obj,1) == TRUE){ /* mon still alive */ #ifndef NOWORM cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp); #endif /* NOWORM */ } else mon = 0; /* weapons thrown disappear sometimes */ if(obj->otyp < BOOMERANG && rn2(3)) { /* check bill; free */ obfree(obj, (struct obj *) 0); return(1); } } else miss(objects[obj->otyp].oc_name, mon); } else if(obj->otyp == HEAVY_IRON_BALL) { tmp = -1+u.ulevel+mon->data->ac+abon(); if(!Punished || obj != uball) tmp += 2; if(u.utrap) tmp -= 2; if(u.uswallow || tmp >= rnd(20)) { if(hmon(mon,obj,1) == FALSE) mon = 0; /* he died */ } else miss("iron ball", mon); } else if(obj->olet == POTION_SYM && u.ulevel > rn2(15)) { potionhit(mon, obj); return(1); } else { if(cansee(bhitpos.x,bhitpos.y)) pline("You miss %s.",monnam(mon)); else pline("You miss it."); if(obj->olet == FOOD_SYM && mon->data->mlet == 'd') if(tamedog(mon,obj)) return(1); if(obj->olet == GEM_SYM && mon->data->mlet == 'u' && !mon->mtame){ if(obj->dknown && objects[obj->otyp].oc_name_known){ if(objects[obj->otyp].g_val > 0){ u.uluck += 5; goto valuable; } else { pline("%s is not interested in your junk.", Monnam(mon)); } } else { /* value unknown to @ */ u.uluck++; valuable: if(u.uluck > LUCKMAX) /* dan@ut-ngp */ u.uluck = LUCKMAX; pline("%s graciously accepts your gift.", Monnam(mon)); mpickobj(mon, obj); rloc(mon); return(1); } } } } /* the code following might become part of dropy() */ if(obj->otyp == CRYSKNIFE) obj->otyp = WORM_TOOTH; obj->ox = bhitpos.x; obj->oy = bhitpos.y; obj->nobj = fobj; fobj = obj; /* prevent him from throwing articles to the exit and escaping */ /* subfrombill(obj); */ stackobj(obj); if(Punished && obj == uball && (bhitpos.x != u.ux || bhitpos.y != u.uy)){ freeobj(uchain); unpobj(uchain); if(u.utrap){ if(u.utraptype == TT_PIT) pline("The ball pulls you out of the pit!"); else { long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; pline("The ball pulls you out of the bear trap."); pline("Your %s leg is severely damaged.", (side == LEFT_SIDE) ? "left" : "right"); set_wounded_legs(side, 500+rn2(1000)); losehp(2, "thrown ball"); } u.utrap = 0; } unsee(); uchain->nobj = fobj; fobj = uchain; u.ux = uchain->ox = bhitpos.x - u.dx; u.uy = uchain->oy = bhitpos.y - u.dy; setsee(); (void) inshop(); } if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); return(1); }
void potionhit(struct monst *mon, struct obj *obj) { char *botlnam = bottlenames[rn2(SIZE(bottlenames))]; boolean uclose, isyou = (mon == &youmonst); if(isyou) { uclose = TRUE; pline("The %s crashes on your head and breaks into shivers.", botlnam); losehp(rnd(2), "thrown potion"); } else { uclose = (dist(mon->mx,mon->my) < 3); /* perhaps 'E' and 'a' have no head? */ pline("The %s crashes on %s's head and breaks into shivers.", botlnam, monnam(mon)); if(rn2(5) && mon->mhp > 1) mon->mhp--; } pline("The %s evaporates.", xname(obj)); if(!isyou && !rn2(3)) switch(obj->otyp) { case POT_RESTORE_STRENGTH: case POT_GAIN_STRENGTH: case POT_HEALING: case POT_EXTRA_HEALING: if(mon->mhp < mon->mhpmax) { mon->mhp = mon->mhpmax; pline("%s looks sound and hale again!", Monnam(mon)); } break; case POT_SICKNESS: if(mon->mhpmax > 3) mon->mhpmax /= 2; if(mon->mhp > 2) mon->mhp /= 2; break; case POT_CONFUSION: case POT_BOOZE: mon->mconf = 1; break; case POT_INVISIBILITY: unpmon(mon); mon->minvis = 1; pmon(mon); break; case POT_PARALYSIS: mon->mfroz = 1; break; case POT_SPEED: mon->mspeed = MFAST; break; case POT_BLINDNESS: mon->mblinded |= 64 + rn2(64); break; /* case POT_GAIN_LEVEL: case POT_LEVITATION: case POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case POT_OBJECT_DETECTION: break; */ } if(uclose && rn2(5)) potionbreathe(obj); obfree(obj, Null(obj)); }
// NOTE: To hit "you" with a potion p, call "potionhit(NULL, p)". no "youmonst" void potionhit(monst_t *mon, obj_t *obj) { Char *botlnam = bottlenames[rund(MAX_BOTTLES)]; Boolean uclose; // , isyou = (mon==NULL); if (!mon) { uclose = true; StrPrintF(ScratchBuffer, "The %s crashes on your head and breaks into shivers.", botlnam); message(ScratchBuffer); losehp(rnd(2), "thrown potion"); } else { uclose = (dist(mon->mx,mon->my) < 3); /* perhaps 'E' and 'a' have no head? */ StrPrintF(ScratchBuffer, "The %s crashes on %s's head and breaks into shivers.", botlnam, monnam(mon)); message(ScratchBuffer); if (rund(5) && mon->mhp > 1) mon->mhp--; } StrPrintF(ScratchBuffer, "The %s evaporates.", xname(obj)); message(ScratchBuffer); if (mon && !rund(3)) { switch(obj->otype) { case POT_RESTORE_STRENGTH: case POT_GAIN_STRENGTH: case POT_HEALING: case POT_EXTRA_HEALING: if (mon->mhp < mon->mhpmax) { mon->mhp = mon->mhpmax; StrPrintF(ScratchBuffer, "%s looks sound and hale again!", Monnam(mon)); message(ScratchBuffer); } break; case POT_SICKNESS: if (mon->mhpmax > 3) mon->mhpmax /= 2; if (mon->mhp > 2) mon->mhp /= 2; break; case POT_CONFUSION: case POT_BOOZE: mon->bitflags |= M_IS_CONFUSED; // mon->mconf = 1; break; case POT_INVISIBILITY: unpmon(mon); mon->bitflags |= M_IS_INVISIBLE; // mon->minvis = 1; pmon(mon); break; case POT_PARALYSIS: mon->bitflags |= M_IS_FROZEN; // mon->mfroz = 1; break; case POT_SPEED: mon->mspeed = MFAST; break; case POT_BLINDNESS: mon->mcansee_and_blinded |= 64 + rund(64); // "|="? "=" to turn off SEE? break; /* case POT_GAIN_LEVEL: case POT_LEVITATION: case POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case POT_OBJECT_DETECTION: break; */ default: break; } } if (uclose && rund(5)) potionbreathe(obj); free_obj(obj, NULL); }