summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-14 23:29:19 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-14 23:29:19 +0000
commit94002884ec345eb4e7d6680d6ce26c9b3b0a245a (patch)
tree2823754e89885a73fb83dd1c0ea07b76e88e3a6d
parent3b818666ded14091b0ad01215b66fe1fccf2a2d6 (diff)
downloadcrawl-ref-94002884ec345eb4e7d6680d6ce26c9b3b0a245a.tar.gz
crawl-ref-94002884ec345eb4e7d6680d6ce26c9b3b0a245a.zip
Vampires, yay! Credit mostly goes to Jarmo, though
there are a few traces of things I've changed (that I've included and then commented out). There's still lots of stuff to be added, but they should be playable right now. I notice that their vampiric bite attack needs to be made more probable. Feel free to comment on anything that looks weird, is plain wrong, or goes against the spirit of Crawl/Stonesoup. Positive feedback will be appreciated as well. :) git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1870 c06c8d41-db1a-0410-9941-cceddc491573
-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;