summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/beam.cc25
-rw-r--r--crawl-ref/source/beam.h5
-rw-r--r--crawl-ref/source/dungeon.cc7
-rw-r--r--crawl-ref/source/externs.h31
-rw-r--r--crawl-ref/source/fight.cc6
-rw-r--r--crawl-ref/source/it_use2.cc3
-rw-r--r--crawl-ref/source/mon-util.cc31
-rw-r--r--crawl-ref/source/monstuff.cc2
-rw-r--r--crawl-ref/source/mstuff2.cc23
-rw-r--r--crawl-ref/source/player.cc8
-rw-r--r--crawl-ref/source/religion.cc2
-rw-r--r--crawl-ref/source/spl-cast.cc53
12 files changed, 143 insertions, 53 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 248c50f04c..13644d9d7d 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2562,7 +2562,7 @@ bool curare_hits_monster(actor *agent, monsters *monster, kill_category who,
}
if (monster->alive())
- enchant_monster_with_flavour(monster, BEAM_SLOW);
+ enchant_monster_with_flavour(monster, agent, BEAM_SLOW);
}
// Deities take notice.
@@ -3593,7 +3593,7 @@ void bolt::affect_player_enchantment() {
break;
case BEAM_PETRIFY:
- you.petrify( ench_power );
+ you.petrify( agent(), ench_power );
obvious_effect = true;
break;
@@ -4608,11 +4608,13 @@ bool _ench_flavour_affects_monster(beam_type flavour, const monsters* mon)
return rc;
}
-bool enchant_monster_with_flavour(monsters* mon, beam_type flavour, int powc)
+bool enchant_monster_with_flavour(monsters* mon, actor *foe,
+ beam_type flavour, int powc)
{
bolt dummy;
dummy.flavour = flavour;
dummy.ench_power = powc;
+ dummy.set_agent(foe);
dummy.apply_enchantment_to_monster(mon);
return dummy.obvious_effect;
}
@@ -5462,6 +5464,23 @@ void bolt::setup_retrace()
aimed_at_spot = true;
}
+void bolt::set_agent(actor *actor)
+{
+ // NULL actor is fine by us.
+ if (!actor)
+ return;
+
+ if (actor->atype() == ACT_PLAYER)
+ {
+ thrower = KILL_YOU_MISSILE;
+ }
+ else
+ {
+ thrower = KILL_MON_MISSILE;
+ beam_source = monster_index(dynamic_cast<monsters*>(actor));
+ }
+}
+
actor* bolt::agent() const
{
if (YOU_KILL(this->thrower))
diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h
index e88008f4ec..bec6360a0c 100644
--- a/crawl-ref/source/beam.h
+++ b/crawl-ref/source/beam.h
@@ -118,6 +118,7 @@ public:
bool is_enchantment() const; // no block/dodge, use magic resist
void set_target(const dist &targ);
+ void set_agent(actor *agent);
void setup_retrace();
// Returns YOU_KILL or MON_KILL, depending on the source of the beam.
@@ -245,8 +246,8 @@ int mons_adjust_flavoured(monsters *monster, bolt &pbolt, int hurted,
bool doFlavouredEffects = true);
// Return whether the effect was visible.
-bool enchant_monster_with_flavour(monsters* mon, beam_type flavour,
- int powc = 0);
+bool enchant_monster_with_flavour(monsters* mon, actor *atk,
+ beam_type flavour, int powc = 0);
// returns true if messages were generated during the enchantment
bool mass_enchantment( enchant_type wh_enchant, int pow, int who,
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 4df4bf78df..3342bf40fe 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -925,6 +925,13 @@ static void _reset_level()
menv[i].reset();
env.mons_alloc.init(MONS_PROGRAM_BUG);
+
+ // Zap clouds
+ env.cgrid.init(EMPTY_CLOUD);
+
+ const cloud_struct empty;
+ env.cloud.init(empty);
+
mgrd.init(NON_MONSTER);
igrd.init(NON_ITEM);
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 4c11d2a6e0..134c247218 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -338,10 +338,10 @@ public:
virtual void teleport(bool right_now = false, bool abyss_shift = false) = 0;
virtual void poison(actor *attacker, int amount = 1) = 0;
virtual bool sicken(int amount) = 0;
- virtual void paralyse(int strength) = 0;
- virtual void petrify(int strength) = 0;
- virtual void slow_down(int strength) = 0;
- virtual void confuse(int strength) = 0;
+ virtual void paralyse(actor *attacker, int strength) = 0;
+ virtual void petrify(actor *attacker, int strength) = 0;
+ virtual void slow_down(actor *attacker, int strength) = 0;
+ virtual void confuse(actor *attacker, int strength) = 0;
virtual void rot(actor *attacker, int rotlevel, int immediate_rot) = 0;
virtual void expose_to_element(beam_type element, int strength = 0) = 0;
virtual void drain_stat(int stat, int amount, actor* attacker) { }
@@ -1061,10 +1061,10 @@ public:
void make_hungry(int nutrition, bool silent = true);
void poison(actor *agent, int amount = 1);
bool sicken(int amount);
- void paralyse(int str);
- void petrify(int str);
- void slow_down(int str);
- void confuse(int strength);
+ void paralyse(actor *, int str);
+ void petrify(actor *, int str);
+ void slow_down(actor *, int str);
+ void confuse(actor *, int strength);
void rot(actor *agent, int rotlevel, int immed_rot);
void heal(int amount, bool max_too = false);
int hurt(const actor *attacker, int amount,
@@ -1323,6 +1323,8 @@ public:
void react_to_damage(int damage, beam_type flavour);
+ void forget_random_spell();
+
void add_enchantment_effect(const mon_enchant &me, bool quiet = false);
void remove_enchantment_effect(const mon_enchant &me, bool quiet = false);
void apply_enchantments();
@@ -1489,10 +1491,10 @@ public:
void poison(actor *agent, int amount = 1);
bool sicken(int strength);
- void paralyse(int str);
- void petrify(int str);
- void slow_down(int str);
- void confuse(int strength);
+ void paralyse(actor *, int str);
+ void petrify(actor *, int str);
+ void slow_down(actor *, int str);
+ void confuse(actor *, int strength);
void rot(actor *agent, int rotlevel, int immed_rot);
int hurt(const actor *attacker, int amount,
beam_type flavour = BEAM_MISSILE,
@@ -1559,6 +1561,11 @@ struct cloud_struct
kill_category whose;
killer_type killer;
+ cloud_struct() : pos(), type(CLOUD_NONE), decay(0), spread_rate(0),
+ whose(KC_OTHER), killer(KILL_NONE)
+ {
+ }
+
void set_whose(kill_category _whose);
void set_killer(killer_type _killer);
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 5f8ed20af7..1f9c08369e 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -4215,9 +4215,9 @@ void melee_attack::wasp_paralyse_defender()
if (defender->res_poison() <= 0)
{
if (one_chance_in(paralyse_roll))
- defender->paralyse( roll_dice(1, 3) );
+ defender->paralyse( attacker, roll_dice(1, 3) );
else
- defender->slow_down( roll_dice(1, 3) );
+ defender->slow_down( attacker, roll_dice(1, 3) );
}
}
@@ -4440,7 +4440,7 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
if (one_chance_in(10)
|| (damage_done > 2 && one_chance_in(3)))
{
- defender->confuse(1 + random2(3 + atk->hit_dice));
+ defender->confuse(attacker, 1 + random2(3 + atk->hit_dice));
}
break;
diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc
index 16ba9dfdd4..2c3714ae77 100644
--- a/crawl-ref/source/it_use2.cc
+++ b/crawl-ref/source/it_use2.cc
@@ -217,7 +217,8 @@ bool potion_effect( potion_type pot_eff, int pow, bool was_known )
break;
case POT_PARALYSIS:
- you.paralyse((2 + random2( 6 + you.duration[DUR_PARALYSIS] )) / factor);
+ you.paralyse(NULL,
+ (2 + random2( 6 + you.duration[DUR_PARALYSIS] )) / factor);
xom_is_stimulated(64 / factor);
break;
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 1435023650..4f7e80b8cf 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -5663,27 +5663,27 @@ void monsters::rot(actor *agent, int rotlevel, int immed_rot)
}
}
-void monsters::confuse(int strength)
+void monsters::confuse(actor *atk, int strength)
{
- enchant_monster_with_flavour(this, BEAM_CONFUSION, strength);
+ enchant_monster_with_flavour(this, atk, BEAM_CONFUSION, strength);
}
-void monsters::paralyse(int strength)
+void monsters::paralyse(actor *atk, int strength)
{
- enchant_monster_with_flavour(this, BEAM_PARALYSIS, strength);
+ enchant_monster_with_flavour(this, atk, BEAM_PARALYSIS, strength);
}
-void monsters::petrify(int strength)
+void monsters::petrify(actor *atk, int strength)
{
if (mons_is_insubstantial(type))
return;
- enchant_monster_with_flavour(this, BEAM_PETRIFY, strength);
+ enchant_monster_with_flavour(this, atk, BEAM_PETRIFY, strength);
}
-void monsters::slow_down(int strength)
+void monsters::slow_down(actor *atk, int strength)
{
- enchant_monster_with_flavour(this, BEAM_SLOW, strength);
+ enchant_monster_with_flavour(this, atk, BEAM_SLOW, strength);
}
void monsters::set_ghost(const ghost_demon &g)
@@ -5986,6 +5986,17 @@ bool monsters::add_ench(const mon_enchant &ench)
return (true);
}
+void monsters::forget_random_spell()
+{
+ int which_spell = -1;
+ int count = 0;
+ for (int i = 0; i < NUM_MONSTER_SPELL_SLOTS; ++i)
+ if (spells[i] != SPELL_NO_SPELL && one_chance_in(++count))
+ which_spell = i;
+ if (which_spell != -1)
+ spells[which_spell] = SPELL_NO_SPELL;
+}
+
void monsters::add_enchantment_effect(const mon_enchant &ench, bool quiet)
{
// Check for slow/haste.
@@ -7512,12 +7523,12 @@ item_type_id_state_type monsters::drink_potion_effect(potion_type ptype)
break;
case POT_SPEED:
- if (enchant_monster_with_flavour(this, BEAM_HASTE))
+ if (enchant_monster_with_flavour(this, this, BEAM_HASTE))
ident = ID_KNOWN_TYPE;
break;
case POT_INVISIBILITY:
- if (enchant_monster_with_flavour(this, BEAM_INVISIBILITY))
+ if (enchant_monster_with_flavour(this, this, BEAM_INVISIBILITY))
ident = ID_KNOWN_TYPE;
break;
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 795b825621..6fc5625818 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -6556,7 +6556,7 @@ static void _handle_monster_move(int i, monsters *monster)
}
}
- if (mons_is_lurking(monster))
+ if (mons_is_lurking(monster) || mons_is_submerged(monster))
{
// Lurking monsters only stop lurking if their target is right
// next to them, otherwise they just sit there.
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index ecdfc8e4ca..a2276bac09 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -24,6 +24,7 @@
#include "itemname.h"
#include "itemprop.h"
#include "items.h"
+#include "Kills.h"
#include "message.h"
#include "misc.h"
#include "monplace.h"
@@ -2237,7 +2238,8 @@ static int _monster_abjuration(const monsters *caster, bool actual)
bool silver_statue_effects(monsters *mons)
{
- if ((mons_player_visible(mons) || one_chance_in(3)) && !one_chance_in(3))
+ actor *foe = mons->get_foe();
+ if (foe && mons->can_see(foe) && !one_chance_in(3))
{
const std::string msg =
"'s eyes glow " + weird_glowing_colour() + '.';
@@ -2247,7 +2249,7 @@ bool silver_statue_effects(monsters *mons)
mgen_data(
summon_any_demon((coinflip() ? DEMON_COMMON
: DEMON_LESSER)),
- BEH_HOSTILE, 5, you.pos(), MHITYOU));
+ BEH_HOSTILE, 5, foe->pos(), MHITYOU));
return (true);
}
return (false);
@@ -2255,12 +2257,21 @@ bool silver_statue_effects(monsters *mons)
bool orange_statue_effects(monsters *mons)
{
- if ((mons_player_visible(mons) || one_chance_in(3))
- && !one_chance_in(3))
+ actor *foe = mons->get_foe();
+ if (foe && mons->can_see(foe) && !one_chance_in(3))
{
- mpr("A hostile presence attacks your mind!", MSGCH_WARN);
+ if (you.can_see(foe))
+ {
+ if (foe == &you)
+ mprf(MSGCH_WARN, "A hostile presence attacks your mind!");
+ else if (you.can_see(mons))
+ mprf(MSGCH_WARN, "%s fixes %s piercing gaze on %s.",
+ mons->name(DESC_CAP_THE).c_str(),
+ mons->pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str(),
+ foe->name(DESC_NOCAP_THE).c_str());
+ }
- MiscastEffect( &you, monster_index(mons), SPTYP_DIVINATION,
+ MiscastEffect( foe, monster_index(mons), SPTYP_DIVINATION,
random2(15), random2(150),
"an orange crystal statue");
return (true);
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index cc236f217a..f04a9e4094 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6827,12 +6827,12 @@ void player::rot(actor *who, int rotlevel, int immed_rot)
disease_player( 50 + random2(100) );
}
-void player::confuse(int str)
+void player::confuse(actor *who, int str)
{
confuse_player(str);
}
-void player::paralyse(int str)
+void player::paralyse(actor *who, int str)
{
int &paralysis(duration[DUR_PARALYSIS]);
@@ -6846,7 +6846,7 @@ void player::paralyse(int str)
paralysis = 13;
}
-void player::petrify(int str)
+void player::petrify(actor *who, int str)
{
int &petrif(duration[DUR_PETRIFIED]);
@@ -6859,7 +6859,7 @@ void player::petrify(int str)
petrif = std::min(13, petrif);
}
-void player::slow_down(int str)
+void player::slow_down(actor *foe, int str)
{
::slow_player( str );
}
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 2ca8d4d9b4..c1e1845971 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -4145,7 +4145,7 @@ static bool _zin_retribution()
you.put_to_sleep();
break;
case 2:
- you.paralyse(3 + random2(10));
+ you.paralyse(NULL, 3 + random2(10));
break;
}
break;
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index d448f053c5..2623db1db4 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -2461,8 +2461,10 @@ void MiscastEffect::do_miscast()
// killed a target which was alive when the object was created.
if (!target->alive())
{
+#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Miscast target '%s' already dead",
target->name(DESC_PLAIN, true).c_str());
+#endif
return;
}
@@ -2484,13 +2486,8 @@ void MiscastEffect::do_miscast()
sp_type = school;
if (sp_type == SPTYP_RANDOM)
{
- // XXX: Monsters currently have no divination miscasts.
- do
- {
- int exp = (random2(SPTYP_LAST_EXPONENT));
- sp_type = (spschool_flag_type) (1 << exp);
- } while (sp_type == SPTYP_DIVINATION
- && target->atype() == ACT_MONSTER);
+ int exp = (random2(SPTYP_LAST_EXPONENT));
+ sp_type = (spschool_flag_type) (1 << exp);
}
}
@@ -2788,13 +2785,13 @@ void MiscastEffect::_potion_effect(int pot_eff, int pot_pow)
}
// Intentional fallthrough if that didn't work.
case POT_SLOWING:
- target->slow_down(pot_pow);
+ target->slow_down(act_source, pot_pow);
break;
case POT_PARALYSIS:
- target->paralyse(pot_pow);
+ target->paralyse(act_source, pot_pow);
break;
case POT_CONFUSION:
- target->confuse(pot_pow);
+ target->confuse(act_source, pot_pow);
break;
default:
@@ -3662,6 +3659,42 @@ void MiscastEffect::_divination_you(int severity)
// XXX: Monster divination miscasts.
void MiscastEffect::_divination_mon(int severity)
{
+ switch (severity)
+ {
+ case 0: // just a harmless message
+ mon_msg_seen = "@The_monster@ looks momentarily confused.";
+ break;
+
+ case 1: // more annoying things
+ switch (random2(2))
+ {
+ case 0:
+ mon_msg_seen = "@The_monster@ looks slightly disoriented.";
+ break;
+ case 1:
+ mon_target->confuse(
+ act_source,
+ 1 + random2(3 + act_source->get_experience_level()));
+ break;
+ }
+ break;
+
+ case 2: // even more annoying things
+ mon_msg_seen = "@The_monster@ shudders.";
+ mon_target->confuse(
+ act_source,
+ 5 + random2(3 + act_source->get_experience_level()));
+ break;
+
+ case 3: // nasty
+ mon_msg_seen = "@The_monster@ reels.";
+ if (one_chance_in(7))
+ mon_target->forget_random_spell();
+ mon_target->confuse(
+ act_source,
+ 8 + random2(3 + act_source->get_experience_level()));
+ break;
+ }
}
void MiscastEffect::_necromancy(int severity)