diff options
author | j-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-05-15 23:46:58 +0000 |
---|---|---|
committer | j-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-05-15 23:46:58 +0000 |
commit | 6c1c71a64485cb196aaa21082d04246bfe922466 (patch) | |
tree | c369625e01d61cb00b9f30f38dd0e10b8d0134cf | |
parent | 3c019579930be9cdff59094b613b68575f895bae (diff) | |
download | crawl-ref-6c1c71a64485cb196aaa21082d04246bfe922466.tar.gz crawl-ref-6c1c71a64485cb196aaa21082d04246bfe922466.zip |
Implement FR 1936340: add a shortcut for butchering (a)ll corpses in a
stack. Does not yet differentiate between butchering and bottling (for
Vampires), and if several butcher/sacrifice delays have been chained and
are now interrupted, you only get the "not switching back to xyz"
message if the interruption happens while butchering the last corpse.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5068 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r-- | crawl-ref/source/delay.cc | 148 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/food.cc | 406 | ||||
-rw-r--r-- | crawl-ref/source/initfile.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/tutorial.cc | 2 |
6 files changed, 360 insertions, 205 deletions
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 8aa6fcfcec..2f8c170abc 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -286,11 +286,11 @@ void start_delay( delay_type type, int turns, int parm1, int parm2 ) delay_queue_item delay; - delay.type = type; + delay.type = type; delay.duration = turns; - delay.parm1 = parm1; - delay.parm2 = parm2; - delay.started = false; + delay.parm1 = parm1; + delay.parm2 = parm2; + delay.started = false; // Handle zero-turn delays (possible with butchering). if (turns == 0) @@ -307,7 +307,7 @@ void start_delay( delay_type type, int turns, int parm1, int parm2 ) void stop_delay( bool stop_stair_travel ) /*********************/ { - if ( you.delay_queue.empty() ) + if (you.delay_queue.empty()) return; delay_queue_item delay = you.delay_queue.front(); @@ -315,9 +315,10 @@ void stop_delay( bool stop_stair_travel ) ASSERT(!crawl_state.is_repeating_cmd() || delay.type == DELAY_MACRO); const bool butcher_swap_warn = - (delay.type == DELAY_BUTCHER - && you.delay_queue.size() >= 2 - && you.delay_queue[1].type == DELAY_WEAPON_SWAP); + ((delay.type == DELAY_BUTCHER + || delay.type == DELAY_OFFER_CORPSE) + && you.delay_queue.size() >= 2 + && you.delay_queue[1].type == DELAY_WEAPON_SWAP); const int butcher_swap_weapon = butcher_swap_warn? you.delay_queue[1].parm1 : -10; @@ -334,20 +335,25 @@ void stop_delay( bool stop_stair_travel ) { case DELAY_BUTCHER: // Corpse keeps track of work in plus2 field, see handle_delay() -- bwr + // FIXME: Also print this message for interruptions in chained + // butchery/sacrifice session. 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 butchering the corpse; not switching " "back to %s.", weapon.c_str()); } else mpr( "You stop butchering the corpse." ); + pop_delay(); break; @@ -462,10 +468,17 @@ void stop_delay( bool stop_stair_travel ) } break; + case DELAY_OFFER_CORPSE: // one turn +#ifdef DEBUG_DIAGNOSTICS + mpr("Stop sacrificing."); +#endif + pop_delay(); + break; + case DELAY_WEAPON_SWAP: // one turn... too much trouble case DELAY_DROP_ITEM: // one turn... only used for easy armour drops - case DELAY_UNINTERRUPTIBLE: // never stoppable case DELAY_JEWELLERY_ON: // one turn + case DELAY_UNINTERRUPTIBLE: // never stoppable default: break; } @@ -476,8 +489,11 @@ void stop_delay( bool stop_stair_travel ) void stop_butcher_delay() { - if (current_delay_action() == DELAY_BUTCHER) + if (current_delay_action() == DELAY_BUTCHER + || current_delay_action() == DELAY_OFFER_CORPSE) + { stop_delay(); + } } bool you_are_delayed( void ) @@ -588,9 +604,9 @@ void handle_delay( void ) delay_queue_item &delay = you.delay_queue.front(); - if ( !delay.started ) + if (!delay.started) { - switch ( delay.type ) + switch (delay.type) { case DELAY_ARMOUR_ON: mpr("You start putting on your armour.", MSGCH_MULTITURN_ACTION); @@ -599,9 +615,16 @@ void handle_delay( void ) mpr("You start removing your armour.", MSGCH_MULTITURN_ACTION); break; case DELAY_BUTCHER: - mprf(MSGCH_MULTITURN_ACTION, "You start %s the corpse.", - can_bottle_blood_from_corpse(mitm[delay.parm1].plus)? - "bottling blood from" : "butchering"); + mprf(MSGCH_MULTITURN_ACTION, "You start %s the %s.", + can_bottle_blood_from_corpse(mitm[delay.parm1].plus) ? + "bottling blood from" : "butchering", + mitm[delay.parm1].name(DESC_PLAIN).c_str()); + + if (you.duration[DUR_PRAYER] + && god_hates_butchery(you.religion)) + { + did_god_conduct(DID_DEDICATED_BUTCHERY, 10); + } break; case DELAY_MEMORISE: mpr("You start memorising the spell.", MSGCH_MULTITURN_ACTION); @@ -649,14 +672,14 @@ void handle_delay( void ) // First check cases where delay may no longer be valid: // XXX: need to handle passwall when monster digs -- bwr - if (delay.type == DELAY_BUTCHER) + if (delay.type == DELAY_BUTCHER || delay.type == DELAY_OFFER_CORPSE) { // A monster may have raised the corpse you're chopping up! -- bwr // Note that a monster could have raised the corpse and another // monster could die and create a corpse with the same ID number... // However, it would not be at the player's square like the // original and that's why we do it this way. - if (is_valid_item( mitm[ delay.parm1 ] ) + if (is_valid_item(mitm[ delay.parm1 ]) && mitm[ delay.parm1 ].base_type == OBJ_CORPSES && mitm[ delay.parm1 ].x == you.x_pos && mitm[ delay.parm1 ].y == you.y_pos ) @@ -664,19 +687,41 @@ void handle_delay( void ) if (mitm[ delay.parm1 ].sub_type == CORPSE_SKELETON) { mpr("The corpse rots away into a skeleton!"); - if (player_mutation_level(MUT_SAPROVOROUS) == 3) - xom_check_corpse_waste(); + if (delay.type == DELAY_BUTCHER) + { + if (player_mutation_level(MUT_SAPROVOROUS) == 3) + xom_check_corpse_waste(); + else + xom_is_stimulated(32); + delay.duration = 0; + } else - xom_is_stimulated(32); - delay.duration = 0; + { + // don't attempt to offer a skeleton + pop_delay(); + + // Chain onto the next delay. + handle_delay(); + return; + } } else { - // special < 100 is the rottenness check - if ( (mitm[delay.parm1].special < 100) && - (delay.parm2 >= 100) ) + // Only give the rotting message if the corpse wasn't + // previously rotten. (special < 100 is the rottenness check) + if (food_is_rotten(mitm[delay.parm1]) && delay.parm2 >= 100) { mpr("The corpse rots.", MSGCH_ROTTEN_MEAT); + if (delay.type == DELAY_OFFER_CORPSE) + { + // don't attempt to offer a rotten corpse + pop_delay(); + + // Chain onto the next delay. + handle_delay(); + return; + } + delay.parm2 = 99; // don't give the message twice if (you.is_undead != US_UNDEAD @@ -697,6 +742,16 @@ void handle_delay( void ) mitm[ delay.parm1 ].plus2++; } } + else if (delay.type == DELAY_OFFER_CORPSE) + { + mprf("Corpse %d no longer valid!", delay.parm1); + // don't attempt to offer an invalid item + pop_delay(); + + // Chain onto the next delay. + handle_delay(); + return; + } else { // corpse is no longer valid! End the butchering normally @@ -704,8 +759,14 @@ void handle_delay( void ) // back to their main weapon if necessary. delay.duration = 0; } + + if (delay.type == DELAY_OFFER_CORPSE && !you.duration[DUR_PRAYER] + && do_autopray()) + { + return; + } } - if ( delay.type == DELAY_MULTIDROP ) + else if (delay.type == DELAY_MULTIDROP) { // Throw away invalid items; items usually go invalid because // of chunks rotting away. @@ -713,7 +774,9 @@ void handle_delay( void ) // Don't look for gold in inventory && items_for_multidrop[0].slot != PROMPT_GOT_SPECIAL && !is_valid_item(you.inv[ items_for_multidrop[0].slot ])) + { items_for_multidrop.erase( items_for_multidrop.begin() ); + } if ( items_for_multidrop.empty() ) { @@ -722,10 +785,8 @@ void handle_delay( void ) return; } } - - if ( delay.type == DELAY_RECITE) + else if (delay.type == DELAY_RECITE) { - if (check_recital_audience() < 1 // maybe you've lost your audience || Options.hp_warning && you.hp*Options.hp_warning <= you.hp_max && delay.parm2*Options.hp_warning > you.hp_max @@ -796,7 +857,7 @@ void handle_delay( void ) mpr("This corpse has started to rot.", MSGCH_ROTTEN_MEAT); xom_check_corpse_waste(); stop_delay(); - break; + return; } mprf(MSGCH_MULTITURN_ACTION, "You continue drinking."); vampire_nutrition_per_turn(corpse, 0); @@ -990,17 +1051,22 @@ static void finish_delay(const delay_queue_item &delay) } else { - mprf("You finish %s the corpse into pieces.", + mprf("You finish %s the %s into pieces.", (you.has_usable_claws() - || player_mutation_level(MUT_FANGS) == 3) ? - "ripping" : "chopping"); + || player_mutation_level(MUT_FANGS) == 3) ? "ripping" + : "chopping", + mitm[delay.parm1].name(DESC_PLAIN).c_str()); if (is_good_god(you.religion) && is_player_same_species(item.plus)) + { simple_god_message(" expects more respect for your departed " "relatives."); + } else if (you.religion == GOD_ZIN && mons_intel(item.plus) >= I_NORMAL) + { simple_god_message(" expects more respect for this departed " "soul."); + } if (you.species == SP_VAMPIRE && you.experience_level < 6 && mons_has_blood(item.plus) @@ -1029,6 +1095,17 @@ static void finish_delay(const delay_queue_item &delay) break; } + case DELAY_OFFER_CORPSE: + { + if (!you.duration[DUR_PRAYER] && !do_autopray()) + { + stop_delay(); + return; + } + + offer_corpse(delay.parm1); + break; + } case DELAY_DROP_ITEM: // Note: checking if item is droppable is assumed to // be done before setting up this delay... this includes @@ -1639,9 +1716,10 @@ activity_interrupt_type get_activity_interrupt(const std::string &name) static const char *delay_names[] = { "not_delayed", "eat", "vampire_feed", "armour_on", "armour_off", - "jewellery_on", "memorise", "butcher", "weapon_swap", "passwall", - "drop_item", "multidrop", "ascending_stairs", "descending_stairs", "recite", - "run", "rest", "travel", "macro", "interruptible", "uninterruptible", + "jewellery_on", "memorise", "butcher", "offer_corpse", "weapon_swap", + "passwall", "drop_item", "multidrop", "ascending_stairs", + "descending_stairs", "recite", "run", "rest", "travel", "macro", + "interruptible", "uninterruptible" }; // Gets a delay given its name. diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 7abdfa5d21..107ccceaae 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -708,6 +708,7 @@ enum delay_type DELAY_JEWELLERY_ON, DELAY_MEMORISE, DELAY_BUTCHER, + DELAY_OFFER_CORPSE, DELAY_WEAPON_SWAP, // for easy_butcher DELAY_PASSWALL, DELAY_DROP_ITEM, diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index be6770421d..108d823b7b 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -55,14 +55,14 @@ #include "tutorial.h" #include "xom.h" -static int _determine_chunk_effect(int which_chunk_type, bool rotten_chunk); -static void _eat_chunk( int chunk_effect, bool cannibal, int mon_intel = 0); -static void _eating(unsigned char item_class, int item_type); -static void _describe_food_change(int hunger_increment); -static bool _food_change(bool suppress_message); -static bool _vampire_consume_corpse(int slot, bool invent); -static void _heal_from_food(int hp_amt, int mp_amt, bool unrot, - bool restore_str); +static int _determine_chunk_effect(int which_chunk_type, bool rotten_chunk); +static void _eat_chunk( int chunk_effect, bool cannibal, int mon_intel = 0); +static void _eating(unsigned char item_class, int item_type); +static void _describe_food_change(int hunger_increment); +static bool _food_change(bool suppress_message); +static bool _vampire_consume_corpse(int slot, bool invent); +static void _heal_from_food(int hp_amt, int mp_amt, bool unrot, + bool restore_str); /* ************************************************** @@ -178,10 +178,15 @@ static bool _find_butchering_implement( bool fallback ) mprf(MSGCH_WARN, "You're wielding a weapon of distortion, will not autoswap " "for butchering."); - return false; + return (false); } + // no switching necessary + if (can_cut_meat( *wpn )) + return (false); } + int old_weapon = you.equip[EQ_WEAPON]; + // look for a butchering implement in your pack for (int i = 0; i < ENDOFPACK; ++i) { @@ -201,70 +206,168 @@ static bool _find_butchering_implement( bool fallback ) } } - if ( !fallback ) + if (!fallback) return false; // if we didn't swap above, then we still can't cut...let's call // wield_weapon() in the "prompt the user" way... // prompt for new weapon - int old_weapon = you.equip[EQ_WEAPON]; - mpr( "What would you like to use?", MSGCH_PROMPT ); + mpr("What would you like to use?", MSGCH_PROMPT); wield_weapon( false ); // let's see if the user did something... return (you.equip[EQ_WEAPON] != old_weapon); } -bool butchery(int which_corpse) +static bool _prepare_butchery(bool can_butcher, bool barehand_butcher, + bool wpn_switch, bool removed_gloves, + bool new_cursed) { - bool new_cursed = false; - int old_weapon = you.equip[EQ_WEAPON]; - int old_gloves = you.equip[EQ_GLOVES]; + // No preparation necessary. + if (can_butcher) + return (true); - const transformation_type transform = - static_cast<transformation_type>(you.attribute[ATTR_TRANSFORMATION]); + // We don't want auto-switching. + if (!Options.easy_butcher) + return (false); - // Xom probably likes this, occasionally - // Vampires' fangs are optimised for biting, not for tearing flesh. - // Other species with this mutation still might benefit from this. - bool teeth_butcher = (player_mutation_level(MUT_FANGS) == 3 - && you.species != SP_VAMPIRE); + // If you can butcher by taking off your gloves, don't prompt. + if (removed_gloves) + { + // Actually take off the gloves; this creates a + // delay. We assume later on that gloves have a 1-turn + // takeoff delay! + takeoff_armour(you.equip[EQ_GLOVES]); + barehand_butcher = true; + } - bool barehand_butcher = (transform_can_butcher_barehanded(transform) - || you.has_claws()) && you.equip[EQ_GLOVES] == -1; + // note that if barehanded then the user selected '-' when + // switching weapons + if (!barehand_butcher && (!wpn_switch + || you.weapon() == NULL + || !can_cut_meat(*you.weapon()))) + { + // still can't butcher. Early out + if ( you.weapon() == NULL ) + { + if (you.equip[EQ_GLOVES] == -1) + mpr("What, with your bare hands?"); + else + mpr("Your gloves aren't that sharp!"); + } + else + mpr("Maybe you should try using a sharper implement."); - bool gloved_butcher = you.has_claws() && (you.equip[EQ_GLOVES] != -1 - && !item_cursed(you.inv[you.equip[EQ_GLOVES]])); + // Switch back to old weapon. + if (!new_cursed && wpn_switch) + start_delay( DELAY_WEAPON_SWAP, 1, you.equip[EQ_WEAPON] ); - bool can_butcher = teeth_butcher || barehand_butcher - || you.equip[EQ_WEAPON] != -1 - && can_cut_meat(you.inv[you.equip[EQ_WEAPON]]); + return (false); + } + you.turn_is_over = true; + // switched to a good butchering tool + return (true); +} + +static bool _butcher_corpse(int corpse_id) +{ + ASSERT(corpse_id != -1); + + const bool rotten = food_is_rotten(mitm[corpse_id]); + const bool can_sac = you.duration[DUR_PRAYER] + && god_likes_butchery(you.religion); + + if (can_sac && !rotten) + { + start_delay(DELAY_OFFER_CORPSE, 1, corpse_id); + } + else + { + if (can_sac && rotten) + { + simple_god_message(coinflip() ? " refuses to accept that" + " mouldy sacrifice!" + : " demands fresh blood!", + you.religion); + } + + // If we didn't switch weapons, we get in one turn of butchery; + // otherwise the work has to happen in the delay. +// if (!wpn_switch && !removed_gloves) +// ++mitm[corpse_id].plus2; + + int work_req = 4 - mitm[corpse_id].plus2; + if (work_req < 0) + work_req = 0; + + start_delay(DELAY_BUTCHER, work_req, corpse_id, + mitm[corpse_id].special); + } + + you.turn_is_over = true; + return true; +} + +static void _terminate_butchery(bool wpn_switch, bool removed_gloves, + bool new_cursed, int old_weapon, int old_gloves) +{ + // switch weapon back + if (!new_cursed && wpn_switch) + start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); + + // put on the removed gloves + if (removed_gloves) + start_delay( DELAY_ARMOUR_ON, 1, old_gloves ); + + you.turn_is_over = true; +} + +bool butchery(int which_corpse) +{ if (igrd[you.x_pos][you.y_pos] == NON_ITEM) { mpr("There isn't anything here!"); return (false); } - if (!Options.easy_butcher && !can_butcher) + if (you.flight_mode() == FL_LEVITATE) { - mpr("Maybe you should try using a sharper implement."); + mpr("You can't reach the floor from up here."); return (false); } - if (you.flight_mode() == FL_LEVITATE) + const transformation_type transform = + static_cast<transformation_type>(you.attribute[ATTR_TRANSFORMATION]); + + // Vampires' fangs are optimised for biting, not for tearing flesh. + // Other species with this mutation still might benefit from this. + bool teeth_butcher = (player_mutation_level(MUT_FANGS) == 3 + && you.species != SP_VAMPIRE); + + bool barehand_butcher = (transform_can_butcher_barehanded(transform) + || you.has_claws()) && you.equip[EQ_GLOVES] == -1; + + bool gloved_butcher = (you.has_claws() && you.equip[EQ_GLOVES] != -1 + && !item_cursed(you.inv[you.equip[EQ_GLOVES]])); + + bool can_butcher = teeth_butcher || barehand_butcher + || you.equip[EQ_WEAPON] != -1 + && can_cut_meat(you.inv[you.equip[EQ_WEAPON]]); + + if (!Options.easy_butcher && !can_butcher) { - mpr("You can't reach the floor from up here."); + mpr("Maybe you should try using a sharper implement."); return (false); } // It makes more sense that you first find out if there's anything // to butcher, *then* decide to actually butcher it. // The old code did it the other way. - if ( !can_butcher && you.duration[DUR_BERSERKER] ) + if (!can_butcher && you.duration[DUR_BERSERKER]) { - mpr ("You are too berserk to search for a butchering tool!"); + mpr("You are too berserk to search for a butchering tool!"); return (false); } @@ -274,8 +377,8 @@ bool butchery(int which_corpse) bool prechosen = (which_corpse != -1); for (int o = igrd[you.x_pos][you.y_pos]; o != NON_ITEM; o = mitm[o].link) { - if (mitm[o].base_type == OBJ_CORPSES && - mitm[o].sub_type == CORPSE_BODY) + if (mitm[o].base_type == OBJ_CORPSES + && mitm[o].sub_type == CORPSE_BODY) { corpse_id = o; num_corpses++; @@ -285,165 +388,127 @@ bool butchery(int which_corpse) break; } } - // pre-chosen corpse not found? - if (prechosen && corpse_id != which_corpse) - prechosen = false; - - bool canceled_butcher = false; - // Now pick what you want to butcher. This is only a problem - // if there are several corpses on the square. - if ( num_corpses == 0 ) + if (num_corpses == 0) { mprf("There isn't anything to %s here.", you.species == SP_VAMPIRE && you.experience_level > 5 ? "bottle" - : "butcher"); - return false; + : "butcher"); + return (false); } - else if ( !prechosen - && (num_corpses > 1 || Options.always_confirm_butcher) ) + + int old_weapon = you.equip[EQ_WEAPON]; + int old_gloves = you.equip[EQ_GLOVES]; + + bool wpn_switch = false; + bool removed_gloves = false; + bool new_cursed = false; + + if (!can_butcher) { - corpse_id = -1; - for (int o=igrd[you.x_pos][you.y_pos]; o != NON_ITEM; o = mitm[o].link) - { - if ( (mitm[o].base_type != OBJ_CORPSES) || - (mitm[o].sub_type != CORPSE_BODY) ) - continue; + // Try to find a butchering implement. + wpn_switch = _find_butchering_implement(!gloved_butcher); + removed_gloves = gloved_butcher && !wpn_switch; - // offer the possibility of butchering - snprintf(info, INFO_SIZE, "%s %s?", - can_bottle_blood_from_corpse(mitm[o].plus)? "Bottle" : "Butcher", - mitm[o].name(DESC_NOCAP_A).c_str()); + if (wpn_switch) + { + new_cursed = ( you.weapon() != NULL + && you.weapon()->base_type == OBJ_WEAPONS + && item_cursed(*you.weapon()) ); + } + } - const int result = yesnoquit(info, true, 'N', false, false, 'C', 'D'); - if ( result == -1 ) - { - canceled_butcher = true; - corpse_id = -1; - break; - } - else if ( result == 1 ) - { - corpse_id = o; - break; - } - // continue loop for 0 + // Butcher pre-chosen corpse, if found, or if there is only one corpse. + bool success = false; + if (prechosen && corpse_id == which_corpse + || num_corpses == 1 && !Options.always_confirm_butcher) + { + if (!_prepare_butchery(can_butcher, barehand_butcher, wpn_switch, + removed_gloves, new_cursed)) + { + return (false); } + success = _butcher_corpse(corpse_id); + _terminate_butchery(wpn_switch, removed_gloves, new_cursed, + old_weapon, old_gloves); + + return success; } - // Do the actual butchery, if we found a good corpse. - if ( corpse_id != -1 ) + // Now pick what you want to butcher. This is only a problem + // if there are several corpses on the square. + bool butcher_all = false; + for (int o = igrd[you.x_pos][you.y_pos]; o != NON_ITEM; o = mitm[o].link) { - const bool can_sac = you.duration[DUR_PRAYER] - && god_likes_butchery(you.religion); - bool removed_gloves = false; - bool wpn_switch = false; + if (mitm[o].base_type != OBJ_CORPSES + || mitm[o].sub_type != CORPSE_BODY) + { + continue; + } - if ( Options.easy_butcher && !can_butcher ) + if (butcher_all) + corpse_id = o; + else { - // Try to find a butchering implement. - // If you can butcher by taking off your gloves, don't prompt. - wpn_switch = _find_butchering_implement(!gloved_butcher); - removed_gloves = gloved_butcher && !wpn_switch; - if ( removed_gloves ) + corpse_id = -1; + + // Shall we butcher this corpse? + snprintf(info, INFO_SIZE, "%s %s?", + can_bottle_blood_from_corpse(mitm[o].plus) ? "Bottle" + : "Butcher", + mitm[o].name(DESC_NOCAP_A).c_str()); + + const int result = yesnoquit(info, true, 'N', true, false, + 'C', 'D'); + + if (result == -1) // (q)uit { - // Actually take off the gloves; this creates a - // delay. We assume later on that gloves have a 1-turn - // takeoff delay! - takeoff_armour(old_gloves); - barehand_butcher = true; + canned_msg(MSG_OK); + _terminate_butchery(wpn_switch, removed_gloves, new_cursed, + old_weapon, old_gloves); + return (false); } - if ( wpn_switch ) + else if (result == 0) // (n)o { - new_cursed = - (you.weapon() != NULL) && - (you.weapon()->base_type == OBJ_WEAPONS) && - item_cursed( *you.weapon() ); + continue; } - - // note that if barehanded then the user selected '-' when - // switching weapons - - if (!barehand_butcher && (!wpn_switch || - you.weapon() == NULL || - !can_cut_meat(*you.weapon()))) + else if (result == 1 || result == 2) // (y)es, (a)ll { - // still can't butcher. Early out - if ( you.weapon() == NULL ) + if (!_prepare_butchery(can_butcher, barehand_butcher, + wpn_switch, removed_gloves, new_cursed)) { - if (you.equip[EQ_GLOVES] == -1) - mpr("What, with your bare hands?"); - else - mpr("Your gloves aren't that sharp!"); + return (false); } - else - mpr("Maybe you should try using a sharper implement."); - - if ( !new_cursed && wpn_switch ) - start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); + corpse_id = o; - return false; + if (result == 2) // (a)ll + butcher_all = true; } - - // switched to a good butchering knife - can_butcher = true; } - if ( can_butcher ) + if (corpse_id != -1) { - const bool rotten = food_is_rotten(mitm[corpse_id]); - if (can_sac && !rotten) - offer_corpse(corpse_id); - else - { - if (can_sac && rotten) - { - simple_god_message(coinflip() ? - " refuses to accept that mouldy " - "sacrifice!" : - " demands fresh blood!", you.religion); - } + if (_butcher_corpse(corpse_id)) + success = true; - // If we didn't switch weapons, we get in one turn of butchery; - // otherwise the work has to happen in the delay. - if (!wpn_switch && !removed_gloves) - ++mitm[corpse_id].plus2; - - int work_req = 4 - mitm[corpse_id].plus2; - if (work_req < 0) - work_req = 0; - - start_delay(DELAY_BUTCHER, work_req, corpse_id, - mitm[corpse_id].special); - - if (you.duration[DUR_PRAYER] - && god_hates_butchery(you.religion)) - { - did_god_conduct(DID_DEDICATED_BUTCHERY, 10); - } - } + if (!butcher_all) + break; } - - // switch weapon back - if (!new_cursed && wpn_switch) - start_delay( DELAY_WEAPON_SWAP, 1, old_weapon ); - - // put on the removed gloves - if ( removed_gloves ) - start_delay( DELAY_ARMOUR_ON, 1, old_gloves ); - - you.turn_is_over = true; - return true; } - if (canceled_butcher) - canned_msg(MSG_OK); - else + if (!butcher_all && corpse_id == -1) + { mprf("There isn't anything else to %s here.", - you.species == SP_VAMPIRE && you.experience_level >= 6 ? - "bottle" : "butcher"); + you.species == SP_VAMPIRE && you.experience_level >= 6 ? + "bottle" : "butcher"); + } + else + { + _terminate_butchery(wpn_switch, removed_gloves, new_cursed, + old_weapon, old_gloves); + } - return false; + return success; } // end butchery() void lua_push_items(lua_State *ls, int link) @@ -694,16 +759,20 @@ static bool _food_change(bool suppress_message) msg += "feel devoid of blood!"; else msg += "are starving!"; + mpr(msg.c_str(), MSGCH_FOOD, less_hungry); learned_something_new(TUT_YOU_STARVING); you.check_awaken(500); break; + case HS_NEAR_STARVING: if (you.species == SP_VAMPIRE) msg += "feel almost devoid of blood!"; else msg += "are near starving!"; + mpr(msg.c_str(), MSGCH_FOOD, less_hungry); learned_something_new(TUT_YOU_HUNGRY); break; + case HS_VERY_HUNGRY: case HS_HUNGRY: msg += "are feeling "; @@ -711,12 +780,13 @@ static bool _food_change(bool suppress_message) msg += "very "; msg += _how_hungry(); msg += "."; + mpr(msg.c_str(), MSGCH_FOOD, less_hungry); learned_something_new(TUT_YOU_HUNGRY); break; + default: return (state_changed); } - mpr(msg.c_str(), MSGCH_FOOD, less_hungry); } } @@ -864,7 +934,9 @@ int eat_from_floor() << ' ' << ((item.quantity > 1) ? "one of " : "") << item.name(DESC_NOCAP_A) << '?'; - const int ans = yesnoquit( prompt.str().c_str(), true, 0, false, 'E' ); + const int ans = yesnoquit( prompt.str().c_str(), true, 0, false, false, + 'E' ); + if ( ans == -1 ) // quit return -1; else if ( ans == 1 ) // yes diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index d2e44d7d14..7e168db497 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -493,6 +493,7 @@ void game_options::set_default_activity_interrupts() "interrupt_recite = teleport", "interrupt_uninterruptible =", "interrupt_weapon_swap =", + "interrupt_offer_corpse = interrupt_butcher, hungry", NULL }; diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 92c46482ac..c9be50c2ed 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -979,11 +979,14 @@ static std::string _list_alternative_yes(char yes1, char yes2, } static const char* _list_allowed_keys(char yes1, char yes2, - bool lowered = false) + bool lowered = false, + bool allow_all = false) { std::string result = " ["; result += (lowered ? "y" : "Y"); result += _list_alternative_yes(yes1, yes2, lowered); + if (allow_all) + result += (lowered? "/a" : "/A"); result += (lowered ? "/n/q" : "/N/Q"); result += "]"; @@ -1000,7 +1003,7 @@ int yesnoquit( const char* str, bool safe, int safeanswer, bool allow_all, std::string prompt = make_stringf("%s%s ", str ? str : "Buggy prompt?", _list_allowed_keys(alt_yes, alt_yes2, - safe)); + safe, allow_all)); while (true) { diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc index c7765e2412..f2480f9445 100644 --- a/crawl-ref/source/tutorial.cc +++ b/crawl-ref/source/tutorial.cc @@ -857,7 +857,7 @@ void tutorial_healing_reminder() learned_something_new(TUT_NEED_POISON_HEALING); } else if (Options.tut_seen_invisible > 0 - && you.num_turns < Options.tut_seen_invisible - 20) + && you.num_turns < Options.tut_seen_invisible + 20) { // If we recently encountered an invisible monster, we need a // special message. |