summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-10-08 20:08:53 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-10-08 20:08:53 +0000
commit95d587c3feda35ad847d676165aa9e9a6c67bfb4 (patch)
treef62bf3770b9958bcd590466184a7386361a27b33 /crawl-ref
parent9da9f88dfcd5bbbc28cd41b33bdee86f05183398 (diff)
downloadcrawl-ref-95d587c3feda35ad847d676165aa9e9a6c67bfb4.tar.gz
crawl-ref-95d587c3feda35ad847d676165aa9e9a6c67bfb4.zip
Orc knights and warlords can yell battle-cries to make lesser orcs fight better.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2387 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/debug.cc25
-rw-r--r--crawl-ref/source/direct.cc7
-rw-r--r--crawl-ref/source/enum.h1
-rw-r--r--crawl-ref/source/externs.h12
-rw-r--r--crawl-ref/source/fight.cc15
-rw-r--r--crawl-ref/source/mon-util.cc20
-rw-r--r--crawl-ref/source/mon-util.h4
-rw-r--r--crawl-ref/source/monstuff.cc7
-rw-r--r--crawl-ref/source/mstuff2.cc72
-rw-r--r--crawl-ref/source/mstuff2.h1
-rw-r--r--crawl-ref/source/player.cc10
11 files changed, 124 insertions, 50 deletions
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index a0c4ed14d4..07e26b7dad 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -428,31 +428,6 @@ void create_spec_monster_name(int x, int y)
const mons_spec mspec = mlist.get_monster(0);
if (!force_place && mspec.mid != -1)
{
- // Only one ghost allowed per level
- if (mspec.mid == MONS_PLAYER_GHOST)
- {
- for (int i = 0; i < MAX_MONSTERS; i++)
- if (menv[i].type == MONS_PLAYER_GHOST
- && menv[i].alive())
- {
- mpr("Only one player ghost per level allowed, "
- "and this level already has one.");
- return;
- }
- }
- // Only one pandemonium lord allowed per level as well.
- else if (mspec.mid == MONS_PANDEMONIUM_DEMON)
- {
- for (int i = 0; i < MAX_MONSTERS; i++)
- if (menv[i].type == MONS_PANDEMONIUM_DEMON
- && menv[i].alive())
- {
- mpr("Only one Pandemonium lord per level allowed, "
- "and this level already has one.");
- return;
- }
- }
-
coord_def place = find_newmons_square(mspec.mid, x, y);
if (in_bounds(place))
{
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc
index a36b6ffe45..40f16abf09 100644
--- a/crawl-ref/source/direct.cc
+++ b/crawl-ref/source/direct.cc
@@ -1741,8 +1741,11 @@ static std::string describe_mons_enchantment(const monsters &mons,
if (paralysed && (ench.ench == ENCH_SLOW || ench.ench == ENCH_HASTE))
return "";
- if (ench.ench == ENCH_HASTE && mons.has_ench(ENCH_BERSERK))
+ if ((ench.ench == ENCH_HASTE || ench.ench == ENCH_BATTLE_FRENZY)
+ && mons.has_ench(ENCH_BERSERK))
+ {
return "";
+ }
switch (ench.ench)
{
@@ -1758,6 +1761,8 @@ static std::string describe_mons_enchantment(const monsters &mons,
return "moving slowly";
case ENCH_BERSERK:
return "berserk";
+ case ENCH_BATTLE_FRENZY:
+ return "consumed by blood-lust";
case ENCH_HASTE:
return "moving very quickly";
case ENCH_CONFUSION:
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index ed9d2c6525..01048e2340 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -1061,6 +1061,7 @@ enum enchant_type
ENCH_SLEEPY, // Monster can't wake until this wears off.
ENCH_FATIGUE, // Post-berserk fatigue.
ENCH_HELD, // caught in a net
+ ENCH_BATTLE_FRENZY, // Monster is in a battle frenzy
NUM_ENCHANTMENTS
};
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 194e9dba55..f94cdd07f6 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -113,8 +113,8 @@ public:
virtual bool can_go_berserk() const = 0;
virtual bool can_see_invisible() const = 0;
virtual bool invisible() const = 0;
- virtual bool visible_to(actor *looker) = 0;
- virtual bool can_see(actor *target) = 0;
+ virtual bool visible_to(const actor *looker) const = 0;
+ virtual bool can_see(const actor *target) const = 0;
virtual bool is_icy() const = 0;
virtual void go_berserk(bool intentional) = 0;
virtual void mutate() = 0;
@@ -714,8 +714,8 @@ public:
bool cannot_speak() const;
bool invisible() const;
bool can_see_invisible() const;
- bool visible_to(actor *looker);
- bool can_see(actor *target);
+ bool visible_to(const actor *looker) const;
+ bool can_see(const actor *target) const;
bool is_icy() const;
bool light_flight() const;
@@ -1072,8 +1072,8 @@ public:
bool is_levitating() const;
bool invisible() const;
bool can_see_invisible() const;
- bool visible_to(actor *looker);
- bool can_see(actor *target);
+ bool visible_to(const actor *looker) const ;
+ bool can_see(const actor *target) const;
bool is_icy() const;
bool paralysed() const;
bool confused() const;
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index e09e30410b..a9dcc7c14e 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -2882,6 +2882,21 @@ int melee_attack::mons_calc_damage(const mon_attack_def &attk)
// Berserk monsters get bonus damage.
if (atk->has_ench(ENCH_BERSERK))
damage = damage * 3 / 2;
+ else if (atk->has_ench(ENCH_BATTLE_FRENZY))
+ {
+ const mon_enchant ench = atk->get_ench(ENCH_BATTLE_FRENZY);
+
+#ifdef DEBUG_DIAGNOSTICS
+ const int orig_damage = damage;
+#endif
+
+ damage = damage * (115 + ench.degree * 15) / 100;
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "%s frenzy damage: %d->%d",
+ attacker->name(DESC_PLAIN).c_str(), orig_damage, damage);
+#endif
+ }
if (water_attack)
damage *= 2;
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index f8ec245d87..c1f219a6c1 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -620,7 +620,7 @@ bool mons_see_invis(const monsters *mon)
// This does NOT do line of sight! It checks the targ's visibility
// with respect to mon's perception, but doesn't do walls or range.
-bool mons_monster_visible( struct monsters *mon, struct monsters *targ )
+bool mons_monster_visible( const monsters *mon, const monsters *targ )
{
if (targ->has_ench(ENCH_SUBMERGED)
|| (targ->invisible() && !mons_see_invis(mon)))
@@ -633,7 +633,7 @@ bool mons_monster_visible( struct monsters *mon, struct monsters *targ )
// This does NOT do line of sight! It checks the player's visibility
// with respect to mon's perception, but doesn't do walls or range.
-bool mons_player_visible( struct monsters *mon )
+bool mons_player_visible( const monsters *mon )
{
if (you.invisible())
{
@@ -4118,6 +4118,7 @@ void monsters::timeout_enchantments(int levels)
case ENCH_SLOW: case ENCH_HASTE: case ENCH_FEAR:
case ENCH_INVIS: case ENCH_CHARM: case ENCH_SLEEP_WARY:
case ENCH_SICK: case ENCH_SLEEPY: case ENCH_PARALYSIS:
+ case ENCH_BATTLE_FRENZY:
lose_ench_levels(i->second, levels);
break;
@@ -4249,6 +4250,10 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_SLEEP_WARY:
decay_enchantment(me);
break;
+
+ case ENCH_BATTLE_FRENZY:
+ decay_enchantment(me, false);
+ break;
case ENCH_HELD:
{
@@ -4736,7 +4741,7 @@ bool monsters::invisible() const
return (has_ench(ENCH_INVIS) && !backlit());
}
-bool monsters::visible_to(actor *looker)
+bool monsters::visible_to(const actor *looker) const
{
if (this == looker)
return (!invisible() || can_see_invisible());
@@ -4745,13 +4750,12 @@ bool monsters::visible_to(actor *looker)
return player_monster_visible(this);
else
{
- monsters* mon = dynamic_cast<monsters*>(looker);
-
+ const monsters* mon = dynamic_cast<const monsters*>(looker);
return mons_monster_visible(mon, this);
}
}
-bool monsters::can_see(actor *target)
+bool monsters::can_see(const actor *target) const
{
if (this == target)
return visible_to(target);
@@ -4762,7 +4766,7 @@ bool monsters::can_see(actor *target)
if (target->atype() == ACT_PLAYER)
return mons_near(this);
- monsters* mon = dynamic_cast<monsters*>(target);
+ const monsters* mon = dynamic_cast<const monsters*>(target);
int tx = mon->x;
int ty = mon->y;
@@ -4901,7 +4905,7 @@ static const char *enchant_names[] =
"rot", "summon", "abj", "backlit", "charm", "fire",
"gloshifter", "shifter", "tp", "wary", "submerged",
"short lived", "paralysis", "sick", "sleep", "fatigue", "held",
- "bug"
+ "blood-lust", "bug"
};
const char *mons_enchantment_name(enchant_type ench)
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 6e4b032495..68659bd890 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -328,8 +328,8 @@ mon_itemuse_type mons_itemuse(int mc);
* *********************************************************************** */
bool mons_see_invis(const monsters *mon);
bool mons_sense_invis(const monsters *mon);
-bool mons_monster_visible( struct monsters *mon, struct monsters *targ );
-bool mons_player_visible( struct monsters *mon );
+bool mons_monster_visible( const monsters *mon, const monsters *targ );
+bool mons_player_visible( const monsters *mon );
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index f49a24aaf9..1d9084efe8 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -2373,10 +2373,13 @@ static bool handle_special_ability(monsters *monster, bolt & beem)
return (false);
}
-// losight(show, grd, you.x_pos, you.y_pos);
-
switch (mclass)
{
+ case MONS_ORC_KNIGHT:
+ case MONS_ORC_WARLORD:
+ used = orc_battle_cry(monster);
+ break;
+
case MONS_ORANGE_STATUE:
used = orange_statue_effects(monster);
break;
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index c402c44f8c..66c624e06a 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -2147,6 +2147,78 @@ bool orange_statue_effects(monsters *mons)
return (false);
}
+bool orc_battle_cry(monsters *chief)
+{
+ const actor *foe = chief->get_foe();
+ if (foe && chief->can_see(foe) && coinflip())
+ {
+ const int boss_index = monster_index(chief);
+ const int level = chief->hit_dice > 12? 2 : 1;
+ std::vector<monsters*> affected;
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *mons = &menv[i];
+ if (mons != chief
+ && mons->alive()
+ && mons_species(mons->type) == MONS_ORC
+ && mons_aligned(boss_index, i)
+ && mons->hit_dice < chief->hit_dice
+ && chief->can_see(mons))
+ {
+ mon_enchant ench = mons->get_ench(ENCH_BATTLE_FRENZY);
+ if (ench.ench == ENCH_NONE || ench.degree < level)
+ {
+ const int dur =
+ random_range(5, 10) * speed_to_duration(mons->speed);
+
+ if (ench.ench != ENCH_NONE)
+ {
+ ench.degree = level;
+ ench.duration = std::max(ench.duration, dur);
+ mons->update_ench(ench);
+ }
+ else
+ {
+ mons->add_ench(
+ mon_enchant(ENCH_BATTLE_FRENZY, level,
+ KC_OTHER,
+ dur));
+ }
+ affected.push_back(mons);
+ }
+ }
+ }
+
+ if (!affected.empty())
+ {
+ if (you.can_see(chief))
+ mprf("%s roars a battle-cry!",
+ chief->name(DESC_CAP_THE).c_str());
+
+ // Disabling detailed frenzy announcement because it's so spammy.
+#ifdef ANNOUNCE_BATTLE_FRENZY
+ std::map<std::string, int> names;
+ for (int i = 0, size = affected.size(); i < size; ++i)
+ {
+ if (you.can_see(affected[i]))
+ names[affected[i]->name(DESC_PLAIN)]++;
+ }
+
+ for (std::map<std::string,int>::const_iterator i = names.begin();
+ i != names.end(); ++i)
+ {
+ const std::string s =
+ i->second> 1? pluralise(i->first) : i->first;
+ mprf("The %s go%s into a battle-frenzy!",
+ s.c_str(), i->second == 1? "es" : "");
+ }
+#endif
+ }
+ }
+ // Orc battle cry doesn't cost the monster an action.
+ return (false);
+}
+
static bool make_monster_angry(const monsters *mon, monsters *targ)
{
if (mons_friendly(mon) != mons_friendly(targ))
diff --git a/crawl-ref/source/mstuff2.h b/crawl-ref/source/mstuff2.h
index 9c75055bd4..25cc10a3bf 100644
--- a/crawl-ref/source/mstuff2.h
+++ b/crawl-ref/source/mstuff2.h
@@ -92,6 +92,7 @@ void monster_teleport(struct monsters *monster, bool instan,
* *********************************************************************** */
void spore_goes_pop(struct monsters *monster);
+bool orc_battle_cry(monsters *chief);
bool orange_statue_effects(monsters *mons);
bool silver_statue_effects(monsters *mons);
bool moth_incite_monsters(const monsters *mon);
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 6b9a0f7158..1553b85763 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6019,23 +6019,21 @@ bool player::invisible() const
return (duration[DUR_INVIS] && !backlit());
}
-bool player::visible_to(actor *looker)
+bool player::visible_to(const actor *looker) const
{
if (this == looker)
return (!invisible() || can_see_invisible());
- monsters* mon = dynamic_cast<monsters*>(looker);
-
+ const monsters* mon = dynamic_cast<const monsters*>(looker);
return mons_player_visible(mon);
}
-bool player::can_see(actor *target)
+bool player::can_see(const actor *target) const
{
if (this == target)
return visible_to(target);
- monsters* mon = dynamic_cast<monsters*>(target);
-
+ const monsters* mon = dynamic_cast<const monsters*>(target);
return (mons_near(mon) && target->visible_to(this));
}