summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-02-08 09:12:58 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-02-08 09:12:58 +0000
commit6a7804a077312c11ade9582bf5957628046ea3d7 (patch)
treea84abd9cb89482ba7e2065ab481f15ccc1e41267 /crawl-ref
parentbf1085165e25a72de45edd793a6b9f17752a4a38 (diff)
downloadcrawl-ref-6a7804a077312c11ade9582bf5957628046ea3d7.tar.gz
crawl-ref-6a7804a077312c11ade9582bf5957628046ea3d7.zip
Hydras now behave the same way in monster-vs-monster combat as they do in
player vs monster. Specifically, hydras get their as many attacks as they have heads vs other monsters, and other monsters can chop off hydra heads (at 25% of the probability that the player has of chopping off heads). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@936 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/enum.h9
-rw-r--r--crawl-ref/source/fight.cc276
-rw-r--r--crawl-ref/source/mon-data.h30
-rw-r--r--crawl-ref/source/mon-util.cc60
-rw-r--r--crawl-ref/source/mon-util.h5
-rw-r--r--crawl-ref/source/player.cc48
-rw-r--r--crawl-ref/source/player.h5
7 files changed, 304 insertions, 129 deletions
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index ccc8b70890..1bcc8e7a0e 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -1830,15 +1830,12 @@ enum mons_class_flags
M_EVIL = (1<<19), // monster vulnerable to holy spells
M_UNIQUE = (1<<20), // monster is a unique
- M_FROZEN = (1<<21), // XXX: Potentially ditchable
-
+
+ M_CLAWS = (1<<21), // Chops off hydra heads in combat.
M_SPECIAL_ABILITY = (1<<26), // XXX: eventually make these spells?
- M_COLOUR_SHIFT = (1<<27), // flag for element colour shifters
- M_DCHAR_SYMBOL = (1<<28), // monster looks like a DCHAR terrain
M_NO_SKELETON = (1<<29), // boneless corpses
- M_NO_WOUNDS = (1<<30), // doesn't show would level
M_NO_EXP_GAIN = (1<<31) // worth 0 xp
};
@@ -3765,6 +3762,8 @@ enum vorpal_damage_type
DVORP_CHOPPING = 0x4000, // used for axes
DVORP_SLASHING = 0x5000, // used for whips
DVORP_STABBING = 0x6000, // used for knives/daggers
+
+ DVORP_CLAWING = 0x7000, // claw damage
// These are shortcuts to tie vorpal/damage types for easy setting...
// as above, setting more than one vorpal type is trouble.
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 0c41990f30..3fbae8f4e5 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -375,6 +375,112 @@ int calc_heavy_armour_penalty( bool random_factor )
return heavy_armour;
}
+// Returns true if a head got lopped off.
+static bool chop_hydra_head( const monsters *attacker,
+ monsters *defender,
+ int damage_done,
+ int dam_type,
+ int wpn_brand )
+{
+ const bool defender_visible = mons_near(defender);
+
+ // Monster attackers have only a 25% chance of making the
+ // chop-check to prevent runaway head inflation.
+ if (attacker && !one_chance_in(4))
+ return (false);
+
+ if ((dam_type == DVORP_SLICING || dam_type == DVORP_CHOPPING
+ || dam_type == DVORP_CLAWING)
+ && damage_done > 0
+ && (damage_done >= 4 || wpn_brand == SPWPN_VORPAL || coinflip()))
+ {
+ defender->number--;
+
+ const char *verb = NULL;
+
+ if (dam_type == DVORP_CLAWING)
+ {
+ static const char *claw_verbs[] = { "rip", "tear", "claw" };
+ verb =
+ claw_verbs[
+ random2( sizeof(claw_verbs) / sizeof(*claw_verbs) ) ];
+ }
+ else
+ {
+ static const char *slice_verbs[] =
+ {
+ "slice", "lop", "chop", "hack"
+ };
+ verb =
+ slice_verbs[
+ random2( sizeof(slice_verbs) / sizeof(*slice_verbs) ) ];
+ }
+
+ if (defender->number < 1)
+ {
+ if (defender_visible)
+ mprf( "%s %s %s's last head off!",
+ actor_name(attacker, DESC_CAP_THE).c_str(),
+ actor_verb(attacker, verb).c_str(),
+ str_monam(defender, DESC_NOCAP_THE).c_str() );
+
+ defender->hit_points = -1;
+ }
+ else
+ {
+ if (defender_visible)
+ mprf( "%s %s one of %s's heads off!",
+ actor_name(attacker, DESC_CAP_THE).c_str(),
+ actor_verb(attacker, verb).c_str(),
+ str_monam(defender, DESC_NOCAP_THE).c_str() );
+
+ if (wpn_brand == SPWPN_FLAMING)
+ {
+ if (defender_visible)
+ mpr( "The flame cauterises the wound!" );
+ }
+ else if (defender->number < 19)
+ {
+ simple_monster_message( defender, " grows two more!" );
+ defender->number += 2;
+ heal_monster( defender, 8 + random2(8), true );
+ }
+ }
+
+ return (true);
+ }
+
+ return (false);
+}
+
+static bool actor_decapitates_hydra(monsters *attacker, monsters *defender,
+ int damage_done)
+{
+ if (defender->type == MONS_HYDRA)
+ {
+ const int dam_type = actor_damage_type(attacker);
+ const int wpn_brand = actor_damage_brand(attacker);
+
+ return chop_hydra_head(attacker, defender, damage_done,
+ dam_type, wpn_brand);
+ }
+ return (false);
+}
+
+static bool player_fumbles_attack()
+{
+ // fumbling in shallow water <early return>:
+ if (player_in_water() && !player_is_swimming())
+ {
+ if (random2(you.dex) < 4 || one_chance_in(5))
+ {
+ mpr("Unstable footing causes you to fumble your attack.");
+ return (true);
+ }
+ }
+ return (false);
+}
+
// Returns true if you hit the monster.
bool you_attack(int monster_attacked, bool unarmed_attacks)
{
@@ -485,23 +591,11 @@ bool you_attack(int monster_attacked, bool unarmed_attacks)
if (you.pet_target == MHITNOT)
you.pet_target = monster_attacked;
- // fumbling in shallow water <early return>:
- if (player_in_water() && !player_is_swimming())
- {
- if (random2(you.dex) < 4 || one_chance_in(5))
- {
- mpr("Unstable footing causes you to fumble your attack.");
- return (false);
- }
- }
+ if (player_fumbles_attack())
+ return (false);
- // wet merfolk
- if (player_is_swimming()
- // monster not a water creature, but is in water
- && monster_floundering(defender))
- {
- water_attack = true;
- }
+ // Swimmers get bonus against non-swimmers wading in water.
+ water_attack = player_is_swimming() && monster_floundering(defender);
// new unified to-hit calculation
your_to_hit = calc_your_to_hit( heavy_armour, use_hand_and_a_half_bonus,
@@ -509,7 +603,7 @@ bool you_attack(int monster_attacked, bool unarmed_attacks)
//jmf: check for backlight enchantment
if (mons_has_ench(defender, ENCH_BACKLIGHT_I, ENCH_BACKLIGHT_IV))
- your_to_hit += 2 + random2(8);
+ your_to_hit += 2 + random2(8);
// energy expenditure in terms of food:
make_hungry(3, true);
@@ -517,10 +611,10 @@ bool you_attack(int monster_attacked, bool unarmed_attacks)
if (ur_armed &&
you.inv[ weapon ].base_type == OBJ_WEAPONS &&
is_random_artefact( you.inv[ weapon ] ) &&
- art_proprt[RAP_ANGRY] >= 1 &&
- random2(1 + art_proprt[RAP_ANGRY]))
+ art_proprt[RAP_ANGRY] >= 1 &&
+ random2(1 + art_proprt[RAP_ANGRY]))
{
- go_berserk(false);
+ go_berserk(false);
}
switch (you.special_wield)
@@ -1136,16 +1230,16 @@ bool you_attack(int monster_attacked, bool unarmed_attacks)
/* remember, damage_done is still useful! */
if (hit)
{
- if (defender->type == MONS_JELLY
- || defender->type == MONS_BROWN_OOZE
- || defender->type == MONS_ACID_BLOB
- || defender->type == MONS_ROYAL_JELLY)
- {
- weapon_acid(5);
- }
-
+ if (defender->type == MONS_JELLY
+ || defender->type == MONS_BROWN_OOZE
+ || defender->type == MONS_ACID_BLOB
+ || defender->type == MONS_ROYAL_JELLY)
+ {
+ weapon_acid(5);
+ }
+
int specdam = 0;
-
+
if (ur_armed
&& you.inv[ weapon ].base_type == OBJ_WEAPONS
&& is_demonic( you.inv[ weapon ] ))
@@ -1156,56 +1250,9 @@ bool you_attack(int monster_attacked, bool unarmed_attacks)
if (mons_holiness(defender) == MH_HOLY)
did_god_conduct(DID_ATTACK_HOLY, defender->hit_dice);
- if (defender->type == MONS_HYDRA)
- {
- const int dam_type = player_damage_type();
- const int wpn_brand = player_damage_brand();
-
- if ((dam_type == DVORP_SLICING || dam_type == DVORP_CHOPPING)
- && damage_done > 0
- && (damage_done >= 4 || wpn_brand == SPWPN_VORPAL || coinflip()))
- {
- defender->number--;
-
- temp_rand = random2(4);
- const char *const verb = (temp_rand == 0) ? "slice" :
- (temp_rand == 1) ? "lop" :
- (temp_rand == 2) ? "chop" : "hack";
-
- if (defender->number < 1)
- {
- snprintf( info, INFO_SIZE, "You %s %s's last head off!",
- verb, ptr_monam(defender, DESC_NOCAP_THE) );
- mpr( info );
-
- defender->hit_points = -1;
- }
- else
- {
- snprintf( info, INFO_SIZE, "You %s one of %s's heads off!",
- verb, ptr_monam(defender, DESC_NOCAP_THE) );
- mpr( info );
-
- if (wpn_brand == SPWPN_FLAMING)
- mpr( "The flame cauterises the wound!" );
- else if (defender->number < 19)
- {
- simple_monster_message( defender, " grows two more!" );
- defender->number += 2;
- heal_monster( defender, 8 + random2(8), true );
- }
- }
-
- // if the hydra looses a head:
- // - it's dead if it has none remaining (HP set to -1)
- // - flame used to cauterise doesn't do extra damage
- // - ego weapons do their additional damage to the
- // hydra's decapitated head, so it's ignored.
- //
- // ... and so we skip the special damage.
- goto mons_dies;
- }
- }
+ // If decapitation, extra damage is bypassed.
+ if (actor_decapitates_hydra(NULL, defender, damage_done))
+ goto mons_dies;
// jmf: BEGIN STAFF HACK
// How much bonus damage will a staff of <foo> do?
@@ -2015,6 +2062,20 @@ bool you_attack(int monster_attacked, bool unarmed_attacks)
return (hit);
} // end you_attack()
+static void mons_lose_attack_energy(monsters *attacker, int wpn_speed,
+ int which_attack)
+{
+ // speed adjustment for weapon using monsters
+ if (wpn_speed > 0)
+ {
+ // only get one third penalty/bonus for second weapons.
+ if (which_attack > 0)
+ wpn_speed = (20 + wpn_speed) / 3;
+
+ attacker->speed_increment -= (wpn_speed - 10) / 2;
+ }
+}
+
void monster_attack(int monster_attacking)
{
struct monsters *attacker = &menv[monster_attacking];
@@ -3085,15 +3146,7 @@ commented out for now
}
}
- // adjust time taken if monster used weapon
- if (wpn_speed > 0)
- {
- // only get one third penalty/bonus for second weapons.
- if (runthru > 0)
- wpn_speed = (20 + wpn_speed) / 3;
-
- attacker->speed_increment -= (wpn_speed - 10) / 2;
- }
+ mons_lose_attack_energy(attacker, wpn_speed, runthru);
} // end of for runthru
if (player_perceives_attack)
@@ -3162,11 +3215,21 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
// now disturb defender, regardless
behaviour_event(defender, ME_WHACK, monster_attacking);
- char runthru;
+ int heads = 0;
- for (runthru = 0; runthru < 4; runthru++)
+ if (attacker->type == MONS_HYDRA)
+ heads = attacker->number;
+
+ for (int runthru = 0; runthru < 4; runthru++)
{
- char mdam = mons_damage(attacker->type, runthru);
+ if (attacker->type == MONS_HYDRA)
+ {
+ runthru = 0;
+ if (heads-- < 1)
+ break;
+ }
+
+ int mdam = mons_damage(attacker->type, runthru);
wpn_speed = 0;
if (attacker->type == MONS_ZOMBIE_SMALL
@@ -3194,8 +3257,7 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
if (mdam == 0)
break;
- if ((attacker->type == MONS_TWO_HEADED_OGRE
- || attacker->type == MONS_ETTIN)
+ if (mons_wields_two_weapons(attacker)
&& runthru == 1 && attacker->inv[MSLOT_MISSILE] != NON_ITEM)
{
hand_used = 1;
@@ -3223,8 +3285,8 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
mons_to_hit = random2(mons_to_hit);
if (mons_to_hit >= defender->evasion ||
- ((mons_is_paralysed(defender) || defender->behaviour == BEH_SLEEP)
- && !one_chance_in(20)))
+ ((mons_is_paralysed(defender) || defender->behaviour == BEH_SLEEP)
+ && !one_chance_in(20)))
{
hit = true;
@@ -3337,6 +3399,20 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
mpr(info);
}
+ if (actor_decapitates_hydra(attacker, defender, damage_taken))
+ {
+ mons_lose_attack_energy(attacker, wpn_speed, runthru);
+
+ if (defender->hit_points < 1)
+ {
+ monster_die(defender, KILL_MON, monster_attacking);
+ return (true);
+ }
+
+ // Skip rest of attack.
+ continue;
+ }
+
// special attacks:
switch (attacker->type)
{
@@ -3883,15 +3959,7 @@ bool monsters_fight(int monster_attacking, int monster_attacked)
}
}
- // speed adjustment for weapon using monsters
- if (wpn_speed > 0)
- {
- // only get one third penalty/bonus for second weapons.
- if (runthru > 0)
- wpn_speed = (20 + wpn_speed) / 3;
-
- attacker->speed_increment -= (wpn_speed - 10) / 2;
- }
+ mons_lose_attack_energy(attacker, wpn_speed, runthru);
} // end of for runthru
return true;
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index ac38883343..fb7da5a8d5 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -480,7 +480,7 @@
{
MONS_DRAGON, 'D', GREEN, "dragon",
- M_FLIES | M_SPECIAL_ABILITY, //jmf: warm blood?
+ M_FLIES | M_SPECIAL_ABILITY | M_CLAWS, //jmf: warm blood?
MR_RES_POISON | MR_RES_FIRE | MR_VUL_COLD,
2200, 12, MONS_DRAGON, MONS_DRAGON, MH_NATURAL, -4,
{ 20, 13, 13, 0 },
@@ -674,7 +674,7 @@
{
MONS_TROLL, 'T', BROWN, "troll",
- M_WARM_BLOOD | M_EVIL,
+ M_WARM_BLOOD | M_EVIL | M_CLAWS,
MR_NO_FLAGS,
1500, 10, MONS_TROLL, MONS_TROLL, MH_NATURAL, -3,
{ 20, 15, 15, 0 },
@@ -1040,7 +1040,7 @@
{
MONS_ICE_DRAGON, 'D', WHITE, "ice dragon",
- M_FLIES | M_SPECIAL_ABILITY,
+ M_FLIES | M_SPECIAL_ABILITY | M_CLAWS,
MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
2200, 10, MONS_DRAGON, MONS_ICE_DRAGON, MH_NATURAL, -3,
{ 17, 17, 17, 0 },
@@ -1258,7 +1258,7 @@
{
MONS_STEAM_DRAGON, 'D', LIGHTGREY, "steam dragon",
- M_SPELLCASTER | M_FLIES,
+ M_SPELLCASTER | M_FLIES | M_CLAWS,
MR_NO_FLAGS,
1000, 10, MONS_DRAGON, MONS_STEAM_DRAGON, MH_NATURAL, -3,
{ 12, 0, 0, 0 },
@@ -1518,7 +1518,7 @@
{
MONS_MOTTLED_DRAGON, 'D', RED, "mottled dragon",
- M_SPELLCASTER | M_FLIES,
+ M_SPELLCASTER | M_FLIES | M_CLAWS,
MR_RES_POISON | MR_RES_FIRE,
1100, 10, MONS_DRAGON, MONS_MOTTLED_DRAGON, MH_NATURAL, -3,
{ 15, 0, 0, 0 },
@@ -1568,7 +1568,7 @@
{
MONS_ICE_FIEND, '1', WHITE, "Ice Fiend",
- M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_FROZEN | M_EVIL,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL,
MR_RES_POISON | MR_VUL_FIRE | MR_RES_COLD,
0, 10, MONS_FIEND, MONS_ICE_FIEND, MH_DEMONIC, -12,
{ 25, 25, 0, 0 },
@@ -1640,7 +1640,7 @@
{
MONS_STORM_DRAGON, 'D', LIGHTBLUE, "storm dragon",
- M_SPELLCASTER | M_FLIES,
+ M_SPELLCASTER | M_FLIES | M_CLAWS,
MR_RES_ELEC | MR_RES_COLD,
2800, 12, MONS_DRAGON, MONS_STORM_DRAGON, MH_NATURAL, -5,
{ 25, 15, 15, 0 },
@@ -1810,7 +1810,7 @@
{
MONS_GOLDEN_DRAGON, 'D', YELLOW, "golden dragon",
- M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_CLAWS,
MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
3000, 17, MONS_DRAGON, MONS_GOLDEN_DRAGON, MH_NATURAL, -8,
{ 40, 20, 20, 0 },
@@ -1936,7 +1936,7 @@
{
MONS_GHOUL, 'n', RED, "ghoul",
- M_EVIL,
+ M_EVIL | M_CLAWS,
MR_RES_POISON | MR_RES_COLD,
500, 12, MONS_GHOUL, MONS_GHOUL, MH_UNDEAD, -5,
{ 9, 0, 0, 0 },
@@ -2046,7 +2046,7 @@
{
MONS_SHADOW_DRAGON, 'D', DARKGREY, "shadow dragon",
- M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_EVIL | M_CLAWS,
MR_RES_POISON | MR_RES_COLD,
2000, 12, MONS_DRAGON, MONS_SHADOW_DRAGON, MH_NATURAL, -5,
{ 20, 15, 15, 0 },
@@ -2117,7 +2117,7 @@
{
MONS_SWAMP_DRAGON, 'D', BROWN, "swamp dragon",
- M_SPELLCASTER | M_FLIES,
+ M_SPELLCASTER | M_FLIES | M_CLAWS,
MR_RES_POISON,
1900, 11, MONS_DRAGON, MONS_SWAMP_DRAGON, MH_NATURAL, -3,
{ 18, 9, 9, 0 },
@@ -3252,7 +3252,7 @@
{
MONS_XTAHUA, 'D', RED, "Xtahua",
- M_SPEAKS | M_SEE_INVIS | M_FLIES | M_SPECIAL_ABILITY | M_UNIQUE,
+ M_SPEAKS | M_SEE_INVIS | M_FLIES | M_SPECIAL_ABILITY | M_UNIQUE | M_CLAWS,
MR_RES_POISON | MR_RES_FIRE | MR_VUL_COLD,
0, 20, MONS_DRAGON, MONS_DRAGON, MH_NATURAL, -7,
{ 29, 17, 17, 0 },
@@ -3514,7 +3514,7 @@
{
MONS_SKELETAL_DRAGON, 'D', LIGHTGREY, "skeletal dragon",
- M_SEE_INVIS | M_EVIL,
+ M_SEE_INVIS | M_EVIL | M_CLAWS,
MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
0, 12, MONS_SKELETAL_WARRIOR, MONS_SKELETAL_DRAGON, MH_UNDEAD, -4,
{ 30, 20, 20, 0 },
@@ -4022,7 +4022,7 @@
{
MONS_QUICKSILVER_DRAGON, 'D', LIGHTCYAN, "quicksilver dragon",
- M_SPELLCASTER | M_FLIES | M_SEE_INVIS,
+ M_SPELLCASTER | M_FLIES | M_SEE_INVIS | M_CLAWS,
MR_NO_FLAGS,
0, 14, MONS_DRAGON, MONS_QUICKSILVER_DRAGON, MH_NATURAL, -7,
{ 45, 0, 0, 0 },
@@ -4034,7 +4034,7 @@
{
MONS_IRON_DRAGON, 'D', CYAN, "iron dragon",
- M_SPELLCASTER | M_SEE_INVIS,
+ M_SPELLCASTER | M_SEE_INVIS | M_CLAWS,
MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD,
0, 14, MONS_DRAGON, MONS_IRON_DRAGON, MH_NATURAL, -7,
{ 25, 25, 25, 0 },
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index d0fb486907..04bd443b97 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -1326,6 +1326,11 @@ void define_monster(int index)
mons.enchantment[i] = ENCH_NONE;
} // end define_monster()
+std::string str_monam(const monsters *mon, description_level_type desc,
+ bool force_seen)
+{
+ return (ptr_monam(mon, desc, force_seen));
+}
/* ------------------------- monam/moname ------------------------- */
const char *ptr_monam( const monsters *mon, char desc, bool force_seen )
@@ -1626,6 +1631,61 @@ bool mons_aligned(int m1, int m2)
return (fr1 == fr2);
}
+bool mons_wields_two_weapons(const monsters *m)
+{
+ return (m->type == MONS_TWO_HEADED_OGRE || m->type == MONS_ETTIN);
+}
+
+// Does not check whether the monster can dual-wield - that is the
+// caller's responsibility.
+int mons_offhand_weapon_index(const monsters *m)
+{
+ return (m->inv[1]);
+}
+
+int mons_weapon_index(const monsters *m)
+{
+ // This randomly picks one of the wielded weapons for monsters that can use
+ // two weapons. Not ideal, but better than nothing. fight.cc does it right,
+ // for various values of right.
+ int weap = m->inv[MSLOT_WEAPON];
+
+ if (mons_wields_two_weapons(m))
+ {
+ const int offhand = mons_offhand_weapon_index(m);
+ if (offhand != NON_ITEM && (weap == NON_ITEM || coinflip()))
+ weap = offhand;
+ }
+
+ return (weap);
+}
+
+int mons_base_damage_type(const monsters *m)
+{
+ return (mons_class_flag(m->type, M_CLAWS)? DVORP_CLAWING : DVORP_CRUSHING);
+}
+
+int mons_damage_type(const monsters *m)
+{
+ const int mweap = mons_weapon_index(m);
+
+ if (mweap == NON_ITEM)
+ return (mons_base_damage_type(m));
+
+ return (get_vorpal_type(mitm[mweap]));
+}
+
+int mons_damage_brand(const monsters *m)
+{
+ const int mweap = mons_weapon_index(m);
+
+ if (mweap == NON_ITEM)
+ return (SPWPN_NORMAL);
+
+ const item_def &weap = mitm[mweap];
+ return (!is_range_weapon(weap)? get_weapon_brand(weap) : SPWPN_NORMAL);
+}
+
bool mons_friendly(const monsters *m)
{
return (m->attitude == ATT_FRIENDLY || mons_has_ench(m, ENCH_CHARM));
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 7bec117412..e7584b97df 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -134,6 +134,8 @@ const char *monam(int mons_num, int mons, bool vis, char desc, int mons_wpn = NO
// these front for monam
const char *ptr_monam(const monsters *mon, char desc, bool force_seen = false);
+std::string str_monam(const monsters *mon, description_level_type desc,
+ bool force_seen = false);
// last updated 12may2000 {dlb}
/* ***********************************************************************
@@ -226,6 +228,9 @@ bool mons_is_statue(int mc);
bool mons_is_demon( int mc );
bool mons_is_humanoid( int mc );
+bool mons_wields_two_weapons(const monsters *m);
+int mons_damage_type(const monsters *m);
+int mons_damage_brand(const monsters *m);
// last updated 12may2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 4cd501d463..dea3890397 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -57,8 +57,42 @@
#include "tutorial.h"
#include "view.h"
+/////////////////////////////////////////////////////////////////////////////
+// Actor stuff - generic functions that can be called with a monster pointer,
+// or NULL for the player.
+
+std::string pronoun_you(description_level_type desc)
+{
+ return (desc == DESC_CAP_A || desc == DESC_CAP_THE? "You" : "you");
+}
+
+std::string actor_name(const monsters *actor, description_level_type desc)
+{
+ return (actor? ptr_monam(actor, desc) : pronoun_you(desc));
+}
+
+// actor_verb(NULL, "chop") == chop, as in "You chop"
+// actor_verb(monster, "chop") == chops, as in "The skeletal warrior chops".
+std::string actor_verb(const monsters *actor, const std::string &verb)
+{
+ // Simplistic - we really should be conjugating the verb
+ // appropriately. We'll special-case as necessary.
+ return (actor? verb + "s" : verb);
+}
+
+int actor_damage_type(const monsters *actor)
+{
+ return (actor? mons_damage_type(actor) : player_damage_type());
+}
+
+int actor_damage_brand(const monsters *actor)
+{
+ return (actor? mons_damage_brand(actor) : player_damage_brand());
+}
+
/*
you.duration []: //jmf: obsolete, see enum.h instead
+ //[ds] Well, can we lose it yet?
0 - liquid flames
1 - icy armour
2 - repel missiles
@@ -600,14 +634,18 @@ int player_damage_type( void )
return (get_vorpal_type(you.inv[wpn]));
}
else if (you.equip[EQ_GLOVES] == -1 &&
- (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS
- || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON
- || you.mutation[MUT_CLAWS]
- || you.species == SP_TROLL
- || you.species == SP_GHOUL))
+ you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS)
{
return (DVORP_SLICING);
}
+ else if (you.equip[EQ_GLOVES] == -1 &&
+ (you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON
+ || you.mutation[MUT_CLAWS]
+ || you.species == SP_TROLL
+ || you.species == SP_GHOUL))
+ {
+ return (DVORP_CLAWING);
+ }
return (DVORP_CRUSHING);
}
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index ed08ec44dd..29d551582d 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -16,6 +16,11 @@
#include "externs.h"
+std::string actor_name(const monsters *actor, description_level_type desc);
+std::string actor_verb(const monsters *actor, const std::string &verb);
+int actor_damage_type(const monsters *actor);
+int actor_damage_brand(const monsters *actor);
+
bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift,
bool force );