summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/fight.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-28 00:04:30 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-28 00:04:30 +0000
commitde8f4030ab16a4d839e67096aa45c89de5b0d9ab (patch)
tree18290573c22137d17c4738045a4d524e9c8be1fc /crawl-ref/source/fight.cc
parentd492483ffce1744f3bfb0812c6aef470a7aa36c6 (diff)
downloadcrawl-ref-de8f4030ab16a4d839e67096aa45c89de5b0d9ab.tar.gz
crawl-ref-de8f4030ab16a4d839e67096aa45c89de5b0d9ab.zip
Clean up vampire biting attack, and call the new method whenever a
vampire successfully stabs one of those walking blood replenishers. All in all, vampires will bite monsters that don't yield blood less often (1/3 chance), though their overall biting chance has been slightly increases, and much so when stabbing. Weapons of vampiricism are now a distinct case, so vampiric biting (that also is signified by SPWPN_VAMPIRICISM, occasionally) consistently doesn't check for life protection (though that might be added) and instead always respects the mons_has_blood checks. Also, food messages ("You are very hungry.") are now displayed in green if your food level has increased. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3904 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/fight.cc')
-rw-r--r--crawl-ref/source/fight.cc318
1 files changed, 182 insertions, 136 deletions
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 90ff0255cb..11dffcecb7 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -562,6 +562,88 @@ bool melee_attack::attack()
mons_attack_mons() );
}
+static bool _vamp_wants_blood_from_monster(const monsters *mon)
+{
+ if (you.species != SP_VAMPIRE)
+ return (false);
+
+ if (you.hunger_state >= HS_ENGORGED)
+ return (false);
+
+ if (!mons_has_blood(mon->type))
+ return (false);
+
+ const int chunk_type = mons_corpse_effect( mon->type );
+
+ // don't drink poisonous or mutagenic blood
+ return (chunk_type == CE_CLEAN || chunk_type == CE_CONTAMINATED
+ || chunk_type == CE_POISONOUS && player_res_poison());
+}
+
+// Should life protection protect from this?
+// Called when stabbing and for bite attacks.
+// Returns true if blood was drawn.
+static bool _player_vampire_draws_blood(const int mons, const int damage,
+ bool needs_bite_msg = false)
+{
+ ASSERT(you.species == SP_VAMPIRE);
+ 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!)
+ if (needs_bite_msg && you.attribute[ATTR_TRANSFORMATION] != TRAN_BAT)
+ {
+ mprf( "You bite %s, and draw %s blood!",
+ mon->name(DESC_NOCAP_THE, true).c_str(),
+ mon->pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str());
+ }
+ else
+ mprf( "You draw %s's blood!", mon->name(DESC_NOCAP_THE, true).c_str() );
+
+ // regain hp
+ if (you.hp < you.hp_max)
+ {
+ int heal = 1 + random2(damage);
+ if (heal > you.experience_level)
+ heal = you.experience_level;
+
+ if (chunk_type == CE_CLEAN)
+ heal += 1 + random2(damage);
+
+ inc_hp(heal, false);
+ mprf("You feel %sbetter.", (you.hp == you.hp_max) ? "much " : "");
+ }
+
+ // gain nutrition
+ if (you.hunger_state < HS_ENGORGED)
+ {
+ int food_value = 0;
+ if (chunk_type == CE_CLEAN)
+ food_value = 30 + random2avg(59, 2);
+ else if (chunk_type == CE_CONTAMINATED
+ || chunk_type == CE_POISONOUS)
+ {
+ food_value = 15 + random2avg(29, 2);
+ }
+
+ // bats get a little less nutrition out of it
+ if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)
+ food_value -= 5 + random2(16);
+
+ lessen_hunger(food_value, false);
+ }
+
+ did_god_conduct(DID_DRINK_BLOOD, 5 + random2(4));
+
+ return (true);
+}
+
bool melee_attack::player_attack()
{
potential_damage =
@@ -618,11 +700,12 @@ bool melee_attack::player_attack()
if (damage_done > 0 || !defender_visible)
player_announce_hit();
else if (!shield_blocked && damage_done <= 0)
+ {
no_damage_message =
- make_stringf("You %s %s.",
- attack_verb.c_str(),
+ make_stringf("You %s %s.", attack_verb.c_str(),
defender->name(DESC_NOCAP_THE).c_str());
-
+ }
+
if (damage_done)
player_exercise_combat_skills();
@@ -630,6 +713,13 @@ bool melee_attack::player_attack()
return (true);
player_sustain_passive_damage();
+
+ // thirsty stabbing vampires get to draw blood
+ if (you.species == SP_VAMPIRE && you.hunger_state <= HS_HUNGRY
+ && stab_attempt && stab_bonus > 0)
+ {
+ _player_vampire_draws_blood(monster_index(def), damage_done, true);
+ }
// At this point, pretend we didn't hit at all.
if (shield_blocked)
@@ -666,8 +756,8 @@ bool melee_attack::player_attack()
// Returns true to end the attack round.
bool melee_attack::player_aux_unarmed()
{
- damage_brand = SPWPN_NORMAL;
- int uattack = UNAT_NO_ATTACK;
+ damage_brand = SPWPN_NORMAL;
+ int uattack = UNAT_NO_ATTACK;
bool simple_miss_message = false;
std::string miss_verb;
@@ -679,8 +769,10 @@ bool melee_attack::player_aux_unarmed()
uattack = (coinflip() ? UNAT_HEADBUTT : UNAT_KICK);
if (you.mutation[MUT_FANGS]
- || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON)
+ || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON)
+ {
uattack = UNAT_BITE;
+ }
if ((you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON
|| player_genus(GENPC_DRACONIAN)
@@ -705,8 +797,6 @@ bool melee_attack::player_aux_unarmed()
simple_miss_message = false;
damage_brand = SPWPN_NORMAL;
aux_damage = 0;
-
- bool vampiric = false;
switch (scount)
{
@@ -872,28 +962,39 @@ bool melee_attack::player_aux_unarmed()
case 4:
if (uattack != UNAT_BITE)
- {
continue;
- }
- if (!you.mutation[MUT_FANGS] || one_chance_in(5))
+
+ if (!you.mutation[MUT_FANGS])
+ continue;
+
+ if (you.species != SP_VAMPIRE && one_chance_in(5)
+ || one_chance_in(7))
{
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;
+ if (_vamp_wants_blood_from_monster(def))
+ {
+ // prob of vampiric bite:
+ // 1/4 when non-hungry, 1/2 when hungry, 100% when starving
+ if (you.hunger_state > HS_HUNGRY && coinflip())
+ break;
+
+ if (you.hunger_state > HS_STARVING && coinflip())
+ break;
- damage_brand = SPWPN_VAMPIRICISM;
- vampiric = true;
+ damage_brand = SPWPN_VAMPIRICISM;
+ }
+ else if (!one_chance_in(3)) // monster not interesting bloodwise
+ continue;
}
+
break;
/* To add more, add to while part of loop below as well */
@@ -902,7 +1003,8 @@ bool melee_attack::player_aux_unarmed()
}
// unified to-hit calculation
- to_hit = random2( calc_your_to_hit_unarmed(uattack, vampiric) );
+ to_hit = random2( calc_your_to_hit_unarmed(uattack,
+ damage_brand == SPWPN_VAMPIRICISM) );
make_hungry(2, true);
@@ -983,46 +1085,11 @@ bool melee_attack::player_apply_aux_unarmed()
if (mons_holiness(def) == MH_HOLY)
did_god_conduct(DID_ATTACK_HOLY, 1, true, def);
- // normal vampiric biting attack
- if (damage_brand == SPWPN_VAMPIRICISM
- && defender->holiness() == MH_NATURAL)
+ // normal vampiric biting attack, not if already got stabbing special
+ if (damage_brand == SPWPN_VAMPIRICISM && you.species == SP_VAMPIRE
+ && (!stab_attempt || stab_bonus <= 0))
{
- const int chunk_type = mons_corpse_effect( def->type );
-
- // don't drink poisonous or mutagenic blood
- if (chunk_type == CE_CLEAN || chunk_type == CE_CONTAMINATED)
- {
- mprf( "You draw %s's blood!",
- def->name(DESC_NOCAP_THE, true).c_str() );
-
- if (you.hp < you.hp_max)
- {
- int heal = 1 + random2(damage_done);
- if (heal > you.experience_level)
- heal = you.experience_level;
-
- if (chunk_type == CE_CLEAN)
- heal += 1 + random2(damage_done);
-
- inc_hp(heal, false);
- mpr("You feel better.");
- }
-
- if (you.hunger_state < HS_ENGORGED)
- {
- int food_value = 0;
- if (chunk_type == CE_CLEAN)
- food_value = 45 + random2avg(59, 2);
- else if (chunk_type == CE_CONTAMINATED)
- food_value = 22 + random2avg(29, 2);
-
- if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)
- food_value -= 5 + random2(16);
-
- lessen_hunger(food_value, true);
- }
- did_god_conduct(DID_DRINK_BLOOD, 5 + random2(4));
- }
+ _player_vampire_draws_blood(monster_index(def), damage_done);
}
}
else // no damage was done
@@ -1391,7 +1458,7 @@ int melee_attack::player_weapon_type_modify(int damage)
// 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
+ // Exception: vampire bats only _bite_ to allow for drawing blood
if (damage < HIT_WEAK && (you.species != SP_VAMPIRE
|| you.attribute[ATTR_TRANSFORMATION] != TRAN_BAT))
{
@@ -1595,13 +1662,20 @@ void melee_attack::player_check_weapon_effects()
bool melee_attack::player_monattk_hit_effects(bool mondied)
{
if (mons_holiness(def) == MH_HOLY)
- did_god_conduct(mondied? DID_KILL_HOLY : DID_ATTACK_HOLY, 1,
- true, def);
+ did_god_conduct(mondied? DID_KILL_HOLY : DID_ATTACK_HOLY, 1, true, def);
player_check_weapon_effects();
- // Vampiric effects for the killing blow.
- if (mondied && damage_brand == SPWPN_VAMPIRICISM)
+ // thirsty vampires will try to use a stabbing situation to draw blood
+ if (you.species == SP_VAMPIRE && you.hunger_state <= HS_HUNGRY
+ && mondied && stab_attempt && stab_bonus > 0
+ && _player_vampire_draws_blood(monster_index(def), damage_done, true))
+ {
+ // no further effects
+ }
+ // Vampiric *weapon* effects for the killing blow.
+ else if (mondied && damage_brand == SPWPN_VAMPIRICISM
+ && you.equip[EQ_WEAPON] != -1)
{
if (defender->holiness() == MH_NATURAL
&& damage_done > 0
@@ -1621,7 +1695,7 @@ bool melee_attack::player_monattk_hit_effects(bool mondied)
inc_hp(heal, false);
if (you.hunger_state != HS_ENGORGED)
- lessen_hunger(30 + random2avg(59, 2), true);
+ lessen_hunger(30 + random2avg(59, 2), false);
did_god_conduct(DID_NECROMANCY, 2);
}
@@ -2029,94 +2103,64 @@ bool melee_attack::apply_damage_brand()
break;
case SPWPN_VAMPIRICISM:
- if (defender->holiness() != MH_NATURAL ||
- defender->res_negative_energy() > 0 ||
- damage_done < 1 || attacker->stat_hp() == attacker->stat_maxhp() ||
- one_chance_in(5))
+ {
+ // vampire bat form, why the special handling?
+ if (attacker->atype() == ACT_PLAYER && you.species == SP_VAMPIRE
+ && you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)
+ {
+ _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()
+ || one_chance_in(5))
{
break;
}
obvious_effect = true;
- // vampire bat form
- if (you.species == SP_VAMPIRE && attacker->atype() == ACT_PLAYER
- && you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT)
- {
- const int chunk_type = mons_corpse_effect( def->type );
+ // handle weapon effects
+ // We only get here if we've done base damage, so no
+ // worries on that score.
- // don't drink poisonous or mutagenic blood
- if (mons_has_blood(def->type)
- && (chunk_type == CE_CLEAN || chunk_type == CE_CONTAMINATED
- || chunk_type == CE_POISONOUS && player_res_poison() ))
+ if (attacker->atype() == ACT_PLAYER)
+ mpr("You feel better.");
+ else if (attacker_visible)
+ {
+ if (defender->atype() == ACT_PLAYER)
{
- mprf( "You draw %s's blood!",
- def->name(DESC_NOCAP_THE, true).c_str() );
-
- if (you.hp < you.hp_max)
- {
- int heal = 1 + random2(damage_done);
- if (heal > you.experience_level)
- heal = you.experience_level;
-
- if (chunk_type == CE_CLEAN)
- heal += 1 + random2(damage_done);
-
- inc_hp(heal, false);
- mpr("You feel better.");
- }
-
- if (you.hunger_state < HS_ENGORGED)
- {
- int food_value = 0;
- if (chunk_type == CE_CLEAN)
- food_value = 30 + random2avg(59, 2);
- else if (chunk_type == CE_CONTAMINATED)
- food_value = 15 + random2avg(29, 2);
-
- lessen_hunger(food_value, true);
- }
- did_god_conduct(DID_DRINK_BLOOD, 5 + random2(4));
+ mprf("%s draws strength from your injuries!",
+ attacker->name(DESC_CAP_THE).c_str());
}
+ else
+ mprf("%s is healed.",
+ attacker->name(DESC_CAP_THE).c_str());
}
- else { // handle weapon effects
- // We only get here if we've done base damage, so no
- // worries on that score.
- if (attacker->atype() == ACT_PLAYER)
- mpr("You feel better.");
- else if (attacker_visible)
- {
- if (defender->atype() == ACT_PLAYER)
- mprf("%s draws strength from your injuries!",
- attacker->name(DESC_CAP_THE).c_str());
- else
- mprf("%s is healed.",
- attacker->name(DESC_CAP_THE).c_str());
- }
+ int hp_boost = 0;
- int hp_boost = 0;
-
- // thus is probably more valuable on larger weapons?
- if (weapon && is_fixed_artefact( *weapon )
- && weapon->special == SPWPN_VAMPIRES_TOOTH)
- {
- hp_boost = damage_done;
- }
- else
- {
- hp_boost = 1 + random2(damage_done);
- }
+ // thus is probably more valuable on larger weapons?
+ if (weapon && is_fixed_artefact( *weapon )
+ && weapon->special == SPWPN_VAMPIRES_TOOTH)
+ {
+ hp_boost = damage_done;
+ }
+ else
+ {
+ hp_boost = 1 + random2(damage_done);
+ }
- attacker->heal(hp_boost);
+ attacker->heal(hp_boost);
- if (attacker->hunger_level() != HS_ENGORGED)
- attacker->make_hungry(-random2avg(59, 2));
+ if (attacker->hunger_level() != HS_ENGORGED)
+ attacker->make_hungry(-random2avg(59, 2));
- attacker->god_conduct( DID_NECROMANCY, 2 );
- }
+ attacker->god_conduct( DID_NECROMANCY, 2 );
break;
-
+ }
case SPWPN_PAIN:
if (defender->res_negative_energy() <= 0
&& random2(8) <= attacker->skill(SK_NECROMANCY))
@@ -2444,8 +2488,10 @@ bool melee_attack::player_check_monster_died()
player_monattk_hit_effects(true);
if (def->type == MONS_GIANT_SPORE || def->type == MONS_BALL_LIGHTNING)
+ {
msg::stream << "You " << attack_verb << ' '
<< def->name(DESC_NOCAP_THE) << '.' << std::endl;
+ }
monster_die(def, KILL_YOU, 0);
return (true);