summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/options_guide.txt5
-rw-r--r--crawl-ref/source/delay.cc117
-rw-r--r--crawl-ref/source/enum.h1
-rw-r--r--crawl-ref/source/food.cc37
-rw-r--r--crawl-ref/source/initfile.cc3
-rw-r--r--crawl-ref/source/mutation.cc2
-rw-r--r--crawl-ref/source/player.cc8
-rw-r--r--crawl-ref/source/religion.cc16
-rw-r--r--crawl-ref/source/tutorial.cc5
9 files changed, 118 insertions, 76 deletions
diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt
index b5c7f2352f..bc71862bed 100644
--- a/crawl-ref/docs/options_guide.txt
+++ b/crawl-ref/docs/options_guide.txt
@@ -1460,6 +1460,7 @@ The following events are logged:
- Being put under penance and being forgiven
- Receiving a gift from a god (except Xom)
- Being able to invoke a godly power for the first time
+ - Picking up a rune or the orb of zot for the first time
- Identifying items (see below)
- Killing OOD or unique monsters (see below)
- Reaching critical HP levels (see below)
@@ -1477,14 +1478,14 @@ note_items = <regexes>
artefact
(fixed, unrand, or random) or if its short description matches a
regex. E.g.
- note_items = rod,book,rune,acquirement
+ note_items = rod,book,acquirement
note_monsters = <regex list>
Monsters whose name matches an item in this comma-separated list
are considered interesting. You can have multiple note_monsters
lines. E.g.
note_monsters = Klown,orb of fire
-
+
ood_interesting = 8
Monsters which are out of depth (OOD for short) for their
current level, e.g. a dragon on level 2, will be noted if they
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 2f8c170abc..7c16e684fd 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -314,15 +314,6 @@ 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
- || 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;
-
// At the very least we can remove any queued delays, right
// now there is no problem with doing this... note that
// any queuing here can only happen from a single command,
@@ -334,11 +325,40 @@ void stop_delay( bool stop_stair_travel )
switch (delay.type)
{
case DELAY_BUTCHER:
+ case DELAY_BOTTLE_BLOOD:
+ case DELAY_OFFER_CORPSE:
+ {
+ bool multiple_corpses = false;
+ bool butcher_swap_warn = false;
+ int wpn_delay = -1;
+ for (unsigned int i = 1; i < you.delay_queue.size(); i++)
+ {
+ if (you.delay_queue[i].type == DELAY_BUTCHER
+ || you.delay_queue[i].type == DELAY_BOTTLE_BLOOD
+ || you.delay_queue[i].type == DELAY_OFFER_CORPSE)
+ {
+ multiple_corpses = true;
+ }
+ else if (you.delay_queue[i].type == DELAY_WEAPON_SWAP)
+ {
+ wpn_delay = i;
+ butcher_swap_warn = true;
+ break;
+ }
+ else
+ break;
+ }
+
+ const std::string butcher_verb =
+ (delay.type == DELAY_BUTCHER ? "butchering" :
+ delay.type == DELAY_BOTTLE_BLOOD ? "bottling blood from"
+ : "sacrificing");
+
// 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)
{
+ const int butcher_swap_weapon = you.delay_queue[wpn_delay].parm1;
+
std::string weapon;
if (butcher_swap_weapon == -1)
weapon = "unarmed combat";
@@ -347,16 +367,16 @@ void stop_delay( bool stop_stair_travel )
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());
+ mprf(MSGCH_WARN, "You stop %s the corpse%s; not switching "
+ "back to %s.", butcher_verb.c_str(),
+ (multiple_corpses ? "s" : ""), weapon.c_str());
}
else
- mpr( "You stop butchering the corpse." );
+ mprf("You stop %s the corpse.", butcher_verb.c_str());
pop_delay();
break;
-
+ }
case DELAY_MEMORISE:
// Losing work here is okay... having to start from
// scratch is a reasonable behaviour. -- bwr
@@ -468,13 +488,6 @@ 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_JEWELLERY_ON: // one turn
@@ -490,6 +503,7 @@ void stop_delay( bool stop_stair_travel )
void stop_butcher_delay()
{
if (current_delay_action() == DELAY_BUTCHER
+ || current_delay_action() == DELAY_BOTTLE_BLOOD
|| current_delay_action() == DELAY_OFFER_CORPSE)
{
stop_delay();
@@ -521,7 +535,7 @@ bool is_being_butchered(const item_def &item)
return (false);
const delay_queue_item &delay = you.delay_queue.front();
- if (delay.type == DELAY_BUTCHER)
+ if (delay.type == DELAY_BUTCHER || delay.type == DELAY_BOTTLE_BLOOD)
{
const item_def &corpse = mitm[ delay.parm1 ];
return (&corpse == &item);
@@ -615,11 +629,13 @@ void handle_delay( void )
mpr("You start removing your armour.", MSGCH_MULTITURN_ACTION);
break;
case DELAY_BUTCHER:
+ case DELAY_BOTTLE_BLOOD:
mprf(MSGCH_MULTITURN_ACTION, "You start %s the %s.",
- can_bottle_blood_from_corpse(mitm[delay.parm1].plus) ?
- "bottling blood from" : "butchering",
+ (delay.type == DELAY_BOTTLE_BLOOD ? "bottling blood from"
+ : "butchering"),
mitm[delay.parm1].name(DESC_PLAIN).c_str());
+ // also for bottling blood
if (you.duration[DUR_PRAYER]
&& god_hates_butchery(you.religion))
{
@@ -672,8 +688,16 @@ 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 || delay.type == DELAY_OFFER_CORPSE)
+ if (delay.type == DELAY_BUTCHER || delay.type == DELAY_BOTTLE_BLOOD
+ || delay.type == DELAY_OFFER_CORPSE)
{
+ if (delay.type == DELAY_BOTTLE_BLOOD && you.experience_level < 6)
+ {
+ mpr("You cannot bottle blood anymore!");
+ stop_delay();
+ return;
+ }
+
// 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...
@@ -687,7 +711,8 @@ void handle_delay( void )
if (mitm[ delay.parm1 ].sub_type == CORPSE_SKELETON)
{
mpr("The corpse rots away into a skeleton!");
- if (delay.type == DELAY_BUTCHER)
+ if (delay.type == DELAY_BUTCHER
+ || delay.type == DELAY_BOTTLE_BLOOD)
{
if (player_mutation_level(MUT_SAPROVOROUS) == 3)
xom_check_corpse_waste();
@@ -697,7 +722,7 @@ void handle_delay( void )
}
else
{
- // don't attempt to offer a skeleton
+ // Don't attempt to offer a skeleton.
pop_delay();
// Chain onto the next delay.
@@ -730,7 +755,7 @@ void handle_delay( void )
xom_check_corpse_waste();
}
// Vampires won't continue bottling rotting corpses.
- if (can_bottle_blood_from_corpse(mitm[delay.parm1].plus))
+ if (delay.type == DELAY_BOTTLE_BLOOD)
{
mpr("You stop bottling this corpse's foul-smelling "
"blood!");
@@ -822,9 +847,11 @@ void handle_delay( void )
you.inv[delay.parm1].name(DESC_NOCAP_YOUR).c_str());
break;
case DELAY_BUTCHER:
- mprf(MSGCH_MULTITURN_ACTION, "You continue %s the corpse.",
- can_bottle_blood_from_corpse(mitm[delay.parm1].plus)?
- "bottling blood from" : "butchering");
+ mprf(MSGCH_MULTITURN_ACTION, "You continue butchering the corpse.");
+ break;
+ case DELAY_BOTTLE_BLOOD:
+ mprf(MSGCH_MULTITURN_ACTION, "You continue bottling blood from "
+ "the corpse.");
break;
case DELAY_MEMORISE:
mpr("You continue memorising.", MSGCH_MULTITURN_ACTION);
@@ -1026,6 +1053,7 @@ static void finish_delay(const delay_queue_item &delay)
}
case DELAY_BUTCHER:
+ case DELAY_BOTTLE_BLOOD:
{
const item_def &item = mitm[delay.parm1];
if (is_valid_item(item) && item.base_type == OBJ_CORPSES)
@@ -1033,9 +1061,9 @@ static void finish_delay(const delay_queue_item &delay)
if (item.sub_type == CORPSE_SKELETON)
{
mprf("The corpse rots away into a skeleton just before you "
- "finish %s!", can_bottle_blood_from_corpse(item.plus)
- ? "bottling its blood"
- : "butchering");
+ "finish %s!",
+ (delay.type == DELAY_BOTTLE_BLOOD ? "bottling its blood"
+ : "butchering"));
if (player_mutation_level(MUT_SAPROVOROUS) == 3)
xom_check_corpse_waste();
@@ -1045,7 +1073,7 @@ static void finish_delay(const delay_queue_item &delay)
break;
}
- if (can_bottle_blood_from_corpse(item.plus))
+ if (delay.type == DELAY_BOTTLE_BLOOD)
{
turn_corpse_into_blood_potions( mitm[ delay.parm1 ] );
}
@@ -1053,8 +1081,9 @@ static void finish_delay(const delay_queue_item &delay)
{
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
+ && you.species != SP_VAMPIRE) ? "ripping"
+ : "chopping",
mitm[delay.parm1].name(DESC_PLAIN).c_str());
if (is_good_god(you.religion) && is_player_same_species(item.plus))
@@ -1068,10 +1097,8 @@ static void finish_delay(const delay_queue_item &delay)
"soul.");
}
- if (you.species == SP_VAMPIRE && you.experience_level < 6
- && mons_has_blood(item.plus)
- && (!god_likes_butchery(you.religion)
- || !you.duration[DUR_PRAYER]))
+ if (you.species == SP_VAMPIRE && delay.type == DELAY_BUTCHER
+ && mons_has_blood(item.plus))
{
mpr("What a waste.");
}
@@ -1716,8 +1743,8 @@ 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", "offer_corpse", "weapon_swap",
- "passwall", "drop_item", "multidrop", "ascending_stairs",
+ "jewellery_on", "memorise", "butcher", "bottle_blood", "offer_corpse",
+ "weapon_swap", "passwall", "drop_item", "multidrop", "ascending_stairs",
"descending_stairs", "recite", "run", "rest", "travel", "macro",
"interruptible", "uninterruptible"
};
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 107ccceaae..7335e88de7 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_BOTTLE_BLOOD,
DELAY_OFFER_CORPSE,
DELAY_WEAPON_SWAP, // for easy_butcher
DELAY_PASSWALL,
diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc
index 108d823b7b..83fb8b507b 100644
--- a/crawl-ref/source/food.cc
+++ b/crawl-ref/source/food.cc
@@ -271,7 +271,7 @@ static bool _prepare_butchery(bool can_butcher, bool barehand_butcher,
return (true);
}
-static bool _butcher_corpse(int corpse_id)
+static bool _butcher_corpse(int corpse_id, bool force_butcher = false)
{
ASSERT(corpse_id != -1);
@@ -293,17 +293,19 @@ static bool _butcher_corpse(int corpse_id)
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);
+
+ delay_type dtype = DELAY_BUTCHER;
+ if (!force_butcher
+ && can_bottle_blood_from_corpse(mitm[corpse_id].plus))
+ {
+ dtype = DELAY_BOTTLE_BLOOD;
+ }
+
+ start_delay(dtype, work_req, corpse_id, mitm[corpse_id].special);
}
you.turn_is_over = true;
@@ -438,6 +440,7 @@ bool butchery(int which_corpse)
// Now pick what you want to butcher. This is only a problem
// if there are several corpses on the square.
bool butcher_all = false;
+ bool bottle_all = false; // for Vampires
for (int o = igrd[you.x_pos][you.y_pos]; o != NON_ITEM; o = mitm[o].link)
{
if (mitm[o].base_type != OBJ_CORPSES
@@ -446,7 +449,10 @@ bool butchery(int which_corpse)
continue;
}
- if (butcher_all)
+ if (bottle_all && !can_bottle_blood_from_corpse(mitm[o].plus))
+ continue;
+
+ if (butcher_all || bottle_all)
corpse_id = o;
else
{
@@ -482,21 +488,26 @@ bool butchery(int which_corpse)
corpse_id = o;
if (result == 2) // (a)ll
- butcher_all = true;
+ {
+ if (can_bottle_blood_from_corpse(mitm[o].plus))
+ bottle_all = true;
+ else
+ butcher_all = true;
+ }
}
}
if (corpse_id != -1)
{
- if (_butcher_corpse(corpse_id))
+ if (_butcher_corpse(corpse_id, butcher_all))
success = true;
- if (!butcher_all)
+ if (!butcher_all && !bottle_all)
break;
}
}
- if (!butcher_all && corpse_id == -1)
+ if (!butcher_all && !bottle_all && corpse_id == -1)
{
mprf("There isn't anything else to %s here.",
you.species == SP_VAMPIRE && you.experience_level >= 6 ?
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 7e168db497..2c090643d7 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -477,6 +477,8 @@ void game_options::set_default_activity_interrupts()
"interrupt_jewellery_on = interrupt_armour_on",
"interrupt_memorise = interrupt_armour_on, stat",
"interrupt_butcher = interrupt_armour_on, teleport, stat",
+ "interrupt_bottle_blood = interrupt_butcher",
+ "interrupt_offer_corpse = interrupt_butcher, hungry",
"interrupt_vampire_feed = interrupt_butcher",
"interrupt_passwall = interrupt_butcher",
"interrupt_multidrop = interrupt_butcher",
@@ -493,7 +495,6 @@ 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/mutation.cc b/crawl-ref/source/mutation.cc
index 45ce62d218..a23aac08fb 100644
--- a/crawl-ref/source/mutation.cc
+++ b/crawl-ref/source/mutation.cc
@@ -1434,7 +1434,7 @@ static void _display_vampire_attributes()
{"Bat Form ", "no ", "no ", "yes ", "yes ", "yes ", "yes "},
- {"Spell hunger ", "full ", "full ", "full ", "reduced ", "lowered ", "none "}
+ {"Spell hunger ", "full ", "full ", "full ", "halved ", "none ", "none "}
};
int current = 0;
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index d7c49328c8..f96b3ec1d2 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6017,13 +6017,15 @@ void player::make_hungry(int hunger_increase, bool silent)
}
// For semi-undead species (Vampire!) reduce food cost for spells and abilities
-// to 75% (hungry), 50% (very hungry), 25% (near starving), or zero (starving).
+// to 50% (hungry, very hungry) or zero (near starving, starving).
int calc_hunger(int food_cost)
{
if (you.is_undead == US_SEMI_UNDEAD && you.hunger_state < HS_SATIATED)
{
- food_cost *= you.hunger_state;
- food_cost /= 4;
+ if (you.hunger_state <= HS_NEAR_STARVING)
+ return 0;
+
+ return (food_cost/2);
}
return (food_cost);
}
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 52da4191de..af4d0b3ba3 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -4586,7 +4586,7 @@ static bool _god_likes_item(god_type god, const item_def& item)
switch (god)
{
case GOD_KIKUBAAQUDGHA: case GOD_TROG:
- return item.base_type == OBJ_CORPSES;
+ return (item.base_type == OBJ_CORPSES || is_blood_potion(item));
case GOD_NEMELEX_XOBEH:
return !is_deck(item);
@@ -5020,18 +5020,16 @@ std::string god_hates_your_god_reaction(god_type god,
bool god_likes_butchery(god_type god)
{
- return
- god == GOD_OKAWARU ||
- god == GOD_MAKHLEB ||
- god == GOD_TROG ||
- god == GOD_BEOGH ||
- god == GOD_LUGONU;
+ return (god == GOD_OKAWARU
+ || god == GOD_MAKHLEB
+ || god == GOD_TROG
+ || god == GOD_BEOGH
+ || god == GOD_LUGONU);
}
bool god_hates_butchery(god_type god)
{
- return
- god == GOD_ELYVILON;
+ return (god == GOD_ELYVILON);
}
harm_protection_type god_protects_from_harm(god_type god, bool actual)
diff --git a/crawl-ref/source/tutorial.cc b/crawl-ref/source/tutorial.cc
index f2480f9445..e77664d47c 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.
@@ -2434,7 +2434,8 @@ void tutorial_describe_item(const item_def &item)
"<w>d</w>rop menu. On a related note, offering several "
"corpses on a floor square is facilitated by using the "
"<w>c</w>hop prompt where <w>c</w> is a valid synonym "
- "for <w>y</w>es.";
+ "for <w>y</w>es, or directly chopping <w>a</w>ll "
+ "corpses.";
}
#endif
Options.tutorial_events[TUT_SEEN_CARRION] = 0;