summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r--crawl-ref/source/monstuff.cc124
1 files changed, 89 insertions, 35 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 7810c20034..010e5ee080 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -784,6 +784,86 @@ static void _mummy_curse(monsters* monster, killer_type killer, int index)
}
}
+static void _spore_goes_pop(monsters *monster, killer_type killer,
+ int killer_index, bool pet_kill, bool wizard)
+{
+ if (monster->hit_points > 0 || monster->hit_points <= -15 || wizard
+ || killer == KILL_RESET || killer == KILL_DISMISSED)
+ {
+ return;
+ }
+
+ if (killer == KILL_MISC)
+ killer = KILL_MON;
+
+ bolt beam;
+ const int type = monster->type;
+
+ beam.is_tracer = false;
+ beam.is_explosion = true;
+ beam.beam_source = monster_index(monster);
+ beam.type = dchar_glyph(DCHAR_FIRED_BURST);
+ beam.pos = monster->pos();
+ beam.source = monster->pos();
+ beam.target = monster->pos();
+ beam.thrower = killer;
+ beam.aux_source.clear();
+
+ if (YOU_KILL(killer))
+ beam.aux_source = "set off by themselves";
+ else if (pet_kill)
+ beam.aux_source = "set off by their pet";
+
+ const char* msg = NULL;
+ const char* sanct_msg = NULL;
+ if (type == MONS_GIANT_SPORE)
+ {
+ beam.flavour = BEAM_SPORE;
+ beam.name = "explosion of spores";
+ beam.colour = LIGHTGREY;
+ beam.damage = dice_def( 3, 15 );
+ beam.ex_size = 2;
+ msg = "The giant spore explodes!";
+ sanct_msg = "By Zin's power, the giant spore's explosion is contained.";
+ }
+ else if (type == MONS_BALL_LIGHTNING)
+ {
+ beam.flavour = BEAM_ELECTRICITY;
+ beam.name = "blast of lightning";
+ beam.colour = LIGHTCYAN;
+ beam.damage = dice_def( 3, 20 );
+ beam.ex_size = coinflip() ? 3 : 2;
+ msg = "The ball lightning explodes!";
+ sanct_msg = "By Zin's power, the ball lightning's explosion "
+ "is contained.";
+ }
+ else
+ {
+ msg::streams(MSGCH_DIAGNOSTICS) << "Unknown spore type: "
+ << static_cast<int>(type)
+ << std::endl;
+ return;
+ }
+
+ if (you.can_see(monster))
+ {
+ viewwindow(true, false);
+ if (is_sanctuary(monster->pos()))
+ mpr(sanct_msg, MSGCH_GOD);
+ else
+ mpr(msg);
+ }
+
+ if (is_sanctuary(monster->pos()))
+ return;
+
+ // Detach monster from the grid first, so it doesn't get hit by
+ // its own explosion. (GDL)
+ mgrd(monster->pos()) = NON_MONSTER;
+ explosion(beam, false, false, true, true, mons_near(monster));
+ mgrd(monster->pos()) = monster_index(monster);
+}
+
void monster_die(monsters *monster, killer_type killer,
int killer_index, bool silent, bool wizard)
{
@@ -879,20 +959,20 @@ void monster_die(monsters *monster, killer_type killer,
if (monster->type == MONS_GIANT_SPORE
|| monster->type == MONS_BALL_LIGHTNING)
{
- if (monster->hit_points < 1 && monster->hit_points > -15)
- return;
+ _spore_goes_pop(monster, killer, killer_index, pet_kill, wizard);
}
else if (monster->type == MONS_FIRE_VORTEX
|| monster->type == MONS_SPATIAL_VORTEX)
{
- if (!silent)
+ if (!silent && killer != KILL_RESET)
{
simple_monster_message( monster, " dissipates!",
MSGCH_MONSTER_DAMAGE, MDAM_DEAD );
silent = true;
}
- if (monster->type == MONS_FIRE_VORTEX)
+ if (monster->type == MONS_FIRE_VORTEX && !wizard
+ && killer != KILL_RESET)
{
place_cloud(CLOUD_FIRE, monster->pos(), 2 + random2(4),
monster->kill_alignment());
@@ -904,15 +984,16 @@ void monster_die(monsters *monster, killer_type killer,
else if (monster->type == MONS_SIMULACRUM_SMALL
|| monster->type == MONS_SIMULACRUM_LARGE)
{
- if (!silent)
+ if (!silent && killer != KILL_RESET)
{
simple_monster_message( monster, " vapourises!",
MSGCH_MONSTER_DAMAGE, MDAM_DEAD );
silent = true;
}
- place_cloud(CLOUD_COLD, monster->pos(), 2 + random2(4),
- monster->kill_alignment());
+ if (!wizard && killer != KILL_RESET)
+ place_cloud(CLOUD_COLD, monster->pos(), 2 + random2(4),
+ monster->kill_alignment());
if (killer == KILL_RESET)
killer = KILL_DISMISSED;
@@ -5860,7 +5941,7 @@ static void _swim_or_move_energy(monsters *mon)
#if DEBUG
# define DEBUG_ENERGY_USE(problem) \
- if (monster->speed_increment == old_energy) \
+ if (monster->speed_increment == old_energy && monster->alive()) \
mprf(MSGCH_DIAGNOSTICS, \
problem " for monster '%s' consumed no energy", \
monster->name(DESC_PLAIN).c_str(), true);
@@ -6282,19 +6363,6 @@ static void _handle_monster_move(int i, monsters *monster)
DEBUG_ENERGY_USE("monster_attack()");
}
- if ((monster->type == MONS_GIANT_SPORE
- || monster->type == MONS_BALL_LIGHTNING)
- && monster->hit_points < 1)
- {
- // Detach monster from the grid first, so it
- // doesn't get hit by its own explosion. (GDL)
- mgrd(monster->pos()) = NON_MONSTER;
-
- spore_goes_pop(monster);
- monster_cleanup(monster);
- continue;
- }
-
if (attacked)
{
mmov.reset();
@@ -6324,21 +6392,7 @@ static void _handle_monster_move(int i, monsters *monster)
}
if (monster->type != -1 && monster->hit_points < 1)
- {
- if (monster->type == MONS_GIANT_SPORE
- || monster->type == MONS_BALL_LIGHTNING)
- {
- // Detach monster from the grid first, so it
- // doesn't get hit by its own explosion. (GDL)
- mgrd(monster->pos()) = NON_MONSTER;
-
- spore_goes_pop(monster);
- monster_cleanup(monster);
- return;
- }
- else
monster_die(monster, KILL_MISC, NON_MONSTER);
- }
}
//---------------------------------------------------------------