1 #include "AppHdr.h"
2 
3 #ifdef USE_TILE
4 #include "tilemcache.h"
5 
6 #include "colour.h"
7 #include "env.h"
8 #include "libutil.h"
9 #include "misc.h"
10 #include "mon-info.h"
11 #include "mon-util.h"
12 #include "mutant-beast.h"
13 #include "options.h"
14 #include "tile-flags.h"
15 #include "rltiles/tiledef-player.h"
16 #include "tiledoll.h"
17 #include "tilepick.h"
18 #include "tilepick-p.h"
19 
20 mcache_manager mcache;
21 
22 struct demon_data
23 {
demon_datademon_data24     demon_data() { head = body = wings = 0; }
25 
26     tileidx_t head;
27     tileidx_t body;
28     tileidx_t wings;
29 };
30 
31 // Internal mcache classes. The mcache_manager creates these internally.
32 // The only access external clients need is through the virtual
33 // info function.
34 
35 class mcache_monster : public mcache_entry
36 {
37 public:
38     mcache_monster(const monster_info& mon);
39 
40     virtual int info(tile_draw_info *dinfo) const override;
41 
42     static bool valid(const monster_info& mon);
43 
44     static bool get_weapon_offset(tileidx_t mon_tile, int *ofs_x, int *ofs_y);
45     static bool get_shield_offset(tileidx_t mon_tile, int *ofs_x, int *ofs_y);
46 
47 protected:
48     monster_type mtype;
49     tileidx_t m_mon_tile;
50     tileidx_t m_equ_tile;
51     tileidx_t m_shd_tile;
52 };
53 
54 class mcache_draco : public mcache_entry
55 {
56 public:
57     mcache_draco(const monster_info& mon);
58 
59     virtual int info(tile_draw_info *dinfo) const override;
60 
61     static bool valid(const monster_info& mon);
62 
63 protected:
64     tileidx_t m_mon_tile;
65     tileidx_t m_job_tile;
66     tileidx_t m_equ_tile;
67     tileidx_t m_shd_tile;
68     bool draco;
69 };
70 
71 class mcache_mbeast : public mcache_entry
72 {
73 public:
74     mcache_mbeast(const monster_info& mon);
75 
76     virtual int info(tile_draw_info *dinfo) const override;
77 
78     static bool valid(const monster_info& mon);
79 
80 protected:
81     vector<tileidx_t> layers;
82 };
83 
84 class mcache_ghost : public mcache_entry
85 {
86 public:
87     mcache_ghost(const monster_info& mon);
88 
89     virtual const dolls_data *doll() const override;
90 
91     static bool valid(const monster_info& mon);
92 
93     virtual bool transparent() const override;
94 
95 protected:
96     dolls_data m_doll;
97 };
98 
99 class mcache_demon : public mcache_entry
100 {
101 public:
102     mcache_demon(const monster_info& minf);
103 
104     virtual int info(tile_draw_info *dinfo) const override;
105 
106     static bool valid(const monster_info& mon);
107 
108 protected:
109     demon_data m_demon;
110 };
111 
112 class mcache_armour : public mcache_entry
113 {
114 public:
115     mcache_armour(const monster_info& minf);
116 
117     virtual int info(tile_draw_info *dinfo) const override;
118 
119     static bool valid(const monster_info& mon);
120 
121 protected:
122     tileidx_t m_mon_tile;
123     tileidx_t m_arm_tile;
124 };
125 
126 /////////////////////////////////////////////////////////////////////////////
127 // tile_fg_store
128 
operator =(tileidx_t tile)129 tileidx_t tile_fg_store::operator=(tileidx_t tile)
130 {
131     if ((tile & TILE_FLAG_MASK) == (m_tile & TILE_FLAG_MASK))
132     {
133         // Update, as flags may have changed.
134         m_tile = tile;
135         return m_tile;
136     }
137 
138     mcache_entry *old_entry = mcache.get(m_tile);
139     if (old_entry)
140         old_entry->dec_ref();
141 
142     m_tile = tile;
143 
144     mcache_entry *new_entry = mcache.get(m_tile);
145     if (new_entry)
146         new_entry->inc_ref();
147 
148     return m_tile;
149 }
150 
151 /////////////////////////////////////////////////////////////////////////////
152 // mcache_manager
153 
~mcache_manager()154 mcache_manager::~mcache_manager()
155 {
156     clear_all();
157 }
158 
register_monster(const monster_info & minf)159 unsigned int mcache_manager::register_monster(const monster_info& minf)
160 {
161     // TODO enne - is it worth it to search against all mcache entries?
162     // TODO enne - pool mcache types to avoid too much alloc/dealloc?
163 
164     mcache_entry *entry;
165 
166     if (minf.props.exists("monster_tile"))
167     {
168         if (mcache_monster::valid(minf))
169             entry = new mcache_monster(minf);
170         else
171             return 0;
172     }
173     else if (mcache_demon::valid(minf))
174         entry = new mcache_demon(minf);
175     else if (mcache_mbeast::valid(minf))
176         entry = new mcache_mbeast(minf);
177     else if (mcache_ghost::valid(minf))
178         entry = new mcache_ghost(minf);
179     else if (mcache_draco::valid(minf))
180         entry = new mcache_draco(minf);
181     else if (mcache_armour::valid(minf))
182         entry = new mcache_armour(minf);
183     else if (mcache_monster::valid(minf))
184         entry = new mcache_monster(minf);
185     else
186         return 0;
187 
188     tileidx_t idx = ~0;
189 
190     for (unsigned int i = 0; i < m_entries.size(); i++)
191     {
192         if (!m_entries[i])
193         {
194             m_entries[i] = entry;
195             idx = i;
196             break;
197         }
198     }
199 
200     if (idx > m_entries.size())
201     {
202         idx = m_entries.size();
203         m_entries.push_back(entry);
204     }
205 
206     return TILEP_MCACHE_START + idx;
207 }
208 
clear_nonref()209 void mcache_manager::clear_nonref()
210 {
211     for (mcache_entry *&entry : m_entries)
212     {
213         if (!entry || entry->ref_count() > 0)
214             continue;
215 
216         delete entry;
217         entry = nullptr;
218     }
219 }
220 
clear_all()221 void mcache_manager::clear_all()
222 {
223     deleteAll(m_entries);
224 }
225 
get(tileidx_t tile)226 mcache_entry *mcache_manager::get(tileidx_t tile)
227 {
228     tileidx_t idx = tile & TILE_FLAG_MASK;
229     if (idx < TILEP_MCACHE_START)
230         return nullptr;
231 
232     if (idx >= TILEP_MCACHE_START + m_entries.size())
233         return nullptr;
234 
235     mcache_entry *entry = m_entries[idx - TILEP_MCACHE_START];
236     return entry;
237 }
238 
239 /////////////////////////////////////////////////////////////////////////////
240 // mcache_monster
241 
mcache_monster(const monster_info & mon)242 mcache_monster::mcache_monster(const monster_info& mon)
243 {
244     ASSERT(mcache_monster::valid(mon));
245 
246     mtype = mon.type;
247     m_mon_tile = tileidx_monster(mon) & TILE_FLAG_MASK;
248 
249     const item_def* mon_weapon = mon.inv[MSLOT_WEAPON].get();
250     m_equ_tile = (mon_weapon != nullptr) ? tilep_equ_weapon(*mon_weapon) : 0;
251     if (mons_class_wields_two_weapons(mon.type))
252     {
253         const item_def* mon_weapon2 = mon.inv[MSLOT_ALT_WEAPON].get();
254         if (mon_weapon2)
255         {
256             switch (tilep_equ_weapon(*mon_weapon2))
257             {
258                 case TILEP_HAND1_DAGGER:
259                     m_shd_tile = TILEP_HAND2_DAGGER;
260                     break;
261                 case TILEP_DAGGER_1:
262                     m_shd_tile = TILEP_HAND2_DAGGER_1;
263                     break;
264                 case TILEP_HAND1_RAPIER:
265                     m_shd_tile = TILEP_HAND2_RAPIER;
266                     break;
267                 case TILEP_RAPIER_1:
268                     m_shd_tile = TILEP_HAND2_RAPIER_1;
269                     break;
270                 default:
271                 case TILEP_HAND1_SHORT_SWORD_SLANT:
272                     m_shd_tile = TILEP_HAND2_SHORT_SWORD_SLANT;
273                     break;
274                 case TILEP_SHORT_SWORD_SLANT_1:
275                     m_shd_tile = TILEP_HAND2_SHORT_SWORD_SLANT_1;
276                     break;
277                 case TILEP_HAND1_GREAT_FLAIL:
278                     m_shd_tile = TILEP_HAND2_GREAT_FLAIL;
279                     break;
280                 case TILEP_GREAT_FLAIL_1:
281                     m_shd_tile = TILEP_HAND2_GREAT_FLAIL_1;
282                     break;
283                 case TILEP_HAND1_GREAT_MACE:
284                     m_shd_tile = TILEP_HAND2_GREAT_MACE;
285                     break;
286                 case TILEP_GREAT_MACE_1:
287                     m_shd_tile = TILEP_HAND2_GREAT_MACE_1;
288                     break;
289                 case TILEP_HAND1_GIANT_CLUB:
290                     m_shd_tile = TILEP_HAND2_GIANT_CLUB;
291                     break;
292                 case TILEP_HAND1_GIANT_CLUB_SLANT:
293                     m_shd_tile = TILEP_HAND2_GIANT_CLUB_SLANT;
294                     break;
295                 case TILEP_HAND1_GIANT_CLUB_SPIKE:
296                     m_shd_tile = TILEP_HAND2_GIANT_CLUB_SPIKE;
297                     break;
298                 case TILEP_HAND1_GIANT_CLUB_SPIKE_SLANT:
299                     m_shd_tile = TILEP_HAND2_GIANT_CLUB_SPIKE_SLANT;
300                     break;
301                 case TILEP_HAND1_GIANT_CLUB_PLAIN:
302                     m_shd_tile = TILEP_HAND2_GIANT_CLUB_PLAIN;
303                     break;
304             };
305         }
306         else
307             m_shd_tile = 0;
308     }
309     else
310     {
311         const item_def* mon_shield = mon.inv[MSLOT_SHIELD].get();
312         m_shd_tile = (mon_shield != nullptr) ? tilep_equ_shield(*mon_shield) : 0;
313     }
314 }
315 
316 // Returns the amount of pixels necessary to shift a wielded weapon
317 // from its default placement. Tiles showing monsters already wielding
318 // a weapon should not be listed here.
get_weapon_offset(tileidx_t mon_tile,int * ofs_x,int * ofs_y)319 bool mcache_monster::get_weapon_offset(tileidx_t mon_tile,
320                                        int *ofs_x, int *ofs_y)
321 {
322     switch (mon_tile)
323     {
324     // No shift necessary.
325     case TILEP_MONS_DEEP_ELF_ARCHER:
326     case TILEP_MONS_DEEP_ELF_MASTER_ARCHER:
327     case TILEP_MONS_DEEP_ELF_BLADEMASTER:
328     case TILEP_MONS_CRIMSON_IMP:
329     case TILEP_MONS_IRON_IMP:
330     case TILEP_MONS_SHADOW_IMP:
331     case TILEP_MONS_HAROLD:
332     case TILEP_MONS_JOSEPHINE:
333     case TILEP_MONS_JOSEPH:
334     case TILEP_MONS_TERENCE:
335     case TILEP_MONS_RAKSHASA:
336     case TILEP_MONS_VAMPIRE_KNIGHT:
337     case TILEP_MONS_CHERUB:
338     case TILEP_MONS_MENNAS:
339     case TILEP_MONS_PROFANE_SERVITOR:
340     case TILEP_MONS_KOBOLD:
341     case TILEP_MONS_OCTOPODE:
342     case TILEP_MONS_ZOMBIE_OCTOPODE:
343     case TILEP_MONS_ANCESTOR:
344     case TILEP_MONS_ANCESTOR_KNIGHT:
345     case TILEP_MONS_ANCESTOR_BATTLEMAGE:
346     case TILEP_MONS_RAGGED_HIEROPHANT:
347         *ofs_x = 0;
348         *ofs_y = 0;
349         break;
350     // Shift to the left.
351     case TILEP_MONS_DEEP_ELF_DEATH_MAGE:
352         *ofs_x = -1;
353         *ofs_y = 0;
354         break;
355     case TILEP_MONS_HOBGOBLIN:
356     case TILEP_MONS_ROBIN:
357     case TILEP_MONS_GNOLL_SERGEANT:
358     case TILEP_MONS_TIAMAT:
359     case TILEP_MONS_TIAMAT_1:
360     case TILEP_MONS_TIAMAT_2:
361     case TILEP_MONS_TIAMAT_3:
362     case TILEP_MONS_TIAMAT_4:
363     case TILEP_MONS_TIAMAT_5:
364     case TILEP_MONS_TIAMAT_6:
365     case TILEP_MONS_TIAMAT_7:
366     case TILEP_MONS_TENGU:
367     case TILEP_MONS_TENGU_CONJURER:
368     case TILEP_MONS_TENGU_WARRIOR:
369     case TILEP_MONS_TENGU_REAVER:
370     case TILEP_MONS_SOJOBO:
371     case TILEP_MONS_BALRUG:
372         *ofs_x = -2;
373         *ofs_y = 0;
374         break;
375     case TILEP_MONS_SKELETON_LARGE:
376     case TILEP_MONS_ORC_WARLORD:
377     case TILEP_MONS_KOBOLD_BRIGAND:
378     case TILEP_MONS_EFREET:
379     case TILEP_MONS_VAMPIRE_MAGE:
380     case TILEP_MONS_GNOLL:
381     case TILEP_MONS_CRAZY_YIUF:
382     case TILEP_MONS_GRUM:
383     case TILEP_MONS_GNOLL_SHAMAN:
384         *ofs_x = -3;
385         *ofs_y = 0;
386         break;
387     // Shift to the right.
388     case TILEP_MONS_VAULT_GUARD:
389     case TILEP_MONS_VAULT_WARDEN:
390     case TILEP_MONS_VAULT_SENTINEL:
391     case TILEP_MONS_IRONBOUND_CONVOKER:
392     case TILEP_MONS_IRONBOUND_PRESERVER:
393     case TILEP_MONS_GARGOYLE:
394     case TILEP_MONS_MOLTEN_GARGOYLE:
395     case TILEP_MONS_WAR_GARGOYLE:
396     case TILEP_MONS_SERVANT_OF_WHISPERS:
397         *ofs_x = 1;
398         *ofs_y = 0;
399         break;
400     case TILEP_MONS_YAKTAUR_MELEE:
401         *ofs_x = 2;
402         *ofs_y = 0;
403         break;
404     case TILEP_MONS_YAKTAUR_CAPTAIN_MELEE:
405         *ofs_x = 4;
406         *ofs_y = 0;
407         break;
408     case TILEP_MONS_MARA:
409         *ofs_x = 4;
410         *ofs_y = -5;
411         break;
412     // Shift upwards.
413     case TILEP_MONS_CENTAUR_WARRIOR_MELEE:
414     case TILEP_MONS_DEEP_ELF_SORCERER:
415     case TILEP_MONS_DEEP_ELF_HIGH_PRIEST:
416     case TILEP_MONS_HELL_KNIGHT:
417     case TILEP_MONS_DEATH_KNIGHT:
418     case TILEP_MONS_MUMMY:
419     case TILEP_MONS_MUMMY_PRIEST:
420     case TILEP_MONS_GUARDIAN_MUMMY:
421     case TILEP_MONS_SKELETON_SMALL:
422     case TILEP_MONS_PSYCHE:
423     case TILEP_MONS_DUVESSA:
424     case TILEP_MONS_DUVESSA_1:
425         *ofs_x = 0;
426         *ofs_y = -1;
427         break;
428     case TILEP_MONS_MELIAI:
429         *ofs_x = 1;
430         *ofs_y = -1;
431         break;
432     case TILEP_MONS_SALAMANDER_MYSTIC:
433         *ofs_x = 0;
434         *ofs_y = -2;
435         break;
436     case TILEP_MONS_RED_DEVIL:
437         *ofs_x = 0;
438         *ofs_y = -3;
439         break;
440     case TILEP_MONS_NAGA:
441     case TILEP_MONS_NAGA_WARRIOR:
442     case TILEP_MONS_NAGA_MAGE:
443     case TILEP_MONS_NAGA_RITUALIST:
444     case TILEP_MONS_NAGA_SHARPSHOOTER:
445     case TILEP_MONS_VASHNIA:
446         *ofs_x = 0;
447         *ofs_y = -4;
448         break;
449     // Shift downwards.
450     case TILEP_MONS_DEEP_ELF_KNIGHT:
451     case TILEP_MONS_GUARDIAN_SERPENT:
452     case TILEP_MONS_DEEP_DWARF:
453     case TILEP_MONS_RUST_DEVIL:
454         *ofs_x = 0;
455         *ofs_y = 1;
456         break;
457     case TILEP_MONS_BLORK_THE_ORC:
458     case TILEP_MONS_BOGGART:
459     case TILEP_MONS_JORGRUN:
460     case TILEP_MONS_DIMME:
461     case TILEP_MONS_HALFLING:
462     case TILEP_MONS_IMPERIAL_MYRMIDON:
463         *ofs_x = 0;
464         *ofs_y = 2;
465         break;
466     // Shift upwards and to the left.
467     case TILEP_MONS_DEEP_ELF_AIR_MAGE:
468     case TILEP_MONS_DEEP_ELF_FIRE_MAGE:
469     case TILEP_MONS_DEEP_ELF_DEMONOLOGIST:
470     case TILEP_MONS_DEEP_ELF_ANNIHILATOR:
471     case TILEP_MONS_MINOTAUR:
472     case TILEP_MONS_VAMPIRE:
473         *ofs_x = -1;
474         *ofs_y = -2;
475         break;
476     case TILEP_MONS_CENTAUR_MELEE:
477     case TILEP_MONS_EUSTACHIO:
478         *ofs_x = -3;
479         *ofs_y = -3;
480         break;
481     case TILEP_MONS_DEMIGOD:
482     case TILEP_MONS_KIRKE:
483     case TILEP_MONS_FREDERICK:
484         *ofs_x = -1;
485         *ofs_y = -3;
486         break;
487     case TILEP_MONS_SONJA:
488     case TILEP_MONS_ANCIENT_CHAMPION:
489     case TILEP_MONS_SKELETAL_WARRIOR:
490     case TILEP_MONS_SALAMANDER:
491     case TILEP_MONS_VINE_STALKER:
492     case TILEP_MONS_NECROPHAGE:
493     case TILEP_MONS_WIGHT:
494         *ofs_x = -2;
495         *ofs_y = -2;
496         break;
497     case TILEP_MONS_SPRIGGAN_BERSERKER:
498         *ofs_x = -3;
499         *ofs_y = -2;
500         break;
501     case TILEP_MONS_RUPERT:
502         *ofs_x = -3;
503         *ofs_y = -3;
504         break;
505     case TILEP_MONS_SPRIGGAN_AIR_MAGE:
506         *ofs_x = -3;
507         *ofs_y = -5;
508         break;
509     case TILEP_MONS_DEEP_ELF_ELEMENTALIST:
510     case TILEP_MONS_DEEP_ELF_ELEMENTALIST_1:
511     case TILEP_MONS_DEEP_ELF_ELEMENTALIST_2:
512     case TILEP_MONS_DEEP_ELF_ELEMENTALIST_3:
513     case TILEP_MONS_FORMICID:
514     case TILEP_MONS_IRONBOUND_BEASTMASTER:
515         *ofs_x = -2;
516         *ofs_y = -1;
517         break;
518     case TILEP_MONS_FANNAR:
519     case TILEP_MONS_DONALD:
520         *ofs_x = -2;
521         *ofs_y = -4;
522         break;
523     case TILEP_MONS_NAGARAJA:
524         *ofs_x = -2;
525         *ofs_y = -5;
526         break;
527     case TILEP_MONS_NIKOLA:
528         *ofs_x = -4;
529         *ofs_y = -3;
530         break;
531     case TILEP_MONS_IRONBOUND_FROSTHEART:
532         *ofs_x = -4;
533         *ofs_y = -1;
534         break;
535     case TILEP_MONS_ARACHNE_STAVELESS:
536     case TILEP_MONS_MERFOLK_WATER:
537     case TILEP_MONS_MERFOLK_AQUAMANCER_WATER:
538     case TILEP_MONS_MERFOLK_IMPALER_WATER:
539     case TILEP_MONS_MERFOLK_JAVELINEER_WATER:
540     case TILEP_MONS_MERFOLK_SIREN_WATER:
541     case TILEP_MONS_MERFOLK_AVATAR_WATER:
542     case TILEP_MONS_ILSUIW_WATER:
543         *ofs_x = -1;
544         *ofs_y = -5;
545         break;
546     case TILEP_MONS_ASTERION:
547         *ofs_x = -3;
548         *ofs_y = -1;
549         break;
550     // Shift upwards and to the right.
551     case TILEP_MONS_NECROMANCER:
552     case TILEP_MONS_WIZARD:
553     case TILEP_MONS_CLOUD_MAGE:
554     case TILEP_MONS_MASTER_ELEMENTALIST:
555     case TILEP_MONS_JESSICA:
556     case TILEP_MONS_ANGEL:
557     case TILEP_MONS_DAEVA:
558     case TILEP_MONS_ANCESTOR_HEXER:
559     case TILEP_MONS_MAGGIE:
560         *ofs_x = 1;
561         *ofs_y = -1;
562         break;
563     case TILEP_MONS_AGNES_STAVELESS:
564         *ofs_x = 0;
565         *ofs_y = 1;
566         break;
567     case TILEP_MONS_TRAINING_DUMMY:
568         *ofs_x = 3;
569         *ofs_y = -1;
570         break;
571     case TILEP_MONS_MARGERY:
572     case TILEP_MONS_ERICA_SWORDLESS:
573     case TILEP_MONS_FAUN:
574         *ofs_x = 1;
575         *ofs_y = -3;
576         break;
577     case TILEP_MONS_LOUISE:
578     case TILEP_MONS_SATYR:
579         *ofs_x = 1;
580         *ofs_y = -4;
581         break;
582     case TILEP_MONS_HELL_WIZARD:
583     case TILEP_MONS_HELL_WIZARD_1:
584     case TILEP_MONS_HELL_WIZARD_2:
585         *ofs_x = 2;
586         *ofs_y = -2;
587         break;
588     case TILEP_MONS_ELF:
589         *ofs_x = 2;
590         *ofs_y = -3;
591         break;
592     case TILEP_MONS_HUMAN:
593     case TILEP_MONS_HUMAN_1:
594     case TILEP_MONS_HUMAN_2:
595         *ofs_x = -1;
596         *ofs_y = -2;
597         break;
598     case TILEP_MONS_GHOST:
599         *ofs_x = 3;
600         *ofs_y = -4;
601         break;
602     case TILEP_MONS_MERFOLK:
603     case TILEP_MONS_MERFOLK_AQUAMANCER:
604     case TILEP_MONS_MERFOLK_IMPALER:
605     case TILEP_MONS_MERFOLK_JAVELINEER:
606     case TILEP_MONS_MERFOLK_SIREN:
607     case TILEP_MONS_MERFOLK_AVATAR:
608     case TILEP_MONS_ILSUIW:
609         *ofs_x = 1;
610         *ofs_y = -5;
611         break;
612     case TILEP_MONS_FRANCES: // left-handed
613         *ofs_x = 20;
614         *ofs_y = -1;
615         break;
616     // Shift downwards and to the left.
617     case TILEP_MONS_GOBLIN:
618     case TILEP_MONS_IJYB:
619         *ofs_x = -2;
620         *ofs_y = 4;
621         break;
622     case TILEP_MONS_ORC:
623     case TILEP_MONS_ORC_WARRIOR:
624     case TILEP_MONS_URUG:
625     case TILEP_MONS_ORC_PRIEST:
626     case TILEP_MONS_ORC_HIGH_PRIEST:
627     case TILEP_MONS_SPRIGGAN:
628     case TILEP_MONS_SPRIGGAN_DEFENDER:
629         *ofs_x = -1;
630         *ofs_y = 1;
631         break;
632     case TILEP_MONS_ORC_KNIGHT:
633     case TILEP_MONS_ORC_WIZARD:
634     case TILEP_MONS_ORC_SORCERER:
635     case TILEP_MONS_NERGALLE:
636     case TILEP_MONS_ETTIN:
637     case TILEP_MONS_FROST_GIANT:
638     case TILEP_MONS_FIRE_GIANT:
639     case TILEP_MONS_IRON_GIANT:
640     case TILEP_MONS_THE_ENCHANTRESS:
641         *ofs_x = -2;
642         *ofs_y = 1;
643         break;
644     case TILEP_MONS_SAINT_ROKA:
645         *ofs_x = -3;
646         *ofs_y = 1;
647         break;
648     case TILEP_MONS_SERAPH:
649         *ofs_x = -1;
650         *ofs_y = -10;
651         break;
652     // Shift downwards and to the right.
653     case TILEP_MONS_OGRE:
654     case TILEP_MONS_OGRE_MAGE:
655     case TILEP_MONS_IRONBOUND_THUNDERHULK:
656         *ofs_x = 1;
657         *ofs_y = 1;
658         break;
659     case TILEP_MONS_TWO_HEADED_OGRE:
660         *ofs_x = 1;
661         *ofs_y = 2;
662         break;
663     case TILEP_MONS_ZOMBIE_LARGE:
664         *ofs_x = 4;
665         *ofs_y = 1;
666         break;
667     case TILEP_MONS_ZOMBIE_SMALL:
668         *ofs_x = 4;
669         *ofs_y = 3;
670         break;
671     case TILEP_MONS_TROLL:
672         *ofs_x = -3;
673         *ofs_y = 11;
674         break;
675     case TILEP_MONS_GHOUL:
676         *ofs_x = -3;
677         *ofs_y = -3;
678         break;
679     case TILEP_MONS_ORB_OF_FIRE:
680         *ofs_x = 0;
681         *ofs_y = 2;
682         break;
683     case TILEP_MONS_TENTACLED_MONSTROSITY:
684     case TILEP_MONS_CIGOTUVIS_MONSTER:
685         *ofs_x = -4;
686         *ofs_y = 2;
687         break;
688     case TILEP_MONS_SERPENT_OF_HELL_GEHENNA:
689     case TILEP_MONS_SERPENT_OF_HELL_COCYTUS:
690     case TILEP_MONS_SERPENT_OF_HELL_DIS:
691     case TILEP_MONS_SERPENT_OF_HELL_TARTARUS:
692         *ofs_x = -4;
693         *ofs_y = 3;
694         break;
695     case TILEP_MONS_UNSEEN_HORROR:
696         *ofs_x = -4;
697         *ofs_y = -4;
698         break;
699     case TILEP_MONS_UGLY_THING:
700     case TILEP_MONS_UGLY_THING_1:
701     case TILEP_MONS_UGLY_THING_2:
702     case TILEP_MONS_UGLY_THING_3:
703     case TILEP_MONS_UGLY_THING_4:
704     case TILEP_MONS_UGLY_THING_5:
705         *ofs_x = -4;
706         *ofs_y = -7;
707         break;
708     case TILEP_MONS_VERY_UGLY_THING:
709     case TILEP_MONS_VERY_UGLY_THING_1:
710     case TILEP_MONS_VERY_UGLY_THING_2:
711     case TILEP_MONS_VERY_UGLY_THING_3:
712     case TILEP_MONS_VERY_UGLY_THING_4:
713     case TILEP_MONS_VERY_UGLY_THING_5:
714         *ofs_x = -3;
715         *ofs_y = 4;
716         break;
717     case TILEP_MONS_ORANGE_STATUE:
718         *ofs_x = 3;
719         *ofs_y = -4;
720         break;
721     case TILEP_MONS_LOROCYPROCA:
722         *ofs_x = -4;
723         *ofs_y = 6;
724         break;
725     case TILEP_MONS_HELLION:
726         *ofs_x = -1;
727         *ofs_y = 4;
728         break;
729     case TILEP_MONS_CACODEMON:
730         *ofs_x = -3;
731         *ofs_y = -13;
732         break;
733     case TILEP_MONS_STARCURSED_MASS:
734     case TILEP_MONS_EXECUTIONER:
735         *ofs_x = -4;
736         *ofs_y = 4;
737         break;
738     case TILEP_MONS_WRETCHED_STAR:
739         *ofs_x = 1;
740         *ofs_y = -4;
741         break;
742     case TILEP_MONS_ELDRITCH_TENTACLE_PORTAL_9:
743         *ofs_x = -2;
744         *ofs_y = -3;
745         break;
746     case TILEP_MONS_ICE_FIEND:
747         *ofs_x = 1;
748         *ofs_y = 2;
749         break;
750     case TILEP_MONS_PANDEMONIUM_LORD:
751         *ofs_x = -2;
752         *ofs_y = 0;
753         break;
754     case TILEP_MONS_HELL_SENTINEL:
755         *ofs_x = -1;
756         *ofs_y = 4;
757         break;
758     case TILEP_MONS_DEMONIC_PLANT:
759         *ofs_x = -1;
760         *ofs_y = 2;
761         break;
762     case TILEP_MONS_TENTACLED_STARSPAWN:
763         *ofs_x = -1;
764         *ofs_y = 1;
765         break;
766     case TILEP_MONS_ABOMINATION_LARGE_1:
767         *ofs_x = -2;
768         *ofs_y = -8;
769         break;
770     case TILEP_MONS_ABOMINATION_LARGE_2:
771         *ofs_x = -3;
772         *ofs_y = 0;
773         break;
774     case TILEP_MONS_ABOMINATION_LARGE_3:
775         *ofs_x = -4;
776         *ofs_y = -5;
777         break;
778     case TILEP_MONS_ABOMINATION_LARGE_4:
779         *ofs_x = -3;
780         *ofs_y = -10;
781         break;
782     case TILEP_MONS_ABOMINATION_LARGE_6:
783         *ofs_x = -4;
784         *ofs_y = -11;
785         break;
786     case TILEP_MONS_CHAOS_SPAWN:
787         *ofs_x = 0;
788         *ofs_y = -5;
789         break;
790     case TILEP_MONS_CHAOS_SPAWN_2:
791         *ofs_x = 2;
792         *ofs_y = -3;
793         break;
794     case TILEP_MONS_CHAOS_SPAWN_3:
795         *ofs_x = -2;
796         *ofs_y = -1;
797         break;
798     case TILEP_MONS_GREAT_ORB_OF_EYES:
799         *ofs_x = -2;
800         *ofs_y = -2;
801         break;
802     case TILEP_MONS_WRAITH:
803         *ofs_x = -4;
804         *ofs_y = -4;
805         break;
806     case TILEP_MONS_ORB_GUARDIAN:
807         *ofs_x = -1;
808         *ofs_y = 2;
809         break;
810     case TILEP_MONS_ORB_GUARDIAN_FETUS:
811         *ofs_x = 4;
812         *ofs_y = -7;
813         break;
814     case TILEP_MONS_JORMUNGANDR:
815         *ofs_x = 9;
816         *ofs_y = -4;
817         break;
818     case TILEP_MONS_GIAGGOSTUONO:
819         *ofs_x = -5;
820         *ofs_y = 5;
821         break;
822     case TILEP_MONS_KILLER_KLOWN:
823         *ofs_x = 0;
824         *ofs_y = 4;
825         break;
826     case TILEP_MONS_KILLER_KLOWN_1:
827         *ofs_x = -4;
828         *ofs_y = -1;
829         break;
830     case TILEP_MONS_KILLER_KLOWN_2:
831         *ofs_x = -2;
832         *ofs_y = 4;
833         break;
834     case TILEP_MONS_KILLER_KLOWN_3:
835         *ofs_x = -2;
836         *ofs_y = -5;
837         break;
838     case TILEP_MONS_KILLER_KLOWN_4:
839         *ofs_x = 20;
840         *ofs_y = -10;
841         break;
842 
843     default:
844         // This monster cannot be displayed with a weapon.
845         return false;
846     }
847 
848     return true;
849 }
850 
851 // Returns the amount of pixels necessary to shift a worn shield, like
852 // it's done with weapon. No monster should have a shield hard-drawn
853 // on the tile.
get_shield_offset(tileidx_t mon_tile,int * ofs_x,int * ofs_y)854 bool mcache_monster::get_shield_offset(tileidx_t mon_tile,
855                                        int *ofs_x, int *ofs_y)
856 {
857     switch (mon_tile)
858     {
859     case TILEP_MONS_ORC:
860     case TILEP_MONS_URUG:
861     case TILEP_MONS_BLORK_THE_ORC:
862     case TILEP_MONS_ORC_PRIEST:
863     case TILEP_MONS_ORC_WARRIOR:
864     case TILEP_MONS_ORC_KNIGHT:
865     case TILEP_MONS_ORC_WARLORD:
866     case TILEP_MONS_DEEP_ELF_KNIGHT:
867     case TILEP_MONS_KIRKE:
868     case TILEP_MONS_DIMME:
869         *ofs_x = 1;
870         *ofs_y = 0;
871         break;
872 
873     case TILEP_MONS_SAINT_ROKA:
874     case TILEP_MONS_MINOTAUR:
875         *ofs_x = 2;
876         *ofs_y = 0;
877         break;
878 
879     case TILEP_MONS_ARACHNE_STAVELESS:
880         *ofs_x = -6;
881         *ofs_y = 1;
882         break;
883 
884     case TILEP_MONS_ZOMBIE_SMALL:
885     case TILEP_MONS_SKELETON_SMALL:
886     case TILEP_MONS_VAULT_GUARD:
887     case TILEP_MONS_IRONBOUND_CONVOKER:
888     case TILEP_MONS_IRONBOUND_PRESERVER:
889     case TILEP_MONS_IRONBOUND_BEASTMASTER:
890     case TILEP_MONS_IRONBOUND_FROSTHEART:
891     case TILEP_MONS_VAULT_WARDEN:
892         *ofs_x = -2;
893         *ofs_y = 1;
894         break;
895 
896     case TILEP_MONS_HUMAN:
897     case TILEP_MONS_HUMAN_1:
898     case TILEP_MONS_HUMAN_2:
899     case TILEP_MONS_DEEP_ELF_BLADEMASTER: // second weapon
900     case TILEP_MONS_LOUISE:
901     case TILEP_MONS_TENGU:
902     case TILEP_MONS_TENGU_CONJURER:
903     case TILEP_MONS_TENGU_WARRIOR:
904     case TILEP_MONS_TENGU_REAVER:
905     case TILEP_MONS_SOJOBO:
906     case TILEP_MONS_FORMICID:
907     case TILEP_MONS_VINE_STALKER:
908     case TILEP_MONS_OCTOPODE:
909     case TILEP_MONS_CHERUB:
910     case TILEP_MONS_MENNAS:
911         *ofs_x = 0;
912         *ofs_y = 0;
913         break;
914 
915     case TILEP_MONS_DONALD:
916     case TILEP_MONS_ANCESTOR_KNIGHT:
917         *ofs_x = -1;
918         *ofs_y = -1;
919         break;
920 
921     case TILEP_MONS_GNOLL:
922         *ofs_x = -1;
923         *ofs_y = 1;
924         break;
925 
926     case TILEP_MONS_TWO_HEADED_OGRE: // second weapon
927         *ofs_x = 0;
928         *ofs_y = 2;
929         break;
930 
931     case TILEP_MONS_NAGA:
932     case TILEP_MONS_NAGA_WARRIOR:
933     case TILEP_MONS_NAGARAJA:
934         *ofs_x = -3;
935         *ofs_y = 0;
936         break;
937 
938     case TILEP_MONS_SPRIGGAN:
939     case TILEP_MONS_SPRIGGAN_DEFENDER:
940     case TILEP_MONS_SPRIGGAN_BERSERKER:
941         *ofs_x = 2;
942         *ofs_y = 3;
943         break;
944 
945     case TILEP_MONS_SPRIGGAN_DRUID:
946         *ofs_x = 2;
947         *ofs_y = -4;
948         break;
949 
950     case TILEP_MONS_SPRIGGAN_AIR_MAGE:
951         *ofs_x = 2;
952         *ofs_y = -9;
953         break;
954 
955     case TILEP_MONS_THE_ENCHANTRESS:
956         *ofs_x = 6;
957         *ofs_y = 3;
958         break;
959 
960     case TILEP_MONS_ASTERION:
961         *ofs_x = 1;
962         *ofs_y = 1;
963         break;
964 
965     case TILEP_MONS_SALAMANDER:
966         *ofs_x = 0;
967         *ofs_y = -1;
968         break;
969 
970     case TILEP_MONS_GNOLL_SERGEANT:
971     case TILEP_MONS_FREDERICK:
972         *ofs_x = 1;
973         *ofs_y = -1;
974         break;
975 
976     case TILEP_MONS_ENTROPY_WEAVER:
977     case TILEP_MONS_HELL_KNIGHT:
978     case TILEP_MONS_DEATH_KNIGHT:
979         *ofs_x = -3;
980         *ofs_y = 2;
981         break;
982 
983     case TILEP_MONS_KOBOLD:
984         *ofs_x = 0;
985         *ofs_y = 3;
986         break;
987 
988     case TILEP_MONS_SONJA:
989         *ofs_x = 3;
990         *ofs_y = -10;
991         break;
992 
993     case TILEP_MONS_MUMMY:
994         *ofs_x = -6;
995         *ofs_y = 0;
996         break;
997 
998     case TILEP_MONS_MERFOLK:
999     case TILEP_MONS_MERFOLK_AQUAMANCER:
1000     case TILEP_MONS_MERFOLK_IMPALER:
1001     case TILEP_MONS_MERFOLK_JAVELINEER:
1002     case TILEP_MONS_MERFOLK_SIREN:
1003     case TILEP_MONS_MERFOLK_AVATAR:
1004     case TILEP_MONS_ILSUIW:
1005     case TILEP_MONS_WRAITH:
1006         *ofs_x = -3;
1007         *ofs_y = -2;
1008         break;
1009 
1010     case TILEP_MONS_MERFOLK_WATER:
1011     case TILEP_MONS_MERFOLK_AQUAMANCER_WATER:
1012     case TILEP_MONS_MERFOLK_IMPALER_WATER:
1013     case TILEP_MONS_MERFOLK_JAVELINEER_WATER:
1014     case TILEP_MONS_MERFOLK_SIREN_WATER:
1015     case TILEP_MONS_MERFOLK_AVATAR_WATER:
1016     case TILEP_MONS_ILSUIW_WATER:
1017         *ofs_x = -5;
1018         *ofs_y = -2;
1019         break;
1020 
1021     case TILEP_MONS_TROLL:
1022         *ofs_x = 2;
1023         *ofs_y = 7;
1024         break;
1025 
1026     case TILEP_MONS_GHOUL:
1027     case TILEP_MONS_OGRE:
1028         *ofs_x = 2;
1029         *ofs_y = 1;
1030         break;
1031 
1032     case TILEP_MONS_GARGOYLE:
1033         *ofs_x = -8;
1034         *ofs_y = 1;
1035         break;
1036 
1037     case TILEP_MONS_CENTAUR_MELEE:
1038         *ofs_x = -8;
1039         *ofs_y = -4;
1040         break;
1041 
1042     case TILEP_MONS_HALFLING:
1043         *ofs_x = -2;
1044         *ofs_y = 5;
1045         break;
1046 
1047     case TILEP_MONS_DEEP_ELF_DEMONOLOGIST:
1048     case TILEP_MONS_DEEP_ELF_AIR_MAGE:
1049     case TILEP_MONS_DEEP_ELF_FIRE_MAGE:
1050         *ofs_x = 3;
1051         *ofs_y = -7;
1052         break;
1053 
1054     case TILEP_MONS_ORB_OF_FIRE:
1055         *ofs_x = -4;
1056         *ofs_y = 2;
1057         break;
1058 
1059     case TILEP_MONS_TENTACLED_MONSTROSITY:
1060     case TILEP_MONS_CIGOTUVIS_MONSTER:
1061     case TILEP_MONS_SERPENT_OF_HELL_GEHENNA:
1062     case TILEP_MONS_SERPENT_OF_HELL_COCYTUS:
1063     case TILEP_MONS_SERPENT_OF_HELL_DIS:
1064     case TILEP_MONS_SERPENT_OF_HELL_TARTARUS:
1065         *ofs_x = 4;
1066         *ofs_y = -1;
1067         break;
1068 
1069     case TILEP_MONS_UNSEEN_HORROR:
1070         *ofs_x = 5;
1071         *ofs_y = -1;
1072         break;
1073 
1074     case TILEP_MONS_UGLY_THING:
1075     case TILEP_MONS_UGLY_THING_1:
1076     case TILEP_MONS_UGLY_THING_2:
1077     case TILEP_MONS_UGLY_THING_3:
1078     case TILEP_MONS_UGLY_THING_4:
1079     case TILEP_MONS_UGLY_THING_5:
1080         *ofs_x = 4;
1081         *ofs_y = -1;
1082         break;
1083 
1084     case TILEP_MONS_VERY_UGLY_THING:
1085     case TILEP_MONS_VERY_UGLY_THING_1:
1086     case TILEP_MONS_VERY_UGLY_THING_2:
1087     case TILEP_MONS_VERY_UGLY_THING_3:
1088     case TILEP_MONS_VERY_UGLY_THING_4:
1089     case TILEP_MONS_VERY_UGLY_THING_5:
1090         *ofs_x = 4;
1091         *ofs_y = 5;
1092         break;
1093 
1094     case TILEP_MONS_ORANGE_STATUE:
1095         *ofs_x = -2;
1096         *ofs_y = -3;
1097         break;
1098 
1099     case TILEP_MONS_LOROCYPROCA:
1100         *ofs_x = -3;
1101         *ofs_y = 0;
1102         break;
1103 
1104     case TILEP_MONS_HELLION:
1105         *ofs_x = 0;
1106         *ofs_y = 4;
1107         break;
1108 
1109     case TILEP_MONS_CACODEMON:
1110         *ofs_x = 4;
1111         *ofs_y = -13;
1112         break;
1113 
1114     case TILEP_MONS_STARCURSED_MASS:
1115         *ofs_x = -3;
1116         *ofs_y = 2;
1117         break;
1118 
1119     case TILEP_MONS_WRETCHED_STAR:
1120         *ofs_x = 1;
1121         *ofs_y = -4;
1122         break;
1123 
1124     case TILEP_MONS_ELDRITCH_TENTACLE_PORTAL_9:
1125         *ofs_x = 3;
1126         *ofs_y = 0;
1127         break;
1128 
1129     case TILEP_MONS_EXECUTIONER:
1130         *ofs_x = 2;
1131         *ofs_y = 4;
1132         break;
1133 
1134     case TILEP_MONS_ICE_FIEND:
1135         *ofs_x = -2;
1136         *ofs_y = 2;
1137         break;
1138 
1139     case TILEP_MONS_PANDEMONIUM_LORD:
1140     case TILEP_MONS_ANGEL:
1141     case TILEP_MONS_DAEVA:
1142         *ofs_x = 1;
1143         *ofs_y = 1;
1144         break;
1145 
1146     case TILEP_MONS_HELL_SENTINEL:
1147         *ofs_x = 4;
1148         *ofs_y = -5;
1149         break;
1150 
1151     case TILEP_MONS_DEMONIC_PLANT:
1152         *ofs_x = 5;
1153         *ofs_y = 2;
1154         break;
1155 
1156     case TILEP_MONS_TENTACLED_STARSPAWN:
1157         *ofs_x = 1;
1158         *ofs_y = 1;
1159         break;
1160 
1161     case TILEP_MONS_GOBLIN:
1162     case TILEP_MONS_IJYB:
1163         *ofs_x = 1;
1164         *ofs_y = 4;
1165         break;
1166 
1167     case TILEP_MONS_ABOMINATION_LARGE_1:
1168         *ofs_x = 2;
1169         *ofs_y = -8;
1170         break;
1171 
1172     case TILEP_MONS_ABOMINATION_LARGE_2:
1173         *ofs_x = 2;
1174         *ofs_y = 0;
1175         break;
1176 
1177     case TILEP_MONS_ABOMINATION_LARGE_3:
1178         *ofs_x = -2;
1179         *ofs_y = -2;
1180         break;
1181 
1182     case TILEP_MONS_ABOMINATION_LARGE_4:
1183         *ofs_x = 2;
1184         *ofs_y = -7;
1185         break;
1186 
1187     case TILEP_MONS_ABOMINATION_LARGE_6:
1188         *ofs_x = 3;
1189         *ofs_y = -10;
1190         break;
1191 
1192     case TILEP_MONS_CHAOS_SPAWN:
1193         *ofs_x = 0;
1194         *ofs_y = -5;
1195         break;
1196 
1197     case TILEP_MONS_CHAOS_SPAWN_2:
1198         *ofs_x = 0;
1199         *ofs_y = -2;
1200         break;
1201 
1202     case TILEP_MONS_CHAOS_SPAWN_3:
1203         *ofs_x = 2;
1204         *ofs_y = -1;
1205         break;
1206 
1207     case TILEP_MONS_GREAT_ORB_OF_EYES:
1208     case TILEP_MONS_GHOST:
1209         *ofs_x = 2;
1210         *ofs_y = -2;
1211         break;
1212 
1213     case TILEP_MONS_FRANCES: // left-handed - shield goes in right hand
1214         *ofs_x = -20;
1215         *ofs_y = -1;
1216         break;
1217 
1218     case TILEP_MONS_ORB_GUARDIAN:
1219     case TILEP_MONS_ETTIN: // second weapon
1220         *ofs_x = 1;
1221         *ofs_y = 0;
1222         break;
1223 
1224     case TILEP_MONS_ORB_GUARDIAN_FETUS:
1225         *ofs_x = -8;
1226         *ofs_y = 5;
1227         break;
1228 
1229     case TILEP_MONS_JORMUNGANDR:
1230         *ofs_x = -2;
1231         *ofs_y = 2;
1232         break;
1233     case TILEP_MONS_SERAPH:
1234         *ofs_x = -2;
1235         *ofs_y = -7;
1236         break;
1237     case TILEP_MONS_LAMIA:
1238         *ofs_x = -2;
1239         *ofs_y = -5;
1240         break;
1241     case TILEP_MONS_GIAGGOSTUONO:
1242         *ofs_x = 2;
1243         *ofs_y = -7;
1244         break;
1245 
1246     case TILEP_MONS_SPRIGGAN_RIDER: // shield covered, out of picture
1247     default:
1248         // This monster cannot be displayed with a shield.
1249         return false;
1250     }
1251 
1252     return true;
1253 }
1254 
info(tile_draw_info * dinfo) const1255 int mcache_monster::info(tile_draw_info *dinfo) const
1256 {
1257     int count = 0;
1258     dinfo[count++].set(m_mon_tile);
1259 
1260     int ofs_x, ofs_y;
1261 
1262     if (m_equ_tile)
1263     {
1264         bool have_offs = false;
1265         // This mcache is for the player using a custom tile.
1266         if (mtype == MONS_PLAYER
1267             && Options.tile_weapon_offsets.first != INT_MAX)
1268         {
1269             ofs_x = Options.tile_weapon_offsets.first;
1270             ofs_y = Options.tile_weapon_offsets.second;
1271             have_offs = true;
1272         }
1273         else if (get_weapon_offset(m_mon_tile, &ofs_x, &ofs_y))
1274             have_offs = true;
1275 
1276         if (have_offs)
1277             dinfo[count++].set(m_equ_tile, ofs_x, ofs_y);
1278     }
1279     if (m_shd_tile)
1280     {
1281         bool have_offs = false;
1282         if (mtype == MONS_PLAYER
1283             && Options.tile_shield_offsets.first != INT_MAX)
1284         {
1285             ofs_x = Options.tile_shield_offsets.first;
1286             ofs_y = Options.tile_shield_offsets.second;
1287             have_offs = true;
1288         }
1289         else if (get_shield_offset(m_mon_tile, &ofs_x, &ofs_y))
1290             have_offs = true;
1291 
1292         if (have_offs)
1293             dinfo[count++].set(m_shd_tile, ofs_x, ofs_y);
1294     }
1295     return count;
1296 }
1297 
valid(const monster_info & mon)1298 bool mcache_monster::valid(const monster_info& mon)
1299 {
1300     tileidx_t mon_tile = tileidx_monster(mon) & TILE_FLAG_MASK;
1301 
1302     int ox, oy;
1303     bool have_weapon_offs = (mon.type == MONS_PLAYER
1304                              && Options.tile_weapon_offsets.first != INT_MAX)
1305         || get_weapon_offset(mon_tile, &ox, &oy);
1306     bool have_shield_offs = (mon.type == MONS_PLAYER
1307                              && Options.tile_shield_offsets.first != INT_MAX)
1308         || get_shield_offset(mon_tile, &ox, &oy);
1309     // Return true if the tile has a weapon offset and has a weapon,
1310     // a shield offset and a shield, or is a dual-wielder and has a
1311     // shield offset and an off-hand weapon (a valid edge case)
1312     return have_weapon_offs && mon.inv[MSLOT_WEAPON]
1313            || have_shield_offs
1314               && (mon.inv[MSLOT_SHIELD]
1315                   || mon.inv[MSLOT_ALT_WEAPON]
1316                      && mons_class_wields_two_weapons(mon.type));
1317 }
1318 
1319 /////////////////////////////////////////////////////////////////////////////
1320 // mcache_draco
1321 
mcache_draco(const monster_info & mon)1322 mcache_draco::mcache_draco(const monster_info& mon)
1323 {
1324     ASSERT(mcache_draco::valid(mon));
1325     draco = mons_is_draconian(mon.type);
1326 
1327     m_mon_tile = draco ? tileidx_draco_base(mon)
1328                        : tileidx_demonspawn_base(mon);
1329     const item_def* mon_wep = mon.inv[MSLOT_WEAPON].get();
1330     m_equ_tile = (mon_wep != nullptr) ? tilep_equ_weapon(*mon_wep) : 0;
1331     mon_wep = mon.inv[MSLOT_SHIELD].get();
1332     m_shd_tile = (mon_wep != nullptr) ? tilep_equ_shield(*mon_wep) : 0;
1333     m_job_tile = draco ? tileidx_draco_job(mon)
1334                        : tileidx_demonspawn_job(mon);
1335 }
1336 
info(tile_draw_info * dinfo) const1337 int mcache_draco::info(tile_draw_info *dinfo) const
1338 {
1339     int i = 0;
1340 
1341     dinfo[i++].set(m_mon_tile);
1342     if (m_job_tile)
1343         dinfo[i++].set(m_job_tile);
1344     if (m_equ_tile)
1345     {
1346         if (draco)
1347             dinfo[i++].set(m_equ_tile, -3, -1);
1348         else
1349             dinfo[i++].set(m_equ_tile, -1, 0);
1350     }
1351     if (m_shd_tile)
1352         dinfo[i++].set(m_shd_tile, 2, 0);
1353 
1354     return i;
1355 }
1356 
valid(const monster_info & mon)1357 bool mcache_draco::valid(const monster_info& mon)
1358 {
1359     return mons_is_draconian(mon.type) || mons_is_demonspawn(mon.type);
1360 }
1361 
1362 /////////////////////////////////////////////////////////////////////////////
1363 // mcache_ghost
1364 
mcache_ghost(const monster_info & mon)1365 mcache_ghost::mcache_ghost(const monster_info& mon)
1366 {
1367     ASSERT(mcache_ghost::valid(mon));
1368 
1369     const uint32_t seed = hash32(&mon.mname[0], mon.mname.size())
1370                         ^ hash32(&mon.i_ghost, sizeof(mon.i_ghost));
1371 
1372     m_doll.parts[TILEP_PART_BASE] = TILEP_SHOW_EQUIP;
1373     tilep_race_default(mon.i_ghost.species, 0, &m_doll);
1374     tilep_job_default(mon.i_ghost.job, &m_doll);
1375 
1376     for (int p = TILEP_PART_CLOAK; p < TILEP_PART_MAX; p++)
1377     {
1378         if (m_doll.parts[p] == TILEP_SHOW_EQUIP)
1379         {
1380             int part_offset = hash_with_seed(tile_player_part_count[p], seed, p);
1381             m_doll.parts[p] = tile_player_part_start[p] + part_offset;
1382         }
1383     }
1384 
1385     int ac = mon.i_ghost.ac;
1386     ac *= (5 + hash_with_seed(11, seed, 1000));
1387     ac /= 10;
1388 
1389     // Become uncannily spooky!
1390     if (today_is_halloween())
1391         m_doll.parts[TILEP_PART_HELM] = TILEP_HELM_PUMPKIN;
1392     else if (m_doll.parts[TILEP_PART_HELM] == TILEP_HELM_PUMPKIN)
1393         m_doll.parts[TILEP_PART_HELM] = TILEP_HELM_FIRST_NORM; // every day is *not* halloween
1394 
1395 
1396     if (ac > 25)
1397         m_doll.parts[TILEP_PART_BODY] = TILEP_BODY_PLATE_BLACK;
1398     else if (ac > 18)
1399         m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_CHAINMAIL;
1400     else if (ac > 12)
1401         m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_SCALEMAIL;
1402     else if (ac > 5)
1403         m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_LEATHER_ARMOUR;
1404     else
1405         m_doll.parts[TILEP_PART_BODY]= TILEP_BODY_ROBE_BLUE;
1406 
1407     int sk = mon.i_ghost.best_skill;
1408     int dam = mon.i_ghost.damage;
1409     dam *= (5 + hash_with_seed(11, seed, 1001));
1410     dam /= 10;
1411 
1412     switch (sk)
1413     {
1414     case SK_MACES_FLAILS:
1415         if (dam > 30)
1416             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GREAT_FLAIL;
1417         else if (dam > 25)
1418             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GREAT_MACE;
1419         else if (dam > 20)
1420             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_EVENINGSTAR;
1421         else if (dam > 15)
1422             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_MORNINGSTAR;
1423         else if (dam > 10)
1424             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_FLAIL;
1425         else if (dam > 5)
1426             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_MACE;
1427         else
1428             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_CLUB_SLANT;
1429         break;
1430 
1431     case SK_SHORT_BLADES:
1432         if (dam > 20)
1433             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_RAPIER;
1434         else if (dam > 10)
1435             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SHORT_SWORD_SLANT;
1436         else
1437             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_DAGGER_SLANT;
1438         break;
1439 
1440     case SK_LONG_BLADES:
1441         if (dam > 25)
1442             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GREAT_SWORD_SLANT;
1443         else if (dam > 20)
1444             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_KATANA_SLANT;
1445         else if (dam > 15)
1446             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SCIMITAR;
1447         else if (dam > 10)
1448             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_LONG_SWORD_SLANT;
1449         else
1450             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_FALCHION;
1451         break;
1452 
1453     case SK_AXES:
1454         if (dam > 30)
1455             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_EXECUTIONERS_AXE;
1456         else if (dam > 20)
1457             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_BATTLEAXE;
1458         else if (dam > 15)
1459             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_BROAD_AXE;
1460         else if (dam > 10)
1461             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_WAR_AXE;
1462         else
1463             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_HAND_AXE;
1464         break;
1465 
1466     case SK_POLEARMS:
1467         if (dam > 30)
1468             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_GLAIVE;
1469         else if (dam > 20)
1470             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SCYTHE;
1471         else if (dam > 15)
1472             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_HALBERD;
1473         else if (dam > 10)
1474             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_TRIDENT2;
1475         else
1476             m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_SPEAR;
1477         break;
1478 
1479     case SK_BOWS:
1480         m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_BOW2;
1481         break;
1482 
1483     case SK_CROSSBOWS:
1484         m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_ARBALEST;
1485         break;
1486 
1487     case SK_SLINGS:
1488         m_doll.parts[TILEP_PART_HAND1] = TILEP_HAND1_HUNTING_SLING;
1489         break;
1490 
1491     case SK_UNARMED_COMBAT:
1492     default:
1493         m_doll.parts[TILEP_PART_HAND1] = m_doll.parts[TILEP_PART_HAND2] = 0;
1494         break;
1495     }
1496 }
1497 
doll() const1498 const dolls_data *mcache_ghost::doll() const
1499 {
1500     return &m_doll;
1501 }
1502 
valid(const monster_info & mon)1503 bool mcache_ghost::valid(const monster_info& mon)
1504 {
1505     return mons_is_pghost(mon.type);
1506 }
1507 
transparent() const1508 bool mcache_ghost::transparent() const
1509 {
1510     return true;
1511 }
1512 
1513 /////////////////////////////////////////////////////////////////////////////
1514 // mcache_armour
mcache_armour(const monster_info & mon)1515 mcache_armour::mcache_armour(const monster_info& mon)
1516 {
1517     ASSERT(mcache_armour::valid(mon));
1518 
1519     m_mon_tile = tileidx_monster(mon) & TILE_FLAG_MASK;
1520 
1521     const item_def* mon_armour = mon.inv[MSLOT_ARMOUR].get();
1522     if (mon_armour)
1523         m_arm_tile = tilep_equ_armour(*mon_armour);
1524     else
1525         m_arm_tile = 0;
1526 }
1527 
info(tile_draw_info * dinfo) const1528 int mcache_armour::info(tile_draw_info *dinfo) const
1529 {
1530     int count = 0;
1531     dinfo[count++].set(m_mon_tile);
1532     if (m_arm_tile)
1533         dinfo[count++].set(m_arm_tile);
1534     return count;
1535 }
1536 
valid(const monster_info & mon)1537 bool mcache_armour::valid(const monster_info& mon)
1538 {
1539     return mon.type == MONS_ANIMATED_ARMOUR;
1540 }
1541 
1542 /////////////////////////////////////////////////////////////////////////////
1543 // mcache_demon
1544 
mcache_demon(const monster_info & minf)1545 mcache_demon::mcache_demon(const monster_info& minf)
1546 {
1547     ASSERT(mcache_demon::valid(minf));
1548 
1549     const uint32_t seed = hash32(&minf.mname[0], minf.mname.size());
1550 
1551     m_demon.head = tile_player_coloured(TILEP_DEMON_HEAD,
1552                                         element_colour(minf.colour()))
1553         + hash_with_seed(tile_player_count(TILEP_DEMON_HEAD), seed, 1);
1554     m_demon.body = tile_player_coloured(TILEP_DEMON_BODY,
1555                                         element_colour(minf.colour()))
1556         + hash_with_seed(tile_player_count(TILEP_DEMON_BODY), seed, 2);
1557 
1558     if (minf.is(MB_AIRBORNE))
1559     {
1560         m_demon.wings = tile_player_coloured(TILEP_DEMON_WINGS,
1561                                              element_colour(minf.colour()))
1562             + hash_with_seed(tile_player_count(TILEP_DEMON_WINGS), seed, 3);
1563     }
1564     else
1565         m_demon.wings = 0;
1566 }
1567 
info(tile_draw_info * dinfo) const1568 int mcache_demon::info(tile_draw_info *dinfo) const
1569 {
1570     if (m_demon.wings)
1571     {
1572         dinfo[0].set(m_demon.wings);
1573         dinfo[1].set(m_demon.body);
1574         dinfo[2].set(m_demon.head);
1575         return 3;
1576     }
1577     else
1578     {
1579         dinfo[0].set(m_demon.body);
1580         dinfo[1].set(m_demon.head);
1581         return 2;
1582     }
1583 }
1584 
valid(const monster_info & mon)1585 bool mcache_demon::valid(const monster_info& mon)
1586 {
1587     return mon.type == MONS_PANDEMONIUM_LORD;
1588 }
1589 
1590 /////////////////////////////////////////////////////////////////////////////
1591 // mcache_mbeast
1592 
mcache_mbeast(const monster_info & minf)1593 mcache_mbeast::mcache_mbeast(const monster_info& minf)
1594 {
1595     ASSERT(mcache_mbeast::valid(minf));
1596 
1597     // the layer order should be:
1598     // base < fire < bwing < ox < weird < sting < twing < shock < horn
1599     // (lowest to highest)
1600 
1601     const int tier
1602         = mutant_beast_tier(minf.props[MUTANT_BEAST_TIER].get_short()) - 1;
1603     ASSERT(tier >= 0);
1604     ASSERT(tier < (short)tile_player_count(TILEP_MUTANT_BEAST_BASE));
1605     layers.push_back(TILEP_MUTANT_BEAST_BASE + tier);
1606 
1607     int facets = 0; // bitfield
1608     for (auto facet : minf.props[MUTANT_BEAST_FACETS].get_vector())
1609         facets |= (1 << facet.get_int());
1610 
1611     // an ordered list of tiers and corresponding tiles to add.
1612     // tiers may appear repeatedly, if they have multiple layers.
1613     static const vector<pair<beast_facet, tileidx_t>> facet_layers = {
1614         { BF_FIRE,  TILEP_MUTANT_BEAST_FIRE },
1615         { BF_BAT,   TILEP_MUTANT_BEAST_WING_BASE },
1616         { BF_OX,    TILEP_MUTANT_BEAST_OX },
1617         { BF_WEIRD, TILEP_MUTANT_BEAST_WEIRD },
1618         { BF_STING, TILEP_MUTANT_BEAST_STING },
1619         { BF_BAT,   TILEP_MUTANT_BEAST_WING_TOP },
1620         { BF_SHOCK, TILEP_MUTANT_BEAST_SHOCK },
1621         { BF_OX,    TILEP_MUTANT_BEAST_HORN },
1622     };
1623 
1624     for (auto &facet_layer : facet_layers)
1625         if (facets & (1 << facet_layer.first))
1626             layers.emplace_back(facet_layer.second + tier);
1627 }
1628 
info(tile_draw_info * dinfo) const1629 int mcache_mbeast::info(tile_draw_info *dinfo) const
1630 {
1631     for (int i = 0; i < (int)layers.size(); ++i)
1632         dinfo[i].set(layers[i]);
1633     return layers.size();
1634 }
1635 
valid(const monster_info & mon)1636 bool mcache_mbeast::valid(const monster_info& mon)
1637 {
1638     return mon.type == MONS_MUTANT_BEAST;
1639 }
1640 
1641 #endif
1642