1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2016 EDuke32 developers and contributors
4
5 This file is part of EDuke32.
6
7 EDuke32 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the 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
23 #define actors_c_
24
25 #include "duke3d.h"
26
27 #if KRANDDEBUG
28 # define ACTOR_STATIC
29 #else
30 # define ACTOR_STATIC static
31 #endif
32
33 #define DELETE_SPRITE_AND_CONTINUE(KX) do { A_DeleteSprite(KX); goto next_sprite; } while (0)
34
35 int32_t otherp;
36
G_SetInterpolation(int32_t * const posptr)37 int G_SetInterpolation(int32_t *const posptr)
38 {
39 if (g_interpolationCnt >= MAXINTERPOLATIONS)
40 return 1;
41
42 for (bssize_t i = 0; i < g_interpolationCnt; ++i)
43 if (curipos[i] == posptr)
44 return 0;
45
46 curipos[g_interpolationCnt] = posptr;
47 oldipos[g_interpolationCnt] = *posptr;
48 g_interpolationCnt++;
49 return 0;
50 }
51
G_StopInterpolation(const int32_t * const posptr)52 void G_StopInterpolation(const int32_t * const posptr)
53 {
54 for (bssize_t i = 0; i < g_interpolationCnt; ++i)
55 if (curipos[i] == posptr)
56 {
57 g_interpolationCnt--;
58 oldipos[i] = oldipos[g_interpolationCnt];
59 bakipos[i] = bakipos[g_interpolationCnt];
60 curipos[i] = curipos[g_interpolationCnt];
61 }
62 }
63
G_DoInterpolations(int smoothRatio)64 void G_DoInterpolations(int smoothRatio)
65 {
66 if (g_interpolationLock++)
67 return;
68
69 int32_t ndelta = 0;
70
71 for (bssize_t i = 0, j = 0; i < g_interpolationCnt; ++i)
72 {
73 int32_t const odelta = ndelta;
74 bakipos[i] = *curipos[i];
75 ndelta = (*curipos[i]) - oldipos[i];
76 if (odelta != ndelta)
77 j = mulscale16(ndelta, smoothRatio);
78 *curipos[i] = oldipos[i] + j;
79 }
80 }
81
G_ClearCameraView(DukePlayer_t * ps)82 void G_ClearCameraView(DukePlayer_t *ps)
83 {
84 ps->newowner = -1;
85 ps->pos = ps->opos;
86 ps->q16ang = ps->oq16ang;
87
88 updatesector(ps->pos.x, ps->pos.y, &ps->cursectnum);
89 if (!REALITY)
90 {
91 P_UpdateScreenPal(ps);
92
93 for (bssize_t SPRITES_OF(STAT_ACTOR, k))
94 if (sprite[k].picnum==CAMERA1)
95 sprite[k].yvel = 0;
96 }
97 }
98
99 // Manhattan distance between wall-point and sprite.
G_WallSpriteDist(uwalltype const * const wal,uspritetype const * const spr)100 static FORCE_INLINE int32_t G_WallSpriteDist(uwalltype const * const wal, uspritetype const * const spr)
101 {
102 return klabs(wal->x - spr->x) + klabs(wal->y - spr->y);
103 }
104
A_RadiusDamage(int spriteNum,int blastRadius,int dmg1,int dmg2,int dmg3,int dmg4)105 void A_RadiusDamage(int spriteNum, int blastRadius, int dmg1, int dmg2, int dmg3, int dmg4)
106 {
107 uspritetype const *const pSprite = (uspritetype *)&sprite[spriteNum];
108
109 int32_t sectorCount = 0;
110 int32_t numSectors = 1;
111 int16_t sectorList[64] = { pSprite->sectnum };
112
113 if ((!REALITY && pSprite->picnum == RPG && pSprite->xrepeat < 11)
114 || (RRRA && pSprite->picnum == RPG2 && pSprite->xrepeat < 11)
115 || (!RR && pSprite->picnum == SHRINKSPARK))
116 goto SKIPWALLCHECK;
117
118 do
119 {
120 int const sectorNum = sectorList[sectorCount++];
121 int const startWall = sector[sectorNum].wallptr;
122 int const endWall = startWall + sector[sectorNum].wallnum;
123 int const w2 = wall[startWall].point2;
124
125 // Check if "hit" 1st or 3rd wall-point. This mainly makes sense
126 // for rectangular "ceiling light"-style sectors.
127 if (G_WallSpriteDist((uwalltype *)&wall[startWall], pSprite) < blastRadius ||
128 G_WallSpriteDist((uwalltype *)&wall[wall[w2].point2], pSprite) < blastRadius)
129 {
130 if (((sector[sectorNum].ceilingz-pSprite->z)>>8) < blastRadius)
131 Sect_DamageCeiling(sectorNum);
132 }
133
134 native_t w = startWall;
135
136 for (uwalltype const *pWall = (uwalltype *)&wall[startWall]; w < endWall; w++, pWall++)
137 {
138 if (G_WallSpriteDist(pWall, pSprite) >= blastRadius)
139 continue;
140
141 int const nextSector = pWall->nextsector;
142
143 if (nextSector >= 0)
144 {
145 native_t otherSector = 0;
146
147 for (; otherSector < numSectors; ++otherSector)
148 if (sectorList[otherSector] == nextSector)
149 break;
150
151 if (otherSector == numSectors)
152 {
153 if (numSectors == ARRAY_SIZE(sectorList))
154 goto SKIPWALLCHECK; // prevent oob access of 'sectorlist'
155
156 sectorList[numSectors++] = nextSector;
157 }
158 }
159
160 int16_t damageSector = (nextSector >= 0) ? wall[wall[w].nextwall].nextsector : sectorofwall(w);
161 vec3_t const vect = { (((pWall->x + wall[pWall->point2].x) >> 1) + pSprite->x) >> 1,
162 (((pWall->y + wall[pWall->point2].y) >> 1) + pSprite->y) >> 1, pSprite->z };
163
164 updatesector(vect.x, vect.y, &damageSector);
165
166 if (damageSector >= 0 && cansee(vect.x, vect.y, pSprite->z, damageSector, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum))
167 A_DamageWall(spriteNum, w, &vect, pSprite->picnum);
168 }
169 }
170 while (sectorCount < numSectors);
171
172 SKIPWALLCHECK:
173
174 // this is really weird
175 int32_t const zRand = (RR ? -(24<<8) : -ZOFFSET2) + (krand2()&(ZOFFSET5-1));
176
177 static const uint8_t statnumList [] ={
178 STAT_DEFAULT, STAT_ACTOR, STAT_STANDABLE,
179 STAT_PLAYER, STAT_FALLER, STAT_ZOMBIEACTOR, STAT_MISC
180 };
181
182 for (unsigned char stati : statnumList)
183 {
184 int32_t otherSprite = headspritestat[stati];
185
186 while (otherSprite >= 0)
187 {
188 int const nextOther = nextspritestat[otherSprite];
189 spritetype *const pOther = &sprite[otherSprite];
190
191 // DEFAULT, ZOMBIEACTOR, MISC
192 if (stati == STAT_DEFAULT || stati == STAT_ZOMBIEACTOR || stati == STAT_MISC || AFLAMABLE(pOther->picnum))
193 {
194 if ((!RR && pSprite->picnum != SHRINKSPARK) || (pOther->cstat&257))
195 {
196 if (dist(pSprite, pOther) < blastRadius)
197 {
198 if (A_CheckEnemySprite(pOther) && !cansee(pOther->x, pOther->y, pOther->z+zRand, pOther->sectnum, pSprite->x, pSprite->y, pSprite->z+zRand, pSprite->sectnum))
199 goto next_sprite;
200 A_DamageObject(otherSprite, spriteNum);
201 }
202 }
203 }
204 else if (pOther->extra >= 0 && (uspritetype *)pOther != pSprite && ((pOther->cstat & 257) ||
205 (!RR && pOther->picnum == TRIPBOMB) || pOther->picnum == QUEBALL || (RR && pOther->picnum == RRTILE3440) || pOther->picnum == STRIPEBALL || pOther->picnum == DUKELYINGDEAD ||
206 A_CheckEnemySprite(pOther)))
207 {
208 if ((!RR && pSprite->picnum == SHRINKSPARK && pOther->picnum != SHARK && (otherSprite == pSprite->owner || pOther->xrepeat < 24))
209 || ((pSprite->picnum == MORTER || (REALITY && pSprite->picnum == DN64TILE3841)) && otherSprite == pSprite->owner)
210 || (RRRA && ((pSprite->picnum == CHEERBOMB && otherSprite == pSprite->owner) || (pOther->picnum == MINION && pOther->pal == 19))))
211 goto next_sprite;
212 int32_t const spriteDist = pOther->picnum == APLAYER
213 ? FindDistance3D(pSprite->x - pOther->x, pSprite->y - pOther->y, pSprite->z - (pOther->z - PHEIGHT))
214 : dist(pSprite, pOther);
215
216 if (spriteDist >= blastRadius || !cansee(pOther->x, pOther->y, pOther->z - ZOFFSET3, pOther->sectnum, pSprite->x,
217 pSprite->y, pSprite->z - ZOFFSET4, pSprite->sectnum))
218 goto next_sprite;
219
220 actor_t & dmgActor = actor[otherSprite];
221
222 dmgActor.ang = getangle(pOther->x - pSprite->x, pOther->y - pSprite->y);
223
224 if (RRRA && pOther->extra > 0 && pSprite->picnum == RPG2)
225 dmgActor.picnum = RPG;
226 else if ((pOther->extra > 0 && pSprite->picnum == RPG)
227 || (!RR && (pSprite->picnum == SHRINKSPARK || (REALITY && pSprite->picnum == DN64TILE3841))))
228 dmgActor.picnum = pSprite->picnum;
229 else dmgActor.picnum = RADIUSEXPLOSION;
230
231 if (RR || pSprite->picnum != SHRINKSPARK)
232 {
233 if (spriteDist < blastRadius/3)
234 {
235 if (dmg4 == dmg3) dmg4++;
236 dmgActor.extra = dmg3 + (krand2()%(dmg4-dmg3));
237 }
238 else if (spriteDist < (2*blastRadius)/3)
239 {
240 if (dmg3 == dmg2) dmg3++;
241 dmgActor.extra = dmg2 + (krand2()%(dmg3-dmg2));
242 }
243 else if (spriteDist < blastRadius)
244 {
245 if (dmg2 == dmg1) dmg2++;
246 dmgActor.extra = dmg1 + (krand2()%(dmg2-dmg1));
247 }
248
249 if (!A_CheckSpriteFlags(otherSprite, SFLAG_NODAMAGEPUSH))
250 {
251 if (pOther->xvel < 0) pOther->xvel = 0;
252 pOther->xvel += ((RR ? pOther->extra : pSprite->extra)<<2);
253 }
254
255 switch (DYNAMICTILEMAP(pOther->picnum))
256 {
257 case PODFEM1__STATIC:
258 case FEM1__STATIC:
259 case FEM2__STATIC:
260 case FEM3__STATIC:
261 case FEM4__STATIC:
262 case FEM5__STATIC:
263 case FEM6__STATIC:
264 case FEM7__STATIC:
265 case FEM8__STATIC:
266 case FEM9__STATIC:
267 case FEM10__STATIC:
268 case SPACEMARINE__STATIC: if (RR) break; fallthrough__;
269 case STATUE__STATIC:
270 case STATUEFLASH__STATIC:
271 case QUEBALL__STATIC:
272 case RRTILE3440__STATICRR:
273 case STRIPEBALL__STATIC: A_DamageObject(otherSprite, spriteNum);
274 default: break;
275 }
276 }
277 else if (pSprite->extra == 0) dmgActor.extra = 0;
278
279 if (pOther->picnum != RADIUSEXPLOSION &&
280 pSprite->owner >= 0 && sprite[pSprite->owner].statnum < MAXSTATUS)
281 {
282 if (pOther->picnum == APLAYER)
283 {
284 DukePlayer_t *pPlayer = g_player[P_GetP((uspritetype *)pOther)].ps;
285
286 if (pPlayer->newowner >= 0)
287 G_ClearCameraView(pPlayer);
288 }
289
290 dmgActor.owner = pSprite->owner;
291 }
292 }
293 next_sprite:
294 otherSprite = nextOther;
295 }
296 }
297 }
298
299 // Check whether sprite <s> is on/in a non-SE7 water sector.
300 // <othersectptr>: if not NULL, the sector on the other side.
A_CheckNoSE7Water(uspritetype const * const pSprite,int sectNum,int sectLotag,int32_t * pOther)301 int A_CheckNoSE7Water(uspritetype const * const pSprite, int sectNum, int sectLotag, int32_t *pOther)
302 {
303 if (sectLotag == ST_1_ABOVE_WATER || sectLotag == ST_2_UNDERWATER)
304 {
305 int const otherSect =
306 yax_getneighborsect(pSprite->x, pSprite->y, sectNum, sectLotag == ST_1_ABOVE_WATER ? YAX_FLOOR : YAX_CEILING);
307 int const otherLotag = (sectLotag == ST_1_ABOVE_WATER) ? ST_2_UNDERWATER : ST_1_ABOVE_WATER;
308
309 // If submerging, the lower sector MUST have lotag 2.
310 // If emerging, the upper sector MUST have lotag 1.
311 // This way, the x/y coordinates where above/below water
312 // changes can happen are the same.
313 if (otherSect >= 0 && sector[otherSect].lotag == otherLotag)
314 {
315 if (pOther)
316 *pOther = otherSect;
317 return 1;
318 }
319 }
320
321 return 0;
322 }
323
324 // Check whether to do a z position update of sprite <spritenum>.
325 // Returns:
326 // 0 if no.
327 // 1 if yes, but stayed inside [actor[].ceilingz+1, actor[].floorz].
328 // <0 if yes, but passed a TROR no-SE7 water boundary. -returnvalue-1 is the
329 // other-side sector number.
A_CheckNeedZUpdate(int32_t spriteNum,int32_t zChange,int32_t * pZcoord)330 static int32_t A_CheckNeedZUpdate(int32_t spriteNum, int32_t zChange, int32_t *pZcoord)
331 {
332 uspritetype const *const pSprite = (uspritetype *)&sprite[spriteNum];
333 int const newZ = pSprite->z + (zChange >> 1);
334
335 *pZcoord = newZ;
336
337 if (newZ > actor[spriteNum].ceilingz && newZ <= actor[spriteNum].floorz)
338 return 1;
339
340 #ifdef YAX_ENABLE
341 int const sectNum = pSprite->sectnum;
342 int const sectLotag = sector[sectNum].lotag;
343 int32_t otherSect;
344
345 // Non-SE7 water.
346 // PROJECTILE_CHSECT
347 if ((zChange < 0 && sectLotag == ST_2_UNDERWATER) || (zChange > 0 && sectLotag == ST_1_ABOVE_WATER))
348 {
349 if (A_CheckNoSE7Water(pSprite, sprite[spriteNum].sectnum, sectLotag, &otherSect))
350 {
351 A_Spawn(spriteNum, WATERSPLASH2);
352 // NOTE: Don't tweak its z position afterwards like with
353 // SE7-induced projectile teleportation. It doesn't look good
354 // with TROR water.
355
356 actor[spriteNum].flags |= SFLAG_DIDNOSE7WATER;
357 return -otherSect-1;
358 }
359 }
360 #endif
361
362 return 0;
363 }
364
A_MoveSprite(int32_t spriteNum,vec3_t const * const change,uint32_t clipType)365 int32_t A_MoveSprite(int32_t spriteNum, vec3_t const * const change, uint32_t clipType)
366 {
367 spritetype *const pSprite = &sprite[spriteNum];
368 int const isEnemy = A_CheckEnemySprite(pSprite);
369 vec2_t const oldPos = *(vec2_t *)pSprite;
370
371 if (pSprite->statnum == STAT_MISC || (isEnemy && pSprite->xrepeat < 4))
372 {
373 pSprite->x += change->x;
374 pSprite->y += change->y;
375 pSprite->z += change->z;
376
377 if (isEnemy)
378 setsprite(spriteNum, (vec3_t *)pSprite);
379
380 return 0;
381 }
382
383 int32_t clipDist;
384
385 if (isEnemy)
386 {
387 if (RR)
388 clipDist = 192;
389 else if (pSprite->xrepeat > 60)
390 clipDist = 1024;
391 else if (pSprite->picnum == LIZMAN)
392 clipDist = 292;
393 else if (A_CheckSpriteFlags(spriteNum, SFLAG_BADGUY))
394 clipDist = pSprite->clipdist<<2;
395 else
396 clipDist = 192;
397 }
398 else
399 {
400 if (pSprite->statnum == STAT_PROJECTILE)
401 clipDist = 8;
402 else if (RR)
403 clipDist = 128;
404 else
405 clipDist = pSprite->clipdist<<2;
406 }
407
408 int16_t newSectnum = pSprite->sectnum;
409 int32_t newZ = pSprite->z - 2 * tilesiz[pSprite->picnum].y * pSprite->yrepeat;
410 int const oldZ = pSprite->z;
411
412 // Handle horizontal movement first.
413 pSprite->z = newZ;
414 int returnValue =
415 clipmove((vec3_t *)pSprite, &newSectnum, change->x << 13, change->y << 13, clipDist, ZOFFSET6, ZOFFSET6, clipType);
416 pSprite->z = oldZ;
417
418 if (isEnemy)
419 {
420 // Handle potential stayput condition (map-provided or hard-coded).
421 if (newSectnum < 0
422 || ((actor[spriteNum].actorstayput >= 0 && actor[spriteNum].actorstayput != newSectnum)
423 || (!RR && ((pSprite->picnum == BOSS2 && (REALITY || pSprite->pal == 0) && sector[newSectnum].lotag != ST_3)
424 || ((pSprite->picnum == BOSS1 || pSprite->picnum == BOSS2) && sector[newSectnum].lotag == ST_1_ABOVE_WATER)
425 || (sector[newSectnum].lotag == ST_1_ABOVE_WATER
426 && (pSprite->picnum == LIZMAN || (pSprite->picnum == LIZTROOP && pSprite->zvel == 0)))))
427 ))
428 {
429 *(vec2_t *) pSprite = oldPos;
430
431 if ((newSectnum >= 0 && sector[newSectnum].lotag == ST_1_ABOVE_WATER && (RR || pSprite->picnum == LIZMAN))
432 || ((AC_COUNT(actor[spriteNum].t_data)&3) == 1 && (RR || pSprite->picnum != COMMANDER)))
433 pSprite->ang = krand2()&2047;
434
435 setsprite(spriteNum, (vec3_t *)pSprite);
436
437 if (newSectnum < 0)
438 newSectnum = 0;
439
440 return 16384+newSectnum;
441 }
442
443 if ((returnValue&49152) >= 32768 && actor[spriteNum].cgg==0)
444 pSprite->ang += 768;
445 }
446
447 if (newSectnum == -1)
448 {
449 newSectnum = pSprite->sectnum;
450 // OSD_Printf("%s:%d wtf\n",__FILE__,__LINE__);
451 }
452 else if (newSectnum != pSprite->sectnum)
453 {
454 changespritesect(spriteNum, newSectnum);
455 // A_GetZLimits(spritenum);
456 }
457
458 Bassert(newSectnum == pSprite->sectnum);
459
460 int const doZUpdate = A_CheckNeedZUpdate(spriteNum, change->z, &newZ);
461
462 // Update sprite's z positions and (for TROR) maybe the sector number.
463 if (doZUpdate)
464 {
465 pSprite->z = newZ;
466 #ifdef YAX_ENABLE
467 if (doZUpdate < 0)
468 {
469 // If we passed a TROR no-SE7 water boundary, signal to the outside
470 // that the ceiling/floor was not hit. However, this is not enough:
471 // later, code checks for (retval&49152)!=49152
472 // [i.e. not "was ceiling or floor hit", but "was no sprite hit"]
473 // and calls G_WeaponHitCeilingOrFloor() then, so we need to set
474 // actor[].flags |= SFLAG_DIDNOSE7WATER in A_CheckNeedZUpdate()
475 // previously.
476 // XXX: Why is this contrived data flow necessary? (If at all.)
477 changespritesect(spriteNum, -doZUpdate-1);
478 return 0;
479 }
480
481 if (yax_getbunch(newSectnum, (change->z>0))>=0
482 && (SECTORFLD(newSectnum,stat, (change->z>0))&yax_waltosecmask(clipType))==0)
483 {
484 setspritez(spriteNum, (vec3_t *)pSprite);
485 }
486 #endif
487 }
488 else if (returnValue == 0)
489 returnValue = 16384+newSectnum;
490
491 return returnValue;
492 }
493
494 int32_t block_deletesprite = 0;
495
496 #ifdef POLYMER
A_DeleteLight(int32_t s)497 static void A_DeleteLight(int32_t s)
498 {
499 if (actor[s].lightId >= 0)
500 polymer_deletelight(actor[s].lightId);
501 actor[s].lightId = -1;
502 actor[s].lightptr = NULL;
503 }
504
G_Polymer_UnInit(void)505 void G_Polymer_UnInit(void)
506 {
507 int32_t i;
508
509 for (i=0; i<MAXSPRITES; i++)
510 A_DeleteLight(i);
511 }
512 #endif
513
514 // deletesprite() game wrapper
A_DeleteSprite(int spriteNum)515 void A_DeleteSprite(int spriteNum)
516 {
517 if (EDUKE32_PREDICT_FALSE(block_deletesprite))
518 {
519 OSD_Printf(OSD_ERROR "A_DeleteSprite(): tried to remove sprite %d in EVENT_EGS\n", spriteNum);
520 return;
521 }
522
523 #ifdef POLYMER
524 if (actor[spriteNum].lightptr != NULL && videoGetRenderMode() == REND_POLYMER)
525 A_DeleteLight(spriteNum);
526 #endif
527
528 // AMBIENT_SFX_PLAYING
529 if (sprite[spriteNum].picnum == MUSICANDSFX && actor[spriteNum].t_data[0] == 1)
530 S_StopEnvSound(sprite[spriteNum].lotag, spriteNum);
531
532 // NetAlloc
533 //if (Net_IsRelevantSprite(spriteNum))
534 //{
535 // Net_DeleteSprite(spriteNum);
536 // return;
537 //}
538
539 deletesprite(spriteNum);
540 }
541
A_AddToDeleteQueue(int spriteNum)542 void A_AddToDeleteQueue(int spriteNum)
543 {
544 if (g_deleteQueueSize == 0)
545 {
546 A_DeleteSprite(spriteNum);
547 return;
548 }
549
550 if (SpriteDeletionQueue[g_spriteDeleteQueuePos] >= 0)
551 sprite[SpriteDeletionQueue[g_spriteDeleteQueuePos]].xrepeat = 0;
552 SpriteDeletionQueue[g_spriteDeleteQueuePos] = spriteNum;
553 g_spriteDeleteQueuePos = (g_spriteDeleteQueuePos+1)%g_deleteQueueSize;
554 }
555
A_SpawnMultiple(int spriteNum,int tileNum,int spawnCnt)556 void A_SpawnMultiple(int spriteNum, int tileNum, int spawnCnt)
557 {
558 spritetype *pSprite = &sprite[spriteNum];
559
560 for (; spawnCnt>0; spawnCnt--)
561 {
562 int32_t r1 = krand2(), r2 = krand2();
563 if (REALITY)
564 swap(&r1, &r2);
565 int const j = A_InsertSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z - (r2 % (47 << 8)), tileNum, -32, 8,
566 8, r1 & 2047, 0, 0, spriteNum, 5);
567 //A_Spawn(-1, j);
568 sprite[j].cstat = krand2()&12;
569 }
570 }
571
A_DoGuts(int spriteNum,int tileNum,int spawnCnt)572 void A_DoGuts(int spriteNum, int tileNum, int spawnCnt)
573 {
574 uspritetype const *const pSprite = (uspritetype *)&sprite[spriteNum];
575 vec2_t repeat = { 32, 32 };
576
577 if (REALITY)
578 spawnCnt = max(1, spawnCnt / numplayers);
579
580 if (A_CheckEnemySprite(pSprite) && pSprite->xrepeat < 16)
581 repeat.x = repeat.y = 8;
582
583 int gutZ = pSprite->z - ZOFFSET3;
584 int floorz = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
585
586 if (gutZ > (floorz-ZOFFSET3))
587 gutZ = floorz-ZOFFSET3;
588
589 if (!RR && pSprite->picnum == COMMANDER)
590 gutZ -= (24<<8);
591
592 uint8_t pal = 0;
593
594 if (A_CheckEnemySprite(pSprite) && pSprite->pal == 6)
595 pal = 6;
596 else if (RRRA && pSprite->picnum == MINION && (pSprite->pal == 8 || pSprite->pal == 19))
597 pal = pSprite->pal;
598
599 if (RR) repeat.x >>= 1, repeat.y >>= 1;
600
601 for (bssize_t j=spawnCnt; j>0; j--)
602 {
603 int32_t const ang = krand2() & 2047;
604 int32_t r1 = krand2(), r2 = krand2(), r3 = krand2(), r4 = krand2(), r5 = krand2();
605 if (REALITY)
606 {
607 swap(&r1, &r5);
608 swap(&r2, &r4);
609 }
610 int const i = A_InsertSprite(pSprite->sectnum, pSprite->x + (r5 & 255) - 128,
611 pSprite->y + (r4 & 255) - 128, gutZ - (r3 & 8191), tileNum, -32, repeat.x,
612 repeat.y, ang, 48 + (r2 & 31), -512 - (r1 & 2047), spriteNum, 5);
613
614 if (!RR && PN(i) == JIBS2)
615 {
616 sprite[i].xrepeat >>= 2;
617 sprite[i].yrepeat >>= 2;
618 }
619
620 sprite[i].pal = pal;
621 }
622 }
623
A_DoGutsDir(int spriteNum,int tileNum,int spawnCnt)624 void A_DoGutsDir(int spriteNum, int tileNum, int spawnCnt)
625 {
626 uspritetype const * const s = (uspritetype *)&sprite[spriteNum];
627 vec2_t repeat = { 32, 32 };
628
629 if (A_CheckEnemySprite(s) && s->xrepeat < 16)
630 repeat.x = repeat.y = 8;
631
632 int gutZ = s->z-ZOFFSET3;
633 int floorZ = getflorzofslope(s->sectnum,s->x,s->y);
634
635 if (gutZ > (floorZ-ZOFFSET3))
636 gutZ = floorZ-ZOFFSET3;
637
638 if (!RR && s->picnum == COMMANDER)
639 gutZ -= (24<<8);
640
641 for (bssize_t j=spawnCnt; j>0; j--)
642 {
643 int32_t const ang = krand2() & 2047;
644 int32_t r1 = krand2(), r2 = krand2();
645 if (REALITY)
646 swap(&r1, &r2);
647 A_InsertSprite(s->sectnum, s->x, s->y, gutZ, tileNum, -32, repeat.x, repeat.y, ang,
648 256 + (r2 & 127), -512 - (r1 & 2047), spriteNum, 5);
649 }
650 }
651
G_ToggleWallInterpolation(int32_t wallNum,int32_t setInterpolation)652 static int32_t G_ToggleWallInterpolation(int32_t wallNum, int32_t setInterpolation)
653 {
654 if (setInterpolation)
655 {
656 return G_SetInterpolation(&wall[wallNum].x) || G_SetInterpolation(&wall[wallNum].y);
657 }
658 else
659 {
660 G_StopInterpolation(&wall[wallNum].x);
661 G_StopInterpolation(&wall[wallNum].y);
662 return 0;
663 }
664 }
665
Sect_ToggleInterpolation(int sectNum,int setInterpolation)666 void Sect_ToggleInterpolation(int sectNum, int setInterpolation)
667 {
668 for (bssize_t j = sector[sectNum].wallptr, endwall = sector[sectNum].wallptr + sector[sectNum].wallnum; j < endwall; j++)
669 {
670 G_ToggleWallInterpolation(j, setInterpolation);
671
672 int const nextWall = wall[j].nextwall;
673
674 if (nextWall >= 0)
675 {
676 G_ToggleWallInterpolation(nextWall, setInterpolation);
677 G_ToggleWallInterpolation(wall[nextWall].point2, setInterpolation);
678 }
679 }
680 }
681
A_MoveSector(int spriteNum)682 void A_MoveSector(int spriteNum)
683 {
684 // T1,T2 and T3 are used for all the sector moving stuff!!!
685
686 spritetype *const pSprite = &sprite[spriteNum];
687 int const rotateAngle = T3(spriteNum);
688 int originIdx = T2(spriteNum);
689
690 pSprite->x += (pSprite->xvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14;
691 pSprite->y += (pSprite->xvel * (sintable[pSprite->ang & 2047])) >> 14;
692
693 if (REALITY)
694 RT_MS_Update(pSprite->sectnum, rotateAngle, pSprite->x, pSprite->y);
695
696 int const endWall = sector[pSprite->sectnum].wallptr + sector[pSprite->sectnum].wallnum;
697
698 for (bssize_t wallNum = sector[pSprite->sectnum].wallptr; wallNum < endWall; wallNum++)
699 {
700 vec2_t const origin = g_origins[originIdx];
701 vec2_t result;
702 rotatevec(origin, rotateAngle & 2047, &result);
703 dragpoint(wallNum, pSprite->x + result.x, pSprite->y + result.y, 0);
704
705 originIdx++;
706 }
707 }
708
709 // NOTE: T5 is AC_ACTION_ID
710 # define LIGHTRAD_PICOFS(i) (T5(i) ? *(apScript + T5(i)) + (*(apScript + T5(i) + 2)) * AC_CURFRAME(actor[i].t_data) : 0)
711
712 // this is the same crap as in game.c's tspr manipulation. puke.
713 // XXX: may access tilesizy out-of-bounds by bad user code.
714 #define LIGHTRAD(spriteNum, s) (s->yrepeat * tilesiz[s->picnum + LIGHTRAD_PICOFS(spriteNum)].y)
715 #define LIGHTRAD2(spriteNum, s) ((s->yrepeat + ((rand() % s->yrepeat)>>2)) * tilesiz[s->picnum + LIGHTRAD_PICOFS(spriteNum)].y)
716
G_AddGameLight(int lightRadius,int spriteNum,int zOffset,int lightRange,int lightColor,int lightPrio)717 void G_AddGameLight(int lightRadius, int spriteNum, int zOffset, int lightRange, int lightColor, int lightPrio)
718 {
719 #ifdef POLYMER
720 spritetype *s = &sprite[spriteNum];
721
722 if (videoGetRenderMode() != REND_POLYMER || pr_lighting != 1)
723 return;
724
725 if (actor[spriteNum].lightptr == NULL)
726 {
727 #pragma pack(push, 1)
728 _prlight mylight;
729 #pragma pack(pop)
730 Bmemset(&mylight, 0, sizeof(mylight));
731
732 mylight.sector = s->sectnum;
733 mylight.x = s->x;
734 mylight.y = s->y;
735 mylight.z = s->z - zOffset;
736 mylight.color[0] = lightColor & 255;
737 mylight.color[1] = (lightColor >> 8) & 255;
738 mylight.color[2] = (lightColor >> 16) & 255;
739 mylight.radius = lightRadius;
740 actor[spriteNum].lightmaxrange = mylight.range = lightRange;
741
742 mylight.priority = lightPrio;
743 mylight.tilenum = 0;
744
745 mylight.publicflags.emitshadow = 1;
746 mylight.publicflags.negative = 0;
747
748 actor[spriteNum].lightId = polymer_addlight(&mylight);
749 if (actor[spriteNum].lightId >= 0)
750 actor[spriteNum].lightptr = &prlights[actor[spriteNum].lightId];
751 return;
752 }
753
754 s->z -= zOffset;
755
756 if (lightRange<actor[spriteNum].lightmaxrange>> 1)
757 actor[spriteNum].lightmaxrange = 0;
758
759 if (lightRange > actor[spriteNum].lightmaxrange || lightPrio != actor[spriteNum].lightptr->priority ||
760 Bmemcmp(&sprite[spriteNum], actor[spriteNum].lightptr, sizeof(int32_t) * 3))
761 {
762 if (lightRange > actor[spriteNum].lightmaxrange)
763 actor[spriteNum].lightmaxrange = lightRange;
764
765 Bmemcpy(actor[spriteNum].lightptr, &sprite[spriteNum], sizeof(int32_t) * 3);
766 actor[spriteNum].lightptr->sector = s->sectnum;
767 actor[spriteNum].lightptr->flags.invalidate = 1;
768 }
769
770 actor[spriteNum].lightptr->priority = lightPrio;
771 actor[spriteNum].lightptr->range = lightRange;
772 actor[spriteNum].lightptr->color[0] = lightColor & 255;
773 actor[spriteNum].lightptr->color[1] = (lightColor >> 8) & 255;
774 actor[spriteNum].lightptr->color[2] = (lightColor >> 16) & 255;
775
776 s->z += zOffset;
777
778 #else
779 UNREFERENCED_PARAMETER(lightRadius);
780 UNREFERENCED_PARAMETER(spriteNum);
781 UNREFERENCED_PARAMETER(zOffset);
782 UNREFERENCED_PARAMETER(lightRange);
783 UNREFERENCED_PARAMETER(lightColor);
784 UNREFERENCED_PARAMETER(lightPrio);
785 #endif
786 }
787
788 int g_canSeePlayer = 0;
789
G_WakeUp(spritetype * const pSprite,int const playerNum)790 ACTOR_STATIC int G_WakeUp(spritetype *const pSprite, int const playerNum)
791 {
792 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
793 if (!pPlayer->make_noise)
794 return 0;
795 int const radius = pPlayer->noise_radius;
796
797 if (pSprite->pal == 30 || pSprite->pal == 32 || pSprite->pal == 33 || (RRRA && pSprite->pal == 8))
798 return 0;
799
800 return (pPlayer->noise_x - radius < pSprite->x && pPlayer->noise_x + radius > pSprite->x
801 && pPlayer->noise_y - radius < pSprite->y && pPlayer->noise_y + radius > pSprite->y);
802 }
803
804 // sleeping monsters, etc
G_MoveZombieActors(void)805 ACTOR_STATIC void G_MoveZombieActors(void)
806 {
807 int spriteNum = headspritestat[STAT_ZOMBIEACTOR], canSeePlayer;
808
809 if (RR)
810 canSeePlayer = g_canSeePlayer;
811
812 while (spriteNum >= 0)
813 {
814 int const nextSprite = nextspritestat[spriteNum];
815 int32_t playerDist;
816 spritetype *const pSprite = &sprite[spriteNum];
817 int const playerNum = A_FindPlayer(pSprite, &playerDist);
818 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
819
820 if (sprite[pPlayer->i].extra > 0)
821 {
822 if (playerDist < 30000)
823 {
824 actor[spriteNum].timetosleep++;
825 if (actor[spriteNum].timetosleep >= (playerDist>>8))
826 {
827 if (A_CheckEnemySprite(pSprite))
828 {
829 vec3_t p = { pPlayer->opos.x + 64 - (krand2() & 127),
830 pPlayer->opos.y + 64 - (krand2() & 127),
831 0 };
832
833 int16_t pSectnum = pPlayer->cursectnum;
834
835 updatesector(p.x, p.y, &pSectnum);
836
837 if (pSectnum == -1)
838 {
839 spriteNum = nextSprite;
840 continue;
841 }
842
843 vec3_t s = { pSprite->x + 64 - (krand2() & 127),
844 pSprite->y + 64 - (krand2() & 127),
845 0 };
846
847 int16_t sectNum = pSprite->sectnum;
848
849 updatesector(s.x, s.y, §Num);
850
851 //if (sectNum == -1)
852 //{
853 // spriteNum = nextSprite;
854 // continue;
855 //}
856 canSeePlayer = 0;
857 if (!RR || pSprite->pal == 33 || A_CheckSpriteFlags(spriteNum, SFLAG_NOCANSEECHECK)
858 || (RRRA && pSprite->picnum == MINION && pSprite->pal == 8)
859 || (sintable[(pSprite->ang+512)&2047]*(p.x-s.x)+sintable[pSprite->ang&2047]*(p.y-s.y) >= 0))
860 {
861 int32_t r1 = krand2(), r2 = krand2();
862 if (REALITY)
863 swap(&r1, &r2);
864 s.z = pSprite->z - (r2 % (52 << 8));
865 p.z = pPlayer->opos.z - (r1 % ZOFFSET5);
866 canSeePlayer = cansee(s.x, s.y, s.z, pSprite->sectnum, p.x, p.y, p.z, pPlayer->cursectnum);
867 }
868 }
869 else
870 {
871 int32_t r1 = krand2(), r2 = krand2();
872 if (REALITY)
873 swap(&r1, &r2);
874 canSeePlayer = cansee(pSprite->x, pSprite->y, pSprite->z - ((r2 & 31) << 8), pSprite->sectnum, pPlayer->opos.x,
875 pPlayer->opos.y, pPlayer->opos.z - ((r1 & 31) << 8), pPlayer->cursectnum);
876 }
877
878 if (canSeePlayer)
879 {
880 switch (DYNAMICTILEMAP(pSprite->picnum))
881 {
882 case CANWITHSOMETHING2__STATIC:
883 case CANWITHSOMETHING3__STATIC:
884 case CANWITHSOMETHING4__STATIC:
885 case TRIPBOMB__STATIC:
886 if (RR) goto default_case;
887 fallthrough__;
888 case RUBBERCAN__STATIC:
889 case EXPLODINGBARREL__STATIC:
890 case WOODENHORSE__STATIC:
891 case HORSEONSIDE__STATIC:
892 case CANWITHSOMETHING__STATIC:
893 case FIREBARREL__STATIC:
894 case FIREVASE__STATIC:
895 case NUKEBARREL__STATIC:
896 case NUKEBARRELDENTED__STATIC:
897 case NUKEBARRELLEAKED__STATIC:
898 pSprite->shade = (sector[pSprite->sectnum].ceilingstat & 1)
899 ? sector[pSprite->sectnum].ceilingshade
900 : sector[pSprite->sectnum].floorshade;
901 actor[spriteNum].timetosleep = 0;
902 changespritestat(spriteNum, STAT_STANDABLE);
903 break;
904
905 default:
906 default_case:
907 if (A_CheckSpriteFlags(spriteNum, SFLAG_USEACTIVATOR) && sector[sprite[spriteNum].sectnum].lotag & 16384)
908 break;
909
910 actor[spriteNum].timetosleep = 0;
911 A_PlayAlertSound(spriteNum);
912 changespritestat(spriteNum, STAT_ACTOR);
913
914 break;
915 }
916 }
917 else
918 actor[spriteNum].timetosleep = 0;
919 }
920 }
921
922 if ((!RR || !canSeePlayer) && A_CheckEnemySprite(pSprite))
923 {
924 pSprite->shade = (sector[pSprite->sectnum].ceilingstat & 1)
925 ? sector[pSprite->sectnum].ceilingshade
926 : sector[pSprite->sectnum].floorshade;
927
928 if (RR && G_WakeUp(pSprite, playerNum))
929 {
930 actor[spriteNum].timetosleep = 0;
931 A_PlayAlertSound(spriteNum);
932 changespritestat(spriteNum, STAT_ACTOR);
933 }
934 }
935 }
936
937 spriteNum = nextSprite;
938 }
939 }
940
941 // stupid name, but it's what the function does.
G_FindExplosionInSector(int const sectNum)942 static FORCE_INLINE int G_FindExplosionInSector(int const sectNum)
943 {
944 if (RR)
945 {
946 for (bssize_t SPRITES_OF(STAT_MISC, i))
947 if (PN(i) == EXPLOSION2 || (PN(i) == EXPLOSION3 && sectNum == SECT(i)))
948 return i;
949 }
950 else
951 {
952 for (bssize_t SPRITES_OF(STAT_MISC, i))
953 if (PN(i) == EXPLOSION2 && sectNum == SECT(i))
954 return i;
955 }
956
957 return -1;
958 }
959
P_Nudge(int playerNum,int spriteNum,int shiftLeft)960 static FORCE_INLINE void P_Nudge(int playerNum, int spriteNum, int shiftLeft)
961 {
962 g_player[playerNum].ps->vel.x += actor[spriteNum].extra * (sintable[(actor[spriteNum].ang + 512) & 2047]) << shiftLeft;
963 g_player[playerNum].ps->vel.y += actor[spriteNum].extra * (sintable[actor[spriteNum].ang & 2047]) << shiftLeft;
964 }
965
A_IncurDamage(int const spriteNum)966 int A_IncurDamage(int const spriteNum)
967 {
968 spritetype *const pSprite = &sprite[spriteNum];
969 actor_t *const pActor = &actor[spriteNum];
970
971 // dmg->picnum check: safety, since it might have been set to <0 from CON.
972 if (pActor->extra < 0 || pSprite->extra < 0 || pActor->picnum < 0)
973 {
974 pActor->extra = -1;
975 return -1;
976 }
977
978 if (pSprite->picnum == APLAYER)
979 {
980 if (ud.god && (RR || REALITY || pActor->picnum != SHRINKSPARK))
981 return -1;
982
983 int const playerNum = P_GetP(pSprite);
984
985 if (pActor->owner >= 0 && (sprite[pActor->owner].picnum == APLAYER))
986 {
987 if (
988 (ud.ffire == 0) &&
989 ((g_gametypeFlags[ud.coop] & GAMETYPE_PLAYERSFRIENDLY) ||
990 ((g_gametypeFlags[ud.coop] & GAMETYPE_TDM) && g_player[playerNum].ps->team == g_player[P_Get(pActor->owner)].ps->team))
991 )
992 {
993 return -1;
994 }
995 }
996
997 pSprite->extra -= pActor->extra;
998
999 if (pActor->owner >= 0 && pSprite->extra <= 0 && (REALITY || pActor->picnum != FREEZEBLAST))
1000 {
1001 int const damageOwner = pActor->owner;
1002 pSprite->extra = 0;
1003
1004 g_player[playerNum].ps->wackedbyactor = damageOwner;
1005
1006 if (sprite[damageOwner].picnum == APLAYER && playerNum != P_Get(damageOwner))
1007 g_player[playerNum].ps->frag_ps = P_Get(damageOwner);
1008
1009 pActor->owner = g_player[playerNum].ps->i;
1010 }
1011
1012 switch (DYNAMICTILEMAP(pActor->picnum))
1013 {
1014 case RPG2__STATICRR:
1015 if (!RRRA) goto default_case;
1016 fallthrough__;
1017 case TRIPBOMBSPRITE__STATIC:
1018 if (!RR) goto default_case;
1019 fallthrough__;
1020 case RADIUSEXPLOSION__STATIC:
1021 case SEENINE__STATIC:
1022 case RPG__STATIC:
1023 case HYDRENT__STATIC:
1024 case HEAVYHBOMB__STATIC:
1025 case OOZFILTER__STATIC:
1026 case EXPLODINGBARREL__STATIC:
1027 P_Nudge(playerNum, spriteNum, 2);
1028 break;
1029
1030 default:
1031 default_case:
1032 P_Nudge(playerNum, spriteNum, 1);
1033 break;
1034 }
1035
1036 pActor->extra = -1;
1037 return pActor->picnum;
1038 }
1039
1040 if (pActor->extra == 0 && (RR || pActor->picnum == SHRINKSPARK) && pSprite->xrepeat < 24)
1041 return -1;
1042
1043 pSprite->extra -= pActor->extra;
1044
1045 if (pSprite->picnum != RECON && pSprite->owner >= 0 && sprite[pSprite->owner].statnum < MAXSTATUS)
1046 pSprite->owner = pActor->owner;
1047
1048 pActor->extra = -1;
1049
1050 return pActor->picnum;
1051 }
1052
A_MoveCyclers(void)1053 void A_MoveCyclers(void)
1054 {
1055 for (bssize_t i=g_cyclerCnt-1; i>=0; i--)
1056 {
1057 int16_t *const pCycler = g_cyclers[i];
1058 int const sectNum = pCycler[0];
1059 int spriteShade = pCycler[2];
1060 int const floorShade = pCycler[3];
1061 int sectorShade = clamp(floorShade + (sintable[pCycler[1] & 2047] >> 10), spriteShade, floorShade);
1062
1063 pCycler[1] += sector[sectNum].extra;
1064
1065 if (pCycler[5]) // angle 1536...
1066 {
1067 walltype *pWall = &wall[sector[sectNum].wallptr];
1068
1069 for (bssize_t wallsLeft = sector[sectNum].wallnum; wallsLeft > 0; wallsLeft--, pWall++)
1070 {
1071 if (pWall->hitag != 1)
1072 {
1073 pWall->shade = sectorShade;
1074
1075 if ((pWall->cstat&2) && pWall->nextwall >= 0)
1076 wall[pWall->nextwall].shade = sectorShade;
1077 }
1078 }
1079
1080 sector[sectNum].floorshade = sector[sectNum].ceilingshade = sectorShade;
1081 }
1082 }
1083 }
1084
A_MoveDummyPlayers(void)1085 void A_MoveDummyPlayers(void)
1086 {
1087 int spriteNum = headspritestat[STAT_DUMMYPLAYER];
1088
1089 while (spriteNum >= 0)
1090 {
1091 int const playerNum = P_Get(OW(spriteNum));
1092 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
1093 int const nextSprite = nextspritestat[spriteNum];
1094 int const playerSectnum = pPlayer->cursectnum;
1095
1096 if ((!RR && pPlayer->on_crane >= 0) || (playerSectnum >= 0 && sector[playerSectnum].lotag != ST_1_ABOVE_WATER) || sprite[pPlayer->i].extra <= 0)
1097 {
1098 pPlayer->dummyplayersprite = -1;
1099 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1100 }
1101 else
1102 {
1103 if (pPlayer->on_ground && pPlayer->on_warping_sector == 1 && playerSectnum >= 0 && sector[playerSectnum].lotag == ST_1_ABOVE_WATER)
1104 {
1105 CS(spriteNum) = 257;
1106 SZ(spriteNum) = sector[SECT(spriteNum)].ceilingz+(27<<8);
1107 SA(spriteNum) = fix16_to_int(pPlayer->q16ang);
1108 if (T1(spriteNum) == 8)
1109 T1(spriteNum) = 0;
1110 else T1(spriteNum)++;
1111 }
1112 else
1113 {
1114 if (sector[SECT(spriteNum)].lotag != ST_2_UNDERWATER) SZ(spriteNum) = sector[SECT(spriteNum)].floorz;
1115 CS(spriteNum) = 32768;
1116 }
1117 }
1118
1119 SX(spriteNum) += (pPlayer->pos.x-pPlayer->opos.x);
1120 SY(spriteNum) += (pPlayer->pos.y-pPlayer->opos.y);
1121 setsprite(spriteNum, (vec3_t *)&sprite[spriteNum]);
1122
1123 next_sprite:
1124 spriteNum = nextSprite;
1125 }
1126 }
1127
1128
1129 static int P_Submerge(int, int, DukePlayer_t *, int, int);
1130 static int P_Emerge(int, int, DukePlayer_t *, int, int);
1131 static void P_FinishWaterChange(int, DukePlayer_t *, int, int, int);
1132
G_MovePlayers(void)1133 ACTOR_STATIC void G_MovePlayers(void)
1134 {
1135 int spriteNum = headspritestat[STAT_PLAYER];
1136
1137 while (spriteNum >= 0)
1138 {
1139 int const nextSprite = nextspritestat[spriteNum];
1140 spritetype *const pSprite = &sprite[spriteNum];
1141 DukePlayer_t *const pPlayer = g_player[P_GetP(pSprite)].ps;
1142
1143 if (pSprite->owner >= 0)
1144 {
1145 if (pPlayer->newowner >= 0) //Looking thru the camera
1146 {
1147 pSprite->x = pPlayer->opos.x;
1148 pSprite->y = pPlayer->opos.y;
1149 pSprite->z = pPlayer->opos.z + PHEIGHT;
1150 actor[spriteNum].bpos.z = pSprite->z;
1151 pSprite->ang = fix16_to_int(pPlayer->oq16ang);
1152
1153 setsprite(spriteNum, (vec3_t *)pSprite);
1154 }
1155 else
1156 {
1157 int32_t otherPlayerDist;
1158 #ifdef YAX_ENABLE
1159 // TROR water submerge/emerge
1160 int const playerSectnum = pSprite->sectnum;
1161 int const sectorLotag = sector[playerSectnum].lotag;
1162 int32_t otherSector;
1163
1164 if (A_CheckNoSE7Water((uspritetype const *)pSprite, playerSectnum, sectorLotag, &otherSector))
1165 {
1166 // NOTE: Compare with G_MoveTransports().
1167 pPlayer->on_warping_sector = 1;
1168
1169 if ((sectorLotag == ST_1_ABOVE_WATER ?
1170 P_Submerge(spriteNum, P_GetP(pSprite), pPlayer, playerSectnum, otherSector) :
1171 P_Emerge(spriteNum, P_GetP(pSprite), pPlayer, playerSectnum, otherSector)) == 1)
1172 P_FinishWaterChange(spriteNum, pPlayer, sectorLotag, -1, otherSector);
1173 }
1174 #endif
1175 if (g_netServer || ud.multimode > 1)
1176 otherp = P_FindOtherPlayer(P_GetP(pSprite), &otherPlayerDist);
1177 else
1178 {
1179 otherp = P_GetP(pSprite);
1180 otherPlayerDist = 0;
1181 }
1182
1183 if (G_HaveActor(sprite[spriteNum].picnum))
1184 A_Execute(spriteNum, P_GetP(pSprite), otherPlayerDist);
1185
1186 if (g_netServer || ud.multimode > 1)
1187 {
1188 if (sprite[g_player[otherp].ps->i].extra > 0)
1189 {
1190 if (pSprite->yrepeat > 32 && sprite[g_player[otherp].ps->i].yrepeat < 32)
1191 {
1192 if (otherPlayerDist < 1400 && pPlayer->knee_incs == 0)
1193 {
1194 pPlayer->knee_incs = 1;
1195 pPlayer->weapon_pos = -1;
1196 pPlayer->actorsqu = g_player[otherp].ps->i;
1197 }
1198 }
1199 }
1200 }
1201
1202 if (ud.god)
1203 {
1204 pSprite->extra = pPlayer->max_player_health;
1205 pSprite->cstat = 257;
1206 if (!RR && !WW2GI)
1207 pPlayer->inv_amount[GET_JETPACK] = 1599;
1208 }
1209
1210 if (pSprite->extra > 0)
1211 {
1212 actor[spriteNum].owner = spriteNum;
1213
1214 if (ud.god == 0)
1215 if (G_CheckForSpaceCeiling(pSprite->sectnum) || G_CheckForSpaceFloor(pSprite->sectnum))
1216 P_QuickKill(pPlayer);
1217 }
1218 else
1219 {
1220 pPlayer->pos.x = pSprite->x;
1221 pPlayer->pos.y = pSprite->y;
1222 pPlayer->pos.z = pSprite->z-(20<<8);
1223
1224 pPlayer->newowner = -1;
1225
1226 if (!REALITY && pPlayer->wackedbyactor >= 0 && sprite[pPlayer->wackedbyactor].statnum < MAXSTATUS)
1227 {
1228 pPlayer->q16ang += fix16_from_int(G_GetAngleDelta(fix16_to_int(pPlayer->q16ang),
1229 getangle(sprite[pPlayer->wackedbyactor].x - pPlayer->pos.x,
1230 sprite[pPlayer->wackedbyactor].y - pPlayer->pos.y))
1231 >> 1);
1232 pPlayer->q16ang &= 0x7FFFFFF;
1233 }
1234 }
1235
1236 pSprite->ang = fix16_to_int(pPlayer->q16ang);
1237 }
1238 }
1239 else
1240 {
1241 if (pPlayer->holoduke_on == -1)
1242 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1243
1244 Bmemcpy(&actor[spriteNum].bpos, pSprite, sizeof(vec3_t));
1245 pSprite->cstat = 0;
1246
1247 if (pSprite->xrepeat < 42)
1248 {
1249 pSprite->xrepeat += 4;
1250 pSprite->cstat |= 2;
1251 }
1252 else pSprite->xrepeat = 42;
1253
1254 if (pSprite->yrepeat < 36)
1255 pSprite->yrepeat += 4;
1256 else
1257 {
1258 pSprite->yrepeat = 36;
1259 if (sector[pSprite->sectnum].lotag != ST_2_UNDERWATER)
1260 A_Fall(spriteNum);
1261 if (pSprite->zvel == 0 && sector[pSprite->sectnum].lotag == ST_1_ABOVE_WATER)
1262 pSprite->z += ZOFFSET5;
1263 }
1264
1265 if (pSprite->extra < 8)
1266 {
1267 pSprite->xvel = 128;
1268 pSprite->ang = fix16_to_int(pPlayer->q16ang);
1269 pSprite->extra++;
1270 A_SetSprite(spriteNum,CLIPMASK0);
1271 }
1272 else
1273 {
1274 pSprite->ang = 2047-fix16_to_int(pPlayer->q16ang);
1275 setsprite(spriteNum,(vec3_t *)pSprite);
1276 }
1277 }
1278
1279 pSprite->shade =
1280 logapproach(pSprite->shade, (sector[pSprite->sectnum].ceilingstat & 1) ? sector[pSprite->sectnum].ceilingshade
1281 : sector[pSprite->sectnum].floorshade);
1282
1283 next_sprite:
1284 spriteNum = nextSprite;
1285 }
1286 }
1287
G_MoveFX(void)1288 ACTOR_STATIC void G_MoveFX(void)
1289 {
1290 int spriteNum = headspritestat[STAT_FX];
1291
1292 while (spriteNum >= 0)
1293 {
1294 spritetype *const pSprite = &sprite[spriteNum];
1295 int const nextSprite = nextspritestat[spriteNum];
1296
1297 switch (DYNAMICTILEMAP(pSprite->picnum))
1298 {
1299 case RESPAWN__STATIC:
1300 if (pSprite->extra == 66)
1301 {
1302 int32_t j = A_Spawn(spriteNum,SHT(spriteNum));
1303 if (RRRA)
1304 {
1305 sprite[j].pal = pSprite->pal;
1306 if (sprite[j].picnum == MAMA)
1307 {
1308 switch (sprite[j].pal)
1309 {
1310 case 30:
1311 sprite[j].xrepeat = sprite[j].yrepeat = 26;
1312 sprite[j].clipdist = 75;
1313 break;
1314 case 31:
1315 sprite[j].xrepeat = sprite[j].yrepeat = 36;
1316 sprite[j].clipdist = 100;
1317 break;
1318 default:
1319 sprite[j].xrepeat = sprite[j].yrepeat = 50;
1320 sprite[j].clipdist = 100;
1321 break;
1322 }
1323 }
1324
1325 if (sprite[j].pal == 8)
1326 sprite[j].cstat |= 2;
1327 else if (sprite[j].pal == 6)
1328 {
1329 pSprite->extra = 66-13;
1330 sprite[j].pal = 0;
1331 break;
1332 }
1333 }
1334 // sprite[j].pal = sprite[i].pal;
1335 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1336 }
1337 else if (pSprite->extra > (66-13))
1338 sprite[spriteNum].extra++;
1339 break;
1340
1341 case MUSICANDSFX__STATIC:
1342 {
1343 int32_t const spriteHitag = (uint16_t)pSprite->hitag;
1344 DukePlayer_t *const pPlayer = g_player[screenpeek].ps;
1345
1346 if (T2(spriteNum) != ud.config.SoundToggle)
1347 {
1348 // If sound playback was toggled, restart.
1349 T2(spriteNum) = ud.config.SoundToggle;
1350 T1(spriteNum) = 0;
1351 }
1352
1353 if (pSprite->lotag >= 1000 && pSprite->lotag < 2000)
1354 {
1355 if (!REALITY)
1356 {
1357 int32_t playerDist = ldist(&sprite[pPlayer->i], pSprite);
1358
1359 #ifdef SPLITSCREEN_MOD_HACKS
1360 if (g_fakeMultiMode==2)
1361 {
1362 // HACK for splitscreen mod
1363 int32_t otherdist = ldist(&sprite[g_player[1].ps->i],pSprite);
1364 playerDist = min(playerDist, otherdist);
1365 }
1366 #endif
1367
1368 if (playerDist < spriteHitag && T1(spriteNum) == 0)
1369 {
1370 FX_SetReverb(pSprite->lotag - 1000);
1371 T1(spriteNum) = 1;
1372 }
1373 else if (playerDist >= spriteHitag && T1(spriteNum) == 1)
1374 {
1375 FX_SetReverb(0);
1376 FX_SetReverbDelay(0);
1377 T1(spriteNum) = 0;
1378 }
1379 }
1380 }
1381 else if (pSprite->lotag < 999 && (unsigned)sector[pSprite->sectnum].lotag < 9 && // ST_9_SLIDING_ST_DOOR
1382 ud.config.AmbienceToggle && sector[SECT(spriteNum)].floorz != sector[SECT(spriteNum)].ceilingz)
1383 {
1384 if (g_sounds[pSprite->lotag].m & SF_MSFX)
1385 {
1386 int playerDist = dist(&sprite[pPlayer->i], pSprite);
1387
1388 #ifdef SPLITSCREEN_MOD_HACKS
1389 if (g_fakeMultiMode==2)
1390 {
1391 // HACK for splitscreen mod
1392 int32_t otherdist = dist(&sprite[g_player[1].ps->i],pSprite);
1393 playerDist = min(playerDist, otherdist);
1394 }
1395 #endif
1396
1397 if (playerDist < spriteHitag && T1(spriteNum) == 0 && FX_VoiceAvailable(g_sounds[pSprite->lotag].pr-1))
1398 {
1399 // Start playing an ambience sound.
1400
1401 char om = g_sounds[pSprite->lotag].m;
1402 if (g_numEnvSoundsPlaying == ud.config.NumVoices)
1403 {
1404 int32_t j;
1405
1406 for (SPRITES_OF(STAT_FX, j))
1407 if (j != spriteNum && S_IsAmbientSFX(j) && actor[j].t_data[0] == 1 &&
1408 dist(&sprite[j], &sprite[pPlayer->i]) > playerDist)
1409 {
1410 S_StopEnvSound(sprite[j].lotag,j);
1411 break;
1412 }
1413
1414 if (j == -1)
1415 goto next_sprite;
1416 }
1417
1418 g_sounds[pSprite->lotag].m |= SF_LOOP;
1419 A_PlaySound(pSprite->lotag,spriteNum);
1420 g_sounds[pSprite->lotag].m = om;
1421 T1(spriteNum) = 1; // AMBIENT_SFX_PLAYING
1422 }
1423 else if (playerDist >= spriteHitag && T1(spriteNum) == 1)
1424 {
1425 // Stop playing ambience sound because we're out of its range.
1426
1427 // T1 will be reset in sounds.c: CLEAR_SOUND_T0
1428 // T1 = 0;
1429 S_StopEnvSound(pSprite->lotag,spriteNum);
1430 }
1431 }
1432
1433 if (g_sounds[pSprite->lotag].m & SF_GLOBAL)
1434 {
1435 // Randomly playing global sounds (flyby of planes, screams, ...)
1436
1437 if (T5(spriteNum) > 0)
1438 T5(spriteNum)--;
1439 else
1440 {
1441 for (int TRAVERSE_CONNECT(playerNum))
1442 if (playerNum == myconnectindex && g_player[playerNum].ps->cursectnum == pSprite->sectnum)
1443 {
1444 S_PlaySound(pSprite->lotag + (unsigned)g_globalRandom % (pSprite->hitag+1));
1445 T5(spriteNum) = GAMETICSPERSEC*40 + g_globalRandom%(GAMETICSPERSEC*40);
1446 }
1447 }
1448 }
1449 }
1450 break;
1451 }
1452 }
1453 next_sprite:
1454 spriteNum = nextSprite;
1455 }
1456 }
1457
G_MoveFallers(void)1458 ACTOR_STATIC void G_MoveFallers(void)
1459 {
1460 int spriteNum = headspritestat[STAT_FALLER];
1461
1462 while (spriteNum >= 0)
1463 {
1464 int const nextSprite = nextspritestat[spriteNum];
1465 spritetype *const pSprite = &sprite[spriteNum];
1466 int const sectNum = pSprite->sectnum;
1467
1468 if (T1(spriteNum) == 0)
1469 {
1470 const int16_t oextra = pSprite->extra;
1471 int j;
1472
1473 pSprite->z -= ZOFFSET2;
1474 T2(spriteNum) = pSprite->ang;
1475
1476 if ((j = A_IncurDamage(spriteNum)) >= 0)
1477 {
1478 if ((!RR && j == FIREEXT) || j == RPG || (RRRA && j == RPG2) || j == RADIUSEXPLOSION || j == SEENINE || j == OOZFILTER)
1479 {
1480 if (pSprite->extra <= 0)
1481 {
1482 T1(spriteNum) = 1;
1483
1484 for (bssize_t SPRITES_OF(STAT_FALLER, j))
1485 {
1486 if (sprite[j].hitag == SHT(spriteNum))
1487 {
1488 actor[j].t_data[0] = 1;
1489 sprite[j].cstat &= (65535-64);
1490 if (sprite[j].picnum == CEILINGSTEAM || sprite[j].picnum == STEAM)
1491 sprite[j].cstat |= 32768;
1492 }
1493 }
1494 }
1495 }
1496 else
1497 {
1498 actor[spriteNum].extra = 0;
1499 pSprite->extra = oextra;
1500 }
1501 }
1502 pSprite->ang = T2(spriteNum);
1503 pSprite->z += ZOFFSET2;
1504 }
1505 else if (T1(spriteNum) == 1)
1506 {
1507 if ((int16_t)pSprite->lotag > 0)
1508 {
1509 pSprite->lotag-=3;
1510 if (RR)
1511 {
1512 pSprite->xvel = (64+krand2())&127;
1513 pSprite->zvel = -(1024+(krand2()&1023));
1514 }
1515 else if ((int16_t)pSprite->lotag <= 0)
1516 {
1517 pSprite->xvel = (32+krand2())&63;
1518 pSprite->zvel = -(1024+(krand2()&1023));
1519 }
1520 }
1521 else
1522 {
1523 int32_t spriteGravity = g_spriteGravity;
1524
1525 if (pSprite->xvel > 0)
1526 {
1527 pSprite->xvel -= RR ? 2 : 8;
1528 A_SetSprite(spriteNum,CLIPMASK0);
1529 }
1530
1531 if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(pSprite->sectnum)))
1532 spriteGravity = 0;
1533 else if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(pSprite->sectnum)))
1534 spriteGravity = g_spriteGravity / 6;
1535
1536 if (pSprite->z < (sector[sectNum].floorz-ZOFFSET))
1537 {
1538 pSprite->zvel += spriteGravity;
1539 if (pSprite->zvel > 6144)
1540 pSprite->zvel = 6144;
1541 pSprite->z += pSprite->zvel;
1542 }
1543
1544 if ((sector[sectNum].floorz-pSprite->z) < ZOFFSET2)
1545 {
1546 for (size_t x = 0, x_end = 1+(krand2()&7); x < x_end; ++x)
1547 RANDOMSCRAP(pSprite, spriteNum);
1548 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1549 }
1550 }
1551 }
1552
1553 next_sprite:
1554 spriteNum = nextSprite;
1555 }
1556 }
1557
G_MoveStandables(void)1558 ACTOR_STATIC void G_MoveStandables(void)
1559 {
1560 int spriteNum = headspritestat[STAT_STANDABLE], j, switchPic;
1561
1562 while (spriteNum >= 0)
1563 {
1564 const int nextSprite = nextspritestat[spriteNum];
1565 int32_t *const pData = &actor[spriteNum].t_data[0];
1566 spritetype *const pSprite = &sprite[spriteNum];
1567 const int sectNum = pSprite->sectnum;
1568
1569 if (sectNum < 0)
1570 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1571
1572 Bmemcpy(&actor[spriteNum].bpos, pSprite, sizeof(vec3_t));
1573
1574 if (PN(spriteNum) >= CRANE && PN(spriteNum) <= CRANE+3)
1575 {
1576 int32_t nextj;
1577
1578 //t[0] = state
1579 //t[1] = checking sector number
1580
1581 if (pSprite->xvel) A_GetZLimits(spriteNum);
1582
1583 if (pData[0] == 0) //Waiting to check the sector
1584 {
1585 for (SPRITES_OF_SECT_SAFE(pData[1], j, nextj))
1586 {
1587 switch (sprite[j].statnum)
1588 {
1589 case STAT_ACTOR:
1590 case STAT_ZOMBIEACTOR:
1591 case STAT_STANDABLE:
1592 case STAT_PLAYER:
1593 {
1594 vec3_t vect = { g_origins[pData[4]+1].x, g_origins[pData[4]+1].y, sprite[j].z };
1595
1596 pSprite->ang = getangle(vect.x-pSprite->x, vect.y-pSprite->y);
1597 setsprite(j, &vect);
1598 pData[0]++;
1599 goto next_sprite;
1600 }
1601 }
1602 }
1603 }
1604
1605 else if (pData[0]==1)
1606 {
1607 if (pSprite->xvel < 184)
1608 {
1609 pSprite->picnum = CRANE+1;
1610 pSprite->xvel += 8;
1611 }
1612 A_SetSprite(spriteNum,CLIPMASK0);
1613 if (sectNum == pData[1])
1614 pData[0]++;
1615 }
1616 else if (pData[0]==2 || pData[0]==7)
1617 {
1618 pSprite->z += (1024+512);
1619
1620 if (pData[0]==2)
1621 {
1622 if (sector[sectNum].floorz - pSprite->z < (64<<8))
1623 if (pSprite->picnum > CRANE) pSprite->picnum--;
1624
1625 if (sector[sectNum].floorz - pSprite->z < 4096+1024)
1626 pData[0]++;
1627 }
1628
1629 if (pData[0]==7)
1630 {
1631 if (sector[sectNum].floorz - pSprite->z < (64<<8))
1632 {
1633 if (pSprite->picnum > CRANE) pSprite->picnum--;
1634 else
1635 {
1636 if (pSprite->owner==-2)
1637 {
1638 int32_t p = A_FindPlayer(pSprite, NULL);
1639 A_PlaySound(RR ? 390 : (REALITY ? 31: DUKE_GRUNT),g_player[p].ps->i);
1640 if (g_player[p].ps->on_crane == spriteNum)
1641 g_player[p].ps->on_crane = -1;
1642 }
1643
1644 pData[0]++;
1645 pSprite->owner = -1;
1646 }
1647 }
1648 }
1649 }
1650 else if (pData[0]==3)
1651 {
1652 pSprite->picnum++;
1653 if (pSprite->picnum == CRANE+2)
1654 {
1655 int32_t p = G_CheckPlayerInSector(pData[1]);
1656
1657 if (p >= 0 && g_player[p].ps->on_ground)
1658 {
1659 pSprite->owner = -2;
1660 g_player[p].ps->on_crane = spriteNum;
1661 A_PlaySound(RR ? 390 : (REALITY ? 31: DUKE_GRUNT),g_player[p].ps->i);
1662 g_player[p].ps->q16ang = fix16_from_int(pSprite->ang+1024);
1663 }
1664 else
1665 {
1666 for (SPRITES_OF_SECT(pData[1], j))
1667 {
1668 switch (sprite[j].statnum)
1669 {
1670 case STAT_ACTOR:
1671 case STAT_STANDABLE:
1672 pSprite->owner = j;
1673 break;
1674 }
1675 }
1676 }
1677
1678 pData[0]++;//Grabbed the sprite
1679 pData[2]=0;
1680 goto next_sprite;
1681 }
1682 }
1683 else if (pData[0]==4) //Delay before going up
1684 {
1685 pData[2]++;
1686 if (pData[2] > 10)
1687 pData[0]++;
1688 }
1689 else if (pData[0]==5 || pData[0] == 8)
1690 {
1691 if (pData[0]==8 && pSprite->picnum < (CRANE+2))
1692 if ((sector[sectNum].floorz-pSprite->z) > 8192)
1693 pSprite->picnum++;
1694
1695 if (pSprite->z < g_origins[pData[4]+2].x)
1696 {
1697 pData[0]++;
1698 pSprite->xvel = 0;
1699 }
1700 else
1701 pSprite->z -= (1024+512);
1702 }
1703 else if (pData[0]==6)
1704 {
1705 if (pSprite->xvel < 192)
1706 pSprite->xvel += 8;
1707 pSprite->ang = getangle(g_origins[pData[4]].x - pSprite->x, g_origins[pData[4]].y - pSprite->y);
1708 A_SetSprite(spriteNum,CLIPMASK0);
1709 if (((pSprite->x-g_origins[pData[4]].x)*(pSprite->x-g_origins[pData[4]].x)+(pSprite->y-g_origins[pData[4]].y)*(pSprite->y-g_origins[pData[4]].y)) < (128*128))
1710 pData[0]++;
1711 }
1712
1713 else if (pData[0]==9)
1714 pData[0] = 0;
1715
1716 {
1717 vec3_t vect;
1718 Bmemcpy(&vect,pSprite,sizeof(vec3_t));
1719 vect.z -= (34<<8);
1720 setsprite(g_origins[pData[4]+2].y, &vect);
1721 }
1722
1723
1724 if (pSprite->owner != -1)
1725 {
1726 int32_t p = A_FindPlayer(pSprite, NULL);
1727
1728 if (A_IncurDamage(spriteNum) >= 0)
1729 {
1730 if (pSprite->owner == -2)
1731 if (g_player[p].ps->on_crane == spriteNum)
1732 g_player[p].ps->on_crane = -1;
1733 pSprite->owner = -1;
1734 pSprite->picnum = CRANE;
1735 goto next_sprite;
1736 }
1737
1738 if (pSprite->owner >= 0)
1739 {
1740 setsprite(pSprite->owner,(vec3_t *)pSprite);
1741
1742 Bmemcpy(&actor[pSprite->owner].bpos, pSprite, sizeof(vec3_t));
1743
1744 pSprite->zvel = 0;
1745 }
1746 else if (pSprite->owner == -2)
1747 {
1748 DukePlayer_t *const ps = g_player[p].ps;
1749
1750 ps->opos.x = ps->pos.x = pSprite->x-(sintable[(fix16_to_int(ps->q16ang)+512)&2047]>>6);
1751 ps->opos.y = ps->pos.y = pSprite->y-(sintable[fix16_to_int(ps->q16ang)&2047]>>6);
1752 ps->opos.z = ps->pos.z = pSprite->z+(2<<8);
1753
1754 setsprite(ps->i, (vec3_t *)ps);
1755 ps->cursectnum = sprite[ps->i].sectnum;
1756 }
1757 }
1758
1759 goto next_sprite;
1760 }
1761 else if (PN(spriteNum) >= WATERFOUNTAIN && PN(spriteNum) <= WATERFOUNTAIN+3)
1762 {
1763 if (pData[0] > 0)
1764 {
1765 if (pData[0] < 20)
1766 {
1767 pData[0]++;
1768
1769 pSprite->picnum++;
1770
1771 if (pSprite->picnum == (WATERFOUNTAIN+3))
1772 pSprite->picnum = WATERFOUNTAIN+1;
1773 }
1774 else
1775 {
1776 int32_t playerDist;
1777
1778 A_FindPlayer(pSprite,&playerDist);
1779
1780 if (playerDist > 512)
1781 {
1782 pData[0] = 0;
1783 pSprite->picnum = WATERFOUNTAIN;
1784 }
1785 else pData[0] = 1;
1786 }
1787 }
1788 goto next_sprite;
1789 }
1790 else if (AFLAMABLE(pSprite->picnum))
1791 {
1792 if (T1(spriteNum) == 1)
1793 {
1794 if ((++T2(spriteNum)&3) > 0) goto next_sprite;
1795
1796 if (pSprite->picnum == TIRE && T2(spriteNum) == 32)
1797 {
1798 pSprite->cstat = 0;
1799 j = A_Spawn(spriteNum,BLOODPOOL);
1800 sprite[j].shade = 127;
1801 }
1802 else
1803 {
1804 if (pSprite->shade < 64) pSprite->shade++;
1805 else DELETE_SPRITE_AND_CONTINUE(spriteNum);
1806 }
1807
1808 j = pSprite->xrepeat-(krand2()&7);
1809 if (j < 10)
1810 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1811
1812 pSprite->xrepeat = j;
1813
1814 j = pSprite->yrepeat-(krand2()&7);
1815 if (j < 4)
1816 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1817
1818 pSprite->yrepeat = j;
1819 }
1820 if (!RR && pSprite->picnum == BOX)
1821 {
1822 A_Fall(spriteNum);
1823 actor[spriteNum].ceilingz = sector[pSprite->sectnum].ceilingz;
1824 }
1825 goto next_sprite;
1826 }
1827 else if (!RR && pSprite->picnum == TRIPBOMB)
1828 {
1829 int const tripBombMode = Gv_GetVarByLabel("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, -1, -1);
1830 if(tripBombMode & TRIPBOMB_TIMER)
1831 {
1832 // we're on a timer....
1833 if (pSprite->extra >= 0)
1834 {
1835 pSprite->extra--;
1836 if (pSprite->extra == 0)
1837 {
1838 T3(spriteNum) = 16;
1839 A_PlaySound(LASERTRIP_ARMING,spriteNum);
1840 }
1841 }
1842 }
1843 if (T3(spriteNum) > 0)
1844 {
1845 T3(spriteNum)--;
1846
1847 if (T3(spriteNum) == 8)
1848 {
1849 for (j=0; j<5; j++)
1850 RANDOMSCRAP(pSprite, spriteNum);
1851
1852 int const dmg = pSprite->extra;
1853 A_RadiusDamage(spriteNum, g_tripbombRadius, dmg>>2, dmg>>1, dmg-(dmg>>2), dmg);
1854
1855 j = A_Spawn(spriteNum,EXPLOSION2);
1856 A_PlaySound(REALITY ? 15 : LASERTRIP_EXPLODE,j);
1857 sprite[j].ang = pSprite->ang;
1858 sprite[j].xvel = 348;
1859 A_SetSprite(j,CLIPMASK0);
1860
1861 for (SPRITES_OF(STAT_MISC, j))
1862 {
1863 if (sprite[j].picnum == LASERLINE && pSprite->hitag == sprite[j].hitag)
1864 sprite[j].xrepeat = sprite[j].yrepeat = 0;
1865 }
1866
1867 DELETE_SPRITE_AND_CONTINUE(spriteNum);
1868 }
1869 goto next_sprite;
1870 }
1871 else
1872 {
1873 int const oldExtra = pSprite->extra;
1874 int const oldAng = pSprite->ang;
1875
1876 pSprite->extra = 1;
1877 if (A_IncurDamage(spriteNum) >= 0)
1878 {
1879 T3(spriteNum) = 16;
1880 }
1881 pSprite->extra = oldExtra;
1882 pSprite->ang = oldAng;
1883 }
1884
1885 if (T1(spriteNum) < 32)
1886 {
1887 int32_t playerDist;
1888 A_FindPlayer(pSprite, &playerDist);
1889 if (playerDist > 768 || T1(spriteNum) > 16) T1(spriteNum)++;
1890 }
1891
1892 if (T1(spriteNum) == 32)
1893 {
1894 int16_t hitSprite;
1895 int const oldAng = pSprite->ang;
1896
1897 pSprite->ang = T6(spriteNum);
1898
1899 T4(spriteNum) = pSprite->x;
1900 T5(spriteNum) = pSprite->y;
1901
1902 pSprite->x += sintable[(T6(spriteNum)+512)&2047]>>9;
1903 pSprite->y += sintable[(T6(spriteNum))&2047]>>9;
1904 pSprite->z -= (3<<8);
1905
1906 setsprite(spriteNum,(vec3_t *)pSprite);
1907
1908 int hitDist = A_CheckHitSprite(spriteNum, &hitSprite);
1909
1910 actor[spriteNum].lastv.x = hitDist;
1911 pSprite->ang = oldAng;
1912
1913 if (tripBombMode & TRIPBOMB_TRIPWIRE)
1914 {
1915 // we're on a trip wire
1916 int16_t cursectnum;
1917
1918 if (REALITY)
1919 {
1920 pSprite->x += sintable[(T6(spriteNum)+512)&2047]>>5;
1921 pSprite->y += sintable[(T6(spriteNum))&2047]>>5;
1922 }
1923
1924 while (hitDist > 0)
1925 {
1926 j = A_Spawn(spriteNum,LASERLINE);
1927 setsprite(j,(vec3_t *)&sprite[j]);
1928 sprite[j].hitag = pSprite->hitag;
1929 actor[j].t_data[1] = sprite[j].z;
1930
1931 if (REALITY && hitDist < 2048)
1932 {
1933 pSprite->x += (sintable[(T6(spriteNum)+512)&2047] * hitDist) >> 15;
1934 pSprite->y += (sintable[(T6(spriteNum))&2047] * hitDist) >> 15;
1935 }
1936 else
1937 {
1938 pSprite->x += sintable[(T6(spriteNum)+512)&2047]>>4;
1939 pSprite->y += sintable[(T6(spriteNum))&2047]>>4;
1940 }
1941
1942 if (hitDist < 1024)
1943 {
1944 sprite[j].xrepeat = (hitDist + (REALITY ? 31 : 0))>>5;
1945 break;
1946 }
1947 hitDist -= 1024;
1948
1949 //cursectnum = pSprite->sectnum;
1950 //updatesector(pSprite->x, pSprite->y, &cursectnum);
1951 //if (cursectnum < 0)
1952 // break;
1953 }
1954 }
1955
1956 T1(spriteNum)++;
1957
1958 pSprite->x = T4(spriteNum);
1959 pSprite->y = T5(spriteNum);
1960 pSprite->z += (3<<8);
1961
1962 setsprite(spriteNum,(vec3_t *)pSprite);
1963 T4(spriteNum) = T3(spriteNum) = 0;
1964
1965 if (hitSprite >= 0 && (tripBombMode & TRIPBOMB_TRIPWIRE))
1966 {
1967 T3(spriteNum) = 13;
1968 A_PlaySound(REALITY ? 14 : LASERTRIP_ARMING,spriteNum);
1969 }
1970 }
1971
1972 if (T1(spriteNum) == 33)
1973 {
1974 T2(spriteNum)++;
1975
1976 T4(spriteNum) = pSprite->x;
1977 T5(spriteNum) = pSprite->y;
1978
1979 pSprite->x += sintable[(T6(spriteNum)+512)&2047]>>9;
1980 pSprite->y += sintable[(T6(spriteNum))&2047]>>9;
1981 pSprite->z -= (3<<8);
1982
1983 setsprite(spriteNum, (vec3_t *) pSprite);
1984
1985 int hitDist = A_CheckHitSprite(spriteNum, NULL);
1986
1987 pSprite->x = T4(spriteNum);
1988 pSprite->y = T5(spriteNum);
1989 pSprite->z += (3<<8);
1990 setsprite(spriteNum, (vec3_t *) pSprite);
1991
1992 // if( Actor[i].lastvx != x && lTripBombControl & TRIPBOMB_TRIPWIRE)
1993 if (actor[spriteNum].lastv.x != hitDist && (tripBombMode & TRIPBOMB_TRIPWIRE))
1994 {
1995 T3(spriteNum) = 13;
1996 A_PlaySound(REALITY ? 14 : LASERTRIP_ARMING, spriteNum);
1997 }
1998 }
1999
2000 goto next_sprite;
2001 }
2002 else if (pSprite->picnum >= CRACK1 && pSprite->picnum <= CRACK4)
2003 {
2004 if (pSprite->hitag)
2005 {
2006 pData[0] = pSprite->cstat;
2007 pData[1] = pSprite->ang;
2008
2009 int const dmgTile = A_IncurDamage(spriteNum);
2010
2011 if (dmgTile < 0)
2012 goto crack_default;
2013
2014 switch (DYNAMICTILEMAP(dmgTile))
2015 {
2016 case RPG2__STATICRR:
2017 if (!RRRA) goto crack_default;
2018 fallthrough__;
2019 case FIREEXT__STATIC:
2020 if (RR) goto crack_default;
2021 fallthrough__;
2022 case RPG__STATIC:
2023 case RADIUSEXPLOSION__STATIC:
2024 case SEENINE__STATIC:
2025 case OOZFILTER__STATIC:
2026 case DN64TILE3634__STATIC:
2027 case DN64TILE3841__STATIC:
2028 if (!REALITY && (dmgTile == DN64TILE3634 || dmgTile == DN64TILE3841))
2029 goto crack_default;
2030 for (SPRITES_OF(STAT_STANDABLE, j))
2031 {
2032 if (pSprite->hitag == sprite[j].hitag &&
2033 (sprite[j].picnum == OOZFILTER || sprite[j].picnum == SEENINE))
2034 if (sprite[j].shade != -32)
2035 sprite[j].shade = -32;
2036 }
2037
2038 goto DETONATE;
2039
2040 crack_default:
2041 default:
2042 pSprite->cstat = pData[0];
2043 pSprite->ang = pData[1];
2044 pSprite->extra = 0;
2045
2046 goto next_sprite;
2047 }
2048 }
2049 goto next_sprite;
2050 }
2051 else if (!RR && pSprite->picnum == FIREEXT)
2052 {
2053 if (A_IncurDamage(spriteNum) < 0)
2054 goto next_sprite;
2055
2056 for (bsize_t k=0; k<16; k++)
2057 {
2058 int32_t r1 = krand2(), r2 = krand2(), r3 = krand2(), r4 = krand2(), r5 = krand2();
2059 if (REALITY)
2060 {
2061 swap(&r1, &r5);
2062 swap(&r2, &r4);
2063 }
2064 j = A_InsertSprite(SECT(spriteNum), SX(spriteNum), SY(spriteNum), SZ(spriteNum) - (r5 % (48 << 8)),
2065 SCRAP3 + (r4 & 3), -8, 48, 48, r3 & 2047, (r2 & 63) + 64,
2066 -(r1 & 4095) - (sprite[spriteNum].zvel >> 2), spriteNum, 5);
2067
2068 sprite[j].pal = 2;
2069 }
2070
2071 j = A_Spawn(spriteNum,EXPLOSION2);
2072 A_PlaySound(REALITY ? 12 : PIPEBOMB_EXPLODE,j);
2073 A_PlaySound(REALITY ? 18 : GLASS_HEAVYBREAK,j);
2074
2075 if ((int16_t)pSprite->hitag > 0)
2076 {
2077 for (SPRITES_OF(STAT_STANDABLE, j))
2078 {
2079 // XXX: This block seems to be CODEDUP'd a lot of times.
2080 if (pSprite->hitag == sprite[j].hitag && (sprite[j].picnum == OOZFILTER || sprite[j].picnum == SEENINE))
2081 if (sprite[j].shade != -32)
2082 sprite[j].shade = -32;
2083 }
2084
2085 j = A_Spawn(spriteNum,EXPLOSION2);
2086 int const dmg = pSprite->extra;
2087 A_RadiusDamage(spriteNum, g_pipebombRadius,dmg>>2, dmg-(dmg>>1),dmg-(dmg>>2), dmg);
2088 A_PlaySound(REALITY ? 12 : PIPEBOMB_EXPLODE,j);
2089
2090 goto DETONATE;
2091 }
2092 else
2093 {
2094 A_RadiusDamage(spriteNum,g_seenineRadius,10,15,20,25);
2095 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2096 }
2097 goto next_sprite;
2098 }
2099 else if (pSprite->picnum == OOZFILTER || pSprite->picnum == SEENINE || pSprite->picnum == SEENINEDEAD || pSprite->picnum == SEENINEDEAD+1)
2100 {
2101 if (pSprite->shade != -32 && pSprite->shade != -33)
2102 {
2103 if (pSprite->xrepeat)
2104 j = (A_IncurDamage(spriteNum) >= 0);
2105 else
2106 j = 0;
2107
2108 if (j || pSprite->shade == -31)
2109 {
2110 if (j) pSprite->lotag = 0;
2111
2112 pData[3] = 1;
2113
2114 for (SPRITES_OF(STAT_STANDABLE, j))
2115 {
2116 if (pSprite->hitag == sprite[j].hitag && (sprite[j].picnum == SEENINE || sprite[j].picnum == OOZFILTER))
2117 sprite[j].shade = -32;
2118 }
2119 }
2120 }
2121 else
2122 {
2123 if (pSprite->shade == -32)
2124 {
2125 if ((int16_t)pSprite->lotag > 0)
2126 {
2127 pSprite->lotag -= 3;
2128 if ((int16_t)pSprite->lotag <= 0)
2129 pSprite->lotag = -99;
2130 }
2131 else
2132 pSprite->shade = -33;
2133 }
2134 else
2135 {
2136 if (pSprite->xrepeat > 0)
2137 {
2138 T3(spriteNum)++;
2139 if (T3(spriteNum) == 3)
2140 {
2141 if (pSprite->picnum == OOZFILTER)
2142 {
2143 T3(spriteNum) = 0;
2144 goto DETONATE;
2145 }
2146
2147 if (pSprite->picnum != (SEENINEDEAD+1))
2148 {
2149 T3(spriteNum) = 0;
2150
2151 if (pSprite->picnum == SEENINEDEAD)
2152 pSprite->picnum++;
2153 else if (pSprite->picnum == SEENINE)
2154 pSprite->picnum = SEENINEDEAD;
2155 }
2156 else goto DETONATE;
2157 }
2158 goto next_sprite;
2159 }
2160
2161 DETONATE:
2162 g_earthquakeTime = 16;
2163
2164 for (SPRITES_OF(STAT_EFFECTOR, j))
2165 {
2166 if (pSprite->hitag == sprite[j].hitag)
2167 {
2168 if (sprite[j].lotag == SE_13_EXPLOSIVE)
2169 {
2170 if (actor[j].t_data[2] == 0)
2171 actor[j].t_data[2] = 1;
2172 }
2173 else if (sprite[j].lotag == SE_8_UP_OPEN_DOOR_LIGHTS)
2174 actor[j].t_data[4] = 1;
2175 else if (sprite[j].lotag == SE_18_INCREMENTAL_SECTOR_RISE_FALL)
2176 {
2177 if (actor[j].t_data[0] == 0)
2178 actor[j].t_data[0] = 1;
2179 }
2180 else if (sprite[j].lotag == SE_21_DROP_FLOOR)
2181 actor[j].t_data[0] = 1;
2182 }
2183 }
2184
2185 pSprite->z -= ZOFFSET5;
2186
2187 if ((pData[3] == 1 && pSprite->xrepeat) || (int16_t)pSprite->lotag == -99)
2188 {
2189 int const newSprite = A_Spawn(spriteNum,EXPLOSION2);
2190 int const dmg = pSprite->extra;
2191
2192 A_RadiusDamage(spriteNum,g_seenineRadius,dmg>>2, dmg-(dmg>>1),dmg-(dmg>>2), dmg);
2193 A_PlaySound(REALITY ? 12 : PIPEBOMB_EXPLODE, newSprite);
2194 }
2195
2196 if (pSprite->xrepeat)
2197 for (bsize_t x=0; x<8; x++)
2198 RANDOMSCRAP(pSprite, spriteNum);
2199
2200 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2201 }
2202 }
2203 goto next_sprite;
2204 }
2205 else if (pSprite->picnum == MASTERSWITCH)
2206 {
2207 if (pSprite->yvel == 1)
2208 {
2209 if ((int16_t)--pSprite->hitag <= 0)
2210 {
2211 G_OperateSectors(sectNum,spriteNum);
2212
2213 for (SPRITES_OF_SECT(sectNum, j))
2214 {
2215 if (sprite[j].statnum == STAT_EFFECTOR)
2216 {
2217 switch (sprite[j].lotag)
2218 {
2219 case SE_2_EARTHQUAKE:
2220 case SE_21_DROP_FLOOR:
2221 case SE_31_FLOOR_RISE_FALL:
2222 case SE_32_CEILING_RISE_FALL:
2223 case SE_36_PROJ_SHOOTER:
2224 actor[j].t_data[0] = 1;
2225 break;
2226 case SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT:
2227 actor[j].t_data[4] = 1;
2228 break;
2229 }
2230 }
2231 else if (sprite[j].statnum == STAT_STANDABLE)
2232 {
2233 switch (DYNAMICTILEMAP(sprite[j].picnum))
2234 {
2235 case SEENINE__STATIC:
2236 case OOZFILTER__STATIC:
2237 sprite[j].shade = -31;
2238 break;
2239 }
2240 }
2241 }
2242
2243 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2244 }
2245 }
2246 goto next_sprite;
2247 }
2248 else
2249 {
2250 switchPic = pSprite->picnum;
2251
2252 if (!RR && switchPic > SIDEBOLT1 && switchPic <= SIDEBOLT1 + 3)
2253 switchPic = SIDEBOLT1;
2254 else if (switchPic > BOLT1 && switchPic <= BOLT1 + 3)
2255 switchPic = BOLT1;
2256 switch (DYNAMICTILEMAP(switchPic))
2257 {
2258 case VIEWSCREEN__STATIC:
2259 case VIEWSCREEN2__STATIC:
2260 if (RR) goto next_sprite;
2261
2262 if (pSprite->xrepeat == 0)
2263 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2264
2265 {
2266 int32_t playerDist;
2267 int const p = A_FindPlayer(pSprite, &playerDist);
2268 const DukePlayer_t *const ps = g_player[p].ps;
2269
2270 if (dist(&sprite[ps->i], pSprite) < VIEWSCREEN_ACTIVE_DISTANCE)
2271 {
2272 #if 0
2273 if (sprite[i].yvel == 1) // VIEWSCREEN_YVEL
2274 g_curViewscreen = i;
2275 #endif
2276 }
2277 else if (g_curViewscreen == spriteNum /*&& T1 == 1*/)
2278 {
2279 g_curViewscreen = -1;
2280 sprite[spriteNum].yvel = 0; // VIEWSCREEN_YVEL
2281 T1(spriteNum) = 0;
2282
2283 for (bssize_t ii = 0; ii < VIEWSCREENFACTOR; ii++) walock[TILE_VIEWSCR - ii] = 199;
2284 }
2285 }
2286
2287 goto next_sprite;
2288 case TRASH__STATIC:
2289
2290 if (pSprite->xvel == 0)
2291 pSprite->xvel = 1;
2292 if (A_SetSprite(spriteNum, CLIPMASK0))
2293 {
2294 A_Fall(spriteNum);
2295 if (krand2() & 1)
2296 pSprite->zvel -= 256;
2297 if ((pSprite->xvel) < 48)
2298 pSprite->xvel += (krand2() & 3);
2299 }
2300 else
2301 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2302 break;
2303
2304 case SIDEBOLT1__STATIC:
2305 // case SIDEBOLT1+1:
2306 // case SIDEBOLT1+2:
2307 // case SIDEBOLT1+3:
2308 {
2309 if (RR) goto next_sprite;
2310 int32_t playerDist;
2311 A_FindPlayer(pSprite, &playerDist);
2312 if (playerDist > 20480)
2313 goto next_sprite;
2314
2315 CLEAR_THE_BOLT2:
2316 if (pData[2])
2317 {
2318 pData[2]--;
2319 goto next_sprite;
2320 }
2321 if ((pSprite->xrepeat | pSprite->yrepeat) == 0)
2322 {
2323 pSprite->xrepeat = pData[0];
2324 pSprite->yrepeat = pData[1];
2325 }
2326 if ((krand2() & 8) == 0)
2327 {
2328 pData[0] = pSprite->xrepeat;
2329 pData[1] = pSprite->yrepeat;
2330 pData[2] = g_globalRandom & 4;
2331 pSprite->xrepeat = pSprite->yrepeat = 0;
2332 goto CLEAR_THE_BOLT2;
2333 }
2334 pSprite->picnum++;
2335
2336 #if 0
2337 // NOTE: Um, this 'l' was assigned to last at the beginning of this function.
2338 // SIDEBOLT1 never gets translucent as a consequence, unlike BOLT1.
2339 if (randomRepeat & 1)
2340 pSprite->cstat ^= 2;
2341 #endif
2342
2343 if ((krand2() & 1) && sector[sectNum].floorpicnum == HURTRAIL)
2344 A_PlaySound(REALITY ? 19 : SHORT_CIRCUIT, spriteNum);
2345
2346 if (pSprite->picnum == SIDEBOLT1 + 4)
2347 pSprite->picnum = SIDEBOLT1;
2348
2349 goto next_sprite;
2350 }
2351
2352 case BOLT1__STATIC:
2353 // case BOLT1+1:
2354 // case BOLT1+2:
2355 // case BOLT1+3:
2356 {
2357 int32_t playerDist;
2358 A_FindPlayer(pSprite, &playerDist);
2359 if (playerDist > 20480)
2360 goto next_sprite;
2361
2362 if (pData[3] == 0)
2363 pData[3] = sector[sectNum].floorshade;
2364
2365 CLEAR_THE_BOLT:
2366 if (pData[2])
2367 {
2368 pData[2]--;
2369 sector[sectNum].floorshade = 20;
2370 sector[sectNum].ceilingshade = 20;
2371 goto next_sprite;
2372 }
2373 if ((pSprite->xrepeat | pSprite->yrepeat) == 0)
2374 {
2375 pSprite->xrepeat = pData[0];
2376 pSprite->yrepeat = pData[1];
2377 }
2378 else if ((krand2() & 8) == 0)
2379 {
2380 pData[0] = pSprite->xrepeat;
2381 pData[1] = pSprite->yrepeat;
2382 pData[2] = g_globalRandom & 4;
2383 pSprite->xrepeat = pSprite->yrepeat = 0;
2384 goto CLEAR_THE_BOLT;
2385 }
2386 pSprite->picnum++;
2387
2388 int const randomRepeat = g_globalRandom & 7;
2389 pSprite->xrepeat = randomRepeat + 8;
2390
2391 if (randomRepeat & 1)
2392 pSprite->cstat ^= 2;
2393
2394 if (pSprite->picnum == (BOLT1 + 1)
2395 && (RR ? (krand2() & 1) != 0 : (krand2() & 7) == 0) && sector[sectNum].floorpicnum == HURTRAIL)
2396 A_PlaySound(REALITY ? 19 : SHORT_CIRCUIT, spriteNum);
2397
2398 if (pSprite->picnum == BOLT1 + 4)
2399 pSprite->picnum = BOLT1;
2400
2401 if (pSprite->picnum & 1)
2402 {
2403 sector[sectNum].floorshade = 0;
2404 sector[sectNum].ceilingshade = 0;
2405 }
2406 else
2407 {
2408 sector[sectNum].floorshade = 20;
2409 sector[sectNum].ceilingshade = 20;
2410 }
2411 goto next_sprite;
2412 }
2413
2414 case WATERDRIP__STATIC:
2415
2416 if (pData[1])
2417 {
2418 if (--pData[1] == 0)
2419 pSprite->cstat &= 32767;
2420 }
2421 else
2422 {
2423 A_Fall(spriteNum);
2424 A_SetSprite(spriteNum, CLIPMASK0);
2425 if (pSprite->xvel > 0)
2426 pSprite->xvel -= 2;
2427
2428 if (pSprite->zvel == 0)
2429 {
2430 pSprite->cstat |= 32768;
2431
2432 if (pSprite->pal != 2 && (RR || pSprite->hitag == 0))
2433 A_PlaySound(REALITY ? 65 : SOMETHING_DRIPPING, spriteNum);
2434
2435 if (sprite[pSprite->owner].picnum != WATERDRIP)
2436 {
2437 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2438 }
2439 else
2440 {
2441 actor[spriteNum].bpos.z = pSprite->z = pData[0];
2442 pData[1] = 48 + (krand2() & 31);
2443 }
2444 }
2445 }
2446
2447
2448 goto next_sprite;
2449
2450 case DOORSHOCK__STATIC:
2451 pSprite->yrepeat = (klabs(sector[sectNum].ceilingz - sector[sectNum].floorz) >> 9) + 4;
2452 pSprite->xrepeat = 16;
2453 pSprite->z = sector[sectNum].floorz;
2454 goto next_sprite;
2455
2456 case TOUCHPLATE__STATIC:
2457 if (pData[1] == 1 && (int16_t)pSprite->hitag >= 0) // Move the sector floor
2458 {
2459 int const floorZ = sector[sectNum].floorz;
2460
2461 if (pData[3] == 1)
2462 {
2463 if (floorZ >= pData[2])
2464 {
2465 sector[sectNum].floorz = floorZ;
2466 pData[1] = 0;
2467 }
2468 else
2469 {
2470 sector[sectNum].floorz += sector[sectNum].extra;
2471 int const playerNum = G_CheckPlayerInSector(sectNum);
2472 if (playerNum >= 0)
2473 g_player[playerNum].ps->pos.z += sector[sectNum].extra;
2474 }
2475 }
2476 else
2477 {
2478 if (floorZ <= pSprite->z)
2479 {
2480 sector[sectNum].floorz = pSprite->z;
2481 pData[1] = 0;
2482 }
2483 else
2484 {
2485 int32_t p;
2486 sector[sectNum].floorz -= sector[sectNum].extra;
2487 p = G_CheckPlayerInSector(sectNum);
2488 if (p >= 0)
2489 g_player[p].ps->pos.z -= sector[sectNum].extra;
2490 }
2491 }
2492 goto next_sprite;
2493 }
2494
2495 if (pData[5] == 1)
2496 goto next_sprite;
2497
2498 {
2499 int32_t p = G_CheckPlayerInSector(sectNum);
2500
2501 if (p >= 0 && (g_player[p].ps->on_ground || pSprite->ang == 512))
2502 {
2503 if (pData[0] == 0 && !G_CheckActivatorMotion(pSprite->lotag))
2504 {
2505 pData[0] = 1;
2506 pData[1] = 1;
2507 pData[3] = !pData[3];
2508 G_OperateMasterSwitches(pSprite->lotag);
2509 G_OperateActivators(pSprite->lotag, p);
2510 if ((int16_t)pSprite->hitag > 0)
2511 {
2512 pSprite->hitag--;
2513 if (pSprite->hitag == 0)
2514 pData[5] = 1;
2515 }
2516 }
2517 }
2518 else
2519 pData[0] = 0;
2520 }
2521
2522 if (pData[1] == 1)
2523 {
2524 for (SPRITES_OF(STAT_STANDABLE, j))
2525 {
2526 if (j != spriteNum && sprite[j].picnum == TOUCHPLATE && sprite[j].lotag == pSprite->lotag)
2527 {
2528 actor[j].t_data[1] = 1;
2529 actor[j].t_data[3] = pData[3];
2530 }
2531 }
2532 }
2533 goto next_sprite;
2534
2535 case CANWITHSOMETHING2__STATIC:
2536 case CANWITHSOMETHING3__STATIC:
2537 case CANWITHSOMETHING4__STATIC:
2538 if (RR) goto next_sprite;
2539 fallthrough__;
2540 case CANWITHSOMETHING__STATIC:
2541 A_Fall(spriteNum);
2542 if (A_IncurDamage(spriteNum) >= 0)
2543 {
2544 A_PlaySound(REALITY ? 16 : VENT_BUST, spriteNum);
2545
2546 for (j = 9; j >= 0; j--) RANDOMSCRAP(pSprite, spriteNum);
2547
2548 if (pSprite->lotag)
2549 A_Spawn(spriteNum, pSprite->lotag);
2550
2551 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2552 }
2553 goto next_sprite;
2554
2555 case FLOORFLAME__STATIC:
2556 if (RR) goto next_sprite;
2557 fallthrough__;
2558 case EXPLODINGBARREL__STATIC:
2559 case WOODENHORSE__STATIC:
2560 case HORSEONSIDE__STATIC:
2561 case FIREBARREL__STATIC:
2562 case FIREVASE__STATIC:
2563 case NUKEBARREL__STATIC:
2564 case NUKEBARRELDENTED__STATIC:
2565 case NUKEBARRELLEAKED__STATIC:
2566 case TOILETWATER__STATIC:
2567 case RUBBERCAN__STATIC:
2568 case STEAM__STATIC:
2569 case CEILINGSTEAM__STATIC:
2570 case WATERBUBBLEMAKER__STATIC:
2571 if (!G_HaveActor(sprite[spriteNum].picnum))
2572 goto next_sprite;
2573 {
2574 int32_t playerDist;
2575 int const playerNum = A_FindPlayer(pSprite, &playerDist);
2576 A_Execute(spriteNum, playerNum, playerDist);
2577 }
2578 goto next_sprite;
2579 }
2580 }
2581
2582 next_sprite:
2583 spriteNum = nextSprite;
2584 }
2585 }
2586
A_DoProjectileBounce(int const spriteNum)2587 ACTOR_STATIC void A_DoProjectileBounce(int const spriteNum)
2588 {
2589 spritetype * const pSprite = &sprite[spriteNum];
2590 int32_t const hitSectnum = pSprite->sectnum;
2591 int const firstWall = sector[hitSectnum].wallptr;
2592 int const secondWall = wall[firstWall].point2;
2593 int const wallAngle = getangle(wall[secondWall].x - wall[firstWall].x, wall[secondWall].y - wall[firstWall].y);
2594 vec3_t vect = { mulscale10(pSprite->xvel, sintable[(pSprite->ang + 512) & 2047]),
2595 mulscale10(pSprite->xvel, sintable[pSprite->ang & 2047]), pSprite->zvel };
2596
2597 int k = (pSprite->z<(actor[spriteNum].floorz + actor[spriteNum].ceilingz)>> 1) ? sector[hitSectnum].ceilingheinum
2598 : sector[hitSectnum].floorheinum;
2599
2600 vec3_t const da = { mulscale14(k, sintable[(wallAngle)&2047]),
2601 mulscale14(k, sintable[(wallAngle + 1536) & 2047]), 4096 };
2602
2603 k = vect.x * da.x + vect.y * da.y + vect.z * da.z;
2604 int l = da.x * da.x + da.y * da.y + da.z * da.z;
2605
2606 if ((klabs(k) >> 14) < l)
2607 {
2608 k = divscale17(k, l);
2609 vect.x -= mulscale16(da.x, k);
2610 vect.y -= mulscale16(da.y, k);
2611 vect.z -= mulscale16(da.z, k);
2612 }
2613
2614 pSprite->zvel = vect.z;
2615 pSprite->xvel = ksqrt(dmulscale8(vect.x, vect.x, vect.y, vect.y));
2616 pSprite->ang = getangle(vect.x, vect.y);
2617 }
2618
P_HandleBeingSpitOn(DukePlayer_t * const ps)2619 ACTOR_STATIC void P_HandleBeingSpitOn(DukePlayer_t * const ps)
2620 {
2621 ps->q16horiz += F16(32);
2622 ps->return_to_center = 8;
2623
2624 if (ps->loogcnt)
2625 return;
2626
2627 if (!A_CheckSoundPlaying(ps->i, REALITY ? 168 : DUKE_LONGTERM_PAIN))
2628 A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN,ps->i);
2629
2630 int j = 3+(krand2()&3);
2631 ps->numloogs = j;
2632 ps->loogcnt = 24*4;
2633 for (bssize_t x=0; x < j; x++)
2634 {
2635 ps->loogiex[x] = krand2()%xdim;
2636 ps->loogiey[x] = krand2()%ydim;
2637 }
2638 }
2639
G_WeaponHitCeilingOrFloor(int32_t i,spritetype * s,int * j)2640 static void G_WeaponHitCeilingOrFloor(int32_t i, spritetype *s, int *j)
2641 {
2642 if (actor[i].flags & SFLAG_DIDNOSE7WATER)
2643 {
2644 actor[i].flags &= ~SFLAG_DIDNOSE7WATER;
2645 return;
2646 }
2647
2648 if (s->z < actor[i].ceilingz)
2649 {
2650 *j = 16384|s->sectnum;
2651 s->zvel = -1;
2652 }
2653 else if (s->z > actor[i].floorz + (RR ? 0 : (ZOFFSET2*(sector[s->sectnum].lotag == ST_1_ABOVE_WATER))))
2654 {
2655 *j = 16384|s->sectnum;
2656
2657 if (sector[s->sectnum].lotag != ST_1_ABOVE_WATER)
2658 s->zvel = 1;
2659 }
2660 }
2661
Proj_BounceOffWall(spritetype * s,int j)2662 static void Proj_BounceOffWall(spritetype *s, int j)
2663 {
2664 int k = getangle(
2665 wall[wall[j].point2].x-wall[j].x,
2666 wall[wall[j].point2].y-wall[j].y);
2667 s->ang = ((k<<1) - s->ang)&2047;
2668 }
2669
2670 #define PROJ_DECAYVELOCITY(s) s->xvel >>= 1, s->zvel >>= 1
2671
2672 // Maybe damage a ceiling or floor as the consequence of projectile impact.
2673 // Returns 1 if sprite <s> should be killed.
2674 // NOTE: Compare with Proj_MaybeDamageCF2() in sector.c
Proj_MaybeDamageCF(int spriteNum)2675 static int Proj_MaybeDamageCF(int spriteNum)
2676 {
2677 uspritetype const * const s = (uspritetype const *)&sprite[spriteNum];
2678
2679 if (s->zvel < 0)
2680 {
2681 if ((sector[s->sectnum].ceilingstat&1) && sector[s->sectnum].ceilingpal == 0)
2682 return 1;
2683
2684 Sect_DamageCeiling(s->sectnum);
2685 }
2686
2687 return 0;
2688 }
2689
getanglediff(int a1,int a2)2690 static int getanglediff(int a1, int a2)
2691 {
2692 int a = min(a1, a2);
2693 int v1 = a1 - a;
2694 int v2 = a2 - a;
2695 if (v2 > v1)
2696 {
2697 if (v2 > 1024)
2698 return v2 - 2048;
2699 return v2;
2700 }
2701 if (v1 > 1024)
2702 return 2048 - v1;
2703 return -v1;
2704 }
2705
G_MoveWeapons(void)2706 ACTOR_STATIC void G_MoveWeapons(void)
2707 {
2708 int spriteNum = headspritestat[STAT_PROJECTILE];
2709
2710 while (spriteNum >= 0)
2711 {
2712 int const nextSprite = nextspritestat[spriteNum];
2713 spritetype *const pSprite = &sprite[spriteNum];
2714
2715 if (pSprite->sectnum < 0)
2716 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2717
2718 actor[spriteNum].bpos = *(vec3_t *)pSprite;
2719
2720 // hard coded projectiles
2721 switch (DYNAMICTILEMAP(pSprite->picnum))
2722 {
2723 case KNEE__STATIC:
2724 if (RR) goto next_sprite;
2725 fallthrough__;
2726 case RADIUSEXPLOSION__STATIC: DELETE_SPRITE_AND_CONTINUE(spriteNum);
2727 case TONGUE__STATIC:
2728 T1(spriteNum) = sintable[T2(spriteNum)&2047] >> 9;
2729 T2(spriteNum) += 32;
2730 if (T2(spriteNum) > 2047)
2731 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2732
2733 if (sprite[pSprite->owner].statnum == MAXSTATUS && !A_CheckEnemySprite(&sprite[pSprite->owner]))
2734 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2735
2736 pSprite->ang = sprite[pSprite->owner].ang;
2737 pSprite->x = sprite[pSprite->owner].x;
2738 pSprite->y = sprite[pSprite->owner].y;
2739
2740 if (sprite[pSprite->owner].picnum == APLAYER)
2741 pSprite->z = sprite[pSprite->owner].z - (34<<8);
2742
2743 for (int i = 0; i < T1(spriteNum); i++) {
2744 int const newSprite = A_InsertSprite(pSprite->sectnum,
2745 pSprite->x+((i*sintable[(pSprite->ang+512)&2047])>>9),
2746 pSprite->y+((i*sintable[pSprite->ang])>>9),
2747 pSprite->z+((i*ksgn(pSprite->zvel))*klabs(pSprite->zvel/12)), TONGUE, -40+i*2,
2748 8, 8, 0, 0, 0, spriteNum, STAT_MISC);
2749
2750 sprite[newSprite].cstat = 128;
2751 sprite[newSprite].pal = 8;
2752 }
2753
2754 {
2755 int const i = max(T1(spriteNum), 0);
2756 int const newSprite = A_InsertSprite(pSprite->sectnum,
2757 pSprite->x+((i*sintable[(pSprite->ang+512)&2047])>>9),
2758 pSprite->y+((i*sintable[pSprite->ang])>>9),
2759 pSprite->z+((i*ksgn(pSprite->zvel))*klabs(pSprite->zvel/12)), INNERJAW, -40,
2760 32, 32, 0, 0, 0, spriteNum, STAT_MISC);
2761
2762 sprite[newSprite].cstat = 128;
2763 if (T2(spriteNum) > 512 && T2(spriteNum) < 1024)
2764 sprite[newSprite].picnum = INNERJAW+1;
2765 }
2766 goto next_sprite;
2767
2768 case FREEZEBLAST__STATIC:
2769 if (REALITY) goto next_sprite;
2770 if (pSprite->yvel < 1 || pSprite->extra < 2 || (pSprite->xvel | pSprite->zvel) == 0)
2771 {
2772 int const newSprite = A_Spawn(spriteNum, TRANSPORTERSTAR);
2773 sprite[newSprite].pal = 1;
2774 sprite[newSprite].xrepeat = 32;
2775 sprite[newSprite].yrepeat = 32;
2776 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2777 }
2778 fallthrough__;
2779 case RPG2__STATICRR:
2780 case RRTILE1790__STATICRR:
2781 if (!RRRA && pSprite->picnum != FREEZEBLAST) goto next_sprite;
2782 fallthrough__;
2783 case SHRINKSPARK__STATIC:
2784 case RPG__STATIC:
2785 case FIRELASER__STATIC:
2786 case SPIT__STATIC:
2787 case COOLEXPLOSION1__STATIC:
2788 case OWHIP__STATICRR:
2789 case UWHIP__STATICRR:
2790 case DN64TILE3841__STATIC:
2791 {
2792 if (!RR && pSprite->picnum == COOLEXPLOSION1)
2793 if (!S_CheckSoundPlaying(spriteNum, REALITY ? 126 : WIERDSHOT_FLY))
2794 A_PlaySound(REALITY ? 126 : WIERDSHOT_FLY, spriteNum);
2795
2796 if (!REALITY && pSprite->picnum == DN64TILE3841)
2797 goto next_sprite;
2798
2799 int spriteXvel = pSprite->xvel;
2800 int spriteZvel = pSprite->zvel;
2801
2802 if ((pSprite->picnum == RPG || (RRRA && pSprite->picnum == RPG2)) && sector[pSprite->sectnum].lotag == ST_2_UNDERWATER)
2803 {
2804 spriteXvel >>= 1;
2805 spriteZvel >>= 1;
2806 }
2807
2808 vec3_t davect = *(vec3_t *) pSprite;
2809
2810 A_GetZLimits(spriteNum);
2811
2812 if (pSprite->picnum == RPG && actor[spriteNum].picnum != BOSS2 && (REALITY || pSprite->xrepeat >= 10)
2813 && sector[pSprite->sectnum].lotag != ST_2_UNDERWATER && (!REALITY || numplayers == 1))
2814 {
2815 int const newSprite = A_Spawn(spriteNum, SMALLSMOKE);
2816 sprite[newSprite].z += (1 << 8);
2817 }
2818
2819 if (RRRA)
2820 {
2821 if (pSprite->picnum == RPG2)
2822 {
2823 pSprite->hitag++;
2824 if (actor[spriteNum].picnum != BOSS2 && pSprite->xrepeat >= 10
2825 && sector[pSprite->sectnum].lotag != ST_2_UNDERWATER)
2826 {
2827 int const newSprite = A_Spawn(spriteNum, SMALLSMOKE);
2828 sprite[newSprite].z += (1 << 8);
2829 if ((krand2() & 15) == 2)
2830 A_Spawn(spriteNum, MONEY);
2831 }
2832 if (sprite[pSprite->lotag].extra <= 0)
2833 pSprite->lotag = 0;
2834 else if (pSprite->lotag != 0 && pSprite->hitag > 5)
2835 {
2836 spritetype *pTarget = &sprite[pSprite->lotag];
2837 int const angle = getangle(pTarget->x - pSprite->x, pTarget->y - pSprite->y);
2838 int const angleDiff = angle - pSprite->ang;
2839 int const angleDiffAbs = klabs(angleDiff);
2840 if (angleDiff < 100)
2841 {
2842 if (angleDiffAbs > 1023)
2843 pSprite->ang += 51;
2844 else
2845 pSprite->ang -= 51;
2846 }
2847 else if (angleDiff > 100)
2848 {
2849 if (angleDiffAbs > 1023)
2850 pSprite->ang -= 51;
2851 else
2852 pSprite->ang += 51;
2853 }
2854 else
2855 pSprite->ang = angle;
2856
2857 if (pSprite->hitag > 180 && pSprite->zvel <= 0)
2858 pSprite->zvel += 200;
2859 }
2860 }
2861 else if (pSprite->picnum == RRTILE1790)
2862 {
2863 if (pSprite->extra)
2864 {
2865 pSprite->zvel = -(pSprite->extra * 250);
2866 pSprite->extra--;
2867 }
2868 else
2869 A_Fall(spriteNum);
2870 if (pSprite->xrepeat >= 10 && sector[pSprite->sectnum].lotag != ST_2_UNDERWATER)
2871 {
2872 int const newSprite = A_Spawn(spriteNum, SMALLSMOKE);
2873 sprite[newSprite].z += (1 << 8);
2874 }
2875 }
2876 }
2877
2878 int ang = pSprite->ang;
2879
2880 if (REALITY && pSprite->picnum == RPG && pSprite->xvel < 640)
2881 {
2882 if (pSprite->xvel == 512)
2883 {
2884 ang += sintable[((int)totalclock * 32 + 512) & 2047] >> 9;
2885 spriteZvel += sintable[((int)totalclock * 32) & 2047] >> 4;
2886 }
2887 else
2888 {
2889 ang += sintable[((int)totalclock * 32 + 5) & 2047] >> 9;
2890 spriteZvel += sintable[((int)totalclock * 32 + 512) & 2047] >> 4;
2891 }
2892 }
2893
2894 vec3_t const tmpvect = { (spriteXvel * (sintable[(ang + 512) & 2047])) >> 14,
2895 (spriteXvel * (sintable[ang & 2047])) >> 14, spriteZvel };
2896
2897 int moveSprite = A_MoveSprite(spriteNum, &tmpvect, CLIPMASK1);
2898
2899 if ((pSprite->picnum == RPG || (RRRA && (pSprite->picnum == RPG2 || pSprite->picnum == RRTILE1790)))
2900 && (unsigned) pSprite->yvel < MAXSPRITES) // RPG_YVEL
2901 {
2902 if (REALITY && pSprite->xvel < 640)
2903 {
2904 int ta = getangle(sprite[pSprite->yvel].x - pSprite->x, sprite[pSprite->yvel].y - pSprite->y);
2905 int td = clamp(getanglediff(pSprite->ang, ta), -20, 20);
2906 pSprite->ang += td;
2907 pSprite->z += clamp(sprite[pSprite->yvel].z - pSprite->z - (32 << 8), -1024, 1024);
2908
2909 }
2910 if (FindDistance2D(pSprite->x - sprite[pSprite->yvel].x, pSprite->y - sprite[pSprite->yvel].y) < 256)
2911 moveSprite = 49152 | pSprite->yvel;
2912 }
2913
2914 //actor[spriteNum].movflag = moveSprite;
2915
2916 if (pSprite->sectnum < 0)
2917 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2918
2919 //if (RR && g_sectorExtra[pSprite->sectnum] == 800)
2920 // DELETE_SPRITE_AND_CONTINUE(spriteNum);
2921
2922 if ((moveSprite & 49152) != 49152 && (REALITY || pSprite->picnum != FREEZEBLAST))
2923 G_WeaponHitCeilingOrFloor(spriteNum, pSprite, &moveSprite);
2924
2925 if (REALITY && pSprite->picnum == RPG)
2926 {
2927 int const newSprite = A_InsertSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, DN64TILE3845,
2928 0, 64, 32, 0, 0, 0, pSprite->owner, 5);
2929 sprite[newSprite].cstat = 128;
2930 }
2931
2932 if (pSprite->picnum == FIRELASER)
2933 {
2934 for (bssize_t k = -3; k < 2; k++)
2935 {
2936 int const newSprite
2937 = A_InsertSprite(pSprite->sectnum, pSprite->x + ((k * sintable[(pSprite->ang + 512) & 2047]) >> 9),
2938 pSprite->y + ((k * sintable[pSprite->ang & 2047]) >> 9),
2939 pSprite->z + ((k * ksgn(pSprite->zvel)) * klabs(pSprite->zvel / 24)), FIRELASER, -40 + (k << 2),
2940 pSprite->xrepeat, pSprite->yrepeat, 0, 0, 0, pSprite->owner, 5);
2941
2942 sprite[newSprite].cstat = 128;
2943 sprite[newSprite].pal = pSprite->pal;
2944 }
2945 }
2946 else if (pSprite->picnum == SPIT)
2947 if (pSprite->zvel < 6144)
2948 pSprite->zvel += g_spriteGravity - 112;
2949
2950 if (moveSprite != 0)
2951 {
2952 if (!RR && pSprite->picnum == COOLEXPLOSION1)
2953 {
2954 if ((moveSprite & 49152) == 49152 && sprite[moveSprite & (MAXSPRITES - 1)].picnum != APLAYER)
2955 goto COOLEXPLOSION;
2956 pSprite->xvel = 0;
2957 pSprite->zvel = 0;
2958 }
2959
2960 switch (moveSprite & 49152)
2961 {
2962 case 49152:
2963 moveSprite &= (MAXSPRITES - 1);
2964
2965 if (RRRA && sprite[moveSprite].picnum == MINION && (pSprite->picnum == RPG || pSprite->picnum == RPG2)
2966 && sprite[moveSprite].pal == 19)
2967 {
2968 int const newSprite = A_Spawn(spriteNum, EXPLOSION2);
2969 A_PlaySound(RPG_EXPLODE, newSprite);
2970 sprite[newSprite].x = davect.x;
2971 sprite[newSprite].y = davect.y;
2972 sprite[newSprite].z = davect.z;
2973 goto next_sprite;
2974 }
2975
2976 if (!RRRA && !REALITY && pSprite->picnum == FREEZEBLAST && sprite[moveSprite].pal == 1)
2977 if (A_CheckEnemySprite(&sprite[moveSprite]) || sprite[moveSprite].picnum == APLAYER)
2978 {
2979 int const newSprite = A_Spawn(spriteNum, TRANSPORTERSTAR);
2980 sprite[newSprite].pal = 1;
2981 sprite[newSprite].xrepeat = 32;
2982 sprite[newSprite].yrepeat = 32;
2983
2984 DELETE_SPRITE_AND_CONTINUE(spriteNum);
2985 }
2986
2987 A_DamageObject(moveSprite, spriteNum);
2988
2989 if (sprite[moveSprite].picnum == APLAYER)
2990 {
2991 int const playerNum = P_Get(moveSprite);
2992 A_PlaySound(REALITY ? 1 : PISTOL_BODYHIT, moveSprite);
2993
2994 if (pSprite->picnum == SPIT)
2995 {
2996 if (RRRA && sprite[pSprite->owner].picnum == MAMA)
2997 {
2998 A_DoGuts(spriteNum, RABBITJIBA, 2);
2999 A_DoGuts(spriteNum, RABBITJIBB, 2);
3000 A_DoGuts(spriteNum, RABBITJIBC, 2);
3001 }
3002 P_HandleBeingSpitOn(g_player[playerNum].ps);
3003 }
3004 }
3005 break;
3006
3007 case 32768:
3008 moveSprite &= (MAXWALLS - 1);
3009
3010 if (RRRA && sprite[pSprite->owner].picnum == MAMA)
3011 {
3012 A_DoGuts(spriteNum, RABBITJIBA, 2);
3013 A_DoGuts(spriteNum, RABBITJIBB, 2);
3014 A_DoGuts(spriteNum, RABBITJIBC, 2);
3015 }
3016
3017 if (pSprite->picnum != RPG && (!REALITY || pSprite->picnum != DN64TILE3841) && (!RRRA || pSprite->picnum != RPG2) && (REALITY || pSprite->picnum != FREEZEBLAST) && pSprite->picnum != SPIT
3018 && (!RR || pSprite->picnum != SHRINKSPARK) && (wall[moveSprite].overpicnum == MIRROR || wall[moveSprite].picnum == MIRROR))
3019 {
3020 Proj_BounceOffWall(pSprite, moveSprite);
3021 pSprite->owner = spriteNum;
3022 A_Spawn(spriteNum, TRANSPORTERSTAR);
3023 goto next_sprite;
3024 }
3025 else
3026 {
3027 setsprite(spriteNum, &davect);
3028 A_DamageWall(spriteNum, moveSprite, (vec3_t *)pSprite, pSprite->picnum);
3029
3030 if (!RRRA && !REALITY && pSprite->picnum == FREEZEBLAST)
3031 {
3032 if (wall[moveSprite].overpicnum != MIRROR && wall[moveSprite].picnum != MIRROR)
3033 {
3034 pSprite->extra >>= 1;
3035 if (RR)
3036 {
3037 if (pSprite->xrepeat > 8)
3038 pSprite->xrepeat--;
3039 if (pSprite->yrepeat > 8)
3040 pSprite->yrepeat--;
3041 }
3042 pSprite->yvel--;
3043 }
3044
3045 Proj_BounceOffWall(pSprite, moveSprite);
3046 goto next_sprite;
3047 }
3048
3049 if (RR && pSprite->picnum == SHRINKSPARK)
3050 {
3051 if (wall[moveSprite].picnum >= RRTILE3643 && wall[moveSprite].picnum < RRTILE3643+3)
3052 DELETE_SPRITE_AND_CONTINUE(spriteNum);
3053 if (pSprite->extra <= 0)
3054 {
3055 pSprite->x += sintable[(pSprite->ang+512)&2047]>>7;
3056 pSprite->y += sintable[pSprite->ang&2047]>>7;
3057
3058 if (!RRRA || (sprite[pSprite->owner].picnum != CHEER && sprite[pSprite->owner].picnum != CHEERSTAYPUT))
3059 {
3060 int const newSprite = A_Spawn(spriteNum, CIRCLESTUCK);
3061 sprite[newSprite].xrepeat = 8;
3062 sprite[newSprite].yrepeat = 8;
3063 sprite[newSprite].cstat = 16;
3064 sprite[newSprite].ang = (sprite[newSprite].ang+512)&2047;
3065 sprite[newSprite].clipdist = mulscale7(pSprite->xrepeat, tilesiz[pSprite->picnum].x);
3066 }
3067 DELETE_SPRITE_AND_CONTINUE(spriteNum);
3068 }
3069 if (wall[moveSprite].overpicnum != MIRROR && wall[moveSprite].picnum != MIRROR)
3070 {
3071 pSprite->extra -= 20;
3072 pSprite->yvel--;
3073 }
3074
3075 Proj_BounceOffWall(pSprite, moveSprite);
3076 goto next_sprite;
3077 }
3078 }
3079 break;
3080
3081 case 16384:
3082 setsprite(spriteNum, &davect);
3083
3084 if (RRRA && sprite[pSprite->owner].picnum == MAMA)
3085 {
3086 A_DoGuts(spriteNum, RABBITJIBA, 2);
3087 A_DoGuts(spriteNum, RABBITJIBB, 2);
3088 A_DoGuts(spriteNum, RABBITJIBC, 2);
3089 }
3090
3091 if (Proj_MaybeDamageCF(spriteNum))
3092 DELETE_SPRITE_AND_CONTINUE(spriteNum);
3093
3094 if (!RRRA && !REALITY && pSprite->picnum == FREEZEBLAST)
3095 {
3096 A_DoProjectileBounce(spriteNum);
3097 A_SetSprite(spriteNum, CLIPMASK1);
3098
3099 pSprite->extra >>= 1;
3100
3101 if (pSprite->xrepeat > 8)
3102 pSprite->xrepeat -= 2;
3103
3104 if (pSprite->yrepeat > 8)
3105 pSprite->yrepeat -= 2;
3106
3107 pSprite->yvel--;
3108 goto next_sprite;
3109 }
3110 break;
3111 default: break;
3112 }
3113
3114 switch (DYNAMICTILEMAP(pSprite->picnum))
3115 {
3116 case COOLEXPLOSION1__STATIC:
3117 if (RR) goto default_case;
3118 fallthrough__;
3119 case SPIT__STATIC:
3120 case FREEZEBLAST__STATIC:
3121 case FIRELASER__STATIC: break;
3122
3123 case RPG__STATIC:
3124 case RPG2__STATICRR:
3125 case RRTILE1790__STATICRR:
3126 {
3127 if (!RRRA && (pSprite->picnum == RPG2 || pSprite->picnum == RRTILE1790))
3128 break;
3129 int const newSprite = A_Spawn(spriteNum, EXPLOSION2);
3130 if (pSprite->picnum == RPG2)
3131 {
3132 pSprite->extra = 150;
3133 A_PlaySound(247, newSprite);
3134 }
3135 else if (pSprite->picnum == RRTILE1790)
3136 {
3137 pSprite->extra = 160;
3138 A_PlaySound(RPG_EXPLODE, newSprite);
3139 }
3140 else
3141 A_PlaySound(REALITY ? 8 : RPG_EXPLODE, newSprite);
3142 Bmemcpy(&sprite[newSprite], &davect, sizeof(vec3_t));
3143
3144 if (!REALITY && pSprite->xrepeat < 10)
3145 {
3146 sprite[newSprite].xrepeat = 6;
3147 sprite[newSprite].yrepeat = 6;
3148 }
3149 else if ((moveSprite & 49152) == 16384)
3150 {
3151 if (!RR && !REALITY && pSprite->zvel > 0)
3152 A_Spawn(spriteNum, EXPLOSION2BOT);
3153 else
3154 {
3155 sprite[newSprite].cstat |= 8;
3156 sprite[newSprite].z += (48 << 8);
3157 }
3158 }
3159
3160 if (REALITY || pSprite->xrepeat >= 10)
3161 {
3162 int const x = pSprite->extra;
3163 A_RadiusDamage(spriteNum, g_rpgRadius, x >> 2, x >> 1, x - (x >> 2), x);
3164 }
3165 else
3166 {
3167 int const x = pSprite->extra + (g_globalRandom & 3);
3168 A_RadiusDamage(spriteNum, (g_rpgRadius >> 1), x >> 2, x >> 1, x - (x >> 2), x);
3169 }
3170 break;
3171 }
3172
3173 case SHRINKSPARK__STATIC:
3174 if (RR)
3175 break;
3176 A_Spawn(spriteNum, SHRINKEREXPLOSION);
3177 A_PlaySound(REALITY ? 197 : SHRINKER_HIT, spriteNum);
3178 A_RadiusDamage(spriteNum, g_shrinkerRadius, 0, 0, 0, 0);
3179 break;
3180
3181 case DN64TILE3841__STATIC:
3182 {
3183 if (!REALITY)
3184 goto default_case;
3185 int const newSprite = A_InsertSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z,
3186 FORCERIPPLE, -127, 64, 64, 0, 0, 0, spriteNum, 5);
3187 sprite[newSprite].cstat = 128;
3188 if (pSprite->yvel > 88)
3189 {
3190 A_PlaySound(271, newSprite);
3191 for (int TRAVERSE_CONNECT(pn))
3192 {
3193 DukePlayer_t *ps = g_player[pn].ps;
3194 if (ps->last_extra > 0
3195 && cansee(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum,
3196 ps->pos.x, ps->pos.y, ps->pos.z, ps->cursectnum))
3197 {
3198 P_PalFrom(ps, pSprite->yvel - 32, 64, 96, 96);
3199 }
3200 }
3201 g_earthquakeTime = 15;
3202 RT_AddExplosion(pSprite->x >> 1, pSprite->y >> 1, pSprite->z >> 5, 4);
3203 }
3204 else
3205 {
3206 A_PlaySound(8, newSprite);
3207 RT_AddExplosion(pSprite->x >> 1, pSprite->y >> 1, pSprite->z >> 5, 6);
3208 }
3209 int const x = pSprite->extra;
3210 A_RadiusDamage(spriteNum, g_rpgRadius + pSprite->yvel * 30, x >> 2, x >> 1, x - (x >> 2), x);
3211 break;
3212 }
3213
3214 default:
3215 default_case:
3216 {
3217 if (REALITY)
3218 break;
3219 int const newSprite = A_Spawn(spriteNum, EXPLOSION2);
3220 sprite[newSprite].xrepeat = sprite[newSprite].yrepeat = pSprite->xrepeat >> 1;
3221 if ((moveSprite & 49152) == 16384)
3222 {
3223 if (pSprite->zvel < 0)
3224 {
3225 sprite[newSprite].cstat |= 8;
3226 sprite[newSprite].z += (72 << 8);
3227 }
3228 }
3229 break;
3230 }
3231 }
3232
3233 if (RR || pSprite->picnum != COOLEXPLOSION1)
3234 DELETE_SPRITE_AND_CONTINUE(spriteNum);
3235 }
3236
3237 if (!RR && pSprite->picnum == COOLEXPLOSION1)
3238 {
3239 COOLEXPLOSION:
3240 pSprite->shade++;
3241 if (pSprite->shade >= 40)
3242 DELETE_SPRITE_AND_CONTINUE(spriteNum);
3243 }
3244 else if ((pSprite->picnum == RPG || (RRRA && pSprite->picnum == RPG2)) && sector[pSprite->sectnum].lotag == ST_2_UNDERWATER && (REALITY || pSprite->xrepeat >= 10) && rnd(140))
3245 A_Spawn(spriteNum, WATERBUBBLE);
3246
3247 goto next_sprite;
3248 }
3249
3250 case DN64TILE2596__STATIC:
3251 case DN64TILE2597__STATIC:
3252 case DN64TILE2598__STATIC:
3253 case DN64TILE2599__STATIC:
3254 if (!REALITY)
3255 goto next_sprite;
3256 case SHOTSPARK1__STATIC:
3257 {
3258 if (!G_HaveActor(sprite[spriteNum].picnum))
3259 goto next_sprite;
3260 int32_t playerDist;
3261 int const playerNum = A_FindPlayer(pSprite, &playerDist);
3262 A_Execute(spriteNum, playerNum, playerDist);
3263 goto next_sprite;
3264 }
3265 }
3266 next_sprite:
3267 spriteNum = nextSprite;
3268 }
3269 }
3270
3271
P_Submerge(int const spriteNum,int const playerNum,DukePlayer_t * const pPlayer,int const sectNum,int const otherSect)3272 static int P_Submerge(int const spriteNum, int const playerNum, DukePlayer_t * const pPlayer, int const sectNum, int const otherSect)
3273 {
3274 if ((!RR && pPlayer->on_ground && pPlayer->pos.z > sector[sectNum].floorz - ZOFFSET2
3275 && (TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_CROUCH) || pPlayer->vel.z > 2048))
3276 || (RR && pPlayer->pos.z > (sector[sectNum].floorz-(6<<8))) || pPlayer->on_motorcycle)
3277 // if( onfloorz && sectlotag == 1 && ps->pos.z > (sector[sect].floorz-(6<<8)) )
3278 {
3279 if (pPlayer->on_boat) return 0;
3280
3281 if (screenpeek == playerNum)
3282 {
3283 FX_StopAllSounds();
3284 S_ClearSoundLocks();
3285 }
3286
3287 if (RR || sprite[pPlayer->i].extra > 0)
3288 A_PlaySound(REALITY ? 37 : DUKE_UNDERWATER, spriteNum);
3289
3290 pPlayer->opos.z = pPlayer->pos.z = sector[otherSect].ceilingz + (7<<8);
3291
3292 if (!RR)
3293 {
3294 pPlayer->vel.x = 4096-(krand2()&8192);
3295 pPlayer->vel.y = 4096-(krand2()&8192);
3296 }
3297
3298 if (pPlayer->on_motorcycle)
3299 pPlayer->moto_underwater = 1;
3300
3301 return 1;
3302 }
3303
3304 return 0;
3305 }
3306
P_Emerge(int const spriteNum,int const playerNum,DukePlayer_t * const pPlayer,int const sectNum,int const otherSect)3307 static int P_Emerge(int const spriteNum, int const playerNum, DukePlayer_t * const pPlayer, int const sectNum, int const otherSect)
3308 {
3309 // r1449-:
3310 if (pPlayer->pos.z < (sector[sectNum].ceilingz+(6<<8)))
3311 // r1450+, breaks submergible slime in bobsp2:
3312 // if (onfloorz && sectlotag == 2 && ps->pos.z <= sector[sect].ceilingz /*&& ps->vel.z == 0*/)
3313 {
3314 if (RR && sprite[pPlayer->i].extra <= 0) return 1;
3315 if (screenpeek == playerNum)
3316 {
3317 FX_StopAllSounds();
3318 S_ClearSoundLocks();
3319 }
3320
3321 A_PlaySound(REALITY ? 21 : DUKE_GASP, spriteNum);
3322
3323 pPlayer->opos.z = pPlayer->pos.z = sector[otherSect].floorz - (7<<8);
3324 //pPlayer->vel.z = 0;
3325 // ps->vel.z += 1024;
3326
3327 if (!RR)
3328 {
3329 pPlayer->jumping_toggle = 1;
3330 pPlayer->jumping_counter = 0;
3331 }
3332
3333 return 1;
3334 }
3335
3336 return 0;
3337 }
3338
P_FinishWaterChange(int const playerNum,DukePlayer_t * const pPlayer,int const sectLotag,int const spriteOwner,int const newSector)3339 static void P_FinishWaterChange(int const playerNum, DukePlayer_t * const pPlayer, int const sectLotag, int const spriteOwner, int const newSector)
3340 {
3341 /*pPlayer->bobpos.x = */pPlayer->opos.x = pPlayer->pos.x;
3342 /*pPlayer->bobpos.y = */pPlayer->opos.y = pPlayer->pos.y;
3343
3344 if (spriteOwner < 0 || sprite[spriteOwner].owner != spriteOwner)
3345 pPlayer->transporter_hold = -2;
3346
3347 pPlayer->cursectnum = newSector;
3348 changespritesect(playerNum, newSector);
3349
3350 if (!RR)
3351 {
3352 vec3_t vect = pPlayer->pos;
3353 vect.z += PHEIGHT;
3354 setsprite(pPlayer->i, &vect);
3355 }
3356
3357 P_UpdateScreenPal(pPlayer);
3358
3359 if ((krand2()&255) < 32)
3360 A_Spawn(RR ? pPlayer->i : playerNum, WATERSPLASH2);
3361
3362 if (!RR && sectLotag == ST_1_ABOVE_WATER)
3363 {
3364 for (bssize_t l = 0; l < 9; l++)
3365 sprite[A_Spawn(pPlayer->i, WATERBUBBLE)].z += krand2() & 16383;
3366 }
3367 }
3368
3369 // Check prevention of teleportation *when alive*. For example, commanders and
3370 // octabrains would be transported by SE7 (both water and normal) only if dead.
A_CheckNonTeleporting(int const spriteNum)3371 static int A_CheckNonTeleporting(int const spriteNum)
3372 {
3373 int const tileNum = sprite[spriteNum].picnum;
3374 if (RRRA)
3375 {
3376 return !!(tileNum == SHARK || tileNum == CHEERBOAT || tileNum == HULKBOAT
3377 || tileNum == MINIONBOAT || tileNum == UFO1);
3378 }
3379 else if (RR)
3380 {
3381 return !!(tileNum == SHARK || tileNum == UFO1 || tileNum == UFO2
3382 || tileNum == UFO3 || tileNum == UFO4 || tileNum == UFO5);
3383 }
3384 return !!(tileNum == SHARK || tileNum == COMMANDER || tileNum == OCTABRAIN
3385 || (tileNum >= GREENSLIME && tileNum <= GREENSLIME + 7));
3386 }
3387
G_MoveTransports(void)3388 ACTOR_STATIC void G_MoveTransports(void)
3389 {
3390 int spriteNum = headspritestat[STAT_TRANSPORT];
3391
3392 while (spriteNum >= 0)
3393 {
3394 int const nextSprite = nextspritestat[spriteNum];
3395
3396 if (OW(spriteNum) == spriteNum)
3397 {
3398 spriteNum = nextSprite;
3399 continue;
3400 }
3401
3402 int const sectNum = SECT(spriteNum);
3403 int const sectLotag = sector[sectNum].lotag;
3404 int const onFloor = T5(spriteNum); // ONFLOORZ
3405
3406 if (T1(spriteNum) > 0)
3407 T1(spriteNum)--;
3408
3409 int sectSprite = headspritesect[sectNum];
3410 while (sectSprite >= 0)
3411 {
3412 int const nextSectSprite = nextspritesect[sectSprite];
3413
3414 switch (sprite[sectSprite].statnum)
3415 {
3416 case STAT_PLAYER:
3417 if (sprite[sectSprite].owner != -1)
3418 {
3419 int const playerNum = P_Get(sectSprite);
3420 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
3421
3422 pPlayer->on_warping_sector = 1;
3423
3424 if (pPlayer->transporter_hold == 0 && pPlayer->jumping_counter == 0)
3425 {
3426 if (pPlayer->on_ground && sectLotag == 0 && onFloor && pPlayer->jetpack_on == 0)
3427 {
3428 if (RR || sprite[spriteNum].pal == 0)
3429 {
3430 A_Spawn(spriteNum, TRANSPORTERBEAM);
3431 A_PlaySound(REALITY ? 45 : TELEPORTER, spriteNum);
3432 }
3433 for (int TRAVERSE_CONNECT(otherPlayer))
3434 {
3435 if (g_player[otherPlayer].ps->cursectnum == sprite[OW(spriteNum)].sectnum)
3436 {
3437 g_player[otherPlayer].ps->frag_ps = playerNum;
3438 sprite[g_player[otherPlayer].ps->i].extra = 0;
3439 }
3440 }
3441
3442 pPlayer->q16ang = fix16_from_int(sprite[OW(spriteNum)].ang);
3443
3444 if (sprite[OW(spriteNum)].owner != OW(spriteNum))
3445 {
3446 T1(spriteNum) = 13;
3447 actor[OW(spriteNum)].t_data[0] = 13;
3448 pPlayer->transporter_hold = 13;
3449 }
3450
3451 pPlayer->pos = sprite[OW(spriteNum)].pos;
3452 pPlayer->pos.z -= PHEIGHT-(RR ? (4<<8) : 0);
3453 pPlayer->opos = pPlayer->pos;
3454 pPlayer->bobpos = pPlayer->pos.vec2;
3455
3456 changespritesect(sectSprite, sprite[OW(spriteNum)].sectnum);
3457 pPlayer->cursectnum = sprite[sectSprite].sectnum;
3458
3459 if (RR || sprite[spriteNum].pal == 0)
3460 {
3461 int const newSprite = A_Spawn(OW(spriteNum), TRANSPORTERBEAM);
3462 A_PlaySound(REALITY ? 45 : TELEPORTER, newSprite);
3463 }
3464 break;
3465 }
3466 }
3467 else if (RR || !(sectLotag == ST_1_ABOVE_WATER && pPlayer->on_ground == 1))
3468 break;
3469
3470 if (onFloor == 0 && klabs(SZ(spriteNum) - pPlayer->pos.z) < 6144)
3471 if (!pPlayer->jetpack_on || TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_JUMP)
3472 || (TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_CROUCH) ^ pPlayer->crouch_toggle))
3473 {
3474 pPlayer->pos.x += sprite[OW(spriteNum)].x - SX(spriteNum);
3475 pPlayer->pos.y += sprite[OW(spriteNum)].y - SY(spriteNum);
3476 pPlayer->pos.z = (pPlayer->jetpack_on && (TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_JUMP)
3477 || pPlayer->jetpack_on < 11))
3478 ? sprite[OW(spriteNum)].z - 6144
3479 : sprite[OW(spriteNum)].z + 6144;
3480
3481 if (!RR)
3482 actor[pPlayer->i].bpos = pPlayer->pos;
3483 pPlayer->opos = pPlayer->pos;
3484 //pPlayer->bobpos = *(vec2_t *)&pPlayer->pos;
3485
3486 changespritesect(sectSprite, sprite[OW(spriteNum)].sectnum);
3487 pPlayer->cursectnum = sprite[OW(spriteNum)].sectnum;
3488
3489 break;
3490 }
3491
3492 int doWater = 0;
3493
3494 if (RRRA)
3495 {
3496 if (onFloor)
3497 {
3498 if (sectLotag == 160 && pPlayer->pos.z > (sector[sectNum].floorz-(48<<8)))
3499 {
3500 doWater = 2;
3501 pPlayer->opos.z = pPlayer->pos.z = sector[sprite[OW(spriteNum)].sectnum].ceilingz+(7<<8);
3502 }
3503 else if (sectLotag == 161 && pPlayer->pos.z < (sector[sectNum].ceilingz+(6<<8)) && sprite[pPlayer->i].extra > 0)
3504 {
3505 doWater = 2;
3506 pPlayer->opos.z = pPlayer->pos.z = sector[sprite[OW(spriteNum)].sectnum].floorz-(49<<8);
3507 }
3508 }
3509 }
3510
3511 if (onFloor)
3512 {
3513 if (sectLotag == ST_1_ABOVE_WATER)
3514 doWater = P_Submerge(sectSprite, playerNum, pPlayer, sectNum, sprite[OW(spriteNum)].sectnum);
3515 else if (sectLotag == ST_2_UNDERWATER)
3516 doWater = P_Emerge(sectSprite, playerNum, pPlayer, sectNum, sprite[OW(spriteNum)].sectnum);
3517 }
3518
3519 if (doWater == 1)
3520 {
3521 pPlayer->pos.x += sprite[OW(spriteNum)].x - SX(spriteNum);
3522 pPlayer->pos.y += sprite[OW(spriteNum)].y - SY(spriteNum);
3523
3524 P_FinishWaterChange(sectSprite, pPlayer, sectLotag, OW(spriteNum), sprite[OW(spriteNum)].sectnum);
3525 }
3526 else if (doWater == 2)
3527 {
3528 pPlayer->pos.x += sprite[OW(spriteNum)].x - SX(spriteNum);
3529 pPlayer->pos.y += sprite[OW(spriteNum)].y - SY(spriteNum);
3530 pPlayer->opos.x = pPlayer->pos.x;
3531 pPlayer->opos.y = pPlayer->pos.y;
3532
3533 if (sprite[OW(spriteNum)].owner != OW(spriteNum))
3534 pPlayer->transporter_hold = -2;
3535
3536 pPlayer->cursectnum = sprite[OW(spriteNum)].sectnum;
3537 changespritesect(sectSprite, sprite[OW(spriteNum)].sectnum);
3538 }
3539 }
3540 break;
3541
3542
3543 ////////// Non-player teleportation //////////
3544
3545 case STAT_ACTOR:
3546 if ((RR || sprite[sectSprite].extra > 0) && A_CheckNonTeleporting(sectSprite))
3547 goto JBOLT;
3548 fallthrough__;
3549 case STAT_PROJECTILE:
3550 case STAT_MISC:
3551 case STAT_FALLER:
3552 case STAT_DUMMYPLAYER:
3553 {
3554 if (RR && sprite[sectSprite].statnum == STAT_FALLER) break;
3555 //if ((totalclock & UINT8_MAX) != actor[sectSprite].lasttransport)
3556 {
3557 int const zvel = sprite[sectSprite].zvel;
3558 int const absZvel = klabs(zvel);
3559 int doWarp = 0;
3560 int warpDir;
3561 int absZdiff;
3562
3563 if (zvel >= 0)
3564 warpDir = 2;
3565 else
3566 warpDir = 1;
3567
3568 if (absZvel != 0)
3569 {
3570 if (sectLotag == ST_2_UNDERWATER && sprite[sectSprite].z < (sector[sectNum].ceilingz + absZvel))
3571 doWarp = 1;
3572 if (sectLotag == ST_1_ABOVE_WATER && sprite[sectSprite].z > (sector[sectNum].floorz - absZvel))
3573 if (!RRRA || (sprite[sectSprite].picnum != CHEERBOAT && sprite[sectSprite].picnum != HULKBOAT && sprite[sectSprite].picnum != MINIONBOAT))
3574 doWarp = 1;
3575 }
3576
3577 if (RRRA)
3578 {
3579 if (absZvel != 0 && sectLotag == 161 && sprite[sectSprite].z < (sector[sectNum].ceilingz + absZvel) && warpDir == 1)
3580 {
3581 doWarp = 1;
3582 absZdiff = absZvel - klabs(sprite[sectSprite].z-sector[sectNum].ceilingz);
3583 }
3584 else if (sectLotag == 161 && sprite[sectSprite].z < (sector[sectNum].ceilingz + 1000) && warpDir == 1)
3585 {
3586 doWarp = 1;
3587 absZdiff = 1;
3588 }
3589 if (absZvel != 0 && sectLotag == 160 && sprite[sectSprite].z > (sector[sectNum].floorz - absZvel) && warpDir == 2)
3590 {
3591 doWarp = 1;
3592 absZdiff = absZvel - klabs(sector[sectNum].floorz-sprite[sectSprite].z);
3593 }
3594 else if (sectLotag == 160 && sprite[sectSprite].z > (sector[sectNum].floorz - 1000) && warpDir == 2)
3595 {
3596 doWarp = 1;
3597 absZdiff = 1;
3598 }
3599 }
3600
3601 if (sectLotag == 0 && (onFloor || klabs(sprite[sectSprite].z - SZ(spriteNum)) < 4096))
3602 {
3603 if (sprite[OW(spriteNum)].owner != OW(spriteNum) && onFloor && T1(spriteNum) > 0
3604 && sprite[sectSprite].statnum != STAT_MISC)
3605 {
3606 T1(spriteNum)++;
3607 goto next_sprite;
3608 }
3609 doWarp = 1;
3610 }
3611
3612 if (doWarp)
3613 {
3614 switch (DYNAMICTILEMAP(sprite[sectSprite].picnum))
3615 {
3616 case TRIPBOMB__STATIC:
3617 case BURNING2__STATIC:
3618 case FIRE2__STATIC:
3619 case TOILETWATER__STATIC:
3620 case LASERLINE__STATIC:
3621 if (RR) goto default_case;
3622 fallthrough__;
3623 case TRIPBOMBSPRITE__STATIC:
3624 if (!RR && sprite[sectSprite].picnum == TRIPBOMBSPRITE)
3625 goto default_case;
3626 fallthrough__;
3627 case TRANSPORTERSTAR__STATIC:
3628 case TRANSPORTERBEAM__STATIC:
3629 case BULLETHOLE__STATIC:
3630 case WATERSPLASH2__STATIC:
3631 case BURNING__STATIC:
3632 case FIRE__STATIC:
3633 case MUD__STATICRR: goto JBOLT;
3634 case PLAYERONWATER__STATIC:
3635 if (sectLotag == ST_2_UNDERWATER)
3636 {
3637 sprite[sectSprite].cstat &= 32767;
3638 break;
3639 }
3640 fallthrough__;
3641 default:
3642 default_case:
3643 if (sprite[sectSprite].statnum == STAT_MISC && !(sectLotag == ST_1_ABOVE_WATER || sectLotag == ST_2_UNDERWATER || (RRRA && (sectLotag == 160 || sectLotag == 161))))
3644 break;
3645 fallthrough__;
3646 case WATERBUBBLE__STATIC:
3647 if (RR)
3648 if( rnd(192) && sprite[sectSprite].picnum == WATERBUBBLE)
3649 break;
3650
3651 if (sectLotag > 0)
3652 {
3653 // Water SE7 teleportation.
3654 int const osect = sprite[OW(spriteNum)].sectnum;
3655
3656 Bassert(sectLotag == ST_1_ABOVE_WATER || sectLotag == ST_2_UNDERWATER || (RRRA && (sectLotag == 160 || sectLotag == 161)));
3657
3658 int const newSprite = A_Spawn(sectSprite, WATERSPLASH2);
3659
3660 if (sectLotag == ST_1_ABOVE_WATER && sprite[sectSprite].statnum == STAT_PROJECTILE)
3661 {
3662 sprite[newSprite].xvel = sprite[sectSprite].xvel >> 1;
3663 sprite[newSprite].ang = sprite[sectSprite].ang;
3664 A_SetSprite(newSprite, CLIPMASK0);
3665 }
3666
3667 actor[sectSprite].lasttransport = ((int32_t) totalclock & UINT8_MAX);
3668
3669 if (sectLotag == ST_1_ABOVE_WATER || sectLotag == ST_2_UNDERWATER)
3670 {
3671 sprite[sectSprite].x += sprite[OW(spriteNum)].x - SX(spriteNum);
3672 sprite[sectSprite].y += sprite[OW(spriteNum)].y - SY(spriteNum);
3673 sprite[sectSprite].z = (sectLotag == ST_1_ABOVE_WATER) ? sector[osect].ceilingz+absZvel : sector[osect].floorz-absZvel;
3674
3675 actor[sectSprite].bpos = sprite[sectSprite].pos;
3676
3677 changespritesect(sectSprite, sprite[OW(spriteNum)].sectnum);
3678 }
3679 else
3680 {
3681 sprite[sectSprite].x += sprite[OW(spriteNum)].x - SX(spriteNum);
3682 sprite[sectSprite].y += sprite[OW(spriteNum)].y - SY(spriteNum);
3683 sprite[sectSprite].z = (sectLotag == 160) ? sector[osect].ceilingz+absZdiff : sector[osect].floorz-absZdiff;
3684
3685 actor[sectSprite].bpos = sprite[sectSprite].pos;
3686
3687 changespritesect(sectSprite, sprite[OW(spriteNum)].sectnum);
3688
3689 vec3_t const vect = {
3690 (sprite[sectSprite].xvel*sintable[(sprite[sectSprite].ang+512)&2047])>>14,
3691 (sprite[sectSprite].xvel*sintable[sprite[sectSprite].ang])>>14,
3692 0
3693 };
3694
3695 A_MoveSprite(sectSprite, &vect, CLIPMASK1);
3696 }
3697 }
3698 else if (Bassert(sectLotag == 0), 1)
3699 {
3700 // Non-water SE7 teleportation.
3701
3702 if (onFloor)
3703 {
3704 if ((!RR && sprite[sectSprite].statnum == STAT_PROJECTILE)
3705 || (G_CheckPlayerInSector(sectNum) == -1
3706 && G_CheckPlayerInSector(sprite[OW(spriteNum)].sectnum) == -1))
3707 {
3708 sprite[sectSprite].x += (sprite[OW(spriteNum)].x - SX(spriteNum));
3709 sprite[sectSprite].y += (sprite[OW(spriteNum)].y - SY(spriteNum));
3710 sprite[sectSprite].z -= SZ(spriteNum) - sector[sprite[OW(spriteNum)].sectnum].floorz;
3711
3712 sprite[sectSprite].ang = sprite[OW(spriteNum)].ang;
3713 actor[sectSprite].bpos = sprite[sectSprite].pos;
3714
3715 if (RR || sprite[spriteNum].pal == 0)
3716 {
3717 int newSprite = A_Spawn(spriteNum, TRANSPORTERBEAM);
3718 A_PlaySound(REALITY ? 45 : TELEPORTER, newSprite);
3719
3720 newSprite = A_Spawn(OW(spriteNum), TRANSPORTERBEAM);
3721 A_PlaySound(REALITY ? 45 : TELEPORTER, newSprite);
3722 }
3723
3724 if (sprite[OW(spriteNum)].owner != OW(spriteNum))
3725 {
3726 T1(spriteNum) = 13;
3727 actor[OW(spriteNum)].t_data[0] = 13;
3728 }
3729
3730 changespritesect(sectSprite, sprite[OW(spriteNum)].sectnum);
3731 }
3732 }
3733 else
3734 {
3735 sprite[sectSprite].x += (sprite[OW(spriteNum)].x - SX(spriteNum));
3736 sprite[sectSprite].y += (sprite[OW(spriteNum)].y - SY(spriteNum));
3737 sprite[sectSprite].z = sprite[OW(spriteNum)].z + 4096;
3738
3739 actor[sectSprite].bpos = sprite[sectSprite].pos;
3740
3741 changespritesect(sectSprite, sprite[OW(spriteNum)].sectnum);
3742 }
3743 }
3744
3745 break;
3746 } // switch (DYNAMICTILEMAP(sprite[j].picnum))
3747 } // if (doWarp)
3748 } // if (totalclock > actor[j].lasttransport)
3749
3750 break;
3751 } // five cases
3752
3753 } // switch (sprite[j].statnum)
3754 JBOLT:
3755 sectSprite = nextSectSprite;
3756 }
3757 next_sprite:
3758 spriteNum = nextSprite;
3759 }
3760 }
3761
A_FindLocator(int const tag,int const sectNum)3762 static int A_FindLocator(int const tag, int const sectNum)
3763 {
3764 for (bssize_t SPRITES_OF(STAT_LOCATOR, spriteNum))
3765 {
3766 if ((sectNum == -1 || sectNum == SECT(spriteNum)) && tag == SLT(spriteNum))
3767 return spriteNum;
3768 }
3769
3770 return -1;
3771 }
3772
A_PinSectorResetDown(int16_t const sectNum)3773 ACTOR_STATIC int A_PinSectorResetDown(int16_t const sectNum)
3774 {
3775 if (GetAnimationGoal(§or[sectNum].ceilingz) == -1)
3776 {
3777 int const newZ = sector[sectNum].floorz;
3778 SetAnimation(sectNum,§or[sectNum].ceilingz,newZ,64);
3779 return 1;
3780 }
3781 return 0;
3782 }
3783
A_PinSectorResetUp(int16_t const sectNum)3784 ACTOR_STATIC int A_PinSectorResetUp(int16_t const sectNum)
3785 {
3786 if (GetAnimationGoal(§or[sectNum].ceilingz) == -1)
3787 {
3788 int const newZ = sector[nextsectorneighborz(sectNum, sector[sectNum].ceilingz,-1,-1)].ceilingz;
3789 SetAnimation(sectNum,§or[sectNum].ceilingz,newZ,64);
3790 return 1;
3791 }
3792 return 0;
3793 }
3794
A_BallReturn(int16_t const pinSprite)3795 ACTOR_STATIC void A_BallReturn(int16_t const pinSprite)
3796 {
3797 int spriteNum = headspritestat[105];
3798 while (spriteNum >= 0)
3799 {
3800 int const nextSprite = nextspritestat[spriteNum];
3801 if (sprite[spriteNum].picnum == RRTILE281)
3802 if (sprite[pinSprite].sectnum == sprite[spriteNum].sectnum)
3803 {
3804 int otherSprite = headspritestat[105];
3805 while (otherSprite >= 0)
3806 {
3807 int const otherSpriteNext = nextspritestat[otherSprite];
3808 if (sprite[otherSprite].picnum == RRTILE282)
3809 if (sprite[spriteNum].hitag == sprite[otherSprite].hitag)
3810 A_Spawn(otherSprite, BOWLINGBALLSPRITE);
3811 if (sprite[otherSprite].picnum == RRTILE280)
3812 if (sprite[spriteNum].hitag == sprite[otherSprite].hitag)
3813 if (sprite[otherSprite].lotag == 0)
3814 {
3815 sprite[otherSprite].lotag = 100;
3816 sprite[otherSprite].extra++;
3817 A_PinSectorResetDown(sprite[otherSprite].sectnum);
3818 }
3819 otherSprite = otherSpriteNext;
3820 }
3821 }
3822
3823 spriteNum = nextSprite;
3824 }
3825 }
3826
A_CheckPins(int16_t const sectNum)3827 ACTOR_STATIC int A_CheckPins(int16_t const sectNum)
3828 {
3829 uint8_t pins[10];
3830 int pinCount = 0;
3831 int tag;
3832
3833 Bmemset(pins, 0, sizeof(pins));
3834
3835 int spriteNum = headspritesect[sectNum];
3836
3837 while (spriteNum >= 0)
3838 {
3839 if (sprite[spriteNum].picnum == RRTILE3440)
3840 {
3841 pinCount++;
3842 pins[sprite[spriteNum].lotag] = 1;
3843 }
3844 if (sprite[spriteNum].picnum == RRTILE280)
3845 {
3846 tag = sprite[spriteNum].hitag;
3847 }
3848 spriteNum = nextspritesect[spriteNum];
3849 }
3850
3851 if (tag != 0)
3852 {
3853 int const tileNumber = LANEPICS + tag + 1;
3854 tileCopySection(LANEPICS+1, 0, 0, 128, 64, tileNumber, 0, 0);
3855
3856 for (int pin = 0; pin < 10; pin++)
3857 {
3858 if (pins[pin] == 1)
3859 {
3860 int x, y;
3861 switch (pin)
3862 {
3863 case 0:
3864 x = 64;
3865 y = 48;
3866 break;
3867 case 1:
3868 x = 56;
3869 y = 40;
3870 break;
3871 case 2:
3872 x = 72;
3873 y = 40;
3874 break;
3875 case 3:
3876 x = 48;
3877 y = 32;
3878 break;
3879 case 4:
3880 x = 64;
3881 y = 32;
3882 break;
3883 case 5:
3884 x = 80;
3885 y = 32;
3886 break;
3887 case 6:
3888 x = 40;
3889 y = 24;
3890 break;
3891 case 7:
3892 x = 56;
3893 y = 24;
3894 break;
3895 case 8:
3896 x = 72;
3897 y = 24;
3898 break;
3899 case 9:
3900 x = 88;
3901 y = 24;
3902 break;
3903 }
3904 tileCopySection(LANEPICS, 0, 0, 8, 8, tileNumber, x - 4, y - 10);
3905 }
3906 }
3907 }
3908
3909 return pinCount;
3910 }
3911
A_ResetPins(int16_t sect)3912 ACTOR_STATIC void A_ResetPins(int16_t sect)
3913 {
3914 int step = 0;
3915 int tag = 0;
3916 int spriteNum = headspritesect[sect];
3917 while (spriteNum >= 0)
3918 {
3919 if (spriteNum > MAXSECTORSV7 || step > 1000)
3920 break;
3921 int const nextSprite = headspritesect[spriteNum];
3922 if (sprite[spriteNum].picnum == RRTILE3440)
3923 deletesprite(spriteNum);
3924 spriteNum = nextSprite;
3925 step++;
3926 }
3927 spriteNum = headspritesect[sect];
3928 while (spriteNum >= 0)
3929 {
3930 int const nextSprite = nextspritesect[spriteNum];
3931 if (sprite[spriteNum].picnum == RRTILE283)
3932 {
3933 int const newSprite = A_Spawn(spriteNum, RRTILE3440);
3934 sprite[newSprite].lotag = sprite[spriteNum].lotag;
3935 krand2();
3936 sprite[newSprite].clipdist = 48;
3937 sprite[newSprite].ang -= ((krand2()&32)-(krand2()&64))&2047;
3938 }
3939 if (sprite[spriteNum].picnum == RRTILE280)
3940 tag = sprite[spriteNum].hitag;
3941 spriteNum = nextSprite;
3942 }
3943 if (tag != 0)
3944 {
3945 int const tileNumber = LANEPICS + tag + 1;
3946 tileCopySection(LANEPICS+1, 0, 0, 128, 64, tileNumber, 0, 0);
3947
3948 for (int pin = 0; pin < 10; pin++)
3949 {
3950 int x, y;
3951 switch (pin)
3952 {
3953 case 0:
3954 x = 64;
3955 y = 48;
3956 break;
3957 case 1:
3958 x = 56;
3959 y = 40;
3960 break;
3961 case 2:
3962 x = 72;
3963 y = 40;
3964 break;
3965 case 3:
3966 x = 48;
3967 y = 32;
3968 break;
3969 case 4:
3970 x = 64;
3971 y = 32;
3972 break;
3973 case 5:
3974 x = 80;
3975 y = 32;
3976 break;
3977 case 6:
3978 x = 40;
3979 y = 24;
3980 break;
3981 case 7:
3982 x = 56;
3983 y = 24;
3984 break;
3985 case 8:
3986 x = 72;
3987 y = 24;
3988 break;
3989 case 9:
3990 x = 88;
3991 y = 24;
3992 break;
3993 }
3994 tileCopySection(LANEPICS, 0, 0, 8, 8, tileNumber, x - 4, y - 10);
3995 }
3996 }
3997 }
3998
A_ResetLanePics(void)3999 void A_ResetLanePics(void)
4000 {
4001 for (int tag = 1; tag <= 4; tag++)
4002 {
4003 int const tileNumber = LANEPICS + tag + 1;
4004 tileCopySection(LANEPICS + 1, 0, 0, 128, 64, tileNumber, 0, 0);
4005
4006 for (int pin = 0; pin < 10; pin++)
4007 {
4008 int x, y;
4009 switch (pin)
4010 {
4011 case 0:
4012 x = 64;
4013 y = 48;
4014 break;
4015 case 1:
4016 x = 56;
4017 y = 40;
4018 break;
4019 case 2:
4020 x = 72;
4021 y = 40;
4022 break;
4023 case 3:
4024 x = 48;
4025 y = 32;
4026 break;
4027 case 4:
4028 x = 64;
4029 y = 32;
4030 break;
4031 case 5:
4032 x = 80;
4033 y = 32;
4034 break;
4035 case 6:
4036 x = 40;
4037 y = 24;
4038 break;
4039 case 7:
4040 x = 56;
4041 y = 24;
4042 break;
4043 case 8:
4044 x = 72;
4045 y = 24;
4046 break;
4047 case 9:
4048 x = 88;
4049 y = 24;
4050 break;
4051 }
4052 tileCopySection(LANEPICS, 0, 0, 8, 8, tileNumber, x - 4, y - 10);
4053 }
4054 }
4055 }
4056
A_ManhattanDistance(int s1,int s2)4057 static inline int A_ManhattanDistance(int s1, int s2)
4058 {
4059 int dx = klabs(sprite[s1].x - sprite[s2].x);
4060 int dy = klabs(sprite[s1].y - sprite[s2].y);
4061 int dz = klabs(sprite[s1].z - sprite[s2].z);
4062 return dx + dy + (dz >> 4);
4063 }
4064
G_MoveActors(void)4065 ACTOR_STATIC void G_MoveActors(void)
4066 {
4067 extern char g_demo_legacy;
4068 int spriteNum;
4069
4070 if (!DEER && g_jailDoorCnt)
4071 G_DoJailDoor();
4072
4073 if (!DEER && g_mineCartCnt)
4074 G_MoveMineCart();
4075
4076 int bBoom = 0;
4077
4078 if (!DEER && RRRA)
4079 {
4080 int spriteNum = headspritestat[117];
4081 while (spriteNum >= 0)
4082 {
4083 int const nextSprite = nextspritestat[spriteNum];
4084 if (sprite[spriteNum].hitag > 2)
4085 sprite[spriteNum].hitag = 0;
4086 if ((sprite[spriteNum].picnum == RRTILE8488 || sprite[spriteNum].picnum == RRTILE8490) && sprite[spriteNum].hitag != 2)
4087 {
4088 sprite[spriteNum].hitag = 2;
4089 sprite[spriteNum].extra = -100;
4090 }
4091 if (sprite[spriteNum].hitag == 0)
4092 {
4093 sprite[spriteNum].extra++;
4094 if (sprite[spriteNum].extra >= 30)
4095 sprite[spriteNum].hitag = 1;
4096 }
4097 else if (sprite[spriteNum].hitag == 1)
4098 {
4099 sprite[spriteNum].extra--;
4100 if (sprite[spriteNum].extra <= -30)
4101 sprite[spriteNum].hitag = 0;
4102 }
4103 else if (sprite[spriteNum].hitag == 2)
4104 {
4105 sprite[spriteNum].extra--;
4106 if (sprite[spriteNum].extra <= -104)
4107 {
4108 A_Spawn(spriteNum, sprite[spriteNum].lotag);
4109 deletesprite(spriteNum);
4110 }
4111 }
4112
4113 vec3_t const vect = { 0, 0, sprite[spriteNum].extra * 2};
4114
4115 A_MoveSprite(spriteNum, &vect, CLIPMASK0);
4116 spriteNum = nextSprite;
4117 }
4118
4119 spriteNum = headspritestat[118];
4120 while (spriteNum >= 0)
4121 {
4122 int const nextSprite = nextspritestat[spriteNum];
4123 if (sprite[spriteNum].hitag > 1)
4124 sprite[spriteNum].hitag = 0;
4125 if (sprite[spriteNum].hitag == 0)
4126 {
4127 sprite[spriteNum].extra++;
4128 if (sprite[spriteNum].extra >= 20)
4129 sprite[spriteNum].hitag = 1;
4130 }
4131 else if (sprite[spriteNum].hitag == 1)
4132 {
4133 sprite[spriteNum].extra--;
4134 if (sprite[spriteNum].extra <= -20)
4135 sprite[spriteNum].hitag = 0;
4136 }
4137
4138 vec3_t const vect = { 0, 0, sprite[spriteNum].extra };
4139
4140 A_MoveSprite(spriteNum, &vect, CLIPMASK0);
4141 spriteNum = nextSprite;
4142 }
4143
4144 if (g_player[myconnectindex].ps->level_end_timer > 0)
4145 {
4146 if (--g_player[myconnectindex].ps->level_end_timer == 0)
4147 {
4148 for (bssize_t TRAVERSE_CONNECT(playerNum))
4149 g_player[playerNum].ps->gm = MODE_EOL;
4150 ud.eog = 1;
4151 ud.level_number++;
4152 if (ud.level_number > 6)
4153 ud.level_number = 0;
4154 ud.m_level_number = ud.level_number;
4155 }
4156 }
4157
4158 if (g_changeEnemySize > 0)
4159 {
4160 for (bssize_t enemySprite = 0; enemySprite < MAXSPRITES; enemySprite++)
4161 {
4162 switch (DYNAMICTILEMAP(sprite[enemySprite].picnum))
4163 {
4164 case BILLYCOCK__STATICRR:
4165 case BILLYRAY__STATICRR:
4166 case BILLYRAYSTAYPUT__STATICRR:
4167 case BRAYSNIPER__STATICRR:
4168 case DOGRUN__STATICRR:
4169 case LTH__STATICRR:
4170 case HULKJUMP__STATICRR:
4171 case HULK__STATICRR:
4172 case HULKSTAYPUT__STATICRR:
4173 case HEN__STATICRR:
4174 case DRONE__STATIC:
4175 case PIG__STATICRR:
4176 case MINION__STATICRR:
4177 case MINIONSTAYPUT__STATICRR:
4178 case UFO1__STATICRR:
4179 case UFO2__STATICRR:
4180 case UFO3__STATICRR:
4181 case UFO4__STATICRR:
4182 case UFO5__STATICRR:
4183 case COOT__STATICRR:
4184 case COOTSTAYPUT__STATICRR:
4185 case VIXEN__STATICRR:
4186 case BIKERB__STATICRR:
4187 case BIKERBV2__STATICRR:
4188 case BIKER__STATICRR:
4189 case MAKEOUT__STATICRR:
4190 case CHEERB__STATICRR:
4191 case CHEER__STATICRR:
4192 case CHEERSTAYPUT__STATICRR:
4193 case COOTPLAY__STATICRR:
4194 case BILLYPLAY__STATICRR:
4195 case MINIONBOAT__STATICRR:
4196 case HULKBOAT__STATICRR:
4197 case CHEERBOAT__STATICRR:
4198 case RABBIT__STATICRR:
4199 case MAMA__STATICRR:
4200 if (g_changeEnemySize == 3)
4201 {
4202 sprite[enemySprite].xrepeat = sprite[enemySprite].xrepeat << 1;
4203 sprite[enemySprite].yrepeat = sprite[enemySprite].yrepeat << 1;
4204 sprite[enemySprite].clipdist = mulscale7(sprite[enemySprite].xrepeat, tilesiz[sprite[enemySprite].picnum].x);
4205 }
4206 else if (g_changeEnemySize == 2)
4207 {
4208 sprite[enemySprite].xrepeat = sprite[enemySprite].xrepeat >> 1;
4209 sprite[enemySprite].yrepeat = sprite[enemySprite].yrepeat >> 1;
4210 sprite[enemySprite].clipdist = mulscale7(sprite[enemySprite].xrepeat, tilesiz[sprite[enemySprite].picnum].x);
4211 }
4212 break;
4213 }
4214 }
4215 g_changeEnemySize = 0;
4216 }
4217
4218 spriteNum = headspritestat[121];
4219 while (spriteNum >= 0)
4220 {
4221 int const nextSprite = nextspritestat[spriteNum];
4222 sprite[spriteNum].extra++;
4223 if (sprite[spriteNum].extra < 100)
4224 {
4225 if (sprite[spriteNum].extra == 90)
4226 {
4227 sprite[spriteNum].picnum--;
4228 if (sprite[spriteNum].picnum < PIG + 7)
4229 sprite[spriteNum].picnum = PIG + 7;
4230 sprite[spriteNum].extra = 1;
4231 }
4232
4233 vec3_t const vect = { 0, 0, -300 };
4234 A_MoveSprite(spriteNum, &vect, CLIPMASK0);
4235 if (sector[sprite[spriteNum].sectnum].ceilingz + (4 << 8) > sprite[spriteNum].z)
4236 {
4237 sprite[spriteNum].picnum = 0;
4238 sprite[spriteNum].extra = 100;
4239 }
4240 }
4241 else if (sprite[spriteNum].extra == 200)
4242 {
4243 vec3_t const pos = { sprite[spriteNum].x, sprite[spriteNum].y, sector[sprite[spriteNum].sectnum].floorz - 10 };
4244 setsprite(spriteNum, &pos);
4245 sprite[spriteNum].extra = 1;
4246 sprite[spriteNum].picnum = PIG + 11;
4247 A_Spawn(spriteNum, TRANSPORTERSTAR);
4248 }
4249 spriteNum = nextSprite;
4250 }
4251
4252 spriteNum = headspritestat[119];
4253 while (spriteNum >= 0)
4254 {
4255 int const nextSprite = nextspritestat[spriteNum];
4256 if (sprite[spriteNum].hitag > 0)
4257 {
4258 if (sprite[spriteNum].extra == 0)
4259 {
4260 sprite[spriteNum].hitag--;
4261 sprite[spriteNum].extra = 150;
4262 A_Spawn(spriteNum, RABBIT);
4263 }
4264 else
4265 sprite[spriteNum].extra--;
4266 }
4267 spriteNum = nextSprite;
4268 }
4269 spriteNum = headspritestat[116];
4270 while (spriteNum >= 0)
4271 {
4272 int const nextSprite = nextspritestat[spriteNum];
4273 if (sprite[spriteNum].extra)
4274 {
4275 if (sprite[spriteNum].extra == sprite[spriteNum].lotag)
4276 S_PlaySound(183);
4277 sprite[spriteNum].extra--;
4278 vec3_t const vect = {
4279 (sprite[spriteNum].hitag*sintable[(sprite[spriteNum].ang + 512) & 2047]) >> 14,
4280 (sprite[spriteNum].hitag*sintable[sprite[spriteNum].ang & 2047]) >> 14,
4281 sprite[spriteNum].hitag << 1
4282 };
4283 if (A_MoveSprite(spriteNum, &vect, CLIPMASK0) > 0)
4284 {
4285 A_PlaySound(PIPEBOMB_EXPLODE, spriteNum);
4286 deletesprite(spriteNum);
4287 }
4288 if (sprite[spriteNum].extra == 0)
4289 {
4290 S_PlaySound(215);
4291 deletesprite(spriteNum);
4292 g_earthquakeTime = 32;
4293 P_PalFrom(g_player[myconnectindex].ps, 48, 32, 32, 32);
4294 }
4295 }
4296 spriteNum = nextSprite;
4297 }
4298
4299 spriteNum = headspritestat[115];
4300 while (spriteNum >= 0)
4301 {
4302 int const nextSprite = nextspritestat[spriteNum];
4303 if (sprite[spriteNum].extra)
4304 {
4305 if (sprite[spriteNum].picnum != RRTILE8162)
4306 sprite[spriteNum].picnum = RRTILE8162;
4307 sprite[spriteNum].extra--;
4308 if (sprite[spriteNum].extra == 0)
4309 {
4310 int const fortune = krand2()&127;
4311 if (fortune < 96)
4312 {
4313 sprite[spriteNum].picnum = RRTILE8162 + 3;
4314 }
4315 else if (fortune < 112)
4316 {
4317 if (g_slotWin & 1)
4318 {
4319 sprite[spriteNum].picnum = RRTILE8162 + 3;
4320 }
4321 else
4322 {
4323 sprite[spriteNum].picnum = RRTILE8162 + 2;
4324 A_Spawn(spriteNum, BATTERYAMMO);
4325 g_slotWin |= 1;
4326 A_PlaySound(52, spriteNum);
4327 }
4328 }
4329 else if (fortune < 120)
4330 {
4331 if (g_slotWin & 2)
4332 {
4333 sprite[spriteNum].picnum = RRTILE8162 + 3;
4334 }
4335 else
4336 {
4337 sprite[spriteNum].picnum = RRTILE8162 + 6;
4338 A_Spawn(spriteNum, HEAVYHBOMB);
4339 g_slotWin |= 2;
4340 A_PlaySound(52, spriteNum);
4341 }
4342 }
4343 else if (fortune < 126)
4344 {
4345 if (g_slotWin & 4)
4346 {
4347 sprite[spriteNum].picnum = RRTILE8162 + 3;
4348 }
4349 else
4350 {
4351 sprite[spriteNum].picnum = RRTILE8162 + 5;
4352 A_Spawn(spriteNum, SIXPAK);
4353 g_slotWin |= 4;
4354 A_PlaySound(52, spriteNum);
4355 }
4356 }
4357 else
4358 {
4359 if (g_slotWin & 8)
4360 {
4361 sprite[spriteNum].picnum = RRTILE8162 + 3;
4362 }
4363 else
4364 {
4365 sprite[spriteNum].picnum = RRTILE8162 + 4;
4366 A_Spawn(spriteNum, ATOMICHEALTH);
4367 g_slotWin |= 8;
4368 A_PlaySound(52, spriteNum);
4369 }
4370 }
4371 }
4372 }
4373 spriteNum = nextSprite;
4374 }
4375
4376 spriteNum = headspritestat[122];
4377 while (spriteNum >= 0)
4378 {
4379 int const nextSprite = nextspritestat[spriteNum];
4380 if (sprite[spriteNum].extra)
4381 {
4382 if (sprite[spriteNum].picnum != RRTILE8589)
4383 sprite[spriteNum].picnum = RRTILE8589;
4384 sprite[spriteNum].extra--;
4385 if (sprite[spriteNum].extra == 0)
4386 {
4387 int const fortune = krand2()&127;
4388 if (fortune < 96)
4389 {
4390 sprite[spriteNum].picnum = RRTILE8589 + 4;
4391 }
4392 else if (fortune < 112)
4393 {
4394 if (g_slotWin & 1)
4395 {
4396 sprite[spriteNum].picnum = RRTILE8589 + 4;
4397 }
4398 else
4399 {
4400 sprite[spriteNum].picnum = RRTILE8589 + 5;
4401 A_Spawn(spriteNum, BATTERYAMMO);
4402 g_slotWin |= 1;
4403 A_PlaySound(342, spriteNum);
4404 }
4405 }
4406 else if (fortune < 120)
4407 {
4408 if (g_slotWin & 2)
4409 {
4410 sprite[spriteNum].picnum = RRTILE8589 + 4;
4411 }
4412 else
4413 {
4414 sprite[spriteNum].picnum = RRTILE8589 + 6;
4415 A_Spawn(spriteNum, HEAVYHBOMB);
4416 g_slotWin |= 2;
4417 A_PlaySound(342, spriteNum);
4418 }
4419 }
4420 else if (fortune < 126)
4421 {
4422 if (g_slotWin & 4)
4423 {
4424 sprite[spriteNum].picnum = RRTILE8589 + 4;
4425 }
4426 else
4427 {
4428 sprite[spriteNum].picnum = RRTILE8589 + 2;
4429 A_Spawn(spriteNum, SIXPAK);
4430 g_slotWin |= 4;
4431 A_PlaySound(342, spriteNum);
4432 }
4433 }
4434 else
4435 {
4436 if (g_slotWin & 8)
4437 {
4438 sprite[spriteNum].picnum = RRTILE8589 + 4;
4439 }
4440 else
4441 {
4442 sprite[spriteNum].picnum = RRTILE8589 + 3;
4443 A_Spawn(spriteNum, ATOMICHEALTH);
4444 g_slotWin |= 8;
4445 A_PlaySound(342, spriteNum);
4446 }
4447 }
4448 }
4449 }
4450 spriteNum = nextSprite;
4451 }
4452
4453 spriteNum = headspritestat[123];
4454 while (spriteNum >= 0)
4455 {
4456 int const nextSprite = nextspritestat[spriteNum];
4457 if (sprite[spriteNum].lotag == 5)
4458 if (!S_CheckSoundPlaying(spriteNum, 330))
4459 A_PlaySound(330, spriteNum);
4460 spriteNum = nextSprite;
4461 }
4462 }
4463
4464 if (!DEER && RR)
4465 {
4466 spriteNum = headspritestat[107];
4467 while (spriteNum >= 0)
4468 {
4469 int const nextSprite = nextspritestat[spriteNum];
4470
4471 if (sprite[spriteNum].hitag == 100)
4472 {
4473 sprite[spriteNum].z += (4 << 8);
4474 if (sprite[spriteNum].z >= sector[sprite[spriteNum].sectnum].floorz + 15168)
4475 sprite[spriteNum].z = sector[sprite[spriteNum].sectnum].floorz + 15168;
4476 }
4477
4478 if (sprite[spriteNum].picnum == LUMBERBLADE)
4479 {
4480 sprite[spriteNum].extra++;
4481 if (sprite[spriteNum].extra == 192)
4482 {
4483 sprite[spriteNum].hitag = 0;
4484 sprite[spriteNum].z = sector[sprite[spriteNum].sectnum].floorz - 15168;
4485 sprite[spriteNum].extra = 0;
4486 sprite[spriteNum].picnum = RRTILE3410;
4487 int otherSprite = headspritestat[0];
4488 while (otherSprite >= 0)
4489 {
4490 int const nextOtherSprite = nextspritestat[otherSprite];
4491 if (sprite[otherSprite].picnum == DIPSWITCH3 + 1)
4492 if (sprite[otherSprite].hitag == 999)
4493 sprite[otherSprite].picnum = DIPSWITCH3;
4494 otherSprite = nextOtherSprite;
4495 }
4496 }
4497 }
4498 spriteNum = nextSprite;
4499 }
4500
4501 if (g_chickenPlant)
4502 {
4503 spriteNum = headspritestat[106];
4504 while (spriteNum >= 0)
4505 {
4506 int const nextSprite = nextspritestat[spriteNum];
4507 switch (DYNAMICTILEMAP(sprite[spriteNum].picnum))
4508 {
4509 case RRTILE285__STATICRR:
4510 sprite[spriteNum].lotag--;
4511 if (sprite[spriteNum].lotag < 0)
4512 {
4513 int const newSprite = A_Spawn(spriteNum, RRTILE3190);
4514 sprite[newSprite].ang = sprite[spriteNum].ang;
4515 sprite[spriteNum].lotag = 128;
4516 }
4517 break;
4518 case RRTILE286__STATICRR:
4519 sprite[spriteNum].lotag--;
4520 if (sprite[spriteNum].lotag < 0)
4521 {
4522 int const newSprite = A_Spawn(spriteNum, RRTILE3192);
4523 sprite[newSprite].ang = sprite[spriteNum].ang;
4524 sprite[spriteNum].lotag = 256;
4525 }
4526 break;
4527 case RRTILE287__STATICRR:
4528 sprite[spriteNum].lotag--;
4529 if (sprite[spriteNum].lotag < 0)
4530 {
4531 A_SpawnMultiple(spriteNum, MONEY, (krand2()&3)+4);
4532 sprite[spriteNum].lotag = 84;
4533 }
4534 break;
4535 case RRTILE288__STATICRR:
4536 sprite[spriteNum].lotag--;
4537 if (sprite[spriteNum].lotag < 0)
4538 {
4539 int const newSprite = A_Spawn(spriteNum, RRTILE3132);
4540 sprite[spriteNum].lotag = 96;
4541 if (!RRRA)
4542 A_PlaySound(472, newSprite);
4543 }
4544 break;
4545 case RRTILE289__STATICRR:
4546 sprite[spriteNum].lotag--;
4547 if (sprite[spriteNum].lotag < 0)
4548 {
4549 int const newSprite = A_Spawn(spriteNum, RRTILE3120);
4550 sprite[newSprite].ang = sprite[spriteNum].ang;
4551 sprite[spriteNum].lotag = 448;
4552 }
4553 break;
4554 case RRTILE290__STATICRR:
4555 sprite[spriteNum].lotag--;
4556 if (sprite[spriteNum].lotag < 0)
4557 {
4558 int const newSprite = A_Spawn(spriteNum, RRTILE3122);
4559 sprite[newSprite].ang = sprite[spriteNum].ang;
4560 sprite[spriteNum].lotag = 64;
4561 }
4562 break;
4563 case RRTILE291__STATICRR:
4564 sprite[spriteNum].lotag--;
4565 if (sprite[spriteNum].lotag < 0)
4566 {
4567 int const newSprite = A_Spawn(spriteNum, RRTILE3123);
4568 sprite[newSprite].ang = sprite[spriteNum].ang;
4569 sprite[spriteNum].lotag = 512;
4570 }
4571 break;
4572 case RRTILE292__STATICRR:
4573 sprite[spriteNum].lotag--;
4574 if (sprite[spriteNum].lotag < 0)
4575 {
4576 int const newSprite = A_Spawn(spriteNum, RRTILE3124);
4577 sprite[newSprite].ang = sprite[spriteNum].ang;
4578 sprite[spriteNum].lotag = 224;
4579 }
4580 break;
4581 case RRTILE293__STATICRR:
4582 sprite[spriteNum].lotag--;
4583 if (sprite[spriteNum].lotag < 0)
4584 {
4585 A_DoGuts(spriteNum, JIBS1, 1);
4586 A_DoGuts(spriteNum, JIBS2, 1);
4587 A_DoGuts(spriteNum, JIBS3, 1);
4588 A_DoGuts(spriteNum, JIBS4, 1);
4589 sprite[spriteNum].lotag = 256;
4590 }
4591 break;
4592 }
4593 spriteNum = nextSprite;
4594 }
4595 }
4596
4597 spriteNum = headspritestat[105];
4598 while (spriteNum >= 0)
4599 {
4600 int const nextSprite = nextspritestat[spriteNum];
4601 if (sprite[spriteNum].picnum == RRTILE280)
4602 if (sprite[spriteNum].lotag == 100)
4603 {
4604 if (A_PinSectorResetUp(SECT(spriteNum)))
4605 {
4606 sprite[spriteNum].lotag = 0;
4607 if (sprite[spriteNum].extra == 1)
4608 {
4609 if (!A_CheckPins(SECT(spriteNum)))
4610 {
4611 sprite[spriteNum].extra = 2;
4612 }
4613 }
4614 if (sprite[spriteNum].extra == 2)
4615 {
4616 sprite[spriteNum].extra = 0;
4617 A_ResetPins(SECT(spriteNum));
4618 }
4619 }
4620 }
4621 spriteNum = nextSprite;
4622 }
4623
4624 spriteNum = headspritestat[108];
4625 while (spriteNum >= 0)
4626 {
4627 int const nextSprite = nextspritestat[spriteNum];
4628
4629 spritetype *const pSprite= &sprite[spriteNum];
4630 if (pSprite->picnum == RRTILE296)
4631 {
4632 int playerDist;
4633 DukePlayer_t *const pPlayer = g_player[A_FindPlayer(pSprite, &playerDist)].ps;
4634
4635 if (playerDist < 2047)
4636 {
4637 int otherSprite = headspritestat[108];
4638 while (otherSprite >= 0)
4639 {
4640 int const nextOtherSprite = nextspritestat[otherSprite];
4641 if (sprite[otherSprite].picnum == RRTILE297)
4642 {
4643 pPlayer->q16ang = F16(sprite[otherSprite].ang);
4644 pPlayer->pos = *(vec3_t*)&sprite[otherSprite];
4645 pPlayer->pos.z -= (36<<8);
4646
4647 pPlayer->opos = pPlayer->pos;
4648 pPlayer->bobpos = *(vec2_t*)&pPlayer->pos;
4649
4650 changespritesect(pPlayer->i, sprite[otherSprite].sectnum);
4651 pPlayer->cursectnum = sprite[otherSprite].sectnum;
4652
4653 A_PlaySound(TELEPORTER, otherSprite);
4654
4655 A_DeleteSprite(otherSprite);
4656 }
4657 otherSprite = nextOtherSprite;
4658 }
4659 }
4660 }
4661 spriteNum = nextSprite;
4662 }
4663 }
4664
4665 spriteNum = headspritestat[STAT_ACTOR];
4666
4667 while (spriteNum >= 0)
4668 {
4669 int const nextSprite = nextspritestat[spriteNum];
4670 spritetype *const pSprite = &sprite[spriteNum];
4671 int const sectNum = pSprite->sectnum;
4672 int32_t *const pData = actor[spriteNum].t_data;
4673 int deleteAfterExecute = 0;
4674
4675 int switchPic;
4676
4677 if (pSprite->xrepeat == 0 || sectNum < 0 || sectNum >= MAXSECTORS)
4678 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4679
4680 Bmemcpy(&actor[spriteNum].bpos, pSprite, sizeof(vec3_t));
4681
4682 switchPic = pSprite->picnum;
4683
4684 if (!RR && pSprite->picnum > GREENSLIME && pSprite->picnum <= GREENSLIME+7)
4685 switchPic = GREENSLIME;
4686
4687 if (RR && (switchPic == RRTILE3440 + 1 || switchPic == HENSTAND + 1))
4688 switchPic--;
4689
4690
4691 if (!DEER)
4692 switch (DYNAMICTILEMAP(switchPic))
4693 {
4694 case DUCK__STATIC:
4695 case TARGET__STATIC:
4696 if (RR) break;
4697 if (pSprite->cstat&32)
4698 {
4699 pData[0]++;
4700 if (pData[0] > 60)
4701 {
4702 pData[0] = 0;
4703 pSprite->cstat = 128+257+16;
4704 pSprite->extra = 1;
4705 }
4706 }
4707 else
4708 {
4709 if (A_IncurDamage(spriteNum) >= 0)
4710 {
4711 int doEffects = 1;
4712
4713 pSprite->cstat = 32+128;
4714
4715 for (bssize_t SPRITES_OF(STAT_ACTOR, actorNum))
4716 {
4717 if ((sprite[actorNum].lotag == pSprite->lotag && sprite[actorNum].picnum == pSprite->picnum)
4718 && ((sprite[actorNum].hitag != 0) ^ ((sprite[actorNum].cstat & 32) != 0)))
4719 {
4720 doEffects = 0;
4721 break;
4722 }
4723 }
4724
4725 if (doEffects == 1)
4726 {
4727 G_OperateActivators(pSprite->lotag, -1);
4728 G_OperateForceFields(spriteNum, pSprite->lotag);
4729 G_OperateMasterSwitches(pSprite->lotag);
4730 }
4731 }
4732 }
4733 goto next_sprite;
4734
4735 case RESPAWNMARKERRED__STATIC:
4736 case RESPAWNMARKERYELLOW__STATIC:
4737 case RESPAWNMARKERGREEN__STATIC:
4738 if (++T1(spriteNum) > g_itemRespawnTime)
4739 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4740
4741 if (T1(spriteNum) >= (g_itemRespawnTime>>1) && T1(spriteNum) < ((g_itemRespawnTime>>1)+(g_itemRespawnTime>>2)))
4742 PN(spriteNum) = RESPAWNMARKERYELLOW;
4743 else if (T1(spriteNum) > ((g_itemRespawnTime>>1)+(g_itemRespawnTime>>2)))
4744 PN(spriteNum) = RESPAWNMARKERGREEN;
4745
4746 A_Fall(spriteNum);
4747 break;
4748
4749 case HELECOPT__STATIC:
4750 case DUKECAR__STATIC:
4751 if (RR) break;
4752 if (!REALITY)
4753 pSprite->z += pSprite->zvel;
4754 pData[0]++;
4755
4756 if (pData[0] == 4)
4757 A_PlaySound(REALITY ? 186 : WAR_AMBIENCE2,spriteNum);
4758
4759 if (pData[0] > (GAMETICSPERSEC*8))
4760 {
4761 g_earthquakeTime = 16;
4762 S_PlaySound(REALITY ? 8 : RPG_EXPLODE);
4763
4764 for (bssize_t j = 0; j < 32; j++)
4765 RANDOMSCRAP(pSprite, spriteNum);
4766
4767 if (REALITY)
4768 {
4769 A_Spawn(spriteNum,EXPLOSION2);
4770 RT_AddExplosion(pSprite->x>>1, pSprite->y>>1, pSprite->z>>5, 7);
4771 }
4772
4773 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4774 }
4775 else if ((pData[0]&3) == 0)
4776 A_Spawn(spriteNum,EXPLOSION2);
4777
4778 A_SetSprite(spriteNum,CLIPMASK0);
4779 break;
4780
4781 case RAT__STATIC:
4782 A_Fall(spriteNum);
4783 if (A_SetSprite(spriteNum, CLIPMASK0))
4784 {
4785 if (!RRRA && (krand2()&255) < 3) A_PlaySound(REALITY ? 198 : RATTY,spriteNum);
4786 pSprite->ang += (krand2()&31)-15+(sintable[(pData[0]<<8)&2047]>>11);
4787 }
4788 else
4789 {
4790 T1(spriteNum)++;
4791 if (T1(spriteNum) > 1)
4792 {
4793 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4794 }
4795 else pSprite->ang = (krand2()&2047);
4796 }
4797 if (pSprite->xvel < 128)
4798 pSprite->xvel+=2;
4799 pSprite->ang += (krand2()&3)-6;
4800 break;
4801
4802 case RRTILE3190__STATICRR:
4803 case RRTILE3191__STATICRR:
4804 case RRTILE3192__STATICRR:
4805 {
4806 if (!g_chickenPlant) DELETE_SPRITE_AND_CONTINUE(spriteNum);
4807 if (sector[SECT(spriteNum)].lotag == 903)
4808 A_Fall(spriteNum);
4809
4810 vec3_t const vect = {
4811 (pSprite->xvel*(sintable[(pSprite->ang + 512) & 2047])) >> 14,
4812 (pSprite->xvel*(sintable[pSprite->ang & 2047])) >> 14,
4813 pSprite->zvel
4814 };
4815 int const moveSprite = A_MoveSprite(spriteNum, &vect, CLIPMASK0);
4816 switch (sector[SECT(spriteNum)].lotag)
4817 {
4818 case 901:
4819 sprite[spriteNum].picnum = RRTILE3191;
4820 break;
4821 case 902:
4822 sprite[spriteNum].picnum = RRTILE3192;
4823 break;
4824 case 903:
4825 if (SZ(spriteNum) >= sector[SECT(spriteNum)].floorz - ZOFFSET3) { DELETE_SPRITE_AND_CONTINUE(spriteNum); }
4826 break;
4827 case 904:
4828 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4829 break;
4830 }
4831 if (moveSprite & 49152)
4832 {
4833 if ((moveSprite & 49152) == 32768) { DELETE_SPRITE_AND_CONTINUE(spriteNum); }
4834 else if ((moveSprite & 49152) == 49152) { DELETE_SPRITE_AND_CONTINUE(spriteNum); }
4835 }
4836 break;
4837 }
4838
4839 case RRTILE3120__STATICRR:
4840 case RRTILE3122__STATICRR:
4841 case RRTILE3123__STATICRR:
4842 case RRTILE3124__STATICRR:
4843 {
4844 if (!g_chickenPlant) DELETE_SPRITE_AND_CONTINUE(spriteNum);
4845 A_Fall(spriteNum);
4846
4847 vec3_t const vect = {
4848 (pSprite->xvel*(sintable[(pSprite->ang + 512) & 2047])) >> 14,
4849 (pSprite->xvel*(sintable[pSprite->ang & 2047])) >> 14,
4850 pSprite->zvel
4851 };
4852 int const moveSprite = A_MoveSprite(spriteNum, &vect, CLIPMASK0);
4853 if (moveSprite & 49152)
4854 {
4855 if ((moveSprite & 49152) == 32768) { DELETE_SPRITE_AND_CONTINUE(spriteNum); }
4856 else if ((moveSprite & 49152) == 49152) { DELETE_SPRITE_AND_CONTINUE(spriteNum); }
4857 }
4858 if (sector[pSprite->sectnum].lotag == 903)
4859 {
4860 if (SZ(spriteNum) >= sector[SECT(spriteNum)].floorz - (4 << 8))
4861 {
4862 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4863 }
4864 }
4865 else if (sector[pSprite->sectnum].lotag == 904)
4866 {
4867 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4868 }
4869 break;
4870 }
4871
4872 case RRTILE3132__STATICRR:
4873 {
4874 if (!g_chickenPlant) DELETE_SPRITE_AND_CONTINUE(spriteNum);
4875 A_Fall(spriteNum);
4876
4877 vec3_t const vect = {
4878 (pSprite->xvel*(sintable[(pSprite->ang + 512) & 2047])) >> 14,
4879 (pSprite->xvel*(sintable[pSprite->ang & 2047])) >> 14,
4880 pSprite->zvel
4881 };
4882 A_MoveSprite(spriteNum, &vect, CLIPMASK0);
4883 if (pSprite->z >= sector[pSprite->sectnum].floorz - (8 << 8))
4884 {
4885 if (sector[pSprite->sectnum].lotag == 1)
4886 {
4887 int const newSprite = A_Spawn(spriteNum, WATERSPLASH2);
4888 sprite[newSprite].z = sector[sprite[newSprite].sectnum].floorz;
4889 }
4890 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4891 }
4892 break;
4893 }
4894
4895 case BOWLINGBALL__STATICRR:
4896 if (pSprite->xvel)
4897 {
4898 if (!A_CheckSoundPlaying(spriteNum, 356))
4899 A_PlaySound(356, spriteNum);
4900 }
4901 else
4902 {
4903 A_Spawn(spriteNum, BOWLINGBALLSPRITE);
4904 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4905 }
4906 if (sector[pSprite->sectnum].lotag == 900)
4907 {
4908 S_StopEnvSound(356, spriteNum);
4909 }
4910 fallthrough__;
4911 case RRTILE3440__STATICRR:
4912 case HENSTAND__STATICRR:
4913 if (pSprite->picnum == HENSTAND || pSprite->picnum == HENSTAND + 1)
4914 {
4915 if (--pSprite->lotag == 0)
4916 {
4917 A_Spawn(spriteNum, HEN);
4918 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4919 }
4920 }
4921 if (sector[pSprite->sectnum].lotag == 900)
4922 pSprite->xvel = 0;
4923 if (pSprite->xvel)
4924 {
4925 A_Fall(spriteNum);
4926
4927 vec3_t const vect = {
4928 (pSprite->xvel*(sintable[(pSprite->ang + 512) & 2047])) >> 14,
4929 (pSprite->xvel*(sintable[pSprite->ang & 2047])) >> 14,
4930 pSprite->zvel
4931 };
4932 int moveSprite = A_MoveSprite(spriteNum, &vect, CLIPMASK0);
4933 if (moveSprite & 49152)
4934 {
4935 if ((moveSprite & 49152) == 32768)
4936 {
4937 moveSprite &= (MAXWALLS - 1);
4938 Proj_BounceOffWall(pSprite, moveSprite);
4939 }
4940 else if ((moveSprite & 49152) == 49152)
4941 {
4942 moveSprite &= (MAXSPRITES - 1);
4943 A_DamageObject(spriteNum, moveSprite);
4944 if (sprite[moveSprite].picnum == HEN)
4945 {
4946 int const newSprite = A_Spawn(moveSprite, HENSTAND);
4947 A_DeleteSprite(moveSprite);
4948 sprite[newSprite].xvel = 32;
4949 sprite[newSprite].lotag = 40;
4950 sprite[newSprite].ang = pSprite->ang;
4951 }
4952 }
4953 }
4954 if (--pSprite->xvel < 0) pSprite->xvel = 0;
4955 pSprite->cstat = 257;
4956 if (pSprite->picnum == RRTILE3440)
4957 {
4958 pSprite->cstat |= 4 & pSprite->xvel;
4959 pSprite->cstat |= 8 & pSprite->xvel;
4960 if (krand2() & 1)
4961 pSprite->picnum = RRTILE3440 + 1;
4962 }
4963 else if (pSprite->picnum == HENSTAND)
4964 {
4965 pSprite->cstat |= 4 & pSprite->xvel;
4966 pSprite->cstat |= 8 & pSprite->xvel;
4967 if (krand2() & 1)
4968 pSprite->picnum = HENSTAND + 1;
4969 if (!pSprite->xvel)
4970 deleteAfterExecute = 1;
4971 }
4972 if (pSprite->picnum == RRTILE3440 || (pSprite->picnum == RRTILE3440 + 1 && !pSprite->xvel))
4973 deleteAfterExecute = 1;
4974 }
4975 else if (sector[pSprite->sectnum].lotag == 900)
4976 {
4977 if (pSprite->picnum == BOWLINGBALL)
4978 A_BallReturn(spriteNum);
4979 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4980 }
4981 break;
4982
4983 case QUEBALL__STATIC:
4984 case STRIPEBALL__STATIC:
4985 if (pSprite->xvel)
4986 {
4987 for (bssize_t SPRITES_OF(STAT_DEFAULT, hitObject))
4988 if (sprite[hitObject].picnum == POCKET && ldist(&sprite[hitObject],pSprite) < 52)
4989 DELETE_SPRITE_AND_CONTINUE(spriteNum);
4990
4991 int hitObject = clipmove((vec3_t *)pSprite, &pSprite->sectnum,
4992 (((pSprite->xvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14) * TICSPERFRAME) << 11,
4993 (((pSprite->xvel * (sintable[pSprite->ang & 2047])) >> 14) * TICSPERFRAME) << 11, 24L, ZOFFSET6,
4994 ZOFFSET6, CLIPMASK1);
4995
4996 if (hitObject & 49152)
4997 {
4998 if ((hitObject & 49152) == 32768)
4999 {
5000 hitObject &= (MAXWALLS - 1);
5001 Proj_BounceOffWall(pSprite, hitObject);
5002 }
5003 else if ((hitObject & 49152) == 49152)
5004 {
5005 hitObject &= (MAXSPRITES - 1);
5006 A_DamageObject(spriteNum, hitObject);
5007 }
5008 }
5009
5010 if (--pSprite->xvel < 0)
5011 pSprite->xvel = 0;
5012
5013 if (pSprite->picnum == STRIPEBALL)
5014 {
5015 pSprite->cstat = 257;
5016 pSprite->cstat |= (4 & pSprite->xvel) | (8 & pSprite->xvel);
5017 }
5018 }
5019 else
5020 {
5021 int32_t playerDist;
5022 int const playerNum = A_FindPlayer(pSprite,&playerDist);
5023 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
5024
5025 // I'm 50/50 on this being either a typo or a stupid hack
5026 if (playerDist < 1596)
5027 {
5028 int const angDiff = G_GetAngleDelta(fix16_to_int(pPlayer->q16ang),getangle(pSprite->x-pPlayer->pos.x,pSprite->y-pPlayer->pos.y));
5029
5030 if (angDiff > -64 && angDiff < 64 && TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_OPEN)
5031 && pPlayer->toggle_key_flag == 1)
5032 {
5033 int ballSprite;
5034
5035 for (SPRITES_OF(STAT_ACTOR, ballSprite))
5036 {
5037 if (sprite[ballSprite].picnum == QUEBALL || sprite[ballSprite].picnum == STRIPEBALL)
5038 {
5039 int const angDiff2 = G_GetAngleDelta(
5040 fix16_to_int(pPlayer->q16ang), getangle(sprite[ballSprite].x - pPlayer->pos.x, sprite[ballSprite].y - pPlayer->pos.y));
5041
5042 if (angDiff2 > -64 && angDiff2 < 64)
5043 {
5044 int32_t ballDist;
5045 A_FindPlayer(&sprite[ballSprite], &ballDist);
5046
5047 if (playerDist > ballDist)
5048 break;
5049 }
5050 }
5051 }
5052
5053 if (ballSprite == -1)
5054 {
5055 pSprite->xvel = (pSprite->pal == 12) ? 164 : 140;
5056 pSprite->ang = fix16_to_int(pPlayer->q16ang);
5057
5058 pPlayer->toggle_key_flag = 2;
5059 }
5060 }
5061 }
5062
5063 if (playerDist < 512 && pSprite->sectnum == pPlayer->cursectnum)
5064 {
5065 pSprite->ang = getangle(pSprite->x-pPlayer->pos.x,pSprite->y-pPlayer->pos.y);
5066 pSprite->xvel = 48;
5067 }
5068 }
5069
5070 break;
5071
5072 case FORCESPHERE__STATIC:
5073 if (pSprite->yvel == 0)
5074 {
5075 pSprite->yvel = 1;
5076
5077 for (bssize_t l = 512; l < (2048 - 512); l += 128)
5078 {
5079 for (bssize_t j = 0; j < 2048; j += 128)
5080 {
5081 int const newSprite = A_Spawn(spriteNum, FORCESPHERE);
5082 sprite[newSprite].cstat = 257 + 128;
5083 sprite[newSprite].clipdist = 64;
5084 sprite[newSprite].ang = j;
5085 sprite[newSprite].zvel = sintable[l & 2047] >> 5;
5086 sprite[newSprite].xvel = sintable[(l + 512) & 2047] >> 9;
5087 sprite[newSprite].owner = spriteNum;
5088 }
5089 }
5090 }
5091
5092 if (pData[3] > 0)
5093 {
5094 if (pSprite->zvel < 6144)
5095 pSprite->zvel += 192;
5096
5097 pSprite->z += pSprite->zvel;
5098
5099 if (pSprite->z > sector[sectNum].floorz)
5100 pSprite->z = sector[sectNum].floorz;
5101
5102 if (--pData[3] == 0)
5103 DELETE_SPRITE_AND_CONTINUE(spriteNum);
5104 }
5105 else if (pData[2] > 10)
5106 {
5107 for (bssize_t SPRITES_OF(STAT_MISC, miscSprite))
5108 {
5109 if (sprite[miscSprite].owner == spriteNum && sprite[miscSprite].picnum == FORCESPHERE)
5110 actor[miscSprite].t_data[1] = 1 + (krand2() & 63);
5111 }
5112
5113 pData[3] = 64;
5114 }
5115
5116 goto next_sprite;
5117
5118 case RECON__STATIC:
5119 case UFO1__STATICRR:
5120 case UFO2__STATICRR:
5121 case UFO3__STATICRR:
5122 case UFO4__STATICRR:
5123 case UFO5__STATICRR:
5124 {
5125 int playerNum;
5126 DukePlayer_t *pPlayer;
5127
5128 A_GetZLimits(spriteNum);
5129
5130 pSprite->shade += (sector[pSprite->sectnum].ceilingstat & 1) ? (sector[pSprite->sectnum].ceilingshade - pSprite->shade) >> 1
5131 : (sector[pSprite->sectnum].floorshade - pSprite->shade) >> 1;
5132
5133 if (pSprite->z < sector[sectNum].ceilingz + ZOFFSET5)
5134 pSprite->z = sector[sectNum].ceilingz + ZOFFSET5;
5135
5136 #if 0 //def POLYMER
5137 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].sector = s->sectnum;
5138 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].x = s->x;
5139 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].y = s->y;
5140 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].z = s->z + 10248;
5141 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].range = 8192;
5142
5143 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].angle = s->ang;
5144 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].horiz = 100;
5145 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].radius = 256;
5146 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].faderadius = 200;
5147
5148 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].color[0] = 255;
5149 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].color[1] = 255;
5150 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].color[2] = 255;
5151
5152 gamelights[gamelightcount&(PR_MAXLIGHTS-1)].priority = PR_LIGHT_PRIO_MAX_GAME;
5153
5154 if (gamelightcount < PR_MAXLIGHTS)
5155 gamelightcount++;
5156 #endif
5157
5158 if (!g_netServer && ud.multimode < 2)
5159 {
5160 if (g_noEnemies == 1)
5161 {
5162 pSprite->cstat = 32768;
5163 goto next_sprite;
5164 }
5165 else if (g_noEnemies == 2) pSprite->cstat = 257;
5166 }
5167 if (A_IncurDamage(spriteNum) >= 0)
5168 {
5169 if (pSprite->extra < 0 && pData[0] != -1)
5170 {
5171 pData[0] = -1;
5172 pSprite->extra = 0;
5173 }
5174
5175 if (!RR)
5176 A_PlaySound(REALITY ? 99 : RECO_PAIN,spriteNum);
5177 RANDOMSCRAP(pSprite, spriteNum);
5178 }
5179
5180 int32_t playerDist;
5181
5182 if (REALITY)
5183 playerNum = A_FindPlayer(pSprite, &playerDist);
5184
5185 if (pData[0] == -1)
5186 {
5187 pSprite->z += 1024;
5188 pData[2]++;
5189
5190 if ((pData[2]&3) == 0)
5191 A_Spawn(spriteNum,EXPLOSION2);
5192
5193 A_GetZLimits(spriteNum);
5194 pSprite->ang += 96;
5195 pSprite->xvel = 128;
5196
5197 if (A_SetSprite(spriteNum, CLIPMASK0) != 1 || pSprite->z > actor[spriteNum].floorz)
5198 {
5199 for (bssize_t l = 0; l < 16; l++)
5200 RANDOMSCRAP(pSprite, spriteNum);
5201
5202 //int const newSprite = A_Spawn(spriteNum, EXPLOSION2);
5203 A_PlaySound(REALITY ? 15 : LASERTRIP_EXPLODE, spriteNum);
5204 if (REALITY)
5205 RT_AddSmoke(pSprite->x>>1, pSprite->y>>1, pSprite->z>>5, 1);
5206 if (RR)
5207 {
5208 if (RRRA && g_ufoSpawnMinion)
5209 A_Spawn(spriteNum, MINION);
5210 else if (pSprite->picnum == UFO1)
5211 A_Spawn(spriteNum, HEN);
5212 else if (pSprite->picnum == UFO2)
5213 A_Spawn(spriteNum, COOT);
5214 else if (pSprite->picnum == UFO3)
5215 A_Spawn(spriteNum, COW);
5216 else if (pSprite->picnum == UFO4)
5217 A_Spawn(spriteNum, PIG);
5218 else if (pSprite->picnum == UFO5)
5219 A_Spawn(spriteNum, BILLYRAY);
5220 }
5221 else
5222 A_Spawn(spriteNum, PIGCOP);
5223 P_AddKills(g_player[REALITY ? playerNum : myconnectindex].ps, 1);
5224 DELETE_SPRITE_AND_CONTINUE(spriteNum);
5225 }
5226
5227 goto next_sprite;
5228 }
5229 else
5230 {
5231 if (pSprite->z > actor[spriteNum].floorz-(48<<8))
5232 pSprite->z = actor[spriteNum].floorz-(48<<8);
5233 }
5234
5235 if (!REALITY)
5236 playerNum = A_FindPlayer(pSprite, &playerDist);
5237 pPlayer = g_player[playerNum].ps;
5238
5239 int const spriteOwner = pSprite->owner;
5240
5241 // 3 = findplayerz, 4 = shoot
5242
5243 if (pData[0] >= 4)
5244 {
5245 if ((++pData[2] & 15) == 0)
5246 {
5247 int const saveAng = pSprite->ang;
5248 pSprite->ang = actor[spriteNum].tempang;
5249 if (!RR)
5250 A_PlaySound(REALITY ? 98 : RECO_ATTACK, spriteNum);
5251 A_Shoot(spriteNum, FIRELASER);
5252 pSprite->ang = saveAng;
5253 }
5254 if (pData[2] > (GAMETICSPERSEC * 3)
5255 || !cansee(pSprite->x, pSprite->y, pSprite->z - ZOFFSET2, pSprite->sectnum, pPlayer->pos.x, pPlayer->pos.y,
5256 pPlayer->pos.z, pPlayer->cursectnum))
5257 {
5258 pData[0] = 0;
5259 pData[2] = 0;
5260 }
5261 else actor[spriteNum].tempang += G_GetAngleDelta(actor[spriteNum].tempang,
5262 getangle(pPlayer->pos.x - pSprite->x,
5263 pPlayer->pos.y - pSprite->y)) / 3;
5264 }
5265 else if (pData[0] == 2 || pData[0] == 3)
5266 {
5267 pData[3] = 0;
5268 pSprite->xvel = (pSprite->xvel > 0) ? pSprite->xvel - 16 : 0;
5269
5270 if (pData[0] == 2)
5271 {
5272 int const zDiff = pPlayer->pos.z - pSprite->z;
5273
5274 if (klabs(zDiff) < (48 << 8))
5275 pData[0] = 3;
5276 else
5277 pSprite->z += ksgn(pPlayer->pos.z - pSprite->z) << (RR ? 8 : 10);
5278 }
5279 else
5280 {
5281 pData[2]++;
5282 if (pData[2] > (GAMETICSPERSEC*3) ||
5283 !cansee(pSprite->x,pSprite->y,pSprite->z-ZOFFSET2,pSprite->sectnum, pPlayer->pos.x,pPlayer->pos.y,pPlayer->pos.z,pPlayer->cursectnum))
5284 {
5285 pData[0] = 1;
5286 pData[2] = 0;
5287 }
5288 else if ((pData[2]&15) == 0)
5289 {
5290 if (!RR)
5291 A_PlaySound(REALITY ? 98 : RECO_ATTACK,spriteNum);
5292 A_Shoot(spriteNum,FIRELASER);
5293 }
5294 }
5295 pSprite->ang += G_GetAngleDelta(pSprite->ang, getangle(pPlayer->pos.x - pSprite->x, pPlayer->pos.y - pSprite->y)) >> 2;
5296 }
5297
5298 if (pData[0] != 2 && pData[0] != 3)
5299 {
5300 int newAngle;
5301 int locatorDist = ldist(&sprite[spriteOwner], pSprite);
5302 if (locatorDist <= 1524)
5303 {
5304 newAngle = pSprite->ang;
5305 pSprite->xvel >>= 1;
5306 }
5307 else newAngle = getangle(sprite[spriteOwner].x - pSprite->x, sprite[spriteOwner].y - pSprite->y);
5308
5309 if (pData[0] == 1 || pData[0] == 4) // Found a locator and going with it
5310 {
5311 locatorDist = dist(&sprite[spriteOwner], pSprite);
5312
5313 if (locatorDist <= 1524)
5314 {
5315 pData[0] = (pData[0] == 1) ? 0 : 5;
5316 }
5317 else
5318 {
5319 // Control speed here
5320 if (pSprite->xvel < 256) pSprite->xvel += 32;
5321 }
5322
5323 if (pData[0] < 2) pData[2]++;
5324
5325 if (playerDist < 6144 && pData[0] < 2 && pData[2] > (GAMETICSPERSEC*4))
5326 {
5327 pData[0] = 2+(krand2()&2);
5328 pData[2] = 0;
5329 actor[spriteNum].tempang = pSprite->ang;
5330 }
5331 }
5332
5333 int locatorSprite = pSprite->owner;
5334
5335 if (pData[0] == 0 || pData[0] == 5)
5336 {
5337 pData[0] = (pData[0] == 0) ? 1 : 4;
5338 pSprite->owner = A_FindLocator(pSprite->hitag, -1);
5339 locatorSprite = pSprite->owner;
5340
5341 if (locatorSprite == -1)
5342 {
5343 locatorSprite = actor[spriteNum].t_data[5];
5344 pSprite->hitag = locatorSprite;
5345 pSprite->owner = A_FindLocator(locatorSprite, -1);
5346 locatorSprite = pSprite->owner;
5347
5348 if (locatorSprite == -1)
5349 DELETE_SPRITE_AND_CONTINUE(spriteNum);
5350 }
5351 else pSprite->hitag++;
5352 }
5353
5354 // RECON_T4
5355 pData[3] = G_GetAngleDelta(pSprite->ang,newAngle);
5356 pSprite->ang += pData[3]>>3;
5357
5358 if (pSprite->z < sprite[locatorSprite].z)
5359 pSprite->z += 1024;
5360 else
5361 pSprite->z -= 1024;
5362 }
5363
5364 int sndNum = RR ? 457 : (REALITY ? 96 : RECO_ROAM);
5365
5366 if (!A_CheckSoundPlaying(spriteNum,sndNum))
5367 A_PlaySound(sndNum,spriteNum);
5368
5369 A_SetSprite(spriteNum,CLIPMASK0);
5370
5371 goto next_sprite;
5372 }
5373
5374 case OOZ2__STATIC:
5375 if (RR) break;
5376 fallthrough__;
5377 case OOZ__STATIC:
5378 {
5379 A_GetZLimits(spriteNum);
5380
5381 int const yrepeat = min((actor[spriteNum].floorz - actor[spriteNum].ceilingz) >> 9, 255);
5382 int const xrepeat = clamp(25 - (yrepeat >> 1), 8, 48);
5383
5384 pSprite->yrepeat = yrepeat;
5385 pSprite->xrepeat = xrepeat;
5386 pSprite->z = actor[spriteNum].floorz;
5387
5388 goto next_sprite;
5389 }
5390
5391 case GREENSLIME__STATIC:
5392 {
5393 if (RR) break;
5394 // #ifndef VOLUMEONE
5395 if (!g_netServer && ud.multimode < 2)
5396 {
5397 if (g_noEnemies == 1)
5398 {
5399 pSprite->cstat = 32768;
5400 goto next_sprite;
5401 }
5402 else if (g_noEnemies == 2) pSprite->cstat = 257;
5403 }
5404 // #endif
5405
5406 pData[1]+=128;
5407
5408 if (sector[sectNum].floorstat&1)
5409 DELETE_SPRITE_AND_CONTINUE(spriteNum);
5410
5411 int32_t playerDist;
5412 int const playerNum = A_FindPlayer(pSprite, &playerDist);
5413 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
5414
5415 if (playerDist > 20480)
5416 {
5417 if (++actor[spriteNum].timetosleep > SLEEPTIME)
5418 {
5419 actor[spriteNum].timetosleep = 0;
5420 changespritestat(spriteNum, STAT_ZOMBIEACTOR);
5421 goto next_sprite;
5422 }
5423 }
5424
5425 if (!REALITY && pData[0] == -5) // FROZEN
5426 {
5427 pData[3]++;
5428 if (pData[3] > 280)
5429 {
5430 pSprite->pal = 0;
5431 pData[0] = pData[3] = 0;
5432 goto next_sprite;
5433 }
5434 A_Fall(spriteNum);
5435
5436 pSprite->cstat = 257;
5437 pSprite->picnum = GREENSLIME + 2;
5438 pSprite->extra = 1;
5439 pSprite->pal = 1;
5440
5441 int const damageTile = A_IncurDamage(spriteNum);
5442 if (damageTile >= 0)
5443 {
5444 if (damageTile == FREEZEBLAST)
5445 goto next_sprite;
5446
5447 P_AddKills(pPlayer, 1);
5448
5449 for (bssize_t j = 16; j >= 0; --j)
5450 {
5451 int32_t const r1 = krand2(), r2 = krand2(), r3 = krand2();
5452 int32_t newSprite = A_InsertSprite(SECT(spriteNum), SX(spriteNum), SY(spriteNum), SZ(spriteNum),
5453 GLASSPIECES + (j % 3), -32, 36, 36, r3 & 2047, 32 + (r2 & 63),
5454 1024 - (r1 & 1023), spriteNum, 5);
5455 sprite[newSprite].pal = 1;
5456 }
5457
5458 A_PlaySound(GLASS_BREAKING, spriteNum);
5459 DELETE_SPRITE_AND_CONTINUE(spriteNum);
5460 }
5461 else if (playerDist < 1024 && pPlayer->quick_kick == 0)
5462 {
5463 int const angDiff = G_GetAngleDelta(fix16_to_int(pPlayer->q16ang), getangle(SX(spriteNum) - pPlayer->pos.x,
5464 SY(spriteNum) - pPlayer->pos.y));
5465
5466 if (angDiff > -128 && angDiff < 128)
5467 pPlayer->quick_kick = 14;
5468 }
5469
5470 goto next_sprite;
5471 }
5472
5473 pSprite->cstat = (playerDist < 1596) ? 0 : 257;
5474
5475 if (pData[0] == -4) //On the player
5476 {
5477 if (sprite[pPlayer->i].extra < 1)
5478 {
5479 pData[0] = 0;
5480 goto next_sprite;
5481 }
5482
5483 setsprite(spriteNum,(vec3_t *)pSprite);
5484
5485 pSprite->ang = fix16_to_int(pPlayer->q16ang);
5486
5487 if ((TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_FIRE) || (pPlayer->quick_kick > 0)) && sprite[pPlayer->i].extra > 0)
5488 if (pPlayer->quick_kick > 0 ||
5489 (pPlayer->curr_weapon != HANDREMOTE_WEAPON && pPlayer->curr_weapon != HANDBOMB_WEAPON &&
5490 pPlayer->curr_weapon != TRIPBOMB_WEAPON && pPlayer->ammo_amount[pPlayer->curr_weapon] >= 0))
5491 {
5492 for (bssize_t x = 0; x < 8; ++x)
5493 {
5494 int32_t r1 = krand2(), r2 = krand2(), r3 = krand2(), r4 = krand2();
5495 if (REALITY)
5496 {
5497 swap(&r1, &r4);
5498 swap(&r2, &r3);
5499 }
5500 int const j
5501 = A_InsertSprite(sectNum, pSprite->x, pSprite->y, pSprite->z - ZOFFSET3, SCRAP3 + (r4 & 3), -8, 48, 48,
5502 r3 & 2047, (r2 & 63) + 64, -(r1 & 4095) - (pSprite->zvel >> 2), spriteNum, 5);
5503 sprite[j].pal = 6;
5504 }
5505
5506 A_PlaySound(REALITY ? 116 : SLIM_DYING,spriteNum);
5507 A_PlaySound(REALITY ? 44 : SQUISHED,spriteNum);
5508
5509 if ((krand2()&255) < 32)
5510 {
5511 int const j = A_Spawn(spriteNum,BLOODPOOL);
5512 sprite[j].pal = 0;
5513 }
5514
5515 P_AddKills(pPlayer, 1);
5516 pData[0] = -3;
5517
5518 if (pPlayer->somethingonplayer == spriteNum)
5519 pPlayer->somethingonplayer = -1;
5520
5521 DELETE_SPRITE_AND_CONTINUE(spriteNum);
5522 }
5523
5524 pSprite->z = pPlayer->pos.z + pPlayer->pyoff - pData[2] + ZOFFSET3 + (fix16_to_int(F16(100) - pPlayer->q16horiz) << 4);
5525
5526 if (pData[2] > 512)
5527 pData[2] -= 128;
5528
5529 if (pData[2] < 348)
5530 pData[2] += 128;
5531
5532 if (pPlayer->newowner >= 0)
5533 G_ClearCameraView(pPlayer);
5534
5535 if (pData[3] > 0)
5536 {
5537 static const char slimeFrames[] = { 5, 5, 6, 6, 7, 7, 6, 5 };
5538
5539 Bassert(pData[3] < ARRAY_SSIZE(slimeFrames));
5540
5541 pSprite->picnum = GREENSLIME + slimeFrames[pData[3]];
5542
5543 if (pData[3] == 5)
5544 {
5545 sprite[pPlayer->i].extra += -(5 + (krand2() & 3));
5546 A_PlaySound(REALITY ? 27 : SLIM_ATTACK, spriteNum);
5547 }
5548
5549 if (pData[3] < 7)
5550 pData[3]++;
5551 else
5552 pData[3] = 0;
5553 }
5554 else
5555 {
5556 pSprite->picnum = GREENSLIME + 5;
5557 if (rnd(32))
5558 pData[3] = 1;
5559 }
5560
5561 pSprite->xrepeat = 20 + (sintable[pData[1] & 2047] >> 13);
5562 pSprite->yrepeat = 15 + (sintable[pData[1] & 2047] >> 13);
5563 pSprite->x = pPlayer->pos.x + (sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] >> 7);
5564 pSprite->y = pPlayer->pos.y + (sintable[fix16_to_int(pPlayer->q16ang) & 2047] >> 7);
5565
5566 goto next_sprite;
5567 }
5568
5569 else if (pSprite->xvel < 64 && playerDist < 768)
5570 {
5571 if (pPlayer->somethingonplayer == -1)
5572 {
5573 pPlayer->somethingonplayer = spriteNum;
5574 if (pData[0] == 3 || pData[0] == 2) // Falling downward
5575 pData[2] = (12 << 8);
5576 else
5577 pData[2] = -(13 << 8); // Climbing up player
5578 pData[0] = -4;
5579 }
5580 }
5581
5582 int const damageTile = A_IncurDamage(spriteNum);
5583 if (damageTile >= 0)
5584 {
5585 A_PlaySound(REALITY ? 116 : SLIM_DYING,spriteNum);
5586
5587 P_AddKills(pPlayer, 1);
5588
5589 if (pPlayer->somethingonplayer == spriteNum)
5590 pPlayer->somethingonplayer = -1;
5591
5592 if (!REALITY && damageTile == FREEZEBLAST)
5593 {
5594 A_PlaySound(SOMETHINGFROZE, spriteNum);
5595 pData[0] = -5;
5596 pData[3] = 0;
5597 goto next_sprite;
5598 }
5599
5600 if ((krand2()&255) < 32)
5601 {
5602 int const j = A_Spawn(spriteNum,BLOODPOOL);
5603 sprite[j].pal = 0;
5604 }
5605
5606 for (bssize_t x=0; x<8; x++)
5607 {
5608 int32_t r1 = krand2(), r2 = krand2(), r3 = krand2(), r4 = krand2();
5609 if (REALITY)
5610 {
5611 swap(&r1, &r4);
5612 swap(&r2, &r3);
5613 }
5614 int const j = A_InsertSprite(sectNum, pSprite->x, pSprite->y, pSprite->z - ZOFFSET3, SCRAP3 + (r4 & 3), -8,
5615 48, 48, r3 & 2047, (r2 & 63) + 64, -(r1 & 4095) - (pSprite->zvel >> 2),
5616 spriteNum, 5);
5617 sprite[j].pal = 6;
5618 }
5619 pData[0] = -3;
5620 DELETE_SPRITE_AND_CONTINUE(spriteNum);
5621 }
5622 // All weap
5623 if (pData[0] == -1) //Shrinking down
5624 {
5625 A_Fall(spriteNum);
5626
5627 pSprite->cstat &= 65535-8;
5628 pSprite->picnum = GREENSLIME+4;
5629
5630 // if(s->yrepeat > 62)
5631 // A_DoGuts(s,JIBS6,5,myconnectindex);
5632
5633 if (pSprite->xrepeat > 32) pSprite->xrepeat -= krand2()&7;
5634 if (pSprite->yrepeat > 16) pSprite->yrepeat -= krand2()&7;
5635 else
5636 {
5637 pSprite->xrepeat = 40;
5638 pSprite->yrepeat = 16;
5639 pData[5] = -1;
5640 pData[0] = 0;
5641 }
5642
5643 goto next_sprite;
5644 }
5645 else if (pData[0] != -2) A_GetZLimits(spriteNum);
5646
5647 if (pData[0] == -2) //On top of somebody
5648 {
5649 A_Fall(spriteNum);
5650 sprite[pData[5]].xvel = 0;
5651
5652 int const ang = sprite[pData[5]].ang;
5653 pSprite->x = sprite[pData[5]].x + (sintable[(ang + 512) & 2047] >> 11);
5654 pSprite->y = sprite[pData[5]].y + (sintable[ang & 2047] >> 11);
5655 pSprite->z = sprite[pData[5]].z;
5656
5657 pSprite->picnum = GREENSLIME + 2 + (g_globalRandom & 1);
5658
5659 if (pSprite->yrepeat < 64)
5660 pSprite->yrepeat += 2;
5661 else
5662 {
5663 if (pSprite->xrepeat < 32)
5664 pSprite->xrepeat += 4;
5665 else
5666 {
5667 pData[0] = -1;
5668 playerDist = ldist(pSprite, &sprite[pData[5]]);
5669
5670 if (playerDist < 768)
5671 sprite[pData[5]].xrepeat = 0;
5672 }
5673 }
5674
5675 goto next_sprite;
5676 }
5677
5678 //Check randomly to see of there is an actor near
5679 if (rnd(32))
5680 {
5681 for (bssize_t SPRITES_OF_SECT(sectNum, j))
5682 {
5683 if (A_CheckSpriteFlags(j, SFLAG_GREENSLIMEFOOD))
5684 {
5685 if (ldist(pSprite, &sprite[j]) < 768 && (klabs(pSprite->z - sprite[j].z) < 8192)) // Gulp them
5686 {
5687 pData[5] = j;
5688 pData[0] = -2;
5689 pData[1] = 0;
5690 goto next_sprite;
5691 }
5692 }
5693 }
5694 }
5695
5696 //Moving on the ground or ceiling
5697
5698 if (pData[0] == 0 || pData[0] == 2)
5699 {
5700 pSprite->picnum = GREENSLIME;
5701
5702 if ((krand2()&511) == 0)
5703 A_PlaySound(REALITY ? 127 : SLIM_ROAM,spriteNum);
5704
5705 if (pData[0]==2)
5706 {
5707 pSprite->zvel = 0;
5708 pSprite->cstat &= (65535-8);
5709
5710 if ((sector[sectNum].ceilingstat&1) || (actor[spriteNum].ceilingz+6144) < pSprite->z)
5711 {
5712 pSprite->z += 2048;
5713 pData[0] = 3;
5714 goto next_sprite;
5715 }
5716 }
5717 else
5718 {
5719 pSprite->cstat |= 8;
5720 A_Fall(spriteNum);
5721 }
5722
5723 if (everyothertime&1) A_SetSprite(spriteNum,CLIPMASK0);
5724
5725 if (pSprite->xvel > 96)
5726 {
5727 pSprite->xvel -= 2;
5728 goto next_sprite;
5729 }
5730 else
5731 {
5732 if (pSprite->xvel < 32) pSprite->xvel += 4;
5733 pSprite->xvel = 64 - (sintable[(pData[1]+512)&2047]>>9);
5734
5735 pSprite->ang += G_GetAngleDelta(pSprite->ang,
5736 getangle(pPlayer->pos.x-pSprite->x,pPlayer->pos.y-pSprite->y))>>3;
5737 // TJR
5738 }
5739
5740 pSprite->xrepeat = 36 + (sintable[(pData[1]+512)&2047]>>11);
5741 pSprite->yrepeat = 16 + (sintable[pData[1]&2047]>>13);
5742
5743 if (rnd(4) && (sector[sectNum].ceilingstat&1) == 0 &&
5744 klabs(actor[spriteNum].floorz-actor[spriteNum].ceilingz)
5745 < (192<<8))
5746 {
5747 pSprite->zvel = 0;
5748 pData[0]++;
5749 }
5750
5751 }
5752
5753 if (pData[0]==1)
5754 {
5755 pSprite->picnum = GREENSLIME;
5756 if (pSprite->yrepeat < 40) pSprite->yrepeat+=8;
5757 if (pSprite->xrepeat > 8) pSprite->xrepeat-=4;
5758 if (pSprite->zvel > -(2048+1024))
5759 pSprite->zvel -= 348;
5760 pSprite->z += pSprite->zvel;
5761 if (pSprite->z < actor[spriteNum].ceilingz+4096)
5762 {
5763 pSprite->z = actor[spriteNum].ceilingz+4096;
5764 pSprite->xvel = 0;
5765 pData[0] = 2;
5766 }
5767 }
5768
5769 if (pData[0]==3)
5770 {
5771 pSprite->picnum = GREENSLIME+1;
5772
5773 A_Fall(spriteNum);
5774
5775 if (pSprite->z > actor[spriteNum].floorz-ZOFFSET3)
5776 {
5777 pSprite->yrepeat-=4;
5778 pSprite->xrepeat+=2;
5779 }
5780 else
5781 {
5782 if (pSprite->yrepeat < (40-4)) pSprite->yrepeat+=8;
5783 if (pSprite->xrepeat > 8) pSprite->xrepeat-=4;
5784 }
5785
5786 if (pSprite->z > actor[spriteNum].floorz-2048)
5787 {
5788 pSprite->z = actor[spriteNum].floorz-2048;
5789 pData[0] = 0;
5790 pSprite->xvel = 0;
5791 }
5792 }
5793 goto next_sprite;
5794 }
5795
5796 case EMPTYBIKE__STATICRR:
5797 if(!RRRA) break;
5798 A_Fall(spriteNum);
5799 A_GetZLimits(spriteNum);
5800 if (sector[sectNum].lotag == ST_1_ABOVE_WATER)
5801 {
5802 vec3_t const pos = { pSprite->x, pSprite->y, actor[spriteNum].floorz + ZOFFSET2 };
5803 setsprite(spriteNum, &pos);
5804 }
5805 break;
5806
5807 case EMPTYBOAT__STATICRR:
5808 if (!RRRA) break;
5809 A_Fall(spriteNum);
5810 A_GetZLimits(spriteNum);
5811 break;
5812
5813 case TRIPBOMBSPRITE__STATIC:
5814 if (!RR) break;
5815 if (!RRRA || (sector[sectNum].lotag != ST_1_ABOVE_WATER && sector[sectNum].lotag != 160))
5816 if (pSprite->xvel)
5817 {
5818 vec3_t const vect = {
5819 (pSprite->xvel*(sintable[(pSprite->ang + 512) & 2047])) >> 14,
5820 (pSprite->xvel*(sintable[pSprite->ang & 2047])) >> 14,
5821 pSprite->zvel
5822 };
5823
5824 A_MoveSprite(spriteNum, &vect, CLIPMASK0);
5825 pSprite->xvel--;
5826 }
5827 break;
5828
5829 case BOUNCEMINE__STATIC:
5830 if (RR) break;
5831 fallthrough__;
5832 case MORTER__STATIC:
5833 if (!RR && !REALITY)
5834 {
5835 int const j = A_Spawn(spriteNum, FRAMEEFFECT1);
5836 actor[j].t_data[0] = 3;
5837 }
5838 fallthrough__;
5839 case DN64TILE3634__STATIC:
5840 case HEAVYHBOMB__STATIC:
5841 case CHEERBOMB__STATICRR:
5842 {
5843 if (!REALITY && pSprite->picnum == DN64TILE3634)
5844 break;
5845 int playerNum;
5846 DukePlayer_t *pPlayer;
5847 int detonatePlayer;
5848
5849 if ((pSprite->cstat&32768))
5850 {
5851 if (--pData[2] <= 0)
5852 {
5853 A_PlaySound(REALITY ? 45 : TELEPORTER, spriteNum);
5854 A_Spawn(spriteNum, TRANSPORTERSTAR);
5855 pSprite->cstat = 257;
5856 }
5857 goto next_sprite;
5858 }
5859
5860 int32_t playerDist;
5861 playerNum = A_FindPlayer(pSprite, &playerDist);
5862 pPlayer = g_player[playerNum].ps;
5863
5864 if (playerDist < 1220)
5865 pSprite->cstat &= ~257;
5866 else
5867 pSprite->cstat |= 257;
5868
5869 if (pData[3] == 0)
5870 {
5871 if (A_IncurDamage(spriteNum) >= 0)
5872 {
5873 pData[3] = 1;
5874 pData[4] = 0;
5875 detonatePlayer = 0;
5876 pSprite->xvel = 0;
5877 goto DETONATEB;
5878 }
5879
5880 if (REALITY)
5881 {
5882 if (pSprite->picnum == MORTER)
5883 {
5884 if (pSprite->xvel == 0)
5885 {
5886 pData[3] = 1;
5887 pData[4] = 0;
5888 detonatePlayer = 0;
5889 goto DETONATEB;
5890 }
5891 if (pSprite->lotag == ST_2_UNDERWATER)
5892 {
5893 if (krand2() & 8)
5894 A_Spawn(spriteNum, WATERBUBBLE);
5895 }
5896 else
5897 A_Spawn(spriteNum, SMALLSMOKE);
5898 }
5899 if (pSprite->picnum == DN64TILE3634)
5900 {
5901 if (++pSprite->yvel == 64)
5902 {
5903 pData[3] = 1;
5904 pData[4] = 0;
5905 detonatePlayer = 0;
5906 pSprite->xvel = 0;
5907 goto DETONATEB;
5908 }
5909 if (pSprite->yvel > 5 && numplayers == 1)
5910 {
5911 if (pSprite->lotag == ST_2_UNDERWATER)
5912 {
5913 if (krand2() & 8)
5914 A_Spawn(spriteNum, WATERBUBBLE);
5915 }
5916 else
5917 A_Spawn(spriteNum, SMALLSMOKE);
5918 }
5919 }
5920 }
5921 }
5922
5923 int moveSprite, zvel;
5924 zvel = pSprite->zvel;
5925
5926 if (RR || pSprite->picnum != BOUNCEMINE)
5927 {
5928 if (REALITY)
5929 {
5930 A_FallBomb(spriteNum);
5931 vec3_t tmpvect = {
5932 (pSprite->xvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14,
5933 (pSprite->xvel * (sintable[pSprite->ang & 2047])) >> 14,
5934 pSprite->zvel };
5935
5936 moveSprite = A_MoveSprite(spriteNum, &tmpvect, REALITY ? CLIPMASK1 : CLIPMASK0);
5937
5938 if (pSprite->picnum == DN64TILE3634 && pData[3] == 0 && pSprite->yvel > 5)
5939 {
5940 int otherSprite, nextOtherSprite;
5941 for (SPRITES_OF_STAT_SAFE(STAT_ACTOR, otherSprite, nextOtherSprite))
5942 {
5943 if (A_CheckSpriteFlags(otherSprite, SFLAG_HARDCODED_BADGUY))
5944 {
5945 int d1 = 1024;
5946 if (sprite[otherSprite].picnum == BOSS1 || sprite[otherSprite].picnum == BOSS2
5947 || sprite[otherSprite].picnum == BOSS3)
5948 {
5949 d1 = 3072;
5950 }
5951 if (A_ManhattanDistance(spriteNum, otherSprite) < d1)
5952 {
5953 pData[3] = 1;
5954 pData[4] = 1;
5955 detonatePlayer = 0;
5956 pSprite->xvel = 0;
5957 goto DETONATEB;
5958 }
5959 }
5960 }
5961 for (SPRITES_OF_STAT_SAFE(STAT_PLAYER, otherSprite, nextOtherSprite))
5962 {
5963 if (pSprite->owner != otherSprite || pSprite->yvel > 10)
5964 if (sprite[otherSprite].extra > 0 && A_ManhattanDistance(spriteNum, otherSprite) < 1024)
5965 {
5966 pData[3] = 1;
5967 pData[4] = 1;
5968 detonatePlayer = 0;
5969 pSprite->xvel = 0;
5970 goto DETONATEB;
5971 }
5972 }
5973 for (SPRITES_OF_STAT_SAFE(STAT_STANDABLE, otherSprite, nextOtherSprite))
5974 {
5975 if (sprite[otherSprite].picnum >= CRACK1 && sprite[otherSprite].picnum <= CRACK4)
5976 if (A_ManhattanDistance(spriteNum, otherSprite) < 1024)
5977 {
5978 pData[3] = 1;
5979 pData[4] = 1;
5980 detonatePlayer = 0;
5981 pSprite->xvel = 0;
5982 goto DETONATEB;
5983 }
5984 }
5985 }
5986
5987 }
5988 else
5989 A_Fall(spriteNum);
5990
5991 if (sector[sectNum].lotag != ST_1_ABOVE_WATER && (!RRRA || sector[sectNum].lotag != 160) && pSprite->z >= actor[spriteNum].floorz-(ZOFFSET) && pSprite->yvel < 3)
5992 {
5993 if (REALITY || pSprite->yvel > 0 || (pSprite->yvel == 0 && actor[spriteNum].floorz == sector[sectNum].floorz))
5994 {
5995 if (RRRA && pSprite->picnum == CHEERBOMB)
5996 {
5997 pData[3] = 1;
5998 pData[4] = 1;
5999 detonatePlayer = 0;
6000 goto DETONATEB;
6001 }
6002 else if (REALITY && pSprite->picnum == HEAVYHBOMB)
6003 {
6004 if (pSprite->yvel > 0 || (pSprite->yvel == 0 && actor[spriteNum].floorz == sector[sectNum].floorz))
6005 A_PlaySound(11, spriteNum);
6006 pSprite->zvel = -((4-pSprite->yvel)<<8);
6007 pSprite->yvel++;
6008 pSprite->cstat ^= 4;
6009 }
6010 else
6011 {
6012 A_PlaySound(REALITY ? 11 : PIPEBOMB_BOUNCE,spriteNum);
6013 if (REALITY)
6014 pSprite->zvel = -(zvel >> 1);
6015 }
6016 }
6017 if (REALITY)
6018 {
6019 if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER)
6020 pSprite->zvel >>= 2;
6021 pSprite->xvel >>= 1;
6022 }
6023 else
6024 {
6025 pSprite->zvel = -((4-pSprite->yvel)<<8);
6026 if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER)
6027 pSprite->zvel >>= 2;
6028 pSprite->yvel++;
6029 }
6030 }
6031 if (RR)
6032 {
6033 if ((!RRRA || pSprite->picnum != CHEERBOMB) && pSprite->z < actor[spriteNum].ceilingz+(16<<8) && sector[sectNum].lotag != ST_2_UNDERWATER )
6034 {
6035 pSprite->z = actor[spriteNum].ceilingz+(16<<8);
6036 pSprite->zvel = 0;
6037 }
6038 }
6039 else if (REALITY)
6040 {
6041 if (pSprite->z <= actor[spriteNum].ceilingz)
6042 {
6043 pSprite->z = actor[spriteNum].ceilingz+(3<<8);
6044 pSprite->zvel = -(zvel >> 1);
6045 }
6046 }
6047 else
6048 {
6049 if (pSprite->z < actor[spriteNum].ceilingz) // && sector[sect].lotag != ST_2_UNDERWATER )
6050 {
6051 pSprite->z = actor[spriteNum].ceilingz+(3<<8);
6052 pSprite->zvel = 0;
6053 }
6054 }
6055
6056 if (REALITY)
6057 goto __skip_movesprite;
6058 }
6059
6060 // can't initialize this because of the goto above
6061 vec3_t tmpvect;
6062 tmpvect.x = (pSprite->xvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14;
6063 tmpvect.y = (pSprite->xvel * (sintable[pSprite->ang & 2047])) >> 14;
6064 tmpvect.z = pSprite->zvel;
6065
6066 moveSprite = A_MoveSprite(spriteNum, &tmpvect, REALITY ? CLIPMASK1 : CLIPMASK0);
6067
6068 __skip_movesprite:
6069
6070 //actor[spriteNum].movflag = moveSprite;
6071
6072 if (sector[SECT(spriteNum)].lotag == ST_1_ABOVE_WATER && pSprite->zvel == 0)
6073 {
6074 pSprite->z += ZOFFSET5;
6075 if (REALITY)
6076 pSprite->zvel = zvel;
6077 if (pData[5] == 0)
6078 {
6079 pData[5] = 1;
6080 A_Spawn(spriteNum,WATERSPLASH2);
6081 if (RRRA && pSprite->picnum == MORTER)
6082 pSprite->xvel = 0;
6083 }
6084 }
6085 else pData[5] = 0;
6086
6087 if (pData[3] == 0 && ((!RR && pSprite->picnum == BOUNCEMINE) || pSprite->picnum == MORTER || (RRRA && pSprite->picnum == CHEERBOMB))
6088 && (moveSprite || playerDist < 844))
6089 {
6090 pData[3] = 1;
6091 pData[4] = 0;
6092 detonatePlayer = 0;
6093 pSprite->xvel = 0;
6094 goto DETONATEB;
6095 }
6096
6097 if (sprite[pSprite->owner].picnum == APLAYER && (!REALITY || pSprite->picnum == HEAVYHBOMB))
6098 detonatePlayer = P_Get(pSprite->owner);
6099 else detonatePlayer = -1;
6100
6101 if (REALITY)
6102 {
6103 if (sector[sectNum].lotag == ST_2_UNDERWATER)
6104 {
6105 pSprite->xvel = pSprite->xvel*0.95;
6106 pSprite->zvel = pSprite->zvel*0.95;
6107 }
6108 if (pSprite->zvel == 0)
6109 pSprite->xvel -= 5;
6110 if (pSprite->xvel < 0)
6111 pSprite->xvel = 0;
6112 if (pSprite->picnum == HEAVYHBOMB && (pSprite->xvel&8)) pSprite->cstat ^= 4;
6113 }
6114 else
6115 {
6116 if (pSprite->xvel > 0)
6117 {
6118 pSprite->xvel -= 5;
6119 if (sector[sectNum].lotag == ST_2_UNDERWATER)
6120 pSprite->xvel -= 10;
6121
6122 if (pSprite->xvel < 0)
6123 pSprite->xvel = 0;
6124 if (pSprite->xvel&8) pSprite->cstat ^= 4;
6125 }
6126 }
6127
6128 if ((moveSprite&49152) == 32768)
6129 {
6130 vec3_t davect = *(vec3_t *)pSprite;
6131 moveSprite &= (MAXWALLS - 1);
6132 A_DamageWall(spriteNum, moveSprite, &davect, pSprite->picnum);
6133 if (RRRA && pSprite->picnum == CHEERBOMB)
6134 {
6135 pData[3] = 1;
6136 pData[4] = 0;
6137 detonatePlayer = 0;
6138 pSprite->xvel = 0;
6139 goto DETONATEB;
6140 }
6141 if (!REALITY || (wall[moveSprite].overpicnum != GLASS && wall[moveSprite].overpicnum != GLASS2))
6142 {
6143 Proj_BounceOffWall(pSprite, moveSprite);
6144 if (REALITY)
6145 A_PlaySound(11, spriteNum);
6146 }
6147 pSprite->xvel >>= 1;
6148 if (REALITY)
6149 pSprite->zvel >>= 1;
6150 }
6151
6152 DETONATEB:
6153 if (!NAM_WW2GI)
6154 bBoom = 0;
6155 if ((detonatePlayer >= 0 && g_player[detonatePlayer].ps->hbomb_on == 0) || pData[3] == 1)
6156 bBoom = 1;
6157 if (NAM_WW2GI && pSprite->picnum == HEAVYHBOMB)
6158 {
6159 pSprite->extra--;
6160 if (pSprite->extra <= 0)
6161 bBoom = 1;
6162 }
6163
6164 if (bBoom)
6165 {
6166 pData[4]++;
6167
6168 if (pData[4] == 2)
6169 {
6170 int const x = pSprite->extra;
6171 int radius = 0;
6172
6173 switch (DYNAMICTILEMAP(pSprite->picnum))
6174 {
6175 case TRIPBOMBSPRITE__STATIC: if(RR) radius = g_tripbombRadius; break;
6176 case HEAVYHBOMB__STATIC: radius = g_pipebombRadius; break;
6177 case HBOMBAMMO__STATIC: if (RR) radius = g_pipebombRadius; break;
6178 case MORTER__STATIC: radius = g_morterRadius; break;
6179 case BOUNCEMINE__STATIC: if (!RR) radius = g_bouncemineRadius; break;
6180 case CHEERBOMB__STATICRR: if (RRRA) radius = g_morterRadius; break;
6181 case DN64TILE3634__STATIC: if (REALITY) radius = g_pipebombRadius; break;
6182 }
6183
6184 if (!RR || sector[pSprite->sectnum].lotag != 800)
6185 {
6186 A_RadiusDamage(spriteNum, radius, x >> 2, x >> 1, x - (x >> 2), x);
6187
6188 int const j = A_Spawn(spriteNum, EXPLOSION2);
6189 A_PlaySound(REALITY ? 12 : PIPEBOMB_EXPLODE, j);
6190
6191 if (RRRA && pSprite->picnum == CHEERBOMB)
6192 A_Spawn(spriteNum, BURNING);
6193
6194 if (!RR && !REALITY && pSprite->zvel == 0)
6195 A_Spawn(spriteNum,EXPLOSION2BOT);
6196
6197 for (bssize_t x = 0; x < 8; ++x)
6198 RANDOMSCRAP(pSprite, spriteNum);
6199 }
6200 }
6201
6202 if (pSprite->yrepeat)
6203 {
6204 pSprite->yrepeat = 0;
6205 goto next_sprite;
6206 }
6207
6208 if (pData[4] > 20)
6209 {
6210 if (RR || pSprite->owner != spriteNum || ud.respawn_items == 0)
6211 {
6212 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6213 }
6214 else
6215 {
6216 pData[4] = g_itemRespawnTime;
6217 A_Spawn(spriteNum,RESPAWNMARKERRED);
6218 pSprite->cstat = 32768;
6219 pSprite->yrepeat = 9;
6220 goto next_sprite;
6221 }
6222 }
6223 if (RRRA && pSprite->picnum == CHEERBOMB)
6224 {
6225 A_Spawn(spriteNum, BURNING);
6226 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6227 }
6228 }
6229 else if (pSprite->picnum == HEAVYHBOMB && playerDist < 788 && pData[0] > 7 && pSprite->xvel == 0)
6230 {
6231 if (cansee(pSprite->x, pSprite->y, pSprite->z - ZOFFSET3, pSprite->sectnum,
6232 pPlayer->pos.x, pPlayer->pos.y, pPlayer->pos.z, pPlayer->cursectnum))
6233 {
6234 if (pPlayer->ammo_amount[HANDBOMB_WEAPON] < pPlayer->max_ammo_amount[HANDBOMB_WEAPON] && (!RR || pSprite->pal == 0))
6235 {
6236 if ((g_gametypeFlags[ud.coop] & GAMETYPE_WEAPSTAY) && (RR || pSprite->owner == spriteNum))
6237 {
6238 for (bssize_t j = 0; j < pPlayer->weapreccnt; j++)
6239 {
6240 if (pPlayer->weaprecs[j] == (RR ? spriteNum : pSprite->picnum))
6241 goto next_sprite;
6242 }
6243
6244 if (pPlayer->weapreccnt < MAX_WEAPON_RECS-1)
6245 pPlayer->weaprecs[pPlayer->weapreccnt++] = (RR ? spriteNum : pSprite->picnum);
6246 }
6247
6248 P_AddAmmo(pPlayer, HANDBOMB_WEAPON, 1);
6249 if (RR)
6250 P_AddAmmo(pPlayer, RPG_WEAPON, 1);
6251 A_PlaySound(REALITY ? 167 : DUKE_GET, pPlayer->i);
6252
6253 if ((pPlayer->gotweapon & (1<<HANDBOMB_WEAPON)) == 0 || pSprite->owner == pPlayer->i)
6254 P_AddWeapon(pPlayer, HANDBOMB_WEAPON);
6255
6256 if (sprite[pSprite->owner].picnum != APLAYER)
6257 {
6258 if (REALITY)
6259 P_PalFrom(pPlayer, 32, 0, 0, 32);
6260 else
6261 P_PalFrom(pPlayer, 32, 0, 32, 0);
6262 }
6263
6264 if ((RR && actor[pSprite->owner].picnum != HEAVYHBOMB) || (!RR && pSprite->owner != spriteNum)
6265 || ud.respawn_items == 0)
6266 {
6267 if ((!RR || (pSprite->picnum == HEAVYHBOMB && sprite[pSprite->owner].picnum != APLAYER)) && (RR || pSprite->owner == spriteNum) && (g_gametypeFlags[ud.coop] & GAMETYPE_WEAPSTAY))
6268 goto next_sprite;
6269 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6270 }
6271 else
6272 {
6273 pData[2] = g_itemRespawnTime;
6274 A_Spawn(spriteNum, RESPAWNMARKERRED);
6275 pSprite->cstat = 32768;
6276 }
6277 }
6278 }
6279 }
6280
6281 if (pData[0] < 8)
6282 pData[0]++;
6283
6284 goto next_sprite;
6285 }
6286
6287 case REACTORBURNT__STATIC:
6288 case REACTOR2BURNT__STATIC:
6289 goto next_sprite;
6290
6291 case REACTOR__STATIC:
6292 case REACTOR2__STATIC:
6293 {
6294 if (pData[4] == 1)
6295 {
6296 for (bssize_t SPRITES_OF_SECT(sectNum, j))
6297 {
6298 switch (DYNAMICTILEMAP(sprite[j].picnum))
6299 {
6300 case SECTOREFFECTOR__STATIC:
6301 if (sprite[j].lotag == 1)
6302 {
6303 sprite[j].lotag = 65535u;
6304 sprite[j].hitag = 65535u;
6305 }
6306 break;
6307 case REACTOR__STATIC:
6308 sprite[j].picnum = REACTORBURNT;
6309 break;
6310 case REACTOR2__STATIC:
6311 sprite[j].picnum = REACTOR2BURNT;
6312 break;
6313 case REACTORSPARK__STATIC:
6314 case REACTOR2SPARK__STATIC:
6315 sprite[j].cstat = 32768;
6316 break;
6317 }
6318 }
6319
6320 goto next_sprite;
6321 }
6322
6323 if (pData[1] >= 20)
6324 {
6325 pData[4] = 1;
6326 goto next_sprite;
6327 }
6328
6329 int32_t playerDist;
6330 int playerNum = A_FindPlayer(pSprite, &playerDist);
6331 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
6332
6333 if (++pData[2] == 4)
6334 pData[2] = 0;
6335
6336 if (playerDist < 4096)
6337 {
6338 if ((krand2() & 255) < 16)
6339 {
6340 if (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 168 : DUKE_LONGTERM_PAIN))
6341 A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN, pPlayer->i);
6342
6343 A_PlaySound(REALITY ? 19 : SHORT_CIRCUIT, spriteNum);
6344 sprite[pPlayer->i].extra--;
6345 P_PalFrom(pPlayer, 32, 32, 0, 0);
6346 }
6347
6348 pData[0] += 128;
6349
6350 if (pData[3] == 0)
6351 pData[3] = 1;
6352 }
6353 else pData[3] = 0;
6354
6355 if (pData[1])
6356 {
6357 pData[1]++;
6358 pData[4] = pSprite->z;
6359 pSprite->z = sector[sectNum].floorz - (krand2() % (sector[sectNum].floorz - sector[sectNum].ceilingz));
6360
6361 switch (pData[1])
6362 {
6363 case 3:
6364 // Turn on all of those flashing sectoreffector.
6365 A_RadiusDamage(spriteNum, 4096, g_impactDamage << 2, g_impactDamage << 2, g_impactDamage << 2, g_impactDamage << 2);
6366
6367 for (bssize_t SPRITES_OF(STAT_STANDABLE, j))
6368 {
6369 if (sprite[j].picnum == MASTERSWITCH && sprite[j].hitag == pSprite->hitag && sprite[j].yvel == 0)
6370 sprite[j].yvel = 1;
6371 }
6372 break;
6373
6374 case 4:
6375 case 7:
6376 case 10:
6377 case 15:
6378 for (bssize_t SPRITES_OF_SECT(sectNum, j))
6379 {
6380 if (j != spriteNum)
6381 {
6382 A_DeleteSprite(j);
6383 break;
6384 }
6385 }
6386
6387 break;
6388 }
6389
6390 for (bssize_t x = 0; x < ((REALITY && numplayers > 1) ? 1 : 16); x++)
6391 RANDOMSCRAP(pSprite, spriteNum);
6392
6393 pSprite->z = pData[4];
6394 pData[4] = 0;
6395 }
6396 else if (A_IncurDamage(spriteNum) >= 0)
6397 {
6398 for (bssize_t x = 0; x < ((REALITY && numplayers > 1) ? 1 : 32); x++)
6399 RANDOMSCRAP(pSprite, spriteNum);
6400
6401 if (pSprite->extra < 0)
6402 pData[1] = 1;
6403 }
6404 goto next_sprite;
6405 }
6406
6407 case CAMERA1__STATIC:
6408 if (pData[0] == 0)
6409 {
6410 pData[1]+=8;
6411 if (g_damageCameras)
6412 {
6413 if (A_IncurDamage(spriteNum) >= 0)
6414 {
6415 pData[0] = 1; // static
6416 pSprite->cstat = 32768;
6417
6418 for (bssize_t x = 0; x < 5; x++)
6419 RANDOMSCRAP(pSprite, spriteNum);
6420
6421 goto next_sprite;
6422 }
6423 }
6424
6425 if (pSprite->hitag > 0)
6426 {
6427 if (pData[1] < pSprite->hitag) pSprite->ang += 8;
6428 else if (pData[1] < pSprite->hitag * 3) pSprite->ang -= 8;
6429 else if (pData[1] < (pSprite->hitag << 2)) pSprite->ang += 8;
6430 else
6431 {
6432 pData[1] = 8;
6433 pSprite->ang += 16;
6434 }
6435 }
6436 }
6437 goto next_sprite;
6438 }
6439
6440 if (!g_netServer && ud.multimode < 2 && A_CheckEnemySprite(pSprite))
6441 {
6442 if (g_noEnemies == 1)
6443 {
6444 pSprite->cstat = 32768;
6445 goto next_sprite;
6446 }
6447 else if (g_noEnemies == 2)
6448 {
6449 pSprite->cstat = 257;
6450 }
6451 }
6452
6453 if (deleteAfterExecute && ud.recstat == 2 && g_demo_legacy)
6454 {
6455 A_DeleteSprite(spriteNum);
6456 deleteAfterExecute = 0;
6457 }
6458
6459 if (G_HaveActor(sprite[spriteNum].picnum))
6460 {
6461 int32_t playerDist;
6462 int playerNum = A_FindPlayer(pSprite, &playerDist);
6463 A_Execute(spriteNum, playerNum, playerDist);
6464 }
6465 if (deleteAfterExecute)
6466 A_DeleteSprite(spriteNum);
6467 next_sprite:
6468 spriteNum = nextSprite;
6469 }
6470 }
6471
G_MoveMisc(void)6472 ACTOR_STATIC void G_MoveMisc(void) // STATNUM 5
6473 {
6474 int spriteNum = headspritestat[STAT_MISC];
6475
6476 while (spriteNum >= 0)
6477 {
6478 int const nextSprite = nextspritestat[spriteNum];
6479 int32_t playerDist;
6480 int32_t *const pData = actor[spriteNum].t_data;
6481 spritetype *const pSprite = &sprite[spriteNum];
6482 int sectNum = pSprite->sectnum; // XXX: not const
6483 int switchPic;
6484
6485 if (sectNum < 0 || pSprite->xrepeat == 0)
6486 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6487
6488 Bmemcpy(&actor[spriteNum].bpos, pSprite, sizeof(vec3_t));
6489
6490 switchPic = pSprite->picnum;
6491
6492 if (!RR && pSprite->picnum > NUKEBUTTON && pSprite->picnum <= NUKEBUTTON+3)
6493 switchPic = NUKEBUTTON;
6494
6495 if (pSprite->picnum > GLASSPIECES && pSprite->picnum <= GLASSPIECES+2)
6496 switchPic = GLASSPIECES;
6497
6498 if (pSprite->picnum == INNERJAW+1)
6499 switchPic--;
6500
6501 if ((pSprite->picnum == MONEY+1) || (!RR && (pSprite->picnum == MAIL+1 || pSprite->picnum == PAPER+1)))
6502 {
6503 actor[spriteNum].floorz = pSprite->z = getflorzofslope(pSprite->sectnum,pSprite->x,pSprite->y);
6504 if (RR && sector[pSprite->sectnum].lotag == 800)
6505 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6506 }
6507 else switch (DYNAMICTILEMAP(switchPic))
6508 {
6509
6510 //case APLAYER__STATIC: pSprite->cstat = 32768; goto next_sprite;
6511
6512 case SHOTGUNSPRITE__STATIC:
6513 if (!RR) break;
6514 if (sector[pSprite->sectnum].lotag == 800 && pSprite->z >= sector[pSprite->sectnum].floorz - ZOFFSET3)
6515 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6516 break;
6517
6518 case NEON1__STATIC:
6519 case NEON2__STATIC:
6520 case NEON3__STATIC:
6521 case NEON4__STATIC:
6522 case NEON5__STATIC:
6523 case NEON6__STATIC:
6524 pSprite->shade = ((tabledivide32_noinline(g_globalRandom, pSprite->lotag + 1) & 31) > 4) ? -127 : 127;
6525 goto next_sprite;
6526
6527 case BLOODSPLAT1__STATIC:
6528 case BLOODSPLAT2__STATIC:
6529 case BLOODSPLAT3__STATIC:
6530 case BLOODSPLAT4__STATIC:
6531 if (pData[0] == 7 * GAMETICSPERSEC)
6532 goto next_sprite;
6533
6534 pSprite->z += 16 + (krand2() & 15);
6535
6536 if ((++pData[0] % 9) == 0)
6537 pSprite->yrepeat++;
6538
6539
6540 goto next_sprite;
6541
6542 case NUKEBUTTON__STATIC:
6543 // case NUKEBUTTON+1:
6544 // case NUKEBUTTON+2:
6545 // case NUKEBUTTON+3:
6546
6547 if (RR) break;
6548
6549 // if (REALITY && ud.multimode > 1 && ud.coop == 0 && dukematch_mode != 1)
6550 // goto next_sprite;
6551
6552 if (pData[0])
6553 {
6554 pData[0]++;
6555 if (pData[0] == 8)
6556 pSprite->picnum = NUKEBUTTON + 1;
6557 else if (pData[0] == 16)
6558 {
6559 pSprite->picnum = NUKEBUTTON + 2;
6560 g_player[P_Get(pSprite->owner)].ps->fist_incs = 1;
6561 }
6562 if (g_player[P_Get(pSprite->owner)].ps->fist_incs == GAMETICSPERSEC)
6563 pSprite->picnum = NUKEBUTTON + 3;
6564 }
6565 goto next_sprite;
6566
6567 case FORCESPHERE__STATIC:
6568 {
6569 int forceRepeat = pSprite->xrepeat;
6570 if (pData[1] > 0)
6571 {
6572 pData[1]--;
6573 if (pData[1] == 0)
6574 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6575 }
6576 if (actor[pSprite->owner].t_data[1] == 0)
6577 {
6578 if (pData[0] < 64)
6579 {
6580 pData[0]++;
6581 forceRepeat += 3;
6582 }
6583 }
6584 else if (pData[0] > 64)
6585 {
6586 pData[0]--;
6587 forceRepeat -= 3;
6588 }
6589
6590 *(vec3_t *)pSprite = *(vec3_t *)&sprite[pSprite->owner];
6591 pSprite->ang += actor[pSprite->owner].t_data[0];
6592
6593 forceRepeat = clamp2(forceRepeat, 1, 64);
6594 pSprite->xrepeat = forceRepeat;
6595 pSprite->yrepeat = forceRepeat;
6596 pSprite->shade = (forceRepeat >> 1) - 48;
6597
6598 for (bsize_t j = pData[0]; j > 0; j--)
6599 A_SetSprite(spriteNum, CLIPMASK0);
6600 goto next_sprite;
6601 }
6602
6603 case MUD__STATICRR:
6604 pData[0]++;
6605 if (pData[0] == 1)
6606 {
6607 if (sector[sectNum].floorpicnum != RRTILE3073)
6608 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6609 if (!S_CheckSoundPlaying(spriteNum,ITEM_SPLASH))
6610 A_PlaySound(ITEM_SPLASH,spriteNum);
6611 }
6612 if (pData[0] == 3)
6613 {
6614 pData[0] = 0;
6615 pData[1]++; // WATERSPLASH_T2
6616 }
6617 if (pData[1] == 5)
6618 A_DeleteSprite(spriteNum);
6619 goto next_sprite;
6620
6621 case WATERSPLASH2__STATIC:
6622 pData[0]++;
6623 if (pData[0] == 1)
6624 {
6625 if (sector[sectNum].lotag != ST_1_ABOVE_WATER && sector[sectNum].lotag != ST_2_UNDERWATER)
6626 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6627 /*
6628 else
6629 {
6630 l = getflorzofslope(sect,s->x,s->y)-s->z;
6631 if( l > ZOFFSET2 ) KILLIT(i);
6632 }
6633 else
6634 */
6635 if (!S_CheckSoundPlaying(spriteNum,REALITY ? 20 : ITEM_SPLASH))
6636 A_PlaySound(REALITY ? 20 : ITEM_SPLASH,spriteNum);
6637 }
6638 if (pData[0] == 3)
6639 {
6640 pData[0] = 0;
6641 pData[1]++; // WATERSPLASH_T2
6642 }
6643 if (pData[1] == 5)
6644 A_DeleteSprite(spriteNum);
6645 goto next_sprite;
6646 case FRAMEEFFECT1__STATIC:
6647
6648 if (pSprite->owner >= 0)
6649 {
6650 pData[0]++;
6651
6652 if (pData[0] > 7)
6653 {
6654 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6655 }
6656 else if (pData[0] > 4)
6657 pSprite->cstat |= 512 + 2;
6658 else if (pData[0] > 2)
6659 pSprite->cstat |= 2;
6660 pSprite->xoffset = sprite[pSprite->owner].xoffset;
6661 pSprite->yoffset = sprite[pSprite->owner].yoffset;
6662 }
6663 goto next_sprite;
6664 case INNERJAW__STATIC:
6665 {
6666 // case INNERJAW+1:
6667 int32_t playerDist, playerNum = A_FindPlayer(pSprite,&playerDist);
6668
6669 if (playerDist < 512)
6670 {
6671 P_PalFrom(g_player[playerNum].ps, 32, 32,0,0);
6672 sprite[g_player[playerNum].ps->i].extra -= 4;
6673 }
6674 }
6675 fallthrough__;
6676 case COOLEXPLOSION1__STATIC:
6677 if (!RR && switchPic == COOLEXPLOSION1)
6678 break;
6679 fallthrough__;
6680 case OWHIP__STATICRR:
6681 case UWHIP__STATICRR:
6682 case FIRELASER__STATIC:
6683 if (pSprite->extra != 999)
6684 pSprite->extra = 999;
6685 else DELETE_SPRITE_AND_CONTINUE(spriteNum);
6686 break;
6687 case TONGUE__STATIC:
6688 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6689
6690 case MONEY__STATIC:
6691 case MAIL__STATIC:
6692 case PAPER__STATIC:
6693 {
6694 if (RR && (switchPic == MAIL || switchPic == PAPER))
6695 break;
6696 pSprite->xvel = (krand2()&7)+(sintable[T1(spriteNum)&2047]>>9);
6697 T1(spriteNum) += (krand2()&63);
6698 if ((T1(spriteNum)&2047) > 512 && (T1(spriteNum)&2047) < 1596)
6699 {
6700 if (sector[sectNum].lotag == ST_2_UNDERWATER)
6701 {
6702 if (pSprite->zvel < 64)
6703 pSprite->zvel += (g_spriteGravity>>5)+(krand2()&7);
6704 }
6705 else if (pSprite->zvel < 144)
6706 pSprite->zvel += (g_spriteGravity>>5)+(krand2()&7);
6707 }
6708
6709 A_SetSprite(spriteNum, CLIPMASK0);
6710
6711 if ((krand2()&3) == 0)
6712 setsprite(spriteNum, (vec3_t *) pSprite);
6713
6714 if (pSprite->sectnum == -1)
6715 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6716
6717 int const floorZ = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
6718
6719 if (pSprite->z > floorZ)
6720 {
6721 pSprite->z = floorZ;
6722 A_AddToDeleteQueue(spriteNum);
6723 PN(spriteNum)++;
6724
6725 for (bssize_t SPRITES_OF(STAT_MISC, j))
6726 {
6727 if (sprite[j].picnum == BLOODPOOL && ldist(pSprite, &sprite[j]) < 348)
6728 {
6729 pSprite->pal = 2;
6730 break;
6731 }
6732 }
6733 }
6734
6735
6736 if (RR && sector[pSprite->sectnum].lotag == 800 && pSprite->z >= sector[pSprite->sectnum].floorz - ZOFFSET3)
6737 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6738
6739 break;
6740 }
6741
6742 case HEADJIB1__STATIC:
6743 case ARMJIB1__STATIC:
6744 case LEGJIB1__STATIC:
6745 case LIZMANHEAD1__STATIC:
6746 case LIZMANARM1__STATIC:
6747 case LIZMANLEG1__STATIC:
6748 if (RR) break;
6749 goto jib_code;
6750 case RRTILE2460__STATICRR:
6751 case RRTILE2465__STATICRR:
6752 case BIKEJIBA__STATICRR:
6753 case BIKEJIBB__STATICRR:
6754 case BIKEJIBC__STATICRR:
6755 case BIKERJIBA__STATICRR:
6756 case BIKERJIBB__STATICRR:
6757 case BIKERJIBC__STATICRR:
6758 case BIKERJIBD__STATICRR:
6759 case CHEERJIBA__STATICRR:
6760 case CHEERJIBB__STATICRR:
6761 case CHEERJIBC__STATICRR:
6762 case CHEERJIBD__STATICRR:
6763 case FBOATJIBA__STATICRR:
6764 case FBOATJIBB__STATICRR:
6765 case RABBITJIBA__STATICRR:
6766 case RABBITJIBB__STATICRR:
6767 case RABBITJIBC__STATICRR:
6768 case MAMAJIBA__STATICRR:
6769 case MAMAJIBB__STATICRR:
6770 if (!RRRA) break;
6771 goto jib_code;
6772 case JIBS1__STATIC:
6773 case JIBS2__STATIC:
6774 case JIBS3__STATIC:
6775 case JIBS4__STATIC:
6776 case JIBS5__STATIC:
6777 case JIBS6__STATIC:
6778 case DUKETORSO__STATIC:
6779 case DUKEGUN__STATIC:
6780 case DUKELEG__STATIC:
6781 case BILLYJIBA__STATICRR:
6782 case BILLYJIBB__STATICRR:
6783 case HULKJIBA__STATICRR:
6784 case HULKJIBB__STATICRR:
6785 case HULKJIBC__STATICRR:
6786 case MINJIBA__STATICRR:
6787 case MINJIBB__STATICRR:
6788 case MINJIBC__STATICRR:
6789 case COOTJIBA__STATICRR:
6790 case COOTJIBB__STATICRR:
6791 case COOTJIBC__STATICRR:
6792 jib_code:
6793 {
6794 pSprite->xvel = (pSprite->xvel > 0) ? pSprite->xvel - 1 : 0;
6795
6796 if (!RR)
6797 {
6798 if (pData[5] < (30*10))
6799 pData[5]++;
6800 else
6801 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6802 }
6803
6804 if (pSprite->zvel > 1024 && pSprite->zvel < 1280)
6805 {
6806 setsprite(spriteNum, (vec3_t *) pSprite);
6807 sectNum = pSprite->sectnum;
6808 }
6809
6810 if (RR)
6811 setsprite(spriteNum, (vec3_t * ) pSprite);
6812
6813 int32_t floorZ, ceilZ;
6814 getzsofslope(sectNum, pSprite->x, pSprite->y, &ceilZ, &floorZ);
6815
6816 if (ceilZ == floorZ || sectNum < 0 || sectNum >= MAXSECTORS)
6817 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6818
6819 if (pSprite->z < floorZ-(2<<8))
6820 {
6821 if (pData[1] < 2) pData[1]++;
6822 else if (sector[sectNum].lotag != ST_2_UNDERWATER)
6823 {
6824 pData[1] = 0;
6825
6826 if (pSprite->picnum == DUKELEG || pSprite->picnum == DUKETORSO || pSprite->picnum == DUKEGUN)
6827 {
6828 pData[0] = (pData[0] > 6) ? 0 : pData[0] + 1;
6829 }
6830 else
6831 {
6832 pData[0] = (pData[0] > 2) ? 0 : pData[0] + 1;
6833 }
6834 }
6835
6836 if (pSprite->zvel < 6144)
6837 {
6838 if (sector[sectNum].lotag == ST_2_UNDERWATER)
6839 {
6840 if (pSprite->zvel < 1024)
6841 pSprite->zvel += 48;
6842 else pSprite->zvel = 1024;
6843 }
6844 else pSprite->zvel += g_spriteGravity-50;
6845 }
6846
6847 pSprite->x += (pSprite->xvel*sintable[(pSprite->ang+512)&2047])>>14;
6848 pSprite->y += (pSprite->xvel*sintable[pSprite->ang&2047])>>14;
6849 pSprite->z += pSprite->zvel;
6850
6851 if (RR && pSprite->z >= sector[pSprite->sectnum].floorz)
6852 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6853 }
6854 else
6855 {
6856 if (RRRA || (pSprite->picnum == RRTILE2465 || pSprite->picnum == RRTILE2560))
6857 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6858 if (pData[2] == 0)
6859 {
6860 if (pSprite->sectnum == -1)
6861 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6862
6863 if ((sector[pSprite->sectnum].floorstat&2))
6864 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6865
6866 pData[2]++;
6867 }
6868
6869 floorZ = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
6870 pSprite->z = floorZ - (2 << 8);
6871 pSprite->xvel = 0;
6872
6873 if (pSprite->picnum == JIBS6)
6874 {
6875 pData[1]++;
6876
6877 if ((pData[1]&3) == 0 && pData[0] < 7)
6878 pData[0]++;
6879
6880 if (pData[1] > 20)
6881 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6882 }
6883 else
6884 {
6885 pSprite->picnum = JIBS6;
6886 pData[0] = 0;
6887 pData[1] = 0;
6888 }
6889 }
6890
6891 if (RR && sector[pSprite->sectnum].lotag == 800 && pSprite->z >= sector[pSprite->sectnum].floorz - ZOFFSET3)
6892 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6893 goto next_sprite;
6894 }
6895
6896 case PUKE__STATIC:
6897 if (RR) break;
6898 fallthrough__;
6899 case BLOODPOOL__STATIC:
6900 {
6901 if (pData[0] == 0)
6902 {
6903 pData[0] = 1;
6904 if (sector[sectNum].floorstat&2)
6905 {
6906 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6907 }
6908 else A_AddToDeleteQueue(spriteNum);
6909 }
6910
6911 A_Fall(spriteNum);
6912
6913 int32_t playerDist;
6914 int const playerNum = A_FindPlayer(pSprite, &playerDist);
6915 pSprite->z = actor[spriteNum].floorz - ZOFFSET;
6916
6917 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
6918
6919 if (pData[2] < 32)
6920 {
6921 pData[2]++;
6922
6923 if (actor[spriteNum].picnum == TIRE)
6924 {
6925 if (pSprite->xrepeat < 64 && pSprite->yrepeat < 64)
6926 {
6927 pSprite->xrepeat += krand2()&3;
6928 pSprite->yrepeat += krand2()&3;
6929 }
6930 }
6931 else
6932 {
6933 if (pSprite->xrepeat < 32 && pSprite->yrepeat < 32)
6934 {
6935 pSprite->xrepeat += krand2()&3;
6936 pSprite->yrepeat += krand2()&3;
6937 }
6938 }
6939 }
6940
6941 if (playerDist < 844 && pSprite->xrepeat > 6 && pSprite->yrepeat > 6)
6942 {
6943 if (pSprite->pal == 0 && (krand2()&255) < 16 && (RR || pSprite->picnum != PUKE))
6944 {
6945 if (pPlayer->inv_amount[GET_BOOTS] > 0)
6946 pPlayer->inv_amount[GET_BOOTS]--;
6947 else
6948 {
6949 if (!A_CheckSoundPlaying(pPlayer->i,REALITY ? 168 : DUKE_LONGTERM_PAIN))
6950 A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN,pPlayer->i);
6951
6952 sprite[pPlayer->i].extra --;
6953
6954 P_PalFrom(pPlayer, 32, 16,0,0);
6955 }
6956 }
6957
6958 if (pData[1] == 1) goto next_sprite;
6959
6960 pData[1] = 1;
6961
6962 pPlayer->footprintcount = (actor[spriteNum].picnum == TIRE) ? 10 : 3;
6963 if (REALITY && sprite[spriteNum].picnum == BLOODPOOL && sprite[spriteNum].xrepeat >= 30)
6964 {
6965 if ((krand2()&255) < 16)
6966 A_PlaySound(260, pPlayer->i);
6967 }
6968 pPlayer->footprintpal = pSprite->pal;
6969 pPlayer->footprintshade = pSprite->shade;
6970
6971 if (pData[2] == 32)
6972 {
6973 pSprite->xrepeat -= 6;
6974 pSprite->yrepeat -= 6;
6975 }
6976 }
6977 else pData[1] = 0;
6978
6979 if (RR && sector[pSprite->sectnum].lotag == 800 && pSprite->z >= sector[pSprite->sectnum].floorz - ZOFFSET3)
6980 DELETE_SPRITE_AND_CONTINUE(spriteNum);
6981 goto next_sprite;
6982 }
6983
6984 case EXPLOSION2BOT__STATIC:
6985 if (REALITY) break;
6986 fallthrough__;
6987 case SHRINKEREXPLOSION__STATIC:
6988 case BURNING2__STATIC:
6989 case FECES__STATIC:
6990 case LASERSITE__STATIC:
6991 if (RR) break;
6992 fallthrough__;
6993 case BURNING__STATIC:
6994 case WATERBUBBLE__STATIC:
6995 case SMALLSMOKE__STATIC:
6996 case EXPLOSION2__STATIC:
6997 case EXPLOSION3__STATICRR:
6998 case BLOOD__STATIC:
6999 case FORCERIPPLE__STATIC:
7000 case TRANSPORTERSTAR__STATIC:
7001 case TRANSPORTERBEAM__STATIC:
7002 {
7003 if (!G_HaveActor(sprite[spriteNum].picnum))
7004 goto next_sprite;
7005 int const playerNum = A_FindPlayer(pSprite, &playerDist);
7006 A_Execute(spriteNum, playerNum, playerDist);
7007 goto next_sprite;
7008 }
7009
7010
7011 case SHELL__STATIC:
7012 case SHOTGUNSHELL__STATIC:
7013
7014 A_SetSprite(spriteNum,CLIPMASK0);
7015
7016 if (sectNum < 0 || (!RR && (sector[sectNum].floorz + (24<<8)) < pSprite->z))
7017 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7018
7019 if (sector[sectNum].lotag == ST_2_UNDERWATER)
7020 {
7021 pData[1]++;
7022 if (pData[1] > 8)
7023 {
7024 pData[1] = 0;
7025 pData[0]++;
7026 pData[0] &= 3;
7027 }
7028 if (pSprite->zvel < 128) pSprite->zvel += (g_spriteGravity/13); // 8
7029 else pSprite->zvel -= 64;
7030 if (pSprite->xvel > 0)
7031 pSprite->xvel -= 4;
7032 else pSprite->xvel = 0;
7033 }
7034 else
7035 {
7036 pData[1]++;
7037 if (pData[1] > 3)
7038 {
7039 pData[1] = 0;
7040 pData[0]++;
7041 pData[0] &= 3;
7042 }
7043 if (pSprite->zvel < 512) pSprite->zvel += (g_spriteGravity/3); // 52;
7044 if (!REALITY)
7045 {
7046 if (pSprite->xvel > 0)
7047 pSprite->xvel --;
7048 else
7049 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7050 }
7051 }
7052
7053 goto next_sprite;
7054
7055 case GLASSPIECES__STATIC:
7056 case POPCORN__STATICRR:
7057 // case GLASSPIECES+1:
7058 // case GLASSPIECES+2:
7059
7060 A_Fall(spriteNum);
7061
7062 if (pSprite->zvel > 4096) pSprite->zvel = 4096;
7063 if (sectNum < 0)
7064 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7065
7066 if (pSprite->z == actor[spriteNum].floorz-(ZOFFSET) && pData[0] < 3)
7067 {
7068 pSprite->zvel = -((3-pData[0])<<8)-(krand2()&511);
7069 if (sector[sectNum].lotag == ST_2_UNDERWATER)
7070 pSprite->zvel >>= 1;
7071 pSprite->xrepeat >>= 1;
7072 pSprite->yrepeat >>= 1;
7073 if (rnd(96))
7074 setsprite(spriteNum,(vec3_t *)pSprite);
7075 pData[0]++;//Number of bounces
7076 }
7077 else if (pData[0] == 3)
7078 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7079
7080 if (pSprite->xvel > 0)
7081 {
7082 pSprite->xvel -= 2;
7083 pSprite->cstat = ((pSprite->xvel&3)<<2);
7084 }
7085 else pSprite->xvel = 0;
7086
7087 A_SetSprite(spriteNum,CLIPMASK0);
7088
7089 goto next_sprite;
7090 case DN64TILE3845__STATIC:
7091 if (!REALITY) break;
7092 if (pSprite->extra != 999)
7093 pSprite->extra = 999;
7094 else DELETE_SPRITE_AND_CONTINUE(spriteNum);
7095 break;
7096 case DN64TILE3953__STATIC:
7097 {
7098 if (!REALITY || !G_HaveActor(sprite[spriteNum].picnum))
7099 goto next_sprite;
7100 int const playerNum = A_FindPlayer(pSprite, &playerDist);
7101 A_Execute(spriteNum, playerNum, playerDist);
7102 goto next_sprite;
7103 }
7104 }
7105
7106 if (PN(spriteNum) >= SCRAP6 && PN(spriteNum) <= SCRAP5+3)
7107 {
7108 if (pSprite->xvel > 0)
7109 pSprite->xvel--;
7110 else pSprite->xvel = 0;
7111
7112 if (pSprite->zvel > 1024 && pSprite->zvel < 1280)
7113 {
7114 setsprite(spriteNum,(vec3_t *)pSprite);
7115 sectNum = pSprite->sectnum;
7116 }
7117
7118 if (pSprite->z < sector[sectNum].floorz-(2<<8))
7119 {
7120 if (pData[1] < 1) pData[1]++;
7121 else
7122 {
7123 pData[1] = 0;
7124
7125 if (pSprite->picnum < SCRAP6 + 8)
7126 pData[0] = (pData[0] > 6) ? 0 : pData[0] + 1;
7127 else
7128 pData[0] = (pData[0] > 2) ? 0 : pData[0] + 1;
7129 }
7130 if (pSprite->zvel < 4096)
7131 pSprite->zvel += g_spriteGravity - 50;
7132 pSprite->x += (pSprite->xvel*sintable[(pSprite->ang+512)&2047])>>14;
7133 pSprite->y += (pSprite->xvel*sintable[pSprite->ang&2047])>>14;
7134 pSprite->z += pSprite->zvel;
7135 }
7136 else
7137 {
7138 if (pSprite->picnum == SCRAP1 && pSprite->yvel > 0 && pSprite->yvel < MAXUSERTILES)
7139 {
7140 int32_t j = A_Spawn(spriteNum, pSprite->yvel);
7141
7142 setsprite(j,(vec3_t *)pSprite);
7143 A_GetZLimits(j);
7144 sprite[j].hitag = sprite[j].lotag = 0;
7145 }
7146
7147 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7148 }
7149 goto next_sprite;
7150 }
7151
7152 next_sprite:
7153 spriteNum = nextSprite;
7154 }
7155 }
7156
7157
7158 // i: SE spritenum
HandleSE31(int spriteNum,int setFloorZ,int spriteZ,int SEdir,int zDifference)7159 static void HandleSE31(int spriteNum, int setFloorZ, int spriteZ, int SEdir, int zDifference)
7160 {
7161 const spritetype *pSprite = &sprite[spriteNum];
7162 sectortype *const pSector = §or[sprite[spriteNum].sectnum];
7163 int32_t *const pData = actor[spriteNum].t_data;
7164
7165 if (klabs(pSector->floorz - spriteZ) < SP(spriteNum))
7166 {
7167 if (setFloorZ)
7168 pSector->floorz = spriteZ;
7169
7170 pData[2] = SEdir;
7171 pData[0] = 0;
7172 if (!RR)
7173 pData[3] = pSprite->hitag;
7174
7175 A_CallSound(pSprite->sectnum, spriteNum);
7176 }
7177 else
7178 {
7179 int const zChange = ksgn(zDifference) * SP(spriteNum);
7180
7181 pSector->floorz += zChange;
7182
7183 for (bssize_t SPRITES_OF_SECT(pSprite->sectnum, j))
7184 {
7185 if (sprite[j].picnum == APLAYER && sprite[j].owner >= 0)
7186 {
7187 int const playerNum = P_Get(j);
7188
7189 if (g_player[playerNum].ps->on_ground == 1)
7190 g_player[playerNum].ps->pos.z += zChange;
7191 }
7192
7193 if (sprite[j].zvel == 0 && sprite[j].statnum != STAT_EFFECTOR && (RR || sprite[j].statnum != STAT_PROJECTILE))
7194 {
7195 sprite[j].z += zChange;
7196 actor[j].bpos.z = sprite[j].z;
7197 actor[j].floorz = pSector->floorz;
7198 }
7199 }
7200 }
7201 }
7202
7203 // s: SE sprite
MaybeTrainKillPlayer(const spritetype * pSprite,int const setOPos)7204 static void MaybeTrainKillPlayer(const spritetype *pSprite, int const setOPos)
7205 {
7206 for (bssize_t TRAVERSE_CONNECT(playerNum))
7207 {
7208 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7209
7210 if (sprite[pPlayer->i].extra > 0)
7211 {
7212 int16_t playerSectnum = pPlayer->cursectnum;
7213
7214 updatesector(pPlayer->pos.x, pPlayer->pos.y, &playerSectnum);
7215
7216 if ((playerSectnum == -1 && !ud.noclip) || (pPlayer->cursectnum != pSprite->sectnum && playerSectnum == pSprite->sectnum))
7217 {
7218 *(vec2_t *)pPlayer = *(vec2_t const *)pSprite;
7219
7220 if (setOPos)
7221 *(vec2_t *)&pPlayer->opos = *(vec2_t *)pPlayer;
7222
7223 pPlayer->cursectnum = pSprite->sectnum;
7224
7225 setsprite(pPlayer->i, (vec3_t const *)pSprite);
7226 P_QuickKill(pPlayer);
7227 }
7228 }
7229 }
7230 }
7231
7232 // i: SE spritenum
MaybeTrainKillEnemies(int const spriteNum,int const gutSpawnCnt)7233 static void MaybeTrainKillEnemies(int const spriteNum, int const gutSpawnCnt)
7234 {
7235 int findSprite = headspritesect[sprite[OW(spriteNum)].sectnum];
7236
7237 do
7238 {
7239 int const nextSprite = nextspritesect[findSprite];
7240
7241 if (sprite[findSprite].statnum == STAT_ACTOR && A_CheckEnemySprite(&sprite[findSprite]))
7242 {
7243 int16_t sectNum = sprite[findSprite].sectnum;
7244
7245 updatesector(sprite[findSprite].x,sprite[findSprite].y,§Num);
7246
7247 if (sprite[findSprite].extra >= 0 && sectNum == sprite[spriteNum].sectnum)
7248 {
7249 A_DoGutsDir(findSprite, JIBS6, gutSpawnCnt);
7250 A_PlaySound(REALITY ? 44 :SQUISHED, findSprite);
7251 A_DeleteSprite(findSprite);
7252 }
7253 }
7254
7255 findSprite = nextSprite;
7256 }
7257 while (findSprite >= 0);
7258 }
7259
G_MoveEffectors(void)7260 ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3
7261 {
7262 int32_t q = 0, j, k, l, m, x;
7263 int spriteNum = headspritestat[STAT_EFFECTOR];
7264
7265 for (native_t TRAVERSE_CONNECT(playerNum))
7266 {
7267 vec2_t & fric = g_player[playerNum].ps->fric;
7268 fric.x = fric.y = 0;
7269 }
7270
7271 while (spriteNum >= 0)
7272 {
7273 int const nextSprite = nextspritestat[spriteNum];
7274 spritetype *const pSprite = &sprite[spriteNum];
7275 int32_t playerDist;
7276 int playerNum = A_FindPlayer(pSprite, &playerDist);
7277 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7278
7279 sectortype *const pSector = §or[pSprite->sectnum];
7280 int const spriteLotag = pSprite->lotag;
7281 int const spriteHitag = pSprite->hitag;
7282 int32_t *const pData = &actor[spriteNum].t_data[0];
7283
7284 switch (spriteLotag)
7285 {
7286 case SE_0_ROTATING_SECTOR:
7287 {
7288 int32_t zchange = 0;
7289
7290 j = pSprite->owner;
7291
7292 if ((uint16_t)sprite[j].lotag == UINT16_MAX)
7293 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7294
7295 q = pSector->extra>>3;
7296 l = 0;
7297
7298 if (pSector->lotag == ST_30_ROTATE_RISE_BRIDGE)
7299 {
7300 q >>= 2;
7301
7302 if (sprite[spriteNum].extra == 1)
7303 {
7304 if (actor[spriteNum].tempang < 256)
7305 {
7306 actor[spriteNum].tempang += 4;
7307 if (actor[spriteNum].tempang >= 256)
7308 A_CallSound(pSprite->sectnum,spriteNum);
7309 if (pSprite->clipdist) l = 1;
7310 else l = -1;
7311 }
7312 else actor[spriteNum].tempang = 256;
7313
7314 if (pSector->floorz > pSprite->z) //z's are touching
7315 {
7316 pSector->floorz -= 512;
7317 zchange = -512;
7318 if (pSector->floorz < pSprite->z)
7319 pSector->floorz = pSprite->z;
7320 }
7321 else if (pSector->floorz < pSprite->z) //z's are touching
7322 {
7323 pSector->floorz += 512;
7324 zchange = 512;
7325 if (pSector->floorz > pSprite->z)
7326 pSector->floorz = pSprite->z;
7327 }
7328 }
7329 else if (sprite[spriteNum].extra == 3)
7330 {
7331 if (actor[spriteNum].tempang > 0)
7332 {
7333 actor[spriteNum].tempang -= 4;
7334 if (actor[spriteNum].tempang <= 0)
7335 A_CallSound(pSprite->sectnum,spriteNum);
7336 if (pSprite->clipdist) l = -1;
7337 else l = 1;
7338 }
7339 else actor[spriteNum].tempang = 0;
7340
7341 if (pSector->floorz > T4(spriteNum)) //z's are touching
7342 {
7343 pSector->floorz -= 512;
7344 zchange = -512;
7345 if (pSector->floorz < T4(spriteNum))
7346 pSector->floorz = T4(spriteNum);
7347 }
7348 else if (pSector->floorz < T4(spriteNum)) //z's are touching
7349 {
7350 pSector->floorz += 512;
7351 zchange = 512;
7352 if (pSector->floorz > T4(spriteNum))
7353 pSector->floorz = T4(spriteNum);
7354 }
7355 }
7356 }
7357 else
7358 {
7359 if (actor[j].t_data[0] == 0) break;
7360 if (actor[j].t_data[0] == 2) DELETE_SPRITE_AND_CONTINUE(spriteNum);
7361
7362 l = (sprite[j].ang > 1024) ? -1 : 1;
7363
7364 if (pData[3] == 0)
7365 pData[3] = ldist(pSprite,&sprite[j]);
7366 pSprite->xvel = pData[3];
7367 pSprite->x = sprite[j].x;
7368 pSprite->y = sprite[j].y;
7369 }
7370
7371 pSprite->ang += (l*q);
7372 pData[2] += (l*q);
7373
7374 if (l && (pSector->floorstat&64))
7375 {
7376 for (TRAVERSE_CONNECT(playerNum))
7377 {
7378 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7379
7380 if (pPlayer->cursectnum == pSprite->sectnum && pPlayer->on_ground == 1)
7381 {
7382 pPlayer->q16ang += fix16_from_int(l*q);
7383 pPlayer->q16ang &= 0x7FFFFFF;
7384
7385 pPlayer->pos.z += zchange;
7386
7387 vec2_t r;
7388 rotatepoint(sprite[j].pos.vec2,pPlayer->pos.vec2,(q*l),&r);
7389
7390 pPlayer->bobpos.x += r.x-pPlayer->pos.x;
7391 pPlayer->bobpos.y += r.y-pPlayer->pos.y;
7392
7393 pPlayer->pos.vec2 = r;
7394
7395 if (sprite[pPlayer->i].extra <= 0)
7396 sprite[pPlayer->i].pos.vec2 = r;
7397 }
7398 }
7399
7400 for (bssize_t SPRITES_OF_SECT(pSprite->sectnum, p))
7401 {
7402 // KEEPINSYNC1
7403 if (sprite[p].statnum != STAT_EFFECTOR && sprite[p].statnum != STAT_PROJECTILE)
7404 if (RR || sprite[p].picnum != LASERLINE)
7405 {
7406 if (sprite[p].picnum == APLAYER && sprite[p].owner >= 0)
7407 continue;
7408
7409 sprite[p].ang += (l*q);
7410 sprite[p].ang &= 2047;
7411
7412 sprite[p].z += zchange;
7413
7414 rotatepoint(sprite[j].pos.vec2, sprite[p].pos.vec2, (q * l), &sprite[p].pos.vec2);
7415 }
7416 }
7417
7418 }
7419
7420 A_MoveSector(spriteNum);
7421 }
7422 break;
7423
7424 case SE_1_PIVOT: //Nothing for now used as the pivot
7425 if (pSprite->owner == -1) //Init
7426 {
7427 pSprite->owner = spriteNum;
7428
7429 for (SPRITES_OF(STAT_EFFECTOR, j))
7430 {
7431 if (sprite[j].lotag == SE_19_EXPLOSION_LOWERS_CEILING && sprite[j].hitag == spriteHitag)
7432 {
7433 pData[0] = 0;
7434 break;
7435 }
7436 }
7437 }
7438 break;
7439
7440 case SE_6_SUBWAY:
7441 k = pSector->extra;
7442
7443 if (pData[4] > 0)
7444 {
7445 pData[4]--;
7446 if (pData[4] >= (k-(k>>3)))
7447 pSprite->xvel -= (k>>5);
7448 if (pData[4] > ((k>>1)-1) && pData[4] < (k-(k>>3)))
7449 pSprite->xvel = 0;
7450 if (pData[4] < (k>>1))
7451 pSprite->xvel += (k>>5);
7452 if (pData[4] < ((k>>1)-(k>>3)))
7453 {
7454 pData[4] = 0;
7455 pSprite->xvel = k;
7456 if (RR && (!RRRA || g_lastLevel) && g_hulkSpawn)
7457 {
7458 g_hulkSpawn--;
7459 int newSprite = A_Spawn(spriteNum, HULK);
7460 sprite[newSprite].z = sector[sprite[newSprite].sectnum].ceilingz;
7461 sprite[newSprite].pal = 33;
7462 if (!g_hulkSpawn)
7463 {
7464 newSprite = A_InsertSprite(pSprite->sectnum, pSprite->x, pSprite->y,
7465 sector[pSprite->sectnum].ceilingz + 119428, RRTILE3677, -8, 16, 16, 0, 0, 0, spriteNum, STAT_MISC);
7466 sprite[newSprite].cstat = 514;
7467 sprite[newSprite].pal = 7;
7468 sprite[newSprite].xrepeat = 80;
7469 sprite[newSprite].yrepeat = 255;
7470 newSprite = A_Spawn(spriteNum, RRTILE296);
7471 sprite[newSprite].cstat = 0;
7472 sprite[newSprite].cstat |= 32768;
7473 sprite[newSprite].z = sector[pSprite->sectnum].floorz - 6144;
7474 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7475 }
7476 }
7477 }
7478 }
7479 else
7480 {
7481 pSprite->xvel = k;
7482 if (RR)
7483 {
7484 int otherSprite = headspritesect[pSprite->sectnum];
7485 while (otherSprite >= 0)
7486 {
7487 int const nextOtherSprite = nextspritesect[otherSprite];
7488 if (sprite[otherSprite].picnum == UFOBEAM)
7489 if (g_ufoSpawn)
7490 if (++g_ufoCnt == 64)
7491 {
7492 g_ufoCnt = 0;
7493 g_ufoSpawn--;
7494 int ufoTile = UFO1;
7495 switch (krand2()&3)
7496 {
7497 case 0:
7498 ufoTile = UFO1;
7499 break;
7500 case 1:
7501 ufoTile = UFO2;
7502 break;
7503 case 2:
7504 ufoTile = UFO3;
7505 break;
7506 case 3:
7507 ufoTile = UFO4;
7508 break;
7509 }
7510 if (RRRA)
7511 ufoTile = UFO1;
7512 int const newSprite = A_Spawn(spriteNum, ufoTile);
7513 sprite[newSprite].z = sector[sprite[newSprite].sectnum].ceilingz;
7514 }
7515 otherSprite = nextOtherSprite;
7516 }
7517 }
7518 }
7519
7520 for (SPRITES_OF(STAT_EFFECTOR, j))
7521 {
7522 if (sprite[j].lotag == SE_14_SUBWAY_CAR && spriteHitag == sprite[j].hitag && actor[j].t_data[0] == pData[0])
7523 {
7524 sprite[j].xvel = pSprite->xvel;
7525 // if( t[4] == 1 )
7526 {
7527 if (actor[j].t_data[5] == 0)
7528 actor[j].t_data[5] = dist(&sprite[j],pSprite);
7529 x = ksgn(dist(&sprite[j],pSprite)-actor[j].t_data[5]);
7530 if (sprite[j].extra)
7531 x = -x;
7532 pSprite->xvel += x;
7533 }
7534 actor[j].t_data[4] = pData[4];
7535 }
7536 }
7537 x = 0; // XXX: This assignment is dead?
7538 fallthrough__;
7539
7540 case SE_14_SUBWAY_CAR:
7541 if (pSprite->owner==-1)
7542 pSprite->owner = A_FindLocator((int16_t)pData[3],(int16_t)pData[0]);
7543
7544 if (pSprite->owner == -1)
7545 {
7546 // debugging subway cars (mapping-wise) is freakin annoying
7547 // let's at least have a helpful message...
7548 Bsprintf(tempbuf,"Could not find any locators in sector %d"
7549 " for SE# 6 or 14 with hitag %d.\n", (int)pData[0], (int)pData[3]);
7550 G_GameExit(tempbuf);
7551 }
7552
7553 j = ldist(&sprite[pSprite->owner],pSprite);
7554
7555 if (j < 1024L)
7556 {
7557 if (spriteLotag==SE_6_SUBWAY)
7558 if (sprite[pSprite->owner].hitag&1)
7559 pData[4]=pSector->extra; //Slow it down
7560 pData[3]++;
7561 pSprite->owner = A_FindLocator(pData[3],pData[0]);
7562 if (pSprite->owner==-1)
7563 {
7564 pData[3]=0;
7565 pSprite->owner = A_FindLocator(0,pData[0]);
7566 }
7567 }
7568
7569 if (pSprite->xvel)
7570 {
7571 #ifdef YAX_ENABLE
7572 int32_t firstrun = 1;
7573 #endif
7574 x = getangle(sprite[pSprite->owner].x-pSprite->x,sprite[pSprite->owner].y-pSprite->y);
7575 q = G_GetAngleDelta(pSprite->ang,x)>>3;
7576
7577 pData[2] += q;
7578 pSprite->ang += q;
7579
7580 if (pSprite->xvel == pSector->extra)
7581 {
7582 if (RR)
7583 {
7584 if (!S_CheckSoundPlaying(spriteNum,actor[spriteNum].lastv.x))
7585 A_PlaySound(actor[spriteNum].lastv.x,spriteNum);
7586 }
7587 if (!RR && (pSector->floorstat&1) == 0 && (pSector->ceilingstat&1) == 0)
7588 {
7589 if (!S_CheckSoundPlaying(spriteNum,actor[spriteNum].lastv.x))
7590 A_PlaySound(actor[spriteNum].lastv.x,spriteNum);
7591 }
7592 else if (ud.monsters_off == 0 && pSector->floorpal == 0 && (pSector->floorstat&1) && rnd(8))
7593 {
7594 if (playerDist < 20480)
7595 {
7596 j = pSprite->ang;
7597 pSprite->ang = getangle(pSprite->x-g_player[playerNum].ps->pos.x,pSprite->y-g_player[playerNum].ps->pos.y);
7598 A_Shoot(spriteNum,RPG);
7599 pSprite->ang = j;
7600 }
7601 }
7602 }
7603
7604 if (pSprite->xvel <= 64 && (RR || ((pSector->floorstat&1) == 0 && (pSector->ceilingstat&1) == 0)))
7605 S_StopEnvSound(actor[spriteNum].lastv.x,spriteNum);
7606
7607 if ((pSector->floorz-pSector->ceilingz) < (108<<8))
7608 {
7609 if (ud.noclip == 0 && pSprite->xvel >= 192)
7610 MaybeTrainKillPlayer(pSprite, 0);
7611 }
7612
7613 m = (pSprite->xvel*sintable[(pSprite->ang+512)&2047])>>14;
7614 x = (pSprite->xvel*sintable[pSprite->ang&2047])>>14;
7615
7616 for (TRAVERSE_CONNECT(playerNum))
7617 {
7618 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7619
7620 // might happen when squished into void space
7621 if (pPlayer->cursectnum < 0)
7622 continue;
7623
7624 if (sector[pPlayer->cursectnum].lotag != ST_2_UNDERWATER)
7625 {
7626 if (g_playerSpawnPoints[playerNum].sect == pSprite->sectnum)
7627 {
7628 g_playerSpawnPoints[playerNum].pos.x += m;
7629 g_playerSpawnPoints[playerNum].pos.y += x;
7630 }
7631
7632 if (pSprite->sectnum == sprite[pPlayer->i].sectnum
7633 #ifdef YAX_ENABLE
7634 || (pData[9]>=0 && pData[9] == sprite[pPlayer->i].sectnum)
7635 #endif
7636 )
7637 {
7638 rotatepoint(*(vec2_t *)pSprite, *(vec2_t *)&pPlayer->pos, q, (vec2_t *)&pPlayer->pos);
7639
7640 pPlayer->pos.x += m;
7641 pPlayer->pos.y += x;
7642
7643 pPlayer->bobpos.x += m;
7644 pPlayer->bobpos.y += x;
7645
7646 pPlayer->q16ang += fix16_from_int(q);
7647 pPlayer->q16ang &= 0x7FFFFFF;
7648
7649 if (g_netServer || numplayers > 1)
7650 {
7651 pPlayer->opos.x = pPlayer->pos.x;
7652 pPlayer->opos.y = pPlayer->pos.y;
7653 }
7654 if (sprite[pPlayer->i].extra <= 0)
7655 {
7656 sprite[pPlayer->i].x = pPlayer->pos.x;
7657 sprite[pPlayer->i].y = pPlayer->pos.y;
7658 }
7659 }
7660 }
7661 }
7662
7663 // NOTE: special loop handling
7664 j = headspritesect[pSprite->sectnum];
7665 while (j >= 0)
7666 {
7667 // KEEPINSYNC2
7668 // XXX: underwater check?
7669 if (sprite[j].statnum != STAT_PLAYER && sector[sprite[j].sectnum].lotag != ST_2_UNDERWATER &&
7670 (sprite[j].picnum != SECTOREFFECTOR || (sprite[j].lotag == SE_49_POINT_LIGHT||sprite[j].lotag == SE_50_SPOT_LIGHT))
7671 && sprite[j].picnum != LOCATORS)
7672 {
7673 rotatepoint(pSprite->pos.vec2,sprite[j].pos.vec2,q,&sprite[j].pos.vec2);
7674
7675 sprite[j].x+= m;
7676 sprite[j].y+= x;
7677
7678 sprite[j].ang+=q;
7679
7680 if (g_netServer || numplayers > 1)
7681 {
7682 actor[j].bpos.x = sprite[j].x;
7683 actor[j].bpos.y = sprite[j].y;
7684 }
7685 }
7686 j = nextspritesect[j];
7687 #ifdef YAX_ENABLE
7688 if (j < 0)
7689 {
7690 if (pData[9]>=0 && firstrun)
7691 {
7692 firstrun = 0;
7693 j = headspritesect[pData[9]];
7694 }
7695 }
7696 #endif
7697 }
7698
7699 A_MoveSector(spriteNum);
7700 setsprite(spriteNum,&pSprite->pos);
7701
7702 if ((pSector->floorz-pSector->ceilingz) < (108<<8))
7703 {
7704 if (ud.noclip == 0 && pSprite->xvel >= 192)
7705 MaybeTrainKillPlayer(pSprite, 1);
7706
7707 MaybeTrainKillEnemies(spriteNum, 72);
7708 }
7709 }
7710
7711 break;
7712
7713 case SE_30_TWO_WAY_TRAIN:
7714 if (REALITY)
7715 {
7716 if (pSprite->xvel && pSprite->pal)
7717 if (!S_CheckSoundPlaying(spriteNum,actor[spriteNum].lastv.x))
7718 A_PlaySound(actor[spriteNum].lastv.x,spriteNum);
7719
7720 if (pData[4] == 0 && pSprite->pal)
7721 pData[4] = 300;
7722 }
7723 if (pSprite->owner == -1)
7724 {
7725 pData[3] = !pData[3];
7726 pSprite->owner = A_FindLocator(pData[3],pData[0]);
7727 }
7728 else
7729 {
7730
7731 if (pData[4] == 1) // Starting to go
7732 {
7733 if (ldist(&sprite[pSprite->owner],pSprite) < (2048-128))
7734 pData[4] = 2;
7735 else
7736 {
7737 if (pSprite->xvel == 0 && (!REALITY || pSprite->pal == 0))
7738 G_OperateActivators(pSprite->hitag+(!pData[3]),-1);
7739 if (pSprite->xvel < 256)
7740 pSprite->xvel += 16;
7741 }
7742 }
7743 if (pData[4] == 2)
7744 {
7745 l = FindDistance2D(sprite[pSprite->owner].x-pSprite->x,sprite[pSprite->owner].y-pSprite->y);
7746
7747 if (l <= 128)
7748 pSprite->xvel = 0;
7749
7750 if (pSprite->xvel > 0)
7751 pSprite->xvel -= 16;
7752 else
7753 {
7754 pSprite->xvel = 0;
7755 if (!REALITY || pSprite->pal == 0)
7756 G_OperateActivators(pSprite->hitag+(int16_t)pData[3],-1);
7757 pSprite->owner = -1;
7758 pSprite->ang += 1024;
7759 pData[4] = 0;
7760 if (!REALITY || pSprite->pal == 0)
7761 G_OperateForceFields(spriteNum,pSprite->hitag);
7762
7763 for (SPRITES_OF_SECT(pSprite->sectnum, j))
7764 {
7765 if (sprite[j].picnum != SECTOREFFECTOR && sprite[j].picnum != LOCATORS)
7766 {
7767 actor[j].bpos.x = sprite[j].x;
7768 actor[j].bpos.y = sprite[j].y;
7769 }
7770 }
7771
7772 }
7773 }
7774 if (REALITY && pData[4] > 10)
7775 {
7776 if (--pData[4] == 10)
7777 pData[4] = 1;
7778 }
7779 }
7780
7781 if (pSprite->xvel)
7782 {
7783 l = (pSprite->xvel*sintable[(pSprite->ang+512)&2047])>>14;
7784 x = (pSprite->xvel*sintable[pSprite->ang&2047])>>14;
7785
7786 if ((pSector->floorz-pSector->ceilingz) < (108<<8))
7787 if (ud.noclip == 0)
7788 MaybeTrainKillPlayer(pSprite, 0);
7789
7790 for (int TRAVERSE_CONNECT(playerNum))
7791 {
7792 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7793
7794 if (sprite[pPlayer->i].sectnum == pSprite->sectnum)
7795 {
7796 pPlayer->pos.x += l;
7797 pPlayer->pos.y += x;
7798
7799 if (g_netServer || numplayers > 1)
7800 {
7801 pPlayer->opos.x = pPlayer->pos.x;
7802 pPlayer->opos.y = pPlayer->pos.y;
7803 }
7804
7805 pPlayer->bobpos.x += l;
7806 pPlayer->bobpos.y += x;
7807 }
7808
7809 if (g_playerSpawnPoints[playerNum].sect == pSprite->sectnum)
7810 {
7811 g_playerSpawnPoints[playerNum].pos.x += l;
7812 g_playerSpawnPoints[playerNum].pos.y += x;
7813 }
7814 }
7815
7816 for (SPRITES_OF_SECT(pSprite->sectnum, j))
7817 {
7818 // TODO: replace some checks for SE 49/50 with statnum LIGHT instead?
7819 if ((sprite[j].picnum != SECTOREFFECTOR || sprite[j].lotag==SE_49_POINT_LIGHT || sprite[j].lotag==SE_50_SPOT_LIGHT)
7820 && sprite[j].picnum != LOCATORS)
7821 {
7822 if (numplayers < 2 && !g_netServer)
7823 {
7824 actor[j].bpos.x = sprite[j].x;
7825 actor[j].bpos.y = sprite[j].y;
7826 }
7827
7828 sprite[j].x += l;
7829 sprite[j].y += x;
7830
7831 if (g_netServer || numplayers > 1)
7832 {
7833 actor[j].bpos.x = sprite[j].x;
7834 actor[j].bpos.y = sprite[j].y;
7835 }
7836 }
7837 }
7838
7839 A_MoveSector(spriteNum);
7840 setsprite(spriteNum,(vec3_t *)pSprite);
7841
7842 if (pSector->floorz-pSector->ceilingz < (108<<8))
7843 {
7844 if (ud.noclip == 0)
7845 MaybeTrainKillPlayer(pSprite, 1);
7846
7847 MaybeTrainKillEnemies(spriteNum, 24);
7848 }
7849 }
7850
7851 break;
7852
7853
7854 case SE_2_EARTHQUAKE://Quakes
7855 if (pData[4] > 0 && pData[0] == 0)
7856 {
7857 if (pData[4] < spriteHitag)
7858 pData[4]++;
7859 else pData[0] = 1;
7860 }
7861
7862 if (pData[0] > 0)
7863 {
7864 pData[0]++;
7865
7866 pSprite->xvel = 3;
7867
7868 if (pData[0] > 96)
7869 {
7870 pData[0] = -1; //Stop the quake
7871 pData[4] = -1;
7872 DELETE_SPRITE_AND_CONTINUE(spriteNum);
7873 }
7874 else
7875 {
7876 if ((pData[0]&31) == 8)
7877 {
7878 g_earthquakeTime = 48;
7879 A_PlaySound(REALITY ? 54 : EARTHQUAKE,g_player[screenpeek].ps->i);
7880 }
7881
7882 pSector->floorheinum = (klabs(pSector->floorheinum - pData[5]) < 8)
7883 ? pData[5]
7884 : pSector->floorheinum + (ksgn(pData[5] - pSector->floorheinum) << 4);
7885 }
7886
7887 if (REALITY)
7888 break;
7889
7890 vec2_t const vect = { (pSprite->xvel * sintable[(pSprite->ang + 512) & 2047]) >> 14,
7891 (pSprite->xvel * sintable[pSprite->ang & 2047]) >> 14 };
7892
7893 for (TRAVERSE_CONNECT(playerNum))
7894 {
7895 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7896
7897 if (pPlayer->cursectnum == pSprite->sectnum && pPlayer->on_ground)
7898 {
7899 pPlayer->pos.x += vect.x;
7900 pPlayer->pos.y += vect.y;
7901
7902 pPlayer->bobpos.x += vect.x;
7903 pPlayer->bobpos.y += vect.y;
7904 }
7905 }
7906
7907 for (bssize_t nextSprite, SPRITES_OF_SECT_SAFE(pSprite->sectnum, sectSprite, nextSprite))
7908 {
7909 if (sprite[sectSprite].picnum != SECTOREFFECTOR)
7910 {
7911 sprite[sectSprite].x+=vect.x;
7912 sprite[sectSprite].y+=vect.y;
7913 setsprite(sectSprite,(vec3_t *)&sprite[sectSprite]);
7914 }
7915 }
7916
7917 A_MoveSector(spriteNum);
7918 setsprite(spriteNum,(vec3_t *)pSprite);
7919 }
7920 break;
7921
7922 //Flashing sector lights after reactor EXPLOSION2
7923
7924 case SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT:
7925 {
7926 if (pData[4] == 0) break;
7927
7928 // if(t[5] > 0) { t[5]--; break; }
7929
7930 if ((tabledivide32_noinline(g_globalRandom, spriteHitag+1)&31) < 4 && !pData[2])
7931 {
7932 // t[5] = 4+(g_globalRandom&7);
7933 pSector->ceilingpal = pSprite->owner >> 8;
7934 pSector->floorpal = pSprite->owner & 0xff;
7935 pData[0] = pSprite->shade + (g_globalRandom & 15);
7936 }
7937 else
7938 {
7939 // t[5] = 4+(g_globalRandom&3);
7940 pSector->ceilingpal = pSprite->pal;
7941 pSector->floorpal = pSprite->pal;
7942 pData[0] = pData[3];
7943 }
7944
7945 pSector->ceilingshade = pData[0];
7946 pSector->floorshade = pData[0];
7947
7948 walltype *pWall = &wall[pSector->wallptr];
7949
7950 for (x=pSector->wallnum; x > 0; x--,pWall++)
7951 {
7952 if (pWall->hitag != 1)
7953 {
7954 pWall->shade = pData[0];
7955
7956 if ((pWall->cstat & 2) && pWall->nextwall >= 0)
7957 wall[pWall->nextwall].shade = pWall->shade;
7958 }
7959 }
7960
7961 break;
7962 }
7963
7964 case SE_4_RANDOM_LIGHTS:
7965 {
7966 // See A_Spawn():
7967 // s->owner: original ((ceilingpal<<8) | floorpal)
7968 // t[2]: original floor shade
7969 // t[3]: max wall shade
7970 int lightFlag;
7971
7972 if ((tabledivide32_noinline(g_globalRandom, spriteHitag+1)&31) < 4)
7973 {
7974 pData[1] = pSprite->shade + (g_globalRandom & 15); // Got really bright
7975 pData[0] = pSprite->shade + (g_globalRandom & 15);
7976 pSector->ceilingpal = pSprite->owner >> 8;
7977 pSector->floorpal = pSprite->owner & 0xff;
7978 lightFlag = 1;
7979 }
7980 else
7981 {
7982 pData[1] = pData[2];
7983 pData[0] = pData[3];
7984
7985 pSector->ceilingpal = pSprite->pal;
7986 pSector->floorpal = pSprite->pal;
7987
7988 lightFlag = 0;
7989 }
7990
7991 pSector->floorshade = pData[1];
7992 pSector->ceilingshade = pData[1];
7993
7994 walltype *pWall = &wall[pSector->wallptr];
7995
7996 for (x=pSector->wallnum; x > 0; x--,pWall++)
7997 {
7998 if (lightFlag) pWall->pal = (pSprite->owner&0xff);
7999 else pWall->pal = pSprite->pal;
8000
8001 if (pWall->hitag != 1)
8002 {
8003 pWall->shade = pData[0];
8004 if ((pWall->cstat&2) && pWall->nextwall >= 0)
8005 wall[pWall->nextwall].shade = pWall->shade;
8006 }
8007 }
8008
8009 for (bssize_t SPRITES_OF_SECT(SECT(spriteNum), sectSprite))
8010 {
8011 if (sprite[sectSprite].cstat&16)
8012 sprite[sectSprite].shade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
8013 }
8014
8015 if (pData[4])
8016 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8017
8018 break;
8019 }
8020
8021 //BOSS
8022 case SE_5:
8023 {
8024 if (REALITY) break;
8025 if (playerDist < 8192)
8026 {
8027 int const saveAng = pSprite->ang;
8028 pSprite->ang = getangle(pSprite->x - pPlayer->pos.x, pSprite->y - pPlayer->pos.y);
8029 A_Shoot(spriteNum, FIRELASER);
8030 pSprite->ang = saveAng;
8031 }
8032
8033 if (pSprite->owner==-1) //Start search
8034 {
8035 pData[4] = 0;
8036 int closestLocatorDist = INT32_MAX;
8037 int closestLocator = pSprite->owner;
8038
8039 //Find the shortest dist
8040 do
8041 {
8042 pSprite->owner = A_FindLocator((int16_t)pData[4], -1); // t[0] hold sectnum
8043
8044 if (pSprite->owner == -1)
8045 break;
8046
8047 int const locatorDist = ldist(&sprite[pPlayer->i],&sprite[pSprite->owner]);
8048
8049 if (closestLocatorDist > locatorDist)
8050 {
8051 closestLocator = pSprite->owner;
8052 closestLocatorDist = locatorDist;
8053 }
8054
8055 pData[4]++;
8056 }
8057 while (1);
8058
8059 pSprite->owner = closestLocator;
8060 pSprite->zvel = ksgn(sprite[closestLocator].z - pSprite->z) << 4;
8061 }
8062
8063 if (ldist(&sprite[pSprite->owner],pSprite) < 1024)
8064 {
8065 pSprite->owner = -1;
8066 goto next_sprite;
8067 }
8068 else pSprite->xvel=256;
8069
8070 int const angInc = G_GetAngleDelta(pSprite->ang, getangle(sprite[pSprite->owner].x-pSprite->x,
8071 sprite[pSprite->owner].y-pSprite->y))>>3;
8072 pSprite->ang += angInc;
8073
8074 if (rnd(32))
8075 {
8076 pData[2] += angInc;
8077 pSector->ceilingshade = 127;
8078 }
8079 else
8080 {
8081 pData[2] += G_GetAngleDelta(pData[2] + 512, getangle(pPlayer->pos.x - pSprite->x, pPlayer->pos.y - pSprite->y)) >> 2;
8082 pSector->ceilingshade = 0;
8083 }
8084
8085 if (A_IncurDamage(spriteNum) >= 0)
8086 {
8087 if (++pData[3] == 5)
8088 {
8089 pSprite->zvel += 1024;
8090 P_DoQuote(QUOTE_WASTED, g_player[myconnectindex].ps);
8091 }
8092 }
8093
8094 pSprite->z += pSprite->zvel;
8095 pSector->ceilingz += pSprite->zvel;
8096 sector[pData[0]].ceilingz += pSprite->zvel;
8097
8098 A_MoveSector(spriteNum);
8099 setsprite(spriteNum, (vec3_t *)pSprite);
8100 break;
8101 }
8102
8103 case SE_8_UP_OPEN_DOOR_LIGHTS:
8104 case SE_9_DOWN_OPEN_DOOR_LIGHTS:
8105 {
8106
8107 // work only if its moving
8108
8109 int animGoal = -1;
8110
8111 if (actor[spriteNum].t_data[4])
8112 {
8113 if (++actor[spriteNum].t_data[4] > 8)
8114 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8115
8116 animGoal = 1;
8117 }
8118 else animGoal = GetAnimationGoal(&pSector->ceilingz);
8119
8120 if (animGoal >= 0)
8121 {
8122 int shadeInc = ((pSector->lotag & 0x8000u) || actor[spriteNum].t_data[4]) ? -pData[3] : pData[3];
8123
8124 if (spriteLotag == SE_9_DOWN_OPEN_DOOR_LIGHTS)
8125 shadeInc = -shadeInc;
8126
8127 for (bssize_t SPRITES_OF(STAT_EFFECTOR, sectorEffector))
8128 {
8129 if (sprite[sectorEffector].lotag == spriteLotag && sprite[sectorEffector].hitag == spriteHitag)
8130 {
8131 int const sectNum = sprite[sectorEffector].sectnum;
8132 int const spriteShade = sprite[sectorEffector].shade;
8133
8134 walltype *pWall = &wall[sector[sectNum].wallptr];
8135
8136 for (bsize_t l=sector[sectNum].wallnum; l>0; l--, pWall++)
8137 {
8138 if (pWall->hitag == 1)
8139 continue;
8140
8141 pWall->shade += shadeInc;
8142
8143 if (pWall->shade < spriteShade)
8144 pWall->shade = spriteShade;
8145 else if (pWall->shade > actor[sectorEffector].t_data[2])
8146 pWall->shade = actor[sectorEffector].t_data[2];
8147
8148 if (pWall->nextwall >= 0 && wall[pWall->nextwall].hitag != 1)
8149 wall[pWall->nextwall].shade = pWall->shade;
8150 }
8151
8152 sector[sectNum].floorshade += shadeInc;
8153 sector[sectNum].ceilingshade += shadeInc;
8154
8155 if (sector[sectNum].floorshade < spriteShade)
8156 sector[sectNum].floorshade = spriteShade;
8157 else if (sector[sectNum].floorshade > actor[sectorEffector].t_data[0])
8158 sector[sectNum].floorshade = actor[sectorEffector].t_data[0];
8159
8160 if (sector[sectNum].ceilingshade < spriteShade)
8161 sector[sectNum].ceilingshade = spriteShade;
8162 else if (sector[sectNum].ceilingshade > actor[sectorEffector].t_data[1])
8163 sector[sectNum].ceilingshade = actor[sectorEffector].t_data[1];
8164
8165 if (RR && sector[sectNum].hitag == 1)
8166 sector[sectNum].ceilingshade = actor[sectorEffector].t_data[1];
8167 }
8168 }
8169 }
8170 break;
8171 }
8172
8173 case SE_10_DOOR_AUTO_CLOSE:
8174 // XXX: 32791, what the hell?
8175 if ((pSector->lotag&0xff) == ST_27_STRETCH_BRIDGE || (pSector->floorz > pSector->ceilingz && (pSector->lotag&0xff) != ST_23_SWINGING_DOOR) || pSector->lotag == (int16_t)32791u)
8176 {
8177 j = 1;
8178
8179 if ((pSector->lotag&0xff) != ST_27_STRETCH_BRIDGE)
8180 for (bssize_t TRAVERSE_CONNECT(playerNum))
8181 if (pSector->lotag != ST_30_ROTATE_RISE_BRIDGE && pSector->lotag != ST_31_TWO_WAY_TRAIN && pSector->lotag != 0
8182 && pSprite->sectnum == sprite[g_player[playerNum].ps->i].sectnum)
8183 j = 0;
8184
8185 if (j == 1)
8186 {
8187 if (pData[0] > spriteHitag)
8188 switch (sector[pSprite->sectnum].lotag)
8189 {
8190 case ST_20_CEILING_DOOR:
8191 case ST_21_FLOOR_DOOR:
8192 case ST_22_SPLITTING_DOOR:
8193 case ST_26_SPLITTING_ST_DOOR:
8194 if (!RR && GetAnimationGoal(§or[pSprite->sectnum].ceilingz) >= 0)
8195 break;
8196 fallthrough__;
8197 default:
8198 G_ActivateBySector(pSprite->sectnum,spriteNum);
8199 pData[0] = 0;
8200 break;
8201 }
8202 else pData[0]++;
8203 }
8204 }
8205 else pData[0]=0;
8206 break;
8207
8208 case SE_11_SWINGING_DOOR: //Swingdoor
8209
8210 if (pData[5] > 0)
8211 {
8212 pData[5]--;
8213 break;
8214 }
8215
8216 if (pData[4])
8217 {
8218 int const endWall = pSector->wallptr+pSector->wallnum;
8219
8220 l = (SP(spriteNum) >> 3) * pData[3];
8221 for (j=pSector->wallptr; j<endWall; j++)
8222 {
8223 for (SPRITES_OF(STAT_ACTOR, k))
8224 {
8225 if (sprite[k].extra > 0 && A_CheckEnemySprite(&sprite[k])
8226 && clipinsidebox((vec2_t *)&sprite[k], j, 256) == 1)
8227 goto next_sprite;
8228 }
8229 for (SPRITES_OF(STAT_PLAYER, k))
8230 {
8231 if (sprite[k].owner >= 0 && clipinsidebox((vec2_t *)&sprite[k], j, 144) == 1)
8232 {
8233 pData[5] = 8; // Delay
8234 pData[2] -= l;
8235 pData[4] -= l;
8236 A_MoveSector(spriteNum);
8237 setsprite(spriteNum, (vec3_t *)pSprite);
8238 goto next_sprite;
8239 }
8240 }
8241 }
8242
8243 pData[2] += l;
8244 pData[4] += l;
8245 A_MoveSector(spriteNum);
8246 setsprite(spriteNum, (vec3_t *)pSprite);
8247
8248 if (pData[4] <= -511 || pData[4] >= 512)
8249 {
8250 pData[4] = 0;
8251 pData[2] &= 0xffffff00;
8252 A_MoveSector(spriteNum);
8253 setsprite(spriteNum, (vec3_t *) pSprite);
8254 break;
8255 }
8256 }
8257 break;
8258
8259 case SE_12_LIGHT_SWITCH:
8260 if (pData[0] == 3 || pData[3] == 1) //Lights going off
8261 {
8262 pSector->floorpal = 0;
8263 pSector->ceilingpal = 0;
8264
8265 walltype *pWall = &wall[pSector->wallptr];
8266
8267 for (j = pSector->wallnum; j > 0; j--, pWall++)
8268 {
8269 if (pWall->hitag != 1)
8270 {
8271 pWall->shade = pData[1];
8272 pWall->pal = 0;
8273 }
8274 }
8275
8276 pSector->floorshade = pData[1];
8277 pSector->ceilingshade = pData[2];
8278 pData[0] = 0;
8279
8280 for (SPRITES_OF_SECT(SECT(spriteNum), j))
8281 {
8282 if (sprite[j].cstat & 16)
8283 sprite[j].shade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
8284 }
8285
8286 if (pData[3] == 1)
8287 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8288 }
8289
8290 if (pData[0] == 1) //Lights flickering on
8291 {
8292 if (pSector->floorshade > pSprite->shade)
8293 {
8294 pSector->floorpal = pSprite->pal;
8295 pSector->ceilingpal = pSprite->pal;
8296
8297 pSector->floorshade -= 2;
8298 pSector->ceilingshade -= 2;
8299
8300 walltype *pWall = &wall[pSector->wallptr];
8301 for (j = pSector->wallnum; j > 0; j--, pWall++)
8302 {
8303 if (pWall->hitag != 1)
8304 {
8305 pWall->pal = pSprite->pal;
8306 pWall->shade -= 2;
8307 }
8308 }
8309 }
8310 else pData[0] = 2;
8311
8312 for (SPRITES_OF_SECT(SECT(spriteNum), j))
8313 {
8314 if (sprite[j].cstat&16)
8315 {
8316 if (sprite[j].cstat & 16)
8317 sprite[j].shade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
8318 }
8319 }
8320 }
8321 break;
8322
8323 case 47:
8324 if (!RRRA)
8325 break;
8326 if (pData[0] == 3 || pData[3] == 1) //Lights going off
8327 {
8328 pSector->floorpal = 0;
8329 pSector->ceilingpal = 0;
8330
8331 walltype *pWall = &wall[pSector->wallptr];
8332
8333 for (j = pSector->wallnum; j > 0; j--, pWall++)
8334 {
8335 if (pWall->hitag != 1)
8336 {
8337 pWall->shade = pData[1];
8338 pWall->pal = 0;
8339 }
8340 }
8341
8342 pSector->floorshade = pData[1];
8343 pSector->ceilingshade = pData[2];
8344 pData[0] = 0;
8345
8346 for (SPRITES_OF_SECT(SECT(spriteNum), j))
8347 {
8348 if (sprite[j].cstat & 16)
8349 sprite[j].shade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
8350 }
8351
8352 if (pData[3] == 1)
8353 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8354 }
8355
8356 if (pData[0] == 1) //Lights flickering on
8357 {
8358 if (pSector->floorshade > pSprite->shade)
8359 {
8360 pSector->floorpal = pSprite->pal;
8361
8362 pSector->floorshade -= 2;
8363
8364 walltype *pWall = &wall[pSector->wallptr];
8365 for (j = pSector->wallnum; j > 0; j--, pWall++)
8366 {
8367 if (pWall->hitag != 1)
8368 {
8369 pWall->pal = pSprite->pal;
8370 pWall->shade -= 2;
8371 }
8372 }
8373 }
8374 else pData[0] = 2;
8375
8376 for (SPRITES_OF_SECT(SECT(spriteNum), j))
8377 {
8378 if (sprite[j].cstat&16)
8379 {
8380 if (sprite[j].cstat & 16)
8381 sprite[j].shade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
8382 }
8383 }
8384 }
8385 break;
8386
8387 case 48:
8388 if (!RRRA)
8389 break;
8390 if (pData[0] == 3 || pData[3] == 1) //Lights going off
8391 {
8392 pSector->floorpal = 0;
8393 pSector->ceilingpal = 0;
8394
8395 walltype *pWall = &wall[pSector->wallptr];
8396
8397 for (j = pSector->wallnum; j > 0; j--, pWall++)
8398 {
8399 if (pWall->hitag != 1)
8400 {
8401 pWall->shade = pData[1];
8402 pWall->pal = 0;
8403 }
8404 }
8405
8406 pSector->floorshade = pData[1];
8407 pSector->ceilingshade = pData[2];
8408 pData[0] = 0;
8409
8410 for (SPRITES_OF_SECT(SECT(spriteNum), j))
8411 {
8412 if (sprite[j].cstat & 16)
8413 sprite[j].shade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
8414 }
8415
8416 if (pData[3] == 1)
8417 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8418 }
8419
8420 if (pData[0] == 1) //Lights flickering on
8421 {
8422 if (pSector->ceilingshade > pSprite->shade)
8423 {
8424 pSector->ceilingpal = pSprite->pal;
8425
8426 pSector->ceilingshade -= 2;
8427
8428 walltype *pWall = &wall[pSector->wallptr];
8429 for (j = pSector->wallnum; j > 0; j--, pWall++)
8430 {
8431 if (pWall->hitag != 1)
8432 {
8433 pWall->pal = pSprite->pal;
8434 pWall->shade -= 2;
8435 }
8436 }
8437 }
8438 else pData[0] = 2;
8439
8440 for (SPRITES_OF_SECT(SECT(spriteNum), j))
8441 {
8442 if (sprite[j].cstat&16)
8443 sprite[j].shade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
8444 }
8445 }
8446 break;
8447
8448
8449 case SE_13_EXPLOSIVE:
8450 if (pData[2])
8451 {
8452 // t[0]: ceiling z
8453 // t[1]: floor z
8454 // s->owner: 1 if affect ceiling, 0 if affect floor
8455 // t[3]: 1 if ceiling was parallaxed at premap, 0 else
8456
8457 j = (SP(spriteNum)<<5)|1;
8458
8459 if (pSprite->ang == 512)
8460 {
8461 if (pSprite->owner)
8462 {
8463 pSector->ceilingz = (klabs(pData[0] - pSector->ceilingz) >= j)
8464 ? pSector->ceilingz + ksgn(pData[0] - pSector->ceilingz) * j
8465 : pData[0];
8466 }
8467 else
8468 {
8469 pSector->floorz = (klabs(pData[1] - pSector->floorz) >= j)
8470 ? pSector->floorz + ksgn(pData[1] - pSector->floorz) * j
8471 : pData[1];
8472 }
8473 }
8474 else
8475 {
8476 pSector->floorz = (klabs(pData[1] - pSector->floorz) >= j)
8477 ? pSector->floorz + ksgn(pData[1] - pSector->floorz) * j
8478 : pData[1];
8479
8480 pSector->ceilingz = /*(klabs(pData[0] - pSector->ceilingz) >= j)
8481 ? pSector->ceilingz + ksgn(pData[0] - pSector->ceilingz) * j
8482 : */pData[0];
8483 }
8484 #ifdef YAX_ENABLE
8485 if (pSprite->ang == 512)
8486 {
8487 int16_t cf=!pSprite->owner, bn=yax_getbunch(pSector-sector, cf);
8488 int32_t jj, daz=SECTORFLD(pSector-sector,z, cf);
8489
8490 if (bn >= 0)
8491 {
8492 for (SECTORS_OF_BUNCH(bn, cf, jj))
8493 {
8494 SECTORFLD(jj,z, cf) = daz;
8495 SECTORFLD(jj,stat, cf) &= ~(128+256 + 512+2048);
8496 }
8497 for (SECTORS_OF_BUNCH(bn, !cf, jj))
8498 {
8499 SECTORFLD(jj,z, !cf) = daz;
8500 SECTORFLD(jj,stat, !cf) &= ~(128+256 + 512+2048);
8501 }
8502 }
8503 }
8504 #endif
8505 if (pData[3] == 1)
8506 {
8507 //Change the shades
8508
8509 pData[3]++;
8510 pSector->ceilingstat ^= 1;
8511
8512 if (pSprite->ang == 512)
8513 {
8514 walltype *pWall = &wall[pSector->wallptr];
8515
8516 for (j = pSector->wallnum; j > 0; j--, pWall++)
8517 pWall->shade = pSprite->shade;
8518
8519 pSector->floorshade = pSprite->shade;
8520
8521 if (!REALITY && g_player[0].ps->one_parallax_sectnum >= 0)
8522 {
8523 pSector->ceilingpicnum = sector[g_player[0].ps->one_parallax_sectnum].ceilingpicnum;
8524 pSector->ceilingshade = sector[g_player[0].ps->one_parallax_sectnum].ceilingshade;
8525 }
8526 }
8527 }
8528
8529 if (++pData[2] > 256)
8530 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8531 }
8532
8533 if (pData[2] == 4 && pSprite->ang != 512)
8534 for (x=0; x<7; x++) RANDOMSCRAP(pSprite, spriteNum);
8535 break;
8536
8537
8538 case SE_15_SLIDING_DOOR:
8539
8540 if (pData[4])
8541 {
8542 pSprite->xvel = 16;
8543
8544 if (pData[4] == 1) //Opening
8545 {
8546 if (pData[3] >= (SP(spriteNum)>>3))
8547 {
8548 pData[4] = 0; //Turn off the sliders
8549 A_CallSound(pSprite->sectnum,spriteNum);
8550 break;
8551 }
8552 pData[3]++;
8553 }
8554 else if (pData[4] == 2)
8555 {
8556 if (pData[3]<1)
8557 {
8558 pData[4] = 0;
8559 A_CallSound(pSprite->sectnum,spriteNum);
8560 break;
8561 }
8562 pData[3]--;
8563 }
8564
8565 A_MoveSector(spriteNum);
8566 setsprite(spriteNum,(vec3_t *)pSprite);
8567 }
8568 break;
8569
8570 case SE_16_REACTOR: //Reactor
8571
8572 pData[2]+=32;
8573
8574 if (pSector->floorz < pSector->ceilingz)
8575 pSprite->shade = 0;
8576 else if (pSector->ceilingz < pData[3])
8577 {
8578 //The following code check to see if
8579 //there is any other sprites in the sector.
8580 //If there isn't, then kill this sectoreffector
8581 //itself.....
8582
8583 for (SPRITES_OF_SECT(pSprite->sectnum, j))
8584 {
8585 if (sprite[j].picnum == REACTOR || sprite[j].picnum == REACTOR2)
8586 break;
8587 }
8588
8589 if (j == -1)
8590 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8591
8592 pSprite->shade = 1;
8593 }
8594
8595 pSector->ceilingz = (pSprite->shade)
8596 ? pSector->ceilingz + 1024
8597 : pSector->ceilingz - 512;
8598
8599 A_MoveSector(spriteNum);
8600 setsprite(spriteNum,(vec3_t *)pSprite);
8601
8602 break;
8603
8604 case SE_17_WARP_ELEVATOR:
8605 {
8606 int32_t nextk;
8607
8608 q = pData[0]*(SP(spriteNum)<<2);
8609
8610 pSector->ceilingz += q;
8611 pSector->floorz += q;
8612
8613 for (SPRITES_OF_SECT(pSprite->sectnum, j))
8614 {
8615 if (sprite[j].statnum == STAT_PLAYER && sprite[j].owner >= 0)
8616 {
8617 int const warpPlayer = P_Get(j);
8618 DukePlayer_t *const pPlayer = g_player[warpPlayer].ps;
8619
8620 if (numplayers < 2 && !g_netServer)
8621 pPlayer->opos.z = pPlayer->pos.z;
8622
8623 pPlayer->pos.z += q;
8624 pPlayer->truefz += q;
8625 pPlayer->truecz += q;
8626
8627 if (g_netServer || numplayers > 1)
8628 pPlayer->opos.z = pPlayer->pos.z;
8629 }
8630
8631 if (sprite[j].statnum != STAT_EFFECTOR)
8632 {
8633 actor[j].bpos.z = sprite[j].z;
8634 sprite[j].z += q;
8635 }
8636
8637 actor[j].floorz = pSector->floorz;
8638 actor[j].ceilingz = pSector->ceilingz;
8639 }
8640
8641 if (pData[0]) //If in motion
8642 {
8643 if (klabs(pSector->floorz-pData[2]) <= SP(spriteNum))
8644 {
8645 G_ActivateWarpElevators(spriteNum,0);
8646 break;
8647 }
8648
8649 // If we still see the opening, we can't yet teleport.
8650 if (pData[0]==-1)
8651 {
8652 if (pSector->floorz > pData[3])
8653 break;
8654 }
8655 else if (pSector->ceilingz < pData[4]) break;
8656
8657 if (pData[1] == 0) break;
8658 pData[1] = 0;
8659
8660 for (SPRITES_OF(STAT_EFFECTOR, j))
8661 {
8662 if (spriteNum != j && sprite[j].lotag == SE_17_WARP_ELEVATOR)
8663 if (pSector->hitag-pData[0] == sector[sprite[j].sectnum].hitag
8664 && spriteHitag == sprite[j].hitag)
8665 break;
8666 }
8667
8668 if (j == -1) break;
8669
8670 for (SPRITES_OF_SECT_SAFE(pSprite->sectnum, k, nextk))
8671 {
8672 if (sprite[k].statnum == STAT_PLAYER && sprite[k].owner >= 0)
8673 {
8674 int const warpPlayer = P_Get(k);
8675 DukePlayer_t *const pPlayer = g_player[warpPlayer].ps;
8676
8677 pPlayer->pos.x += sprite[j].x - pSprite->x;
8678 pPlayer->pos.y += sprite[j].y - pSprite->y;
8679 pPlayer->pos.z = sector[sprite[j].sectnum].floorz - (pSector->floorz - pPlayer->pos.z);
8680
8681 actor[k].floorz = sector[sprite[j].sectnum].floorz;
8682 actor[k].ceilingz = sector[sprite[j].sectnum].ceilingz;
8683 *(vec2_t *)&pPlayer->opos = *(vec2_t *)pPlayer;
8684 *(vec2_t *)&pPlayer->bobpos = *(vec2_t *)pPlayer;
8685 pPlayer->opos.z = pPlayer->pos.z;
8686 pPlayer->truefz = actor[k].floorz;
8687 pPlayer->truecz = actor[k].ceilingz;
8688 pPlayer->bobcounter = 0;
8689
8690 changespritesect(k, sprite[j].sectnum);
8691 pPlayer->cursectnum = sprite[j].sectnum;
8692 }
8693 else if (sprite[k].statnum != STAT_EFFECTOR)
8694 {
8695 sprite[k].x += sprite[j].x-pSprite->x;
8696 sprite[k].y += sprite[j].y-pSprite->y;
8697 sprite[k].z = sector[sprite[j].sectnum].floorz - (pSector->floorz - sprite[k].z);
8698
8699 Bmemcpy(&actor[k].bpos, &sprite[k], sizeof(vec3_t));
8700
8701 changespritesect(k,sprite[j].sectnum);
8702 setsprite(k,(vec3_t *)&sprite[k]);
8703
8704 actor[k].floorz = sector[sprite[j].sectnum].floorz;
8705 actor[k].ceilingz = sector[sprite[j].sectnum].ceilingz;
8706 }
8707 }
8708 }
8709 break;
8710 }
8711
8712 case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
8713 if (pData[0])
8714 {
8715 if (pSprite->pal)
8716 {
8717 if (pSprite->ang == 512)
8718 {
8719 pSector->ceilingz -= pSector->extra;
8720 if (pSector->ceilingz <= pData[1])
8721 {
8722 pSector->ceilingz = pData[1];
8723 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8724 }
8725 }
8726 else
8727 {
8728 pSector->floorz += pSector->extra;
8729
8730 if (!RR)
8731 for (bssize_t SPRITES_OF_SECT(pSprite->sectnum, sectSprite))
8732 {
8733 if (sprite[sectSprite].picnum == APLAYER && sprite[sectSprite].owner >= 0 && g_player[P_Get(sectSprite)].ps->on_ground == 1)
8734 g_player[P_Get(sectSprite)].ps->pos.z += pSector->extra;
8735
8736 if (sprite[sectSprite].zvel == 0 && sprite[sectSprite].statnum != STAT_EFFECTOR && sprite[sectSprite].statnum != STAT_PROJECTILE)
8737 {
8738 actor[sectSprite].bpos.z = sprite[sectSprite].z += pSector->extra;
8739 actor[sectSprite].floorz = pSector->floorz;
8740 }
8741 }
8742
8743 if (pSector->floorz >= pData[1])
8744 {
8745 pSector->floorz = pData[1];
8746 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8747 }
8748 }
8749 }
8750 else
8751 {
8752 if (pSprite->ang == 512)
8753 {
8754 pSector->ceilingz += pSector->extra;
8755 if (pSector->ceilingz >= pSprite->z)
8756 {
8757 pSector->ceilingz = pSprite->z;
8758 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8759 }
8760 }
8761 else
8762 {
8763 pSector->floorz -= pSector->extra;
8764
8765 if (!RR)
8766 for (bssize_t SPRITES_OF_SECT(pSprite->sectnum, sectSprite))
8767 {
8768 if (sprite[sectSprite].picnum == APLAYER && sprite[sectSprite].owner >= 0 &&g_player[P_Get(sectSprite)].ps->on_ground == 1)
8769 g_player[P_Get(sectSprite)].ps->pos.z -= pSector->extra;
8770
8771 if (sprite[sectSprite].zvel == 0 && sprite[sectSprite].statnum != STAT_EFFECTOR && sprite[sectSprite].statnum != STAT_PROJECTILE)
8772 {
8773 actor[sectSprite].bpos.z = sprite[sectSprite].z -= pSector->extra;
8774 actor[sectSprite].floorz = pSector->floorz;
8775 }
8776 }
8777
8778 if (pSector->floorz <= pSprite->z)
8779 {
8780 pSector->floorz = pSprite->z;
8781 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8782 }
8783 }
8784 }
8785
8786 if (++pData[2] >= pSprite->hitag)
8787 {
8788 pData[2] = 0;
8789 pData[0] = 0;
8790 }
8791 }
8792 break;
8793
8794 case SE_19_EXPLOSION_LOWERS_CEILING: //Battlestar galactia shields
8795
8796 if (pData[0])
8797 {
8798 if (pData[0] == 1)
8799 {
8800 pData[0]++;
8801 x = pSector->wallptr;
8802 q = x+pSector->wallnum;
8803
8804 for (j=x; j<q; j++)
8805 {
8806 if (wall[j].overpicnum == BIGFORCE)
8807 {
8808 wall[j].cstat &= (128+32+8+4+2);
8809 wall[j].overpicnum = 0;
8810
8811 if (wall[j].nextwall >= 0)
8812 {
8813 wall[wall[j].nextwall].overpicnum = 0;
8814 wall[wall[j].nextwall].cstat &= (128+32+8+4+2);
8815 }
8816 }
8817 }
8818 }
8819
8820 if (pSector->ceilingz < pSector->floorz)
8821 pSector->ceilingz += SP(spriteNum);
8822 else
8823 {
8824 pSector->ceilingz = pSector->floorz;
8825
8826 for (SPRITES_OF(STAT_EFFECTOR, j))
8827 {
8828 if (sprite[j].lotag == SE_0_ROTATING_SECTOR && sprite[j].hitag==spriteHitag)
8829 {
8830 sectortype *const pSector = §or[sprite[j].sectnum];
8831 int const ownerSector = sprite[sprite[j].owner].sectnum;
8832
8833 pSector->ceilingpal = sector[ownerSector].floorpal;
8834 pSector->floorpal = pSector->ceilingpal;
8835 pSector->ceilingshade = sector[ownerSector].floorshade;
8836 pSector->floorshade = pSector->ceilingshade;
8837
8838 actor[sprite[j].owner].t_data[0] = 2;
8839 }
8840 }
8841
8842 DELETE_SPRITE_AND_CONTINUE(spriteNum);
8843 }
8844 }
8845 else //Not hit yet
8846 {
8847 if (G_FindExplosionInSector(pSprite->sectnum) >= 0)
8848 {
8849 P_DoQuote(QUOTE_UNLOCKED, g_player[myconnectindex].ps);
8850
8851 for (SPRITES_OF(STAT_EFFECTOR, l))
8852 {
8853 switch (sprite[l].lotag & 0x7fff)
8854 {
8855 case SE_0_ROTATING_SECTOR:
8856 if (sprite[l].hitag == spriteHitag)
8857 {
8858 int const spriteOwner = sprite[l].owner;
8859 int const sectNum = sprite[l].sectnum;
8860
8861 sector[sectNum].ceilingshade = sprite[spriteOwner].shade;
8862 sector[sectNum].floorshade = sector[sectNum].ceilingshade;
8863 sector[sectNum].ceilingpal = sprite[spriteOwner].pal;
8864 sector[sectNum].floorpal = sector[sectNum].ceilingpal;
8865 }
8866 break;
8867
8868 case SE_1_PIVOT:
8869 case SE_12_LIGHT_SWITCH:
8870 // case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
8871 case SE_19_EXPLOSION_LOWERS_CEILING:
8872 if (spriteHitag == sprite[l].hitag)
8873 if (actor[l].t_data[0] == 0)
8874 {
8875 actor[l].t_data[0] = 1; // Shut them all on
8876 sprite[l].owner = spriteNum;
8877 }
8878
8879 break;
8880 }
8881 }
8882 }
8883 }
8884
8885 break;
8886
8887 case SE_20_STRETCH_BRIDGE: //Extend-o-bridge
8888 if (pData[0] == 0) break;
8889 pSprite->xvel = (pData[0] == 1) ? 8 : -8;
8890
8891 if (pSprite->xvel) //Moving
8892 {
8893 vec2_t const vect = { (pSprite->xvel * sintable[(pSprite->ang + 512) & 2047]) >> 14,
8894 (pSprite->xvel * sintable[pSprite->ang & 2047]) >> 14 };
8895
8896 pData[3] += pSprite->xvel;
8897
8898 pSprite->x += vect.x;
8899 pSprite->y += vect.y;
8900
8901 if (pData[3] <= 0 || (pData[3] >> 6) >= (SP(spriteNum) >> 6))
8902 {
8903 pSprite->x -= vect.x;
8904 pSprite->y -= vect.y;
8905 pData[0] = 0;
8906 A_CallSound(pSprite->sectnum, spriteNum);
8907 break;
8908 }
8909
8910 for (bssize_t nextSprite, SPRITES_OF_SECT_SAFE(pSprite->sectnum, sectSprite, nextSprite))
8911 {
8912 if (sprite[sectSprite].statnum != STAT_EFFECTOR && sprite[sectSprite].zvel == 0)
8913 {
8914 sprite[sectSprite].x += vect.x;
8915 sprite[sectSprite].y += vect.y;
8916
8917 setsprite(sectSprite, (vec3_t *)&sprite[sectSprite]);
8918
8919 if (sector[sprite[sectSprite].sectnum].floorstat & 2 && sprite[sectSprite].statnum == STAT_ZOMBIEACTOR)
8920 A_Fall(sectSprite);
8921 }
8922 }
8923
8924 dragpoint((int16_t)pData[1], wall[pData[1]].x + vect.x, wall[pData[1]].y + vect.y, 0);
8925 dragpoint((int16_t)pData[2], wall[pData[2]].x + vect.x, wall[pData[2]].y + vect.y, 0);
8926
8927 for (bssize_t TRAVERSE_CONNECT(playerNum))
8928 {
8929 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
8930
8931 if (pPlayer->cursectnum == pSprite->sectnum && pPlayer->on_ground)
8932 {
8933 pPlayer->pos.x += vect.x;
8934 pPlayer->pos.y += vect.y;
8935
8936 pPlayer->opos.x = pPlayer->pos.x;
8937 pPlayer->opos.y = pPlayer->pos.y;
8938
8939 pPlayer->pos.z += PHEIGHT;
8940 setsprite(pPlayer->i, (vec3_t *)pPlayer);
8941 pPlayer->pos.z -= PHEIGHT;
8942 }
8943 }
8944
8945 pSector->floorxpanning -= vect.x >> 3;
8946 pSector->floorypanning -= vect.y >> 3;
8947
8948 if (REALITY)
8949 RT_AdjustFloorPanning(pSprite->sectnum, (-vect.x) >> 3, (-vect.y) >> 3);
8950
8951 pSector->ceilingxpanning -= vect.x >> 3;
8952 pSector->ceilingypanning -= vect.y >> 3;
8953
8954 if (REALITY)
8955 RT_AdjustCeilingPanning(pSprite->sectnum, (-vect.x) >> 3, (-vect.y) >> 3);
8956 }
8957
8958 break;
8959
8960 case SE_21_DROP_FLOOR: // Cascading effect
8961 {
8962 if (pData[0] == 0) break;
8963
8964 int32_t *zptr = (pSprite->ang == 1536) ? &pSector->ceilingz : &pSector->floorz;
8965
8966 if (pData[0] == 1) //Decide if the s->sectnum should go up or down
8967 {
8968 pSprite->zvel = ksgn(pSprite->z-*zptr) * (SP(spriteNum)<<4);
8969 pData[0]++;
8970 }
8971
8972 if (pSector->extra == 0)
8973 {
8974 *zptr += pSprite->zvel;
8975
8976 if (klabs(*zptr-pSprite->z) < 1024)
8977 {
8978 *zptr = pSprite->z;
8979 DELETE_SPRITE_AND_CONTINUE(spriteNum); //All done // SE_21_KILLIT, see sector.c
8980 }
8981 }
8982 else pSector->extra--;
8983 break;
8984 }
8985
8986 case SE_22_TEETH_DOOR:
8987 if (pData[1])
8988 {
8989 if (GetAnimationGoal(§or[pData[0]].ceilingz) >= 0)
8990 pSector->ceilingz += pSector->extra*9;
8991 else pData[1] = 0;
8992 }
8993 break;
8994
8995 case 156:
8996 if (!RRRA) break;
8997 fallthrough__;
8998 case SE_24_CONVEYOR:
8999 case SE_34:
9000 {
9001 if (pData[4])
9002 break;
9003
9004 vec2_t const vect = { (SP(spriteNum) * sintable[(pSprite->ang + 512) & 2047]) >> 18,
9005 (SP(spriteNum) * sintable[pSprite->ang & 2047]) >> 18 };
9006
9007 k = 0;
9008
9009 for (bssize_t nextSprite, SPRITES_OF_SECT_SAFE(pSprite->sectnum, sectSprite, nextSprite))
9010 {
9011 if (sprite[sectSprite].zvel < 0)
9012 continue;
9013
9014 switch (sprite[sectSprite].statnum)
9015 {
9016 case STAT_MISC:
9017 switch (DYNAMICTILEMAP(sprite[sectSprite].picnum))
9018 {
9019 case PUKE__STATIC:
9020 case FOOTPRINTS4__STATIC:
9021 case BLOODSPLAT1__STATIC:
9022 case BLOODSPLAT2__STATIC:
9023 case BLOODSPLAT3__STATIC:
9024 case BLOODSPLAT4__STATIC:
9025 if (RR) break;
9026 fallthrough__;
9027 case BULLETHOLE__STATIC:
9028 if (RR && sprite[sectSprite].picnum == BULLETHOLE) continue;
9029 fallthrough__;
9030 case BLOODPOOL__STATIC:
9031 case FOOTPRINTS__STATIC:
9032 case FOOTPRINTS2__STATIC:
9033 case FOOTPRINTS3__STATIC: sprite[sectSprite].xrepeat = sprite[sectSprite].yrepeat = 0; continue;
9034
9035 case LASERLINE__STATIC: if (RR) break; continue;
9036 }
9037 fallthrough__;
9038 case STAT_STANDABLE:
9039 if (!RR && sprite[sectSprite].picnum == TRIPBOMB)
9040 break;
9041 fallthrough__;
9042 case STAT_ACTOR:
9043 case STAT_DEFAULT:
9044 if (sprite[sectSprite].picnum == BOLT1
9045 || sprite[sectSprite].picnum == BOLT1 + 1
9046 || sprite[sectSprite].picnum == BOLT1 + 2
9047 || sprite[sectSprite].picnum == BOLT1 + 3
9048 || (!RR && (sprite[sectSprite].picnum == SIDEBOLT1
9049 || sprite[sectSprite].picnum == SIDEBOLT1 + 1
9050 || sprite[sectSprite].picnum == SIDEBOLT1 + 2
9051 || sprite[sectSprite].picnum == SIDEBOLT1 + 3))
9052 || A_CheckSwitchTile(sectSprite))
9053 break;
9054
9055 if (!(sprite[sectSprite].picnum >= CRANE && sprite[sectSprite].picnum <= CRANE + 3))
9056 {
9057 if (sprite[sectSprite].z > actor[sectSprite].floorz - ZOFFSET2)
9058 {
9059 actor[sectSprite].bpos.x = sprite[sectSprite].x;
9060 actor[sectSprite].bpos.y = sprite[sectSprite].y;
9061
9062 sprite[sectSprite].x += vect.x >> (RR ? 1 : 2);
9063 sprite[sectSprite].y += vect.y >> (RR ? 1 : 2);
9064
9065 setsprite(sectSprite, (vec3_t *)&sprite[sectSprite]);
9066
9067 if (sector[sprite[sectSprite].sectnum].floorstat & 2)
9068 if (sprite[sectSprite].statnum == STAT_ZOMBIEACTOR)
9069 A_Fall(sectSprite);
9070 }
9071 }
9072 break;
9073 }
9074 }
9075
9076 for (bssize_t TRAVERSE_CONNECT(playerNum))
9077 {
9078 DukePlayer_t *const pPlayer = g_player[playerNum].ps;
9079
9080 if (pPlayer->cursectnum == pSprite->sectnum && pPlayer->on_ground)
9081 {
9082 if (klabs(pPlayer->pos.z - pPlayer->truefz) < PHEIGHT + (9 << 8))
9083 {
9084 pPlayer->fric.x += vect.x << 3;
9085 pPlayer->fric.y += vect.y << 3;
9086 }
9087 }
9088 }
9089 if (!RRRA || spriteLotag != 156)
9090 {
9091 pSector->floorxpanning += SP(spriteNum)>>7;
9092 if (REALITY)
9093 RT_AdjustFloorPanning(pSprite->sectnum, SP(spriteNum)>>7, 0);
9094 }
9095
9096 break;
9097 }
9098
9099 case SE_35:
9100 if (pSector->ceilingz > pSprite->z)
9101 {
9102 for (j = 0; j < 8; j++)
9103 {
9104 pSprite->ang += krand2()&511;
9105 k = A_Spawn(spriteNum, SMALLSMOKE);
9106 sprite[k].xvel = 96+(krand2()&127);
9107 A_SetSprite(k, CLIPMASK0);
9108 setsprite(k, (vec3_t *) &sprite[k]);
9109 if (rnd(16))
9110 A_Spawn(spriteNum, EXPLOSION2);
9111 }
9112
9113 }
9114 switch (pData[0])
9115 {
9116 case 0:
9117 pSector->ceilingz += pSprite->yvel;
9118 if (pSector->ceilingz > pSector->floorz)
9119 pSector->floorz = pSector->ceilingz;
9120 if (pSector->ceilingz > pSprite->z+ZOFFSET5)
9121 pData[0]++;
9122 break;
9123 case 1:
9124 pSector->ceilingz-=(pSprite->yvel<<2);
9125 if (pSector->ceilingz < pData[4])
9126 {
9127 pSector->ceilingz = pData[4];
9128 pData[0] = 0;
9129 }
9130 break;
9131 }
9132 break;
9133
9134 case SE_25_PISTON: //PISTONS
9135 if (pData[4] == 0) break;
9136
9137 if (pSector->floorz <= pSector->ceilingz)
9138 pSprite->shade = 0;
9139 else if (pSector->ceilingz <= pData[RR?4:3])
9140 pSprite->shade = 1;
9141
9142 if (pSprite->shade)
9143 {
9144 pSector->ceilingz += SP(spriteNum)<<4;
9145 if (pSector->ceilingz > pSector->floorz)
9146 {
9147 pSector->ceilingz = pSector->floorz;
9148 if (RRRA && g_pistonSound)
9149 A_PlaySound(371, spriteNum);
9150 }
9151 }
9152 else
9153 {
9154 pSector->ceilingz -= SP(spriteNum)<<4;
9155 if (pSector->ceilingz < pData[RR?4:3])
9156 {
9157 pSector->ceilingz = pData[RR?4:3];
9158 if (RRRA && g_pistonSound)
9159 A_PlaySound(167, spriteNum);
9160 }
9161 }
9162
9163 break;
9164
9165 case SE_26:
9166 {
9167 int32_t p, nextj;
9168
9169 pSprite->xvel = 32;
9170 l = (pSprite->xvel*sintable[(pSprite->ang+512)&2047])>>14;
9171 x = (pSprite->xvel*sintable[pSprite->ang&2047])>>14;
9172
9173 pSprite->shade++;
9174 if (pSprite->shade > 7)
9175 {
9176 pSprite->x = pData[3];
9177 pSprite->y = pData[4];
9178 pSector->floorz -= ((pSprite->zvel*pSprite->shade)-pSprite->zvel);
9179 pSprite->shade = 0;
9180 }
9181 else
9182 pSector->floorz += pSprite->zvel;
9183
9184 for (SPRITES_OF_SECT_SAFE(pSprite->sectnum, j, nextj))
9185 {
9186 if (sprite[j].statnum != STAT_EFFECTOR && sprite[j].statnum != STAT_PLAYER )
9187 {
9188 actor[j].bpos.x = sprite[j].x;
9189 actor[j].bpos.y = sprite[j].y;
9190
9191 sprite[j].x += l;
9192 sprite[j].y += x;
9193 sprite[j].z += pSprite->zvel;
9194
9195 setsprite(j, (vec3_t *)&sprite[j]);
9196 }
9197 }
9198
9199 for (TRAVERSE_CONNECT(p))
9200 {
9201 DukePlayer_t *const pPlayer = g_player[p].ps;
9202
9203 if (pSprite->sectnum == sprite[pPlayer->i].sectnum && pPlayer->on_ground)
9204 {
9205 pPlayer->fric.x += l << 5;
9206 pPlayer->fric.y += x << 5;
9207 pPlayer->pos.z += pSprite->zvel;
9208 }
9209 }
9210
9211 A_MoveSector(spriteNum);
9212 setsprite(spriteNum,(vec3_t *)pSprite);
9213
9214 break;
9215 }
9216
9217 case SE_27_DEMO_CAM:
9218 {
9219 if (ud.recstat == 0 || !ud.democams) break;
9220
9221 actor[spriteNum].tempang = pSprite->ang;
9222
9223 int const p = A_FindPlayer(pSprite,&x);
9224 DukePlayer_t * const ps = g_player[p].ps;
9225
9226 if (sprite[ps->i].extra > 0 && myconnectindex == screenpeek)
9227 {
9228 if (pData[0] < 0)
9229 {
9230 ud.camerasprite = spriteNum;
9231 pData[0]++;
9232 }
9233 else if (ud.recstat == 2 && ps->newowner == -1)
9234 {
9235 if (cansee(pSprite->x,pSprite->y,pSprite->z,SECT(spriteNum),ps->pos.x,ps->pos.y,ps->pos.z,ps->cursectnum))
9236 {
9237 if (x < (int32_t)((unsigned)spriteHitag))
9238 {
9239 ud.camerasprite = spriteNum;
9240 pData[0] = 999;
9241 pSprite->ang += G_GetAngleDelta(pSprite->ang,getangle(ps->pos.x-pSprite->x,ps->pos.y-pSprite->y))>>3;
9242 SP(spriteNum) = 100+((pSprite->z-ps->pos.z)/257);
9243
9244 }
9245 else if (pData[0] == 999)
9246 {
9247 if (ud.camerasprite == spriteNum)
9248 pData[0] = 0;
9249 else pData[0] = -10;
9250 ud.camerasprite = spriteNum;
9251
9252 }
9253 }
9254 else
9255 {
9256 pSprite->ang = getangle(ps->pos.x-pSprite->x,ps->pos.y-pSprite->y);
9257
9258 if (pData[0] == 999)
9259 {
9260 if (ud.camerasprite == spriteNum)
9261 pData[0] = 0;
9262 else pData[0] = -20;
9263 ud.camerasprite = spriteNum;
9264 }
9265 }
9266 }
9267 }
9268 break;
9269 }
9270
9271 case SE_28_LIGHTNING:
9272 {
9273 if (RR)
9274 break;
9275 if (pData[5] > 0)
9276 {
9277 pData[5]--;
9278 break;
9279 }
9280
9281 if (T1(spriteNum) == 0)
9282 {
9283 A_FindPlayer(pSprite,&x);
9284 if (x > 15500)
9285 break;
9286 T1(spriteNum) = 1;
9287 T2(spriteNum) = 64 + (krand2()&511);
9288 T3(spriteNum) = 0;
9289 }
9290 else
9291 {
9292 T3(spriteNum)++;
9293 if (T3(spriteNum) > T2(spriteNum))
9294 {
9295 T1(spriteNum) = 0;
9296 g_player[screenpeek].ps->visibility = ud.const_visibility;
9297 break;
9298 }
9299 else if (T3(spriteNum) == (T2(spriteNum)>>1))
9300 A_PlaySound(REALITY ? 247 : THUNDER,spriteNum);
9301 else if (T3(spriteNum) == (T2(spriteNum)>>3))
9302 A_PlaySound(REALITY ? 246 : LIGHTNING_SLAP,spriteNum);
9303 else if (T3(spriteNum) == (T2(spriteNum)>>2))
9304 {
9305 for (SPRITES_OF(STAT_DEFAULT, j))
9306 if (sprite[j].picnum == NATURALLIGHTNING && sprite[j].hitag == pSprite->hitag)
9307 sprite[j].cstat |= 32768;
9308 }
9309 else if (T3(spriteNum) > (T2(spriteNum)>>3) && T3(spriteNum) < (T2(spriteNum)>>2))
9310 {
9311 if (cansee(pSprite->x,pSprite->y,pSprite->z,pSprite->sectnum,g_player[screenpeek].ps->pos.x,g_player[screenpeek].ps->pos.y,g_player[screenpeek].ps->pos.z,g_player[screenpeek].ps->cursectnum))
9312 j = 1;
9313 else j = 0;
9314
9315 if (rnd(192) && (T3(spriteNum)&1))
9316 {
9317 if (j)
9318 g_player[screenpeek].ps->visibility = 0;
9319 }
9320 else if (j)
9321 g_player[screenpeek].ps->visibility = ud.const_visibility;
9322
9323 for (SPRITES_OF(STAT_DEFAULT, j))
9324 {
9325 if (sprite[j].picnum == NATURALLIGHTNING && sprite[j].hitag == pSprite->hitag)
9326 {
9327 if (rnd(32) && (T3(spriteNum)&1))
9328 {
9329 int32_t p;
9330 DukePlayer_t *ps;
9331
9332 sprite[j].cstat &= 32767;
9333 A_Spawn(j,SMALLSMOKE);
9334
9335 p = A_FindPlayer(pSprite, NULL);
9336 ps = g_player[p].ps;
9337
9338 x = ldist(&sprite[ps->i], &sprite[j]);
9339 if (x < 768)
9340 {
9341 if (!A_CheckSoundPlaying(ps->i,REALITY ? 168 : DUKE_LONGTERM_PAIN))
9342 A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN,ps->i);
9343 A_PlaySound(REALITY ? 19 : SHORT_CIRCUIT,ps->i);
9344 sprite[ps->i].extra -= 8+(krand2()&7);
9345
9346 P_PalFrom(ps, 32, 16,0,0);
9347 }
9348 break;
9349 }
9350 else sprite[j].cstat |= 32768;
9351 }
9352 }
9353 }
9354 }
9355 break;
9356 }
9357
9358 case SE_29_WAVES:
9359 pSprite->hitag += 64;
9360 l = mulscale12((int32_t)pSprite->yvel,sintable[pSprite->hitag&2047]);
9361 pSector->floorz = pSprite->z + l;
9362 break;
9363
9364 case SE_31_FLOOR_RISE_FALL: // True Drop Floor
9365 if (pData[0] == 1)
9366 {
9367 // Choose dir
9368
9369 if (!RR && pData[3] > 0)
9370 {
9371 pData[3]--;
9372 break;
9373 }
9374
9375 if (pData[2] == 1) // Retract
9376 {
9377 if (SA(spriteNum) != 1536)
9378 HandleSE31(spriteNum, 1, pSprite->z, 0, pSprite->z-pSector->floorz);
9379 else
9380 HandleSE31(spriteNum, 1, pData[1], 0, pData[1]-pSector->floorz);
9381
9382 Yax_SetBunchZs(pSector-sector, YAX_FLOOR, pSector->floorz);
9383
9384 break;
9385 }
9386
9387 if ((pSprite->ang&2047) == 1536)
9388 HandleSE31(spriteNum, 0, pSprite->z, 1, pSprite->z-pSector->floorz);
9389 else
9390 HandleSE31(spriteNum, 0, pData[1], 1, pData[1]-pSprite->z);
9391
9392 Yax_SetBunchZs(pSector-sector, YAX_FLOOR, pSector->floorz);
9393 }
9394 break;
9395
9396 case SE_32_CEILING_RISE_FALL: // True Drop Ceiling
9397 if (pData[0] == 1)
9398 {
9399 // Choose dir
9400
9401 if (pData[2] == 1) // Retract
9402 {
9403 if (SA(spriteNum) != 1536)
9404 {
9405 if (klabs(pSector->ceilingz - pSprite->z) < (SP(spriteNum)<<1))
9406 {
9407 pSector->ceilingz = pSprite->z;
9408 A_CallSound(pSprite->sectnum,spriteNum);
9409 pData[2] = 0;
9410 pData[0] = 0;
9411 }
9412 else pSector->ceilingz += ksgn(pSprite->z-pSector->ceilingz)*SP(spriteNum);
9413 }
9414 else
9415 {
9416 if (klabs(pSector->ceilingz - pData[1]) < (SP(spriteNum)<<1))
9417 {
9418 pSector->ceilingz = pData[1];
9419 A_CallSound(pSprite->sectnum,spriteNum);
9420 pData[2] = 0;
9421 pData[0] = 0;
9422 }
9423 else pSector->ceilingz += ksgn(pData[1]-pSector->ceilingz)*SP(spriteNum);
9424 }
9425
9426 Yax_SetBunchZs(pSector-sector, YAX_CEILING, pSector->ceilingz);
9427
9428 break;
9429 }
9430
9431 if ((pSprite->ang&2047) == 1536)
9432 {
9433 if (klabs(pSector->ceilingz-pSprite->z) < (SP(spriteNum)<<1))
9434 {
9435 pData[0] = 0;
9436 pData[2] = !pData[2];
9437 A_CallSound(pSprite->sectnum,spriteNum);
9438 pSector->ceilingz = pSprite->z;
9439 }
9440 else pSector->ceilingz += ksgn(pSprite->z-pSector->ceilingz)*SP(spriteNum);
9441 }
9442 else
9443 {
9444 if (klabs(pSector->ceilingz-pData[1]) < (SP(spriteNum)<<1))
9445 {
9446 pData[0] = 0;
9447 pData[2] = !pData[2];
9448 A_CallSound(pSprite->sectnum,spriteNum);
9449 }
9450 else pSector->ceilingz -= ksgn(pSprite->z-pData[1])*SP(spriteNum);
9451 }
9452
9453 Yax_SetBunchZs(pSector-sector, YAX_CEILING, pSector->ceilingz);
9454 }
9455 break;
9456
9457 case SE_33_QUAKE_DEBRIS:
9458 if (g_earthquakeTime > 0 && (krand2()&7) == 0)
9459 RANDOMSCRAP(pSprite, spriteNum);
9460 break;
9461
9462 case SE_36_PROJ_SHOOTER:
9463 if (pData[0])
9464 {
9465 if (pData[0] == 1)
9466 A_Shoot(spriteNum,pSector->extra);
9467 else if (pData[0] == GAMETICSPERSEC*5)
9468 pData[0] = 0;
9469 pData[0]++;
9470 }
9471 break;
9472
9473 case 128: //SE to control glass breakage
9474 {
9475 walltype *pWall = &wall[pData[2]];
9476
9477 if (pWall->cstat|32)
9478 {
9479 pWall->cstat &= (255-32);
9480 pWall->cstat |= 16;
9481 if (pWall->nextwall >= 0)
9482 {
9483 wall[pWall->nextwall].cstat &= (255-32);
9484 wall[pWall->nextwall].cstat |= 16;
9485 }
9486 }
9487 else break;
9488
9489 pWall->overpicnum++;
9490 if (pWall->nextwall >= 0)
9491 wall[pWall->nextwall].overpicnum++;
9492
9493 if (pData[0] < pData[1]) pData[0]++;
9494 else
9495 {
9496 pWall->cstat &= (128+32+8+4+2);
9497 if (pWall->nextwall >= 0)
9498 wall[pWall->nextwall].cstat &= (128+32+8+4+2);
9499 DELETE_SPRITE_AND_CONTINUE(spriteNum);
9500 }
9501 }
9502 break;
9503
9504 case SE_130:
9505 if (pData[0] > 80)
9506 {
9507 DELETE_SPRITE_AND_CONTINUE(spriteNum);
9508 }
9509 else pData[0]++;
9510
9511 x = pSector->floorz-pSector->ceilingz;
9512
9513 if (rnd(64))
9514 {
9515 k = A_Spawn(spriteNum,EXPLOSION2);
9516 sprite[k].xrepeat = sprite[k].yrepeat = 2+(krand2()&7);
9517 sprite[k].z = pSector->floorz-(krand2()%x);
9518 sprite[k].ang += 256-(krand2()%511);
9519 sprite[k].xvel = krand2()&127;
9520 A_SetSprite(k,CLIPMASK0);
9521 }
9522 break;
9523
9524 case SE_131:
9525 if (pData[0] > 40)
9526 {
9527 DELETE_SPRITE_AND_CONTINUE(spriteNum);
9528 }
9529 else pData[0]++;
9530
9531 x = pSector->floorz-pSector->ceilingz;
9532
9533 if (rnd(32))
9534 {
9535 k = A_Spawn(spriteNum,EXPLOSION2);
9536 sprite[k].xrepeat = sprite[k].yrepeat = 2+(krand2()&3);
9537 sprite[k].z = pSector->floorz-(krand2()%x);
9538 sprite[k].ang += 256-(krand2()%511);
9539 sprite[k].xvel = krand2()&127;
9540 A_SetSprite(k,CLIPMASK0);
9541 }
9542 break;
9543
9544 case SE_77:
9545 if (!REALITY)
9546 break;
9547 // if (ud.multimode > 1 && ud.coop == 0 && dukematch_mode != 1)
9548 // break;
9549
9550 for (int TRAVERSE_CONNECT(playerNum))
9551 if (g_player[playerNum].ps->cursectnum == pSprite->sectnum && klabs(g_player[playerNum].ps->pos.z - pSprite->z) <= (24<<8)
9552 && g_player[playerNum].ps->timebeforeexit == 0)
9553 {
9554 g_player[playerNum].ps->timebeforeexit = 17;
9555 }
9556 break;
9557
9558 case SE_49_POINT_LIGHT:
9559 case SE_50_SPOT_LIGHT:
9560 changespritestat(spriteNum, STAT_LIGHT);
9561 break;
9562 }
9563 next_sprite:
9564 spriteNum = nextSprite;
9565 }
9566
9567 //Sloped sin-wave floors!
9568 for (SPRITES_OF(STAT_EFFECTOR, spriteNum))
9569 {
9570 const spritetype *s = &sprite[spriteNum];
9571
9572 if (s->lotag == SE_29_WAVES)
9573 {
9574 usectortype const *const sc = (usectortype *)§or[s->sectnum];
9575
9576 if (sc->wallnum == 4)
9577 {
9578 walltype *const pWall = &wall[sc->wallptr+2];
9579 if (pWall->nextsector >= 0)
9580 alignflorslope(s->sectnum, pWall->x,pWall->y, sector[pWall->nextsector].floorz);
9581 }
9582 }
9583 }
9584 }
9585
G_DoEffectorLights(void)9586 static void G_DoEffectorLights(void) // STATNUM 14
9587 {
9588 int32_t i;
9589
9590 for (SPRITES_OF(STAT_LIGHT, i))
9591 {
9592 switch (sprite[i].lotag)
9593 {
9594 #ifdef POLYMER
9595 case SE_49_POINT_LIGHT:
9596 {
9597 if (!A_CheckSpriteFlags(i, SFLAG_NOLIGHT) && videoGetRenderMode() == REND_POLYMER &&
9598 !(A_CheckSpriteFlags(i, SFLAG_USEACTIVATOR) && sector[sprite[i].sectnum].lotag & 16384))
9599 {
9600 if (actor[i].lightptr == NULL)
9601 {
9602 #pragma pack(push,1)
9603 _prlight mylight;
9604 #pragma pack(pop)
9605 mylight.sector = SECT(i);
9606 Bmemcpy(&mylight, &sprite[i], sizeof(int32_t) * 3);
9607 mylight.range = SHT(i);
9608 mylight.color[0] = sprite[i].xvel;
9609 mylight.color[1] = sprite[i].yvel;
9610 mylight.color[2] = sprite[i].zvel;
9611 mylight.radius = 0;
9612 mylight.angle = SA(i);
9613 mylight.horiz = SH(i);
9614 mylight.minshade = sprite[i].xoffset;
9615 mylight.maxshade = sprite[i].yoffset;
9616 mylight.tilenum = 0;
9617 mylight.publicflags.emitshadow = 0;
9618 mylight.publicflags.negative = !!(CS(i) & 128);
9619
9620 if (CS(i) & 2)
9621 {
9622 if (CS(i) & 512)
9623 mylight.priority = PR_LIGHT_PRIO_LOW;
9624 else
9625 mylight.priority = PR_LIGHT_PRIO_HIGH;
9626 }
9627 else
9628 mylight.priority = PR_LIGHT_PRIO_MAX;
9629
9630 actor[i].lightId = polymer_addlight(&mylight);
9631 if (actor[i].lightId >= 0)
9632 actor[i].lightptr = &prlights[actor[i].lightId];
9633 break;
9634 }
9635
9636 if (Bmemcmp(&sprite[i], actor[i].lightptr, sizeof(int32_t) * 3))
9637 {
9638 Bmemcpy(actor[i].lightptr, &sprite[i], sizeof(int32_t) * 3);
9639 actor[i].lightptr->sector = sprite[i].sectnum;
9640 actor[i].lightptr->flags.invalidate = 1;
9641 }
9642 if (SHT(i) != actor[i].lightptr->range)
9643 {
9644 actor[i].lightptr->range = SHT(i);
9645 actor[i].lightptr->flags.invalidate = 1;
9646 }
9647 if ((sprite[i].xvel != actor[i].lightptr->color[0]) ||
9648 (sprite[i].yvel != actor[i].lightptr->color[1]) ||
9649 (sprite[i].zvel != actor[i].lightptr->color[2]))
9650 {
9651 actor[i].lightptr->color[0] = sprite[i].xvel;
9652 actor[i].lightptr->color[1] = sprite[i].yvel;
9653 actor[i].lightptr->color[2] = sprite[i].zvel;
9654 }
9655 if ((int)!!(CS(i) & 128) != actor[i].lightptr->publicflags.negative) {
9656 actor[i].lightptr->publicflags.negative = !!(CS(i) & 128);
9657 }
9658 }
9659 break;
9660 }
9661 case SE_50_SPOT_LIGHT:
9662 {
9663 if (!A_CheckSpriteFlags(i, SFLAG_NOLIGHT) && videoGetRenderMode() == REND_POLYMER &&
9664 !(A_CheckSpriteFlags(i, SFLAG_USEACTIVATOR) && sector[sprite[i].sectnum].lotag & 16384))
9665 {
9666 if (actor[i].lightptr == NULL)
9667 {
9668 #pragma pack(push,1)
9669 _prlight mylight;
9670 #pragma pack(pop)
9671
9672 mylight.sector = SECT(i);
9673 Bmemcpy(&mylight, &sprite[i], sizeof(int32_t) * 3);
9674 mylight.range = SHT(i);
9675 mylight.color[0] = sprite[i].xvel;
9676 mylight.color[1] = sprite[i].yvel;
9677 mylight.color[2] = sprite[i].zvel;
9678 mylight.radius = (256-(SS(i)+128))<<1;
9679 mylight.faderadius = (int16_t)(mylight.radius * 0.75f);
9680 mylight.angle = SA(i);
9681 mylight.horiz = SH(i);
9682 mylight.minshade = sprite[i].xoffset;
9683 mylight.maxshade = sprite[i].yoffset;
9684 mylight.tilenum = actor[i].picnum;
9685 mylight.publicflags.emitshadow = !(CS(i) & 64);
9686 mylight.publicflags.negative = !!(CS(i) & 128);
9687
9688 if (CS(i) & 2)
9689 {
9690 if (CS(i) & 512)
9691 mylight.priority = PR_LIGHT_PRIO_LOW;
9692 else
9693 mylight.priority = PR_LIGHT_PRIO_HIGH;
9694 }
9695 else
9696 mylight.priority = PR_LIGHT_PRIO_MAX;
9697
9698 actor[i].lightId = polymer_addlight(&mylight);
9699 if (actor[i].lightId >= 0)
9700 {
9701 actor[i].lightptr = &prlights[actor[i].lightId];
9702
9703 // Hack in case polymer_addlight tweaked the horiz value
9704 if (actor[i].lightptr->horiz != SH(i))
9705 SH(i) = actor[i].lightptr->horiz;
9706 }
9707 break;
9708 }
9709
9710 if (Bmemcmp(&sprite[i], actor[i].lightptr, sizeof(int32_t) * 3))
9711 {
9712 Bmemcpy(actor[i].lightptr, &sprite[i], sizeof(int32_t) * 3);
9713 actor[i].lightptr->sector = sprite[i].sectnum;
9714 actor[i].lightptr->flags.invalidate = 1;
9715 }
9716 if (SHT(i) != actor[i].lightptr->range)
9717 {
9718 actor[i].lightptr->range = SHT(i);
9719 actor[i].lightptr->flags.invalidate = 1;
9720 }
9721 if ((sprite[i].xvel != actor[i].lightptr->color[0]) ||
9722 (sprite[i].yvel != actor[i].lightptr->color[1]) ||
9723 (sprite[i].zvel != actor[i].lightptr->color[2]))
9724 {
9725 actor[i].lightptr->color[0] = sprite[i].xvel;
9726 actor[i].lightptr->color[1] = sprite[i].yvel;
9727 actor[i].lightptr->color[2] = sprite[i].zvel;
9728 }
9729 if (((256-(SS(i)+128))<<1) != actor[i].lightptr->radius)
9730 {
9731 actor[i].lightptr->radius = (256-(SS(i)+128))<<1;
9732 actor[i].lightptr->faderadius = (int16_t)(actor[i].lightptr->radius * 0.75f);
9733 actor[i].lightptr->flags.invalidate = 1;
9734 }
9735 if (SA(i) != actor[i].lightptr->angle)
9736 {
9737 actor[i].lightptr->angle = SA(i);
9738 actor[i].lightptr->flags.invalidate = 1;
9739 }
9740 if (SH(i) != actor[i].lightptr->horiz)
9741 {
9742 actor[i].lightptr->horiz = SH(i);
9743 actor[i].lightptr->flags.invalidate = 1;
9744 }
9745 if ((int)!(CS(i) & 64) != actor[i].lightptr->publicflags.emitshadow) {
9746 actor[i].lightptr->publicflags.emitshadow = !(CS(i) & 64);
9747 }
9748 if ((int)!!(CS(i) & 128) != actor[i].lightptr->publicflags.negative) {
9749 actor[i].lightptr->publicflags.negative = !!(CS(i) & 128);
9750 }
9751 actor[i].lightptr->tilenum = actor[i].picnum;
9752 }
9753
9754 break;
9755 }
9756 #endif // POLYMER
9757 }
9758 }
9759 }
9760
9761 #ifdef POLYMER
A_DoLight(int spriteNum)9762 static void A_DoLight(int spriteNum)
9763 {
9764 spritetype *const pSprite = &sprite[spriteNum];
9765 int savedFires = 0;
9766
9767 if (((sector[pSprite->sectnum].floorz - sector[pSprite->sectnum].ceilingz) < 16) || pSprite->z > sector[pSprite->sectnum].floorz || pSprite->z > actor[spriteNum].floorz ||
9768 (pSprite->picnum != SECTOREFFECTOR && ((pSprite->cstat & 32768) || pSprite->yrepeat < 4)) ||
9769 A_CheckSpriteFlags(spriteNum, SFLAG_NOLIGHT) || (A_CheckSpriteFlags(spriteNum, SFLAG_USEACTIVATOR) && sector[pSprite->sectnum].lotag & 16384))
9770 {
9771 if (actor[spriteNum].lightptr != NULL)
9772 A_DeleteLight(spriteNum);
9773 }
9774 else
9775 {
9776 if (actor[spriteNum].lightptr != NULL && actor[spriteNum].lightcount)
9777 {
9778 if (!(--actor[spriteNum].lightcount))
9779 A_DeleteLight(spriteNum);
9780 }
9781
9782 if (pr_lighting != 1)
9783 return;
9784
9785 for (bsize_t ii=0; ii<2; ii++)
9786 {
9787 if (pSprite->picnum <= 0) // oob safety
9788 break;
9789
9790 switch (DYNAMICTILEMAP(pSprite->picnum-1+ii))
9791 {
9792 case DIPSWITCH__STATIC:
9793 case DIPSWITCH2__STATIC:
9794 case DIPSWITCH3__STATIC:
9795 case PULLSWITCH__STATIC:
9796 case SLOTDOOR__STATIC:
9797 case LIGHTSWITCH__STATIC:
9798 case SPACELIGHTSWITCH__STATIC:
9799 case SPACEDOORSWITCH__STATIC:
9800 case FRANKENSTINESWITCH__STATIC:
9801 case POWERSWITCH1__STATIC:
9802 case LOCKSWITCH1__STATIC:
9803 case POWERSWITCH2__STATIC:
9804 case TECHSWITCH__STATIC:
9805 case ACCESSSWITCH__STATIC:
9806 case ACCESSSWITCH2__STATIC:
9807 {
9808 if ((pSprite->cstat & 32768) || A_CheckSpriteFlags(spriteNum, SFLAG_NOLIGHT))
9809 {
9810 if (actor[spriteNum].lightptr != NULL)
9811 A_DeleteLight(spriteNum);
9812 break;
9813 }
9814
9815 vec2_t const d = { sintable[(pSprite->ang+512)&2047]>>7, sintable[(pSprite->ang)&2047]>>7 };
9816
9817 pSprite->x += d.x;
9818 pSprite->y += d.y;
9819
9820 int16_t sectnum = pSprite->sectnum;
9821 updatesector(pSprite->x, pSprite->y, §num);
9822
9823 if ((unsigned) sectnum >= MAXSECTORS || pSprite->z > sector[sectnum].floorz || pSprite->z < sector[sectnum].ceilingz)
9824 goto POOP;
9825
9826 G_AddGameLight(0, spriteNum, (pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1, 512-ii*128,
9827 ii==0 ? (172+(200<<8)+(104<<16)) : 216+(52<<8)+(20<<16), PR_LIGHT_PRIO_LOW);
9828
9829 POOP:
9830 pSprite->x -= d.x;
9831 pSprite->y -= d.y;
9832 }
9833 break;
9834 }
9835 }
9836
9837 switch (DYNAMICTILEMAP(pSprite->picnum))
9838 {
9839 case ATOMICHEALTH__STATIC:
9840 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), LIGHTRAD2(spriteNum, pSprite), 128+(128<<8)+(255<<16),PR_LIGHT_PRIO_HIGH_GAME);
9841 break;
9842
9843 case FIRE__STATIC:
9844 case FIRE2__STATIC:
9845 case BURNING__STATIC:
9846 case BURNING2__STATIC:
9847 {
9848 uint32_t color;
9849 int32_t jj;
9850
9851 static int32_t savedfires[32][4]; // sectnum x y z
9852
9853 /*
9854 if (Actor[i].floorz - Actor[i].ceilingz < 128) break;
9855 if (s->z > Actor[i].floorz+2048) break;
9856 */
9857
9858 switch (pSprite->pal)
9859 {
9860 case 1: color = 128+(128<<8)+(255<<16); break;
9861 case 2: color = 255+(48<<8)+(48<<16); break;
9862 case 8: color = 48+(255<<8)+(48<<16); break;
9863 default: color = 240+(160<<8)+(80<<16); break;
9864 }
9865
9866 for (jj=savedFires-1; jj>=0; jj--)
9867 if (savedfires[jj][0]==pSprite->sectnum && savedfires[jj][1]==(pSprite->x>>3) &&
9868 savedfires[jj][2]==(pSprite->y>>3) && savedfires[jj][3]==(pSprite->z>>7))
9869 break;
9870
9871 if (jj==-1 && savedFires<32)
9872 {
9873 jj = savedFires;
9874 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), LIGHTRAD2(spriteNum, pSprite), color, PR_LIGHT_PRIO_HIGH_GAME);
9875 savedfires[jj][0] = pSprite->sectnum;
9876 savedfires[jj][1] = pSprite->x>>3;
9877 savedfires[jj][2] = pSprite->y>>3;
9878 savedfires[jj][3] = pSprite->z>>7;
9879 savedFires++;
9880 }
9881 }
9882 break;
9883
9884 case OOZFILTER__STATIC:
9885 if (pSprite->xrepeat > 4)
9886 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), 4096, 176+(252<<8)+(120<<16),PR_LIGHT_PRIO_HIGH_GAME);
9887 break;
9888 case FLOORFLAME__STATIC:
9889 case FIREBARREL__STATIC:
9890 case FIREVASE__STATIC:
9891 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<2), LIGHTRAD2(spriteNum, pSprite)>>1, 255+(95<<8),PR_LIGHT_PRIO_HIGH_GAME);
9892 break;
9893
9894 case EXPLOSION2__STATIC:
9895 if (!actor[spriteNum].lightcount)
9896 {
9897 // XXX: This block gets CODEDUP'd too much.
9898 int32_t x = ((sintable[(pSprite->ang+512)&2047])>>6);
9899 int32_t y = ((sintable[(pSprite->ang)&2047])>>6);
9900
9901 pSprite->x -= x;
9902 pSprite->y -= y;
9903
9904 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), LIGHTRAD(spriteNum, pSprite), 240+(160<<8)+(80<<16),
9905 pSprite->yrepeat > 32 ? PR_LIGHT_PRIO_HIGH_GAME : PR_LIGHT_PRIO_LOW_GAME);
9906
9907 pSprite->x += x;
9908 pSprite->y += y;
9909 }
9910 break;
9911 case FORCERIPPLE__STATIC:
9912 case TRANSPORTERBEAM__STATIC:
9913 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), LIGHTRAD(spriteNum, pSprite), 80+(80<<8)+(255<<16),PR_LIGHT_PRIO_LOW_GAME);
9914 break;
9915 case GROWSPARK__STATIC:
9916 {
9917 int32_t x = ((sintable[(pSprite->ang+512)&2047])>>6);
9918 int32_t y = ((sintable[(pSprite->ang)&2047])>>6);
9919
9920 pSprite->x -= x;
9921 pSprite->y -= y;
9922
9923 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), 1024, 216+(52<<8)+(20<<16),PR_LIGHT_PRIO_HIGH_GAME);
9924
9925 pSprite->x += x;
9926 pSprite->y += y;
9927 }
9928 break;
9929 case SHRINKEREXPLOSION__STATIC:
9930 {
9931 int32_t x = ((sintable[(pSprite->ang+512)&2047])>>6);
9932 int32_t y = ((sintable[(pSprite->ang)&2047])>>6);
9933
9934 pSprite->x -= x;
9935 pSprite->y -= y;
9936
9937 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), 2048, 176+(252<<8)+(120<<16),PR_LIGHT_PRIO_HIGH_GAME);
9938
9939 pSprite->x += x;
9940 pSprite->y += y;
9941 }
9942 break;
9943 case FREEZEBLAST__STATIC:
9944 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), LIGHTRAD(spriteNum, pSprite)<<2, 72+(88<<8)+(140<<16),PR_LIGHT_PRIO_HIGH_GAME);
9945 break;
9946 case COOLEXPLOSION1__STATIC:
9947 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), LIGHTRAD(spriteNum, pSprite)<<2, 128+(0<<8)+(255<<16),PR_LIGHT_PRIO_HIGH_GAME);
9948 break;
9949 case SHRINKSPARK__STATIC:
9950 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), LIGHTRAD(spriteNum, pSprite), 176+(252<<8)+(120<<16),PR_LIGHT_PRIO_HIGH_GAME);
9951 break;
9952 case FIRELASER__STATIC:
9953 if (pSprite->statnum == STAT_PROJECTILE)
9954 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), 64 * pSprite->yrepeat, 255+(95<<8),PR_LIGHT_PRIO_LOW_GAME);
9955 break;
9956 case RPG__STATIC:
9957 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), 128 * pSprite->yrepeat, 255+(95<<8),PR_LIGHT_PRIO_LOW_GAME);
9958 break;
9959 case SHOTSPARK1__STATIC:
9960 if (actor[spriteNum].t_data[2] == 0) // check for first frame of action
9961 {
9962 int32_t x = ((sintable[(pSprite->ang+512)&2047])>>7);
9963 int32_t y = ((sintable[(pSprite->ang)&2047])>>7);
9964
9965 pSprite->x -= x;
9966 pSprite->y -= y;
9967
9968 G_AddGameLight(0, spriteNum, ((pSprite->yrepeat*tilesiz[pSprite->picnum].y)<<1), 8 * pSprite->yrepeat, 240+(160<<8)+(80<<16),PR_LIGHT_PRIO_LOW_GAME);
9969 actor[spriteNum].lightcount = 1;
9970
9971 pSprite->x += x;
9972 pSprite->y += y;
9973 }
9974 break;
9975 }
9976 }
9977 }
9978 #endif // POLYMER
9979
A_PlayAlertSound(int spriteNum)9980 void A_PlayAlertSound(int spriteNum)
9981 {
9982 if (DEER)
9983 return;
9984 if (RR)
9985 {
9986 if (sprite[spriteNum].extra > 0)
9987 {
9988 switch (DYNAMICTILEMAP(PN(spriteNum)))
9989 {
9990 case COOT__STATICRR: if (!RRRA || (krand2()&3) == 2) A_PlaySound(PRED_RECOG, spriteNum); break;
9991 case LTH__STATICRR: break;
9992 case BILLYCOCK__STATICRR:
9993 case BILLYRAY__STATICRR:
9994 case BRAYSNIPER__STATICRR: A_PlaySound(PIG_RECOG, spriteNum); break;
9995 case DOGRUN__STATICRR:
9996 case HULK__STATICRR:
9997 case HEN__STATICRR:
9998 case DRONE__STATICRR:
9999 case PIG__STATICRR:
10000 case RECON__STATICRR:
10001 case MINION__STATICRR:
10002 case COW__STATICRR:
10003 case VIXEN__STATICRR:
10004 case RABBIT__STATICRR: break;
10005 }
10006 }
10007 return;
10008 }
10009 if (sprite[spriteNum].extra > 0)
10010 {
10011 switch (DYNAMICTILEMAP(PN(spriteNum)))
10012 {
10013 case LIZTROOPONTOILET__STATIC:
10014 case LIZTROOPJUSTSIT__STATIC:
10015 case LIZTROOPSHOOT__STATIC:
10016 case LIZTROOPJETPACK__STATIC:
10017 case LIZTROOPDUCKING__STATIC:
10018 case LIZTROOPRUNNING__STATIC:
10019 case LIZTROOP__STATIC: A_PlaySound(REALITY ? 82 : PRED_RECOG, spriteNum); break;
10020 case LIZMAN__STATIC:
10021 case LIZMANSPITTING__STATIC:
10022 case LIZMANFEEDING__STATIC:
10023 case LIZMANJUMP__STATIC: A_PlaySound(REALITY ? 88 : CAPT_RECOG, spriteNum); break;
10024 case PIGCOP__STATIC:
10025 case PIGCOPDIVE__STATIC: A_PlaySound(REALITY ? 92 : PIG_RECOG, spriteNum); break;
10026 case RECON__STATIC: A_PlaySound(REALITY ? 97 : RECO_RECOG, spriteNum); break;
10027 case DRONE__STATIC: A_PlaySound(REALITY ? 101 : DRON_RECOG, spriteNum); break;
10028 case COMMANDER__STATIC:
10029 case COMMANDERSTAYPUT__STATIC: A_PlaySound(REALITY ? 106 : COMM_RECOG, spriteNum); break;
10030 case ORGANTIC__STATIC: if (REALITY) break; A_PlaySound(TURR_RECOG, spriteNum); break;
10031 case OCTABRAIN__STATIC:
10032 case OCTABRAINSTAYPUT__STATIC: A_PlaySound(REALITY ? 111 : OCTA_RECOG, spriteNum); break;
10033 case BOSS1__STATIC: S_PlaySound(REALITY ? ((sprite[spriteNum].pal != 0) ? 68 : 262) : BOS1_RECOG); break;
10034 case BOSS2__STATIC: S_PlaySound(REALITY ? 226 : ((sprite[spriteNum].pal == 1) ? BOS2_RECOG : WHIPYOURASS)); break;
10035 case BOSS3__STATIC: S_PlaySound(REALITY ? ((sprite[spriteNum].pal != 0) ? 118 : 261) : ((sprite[spriteNum].pal == 1) ? BOS3_RECOG : RIPHEADNECK)); break;
10036 case BOSS4__STATIC:
10037 case BOSS4STAYPUT__STATIC: if (REALITY) break; if (sprite[spriteNum].pal == 1) S_PlaySound(BOS4_RECOG); S_PlaySound(BOSS4_FIRSTSEE); break;
10038 case GREENSLIME__STATIC: A_PlaySound(REALITY ? 22 : SLIM_RECOG, spriteNum); break;
10039 }
10040 }
10041 }
10042
A_CheckSwitchTile(int spriteNum)10043 int A_CheckSwitchTile(int spriteNum)
10044 {
10045 // picnum 0 would oob in the switch below,
10046
10047 if (PN(spriteNum) <= 0)
10048 return 0;
10049
10050 // MULTISWITCH has 4 states so deal with it separately,
10051 // ACCESSSWITCH and ACCESSSWITCH2 are only active in one state so deal with
10052 // them separately.
10053
10054 if ((PN(spriteNum) >= MULTISWITCH && PN(spriteNum) <= MULTISWITCH + 3) || (PN(spriteNum) == ACCESSSWITCH || PN(spriteNum) == ACCESSSWITCH2))
10055 return 1;
10056
10057 if (RRRA && PN(spriteNum) >= MULTISWITCH2 && PN(spriteNum) <= MULTISWITCH2 + 3)
10058 return 1;
10059
10060 // Loop to catch both states of switches.
10061 for (bssize_t j=1; j>=0; j--)
10062 {
10063 switch (DYNAMICTILEMAP(PN(spriteNum)-j))
10064 {
10065 case RRTILE8464__STATICRR:
10066 if (RRRA) return 1;
10067 break;
10068 case NUKEBUTTON__STATIC:
10069 if (RR) return 1;
10070 break;
10071 case HANDPRINTSWITCH__STATIC:
10072 case ALIENSWITCH__STATIC:
10073 case MULTISWITCH__STATIC:
10074 case PULLSWITCH__STATIC:
10075 case HANDSWITCH__STATIC:
10076 case SLOTDOOR__STATIC:
10077 case LIGHTSWITCH__STATIC:
10078 case SPACELIGHTSWITCH__STATIC:
10079 case SPACEDOORSWITCH__STATIC:
10080 case FRANKENSTINESWITCH__STATIC:
10081 case LIGHTSWITCH2__STATIC:
10082 case POWERSWITCH1__STATIC:
10083 case LOCKSWITCH1__STATIC:
10084 case POWERSWITCH2__STATIC:
10085 case DIPSWITCH__STATIC:
10086 case DIPSWITCH2__STATIC:
10087 case TECHSWITCH__STATIC:
10088 case DIPSWITCH3__STATIC:
10089 return 1;
10090 }
10091 }
10092
10093 return 0;
10094 }
10095
G_RefreshLights(void)10096 void G_RefreshLights(void)
10097 {
10098 #ifdef POLYMER
10099 if (Numsprites && videoGetRenderMode() == REND_POLYMER)
10100 {
10101 int statNum = 0;
10102
10103 do
10104 {
10105 int spriteNum = headspritestat[statNum++];
10106
10107 while (spriteNum >= 0)
10108 {
10109 A_DoLight(spriteNum);
10110 spriteNum = nextspritestat[spriteNum];
10111 }
10112 }
10113 while (statNum < MAXSTATUS);
10114 }
10115 #endif
10116 }
10117
G_MoveWorld(void)10118 void G_MoveWorld(void)
10119 {
10120 extern double g_moveActorsTime, g_moveWorldTime;
10121 const double worldTime = timerGetHiTicks();
10122
10123 if (!DEER)
10124 {
10125 G_MoveZombieActors(); //ST 2
10126 G_MoveWeapons(); //ST 4
10127 G_MoveTransports(); //ST 9
10128 }
10129
10130 G_MovePlayers(); //ST 10
10131 G_MoveFallers(); //ST 12
10132 if (!DEER)
10133 G_MoveMisc(); //ST 5
10134
10135 const double actorsTime = timerGetHiTicks();
10136
10137 G_MoveActors(); //ST 1
10138
10139 g_moveActorsTime = (1-0.033)*g_moveActorsTime + 0.033*(timerGetHiTicks()-actorsTime);
10140
10141 if (DEER)
10142 {
10143 sub_56EA8();
10144 ghtarget_move();
10145 gharrow_move();
10146 ghdeploy_move();
10147 sub_519E8(ud.level_number);
10148 sub_5524C();
10149 }
10150
10151 // XXX: Has to be before effectors, in particular movers?
10152 // TODO: lights in moving sectors ought to be interpolated
10153 G_DoEffectorLights();
10154 if (!DEER)
10155 {
10156 G_MoveEffectors(); //ST 3
10157 G_MoveStandables(); //ST 6
10158 }
10159
10160 G_RefreshLights();
10161 G_DoSectorAnimations();
10162 if (!DEER)
10163 G_MoveFX(); //ST 11
10164
10165 if (RR && numplayers < 2 && g_thunderOn)
10166 G_Thunder();
10167
10168 g_moveWorldTime = (1-0.033)*g_moveWorldTime + 0.033*(timerGetHiTicks()-worldTime);
10169 }
10170