summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-27 13:29:07 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-27 13:29:07 +0000
commit62ba7977a2d7085a7ee0232fa317293c878f9365 (patch)
tree172223027970cb8d574af7947e8b6eaa63c493da /crawl-ref
parent0566854703cbf6aef6623f44fde4bd5becb16854 (diff)
downloadcrawl-ref-62ba7977a2d7085a7ee0232fa317293c878f9365.tar.gz
crawl-ref-62ba7977a2d7085a7ee0232fa317293c878f9365.zip
Giant spores and lightning balls exploding is now handled immediately inside
of monster_die(), removing the need to ever check for "monster is dead but still present because it's about to explode". It also lets you get the credit (and blame) for any monsters the explosion hits if you attacking it triggered the explosion. While I was at it I made the death-cause display show if death from spore/ball explosion was due to an explosion triggered by the player or one of the player's pets. Also made it so that when similacrums and fire vortices are banished or wizard-command-genocided that they don't leave behind a freezing/burning cloud. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7653 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/beam.cc24
-rw-r--r--crawl-ref/source/hiscores.cc37
-rw-r--r--crawl-ref/source/monstuff.cc124
-rw-r--r--crawl-ref/source/mstuff2.cc63
-rw-r--r--crawl-ref/source/mstuff2.h1
-rw-r--r--crawl-ref/source/spl-cast.cc5
6 files changed, 138 insertions, 116 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 04720fe360..cd600a3ba6 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -3219,18 +3219,26 @@ static void _affect_place_explosion_clouds(bolt &beam, const coord_def& p)
// A little helper function to handle the calling of ouch()...
static void _beam_ouch(int dam, bolt &beam)
{
+ monsters *monst = NULL;
+ if (!invalid_monster_index(beam.beam_source)
+ && menv[beam.beam_source].type != -1)
+ {
+ monst = &menv[beam.beam_source];
+ }
+
// The order of this is important.
- if (YOU_KILL(beam.thrower) && beam.aux_source.empty())
+ if (monst && (monst->type == MONS_GIANT_SPORE
+ || monst->type == MONS_BALL_LIGHTNING))
+ {
+ ouch(dam, beam.beam_source, KILLED_BY_SPORE,
+ beam.aux_source.c_str());
+ }
+ else if (YOU_KILL(beam.thrower) && beam.aux_source.empty())
ouch(dam, NON_MONSTER, KILLED_BY_TARGETTING);
else if (MON_KILL(beam.thrower))
{
- if (beam.flavour == BEAM_SPORE)
- ouch(dam, beam.beam_source, KILLED_BY_SPORE);
- else
- {
- ouch(dam, beam.beam_source, KILLED_BY_BEAM,
- beam.aux_source.c_str());
- }
+ ouch(dam, beam.beam_source, KILLED_BY_BEAM,
+ beam.aux_source.c_str());
}
else // KILL_MISC || (YOU_KILL && aux_source)
{
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index d3d194d554..548e9c1532 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -762,8 +762,10 @@ void scorefile_entry::init_death_cause(int dam, int dsrc,
auxkilldata = aux;
// for death by monster
- if ((death_type == KILLED_BY_MONSTER || death_type == KILLED_BY_BEAM)
- && !invalid_monster_index(death_source))
+ if ((death_type == KILLED_BY_MONSTER || death_type == KILLED_BY_BEAM
+ || death_type == KILLED_BY_SPORE)
+ && !invalid_monster_index(death_source)
+ && menv[death_source].type != -1)
{
const monsters *monster = &menv[death_source];
@@ -806,10 +808,13 @@ void scorefile_entry::init_death_cause(int dam, int dsrc,
const bool death = you.hp <= 0;
- death_source_name = monster->name(DESC_NOCAP_A, death);
+ const description_level_type desc =
+ death_type == KILLED_BY_SPORE ? DESC_PLAIN : DESC_NOCAP_A;
+
+ death_source_name = monster->name(desc, death);
if (monster->has_base_name())
death_source_name +=
- ", " + monster->base_name(DESC_NOCAP_A, death);
+ ", " + monster->base_name(desc, death);
if (monster->has_ench(ENCH_SHAPESHIFTER))
death_source_name += " (shapeshifter)";
@@ -1636,7 +1641,21 @@ std::string scorefile_entry::death_description(death_desc_verbosity verbosity)
break;
case KILLED_BY_SPORE:
- desc += terse? "spore" : "Killed by an exploding spore";
+ if (terse)
+ {
+ if (death_source_name.empty())
+ desc += "spore";
+ else
+ desc += get_monster_data(death_source)->name;
+ }
+ else
+ {
+ desc += "Killed by an exploding ";
+ if (death_source_name.empty())
+ desc += "spore";
+ else
+ desc += death_source_name;
+ }
needs_damage = true;
break;
@@ -1851,6 +1870,14 @@ std::string scorefile_entry::death_description(death_desc_verbosity verbosity)
}
}
+ if (death_type == KILLED_BY_SPORE && !terse && !auxkilldata.empty())
+ {
+ desc += "... ";
+ desc += auxkilldata;
+ desc += "\n";
+ desc += " ";
+ }
+
if (terse)
{
trim_string(desc);
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);
- }
}
//---------------------------------------------------------------
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 640c2d24e0..18da736352 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -1237,69 +1237,6 @@ bool mons_thrown_object_destroyed( item_def *item, const coord_def& where,
return destroyed;
}
-// XXX: Should really do something about mons_hit, but can't be bothered.
-void spore_goes_pop(monsters *monster)
-{
- bolt beam;
- const int type = monster->type;
-
- if (monster == NULL)
- return;
-
- beam.is_tracer = false;
- beam.is_explosion = true;
- beam.beam_source = monster_index(monster);
- beam.type = dchar_glyph(DCHAR_FIRED_BURST);
- beam.target = monster->pos();
- beam.thrower = KILL_MON; // someone else's explosion
- beam.aux_source.clear();
-
- 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;
-
- explosion(beam, false, false, true, true, mons_near(monster));
-}
-
bolt mons_spells( monsters *mons, spell_type spell_cast, int power )
{
ASSERT(power > 0);
diff --git a/crawl-ref/source/mstuff2.h b/crawl-ref/source/mstuff2.h
index 1a3b722953..d0f9a32744 100644
--- a/crawl-ref/source/mstuff2.h
+++ b/crawl-ref/source/mstuff2.h
@@ -30,7 +30,6 @@ bool monster_random_space(const monsters *monster, coord_def& target,
bool monster_random_space(monster_type mon, coord_def& target,
bool forbid_sanctuary = false);
void monster_teleport(monsters *monster, bool instan, bool silent = false);
-void spore_goes_pop(monsters *monster);
bool orc_battle_cry(monsters *chief);
bool orange_statue_effects(monsters *mons);
bool silver_statue_effects(monsters *mons);
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 11556d5570..b16e8b3cd1 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -2234,10 +2234,7 @@ void MiscastEffect::init()
|| pow == -1 && fail == -1 && level >= 0 && level <= 3);
ASSERT(target != NULL);
- // A dead but not-yet-exploded giant spore or ball lightning *might*
- // be the target of a miscast effect.
- ASSERT(target->alive() || target->id() == MONS_GIANT_SPORE
- || target->id() == MONS_BALL_LIGHTNING);
+ ASSERT(target->alive());
source_known = target_known = false;