summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/attitude-change.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/attitude-change.cc')
-rw-r--r--crawl-ref/source/attitude-change.cc962
1 files changed, 962 insertions, 0 deletions
diff --git a/crawl-ref/source/attitude-change.cc b/crawl-ref/source/attitude-change.cc
new file mode 100644
index 0000000000..0f3ba57b41
--- /dev/null
+++ b/crawl-ref/source/attitude-change.cc
@@ -0,0 +1,962 @@
+/*
+ * Summary: Monster attitude changing due to religion.
+ */
+
+#include "AppHdr.h"
+
+#include "attitude-change.h"
+
+#include <sstream>
+
+#include "coordit.h"
+#include "database.h"
+#include "env.h"
+#include "files.h"
+#include "godabil.h"
+#include "goditem.h"
+#include "message.h"
+#include "mon-behv.h"
+#include "mon-util.h"
+#include "monster.h"
+#include "monstuff.h"
+#include "player.h"
+#include "random.h"
+#include "religion.h"
+#include "state.h"
+#include "stuff.h"
+#include "travel.h"
+
+void good_god_follower_attitude_change(monsters *monster)
+{
+ if (you.is_unholy() || crawl_state.arena)
+ return;
+
+ // For followers of good gods, decide whether holy beings will be
+ // good neutral towards you.
+ if (is_good_god(you.religion)
+ && monster->foe == MHITYOU
+ && mons_is_holy(monster)
+ && !testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT)
+ && !mons_wont_attack(monster)
+ && you.visible_to(monster) && !monster->asleep()
+ && !mons_is_confused(monster) && !monster->paralysed())
+ {
+ monster->flags |= MF_ATT_CHANGE_ATTEMPT;
+
+ if (x_chance_in_y(you.piety, MAX_PIETY) && !you.penance[you.religion])
+ {
+ const item_def* wpn = you.weapon();
+ if (wpn
+ && wpn->base_type == OBJ_WEAPONS
+ && is_evil_item(*wpn)
+ && coinflip()) // 50% chance of conversion failing
+ {
+ msg::stream << monster->name(DESC_CAP_THE)
+ << " glares at your weapon."
+ << std::endl;
+ good_god_holy_fail_attitude_change(monster);
+ return;
+ }
+ good_god_holy_attitude_change(monster);
+ stop_running();
+ }
+ else
+ good_god_holy_fail_attitude_change(monster);
+ }
+}
+
+void beogh_follower_convert(monsters *monster, bool orc_hit)
+{
+ if (you.species != SP_HILL_ORC || crawl_state.arena)
+ return;
+
+ // For followers of Beogh, decide whether orcs will join you.
+ if (you.religion == GOD_BEOGH
+ && monster->foe == MHITYOU
+ && mons_species(monster->type) == MONS_ORC
+ && !mons_is_summoned(monster)
+ && !mons_is_shapeshifter(monster)
+ && !testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT)
+ && !mons_friendly(monster)
+ && you.visible_to(monster) && !monster->asleep()
+ && !mons_is_confused(monster) && !monster->paralysed())
+ {
+ monster->flags |= MF_ATT_CHANGE_ATTEMPT;
+
+ const int hd = monster->hit_dice;
+
+ if (you.piety >= piety_breakpoint(2) && !player_under_penance()
+ && random2(you.piety / 15) + random2(4 + you.experience_level / 3)
+ > random2(hd) + hd + random2(5))
+ {
+ if (you.weapon()
+ && you.weapon()->base_type == OBJ_WEAPONS
+ && get_weapon_brand(*you.weapon()) == SPWPN_ORC_SLAYING
+ && coinflip()) // 50% chance of conversion failing
+ {
+ msg::stream << monster->name(DESC_CAP_THE)
+ << " flinches from your weapon."
+ << std::endl;
+ return;
+ }
+ beogh_convert_orc(monster, orc_hit);
+ stop_running();
+ }
+ }
+}
+
+void slime_convert(monsters* monster)
+{
+ if (you.religion == GOD_JIYVA && mons_is_slime(monster)
+ && !mons_is_summoned(monster)
+ && !mons_is_shapeshifter(monster)
+ && !mons_neutral(monster)
+ && !mons_friendly(monster)
+ && !testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT)
+ && you.visible_to(monster) && !monster->asleep()
+ && !mons_is_confused(monster) && !monster->paralysed())
+ {
+ monster->flags |= MF_ATT_CHANGE_ATTEMPT;
+ if (!player_under_penance())
+ {
+ jiyva_convert_slime(monster);
+ stop_running();
+ }
+ }
+}
+
+void feawn_neutralise(monsters* monster)
+{
+ if (you.religion == GOD_FEAWN
+ && monster->attitude == ATT_HOSTILE
+ && feawn_neutralises(monster)
+ && !testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT)
+ && !player_under_penance())
+ {
+ // We must call remove_auto_exclude before neutralizing the
+ // plant because remove_auto_exclude only removes exclusions
+ // it thinks were caused by auto-exclude, and
+ // auto-exclusions now check for ATT_HOSTILE. Oh, what a
+ // tangled web, etc.
+ remove_auto_exclude(monster, false);
+
+ feawn_neutralise_plant(monster);
+ monster->flags |= MF_ATT_CHANGE_ATTEMPT;
+
+ stop_running();
+ }
+}
+
+static bool _holy_beings_on_level_attitude_change()
+{
+ bool success = false;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (monster->alive()
+ && mons_is_holy(monster))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Holy attitude changing: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ // If you worship a good god, you get another chance to make
+ // neutral and hostile holy beings good neutral.
+ if (is_good_god(you.religion) && !mons_wont_attack(monster))
+ {
+ if (testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT))
+ {
+ monster->flags &= ~MF_ATT_CHANGE_ATTEMPT;
+
+ success = true;
+ }
+ }
+ // If you don't worship a good god, you make all friendly
+ // and good neutral holy beings that worship a good god
+ // hostile.
+ else if (!is_good_god(you.religion) && mons_wont_attack(monster)
+ && is_good_god(monster->god))
+ {
+ monster->attitude = ATT_HOSTILE;
+ monster->del_ench(ENCH_CHARM, true);
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+
+ success = true;
+ }
+ }
+ }
+
+ return (success);
+}
+
+bool holy_beings_attitude_change()
+{
+ return (apply_to_all_dungeons(_holy_beings_on_level_attitude_change));
+}
+
+static bool _evil_beings_on_level_attitude_change()
+{
+ bool success = false;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (monster->alive()
+ && monster->is_evil())
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Evil attitude changing: %s "
+ "on level %d, branch %d",
+ monster->name(DESC_PLAIN, true).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ // If you worship a good god, you make all friendly and good
+ // neutral evil and unholy beings hostile.
+ if (is_good_god(you.religion) && mons_wont_attack(monster))
+ {
+ monster->attitude = ATT_HOSTILE;
+ monster->del_ench(ENCH_CHARM, true);
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+
+ success = true;
+ }
+ }
+ }
+
+ return (success);
+}
+
+bool evil_beings_attitude_change()
+{
+ return (apply_to_all_dungeons(_evil_beings_on_level_attitude_change));
+}
+
+static bool _chaotic_beings_on_level_attitude_change()
+{
+ bool success = false;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (monster->alive()
+ && monster->is_chaotic())
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Chaotic attitude changing: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ // If you worship Zin, you make all friendly and good neutral
+ // chaotic beings hostile.
+ if (you.religion == GOD_ZIN && mons_wont_attack(monster))
+ {
+ monster->attitude = ATT_HOSTILE;
+ monster->del_ench(ENCH_CHARM, true);
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+
+ success = true;
+ }
+ }
+ }
+
+ return (success);
+}
+
+bool chaotic_beings_attitude_change()
+{
+ return (apply_to_all_dungeons(_chaotic_beings_on_level_attitude_change));
+}
+
+static bool _magic_users_on_level_attitude_change()
+{
+ bool success = false;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (monster->alive()
+ && mons_is_magic_user(monster))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Magic user attitude changing: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ // If you worship Trog, you make all friendly and good neutral
+ // magic users hostile.
+ if (you.religion == GOD_TROG && mons_wont_attack(monster))
+ {
+ monster->attitude = ATT_HOSTILE;
+ monster->del_ench(ENCH_CHARM, true);
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY/WAS_NEUTRAL stays.
+
+ success = true;
+ }
+ }
+ }
+
+ return (success);
+}
+
+bool magic_users_attitude_change()
+{
+ return (apply_to_all_dungeons(_magic_users_on_level_attitude_change));
+}
+
+// Make summoned (temporary) god gifts disappear on penance or when
+// abandoning the god in question. If seen, only count monsters where
+// the player can see the change, and output a message.
+static bool _make_god_gifts_on_level_disappear(bool seen = false)
+{
+ const god_type god =
+ (crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
+ : GOD_NO_GOD;
+ int count = 0;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (is_follower(monster)
+ && monster->has_ench(ENCH_ABJ)
+ && mons_is_god_gift(monster, god))
+ {
+ if (!seen || simple_monster_message(monster, " abandons you!"))
+ count++;
+
+ // The monster disappears.
+ monster_die(monster, KILL_DISMISSED, NON_MONSTER);
+ }
+ }
+
+ return (count);
+}
+
+static bool _god_gifts_disappear_wrapper()
+{
+ return (_make_god_gifts_on_level_disappear());
+}
+
+// Make god gifts disappear on all levels, or on only the current one.
+bool make_god_gifts_disappear(bool level_only)
+{
+ bool success = _make_god_gifts_on_level_disappear(true);
+
+ if (level_only)
+ return (success);
+
+ return (apply_to_all_dungeons(_god_gifts_disappear_wrapper) || success);
+}
+
+// When abandoning the god in question, turn holy god gifts good
+// neutral. If seen, only count monsters where the player can see the
+// change, and output a message.
+static bool _make_holy_god_gifts_on_level_good_neutral(bool seen = false)
+{
+ const god_type god =
+ (crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
+ : GOD_NO_GOD;
+ int count = 0;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (is_follower(monster)
+ && !monster->has_ench(ENCH_CHARM)
+ && mons_is_holy(monster)
+ && mons_is_god_gift(monster, god))
+ {
+ // monster changes attitude
+ monster->attitude = ATT_GOOD_NEUTRAL;
+
+ if (!seen || simple_monster_message(monster, " becomes indifferent."))
+ count++;
+ }
+ }
+
+ return (count);
+}
+
+static bool _holy_god_gifts_good_neutral_wrapper()
+{
+ return (_make_holy_god_gifts_on_level_good_neutral());
+}
+
+// Make holy god gifts turn good neutral on all levels, or on only the
+// current one.
+bool make_holy_god_gifts_good_neutral(bool level_only)
+{
+ bool success = _make_holy_god_gifts_on_level_good_neutral(true);
+
+ if (level_only)
+ return (success);
+
+ return (apply_to_all_dungeons(_holy_god_gifts_good_neutral_wrapper) || success);
+}
+
+// When abandoning the god in question, turn god gifts hostile. If
+// seen, only count monsters where the player can see the change, and
+// output a message.
+static bool _make_god_gifts_on_level_hostile(bool seen = false)
+{
+ const god_type god =
+ (crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
+ : GOD_NO_GOD;
+ int count = 0;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (is_follower(monster)
+ && mons_is_god_gift(monster, god))
+ {
+ // monster changes attitude and behaviour
+ monster->attitude = ATT_HOSTILE;
+ monster->del_ench(ENCH_CHARM, true);
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+
+ if (!seen || simple_monster_message(monster, " turns against you!"))
+ count++;
+ }
+ }
+
+ return (count);
+}
+
+static bool _god_gifts_hostile_wrapper()
+{
+ return (_make_god_gifts_on_level_hostile());
+}
+
+// Make god gifts turn hostile on all levels, or on only the current
+// one.
+bool make_god_gifts_hostile(bool level_only)
+{
+ bool success = _make_god_gifts_on_level_hostile(true);
+
+ if (level_only)
+ return (success);
+
+ return (apply_to_all_dungeons(_god_gifts_hostile_wrapper) || success);
+}
+
+static bool _is_yred_enslaved_body_and_soul(const monsters* mon)
+{
+ return (mon->alive() && mons_enslaved_body_and_soul(mon));
+}
+
+static bool _yred_slaves_on_level_abandon_you()
+{
+ bool success = false;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (_is_yred_enslaved_body_and_soul(monster))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Undead soul abandoning: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ yred_make_enslaved_soul(monster, true, true, true);
+
+ success = true;
+ }
+ else if (is_yred_undead_slave(monster))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Undead abandoning: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ monster->attitude = ATT_HOSTILE;
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY stays.
+
+ success = true;
+ }
+ }
+
+ return (success);
+}
+
+static bool _beogh_followers_on_level_abandon_you()
+{
+ bool success = false;
+
+ // Note that orc high priests' summons are gifts of Beogh, so we
+ // can't use is_orcish_follower() here.
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (mons_is_god_gift(monster, GOD_BEOGH))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Orc abandoning: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ monster->attitude = ATT_HOSTILE;
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY stays.
+
+ success = true;
+ }
+ }
+
+ return (success);
+}
+
+static bool _jiyva_slimes_on_level_abandon_you()
+{
+ bool success = false;
+
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (is_fellow_slime(monster))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Slime abandoning: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ monster->attitude = ATT_HOSTILE;
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now WAS_NEUTRAL stays.
+
+ success = true;
+ }
+ }
+
+ return (success);
+}
+
+// Upon excommunication, ex-Yredelemnulites lose all their undead
+// slaves. When under penance, Yredelemnulites can lose all undead
+// slaves in sight.
+bool yred_slaves_abandon_you()
+{
+ bool reclaim = false;
+ int num_reclaim = 0;
+ int num_slaves = 0;
+
+ if (you.religion != GOD_YREDELEMNUL)
+ reclaim = apply_to_all_dungeons(_yred_slaves_on_level_abandon_you);
+ else
+ {
+ for (radius_iterator ri(you.pos(), 9); ri; ++ri)
+ {
+ monsters *monster = monster_at(*ri);
+ if (monster == NULL)
+ continue;
+
+ if (_is_yred_enslaved_body_and_soul(monster)
+ || is_yred_undead_slave(monster))
+ {
+ num_slaves++;
+
+ const int hd = monster->hit_dice;
+
+ // During penance, followers get a saving throw.
+ if (random2((you.piety - you.penance[GOD_YREDELEMNUL]) / 18)
+ + random2(you.skills[SK_INVOCATIONS] - 6)
+ > random2(hd) + hd + random2(5))
+ {
+ continue;
+ }
+
+
+ if (_is_yred_enslaved_body_and_soul(monster))
+ yred_make_enslaved_soul(monster, true, true, true);
+ else
+ {
+ monster->attitude = ATT_HOSTILE;
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY stays.
+ }
+
+ num_reclaim++;
+
+ reclaim = true;
+ }
+ }
+ }
+
+ if (reclaim)
+ {
+ if (you.religion != GOD_YREDELEMNUL)
+ {
+ simple_god_message(" reclaims all of your granted undead slaves!",
+ GOD_YREDELEMNUL);
+ }
+ else if (num_reclaim > 0)
+ {
+ if (num_reclaim == 1 && num_slaves > 1)
+ simple_god_message(" reclaims one of your granted undead slaves!");
+ else if (num_reclaim == num_slaves)
+ simple_god_message(" reclaims your granted undead slaves!");
+ else
+ simple_god_message(" reclaims some of your granted undead slaves!");
+ }
+
+ return (true);
+ }
+
+ return (false);
+}
+
+static bool _feawn_plants_on_level_hostile()
+{
+ for (int i = 0; i < MAX_MONSTERS; ++i)
+ {
+ monsters *monster = &menv[i];
+ if (monster->alive()
+ && mons_is_plant(monster))
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS, "Plant hostility: %s on level %d, branch %d",
+ monster->name(DESC_PLAIN).c_str(),
+ static_cast<int>(you.your_level),
+ static_cast<int>(you.where_are_you));
+#endif
+
+ // You can potentially turn an oklob or whatever neutral
+ // again by going back to Feawn.
+ if (testbits(monster->flags, MF_ATT_CHANGE_ATTEMPT))
+ monster->flags &= ~MF_ATT_CHANGE_ATTEMPT;
+
+ monster->attitude = ATT_HOSTILE;
+ monster->del_ench(ENCH_CHARM, true);
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now WAS_NEUTRAL stays.
+ }
+ }
+
+ return (true);
+}
+
+bool feawn_plants_hostile()
+{
+ if (apply_to_all_dungeons(_feawn_plants_on_level_hostile))
+ {
+ mpr("The plants of the dungeon turn on you!", MSGCH_GOD);
+ return (true);
+ }
+
+ return (false);
+}
+
+// Upon excommunication, ex-Beoghites lose all their orcish followers,
+// plus all monsters created by their priestly orcish followers. When
+// under penance, Beoghites can lose all orcish followers in sight,
+// subject to a few limitations.
+bool beogh_followers_abandon_you()
+{
+ bool reconvert = false;
+ int num_reconvert = 0;
+ int num_followers = 0;
+
+ if (you.religion != GOD_BEOGH)
+ {
+ reconvert =
+ apply_to_all_dungeons(_beogh_followers_on_level_abandon_you);
+ }
+ else
+ {
+ for (radius_iterator ri(you.pos(), 9); ri; ++ri)
+ {
+ monsters *monster = monster_at(*ri);
+ if (monster == NULL)
+ continue;
+
+ // Note that orc high priests' summons are gifts of Beogh,
+ // so we can't use is_orcish_follower() here.
+ if (mons_is_god_gift(monster, GOD_BEOGH))
+ {
+ num_followers++;
+
+ if (you.visible_to(monster)
+ && !monster->asleep()
+ && !mons_is_confused(monster)
+ && !mons_cannot_act(monster))
+ {
+ const int hd = monster->hit_dice;
+
+ // During penance, followers get a saving throw.
+ if (random2((you.piety - you.penance[GOD_BEOGH]) / 18)
+ + random2(you.skills[SK_INVOCATIONS] - 6)
+ > random2(hd) + hd + random2(5))
+ {
+ continue;
+ }
+
+ monster->attitude = ATT_HOSTILE;
+ behaviour_event(monster, ME_ALERT, MHITYOU);
+ // For now CREATED_FRIENDLY stays.
+
+ if (you.can_see(monster))
+ num_reconvert++; // Only visible ones.
+
+ reconvert = true;
+ }
+ }
+ }
+ }
+
+ if (reconvert) // Maybe all of them are invisible.
+ {
+ simple_god_message("'s voice booms out, \"Who do you think you "
+ "are?\"", GOD_BEOGH);
+
+ std::ostream& chan = msg::streams(MSGCH_MONSTER_ENCHANT);
+
+ if (you.religion != GOD_BEOGH)
+ chan << "All of your followers decide to abandon you.";
+ else if (num_reconvert > 0)
+ {
+ if (num_reconvert == 1 && num_followers > 1)
+ chan << "One of your followers decides to abandon you.";
+ else if (num_reconvert == num_followers)
+ chan << "Your followers decide to abandon you.";
+ else
+ chan << "Some of your followers decide to abandon you.";
+ }
+
+ chan << std::endl;
+
+ return (true);
+ }
+
+ return (false);
+}
+
+// Upon excommunication, ex-Jiyvaites lose all their fellow slimes.
+bool jiyva_slimes_abandon_you()
+{
+ if (apply_to_all_dungeons(_jiyva_slimes_on_level_abandon_you))
+ {
+ std::ostream& chan = msg::streams(MSGCH_MONSTER_ENCHANT);
+
+ chan << "All of your fellow slimes turn on you." << std::endl;
+
+ return (true);
+ }
+
+ return (false);
+}
+
+static void _print_good_god_holy_being_speech(bool neutral,
+ const std::string key,
+ monsters *mon,
+ msg_channel_type channel)
+{
+ std::string full_key = "good_god_";
+ if (!neutral)
+ full_key += "non";
+ full_key += "neutral_holy_being_";
+ full_key += key;
+
+ std::string msg = getSpeakString(full_key);
+
+ if (!msg.empty())
+ {
+ msg = do_mon_str_replacements(msg, mon);
+ mpr(msg.c_str(), channel);
+ }
+}
+
+// Holy monsters may turn good neutral when encountering followers of
+// the good gods, and be made worshippers of TSO if necessary.
+void good_god_holy_attitude_change(monsters *holy)
+{
+ ASSERT(mons_is_holy(holy));
+
+ if (you.can_see(holy)) // show reaction
+ {
+ _print_good_god_holy_being_speech(true, "reaction", holy,
+ MSGCH_FRIEND_ENCHANT);
+
+ if (!one_chance_in(3))
+ _print_good_god_holy_being_speech(true, "speech", holy,
+ MSGCH_TALK);
+ }
+
+ holy->attitude = ATT_GOOD_NEUTRAL;
+
+ // The monster is not really *created* neutral, but should it become
+ // hostile later on, it won't count as a good kill.
+ holy->flags |= MF_WAS_NEUTRAL;
+
+ // If the holy being was previously worshipping a different god,
+ // make it worship TSO.
+ holy->god = GOD_SHINING_ONE;
+
+ // Avoid immobile "followers".
+ behaviour_event(holy, ME_ALERT, MHITNOT);
+}
+
+void good_god_holy_fail_attitude_change(monsters *holy)
+{
+ ASSERT(mons_is_holy(holy));
+
+ if (you.can_see(holy)) // show reaction
+ {
+ _print_good_god_holy_being_speech(false, "reaction", holy,
+ MSGCH_FRIEND_ENCHANT);
+
+ if (!one_chance_in(3))
+ _print_good_god_holy_being_speech(false, "speech", holy,
+ MSGCH_TALK);
+ }
+}
+
+static void _print_converted_orc_speech(const std::string key,
+ monsters *mon,
+ msg_channel_type channel)
+{
+ std::string msg = getSpeakString("beogh_converted_orc_" + key);
+
+ if (!msg.empty())
+ {
+ msg = do_mon_str_replacements(msg, mon);
+ mpr(msg.c_str(), channel);
+ }
+}
+
+// Orcs may turn friendly when encountering followers of Beogh, and be
+// made gifts of Beogh.
+void beogh_convert_orc(monsters *orc, bool emergency,
+ bool converted_by_follower)
+{
+ ASSERT(mons_species(orc->type) == MONS_ORC);
+
+ if (you.can_see(orc)) // show reaction
+ {
+ if (emergency || !orc->alive())
+ {
+ if (converted_by_follower)
+ {
+ _print_converted_orc_speech("reaction_battle_follower", orc,
+ MSGCH_FRIEND_ENCHANT);
+ _print_converted_orc_speech("speech_battle_follower", orc,
+ MSGCH_TALK);
+ }
+ else
+ {
+ _print_converted_orc_speech("reaction_battle", orc,
+ MSGCH_FRIEND_ENCHANT);
+ _print_converted_orc_speech("speech_battle", orc, MSGCH_TALK);
+ }
+ }
+ else
+ {
+ _print_converted_orc_speech("reaction_sight", orc,
+ MSGCH_FRIEND_ENCHANT);
+
+ if (!one_chance_in(3))
+ _print_converted_orc_speech("speech_sight", orc, MSGCH_TALK);
+ }
+ }
+
+ orc->attitude = ATT_FRIENDLY;
+
+ // The monster is not really *created* friendly, but should it
+ // become hostile later on, it won't count as a good kill.
+ orc->flags |= MF_CREATED_FRIENDLY;
+
+ // Prevent assertion if the orc was previously worshipping a
+ // different god, rather than already worshipping Beogh or being an
+ // atheist.
+ orc->god = GOD_NO_GOD;
+
+ mons_make_god_gift(orc, GOD_BEOGH);
+
+ if (orc->is_patrolling())
+ {
+ // Make orcs stop patrolling and forget their patrol point,
+ // they're supposed to follow you now.
+ orc->patrol_point = coord_def(0, 0);
+ }
+
+ if (!orc->alive())
+ orc->hit_points = std::min(random_range(1, 4), orc->max_hit_points);
+
+ // Avoid immobile "followers".
+ behaviour_event(orc, ME_ALERT, MHITNOT);
+}
+
+void feawn_neutralise_plant(monsters *plant)
+{
+ if (!plant
+ || !feawn_neutralises(plant)
+ || plant->attitude != ATT_HOSTILE
+ || testbits(plant->flags, MF_ATT_CHANGE_ATTEMPT))
+ {
+ return;
+ }
+
+ plant->attitude = ATT_GOOD_NEUTRAL;
+ plant->flags |= MF_WAS_NEUTRAL;
+}
+
+void jiyva_convert_slime(monsters* slime)
+{
+ ASSERT(mons_is_slime(slime));
+
+ if (you.can_see(slime))
+ {
+ if (mons_genus(slime->type) == MONS_GIANT_EYEBALL)
+ {
+ mprf(MSGCH_GOD, "%s stares at you suspiciously for a moment, "
+ "then relaxes.",
+
+ slime->name(DESC_CAP_THE).c_str());
+ }
+ else
+ {
+ mprf(MSGCH_GOD, "%s trembles before you.",
+ slime->name(DESC_CAP_THE).c_str());
+ }
+ }
+
+ slime->attitude = ATT_STRICT_NEUTRAL;
+ slime->flags |= MF_WAS_NEUTRAL;
+
+ if (!mons_eats_items(slime))
+ {
+ slime->add_ench(ENCH_EAT_ITEMS);
+
+ mprf(MSGCH_MONSTER_ENCHANT, "%s looks hungrier.",
+ slime->name(DESC_CAP_THE).c_str());
+ }
+
+ // Prevent assertion if the slime was previously worshipping a
+ // different god, rather than already worshipping Jiyva or being an
+ // atheist.
+ slime->god = GOD_NO_GOD;
+
+ mons_make_god_gift(slime, GOD_JIYVA);
+}