extend #timeout to cover all properties

Extend the wizard mode #timeout command:  show timeouts for all 67
intrinsics rather than just a handful.  Most won't appear because
they don't have any way to receive a timed value.  Except for...

Extend the wizard mode #wizintrinsic command:  allow setting a
brief (30 turn) timeout for any/every intrinsic, not just for
deafness.  It ought to prompt for duration, but that's more effort
than I'm willing to expend.  This might turn up lots of quirks that
the code isn't prepared to handle (like setting life-saving to
non-zero will break the assumption that it comes from worn amulet).
Perhaps some will warrant fixing, others just a shrug.

There are still some timed events that aren't listed by #timeout:
remaining duration to stay polymorphed in current form, number of
turns until it's safe to pray, luck decay, number of turns until
next attribute exercise/abuse check, probably others that I'm
overlooking.

Bug fix:  while testing, I observed
  Your limbs have turned to stone.
  You have turned to stone.
  You can hear again.
  You are a statue.
when deafness and petrification were timing out at the same time.
This modifies the stoning and sliming countdowns to extend deafness
duration a little if it's about to time out at the tail end of the
stoning or sliming sequence, so that "you can hear again" won't
happen until after life-saving.  There are probably other variations
of simultaneous or near simultaneous timeout that interact oddly.
This commit is contained in:
PatR
2017-06-26 01:04:58 -07:00
parent 8e213472c2
commit 8e8ea0566b
3 changed files with 171 additions and 66 deletions

111
src/cmd.c
View File

@@ -1141,41 +1141,94 @@ STATIC_PTR int
wiz_intrinsic(VOID_ARGS)
{
if (wizard) {
extern const char *const propertynames[]; /* timeout.c */
static const char wizintrinsic[] = "#wizintrinsic";
static const char fmt[] = "You are%s %s.";
winid win;
anything any;
int i, n, accelerator;
char buf[BUFSZ];
int i, n, p, amt, typ;
long oldtimeout, newtimeout;
const char *propname;
menu_item *pick_list = (menu_item *) 0;
static const char *const intrinsics[] = {
"deafness",
};
win = create_nhwindow(NHW_MENU);
start_menu(win);
accelerator = 0;
for (i = 0; i < SIZE(intrinsics); ++i) {
accelerator = intrinsics[i][0];
any.a_int = i + 1;
add_menu(win, NO_GLYPH, &any, accelerator, 0,
ATR_NONE, intrinsics[i], FALSE);
for (i = 1; (propname = propertynames[i]) != 0; ++i) {
if (i == HALLUC_RES) {
/* Grayswandir vs hallucination; ought to be redone to
use u.uprops[HALLUC].blocked instead of being treated
as a separate property; letting in be manually toggled
even only in wizard mode would be asking for trouble... */
continue;
}
any.a_int = i;
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, propname, FALSE);
}
end_menu(win, "Which intrinsic?");
n = select_menu(win, PICK_ONE, &pick_list);
end_menu(win, "Which intrinsics?");
n = select_menu(win, PICK_ANY, &pick_list);
destroy_nhwindow(win);
if (n >= 1) {
i = pick_list[0].item.a_int-1;
free((genericptr_t) pick_list);
} else {
return 0;
}
amt = 30; /* TODO: prompt for duration */
for (i = 0; i < n; ++i) {
p = pick_list[i].item.a_int;
oldtimeout = u.uprops[p].intrinsic & TIMEOUT;
newtimeout = oldtimeout + (long) amt;
switch (p) {
case SICK:
case SLIMED:
case STONED:
if (oldtimeout > 0L && newtimeout > oldtimeout)
newtimeout = oldtimeout;
break;
}
if (!strcmp(intrinsics[i], "deafness")) {
You("go deaf.");
incr_itimeout(&HDeaf, 30);
context.botl = TRUE;
switch (p) {
case BLINDED:
make_blinded(newtimeout, TRUE);
break;
case CONFUSION:
make_confused(newtimeout, TRUE);
break;
case DEAF:
make_deaf(newtimeout, TRUE);
break;
case HALLUC:
make_hallucinated(newtimeout, TRUE, 0L);
break;
case SICK:
typ = !rn2(2) ? SICK_VOMITABLE : SICK_NONVOMITABLE;
make_sick(newtimeout, wizintrinsic, TRUE, typ);
break;
case SLIMED:
Sprintf(buf, fmt,
!Slimed ? "" : " still", "turning into slime");
make_slimed(newtimeout, buf);
break;
case STONED:
Sprintf(buf, fmt,
!Stoned ? "" : " still", "turning into stone");
make_stoned(newtimeout, buf, KILLED_BY, wizintrinsic);
break;
case STUNNED:
make_stunned(newtimeout, TRUE);
break;
case VOMITING:
Sprintf(buf, fmt, !Vomiting ? "" : " still", "vomiting");
make_vomiting(newtimeout, FALSE);
pline1(buf);
break;
default:
pline("Timeout for %s %s %d.", propertynames[p],
oldtimeout ? "increased by" : "set to", amt);
incr_itimeout(&u.uprops[p].intrinsic, amt);
break;
}
context.botl = 1; /* probably not necessary... */
}
if (n >= 1)
free((genericptr_t) pick_list);
} else
pline("Unavailable command '%s'.",
visctrl((int) cmd_from_func(wiz_intrinsic)));
@@ -2814,7 +2867,7 @@ struct ext_func_tab extcmdlist[] = {
{ '\\', "known", "show what object types have been discovered",
dodiscovered, IFBURIED | GENERALCMD },
{ '`', "knownclass", "show discovered types for one class of objects",
doclassdisco, IFBURIED|GENERALCMD },
doclassdisco, IFBURIED | GENERALCMD },
{ '\0', "levelchange", "change experience level",
wiz_level_change, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "lightsources", "show mobile light sources",
@@ -2835,11 +2888,11 @@ struct ext_func_tab extcmdlist[] = {
dosacrifice, AUTOCOMPLETE },
{ 'o', "open", "open a door", doopen },
{ 'O', "options", "show option settings, possibly change them",
doset, IFBURIED|GENERALCMD },
doset, IFBURIED | GENERALCMD },
{ C('o'), "overview", "show a summary of the explored dungeon",
dooverview, IFBURIED|AUTOCOMPLETE },
dooverview, IFBURIED | AUTOCOMPLETE },
{ '\0', "panic", "test panic routine (fatal to game)",
wiz_panic, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
wiz_panic, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ 'p', "pay", "pay your shopping bill", dopay },
{ ',', "pickup", "pick up things at the current location", dopickup },
{ '\0', "polyself", "polymorph self",
@@ -2851,7 +2904,7 @@ struct ext_func_tab extcmdlist[] = {
{ M('p'), "pray", "pray to the gods for help",
dopray, IFBURIED | AUTOCOMPLETE },
{ C('p'), "prevmsg", "view recent game messages",
doprev_message, IFBURIED|GENERALCMD },
doprev_message, IFBURIED | GENERALCMD },
{ 'P', "puton", "put on an accessory (ring, amulet, etc)", doputon },
{ 'q', "quaff", "quaff (drink) something", dodrink },
{ M('q'), "quit", "exit without saving current game",
@@ -2900,7 +2953,7 @@ struct ext_func_tab extcmdlist[] = {
{ '\0', "terrain", "show map without obstructions",
doterrain, IFBURIED | AUTOCOMPLETE },
{ 't', "throw", "throw something", dothrow },
{ '\0', "timeout", "look at timeout queue",
{ '\0', "timeout", "look at timeout queue and hero's timed intrinsics",
wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ M('T'), "tip", "empty a container", dotip, AUTOCOMPLETE },
{ '_', "travel", "travel to a specific location on the map", dotravel },