Add 'pickup_stolen' option

Add pickup_stolen option to autopick items stolen from you by a nymph or
monkey, even if they don't match your normal autopickup settings.
Replace was_dropped, was_thrown with a 2-bit bitfield that can contain
values LOST_DROPPED, LOST_THROWN, and LOST_STOLEN (or 0), since they
should all be mutually exclusive anyway as they track the most recent
way the item left the hero's inventory.

[Rebase/merge conflict fixed up.  PR]
This commit is contained in:
Michael Meyer
2023-11-17 09:37:16 -05:00
committed by PatR
parent ecda85cc32
commit 1736f3caaa
15 changed files with 54 additions and 23 deletions

View File

@@ -107,8 +107,7 @@ resetobjs(struct obj *ochain, boolean restore)
otmp->cknown = 0;
otmp->invlet = 0;
otmp->no_charge = 0;
otmp->was_thrown = 0;
otmp->was_dropped = 0;
otmp->how_lost = LOST_NONE;
/* strip user-supplied names */
/* Statue and some corpse names are left intact,

View File

@@ -760,7 +760,7 @@ drop(struct obj *obj)
if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose)
You("drop %s.", doname(obj));
}
obj->was_dropped = 1;
obj->how_lost = LOST_DROPPED;
dropx(obj);
return ECMD_TIME;
}

View File

@@ -1504,7 +1504,7 @@ throwit(struct obj *obj,
}
gt.thrownobj = obj;
gt.thrownobj->was_thrown = 1;
gt.thrownobj->how_lost = LOST_THROWN;
iflags.returning_missile = AutoReturn(obj, wep_mask) ? (genericptr_t) obj
: (genericptr_t) 0;
/* NOTE: No early returns after this point or returning_missile
@@ -1719,7 +1719,7 @@ throwit(struct obj *obj,
if (tethered_weapon)
tmp_at(DISP_END, 0);
/* when this location is stepped on, the weapon will be
auto-picked up due to 'obj->was_thrown' of 1;
auto-picked up due to 'obj->how_lost' of LOST_THROWN;
addinv() prevents thrown Mjollnir from being placed
into the quiver slot, but an aklys will end up there if
that slot is empty at the time; since hero will need to

View File

@@ -942,7 +942,8 @@ merged(struct obj **potmp, struct obj **pobj)
items, where this would be too spammy as such items get
unidentified by monsters very frequently). */
if (discovered && otmp->where == OBJ_INVENT
&& !obj->was_thrown && !otmp->was_thrown) {
&& obj->how_lost != LOST_THROWN
&& otmp->how_lost != LOST_THROWN) {
pline("You learn more about your items by comparing them.");
}
@@ -1049,8 +1050,8 @@ addinv_core0(struct obj *obj, struct obj *other_obj,
obj->no_charge = 0; /* should not be set in hero's invent */
if (Has_contents(obj))
picked_container(obj); /* clear no_charge */
obj_was_thrown = obj->was_thrown;
obj->was_thrown = obj->was_dropped = 0; /* not meaningful for invent */
obj_was_thrown = (obj->how_lost == LOST_THROWN);
obj->how_lost = LOST_NONE;
if (gl.loot_reset_justpicked) {
gl.loot_reset_justpicked = FALSE;
@@ -4823,8 +4824,7 @@ mergable(
if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
|| obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
|| obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
|| obj->was_thrown != otmp->was_thrown
|| obj->was_dropped != otmp->was_dropped)
|| obj->how_lost != otmp->how_lost)
return FALSE;
if (obj->oclass == FOOD_CLASS

View File

@@ -2863,9 +2863,10 @@ objlist_sanity(struct obj *objlist, int wheretype, const char *mesg)
for (obj = objlist; obj; obj = obj->nobj) {
if (obj->where != wheretype)
insane_object(obj, ofmt0, mesg, (struct monst *) 0);
if (obj->was_thrown && obj->was_dropped) {
insane_object(obj, "%s obj is both thrown and dropped! %s %s: %s",
mesg, obj->ocarry);
if (obj->where == OBJ_INVENT && obj->how_lost != LOST_NONE) {
char lostbuf[40];
Sprintf(lostbuf, "how_lost=%d obj in inventory!", obj->how_lost);
insane_object(obj, ofmt0, lostbuf, (struct monst *) 0);
}
if (Has_contents(obj)) {
if (wheretype == OBJ_ONBILL)

View File

@@ -312,7 +312,7 @@ l_obj_to_table(lua_State *L)
nhl_add_table_entry_int(L, "globby", obj->globby);
nhl_add_table_entry_int(L, "greased", obj->greased);
nhl_add_table_entry_int(L, "nomerge", obj->nomerge);
nhl_add_table_entry_int(L, "was_thrown", obj->was_thrown);
nhl_add_table_entry_int(L, "how_lost", obj->how_lost);
nhl_add_table_entry_int(L, "in_use", obj->in_use);
nhl_add_table_entry_int(L, "bypass", obj->bypass);
nhl_add_table_entry_int(L, "cknown", obj->cknown);

View File

@@ -8594,6 +8594,7 @@ doset_simple_menu(void)
spelling of their names; emphasize what it means */
if (allopt[i].idx == opt_pickup_types
|| allopt[i].idx == opt_pickup_thrown
|| allopt[i].idx == opt_pickup_stolen
|| allopt[i].idx == opt_dropped_nopick)
Strcat(buf, " (for autopickup)");
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,

View File

@@ -904,10 +904,12 @@ autopick_testobj(struct obj *otmp, boolean calc_costly)
if (costly && !otmp->no_charge)
return FALSE;
/* pickup_thrown/nopick_dropped override pickup_types and exceptions */
if (flags.pickup_thrown && otmp->was_thrown)
/* pickup_thrown/pickup_stolen/nopick_dropped override pickup_types and
exceptions */
if ((flags.pickup_thrown && otmp->how_lost == LOST_THROWN)
|| (flags.pickup_stolen && otmp->how_lost == LOST_STOLEN))
return TRUE;
if (flags.nopick_dropped && otmp->was_dropped)
if (flags.nopick_dropped && otmp->how_lost == LOST_DROPPED)
return FALSE;
/* check for pickup_types */
@@ -3667,7 +3669,7 @@ tipcontainer(struct obj *box) /* or bag */
(void) add_to_container(targetbox, otmp);
}
} else if (highdrop) {
otmp->was_dropped = 1;
otmp->how_lost = LOST_DROPPED;
/* might break or fall down stairs; handles altars itself */
hitfloor(otmp, TRUE);
} else {
@@ -3680,7 +3682,7 @@ tipcontainer(struct obj *box) /* or bag */
pline("%s%c", doname(otmp), nobj ? ',' : '.');
iflags.last_msg = PLNMSG_OBJNAM_ONLY;
}
otmp->was_dropped = 1;
otmp->how_lost = LOST_DROPPED;
dropy(otmp);
if (iflags.last_msg != PLNMSG_OBJNAM_ONLY)
terse = FALSE; /* terse formatting has been interrupted */

View File

@@ -527,6 +527,7 @@ steal(struct monst* mtmp, char* objnambuf)
(void) encumber_msg();
could_petrify = (otmp->otyp == CORPSE
&& touch_petrifies(&mons[otmp->corpsenm]));
otmp->how_lost = LOST_STOLEN;
(void) mpickobj(mtmp, otmp); /* may free otmp */
if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) {
minstapetrify(mtmp, TRUE);