summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/abl-show.cc16
-rw-r--r--crawl-ref/source/acr.cc40
-rw-r--r--crawl-ref/source/chardump.cc3
-rw-r--r--crawl-ref/source/clua.cc2
-rw-r--r--crawl-ref/source/decks.cc7
-rw-r--r--crawl-ref/source/delay.cc11
-rw-r--r--crawl-ref/source/describe.cc3
-rw-r--r--crawl-ref/source/effects.cc7
-rw-r--r--crawl-ref/source/enum.h9
-rw-r--r--crawl-ref/source/fight.cc113
-rw-r--r--crawl-ref/source/food.cc163
-rw-r--r--crawl-ref/source/it_use2.cc107
-rw-r--r--crawl-ref/source/itemname.cc1
-rw-r--r--crawl-ref/source/makeitem.cc15
-rw-r--r--crawl-ref/source/mutation.cc43
-rw-r--r--crawl-ref/source/newgame.cc44
-rw-r--r--crawl-ref/source/output.cc33
-rw-r--r--crawl-ref/source/player.cc111
-rw-r--r--crawl-ref/source/religion.cc15
-rw-r--r--crawl-ref/source/shopping.cc1
-rw-r--r--crawl-ref/source/skills2.cc43
-rw-r--r--crawl-ref/source/spells4.cc5
-rw-r--r--crawl-ref/source/spl-cast.cc1
-rw-r--r--crawl-ref/source/transfor.cc33
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;