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