summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-07-02 01:43:29 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-07-02 01:43:29 +0000
commit3b1cbcc423f4d5bf475ce83cde8971bffb351abb (patch)
treef75474b191bae857c90ae7b736fa71029bc00188 /crawl-ref
parent9c75e7f7e8d1d8c58ac441f3b3bd77cb4d91bf24 (diff)
downloadcrawl-ref-3b1cbcc423f4d5bf475ce83cde8971bffb351abb.tar.gz
crawl-ref-3b1cbcc423f4d5bf475ce83cde8971bffb351abb.zip
When laying down Sanctuary make all pets inside it stop attacking and move
towards you. You can get them to attack while inside Sanctuary by giving them an order to attack a specific monster, and if they do attack and violate Sanctuary then it will be removed. Attempting to give such an order will give a warning that it might violate Sanctuary. Prevent confused and berserking pets from violating Sanctuary, since you can't order them not to. Prevent monsters fleeing Sanctuary from attacking monsters which are blocking their flight path. The player attacking him/her-self because of confusion no longer vilates Sanctuary. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6312 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-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);
}