summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2009-02-16 13:14:09 +0000
committerharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2009-02-16 13:14:09 +0000
commit78a45dd9099c4340a9aec9d634d3ef91bab181ac (patch)
tree3ff8e7ff42e66524b89fbfa0a163a106a9655247 /crawl-ref/source
parent263a61728d25f53837389fcf1c333eebd78c535b (diff)
downloadcrawl-ref-78a45dd9099c4340a9aec9d634d3ef91bab181ac.tar.gz
crawl-ref-78a45dd9099c4340a9aec9d634d3ef91bab181ac.zip
Fix [2004960]: clean up sanctuary logic. Monsters will now stop fleeing
and attack you if you step outside of sanctuary; also, they can acquire and chase new targets while still respecting sanctuary. Hopefully non-buggy. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9100 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/enum.h3
-rw-r--r--crawl-ref/source/mon-util.cc29
-rw-r--r--crawl-ref/source/mon-util.h6
-rw-r--r--crawl-ref/source/monstuff.cc63
-rw-r--r--crawl-ref/source/monstuff.h10
-rw-r--r--crawl-ref/source/spells3.cc98
6 files changed, 122 insertions, 87 deletions
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index aedfa39668..9c298c19e4 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -2109,7 +2109,8 @@ enum monster_flag_type
MF_NAME_REPLACE = 0x30000, // mname entirely replaces normal monster
// name.
MF_NAME_MASK = 0x30000,
- MF_GOD_GIFT = 0x40000 // Is a god gift.
+ MF_GOD_GIFT = 0x40000, // Is a god gift.
+ MF_FLEEING_FROM_SANCTUARY = 0x80000 // Is running away from player sanctuary
};
// Adding slots breaks saves. YHBW.
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 2c1fac0b54..9ebfc2737a 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -2651,6 +2651,20 @@ bool mons_is_lurking(const monsters *m)
return (m->behaviour == BEH_LURK);
}
+bool mons_is_influenced_by_sanctuary(const monsters *m)
+{
+ return (!mons_wont_attack(m)
+ && mons_holiness(m) != MH_PLANT
+ && !mons_is_stationary(m));
+}
+
+bool mons_is_fleeing_sanctuary(const monsters *m)
+{
+ return (mons_is_influenced_by_sanctuary(m)
+ && inside_level_bounds(env.sanctuary_pos)
+ && (m->flags & MF_FLEEING_FROM_SANCTUARY));
+}
+
bool mons_is_batty(const monsters *m)
{
return mons_class_flag(m->type, M_BATTY);
@@ -2684,6 +2698,21 @@ bool mons_looks_distracted(const monsters *m)
&& uat != UCAT_SLEEPING);
}
+void mons_start_fleeing_from_sanctuary(monsters *monster)
+{
+ monster->flags |= MF_FLEEING_FROM_SANCTUARY;
+ monster->target = env.sanctuary_pos;
+ behaviour_event(monster, ME_SCARE, MHITNOT, env.sanctuary_pos);
+}
+
+void mons_stop_fleeing_from_sanctuary(monsters *monster)
+{
+ const bool had_flag = (monster->flags & MF_FLEEING_FROM_SANCTUARY);
+ monster->flags &= (~MF_FLEEING_FROM_SANCTUARY);
+ if (had_flag)
+ behaviour_event(monster, ME_EVAL, MHITYOU);
+}
+
void mons_pacify(monsters *mon)
{
// Make the monster permanently neutral.
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 1cbf54ed89..ab343e73df 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -161,7 +161,6 @@ enum mon_event_type
ME_ANNOY, // annoy at range
ME_ALERT, // alert to presence
ME_WHACK, // physical attack
- ME_SHOT, // attack at range
ME_SCARE, // frighten monster
ME_CORNERED // cannot flee
};
@@ -767,6 +766,8 @@ bool mons_is_panicking(const monsters *m);
bool mons_is_cornered(const monsters *m);
bool mons_is_lurking(const monsters *m);
bool mons_is_batty(const monsters *m);
+bool mons_is_influenced_by_sanctuary(const monsters *m);
+bool mons_is_fleeing_sanctuary(const monsters *m);
bool mons_was_seen(const monsters *m);
bool mons_is_known_mimic(const monsters *m);
bool mons_is_holy(const monsters *mon);
@@ -783,6 +784,9 @@ monster_type mons_species(int mc);
bool mons_looks_stabbable(const monsters *m);
bool mons_looks_distracted(const monsters *m);
+void mons_start_fleeing_from_sanctuary(monsters *monster);
+void mons_stop_fleeing_from_sanctuary(monsters *monster);
+
bool mons_has_smite_attack(const monsters *monster);
bool check_mons_resist_magic(const monsters *monster, int pow);
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 66fafc2233..fb1be02ae6 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1827,7 +1827,7 @@ void alert_nearby_monsters(void)
// alert monsters that aren't sleeping. For cases where an
// event should wake up monsters and alert them, I'd suggest
// calling noisy() before calling this function. -- bwr
- if (monster->type != -1
+ if (monster->alive()
&& mons_near(monster)
&& !mons_is_sleeping(monster))
{
@@ -2490,14 +2490,14 @@ static bool _wounded_damaged(int monster_type)
// 2. Call handle_behaviour to re-evaluate AI state and target x,y
//
//---------------------------------------------------------------
-void behaviour_event(monsters *mon, int event, int src,
+void behaviour_event(monsters *mon, mon_event_type event, int src,
coord_def src_pos)
{
ASSERT(src >= 0 && src <= MHITYOU);
ASSERT(!crawl_state.arena || src != MHITYOU);
ASSERT(in_bounds(src_pos) || src_pos.origin());
- beh_type old_behaviour = mon->behaviour;
+ const beh_type old_behaviour = mon->behaviour;
bool isSmart = (mons_intel(mon) > I_ANIMAL);
bool wontAttack = mons_wont_attack_real(mon);
@@ -2510,6 +2510,14 @@ void behaviour_event(monsters *mon, int event, int src,
else if (src != MHITNOT)
sourceWontAttack = mons_wont_attack_real( &menv[src] );
+ if (is_sanctuary(mon->pos()) && mons_is_fleeing_sanctuary(mon))
+ {
+ mon->behaviour = BEH_FLEE;
+ mon->foe = MHITYOU;
+ mon->target = env.sanctuary_pos;
+ return;
+ }
+
switch (event)
{
case ME_DISTURB:
@@ -2566,8 +2574,8 @@ void behaviour_event(monsters *mon, int event, int src,
}
}
- // Now set target x, y so that monster can whack
- // back (once) at an invisible foe.
+ // Now set target so that monster can whack back (once) at an
+ // invisible foe.
if (event == ME_WHACK)
setTarget = true;
break;
@@ -2614,25 +2622,20 @@ void behaviour_event(monsters *mon, int event, int src,
break;
case ME_SCARE:
- {
- const bool flee_sanct = !mons_wont_attack(mon)
- && is_sanctuary(mon->pos());
-
- // Stationary monsters can't flee, even from sanctuary.
+ // Stationary monsters can't flee.
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)
+ // Berserking monsters don't flee.
+ if (mon->has_ench(ENCH_BERSERK))
break;
- // Neither do plants or nonliving beings, and sanctuary doesn't
- // affect plants.
+ // Neither do plants or nonliving beings.
if (mons_class_holiness(mon->type) == MH_PLANT
- || (mons_class_holiness(mon->type) == MH_NONLIVING && !flee_sanct))
+ || mons_class_holiness(mon->type) == MH_NONLIVING)
{
mon->del_ench(ENCH_FEAR, true, true);
break;
@@ -2646,17 +2649,12 @@ void behaviour_event(monsters *mon, int event, int src,
if (see_grid(mon->pos()))
learned_something_new(TUT_FLEEING_MONSTER);
break;
- }
case ME_CORNERED:
// 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->pos()))
- break;
-
// Pacified monsters shouldn't change their behaviour.
if (mons_is_pacified(mon))
break;
@@ -2669,7 +2667,6 @@ void behaviour_event(monsters *mon, int event, int src,
break;
case ME_EVAL:
- default:
break;
}
@@ -3797,6 +3794,13 @@ static void _handle_behaviour(monsters *mon)
return;
}
+ if (mons_is_fleeing_sanctuary(mon)
+ && mons_is_fleeing(mon)
+ && is_sanctuary(you.pos()))
+ {
+ return;
+ }
+
if (crawl_state.arena)
{
if (Options.arena_force_ai)
@@ -4564,15 +4568,14 @@ static void _handle_movement(monsters *monster)
_maybe_set_patrol_route(monster);
// Monsters will try to flee out of a sanctuary.
- if (is_sanctuary(monster->pos()) && !mons_friendly(monster)
- && !mons_is_fleeing(monster)
- && monster->add_ench(mon_enchant(ENCH_FEAR, 0, KC_YOU)))
+ if (is_sanctuary(monster->pos())
+ && mons_is_influenced_by_sanctuary(monster)
+ && !mons_is_fleeing_sanctuary(monster))
{
- behaviour_event(monster, ME_SCARE, MHITNOT, monster->pos());
+ mons_start_fleeing_from_sanctuary(monster);
}
- else if (mons_is_fleeing(monster) && inside_level_bounds(env.sanctuary_pos)
- && !is_sanctuary(monster->pos())
- && monster->target == env.sanctuary_pos)
+ else if (mons_is_fleeing_sanctuary(monster)
+ && !is_sanctuary(monster->pos()))
{
// Once outside there's a chance they'll regain their courage.
// Nonliving and berserking monsters always stop immediately,
@@ -4580,9 +4583,9 @@ static void _handle_movement(monsters *monster)
// scared.
if (monster->holiness() == MH_NONLIVING
|| monster->has_ench(ENCH_BERSERK)
- || random2(5) > 2)
+ || x_chance_in_y(2, 5))
{
- monster->del_ench(ENCH_FEAR);
+ mons_stop_fleeing_from_sanctuary(monster);
}
}
diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h
index 36561e82a4..128b9d1f02 100644
--- a/crawl-ref/source/monstuff.h
+++ b/crawl-ref/source/monstuff.h
@@ -105,15 +105,9 @@ void mons_check_pool(monsters *monster, const coord_def &oldpos,
void monster_cleanup(monsters *monster);
-/* ***********************************************************************
- * called from: monstuff beam effects fight view
- * *********************************************************************** */
-void behaviour_event(monsters *mon, int event_type, int src = MHITNOT,
- coord_def src_pos = coord_def() );
+void behaviour_event(monsters *mon, mon_event_type event_type,
+ int src = MHITNOT, coord_def src_pos = coord_def());
-/* ***********************************************************************
- * called from: fight - it_use3 - spells
- * *********************************************************************** */
bool curse_an_item(bool decay_potions, bool quiet = false);
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 9d63b3ca96..7bbe991901 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -1534,7 +1534,7 @@ static int _inside_circle(const coord_def& where, int radius)
return (dist);
}
-static void _remove_sanctuary_property(coord_def where)
+static void _remove_sanctuary_property(const coord_def& where)
{
env.map(where).property &= ~(FPROP_SANCTUARY_1 | FPROP_SANCTUARY_2);
}
@@ -1559,9 +1559,7 @@ bool remove_sanctuary(bool did_attack)
}
}
-// Do not reset so as to allow monsters to see if their fleeing source
-// used to be the centre of a sanctuary. (jpeg)
-// env.sanctuary_pos.x = env.sanctuary_pos.y = -1;
+ env.sanctuary_pos.set(-1, -1);
if (did_attack)
{
@@ -1570,6 +1568,15 @@ bool remove_sanctuary(bool did_attack)
did_god_conduct(DID_FRIEND_DIED, 3);
}
+ // Now that the sanctuary is gone, monsters aren't afraid of it
+ // anymore.
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *mon = &menv[i];
+ if (mon->alive())
+ mons_stop_fleeing_from_sanctuary(mon);
+ }
+
if (is_resting())
stop_running();
@@ -1579,7 +1586,7 @@ bool remove_sanctuary(bool did_attack)
// For the last (radius) counter turns the sanctuary will slowly shrink.
void decrease_sanctuary_radius()
{
- int radius = 5;
+ const int radius = 5;
// For the last (radius-1) turns 33% chance of not decreasing.
if (env.sanctuary_time < radius && one_chance_in(3))
@@ -1595,30 +1602,20 @@ void decrease_sanctuary_radius()
stop_running();
}
- radius = size+1;
- for (int x = -radius; x <= radius; x++)
- for (int y = -radius; y <= radius; y++)
- {
- int posx = env.sanctuary_pos.x + x;
- int posy = env.sanctuary_pos.y + y;
-
- if (!inside_level_bounds(posx,posy))
- continue;
-
- int dist = distance(posx, posy, env.sanctuary_pos.x,
- env.sanctuary_pos.y);
+ for (radius_iterator ri(env.sanctuary_pos, size+1, true, false); ri; ++ri)
+ {
+ int dist = distance(*ri, env.sanctuary_pos);
- // If necessary overwrite sanctuary property.
- if (dist > size*size)
- _remove_sanctuary_property(coord_def(posx, posy));
- }
+ // If necessary overwrite sanctuary property.
+ if (dist > size*size)
+ _remove_sanctuary_property(*ri);
+ }
// Special case for time-out of sanctuary.
if (!size)
{
- _remove_sanctuary_property(coord_def(env.sanctuary_pos.x,
- env.sanctuary_pos.y));
- if (see_grid(coord_def(env.sanctuary_pos.x,env.sanctuary_pos.y)))
+ _remove_sanctuary_property(env.sanctuary_pos);
+ if (see_grid(env.sanctuary_pos))
mpr("The sanctuary disappears.", MSGCH_DURATION);
}
}
@@ -1653,16 +1650,15 @@ bool cast_sanctuary(const int power)
// radius could also be influenced by Inv
// and would then have to be stored globally.
const int radius = 5;
- const int pattern = random2(4);
int blood_count = 0;
int trap_count = 0;
int scare_count = 0;
int cloud_count = 0;
monsters *seen_mon = NULL;
- for ( radius_iterator ri(you.pos(), radius, false, false); ri; ++ri )
+ for (radius_iterator ri(you.pos(), radius, false, false); ri; ++ri)
{
- int dist = _inside_circle(*ri, radius);
+ const int dist = _inside_circle(*ri, radius);
if (dist == -1)
continue;
@@ -1682,25 +1678,34 @@ bool cast_sanctuary(const int power)
// forming patterns
const int x = pos.x - you.pos().x, y = pos.y - you.pos().y;
- if (pattern == 0 // outward rays
- && (x == 0 || y == 0 || x == y || x == -y)
- || pattern == 1 // circles
- && (dist >= (radius-1)*(radius-1) && dist <= radius*radius
- || dist >= (radius/2-1)*(radius/2-1)
- && dist <= radius*radius/4)
- || pattern == 2 // latticed
- && (x%2 == 0 || y%2 == 0)
- || pattern == 3 // cross-like
- && (abs(x)+abs(y) < 5 && x != y && x != -y))
+ bool in_yellow = false;
+ switch (random2(4))
{
- env.map(pos).property |= FPROP_SANCTUARY_1; // yellow
+ case 0: // outward rays
+ in_yellow = (x == 0 || y == 0 || x == y || x == -y);
+ break;
+ case 1: // circles
+ in_yellow = (dist >= (radius-1)*(radius-1)
+ && dist <= radius*radius
+ || dist >= (radius/2-1)*(radius/2-1)
+ && dist <= radius*radius/4);
+ break;
+ case 2: // latticed
+ in_yellow = (x%2 == 0 || y%2 == 0);
+ break;
+ case 3: // cross-like
+ in_yellow = (abs(x)+abs(y) < 5 && x != y && x != -y);
+ break;
+ default:
+ break;
}
- else
- env.map(pos).property |= FPROP_SANCTUARY_2; // white
+
+ env.map(pos).property |= (in_yellow ? FPROP_SANCTUARY_1
+ : FPROP_SANCTUARY_2);
env.map(pos).property &= ~(FPROP_BLOODY);
- // scare all attacking monsters inside sanctuary, and make
+ // Scare all attacking monsters inside sanctuary, and make
// all friendly monsters inside sanctuary stop attacking and
// move towards the player.
if (monsters* mon = monster_at(pos))
@@ -1717,18 +1722,17 @@ bool cast_sanctuary(const int power)
if (mons_is_mimic(mon->type))
{
mimic_alert(mon);
- if(you.can_see(mon))
+ if (you.can_see(mon))
{
scare_count++;
seen_mon = mon;
}
}
- else if (mon->add_ench(mon_enchant(ENCH_FEAR, 0, KC_YOU)))
+ else if (mons_is_influenced_by_sanctuary(mon))
{
- behaviour_event(mon, ME_SCARE, MHITYOU);
+ mons_start_fleeing_from_sanctuary(mon);
- // Check to see that monster is actually fleeing,
- // since plants can't flee.
+ // Check to see that monster is actually fleeing.
if (mons_is_fleeing(mon) && you.can_see(mon))
{
scare_count++;
@@ -1736,7 +1740,7 @@ bool cast_sanctuary(const int power)
}
}
}
- } // if (monster != NON_MONSTER)
+ }
if (!is_harmless_cloud(cloud_type_at(pos)))
{