1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef XEEN_COMBAT_H
24 #define XEEN_COMBAT_H
25 
26 #include "common/scummsys.h"
27 #include "common/rect.h"
28 #include "xeen/files.h"
29 #include "xeen/sprites.h"
30 
31 namespace Xeen {
32 
33 #define MAX_NUM_MONSTERS 107
34 #define PARTY_AND_MONSTERS 12
35 #define POW_COUNT 12
36 #define ATTACK_MONSTERS_COUNT 26
37 
38 enum DamageType {
39 	DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3,
40 	DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7,
41 	DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10,
42 	DT_UNDEAD = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13,
43 	DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16,
44 	DT_POISON_VOLLEY = 17, DT_MAGIC_ARROW = 18
45 };
46 
47 enum SpecialAttack {
48 	SA_NONE = 0, SA_MAGIC = 1, SA_FIRE = 2, SA_ELEC = 3, SA_COLD = 4,
49 	SA_POISON = 5, SA_ENERGY = 6, SA_DISEASE = 7, SA_INSANE = 8,
50 	SA_SLEEP = 9, SA_CURSEITEM = 10, SA_INLOVE = 11, SA_DRAINSP = 12,
51 	SA_CURSE = 13, SA_PARALYZE = 14, SA_UNCONSCIOUS = 15,
52 	SA_CONFUSE = 16, SA_BREAKWEAPON = 17, SA_WEAKEN = 18,
53 	SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22
54 };
55 
56 enum ShootType {
57 	ST_0 = 0, ST_1 = 1
58 };
59 
60 enum CombatMode {
61 	COMBATMODE_STARTUP = 0, COMBATMODE_INTERACTIVE = 1, COMBATMODE_2 = 2
62 };
63 
64 enum PowType {
65 	POW_INVALID = -1, POW_FIREBALL = 0, POW_INCINERATE = 1,
66 	POW_FIERY_FLAIL = 2, POW_LIGHTNING = 3, POW_MEGAVOLTS = 4,
67 	POW_SPARKS = 5, POW_STOPPER = 6, POW_MAGIC_ORB = 7,
68 	POW_COLD_RAY = 8, POW_FROST_WAVE = 9, POW_SPRAY = 10,
69 	POW_ARROW = 11, POW_MAGIC_ARROW = 12, POW_ENERGY_BLAST = 13,
70 	POW_SPARKLES = 14, POW_DEADLY_SWARM = 15
71 };
72 
73 enum RangeType {
74 	RT_SINGLE = 0, RT_GROUP = 1, RT_ALL = 2, RT_HIT = 3
75 };
76 
77 class XeenEngine;
78 class Character;
79 class XeenItem;
80 class MonsterStruct;
81 
82 struct PowSlot {
83 	bool _active;
84 	int _duration;
85 	int _scale;
86 	int _elemFrame;
87 	int _elemScale;
88 
PowSlotPowSlot89 	PowSlot() : _active(false), _duration(0), _scale(0),
90 		_elemFrame(0), _elemScale(0) {}
91 };
92 
93 class PowSlots {
94 private:
95 	PowSlot _data[POW_COUNT];
96 public:
97 	/**
98 	 * Gets a slot entry
99 	 */
100 	PowSlot &operator[](uint idx) {
101 		assert(idx < POW_COUNT);
102 		return _data[idx];
103 	}
104 
105 	/**
106 	 * Resets the elemental frame used in all the slots
107 	 */
resetElementals()108 	void resetElementals() {
109 		for (int idx = 0; idx < POW_COUNT; ++idx)
110 			_data[idx]._elemFrame = 0;
111 	}
112 };
113 
114 class Combat {
115 private:
116 	XeenEngine *_vm;
117 
118 	/**
119 	 * Handles the logic for attacking with a given amount of damage
120 	 */
121 	void attack2(int damage, RangeType rangeType);
122 
123 	/**
124 	 * Returns true if the character successfully hits the monster
125 	 */
126 	bool hitMonster(Character &c, RangeType rangeType);
127 
128 	/**
129 	 * Gets the damage a given character's equipped weapon will do
130 	 */
131 	void getWeaponDamage(Character &c, RangeType rangeType);
132 
133 	/**
134 	 * Returns how much damage will be done to a monster
135 	 */
136 	int getMonsterDamage(Character &c);
137 
138 	/**
139 	 * Gets the scale of damage, used for sprite display in the scene
140 	 */
141 	int getDamageScale(int v);
142 
143 	/**
144 	 * Gets the current monster's damage resistance to the currently set damage type
145 	 */
146 	int getMonsterResistence(RangeType rangeType);
147 
148 	/**
149 	 * Distribute experience between active party members
150 	 */
151 	void giveExperience(int experience);
152 public:
153 	Common::Array<Character *> _combatParty;
154 	bool _charsBlocked[PARTY_AND_MONSTERS];
155 	int _charsGone[PARTY_AND_MONSTERS];
156 	SpriteResource _powSprites;
157 	int _attackMonsters[ATTACK_MONSTERS_COUNT];
158 	int _monster2Attack;
159 	PowSlots _pow;
160 	int _missedShot[8];
161 	Common::Array<int> _speedTable;
162 	int _shootingRow[8];
163 	int _globalCombat;
164 	int _whosTurn;
165 	bool _itemFlag;
166 	int _monsterMap[32][32];
167 	bool _monsterMoved[MAX_NUM_MONSTERS];
168 	bool _rangeAttacking[MAX_NUM_MONSTERS];
169 	int _gmonHit[36];
170 	bool _monstersAttacking;
171 	CombatMode _combatMode;
172 	int _attackDurationCtr;
173 	bool _partyRan;
174 	int _whosSpeed;
175 	DamageType _damageType;
176 	Character *_oldCharacter;
177 	int _monsterDamage;
178 	int _weaponDamage;
179 	int _weaponDie, _weaponDice;
180 	int _weaponElemMaterial;
181 	XeenItem *_attackWeapon;
182 	int _attackWeaponId;
183 	File _missVoc;
184 	int _hitChanceBonus;
185 	bool _dangerPresent;
186 	bool _moveMonsters;
187 	RangeType _rangeType;
188 	ShootType _shootType;
189 	int _combatTarget;
190 public:
191 	Combat(XeenEngine *vm);
192 
193 	/**
194 	 * Clear the list of attacking monsters
195 	 */
196 	void clearAttackers();
197 
198 	/**
199 	 * Clear the list of blocked characters
200 	 */
201 	void clearBlocked();
202 
203 	/**
204 	 * Clear the list of ros projectiles are on headed for part members
205 	 */
206 	void clearShooting();
207 
208 	/**
209 	 * Resets all combat related data
210 	 */
211 	void reset();
212 
213 	/**
214 	 * Gives damage to character or characters in the party
215 	 */
216 	void giveCharDamage(int damage, DamageType attackType, int charIndex);
217 
218 	/**
219 	 * Do damage to a specific character
220 	 */
221 	void doCharDamage(Character &c, int charNum, int monsterDataIndex);
222 
223 	/**
224 	 * Handles moving monsters by a space between game turns
225 	 */
226 	void moveMonsters();
227 
228 	/**
229 	 * Setup the combat party with a copy of the currently active party
230 	 */
231 	void setupCombatParty();
232 
233 	/**
234 	 * Sets up a table of speeds to determine the order in which characters and monsters fight
235 	 */
236 	void setSpeedTable();
237 
238 	/**
239 	 * Returns true if all participants in the combat are disabled
240 	 */
241 	bool allHaveGone() const;
242 
243 	/**
244 	 * Returns true if all the characters of the party are disabled
245 	 */
246 	bool charsCantAct() const;
247 
248 	/**
249 	 * Return a description of the monsters being faced
250 	 */
251 	Common::String getMonsterDescriptions();
252 
253 	/**
254 	 * Main method for characters to attack
255 	 */
256 	void attack(Character &c, RangeType rangeType);
257 
258 	/**
259 	 * Flag the currently active character as blocking/defending
260 	 */
261 	void block();
262 
263 	/**
264 	 * Perform whatever the current combat character's quick action is
265 	 */
266 	void quickFight();
267 
268 	/**
269 	 * Current selected character is trying to run away
270 	 */
271 	void run();
272 
273 	/**
274 	 * Called to handle monsters doing ranged attacks against the party
275 	 */
276 	void monstersAttack();
277 
278 	void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt);
279 
280 	/**
281 	 * Determines whether a given monster can move
282 	 * @param pt			Monster position
283 	 * @param wallShift		Shift mask for determining direction being moved
284 	 * @param xDiff			X Delta for move
285 	 * @param yDiff			Y Delta for move
286 	 * @param monsterId		Monster number being tested
287 	 */
288 	bool canMonsterMove(const Common::Point &pt, int wallShift, int xDiff, int yDiff, int monsterId);
289 
290 	/**
291 	 * Moves a monster by a given delta amount if it's a valid move
292 	 */
293 	void moveMonster(int monsterId, const Common::Point &moveDelta);
294 
295 	/**
296 	 * Handle a monster's turn at attacking combat party members
297 	 */
298 	void doMonsterTurn(int monsterId);
299 
300 	/**
301 	 * Handles a monster's turn at attacking a specific member of the combat party
302 	 */
303 	void doMonsterTurn(int monsterId, int charNum);
304 
305 	/**
306 	 * Called when combat has ended
307 	 */
308 	void endAttack();
309 
310 	void monsterOvercome();
311 
312 	/**
313 	 * Checks whether a given position on the map will stop a ranged attack
314 	 */
315 	int stopAttack(const Common::Point &diffPt);
316 
317 	/**
318 	 * Called to do ranged attacks, both with bows or using a spell
319 	 */
320 	void rangedAttack(PowType powNum);
321 
322 	/**
323 	 * Fires off a ranged attack at all oncoming monsters
324 	 */
325 	void shootRangedWeapon();
326 
327 	/**
328 	 * Returns true if there are any monsters in the vacinity
329 	 */
330 	bool areMonstersPresent() const;
331 };
332 
333 } // End of namespace Xeen
334 
335 #endif	/* XEEN_COMBAT_H */
336