summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/externs.h3
-rw-r--r--crawl-ref/source/fight.cc13
-rw-r--r--crawl-ref/source/mon-util.cc22
-rw-r--r--crawl-ref/source/player.cc9
-rw-r--r--crawl-ref/source/spl-cast.cc44
5 files changed, 58 insertions, 33 deletions
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 6a65a845a9..747c733956 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -335,6 +335,7 @@ public:
virtual bool can_safely_mutate() const = 0;
virtual bool can_bleed() const = 0;
virtual bool mutate() = 0;
+ virtual void drain_exp(actor *agent) = 0;
virtual void rot(actor *agent, int amount, int immediate = 0) = 0;
virtual int hurt(const actor *attacker, int amount,
beam_type flavour = BEAM_MISSILE,
@@ -1073,6 +1074,7 @@ public:
void slow_down(actor *, int str);
void confuse(actor *, int strength);
void heal(int amount, bool max_too = false);
+ void drain_exp(actor *);
void rot(actor *, int amount, int immediate = 0);
int hurt(const actor *attacker, int amount,
beam_type flavour = BEAM_MISSILE,
@@ -1502,6 +1504,7 @@ public:
void petrify(actor *, int str);
void slow_down(actor *, int str);
void confuse(actor *, int strength);
+ void drain_exp(actor *);
void rot(actor *, int amount, int immediate = 0);
int hurt(const actor *attacker, int amount,
beam_type flavour = BEAM_MISSILE,
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 7fc91ca58a..6d3bd5f2a6 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -2062,7 +2062,8 @@ void melee_attack::drain_defender()
void melee_attack::drain_player()
{
- drain_exp();
+ defender->drain_exp(attacker);
+
special_damage = random2(damage_done) /
(2 + defender->res_negative_energy()) + 1;
@@ -2085,16 +2086,10 @@ void melee_attack::drain_monster()
def_name(DESC_NOCAP_THE).c_str());
}
- if (one_chance_in(5))
- {
- defender_as_monster()->hit_dice--;
- defender_as_monster()->experience = 0;
- }
-
- defender_as_monster()->max_hit_points -= 2 + random2(3);
- defender->hurt(attacker, 2 + random2(3), BEAM_NEG, false);
+ defender->drain_exp(attacker);
special_damage = 1 + (random2(damage_done) / 2);
+
attacker->god_conduct(DID_NECROMANCY, 2);
}
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index c5e4a2470c..193ee22c88 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -5874,6 +5874,22 @@ god_type monsters::deity() const
return (god);
}
+void monsters::drain_exp(actor *agent)
+{
+ if (res_negative_energy())
+ return;
+
+ if (one_chance_in(5))
+ {
+ hit_dice--;
+ experience = 0;
+ }
+
+ max_hit_points -= 2 + random2(3);
+
+ hurt(agent, 2 + random2(3), BEAM_NEG);
+}
+
void monsters::rot(actor *agent, int amount, int immediate)
{
if (res_rotting() > 0 || amount <= 0)
@@ -7138,7 +7154,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
{
// We don't have a reasonable agent to give.
// Don't clean up the monster in order to credit properly.
- this->hurt(NULL, dam, BEAM_POISON, false);
+ hurt(NULL, dam, BEAM_POISON, false);
#if DEBUG_DIAGNOSTICS
// For debugging, we don't have this silent.
@@ -7162,7 +7178,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
{
if (hit_points > 1 && one_chance_in(3))
{
- this->hurt(NULL, 1); // nonlethal so we don't care about agent
+ hurt(NULL, 1); // nonlethal so we don't care about agent
if (hit_points < max_hit_points && coinflip())
--max_hit_points;
}
@@ -7182,7 +7198,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
simple_monster_message(this, " burns!");
// We don't have a reasonable agent to give.
// Don't clean up the monster in order to credit properly.
- this->hurt(NULL, dam, BEAM_NAPALM, false);
+ hurt(NULL, dam, BEAM_NAPALM, false);
#if DEBUG_DIAGNOSTICS
mprf( MSGCH_DIAGNOSTICS, "sticky flame damage: %d", dam );
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 83f9acc7fa..cb1a22ace2 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6963,7 +6963,7 @@ int player::hurt(const actor *agent, int amount, beam_type flavour,
return (amount);
}
-void player::drain_stat(int stat, int amount, actor* attacker)
+void player::drain_stat(int stat, int amount, actor *attacker)
{
if (attacker == NULL)
lose_stat(stat, amount, false, "");
@@ -6987,6 +6987,11 @@ void player::rot(actor *who, int amount, int immediate)
disease_player(50 + random2(100));
}
+void player::drain_exp(actor *who)
+{
+ ::drain_exp();
+}
+
void player::confuse(actor *who, int str)
{
confuse_player(str);
@@ -7025,7 +7030,7 @@ void player::petrify(actor *who, int str)
void player::slow_down(actor *foe, int str)
{
- ::slow_player( str );
+ ::slow_player(str);
}
int player::has_claws(bool allow_tran) const
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index f1e6e81603..42d14d6b2f 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -3843,16 +3843,20 @@ void MiscastEffect::_necromancy(int severity)
}
case 1:
- if (target->atype() == ACT_PLAYER && !player_prot_life()
- && one_chance_in(3))
+ you_msg = "You are engulfed in negative energy!";
+ mon_msg_seen = "@The_monster@ is engulfed in negative energy!";
+
+ if (lethality_margin == 0 || you.experience > 0
+ || !avoid_lethal(you.hp))
{
- if (lethality_margin == 0 || you.experience > 0
- || !avoid_lethal(you.hp))
+ if (!target->res_negative_energy() && one_chance_in(3))
{
- drain_exp();
+ target->drain_exp(act_source);
+ break;
}
- break;
- } // otherwise it just flows through...
+ }
+
+ // If draining failed, just flow through...
case 2:
// Monster messages needed.
@@ -3872,8 +3876,8 @@ void MiscastEffect::_necromancy(int severity)
break;
case 3: // even nastier
- // Don't use two last cases for monsters.
- switch (random2(target->atype() == ACT_PLAYER ? 6 : 4))
+ // Don't use last case for monsters.
+ switch (random2(target->atype() == ACT_PLAYER ? 6 : 5))
{
case 0:
if (target->holiness() == MH_UNDEAD)
@@ -3911,24 +3915,26 @@ void MiscastEffect::_necromancy(int severity)
break;
case 4:
- if (lethality_margin > 0 && you.experience == 0
- && avoid_lethal(you.hp))
+ you_msg = "You are engulfed in negative energy!";
+ mon_msg_seen = "@The_monster@ is engulfed in negative energy!";
+
+ if (lethality_margin == 0 || you.experience > 0
+ || !avoid_lethal(you.hp))
{
- return;
+ if (!target->res_negative_energy())
+ {
+ target->drain_exp(act_source);
+ break;
+ }
}
- mpr("You are engulfed in negative energy!");
-
- if (!player_prot_life())
- {
- drain_exp();
+ // If draining failed, just flow through if it's the player...
+ if (target->atype() == ACT_MONSTER)
break;
- } // otherwise it just flows through...
case 5:
_lose_stat(STAT_RANDOM, 1 + random2avg(7, 2));
break;
-
}
break;
}