summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/main.cc')
-rw-r--r--crawl-ref/source/main.cc1186
1 files changed, 7 insertions, 1179 deletions
diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc
index f8991e3cf3..d6f314ab50 100644
--- a/crawl-ref/source/main.cc
+++ b/crawl-ref/source/main.cc
@@ -103,6 +103,7 @@
#include "output.h"
#include "player.h"
#include "player-equip.h"
+#include "player-reacts.h"
#include "player-stats.h"
#include "quiver.h"
#include "random.h"
@@ -181,7 +182,7 @@ string init_file_error; // externed in newgame.cc
char info[ INFO_SIZE ]; // messaging queue extern'd everywhere {dlb}
-int stealth; // externed in view.cc
+int stealth; // externed in shout.cc and player_reacts.cc
void world_reacts();
@@ -201,7 +202,6 @@ NORETURN static void _launch_game();
static void _do_berserk_no_combat_penalty(void);
static void _do_searing_ray(void);
-static void _extract_manticore_spikes(void);
static void _input(void);
static void _move_player(int move_x, int move_y);
static void _move_player(coord_def move);
@@ -1964,7 +1964,8 @@ void process_command(command_type cmd)
case CMD_WAIT:
you.check_clinging(false);
you.turn_is_over = true;
- _extract_manticore_spikes();
+ extract_manticore_spikes("You carefully extract the manticore spikes "
+ "from your body.");
break;
case CMD_PICKUP:
@@ -2205,901 +2206,6 @@ static void _prep_input()
}
}
-/**
- * Decrement a duration by the given delay.
-
- * The midloss value should be either 0 or a number of turns where the delay
- * from those turns at normal speed is less than the duration's midpoint. The
- * use of midloss prevents the player from knowing the exact remaining duration
- * when the midpoint message is displayed.
- *
- * @param dur The duration type to be decremented.
- * @param delay The delay aut amount by which to decrement the duration.
- * @param endmsg The message to be displayed when the duration ends.
- * @param midloss A number of normal-speed turns by which to further decrement
- * the duration if we cross the duration's midpoint.
- * @param endmsg The message to be displayed when the duration is decremented
- * to a value under its midpoint.
- * @param chan The channel where the endmsg will be printed if the duration
- * ends.
- *
- * @returns True if the duration ended, false otherwise.
- */
-static bool _decrement_a_duration(duration_type dur, int delay,
- const char* endmsg = nullptr,
- int midloss = 0,
- const char* midmsg = nullptr,
- msg_channel_type chan = MSGCH_DURATION)
-{
- ASSERT(you.duration[dur] >= 0);
- if (you.duration[dur] == 0)
- return false;
-
- ASSERT(!midloss || midmsg != nullptr);
- const int midpoint = get_expiration_threshold(dur);
- ASSERTM(!midloss || midloss * BASELINE_DELAY < midpoint,
- "midpoint delay loss %d not less than duration midpoint %d",
- midloss * BASELINE_DELAY, midpoint);
-
- int old_dur = you.duration[dur];
- you.duration[dur] -= delay;
-
- // If we cross the midpoint, handle midloss and print the midpoint message.
- if (you.duration[dur] <= midpoint && old_dur > midpoint)
- {
- you.duration[dur] -= midloss * BASELINE_DELAY;
- if (midmsg)
- {
- // Make sure the player has a turn to react to the midpoint
- // message.
- if (you.duration[dur] <= 0)
- you.duration[dur] = 1;
- if (need_expiration_warning(dur))
- mprf(MSGCH_DANGER, "Careful! %s", midmsg);
- else
- mprf(chan, "%s", midmsg);
- }
- }
-
- if (you.duration[dur] <= 0)
- {
- you.duration[dur] = 0;
- if (endmsg)
- mprf(chan, "%s", endmsg);
- return true;
- }
-
- return false;
-}
-
-static void _decrement_paralysis(int delay)
-{
- _decrement_a_duration(DUR_PARALYSIS_IMMUNITY, delay);
-
- if (you.duration[DUR_PARALYSIS])
- {
- _decrement_a_duration(DUR_PARALYSIS, delay);
-
- if (!you.duration[DUR_PARALYSIS] && !you.petrified())
- {
- mprf(MSGCH_DURATION, "You can move again.");
- you.redraw_evasion = true;
- you.duration[DUR_PARALYSIS_IMMUNITY] = roll_dice(1, 3)
- * BASELINE_DELAY;
- if (you.props.exists("paralysed_by"))
- you.props.erase("paralysed_by");
- }
- }
-}
-
-static void _decrement_petrification(int delay)
-{
- if (_decrement_a_duration(DUR_PETRIFIED, delay) && !you.paralysed())
- {
- you.redraw_evasion = true;
- mprf(MSGCH_DURATION, "You turn to %s and can move again.",
- you.form == TRAN_LICH ? "bone" :
- you.form == TRAN_ICE_BEAST ? "ice" :
- "flesh");
- }
-
- if (you.duration[DUR_PETRIFYING])
- {
- int &dur = you.duration[DUR_PETRIFYING];
- int old_dur = dur;
- if ((dur -= delay) <= 0)
- {
- dur = 0;
- // If we'd kill the player when active flight stops, this will
- // need to pass the killer. Unlike monsters, almost all flight is
- // magical, inluding tengu, as there's no flapping of wings. Should
- // we be nasty to dragon and bat forms? For now, let's not instakill
- // them even if it's inconsistent.
- you.fully_petrify(NULL);
- }
- else if (dur < 15 && old_dur >= 15)
- mpr("Your limbs are stiffening.");
- }
-}
-
-static int _zin_recite_to_monsters(coord_def where, int prayertype, int, actor *)
-{
- ASSERT_RANGE(prayertype, 0, NUM_RECITE_TYPES);
- return zin_recite_to_single_monster(where, (recite_type)prayertype);
-}
-
-static bool _check_recite()
-{
- if (you.hp*2 < you.attribute[ATTR_RECITE_HP]
- || silenced(you.pos())
- || you.paralysed()
- || you.confused()
- || you.asleep()
- || you.petrified()
- || you.berserk())
- {
- zin_recite_interrupt();
- return false;
- }
- return true;
-}
-
-static void _handle_recitation(int step)
-{
- mprf("\"%s\"",
- zin_recite_text(you.attribute[ATTR_RECITE_SEED],
- you.attribute[ATTR_RECITE_TYPE], step).c_str());
-
- if (apply_area_visible(_zin_recite_to_monsters,
- you.attribute[ATTR_RECITE_TYPE], &you))
- viewwindow();
-
- // Recite trains more than once per use, because it has a
- // long timer in between uses and actually takes up multiple
- // turns.
- practise(EX_USED_ABIL, ABIL_ZIN_RECITE);
-
- noisy(you.shout_volume(), you.pos());
-
- if (step == 0)
- {
- string speech = zin_recite_text(you.attribute[ATTR_RECITE_SEED],
- you.attribute[ATTR_RECITE_TYPE], -1);
- speech += ".";
- if (one_chance_in(9))
- {
- const string closure = getSpeakString("recite_closure");
- if (!closure.empty() && one_chance_in(3))
- {
- speech += " ";
- speech += closure;
- }
- }
- mprf(MSGCH_DURATION, "You finish reciting %s", speech.c_str());
- mpr("You feel short of breath.");
- you.increase_duration(DUR_BREATH_WEAPON, random2(10) + random2(30));
- }
-}
-
-// Perhaps we should write functions like: update_liquid_flames(), etc.
-// Even better, we could have a vector of callback functions (or
-// objects) which get installed at some point.
-
-/**
- * Decrement player durations based on how long the player's turn lasted in aut.
- */
-static void _decrement_durations()
-{
- int delay = you.time_taken;
-
- if (you.gourmand())
- {
- // Innate gourmand is always fully active.
- if (player_mutation_level(MUT_GOURMAND) > 0)
- you.duration[DUR_GOURMAND] = GOURMAND_MAX;
- else if (you.duration[DUR_GOURMAND] < GOURMAND_MAX && coinflip())
- you.duration[DUR_GOURMAND] += delay;
- }
- else
- you.duration[DUR_GOURMAND] = 0;
-
- if (you.duration[DUR_ICEMAIL_DEPLETED] > 0)
- {
- if (delay > you.duration[DUR_ICEMAIL_DEPLETED])
- you.duration[DUR_ICEMAIL_DEPLETED] = 0;
- else
- you.duration[DUR_ICEMAIL_DEPLETED] -= delay;
-
- if (!you.duration[DUR_ICEMAIL_DEPLETED])
- mprf(MSGCH_DURATION, "Your icy envelope is restored.");
-
- you.redraw_armour_class = true;
- }
-
- if (you.duration[DUR_DEMONIC_GUARDIAN] > 0)
- {
- if (delay > you.duration[DUR_DEMONIC_GUARDIAN])
- you.duration[DUR_DEMONIC_GUARDIAN] = 0;
- else
- you.duration[DUR_DEMONIC_GUARDIAN] -= delay;
- }
-
- // Must come before berserk.
- if (_decrement_a_duration(DUR_BUILDING_RAGE, delay))
- go_berserk(false);
-
- if (you.duration[DUR_LIQUID_FLAMES])
- dec_napalm_player(delay);
-
- const bool melted = you.props.exists(MELT_ARMOUR_KEY);
- if (_decrement_a_duration(DUR_ICY_ARMOUR, delay,
- "Your icy armour evaporates.",
- melted ? 0 : coinflip(),
- melted ? nullptr
- : "Your icy armour starts to melt."))
- {
- you.redraw_armour_class = true;
- }
-
- // Possible reduction of silence radius.
- if (you.duration[DUR_SILENCE])
- invalidate_agrid();
- // and liquefying radius.
- if (you.duration[DUR_LIQUEFYING])
- invalidate_agrid();
-
- _decrement_a_duration(DUR_SILENCE, delay, "Your hearing returns.");
-
- if (_decrement_a_duration(DUR_TROGS_HAND, delay,
- NULL, coinflip(),
- "You feel the effects of Trog's Hand fading."))
- {
- trog_remove_trogs_hand();
- }
-
- _decrement_a_duration(DUR_REGENERATION, delay,
- "Your skin stops crawling.",
- coinflip(),
- "Your skin is crawling a little less now.");
-
- _decrement_a_duration(DUR_VEHUMET_GIFT, delay);
-
- _decrement_a_duration(DUR_JELLY_PRAYER, delay, "Your prayer is over.");
-
- if (you.duration[DUR_DIVINE_SHIELD] > 0)
- {
- if (you.duration[DUR_DIVINE_SHIELD] > 1)
- {
- you.duration[DUR_DIVINE_SHIELD] -= delay;
- if (you.duration[DUR_DIVINE_SHIELD] <= 1)
- {
- you.duration[DUR_DIVINE_SHIELD] = 1;
- mprf(MSGCH_DURATION, "Your divine shield starts to fade.");
- }
- }
-
- if (you.duration[DUR_DIVINE_SHIELD] == 1 && !one_chance_in(3))
- {
- you.redraw_armour_class = true;
- if (--you.attribute[ATTR_DIVINE_SHIELD] == 0)
- {
- you.duration[DUR_DIVINE_SHIELD] = 0;
- mprf(MSGCH_DURATION, "Your divine shield fades away.");
- }
- }
- }
-
- //jmf: More flexible weapon branding code.
- int last_value = you.duration[DUR_WEAPON_BRAND];
-
- if (last_value > 0)
- {
- you.duration[DUR_WEAPON_BRAND] -= delay;
-
- if (you.duration[DUR_WEAPON_BRAND] <= 0)
- {
- you.duration[DUR_WEAPON_BRAND] = 0;
- item_def& weapon = *you.weapon();
- const int temp_effect = get_weapon_brand(weapon);
-
- set_item_ego_type(weapon, OBJ_WEAPONS, SPWPN_NORMAL);
- const char *msg = nullptr;
-
- switch (temp_effect)
- {
- case SPWPN_VORPAL:
- if (get_vorpal_type(weapon) == DVORP_SLICING)
- msg = " seems blunter.";
- else
- msg = " feels lighter.";
- break;
- case SPWPN_FLAME:
- case SPWPN_FLAMING:
- msg = " goes out.";
- break;
- case SPWPN_FREEZING:
- msg = " stops glowing.";
- break;
- case SPWPN_FROST:
- msg = "'s frost melts away.";
- break;
- case SPWPN_VENOM:
- msg = " stops dripping with poison.";
- break;
- case SPWPN_DRAINING:
- msg = " stops crackling.";
- break;
- case SPWPN_DISTORTION:
- msg = " seems straighter.";
- break;
- case SPWPN_PAIN:
- msg = " seems less pained.";
- break;
- case SPWPN_CHAOS:
- msg = " seems more stable.";
- break;
- case SPWPN_ELECTROCUTION:
- msg = " stops emitting sparks.";
- break;
- case SPWPN_HOLY_WRATH:
- msg = "'s light goes out.";
- break;
- case SPWPN_ANTIMAGIC:
- msg = " stops repelling magic.";
- calc_mp();
- break;
- default:
- msg = " seems inexplicably less special.";
- break;
- }
-
- mprf(MSGCH_DURATION, "%s%s", weapon.name(DESC_YOUR).c_str(), msg);
- you.wield_change = true;
- }
- }
-
- // FIXME: [ds] Remove this once we've ensured durations can never go < 0?
- if (you.duration[DUR_TRANSFORMATION] <= 0
- && you.form != TRAN_NONE)
- {
- you.duration[DUR_TRANSFORMATION] = 1;
- }
-
- // Vampire bat transformations are permanent (until ended).
- if (you.species != SP_VAMPIRE || you.form != TRAN_BAT
- || you.duration[DUR_TRANSFORMATION] <= 5 * BASELINE_DELAY)
- {
- if (_decrement_a_duration(DUR_TRANSFORMATION, delay, NULL, random2(3),
- "Your transformation is almost over."))
- {
- untransform();
- }
- }
-
- // Must come after transformation duration.
- _decrement_a_duration(DUR_BREATH_WEAPON, delay,
- "You have got your breath back.", 0, NULL,
- MSGCH_RECOVERY);
-
- if (you.attribute[ATTR_SWIFTNESS] >= 0)
- {
- if (_decrement_a_duration(DUR_SWIFTNESS, delay,
- "You feel sluggish.", coinflip(),
- "You start to feel a little slower."))
- {
- // Start anti-swiftness.
- you.duration[DUR_SWIFTNESS] = you.attribute[ATTR_SWIFTNESS];
- you.attribute[ATTR_SWIFTNESS] = -1;
- }
- }
- else
- {
- if (_decrement_a_duration(DUR_SWIFTNESS, delay,
- "You no longer feel sluggish.", coinflip(),
- "You start to feel a little faster."))
- {
- you.attribute[ATTR_SWIFTNESS] = 0;
- }
- }
-
- _decrement_a_duration(DUR_RESISTANCE, delay,
- "Your resistance to elements expires.", coinflip(),
- "You start to feel less resistant.");
-
- if (_decrement_a_duration(DUR_PHASE_SHIFT, delay,
- "You are firmly grounded in the material plane once more.",
- coinflip(),
- "You feel closer to the material plane."))
- {
- you.redraw_evasion = true;
- }
-
- _decrement_a_duration(DUR_POWERED_BY_DEATH, delay,
- "You feel less regenerative.");
-
- _decrement_a_duration(DUR_TELEPATHY, delay, "You feel less empathic.");
-
- if (_decrement_a_duration(DUR_CONDENSATION_SHIELD, delay,
- "Your icy shield evaporates.",
- coinflip(),
- "Your icy shield starts to melt."))
- {
- you.redraw_armour_class = true;
- }
-
- if (_decrement_a_duration(DUR_MAGIC_SHIELD, delay,
- "Your magical shield disappears."))
- {
- you.redraw_armour_class = true;
- }
-
- if (_decrement_a_duration(DUR_STONESKIN, delay, "Your skin feels tender."))
- you.redraw_armour_class = true;
-
- if (_decrement_a_duration(DUR_TELEPORT, delay))
- {
- you_teleport_now(true);
- untag_followers();
- }
-
- _decrement_a_duration(DUR_CONTROL_TELEPORT, delay,
- "You feel uncertain.", coinflip(),
- "You start to feel a little uncertain.");
-
- if (_decrement_a_duration(DUR_DEATH_CHANNEL, delay,
- "Your unholy channel expires.", coinflip(),
- "Your unholy channel is weakening."))
- {
- you.attribute[ATTR_DIVINE_DEATH_CHANNEL] = 0;
- }
-
- _decrement_a_duration(DUR_STEALTH, delay, "You feel less stealthy.");
-
- if (_decrement_a_duration(DUR_INVIS, delay, NULL,
- coinflip(), "You flicker for a moment."))
- {
- if (you.invisible())
- mprf(MSGCH_DURATION, "You feel more conspicuous.");
- else
- mprf(MSGCH_DURATION, "You flicker back into view.");
- you.attribute[ATTR_INVIS_UNCANCELLABLE] = 0;
- }
-
- _decrement_a_duration(DUR_CONF, delay, "You feel less confused.");
- _decrement_a_duration(DUR_LOWERED_MR, delay, "You feel less vulnerable to hostile enchantments.");
- _decrement_a_duration(DUR_SLIMIFY, delay, "You feel less slimy.",
- coinflip(), "Your slime is starting to congeal.");
- if (_decrement_a_duration(DUR_QUAD_DAMAGE, delay, NULL, 0,
- "Quad Damage is wearing off."))
- {
- invalidate_agrid(true);
- }
- _decrement_a_duration(DUR_MIRROR_DAMAGE, delay,
- "Your dark mirror aura disappears.");
- if (_decrement_a_duration(DUR_HEROISM, delay,
- "You feel like a meek peon again."))
- {
- you.redraw_evasion = true;
- you.redraw_armour_class = true;
- }
- _decrement_a_duration(DUR_FINESSE, delay, "Your hands slow down.");
-
- _decrement_a_duration(DUR_CONFUSING_TOUCH, delay,
- ((string("Your ") + you.hand_name(true)) +
- " stop glowing.").c_str());
-
- _decrement_a_duration(DUR_SURE_BLADE, delay,
- "The bond with your blade fades away.");
-
- _decrement_a_duration(DUR_FORESTED, delay,
- "Space becomes stable.");
-
- if (_decrement_a_duration(DUR_MESMERISED, delay,
- "You break out of your daze.",
- 0, NULL, MSGCH_RECOVERY))
- {
- you.clear_beholders();
- }
-
- _decrement_a_duration(DUR_MESMERISE_IMMUNE, delay);
-
- if (_decrement_a_duration(DUR_AFRAID, delay,
- "Your fear fades away.",
- 0, NULL, MSGCH_RECOVERY))
- {
- you.clear_fearmongers();
- }
-
- _decrement_a_duration(DUR_FROZEN, delay,
- "The ice encasing you melts away.",
- 0, NULL, MSGCH_RECOVERY);
-
- dec_slow_player(delay);
- dec_exhaust_player(delay);
- dec_haste_player(delay);
-
- if (you.duration[DUR_LIQUEFYING] && !you.stand_on_solid_ground())
- you.duration[DUR_LIQUEFYING] = 1;
-
- if (_decrement_a_duration(DUR_LIQUEFYING, delay,
- "The ground is no longer liquid beneath you."))
- {
- invalidate_agrid();
- }
-
- if (_decrement_a_duration(DUR_MIGHT, delay,
- "You feel a little less mighty now."))
- {
- notify_stat_change(STAT_STR, -5, true, "might running out");
- }
-
- if (_decrement_a_duration(DUR_AGILITY, delay,
- "You feel a little less agile now."))
- {
- notify_stat_change(STAT_DEX, -5, true, "agility running out");
- }
-
- if (_decrement_a_duration(DUR_BRILLIANCE, delay,
- "You feel a little less clever now."))
- {
- notify_stat_change(STAT_INT, -5, true, "brilliance running out");
- }
-
- if (you.duration[DUR_BERSERK]
- && (_decrement_a_duration(DUR_BERSERK, delay)
- || you.hunger + 100 <= HUNGER_STARVING + BERSERK_NUTRITION))
- {
- mpr("You are no longer berserk.");
- you.duration[DUR_BERSERK] = 0;
-
- // Sometimes berserk leaves us physically drained.
- //
- // Chance of passing out:
- // - mutation gives a large plus in order to try and
- // avoid the mutation being a "death sentence" to
- // certain characters.
-
- if (you.berserk_penalty != NO_BERSERK_PENALTY
- && one_chance_in(10 + player_mutation_level(MUT_BERSERK) * 25))
- {
- // Note the beauty of Trog! They get an extra save that's at
- // the very least 20% and goes up to 100%.
- if (you_worship(GOD_TROG)
- && !player_under_penance()
- && x_chance_in_y(you.piety, piety_breakpoint(5)))
- {
- mpr("Trog's vigour flows through your veins.");
- }
- else
- {
- mprf(MSGCH_WARN, "You pass out from exhaustion.");
- you.increase_duration(DUR_PARALYSIS, roll_dice(1,4));
- you.stop_constricting_all();
- }
- }
-
- if (!you.duration[DUR_PARALYSIS] && !you.petrified())
- mprf(MSGCH_WARN, "You are exhausted.");
-
- if (you.species == SP_LAVA_ORC)
- mpr("You feel less hot-headed.");
-
- // This resets from an actual penalty or from NO_BERSERK_PENALTY.
- you.berserk_penalty = 0;
-
- int dur = 12 + roll_dice(2, 12);
- // For consistency with slow give exhaustion 2 times the nominal
- // duration.
- you.increase_duration(DUR_EXHAUSTED, dur * 2);
-
- notify_stat_change(STAT_STR, -5, true, "berserk running out");
-
- // Don't trigger too many hints mode messages.
- const bool hints_slow = Hints.hints_events[HINT_YOU_ENCHANTED];
- Hints.hints_events[HINT_YOU_ENCHANTED] = false;
-
- slow_player(dur);
-
- make_hungry(BERSERK_NUTRITION, true);
- you.hunger = max(HUNGER_STARVING - 100, you.hunger);
-
- // 1KB: No berserk healing.
- set_hp((you.hp + 1) * 2 / 3);
- calc_hp();
-
- learned_something_new(HINT_POSTBERSERK);
- Hints.hints_events[HINT_YOU_ENCHANTED] = hints_slow;
- you.redraw_quiver = true; // Can throw again.
- }
-
- if (_decrement_a_duration(DUR_CORONA, delay) && !you.backlit())
- mprf(MSGCH_DURATION, "You are no longer glowing.");
-
- // Leak piety from the piety pool into actual piety.
- // Note that changes of religious status without corresponding actions
- // (killing monsters, offering items, ...) might be confusing for characters
- // of other religions.
- // For now, though, keep information about what happened hidden.
- if (you.piety < MAX_PIETY && you.duration[DUR_PIETY_POOL] > 0
- && one_chance_in(5))
- {
- you.duration[DUR_PIETY_POOL]--;
- gain_piety(1, 1, true);
-
-#if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_SACRIFICE) || defined(DEBUG_PIETY)
- mprf(MSGCH_DIAGNOSTICS, "Piety increases by 1 due to piety pool.");
-
- if (you.duration[DUR_PIETY_POOL] == 0)
- mprf(MSGCH_DIAGNOSTICS, "Piety pool is now empty.");
-#endif
- }
-
- if (you.duration[DUR_DISJUNCTION])
- {
- disjunction();
- _decrement_a_duration(DUR_DISJUNCTION, delay,
- "The translocation energy dissipates.");
- if (!you.duration[DUR_DISJUNCTION])
- invalidate_agrid(true);
- }
-
- if (_decrement_a_duration(DUR_TORNADO_COOLDOWN, delay,
- "The winds around you calm down."))
- {
- remove_tornado_clouds(MID_PLAYER);
- }
- // Should expire before flight.
- if (you.duration[DUR_TORNADO])
- {
- tornado_damage(&you, min(delay, you.duration[DUR_TORNADO]));
- _decrement_a_duration(DUR_TORNADO, delay,
- "The winds around you start to calm down.");
- if (!you.duration[DUR_TORNADO])
- you.duration[DUR_TORNADO_COOLDOWN] = random_range(25, 35);
- }
-
- if (you.duration[DUR_FLIGHT])
- {
- if (!you.permanent_flight())
- {
- if (_decrement_a_duration(DUR_FLIGHT, delay, nullptr, random2(6),
- "You are starting to lose your buoyancy."))
- {
- land_player();
- }
- }
- else if ((you.duration[DUR_FLIGHT] -= delay) <= 0)
- {
- // Just time out potions/spells/miscasts.
- you.attribute[ATTR_FLIGHT_UNCANCELLABLE] = 0;
- you.duration[DUR_FLIGHT] = 0;
- }
- }
-
- if (you.rotting > 0)
- {
- // XXX: Mummies have an ability (albeit an expensive one) that
- // can fix rotted HPs now... it's probably impossible for them
- // to even start rotting right now, but that could be changed. - bwr
- // It's not normal biology, so Cheibriados won't help.
- if (you.species == SP_MUMMY)
- you.rotting = 0;
- else if (x_chance_in_y(you.rotting, 20)
- && !you.duration[DUR_DEATHS_DOOR])
- {
- mprf(MSGCH_WARN, "You feel your flesh rotting away.");
- rot_hp(1);
- you.rotting--;
- }
- }
-
- // ghoul rotting is special, but will deduct from you.rotting
- // if it happens to be positive - because this is placed after
- // the "normal" rotting check, rotting attacks can be somewhat
- // more painful on ghouls - reversing order would make rotting
- // attacks somewhat less painful, but that seems wrong-headed {dlb}:
- if (you.species == SP_GHOUL)
- {
- int resilience = 400;
-
- if (you_worship(GOD_CHEIBRIADOS) && you.piety >= piety_breakpoint(0))
- resilience = resilience * 3 / 2;
-
- // Faster rotting when hungry.
- if (you.hunger_state < HS_SATIATED)
- resilience >>= HS_SATIATED - you.hunger_state;
-
- if (one_chance_in(resilience))
- {
- dprf("rot rate: 1/%d", resilience);
- mprf(MSGCH_WARN, "You feel your flesh rotting away.");
- rot_hp(1);
- if (you.rotting > 0)
- you.rotting--;
- }
- }
-
- if (you.duration[DUR_DEATHS_DOOR])
- {
- if (you.hp > allowed_deaths_door_hp())
- {
- set_hp(allowed_deaths_door_hp());
- you.redraw_hit_points = true;
- }
-
- if (_decrement_a_duration(DUR_DEATHS_DOOR, delay,
- "Your life is in your own hands again!",
- random2(6),
- "Your time is quickly running out!"))
- {
- you.increase_duration(DUR_EXHAUSTED, roll_dice(1,3));
- }
- }
-
- if (_decrement_a_duration(DUR_DIVINE_STAMINA, delay))
- zin_remove_divine_stamina();
-
- if (_decrement_a_duration(DUR_DIVINE_VIGOUR, delay))
- elyvilon_remove_divine_vigour();
-
- _decrement_a_duration(DUR_REPEL_STAIRS_MOVE, delay);
- _decrement_a_duration(DUR_REPEL_STAIRS_CLIMB, delay);
-
- _decrement_a_duration(DUR_COLOUR_SMOKE_TRAIL, 1);
-
- if (_decrement_a_duration(DUR_SCRYING, delay,
- "Your astral sight fades away."))
- {
- you.xray_vision = false;
- }
-
- _decrement_a_duration(DUR_LIFESAVING, delay,
- "Your divine protection fades away.");
-
- if (_decrement_a_duration(DUR_DARKNESS, delay,
- "The ambient light returns to normal.")
- || (you.duration[DUR_DARKNESS] && you.haloed()))
- {
- if (you.duration[DUR_DARKNESS])
- {
- you.duration[DUR_DARKNESS] = 0;
- mpr("The divine light dispels your darkness!");
- }
- update_vision_range();
- }
-
- _decrement_a_duration(DUR_SHROUD_OF_GOLUBRIA, delay,
- "Your shroud unravels.",
- 0,
- "Your shroud begins to fray at the edges.");
-
- _decrement_a_duration(DUR_INFUSION, delay,
- "Your attacks are no longer magically infused.",
- 0,
- "You are feeling less magically infused.");
-
- _decrement_a_duration(DUR_SONG_OF_SLAYING, delay,
- "Your song has ended.",
- 0,
- "Your song is almost over.");
-
- _decrement_a_duration(DUR_SENTINEL_MARK, delay,
- "The sentinel's mark upon you fades away.");
-
- _decrement_a_duration(DUR_WEAK, delay,
- "Your attacks no longer feel as feeble.");
-
- _decrement_a_duration(DUR_DIMENSION_ANCHOR, delay,
- "You are no longer firmly anchored in space.");
-
- _decrement_a_duration(DUR_SICKENING, delay);
-
- _decrement_a_duration(DUR_SAP_MAGIC, delay,
- "Your magic seems less tainted.");
-
- if (!you.duration[DUR_SAP_MAGIC])
- {
- _decrement_a_duration(DUR_MAGIC_SAPPED, delay,
- "You feel more in control of your magic.");
- }
-
- _decrement_a_duration(DUR_ANTIMAGIC, delay,
- "You regain control over your magic.");
-
- _decrement_a_duration(DUR_WATER_HOLD_IMMUNITY, delay);
- if (you.duration[DUR_WATER_HOLD])
- handle_player_drowning(delay);
-
- if (you.duration[DUR_FLAYED])
- {
- bool near_ghost = false;
- for (monster_iterator mi; mi; ++mi)
- {
- if (mi->type == MONS_FLAYED_GHOST && !mi->wont_attack()
- && you.see_cell(mi->pos()))
- {
- near_ghost = true;
- break;
- }
- }
- if (!near_ghost)
- {
- if (_decrement_a_duration(DUR_FLAYED, delay))
- heal_flayed_effect(&you);
- }
- else if (you.duration[DUR_FLAYED] < 80)
- you.duration[DUR_FLAYED] += div_rand_round(50, delay);
- }
-
- _decrement_a_duration(DUR_RETCHING, delay, "Your fit of retching subsides.");
-
- if (you.duration[DUR_TOXIC_RADIANCE])
- {
- int ticks = (you.duration[DUR_TOXIC_RADIANCE] / 10)
- - ((you.duration[DUR_TOXIC_RADIANCE] - delay) / 10);
- toxic_radiance_effect(&you, ticks);
- _decrement_a_duration(DUR_TOXIC_RADIANCE, delay,
- "Your toxic aura wanes.");
- }
-
- if (you.duration[DUR_RECITE] && _check_recite())
- {
- const int old_recite =
- (you.duration[DUR_RECITE] + BASELINE_DELAY - 1) / BASELINE_DELAY;
- _decrement_a_duration(DUR_RECITE, delay);
- const int new_recite =
- (you.duration[DUR_RECITE] + BASELINE_DELAY - 1) / BASELINE_DELAY;
- if (old_recite != new_recite)
- _handle_recitation(new_recite);
- }
-
- if (you.duration[DUR_GRASPING_ROOTS])
- check_grasping_roots(&you);
-
- if (you.attribute[ATTR_NEXT_RECALL_INDEX] > 0)
- do_recall(delay);
-
- _decrement_a_duration(DUR_SLEEP_IMMUNITY, delay);
-
- _decrement_a_duration(DUR_FIRE_VULN, delay,
- "You feel less vulnerable to fire.");
-
- _decrement_a_duration(DUR_POISON_VULN, delay,
- "You feel less vulnerable to poison.");
-
- if (_decrement_a_duration(DUR_PORTAL_PROJECTILE, delay,
- "You are no longer teleporting projectiles to their destination."))
- {
- you.attribute[ATTR_PORTAL_PROJECTILE] = 0;
- }
-
- _decrement_a_duration(DUR_DRAGON_CALL_COOLDOWN, delay,
- "You can once more reach out to the dragon horde.");
-
- if (you.duration[DUR_DRAGON_CALL])
- {
- do_dragon_call(delay);
- if (_decrement_a_duration(DUR_DRAGON_CALL, delay,
- "The roar of the dragon horde subsides."))
- {
- you.duration[DUR_DRAGON_CALL_COOLDOWN] = random_range(150, 250);
- }
-
- }
-
- if (you.duration[DUR_ABJURATION_AURA])
- {
- do_aura_of_abjuration(delay);
- _decrement_a_duration(DUR_ABJURATION_AURA, delay,
- "Your aura of abjuration expires.");
- }
-
- dec_elixir_player(delay);
-
- if (!env.sunlight.empty())
- process_sunlights();
-}
-
static void _check_banished()
{
if (you.banished)
@@ -3141,70 +2247,6 @@ static void _check_sanctuary()
decrease_sanctuary_radius();
}
-// cjo: Handles player hp and mp regeneration. If the counter you.hit_points_regeneration
-// is over 100, a loop restores 1 hp and decreases the counter by 100 (so you can regen
-// more than 1 hp per turn). If the counter is below 100, it is increased by a variable
-// calculated from delay, BASELINE_DELAY, and your regeneration rate. MP regeneration happens
-// similarly, but the countup depends on delay, BASELINE_DELAY, and you.max_magic_points
-static void _regenerate_hp_and_mp(int delay)
-{
- if (crawl_state.disables[DIS_PLAYER_REGEN])
- return;
-
- // XXX: using an int tmp to fix the fact that hit_points_regeneration
- // is only an unsigned char and is thus likely to overflow. -- bwr
- int tmp = you.hit_points_regeneration;
-
- if (you.hp < you.hp_max && !you.duration[DUR_DEATHS_DOOR])
- {
- const int base_val = player_regen();
- tmp += div_rand_round(base_val * delay, BASELINE_DELAY);
- }
-
- while (tmp >= 100)
- {
- // at low mp, "mana link" restores mp in place of hp
- if (you.mutation[MUT_MANA_LINK]
- && !x_chance_in_y(you.magic_points, you.max_magic_points))
- {
- inc_mp(1);
- }
- else // standard hp regeneration
- inc_hp(1);
- tmp -= 100;
- }
-
- ASSERT_RANGE(tmp, 0, 100);
- you.hit_points_regeneration = tmp;
-
- // XXX: Don't let DD use guardian spirit for free HP, since their
- // damage shaving is enough. (due, dpeg)
- if (you.spirit_shield() && you.species == SP_DEEP_DWARF)
- return;
-
- // XXX: Doing the same as the above, although overflow isn't an
- // issue with magic point regeneration, yet. -- bwr
- tmp = you.magic_points_regeneration;
-
- if (you.magic_points < you.max_magic_points)
- {
- const int base_val = 7 + you.max_magic_points / 2;
- int mp_regen_countup = div_rand_round(base_val * delay, BASELINE_DELAY);
- if (you.mutation[MUT_MANA_REGENERATION])
- mp_regen_countup *= 2;
- tmp += mp_regen_countup;
- }
-
- while (tmp >= 100)
- {
- inc_mp(1);
- tmp -= 100;
- }
-
- ASSERT_RANGE(tmp, 0, 100);
- you.magic_points_regeneration = tmp;
-}
-
static void _update_mold_state(const coord_def & pos)
{
if (coinflip())
@@ -3252,208 +2294,6 @@ static void _update_mold()
}
}
-// For worn items; weapons do this on melee attacks.
-static void _check_equipment_conducts()
-{
- if (you_worship(GOD_DITHMENOS) && one_chance_in(10))
- {
- bool illuminating = false, fiery = false;
- const item_def* item;
- for (int i = EQ_MIN_ARMOUR; i < NUM_EQUIP; i++)
- {
- item = you.slot_item(static_cast<equipment_type>(i));
- if (!item)
- continue;
- if (is_illuminating_item(*item))
- illuminating = true;
- else if (is_fiery_item(*item))
- fiery = true;
- if (illuminating && fiery)
- break;
- }
- if (illuminating)
- did_god_conduct(DID_ILLUMINATE, 1, true);
- else if (fiery)
- did_god_conduct(DID_FIRE, 1, true);
- }
-}
-
-static void _player_reacts()
-{
- search_around();
-
- stealth = check_stealth();
-
-#ifdef DEBUG_STEALTH
- // Too annoying for regular diagnostics.
- mprf(MSGCH_DIAGNOSTICS, "stealth: %d", stealth);
-#endif
-
- if (you.attribute[ATTR_SHADOWS])
- shadow_lantern_effect();
-
- if (you.species == SP_LAVA_ORC)
- temperature_check();
-
- if (player_mutation_level(MUT_DEMONIC_GUARDIAN))
- check_demonic_guardian();
-
- _check_equipment_conducts();
-
- if (you.unrand_reacts != 0)
- unrand_reacts();
-
- // Handle sound-dependent effects that are silenced
- if (silenced(you.pos()))
- {
- if (you.duration[DUR_SONG_OF_SLAYING])
- {
- mpr("The silence causes your song to end.");
- _decrement_a_duration(DUR_SONG_OF_SLAYING, you.duration[DUR_SONG_OF_SLAYING]);
- }
- }
-
- // Singing makes a continuous noise
- if (you.duration[DUR_SONG_OF_SLAYING])
- noisy(8, you.pos());
-
- if (one_chance_in(10))
- {
- const int teleportitis_level = player_teleport();
- // this is instantaneous
- if (teleportitis_level > 0 && one_chance_in(100 / teleportitis_level))
- {
- if (teleportitis_level >= 8)
- you_teleport_now(true);
- else
- you_teleport_now(true, false, teleportitis_level * 5);
- }
- else if (player_in_branch(BRANCH_ABYSS) && one_chance_in(80)
- && (!map_masked(you.pos(), MMT_VAULT) || one_chance_in(3)))
- {
- mprf(MSGCH_BANISHMENT, "You are suddenly pulled into a different region of the Abyss!");
- you_teleport_now(false); // to new area of the Abyss
-
- // It's effectively a new level, make a checkpoint save so eventual
- // crashes lose less of the player's progress (and fresh new bad
- // mutations).
- if (!crawl_state.disables[DIS_SAVE_CHECKPOINTS])
- save_game(false);
- }
- else if (you.form == TRAN_WISP && !you.stasis())
- random_blink(false);
- }
-
- actor_apply_cloud(&you);
-
- if (env.level_state & LSTATE_SLIMY_WALL)
- slime_wall_damage(&you, you.time_taken);
-
- // Icy shield and armour melt over lava.
- if (grd(you.pos()) == DNGN_LAVA)
- expose_player_to_element(BEAM_LAVA);
-
- you.update_beholders();
- you.update_fearmongers();
-
- _decrement_durations();
- you.handle_constriction();
-
- // increment constriction durations
- you.accum_has_constricted();
-
- int capped_time = you.time_taken;
- if (you.walking && capped_time > BASELINE_DELAY)
- capped_time = BASELINE_DELAY;
-
- int food_use = player_hunger_rate();
- food_use = div_rand_round(food_use * capped_time, BASELINE_DELAY);
-
- if (food_use > 0 && you.hunger > 0)
- {
- make_hungry(food_use, true);
- if (you.duration[DUR_AMBROSIA])
- {
- if (food_use > you.duration[DUR_AMBROSIA])
- food_use = you.duration[DUR_AMBROSIA];
- you.duration[DUR_AMBROSIA] -= food_use;
- inc_mp(food_use);
- }
- }
-
- _regenerate_hp_and_mp(capped_time);
- dec_disease_player(capped_time);
- if (you.duration[DUR_POISONING])
- handle_player_poison(capped_time);
- recharge_rods(you.time_taken, false);
-
- // Reveal adjacent mimics.
- for (adjacent_iterator ai(you.pos(), false); ai; ++ai)
- discover_mimic(*ai);
-
- // Player stealth check.
- seen_monsters_react();
-
- update_stat_zero();
-
- // XOM now ticks from here, to increase his reaction time to tension.
- if (you_worship(GOD_XOM))
- xom_tick();
-}
-
-
-/**
- * Player reactions after monster and cloud activities in the turn are finished.
- */
-static void _player_reacts_to_monsters()
-{
- // In case Maurice managed to steal a needed item for example.
- if (!you_are_delayed())
- update_can_train();
-
- if (you.duration[DUR_FIRE_SHIELD] > 0)
- manage_fire_shield(you.time_taken);
-
- check_monster_detect();
-
- if ((you_worship(GOD_ASHENZARI) && !player_under_penance())
- || you.mutation[MUT_JELLY_GROWTH])
- {
- detect_items(-1);
- }
-
- if (you.duration[DUR_TELEPATHY])
- detect_creatures(1 + you.duration[DUR_TELEPATHY] /
- (2 * BASELINE_DELAY), true);
-
- // We have to do the messaging here, because a simple wand of flame will
- // call _maybe_melt_player_enchantments twice. It also avoid duplicate
- // messages when melting because of several heating sources.
- string what;
- if (you.props.exists(MELT_ARMOUR_KEY))
- {
- what = "armour";
- you.props.erase(MELT_ARMOUR_KEY);
- }
-
- if (you.props.exists("melt_shield"))
- {
- if (what != "")
- what += " and ";
- what += "shield";
- you.props.erase("melt_shield");
- }
-
- if (what != "")
- mprf(MSGCH_DURATION, "The heat melts your icy %s.", what.c_str());
-
- handle_starvation();
- _decrement_paralysis(you.time_taken);
- _decrement_petrification(you.time_taken);
- if (_decrement_a_duration(DUR_SLEEP, you.time_taken))
- you.awake();
-}
-
static void _update_golubria_traps()
{
vector<coord_def> traps = find_golubria_on_level();
@@ -3518,7 +2358,7 @@ void world_reacts()
run_environment_effects();
if (!crawl_state.game_is_arena())
- _player_reacts();
+ player_reacts();
abyss_morph(you.time_taken);
apply_noises();
@@ -3577,7 +2417,7 @@ void world_reacts()
}
}
if (!crawl_state.game_is_arena())
- _player_reacts_to_monsters();
+ player_reacts_to_monsters();
viewwindow();
@@ -4397,15 +3237,6 @@ static void _do_searing_ray()
end_searing_ray();
}
-static void _extract_manticore_spikes()
-{
- if (_decrement_a_duration(DUR_BARBS, you.time_taken,
- "You carefully extract the manticore spikes from your body."))
- {
- you.attribute[ATTR_BARBS_POW] = 0;
- }
-}
-
// Called when the player moves by walking/running. Also calls attack
// function etc when necessary.
static void _move_player(int move_x, int move_y)
@@ -4767,10 +3598,7 @@ static void _move_player(coord_def move)
// Sometimes decrease duration even when we move.
if (one_chance_in(3))
- {
- _decrement_a_duration(DUR_BARBS, you.time_taken,
- "The manticore spikes snap loose.");
- }
+ extract_manticore_spikes("The manticore spikes snap loose.");
}
if (delay_is_run(current_delay_action()))