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