-/* NetHack 3.6 dokick.c $NHDT-Date: 1517128663 2018/01/28 08:37:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.113 $ */
+/* NetHack 3.6 dokick.c $NHDT-Date: 1551920353 2019/03/07 00:59:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.131 $ */
/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
*/
static const char kick_passes_thru[] = "\8fR\82è\82Í\83_\83\81\81[\83W\82ð\97^\82¦\82¸\82É\82·\82è\94²\82¯\82½";
+/* kicking damage when not poly'd into a form with a kick attack */
STATIC_OVL void
kickdmg(mon, clumsy)
-register struct monst *mon;
-register boolean clumsy;
+struct monst *mon;
+boolean clumsy;
{
- register int mdx, mdy;
- register int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
- int kick_skill = P_NONE;
- int blessed_foot_damage = 0;
+ int mdx, mdy;
+ int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
+ int specialdmg, kick_skill = P_NONE;
boolean trapkilled = FALSE;
if (uarmf && uarmf->otyp == KICKING_BOOTS)
if (thick_skinned(mon->data))
dmg = 0;
- /* attacking a shade is useless */
+ /* attacking a shade is normally useless */
if (mon->data == &mons[PM_SHADE])
dmg = 0;
- if ((is_undead(mon->data) || is_demon(mon->data) || is_vampshifter(mon))
- && uarmf && uarmf->blessed)
- blessed_foot_damage = 1;
+ specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
- if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
+ if (mon->data == &mons[PM_SHADE] && !specialdmg) {
/*JP
pline_The("%s.", kick_passes_thru);
*/
return;
}
- if (mon->m_ap_type)
+ if (M_AP_TYPE(mon))
seemimic(mon);
check_caitiff(mon);
/* a good kick exercises your dex */
exercise(A_DEX, TRUE);
}
- if (blessed_foot_damage)
- dmg += rnd(4);
+ dmg += specialdmg; /* for blessed (or hypothetically, silver) boots */
if (uarmf)
dmg += uarmf->spe;
dmg += u.udaminc; /* add ring(s) of increase damage */
if (dmg > 0)
mon->mhp -= dmg;
- if (mon->mhp > 0 && martial() && !bigmonst(mon->data) && !rn2(3)
+ if (!DEADMONSTER(mon) && martial() && !bigmonst(mon->data) && !rn2(3)
&& mon->mcanmove && mon != u.ustuck && !mon->mtrapped) {
/* see if the monster has a place to move into */
mdx = mon->mx + u.dx;
}
}
- (void) passive(mon, uarmf, TRUE, mon->mhp > 0, AT_KICK, FALSE);
- if (mon->mhp <= 0 && !trapkilled)
+ (void) passive(mon, uarmf, TRUE, !DEADMONSTER(mon), AT_KICK, FALSE);
+ if (DEADMONSTER(mon) && !trapkilled)
killed(mon);
/* may bring up a dialog, so put this after all messages */
/* reveal hidden target even if kick ends up missing (note: being
hidden doesn't affect chance to hit so neither does this reveal) */
if (mon->mundetected
- || (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER)) {
- if (mon->m_ap_type)
+ || (M_AP_TYPE(mon) && M_AP_TYPE(mon) != M_AP_MONSTER)) {
+ if (M_AP_TYPE(mon))
seemimic(mon);
mon->mundetected = 0;
if (!canspotmon(mon))
*/
if (Upolyd && attacktype(youmonst.data, AT_KICK)) {
struct attack *uattk;
- int sum, kickdieroll, armorpenalty,
+ int sum, kickdieroll, armorpenalty, specialdmg,
attknum = 0,
tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum,
&armorpenalty);
if (uattk->aatyp != AT_KICK)
continue;
- if (mon->data == &mons[PM_SHADE] && (!uarmf || !uarmf->blessed)) {
+ kickdieroll = rnd(20);
+ specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
+ if (mon->data == &mons[PM_SHADE] && !specialdmg) {
/* doesn't matter whether it would have hit or missed,
and shades have no passive counterattack */
/*JP
*/
You("%s\82ð\8fR\82Á\82½\82ª\81C%s\81D", mon_nam(mon), kick_passes_thru);
break; /* skip any additional kicks */
- } else if (tmp > (kickdieroll = rnd(20))) {
+ } else if (tmp > kickdieroll) {
/*JP
You("kick %s.", mon_nam(mon));
*/
You("%s\82ð\8fR\82Á\82½\81D", mon_nam(mon));
- sum = damageum(mon, uattk);
+ sum = damageum(mon, uattk, specialdmg);
(void) passive(mon, uarmf, (boolean) (sum > 0),
(sum != 2), AT_KICK, FALSE);
if (sum == 2)
else if (uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
clumsy = TRUE;
-doit:
+ doit:
/*JP
You("kick %s.", mon_nam(mon));
*/
return 0;
if ((trap = t_at(x, y)) != 0) {
- if (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && !Passes_walls)
- || trap->ttyp == WEB) {
+ if ((is_pit(trap->ttyp) && !Passes_walls) || trap->ttyp == WEB) {
if (!trap->tseen)
find_trap(trap);
#if 0 /*JP:T*/
You_cant("kick %s that's in a %s!", something,
- Hallucination ? "tizzy" :
- (trap->ttyp == WEB) ? "web" : "pit");
+ Hallucination ? "tizzy"
+ : (trap->ttyp == WEB) ? "web"
+ : "pit");
#else
You("%s\82Å\82Í%s\82ð\8fR\82é\82±\82Æ\82ª\82Å\82«\82È\82¢\81I",
Hallucination ? "\8d¬\97\90\82µ\82½\8fó\91Ô" :
}
}
- /* range < 2 means the object will not move. */
- /* maybe dexterity should also figure here. */
- range = (int) ((ACURRSTR) / 2 - kickedobj->owt / 40);
+ isgold = (kickedobj->oclass == COIN_CLASS);
+ {
+ int k_owt = (int) kickedobj->owt;
+
+ /* for non-gold stack, 1 item will be split off below (unless an
+ early return occurs, so we aren't moving the split to here);
+ calculate the range for that 1 rather than for the whole stack */
+ if (kickedobj->quan > 1L && !isgold) {
+ long save_quan = kickedobj->quan;
+
+ kickedobj->quan = 1L;
+ k_owt = weight(kickedobj);
+ kickedobj->quan = save_quan;
+ }
+
+ /* range < 2 means the object will not move
+ (maybe dexterity should also figure here) */
+ range = ((int) ACURRSTR) / 2 - k_owt / 40;
+ }
if (martial())
range += rnd(3);
costly = (!(kickedobj->no_charge && !Has_contents(kickedobj))
&& (shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0
&& costly_spot(x, y));
- isgold = (kickedobj->oclass == COIN_CLASS);
if (IS_ROCK(levl[x][y].typ) || closed_door(x, y)) {
if ((!martial() && rn2(20) > ACURR(A_DEX))
kick_monster(mtmp, x, y);
glyph = glyph_at(x, y);
/* see comment in attack_checks() */
- if (mtmp->mhp <= 0) { /* DEADMONSTER() */
+ if (DEADMONSTER(mtmp)) { /* DEADMONSTER() */
/* if we mapped an invisible monster and immediately
killed it, we don't want to forget what we thought
was there before the kick */
/*JP
You("splash some %s around.", hliquid("water"));
*/
- You("%s\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D", hliquid("water"));
+ You("%s\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D", hliquid("\90\85"));
return 1;
}
|| IS_STWALL(maploc->typ)) {
if (!IS_STWALL(maploc->typ) && maploc->ladder == LA_DOWN)
goto dumb;
- ouch:
+ ouch:
/*JP
pline("Ouch! That hurts!");
*/
if (maploc->doormask == D_ISOPEN || maploc->doormask == D_BROKEN
|| maploc->doormask == D_NODOOR) {
- dumb:
+ dumb:
exercise(A_DEX, FALSE);
if (martial() || ACURR(A_DEX) >= 16 || rn2(3)) {
/*JP
obj_extract_self(obj);
if (costly) {
- price += stolen_value(
- obj, x, y, (costly_spot(u.ux, u.uy)
- && index(u.urooms, *in_rooms(x, y, SHOPBASE))),
- TRUE);
+ price += stolen_value(obj, x, y,
+ (costly_spot(u.ux, u.uy)
+ && index(u.urooms,
+ *in_rooms(x, y, SHOPBASE))),
+ TRUE);
/* set obj->no_charge to 0 */
if (Has_contents(obj))
picked_container(obj); /* does the right thing */
/* boulders never fall through trap doors, but they might knock
other things down before plugging the hole */
if (otmp->otyp == BOULDER && ((t = t_at(x, y)) != 0)
- && (t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
+ && is_hole(t->ttyp)) {
if (impact)
impact_drop(otmp, x, y, 0);
return FALSE; /* let caller finish the drop */
continue;
where = (int) (otmp->owornmask & 0x7fffL); /* destination code */
+ if ((where & MIGR_TO_SPECIES) != 0)
+ continue;
+
nobreak = (where & MIGR_NOBREAK) != 0;
noscatter = (where & MIGR_WITH_HERO) != 0;
where &= ~(MIGR_NOBREAK | MIGR_NOSCATTER);
stackobj(otmp);
if (!noscatter)
(void) scatter(nx, ny, rnd(2), 0, otmp);
+ else
+ newsym(nx, ny);
} else { /* random location */
/* set dummy coordinates because there's no
current position for rloco() to update */
}
}
+void
+deliver_obj_to_mon(mtmp, cnt, deliverflags)
+int cnt;
+struct monst *mtmp;
+unsigned long deliverflags;
+{
+ struct obj *otmp, *otmp2;
+ int where, maxobj = 1;
+ boolean at_crime_scene = In_mines(&u.uz);
+
+ if ((deliverflags & DF_RANDOM) && cnt > 1)
+ maxobj = rnd(cnt);
+ else if (deliverflags & DF_ALL)
+ maxobj = 0;
+ else
+ maxobj = 1;
+
+ cnt = 0;
+ for (otmp = migrating_objs; otmp; otmp = otmp2) {
+ otmp2 = otmp->nobj;
+ where = (int) (otmp->owornmask & 0x7fffL); /* destination code */
+ if ((where & MIGR_TO_SPECIES) == 0)
+ continue;
+
+ if ((mtmp->data->mflags2 & otmp->corpsenm) != 0) {
+ obj_extract_self(otmp);
+ otmp->owornmask = 0L;
+ otmp->ox = otmp->oy = 0;
+
+ /* special treatment for orcs and their kind */
+ if ((otmp->corpsenm & M2_ORC) != 0 && has_oname(otmp)) {
+ if (!has_mname(mtmp)) {
+ if (at_crime_scene || !rn2(2))
+ mtmp = christen_orc(mtmp,
+ at_crime_scene ? ONAME(otmp)
+ : (char *) 0,
+ /* bought the stolen goods */
+ " the Fence");
+ }
+ free_oname(otmp);
+ }
+ otmp->corpsenm = 0;
+ (void) add_to_minv(mtmp, otmp);
+ cnt++;
+ if (maxobj && cnt >= maxobj)
+ break;
+ /* getting here implies DF_ALL */
+ }
+ }
+}
+
STATIC_OVL void
otransit_msg(otmp, nodrop, num)
register struct obj *otmp;
register boolean nodrop;
long num;
{
- char obuf[BUFSZ];
+ char *optr = 0, obuf[BUFSZ], xbuf[BUFSZ];
#if 0 /*JP*/
- Sprintf(obuf, "%s%s",
- (otmp->otyp == CORPSE && type_is_pname(&mons[otmp->corpsenm]))
- ? ""
- : "The ",
- cxname(otmp));
+ if (otmp->otyp == CORPSE) {
+ /* Tobjnam() calls xname() and would yield "The corpse";
+ we want more specific "The newt corpse" or "Medusa's corpse" */
+ optr = upstart(corpse_xname(otmp, (char *) 0, CXN_PFX_THE));
+ } else {
+ optr = Tobjnam(otmp, (char *) 0);
+ }
+ Strcpy(obuf, optr);
#else
Sprintf(obuf, "%s\82Í", xname(otmp));
#endif
if (num) { /* means: other objects are impacted */
+ /* 3.6.2: use a separate buffer for the suffix to avoid risk of
+ overrunning obuf[] (let pline() handle truncation if necessary) */
#if 0 /*JP*/
- Sprintf(eos(obuf), " %s %s object%s", otense(otmp, "hit"),
- num == 1L ? "another" : "other", num > 1L ? "s" : "");
+ Sprintf(xbuf, " %s %s object%s", otense(otmp, "hit"),
+ (num == 1L) ? "another" : "other", (num > 1L) ? "s" : "");
if (nodrop)
- Sprintf(eos(obuf), ".");
+ Sprintf(eos(xbuf), ".");
else
- Sprintf(eos(obuf), " and %s %s.", otense(otmp, "fall"), gate_str);
+ Sprintf(eos(xbuf), " and %s %s.", otense(otmp, "fall"), gate_str);
#else
- Sprintf(eos(obuf), "\91¼\82Ì\95¨\91Ì\82É\96½\92\86\82µ\82Ä");
+ Sprintf(xbuf, "\91¼\82Ì\95¨\91Ì\82É\96½\92\86\82µ\82Ä");
if(nodrop)
- Sprintf(eos(obuf), "\8e~\82Ü\82Á\82½\81D");
+ Sprintf(eos(xbuf), "\8e~\82Ü\82Á\82½\81D");
else
- Sprintf(eos(obuf), "%s\97\8e\82¿\82½\81D", gate_str);
+ Sprintf(eos(xbuf), "%s\97\8e\82¿\82½\81D", gate_str);
#endif
- pline1(obuf);
+ pline("%s%s", obuf, xbuf);
} else if (!nodrop)
/*JP
pline("%s %s %s.", obuf, otense(otmp, "fall"), gate_str);
}
if (((ttmp = t_at(x, y)) != 0 && ttmp->tseen)
- && (ttmp->ttyp == TRAPDOOR || ttmp->ttyp == HOLE)) {
+ && is_hole(ttmp->ttyp)) {
#if 0 /*JP*/
gate_str = (ttmp->ttyp == TRAPDOOR) ? "through the trap door"
: "through the hole";