yet (I had "You stop feeding" followed by "You continue feeding" including full effects), but it's probably better to commit now anyway. Known potions of blood or porridge cannot be quaffed when engorged (alive). Also clean up blood potions check.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4871 c06c8d41-db1a-0410-9941-cceddc491573
RQR4PTMGQLTRWLYRU3KXIIDGND7FBORESJWMWFVD3WYU5SISZXAAC
GZ4FB5VKL4C22KK3GSKQPLJYMRGLFXUDCOBNEBC2OKK6KVZL3OSQC
CDLXSWKIUQAM6TJRTU6HUSYVQXPHXN34NILPPHT2PJ2TPTJT3I2AC
N7CJFGD46WJE3ESYSEOJAYE63HAZBBAR5LB463ITAXKVN5FPTRYAC
NRIZKLUO26UHNKB4IERXI6ECMD2IJYZACQNIUU3SH6BPLGHAJYVAC
WQLOHSNCA3VOMDJF6IINJYKSYVYZEBPJJWBB33QSNE4RP5HEXPMAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
QCUMH3C7GXV7ZW444WT5SFAXQOJKJSE2YCQCEHMRYXCWF4QI7UMAC
Q3XHNSHW6FI4JCXSEABATRFBJPMCF7PXNG2K6ZQTRRPVMIZFHUBQC
M2HMYLYYXSP5XGX6MCI77IT6UW5K4YSEUJWHPQPYXVSW5L36BJ2AC
R5UWCN73VGZBWSRVBEMDX5D6WH3NGKUGBTNUGVAH32QFQSKSSZDAC
PBKRKGKARGZSLVFVDTK5NWDXQD26NHNN67LDSSB75CLEWBR6TLEQC
GXXYPBFEWKRZQ6OBGYNS2EXZN52NGNV3UU3WM6S5R74CMJBAKGTAC
KBNY5FWKTEAKABFCLPC3QFKFSVZKAGXINPCIFV6WDSWFO4VCKNTAC
VXSORUQOM2VZA4CAZDC6KPAY373NQIN3UT7CXQXTRCYXO2WM62DAC
2O3C3MTT2ZBYIFGPJ4MF5R4AXBYUHOEN62KAUWFWF6JWHIIVLRNQC
5FBOE2QNRLKUNOP54CZD6LFAMM7LX6NNLHJRJHRDDIUTQ7J723DQC
DTO3EUKWHZ5RJNGNCFYXSOVTIPVXPP637F2W7WFGYKJ7JK7VNKNQC
OXHOOJE4XEQKGI3JKURNSITG6CRQFAOFQ2EKKG6M5DCLN7LS4GUAC
25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC
7F557LW23VUXRRVQLNL7MKECGJGPPFVVEMEZUXXYNNOYC4635HVAC
CGYTZT5QWIEGYKUOLOK7MFXSLJKLYRZONER5ZCDZO5XYWSLG475QC
KBTDCQ7GYBRPB346ZEOJ4OM2XHOHN6FJMVMTOJ42EDK5KJX7VLIAC
2H32CFFM2FNS63JJPNM2S6HMO543EX72GMPOU5GI6HTMQYPL6I3AC
ARVJY7XPMCHI4IAQMD2VUWTAXQLCRNVSM2MK3YT4S4WHQYFTLEMAC
74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC
6PNVX6Q45HH733TZDXYBA6BYPJKDMND5BA4N2MP6HA3QVNCEPN2QC
JCWJWGMQIKQGSSFJUQRKNIWW3HBOJSHYDTOPPE5BWOJTIJTDYUTAC
2WVP47RBNL5OVYMAZH7TKRYD7F2TGSZ5X74PWVGAYCQP26G3JUHQC
P2ZCF3BBG523ZEOD6XQA4X5YEHBTWH3IM33YVHXP2SQ5POXZIH4QC
TFNFP2YQA4EOVE4VIXBEQSGACZSXHWIQ2T4TIPQ46R2MJW2C4B5AC
5TG5LXU4DX65KMWCZ7YJHOB3VAETQAVBUHEUSQTPMA327XV2HQWAC
2VOD7XONHR3G2JGZGXOPHNR2AN7WUQZFR5KJH5ZY4P4G67H3RCSQC
JXOE7KJIEAJHPLMZAJ6O4YHDTRB6BGNP6XT3ZSEFYGSIUMHR77KQC
5ZG33P3GHTV45HM5STF23BNSV7T4Z6MGCLPRGCNHIVCQUTHDPOTQC
H7KLIGBECC2SCGAIFPZFZ7P2TVDKR67HQ7AG5LXPP5SVNL7RWAHAC
3ZWALZFSTSIVYXY4BAY6ANGINTDACZC6RSSJTEMQSTSUIE66YOBQC
MLZSEZWNNZMSIDQNAAIOJJR4K7VSVJICL5SAGHD3ROM7SYDVZABAC
DMRXDEKHHBQNY37NPGZFAGUQPALWFANGGK4CUWIOQUPSLM2JBNFQC
QHAYBZTRPVJMK55WXT3F63CNRSAEVN3CQAAG42GCJTONLXQLNNNQC
SWT4O2TCOAQOVFA6WRA7MCU3KMTMJWFEMIHO64N4PWL5FNHDPADAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
4EZVKDQA5GM3QDTNTCKEKGH4F6LGAYNLBT756PXODKZ2B7C4ZVHAC
BBQWA33DPXWEDYOOPO45VAYD4JQDZQVMZSEJ4RUI5LLC733IMIIQC
G4TVXOLIF5X2MWV7I4UPT3MSQHRMGME6QRIIFAQ64C45JGYK7SIAC
OI7JKBFFIMIGWID2EJSMRP2EPEJH5YY42WTEY4QSSL6PFKRU3KJQC
IPXXB4VRVZWOU5DKQ5ZTD37LS3QNK2R6APNZUO672YEEJT6OFAYQC
5R4WV4H5SNIM5WU2X33JJ63HIEGKCXN2HELZ6FRRKKANPLMRLF3QC
CY63M5CMG4LYSCOK6QPRLFJEWCB3OMULUZBZCCJDJ6VGPOYDHZ6AC
23PFLB2E4QHL5SF3Q2YV5FXRH6MFHENEU2ACVC572ZCYDXCBZVQAC
PSLBTBSCSC65MRX6TEGGFNKPXLP4OE2FZYGMM6VRJTBXTTGMP5UQC
3UHMSNL7FEGVWYDX6AAJD2XQUQQ3HJMMTDR66IORZPYP5MJ2L7AQC
MBBPLL4SZUB3JUUYQYLZW7S5OXRCEGJX3WWADOQXGHWQ7BIKCY5QC
SGR2P5BGJIJHVSSQYQHWS4ORLVHQBZTDES3D4BFC6SVAQXSKENNQC
if (mitm[obj].base_type == OBJ_POTIONS
&& (mitm[obj].sub_type == POT_BLOOD
|| mitm[obj].sub_type == POT_BLOOD_COAGULATED))
{
if (is_blood_potion(mitm[obj]))
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 mons_type, int mass,
int chunk_type, bool rotten);
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);
if (you.species != SP_VAMPIRE)
return;
const int mons_type = food.plus;
const bool rotten = food_is_rotten(food);
const int chunk_type
= determine_chunk_effect(mons_corpse_effect( mons_type ), rotten);
const int mass = mons_weight(food.plus)/150;
if (!vampire_consume_corpse(mons_type, mass, chunk_type, rotten))
return;
if (!mons_skeleton( mons_type ) || one_chance_in(4))
{
dec_inv_item_quantity( which_inventory_slot, 1 );
}
else
{
food.sub_type = CORPSE_SKELETON;
food.special = 90;
food.colour = LIGHTGREY;
}
_vampire_consume_corpse(which_inventory_slot, true);
const int mons_type = food.plus;
const bool rotten = food_is_rotten(food);
const int chunk_type
= determine_chunk_effect(mons_corpse_effect( mons_type ), rotten);
const int mass = mons_weight(food.plus)/150;
if (!vampire_consume_corpse(mons_type, mass, chunk_type, rotten))
if (you.species != SP_VAMPIRE)
if (!mons_skeleton( mons_type ) || one_chance_in(4))
{
dec_mitm_item_quantity( item_link, 1 );
}
else
{
food.sub_type = CORPSE_SKELETON;
food.special = 90;
food.colour = LIGHTGREY;
}
// dec_mitm_item_quantity( item_link, 1 );
if (_vampire_consume_corpse(item_link, false))
you.turn_is_over = true;
// through food::determine_chunk_effect() first {dlb}:
static void eat_chunk( int chunk_effect, bool cannibal, int mon_intel )
// through food::_determine_chunk_effect() first {dlb}:
static void _eat_chunk( int chunk_effect, bool cannibal, int mon_intel )
// Divide full nutrition by duration, so that each turn you get the same
// amount of nutrition. Also, experimentally regenerate 1 hp per feeding turn
// - this is likely too strong.
// feeding is -1 at start, 1 when finishing, and 0 else
void vampire_nutrition_per_turn(const item_def &corpse, int feeding)
{
const int mons_type = corpse.plus;
const int chunk_type = _determine_chunk_effect(
mons_corpse_effect(mons_type), false);
// This is the exact formula of corpse nutrition for chunk lovers
const int max_chunks = mons_weight(mons_type)/150;
int chunk_amount = 1 + max_chunks/2;
chunk_amount = stepdown_value( chunk_amount, 4, 4, 12, 12 );
int food_value = CHUNK_BASE_NUTRITION;
// int mass = CHUNK_BASE_NUTRITION * chunk_amount;
const int duration = 1 + chunk_amount/2;
bool start_feeding = false;
bool during_feeding = false;
bool end_feeding = false;
if (feeding < 0)
start_feeding = true;
else if (feeding > 0)
end_feeding = true;
else
during_feeding = true;
switch (mons_type)
{
case MONS_HUMAN:
{
food_value += random2avg((you.experience_level * 10)/duration, 2);
int hp_amt = 1 + you.experience_level/2;
if (!end_feeding)
{
if (start_feeding)
mpr("This warm blood tastes really delicious!");
// Human blood gives extra healing during feeding.
if (hp_amt >= duration)
hp_amt /= duration;
else if (random2(duration) < hp_amt)
hp_amt = 1;
_heal_from_food(hp_amt, 0, one_chance_in(duration/2),
one_chance_in(duration));
}
else
{
// Give the remainder of healing at the end.
if (hp_amt > duration)
{
_heal_from_food(hp_amt % duration, 0,
one_chance_in(duration/2),
one_chance_in(duration));
}
}
break;
}
case MONS_ELF:
{
food_value += random2avg((you.experience_level * 10)/duration, 2);
if (end_feeding)
{
// Elven blood gives mana at the end of feeding.
const int mp_amt = 1 + random2(3);
_heal_from_food(1, mp_amt, one_chance_in(duration/2),
one_chance_in(duration));
}
else if (start_feeding)
mpr("This warm blood tastes magically delicious!");
break;
}
default:
switch (chunk_type)
{
case CE_CLEAN:
if (start_feeding)
mpr("This warm blood tastes delicious!");
else if (end_feeding)
_heal_from_food(1, 0, one_chance_in(duration), false);
break;
case CE_CONTAMINATED:
food_value = CHUNK_BASE_NUTRITION/2;
if (start_feeding)
mpr("Somehow this blood was not very filling!");
else if (end_feeding)
_heal_from_food(1, 0, one_chance_in(duration), false);
break;
case CE_POISONOUS:
make_hungry(CHUNK_BASE_NUTRITION/2, false);
// Always print this message - maybe you lost poison res.
// due to feeding.
mpr("Blech - this blood tastes nasty!");
if (poison_player( 1 + random2(3) ))
xom_is_stimulated(random2(128));
stop_delay();
return;
case CE_MUTAGEN_RANDOM:
food_value = CHUNK_BASE_NUTRITION/2;
if (start_feeding)
mpr("This blood tastes really weird!");
mutate(RANDOM_MUTATION);
did_god_conduct( DID_DELIBERATE_MUTATING, 10);
xom_is_stimulated(100);
if (end_feeding)
_heal_from_food(1, 0, false, false);
break;
case CE_MUTAGEN_BAD:
food_value = CHUNK_BASE_NUTRITION/2;
if (start_feeding)
mpr("This blood tastes *really* weird.");
give_bad_mutation();
did_god_conduct( DID_DELIBERATE_MUTATING, 10);
xom_is_stimulated(random2(200));
if (end_feeding)
_heal_from_food(1, 0, false, false);
break;
case CE_HCL:
rot_player( 5 + random2(5) );
if (disease_player( 50 + random2(100) ))
xom_is_stimulated(random2(100));
stop_delay();
break;
}
}
if (!end_feeding)
lessen_hunger(food_value / duration, !start_feeding);
}
// This is the exact formula of corpse nutrition for chunk lovers
int chunk_amount = 1 + random2(max_chunks);
chunk_amount = stepdown_value( chunk_amount, 4, 4, 12, 12 );
int mass = CHUNK_BASE_NUTRITION * chunk_amount;
if (wearing_amulet(AMU_THE_GOURMAND))
{
food_value = mass/2 + random2(you.experience_level * 5);
mpr("Slurp.");
did_god_conduct(DID_DRINK_BLOOD, 8);
}
else
{
mpr("It's not fresh enough.");
return false;
}
}
else
{
hp_amt++;
switch (mons_type)
{
case MONS_HUMAN:
food_value = mass + random2avg(you.experience_level * 10, 2);
mpr( "This warm blood tastes really delicious!" );
hp_amt += 1 + random2(1 + you.experience_level);
break;
case MONS_ELF:
food_value = mass + random2avg(you.experience_level * 10, 2);
mpr( "This warm blood tastes magically delicious!" );
mp_amt += 1 + random2(3);
break;
default:
switch (chunk_type)
{
case CE_CLEAN:
food_value = mass;
mpr( "This warm blood tastes delicious!" );
break;
case CE_CONTAMINATED:
food_value = mass / (random2(3) + 1);
mpr( "Somehow this blood was not very filling!" );
break;
case CE_POISONOUS:
food_value = -random2(mass/2);
mpr( "Blech - this blood tastes nasty!" );
if (poison_player( 3 + random2(4) ))
xom_is_stimulated(random2(128));
break;
case CE_MUTAGEN_RANDOM:
food_value = random2(mass);
mpr( "This blood tastes really weird!" );
mutate(RANDOM_MUTATION);
did_god_conduct( DID_DELIBERATE_MUTATING, 10);
xom_is_stimulated(100);
break;
case CE_MUTAGEN_BAD:
food_value = random2(mass/2);
mpr("This blood tastes *really* weird.");
give_bad_mutation();
did_god_conduct( DID_DELIBERATE_MUTATING, 10);
xom_is_stimulated(random2(200));
break;
case CE_HCL:
rot_player( 10 + random2(10) );
if (disease_player( 50 + random2(100) ))
xom_is_stimulated(random2(100));
break;
}
}
did_god_conduct(DID_DRINK_BLOOD, 8);
mpr("It's not fresh enough.");
return false;
heal_from_food(hp_amt, mp_amt,
!rotten && one_chance_in(4), one_chance_in(3));
lessen_hunger( food_value, true );
describe_food_change(food_value);
// but the delay should be greater.
start_delay( DELAY_EAT, mass / 400 );
// but the delay should be smaller.
const int max_chunks = mons_weight(corpse.plus)/150;
int chunk_amount = 1 + max_chunks/2;
chunk_amount = stepdown_value( chunk_amount, 4, 4, 12, 12 );
start_delay( DELAY_FEED_VAMPIRE, 1 + chunk_amount/2,
(int) invent, slot );
item_def &corpse = (delay.parm1 ? you.inv[delay.parm2]
: mitm[delay.parm2]);
if (!mons_skeleton( corpse.plus ))
{
if (delay.parm1)
dec_inv_item_quantity( delay.parm2, 1 );
else
dec_mitm_item_quantity( delay.parm2, 1 );
}
else
{
mpr("All blood oozes out of the corpse!");
bleed_onto_floor(you.x_pos, you.y_pos, corpse.plus, delay.duration,
false);
corpse.sub_type = CORPSE_SKELETON;
corpse.special = 90;
corpse.colour = LIGHTGREY;
}
did_god_conduct(DID_DRINK_BLOOD, 8);
pop_delay();
break;
}
mprf(MSGCH_MULTITURN_ACTION, "You continue %sing.",
you.species == SP_VAMPIRE ? "drink" : "eat");
mpr("You continue eating.", MSGCH_MULTITURN_ACTION);
break;
case DELAY_FEED_VAMPIRE:
{
item_def &corpse = (delay.parm1 ? you.inv[delay.parm2]
: mitm[delay.parm2]);
if (food_is_rotten(corpse))
{
mpr("This corpse has started to rot.", MSGCH_ROTTEN_MEAT);
stop_delay();
break;
}
mprf(MSGCH_MULTITURN_ACTION, "You continue drinking.");
vampire_nutrition_per_turn(corpse, 0);
case DELAY_FEED_VAMPIRE:
{
mprf("You finish drinking.");
did_god_conduct(DID_DRINK_BLOOD, 8);
item_def &corpse = (delay.parm1 ? you.inv[delay.parm2]
: mitm[delay.parm2]);
vampire_nutrition_per_turn(corpse, 1);
if (!mons_skeleton( corpse.plus ))
{
if (delay.parm1)
dec_inv_item_quantity( delay.parm2, 1 );
else
dec_mitm_item_quantity( delay.parm2, 1 );
}
else if (!one_chance_in(4))
{
corpse.sub_type = CORPSE_SKELETON;
corpse.special = 90;
corpse.colour = LIGHTGREY;
}
break;
}
"not_delayed", "eat", "armour_on", "armour_off", "jewellery_on",
"memorise", "butcher", "weapon_swap", "passwall",
"not_delayed", "eat", "vampire_feed", "armour_on", "armour_off",
"jewellery_on", "memorise", "butcher", "weapon_swap", "passwall",