summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-14 13:34:33 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-14 13:34:33 +0000
commit3d3d03f771d2161b20986726a05d680c5771c8f1 (patch)
tree503d9b7470f88be08f395a92397736cf33e54519
parent4bd5cef214da1bb0553ef69e9b6d09ea37bf31bd (diff)
downloadcrawl-ref-3d3d03f771d2161b20986726a05d680c5771c8f1.tar.gz
crawl-ref-3d3d03f771d2161b20986726a05d680c5771c8f1.zip
Partial implementation of FR #2011386: Xom shouldn't directly kill the player
unless he's being nasty (the player is under penance from Xom or Xom is bored). I've put checks into _xom_is_good() and _xom_is_bad() to avoid this as much as possible, and as a safety-net changed ouch() to return early if the player dies from a Xom effect when Xom wasn't being nasty so that xom_acts() can then fix things up (this causes Xom to give a message from "Xom accidental homicide" in dat/database/godspeak.txt) Next up will be an addition to mutate() so you can request random mutations be non-lethal, which should take care of all known situations where ouch() returns early due to Xom making a mistake. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7833 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/dat/database/godspeak.txt5
-rw-r--r--crawl-ref/source/ouch.cc16
-rw-r--r--crawl-ref/source/xom.cc108
3 files changed, 120 insertions, 9 deletions
diff --git a/crawl-ref/source/dat/database/godspeak.txt b/crawl-ref/source/dat/database/godspeak.txt
index 5caaeedf97..8c029bfaee 100644
--- a/crawl-ref/source/dat/database/godspeak.txt
+++ b/crawl-ref/source/dat/database/godspeak.txt
@@ -348,6 +348,11 @@ Xom's power brushes against you for a moment.
You hear Xom's avuncular chuckle.
%%%%
+Xom accidental homicide
+
+"Oops, I didn't mean to do *that*!"
+Xom brings you back to life.
+%%%%
############################################
# Beogh rants on destroying an orcish idol #
############################################
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index 50b2dbb25f..be12b7db79 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -896,6 +896,22 @@ void ouch(int dam, int death_source, kill_method_type death_type,
} // else hp <= 0
}
+ if (crawl_state.is_god_acting()
+ && crawl_state.which_god_acting() == GOD_XOM
+ && crawl_state.other_gods_acting().size() == 0)
+ {
+ if (aux == NULL || strstr(aux, "Xom") == NULL)
+ death_type = KILLED_BY_XOM;
+
+ // Xom should only cause death if the player is under penance or
+ // Xom is bored.
+ if (!you.penance[GOD_XOM]
+ && !(you.religion == GOD_XOM && you.gift_timeout == 0))
+ {
+ return;
+ }
+ }
+
// Construct scorefile entry.
scorefile_entry se(dam, death_source, death_type, aux);
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index 3202272274..834aef0fec 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -711,6 +711,10 @@ static bool _xom_is_good(int sever)
{
bool done = false;
+ // Did Xom (already) kill the player?
+ if (you.hp <= 0)
+ return (true);
+
god_acting gdact(GOD_XOM);
// This series of random calls produces a poisson-looking
@@ -1047,6 +1051,9 @@ static bool _xom_is_good(int sever)
{
if (you.hp <= random2(201))
you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] = 1;
+ else
+ // Make sure we don't directly kill the player.
+ you.hp += 90;
god_speaks(GOD_XOM, "The area is suffused with divine lightning!");
@@ -1070,6 +1077,11 @@ static bool _xom_is_good(int sever)
mpr("Your divine protection wanes.");
you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] = 0;
}
+ else
+ {
+ you.hp -= 90;
+ you.hp = std::max(1, you.hp);
+ }
done = true;
}
@@ -1082,10 +1094,19 @@ static bool _xom_is_bad(int sever)
{
bool done = false;
+ // Xom will only directly kill you with a bad effect if you're under
+ // penance from him or he's bored.
+ const bool nasty = you.penance[GOD_XOM]
+ || (you.religion == GOD_XOM && you.gift_timeout == 0);
+
god_acting gdact(GOD_XOM);
while (!done)
{
+ // Did Xom kill the player?
+ if (you.hp <= 0)
+ return (true);
+
if (x_chance_in_y(3, sever))
{
god_speaks(GOD_XOM, _get_xom_speech("zero miscast effect").c_str());
@@ -1095,7 +1116,7 @@ static bool _xom_is_bad(int sever)
done = true;
}
- else if (x_chance_in_y(4, sever))
+ else if (x_chance_in_y(4, sever) && (nasty || you.hp > 12))
{
god_speaks(GOD_XOM, _get_xom_speech("minor miscast effect").c_str());
@@ -1106,14 +1127,41 @@ static bool _xom_is_bad(int sever)
}
else if (x_chance_in_y(5, sever))
{
- god_speaks(GOD_XOM, _get_xom_speech("lose stats").c_str());
+ stat_type stat = STAT_RANDOM;
+ int max = 3;
+
+ // Don't kill the player unless Xom is being nasty.
+ if (!nasty)
+ {
+ // Make sure not to lower strength so much that the player
+ // will die once might wears off.
+ char vals[3] =
+ {you.strength - (you.duration[DUR_MIGHT] ? 5 : 0),
+ you.dex, you.intel};
+ stat_type types[3] = {STAT_STRENGTH, STAT_DEXTERITY,
+ STAT_INTELLIGENCE};
+
+ int count = 0;
+ for (int i = 0; i < 3; i++)
+ {
+ int val = vals[i];
+
+ if (val > 1 && one_chance_in(++count))
+ {
+ stat = types[i];
+ max = val - 1;
+ }
+ }
+ if (count == 0)
+ continue;
+ }
- lose_stat(STAT_RANDOM, 1 + random2(3), true,
- "the capriciousness of Xom" );
+ god_speaks(GOD_XOM, _get_xom_speech("lose stats").c_str());
+ lose_stat(stat, 1 + random2(max), true, "the vengeance of Xom" );
done = true;
}
- else if (x_chance_in_y(6, sever))
+ else if (x_chance_in_y(6, sever) && (nasty || you.hp > 25))
{
god_speaks(GOD_XOM, _get_xom_speech("medium miscast effect").c_str());
@@ -1243,14 +1291,14 @@ static bool _xom_is_bad(int sever)
if (one_chance_in(4))
{
- if (player_prot_life() < 3)
+ if (player_prot_life() < 3 && (nasty || you.experience > 0))
{
god_speaks(GOD_XOM, speech.c_str());
drain_exp();
- if (random2(sever) > 3)
+ if (random2(sever) > 3 && (nasty || you.experience > 0))
drain_exp();
- if (random2(sever) > 3)
+ if (random2(sever) > 3 && (nasty || you.experience > 0))
drain_exp();
done = true;
@@ -1309,7 +1357,7 @@ static bool _xom_is_bad(int sever)
}
}
}
- else if (x_chance_in_y(14, sever))
+ else if (x_chance_in_y(14, sever) && (nasty || you.hp > 30))
{
god_speaks(GOD_XOM, _get_xom_speech("major miscast effect").c_str());
@@ -1364,6 +1412,13 @@ void xom_acts(bool niceness, int sever)
}
}
+ int orig_hp = you.hp;
+ int orig_str = you.strength;
+ int orig_dex = you.dex;
+ int orig_int = you.intel;
+
+ FixedVector<unsigned char, NUM_MUTATIONS> orig_mutation = you.mutation;
+
if (niceness && !one_chance_in(5))
{
// Good stuff.
@@ -1377,6 +1432,41 @@ void xom_acts(bool niceness, int sever)
;
}
+ 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());
+
+ int changes = 0;
+ for (int i = 0; i < NUM_MUTATIONS; i++)
+ {
+ if (orig_mutation[i] != you.mutation[i])
+ changes++;
+ }
+
+ if (changes > 0)
+ {
+ std::string str = "Xom undoes your latest mutation";
+ if (changes > 1)
+ str += "s";
+ str += ".";
+ god_speaks(GOD_XOM, str.c_str());
+ }
+
+ you.mutation = orig_mutation;
+
+ you.hp = orig_hp;
+ you.strength = orig_str;
+ you.dex = orig_dex;
+ you.intel = orig_int;
+
+ 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);
+ }
+
// Drawing the Xom card from Nemelex's decks of oddities or punishment.
if (crawl_state.is_god_acting()
&& crawl_state.which_god_acting() != GOD_XOM)