summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
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 /crawl-ref/source
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
Diffstat (limited to 'crawl-ref/source')
-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
7 files changed, 128 insertions, 43 deletions
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)
{