summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/food.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-05-15 23:46:58 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-05-15 23:46:58 +0000
commit6c1c71a64485cb196aaa21082d04246bfe922466 (patch)
treec369625e01d61cb00b9f30f38dd0e10b8d0134cf /crawl-ref/source/food.cc
parent3c019579930be9cdff59094b613b68575f895bae (diff)
downloadcrawl-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
Diffstat (limited to 'crawl-ref/source/food.cc')
-rw-r--r--crawl-ref/source/food.cc406
1 files changed, 239 insertions, 167 deletions
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