git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7900 c06c8d41-db1a-0410-9941-cceddc491573
RDOOG5LBE5TCTFYCKJIB7TGGTRFX4HBLMJZYXS5TCFWNCU3QII5QC
5WHLQTLOJRJ67M4KAJZURHMNQLYHBW4XHQFBXV2LUQ4W6YKTOXVAC
LS2AILMM7THCB7OHESW7BGJMNZZXFHYOYVZBZH6OCFNETNLDEP5QC
TO3JMTZO6ETZWBXPA75JLCFD7ML546WXBRLWHPKL44ZIQ2H5HW6QC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
ERS7DYNAVCC7QUVG5FXJJRONYESLZU22CQGKCA5HLLLG6DMXYRLQC
BQ5QKUWLCYSBO4A7EWZN4FXPNSIAR6JPBAZE4PSV6XCUNTV53ERQC
5MGUZD2UACJCSG74TEZHI3Z4YL5KL6ZVUCQ3XVZKDOLKM7EMGWJAC
5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC
HCVH2CWL32UD66O6Z7ZYDUASWN3RF5TW6FSWURGMD7MELKB772FAC
6YMXFO4BZAMBWHSVWS2FTO2D7EGABBK4NPCSCAN4ELFHEYTWGXVAC
ENI6P5WUO7DS4Y7EUDCYB4PSNT7CXH2L5JIB5BLZHNMWN4QDXMWQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC
3PY3L3A4QRW3Z5Y7SHO4TMVOOP2VNCO27X2MX4DTOP2SADLBQUOAC
NMZFCCM6O3KO2GJWKOSULN27B3QIZKWPBOB62PAILXMRQD4JMIMAC
IQGGFC563RBS7GDOACKCLXK752EE5RC3T6G5L6H446SXTMSA7T2AC
JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC
}
static bool _feat_is_deadly(dungeon_feature_type feat)
{
if (you.airborne())
return (false);
return (feat == DNGN_LAVA || feat == DNGN_DEEP_WATER && !you.can_swim());
}
static bool _player_is_dead()
{
return (you.hp <= 0 || you.strength <= 0 || you.dex <= 0 || you.intel <= 0
|| _feat_is_deadly(grd(you.pos()))
|| you.did_escape_death());
// Don't accidentally kill the player when doing a good
// act.
you.hp = std::max(1, you.hp);
// Don't accidentally kill the player when doing a good act.
if (you.escaped_death_cause == KILLED_BY_WILD_MAGIC
&& you.escaped_death_aux == "Xom's lightning strike")
{
you.hp = 1;
you.reset_escaped_death();
}
static char* _stat_ptrs[3] = {&you.strength, &you.intel, &you.dex};
static void _handle_accidental_death(const int orig_hp,
const char orig_stats[],
const FixedVector<unsigned char, NUM_MUTATIONS> &orig_mutation)
{
// Did ouch() return early because the player died from the Xom effect
// even though neither is the player under penance nor is Xom bored?
if (!you.did_escape_death()
&& you.escaped_death_aux.empty()
&& !_player_is_dead())
{
// Player is fine.
return;
}
std::string speech_type = "accidental homicide";
const dungeon_feature_type feat = grd(you.pos());
switch(you.escaped_death_cause)
{
case NUM_KILLBY:
case KILLED_BY_LEAVING:
case KILLED_BY_WINNING:
case KILLED_BY_QUITTING:
speech_type = "weird death";
break;
case KILLED_BY_LAVA:
case KILLED_BY_WATER:
if (!_feat_is_deadly(feat))
speech_type = "weird death";
break;
case KILLED_BY_STUPIDITY:
if (you.intel > 0)
speech_type = "weird death";
break;
case KILLED_BY_WEAKNESS:
if (you.strength > 0)
speech_type = "weird death";
break;
case KILLED_BY_CLUMSINESS:
if (you.dex > 0)
speech_type = "weird death";
break;
default:
if (_feat_is_deadly(feat))
speech_type = "weird death";
if (you.strength <= 0 || you.intel <= 0 || you.dex <= 0)
speech_type = "weird death";
break;
}
mpr("You die...");
god_speaks(GOD_XOM, _get_xom_speech(speech_type).c_str());
god_speaks(GOD_XOM, _get_xom_speech("resurrection").c_str());
if (you.hp <= 0)
you.hp = std::min(orig_hp, you.hp_max);
mutation_type dex_muts[5] = {MUT_GREY2_SCALES, MUT_METALLIC_SCALES,
MUT_YELLOW_SCALES, MUT_RED2_SCALES,
MUT_STRONG_STIFF};
for (int i = 0; i < 5; ++i)
{
mutation_type bad = dex_muts[i];
while (you.dex <= 0 && you.mutation[bad] > orig_mutation[bad])
delete_mutation(bad, true, true);
}
while(you.dex <= 0
&& you.mutation[MUT_FLEXIBLE_WEAK] <
orig_mutation[MUT_FLEXIBLE_WEAK])
{
mutate(MUT_FLEXIBLE_WEAK, true, true, true);
}
while (you.strength <= 0
&& you.mutation[MUT_FLEXIBLE_WEAK] >
orig_mutation[MUT_FLEXIBLE_WEAK])
{
delete_mutation(MUT_FLEXIBLE_WEAK, true, true);
}
while (you.strength <= 0
&& you.mutation[MUT_STRONG_STIFF] <
orig_mutation[MUT_STRONG_STIFF])
{
mutate(MUT_STRONG_STIFF, true, true, true);
}
mutation_type bad_muts[3] = { MUT_WEAK, MUT_DOPEY, MUT_CLUMSY };
mutation_type good_muts[3] = { MUT_STRONG, MUT_CLEVER, MUT_AGILE };
for (int i = 0; i < 3; ++i)
{
while (*(_stat_ptrs[i]) <= 0)
{
mutation_type good = good_muts[i];
mutation_type bad = bad_muts[i];
if (you.mutation[bad] > orig_mutation[bad]
|| you.mutation[good] < orig_mutation[good])
{
mutate(good, true, true, true);
}
else
{
*(_stat_ptrs[i]) = orig_stats[i];
break;
}
}
}
you.max_strength = std::max(you.max_strength, you.strength);
you.max_intel = std::max(you.max_intel, you.intel);
you.max_dex = std::max(you.max_dex, you.dex);
if (_feat_is_deadly(feat))
you.teleport(true);
}
#ifdef WIZARD
if (_player_is_dead())
{
// Should only happen if the player used wizard mode to escape from
// death via stat loss, or used wizard mode to escape death from
// deep water or lava.
ASSERT(you.wizard && !you.did_escape_death());
if (_feat_is_deadly(grd(you.pos())))
mpr("Player is standing in deadly terrain, skipping Xom act.",
MSGCH_DIAGNOSTICS);
else
mpr("Player is already dead, skipping Xom act.",
MSGCH_DIAGNOSTICS);
return;
}
#else
ASSERT(!_player_is_dead());
#endif
}
bool already_oopsed = false;
if (you.hp <= 0 || you.strength <= 0 || you.dex <= 0 || you.intel <= 0)
{
// ouch() returned early because the player died from the Xom effect
// even though neither is the player under penance nor is Xom bored.
mpr("You die...");
god_speaks(GOD_XOM, _get_xom_speech("accidental homicide").c_str());
god_speaks(GOD_XOM, _get_xom_speech("resurrection").c_str());
already_oopsed = true;
if (you.hp <= 0)
you.hp = orig_hp;
mutation_type dex_muts[5] = {MUT_GREY2_SCALES, MUT_METALLIC_SCALES,
MUT_YELLOW_SCALES, MUT_RED2_SCALES,
MUT_STRONG_STIFF};
for (int i = 0; i < 5; ++i)
{
mutation_type bad = dex_muts[i];
while (you.dex <= 0 && you.mutation[bad] > orig_mutation[bad])
delete_mutation(bad, true, true);
}
while(you.dex <= 0
&& you.mutation[MUT_FLEXIBLE_WEAK] <
orig_mutation[MUT_FLEXIBLE_WEAK])
{
mutate(MUT_FLEXIBLE_WEAK, true, true, true);
}
while (you.strength <= 0
&& you.mutation[MUT_FLEXIBLE_WEAK] >
orig_mutation[MUT_FLEXIBLE_WEAK])
{
delete_mutation(MUT_FLEXIBLE_WEAK, true, true);
}
while (you.strength <= 0
&& you.mutation[MUT_STRONG_STIFF] <
orig_mutation[MUT_STRONG_STIFF])
{
mutate(MUT_STRONG_STIFF, true, true, true);
}
mutation_type bad_muts[3] = { MUT_WEAK, MUT_DOPEY, MUT_CLUMSY };
mutation_type good_muts[3] = { MUT_STRONG, MUT_CLEVER, MUT_AGILE };
for (int i = 0; i < 3; ++i)
{
while (*(stat_ptrs[i]) <= 0)
{
mutation_type good = good_muts[i];
mutation_type bad = bad_muts[i];
if (you.mutation[bad] > orig_mutation[bad]
|| you.mutation[good] < orig_mutation[good])
{
mutate(good, true, true, true);
}
else
{
*(stat_ptrs[i]) = orig_stats[i];
break;
}
}
}
you.max_strength = std::max(you.max_strength, you.strength);
you.max_intel = std::max(you.max_intel, you.intel);
you.max_dex = std::max(you.max_dex, you.dex);
// Or maybe Xom accidentally tossed you in deep water or lava.
dungeon_feature_type feat = grd(you.pos());
if (feat != orig_feat && !you.airborne()
&& (feat == DNGN_DEEP_WATER && !you.swimming()
|| feat == DNGN_LAVA && player_res_fire() <= 0))
{
if (!already_oopsed)
{
mpr("You die...");
god_speaks(GOD_XOM,
_get_xom_speech("accidental homicide").c_str());
god_speaks(GOD_XOM, _get_xom_speech("resurrection").c_str());
}
void player::reset_escaped_death()
{
escaped_death_cause = NUM_KILLBY;
escaped_death_aux = "";
}