summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 );