1 /**
2  ** Monstinf.cc - Information (about NPC's, really) from 'monster.dat'.
3  **
4  ** Written: 8/13/01 - JSF
5  **/
6 
7 /*
8 Copyright (C) 2000-2013 The Exult Team
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 */
24 
25 #include "utils.h"
26 #include "exult_constants.h"
27 #include "monstinf.h"
28 #include "ignore_unused_variable_warning.h"
29 
30 using std::istream;
31 
32 std::vector<Equip_record> Monster_info::equip;
33 Monster_info Monster_info::default_info;
34 
35 /*
36  *  Read in monster info. from 'monsters.dat'.
37  *
38  *  Output: Shape # this entry describes.
39  */
40 
read(std::istream & in,int version,Exult_Game game)41 bool Monster_info::read(
42     std::istream &in,   // Input stream.
43     int version,        // Data file version.
44     Exult_Game game     // Loading BG file.
45 ) {
46 	ignore_unused_variable_warning(version);
47 	uint8 buf[Monster_info::entry_size - 2];    // Entry length.
48 	in.read(reinterpret_cast<char *>(buf), sizeof(buf));
49 	uint8 *ptr = buf;
50 	if (buf[Monster_info::entry_size - 3] == 0xff) { // means delete entry.
51 		set_invalid(true);
52 		return true;
53 	}
54 	m_sleep_safe = (*ptr & 1);
55 	m_charm_safe = (*ptr >> 1) & 1;
56 	strength = (*ptr++ >> 2) & 63;  // Byte 2.
57 
58 	m_curse_safe = (*ptr & 1);
59 	m_paralysis_safe = (*ptr >> 1) & 1;
60 	dexterity = (*ptr++ >> 2) & 63; // Byte 3.
61 
62 	m_poison_safe = (*ptr & 1); // verified
63 	m_int_b1 = (*ptr >> 1) & 1; // What does this do?
64 	intelligence = (*ptr++ >> 2) & 63;  // Byte 4.
65 
66 	alignment = *ptr & 3;       // Byte 5.
67 	combat = (*ptr++ >> 2) & 63;
68 
69 	m_splits = (*ptr & 1);  // Byte 6 (slimes).
70 	m_cant_die = (*ptr & 2) != 0;
71 	m_power_safe = (*ptr & 4) != 0;
72 	m_death_safe = (*ptr & 8) != 0;
73 	armor = (*ptr++ >> 4) & 15;
74 
75 	ptr++;              // Byte 7: Unknown.
76 	reach = *ptr & 15;      // Byte 8 - weapon reach.
77 	weapon = (*ptr++ >> 4) & 15;
78 	flags = *ptr++;         // Byte 9.
79 	vulnerable = *ptr++;    // Byte 10.
80 	immune = *ptr++;        // Byte 11.
81 	m_cant_yell = (*ptr & (1 << 5)) != 0;   // Byte 12.
82 	m_cant_bleed = (*ptr & (1 << 6)) != 0;
83 	ptr++;
84 	m_attackmode = (*ptr & 7);
85 	if (m_attackmode == 0)       // Fixes invalid data saved by older
86 		m_attackmode = 2;       // versions of ES.
87 	else
88 		m_attackmode--;
89 	m_byte13 = (*ptr++)&~7; // Byte 13: partly unknown.
90 	equip_offset = *ptr++;      // Byte 14.
91 	m_can_teleport = (*ptr & 1) != 0;   // Exult's extra flags: byte 15.
92 	m_can_summon = (*ptr & 2) != 0;
93 	m_can_be_invisible = (*ptr & 4) != 0;
94 	ptr++;
95 	ptr++;      // Byte 16: Unknown (0).
96 	int sfx_delta = game == BLACK_GATE ? -1 : 0;
97 	sfx = *reinterpret_cast<signed char *>(ptr++) + sfx_delta;  // Byte 17.
98 	return true;
99 }
100 
101 /*
102  *  Get a default block for generic NPC's.
103  */
104 
get_default()105 const Monster_info *Monster_info::get_default(
106 ) {
107 	if (!default_info.strength) { // First time?
108 		default_info.strength =
109 		    default_info.dexterity =
110 		        default_info.intelligence =
111 		            default_info.combat = 10;
112 		default_info.alignment = 0;     // Neutral.
113 		default_info.armor =
114 		    default_info.weapon = 0;
115 		default_info.reach = 3;
116 		default_info.flags = (1 << static_cast<int>(walk));
117 		default_info.equip_offset = 0;
118 		default_info.immune =
119 		    default_info.vulnerable =
120 		        default_info.m_byte13 = 0;
121 		default_info.m_can_be_invisible =
122 		    default_info.m_can_summon =
123 		        default_info.m_can_teleport =
124 		            default_info.m_cant_bleed =
125 		                default_info.m_cant_die =
126 		                    default_info.m_cant_yell =
127 		                        default_info.m_poison_safe =
128 		                            default_info.m_charm_safe =
129 		                                default_info.m_sleep_safe =
130 		                                    default_info.m_paralysis_safe =
131 		                                        default_info.m_curse_safe =
132 		                                                default_info.m_power_safe =
133 		                                                        default_info.m_death_safe =
134 		                                                                default_info.m_int_b1 =
135 		                                                                        default_info.m_splits = false;
136 		default_info.m_attackmode = 2;
137 	}
138 	return &default_info;
139 }
140 
141 /*
142  *  Set all the stats.
143  */
144 
set_stats(int str,int dex,int intel,int cmb,int armour,int wpn,int rch)145 void Monster_info::set_stats(
146     int str, int dex, int intel, int cmb, int armour,
147     int wpn, int rch
148 ) {
149 	if (strength != str || dexterity != dex || intelligence != intel
150 	        || combat != cmb || armor != armour || weapon != wpn
151 	        || reach != rch)
152 		set_modified(true);
153 	strength = str;
154 	dexterity = dex;
155 	intelligence = intel;
156 	combat = cmb;
157 	armor = armour;
158 	weapon = wpn;
159 	reach = rch;
160 }
161 
162 /*
163  *  How much experience the monster is worth. Ignores stats,
164  *  immunities and vulnerabilities (check Actor::reduce_health
165  *  for why).
166  */
167 
get_base_xp_value() const168 int Monster_info::get_base_xp_value() const {
169 	// This formula is exact.
170 	int expval = armor + weapon;
171 	expval += m_sleep_safe ? 1 : 0;
172 	expval += m_charm_safe ? 1 : 0;
173 	expval += m_curse_safe ? 1 : 0;
174 	expval += m_paralysis_safe ? 1 : 0;
175 	expval += m_poison_safe ? 1 : 0;
176 	// Don't know what this does, but it *does* add to XP.
177 	expval += m_int_b1 ? 1 : 0;
178 	// This prevents death from Death Bolt.
179 	expval += m_death_safe ? 1 : 0;
180 	expval += m_power_safe ? 8 : 0;
181 	expval += (flags & (1 << fly)) ? 1 : 0;
182 	expval += (flags & (1 << swim)) ? 1 : 0;
183 	expval += (flags & (1 << ethereal)) ? 2 : 0;
184 	expval += (flags & (1 << 5)) ? 2 : 0;   // No idea what this does.
185 	expval += (flags & (1 << see_invisible)) ? 2 : 0;
186 	expval += (flags & (1 << start_invisible)) ? 8 : 0;
187 	expval += m_splits ? 2 : 0;
188 	expval += reach > 5 ? 2 : (reach > 3 ? 1 : 0);
189 	return expval;
190 }
191 
192