some tipping fixes
- adjust the surface name in prompts (resolves a TODO in the code). - be more player-friendly with the prompting, and don't prompt a second time if the floor/surface is the only tip-destination, as that can be annoyng and viewed as unnecessary. Instead, include that information in the first decision prompt. Resolves #1537
This commit is contained in:
+102
-56
@@ -42,7 +42,7 @@ staticfn int traditional_loot(boolean);
|
||||
staticfn int menu_loot(int, boolean);
|
||||
staticfn int tip_ok(struct obj *);
|
||||
staticfn int choose_tip_container_menu(void);
|
||||
staticfn struct obj *tipcontainer_gettarget(struct obj *, boolean *);
|
||||
staticfn struct obj *tipcontainer_gettarget(struct obj *, boolean *, int *);
|
||||
staticfn int tipcontainer_checks(struct obj *, struct obj *, boolean);
|
||||
staticfn char in_or_out_menu(const char *, struct obj *, boolean, boolean,
|
||||
boolean, boolean);
|
||||
@@ -3607,10 +3607,25 @@ dotip(void)
|
||||
} else {
|
||||
for (cobj = svl.level.objects[cc.x][cc.y]; cobj;
|
||||
cobj = nobj) {
|
||||
int target_count = 0;
|
||||
boolean dum; /* argument placeholder, not actually used */
|
||||
char prompt_part2[BUFSZ];
|
||||
|
||||
nobj = cobj->nexthere;
|
||||
if (!Is_container(cobj))
|
||||
continue;
|
||||
c = ynq(safe_qbuf(qbuf, "There is ", " here, tip it?",
|
||||
/*
|
||||
* Calling tipcontainer_gettarget with a non-zero int ptr
|
||||
* as the 3rd argument just obtains the count of elligible
|
||||
* tip targets. No menu is displayed and no tip-target pick
|
||||
* is carried out.
|
||||
*/
|
||||
(void) tipcontainer_gettarget(cobj, &dum, &target_count);
|
||||
Sprintf(prompt_part2, " here, tip it%s%s?",
|
||||
(target_count == 0) ? " onto the " : "",
|
||||
(target_count == 0) ? surface(cobj->ox, cobj->oy)
|
||||
: "");
|
||||
c = ynq(safe_qbuf(qbuf, "There is ", prompt_part2,
|
||||
cobj,
|
||||
doname, ansimpleoname, "container"));
|
||||
if (c == 'q')
|
||||
@@ -3709,7 +3724,7 @@ tipcontainer(struct obj *box) /* or bag */
|
||||
* if 'box' is known to be empty or known to be locked, give up
|
||||
* before choosing 'targetbox'.
|
||||
*/
|
||||
targetbox = tipcontainer_gettarget(box, &cancelled);
|
||||
targetbox = tipcontainer_gettarget(box, &cancelled, (int *) 0);
|
||||
if (cancelled)
|
||||
return;
|
||||
|
||||
@@ -3876,16 +3891,17 @@ count_target_containers(
|
||||
staticfn struct obj *
|
||||
tipcontainer_gettarget(
|
||||
struct obj *box,
|
||||
boolean *cancelled)
|
||||
boolean *cancelled,
|
||||
int *only_count_targets)
|
||||
{
|
||||
int n, n_conts, tmpglyph;
|
||||
int n, n_conts = 0, tmpglyph, looppass, count_tiptargets = 0;
|
||||
glyph_info tmpglyphinfo;
|
||||
winid win;
|
||||
winid win = WIN_ERR;
|
||||
anything any;
|
||||
char buf[BUFSZ];
|
||||
char buf[BUFSZ], on_the_surface[BUFSZ];
|
||||
menu_item *pick_list = (menu_item *) 0;
|
||||
struct obj dummyobj, *otmp;
|
||||
boolean hands_available = TRUE, exclude_it;
|
||||
boolean hands_available = TRUE, exclude_it, skip_targetmenu = FALSE;
|
||||
int clr = NO_COLOR;
|
||||
|
||||
#if 0 /* [skip potential early return so that menu response is needed
|
||||
@@ -3899,58 +3915,88 @@ tipcontainer_gettarget(
|
||||
return (struct obj *) 0;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* looppass 0 : count the elligible drop targets
|
||||
* looppass 1 : if there are elligible tip targets, besides the floor,
|
||||
* then build and present a menu of those targets, including
|
||||
* the floor.
|
||||
*/
|
||||
for (looppass = 0; looppass < 2; looppass++) {
|
||||
if (looppass == 1) {
|
||||
if (only_count_targets) {
|
||||
*only_count_targets = count_tiptargets;
|
||||
skip_targetmenu = TRUE;
|
||||
break;
|
||||
}
|
||||
if (count_tiptargets == 0) {
|
||||
/* nothing but the floor */
|
||||
skip_targetmenu = TRUE;
|
||||
break;
|
||||
}
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
dummyobj = cg.zeroobj; /* lint suppression; only its address
|
||||
matters */
|
||||
any = cg.zeroany;
|
||||
any.a_obj = &dummyobj;
|
||||
/* tip to floor does not require free hands */
|
||||
Sprintf(on_the_surface, "on the %s", surface(u.ux, u.uy));
|
||||
add_menu(win, &nul_glyphinfo, &any, '-', 0, ATR_NONE, clr,
|
||||
on_the_surface, MENU_ITEMFLAGS_SELECTED);
|
||||
add_menu_str(win, "");
|
||||
|
||||
dummyobj = cg.zeroobj; /* lint suppression; only its address matters */
|
||||
any = cg.zeroany;
|
||||
any.a_obj = &dummyobj;
|
||||
/* tip to floor does not require free hands */
|
||||
add_menu(win, &nul_glyphinfo, &any, '-', 0, ATR_NONE, clr,
|
||||
/* [TODO? vary destination string depending on surface()] */
|
||||
"on the floor", MENU_ITEMFLAGS_SELECTED);
|
||||
add_menu_str(win, "");
|
||||
|
||||
n_conts = 0;
|
||||
for (otmp = gi.invent; otmp; otmp = otmp->nobj) {
|
||||
if (otmp == box)
|
||||
continue;
|
||||
/* skip non-containers; bag of tricks passes Is_container() test,
|
||||
only include it if it isn't known to be a bag of tricks */
|
||||
if (!Is_container(otmp)
|
||||
|| (otmp->otyp == BAG_OF_TRICKS && otmp->dknown
|
||||
&& objects[otmp->otyp].oc_name_known))
|
||||
continue;
|
||||
if (!n_conts++)
|
||||
hands_available = u_handsy(); /* might issue message */
|
||||
/* container-to-container tip requires free hands;
|
||||
exclude container as possible target when known to be locked */
|
||||
exclude_it = !hands_available || (otmp->olocked && otmp->lknown);
|
||||
any = cg.zeroany;
|
||||
any.a_obj = !exclude_it ? otmp : 0;
|
||||
Sprintf(buf, "%s%s", !exclude_it ? "" : " ", doname(otmp));
|
||||
tmpglyph = obj_to_glyph(otmp, rn2_on_display_rng);
|
||||
map_glyphinfo(0, 0, tmpglyph, 0U, &tmpglyphinfo);
|
||||
add_menu(win, &tmpglyphinfo, &any, !exclude_it ? otmp->invlet : 0, 0,
|
||||
ATR_NONE, clr, buf, MENU_ITEMFLAGS_NONE);
|
||||
n_conts = 0;
|
||||
}
|
||||
for (otmp = gi.invent; otmp; otmp = otmp->nobj) {
|
||||
if (otmp == box)
|
||||
continue;
|
||||
/* skip non-containers; bag of tricks passes Is_container() test,
|
||||
only include it if it isn't known to be a bag of tricks */
|
||||
if (!Is_container(otmp)
|
||||
|| (otmp->otyp == BAG_OF_TRICKS && otmp->dknown
|
||||
&& objects[otmp->otyp].oc_name_known))
|
||||
continue;
|
||||
if (!n_conts++)
|
||||
hands_available = u_handsy(); /* might issue message */
|
||||
/* container-to-container tip requires free hands;
|
||||
exclude container as possible target when known to be locked */
|
||||
exclude_it = !hands_available || (otmp->olocked && otmp->lknown);
|
||||
if (looppass == 0) {
|
||||
if (!exclude_it)
|
||||
count_tiptargets++;
|
||||
} else {
|
||||
any = cg.zeroany;
|
||||
any.a_obj = !exclude_it ? otmp : 0;
|
||||
Sprintf(buf, "%s%s", !exclude_it ? "" : " ", doname(otmp));
|
||||
tmpglyph = obj_to_glyph(otmp, rn2_on_display_rng);
|
||||
map_glyphinfo(0, 0, tmpglyph, 0U, &tmpglyphinfo);
|
||||
add_menu(win, &tmpglyphinfo, &any,
|
||||
!exclude_it ? otmp->invlet : 0, 0, ATR_NONE, clr,
|
||||
buf, MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!skip_targetmenu) {
|
||||
Sprintf(buf, "Where to tip the contents of %s", doname(box));
|
||||
end_menu(win, buf);
|
||||
n = select_menu(win, PICK_ONE, &pick_list);
|
||||
destroy_nhwindow(win);
|
||||
|
||||
Sprintf(buf, "Where to tip the contents of %s", doname(box));
|
||||
end_menu(win, buf);
|
||||
n = select_menu(win, PICK_ONE, &pick_list);
|
||||
destroy_nhwindow(win);
|
||||
|
||||
otmp = 0;
|
||||
if (pick_list) {
|
||||
otmp = pick_list[0].item.a_obj;
|
||||
/* PICK_ONE with a preselected item might return 2;
|
||||
if so, choose the one that wasn't preselected */
|
||||
if (n > 1 && otmp == &dummyobj)
|
||||
otmp = pick_list[1].item.a_obj;
|
||||
if (otmp == &dummyobj)
|
||||
otmp = 0;
|
||||
free((genericptr_t) pick_list);
|
||||
otmp = 0;
|
||||
if (pick_list) {
|
||||
otmp = pick_list[0].item.a_obj;
|
||||
/* PICK_ONE with a preselected item might return 2;
|
||||
if so, choose the one that wasn't preselected */
|
||||
if (n > 1 && otmp == &dummyobj)
|
||||
otmp = pick_list[1].item.a_obj;
|
||||
if (otmp == &dummyobj)
|
||||
otmp = 0;
|
||||
free((genericptr_t) pick_list);
|
||||
}
|
||||
} else {
|
||||
otmp = 0;
|
||||
n = 0; /* don't flag as having been cancelled */
|
||||
}
|
||||
*cancelled = (boolean) (n == -1);
|
||||
return otmp;
|
||||
|
||||
Reference in New Issue
Block a user