1 /**
2  ** Monstinf.h - Information (about NPC's, really) from 'monster.dat'.
3  **
4  ** Written: 8/13/01 - JSF
5  **/
6 
7 #ifndef INCL_MONSTINF
8 #define INCL_MONSTINF   1
9 
10 /*
11 Copyright (C) 2000-2013 The Exult Team
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 <cassert>
30 #include <vector>
31 
32 #include "baseinf.h"
33 #include "exult_constants.h"
34 
35 class Shape_info;
36 class Shapes_vga_file;
37 
38 /*
39  *  An element from 'equip.dat', describing a monster's equipment:
40  */
41 class Equip_element {
42 	unsigned short shapenum = 0;    // What to create, or 0 for nothing.
43 	unsigned char probability = 0;  // 0-100:  probabilit of creation.
44 	unsigned char quantity = 0;     // # to create.
45 public:
46 	friend class Monster_info;
47 	friend class Monster_actor;
set(int shnum,int prob,int quant)48 	void set(int shnum, int prob, int quant) {
49 		shapenum = shnum;
50 		probability = prob;
51 		quantity = quant;
52 	}
get_shapenum()53 	int get_shapenum() const {
54 		return shapenum;
55 	}
get_probability()56 	int get_probability() const {
57 		return probability;
58 	}
get_quantity()59 	int get_quantity() const {
60 		return quantity;
61 	}
62 };
63 
64 /*
65  *  A record from 'equip.dat' consists of 10 elements.
66  */
67 class Equip_record {
68 	Equip_element elements[10];
69 public:
70 	friend class Monster_info;
71 	friend class Monster_actor;
72 	// Set i'th element.
set(int i,int shnum,int prob,int quant)73 	void set(int i, int shnum, int prob, int quant) {
74 		elements[i].set(shnum, prob, quant);
75 	}
get(int i)76 	Equip_element &get(int i) {
77 		assert(i >= 0 && i < 10);
78 		return elements[i];
79 	}
80 };
81 
82 /*
83  *  Monster info. from 'monsters.dat':
84  */
85 class Monster_info : public Base_info {
86 	static std::vector<Equip_record> equip; // ->equipment info.
87 	static Monster_info default_info;   // For shapes not found.
88 	unsigned char strength;     // Attributes.
89 	unsigned char dexterity;
90 	unsigned char intelligence;
91 	unsigned char alignment;    // Default alignment.
92 	unsigned char combat;
93 	unsigned char armor;        // These are unarmed stats.
94 	unsigned char weapon;
95 	unsigned char reach;
96 	unsigned char flags;        // Defined below.
97 	// The following are bits corresponding
98 	//   to Weapon_data::Damage_type.
99 	unsigned char vulnerable, immune;
100 	unsigned char equip_offset; // Offset in 'equip.dat' (1 based;
101 	//   if 0, there's none.)
102 	short sfx;      // Sound used when attacking. We *need* better sfx packs.
103 	bool m_splits;          // For slimes.
104 	bool m_cant_die;
105 	bool m_cant_yell;       // Can't yell during combat.
106 	bool m_cant_bleed;
107 
108 	bool m_poison_safe;     // Can't be poisoned.
109 	bool m_charm_safe;      // Can't be charmed.
110 	bool m_sleep_safe;      // Can't be put to sleep.
111 	bool m_paralysis_safe;      // Can't be paralyzed.
112 	bool m_curse_safe;      // Can't be cursed.
113 	bool m_power_safe;      // As above 4 items, plus return of flag 13.
114 	bool m_death_safe;      // Return of flag 14. Immune to death spells?
115 	bool m_int_b1;          // May give XP; but what does it do???
116 
117 	unsigned char m_attackmode;      // Sets initial attack mode.
118 	unsigned char m_byte13;          // Unknown; Bits 3 through 7 of byte 13.
119 
120 	bool m_can_teleport;
121 	bool m_can_summon;
122 	bool m_can_be_invisible;
123 public:
124 	friend class Shape_info;
125 	friend class Monster_actor;
126 	// Read in from file.
127 	bool read(std::istream &in, int version, Exult_Game game);
128 	// Write out.
129 	void write(std::ostream &out, int shapenum, Exult_Game game);
130 	enum { is_binary = 1, entry_size = 25 };
131 	static const Monster_info *get_default();
reserve_equip(int cnt)132 	static void reserve_equip(int cnt) {
133 		equip.reserve(cnt);
134 	}
add_equip(Equip_record & eq)135 	static void add_equip(Equip_record &eq) {
136 		equip.push_back(eq);
137 	}
get_equip_cnt()138 	static int get_equip_cnt() {
139 		return equip.size();
140 	}
get_equip(int i)141 	static Equip_record &get_equip(int i) {
142 		assert(i >= 0 && static_cast<size_t>(i) < equip.size());
143 		return equip[i];
144 	}
splits()145 	bool splits() const {
146 		return m_splits;
147 	}
set_splits(bool tf)148 	void set_splits(bool tf) {
149 		if (m_splits != tf) {
150 			set_modified(true);
151 			m_splits = tf;
152 		}
153 	}
cant_die()154 	bool cant_die() const {
155 		return m_cant_die;
156 	}
set_cant_die(bool tf)157 	void set_cant_die(bool tf) {
158 		if (m_cant_die != tf) {
159 			set_modified(true);
160 			m_cant_die = tf;
161 		}
162 	}
cant_yell()163 	bool cant_yell() const {
164 		return m_cant_yell;
165 	}
set_cant_yell(bool tf)166 	void set_cant_yell(bool tf) {
167 		if (m_cant_yell != tf) {
168 			set_modified(true);
169 			m_cant_yell = tf;
170 		}
171 	}
cant_bleed()172 	bool cant_bleed() const {
173 		return m_cant_bleed;
174 	}
set_cant_bleed(bool tf)175 	void set_cant_bleed(bool tf) {
176 		if (m_cant_bleed != tf) {
177 			set_modified(true);
178 			m_cant_bleed = tf;
179 		}
180 	}
poison_safe()181 	bool poison_safe() const {
182 		return m_poison_safe;
183 	}
set_poison_safe(bool tf)184 	void set_poison_safe(bool tf) {
185 		if (m_poison_safe != tf) {
186 			set_modified(true);
187 			m_poison_safe = tf;
188 		}
189 	}
charm_safe()190 	bool charm_safe() const {
191 		return m_charm_safe;
192 	}
set_charm_safe(bool tf)193 	void set_charm_safe(bool tf) {
194 		if (m_charm_safe != tf) {
195 			set_modified(true);
196 			m_charm_safe = tf;
197 		}
198 	}
sleep_safe()199 	bool sleep_safe() const {
200 		return m_sleep_safe;
201 	}
set_sleep_safe(bool tf)202 	void set_sleep_safe(bool tf) {
203 		if (m_sleep_safe != tf) {
204 			set_modified(true);
205 			m_sleep_safe = tf;
206 		}
207 	}
paralysis_safe()208 	bool paralysis_safe() const {
209 		return m_paralysis_safe;
210 	}
set_paralysis_safe(bool tf)211 	void set_paralysis_safe(bool tf) {
212 		if (m_paralysis_safe != tf) {
213 			set_modified(true);
214 			m_paralysis_safe = tf;
215 		}
216 	}
curse_safe()217 	bool curse_safe() const {
218 		return m_curse_safe;
219 	}
set_curse_safe(bool tf)220 	void set_curse_safe(bool tf) {
221 		if (m_curse_safe != tf) {
222 			set_modified(true);
223 			m_curse_safe = tf;
224 		}
225 	}
power_safe()226 	bool power_safe() const {
227 		return m_power_safe;
228 	}
set_power_safe(bool tf)229 	void set_power_safe(bool tf) {
230 		if (m_power_safe != tf) {
231 			set_modified(true);
232 			m_power_safe = tf;
233 		}
234 	}
death_safe()235 	bool death_safe() const {
236 		return m_death_safe;
237 	}
set_death_safe(bool tf)238 	void set_death_safe(bool tf) {
239 		if (m_death_safe != tf) {
240 			set_modified(true);
241 			m_death_safe = tf;
242 		}
243 	}
get_int_b1()244 	bool get_int_b1() const {
245 		return m_int_b1;
246 	}
set_int_b1(bool tf)247 	void set_int_b1(bool tf) {
248 		if (m_int_b1 != tf) {
249 			set_modified(true);
250 			m_int_b1 = tf;
251 		}
252 	}
get_byte13()253 	unsigned char get_byte13() const {
254 		return m_byte13;
255 	}
set_byte13(char c)256 	void set_byte13(char c) {
257 		if (m_byte13 != c) {
258 			set_modified(true);
259 			m_byte13 = c;
260 		}
261 	}
get_attackmode()262 	unsigned char get_attackmode() const {
263 		return m_attackmode;
264 	}
set_attackmode(unsigned char c)265 	void set_attackmode(unsigned char c) {
266 		if (m_attackmode != c) {
267 			set_modified(true);
268 			m_attackmode = c;
269 		}
270 	}
can_teleport()271 	bool can_teleport() const {
272 		return m_can_teleport;
273 	}
set_can_teleport(bool tf)274 	void set_can_teleport(bool tf) {
275 		if (m_can_teleport != tf) {
276 			set_modified(true);
277 			m_can_teleport = tf;
278 		}
279 	}
can_summon()280 	bool can_summon() const {
281 		return m_can_summon;
282 	}
set_can_summon(bool tf)283 	void set_can_summon(bool tf) {
284 		if (m_can_summon != tf) {
285 			set_modified(true);
286 			m_can_summon = tf;
287 		}
288 	}
can_be_invisible()289 	bool can_be_invisible() const {
290 		return m_can_be_invisible;
291 	}
set_can_be_invisible(bool tf)292 	void set_can_be_invisible(bool tf) {
293 		if (m_can_be_invisible != tf) {
294 			set_modified(true);
295 			m_can_be_invisible = tf;
296 		}
297 	}
298 	// Get bits indicating
299 	//   Weapon_data::damage_type:
get_vulnerable()300 	unsigned char get_vulnerable() const {
301 		return vulnerable;
302 	}
set_vulnerable(unsigned char v)303 	void set_vulnerable(unsigned char v) {
304 		if (vulnerable != v) {
305 			set_modified(true);
306 			vulnerable = v;
307 		}
308 	}
get_immune()309 	unsigned char get_immune() const {
310 		return immune;
311 	}
set_immune(unsigned char v)312 	void set_immune(unsigned char v) {
313 		if (immune != v) {
314 			set_modified(true);
315 			immune = v;
316 		}
317 	}
318 	enum Flags {
319 	    fly = 0,
320 	    swim = 1,
321 	    walk = 2,
322 	    ethereal = 3,       // Can walk through walls.
323 	    no_body = 4,        // Don't create body.
324 	    // 5:  gazer, hook only.
325 	    start_invisible = 6,
326 	    see_invisible = 7
327 	};
get_flags()328 	unsigned char get_flags() const { // Get above set of flags.
329 		return flags;
330 	}
set_flags(unsigned char f)331 	void set_flags(unsigned char f) {
332 		if (flags != f) {
333 			set_modified(true);
334 			flags = f;
335 		}
336 	}
has_no_body()337 	bool has_no_body() const {  // No dead body?
338 		return (flags >> no_body) & 1;
339 	}
get_strength()340 	int get_strength() const {
341 		return strength;
342 	}
get_dexterity()343 	int get_dexterity() const {
344 		return dexterity;
345 	}
get_intelligence()346 	int get_intelligence() const {
347 		return intelligence;
348 	}
get_alignment()349 	int get_alignment() const {
350 		return alignment;
351 	}
set_alignment(int a)352 	void set_alignment(int a) {
353 		if (alignment != a) {
354 			set_modified(true);
355 			alignment = a;
356 		}
357 	}
get_combat()358 	int get_combat() const {
359 		return combat;
360 	}
get_armor()361 	int get_armor() const {
362 		return armor;
363 	}
get_weapon()364 	int get_weapon() const {
365 		return weapon;
366 	}
get_reach()367 	int get_reach() const {
368 		return reach;
369 	}
370 	void set_stats(int str, int dex, int intel, int cmb, int armour,
371 	               int wpn, int rch);
get_equip_offset()372 	int get_equip_offset() const {
373 		return equip_offset;
374 	}
set_equip_offset(int o)375 	void set_equip_offset(int o) {
376 		if (equip_offset != o) {
377 			set_modified(true);
378 			equip_offset = o;
379 		}
380 	}
get_hitsfx()381 	short get_hitsfx() const {
382 		return sfx;
383 	}
set_hitsfx(short s)384 	void set_hitsfx(short s) {
385 		if (sfx != s) {
386 			set_modified(true);
387 			sfx = s;
388 		}
389 	}
get_info_flag()390 	static int get_info_flag() {
391 		return 8;
392 	}
393 	int get_base_xp_value() const;
394 };
395 
396 
397 
398 #endif
399