Make saving grace also work against repeated damage sources
For example, being hit by the bounce of a wand of fire means that the main character could take damage twice in a turn, which would kill even through saving grace; and scrolls and potions could burn up after that and finish off the last HP, even if the wand only hit once. This commit changes it to track all damage done during the turn, and prevent HP dropping below 1 from damage until the next player action or the next turn boundary, whichever comes first.
This commit is contained in:
@@ -838,6 +838,9 @@ struct instance_globals_r {
|
||||
|
||||
struct instance_globals_s {
|
||||
|
||||
/* allmain.c */
|
||||
boolean saving_grace_turn; /* saving grace was triggered this turn */
|
||||
|
||||
/* artifact.c */
|
||||
int spec_dbon_applies; /* coordinate effects from spec_dbon() with
|
||||
messages in artifact_hit() */
|
||||
@@ -969,6 +972,9 @@ struct instance_globals_t {
|
||||
|
||||
struct instance_globals_u {
|
||||
|
||||
/* allmain.c */
|
||||
int uhp_at_start_of_monster_turn;
|
||||
|
||||
/* botl.c */
|
||||
boolean update_all;
|
||||
|
||||
|
||||
@@ -200,6 +200,7 @@ moveloop_core(void)
|
||||
encumber_msg();
|
||||
|
||||
svc.context.mon_moving = TRUE;
|
||||
gu.uhp_at_start_of_monster_turn = u.uhp;
|
||||
do {
|
||||
monscanmove = movemon();
|
||||
if (u.umovement >= NORMAL_SPEED)
|
||||
@@ -272,6 +273,8 @@ moveloop_core(void)
|
||||
if (u.ublesscnt)
|
||||
u.ublesscnt--;
|
||||
|
||||
gs.saving_grace_turn = FALSE;
|
||||
|
||||
/* One possible result of prayer is healing. Whether or
|
||||
* not you get healed depends on your current hit points.
|
||||
* If you are allowed to regenerate during the prayer,
|
||||
@@ -423,6 +426,8 @@ moveloop_core(void)
|
||||
else if (!u.umoved)
|
||||
(void) pooleffects(FALSE);
|
||||
|
||||
gs.saving_grace_turn = FALSE;
|
||||
|
||||
/* vision while buried or underwater is updated here */
|
||||
if (Underwater)
|
||||
under_water(0);
|
||||
|
||||
@@ -674,6 +674,8 @@ static const struct instance_globals_r g_init_r = {
|
||||
};
|
||||
|
||||
static const struct instance_globals_s g_init_s = {
|
||||
/* allmain.c */
|
||||
FALSE, /* saving_grace_turn */
|
||||
/* artifact.c */
|
||||
0, /* spec_dbon_applies */
|
||||
/* decl.c */
|
||||
@@ -764,6 +766,8 @@ static const struct instance_globals_t g_init_t = {
|
||||
};
|
||||
|
||||
static const struct instance_globals_u g_init_u = {
|
||||
/* allmain.c */
|
||||
0, /* uhp_at_start_of_monster_turn */
|
||||
/* botl.c */
|
||||
FALSE, /* update_all */
|
||||
/* decl.c */
|
||||
|
||||
25
src/hack.c
25
src/hack.c
@@ -4126,7 +4126,25 @@ saving_grace(int dmg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!u.usaving_grace && dmg >= u.uhp && (u.uhp * 100 / u.uhpmax) > 90) {
|
||||
if (!svc.context.mon_moving) {
|
||||
/* saving grace doesn't protect you from your own actions */
|
||||
return dmg;
|
||||
}
|
||||
|
||||
if (dmg < u.uhp || u.uhp <= 0) {
|
||||
/* no need for saving grace */
|
||||
return dmg;
|
||||
}
|
||||
|
||||
if (gs.saving_grace_turn) {
|
||||
/* saving grace already triggered and prevents HP reducing below 1
|
||||
this turn (specifically: until the next player action or turn
|
||||
boundary), don't print further messages or livelog entries */
|
||||
return u.uhp - 1;
|
||||
}
|
||||
|
||||
if (!u.usaving_grace &&
|
||||
(gu.uhp_at_start_of_monster_turn * 100 / u.uhpmax) >= 90) {
|
||||
/* saving_grace doesn't have it's own livelog classification;
|
||||
we might invent one, or perhaps use LL_LIFESAVE, but surviving
|
||||
certain death (or preserving worn amulet of life saving) via
|
||||
@@ -4135,11 +4153,14 @@ saving_grace(int dmg)
|
||||
from #chronicle during play but show it to livelog observers */
|
||||
livelog_printf(LL_CONDUCT | LL_SPOILER, "%s (%d damage, %d/%d HP)",
|
||||
"survived one-shot death via saving-grace",
|
||||
dmg, u.uhp, u.uhpmax);
|
||||
/* include damage that happened earlier this turn */
|
||||
gu.uhp_at_start_of_monster_turn - u.uhp + dmg,
|
||||
gu.uhp_at_start_of_monster_turn, u.uhpmax);
|
||||
|
||||
/* note: this could reduce dmg to 0 if u.uhpmax==1 */
|
||||
dmg = u.uhp - 1;
|
||||
u.usaving_grace = 1; /* used up */
|
||||
gs.saving_grace_turn = TRUE;
|
||||
end_running(TRUE);
|
||||
if (u.usleep)
|
||||
unmul("Suddenly you wake up!");
|
||||
|
||||
Reference in New Issue
Block a user