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

@@ -1514,6 +1514,7 @@ cursed magic whistle can teleport you to your pet
Fire and Frost Brand can be invoked for expert level fireball or cone of cold
wielding Trollsbane grants hungerless regeneration
hitting with Ogresmasher gives a higher chance of knockback
Snickersnee can hit at a distance once per turn for free
Fixes to 3.7.0-x General Problems Exposed Via git Repository

View File

@@ -148,6 +148,7 @@ struct context_info {
int warnlevel; /* threshold (digit) to warn about unseen mons */
long next_attrib_check; /* next attribute check */
long seer_turn; /* when random clairvoyance will next kick in */
long snickersnee_turn; /* Snickersnee last used to distance attack */
long stethoscope_seq; /* when a stethoscope was last used; first use
* during a move takes no time, second uses move */
boolean travel; /* find way automatically to u.tx,u.ty */

View File

@@ -222,10 +222,12 @@ struct obj {
(otmp->oclass == WEAPON_CLASS \
&& objects[otmp->otyp].oc_skill >= P_SHORT_SWORD \
&& objects[otmp->otyp].oc_skill <= P_SABER)
/* Snickersnee is not a polearm, but can hit from distance */
#define is_pole(otmp) \
((otmp->oclass == WEAPON_CLASS || otmp->oclass == TOOL_CLASS) \
&& (objects[otmp->otyp].oc_skill == P_POLEARMS \
|| objects[otmp->otyp].oc_skill == P_LANCE))
|| objects[otmp->otyp].oc_skill == P_LANCE \
|| is_art(otmp, ART_SNICKERSNEE)))
#define is_spear(otmp) \
(otmp->oclass == WEAPON_CLASS && objects[otmp->otyp].oc_skill == P_SPEAR)
#define is_launcher(otmp) \

View File

@@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 123
#define EDITLEVEL 124
/*
* Development status possibilities.

View File

@@ -197,6 +197,7 @@
seffect(stone_breaking),
seffect(stone_crumbling),
seffect(swoosh),
seffect(sword_blade_rings),
seffect(thud),
seffect(thump),
seffect(thunderclap),

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 */