summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mon-util.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-24 09:35:03 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-24 09:35:03 +0000
commit904a64bbcff41f7ecde8de133ddf68eeb2a8959f (patch)
tree0ed2875917488e791faadd9d7fb629d62b8594ee /crawl-ref/source/mon-util.cc
parent49271d835b9ebb39bcfdae8acbc644aeff6f2f3c (diff)
downloadcrawl-ref-904a64bbcff41f7ecde8de133ddf68eeb2a8959f.tar.gz
crawl-ref-904a64bbcff41f7ecde8de133ddf68eeb2a8959f.zip
* Add a wizard function apply_monster_blessing to allow for easy testing
of dolorous' fabulous blessing routines. * Allow the possibility of naming monsters: A monster's random name seed is stored in its number property, and the actual name gets picked from randname.txt. (Once this leaves the experimental stage I'll move them into a file of their own.) This means that monster types that already use number for something else (hydras for #heads, manticores for #spikes, or zombies for monster type) cannot be named. Use the new functions for naming orcs blessed by Beogh. Only non-generic orcs may get named, e.g. orcs promoted to priesthood or orc warriors that get their weapon enchanted. I tried to come up with a number of thematic orcish names, and if anyone would like to contribute, they're welcome to do so. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4586 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/mon-util.cc')
-rw-r--r--crawl-ref/source/mon-util.cc195
1 files changed, 155 insertions, 40 deletions
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index bc56df06f6..c6314be4f2 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -1651,7 +1651,7 @@ static std::string _str_monam(const monsters& mon, description_level_type desc,
switch (mon.type)
{
case MONS_SPECTRAL_THING:
- result += "spectral ";
+ result += "spectral ";
nametype = mon.number;
break;
@@ -1725,16 +1725,107 @@ std::string mons_type_name(int type, description_level_type desc )
result += get_monster_data(type)->name;
// Vowel fix: Change 'a orc' to 'an orc'
- if ( result.length() >= 3 &&
- (result[0] == 'a' || result[0] == 'A') &&
- result[1] == ' ' &&
- is_vowel(result[2]) )
+ if ( result.length() >= 3
+ && (result[0] == 'a' || result[0] == 'A')
+ && result[1] == ' '
+ && is_vowel(result[2]) )
{
result.insert(1, "n");
}
return result;
}
+// Fills the number parameter (if not otherwise needed) with a seed for
+// random name choice from randname.txt.
+bool give_unique_monster_name(monsters *mon, bool higher_orcs_only)
+{
+ // already have a name
+ if (mons_is_unique(mon->type) || mon->type == MONS_PLAYER_GHOST
+ || mon->type == MONS_PANDEMONIUM_DEMON)
+ {
+ return false;
+ }
+
+ // need their number parameter for other information
+ if (mon->type == MONS_HYDRA // #heads
+ || mon->type == MONS_ABOMINATION_SMALL // colour
+ || mon->type == MONS_ABOMINATION_LARGE // colour
+ || mon->type == MONS_MANTICORE // #spikes
+ || mons_genus(mon->type) == MONS_DRACONIAN // subspecies
+ || mons_class_is_zombified(mon->type)) // zombie type
+ {
+ return false;
+ }
+
+ // Since this is called from the various divine blessing routines,
+ // don't bless non-orcs, and don't bless plain orcs, either.
+ if (higher_orcs_only
+ && (mons_species(mon->type) != MONS_ORC || mon->type == MONS_ORC))
+ {
+ return false;
+ }
+
+ // already has a unique name
+ if (mon->number > 0 && mon->number != MONS_PROGRAM_BUG)
+ return false;
+
+ // randomly pick a number
+ // XXX: Why does unsigned int (number's type) get munged on save & reload?
+ mon->number = (unsigned char) random_int();
+// mprf(MSGCH_DIAGNOSTICS, "new monster number is %d", mon->number);
+
+ return (mon->number != 0 && mon->number != MONS_PROGRAM_BUG);
+}
+
+std::string get_unique_monster_name(const monsters *mon)
+{
+ if (mons_is_unique(mon->type))
+ return get_monster_data(mon->type)->name;
+
+ if (mon->type == MONS_PLAYER_GHOST)
+ return mon->ghost->name + "'s ghost";
+
+ if (mon->type == MONS_PANDEMONIUM_DEMON)
+ return mon->ghost->name;
+
+ // Since the seed for the monster name is stored in mon->number
+ // any monster that uses number for something else cannot be named.
+ if (mon->type == MONS_HYDRA // #heads
+ || mon->type == MONS_ABOMINATION_SMALL // colour
+ || mon->type == MONS_ABOMINATION_LARGE // colour
+ || mon->type == MONS_MANTICORE // #spikes
+ || mons_genus(mon->type) == MONS_DRACONIAN // subspecies
+ || mons_class_is_zombified(mon->type)) // zombie type
+ {
+ return "";
+ }
+
+ // unnamed, sorry
+ if (mon->number <= 0 || mon->number == MONS_PROGRAM_BUG)
+ return "";
+
+// mprf(MSGCH_DIAGNOSTICS, "get name from number %d", mon->number);
+
+ rng_save_excursion rng_state;
+ seed_rng( mon->number );
+
+ std::string name
+ = getRandNameString(get_monster_data(mon->type)->name, " name");
+
+ if (!name.empty())
+ return name;
+
+ name = getRandNameString(get_monster_data(mons_genus(mon->type))->name,
+ " name");
+
+ if (!name.empty())
+ return name;
+
+ name = getRandNameString("generic_monster_name");
+
+ return name;
+}
+
/* ********************* END PUBLIC FUNCTIONS ********************* */
// see mons_init for initialization of mon_entry array.
@@ -2921,8 +3012,10 @@ void monsters::equip_weapon(item_def &item, int near)
void monsters::equip_armour(item_def &item, int near)
{
if (need_message(near))
+ {
mprf("%s wears %s.", name(DESC_CAP_THE).c_str(),
item.name(DESC_NOCAP_A).c_str());
+ }
const equipment_type eq = get_armour_slot(item);
if (eq != EQ_SHIELD)
@@ -2959,9 +3052,11 @@ void monsters::equip(item_def &item, int slot, int near)
void monsters::unequip_weapon(item_def &item, int near)
{
if (need_message(near))
+ {
mprf("%s unwields %s.", name(DESC_CAP_THE).c_str(),
item.name(DESC_NOCAP_A, false, false, true,
false, ISFLAG_CURSED).c_str());
+ }
const int brand = get_weapon_brand(item);
if (brand == SPWPN_PROTECTION)
@@ -3003,8 +3098,10 @@ void monsters::unequip_weapon(item_def &item, int near)
void monsters::unequip_armour(item_def &item, int near)
{
if (need_message(near))
+ {
mprf("%s takes off %s.", name(DESC_CAP_THE).c_str(),
item.name(DESC_NOCAP_A).c_str());
+ }
const equipment_type eq = get_armour_slot(item);
if (eq != EQ_SHIELD)
@@ -3483,8 +3580,10 @@ bool monsters::eat_corpse(item_def &carrion, int near)
max_hit_points = hit_points;
if (need_message(near))
+ {
mprf("%s eats %s.", name(DESC_CAP_THE).c_str(),
carrion.name(DESC_NOCAP_THE).c_str());
+ }
destroy_item( carrion.index() );
return (true);
@@ -3622,6 +3721,10 @@ item_def *monsters::shield()
std::string monsters::name(description_level_type desc) const
{
+ std::string monnam = get_unique_monster_name(this);
+ if (!monnam.empty())
+ return monnam;
+
return this->name(desc, false);
}
@@ -4009,37 +4112,39 @@ void monsters::set_ghost(const ghost_demon &g)
void monsters::pandemon_init()
{
- hit_dice = ghost->xl;
- hit_points = ghost->max_hp;
- max_hit_points = ghost->max_hp;
- ac = ghost->ac;
- ev = ghost->ev;
- speed = (one_chance_in(3) ? 10 : 8 + roll_dice(2, 9));
+ hit_dice = ghost->xl;
+ hit_points = ghost->max_hp;
+ max_hit_points = ghost->max_hp;
+ ac = ghost->ac;
+ ev = ghost->ev;
+ speed = (one_chance_in(3) ? 10 : 8 + roll_dice(2, 9));
speed_increment = 70;
+
if (you.char_direction == GDT_ASCENDING && you.level_type == LEVEL_DUNGEON)
colour = LIGHTRED;
else
colour = random_colour(); // demon's colour
+
load_spells(MST_GHOST);
}
void monsters::ghost_init()
{
- type = MONS_PLAYER_GHOST;
- hit_dice = ghost->xl;
- hit_points = ghost->max_hp;
- max_hit_points = ghost->max_hp;
- ac = ghost->ac;
- ev = ghost->ev;
- speed = ghost->speed;
+ type = MONS_PLAYER_GHOST;
+ hit_dice = ghost->xl;
+ hit_points = ghost->max_hp;
+ max_hit_points = ghost->max_hp;
+ ac = ghost->ac;
+ ev = ghost->ev;
+ speed = ghost->speed;
speed_increment = 70;
- attitude = ATT_HOSTILE;
- behaviour = BEH_WANDER;
- flags = 0;
- foe = MHITNOT;
- foe_memory = 0;
- colour = mons_class_colour(MONS_PLAYER_GHOST);
- number = MONS_PROGRAM_BUG;
+ attitude = ATT_HOSTILE;
+ behaviour = BEH_WANDER;
+ flags = 0;
+ foe = MHITNOT;
+ foe_memory = 0;
+ colour = mons_class_colour(MONS_PLAYER_GHOST);
+ number = MONS_PROGRAM_BUG;
load_spells(MST_GHOST);
inv.init(NON_ITEM);
@@ -4152,19 +4257,19 @@ void monsters::reset()
ench_countdown = 0;
inv.init(NON_ITEM);
- flags = 0;
- experience = 0L;
- type = -1;
- hit_points = 0;
- max_hit_points = 0;
- hit_dice = 0;
- ac = 0;
- ev = 0;
+ flags = 0;
+ experience = 0L;
+ type = -1;
+ hit_points = 0;
+ max_hit_points = 0;
+ hit_dice = 0;
+ ac = 0;
+ ev = 0;
speed_increment = 0;
- attitude = ATT_HOSTILE;
- behaviour = BEH_SLEEP;
- foe = MHITNOT;
- number = 0;
+ attitude = ATT_HOSTILE;
+ behaviour = BEH_SLEEP;
+ foe = MHITNOT;
+ number = 0;
if (in_bounds(x, y))
mgrd[x][y] = NON_MONSTER;
@@ -4190,7 +4295,7 @@ void monsters::set_transit(const level_id &dest)
void monsters::load_spells(mon_spellbook_type book)
{
spells.init(SPELL_NO_SPELL);
- if (book == MST_NO_SPELLS || (book == MST_GHOST && !ghost.get()))
+ if (book == MST_NO_SPELLS || book == MST_GHOST && !ghost.get())
return;
#if DEBUG_DIAGNOSTICS
@@ -5483,9 +5588,11 @@ void monsters::react_to_damage(int damage)
if (spawned == 1)
mprf("%s spits out another jelly.", mname.c_str());
else
+ {
mprf("%s spits out %s more jellies.",
mname.c_str(),
number_in_words(spawned).c_str());
+ }
}
}
}
@@ -5744,8 +5851,16 @@ std::string do_mon_str_replacements(const std::string &in_msg,
std::string msg = in_msg;
description_level_type nocap, cap;
- if (monster->attitude == ATT_FRIENDLY && !mons_is_unique(monster->type)
- && player_monster_visible(monster))
+ std::string name = get_unique_monster_name(monster);
+ if (!name.empty() && player_monster_visible(monster))
+ {
+ msg = replace_all(msg, "@the_something@", name);
+ msg = replace_all(msg, "@The_something@", name);
+ msg = replace_all(msg, "@the_monster@", name);
+ msg = replace_all(msg, "@The_monster@", name);
+ }
+ else if (monster->attitude == ATT_FRIENDLY && !mons_is_unique(monster->type)
+ && player_monster_visible(monster))
{
nocap = DESC_PLAIN;
cap = DESC_PLAIN;