From 4e05b9a1ec9e4c6d67bf3e5866ebcb2891009527 Mon Sep 17 00:00:00 2001 From: Sean Hunt Date: Mon, 23 Feb 2015 17:21:11 -0500 Subject: [PATCH] A lot more cleanup to rust and water. --- doc/fixes35.0 | 1 + include/extern.h | 8 +- src/do.c | 3 +- src/do_wear.c | 14 --- src/dokick.c | 2 +- src/fountain.c | 2 +- src/mhitm.c | 10 +- src/mhitu.c | 70 +----------- src/mon.c | 6 +- src/objnam.c | 2 +- src/sit.c | 4 +- src/trap.c | 283 ++++++++++++++++++++++++----------------------- src/uhitm.c | 43 +++---- src/worn.c | 27 ++++- src/zap.c | 4 +- 15 files changed, 209 insertions(+), 270 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 4fd81cff5..48da8da36 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -861,6 +861,7 @@ fix used-up magic trap trying to hit steed. messages are now printed when objects on the ground are eroded object erosion now always identifies rust/rot/fire/corrodeproof objects grease protects from all types of erosion +all sources of erosion now affect objects the same way Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 87427dd3a..87d3adee7 100644 --- a/include/extern.h +++ b/include/extern.h @@ -434,7 +434,6 @@ E int NDECL(doputon); E void NDECL(find_ac); E void NDECL(glibr); E struct obj *FDECL(some_armor,(struct monst *)); -E void FDECL(erode_armor, (struct monst *,BOOLEAN_P)); E struct obj *FDECL(stuck_ring, (struct obj *,int)); E struct obj *NDECL(unchanger); E void NDECL(reset_remarm); @@ -2203,7 +2202,7 @@ E coord *FDECL(gettrack, (int,int)); /* ### trap.c ### */ E boolean FDECL(burnarmor,(struct monst *)); -E boolean FDECL(rust_dmg, (struct obj *,const char *,int,BOOLEAN_P)); +E boolean FDECL(rust_dmg, (struct obj *,const char *,int,BOOLEAN_P,BOOLEAN_P)); E boolean FDECL(grease_protect, (struct obj *,const char *,struct monst *)); E struct trap *FDECL(maketrap, (int,int,int)); E void FDECL(fall_through, (BOOLEAN_P)); @@ -2223,7 +2222,8 @@ E void FDECL(fill_pit, (int,int)); E int FDECL(float_down, (long, long)); E void NDECL(climb_pit); E int FDECL(fire_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P,XCHAR_P,XCHAR_P)); -E void FDECL(water_damage, (struct obj **,BOOLEAN_P,BOOLEAN_P)); +E int FDECL(water_damage, (struct obj *,const char*,BOOLEAN_P)); +E void FDECL(water_damage_chain, (struct obj *,BOOLEAN_P)); E boolean NDECL(drown); E void FDECL(drain_en, (int)); E int NDECL(dountrap); @@ -2253,7 +2253,7 @@ E void NDECL(u_init); /* ### uhitm.c ### */ -E void FDECL(hurtmarmor,(struct monst *,int)); +E void FDECL(erode_armor,(struct monst *,int)); E boolean FDECL(attack_checks, (struct monst *,struct obj *)); E void FDECL(check_caitiff, (struct monst *)); E int FDECL(find_roll_to_hit, (struct monst *,UCHAR_P,struct obj *,int *,int *)); diff --git a/src/do.c b/src/do.c index 981981293..319317bf5 100644 --- a/src/do.c +++ b/src/do.c @@ -201,8 +201,7 @@ const char *verb; map_background(x, y, 0); newsym(x, y); } - water_damage(&obj, FALSE, FALSE); - if (!obj) return TRUE; + return water_damage(obj, NULL, FALSE) == 3; } else if (u.ux == x && u.uy == y && (t = t_at(x,y)) != 0 && uteetering_at_seen_pit(t)) { if (Blind && !Deaf) diff --git a/src/do_wear.c b/src/do_wear.c index 414f5a522..9925ceaf0 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1937,20 +1937,6 @@ struct monst *victim; return(otmph); } -/* erode some arbitrary armor worn by the victim */ -void -erode_armor(victim, acid_dmg) -struct monst *victim; -boolean acid_dmg; -{ - struct obj *otmph = some_armor(victim); - - if (otmph && (otmph != uarmf)) { - (void) erode_obj(otmph, acid_dmg ? 3 : 1, FALSE, FALSE); - if (carried(otmph)) update_inventory(); - } -} - /* used for praying to check and fix levitation trouble */ struct obj * stuck_ring(ring, otyp) diff --git a/src/dokick.c b/src/dokick.c index 06ff075e6..c399f6bbc 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -983,7 +983,7 @@ dokick() if(!rn2(3)) goto ouch; /* make metal boots rust */ if(uarmf && rn2(3)) - if (!rust_dmg(uarmf, "metal boots", 1, FALSE)) { + if (!water_damage(uarmf, "metal boots", TRUE)) { Your("boots get wet."); /* could cause short-lived fumbling here */ } diff --git a/src/fountain.c b/src/fountain.c index f167c09d4..cc8aeb7bf 100644 --- a/src/fountain.c +++ b/src/fountain.c @@ -136,7 +136,7 @@ genericptr_t poolcnt; levl[x][y].typ = POOL; /* No kelp! */ del_engr_at(x, y); - water_damage(&level.objects[x][y], FALSE, TRUE); + water_damage_chain(level.objects[x][y], TRUE); if ((mtmp = m_at(x, y)) != 0) (void) minliquid(mtmp); diff --git a/src/mhitm.c b/src/mhitm.c index 47a14915f..ae66279e7 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -883,7 +883,7 @@ mdamagem(magr, mdef, mattk) pline("%s is covered in acid!", Monnam(mdef)); pline("It burns %s!", mon_nam(mdef)); } - if (!rn2(30)) erode_armor(mdef, TRUE); + if (!rn2(30)) erode_armor(mdef, ERODE_CORRODE); if (!rn2(6)) (void) erode_obj(MON_WEP(mdef), 3, TRUE, FALSE); break; case AD_RUST: @@ -897,13 +897,13 @@ mdamagem(magr, mdef, mattk) return (MM_DEF_DIED | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED)); } - hurtmarmor(mdef, AD_RUST); + erode_armor(mdef, ERODE_RUST); mdef->mstrategy &= ~STRAT_WAITFORU; tmp = 0; break; case AD_CORR: if (magr->mcan) break; - hurtmarmor(mdef, AD_CORR); + erode_armor(mdef, ERODE_CORRODE); mdef->mstrategy &= ~STRAT_WAITFORU; tmp = 0; break; @@ -919,7 +919,7 @@ mdamagem(magr, mdef, mattk) return (MM_DEF_DIED | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED)); } - hurtmarmor(mdef, AD_DCAY); + erode_armor(mdef, ERODE_CORRODE); mdef->mstrategy &= ~STRAT_WAITFORU; tmp = 0; break; @@ -1361,7 +1361,7 @@ int mdead; tmp = 0; } } else tmp = 0; - if (!rn2(30)) erode_armor(magr, TRUE); + if (!rn2(30)) erode_armor(magr, ERODE_CORRODE); if (!rn2(6)) (void)erode_obj(MON_WEP(magr), 3, TRUE, FALSE); goto assess_dmg; case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ diff --git a/src/mhitu.c b/src/mhitu.c index 416edaa5b..cc9b6f1be 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -22,7 +22,6 @@ STATIC_DCL void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *)); STATIC_DCL void FDECL(mswings,(struct monst *,struct obj *)); STATIC_DCL void FDECL(wildmiss, (struct monst *,struct attack *)); -STATIC_DCL void FDECL(hurtarmor,(int)); STATIC_DCL void FDECL(hitmsg,(struct monst *,struct attack *)); /* See comment in mhitm.c. If we use this a lot it probably should be */ @@ -714,67 +713,6 @@ mattacku(mtmp) return(0); } -/* - * helper function for some compilers that have trouble with hitmu - */ - -STATIC_OVL void -hurtarmor(attk) -int attk; -{ - int hurt; - - switch(attk) { - /* 0 is burning, which we should never be called with */ - case AD_RUST: hurt = 1; break; - case AD_CORR: hurt = 3; break; - default: hurt = 2; break; - } - - /* What the following code does: it keeps looping until it - * finds a target for the rust monster. - * Head, feet, etc... not covered by metal, or covered by - * rusty metal, are not targets. However, your body always - * is, no matter what covers it. - */ - while (1) { - switch(rn2(5)) { - case 0: - if (!uarmh || !rust_dmg(uarmh, xname(uarmh), hurt, FALSE)) - continue; - break; - case 1: - if (uarmc) { - (void)rust_dmg(uarmc, xname(uarmc), hurt, TRUE); - break; - } - /* Note the difference between break and continue; - * break means it was hit and didn't rust; continue - * means it wasn't a target and though it didn't rust - * something else did. - */ - if (uarm) - (void)rust_dmg(uarm, xname(uarm), hurt, TRUE); - else if (uarmu) - (void)rust_dmg(uarmu, xname(uarmu), hurt, TRUE); - break; - case 2: - if (!uarms || !rust_dmg(uarms, xname(uarms), hurt, FALSE)) - continue; - break; - case 3: - if (!uarmg || !rust_dmg(uarmg, xname(uarmg), hurt, FALSE)) - continue; - break; - case 4: - if (!uarmf || !rust_dmg(uarmf, xname(uarmf), hurt, FALSE)) - continue; - break; - } - break; /* Out of while loop */ - } -} - STATIC_OVL boolean diseasemu(mdat) struct permonst *mdat; @@ -1336,12 +1274,12 @@ dopois: rehumanize(); break; } - hurtarmor(AD_RUST); + erode_armor(&youmonst, ERODE_RUST); break; case AD_CORR: hitmsg(mtmp, mattk); if (mtmp->mcan) break; - hurtarmor(AD_CORR); + erode_armor(&youmonst, ERODE_CORRODE); break; case AD_DCAY: hitmsg(mtmp, mattk); @@ -1353,7 +1291,7 @@ dopois: rehumanize(); break; } - hurtarmor(AD_DCAY); + erode_armor(&youmonst, ERODE_ROT); break; case AD_HEAL: /* a cancelled nurse is just an ordinary monster, @@ -2503,7 +2441,7 @@ register struct attack *mattk; tmp = 0; } } else tmp = 0; - if (!rn2(30)) erode_armor(mtmp, TRUE); + if (!rn2(30)) erode_armor(mtmp, ERODE_CORRODE); if (!rn2(6)) (void)erode_obj(MON_WEP(mtmp), 3, TRUE, FALSE); goto assess_dmg; case AD_STON: /* cockatrice */ diff --git a/src/mon.c b/src/mon.c index f617dad4c..1c2009a0b 100644 --- a/src/mon.c +++ b/src/mon.c @@ -333,7 +333,7 @@ register struct monst *mtmp; if (mtmp->data == &mons[PM_GREMLIN] && (inpool || infountain) && rn2(3)) { if (split_mon(mtmp, (struct monst *)0)) dryup(mtmp->mx, mtmp->my, FALSE); - if (inpool) water_damage(&mtmp->minvent, FALSE, FALSE); + if (inpool) water_damage_chain(mtmp->minvent, FALSE); return (0); } else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) { int dam = d(2,6); @@ -345,7 +345,7 @@ register struct monst *mtmp; mondead(mtmp); if (mtmp->mhp < 1) return (1); } - water_damage(&mtmp->minvent, FALSE, FALSE); + water_damage_chain(mtmp->minvent, FALSE); return (0); } @@ -398,7 +398,7 @@ register struct monst *mtmp; } mondead(mtmp); if (mtmp->mhp > 0) { - water_damage(&mtmp->minvent, FALSE, FALSE); + water_damage_chain(mtmp->minvent, FALSE); (void) rloc(mtmp, FALSE); return 0; } diff --git a/src/objnam.c b/src/objnam.c index 84c3599f4..fe692b226 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -2893,7 +2893,7 @@ wiztrap: del_engr_at(x, y); pline("A %s.", (lev->typ == POOL) ? "pool" : "moat"); /* Must manually make kelp! */ - water_damage(&level.objects[x][y], FALSE, TRUE); + water_damage_chain(level.objects[x][y], TRUE); newsym(x, y); return &zeroobj; } diff --git a/src/sit.c b/src/sit.c index e5e77aa42..19cd63471 100644 --- a/src/sit.c +++ b/src/sit.c @@ -113,9 +113,9 @@ dosit() in_water: You("sit in the water."); if (!rn2(10) && uarm) - (void) rust_dmg(uarm, "armor", 1, TRUE); + (void) water_damage(uarm, "armor", TRUE); if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS) - (void) rust_dmg(uarm, "armor", 1, TRUE); + (void) water_damage(uarm, "armor", TRUE); } else if(IS_SINK(typ)) { You(sit_message, defsyms[S_sink].explanation); Your("%s gets wet.", humanoid(youmonst.data) ? "rump" : "underside"); diff --git a/src/trap.c b/src/trap.c index 1220105f5..f6266791f 100644 --- a/src/trap.c +++ b/src/trap.c @@ -55,7 +55,7 @@ struct monst *victim; int mat_idx; if (!victim) return 0; -#define burn_dmg(obj,descr) rust_dmg(obj, descr, 0, FALSE) +#define burn_dmg(obj,descr) rust_dmg(obj, descr, ERODE_BURN, TRUE, FALSE) while (1) { switch (rn2(5)) { case 0: @@ -102,20 +102,21 @@ struct monst *victim; } /* Generic erode-item function. Returns TRUE if any change in state - * occurred. "print", if set, means to print a message even if no change - * occurs. + * occurred, or if grease protected the item. + * "check_grease", if FALSE, means that grease is not checked for + * "print", if set, means to print a message even if no change occurs. */ boolean -rust_dmg(otmp, ostr, type, print) +rust_dmg(otmp, ostr, type, check_grease, print) register struct obj *otmp; register const char *ostr; int type; +boolean check_grease; boolean print; { static NEARDATA const char * const action[] = { "smoulder", "rust", "rot", "corrode" }; static NEARDATA const char * const msg[] = { "burnt", "rusted", "rotten", "corroded" }; boolean vulnerable = FALSE; - boolean grprot = FALSE; boolean is_primary = TRUE; int erosion; struct monst *victim; @@ -133,18 +134,18 @@ boolean print; switch(type) { case ERODE_BURN: vulnerable = is_flammable(otmp); + check_grease = FALSE; break; case ERODE_RUST: vulnerable = is_rustprone(otmp); - grprot = TRUE; break; case ERODE_ROT: vulnerable = is_rottable(otmp); + check_grease = FALSE; is_primary = FALSE; break; case ERODE_CORRODE: vulnerable = is_corrodeable(otmp); - grprot = TRUE; is_primary = FALSE; break; default: @@ -156,8 +157,9 @@ boolean print; if (!ostr) ostr = cxname(otmp); - if (grprot && otmp->greased) { - return grease_protect(otmp, ostr, victim); + if (check_grease && otmp->greased) { + grease_protect(otmp, ostr, victim); + return TRUE; } else if (!vulnerable || (otmp->oerodeproof && otmp->rknown)) { if (print && flags.verbose) { if (victim == &youmonst) @@ -167,7 +169,7 @@ boolean print; vtense(ostr, "are")); } return FALSE; - } else if (otmp->oerodeproof || otmp->blessed && !rnl(4)) { + } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) { if (flags.verbose && (print || otmp->oerodeproof)) { if (victim == &youmonst) pline("Somehow, your %s %s not affected.", @@ -176,7 +178,7 @@ boolean print; pline("Somehow, %s's %s %s not affected.", mon_nam(victim), ostr, vtense(ostr, "are")); else if (visobj) - pline("Somehow, the %s %s not affected." ostr, + pline("Somehow, the %s %s not affected.", ostr, vtense(ostr, "are")); } /* We assume here that if the object is protected because it @@ -188,7 +190,7 @@ boolean print; return FALSE; } else if (erosion < MAX_ERODE) { const char *adverb = (erosion + 1 == MAX_ERODE) ? - " complete" : erosion ? " further" : ""; + " completely" : erosion ? " further" : ""; if (victim == &youmonst) Your("%s %s%s!", ostr, vtense(ostr, action[type]), adverb); @@ -931,18 +933,6 @@ unsigned trflags; case RUST_TRAP: seetrap(trap); - if (u.umonnum == PM_IRON_GOLEM) { - int dam = u.mhmax; - - pline("%s you!", A_gush_of_water_hits); - You("are covered with rust!"); - losehp(Maybe_Half_Phys(dam), "rusting away", KILLED_BY); - break; - } else if (u.umonnum == PM_GREMLIN && rn2(3)) { - pline("%s you!", A_gush_of_water_hits); - (void)split_mon(&youmonst, (struct monst *)0); - break; - } /* Unlike monsters, traps cannot aim their rust attacks at * you, so instead of looping through and taking either the @@ -953,18 +943,18 @@ unsigned trflags; case 0: pline("%s you on the %s!", A_gush_of_water_hits, body_part(HEAD)); - (void) rust_dmg(uarmh, helm_simple_name(uarmh), - 1, TRUE); + (void) water_damage(uarmh, helm_simple_name(uarmh), + TRUE); break; case 1: pline("%s your left %s!", A_gush_of_water_hits, body_part(ARM)); - if (rust_dmg(uarms, "shield", 1, TRUE)) + if (water_damage(uarms, "shield", TRUE)) break; if (u.twoweap || (uwep && bimanual(uwep))) (void) erode_obj(u.twoweap ? uswapwep : uwep, 1, TRUE, FALSE); -glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE); +glovecheck: (void) water_damage(uarmg, "gauntlets", TRUE); /* Not "metal gauntlets" since it gets called * even if it's leather for the message */ @@ -981,14 +971,26 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE); (otmp != uswapwep || !u.twoweap)) (void) snuff_lit(otmp); if (uarmc) - (void) rust_dmg(uarmc, cloak_simple_name(uarmc), - 1, TRUE); + (void) water_damage(uarmc, cloak_simple_name(uarmc), + TRUE); else if (uarm) - (void) rust_dmg(uarm, "armor", 1, TRUE); + (void) water_damage(uarm, "armor", TRUE); else if (uarmu) - (void) rust_dmg(uarmu, "shirt", 1, TRUE); + (void) water_damage(uarmu, "shirt", TRUE); } update_inventory(); + + if (u.umonnum == PM_IRON_GOLEM) { + int dam = u.mhmax; + + pline("%s you!", A_gush_of_water_hits); + You("are covered with rust!"); + losehp(Maybe_Half_Phys(dam), "rusting away", KILLED_BY); + } else if (u.umonnum == PM_GREMLIN && rn2(3)) { + pline("%s you!", A_gush_of_water_hits); + (void)split_mon(&youmonst, (struct monst *)0); + } + break; case FIRE_TRAP: @@ -2084,21 +2086,21 @@ register struct monst *mtmp; pline("%s %s on the %s!", A_gush_of_water_hits, mon_nam(mtmp), mbodypart(mtmp, HEAD)); target = which_armor(mtmp, W_ARMH); - (void) rust_dmg(target, helm_simple_name(target), - 1, TRUE); + (void) water_damage(target, helm_simple_name(target), + TRUE); break; case 1: if (in_sight) pline("%s %s's left %s!", A_gush_of_water_hits, mon_nam(mtmp), mbodypart(mtmp, ARM)); target = which_armor(mtmp, W_ARMS); - if (rust_dmg(target, "shield", 1, TRUE)) + if (water_damage(target, "shield", TRUE)) break; target = MON_WEP(mtmp); if (target && bimanual(target)) (void) erode_obj(target, 1, TRUE, FALSE); glovecheck: target = which_armor(mtmp, W_ARMG); - (void) rust_dmg(target, "gauntlets", 1, TRUE); + (void) water_damage(target, "gauntlets", TRUE); break; case 2: if (in_sight) @@ -2115,13 +2117,13 @@ glovecheck: target = which_armor(mtmp, W_ARMG); (otmp->owornmask & (W_WEP|W_SWAPWEP)) == 0) (void) snuff_lit(otmp); if ((target = which_armor(mtmp, W_ARMC)) != 0) - (void) rust_dmg(target, - cloak_simple_name(target), - 1, TRUE); + (void) water_damage(target, + cloak_simple_name(target), + TRUE); else if ((target = which_armor(mtmp, W_ARM)) != 0) - (void) rust_dmg(target, "armor", 1, TRUE); + (void) water_damage(target, "armor", TRUE); else if ((target = which_armor(mtmp, W_ARMU)) != 0) - (void) rust_dmg(target, "shirt", 1, TRUE); + (void) water_damage(target, "shirt", TRUE); } if (mptr == &mons[PM_IRON_GOLEM]) { @@ -3067,107 +3069,112 @@ xchar x, y; return retval; } -void -water_damage(objp, force, here) -struct obj **objp; -boolean force, here; +/* returns: + * 0 if obj is unaffected + * 1 if obj is protected by grease + * 2 if obj is changed but survived + * 3 if obj is destroyed + */ +int +water_damage(obj, ostr, force) +struct obj *obj; +const char *ostr; +boolean force; { - register struct obj *obj = *objp, *otmp; boolean loose_obj = (obj && obj->where == OBJ_FREE), exploded = FALSE; - if (loose_obj && (obj->nobj || obj->nexthere)) { - /* [this should actually be a panic()] */ - impossible("water_damage: loose object has%s%s%s list%s?", - obj->nobj ? " nobj" : "", - (obj->nobj && obj->nexthere) ? " and" : "", - obj->nexthere ? " nexthere" : "", - (obj->nobj && obj->nexthere) ? "s" : ""); - } - - /* Scrolls, spellbooks, potions, weapons and - pieces of armor may get affected by the water. - - [FIXME? The item transformations here lack shop price/billing - handling [costly_alteration()], which is okay as long as shops - don't contain any pools. However, that's probably not a valid - assumption; a broken fountain might spill new pools far enough - to put one inside a nearby shop, particularly if dug walls in - Minetown haven't been repaired yet. Note that water_damage() - might be getting called right now because we're in the midst - of creating such a pool, not just because one has already been - created and we've walked into it while carrying unpaid stuff.] - */ - for (; obj; obj = otmp) { - otmp = here ? obj->nexthere : obj->nobj; - - (void) snuff_lit(obj); - - if(obj->otyp == CAN_OF_GREASE && obj->spe > 0) { - continue; - } else if(obj->greased) { - if (force || !rn2(2)) obj->greased = 0; - } else if(Is_container(obj) && !Is_box(obj) && - (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) { - water_damage(&obj->cobj, force, FALSE); - } else if (!force && (Luck + 5) > rn2(20)) { - /* chance per item of sustaining damage: - * max luck: 10% - * avg luck (Luck==0): 75% - * awful luck (Luck<-4): 100% - */ - continue; - } else if (obj->oclass == SCROLL_CLASS) { + (void) snuff_lit(obj); + + if(obj->otyp == CAN_OF_GREASE && obj->spe > 0) { + return 0; + } else if(obj->greased) { + if (!rn2(2)) obj->greased = 0; + if (carried(obj)) update_inventory(); + return 1; + } else if(Is_container(obj) && !Is_box(obj) && + (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) { + water_damage_chain(obj->cobj, FALSE); + return 0; + } else if (!force && (Luck + 5) > rn2(20)) { + /* chance per item of sustaining damage: + * max luck: 10% + * avg luck (Luck==0): 75% + * awful luck (Luck<-4): 100% + */ + return 0; + } else if (obj->oclass == SCROLL_CLASS) { #ifdef MAIL - if (obj->otyp == SCR_MAIL) continue; + if (obj->otyp == SCR_MAIL) return 0; #endif - obj->otyp = SCR_BLANK_PAPER; - obj->dknown = 0; - obj->spe = 0; - } else if (obj->oclass == SPBOOK_CLASS) { - if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { - pline("Steam rises from %s.", the(xname(obj))); - continue; - } - obj->otyp = SPE_BLANK_PAPER; - obj->dknown = 0; - } else if (obj->oclass == POTION_CLASS) { - if (obj->otyp == POT_ACID) { - char *bufp, buf[BUFSZ]; - boolean one = (obj->quan == 1L); - - bufp = strcpy(buf, "potion"); - if (!one) bufp = makeplural(bufp); - /* [should we damage player/monster?] */ - pline("%s %s %s!", /* "A potion explodes!" */ - !exploded ? (one ? "A" : "Some") : - (one ? "Another" : "More"), - bufp, vtense(bufp, "explode")); - exploded = TRUE; - /* let caller know that obj has gone away - [when obj is part of a list, delobj()'s - obj_extract_self() takes care of this; - for loose_obj, obj should always equal - *objp and otmp should always be null] */ - if (loose_obj && obj == *objp) *objp = otmp; - delobj(obj); - continue; - } else if (obj->odiluted) { - obj->otyp = POT_WATER; - obj->dknown = 0; - obj->blessed = obj->cursed = 0; - obj->odiluted = 0; - } else if (obj->otyp != POT_WATER) - obj->odiluted++; - } else if (is_rustprone(obj) && obj->oeroded < MAX_ERODE && - !(obj->oerodeproof || (obj->blessed && !rnl(4)))) { - /* all metal stuff and armor except (body armor - protected by oilskin cloak) */ - if(obj->oclass != ARMOR_CLASS || obj != uarm || - !uarmc || uarmc->otyp != OILSKIN_CLOAK || - (uarmc->cursed && !rn2(3))) - obj->oeroded++; - } - } + obj->otyp = SCR_BLANK_PAPER; + obj->dknown = 0; + obj->spe = 0; + if (carried(obj)) + update_inventory(); + return 2; + } else if (obj->oclass == SPBOOK_CLASS) { + if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { + pline("Steam rises from %s.", the(xname(obj))); + return 0; + } + obj->otyp = SPE_BLANK_PAPER; + obj->dknown = 0; + if (carried(obj)) + update_inventory(); + return 2; + } else if (obj->oclass == POTION_CLASS) { + if (obj->otyp == POT_ACID) { + char *bufp, buf[BUFSZ]; + boolean one = (obj->quan == 1L); + boolean update = carried(obj); + + bufp = strcpy(buf, "potion"); + if (!one) bufp = makeplural(bufp); + /* [should we damage player/monster?] */ + pline("%s %s %s!", /* "A potion explodes!" */ + !exploded ? (one ? "A" : "Some") : + (one ? "Another" : "More"), + bufp, vtense(bufp, "explode")); + exploded = TRUE; + /* let caller know that obj has gone away + [when obj is part of a list, delobj()'s + obj_extract_self() takes care of this; + for loose_obj, obj should always equal + *objp and otmp should always be null] */ + delobj(obj); + if (update) + update_inventory(); + return 3; + } else if (obj->odiluted) { + obj->otyp = POT_WATER; + obj->dknown = 0; + obj->blessed = obj->cursed = 0; + obj->odiluted = 0; + if (carried(obj)) + update_inventory(); + return 2; + } else if (obj->otyp != POT_WATER) { + obj->odiluted++; + if (carried(obj)) + update_inventory(); + return 2; + } + } else { + return rust_dmg(obj, ostr, ERODE_RUST, FALSE, FALSE) ? 2 : 0; + } + return 0; +} + +void +water_damage_chain(obj,here) +struct obj *obj; +boolean here; +{ + struct obj *otmp; + for (; obj; obj = otmp) { + otmp = here ? obj->nexthere : obj->nobj; + water_damage(obj, NULL, FALSE); + } } /* @@ -3246,7 +3253,7 @@ drown() Hallucination ? "the Titanic" : "a rock"); } - water_damage(&invent, FALSE, FALSE); + water_damage_chain(invent, FALSE); if (u.umonnum == PM_GREMLIN && rn2(3)) (void)split_mon(&youmonst, (struct monst *)0); diff --git a/src/uhitm.c b/src/uhitm.c index 1ccb8a2cb..a0f90d3de 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -30,22 +30,13 @@ static boolean override_confirmation = FALSE; #define PROJECTILE(obj) ((obj) && is_ammo(obj)) -/* modified from hurtarmor() in mhitu.c */ -/* This is not static because it is also used for monsters rusting monsters */ void -hurtmarmor(mdef, attk) +erode_armor(mdef, hurt) struct monst *mdef; -int attk; +int hurt; { - int hurt; struct obj *target; - switch(attk) { - /* 0 is burning, which we should never be called with */ - case AD_RUST: hurt = 1; break; - case AD_CORR: hurt = 3; break; - default: hurt = 2; break; - } /* What the following code does: it keeps looping until it * finds a target for the rust monster. * Head, feet, etc... not covered by metal, or covered by @@ -56,34 +47,34 @@ int attk; switch(rn2(5)) { case 0: target = which_armor(mdef, W_ARMH); - if (!target || !rust_dmg(target, xname(target), hurt, FALSE)) + if (!target || !rust_dmg(target, xname(target), hurt, TRUE, FALSE)) continue; break; case 1: target = which_armor(mdef, W_ARMC); if (target) { - (void)rust_dmg(target, xname(target), hurt, TRUE); + (void)rust_dmg(target, xname(target), hurt, TRUE, TRUE); break; } if ((target = which_armor(mdef, W_ARM)) != (struct obj *)0) { - (void)rust_dmg(target, xname(target), hurt, TRUE); + (void)rust_dmg(target, xname(target), hurt, TRUE, TRUE); } else if ((target = which_armor(mdef, W_ARMU)) != (struct obj *)0) { - (void)rust_dmg(target, xname(target), hurt, TRUE); + (void)rust_dmg(target, xname(target), hurt, TRUE, TRUE); } break; case 2: target = which_armor(mdef, W_ARMS); - if (!target || !rust_dmg(target, xname(target), hurt, FALSE)) + if (!target || !rust_dmg(target, xname(target), hurt, TRUE, FALSE)) continue; break; case 3: target = which_armor(mdef, W_ARMG); - if (!target || !rust_dmg(target, xname(target), hurt, FALSE)) + if (!target || !rust_dmg(target, xname(target), hurt, TRUE, FALSE)) continue; break; case 4: target = which_armor(mdef, W_ARMF); - if (!target || !rust_dmg(target, xname(target), hurt, FALSE)) + if (!target || !rust_dmg(target, xname(target), hurt, TRUE, FALSE)) continue; break; } @@ -1536,11 +1527,11 @@ register struct attack *mattk; pline("%s falls to pieces!", Monnam(mdef)); xkilled(mdef,0); } - hurtmarmor(mdef, AD_RUST); + erode_armor(mdef, ERODE_RUST); tmp = 0; break; case AD_CORR: - hurtmarmor(mdef, AD_CORR); + erode_armor(mdef, ERODE_CORRODE); tmp = 0; break; case AD_DCAY: @@ -1549,7 +1540,7 @@ register struct attack *mattk; pline("%s falls to pieces!", Monnam(mdef)); xkilled(mdef,0); } - hurtmarmor(mdef, AD_DCAY); + erode_armor(mdef, ERODE_ROT); tmp = 0; break; case AD_DREN: @@ -2231,7 +2222,7 @@ boolean wep_was_destroyed; if(mhit && !mon->mcan) { if (aatyp == AT_KICK) { if (uarmf && !rn2(6)) - (void)rust_dmg(uarmf, xname(uarmf), 0, TRUE); + (void)rust_dmg(uarmf, xname(uarmf), ERODE_BURN, TRUE, TRUE); } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || aatyp == AT_MAGC || aatyp == AT_TUCH) passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); @@ -2246,12 +2237,12 @@ boolean wep_was_destroyed; if (!Acid_resistance) mdamageu(mon, tmp); - if(!rn2(30)) erode_armor(&youmonst, TRUE); + if(!rn2(30)) erode_armor(&youmonst, ERODE_CORRODE); } if (mhit) { if (aatyp == AT_KICK) { if (uarmf && !rn2(6)) - (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE); + (void)rust_dmg(uarmf, xname(uarmf), ERODE_CORRODE, TRUE, TRUE); } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || aatyp == AT_MAGC || aatyp == AT_TUCH) passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); @@ -2284,7 +2275,7 @@ boolean wep_was_destroyed; if(mhit && !mon->mcan) { if (aatyp == AT_KICK) { if (uarmf) - (void)rust_dmg(uarmf, xname(uarmf), 1, TRUE); + (void)rust_dmg(uarmf, xname(uarmf), ERODE_RUST, TRUE, TRUE); } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || aatyp == AT_MAGC || aatyp == AT_TUCH) passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); @@ -2294,7 +2285,7 @@ boolean wep_was_destroyed; if(mhit && !mon->mcan) { if (aatyp == AT_KICK) { if (uarmf) - (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE); + (void)rust_dmg(uarmf, xname(uarmf), ERODE_CORRODE, TRUE, TRUE); } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || aatyp == AT_MAGC || aatyp == AT_TUCH) passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); diff --git a/src/worn.c b/src/worn.c index 32bfe1003..a542f3be4 100644 --- a/src/worn.c +++ b/src/worn.c @@ -583,11 +583,28 @@ which_armor(mon, flag) struct monst *mon; long flag; { - register struct obj *obj; - - for(obj = mon->minvent; obj; obj = obj->nobj) - if (obj->owornmask & flag) return obj; - return((struct obj *)0); + if (mon == &youmonst) { + switch (flag) { + case W_ARM: return uarm; + case W_ARMC: return uarmc; + case W_ARMH: return uarmh; + case W_ARMS: return uarms; + case W_ARMG: return uarmg; + case W_ARMF: return uarmf; +#ifdef TOURIST + case W_ARMU: return uarmu; +#endif + default: + impossible("bad flag in which_armor"); + return 0; + } + } else { + register struct obj *obj; + + for(obj = mon->minvent; obj; obj = obj->nobj) + if (obj->owornmask & flag) return obj; + return((struct obj *)0); + } } /* remove an item of armor and then drop it */ diff --git a/src/zap.c b/src/zap.c index 03cbc6c52..2fb2396de 100644 --- a/src/zap.c +++ b/src/zap.c @@ -3396,7 +3396,7 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */ } tmp = d(nd,6); if (!rn2(6)) (void) erode_obj(MON_WEP(mon), 3, TRUE, FALSE); - if (!rn2(6)) erode_armor(mon, TRUE); + if (!rn2(6)) erode_armor(mon, ERODE_CORRODE); break; } if (sho_shieldeff) shieldeff(mon->mx, mon->my); @@ -3525,7 +3525,7 @@ xchar sx, sy; (void) erode_obj(uwep, 3, TRUE, FALSE); if (u.twoweap && !rn2(3)) (void) erode_obj(uswapwep, 3, TRUE, FALSE); - if (!rn2(6)) erode_armor(&youmonst, TRUE); + if (!rn2(6)) erode_armor(&youmonst, ERODE_CORRODE); break; } -- 2.40.0