A lot more cleanup to rust and water.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 *));
|
||||
|
||||
3
src/do.c
3
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
10
src/mhitm.c
10
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) */
|
||||
|
||||
70
src/mhitu.c
70
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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
279
src/trap.c
279
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" : "");
|
||||
}
|
||||
(void) snuff_lit(obj);
|
||||
|
||||
/* 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) {
|
||||
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);
|
||||
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] */
|
||||
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++;
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
43
src/uhitm.c
43
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]));
|
||||
|
||||
25
src/worn.c
25
src/worn.c
@@ -583,11 +583,28 @@ which_armor(mon, flag)
|
||||
struct monst *mon;
|
||||
long flag;
|
||||
{
|
||||
register struct obj *obj;
|
||||
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);
|
||||
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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user