From b12d8522c5e0c2c79607e4aa11b37e51977ebabd Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sat, 24 Jan 2009 01:44:29 +0000 Subject: [PATCH] Sunsword redux (trunk only) This started out as a one line change. After I saw someone in the newsgroup mention that Sunsword's light was inferior to that of a lamp, I decided to make it work better (than in 3.4.3, that is, becoming the same brightness as a lamp) when blessed and worse when cursed (useless to hero but still visible if wielded by a monster). But then it needed to change light radius when its curse/bless state changed, and it needed message feedback when doing so, and that got kind of complicated. I wouldn't have bothered if I'd known what I was getting into, but I don't want to throw it away now that I've done all this work.... Sunsword now gives a light radius of 3 when blessed (same as a lit lamp), radius of 2 when uncursed (same as a lit candle and as it has been providing since added in 3.4.0), and a radius of 1 when cursed (nearly but not completely useless, as mentioned above). Also, it now "shines" rather than "glows" since we usually use the latter for temporary effects. --- doc/fixes35.0 | 2 ++ include/extern.h | 5 +++- include/flag.h | 1 + src/light.c | 54 +++++++++++++++++++++++++++++++++++++++- src/mkobj.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++- src/potion.c | 1 + src/pray.c | 34 ++++++++++++++----------- src/timeout.c | 4 +-- src/weapon.c | 10 ++++---- src/wield.c | 9 ++++--- 10 files changed, 156 insertions(+), 28 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 90fb26c3b..37e552582 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -300,6 +300,7 @@ message sequencing for fatal explosions was confusing if feedback was given for carried items being destroyed when dipping something in holy/unholy water, only learn its new bless/curse state if hero sees it glow +describe lit Sunsword as shining rather than glowing Platform- and/or Interface-Specific Fixes @@ -419,6 +420,7 @@ streamline old ^X output and integrate it with enlightenment feedback; eating disenchanter corpses is now considered risky make '[' command more precise when poly'd hero has embedded dragon scales/mail fainting while wielding a cockatrice corpse will be fatal +Sunsword's light radius depends on its curse/bless state Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index 6d525b2c3..cda31de6e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)extern.h 3.5 2008/01/30 */ +/* SCCS Id: @(#)extern.h 3.5 2009/01/20 */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -974,7 +974,10 @@ E boolean FDECL(obj_sheds_light, (struct obj *)); E boolean FDECL(obj_is_burning, (struct obj *)); E void FDECL(obj_split_light_source, (struct obj *, struct obj *)); E void FDECL(obj_merge_light_sources, (struct obj *,struct obj *)); +E void FDECL(obj_adjust_light_radius, (struct obj *,int)); E int FDECL(candle_light_range, (struct obj *)); +E int FDECL(arti_light_radius, (struct obj *)); +E const char *FDECL(arti_light_description, (struct obj *)); #ifdef WIZARD E int NDECL(wiz_light_sources); #endif diff --git a/include/flag.h b/include/flag.h index b05629975..e45a374d3 100644 --- a/include/flag.h +++ b/include/flag.h @@ -326,6 +326,7 @@ extern NEARDATA struct instance_flags iflags; #define PLNMSG_ONE_ITEM_HERE 1 /* "you see here" */ #define PLNMSG_TOWER_OF_FLAME 2 /* scroll of fire */ #define PLNMSG_CAUGHT_IN_EXPLOSION 3 /* explode() feedback */ +#define PLNMSG_OBJ_GLOWS 4 /* "the glows " */ /* runmode options */ #define RUN_TPORT 0 /* don't update display until movement stops */ diff --git a/src/light.c b/src/light.c index 1940a8434..2f499cc92 100644 --- a/src/light.c +++ b/src/light.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)light.c 3.5 2006/07/08 */ +/* SCCS Id: @(#)light.c 3.5 2009/01/20 */ /* Copyright (c) Dean Luick, 1994 */ /* NetHack may be freely redistributed. See license for details. */ @@ -538,6 +538,23 @@ struct obj *src, *dest; } } +/* light source `obj' is being made brighter or dimmer */ +void +obj_adjust_light_radius(obj, new_radius) +struct obj *obj; +int new_radius; +{ + light_source *ls; + + for (ls = light_base; ls; ls = ls->next) + if (ls->type == LS_OBJECT && ls->id.a_obj == obj) { + if (new_radius != ls->range) vision_full_recalc = 1; + ls->range = new_radius; + return; + } + impossible("obj_adjust_light_radius: can't find %s", xname(obj)); +} + /* Candlelight is proportional to the number of candles; minimum range is 2 rather than 1 for playability. */ int @@ -579,6 +596,41 @@ struct obj *obj; return radius; } +/* light emitting artifact's range depends upon its curse/bless state */ +int +arti_light_radius(obj) +struct obj *obj; +{ + /* + * Used by begin_burn() when setting up a new light source + * (obj->lamplit will already be set by this point) and + * also by bless()/unbless()/uncurse()/curse() to decide + * whether to call obj_adjust_light_radius(). + */ + + /* sanity check [simplifies usage by bless()/curse()/&c] */ + if (!obj->lamplit || !artifact_light(obj)) return 0; + + /* cursed radius of 1 is not noticeable for an item that's + carried by the hero but is if it's carried by a monster + or left lit on the floor (not applicable for Sunsword) */ + return (obj->blessed ? 3 : !obj->cursed ? 2 : 1); +} + +/* adverb describing lit artifact's light; depends on curse/bless state */ +const char * +arti_light_description(obj) +struct obj *obj; +{ + switch (arti_light_radius(obj)) { + case 3: return "brilliantly"; /* blessed */ + case 2: return "brightly"; /* uncursed */ + case 1: return "dimly"; /* cursed */ + default: break; + } + return "strangely"; +} + #ifdef WIZARD int diff --git a/src/mkobj.c b/src/mkobj.c index 90460600f..01b165c46 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,10 +1,11 @@ -/* SCCS Id: @(#)mkobj.c 3.5 2008/07/20 */ +/* SCCS Id: @(#)mkobj.c 3.5 2009/01/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" STATIC_DCL void FDECL(mkbox_cnts,(struct obj *)); +STATIC_DCL void FDECL(maybe_adjust_light, (struct obj *,int)); STATIC_DCL void FDECL(obj_timer_checks,(struct obj *, XCHAR_P, XCHAR_P, int)); STATIC_DCL void FDECL(container_weight, (struct obj *)); STATIC_DCL struct obj *FDECL(save_mtraits, (struct obj *, struct monst *)); @@ -976,13 +977,61 @@ start_corpse_timeout(body) (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body)); } +STATIC_OVL void +maybe_adjust_light(obj, old_range) +struct obj *obj; +int old_range; +{ + char buf[BUFSZ]; + xchar ox, oy; + int new_range = arti_light_radius(obj), + delta = new_range - old_range; + + /* radius of light emitting artifact varies by curse/bless state + so will change after blessing or cursing */ + if (delta) { + obj_adjust_light_radius(obj, new_range); + /* simplifying assumptions: hero is wielding this object; + artifacts have to be in use to emit light and monsters' + gear won't change bless or curse state */ + if (!Blind && get_obj_location(obj, &ox, &oy, 0)) { + *buf = '\0'; + if (iflags.last_msg == PLNMSG_OBJ_GLOWS) + /* we just saw "The glows ." from dipping */ + Strcpy(buf, (obj->quan == 1L) ? "It" : "They"); + else if (carried(obj) || cansee(ox, oy)) + Strcpy(buf, Yname2(obj)); + if (*buf) { + /* initial activation says "dimly" if cursed, + "brightly" if uncursed, and "brilliantly" if blessed; + when changing intensity, using "less brightly" is + straightforward for dimming, but we need "brighter" + rather than "more brightly" for brightening; ugh */ + pline("%s %s %s%s.", + buf, otense(obj, "shine"), + (abs(delta) > 1) ? "much " : "", + (delta > 0) ? "brighter" : "less brightly"); + } + } + } +} + +/* + * bless(), curse(), unbless(), uncurse() -- any relevant message + * about glowing amber/black/&c should be delivered prior to calling + * these routines to make the actual curse/bless state change. + */ + void bless(otmp) register struct obj *otmp; { + int old_light = 0; + #ifdef GOLDOBJ if (otmp->oclass == COIN_CLASS) return; #endif + if (otmp->lamplit) old_light = arti_light_radius(otmp); otmp->cursed = 0; otmp->blessed = 1; if (carried(otmp) && confers_luck(otmp)) @@ -991,6 +1040,7 @@ register struct obj *otmp; otmp->owt = weight(otmp); else if (otmp->otyp == FIGURINE && otmp->timed) (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp)); + if (otmp->lamplit) maybe_adjust_light(otmp, old_light); return; } @@ -998,20 +1048,27 @@ void unbless(otmp) register struct obj *otmp; { + int old_light = 0; + + if (otmp->lamplit) old_light = arti_light_radius(otmp); otmp->blessed = 0; if (carried(otmp) && confers_luck(otmp)) set_moreluck(); else if (otmp->otyp == BAG_OF_HOLDING) otmp->owt = weight(otmp); + if (otmp->lamplit) maybe_adjust_light(otmp, old_light); } void curse(otmp) register struct obj *otmp; { + int old_light = 0; + #ifdef GOLDOBJ if (otmp->oclass == COIN_CLASS) return; #endif + if (otmp->lamplit) old_light = arti_light_radius(otmp); otmp->blessed = 0; otmp->cursed = 1; /* welded two-handed weapon interferes with some armor removal */ @@ -1031,6 +1088,7 @@ register struct obj *otmp; && (carried(otmp) || mcarried(otmp))) attach_fig_transform_timeout(otmp); } + if (otmp->lamplit) maybe_adjust_light(otmp, old_light); return; } @@ -1038,6 +1096,9 @@ void uncurse(otmp) register struct obj *otmp; { + int old_light = 0; + + if (otmp->lamplit) old_light = arti_light_radius(otmp); otmp->cursed = 0; if (carried(otmp) && confers_luck(otmp)) set_moreluck(); @@ -1045,6 +1106,7 @@ register struct obj *otmp; otmp->owt = weight(otmp); else if (otmp->otyp == FIGURINE && otmp->timed) (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp)); + if (otmp->lamplit) maybe_adjust_light(otmp, old_light); return; } diff --git a/src/potion.c b/src/potion.c index a3e718718..7d4576bd1 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1092,6 +1092,7 @@ const char *objphrase; /* "Your widget glows" or "Steed's saddle glows" */ pline("%s with %s aura.", objphrase, an(glowcolor)); else pline("%s %s.", objphrase, glowcolor); + iflags.last_msg = PLNMSG_OBJ_GLOWS; targobj->bknown = !Hallucination; } /* potions of water are the only shop goods whose price depends diff --git a/src/pray.c b/src/pray.c index 034efbb4d..b5e39d830 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pray.c 3.5 2008/10/09 */ +/* SCCS Id: @(#)pray.c 3.5 2009/01/23 */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -431,13 +431,14 @@ decurse: impossible("fix_worst_trouble: nothing to uncurse."); return; } - uncurse(otmp); if (!Blind || (otmp == ublindf && Blindfolded_only)) { pline("%s %s.", what ? what : (const char *)Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER)); + iflags.last_msg = PLNMSG_OBJ_GLOWS; otmp->bknown = TRUE; } + uncurse(otmp); update_inventory(); break; case TROUBLE_POISONED: @@ -480,12 +481,12 @@ decurse: #ifdef STEED case TROUBLE_SADDLE: otmp = which_armor(u.usteed, W_SADDLE); - uncurse(otmp); if (!Blind) { pline("%s %s.", Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER)); otmp->bknown = TRUE; } + uncurse(otmp); break; #endif } @@ -908,23 +909,27 @@ pleased(g_align) otense(uwep, "are")); if (uwep->cursed) { - uncurse(uwep); - uwep->bknown = TRUE; - if (!Blind) + if (!Blind) { pline("%s %s%s.", Yobjnam2(uwep, "softly glow"), hcolor(NH_AMBER), repair_buf); - else You_feel("the power of %s over %s.", - u_gname(), yname(uwep)); + iflags.last_msg = PLNMSG_OBJ_GLOWS; + } else + You_feel("the power of %s over %s.", + u_gname(), yname(uwep)); + uncurse(uwep); + uwep->bknown = TRUE; *repair_buf = '\0'; } else if (!uwep->blessed) { - bless(uwep); - uwep->bknown = TRUE; - if (!Blind) + if (!Blind) { pline("%s with %s aura%s.", Yobjnam2(uwep, "softly glow"), an(hcolor(NH_LIGHT_BLUE)), repair_buf); - else You_feel("the blessing of %s over %s.", - u_gname(), yname(uwep)); + iflags.last_msg = PLNMSG_OBJ_GLOWS; + } else + You_feel("the blessing of %s over %s.", + u_gname(), yname(uwep)); + bless(uwep); + uwep->bknown = TRUE; *repair_buf = '\0'; } @@ -993,13 +998,14 @@ pleased(g_align) an(hcolor(NH_LIGHT_BLUE))); for(otmp=invent; otmp; otmp=otmp->nobj) { if (otmp->cursed) { - uncurse(otmp); if (!Blind) { pline("%s %s.", Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER)); + iflags.last_msg = PLNMSG_OBJ_GLOWS; otmp->bknown = TRUE; ++any; } + uncurse(otmp); } } if (any) update_inventory(); diff --git a/src/timeout.c b/src/timeout.c index 0d71b516e..627c3c627 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)timeout.c 3.5 2007/03/15 */ +/* SCCS Id: @(#)timeout.c 3.5 2009/01/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1145,7 +1145,7 @@ begin_burn(obj, already_lit) if (artifact_light(obj)) { obj->lamplit = 1; do_timer = FALSE; - radius = 2; + radius = arti_light_radius(obj); } else { impossible("begin burn: unexpected %s", xname(obj)); turns = obj->age; diff --git a/src/weapon.c b/src/weapon.c index 09d960fa9..c823108be 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)weapon.c 3.5 2008/05/07 */ +/* SCCS Id: @(#)weapon.c 3.5 2009/01/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -706,9 +706,9 @@ register struct monst *mon; if (artifact_light(obj) && !obj->lamplit) { begin_burn(obj, FALSE); if (canseemon(mon)) - pline("%s brilliantly in %s %s!", - Tobjnam(obj, "glow"), - s_suffix(mon_nam(mon)), mbodypart(mon,HAND)); + pline("%s %s in %s %s!", Tobjnam(obj, "shine"), + arti_light_description(obj), + s_suffix(mon_nam(mon)), mbodypart(mon,HAND)); } obj->owornmask = W_WEP; return 1; @@ -1352,7 +1352,7 @@ register struct obj *obj; if (artifact_light(obj) && obj->lamplit) { end_burn(obj, FALSE); if (canseemon(mon)) - pline("%s in %s %s %s glowing.", The(xname(obj)), + pline("%s in %s %s %s shining.", The(xname(obj)), s_suffix(mon_nam(mon)), mbodypart(mon,HAND), otense(obj, "stop")); } diff --git a/src/wield.c b/src/wield.c index 47a511a54..55d088f9b 100644 --- a/src/wield.c +++ b/src/wield.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wield.c 3.5 2007/02/07 */ +/* SCCS Id: @(#)wield.c 3.5 2009/01/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -94,7 +94,7 @@ register struct obj *obj; setworn(obj, W_WEP); if (uwep == obj && artifact_light(olduwep) && olduwep->lamplit) { end_burn(olduwep, FALSE); - if (!Blind) pline("%s glowing.", Tobjnam(olduwep, "stop")); + if (!Blind) pline("%s shining.", Tobjnam(olduwep, "stop")); } /* Note: Explicitly wielding a pick-axe will not give a "bashing" * message. Wielding one via 'a'pplying it will. @@ -190,7 +190,8 @@ struct obj *wep; if (artifact_light(wep) && !wep->lamplit) { begin_burn(wep, FALSE); if (!Blind) - pline("%s to glow brilliantly!", Tobjnam(wep, "begin")); + pline("%s to shine %s!", Tobjnam(wep, "begin"), + arti_light_description(wep)); } #if 0 @@ -574,7 +575,7 @@ uwepgone() if (uwep) { if (artifact_light(uwep) && uwep->lamplit) { end_burn(uwep, FALSE); - if (!Blind) pline("%s glowing.", Tobjnam(uwep, "stop")); + if (!Blind) pline("%s shining.", Tobjnam(uwep, "stop")); } setworn((struct obj *)0, W_WEP); unweapon = TRUE;