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 * aint32 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 #include "saga2/saga2.h"
28 #include "saga2/spelshow.h"
29 #include "saga2/spelvals.h"
30 #include "saga2/tilevect.h"
31
32 namespace Saga2 {
33
34 // ------------------------------------------------------------------
35 // Spell Display Initialization handlers
36 //
37 // What is primarily done in these routines is to set up
38 // the positions, velocities & accelerations of the individual
39 // effectrons
40 // In most cases, once the effectrons are given their initial
41 // push they can be updated by just adding the velocity to the
42 // position.
43 // Sprite directionality is also set up here
44 //
45
46 /* ===================================================================== *
47 Inlines
48 * ===================================================================== */
49
50 #define randOff (randomVector(TilePoint(-1,-1,0),TilePoint(1,1,0)))
51
52 /* ===================================================================== *
53 Effect specific code
54 * ===================================================================== */
55
56 // ------------------------------------------------------------------
57 // null effect
58
SPELLINITFUNCTION(invisibleSpellInit)59 SPELLINITFUNCTION(invisibleSpellInit) {
60 effectron->velocity = TilePoint(0, 0, 0);
61 effectron->acceleration = TilePoint(0, 0, 0);
62 }
63
64 // ------------------------------------------------------------------
65 // aura that tracks target
66
SPELLINITFUNCTION(auraSpellInit)67 SPELLINITFUNCTION(auraSpellInit) {
68 if (effectron->parent->maxAge)
69 effectron->totalSteps = effectron->parent->maxAge;
70 else
71 effectron->totalSteps = 20;
72 effectron->current = effectron->parent->target->getPoint();
73 effectron->velocity = TilePoint(0, 0, 0);
74 effectron->acceleration = TilePoint(0, 0, 0);
75 }
76
77 // ------------------------------------------------------------------
78 // aura that tracks target (in front)
79
SPELLINITFUNCTION(glowSpellInit)80 SPELLINITFUNCTION(glowSpellInit) {
81 if (effectron->parent->maxAge)
82 effectron->totalSteps = effectron->parent->maxAge;
83 else
84 effectron->totalSteps = 20;
85 effectron->current = effectron->parent->target->getPoint() - TilePoint(1, 1, 0);
86 effectron->finish = effectron->current;
87 effectron->velocity = TilePoint(0, 0, 0);
88 effectron->acceleration = TilePoint(0, 0, 0);
89 }
90
91 // ------------------------------------------------------------------
92 // sprites that surround target
93
SPELLINITFUNCTION(wallSpellInit)94 SPELLINITFUNCTION(wallSpellInit) {
95 if (effectron->parent->maxAge)
96 effectron->totalSteps = effectron->parent->maxAge;
97 else
98 effectron->totalSteps = 20;
99 effectron->current = effectron->parent->target->getPoint();
100 effectron->velocity = WallVectors[effectron->partno] * wallSpellRadius / 3;
101 effectron->current = effectron->parent->target->getPoint() + effectron->velocity;
102 effectron->acceleration = TilePoint(0, 0, 0);
103 }
104
105 // ------------------------------------------------------------------
106 // projectile from caster to target
107
SPELLINITFUNCTION(projectileSpellInit)108 SPELLINITFUNCTION(projectileSpellInit) {
109 effectron->start = effectron->current;
110 effectron->finish = effectron->parent->target->getPoint();
111 TilePoint tp = (effectron->finish - effectron->start);
112 effectron->totalSteps = 1 + (tp.magnitude() / (2 * SpellJumpiness));
113 effectron->velocity = tp / effectron->totalSteps;
114 effectron->acceleration = TilePoint(0, 0, 0);
115 }
116
117 // ------------------------------------------------------------------
118 // bi-directional beams of energy
119
SPELLINITFUNCTION(exchangeSpellInit)120 SPELLINITFUNCTION(exchangeSpellInit) {
121 if (effectron->partno % 2) {
122 effectron->finish = effectron->current;
123 effectron->start = effectron->parent->target->getPoint();
124 } else {
125 effectron->start = effectron->current;
126 effectron->finish = effectron->parent->target->getPoint();
127 }
128 TilePoint tp = (effectron->finish - effectron->start);
129 effectron->totalSteps = 1 + (tp.magnitude() / (SpellJumpiness));
130 effectron->velocity = tp / effectron->totalSteps;
131 effectron->totalSteps += (effectron->partno / 2);
132 effectron->acceleration = TilePoint(0, 0, 0);
133 effectron->current = effectron->start;
134 }
135
136 // ------------------------------------------------------------------
137 // lightning bolt shaped spell
138
SPELLINITFUNCTION(boltSpellInit)139 SPELLINITFUNCTION(boltSpellInit) {
140 effectron->stepNo = 0;
141 if (effectron->parent->maxAge)
142 effectron->totalSteps = effectron->parent->maxAge;
143 else
144 effectron->totalSteps = 1 + (boltSpellLength / (SpellJumpiness * 3));
145
146 effectron->start = effectron->current;
147 effectron->finish = effectron->parent->target->getPoint();
148
149 TilePoint tVect = effectron->finish - effectron->start ;
150 setMagnitude(tVect, boltSpellLength);
151 TilePoint orth = rightVector(tVect, 0);
152 setMagnitude(orth, boltSpellWidth * (effectron->partno % 3 - 1) / 6);
153 TilePoint offVect = tVect * ((effectron->partno / 3) % 3) / (SpellJumpiness * 3);
154
155 effectron->start += orth;
156 effectron->finish += orth + offVect;
157
158 effectron->velocity = tVect / effectron->totalSteps + randOff;
159 effectron->acceleration = TilePoint(0, 0, 0);
160
161 effectron->current = effectron->start;
162 }
163
164 // ------------------------------------------------------------------
165 // narrow bolt
166
SPELLINITFUNCTION(beamSpellInit)167 SPELLINITFUNCTION(beamSpellInit) {
168 effectron->stepNo = 0;
169 if (effectron->parent->maxAge)
170 effectron->totalSteps = effectron->parent->maxAge;
171 else
172 effectron->totalSteps = 1 + (beamSpellLength / (SpellJumpiness));
173
174 effectron->start = effectron->current;
175 effectron->finish = effectron->parent->target->getPoint();
176
177 TilePoint tVect = effectron->finish - effectron->start ;
178 setMagnitude(tVect, beamSpellLength);
179 TilePoint orth = rightVector(tVect, 0);
180 setMagnitude(orth, beamSpellWidth / 2);
181
182 effectron->start += (tVect * effectron->partno) / effectron->totalSteps;
183 effectron->finish = effectron->start;
184
185 effectron->velocity = orth;
186 effectron->acceleration = TilePoint(0, 0, 0);
187
188 effectron->current = effectron->start;
189 }
190
191 // ------------------------------------------------------------------
192 // narrow cone shaped spell
193
SPELLINITFUNCTION(coneSpellInit)194 SPELLINITFUNCTION(coneSpellInit) {
195 effectron->stepNo = 0;
196 effectron->totalSteps = 1 + (coneSpellLength / (SpellJumpiness * 3));
197
198 effectron->start = effectron->current;
199 effectron->finish = effectron->parent->target->getPoint();
200
201 TilePoint tVect = effectron->finish - effectron->start ;
202 setMagnitude(tVect, coneSpellLength);
203 TilePoint orth = rightVector(tVect, 0);
204 setMagnitude(orth, coneSpellWidth * (effectron->partno % 9 - 4) / 8);
205
206 effectron->finish = effectron->start + tVect + orth;
207
208 effectron->velocity = (effectron->finish - effectron->start) / effectron->totalSteps + randOff;
209 effectron->acceleration = TilePoint(0, 0, 0);
210 }
211
212 // ------------------------------------------------------------------
213 // wide cone shaped spell
214
SPELLINITFUNCTION(waveSpellInit)215 SPELLINITFUNCTION(waveSpellInit) {
216 effectron->stepNo = 0;
217 effectron->totalSteps = 1 + (coneSpellLength / (SpellJumpiness * 2));
218
219 effectron->start = effectron->current;
220 effectron->finish = effectron->parent->target->getPoint();
221
222 TilePoint tVect = effectron->finish - effectron->start ;
223 setMagnitude(tVect, waveSpellLength);
224 TilePoint orth = rightVector(tVect, 0);
225 setMagnitude(orth, waveSpellWidth * (effectron->partno % 17 - 8) / 8);
226
227 effectron->finish = effectron->start + tVect + orth;
228
229 effectron->velocity = (effectron->finish - effectron->start) / effectron->totalSteps + randOff;
230 effectron->acceleration = TilePoint(0, 0, 0);
231 }
232
233 // ------------------------------------------------------------------
234 // small exploding ball
235
SPELLINITFUNCTION(ballSpellInit)236 SPELLINITFUNCTION(ballSpellInit) {
237 effectron->stepNo = 0;
238 effectron->start = effectron->current;
239 effectron->finish = FireballVectors[effectron->partno];
240 setMagnitude(effectron->finish, ballSpellRadius);
241 effectron->finish = effectron->finish + effectron->start;
242 effectron->totalSteps = 1 + (ballSpellRadius / SpellJumpiness);
243 effectron->acceleration = TilePoint(0, 0, 0);
244
245 TilePoint tp = (effectron->finish - effectron->start);
246 effectron->totalSteps = 1 + (tp.magnitude() / SpellJumpiness);
247 effectron->velocity = tp / effectron->totalSteps;
248 effectron->velocity.z = 0;
249 effectron->acceleration = TilePoint(0, 0, 0);
250 }
251
252 // ------------------------------------------------------------------
253 // square exploding ball
254
SPELLINITFUNCTION(squareSpellInit)255 SPELLINITFUNCTION(squareSpellInit) {
256 effectron->stepNo = 0;
257 effectron->start = effectron->current;
258 effectron->finish = SquareSpellVectors[effectron->partno];
259 setMagnitude(effectron->finish, effectron->finish.magnitude()*squareSpellSize / 4);
260 effectron->finish = effectron->finish + effectron->start;
261 effectron->totalSteps = 1 + (squareSpellSize / SpellJumpiness);
262 effectron->acceleration = TilePoint(0, 0, 0);
263
264 TilePoint tp = (effectron->finish - effectron->start);
265 effectron->totalSteps = 1 + (tp.magnitude() / SpellJumpiness);
266 effectron->velocity = tp / effectron->totalSteps;
267 effectron->velocity.z = 0;
268 effectron->acceleration = TilePoint(0, 0, 0);
269 }
270
271 // ------------------------------------------------------------------
272 // large exploding ball
273
SPELLINITFUNCTION(stormSpellInit)274 SPELLINITFUNCTION(stormSpellInit) {
275 effectron->stepNo = 0;
276 effectron->start = effectron->current;
277 effectron->finish = FireballVectors[effectron->partno];
278 setMagnitude(effectron->finish, ballSpellRadius);
279 effectron->finish = effectron->finish + effectron->start;
280 effectron->totalSteps = 1 + (ballSpellRadius / SpellJumpiness);
281 effectron->acceleration = TilePoint(0, 0, 0);
282
283 TilePoint tp = (effectron->finish - effectron->start);
284 effectron->totalSteps = 1 + (2 * tp.magnitude() / SpellJumpiness);
285 effectron->velocity = tp / effectron->totalSteps;
286 effectron->velocity.z = 0;
287 effectron->acceleration = TilePoint(0, 0, 0);
288 }
289
290 } // end of namespace Saga2
291