Am I stupid? I don't see how the patch doubles damage done by the player. [PATCH] Fix a crash with cleaving + infusion vs spectral weapons. From e0bdd66d849c596fceac82094b8595117c4c4f9e Mon Sep 17...
Am I stupid? I don't see how the patch doubles damage done by the player.
[PATCH] Fix a crash with cleaving + infusion vs spectral weapons.
From e0bdd66d849c596fceac82094b8595117c4c4f9e Mon Sep 17 00:00:00 2001
From: Neil Moore <neil@s-z.org>
Date: Fri, 6 Mar 2015 11:31:13 -0500
Subject: [PATCH] Fix a crash with cleaving + infusion vs spectral weapons.
If we cleaved from the SW's caster (killing it) into the SW, the call
sequence melee_attack::handle_phase_hit() -> attack::calc_damage ->()
attack::player_stab() -> alert_nearby_monsters() could would cause the
SW to notice the dead caster and cease to exist. But then we check the
vanished SW's AC for infusion damage immediately afterwards, leading
to a crash:
http://dobrazupa.org/morgue/ihatethisgame/crash-ihatethisgame-20150302-235727.txt
Instead, calculate the infusion damage first, before calling
calc_damage.
Also, for robustness, add an extra check to prevent vampires trying to
drain already-reset monsters like these. This check isn't currently
necessary, because _player_vampire_draws_blood happens to think that
reset monsters have no blood.
---
crawl-ref/source/melee_attack.cc | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/crawl-ref/source/melee_attack.cc b/crawl-ref/source/melee_attack.cc
index d0528b7280b..e370089659b 100644
--- a/crawl-ref/source/melee_attack.cc
+++ b/crawl-ref/source/melee_attack.cc
@@ -412,6 +412,7 @@ bool melee_attack::handle_phase_hit()
}
}
+ damage_done = 0;
// Slimify does no damage and serves as an on-hit effect, handle it
if (attacker->is_player() && you.duration[DUR_SLIMIFY]
&& mon_can_be_slimified(defender->as_monster())
@@ -419,17 +420,12 @@ bool melee_attack::handle_phase_hit()
{
// Bail out after sliming so we don't get aux unarmed and
// attack a fellow slime.
- damage_done = 0;
slimify_monster(defender->as_monster());
you.duration[DUR_SLIMIFY] = 0;
return false;
}
- // This does more than just calculate the damage, it also sets up
- // messages, etc.
- damage_done = calc_damage();
-
if (attacker->is_player() && you.duration[DUR_INFUSION])
{
if (enough_mp(1, true, false))
@@ -443,12 +439,18 @@ bool melee_attack::handle_phase_hit()
if (hurt > 0)
{
- damage_done += hurt;
+ damage_done = hurt;
dec_mp(1);
}
}
}
+ // This does more than just calculate the damage, it also sets up
+ // messages, etc. It also wakes nearby creatures on a failed stab,
+ // meaning it could have made the attacked creature vanish. That
+ // will be checked early in player_monattack_hit_effects
+ damage_done += calc_damage();
+
bool stop_hit = false;
// Check if some hit-effect killed the monster.
if (attacker->is_player())
@@ -1879,6 +1881,12 @@ bool melee_attack::player_monattk_hit_effects()
{
player_weapon_upsets_god();
+ // Don't even check vampire bloodletting if the monster has already
+ // been reset (for example, a spectral weapon who noticed in
+ // player_stab_check that it shouldn't exist anymore).
+ if (defender->type == MONS_NO_MONSTER)
+ return false;
+
// Thirsty vampires will try to use a stabbing situation to draw blood.
if (you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED
&& damage_done > 0 && stab_attempt && stab_bonus > 0
This is the fixed commit, so maybe it's a better one to look at: https://github.com/crawl/crawl/commit/90bd1c500bff56e71350d45dbea52bac3bedbd97 The comment on it says: So it sounds like re-using a...
Am I stupid? I don't see how the patch doubles damage done by the player.
[PATCH] Fix a crash with cleaving + infusion vs spectral weapons.
This is the fixed commit, so maybe it's a better one to look at: https://github.com/crawl/crawl/commit/90bd1c500bff56e71350d45dbea52bac3bedbd97
The comment on it says:
So it sounds like re-using a class/object attribute caused it to be added to twice, ending up with double damage.
Oh. Turns out the problem is with C++ readability. I had no idea that was a class attribute.