1 /****************************************************************************
2 Witchaven
3
4 WHFX.C
5
6 Rafael Paiz
7
8 ****************************************************************************/
9
10 #include "effects.h"
11 #include "player.h"
12 #include "sound.h"
13 #include "objects.h"
14 #include "witchaven.h"
15 #include "input.h"
16 #include "view.h"
17
18 #define LAVASIZ 128
19 #define LAVALOGSIZ 7
20 #define LAVAMAXDROPS 32
21
22 #define WATERSIZ 128
23 #define WATERLOGSIZ 7
24 #define WATERMAXDROPS 16 // bjd - this was 1 but contradicts the way arrays sized with this define were accessed
25
26 #define FLOORUNIT 16384L
27
28 int justwarpedfx = 0;
29 int lastbat = -1;
30
31 extern int justteleported;
32
33 extern short lavadrylandsector[32];
34 extern short lavadrylandcnt;
35
36
37 static char lavabakpic[(LAVASIZ+2)*(LAVASIZ+2)], lavainc[LAVASIZ];
38 static int lavanumdrops, lavanumframes;
39 static int lavadropx[LAVAMAXDROPS], lavadropy[LAVAMAXDROPS];
40 static int lavadropsiz[LAVAMAXDROPS], lavadropsizlookup[LAVAMAXDROPS];
41 static int lavaradx[32][128], lavarady[32][128], lavaradcnt[32];
42
43 static char waterbakpic[(WATERSIZ+2)*(WATERSIZ+2)], waterinc[WATERSIZ];
44 static int waternumdrops, waternumframes;
45 static int waterdropx[WATERMAXDROPS], waterdropy[WATERMAXDROPS];
46 static int waterdropsiz[WATERMAXDROPS], waterdropsizlookup[WATERMAXDROPS];
47 static int waterradx[32][128], waterrady[32][128], waterradcnt[32];
48
49 extern short revolvesector[], revolveang[], revolveclip[], revolvecnt;
50 extern int revolvex[16][16], revolvey[16][16];
51 extern int revolvepivotx[], revolvepivoty[];
52
53 extern short xpanningsectorlist[], xpanningsectorcnt;
54 extern short ypanningwalllist[], ypanningwallcnt;
55 extern short floorpanninglist[], floorpanningcnt;
56 extern short skypanlist[], skypancnt;
57 extern short crushsectorlist[], crushsectorcnt;
58 extern short crushsectoranim[], crushsectordone[];
59 extern short bobbingsectorcnt, bobbingsectorlist[];
60 extern short warpsectorlist[], warpsectorcnt;
61
62 char revolvesyncstat;
63 short revolvesyncang, revolvesyncrotang;
64 int revolvesyncx, revolvesyncy;
65
66 extern int mapon;
67
68
initlava()69 void initlava()
70 {
71 for (int x = -16; x <= 16; x++)
72 {
73 for (int y = -16; y <= 16; y++)
74 {
75 int r = ksqrt(x * x + y * y);
76 lavaradx[r][lavaradcnt[r]] = x;
77 lavarady[r][lavaradcnt[r]] = y;
78 lavaradcnt[r]++;
79 }
80 }
81
82 for (int z = 0; z < 16; z++)
83 lavadropsizlookup[z] = 8 / (ksqrt(z) + 1);
84
85 for (int z = 0; z < LAVASIZ; z++)
86 lavainc[z] = klabs((((z ^ 17) >> 4) & 7) - 4) + 12;
87
88 lavanumdrops = 0;
89 lavanumframes = 0;
90 }
91
movelava(char * dapic)92 void movelava(char* dapic)
93 {
94 char dat, * ptr;
95 int32_t x, y, z, zx, dalavadropsiz, dadropsizlookup;
96 intptr_t offs, offs2;
97 int32_t dalavax, dalavay;
98
99 z = 3;
100 if (lavanumdrops + z >= LAVAMAXDROPS)
101 z = LAVAMAXDROPS - lavanumdrops - 1;
102
103 while (z >= 0)
104 {
105 lavadropx[lavanumdrops] = (rand() & (LAVASIZ - 1));
106 lavadropy[lavanumdrops] = (rand() & (LAVASIZ - 1));
107 lavadropsiz[lavanumdrops] = 1;
108 lavanumdrops++;
109 z--;
110 }
111
112 z = lavanumdrops - 1;
113 while (z >= 0)
114 {
115 dadropsizlookup = lavadropsizlookup[lavadropsiz[z]] * (((z & 1) << 1) - 1);
116 dalavadropsiz = lavadropsiz[z];
117 dalavax = lavadropx[z]; dalavay = lavadropy[z];
118 for (zx = lavaradcnt[lavadropsiz[z]] - 1; zx >= 0; zx--)
119 {
120 offs = (((lavaradx[dalavadropsiz][zx] + dalavax) & (LAVASIZ - 1)) << LAVALOGSIZ);
121 offs += ((lavarady[dalavadropsiz][zx] + dalavay) & (LAVASIZ - 1));
122 dapic[offs] += dadropsizlookup;
123
124 if (dapic[offs] < 192)
125 dapic[offs] = 192;
126 }
127
128 lavadropsiz[z]++;
129 if (lavadropsiz[z] > 10)
130 {
131 lavanumdrops--;
132 lavadropx[z] = lavadropx[lavanumdrops];
133 lavadropy[z] = lavadropy[lavanumdrops];
134 lavadropsiz[z] = lavadropsiz[lavanumdrops];
135 }
136 z--;
137 }
138
139 //Back up dapic with 1 pixel extra on each boundary
140 //(to prevent anding for wrap-around)
141 offs = ((intptr_t)dapic);
142 offs2 = (LAVASIZ + 2) + 1 + ((intptr_t)lavabakpic);
143 for (x = 0; x < LAVASIZ; x++)
144 {
145 copybuf((char*)offs, (char*)offs2, LAVASIZ >> 2);
146 offs += LAVASIZ;
147 offs2 += LAVASIZ + 2;
148 }
149 for (y = 0; y < LAVASIZ; y++)
150 {
151 lavabakpic[y + 1] = dapic[y + ((LAVASIZ - 1) << LAVALOGSIZ)];
152 lavabakpic[y + 1 + (LAVASIZ + 1) * (LAVASIZ + 2)] = dapic[y];
153 }
154 for (x = 0; x < LAVASIZ; x++)
155 {
156 lavabakpic[(x + 1) * (LAVASIZ + 2)] = dapic[(x << LAVALOGSIZ) + (LAVASIZ - 1)];
157 lavabakpic[(x + 1) * (LAVASIZ + 2) + (LAVASIZ + 1)] = dapic[x << LAVALOGSIZ];
158 }
159 lavabakpic[0] = dapic[LAVASIZ * LAVASIZ - 1];
160 lavabakpic[LAVASIZ + 1] = dapic[LAVASIZ * (LAVASIZ - 1)];
161 lavabakpic[(LAVASIZ + 2) * (LAVASIZ + 1)] = dapic[LAVASIZ - 1];
162 lavabakpic[(LAVASIZ + 2) * (LAVASIZ + 2) - 1] = dapic[0];
163
164 for (z = (LAVASIZ + 2) * (LAVASIZ + 2) - 4; z >= 0; z -= 4)
165 {
166 lavabakpic[z + 0] &= 31;
167 lavabakpic[z + 1] &= 31;
168 lavabakpic[z + 2] &= 31;
169 lavabakpic[z + 3] &= 31;
170 }
171
172 for (x = LAVASIZ - 1; x >= 0; x--)
173 {
174 offs = (x + 1) * (LAVASIZ + 2) + 1;
175 ptr = (char*)((x << LAVALOGSIZ) + (intptr_t)dapic);
176
177 zx = ((x + lavanumframes) & (LAVASIZ - 1));
178
179 offs2 = LAVASIZ - 1;
180 for (y = offs; y < offs + LAVASIZ; y++)
181 {
182 dat = lavainc[(offs2--) & zx];
183 dat += lavabakpic[y - (LAVASIZ + 2) - 1];
184 dat += lavabakpic[y - (LAVASIZ + 2)];
185 dat += lavabakpic[y - (LAVASIZ + 2) + 1];
186 dat += lavabakpic[y - 1];
187 dat += lavabakpic[y + 1];
188 dat += lavabakpic[y + (LAVASIZ + 2)];
189 dat += lavabakpic[y + (LAVASIZ + 2) - 1];
190 *ptr++ = (dat >> 3) + 192;
191 }
192 }
193
194 lavanumframes++;
195 }
196
initwater()197 void initwater()
198 {
199 for (int x = -16; x <= 16; x++)
200 {
201 for (int y = -16; y <= 16; y++)
202 {
203 int r = ksqrt(x * x + y * y);
204 waterradx[r][waterradcnt[r]] = x;
205 waterrady[r][waterradcnt[r]] = y;
206 waterradcnt[r]++;
207 }
208 }
209
210 for (int z = 0; z < WATERMAXDROPS; z++)
211 waterdropsizlookup[z] = 8 / (ksqrt(z) + 1);
212
213 for (int z = 0; z < WATERSIZ; z++)
214 waterinc[z] = klabs((((z ^ 17) >> 4) & 7) - 4) + 12;
215
216 waternumdrops = 0;
217 waternumframes = 0;
218 }
219
movewater(char * dapic)220 void movewater(char* dapic)
221 {
222 char dat, * ptr;
223 int32_t x, y, z, zx, dawaterdropsiz, dadropsizlookup;
224 intptr_t offs, offs2;
225 int32_t dawaterx, dawatery;
226
227 z = 3;
228 if (waternumdrops + z >= WATERMAXDROPS)
229 z = WATERMAXDROPS - waternumdrops - 1;
230
231 while (z >= 0)
232 {
233 waterdropx[waternumdrops] = (rand() & (WATERSIZ - 1));
234 waterdropy[waternumdrops] = (rand() & (WATERSIZ - 1));
235 waterdropsiz[waternumdrops] = 1;
236 waternumdrops++;
237 z--;
238 }
239
240 z = waternumdrops - 1;
241
242 while (z >= 0)
243 {
244 dadropsizlookup = waterdropsizlookup[waterdropsiz[z]] * (((z & 1) << 1) - 1);
245 dawaterdropsiz = waterdropsiz[z];
246 dawaterx = waterdropx[z]; dawatery = waterdropy[z];
247 for (zx = waterradcnt[waterdropsiz[z]] - 1; zx >= 0; zx--)
248 {
249 offs = (((waterradx[dawaterdropsiz][zx] + dawaterx) & (WATERSIZ - 1)) << WATERLOGSIZ);
250 offs += ((waterrady[dawaterdropsiz][zx] + dawatery) & (WATERSIZ - 1));
251 dapic[offs] += dadropsizlookup;
252 if (dapic[offs] < 224) dapic[offs] = 224;
253 }
254
255 waterdropsiz[z]++;
256 if (waterdropsiz[z] > 10)
257 {
258 waternumdrops--;
259 waterdropx[z] = waterdropx[waternumdrops];
260 waterdropy[z] = waterdropy[waternumdrops];
261 waterdropsiz[z] = waterdropsiz[waternumdrops];
262 }
263 z--;
264 }
265
266 offs = ((intptr_t)dapic);
267 offs2 = (WATERSIZ + 2) + 1 + ((intptr_t)waterbakpic);
268
269 for (x = 0; x < WATERSIZ; x++)
270 {
271 copybuf((char*)offs, (char*)offs2, WATERSIZ >> 2);
272 offs += WATERSIZ;
273 offs2 += WATERSIZ + 2;
274 }
275 for (y = 0; y < WATERSIZ; y++)
276 {
277 waterbakpic[y + 1] = dapic[y + ((WATERSIZ - 1) << WATERLOGSIZ)];
278 waterbakpic[y + 1 + (WATERSIZ + 1) * (WATERSIZ + 2)] = dapic[y];
279 }
280 for (x = 0; x < WATERSIZ; x++)
281 {
282 waterbakpic[(x + 1) * (WATERSIZ + 2)] = dapic[(x << WATERLOGSIZ) + (WATERSIZ - 1)];
283 waterbakpic[(x + 1) * (WATERSIZ + 2) + (WATERSIZ + 1)] = dapic[x << WATERLOGSIZ];
284 }
285
286 waterbakpic[0] = dapic[WATERSIZ * WATERSIZ - 1];
287 waterbakpic[WATERSIZ + 1] = dapic[WATERSIZ * (WATERSIZ - 1)];
288 waterbakpic[(WATERSIZ + 2) * (WATERSIZ + 1)] = dapic[WATERSIZ - 1];
289 waterbakpic[(WATERSIZ + 2) * (WATERSIZ + 2) - 1] = dapic[0];
290
291 for (z = (WATERSIZ + 2) * (WATERSIZ + 2) - 4; z >= 0; z -= 4)
292 {
293 waterbakpic[z + 0] &= 15;
294 waterbakpic[z + 1] &= 15;
295 waterbakpic[z + 2] &= 15;
296 waterbakpic[z + 3] &= 15;
297 }
298
299 for (x = WATERSIZ - 1; x >= 0; x--)
300 {
301 offs = (x + 1) * (WATERSIZ + 2) + 1;
302 ptr = (char*)((x << WATERLOGSIZ) + (intptr_t)dapic);
303
304 zx = ((x + waternumframes) & (WATERSIZ - 1));
305
306 offs2 = WATERSIZ - 1;
307 for (y = offs; y < offs + WATERSIZ; y++)
308 {
309 dat = waterinc[(offs2--) & zx];
310 dat += waterbakpic[y - (WATERSIZ + 2) - 1];
311 dat += waterbakpic[y - (WATERSIZ + 2)];
312 dat += waterbakpic[y - (WATERSIZ + 2) + 1];
313 dat += waterbakpic[y - 1];
314 dat += waterbakpic[y + 1];
315 dat += waterbakpic[y + (WATERSIZ + 2) + 1];
316 dat += waterbakpic[y + (WATERSIZ + 2)];
317 dat += waterbakpic[y + (WATERSIZ + 2) - 1];
318 *ptr++ = (dat >> 3) + 223;
319 }
320 }
321
322 waternumframes++;
323 }
324
skypanfx()325 void skypanfx()
326 {
327 for (int i = 0; i < skypancnt; i++) {
328 sector[skypanlist[i]].ceilingxpanning = -((lockclock >> 2) & 255);
329 }
330 }
331
panningfx()332 void panningfx()
333 {
334 Player* plr = &player[pyrn];
335
336 //
337 // n ne e se s sw w nw
338 // 0 1 2 3 4 5 6 7
339 //
340 for (int i = 0; i < floorpanningcnt; i++)
341 {
342 short whichdir = sector[floorpanninglist[i]].lotag - 80;
343
344 switch (whichdir)
345 {
346 case 0:
347 sector[floorpanninglist[i]].floorypanning = ((lockclock >> 2) & 255);
348 break;
349 case 1:
350 sector[floorpanninglist[i]].floorxpanning = -((lockclock >> 2) & 255);
351 sector[floorpanninglist[i]].floorypanning = ((lockclock >> 2) & 255);
352 break;
353 case 2:
354 sector[floorpanninglist[i]].floorxpanning = -((lockclock >> 2) & 255);
355 break;
356 case 3:
357 sector[floorpanninglist[i]].floorxpanning = -((lockclock >> 2) & 255);
358 sector[floorpanninglist[i]].floorypanning = -((lockclock >> 2) & 255);
359 break;
360 case 4:
361 sector[floorpanninglist[i]].floorypanning = -((lockclock >> 2) & 255);
362 break;
363 case 5:
364 sector[floorpanninglist[i]].floorxpanning = ((lockclock >> 2) & 255);
365 sector[floorpanninglist[i]].floorypanning = -((lockclock >> 2) & 255);
366 break;
367 case 6:
368 sector[floorpanninglist[i]].floorxpanning = ((lockclock >> 2) & 255);
369 break;
370 case 7:
371 sector[floorpanninglist[i]].floorxpanning = ((lockclock >> 2) & 255);
372 sector[floorpanninglist[i]].floorypanning = ((lockclock >> 2) & 255);
373 break;
374 default:
375 sector[floorpanninglist[i]].floorxpanning = 0;
376 sector[floorpanninglist[i]].floorypanning = 0;
377 break;
378 }
379 }
380
381 for (int i = 0; i < xpanningsectorcnt; i++)
382 {
383 short dasector = xpanningsectorlist[i];
384 short startwall = sector[dasector].wallptr;
385 short endwall = startwall + sector[dasector].wallnum - 1;
386 for (int s = startwall; s <= endwall; s++)
387 {
388 wall[s].xpanning = ((lockclock >> 2) & 255);
389 }
390 }
391
392 for (int i = 0; i < ypanningwallcnt; i++) {
393 wall[ypanningwalllist[i]].ypanning = ~(lockclock & 255);
394 }
395 }
396
crushingfx()397 void crushingfx()
398 {
399 int j, s;
400 int32_t daz, goalz;
401
402 for (int i = 0; i < crushsectorcnt; i++)
403 {
404 s = crushsectorlist[i];
405
406 if (crushsectordone[s] == 1)
407 {
408 switch (crushsectoranim[s])
409 {
410 case 1:
411 if ((j = getanimationgoal(§or[s].floorz)) < 0)
412 {
413 setanimation(§or[s].floorz, sector[s].ceilingz, 64);
414 crushsectordone[s] = 2;
415 }
416 break;
417 case 2:
418 if ((j = getanimationgoal(§or[s].ceilingz)) < 0)
419 {
420 setanimation(§or[s].ceilingz, sector[s].floorz, 64);
421 crushsectordone[s] = 2;
422 }
423 break;
424 case 3:
425 if ((j = getanimationgoal(§or[s].ceilingz)) < 0)
426 {
427 daz = (sector[s].ceilingz + sector[s].floorz) >> 1;
428 setanimation(§or[s].ceilingz, daz, 64);
429 setanimation(§or[s].floorz, daz, 64);
430 crushsectordone[s] = 2;
431 }
432 break;
433 }
434 }
435
436 if (crushsectordone[s] == 2)
437 {
438 switch (crushsectoranim[s])
439 {
440 case 1:
441 if ((j = getanimationgoal(§or[s].floorz)) < 0)
442 {
443 goalz = sector[nextsectorneighborz(s, sector[s].floorz, 1, 1)].floorz;
444 setanimation(§or[s].floorz, goalz, 64);
445 crushsectordone[s] = 1;
446 }
447 break;
448 case 2:
449 if ((j = getanimationgoal(§or[s].ceilingz)) < 0)
450 {
451 goalz = sector[nextsectorneighborz(s, sector[s].ceilingz, -1, -1)].ceilingz;
452 setanimation(§or[s].ceilingz, goalz, 64);
453 crushsectordone[s] = 1;
454 }
455 break;
456 case 3:
457 if ((j = getanimationgoal(§or[s].ceilingz)) < 0)
458 {
459 goalz = sector[nextsectorneighborz(s, sector[s].ceilingz, -1, -1)].ceilingz;
460 setanimation(§or[s].ceilingz, goalz, 64);
461 goalz = sector[nextsectorneighborz(s, sector[s].floorz, 1, 1)].floorz;
462 setanimation(§or[s].floorz, goalz, 64);
463 crushsectordone[s] = 1;
464 }
465 break;
466 }
467 }
468 }
469 }
470
revolvefx()471 void revolvefx()
472 {
473 int32_t dax, day;
474 Player* plr = &player[pyrn];
475
476 for (int i = 0; i < revolvecnt; i++)
477 {
478 short startwall = sector[revolvesector[i]].wallptr;
479 short endwall = startwall + sector[revolvesector[i]].wallnum - 1;
480
481 revolveang[i] = ((revolveang[i] + 2048 - (synctics << 1)) & kAngleMask);
482
483 for (int k = startwall; k <= endwall; k++)
484 {
485 vec2_t pivot;
486 pivot.x = revolvepivotx[i];
487 pivot.y = revolvepivoty[i];
488
489 vec2_t p;
490 p.x = revolvex[i][k - startwall];
491 p.y = revolvey[i][k - startwall];
492
493 vec2_t p2;
494 rotatepoint(pivot, p, revolveang[i], &p2);
495
496 dax = p2.x;
497 day = p2.y;
498
499 dragpoint(k, dax, day, 0); // CHECKME - flags
500 }
501
502 if (plr->sector == revolvesector[i])
503 {
504 revolvesyncang = plr->ang;
505 revolvesyncrotang = 0;
506 revolvesyncx = plr->x;
507 revolvesyncy = plr->y;
508 revolvesyncrotang = ((revolvesyncrotang + 2048 - (synctics << 1)) & kAngleMask);
509
510 vec2_t pivot;
511 pivot.x = revolvepivotx[i];
512 pivot.y = revolvepivoty[i];
513
514 vec2_t p;
515 p.x = revolvesyncx;
516 p.y = revolvesyncy;
517
518 vec2_t p2;
519 p2.x = plr->x;
520 p2.y = plr->y;
521
522 rotatepoint(pivot, p, revolvesyncrotang, &p2);
523
524 plr->x = p2.x;
525 plr->y = p2.y;
526
527 plr->ang = ((revolvesyncang + revolvesyncrotang) & kAngleMask);
528 }
529 }
530 }
531
bobbingsector()532 void bobbingsector()
533 {
534 for (int i = 0; i < bobbingsectorcnt; i++)
535 {
536 int dasector = bobbingsectorlist[i];
537
538 sector[dasector].floorz += Sin(lockclock << 4) >> 6;
539 }
540 }
541
542
543 #define NEXTLEVEL 1
544 #define ENDOFDEMO 2
545
teleporter()546 void teleporter()
547 {
548 short dasector;
549 short startwall, endwall;
550 int i, j;
551 int s;
552 short daang;
553
554 Player* plr = &player[pyrn];
555
556 for (i = 0; i < warpsectorcnt; i++)
557 {
558 dasector = warpsectorlist[i];
559 j = ((lockclock & 127) >> 2);
560
561 if (j >= 16) j = 31 - j;
562 {
563 sector[dasector].ceilingshade = j;
564 sector[dasector].floorshade = j;
565 startwall = sector[dasector].wallptr;
566 endwall = startwall + sector[dasector].wallnum - 1;
567 for (s = startwall; s <= endwall; s++)
568 wall[s].shade = j;
569 }
570 }
571
572 if (sector[plr->sector].lotag == 10)
573 {
574 if (plr->sector != plr->oldsector)
575 {
576 daang = (short)plr->ang;
577 warpfxsprite(plr->spritenum);
578 warp(&plr->x, &plr->y, &plr->z, &daang, &plr->sector);
579 warpfxsprite(plr->spritenum);
580 plr->ang = (int)daang;
581 justwarpedfx = 48;
582 //JSA PLUTO
583 playsound_loc(S_WARP, plr->x, plr->y);
584
585 vec3_t pos;
586 pos.x = plr->x;
587 pos.y = plr->y;
588 pos.z = plr->z + (32 << 8);
589
590 setsprite(plr->spritenum, &pos);
591 }
592 }
593
594 if (sector[plr->sector].lotag == 4002)
595 {
596 if (plr->treasure[8] == 1)
597 {
598 plr->treasure[8] = 0;
599 if (plr->sector != plr->oldsector)
600 {
601 switch (sector[plr->sector].hitag)
602 {
603 case NEXTLEVEL:
604 justteleported = 1;
605 mapon++;
606 vel = 0;
607 angvel = 0;
608 svel = 0;
609 playsound_loc(S_CHAINDOOR1, plr->x, plr->y);
610 loadnewlevel(mapon);
611 warpfxsprite(plr->spritenum);
612 // cleans up the keys (ivorykey etc)
613 plr->treasure[14] = plr->treasure[15] = plr->treasure[16] = plr->treasure[17] = 0;
614 plr->treasure[4] = plr->treasure[5] = 0;
615 SND_CheckLoops();
616 break;
617 case ENDOFDEMO:
618 playsound_loc(S_THUNDER1, plr->x, plr->y);
619 justteleported = 1;
620 victory();
621 SND_CheckLoops();
622 break;
623 }
624 }
625 }
626 else
627 {
628 // player need pentagram to teleport
629 StatusMessage(360, "ITEM NEEDED");
630 }
631 }
632 }
633
warp(int32_t * x,int32_t * y,int32_t * z,short * daang,short * dasector)634 void warp(int32_t* x, int32_t* y, int32_t* z, short* daang, short* dasector)
635 {
636 short startwall, endwall, s;
637 int32_t i, dax, day;
638
639 for (int i = 0; i < warpsectorcnt; i++)
640 {
641 if (sector[warpsectorlist[i]].hitag == sector[*dasector].hitag && warpsectorlist[i] != *dasector)
642 {
643 *dasector = warpsectorlist[i];
644 break;
645 }
646 }
647
648 startwall = sector[*dasector].wallptr;
649 endwall = startwall + sector[*dasector].wallnum - 1;
650 dax = 0, day = 0;
651
652 for (s = startwall; s <= endwall; s++)
653 {
654 dax += wall[s].x, day += wall[s].y;
655 if (wall[s].nextsector >= 0)
656 {
657 i = s;
658 }
659 }
660
661 *x = dax / (endwall - startwall + 1);
662 *y = day / (endwall - startwall + 1);
663 *z = sector[*dasector].floorz - (32 << 8);
664 updatesector(*x, *y, dasector);
665 dax = ((wall[i].x + wall[wall[i].point2].x) >> 1);
666 day = ((wall[i].y + wall[wall[i].point2].y) >> 1);
667 *daang = getangle(dax - *x, day - *y);
668 }
669
warpsprite(short spritenum)670 void warpsprite(short spritenum)
671 {
672 short dasectnum = sprite[spritenum].sectnum;
673
674 warpfxsprite(spritenum);
675 warp(&sprite[spritenum].x, &sprite[spritenum].y, &sprite[spritenum].z, &sprite[spritenum].ang, &dasectnum);
676
677 warpfxsprite(spritenum);
678
679 vec3_t pos;
680 pos.x = sprite[spritenum].x;
681 pos.y = sprite[spritenum].y;
682 pos.z = sprite[spritenum].z;
683
684 setsprite(spritenum, &pos);
685 }
686
687 #define GRATEROT 16
688 #define GRATEVERT 512
689
ironbars()690 void ironbars()
691 {
692 int32_t spritenum;
693 int32_t ironbarmove;
694
695 for (int i = 0; i < ironbarscnt; i++)
696 {
697 if (ironbarsdone[i] == 1)
698 {
699 spritenum = ironbarsanim[i];
700
701 switch (sprite[ironbarsanim[i]].hitag)
702 {
703 case 1:
704 {
705 sprite[ironbarsanim[i]].ang += synctics << 1;
706 if (sprite[ironbarsanim[i]].ang > 2047)
707 sprite[ironbarsanim[i]].ang -= 2047;
708 ironbarmove = ironbarsgoal[i] += synctics << 1;
709
710 vec3_t pos;
711 pos.x = sprite[spritenum].x;
712 pos.y = sprite[spritenum].y;
713 pos.z = sprite[spritenum].z;
714
715 setsprite(spritenum, &pos);
716 if (ironbarsgoal[i] > 512)
717 {
718 ironbarsgoal[i] = 0;
719 sprite[ironbarsanim[i]].hitag = 2;
720 ironbarsdone[i] = 0;
721 }
722 break;
723 }
724 case 2:
725 {
726 sprite[ironbarsanim[i]].ang -= synctics << 1;
727 if (sprite[ironbarsanim[i]].ang < 0)
728 sprite[ironbarsanim[i]].ang += 2047;
729 ironbarsgoal[i] += synctics << 1;
730
731 vec3_t pos;
732 pos.x = sprite[spritenum].x;
733 pos.y = sprite[spritenum].y;
734 pos.z = sprite[spritenum].z;
735
736 setsprite(spritenum, &pos);
737 if (ironbarsgoal[i] > 512)
738 {
739 ironbarsgoal[i] = 0;
740 sprite[ironbarsanim[i]].hitag = 1;
741 ironbarsdone[i] = 0;
742 }
743 break;
744 }
745 case 3:
746 {
747 sprite[ironbarsanim[i]].z -= synctics << 4;
748 if (sprite[ironbarsanim[i]].z < ironbarsgoal[i])
749 {
750 sprite[ironbarsanim[i]].z = ironbarsgoal[i];
751 sprite[ironbarsanim[i]].hitag = 4;
752 ironbarsdone[i] = 0;
753 ironbarsgoal[i] = sprite[ironbarsanim[i]].z + 6000;
754 }
755
756 vec3_t pos;
757 pos.x = sprite[spritenum].x;
758 pos.y = sprite[spritenum].y;
759 pos.z = sprite[spritenum].z;
760
761 setsprite(spritenum, &pos);
762 break;
763 }
764 case 4:
765 {
766 sprite[ironbarsanim[i]].z += synctics << 4;
767 if (sprite[ironbarsanim[i]].z > ironbarsgoal[i])
768 {
769 sprite[ironbarsanim[i]].z = ironbarsgoal[i];
770 sprite[ironbarsanim[i]].hitag = 3;
771 ironbarsdone[i] = 0;
772 ironbarsgoal[i] = sprite[ironbarsanim[i]].z - 6000;
773 }
774
775 vec3_t pos;
776 pos.x = sprite[spritenum].x;
777 pos.y = sprite[spritenum].y;
778 pos.z = sprite[spritenum].z;
779
780 setsprite(spritenum, &pos);
781 break;
782 }
783 }
784 }
785 }
786 }
787
sectorsounds()788 void sectorsounds()
789 {
790 uint16_t sec;
791 int index;
792
793 if (!SoundMode)
794 return;
795
796 Player* plr = &player[pyrn];
797
798 sec = sector[plr->sector].extra;
799
800 if (sec)
801 {
802 if (sec & 32768)
803 {
804 // loop on/off sector
805 if (sec & 1)
806 {
807 // turn loop on if lsb is 1
808 index = ((sec ^ 32769) >> 1);
809 if (ambsoundarray[index].hsound == -1)
810 ambsoundarray[index].hsound = SND_PlaySound(ambsoundarray[index].soundnum, 0, 0, 0, -1);
811 }
812 else
813 {
814 // turn loop off if lsb is 0 and its playing
815 index = ((sec ^ 32768) >> 1);
816 if (ambsoundarray[index].hsound != -1)
817 {
818 SND_StopLoop(ambsoundarray[index].hsound);
819 ambsoundarray[index].hsound = -1;
820 }
821 }
822 }
823 else
824 {
825 if (plr->z <= sector[plr->sector].floorz - (8 << 8))
826 playsound_loc(sec, plr->x, plr->y);
827 }
828 }
829 }
830
831 int scarytime=-1;
832 int scarysize=0;
833
scary()834 void scary()
835 {
836 if (rand() > 32600 && rand() > 32600 && scarytime < 0)
837 {
838 scarytime = 180;
839 scarysize = 30;
840 SND_PlaySound(S_SCARYDUDE, 0, 0, 0, 0);
841 }
842
843 if (scarytime >= 0)
844 {
845 scarytime -= synctics << 1;
846 scarysize += synctics << 1;
847 if (scarytime > 140 && scarytime < 180)
848 rotatesprite_fs(320 << 15, 200 << 15, scarysize << 9, 0, SCARY, 0, 0, 1 + 2);
849 if (scarytime > 120 && scarytime < 139)
850 rotatesprite_fs(320 << 15, 200 << 15, scarysize << 9, 0, SCARY + 1, 0, 0, 1 + 2);
851 if (scarytime > 100 && scarytime < 119)
852 rotatesprite_fs(320 << 15, 200 << 15, scarysize << 9, 0, SCARY + 2, 0, 0, 1 + 2);
853 if (scarytime > 0 && scarytime < 99)
854 rotatesprite_fs(320 << 15, 200 << 15, scarysize << 9, 0, SCARY + 3, 0, 0, 1 + 2);
855 }
856 }
857
dofx()858 void dofx()
859 {
860 lavadryland();
861 scary();
862
863 if (revolvecnt > 0)
864 revolvefx();
865
866 panningfx();
867 teleporter();
868 bobbingsector();
869
870 if (ironbarscnt > 0)
871 ironbars();
872
873 if ((gotpic[ANILAVA >> 3] & (1 << (ANILAVA & 7))) > 0)
874 {
875 gotpic[ANILAVA >> 3] &= ~(1 << (ANILAVA & 7));
876 if (waloff[ANILAVA] != -1)
877 {
878 movelava((char*)waloff[ANILAVA]);
879 }
880 }
881
882 if ((gotpic[HEALTHWATER >> 3] & (1 << (HEALTHWATER & 7))) > 0)
883 {
884 gotpic[HEALTHWATER >> 3] &= ~(1 << (HEALTHWATER & 7));
885 if (waloff[HEALTHWATER] != -1)
886 {
887 movewater((char*)waloff[HEALTHWATER]);
888 }
889 }
890
891 thesplash();
892 thunder();
893 cracks();
894 }
895
896 int thunderflash;
897 int thundertime;
898
thunder()899 void thunder()
900 {
901 if (thunderflash == 0)
902 {
903 if ((gotpic[SKY >> 3] & (1 << (SKY & 7))) > 0)
904 {
905 gotpic[SKY >> 3] &= ~(1 << (SKY & 7));
906 if (waloff[SKY] != -1)
907 {
908 visibility = 1024;
909 if (rand() > 32700)
910 {
911 thunderflash = 1;
912 thundertime = 120;
913 }
914 }
915 }
916 else if ((gotpic[SKY2 >> 3] & (1 << (SKY2 & 7))) > 0)
917 {
918 gotpic[SKY2 >> 3] &= ~(1 << (SKY2 & 7));
919 if (waloff[SKY2] != -1)
920 {
921 visibility = 768;
922 if (rand() > 32700)
923 {
924 thunderflash = 1;
925 thundertime = 120;
926 }
927 }
928 }
929 else if ((gotpic[SKY3 >> 3] & (1 << (SKY3 & 7))) > 0)
930 {
931 gotpic[SKY3 >> 3] &= ~(1 << (SKY3 & 7));
932 if (waloff[SKY3] != -1)
933 {
934 visibility = 512;
935 if (rand() > 32700)
936 {
937 thunderflash = 1;
938 thundertime = 120;
939 }
940 }
941 }
942 else if ((gotpic[SKY4 >> 3] & (1 << (SKY4 & 7))) > 0)
943 {
944 gotpic[SKY4 >> 3] &= ~(1 << (SKY4 & 7));
945 if (waloff[SKY4] != -1)
946 {
947 visibility = 512;
948 if (rand() > 32700)
949 {
950 thunderflash = 1;
951 thundertime = 120;
952 }
953 }
954 }
955 else if ((gotpic[SKY5 >> 3] & (1 << (SKY5 & 7))) > 0)
956 {
957 gotpic[SKY5 >> 3] &= ~(1 << (SKY5 & 7));
958 if (waloff[SKY5] != -1)
959 {
960 visibility = 1024;
961 if (rand() > 32700)
962 {
963 thunderflash = 1;
964 thundertime = 120;
965 }
966 }
967 }
968 else if ((gotpic[SKY6 >> 3] & (1 << (SKY6 & 7))) > 0)
969 {
970 gotpic[SKY6 >> 3] &= ~(1 << (SKY6 & 7));
971 if (waloff[SKY6] != -1)
972 {
973 visibility = 512;
974 if (rand() > 32700)
975 {
976 thunderflash = 1;
977 thundertime = 120;
978 }
979 }
980 }
981 else if ((gotpic[SKY7 >> 3] & (1 << (SKY7 & 7))) > 0)
982 {
983 gotpic[SKY7 >> 3] &= ~(1 << (SKY7 & 7));
984 if (waloff[SKY7] != -1)
985 {
986 visibility = 512;
987 if (rand() > 32700)
988 {
989 thunderflash = 1;
990 thundertime = 120;
991 }
992 }
993 }
994 else if ((gotpic[SKY8 >> 3] & (1 << (SKY8 & 7))) > 0)
995 {
996 gotpic[SKY8 >> 3] &= ~(1 << (SKY8 & 7));
997 if (waloff[SKY8] != -1)
998 {
999 visibility = 1024;
1000 if (rand() > 32700)
1001 {
1002 thunderflash = 1;
1003 thundertime = 120;
1004 }
1005 }
1006 }
1007 else if ((gotpic[SKY9 >> 3] & (1 << (SKY9 & 7))) > 0)
1008 {
1009 gotpic[SKY9 >> 3] &= ~(1 << (SKY9 & 7));
1010 if (waloff[SKY9] != -1)
1011 {
1012 visibility = 2048;
1013 if (rand() > 32700)
1014 {
1015 thunderflash = 1;
1016 thundertime = 120;
1017 }
1018 }
1019 }
1020 else if ((gotpic[SKY10 >> 3] & (1 << (SKY10 & 7))) > 0)
1021 {
1022 gotpic[SKY10 >> 3] &= ~(1 << (SKY10 & 7));
1023 if (waloff[SKY10] != -1)
1024 {
1025 visibility = 1024;
1026 if (rand() > 32700)
1027 {
1028 thunderflash = 1;
1029 thundertime = 120;
1030 }
1031 }
1032 }
1033 else
1034 visibility = 1024;
1035 }
1036 else
1037 {
1038 thundertime -= synctics;
1039 if (thundertime < 0)
1040 {
1041 thunderflash = 0;
1042 brightness = gbrightness;
1043 setbrightness(brightness);
1044
1045 SND_Sound(S_THUNDER1 + (rand() % 4));
1046 visibility = 1024;
1047 }
1048 }
1049
1050 if (thunderflash == 1)
1051 {
1052 if (waloff[SKY] != -1)
1053 {
1054 int val = rand() % 4;
1055 brightness += val;
1056
1057 switch (val)
1058 {
1059 case 0:
1060 visibility = 2048;
1061 break;
1062 case 1:
1063 visibility = 1024;
1064 break;
1065 case 2:
1066 visibility = 512;
1067 break;
1068 case 3:
1069 visibility = 256;
1070 break;
1071 default:
1072 visibility = 4096;
1073 break;
1074 }
1075
1076 if (brightness > 8) {
1077 brightness = 0;
1078 }
1079
1080 setbrightness(brightness);
1081 }
1082 }
1083 }
1084
thesplash()1085 void thesplash()
1086 {
1087 Player* plr = &player[pyrn];
1088
1089 if (sector[plr->sector].floorpicnum == WATER ||
1090 sector[plr->sector].floorpicnum == LAVA ||
1091 sector[plr->sector].floorpicnum == SLIME)
1092 {
1093 if (plr->sector != plr->oldsector)
1094 {
1095 if (sector[plr->sector].floorpicnum == WATER || sector[plr->sector].floorpicnum == SLIME)
1096 makeasplash(SPLASHAROO, plr);
1097 else
1098 makeasplash(LAVASPLASH, plr);
1099 }
1100 }
1101 }
1102
makeasplash(int picnum,Player * plr)1103 void makeasplash(int picnum, Player* plr)
1104 {
1105 int32_t j = insertsprite(plr->sector, MASPLASH);
1106 sprite[j].x = plr->x;
1107 sprite[j].y = plr->y;
1108 sprite[j].z = sector[plr->sector].floorz + (tilesiz[picnum].y << 8);
1109 sprite[j].cstat = 0; //Hitscan does not hit other bullets
1110 sprite[j].picnum = picnum;
1111 sprite[j].shade = 0;
1112 sprite[j].pal = 0;
1113 sprite[j].xrepeat = 64;
1114 sprite[j].yrepeat = 64;
1115 sprite[j].owner = 0;
1116 sprite[j].clipdist = 16;
1117 sprite[j].lotag = 8;
1118 sprite[j].hitag = 0;
1119
1120 switch (picnum)
1121 {
1122 case SPLASHAROO:
1123 playsound_loc(S_SPLASH1 + (krand() % 3), sprite[j].x, sprite[j].y);
1124 break;
1125 case LAVASPLASH:
1126 break;
1127 }
1128
1129 movesprite(j, (Cos(sprite[j].ang) * synctics) << 3, (((int)sintable[sprite[j].ang]) * synctics) << 3, 0, 4 << 8, 4 << 8, 0);
1130 }
1131
makemonstersplash(int picnum,int i)1132 void makemonstersplash(int picnum, int i)
1133 {
1134 if (sprite[i].picnum == FISH)
1135 return;
1136
1137 int32_t j = insertsprite(sprite[i].sectnum, MASPLASH);
1138 sprite[j].x = sprite[i].x;
1139 sprite[j].y = sprite[i].y;
1140 sprite[j].z = sector[sprite[i].sectnum].floorz + (tilesiz[picnum].y << 8);
1141 sprite[j].cstat = 0; //Hitscan does not hit other bullets
1142 sprite[j].picnum = picnum;
1143 sprite[j].shade = 0;
1144
1145 if (sector[sprite[i].sectnum].floorpal == 9)
1146 sprite[j].pal = 9;
1147 else
1148 sprite[j].pal = 0;
1149
1150 sprite[j].xrepeat = 64;
1151 sprite[j].yrepeat = 64;
1152 sprite[j].owner = 0;
1153 sprite[j].clipdist = 16;
1154 sprite[j].lotag = 8;
1155 sprite[j].hitag = 0;
1156
1157 switch (picnum)
1158 {
1159 case SPLASHAROO:
1160 if (rand() % 2)
1161 {
1162 if ((gotpic[WATER >> 3] & (1 << (WATER & 7))) > 0)
1163 {
1164 gotpic[WATER >> 3] &= ~(1 << (WATER & 7));
1165 if (waloff[WATER] != -1)
1166 {
1167 if (rand() % 2)
1168 {
1169 playsound_loc(S_SPLASH1 + (krand() % 3), sprite[j].x, sprite[j].y);
1170 }
1171 }
1172 }
1173 }
1174 if (rand() % 2)
1175 {
1176 if ((gotpic[SLIME >> 3] & (1 << (SLIME & 7))) > 0)
1177 {
1178 gotpic[SLIME >> 3] &= ~(1 << (SLIME & 7));
1179 if (waloff[SLIME] != -1)
1180 {
1181 if (rand() % 2)
1182 {
1183 playsound_loc(S_SPLASH1 + (krand() % 3), sprite[j].x, sprite[j].y);
1184 }
1185 }
1186 }
1187 }
1188 break;
1189 case LAVASPLASH:
1190 break;
1191 }
1192 }
1193
bats(short k)1194 void bats(short k)
1195 {
1196 int32_t j = insertsprite(sprite[k].sectnum, FLOCK);
1197 sprite[j].x = sprite[k].x;
1198 sprite[j].y = sprite[k].y;
1199 sprite[j].z = sprite[k].z;
1200 sprite[j].cstat = 0;
1201 sprite[j].picnum = BAT;
1202 sprite[j].shade = 0;
1203 sprite[j].xrepeat = 64;
1204 sprite[j].yrepeat = 64;
1205 sprite[j].ang = Sin(sprite[k].ang + ((krand() & 128) - 256));
1206 sprite[j].owner = k;
1207 sprite[j].clipdist = 16;
1208 sprite[j].lotag = 128;
1209 sprite[j].hitag = k;
1210 sprite[j].extra = 0;
1211
1212 newstatus(j, FLOCK);
1213
1214 if (sprite[k].extra == 1)
1215 lastbat = j;
1216 }
1217
cracks()1218 void cracks()
1219 {
1220 short datag;
1221 int32_t daz;
1222 int j, k;
1223
1224 Player* plr = &player[pyrn];
1225
1226 datag = sector[plr->sector].lotag;
1227
1228 if (floorpanningcnt < 64)
1229 {
1230 if (datag >= 3500 && datag <= 3599)
1231 {
1232 sector[plr->sector].hitag = 0;
1233 daz = sector[plr->sector].floorz + (1024 * (sector[plr->sector].lotag - 3500));
1234 if ((j = setanimation(§or[plr->sector].floorz, daz, 32)) >= 0)
1235 {
1236 sector[plr->sector].floorpicnum = LAVA1;
1237 sector[plr->sector].floorshade = -25;
1238 SND_PlaySound(S_CRACKING, 0, 0, 0, 0);
1239 }
1240 sector[plr->sector].lotag = 80;
1241 floorpanninglist[floorpanningcnt++] = plr->sector;
1242 }
1243 }
1244
1245 if (datag >= 5100 && datag <= 5199)
1246 {
1247 sector[plr->sector].hitag = 0;
1248
1249 daz = sector[plr->sector].floorz + (1024 * (sector[plr->sector].lotag - 5100));
1250 sector[plr->sector].lotag = 0;
1251 }
1252
1253 if (datag >= 5200 && datag <= 5299)
1254 {
1255 sector[plr->sector].hitag = 0;
1256
1257 daz = sector[plr->sector].floorz + (1024 * (sector[plr->sector].lotag - 5200));
1258 sector[plr->sector].lotag = 0;
1259 }
1260
1261 if (datag == 3001)
1262 {
1263 sector[plr->sector].lotag = 0;
1264
1265 for (k = 0; k < MAXSPRITES; k++)
1266 {
1267 if (sector[plr->sector].hitag == sprite[k].hitag)
1268 {
1269 sprite[k].lotag = 36;
1270 sprite[k].zvel = (krand() & 1024) + 512;
1271 newstatus(k, SHOVE);
1272 }
1273 }
1274 }
1275 }
1276
lavadryland()1277 void lavadryland()
1278 {
1279 short k;
1280 short s;
1281 int32_t daz;
1282
1283 Player* plr = &player[pyrn];
1284
1285 for (k = 0; k<lavadrylandcnt; k++)
1286 {
1287 s = lavadrylandsector[k];
1288
1289 if (plr->sector==s&§or[s].lotag>0)
1290 {
1291 sector[s].hitag = 0;
1292
1293 switch (sector[s].floorpicnum)
1294 {
1295 case LAVA:
1296 case ANILAVA:
1297 case LAVA1:
1298 sector[s].floorpicnum = COOLLAVA;
1299 break;
1300 case SLIME:
1301 sector[s].floorpicnum = DRYSLIME;
1302 break;
1303 case WATER:
1304 case HEALTHWATER:
1305 sector[s].floorpicnum = DRYWATER;
1306 break;
1307 case LAVA2:
1308 sector[s].floorpicnum = COOLLAVA2;
1309 break;
1310 }
1311
1312 daz = sector[s].floorz-(1024*(sector[s].lotag-900));
1313
1314 sector[s].lotag = 0;
1315 }
1316 }
1317 }
1318
warpfxsprite(int s)1319 void warpfxsprite(int s)
1320 {
1321 short daang;
1322 Player* plr = &player[pyrn];
1323
1324 int32_t j = insertsprite(sprite[s].sectnum, WARPFX);
1325
1326 sprite[j].x = sprite[s].x;
1327 sprite[j].y = sprite[s].y;
1328 sprite[j].z = sprite[s].z-(32<<8);
1329 sprite[j].cstat = 0;
1330 sprite[j].picnum = ANNIHILATE;
1331
1332 if (s == plr->spritenum)
1333 {
1334 daang = plr->ang;
1335 sprite[j].ang = daang;
1336 }
1337 else
1338 {
1339 daang = sprite[s].ang;
1340 sprite[j].ang = daang;
1341 }
1342
1343 sprite[j].xrepeat = 48;
1344 sprite[j].yrepeat = 48;
1345 sprite[j].clipdist = 16;
1346 sprite[j].extra = 0;
1347 sprite[j].shade = -31;
1348 sprite[j].xvel = ((krand()&256)-128);
1349 sprite[j].yvel = ((krand()&256)-128);
1350 sprite[j].zvel = ((krand()&256)-128);
1351 sprite[j].owner = s;
1352 sprite[j].lotag = 12;
1353 sprite[j].hitag = 0;
1354 sprite[j].pal = 0;
1355
1356 int32_t daz = ((((int)sprite[j].zvel)*synctics)>>3);
1357
1358 movesprite(j, (Cos(daang)*synctics)<<3, (Sin(daang)*synctics)<<3, daz, 4<<8, 4<<8, 1);
1359 }
1360