Snickersnee can hit at a distance once per turn for free

Once per turn, Snickersnee can be used to hit at a distance,
similar to a polearm, without taking any time.

Breaks saves.
This commit is contained in:
Pasi Kallinen
2025-05-12 20:23:43 +03:00
parent 8ac31b24f6
commit 035cd4377f
7 changed files with 38 additions and 4 deletions

View File

@@ -33,6 +33,7 @@ staticfn int use_stone(struct obj *);
staticfn int set_trap(void); /* occupation callback */
staticfn void display_polearm_positions(boolean);
staticfn void calc_pole_range(int *, int *);
staticfn boolean snickersnee_used_dist_attk(struct obj *);
staticfn int use_cream_pie(struct obj *);
staticfn int jelly_ok(struct obj *);
staticfn int use_royal_jelly(struct obj **);
@@ -3403,6 +3404,16 @@ could_pole_mon(void)
return FALSE;
}
/* was Snickersnee used to attack at distance this turn already? */
staticfn boolean
snickersnee_used_dist_attk(struct obj *obj)
{
if (obj && obj == uwep && u_wield_art(ART_SNICKERSNEE)
&& svc.context.snickersnee_turn == svm.moves)
return TRUE;
return FALSE;
}
/* Distance attacks by pole-weapons */
int
use_pole(struct obj *obj, boolean autohit)
@@ -3412,6 +3423,7 @@ use_pole(struct obj *obj, boolean autohit)
coord cc;
struct monst *mtmp;
struct monst *hitm = svc.context.polearm.hitmon;
boolean freehit = FALSE;
/* Are you allowed to use the pole? */
if (u.uswallow) {
@@ -3480,8 +3492,25 @@ use_pole(struct obj *obj, boolean autohit)
if (overexertion())
return ECMD_TIME; /* burn nutrition; maybe pass out */
svc.context.polearm.hitmon = mtmp;
if (snickersnee_used_dist_attk(obj)) {
pline_The("blade doesn't reach there!");
return ECMD_FAIL;
}
check_caitiff(mtmp);
gn.notonhead = (gb.bhitpos.x != mtmp->mx || gb.bhitpos.y != mtmp->my);
/* Snickersnee allows one free hit from a distance per turn */
if (obj == uwep && u_wield_art(ART_SNICKERSNEE)) {
freehit = (svm.moves != svc.context.snickersnee_turn);
svc.context.snickersnee_turn = svm.moves;
if (freehit && !Deaf) {
Soundeffect(se_sword_blade_rings, 100);
pline("Shkinng!"); /* /sha-kin!/ */
}
}
(void) thitmonst(mtmp, uwep);
} else if (glyph_is_statue(glyph) /* might be hallucinatory */
&& sobj_at(STATUE, gb.bhitpos.x, gb.bhitpos.y)) {
@@ -3523,7 +3552,7 @@ use_pole(struct obj *obj, boolean autohit)
}
}
u_wipe_engr(2); /* same as for melee or throwing */
return ECMD_TIME;
return freehit ? ECMD_OK : ECMD_TIME;
}
#undef glyph_is_poleable

View File

@@ -123,7 +123,7 @@ setuwep(struct obj *obj)
if (obj) {
gu.unweapon = (obj->oclass == WEAPON_CLASS)
? is_launcher(obj) || is_ammo(obj) || is_missile(obj)
|| (is_pole(obj) && !u.usteed)
|| (is_pole(obj) && !u.usteed && !is_art(obj, ART_SNICKERSNEE))
: !is_weptool(obj) && !is_wet_towel(obj);
} else
gu.unweapon = TRUE; /* for "bare hands" message */