summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-29 04:38:32 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-29 04:38:32 +0000
commit3ccb84a86f21de5797a5a2480711233fb38ea9d5 (patch)
treef9179f655db052cf8b002614cde1ac8bfd706891 /crawl-ref/source
parent8f4023a8f1efa5f683e92244341149b6cc46a338 (diff)
downloadcrawl-ref-3ccb84a86f21de5797a5a2480711233fb38ea9d5.tar.gz
crawl-ref-3ccb84a86f21de5797a5a2480711233fb38ea9d5.zip
Changes to monster spell messages:
* If the monster's casting would be affected by Silence then attempt to indicate that the monster is using words. * Allow for different messages for targeted spells vs untargeted spells. * Provide some special messages for the Animate Dead spell. * Don't let sphinxes gesture or point. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8007 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/dat/database/monspell.txt177
-rw-r--r--crawl-ref/source/externs.h8
-rw-r--r--crawl-ref/source/mon-util.cc73
-rw-r--r--crawl-ref/source/mstuff2.cc178
-rw-r--r--crawl-ref/source/player.cc23
5 files changed, 334 insertions, 125 deletions
diff --git a/crawl-ref/source/dat/database/monspell.txt b/crawl-ref/source/dat/database/monspell.txt
index bbf76a8b83..821186e6ff 100644
--- a/crawl-ref/source/dat/database/monspell.txt
+++ b/crawl-ref/source/dat/database/monspell.txt
@@ -1,12 +1,68 @@
+# This file contains the messages used to "announce" a spell, like
+# "The wizard mumbles some strange words." The messages are looked
+# up in the following order by the following keys:
+#
+# 1) The name of the spell being cast:
+# a) If being cast by a wizard or priest monster with arms, first try
+# with the suffix "real".
+# b) If being cast by a monster of normal or higher intelligence with arms,
+# try with the suffix "gestures".
+# c) Next, try without any suffix.
+# 2) The name of the monster's type.
+# 3) The name of the monster's species.
+# 4) The name of the monster's genus.
+# 5) "priest" if the monster is a priest type, "wizard" if it's a wizard type,
+# or "demon" if it's demonic.
+#
+# For 2 to 5, if the spell has a target it will first add the suffix
+# "targeted" to the lookup key before trying without the suffix.
+#
+# For all lookups, if the monster is unseen by the player it will add the
+# prefix "unseen" to the key, or if the player or monster is silenced
+# it will prefix "silent" to the key (if the monster is both unseen and
+# unheard no message is ever given). If using the prefix "silent" gives
+# no results it will try again without the prefix, assuming that the
+# spell has no sound component.
+#
+# To give no message use the string "__NONE", and to skip the current
+# lookup method and move onto the next one use the string "__NEXT".
+
#####################################################
# Individual spells.
#####################################################
%%%%
+unseen Animate Dead cast real
+
+You hear @something@ calling out to the dead.
+%%%%
+Animate Dead cast real
+
+@The_monster@ gestures at the surounding area while chanting.
+
+@The_monster@ throws @possessive@ @arms@ wide while chanting.
+%%%%
+Animate Dead cast gestures
+
+@The_monster@ gestures at the surounding.
+
+@The_monster@ throws @possessive@ @arms@ wide.
+%%%%
+Symbol of Torment cast
+
+@The_monster@ calls on the powers of Hell!
+%%%%
+unseen Symbol of Torment cast
+
+@The_something@ calls on the powers of Hell!
+#####################################################
+# Individual innate spells (breathing and spitting).
+#####################################################
+%%%%
Acid Splash cast
@The_monster@ spits acid at @target@.
%%%%
-Acid Splash cast unseen
+unseen Acid Splash cast
You hear a spitting sound.
%%%%
@@ -14,7 +70,7 @@ Draconian Breath cast
@The_monster@ breathes @beam@ at @target@.
%%%%
-Draconian Breath cast unseen
+unseen Draconian Breath cast
You hear a roar.
%%%%
@@ -22,7 +78,7 @@ Poison Splash cast
@The_monster@ spits poison at @target@.
%%%%
-Poison Splash cast unseen
+unseen Poison Splash cast
You hear a spitting sound.
%%%%
@@ -30,57 +86,56 @@ Sticky Flame Splash cast
@The_monster@ spits sticky flame at @target@.
%%%%
-Sticky Flame Splash cast unseen
+unseen Sticky Flame Splash cast
You hear a spitting sound.
+########################################################################
+# Individual monsters
+########################################################################
%%%%
-Symbol of Torment cast
+Geryon cast
-@The_monster@ calls on the powers of Hell!
+@The_monster@ winds a great silver horn.
%%%%
-Symbol of Torment cast unseen
+unseen Geryon cast
-@The_something@ calls on the powers of Hell!
-#####################################################
-# Priest and wizard casting messages.
-#####################################################
+You hear a weird and mournful sound.
%%%%
-priest cast
+giant orange brain cast
-@The_monster@ prays.
+@The_monster@ pulsates.
+%%%%
+orb of fire cast
-@The_monster@ mumbles some strange prayers.
+@The_monster@ glows yellow.
-@The_monster@ utters an invocation.
-%%%%
-priest cast unseen
+@The_monster@ glows bright magenta.
-You hear some strange, mumbled prayers.
-%%%%
-wizard cast
+@The_monster@ glows deep purple.
-@The_monster@ gestures wildly.
+@The_monster@ glows red.
+
+@The_monster@ emits a lurid red light.
+%%%%
+# Sphinxes can't gesture or point.
+sphinx cast
@The_monster@ mumbles some strange words.
@The_monster@ casts a spell.
-%%%%
-wizard cast unseen
-
-You hear some strange, mumbled words.
########################################################################
-# Monster genus and species messages.
+# Monster species and genus messages.
########################################################################
%%%%
-demon cast
+dragon cast targeted
-@The_monster@ gestures.
+@The_monster@ breathes @beam@ at @target@.
%%%%
dragon cast
-@The_monster@ breathes @beam@ at @target@.
+@The_monster@ USED A NON-TARGETED DRAGON SPELL. Please file a bug report.
%%%%
-dragon cast unseen
+unseen dragon cast
You hear a roar.
%%%%
@@ -90,38 +145,66 @@ curse skull cast
@The_monster@ casts a spell.
%%%%
-curse skull cast unseen
+unseen curse skull cast
You hear the clattering of teeth.
%%%%
+giant eyeball cast targeted
+
+@The_monster@ gazes at @target@.
+%%%%
giant eyeball cast
-@The_monster@ gazes.
-########################################################################
-# Individual monsters
-########################################################################
+@The_monster@ looks around.
+######################################################
+# Generic priest, wizard and demonic casting messages.
+######################################################
%%%%
-Geryon cast
+priest cast targeted
-@The_monster@ winds a great silver horn.
+@The_monster@ prays against @target@.
+
+@The_monster@ mumbles some strange prayers against @target@.
+
+@The_monster@ utters an invocation against @target@.
%%%%
-Geryon cast unseen
+priest cast
-You hear a weird and mournful sound.
+@The_monster@ prays.
+
+@The_monster@ mumbles some strange prayers.
+
+@The_monster@ utters an invocation.
%%%%
-giant orange brain cast
+unseen priest cast
-@The_monster@ pulsates.
+You hear some strange, mumbled prayers.
%%%%
-orb of fire cast
+wizard cast targeted
-@The_monster@ glows yellow.
+@The_monster@ gestures at @target@ while chanting.
-@The_monster@ glows bright magenta.
+@The_monster@ points at @target@ and mumbles some strange words.
-@The_monster@ glows deep purple.
+@The_monster@ casts a spell at @target@.
+%%%%
+wizard cast
-@The_monster@ glows red.
+@The_monster@ gestures wildly while chanting.
-@The_monster@ emits a lurid red light.
+@The_monster@ mumbles some strange words.
+
+@The_monster@ casts a spell.
+%%%%
+unseen wizard cast
+
+You hear some strange, mumbled words.
+%%%%
+demon cast targeted
+
+@The_monster@ gestures at @target@.
+%%%%
+demon cast
+
+@The_monster@ gestures.
%%%%
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 520d7f08b1..4c11d2a6e0 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -310,6 +310,8 @@ public:
bool *can_plural = NULL) const = 0;
virtual std::string foot_name(bool plural,
bool *can_plural = NULL) const = 0;
+ virtual std::string arm_name(bool plural,
+ bool *can_plural = NULL) const = 0;
virtual bool fumbles_attack(bool verbose = true) = 0;
@@ -387,6 +389,7 @@ public:
virtual bool paralysed() const = 0;
virtual bool cannot_move() const = 0;
+ virtual bool cannot_act() const = 0;
virtual bool confused() const = 0;
virtual bool caught() const = 0;
virtual bool asleep() const { return (false); }
@@ -1034,6 +1037,7 @@ public:
std::string conj_verb(const std::string &verb) const;
std::string hand_name(bool plural, bool *can_plural = NULL) const;
std::string foot_name(bool plural, bool *can_plural = NULL) const;
+ std::string arm_name(bool plural, bool *can_plural = NULL) const;
bool fumbles_attack(bool verbose = true);
bool cannot_fight() const;
@@ -1094,6 +1098,7 @@ public:
bool paralysed() const;
bool cannot_move() const;
+ bool cannot_act() const;
bool confused() const;
bool caught() const;
bool backlit(bool check_haloed = true) const;
@@ -1104,8 +1109,6 @@ public:
void awake();
void check_awaken(int disturbance);
- bool cannot_act() const;
-
bool can_throw_large_rocks() const;
int armour_class() const;
@@ -1426,6 +1429,7 @@ public:
std::string conj_verb(const std::string &verb) const;
std::string hand_name(bool plural, bool *can_plural = NULL) const;
std::string foot_name(bool plural, bool *can_plural = NULL) const;
+ std::string arm_name(bool plural, bool *can_plural = NULL) const;
bool fumbles_attack(bool verbose = true);
bool cannot_fight() const;
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 6e3aad8da5..e90a4d7809 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -5233,6 +5233,36 @@ std::string monsters::foot_name(bool plural, bool *can_plural) const
return (str);
}
+std::string monsters::arm_name(bool plural, bool *can_plural) const
+{
+ mon_body_shape shape = get_mon_shape(this);
+
+ if (shape > MON_SHAPE_NAGA)
+ return hand_name(plural, can_plural);
+
+ if (can_plural != NULL)
+ *can_plural = true;
+
+ std::string str;
+ switch(mons_genus(type))
+ {
+ case MONS_NAGA:
+ case MONS_DRACONIAN: str = "scaled arm"; break;
+
+ case MONS_MUMMY: str = "bandaged wrapped arm"; break;
+
+ case MONS_SKELETAL_WARRIOR:
+ case MONS_LICH: str = "bony arm"; break;
+
+ default: str = "arm"; break;
+ }
+
+ if (plural)
+ str = pluralise(str);
+
+ return (str);
+}
+
int monsters::id() const
{
return (type);
@@ -7903,6 +7933,49 @@ std::string do_mon_str_replacements(const std::string &in_msg,
msg = replace_all(msg, "@possessive@",
monster->pronoun(PRONOUN_NOCAP_POSSESSIVE));
+ // Body parts.
+ bool can_plural = false;
+ std::string part_str = monster->hand_name(false, &can_plural);
+
+ msg = replace_all(msg, "@hand@", part_str);
+ msg = replace_all(msg, "@Hand@", upcase_first(part_str));
+
+ if (!can_plural)
+ part_str = "NO PLURAL HANDS";
+ else
+ part_str = monster->hand_name(true);
+
+ msg = replace_all(msg, "@hands@", part_str);
+ msg = replace_all(msg, "@Hands@", upcase_first(part_str));
+
+ can_plural = false;
+ part_str = monster->arm_name(false, &can_plural);
+
+ msg = replace_all(msg, "@arm@", part_str);
+ msg = replace_all(msg, "@Arm@", upcase_first(part_str));
+
+ if (!can_plural)
+ part_str = "NO PLURAL ARMS";
+ else
+ part_str = monster->arm_name(true);
+
+ msg = replace_all(msg, "@arms@", part_str);
+ msg = replace_all(msg, "@Arms@", upcase_first(part_str));
+
+ can_plural = false;
+ part_str = monster->foot_name(false, &can_plural);
+
+ msg = replace_all(msg, "@foot@", part_str);
+ msg = replace_all(msg, "@Foot@", upcase_first(part_str));
+
+ if (!can_plural)
+ part_str = "NO PLURAL FOOT";
+ else
+ part_str = monster->foot_name(true);
+
+ msg = replace_all(msg, "@feet@", part_str);
+ msg = replace_all(msg, "@Feet@", upcase_first(part_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));
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index ca82b57e37..ecdfc8e4ca 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -549,24 +549,26 @@ void mons_cast_noise(monsters *monster, bolt &pbolt, spell_type spell_cast)
// Draining breath is silent.
force_silent = true;
- const bool unseen = !you.can_see(monster);
- const bool silent = silenced(monster->pos()) || force_silent;
+ const bool unseen = !you.can_see(monster);
+ const bool silent = silenced(monster->pos()) || force_silent;
+ const bool no_silent = mons_class_flag(monster->type, M_SPELL_NO_SILENT);
- if (unseen && silent)
+ if (unseen && silent || silent && no_silent)
return;
const unsigned int flags = get_spell_flags(real_spell);
const bool priest = mons_class_flag(monster->type, M_PRIEST);
const bool wizard = mons_class_flag(monster->type, M_ACTUAL_SPELLS);
- const bool innate = !(priest || wizard) || (flags & SPFLAG_INNATE);
+ const bool innate = !(priest || wizard || no_silent)
+ || (flags & SPFLAG_INNATE);
int noise;
if(silent
|| (innate
- && !mons_class_flag(monster->type, M_SPELL_NO_SILENT
- | M_NOISY_SPELLS)
- && !(flags & SPFLAG_NOISY)))
+ && !mons_class_flag(monster->type, M_NOISY_SPELLS)
+ && !(flags & SPFLAG_NOISY)
+ && mons_genus(monster->type) != MONS_DRAGON))
{
noise = 0;
}
@@ -579,78 +581,101 @@ void mons_cast_noise(monsters *monster, bolt &pbolt, spell_type spell_cast)
}
const std::string cast_str = " cast";
- std::string suffix;
- if (silent)
- suffix = " silent";
- else if (unseen)
- suffix = " unseen";
-
- std::string key;
- // First try the individual spell.
- key = spell_title(real_spell) + cast_str;
- std::string msg = getSpeakString(key + suffix);
+ const std::string spell_name = spell_title(real_spell);
+ const mon_body_shape shape = get_mon_shape(monster);
- if (msg.empty() && silent)
- msg = getSpeakString(key);
+ std::vector<std::string> key_list;
- // Second, try the individual monster.
- if (msg.empty())
+ // First try the spells name.
+ if (shape <= MON_SHAPE_NAGA && !innate)
{
- key = mons_type_name(monster->type, DESC_PLAIN);
- key += cast_str;
- msg = getSpeakString(key + suffix);
-
- if (msg.empty() && silent)
- msg = getSpeakString(key);
+ if (priest || wizard)
+ key_list.push_back(spell_name + cast_str + " real");
+ if (mons_intel(monster) >= I_NORMAL)
+ key_list.push_back(spell_name + cast_str + " gestures");
}
+ key_list.push_back(spell_name + cast_str);
- // Third, try generic priest or wizard messages.
- if (msg.empty() && !innate)
- {
- if (priest)
- key = "priest";
- else
- key = "wizard";
+ const unsigned int num_spell_keys = key_list.size();
- key += cast_str;
- msg = getSpeakString(key + suffix);
+ // Next the monster type name, then species name, then genus name.
+ key_list.push_back(mons_type_name(monster->type, DESC_PLAIN) + cast_str);
+ key_list.push_back(mons_type_name(mons_species(monster->type), DESC_PLAIN)
+ + cast_str);
+ key_list.push_back(mons_type_name(mons_genus(monster->type), DESC_PLAIN)
+ + cast_str);
- if (msg.empty() && silent)
- msg = getSpeakString(key);
- }
+ // Last, generic wizard, priest or demon.
+ if (wizard)
+ key_list.push_back("wizard" + cast_str);
+ else if (priest)
+ key_list.push_back("priest" + cast_str);
+ else if (mons_is_demon(monster->type))
+ key_list.push_back("demon" + cast_str);
- // Fourth, try the monster's species.
- if (msg.empty())
+ // For targeted spells, try with the targeted suffix first.
+ if (in_bounds(pbolt.target) && pbolt.target != monster->pos()
+ && (flags & SPFLAG_TARGETING_MASK))
{
- key = mons_type_name(mons_species(monster->type), DESC_PLAIN);
- key += cast_str;
- msg = getSpeakString(key + suffix);
-
- if (msg.empty() && silent)
- msg = getSpeakString(key);
+ for (unsigned int i = key_list.size() - 1; i >= num_spell_keys; i--)
+ {
+ std::string str = key_list[i] + " targeted";
+ key_list.insert(key_list.begin() + i, str);
+ }
}
- // Fifth, try the monster's genus.
- if (msg.empty())
+ std::string prefix;
+ if (silent)
+ prefix = "silent ";
+ else if (unseen)
+ prefix = "unseen ";
+
+ std::string msg;
+ for (unsigned int i = 0; i < key_list.size(); i++)
{
- key = mons_type_name(mons_genus(monster->type), DESC_PLAIN);
- key += cast_str;
- msg = getSpeakString(key + suffix);
+ const std::string key = key_list[i];
- if (msg.empty() && silent)
- msg = getSpeakString(key);
- }
+ msg = getSpeakString(prefix + key);
+ if (msg == "__NONE")
+ {
+ msg = "";
+ break;
+ }
+ else if (msg == "__NEXT")
+ {
+ msg = "";
+ if (i < num_spell_keys)
+ i = num_spell_keys - 1;
+ else if (ends_with(key, " targeted"))
+ i++;
+ continue;
+ }
+ else if (!msg.empty())
+ break;
- // Lastly, maybe it's a demon.
- if (msg.empty() && mons_is_demon(monster->type))
- {
- key = "demon";
- key += cast_str;
- msg = getSpeakString(key + suffix);
+ // If we got no message and we're using the silent prefix, then
+ // try again without the prefix.
+ if (prefix != "silent")
+ continue;
- if (msg.empty() && silent)
- msg = getSpeakString(key);
+ msg = getSpeakString(key);
+ if (msg == "__NONE")
+ {
+ msg = "";
+ break;
+ }
+ else if (msg == "__NEXT")
+ {
+ msg = "";
+ if (i < num_spell_keys)
+ i = num_spell_keys - 1;
+ else if (ends_with(key, " targeted"))
+ i++;
+ continue;
+ }
+ else if (!msg.empty())
+ break;
}
if (msg.empty())
@@ -662,9 +687,17 @@ void mons_cast_noise(monsters *monster, bolt &pbolt, spell_type spell_cast)
return;
}
+ /////////////////////
+ // We have a message.
+ /////////////////////
+
std::string target = "something";
- if (pbolt.target == you.pos())
+ if (!(flags & SPFLAG_TARGETING_MASK) || !in_bounds(pbolt.target))
+ target = "NO TARGET";
+ else if (pbolt.target == you.pos())
target = "you";
+ else if (pbolt.target == monster->pos())
+ target = monster->pronoun(PRONOUN_REFLEXIVE);
else if (see_grid(pbolt.target))
{
int midx = mgrd(pbolt.target);
@@ -684,13 +717,16 @@ void mons_cast_noise(monsters *monster, bolt &pbolt, spell_type spell_cast)
// fired.
std::string beam_name;
if (pbolt.flavour <= BEAM_NONE
- || pbolt.flavour >= NUM_BEAMS
+ || pbolt.flavour > BEAM_LAST_REAL
|| pbolt.name.empty())
{
beam_name = "INVALID BEAM";
}
- else if (pbolt.type == 0 || pbolt.name[0] == '0')
+ else if (pbolt.type == 0 || pbolt.type == ' ' || pbolt.name[0] == '0'
+ || pbolt.is_enchantment())
+ {
beam_name = "INVISIBLE BEAM";
+ }
else
beam_name = pbolt.get_short_name();
@@ -707,16 +743,6 @@ void mons_cast_noise(monsters *monster, bolt &pbolt, spell_type spell_cast)
return;
}
- if (msg.find(" roar") != std::string::npos)
- noise = get_shout_noise_level(S_ROAR);
- else if (msg.find(" breathes") != std::string::npos)
- {
- shout_type type = mons_shouts(monster->type);
- if(type == S_SILENT)
- type = S_ROAR;
- noise = get_shout_noise_level(type);
- }
-
// noisy() returns true if the player heard the noise.
if (noisy(noise, monster->pos()) || !unseen)
mons_speaks_msg(monster, msg, chan);
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 526e6358eb..4fc49dc56a 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6295,6 +6295,29 @@ std::string player::foot_name(bool plural, bool *can_plural) const
return str;
}
+std::string player::arm_name(bool plural, bool *can_plural) const
+{
+ if (transform_changed_physiology())
+ return hand_name(plural, can_plural);
+
+ if (can_plural != NULL)
+ *can_plural = true;
+
+ std::string str = "arm";
+
+ if (player_genus(GENPC_DRACONIAN) || you.species == SP_NAGA)
+ str = "scaled arm";
+ else if (you.species == SP_KENKU)
+ str = "feathered arm";
+ else if (you.species == SP_MUMMY)
+ str = "bandaged wrapped arm";
+
+ if (plural)
+ str = pluralise(str);
+
+ return (str);
+}
+
int player::id() const
{
return (-1);