multishot by monsters, plus reformatting

Some reformatting of the recently added pet ranged attack code.

The redundant--but different--multishot volley code has been replaced
so that there are only two versions (hero and monster) instead of
three (hero and monster vs hero and pet vs other monster).  The monst
version was out of date relative to post-3.4.3 changes to the hero one.
The pet version was way out of date and had some bugs:  wielding an
elven bow gave a +1 multishot increment to volley count for fast weapon
even when throwing something rather than shooting arrows, wielding any
weapon which had at least +2 enchantment gave 1/3 enchantment bonus to
volley count when throwing instead of shooting shoot ammo, and a pet
which got killed in the midst of a multishot volley--perhaps by a gas
spore explosion or some other passive counterattack--would keep on
shooting/throwing until the volley count was exhausted.

Pet use of ranged weapons is not ready for prime-time.  Pets don't
hang on to missiles or launchers+ammo, they just drop them if there is
no target immediately available.
This commit is contained in:
PatR
2016-06-06 17:42:58 -07:00
parent e276540230
commit 8c0810f687
5 changed files with 333 additions and 367 deletions

View File

@@ -8,11 +8,9 @@
STATIC_VAR NEARDATA struct obj *otmp;
STATIC_DCL boolean FDECL(u_slip_free, (struct monst *, struct attack *));
STATIC_DCL int FDECL(passiveum,
(struct permonst *, struct monst *, struct attack *));
STATIC_DCL int FDECL(passiveum, (struct permonst *, struct monst *,
struct attack *));
STATIC_DCL void FDECL(mayberem, (struct obj *, const char *));
STATIC_DCL boolean FDECL(diseasemu, (struct permonst *));
STATIC_DCL int FDECL(hitmu, (struct monst *, struct attack *));
STATIC_DCL int FDECL(gulpmu, (struct monst *, struct attack *));
@@ -20,7 +18,6 @@ STATIC_DCL int FDECL(explmu, (struct monst *, struct attack *, BOOLEAN_P));
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(hitmsg, (struct monst *, struct attack *));
/* See comment in mhitm.c. If we use this a lot it probably should be */
@@ -33,41 +30,48 @@ register struct monst *mtmp;
register struct attack *mattk;
{
int compat;
const char *pfmt = 0;
char *Monst_name = Monnam(mtmp);
/* Note: if opposite gender, "seductively" */
/* If same gender, "engagingly" for nymph, normal msg for others */
if ((compat = could_seduce(mtmp, &youmonst, mattk)) && !mtmp->mcan
&& !mtmp->mspec_used) {
pline("%s %s you %s.", Monnam(mtmp), Blind ? "talks to" : "smiles at",
compat == 2 ? "engagingly" : "seductively");
} else
if ((compat = could_seduce(mtmp, &youmonst, mattk)) != 0
&& !mtmp->mcan && !mtmp->mspec_used) {
pline("%s %s you %s.", Monst_name,
Blind ? "talks to" : "smiles at",
(compat == 2) ? "engagingly" : "seductively");
} else {
switch (mattk->aatyp) {
case AT_BITE:
pline("%s bites!", Monnam(mtmp));
pfmt = "%s bites!";
break;
case AT_KICK:
pline("%s kicks%c", Monnam(mtmp),
pline("%s kicks%c", Monst_name,
thick_skinned(youmonst.data) ? '.' : '!');
break;
case AT_STNG:
pline("%s stings!", Monnam(mtmp));
pfmt = "%s stings!";
break;
case AT_BUTT:
pline("%s butts!", Monnam(mtmp));
pfmt = "%s butts!";
break;
case AT_TUCH:
pline("%s touches you!", Monnam(mtmp));
pfmt = "%s touches you!";
break;
case AT_TENT:
pline("%s tentacles suck you!", s_suffix(Monnam(mtmp)));
pfmt = "%s tentacles suck you!";
Monst_name = s_suffix(Monst_name);
break;
case AT_EXPL:
case AT_BOOM:
pline("%s explodes!", Monnam(mtmp));
pfmt = "%s explodes!";
break;
default:
pline("%s hits!", Monnam(mtmp));
pfmt = "%s hits!";
}
if (pfmt)
pline(pfmt, Monst_name);
}
}
/* monster missed you */
@@ -139,6 +143,7 @@ register struct monst *mtmp;
register struct attack *mattk;
{
int compat;
const char *Monst_name; /* Monnam(mtmp) */
/* no map_invisible() -- no way to tell where _this_ is coming from */
@@ -150,42 +155,41 @@ register struct attack *mattk;
compat = ((mattk->adtyp == AD_SEDU || mattk->adtyp == AD_SSEX)
&& could_seduce(mtmp, &youmonst, (struct attack *) 0));
Monst_name = Monnam(mtmp);
if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) {
const char *swings =
mattk->aatyp == AT_BITE
? "snaps"
: mattk->aatyp == AT_KICK
? "kicks"
: (mattk->aatyp == AT_STNG || mattk->aatyp == AT_BUTT
|| nolimbs(mtmp->data))
? "lunges"
: "swings";
const char *swings = (mattk->aatyp == AT_BITE) ? "snaps"
: (mattk->aatyp == AT_KICK) ? "kicks"
: (mattk->aatyp == AT_STNG
|| mattk->aatyp == AT_BUTT
|| nolimbs(mtmp->data)) ? "lunges"
: "swings";
if (compat)
pline("%s tries to touch you and misses!", Monnam(mtmp));
pline("%s tries to touch you and misses!", Monst_name);
else
switch (rn2(3)) {
case 0:
pline("%s %s wildly and misses!", Monnam(mtmp), swings);
pline("%s %s wildly and misses!", Monst_name, swings);
break;
case 1:
pline("%s attacks a spot beside you.", Monnam(mtmp));
pline("%s attacks a spot beside you.", Monst_name);
break;
case 2:
pline("%s strikes at %s!", Monnam(mtmp),
levl[mtmp->mux][mtmp->muy].typ == WATER ? "empty water"
: "thin air");
pline("%s strikes at %s!", Monst_name,
(levl[mtmp->mux][mtmp->muy].typ == WATER)
? "empty water"
: "thin air");
break;
default:
pline("%s %s wildly!", Monnam(mtmp), swings);
pline("%s %s wildly!", Monst_name, swings);
break;
}
} else if (Displaced) {
if (compat)
pline("%s smiles %s at your %sdisplaced image...", Monnam(mtmp),
compat == 2 ? "engagingly" : "seductively",
pline("%s smiles %s at your %sdisplaced image...", Monst_name,
(compat == 2) ? "engagingly" : "seductively",
Invis ? "invisible " : "");
else
pline("%s strikes at your %sdisplaced image and misses you!",
@@ -194,20 +198,20 @@ register struct attack *mattk;
* displaced image, since the displaced image is also
* invisible.
*/
Monnam(mtmp), Invis ? "invisible " : "");
Monst_name, Invis ? "invisible " : "");
} else if (Underwater) {
/* monsters may miss especially on water level where
bubbles shake the player here and there */
if (compat)
pline("%s reaches towards your distorted image.", Monnam(mtmp));
pline("%s reaches towards your distorted image.", Monst_name);
else
pline("%s is fooled by water reflections and misses!",
Monnam(mtmp));
Monst_name);
} else
impossible("%s attacks you without knowing your location?",
Monnam(mtmp));
Monst_name);
}
void
@@ -217,9 +221,9 @@ struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */
boolean message;
{
if (message) {
if (is_animal(mdat))
if (is_animal(mdat)) {
You("get regurgitated!");
else {
} else {
char blast[40];
register int i;
@@ -227,9 +231,9 @@ boolean message;
for (i = 0; i < NATTK; i++)
if (mdat->mattk[i].aatyp == AT_ENGL)
break;
if (mdat->mattk[i].aatyp != AT_ENGL)
if (mdat->mattk[i].aatyp != AT_ENGL) {
impossible("Swallower has no engulfing attack?");
else {
} else {
if (is_whirly(mdat)) {
switch (mdat->mattk[i].adtyp) {
case AD_ELEC:
@@ -306,11 +310,10 @@ struct attack *alt_attk_buf;
&& !(mptr->mattk[1].aatyp == AT_WEAP
&& mptr->mattk[1].adtyp == AD_PHYS)
&& (magr->mcan
|| (weap
&& ((weap->otyp == CORPSE
&& touch_petrifies(&mons[weap->corpsenm]))
|| weap->oartifact == ART_STORMBRINGER
|| weap->oartifact == ART_VORPAL_BLADE)))) {
|| (weap && ((weap->otyp == CORPSE
&& touch_petrifies(&mons[weap->corpsenm]))
|| weap->oartifact == ART_STORMBRINGER
|| weap->oartifact == ART_VORPAL_BLADE)))) {
*alt_attk_buf = *attk;
attk = alt_attk_buf;
attk->adtyp = AD_PHYS;
@@ -1157,7 +1160,8 @@ register struct attack *mattk;
break;
case AD_LEGS: {
register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left";
const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left",
*Monst_name = Monnam(mtmp), *leg = body_part(LEG);
/* This case is too obvious to ignore, but Nethack is not in
* general very good at considering height--most short monsters
@@ -1165,31 +1169,30 @@ register struct attack *mattk;
* [FIXME: why can't a flying attacker overcome this?]
*/
if (u.usteed || Levitation || Flying) {
pline("%s tries to reach your %s %s!", Monnam(mtmp), sidestr,
body_part(LEG));
pline("%s tries to reach your %s %s!", Monst_name, sidestr, leg);
dmg = 0;
} else if (mtmp->mcan) {
pline("%s nuzzles against your %s %s!", Monnam(mtmp), sidestr,
body_part(LEG));
pline("%s nuzzles against your %s %s!", Monnam(mtmp),
sidestr, leg);
dmg = 0;
} else {
if (uarmf) {
if (rn2(2) && (uarmf->otyp == LOW_BOOTS
|| uarmf->otyp == IRON_SHOES))
|| uarmf->otyp == IRON_SHOES)) {
pline("%s pricks the exposed part of your %s %s!",
Monnam(mtmp), sidestr, body_part(LEG));
else if (!rn2(5))
pline("%s pricks through your %s boot!", Monnam(mtmp),
Monst_name, sidestr, leg);
} else if (!rn2(5)) {
pline("%s pricks through your %s boot!", Monst_name,
sidestr);
else {
pline("%s scratches your %s boot!", Monnam(mtmp),
} else {
pline("%s scratches your %s boot!", Monst_name,
sidestr);
dmg = 0;
break;
}
} else
pline("%s pricks your %s %s!", Monnam(mtmp), sidestr,
body_part(LEG));
pline("%s pricks your %s %s!", Monst_name, sidestr, leg);
set_wounded_legs(side, rnd(60 - ACURR(A_DEX)));
exercise(A_STR, FALSE);
exercise(A_DEX, FALSE);
@@ -1308,12 +1311,11 @@ register struct attack *mattk;
(void) rloc(mtmp, TRUE);
return 3;
} else if (mtmp->mcan) {
if (!Blind) {
if (!Blind)
pline("%s tries to %s you, but you seem %s.",
Adjmonnam(mtmp, "plain"),
flags.female ? "charm" : "seduce",
flags.female ? "unaffected" : "uninterested");
}
if (rn2(3)) {
if (!tele_restrict(mtmp))
(void) rloc(mtmp, TRUE);
@@ -1705,6 +1707,7 @@ register struct attack *mattk;
newsym(mtmp->mx, mtmp->my);
if (is_animal(mtmp->data) && u.usteed) {
char buf[BUFSZ];
/* Too many quirks presently if hero and steed
* are swallowed. Pretend purple worms don't
* like horses for now :-)