player.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8224 c06c8d41-db1a-0410-9941-cceddc491573
I6UO62GLJASOSMHEV4M74WQ3U4YFUFLM4AUA6XGWROCIK2LVDA7QC
BZOWGMBBSF5B7YSULCT7MLLHAHHNSYH5BSUXWSZWIVBP5YUYDTYAC
YCRNHMRKDOFDHHUHCBSQTMLD6ZTPWS2SS5EBUL5BIQ3JN6YV7YWAC
EHON5UAC6S4MGKE5P5NYQFSONIYWUDH7X2NG7JPYAST3NXIEHDFQC
MAYNJBDDCCUOFMJS5BQTK2YFZZX4OBEQHCP5ATDXDNU2EDBEKILQC
R2PSUO2P6A4NWITNJLUB5DPSVM43R3N2H7T6RMBV6HZBDAKX6XUQC
V3DXA3JNGCGVUO6GQEOUY5FCYLNWS7RGH4IOBFYCFHGJSYXL2LEQC
2BJFHMLTZXNPVJYS7Q4CS2PRFXPV7TJEQKKOQW6QHFJPFF35R76QC
DYPYV5344257DUQRFXFR4YPM6WB6MG2DT4TYFJKMRZ4XXYZ3DAKAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
6GSGCC5JQJ5NOKX36UHRNOCXNHDBS2A2TDMAR34UBOGWE2DORXIQC
B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC
3QLM46S44Z7GDLWPH3VHBMW2RSWZAOLGJMG2BDKNGUOZIM4IX6WAC
72GIZBEMQLEF3TITOHABWHRLL5TE7KOUSVWOUEHFMO2OZQ4EIB7AC
J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
HM6NOS7BN5665KWIFGBXOHZIDMRSVCESN72GMGI6NVBFZGCF3L6QC
BLN5LDH5NRRJPBY77A36Q4THEY75N42MVCJMZRUZ2D5YSXTDL4HQC
E3X5HVN5UN75OMTJA6JFQBNZ54P37NDZLZZF7EFBZZC45KR73YGAC
G5WLU3B4MR3ZDJLGR6OHNIMLZXGQS2EWBJ5YYY5J2GWM6DTD44BAC
ZEFGFQHN6J2S6EIPX7EPDG22C5YXTI6DMKQHHRCLWN5MQC44KY3AC
ADIVVYTV2MJ3XVRYDNBLPTAEACCNF27XZDCRVZFQEHRHPMZGNITQC
QXITU67XLMZPUZNVB3ALUWVEYHIBQR3OWK2DCHRHJQWHEXNEUJXQC
S7KC3IFKCUNBO3XO4TV3KEQEIDZWSRJSKXY65DPONKMG54VHU3UQC
UWI3ZNJDRQRL7CXFNFEG46TA6SAK24XUFY5YOKVOTJA3VG3OBNFAC
G7CTMQ3VNTAB73ZI3LNZHKTAJ5LEQEGG772MVFQQ5XXLCMJVORTQC
QG7MKYZECIRDJJZKVRFI6XTCH42GTKA55BFIWPJBQZ27CZVLUJDQC
K2RBO245UPBDAGMUUMB5EPUNKBDMQ2FM4HLCTTF6Y7ILWW2XVSDQC
774O5HM4CU5QYP4MPKKLHIVZQ5JLLZETYIDZZYBAPOJSO6ILC5RAC
R2DQBWKIW7YUJB5SOQ7J274JIYRVX4H3ISFRPAL5RG2RVVP4G2KAC
DAB4UJ6EPV46LAI7QWYRELMJ4ZCFNNR3KVQFIVMULDV3VHYYFQLAC
BMHUBADDGIOZRVN4P3O5QKIDUYD4RFWBS7MP5X6LZWAYHUBRVD2QC
2XFQMYACTXJZRFSEMXTVZJDHPFYTSOHMZ2FVUBBIJZEOUIKHJNDQC
AIIVH43Z5X3GTPFY4FXQRZPG6Y7QPH2KJ47VM2Q43PCGGD5MTMOAC
NRMSQFTORG3GC7HQBIN5DHB5GLWXM6IQO6PTXD4C7LBQWJIHYIGAC
QJXDZXN3KYCMZCJ7VHUFD737HFHOZ2PTX3H64QW4PPQF4HBJUX5AC
2FHNLTLN3DVVD67N4QMAQ2LO7YY4GVZWXJAOIWGCCYYGIX7UHSVQC
2TFYJ7D72JY4DYQW3GSPEONA2WYIVHAJXTIQ2QRDIWF65XN2QFGAC
GGUXPDKYPGGHSXH25WE5AFUAQE2DLWNOR4DGKNACTFBLKVVZ4V4AC
YM3U5YZEFIYLRJVDWQCSP75JL56WC36XLQSL5ZBT4IWSXYJRBCBAC
JYEEOUYQ7ZPKOGWUV7VCORBVSOLF2UCBFBH3TR75RGOSS6PNKYUAC
F6LX36GU6BWJFJLV2JNVM6PWTMQ35R33EOMQNGGQNQY67V2LJVIAC
64RZSOR4B4T5QO3FAERBTH2QJIQFSCIFHI4WYK3MDAEAZVAHRLVQC
LM764EO6YIFOKMRXWZ5S4GYZB4BHZQDTEFP7MEVYO4NN4EDOFGNQC
static std::string _try_exact_string(const std::vector<std::string> prefixes,
const std::string key,
bool ignore_hostile = false,
bool ignore_related = false,
bool ignore_religion = false,
bool ignore_silenced = false)
static std::string __try_exact_string(const std::vector<std::string> &prefixes,
const std::string &key,
bool ignore_hostile = false,
bool ignore_related = false,
bool ignore_religion = false,
bool ignore_silenced = false)
static bool _invalid_msg(const std::string &msg, bool no_player, bool no_foe,
bool no_foe_name, bool no_god)
{
if (no_player
&& (msg.find("@player") != std::string::npos
|| msg.find("@Player") != std::string::npos
|| msg.find(":You") != std::string::npos))
{
return (true);
}
if (no_player)
{
std::vector<std::string> lines = split_string("\n", msg);
for (unsigned int i = 0; i < lines.size(); i++)
{
if (starts_with(lines[i], "You")
|| ends_with(lines[i], "you."))
{
return (true);
}
}
}
if (no_foe && (msg.find("@foe") != std::string::npos
|| msg.find("@Foe") != std::string::npos
|| msg.find("foe@") != std::string::npos
|| msg.find("@species") != std::string::npos))
{
return (true);
}
if (no_god && (msg.find("_god@") != std::string::npos
|| msg.find("@god_") != std::string::npos))
{
return (true);
}
if (no_foe_name && msg.find("@foe_name@") != std::string::npos)
return (true);
static std::string _get_speak_string(const std::vector<std::string> prefixes,
const std::string key,
const monsters *monster)
return (false);
}
static std::string _try_exact_string(const std::vector<std::string> &prefixes,
const std::string &key,
bool no_player, bool no_foe,
bool no_foe_name, bool no_god,
bool ignore_hostile = false,
bool ignore_related = false,
bool ignore_religion = false,
bool ignore_silenced = false)
{
std::string msg;
for (int tries = 0; tries < 10; tries++)
{
msg =
__try_exact_string(prefixes, key, ignore_hostile, ignore_related,
ignore_religion, ignore_silenced);
// If the first message was non-empty and discarded then discard
// all subsequent empty messages, so as to not replace an
// invalid non-empty message with an empty one.
if (msg.empty())
{
if (tries == 0)
return (msg);
else
{
tries--;
continue;
}
}
if (_invalid_msg(msg, no_player, no_foe, no_foe_name, no_god))
{
msg = "";
continue;
}
break;
}
return (msg);
}
static std::string __get_speak_string(const std::vector<std::string> &prefixes,
const std::string &key,
const monsters *monster,
bool no_player, bool no_foe,
bool no_foe_name, bool no_god)
static std::string _get_speak_string(const std::vector<std::string> &prefixes,
const std::string &key,
const monsters *monster,
bool no_player, bool no_foe,
bool no_foe_name, bool no_god)
{
std::string msg;
for (int tries = 0; tries < 10; tries++)
{
msg =
__get_speak_string(prefixes, key, monster, no_player, no_foe,
no_foe_name, no_god);
// If the first message was non-empty and discarded then discard
// all subsequent empty messages, so as to not replace an
// invalid non-empty message with an empty one.
if (msg.empty())
{
if (tries == 0)
return (msg);
else
{
tries--;
continue;
}
}
if (_invalid_msg(msg, no_player, no_foe, no_foe_name, no_god))
{
msg = "";
continue;
}
break;
}
return (msg);
}
// animals only look at the current player form,
// smart monsters at the actual player genus
if (is_player_same_species(monster->type,
mons_intel(monster) <= I_ANIMAL))
const actor* foe = (!crawl_state.arena && mons_wont_attack(monster)
&& invalid_monster_index(monster->foe)) ?
&you : monster->get_foe();
const monsters* m_foe = (foe && foe->atype() == ACT_MONSTER) ?
dynamic_cast<const monsters*>(foe) : NULL;
// animals only look at the current player form, smart monsters at the
// actual player genus
if (!foe || foe->atype() == ACT_PLAYER)
{
if (is_player_same_species(monster->type,
mons_intel(monster) <= I_ANIMAL))
{
prefixes.push_back("related"); // maybe overkill for Beogh?
}
}
else
const bool no_foe = foe == NULL;
const bool no_player = crawl_state.arena
|| (!mons_wont_attack(monster)
&& (!foe || foe->atype() != ACT_PLAYER));
const bool mon_foe = m_foe != NULL;
const bool no_god = no_foe || (mon_foe && foe->deity() == GOD_NO_GOD);
const bool named_foe = !no_foe
&& (!mon_foe || (m_foe->is_named()
&& m_foe->type != MONS_ROYAL_JELLY));
const bool no_foe_name = !named_foe
|| (mon_foe && (m_foe->flags & MF_NAME_MASK));
const actor* foe = (!crawl_state.arena && mons_wont_attack(monster)
&& invalid_monster_index(monster->foe)) ?
&you : monster->get_foe();
const monsters* m_foe = (foe && foe->atype() == ACT_MONSTER) ?
dynamic_cast<const monsters*>(foe) : NULL;
std::string foe_species;
if (foe == NULL)
;
else if (foe->atype() == ACT_PLAYER)
{
foe_species = species_name(you.species, 1, true);
msg = replace_all(msg, "@player_only@", "");
msg = replace_all(msg, " @foe,@", ",");
msg = replace_all(msg, "@player", "@foe");
msg = replace_all(msg, "@Player", "@Foe");
msg = replace_all(msg, "@foe@", "you");
msg = replace_all(msg, "@Foe@", "You");
msg = replace_all(msg, "@foe_name@", you.your_name);
msg = replace_all(msg, "@foe_species@", species_name(you.species, 1));
msg = replace_all(msg, "@foe_genus@", foe_species);
msg = replace_all(msg, "@foe_genus_plural@",
_pluralise_player_genus());
}
else
{
std::string foe_name;
if (you.can_see(m_foe) || crawl_state.arena)
{
if (m_foe->attitude == ATT_FRIENDLY
&& !mons_is_unique(m_foe->type)
&& !crawl_state.arena)
{
foe_name = m_foe->name(DESC_NOCAP_YOUR);
}
else
foe_name = m_foe->name(DESC_NOCAP_THE);
}
else
foe_name = "something";
msg = replace_all(msg, " @to_foe@", " to @foe@");
msg = replace_all(msg, " @at_foe@", " at @foe@");
msg = replace_all(msg, "@foe,@", "@foe@,");
msg = replace_all(msg, "@foe@", foe_name);
msg = replace_all(msg, "@Foe@", upcase_first(foe_name));
if (m_foe->is_named())
msg = replace_all(msg, "@foe_name@",
m_foe->name(DESC_PLAIN, true));
std::string species = mons_type_name(mons_species(m_foe->type),
DESC_PLAIN);
msg = replace_all(msg, "@foe_species@", species);
std::string genus = mons_type_name(mons_genus(m_foe->type),
DESC_PLAIN);
msg = replace_all(msg, "@foe_genus@", genus);
msg = replace_all(msg, "@foe_genus_plural@", pluralise(genus));
foe_species = genus;
}
msg = replace_all(msg, "@player_name@", you.your_name);
msg = replace_all(msg, "@player_species@",
species_name(you.species, 1).c_str());
msg = replace_all(msg, "@player_genus@",
species_name(you.species, 1, true, false).c_str());
msg = replace_all(msg, "@player_genus_plural@",
_pluralise_player_genus().c_str());
// Replace with "you are" for atheists.
msg = replace_all(msg, "@god_is@", _replace_god_name(true, false));
msg = replace_all(msg, "@God_is@", _replace_god_name(true, true));
if (foe != NULL)
{
const god_type god = foe->deity();
// No verb needed,
msg = replace_all(msg, "@player_god@", _replace_god_name(false, false));
msg = replace_all(msg, "@Player_god@", _replace_god_name(false, true));
// Replace with "you are" for atheists.
msg = replace_all(msg, "@god_is@",
_replace_god_name(god, true, false));
msg = replace_all(msg, "@God_is@", _replace_god_name(god, true, true));
// No verb needed,
msg = replace_all(msg, "@foe_god@",
_replace_god_name(god, false, false));
msg = replace_all(msg, "@foe_god@",
_replace_god_name(god, false, true));
}
Speaking to the player vs to another monster
--------------------------------------------
If a message contains a variable starting with "@player", then that message
will only be used by friendly/good-neutral monsters, or by hostile/neutral
monsters which have the player as their foe (and it will never be used in the
arena). Additionally, any message containing a line starting with "You" or
ending in a bare "you." (but not a quoted "you.") will also be considered
player centric. You can also make a message player-centric by appending
"@player_only@" to the end of any of the lines in the message, which will be
removed before displaying it to the player.
If you want a message to be able to apply to a foe which is another monster in
*addition* to the player, you can replace "@player" with "@foe" to have the
variable filled out with a string appropriate for the foe being either the
player or another monster. If "@foe_name@" is present then the message will
only be used on monster foes which are named, and if "@foe_god@" or "@god_is@"
is present then it will only be used on priestly monsters or god gift monsters.
"@Foe@" or "@foe@" will be replaced with "You" or "you" if directed at the
player, or if directed at another monster be the same as "@The_monster@" or
"@the_monster@", but with the foe monster's name rather than the speaking
monster's name
If you want to indicate which monster a message is directed at, you can put in
"@to_foe@" or "@at_foe@" to fill in the foe name when the message is directed
at a monster; when directed at the player the variable will be removed. For
example, with the message:
@The_monster@ says @to_foe@, "Defend yourself!"
If directed at an orc will expand to:
@The_monster@ says to the orc, "Defend yourself!"
but if directed at the player will expand to:
@The_monster@ says, "Defend yourself!"
You can do something similar with "@foe,@" for asking questions and the like.
For example:
@The_monster@ asks @foe,@ "Who are you?"
when directed at an orc will expand to:
@The_monster@ asks the orc, "Who are you?"
and when directed at the player will expand to:
@The_monster@ asks, "Who are you?"