attacking a monster that is in sight.
Implemented AF_MUTATE for pulsating lumps.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1288 c06c8d41-db1a-0410-9941-cceddc491573
ACKNLTFL2RI3PMRWLNRVLRWGQAMLRFKNGNS5LED6NFE5GVGFIHFAC
C67GX7W5HBCDPQJRSHWMLM4DUJ3ELFSHH42SVICFJVCJW25T5Z3AC
FTDI4OSR3G5KKGJ5UILSHTHOP4GF4XJ4DHKYPUWFKWAGGXTOCJSQC
6GT5JAWOIIL4SQ5MWIID6ZVO3KKQFWDQDZNVFHZ6DNK5QCBXJ4UAC
HH3HFWVXABJ4IRMN22PPJCREMULZSN6DA7VYKOGECGMNUQTZ5QNQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
33ZMPQC6OXTESW7SRW765GRNJUEJRSYONRVZVIEUDAUEJ2PPMB4AC
ITDUEUO7XAZANPC4GRB3SEDFBOV7GLFPNPTYE5LYNC3CS6BSVZTQC
L4PKJZERR7WADKWHY3MR6J6OZFREVPL3CB43I6MLJ2BVKWCUTE7AC
GS2I6EO4OQZ5FHQJQ6YRUDPSJ5XWGLHN544MVQPSF2PATUSJFSSAC
NNG27Y5ZQAZX6UD7F7M4F6KEZBEDFXPEEC3LFUSX4ESKT7K6UJQAC
OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
DDU4A3JGN5IUIPP5IASOODKPR2WBHSDSV4FITZ6HNXNSXXQACWAQC
static std::string anon_name(description_level_type desc);
static std::string actor_name(const actor *a, description_level_type desc,
bool actor_visible);
static std::string pronoun(const actor *a, pronoun_type ptyp,
bool actor_visible);
static std::string anon_pronoun(pronoun_type ptyp);
}
// Returns true if a head got lopped off.
static bool chop_hydra_head( const actor *attacker,
actor *def,
int damage_done,
int dam_type,
int wpn_brand )
{
monsters *defender = dynamic_cast<monsters*>(def);
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->atype() == ACT_MONSTER && !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!",
attacker->name(DESC_CAP_THE).c_str(),
attacker->conj_verb(verb).c_str(),
defender->name(DESC_NOCAP_THE).c_str() );
defender->hurt(attacker, defender->hit_points);
}
else
{
if (defender_visible)
mprf( "%s %s one of %s's heads off!",
attacker->name(DESC_CAP_THE).c_str(),
attacker->conj_verb(verb).c_str(),
defender->name(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(actor *attacker, actor *defender,
int damage_done, int damage_type = -1)
{
if (defender->id() == MONS_HYDRA)
{
const int dam_type =
damage_type != -1? damage_type : attacker->damage_type();
const int wpn_brand = attacker->damage_brand();
return chop_hydra_head(attacker, defender, damage_done,
dam_type, wpn_brand);
}
return (false);
std::string melee_attack::actor_name(const actor *a,
description_level_type desc,
bool actor_visible)
{
return (actor_visible? a->name(desc) : anon_name(desc));
}
std::string melee_attack::pronoun(const actor *a,
pronoun_type pron,
bool actor_visible)
{
return (actor_visible? a->pronoun(pron) : anon_pronoun(pron));
}
std::string melee_attack::anon_pronoun(pronoun_type pron)
{
switch (pron)
{
default:
case PRONOUN_CAP: return "It";
case PRONOUN_NOCAP: return "it";
case PRONOUN_CAP_POSSESSIVE: return "Its";
case PRONOUN_NOCAP_POSSESSIVE: return "its";
case PRONOUN_REFLEXIVE: return "itself";
}
}
std::string melee_attack::anon_name(description_level_type desc)
{
switch (desc)
{
case DESC_CAP_THE:
case DESC_CAP_A:
return ("It");
case DESC_CAP_YOUR:
return ("Its");
case DESC_NOCAP_YOUR:
case DESC_NOCAP_ITS:
return ("its");
case DESC_NOCAP_THE:
case DESC_NOCAP_A:
case DESC_PLAIN:
default:
return ("it");
}
}
std::string melee_attack::atk_name(description_level_type desc) const
{
return actor_name(attacker, desc, attacker_visible);
}
std::string melee_attack::def_name(description_level_type desc) const
{
return actor_name(defender, desc, defender_visible);
}
special_damage_message =
make_stringf("%s %s in the translocular energy.",
defender->name(DESC_CAP_THE).c_str(),
defender->conj_verb("bask").c_str());
if (defender_visible)
special_damage_message =
make_stringf("%s %s in the translocular energy.",
def_name(DESC_CAP_THE).c_str(),
defender->conj_verb("bask").c_str());
special_damage_message =
make_stringf(
"%s %s%s",
defender->name(DESC_CAP_THE).c_str(),
defender->conj_verb("convulse").c_str(),
special_attack_punctuation().c_str());
if (defender_visible)
special_damage_message =
make_stringf(
"%s %s%s",
defender->name(DESC_CAP_THE).c_str(),
defender->conj_verb("convulse").c_str(),
special_attack_punctuation().c_str());
special_damage_message =
defender->atype() == ACT_MONSTER?
make_stringf("%s %s.",
defender->name(DESC_CAP_THE).c_str(),
defender->conj_verb("shudder").c_str())
: ("You are blasted by holy energy!");
if (defender_visible)
special_damage_message =
defender->atype() == ACT_MONSTER?
make_stringf("%s %s.",
defender->name(DESC_CAP_THE).c_str(),
defender->conj_verb("shudder").c_str())
: ("You are blasted by holy energy!");
special_damage_message =
make_stringf("%s %s in agony.",
defender->name(DESC_CAP_THE).c_str(),
defender->conj_verb("writhe").c_str());
if (defender_visible)
special_damage_message =
make_stringf("%s %s in agony.",
defender->name(DESC_CAP_THE).c_str(),
defender->conj_verb("writhe").c_str());
// Returns true if a head got lopped off.
bool melee_attack::chop_hydra_head( int dam,
int dam_type,
int wpn_brand )
{
// Monster attackers have only a 25% chance of making the
// 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
&& (dam >= 4 || wpn_brand == SPWPN_VORPAL || coinflip()))
{
def->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 (def->number < 1)
{
if (defender_visible)
mprf( "%s %s %s's last head off!",
atk_name(DESC_CAP_THE).c_str(),
attacker->conj_verb(verb).c_str(),
def_name(DESC_NOCAP_THE).c_str() );
defender->hurt(attacker, def->hit_points);
}
else
{
if (defender_visible)
mprf( "%s %s one of %s's heads off!",
atk_name(DESC_CAP_THE).c_str(),
attacker->conj_verb(verb).c_str(),
def_name(DESC_NOCAP_THE).c_str() );
if (wpn_brand == SPWPN_FLAMING)
{
if (defender_visible)
mpr( "The flame cauterises the wound!" );
}
else if (def->number < 19)
{
simple_monster_message( def, " grows two more!" );
def->number += 2;
heal_monster( def, 8 + random2(8), true );
}
}
return (true);
}
return (false);
}
bool melee_attack::decapitate_hydra(int dam, int damage_type)
{
if (defender->id() == MONS_HYDRA)
{
const int dam_type =
damage_type != -1? damage_type : attacker->damage_type();
const int wpn_brand = attacker->damage_brand();
return chop_hydra_head(dam, dam_type, wpn_brand);
}
return (false);
}
atk->name(DESC_CAP_THE).c_str(),
defender->name(DESC_NOCAP_THE).c_str(),
defender->pronoun(PRONOUN_NOCAP_POSSESSIVE).c_str());
atk_name(DESC_CAP_THE).c_str(),
def_name(DESC_NOCAP_THE).c_str(),
pronoun(defender, PRONOUN_NOCAP_POSSESSIVE,
defender_visible).c_str());