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 * Originally written by Syn9 in FreeBASIC with SDL
23 * http://syn9.thehideoutgames.com/index_backup.php
24 *
25 * Ported to plain C for GCW-Zero handheld by Dmitry Smagin
26 * http://github.com/dmitrysmagin/griffon_legend
27 *
28 *
29 * Programming/Graphics: Daniel "Syn9" Kennedy
30 * Music/Sound effects: David Turner
31 *
32 * Beta testing and gameplay design help:
33 * Deleter, Cha0s, Aether Fox, and Kiz
34 *
35 */
36
37 #include "griffon/griffon.h"
38
39 namespace Griffon {
40
41 // memo
42
43 /*
44 chests
45 0 - regular flask
46 11 - key chest
47 14 - blue flask chest
48 15 - lightning chest
49 16 - armour chest
50 17 - citadel master key
51 18 - sword3
52 19 - shield3
53 20 - armour3
54
55 */
56
57 // element tile locations
58 const int8 elementmap[15][20] = {
59 { 2, 2, 2, 2, -1, -1, -1, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1 },
60 { 2, -1, -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1 },
61 { 2, -1, 2, 2, -1, -1, -1, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1 },
62 { 2, -1, 2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
63 { 2, 2, 2, 2, 2, -1, -1, -1, 2, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1 },
64 { -1, -1, -1, -1, 2, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
65 { -1, -1, -1, -1, -1, 0, 0, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
66 { -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
67 { -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
68 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
69 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
70 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
71 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
72 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
73 { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
74 };
75
76
updateAnims()77 void GriffonEngine::updateAnims() {
78 for (int i = 0; i <= _lastObj; i++) {
79 int nFrames = _objectInfo[i].nFrames;
80 int objAnimSpeed = _objectInfo[i].speed;
81 float frame = _objectFrame[i][0];
82
83 if (nFrames > 1) {
84 frame += objAnimSpeed / 50 * _fpsr;
85 while (frame >= nFrames)
86 frame -= nFrames;
87
88 int cframe = (int)frame; // truncate fractional part
89 if (cframe < 0)
90 cframe = 0;
91
92 _objectFrame[i][0] = frame;
93 _objectFrame[i][1] = cframe;
94 }
95 }
96 }
97
updateY()98 void GriffonEngine::updateY() {
99 for (int i = 0; i <= 2400; i++)
100 _ysort[i] = -1;
101
102 int ff = (int)(_player.py * 10);
103 if (ff < 0) // HACKFIX or _ysort[yy] may go out of bounds
104 ff = 0;
105 _player.ysort = ff;
106 _ysort[ff] = 0;
107
108 _firsty = 2400;
109 _lasty = 0;
110
111 for (int i = 1; i <= _lastNpc; i++) {
112 if (!_npcInfo[i].onMap)
113 continue;
114
115 int yy = (int)(_npcInfo[i].y * 10);
116
117 do {
118 if (_ysort[yy] == -1 || yy == 2400)
119 break;
120 ++yy;
121 } while (1);
122
123 _ysort[yy] = i;
124 if (yy < _firsty)
125 _firsty = yy;
126 if (yy > _lasty)
127 _lasty = yy;
128 }
129 }
130
updateNPCs()131 void GriffonEngine::updateNPCs() {
132 for (int i = 1; i <= _lastNpc; i++) {
133 if (_npcInfo[i].hp > 0) {
134 // is npc walking
135 int pass = 0;
136 if (!_npcInfo[i].attacking)
137 pass = 1;
138 if (_npcInfo[i].spriteset == kMonsterFireHydra)
139 pass = 1;
140 if (pass == 1) {
141 bool moveup = false;
142 bool movedown = false;
143 bool moveleft = false;
144 bool moveright = false;
145
146 float npx = _npcInfo[i].x;
147 float npy = _npcInfo[i].y;
148
149 float onpx = npx;
150 float onpy = npy;
151
152 float wspd = _npcInfo[i].walkspd / 4;
153
154 if (_npcInfo[i].spriteset == kMonsterDragon2)
155 wspd = wspd * 2;
156 int wdir = _npcInfo[i].walkdir;
157
158 int mode = _npcInfo[i].movementmode;
159
160 float xdif = _player.px - npx;
161 float ydif = _player.py - npy;
162
163 if (ABS(xdif) < 4 * 16 && ABS(ydif) < 4 * 16 && mode < 3)
164 mode = 0;
165 if (_npcInfo[i].hp < _npcInfo[i].maxhp * 0.25)
166 mode = 3;
167
168 if (_npcInfo[i].pause > _ticks)
169 mode = -1;
170 if (_npcInfo[i].spriteset == kMonsterOneWing && _npcInfo[i].castPause > _ticks)
171 mode = -1;
172
173 if (mode == 3) {
174 mode = 1;
175 if (ABS(xdif) < 4 * 16 && ABS(ydif) < 4 * 16)
176 mode = 3;
177 }
178
179 bool checkpass = false;
180
181 // npc AI CODE
182 // --------------
183
184 // *** aggressive
185 if (mode == 0) {
186 wspd = _npcInfo[i].walkspd / 2;
187
188 xdif = _player.px - npx;
189 ydif = _player.py - npy;
190
191 if (ABS(xdif) > ABS(ydif)) {
192 if (xdif < 4)
193 wdir = 2;
194 if (xdif > -4)
195 wdir = 3;
196 } else {
197 if (ydif < 4)
198 wdir = 0;
199 if (ydif > -4)
200 wdir = 1;
201 }
202
203 if (xdif < 4)
204 moveleft = true;
205 if (xdif > -4)
206 moveright = true;
207 if (ydif < 4)
208 moveup = true;
209 if (ydif > -4)
210 movedown = true;
211 }
212 // *******************
213
214 // *** defensive
215 if (mode == 1) {
216
217 int movingdir = _npcInfo[i].movingdir;
218
219 if (_npcInfo[i].ticks > _ticks + 100000)
220 _npcInfo[i].ticks = _ticks;
221
222 if (_npcInfo[i].ticks < _ticks) {
223 _npcInfo[i].ticks = _ticks + 2000;
224 movingdir = (int)(RND() * 8);
225 _npcInfo[i].movingdir = movingdir;
226 }
227
228 if (movingdir == 0) {
229 wdir = 2; // left
230 moveup = true;
231 moveleft = true;
232 } else if (movingdir == 1) {
233 wdir = 0; // up
234 moveup = true;
235 } else if (movingdir == 2) {
236 wdir = 3; // right
237 moveup = true;
238 moveright = true;
239 } else if (movingdir == 3) {
240 wdir = 3; // right
241 moveright = true;
242 } else if (movingdir == 4) {
243 wdir = 3; // right
244 moveright = true;
245 movedown = true;
246 } else if (movingdir == 5) {
247 wdir = 1; // down
248 movedown = true;
249 } else if (movingdir == 6) {
250 wdir = 2; // left
251 movedown = true;
252 moveleft = true;
253 } else if (movingdir == 7) {
254 wdir = 2; // left
255 moveleft = true;
256 }
257
258 checkpass = true;
259 }
260 // *******************
261
262 // *** run away
263 if (mode == 3) {
264 wspd = _npcInfo[i].walkspd / 2;
265
266 xdif = _player.px - npx;
267 ydif = _player.py - npy;
268
269 if (ABS(xdif) > ABS(ydif)) {
270 if (xdif < 4)
271 wdir = 3;
272 if (xdif > -4)
273 wdir = 2;
274 } else {
275 if (ydif < 4)
276 wdir = 1;
277 if (ydif > -4)
278 wdir = 0;
279 }
280
281 if (xdif < 4)
282 moveright = true;
283 if (xdif > -4)
284 moveleft = true;
285 if (ydif < 4)
286 movedown = true;
287 if (ydif > -4)
288 moveup = true;
289 }
290 // *******************
291
292 // -------------- ?? move*** vs movin***
293 bool movinup = false;
294 bool movindown = false;
295 bool movinleft = false;
296 bool movinright = false;
297
298 float xp = (npx / 2 + 6);
299 float yp = (npy / 2 + 10);
300
301 if (_npcInfo[i].spriteset == kMonsterDragon2)
302 wspd = wspd * 2;
303
304 float ii = wspd * _fpsr;
305 if (ii < 1)
306 ii = 1;
307
308 if (moveup) {
309 int sx = xp;
310 int sy = yp - ii;
311 uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
312 uint32 dq = *temp;
313 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
314 dq = 0;
315
316 if (dq == 0)
317 movinup = true;
318 if (dq > 0) {
319 sx = xp - ii;
320 sy = yp - ii;
321 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
322 dq = *temp;
323 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
324 dq = 0;
325 if (dq == 0) {
326 movinup = true;
327 movinleft = true;
328 }
329 }
330 if (dq > 0) {
331 sx = xp + ii;
332 sy = yp - ii;
333 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
334 dq = *temp;
335 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
336 dq = 0;
337 if (dq == 0) {
338 movinup = true;
339 movinright = true;
340 }
341 }
342 }
343
344 if (movedown) {
345 int sx = xp;
346 int sy = yp + ii;
347 uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
348 uint32 dq = *temp;
349 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
350 dq = 0;
351 if (dq == 0)
352 movindown = true;
353 if (dq > 0) {
354 sx = xp - ii;
355 sy = yp + ii;
356 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
357 dq = *temp;
358 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
359 dq = 0;
360 if (dq == 0) {
361 movindown = true;
362 movinleft = true;
363 }
364 }
365 if (dq > 0) {
366 sx = xp + ii;
367 sy = yp + ii;
368 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
369 dq = *temp;
370 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
371 dq = 0;
372 if (dq == 0) {
373 movindown = true;
374 movinright = true;
375 }
376 }
377 }
378
379 if (moveleft) {
380 int sx = xp - ii;
381 int sy = yp;
382 uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
383 uint32 dq = *temp;
384 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
385 dq = 0;
386 if (dq == 0)
387 movinleft = true;
388 if (dq > 0) {
389 sx = xp - ii;
390 sy = yp - ii;
391 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
392 dq = *temp;
393 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
394 dq = 0;
395 if (dq == 0) {
396 movinleft = true;
397 movinup = true;
398 }
399 }
400 if (dq > 0) {
401 sx = xp - ii;
402 sy = yp + ii;
403 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
404 dq = *temp;
405 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
406 dq = 0;
407 if (dq == 0) {
408 movinleft = true;
409 movindown = true;
410 }
411 }
412 }
413
414 if (moveright) {
415 int sx = xp + ii;
416 int sy = yp;
417 uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
418 uint32 dq = *temp;
419 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
420 dq = 0;
421 if (dq == 0)
422 movinright = true;
423 if (dq > 0) {
424 sx = xp + ii;
425 sy = yp - ii;
426 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
427 dq = *temp;
428 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
429 dq = 0;
430 if (dq == 0) {
431 movinright = true;
432 movinup = true;
433 }
434 }
435 if (dq > 0) {
436 sx = xp + ii;
437 sy = yp + ii;
438 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
439 dq = *temp;
440 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
441 dq = 0;
442 if (dq == 0) {
443 movinright = true;
444 movindown = true;
445 }
446 }
447 }
448
449 if (movinup)
450 npy -= wspd * _fpsr;
451 if (movindown)
452 npy += wspd * _fpsr;
453 if (movinleft)
454 npx -= wspd * _fpsr;
455 if (movinright)
456 npx += wspd * _fpsr;
457
458 if (checkpass) {
459 pass = 0;
460 if (npx >= _npcInfo[i].x1 * 16 - 8 && npx <= _npcInfo[i].x2 * 16 + 8 && npy >= _npcInfo[i].y1 * 16 - 8 && npy <= _npcInfo[i].y2 * 16 + 8)
461 pass = 1;
462 if (pass == 0) {
463 npx = onpx;
464 npy = onpy;
465 _npcInfo[i].ticks = _ticks;
466 }
467 }
468
469 float aspd = wspd;
470
471 if (_npcInfo[i].spriteset == kMonsterDragon2)
472 aspd = wspd / 2;
473
474 xp = (npx / 2 + 6);
475 yp = (npy / 2 + 10);
476
477 int sx = xp;
478 int sy = yp;
479 uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
480 uint32 bgc = *temp;
481
482 float anpx = npx + 12;
483 float anpy = npy + 20;
484
485 int lx = (int)anpx / 16;
486 int ly = (int)anpy / 16;
487
488 if (_triggerLoc[lx][ly] > -1)
489 bgc = 1;
490 if (_npcInfo[i].spriteset == kMonsterFinalBoss)
491 bgc = 0;
492
493 bool rst = false;
494
495 if (_npcInfo[i].spriteset == kMonsterFinalBoss) {
496 if (npx < 40 || npx > 280 || npy < 36 || npy > 204)
497 rst = true;
498 }
499
500 if (bgc > 0 || rst) {
501 npx = onpx;
502 npy = onpy;
503 }
504
505 _npcInfo[i].x = npx;
506 _npcInfo[i].y = npy;
507
508 _npcInfo[i].walkdir = wdir;
509 _npcInfo[i].moving = false;
510
511 if (npx != onpx || npy != onpy)
512 _npcInfo[i].moving = true;
513
514 if (_npcInfo[i].moving) {
515 float frame = _npcInfo[i].frame;
516
517 frame += aspd * _fpsr;
518 while (frame >= 16)
519 frame -= 16;
520
521 int cframe = (int)(frame);
522 if (cframe < 0)
523 cframe = 0;
524
525 _npcInfo[i].frame = frame;
526 _npcInfo[i].cframe = cframe;
527 }
528
529 // spriteset1 specific
530 if (_npcInfo[i].spriteset == kMonsterBabyDragon && _npcInfo[i].attackattempt < _ticks) {
531 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
532 npx = _npcInfo[i].x;
533 npy = _npcInfo[i].y;
534
535 xdif = _player.px - npx;
536 ydif = _player.py - npy;
537
538 if (ABS(xdif) < 20 && ABS(ydif) < 20) {
539 _npcInfo[i].attackattempt = _ticks + 100;
540 if ((int)(RND() * 2) == 0) {
541 if (config.effects) {
542 int snd = playSound(_sfx[kSndEnemyHit]);
543 setChannelVolume(snd, config.effectsVol);
544 }
545
546 _npcInfo[i].attacking = true;
547 _npcInfo[i].attackframe = 0;
548 }
549 }
550 }
551 }
552
553 bool dospell = false;
554
555 // onewing specific
556 if (_npcInfo[i].spriteset == kMonsterOneWing) {
557 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
558 npx = _npcInfo[i].x;
559 npy = _npcInfo[i].y;
560
561 xdif = _player.px - npx;
562 ydif = _player.py - npy;
563
564 if (ABS(xdif) < 24 && ABS(ydif) < 24) {
565 float dist = sqrt(xdif * xdif + ydif * ydif);
566
567 if ((dist) < 24) {
568 if (config.effects) {
569 int snd = playSound(_sfx[kSndBite]);
570 setChannelVolume(snd, config.effectsVol);
571 }
572
573 _npcInfo[i].attacking = true;
574 _npcInfo[i].attackframe = 0;
575
576 _npcInfo[i].headTargetX[0] = _player.px + 12;
577 _npcInfo[i].headTargetY[0] = _player.py - 4;
578 }
579 }
580
581 }
582
583 dospell = false;
584
585 if (!_npcInfo[i].attacking && _npcInfo[i].castPause < _ticks) {
586 _npcInfo[i].swaySpeed = _npcInfo[i].swaySpeed + _npcInfo[i].swaySpeed / 200 * _fpsr;
587 if (_npcInfo[i].swaySpeed > 15) {
588 dospell = true;
589 _npcInfo[i].swaySpeed = 1;
590 }
591
592 // sway code
593 _npcInfo[i].swayAngle = _npcInfo[i].swayAngle + _npcInfo[i].swaySpeed * _fpsr;
594 if (_npcInfo[i].swayAngle >= 360)
595 _npcInfo[i].swayAngle = _npcInfo[i].swayAngle - 360;
596
597 _npcInfo[i].headTargetX[0] = _npcInfo[i].x + (24 - _npcInfo[i].swaySpeed / 2) * sin(3.14159 / 180 * _npcInfo[i].swayAngle) + 12;
598 _npcInfo[i].headTargetY[0] = _npcInfo[i].y - 36 + 16 + 8 * sin(3.14159 * 2 / 180 * _npcInfo[i].swayAngle);
599 }
600
601 if (dospell) {
602 _npcInfo[i].pause = _ticks + 3000;
603 _npcInfo[i].attacknext = _ticks + 4500;
604 _npcInfo[i].castPause = _ticks + 4500;
605
606 castSpell(3, _npcInfo[i].x, _npcInfo[i].y, _npcInfo[i].x, _npcInfo[i].y, i);
607
608 _npcInfo[i].headTargetX[0] = _npcInfo[i].x;
609 _npcInfo[i].headTargetY[0] = _npcInfo[i].y - 36 + 16;
610 }
611
612 // targethead code
613 xdif = _npcInfo[i].bodysection[7].x - _npcInfo[i].headTargetX[0];
614 ydif = _npcInfo[i].bodysection[7].y - _npcInfo[i].headTargetY[0];
615
616
617 _npcInfo[i].bodysection[7].x = _npcInfo[i].bodysection[7].x - xdif * 0.4 * _fpsr;
618 _npcInfo[i].bodysection[7].y = _npcInfo[i].bodysection[7].y - ydif * 0.4 * _fpsr;
619
620
621 _npcInfo[i].bodysection[0].x = _npcInfo[i].x + 12;
622 _npcInfo[i].bodysection[0].y = _npcInfo[i].y + 12;
623
624 for (int f = 6; f >= 1; f--) {
625 xdif = _npcInfo[i].bodysection[f + 1].x - _npcInfo[i].bodysection[f - 1].x;
626 ydif = _npcInfo[i].bodysection[f + 1].y - _npcInfo[i].bodysection[f - 1].y;
627
628 float tx = _npcInfo[i].bodysection[f - 1].x + xdif / 2;
629 float ty = _npcInfo[i].bodysection[f - 1].y + ydif / 2;
630
631 _npcInfo[i].bodysection[f].x = _npcInfo[i].bodysection[f].x - (_npcInfo[i].bodysection[f].x - tx) / 3;
632 _npcInfo[i].bodysection[f].y = _npcInfo[i].bodysection[f].y - (_npcInfo[i].bodysection[f].y - ty) / 3;
633 }
634 }
635
636 // boss1 specific and blackknight
637 if (_npcInfo[i].spriteset == kMonsterBoss1 || _npcInfo[i].spriteset == kMonsterBlackKnight) {
638 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
639 _npcInfo[i].attacking = true;
640 _npcInfo[i].attackframe = 0;
641
642 castSpell(1, _npcInfo[i].x, _npcInfo[i].y, _player.px, _player.py, i);
643 }
644
645 if (_npcInfo[i].castPause < _ticks) {
646 castSpell(6, _npcInfo[i].x, _npcInfo[i].y, _player.px, _player.py, i);
647 _npcInfo[i].castPause = _ticks + 12000;
648 }
649 }
650
651
652 // firehydra specific
653 if (_npcInfo[i].spriteset == kMonsterFireHydra) {
654 _npcInfo[i].swaySpeed = 4;
655
656 // sway code
657 _npcInfo[i].swayAngle = _npcInfo[i].swayAngle + _npcInfo[i].swaySpeed * _fpsr;
658 if (_npcInfo[i].swayAngle >= 360)
659 _npcInfo[i].swayAngle = _npcInfo[i].swayAngle - 360;
660
661 for (int ff = 0; ff <= 2; ff++) {
662 if (_npcInfo[i].hp > 10 * ff * 20) {
663 if (_npcInfo[i].pause < _ticks && _npcInfo[i].attacking2[ff] == 0 && _npcInfo[i].attacknext2[ff] < _ticks) {
664 npx = _npcInfo[i].x;
665 npy = _npcInfo[i].y;
666
667 xdif = _player.px - npx;
668 ydif = _player.py - npy;
669
670 if (ABS(xdif) < 48 && ABS(ydif) < 48) {
671 float dist = sqrt(xdif * xdif + ydif * ydif);
672
673 if ((dist) < 36) {
674 if (config.effects) {
675 int snd = playSound(_sfx[kSndBite]);
676 setChannelVolume(snd, config.effectsVol);
677 }
678
679 _npcInfo[i].attacking = true;
680 _npcInfo[i].attacking2[ff] = 1;
681 _npcInfo[i].attackframe2[ff] = 0;
682
683 _npcInfo[i].headTargetX[ff] = _player.px + 12;
684 _npcInfo[i].headTargetY[ff] = _player.py - 4;
685
686 _npcInfo[i].swayAngle = 0;
687 }
688 }
689
690 }
691
692 if (_npcInfo[i].attacking2[ff] == 0) {
693 _npcInfo[i].headTargetX[ff] = _npcInfo[i].x + 38 * sin(3.14159 / 180 * (_npcInfo[i].swayAngle + 120 * ff)) + 12;
694 _npcInfo[i].headTargetY[ff] = _npcInfo[i].y - 46 + 16 + 16 * sin(3.14159 * 2 / 180 * (_npcInfo[i].swayAngle + 120 * ff));
695 }
696
697 // targethead code
698 xdif = _npcInfo[i].bodysection[10 * ff + 9].x - _npcInfo[i].headTargetX[ff];
699 ydif = _npcInfo[i].bodysection[10 * ff + 9].y - _npcInfo[i].headTargetY[ff];
700
701 _npcInfo[i].bodysection[10 * ff + 9].x = _npcInfo[i].bodysection[10 * ff + 9].x - xdif * 0.4 * _fpsr;
702 _npcInfo[i].bodysection[10 * ff + 9].y = _npcInfo[i].bodysection[10 * ff + 9].y - ydif * 0.4 * _fpsr;
703
704 _npcInfo[i].bodysection[10 * ff].x = _npcInfo[i].x + 12 + 8 * cos(3.141592 * 2 * (_itemyloc / 16 + ff * 120 / 360));
705 _npcInfo[i].bodysection[10 * ff].y = _npcInfo[i].y + 12 + 8 * sin(3.141592 * 2 * (_itemyloc / 16 + ff * 120 / 360));
706
707 for (int f = 8; f >= 1; f--) {
708 xdif = _npcInfo[i].bodysection[ff * 10 + f + 1].x - _npcInfo[i].bodysection[ff * 10 + f - 1].x;
709 ydif = _npcInfo[i].bodysection[ff * 10 + f + 1].y - _npcInfo[i].bodysection[ff * 10 + f - 1].y;
710
711 float tx = _npcInfo[i].bodysection[ff * 10 + f - 1].x + xdif / 2;
712 float ty = _npcInfo[i].bodysection[ff * 10 + f - 1].y + ydif / 2;
713
714 _npcInfo[i].bodysection[ff * 10 + f].x = _npcInfo[i].bodysection[ff * 10 + f].x - (_npcInfo[i].bodysection[ff * 10 + f].x - tx) / 3;
715 _npcInfo[i].bodysection[ff * 10 + f].y = _npcInfo[i].bodysection[ff * 10 + f].y - (_npcInfo[i].bodysection[ff * 10 + f].y - ty) / 3;
716 }
717 }
718 }
719 }
720
721 // spriteset6 specific
722 if (_npcInfo[i].spriteset == kMonsterRedDragon && _npcInfo[i].attackattempt < _ticks) {
723 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
724 npx = _npcInfo[i].x;
725 npy = _npcInfo[i].y;
726
727 xdif = _player.px - npx;
728 ydif = _player.py - npy;
729
730 pass = 0;
731 if (ABS(xdif) < 48 && ABS(ydif) < 6)
732 pass = 1;
733 if (ABS(ydif) < 48 && ABS(xdif) < 6)
734 pass = 2;
735
736 if (pass > 0) {
737 _npcInfo[i].attackattempt = _ticks + 100;
738 if ((int)(RND() * 2) == 0) {
739 _npcInfo[i].attacking = true;
740 _npcInfo[i].attackframe = 0;
741 float nnxa = 0, nnya = 0, nnxb = 0, nnyb = 0;
742
743 if (pass == 1 && xdif < 0) {
744 nnxa = npx - 8;
745 nnya = npy + 4;
746 nnxb = npx - 48 - 8;
747 nnyb = npy + 4;
748 } else if (pass == 1 && xdif > 0) {
749 nnxa = npx + 16;
750 nnya = npy + 4;
751 nnxb = npx + 16 + 48;
752 nnyb = npy + 4;
753 } else if (pass == 2 && ydif < 0) {
754 nnya = npy;
755 nnxa = npx + 4;
756 nnyb = npy - 48;
757 nnxb = npx + 4;
758 } else if (pass == 2 && ydif > 0) {
759 nnya = npy + 20;
760 nnxa = npx + 4;
761 nnyb = npy + 20 + 48;
762 nnxb = npx + 4;
763 }
764
765 castSpell(7, nnxa, nnya, nnxb, nnyb, i);
766 }
767 }
768 }
769 }
770
771 // wizard1 specific
772 if (_npcInfo[i].spriteset == kMonsterPriest) {
773 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
774 _npcInfo[i].attacking = true;
775 _npcInfo[i].attackframe = 0;
776
777 castSpell(9, _npcInfo[i].x, _npcInfo[i].y, _player.px, _player.py, i);
778 }
779
780 if (_npcInfo[i].castPause < _ticks) {
781 // castSpell 6, _npcinfo[i].x, _npcinfo[i].y, _player.px, _player.py, i
782 // _npcinfo[i].castpause = _ticks + 12000
783 }
784
785 }
786
787 // spriteset6 specific
788 if (_npcInfo[i].spriteset == kMonsterYellowDragon && _npcInfo[i].attackattempt < _ticks) {
789 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
790 npx = _npcInfo[i].x;
791 npy = _npcInfo[i].y;
792
793 xdif = _player.px - npx;
794 ydif = _player.py - npy;
795
796 pass = 0;
797 if (ABS(xdif) < 56 && ABS(ydif) < 6)
798 pass = 1;
799 if (ABS(ydif) < 56 && ABS(xdif) < 6)
800 pass = 2;
801
802 if (pass > 0) {
803 _npcInfo[i].attackattempt = _ticks + 100;
804 if ((int)(RND() * 2) == 0) {
805 _npcInfo[i].attacking = true;
806 _npcInfo[i].attackframe = 0;
807
808 float nnxa = 0, nnya = 0, nnxb = 0, nnyb = 0;
809 if (pass == 1 && xdif < 0) {
810 nnxa = npx - 8;
811 nnya = npy + 4;
812 nnxb = npx - 56 - 8;
813 nnyb = npy + 4;
814 _npcInfo[i].walkdir = 2;
815 } else if (pass == 1 && xdif > 0) {
816 nnxa = npx + 16;
817 nnya = npy + 4;
818 nnxb = npx + 16 + 56;
819 nnyb = npy + 4;
820 _npcInfo[i].walkdir = 3;
821 } else if (pass == 2 && ydif < 0) {
822 nnya = npy;
823 nnxa = npx + 4;
824 nnyb = npy - 56;
825 nnxb = npx + 4;
826 _npcInfo[i].walkdir = 0;
827 } else if (pass == 2 && ydif > 0) {
828 nnya = npy + 20;
829 nnxa = npx + 4;
830 nnyb = npy + 20 + 56;
831 nnxb = npx + 4;
832 _npcInfo[i].walkdir = 1;
833 }
834
835 castSpell(7, nnxa, nnya, nnxb, nnyb, i);
836 }
837 }
838 }
839 }
840
841 // twowing specific
842 if (_npcInfo[i].spriteset == kMonsterTwoWing) {
843 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
844 npx = _npcInfo[i].bodysection[7].x;
845 npy = _npcInfo[i].bodysection[7].y;
846
847 xdif = _player.px - npx;
848 ydif = _player.py - npy;
849
850 if (ABS(xdif) < 24 && ABS(ydif) < 24) {
851 float dist = sqrt(xdif * xdif + ydif * ydif);
852
853 if ((dist) < 24) {
854 if (config.effects) {
855 int snd = playSound(_sfx[kSndBite]);
856 setChannelVolume(snd, config.effectsVol);
857 }
858
859 _npcInfo[i].attacking = true;
860 _npcInfo[i].attackframe = 0;
861
862 _npcInfo[i].headTargetX[0] = _player.px + 12;
863 _npcInfo[i].headTargetY[0] = _player.py - 4;
864 }
865 }
866
867 }
868
869 if (!_npcInfo[i].attacking && _npcInfo[i].castPause < _ticks) {
870 _npcInfo[i].swaySpeed = 4;
871
872 // sway code
873 _npcInfo[i].swayAngle = _npcInfo[i].swayAngle + _npcInfo[i].swaySpeed * _fpsr;
874 if (_npcInfo[i].swayAngle >= 360)
875 _npcInfo[i].swayAngle = _npcInfo[i].swayAngle - 360;
876
877 _npcInfo[i].headTargetX[0] = _npcInfo[i].x + (24 - _npcInfo[i].swaySpeed / 2) * sin(3.14159 / 180 * _npcInfo[i].swayAngle) + 12;
878 _npcInfo[i].headTargetY[0] = _npcInfo[i].y - 36 + 16 + 8 * sin(3.14159 * 2 / 180 * _npcInfo[i].swayAngle);
879 }
880
881 if (dospell) {
882 _npcInfo[i].pause = _ticks + 3000;
883 _npcInfo[i].attacknext = _ticks + 5000;
884 _npcInfo[i].castPause = _ticks + 3000;
885
886 castSpell(3, _npcInfo[i].x, _npcInfo[i].y, _npcInfo[i].x, _npcInfo[i].y, i);
887
888 _npcInfo[i].headTargetX[0] = _npcInfo[i].x;
889 _npcInfo[i].headTargetY[0] = _npcInfo[i].y - 36 + 16;
890 }
891
892 // targethead code
893 xdif = _npcInfo[i].bodysection[7].x - _npcInfo[i].headTargetX[0];
894 ydif = _npcInfo[i].bodysection[7].y - _npcInfo[i].headTargetY[0];
895
896
897 _npcInfo[i].bodysection[7].x = _npcInfo[i].bodysection[7].x - xdif * 0.4 * _fpsr;
898 _npcInfo[i].bodysection[7].y = _npcInfo[i].bodysection[7].y - ydif * 0.4 * _fpsr;
899
900 _npcInfo[i].bodysection[0].x = _npcInfo[i].x + 12;
901 _npcInfo[i].bodysection[0].y = _npcInfo[i].y + 12;
902
903 for (int f = 6; f >= 1; f--) {
904 xdif = _npcInfo[i].bodysection[f + 1].x - _npcInfo[i].bodysection[f - 1].x;
905 ydif = _npcInfo[i].bodysection[f + 1].y - _npcInfo[i].bodysection[f - 1].y;
906
907 float tx = _npcInfo[i].bodysection[f - 1].x + xdif / 2;
908 float ty = _npcInfo[i].bodysection[f - 1].y + ydif / 2;
909
910 _npcInfo[i].bodysection[f].x = _npcInfo[i].bodysection[f].x - (_npcInfo[i].bodysection[f].x - tx) / 3;
911 _npcInfo[i].bodysection[f].y = _npcInfo[i].bodysection[f].y - (_npcInfo[i].bodysection[f].y - ty) / 3;
912 }
913
914 }
915
916 // dragon2 specific
917 if (_npcInfo[i].spriteset == kMonsterDragon2 && _npcInfo[i].attackattempt < _ticks) {
918 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
919 npx = _npcInfo[i].x;
920 npy = _npcInfo[i].y;
921
922 xdif = _player.px - npx;
923 ydif = _player.py - npy;
924
925 if (ABS(xdif) < 32 && ABS(ydif) < 32) {
926 _npcInfo[i].attackattempt = _ticks + 100;
927 if ((int)(RND() * 2) == 0) {
928 if (config.effects) {
929 int snd = playSound(_sfx[kSndEnemyHit]);
930 setChannelVolume(snd, config.effectsVol);
931 }
932
933 _npcInfo[i].attacking = true;
934 _npcInfo[i].attackframe = 0;
935 }
936 }
937 }
938 }
939
940
941 // endboss specific
942 if (_npcInfo[i].spriteset == kMonsterFinalBoss && _npcInfo[i].attackattempt < _ticks) {
943 if (_npcInfo[i].attacknext < _ticks && _npcInfo[i].pause < _ticks && !_npcInfo[i].attacking) {
944 npx = _npcInfo[i].x;
945 npy = _npcInfo[i].y;
946
947 xdif = _player.px - npx;
948 ydif = _player.py - npy;
949
950 if (ABS(xdif) < 38 && ABS(ydif) < 38) {
951 _npcInfo[i].attackattempt = _ticks + 100;
952 if ((int)(RND() * 2) == 0) {
953 if (config.effects) {
954 int snd = playSound(_sfx[kSndIce]);
955 setChannelVolume(snd, config.effectsVol);
956 }
957 _npcInfo[i].attacking = true;
958 _npcInfo[i].attackframe = 0;
959 }
960 }
961 }
962 }
963 }
964
965
966 float npx = _npcInfo[i].x;
967 float npy = _npcInfo[i].y;
968
969 int xp = (npx / 2 + 6);
970 int yp = (npy / 2 + 10);
971
972 rcSrc.left = xp - 1;
973 rcSrc.top = yp - 1;
974 rcSrc.setWidth(3);
975 rcSrc.setHeight(3);
976
977 if (_npcInfo[i].pause < _ticks)
978 _clipBg->fillRect(rcSrc, i);
979
980
981 pass = 0;
982 if (_npcInfo[i].attacking)
983 pass = 1;
984 if (_npcInfo[i].spriteset == kMonsterFireHydra) {
985 if (_npcInfo[i].attacking2[0] || _npcInfo[i].attacking2[1] || _npcInfo[i].attacking2[2])
986 pass = 1;
987 }
988
989 if (pass == 1) {
990 int dist;
991 float damage;
992 // spriteset1 specific
993 if (_npcInfo[i].spriteset == kMonsterBabyDragon) {
994 _npcInfo[i].attackframe = _npcInfo[i].attackframe + _npcInfo[i].attackspd * _fpsr;
995 if (_npcInfo[i].attackframe >= 16) {
996 _npcInfo[i].attackframe = 0;
997 _npcInfo[i].attacking = false;
998 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
999 }
1000
1001 _npcInfo[i].cattackframe = (int)(_npcInfo[i].attackframe);
1002
1003 npx = _npcInfo[i].x;
1004 npy = _npcInfo[i].y;
1005
1006 float xdif = _player.px - npx;
1007 float ydif = _player.py - npy;
1008
1009 dist = 10;
1010
1011 if (ABS(xdif) < dist && ABS(ydif) < dist && _player.pause < _ticks) {
1012 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1013 // _npcinfo[i].attackframe = 0;
1014 // _npcinfo[i].attacking = false;
1015
1016 damage = (float)_npcInfo[i].attackDamage * (0.5 + RND() * 1.0);
1017
1018 if (_player.hp > 0)
1019 damagePlayer(damage);
1020 }
1021 }
1022
1023 if (_npcInfo[i].spriteset == kMonsterOneWing) {
1024 // targethead code
1025 float xdif = _npcInfo[i].bodysection[7].x - _npcInfo[i].headTargetX[0];
1026 float ydif = _npcInfo[i].bodysection[7].y - _npcInfo[i].headTargetY[0];
1027
1028 _npcInfo[i].bodysection[7].x = _npcInfo[i].bodysection[7].x - xdif * 0.4 * _fpsr;
1029 _npcInfo[i].bodysection[7].y = _npcInfo[i].bodysection[7].y - ydif * 0.4 * _fpsr;
1030
1031 _npcInfo[i].bodysection[0].x = _npcInfo[i].x + 12;
1032 _npcInfo[i].bodysection[0].y = _npcInfo[i].y + 12;
1033
1034 for (int f = 6; f >= 1; f--) {
1035 xdif = _npcInfo[i].bodysection[f + 1].x - _npcInfo[i].bodysection[f - 1].x;
1036 ydif = _npcInfo[i].bodysection[f + 1].y - _npcInfo[i].bodysection[f - 1].y;
1037
1038 float tx = _npcInfo[i].bodysection[f - 1].x + xdif / 2;
1039 float ty = _npcInfo[i].bodysection[f - 1].y + ydif / 2;
1040
1041 _npcInfo[i].bodysection[f].x = _npcInfo[i].bodysection[f].x - (_npcInfo[i].bodysection[f].x - tx);
1042 _npcInfo[i].bodysection[f].y = _npcInfo[i].bodysection[f].y - (_npcInfo[i].bodysection[f].y - ty);
1043 }
1044
1045 _npcInfo[i].attackframe = _npcInfo[i].attackframe + _npcInfo[i].attackspd * _fpsr;
1046 if (_npcInfo[i].attackframe >= 16) {
1047 _npcInfo[i].attackframe = 0;
1048 _npcInfo[i].attacking = false;
1049 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1050 }
1051
1052 _npcInfo[i].cattackframe = (int)(_npcInfo[i].attackframe);
1053
1054 npx = _npcInfo[i].bodysection[7].x;
1055 npy = (_npcInfo[i].bodysection[7].y + 16);
1056
1057 xdif = (_player.px + 12) - npx;
1058 ydif = (_player.py + 12) - npy;
1059
1060 dist = 8;
1061
1062 if (ABS(xdif) < dist && ABS(ydif) < dist && _player.pause < _ticks) {
1063 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1064 // _npcinfo[i].attackframe = 0
1065 // _npcinfo[i].attacking = false
1066 damage = (float)_npcInfo[i].attackDamage * (1.0 + (RND() * 0.5));
1067 if (_player.hp > 0)
1068 damagePlayer(damage);
1069 }
1070 }
1071
1072
1073 // firehydra
1074 if (_npcInfo[i].spriteset == kMonsterFireHydra) {
1075 for (int ff = 0; ff <= 2; ff++) {
1076 if (_npcInfo[i].attacking2[ff]) {
1077 float xdif = _npcInfo[i].bodysection[10 * ff + 9].x - _npcInfo[i].headTargetX[ff];
1078 float ydif = _npcInfo[i].bodysection[10 * ff + 9].y - _npcInfo[i].headTargetY[ff];
1079
1080 _npcInfo[i].bodysection[10 * ff + 9].x = _npcInfo[i].bodysection[10 * ff + 9].x - xdif * .2 * _fpsr;
1081 _npcInfo[i].bodysection[10 * ff + 9].y = _npcInfo[i].bodysection[10 * ff + 9].y - ydif * .2 * _fpsr;
1082
1083 _npcInfo[i].bodysection[10 * ff].x = _npcInfo[i].x + 12 + 8 * cos(3.141592 * 2 * (_itemyloc / 16 + ff * 120 / 360));
1084 _npcInfo[i].bodysection[10 * ff].y = _npcInfo[i].y + 12 + 8 * sin(3.141592 * 2 * (_itemyloc / 16 + ff * 120 / 360));
1085
1086 for (int f = 8; f >= 1; f--) {
1087 xdif = _npcInfo[i].bodysection[ff * 10 + f + 1].x - _npcInfo[i].bodysection[ff * 10 + f - 1].x;
1088 ydif = _npcInfo[i].bodysection[ff * 10 + f + 1].y - _npcInfo[i].bodysection[ff * 10 + f - 1].y;
1089
1090 float tx = _npcInfo[i].bodysection[ff * 10 + f - 1].x + xdif / 2;
1091 float ty = _npcInfo[i].bodysection[ff * 10 + f - 1].y + ydif / 2;
1092
1093 _npcInfo[i].bodysection[ff * 10 + f].x = _npcInfo[i].bodysection[ff * 10 + f].x - (_npcInfo[i].bodysection[ff * 10 + f].x - tx) / 3;
1094 _npcInfo[i].bodysection[ff * 10 + f].y = _npcInfo[i].bodysection[ff * 10 + f].y - (_npcInfo[i].bodysection[ff * 10 + f].y - ty) / 3;
1095 }
1096
1097 _npcInfo[i].attackframe2[ff] = _npcInfo[i].attackframe2[ff] + _npcInfo[i].attackspd * _fpsr;
1098 if (_npcInfo[i].attackframe2[ff] >= 16) {
1099 _npcInfo[i].attackframe2[ff] = 0;
1100 _npcInfo[i].attacking2[ff] = false;
1101 _npcInfo[i].attacknext2[ff] = _ticks + _npcInfo[i].attackdelay;
1102 }
1103
1104 _npcInfo[i].cattackframe = (int)(_npcInfo[i].attackframe);
1105
1106 npx = _npcInfo[i].bodysection[10 * ff + 9].x;
1107 npy = (_npcInfo[i].bodysection[10 * ff + 9].y + 16);
1108
1109 xdif = (_player.px + 12) - npx;
1110 ydif = (_player.py + 12) - npy;
1111
1112 dist = 8;
1113
1114 if (ABS(xdif) < dist && ABS(ydif) < dist && _player.pause < _ticks) {
1115 _npcInfo[i].attacknext2[ff] = _ticks + _npcInfo[i].attackdelay;
1116 // _npcinfo[i].attackframe2(ff) = 0
1117 // _npcinfo[i].attacking2(ff) = false
1118 damage = (float)_npcInfo[i].attackDamage * (1.0 + RND() * 0.5);
1119 if (_player.hp > 0)
1120 damagePlayer(damage);
1121 }
1122 }
1123 }
1124
1125 }
1126
1127 // twowing specific
1128 if (_npcInfo[i].spriteset == kMonsterTwoWing) {
1129 // targethead code
1130 float xdif = _npcInfo[i].bodysection[7].x - _npcInfo[i].headTargetX[0];
1131 float ydif = _npcInfo[i].bodysection[7].y - _npcInfo[i].headTargetY[0];
1132
1133 _npcInfo[i].bodysection[7].x = _npcInfo[i].bodysection[7].x - xdif * 0.4 * _fpsr;
1134 _npcInfo[i].bodysection[7].y = _npcInfo[i].bodysection[7].y - ydif * 0.4 * _fpsr;
1135
1136 _npcInfo[i].bodysection[0].x = _npcInfo[i].x + 12;
1137 _npcInfo[i].bodysection[0].y = _npcInfo[i].y + 12;
1138
1139 for (int f = 6; f >= 1; f--) {
1140 xdif = _npcInfo[i].bodysection[f + 1].x - _npcInfo[i].bodysection[f - 1].x;
1141 ydif = _npcInfo[i].bodysection[f + 1].y - _npcInfo[i].bodysection[f - 1].y;
1142
1143 float tx = _npcInfo[i].bodysection[f - 1].x + xdif / 2;
1144 float ty = _npcInfo[i].bodysection[f - 1].y + ydif / 2;
1145
1146 _npcInfo[i].bodysection[f].x = _npcInfo[i].bodysection[f].x - (_npcInfo[i].bodysection[f].x - tx);
1147 _npcInfo[i].bodysection[f].y = _npcInfo[i].bodysection[f].y - (_npcInfo[i].bodysection[f].y - ty);
1148 }
1149
1150 _npcInfo[i].attackframe = _npcInfo[i].attackframe + _npcInfo[i].attackspd * _fpsr;
1151 if (_npcInfo[i].attackframe >= 16) {
1152 _npcInfo[i].attackframe = 0;
1153 _npcInfo[i].attacking = false;
1154 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1155 }
1156
1157 _npcInfo[i].cattackframe = (int)(_npcInfo[i].attackframe);
1158
1159 npx = _npcInfo[i].bodysection[7].x;
1160 npy = (_npcInfo[i].bodysection[7].y + 16);
1161
1162 xdif = (_player.px + 12) - npx;
1163 ydif = (_player.py + 12) - npy;
1164
1165 dist = 8;
1166
1167 if (ABS(xdif) < dist && ABS(ydif) < dist && _player.pause < _ticks) {
1168 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1169 // _npcinfo[i].attackframe = 0
1170 // _npcinfo[i].attacking = false
1171 damage = (float)_npcInfo[i].attackDamage * (1.0 + RND() * 0.5);
1172 if (_player.hp > 0)
1173 damagePlayer(damage);
1174 }
1175 }
1176
1177 // dragon 2 specific
1178 if (_npcInfo[i].spriteset == kMonsterDragon2) {
1179
1180 _npcInfo[i].attackframe = _npcInfo[i].attackframe + _npcInfo[i].attackspd * _fpsr;
1181 if (_npcInfo[i].attackframe >= 16) {
1182 _npcInfo[i].attackframe = 0;
1183 _npcInfo[i].attacking = false;
1184 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1185 }
1186
1187 _npcInfo[i].cattackframe = (int)(_npcInfo[i].attackframe);
1188
1189 npx = _npcInfo[i].x;
1190 npy = _npcInfo[i].y;
1191
1192 float xdif = _player.px - npx;
1193 float ydif = _player.py - npy;
1194
1195 dist = 16 + _npcInfo[i].attackframe;
1196
1197 if (ABS(xdif) < dist && ABS(ydif) < dist && _player.pause < _ticks) {
1198 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1199 // _npcinfo[i].attackframe = 0
1200 // _npcinfo[i].attacking = false
1201 damage = (float)_npcInfo[i].attackDamage * (0.5 + RND() * 1.0);
1202 if (_player.hp > 0)
1203 damagePlayer(damage);
1204 }
1205 }
1206
1207 // endboss specific
1208 if (_npcInfo[i].spriteset == kMonsterFinalBoss) {
1209 _npcInfo[i].attackframe = _npcInfo[i].attackframe + _npcInfo[i].attackspd * _fpsr;
1210 if (_npcInfo[i].attackframe >= 16) {
1211 _npcInfo[i].attackframe = 0;
1212 _npcInfo[i].attacking = false;
1213 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1214 }
1215
1216 _npcInfo[i].cattackframe = (int)(_npcInfo[i].attackframe);
1217
1218 npx = _npcInfo[i].x;
1219 npy = _npcInfo[i].y;
1220
1221 float xdif = _player.px - npx;
1222 float ydif = _player.py - npy;
1223
1224 dist = 36;
1225
1226 if (ABS(xdif) < dist && ABS(ydif) < dist && _player.pause < _ticks) {
1227 _npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay;
1228 // _npcinfo[i].attackframe = 0
1229 // _npcinfo[i].attacking = false
1230 damage = (float)_npcInfo[i].attackDamage * (0.5 + RND() * 1.0);
1231 if (_player.hp > 0)
1232 damagePlayer(damage);
1233 }
1234 }
1235 }
1236 // -------end fight code
1237 }
1238 }
1239 }
1240
updateSpells()1241 void GriffonEngine::updateSpells() {
1242 float xloc = 0, yloc = 0;
1243
1244 for (int i = 0; i < kMaxSpell; i++) {
1245 if (_spellInfo[i].frame > 0) {
1246 int spellnum = _spellInfo[i].spellnum;
1247
1248 // water
1249 if (spellnum == 0 && !_forcePause) {
1250 float fr = (32 - _spellInfo[i].frame);
1251 int ll[4][2];
1252
1253 ll[0][0] = -2;
1254 ll[0][1] = -3;
1255 ll[1][0] = 2;
1256 ll[1][1] = -3;
1257 ll[2][0] = -4;
1258 ll[2][1] = -2;
1259 ll[3][0] = 4;
1260 ll[3][1] = -2;
1261
1262 for (int f = 0; f <= 3; f++) {
1263 if (fr > f * 4 && fr < f * 4 + 16) {
1264 float alf = 255;
1265
1266 if (fr < f * 4 + 8) {
1267 int fi = (int)((fr - f * 4) * 3) % 4;
1268 rcSrc.left = 32 + fi * 16;
1269 rcSrc.top = 80;
1270 rcSrc.setWidth(16);
1271 rcSrc.setHeight(16);
1272
1273 xloc = _spellInfo[i].enemyx + 12 + ll[f][0] * 16;
1274 yloc = _spellInfo[i].enemyy + 16 + ll[f][1] * 16;
1275
1276 rcDest.left = xloc;
1277 rcDest.top = yloc;
1278
1279 alf = 255 * ((fr - f * 4) / 8);
1280 }
1281
1282 if (fr >= f * 4 + 8) {
1283 int fi = 0; // ??
1284
1285 if (f == 0 || f == 2)
1286 fi = 0;
1287 if (f == 1 || f == 3)
1288 fi = 1;
1289 rcSrc.left = 32 + fi * 16;
1290 rcSrc.top = 80;
1291 rcSrc.setWidth(16);
1292 rcSrc.setHeight(16);
1293
1294 float xst = _spellInfo[i].enemyx + 12 + ll[f][0] * 16;
1295 float yst = _spellInfo[i].enemyy + 16 + ll[f][1] * 16;
1296
1297 float xi = (_spellInfo[i].enemyx - xst) * 2 / 8;
1298 float yi = (_spellInfo[i].enemyy - yst) * 2 / 8;
1299
1300 float fl = (fr - f * 4 - 8) / 2;
1301 xloc = xst + xi * fl * fl;
1302 yloc = yst + yi * fl * fl;
1303
1304 rcDest.left = xloc;
1305 rcDest.top = yloc;
1306
1307 alf = 255;
1308 }
1309
1310 if (xloc > -16 && xloc < 304 && yloc > -16 && yloc < 224) {
1311 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB((int)alf, 255, 255, 255));
1312
1313 if (_spellInfo[i].damagewho == 0) {
1314 for (int e = 1; e <= _lastNpc; e++) {
1315 float xdif = (xloc + 16) - (_npcInfo[e].x + 12);
1316 float ydif = (yloc + 16) - (_npcInfo[e].y + 12);
1317
1318 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1319 float damage = (float)_player.spellDamage * (1.0 + RND() * 0.5) * (float)_spellInfo[i].strength;
1320
1321 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks) {
1322 damageNPC(e, damage, 1);
1323 if (config.effects) {
1324 int snd = playSound(_sfx[kSndIce]);
1325 setChannelVolume(snd, config.effectsVol);
1326 }
1327 }
1328 }
1329 }
1330 }
1331
1332 // check for post damage
1333 if (_postInfoNbr > 0) {
1334 for (int e = 0; e <= _postInfoNbr - 1; e++) {
1335 float xdif = (xloc + 16) - (_postInfo[e][0] + 8);
1336 float ydif = (yloc + 16) - (_postInfo[e][1] + 8);
1337
1338 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1339 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
1340 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
1341
1342 rcSrc.left = _postInfo[e][0] / 2;
1343 rcSrc.top = _postInfo[e][1] / 2;
1344 rcSrc.setWidth(8);
1345 rcSrc.setHeight(8);
1346
1347 _clipBg2->fillRect(rcSrc, 0);
1348
1349 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
1350
1351 if (config.effects) {
1352 int snd = playSound(_sfx[kSndIce]);
1353 setChannelVolume(snd, config.effectsVol);
1354 }
1355 }
1356 }
1357 }
1358 }
1359 }
1360 }
1361 }
1362
1363 // metal
1364 if (spellnum == 1 && !_forcePause) {
1365 int fr = (int)((32 - _spellInfo[i].frame) * 4) % 3;
1366
1367 rcSrc.left = fr * 48;
1368 rcSrc.top = 0;
1369 rcSrc.setWidth(48);
1370 rcSrc.setHeight(48);
1371
1372 float c1 = (32 - _spellInfo[i].frame) / 16;
1373
1374 float halfx = (_spellInfo[i].homex - 12) + ((_spellInfo[i].enemyx - 12) - (_spellInfo[i].homex - 12)) / 2;
1375 float halfy = (_spellInfo[i].homey - 12) + ((_spellInfo[i].enemyy - 12) - (_spellInfo[i].homey - 12)) / 2;
1376
1377 float wdth = (halfx - _spellInfo[i].homex) * 1.2;
1378 float hight = (halfy - _spellInfo[i].homey) * 1.2;
1379
1380 xloc = halfx + wdth * cos(3.14159 + 3.14159 * 2 * c1);
1381 yloc = halfy + hight * sin(3.14159 + 3.14159 * 2 * c1);
1382
1383 rcDest.left = xloc;
1384 rcDest.top = yloc;
1385
1386 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(255, 255, 255, 255));
1387
1388 _spellInfo[i].frame = _spellInfo[i].frame - 0.2 * _fpsr;
1389 if (_spellInfo[i].frame < 0)
1390 _spellInfo[i].frame = 0;
1391
1392 if (_spellInfo[i].damagewho == 0) {
1393 for (int e = 1; e <= _lastNpc; e++) {
1394 float xdif = (xloc + 24) - (_npcInfo[e].x + 12);
1395 float ydif = (yloc + 24) - (_npcInfo[e].y + 12);
1396
1397 if ((ABS(xdif) < 24 && ABS(ydif) < 24)) {
1398 float damage = (float)_player.spellDamage * (1.0 + RND() * 0.5) * (float)_spellInfo[i].strength;
1399
1400 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks) {
1401 damageNPC(e, damage, 1);
1402 if (config.effects) {
1403 int snd = playSound(_sfx[kSndMetalHit]);
1404 setChannelVolume(snd, config.effectsVol);
1405 }
1406 }
1407 }
1408 }
1409 }
1410
1411 if (_spellInfo[i].damagewho == 1) {
1412 // --------- boss 1 specific
1413 if (ABS(_spellInfo[i].frame) < 0 && _npcInfo[_spellInfo[i].npc].spriteset == kMonsterBoss1) {
1414 int npc = _spellInfo[i].npc;
1415 _npcInfo[npc].attackframe = 0;
1416 _npcInfo[npc].attacking = false;
1417
1418 _npcInfo[npc].pause = _ticks + 1000;
1419 _npcInfo[npc].attacknext = _ticks + 4000;
1420 }
1421 // ---------------
1422
1423 // --------- blackknight specific
1424 if (ABS(_spellInfo[i].frame) < 0 && _npcInfo[_spellInfo[i].npc].spriteset == kMonsterBlackKnight) {
1425 int npc = _spellInfo[i].npc;
1426 _npcInfo[npc].attackframe = 0;
1427 _npcInfo[npc].attacking = false;
1428
1429 _npcInfo[npc].pause = _ticks + 1000;
1430 _npcInfo[npc].attacknext = _ticks + 3500;
1431 }
1432 // ---------------
1433
1434 float xdif = (xloc + 24) - (_player.px + 12);
1435 float ydif = (yloc + 24) - (_player.py + 12);
1436
1437 if ((ABS(xdif) < 24 && ABS(ydif) < 24) && _player.pause < _ticks) {
1438 float damage = (float)_npcInfo[_spellInfo[i].npc].spellDamage * (1.0 + RND() * 0.5);
1439
1440 if (_player.hp > 0) {
1441 damagePlayer(damage);
1442 if (config.effects) {
1443 int snd = playSound(_sfx[kSndMetalHit]);
1444 setChannelVolume(snd, config.effectsVol);
1445 }
1446 }
1447 }
1448 }
1449
1450
1451 // check for(int post damage
1452 if (_postInfoNbr > 0) {
1453 for (int e = 0; e <= _postInfoNbr - 1; e++) {
1454 float xdif = (xloc + 24) - (_postInfo[e][0] + 8);
1455 float ydif = (yloc + 24) - (_postInfo[e][1] + 8);
1456
1457 if ((ABS(xdif) < 24 && ABS(ydif) < 24)) {
1458 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
1459 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
1460
1461 rcSrc.left = _postInfo[e][0] / 2;
1462 rcSrc.top = _postInfo[e][1] / 2;
1463 rcSrc.setWidth(8);
1464 rcSrc.setHeight(8);
1465
1466 _clipBg2->fillRect(rcSrc, 0);
1467
1468 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
1469
1470 if (config.effects) {
1471 int snd = playSound(_sfx[kSndMetalHit]);
1472 setChannelVolume(snd, config.effectsVol);
1473 }
1474 }
1475 }
1476 }
1477 }
1478
1479 // earth
1480 if (spellnum == 2 && !_forcePause) {
1481 float hght = 240 - _spellInfo[i].enemyy;
1482
1483 for (int f = 8; f >= 0; f--) {
1484
1485 float fr = (32 - _spellInfo[i].frame);
1486
1487 if (fr > f && fr < f + 16) {
1488 rcSrc.left = 32 * _spellInfo[i].rockimg[f];
1489 rcSrc.top = 48;
1490 rcSrc.setWidth(32);
1491 rcSrc.setHeight(32);
1492
1493 bool scatter = false;
1494 if (fr < 8 + f) {
1495 xloc = _spellInfo[i].enemyx - 4;
1496 yloc = _spellInfo[i].enemyy * (1 - cos(3.14159 / 2 * (fr - f) / 8)); // ^ 2;
1497 yloc *= yloc;
1498 } else {
1499 scatter = true;
1500 xloc = _spellInfo[i].enemyx - 4 - _spellInfo[i].rockdeflect[f] * sin(3.14159 / 2 * ((fr - f) - 8) / 8);
1501 yloc = _spellInfo[i].enemyy + hght * (1 - cos(3.14159 / 2 * ((fr - f) - 8) / 8));
1502 }
1503
1504 rcDest.left = xloc;
1505 rcDest.top = yloc;
1506
1507 if (xloc > -16 && xloc < 304 && yloc > -16 && yloc < 224) {
1508 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(255, 255, 255, 255));
1509
1510 if (scatter) {
1511 if (_spellInfo[i].damagewho == 0) {
1512 for (int e = 1; e <= _lastNpc; e++) {
1513 float xdif = (xloc + 16) - (_npcInfo[e].x + 12);
1514 float ydif = (yloc + 16) - (_npcInfo[e].y + 12);
1515
1516 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1517 float damage = (float)_player.spellDamage * (1.0 + RND() * 0.5) * (float)_spellInfo[i].strength;
1518
1519 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks) {
1520 damageNPC(e, damage, 1);
1521 if (config.effects) {
1522 int snd = playSound(_sfx[kSndRocks]);
1523 setChannelVolume(snd, config.effectsVol);
1524 }
1525 }
1526 }
1527 }
1528 }
1529
1530
1531 // check for(int post damage
1532 if (_postInfoNbr > 0) {
1533 for (int e = 0; e <= _postInfoNbr - 1; e++) {
1534 float xdif = (xloc + 16) - (_postInfo[e][0] + 8);
1535 float ydif = (yloc + 16) - (_postInfo[e][1] + 8);
1536
1537 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1538 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
1539 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
1540
1541 rcSrc.left = _postInfo[e][0] / 2;
1542 rcSrc.top = _postInfo[e][1] / 2;
1543 rcSrc.setWidth(8);
1544 rcSrc.setHeight(8);
1545
1546 _clipBg2->fillRect(rcSrc, 0);
1547
1548 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
1549
1550 if (config.effects) {
1551 int snd = playSound(_sfx[kSndRocks]);
1552 setChannelVolume(snd, config.effectsVol);
1553 }
1554 }
1555 }
1556 }
1557 }
1558 }
1559 }
1560 }
1561
1562 _spellInfo[i].frame = _spellInfo[i].frame - 0.2 * _fpsr;
1563 if (_spellInfo[i].frame < 0)
1564 _spellInfo[i].frame = 0;
1565 }
1566
1567 // crystal
1568 if (spellnum == 5) {
1569
1570 float fra = (32 - _spellInfo[i].frame);
1571 int fr = (int)((_spellInfo[i].frame) * 2) % 8;
1572
1573 rcSrc.left = fr * 32;
1574 rcSrc.top = 96 + 48;
1575 rcSrc.setWidth(32);
1576 rcSrc.setHeight(64);
1577
1578 rcDest.left = _player.px - 4;
1579 rcDest.top = _player.py + 16 - 48;
1580
1581 int f = 160;
1582 if (fra < 8)
1583 f = 192 * fra / 8;
1584 if (fra > 24)
1585 f = 192 * (1 - (fra - 24) / 8);
1586
1587 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(f, 255, 255, 255));
1588
1589 _spellInfo[i].frame = _spellInfo[i].frame - 0.3 * _fpsr;
1590 if (_spellInfo[i].frame < 0) {
1591 _spellInfo[i].frame = 0;
1592 _forcePause = false;
1593
1594 float npx = _player.px + 12;
1595 float npy = _player.py + 20;
1596
1597 int lx = (int)npx / 16;
1598 int ly = (int)npy / 16;
1599
1600 bool foundel[5];
1601 for (int f1 = 0; f1 < 5; f1++) { // !! f < 5
1602 foundel[f1] = false;
1603 }
1604
1605 for (int xo = -2; xo <= 2; xo++) {
1606 for (int yo = -2; yo <= 2; yo++) {
1607
1608 int sx = lx + xo;
1609 int sy = ly + yo;
1610
1611 if (sx > -1 && sx < 20 && sy > -1 && sy < 15) {
1612 for (int l = 0; l <= 2; l++) {
1613 int curtile = _tileinfo[l][sx][sy][0];
1614 int curtilel = _tileinfo[l][sx][sy][1];
1615
1616 if (curtile > 0) {
1617 curtile = curtile - 1;
1618 int curtilex = curtile % 20;
1619 int curtiley = (curtile - curtilex) / 20;
1620
1621 int element = elementmap[curtiley][curtilex];
1622 if (element > -1 && curtilel == 0)
1623 foundel[element + 1] = true;
1624 }
1625 }
1626
1627 int o = _objectMap[sx][sy];
1628 if (o > -1) {
1629 if (_objectInfo[o].type == 1)
1630 foundel[2] = true;
1631 if (o == 1 || o == 2) {
1632 foundel[2] = true;
1633 foundel[4] = true;
1634 }
1635 }
1636 }
1637 }
1638 }
1639
1640 char line[256];
1641 strcpy(line, "Found... nothing...");
1642
1643 for (int f1 = 0; f1 < 5; f1++) {
1644 if (foundel[f1] && !_player.foundSpell[f1]) {
1645 _player.foundSpell[f1] = 1;
1646 _player.spellCharge[f1] = 0;
1647 if (f1 == 1)
1648 strcpy(line, "Found... Water Essence");
1649 if (f1 == 2)
1650 strcpy(line, "Found... Metal Essence");
1651 if (f1 == 3)
1652 strcpy(line, "Found... Earth Essence");
1653 if (f1 == 4)
1654 strcpy(line, "Found... Fire Essence");
1655 break;
1656 }
1657 }
1658
1659 eventText(line);
1660 }
1661 }
1662
1663 // room fireballs
1664 if (spellnum == 6 && !_forcePause) {
1665
1666 if (_spellInfo[i].frame > 16) {
1667 float fr = (32 - _spellInfo[i].frame);
1668
1669 int alpha = 192 * sin(3.14159 * fr / 4);
1670
1671 rcSrc.left = 16 * (int)(RND() * 2);
1672 rcSrc.top = 80;
1673 rcSrc.setWidth(16);
1674 rcSrc.setHeight(16);
1675
1676 for (int ff = 0; ff <= _spellInfo[i].nfballs - 1; ff++) {
1677
1678 xloc = _spellInfo[i].fireballs[ff][0] + (int)(RND() * 3) - 1;
1679 yloc = _spellInfo[i].fireballs[ff][1] + (int)(RND() * 3) - 1;
1680
1681 rcDest.left = xloc;
1682 rcDest.top = yloc;
1683
1684 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(alpha, 255, 255, 255));
1685 }
1686 } else {
1687
1688 rcSrc.left = 16 * (int)(RND() * 2);
1689 rcSrc.top = 80;
1690 rcSrc.setWidth(16);
1691 rcSrc.setHeight(16);
1692
1693 for (int ff = 0; ff <= _spellInfo[i].nfballs - 1; ff++) {
1694 float ax = _spellInfo[i].fireballs[ff][0];
1695 float ay = _spellInfo[i].fireballs[ff][1];
1696 float bx = _player.px + 4;
1697 float by = _player.py + 4;
1698 float d = sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay));
1699
1700 float tx = (bx - ax) / d;
1701 float ty = (by - ay) / d;
1702
1703 _spellInfo[i].fireballs[ff][2] += tx * 1.2 * _fpsr;
1704 _spellInfo[i].fireballs[ff][3] += ty * 1.2 * _fpsr;
1705
1706 if (_spellInfo[i].ballon[ff] == 1) {
1707 _spellInfo[i].fireballs[ff][0] = ax + _spellInfo[i].fireballs[ff][2] * 0.2 * _fpsr;
1708 _spellInfo[i].fireballs[ff][1] = ay + _spellInfo[i].fireballs[ff][3] * 0.2 * _fpsr;
1709
1710 xloc = _spellInfo[i].fireballs[ff][0] + (int)(RND() * 3) - 1;
1711 yloc = _spellInfo[i].fireballs[ff][1] + (int)(RND() * 3) - 1;
1712
1713 rcDest.left = xloc;
1714 rcDest.top = yloc;
1715
1716 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(192, 255, 255, 255));
1717 }
1718
1719 if (xloc < -1 || yloc < -1 || xloc > 304 || yloc > 224)
1720 _spellInfo[i].ballon[ff] = 0;
1721 }
1722 }
1723
1724 _spellInfo[i].frame = _spellInfo[i].frame - 0.2 * _fpsr;
1725 if (_spellInfo[i].frame < 0)
1726 _spellInfo[i].frame = 0;
1727
1728 if (_spellInfo[i].damagewho == 1) {
1729 for (int ff = 0; ff <= _spellInfo[i].nfballs - 1; ff++) {
1730 if (_spellInfo[i].ballon[ff] == 1) {
1731 xloc = _spellInfo[i].fireballs[ff][0] + (int)(RND() * 3) - 1;
1732 yloc = _spellInfo[i].fireballs[ff][1] + (int)(RND() * 3) - 1;
1733
1734 float xdif = (xloc + 8) - (_player.px + 12);
1735 float ydif = (yloc + 8) - (_player.py + 12);
1736
1737 if ((ABS(xdif) < 8 && ABS(ydif) < 8) && _player.pause < _ticks) {
1738 float damage = _npcInfo[_spellInfo[i].npc].spellDamage * (1 + RND() * 0.5) / 3;
1739
1740 if (_player.hp > 0)
1741 damagePlayer(damage);
1742
1743 if (config.effects) {
1744 int snd = playSound(_sfx[kSndFire]);
1745 setChannelVolume(snd, config.effectsVol);
1746 }
1747 }
1748 }
1749 }
1750 }
1751 }
1752
1753 // lightning bomb
1754 if (spellnum == 8) {
1755 long cl1 = _videoBuffer->format.RGBToColor(0, 32, 204);
1756 long cl2 = _videoBuffer->format.RGBToColor(142, 173, 191);
1757 long cl3 = _videoBuffer->format.RGBToColor(240, 240, 240);
1758
1759 float px = _player.px + 12;
1760 float py = _player.py + 12;
1761
1762 int apx = px + (int)(RND() * 5 - 2);
1763 int apy = py + (int)(RND() * 5 - 2);
1764
1765 for (int f = 0; f <= 0; f++) { // ??
1766 int y = apy;
1767 int orn = 0;
1768 for (int x = apx; x <= 319; x++) {
1769 int rn = (int)(RND() * 3);
1770
1771 if (orn == 0)
1772 --y;
1773 else if (orn == 2)
1774 ++y;
1775
1776 drawLine(_videoBuffer, x, y - 1, x, y + 2, cl1);
1777 drawLine(_videoBuffer, x, y, x, y + 1, cl3);
1778
1779 if (rn == 0)
1780 drawLine(_videoBuffer, x, y + 1, x, y + 1, cl2);
1781 if (rn == 2)
1782 drawLine(_videoBuffer, x, y, x, y, cl2);
1783
1784 orn = rn;
1785
1786 if (_spellInfo[i].damagewho == 0) {
1787 for (int e = 1; e <= _lastNpc; e++) {
1788 float xdif = (x + 16) - (_npcInfo[e].x + 12);
1789 float ydif = (y + 16) - (_npcInfo[e].y + 12);
1790
1791 if ((ABS(xdif) < 8 && ABS(ydif) < 8)) {
1792 float damage = 30 * (1 + RND() * 0.5);
1793
1794 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks)
1795 damageNPC(e, damage, 1);
1796 }
1797 }
1798 }
1799
1800 // check for post damage
1801 if (_postInfoNbr > 0) {
1802 for (int e = 0; e <= _postInfoNbr - 1; e++) {
1803 float xdif = (xloc + 16) - (_postInfo[e][0] + 8);
1804 float ydif = (yloc + 16) - (_postInfo[e][1] + 8);
1805
1806 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1807 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
1808 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
1809
1810 rcSrc.left = _postInfo[e][0] / 2;
1811 rcSrc.top = _postInfo[e][1] / 2;
1812 rcSrc.setWidth(8);
1813 rcSrc.setHeight(8);
1814
1815 _clipBg2->fillRect(rcSrc, 0);
1816
1817 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
1818 }
1819 }
1820 }
1821 }
1822
1823 y = apy;
1824 orn = 0;
1825 for (int x = apx; x >= 0; x--) {
1826 int rn = (int)(RND() * 3);
1827
1828 if (orn == 0)
1829 --y;
1830 else if (orn == 2)
1831 ++y;
1832
1833 drawLine(_videoBuffer, x, y - 1, x, y + 2, cl1);
1834 drawLine(_videoBuffer, x, y, x, y + 1, cl3);
1835
1836 if (rn == 0)
1837 drawLine(_videoBuffer, x, y + 1, x, y + 1, cl2);
1838 if (rn == 2)
1839 drawLine(_videoBuffer, x, y, x, y, cl2);
1840
1841 orn = rn;
1842
1843 if (_spellInfo[i].damagewho == 0) {
1844 for (int e = 1; e <= _lastNpc; e++) {
1845 float xdif = (x + 16) - (_npcInfo[e].x + 12);
1846 float ydif = (y + 16) - (_npcInfo[e].y + 12);
1847
1848 if ((ABS(xdif) < 8 && ABS(ydif) < 8)) {
1849 float damage = 30 * (1 + RND() * 0.5);
1850
1851 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks)
1852 damageNPC(e, damage, 1);
1853 }
1854 }
1855 }
1856
1857 // check for post damage
1858 if (_postInfoNbr > 0) {
1859 for (int e = 0; e <= _postInfoNbr - 1; e++) {
1860 float xdif = (xloc + 16) - (_postInfo[e][0] + 8);
1861 float ydif = (yloc + 16) - (_postInfo[e][1] + 8);
1862
1863 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1864 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
1865 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
1866
1867 rcSrc.left = _postInfo[e][0] / 2;
1868 rcSrc.top = _postInfo[e][1] / 2;
1869 rcSrc.setWidth(8);
1870 rcSrc.setHeight(8);
1871
1872 _clipBg2->fillRect(rcSrc, 0);
1873
1874 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
1875 }
1876 }
1877 }
1878 }
1879
1880 int x = apx;
1881 orn = 0;
1882 for (y = apy; y <= 239; y++) {
1883 int rn = (int)(RND() * 3);
1884
1885 if (orn == 0)
1886 x = x - 1;
1887 if (orn == 2)
1888 x = x + 1;
1889
1890 drawLine(_videoBuffer, x - 1, y, x + 2, y, cl1);
1891 drawLine(_videoBuffer, x, y, x + 1, y, cl3);
1892
1893 if (rn == 0)
1894 drawLine(_videoBuffer, x + 1, y, x + 1, y, cl2);
1895 if (rn == 2)
1896 drawLine(_videoBuffer, x, y, x, y, cl2);
1897
1898 orn = rn;
1899
1900 if (_spellInfo[i].damagewho == 0) {
1901 for (int e = 1; e <= _lastNpc; e++) {
1902 float xdif = (x + 16) - (_npcInfo[e].x + 12);
1903 float ydif = (y + 16) - (_npcInfo[e].y + 12);
1904
1905 if ((ABS(xdif) < 8 && ABS(ydif) < 8)) {
1906 float damage = 30 * (1 + RND() * 0.5);
1907
1908 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks)
1909 damageNPC(e, damage, 1);
1910 }
1911 }
1912 }
1913
1914 // check for post damage
1915 if (_postInfoNbr > 0) {
1916 for (int e = 0; e <= _postInfoNbr - 1; e++) {
1917 float xdif = (xloc + 16) - (_postInfo[e][0] + 8);
1918 float ydif = (yloc + 16) - (_postInfo[e][1] + 8);
1919
1920 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1921 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
1922 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
1923
1924 rcSrc.left = _postInfo[e][0] / 2;
1925 rcSrc.top = _postInfo[e][1] / 2;
1926 rcSrc.setWidth(8);
1927 rcSrc.setHeight(8);
1928
1929 _clipBg2->fillRect(rcSrc, 0);
1930
1931 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
1932 }
1933 }
1934 }
1935 }
1936
1937 x = apx;
1938 orn = 0;
1939 for (y = apy; y >= 0; y--) {
1940 int rn = (int)(RND() * 3);
1941
1942 if (orn == 0)
1943 x = x - 1;
1944 if (orn == 2)
1945 x = x + 1;
1946
1947 drawLine(_videoBuffer, x - 1, y, x + 2, y, cl1);
1948 drawLine(_videoBuffer, x, y, x + 1, y, cl3);
1949
1950 if (rn == 0)
1951 drawLine(_videoBuffer, x + 1, y, x + 1, y, cl2);
1952 if (rn == 2)
1953 drawLine(_videoBuffer, x, y, x, y, cl2);
1954
1955 orn = rn;
1956
1957 if (_spellInfo[i].damagewho == 0) {
1958 for (int e = 1; e <= _lastNpc; e++) {
1959 float xdif = (x + 16) - (_npcInfo[e].x + 12);
1960 float ydif = (y + 16) - (_npcInfo[e].y + 12);
1961
1962 if ((ABS(xdif) < 8 && ABS(ydif) < 8)) {
1963 float damage = 30 * (1 + RND() * 0.5);
1964
1965 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks)
1966 damageNPC(e, damage, 1);
1967 }
1968 }
1969 }
1970
1971 // check for post damage
1972 if (_postInfoNbr > 0) {
1973 for (int e = 0; e <= _postInfoNbr - 1; e++) {
1974 float xdif = (xloc + 16) - (_postInfo[e][0] + 8);
1975 float ydif = (yloc + 16) - (_postInfo[e][1] + 8);
1976
1977 if ((ABS(xdif) < 16 && ABS(ydif) < 16)) {
1978 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
1979 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
1980
1981 rcSrc.left = _postInfo[e][0] / 2;
1982 rcSrc.top = _postInfo[e][1] / 2;
1983 rcSrc.setWidth(8);
1984 rcSrc.setHeight(8);
1985
1986 _clipBg2->fillRect(rcSrc, 0);
1987
1988 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
1989 }
1990 }
1991 }
1992 }
1993 }
1994
1995 _spellInfo[i].frame -= 0.5 * _fpsr;
1996 if (_spellInfo[i].frame < 0) {
1997 _spellInfo[i].frame = 0;
1998 _forcePause = false;
1999 }
2000 }
2001
2002 // wizard 1 lightning
2003 if (spellnum == 9) {
2004 long cl1 = _videoBuffer->format.RGBToColor(0, 32, 204);
2005 long cl2 = _videoBuffer->format.RGBToColor(142, 173, 191);
2006 long cl3 = _videoBuffer->format.RGBToColor(240, 240, 240);
2007
2008 int px = _spellInfo[i].enemyx + 12;
2009 int py = _spellInfo[i].enemyy + 24;
2010
2011 int apx = px + (int)(RND() * 20 - 10);
2012 int apy = py + (int)(RND() * 20 - 10);
2013
2014 int x = apx;
2015 int orn = 0;
2016 for (int y = 0; y <= apy; y++) {
2017 if (y < 240) {
2018 int rn = (int)(RND() * 3);
2019
2020 if (orn == 0)
2021 x = x - 1;
2022 if (orn == 2)
2023 x = x + 1;
2024
2025 drawLine(_videoBuffer, x - 1, y, x + 2, y, cl1);
2026 drawLine(_videoBuffer, x, y, x + 1, y, cl3);
2027
2028 if (rn == 0)
2029 drawLine(_videoBuffer, x + 1, y, x + 1, y, cl2);
2030 if (rn == 2)
2031 drawLine(_videoBuffer, x, y, x, y, cl2);
2032
2033 orn = rn;
2034
2035 if (_spellInfo[i].damagewho == 1) {
2036 float xdif = (x + 8) - (_player.px + 12);
2037 float ydif = (y + 8) - (_player.py + 12);
2038
2039 if ((ABS(xdif) < 8 && ABS(ydif) < 8) && _player.pause < _ticks) {
2040 float damage = ((float)_player.hp * 0.75) * (RND() * 0.5 + 0.5);
2041 if (damage < 5)
2042 damage = 5;
2043
2044 if ((_npcInfo[_spellInfo[i].npc].spriteset == kMonsterBatKitty) && (damage < 50))
2045 damage = 40 + (int)(RND() * 40);
2046
2047 if (_player.hp > 0)
2048 damagePlayer(damage);
2049 }
2050 }
2051 }
2052 }
2053
2054 _spellInfo[i].frame -= 0.5 * _fpsr;
2055 if (_spellInfo[i].frame < 0) {
2056 _spellInfo[i].frame = 0;
2057
2058 _npcInfo[_spellInfo[i].npc].attacking = false;
2059 _npcInfo[_spellInfo[i].npc].attacknext = _ticks + _npcInfo[_spellInfo[i].npc].attackdelay;
2060 }
2061 }
2062 }
2063 }
2064 }
2065
updateSpellsUnder()2066 void GriffonEngine::updateSpellsUnder() {
2067 if (_forcePause)
2068 return;
2069
2070 for (int i = 0; i < kMaxSpell; i++) {
2071 if (_spellInfo[i].frame > 0) {
2072 int spellnum = _spellInfo[i].spellnum;
2073
2074 // water
2075 if (spellnum == 0) {
2076 int fra = (32 - _spellInfo[i].frame);
2077 int fr = (int)((32 - _spellInfo[i].frame) * 2) % 4;
2078
2079 rcSrc.left = fr * 48;
2080 rcSrc.top = 96;
2081 rcSrc.setWidth(48);
2082 rcSrc.setHeight(48);
2083
2084 rcDest.left = _spellInfo[i].enemyx - 12;
2085 rcDest.top = _spellInfo[i].enemyy - 8;
2086
2087 int f = 160;
2088 if (fra < 8)
2089 f = 160 * fra / 8;
2090 if (fra > 24)
2091 f = 160 * (1 - (fra - 24) / 8);
2092
2093 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(f, 255, 255, 255));
2094
2095 _spellInfo[i].frame = _spellInfo[i].frame - 0.2 * _fpsr;
2096 if (_spellInfo[i].frame < 0)
2097 _spellInfo[i].frame = 0;
2098
2099
2100 for (f = 1; f <= _lastNpc; f++) {
2101 int xdif = _spellInfo[i].enemyx - _npcInfo[f].x;
2102 int ydif = _spellInfo[i].enemyy - _npcInfo[f].y;
2103
2104 float dist = sqrt((float)(xdif * xdif + ydif * ydif));
2105
2106 if (dist > 20)
2107 dist = 20;
2108
2109 if (dist > 5) {
2110 float ratio = (1 - dist / 25);
2111
2112 float newx = _npcInfo[f].x + ratio * xdif / 3 * _fpsr;
2113 float newy = _npcInfo[f].y + ratio * ydif / 3 * _fpsr;
2114
2115 int sx = (newx / 2 + 6);
2116 int sy = (newy / 2 + 10);
2117
2118 uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
2119 uint32 dq = *temp;
2120
2121 if (dq == 0) {
2122 _npcInfo[f].x = newx;
2123 _npcInfo[f].y = newy;
2124 // _npcinfo[f].castpause = _ticks + 200;
2125 } else {
2126 int xpass = 0;
2127 int ypass = 0;
2128
2129 sx = (newx / 2 + 6);
2130 sy = (_npcInfo[f].y / 2 + 10);
2131 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
2132 dq = *temp;
2133
2134 if (dq == 0)
2135 xpass = 1;
2136
2137
2138 sx = (_npcInfo[f].x / 2 + 6);
2139 sy = (newy / 2 + 10);
2140 temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
2141 dq = *temp;
2142
2143 if (dq == 0)
2144 ypass = 1;
2145
2146 if (ypass == 1) {
2147 newx = _npcInfo[f].x;
2148 } else if (xpass == 1) {
2149 newy = _npcInfo[f].y;
2150 }
2151
2152 if (xpass == 1 || ypass == 1) {
2153 _npcInfo[f].x = newx;
2154 _npcInfo[f].y = newy;
2155 // _npcinfo[f].castpause = _ticks + 200;
2156 }
2157 }
2158 }
2159 }
2160 }
2161
2162 // fire
2163 if (spellnum == 3) {
2164 float fr = (32 - _spellInfo[i].frame);
2165
2166 fr = fr * fr * (1 - cos(3.14159 / 4 + 3.14159 / 4 * fr / 32));
2167
2168 if (fr > 32)
2169 fr = 32;
2170
2171 float s = 8;
2172 if (_spellInfo[i].frame < 8)
2173 s = _spellInfo[i].frame;
2174
2175 int fra = (int)fr;
2176
2177 for (int f = 0; f <= 4; f++) {
2178 for (int x = 0; x <= fra; x += 2) {
2179 if (_spellInfo[i].legalive[f] >= x) {
2180 int alpha = 192 * sin(3.14159 * x / 32) * s / 8;
2181
2182 float an = 360 / 5 * f + x / 32 * 180;
2183
2184 rcSrc.left = 16 * (int)(RND() * 2);
2185 rcSrc.top = 80;
2186 rcSrc.setWidth(16);
2187 rcSrc.setHeight(16);
2188
2189 float xloc = (float)(_spellInfo[i].enemyx + 4 + x * 2 * cos(3.14159 / 180 * an) + (int)(RND() * 3) - 1);
2190 float yloc = (float)(_spellInfo[i].enemyy + 4 + x * 2 * sin(3.14159 / 180 * an) + (int)(RND() * 3) - 1);
2191 rcDest.left = (int)xloc;
2192 rcDest.top = (int)yloc;
2193
2194 if (xloc > -1 && xloc < 304 && yloc > -1 && yloc < 224) {
2195 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(alpha, 255, 255, 255));
2196
2197 int sx = (xloc / 2 + 4);
2198 int sy = (yloc / 2 + 8);
2199
2200 uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
2201 uint32 dq = *temp;
2202
2203 if (dq > 1000 && x > 4)
2204 _spellInfo[i].legalive[f] = x;
2205
2206 if (_spellInfo[i].damagewho == 0) {
2207 for (int e = 1; e <= _lastNpc; e++) {
2208 float xdif = (xloc + 8) - (_npcInfo[e].x + 12);
2209 float ydif = (yloc + 8) - (_npcInfo[e].y + 12);
2210
2211 if ((ABS(xdif) < 8 && ABS(ydif) < 8)) {
2212 float damage = (float)_player.spellDamage * (1.0 + RND() * 0.5) * (float)_spellInfo[i].strength;
2213
2214 if (_npcInfo[e].spriteset == kMonsterFireHydra)
2215 damage = -damage;
2216 if (_npcInfo[e].spriteset == kMonsterFinalBoss)
2217 damage = -damage;
2218 if (_npcInfo[e].hp > 0 && _npcInfo[e].pause < _ticks) {
2219 damageNPC(e, damage, 1);
2220 if (config.effects) {
2221 int snd = playSound(_sfx[kSndFire]);
2222 setChannelVolume(snd, config.effectsVol);
2223 }
2224 }
2225 }
2226 }
2227 }
2228
2229 if (_spellInfo[i].damagewho == 1) {
2230 float xdif = (xloc + 8) - (_player.px + 12);
2231 float ydif = (yloc + 8) - (_player.py + 12);
2232
2233 if ((ABS(xdif) < 8 && ABS(ydif) < 8) && _player.pause < _ticks) {
2234 float damage = (float)_npcInfo[_spellInfo[i].npc].spellDamage * (1.0 + RND() * 0.5);
2235
2236 if (_player.hp > 0) {
2237 damagePlayer(damage);
2238
2239 if (config.effects) {
2240 int snd = playSound(_sfx[kSndFire]);
2241 setChannelVolume(snd, config.effectsVol);
2242 }
2243 }
2244 }
2245 }
2246
2247 // check for post damage
2248 if (_postInfoNbr > 0) {
2249 for (int e = 0; e <= _postInfoNbr - 1; e++) {
2250 float xdif = (xloc + 8) - (_postInfo[e][0] + 8);
2251 float ydif = (yloc + 8) - (_postInfo[e][1] + 8);
2252
2253 if ((ABS(xdif) < 8 && ABS(ydif) < 8)) {
2254 _objectMapFull[_curMap][(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = 1;
2255 _objectMap[(int)_postInfo[e][0] / 16][(int)_postInfo[e][1] / 16] = -1;
2256
2257 rcSrc.left = _postInfo[e][0] / 2;
2258 rcSrc.top = _postInfo[e][1] / 2;
2259 rcSrc.setWidth(8);
2260 rcSrc.setHeight(8);
2261
2262 _clipBg2->fillRect(rcSrc, 0);
2263
2264 if (config.effects) {
2265 int snd = playSound(_sfx[kSndFire]);
2266 setChannelVolume(snd, config.effectsVol);
2267 }
2268
2269 addFloatIcon(99, _postInfo[e][0], _postInfo[e][1]);
2270 }
2271 }
2272 }
2273 }
2274 }
2275 }
2276 }
2277
2278 _spellInfo[i].frame = _spellInfo[i].frame - 0.2 * _fpsr;
2279 if (_spellInfo[i].frame < 0)
2280 _spellInfo[i].frame = 0;
2281
2282
2283 }
2284
2285
2286 // sprite 6 spitfire
2287 if (spellnum == 7) {
2288 float xspan = _spellInfo[i].enemyx - _spellInfo[i].homex;
2289 float yspan = _spellInfo[i].enemyy - _spellInfo[i].homey;
2290 float fr = (32 - _spellInfo[i].frame);
2291
2292 for (int f = 0; f <= 7; f++) {
2293 int alpha = 0;
2294 float xx = 0;
2295 if (fr > f * 2 && fr < f * 2 + 16)
2296 xx = fr - f * 2;
2297 if (xx < 8)
2298 alpha = 255 * xx / 8;
2299 if (xx > 8)
2300 alpha = 255 * (1 - (xx - 8) / 8);
2301 float yy = 16 * sin(3.141592 / 2 * xx / 16) - 8;
2302
2303 alpha = CLIP(alpha, 0, 255);
2304
2305 rcSrc.left = 16 * (int)(RND() * 2);
2306 rcSrc.top = 80;
2307 rcSrc.setWidth(16);
2308 rcSrc.setHeight(16);
2309
2310 float xloc = _spellInfo[i].homex + xspan / 7 * f;
2311 float yloc = _spellInfo[i].homey + yspan / 7 * f - yy;
2312
2313 rcDest.left = xloc;
2314 rcDest.top = yloc;
2315
2316 if (xloc > -16 && xloc < 320 && yloc > -16 && yloc < 240) {
2317 _spellImg->blit(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(alpha, 255, 255, 255));
2318
2319 if (_spellInfo[i].damagewho == 1) {
2320 float xdif = (xloc + 8) - (_player.px + 12);
2321 float ydif = (yloc + 8) - (_player.py + 12);
2322
2323 if ((ABS(xdif) < 8 && ABS(ydif) < 8) && _player.pause < _ticks && alpha > 64) {
2324 float damage = (float)_npcInfo[_spellInfo[i].npc].spellDamage * (1.0 + RND() * 0.5);
2325
2326 if (_player.hp > 0) {
2327 damagePlayer(damage);
2328 if (config.effects) {
2329 int snd = playSound(_sfx[kSndFire]);
2330 setChannelVolume(snd, config.effectsVol);
2331 }
2332 }
2333
2334 }
2335 }
2336
2337 }
2338
2339 }
2340
2341 _spellInfo[i].frame = _spellInfo[i].frame - 0.5 * _fpsr;
2342 if (_spellInfo[i].frame < 0)
2343 _spellInfo[i].frame = 0;
2344
2345 if (ABS(_spellInfo[i].frame) < kEpsilon) {
2346 _npcInfo[_spellInfo[i].npc].attacking = false;
2347 _npcInfo[_spellInfo[i].npc].attacknext = _ticks + _npcInfo[_spellInfo[i].npc].attackdelay;
2348 }
2349 }
2350 }
2351 }
2352 }
2353
2354
2355 } // end of namespace Griffon
2356