From 1d5b5da76795d490b6cd64b35d0c61d19f25b5e9 Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Sun, 28 Sep 2008 19:52:12 +0000 Subject: Vampire feeding changes: * remove randomness and unify formulas for nutrition value of blood potions and corpses, so bottling potions can no longer be used to enforce greater nutrition: this means that draining corpses give more nutrition now * draining duration now matches nutrition more closely (the formulas used to be completely distinct, and quite complicated) * decrease blood potions' nutrition again (I'd increased it in my previous related commit), coagulated blood gives only 80% nutrition * blood potions last a bit longer (counter 2000 -> 2500) * healing from blood potions is impossible * healing from corpses is only possible while they're still fresh (i.e. won't start rotting soon, counter > 150) * remove unrotting etc. effects, decrease healing from human corpses git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7055 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/food.cc | 144 +++++++++++++++++++++++++++----------------- crawl-ref/source/it_use2.cc | 4 +- crawl-ref/source/misc.cc | 45 ++++++++------ crawl-ref/source/misc.h | 1 + crawl-ref/source/stuff.cc | 2 +- 5 files changed, 119 insertions(+), 77 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index f5c0823b2d..b4c18e1b08 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -58,8 +58,8 @@ 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 void _heal_from_food(int hp_amt, int mp_amt = 0, bool unrot = false, + bool restore_str = false); /* * BEGIN PUBLIC FUNCTIONS @@ -97,6 +97,7 @@ void lessen_hunger( int satiated_amount, bool suppress_msg ) if (you.is_undead == US_UNDEAD) return; + mprf("satiated_amount: %d", satiated_amount); you.hunger += satiated_amount; if (you.hunger > 12000) @@ -1426,7 +1427,7 @@ static void _eat_chunk( int chunk_effect, bool cannibal, int mon_intel ) if (you.species == SP_GHOUL) { _heal_from_food((!one_chance_in(5) ? hp_amt : 0), 0, - !one_chance_in(3), false); + !one_chance_in(3)); } } else @@ -1759,20 +1760,44 @@ void finished_eating_message(int food_type) // 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 + +// Here are some values for nutrition (quantity * 1000) and duration: +// max_chunks quantity duration +// 1 1 1 +// 2 1 1 +// 3 1 2 +// 4 1 2 +// 5 1 2 +// 6 2 3 +// 7 2 3 +// 8 2 3 +// 9 2 4 +// 10 2 4 +// 12 3 5 +// 15 3 5 +// 20 4 6 +// 25 4 6 +// 30 5 7 + 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. + // Duration depends on corpse weight. 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 chunk_amount = 1 + max_chunks/3; + chunk_amount = stepdown_value( chunk_amount, 6, 6, 12, 12 ); + + // Add 1 for the artificial extra call at the start of draining. + const int duration = 1 + chunk_amount; + + // Use number of potions per corpse to calculate total nutrition, which + // then gets distributed over the entire duration. + int food_value = CHUNK_BASE_NUTRITION + * num_blood_potions_from_corpse(mons_type, chunk_type); - 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; @@ -1787,70 +1812,73 @@ void vampire_nutrition_per_turn(const item_def &corpse, int feeding) 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) + // Human may give a bit of healing during feeding as long as + // the corpse is still fairly fresh. + if (corpse.special > 150) { - if (start_feeding) - mpr("This warm blood tastes really delicious!"); + int hp_amt = 1 + you.experience_level/3; - // Human blood gives extra healing during feeding. - if (hp_amt >= duration) - hp_amt /= duration; - else if (x_chance_in_y(hp_amt, duration)) - hp_amt = 1; + if (!end_feeding) + { + if (start_feeding) + mpr("This warm blood tastes really delicious!"); - _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) + if (hp_amt >= duration) + hp_amt /= duration; + else if (x_chance_in_y(hp_amt, duration)) + hp_amt = 1; + + _heal_from_food(hp_amt); + } + else { - _heal_from_food(hp_amt % duration, 0, - one_chance_in(duration/2), - one_chance_in(duration)); + // Give the remainder of healing at the end. + if (hp_amt > duration) + _heal_from_food(hp_amt % duration); } } break; - } + case MONS_ELF: - { food_value += random2avg((you.experience_level * 10)/duration, 2); - if (end_feeding) + // Elven blood gives a bit of mana at the end of feeding, but + // only from fairly fresh corpses. + if (corpse.special > 150) { - // 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)); + if (end_feeding) + { + const int mp_amt = 1 + random2(3); + _heal_from_food(1, mp_amt); + } + else if (start_feeding) + mpr("This warm blood tastes magically delicious!"); } - 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); + else if (end_feeding && corpse.special > 150) + _heal_from_food(1); break; + case CE_CONTAMINATED: - food_value = CHUNK_BASE_NUTRITION/2; + food_value /= 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); + else if (end_feeding && corpse.special > 150) + _heal_from_food(1); break; + case CE_POISONOUS: - make_hungry(CHUNK_BASE_NUTRITION/2, false); + make_hungry(food_value/2, false); // Always print this message - maybe you lost poison res. // due to feeding. mpr("Blech - this blood tastes nasty!"); @@ -1858,26 +1886,29 @@ void vampire_nutrition_per_turn(const item_def &corpse, int feeding) xom_is_stimulated(random2(128)); stop_delay(); return; + case CE_MUTAGEN_RANDOM: - food_value = CHUNK_BASE_NUTRITION/2; + food_value /= 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); + // Sometimes heal by one hp. + if (end_feeding && corpse.special > 150 && coinflip()) + _heal_from_food(1); break; + case CE_MUTAGEN_BAD: - food_value = CHUNK_BASE_NUTRITION/2; + food_value /= 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); + // No healing from bad mutagenic blood. break; + case CE_HCL: rot_player( 5 + random2(5) ); if (disease_player( 50 + random2(100) )) @@ -1889,6 +1920,8 @@ void vampire_nutrition_per_turn(const item_def &corpse, int feeding) if (!end_feeding) lessen_hunger(food_value / duration, !start_feeding); + else + mprf("feeding finished: %d turns", duration); } // Returns true if a food item (also corpses) is poisonous AND the player @@ -2341,16 +2374,15 @@ static bool _vampire_consume_corpse(const int slot, bool invent) // Here the base nutrition value equals that of chunks, // 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 ); + int duration = 1 + max_chunks/3; + duration = stepdown_value( duration, 6, 6, 12, 12 ); // Get some nutrition right away, in case we're interrupted. // (-1 for the starting message.) vampire_nutrition_per_turn(corpse, -1); // The draining delay doesn't have a start action, and we only need // the continue/finish messages if it takes longer than 1 turn. - start_delay( DELAY_FEED_VAMPIRE, chunk_amount/2, - (int) invent, slot ); + start_delay( DELAY_FEED_VAMPIRE, duration, (int) invent, slot ); return (true); } diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc index e8217e08d6..84942b6f72 100644 --- a/crawl-ref/source/it_use2.cc +++ b/crawl-ref/source/it_use2.cc @@ -85,11 +85,11 @@ bool potion_effect( potion_type pot_eff, int pow, bool was_known ) { // No healing anymore! (jpeg) - int value = 1000; + int value = 800; if (pot_eff == POT_BLOOD) { mpr("Yummy - fresh blood!"); - value += 500; + value += 200; } else // coagulated mpr("This tastes delicious!"); diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index aa9a7c04fd..04c51de4a5 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -194,7 +194,7 @@ void init_stack_blood_potions(item_def &stack, int age) if (age == -1) { if (stack.sub_type == POT_BLOOD) - age = 2000; + age = 2500; else // coagulated blood age = 500; } @@ -908,8 +908,29 @@ bool can_bottle_blood_from_corpse(int mons_type) return (false); } -// Maybe potions should automatically merge into those already on the floor, -// or the player's inventory. +int num_blood_potions_from_corpse(int mons_class, int chunk_type) +{ + if (chunk_type == -1) + chunk_type = mons_corpse_effect(mons_class); + + // Max. amount is about one third of the max. amount for chunks. + const int max_chunks = mons_weight( mons_class ) / 150; + + // Max. amount is about one third of the max. amount for chunks. + int pot_quantity = max_chunks/3; + pot_quantity = stepdown_value( pot_quantity, 2, 2, 6, 6 ); + + // Halve number of potions obtained from contaminated chunk type corpses. + if (chunk_type == CE_CONTAMINATED) + pot_quantity /= 2; + + if (pot_quantity < 1) + pot_quantity = 1; + + return (pot_quantity); +} + +// If autopickup is active, the potions are auto-picked up after creation. void turn_corpse_into_blood_potions( item_def &item ) { ASSERT( item.base_type == OBJ_CORPSES ); @@ -923,24 +944,12 @@ void turn_corpse_into_blood_potions( item_def &item ) item_colour(item); item.flags &= ~(ISFLAG_THROWN | ISFLAG_DROPPED); - // Max. amount is about one third of the max. amount for chunks. - const int max_chunks = mons_weight( mons_class ) / 150; - item.quantity = 1 + random2( max_chunks/3 ); - item.quantity = stepdown_value( item.quantity, 2, 2, 6, 6 ); - - // Lower number of potions obtained from contaminated chunk type corpses. - if (mons_corpse_effect( mons_class ) == CE_CONTAMINATED) - { - item.quantity /= (random2(3) + 1); - - if (item.quantity < 1) - item.quantity = 1; - } + item.quantity = num_blood_potions_from_corpse(mons_class); // Initialize timer depending on corpse age: // almost rotting: age = 100 --> potion timer = 500 --> will coagulate soon - // freshly killed: age = 200 --> potion timer = 2000 --> fresh !blood - init_stack_blood_potions(item, (item.special - 100) * 15 + 500); + // freshly killed: age = 200 --> potion timer = 2500 --> fresh !blood + init_stack_blood_potions(item, (item.special - 100) * 20 + 500); // Happens after the blood has been bottled. if (monster_descriptor(mons_class, MDSC_LEAVES_HIDE) && !one_chance_in(3)) diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h index 35b5df6daa..21fc63889c 100644 --- a/crawl-ref/source/misc.h +++ b/crawl-ref/source/misc.h @@ -36,6 +36,7 @@ void drop_blood_potions_stack( item_def &stack, int quant, void pick_up_blood_potions_stack( item_def &stack, int quant ); bool can_bottle_blood_from_corpse( int mons_type ); +int num_blood_potions_from_corpse( int mons_class, int chunk_type = -1 ); void turn_corpse_into_blood_potions ( item_def &item ); void split_potions_into_decay( int obj, int amount, bool need_msg = true ); diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index adab2d84b7..377c772102 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -851,7 +851,7 @@ int stepdown_value(int base_value, int stepping, int first_step, return return_value; for (int this_step = first_step; this_step <= last_step; - this_step += stepping) + this_step += stepping) { if (return_value > this_step) return_value = ((return_value - this_step) / 2) + this_step; -- cgit v1.2.3-54-g00ecf