summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-03-31 07:05:53 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-03-31 07:05:53 +0000
commit20e25439cad6e0c97716e197bb2dceae731a9d24 (patch)
treed188c2b097b39976c6084a5619b5668dd823ada4
parent4f02417442109656263366ffcefd68231a0da7e9 (diff)
downloadcrawl-ref-20e25439cad6e0c97716e197bb2dceae731a9d24.tar.gz
crawl-ref-20e25439cad6e0c97716e197bb2dceae731a9d24.zip
Add some checks to Xom making you cast spells, so you don't attempt to
e.g. cast a branding spell, or a transformation that will fail for whatever reason. You may still occasionally get a "The spell fizzled" (or whatever) message but that should be rarer now. Apply the same fail chances for Detect Items as for Magic Mapping for fully explored levels, and for low severity make Summon Butterflies more likely to avoid endless attempts of casting Magic Mapping on fully explored levels. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9573 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/docs/changes.stone_soup15
-rw-r--r--crawl-ref/source/command.cc1
-rw-r--r--crawl-ref/source/debug.cc12
-rw-r--r--crawl-ref/source/describe.cc2
-rw-r--r--crawl-ref/source/transfor.cc41
-rw-r--r--crawl-ref/source/transfor.h3
-rw-r--r--crawl-ref/source/xom.cc110
-rw-r--r--crawl-ref/source/xom.h2
8 files changed, 137 insertions, 49 deletions
diff --git a/crawl-ref/docs/changes.stone_soup b/crawl-ref/docs/changes.stone_soup
index ef788909b3..8a61b89809 100644
--- a/crawl-ref/docs/changes.stone_soup
+++ b/crawl-ref/docs/changes.stone_soup
@@ -8,7 +8,7 @@ Breaks saves compatibility.
0.5 Highlights
--------------
-* New species and class: Deep Dwarf, Artificer.
+* New species and job: Deep Dwarf, Artificer.
* Removed three species: Gnome, Grey Elf, Ogre-Mage.
* Several cool new uniques and other monsters.
* Several great new portal vaults.
@@ -42,6 +42,7 @@ Characters
* Vampires can no longer heal via potions of blood or non-fresh corpses.
* Vampires recover lost attributes depending on blood level.
* Draining of the experience pool is now reduced by life protection.
+* Merfolk can now swim in heavy armour, albeit with doubled armour penalty.
* Player and monster nagas no longer flounder or lose stealth in shallow water.
* Secondary unarmed attacks now wake sleeping monsters.
* Pure spellcasters don't start with a weapon anymore.
@@ -78,6 +79,8 @@ Monsters
Interface
---------
* Store message history across saves.
+* Some message condensation for identical messages.
+* Added stat_colour option to highlight dangerously low stats.
* New option: Automatically set travel exclusions for statues and oklob plants.
* Limit travel exclusions to line of sight.
* Change exclusion commands to e, E, Ctrl-E (was Ctrl-X, x, Ctrl-E).
@@ -86,7 +89,7 @@ Interface
* Wizard commands can now be used from the wizard help screen.
* With a full pack, check entire list of selected items to allow for merging.
* Added an option to make menu colours apply to shops.
-* Added stat_colour option to highlight dangerously low stats.
+* Use menu colours for announcements of items found while travelling.
* Pressing Esc at -More- automatically clears all queued -More- prompts.
* Greatly improved the monster view command ('V'), allowing travel to items.
* Add FAQ to help screen ('?Q').
@@ -124,19 +127,19 @@ Items
Gods
----
* Greatly improved Yredelemnul.
-* Nerfed TSO/Beogh blessings of followers.
-* Xom is much more interesting.
+* Nerfed TSO/Beogh's blessings of followers.
+* Xom is more interesting and more useful in combat.
* Cleansing Flame centers on the player and deals less damage.
* Killing a holy being is now sometimes avenged by TSO.
* Move Divine Robustness from Zin to Elyvilon, replacing Incredible Healing.
* Make Zin's retribution-summoned plagues permanent.
-* Allow Trog to accept kills of demons.
* Sif Muna no longer gifts Kiku/Vehumet specific books, spells still possible.
+* Allow Trog to accept kills of demons.
* Vehumet accepts undead killing for you.
-* Disallow shapeshifters in orc form to become Beoghites' followers.
* Beogh no longer accepts butcher but likes prayer over orcish remains.
* Beogh accepts more kinds of kills.
* Beogh has a non-cannibalism conduct.
+* Disallow shapeshifters in orc form to become Beoghites' followers.
Tiles
-----
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 6014528aae..6bcb35072f 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -1371,6 +1371,7 @@ static bool _do_description(std::string key, std::string type,
if (thing_created != NON_ITEM
&& (type == "item" || type == "spell"))
{
+
char name[80];
strncpy(name, key.c_str(), sizeof(name));
if (get_item_by_name(&mitm[thing_created], name, OBJ_WEAPONS))
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 4736162af4..1fd4cd306f 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -930,14 +930,11 @@ static void _rune_from_specs(const char* _specs, item_def &item)
while (true)
{
- mpr(
-"[a] iron [b] obsidian [c] icy [d] bone [e] slimy [f] silver",
+ mpr("[a] iron [b] obsidian [c] icy [d] bone [e] slimy [f] silver",
MSGCH_PROMPT);
- mpr(
-"[g] serpentine [h] elven [i] golden [j] decaying [k] barnacle [l] demonic",
+ mpr("[g] serpentine [h] elven [i] golden [j] decaying [k] barnacle [l] demonic",
MSGCH_PROMPT);
- mpr(
-"[m] abyssal [n] glowing [o] magical [p] fiery [q] dark [r] buggy",
+ mpr("[m] abyssal [n] glowing [o] magical [p] fiery [q] dark [r] buggy",
MSGCH_PROMPT);
mpr("Which rune (ESC to exit)? ", MSGCH_PROMPT);
@@ -2424,7 +2421,6 @@ void wizard_gain_piety()
}
else if (you.religion == GOD_XOM)
{
- const std::string old_xom_favour = describe_xom_favour();
you.piety = random2(MAX_PIETY+1); // reroll mood
if (one_chance_in(10))
you.gift_timeout = 0;
@@ -2432,7 +2428,7 @@ void wizard_gain_piety()
you.gift_timeout = random2(40) + random2(40); // reroll interest
const std::string new_xom_favour = describe_xom_favour();
- const std::string msg = "Your title is now: " + new_xom_favour;
+ const std::string msg = "You are now " + new_xom_favour;
god_speaks(you.religion, msg.c_str());
return;
}
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 97f0281497..bc612b78fc 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -3102,7 +3102,7 @@ std::string describe_favour(god_type which_god)
: "You should show more discipline.";
}
- return (which_god == GOD_XOM) ? describe_xom_favour()
+ return (which_god == GOD_XOM) ? describe_xom_favour(true)
: _describe_favour_generic(which_god);
}
diff --git a/crawl-ref/source/transfor.cc b/crawl-ref/source/transfor.cc
index 7243beae21..6431e6477e 100644
--- a/crawl-ref/source/transfor.cc
+++ b/crawl-ref/source/transfor.cc
@@ -354,7 +354,7 @@ bool check_transformation_stat_loss(const std::set<equipment_type> &remove,
return (true);
}
- // Check over all items to be removed.
+ // Check over all items to be removed or melded.
std::set<equipment_type>::const_iterator iter;
for (iter = remove.begin(); iter != remove.end(); ++iter)
{
@@ -364,15 +364,14 @@ bool check_transformation_stat_loss(const std::set<equipment_type> &remove,
const item_def& item = you.inv[you.equip[e]];
- // Wielding a stat-boosting non-weapon/non-staff won't hinder
- // transformations.
+ // There are no stat-boosting non-weapons/non-staves.
if (e == EQ_WEAPON
&& item.base_type != OBJ_WEAPONS && item.base_type != OBJ_STAVES)
{
continue;
}
- // Currently, the only nonartefacts which have stat-changing
+ // Currently, the only non-artefacts which have stat-changing
// effects are rings.
if (item.base_type == OBJ_JEWELLERY)
{
@@ -448,8 +447,10 @@ static void _transformation_expiration_warning()
}
// Transforms you into the specified form. If quiet is true, fails silently
-// (if it fails).
-bool transform(int pow, transformation_type which_trans, bool quiet)
+// (if it fails). If just_check is true the transformation doesn't actually
+// happen, but the method returns whether it would be successful.
+bool transform(int pow, transformation_type which_trans, bool quiet,
+ bool just_check)
{
if (you.species == SP_MERFOLK && player_is_swimming()
&& which_trans != TRAN_DRAGON && which_trans != TRAN_BAT)
@@ -471,6 +472,9 @@ bool transform(int pow, transformation_type which_trans, bool quiet)
{
if (you.duration[DUR_TRANSFORMATION] < 100)
{
+ if (just_check)
+ return (true);
+
mpr("You extend your transformation's duration.");
you.duration[DUR_TRANSFORMATION] += random2(pow);
@@ -487,7 +491,7 @@ bool transform(int pow, transformation_type which_trans, bool quiet)
}
}
- if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE)
+ if (!just_check && you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE)
untransform();
// Catch some conditions which prevent transformation.
@@ -568,7 +572,7 @@ bool transform(int pow, transformation_type which_trans, bool quiet)
if (you.species == SP_MERFOLK && player_is_swimming())
{
msg = "You fly out of the water as you turn into "
- "a fearsome dragon!";
+ "a fearsome dragon!";
}
else
msg = "You turn into a fearsome dragon!";
@@ -602,15 +606,19 @@ bool transform(int pow, transformation_type which_trans, bool quiet)
}
if (check_transformation_stat_loss(rem_stuff, quiet,
- std::max(-str, 0), std::max(-dex,0)))
+ std::max(-str, 0), std::max(-dex, 0)))
{
return (false);
}
+ // If we're just pretending return now.
+ if (just_check)
+ return (true);
+
// All checks done, transformation will take place now.
- you.redraw_evasion = true;
+ you.redraw_evasion = true;
you.redraw_armour_class = true;
- you.wield_change = true;
+ you.wield_change = true;
// Most transformations conflict with stone skin.
if (which_trans != TRAN_NONE
@@ -692,6 +700,11 @@ bool transform(int pow, transformation_type which_trans, bool quiet)
break;
}
+ // This only has an effect if the transformation happens passively,
+ // for example if Xom decides to transform you while you're busy
+ // running around or butchering corpses.
+ stop_delay();
+
if (you.species != SP_VAMPIRE || which_trans != TRAN_BAT)
_transformation_expiration_warning();
@@ -707,9 +720,9 @@ void untransform(void)
{
const flight_type old_flight = you.flight_mode();
- you.redraw_evasion = true;
+ you.redraw_evasion = true;
you.redraw_armour_class = true;
- you.wield_change = true;
+ you.wield_change = true;
you.symbol = '@';
you.colour = LIGHTGREY;
@@ -722,7 +735,7 @@ void untransform(void)
std::set<equipment_type> melded = _init_equipment_removal(old_form);
you.attribute[ATTR_TRANSFORMATION] = TRAN_NONE;
- you.duration[DUR_TRANSFORMATION] = 0;
+ you.duration[DUR_TRANSFORMATION] = 0;
int hp_downscale = 10;
diff --git a/crawl-ref/source/transfor.h b/crawl-ref/source/transfor.h
index 072b92a4f9..d9cc16f1bc 100644
--- a/crawl-ref/source/transfor.h
+++ b/crawl-ref/source/transfor.h
@@ -38,7 +38,8 @@ bool check_transformation_stat_loss(const std::set<equipment_type> &remove,
int dex_loss = 0, int int_loss = 0);
size_type transform_size(int psize = PSIZE_BODY);
-bool transform(int pow, transformation_type which_trans, bool quiet = false);
+bool transform(int pow, transformation_type which_trans, bool quiet = false,
+ bool just_check = false);
void remove_one_equip(equipment_type eq, bool meld = true);
void unmeld_one_equip(equipment_type eq);
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index 0626b35b5f..82abc823f1 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -58,14 +58,18 @@ REVISION("$Rev$");
// Which spells? First I copied all spells from your_spells(), and then
// I filtered some out, especially conjurations. Then I sorted them in
// roughly ascending order of power.
+
+// Spells to be cast at tension 0 (no or only low-level monsters around),
+// mostly flavour.
static const spell_type _xom_nontension_spells[] =
{
- SPELL_MAGIC_MAPPING, SPELL_DETECT_ITEMS, SPELL_DETECT_CREATURES,
- SPELL_OLGREBS_TOXIC_RADIANCE, SPELL_SUMMON_BUTTERFLIES,
- SPELL_FLY, SPELL_SPIDER_FORM, SPELL_STATUE_FORM, SPELL_ICE_FORM,
+ SPELL_MAGIC_MAPPING, SPELL_DETECT_ITEMS, SPELL_SUMMON_BUTTERFLIES,
+ SPELL_DETECT_CREATURES, SPELL_FLY, SPELL_SPIDER_FORM,
+ SPELL_OLGREBS_TOXIC_RADIANCE, SPELL_STATUE_FORM, SPELL_ICE_FORM,
SPELL_DRAGON_FORM, SPELL_NECROMUTATION
};
+// Spells to be cast at tension > 0, i.e. usually in battle situations.
static const spell_type _xom_tension_spells[] =
{
SPELL_BLINK, SPELL_CONFUSING_TOUCH, SPELL_CAUSE_FEAR,
@@ -106,22 +110,28 @@ static const char *_xom_message_arrays[NUM_XOM_MESSAGE_TYPES][6] =
}
};
-const char *describe_xom_favour()
+const char *describe_xom_favour(bool upper)
{
+ std::string favour;
if (you.religion != GOD_XOM)
- return ("A very buggy toy of Xom.");
+ favour = "a very buggy toy of Xom.";
else if (you.gift_timeout < 1)
- return "A BORING thing.";
+ favour = "a BORING thing.";
else
{
- return (you.piety > 180) ? "Xom's teddy bear." :
- (you.piety > 150) ? "A beloved toy of Xom." :
- (you.piety > 120) ? "A favourite toy of Xom." :
- (you.piety > 80) ? "A toy of Xom." :
- (you.piety > 50) ? "A plaything of Xom." :
- (you.piety > 20) ? "A special plaything of Xom."
- : "A very special plaything of Xom.";
+ favour = (you.piety > 180) ? "Xom's teddy bear." :
+ (you.piety > 150) ? "a beloved toy of Xom." :
+ (you.piety > 120) ? "a favourite toy of Xom." :
+ (you.piety > 80) ? "a toy of Xom." :
+ (you.piety > 50) ? "a plaything of Xom." :
+ (you.piety > 20) ? "a special plaything of Xom."
+ : "a very special plaything of Xom.";
}
+
+ if (upper)
+ favour = uppercase_first(favour);
+
+ return (favour.c_str());
}
static std::string _get_xom_speech(const std::string key)
@@ -248,7 +258,7 @@ void xom_tick()
new_xom_favour = describe_xom_favour();
if (old_xom_favour != new_xom_favour)
{
- const std::string msg = "Your title is now: " + new_xom_favour;
+ const std::string msg = "You are now " + new_xom_favour;
god_speaks(you.religion, msg.c_str());
}
@@ -351,9 +361,60 @@ static int _exploration_estimate(bool seen_only = false)
return (seen);
}
+static bool _spell_requires_weapon(const spell_type spell)
+{
+ switch (spell)
+ {
+ case SPELL_TUKIMAS_VORPAL_BLADE:
+ case SPELL_MAXWELLS_SILVER_HAMMER:
+ case SPELL_FIRE_BRAND:
+ case SPELL_FREEZING_AURA:
+ case SPELL_POISON_WEAPON:
+ case SPELL_LETHAL_INFUSION:
+ case SPELL_EXCRUCIATING_WOUNDS:
+ case SPELL_WARP_BRAND:
+ case SPELL_TUKIMAS_DANCE:
+ return (true);
+ default:
+ return (false);
+ }
+}
+
+static bool _transformation_check(const spell_type spell)
+{
+ transformation_type tran = TRAN_NONE;
+ switch (spell)
+ {
+ case SPELL_SPIDER_FORM:
+ tran = TRAN_SPIDER;
+ break;
+ case SPELL_STATUE_FORM:
+ tran = TRAN_STATUE;
+ break;
+ case SPELL_ICE_FORM:
+ tran = TRAN_ICE_BEAST;
+ break;
+ case SPELL_DRAGON_FORM:
+ tran = TRAN_DRAGON;
+ break;
+ case SPELL_NECROMUTATION:
+ tran = TRAN_LICH;
+ break;
+ default:
+ break;
+ }
+
+ if (tran == TRAN_NONE)
+ return (true);
+
+ // Check whether existing enchantments/transformations, cursed equipment,
+ // or potential stat loss interfere with this transformation.
+ return transform(0, tran, true, true);
+}
+
static bool _xom_makes_you_cast_random_spell(int sever, int tension)
{
- int spellenum = sever;
+ int spellenum = std::max(1, sever);
god_acting gdact(GOD_XOM);
@@ -363,14 +424,20 @@ static bool _xom_makes_you_cast_random_spell(int sever, int tension)
const int nxomspells = ARRAYSZ(_xom_tension_spells);
spellenum = std::min(nxomspells, spellenum);
spell = _xom_tension_spells[random2(spellenum)];
+
+ // Don't attempt to cast spells that are guaranteed to fail.
+ // You may still get results such as "The spell fizzles" or
+ // "Nothing appears to happen", but those should be rarer now.
+ if (_spell_requires_weapon(spell) && !player_weapon_wielded())
+ return (false);
}
else
{
const int nxomspells = ARRAYSZ(_xom_nontension_spells);
- spellenum = std::min(nxomspells, spellenum);
+ spellenum = std::min(nxomspells, std::max(3 + coinflip(), spellenum));
spell = _xom_nontension_spells[random2(spellenum)];
- if (spell == SPELL_MAGIC_MAPPING)
+ if (spell == SPELL_MAGIC_MAPPING || spell == SPELL_DETECT_ITEMS)
{
// If the level is already mostly explored, there's
// a chance we might try something else.
@@ -383,6 +450,10 @@ static bool _xom_makes_you_cast_random_spell(int sever, int tension)
if (you_cannot_memorise(spell))
return (false);
+ // Don't attempt to transform the player if the transformation will fail.
+ if (!_transformation_check(spell))
+ return (false);
+
god_speaks(GOD_XOM, _get_xom_speech("spell effect").c_str());
#if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_RELIGION) || defined(DEBUG_XOM)
@@ -2135,6 +2206,9 @@ static bool _xom_is_bad(int sever, int tension)
mprf(MSGCH_DIAGNOSTICS, "badness: %d, new interest: %d",
badness, you.gift_timeout);
#endif
+ const std::string new_xom_favour = describe_xom_favour();
+ const std::string msg = "You are now " + new_xom_favour;
+ god_speaks(you.religion, msg.c_str());
}
return (done);
}
@@ -2367,7 +2441,7 @@ void xom_acts(bool niceness, int sever, int tension)
const std::string new_xom_favour = describe_xom_favour();
if (old_xom_favour != new_xom_favour)
{
- const std::string msg = "Your title is now: " + new_xom_favour;
+ const std::string msg = "You are now " + new_xom_favour;
god_speaks(you.religion, msg.c_str());
}
}
diff --git a/crawl-ref/source/xom.h b/crawl-ref/source/xom.h
index cda54827fd..cd1c0a67bb 100644
--- a/crawl-ref/source/xom.h
+++ b/crawl-ref/source/xom.h
@@ -28,7 +28,7 @@ void xom_is_stimulated(int maxinterestingness, const std::string& message,
bool force_message = false);
bool xom_is_nice();
void xom_acts(bool niceness, int sever, int tension = -1);
-const char *describe_xom_favour();
+const char *describe_xom_favour(bool upper = false);
inline void xom_acts(int sever, int tension = -1)
{