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
BYURAML2EPTULHH22Q5RPXYGDEYAJYESR6C72UMNPPYHTCJZUPFAC
H7Z2K4SMEWSGLXGTI5D3RDDRSK45VD5XU6MMUZ2KWYTMHL2CJTVQC
RWCCZ64BG3HSOTM54ANIGENC3F3AIR42LJFRYSAKMCPCIUSOZY5QC
K7J2IGELTIQL5KAMBV62MFVIVMEZEWCOLZ7GHFXHYPANYIF7BRZAC
3DQXSE4YGFBBDUWK4YEOFWW4UPWILWELFSLP37SL6BERGAZJC5YAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
DKRSOHZXL6EPSLKOKHF7GJXSZEJVY7CXGACSHWLM5B5FTRETWWCAC
W74555HMPXUQ72AGKBXC5P3STMMX5DZAW6ZESUDLNVJBCAG43PLAC
HAM54HXIO2245W6REO4RZDY2QMIH476AWWJSMYAMSYYNEBBJSHWAC
5DMO2DEV7IK3MJG274EUNZBGQ7EBZWC2WTSKAEGPDMILX7BXYG3AC
7RE7J5DEMEO52RKOE77JMEXKZ7ORJJMCRGKLC6NHYDJW66UKYE4AC
Y2NYY7HWFZ2LQDK3ACSLGS37F2J2IJ5LRGCIMZYXLEOSVPD3A4DAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC
3KRKUK3HCBBZWS5MXFAMM4R5PGWWTSURBSFXEEZPRRCFAZ5EZTCAC
XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC
WKX3GD3EAZUV5PV5EXVB7CFYJOGMIOM3LPPPUAW3HTS2EFPF2EPAC
TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC
YCL3W2PFE6ILTGBFODCSXNPDIA46KVSZP2TI7HDMYAOEJT65RIEAC
NNG27Y5ZQAZX6UD7F7M4F6KEZBEDFXPEEC3LFUSX4ESKT7K6UJQAC
F5APHUYFFFBUYWCU3OPCE5535X5FNUHMPZQ2H4M5J2RPIJIXTNRQC
J4FEX23HNK5K75KWIVDILPIWY33F23W66CT4P5BFVZQVZMLZ42WQC
B62ICMDTN5V7R7RBL4JALFVKEMVOOVLRSJASRNYS6CGFWBEEF5JQC
P5KSBMFHDCAFUGHSOCLDG7J7XKCGJBCSDICYOMOYCEBBBXM55CEAC
OSGS3PH2L5CBTDVZCZS6OCFQNA4A7RMEXBYJQB7DDZBYYJW7QSSAC
4UXFU3FZOCBSLDQ4S7MJKAE2H7VUHCNRDQMIY6NJ3PHYXWNGISDQC
ZGUJWUFJ4NFFJ6PGXLFGQWCWBCZHPWGWI44NJHJEVPRG5L36PADQC
UIRWVLX5LDNWURTZOG7EFLXE5OOEL4XBPSLSUHUQSKHC4A7WCVLQC
EYMNSHCYA5455YMSGDF4MCOJKYRTFHXMEPFYYXBR6CPXHOMAQB3AC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
TK4J7NP55IDXTPPEGGB5MMQJCJI34MJ4P6QGFXA3G3P6M3OCOHWQC
RISMOCQM6BKK4XSIRKYLOBB2UPDYJNDAL6OGIIR5GGNZQAK5YSZAC
ZKBPM2G7BTRIXQMFPWFIQY5U7CV2GEXSOBCGFN6UBE27IBIJAMRAC
GVW4OBPGXY2Q75HB7QHADZIOHKL22FI2BSJ2TM4K5SBJENBFTQKAC
// 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));
}
}
}
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);
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 ((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;
{
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
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)
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;
}
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())
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());