summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorDarshan Shaligram <dshaligram@users.sourceforge.net>2010-01-11 12:31:58 +0530
committerDarshan Shaligram <dshaligram@users.sourceforge.net>2010-01-11 12:31:58 +0530
commitcacdc4a68146726b069be133d42dd40b4be5185d (patch)
tree1b90b0ad214ad0c522206a3761ecebaf9e9783b9 /crawl-ref/source
parent0879f0bf6cdbb83fa2e35a42bbb4b2e227ef354f (diff)
downloadcrawl-ref-cacdc4a68146726b069be133d42dd40b4be5185d.tar.gz
crawl-ref-cacdc4a68146726b069be133d42dd40b4be5185d.zip
Disallow intrinsic reaching attacks (turtles) from reach-attacking at full diagonals (2,2).
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/fight.cc10
-rw-r--r--crawl-ref/source/fight.h2
-rw-r--r--crawl-ref/source/mon-act.cc70
3 files changed, 43 insertions, 39 deletions
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 1b7e53e9fd..ef9f525e0f 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -5821,6 +5821,16 @@ static void mons_lose_attack_energy(monsters *attacker, int wpn_speed,
}
}
+bool monster_attack_actor(monsters *attacker, actor *defender,
+ bool allow_unarmed)
+{
+ ASSERT(defender == &you || defender->atype() == ACT_MONSTER);
+ return (defender->atype() == ACT_PLAYER ?
+ monster_attack(attacker, allow_unarmed)
+ : monsters_fight(attacker, dynamic_cast<monsters*>(defender),
+ allow_unarmed));
+}
+
// A monster attacking the player.
bool monster_attack(monsters* attacker, bool allow_unarmed)
{
diff --git a/crawl-ref/source/fight.h b/crawl-ref/source/fight.h
index 538858a4d8..70427a8ec1 100644
--- a/crawl-ref/source/fight.h
+++ b/crawl-ref/source/fight.h
@@ -56,6 +56,8 @@ int resist_adjust_damage(actor *defender, beam_type flavour,
int weapon_str_weight( object_class_type wpn_class, int wpn_type );
bool you_attack(int monster_attacked, bool unarmed_attacks);
+bool monster_attack_actor(monsters *attacker, actor *defender,
+ bool allow_unarmed);
bool monster_attack(monsters* attacker, bool allow_unarmed = true);
bool monsters_fight(monsters* attacker, monsters* attacked,
bool allow_unarmed = true);
diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc
index 4120508703..bc15130cc4 100644
--- a/crawl-ref/source/mon-act.cc
+++ b/crawl-ref/source/mon-act.cc
@@ -740,6 +740,10 @@ static bool _handle_reaching(monsters *monster)
bool ret = false;
item_def *wpn = monster->weapon(0);
const mon_attack_def attk(mons_attack_spec(monster, 0));
+ actor *foe = monster->get_foe();
+
+ if (!foe)
+ return (false);
if (monster->submerged())
return (false);
@@ -747,47 +751,35 @@ static bool _handle_reaching(monsters *monster)
if (mons_aligned(monster->mindex(), monster->foe))
return (false);
- if ((wpn && get_weapon_brand(*wpn) == SPWPN_REACHING)
- || (attk.flavour == AF_REACH && attk.damage))
- {
- if (monster->foe == MHITYOU)
- {
- const coord_def delta = monster->pos() - you.pos();
- const int x_middle = std::max(monster->pos().x, you.pos().x)
- - (abs(delta.x) / 2);
- const int y_middle = std::max(monster->pos().y, you.pos().y)
- - (abs(delta.y) / 2);
- const coord_def middle(x_middle, y_middle);
-
- // This check isn't redundant -- player may be invisible.
- if (monster->target == you.pos()
- && grid_distance(monster->pos(), you.pos()) == 2
- && (you.see_cell_no_trans(monster->pos())
- || grd(middle) > DNGN_MAX_NONREACH))
- {
- ret = true;
- monster_attack(monster, false);
- }
- }
- else if (monster->foe != MHITNOT)
- {
- monsters& mfoe = menv[monster->foe];
- coord_def foepos = mfoe.pos();
- // Same comments as to invisibility as above.
- if (monster->target == foepos
- && monster->mon_see_cell(foepos, true)
- && grid_distance(monster->pos(), foepos) == 2)
- {
- ret = true;
- monsters_fight(monster, &mfoe, false);
- }
- }
+ const coord_def foepos(foe->pos());
+ const coord_def delta(foepos - monster->pos());
+ const int grid_distance(delta.rdist());
+ const coord_def middle(monster->pos() + delta / 2);
+
+ if (grid_distance == 2
+ // The monster has to be attacking the correct position.
+ && monster->target == foepos
+ // With a reaching weapon OR ...
+ && ((wpn && get_weapon_brand(*wpn) == SPWPN_REACHING)
+ // ... with a native reaching attack, provided the attack
+ // is not on a full diagonal.
+ || (attk.flavour == AF_REACH && attk.damage
+ && delta.abs() <= 5))
+ // And with no dungeon furniture in the way of the reaching
+ // attack; if the middle square is empty, skip the LOS check.
+ && (grd(middle) > DNGN_MAX_NONREACH
+ || (monster->foe == MHITYOU?
+ you.see_cell_no_trans(monster->pos())
+ : monster->mon_see_cell(foepos, true))))
+ {
+ ret = true;
+ monster_attack_actor(monster, foe, false);
+
+ // Player saw the item reach.
+ if (wpn && !is_artefact(*wpn) && you.can_see(monster))
+ set_ident_flags(*wpn, ISFLAG_KNOW_TYPE);
}
- // Player saw the item reach.
- if (ret && wpn && !is_artefact(*wpn) && you.can_see(monster))
- set_ident_flags(*wpn, ISFLAG_KNOW_TYPE);
-
return (ret);
}