summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2009-12-31 14:08:54 +0100
committerAdam Borowski <kilobyte@angband.pl>2009-12-31 14:08:54 +0100
commit8d8a727b80167a76d8282614fff1610fd9625a61 (patch)
treed3f96e793325bb5ac7568fd321f4f089274865e6 /crawl-ref
parentfdfbfdeb226cb33da8198cb3da6b6f39d7118dfc (diff)
downloadcrawl-ref-8d8a727b80167a76d8282614fff1610fd9625a61.tar.gz
crawl-ref-8d8a727b80167a76d8282614fff1610fd9625a61.zip
IOOD vs shields: blocks (boo!) and reflection (yay!)
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/beam.cc10
-rw-r--r--crawl-ref/source/itemprop.cc6
-rw-r--r--crawl-ref/source/itemprop.h1
-rw-r--r--crawl-ref/source/mon-project.cc72
4 files changed, 81 insertions, 8 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 41eddbe46b..e991e44b51 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -3720,12 +3720,6 @@ bool bolt::is_reflectable(const item_def *it) const
return (it && is_shield(*it) && shield_reflects(*it));
}
-static void _ident_reflector(item_def *item)
-{
- if (!is_artefact(*item))
- set_ident_flags(*item, ISFLAG_KNOW_TYPE);
-}
-
// Reflect a beam back the direction it came. This is used
// by shields of reflection.
void bolt::reflect()
@@ -3852,7 +3846,7 @@ bool bolt::misses_player()
mprf( "Your %s reflects the %s!",
you.shield()->name(DESC_PLAIN).c_str(),
name.c_str() );
- _ident_reflector(you.shield());
+ ident_reflector(you.shield());
reflect();
}
else
@@ -4818,7 +4812,7 @@ bool bolt::attempt_block(monsters* mon)
name.c_str(),
mon->pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str(),
shield->name(DESC_PLAIN).c_str());
- _ident_reflector(shield);
+ ident_reflector(shield);
}
else if (you.see_cell(pos()))
mprf("The %s bounces off of thin air!", name.c_str());
diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc
index bf47f3ab96..88b579114d 100644
--- a/crawl-ref/source/itemprop.cc
+++ b/crawl-ref/source/itemprop.cc
@@ -2462,6 +2462,12 @@ bool shield_reflects(const item_def &shield)
return (get_armour_ego_type(shield) == SPARM_REFLECTION);
}
+void ident_reflector(item_def *item)
+{
+ if (!is_artefact(*item))
+ set_ident_flags(*item, ISFLAG_KNOW_TYPE);
+}
+
std::string item_base_name(const item_def &item)
{
switch (item.base_type)
diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h
index 5604d352f5..d1231bc9f5 100644
--- a/crawl-ref/source/itemprop.h
+++ b/crawl-ref/source/itemprop.h
@@ -84,6 +84,7 @@ bool is_shield(const item_def &item);
bool is_shield_incompatible(const item_def &weapon,
const item_def *shield = NULL);
bool shield_reflects(const item_def &shield);
+void ident_reflector(item_def *item);
// Only works for armour/weapons/missiles
// weapon functions:
diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc
index 0af08ef38d..86ebc0a983 100644
--- a/crawl-ref/source/mon-project.cc
+++ b/crawl-ref/source/mon-project.cc
@@ -19,6 +19,7 @@
#include "directn.h"
#include "coord.h"
#include "env.h"
+#include "itemprop.h"
#include "mgen_data.h"
#include "mon-place.h"
#include "mon-stuff.h"
@@ -88,6 +89,19 @@ void _iood_dissipate(monsters &mon)
monster_die(&mon, KILL_DISMISSED, NON_MONSTER);
}
+// Alas, too much differs to reuse beam shield blocks :(
+bool _iood_shielded(monsters &mon, actor &victim)
+{
+ if (!victim.shield() || victim.incapacitated())
+ return (false);
+
+ const int to_hit = 15 + mon.props["iood_pow"].get_short()/12;
+ const int con_block = random2(to_hit + victim.shield_block_penalty());
+ const int pro_block = victim.shield_bonus();
+ dprf("iood shield: pro %d, con %d", pro_block, con_block);
+ return (pro_block >= con_block);
+}
+
bool _iood_hit(monsters &mon, const coord_def &pos, bool big_boom = false)
{
bolt beam;
@@ -193,6 +207,8 @@ bool iood_act(monsters &mon, bool no_trail)
mon.props["iood_vy"] = vy;
}
+reflected:
+
x += vx;
y += vy;
@@ -236,6 +252,62 @@ bool iood_act(monsters &mon, bool no_trail)
return (true);
}
+ if (victim && _iood_shielded(mon, *victim))
+ {
+ item_def *shield = victim->shield();
+ if (!shield_reflects(*shield))
+ {
+ if (victim->atype() == ACT_PLAYER)
+ {
+ mprf("You block %s.", mon.name(DESC_NOCAP_THE, true).c_str());
+ }
+ else
+ {
+ simple_monster_message((monsters*)victim, (" blocks the "
+ + mon.name(DESC_NOCAP_THE, true) + ".").c_str());
+ }
+ victim->shield_block_succeeded(&mon);
+ _iood_dissipate(mon);
+ return (true);
+ }
+
+ if (victim->atype() == ACT_PLAYER)
+ {
+ mprf("Your %s reflects %s!",
+ shield->name(DESC_PLAIN).c_str(),
+ mon.name(DESC_NOCAP_THE, true).c_str());
+ ident_reflector(shield);
+ }
+ else if (you.see_cell(pos))
+ {
+ if (victim->observable())
+ {
+ mprf("%s reflects %s with %s %s!",
+ victim->name(DESC_CAP_THE, true).c_str(),
+ mon.name(DESC_NOCAP_THE, true).c_str(),
+ mon.pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str(),
+ shield->name(DESC_PLAIN).c_str());
+ ident_reflector(shield);
+ }
+ else
+ {
+ mprf("%s bounces off thin air!",
+ mon.name(DESC_CAP_THE, true).c_str());
+ }
+ }
+ victim->shield_block_succeeded(&mon);
+
+ mon.props["iood_vx"] = vx = -vx;
+ mon.props["iood_vy"] = vy = -vy;
+
+ // Need to get out of the victim's square.
+
+ // If you're next to the caster and both of you wear shields of
+ // reflection, this can lead to a brief game of ping-pong, but
+ // rapidly increasing shield penalties will make it short.
+ goto reflected;
+ }
+
if (_iood_hit(mon, pos))
return (true);
}