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, &sectNum);
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(&sector[sectNum].ceilingz) == -1)
3776     {
3777         int const newZ = sector[sectNum].floorz;
3778         SetAnimation(sectNum,&sector[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(&sector[sectNum].ceilingz) == -1)
3787     {
3788         int const newZ = sector[nextsectorneighborz(sectNum, sector[sectNum].ceilingz,-1,-1)].ceilingz;
3789         SetAnimation(sectNum,&sector[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 = &sector[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,&sectNum);
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     = &sector[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(&sector[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     = &sector[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(&sector[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 *)&sector[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, &sectnum);
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