summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mon-project.cc
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2009-12-20 19:04:36 +0100
committerAdam Borowski <kilobyte@angband.pl>2009-12-20 19:04:36 +0100
commit76442a6a837472a0909ad49e6a118184b90777d4 (patch)
tree22c1192017ef37e6e0d710a1a43e3a48a8cff209 /crawl-ref/source/mon-project.cc
parent85138818b78fbeec60ef96a72f8fa5ba05034274 (diff)
downloadcrawl-ref-76442a6a837472a0909ad49e6a118184b90777d4.tar.gz
crawl-ref-76442a6a837472a0909ad49e6a118184b90777d4.zip
Homing.
Diffstat (limited to 'crawl-ref/source/mon-project.cc')
-rw-r--r--crawl-ref/source/mon-project.cc59
1 files changed, 58 insertions, 1 deletions
diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc
index 4a080a43fd..ffcfb8a8a2 100644
--- a/crawl-ref/source/mon-project.cc
+++ b/crawl-ref/source/mon-project.cc
@@ -69,7 +69,7 @@ bool cast_iood(actor *caster, int pow, bolt *beam)
return (true);
}
-void _normalize(float &x, float &y)
+static void _normalize(float &x, float &y)
{
const float d = sqrt(x*x + y*y);
if (d <= 0.000001)
@@ -78,6 +78,12 @@ void _normalize(float &x, float &y)
y/=d;
}
+// angle measured in chord length
+static bool _in_front(float vx, float vy, float dx, float dy, float angle)
+{
+ return ((dx-vx)*(dx-vx) + (dy-vy)*(dy-vy) <= (angle*angle));
+}
+
void _iood_dissipate(monsters &mon)
{
simple_monster_message(&mon, " dissipates.");
@@ -112,6 +118,13 @@ bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false)
return (true);
}
+#ifdef DEBUG_DIAGNOSTICS
+#define dprf(...) mprf(MSGCH_DIAGNOSTICS, __VA_ARGS__)
+#else
+static void nada();
+#define dprf(...) nada()
+#endif
+
// returns true if the orb is gone
bool iood_act(monsters &mon, bool no_trail)
{
@@ -151,6 +164,50 @@ bool iood_act(monsters &mon, bool no_trail)
_normalize(vx, vy);
+ if (target != coord_def(-1, -1))
+ {
+ float dx = target.x - x;
+ float dy = target.y - y;
+ _normalize(dx, dy);
+
+ // Special case:
+ // Moving diagonally when the orb is just about to hit you
+ // 2
+ // ->*1
+ // (from 1 to 2) would be a guaranteed escape. This may be
+ // realistic (strafing!), but since the game has no non-cheesy
+ // means of waiting a small fraction of a turn, we don't want it.
+ const int old_t_pos = mon.props["iood_tpos"].get_short();
+ if (old_t_pos && old_t_pos != (256 * target.x + target.y)
+ && (coord_def(round(x), round(y)) - target).rdist() <= 1
+ // ... but following an orb is ok.
+ && _in_front(vx, vy, dx, dy, 1.5)) // ~97 degrees
+ {
+ vx = dx;
+ vy = dy;
+ }
+ mon.props["iood_tpos"].get_short() = 256 * target.x + target.y;
+
+ if (!_in_front(vx, vy, dx, dy, 0.5)) // ~29 degrees
+ {
+ float ax, ay;
+ if (dy*vx < dx*vy)
+ ax = vy, ay = -vx, dprf("iood: veering left");
+ else
+ ax = -vy, ay = vx, dprf("iood: veering right");
+ mprf(MSGCH_DIAGNOSTICS, "iood: veering %s", (dy*vx < dx*vy) ?
+ "left" : "right");
+ vx += ax * 0.3;
+ vy += ay * 0.3;
+ }
+ else
+ dprf("iood: keeping course");
+
+ _normalize(vx, vy);
+ mon.props["iood_vx"] = vx;
+ mon.props["iood_vy"] = vy;
+ }
+
x += vx;
y += vy;