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 menu_loot(int, boolean);
|
||||||
staticfn int tip_ok(struct obj *);
|
staticfn int tip_ok(struct obj *);
|
||||||
staticfn int choose_tip_container_menu(void);
|
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 int tipcontainer_checks(struct obj *, struct obj *, boolean);
|
||||||
staticfn char in_or_out_menu(const char *, struct obj *, boolean, boolean,
|
staticfn char in_or_out_menu(const char *, struct obj *, boolean, boolean,
|
||||||
boolean, boolean);
|
boolean, boolean);
|
||||||
@@ -3607,10 +3607,25 @@ dotip(void)
|
|||||||
} else {
|
} else {
|
||||||
for (cobj = svl.level.objects[cc.x][cc.y]; cobj;
|
for (cobj = svl.level.objects[cc.x][cc.y]; cobj;
|
||||||
cobj = nobj) {
|
cobj = nobj) {
|
||||||
|
int target_count = 0;
|
||||||
|
boolean dum; /* argument placeholder, not actually used */
|
||||||
|
char prompt_part2[BUFSZ];
|
||||||
|
|
||||||
nobj = cobj->nexthere;
|
nobj = cobj->nexthere;
|
||||||
if (!Is_container(cobj))
|
if (!Is_container(cobj))
|
||||||
continue;
|
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,
|
cobj,
|
||||||
doname, ansimpleoname, "container"));
|
doname, ansimpleoname, "container"));
|
||||||
if (c == 'q')
|
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
|
* if 'box' is known to be empty or known to be locked, give up
|
||||||
* before choosing 'targetbox'.
|
* before choosing 'targetbox'.
|
||||||
*/
|
*/
|
||||||
targetbox = tipcontainer_gettarget(box, &cancelled);
|
targetbox = tipcontainer_gettarget(box, &cancelled, (int *) 0);
|
||||||
if (cancelled)
|
if (cancelled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -3876,16 +3891,17 @@ count_target_containers(
|
|||||||
staticfn struct obj *
|
staticfn struct obj *
|
||||||
tipcontainer_gettarget(
|
tipcontainer_gettarget(
|
||||||
struct obj *box,
|
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;
|
glyph_info tmpglyphinfo;
|
||||||
winid win;
|
winid win = WIN_ERR;
|
||||||
anything any;
|
anything any;
|
||||||
char buf[BUFSZ];
|
char buf[BUFSZ], on_the_surface[BUFSZ];
|
||||||
menu_item *pick_list = (menu_item *) 0;
|
menu_item *pick_list = (menu_item *) 0;
|
||||||
struct obj dummyobj, *otmp;
|
struct obj dummyobj, *otmp;
|
||||||
boolean hands_available = TRUE, exclude_it;
|
boolean hands_available = TRUE, exclude_it, skip_targetmenu = FALSE;
|
||||||
int clr = NO_COLOR;
|
int clr = NO_COLOR;
|
||||||
|
|
||||||
#if 0 /* [skip potential early return so that menu response is needed
|
#if 0 /* [skip potential early return so that menu response is needed
|
||||||
@@ -3899,58 +3915,88 @@ tipcontainer_gettarget(
|
|||||||
return (struct obj *) 0;
|
return (struct obj *) 0;
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
dummyobj = cg.zeroobj; /* lint suppression; only its address
|
||||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
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 */
|
n_conts = 0;
|
||||||
any = cg.zeroany;
|
}
|
||||||
any.a_obj = &dummyobj;
|
for (otmp = gi.invent; otmp; otmp = otmp->nobj) {
|
||||||
/* tip to floor does not require free hands */
|
if (otmp == box)
|
||||||
add_menu(win, &nul_glyphinfo, &any, '-', 0, ATR_NONE, clr,
|
continue;
|
||||||
/* [TODO? vary destination string depending on surface()] */
|
/* skip non-containers; bag of tricks passes Is_container() test,
|
||||||
"on the floor", MENU_ITEMFLAGS_SELECTED);
|
only include it if it isn't known to be a bag of tricks */
|
||||||
add_menu_str(win, "");
|
if (!Is_container(otmp)
|
||||||
|
|| (otmp->otyp == BAG_OF_TRICKS && otmp->dknown
|
||||||
n_conts = 0;
|
&& objects[otmp->otyp].oc_name_known))
|
||||||
for (otmp = gi.invent; otmp; otmp = otmp->nobj) {
|
continue;
|
||||||
if (otmp == box)
|
if (!n_conts++)
|
||||||
continue;
|
hands_available = u_handsy(); /* might issue message */
|
||||||
/* skip non-containers; bag of tricks passes Is_container() test,
|
/* container-to-container tip requires free hands;
|
||||||
only include it if it isn't known to be a bag of tricks */
|
exclude container as possible target when known to be locked */
|
||||||
if (!Is_container(otmp)
|
exclude_it = !hands_available || (otmp->olocked && otmp->lknown);
|
||||||
|| (otmp->otyp == BAG_OF_TRICKS && otmp->dknown
|
if (looppass == 0) {
|
||||||
&& objects[otmp->otyp].oc_name_known))
|
if (!exclude_it)
|
||||||
continue;
|
count_tiptargets++;
|
||||||
if (!n_conts++)
|
} else {
|
||||||
hands_available = u_handsy(); /* might issue message */
|
any = cg.zeroany;
|
||||||
/* container-to-container tip requires free hands;
|
any.a_obj = !exclude_it ? otmp : 0;
|
||||||
exclude container as possible target when known to be locked */
|
Sprintf(buf, "%s%s", !exclude_it ? "" : " ", doname(otmp));
|
||||||
exclude_it = !hands_available || (otmp->olocked && otmp->lknown);
|
tmpglyph = obj_to_glyph(otmp, rn2_on_display_rng);
|
||||||
any = cg.zeroany;
|
map_glyphinfo(0, 0, tmpglyph, 0U, &tmpglyphinfo);
|
||||||
any.a_obj = !exclude_it ? otmp : 0;
|
add_menu(win, &tmpglyphinfo, &any,
|
||||||
Sprintf(buf, "%s%s", !exclude_it ? "" : " ", doname(otmp));
|
!exclude_it ? otmp->invlet : 0, 0, ATR_NONE, clr,
|
||||||
tmpglyph = obj_to_glyph(otmp, rn2_on_display_rng);
|
buf, MENU_ITEMFLAGS_NONE);
|
||||||
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));
|
otmp = 0;
|
||||||
end_menu(win, buf);
|
if (pick_list) {
|
||||||
n = select_menu(win, PICK_ONE, &pick_list);
|
otmp = pick_list[0].item.a_obj;
|
||||||
destroy_nhwindow(win);
|
/* PICK_ONE with a preselected item might return 2;
|
||||||
|
if so, choose the one that wasn't preselected */
|
||||||
otmp = 0;
|
if (n > 1 && otmp == &dummyobj)
|
||||||
if (pick_list) {
|
otmp = pick_list[1].item.a_obj;
|
||||||
otmp = pick_list[0].item.a_obj;
|
if (otmp == &dummyobj)
|
||||||
/* PICK_ONE with a preselected item might return 2;
|
otmp = 0;
|
||||||
if so, choose the one that wasn't preselected */
|
free((genericptr_t) pick_list);
|
||||||
if (n > 1 && otmp == &dummyobj)
|
}
|
||||||
otmp = pick_list[1].item.a_obj;
|
} else {
|
||||||
if (otmp == &dummyobj)
|
otmp = 0;
|
||||||
otmp = 0;
|
n = 0; /* don't flag as having been cancelled */
|
||||||
free((genericptr_t) pick_list);
|
|
||||||
}
|
}
|
||||||
*cancelled = (boolean) (n == -1);
|
*cancelled = (boolean) (n == -1);
|
||||||
return otmp;
|
return otmp;
|
||||||
|
|||||||
Reference in New Issue
Block a user