1 /**
2  ** Shapeinf.h: Info. about shapes read from various data files.
3  **
4  ** Written: 4/29/99 - JSF
5  **/
6 
7 #ifndef INCL_SHAPEINF
8 #define INCL_SHAPEINF   1
9 
10 /*
11 Copyright (C) 1998  Jeffrey S. Freedman
12 
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License
15 as published by the Free Software Foundation; either version 2
16 of the License, or (at your option) any later version.
17 
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26 */
27 
28 #include <iosfwd>
29 #include <vector>
30 #include <map>
31 #include <algorithm>
32 #include <iostream>
33 #include "baseinf.h"
34 #include "utils.h"
35 
36 class Armor_info;
37 class Weapon_info;
38 class Ammo_info;
39 class Monster_info;
40 class SFX_info;
41 class Animation_info;
42 class Explosion_info;
43 class Body_info;
44 class Paperdoll_npc;
45 class Paperdoll_item;
46 class Effective_hp_info;
47 class Frame_name_info;
48 class Frame_flags_info;
49 class Frame_usecode_info;
50 class Light_info;
51 class Warmth_info;
52 class Content_rules;
53 class Shapes_vga_file;
54 
55 template <typename T, class Info, T Info::*data>
56 class Text_reader_functor;
57 template <typename T, class Info, T Info::*data1, T Info::*data2>
58 class Text_pair_reader_functor;
59 template <typename T, class Info, T Info::*data, int bit>
60 class Bit_text_reader_functor;
61 template <typename T, class Info, T Info::*data>
62 class Bit_field_text_reader_functor;
63 template <typename T, class Info, T Info::*data, unsigned pad>
64 class Binary_reader_functor;
65 template < typename T1, typename T2, class Info,
66          T1 Info::*data1, T2 Info::*data2, unsigned pad >
67 class Binary_pair_reader_functor;
68 template <typename T, class Info, T *Info::*data>
69 class Class_reader_functor;
70 template <typename T, class Info, std::vector<T> Info::*data>
71 class Vector_reader_functor;
72 template <class Info>
73 class Null_functor;
74 template <int flag, class Info>
75 class Patch_flags_functor;
76 
77 class Gump_reader_functor;
78 class Ready_type_functor;
79 class Actor_flags_functor;
80 class Paperdoll_npc_functor;
81 
82 template <int flag, class Info>
83 class Flag_check_functor;
84 template <int flag, typename T, class Info, T Info::*data>
85 class Text_writer_functor;
86 template <int flag, typename T, class Info, T Info::*data1, T Info::*data2>
87 class Text_pair_writer_functor;
88 template <int flag, typename T, class Info, T Info::*data, int bit>
89 class Bit_text_writer_functor;
90 template <int flag, typename T, class Info, T Info::*data>
91 class Bit_field_text_writer_functor;
92 template <int flag, typename T, class Info, T Info::*data, int pad>
93 class Binary_writer_functor;
94 template < int flag, typename T1, typename T2, class Info,
95          T1 Info::*data1, T2 Info::*data2, int pad >
96 class Binary_pair_writer_functor;
97 template <typename T, class Info, T *Info::*data>
98 class Class_writer_functor;
99 template <typename T, class Info, std::vector<T> Info::*data>
100 class Vector_writer_functor;
101 
102 class Readytype_writer_functor;
103 
104 enum Data_flag_bits {
105     tf_ready_type_flag = 0,
106     tf_gump_shape_flag,
107     tf_monster_food_flag,
108     tf_actor_flags_flag,
109     tf_mountain_top_flag,
110     tf_altready_type_flag,
111     tf_barge_type_flag,
112     tf_field_type_flag,
113     // ++++ Keep shape flags last!
114     tf_usecode_events_flag,
115     tf_is_body_flag,
116     tf_lightweight_flag,
117     tf_quantity_frames_flag,
118     tf_locked_flag,
119     tf_is_volatile_flag,
120     tf_jawbone_flag,
121     tf_mirror_flag,
122 	tf_on_fire_flag,
123 	tf_extradimensional_storage_flag
124 };
125 enum Data_flag_names {
126     ready_type_flag      = (1U << tf_ready_type_flag),
127     gump_shape_flag      = (1U << tf_gump_shape_flag),
128     monster_food_flag    = (1U << tf_monster_food_flag),
129     actor_flags_flag     = (1U << tf_actor_flags_flag),
130     mountain_top_flag    = (1U << tf_mountain_top_flag),
131     altready_type_flag   = (1U << tf_altready_type_flag),
132     barge_type_flag      = (1U << tf_barge_type_flag),
133     field_type_flag      = (1U << tf_field_type_flag),
134     usecode_events_flag  = (1U << tf_usecode_events_flag),
135     is_body_flag         = (1U << tf_is_body_flag),
136     lightweight_flag     = (1U << tf_lightweight_flag),
137     quantity_frames_flag = (1U << tf_quantity_frames_flag),
138     locked_flag          = (1U << tf_locked_flag),
139     is_volatile_flag     = (1U << tf_is_volatile_flag),
140     jawbone_flag         = (1U << tf_jawbone_flag),
141     mirror_flag          = (1U << tf_mirror_flag),
142 	on_fire_flag         = (1U << tf_on_fire_flag),
143 	extradimensional_storage_flag = (1U << tf_extradimensional_storage_flag)
144 };
145 
146 /*
147  *  This class contains information only about shapes from "shapes.vga".
148  */
149 class Shape_info {
150 protected:
151 	// For some non-class data (see Data_flag_names enum).
152 	unsigned int modified_flags = 0;
153 	unsigned int frompatch_flags = 0;
154 	// For class data (to indicate an invalid entry should
155 	// be written by ES).
156 	unsigned int have_static_flags = 0;
157 	unsigned char tfa[3] = {0};       // From "tfa.dat".+++++Keep for
158 	//   debugging, for now.
159 	// 3D dimensions in tiles:
160 	unsigned char dims[3] = {0};      //   (x, y, z)
161 	unsigned char weight = 0, volume = 0;   // From "wgtvol.dat".
162 	unsigned char shpdims[2] = {0};   // From "shpdims.dat".
163 	unsigned char *weapon_offsets = nullptr;  // From "wihh.dat": pixel offsets
164 	//   for drawing weapon in hand
165 	Armor_info *armor = nullptr;          // From armor.dat.
166 	Weapon_info *weapon = nullptr;        // From weapon.dat, if a weapon.
167 	Ammo_info *ammo = nullptr;            // From ammo.dat, if ammo.
168 	Monster_info *monstinf = nullptr;     // From monster.dat.
169 	SFX_info *sfxinf = nullptr;
170 	Animation_info *aniinf = nullptr;
171 	Explosion_info *explosion = nullptr;
172 	Body_info *body = nullptr;
173 	Paperdoll_npc *npcpaperdoll = nullptr;
174 	// These vectors should be totally ordered by the strict-weak
175 	// order operator defined for the classes.
176 	std::vector<Paperdoll_item> objpaperdoll;
177 	std::vector<Effective_hp_info> hpinf;
178 	std::vector<Frame_name_info> nameinf;
179 	std::vector<Frame_flags_info> frflagsinf;
180 	std::vector<Frame_usecode_info> frucinf;
181 	std::vector<Light_info> lightinf;
182 	std::vector<Warmth_info> warminf;
183 	std::vector<Content_rules> cntrules;
184 	short gump_shape = -1;       // From container.dat.
185 	short gump_font = -1;        // From container.dat v2+.
186 	short monster_food = -1;
187 	unsigned short shape_flags = 0;
188 	unsigned char mountain_top = 0;
189 	unsigned char barge_type = 0;
190 	unsigned char actor_flags = 0;
191 	signed char field_type = -1;
192 	unsigned char ready_type = 0xff;    // From "ready.dat": where item can be worn.
193 	unsigned char alt_ready1 = 0xff;    // Alternate spot where item can be worn.
194 	unsigned char alt_ready2 = 0xff;    // Second alternate spot where item can be worn.
195 	bool spell_flag = false;        // Flagged as spell in 'ready.dat'.
196 	bool occludes_flag = false;     // Flagged in 'occlude.dat'.  Roof.
set_tfa_data()197 	void set_tfa_data() {   // Set fields from tfa.
198 		dims[0] = static_cast<unsigned char>(1 + (tfa[2] & 7));
199 		dims[1] = static_cast<unsigned char>(1 + ((tfa[2] >> 3) & 7));
200 		dims[2] = static_cast<unsigned char>(tfa[0] >> 5);
201 	}
202 	// Set/clear tfa bit.
set_tfa(int i,int bit,bool tf)203 	void set_tfa(int i, int bit, bool tf) {
204 		tfa[i] = static_cast<unsigned char>(tf ?
205 		                                    (tfa[i] | (1 << bit)) : (tfa[i]&~(1 << bit)));
206 	}
207 public:
208 	enum Actor_flags {
209 	    cold_immune = 0,
210 	    doesnt_eat,
211 	    teleports,
212 	    summons,
213 	    turns_invisible,
214 	    armageddon_safe,
215 	    quake_walk,
216 	    goblin
217 	};
218 	enum Shape_flags {
219 	    usecode_events = 0,
220 	    is_body,
221 	    lightweight,
222 	    quantity_frames,
223 	    locked,
224 	    is_volatile,
225 	    jawbone,
226 	    mirror,
227 		on_fire,
228 		extradimensional_storage
229 	};
230 	enum Mountain_tops {
231 	    not_mountain_top = 0,
232 	    normal_mountain_top,
233 	    snow_mountain_top
234 	};
235 	enum Barge_types {
236 	    barge_generic = 0,
237 	    barge_raft,
238 	    barge_seat,
239 	    barge_sails,
240 	    barge_wheel,
241 	    barge_draftanimal,
242 	    barge_turtle
243 	};
244 	enum Field_types {
245 	    no_field = -1,
246 	    fire_field = 0,
247 	    sleep_field,
248 	    poison_field,
249 	    caltrops
250 	};
251 	friend class Shapes_vga_file;   // Class that reads in data.
252 
253 	template <typename T, class Info, T Info::*data>
254 	friend class Text_reader_functor;
255 	template <typename T, class Info, T Info::*data1, T Info::*data2>
256 	friend class Text_pair_reader_functor;
257 	template <typename T, class Info, T Info::*data, int bit>
258 	friend class Bit_text_reader_functor;
259 	template <typename T, class Info, T Info::*data>
260 	friend class Bit_field_text_reader_functor;
261 	template <typename T, class Info, T Info::*data, unsigned pad>
262 	friend class Binary_reader_functor;
263 	template < typename T1, typename T2, class Info,
264 	         T1 Info::*data1, T2 Info::*data2, unsigned pad >
265 	friend class Binary_pair_reader_functor;
266 	template <typename T, class Info, T *Info::*data>
267 	friend class Class_reader_functor;
268 	template <typename T, class Info, std::vector<T> Info::*data>
269 	friend class Vector_reader_functor;
270 	template <class Info>
271 	friend class Null_functor;
272 	template <int flag, class Info>
273 	friend class Patch_flags_functor;
274 
275 	friend class Gump_reader_functor;
276 	friend class Ready_type_functor;
277 	friend class Actor_flags_functor;
278 	friend class Paperdoll_npc_functor;
279 
280 	template <int flag, class Info>
281 	friend class Flag_check_functor;
282 	template <int flag, typename T, class Info, T Info::*data>
283 	friend class Text_writer_functor;
284 	template <int flag, typename T, class Info, T Info::*data1, T Info::*data2>
285 	friend class Text_pair_writer_functor;
286 	template <int flag, typename T, class Info, T Info::*data, int bit>
287 	friend class Bit_text_writer_functor;
288 	template <int flag, typename T, class Info, T Info::*data>
289 	friend class Bit_field_text_writer_functor;
290 	template <int flag, typename T, class Info, T Info::*data, int pad>
291 	friend class Binary_writer_functor;
292 	template < int flag, typename T1, typename T2, class Info,
293 	         T1 Info::*data1, T2 Info::*data2, int pad >
294 	friend class Binary_pair_writer_functor;
295 	template <typename T, class Info, T *Info::*data>
296 	friend class Class_writer_functor;
297 	template <typename T, class Info, std::vector<T> Info::*data>
298 	friend class Vector_writer_functor;
299 
300 	friend class Readytype_writer_functor;
301 
302 	Shape_info();
303 	// This copy constructor and assignment operator intentionally cause
304 	// errors.
305 	Shape_info(const Shape_info &other);
306 	Shape_info &operator = (const Shape_info &other);
307 	~Shape_info();
308 	void copy(const Shape_info &inf2, bool skip_dolls = false);
309 
get_weight()310 	int get_weight() const {    // Get weight, volume.
311 		return weight;
312 	}
get_volume()313 	int get_volume() const {
314 		return volume;
315 	}
set_weight_volume(int w,int v)316 	void set_weight_volume(int w, int v) {
317 		weight = static_cast<unsigned char>(w);
318 		volume = static_cast<unsigned char>(v);
319 	}
320 
321 	int get_armor() const;
322 	int get_armor_immunity() const;
323 
324 	int get_explosion_sprite() const;
325 	int get_explosion_sfx() const;
326 
327 	int get_body_shape() const;
328 	int get_body_frame() const;
329 
has_weapon_info()330 	bool has_weapon_info() const {
331 		return weapon != nullptr;
332 	}
333 	const Weapon_info *get_weapon_info_safe() const;
get_weapon_info()334 	const Weapon_info *get_weapon_info() const {
335 		return weapon;
336 	}
337 	Weapon_info *set_weapon_info(bool tf);
338 
has_ammo_info()339 	bool has_ammo_info() const {
340 		return ammo != nullptr;
341 	}
342 	const Ammo_info *get_ammo_info_safe() const;
get_ammo_info()343 	const Ammo_info *get_ammo_info() const {
344 		return ammo;
345 	}
346 	Ammo_info *set_ammo_info(bool tf);
347 
has_armor_info()348 	bool has_armor_info() const {
349 		return armor != nullptr;
350 	}
get_armor_info()351 	const Armor_info *get_armor_info() const {
352 		return armor;
353 	}
354 	Armor_info *set_armor_info(bool tf);
355 
has_monster_info()356 	bool has_monster_info() const {
357 		return monstinf != nullptr;
358 	}
359 	const Monster_info *get_monster_info_safe() const;
get_monster_info()360 	const Monster_info *get_monster_info() const {
361 		return monstinf;
362 	}
363 	Monster_info *set_monster_info(bool tf);
364 
has_npc_paperdoll_info()365 	bool has_npc_paperdoll_info() const {
366 		return npcpaperdoll != nullptr;
367 	}
get_npc_paperdoll()368 	const Paperdoll_npc *get_npc_paperdoll() const {
369 		return npcpaperdoll;
370 	}
371 	Paperdoll_npc *set_npc_paperdoll_info(bool tf);
372 	const Paperdoll_npc *get_npc_paperdoll_safe(bool sex) const;
373 
has_sfx_info()374 	bool has_sfx_info() const {
375 		return sfxinf != nullptr;
376 	}
get_sfx_info()377 	const SFX_info *get_sfx_info() const {
378 		return sfxinf;
379 	}
380 	SFX_info *set_sfx_info(bool tf);
381 
has_explosion_info()382 	bool has_explosion_info() const {
383 		return explosion != nullptr;
384 	}
get_explosion_info()385 	const Explosion_info *get_explosion_info() const {
386 		return explosion;
387 	}
388 	Explosion_info *set_explosion_info(bool tf);
389 
has_animation_info()390 	bool has_animation_info() const {
391 		return aniinf != nullptr;
392 	}
get_animation_info()393 	const Animation_info *get_animation_info() const {
394 		return aniinf;
395 	}
396 	const Animation_info *get_animation_info_safe(int shnum, int nframes);
397 	Animation_info *set_animation_info(bool tf);
398 
has_body_info()399 	bool has_body_info() const {
400 		return body != nullptr;
401 	}
get_body_info()402 	const Body_info *get_body_info() const {
403 		return body;
404 	}
405 	Body_info *set_body_info(bool tf);
406 
407 	bool has_paperdoll_info() const;
get_paperdoll_info()408 	const std::vector<Paperdoll_item> &get_paperdoll_info() const {
409 		return objpaperdoll;
410 	}
411 	std::vector<Paperdoll_item> &set_paperdoll_info(bool tf);
412 	void clean_invalid_paperdolls();
413 	void clear_paperdoll_info();
414 	void add_paperdoll_info(Paperdoll_item &add);
415 	const Paperdoll_item *get_item_paperdoll(int frame, int spot) const;
is_object_allowed(int frame,int spot)416 	bool is_object_allowed(int frame, int spot) const {
417 		return get_item_paperdoll(frame, spot) != nullptr;
418 	}
419 
420 	bool has_content_rules() const;
get_content_rules()421 	const std::vector<Content_rules> &get_content_rules() const {
422 		return cntrules;
423 	}
424 	std::vector<Content_rules> &set_content_rules(bool tf);
425 	void clean_invalid_content_rules();
426 	void clear_content_rules();
427 	void add_content_rule(Content_rules &add);
428 	bool is_shape_accepted(int shape) const;
429 
430 	bool has_effective_hp_info() const;
get_effective_hp_info()431 	const std::vector<Effective_hp_info> &get_effective_hp_info() const {
432 		return hpinf;
433 	}
434 	std::vector<Effective_hp_info> &set_effective_hp_info(bool tf);
435 	void clean_invalid_hp_info();
436 	void clear_effective_hp_info();
437 	void add_effective_hp_info(Effective_hp_info &add);
438 	int get_effective_hps(int frame, int quality) const;
439 
440 	bool has_frame_name_info() const;
get_frame_name_info()441 	const std::vector<Frame_name_info> &get_frame_name_info() const {
442 		return nameinf;
443 	}
444 	std::vector<Frame_name_info> &set_frame_name_info(bool tf);
445 	void clean_invalid_name_info();
446 	void clear_frame_name_info();
447 	void add_frame_name_info(Frame_name_info &add);
448 	const Frame_name_info *get_frame_name(int frame, int quality) const;
449 
450 	bool has_frame_usecode_info() const;
get_frame_usecode_info()451 	const std::vector<Frame_usecode_info> &get_frame_usecode_info() const {
452 		return frucinf;
453 	}
454 	std::vector<Frame_usecode_info> &set_frame_usecode_info(bool tf);
455 	void clean_invalid_usecode_info();
456 	void clear_frame_usecode_info();
457 	void add_frame_usecode_info(Frame_usecode_info &add);
458 	const Frame_usecode_info *get_frame_usecode(int frame, int quality) const;
459 
460 	bool has_frame_flags() const;
get_frame_flags()461 	const std::vector<Frame_flags_info> &get_frame_flags() const {
462 		return frflagsinf;
463 	}
464 	std::vector<Frame_flags_info> &set_frame_flags(bool tf);
465 	void clean_invalid_frame_flags();
466 	void clear_frame_flags();
467 	void add_frame_flags(Frame_flags_info &add);
468 	int get_object_flags(int frame, int qual) const;
has_object_flag(int frame,int qual,int p)469 	bool has_object_flag(int frame, int qual, int p) const {
470 		return (get_object_flags(frame, qual) & (1 << p)) != 0;
471 	}
472 
473 	bool has_light_info() const;
get_light_info()474 	const std::vector<Light_info> &get_light_info() const {
475 		return lightinf;
476 	}
477 	std::vector<Light_info> &set_light_info(bool tf);
478 	void clean_invalid_light_info();
479 	void clear_light_info();
480 	void add_light_info(Light_info &add);
481 	int get_object_light(int frame) const;
482 
483 	bool has_warmth_info() const;
get_warmth_info()484 	const std::vector<Warmth_info> &get_warmth_info() const {
485 		return warminf;
486 	}
487 	std::vector<Warmth_info> &set_warmth_info(bool tf);
488 	void clean_invalid_warmth_info();
489 	void clear_warmth_info();
490 	void add_warmth_info(Warmth_info &add);
491 	int get_object_warmth(int frame) const;
492 
get_monster_food()493 	int get_monster_food() const {
494 		return monster_food;
495 	}
set_monster_food(int sh)496 	void set_monster_food(int sh) {
497 		if (monster_food != static_cast<short>(sh)) {
498 			modified_flags |= monster_food_flag;
499 			monster_food = static_cast<short>(sh);
500 		}
501 	}
502 
get_mountain_top_type()503 	int get_mountain_top_type() const {
504 		return mountain_top;
505 	}
set_mountain_top(int sh)506 	void set_mountain_top(int sh) {
507 		if (mountain_top != static_cast<unsigned char>(sh)) {
508 			modified_flags |= mountain_top_flag;
509 			mountain_top = static_cast<unsigned char>(sh);
510 		}
511 	}
512 
get_barge_type()513 	int get_barge_type() const {
514 		return barge_type;
515 	}
set_barge_type(int sh)516 	void set_barge_type(int sh) {
517 		if (barge_type != static_cast<unsigned char>(sh)) {
518 			modified_flags |= barge_type_flag;
519 			barge_type = static_cast<unsigned char>(sh);
520 		}
521 	}
522 
get_field_type()523 	int get_field_type() const {
524 		return field_type;
525 	}
set_field_type(int sh)526 	void set_field_type(int sh) {
527 		if (field_type != static_cast<signed char>(sh)) {
528 			modified_flags |= field_type_flag;
529 			field_type = static_cast<signed char>(sh);
530 		}
531 	}
532 
get_gump_shape()533 	int get_gump_shape() const {
534 		return gump_shape;
535 	}
get_gump_font()536 	int get_gump_font() const {
537 		return gump_font;
538 	}
set_gump_data(int sh,int fnt)539 	void set_gump_data(int sh, int fnt) {
540 		if (gump_shape != static_cast<short>(sh)
541 		        || gump_font != static_cast<short>(sh)) {
542 			modified_flags |= gump_shape_flag;
543 			gump_shape = static_cast<short>(sh);
544 			gump_font = static_cast<short>(fnt);
545 		}
546 	}
547 
get_shape_flags()548 	unsigned short get_shape_flags() const {
549 		return shape_flags;
550 	}
set_shape_flags(unsigned short flags)551 	void set_shape_flags(unsigned short flags) {
552 		if (shape_flags != flags) {
553 			int diff = (shape_flags ^ flags) * usecode_events_flag;
554 			modified_flags |= diff;
555 			shape_flags = flags;
556 		}
557 	}
get_shape_flag(int tf)558 	bool get_shape_flag(int tf) const {
559 		return (shape_flags & (1U << tf)) != 0;
560 	}
set_shape_flag(int tf,int mod)561 	void set_shape_flag(int tf, int mod) {
562 		if (!(shape_flags & (1U << tf))) {
563 			modified_flags |= (1U << mod);
564 			shape_flags |= (1U << tf);
565 		}
566 	}
clear_shape_flag(int tf,int mod)567 	void clear_shape_flag(int tf, int mod) {
568 		if (shape_flags & (1U << tf)) {
569 			modified_flags |= (1U << mod);
570 			shape_flags &= ~(1U << tf);
571 		}
572 	}
573 
has_usecode_events()574 	bool has_usecode_events() const {
575 		return get_shape_flag(usecode_events);
576 	}
is_body_shape()577 	bool is_body_shape() const {
578 		return get_shape_flag(is_body);
579 	}
is_lightweight()580 	bool is_lightweight() const {
581 		return get_shape_flag(lightweight);
582 	}
has_quantity_frames()583 	bool has_quantity_frames() const {
584 		return get_shape_flag(quantity_frames);
585 	}
is_container_locked()586 	bool is_container_locked() const {
587 		return get_shape_flag(locked);
588 	}
is_explosive()589 	bool is_explosive() const {
590 		return get_shape_flag(is_volatile);
591 	}
is_jawbone()592 	bool is_jawbone() const {
593 		return get_shape_flag(jawbone);
594 	}
is_mirror()595 	bool is_mirror() const {
596 		return get_shape_flag(mirror);
597 	}
is_on_fire()598 	bool is_on_fire() const {
599 		return get_shape_flag(on_fire);
600 	}
has_extradimensional_storage()601 	bool has_extradimensional_storage() const {
602 		return get_shape_flag(extradimensional_storage);
603 	}
604 
get_actor_flags()605 	unsigned char get_actor_flags() const {
606 		return actor_flags;
607 	}
set_actor_flags(char flags)608 	void set_actor_flags(char flags) {
609 		if (actor_flags != flags) {
610 			modified_flags |= actor_flags_flag;
611 			actor_flags = flags;
612 		}
613 	}
get_actor_flag(int tf)614 	bool get_actor_flag(int tf) const {
615 		return (actor_flags & (1 << tf)) != 0;
616 	}
set_actor_flag(int tf)617 	void set_actor_flag(int tf) {
618 		if (!(actor_flags & (1 << tf))) {
619 			modified_flags |= actor_flags_flag;
620 			actor_flags |= (1U << tf);
621 		}
622 	}
clear_actor_flag(int tf)623 	void clear_actor_flag(int tf) {
624 		if (actor_flags & (1 << tf)) {
625 			modified_flags |= actor_flags_flag;
626 			actor_flags &= ~(1U << tf);
627 		}
628 	}
629 
is_cold_immune()630 	bool is_cold_immune() const {
631 		return get_actor_flag(cold_immune);
632 	}
does_not_eat()633 	bool does_not_eat() const {
634 		return get_actor_flag(doesnt_eat);
635 	}
can_teleport()636 	bool can_teleport() const {
637 		return get_actor_flag(teleports);
638 	}
can_summon()639 	bool can_summon() const {
640 		return get_actor_flag(summons);
641 	}
can_be_invisible()642 	bool can_be_invisible() const {
643 		return get_actor_flag(turns_invisible);
644 	}
survives_armageddon()645 	bool survives_armageddon() const {
646 		return get_actor_flag(armageddon_safe);
647 	}
quake_on_walk()648 	bool quake_on_walk() const {
649 		return get_actor_flag(quake_walk);
650 	}
is_goblin()651 	bool is_goblin() const {
652 		return get_actor_flag(goblin);
653 	}
654 	// Get tile dims., flipped for
655 	//   reflected (bit 5) frames.
get_3d_xtiles(unsigned int framenum)656 	int get_3d_xtiles(unsigned int framenum) const {
657 		return dims[(framenum >> 5) & 1];
658 	}
get_3d_ytiles(unsigned int framenum)659 	int get_3d_ytiles(unsigned int framenum) const {
660 		return dims[1 ^ ((framenum >> 5) & 1)];
661 	}
get_3d_height()662 	int get_3d_height() const {   // Height (in lifts?).
663 		return dims[2];
664 	}
665 	void set_3d(int xt, int yt, int zt);
get_tfa(int i)666 	unsigned char get_tfa(int i) const {  // For debugging:
667 		return tfa[i];
668 	}
has_sfx()669 	bool has_sfx() const {         // Has a sound effect (guessing).
670 		return (tfa[0] & (1 << 0)) != 0;
671 	}
set_sfx(bool tf)672 	void set_sfx(bool tf) {
673 		set_tfa(0, 0, tf);
674 	}
has_strange_movement()675 	bool has_strange_movement() const { // Slimes, sea monsters.
676 		return (tfa[0] & (1 << 1)) != 0;
677 	}
set_strange_movement(bool tf)678 	void set_strange_movement(bool tf) {
679 		set_tfa(0, 1, tf);
680 	}
is_animated()681 	bool is_animated() const {
682 		return (tfa[0] & (1 << 2)) != 0;
683 	}
set_animated(bool tf)684 	void set_animated(bool tf) {
685 		set_tfa(0, 2, tf);
686 	}
is_solid()687 	bool is_solid() const {        // Guessing.  Means can't walk through.
688 		return (tfa[0] & (1 << 3)) != 0;
689 	}
set_solid(bool tf)690 	void set_solid(bool tf) {
691 		set_tfa(0, 3, tf);
692 	}
is_water()693 	bool is_water() const {        // Guessing.
694 		return (tfa[0] & (1 << 4)) != 0;
695 	}
set_water(bool tf)696 	void set_water(bool tf) {
697 		set_tfa(0, 4, tf);
698 	}
is_poisonous()699 	bool is_poisonous() const {    // Swamps.  Applies to tiles.
700 		return (tfa[1] & (1 << 4)) != 0;
701 	}
is_field()702 	bool is_field() const {        // Applies to Game_objects??
703 		return (tfa[1] & (1 << 4)) != 0;
704 	}
set_field(bool tf)705 	void set_field(bool tf) {
706 		set_tfa(1, 4, tf);
707 	}
is_door()708 	bool is_door() const {
709 		return (tfa[1] & (1 << 5)) != 0;
710 	}
set_door(bool tf)711 	void set_door(bool tf) {
712 		set_tfa(1, 5, tf);
713 	}
is_barge_part()714 	bool is_barge_part() const {
715 		return (tfa[1] & (1 << 6)) != 0;
716 	}
set_barge_part(bool tf)717 	void set_barge_part(bool tf) {
718 		set_tfa(1, 6, tf);
719 	}
is_transparent()720 	bool is_transparent() const {      // ??
721 		return (tfa[1] & (1 << 7)) != 0;
722 	}
set_transparent(bool tf)723 	void set_transparent(bool tf) {
724 		set_tfa(1, 7, tf);
725 	}
is_light_source()726 	bool is_light_source() const {
727 		return (tfa[2] & (1 << 6)) != 0;
728 	}
set_light_source(bool tf)729 	void set_light_source(bool tf) {
730 		set_tfa(2, 6, tf);
731 	}
has_translucency()732 	bool has_translucency() const {
733 		return (tfa[2] & (1 << 7)) != 0;
734 	}
set_translucency(bool tf)735 	void set_translucency(bool tf) {
736 		set_tfa(2, 7, tf);
737 	}
is_xobstacle()738 	bool is_xobstacle() const {    // Obstacle in x-dir.???
739 		return (shpdims[1] & 1) != 0;
740 	}
is_yobstacle()741 	bool is_yobstacle() const {    // Obstacle in y-dir.???
742 		return (shpdims[0] & 1) != 0;
743 	}
set_obstacle(bool x,bool y)744 	void set_obstacle(bool x, bool y) {
745 		shpdims[1] = x ? (shpdims[1] | 1) : (shpdims[1]&~1);
746 		shpdims[0] = y ? (shpdims[0] | 1) : (shpdims[0]&~1);
747 	}
748 	/*
749 	 *  TFA[1][b0-b3] seems to indicate object types:
750 	 */
751 	enum Shape_class {
752 	    unusable = 0,       // Trees.
753 	    quality = 2,
754 	    quantity = 3,       // Can have more than 1:  coins, arrs.
755 	    has_hp = 4,     // Breakable items (if hp != 0, that is)
756 	    quality_flags = 5,  // Item quality is set of flags:
757 	    // Bit 3 = okay-to-take.
758 	    container = 6,
759 	    hatchable = 7,      // Eggs, traps, moongates.
760 	    spellbook = 8,
761 	    barge = 9,
762 	    virtue_stone = 11,
763 	    monster = 12,       // Non-human's.
764 	    human = 13,     // Human NPC's.
765 	    building = 14       // Roof, window, mountain.
766 	};
get_shape_class()767 	Shape_class get_shape_class() const {
768 		return static_cast<Shape_class>(tfa[1] & 15);
769 	}
set_shape_class(Shape_class c)770 	void set_shape_class(Shape_class c) {
771 		tfa[1] = (tfa[1]&~15) | static_cast<int>(c);
772 	}
is_npc()773 	bool is_npc() const {
774 		Shape_class c = get_shape_class();
775 		return c == human || c == monster;
776 	}
has_quantity()777 	bool has_quantity() const {
778 		return get_shape_class() == quantity;
779 	}
has_quality_flags()780 	bool has_quality_flags() const {  // Might be more...
781 		return get_shape_class() == quality_flags;
782 	}
has_quality()783 	bool has_quality() const {
784 		Shape_class c = get_shape_class();
785 		return c == 2 || c == 6 || c == 7 || c == 11 || c == 12 || c == 13;
786 		//      return qual[(int) c];
787 	}
occludes()788 	bool occludes() const {
789 		return occludes_flag;
790 	}
set_occludes(bool tf)791 	void set_occludes(bool tf) {
792 		occludes_flag = tf;
793 	}
get_ready_type()794 	unsigned char get_ready_type() const {
795 		return ready_type;
796 	}
set_ready_type(unsigned char t)797 	void set_ready_type(unsigned char t) {
798 		if (ready_type != t) {
799 			modified_flags |= ready_type_flag;
800 			ready_type = t;
801 		}
802 	}
is_spell()803 	bool is_spell() const {
804 		return spell_flag;
805 	}
set_is_spell(bool tf)806 	void set_is_spell(bool tf) {
807 		if (spell_flag != tf) {
808 			modified_flags |= ready_type_flag;
809 			spell_flag = tf;
810 		}
811 	}
get_alt_ready1()812 	unsigned char get_alt_ready1() const {
813 		return alt_ready1;
814 	}
get_alt_ready2()815 	unsigned char get_alt_ready2() const {
816 		return alt_ready2;
817 	}
set_alt_ready(unsigned char t1,unsigned char t2)818 	void set_alt_ready(unsigned char t1, unsigned char t2) {
819 		if (alt_ready1 != t1 || alt_ready2 != t2) {
820 			modified_flags |= altready_type_flag;
821 			alt_ready1 = t1;
822 			alt_ready2 = t2;
823 		}
824 	}
825 	// Sets x to 255 if there is no weapon offset
get_weapon_offset(int frame,unsigned char & x,unsigned char & y)826 	void get_weapon_offset(int frame, unsigned char &x, unsigned char &y) const {
827 		if (!weapon_offsets) {
828 			x = 255;
829 			y = 255;
830 		} else {
831 			// x could be 255 (see read_info())
832 			x = weapon_offsets[frame * 2];
833 			y = weapon_offsets[frame * 2 + 1];
834 		}
835 	}
836 	void set_weapon_offset(int frame, unsigned char x, unsigned char y);
837 	int get_rotated_frame(int curframe, int quads) const;
838 };
839 
840 #endif
841