1 /***************************************************************************
2                  spell.h  -  Spell and magic school classes
3                              -------------------
4     begin                : Sun Sep 28 2003
5     copyright            : (C) 2003 by Gabor Torok
6     email                : cctorok@yahoo.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #ifndef SPELL_H
18 #define SPELL_H
19 #pragma once
20 
21 #include <map>
22 #include <string>
23 #include <vector>
24 #include "../storable.h"
25 #include "../util.h"
26 
27 /// A dice. You know at least one belongs in every RPG.
28 class Dice {
29 private:
30 	enum { S_SIZE = 80 };
31 	char s[ S_SIZE ];
32 	int count;
33 	int sides;
34 	int mod;
35 
36 public:
37 	Dice( char const* s );
38 	Dice( int count, int sides, int mod );
39 	~Dice();
toString()40 	inline char *toString() {
41 		return s;
42 	}
roll()43 	inline int roll() {
44 		int n = 0;
45 		for ( int i = 0; i < count; i++ ) {
46 			n += Util::pickOne( 1, sides );
47 		}
48 		return n + mod;
49 	}
getMax()50 	inline int getMax() {
51 		return count * sides + mod;
52 	}
getMin()53 	inline int getMin() {
54 		return count + mod;
55 	}
getCount()56 	inline int getCount() {
57 		return count;
58 	}
getSides()59 	inline int getSides() {
60 		return sides;
61 	}
getMod()62 	inline int getMod() {
63 		return mod;
64 	}
65 };
66 
67 class MagicSchool;
68 
69 /// A magical spell.
70 class Spell : public Storable {
71 private:
72 	std::string name;
73 	std::string displayName;
74 	std::string sound;
75 	int level;
76 	int mp;
77 	int exp;
78 	int failureRate;
79 	Dice action;
80 	int distance;
81 	int targetType;
82 	char notes[1000];
83 	int speed;
84 	int effect;
85 	MagicSchool *school;
86 	bool creatureTarget, locationTarget, itemTarget, partyTarget, doorTarget;
87 	int iconTileX, iconTileY;
88 	bool friendly;
89 	int stateModPrereq;
90 	std::string symbol;
91 
92 	static std::map<std::string, Spell*> spellMap;
93 
94 public:
95 
96 	Spell( char const* name, char const* displayName, char const* symbol, int level, int mp, int exp, int failureRate, char const* action,
97 	       int distance, int targetType, int speed, int effect, bool creatureTarget,
98 	       bool locationTarget, bool itemTarget, bool partyTarget, bool doorTarget,
99 	       MagicSchool *school,
100 	       int iconTileX, int iconTileY, bool friendly, int stateModPrereq );
101 	~Spell();
102 
103 	/// The "symbol" of the spell (used in various descriptions).
getSymbol()104 	inline char const* getSymbol() {
105 		return symbol.c_str();
106 	}
getStorableType()107 	inline int getStorableType() {
108 		return Storable::SPELL_STORABLE;
109 	}
isStorable()110 	inline const char *isStorable() {
111 		return NULL;
112 	}
113 
114 	/// Is it for friendly or hostile targets?
isFriendly()115 	inline bool isFriendly() {
116 		return friendly;
117 	}
118 	/// Does it affect a state mod?
hasStateModPrereq()119 	inline bool hasStateModPrereq() {
120 		return( stateModPrereq != -1 );
121 	}
122 	/// Which state mod/potion skill is affected?
getStateModPrereq()123 	inline int getStateModPrereq() {
124 		return( stateModPrereq < -1 ?
125 		        ( -stateModPrereq ) - 2 : // potion skill
126 		        stateModPrereq ); // regular state mod
127 	}
128 	/// Does it affect a "potion skill" (HP, MP, armor)?
isStateModPrereqAPotionSkill()129 	inline bool isStateModPrereqAPotionSkill() {
130 		return( stateModPrereq < -1 );
131 	}
132 	/// Icon tile within spells.png.
getIconTileX()133 	inline int getIconTileX() {
134 		return iconTileX;
135 	}
136 	/// Icon tile within spells.png.
getIconTileY()137 	inline int getIconTileY() {
138 		return iconTileY;
139 	}
140 	/// Unlocalized internal name of the spell.
getName()141 	inline const char *getName() {
142 		return name.c_str();
143 	}
144 	/// Localized name of the spell.
getDisplayName()145 	inline const char *getDisplayName() {
146 		return displayName.c_str();
147 	}
148 	/// Returns a damage roll (without further modifiers).
getAction()149 	inline int getAction() {
150 		return action.roll();
151 	}
152 
153 	void getAttack( int casterLevel, float *maxP, float *minP );
154 
155 	/// The spell's level.
getLevel()156 	inline int getLevel()  {
157 		return level;
158 	}
159 	/// Magic point cost.
getMp()160 	inline int getMp() {
161 		return mp;
162 	}
163 	/// Experience gained by successfully casting the spell.
getExp()164 	inline int getExp() {
165 		return exp;
166 	}
167 	/// Probability of failure.
getFailureRate()168 	inline int getFailureRate() {
169 		return failureRate;
170 	}
171 	/// Action radius of the spell.
getDistance()172 	inline int getDistance() {
173 		return distance;
174 	}
175 	/// Which type of target is allowed?
getTargetType()176 	inline int getTargetType() {
177 		return targetType;
178 	}
179 	/// The spell's long description.
getNotes()180 	inline char const* getNotes() {
181 		return notes;
182 	}
183 	/// How fast can it be cast?
getSpeed()184 	inline int getSpeed() {
185 		return speed;
186 	}
187 	/// The visual effect displayed for the spell.
getEffect()188 	inline int getEffect() {
189 		return effect;
190 	}
191 	/// The spell's magic school.
getSchool()192 	inline MagicSchool *getSchool() {
193 		return school;
194 	}
195 	/// Unused.
isRangedSpell()196 	inline bool isRangedSpell() {
197 		return distance > 1;
198 	}
199 	/// Short one-line description of the spell.
describe(char * s,size_t count)200 	inline void describe( char *s, size_t count ) {
201 		snprintf( s, count, _( "%s (L:%d)(M:%d)" ), displayName.c_str(), level, mp );
202 	}
203 	/// Adds a string to the long description.
addNotes(char * s)204 	inline void addNotes( char *s ) {
205 		strcat( notes, s );
206 	}
207 	/// The sound to play when the spell is cast.
setSound(char const * s)208 	inline void setSound( char const* s ) {
209 		sound = s;
210 	}
getSound()211 	inline char const* getSound() {
212 		return sound.c_str();
213 	}
214 
215 	/// Can it target creatures?
isCreatureTargetAllowed()216 	inline bool isCreatureTargetAllowed() {
217 		return creatureTarget;
218 	}
219 	/// Can it target a map location (some point on the floor etc.)?
isLocationTargetAllowed()220 	inline bool isLocationTargetAllowed() {
221 		return locationTarget;
222 	}
223 	/// Can it target items?
isItemTargetAllowed()224 	inline bool isItemTargetAllowed() {
225 		return itemTarget;
226 	}
227 	/// Can it target a party member?
isPartyTargetAllowed()228 	inline bool isPartyTargetAllowed() {
229 		return partyTarget;
230 	}
231 	/// Can it target doors?
isDoorTargetAllowed()232 	inline bool isDoorTargetAllowed() {
233 		return doorTarget;
234 	}
235 
236 	static Spell *getSpellByName( char *name );
237 
238 };
239 
240 /// A magic school.
241 class MagicSchool {
242 private:
243 	std::string name;
244 	std::string displayName;
245 	std::string shortName;
246 	std::string deity;
247 	char deityDescription[3000];
248 	float red, green, blue;
249 	std::string symbol;
250 	int skill, resistSkill;
251 	std::vector<Spell*> spells;
252 	std::vector<std::string> lowDonate, neutralDonate, highDonate;
253 	float baseAlignment;
254 
255 	static MagicSchool *schools[10];
256 	static int schoolCount;
257 	static std::map<std::string, MagicSchool*> schoolMap;
258 
259 public:
260 	MagicSchool( char const* name, char const* displayName, char const* deity, int skill, int resistSkill, float alignment, float red, float green, float blue, char const* symbol );
261 	~MagicSchool();
262 
263 	/// The school's internal, unlocalized name.
getName()264 	inline char const* getName() {
265 		return name.c_str();
266 	}
267 	/// The school's localized name.
getDisplayName()268 	inline char const* getDisplayName() {
269 		return displayName.c_str();
270 	}
getShortName()271 	inline char const* getShortName() {
272 		return shortName.c_str();
273 	}
274 	/// Returns the deity associated to the school.
getDeity()275 	inline char const* getDeity() {
276 		return deity.c_str();
277 	}
278 	/// The associated deity's localized name.
getDeityDescription()279 	inline char *getDeityDescription() {
280 		return deityDescription;
281 	}
282 	/// The school's associated skill.
getSkill()283 	inline int getSkill() {
284 		return skill;
285 	}
286 	/// The skill used to resist spells from this school.
getResistSkill()287 	inline int getResistSkill() {
288 		return resistSkill;
289 	}
290 	/// Number of spells in this school.
getSpellCount()291 	inline int getSpellCount() {
292 		return spells.size();
293 	}
294 	/// Returns a spell from the school by index.
getSpell(int index)295 	inline Spell *getSpell( int index ) {
296 		return spells[index];
297 	}
298 	/// Adds a string to the description of the school's associated deity.
addToDeityDescription(char * s)299 	inline void addToDeityDescription( char *s ) {
300 		if ( strlen( deityDescription ) ) strcat( deityDescription, " " ); strcat( deityDescription, s );
301 	}
302 	/// The deity's color. Used to color the effect above pools for example.
getDeityRed()303 	inline float getDeityRed() {
304 		return red;
305 	}
getDeityGreen()306 	inline float getDeityGreen() {
307 		return green;
308 	}
getDeityBlue()309 	inline float getDeityBlue() {
310 		return blue;
311 	}
312 	/// The "symbol" of the school (used in various descriptions).
getSymbol()313 	inline char const* getSymbol() {
314 		return symbol.c_str();
315 	}
316 
317 	/// The base alignment (chaotic, neutral or lawful) of the school.
getBaseAlignment()318 	inline float getBaseAlignment() {
319 		return baseAlignment;
320 	}
321 
322 	static void initMagic();
323 	static void unInitMagic();
324 
325 	/// Number of magic schools in the game.
getMagicSchoolCount()326 	inline static int getMagicSchoolCount() {
327 		return schoolCount;
328 	}
329 	/// Gets magic school by index.
getMagicSchool(int index)330 	inline static MagicSchool *getMagicSchool( int index ) {
331 		return schools[index];
332 	}
333 	static Spell *getRandomSpell( int level );
334 	/// Gets magic school by its internal name.
getMagicSchoolByName(char const * s)335 	static MagicSchool *getMagicSchoolByName( char const* s ) {
336 		std::string name = s; return ( schoolMap.find( name ) == schoolMap.end() ? NULL : schoolMap[name] );
337 	}
338 	/// Returns a random magic school.
getRandomSchool()339 	static MagicSchool *getRandomSchool() {
340 		return getMagicSchool( getRandomSchoolIndex() );
341 	}
342 	/// Returns an index to a random magic school.
getRandomSchoolIndex()343 	static int getRandomSchoolIndex() {
344 		return Util::dice( schoolCount );
345 	}
346 
347 	const char *getLowDonateMessage();
348 	const char *getNeutralDonateMessage();
349 	const char *getHighDonateMessage();
350 
351 protected:
352 	/// Adds a spell to this school.
addSpell(Spell * spell)353 	inline void addSpell( Spell *spell ) {
354 		spells.push_back( spell );
355 	}
356 	const char *getRandomString( std::vector<std::string> *v );
357 
358 };
359 
360 #endif
361