fix pull request #470 - two riding fixes

Post-3.6 change to monster inventory handling could result in hero
remaining mounted on an unsaddled steed (if saddle was removed via
opening magic).

Hero falling out of saddle would fall to the ground and take damage
even if levitating or flying without steed's help after dismount.

Fixes #470
This commit is contained in:
PatR
2021-03-16 11:01:43 -07:00
parent b3d21fd337
commit 0cca010ff1
4 changed files with 34 additions and 19 deletions
+3
View File
@@ -410,6 +410,8 @@ remove superfluous "All" from "All foos are already nonexistent." when blessed
genocide tries to remove something which has already been genocided genocide tries to remove something which has already been genocided
"#dip <item> into -" produced a scrambled message: "#dip <item> into -" produced a scrambled message:
You mime dip <item> intoing something. You mime dip <item> intoing something.
mounted hero falling out of saddle shouldn't hit ground and take damage when
levitating or flying (if done without steed's help)
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
@@ -540,6 +542,7 @@ change wizard mode command #wizmgender to wizard mode option 'wizmgender'
engraving with non-blade dulled the weapon anyway (pr #464) engraving with non-blade dulled the weapon anyway (pr #464)
'sortdiscoveries:s' had a spurious generic header shown at the start of the 'sortdiscoveries:s' had a spurious generic header shown at the start of the
last class if there were any artifacts or unique items discovered last class if there were any artifacts or unique items discovered
loss of saddle by opening magic left hero mounted on unsaddled steed
curses: 'msg_window' option wasn't functional for curses unless the binary curses: 'msg_window' option wasn't functional for curses unless the binary
also included tty support also included tty support
+1 -1
View File
@@ -671,7 +671,7 @@ mdrop_obj(
boolean verbosely) boolean verbosely)
{ {
int omx = mon->mx, omy = mon->my; int omx = mon->mx, omy = mon->my;
boolean unwornmask = obj->owornmask; long unwornmask = obj->owornmask;
extract_from_minvent(mon, obj, FALSE, TRUE); extract_from_minvent(mon, obj, FALSE, TRUE);
/* don't charge for an owned saddle on dead steed (provided /* don't charge for an owned saddle on dead steed (provided
+16 -8
View File
@@ -482,30 +482,38 @@ dismount_steed(
{ {
struct monst *mtmp; struct monst *mtmp;
struct obj *otmp; struct obj *otmp;
const char *verb;
coord cc, steedcc; coord cc, steedcc;
const char *verb = "fall";
boolean repair_leg_damage = (Wounded_legs != 0L);
unsigned save_utrap = u.utrap; unsigned save_utrap = u.utrap;
boolean have_spot = landing_spot(&cc, reason, 0); boolean ulev, ufly,
repair_leg_damage = (Wounded_legs != 0L),
have_spot = landing_spot(&cc, reason, 0);
mtmp = u.usteed; /* make a copy of steed pointer */ mtmp = u.usteed; /* make a copy of steed pointer */
/* Sanity check */ /* Sanity check */
if (!mtmp) /* Just return silently */ if (!mtmp) /* Just return silently */
return; return;
u.usteed = 0; /* affects Fly test; could hypothetically affect Lev */
ufly = Flying ? TRUE : FALSE;
ulev = Levitation ? TRUE : FALSE;
u.usteed = mtmp;
/* Check the reason for dismounting */ /* Check the reason for dismounting */
otmp = which_armor(mtmp, W_SADDLE); otmp = which_armor(mtmp, W_SADDLE);
switch (reason) { switch (reason) {
case DISMOUNT_THROWN: case DISMOUNT_THROWN:
verb = "are thrown";
/*FALLTHRU*/
case DISMOUNT_FELL: case DISMOUNT_FELL:
verb = (reason == DISMOUNT_THROWN) ? "are thrown"
: ulev ? "float" : ufly ? "fly" : "fall";
You("%s off of %s!", verb, mon_nam(mtmp)); You("%s off of %s!", verb, mon_nam(mtmp));
if (!have_spot) if (!have_spot)
have_spot = landing_spot(&cc, reason, 1); have_spot = landing_spot(&cc, reason, 1);
losehp(Maybe_Half_Phys(rn1(10, 10)), "riding accident", KILLED_BY_AN); if (!ulev && !ufly) {
set_wounded_legs(BOTH_SIDES, (int) HWounded_legs + rn1(5, 5)); losehp(Maybe_Half_Phys(rn1(10, 10)), "riding accident",
repair_leg_damage = FALSE; KILLED_BY_AN);
set_wounded_legs(BOTH_SIDES, (int) HWounded_legs + rn1(5, 5));
repair_leg_damage = FALSE;
}
break; break;
case DISMOUNT_POLY: case DISMOUNT_POLY:
You("can no longer ride %s.", mon_nam(u.usteed)); You("can no longer ride %s.", mon_nam(u.usteed));
+14 -10
View File
@@ -1035,20 +1035,24 @@ racial_exception(struct monst *mon, struct obj *obj)
return 0; return 0;
} }
/* Remove an object from a monster's inventory. /* Remove an object from a monster's inventory. */
* At its core this is just obj_extract_self(), but it also handles any updates
* that needs to happen if the gear is equipped or in some other sort of state
* that needs handling.
* Note that like obj_extract_self(), this leaves obj free. */
void void
extract_from_minvent(struct monst *mon, struct obj *obj, extract_from_minvent(
boolean do_intrinsics, /* whether to call struct monst *mon,
update_mon_intrinsics */ struct obj *obj,
boolean silently) /* doesn't affect all possible messages, boolean do_intrinsics, /* whether to call update_mon_intrinsics */
just update_mon_intrinsics's */ boolean silently) /* doesn't affect all possible messages,
* just update_mon_intrinsics's */
{ {
long unwornmask = obj->owornmask; long unwornmask = obj->owornmask;
/*
* At its core this is just obj_extract_self(), but it also handles
* any updates that need to happen if the gear is equipped or in
* some other sort of state that needs handling.
* Note that like obj_extract_self(), this leaves obj free.
*/
if (obj->where != OBJ_MINVENT) { if (obj->where != OBJ_MINVENT) {
impossible("extract_from_minvent called on object not in minvent"); impossible("extract_from_minvent called on object not in minvent");
return; return;