From 95d587c3feda35ad847d676165aa9e9a6c67bfb4 Mon Sep 17 00:00:00 2001 From: dshaligram Date: Mon, 8 Oct 2007 20:08:53 +0000 Subject: 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 --- crawl-ref/source/debug.cc | 25 --------------- crawl-ref/source/direct.cc | 7 ++++- crawl-ref/source/enum.h | 1 + crawl-ref/source/externs.h | 12 ++++---- crawl-ref/source/fight.cc | 15 +++++++++ crawl-ref/source/mon-util.cc | 20 +++++++----- crawl-ref/source/mon-util.h | 4 +-- crawl-ref/source/monstuff.cc | 7 +++-- crawl-ref/source/mstuff2.cc | 72 ++++++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/mstuff2.h | 1 + crawl-ref/source/player.cc | 10 +++--- 11 files changed, 124 insertions(+), 50 deletions(-) (limited to 'crawl-ref/source') 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(looker); - + const monsters* mon = dynamic_cast(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(target); + const monsters* mon = dynamic_cast(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 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 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::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(looker); - + const monsters* mon = dynamic_cast(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(target); - + const monsters* mon = dynamic_cast(target); return (mons_near(mon) && target->visible_to(this)); } -- cgit v1.2.3-54-g00ecf