summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/abl-show.cc315
-rw-r--r--crawl-ref/source/abyss.cc4
-rw-r--r--crawl-ref/source/abyss.h1
-rw-r--r--crawl-ref/source/it_use2.cc2
-rw-r--r--crawl-ref/source/item_use.cc14
-rw-r--r--crawl-ref/source/item_use.h5
-rw-r--r--crawl-ref/source/spells3.cc5
7 files changed, 205 insertions, 141 deletions
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 88fd7e5641..aa6d1604eb 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -963,6 +963,182 @@ bool activate_ability()
return _activate_talent(talents[selected]);
}
+// Check prerequisites for a number of abilities.
+// Abort any attempt if these cannot be met, without losing the turn.
+// TODO: Many more cases need to be added!
+static bool _check_ability_possible(const ability_def& abil,
+ bool hungerCheck = true)
+{
+ // Don't insta-starve the player.
+ // (Happens at 100, losing consciousness possible from 500 downward.)
+ if (hungerCheck && you.species != SP_VAMPIRE)
+ {
+ const int expected_hunger = you.hunger - abil.food_cost * 2;
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_DIAGNOSTICS,
+ "hunger: %d, max. food_cost: %d, expected hunger: %d",
+ you.hunger, abil.food_cost * 2, expected_hunger);
+#endif
+ // Safety margin for natural hunger, mutations etc.
+ if (expected_hunger <= 150)
+ {
+ mpr("You're too hungry.");
+ return (false);
+ }
+ }
+
+ switch (abil.ability)
+ {
+ case ABIL_ZIN_RECITE:
+ {
+ const int result = check_recital_audience();
+ if (result < 0)
+ {
+ mpr("There's no appreciative audience!");
+ return (false);
+ }
+ else if (result < 1)
+ {
+ mpr("There's no-one here to preach to!");
+ return (false);
+ }
+ return (true);
+ }
+ case ABIL_ZIN_CURE_ALL_MUTATIONS:
+ return (how_mutated());
+
+ case ABIL_ZIN_SANCTUARY:
+ if (env.sanctuary_time)
+ {
+ mpr("There's already a sanctuary in place on this level.");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_ELYVILON_PURIFICATION:
+ if (!you.disease && !you.rotting && !you.duration[DUR_POISONING]
+ && !you.duration[DUR_CONF] && !you.duration[DUR_SLOW]
+ && !you.duration[DUR_PARALYSIS] && !you.duration[DUR_PETRIFIED])
+ {
+ mpr("Nothing ails you!");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_ELYVILON_RESTORATION:
+ case ABIL_MUMMY_RESTORATION:
+ if (you.strength == you.max_strength
+ && you.intel == you.max_intel
+ && you.dex == you.max_dex
+ && (abil.ability == ABIL_MUMMY_RESTORATION || !player_rotted()))
+ {
+ mprf("You don't need to restore your stats%s!",
+ abil.ability == ABIL_ELYVILON_RESTORATION ? " or hit points"
+ : "");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_LUGONU_ABYSS_EXIT:
+ if (you.level_type != LEVEL_ABYSS)
+ {
+ mpr("You aren't in the Abyss!");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_LUGONU_CORRUPT:
+ return (!is_level_incorruptible());
+
+ case ABIL_LUGONU_ABYSS_ENTER:
+ if (you.level_type == LEVEL_ABYSS)
+ {
+ mpr("You're already here!");
+ return (false);
+ }
+ else if (you.level_type == LEVEL_PANDEMONIUM)
+ {
+ mpr("That doesn't work from Pandemonium.");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_SIF_MUNA_FORGET_SPELL:
+ if (you.spell_no == 0)
+ {
+ mpr("You don't know any spells.");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_SPIT_POISON:
+ case ABIL_BREATHE_FIRE:
+ case ABIL_BREATHE_FROST:
+ case ABIL_BREATHE_POISON:
+ case ABIL_BREATHE_LIGHTNING:
+ case ABIL_BREATHE_POWER:
+ case ABIL_BREATHE_STICKY_FLAME:
+ case ABIL_BREATHE_STEAM:
+ if (you.duration[DUR_BREATH_WEAPON])
+ {
+ canned_msg(MSG_CANNOT_DO_YET);
+ return (false);
+ }
+ return (true);
+
+ case ABIL_EVOKE_BERSERK:
+ case ABIL_TROG_BERSERK:
+ if (you.hunger_state < HS_SATIATED)
+ {
+ mpr("You're too hungry to berserk.");
+ return (false);
+ }
+ return (you.can_go_berserk(true) && berserk_check_wielded_weapon());
+
+ case ABIL_MAPPING:
+ if (player_mutation_level(MUT_MAPPING) < 3
+ && (you.level_type == LEVEL_PANDEMONIUM
+ || !player_in_mappable_area()))
+ {
+ mpr("You feel momentarily disoriented.");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_FLY_II:
+ if (you.duration[DUR_EXHAUSTED])
+ {
+ mpr("You're too exhausted to fly.");
+ return (false);
+ }
+ else if (you.burden_state != BS_UNENCUMBERED)
+ {
+ mpr("You're carrying too much weight to fly.");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_TORMENT:
+ if (you.is_undead)
+ {
+ mpr("The unliving cannot use this ability.");
+ return (false);
+ }
+ return (true);
+
+ case ABIL_EVOKE_TURN_INVISIBLE: // ring, randarts, darkness items
+ if (you.hunger_state < HS_SATIATED)
+ {
+ mpr("You're too hungry to turn invisible.");
+ return (false);
+ }
+ return (true);
+
+ default:
+ return (true);
+ }
+}
+
static bool _activate_talent(const talent& tal)
{
// Doing these would outright kill the player due to stat drain.
@@ -1029,40 +1205,13 @@ static bool _activate_talent(const talent& tal)
return (false);
}
- if (!enough_hp( abil.hp_cost, false ))
+ if (!enough_hp(abil.hp_cost, false))
{
crawl_state.zero_turns_taken();
return (false);
}
- if (tal.which == ABIL_ZIN_SANCTUARY && env.sanctuary_time)
- {
- mpr("There's already a sanctuary in place on this level.");
- crawl_state.zero_turns_taken();
- return (false);
- }
-
- // Don't insta-starve the player.
- // (Happens at 100, losing consciousness possible from 500 downward.)
- if (hungerCheck && you.species != SP_VAMPIRE)
- {
- const int expected_hunger = you.hunger - abil.food_cost * 2;
-#ifdef DEBUG_DIAGNOSTICS
- mprf(MSGCH_DIAGNOSTICS,
- "hunger: %d, max. food_cost: %d, expected hunger: %d",
- you.hunger, abil.food_cost * 2, expected_hunger);
-#endif
- // Safety margin for natural hunger, mutations etc.
- if (expected_hunger <= 150)
- {
- mpr("You're too hungry.");
- crawl_state.zero_turns_taken();
- return (false);
- }
- }
-
- if ((tal.which == ABIL_EVOKE_BERSERK || tal.which == ABIL_TROG_BERSERK)
- && !berserk_check_wielded_weapon())
+ if (!_check_ability_possible(abil, hungerCheck))
{
crawl_state.zero_turns_taken();
return (false);
@@ -1159,12 +1308,6 @@ static bool _do_ability(const ability_def& abil)
case ABIL_SPIT_POISON: // Naga + spit poison mutation
{
- if (you.duration[DUR_BREATH_WEAPON])
- {
- canned_msg(MSG_CANNOT_DO_YET);
- return (false);
- }
-
const int pow = you.experience_level
+ player_mutation_level(MUT_SPIT_POISON) * 5
+ (you.species == SP_NAGA) * 10;
@@ -1184,15 +1327,6 @@ static bool _do_ability(const ability_def& abil)
}
case ABIL_EVOKE_MAPPING: // Randarts
case ABIL_MAPPING: // Sense surroundings mutation
- if (abil.ability == ABIL_MAPPING
- && player_mutation_level(MUT_MAPPING) < 3
- && (you.level_type == LEVEL_PANDEMONIUM
- || !player_in_mappable_area()))
- {
- mpr("You feel momentarily disoriented.");
- return (false);
- }
-
power = (abil.ability == ABIL_EVOKE_MAPPING) ?
you.skills[SK_EVOCATIONS] : you.experience_level;
@@ -1229,17 +1363,9 @@ static bool _do_ability(const ability_def& abil)
case ABIL_BREATHE_POWER:
case ABIL_BREATHE_STICKY_FLAME:
case ABIL_BREATHE_STEAM:
- if (you.duration[DUR_BREATH_WEAPON] && abil.ability != ABIL_SPIT_ACID)
- {
- canned_msg(MSG_CANNOT_DO_YET);
+ beam.range = _calc_breath_ability_range(abil.ability);
+ if (!spell_direction(abild, beam))
return (false);
- }
- else
- {
- beam.range = _calc_breath_ability_range(abil.ability);
- if (!spell_direction(abild, beam))
- return (false);
- }
switch (abil.ability)
{
@@ -1336,20 +1462,8 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_EVOKE_BERSERK: // amulet of rage, randarts
- // FIXME: This is not the best way to do stuff, because
- // you have a chance of failing the evocation test, in
- // which case you'll lose MP, etc.
- // We should add a pre-failure-test check in general.
- if (you.hunger_state < HS_SATIATED)
- {
- mpr("You're too hungry to berserk.");
- return (false);
- }
- else if (!you.can_go_berserk(true))
- return (false);
-
- // only exercise if berserk succeeds
- // because of the test above, this should always happen,
+ // Only exercise if berserk succeeds.
+ // Because of the test above, this should always happen,
// but I'm leaving it in - haranp
if (go_berserk(true))
exercise(SK_EVOCATIONS, 1);
@@ -1365,18 +1479,7 @@ static bool _do_ability(const ability_def& abil)
// Fly (Draconians, or anything else with wings).
case ABIL_FLY_II:
- if (you.duration[DUR_EXHAUSTED])
- {
- mpr("You're too exhausted to fly.");
- return (false);
- }
- else if (you.burden_state != BS_UNENCUMBERED)
- {
- mpr("You're carrying too much weight to fly.");
- return (false);
- }
- else
- cast_fly(you.experience_level * 2);
+ cast_fly(you.experience_level * 2);
break;
// DEMONIC POWERS:
@@ -1395,12 +1498,6 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_TORMENT:
- if (you.is_undead)
- {
- mpr("The unliving cannot use this ability.");
- return (false);
- }
-
torment(TORMENT_GENERIC, you.pos());
break;
@@ -1448,12 +1545,6 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_EVOKE_TURN_INVISIBLE: // ring, randarts, darkness items
- if (you.hunger_state < HS_SATIATED)
- {
- mpr("You're too hungry to turn invisible.");
- return (false);
- }
-
potion_effect(POT_INVISIBILITY, 2 * you.skills[SK_EVOCATIONS] + 5);
contaminate_player( 1 + random2(3), true );
exercise(SK_EVOCATIONS, 1);
@@ -1487,17 +1578,6 @@ static bool _do_ability(const ability_def& abil)
case ABIL_ZIN_RECITE:
{
- int result = check_recital_audience();
- if (result < 0)
- {
- mpr("There's no appreciative audience!");
- return (false);
- }
- else if (result < 1)
- {
- mpr("There's no-one here to preach to!");
- return (false);
- }
// up to (60 + 40)/2 = 50
const int pow = (2*skill_bump(SK_INVOCATIONS) + you.piety / 5) / 2;
start_delay(DELAY_RECITE, 3, pow, you.hp);
@@ -1707,12 +1787,6 @@ static bool _do_ability(const ability_def& abil)
case ABIL_TROG_BERSERK:
// Trog abilities don't use or train invocations.
- if (you.hunger_state < HS_SATIATED)
- {
- mpr("You're too hungry to berserk.");
- return (false);
- }
-
go_berserk(true);
break;
@@ -1729,7 +1803,8 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_SIF_MUNA_FORGET_SPELL:
- cast_selective_amnesia(true);
+ if (!cast_selective_amnesia(true))
+ return (false);
break;
case ABIL_ELYVILON_DESTROY_WEAPONS:
@@ -1787,12 +1862,6 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_LUGONU_ABYSS_EXIT:
- if (you.level_type != LEVEL_ABYSS)
- {
- mpr("You aren't in the Abyss!");
- return (false); // Don't incur costs.
- }
-
banished(DNGN_EXIT_ABYSS);
exercise(SK_INVOCATIONS, 8 + random2(10));
break;
@@ -1830,17 +1899,6 @@ static bool _do_ability(const ability_def& abil)
case ABIL_LUGONU_ABYSS_ENTER:
{
- if (you.level_type == LEVEL_ABYSS)
- {
- mpr("You're already here.");
- return (false);
- }
- else if (you.level_type == LEVEL_PANDEMONIUM)
- {
- mpr("That doesn't work from Pandemonium.");
- return (false);
- }
-
// Move permanent hp/mp loss from leaving to entering the Abyss. (jpeg)
const int maxloss = std::max(2, div_rand_round(you.hp_max, 30));
// Lose permanent HP
@@ -1927,7 +1985,6 @@ static bool _do_ability(const ability_def& abil)
break;
}
case ABIL_FEAWN_SUNLIGHT:
-
if (!sunlight())
return (false);
@@ -1942,7 +1999,7 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_FEAWN_RAIN:
- rain(you.pos() );
+ rain(you.pos());
exercise(SK_INVOCATIONS, 2 + random2(3));
break;
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc
index 50e8d2a2f4..255f9c0bc0 100644
--- a/crawl-ref/source/abyss.cc
+++ b/crawl-ref/source/abyss.cc
@@ -904,7 +904,7 @@ static bool _is_level_corrupted()
return (!!env.markers.find(MAT_CORRUPTION_NEXUS));
}
-static bool _is_level_incorruptible()
+bool is_level_incorruptible()
{
if (_is_level_corrupted())
{
@@ -932,7 +932,7 @@ static void _corrupt_choose_colours()
bool lugonu_corrupt_level(int power)
{
- if (_is_level_incorruptible())
+ if (is_level_incorruptible())
return (false);
mprf(MSGCH_GOD, "Lugonu's Hand of Corruption reaches out!");
diff --git a/crawl-ref/source/abyss.h b/crawl-ref/source/abyss.h
index 7ecebd9e82..6fad89e955 100644
--- a/crawl-ref/source/abyss.h
+++ b/crawl-ref/source/abyss.h
@@ -14,6 +14,7 @@ void generate_abyss();
void area_shift();
void abyss_teleport(bool new_area);
void save_abyss_uniques();
+bool is_level_incorruptible();
bool lugonu_corrupt_level(int power);
void run_corruption_effects(int duration);
diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc
index ca82d654e9..62e8a6ab26 100644
--- a/crawl-ref/source/it_use2.cc
+++ b/crawl-ref/source/it_use2.cc
@@ -486,7 +486,7 @@ bool unwield_item(bool showMsgs)
if (you.duration[DUR_WEAPON_BRAND])
{
you.duration[DUR_WEAPON_BRAND] = 0;
- set_item_ego_type( item, OBJ_WEAPONS, SPWPN_NORMAL );
+ set_item_ego_type(item, OBJ_WEAPONS, SPWPN_NORMAL);
// We're letting this through even if hiding messages.
mpr("Your branding evaporates.");
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 9266f445cd..5a0ed0af1e 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -224,7 +224,7 @@ static bool _valid_weapon_swap(const item_def &item)
// If force is true, don't check weapon inscriptions.
// (Assuming the player was already prompted for that.)
bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages,
- bool force)
+ bool force, bool show_unwield_msg)
{
if (inv_count() < 1)
{
@@ -304,7 +304,8 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages,
if (!unwield_item(show_weff_messages))
return (false);
- canned_msg(MSG_EMPTY_HANDED);
+ if (show_unwield_msg)
+ canned_msg(MSG_EMPTY_HANDED);
// Switching to bare hands is extra fast.
you.turn_is_over = true;
@@ -2220,8 +2221,11 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus,
// Items that get a temporary brand from a player spell lose the
// brand as soon as the player lets go of the item. Can't call
// unwield_item() yet since the beam might get canceled.
- if (you.duration[DUR_WEAPON_BRAND] && projected == LRET_THROWN)
- set_item_ego_type( item, OBJ_WEAPONS, SPWPN_NORMAL );
+ if (you.duration[DUR_WEAPON_BRAND] && projected != LRET_LAUNCHED
+ && throw_2 == you.equip[EQ_WEAPON])
+ {
+ set_item_ego_type(item, OBJ_WEAPONS, SPWPN_NORMAL);
+ }
std::string ammo_name;
setup_missile_beam(&you, pbolt, item, ammo_name, returning);
@@ -2307,7 +2311,7 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus,
bool unwielded = false;
if (throw_2 == you.equip[EQ_WEAPON] && thrown.quantity == 1)
{
- if (!wield_weapon(true, PROMPT_GOT_SPECIAL))
+ if (!wield_weapon(true, PROMPT_GOT_SPECIAL, true, false, false))
return (false);
unwielded = true;
diff --git a/crawl-ref/source/item_use.h b/crawl-ref/source/item_use.h
index 59fbbc944c..24972511a8 100644
--- a/crawl-ref/source/item_use.h
+++ b/crawl-ref/source/item_use.h
@@ -135,8 +135,9 @@ bool can_wield(item_def *weapon, bool say_why = false,
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-bool wield_weapon(bool auto_wield, int slot = -1, bool show_we_messages = true,
- bool force = false);
+bool wield_weapon(bool auto_wield, int slot = -1,
+ bool show_weff_messages = true, bool force = false,
+ bool show_unwield_msg = true);
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index 0a960b525f..6f238654ad 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -93,8 +93,9 @@ bool cast_selective_amnesia(bool force)
return (false);
}
- if (!force &&
- random2(you.skills[SK_SPELLCASTING]) < random2(spell_difficulty(spell)))
+ if (!force
+ && random2(you.skills[SK_SPELLCASTING])
+ < random2(spell_difficulty(spell)))
{
mpr("Oops! This spell sure is a blunt instrument.");
forget_map(20 + random2(50));