git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6875 c06c8d41-db1a-0410-9941-cceddc491573
3SQQ4MM6YO4I37CQ6GIBIX6BXAEVHNVNHPVMR3PPBBNO454D6XWQC WQSH2ITHKHQAONM55ME7JXLZYL6OQS5F477U66P2R5VHJVI2Q22QC RFXNLDTX4EUIJAHEFKPBPFWDZTYFU5AGGI35EEBCONLBPXL5D5FQC UX6M56N7WTF6B3OTKUFTONBUFZXNEL4SKQT22Q7IVFOBM25LKQ3AC 4EOIRJBTEWVOK4EXA4XAWWS5CHAWZHAYRO6BRZWZ2SU2CGKV6VQAC 5HRXXWHM5JHDZBCSUD65GYSQIFRD77DYV5PDAJZU4JTE4ZPH3LQAC BCL6BB7HZXAJCAGKK6MZ7AGWNLFP46FIXRVGJ6LR3QLDE6XFQGVAC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC Q3B3UVMYEVC4YJUPYVSNTR4DJH4E6J4JJDHZNT5LNOCHCPPMEMXAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC HBXWZNXAJ7LUX7FYUIHQYBTRMWVJC6CAQQL3NNZHK5ETLIFEZJ7QC PBRFKFYILME3A2YLLVGRWJ2C7PCE2GONSINX65P4EG22ZGCW6JWAC 66KRMFZAWM65VI75Z6O4CIVCKB3Z2YQCQSGE44OAP6ESTEFUWYOQC PEZFWKRHDHV4UJTPK5XJZ3CGTZ3LPTDYSPTYBENLQ7VRSP7YFSIQC U6ILMKBXTQZYT62IGD2CALYNU4VQGRSTHN6QBFBU7BVUBHWYOEQQC YP2ADVIVFDLAU4NYFG7BTHV6BMH7VPKUYQ6WVQF3Z725L3DSX7HAC 7G4KWTOOBRLHOZZGFGAXGTUCDF3FGSZOXVHUZZ3V2KVWYSFE7EKAC GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC L57WEZMVIHTFRLWVIPWOIOWHCF2I53TVUVYJ2V6IZ64R56FVTZZAC 4SUUJM2DQUEWHDG3UKJUDZABLHFVF2CFUX5GVAWKT7BBBGR2ISTQC LP5EK64IEM7AHNYQID4GGKOQJQNZLKY4DCCZN47SIUZ6IXAXH5UAC 5FA5IEAXTMXYS2VUBVDKBKHPKAIOY4GN5SXYJORBYWQIGHVW3FFQC ND3T5LCZATC63EVQ6SLI7XXMSUL7XICJDNLH3UCYUDEFWTA3N5MQC CSRWDG2SUGS4YR4PAFI574EGEXW65P6JDT4ZHWDICS2G2GZIGEUQC D7EPLNYHJH6C4CTMHCOUUODKGHCJRE4CGKNVSCHCSABN6ZOD2ZBAC YMC3RKF4Z7DOHZNGG7INC343SXCTWOPK7ISD42I3WA3AZZNVBGIAC J3M6J3UPL4AUJDXINY7UKH2JZQVQLKGH7AMOKI6L3QI7Y2F33O5QC 33QMQXTWFPR4LUBHEWTFGR74L5QJJDQTT5JZRBFTPDQBPXIHQIUQC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC C4WXQRJTDW53PYFWQ4LOINSCI2IWMIQTH5WDSI7QUP72PKDBYHZAC 5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC T7CUIVICB74342RA32BR37T36FOX4RBSQIB5PNOHTGTGUYGDKSTQC PSCYVKJ7DGXAL3V5U4O6AJTRV6Q3N3SHQWAZ73VIPRTE4W64F2XAC 7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC 7HA2754QW3SBCAJ5K6KUXNXXXIZB5BIBCFPLXADCXHH6EREKXHSAC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC IE3INS4WUXZOBVXB5VWRBYPVPXADD2U2W5H3TBTOYNWJ3EGRSGQQC JCWJWGMQIKQGSSFJUQRKNIWW3HBOJSHYDTOPPE5BWOJTIJTDYUTAC 6L4EP4ZRWWYLT55PD5KTTJON5J2JB5VV5MWNHF5VPZQZ5BKEYZ4QC I2G7DP3TJL4RDMYKNXAA67P3VRSO3RF7FHZWA5CYINSEWEQE2YSQC // init ghost tilevoid TileGhostInit(const struct ghost_demon &gs);// init pandem demon tile (only in iso mode)void TilePandemInit(struct ghost_demon &gs);// edit pandem tile (debug)void TileEditPandem();
// monster+weapon tilevoid tile_mcache_unlock();int get_base_idx_from_mcache(int tile_idx);void tile_get_monster_weapon_offset(int mon_tile, int &ofs_x, int &ofs_y);bool get_mcache_entry(int tile_idx, int &mon_idx, int &equ_tile, int &draco);
}bool DungeonRegion::draw_objects(unsigned int fg, unsigned int x, unsigned int y){unsigned int fg_idx = fg & TILE_FLAG_MASK;// handled elsewhereif (fg_idx == TILE_PLAYER)return false;int equ_tile;int draco;int mon_tile;if (get_mcache_entry(fg_idx, mon_tile, equ_tile, draco)){if (!draco)add_quad(TEX_DEFAULT, get_base_idx_from_mcache(fg_idx), x, y);return true;}else if (fg_idx){add_quad(TEX_DEFAULT, fg_idx, x, y);}return false;
int armour = 0;int armour2 = 0;int weapon = 0;int weapon2 = 0;int arm = 0;for (int i = 0; i < TILEP_PART_MAX; i++)doll.parts[i] = 0;
const dolls_data *doll = entry->doll();if (doll)draw_doll(*doll, x, y);
doll.parts[TILEP_PART_SHADOW] = TILEP_SHADOW_SHADOW;doll.parts[TILEP_PART_BASE] = TILEP_BASE_DRACONIAN + colour * 2;doll.parts[TILEP_PART_DRCWING] = tile_player_part_start[TILEP_PART_DRCWING]+ colour;doll.parts[TILEP_PART_DRCHEAD] = tile_player_part_start[TILEP_PART_DRCHEAD]+ colour;
tile_draw_info dinfo[3];unsigned int draw_info_count = entry->info(&dinfo[0]);ASSERT(draw_info_count <= sizeof(dinfo) / (sizeof(dinfo[0])));
switch (mon_idx){case MONS_DRACONIAN_CALLER:weapon = TILEP_HAND1_STAFF_EVIL;weapon2 = TILEP_HAND2_BOOK_YELLOW;armour = TILEP_BODY_ROBE_BROWN;break;case MONS_DRACONIAN_MONK:arm = TILEP_ARM_GLOVE_SHORT_BLUE;armour = TILEP_BODY_KARATE2;break;case MONS_DRACONIAN_ZEALOT:weapon = TILEP_HAND1_MACE;weapon2 = TILEP_HAND2_BOOK_CYAN;armour = TILEP_BODY_MONK_BLUE;break;case MONS_DRACONIAN_SHIFTER:weapon = TILEP_HAND1_STAFF_LARGE;armour = TILEP_BODY_ROBE_CYAN;weapon2 = TILEP_HAND2_BOOK_GREEN;break;case MONS_DRACONIAN_ANNIHILATOR:weapon = TILEP_HAND1_STAFF_RUBY;weapon2 = TILEP_HAND2_FIRE_CYAN;armour = TILEP_BODY_ROBE_GREEN_GOLD;break;case MONS_DRACONIAN_KNIGHT:weapon = equ_tile;weapon2 = TILEP_HAND2_SHIELD_KNIGHT_GRAY;armour = TILEP_BODY_BPLATE_METAL1;armour2 = TILEP_LEG_BELT_GRAY;break;case MONS_DRACONIAN_SCORCHER:weapon = TILEP_HAND1_FIRE_RED;weapon2 = TILEP_HAND2_BOOK_RED;armour = TILEP_BODY_ROBE_RED;break;default:weapon = equ_tile;armour = TILEP_BODY_BELT2;armour2 = TILEP_LEG_LOINCLOTH_RED;break;}doll.parts[TILEP_PART_HAND1] = weapon;doll.parts[TILEP_PART_HAND2] = weapon2;doll.parts[TILEP_PART_BODY] = armour;doll.parts[TILEP_PART_LEG] = armour2;doll.parts[TILEP_PART_ARM] = arm;draw_doll(doll, x, y);
for (unsigned int i = 0; i < draw_info_count; i++)add_quad(TEX_DOLL, dinfo[i].idx, x, y, dinfo[i].ofs_x, dinfo[i].ofs_y);
if (fg_idx < TILE_MCACHE_START)return;int equ_tile;int draco;int mon_tile;if (!get_mcache_entry(fg_idx, mon_tile, equ_tile, draco))return;if (draco == 0){int ofs_x, ofs_y;tile_get_monster_weapon_offset(mon_tile, ofs_x, ofs_y);add_quad(TEX_DOLL, equ_tile, x, y, ofs_x, ofs_y, true, TILE_Y);
unsigned int bg_idx = bg & TILE_FLAG_MASK;
// In some cases, overlay a second weapon tile...if (mon_tile == TILE_MONS_DEEP_ELF_BLADEMASTER){int eq2;switch (equ_tile){case TILEP_HAND1_DAGGER:eq2 = TILEP_HAND2_DAGGER;break;case TILEP_HAND1_SABRE:eq2 = TILEP_HAND2_SABRE;break;default:case TILEP_HAND1_SHORT_SWORD_SLANT:eq2 = TILEP_HAND2_SHORT_SWORD_SLANT;break;};add_quad(TEX_DOLL, eq2, x, y, -ofs_x, ofs_y, true, TILE_Y);}}else
if (fg_idx && fg_idx <= TILE_MAIN_MAX)
int colour;switch (draco){default:case MONS_DRACONIAN: colour = 0; break;case MONS_BLACK_DRACONIAN: colour = 1; break;case MONS_YELLOW_DRACONIAN: colour = 2; break;case MONS_GREEN_DRACONIAN: colour = 4; break;case MONS_MOTTLED_DRACONIAN:colour = 5; break;case MONS_PALE_DRACONIAN: colour = 6; break;case MONS_PURPLE_DRACONIAN: colour = 7; break;case MONS_RED_DRACONIAN: colour = 8; break;case MONS_WHITE_DRACONIAN: colour = 9; break;}draw_draco(colour, mon_tile, equ_tile, x, y);
add_quad(TEX_DEFAULT, fg_idx, x, y);
m_textures[TEX_DUNGEON].set_info(TILE_DNGN_MAX, &tile_dngn_info[0]);m_textures[TEX_DOLL].set_info(TILEP_PLAYER_MAX, &tile_player_info[0]);
m_textures[TEX_DUNGEON].set_info(TILE_DNGN_MAX, &tile_dngn_info);m_textures[TEX_DOLL].set_info(TILEP_PLAYER_MAX, &tile_player_info);
struct mcache_entry{int mon_tile;int equ_tile;int draco;};static std::vector<mcache_entry> mcache;int get_base_idx_from_mcache(int tile_idx){int mcache_idx = tile_idx - TILE_MCACHE_START;if (mcache_idx >= 0 && mcache_idx < (int)mcache.size()){return mcache[mcache_idx].mon_tile;}return tile_idx;}bool get_mcache_entry(int tile_idx, int &mon_idx, int &equ_tile, int &draco){int mcache_idx = tile_idx - TILE_MCACHE_START;if (mcache_idx >= 0 && (unsigned int)mcache_idx < mcache.size()){mon_idx = mcache[mcache_idx].mon_tile;equ_tile = mcache[mcache_idx].equ_tile;draco = mcache[mcache_idx].draco;return true;}return false;}static int _mcache_register(int mon_tile, int equ_tile, int draco = 0){mcache_entry entry;entry.mon_tile = mon_tile;entry.equ_tile = equ_tile;entry.draco = draco;mcache.push_back(entry);int idx = TILE_MCACHE_START + mcache.size() - 1;return idx;}
ASSERT(mon_idx != -1);int ch = _tileidx_monster_base(mon_idx, detected);const monsters* mons = &menv[mon_idx];
int ch = _tileidx_monster_base(mons, detected);
case 's': ch = TILE_MONS_WOLF_SPIDER; break;case 'I': ch = TILE_MONS_ICE_BEAST; break;case '8': ch = TILE_MONS_STONE_GOLEM; break;case 'D': ch = TILE_MONS_DRAGON; break;case 'L': ch = TILE_MONS_LICH; break;case '#': ch = TILE_MONS_VAPOUR; break;case 'S': ch = TILE_MONS_LAVA_SNAKE; break;case 'b': ch = TILE_MONS_GIANT_BAT; break;
case 's': ch = TILEP_MONS_WOLF_SPIDER; break;case 'I': ch = TILEP_MONS_ICE_BEAST; break;case '8': ch = TILEP_MONS_STONE_GOLEM; break;case 'D': ch = TILEP_MONS_DRAGON; break;case 'L': ch = TILEP_MONS_LICH; break;case '#': ch = TILEP_MONS_VAPOUR; break;case 'S': ch = TILEP_MONS_LAVA_SNAKE; break;case 'b': ch = TILEP_MONS_GIANT_BAT; break;
int race = draco_subspecies(&menv[idx]);int cls = menv[idx].type;int eq = 0;if (mon_wep != NON_ITEM &&(cls == race || cls == MONS_DRACONIAN_KNIGHT)){eq = tilep_equ_weapon(mitm[mon_wep]);}t = flag | _mcache_register(cls, eq, race);
unsigned int mcache_idx = mcache.register_monster(&menv[idx]);t = flag | (mcache_idx ? mcache_idx : t0);
else if (mon_wep != NON_ITEM){int eq = tilep_equ_weapon(mitm[mon_wep]);switch(t0){// 3D charscase TILE_MONS_VAULT_GUARD:case TILE_MONS_BLORK_THE_ORC:case TILE_MONS_ORC:case TILE_MONS_ORC_KNIGHT:case TILE_MONS_ORC_WARLORD:case TILE_MONS_ORC_WARRIOR:case TILE_MONS_URUG:case TILE_MONS_GOBLIN:case TILE_MONS_IJYB:case TILE_MONS_HOBGOBLIN:case TILE_MONS_GNOLL:case TILE_MONS_BOGGART:case TILE_MONS_KOBOLD:case TILE_MONS_KOBOLD_DEMONOLOGIST:case TILE_MONS_BIG_KOBOLD:case TILE_MONS_DEEP_ELF_FIGHTER:case TILE_MONS_DEEP_ELF_SOLDIER:case TILE_MONS_DEEP_ELF_KNIGHT:case TILE_MONS_DEEP_ELF_BLADEMASTER:case TILE_MONS_DEEP_ELF_MASTER_ARCHER:case TILE_MONS_DEEP_ELF_MAGE:case TILE_MONS_DEEP_ELF_SUMMONER:case TILE_MONS_DEEP_ELF_CONJURER:case TILE_MONS_DEEP_ELF_PRIEST:case TILE_MONS_DEEP_ELF_HIGH_PRIEST:case TILE_MONS_DEEP_ELF_DEMONOLOGIST:case TILE_MONS_DEEP_ELF_ANNIHILATOR:case TILE_MONS_DEEP_ELF_SORCERER:case TILE_MONS_DEEP_ELF_DEATH_MAGE:case TILE_MONS_MIDGE:case TILE_MONS_IMP:case TILE_MONS_NAGA:case TILE_MONS_GREATER_NAGA:case TILE_MONS_NAGA_WARRIOR:case TILE_MONS_NAGA_MAGE:
case TILE_MONS_OGRE_MAGE:case TILE_MONS_RED_DEVIL:case TILE_MONS_WIZARD:case TILE_MONS_HUMAN:case TILE_MONS_ELF:case TILE_MONS_ANGEL:case TILE_MONS_HELL_KNIGHT:case TILE_MONS_NORRIS:case TILE_MONS_MAUD:case TILE_MONS_DUANE:case TILE_MONS_EDMUND:case TILE_MONS_FRANCES:case TILE_MONS_HAROLD:case TILE_MONS_JOSEPH:case TILE_MONS_JOZEF:case TILE_MONS_RUPERT:case TILE_MONS_TERENCE:case TILE_MONS_WAYNE:case TILE_MONS_FREDERICK:case TILE_MONS_RAKSHASA:case TILE_MONS_RAKSHASA_FAKE:case TILE_MONS_VAMPIRE_KNIGHT:case TILE_MONS_SKELETAL_WARRIOR:case TILE_MONS_MERMAID:case TILE_MONS_MERMAID_WATER:case TILE_MONS_MERFOLK_FIGHTER:case TILE_MONS_MERFOLK_FIGHTER_WATER:if (eq != 0 )t = flag | _mcache_register(t0, eq);break;}}
tiles.add_text_tag(TAG_NAMED_MONSTER,menv[idx].name(DESC_CAP_A), gc);
if (menv[idx].type == MONS_PLAYER_GHOST){// Beautification hack. "Foo's ghost" is a little bit// verbose as a tag. "Foo" on its own should be sufficient.tiles.add_text_tag(TAG_NAMED_MONSTER, menv[idx].mname, gc);}else{tiles.add_text_tag(TAG_NAMED_MONSTER,menv[idx].name(DESC_CAP_A), gc);}
/** File: tilemcache.h* Summary: Monster cache support* Written by: Enne Walker*/#ifdef USE_TILE#ifndef TILEMCACHE_H#define TILEMCACHE_H#include "AppHdr.h"#include "debug.h"#include <vector>// The monster cache is designed to hold extra information about monsters that// can't be contained in a single tile. This is usually for equipment,// doll parts, or demon parts.//// Monster cache entries for monsters that are out of sight are ref-counted// that they can be drawn even if that monster no longer exists. When no// out-of-sight tiles refer to them, they can be deleted.class tile_draw_info{public:tile_draw_info() : idx(~0), ofs_x(0), ofs_y(0) {}void set(unsigned int _idx, int _ofs_x = 0, int _ofs_y = 0){ idx = _idx; _ofs_x = ofs_x; _ofs_y = ofs_y; }unsigned int idx;int ofs_x;int ofs_y;};class mcache_entry{public:mcache_entry() : m_ref_count(0) {}virtual ~mcache_entry() {}void inc_ref() { m_ref_count++; }void dec_ref() { m_ref_count--; ASSERT(m_ref_count >= 0); }int ref_count() { return m_ref_count; }virtual unsigned int info(tile_draw_info *dinfo) const { return 0; }virtual const dolls_data *doll() const { return NULL; }virtual void construct(writer &th);protected:mcache_entry(reader &th);// ref count in backstoreint m_ref_count;};class mcache_manager{public:~mcache_manager();unsigned int register_monster(const monsters *mon);mcache_entry *get(unsigned int idx);void clear_nonref();void clear_all();void read(reader &th);void construct(writer &th);protected:std::vector<mcache_entry*> m_entries;};// The global monster cache.extern mcache_manager mcache;#endif#endif
#include "tilemcache.h"#include "tags.h"#include "ghost.h"#include "mon-util.h"mcache_manager mcache;// Used internally for streamingenum mcache_type{MCACHE_MONSTER,MCACHE_DRACO,MCACHE_GHOST,MCACHE_DEMON,MCACHE_MAX,MCACHE_NULL};// Custom marshall/unmarshall functions.static void unmarshallDoll(reader &th, dolls_data &doll){for (unsigned int i = 0; i < TILEP_PART_MAX; i++){doll.parts[i] = unmarshallLong(th);}}static void marshallDoll(writer &th, const dolls_data &doll){for (unsigned int i = 0; i < TILEP_PART_MAX; i++){marshallLong(th, doll.parts[i]);}}static void unmarshallDemon(reader &th, demon_data &demon){demon.head = unmarshallLong(th);demon.body = unmarshallLong(th);demon.wings = unmarshallLong(th);}static void marshallDemon(writer &th, const demon_data &demon){marshallLong(th, demon.head);marshallLong(th, demon.body);marshallLong(th, demon.wings);}// Internal mcache classes. The mcache_manager creates these internally.// The only access external clients need is through the virtual// info function.class mcache_monster : public mcache_entry{public:mcache_monster(const monsters *mon);mcache_monster(reader &th);virtual unsigned int info(tile_draw_info *dinfo) const;static bool valid(const monsters *mon);static bool get_weapon_offset(int mon_tile, int &ofs_x, int &ofs_y);virtual void construct(writer &th);protected:int m_mon_tile;int m_equ_tile;};class mcache_draco : public mcache_entry{public:mcache_draco(const monsters *mon);mcache_draco(reader &th);virtual const dolls_data *doll() const;static bool valid(const monsters *mon);virtual void construct(writer &th);protected:dolls_data m_doll;};class mcache_ghost : public mcache_entry{public:mcache_ghost(const monsters *mon);mcache_ghost(reader &th);virtual const dolls_data *doll() const;static bool valid(const monsters *mon);virtual void construct(writer &th);protected:dolls_data m_doll;};class mcache_demon : public mcache_entry{public:mcache_demon(const monsters *mon);mcache_demon(reader &th);virtual unsigned int info(tile_draw_info *dinfo) const;static bool valid(const monsters *mon);virtual void construct(writer &th);protected:demon_data m_demon;};/////////////////////////////////////////////////////////////////////////////// tile_fg_storeunsigned int tile_fg_store::operator=(unsigned int tile){if (tile & TILE_FLAG_MASK == m_tile & TILE_FLAG_MASK){// update, as flags may have changed.m_tile = tile;return m_tile;}mcache_entry *old_entry = mcache.get(m_tile);if (old_entry)old_entry->dec_ref();m_tile = tile;mcache_entry *new_entry = mcache.get(m_tile);if (new_entry)new_entry->inc_ref();return m_tile;}/////////////////////////////////////////////////////////////////////////////// mcache_managermcache_manager::~mcache_manager(){clear_all();}unsigned int mcache_manager::register_monster(const monsters *mon){assert(mon);if (!mon)return 0;// TODO enne - is it worth it to search against all mcache entries?// TODO enne - pool mcache types to avoid too much alloc/dealloc?mcache_entry *entry;if (mcache_demon::valid(mon)){entry = new mcache_demon(mon);}else if (mcache_ghost::valid(mon)){entry = new mcache_ghost(mon);}else if (mcache_draco::valid(mon)){entry = new mcache_draco(mon);}else if (mcache_monster::valid(mon)){entry = new mcache_monster(mon);}else{return 0;}unsigned int idx = ~0;for (unsigned int i = 0; i < m_entries.size(); i++){if (!m_entries[i]){m_entries[i] = entry;idx = i;break;}}if (idx > m_entries.size()){idx = m_entries.size();m_entries.push_back(entry);}return TILEP_MCACHE_START + idx;}void mcache_manager::clear_nonref(){for (unsigned int i = 0; i < m_entries.size(); i++){if (!m_entries[i] || m_entries[i]->ref_count() > 0)continue;delete m_entries[i];m_entries[i] = NULL;}}void mcache_manager::clear_all(){for (unsigned int i = 0; i < m_entries.size(); i++){delete m_entries[i];}m_entries.resize(0);}mcache_entry *mcache_manager::get(unsigned int tile){unsigned int idx = tile & TILE_FLAG_MASK;if (idx < TILEP_MCACHE_START)return NULL;if (idx >= TILEP_MCACHE_START + m_entries.size())return NULL;mcache_entry *entry = m_entries[idx - TILEP_MCACHE_START];return (entry);}void mcache_manager::read(reader &th){unsigned int size = unmarshallLong(th);m_entries.reserve(size);m_entries.clear();for (unsigned int i = 0; i < size; i++){char type = unmarshallByte(th);mcache_entry *entry;switch (type){case MCACHE_MONSTER:entry = new mcache_monster(th);break;case MCACHE_DRACO:entry = new mcache_draco(th);break;case MCACHE_GHOST:entry = new mcache_ghost(th);break;case MCACHE_DEMON:entry = new mcache_demon(th);break;default:ASSERT(!"Invalid streamed mcache type.");case MCACHE_NULL:entry = NULL;break;}m_entries.push_back(entry);}}void mcache_manager::construct(writer &th){marshallLong(th, m_entries.size());for (unsigned int i = 0; i < m_entries.size(); i++){if (m_entries[i] == NULL){marshallByte(th, MCACHE_NULL);continue;}if (dynamic_cast<mcache_monster*>(m_entries[i]))marshallByte(th, MCACHE_MONSTER);else if (dynamic_cast<mcache_draco*>(m_entries[i]))marshallByte(th, MCACHE_DRACO);else if (dynamic_cast<mcache_ghost*>(m_entries[i]))marshallByte(th, MCACHE_GHOST);else if (dynamic_cast<mcache_demon*>(m_entries[i]))marshallByte(th, MCACHE_DEMON);else{marshallByte(th, MCACHE_NULL);continue;}m_entries[i]->construct(th);}}/////////////////////////////////////////////////////////////////////////////// mcache_entrymcache_entry::mcache_entry(reader &th){m_ref_count = unmarshallLong(th);}void mcache_entry::construct(writer &th){marshallLong(th, m_ref_count);}/////////////////////////////////////////////////////////////////////////////// mcache_monstermcache_monster::mcache_monster(const monsters *mon){assert(mcache_monster::valid(mon));m_mon_tile = tileidx_monster(mon, false) & TILE_FLAG_MASK;int mon_wep = mon->inv[MSLOT_WEAPON];m_equ_tile = tilep_equ_weapon(mitm[mon_wep]);}bool mcache_monster::get_weapon_offset(int mon_tile, int &ofs_x, int &ofs_y){switch (mon_tile){case TILEP_MONS_VAULT_GUARD:case TILEP_MONS_HOBGOBLIN:case TILEP_MONS_DEEP_ELF_MASTER_ARCHER:case TILEP_MONS_IMP:case TILEP_MONS_ANGEL:case TILEP_MONS_NORRIS:case TILEP_MONS_MAUD:case TILEP_MONS_DUANE:case TILEP_MONS_EDMUND:case TILEP_MONS_FRANCES:case TILEP_MONS_HAROLD:case TILEP_MONS_JOSEPH:case TILEP_MONS_JOZEF:case TILEP_MONS_RUPERT:case TILEP_MONS_TERENCE:case TILEP_MONS_WAYNE:case TILEP_MONS_FREDERICK:case TILEP_MONS_RAKSHASA:case TILEP_MONS_RAKSHASA_FAKE:case TILEP_MONS_VAMPIRE_KNIGHT:case TILEP_MONS_SKELETAL_WARRIOR:case TILEP_MONS_MERMAID:case TILEP_MONS_MERMAID_WATER:case TILEP_MONS_MERFOLK_FIGHTER:case TILEP_MONS_MERFOLK_FIGHTER_WATER:ofs_x = 0;ofs_y = 0;break;case TILEP_MONS_ORC:case TILEP_MONS_URUG:case TILEP_MONS_BLORK_THE_ORC:case TILEP_MONS_ORC_WARRIOR:case TILEP_MONS_ORC_KNIGHT:case TILEP_MONS_ORC_WARLORD:ofs_x = 0;ofs_y = 2;break;case TILEP_MONS_GOBLIN:case TILEP_MONS_IJYB:ofs_x = 0;ofs_y = 4;break;case TILEP_MONS_GNOLL:ofs_x = -1;ofs_y = 0;break;case TILEP_MONS_BOGGART:case TILEP_MONS_DEEP_ELF_FIGHTER:case TILEP_MONS_DEEP_ELF_SOLDIER:ofs_x = 0;ofs_y = 2;break;case TILEP_MONS_DEEP_ELF_KNIGHT:ofs_x = 0;ofs_y = 1;break;case TILEP_MONS_KOBOLD:ofs_x = 3;ofs_y = 4;break;case TILEP_MONS_KOBOLD_DEMONOLOGIST:ofs_x = 0;ofs_y = -10;break;case TILEP_MONS_BIG_KOBOLD:ofs_x = 2;ofs_y = 3;break;case TILEP_MONS_MIDGE:ofs_x = 0;ofs_y = -2;break;case TILEP_MONS_NAGA:case TILEP_MONS_GREATER_NAGA:case TILEP_MONS_NAGA_WARRIOR:case TILEP_MONS_GUARDIAN_NAGA:case TILEP_MONS_NAGA_MAGE:ofs_x = 0;ofs_y = 1;break;case TILEP_MONS_HELL_KNIGHT:ofs_x = -1;ofs_y = 3;break;case TILEP_MONS_RED_DEVIL:ofs_x = 2;ofs_y = -3;break;case TILEP_MONS_WIZARD:ofs_x = 2;ofs_y = -2;break;case TILEP_MONS_HUMAN:ofs_x = 5;ofs_y = 2;break;case TILEP_MONS_ELF:ofs_y = 1;ofs_x = 4;break;case TILEP_MONS_OGRE_MAGE:ofs_y = -2;ofs_x = -4;break;case TILEP_MONS_DEEP_ELF_MAGE:case TILEP_MONS_DEEP_ELF_SUMMONER:case TILEP_MONS_DEEP_ELF_CONJURER:case TILEP_MONS_DEEP_ELF_PRIEST:case TILEP_MONS_DEEP_ELF_HIGH_PRIEST:case TILEP_MONS_DEEP_ELF_DEMONOLOGIST:case TILEP_MONS_DEEP_ELF_ANNIHILATOR:case TILEP_MONS_DEEP_ELF_SORCERER:ofs_x = -1;ofs_y = -2;break;case TILEP_MONS_DEEP_ELF_DEATH_MAGE:ofs_x = -1;ofs_y = 0;break;default:// This monster cannot be displayed with a weapon.return false;}return true;}unsigned int mcache_monster::info(tile_draw_info *dinfo) const{int ofs_x, ofs_y;get_weapon_offset(m_mon_tile, ofs_x, ofs_y);dinfo[0].set(m_mon_tile);dinfo[1].set(m_equ_tile, ofs_x, ofs_y);// In some cases, overlay a second weapon tile...if (m_mon_tile == TILEP_MONS_DEEP_ELF_BLADEMASTER){int eq2;switch (m_equ_tile){case TILEP_HAND1_DAGGER:eq2 = TILEP_HAND2_DAGGER;break;case TILEP_HAND1_SABRE:eq2 = TILEP_HAND2_SABRE;break;default:case TILEP_HAND1_SHORT_SWORD_SLANT:eq2 = TILEP_HAND2_SHORT_SWORD_SLANT;break;};dinfo[2].set(eq2, -ofs_x, ofs_y);return 3;}else{return 2;}}bool mcache_monster::valid(const monsters *mon){if (!mon)return false;int mon_wep = mon->inv[MSLOT_WEAPON];if (mon_wep == NON_ITEM)return false;int mon_tile = tileidx_monster(mon, false) & TILE_FLAG_MASK;int ox, oy;return get_weapon_offset(mon_tile, ox, oy);}mcache_monster::mcache_monster(reader &th) : mcache_entry(th){m_mon_tile = unmarshallLong(th);m_equ_tile = unmarshallLong(th);}void mcache_monster::construct(writer &th){mcache_entry::construct(th);marshallLong(th, m_mon_tile);marshallLong(th, m_equ_tile);}/////////////////////////////////////////////////////////////////////////////// mcache_dracomcache_draco::mcache_draco(const monsters *mon){assert(mcache_draco::valid(mon));int draco = draco_subspecies(mon);int colour;switch (draco){default:case MONS_DRACONIAN: colour = 0; break;case MONS_BLACK_DRACONIAN: colour = 1; break;case MONS_YELLOW_DRACONIAN: colour = 2; break;case MONS_GREEN_DRACONIAN: colour = 4; break;case MONS_MOTTLED_DRACONIAN:colour = 5; break;case MONS_PALE_DRACONIAN: colour = 6; break;case MONS_PURPLE_DRACONIAN: colour = 7; break;case MONS_RED_DRACONIAN: colour = 8; break;case MONS_WHITE_DRACONIAN: colour = 9; break;}m_doll.parts[TILEP_PART_SHADOW] = TILEP_SHADOW_SHADOW;m_doll.parts[TILEP_PART_BASE] = TILEP_BASE_DRACONIAN + colour * 2;m_doll.parts[TILEP_PART_DRCWING] =tile_player_part_start[TILEP_PART_DRCWING] + colour;m_doll.parts[TILEP_PART_DRCHEAD] =tile_player_part_start[TILEP_PART_DRCHEAD] + colour;int mon_wep = mon->inv[MSLOT_WEAPON];int equ_tile = (mon_wep != NON_ITEM) ? tilep_equ_weapon(mitm[mon_wep]) : 0;switch (mon->type){case MONS_DRACONIAN_CALLER:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_STAFF_EVIL;m_doll.parts[TILEP_PART_HAND2] = TILEP_HAND2_BOOK_YELLOW;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_ROBE_BROWN;break;case MONS_DRACONIAN_MONK:m_doll.parts[TILEP_PART_ARM] = TILEP_ARM_GLOVE_SHORT_BLUE;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_KARATE2;break;case MONS_DRACONIAN_ZEALOT:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_MACE;m_doll.parts[TILEP_PART_HAND2] = TILEP_HAND2_BOOK_CYAN;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_MONK_BLUE;break;case MONS_DRACONIAN_SHIFTER:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_STAFF_LARGE;m_doll.parts[TILEP_PART_HAND2] = TILEP_HAND2_BOOK_GREEN;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_ROBE_CYAN;break;case MONS_DRACONIAN_ANNIHILATOR:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_STAFF_RUBY;m_doll.parts[TILEP_PART_HAND2] = TILEP_HAND2_FIRE_CYAN;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_ROBE_GREEN_GOLD;break;case MONS_DRACONIAN_KNIGHT:m_doll.parts[TILEP_PART_HAND1] = equ_tile;m_doll.parts[TILEP_PART_HAND2] = TILEP_HAND2_SHIELD_KNIGHT_GRAY;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_BPLATE_METAL1;m_doll.parts[TILEP_PART_LEG] = TILEP_LEG_BELT_GRAY;break;case MONS_DRACONIAN_SCORCHER:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_FIRE_RED;m_doll.parts[TILEP_PART_HAND2] = TILEP_HAND2_BOOK_RED;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_ROBE_RED;break;default:m_doll.parts[TILEP_PART_HAND1] = equ_tile;m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_BELT2;m_doll.parts[TILEP_PART_LEG] = TILEP_LEG_LOINCLOTH_RED;break;}}const dolls_data *mcache_draco::doll() const{return &m_doll;}bool mcache_draco::valid(const monsters *mon){return (mon && mon->type >= MONS_FIRST_DRACONIAN&& mon->type <= MONS_LAST_DRACONIAN);}mcache_draco::mcache_draco(reader &th) : mcache_entry(th){unmarshallDoll(th, m_doll);}void mcache_draco::construct(writer &th){mcache_entry::construct(th);marshallDoll(th, m_doll);}/////////////////////////////////////////////////////////////////////////////// mcache_ghostmcache_ghost::mcache_ghost(const monsters *mon){assert(mcache_ghost::valid(mon));const struct ghost_demon &ghost = *mon->ghost;unsigned int pseudo_rand = ghost.max_hp * 54321 * 54321;int gender = (pseudo_rand >> 8) & 1;tilep_race_default(ghost.species, gender,ghost.xl, m_doll.parts);tilep_job_default(ghost.job, gender, m_doll.parts);for (int p = TILEP_PART_CLOAK; p < TILEP_PART_MAX; p++){if (m_doll.parts[p] == TILEP_SHOW_EQUIP){int part_offset = pseudo_rand % tile_player_part_count[p];m_doll.parts[p] = tile_player_part_start[p] + part_offset;}}int ac = ghost.ac;ac *= (5 + (pseudo_rand / 11) % 11);ac /= 10;if (ac > 25)m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_PLATE_BLACK;else if (ac > 20)m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_BANDED;else if (ac > 15)m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_SCALEMAIL;else if (ac > 10)m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_CHAINMAIL;else if (ac > 5 )m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_LEATHER_HEAVY;elsem_doll.parts[TILEP_PART_BODY]= TILEP_BODY_ROBE_BLUE;int sk = ghost.best_skill;int dam = ghost.damage;dam *= (5 + pseudo_rand % 11);dam /= 10;switch (sk){case SK_MACES_FLAILS:if (dam > 30)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GREAT_FRAIL;else if (dam > 25)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GREAT_MACE;else if (dam > 20)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SPIKED_FRAIL;else if (dam > 15)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_MORNINGSTAR;else if (dam > 10)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_FRAIL;else if (dam > 5)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_MACE;elsem_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_CLUB_SLANT;break;case SK_SHORT_BLADES:if (dam > 20)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SABRE;else if (dam > 10)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SHORT_SWORD_SLANT;elsem_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_DAGGER_SLANT;break;case SK_LONG_BLADES:if (dam > 25)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GREAT_SWORD_SLANT;else if (dam > 20)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_KATANA_SLANT;else if (dam > 15)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SCIMITAR;else if (dam > 10)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_LONG_SWORD_SLANT;elsem_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_FALCHION;break;case SK_AXES:if (dam > 30)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_EXECUTIONERS_AXE;else if (dam > 20)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_BATTLEAXE;else if (dam > 15)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_BROAD_AXE;else if (dam > 10)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_WAR_AXE;elsem_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_HAND_AXE;break;case SK_POLEARMS:if (dam > 30)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GLAIVE;else if (dam > 20)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SCYTHE;else if (dam > 15)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_HALBERD;else if (dam > 10)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_TRIDENT2;else if (dam > 10)m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_HAMMER;elsem_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SPEAR;break;case SK_BOWS:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_BOW2;break;case SK_CROSSBOWS:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_CROSSBOW;break;case SK_SLINGS:m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SLING;break;case SK_UNARMED_COMBAT:default:m_doll.parts[TILEP_PART_HAND1] = m_doll.parts[TILEP_PART_HAND2] = 0;break;}}const dolls_data *mcache_ghost::doll() const{return &m_doll;}bool mcache_ghost::valid(const monsters *mon){return (mon && mon->type == MONS_PLAYER_GHOST);}mcache_ghost::mcache_ghost(reader &th) : mcache_entry(th){unmarshallDoll(th, m_doll);}void mcache_ghost::construct(writer &th){mcache_entry::construct(th);marshallDoll(th, m_doll);}/////////////////////////////////////////////////////////////////////////////// mcache_demonmcache_demon::mcache_demon(const monsters *mon){assert(mcache_demon::valid(mon));const struct ghost_demon &ghost = *mon->ghost;unsigned int pseudo_rand1 = ghost.max_hp * 54321 * 54321;unsigned int pseudo_rand2 = ghost.ac * 54321 * 54321;unsigned int pseudo_rand3 = ghost.ev * 54321 * 54321;int head_offset = pseudo_rand1 % tile_player_count(TILEP_DEMON_HEAD);m_demon.head = TILEP_DEMON_HEAD + head_offset;int body_offset = pseudo_rand2 % tile_player_count(TILEP_DEMON_BODY);m_demon.body = TILEP_DEMON_BODY + body_offset;if (ghost.ev % 2){int wings_offset = pseudo_rand3 % tile_player_count(TILEP_DEMON_WINGS);m_demon.wings = TILEP_DEMON_WINGS + wings_offset;}else{m_demon.wings = 0;}}unsigned int mcache_demon::info(tile_draw_info *dinfo) const{if (m_demon.wings){dinfo[0].set(m_demon.wings);dinfo[1].set(m_demon.body);dinfo[2].set(m_demon.head);return 3;}else{dinfo[0].set(m_demon.body);dinfo[1].set(m_demon.head);return 2;}}bool mcache_demon::valid(const monsters *mon){return (mon && mon->type == MONS_PANDEMONIUM_DEMON);}mcache_demon::mcache_demon(reader &th) : mcache_entry(th){unmarshallDemon(th, m_demon);}void mcache_demon::construct(writer &th){mcache_entry::construct(th);marshallDemon(th, m_demon);}
void TileGhostInit(const struct ghost_demon &ghost){#if 0dolls_data doll;int x, y;unsigned int pseudo_rand = ghost.max_hp * 54321 * 54321;char mask[TILE_X*TILE_Y];int g_gender = (pseudo_rand >> 8) & 1;for (x = 0; x < TILE_X; x++)for (y = 0; y < TILE_X; y++)mask[x + y*TILE_X] = (x+y)&1;
for (x = 0; x < TILEP_PART_MAX; x++){doll.parts[x] = 0;current_parts[x] = 0;}tilep_race_default(ghost.species, g_gender,ghost.xl, doll.parts);tilep_job_default (ghost.job, g_gender, doll.parts);for (x = TILEP_PART_CLOAK; x < TILEP_PART_MAX; x++){if (doll.parts[x] == TILEP_SHOW_EQUIP){doll.parts[x] = 1 + (pseudo_rand % tilep_parts_total[x]);if (x == TILEP_PART_BODY){int p = 0;int ac = ghost.ac;ac *= (5 + (pseudo_rand/11) % 11);ac /= 10;if (ac > 25)p = TILEP_BODY_PLATE_BLACK;else if (ac > 20)p = TILEP_BODY_BANDED;else if (ac > 15)p = TILEP_BODY_SCALEMAIL;else if (ac > 10)p = TILEP_BODY_CHAINMAIL;else if (ac > 5 )p = TILEP_BODY_LEATHER_HEAVY;elsep = TILEP_BODY_ROBE_BLUE;doll.parts[x] = p;}}}int sk = ghost.best_skill;int dam = ghost.damage;int p = 0;dam *= (5 + pseudo_rand % 11);dam /= 10;switch (sk){case SK_MACES_FLAILS:if (dam > 30)p = TILEP_HAND1_GREAT_FRAIL;else if (dam > 25)p = TILEP_HAND1_GREAT_MACE;else if (dam > 20)p = TILEP_HAND1_SPIKED_FRAIL;else if (dam > 15)p = TILEP_HAND1_MORNINGSTAR;else if (dam > 10)p = TILEP_HAND1_FRAIL;else if (dam > 5)p = TILEP_HAND1_MACE;elsep = TILEP_HAND1_CLUB_SLANT;doll.parts[TILEP_PART_HAND1] = p;break;case SK_SHORT_BLADES:if (dam > 20)p = TILEP_HAND1_SABRE;else if (dam > 10)p = TILEP_HAND1_SHORT_SWORD_SLANT;elsep = TILEP_HAND1_DAGGER_SLANT;doll.parts[TILEP_PART_HAND1] = p;break;case SK_LONG_BLADES:if (dam > 25)p = TILEP_HAND1_GREAT_SWORD_SLANT;else if (dam > 20)p = TILEP_HAND1_KATANA_SLANT;else if (dam > 15)p = TILEP_HAND1_SCIMITAR;else if (dam > 10)p = TILEP_HAND1_LONG_SWORD_SLANT;elsep = TILEP_HAND1_FALCHION;doll.parts[TILEP_PART_HAND1] = p;break;case SK_AXES:if (dam > 30)p = TILEP_HAND1_EXECUTIONERS_AXE;else if (dam > 20)p = TILEP_HAND1_BATTLEAXE;else if (dam > 15)p = TILEP_HAND1_BROAD_AXE;else if (dam > 10)p = TILEP_HAND1_WAR_AXE;elsep = TILEP_HAND1_HAND_AXE;doll.parts[TILEP_PART_HAND1] = p;break;case SK_POLEARMS:if (dam > 30)p = TILEP_HAND1_GLAIVE;else if (dam > 20)p = TILEP_HAND1_SCYTHE;else if (dam > 15)p = TILEP_HAND1_HALBERD;else if (dam > 10)p = TILEP_HAND1_TRIDENT2;else if (dam > 10)p = TILEP_HAND1_HAMMER;elsep = TILEP_HAND1_SPEAR;doll.parts[TILEP_PART_HAND1] = p;break;case SK_BOWS:doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_BOW2;break;case SK_CROSSBOWS:doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_CROSSBOW;break;case SK_SLINGS:doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SLING;break;case SK_UNARMED_COMBAT:default:doll.parts[TILEP_PART_HAND1] = doll.parts[TILEP_PART_HAND2] = 0;break;}ImgClear(DollCacheImg);// Clear_ImgCopyToTileImg(TILE_MONS_PLAYER_GHOST, DollCacheImg, 0, 0, 1);_draw_doll(DollCacheImg, &doll);_ImgCopyToTileImg(TILE_MONS_PLAYER_GHOST, DollCacheImg, 0, 0, 1, mask, false);_redraw_spx_tcache(TILE_MONS_PLAYER_GHOST);#endif}void tile_get_monster_weapon_offset(int mon_tile, int &ofs_x, int &ofs_y){ofs_x = 0;ofs_y = 0;switch (mon_tile){case TILE_MONS_ORC:case TILE_MONS_URUG:case TILE_MONS_BLORK_THE_ORC:case TILE_MONS_ORC_WARRIOR:case TILE_MONS_ORC_KNIGHT:case TILE_MONS_ORC_WARLORD:ofs_y = 2;break;case TILE_MONS_GOBLIN:case TILE_MONS_IJYB:ofs_y = 4;break;case TILE_MONS_GNOLL:ofs_x = -1;break;case TILE_MONS_BOGGART:ofs_y = 2;break;case TILE_MONS_DEEP_ELF_FIGHTER:case TILE_MONS_DEEP_ELF_SOLDIER:ofs_y = 2;break;case TILE_MONS_DEEP_ELF_KNIGHT:ofs_y = 1;break;case TILE_MONS_KOBOLD:ofs_x = 3;ofs_y = 4;break;case TILE_MONS_KOBOLD_DEMONOLOGIST:ofs_y = -10;break;case TILE_MONS_BIG_KOBOLD:ofs_x = 2;ofs_y = 3;break;case TILE_MONS_MIDGE:ofs_y = -2;break;case TILE_MONS_NAGA:case TILE_MONS_GREATER_NAGA:case TILE_MONS_NAGA_WARRIOR:case TILE_MONS_GUARDIAN_NAGA:case TILE_MONS_NAGA_MAGE:ofs_y = 1;break;case TILE_MONS_HELL_KNIGHT:ofs_x = -1;ofs_y = 3;break;case TILE_MONS_RED_DEVIL:ofs_x = 2;ofs_y = -3;break;case TILE_MONS_WIZARD:ofs_x = 2;ofs_y = -2;break;case TILE_MONS_HUMAN:ofs_x = 5;ofs_y = 2;break;case TILE_MONS_ELF:ofs_y = 1;ofs_x = 4;break;case TILE_MONS_OGRE_MAGE:ofs_y = -2;ofs_x = -4;break;case TILE_MONS_DEEP_ELF_MAGE:case TILE_MONS_DEEP_ELF_SUMMONER:case TILE_MONS_DEEP_ELF_CONJURER:case TILE_MONS_DEEP_ELF_PRIEST:case TILE_MONS_DEEP_ELF_HIGH_PRIEST:case TILE_MONS_DEEP_ELF_DEMONOLOGIST:case TILE_MONS_DEEP_ELF_ANNIHILATOR:case TILE_MONS_DEEP_ELF_SORCERER:ofs_x = -1;ofs_y = -2;break;case TILE_MONS_DEEP_ELF_DEATH_MAGE:ofs_x = -1;break;}}
fprintf(fp, "extern int tile_%s_count[%s];\n",lcname.c_str(), max.c_str());fprintf(fp, "extern const char *tile_%s_name[%s];\n",lcname.c_str(), max.c_str());fprintf(fp, "extern tile_info tile_%s_info[%s];\n",lcname.c_str(), max.c_str());
fprintf(fp, "int tile_%s_count(unsigned int idx);\n", lcname.c_str());fprintf(fp, "const char *tile_%s_name(unsigned int idx);\n",lcname.c_str());fprintf(fp, "tile_info &tile_%s_info(unsigned int idx);\n",lcname.c_str());
fprintf(fp, "const char *tile_%s_name[%s] =\n{\n",lcname.c_str(), max.c_str());
fprintf(fp, "int tile_%s_count(unsigned int idx)\n{\n", lcname.c_str());fprintf(fp, " assert(idx >= %s && idx < %s);\n",m_start_value.c_str(), max.c_str());fprintf(fp, " return _tile_%s_count[idx - %s];\n",lcname.c_str(), m_start_value.c_str());fprintf(fp, "}\n\n");fprintf(fp, "const char *_tile_%s_name[%s - %s] =\n{\n",lcname.c_str(), max.c_str(), m_start_value.c_str());
fprintf(fp, "tile_info tile_%s_info[%s] =\n{\n",lcname.c_str(), max.c_str());
fprintf(fp, "const char *tile_%s_name(unsigned int idx)\n{\n",lcname.c_str());fprintf(fp, " assert(idx >= %s && idx < %s);\n",m_start_value.c_str(), max.c_str());fprintf(fp, " return _tile_%s_name[idx - %s];\n",lcname.c_str(), m_start_value.c_str());fprintf(fp, "}\n\n");fprintf(fp, "tile_info _tile_%s_info[%s - %s] =\n{\n",lcname.c_str(), max.c_str(), m_start_value.c_str());
dc-misc/unseen PLAYERdc-misc/unseen_monster MONS_UNKNOWNdc-misc/unseen_monster MCACHE_START
};// A glorified unsigned int that assists with ref-counting the mcache.class tile_fg_store{public:tile_fg_store() : m_tile(0) {}tile_fg_store(unsigned int tile) : m_tile(tile) {}operator unsigned int() { return m_tile; }unsigned int operator=(unsigned int tile);protected:unsigned int m_tile;