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:
Alex Smith
2025-11-26 05:45:45 +00:00
parent 6eb2eb7df7
commit 4d55e1de79
4 changed files with 38 additions and 2 deletions

View File

@@ -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!");