summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohanna Ploog <j-p-e-g@users.sourceforge.net>2009-12-09 21:31:02 +0100
committerJohanna Ploog <j-p-e-g@users.sourceforge.net>2009-12-09 21:31:02 +0100
commitb8f3c183df87ee55833ab561fa12ed324da5a913 (patch)
tree2be4120a6fc0053dc049ba066e68b1ebfe701a01
parentf4efe0a7c1422dede865ea5f9d8e2d96978b2f9f (diff)
downloadcrawl-ref-b8f3c183df87ee55833ab561fa12ed324da5a913.tar.gz
crawl-ref-b8f3c183df87ee55833ab561fa12ed324da5a913.zip
Make Xom sometimes (< 5% chance) revive the player after death.
The chance of this happening depends strongly on tension and mood, as well as type of death. I also tried the normal protection from harm but I figure it's more interesting this way. :D
-rw-r--r--crawl-ref/source/dat/database/godspeak.txt27
-rw-r--r--crawl-ref/source/hiscores.cc2
-rw-r--r--crawl-ref/source/notes.cc4
-rw-r--r--crawl-ref/source/notes.h1
-rw-r--r--crawl-ref/source/ouch.cc8
-rw-r--r--crawl-ref/source/xom.cc119
-rw-r--r--crawl-ref/source/xom.h4
7 files changed, 163 insertions, 2 deletions
diff --git a/crawl-ref/source/dat/database/godspeak.txt b/crawl-ref/source/dat/database/godspeak.txt
index c5045dda27..29b8d734a3 100644
--- a/crawl-ref/source/dat/database/godspeak.txt
+++ b/crawl-ref/source/dat/database/godspeak.txt
@@ -419,6 +419,31 @@ Xom pokes at a nearby @staircase@.
Xom alters the dungeon around you.
%%%%
+Xom life saving general
+
+"What? Wait, NO!"
+
+"Hey, things were just getting interesting!"
+
+"NOOOOOOO, not my @xom_plaything@!"
+
+"Not here, not now."
+
+Xom is feeling generous.
+%%%%
+Xom life saving actor
+
+w:20
+@Xom life saving general@
+
+"Hey, that's my @xom_plaything@!"
+
+"Oh no, you don't!"
+
+"That's my @xom_plaything@, go get your own one!"
+
+"Leave my @xom_plaything@ alone!"
+%%%%
Xom boring death
Xom yawns loudly!
@@ -429,7 +454,7 @@ Xom yawns loudly!
"I guess I need a new plaything now."
-"Hmm? Did I miss something?"
+"Huh? Did I miss anything?"
%%%%
# Xom laughing
# (Currently only used post-game in response to "You die...")
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index 24ca1a90cb..80da72274b 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -1194,7 +1194,9 @@ std::string scorefile_entry::death_source_desc() const
{
if (death_type != KILLED_BY_MONSTER && death_type != KILLED_BY_BEAM
&& death_type != KILLED_BY_DISINT)
+ {
return ("");
+ }
// XXX no longer handles mons_num correctly! FIXME
return (!death_source_name.empty() ?
diff --git a/crawl-ref/source/notes.cc b/crawl-ref/source/notes.cc
index dd3db2b2c8..86808ab553 100644
--- a/crawl-ref/source/notes.cc
+++ b/crawl-ref/source/notes.cc
@@ -123,6 +123,7 @@ static bool _is_noteworthy( const Note& note )
|| note.type == NOTE_PENANCE
|| note.type == NOTE_MOLLIFY_GOD
|| note.type == NOTE_DEATH
+ || note.type == NOTE_XOM_REVIVAL
|| note.type == NOTE_SEEN_FEAT)
{
return (true);
@@ -270,6 +271,9 @@ std::string Note::describe( bool when, bool where, bool what ) const
result << "HP: " << first << "/" << second
<< " [" << name << "]";
break;
+ case NOTE_XOM_REVIVAL:
+ result << "Xom revived you";
+ break;
case NOTE_MP_CHANGE:
result << "Mana: " << first << "/" << second;
break;
diff --git a/crawl-ref/source/notes.h b/crawl-ref/source/notes.h
index 4ba28748ae..36fd2af55e 100644
--- a/crawl-ref/source/notes.h
+++ b/crawl-ref/source/notes.h
@@ -46,6 +46,7 @@ enum NOTE_TYPES
NOTE_DONATE_MONEY, /* needs: amount of gold */
NOTE_SEEN_FEAT, /* needs: feature seen (string) */
NOTE_XOM_EFFECT, /* needs: description (name string) */
+ NOTE_XOM_REVIVAL, /* needs: death cause (string) */
NOTE_NUM_TYPES
};
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index 432cc7b440..93eaacd48b 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -1130,7 +1130,7 @@ void ouch(int dam, int death_source, kill_method_type death_type,
// Okay, you *didn't* escape death.
you.reset_escaped_death();
- // Ensure some minimal information about Xom's involvment.
+ // Ensure some minimal information about Xom's involvement.
if (aux == NULL || strlen(aux) == 0)
{
if (death_type != KILLED_BY_XOM)
@@ -1139,6 +1139,12 @@ void ouch(int dam, int death_source, kill_method_type death_type,
else if (strstr(aux, "Xom") == NULL)
death_type = KILLED_BY_XOM;
}
+ // Xom may still try to save your life.
+ else if (xom_saves_your_life(dam, death_source, death_type, aux,
+ see_source))
+ {
+ return;
+ }
#if WIZARD || DEBUG
if (you.never_die)
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index bc07ae3ffa..d4df0e71d1 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -23,6 +23,7 @@
#include "map_knowledge.h"
#include "feature.h"
#include "goditem.h"
+#include "hiscores.h"
#include "it_use2.h"
#include "itemprop.h"
#include "items.h"
@@ -3787,6 +3788,124 @@ void xom_death_message(const kill_method_type killed_by)
// All others just get ignored by Xom.
}
+static int _death_is_worth_saving(const kill_method_type killed_by,
+ const char *aux)
+{
+ switch (killed_by)
+ {
+ // These don't count.
+ case KILLED_BY_LEAVING:
+ case KILLED_BY_WINNING:
+ case KILLED_BY_QUITTING:
+
+ // These are too much hassle.
+ case KILLED_BY_LAVA:
+ case KILLED_BY_WATER:
+ case KILLED_BY_DRAINING:
+ case KILLED_BY_STARVATION:
+ case KILLED_BY_ROTTING:
+
+ // Don't protect the player from these.
+ case KILLED_BY_SELF_AIMED:
+ case KILLED_BY_TARGETTING:
+ return (false);
+
+ // Only if not caused by equipment.
+ case KILLED_BY_STUPIDITY:
+ case KILLED_BY_WEAKNESS:
+ case KILLED_BY_CLUMSINESS:
+ if (strstr(aux, "wielding") == NULL && strstr(aux, "wearing") == NULL
+ && strstr(aux, "removing") == NULL)
+ {
+ return (true);
+ }
+ return (false);
+
+ // Everything else is fair game.
+ default:
+ return (true);
+ }
+}
+
+static std::string _get_death_type_keyword(const kill_method_type killed_by)
+{
+ switch (killed_by)
+ {
+ case KILLED_BY_MONSTER:
+ case KILLED_BY_BEAM:
+ case KILLED_BY_BEOGH_SMITING:
+ case KILLED_BY_TSO_SMITING:
+ case KILLED_BY_DIVINE_WRATH:
+ return "actor";
+ default:
+ return "general";
+ }
+}
+
+bool xom_saves_your_life(const int dam, const int death_source,
+ const kill_method_type death_type, const char *aux,
+ bool see_source)
+{
+ if (you.religion != GOD_XOM || _xom_feels_nasty())
+ return (false);
+
+ // If this happens, don't bother.
+ if (you.hp_max < 1 || you.experience_level < 1)
+ return (false);
+
+ // Generally a rare effect.
+ if (!one_chance_in(20))
+ return (false);
+
+ if (!_death_is_worth_saving(death_type, aux))
+ return (false);
+
+ // In addition, the chance depends on the current tension and Xom's mood.
+ const int death_tension = get_tension(GOD_XOM, false);
+ if (death_tension < random2(5) || !xom_is_nice(death_tension))
+ return (false);
+
+ // Fake death message.
+ mpr("You die...");
+ more();
+
+ const std::string key = _get_death_type_keyword(death_type);
+ std::string speech = _get_xom_speech("life saving " + key);
+ if (speech.find("@xom_plaything@") != std::string::npos)
+ {
+ std::string toy_name = (you.piety > 180) ? "teddy bear" :
+ (you.piety > 80) ? "toy"
+ : "plaything";
+
+ speech = replace_all(speech, "@xom_plaything@", toy_name);
+ }
+ god_speaks(GOD_XOM, speech.c_str());
+
+ // Give back some hp.
+ if (you.hp < 1)
+ you.hp = 1 + random2(you.hp_max/4);
+
+ // Make sure all stats are at least 1.
+ if (you.strength < 1)
+ you.strength = 1;
+ if (you.dex < 1)
+ you.dex = 1;
+ if (you.intel < 1)
+ you.intel = 1;
+
+ god_speaks(GOD_XOM, "Xom revives you!");
+
+ // Ideally, this should contain the death cause but that is too much
+ // trouble for now.
+ take_note( Note(NOTE_XOM_REVIVAL) );
+
+ // Make sure Xom doesn't get bored within the next couple of turns.
+ if (you.gift_timeout < 10)
+ you.gift_timeout = 10;
+
+ return (true);
+}
+
#ifdef WIZARD
struct xom_effect_count
{
diff --git a/crawl-ref/source/xom.h b/crawl-ref/source/xom.h
index 25706fb1ab..7839987c9d 100644
--- a/crawl-ref/source/xom.h
+++ b/crawl-ref/source/xom.h
@@ -86,6 +86,10 @@ inline void xom_acts(int sever, int tension = -1)
void xom_check_lost_item(const item_def& item);
void xom_check_destroyed_item(const item_def& item, int cause = -1);
void xom_death_message(const kill_method_type killed_by);
+bool xom_saves_your_life(const int dam, const int death_source,
+ const kill_method_type death_type, const char *aux,
+ const bool see_source);
+
#ifdef WIZARD
void debug_xom_effects();
#endif