summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mon-behv.cc
diff options
context:
space:
mode:
authorDracoOmega <draco_omega@live.com>2014-02-12 18:02:50 -0330
committerDracoOmega <draco_omega@live.com>2014-02-12 20:44:57 -0330
commit1d5a4174a97d9874fbca1bd299af56e9d4620288 (patch)
treea34c1c0d86ec0d93b2c22fb03d06e968f76df00f /crawl-ref/source/mon-behv.cc
parentf635930c6cd4e98905a6c7f676c5dd09db77b8d8 (diff)
downloadcrawl-ref-1d5a4174a97d9874fbca1bd299af56e9d4620288.tar.gz
crawl-ref-1d5a4174a97d9874fbca1bd299af56e9d4620288.zip
Allow nearly created allies to automatically choose appropriate foes
Having to repeatedly pause to tw after summoning new allies in a battle-in-progress (lest they simply stand around doing nothing) makes the pure summoner playstyle a bit more tedious than necessary. Also, it is not always intuitive to new players why allied monsters will sometimes appear to engage on their own and other times ignore obvious threats (say, if those threats simply missed you with their attacks on the previous turn). This adds the capacity for newly created summons to automatically choose valid nearby foes similar to if tw had been used just after making them. If there are no valid nearby foes, they will simply follow alongside the player as normal (no change to their general AI behavior has been made). (I did this by repurposing the apparently unused M_PLAYER_MADE flag. Hopefully there wasn't some reason for its existence that was not clear to me.) There is one caveat that is slightly different from tw: they will choose only foes that the player is also in los of (so as to not run off after monsters the player is not yet even aware of) and will even choose a foe that they are not in los of, but the player is, if no other one is available). This last property is particularly because often summons will be created slightly more distant from a monster you are fighting than the player is, and it is often very unclear that the monster cannot actually see the target from that spot. So when they do not engage and simply stand around the player, it appears moreso that the AI has failed to work properly, rather than the monster cannot see any target. We will assume that the player passes along some indication of its foes' positions that allies can use - in practice, the fact that this is even happening is not obvious; things simply just appear to move towards obvious enemies.
Diffstat (limited to 'crawl-ref/source/mon-behv.cc')
-rw-r--r--crawl-ref/source/mon-behv.cc71
1 files changed, 45 insertions, 26 deletions
diff --git a/crawl-ref/source/mon-behv.cc b/crawl-ref/source/mon-behv.cc
index 7c81f91733..53b8b8cece 100644
--- a/crawl-ref/source/mon-behv.cc
+++ b/crawl-ref/source/mon-behv.cc
@@ -37,8 +37,6 @@
#include "view.h"
#include "shout.h"
-static void _set_nearest_monster_foe(monster* mons);
-
static void _guess_invis_foe_pos(monster* mon)
{
const actor* foe = mon->get_foe();
@@ -471,7 +469,7 @@ void handle_behaviour(monster* mon)
if (you.pet_target != MHITNOT)
mon->foe = you.pet_target;
else if (mons_class_is_stationary(mon->type))
- _set_nearest_monster_foe(mon);
+ set_nearest_monster_foe(mon);
}
else // Zotdef only
{
@@ -486,7 +484,7 @@ void handle_behaviour(monster* mon)
{
// Zotdef - this is all new, for out-of-sight friendlies to do
// something useful. If no current target, get the closest one.
- _set_nearest_monster_foe(mon);
+ set_nearest_monster_foe(mon);
}
}
}
@@ -510,7 +508,7 @@ void handle_behaviour(monster* mon)
mon->foe = MHITYOU;
}
else
- _set_nearest_monster_foe(mon);
+ set_nearest_monster_foe(mon);
}
// Pacified monsters leaving the level prefer not to attack.
@@ -521,7 +519,7 @@ void handle_behaviour(monster* mon)
&& mon->behaviour != BEH_SLEEP
&& (proxPlayer || one_chance_in(3)))
{
- _set_nearest_monster_foe(mon);
+ set_nearest_monster_foe(mon);
if (mon->foe == MHITNOT && crawl_state.game_is_zotdef())
mon->foe = MHITYOU;
}
@@ -673,7 +671,7 @@ void handle_behaviour(monster* mon)
// Having a seeking mon with a foe who's target is
// (0, 0) can lead to asserts, so lets try to
// avoid that.
- _set_nearest_monster_foe(mon);
+ set_nearest_monster_foe(mon);
if (mon->foe == MHITNOT)
{
new_beh = BEH_WANDER;
@@ -1143,7 +1141,7 @@ void handle_behaviour(monster* mon)
}
static bool _mons_check_foe(monster* mon, const coord_def& p,
- bool friendly, bool neutral)
+ bool friendly, bool neutral, bool ignore_sight)
{
// We don't check for the player here because otherwise wandering
// monsters will always attack you.
@@ -1155,7 +1153,7 @@ static bool _mons_check_foe(monster* mon, const coord_def& p,
&& (mon->has_ench(ENCH_INSANE)
|| foe->friendly() != friendly
|| neutral && !foe->neutral())
- && mon->can_see(foe)
+ && (ignore_sight || mon->can_see(foe))
&& !foe->is_projectile()
&& summon_can_attack(mon, p)
&& (friendly || !is_sanctuary(p))
@@ -1172,7 +1170,7 @@ static bool _mons_check_foe(monster* mon, const coord_def& p,
}
// Choose random nearest monster as a foe.
-static void _set_nearest_monster_foe(monster* mon)
+void set_nearest_monster_foe(monster* mon, bool near_player)
{
// These don't look for foes.
if (mon->good_neutral() || mon->strict_neutral()
@@ -1186,25 +1184,46 @@ static void _set_nearest_monster_foe(monster* mon)
const bool friendly = mon->friendly();
const bool neutral = mon->neutral();
- for (int k = 1; k <= LOS_RADIUS; ++k)
+ coord_def center = mon->pos();
+ bool second_pass = false;
+
+ while (true)
{
- vector<coord_def> monster_pos;
- for (int i = -k; i <= k; ++i)
- for (int j = -k; j <= k; (abs(i) == k ? j++ : j += 2*k))
- {
- const coord_def p = mon->pos() + coord_def(i, j);
- if (_mons_check_foe(mon, p, friendly, neutral))
- monster_pos.push_back(p);
- }
- if (monster_pos.empty())
- continue;
+ for (int k = 1; k <= LOS_RADIUS; ++k)
+ {
+ vector<coord_def> monster_pos;
+ for (int i = -k; i <= k; ++i)
+ for (int j = -k; j <= k; (abs(i) == k ? j++ : j += 2*k))
+ {
+ const coord_def p = center + coord_def(i, j);
- const coord_def mpos = monster_pos[random2(monster_pos.size())];
- if (mpos == you.pos())
- mon->foe = MHITYOU;
+ if (near_player && !you.see_cell(p))
+ continue;
+
+ if (_mons_check_foe(mon, p, friendly, neutral, second_pass))
+ monster_pos.push_back(p);
+ }
+ if (monster_pos.empty())
+ continue;
+
+ const coord_def mpos = monster_pos[random2(monster_pos.size())];
+ if (mpos == you.pos())
+ mon->foe = MHITYOU;
+ else
+ mon->foe = env.mgrid(mpos);
+ return;
+ }
+
+ // If we're selecting a new summon's autofoe and we were unable to
+ // find a foe in los of the monster, try a second pass using the
+ // player's los instead.
+ if (near_player && !second_pass)
+ {
+ center = you.pos();
+ second_pass = true;
+ }
else
- mon->foe = env.mgrid(mpos);
- return;
+ break;
}
}