diff options
author | cjo <cjo@ulyco.com> | 2013-07-18 19:56:49 -0700 |
---|---|---|
committer | Neil Moore <neil@s-z.org> | 2013-08-24 13:47:01 -0400 |
commit | 2774ec9060c4295fa4dd60553dbd72c375f7f0bd (patch) | |
tree | faf33a08e67a02581d98b1fed520cfd344cdc0c8 /crawl-ref | |
parent | 27b40443b5753db20c10c793f161485d1fe422ef (diff) | |
download | crawl-ref-2774ec9060c4295fa4dd60553dbd72c375f7f0bd.tar.gz crawl-ref-2774ec9060c4295fa4dd60553dbd72c375f7f0bd.zip |
Display monster spells and magical abilities with x-v
Decrease the need for spoilers by showing monster spells and magical
abilities when examining a monster with the command x-v. If monsters
have multiple possible spellbooks, all of them are listed.
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/Makefile | 4 | ||||
-rw-r--r-- | crawl-ref/source/describe.cc | 63 | ||||
-rw-r--r-- | crawl-ref/source/describe.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/mon-data.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/mon-spll.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 134 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 17 |
7 files changed, 142 insertions, 87 deletions
diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile index e4b96c548f..7365f0d9aa 100644 --- a/crawl-ref/source/Makefile +++ b/crawl-ref/source/Makefile @@ -1083,8 +1083,8 @@ LIBS += $(CONTRIB_LIBS) $(EXTRA_LIBS) DOC_BASE := ../docs DOC_TEMPLATES := $(DOC_BASE)/template GENERATED_DOCS := $(DOC_BASE)/aptitudes.txt $(DOC_BASE)/FAQ.html $(DOC_BASE)/crawl_manual.txt -GENERATED_HEADERS := art-enum.h config.h #the rest are private -GENERATED_FILES := $(GENERATED_HEADERS) art-data.h mon-mst.h mi-enum.h \ +GENERATED_HEADERS := art-enum.h config.h mon-mst.h #the rest are private +GENERATED_FILES := $(GENERATED_HEADERS) art-data.h mi-enum.h \ $(RLTILES)/dc-unrand.txt build.h compflag.h dat/dlua/tags.lua \ cmd-name.h diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 88e5a7ea65..509bf827b8 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -45,6 +45,7 @@ #include "message.h" #include "mon-chimera.h" #include "mon-stuff.h" +#include "mon-util.h" #include "output.h" #include "player.h" #include "quiver.h" @@ -3261,6 +3262,68 @@ static string _monster_stat_description(const monster_info& mi) else if (mons_class_flag(mi.type, M_SENSE_INVIS)) result << uppercase_first(pronoun) << " can sense the presence of invisible creatures.\n"; + // Show monster spells and spell-like abilities. + if (mons_class_flag(mi.type, M_SPELLCASTER)) + { + monster* mon = monster_at(mi.pos); + const monsterentry *m = get_monster_data(mon->type); + mon_spellbook_type book = (m->sec); + result << uppercase_first(pronoun); + // The combination of M_ACTUAL_SPELLS with MST_NO_SPELLS means multiple spellbooks + if (mons_class_flag(mi.type, M_ACTUAL_SPELLS) && book == MST_NO_SPELLS) + result << " has mastered one of the following spellbooks:\n"; + // cjo: the division here gets really arbitrary. For example, wretched stars + // cast mystic blast, but are not flagged with M_ACTUAL_SPELLS. Possibly + // these should be combined. + else if (mons_class_flag(mi.type, M_ACTUAL_SPELLS) && book != MST_NO_SPELLS) + result << " has mastered the following spells: "; + else if (mons_class_flag(mi.type, M_SPELLCASTER) && book != MST_NO_SPELLS) + result << " possesses the following magical abilities: "; + + vector<mon_spellbook_type> books = _get_spellbook_list(mon); + + // Loop through books and display spells/abilities for each of them + int num_books = books.size(); + for (int i = 0; i < num_books; ++i) + { + // Create spell list containing no duplicate or irrelevant entries + book = books[i]; + vector<spell_type> book_spells; + for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j) + { + const spell_type &spell = mspell_list[book].spells[j]; + bool match = false; + for (unsigned int k = 0; k < book_spells.size(); ++k) + { + if(book_spells[k] == spell) + match = true; + } + if(!match && spell != SPELL_NO_SPELL && spell != SPELL_MELEE + && spell != SPELL_CANTRIP) + { + book_spells.push_back(spell); + } + } + + // Special casing for Ogre Mages (they always get their first spell + // changed to Haste Other). + if (mi.type == MONS_OGRE_MAGE) + book_spells[0] = SPELL_HASTE_OTHER; + + // Display spells for this book + if (num_books > 1) + result << "Book " << i+1 << ": "; + for (unsigned int j = 0; j < book_spells.size(); ++j) + { + const spell_type spell = book_spells[j]; + if(j > 0) + result << ", "; + result << spell_title(spell); + } + result << "\n"; + } + } // end if(mons_class_flag(mi.type, M_SPELLCASTER)) + // Unusual monster speed. const int speed = mi.base_speed(); if (speed != 10 && speed != 0) diff --git a/crawl-ref/source/describe.h b/crawl-ref/source/describe.h index 7f6b42c26c..c24127605d 100644 --- a/crawl-ref/source/describe.h +++ b/crawl-ref/source/describe.h @@ -10,6 +10,7 @@ #include <sstream> #include "externs.h" #include "enum.h" +#include "mon-util.h" struct monster_info; diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index bc49c2d30d..054a57f454 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -67,6 +67,11 @@ 105 < hp < 165 hp will be around 135 each time. + sec: if the monster has only one possible spellbook, sec is set to that book. + If a monster has multiple possible books, sec is set to MST_NO_SPELLS. Then + the function _get_spellbook_list in mon-util.cc checks for the flag + M_SPELLCASTER, and handles the books. + corpse_thingy - err, bad name. Describes effects of eating corpses. CE_NOCORPSE, leaves no corpse (mass == 0) diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h index 135edf2c25..54c0681c98 100644 --- a/crawl-ref/source/mon-spll.h +++ b/crawl-ref/source/mon-spll.h @@ -4,9 +4,13 @@ /* ********************************************************************* + This file determines which spells are contained in monster spellbooks. + It is used by /util/gen-mst.pl to generate spellbook enums, which are + listed in mon-mst.h. Template Format: + { mon_spellbook_type type { bolt spell, enchantment, @@ -15,6 +19,7 @@ misc(2) spell, // SPELL_DIG must be here to work! emergency spell // only when fleeing } + } ********************************************************************* */ diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 1c8dad2138..4501fa8cb9 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -77,19 +77,6 @@ static bool initialised_randmons = false; static vector<monster_type> monsters_by_habitat[NUM_HABITATS]; static vector<monster_type> species_by_habitat[NUM_HABITATS]; -#include "mon-mst.h" - -struct mon_spellbook -{ - mon_spellbook_type type; - spell_type spells[NUM_MONSTER_SPELL_SLOTS]; -}; - -static const mon_spellbook mspell_list[] = -{ -#include "mon-spll.h" -}; - #include "mon-data.h" #define MONDATASIZE ARRAYSZ(mondata) @@ -2097,103 +2084,98 @@ monster_type random_draconian_monster_species() // contains the unholy and chaotic Banishment spell, but the other // MST_WIZARD-type spellbooks contain no unholy, evil, unclean or // chaotic spells. -static bool _get_spellbook_list(mon_spellbook_type book[6], - monster* mon) +// +// If a monster has only one spellbook, it is specified in mon-data.h. +// If it has multiple books, mon-data.h sets the book to MST_NO_SPELLS, +// and the books are accounted for here. +vector<mon_spellbook_type> _get_spellbook_list(monster* mon) { - bool retval = true; - int mon_type = mon->type; - - book[0] = MST_NO_SPELLS; - book[1] = MST_NO_SPELLS; - book[2] = MST_NO_SPELLS; - book[3] = MST_NO_SPELLS; - book[4] = MST_NO_SPELLS; - book[5] = MST_NO_SPELLS; + vector<mon_spellbook_type> books; + const monsterentry *m = get_monster_data(mon->type); + mon_spellbook_type book = (m->sec); + int mon_type = mon->type; switch (mon_type) { case MONS_HELL_KNIGHT: - book[0] = MST_HELL_KNIGHT_I; - book[1] = MST_HELL_KNIGHT_II; + books.push_back(MST_HELL_KNIGHT_I); + books.push_back(MST_HELL_KNIGHT_II); break; case MONS_LICH: case MONS_ANCIENT_LICH: - book[0] = MST_LICH_I; - book[1] = MST_LICH_II; - book[2] = MST_LICH_III; - book[3] = MST_LICH_IV; + books.push_back(MST_LICH_I); + books.push_back(MST_LICH_II); + books.push_back(MST_LICH_III); + books.push_back(MST_LICH_IV); break; case MONS_NECROMANCER: - book[0] = MST_NECROMANCER_I; - book[1] = MST_NECROMANCER_II; + books.push_back(MST_NECROMANCER_I); + books.push_back(MST_NECROMANCER_II); break; case MONS_ORC_WIZARD: + case MONS_DEEP_ELF_SOLDIER: case MONS_DEEP_ELF_FIGHTER: case MONS_DEEP_ELF_KNIGHT: - book[0] = MST_ORC_WIZARD_I; - book[1] = MST_ORC_WIZARD_II; - book[2] = MST_ORC_WIZARD_III; + books.push_back(MST_ORC_WIZARD_I); + books.push_back(MST_ORC_WIZARD_II); + books.push_back(MST_ORC_WIZARD_III); break; case MONS_WIZARD: case MONS_OGRE_MAGE: case MONS_EROLCHA: - book[0] = MST_WIZARD_I; - book[1] = MST_WIZARD_II; - book[2] = MST_WIZARD_III; - book[3] = MST_WIZARD_IV; - book[4] = MST_WIZARD_V; + case MONS_DEEP_ELF_MAGE: + books.push_back(MST_WIZARD_I); + books.push_back(MST_WIZARD_II); + books.push_back(MST_WIZARD_III); + books.push_back(MST_WIZARD_IV); + books.push_back(MST_WIZARD_V); break; case MONS_DRACONIAN_KNIGHT: - book[0] = MST_DEEP_ELF_CONJURER; - book[1] = MST_HELL_KNIGHT_I; - book[2] = MST_HELL_KNIGHT_II; - book[3] = MST_NECROMANCER_I; - book[4] = MST_NECROMANCER_II; + books.push_back(MST_DEEP_ELF_CONJURER); + books.push_back(MST_HELL_KNIGHT_I); + books.push_back(MST_HELL_KNIGHT_II); + books.push_back(MST_NECROMANCER_I); + books.push_back(MST_NECROMANCER_II); break; case MONS_ANCIENT_CHAMPION: - book[0] = MST_ANCIENT_CHAMPION_I; - book[1] = MST_ANCIENT_CHAMPION_II; - book[2] = MST_ANCIENT_CHAMPION_III; - book[3] = MST_ANCIENT_CHAMPION_IV; + books.push_back(MST_ANCIENT_CHAMPION_I); + books.push_back(MST_ANCIENT_CHAMPION_II); + books.push_back(MST_ANCIENT_CHAMPION_III); + books.push_back(MST_ANCIENT_CHAMPION_IV); break; case MONS_TENGU_CONJURER: - book[0] = MST_TENGU_CONJURER_I; - book[1] = MST_TENGU_CONJURER_II; - book[2] = MST_TENGU_CONJURER_III; - book[3] = MST_TENGU_CONJURER_IV; + books.push_back(MST_TENGU_CONJURER_I); + books.push_back(MST_TENGU_CONJURER_II); + books.push_back(MST_TENGU_CONJURER_III); + books.push_back(MST_TENGU_CONJURER_IV); break; case MONS_TENGU_REAVER: - book[0] = MST_TENGU_REAVER_I; - book[1] = MST_TENGU_REAVER_II; - book[2] = MST_TENGU_REAVER_III; - break; - - case MONS_DEEP_ELF_MAGE: - book[0] = MST_DEEP_ELF_MAGE_I; - book[1] = MST_DEEP_ELF_MAGE_II; - book[2] = MST_DEEP_ELF_MAGE_III; - book[3] = MST_DEEP_ELF_MAGE_IV; - book[4] = MST_DEEP_ELF_MAGE_V; + books.push_back(MST_TENGU_REAVER_I); + books.push_back(MST_TENGU_REAVER_II); + books.push_back(MST_TENGU_REAVER_III); break; default: - retval = false; + books.push_back(book); break; } - return retval; + return books; } -static void _mons_load_spells(monster* mon, mon_spellbook_type book) +static void _mons_load_spells(monster* mon) { + vector<mon_spellbook_type> books = _get_spellbook_list(mon); + mon_spellbook_type book = books[random2(books.size())]; + if (book == MST_GHOST) return mon->load_ghost_spells(); @@ -2213,22 +2195,6 @@ static void _mons_load_spells(monster* mon, mon_spellbook_type book) break; } } -} - -static void _get_spells(mon_spellbook_type book, monster* mon) -{ - if (book == MST_NO_SPELLS && mons_class_flag(mon->type, M_SPELLCASTER)) - { - mon_spellbook_type multi_book[6]; - if (_get_spellbook_list(multi_book, mon)) - { - do - book = multi_book[random2(6)]; - while (book == MST_NO_SPELLS); - } - } - - _mons_load_spells(mon, book); // (Dumb) special casing to give ogre mages Haste Other. -cao if (mon->type == MONS_OGRE_MAGE) @@ -2442,7 +2408,7 @@ void define_monster(monster* mons) mons->bind_melee_flags(); - _get_spells((mon_spellbook_type)m->sec, mons); + _mons_load_spells(mons); mons->bind_spell_flags(); // Reset monster enchantments. diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 020b7cfa2f..d9733833a9 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -11,6 +11,7 @@ #include "enum.h" #include "mon-enum.h" #include "player.h" +#include "mon-mst.h" struct bolt; @@ -96,6 +97,20 @@ private: } }; +vector<mon_spellbook_type> _get_spellbook_list(monster* mon); + +struct mon_spellbook +{ + mon_spellbook_type type; + spell_type spells[NUM_MONSTER_SPELL_SLOTS]; +}; + +static const mon_spellbook mspell_list[] = +{ +#include "mon-spll.h" +}; + + struct monsterentry { short mc; // monster number @@ -134,7 +149,7 @@ struct monsterentry int8_t AC; // armour class int8_t ev; // evasion - int sec; // spellbook + mon_spellbook_type sec; corpse_effect_type corpse_thingy; zombie_size_type zombie_size; shout_type shouts; |