diff options
-rw-r--r-- | crawl-ref/source/beam.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/effects.cc | 10 | ||||
-rw-r--r-- | crawl-ref/source/fight.cc | 110 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 24 | ||||
-rw-r--r-- | crawl-ref/source/spells3.cc | 17 |
5 files changed, 128 insertions, 39 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 8cc5e0ca6a..e52c26d624 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -2038,10 +2038,12 @@ void fire_beam(bolt &pbolt, item_def *item, bool drop_item) else if (pbolt.foe_helped > 0 && pbolt.fr_helped == 0) xom_is_stimulated(128); - // Allow friendlies to react to projectiles. + // Allow friendlies to react to projectiles, except when in + // Sanctuary when pet_target can only be explictly changed + // by the player. const monsters *mon = &menv[pbolt.beam_source]; if (pbolt.foe_hurt > 0 && !mons_wont_attack(mon) - && you.pet_target == MHITNOT) + && you.pet_target == MHITNOT && env.sanctuary_time <= 0) { you.pet_target = pbolt.beam_source; } diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index f45762c9b9..b3dfc3fbeb 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -2018,6 +2018,16 @@ void yell(bool force) return; } + if (env.sanctuary_time > 0) + { + if (!yesno("An ally attacking under your orders might violate " + "sanctuary; order anyways?", false, 'n')) + { + canned_msg(MSG_OK); + return; + } + } + mpr("Gang up on whom?", MSGCH_PROMPT); direction( targ, DIR_TARGET, TARG_ENEMY, -1, false, false ); diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 52be3c7d62..e59d750fda 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -524,6 +524,28 @@ bool melee_attack::attack() identify_mimic(atk); identify_mimic(def); + if (attacker->atype() == ACT_PLAYER && attacker != defender) + { + if (stop_attack_prompt(def, false, false)) + { + cancel_attack = true; + return (false); + } + } + + if (attacker != defender) + { + // Allow setting of your allies' target, etc. + attacker->attacking(defender); + + check_autoberserk(); + } + + // The attacker loses nutrition. + attacker->make_hungry(3, true); + + check_special_wield_effects(); + // Xom thinks fumbles are funny... if (attacker->fumbles_attack()) { @@ -537,6 +559,7 @@ bool melee_attack::attack() xom_is_stimulated(255); else xom_is_stimulated(14); + return (false); } // Non-fumbled self-attacks due to confusion are still pretty @@ -597,31 +620,13 @@ bool melee_attack::attack() return (true); } - // A lot of attack parameters get set in here. 'Ware. to_hit = calc_to_hit(); - // Allow setting of your allies' target, etc. - attacker->attacking(defender); - - // The attacker loses nutrition. - attacker->make_hungry(3, true); - - check_autoberserk(); - check_special_wield_effects(); - god_conduct_trigger conducts[3]; disable_attack_conducts(conducts); - if (attacker->atype() == ACT_PLAYER) - { - if (stop_attack_prompt(def, false, false)) - { - cancel_attack = true; - return (false); - } - else - set_attack_conducts(conducts, def); - } + if (attacker->atype() == ACT_PLAYER && attacker != defender) + set_attack_conducts(conducts, def); // Trying to stay general beyond this point is a recipe for insanity. // Maybe when Stone Soup hits 1.0... :-) @@ -629,6 +634,20 @@ bool melee_attack::attack() (defender->atype() == ACT_PLAYER) ? mons_attack_you() : mons_attack_mons()); + if (env.sanctuary_time > 0 && retval && !cancel_attack + && attacker != defender && !attacker->confused()) + { + const coord_def atk_pos = attacker->pos(); + const coord_def def_pos = defender->pos(); + + if (is_sanctuary(atk_pos.x, atk_pos.y) + || is_sanctuary(def_pos.x, def_pos.y)) + { + if (attacker->atype() == ACT_PLAYER || mons_friendly(atk)) + remove_sanctuary(true); + } + } + enable_attack_conducts(conducts); return retval; @@ -3098,6 +3117,40 @@ int melee_attack::player_calc_base_weapon_damage() bool melee_attack::mons_attack_mons() { + const coord_def atk_pos = atk->pos(); + const coord_def def_pos = def->pos(); + + // Self-attacks never violate sanctuary. + if ((is_sanctuary(atk_pos.x, atk_pos.y) + || is_sanctuary(def_pos.x, def_pos.y)) + && atk != def) + { + // Friendly monsters should only violate sanctuary if + // explictly ordered to do so by the player. + if (mons_friendly(atk)) + { + if (you.pet_target == MHITYOU || you.pet_target == MHITNOT) + { + if (atk->confused() && you.can_see(atk)) + mpr("Zin prevents your ally from violating sanctuary " + "in its confusion.", MSGCH_GOD); + else if (atk->has_ench(ENCH_BERSERK) && you.can_see(atk)) + mpr("Zin prevents your ally from violating sanctuary " + "in its berserker rage.", MSGCH_GOD); + + cancel_attack = true; + return (false); + } + } + // Non-friendly monsters should never violate sanctuary. + else + { + mpr("!!!! Preventing hostile violation of sanctuary"); + cancel_attack = true; + return (false); + } + } + mons_perform_attack(); if (perceived_attack && (def->foe == MHITNOT || one_chance_in(3)) @@ -3107,9 +3160,11 @@ bool melee_attack::mons_attack_mons() } // If an enemy attacked a friend, set the pet target if it isn't - // set already. + // set already, but not if Sanctuary is in effect (pet target must + // be set explicitly by the player during Sanctuary) if (perceived_attack && atk->alive() && mons_friendly(def) - && !mons_wont_attack(atk) && you.pet_target == MHITNOT) + && !mons_wont_attack(atk) && you.pet_target == MHITNOT + && env.sanctuary_time <= 0) { you.pet_target = monster_index(atk); } @@ -3950,8 +4005,10 @@ void melee_attack::mons_check_attack_perceived() { interrupt_activity(AI_MONSTER_ATTACKS, atk); - // If a friend wants to help, they can attack the attacking monster. - if (you.pet_target == MHITNOT) + // If a friend wants to help, they can attack the attacking monster, + // unless Sanctuary is in effect since pet target can only be + // changed explicitly by the player during sanctuary. + if (you.pet_target == MHITNOT && env.sanctuary_time <= 0) you.pet_target = monster_index(atk); } } @@ -4061,11 +4118,6 @@ bool you_attack(int monster_attacked, bool unarmed_attacks) return (false); } - if (is_sanctuary(you.x_pos, you.y_pos) - || is_sanctuary(defender->x, defender->y)) - { - remove_sanctuary(true); - } return (true); } diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 7b79da8b2f..4ad21c1801 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -2058,7 +2058,10 @@ void behaviour_event(monsters *mon, int event, int src, // Stationary monsters can't flee, even from sanctuary. if (mons_is_stationary(mon)) + { + mon->del_ench(ENCH_FEAR, true, true); break; + } // Berserking monsters don't flee, unless it's from sanctuary. if (mon->has_ench(ENCH_BERSERK) && !flee_sanct) @@ -2084,12 +2087,13 @@ void behaviour_event(monsters *mon, int event, int src, } case ME_CORNERED: - // Plants or nonliving monsters cannot flee. - if (mons_class_holiness(mon->type) == MH_PLANT - || mons_class_holiness(mon->type) == MH_NONLIVING) - { + // Some monsters can't flee. + if (mon->behaviour != BEH_FLEE && !mon->has_ench(ENCH_FEAR)) + break; + + // Don't stop fleeing from sanctuary + if (!mons_wont_attack(mon) && is_sanctuary(mon->x, mon->y)) break; - } // Just set behaviour... foe doesn't change. if (!mons_is_cornered(mon)) @@ -3414,6 +3418,13 @@ static void _handle_behaviour(monsters *mon) mon->foe = new_foe; } + + if (is_sanctuary(mon->target_x, mon->target_y) && mon->foe != MHITNOT + && !isFriendly && !mons_is_pacified(mon) && mon->behaviour != BEH_FLEE + && mon->target_pos() != mon->pos()) + { + mon->foe = MHITNOT; + } } static bool _mons_check_set_foe(monsters *mon, int x, int y, @@ -3423,7 +3434,7 @@ static bool _mons_check_set_foe(monsters *mon, int x, int y, return (false); if (!friendly && !neutral && x == you.x_pos && y == you.y_pos - && mons_player_visible(mon)) + && mons_player_visible(mon) && !is_sanctuary(x, y)) { mon->foe = MHITYOU; return (true); @@ -3435,6 +3446,7 @@ static bool _mons_check_set_foe(monsters *mon, int x, int y, if (foe != mon && mon_can_see_monster(mon, foe) + && (friendly || !is_sanctuary(x, y)) && (mons_friendly(foe) != friendly || (neutral && !mons_neutral(foe)))) { diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 9697dd3ebd..82743e0965 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -1710,13 +1710,23 @@ bool cast_sanctuary(const int power) else env.map[posx][posy].property = FPROP_SANCTUARY_2; // white - // scare all attacking monsters inside sanctuary + // scare all attacking monsters inside sanctuary, and make + // all friendly monsters inside sanctuary stop attacking and + // move towards the player. int monster = mgrd[posx][posy]; if (monster != NON_MONSTER) { monsters* mon = &menv[monster]; - if (!mons_wont_attack(mon)) + if (mons_friendly(mon)) + { + mon->foe = MHITYOU; + mon->target_x = you.x_pos; + mon->target_y = you.y_pos; + mon->behaviour = BEH_SEEK; + behaviour_event(mon, ME_EVAL, MHITYOU); + } + else if (!mons_wont_attack(mon)) { if (mons_is_mimic(mon->type)) { @@ -1767,6 +1777,9 @@ bool cast_sanctuary(const int power) "swept away.", MSGCH_GOD); } + // Pets stop attacking and converge on you. + you.pet_target = MHITYOU; + return (true); } |