summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/abl-show.cc111
-rw-r--r--crawl-ref/source/describe.cc4
-rw-r--r--crawl-ref/source/fight.cc199
-rw-r--r--crawl-ref/source/makeitem.cc10
-rw-r--r--crawl-ref/source/misc.cc2
-rw-r--r--crawl-ref/source/misc.h1
-rw-r--r--crawl-ref/source/mon-util.cc6
-rw-r--r--crawl-ref/source/monstuff.cc42
8 files changed, 219 insertions, 156 deletions
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 0fa31e07e5..5647cde72c 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -78,7 +78,7 @@
enum ability_flag_type
{
ABFLAG_NONE = 0x00000000,
- ABFLAG_BREATH = 0x00000001, // ability uses DUR_BREATH_WEAPON
+ ABFLAG_BREATH = 0x00000001, // ability uses DUR_BREATH_WEAPON
ABFLAG_DELAY = 0x00000002, // ability has its own delay (ie recite)
ABFLAG_PAIN = 0x00000004, // ability must hurt player (ie torment)
ABFLAG_EXHAUSTION = 0x00000008, // fails if you.exhausted
@@ -165,7 +165,7 @@ ability_type god_abilities[MAX_NUM_GODS][MAX_GOD_ABILITIES] =
// The description screen was way out of date with the actual costs.
// This table puts all the information in one place... -- bwr
-//
+//
// The four numerical fields are: MP, HP, food, and piety.
// Note: food_cost = val + random2avg( val, 2 )
// piety_cost = val + random2( (val + 1) / 2 + 1 );
@@ -186,7 +186,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_TRAN_BAT, "Bat Form", 2, 0, 0, 0, ABFLAG_NONE },
{ ABIL_SPIT_ACID, "Spit Acid", 0, 0, 125, 0, ABFLAG_NONE },
@@ -210,12 +210,12 @@ static const ability_def Ability_List[] =
{ ABIL_MUMMY_RESTORATION, "Restoration", 1, 0, 0, 0, ABFLAG_PERMANENT_MP },
// EVOKE abilities use Evocations and come from items:
- // Mapping, Teleportation, and Blink can also come from mutations
- // so we have to distinguish them (see above). The off items
+ // Mapping, Teleportation, and Blink can also come from mutations
+ // so we have to distinguish them (see above). The off items
// below are labeled EVOKE because they only work now if the
// player has an item with the evocable power (not just because
- // you used a wand, potion, or miscast effect). I didn't see
- // any reason to label them as "Evoke" in the text, they don't
+ // you used a wand, potion, or miscast effect). I didn't see
+ // any reason to label them as "Evoke" in the text, they don't
// use or train Evocations (the others do). -- bwr
{ ABIL_EVOKE_MAPPING, "Evoke Sense Surroundings", 0, 0, 30, 0, ABFLAG_NONE },
{ ABIL_EVOKE_TELEPORTATION, "Evoke Teleportation", 3, 0, 200, 0, ABFLAG_NONE },
@@ -325,7 +325,7 @@ const struct ability_def & get_ability_def( ability_type abil )
/****************************************************/
{
for (unsigned int i = 0;
- i < sizeof(Ability_List) / sizeof(Ability_List[0]); i++)
+ i < sizeof(Ability_List) / sizeof(Ability_List[0]); i++)
{
if (Ability_List[i].ability == abil)
return (Ability_List[i]);
@@ -354,7 +354,7 @@ std::string print_abilities()
return text;
}
-
+
const std::string make_cost_description( ability_type ability )
{
const ability_def& abil = get_ability_def(ability);
@@ -399,7 +399,7 @@ const std::string make_cost_description( ability_type ability )
if (!ret.str().empty())
ret << ", ";
- ret << "Breath";
+ ret << "Breath";
}
if (abil.flags & ABFLAG_DELAY)
@@ -462,14 +462,14 @@ static talent _get_talent(ability_type ability, bool check_confused)
}
}
- // Look through the table to see if there's a preference, else
+ // Look through the table to see if there's a preference, else
// find a new empty slot for this ability. -- bwr
const int index = _find_ability_slot( ability );
if ( index != -1 )
result.hotkey = index_to_letter(index);
else
result.hotkey = 0; // means 'find later on'
-
+
switch (ability)
{
// begin spell abilities
@@ -482,12 +482,12 @@ static talent _get_talent(ability_type ability, bool check_confused)
// begin species abilities - some are mutagenic, too {dlb}
case ABIL_SPIT_POISON:
failure = ((you.species == SP_NAGA) ? 20 : 40)
- - 10 * you.mutation[MUT_SPIT_POISON]
+ - 10 * you.mutation[MUT_SPIT_POISON]
- you.experience_level;
break;
case ABIL_EVOKE_MAPPING:
- failure = 30 - you.skills[SK_EVOCATIONS];
+ failure = 30 - you.skills[SK_EVOCATIONS];
break;
case ABIL_MAPPING:
@@ -576,7 +576,7 @@ static talent _get_talent(ability_type ability, bool check_confused)
break;
case ABIL_TELEPORTATION:
- failure = ((you.mutation[MUT_TELEPORT_AT_WILL] > 1) ? 30 : 50)
+ failure = ((you.mutation[MUT_TELEPORT_AT_WILL] > 1) ? 30 : 50)
- you.experience_level;
break;
// end demonic powers {dlb}
@@ -614,7 +614,7 @@ static talent _get_talent(ability_type ability, bool check_confused)
if (you.species == SP_TROLL)
failure -= 30;
- else if (player_genus(GENPC_DWARVEN) || you.species == SP_HILL_ORC
+ else if (player_genus(GENPC_DWARVEN) || you.species == SP_HILL_ORC
|| you.species == SP_OGRE)
{
failure -= 10;
@@ -637,7 +637,7 @@ static talent _get_talent(ability_type ability, bool check_confused)
invoc = true;
failure = 30 - (you.piety / 20) - (6 * you.skills[SK_INVOCATIONS]);
break;
-
+
// destroying stuff doesn't train anything
case ABIL_ELYVILON_DESTROY_WEAPONS:
invoc = true;
@@ -648,7 +648,7 @@ static talent _get_talent(ability_type ability, bool check_confused)
invoc = true;
failure = 0;
break;
-
+
// These three are Trog abilities... Invocations means nothing -- bwr
case ABIL_TROG_BERSERK: // piety >= 30
invoc = true;
@@ -728,7 +728,7 @@ static talent _get_talent(ability_type ability, bool check_confused)
invoc = true;
failure = 80 - (you.piety / 25) - (4 * you.skills[SK_EVOCATIONS]);
break;
-
+
case ABIL_NEMELEX_MARK_FOUR:
invoc = true;
failure = 70 - (you.piety * 2 / 45)
@@ -823,11 +823,11 @@ bool activate_ability()
mpr("Sorry, you're too full to transform right now.");
else
mpr("Sorry, you're not good enough to have a special ability.");
-
+
crawl_state.zero_turns_taken();
return false;
}
-
+
if ( you.duration[DUR_CONF] )
{
talents = your_talents(true);
@@ -859,7 +859,7 @@ bool activate_ability()
else if (keyin == ESCAPE || keyin == ' ' ||
keyin == '\r' || keyin == '\n')
{
- canned_msg( MSG_OK );
+ canned_msg( MSG_OK );
return (false);
}
else if ( isalpha(keyin) )
@@ -889,6 +889,23 @@ bool activate_ability()
static bool _activate_talent(const talent& tal)
{
+ // Doing these would outright kill the player due to stat drain.
+ if (tal.which == ABIL_TRAN_BAT && you.strength <= 5)
+ {
+ mpr("You lack the strength for this transformation.");
+ crawl_state.zero_turns_taken();
+ return (false);
+ }
+ else if (tal.which == ABIL_END_TRANSFORMATION
+ && you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT
+ && you.dex <= 5)
+ {
+ mpr("Turning back with such low dexterity would be fatal!");
+ more();
+ crawl_state.zero_turns_taken();
+ return (false);
+ }
+
// some abilities don't need a hunger check
bool hungerCheck = true;
switch (tal.which)
@@ -927,14 +944,14 @@ static bool _activate_talent(const talent& tal)
crawl_state.zero_turns_taken();
return (false);
}
-
+
if (tal.which == ABIL_ZIN_SANCTUARY && env.sanctuary_time)
{
mpr("There's already a sanctuary in place on this level.");
crawl_state.zero_turns_taken();
return (false);
}
-
+
if ((tal.which == ABIL_EVOKE_BERSERK || tal.which == ABIL_TROG_BERSERK)
&& !you.can_go_berserk(true))
{
@@ -982,7 +999,7 @@ static bool _do_ability(const ability_def& abil)
struct bolt beam;
struct dist spd;
- // Note: the costs will not be applied until after this switch
+ // Note: the costs will not be applied until after this switch
// statement... it's assumed that only failures have returned! -- bwr
switch (abil.ability)
{
@@ -1009,7 +1026,7 @@ static bool _do_ability(const ability_def& abil)
case ABIL_DELAYED_FIREBALL:
if ( !spell_direction(spd, beam, DIR_NONE, TARG_ENEMY) )
return (false);
-
+
// Note: power level of ball calculated at release -- bwr
fireball( calc_spell_power( SPELL_DELAYED_FIREBALL, true ), beam );
@@ -1032,7 +1049,7 @@ static bool _do_ability(const ability_def& abil)
mpr("You spit poison.");
zapping( ZAP_SPIT_POISON,
- you.experience_level
+ you.experience_level
+ you.mutation[MUT_SPIT_POISON] * 5
+ (you.species == SP_NAGA) * 10,
beam );
@@ -1065,7 +1082,7 @@ static bool _do_ability(const ability_def& abil)
mpr("You feel momentarily disoriented.");
if (abil.ability == ABIL_EVOKE_MAPPING)
- exercise( SK_EVOCATIONS, 1 );
+ exercise( SK_EVOCATIONS, 1 );
break;
case ABIL_EVOKE_TELEPORTATION: // ring of teleportation
@@ -1198,9 +1215,9 @@ static bool _do_ability(const ability_def& abil)
if (you.experience_level > 14)
mpr("You feel very comfortable in the air.");
break;
-
+
// Fly (Draconians, or anything else with wings)
- case ABIL_FLY_II:
+ case ABIL_FLY_II:
if (you.duration[DUR_EXHAUSTED])
{
mpr("You're too exhausted to fly.");
@@ -1229,7 +1246,7 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_HELLFIRE:
- if (your_spells(SPELL_HELLFIRE,
+ if (your_spells(SPELL_HELLFIRE,
20 + you.experience_level, false) == SPRET_ABORT)
return (false);
break;
@@ -1343,7 +1360,7 @@ static bool _do_ability(const ability_def& abil)
// up to (60 + 40)/2 = 50
const int pow = ( 2*skill_bump(SK_INVOCATIONS) + you.piety / 5 ) / 2;
start_delay(DELAY_RECITE, 3, pow, you.hp);
-
+
exercise( SK_INVOCATIONS, 2 );
break;
}
@@ -1448,7 +1465,7 @@ static bool _do_ability(const ability_def& abil)
case ABIL_YRED_ANIMATE_CORPSE:
mpr("You call on the dead to walk for you...");
- animate_a_corpse( you.x_pos, you.y_pos, BEH_FRIENDLY,
+ animate_a_corpse( you.x_pos, you.y_pos, BEH_FRIENDLY,
you.pet_target, CORPSE_BODY );
exercise(SK_INVOCATIONS, 2 + random2(4));
@@ -1588,7 +1605,7 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_TROG_BERSERK:
- // Trog abilities don't use or train invocations.
+ // Trog abilities don't use or train invocations.
if (you.hunger_state < HS_SATIATED)
{
mpr("You're too hungry to berserk.");
@@ -1669,7 +1686,7 @@ static bool _do_ability(const ability_def& abil)
// Paranoia.
if (you.hp_max < 1)
you.hp_max = 1;
-
+
// Deflate HP
set_hp( 1 + random2(you.hp), false );
@@ -1695,7 +1712,7 @@ static bool _do_ability(const ability_def& abil)
return (false);
}
zapping( ZAP_BANISHMENT, 16 + you.skills[SK_INVOCATIONS] * 8, beam );
- exercise(SK_INVOCATIONS, 3 + random2(5));
+ exercise(SK_INVOCATIONS, 3 + random2(5));
break;
case ABIL_LUGONU_CORRUPT:
@@ -1785,7 +1802,7 @@ static bool _do_ability(const ability_def& abil)
return (false);
}
- if (your_spells( SPELL_HELLFIRE,
+ if (your_spells( SPELL_HELLFIRE,
20 + you.experience_level, false ) == SPRET_ABORT)
return (false);
@@ -1895,7 +1912,7 @@ int choose_ability_menu(const std::vector<talent>& talents)
abil_menu.add_entry(me);
}
}
-
+
if ( found_invocations )
{
abil_menu.add_entry(new MenuEntry(" Invocations - ", MEL_SUBTITLE));
@@ -2001,7 +2018,7 @@ std::vector<talent> your_talents( bool check_confused )
{
_add_talent(talents, ABIL_TRAN_BAT, check_confused );
}
-
+
if (!player_is_airborne())
{
// kenku can fly, but only from the ground
@@ -2053,7 +2070,7 @@ std::vector<talent> your_talents( bool check_confused )
if (you.duration[DUR_TRANSFORMATION])
_add_talent(talents, ABIL_END_TRANSFORMATION, check_confused );
- if (you.mutation[MUT_BLINK])
+ if (you.mutation[MUT_BLINK])
_add_talent(talents, ABIL_BLINK, check_confused );
if (you.mutation[MUT_TELEPORT_AT_WILL])
@@ -2133,7 +2150,7 @@ std::vector<talent> your_talents( bool check_confused )
|| scan_randarts( RAP_LEVITATE ))
{
// Now you can only turn levitation off if you have an
- // activatable item. Potions and miscast effects will
+ // activatable item. Potions and miscast effects will
// have to time out (this makes the miscast effect actually
// a bit annoying). -- bwr
_add_talent(talents, you.duration[DUR_LEVITATION] ?
@@ -2180,15 +2197,15 @@ std::vector<talent> your_talents( bool check_confused )
// In theory, we could be left with an unreachable ability
// here (if you have 53 or more abilities simultaneously.)
}
-
+
return talents;
}
// Note: we're trying for a behaviour where the player gets
// to keep their assigned invocation slots if they get excommunicated
-// and then rejoin (but if they spend time with another god we consider
-// the old invocation slots void and erase them). We also try to
-// protect any bindings the character might have made into the
+// and then rejoin (but if they spend time with another god we consider
+// the old invocation slots void and erase them). We also try to
+// protect any bindings the character might have made into the
// traditional invocation slots (A-E and X). -- bwr
static void _set_god_ability_helper( ability_type abil, char letter )
{
@@ -2298,7 +2315,7 @@ static int _lugonu_warp_monster(int x, int y, int pow, int)
if (!mons_friendly(&mon))
behaviour_event( &mon, ME_ANNOY, MHITYOU );
-
+
if (check_mons_resist_magic(&mon, pow * 2))
{
mprf("%s %s.",
@@ -2337,7 +2354,7 @@ static void _lugonu_bends_space()
_lugonu_warp_area(pow);
random_blink(false, true);
-
+
const int damage = roll_dice(1, 4);
ouch(damage, 0, KILLED_BY_WILD_MAGIC, "a spatial distortion");
}
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 2f487034f4..9f9d44e634 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -1646,7 +1646,6 @@ std::string get_item_description( const item_def &item, bool verbose,
break;
case OBJ_POTIONS:
-#ifdef DEBUG_BLOOD_POTIONS
// list content of timer vector for blood potions
if (item.sub_type == POT_BLOOD
|| item.sub_type == POT_BLOOD_COAGULATED)
@@ -1663,7 +1662,8 @@ std::string get_item_description( const item_def &item, bool verbose,
for (int i = 0; i < timer.size(); i++)
description << (timer[i].get_long()) << " ";
}
-#endif
+ break;
+
case OBJ_SCROLLS:
case OBJ_ORBS:
case OBJ_CORPSES:
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 760a274a25..38d5ae0717 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -127,13 +127,13 @@ bool test_melee_hit(int to_hit, int ev)
miss = 100.0 - MIN_HIT_MISS_PERCENTAGE / 2.0;
else
{
- miss = MIN_HIT_MISS_PERCENTAGE / 2.0 +
+ miss = MIN_HIT_MISS_PERCENTAGE / 2.0 +
((100.0 - MIN_HIT_MISS_PERCENTAGE) * ev) / to_hit;
}
mprf( MSGCH_DIAGNOSTICS,
"to hit: %d; ev: %d; miss: %0.2f%%; roll: %d; result: %s%s (%d)",
- to_hit, ev, miss, roll, (margin >= 0) ? "hit" : "miss",
+ to_hit, ev, miss, roll, (margin >= 0) ? "hit" : "miss",
(roll == -1) ? "!!!" : "", margin );
#endif
@@ -451,7 +451,7 @@ void melee_attack::check_special_wield_effects()
// miscast_effect to operate on any actor.
if (one_chance_in(9) && attacker->atype() == ACT_PLAYER)
{
- miscast_effect( SPTYP_DIVINATION, random2(9), random2(70), 100,
+ miscast_effect( SPTYP_DIVINATION, random2(9), random2(70), 100,
"the Staff of Wucad Mu" );
}
break;
@@ -623,10 +623,10 @@ static bool _player_vampire_draws_blood(const int mons, const int damage,
ASSERT(mons != -1);
const monsters *mon = &menv[mons];
-
+
if (!_vamp_wants_blood_from_monster(mon))
return (false);
-
+
const int chunk_type = mons_corpse_effect( mon->type );
// now print message, need biting unless already done (never for bat form!)
@@ -690,7 +690,7 @@ bool melee_attack::player_attack()
return (false);
coord_def where = defender->pos();
-
+
if (player_hits_monster())
{
did_hit = true;
@@ -773,7 +773,7 @@ bool melee_attack::player_attack()
return (true);
const bool did_primary_hit = did_hit;
-
+
if (unarmed_ok && where == defender->pos() && player_aux_unarmed())
return (true);
@@ -797,7 +797,7 @@ bool melee_attack::player_aux_unarmed()
if (can_do_unarmed)
{
- if (you.species == SP_NAGA)
+ if (you.species == SP_NAGA)
uattack = UNAT_HEADBUTT;
else
uattack = (coinflip() ? UNAT_HEADBUTT : UNAT_KICK);
@@ -807,7 +807,7 @@ bool melee_attack::player_aux_unarmed()
{
uattack = UNAT_BITE;
}
-
+
if ((you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON
|| player_genus(GENPC_DRACONIAN)
|| (you.species == SP_MERFOLK && player_is_swimming())
@@ -819,7 +819,7 @@ bool melee_attack::player_aux_unarmed()
if (coinflip())
uattack = UNAT_PUNCH;
-
+
if (you.species == SP_VAMPIRE && !one_chance_in(3))
uattack = UNAT_BITE;
}
@@ -864,7 +864,7 @@ bool melee_attack::player_aux_unarmed()
}
else
unarmed_attack = "kick";
-
+
aux_damage = (you.mutation[MUT_HOOVES] ? 10
: clawed_kick ? 8 : 5);
break;
@@ -893,7 +893,7 @@ bool melee_attack::player_aux_unarmed()
(you.species == SP_KENKU) ? "peck" : "headbutt";
aux_damage = 5 + you.mutation[MUT_HORNS] * 3;
-
+
// minotaurs used to get +5 damage here, now they get
// +6 because of the horns.
@@ -946,7 +946,7 @@ bool melee_attack::player_aux_unarmed()
// maybe add this to player messaging {dlb}
//
// STINGER mutation doesn't give extra damage here... that
- // would probably be a bit much, we'll still get the
+ // would probably be a bit much, we'll still get the
// poison bonus so it's still somewhat good.
if (you.species == SP_GREY_DRACONIAN && you.experience_level >= 7)
aux_damage = 12;
@@ -969,7 +969,7 @@ bool melee_attack::player_aux_unarmed()
if (shield || coinflip()
|| (weapon
&& hands == HANDS_TWO
- && weapon->base_type != OBJ_STAVES
+ && weapon->base_type != OBJ_STAVES
&& weapon->sub_type != WPN_QUARTERSTAFF) )
{
continue;
@@ -1028,7 +1028,7 @@ bool melee_attack::player_aux_unarmed()
else if (!one_chance_in(3)) // monster not interesting bloodwise
continue;
}
-
+
break;
/* To add more, add to while part of loop below as well */
@@ -1039,14 +1039,14 @@ bool melee_attack::player_aux_unarmed()
// unified to-hit calculation
to_hit = random2( calc_your_to_hit_unarmed(uattack,
damage_brand == SPWPN_VAMPIRICISM) );
-
+
make_hungry(2, true);
alert_nearby_monsters();
// XXX We're clobbering did_hit
did_hit = false;
-
+
bool ely_block = false;
if (you.religion != GOD_ELYVILON && you.penance[GOD_ELYVILON]
&& to_hit >= def->ev && one_chance_in(20))
@@ -1054,7 +1054,7 @@ bool melee_attack::player_aux_unarmed()
simple_god_message(" blocks your attack.", GOD_ELYVILON);
ely_block = true;
}
-
+
if (!ely_block && (to_hit >= def->ev || one_chance_in(30)))
{
if (attack_shield_blocked(true))
@@ -1072,7 +1072,7 @@ bool melee_attack::player_aux_unarmed()
miss_verb.empty()? unarmed_attack.c_str()
: miss_verb.c_str(),
defender->name(DESC_NOCAP_THE).c_str());
-
+
if (ely_block)
dec_penance(GOD_ELYVILON, 1 + random2(to_hit - def->ev));
}
@@ -1134,7 +1134,7 @@ bool melee_attack::player_apply_aux_unarmed()
player_monster_visible(def)?
", but do no damage" : "");
}
-
+
if (def->hit_points < 1)
{
monster_die(def, KILL_YOU, 0);
@@ -1184,7 +1184,7 @@ void melee_attack::player_announce_hit()
{
if (!verb_degree.empty() && verb_degree[0] != ' ')
verb_degree = " " + verb_degree;
-
+
msg::stream << "You " << attack_verb << ' '
<< def->name(DESC_NOCAP_THE)
<< verb_degree << debug_damage_number()
@@ -1231,12 +1231,12 @@ int melee_attack::player_stat_modify_damage(int damage)
{
int dammod = 78;
const int dam_stat_val = calc_stat_to_dam_base();
-
+
if (dam_stat_val > 11)
dammod += (random2(dam_stat_val - 11) * 2);
else if (dam_stat_val < 9)
dammod -= (random2(9 - dam_stat_val) * 3);
-
+
damage *= dammod;
damage /= 78;
@@ -1247,12 +1247,12 @@ int melee_attack::player_aux_stat_modify_damage(int damage)
{
int dammod = 10;
const int dam_stat_val = calc_stat_to_dam_base();
-
+
if (dam_stat_val > 11)
dammod += random2(dam_stat_val - 11) / 3;
if (dam_stat_val < 9)
dammod -= random2(9 - dam_stat_val) / 2;
-
+
damage *= dammod;
damage /= 10;
@@ -1290,7 +1290,7 @@ int melee_attack::player_apply_weapon_skill(int damage)
int melee_attack::player_apply_fighting_skill(int damage, bool aux)
{
const int base = aux? 40 : 30;
-
+
damage *= base + (random2(you.skills[SK_FIGHTING] + 1));
damage /= base;
@@ -1301,7 +1301,7 @@ int melee_attack::player_apply_misc_modifiers(int damage)
{
if (you.duration[DUR_MIGHT] > 1)
damage += 1 + random2(10);
-
+
if (you.hunger_state <= HS_STARVING && you.species != SP_VAMPIRE)
damage -= random2(5);
@@ -1313,7 +1313,7 @@ int melee_attack::player_apply_weapon_bonuses(int damage)
if (weapon && weapon->base_type == OBJ_WEAPONS)
{
int wpn_damage_plus = weapon->plus2;
-
+
damage += (wpn_damage_plus > -1) ? (random2(1 + wpn_damage_plus))
: -(1 + random2(-wpn_damage_plus));
@@ -1321,13 +1321,13 @@ int melee_attack::player_apply_weapon_bonuses(int damage)
// already included in the damage stat for the weapon -- bwr
if (hand_half_bonus)
damage += random2(3);
-
+
if (get_equip_race(*weapon) == ISFLAG_DWARVEN
&& player_genus(GENPC_DWARVEN))
{
damage += random2(3);
}
-
+
if (get_equip_race(*weapon) == ISFLAG_ORCISH
&& you.species == SP_HILL_ORC)
{
@@ -1490,7 +1490,7 @@ int melee_attack::player_weapon_type_modify(int damage)
else if (weapon->base_type == OBJ_WEAPONS)
weap_type = weapon->sub_type;
- // All weak hits look the same, except for when the player
+ // All weak hits look the same, except for when the player
// has a non-weapon in hand. -- bwr
// Exception: vampire bats only _bite_ to allow for drawing blood
if (damage < HIT_WEAK && (you.species != SP_VAMPIRE
@@ -1505,7 +1505,7 @@ int melee_attack::player_weapon_type_modify(int damage)
}
// take transformations into account, if no weapon is wielded
- if (weap_type == WPN_UNARMED
+ if (weap_type == WPN_UNARMED
&& you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE)
{
switch (you.attribute[ATTR_TRANSFORMATION])
@@ -1646,10 +1646,10 @@ bool melee_attack::player_hurt_monster()
void melee_attack::player_exercise_combat_skills()
{
const bool helpless = defender->cannot_fight();
-
+
if (!helpless || you.skills[ wpn_skill ] < 2)
exercise( wpn_skill, 1 );
-
+
if ((!helpless || you.skills[SK_FIGHTING] < 2)
&& one_chance_in(3))
{
@@ -1759,7 +1759,7 @@ bool melee_attack::player_monattk_hit_effects(bool mondied)
attack_verb.c_str(),
defender->name(DESC_NOCAP_THE).c_str());
}
-
+
if (needs_message && !special_damage_message.empty())
mprf("%s", special_damage_message.c_str());
@@ -1808,7 +1808,7 @@ static inline int get_resistible_fraction(beam_type flavour)
// FIXME: Does not (yet) handle life draining, player acid damage
// (does handle monster acid damage), miasma, and other exotic
// attacks.
-//
+//
// beam_type is just use to determine the damage flavour, it does not
// necessarily imply that the attack is a beam attack.
int resist_adjust_damage(actor *defender, beam_type flavour,
@@ -1816,9 +1816,9 @@ int resist_adjust_damage(actor *defender, beam_type flavour,
{
if (!res)
return (rawdamage);
-
+
const bool monster = defender->atype() == ACT_MONSTER;
-
+
// Check if this is a resist that pretends to be boolean for
// damage purposes - only electricity at the moment, raw poison
// damage uses the normal formula.
@@ -1827,7 +1827,7 @@ int resist_adjust_damage(actor *defender, beam_type flavour,
int resistible = rawdamage * resistible_fraction / 100;
const int irresistible = rawdamage - resistible;
-
+
if (res > 0)
{
if (monster && res >= 3)
@@ -1903,7 +1903,7 @@ void melee_attack::drain_monster()
atk_name(DESC_CAP_THE).c_str(),
attacker->conj_verb("drain").c_str(),
def_name(DESC_NOCAP_THE).c_str());
-
+
if (one_chance_in(5))
{
def->hit_dice--;
@@ -1915,10 +1915,10 @@ void melee_attack::drain_monster()
if (def->hit_points >= def->max_hit_points)
def->hit_points = def->max_hit_points;
-
+
if (def->hit_dice < 1)
def->hit_points = 0;
-
+
special_damage = 1 + (random2(damage_done) / 2);
attacker->god_conduct(DID_NECROMANCY, 2);
}
@@ -1938,12 +1938,12 @@ bool melee_attack::distortion_affects_defender()
make_stringf("%s %s in the translocular energy.",
def_name(DESC_CAP_THE).c_str(),
defender->conj_verb("bask").c_str());
-
+
defender->heal(1 + random2avg(7, 2), true); // heh heh
}
return (false);
}
-
+
if (one_chance_in(3))
{
if (defender_visible)
@@ -2121,14 +2121,14 @@ bool melee_attack::apply_damage_brand()
{
obvious_effect = true;
}
-
+
}
break;
case SPWPN_DRAINING:
drain_defender();
break;
-
+
/* 9 = speed - done before */
case SPWPN_VORPAL:
special_damage = 1 + random2(damage_done) / 2;
@@ -2145,7 +2145,7 @@ bool melee_attack::apply_damage_brand()
_player_vampire_draws_blood(monster_index(def), damage_done);
break;
}
-
+
if (defender->holiness() != MH_NATURAL || !weapon
|| defender->res_negative_energy() > 0
|| damage_done < 1 || attacker->stat_hp() == attacker->stat_maxhp()
@@ -2221,7 +2221,7 @@ bool melee_attack::apply_damage_brand()
// here. Generalise.
const int hdcheck =
(defender->holiness() == MH_NATURAL? random2(30) : random2(22));
-
+
if (mons_class_is_confusable(def->type) &&
hdcheck >= defender->get_experience_level())
{
@@ -2239,7 +2239,7 @@ bool melee_attack::apply_damage_brand()
if (attacker->atype() == ACT_PLAYER)
{
you.duration[DUR_CONFUSING_TOUCH] -= roll_dice(3, 5);
-
+
if (you.duration[DUR_CONFUSING_TOUCH] < 1)
you.duration[DUR_CONFUSING_TOUCH] = 1;
}
@@ -2267,7 +2267,7 @@ bool melee_attack::chop_hydra_head( int dam,
// chop-check to prevent runaway head inflation.
if (attacker->atype() == ACT_MONSTER && !one_chance_in(4))
return (false);
-
+
if ((dam_type == DVORP_SLICING || dam_type == DVORP_CHOPPING
|| dam_type == DVORP_CLAWING)
&& dam > 0
@@ -2372,7 +2372,7 @@ void melee_attack::emit_nodmg_hit_message()
void melee_attack::player_apply_staff_damage()
{
special_damage = 0;
-
+
if (!weapon || !item_is_staff(*weapon))
return;
@@ -2382,7 +2382,7 @@ void melee_attack::player_apply_staff_damage()
{
return;
}
-
+
switch (weapon->sub_type)
{
case STAFF_AIR:
@@ -2394,12 +2394,12 @@ void melee_attack::player_apply_staff_damage()
BEAM_ELECTRICITY,
defender->res_elec(),
player_staff_damage(SK_AIR_MAGIC));
-
+
if (special_damage)
special_damage_message =
make_stringf("%s is jolted!",
defender->name(DESC_CAP_THE).c_str());
-
+
break;
case STAFF_COLD:
@@ -2421,7 +2421,7 @@ void melee_attack::player_apply_staff_damage()
case STAFF_EARTH:
special_damage = player_staff_damage(SK_EARTH_MAGIC);
- if (special_damage)
+ if (special_damage)
{
special_damage_message =
make_stringf(
@@ -2588,7 +2588,7 @@ int melee_attack::player_to_hit(bool random_factor)
#ifdef DEBUG_DIAGNOSTICS
const int base_to_hit = your_to_hit;
#endif
-
+
if (water_attack)
your_to_hit += 5;
@@ -2642,7 +2642,7 @@ int melee_attack::player_to_hit(bool random_factor)
{
your_to_hit++;
}
-
+
}
else if (item_is_staff( *weapon ))
{
@@ -2829,7 +2829,7 @@ void melee_attack::player_apply_attack_delay()
#if DEBUG_DIAGNOSTICS
mprf( MSGCH_DIAGNOSTICS,
- "Weapon speed: %d; min: %d; attack time: %d",
+ "Weapon speed: %d; min: %d; attack time: %d",
final_attack_delay, min_delay, you.time_taken );
#endif
}
@@ -2837,46 +2837,46 @@ void melee_attack::player_apply_attack_delay()
int melee_attack::player_weapon_speed()
{
int attack_delay = 0;
-
+
if (weapon && (weapon->base_type == OBJ_WEAPONS
|| item_is_staff( *weapon )))
{
attack_delay = property( *weapon, PWPN_SPEED );
attack_delay -= you.skills[ wpn_skill ] / 2;
-
+
min_delay = property( *weapon, PWPN_SPEED ) / 2;
// Short blades can get up to at least unarmed speed.
if (wpn_skill == SK_SHORT_BLADES && min_delay > 5)
min_delay = 5;
-
+
// Using both hands can get a weapon up to speed 7
if ((hands == HANDS_TWO || hand_half_bonus)
&& min_delay > 7)
{
min_delay = 7;
}
-
+
// never go faster than speed 3 (ie 3 attacks per round)
if (min_delay < 3)
min_delay = 3;
-
+
// Hand and a half bonus only helps speed up to a point, any more
// than speed 10 must come from skill and the weapon
if (hand_half_bonus && attack_delay > 10)
attack_delay--;
-
+
// apply minimum to weapon skill modification
if (attack_delay < min_delay)
attack_delay = min_delay;
-
+
if (weapon->base_type == OBJ_WEAPONS
&& damage_brand == SPWPN_SPEED)
{
attack_delay = (attack_delay + 1) / 2;
}
}
-
+
return (attack_delay);
}
@@ -2885,16 +2885,16 @@ int melee_attack::player_unarmed_speed()
int unarmed_delay = 10;
min_delay = 5;
-
+
// Unarmed speed
if (you.burden_state == BS_UNENCUMBERED
&& one_chance_in(heavy_armour_penalty + 1))
{
if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)
unarmed_delay = 10 - you.skills[SK_UNARMED_COMBAT] / 3;
- else
+ else
unarmed_delay = 10 - you.skills[SK_UNARMED_COMBAT] / 5;
-
+
/* this shouldn't happen anyway...sanity */
if (unarmed_delay < min_delay)
unarmed_delay = min_delay;
@@ -2913,7 +2913,7 @@ int melee_attack::player_apply_shield_delay(int attack_delay)
if (you.skills[SK_SHIELDS] <= 10 + random2(17))
attack_delay++;
// [dshaligram] Fall-through
-
+
case ARM_SHIELD:
if (you.skills[SK_SHIELDS] <= 3 + random2(17))
attack_delay++;
@@ -2987,7 +2987,7 @@ int melee_attack::player_calc_base_unarmed_damage()
int melee_attack::player_calc_base_weapon_damage()
{
int damage = 0;
-
+
if (weapon->base_type == OBJ_WEAPONS
|| item_is_staff( *weapon ))
{
@@ -3083,7 +3083,7 @@ bool melee_attack::attack_shield_blocked(bool verbose)
if (attacker->invisible() && !defender->can_see_invisible())
pro_block /= 3;
-
+
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Defender: %s, Pro-block: %d, Con-block: %d",
def_name(DESC_PLAIN).c_str(), pro_block, con_block);
@@ -3142,13 +3142,13 @@ int melee_attack::mons_calc_damage(const mon_attack_def &attk)
else if (atk->has_ench(ENCH_BATTLE_FRENZY))
{
const mon_enchant ench = atk->get_ench(ENCH_BATTLE_FRENZY);
-
+
#ifdef DEBUG_DIAGNOSTICS
const int orig_damage = damage;
#endif
-
+
damage = damage * (115 + ench.degree * 15) / 100;
-
+
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "%s frenzy damage: %d->%d",
attacker->name(DESC_PLAIN).c_str(), orig_damage, damage);
@@ -3200,7 +3200,7 @@ int melee_attack::mons_apply_defender_ac(int damage, int damage_max)
if (damage < 1)
damage = 0;
-
+
return damage;
}
@@ -3245,7 +3245,7 @@ std::string melee_attack::mons_attack_verb(const mon_attack_def &attk)
// spore
"hit",
-
+
"touch",
"engulf",
"claw",
@@ -3329,7 +3329,7 @@ void melee_attack::check_defender_train_armour()
{
if (defender->wearing_light_armour())
return;
-
+
const item_def *arm = defender->slot_item(EQ_BODY_ARMOUR);
if (arm && coinflip() && random2(1000) <= item_mass(*arm))
defender->exercise(SK_ARMOUR, coinflip()? 2 : 1);
@@ -3345,7 +3345,7 @@ void melee_attack::mons_do_poison(const mon_attack_def &attk)
{
if (defender->res_poison() > 0)
return;
-
+
if (attk.flavour == AF_POISON_NASTY
|| one_chance_in( 15 + 5 * (attk.flavour == AF_POISON) )
|| (damage_done > 1
@@ -3419,7 +3419,7 @@ void melee_attack::splash_defender_with_acid(int strength)
void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
{
// Most of this is from BWR 4.1.2.
-
+
int res = 0;
switch (attk.flavour)
{
@@ -3430,7 +3430,7 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
if (one_chance_in(4))
defender->mutate();
break;
-
+
case AF_POISON:
case AF_POISON_NASTY:
case AF_POISON_MEDIUM:
@@ -3512,6 +3512,15 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
break;
case AF_VAMPIRIC:
+ // only may bite non-vampiric monsters (players) capable of bleeding
+ if (defender->atype() == ACT_PLAYER
+ && (you.species == SP_VAMPIRE || !victim_can_bleed(-1))
+ || defender->atype() == ACT_MONSTER
+ && !victim_can_bleed(def->type))
+ {
+ break;
+ }
+
if (defender->res_negative_energy() > random2(3))
break;
@@ -3604,7 +3613,7 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
{
drain_defender();
}
-
+
break;
case AF_PARALYSE:
@@ -3625,7 +3634,7 @@ void melee_attack::mons_apply_attack_flavour(const mon_attack_def &attk)
case AF_RAGE:
if (!one_chance_in(3) || !defender->can_go_berserk())
break;
-
+
if (needs_message)
mprf("%s %s %s!",
atk_name(DESC_CAP_THE).c_str(),
@@ -3654,7 +3663,7 @@ void melee_attack::mons_perform_attack_rounds()
// Monsters hitting themselves get just one round.
if (attack_number > 0 && attacker == defender)
break;
-
+
const mon_attack_def attk = mons_attack_spec(atk, attack_number);
if (attk.type == AT_NONE)
{
@@ -3732,7 +3741,7 @@ void melee_attack::mons_perform_attack_rounds()
= _modify_blood_amount(damage_done, attacker->damage_type());
if (blood > defender->stat_hp())
blood = defender->stat_hp();
-
+
bleed_onto_floor(pos.x, pos.y, type, blood, true);
if (decapitate_hydra(damage_done,
@@ -3740,7 +3749,7 @@ void melee_attack::mons_perform_attack_rounds()
{
continue;
}
-
+
special_damage = 0;
special_damage_message.clear();
@@ -3748,12 +3757,12 @@ void melee_attack::mons_perform_attack_rounds()
// message sequences look too weird.
if (attacker != defender)
mons_apply_attack_flavour(attk);
-
+
if (!special_damage_message.empty())
mprf("%s", special_damage_message.c_str());
-
+
defender->hurt(attacker, damage_done + special_damage);
-
+
if (!defender->alive() || attacker == defender)
return;
@@ -3782,7 +3791,7 @@ bool melee_attack::mons_perform_attack()
}
mons_perform_attack_rounds();
-
+
return (did_hit);
}
@@ -3794,7 +3803,7 @@ void melee_attack::mons_check_attack_perceived()
if (defender->atype() == ACT_PLAYER)
{
interrupt_activity(AI_MONSTER_ATTACKS, atk);
-
+
// if a friend wants to help, they can attack <monster_attacking>
if (you.pet_target == MHITNOT)
you.pet_target = monster_index(atk);
@@ -3816,7 +3825,7 @@ int melee_attack::mons_to_hit()
#ifdef DEBUG_DIAGNOSTICS
const int base_hit = mhit;
#endif
-
+
if (water_attack)
mhit += 5;
@@ -3841,7 +3850,7 @@ int melee_attack::mons_to_hit()
attacker->name(DESC_PLAIN).c_str(),
base_hit, mhit);
#endif
-
+
return (mhit);
}
@@ -3864,7 +3873,7 @@ static void wielded_weapon_check(const item_def *weapon)
bool you_attack(int monster_attacked, bool unarmed_attacks)
{
monsters *defender = &menv[monster_attacked];
-
+
melee_attack attk(&you, defender, unarmed_attacks);
// We're trying to hit a monster, break out of travel/explore now.
@@ -4099,7 +4108,7 @@ static void stab_message( monsters *defender, int stab_bonus )
}
break;
case 1:
- mprf( "%s fails to defend %s.",
+ mprf( "%s fails to defend %s.",
defender->name(DESC_CAP_THE).c_str(),
defender->pronoun(PRONOUN_REFLEXIVE).c_str() );
break;
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index 53000eed75..fb51386cf2 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -2920,6 +2920,16 @@ static void give_wand(monsters *mon, int level)
static void give_potion(monsters *mon, int level)
{
//mv - give potion
+ if (mons_species( mon->type ) == MONS_VAMPIRE && one_chance_in(5))
+ {
+ const int thing_created =
+ items(0, OBJ_POTIONS, POT_BLOOD, true, level, 0);
+ if (thing_created == NON_ITEM)
+ return;
+
+ mitm[thing_created].flags = 0;
+ give_monster_item(mon, thing_created);
+ }
if (mons_is_unique( mon->type ) && one_chance_in(3))
{
const int thing_created =
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index a069b76a34..bb1cba82f7 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -1028,7 +1028,7 @@ void split_blood_potions_into_decay( int obj, int amount )
}
// checks whether the player or a monster is capable of bleeding
-static bool victim_can_bleed(int montype)
+bool victim_can_bleed(int montype)
{
if (montype == -1) // player
{
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 4c588fc42c..9e71adead8 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -81,6 +81,7 @@ bool can_bottle_blood_from_corpse( int mons_type );
void turn_corpse_into_blood_potions ( item_def &item );
void split_blood_potions_into_decay( int obj, int amount = -1 );
+bool victim_can_bleed(int montype);
void bleed_onto_floor(int x, int y, int mon, int damage, bool spatter = false);
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index a7b062381e..c5487f9386 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -2090,9 +2090,11 @@ bool ms_waste_of_time( const monsters *mon, spell_type monspell )
break;
case SPELL_INVISIBILITY:
- if (mon->has_ench(ENCH_INVIS) ||
- (mons_friendly(mon) && !player_see_invis(false)))
+ if (mon->has_ench(ENCH_INVIS)
+ || (mons_friendly(mon) && !player_see_invis(false)))
+ {
ret = true;
+ }
break;
case SPELL_LESSER_HEALING:
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 035bc36f73..0ed96ff2d3 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -3375,14 +3375,37 @@ static bool _handle_potion(monsters *monster, bolt & beem)
}
break;
+ case POT_BLOOD:
+ case POT_BLOOD_COAGULATED:
+ if (mons_species(monster->type) == MONS_VAMPIRE
+ && monster->hit_points <= monster->max_hit_points / 2)
+ {
+ simple_monster_message(monster, " drinks a potion.");
+
+ if (heal_monster(monster, 10 + random2avg(28, 3), false))
+ {
+ simple_monster_message(monster, " is healed!");
+ ident = ID_MON_TRIED_TYPE;
+ }
+
+ imbibed = true;
+ }
+ break;
+
case POT_SPEED:
// notice that these are the same odd colours used in
// mons_ench_f2() {dlb}
+ if (monster->has_ench(ENCH_HASTE))
+ break;
+
beem.colour = BLUE;
// intentional fall through
case POT_INVISIBILITY:
if (mitm[monster->inv[MSLOT_POTION]].sub_type == POT_INVISIBILITY)
{
+ if (monster->has_ench(ENCH_INVIS))
+ break;
+
beem.colour = MAGENTA;
// Friendly monsters won't go invisible if the player
// can't see invisible. We're being nice.
@@ -3390,15 +3413,10 @@ static bool _handle_potion(monsters *monster, bolt & beem)
break;
}
- // why only drink these if not near player? {dlb}
- if (!mons_near(monster))
- {
- simple_monster_message(monster, " drinks a potion.");
-
- mons_ench_f2(monster, beem);
-
- imbibed = true;
- }
+ // allow monsters to drink these when player in sight (jpeg)
+ simple_monster_message(monster, " drinks a potion.");
+ mons_ench_f2(monster, beem);
+ imbibed = true;
ident = ID_KNOWN_TYPE;
break;
}
@@ -3407,6 +3425,12 @@ static bool _handle_potion(monsters *monster, bolt & beem)
{
if (dec_mitm_item_quantity( monster->inv[MSLOT_POTION], 1 ))
monster->inv[MSLOT_POTION] = NON_ITEM;
+ else if (mitm[monster->inv[MSLOT_POTION]].sub_type == POT_BLOOD
+ || mitm[monster->inv[MSLOT_POTION]].sub_type
+ == POT_BLOOD_COAGULATED)
+ {
+ remove_oldest_blood_potion(mitm[monster->inv[MSLOT_POTION]]);
+ }
if (ident != ID_UNKNOWN_TYPE && was_visible)
set_ident_type(OBJ_POTIONS, potion_type, ident);