diff options
-rw-r--r-- | crawl-ref/source/abl-show.cc | 16 | ||||
-rw-r--r-- | crawl-ref/source/acr.cc | 40 | ||||
-rw-r--r-- | crawl-ref/source/chardump.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/clua.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/decks.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/delay.cc | 11 | ||||
-rw-r--r-- | crawl-ref/source/describe.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/effects.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 9 | ||||
-rw-r--r-- | crawl-ref/source/fight.cc | 113 | ||||
-rw-r--r-- | crawl-ref/source/food.cc | 163 | ||||
-rw-r--r-- | crawl-ref/source/it_use2.cc | 107 | ||||
-rw-r--r-- | crawl-ref/source/itemname.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/makeitem.cc | 15 | ||||
-rw-r--r-- | crawl-ref/source/mutation.cc | 43 | ||||
-rw-r--r-- | crawl-ref/source/newgame.cc | 44 | ||||
-rw-r--r-- | crawl-ref/source/output.cc | 33 | ||||
-rw-r--r-- | crawl-ref/source/player.cc | 111 | ||||
-rw-r--r-- | crawl-ref/source/religion.cc | 15 | ||||
-rw-r--r-- | crawl-ref/source/shopping.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/skills2.cc | 43 | ||||
-rw-r--r-- | crawl-ref/source/spells4.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/spl-cast.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/transfor.cc | 33 |
24 files changed, 773 insertions, 53 deletions
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc index c19f33abb7..2d962bc3a3 100644 --- a/crawl-ref/source/abl-show.cc +++ b/crawl-ref/source/abl-show.cc @@ -168,6 +168,7 @@ static const ability_def Ability_List[] = { ABIL_BREATHE_POWER, "Breathe Power", 0, 0, 125, 0, ABFLAG_BREATH }, { ABIL_BREATHE_STICKY_FLAME, "Breathe Sticky Flame", 0, 0, 125, 0, ABFLAG_BREATH }, { ABIL_BREATHE_STEAM, "Breathe Steam", 0, 0, 75, 0, ABFLAG_BREATH }, + { ABIL_TRAN_BAT, "Bat Form", 2, 0, 25, 0, ABFLAG_NONE }, { ABIL_SPIT_ACID, "Spit Acid", 0, 0, 125, 0, ABFLAG_BREATH }, @@ -507,6 +508,12 @@ static talent get_talent(ability_type ability, bool check_confused) case ABIL_FLY_II: // this is for draconians {dlb} failure = 45 - (you.experience_level + you.strength); break; + + case ABIL_TRAN_BAT: + invoc = true; + failure = 45 - (you.experience_level + you.skills[SK_INVOCATIONS]); +// perfect = true; + break; // end species abilties (some mutagenic) // begin demonic powers {dlb} @@ -1655,6 +1662,10 @@ static bool do_ability(const ability_def& abil) exercise(SK_INVOCATIONS, 2 + random2(4)); break; + case ABIL_TRAN_BAT: + transform(100, TRAN_BAT); + break; + case ABIL_RENOUNCE_RELIGION: if (yesno("Really renounce your faith, foregoing its fabulous benefits?") && yesno( "Are you sure you won't change your mind later?" )) @@ -1844,6 +1855,11 @@ std::vector<talent> your_talents( bool check_confused ) } } + if (you.species == SP_VAMPIRE && you.experience_level >= 3) + { + add_talent(talents, ABIL_TRAN_BAT, check_confused ); + } + //jmf: alternately put check elsewhere if ((you.level_type == LEVEL_DUNGEON && you.mutation[MUT_MAPPING]) || (you.level_type == LEVEL_PANDEMONIUM && you.mutation[MUT_MAPPING]==3)) diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 33a5bae395..abb5544e27 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -1228,12 +1228,24 @@ void process_command( command_type cmd ) break; case CMD_THROW: + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + { + mpr("You can't throw anything in your present form!"); + flush_input_buffer( FLUSH_ON_FAILURE ); + break; + } if (Options.tutorial_left) Options.tut_throw_counter++; throw_anything(); break; case CMD_FIRE: + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + { + mpr("You can't fire anything in your present form!"); + flush_input_buffer( FLUSH_ON_FAILURE ); + break; + } if (Options.tutorial_left) Options.tut_throw_counter++; shoot_thing(); @@ -1253,10 +1265,22 @@ void process_command( command_type cmd ) break; case CMD_REMOVE_JEWELLERY: + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + { + mpr("You can't do that in your present form!"); + flush_input_buffer( FLUSH_ON_FAILURE ); + break; + } remove_ring(); break; case CMD_WEAR_JEWELLERY: + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + { + mpr("You can't do that in your present form!"); + flush_input_buffer( FLUSH_ON_FAILURE ); + break; + } puton_ring(-1, false); break; @@ -1333,7 +1357,14 @@ void process_command( command_type cmd ) flush_input_buffer( FLUSH_ON_FAILURE ); break; } - +/* + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + { + mpr("You can't cast spells in your present form!"); + flush_input_buffer( FLUSH_ON_FAILURE ); + break; + } +*/ if (Options.tutorial_left) Options.tut_spell_counter++; if (!cast_a_spell()) @@ -1756,6 +1787,13 @@ static void decrement_durations() { you.duration[DUR_TRANSFORMATION]--; + if (you.species == SP_VAMPIRE + && you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT + && you.duration[DUR_TRANSFORMATION] > 2) + { + you.duration[DUR_TRANSFORMATION] = 5; + } + if (you.duration[DUR_TRANSFORMATION] == 10) { mpr("Your transformation is almost over.", MSGCH_DURATION); diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index f1ea172024..44d61bfad4 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -217,6 +217,9 @@ static void sdump_transform(dump_params &par) case TRAN_SPIDER: text += "You are in spider-form."; break; + case TRAN_BAT: + text += "You are in bat-form."; + break; case TRAN_BLADE_HANDS: text += "Your hands are blades."; break; diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index 2c20e1592b..fa7da822f1 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -670,6 +670,8 @@ static const char *transform_name() { case TRAN_SPIDER: return "spider"; + case TRAN_BAT: + return "bat"; case TRAN_BLADE_HANDS: return "blade"; case TRAN_STATUE: diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index bc859a48e9..8b257d4d94 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -758,9 +758,12 @@ static void metamorphosis_card(int power, deck_rarity_type rarity) if ( power_level >= 2 ) trans = (coinflip() ? TRAN_DRAGON : TRAN_LICH); else if ( power_level == 1 ) - trans = (coinflip() ? TRAN_STATUE : TRAN_BLADE_HANDS); + { + trans = (one_chance_in(3) ? TRAN_STATUE : + (coinflip() ? TRAN_ICE_BEAST : TRAN_BLADE_HANDS)); + } else - trans = (coinflip() ? TRAN_SPIDER : TRAN_ICE_BEAST); + trans = (coinflip() ? TRAN_SPIDER : TRAN_BAT); transform(random2(power/4), trans); } diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc index 5f4d8877db..fc5b8576ca 100644 --- a/crawl-ref/source/delay.cc +++ b/crawl-ref/source/delay.cc @@ -492,7 +492,10 @@ static void finish_delay(const delay_queue_item &delay) break; } case DELAY_EAT: - mpr( "You finish eating." ); + if (you.species == SP_VAMPIRE) + mpr( "You finish drinking." ); + else + mpr( "You finish eating." ); // For chunks, warn the player if they're not getting much // nutrition. if (delay.parm1) @@ -560,9 +563,13 @@ static void finish_delay(const delay_queue_item &delay) if (is_valid_item(item) && item.base_type == OBJ_CORPSES) { mprf("You finish %s the corpse into pieces.", - (you.species==SP_TROLL || you.species == SP_GHOUL) ? "ripping" + (you.species==SP_TROLL || you.species == SP_GHOUL + || you.mutation[MUT_FANGS] == 3) ? "ripping" : "chopping"); + if (you.species == SP_VAMPIRE) + mpr("What a waste."); + turn_corpse_into_chunks( mitm[ delay.parm1 ] ); if (you.duration[DUR_BERSERKER] && you.berserk_penalty != NO_BERSERK_PENALTY) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 477da3828b..fbb133bb34 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2215,6 +2215,9 @@ static const char* describe_potion( const item_def &item ) "which may be afflicting you.$"; case POT_MUTATION: return "A potion which does very strange things to you.$"; + case POT_BLOOD: + return "A potion containing the essence of life. Vital for all living " + "creatures, as well as some undead ones.$"; case NUM_POTIONS: return "A buggy potion."; } diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index 3cfafba58c..481f513bac 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -508,6 +508,13 @@ static int find_acquirement_subtype(object_class_type class_wanted, type_wanted = one_chance_in(10) ? FOOD_ROYAL_JELLY : FOOD_CHUNK; } + else if (you.species == SP_VAMPIRE) + { + // Vampires really don't want any OBJ_FOOD but OBJ_CORPSES + // but it's easier to just give them a potion of blood + class_wanted = OBJ_POTIONS; + type_wanted = POT_BLOOD; + } else { // Meat is better than bread (except for herbivores), and diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 3dccf66f89..513fda23fc 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -123,6 +123,7 @@ enum ability_type ABIL_TRAN_SERPENT_OF_HELL, ABIL_ROTTING, ABIL_TORMENT_II, + ABIL_TRAN_BAT, ABIL_RENOUNCE_RELIGION = 250 // 250 }; @@ -799,6 +800,7 @@ enum conduct_type DID_SPELL_NONUTILITY, // unused DID_CARDS, DID_STIMULANTS, // unused + DID_DRINK_BLOOD, DID_EAT_MEAT, // unused DID_CREATED_LIFE, // unused @@ -2705,6 +2707,7 @@ enum mutation_type MUT_SMITE, // 57 MUT_CLAWS, //jmf: added MUT_HOOVES, //jmf: etc. + MUT_FANGS, MUT_BREATHE_POISON, // 60 MUT_STINGER, MUT_BIG_WINGS, @@ -2875,6 +2878,7 @@ enum potion_type POT_BERSERK_RAGE, POT_CURE_MUTATION, POT_MUTATION, + POT_BLOOD, NUM_POTIONS }; @@ -3309,6 +3313,7 @@ enum species_type SP_MERFOLK, SP_ELF, // (placeholder) SP_HILL_DWARF, // (placeholder) + SP_VAMPIRE, NUM_SPECIES, // always after the last species SP_UNKNOWN = 100 @@ -3713,6 +3718,7 @@ enum transformation_type TRAN_LICH, TRAN_SERPENT_OF_HELL, TRAN_AIR, + TRAN_BAT, NUM_TRANSFORMATIONS // must remain last member {dlb} }; @@ -3803,7 +3809,8 @@ enum unarmed_attack_type UNAT_KICK, UNAT_HEADBUTT, UNAT_TAILSLAP, - UNAT_PUNCH + UNAT_PUNCH, + UNAT_BITE }; enum undead_state_type // you.is_undead diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 527aececd5..6cfed06cd3 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -165,7 +165,7 @@ static int maybe_random2( int x, bool random_factor ) // Returns the to-hit for your extra unarmed.attacks. // DOES NOT do the final roll (i.e., random2(your_to_hit)). -static int calc_your_to_hit_unarmed() +static int calc_your_to_hit_unarmed(int uattack = UNAT_NO_ATTACK, bool vampiric = false) { int your_to_hit; @@ -175,7 +175,19 @@ static int calc_your_to_hit_unarmed() if (wearing_amulet(AMU_INACCURACY)) your_to_hit -= 5; - if (you.hunger_state == HS_STARVING) + // vampires know how to bite and aim better when hungry + if (you.species == SP_VAMPIRE && uattack == UNAT_BITE) + { + your_to_hit += 1; + if (vampiric) + { + if (you.hunger_state == HS_HUNGRY) + your_to_hit += 1; + else if (you.hunger_state == HS_STARVING) + your_to_hit += 2; + } + } + else if (you.species != SP_VAMPIRE && you.hunger_state == HS_STARVING) your_to_hit -= 3; your_to_hit += slaying_bonus(PWPN_HIT); @@ -554,6 +566,10 @@ bool melee_attack::player_aux_unarmed() else uattack = (coinflip() ? UNAT_HEADBUTT : UNAT_KICK); + if (you.mutation[MUT_FANGS] + || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON) + uattack = UNAT_BITE; + if ((you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON || player_genus(GENPC_DRACONIAN) || (you.species == SP_MERFOLK && player_is_swimming()) @@ -565,13 +581,17 @@ bool melee_attack::player_aux_unarmed() if (coinflip()) uattack = UNAT_PUNCH; + + if (you.species == SP_VAMPIRE && coinflip()) + uattack = UNAT_BITE; } - for (int scount = 0; scount < 4; scount++) + for (int scount = 0; scount < 5; scount++) { unarmed_attack.clear(); damage_brand = SPWPN_NORMAL; aux_damage = 0; + bool vampiric = false; switch (scount) { @@ -590,7 +610,8 @@ bool melee_attack::player_aux_unarmed() if (you.attribute[ATTR_TRANSFORMATION] == TRAN_SERPENT_OF_HELL || you.attribute[ATTR_TRANSFORMATION] == TRAN_ICE_BEAST || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON - || you.attribute[ATTR_TRANSFORMATION] == TRAN_SPIDER) + || you.attribute[ATTR_TRANSFORMATION] == TRAN_SPIDER + || you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) { continue; } @@ -626,7 +647,8 @@ bool melee_attack::player_aux_unarmed() if (you.attribute[ATTR_TRANSFORMATION] == TRAN_SERPENT_OF_HELL || you.attribute[ATTR_TRANSFORMATION] == TRAN_SPIDER || you.attribute[ATTR_TRANSFORMATION] == TRAN_ICE_BEAST - || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON) + || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON + || you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) { continue; } @@ -668,7 +690,8 @@ bool melee_attack::player_aux_unarmed() } if (you.attribute[ATTR_TRANSFORMATION] == TRAN_SPIDER - || you.attribute[ATTR_TRANSFORMATION] == TRAN_ICE_BEAST) + || you.attribute[ATTR_TRANSFORMATION] == TRAN_ICE_BEAST + || you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) { continue; } @@ -699,7 +722,8 @@ bool melee_attack::player_aux_unarmed() if (you.attribute[ATTR_TRANSFORMATION] == TRAN_SERPENT_OF_HELL || you.attribute[ATTR_TRANSFORMATION] == TRAN_SPIDER || you.attribute[ATTR_TRANSFORMATION] == TRAN_ICE_BEAST - || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON) + || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON + || you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) { continue; } @@ -733,6 +757,34 @@ bool melee_attack::player_aux_unarmed() break; + case 4: + if (uattack != UNAT_BITE) + { + continue; + } + if (!you.mutation[MUT_FANGS] || !one_chance_in(5)) + { + continue; + } + + unarmed_attack = "bite"; +// simple_miss_message = true; + + aux_damage += you.mutation[MUT_FANGS] * 2; + + // prob: 1/4 when non-hungry, 1/2 when hungry, 100% when starving + if (you.species == SP_VAMPIRE) + { + if (you.hunger_state > HS_HUNGRY && coinflip()) + break; + if (you.hunger_state > HS_STARVING && coinflip()) + break; + + damage_brand = SPWPN_VAMPIRICISM; + vampiric = true; + } + break; + /* To add more, add to while part of loop below as well */ default: continue; @@ -740,7 +792,7 @@ bool melee_attack::player_aux_unarmed() } // unified to-hit calculation - to_hit = random2( calc_your_to_hit_unarmed() ); + to_hit = random2( calc_your_to_hit_unarmed(uattack, vampiric) ); make_hungry(2, true); @@ -1178,6 +1230,7 @@ int melee_attack::player_weapon_type_modify(int damage) switch (you.attribute[ATTR_TRANSFORMATION]) { case TRAN_SPIDER: + case TRAN_BAT: if (damage < HIT_STRONG) attack_verb = "bite"; else @@ -1334,7 +1387,29 @@ bool melee_attack::player_monattk_hit_effects(bool mondied) did_god_conduct(DID_UNHOLY, 1); } - if (mondied && damage_brand == SPWPN_VAMPIRICISM) + if (you.species == SP_VAMPIRE && damage_brand == SPWPN_VAMPIRICISM) + { + if (mons_holiness(def) == MH_NATURAL + && damage_done > 0 && you.hp < you.hp_max + && !one_chance_in(5)) + { + mpr("You feel better."); + + int heal = 1 + random2(damage_done); + if (heal > you.experience_level) + heal = you.experience_level; + + heal += 1 + random2(damage_done); + inc_hp(heal, false); + + if (you.hunger_state < HS_ENGORGED) + { + lessen_hunger(45 + random2avg(59, 2), true); + } + did_god_conduct(DID_DRINK_BLOOD, 5 + random2(4)); + } + } + else if (mondied && damage_brand == SPWPN_VAMPIRICISM) { if (mons_holiness(def) == MH_NATURAL && damage_done > 0 && you.hp < you.hp_max @@ -1343,7 +1418,9 @@ bool melee_attack::player_monattk_hit_effects(bool mondied) mpr("You feel better."); // more than if not killed - inc_hp(1 + random2(damage_done), false); + int heal = 1 + random2(damage_done); + + inc_hp(heal, false); if (you.hunger_state != HS_ENGORGED) lessen_hunger(30 + random2avg(59, 2), true); @@ -2194,6 +2271,9 @@ int melee_attack::player_to_hit(bool random_factor) case TRAN_SPIDER: your_to_hit += maybe_random2(10, random_factor); break; + case TRAN_BAT: + your_to_hit += maybe_random2(12, random_factor); + break; case TRAN_ICE_BEAST: your_to_hit += maybe_random2(10, random_factor); break; @@ -2379,7 +2459,10 @@ int melee_attack::player_unarmed_speed() if (you.burden_state == BS_UNENCUMBERED && one_chance_in(heavy_armour_penalty + 1)) { - unarmed_delay = 10 - you.skills[SK_UNARMED_COMBAT] / 5; + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + unarmed_delay = 10 - you.skills[SK_UNARMED_COMBAT] / 3; + else + unarmed_delay = 10 - you.skills[SK_UNARMED_COMBAT] / 5; /* this shouldn't happen anyway...sanity */ if (unarmed_delay < min_delay) @@ -2427,6 +2510,9 @@ int melee_attack::player_calc_base_unarmed_damage() case TRAN_SPIDER: damage = 5; break; + case TRAN_BAT: + damage = (you.species == SP_VAMPIRE ? 2 : 1); + break; case TRAN_ICE_BEAST: damage = 12; break; @@ -2459,7 +2545,10 @@ int melee_attack::player_calc_base_unarmed_damage() damage += (you.mutation[ MUT_CLAWS ] * 2); } - damage += you.skills[SK_UNARMED_COMBAT]; + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + damage += you.skills[SK_UNARMED_COMBAT]/3; + else + damage += you.skills[SK_UNARMED_COMBAT]; return (damage); } diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 6131af95f5..ec8dbbdc25 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -53,6 +53,8 @@ static void eating(unsigned char item_class, int item_type); static void ghoul_eat_flesh( int chunk_effect ); static void describe_food_change(int hunger_increment); static bool food_change(bool suppress_message); +bool vampire_consume_corpse(int mons_type, int mass, + int chunk_type, bool rotten); /* ************************************************** @@ -191,7 +193,10 @@ bool butchery(void) const transformation_type transform = static_cast<transformation_type>(you.attribute[ATTR_TRANSFORMATION]); - + + // Xom probably likes this, occasionally + bool teeth_butcher = (you.mutation[MUT_FANGS] == 3); + bool barehand_butcher = (you.equip[ EQ_GLOVES ] == -1 && (transform_can_butcher_barehanded(transform) @@ -207,7 +212,7 @@ bool butchery(void) !item_cursed(you.inv[you.equip[EQ_GLOVES]])); int old_gloves = you.equip[EQ_GLOVES]; - bool can_butcher = barehand_butcher || + bool can_butcher = teeth_butcher || barehand_butcher || (you.equip[EQ_WEAPON] != -1 && can_cut_meat(you.inv[you.equip[EQ_WEAPON]])); @@ -315,7 +320,7 @@ bool butchery(void) if ( can_butcher ) { // we actually butcher now - if ( barehand_butcher ) + if ( teeth_butcher || barehand_butcher ) mpr("You start tearing the corpse apart."); else mpr("You start hacking away."); @@ -431,7 +436,7 @@ bool prompt_eat_from_inventory(void) prompt_invent_item( "Eat which item?", MT_INVLIST, - OBJ_FOOD, + you.species == SP_VAMPIRE ? OBJ_CORPSES : OBJ_FOOD, true, true, true, 0, NULL, OPER_EAT ); if (which_inventory_slot == PROMPT_ABORT) @@ -442,12 +447,21 @@ bool prompt_eat_from_inventory(void) // this conditional can later be merged into food::can_ingest() when // expanded to handle more than just OBJ_FOOD 16mar200 {dlb} - if (you.inv[which_inventory_slot].base_type != OBJ_FOOD) + if (you.species != SP_VAMPIRE && + you.inv[which_inventory_slot].base_type != OBJ_FOOD) { mpr("You can't eat that!"); return (false); } + if (you.species == SP_VAMPIRE && + (you.inv[which_inventory_slot].base_type != OBJ_CORPSES + || you.inv[which_inventory_slot].sub_type != CORPSE_BODY)) + { + mpr("You crave blood!"); + return (false); + } + if (!can_ingest( you.inv[which_inventory_slot].base_type, you.inv[which_inventory_slot].sub_type, false )) { @@ -515,6 +529,12 @@ static bool food_change(bool suppress_message) if (you.species == SP_GHOUL && you.hunger > 6999) you.hunger = 6999; + // vampires can never be engorged or starve to death + if (you.species == SP_VAMPIRE && you.hunger <= 700) + you.hunger = 701; + if (you.species == SP_VAMPIRE && you.hunger > 10999) + you.hunger = 10999; + // get new hunger state if (you.hunger <= 1000) newstate = HS_STARVING; @@ -586,7 +606,29 @@ static void describe_food_change(int food_increment) void eat_from_inventory(int which_inventory_slot) { - if (you.inv[which_inventory_slot].sub_type == FOOD_CHUNK) + if (you.inv[which_inventory_slot].base_type == OBJ_CORPSES + && you.inv[which_inventory_slot].sub_type == CORPSE_BODY) + { + const int mons_type = you.inv[ which_inventory_slot ].plus; + const int chunk_type = mons_corpse_effect( mons_type ); + const bool rotten = (you.inv[which_inventory_slot].special < 100); + const int mass = item_mass( you.inv[which_inventory_slot] ); + + if (!vampire_consume_corpse(mons_type, mass, chunk_type, rotten)) + return; + + if (!mons_skeleton( mons_type )) { + dec_inv_item_quantity( which_inventory_slot, 1 ); + } + else { + you.inv[which_inventory_slot].sub_type = CORPSE_SKELETON; + you.inv[which_inventory_slot].special = 90; + you.inv[which_inventory_slot].colour = LIGHTGREY; + } + // dec_inv_item_quantity( which_inventory_slot, 1 ); + return; + } + else if (you.inv[which_inventory_slot].sub_type == FOOD_CHUNK) { // this is a bit easier to read... most compilers should // handle this the same -- bwr @@ -607,7 +649,31 @@ void eat_from_inventory(int which_inventory_slot) void eat_floor_item(int item_link) { - if (mitm[item_link].sub_type == FOOD_CHUNK) + if (mitm[item_link].base_type == OBJ_CORPSES + && mitm[item_link].sub_type == CORPSE_BODY) + { + const int mons_type = mitm[item_link].plus; + const int chunk_type = mons_corpse_effect( mons_type ); + const bool rotten = (mitm[item_link].special < 100); + const int mass = item_mass( mitm[item_link] ); + + if (!vampire_consume_corpse(mons_type, mass, chunk_type, rotten)) + return; + + if (!mons_skeleton( mons_type )) { + dec_mitm_item_quantity( item_link, 1 ); + } + else { + mitm[item_link].sub_type = CORPSE_SKELETON; + mitm[item_link].special = 90; + mitm[item_link].colour = LIGHTGREY; + } + // dec_mitm_item_quantity( item_link, 1 ); + + you.turn_is_over = 1; + return; + } + else if (mitm[item_link].sub_type == FOOD_CHUNK) { const int chunk_type = mons_corpse_effect( mitm[item_link].plus ); const bool rotten = (mitm[item_link].special < 100); @@ -634,11 +700,16 @@ bool eat_from_floor(void) { item_def& item = mitm[o]; - if (item.base_type != OBJ_FOOD) + if (you.species != SP_VAMPIRE && item.base_type != OBJ_FOOD) + continue; + + if (you.species == SP_VAMPIRE && + (item.base_type != OBJ_CORPSES || item.sub_type != CORPSE_BODY)) continue; mprf( MSGCH_PROMPT, - "Eat %s%s?", (item.quantity > 1) ? "one of " : "", + "%s %s%s?", you.species == SP_VAMPIRE ? "Drink blood from" : "Eat", + (item.quantity > 1) ? "one of " : "", item.name(DESC_NOCAP_A).c_str() ); // If we're prompting now, we don't need a -more- when @@ -1141,6 +1212,18 @@ bool can_ingest(int what_isit, int kindof_thing, bool suppress_msg, bool reqid, return (false); } + if (you.species == SP_VAMPIRE) + { + if (what_isit == OBJ_CORPSES && kindof_thing == CORPSE_BODY) + { + return (true); + } + else + { + mpr("Blech - you need blood!"); + } + return (false); + } bool ur_carnivorous = (you.mutation[MUT_CARNIVOROUS] == 3); @@ -1352,3 +1435,65 @@ static int determine_chunk_effect(int which_chunk_type, bool rotten_chunk) return (this_chunk_effect); } // end determine_chunk_effect() + +bool vampire_consume_corpse(int mons_type, int mass, + int chunk_type, bool rotten) { + int food_value = 0; + + if (chunk_type == CE_HCL) { + mpr( "There is no blood in this body!" ); + return false; + } + else if (!rotten) { + inc_hp(1, false); + + switch (mons_type) { + case MONS_HUMAN: + food_value = mass + random2avg(you.experience_level * 10, 2); + mpr( "This warm blood tastes really delicious!" ); + inc_hp(1 + random2(1 + you.experience_level), false); + break; + + case MONS_ELF: + food_value = mass + random2avg(you.experience_level * 10, 2); + mpr( "This warm blood tastes magically delicious!" ); + inc_mp(1 + random2(3), false); + break; + + default: + food_value = mass; + mpr( "This warm blood tastes delicious!" ); + break; + } + did_god_conduct(DID_DRINK_BLOOD, 8); + } + else if (wearing_amulet(AMU_THE_GOURMAND)){ + food_value = mass/3 + random2(you.experience_level * 5); + mpr("Slurps."); + did_god_conduct(DID_DRINK_BLOOD, 8); + } + else { + mpr("It's not fresh enough."); + return false; + } + + lessen_hunger( food_value, true ); + describe_food_change(food_value); + + if (player_rotted() && !rotten && one_chance_in(4)) + { + mpr("You feel more resilient."); + unrot_hp(1); + } + + if (you.strength < you.max_strength && one_chance_in(3)) + { + mpr("You feel your strength returning."); + you.strength++; + you.redraw_strength = 1; + } + +// start_delay( DELAY_EAT, 3 ); + start_delay( DELAY_EAT, 1 + mass/300 ); + return true; +} // end vampire_consume_corpse() diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc index 9738564c53..eac0ba2cac 100644 --- a/crawl-ref/source/it_use2.cc +++ b/crawl-ref/source/it_use2.cc @@ -54,6 +54,16 @@ bool potion_effect( potion_type pot_eff, int pow ) switch (pot_eff) { case POT_HEALING: + if (you.species == SP_VAMPIRE) + { + inc_hp((5 + random2(7)) / 2, false); + if (!one_chance_in(3)) + you.rotting = 0; + if (!one_chance_in(3)) + you.duration[DUR_CONF] = 0; + mpr("You feel slightly better."); + break; + } mpr("You feel better."); inc_hp(5 + random2(7), false); @@ -71,6 +81,12 @@ bool potion_effect( potion_type pot_eff, int pow ) break; case POT_HEAL_WOUNDS: + if (you.species == SP_VAMPIRE /*&& you.hunger_state */) + { + inc_hp((10 + random2avg(28, 3)) / 2, false); + mpr("You feel better."); + break; + } mpr("You feel much better."); inc_hp(10 + random2avg(28, 3), false); @@ -83,6 +99,11 @@ bool potion_effect( potion_type pot_eff, int pow ) break; case POT_SPEED: + if (you.species == SP_VAMPIRE) + { + haste_player( (40 + random2(pow)) / 2 ); + break; + } haste_player( 40 + random2(pow) ); break; @@ -158,16 +179,34 @@ bool potion_effect( potion_type pot_eff, int pow ) break; case POT_SLOWING: + if (you.species == SP_VAMPIRE) + { + slow_player( (10 + random2(pow)) / 2 ); + xom_is_stimulated(32); + break; + } slow_player( 10 + random2(pow) ); xom_is_stimulated(64); break; case POT_PARALYSIS: + if (you.species == SP_VAMPIRE) + { + slow_player( 10 + random2(pow) ); + xom_is_stimulated(32); + break; + } you.paralyse(2 + random2( 6 + you.duration[DUR_PARALYSIS] )); xom_is_stimulated(64); break; case POT_CONFUSION: + if (you.species == SP_VAMPIRE) + { + confuse_player( (3 + random2(8)) / 2 ); + xom_is_stimulated(54); + break; + } confuse_player( 3 + random2(8) ); xom_is_stimulated(128); break; @@ -190,11 +229,23 @@ bool potion_effect( potion_type pot_eff, int pow ) // carnivore check here? {dlb} case POT_PORRIDGE: // oatmeal - always gluggy white/grey? + if (you.species == SP_VAMPIRE) + { + mpr("Blech - that potion was really gluggy!"); + break; + } mpr("That potion was really gluggy!"); lessen_hunger(6000, true); break; case POT_DEGENERATION: + if (you.species == SP_VAMPIRE) + { + mpr("There was something wrong with that liquid!"); + lose_stat(STAT_RANDOM, 1 + random2(2)); + xom_is_stimulated(32); + break; + } mpr("There was something very wrong with that liquid!"); lose_stat(STAT_RANDOM, 1 + random2avg(4, 2)); xom_is_stimulated(64); @@ -212,6 +263,11 @@ bool potion_effect( potion_type pot_eff, int pow ) break; case POT_WATER: + if (you.species == SP_VAMPIRE) + { + mpr("Blech - this tastes like water."); + break; + } mpr("This tastes like water."); // we should really separate thirst from hunger {dlb} // Thirst would just be annoying for the player, the @@ -256,6 +312,12 @@ bool potion_effect( potion_type pot_eff, int pow ) break; case POT_BERSERK_RAGE: + if (you.species == SP_VAMPIRE) + { + mpr("You feel slightly irritated."); + make_hungry(100, false); + break; + } go_berserk(true); xom_is_stimulated(64); break; @@ -279,6 +341,51 @@ bool potion_effect( potion_type pot_eff, int pow ) did_god_conduct(DID_STIMULANTS, 4 + random2(4)); break; + case POT_BLOOD: + if (you.species == SP_VAMPIRE) + { + int temp_rand = random2(9); + strcpy(info, (temp_rand == 0) ? "human" : + (temp_rand == 1) ? "rat" : + (temp_rand == 2) ? "goblin" : + (temp_rand == 3) ? "elf" : + (temp_rand == 4) ? "goat" : + (temp_rand == 5) ? "sheep" : + (temp_rand == 6) ? "gnoll" : + (temp_rand == 7) ? "sheep" + : "yak"); + + mprf("Yummy - fresh %s blood!", info); + + lessen_hunger(1000, true); + mpr("You feel better."); + inc_hp(1 + random2(10), false); + } + else + { + bool likes_blood = (you.species == SP_KOBOLD + || you.species == SP_OGRE + || you.species == SP_TROLL + || you.mutation[MUT_CARNIVOROUS]); + + if (likes_blood) + { + mpr("This tastes like blood."); + lessen_hunger(200, true); + } + else + { + mpr("Blech - this tastes like blood!"); + if (!you.mutation[MUT_HERBIVOROUS] && one_chance_in(3)) + lessen_hunger(100, true); + else + disease_player( 50 + random2(100) ); + xom_is_stimulated(32); + } + did_god_conduct(DID_DRINK_BLOOD, 1 + random2(3)); + } + break; + case NUM_POTIONS: mpr("You feel bugginess flow through your body."); break; diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc index 12aa67ed59..fc9decb7ce 100644 --- a/crawl-ref/source/itemname.cc +++ b/crawl-ref/source/itemname.cc @@ -480,6 +480,7 @@ static const char* potion_type_name(int potiontype) case POT_BERSERK_RAGE: return "berserk rage"; case POT_CURE_MUTATION: return "cure mutation"; case POT_MUTATION: return "mutation"; + case POT_BLOOD: return "blood"; default: return "bugginess"; } } diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index c3269a0fbd..99a2542278 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -2403,21 +2403,24 @@ int items( int allow_uniques, // not just true-false, case 4: // enhancements if (coinflip()) - mitm[p].sub_type = POT_SPEED; // 6.444% + mitm[p].sub_type = POT_SPEED; // 6.122% else - mitm[p].sub_type = POT_MIGHT; // 6.444% + mitm[p].sub_type = POT_MIGHT; // 6.122% if (one_chance_in(10)) - mitm[p].sub_type = POT_BERSERK_RAGE; // 1.432% + mitm[p].sub_type = POT_BERSERK_RAGE; // 1.360% if (one_chance_in(5)) - mitm[p].sub_type = POT_INVISIBILITY; // 3.580% + mitm[p].sub_type = POT_INVISIBILITY; // 3.401% if (one_chance_in(6)) - mitm[p].sub_type = POT_LEVITATION; // 3.580% + mitm[p].sub_type = POT_LEVITATION; // 3.401% if (one_chance_in(30)) - mitm[p].sub_type = POT_PORRIDGE; // 0.741% + mitm[p].sub_type = POT_PORRIDGE; // 0.704% + + if (one_chance_in(20)) + mitm[p].sub_type = POT_BLOOD; // 1.111% break; case 5: diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 5288b28fe0..a283201d12 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -246,6 +246,10 @@ const char *mutation_descrip[][3] = { {"You have hooves in place of feet.", "", ""}, // 60 - leave some space for more demonic powers... + + {"You have very sharp teeth.", "You have extremely sharp teeth.", + "You have razor-sharp teeth."}, + {"You can exhale a cloud of poison.", "", ""}, {"Your tail ends in a poisonous barb.", @@ -490,7 +494,11 @@ const char *gain_mutation[][3] = { "Your hands twist into claws."}, {"Your feet shrivel into cloven hooves.", "", ""}, - // 60 + // 60 + + {"Your teeth lengthen and sharpen.", + "Your teeth lengthen and sharpen some more.", + "Your teeth are very long and razor-sharp."}, {"You taste something nasty.", "You taste something very nasty.", "You taste something extremely nasty."}, @@ -712,6 +720,8 @@ const char *lose_mutation[][3] = { {"Your hooves expand and flesh out into feet!", "", ""}, // 60 + {"Your teeth shrink and become duller.", "", ""}, + {"", "", ""}, {"", "", ""}, {"", "", ""}, @@ -852,6 +862,7 @@ const char mutation_rarity[] = { 2, //jmf: claws 1, //jmf: hooves // 60 + 1, 0, 0, 0, @@ -1070,6 +1081,16 @@ formatted_string describe_mutations() have_any = true; break; + case SP_VAMPIRE: + result += "You are"; + result += (you.experience_level > 25 && you.hunger_state == HS_FULL) ? + " very strongly" : + (you.experience_level > 12 && you.hunger_state != HS_HUNGRY) ? + " strongly" : ""; + result += " in touch with the powers of death." EOL; + have_any = true; + break; + default: break; } //end switch - innate abilities @@ -1199,6 +1220,7 @@ static int calc_mutation_amusement_value(mutation_type which_mutation) case MUT_FRAIL: case MUT_CLAWS: case MUT_HOOVES: + case MUT_FANGS: case MUT_BREATHE_POISON: case MUT_STINGER: case MUT_BIG_WINGS: @@ -1402,6 +1424,15 @@ bool mutate(mutation_type which_mutation, bool failMsg, bool force_mutation, return false; } + if (mutat == MUT_HERBIVOROUS && you.species == SP_VAMPIRE) + return false; + + if (mutat == MUT_FANGS + && (you.species == SP_VAMPIRE || you.species == SP_KENKU)) + { + return false; + } + if (mutat == MUT_BIG_WINGS && !player_genus(GENPC_DRACONIAN)) return false; @@ -1549,6 +1580,10 @@ bool mutate(mutation_type which_mutation, bool failMsg, bool force_mutation, remove_one_equip(EQ_BOOTS); break; + case MUT_FANGS: + mpr(gain_mutation[mutat][you.mutation[mutat]], MSGCH_MUTATION); + break; + case MUT_CLAWS: mpr((you.species == SP_TROLL ? troll_claw_messages @@ -2330,6 +2365,12 @@ bool give_cosmetic_mutation() how_much = 1; } + if (you.species != SP_VAMPIRE && one_chance_in(5)) + { + mutation = MUT_FANGS; + how_much = 1 + random2(3); + } + if (player_genus(GENPC_DRACONIAN) && one_chance_in(5)) { mutation = MUT_BIG_WINGS; diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index d957b81237..522529acd9 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -390,6 +390,7 @@ static void initialise_item_descriptions() PDESCQ(PDQ_GLUGGY, PDC_WHITE); you.item_description[IDESC_POTIONS][POT_WATER] = PDESCS(PDC_CLEAR); + you.item_description[IDESC_POTIONS][POT_BLOOD] = PDESCS(PDC_RED); for (int i = 0; i < NUM_IDESC; i++) { @@ -452,8 +453,8 @@ static void initialise_item_descriptions() static void give_starting_food() { - // the undead start with no food - if (you.is_undead != US_ALIVE) + // these undead start with no food + if (you.species == SP_MUMMY || you.species == SP_GHOUL) return; item_def item; @@ -462,6 +463,11 @@ static void give_starting_food() item.base_type = OBJ_POTIONS; item.sub_type = POT_PORRIDGE; } + else if (you.species == SP_VAMPIRE) + { + item.base_type = OBJ_POTIONS; + item.sub_type = POT_BLOOD; + } else { item.base_type = OBJ_FOOD; @@ -634,6 +640,7 @@ static void give_species_bonus_hp() case SP_GREY_ELF: case SP_HIGH_ELF: + case SP_VAMPIRE: dec_max_hp(1); break; @@ -657,6 +664,7 @@ static void give_species_bonus_mp() // adjust max_magic_points by species {dlb} switch (you.species) { + case SP_VAMPIRE: case SP_SPRIGGAN: case SP_DEMIGOD: case SP_GREY_ELF: @@ -764,7 +772,9 @@ game_start: species_stat_init( you.species ); // must be down here {dlb} you.is_undead = ((you.species == SP_MUMMY) ? US_UNDEAD : - (you.species == SP_GHOUL) ? US_HUNGRY_DEAD : US_ALIVE); + (you.species == SP_GHOUL || you.species == SP_VAMPIRE) ? + US_HUNGRY_DEAD : + US_ALIVE); // before we get into the inventory init, set light radius based // on species vision. currently, all species see out to 8 squares. @@ -864,7 +874,7 @@ game_start: static bool species_is_undead( unsigned char speci ) { - return (speci == SP_MUMMY || speci == SP_GHOUL); + return (speci == SP_MUMMY || speci == SP_GHOUL || speci == SP_VAMPIRE); } static bool class_allowed( species_type speci, job_type char_class ) @@ -1171,6 +1181,8 @@ static bool class_allowed( species_type speci, job_type char_class ) case JOB_SUMMONER: if (player_genus(GENPC_DWARVEN, speci)) return false; + if (speci == SP_VAMPIRE) + return true; if (species_is_undead( speci )) return false; @@ -1774,6 +1786,7 @@ static void species_stat_init(species_type which_species) case SP_MUMMY: sb = 7; ib = 3; db = 3; break; // 13 case SP_GHOUL: sb = 9; ib = 1; db = 2; break; // 13 + case SP_VAMPIRE: sb = 5; ib = 6; db = 5; break; // 16 case SP_RED_DRACONIAN: case SP_WHITE_DRACONIAN: @@ -1903,6 +1916,11 @@ static void give_basic_mutations(species_type speci) case SP_KOBOLD: you.mutation[MUT_CARNIVOROUS] = 3; break; + case SP_VAMPIRE: + you.mutation[MUT_FANGS] = 3; + you.mutation[MUT_SLOW_METABOLISM] = 1; +// you.mutation[MUT_POISON_RESISTANCE] = 1; + break; default: break; } @@ -1914,6 +1932,9 @@ static void give_basic_mutations(species_type speci) static void give_basic_knowledge(job_type which_job) { + if (you.species == SP_VAMPIRE) + set_ident_type( OBJ_POTIONS, POT_BLOOD, ID_KNOWN_TYPE ); + switch (which_job) { case JOB_PRIEST: @@ -2900,7 +2921,7 @@ static job_type letter_to_class(int keyn) static species_type letter_to_species(int keyn) { - if ( keyn < 'a' || keyn > 'x' ) + if ( keyn < 'a' || keyn > 'y' ) return SP_UNKNOWN; const int offset = keyn - 'a'; int rc; @@ -3402,13 +3423,15 @@ bool give_items_skills() you.inv[2].special = 0; } } - else if (you.species == SP_GHOUL || you.species == SP_MUMMY) + else if (you.is_undead) { you.inv[1].quantity = 1; you.inv[1].base_type = OBJ_ARMOUR; you.inv[1].sub_type = ARM_ROBE; you.inv[1].plus = 0; you.inv[1].special = 0; + if (you.species == SP_VAMPIRE && coinflip()) + you.inv[1].sub_type = ARM_LEATHER_ARMOUR; if (you.species == SP_MUMMY) { @@ -3457,7 +3480,8 @@ bool give_items_skills() you.equip[EQ_BODY_ARMOUR] = 1; if (you.species != SP_KOBOLD && you.species != SP_OGRE - && you.species != SP_TROLL && you.species != SP_GHOUL) + && you.species != SP_TROLL && you.species != SP_GHOUL + && you.species != SP_VAMPIRE) { you.equip[EQ_SHIELD] = 2; } @@ -4886,6 +4910,12 @@ bool give_items_skills() break; } + // Vampires always start with unarmed combat skill. + if (you.species == SP_VAMPIRE && you.skills[SK_UNARMED_COMBAT] < 2) + { + you.skills[SK_UNARMED_COMBAT] = 2; + } + if (weap_skill) you.skills[weapon_skill(OBJ_WEAPONS, you.inv[0].sub_type)] = weap_skill; diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index d27962dc0e..1480f03cfc 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1318,8 +1318,15 @@ std::string status_mut_abilities() if (you.duration[DUR_PRAYER]) text += "praying, "; - if (you.duration[DUR_REGENERATION]) + if (you.duration[DUR_REGENERATION] + && (you.species != SP_VAMPIRE || you.hunger_state >= HS_HUNGRY) + || you.species == SP_VAMPIRE && you.hunger_state == HS_FULL) + { + if (you.disease) + text += "recuperating, "; + else text += "regenerating, "; + } // not used as resistance part already says so // if (you.duration[DUR_INSULATION]) @@ -1456,12 +1463,21 @@ std::string status_mut_abilities() text += info; + if (you.disease + || you.species == SP_VAMPIRE && you.hunger_state < HS_HUNGRY) + { + text += "non-regenerating"; + } + switch (you.attribute[ATTR_TRANSFORMATION]) { case TRAN_SPIDER: text += "\nYou are in spider-form."; break; - case TRAN_BLADE_HANDS: + case TRAN_BAT: + text += "\nYou are in bat-form."; + break; + case TRAN_BLADE_HANDS: text += "\nYou have blades for hands."; break; case TRAN_STATUE: @@ -1660,6 +1676,10 @@ std::string status_mut_abilities() have_any = true; break; + case SP_VAMPIRE: + text += "sharp teeth 3"; + have_any = true; + break; default: break; } //end switch - innate abilities @@ -2046,6 +2066,15 @@ std::string status_mut_abilities() text += "hooves"; have_any = true; break; + case MUT_FANGS: + if (you.species == SP_VAMPIRE) + break; + if (have_any) + text += ", "; + snprintf(info, INFO_SIZE, "sharp teeth %d", level); + text += info; + have_any = true; + break; case MUT_BREATHE_POISON: if (have_any) text += ", "; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 4f58b6fcf0..31ebf65021 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -693,6 +693,22 @@ int player_regen(void) rr /= 2; } + // healing depending on satiation + if (you.species == SP_VAMPIRE) + { + if (you.hunger_state == HS_FULL) + return (rr + 20); + else if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT + || you.hunger_state > HS_HUNGRY) + { + return rr; + } + else if (you.hunger_state == HS_HUNGRY) + return (rr / 2); + else if (you.hunger_state == HS_STARVING) + return 0; // no regeneration for starving vampires + } + if (rr < 1) rr = 1; @@ -703,6 +719,9 @@ int player_hunger_rate(void) { int hunger = 3; + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + return 1; + // jmf: hunger isn't fair while you can't eat // Actually, it is since you can detransform any time you like -- bwr if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR) @@ -738,9 +757,17 @@ int player_hunger_rate(void) hunger -= 2 * player_equip( EQ_RINGS, RING_SUSTENANCE ); // weapon ego types - hunger += 6 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ); - hunger += 9 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH ); - + if (you.species != SP_VAMPIRE) + { + hunger += 6 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ); + hunger += 9 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH ); + } + else + { + hunger += 1 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ); + hunger += 2 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH ); + } + // troll leather armour hunger += player_equip( EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR ); @@ -802,6 +829,7 @@ int player_res_magic(void) case SP_GREY_ELF: case SP_SLUDGE_ELF: case SP_MOUNTAIN_DWARF: + case SP_VAMPIRE: rm = you.experience_level * 4; break; case SP_NAGA: @@ -1167,6 +1195,16 @@ int player_spec_death() if (you.experience_level >= 26) sd++; } + else if (you.species == SP_VAMPIRE) + { + // Vampires get bonus only when not hungry + if (you.experience_level >= 13 && you.hunger_state > HS_HUNGRY) + { + sd++; + if (you.experience_level >= 26) + sd++; + } + } // transformations: if (you.attribute[ATTR_TRANSFORMATION] == TRAN_LICH) @@ -1319,7 +1357,11 @@ int player_prot_life(bool calc_unid) // armour: (checks body armour only) pl += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_POSITIVE_ENERGY ); - if (you.is_undead) + if (you.species == SP_VAMPIRE && you.hunger_state > HS_HUNGRY) + { + pl += 2; + } + else if (you.is_undead && you.species != SP_VAMPIRE) pl += 3; switch (you.attribute[ATTR_TRANSFORMATION]) @@ -1399,6 +1441,8 @@ int player_movement_speed(void) /* transformations */ if (you.attribute[ATTR_TRANSFORMATION] == TRAN_SPIDER) mv = 8; + else if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + mv = 5; // but allowed minimum is six /* armour */ if (player_equip_ego_type( EQ_BOOTS, SPARM_RUNNING )) @@ -2008,6 +2052,10 @@ int old_player_evasion(void) ev += 3; break; + case TRAN_BAT: + ev += 20 + (you.experience_level - 10); + break; + case TRAN_AIR: ev += 20; break; @@ -2101,6 +2149,10 @@ int player_see_invis(bool calc_unid) /* armour: (checks head armour only) */ si += player_equip_ego_type( EQ_HELMET, SPARM_SEE_INVISIBLE ); + /* Vampires can see invisible if not weakened by hunger */ + if (you.species == SP_VAMPIRE && you.hunger_state > HS_HUNGRY) + si++; + if (you.mutation[MUT_ACUTE_VISION] > 0) si += you.mutation[MUT_ACUTE_VISION]; @@ -2477,6 +2529,18 @@ void level_change(void) } break; + case SP_VAMPIRE: + if (you.experience_level == 3) + { + mpr( "You can now transform into a bat", + MSGCH_INTRINSIC_GAIN ); + } + else if (you.experience_level == 13 || you.experience_level == 26) + { + mpr( "You feel more in touch with the powers of death.", + MSGCH_INTRINSIC_GAIN ); + } + break; case SP_NAGA: // lower because of HD raise -- bwr // if (you.experience_level < 14) @@ -2870,7 +2934,7 @@ int check_stealth(void) stealth += (you.skills[SK_STEALTH] * 12); else { - switch (you.species) + switch (you.species) // why not use body_size here? { case SP_TROLL: case SP_OGRE: @@ -2886,6 +2950,14 @@ int check_stealth(void) case SP_KOBOLD: case SP_SPRIGGAN: case SP_NAGA: // not small but very good at stealth + case SP_VAMPIRE: + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT + || you.hunger_state <= HS_HUNGRY) + { + // Hungry vampires are more stealthy + stealth += (you.skills[SK_STEALTH] * 19); + break; + } stealth += (you.skills[SK_STEALTH] * 18); break; default: @@ -3003,6 +3075,9 @@ void display_char_status() case TRAN_SPIDER: mpr( "You are in spider-form." ); break; + case TRAN_BAT: + mpr( "You are in bat-form." ); + break; case TRAN_BLADE_HANDS: mpr( "You have blades for hands." ); break; @@ -3052,8 +3127,14 @@ void display_char_status() if (you.duration[DUR_PRAYER]) mpr( "You are praying." ); - if (you.duration[DUR_REGENERATION]) + if (you.duration[DUR_REGENERATION] && + (you.species != SP_VAMPIRE || you.hunger_state >= HS_HUNGRY)) + { + if (you.disease) + mpr("You are recuperating from your illness."); + else mpr( "You are regenerating." ); + } if (you.duration[DUR_SWIFTNESS]) mpr( "You can move swiftly." ); @@ -3145,6 +3226,9 @@ void display_char_status() " faster than usual." : ".") ); } + if (you.disease || you.species == SP_VAMPIRE && you.hunger_state < HS_HUNGRY) + mpr("You do not regenerate."); + // prints a contamination message contaminate_player( 0, true ); @@ -3473,6 +3557,9 @@ char *species_name( int speci, int level, bool genus, bool adj, bool cap ) case SP_MERFOLK: strcpy( species_buff, (adj) ? "Merfolkian" : "Merfolk" ); break; + case SP_VAMPIRE: + strcpy( species_buff, "Vampire" ); + break; default: strcpy( species_buff, (adj) ? "Yakish" : "Yak" ); break; @@ -3510,7 +3597,8 @@ bool wearing_amulet(char amulet, bool calc_unid) if (amulet == AMU_CONTROLLED_FLIGHT && (you.duration[DUR_CONTROLLED_FLIGHT] || player_genus(GENPC_DRACONIAN) - || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON)) + || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON + || you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)) { return true; } @@ -3580,6 +3668,7 @@ int species_exp_mod(char species) return 14; case SP_HIGH_ELF: case SP_MUMMY: + case SP_VAMPIRE: case SP_TROLL: case SP_OGRE_MAGE: return 15; @@ -4069,7 +4158,7 @@ static const char * Species_Abbrev_List[ NUM_SPECIES ] = { "XX", "Hu", "HE", "GE", "DE", "SE", "MD", "Ha", "HO", "Ko", "Mu", "Na", "Gn", "Og", "Tr", "OM", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", - "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "HD", "El" }; + "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp", "HD", "El" }; int get_species_index_by_abbrev( const char *abbrev ) { @@ -4789,6 +4878,7 @@ coord_def player::pos() const bool player::is_levitating() const { return (attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON || + attribute[ATTR_TRANSFORMATION] == TRAN_BAT || duration[DUR_LEVITATION]); } @@ -4950,6 +5040,11 @@ int player::damage_brand(int) ret = SPWPN_DRAINING; break; + case TRAN_BAT: + if (you.species == SP_VAMPIRE) + { + ret = SPWPN_VAMPIRICISM; + } // else fall through default: break; } diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 90474958fc..512903840b 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -953,6 +953,21 @@ bool did_god_conduct( conduct_type thing_done, int level ) switch (thing_done) { + case DID_DRINK_BLOOD: + switch (you.religion) + { + case GOD_ZIN: + case GOD_SHINING_ONE: + case GOD_ELYVILON: + // no penance as this can happen accidentally + piety_change = -2*level; + ret = true; + break; + default: + break; + } + break; + case DID_NECROMANCY: case DID_UNHOLY: case DID_ATTACK_HOLY: diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index d3124f835f..d90e8d636d 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -1128,6 +1128,7 @@ unsigned int item_value( item_def item, bool ident ) case POT_SPEED: valued += 25; break; + case POT_BLOOD: case POT_HEALING: case POT_LEVITATION: valued += 20; diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc index 4e9dbd8e6e..fdd25cc9db 100644 --- a/crawl-ref/source/skills2.cc +++ b/crawl-ref/source/skills2.cc @@ -1631,6 +1631,49 @@ const int spec_skills[ NUM_SPECIES ][40] = (100 * 75) / 100, // SK_EVOCATIONS }, + { // SP_VAMPIRE (38) + 110, // SK_FIGHTING + 100, // SK_SHORT_BLADES + 110, // SK_LONG_SWORDS + 110, // SK_UNUSED_1 + 110, // SK_AXES + 140, // SK_MACES_FLAILS + 110, // SK_POLEARMS + 140, // SK_STAVES + 140, // SK_SLINGS + 140, // SK_BOWS + 140, // SK_CROSSBOWS + 140, // SK_DARTS + 140, // SK_THROWING + 140, // SK_ARMOUR + 110, // SK_DODGING + 50, // SK_STEALTH + 100, // SK_STABBING + 140, // SK_SHIELDS + 110, // SK_TRAPS_DOORS + 90, // SK_UNARMED_COMBAT + 140, // undefined + 140, // undefined + 140, // undefined + 140, // undefined + 140, // undefined + (100 * 130)/100, // SK_SPELLCASTING + 160, // SK_CONJURATIONS + 140, // SK_ENCHANTMENTS + 100, // SK_SUMMONINGS + 100, // SK_NECROMANCY + 140, // SK_TRANSLOCATIONS + 120, // SK_TRANSMIGRATION + 140, // SK_DIVINATIONS + 140, // SK_FIRE_MAGIC + 140, // SK_ICE_MAGIC + 140, // SK_AIR_MAGIC + 140, // SK_EARTH_MAGIC + 140, // SK_POISON_MAGIC + (140 * 75)/100, // SK_INVOCATIONS + (140 * 75)/100, // SK_EVOCATIONS + }, + // SP_HILL_DWARF placeholder. { }, diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc index 97aca63a03..15c749342e 100644 --- a/crawl-ref/source/spells4.cc +++ b/crawl-ref/source/spells4.cc @@ -99,6 +99,7 @@ std::string your_hand( bool plural ) break; case TRAN_SERPENT_OF_HELL: case TRAN_DRAGON: + case TRAN_BAT: result = "foreclaw"; break; case TRAN_BLADE_HANDS: @@ -411,6 +412,7 @@ void cast_shatter(int pow) case TRAN_DRAGON: case TRAN_AIR: case TRAN_SERPENT_OF_HELL: + case TRAN_BAT: break; case TRAN_STATUE: // full damage @@ -2098,7 +2100,8 @@ void cast_fulsome_distillation( int powc ) switch (mons_corpse_effect( mitm[corpse].plus )) { case CE_CLEAN: - pot_type = (power_up ? POT_CONFUSION : POT_WATER); + pot_type = (power_up ? POT_CONFUSION : + one_chance_in(30)? POT_BLOOD : POT_WATER); break; case CE_CONTAMINATED: diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 70bf35da7b..16c5287227 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -437,6 +437,7 @@ int spell_fail(spell_type spell) break; case TRAN_SPIDER: + case TRAN_BAT: chance2 += 10; break; } diff --git a/crawl-ref/source/transfor.cc b/crawl-ref/source/transfor.cc index ebbfc8a621..3846120be5 100644 --- a/crawl-ref/source/transfor.cc +++ b/crawl-ref/source/transfor.cc @@ -114,6 +114,7 @@ size_type player::transform_size(int psize) const switch (transform) { case TRAN_SPIDER: + case TRAN_BAT: return SIZE_TINY; case TRAN_ICE_BEAST: return SIZE_LARGE; @@ -165,7 +166,7 @@ bool transform(int pow, transformation_type which_trans) if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE) untransform(); - if (you.is_undead) + if (you.is_undead && (you.species != SP_VAMPIRE || which_trans != TRAN_BAT)) { mpr("Your unliving flesh cannot be transformed in this way."); return (false); @@ -209,6 +210,30 @@ bool transform(int pow, transformation_type which_trans) you.colour = BROWN; return (true); + case TRAN_BAT: + // high ev, low ac, high speed + if (check_for_cursed_equipment( rem_stuff )) + return false; + + mprf("You turn into a %sbat.", + you.species == SP_VAMPIRE ? "vampire " : ""); + + remove_equipment( rem_stuff ); + // drop_everything(); + + you.attribute[ATTR_TRANSFORMATION] = TRAN_BAT; + you.duration[DUR_TRANSFORMATION] = 20 + random2(pow) + random2(pow); + + if (you.duration[DUR_TRANSFORMATION] > 100) + you.duration[DUR_TRANSFORMATION] = 100; + + modify_stat( STAT_DEXTERITY, 5, true ); + modify_stat( STAT_STRENGTH, -5, true ); + + you.symbol = 'b'; + you.colour = (you.species == SP_VAMPIRE) ? BLACK : DARKGREY; + return (true); + case TRAN_ICE_BEAST: // also AC +3, cold +3, fire -1, pois +1 mpr( "You turn into a creature of crystalline ice." ); @@ -420,6 +445,12 @@ void untransform(void) modify_stat( STAT_DEXTERITY, -5, true ); break; + case TRAN_BAT: + mpr("Your transformation has ended.", MSGCH_DURATION); + modify_stat( STAT_DEXTERITY, -5, true ); + modify_stat( STAT_STRENGTH, 5, true ); + break; + case TRAN_BLADE_HANDS: mpr( "Your hands revert to their normal proportions.", MSGCH_DURATION ); you.wield_change = true; |