summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-22 19:13:35 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-22 19:13:35 +0000
commitb432e59457a38ff3f885e6da7afd2570c5dd0098 (patch)
tree21dfe97244314bbb6e9c9dc27a1d61babb824310 /crawl-ref
parent67c2c0fa7330cb8a10c881e3370455b8909927dc (diff)
downloadcrawl-ref-b432e59457a38ff3f885e6da7afd2570c5dd0098.tar.gz
crawl-ref-b432e59457a38ff3f885e6da7afd2570c5dd0098.zip
Add Ely's pacifying monsters effect:
When a follower of Elyvilon attempts to heal a hostile monster (via ability or wand) there's a chance, depending on the healing value, max monster hp and monster type, that Ely will make that monster become neutral. If this happens, Ely hands out a bit of piety and his follower gains half of the monster's xp value. If the pacifying attempt fails, the monster is never healed, though you still lose your ressources (mana, piety, charges). Killing neutral monsters currently means you won't get any xp. Also, Ely dislikes this and hands out penance for doing so. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3812 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/beam.cc11
-rw-r--r--crawl-ref/source/enum.h5
-rw-r--r--crawl-ref/source/mon-data.h2
-rw-r--r--crawl-ref/source/monstuff.cc23
-rw-r--r--crawl-ref/source/religion.cc11
-rw-r--r--crawl-ref/source/spells1.cc127
-rw-r--r--crawl-ref/source/spells1.h2
7 files changed, 148 insertions, 33 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 7e637a96cf..7c44cdf1df 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2080,7 +2080,16 @@ int mons_ench_f2(monsters *monster, bolt &pbolt)
return (MON_AFFECTED);
case BEAM_HEALING: /* 2 = healing */
- if (heal_monster( monster, 5 + roll_dice( pbolt.damage ), false ))
+ if (YOU_KILL(pbolt.thrower))
+ {
+ if (cast_healing(5 + roll_dice( pbolt.damage ),
+ monster->x - you.x_pos, monster->y - you.y_pos) > 0)
+ {
+ pbolt.obvious_effect = true;
+ }
+ pbolt.msg_generated = true; // to avoid duplicate "nothing happens"
+ }
+ else if (heal_monster( monster, 5 + roll_dice( pbolt.damage ), false ))
{
if (monster->hit_points == monster->max_hit_points)
{
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 59cfb51ef9..49fcf96304 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -641,7 +641,7 @@ enum conduct_type
DID_KILL_WIZARD,
DID_KILL_PRIEST,
DID_KILL_HOLY,
- DID_KILL_NEUTRAL, // unused
+ DID_KILL_NEUTRAL,
DID_LIVING_KILLED_BY_UNDEAD_SLAVE,
DID_LIVING_KILLED_BY_SERVANT,
DID_UNDEAD_KILLED_BY_SERVANT,
@@ -1887,7 +1887,8 @@ enum monster_flag_type
// (good god worshippers -> neutral)
// and orcs (Beogh worshippers -> friendly)
MF_WAS_IN_VIEW = 0x2000, // Was in view during previous turn
- MF_BAND_MEMBER = 0x4000 // Created as a member of a band
+ MF_BAND_MEMBER = 0x4000, // Created as a member of a band
+ MF_GOT_HALF_XP = 0x8000 // player already got half xp value earlier
};
// Adding slots breaks saves. YHBW.
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 1058e4b926..e9d640b065 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -97,7 +97,7 @@
- various things monsters can do upon seeing you
intel explanation:
- - How smart it is: I_PLANT < I_ANIMAL < I_NORMAL < I_HIGH.
+ - How smart it is: I_PLANT < I_INSECT < I_ANIMAL < I_NORMAL < I_HIGH.
So far, differences here have little effects except for monster's chance
of seeing you if stealthy and rudimentary trap handling;
really stupid monsters will walk through clouds
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index b293160a48..e08685c1cb 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -392,7 +392,7 @@ static void check_kill_milestone(const monsters *mons,
}
#endif // DGL_MILESTONES
-static void give_monster_experience( monsters *victim,
+static void _give_monster_experience( monsters *victim,
int killer_index, int experience,
bool victim_was_born_friendly )
{
@@ -421,27 +421,34 @@ static void give_adjusted_experience(monsters *monster, killer_type killer,
testbits(monster->flags, MF_CREATED_FRIENDLY);
const bool was_neutral = testbits(monster->flags, MF_WAS_NEUTRAL);
const bool no_xp = monster->has_ench(ENCH_ABJ);
+ const bool already_got_half_xp = testbits(monster->flags, MF_GOT_HALF_XP);
if (created_friendly || was_neutral || no_xp)
; // No experience if monster was created friendly or summoned.
else if (YOU_KILL(killer))
{
int old_lev = you.experience_level;
- gain_exp( experience, exp_gain, avail_gain );
+ if (already_got_half_xp)
+ gain_exp( experience / 2, exp_gain, avail_gain );
+ else
+ gain_exp( experience, exp_gain, avail_gain );
+
// Give a message for monsters dying out of sight
if (exp_gain > 0 && !mons_near(monster)
&& you.experience_level == old_lev)
+ {
mpr("You feel a bit more experienced.");
+ }
}
- else if (pet_kill)
+ else if (pet_kill && !already_got_half_xp)
gain_exp( experience / 2 + 1, exp_gain, avail_gain );
if (MON_KILL(killer) && !no_xp)
- give_monster_experience( monster, killer_index, experience,
- created_friendly );
+ _give_monster_experience( monster, killer_index, experience,
+ created_friendly );
}
-static bool is_pet_kill(killer_type killer, int i)
+static bool _is_pet_kill(killer_type killer, int i)
{
if (!MON_KILL(killer))
return (false);
@@ -670,7 +677,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
if (killer == KILL_YOU)
crawl_state.cancel_cmd_repeat();
- const bool pet_kill = is_pet_kill(killer, i);
+ const bool pet_kill = _is_pet_kill(killer, i);
if (monster->type == MONS_GIANT_SPORE
|| monster->type == MONS_BALL_LIGHTNING)
@@ -789,7 +796,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
did_god_conduct(DID_KILL_HOLY, monster->hit_dice,
true, monster);
- if (created_friendly)
+ if (was_neutral)
did_god_conduct(DID_KILL_NEUTRAL, monster->hit_dice,
true, monster);
}
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index da043726bc..01f537ef13 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -1446,6 +1446,16 @@ bool did_god_conduct( conduct_type thing_done, int level, bool known,
}
break;
+ case DID_KILL_NEUTRAL:
+ if (you.religion == GOD_ELYVILON)
+ {
+ simple_god_message(" did not appreciate that!");
+ ret = true;
+ piety_change = -(level/2 + 1);
+ penance = std::min(level, 5);
+ }
+ break;
+
case DID_KILL_LIVING:
switch (you.religion)
{
@@ -1812,7 +1822,6 @@ bool did_god_conduct( conduct_type thing_done, int level, bool known,
}
break;
- case DID_KILL_NEUTRAL: // unused
case DID_STIMULANTS: // unused
case DID_EAT_MEAT: // unused
case DID_CREATED_LIFE: // unused
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index 8b65313412..354be9f688 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -42,6 +42,7 @@
#include "mon-util.h"
#include "player.h"
#include "randart.h"
+#include "religion.h"
#include "skills2.h"
#include "spells3.h"
#include "spells4.h"
@@ -571,32 +572,86 @@ int cast_big_c(int pow, cloud_type cty, kill_category whose, bolt &beam)
big_cloud( cty, whose,
beam.target_x, beam.target_y, pow, 8 + random2(3) );
return (1);
-} // end cast_big_c()
+}
void big_cloud(cloud_type cl_type, kill_category whose,
int cl_x, int cl_y, int pow, int size, int spread_rate)
{
apply_area_cloud(make_a_normal_cloud, cl_x, cl_y, pow, size,
cl_type, whose, spread_rate);
-} // end big_cloud()
+}
+
+static bool _mons_hostile(const monsters *mon)
+{
+ // needs to be done this way because of friendly/neutral enchantments
+ return (!mons_friendly(mon) && !mons_neutral(mon));
+}
+
+static bool _can_pacify_monster(const monsters *mon, const int healed)
+{
+ ASSERT(you.religion == GOD_ELYVILON);
+
+ if (healed < 1)
+ return false;
+
+ if (mons_friendly(mon) || mons_neutral(mon))
+ return false;
+
+ // Ely only cares about natural monsters
+ if (mons_holiness(mon) != MH_NATURAL)
+ return false;
+
+ if (mons_intel(mon->type) <= I_PLANT) // no self-awareness
+ return false;
+
+ if (mons_is_sleeping(mon)) // not aware of what is happening
+ return false;
-static int healing_spell( int healed )
+ const int factor = (mons_intel(mon->type) <= I_ANIMAL) ? 3 : // animals
+ (is_player_same_species(mon->type)) ? 2 // same species
+ : 1; // other
+
+ const int random_factor = random2(you.skills[SK_INVOCATIONS] * healed/3);
+
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "pacifying %s? max hp: %d, factor: %d, Inv: %d, healed: %d, rnd: %d",
+ mon->name(DESC_PLAIN).c_str(), mon->max_hit_points, factor,
+ you.skills[SK_INVOCATIONS], healed, random_factor);
+#endif
+
+ if (mon->max_hit_points < factor * random_factor)
+ return true;
+
+ return false;
+}
+
+static int _healing_spell( int healed, int dir_x = 100, int dir_y = 100)
{
+ ASSERT(healed >= 1);
+
int mgr = 0;
struct monsters *monster = 0; // NULL {dlb}
struct dist bmove;
- mpr("Which direction?", MSGCH_PROMPT);
- direction( bmove, DIR_DIR, TARG_FRIEND );
-
+ if (dir_x == 100 || dir_y == 100)
+ {
+ mpr("Which direction?", MSGCH_PROMPT);
+ direction( bmove, DIR_DIR, TARG_FRIEND );
+ }
+ else
+ {
+ bmove.dx = dir_x;
+ bmove.dy = dir_y;
+ bmove.isValid = true;
+ }
+
if (!bmove.isValid)
{
canned_msg( MSG_OK );
return 0;
}
- mgr = mgrd[you.x_pos + bmove.dx][you.y_pos + bmove.dy];
-
if (bmove.dx == 0 && bmove.dy == 0)
{
mpr("You are healed.");
@@ -604,6 +659,8 @@ static int healing_spell( int healed )
return 1;
}
+ mgr = mgrd[you.x_pos + bmove.dx][you.y_pos + bmove.dy];
+
if (mgr == NON_MONSTER)
{
mpr("There isn't anything there!");
@@ -611,7 +668,16 @@ static int healing_spell( int healed )
}
monster = &menv[mgr];
+
+ // don't heal monster you can't pacify
+ if (you.religion == GOD_ELYVILON && _mons_hostile(monster)
+ && !_can_pacify_monster(monster, healed))
+ {
+ canned_msg(MSG_NOTHING_HAPPENS);
+ return -1;
+ }
+ bool nothing_happens = true;
if (heal_monster(monster, healed, false))
{
mprf("You heal %s.", monster->name(DESC_NOCAP_THE).c_str());
@@ -623,38 +689,61 @@ static int healing_spell( int healed )
const monsters *mons = static_cast<const monsters*>(monster);
print_wounds(mons);
}
+
+ if (you.religion == GOD_ELYVILON && !_mons_hostile(monster))
+ {
+ simple_god_message(" appreciates the healing of a fellow creature.");
+ if (one_chance_in(8))
+ gain_piety(1);
+ return 1;
+ }
+ nothing_happens = false;
}
- else
+
+ if (you.religion == GOD_ELYVILON && _mons_hostile(monster))
{
- canned_msg(MSG_NOTHING_HAPPENS);
+ simple_god_message(" supports your offer of peace.");
+ simple_monster_message( monster, " turns neutral." );
+ monster->attitude = ATT_NEUTRAL;
+ monster->flags |= MF_WAS_NEUTRAL;
+
+ // give half of the monster's xp
+ unsigned int exp_gain = 0, avail_gain = 0;
+ gain_exp( exper_value(monster) / 2 + 1, &exp_gain, &avail_gain );
+ monster->flags |= MF_GOT_HALF_XP;
+
+ // finally give a small piety return
+ gain_piety(1 + random2(healed/15));
}
+ else if (nothing_happens)
+ canned_msg(MSG_NOTHING_HAPPENS);
return 1;
-} // end healing_spell()
+} // end _healing_spell()
#if 0
char cast_lesser_healing( int pow )
{
- return healing_spell(5 + random2avg(7, 2));
-} // end lesser healing()
+ return _healing_spell(5 + random2avg(7, 2));
+}
char cast_greater_healing( int pow )
{
- return healing_spell(15 + random2avg(29, 2));
-} // end cast_greater_healing()
+ return _healing_spell(15 + random2avg(29, 2));
+}
char cast_greatest_healing( int pow )
{
- return healing_spell(50 + random2avg(49, 2));
-} // end cast_greatest_healing()
+ return _healing_spell(50 + random2avg(49, 2));
+}
#endif
-int cast_healing( int pow )
+int cast_healing( int pow, int dir_x, int dir_y )
{
if (pow > 50)
pow = 50;
- return (healing_spell( pow + roll_dice( 2, pow ) - 2 ));
+ return (_healing_spell( pow + roll_dice( 2, pow ) - 2, dir_x, dir_y ));
}
int cast_revitalisation( int pow )
diff --git a/crawl-ref/source/spells1.h b/crawl-ref/source/spells1.h
index b945a4cc78..f7a7f92fe4 100644
--- a/crawl-ref/source/spells1.h
+++ b/crawl-ref/source/spells1.h
@@ -53,7 +53,7 @@ char cast_lesser_healing(void);
/* ***********************************************************************
* called from: ability - spell
* *********************************************************************** */
-int cast_healing(int power);
+int cast_healing(int power, int dir_x = 100, int dir_y = 100);
int cast_revitalisation(int power);
// last updated 24may2000 {dlb}