From dc9de59f63d6144f2b7651900a303b91b57a2cca Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 6 Apr 2020 06:25:17 -0700 Subject: [PATCH] ^X weapon feedback Report weapon skill in the ^X status section when dual-wielding, The effective skill level is the lower of the weapon's skill and two-weapon skill, separately for primary and secondary. It's a much bigger chunk of code than most enlightenment/^X features so I put it in its own routine. --- doc/fixes37.0 | 3 +- src/insight.c | 183 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 163 insertions(+), 23 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 93ac0cb70..efd030bb6 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.163 $ $NHDT-Date: 1586178711 2020/04/06 13:11:51 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.164 $ $NHDT-Date: 1586179508 2020/04/06 13:25:08 $ General Fixes and Modified Features ----------------------------------- @@ -235,6 +235,7 @@ for !fixinv option where inventory letters normally don't stick, try to put a throw-and-return weapon back into the same inventory slot it gets thrown from; only works if it does return and is successfully caught wizard mode #wizborn command +include more skill information in ^X output when dual-wielding Platform- and/or Interface-Specific New Features diff --git a/src/insight.c b/src/insight.c index 832169604..1bd5a2e17 100644 --- a/src/insight.c +++ b/src/insight.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 insight.c $NHDT-Date: 1582321544 2020/02/21 21:45:44 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.7 $ */ +/* NetHack 3.7 insight.c $NHDT-Date: 1586179508 2020/04/06 13:25:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.9 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -27,6 +27,7 @@ static void FDECL(basics_enlightenment, (int, int)); static void FDECL(characteristics_enlightenment, (int, int)); static void FDECL(one_characteristic, (int, int, int)); static void FDECL(status_enlightenment, (int, int)); +static void FDECL(weapon_insight, (int)); static void FDECL(attributes_enlightenment, (int, int)); static void FDECL(show_achievements, (int)); static int FDECL(CFDECLSPEC vanqsort_cmp, (const genericptr, @@ -740,7 +741,7 @@ int mode; int final; { boolean magic = (mode & MAGICENLIGHTENMENT) ? TRUE : FALSE; - int cap, wtype; + int cap; char buf[BUFSZ], youtoo[BUFSZ]; boolean Riding = (u.usteed /* if hero dies while dismounting, u.usteed will still @@ -1015,8 +1016,27 @@ int final; still useful though) */ you_are("unencumbered", ""); } + /* current weapon(s) and corresponding skill level(s) */ + weapon_insight(final); + /* report 'nudity' */ + if (!uarm && !uarmu && !uarmc && !uarms && !uarmg && !uarmf && !uarmh) { + if (u.uroleplay.nudist) + enl_msg(You_, "do", "did", " not wear any armor", ""); + else + you_are("not wearing any armor", ""); + } +} - /* report being weaponless; distinguish whether gloves are worn */ +/* extracted from status_enlightenment() to reduce clutter there */ +static void +weapon_insight(final) +int final; +{ + char buf[BUFSZ]; + int wtype; + + /* report being weaponless; distinguish whether gloves are worn + [perhaps mention silver ring(s) when not wearning gloves?] */ if (!uwep) { you_are(uarmg ? "empty handed" /* gloves imply hands */ : humanoid(g.youmonst.data) @@ -1025,29 +1045,39 @@ int final; /* alternate phrasing for paws or lack of hands */ : "not wielding anything", ""); - /* two-weaponing implies hands (can't be polymorphed) and + + /* two-weaponing implies hands and a weapon or wep-tool (not other odd stuff) in each hand */ } else if (u.twoweap) { you_are("wielding two weapons at once", ""); + /* report most weapons by their skill class (so a katana will be - described as a long sword, for instance; mattock and hook are - exceptions), or wielded non-weapon item by its object class */ + described as a long sword, for instance; mattock, hook, and aklys + are exceptions), or wielded non-weapon item by its object class */ } else { const char *what = weapon_descr(uwep); + /* [what about other silver items?] */ + if (uwep->otyp == SHIELD_OF_REFLECTION) + what = shield_simple_name(uwep); /* silver|smooth shield */ + else if (is_wet_towel(uwep)) + what = /* (uwep->spe < 3) ? "moist towel" : */ "wet towel"; + if (!strcmpi(what, "armor") || !strcmpi(what, "food") || !strcmpi(what, "venom")) Sprintf(buf, "wielding some %s", what); else + /* [maybe include known blessed?] */ Sprintf(buf, "wielding %s", (uwep->quan == 1L) ? an(what) : makeplural(what)); you_are(buf, ""); } + /* * Skill with current weapon. Might help players who've never * noticed #enhance or decided that it was pointless. */ - if ((wtype = uwep_skill_type()) != P_NONE) { + if ((wtype = weapon_type(uwep)) != P_NONE && !is_ammo(uwep)) { char sklvlbuf[20]; int sklvl = P_SKILL(wtype); boolean hav = (sklvl != P_UNSKILLED && sklvl != P_SKILLED); @@ -1060,21 +1090,130 @@ int final; or "you are unskilled/skilled in " */ Sprintf(buf, "%s %s %s", sklvlbuf, hav ? "skill with" : "in", skill_name(wtype)); - if (can_advance(wtype, FALSE)) - Sprintf(eos(buf), " and %s that", - !final ? "can enhance" : "could have enhanced"); - if (hav) - you_have(buf, ""); - else - you_are(buf, ""); - } - /* report 'nudity' */ - if (!uarm && !uarmu && !uarmc && !uarms && !uarmg && !uarmf && !uarmh) { - if (u.uroleplay.nudist) - enl_msg(You_, "do", "did", " not wear any armor", ""); - else - you_are("not wearing any armor", ""); - } + + if (!u.twoweap) { + if (can_advance(wtype, FALSE)) + Sprintf(eos(buf), " and %s that", + !final ? "can enhance" : "could have enhanced"); + if (hav) + you_have(buf, ""); + else + you_are(buf, ""); + + } else { /* twoweap, so two-weapon skill is at least unskilled */ + static const char also_[] = "also "; + char pfx[QBUFSZ], sfx[QBUFSZ], + sknambuf2[20], sklvlbuf2[20], twobuf[20]; + const char *also = "", *also2 = "", *also3 = (char *) 0, + *verb_present, *verb_past; + int a1, a2, ab, + wtype2 = weapon_type(uswapwep), + sklvl2 = P_SKILL(wtype2), + twoskl = P_SKILL(P_TWO_WEAPON_COMBAT); + boolean hav2 = (sklvl2 != P_UNSKILLED && sklvl2 != P_SKILLED); + + /* normally hero must have access to two-weapon skill in + order to initiate u.twoweap, but not if polymorphed into + a form which has multiple weapon attacks, so we need to + avoid getting bitten by unexpected skill value */ + if (twoskl == P_ISRESTRICTED) { + twoskl = P_UNSKILLED; + /* restricted is the same as unskilled as far as bonus + or penaly goes, and it isn't ordinarily seen so + skill_level_name() returns "Unknown" for it */ + Strcpy(twobuf, "restricted"); + } else { + (void) lcase(skill_level_name(P_TWO_WEAPON_COMBAT, twobuf)); + } + + /* keep buf[] from above in case skill levels match */ + pfx[0] = sfx[0] = '\0'; + if (twoskl < sklvl) { + /* twoskil won't be restricted so sklvl is at least basic */ + Sprintf(pfx, "Your skill in %s ", skill_name(wtype)); + Sprintf(sfx, " limited by being %s with two weapons", twobuf); + also = also_; + } else if (twoskl > sklvl) { + /* sklvl might be restricted */ + Strcpy(pfx, "Your two weapon skill "); + Strcpy(sfx, " limited by "); + if (sklvl > P_ISRESTRICTED) + Sprintf(eos(sfx), "being %s", sklvlbuf); + else + Sprintf(eos(sfx), "having no skill"); + Sprintf(eos(sfx), " with %s", skill_name(wtype)); + also2 = also_; + } else { + Strcat(buf, " and two weapons"); + also3 = also_; + } + if (*pfx) + enl_msg(pfx, "is", "was", sfx, ""); + else if (hav) + you_have(buf, ""); + else + you_are(buf, ""); + + if (wtype2 == wtype) + return; + + Strcpy(sknambuf2, skill_name(wtype2)); + (void) lcase(skill_level_name(wtype2, sklvlbuf2)); + verb_present = "is", verb_past = "was"; + pfx[0] = sfx[0] = buf[0] = '\0'; + if (twoskl < sklvl2) { + /* twoskil is at least unskilled, sklvl2 at least basic */ + Sprintf(pfx, "Your skill in %s ", sknambuf2); + Sprintf(sfx, " %slimited by being %s with two weapons", + also, twobuf); + } else if (twoskl > sklvl2) { + /* sklvl2 might be restricted */ + Strcpy(pfx, "Your two weapon skill "); + Sprintf(sfx, " %slimited by ", also2); + if (sklvl2 > P_ISRESTRICTED) + Sprintf(eos(sfx), "being %s with", sklvlbuf2); + else + Strcat(eos(sfx), "having no skill"); + Sprintf(eos(sfx), " with %s", sknambuf2); + + } else { + /* equal; two-weapon is at least unskilled, so so is sklvl2; + "you [also] have basic/expert/master/grand-master skill + with " or "you [also] are unskilled/skilled in*" */ + Sprintf(buf, "%s %s %s", sklvlbuf2, + hav2 ? "skill with" : "in", sknambuf2); + Strcat(buf, " and two weapons"); + if (also3) { + Strcpy(pfx, "You also "); + Sprintf(sfx, " %s", buf), buf[0] = '\0'; + verb_present = hav2 ? "have" : "are"; + verb_past = hav2 ? "had" : "were"; + } + } + if (*pfx) + enl_msg(pfx, verb_present, verb_past, sfx, ""); + else if (hav2) + you_have(buf, ""); + else + you_are(buf, ""); + + a1 = can_advance(wtype, FALSE); + a2 = can_advance(wtype2, FALSE); + ab = can_advance(P_TWO_WEAPON_COMBAT, FALSE); + if (a1 || a2 || ab) { + Sprintf(sfx, " skill%s with %s%s%s%s%s", + (a1 + a2 + ab > 1) ? "s" : "", + a1 ? skill_name(wtype) : "", + ((a1 && a2 && ab) ? ", " + : (a1 && (a2 || ab)) ? " and " : ""), + a2 ? skill_name(wtype2) : "", + ((a1 && a2 && ab) ? ", and " + : (a2 && ab) ? " and " : ""), + ab ? "two weapons" : ""); + enl_msg(You_, "can enhance", "could have enhanced", sfx, ""); + } + } /* two-weapon */ + } /* skill applies */ } /* attributes: intrinsics and the like, other non-obvious capabilities */