-/* NetHack 3.6 weapon.c $NHDT-Date: 1454660575 2016/02/05 08:22:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.57 $ */
+/* NetHack 3.6 weapon.c $NHDT-Date: 1548209744 2019/01/23 02:15:44 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.69 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
+STATIC_DCL void FDECL(give_may_advance_msg, (int));
+STATIC_DCL boolean FDECL(could_advance, (int));
+STATIC_DCL boolean FDECL(peaked_skill, (int));
+STATIC_DCL int FDECL(slots_required, (int));
+STATIC_DCL void FDECL(skill_advance, (int));
+
/* Categories whose names don't come from OBJ_NAME(objects[type])
*/
#define PN_BARE_HANDED (-1) /* includes martial arts */
#define PN_ESCAPE_SPELL (-13)
#define PN_MATTER_SPELL (-14)
-STATIC_DCL void FDECL(give_may_advance_msg, (int));
-
STATIC_VAR NEARDATA const short skill_names_indices[P_NUM_SKILLS] = {
0, DAGGER, KNIFE, AXE, PICK_AXE, SHORT_SWORD, BROADSWORD, LONG_SWORD,
TWO_HANDED_SWORD, SCIMITAR, PN_SABER, CLUB, MACE, MORNING_STAR, FLAIL,
#endif
};
+#define P_NAME(type) \
+ ((skill_names_indices[type] > 0) \
+ ? OBJ_NAME(objects[skill_names_indices[type]]) \
+ : (type == P_BARE_HANDED_COMBAT) \
+ ? barehands_or_martial[martial_bonus()] \
+ : odd_skill_names[-skill_names_indices[type]])
+
+static NEARDATA const char kebabable[] = { S_XORN, S_DRAGON, S_JABBERWOCK,
+ S_NAGA, S_GIANT, '\0' };
+
STATIC_OVL void
give_may_advance_msg(skill)
int skill;
{
#if 0 /*JP*/
You_feel("more confident in your %sskills.",
- skill == P_NONE ? "" : skill <= P_LAST_WEAPON
- ? "weapon "
- : skill <= P_LAST_SPELL
- ? "spell casting "
- : "fighting ");
+ (skill == P_NONE) ? ""
+ : (skill <= P_LAST_WEAPON) ? "weapon "
+ : (skill <= P_LAST_SPELL) ? "spell casting "
+ : "fighting ");
#else
You("%s\83X\83L\83\8b\82ð\8d\82\82ß\82é\8e©\90M\82ª\97N\82¢\82Ä\82«\82½\81D",
- skill == P_NONE ? "" : skill <= P_LAST_WEAPON
- ? "\95\90\8aí\82Ì"
- : skill <= P_LAST_SPELL
- ? "\96\82\96@\82Ì"
- : "\90í\82¢\82Ì");
+ (skill == P_NONE) ? ""
+ : (skill <= P_LAST_WEAPON) ? "\95\90\8aí\82Ì"
+ : (skill <= P_LAST_SPELL) ? "\96\82\96@\82Ì"
+ : "\90í\82¢\82Ì");
#endif
}
-STATIC_DCL boolean FDECL(can_advance, (int, BOOLEAN_P));
-STATIC_DCL boolean FDECL(could_advance, (int));
-STATIC_DCL boolean FDECL(peaked_skill, (int));
-STATIC_DCL int FDECL(slots_required, (int));
-STATIC_DCL char *FDECL(skill_level_name, (int, char *));
-STATIC_DCL void FDECL(skill_advance, (int));
-
-#define P_NAME(type) \
- ((skill_names_indices[type] > 0) \
- ? OBJ_NAME(objects[skill_names_indices[type]]) \
- : (type == P_BARE_HANDED_COMBAT) \
- ? barehands_or_martial[martial_bonus()] \
- : odd_skill_names[-skill_names_indices[type]])
-
-static NEARDATA const char kebabable[] = { S_XORN, S_DRAGON, S_JABBERWOCK,
- S_NAGA, S_GIANT, '\0' };
-
/* weapon's skill category name for use as generalized description of weapon;
mostly used to shorten "you drop your <weapon>" messages when slippery
fingers or polymorph causes hero to involuntarily drop wielded weapon(s) */
bonus += rnd(4);
if (objects[otyp].oc_material == SILVER && mon_hates_silver(mon))
bonus += rnd(20);
+ if (artifact_light(otmp) && otmp->lamplit && hates_light(ptr))
+ bonus += rnd(8);
/* if the weapon is going to get a double damage bonus, adjust
this bonus so that effectively it's added after the doubling */
return tmp;
}
+/* check whether blessed and/or silver damage applies for *non-weapon* hit;
+ return value is the amount of the extra damage */
+int
+special_dmgval(magr, mdef, armask, silverhit_p)
+struct monst *magr, *mdef;
+long armask; /* armor mask, multiple bits accepted for W_ARMC|W_ARM|W_ARMU
+ * or W_ARMG|W_RINGL|W_RINGR only */
+long *silverhit_p; /* output flag mask for silver bonus */
+{
+ struct obj *obj;
+ struct permonst *ptr = mdef->data;
+ boolean left_ring = (armask & W_RINGL) ? TRUE : FALSE,
+ right_ring = (armask & W_RINGR) ? TRUE : FALSE;
+ long silverhit = 0L;
+ int bonus = 0;
+
+ obj = 0;
+ if (armask & (W_ARMC | W_ARM | W_ARMU)) {
+ if ((armask & W_ARMC) != 0L
+ && (obj = which_armor(magr, W_ARMC)) != 0)
+ armask = W_ARMC;
+ else if ((armask & W_ARM) != 0L
+ && (obj = which_armor(magr, W_ARM)) != 0)
+ armask = W_ARM;
+ else if ((armask & W_ARMU) != 0L
+ && (obj = which_armor(magr, W_ARMU)) != 0)
+ armask = W_ARMU;
+ else
+ armask = 0L;
+ } else if (armask & (W_ARMG | W_RINGL | W_RINGR)) {
+ armask = ((obj = which_armor(magr, W_ARMG)) != 0) ? W_ARMG : 0L;
+ } else {
+ obj = which_armor(magr, armask);
+ }
+
+ if (obj) {
+ if (obj->blessed
+ && (is_undead(ptr) || is_demon(ptr) || is_vampshifter(mdef)))
+ bonus += rnd(4);
+ /* the only silver armor is shield of reflection (silver dragon
+ scales refer to color, not material) and the only way to hit
+ with one--aside from throwing--is to wield it and perform a
+ weapon hit, but we include a general check here */
+ if (objects[obj->otyp].oc_material == SILVER
+ && mon_hates_silver(mdef)) {
+ bonus += rnd(20);
+ silverhit |= armask;
+ }
+
+ /* when no gloves we check for silver rings (blessed rings ignored) */
+ } else if ((left_ring || right_ring) && magr == &youmonst) {
+ if (left_ring && uleft) {
+ if (objects[uleft->otyp].oc_material == SILVER
+ && mon_hates_silver(mdef)) {
+ bonus += rnd(20);
+ silverhit |= W_RINGL;
+ }
+ }
+ if (right_ring && uright) {
+ if (objects[uright->otyp].oc_material == SILVER
+ && mon_hates_silver(mdef)) {
+ /* two silver rings don't give double silver damage
+ but 'silverhit' messages might be adjusted for them */
+ if (!(silverhit & W_RINGL))
+ bonus += rnd(20);
+ silverhit |= W_RINGR;
+ }
+ }
+ }
+
+ if (silverhit_p)
+ *silverhit_p = silverhit;
+ return bonus;
+}
+
+/* give a "silver <item> sears <target>" message;
+ not used for weapon hit, so we only handle rings */
+void
+silver_sears(magr, mdef, silverhit)
+struct monst *magr UNUSED;
+struct monst *mdef;
+long silverhit;
+{
+ char rings[20]; /* plenty of room for "rings" */
+ int ltyp = ((uleft && (silverhit & W_RINGL) != 0L)
+ ? uleft->otyp : STRANGE_OBJECT),
+ rtyp = ((uright && (silverhit & W_RINGR) != 0L)
+ ? uright->otyp : STRANGE_OBJECT);
+ boolean both,
+ l_ag = (objects[ltyp].oc_material == SILVER && uleft->dknown),
+ r_ag = (objects[rtyp].oc_material == SILVER && uright->dknown);
+
+ if ((silverhit & (W_RINGL | W_RINGR)) != 0L) {
+ /* plural if both the same type (so not multi_claw and both rings
+ are non-Null) and either both known or neither known, or both
+ silver (in case there is ever more than one type of silver ring)
+ and both known; singular if multi_claw (where one of ltyp or
+ rtyp will always be STRANGE_OBJECT) even if both rings are known
+ silver [see hmonas(uhitm.c) for explanation of 'multi_claw'] */
+ both = ((ltyp == rtyp && uleft->dknown == uright->dknown)
+ || (l_ag && r_ag));
+ Sprintf(rings, "ring%s", both ? "s" : "");
+ Your("%s%s %s %s!",
+ (l_ag || r_ag) ? "silver "
+ : both ? ""
+ : ((silverhit & W_RINGL) != 0L) ? "left "
+ : "right ",
+ rings, vtense(rings, "sear"), mon_nam(mdef));
+ }
+}
+
STATIC_DCL struct obj *FDECL(oselect, (struct monst *, int));
#define Oselect(x) \
if ((otmp = oselect(mtmp, x)) != 0) \
return (struct obj *) 0;
}
+/* TODO: have monsters use aklys' throw-and-return */
static NEARDATA const int rwep[] = {
DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN,
SHURIKEN, YA, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW,
char mlet = mtmp->data->mlet;
- propellor = &zeroobj;
+ propellor = (struct obj *) &zeroobj;
Oselect(EGG); /* cockatrice egg */
if (mlet == S_KOP) /* pies are first choice for Kops */
Oselect(CREAM_PIE);
}
/* KMH -- This belongs here so darts will work */
- propellor = &zeroobj;
+ propellor = (struct obj *) &zeroobj;
- prop = (objects[rwep[i]]).oc_skill;
+ prop = objects[rwep[i]].oc_skill;
if (prop < 0) {
switch (-prop) {
case P_BOW:
- propellor = (oselect(mtmp, YUMI));
+ propellor = oselect(mtmp, YUMI);
if (!propellor)
- propellor = (oselect(mtmp, ELVEN_BOW));
+ propellor = oselect(mtmp, ELVEN_BOW);
if (!propellor)
- propellor = (oselect(mtmp, BOW));
+ propellor = oselect(mtmp, BOW);
if (!propellor)
- propellor = (oselect(mtmp, ORCISH_BOW));
+ propellor = oselect(mtmp, ORCISH_BOW);
break;
case P_SLING:
- propellor = (oselect(mtmp, SLING));
+ propellor = oselect(mtmp, SLING);
break;
case P_CROSSBOW:
- propellor = (oselect(mtmp, CROSSBOW));
+ propellor = oselect(mtmp, CROSSBOW);
}
if ((otmp = MON_WEP(mtmp)) && mwelded(otmp) && otmp != propellor
&& mtmp->weapon_check == NO_WEAPON_WANTED)
return (struct obj *) 0;
}
+/* is 'obj' a type of weapon that any monster knows how to throw? */
+boolean
+monmightthrowwep(obj)
+struct obj *obj;
+{
+ short idx;
+
+ for (idx = 0; idx < SIZE(rwep); ++idx)
+ if (obj->otyp == rwep[idx])
+ return TRUE;
+ return FALSE;
+}
+
/* Weapons in order of preference */
static const NEARDATA short hwep[] = {
CORPSE, /* cockatrice corpse */
}
if (obj && obj != &zeroobj) {
struct obj *mw_tmp = MON_WEP(mon);
+
if (mw_tmp && mw_tmp->otyp == obj->otyp) {
/* already wielding it */
mon->weapon_check = NEED_WEAPON;
}
/* copy the skill level name into the given buffer */
-STATIC_OVL char *
+char *
skill_level_name(skill, buf)
int skill;
char *buf;
return buf;
}
+const char *
+skill_name(skill)
+int skill;
+{
+ return P_NAME(skill);
+}
+
/* return the # of slots required to advance the skill */
STATIC_OVL int
slots_required(skill)
}
/* return true if this skill can be advanced */
-/*ARGSUSED*/
-STATIC_OVL boolean
+boolean
can_advance(skill, speedy)
int skill;
boolean speedy;