summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-02 07:59:12 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-02 07:59:12 +0000
commit07eadf8e4cf3dd61fa66d194720143685ab84174 (patch)
tree60ca13a09c47d9c6a7b0d871bac374f057134e85
parentd03bcac5636625a61db20500a51418227316b34b (diff)
downloadcrawl-ref-07eadf8e4cf3dd61fa66d194720143685ab84174.tar.gz
crawl-ref-07eadf8e4cf3dd61fa66d194720143685ab84174.zip
Merge r7717 and r7718: improvements to interrupted butchery behaviour.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup-0.4@7719 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/docs/options_guide.txt10
-rw-r--r--crawl-ref/settings/init.txt2
-rw-r--r--crawl-ref/source/acr.cc17
-rw-r--r--crawl-ref/source/delay.cc185
-rw-r--r--crawl-ref/source/delay.h2
-rw-r--r--crawl-ref/source/externs.h4
-rw-r--r--crawl-ref/source/fight.cc14
-rw-r--r--crawl-ref/source/files.cc13
-rw-r--r--crawl-ref/source/initfile.cc4
-rw-r--r--crawl-ref/source/spells3.cc11
10 files changed, 194 insertions, 68 deletions
diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt
index bbbde61be6..15760b7562 100644
--- a/crawl-ref/docs/options_guide.txt
+++ b/crawl-ref/docs/options_guide.txt
@@ -58,7 +58,7 @@ The contents of this text are:
4-i Command Enhancements.
auto_list, easy_open, easy_unequip, easy_confirm,
allow_self_target, easy_butcher, always_confirm_butcher,
- swap_when_safe, easy_quit_item_prompts, easy_exit_menu,
+ prompt_for_swap, easy_quit_item_prompts, easy_exit_menu,
sort_menus
4-j Message and Display Improvements.
hp_warning, mp_warning, hp_colour, mp_colour,
@@ -990,10 +990,12 @@ always_confirm_butcher = false
one corpse on the square. If there are multiple corpses on a
square, you will always be prompted, regardless of this option.
-swap_when_safe = true
+prompt_for_swap = true
If both this and easy_butcher are true, then if an auto-switch
- butchery is interrupted, the auto-switch will be reversed as
- soon as you are safe again.
+ butchery is interrupted by a hostile monster, the game will
+ ask if you wish to switch back to your weapon. It will also
+ prompt you if after butchery is interupted you teleport or
+ change levels and find yourself near hostile monsters.
easy_quit_item_prompts = true
Setting this option to true allows the quitting of item listing
diff --git a/crawl-ref/settings/init.txt b/crawl-ref/settings/init.txt
index a483f0096a..ecea500c90 100644
--- a/crawl-ref/settings/init.txt
+++ b/crawl-ref/settings/init.txt
@@ -206,7 +206,7 @@ include = travel_stoppers.txt
# allow_self_target = (yes | no | prompt)
# easy_butcher = false
# always_confirm_butcher = true
-# swap_when_safe = false
+# prompt_for_swap = false
# easy_quit_item_prompts = false
# easy_exit_menu = false
# sort_menus = pickup: true : basename, qualname, curse, qty
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index cad9eecef1..7c561a11a5 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1469,23 +1469,6 @@ static void _input()
if (need_to_autoinscribe())
autoinscribe();
- // XXX: Is there some smart way to avoid autoswitching back if we're
- // just about to continue butchering?
- if (!you.turn_is_over && player_feels_safe
- && you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED])
- {
- // Decrease value by 1. (0 means attribute is false, 1 = a, 2 = b, ...)
- int weap = you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] - 1;
- if (weap == ENDOFPACK)
- weap = -1;
-
- weapon_switch(weap);
- print_stats();
-
- // To prevent spam in case the weapon can't be switched back to.
- you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
- }
-
handle_delay();
_center_cursor();
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 2a97292056..5aa664fc53 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -308,6 +308,10 @@ void start_delay( delay_type type, int turns, int parm1, int parm2 )
delay.parm2 = parm2;
delay.started = false;
+ // Paranoia
+ if (type == DELAY_WEAPON_SWAP)
+ you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
+
// Handle zero-turn delays (possible with butchering).
if (turns == 0)
{
@@ -345,8 +349,9 @@ void stop_delay( bool stop_stair_travel )
case DELAY_BOTTLE_BLOOD:
case DELAY_OFFER_CORPSE:
{
+ // Corpse keeps track of work in plus2 field, see handle_delay(). -- bwr
bool multiple_corpses = false;
- bool butcher_swap_warn = false;
+ bool butcher_swap_setup = false;
int butcher_swap_weapon = 0;
for (unsigned int i = 1; i < you.delay_queue.size(); i++)
@@ -360,16 +365,16 @@ void stop_delay( bool stop_stair_travel )
else if (you.delay_queue[i].type == DELAY_WEAPON_SWAP)
{
butcher_swap_weapon = you.delay_queue[i].parm1;
- butcher_swap_warn = true;
+ butcher_swap_setup = true;
break;
}
else
break;
}
- if (!butcher_swap_warn && delays_cleared[DELAY_WEAPON_SWAP] > 0)
+ if (!butcher_swap_setup && delays_cleared[DELAY_WEAPON_SWAP] > 0)
{
- butcher_swap_warn = true;
+ butcher_swap_setup = true;
butcher_swap_weapon = cleared_delays_parm1[DELAY_WEAPON_SWAP];
}
@@ -378,38 +383,27 @@ void stop_delay( bool stop_stair_travel )
delay.type == DELAY_BOTTLE_BLOOD ? "bottling blood from"
: "sacrificing");
- // Corpse keeps track of work in plus2 field, see handle_delay(). -- bwr
- if (butcher_swap_warn)
- {
- std::string weapon;
- if (butcher_swap_weapon == -1)
- weapon = "unarmed combat";
- else
- {
- weapon = "your " +
- you.inv[butcher_swap_weapon].name(DESC_BASENAME);
- }
- mprf(MSGCH_WARN, "You stop %s the corpse%s; not switching "
- "back to %s.", butcher_verb.c_str(),
- (multiple_corpses ? "s" : ""), weapon.c_str());
+ mprf("You stop %s the corpse%s.", butcher_verb.c_str(),
+ multiple_corpses ? "s" : "");
- if (Options.swap_when_safe)
- {
- // Use weapon slot + 1, so weapon slot 'a' (== 0) doesn't
- // return false when checking if
- // you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED].
- you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED]
- = (butcher_swap_weapon == -1 ? ENDOFPACK
- : butcher_swap_weapon) + 1;
- }
- }
- else
+ _pop_delay();
+
+ if (butcher_swap_setup)
{
- mprf("You stop %s the corpse%s.", butcher_verb.c_str(),
- multiple_corpses ? "s" : "");
+ // Use weapon slot + 1, so weapon slot 'a' (== 0) doesn't
+ // return false when checking if
+ // you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED].
+ you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED]
+ = (butcher_swap_weapon == -1 ? ENDOFPACK
+ : butcher_swap_weapon) + 1;
+
+ // Possibly prompt if user wants to switch back from
+ // butchering tool in order to use their normal weapon to
+ // fight the interrupting monster.
+ if (!i_feel_safe())
+ handle_interrupted_swap(false, true);
}
- _pop_delay();
break;
}
case DELAY_MEMORISE:
@@ -545,6 +539,89 @@ void stop_butcher_delay()
}
}
+static bool _is_butcher_delay(int delay)
+{
+ return (delay == DELAY_BUTCHER || delay == DELAY_BOTTLE_BLOOD
+ || delay == DELAY_OFFER_CORPSE);
+}
+
+void handle_interrupted_swap(bool swap_if_safe, bool force_unsafe)
+{
+ if (!you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED]
+ || !you_tran_can_wear(EQ_WEAPON) || you.cannot_act())
+ {
+ return;
+ }
+
+ // Decrease value by 1. (0 means attribute is false, 1 = a, 2 = b, ...)
+ int weap = you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] - 1;
+ if (weap == ENDOFPACK)
+ weap = -1;
+
+ const bool safe = i_feel_safe() && !force_unsafe;
+ const bool prompt = Options.prompt_for_swap && !safe;
+ const delay_type delay = current_delay_action();
+
+ const char* prompt_str = "Switch back from butchering tool?";
+
+ // If we're going to prompt then update the window so the player can
+ // see what the monsters are.
+ if (prompt)
+ viewwindow(true, false);
+
+ if (delay == DELAY_WEAPON_SWAP)
+ {
+ ASSERT(!"handle_interrupted_swap() called while already swapping "
+ "weapons");
+ you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
+ return;
+ }
+ else if (!you.turn_is_over
+ && (delay == DELAY_ASCENDING_STAIRS
+ || delay == DELAY_DESCENDING_STAIRS))
+ {
+ // We just arrived on the level, let rest of function do its stuff.
+ ;
+ }
+ else if (you.turn_is_over && delay == DELAY_NOT_DELAYED)
+ {
+ // Turn is over, set up a delay to do swapping next turn.
+ if (prompt && yesno(prompt_str, false) || safe && swap_if_safe)
+ {
+ start_delay(DELAY_WEAPON_SWAP, 1, weap);
+ you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
+ }
+ return;
+ }
+ else if (delay != DELAY_NOT_DELAYED)
+ {
+ // If ATTR_WEAPON_SWAP_INTERRUPTED is set while a corpse is being
+ // butchered/bottled/offered, then fake a weapon swap delay.
+ if (_is_butcher_delay(delay)
+ && (safe || prompt && yesno(prompt_str, false)))
+ {
+ start_delay(DELAY_WEAPON_SWAP, 1, weap);
+ you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
+ }
+ return;
+ }
+
+ if (safe)
+ {
+ if (!swap_if_safe)
+ return;
+ }
+ else if (!prompt || !yesno(prompt_str, false))
+ {
+ return;
+ }
+
+ weapon_switch(weap);
+ print_stats();
+
+ you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
+}
+
bool you_are_delayed( void )
{
return (!you.delay_queue.empty());
@@ -1170,6 +1247,12 @@ static void _finish_delay(const delay_queue_item &delay)
{
autopickup();
}
+
+ // If we were interrupted while butchering (by poisonig, for
+ // example) then resumed butchering and finished, swap back from
+ // butchering tool if appropriate.
+ if (you.delay_queue.size() == 1)
+ handle_interrupted_swap(true);
}
else
{
@@ -1206,6 +1289,11 @@ static void _finish_delay(const delay_queue_item &delay)
offer_corpse(delay.parm1);
StashTrack.update_stash(); // Don't stash-track this corpse anymore.
}
+ // If we were interrupted while butchering (by poisonig, for
+ // example) then resumed butchering and finished, swap back from
+ // butchering tool if appropriate.
+ if (you.delay_queue.size() == 1)
+ handle_interrupted_swap(true);
break;
}
case DELAY_DROP_ITEM:
@@ -1645,15 +1733,16 @@ static bool _should_stop_activity(const delay_queue_item &item,
|| Options.activity_interrupts[item.type][ai]);
}
-inline static void _monster_warning(activity_interrupt_type ai,
+inline static bool _monster_warning(activity_interrupt_type ai,
const activity_interrupt_data &at,
int atype)
{
- if (ai == AI_SEE_MONSTER && is_run_delay(atype))
+ if (ai == AI_SEE_MONSTER && (is_run_delay(atype)
+ || _is_butcher_delay(atype)))
{
const monsters* mon = static_cast<const monsters*>(at.data);
if (!mon->visible())
- return;
+ return (false);
if (at.context == "already seen")
{
// Only say "comes into view" if the monster wasn't in view
@@ -1711,10 +1800,14 @@ inline static void _monster_warning(activity_interrupt_type ai,
if (Options.tutorial_left)
tutorial_first_monster(*mon);
+
+ return (true);
}
+
+ return (false);
}
-static void _paranoid_option_disable( activity_interrupt_type ai,
+static bool _paranoid_option_disable( activity_interrupt_type ai,
const activity_interrupt_data &at )
{
if (ai == AI_HIT_MONSTER || ai == AI_MONSTER_ATTACKS)
@@ -1747,7 +1840,10 @@ static void _paranoid_option_disable( activity_interrupt_type ai,
Options.tut_seen_invisible = you.num_turns;
}
}
+ return (true);
}
+
+ return (false);
}
// Returns true if any activity was stopped.
@@ -1757,7 +1853,7 @@ bool interrupt_activity( activity_interrupt_type ai,
if (_interrupts_blocked > 0)
return (false);
- _paranoid_option_disable(ai, at);
+ bool was_monst = _paranoid_option_disable(ai, at);
if (crawl_state.is_repeating_cmd())
return interrupt_cmd_repeat(ai, at);
@@ -1782,8 +1878,11 @@ bool interrupt_activity( activity_interrupt_type ai,
if (is_sanctuary(you.x_pos, you.y_pos))
return (false);
- _monster_warning(ai, at, item.type);
+ was_monst = _monster_warning(ai, at, item.type) || was_monst;
stop_delay();
+ if (was_monst)
+ handle_interrupted_swap(false, true);
+
return (true);
}
@@ -1802,8 +1901,13 @@ bool interrupt_activity( activity_interrupt_type ai,
{
if (is_run_delay( you.delay_queue[j].type ))
{
- _monster_warning(ai, at, you.delay_queue[j].type);
+ was_monst =
+ _monster_warning(ai, at, you.delay_queue[j].type)
+ || was_monst;
+
stop_delay();
+ if (was_monst)
+ handle_interrupted_swap(false, true);
return (true);
}
}
@@ -1811,6 +1915,9 @@ bool interrupt_activity( activity_interrupt_type ai,
// Non-run queued delays can be discarded without any processing.
you.delay_queue.erase( you.delay_queue.begin() + i,
you.delay_queue.end() );
+ if (was_monst)
+ handle_interrupted_swap(false, true);
+
return (true);
}
}
diff --git a/crawl-ref/source/delay.h b/crawl-ref/source/delay.h
index bffb1b8a8c..42545629bd 100644
--- a/crawl-ref/source/delay.h
+++ b/crawl-ref/source/delay.h
@@ -81,6 +81,8 @@ bool is_run_delay(int delay);
bool is_being_butchered(const item_def &item, bool just_first = true);
bool is_vampire_feeding( void );
void stop_butcher_delay();
+void handle_interrupted_swap(bool swap_if_safe = false,
+ bool force_unsafe = false);
const char *activity_interrupt_name(activity_interrupt_type ai);
activity_interrupt_type get_activity_interrupt(const std::string &);
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 922b15d9e9..0899158057 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1657,8 +1657,8 @@ public:
bool easy_butcher; // autoswap to butchering tool
bool always_confirm_butcher; // even if only one corpse
bool chunks_autopickup; // Autopickup chunks after butchering
- bool swap_when_safe; // If autoswapped butchery was interrupted,
- // swap weapon back when safe.
+ bool prompt_for_swap; // Prompt to switch back from butchering
+ // tool if hostile monsters are around.
bool list_rotten; // list slots for rotting corpses/chunks
bool default_target; // start targeting on a real target
bool autopickup_no_burden; // don't autopickup if it changes burden
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 8dfbb0aafe..676c72386a 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -3847,8 +3847,9 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
void melee_attack::mons_perform_attack_rounds()
{
- const int nrounds = atk->has_hydra_multi_attack()? atk->number : 4;
- const coord_def pos = defender->pos();
+ const int nrounds = atk->has_hydra_multi_attack() ? atk->number : 4;
+ const coord_def pos = defender->pos();
+ const bool was_delayed = you_are_delayed();
// Melee combat, tell attacker to wield its melee weapon.
atk->wield_melee_weapon();
@@ -3977,7 +3978,7 @@ void melee_attack::mons_perform_attack_rounds()
defender->hurt(attacker, damage_done + special_damage);
if (!defender->alive() || attacker == defender)
- return;
+ break;
special_damage = 0;
special_damage_message.clear();
@@ -3997,6 +3998,13 @@ void melee_attack::mons_perform_attack_rounds()
set_ident_flags( *weap, ISFLAG_KNOW_CURSE );
}
}
+
+ // Inivislbe monster might have interrupted butchering.
+ if (was_delayed && defender->atype() == ACT_PLAYER && perceived_attack
+ && !attacker_visible)
+ {
+ handle_interrupted_swap(false, true);
+ }
}
bool melee_attack::mons_perform_attack()
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 3a25835dde..fac6710599 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -23,6 +23,7 @@
*/
#include "AppHdr.h"
+#include "delay.h"
#include "files.h"
#include "version.h"
@@ -1340,6 +1341,18 @@ bool load( dungeon_feature_type stair_taken, load_mode_type load_mode,
if (load_mode != LOAD_VISITOR)
dungeon_events.fire_event(DET_ENTERED_LEVEL);
+ if (load_mode == LOAD_ENTER_LEVEL)
+ {
+ // If butchering was interrupted by switching levels (banishment)
+ // then switch back from butchering tool if there's no hostiles
+ // nearby.
+ handle_interrupted_swap(true);
+
+ // Forget about interrupted butchering, since we probably aren't going
+ // to get back to the corpse in time to finish things.
+ you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
+ }
+
return just_created_level;
} // end load()
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index b589964586..4db8cb975e 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -687,7 +687,7 @@ void game_options::reset_options()
easy_butcher = true;
always_confirm_butcher = false;
chunks_autopickup = true;
- swap_when_safe = true;
+ prompt_for_swap = true;
list_rotten = true;
easy_confirm = CONFIRM_SAFE_EASY;
easy_quit_item_prompts = true;
@@ -2039,7 +2039,7 @@ void game_options::read_option_line(const std::string &str, bool runscript)
else BOOL_OPTION(easy_butcher);
else BOOL_OPTION(always_confirm_butcher);
else BOOL_OPTION(chunks_autopickup);
- else BOOL_OPTION(swap_when_safe);
+ else BOOL_OPTION(prompt_for_swap);
else BOOL_OPTION(list_rotten);
else if (key == "lua_file" && runscript)
{
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index ae724e2077..cafe7b5978 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -1297,6 +1297,7 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area )
}
coord_def pos(1, 0);
+ bool large_change = false;
if (is_controlled)
{
@@ -1338,6 +1339,9 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area )
if (pos.x != you.x_pos || pos.y != you.y_pos)
clear_trapping_net();
+ if (!see_grid(pos))
+ large_change = true;
+
you.moveto(pos.x, pos.y);
if (grd[you.x_pos][you.y_pos] != DNGN_FLOOR
@@ -1346,6 +1350,7 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area )
|| env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD)
{
is_controlled = false;
+ large_change = false;
}
else
{
@@ -1378,7 +1383,10 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area )
else if ( see_grid(newx, newy) )
mpr("Your surroundings seem slightly different.");
else
+ {
mpr("Your surroundings suddenly seem different.");
+ large_change = true;
+ }
you.x_pos = newx;
you.y_pos = newy;
@@ -1387,6 +1395,9 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area )
you.moveto(you.pos());
}
+ if (large_change)
+ handle_interrupted_swap(true);
+
return !is_controlled;
}