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 ULTIMA4_GAME_SPELL_H
24 #define ULTIMA4_GAME_SPELL_H
25 
26 #include "ultima/ultima4/game/context.h"
27 #include "ultima/ultima4/map/location.h"
28 #include "ultima/ultima4/map/map.h"
29 #include "ultima/ultima4/filesys/savegame.h"
30 #include "ultima/ultima4/sound/sound.h"
31 
32 namespace Ultima {
33 namespace Ultima4 {
34 
35 enum SpellCastError {
36 	CASTERR_NOERROR,            /* success */
37 	CASTERR_NOMIX,              /* no mixture available */
38 	CASTERR_MPTOOLOW,           /* caster doesn't have enough mp */
39 	CASTERR_FAILED,             /* the spell failed */
40 	CASTERR_WRONGCONTEXT,       /* generic 'wrong-context' error (generrally finds the correct
41 								   context error message on its own) */
42 	CASTERR_COMBATONLY,         /* e.g. spell must be cast in combat */
43 	CASTERR_DUNGEONONLY,        /* e.g. spell must be cast in dungeons */
44 	CASTERR_WORLDMAPONLY       /* e.g. spell must be cast on the world map */
45 };
46 
47 /**
48  * Field types for the Energy field spell
49  */
50 enum EnergyFieldType {
51 	ENERGYFIELD_NONE,
52 	ENERGYFIELD_FIRE,
53 	ENERGYFIELD_LIGHTNING,
54 	ENERGYFIELD_POISON,
55 	ENERGYFIELD_SLEEP
56 };
57 
58 /**
59  * The ingredients for a spell mixture.
60  */
61 class Ingredients {
62 public:
63 	Ingredients();
64 	bool addReagent(Reagent reagent);
65 	bool removeReagent(Reagent reagent);
66 	int getReagent(Reagent reagent) const;
67 	void revert();
68 	bool checkMultiple(int mixes) const;
69 	void multiply(int mixes);
70 
71 private:
72 	unsigned short _reagents[REAG_MAX];
73 };
74 
75 class Spells;
76 typedef int (Spells::*SpellProc)(int);
77 
78 struct Spell {
79 	enum Param {
80 		PARAM_NONE,             ///< None
81 		PARAM_PLAYER,           ///< number of a player required
82 		PARAM_DIR,              ///< direction required
83 		PARAM_TYPEDIR,          ///< type of field and direction required (energy field)
84 		PARAM_PHASE,            ///< phase required (gate)
85 		PARAM_FROMDIR           ///< direction from required (winds)
86 	};
87 
88 	enum SpecialEffects {
89 		SFX_NONE,               ///< none
90 		SFX_INVERT,             ///< invert the screen (moongates, most normal spells)
91 		SFX_TREMOR              ///< tremor spell
92 	};
93 
94 	const char *_name;
95 	int _components;
96 	LocationContext _context;
97 	TransportContext _transportContext;
98 	SpellProc _spellFunc;
99 	Param _paramType;
100 	int _mp;
101 };
102 
103 typedef void (*SpellEffectCallback)(int spell, int player, Sound sound);
104 #define N_SPELLS 26
105 
106 class Spells {
107 private:
108 	static const Spell SPELL_LIST[N_SPELLS];
109 	SpellEffectCallback spellEffectCallback;
110 private:
111 	int spellAwaken(int player);
112 	int spellBlink(int dir);
113 	int spellCure(int player);
114 	int spellDispel(int dir);
115 	int spellEField(int param);
116 	int spellFireball(int dir);
117 	int spellGate(int phase);
118 	int spellHeal(int player);
119 	int spellIceball(int dir);
120 	int spellJinx(int unused);
121 	int spellKill(int dir);
122 	int spellLight(int unused);
123 	int spellMMissle(int dir);
124 	int spellNegate(int unused);
125 	int spellOpen(int unused);
126 	int spellProtect(int unused);
127 	int spellRez(int player);
128 	int spellQuick(int unused);
129 	int spellSleep(int unused);
130 	int spellTremor(int unused);
131 	int spellUndead(int unused);
132 	int spellView(int unsued);
133 	int spellWinds(int fromdir);
134 	int spellXit(int unused);
135 	int spellYup(int unused);
136 	int spellZdown(int unused);
137 private:
138 	CombatController *spellCombatController();
139 
140 	/**
141 	 * Makes a special magic ranged attack in the given direction
142 	 */
143 	void spellMagicAttack(const Common::String &tilename, Direction dir, int minDamage, int maxDamage);
144 	bool spellMagicAttackAt(const Coords &coords, MapTile attackTile, int attackDamage);
145 
146 	LocationContext spellGetContext(uint spell) const;
147 	TransportContext spellGetTransportContext(uint spell) const;
148 
149 	/**
150 	 * Returns true if the debugger is active
151 	 */
152 	bool isDebuggerActive() const;
153 public:
154 	/**
155 	 * Constructor
156 	 */
157 	Spells();
158 
159 	/**
160 	 * Destructor
161 	 */
162 	~Spells();
163 
164 	void spellSetEffectCallback(SpellEffectCallback callback);
165 
spellEffect(int spell,int player,Sound sound)166 	void spellEffect(int spell, int player, Sound sound) {
167 		(spellEffectCallback)(spell, player, sound);
168 	}
169 
170 	/**
171 	 * Mix reagents for a spell.  Fails and returns false if the reagents
172 	 * selected were not correct.
173 	 */
174 	int spellMix(uint spell, const Ingredients *ingredients);
175 
176 	/**
177 	 * Casts spell.  Fails and returns false if the spell cannot be cast.
178 	 * The error code is updated with the reason for failure.
179 	 */
180 	bool spellCast(uint spell, int character, int param, SpellCastError *error, bool spellEffect);
181 
182 	Common::String spellGetErrorMessage(uint spell, SpellCastError error);
183 
184 	const char *spellGetName(uint spell) const;
185 
186 	/**
187 	 * Checks some basic prerequistes for casting a spell.  Returns an
188 	 * error if no mixture is available, the context is invalid, or the
189 	 * character doesn't have enough magic points.
190 	 */
191 	SpellCastError spellCheckPrerequisites(uint spell, int character);
192 	Spell::Param spellGetParamType(uint spell) const;
193 	int spellGetRequiredMP(uint spell) const;
194 	const Spell *getSpell(int i) const;
195 };
196 
197 extern Spells *g_spells;
198 
199 } // End of namespace Ultima4
200 } // End of namespace Ultima
201 
202 #endif
203