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  * Based on the original sources
23  *   Faery Tale II -- The Halls of the Dead
24  *   (c) 1993-1996 The Wyrmkeep Entertainment Co.
25  */
26 
27 #ifndef SAGA2_SPELSHOW_H
28 #define SAGA2_SPELSHOW_H
29 
30 #include "saga2/dispnode.h"
31 #include "saga2/speldefs.h"
32 
33 namespace Saga2 {
34 
35 //-----------------------------------------------------------------------
36 //	Effectron List
37 
38 typedef DisplayNodeList EffectronList;
39 
40 //-----------------------------------------------------------------------
41 // Spell control functions
42 //   Various instances of these can be used in different combinations to
43 //   yield different shaped spells. Each spell will need one each of
44 //   these types of functions:
45 //
46 //   Effectron Status
47 //     This returns the state of a given effectron as a function of time
48 //
49 //   Spell Spritation
50 //     Returns a sprite facing as a function of time.
51 //
52 //   Spell Location
53 //     Returns the position of the effectron as a function of time
54 //
55 //   Spell Height
56 //     This is NOT the effectron's Z coordinate. It is the height used
57 //     for collision detection purposes
58 //
59 //   Spell Breadth
60 //     This is the effectron's cross section for collision detection
61 //     purposes.
62 //
63 
64 //-----------------------------------------------------------------------
65 //	Spell Status
66 
67 typedef EffectronFlags SpellStatusFunction(Effectron *);
68 
69 #define SPELLSTATUSFUNCTION(fname) EffectronFlags fname( Effectron * effectron )
70 
71 //-----------------------------------------------------------------------
72 //	Spell Spritation
73 
74 typedef SpellPoseID SpellSpritationFunction(const Effectron *const);
75 
76 #define SPELLSPRITATIONFUNCTION(fname) SpellPoseID fname( const Effectron * const effectron )
77 
78 //-----------------------------------------------------------------------
79 //	Spell Location Calls
80 
81 typedef TilePoint SpellLocationFunction(const Effectron *const);
82 
83 #define SPELLLOCATIONFUNCTION(fname) TilePoint fname( const Effectron * const effectron )
84 
85 //-----------------------------------------------------------------------
86 //	Spell Height
87 
88 typedef spellHeight SpellHeightFunction(const Effectron *const);
89 
90 #define SPELLHEIGHTFUNCTION(fname) spellHeight fname( const Effectron * const effectron )
91 
92 //-----------------------------------------------------------------------
93 //	Spell width
94 
95 typedef spellBreadth SpellBreadthFunction(const Effectron *const);
96 
97 #define SPELLBREADTHFUNCTION(fname) spellBreadth fname( const Effectron * const effectron )
98 
99 //-----------------------------------------------------------------------
100 //	Spell init
101 
102 typedef void SpellInitFunction(Effectron *);
103 
104 #define SPELLINITFUNCTION(fname) void fname( Effectron * effectron )
105 
106 
107 //-----------------------------------------------------------------------
108 // EffectronDisplayPrototype
109 //   This tracks the functions needed to display a particular type of
110 //   spell on the screen. (Ball spells, bolt spells, etc)
111 //
112 
113 class EffectDisplayPrototype {
SPELLLOCATIONFUNCTION(nullLocation)114 	static SPELLLOCATIONFUNCTION(nullLocation) {
115 		return TilePoint(0, 0, 0);
116 	}
SPELLSPRITATIONFUNCTION(nullSpritation)117 	static SPELLSPRITATIONFUNCTION(nullSpritation) {
118 		return 0;
119 	}
SPELLSTATUSFUNCTION(nullStatus)120 	static SPELLSTATUSFUNCTION(nullStatus) {
121 		return effectronDead;
122 	}
SPELLHEIGHTFUNCTION(nullHeight)123 	static SPELLHEIGHTFUNCTION(nullHeight) {
124 		return 0;
125 	}
SPELLBREADTHFUNCTION(nullBreadth)126 	static SPELLBREADTHFUNCTION(nullBreadth) {
127 		return 0;
128 	}
SPELLINITFUNCTION(nullInit)129 	static SPELLINITFUNCTION(nullInit) {
130 	}
131 
132 	EffectID                ID;
133 public:
134 	int16                   nodeCount;
135 	EffectDisplayPrototype  *next;
136 
137 	SpellLocationFunction   *location;
138 	SpellSpritationFunction *spriteno;
139 	SpellStatusFunction     *status;
140 	SpellHeightFunction     *height;
141 	SpellBreadthFunction    *breadth;
142 	SpellInitFunction       *init;
143 
EffectDisplayPrototype()144 	EffectDisplayPrototype() {
145 		nodeCount = 0;
146 		next = NULL;
147 		location = &nullLocation;
148 		spriteno = &nullSpritation;
149 		status  = &nullStatus;
150 		height  = &nullHeight;
151 		breadth = &nullBreadth;
152 		init    = &nullInit;
153 	}
154 
155 	EffectDisplayPrototype(
156 	    int16                   nodes,
157 	    SpellLocationFunction   *newLocation,
158 	    SpellSpritationFunction *newSpriteno,
159 	    SpellStatusFunction     *newStatus,
160 	    SpellHeightFunction     *newHeight,
161 	    SpellBreadthFunction    *newBreadth,
162 	    SpellInitFunction       *newInit);
~EffectDisplayPrototype()163 	~EffectDisplayPrototype() {
164 		if (next) delete next;
165 		next = NULL;
166 	}
setID(EffectID i)167 	void setID(EffectID i) {
168 		ID = i;
169 	}
thisID(void)170 	EffectID thisID(void) {
171 		return ID;
172 	}
173 };
174 
175 typedef EffectDisplayPrototype *pEffectDisplayPrototype;
176 
177 //-----------------------------------------------------------------------
178 //	Effect Display Prototype List
179 //
180 // This class embodies a global list of EDPs
181 //
182 
183 
184 class EffectDisplayPrototypeList {
185 	pEffectDisplayPrototype         *effects;
186 	uint16                          count;
187 	uint16                          maxCount;
188 
189 public:
190 	EffectDisplayPrototypeList(int32 c);
191 	~EffectDisplayPrototypeList();
192 
193 	int32 add(EffectDisplayPrototype *edp) ;
194 	void cleanup(void);
195 	void append(EffectDisplayPrototype *edp, int32 acount);
196 	EffectDisplayPrototype *operator[](EffectID e);
197 };
198 
199 //-----------------------------------------------------------------------
200 //	Effectron collision flags
201 //
202 //  need to track whether things
203 //    bounce/die/stop/ignore
204 //  when hitting
205 //    actors/objects/terrain
206 //
207 
208 enum effectCollisionCont {
209 	ecFlagNone = 0,
210 	ecFlagBounce,
211 	ecFlagDie,
212 	ecFlagStop
213 };
214 
215 enum effectDirectionInit {
216 	diFlagZero = 0,
217 	diFlagInc = 1,
218 	diFlagInc2 = 2,
219 	diFlagInc3 = 3,
220 	diFlagInc4 = 4,
221 	diFlagRand = 5
222 };
223 
224 
225 //-----------------------------------------------------------------------
226 //  SpellDisplayPrototype
227 //	  All the information needed to display a spell
228 //    Combines a SpellEffectPrototype with the appropriate sprites
229 
230 class SpellDisplayPrototype {
231 	SpellID             ID;
232 public:
233 	EffectID            effect;        // Effect ID
234 	int32               effParm1;      //   effect setting 1
235 	int32               effParm2;      //   effect setting 1
236 	int32               effParm3;      //   effect setting 1
237 	int32               effParm4;      //   effect setting 1
238 
239 	effectDirectionInit scatter;       // direction init mode
240 	effectCollisionCont elasticity;    // collision flags
241 
242 	SpellAge            maxAge;        // auto self-destruct age
243 	SpellAge            implementAge;        // auto self-destruct age
244 	uint32              primarySpriteID;   // RES_ID(x, y, z, 0) to get sprites
245 	uint8               primarySpriteNo;   // sprites available
246 	uint32              secondarySpriteID;   // RES_ID(x, y, z, 0) to get sprites
247 	uint8               secondarySpriteNo;   // sprites available
248 	//uint8             effCount;      // effectrons to allocate
249 
250 	uint8               colorMap[4];          // indirect color map
251 	// full init
252 	SpellDisplayPrototype(
253 	    EffectID, int32, int32, int32, int32, effectDirectionInit,
254 	    effectCollisionCont, SpellAge, uint32, uint8, uint8);
255 
256 	SpellDisplayPrototype(ResourceSpellItem *rsi);
257 
258 	void getColorTranslation(ColorTable mainColors, Effectron *);        // colors for effectrons
setID(SpellID i)259 	void setID(SpellID i) {
260 		ID = i;
261 	}
thisID(void)262 	SpellID thisID(void) {
263 		return ID;
264 	}
265 };
266 
267 //-----------------------------------------------------------------------
268 //	SpellDisplayPrototypeList
269 //    A global list of sdp's
270 
271 typedef SpellDisplayPrototype *pSpellDisplayPrototype;
272 
273 class SpellDisplayPrototypeList {
274 	pSpellDisplayPrototype              *spells;
275 	uint16                              count;
276 	uint16                              maxCount;
277 
278 public:
279 	SpellDisplayPrototypeList(uint16 s);
280 	~SpellDisplayPrototypeList();
281 
282 	void init(void);
283 	void cleanup(void);
284 	int32 add(SpellDisplayPrototype *sdp);
285 	SpellDisplayPrototype *operator[](SpellID s);
286 };
287 
288 //-----------------------------------------------------------------------
289 //	SpellInstance
290 //    When a SpellDisplayPrototype is instantiated, one of these is created
291 //    and the main display loop updates it till it dies
292 
293 class SpellInstance {
294 	friend struct StorageSpellInstance;
295 
296 	SpellAge                implementAge;   // age at which to implement the spell effects
297 public:
298 	EffectDisplayPrototype  *effect;        // effect prototype of the current effect
299 	SpellDisplayPrototype   *dProto;        // effect prototype of the current effect
300 	SpellCaster            *caster;
301 	SpellTarget            *target;
302 	GameWorld              *world;
303 	SpellAge                age;
304 	EffectronList           eList;
305 	SpellID                 spell;
306 	SpellAge                maxAge;
307 	int16                   effSeq;         // which effect in a sequence is being played
308 
309 	SpellInstance(SpellCaster *newCaster, SpellTarget *newTarget, SpellID);
310 	SpellInstance(SpellCaster *newCaster, GameObject  &newTarget, SpellID);
311 	SpellInstance(SpellCaster *newCaster, GameObject  *newTarget, SpellID);
312 	SpellInstance(SpellCaster *newCaster, TilePoint   &newTarget, SpellID);
313 	SpellInstance(StorageSpellInstance &ssi);
314 	~SpellInstance();
315 
316 	void init(void);
317 	void initEffect(TilePoint);
318 	void readEffect(Common::InSaveFile *in, uint16 eListSize);
319 	void writeEffect(Common::MemoryWriteStreamDynamic *out);
320 	void termEffect(void);
321 	size_t saveSize(void);
322 
323 	bool buildList(void);
324 	bool updateStates(int32 deltaTime);
325 };
326 
327 //-----------------------------------------------------------------------
328 //	SpellDisplayList
329 //    This class is used to keep track of all the spells currently
330 //    displaying effectrons
331 
332 typedef SpellInstance *pSpellInstance;
333 
334 class SpellDisplayList {
335 	uint16                      count;
336 	uint16                      maxCount;
337 public :
338 	pSpellInstance              *spells;
339 
340 	void init(void);
341 	void cleanup(void);
342 	SpellDisplayList(uint16 s);
343 	~SpellDisplayList();
344 
345 	void add(SpellInstance *newSpell);
346 
347 	void tidyKill(uint16 spellNo);
348 
349 	void buildList(void);
350 	void updateStates(int32 deltaTime);
351 
352 	void write(Common::OutSaveFile *outD);
353 	void read(Common::InSaveFile *in);
354 	void wipe(void);
355 	size_t saveSize(void);
356 };
357 
358 
359 /* ===================================================================== *
360    Inlines
361  * ===================================================================== */
362 
363 //-----------------------------------------------------------------------
364 // Some functions that require the above definitions to work
365 
world(void)366 inline GameWorld *Effectron::world(void) const {
367 	return parent->world;
368 }
getMapNum(void)369 inline int16 Effectron::getMapNum(void) const {
370 	return parent->world->mapNum;
371 }
372 
spellID(void)373 inline EffectID Effectron::spellID(void) {
374 	return parent->spell;
375 }
spell(void)376 inline SpellDisplayPrototype *Effectron::spell(void) {
377 	return (*g_vm->_sdpList)[(SpellID) spellID()];
378 }
effectID(void)379 inline EffectID Effectron::effectID(void) {
380 	return spell()->effect;
381 }
effect(void)382 inline EffectDisplayPrototype *Effectron::effect(void) {
383 	return parent->effect;
384 }
staCall(void)385 inline EffectronFlags Effectron::staCall(void) {
386 	return parent->effect->status(this);
387 }
posCall(void)388 inline TilePoint Effectron::posCall(void) {
389 	return parent->effect->location(this);
390 }
sprCall(void)391 inline SpellSpritationSeed Effectron::sprCall(void) {
392 	return parent->effect->spriteno(this);
393 }
hgtCall(void)394 inline spellHeight Effectron::hgtCall(void) {
395 	return parent->effect->height(this);
396 }
brdCall(void)397 inline spellBreadth Effectron::brdCall(void) {
398 	return parent->effect->breadth(this);
399 }
initCall(int16 eno)400 inline void Effectron::initCall(int16 eno) {
401 	partno = eno;
402 	parent->effect->init(this);
403 }
404 
405 /* ===================================================================== *
406    prototypes
407  * ===================================================================== */
408 
409 int16 whichColorMap(EffectID eid, const Effectron *const effectron);
410 
411 //-----------------------------------------------------------------------
412 // Spell building block functions
413 //   These are the functions available to update various aspects
414 //   of Effectrons
415 
416 SPELLSTATUSFUNCTION(invisibleSpellSta);
417 SPELLSTATUSFUNCTION(auraSpellSta);
418 SPELLSTATUSFUNCTION(projectileSpellSta);
419 SPELLSTATUSFUNCTION(exchangeSpellSta);
420 SPELLSTATUSFUNCTION(boltSpellSta);
421 SPELLSTATUSFUNCTION(coneSpellSta);
422 SPELLSTATUSFUNCTION(ballSpellSta);
423 SPELLSTATUSFUNCTION(squareSpellSta);
424 SPELLSTATUSFUNCTION(waveSpellSta);
425 SPELLSTATUSFUNCTION(stormSpellSta);
426 SPELLSTATUSFUNCTION(beamSpellSta);
427 SPELLSTATUSFUNCTION(wallSpellSta);
428 
429 SPELLLOCATIONFUNCTION(invisibleSpellPos);
430 SPELLLOCATIONFUNCTION(auraSpellPos);
431 SPELLLOCATIONFUNCTION(projectileSpellPos);
432 SPELLLOCATIONFUNCTION(exchangeSpellPos);
433 SPELLLOCATIONFUNCTION(boltSpellPos);
434 SPELLLOCATIONFUNCTION(coneSpellPos);
435 SPELLLOCATIONFUNCTION(ballSpellPos);
436 SPELLLOCATIONFUNCTION(squareSpellPos);
437 SPELLLOCATIONFUNCTION(waveSpellPos);
438 SPELLLOCATIONFUNCTION(stormSpellPos);
439 SPELLLOCATIONFUNCTION(beamSpellPos);
440 SPELLLOCATIONFUNCTION(wallSpellPos);
441 SPELLLOCATIONFUNCTION(glowSpellPos);
442 
443 SPELLSPRITATIONFUNCTION(invisibleSprites);
444 SPELLSPRITATIONFUNCTION(auraSprites);
445 SPELLSPRITATIONFUNCTION(projectileSprites);
446 SPELLSPRITATIONFUNCTION(exchangeSprites);
447 SPELLSPRITATIONFUNCTION(boltSprites);
448 SPELLSPRITATIONFUNCTION(coneSprites);
449 SPELLSPRITATIONFUNCTION(ballSprites);
450 SPELLSPRITATIONFUNCTION(squareSprites);
451 SPELLSPRITATIONFUNCTION(waveSprites);
452 SPELLSPRITATIONFUNCTION(stormSprites);
453 SPELLSPRITATIONFUNCTION(beamSprites);
454 SPELLSPRITATIONFUNCTION(wallSprites);
455 
456 SPELLHEIGHTFUNCTION(ShortTillThere);
457 SPELLHEIGHTFUNCTION(GrowLinear);
458 SPELLBREADTHFUNCTION(StaticHeight);
459 
460 SPELLBREADTHFUNCTION(ThinTillThere);
461 SPELLBREADTHFUNCTION(BulkLinear);
462 SPELLBREADTHFUNCTION(StaticBreadth);
463 
464 SPELLINITFUNCTION(invisibleSpellInit);
465 SPELLINITFUNCTION(auraSpellInit);
466 SPELLINITFUNCTION(projectileSpellInit);
467 SPELLINITFUNCTION(exchangeSpellInit);
468 SPELLINITFUNCTION(boltSpellInit);
469 SPELLINITFUNCTION(coneSpellInit);
470 SPELLINITFUNCTION(ballSpellInit);
471 SPELLINITFUNCTION(squareSpellInit);
472 SPELLINITFUNCTION(waveSpellInit);
473 SPELLINITFUNCTION(stormSpellInit);
474 SPELLINITFUNCTION(glowSpellInit);
475 SPELLINITFUNCTION(beamSpellInit);
476 SPELLINITFUNCTION(wallSpellInit);
477 
478 } // end of namespace Saga2
479 
480 #endif  //SPELLBUK_H
481