From: <gi...@cr...> - 2011-04-29 12:48:13
|
discards dc95d1435f0fbcb834d056eed53fe7c2f240020e (commit) via 77b712376b5f18b93d8034bc17c81c7b85d02580 (commit) This update added new revisions after undoing existing revisions. That is to say, the old revision is not a strict subset of the new revision. This situation occurs when you --force push a change and generate a repository containing something like this: * -- * -- B -- O -- O -- O (dc95d1435f0fbcb834d056eed53fe7c2f240020e) \ N -- N -- N (77b712376b5f18b93d8034bc17c81c7b85d02580) When this happens we assume that you've already had alert emails for all of the O revisions, and so we here report only the revisions in the N branch from the common base, B. ----------------------------------------------------------------------- commit 77b712376b5f18b93d8034bc17c81c7b85d02580 Author: Robert Burnham <bur...@gm...> Date: Fri Apr 29 07:19:54 2011 -0500 Undo revert, fix a variable mistyping, misc changes Undo the revert of the externalization of monster attack rounds. Fixes the problems where monsters would never miss (I thought it was related to the externliazation, but it was just ev_margin in attack.h being of type bool instead of int. Re-implement effective_attack_number and track it both inside and outside of melee_attack (as necessary). ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/attack.h | 2 +- crawl-ref/source/fight.cc | 86 +++++- crawl-ref/source/melee_attack.cc | 676 +++++++++++++++++--------------------- crawl-ref/source/melee_attack.h | 5 +- 4 files changed, 385 insertions(+), 384 deletions(-) diff --git a/crawl-ref/source/attack.h b/crawl-ref/source/attack.h index 4cf2258..3239791 100644 --- a/crawl-ref/source/attack.h +++ b/crawl-ref/source/attack.h @@ -54,7 +54,7 @@ public: // Fetched/Calculated from the attacker, stored to save execution time bool unarmed_capable; - bool ev_margin; + int ev_margin; item_def *weapon; brand_type damage_brand; diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index e1b345a..a45b0e1 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -15,6 +15,7 @@ #include "externs.h" #include "cloud.h" +#include "coordit.h" #include "debug.h" #include "delay.h" #include "env.h" @@ -96,8 +97,89 @@ bool fight_melee(actor *attacker, actor *defender, bool allow_unarmed) return (true); } - melee_attack attk(attacker, defender, allow_unarmed); - return (attk.attack()); + // If execution gets here, attacker != Player, so we can safely continue + // with processing the number of attacks a monster has without worrying + // about unpredictable or wierd results from players. + + const int nrounds = attacker->as_monster()->has_hydra_multi_attack() ? + attacker->as_monster()->number : 4; + coord_def pos = defender->pos(); + + // Melee combat, tell attacker to wield its melee weapon. + attacker->as_monster()->wield_melee_weapon(); + + int effective_attack_number = 0; + int attack_number; + for (attack_number = 0; attack_number < nrounds && attacker->alive(); + ++attack_number, ++effective_attack_number) + { + if (!attacker->alive()) + return (false); + + // Monster went away? + if (!defender->alive() || defender->pos() != pos) + { + if (attacker == defender + || !attacker->as_monster()->has_multitargeting()) + { + break; + } + + // Hydras can try and pick up a new monster to attack to + // finish out their round. -cao + bool end = true; + for (adjacent_iterator i(attacker->pos()); i; ++i) + { + if (*i == you.pos() + && !mons_aligned(attacker, &you)) + { + attacker->as_monster()->foe = MHITYOU; + attacker->as_monster()->target = you.pos(); + defender = &you; + end = false; + break; + } + + monster* mons = monster_at(*i); + if (mons && !mons_aligned(attacker, mons)) + { + defender = mons; + end = false; + pos = mons->pos(); + break; + } + } + + // No adjacent hostiles. + if (end) + break; + } + + mon_attack_def attk = mons_attack_spec(attacker->as_monster(), + attack_number); + + if (attk.type == AT_NONE) + { + // Make sure the monster uses up some energy, even though it + // didn't actually attack. + if (effective_attack_number == 0) + attacker->as_monster()->lose_energy(EUT_ATTACK); + break; + } + // Skip dummy attacks. + if ((!allow_unarmed && attk.type != AT_HIT && attk.flavour != AF_REACH) + || attk.type == AT_SHOOT) + { + --effective_attack_number; + continue; + } + + melee_attack melee_attk(attacker, defender, allow_unarmed, attack_number, + effective_attack_number); + melee_attk.attack(); + } + + return (true); } // This function returns the "extra" stats the player gets because of diff --git a/crawl-ref/source/melee_attack.cc b/crawl-ref/source/melee_attack.cc index 9b1b34b..3e2fed9 100644 --- a/crawl-ref/source/melee_attack.cc +++ b/crawl-ref/source/melee_attack.cc @@ -91,16 +91,18 @@ * BEGIN PUBLIC FUNCTIONS * ************************************************** */ -melee_attack::melee_attack(actor *attk, actor *defn, bool allow_unarmed) +melee_attack::melee_attack(actor *attk, actor *defn, bool allow_unarmed, + int attack_num, int effective_attack_num) : // Call attack's constructor attack::attack(attk, defn, allow_unarmed), - perceived_attack(false), obvious_effect(false), - attack_number(-1), extra_noise(0), skip_chaos_message(false), - special_damage_flavour(BEAM_NONE), attacker_body_armour_penalty(0), - attacker_shield_penalty(0), attacker_armour_tohit_penalty(0), - attacker_shield_tohit_penalty(0), can_do_unarmed(false), miscast_level(-1), - miscast_type(SPTYP_NONE), miscast_target(NULL) + perceived_attack(false), obvious_effect(false), attack_number(attack_num), + effective_attack_number(effective_attack_num), extra_noise(0), + skip_chaos_message(false), special_damage_flavour(BEAM_NONE), + attacker_body_armour_penalty(0), attacker_shield_penalty(0), + attacker_armour_tohit_penalty(0), attacker_shield_tohit_penalty(0), + can_do_unarmed(false), miscast_level(-1), miscast_type(SPTYP_NONE), + miscast_target(NULL) { init_attack(); } @@ -4438,441 +4440,374 @@ bool melee_attack::do_knockback(bool trample) return false; } -void melee_attack::mons_perform_attack_rounds() +bool melee_attack::mons_perform_attack() { - const int nrounds = attacker->as_monster()->has_hydra_multi_attack() ? - attacker->as_monster()->number : 4; - coord_def pos = defender->pos(); + coord_def pos = defender->pos(); const bool was_delayed = you_are_delayed(); + monster* def_copy = NULL; - // Melee combat, tell attacker to wield its melee weapon. - attacker->as_monster()->wield_melee_weapon(); + if (attacker != defender && attacker->self_destructs()) + return (did_hit = perceived_attack = true); - monster* def_copy = NULL; - int effective_attack_number = 0; - for (attack_number = 0; attack_number < nrounds && attacker->alive(); - ++attack_number, ++effective_attack_number) + if (attacker != defender && attack_warded_off()) { - // Handle noise from previous round. - if (effective_attack_number > 0) - handle_noise(pos); - - if (!attacker->alive()) - return; + // A warded-off attack takes half the normal energy. + attacker->lose_energy(EUT_ATTACK, 2); - // Monster went away? - if (!defender->alive() || defender->pos() != pos) - { - if (attacker == defender - || !attacker->as_monster()->has_multitargeting()) - { - break; - } + perceived_attack = true; + return (false); + } - // Hydras can try and pick up a new monster to attack to - // finish out their round. -cao - bool end = true; - for (adjacent_iterator i(attacker->pos()); i; ++i) - { - if (*i == you.pos() - && !mons_aligned(attacker, &you)) - { - attacker->as_monster()->foe = MHITYOU; - attacker->as_monster()->target = you.pos(); - defender = &you; - end = false; - break; - } + mon_attack_def attk = mons_attack_spec(attacker->as_monster(), + attack_number); + if (attk.type == AT_WEAP_ONLY) + { + int weap = attacker->as_monster()->inv[MSLOT_WEAPON]; + if (weap == NON_ITEM) + attk.type = AT_NONE; + else if (is_range_weapon(mitm[weap])) + attk.type = AT_SHOOT; + else + attk.type = AT_HIT; + } - monster* mons = monster_at(*i); - if (mons && !mons_aligned(attacker, mons)) - { - defender = mons; - end = false; - pos = mons->pos(); - break; - } - } + if (weapon == NULL) + { + switch (attk.type) + { + case AT_HEADBUTT: + case AT_TENTACLE_SLAP: + case AT_TAIL_SLAP: + case AT_TRAMPLE: + case AT_TRUNK_SLAP: + noise_factor = 150; + break; - // No adjacent hostiles. - if (end) - break; - } + case AT_HIT: + case AT_PUNCH: + case AT_KICK: + case AT_CLAW: + case AT_GORE: + case AT_SNAP: + case AT_SPLASH: + noise_factor = 125; + break; - // Monsters hitting themselves get just one round. - if (attack_number > 0 && attacker == defender) + case AT_BITE: + case AT_PECK: + case AT_CONSTRICT: + noise_factor = 100; break; - init_attack(); + case AT_STING: + case AT_SPORE: + case AT_ENGULF: + noise_factor = 75; + break; - mon_attack_def attk = mons_attack_spec(attacker->as_monster(), - attack_number); - if (attk.type == AT_WEAP_ONLY) - { - int weap = attacker->as_monster()->inv[MSLOT_WEAPON]; - if (weap == NON_ITEM) - attk.type = AT_NONE; - else if (is_range_weapon(mitm[weap])) - attk.type = AT_SHOOT; - else - attk.type = AT_HIT; - } + case AT_TOUCH: + noise_factor = 0; + break; - if (attk.type == AT_NONE) - { - // Make sure the monster uses up some energy, even though it - // didn't actually attack. - if (effective_attack_number == 0) - attacker->as_monster()->lose_energy(EUT_ATTACK); + // To prevent compiler warnings. + case AT_NONE: + case AT_RANDOM: + case AT_SHOOT: + die("Invalid attack flavour for noise_factor"); break; - } - // Skip dummy attacks. - if ((!unarmed_ok && attk.type != AT_HIT && attk.flavour != AF_REACH) - || attk.type == AT_SHOOT) - { - --effective_attack_number; - continue; + default: + die("Unhandled attack flavour for noise_factor"); + break; } - if (weapon == NULL) + switch(attk.flavour) { - switch (attk.type) - { - case AT_HEADBUTT: - case AT_TENTACLE_SLAP: - case AT_TAIL_SLAP: - case AT_TRAMPLE: - case AT_TRUNK_SLAP: - noise_factor = 150; - break; + case AF_FIRE: + noise_factor += 50; + break; - case AT_HIT: - case AT_PUNCH: - case AT_KICK: - case AT_CLAW: - case AT_GORE: - case AT_SNAP: - case AT_SPLASH: - noise_factor = 125; - break; + case AF_ELEC: + noise_factor += 100; + break; - case AT_BITE: - case AT_PECK: - case AT_CONSTRICT: - noise_factor = 100; - break; + default: + break; + } + } - case AT_STING: - case AT_SPORE: - case AT_ENGULF: - noise_factor = 75; - break; + damage_done = 0; + mons_set_weapon(attk); + to_hit = calc_to_hit(); - case AT_TOUCH: - noise_factor = 0; - break; + const bool chaos_attack = damage_brand == SPWPN_CHAOS + || (attk.flavour == AF_CHAOS + && attacker != defender); - // To prevent compiler warnings. - case AT_NONE: - case AT_RANDOM: - case AT_SHOOT: - die("Invalid attack flavour for noise_factor"); - break; + // Make copy of monster before monster_die() resets it. + if (chaos_attack && defender->atype() == ACT_MONSTER && !def_copy) + def_copy = new monster(*defender->as_monster()); - default: - die("Unhandled attack flavour for noise_factor"); - break; - } + final_attack_delay = calc_attack_delay(); + if (damage_brand == SPWPN_SPEED) + final_attack_delay = final_attack_delay / 2 + 1; - switch(attk.flavour) - { - case AF_FIRE: - noise_factor += 50; - break; + mons_lose_attack_energy(attacker->as_monster(), + final_attack_delay, + attack_number, + effective_attack_number); - case AF_ELEC: - noise_factor += 100; - break; + bool shield_blocked = false; + bool this_round_hit = false; - default: - break; - } + if (attacker != defender) + { + if (attack_shield_blocked(true)) + { + shield_blocked = true; + perceived_attack = true; + this_round_hit = did_hit = true; } + // XXX: what is the chance for here? + else if (attacker_visible && one_chance_in(3)) + { + perceived_attack = true; + if (defender == &you) + practise(EX_MONSTER_MAY_HIT); + } + } - damage_done = 0; - mons_set_weapon(attk); - to_hit = calc_to_hit(); - - const bool chaos_attack = damage_brand == SPWPN_CHAOS - || (attk.flavour == AF_CHAOS - && attacker != defender); - - // Make copy of monster before monster_die() resets it. - if (chaos_attack && defender->atype() == ACT_MONSTER && !def_copy) - def_copy = new monster(*defender->as_monster()); + if (!shield_blocked) + { + const int defender_evasion = defender->melee_evasion(attacker); + int defender_evasion_help + = defender->melee_evasion(attacker, EV_IGNORE_HELPLESS); + int defender_evasion_nophase + = defender->melee_evasion(attacker, EV_IGNORE_PHASESHIFT); - final_attack_delay = calc_attack_delay(); - if (damage_brand == SPWPN_SPEED) - final_attack_delay = final_attack_delay / 2 + 1; + defer_rand r; - mons_lose_attack_energy(attacker->as_monster(), - final_attack_delay, - attack_number, - effective_attack_number); + if (defender_invisible) + { + // No evasion feedback if we don't know what we're + // fighting. + defender_evasion_help = defender_evasion; + defender_evasion_nophase = defender_evasion; + } - bool shield_blocked = false; - bool this_round_hit = false; + ev_margin = test_melee_hit(to_hit, defender_evasion_help, r); - if (attacker != defender) + if (attacker == defender || ev_margin >= 0) { - if (attack_shield_blocked(true)) + // Will hit no matter what. + this_round_hit = true; + } + else if (test_melee_hit(to_hit, defender_evasion, r) >= 0) + { + if (needs_message) { - shield_blocked = true; - perceived_attack = true; - this_round_hit = did_hit = true; + mprf("Helpless, %s %s to dodge %s attack.", + mons_defender_name().c_str(), + defender->conj_verb("fail").c_str(), + atk_name(DESC_ITS).c_str()); } - // XXX: what is the chance for here? - else if (attacker_visible && one_chance_in(3)) + this_round_hit = true; + } + else if (test_melee_hit(to_hit, defender_evasion_nophase, r) >= 0) + { + if (needs_message) { - perceived_attack = true; - if (defender == &you) - practise(EX_MONSTER_MAY_HIT); + mprf("%s momentarily %s out as %s " + "attack passes through %s%s", + defender->name(DESC_THE).c_str(), + defender->conj_verb("phase").c_str(), + atk_name(DESC_ITS).c_str(), + defender->pronoun(PRONOUN_OBJECTIVE).c_str(), + attack_strength_punctuation().c_str()); } + this_round_hit = false; } - - if (!shield_blocked) + else { - const int defender_evasion = defender->melee_evasion(attacker); - int defender_evasion_help - = defender->melee_evasion(attacker, EV_IGNORE_HELPLESS); - int defender_evasion_nophase - = defender->melee_evasion(attacker, EV_IGNORE_PHASESHIFT); - - defer_rand r; - - if (defender_invisible) + // Misses no matter what. + if (needs_message) { - // No evasion feedback if we don't know what we're - // fighting. - defender_evasion_help = defender_evasion; - defender_evasion_nophase = defender_evasion; + mprf("%s%s misses %s%s", + atk_name(DESC_THE).c_str(), + evasion_margin_adverb().c_str(), + mons_defender_name().c_str(), + attack_strength_punctuation().c_str()); } + } - ev_margin = test_melee_hit(to_hit, defender_evasion_help, r); + if (this_round_hit) + { + did_hit = true; + perceived_attack = true; + damage_done = mons_calc_damage(attk); + } + else + { + perceived_attack = perceived_attack || attacker_visible; + } - if (attacker == defender || ev_margin >= 0) - { - // Will hit no matter what. - this_round_hit = true; - } - else if (test_melee_hit(to_hit, defender_evasion, r) >= 0) - { - if (needs_message) - { - mprf("Helpless, %s %s to dodge %s attack.", - mons_defender_name().c_str(), - defender->conj_verb("fail").c_str(), - atk_name(DESC_ITS).c_str()); - } - this_round_hit = true; - } - else if (test_melee_hit(to_hit, defender_evasion_nophase, r) >= 0) - { - if (needs_message) - { - mprf("%s momentarily %s out as %s " - "attack passes through %s%s", - defender->name(DESC_THE).c_str(), - defender->conj_verb("phase").c_str(), - atk_name(DESC_ITS).c_str(), - defender->pronoun(PRONOUN_OBJECTIVE).c_str(), - attack_strength_punctuation().c_str()); - } - this_round_hit = false; - } - else - { - // Misses no matter what. - if (needs_message) - { - mprf("%s%s misses %s%s", - atk_name(DESC_THE).c_str(), - evasion_margin_adverb().c_str(), - mons_defender_name().c_str(), - attack_strength_punctuation().c_str()); - } - } + if (attacker != defender && + defender->atype() == ACT_PLAYER && + (grid_distance(you.pos(), attacker->as_monster()->pos()) == 1 + || attk.flavour == AF_REACH)) + { + // Check for spiny mutation. + mons_do_spines(); - if (this_round_hit) - { - did_hit = true; - perceived_attack = true; - damage_done = mons_calc_damage(attk); - } - else - { - perceived_attack = perceived_attack || attacker_visible; - } + // Spines can kill! + if (!attacker->alive()) + return (false); + } + } - if (attacker != defender && - defender->atype() == ACT_PLAYER && - (grid_distance(you.pos(), attacker->as_monster()->pos()) == 1 - || attk.flavour == AF_REACH)) - { - // Check for spiny mutation. - mons_do_spines(); + if (check_unrand_effects()) + return (false); - // Spines can kill! - if (!attacker->alive()) - break; - } - } + if (damage_done < 1 && this_round_hit && !shield_blocked) + mons_announce_dud_hit(attk); - if (check_unrand_effects()) - break; + if (damage_done > 0) + { + if (shield_blocked) + dprf("ERROR: Non-zero damage after shield block!"); + mons_announce_hit(attk); - if (damage_done < 1 && this_round_hit && !shield_blocked) - mons_announce_dud_hit(attk); + if (defender == &you) + practise(EX_MONSTER_WILL_HIT); - if (damage_done > 0) + if (defender->can_bleed() + && !defender->is_summoned() + && !defender->submerged()) { - if (shield_blocked) - dprf("ERROR: Non-zero damage after shield block!"); - mons_announce_hit(attk); - - if (defender == &you) - practise(EX_MONSTER_WILL_HIT); + int blood = _modify_blood_amount(damage_done, + attacker->damage_type()); - if (defender->can_bleed() - && !defender->is_summoned() - && !defender->submerged()) - { - int blood = _modify_blood_amount(damage_done, - attacker->damage_type()); + if (blood > defender->stat_hp()) + blood = defender->stat_hp(); - if (blood > defender->stat_hp()) - blood = defender->stat_hp(); + bleed_onto_floor(pos, defender->type, blood, true); + } - bleed_onto_floor(pos, defender->type, blood, true); - } + if (decapitate_hydra(damage_done, + attacker->damage_type(attack_number))) + { + return (true); + } - if (decapitate_hydra(damage_done, - attacker->damage_type(attack_number))) - { - continue; - } + special_damage = 0; + special_damage_message.clear(); + special_damage_flavour = BEAM_NONE; - special_damage = 0; - special_damage_message.clear(); - special_damage_flavour = BEAM_NONE; + if (attacker != defender && attk.type == AT_TRAMPLE) + do_knockback(); - if (attacker != defender && attk.type == AT_TRAMPLE) - do_knockback(); + // Monsters attacking themselves don't get attack flavour. + // The message sequences look too weird. Also, stealing + // attacks aren't handled until after the damage msg. + if (attacker != defender && attk.flavour != AF_STEAL) + mons_apply_attack_flavour(attk); - // Monsters attacking themselves don't get attack flavour. - // The message sequences look too weird. Also, stealing - // attacks aren't handled until after the damage msg. - if (attacker != defender && attk.flavour != AF_STEAL) - mons_apply_attack_flavour(attk); + if (needs_message && !special_damage_message.empty()) + mprf("%s", special_damage_message.c_str()); - if (needs_message && !special_damage_message.empty()) - mprf("%s", special_damage_message.c_str()); + // Defender banished. Bail before chaos_killed_defender() + // is called, since the defender is still alive in the + // Abyss. + if (defender->is_banished()) + { + if (chaos_attack && attacker->alive()) + chaos_affects_attacker(); - // Defender banished. Bail before chaos_killed_defender() - // is called, since the defender is still alive in the - // Abyss. - if (defender->is_banished()) - { - if (chaos_attack && attacker->alive()) - chaos_affects_attacker(); + do_miscast(); + return (false); + } - do_miscast(); - break; - } + defender->hurt(attacker, damage_done + special_damage, + special_damage_flavour); - defender->hurt(attacker, damage_done + special_damage, - special_damage_flavour); + if (!defender->alive()) + { + if (chaos_attack && defender->atype() == ACT_MONSTER) + chaos_killed_defender(def_copy); - if (!defender->alive()) - { - if (chaos_attack && defender->atype() == ACT_MONSTER) - chaos_killed_defender(def_copy); + if (chaos_attack && attacker->alive()) + chaos_affects_attacker(); - if (chaos_attack && attacker->alive()) - chaos_affects_attacker(); + do_miscast(); + return (true); + } + // Yredelemnul's injury mirroring can kill the attacker. + // Also, bail if the monster is attacking itself without a + // weapon, since intrinsic monster attack flavours aren't + // applied for self-attacks. + if (!attacker->alive() || (attacker == defender && !weapon)) + { + if (miscast_target == defender) do_miscast(); - continue; - } - - // Yredelemnul's injury mirroring can kill the attacker. - // Also, bail if the monster is attacking itself without a - // weapon, since intrinsic monster attack flavours aren't - // applied for self-attacks. - if (!attacker->alive() || (attacker == defender && !weapon)) - { - if (miscast_target == defender) - do_miscast(); - break; - } - - special_damage = 0; - special_damage_message.clear(); - special_damage_flavour = BEAM_NONE; - apply_damage_brand(); - - if (needs_message && !special_damage_message.empty()) - { - mprf("%s", special_damage_message.c_str()); - // Don't do message-only miscasts along with a special - // damage message. - if (miscast_level == 0) - miscast_level = -1; - } + return (false); + } - if (special_damage > 0) - defender->hurt(attacker, special_damage, special_damage_flavour); + special_damage = 0; + special_damage_message.clear(); + special_damage_flavour = BEAM_NONE; + apply_damage_brand(); - if (!defender->alive()) - { - if (chaos_attack && defender->atype() == ACT_MONSTER) - chaos_killed_defender(def_copy); + if (needs_message && !special_damage_message.empty()) + { + mprf("%s", special_damage_message.c_str()); + // Don't do message-only miscasts along with a special + // damage message. + if (miscast_level == 0) + miscast_level = -1; + } - if (chaos_attack && attacker->alive()) - chaos_affects_attacker(); + if (special_damage > 0) + defender->hurt(attacker, special_damage, special_damage_flavour); - do_miscast(); - continue; - } + if (!defender->alive()) + { + if (chaos_attack && defender->atype() == ACT_MONSTER) + chaos_killed_defender(def_copy); if (chaos_attack && attacker->alive()) chaos_affects_attacker(); - if (miscast_target == defender) - do_miscast(); + do_miscast(); + return (true); + } - // Yredelemnul's injury mirroring can kill the attacker. - if (!attacker->alive()) - break; + if (chaos_attack && attacker->alive()) + chaos_affects_attacker(); - if (miscast_target == attacker) - do_miscast(); + if (miscast_target == defender) + do_miscast(); - // Miscast might have killed the attacker. - if (!attacker->alive()) - break; + // Yredelemnul's injury mirroring can kill the attacker. + if (!attacker->alive()) + return (false); - if (attk.flavour == AF_STEAL) - mons_apply_attack_flavour(attk); - } + if (miscast_target == attacker) + do_miscast(); - item_def *weap = attacker->as_monster()->mslot_item(MSLOT_WEAPON); - if (weap && you.can_see(attacker) && weap->cursed() - && is_range_weapon(*weap)) - { - set_ident_flags(*weap, ISFLAG_KNOW_CURSE); - } + // Miscast might have killed the attacker. + if (!attacker->alive()) + return (false); + + if (attk.flavour == AF_STEAL) + mons_apply_attack_flavour(attk); + } + + item_def *weap = attacker->as_monster()->mslot_item(MSLOT_WEAPON); + if (weap && you.can_see(attacker) && weap->cursed() + && is_range_weapon(*weap)) + { + set_ident_flags(*weap, ISFLAG_KNOW_CURSE); } // Check for passive freeze or eyeball mutation. @@ -4895,23 +4830,6 @@ void melee_attack::mons_perform_attack_rounds() { handle_interrupted_swap(false, true); } -} - -bool melee_attack::mons_perform_attack() -{ - if (attacker != defender && attacker->self_destructs()) - return (did_hit = perceived_attack = true); - - if (attacker != defender && attack_warded_off()) - { - // A warded-off attack takes half the normal energy. - attacker->lose_energy(EUT_ATTACK, 2); - - perceived_attack = true; - return (false); - } - - mons_perform_attack_rounds(); return (did_hit); } diff --git a/crawl-ref/source/melee_attack.h b/crawl-ref/source/melee_attack.h index 00d5bad..a9e9434 100644 --- a/crawl-ref/source/melee_attack.h +++ b/crawl-ref/source/melee_attack.h @@ -31,6 +31,7 @@ public: // mon_attack_def stuff int attack_number; + int effective_attack_number; int extra_noise; @@ -56,7 +57,8 @@ public: actor* miscast_target; public: - melee_attack(actor *attacker, actor *defender, bool allow_unarmed = true); + melee_attack(actor *attacker, actor *defender, bool allow_unarmed = true, + int attack_num = -1, int effective_attack_num = -1); // Applies attack damage and other effects. bool attack(); @@ -128,7 +130,6 @@ private: int mons_calc_damage(const mon_attack_def &attk); void mons_apply_attack_flavour(const mon_attack_def &attk); bool mons_perform_attack(); - void mons_perform_attack_rounds(); std::string mons_attack_verb(const mon_attack_def &attk); std::string mons_attack_desc(const mon_attack_def &attk); void mons_announce_hit(const mon_attack_def &attk); -- Dungeon Crawl Stone Soup |