summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/beam.cc6
-rw-r--r--crawl-ref/source/effects.cc10
-rw-r--r--crawl-ref/source/fight.cc110
-rw-r--r--crawl-ref/source/monstuff.cc24
-rw-r--r--crawl-ref/source/spells3.cc17
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);
}