summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}