diff options
author | Johanna Ploog <j-p-e-g@users.sourceforge.net> | 2009-12-09 21:31:02 +0100 |
---|---|---|
committer | Johanna Ploog <j-p-e-g@users.sourceforge.net> | 2009-12-09 21:31:02 +0100 |
commit | b8f3c183df87ee55833ab561fa12ed324da5a913 (patch) | |
tree | 2be4120a6fc0053dc049ba066e68b1ebfe701a01 | |
parent | f4efe0a7c1422dede865ea5f9d8e2d96978b2f9f (diff) | |
download | crawl-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.txt | 27 | ||||
-rw-r--r-- | crawl-ref/source/hiscores.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/notes.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/notes.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/ouch.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/xom.cc | 119 | ||||
-rw-r--r-- | crawl-ref/source/xom.h | 4 |
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 |