1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010 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 #include "duke3d.h"
24 #include "demo.h"
25 
26 #ifdef __ANDROID__
27 #include "android.h"
28 #endif
29 
30 int32_t PHEIGHT = PHEIGHT_DUKE;
31 
32 int32_t lastvisinc;
33 hudweapon_t hudweap;
34 
35 #ifdef SPLITSCREEN_MOD_HACKS
36 static int32_t g_snum;
37 #endif
38 
39 extern int32_t g_levelTextTime, ticrandomseed;
40 
41 int32_t g_numObituaries = 0;
42 int32_t g_numSelfObituaries = 0;
43 
44 
45 int const icon_to_inv[ICON_MAX] = { GET_FIRSTAID, GET_FIRSTAID, GET_STEROIDS, GET_HOLODUKE,
46                                     GET_JETPACK,  GET_HEATS,    GET_SCUBA,    GET_BOOTS,    GET_SHIELD };
47 
48 int const inv_to_icon[GET_MAX] = { ICON_STEROIDS, ICON_SHIELD, ICON_SCUBA, ICON_HOLODUKE, ICON_JETPACK, ICON_NONE,
49                                    ICON_NONE,     ICON_HEATS,  ICON_NONE,  ICON_FIRSTAID, ICON_BOOTS };
50 
P_AddKills(DukePlayer_t * const pPlayer,uint16_t kills)51 void P_AddKills(DukePlayer_t * const pPlayer, uint16_t kills)
52 {
53     pPlayer->actors_killed += kills;
54 }
55 
P_UpdateScreenPal(DukePlayer_t * const pPlayer)56 void P_UpdateScreenPal(DukePlayer_t * const pPlayer)
57 {
58     int       inWater       = 0;
59     int const playerSectnum = pPlayer->cursectnum;
60 
61     if (pPlayer->drug_mode)
62         pPlayer->palette = DRUGPAL;
63     else if (pPlayer->heat_on)
64         pPlayer->palette = SLIMEPAL;
65     else if (playerSectnum < 0)
66         pPlayer->palette = BASEPAL;
67     else if (sector[playerSectnum].ceilingpicnum >= FLOORSLIME && sector[playerSectnum].ceilingpicnum <= FLOORSLIME + 2)
68     {
69         pPlayer->palette = SLIMEPAL;
70         inWater          = 1;
71     }
72     else
73     {
74         pPlayer->palette     = (sector[pPlayer->cursectnum].lotag == ST_2_UNDERWATER) ? WATERPAL : BASEPAL;
75         inWater              = 1;
76     }
77 
78     g_restorePalette = 1+inWater;
79 }
80 
P_IncurDamage(DukePlayer_t * const pPlayer)81 static void P_IncurDamage(DukePlayer_t * const pPlayer)
82 {
83     sprite[pPlayer->i].extra -= pPlayer->extra_extra8>>8;
84 
85     int playerDamage = sprite[pPlayer->i].extra - pPlayer->last_extra;
86 
87     if (playerDamage >= 0)
88         return;
89 
90     pPlayer->extra_extra8 = 0;
91 
92     if ((!RR && pPlayer->inv_amount[GET_SHIELD] > 0) || (RR && pPlayer->inv_amount[GET_STEROIDS] > 0 && pPlayer->inv_amount[GET_STEROIDS] < 400))
93     {
94         int const shieldDamage = playerDamage * (20 + (krand2()%30)) / 100;
95 
96         playerDamage                     -= shieldDamage;
97         if (!RR)
98         {
99             pPlayer->inv_amount[GET_SHIELD] += shieldDamage;
100 
101             if (pPlayer->inv_amount[GET_SHIELD] < 0)
102             {
103                 playerDamage += pPlayer->inv_amount[GET_SHIELD];
104                 pPlayer->inv_amount[GET_SHIELD] = 0;
105             }
106         }
107     }
108 
109     if (RR)
110     {
111         int guts = 0;
112         if (pPlayer->drink_amt > 31 && pPlayer->drink_amt < 65)
113             guts++;
114         if (pPlayer->eat_amt > 31 && pPlayer->eat_amt < 65)
115             guts++;
116 
117         switch (guts)
118         {
119             case 1:
120                 playerDamage = (int)(playerDamage*0.75);
121                 break;
122             case 2:
123                 playerDamage = (int)(playerDamage*0.25);
124                 break;
125         }
126     }
127 
128     sprite[pPlayer->i].extra = pPlayer->last_extra + playerDamage;
129 }
130 
P_QuickKill(DukePlayer_t * const pPlayer)131 void P_QuickKill(DukePlayer_t * const pPlayer)
132 {
133     P_PalFrom(pPlayer, 48, 48,48,48);
134 
135     sprite[pPlayer->i].extra = 0;
136     sprite[pPlayer->i].cstat |= 32768;
137 
138     if (ud.god == 0)
139         A_DoGuts(pPlayer->i,JIBS6,8);
140 }
141 
Proj_DoWaterTracers(vec3_t startPos,vec3_t const * endPos,int n,int playerNum)142 static void Proj_DoWaterTracers(vec3_t startPos, vec3_t const *endPos, int n, int playerNum)
143 {
144     const DukePlayer_t *const ps = g_player[playerNum].ps;
145     int16_t sectNum = -1;
146     if (REALITY)
147     {
148         if (playerNum < 0)
149             return;
150         sectNum = g_player[playerNum].ps->cursectnum;
151     }
152     else
153         playerNum = 0;
154 
155     if ((klabs(startPos.x - endPos->x) + klabs(startPos.y - endPos->y)) < 3084)
156         return;
157 
158     vec3_t const v_inc = { tabledivide32_noinline(endPos->x - startPos.x, n + 1), tabledivide32_noinline(endPos->y - startPos.y, n + 1),
159                            tabledivide32_noinline(endPos->z - startPos.z, n + 1) };
160 
161     for (bssize_t i=n; i>0; i--)
162     {
163         startPos.x += v_inc.x;
164         startPos.y += v_inc.y;
165         startPos.z += v_inc.z;
166 
167         updatesector(startPos.x, startPos.y, &sectNum);
168 
169         if (sectNum < 0)
170             continue;
171         if (REALITY && ps->curr_weapon == GROW_WEAPON)
172         {
173             A_InsertSprite(sectNum, startPos.x, startPos.y, startPos.z, GROWSPARK, -16, 1, 1, 0, 0, 0,
174                            g_player[playerNum].ps->i, 5);
175         }
176         else if (sector[sectNum].lotag == ST_2_UNDERWATER)
177         {
178             int32_t r1 = krand2(), r2 = krand2(), r3 = krand2();
179             if (REALITY)
180                 swap(&r1, &r3);
181             A_InsertSprite(sectNum, startPos.x, startPos.y, startPos.z, WATERBUBBLE, -32, 4 + (r3 & 3), 4 + (r2 & 3), r1 & 2047, 0, 0,
182                            g_player[playerNum].ps->i, 5);
183         }
184         else
185         {
186             A_InsertSprite(sectNum, startPos.x, startPos.y, startPos.z, SMALLSMOKE, -32, 14, 14, 0, 0, 0,
187                            g_player[playerNum].ps->i, 5);
188         }
189     }
190 }
191 
A_GetHitscanRange(int spriteNum)192 int32_t A_GetHitscanRange(int spriteNum)
193 {
194     int const zOffset = (PN(spriteNum) == APLAYER) ? (40<<8) : 0;
195     hitdata_t hitData;
196 
197     SZ(spriteNum) -= zOffset;
198     hitscan((const vec3_t *)&sprite[spriteNum], SECT(spriteNum), sintable[(SA(spriteNum) + 512) & 2047],
199             sintable[SA(spriteNum) & 2047], 0, &hitData, CLIPMASK1);
200     SZ(spriteNum) += zOffset;
201 
202     return (FindDistance2D(hitData.pos.x - SX(spriteNum), hitData.pos.y - SY(spriteNum)));
203 }
204 
A_FindTargetSprite(const spritetype * pSprite,int projAng,int projecTile)205 static int A_FindTargetSprite(const spritetype *pSprite, int projAng, int projecTile)
206 {
207     static int const aimstats[] = {
208         STAT_PLAYER, STAT_DUMMYPLAYER, STAT_ACTOR, STAT_ZOMBIEACTOR
209     };
210 
211     int const playerNum = pSprite->picnum == APLAYER ? P_GetP(pSprite) : -1;
212 
213     if (playerNum != -1)
214     {
215         if (!g_player[playerNum].ps->auto_aim && (!RRRA || projecTile != RPG2))
216             return -1;
217 
218         if (g_player[playerNum].ps->auto_aim == 2)
219         {
220             switch (DYNAMICTILEMAP(projecTile))
221             {
222             case TONGUE__STATIC:
223             case FREEZEBLAST__STATIC:
224             case SHRINKSPARK__STATIC:
225             case SHRINKER__STATIC:
226             case RPG__STATIC:
227             case FIRELASER__STATIC:
228             case SPIT__STATIC:
229             case COOLEXPLOSION1__STATIC:
230                 return -1;
231             default:
232                 break;
233             }
234         }
235     }
236 
237     int const spriteAng = pSprite->ang;
238 
239     int isShrinker = (!RR && pSprite->picnum == APLAYER && g_player[playerNum].ps->curr_weapon == SHRINKER_WEAPON);
240     int isFreezer  = (!RR && !REALITY && pSprite->picnum == APLAYER && g_player[playerNum].ps->curr_weapon == FREEZE_WEAPON);
241 
242     if (WW2GI)
243     {
244         isShrinker = (pSprite->picnum == APLAYER && PWEAPON(playerNum, g_player[playerNum].ps->curr_weapon, WorksLike) == SHRINKER_WEAPON);
245         isFreezer  = (pSprite->picnum == APLAYER && PWEAPON(playerNum, g_player[playerNum].ps->curr_weapon, WorksLike) == FREEZE_WEAPON);
246     }
247 
248     vec2_t const d1 = { sintable[(spriteAng + 512 - projAng) & 2047], sintable[(spriteAng - projAng) & 2047] };
249     vec2_t const d2 = { sintable[(spriteAng + 512 + projAng) & 2047], sintable[(spriteAng + projAng) & 2047] };
250     vec2_t const d3 = { sintable[(spriteAng + 512) & 2047], sintable[spriteAng & 2047] };
251 
252     int lastDist   = INT32_MAX;
253     int bestSprite = -1;
254 
255     for (bssize_t k=0; k<4; k++)
256     {
257         if (bestSprite >= 0)
258             break;
259 
260         for (bssize_t spriteNum=headspritestat[aimstats[k]]; spriteNum >= 0; spriteNum=nextspritestat[spriteNum])
261         {
262             if ((sprite[spriteNum].xrepeat > 0 && sprite[spriteNum].extra >= 0 &&
263                  (sprite[spriteNum].cstat & (257 + 32768)) == 257) &&
264                 (A_CheckEnemySprite(&sprite[spriteNum]) || k < 2))
265             {
266                 if (A_CheckEnemySprite(&sprite[spriteNum]) || PN(spriteNum) == APLAYER)
267                 {
268                     if (PN(spriteNum) == APLAYER && pSprite->picnum == APLAYER && pSprite != &sprite[spriteNum] &&
269                         (GTFLAGS(GAMETYPE_PLAYERSFRIENDLY) ||
270                          (GTFLAGS(GAMETYPE_TDM) && g_player[P_Get(spriteNum)].ps->team == g_player[playerNum].ps->team)))
271                         continue;
272 
273                     if ((isShrinker && sprite[spriteNum].xrepeat < 30
274                         && (PN(spriteNum) == SHARK || !(!RR && PN(spriteNum) >= GREENSLIME && PN(spriteNum) <= GREENSLIME + 7)))
275                         || (isFreezer && sprite[spriteNum].pal == 1))
276                         continue;
277                 }
278 
279                 vec2_t const vd = { (SX(spriteNum) - pSprite->x), (SY(spriteNum) - pSprite->y) };
280 
281                 if ((d1.y * vd.x <= d1.x * vd.y) && (d2.y * vd.x >= d2.x * vd.y))
282                 {
283                     int const spriteDist = mulscale14(d3.x, vd.x) + mulscale14(d3.y, vd.y);
284 
285                     if (spriteDist > 512 && spriteDist < lastDist)
286                     {
287                         int onScreen = 1;
288 
289                         if (pSprite->picnum == APLAYER)
290                         {
291                             const DukePlayer_t *const ps = g_player[P_GetP(pSprite)].ps;
292                             if (REALITY && ps->auto_aim != 4)
293                             {
294                                 float const viewang = RT_GetAngle(fix16_to_float(ps->q16horiz + ps->q16horizoff - F16(100)), 128.f) * 1024.f / fPI;
295                                 int const dz = SZ(spriteNum) - pSprite->z + (PN(spriteNum) == ROTATEGUN ? ZOFFSET5 : 0);
296                                 float const targetang = RT_GetAngle(-dz * 0.0625, spriteDist) * 1024.f / fPI;
297                                 onScreen = abs(targetang - viewang) < projAng;
298                             }
299                             else
300                                 onScreen = (klabs(scale(SZ(spriteNum)-pSprite->z,10,spriteDist)-fix16_to_int(ps->q16horiz+ps->q16horizoff-F16(100))) < 100);
301                         }
302 
303                         int const zOffset = (!RR && ((!REALITY && PN(spriteNum) == ORGANTIC) || PN(spriteNum) == ROTATEGUN)) ? 0 : ZOFFSET5;
304                         int const canSee = cansee(SX(spriteNum), SY(spriteNum), SZ(spriteNum) - zOffset, SECT(spriteNum),
305                                                   pSprite->x, pSprite->y, pSprite->z - ZOFFSET5, pSprite->sectnum);
306 
307                         if (onScreen && canSee)
308                         {
309                             lastDist   = spriteDist;
310                             bestSprite = spriteNum;
311                         }
312                     }
313                 }
314             }
315         }
316     }
317 
318     return bestSprite;
319 }
320 
CheckShootSwitchTile(int tileNum)321 static int CheckShootSwitchTile(int tileNum)
322 {
323     return tileNum == DIPSWITCH || tileNum == DIPSWITCH + 1 || tileNum == DIPSWITCH2 || tileNum == DIPSWITCH2 + 1 ||
324            tileNum == DIPSWITCH3 || tileNum == DIPSWITCH3 + 1 || tileNum == HANDSWITCH || tileNum == HANDSWITCH + 1 ||
325            (RRRA && tileNum == RRTILE8660);
326 }
327 
safeldist(int32_t spriteNum,const void * pSprite)328 static int32_t safeldist(int32_t spriteNum, const void *pSprite)
329 {
330     int32_t distance = ldist(&sprite[spriteNum], pSprite);
331     return distance ? distance : 1;
332 }
333 
safeFindDistance2D(int x,int y)334 static int32_t safeFindDistance2D(int x, int y)
335 {
336     int32_t distance = FindDistance2D(x, y);
337     return distance ? distance : 1;
338 }
339 
340 // flags:
341 //  1: do sprite center adjustment (cen-=(8<<8)) for GREENSLIME or ROTATEGUN
342 //  2: do auto getangle only if not RECON (if clear, do unconditionally)
GetAutoAimAng(int spriteNum,int playerNum,int projecTile,int zAdjust,int aimFlags,const vec3_t * startPos,int projVel,int32_t * pZvel,int * pAng)343 static int GetAutoAimAng(int spriteNum, int playerNum, int projecTile, int zAdjust, int aimFlags,
344                                const vec3_t *startPos, int projVel, int32_t *pZvel, int *pAng)
345 {
346     int returnSprite = -1;
347     int aimang;
348 
349     Bassert((unsigned)playerNum < MAXPLAYERS);
350 
351     if (projecTile == DN64TILE2606)
352         aimang = 192;
353     else
354     {
355         Gv_SetVar(g_aimAngleVarID, (g_player[playerNum].ps->auto_aim == 3 && (!RRRA || projecTile != RPG2)) ? AUTO_AIM_ANGLE<<1 : AUTO_AIM_ANGLE, spriteNum, playerNum);
356 
357         VM_OnEvent(EVENT_GETAUTOAIMANGLE, spriteNum, playerNum);
358 
359         aimang = Gv_GetVar(g_aimAngleVarID, spriteNum, playerNum);
360     }
361     if (aimang > 0)
362         returnSprite = A_FindTargetSprite(&sprite[spriteNum], aimang, projecTile);
363 
364     if (returnSprite >= 0)
365     {
366         const uspritetype *const pSprite = (uspritetype *)&sprite[returnSprite];
367         int                      zCenter = 2 * (pSprite->xrepeat * tilesiz[pSprite->picnum].y) + zAdjust;
368 
369         if ((aimFlags&1) && !RR &&
370             ((pSprite->picnum >= GREENSLIME && pSprite->picnum <= GREENSLIME + 7) || pSprite->picnum == ROTATEGUN))
371             zCenter -= ZOFFSET3;
372 
373         int spriteDist = safeldist(g_player[playerNum].ps->i, &sprite[returnSprite]);
374         *pZvel         = tabledivide32_noinline((pSprite->z - startPos->z - zCenter) * projVel, spriteDist);
375 
376         if (!(aimFlags&2) || sprite[returnSprite].picnum != RECON)
377             *pAng = getangle(pSprite->x-startPos->x, pSprite->y-startPos->y);
378     }
379 
380     return returnSprite;
381 }
382 
Proj_MaybeAddSpread(int doSpread,int32_t * zvel,int * shootAng,int zRange,int angRange)383 static void Proj_MaybeAddSpread(int doSpread, int32_t *zvel, int *shootAng, int zRange, int angRange)
384 {
385     if (doSpread)
386     {
387         // Ranges <= 1 mean no spread at all. A range of 1 calls krand2() though.
388         if (zRange > 0)
389             *zvel += (zRange >> 1) - krand2() % zRange;
390 
391         if (angRange > 0)
392             *shootAng += (angRange >> 1) - krand2() % angRange;
393     }
394 }
395 
Proj_MaybeAddSpreadSwapped(int doSpread,int32_t * zvel,int * shootAng,int zRange,int angRange)396 static void Proj_MaybeAddSpreadSwapped(int doSpread, int32_t *zvel, int *shootAng, int zRange, int angRange)
397 {
398     if (doSpread)
399     {
400         // Ranges <= 1 mean no spread at all. A range of 1 calls krand2() though.
401         if (angRange > 0)
402             *shootAng += (angRange >> 1) - krand2() % angRange;
403 
404         if (zRange > 0)
405             *zvel += (zRange >> 1) - krand2() % zRange;
406     }
407 }
408 
409 // Prepare hitscan weapon fired from player p.
P_PreFireHitscan(int spriteNum,int playerNum,int projecTile,vec3_t * srcVect,int32_t * zvel,int * shootAng,int accurateAim,int doSpread)410 static void P_PreFireHitscan(int spriteNum, int playerNum, int projecTile, vec3_t *srcVect, int32_t *zvel, int *shootAng,
411                              int accurateAim, int doSpread)
412 {
413     int angRange  = (RR && projecTile == SHOTGUN) ? 128 : 32;
414     int zRange    = 256;
415     int aimSprite = GetAutoAimAng(spriteNum, playerNum, projecTile, 5 << 8, 0 + 1, srcVect, 256, zvel, shootAng);
416 
417     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
418 
419     Gv_SetVar(g_angRangeVarID, angRange, spriteNum, playerNum);
420     Gv_SetVar(g_zRangeVarID, zRange, spriteNum, playerNum);
421 
422     VM_OnEvent(EVENT_GETSHOTRANGE, spriteNum, playerNum);
423 
424     angRange = Gv_GetVar(g_angRangeVarID, spriteNum, playerNum);
425     zRange   = Gv_GetVar(g_zRangeVarID, spriteNum, playerNum);
426 
427     if (accurateAim)
428     {
429         if (!pPlayer->auto_aim)
430         {
431             hitdata_t hitData;
432 
433             *zvel = fix16_to_int(F16(100)-pPlayer->q16horiz-pPlayer->q16horizoff)<<5;
434 
435             hitscan(srcVect, sprite[spriteNum].sectnum, sintable[(*shootAng + 512) & 2047],
436                     sintable[*shootAng & 2047], *zvel << 6, &hitData, CLIPMASK1);
437 
438             if (hitData.sprite != -1)
439             {
440                 int const statNumMap = ((1 << STAT_ACTOR) | (1 << STAT_ZOMBIEACTOR) | (1 << STAT_PLAYER) | (1 << STAT_DUMMYPLAYER));
441                 int const statNum    = sprite[hitData.sprite].statnum;
442 
443                 if ((unsigned)statNum <= 30 && (statNumMap & (1 << statNum)))
444                     aimSprite = hitData.sprite;
445             }
446         }
447 
448         if (aimSprite == -1)
449             goto notarget;
450     }
451     else
452     {
453         if (aimSprite == -1)  // no target
454         {
455 notarget:
456             *zvel = fix16_to_int(F16(100)-pPlayer->q16horiz-pPlayer->q16horizoff)<<5;
457         }
458 
459         if (REALITY && !accurateAim)
460         {
461             if (projecTile != DN64TILE2599)
462                 Proj_MaybeAddSpread(doSpread, zvel, shootAng, zRange, angRange);
463         }
464         else
465             Proj_MaybeAddSpreadSwapped(doSpread, zvel, shootAng, zRange, angRange);
466     }
467 
468     srcVect->z -= (2<<8);
469 }
470 
471 // Hitscan weapon fired from actor (sprite s);
A_PreFireHitscan(const spritetype * pSprite,vec3_t * const srcVect,int32_t * const zvel,int * const shootAng,int const doSpread)472 static void A_PreFireHitscan(const spritetype *pSprite, vec3_t * const srcVect, int32_t * const zvel, int * const shootAng, int const doSpread)
473 {
474     int const           playerNum  = A_FindPlayer(pSprite, NULL);
475     const DukePlayer_t *pPlayer    = g_player[playerNum].ps;
476     int const           playerDist = safeldist(pPlayer->i, pSprite);
477 
478     srcVect->z -= ZOFFSET6;
479 
480     *zvel = tabledivide32_noinline((pPlayer->pos.z - srcVect->z) << 8, playerDist);
481 
482     if (pSprite->picnum == BOSS1)
483         *shootAng = getangle(pPlayer->pos.x - srcVect->x, pPlayer->pos.y - srcVect->y);
484 
485     Proj_MaybeAddSpread(doSpread, zvel, shootAng, 256, 128 >> (uint8_t)(pSprite->picnum != BOSS1));
486 }
487 
Proj_DoHitscan(int spriteNum,int32_t const cstatmask,const vec3_t * const srcVect,int zvel,int const shootAng,hitdata_t * const hitData)488 static int Proj_DoHitscan(int spriteNum, int32_t const cstatmask, const vec3_t * const srcVect, int zvel, int const shootAng, hitdata_t * const hitData)
489 {
490     spritetype *const pSprite = &sprite[spriteNum];
491 
492     pSprite->cstat &= ~cstatmask;
493     hitscan(srcVect, pSprite->sectnum, sintable[(shootAng + 512) & 2047], sintable[shootAng & 2047], zvel << 6, hitData, CLIPMASK1);
494 
495     if (RRRA)
496     {
497         if (((sector[hitData->sect].lotag == 160 && zvel > 0) || (sector[hitData->sect].lotag == 161 && zvel < 0))
498             && hitData->sprite == -1 && hitData->wall == -1)
499         {
500             for (int spriteNum = 0; spriteNum < MAXSPRITES; spriteNum++)
501             {
502                 if (sprite[spriteNum].sectnum == hitData->sect && sprite[spriteNum].picnum == SECTOREFFECTOR
503                     && sprite[spriteNum].lotag == SE_7_TELEPORT)
504                 {
505                     vec3_t const newVect = {
506                         hitData->pos.x + (sprite[OW(spriteNum)].x - sprite[spriteNum].x),
507                         hitData->pos.y + (sprite[OW(spriteNum)].y - sprite[spriteNum].y),
508                         sector[hitData->sect].lotag == 161 ? sector[sprite[OW(spriteNum)].sectnum].floorz
509                         : sector[sprite[OW(spriteNum)].sectnum].ceilingz
510                     };
511 
512                     hitscan(&newVect, sprite[OW(spriteNum)].sectnum, sintable[(shootAng + 512) & 2047], sintable[shootAng & 2047], zvel << 6,
513                         hitData, CLIPMASK1);
514                     break;
515                 }
516             }
517         }
518     }
519     pSprite->cstat |= cstatmask;
520 
521     return (hitData->sect < 0);
522 }
523 
SectorContainsSE13(int const sectNum)524 static int SectorContainsSE13(int const sectNum)
525 {
526     if (sectNum >= 0)
527     {
528         for (bssize_t SPRITES_OF_SECT(sectNum, i))
529         {
530             if (sprite[i].statnum == STAT_EFFECTOR && sprite[i].lotag == SE_13_EXPLOSIVE)
531                 return 1;
532         }
533     }
534     return 0;
535 }
536 
537 // Maybe handle bit 2 (swap wall bottoms).
538 // (in that case walltype *hitwal may be stale)
HandleHitWall(hitdata_t * hitData)539 static inline void HandleHitWall(hitdata_t *hitData)
540 {
541     uwalltype const * const hitWall = (uwalltype *)&wall[hitData->wall];
542 
543     if ((hitWall->cstat & 2) && redwallp(hitWall) && (hitData->pos.z >= sector[hitWall->nextsector].floorz))
544         hitData->wall = hitWall->nextwall;
545 }
546 
547 // Common "spawn blood?" predicate.
548 // minzdiff: minimal "step" height for blood to be spawned
Proj_CheckBlood(vec3_t const * const srcVect,hitdata_t const * const hitData,int const bloodRange,int const minZdiff)549 static int Proj_CheckBlood(vec3_t const *const srcVect, hitdata_t const *const hitData, int const bloodRange, int const minZdiff)
550 {
551     if (hitData->wall < 0 || hitData->sect < 0)
552         return 0;
553 
554     uwalltype const *const hitWall = (uwalltype *)&wall[hitData->wall];
555 
556     if ((FindDistance2D(srcVect->x - hitData->pos.x, srcVect->y - hitData->pos.y) < bloodRange)
557         && (hitWall->overpicnum != BIGFORCE && (hitWall->cstat & 16) == 0)
558         && (sector[hitData->sect].lotag == 0)
559         && (hitWall->nextsector < 0 || (sector[hitWall->nextsector].lotag == 0 && sector[hitData->sect].lotag == 0
560                                         && sector[hitData->sect].floorz - sector[hitWall->nextsector].floorz > minZdiff)))
561         return 1;
562 
563     return 0;
564 }
565 
A_Shoot(int const spriteNum,int projecTile)566 int A_Shoot(int const spriteNum, int projecTile)
567 {
568     Bassert(projecTile >= 0);
569 
570     spritetype *const   pSprite       = &sprite[spriteNum];
571     int const           spriteSectnum = pSprite->sectnum;
572     int const           playerNum     = (pSprite->picnum == APLAYER) ? P_GetP(pSprite) : -1;
573     DukePlayer_t *const pPlayer       = playerNum >= 0 ? g_player[playerNum].ps : NULL;
574     int32_t             Zvel          = 0;
575 
576     hitdata_t hitData;
577     int       shootAng;
578     vec3_t    startPos;
579     int       vel;
580 
581     if (pPlayer != NULL)
582     {
583         startPos            = *(vec3_t *)pPlayer;
584         startPos.z          += pPlayer->pyoff + ZOFFSET6;
585         shootAng          = fix16_to_int(pPlayer->q16ang);
586         if (!RRRA)
587             pPlayer->crack_time = 777;
588     }
589     else
590     {
591         shootAng = pSprite->ang;
592         startPos   = *(vec3_t *)pSprite;
593         startPos.z -= (((pSprite->yrepeat * tilesiz[pSprite->picnum].y)<<1) - ZOFFSET6);
594 
595         if (RR || pSprite->picnum != ROTATEGUN)
596         {
597             startPos.z -= (7<<8);
598 
599             if (A_CheckEnemySprite(pSprite) && (RR || PN(spriteNum) != COMMANDER))
600             {
601                 startPos.x += (sintable[(shootAng+1024+96)&2047]>>7);
602                 startPos.y += (sintable[(shootAng+512+96)&2047]>>7);
603             }
604         }
605 
606 #ifdef POLYMER
607         switch (DYNAMICTILEMAP(projecTile))
608         {
609             case FIRELASER__STATIC:
610             case SHOTGUN__STATIC:
611             case SHOTSPARK1__STATIC:
612             case CHAINGUN__STATIC:
613             case RPG__STATIC:
614             case MORTER__STATIC:
615                 {
616                     vec2_t const v = { ((sintable[(pSprite->ang + 512) & 2047]) >> 7),
617                                        ((sintable[(pSprite->ang) & 2047]) >> 7) };
618 
619                     pSprite->x += v.x;
620                     pSprite->y += v.y;
621                     G_AddGameLight(0, spriteNum, PHEIGHT, 8192, 255 + (95 << 8), PR_LIGHT_PRIO_MAX_GAME);
622                     actor[spriteNum].lightcount = 2;
623                     pSprite->x -= v.x;
624                     pSprite->y -= v.y;
625                 }
626 
627                 break;
628             }
629 #endif // POLYMER
630     }
631 
632     switch (DYNAMICTILEMAP(projecTile))
633     {
634         case BLOODSPLAT1__STATIC:
635         case BLOODSPLAT2__STATIC:
636         case BLOODSPLAT3__STATIC:
637         case BLOODSPLAT4__STATIC:
638             shootAng += 64 - (krand2() & 127);
639             if (playerNum < 0)
640                 shootAng += 1024;
641             Zvel = 1024 - (krand2() & 2047);
642             fallthrough__;
643         case KNEE__STATIC:
644         case SLINGBLADE__STATICRR:
645             if (RR && !RRRA && projecTile == SLINGBLADE)
646                 break;
647 growspark_rr:
648             if (projecTile == KNEE || (RR && projecTile == GROWSPARK) || (RRRA && projecTile == SLINGBLADE))
649             {
650                 if (playerNum >= 0)
651                 {
652                     Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) << 5;
653                     startPos.z += (6 << 8);
654                     shootAng += 15;
655                 }
656                 else
657                 {
658                     int32_t   playerDist;
659                     int const playerSprite = g_player[A_FindPlayer(pSprite, &playerDist)].ps->i;
660                     Zvel                   = tabledivide32_noinline((sprite[playerSprite].z - startPos.z) << 8, playerDist + 1);
661                     shootAng             = getangle(sprite[playerSprite].x - startPos.x, sprite[playerSprite].y - startPos.y);
662                 }
663             }
664 
665             Proj_DoHitscan(spriteNum, 0, &startPos, Zvel, shootAng, &hitData);
666 
667             if (projecTile >= BLOODSPLAT1 && projecTile <= BLOODSPLAT4)
668             {
669                 if (Proj_CheckBlood(&startPos, &hitData, 1024, 16 << 8))
670                 {
671                     const uwalltype *const hitwal = (uwalltype *)&wall[hitData.wall];
672 
673                     if (SectorContainsSE13(hitwal->nextsector))
674                         return -1;
675 
676                     if (hitwal->nextwall >= 0 && wall[hitwal->nextwall].hitag != 0)
677                         return -1;
678 
679                     if (hitwal->hitag == 0)
680                     {
681                         int const spawnedSprite = A_Spawn(spriteNum, projecTile);
682                         sprite[spawnedSprite].xvel = -12;
683                         sprite[spawnedSprite].ang
684                         = (getangle(hitwal->x - wall[hitwal->point2].x, hitwal->y - wall[hitwal->point2].y) + 512) & 2047;
685                         sprite[spawnedSprite].pos = hitData.pos;
686                         sprite[spawnedSprite].cstat |= (krand2() & 4);
687                         if (REALITY)
688                         {
689                             sprite[spawnedSprite].ang = (sprite[spawnedSprite].ang + 1024) & 2047;
690                             sprite[spawnedSprite].pos.x += sintable[(sprite[spawnedSprite].ang + 512) & 2047] >> 10;
691                             sprite[spawnedSprite].pos.y += sintable[sprite[spawnedSprite].ang & 2047] >> 10;
692                         }
693                         A_SetSprite(spawnedSprite, CLIPMASK0);
694                         setsprite(spawnedSprite, (vec3_t *)&sprite[spawnedSprite]);
695                         if (PN(spriteNum) == OOZFILTER || (!RR && PN(spriteNum) == NEWBEAST))
696                             sprite[spawnedSprite].pal = 6;
697                     }
698                 }
699 
700                 return -1;
701             }
702 
703             if (hitData.sect < 0)
704                 break;
705 
706             if (klabs(startPos.x - hitData.pos.x) + klabs(startPos.y - hitData.pos.y) < 1024)
707             {
708                 if (hitData.wall >= 0 || hitData.sprite >= 0)
709                 {
710                     int kneeSprite = A_InsertSprite(hitData.sect, hitData.pos.x, hitData.pos.y, hitData.pos.z,
711                         (RRRA && projecTile == SLINGBLADE) ? SLINGBLADE : KNEE,-15,0,0,shootAng,32,0,spriteNum,4);
712                     sprite[kneeSprite].extra += (RRRA && projecTile == SLINGBLADE) ? 50 : (krand2()&7);
713 
714                     if (playerNum >= 0)
715                     {
716                         int k = A_Spawn(kneeSprite, SMALLSMOKE);
717                         sprite[k].z -= ZOFFSET3;
718                         if (!RR || projecTile == KNEE)
719                             A_PlaySound(REALITY ? 0 : KICK_HIT, kneeSprite);
720                         else if (RRRA && projecTile == SLINGBLADE)
721                             A_PlaySound(260, kneeSprite);
722                     }
723 
724                     if (pPlayer != NULL && pPlayer->inv_amount[GET_STEROIDS] > 0 && pPlayer->inv_amount[GET_STEROIDS] < 400)
725                         sprite[kneeSprite].extra += (pPlayer->max_player_health>>2);
726 
727                     if (hitData.sprite >= 0 && sprite[hitData.sprite].picnum != ACCESSSWITCH && sprite[hitData.sprite].picnum != ACCESSSWITCH2)
728                     {
729                         A_DamageObject(hitData.sprite, kneeSprite);
730                         if (playerNum >= 0)
731                             P_ActivateSwitch(playerNum, hitData.sprite, 1);
732                     }
733                     else if (hitData.wall >= 0)
734                     {
735                         HandleHitWall(&hitData);
736 
737                         if (hitData.wall >= 0 && wall[hitData.wall].picnum != ACCESSSWITCH && wall[hitData.wall].picnum != ACCESSSWITCH2)
738                         {
739                             A_DamageWall(kneeSprite, hitData.wall, &hitData.pos, projecTile);
740                             if (playerNum >= 0)
741                                 P_ActivateSwitch(playerNum, hitData.wall, 0);
742                         }
743                     }
744                 }
745                 else if(playerNum >= 0 && hitData.pos.z > 0 && sector[hitData.sect].lotag == 1)
746                 {
747                     int splashSprite = A_Spawn(pPlayer->i, WATERSPLASH2);
748                     sprite[splashSprite].x = hitData.pos.x;
749                     sprite[splashSprite].y = hitData.pos.y;
750                     sprite[splashSprite].ang = fix16_to_int(pPlayer->q16ang); // Total tweek
751                     sprite[splashSprite].xvel = 32;
752                     A_SetSprite(spriteNum, RR ? 0 : CLIPMASK0);
753                     sprite[splashSprite].xvel = 0;
754                 }
755             }
756             break;
757 
758         case DN64TILE2596__STATIC:
759         case DN64TILE2597__STATIC:
760         case DN64TILE2598__STATIC:
761         case DN64TILE2599__STATIC:
762             if (!REALITY)
763                 break;
764         case SHOTSPARK1__STATIC:
765         case SHOTGUN__STATIC:
766         case CHAINGUN__STATIC:
767         {
768             if (REALITY)
769             {
770                 if (projecTile == SHOTGUN)
771                     projecTile = DN64TILE2596;
772                 if (projecTile == CHAINGUN)
773                     projecTile = DN64TILE2597;
774             }
775             if (pSprite->extra >= 0)
776                 pSprite->shade = -96;
777 
778             if (playerNum >= 0)
779                 P_PreFireHitscan(spriteNum, playerNum, projecTile, &startPos, &Zvel, &shootAng,
780                     projecTile == SHOTSPARK1 && !WW2GI, 1);
781             else
782                 A_PreFireHitscan(pSprite, &startPos, &Zvel, &shootAng, 1);
783 
784             if (Proj_DoHitscan(spriteNum, 256 + 1, &startPos, Zvel, shootAng, &hitData))
785                 return -1;
786 
787             if (RR && projecTile == SHOTGUN && sector[hitData.sect].lotag == ST_1_ABOVE_WATER && (krand2()&1) != 0)
788                 return -1;
789 
790             if ((krand2() & 15) == 0 && sector[hitData.sect].lotag == ST_2_UNDERWATER)
791                 Proj_DoWaterTracers(hitData.pos, &startPos, 8 - (ud.multimode >> 1), playerNum);
792 
793             int spawnedSprite;
794 
795             if (playerNum >= 0)
796             {
797                 spawnedSprite = A_InsertSprite(hitData.sect, hitData.pos.x, hitData.pos.y, hitData.pos.z, REALITY ? projecTile : SHOTSPARK1, -15, 10, 10, shootAng, 0, 0, spriteNum, 4);
798                 sprite[spawnedSprite].extra = G_DefaultActorHealth(projecTile);
799                 sprite[spawnedSprite].extra += (krand2()%6);
800 
801                 if (REALITY)
802                 {
803                     sprite[spawnedSprite].cstat |= 128;
804                     if ((krand2()&255) < 128)
805                         sprite[spawnedSprite].cstat |= 4;
806                     if ((krand2()&255) < 128)
807                         sprite[spawnedSprite].cstat |= 8;
808                     sprite[spawnedSprite].x += (sintable[(shootAng+1536)&2047]>>10);
809                     sprite[spawnedSprite].y += (sintable[(shootAng+1024)&2047]>>10);
810                 }
811 
812 
813                 if (hitData.wall == -1 && hitData.sprite == -1)
814                 {
815                     if (Zvel < 0)
816                     {
817                         if (REALITY && (sector[hitData.sect].ceilingpicnum == 200 || sector[hitData.sect].ceilingpicnum == 336))
818                         {
819                             sprite[spawnedSprite].xrepeat = 0;
820                             sprite[spawnedSprite].yrepeat = 0;
821                         }
822                         if (sector[hitData.sect].ceilingstat & 1)
823                         {
824                             sprite[spawnedSprite].xrepeat = 0;
825                             sprite[spawnedSprite].yrepeat = 0;
826                             return -1;
827                         }
828                         else
829                             Sect_DamageCeiling(hitData.sect);
830                     }
831                     else
832                     {
833                         if (REALITY && (sector[hitData.sect].floorpicnum == 200 || sector[hitData.sect].floorpicnum == 336))
834                         {
835                             sprite[spawnedSprite].xrepeat = 0;
836                             sprite[spawnedSprite].yrepeat = 0;
837                         }
838                     }
839 
840                     if (!REALITY && (!RR || sector[hitData.sect].lotag != ST_1_ABOVE_WATER))
841                         A_Spawn(spawnedSprite, SMALLSMOKE);
842                 }
843 
844                 if (REALITY && projecTile == DN64TILE2599)
845                 {
846                     int spr = A_Spawn(spawnedSprite, EXPLOSION2);
847                     sprite[spr].xvel = 348;
848                     sprite[spr].ang = (sprite[spawnedSprite].ang + 1024) & 2047;
849                     A_SetSprite(spr, CLIPMASK0);
850                     int dmg = sprite[spawnedSprite].extra;
851                     A_RadiusDamage(spr, 2500, dmg >> 2, dmg >> 1, dmg - (dmg >> 2), dmg);
852                     A_PlaySound(12, spr);
853                 }
854 
855                 if (hitData.sprite >= 0 && (!REALITY || projecTile != DN64TILE2599))
856                 {
857                     if (RR && sprite[hitData.sprite].picnum == TORNADO)
858                         return -1;
859                     A_DamageObject(hitData.sprite, spawnedSprite);
860 
861                     if (REALITY)
862                     {
863                         sprite[spawnedSprite].xrepeat = 0;
864                         sprite[spawnedSprite].yrepeat = 0;
865                     }
866                     else
867                     {
868                         if (sprite[hitData.sprite].picnum == APLAYER &&
869                             (ud.ffire == 1 || (!GTFLAGS(GAMETYPE_PLAYERSFRIENDLY) && GTFLAGS(GAMETYPE_TDM) &&
870                                                g_player[P_Get(hitData.sprite)].ps->team != g_player[P_Get(spriteNum)].ps->team)))
871                         {
872                             int jibSprite = A_Spawn(spawnedSprite, JIBS6);
873 
874                             sprite[spawnedSprite].xrepeat = sprite[spawnedSprite].yrepeat = 0;
875                             sprite[jibSprite].z += ZOFFSET6;
876                             sprite[jibSprite].xvel    = 16;
877                             sprite[jibSprite].xrepeat = sprite[jibSprite].yrepeat = 24;
878                             sprite[jibSprite].ang += 64 - (krand2() & 127);
879                         }
880                         else
881                         {
882                             A_Spawn(spawnedSprite, SMALLSMOKE);
883                         }
884                     }
885 
886                     if (playerNum >= 0 && CheckShootSwitchTile(sprite[hitData.sprite].picnum))
887                     {
888                         P_ActivateSwitch(playerNum, hitData.sprite, 1);
889                         return -1;
890                     }
891                 }
892                 else if (hitData.wall >= 0)
893                 {
894                     uwalltype const * const hitWall = (uwalltype *)&wall[hitData.wall];
895 
896                     if (!REALITY)
897                         A_Spawn(spawnedSprite, SMALLSMOKE);
898 
899                     if (CheckDoorTile(hitWall->picnum) == 1)
900                         goto SKIPBULLETHOLE;
901 
902                     if (RR && CheckBlockDoorTile(hitWall->picnum) == 1)
903                         goto SKIPBULLETHOLE;
904 
905                     if (playerNum >= 0 && CheckShootSwitchTile(hitWall->picnum))
906                     {
907                         P_ActivateSwitch(playerNum, hitData.wall, 0);
908                         return -1;
909                     }
910 
911                     if (REALITY && numplayers != 1)
912                         goto SKIPBULLETHOLE;
913 
914                     if (hitWall->hitag != 0 || (hitWall->nextwall >= 0 && wall[hitWall->nextwall].hitag != 0))
915                         goto SKIPBULLETHOLE;
916 
917                     if ((hitData.sect >= 0 && sector[hitData.sect].lotag == 0) &&
918                         (hitWall->overpicnum != BIGFORCE && (hitWall->cstat & 16) == 0) &&
919                         ((hitWall->nextsector >= 0 && sector[hitWall->nextsector].lotag == 0) || (hitWall->nextsector == -1 && sector[hitData.sect].lotag == 0)))
920                     {
921                         int decalSprite;
922 
923                         if (SectorContainsSE13(hitWall->nextsector))
924                             goto SKIPBULLETHOLE;
925 
926                         for (SPRITES_OF(STAT_MISC, decalSprite))
927                             if (sprite[decalSprite].picnum == BULLETHOLE && dist(&sprite[decalSprite], &sprite[spawnedSprite])
928                                 < (((REALITY && (projecTile == DN64TILE2598 || projecTile == DN64TILE2599)) ? 36 : 12) + (krand2() & 7)))
929                                 goto SKIPBULLETHOLE;
930 
931                         decalSprite = A_Spawn(spawnedSprite, BULLETHOLE);
932 
933                         sprite[decalSprite].xvel = REALITY ? 0 : -1;
934                         sprite[decalSprite].ang
935                         = (getangle(hitWall->x - wall[hitWall->point2].x, hitWall->y - wall[hitWall->point2].y) + 512) & 2047;
936                         if (REALITY)
937                         {
938                             sprite[decalSprite].ang = (sprite[decalSprite].ang + 1024) & 2047;
939                             if (projecTile == DN64TILE2598 || projecTile == DN64TILE2599)
940                             {
941                                 sprite[decalSprite].xrepeat *= 3;
942                                 sprite[decalSprite].yrepeat *= 3;
943                             }
944                         }
945 
946                         A_SetSprite(decalSprite, CLIPMASK0);
947                     }
948 
949                 SKIPBULLETHOLE:
950 
951                     HandleHitWall(&hitData);
952                     A_DamageWall(spawnedSprite, hitData.wall, &hitData.pos, REALITY ? projecTile : SHOTSPARK1);
953                 }
954             }
955             else
956             {
957                 spawnedSprite = A_InsertSprite(hitData.sect, hitData.pos.x, hitData.pos.y, hitData.pos.z, REALITY ? projecTile : SHOTSPARK1, -15, 24, 24, shootAng, 0, 0, spriteNum, 4);
958                 sprite[spawnedSprite].extra = G_DefaultActorHealth(projecTile);
959                 if (REALITY)
960                     sprite[spawnedSprite].cstat |= 0x80;
961 
962                 if (hitData.sprite >= 0)
963                 {
964                     A_DamageObject(hitData.sprite, spawnedSprite);
965                     if (!REALITY && sprite[hitData.sprite].picnum != APLAYER)
966                         A_Spawn(spawnedSprite, SMALLSMOKE);
967                     else
968                     {
969                         sprite[spawnedSprite].xrepeat = 0;
970                         sprite[spawnedSprite].yrepeat = 0;
971                     }
972                 }
973                 else if (hitData.wall >= 0)
974                     A_DamageWall(spawnedSprite, hitData.wall, &hitData.pos, REALITY ? projecTile : SHOTSPARK1);
975             }
976 
977             if (REALITY)
978             {
979                 if (hitData.wall >= 0 && (krand2()&255) < 32)
980                 {
981                     if (g_tile[projecTile].execPtr != g_tile[DN64TILE2599].execPtr && g_tile[projecTile].execPtr != g_tile[DN64TILE2596].execPtr)
982                         S_PlaySound3D(272+(krand2()%5), spawnedSprite, &hitData.pos);
983                 }
984                 return -1;
985             }
986 
987             if ((krand2() & 255) < (RR ? 10 : 4))
988                 S_PlaySound3D(PISTOL_RICOCHET, spawnedSprite, &hitData.pos);
989 
990             return -1;
991         }
992 
993         case TRIPBOMBSPRITE__STATIC:
994         {
995             if (!RR) break;
996             int const newSprite = A_Spawn(spriteNum, projecTile);
997             sprite[newSprite].xvel = 32;
998             sprite[newSprite].ang = sprite[spriteNum].ang;
999             sprite[newSprite].z -= (5<<8);
1000             break;
1001         }
1002 
1003         case BOWLINGBALL__STATICRR:
1004         {
1005             int const newSprite = A_Spawn(spriteNum, projecTile);
1006             sprite[newSprite].xvel = 250;
1007             sprite[newSprite].ang = sprite[spriteNum].ang;
1008             sprite[newSprite].z -= (15<<8);
1009             break;
1010         }
1011 
1012         case OWHIP__STATICRR:
1013         case UWHIP__STATICRR:
1014         {
1015             if (pSprite->extra >= 0)
1016                 pSprite->shade = -96;
1017 
1018             if (projecTile == OWHIP)
1019             {
1020                 vel = 300;
1021                 startPos.z -= (15<<8);
1022             }
1023             else if (projecTile == UWHIP)
1024             {
1025                 vel = 300;
1026                 startPos.z += (4<<8);
1027             }
1028 
1029             if (playerNum >= 0)
1030             {
1031                 if (GetAutoAimAng(spriteNum, playerNum, projecTile, -ZOFFSET4, 0, &startPos, vel, &Zvel, &shootAng) < 0)
1032                     Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 98;
1033             }
1034             else
1035             {
1036                 int const otherPlayer = A_FindPlayer(pSprite, NULL);
1037                 if (pSprite->picnum == VIXEN)
1038                     shootAng -= krand2()&16;
1039                 else
1040                     shootAng += 16 - (krand2() & 31);
1041                 hitData.pos.x         = safeldist(g_player[otherPlayer].ps->i, pSprite);
1042                 Zvel                  = tabledivide32_noinline((g_player[otherPlayer].ps->opos.z - startPos.z + (3 << 8)) * vel, hitData.pos.x);
1043             }
1044 
1045             int spriteSize = (playerNum >= 0) ? 7 : 8;
1046 
1047             int const returnSprite = A_InsertSprite(spriteSectnum, startPos.x, startPos.y, startPos.z, projecTile, -127, spriteSize, spriteSize,
1048                                                     shootAng, vel, Zvel, spriteNum, 4);
1049 
1050             sprite[returnSprite].extra += (krand2() & 7);
1051 
1052             sprite[returnSprite].cstat    = 128;
1053             sprite[returnSprite].clipdist = 4;
1054 
1055             shootAng = pSprite->ang + 32 - (krand2() & 63);
1056             Zvel += 512 - (krand2() & 1023);
1057 
1058             return returnSprite;
1059         }
1060 
1061 
1062         case GROWSPARK__STATIC:
1063         {
1064             if (RR)
1065                 goto growspark_rr;
1066             if (REALITY && pSprite->extra >= 0)
1067                 pSprite->shade = -96;
1068 
1069             if (playerNum >= 0)
1070                 P_PreFireHitscan(spriteNum, playerNum, projecTile, &startPos, &Zvel, &shootAng, 1, 1);
1071             else
1072                 A_PreFireHitscan(pSprite, &startPos, &Zvel, &shootAng, 1);
1073 
1074             if (Proj_DoHitscan(spriteNum, 256 + 1, &startPos, Zvel, shootAng, &hitData))
1075                 return -1;
1076 
1077             int const otherSprite = A_InsertSprite(hitData.sect, hitData.pos.x, hitData.pos.y, hitData.pos.z, GROWSPARK, -16, 28, 28,
1078                                                    shootAng, 0, 0, spriteNum, 1);
1079 
1080             sprite[otherSprite].pal = 2;
1081             sprite[otherSprite].cstat |= 130;
1082             sprite[otherSprite].xrepeat = sprite[otherSprite].yrepeat = 1;
1083 
1084             if (hitData.wall == -1 && hitData.sprite == -1 && hitData.sect >= 0
1085                 && Zvel < 0 && (sector[hitData.sprite].ceilingstat & 1) == 0)
1086             {
1087                 Sect_DamageCeiling(hitData.sect);
1088             }
1089             else if (hitData.sprite >= 0)
1090                 A_DamageObject(hitData.sprite, otherSprite);
1091             else if (hitData.wall >= 0 && wall[hitData.wall].picnum != ACCESSSWITCH && wall[hitData.wall].picnum != ACCESSSWITCH2)
1092                 A_DamageWall(otherSprite, hitData.wall, &hitData.pos, projecTile);
1093         }
1094         break;
1095 
1096         case FIRELASER__STATIC:
1097         case SPIT__STATIC:
1098         case COOLEXPLOSION1__STATIC:
1099         {
1100             if ((!RRRA || projecTile != SPIT) && pSprite->extra >= 0)
1101                 pSprite->shade = -96;
1102 
1103             switch (projecTile)
1104             {
1105                 case SPIT__STATIC:
1106                     if (RRRA && pSprite->picnum == MAMA)
1107                         vel = 600;
1108                     else
1109                         vel = RR ? 400 : 292;
1110                     break;
1111                 case COOLEXPLOSION1__STATIC:
1112                     if (REALITY)
1113                     {
1114                         if (pSprite->picnum == BOSS2)
1115                         {
1116                             vel = 644;
1117                             startPos.z -= 12288.0;
1118                             startPos.x += (sintable[(pSprite->ang+512)&2047] * 1000) >> 14;
1119                             startPos.y += (sintable[pSprite->ang&2047] * 1000) >> 14;
1120                         }
1121                         else
1122                         {
1123                             vel = 348;
1124                             startPos.z -= (4 << 7);
1125                         }
1126                         break;
1127                     }
1128                     if (!RR)
1129                     {
1130                         vel = (pSprite->picnum == BOSS2) ? 644 : 348;
1131                         startPos.z -= (4 << 7);
1132                         break;
1133                     }
1134                     fallthrough__;
1135                 case FIRELASER__STATIC:
1136                 default:
1137                     vel = 840;
1138                     startPos.z -= (4 << 7);
1139                     if (RR)
1140                     {
1141                         if (pSprite->picnum == HULK)
1142                         {
1143                             startPos.x += sintable[(pSprite->ang+512+256)&2047]>>6;
1144                             startPos.y += sintable[(pSprite->ang+256)&2047]>>6;
1145                             startPos.z += (12 << 8);
1146                         }
1147                         else if (pSprite->picnum == VIXEN)
1148                             startPos.z -= (12 << 8);
1149                     }
1150                     break;
1151             }
1152 
1153             if (playerNum >= 0)
1154             {
1155                 if (RR)
1156                 {
1157                     startPos.x += sintable[(pSprite->ang+512+160)&2047]>>7;
1158                     startPos.y += sintable[(pSprite->ang+160)&2047]>>7;
1159                 }
1160                 if (GetAutoAimAng(spriteNum, playerNum, projecTile, -ZOFFSET4, 0, &startPos, vel, &Zvel, &shootAng) < 0)
1161                     Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 98;
1162             }
1163             else
1164             {
1165                 int const otherPlayer = A_FindPlayer(pSprite, NULL);
1166                 if (RR)
1167                 {
1168                     if (pSprite->picnum == HULK)
1169                         shootAng -= krand2()&31;
1170                     else if (pSprite->picnum == VIXEN)
1171                         shootAng -= krand2()&16;
1172                     else if (pSprite->picnum != UFOBEAM)
1173                         shootAng += 16 - (krand2() & 31);
1174                 }
1175                 else
1176                     shootAng           += 16 - (krand2() & 31);
1177                 hitData.pos.x         = REALITY ? safeFindDistance2D(sprite[g_player[otherPlayer].ps->i].x - pSprite->x, sprite[g_player[otherPlayer].ps->i].y - pSprite->y)
1178                                                 : safeldist(g_player[otherPlayer].ps->i, pSprite);
1179                 Zvel                  = tabledivide32_noinline((g_player[otherPlayer].ps->opos.z - startPos.z + (3 << 8)) * vel, hitData.pos.x);
1180             }
1181 
1182             int spriteSize = 18;
1183 
1184             if (RR)
1185             {
1186                 if (projecTile == SPIT)
1187                 {
1188                     if (RRRA && pSprite->picnum == MAMA)
1189                         startPos.z -= (20 << 8);
1190                     else
1191                         startPos.z -= (10 << 8);
1192                 }
1193                 else if (projecTile == COOLEXPLOSION1)
1194                     spriteSize = 8;
1195             }
1196             else
1197             {
1198                 if (projecTile == SPIT)
1199                     startPos.z -= (10 << 8);
1200             }
1201 
1202             if (playerNum >= 0) spriteSize = 7;
1203 
1204             int const returnSprite = A_InsertSprite(spriteSectnum, startPos.x, startPos.y, startPos.z, projecTile, -127, spriteSize, spriteSize,
1205                                                     shootAng, vel, Zvel, spriteNum, 4);
1206 
1207             sprite[returnSprite].extra += (krand2() & 7);
1208 
1209             if (!RR && projecTile == COOLEXPLOSION1)
1210             {
1211                 sprite[returnSprite].shade = 0;
1212 
1213                 if (PN(spriteNum) == BOSS2)
1214                 {
1215                     if (!REALITY)
1216                     {
1217                         int const saveXvel        = sprite[returnSprite].xvel;
1218                         sprite[returnSprite].xvel = 1024;
1219                         A_SetSprite(returnSprite, CLIPMASK0);
1220                         sprite[returnSprite].xvel = saveXvel;
1221                     }
1222                     sprite[returnSprite].ang += 128 - (krand2() & 255);
1223                 }
1224             }
1225 
1226             sprite[returnSprite].cstat    = 128;
1227             sprite[returnSprite].clipdist = 4;
1228 
1229             if (!REALITY)
1230             {
1231                 shootAng = pSprite->ang + 32 - (krand2() & 63);
1232                 Zvel += 512 - (krand2() & 1023);
1233             }
1234 
1235             if (RR && projecTile == FIRELASER)
1236                 sprite[returnSprite].xrepeat = sprite[returnSprite].yrepeat = 8;
1237 
1238             return returnSprite;
1239         }
1240 
1241         case FREEZEBLAST__STATIC:
1242             if (REALITY) break;
1243             startPos.z += (3 << 8);
1244             fallthrough__;
1245         case RPG__STATIC:
1246         case DN64TILE2606__STATIC:
1247         case RPG2__STATICRR:
1248         case RRTILE1790__STATICRR:
1249         case SHRINKSPARK__STATIC:
1250         case DN64TILE3841__STATIC:
1251         {
1252             if (!RR && projecTile == SHRINKSPARK) break;
1253             if (RR && !RRRA && (projecTile == RPG2 || projecTile == RRTILE1790)) break;
1254             if (!REALITY && (projecTile == DN64TILE2599 || projecTile == DN64TILE3841)) break;
1255 
1256             int targetSprite = 0;
1257 
1258             // XXX: "CODEDUP"
1259             if (pSprite->extra >= 0)
1260                 pSprite->shade = -96;
1261 
1262             vel = 644;
1263 
1264             int projecTile2 = projecTile;
1265 
1266             int otherSprite = -1;
1267 
1268             if (playerNum >= 0)
1269             {
1270                 // NOTE: otherSprite is a SPRITE_INDEX
1271                 if (projecTile == DN64TILE2606)
1272                 {
1273                     char t = pPlayer->dn64_385;
1274                     pPlayer->dn64_385 = 1;
1275                     otherSprite = GetAutoAimAng(spriteNum, playerNum, projecTile, 8 << 8, 0 + 2, &startPos, vel, &Zvel, &shootAng);
1276                     pPlayer->dn64_385 = t;
1277                     vel = 512;
1278                     projecTile2 = RPG;
1279                 }
1280                 else
1281                     otherSprite = GetAutoAimAng(spriteNum, playerNum, projecTile, 8 << 8, 0 + 2, &startPos, vel, &Zvel, &shootAng);
1282 
1283                 if (RRRA && projecTile == RPG2 && otherSprite >= 0)
1284                 {
1285                     if (sprite[otherSprite].picnum == HEN || sprite[otherSprite].picnum == HENSTAYPUT)
1286                         targetSprite = pPlayer->i;
1287                     else
1288                         targetSprite = otherSprite;
1289                 }
1290 
1291                 if (projecTile == DN64TILE2606 || otherSprite < 0)
1292                     Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 81;
1293 
1294                 if (projecTile2 == RPG)
1295                     A_PlaySound(REALITY ? 6 : RPG_SHOOT, spriteNum);
1296                 else if (RRRA)
1297                 {
1298                     if (projecTile == RPG2)
1299                         A_PlaySound(244, spriteNum);
1300                     else if (projecTile == RRTILE1790)
1301                         A_PlaySound(94, spriteNum);
1302                 }
1303             }
1304             else
1305             {
1306                 // NOTE: otherSprite is a player index
1307                 otherSprite          = A_FindPlayer(pSprite, NULL);
1308                 shootAng = getangle(g_player[otherSprite].ps->opos.x - startPos.x, g_player[otherSprite].ps->opos.y - startPos.y);
1309                 if (PN(spriteNum) == BOSS3)
1310                 {
1311                     startPos.z -= ZOFFSET5;
1312                     if (REALITY && pSprite->pal != 0)
1313                         startPos.z += ZOFFSET2;
1314                 }
1315                 else if (PN(spriteNum) == BOSS2)
1316                 {
1317                     vel += 128;
1318                     if (REALITY)
1319                     {
1320                         startPos.x = startPos.x + ((sintable[shootAng&2047] << 2) / 56) / 1.3 + ((sintable[(shootAng+512)&2047] << 11) >> 14) / 1.3;
1321                         startPos.y = startPos.y + ((sintable[(shootAng+1536)&2047] << 2) / 56) / 1.3 + ((sintable[shootAng&2047] << 11) >> 14) / 1.3;
1322                     }
1323                     else
1324                         startPos.z += 24<<8;
1325                 }
1326 
1327                 Zvel = tabledivide32_noinline((g_player[otherSprite].ps->opos.z - startPos.z) * vel,
1328                     REALITY ? safeFindDistance2D(sprite[g_player[otherSprite].ps->i].x - pSprite->x, sprite[g_player[otherSprite].ps->i].y - pSprite->y)
1329                             : safeldist(g_player[otherSprite].ps->i, pSprite));
1330 
1331                 if (A_CheckEnemySprite(pSprite) && (AC_MOVFLAGS(pSprite, &actor[spriteNum]) & face_player_smart))
1332                     shootAng = pSprite->ang + (krand2() & 31) - 16;
1333             }
1334 
1335             //if (numplayers > 1 && g_netClient)
1336             //    return -1;
1337 
1338             if (RRRA && projecTile == RRTILE1790)
1339             {
1340                 Zvel = -(10 << 8);
1341                 vel <<= 1;
1342             }
1343 
1344             int const returnSprite = A_InsertSprite(spriteSectnum, startPos.x + (sintable[(348 + shootAng + 512) & 2047] / 448),
1345                                                     startPos.y + (sintable[(shootAng + 348) & 2047] / 448), startPos.z - (1 << 8),
1346                                                     projecTile2, 0, 14, 14, shootAng, vel, Zvel, spriteNum, 4);
1347             spritetype *const pReturn = &sprite[returnSprite];
1348 
1349             if (RRRA)
1350             {
1351                 if (projecTile == RRTILE1790)
1352                 {
1353                     pReturn->extra = 10;
1354                     pReturn->zvel = -(10 << 8);
1355                 }
1356                 else if (projecTile == RPG2)
1357                 {
1358                     pReturn->lotag = targetSprite;
1359                     pReturn->hitag = 0;
1360                     A_SpawnMultiple(returnSprite, MONEY, (krand2()&3)+1);
1361                 }
1362             }
1363 
1364             pReturn->extra += (krand2() & 7);
1365             if (REALITY)
1366             {
1367                 if (projecTile2 == RPG)
1368                     pReturn->yvel = (playerNum >= 0 && otherSprite >= 0) ? otherSprite : -1;  // RPG_YVEL
1369                 if (projecTile == DN64TILE2606)
1370                 {
1371                     if ((krand2() & 63) < 32)
1372                         pReturn->xvel = 513;
1373                 }
1374                 if (projecTile == DN64TILE3841)
1375                 {
1376                     pReturn->zvel -= 32;
1377                     if (playerNum >= 0)
1378                         pReturn->yvel = pPlayer->hbomb_hold_delay;
1379                     else
1380                         pReturn->yvel = 66;
1381                     pReturn->extra += (pReturn->yvel * pReturn->yvel) / 10;
1382                 }
1383             }
1384             else
1385             {
1386                 if (projecTile != FREEZEBLAST)
1387                     pReturn->yvel = (playerNum >= 0 && otherSprite >= 0) ? otherSprite : -1;  // RPG_YVEL
1388                 else
1389                 {
1390                     pReturn->yvel = g_numFreezeBounces;
1391                     pReturn->xrepeat >>= 1;
1392                     pReturn->yrepeat >>= 1;
1393                     pReturn->zvel -= (2 << 4);
1394                 }
1395             }
1396 
1397             if (playerNum == -1)
1398             {
1399                 if (RR && PN(spriteNum) == HULK)
1400                 {
1401                     pReturn->xrepeat = 8;
1402                     pReturn->yrepeat = 8;
1403                 }
1404                 else if (!RR && PN(spriteNum) == BOSS3)
1405                 {
1406                     int dx, dy;
1407                     if (krand2() & 1)
1408                     {
1409                         dx = -(sintable[shootAng & 2047] >> 6);
1410                         dy = -(sintable[(shootAng + 1024 + 512) & 2047] >> 6);
1411                         pReturn->ang -= 8;
1412                     }
1413                     else
1414                     {
1415                         dx = sintable[shootAng & 2047] >> 6;
1416                         dy = sintable[(shootAng + 1024 + 512) & 2047] >> 6;
1417                         pReturn->ang += 4;
1418                     }
1419                     if (REALITY)
1420                     {
1421                         if (pSprite->pal != 0)
1422                         {
1423                             dx /= 2;
1424                             dy /= 2;
1425                         }
1426                         pReturn->x += dx;
1427                         pReturn->y += dy;
1428                         pReturn->xrepeat = 21;
1429                         pReturn->yrepeat = 21;
1430                     }
1431                     else
1432                     {
1433                         pReturn->x += dx;
1434                         pReturn->y += dy;
1435                         pReturn->xrepeat = 42;
1436                         pReturn->yrepeat = 42;
1437                     }
1438                 }
1439                 else if (!RR && PN(spriteNum) == BOSS2)
1440                 {
1441                     if (!REALITY)
1442                     {
1443                         pReturn->x -= sintable[shootAng & 2047] / 56;
1444                         pReturn->y -= sintable[(shootAng + 1024 + 512) & 2047] / 56;
1445                     }
1446                     pReturn->ang -= 8 + (krand2() & 255) - 128;
1447                     pReturn->xrepeat = 24;
1448                     pReturn->yrepeat = 24;
1449                 }
1450                 else if ((!REALITY && projecTile != FREEZEBLAST) || (REALITY && projecTile != DN64TILE3841))
1451                 {
1452                     pReturn->xrepeat = 30;
1453                     pReturn->yrepeat = 30;
1454                     pReturn->extra >>= 2;
1455                 }
1456             }
1457             else if (!REALITY && (WW2GI ? PWEAPON(playerNum, g_player[playerNum].ps->curr_weapon, WorksLike) : g_player[playerNum].ps->curr_weapon) == DEVISTATOR_WEAPON)
1458             {
1459                 pReturn->extra >>= 2;
1460                 pReturn->ang += 16 - (krand2() & 31);
1461                 pReturn->zvel += 256 - (krand2() & 511);
1462 
1463                 if (g_player[playerNum].ps->hbomb_hold_delay)
1464                 {
1465                     pReturn->x -= sintable[shootAng & 2047] / 644;
1466                     pReturn->y -= sintable[(shootAng + 1024 + 512) & 2047] / 644;
1467                 }
1468                 else
1469                 {
1470                     pReturn->x += sintable[shootAng & 2047] >> 8;
1471                     pReturn->y += sintable[(shootAng + 1024 + 512) & 2047] >> 8;
1472                 }
1473                 pReturn->xrepeat >>= 1;
1474                 pReturn->yrepeat >>= 1;
1475             }
1476 
1477             pReturn->cstat    = 128;
1478             pReturn->clipdist = (projecTile2 == RPG) ? 4 : (REALITY ? 80 : 40);
1479 
1480             if (RRRA && (projecTile == RPG2 || projecTile == RRTILE1790))
1481                 pReturn->clipdist = 4;
1482 
1483             return returnSprite;
1484         }
1485 
1486         case HANDHOLDINGLASER__STATIC:
1487         {
1488             if (RR) break;
1489             int const zOffset     = (playerNum >= 0) ? g_player[playerNum].ps->pyoff : 0;
1490             Zvel                  = (playerNum >= 0) ? fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 32 : 0;
1491 
1492             startPos.z -= zOffset;
1493             Proj_DoHitscan(spriteNum, 0, &startPos, Zvel, shootAng, &hitData);
1494             startPos.z += zOffset;
1495 
1496             int placeMine = 0;
1497             if (hitData.sprite >= 0)
1498                 break;
1499 
1500             if (hitData.wall >= 0 && hitData.sect >= 0)
1501                 if (((hitData.pos.x - startPos.x) * (hitData.pos.x - startPos.x)
1502                      + (hitData.pos.y - startPos.y) * (hitData.pos.y - startPos.y))
1503                     < (290 * 290))
1504                 {
1505                     // ST_2_UNDERWATER
1506                     if (wall[hitData.wall].nextsector >= 0)
1507                     {
1508                         if (sector[wall[hitData.wall].nextsector].lotag <= 2 && sector[hitData.sect].lotag <= 2)
1509                             placeMine = 1;
1510                     }
1511                     else if (sector[hitData.sect].lotag <= 2)
1512                         placeMine = 1;
1513                 }
1514 
1515             if (placeMine == 1)
1516             {
1517                 int const tripBombMode = Gv_GetVarByLabel("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, -1, -1);
1518                 int const spawnedSprite = A_InsertSprite(hitData.sect, hitData.pos.x, hitData.pos.y, hitData.pos.z, TRIPBOMB, -16, 4, 5,
1519                                                          shootAng, 0, 0, spriteNum, 6);
1520                 if (tripBombMode & TRIPBOMB_TIMER)
1521                 {
1522                     int32_t lLifetime = Gv_GetVarByLabel("STICKYBOMB_LIFETIME", NAM_GRENADE_LIFETIME, -1, playerNum);
1523                     int32_t lLifetimeVar
1524                     = Gv_GetVarByLabel("STICKYBOMB_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, -1, playerNum);
1525                     // set timer.  blows up when at zero....
1526                     sprite[spawnedSprite].extra = lLifetime + mulscale14(krand2(), lLifetimeVar) - lLifetimeVar;
1527                 }
1528                 sprite[spawnedSprite].hitag = spawnedSprite;
1529                 A_PlaySound(REALITY ? 13 : LASERTRIP_ONWALL, spawnedSprite);
1530                 sprite[spawnedSprite].xvel = -20;
1531                 A_SetSprite(spawnedSprite, CLIPMASK0);
1532                 sprite[spawnedSprite].cstat = 16;
1533 
1534                 int const p2      = wall[hitData.wall].point2;
1535                 int const wallAng = getangle(wall[hitData.wall].x - wall[p2].x, wall[hitData.wall].y - wall[p2].y) - 512;
1536 
1537                 actor[spawnedSprite].t_data[5] = sprite[spawnedSprite].ang = wallAng;
1538 
1539                 if (!WW2GI && playerNum >= 0)
1540                     pPlayer->ammo_amount[TRIPBOMB_WEAPON]--;
1541 
1542                 return spawnedSprite;
1543             }
1544             return -1;
1545         }
1546 
1547         case BOUNCEMINE__STATIC:
1548             if (RR) break;
1549             fallthrough__;
1550         case MORTER__STATIC:
1551         case CHEERBOMB__STATICRR:
1552         {
1553             if (RR && !RRRA && projecTile == CHEERBOMB) break;
1554 
1555             if (pSprite->extra >= 0)
1556                 pSprite->shade = -96;
1557 
1558             int const playerSprite = g_player[A_FindPlayer(pSprite, NULL)].ps->i;
1559             int const playerDist   = ldist(&sprite[playerSprite], pSprite);
1560 
1561             Zvel = -playerDist >> 1;
1562 
1563             if (Zvel < -4096)
1564                 Zvel = -2048;
1565 
1566             vel  = playerDist >> 4;
1567 
1568             int spriteSize = (RRRA && projecTile == CHEERBOMB) ? 16 : 32;
1569 
1570             A_InsertSprite(spriteSectnum, startPos.x + (sintable[(512 + shootAng + 512) & 2047] >> 8),
1571                            startPos.y + (sintable[(shootAng + 512) & 2047] >> 8), startPos.z + (6 << 8), projecTile, -64,
1572                            spriteSize, spriteSize, shootAng, vel, Zvel, spriteNum, 1);
1573             break;
1574         }
1575 
1576         case SHRINKER__STATIC:
1577         {
1578             if (RR) break;
1579             if (pSprite->extra >= 0)
1580                 pSprite->shade = -96;
1581 
1582             if (playerNum >= 0)
1583             {
1584                 if (NAM_WW2GI || GetAutoAimAng(spriteNum, playerNum, projecTile, ZOFFSET6, 0, &startPos, 768, &Zvel, &shootAng) < 0)
1585                     Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 98;
1586             }
1587             else if (pSprite->statnum != STAT_EFFECTOR)
1588             {
1589                 int const otherPlayer = A_FindPlayer(pSprite, NULL);
1590                 Zvel                  = tabledivide32_noinline((g_player[otherPlayer].ps->opos.z - startPos.z) * 512,
1591                                               safeldist(g_player[otherPlayer].ps->i, pSprite));
1592             }
1593             else
1594                 Zvel = 0;
1595 
1596             int const returnSprite = A_InsertSprite(spriteSectnum, startPos.x + (sintable[(512 + shootAng + 512) & 2047] >> 12),
1597                                                     startPos.y + (sintable[(shootAng + 512) & 2047] >> 12), startPos.z + (2 << 8),
1598                                                     SHRINKSPARK, -16, 28, 28, shootAng, 768, Zvel, spriteNum, 4);
1599             sprite[returnSprite].cstat    = 128;
1600             sprite[returnSprite].clipdist = 32;
1601 
1602             return returnSprite;
1603         }
1604 
1605         case DN64TILE3634__STATIC:
1606         {
1607             if (!REALITY)
1608                 break;
1609 
1610             float viewang = RT_GetAngle(fix16_to_float(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)), 128.f) * (-180.f / fPI);
1611             int vc = int(cos(viewang * fPI / 180.f) * 768.f);
1612             int vs = int(sin(viewang * fPI / 180.f) * 768.f);
1613             if (sector[spriteSectnum].lotag == ST_2_UNDERWATER)
1614             {
1615                 vc /= 2;
1616                 vs /= 2;
1617             }
1618 
1619             int const returnSprite = A_InsertSprite(spriteSectnum, startPos.x + sintable[(shootAng + 512 + 348) & 2047] / 448,
1620                 startPos.y + sintable[(shootAng + 348) & 2047] / 448, startPos.z - ZOFFSET, DN64TILE3634, 0, 18, 18,
1621                 shootAng, vc, vs << 4, spriteNum, 1);
1622             sprite[returnSprite].yvel = 0;
1623 
1624             return returnSprite;
1625         }
1626     }
1627 
1628     return -1;
1629 }
1630 
A_DHShoot(int const playerNum)1631 void A_DHShoot(int const playerNum)
1632 {
1633     switch (g_player[playerNum].ps->dhat61f)
1634     {
1635     case 0:
1636         ghpistol_fire(playerNum);
1637         break;
1638     case 1:
1639     case 2:
1640         ghrifle_fire(playerNum);
1641         break;
1642     case 3:
1643         ghshtgn_fire(playerNum);
1644         break;
1645     case 4:
1646         ghbow_fire(playerNum);
1647         break;
1648     }
1649 }
1650 
1651 
1652 //////////////////// HUD WEAPON / MISC. DISPLAY CODE ////////////////////
1653 
P_DisplaySpit(void)1654 static void P_DisplaySpit(void)
1655 {
1656     DukePlayer_t *const pPlayer     = g_player[screenpeek].ps;
1657     int const           loogCounter = pPlayer->loogcnt;
1658 
1659     if (loogCounter == 0)
1660         return;
1661 
1662     int const rotY = loogCounter<<2;
1663 
1664     for (bssize_t i=0; i < pPlayer->numloogs; i++)
1665     {
1666         int const rotAng = klabs(sintable[((loogCounter + i) << 5) & 2047]) >> 5;
1667         int const rotZoom  = 4096 + ((loogCounter + i) << 9);
1668         int const rotX     = (-fix16_to_int(g_player[screenpeek].inputBits->q16avel) >> 1) + (sintable[((loogCounter + i) << 6) & 2047] >> 10);
1669 
1670         rotatesprite_fs((pPlayer->loogiex[i] + rotX) << 16, (200 + pPlayer->loogiey[i] - rotY) << 16, rotZoom - (i << 8),
1671                         256 - rotAng, LOOGIE, 0, 0, 2);
1672     }
1673 }
1674 
P_GetHudPal(const DukePlayer_t * p)1675 int P_GetHudPal(const DukePlayer_t *p)
1676 {
1677     if (sprite[p->i].pal == 1)
1678         return 1;
1679 
1680     if (p->cursectnum >= 0)
1681     {
1682         int const hudPal = sector[p->cursectnum].floorpal;
1683         if (!g_noFloorPal[hudPal])
1684             return hudPal;
1685     }
1686 
1687     return 0;
1688 }
1689 
P_GetKneePal(DukePlayer_t const * pPlayer)1690 int P_GetKneePal(DukePlayer_t const * pPlayer)
1691 {
1692     return P_GetKneePal(pPlayer, P_GetHudPal(pPlayer));
1693 }
1694 
P_GetKneePal(DukePlayer_t const * pPlayer,int const hudPal)1695 int P_GetKneePal(DukePlayer_t const * pPlayer, int const hudPal)
1696 {
1697     return hudPal == 0 ? pPlayer->palookup : hudPal;
1698 }
1699 
P_GetOverheadPal(DukePlayer_t const * pPlayer)1700 int P_GetOverheadPal(DukePlayer_t const * pPlayer)
1701 {
1702     return sprite[pPlayer->i].pal;
1703 }
1704 
P_DisplayFist(int const fistShade)1705 static int P_DisplayFist(int const fistShade)
1706 {
1707     DukePlayer_t const *const pPlayer = g_player[screenpeek].ps;
1708     int fistInc = pPlayer->fist_incs;
1709 
1710     if (fistInc > 32)
1711         fistInc = 32;
1712 
1713     if (fistInc <= 0)
1714         return 0;
1715 
1716     int const fistY       = klabs(pPlayer->look_ang) / 9;
1717     int const fistZoom    = clamp(65536 - (sintable[(512 + (fistInc << 6)) & 2047] << 2), 40920, 90612);
1718     int const fistYOffset = 194 + (sintable[((6 + fistInc) << 7) & 2047] >> 9);
1719     int const fistPal     = P_GetHudPal(pPlayer);
1720     int       wx[2]       = { windowxy1.x, windowxy2.x };
1721 
1722 #ifdef SPLITSCREEN_MOD_HACKS
1723     // XXX: this is outdated, doesn't handle above/below split.
1724     if (g_fakeMultiMode==2)
1725         wx[(g_snum==0)] = (wx[0]+wx[1])/2+1;
1726 #endif
1727 
1728     rotatesprite((-fistInc + 222 + (fix16_to_int(g_player[screenpeek].inputBits->q16avel) >> 5)) << 16, (fistY + fistYOffset) << 16,
1729                  fistZoom, 0, FIST, fistShade, fistPal, 2, wx[0], windowxy1.y, wx[1], windowxy2.y);
1730 
1731     return 1;
1732 }
1733 
1734 #define DRAWEAP_CENTER 262144
1735 #define weapsc(sc) scale(sc, ud.weaponscale, 100)
1736 
1737 static int32_t g_dts_yadd;
1738 
G_DrawTileScaled(int drawX,int drawY,int tileNum,int drawShade,int drawBits,int drawPal,int drawScale=65536,int angleOffset=0)1739 static void G_DrawTileScaled(int drawX, int drawY, int tileNum, int drawShade, int drawBits, int drawPal,
1740     int drawScale = 65536, int angleOffset = 0)
1741 {
1742     int32_t wx[2] = { windowxy1.x, windowxy2.x };
1743     int32_t wy[2] = { windowxy1.y, windowxy2.y };
1744 
1745     int drawYOffset = 0;
1746     int drawXOffset = 192<<16;
1747 
1748     switch (DYNAMICWEAPONMAP(hudweap.cur))
1749     {
1750         case DEVISTATOR_WEAPON__STATIC:
1751         case TRIPBOMB_WEAPON__STATIC:
1752             drawXOffset = 160<<16;
1753             break;
1754         default:
1755             if (drawBits & DRAWEAP_CENTER)
1756             {
1757                 drawXOffset = 160<<16;
1758                 drawBits &= ~DRAWEAP_CENTER;
1759             }
1760             break;
1761     }
1762 
1763     // bit 4 means "flip x" for G_DrawTileScaled
1764     int const drawAng = ((drawBits & 4) ? 1024 : 0) + angleOffset;
1765 
1766 #ifdef SPLITSCREEN_MOD_HACKS
1767     if (g_fakeMultiMode==2)
1768     {
1769         int const sideBySide = (ud.screen_size!=0);
1770 
1771         // splitscreen HACK
1772         drawBits &= ~(1024|512|256);
1773         if (sideBySide)
1774         {
1775             drawBits &= ~8;
1776             wx[(g_snum==0)] = (wx[0]+wx[1])/2 + 2;
1777         }
1778         else
1779         {
1780             drawBits |= 8;
1781             if (g_snum==0)
1782                 drawYOffset = -(100<<16);
1783             wy[(g_snum==0)] = (wy[0]+wy[1])/2 + 2;
1784         }
1785     }
1786 #endif
1787 
1788 #ifdef USE_OPENGL
1789     if (videoGetRenderMode() >= REND_POLYMOST && usemodels && md_tilehasmodel(tileNum,drawPal) >= 0)
1790         drawYOffset += (224<<16)-weapsc(224<<16);
1791 #endif
1792     rotatesprite(weapsc(drawX<<16) + (drawXOffset-weapsc(drawXOffset)),
1793                  weapsc((drawY<<16) + g_dts_yadd) + ((200<<16)-weapsc(200<<16)) + drawYOffset,
1794                  weapsc(drawScale),drawAng,tileNum,drawShade,drawPal,(2|drawBits),
1795                  wx[0],wy[0], wx[1],wy[1]);
1796 }
1797 
G_DrawWeaponTile(int weaponX,int weaponY,int weaponTile,int weaponShade,int weaponBits,int weaponPal,int weaponScale=65536)1798 static void G_DrawWeaponTile(int weaponX, int weaponY, int weaponTile, int weaponShade, int weaponBits, int weaponPal, int weaponScale = 65536)
1799 {
1800     static int shadef = 0;
1801     static int palf = 0;
1802 
1803     // basic fading between player weapon shades
1804     if (shadef != weaponShade && (!weaponPal || palf == weaponPal))
1805     {
1806         shadef += (weaponShade - shadef) >> 2;
1807 
1808         if (!((weaponShade - shadef) >> 2))
1809             shadef = logapproach(shadef, weaponShade);
1810     }
1811     else
1812         shadef = weaponShade;
1813 
1814     palf = weaponPal;
1815 
1816 #ifdef USE_OPENGL
1817     if (videoGetRenderMode() >= REND_POLYMOST)
1818     {
1819         if (!RR && weaponTile >= CHAINGUN + 1 && weaponTile <= CHAINGUN + 4)
1820         {
1821             if (!usemodels || md_tilehasmodel(weaponTile, weaponPal) < 0)
1822             {
1823                 // HACK: Draw the upper part of the chaingun two screen
1824                 // pixels (not texels; multiplied by weapon scale) lower
1825                 // first, preventing ugly horizontal seam.
1826                 g_dts_yadd = tabledivide32_noinline(65536 * 2 * 200, ydim);
1827                 G_DrawTileScaled(weaponX, weaponY, weaponTile, shadef, weaponBits, weaponPal);
1828                 g_dts_yadd = 0;
1829             }
1830         }
1831     }
1832 #endif
1833 
1834     G_DrawTileScaled(weaponX, weaponY, weaponTile, shadef, weaponBits, weaponPal, weaponScale);
1835 }
1836 
G_DrawWeaponTileWithID(int uniqueID,int weaponX,int weaponY,int weaponTile,int weaponShade,int weaponBits,int p,int weaponScale=65536)1837 static inline void G_DrawWeaponTileWithID(int uniqueID, int weaponX, int weaponY, int weaponTile, int weaponShade,
1838                                           int weaponBits, int p, int weaponScale = 65536)
1839 {
1840     int lastUniqueID = guniqhudid;
1841     guniqhudid       = uniqueID;
1842 
1843     G_DrawWeaponTile(weaponX, weaponY, weaponTile, weaponShade, weaponBits, p, weaponScale);
1844 
1845     guniqhudid       = lastUniqueID;
1846 }
1847 
G_DrawWeaponTileUnfadedWithID(int uniqueID,int weaponX,int weaponY,int weaponTile,int weaponShade,int weaponBits,int p)1848 static inline void G_DrawWeaponTileUnfadedWithID(int uniqueID, int weaponX, int weaponY, int weaponTile, int weaponShade,
1849                                           int weaponBits, int p)
1850 {
1851     int lastUniqueID = guniqhudid;
1852     guniqhudid       = uniqueID;
1853 
1854     G_DrawTileScaled(weaponX, weaponY, weaponTile, weaponShade, weaponBits, p); // skip G_DrawWeaponTile
1855 
1856     guniqhudid       = lastUniqueID;
1857 }
1858 
P_DisplayKnee(int kneeShade)1859 static int P_DisplayKnee(int kneeShade)
1860 {
1861     static int8_t const       knee_y[] = { 0, -8, -16, -32, -64, -84, -108, -108, -108, -72, -32, -8 };
1862     const DukePlayer_t *const ps = g_player[screenpeek].ps;
1863 
1864     if (ps->knee_incs == 0)
1865         return 0;
1866 
1867     if (ps->knee_incs >= ARRAY_SIZE(knee_y) || sprite[ps->i].extra <= 0)
1868         return 0;
1869 
1870     int const kneeY   = knee_y[ps->knee_incs] + (klabs(ps->look_ang) / 9) - (ps->hard_landing << 3);
1871     int const kneePal = P_GetKneePal(ps);
1872 
1873     G_DrawTileScaled(105+(fix16_to_int(g_player[screenpeek].inputBits->q16avel)>>5)-(ps->look_ang>>1)+(knee_y[ps->knee_incs]>>2),
1874                      kneeY+280-(fix16_to_int(ps->q16horiz-ps->q16horizoff)>>4),KNEE,kneeShade,4+DRAWEAP_CENTER,kneePal);
1875 
1876     return 1;
1877 }
1878 
P_DisplayKnuckles(int knuckleShade)1879 static int P_DisplayKnuckles(int knuckleShade)
1880 {
1881     if (WW2GI)
1882         return 0;
1883     const DukePlayer_t *const pPlayer = g_player[screenpeek].ps;
1884 
1885     if (pPlayer->knuckle_incs == 0)
1886         return 0;
1887 
1888     static int8_t const knuckleFrames[] = { 0, 1, 2, 2, 3, 3, 3, 2, 2, 1, 0 };
1889 
1890     if ((unsigned) (pPlayer->knuckle_incs>>1) >= ARRAY_SIZE(knuckleFrames) || sprite[pPlayer->i].extra <= 0)
1891         return 0;
1892 
1893     int const knuckleY   = (klabs(pPlayer->look_ang) / 9) - (pPlayer->hard_landing << 3);
1894     int const knucklePal = P_GetHudPal(pPlayer);
1895 
1896     G_DrawTileScaled(160 + (fix16_to_int(g_player[screenpeek].inputBits->q16avel) >> 5) - (pPlayer->look_ang >> 1),
1897                      knuckleY + 180 - (fix16_to_int(pPlayer->q16horiz - pPlayer->q16horizoff) >> 4),
1898                      CRACKKNUCKLES + knuckleFrames[pPlayer->knuckle_incs >> 1], knuckleShade, 4 + DRAWEAP_CENTER,
1899                      knucklePal);
1900 
1901     return 1;
1902 }
1903 
1904 // Set C-CON's WEAPON and WORKSLIKE gamevars.
P_SetWeaponGamevars(int playerNum,const DukePlayer_t * const pPlayer)1905 void P_SetWeaponGamevars(int playerNum, const DukePlayer_t * const pPlayer)
1906 {
1907     if (!WW2GI)
1908         return;
1909     Gv_SetVar(g_weaponVarID, pPlayer->curr_weapon, pPlayer->i, playerNum);
1910     Gv_SetVar(g_worksLikeVarID,
1911               ((unsigned)pPlayer->curr_weapon < MAX_WEAPONS) ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : -1,
1912               pPlayer->i, playerNum);
1913 }
1914 
P_FireWeapon(int playerNum)1915 static void P_FireWeapon(int playerNum)
1916 {
1917     auto const pPlayer = g_player[playerNum].ps;
1918 
1919     if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) != KNEE_WEAPON)
1920         pPlayer->ammo_amount[pPlayer->curr_weapon]--;
1921 
1922     if (PWEAPON(playerNum, pPlayer->curr_weapon, FireSound) > 0)
1923         A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, FireSound), pPlayer->i);
1924 
1925     P_SetWeaponGamevars(playerNum, pPlayer);
1926     //        OSD_Printf("doing %d %d %d\n",PWEAPON(snum, p->curr_weapon, Shoots),p->curr_weapon,snum);
1927     A_Shoot(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Shoots));
1928 
1929     for (bssize_t burstFire = PWEAPON(playerNum, pPlayer->curr_weapon, ShotsPerBurst) - 1; burstFire > 0; --burstFire)
1930     {
1931         A_Shoot(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Shoots));
1932 
1933         if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_AMMOPERSHOT)
1934         {
1935             pPlayer->ammo_amount[pPlayer->curr_weapon]--;
1936         }
1937     }
1938 
1939     if (!(PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_NOVISIBLE))
1940     {
1941 #ifdef POLYMER
1942         spritetype *s = &sprite[pPlayer->i];
1943         int32_t     x = ((sintable[(s->ang + 512) & 2047]) >> 7), y = ((sintable[(s->ang) & 2047]) >> 7);
1944 
1945         s->x += x;
1946         s->y += y;
1947         G_AddGameLight(0, pPlayer->i, PHEIGHT, 8192, PWEAPON(playerNum, pPlayer->curr_weapon, FlashColor),
1948                        PR_LIGHT_PRIO_MAX_GAME);
1949         actor[pPlayer->i].lightcount = 2;
1950         s->x -= x;
1951         s->y -= y;
1952 #endif  // POLYMER
1953         pPlayer->visibility = 0;
1954     }
1955 
1956     if (/*!(PWEAPON(playerNum, p->curr_weapon, Flags) & WEAPON_CHECKATRELOAD) && */
1957             PWEAPON(playerNum, pPlayer->curr_weapon, Reload) > PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime) && pPlayer->ammo_amount[pPlayer->curr_weapon] > 0
1958                 && (PWEAPON(playerNum, pPlayer->curr_weapon, Clip)) && (((pPlayer->ammo_amount[pPlayer->curr_weapon]%(PWEAPON(playerNum, pPlayer->curr_weapon, Clip)))==0)))
1959     {
1960         pPlayer->kickback_pic = PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime);
1961     }
1962 
1963     if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) != KNEE_WEAPON)
1964         P_CheckWeapon(pPlayer);
1965 }
1966 
P_DoWeaponSpawn(int playerNum)1967 static void P_DoWeaponSpawn(int playerNum)
1968 {
1969     auto const pPlayer = g_player[playerNum].ps;
1970 
1971     // NOTE: For the 'Spawn' member, 0 means 'none', too (originally so,
1972     // i.e. legacy). The check for <0 was added to the check because mod
1973     // authors (rightly) assumed that -1 is the no-op value.
1974     if (PWEAPON(playerNum, pPlayer->curr_weapon, Spawn) <= 0)  // <=0 : AMC TC beta/RC2 has WEAPONx_SPAWN -1
1975         return;
1976 
1977     int newSprite = A_Spawn(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Spawn));
1978 
1979     if ((PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_SPAWNTYPE2))
1980     {
1981         // like shotgun shells
1982         sprite[newSprite].ang += 1024;
1983         A_SetSprite(newSprite,CLIPMASK0);
1984         sprite[newSprite].ang += 1024;
1985     }
1986     else if ((PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_SPAWNTYPE3))
1987     {
1988         // like chaingun shells
1989         sprite[newSprite].ang += 1024;
1990         sprite[newSprite].ang &= 2047;
1991         sprite[newSprite].xvel += 32;
1992         sprite[newSprite].z += (3<<8);
1993         A_SetSprite(newSprite,CLIPMASK0);
1994     }
1995 }
1996 
P_DisplayScuba(void)1997 void P_DisplayScuba(void)
1998 {
1999     if (g_player[screenpeek].ps->scuba_on)
2000     {
2001         const DukePlayer_t *const pPlayer = g_player[screenpeek].ps;
2002 
2003         int const scubaPal = P_GetHudPal(pPlayer);
2004 
2005 #ifdef SPLITSCREEN_MOD_HACKS
2006         g_snum = screenpeek;
2007 #endif
2008 
2009         if (RR)
2010         {
2011 
2012             if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING))
2013             {
2014                 G_DrawTileScaled(320 - (tilesiz[SCUBAMASK].x >> 1) - 15, 200 - (tilesiz[SCUBAMASK].y >> 1) + (sintable[(int32_t) totalclock & 2047] >> 10),
2015                                  SCUBAMASK, 0, 2 + 16 + DRAWEAP_CENTER+512, scubaPal,49152);
2016                 G_DrawTileScaled(320 - tilesiz[SCUBAMASK+4].x, 200 - tilesiz[SCUBAMASK+4].y, SCUBAMASK+4, 0, 2 + 16 + DRAWEAP_CENTER + 1024, scubaPal);
2017                 G_DrawTileScaled(tilesiz[SCUBAMASK+4].x, 200 - tilesiz[SCUBAMASK+4].y, SCUBAMASK+4, 0, 2 + 4 + 16 + DRAWEAP_CENTER + 1024, scubaPal);
2018                 //G_DrawTileScaled(35, -1, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER+512, scubaPal);
2019                 //G_DrawTileScaled(35, -1, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER+256, scubaPal);
2020                 //G_DrawTileScaled(285, 200, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER+512, scubaPal,65536,1024);
2021                 //G_DrawTileScaled(285, 200, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER+256, scubaPal,65536,1024);
2022                 G_DrawTileScaled(35, -1, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER+1024, scubaPal);
2023                 G_DrawTileScaled(285, 200, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER+1024, scubaPal,65536,1024);
2024             }
2025             else
2026             {
2027                 G_DrawTileScaled(320 - (tilesiz[SCUBAMASK].x >> 1) - 15, 200 - (tilesiz[SCUBAMASK].y >> 1) + (sintable[(int32_t) totalclock & 2047] >> 10),
2028                                  SCUBAMASK, 0, 2 + 16 + DRAWEAP_CENTER, scubaPal,49152);
2029                 G_DrawTileScaled(320 - tilesiz[SCUBAMASK+4].x, 200 - tilesiz[SCUBAMASK+4].y, SCUBAMASK+4, 0, 2 + 16 + DRAWEAP_CENTER, scubaPal);
2030                 G_DrawTileScaled(tilesiz[SCUBAMASK+4].x, 200 - tilesiz[SCUBAMASK+4].y, SCUBAMASK+4, 0, 2 + 4 + 16 + DRAWEAP_CENTER, scubaPal);
2031                 G_DrawTileScaled(35, -1, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER, scubaPal);
2032                 G_DrawTileScaled(285, 200, SCUBAMASK+3, 0, 2 + 16 + DRAWEAP_CENTER, scubaPal,65536,1024);
2033             }
2034         }
2035         else
2036         {
2037             // this is a hack to hide the seam that appears between the two halves of the mask in GL
2038 #ifdef USE_OPENGL
2039             if (videoGetRenderMode() >= REND_POLYMOST)
2040                 G_DrawTileScaled(44, (200 - tilesiz[SCUBAMASK].y), SCUBAMASK, 0, 2 + 16 + DRAWEAP_CENTER, scubaPal);
2041 #endif
2042             G_DrawTileScaled(43, (200 - tilesiz[SCUBAMASK].y), SCUBAMASK, 0, 2 + 16 + DRAWEAP_CENTER, scubaPal);
2043             G_DrawTileScaled(320 - 43, (200 - tilesiz[SCUBAMASK].y), SCUBAMASK, 0, 2 + 4 + 16 + DRAWEAP_CENTER, scubaPal);
2044         }
2045     }
2046 }
2047 
2048 static int8_t const access_tip_y [] = {
2049     0, -8, -16, -32, -64, -84, -108, -108, -108, -108, -108, -108, -108, -108, -108, -108, -96, -72, -64, -32, -16
2050 };
2051 
P_DisplayTip(int tipShade)2052 static int P_DisplayTip(int tipShade)
2053 {
2054     const DukePlayer_t *const pPlayer = g_player[screenpeek].ps;
2055 
2056     if (pPlayer->tipincs == 0)
2057         return 0;
2058 
2059     // Report that the tipping hand has been drawn so that the otherwise
2060     // selected weapon is not drawn.
2061     if ((unsigned)pPlayer->tipincs >= ARRAY_SIZE(access_tip_y))
2062         return 1;
2063 
2064     int const tipY       = (klabs(pPlayer->look_ang) / 9) - (pPlayer->hard_landing << 3);
2065     int const tipPal     = P_GetHudPal(pPlayer);
2066     int const tipYOffset = access_tip_y[pPlayer->tipincs] >> 1;
2067 
2068     guniqhudid = 201;
2069 
2070     G_DrawTileScaled(170 + (fix16_to_int(g_player[screenpeek].inputBits->q16avel) >> 5) - (pPlayer->look_ang >> 1),
2071                      tipYOffset + tipY + 240 - (fix16_to_int(pPlayer->q16horiz - pPlayer->q16horizoff) >> 4),
2072                      TIP + ((26 - pPlayer->tipincs) >> 4), tipShade, DRAWEAP_CENTER, tipPal);
2073 
2074     guniqhudid = 0;
2075 
2076     return 1;
2077 }
2078 
P_DisplayAccess(int accessShade)2079 static int P_DisplayAccess(int accessShade)
2080 {
2081     const DukePlayer_t *const pSprite = g_player[screenpeek].ps;
2082 
2083     if (pSprite->access_incs == 0)
2084         return 0;
2085 
2086     if ((unsigned)pSprite->access_incs >= ARRAY_SIZE(access_tip_y)-4 || sprite[pSprite->i].extra <= 0)
2087         return 1;
2088 
2089     int const accessX   = access_tip_y[pSprite->access_incs] >> 2;
2090     int const accessY   = access_tip_y[pSprite->access_incs] + (klabs(pSprite->look_ang) / 9) - (pSprite->hard_landing << 3);
2091     int const accessPal = (pSprite->access_spritenum >= 0) ? sprite[pSprite->access_spritenum].pal : 0;
2092 
2093     guniqhudid = 200;
2094 
2095     if ((pSprite->access_incs - 3) > 0 && (pSprite->access_incs - 3) >> 3)
2096     {
2097         G_DrawTileScaled(170 + (fix16_to_int(g_player[screenpeek].inputBits->q16avel) >> 5) - (pSprite->look_ang >> 1) + accessX,
2098                          accessY + 266 - (fix16_to_int(pSprite->q16horiz - pSprite->q16horizoff) >> 4),
2099                          HANDHOLDINGLASER + (pSprite->access_incs >> 3), accessShade, DRAWEAP_CENTER, accessPal);
2100     }
2101     else
2102     {
2103         G_DrawTileScaled(170 + (fix16_to_int(g_player[screenpeek].inputBits->q16avel) >> 5) - (pSprite->look_ang >> 1) + accessX,
2104                          accessY + 266 - (fix16_to_int(pSprite->q16horiz - pSprite->q16horizoff) >> 4), HANDHOLDINGACCESS, accessShade,
2105                          4 + DRAWEAP_CENTER, accessPal);
2106     }
2107 
2108     guniqhudid = 0;
2109 
2110     return 1;
2111 }
2112 
P_DisplayWeapon(void)2113 void P_DisplayWeapon(void)
2114 {
2115     if (REALITY)
2116         return RT_P_DisplayWeapon();
2117 
2118     DukePlayer_t *const  pPlayer     = g_player[screenpeek].ps;
2119     const int16_t *const weaponFrame = &pPlayer->kickback_pic;
2120 
2121     int currentWeapon, quickKickFrame;
2122 
2123 #ifdef SPLITSCREEN_MOD_HACKS
2124     g_snum = screenpeek;
2125 #endif
2126 
2127     if (DEER)
2128     {
2129         switch (pPlayer->dhat61f)
2130         {
2131         case 0:
2132             ghpistol_render(screenpeek);
2133             break;
2134         case 1:
2135             ghrifle_render(screenpeek, 0);
2136             break;
2137         case 2:
2138             ghrifle_render(screenpeek, 1);
2139             break;
2140         case 3:
2141             ghshtgn_render(screenpeek);
2142             break;
2143         case 4:
2144             ghbow_render(screenpeek);
2145             break;
2146         }
2147         return;
2148     }
2149 
2150     if (pPlayer->newowner >= 0 || ud.camerasprite >= 0 || (!RR && pPlayer->over_shoulder_on > 0)
2151         || (sprite[pPlayer->i].pal != 1 && sprite[pPlayer->i].extra <= 0))
2152         return;
2153 
2154     int weaponX       = (160) - 90;
2155     int weaponY       = klabs(pPlayer->look_ang) / 9;
2156     int weaponYOffset = 80 - (pPlayer->weapon_pos * pPlayer->weapon_pos);
2157     int weaponShade   = (RR && pPlayer->cursectnum >= 0 && g_shadedSector[pPlayer->cursectnum]) ? 16 : (sprite[pPlayer->i].shade <= 24 ? sprite[pPlayer->i].shade : 24);
2158 
2159     int32_t weaponBits = 0;
2160     UNREFERENCED_PARAMETER(weaponBits);
2161 
2162     if (!RR && (P_DisplayFist(weaponShade) || P_DisplayKnuckles(weaponShade) || P_DisplayTip(weaponShade) || P_DisplayAccess(weaponShade)))
2163         goto enddisplayweapon;
2164 
2165     if (!RR)
2166         P_DisplayKnee(weaponShade);
2167 
2168     if (ud.weaponsway)
2169     {
2170         weaponX -= (sintable[((pPlayer->weapon_sway>>1)+512)&2047]/(1024+512));
2171         weaponYOffset -= (sprite[pPlayer->i].xrepeat < (RR ? 8 : 32)) ? klabs(sintable[(pPlayer->weapon_sway << 2) & 2047] >> 9)
2172                                                            : klabs(sintable[(pPlayer->weapon_sway >> 1) & 2047] >> 10);
2173     }
2174     else weaponYOffset -= 16;
2175 
2176     weaponX -= 58 + pPlayer->weapon_ang;
2177     weaponYOffset -= (pPlayer->hard_landing << 3);
2178 
2179     if (WW2GI)
2180         currentWeapon   = PWEAPON(screenpeek, (pPlayer->last_weapon >= 0) ? pPlayer->last_weapon : pPlayer->curr_weapon, WorksLike);
2181     else
2182         currentWeapon   = (pPlayer->last_weapon >= 0) ? pPlayer->last_weapon : pPlayer->curr_weapon;
2183     hudweap.gunposy     = weaponYOffset;
2184     hudweap.lookhoriz   = weaponY;
2185     hudweap.cur         = currentWeapon;
2186     hudweap.gunposx     = weaponX;
2187     hudweap.shade       = weaponShade;
2188     hudweap.count       = *weaponFrame;
2189     hudweap.lookhalfang = pPlayer->look_ang >> 1;
2190 
2191     quickKickFrame = 14 - pPlayer->quick_kick;
2192 
2193     if (!RR && (quickKickFrame != 14 || pPlayer->last_quick_kick) && ud.drawweapon == 1)
2194     {
2195         int const weaponPal = P_GetKneePal(pPlayer);
2196 
2197         guniqhudid = 100;
2198 
2199         if (quickKickFrame < 6 || quickKickFrame > 12)
2200             G_DrawTileScaled(weaponX + 80 - (pPlayer->look_ang >> 1), weaponY + 250 - weaponYOffset, KNEE, weaponShade,
2201                                 weaponBits | 4 | DRAWEAP_CENTER, weaponPal);
2202         else
2203             G_DrawTileScaled(weaponX + 160 - 16 - (pPlayer->look_ang >> 1), weaponY + 214 - weaponYOffset, KNEE + 1,
2204                                 weaponShade, weaponBits | 4 | DRAWEAP_CENTER, weaponPal);
2205         guniqhudid = 0;
2206     }
2207 
2208     if (RRRA)
2209     {
2210         if (pPlayer->on_motorcycle)
2211         {
2212             int motoTile = MOTOHIT;
2213             if (!g_netServer && numplayers == 1)
2214             {
2215                 if (*weaponFrame)
2216                 {
2217                     weaponShade = 0;
2218                     if (*weaponFrame == 1)
2219                     {
2220                         if ((krand2()&1) == 1)
2221                             motoTile = MOTOHIT+1;
2222                         else
2223                             motoTile = MOTOHIT+2;
2224                     }
2225                     else if (*weaponFrame == 4)
2226                     {
2227                         if ((krand2()&1) == 1)
2228                             motoTile = MOTOHIT+3;
2229                         else
2230                             motoTile = MOTOHIT+4;
2231                     }
2232                 }
2233             }
2234             else
2235             {
2236                 if (*weaponFrame)
2237                 {
2238                     weaponShade = 0;
2239                     if (*weaponFrame >= 1 && *weaponFrame <= 4)
2240                         motoTile += *weaponFrame;
2241                 }
2242             }
2243 
2244             int const weaponPal = P_GetHudPal(pPlayer);
2245 
2246             G_DrawTileScaled(160-(pPlayer->look_ang>>1), 174, motoTile, weaponShade, 2 | DRAWEAP_CENTER,
2247                 weaponPal, 34816, pPlayer->tilt_status * 5 + (pPlayer->tilt_status < 0 ? 2047 : 0));
2248             return;
2249         }
2250         if (pPlayer->on_boat)
2251         {
2252             int boatTile;
2253             if (pPlayer->tilt_status > 0)
2254             {
2255                 if (*weaponFrame == 0)
2256                     boatTile = BOATHIT+1;
2257                 else if (*weaponFrame <= 3)
2258                 {
2259                     boatTile = BOATHIT+5;
2260                     weaponShade = -96;
2261                 }
2262                 else if (*weaponFrame <= 6)
2263                 {
2264                     boatTile = BOATHIT+6;
2265                     weaponShade = -96;
2266                 }
2267                 else
2268                     boatTile = BOATHIT+1;
2269             }
2270             else if (pPlayer->tilt_status < 0)
2271             {
2272                 if (*weaponFrame == 0)
2273                     boatTile = BOATHIT+2;
2274                 else if (*weaponFrame <= 3)
2275                 {
2276                     boatTile = BOATHIT+7;
2277                     weaponShade = -96;
2278                 }
2279                 else if (*weaponFrame <= 6)
2280                 {
2281                     boatTile = BOATHIT+8;
2282                     weaponShade = -96;
2283                 }
2284                 else
2285                     boatTile = BOATHIT+2;
2286             }
2287             else
2288             {
2289                 if (*weaponFrame == 0)
2290                     boatTile = BOATHIT;
2291                 else if (*weaponFrame <= 3)
2292                 {
2293                     boatTile = BOATHIT+3;
2294                     weaponShade = -96;
2295                 }
2296                 else if (*weaponFrame <= 6)
2297                 {
2298                     boatTile = BOATHIT+4;
2299                     weaponShade = -96;
2300                 }
2301                 else
2302                     boatTile = BOATHIT;
2303             }
2304 
2305             int const weaponPal = P_GetHudPal(pPlayer);
2306             int weaponY;
2307 
2308             if (pPlayer->not_on_water)
2309                 weaponY = 170;
2310             else
2311                 weaponY = 170 + (*weaponFrame>>2);
2312 
2313             G_DrawTileScaled(160-(pPlayer->look_ang>>1), weaponY, boatTile, weaponShade, 2 | DRAWEAP_CENTER,
2314                 weaponPal, 66048, pPlayer->tilt_status + (pPlayer->tilt_status < 0 ? 2047 : 0));
2315             return;
2316         }
2317     }
2318 
2319     if (sprite[pPlayer->i].xrepeat < (RR ? 8 : 40))
2320     {
2321         static int32_t fistPos;
2322 
2323         int const weaponPal = P_GetHudPal(pPlayer);
2324 
2325         if (pPlayer->jetpack_on == 0)
2326         {
2327             int const playerXvel = sprite[pPlayer->i].xvel;
2328             weaponY += 32 - (playerXvel >> 3);
2329             fistPos += playerXvel >> 3;
2330         }
2331 
2332         currentWeapon = weaponX;
2333         weaponX += sintable[(fistPos)&2047] >> 10;
2334         G_DrawTileScaled(weaponX + 250 - (pPlayer->look_ang >> 1), weaponY + 258 - (klabs(sintable[(fistPos)&2047] >> 8)),
2335             FIST, weaponShade, weaponBits, weaponPal);
2336         weaponX = currentWeapon - (sintable[(fistPos)&2047] >> 10);
2337         G_DrawTileScaled(weaponX + 40 - (pPlayer->look_ang >> 1), weaponY + 200 + (klabs(sintable[(fistPos)&2047] >> 8)), FIST,
2338             weaponShade, weaponBits | 4, weaponPal);
2339     }
2340     else
2341     {
2342         switch (ud.drawweapon)
2343         {
2344             case 1: break;
2345             case 2:
2346                 if ((unsigned)hudweap.cur < MAX_WEAPONS && hudweap.cur != KNEE_WEAPON)
2347                     rotatesprite_win(160 << 16, (180 + (pPlayer->weapon_pos * pPlayer->weapon_pos)) << 16, divscale16(ud.statusbarscale, 100), 0,
2348                                         (!RR && hudweap.cur == GROW_WEAPON) ? GROWSPRITEICON : WeaponPickupSprites[hudweap.cur], 0,
2349                                         0, 2);
2350             default: goto enddisplayweapon;
2351         }
2352 
2353         if (!RR && currentWeapon == KNEE_WEAPON && *weaponFrame == 0)
2354             goto enddisplayweapon;
2355 
2356         int const doAnim      = !(sprite[pPlayer->i].pal == 1 || ud.pause_on || g_player[myconnectindex].ps->gm & MODE_MENU);
2357         int const halfLookAng = pPlayer->look_ang >> 1;
2358 
2359         int const weaponPal = P_GetHudPal(pPlayer);
2360 
2361         if (RR)
2362         {
2363             switch (DYNAMICWEAPONMAP(currentWeapon))
2364             {
2365             case KNEE_WEAPON__STATIC:
2366             {
2367                 static int weaponFrames[] = { 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7 };
2368                 static int offsetX[] = { 310,342,364,418,350,316,282,288,0,0 };
2369                 static int offsetY[] = { 300,362,320,268,248,248,277,420,0,0 };
2370                 weaponX = weaponX + ((offsetX[weaponFrames[*weaponFrame]]>>1) - 12);
2371                 weaponY = weaponY + 200 - (244-offsetY[weaponFrames[*weaponFrame]]);
2372                 guniqhudid = currentWeapon;
2373                 G_DrawTileScaled(weaponX - halfLookAng, weaponY - weaponYOffset, KNEE + weaponFrames[*weaponFrame],
2374                                     weaponShade, weaponBits, weaponPal, 32768);
2375                 guniqhudid = 0;
2376                 break;
2377             }
2378             case SLINGBLADE_WEAPON__STATIC:
2379                 if (RRRA)
2380                 {
2381                     if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING))
2382                         weaponBits |= 512;
2383                     static int weaponFrames[] = { 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7 };
2384                     static int offsetX[] = { 580,676,310,491,356,210,310,614 };
2385                     static int offsetY[] = { 369,363,300,323,371,400,300,440 };
2386                     weaponX = weaponX + ((offsetX[weaponFrames[*weaponFrame]]>>1) - 12);
2387                     weaponY = weaponY + 210 - (244-offsetY[weaponFrames[*weaponFrame]]);
2388                     guniqhudid = currentWeapon;
2389                     G_DrawTileScaled(weaponX - halfLookAng + 20, weaponY - weaponYOffset - 80, SLINGBLADE + weaponFrames[*weaponFrame],
2390                                         weaponShade, weaponBits, weaponPal, 32768);
2391                     guniqhudid = 0;
2392                     break;
2393                 }
2394                 break;
2395 
2396             case TRIPBOMB_WEAPON__STATIC:
2397             case BOWLINGBALL_WEAPON__STATIC:
2398                 weaponX += 8;
2399                 weaponYOffset -= 10;
2400 
2401                 if (currentWeapon == BOWLINGBALL_WEAPON)
2402                 {
2403                     if (pPlayer->ammo_amount[BOWLINGBALL_WEAPON])
2404                     {
2405                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 162 - halfLookAng, weaponY + 214 - weaponYOffset + (*weaponFrame) * 8, BOWLINGBALLH,
2406                                                 weaponShade, weaponBits, weaponPal, 32768);
2407                     }
2408                     else
2409                     {
2410                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 162 - halfLookAng, weaponY + 214 - weaponYOffset, HANDTHROW+5,
2411                                                 weaponShade, weaponBits, weaponPal, 36700);
2412                     }
2413                 }
2414                 else
2415                 {
2416                     if (pPlayer->ammo_amount[TRIPBOMB_WEAPON])
2417                     {
2418                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 180 - halfLookAng, weaponY + 214 - weaponYOffset + (*weaponFrame) * 8, POWDERH,
2419                                                 weaponShade, weaponBits, weaponPal, 36700);
2420                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 90 - halfLookAng, weaponY + 214 - weaponYOffset + (*weaponFrame) * 8, POWDERH,
2421                                                 weaponShade, weaponBits | 4, weaponPal, 36700);
2422                     }
2423                     else
2424                     {
2425                         G_DrawWeaponTileWithID(currentWeapon << 2, weaponX + 162 - halfLookAng, weaponY + 214 - weaponYOffset, HANDTHROW+5,
2426                                                 weaponShade, weaponBits, weaponPal, 36700);
2427                     }
2428                 }
2429                 break;
2430 
2431             case RPG_WEAPON__STATIC:
2432             {
2433                 if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING))
2434                     weaponBits |= 512;
2435                 static int frames[] = { 0,1,1,2,2,3,2,3,2,3,2,2,2,2,2,2,2,2,2,4,4,4,4,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7 };
2436                 int frame = frames[*weaponFrame];
2437                 if (frame == 2 || frame == 3)
2438                 {
2439                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 200 - halfLookAng, weaponY + 250 - weaponYOffset,
2440                                            RPGGUN + frame, weaponShade, weaponBits, weaponPal, 36700);
2441                 }
2442                 else if (frame == 1)
2443                 {
2444                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 200 - halfLookAng, weaponY + 250 - weaponYOffset,
2445                                            RPGGUN + frame, 0, weaponBits, weaponPal, 36700);
2446                 }
2447                 else
2448                 {
2449                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - halfLookAng, weaponY + 255 - weaponYOffset,
2450                                            RPGGUN + frame, weaponShade, weaponBits, weaponPal, 36700);
2451                 }
2452                 break;
2453             }
2454 
2455             case CHICKEN_WEAPON__STATIC:
2456             {
2457                 if (!RRRA) break;
2458                 if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING))
2459                     weaponBits |= 512;
2460                 if (*weaponFrame)
2461                 {
2462                     static int frames[] = { 0,1,1,2,2,3,2,3,2,3,2,2,2,2,2,2,2,2,2,4,4,4,4,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7 };
2463                     int frame = frames[*weaponFrame];
2464                     if (frame == 2 || frame == 3)
2465                     {
2466                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 200 - halfLookAng, weaponY + 250 - weaponYOffset,
2467                                                RPGGUN2 + frame, weaponShade, weaponBits, weaponPal, 36700);
2468                     }
2469                     else if (frame == 1)
2470                     {
2471                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 200 - halfLookAng, weaponY + 250 - weaponYOffset,
2472                                                RPGGUN2 + frame, 0, weaponBits, weaponPal, 36700);
2473                     }
2474                     else
2475                     {
2476                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - halfLookAng, weaponY + 255 - weaponYOffset,
2477                                                RPGGUN2 + frame, weaponShade, weaponBits, weaponPal, 36700);
2478                     }
2479                 }
2480                 else
2481                 {
2482                     if (!g_netServer && ud.multimode < 2)
2483                     {
2484                         if (g_chickenWeaponTimer)
2485                         {
2486                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - halfLookAng, weaponY + 222 - weaponYOffset,
2487                                                    RPGGUN2+7, weaponShade, weaponBits, weaponPal, 36700);
2488                         }
2489                         else if ((krand2() & 15) == 5)
2490                         {
2491                             A_PlaySound(327, pPlayer->i);
2492                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - halfLookAng, weaponY + 222 - weaponYOffset,
2493                                                    RPGGUN2+7, weaponShade, weaponBits, weaponPal, 36700);
2494                             g_chickenWeaponTimer = 6;
2495                         }
2496                         else
2497                         {
2498                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - halfLookAng, weaponY + 225 - weaponYOffset,
2499                                                    RPGGUN2, weaponShade, weaponBits, weaponPal, 36700);
2500                         }
2501 
2502                     }
2503                     else
2504                     {
2505                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - halfLookAng, weaponY + 225 - weaponYOffset,
2506                                                RPGGUN2, weaponShade, weaponBits, weaponPal, 36700);
2507                     }
2508                 }
2509                 break;
2510             }
2511 
2512             case SHOTGUN_WEAPON__STATIC:
2513                 weaponX -= 8;
2514                 {
2515                     static int kb_frames3[] = { 0,0,1,1,2,2,5,5,6,6,7,7,8,8,0,0,0,0,0,0,0 };
2516                     static int kb_frames2[] = { 0,0,3,3,4,4,5,5,6,6,7,7,8,8,0,0,20,20,21,21,21,21,20,20,20,20,0,0 };
2517                     static int kb_frames[] = { 0,0,1,1,2,2,3,3,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,0,0,20,20,21,21,21,21,20,20,20,20,0,0 };
2518                     static int kb_ox[] = { 300,300,300,300,300,330,320,310,305,306,302 };
2519                     static int kb_oy[] = { 315,300,302,305,302,302,303,306,302,404,384 };
2520                     if (pPlayer->shotgun_state[1])
2521                     {
2522                         if (*weaponFrame < 26)
2523                         {
2524                             int frm = kb_frames[*weaponFrame];
2525                             if (frm == 3 || frm == 4)
2526                                 weaponShade = 0;
2527                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 52 - halfLookAng + (kb_ox[frm] >> 1),
2528                                 weaponY + kb_oy[frm] - 64 - weaponYOffset, SHOTGUN + frm, weaponShade, weaponBits, weaponPal, 32768);
2529                         }
2530                         else
2531                         {
2532                             int frm;
2533                             if (kb_frames[*weaponFrame] > 0)
2534                                 frm = kb_frames[(*weaponFrame) - 11];
2535                             else
2536                                 frm = kb_frames[*weaponFrame];
2537                             weaponX += (kb_ox[frm] >> 1) - 12;
2538                             weaponY += kb_oy[frm] - 64;
2539                             switch (*weaponFrame)
2540                             {
2541                             case 23:
2542                                 weaponY += 60;
2543                                 break;
2544                             case 24:
2545                                 weaponY += 30;
2546                                 break;
2547                             }
2548                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 64 - halfLookAng, weaponY - weaponYOffset,
2549                                 SHOTGUN + kb_frames[*weaponFrame], weaponShade, weaponBits, weaponPal, 32768);
2550                             if (kb_frames[*weaponFrame] == 21)
2551                                 G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 96 - halfLookAng, weaponY - weaponYOffset,
2552                                     SHOTGUNSHELLS, weaponShade, weaponBits, weaponPal, 32768);
2553                         }
2554                     }
2555                     else
2556                     {
2557                         if ((*weaponFrame) < 16)
2558                         {
2559                             if (pPlayer->shotgun_state[0])
2560                             {
2561                                 int frm = kb_frames2[*weaponFrame];
2562                                 if (frm == 3 || frm == 4)
2563                                     weaponShade = 0;
2564                                 G_DrawWeaponTileWithID(currentWeapon, weaponX + 52 - halfLookAng + (kb_ox[frm] >> 1),
2565                                     weaponY + kb_oy[frm] - 64 - weaponYOffset, SHOTGUN + frm, weaponShade, weaponBits, weaponPal, 32768);
2566                             }
2567                             else
2568                             {
2569                                 int frm = kb_frames3[*weaponFrame];
2570                                 if (frm == 1 || frm == 2)
2571                                     weaponShade = 0;
2572                                 G_DrawWeaponTileWithID(currentWeapon, weaponX + 52 - halfLookAng + (kb_ox[frm] >> 1),
2573                                     weaponY + kb_oy[frm] - 64 - weaponYOffset, SHOTGUN + frm, weaponShade, weaponBits, weaponPal, 32768);
2574                             }
2575                         }
2576                         else if (pPlayer->shotgun_state[0])
2577                         {
2578                             int frm;
2579                             if (kb_frames2[*weaponFrame] > 0)
2580                                 frm = kb_frames2[(*weaponFrame) - 11];
2581                             else
2582                                 frm = kb_frames2[*weaponFrame];
2583                             weaponX += (kb_ox[frm] >> 1) - 12;
2584                             weaponY += kb_oy[frm] - 64;
2585                             switch (*weaponFrame)
2586                             {
2587                             case 23:
2588                                 weaponY += 60;
2589                                 break;
2590                             case 24:
2591                                 weaponY += 30;
2592                                 break;
2593                             }
2594                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 64 - halfLookAng, weaponY - weaponYOffset,
2595                                 SHOTGUN + kb_frames2[*weaponFrame], weaponShade, weaponBits, weaponPal, 32768);
2596                             if (kb_frames2[*weaponFrame] == 21)
2597                                 G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 96 - halfLookAng, weaponY - weaponYOffset,
2598                                     SHOTGUNSHELLS, weaponShade, weaponBits, weaponPal, 32768);
2599                         }
2600                     }
2601                 }
2602                 break;
2603 
2604             case CHAINGUN_WEAPON__STATIC:
2605                 if (*weaponFrame > 0)
2606                 {
2607                     weaponYOffset -= sintable[(*weaponFrame)<<7]>>12;
2608 
2609                     if (doAnim)
2610                         weaponX += 1-(rand()&3);
2611                 }
2612 
2613                 switch (*weaponFrame)
2614                 {
2615                 case 0:
2616                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - (pPlayer->look_ang >> 1) + 30, weaponY + 233 - weaponYOffset + 5,
2617                                             CHAINGUN, weaponShade, weaponBits, weaponPal, 32768);
2618                     break;
2619 
2620                 default:
2621                     if (*weaponFrame < 8)
2622                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - (pPlayer->look_ang >> 1) + 30, weaponY + 233 - weaponYOffset + 5,
2623                                                 CHAINGUN + 1, 0, weaponBits, weaponPal, 32768);
2624                     else
2625                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - (pPlayer->look_ang >> 1) + 30, weaponY + 233 - weaponYOffset + 5,
2626                                                 CHAINGUN + 2, weaponShade, weaponBits, weaponPal, 32768);
2627 
2628                     break;
2629                 }
2630                 break;
2631 
2632             case PISTOL_WEAPON__STATIC:
2633                 if ((*weaponFrame) < 22)
2634                 {
2635                     static int frames[] = { 0,0,1,1,2,2,3,3,4,4,6,6,6,6,5,5,4,4,3,3,0,0 };
2636                     static int offsetX[] = { 194,190,185,208,215,215,216,216,201,170 };
2637                     static int offsetY[] = { 256,249,248,238,228,218,208,256,245,258 };
2638                     int frame = frames[*weaponFrame];
2639 
2640                     if (frame)
2641                         weaponShade = 0;
2642 
2643                     G_DrawWeaponTileWithID(currentWeapon, offsetX[frame] - 12 + weaponX - (pPlayer->look_ang >> 1), weaponY + offsetY[frame] - weaponYOffset,
2644                                             FIRSTGUN + frame, weaponShade, weaponBits, weaponPal, 36700);
2645 
2646                     break;
2647                 }
2648                 else
2649                 {
2650                     static int frames[] = { 0,0,1,1,2,2,2,2,2,2,2,2,2,2,2,1,1,0,0 };
2651                     static int offsetX[] = { 244,244,244 };
2652                     static int offsetY[] = { 256,249,248 };
2653                     int dx, dy;
2654                     int frame = frames[(*weaponFrame) - 22];
2655                     switch (*weaponFrame)
2656                     {
2657                         case 28:
2658                             dy = 10;
2659                             dx = 5;
2660                             break;
2661                         case 29:
2662                             dy = 20;
2663                             dx = 10;
2664                             break;
2665                         case 30:
2666                             dy = 30;
2667                             dx = 15;
2668                             break;
2669                         case 31:
2670                             dy = 40;
2671                             dx = 20;
2672                             break;
2673                         case 32:
2674                             dy = 50;
2675                             dx = 25;
2676                             break;
2677                         case 33:
2678                             dy = 40;
2679                             dx = 20;
2680                             break;
2681                         case 34:
2682                             dy = 30;
2683                             dx = 15;
2684                             break;
2685                         case 35:
2686                             dy = 20;
2687                             dx = 10;
2688                             break;
2689                         case 36:
2690                             dy = 10;
2691                             dx = 5;
2692                             break;
2693                         default:
2694                             dy = 0;
2695                             dx = 0;
2696                             break;
2697                     }
2698 
2699                     G_DrawWeaponTileWithID(currentWeapon, weaponX + offsetX[frame] - 12 - dx - halfLookAng, weaponY + offsetY[frame] - weaponYOffset + dy,
2700                                             FIRSTGUNRELOAD + frame, weaponShade, weaponBits, weaponPal, 36700);
2701                 }
2702                 break;
2703 
2704             case HANDBOMB_WEAPON__STATIC:
2705                 weaponYOffset -= 9 * (*weaponFrame);
2706                 G_DrawWeaponTileWithID(currentWeapon, weaponX + 190 - halfLookAng, weaponY + 260 - weaponYOffset,
2707                                         HANDTHROW, weaponShade, weaponBits, weaponPal, 36700);
2708                 break;
2709 
2710             case HANDREMOTE_WEAPON__STATIC:
2711                 if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING))
2712                     weaponBits |= 512;
2713 
2714                 if(*weaponFrame < 20)
2715                 {
2716                     static uint8_t remoteFrames[] = { 1,1,1,1,1,2,2,2,2,3,3,3,4,4,4,5,5,5,5,5,6,6,6 };
2717 
2718                     if (*weaponFrame >= ARRAY_SIZE(remoteFrames))
2719                         break;
2720 
2721                     if (*weaponFrame < 5)
2722                     {
2723                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 265 - halfLookAng, weaponY + 174 - weaponYOffset + pPlayer->hbomb_offset,
2724                                                 RRTILE1752, 0, weaponBits, weaponPal, 36700);
2725                     }
2726                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 290 - halfLookAng, weaponY + 238 - weaponYOffset,
2727                                             HANDTHROW + remoteFrames[(*weaponFrame)], 0, weaponBits, weaponPal, 36700);
2728                 }
2729                 break;
2730 
2731             case DEVISTATOR_WEAPON__STATIC:
2732                 if (*weaponFrame)
2733                     G_DrawWeaponTileWithID(currentWeapon, 150 + (weaponX >> 1) - halfLookAng, 266 + (weaponY >> 1) - weaponYOffset,
2734                                             DEVISTATOR, 0, weaponBits, weaponPal, 47040);
2735                 else
2736                     G_DrawWeaponTileWithID(currentWeapon, 150 + (weaponX >> 1) - halfLookAng, 266 + (weaponY >> 1) - weaponYOffset,
2737                                             DEVISTATOR + 1, weaponShade, weaponBits, weaponPal, 47040);
2738                 break;
2739 
2740             case FREEZE_WEAPON__STATIC:
2741                 if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING))
2742                     weaponBits |= 512;
2743 
2744                 if ((*weaponFrame) > 0)
2745                 {
2746                     static uint8_t freezerFrames[] = { 0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
2747 
2748                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 260 - (pPlayer->look_ang >> 1), weaponY + 215 - weaponYOffset,
2749                                             FREEZE + freezerFrames[*weaponFrame], -32, weaponBits, weaponPal, 32768);
2750                 }
2751                 else
2752                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 260 - (pPlayer->look_ang >> 1), weaponY + 215 - weaponYOffset,
2753                                             FREEZE, weaponShade, weaponBits, weaponPal, 32768);
2754                 break;
2755 
2756             case GROW_WEAPON__STATIC:
2757             case SHRINKER_WEAPON__STATIC:
2758                 weaponX += 28;
2759                 weaponY += 18;
2760 
2761                 if ((*weaponFrame) > 0)
2762                 {
2763                     if (doAnim)
2764                     {
2765                         weaponX += rand() & 3;
2766                         weaponYOffset += (rand() & 3);
2767                     }
2768 
2769                     if (currentWeapon == GROW_WEAPON)
2770                     {
2771                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset,
2772                                                 GROWSPARK + ((*weaponFrame)&2), weaponShade, weaponBits, 0, 44040);
2773                     }
2774                     else
2775                     {
2776                         static int frames[] = { 1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0 };
2777                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset,
2778                             SHRINKER + frames[*weaponFrame], weaponShade, weaponBits, 0, 44040);
2779                     }
2780                 }
2781                 else
2782                 {
2783                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset,
2784                                             SHRINKER, weaponShade, weaponBits, weaponPal, 44040);
2785                 }
2786                 break;
2787             }
2788         }
2789         else
2790         {
2791             switch (DYNAMICWEAPONMAP(currentWeapon))
2792             {
2793             case KNEE_WEAPON__STATIC:
2794             {
2795                 int const kneePal = P_GetKneePal(pPlayer, weaponPal);
2796 
2797                 guniqhudid = currentWeapon;
2798                 if (*weaponFrame < 5 || *weaponFrame > 9)
2799                     G_DrawTileScaled(weaponX + 220 - halfLookAng, weaponY + 250 - weaponYOffset, KNEE,
2800                                         weaponShade, weaponBits, kneePal);
2801                 else
2802                     G_DrawTileScaled(weaponX + 160 - halfLookAng, weaponY + 214 - weaponYOffset, KNEE + 1,
2803                                         weaponShade, weaponBits, kneePal);
2804                 guniqhudid = 0;
2805                 break;
2806             }
2807 
2808             case TRIPBOMB_WEAPON__STATIC:
2809                 weaponX += 8;
2810                 weaponYOffset -= 10;
2811 
2812                 if ((*weaponFrame) > 6)
2813                     weaponY += ((*weaponFrame) << 3);
2814                 else if ((*weaponFrame) < 4)
2815                     G_DrawWeaponTileWithID(currentWeapon << 2, weaponX + 142 - halfLookAng,
2816                                             weaponY + 234 - weaponYOffset, HANDHOLDINGLASER + 3, weaponShade, weaponBits, weaponPal);
2817 
2818                 G_DrawWeaponTileWithID(currentWeapon, weaponX + 130 - halfLookAng, weaponY + 249 - weaponYOffset,
2819                                         HANDHOLDINGLASER + ((*weaponFrame) >> 2), weaponShade, weaponBits, weaponPal);
2820 
2821                 G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 152 - halfLookAng,
2822                                         weaponY + 249 - weaponYOffset, HANDHOLDINGLASER + ((*weaponFrame) >> 2), weaponShade, weaponBits | 4,
2823                                         weaponPal);
2824                 break;
2825 
2826             case RPG_WEAPON__STATIC:
2827                 weaponX -= sintable[(768 + ((*weaponFrame) << 7)) & 2047] >> 11;
2828                 weaponYOffset += sintable[(768 + ((*weaponFrame) << 7)) & 2047] >> 11;
2829 
2830                 if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING))
2831                     weaponBits |= 512;
2832 
2833                 if (*weaponFrame > 0)
2834                 {
2835                     int totalTime;
2836                     if (*weaponFrame < (WW2GI ? (totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime)) : 8))
2837                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 164, (weaponY << 1) + 176 - weaponYOffset,
2838                             RPGGUN + ((*weaponFrame) >> 1), weaponShade, weaponBits, weaponPal);
2839                     else if (WW2GI)
2840                     {
2841                         totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime);
2842                         int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload);
2843 
2844                         weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime))
2845                                           ? 10 * ((*weaponFrame) - totalTime)   // down
2846                                           : 10 * (reloadTime - (*weaponFrame)); // up
2847                     }
2848                 }
2849 
2850                 G_DrawWeaponTileWithID(currentWeapon, weaponX + 164, (weaponY << 1) + 176 - weaponYOffset, RPGGUN, weaponShade,
2851                                         weaponBits, weaponPal);
2852                 break;
2853 
2854             case SHOTGUN_WEAPON__STATIC:
2855                 weaponX -= 8;
2856 
2857                 if (WW2GI)
2858                 {
2859                     int const totalTime  = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime);
2860                     int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload);
2861 
2862                     if (*weaponFrame > 0)
2863                         weaponYOffset -= sintable[(*weaponFrame)<<7]>>12;
2864 
2865                     if (*weaponFrame > 0 && doAnim)
2866                         weaponX += 1-(rand()&3);
2867 
2868                     if (*weaponFrame == 0)
2869                     {
2870                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 146 - halfLookAng, weaponY + 202 - weaponYOffset,
2871                                                SHOTGUN, weaponShade, weaponBits, weaponPal);
2872                     }
2873                     else if (*weaponFrame <= totalTime)
2874                     {
2875                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 146 - halfLookAng, weaponY + 202 - weaponYOffset,
2876                                                SHOTGUN + 1, weaponShade, weaponBits, weaponPal);
2877                     }
2878                     // else we are in 'reload time'
2879                     else
2880                     {
2881                         weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime))
2882                                          ? 10 * ((*weaponFrame) - totalTime)    // D
2883                                          : 10 * (reloadTime - (*weaponFrame));  // U
2884 
2885                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 146 - halfLookAng, weaponY + 202 - weaponYOffset,
2886                                                SHOTGUN, weaponShade, weaponBits, weaponPal);
2887                     }
2888 
2889                     break;
2890                 }
2891 
2892                 switch (*weaponFrame)
2893                 {
2894                     case 1:
2895                     case 2:
2896                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 168 - halfLookAng, weaponY + 201 - weaponYOffset,
2897                                                 SHOTGUN + 2, -128, weaponBits, weaponPal);
2898                         fallthrough__;
2899                     case 0:
2900                     case 6:
2901                     case 7:
2902                     case 8:
2903                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 146 - halfLookAng, weaponY + 202 - weaponYOffset,
2904                                                 SHOTGUN, weaponShade, weaponBits, weaponPal);
2905                         break;
2906 
2907                     case 3:
2908                     case 4:
2909                         weaponYOffset -= 40;
2910                         weaponX += 20;
2911 
2912                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 178 - halfLookAng, weaponY + 194 - weaponYOffset,
2913                                                 SHOTGUN + 1 + ((*(weaponFrame)-1) >> 1), -128, weaponBits, weaponPal);
2914                         fallthrough__;
2915                     case 5:
2916                     case 9:
2917                     case 10:
2918                     case 11:
2919                     case 12:
2920                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 158 - halfLookAng, weaponY + 220 - weaponYOffset,
2921                                                 SHOTGUN + 3, weaponShade, weaponBits, weaponPal);
2922                         break;
2923 
2924                     case 13:
2925                     case 14:
2926                     case 15:
2927                         G_DrawWeaponTileWithID(currentWeapon, 32 + weaponX + 166 - halfLookAng, weaponY + 210 - weaponYOffset,
2928                                                 SHOTGUN + 4, weaponShade, weaponBits, weaponPal);
2929                         break;
2930 
2931                     case 16:
2932                     case 17:
2933                     case 18:
2934                     case 19:
2935                     case 24:
2936                     case 25:
2937                     case 26:
2938                     case 27:
2939                         G_DrawWeaponTileWithID(currentWeapon, 64 + weaponX + 170 - halfLookAng, weaponY + 196 - weaponYOffset,
2940                                                 SHOTGUN + 5, weaponShade, weaponBits, weaponPal);
2941                         break;
2942 
2943                     case 20:
2944                     case 21:
2945                     case 22:
2946                     case 23:
2947                         G_DrawWeaponTileWithID(currentWeapon, 64 + weaponX + 176 - halfLookAng, weaponY + 196 - weaponYOffset,
2948                                                 SHOTGUN + 6, weaponShade, weaponBits, weaponPal);
2949                         break;
2950 
2951 
2952                     case 28:
2953                     case 29:
2954                     case 30:
2955                         G_DrawWeaponTileWithID(currentWeapon, 32 + weaponX + 156 - halfLookAng, weaponY + 206 - weaponYOffset,
2956                                                 SHOTGUN + 4, weaponShade, weaponBits, weaponPal);
2957                         break;
2958                 }
2959                 break;
2960 
2961             case CHAINGUN_WEAPON__STATIC:
2962                 if (*weaponFrame > 0)
2963                 {
2964                     weaponYOffset -= sintable[(*weaponFrame)<<7]>>12;
2965 
2966                     if (doAnim)
2967                         weaponX += 1-(rand()&3);
2968                 }
2969 
2970                 if (WW2GI)
2971                 {
2972                     int const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime);
2973                     int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload);
2974 
2975                     if (*weaponFrame == 0)
2976                     {
2977                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - halfLookAng,weaponY+233-weaponYOffset,
2978                             CHAINGUN+1,weaponShade,weaponBits,weaponPal);
2979                     }
2980                     else if (*weaponFrame <= totalTime)
2981                     {
2982                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng,weaponY+243-weaponYOffset,
2983                             CHAINGUN+2,weaponShade,weaponBits,weaponPal);
2984                     }
2985                     // else we are in 'reload time'
2986                     // divide reload time into fifths..
2987                     // 1) move weapon up/right, hand on clip (CHAINGUN - 17)
2988                     // 2) move weapon up/right, hand removing clip (CHAINGUN - 18)
2989                     // 3) hold weapon up/right, hand removed clip (CHAINGUN - 19)
2990                     // 4) hold weapon up/right, hand inserting clip (CHAINGUN - 18)
2991                     // 5) move weapon down/left, clip inserted (CHAINGUN - 17)
2992                     else
2993                     {
2994                         int iFifths = (reloadTime - totalTime) / 5;
2995                         if (iFifths < 1)
2996                             iFifths = 1;
2997 
2998                         if (*weaponFrame < iFifths + totalTime)
2999                         {
3000                             // first segment
3001                             int const weaponOffset = 80 - 10 * (totalTime + iFifths - (*weaponFrame));
3002                             weaponYOffset += weaponOffset;
3003                             weaponX += weaponOffset;
3004                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 17,
3005                                                    weaponShade, weaponBits, weaponPal);
3006                         }
3007                         else if (*weaponFrame < (iFifths * 2 + totalTime))
3008                         {
3009                             // second segment
3010                             weaponYOffset += 80; // D
3011                             weaponX += 80;
3012                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 18,
3013                                                    weaponShade, weaponBits, weaponPal);
3014                         }
3015                         else if (*weaponFrame < (iFifths * 3 + totalTime))
3016                         {
3017                             // third segment
3018                             // up
3019                             weaponYOffset += 80;
3020                             weaponX += 80;
3021                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 19,
3022                                                    weaponShade, weaponBits, weaponPal);
3023                         }
3024                         else if (*weaponFrame < (iFifths * 4 + totalTime))
3025                         {
3026                             // fourth segment
3027                             // down
3028                             weaponYOffset += 80; // D
3029                             weaponX += 80;
3030                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 18,
3031                                                    weaponShade, weaponBits, weaponPal);
3032                         }
3033                         else
3034                         {
3035                             // up and left
3036                             int const weaponOffset = 10 * (reloadTime - (*weaponFrame));
3037                             weaponYOffset += weaponOffset; // U
3038                             weaponX += weaponOffset;
3039                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 168 - halfLookAng, weaponY + 260 - weaponYOffset, CHAINGUN - 17,
3040                                                    weaponShade, weaponBits, weaponPal);
3041                         }
3042                     }
3043 
3044                     break;
3045                 }
3046 
3047                 switch (*weaponFrame)
3048                 {
3049                 case 0:
3050                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - (pPlayer->look_ang >> 1), weaponY + 233 - weaponYOffset,
3051                                             CHAINGUN + 1, weaponShade, weaponBits, weaponPal);
3052                     break;
3053 
3054                 default:
3055                     if (*weaponFrame > 4 && *weaponFrame < 12)
3056                     {
3057                         int randomOffset = doAnim ? rand()&7 : 0;
3058                         G_DrawWeaponTileWithID(currentWeapon << 2, randomOffset + weaponX - 4 + 140 - (pPlayer->look_ang >> 1),
3059                                                 randomOffset + weaponY - ((*weaponFrame) >> 1) + 208 - weaponYOffset,
3060                                                 CHAINGUN + 5 + ((*weaponFrame - 4) / 5), weaponShade, weaponBits, weaponPal);
3061                         if (doAnim) randomOffset = rand()&7;
3062                         G_DrawWeaponTileWithID(currentWeapon << 2, randomOffset + weaponX - 4 + 184 - (pPlayer->look_ang >> 1),
3063                                                 randomOffset + weaponY - ((*weaponFrame) >> 1) + 208 - weaponYOffset,
3064                                                 CHAINGUN + 5 + ((*weaponFrame - 4) / 5), weaponShade, weaponBits, weaponPal);
3065                     }
3066 
3067                     if (*weaponFrame < 8)
3068                     {
3069                         int const randomOffset = doAnim ? rand()&7 : 0;
3070                         G_DrawWeaponTileWithID(currentWeapon << 2, randomOffset + weaponX - 4 + 162 - (pPlayer->look_ang >> 1),
3071                             randomOffset + weaponY - ((*weaponFrame) >> 1) + 208 - weaponYOffset,
3072                                                 CHAINGUN + 5 + ((*weaponFrame - 2) / 5), weaponShade, weaponBits, weaponPal);
3073                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - (pPlayer->look_ang >> 1), weaponY + 233 - weaponYOffset,
3074                                                 CHAINGUN + 1 + ((*weaponFrame) >> 1), weaponShade, weaponBits, weaponPal);
3075                     }
3076                     else
3077                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 178 - (pPlayer->look_ang >> 1), weaponY + 233 - weaponYOffset,
3078                                                 CHAINGUN + 1, weaponShade, weaponBits, weaponPal);
3079 
3080                     break;
3081                 }
3082 
3083                 G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 168 - (pPlayer->look_ang >> 1), weaponY + 260 - weaponYOffset,
3084                                         CHAINGUN, weaponShade, weaponBits, weaponPal);
3085                 break;
3086 
3087             case PISTOL_WEAPON__STATIC:
3088                 if ((*weaponFrame) < 5)
3089                 {
3090                     static uint8_t pistolFrames[] = { 0, 1, 2 };
3091                     int pistolOffset = 195-12+weaponX;
3092 
3093                     if ((*weaponFrame) == 2)
3094                         pistolOffset -= 3;
3095 
3096                     G_DrawWeaponTileWithID(currentWeapon, (pistolOffset - (pPlayer->look_ang >> 1)), (weaponY + 244 - weaponYOffset),
3097                                             FIRSTGUN + pistolFrames[*weaponFrame > 2 ? 0 : *weaponFrame], weaponShade, 2,
3098                                             weaponPal);
3099 
3100                     break;
3101                 }
3102 
3103                 if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING) && DUKE)
3104                     weaponBits |= 512;
3105 
3106                 if ((*weaponFrame) < 10)
3107                     G_DrawWeaponTileWithID(currentWeapon, 194 - (pPlayer->look_ang >> 1), weaponY + 230 - weaponYOffset, FIRSTGUN + 4,
3108                                             weaponShade, weaponBits, weaponPal);
3109                 else if ((*weaponFrame) < 15)
3110                 {
3111                     G_DrawWeaponTileWithID(currentWeapon << 1, 244 - ((*weaponFrame) << 3) - (pPlayer->look_ang >> 1),
3112                                             weaponY + 130 - weaponYOffset + ((*weaponFrame) << 4), FIRSTGUN + 6, weaponShade,
3113                                             weaponBits, weaponPal);
3114                     G_DrawWeaponTileWithID(currentWeapon, 224 - (pPlayer->look_ang >> 1), weaponY + 220 - weaponYOffset, FIRSTGUN + 5,
3115                                             weaponShade, weaponBits, weaponPal);
3116                 }
3117                 else if ((*weaponFrame) < 20)
3118                 {
3119                     G_DrawWeaponTileWithID(currentWeapon << 1, 124 + ((*weaponFrame) << 1) - (pPlayer->look_ang >> 1),
3120                                             weaponY + 430 - weaponYOffset - ((*weaponFrame) << 3), FIRSTGUN + 6, weaponShade,
3121                                             weaponBits, weaponPal);
3122                     G_DrawWeaponTileWithID(currentWeapon, 224 - (pPlayer->look_ang >> 1), weaponY + 220 - weaponYOffset, FIRSTGUN + 5,
3123                                             weaponShade, weaponBits, weaponPal);
3124                 }
3125 
3126                 else if ((*weaponFrame) < (WW2GI ? PWEAPON(screenpeek, PISTOL_WEAPON, Reload) - 12 : (NAM ? 38 : 23)))
3127                 {
3128                     G_DrawWeaponTileWithID(currentWeapon << 2, 184 - (pPlayer->look_ang >> 1), weaponY + 235 - weaponYOffset,
3129                                             FIRSTGUN + 8, weaponShade, weaponBits, weaponPal);
3130                     G_DrawWeaponTileWithID(currentWeapon, 224 - (pPlayer->look_ang >> 1), weaponY + 210 - weaponYOffset, FIRSTGUN + 5,
3131                                             weaponShade, weaponBits, weaponPal);
3132                 }
3133                 else if ((*weaponFrame) < (WW2GI ? PWEAPON(screenpeek, PISTOL_WEAPON, Reload) - 6 : (NAM ? 44 : 25)))
3134                 {
3135                     G_DrawWeaponTileWithID(currentWeapon << 2, 164 - (pPlayer->look_ang >> 1), weaponY + 245 - weaponYOffset,
3136                                             FIRSTGUN + 8, weaponShade, weaponBits, weaponPal);
3137                     G_DrawWeaponTileWithID(currentWeapon, 224 - (pPlayer->look_ang >> 1), weaponY + 220 - weaponYOffset, FIRSTGUN + 5,
3138                                             weaponShade, weaponBits, weaponPal);
3139                 }
3140                 else if ((*weaponFrame) < (WW2GI ? PWEAPON(screenpeek, PISTOL_WEAPON, Reload) : (NAM ? 50 : 27)))
3141                     G_DrawWeaponTileWithID(currentWeapon, 194 - (pPlayer->look_ang >> 1), weaponY + 235 - weaponYOffset, FIRSTGUN + 5,
3142                                             weaponShade, weaponBits, weaponPal);
3143 
3144                 break;
3145 
3146             case HANDBOMB_WEAPON__STATIC:
3147                 {
3148                     static uint8_t pipebombFrames [] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
3149 
3150                     if (*weaponFrame >= ARRAY_SIZE(pipebombFrames))
3151                         break;
3152 
3153                     if (WW2GI && *weaponFrame >= PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime))
3154                         break;
3155 
3156                     if (*weaponFrame)
3157                     {
3158                         if (WW2GI)
3159                         {
3160                             int const fireDelay = PWEAPON(screenpeek, pPlayer->curr_weapon, FireDelay);
3161                             int const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime);
3162 
3163                             if (*weaponFrame <= fireDelay)
3164                             {
3165                                 // it holds here
3166                                 weaponYOffset -= 5 * (*weaponFrame);  // D
3167                             }
3168                             else if (*weaponFrame < ((totalTime - fireDelay) / 2 + fireDelay))
3169                             {
3170                                 // up and left
3171                                 int const weaponOffset = (*weaponFrame) - fireDelay;
3172                                 weaponYOffset += 10 * weaponOffset;  // U
3173                                 weaponX += 80 * weaponOffset;
3174                             }
3175                             else if (*weaponFrame < totalTime)
3176                             {
3177                                 // start high
3178                                 weaponYOffset += 240;
3179                                 weaponYOffset -= 12 * ((*weaponFrame) - fireDelay);  // D
3180                                 // move left
3181                                 weaponX += 90 - 5 * (totalTime - (*weaponFrame));
3182                             }
3183                         }
3184                         else
3185                         {
3186                             if (*weaponFrame < 7)       weaponYOffset -= 10 * (*weaponFrame);  // D
3187                             else if (*weaponFrame < 12) weaponYOffset += 20 * ((*weaponFrame) - 10);  // U
3188                             else if (*weaponFrame < 20) weaponYOffset -= 9  * ((*weaponFrame) - 14);  // D
3189 
3190                             weaponYOffset += 10;
3191                         }
3192                     }
3193 
3194                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 190 - halfLookAng, weaponY + 260 - weaponYOffset,
3195                                             HANDTHROW + pipebombFrames[(*weaponFrame)], weaponShade, weaponBits, weaponPal);
3196                 }
3197                 break;
3198 
3199             case HANDREMOTE_WEAPON__STATIC:
3200                 {
3201                     static uint8_t remoteFrames[] = { 0, 1, 1, 2, 1, 1, 0, 0, 0, 0, 0 };
3202 
3203                     if (*weaponFrame >= ARRAY_SIZE(remoteFrames))
3204                         break;
3205 
3206                     weaponX = -48;
3207                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 150 - halfLookAng, weaponY + 258 - weaponYOffset,
3208                                             HANDREMOTE + remoteFrames[(*weaponFrame)], weaponShade, weaponBits, weaponPal);
3209                 }
3210                 break;
3211 
3212             case DEVISTATOR_WEAPON__STATIC:
3213                 if (WW2GI)
3214                 {
3215                     if (*weaponFrame)
3216                     {
3217                         int32_t const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime);
3218                         int32_t const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload);
3219 
3220                         if (*weaponFrame < totalTime)
3221                         {
3222                             int const tileOffset = ksgn((*weaponFrame) >> 2);
3223 
3224                             if (pPlayer->ammo_amount[pPlayer->curr_weapon] & 1)
3225                             {
3226                                 G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset,
3227                                                        DEVISTATOR, weaponShade, weaponBits | 4, weaponPal);
3228                                 G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset,
3229                                                        DEVISTATOR + tileOffset, -32, weaponBits, weaponPal);
3230                             }
3231                             else
3232                             {
3233                                 G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset,
3234                                                        DEVISTATOR + tileOffset, -32, weaponBits | 4, weaponPal);
3235                                 G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR,
3236                                                        weaponShade, weaponBits, weaponPal);
3237                             }
3238                         }
3239                         // else we are in 'reload time'
3240                         else
3241                         {
3242                             weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime))
3243                                              ? 10 * ((*weaponFrame) - totalTime)
3244                                              : 10 * (reloadTime - (*weaponFrame));
3245 
3246                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR,
3247                                                    weaponShade, weaponBits, weaponPal);
3248                             G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, DEVISTATOR,
3249                                                    weaponShade, weaponBits | 4, weaponPal);
3250                         }
3251                     }
3252                     else
3253                     {
3254                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR,
3255                                                weaponShade, weaponBits, weaponPal);
3256                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, DEVISTATOR,
3257                                                weaponShade, weaponBits | 4, weaponPal);
3258                     }
3259                     break;
3260                 }
3261 
3262                 if (*weaponFrame > 0)
3263                 {
3264                     static uint8_t const devastatorFrames[] = { 0, 4, 12, 24, 12, 4, 0 };
3265 
3266                     if (*weaponFrame >= ARRAY_SIZE(devastatorFrames))
3267                         break;
3268 
3269                     int const tileOffset = ksgn((*weaponFrame) >> 2);
3270 
3271                     if (pPlayer->hbomb_hold_delay)
3272                     {
3273                         G_DrawWeaponTileWithID(currentWeapon, (devastatorFrames[*weaponFrame] >> 1) + weaponX + 268 - halfLookAng,
3274                                                 devastatorFrames[*weaponFrame] + weaponY + 238 - weaponYOffset,
3275                                                 DEVISTATOR + tileOffset, -32, weaponBits, weaponPal);
3276                         G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, DEVISTATOR,
3277                                                 weaponShade, weaponBits | 4, weaponPal);
3278                     }
3279                     else
3280                     {
3281                         G_DrawWeaponTileWithID(currentWeapon << 1, -(devastatorFrames[*weaponFrame] >> 1) + weaponX + 30 - halfLookAng,
3282                                                 devastatorFrames[*weaponFrame] + weaponY + 240 - weaponYOffset,
3283                                                 DEVISTATOR + tileOffset, -32, weaponBits | 4, weaponPal);
3284                         G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR,
3285                                                 weaponShade, weaponBits, weaponPal);
3286                     }
3287                 }
3288                 else
3289                 {
3290                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 268 - halfLookAng, weaponY + 238 - weaponYOffset, DEVISTATOR, weaponShade,
3291                                             weaponBits, weaponPal);
3292                     G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 30 - halfLookAng, weaponY + 240 - weaponYOffset, DEVISTATOR,
3293                                             weaponShade, weaponBits | 4, weaponPal);
3294                 }
3295                 break;
3296 
3297             case FREEZE_WEAPON__STATIC:
3298                 if (!(duke3d_globalflags & DUKE3D_NO_WIDESCREEN_PINNING) && DUKE)
3299                     weaponBits |= 512;
3300 
3301                 if ((*weaponFrame) > 0)
3302                 {
3303                     static uint8_t freezerFrames[] = { 0, 0, 1, 1, 2, 2 };
3304 
3305                     if (*weaponFrame % 6 >= ARRAY_SIZE(freezerFrames))
3306                         break;
3307 
3308                     if (doAnim)
3309                     {
3310                         weaponX += rand() & 3;
3311                         weaponY += rand() & 3;
3312                     }
3313                     weaponYOffset -= 16;
3314                     G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 210 - (pPlayer->look_ang >> 1), weaponY + 261 - weaponYOffset,
3315                                             FREEZE + 2, -32, weaponBits, weaponPal);
3316                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - (pPlayer->look_ang >> 1), weaponY + 235 - weaponYOffset,
3317                                             FREEZE + 3 + freezerFrames[*weaponFrame % 6], -32, weaponBits, weaponPal);
3318                 }
3319                 else
3320                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - (pPlayer->look_ang >> 1), weaponY + 261 - weaponYOffset,
3321                                             FREEZE, weaponShade, weaponBits, weaponPal);
3322                 break;
3323 
3324             case GROW_WEAPON__STATIC:
3325             case SHRINKER_WEAPON__STATIC:
3326                 weaponX += 28;
3327                 weaponY += 18;
3328 
3329                 if (WW2GI)
3330                 {
3331                     if (*weaponFrame == 0)
3332                     {
3333                         // the 'at rest' display
3334                         if (currentWeapon == GROW_WEAPON)
3335                         {
3336                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset, SHRINKER - 2,
3337                                                    weaponShade, weaponBits, weaponPal);
3338                             break;
3339                         }
3340                         else if (pPlayer->ammo_amount[currentWeapon] > 0)
3341                         {
3342                             G_DrawWeaponTileUnfadedWithID(currentWeapon << 1, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset, SHRINKER + 2,
3343                                                           16 - (sintable[pPlayer->random_club_frame & 2047] >> 10), weaponBits, 0);
3344                             G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset, SHRINKER,
3345                                                    weaponShade, weaponBits, weaponPal);
3346                             break;
3347                         }
3348                     }
3349                     else
3350                     {
3351                         // the 'active' display.
3352                         if (doAnim)
3353                         {
3354                             weaponX += rand() & 3;
3355                             weaponYOffset += rand() & 3;
3356                         }
3357 
3358                         int const totalTime = PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime);
3359                         int const reloadTime = PWEAPON(screenpeek, pPlayer->curr_weapon, Reload);
3360 
3361                         if (*weaponFrame < totalTime)
3362                         {
3363                             if (*weaponFrame >= PWEAPON(screenpeek, pPlayer->curr_weapon, FireDelay))
3364                             {
3365                                 // after fire time.
3366                                 // lower weapon to reload cartridge (not clip)
3367                                 weaponYOffset -= (currentWeapon == GROW_WEAPON ? 15 : 10) * (totalTime - (*weaponFrame));
3368                             }
3369                         }
3370                         // else we are in 'reload time'
3371                         else
3372                         {
3373                             weaponYOffset -= (*weaponFrame < ((reloadTime - totalTime) / 2 + totalTime))
3374                                              ? (currentWeapon == GROW_WEAPON ? 5 : 10) * ((*weaponFrame) - totalTime) // D
3375                                              : 10 * (reloadTime - (*weaponFrame)); // U
3376                         }
3377                     }
3378 
3379                     G_DrawWeaponTileUnfadedWithID(currentWeapon << 1, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset,
3380                                                   SHRINKER + 3 + ((*weaponFrame) & 3), -32, weaponBits, currentWeapon == GROW_WEAPON ? 2 : 0);
3381 
3382                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset,
3383                                            SHRINKER + (currentWeapon == GROW_WEAPON ? -1 : 1), weaponShade, weaponBits, weaponPal);
3384 
3385                     break;
3386                 }
3387 
3388                 if ((*weaponFrame) > 0)
3389                 {
3390                     if (doAnim)
3391                     {
3392                         weaponX += rand() & 3;
3393                         weaponYOffset += (rand() & 3);
3394                     }
3395 
3396                     G_DrawWeaponTileUnfadedWithID(currentWeapon << 1, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset,
3397                                                     SHRINKER + 3 + ((*weaponFrame) & 3), -32, weaponBits, currentWeapon == GROW_WEAPON ? 2 : 0);
3398                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset,
3399                                             currentWeapon == GROW_WEAPON ? SHRINKER - 1 : SHRINKER + 1, weaponShade, weaponBits, weaponPal);
3400                 }
3401                 else
3402                 {
3403                     G_DrawWeaponTileUnfadedWithID(currentWeapon << 1, weaponX + 184 - halfLookAng, weaponY + 240 - weaponYOffset,
3404                                                     SHRINKER + 2, 16 - (sintable[pPlayer->random_club_frame & 2047] >> 10), weaponBits,
3405                                                     currentWeapon == GROW_WEAPON ? 2 : 0);
3406                     G_DrawWeaponTileWithID(currentWeapon, weaponX + 188 - halfLookAng, weaponY + 240 - weaponYOffset,
3407                                             currentWeapon == GROW_WEAPON ? SHRINKER - 2 : SHRINKER, weaponShade, weaponBits, weaponPal);
3408                 }
3409                 break;
3410             }
3411         }
3412     }
3413 
3414 enddisplayweapon:
3415     if (!RR)
3416         P_DisplaySpit();
3417 }
3418 
3419 #define TURBOTURNTIME (TICRATE/8) // 7
3420 #define NORMALTURN   15
3421 #define PREAMBLETURN 5
3422 #define NORMALKEYMOVE 40
3423 #define MAXVEL       ((NORMALKEYMOVE*2)+10)
3424 #define MAXSVEL      ((NORMALKEYMOVE*2)+10)
3425 #define MAXANGVEL    1024
3426 #define MAXHORIZ     256
3427 
3428 int32_t g_myAimMode = 0, g_myAimStat = 0, g_oldAimStat = 0;
3429 int32_t mouseyaxismode = -1;
3430 
P_GetInput(int playerNum)3431 void P_GetInput(int playerNum)
3432 {
3433     auto const pPlayer = g_player[playerNum].ps;
3434     ControlInfo info;
3435 
3436     if ((pPlayer->gm & (MODE_MENU|MODE_TYPE)) || (ud.pause_on && !KB_KeyPressed(sc_Pause)))
3437     {
3438         if (!(pPlayer->gm&MODE_MENU))
3439             CONTROL_GetInput(&info);
3440 
3441         Bmemset(&localInput, 0, sizeof(input_t));
3442 
3443         localInput.bits    = (((int32_t)g_gameQuit) << SK_GAMEQUIT);
3444         localInput.extbits |= (1 << 7);
3445 
3446         return;
3447     }
3448 
3449     CONTROL_ProcessBinds();
3450 
3451     if (ud.mouseaiming)
3452         g_myAimMode = BUTTON(gamefunc_Mouse_Aiming);
3453     else
3454     {
3455         g_oldAimStat = g_myAimStat;
3456         g_myAimStat  = BUTTON(gamefunc_Mouse_Aiming);
3457 
3458         if (g_myAimStat > g_oldAimStat)
3459         {
3460             g_myAimMode ^= 1;
3461             P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_myAimMode, pPlayer);
3462         }
3463     }
3464 
3465     CONTROL_GetInput(&info);
3466 
3467     if (ud.config.MouseDeadZone)
3468     {
3469         if (info.mousey > 0)
3470             info.mousey = max(info.mousey - ud.config.MouseDeadZone, 0);
3471         else if (info.mousey < 0)
3472             info.mousey = min(info.mousey + ud.config.MouseDeadZone, 0);
3473 
3474         if (info.mousex > 0)
3475             info.mousex = max(info.mousex - ud.config.MouseDeadZone, 0);
3476         else if (info.mousex < 0)
3477             info.mousex = min(info.mousex + ud.config.MouseDeadZone, 0);
3478     }
3479 
3480     if (ud.config.MouseBias)
3481     {
3482         if (klabs(info.mousex) > klabs(info.mousey))
3483             info.mousey = tabledivide32_noinline(info.mousey, ud.config.MouseBias);
3484         else
3485             info.mousex = tabledivide32_noinline(info.mousex, ud.config.MouseBias);
3486     }
3487 
3488     // JBF: Run key behaviour is selectable
3489     int const playerRunning = (ud.runkey_mode) ? (BUTTON(gamefunc_Run) | ud.auto_run) : (ud.auto_run ^ BUTTON(gamefunc_Run));
3490     int const turnAmount = playerRunning ? (NORMALTURN << 1) : NORMALTURN;
3491     constexpr int const analogTurnAmount = (NORMALTURN << 1);
3492     int const keyMove    = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE;
3493     constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp
3494 
3495     input_t input {};
3496 
3497     if (BUTTON(gamefunc_Strafe))
3498     {
3499         static int strafeyaw;
3500 
3501         input.svel = -(info.mousex + strafeyaw) >> 3;
3502         strafeyaw  = (info.mousex + strafeyaw) % 8;
3503 
3504         input.svel -= info.dyaw * keyMove / analogExtent;
3505     }
3506     else
3507     {
3508         input.q16avel = fix16_div(fix16_from_int(info.mousex), F16(32));
3509         input.q16avel += fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1));
3510     }
3511 
3512     if (g_myAimMode)
3513         input.q16horz = fix16_div(fix16_from_int(info.mousey), F16(64));
3514     else
3515         input.fvel = -(info.mousey >> 6);
3516 
3517     if (ud.mouseflip) input.q16horz = -input.q16horz;
3518 
3519     input.q16horz -= fix16_from_int(info.dpitch) / analogExtent * analogTurnAmount;
3520     input.svel -= info.dx * keyMove / analogExtent;
3521     input.fvel -= info.dz * keyMove / analogExtent;
3522 
3523     if (BUTTON(gamefunc_Strafe))
3524     {
3525         if (BUTTON(gamefunc_Turn_Left) && !(pPlayer->movement_lock&4))
3526             input.svel -= -keyMove;
3527 
3528         if (BUTTON(gamefunc_Turn_Right) && !(pPlayer->movement_lock&8))
3529             input.svel -= keyMove;
3530     }
3531     else
3532     {
3533         static int32_t turnHeldTime   = 0;
3534         static int32_t lastInputClock = 0;  // MED
3535         int32_t const  elapsedTics    = (int32_t) totalclock - lastInputClock;
3536 
3537         lastInputClock = (int32_t) totalclock;
3538 
3539         if (BUTTON(gamefunc_Turn_Left))
3540         {
3541             turnHeldTime += elapsedTics;
3542             input.q16avel -= fix16_from_int((turnHeldTime >= TURBOTURNTIME) ? (turnAmount << 1) : (PREAMBLETURN << 1));
3543         }
3544         else if (BUTTON(gamefunc_Turn_Right))
3545         {
3546             turnHeldTime += elapsedTics;
3547             input.q16avel += fix16_from_int((turnHeldTime >= TURBOTURNTIME) ? (turnAmount << 1) : (PREAMBLETURN << 1));
3548         }
3549         else
3550             turnHeldTime=0;
3551     }
3552 
3553     if (BUTTON(gamefunc_Strafe_Left) && !(pPlayer->movement_lock & 4))
3554         input.svel += keyMove;
3555 
3556     if (BUTTON(gamefunc_Strafe_Right) && !(pPlayer->movement_lock & 8))
3557         input.svel += -keyMove;
3558 
3559     if (RR)
3560     {
3561         /*if (BUTTON(gamefunc_Quick_Kick))
3562         {
3563             localInput.bits |= BUTTON(gamefunc_Move_Forward)<<SK_AIM_UP;
3564             localInput.bits |= BUTTON(gamefunc_Move_Backward)<<SK_AIM_DOWN;
3565         }
3566         else*/
3567         {
3568             if (pPlayer->drink_amt >= 66 && pPlayer->drink_amt <= 87)
3569             {
3570                 if (BUTTON(gamefunc_Move_Forward))
3571                 {
3572                     input.fvel += keyMove;
3573                     if (pPlayer->drink_amt & 1)
3574                         input.svel += keyMove;
3575                     else
3576                         input.svel -= keyMove;
3577                 }
3578 
3579                 if (BUTTON(gamefunc_Move_Backward))
3580                 {
3581                     input.fvel += -keyMove;
3582                     if (pPlayer->drink_amt & 1)
3583                         input.svel -= keyMove;
3584                     else
3585                         input.svel += keyMove;
3586                 }
3587             }
3588             else
3589             {
3590                 if (BUTTON(gamefunc_Move_Forward))
3591                     input.fvel += keyMove;
3592 
3593                 if (BUTTON(gamefunc_Move_Backward))
3594                     input.fvel += -keyMove;
3595             }
3596         }
3597     }
3598     else
3599     {
3600         if (BUTTON(gamefunc_Move_Forward) && !(g_player[playerNum].ps->movement_lock & 1))
3601             input.fvel += keyMove;
3602 
3603         if (BUTTON(gamefunc_Move_Backward) && !(g_player[playerNum].ps->movement_lock & 2))
3604             input.fvel += -keyMove;
3605     }
3606 
3607     input.fvel = clamp(input.fvel, -MAXVEL, MAXVEL);
3608     input.svel = clamp(input.svel, -MAXSVEL, MAXSVEL);
3609 
3610     input.q16avel = fix16_clamp(input.q16avel, F16(-MAXANGVEL), F16(MAXANGVEL));
3611     input.q16horz = fix16_clamp(input.q16horz, F16(-MAXHORIZ), F16(MAXHORIZ));
3612 
3613     int weaponSelection;
3614 
3615     for (weaponSelection = gamefunc_Weapon_10; weaponSelection >= gamefunc_Weapon_1; --weaponSelection)
3616     {
3617         if (BUTTON(weaponSelection))
3618         {
3619             weaponSelection -= (gamefunc_Weapon_1 - 1);
3620             break;
3621         }
3622     }
3623 
3624     if (BUTTON(gamefunc_Last_Weapon))
3625         weaponSelection = 14;
3626     else if (BUTTON(gamefunc_Alt_Weapon))
3627         weaponSelection = 13;
3628     else if (BUTTON(gamefunc_Next_Weapon) || (BUTTON(gamefunc_Dpad_Select) && input.fvel > 0))
3629         weaponSelection = 12;
3630     else if (BUTTON(gamefunc_Previous_Weapon) || (BUTTON(gamefunc_Dpad_Select) && input.fvel < 0))
3631         weaponSelection = 11;
3632     else if (weaponSelection == gamefunc_Weapon_1-1)
3633         weaponSelection = 0;
3634 
3635     localInput.bits = (weaponSelection << SK_WEAPON_BITS) | (BUTTON(gamefunc_Fire) << SK_FIRE);
3636     localInput.bits |= (BUTTON(gamefunc_Open) << SK_OPEN);
3637 
3638     int const sectorLotag = pPlayer->cursectnum != -1 ? sector[pPlayer->cursectnum].lotag : 0;
3639     int const crouchable = sectorLotag != 2 && (sectorLotag != 1 || pPlayer->spritebridge);
3640 
3641     if (BUTTON(gamefunc_Toggle_Crouch))
3642     {
3643         pPlayer->crouch_toggle = !pPlayer->crouch_toggle && crouchable;
3644 
3645         if (crouchable)
3646             CONTROL_ClearButton(gamefunc_Toggle_Crouch);
3647     }
3648 
3649     if (BUTTON(gamefunc_Crouch) || BUTTON(gamefunc_Jump) || pPlayer->jetpack_on || (!crouchable && pPlayer->on_ground))
3650         pPlayer->crouch_toggle = 0;
3651 
3652     int const crouching = BUTTON(gamefunc_Crouch) || BUTTON(gamefunc_Toggle_Crouch) || pPlayer->crouch_toggle;
3653 
3654     localInput.bits |= (BUTTON(gamefunc_Jump) << SK_JUMP) | (crouching << SK_CROUCH);
3655 
3656     localInput.bits |= (BUTTON(gamefunc_Aim_Up) || (BUTTON(gamefunc_Dpad_Aiming) && input.fvel > 0)) << SK_AIM_UP;
3657     localInput.bits |= (BUTTON(gamefunc_Aim_Down) || (BUTTON(gamefunc_Dpad_Aiming) && input.fvel < 0)) << SK_AIM_DOWN;
3658     localInput.bits |= (BUTTON(gamefunc_Center_View) << SK_CENTER_VIEW);
3659 
3660     localInput.bits |= (BUTTON(gamefunc_Look_Left) << SK_LOOK_LEFT) | (BUTTON(gamefunc_Look_Right) << SK_LOOK_RIGHT);
3661     localInput.bits |= (BUTTON(gamefunc_Look_Up) << SK_LOOK_UP) | (BUTTON(gamefunc_Look_Down) << SK_LOOK_DOWN);
3662 
3663     localInput.bits |= (playerRunning << SK_RUN);
3664 
3665     localInput.bits |= (BUTTON(gamefunc_Inventory_Left) || (BUTTON(gamefunc_Dpad_Select) && (input.svel > 0 || input.q16avel < 0))) << SK_INV_LEFT;
3666     localInput.bits |= (BUTTON(gamefunc_Inventory_Right) || (BUTTON(gamefunc_Dpad_Select) && (input.svel < 0 || input.q16avel > 0))) << SK_INV_RIGHT;
3667     localInput.bits |= (BUTTON(gamefunc_Inventory) << SK_INVENTORY);
3668 
3669     localInput.bits |= (BUTTON(gamefunc_Steroids) << SK_STEROIDS) | (BUTTON(gamefunc_NightVision) << SK_NIGHTVISION);
3670     localInput.bits |= (BUTTON(gamefunc_MedKit) << SK_MEDKIT) | (BUTTON(gamefunc_Holo_Duke) << SK_HOLODUKE);
3671     localInput.bits |= (BUTTON(gamefunc_Jetpack) << SK_JETPACK);
3672 
3673     localInput.bits |= BUTTON(gamefunc_Holster_Weapon) << SK_HOLSTER;
3674     localInput.bits |= BUTTON(gamefunc_Quick_Kick) << SK_QUICK_KICK;
3675     localInput.bits |= BUTTON(gamefunc_TurnAround) << SK_TURNAROUND;
3676 
3677     localInput.bits |= (g_myAimMode << SK_AIMMODE);
3678     localInput.bits |= (g_gameQuit << SK_GAMEQUIT);
3679     localInput.bits |= KB_KeyPressed(sc_Pause) << SK_PAUSE;
3680     localInput.bits |= ((uint32_t)KB_KeyPressed(sc_Escape)) << SK_ESCAPE;
3681 
3682     if (RR)
3683     {
3684         if (TEST_SYNC_KEY(localInput.bits, SK_CROUCH))
3685             localInput.bits &= ~(1 << SK_JUMP);
3686         if (pPlayer->drink_amt > 88)
3687             localInput.bits |= 1 << SK_LOOK_LEFT;
3688         if (pPlayer->drink_amt > 99)
3689             localInput.bits |= 1 << SK_LOOK_DOWN;
3690     }
3691 
3692     if (BUTTON(gamefunc_Dpad_Select))
3693     {
3694         input.fvel = 0;
3695         input.svel = 0;
3696         input.q16avel = 0;
3697     }
3698     else if (BUTTON(gamefunc_Dpad_Aiming))
3699         input.fvel = 0;
3700 
3701     localInput.extbits = (BUTTON(gamefunc_Move_Forward) || (input.fvel > 0));
3702     localInput.extbits |= (BUTTON(gamefunc_Move_Backward) || (input.fvel < 0)) << 1;
3703     localInput.extbits |= (BUTTON(gamefunc_Strafe_Left) || (input.svel > 0)) << 2;
3704     localInput.extbits |= (BUTTON(gamefunc_Strafe_Right) || (input.svel < 0)) << 3;
3705     localInput.extbits |= BUTTON(gamefunc_Turn_Left)<<4;
3706     localInput.extbits |= BUTTON(gamefunc_Turn_Right)<<5;
3707 
3708     if (ud.scrollmode && ud.overhead_on)
3709     {
3710         ud.folfvel = input.fvel;
3711         ud.folavel = fix16_to_int(input.q16avel);
3712 
3713         localInput.fvel = 0;
3714         localInput.svel = 0;
3715 
3716         localInput.q16avel = 0;
3717         localInput.q16horz = 0;
3718 
3719         return;
3720     }
3721 
3722     int16_t const q16ang = fix16_to_int(pPlayer->q16ang);
3723 
3724     localInput.fvel = mulscale9(input.fvel, sintable[(q16ang + 2560) & 2047]) +
3725                       mulscale9(input.svel, sintable[(q16ang + 2048) & 2047]) +
3726                       pPlayer->fric.x;
3727 
3728     localInput.svel = mulscale9(input.fvel, sintable[(q16ang + 2048) & 2047]) +
3729                       mulscale9(input.svel, sintable[(q16ang + 1536) & 2047]) +
3730                       pPlayer->fric.y;
3731 
3732     localInput.q16avel = input.q16avel;
3733     localInput.q16horz = input.q16horz;
3734 }
3735 
P_GetInputMotorcycle(int playerNum)3736 void P_GetInputMotorcycle(int playerNum)
3737 {
3738     auto const pPlayer = g_player[playerNum].ps;
3739     ControlInfo info;
3740 
3741     if ((pPlayer->gm & (MODE_MENU|MODE_TYPE)) || (ud.pause_on && !KB_KeyPressed(sc_Pause)))
3742     {
3743         if (!(pPlayer->gm&MODE_MENU))
3744             CONTROL_GetInput(&info);
3745 
3746         Bmemset(&localInput, 0, sizeof(input_t));
3747 
3748         localInput.bits    = (((int32_t)g_gameQuit) << SK_GAMEQUIT);
3749         localInput.extbits |= (1 << 7);
3750 
3751         return;
3752     }
3753 
3754     CONTROL_ProcessBinds();
3755 
3756     if (ud.mouseaiming)
3757         g_myAimMode = BUTTON(gamefunc_Mouse_Aiming);
3758     else
3759     {
3760         g_oldAimStat = g_myAimStat;
3761         g_myAimStat  = BUTTON(gamefunc_Mouse_Aiming);
3762 
3763         if (g_myAimStat > g_oldAimStat)
3764         {
3765             g_myAimMode ^= 1;
3766             P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_myAimMode, pPlayer);
3767         }
3768     }
3769 
3770     CONTROL_GetInput(&info);
3771 
3772     if (ud.config.MouseDeadZone)
3773     {
3774         if (info.mousey > 0)
3775             info.mousey = max(info.mousey - ud.config.MouseDeadZone, 0);
3776         else if (info.mousey < 0)
3777             info.mousey = min(info.mousey + ud.config.MouseDeadZone, 0);
3778 
3779         if (info.mousex > 0)
3780             info.mousex = max(info.mousex - ud.config.MouseDeadZone, 0);
3781         else if (info.mousex < 0)
3782             info.mousex = min(info.mousex + ud.config.MouseDeadZone, 0);
3783     }
3784 
3785     if (ud.config.MouseBias)
3786     {
3787         if (klabs(info.mousex) > klabs(info.mousey))
3788             info.mousey = tabledivide32_noinline(info.mousey, ud.config.MouseBias);
3789         else
3790             info.mousex = tabledivide32_noinline(info.mousex, ud.config.MouseBias);
3791     }
3792 
3793     // JBF: Run key behaviour is selectable
3794     int const playerRunning = (ud.runkey_mode) ? (BUTTON(gamefunc_Run) | ud.auto_run) : (ud.auto_run ^ BUTTON(gamefunc_Run));
3795     constexpr int const analogTurnAmount = (NORMALTURN << 1);
3796     int const keyMove    = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE;
3797     constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp
3798 
3799     input_t input {};
3800 
3801     input.q16avel = fix16_div(fix16_from_int(info.mousex), F16(32));
3802     input.q16avel += fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1));
3803 
3804     input.q16horz = fix16_div(fix16_from_int(info.mousey), F16(64));
3805 
3806     if (ud.mouseflip) input.q16horz = -input.q16horz;
3807 
3808     input.q16horz -= fix16_from_int(info.dpitch) / analogExtent * analogTurnAmount;
3809     input.svel -= info.dx * keyMove / analogExtent;
3810     input.fvel -= info.dz * keyMove / analogExtent;
3811 
3812     input.fvel = clamp(input.fvel, -MAXVEL, MAXVEL);
3813     input.svel = clamp(input.svel, -MAXSVEL, MAXSVEL);
3814 
3815     input.q16avel = fix16_clamp(input.q16avel, F16(-MAXANGVEL), F16(MAXANGVEL));
3816     input.q16horz = fix16_clamp(input.q16horz, F16(-MAXHORIZ), F16(MAXHORIZ));
3817 
3818     pPlayer->crouch_toggle = 0;
3819 
3820     localInput.bits = BUTTON(gamefunc_Fire) << SK_FIRE;
3821     localInput.bits |= BUTTON(gamefunc_Steroids) << SK_STEROIDS;
3822     localInput.bits |= BUTTON(gamefunc_NightVision) << SK_NIGHTVISION;
3823     localInput.bits |= BUTTON(gamefunc_MedKit) << SK_MEDKIT;
3824     localInput.bits |= (BUTTON(gamefunc_Inventory_Left) ||
3825                  (BUTTON(gamefunc_Dpad_Select) && (input.svel > 0 || input.q16avel < 0))) << SK_INV_LEFT;
3826     localInput.bits |= KB_KeyPressed(sc_Pause) << SK_PAUSE;
3827     localInput.bits |= BUTTON(gamefunc_Holo_Duke) << SK_HOLODUKE;
3828     localInput.bits |= BUTTON(gamefunc_Jetpack) << SK_JETPACK;
3829     localInput.bits |= (g_gameQuit << SK_GAMEQUIT);
3830     localInput.bits |= (BUTTON(gamefunc_Inventory_Right) ||
3831                  (BUTTON(gamefunc_Dpad_Select) && (input.svel < 0 || input.q16avel > 0))) << SK_INV_RIGHT;
3832     localInput.bits |= BUTTON(gamefunc_Open) << SK_OPEN;
3833     localInput.bits |= BUTTON(gamefunc_Inventory) << SK_INVENTORY;
3834     localInput.bits |= ((uint32_t)KB_KeyPressed(sc_Escape)) << SK_ESCAPE;
3835 
3836     if (BUTTON(gamefunc_Dpad_Select))
3837     {
3838         input.fvel = 0;
3839         input.svel = 0;
3840         input.q16avel = 0;
3841     }
3842 
3843     if (BUTTON(gamefunc_Dpad_Aiming))
3844         input.fvel = 0;
3845 
3846     localInput.extbits = (BUTTON(gamefunc_Move_Forward) || (input.fvel > 0));
3847     localInput.extbits |= (BUTTON(gamefunc_Move_Backward) || (input.fvel < 0)) << 1;
3848     localInput.extbits |= (BUTTON(gamefunc_Strafe_Left) || (input.svel > 0)) << 2;
3849     localInput.extbits |= (BUTTON(gamefunc_Strafe_Right) || (input.svel < 0)) << 3;
3850 
3851     int const turn = input.q16avel / 32;
3852     int turnLeft = BUTTON(gamefunc_Turn_Left) || BUTTON(gamefunc_Strafe_Left);
3853     int turnRight = BUTTON(gamefunc_Turn_Right) || BUTTON(gamefunc_Strafe_Right);
3854     int avelScale = F16((turnLeft || turnRight) ? 1 : 0);
3855     if (turn)
3856     {
3857         avelScale = fix16_max(avelScale, fix16_clamp(fix16_mul(turn, turn),0,F16(1)));
3858         if (turn < 0)
3859             turnLeft = 1;
3860         else if (turn > 0)
3861             turnRight = 1;
3862     }
3863 
3864     input.svel = input.fvel = input.q16avel = input.q16horz = 0;
3865 
3866     if (!pPlayer->moto_underwater)
3867     {
3868         localInput.bits |= (BUTTON(gamefunc_Move_Forward) || BUTTON(gamefunc_Strafe)) << SK_JUMP;
3869         localInput.bits |= BUTTON(gamefunc_Move_Backward) << SK_AIM_UP;
3870         localInput.bits |= BUTTON(gamefunc_Run) << SK_CROUCH;
3871     }
3872 
3873     localInput.bits |= turnLeft << SK_AIM_DOWN;
3874     localInput.bits |= turnRight << SK_LOOK_LEFT;
3875 
3876     static int32_t turnHeldTime   = 0;
3877     static int32_t lastInputClock = 0;  // MED
3878     int32_t const  elapsedTics    = (int32_t) totalclock - lastInputClock;
3879 
3880     int const moveBack = BUTTON(gamefunc_Move_Backward) && pPlayer->moto_speed <= 0;
3881 
3882     if (pPlayer->moto_speed == 0 || !pPlayer->on_ground)
3883     {
3884         if (turnLeft)
3885         {
3886             pPlayer->tilt_status--;
3887             if (pPlayer->tilt_status < -10)
3888                 pPlayer->tilt_status = -10;
3889         }
3890         else if (turnRight)
3891         {
3892             pPlayer->tilt_status++;
3893             if (pPlayer->tilt_status > 10)
3894                 pPlayer->tilt_status = 10;
3895         }
3896     }
3897     else
3898     {
3899         if (turnLeft || pPlayer->moto_drink < 0)
3900         {
3901             turnHeldTime += elapsedTics;
3902             pPlayer->tilt_status--;
3903             if (pPlayer->tilt_status < -10)
3904                 pPlayer->tilt_status = -10;
3905             if (turnHeldTime >= TURBOTURNTIME && pPlayer->moto_speed > 0)
3906             {
3907                 if (moveBack)
3908                 {
3909                     if (turn)
3910                         input.q16avel += fix16_from_int(20*2);
3911                     else
3912                         input.q16avel += fix16_from_int(10*2);
3913                 }
3914                 else
3915                 {
3916                     if (turn)
3917                         input.q16avel -= fix16_from_int(20*2);
3918                     else
3919                         input.q16avel -= fix16_from_int(10*2);
3920                 }
3921             }
3922             else
3923             {
3924                 if (moveBack)
3925                 {
3926                     if (turn)
3927                         input.q16avel += fix16_from_int(10*2);
3928                     else
3929                         input.q16avel += fix16_from_int(3*2);
3930                 }
3931                 else
3932                 {
3933                     if (turn)
3934                         input.q16avel -= fix16_from_int(10*2);
3935                     else
3936                         input.q16avel -= fix16_from_int(3*2);
3937                 }
3938             }
3939         }
3940         else if (turnRight || pPlayer->moto_drink > 0)
3941         {
3942             turnHeldTime += elapsedTics;
3943             pPlayer->tilt_status++;
3944             if (pPlayer->tilt_status > 10)
3945                 pPlayer->tilt_status = 10;
3946             if (turnHeldTime >= TURBOTURNTIME && pPlayer->moto_speed > 0)
3947             {
3948                 if (moveBack)
3949                 {
3950                     if (turn)
3951                         input.q16avel -= fix16_from_int(20*2);
3952                     else
3953                         input.q16avel -= fix16_from_int(10*2);
3954                 }
3955                 else
3956                 {
3957                     if (turn)
3958                         input.q16avel += fix16_from_int(20*2);
3959                     else
3960                         input.q16avel += fix16_from_int(10*2);
3961                 }
3962             }
3963             else
3964             {
3965                 if (moveBack)
3966                 {
3967                     if (turn)
3968                         input.q16avel -= fix16_from_int(10*2);
3969                     else
3970                         input.q16avel -= fix16_from_int(3*2);
3971                 }
3972                 else
3973                 {
3974                     if (turn)
3975                         input.q16avel += fix16_from_int(10*2);
3976                     else
3977                         input.q16avel += fix16_from_int(3*2);
3978                 }
3979             }
3980         }
3981         else
3982         {
3983             turnHeldTime = 0;
3984 
3985             if (pPlayer->tilt_status > 0)
3986                 pPlayer->tilt_status--;
3987             else if (pPlayer->tilt_status < 0)
3988                 pPlayer->tilt_status++;
3989         }
3990     }
3991 
3992     if (pPlayer->moto_underwater)
3993         pPlayer->moto_speed = 0;
3994 
3995     input.q16avel = fix16_mul(input.q16avel, avelScale);
3996 
3997     input.fvel += pPlayer->moto_speed;
3998 
3999     input.fvel = clamp(input.fvel, -15, 120);
4000     input.svel = clamp(input.svel, -MAXSVEL, MAXSVEL);
4001     input.q16avel = fix16_clamp(input.q16avel, F16(-MAXANGVEL), F16(MAXANGVEL));
4002     input.q16horz = fix16_clamp(input.q16horz, F16(-MAXHORIZ), F16(MAXHORIZ));
4003 
4004     if (ud.scrollmode && ud.overhead_on)
4005     {
4006         ud.folfvel = input.fvel;
4007         ud.folavel = fix16_to_int(input.q16avel);
4008         localInput.fvel   = 0;
4009         localInput.svel   = 0;
4010         localInput.q16avel  = 0;
4011         localInput.q16horz  = 0;
4012         return;
4013     }
4014 
4015     int16_t const q16ang = fix16_to_int(pPlayer->q16ang);
4016 
4017     localInput.fvel = mulscale9(input.fvel, sintable[(q16ang + 2560) & 2047]) +
4018                       mulscale9(input.svel, sintable[(q16ang + 2048) & 2047]) +
4019                       pPlayer->fric.x;
4020 
4021     localInput.svel = mulscale9(input.fvel, sintable[(q16ang + 2048) & 2047]) +
4022                       mulscale9(input.svel, sintable[(q16ang + 1536) & 2047]) +
4023                       pPlayer->fric.y;
4024 
4025     localInput.q16avel = input.q16avel;
4026     localInput.q16horz = input.q16horz;
4027 
4028     if (TEST_SYNC_KEY(localInput.bits, SK_JUMP))
4029     {
4030         localInput.bits |= 1;
4031     }
4032 }
4033 
P_GetInputBoat(int playerNum)4034 void P_GetInputBoat(int playerNum)
4035 {
4036     auto const pPlayer = g_player[playerNum].ps;
4037     ControlInfo info;
4038 
4039     if ((pPlayer->gm & (MODE_MENU|MODE_TYPE)) || (ud.pause_on && !KB_KeyPressed(sc_Pause)))
4040     {
4041         if (!(pPlayer->gm&MODE_MENU))
4042             CONTROL_GetInput(&info);
4043 
4044         Bmemset(&localInput, 0, sizeof(input_t));
4045 
4046         localInput.bits    = (((int32_t)g_gameQuit) << SK_GAMEQUIT);
4047         localInput.extbits |= (1 << 7);
4048 
4049         return;
4050     }
4051 
4052     CONTROL_ProcessBinds();
4053 
4054     if (ud.mouseaiming)
4055         g_myAimMode = BUTTON(gamefunc_Mouse_Aiming);
4056     else
4057     {
4058         g_oldAimStat = g_myAimStat;
4059         g_myAimStat  = BUTTON(gamefunc_Mouse_Aiming);
4060 
4061         if (g_myAimStat > g_oldAimStat)
4062         {
4063             g_myAimMode ^= 1;
4064             P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_myAimMode, pPlayer);
4065         }
4066     }
4067 
4068     CONTROL_GetInput(&info);
4069 
4070     if (ud.config.MouseDeadZone)
4071     {
4072         if (info.mousey > 0)
4073             info.mousey = max(info.mousey - ud.config.MouseDeadZone, 0);
4074         else if (info.mousey < 0)
4075             info.mousey = min(info.mousey + ud.config.MouseDeadZone, 0);
4076 
4077         if (info.mousex > 0)
4078             info.mousex = max(info.mousex - ud.config.MouseDeadZone, 0);
4079         else if (info.mousex < 0)
4080             info.mousex = min(info.mousex + ud.config.MouseDeadZone, 0);
4081     }
4082 
4083     if (ud.config.MouseBias)
4084     {
4085         if (klabs(info.mousex) > klabs(info.mousey))
4086             info.mousey = tabledivide32_noinline(info.mousey, ud.config.MouseBias);
4087         else
4088             info.mousex = tabledivide32_noinline(info.mousex, ud.config.MouseBias);
4089     }
4090 
4091     // JBF: Run key behaviour is selectable
4092     int const playerRunning = (ud.runkey_mode) ? (BUTTON(gamefunc_Run) | ud.auto_run) : (ud.auto_run ^ BUTTON(gamefunc_Run));
4093     constexpr int const analogTurnAmount = (NORMALTURN << 1);
4094     int const keyMove    = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE;
4095     constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp
4096 
4097     input_t input {};
4098 
4099     input.q16avel = fix16_div(fix16_from_int(info.mousex), F16(32));
4100     input.q16avel += fix16_from_int(info.dyaw * analogTurnAmount / (analogExtent >> 1));
4101 
4102     input.q16horz = fix16_div(fix16_from_int(info.mousey), F16(64));
4103 
4104     if (ud.mouseflip) input.q16horz = -input.q16horz;
4105 
4106     input.q16horz -= fix16_from_int(info.dpitch) / analogExtent * analogTurnAmount;
4107     input.svel -= info.dx * keyMove / analogExtent;
4108     input.fvel -= info.dz * keyMove / analogExtent;
4109 
4110     input.fvel = clamp(input.fvel, -MAXVEL, MAXVEL);
4111     input.svel = clamp(input.svel, -MAXSVEL, MAXSVEL);
4112 
4113     input.q16avel = fix16_clamp(input.q16avel, F16(-MAXANGVEL), F16(MAXANGVEL));
4114     input.q16horz = fix16_clamp(input.q16horz, F16(-MAXHORIZ), F16(MAXHORIZ));
4115 
4116     pPlayer->crouch_toggle = 0;
4117 
4118     localInput.bits = BUTTON(gamefunc_Fire) << SK_FIRE;
4119     localInput.bits |= BUTTON(gamefunc_Steroids) << SK_STEROIDS;
4120     localInput.bits |= BUTTON(gamefunc_NightVision) << SK_NIGHTVISION;
4121     localInput.bits |= BUTTON(gamefunc_MedKit) << SK_MEDKIT;
4122     localInput.bits |= (BUTTON(gamefunc_Inventory_Left) ||
4123                  (BUTTON(gamefunc_Dpad_Select) && (input.svel > 0 || input.q16avel < 0))) << SK_INV_LEFT;
4124     localInput.bits |= KB_KeyPressed(sc_Pause) << SK_PAUSE;
4125     localInput.bits |= BUTTON(gamefunc_Holo_Duke) << SK_HOLODUKE;
4126     localInput.bits |= BUTTON(gamefunc_Jetpack) << SK_JETPACK;
4127     localInput.bits |= (g_gameQuit << SK_GAMEQUIT);
4128     localInput.bits |= (BUTTON(gamefunc_Inventory_Right) ||
4129                  (BUTTON(gamefunc_Dpad_Select) && (input.svel < 0 || input.q16avel > 0))) << SK_INV_RIGHT;
4130     localInput.bits |= BUTTON(gamefunc_Open) << SK_OPEN;
4131     localInput.bits |= BUTTON(gamefunc_Inventory) << SK_INVENTORY;
4132     localInput.bits |= ((uint32_t)KB_KeyPressed(sc_Escape)) << SK_ESCAPE;
4133 
4134     if (BUTTON(gamefunc_Dpad_Select))
4135     {
4136         input.fvel = 0;
4137         input.svel = 0;
4138         input.q16avel = 0;
4139     }
4140 
4141     if (BUTTON(gamefunc_Dpad_Aiming))
4142         input.fvel = 0;
4143 
4144     localInput.extbits = (BUTTON(gamefunc_Move_Forward) || (input.fvel > 0));
4145     localInput.extbits |= (BUTTON(gamefunc_Move_Backward) || (input.fvel < 0)) << 1;
4146     localInput.extbits |= (BUTTON(gamefunc_Strafe_Left) || (input.svel > 0)) << 2;
4147     localInput.extbits |= (BUTTON(gamefunc_Strafe_Right) || (input.svel < 0)) << 3;
4148 
4149     int const turn = input.q16avel / 32;
4150     int turnLeft = BUTTON(gamefunc_Turn_Left) || BUTTON(gamefunc_Strafe_Left);
4151     int turnRight = BUTTON(gamefunc_Turn_Right) || BUTTON(gamefunc_Strafe_Right);
4152     int avelScale = F16((turnLeft || turnRight) ? 1 : 0);
4153     if (turn)
4154     {
4155         avelScale = fix16_max(avelScale, fix16_clamp(fix16_mul(turn, turn),0,F16(1)));
4156         if (turn < 0)
4157             turnLeft = 1;
4158         else if (turn > 0)
4159             turnRight = 1;
4160     }
4161 
4162     input.svel = input.fvel = input.q16avel = input.q16horz = 0;
4163 
4164     localInput.bits |= (BUTTON(gamefunc_Move_Forward) || BUTTON(gamefunc_Strafe)) << SK_JUMP;
4165     localInput.bits |= BUTTON(gamefunc_Move_Backward) << SK_AIM_UP;
4166     localInput.bits |= BUTTON(gamefunc_Run) << SK_CROUCH;
4167 
4168     localInput.bits |= turnLeft << SK_AIM_DOWN;
4169     localInput.bits |= turnRight << SK_LOOK_LEFT;
4170 
4171     static int32_t turnHeldTime   = 0;
4172     static int32_t lastInputClock = 0;  // MED
4173     int32_t const  elapsedTics    = (int32_t) totalclock - lastInputClock;
4174 
4175     if (pPlayer->moto_speed != 0)
4176     {
4177         if (turnLeft || pPlayer->moto_drink < 0)
4178         {
4179             turnHeldTime += elapsedTics;
4180             if (!pPlayer->not_on_water)
4181             {
4182                 pPlayer->tilt_status--;
4183                 if (pPlayer->tilt_status < -10)
4184                     pPlayer->tilt_status = -10;
4185             }
4186             if (turnHeldTime >= TURBOTURNTIME)
4187             {
4188                 if (pPlayer->not_on_water)
4189                 {
4190                     if (turn)
4191                         input.q16avel -= fix16_from_int(6*2);
4192                     else
4193                         input.q16avel -= fix16_from_int(3*2);
4194                 }
4195                 else
4196                 {
4197                     if (turn)
4198                         input.q16avel -= fix16_from_int(20*2);
4199                     else
4200                         input.q16avel -= fix16_from_int(10*2);
4201                 }
4202             }
4203             else
4204             {
4205                 if (pPlayer->not_on_water)
4206                 {
4207                     if (turn)
4208                         input.q16avel -= fix16_from_int(2*2);
4209                     else
4210                         input.q16avel -= fix16_from_int(1*2);
4211                 }
4212                 else
4213                 {
4214                     if (turn)
4215                         input.q16avel -= fix16_from_int(6*2);
4216                     else
4217                         input.q16avel -= fix16_from_int(3*2);
4218                 }
4219             }
4220         }
4221         else if (turnRight || pPlayer->moto_drink > 0)
4222         {
4223             turnHeldTime += elapsedTics;
4224             if (!pPlayer->not_on_water)
4225             {
4226                 pPlayer->tilt_status++;
4227                 if (pPlayer->tilt_status > 10)
4228                     pPlayer->tilt_status = 10;
4229             }
4230             if (turnHeldTime >= TURBOTURNTIME)
4231             {
4232                 if (pPlayer->not_on_water)
4233                 {
4234                     if (turn)
4235                         input.q16avel += fix16_from_int(6*2);
4236                     else
4237                         input.q16avel += fix16_from_int(3*2);
4238                 }
4239                 else
4240                 {
4241                     if (turn)
4242                         input.q16avel += fix16_from_int(20*2);
4243                     else
4244                         input.q16avel += fix16_from_int(10*2);
4245                 }
4246             }
4247             else
4248             {
4249                 if (pPlayer->not_on_water)
4250                 {
4251                     if (turn)
4252                         input.q16avel += fix16_from_int(2*2);
4253                     else
4254                         input.q16avel += fix16_from_int(1*2);
4255                 }
4256                 else
4257                 {
4258                     if (turn)
4259                         input.q16avel += fix16_from_int(6*2);
4260                     else
4261                         input.q16avel += fix16_from_int(3*2);
4262                 }
4263             }
4264         }
4265         else if (!pPlayer->not_on_water)
4266         {
4267             turnHeldTime = 0;
4268 
4269             if (pPlayer->tilt_status > 0)
4270                 pPlayer->tilt_status--;
4271             else if (pPlayer->tilt_status < 0)
4272                 pPlayer->tilt_status++;
4273         }
4274     }
4275     else if (!pPlayer->not_on_water)
4276     {
4277         turnHeldTime = 0;
4278 
4279         if (pPlayer->tilt_status > 0)
4280             pPlayer->tilt_status--;
4281         else if (pPlayer->tilt_status < 0)
4282             pPlayer->tilt_status++;
4283     }
4284 
4285     input.fvel += pPlayer->moto_speed;
4286 
4287     input.q16avel = fix16_mul(input.q16avel, avelScale);
4288 
4289     input.fvel = clamp(input.fvel, -15, 120);
4290     input.svel = clamp(input.svel, -MAXSVEL, MAXSVEL);
4291     input.q16avel = fix16_clamp(input.q16avel, F16(-MAXANGVEL), F16(MAXANGVEL));
4292     input.q16horz = fix16_clamp(input.q16horz, F16(-MAXHORIZ), F16(MAXHORIZ));
4293 
4294     if (ud.scrollmode && ud.overhead_on)
4295     {
4296         ud.folfvel = input.fvel;
4297         ud.folavel = fix16_to_int(input.q16avel);
4298         localInput.fvel   = 0;
4299         localInput.svel   = 0;
4300         localInput.q16avel  = 0;
4301         localInput.q16horz  = 0;
4302         return;
4303     }
4304 
4305     int16_t const q16ang = fix16_to_int(pPlayer->q16ang);
4306 
4307     localInput.fvel = mulscale9(input.fvel, sintable[(q16ang + 2560) & 2047]) +
4308                       mulscale9(input.svel, sintable[(q16ang + 2048) & 2047]) +
4309                       pPlayer->fric.x;
4310 
4311     localInput.svel = mulscale9(input.fvel, sintable[(q16ang + 2048) & 2047]) +
4312                       mulscale9(input.svel, sintable[(q16ang + 1536) & 2047]) +
4313                       pPlayer->fric.y;
4314 
4315     localInput.q16avel = input.q16avel;
4316     localInput.q16horz = input.q16horz;
4317 }
4318 
4319 int dword_A99D4, dword_A99D8, dword_A99DC, dword_A99E0;
4320 int dword_164620, dword_164624;
4321 
sub_299C0(void)4322 void sub_299C0(void)
4323 {
4324     dword_A99D8 = 0;
4325     dword_A99DC = 0;
4326 }
4327 
sub_299D8(void)4328 int sub_299D8(void)
4329 {
4330     if ((int)totalclock - dword_A99D8 >= 30 && BUTTON(gamefunc_Crouch))
4331     {
4332         dword_A99D8 = (int)totalclock;
4333         dword_A99DC ^= 1;
4334     }
4335     return dword_A99DC;
4336 }
4337 
P_DHGetInput(int const playerNum)4338 void P_DHGetInput(int const playerNum)
4339 {
4340     auto const pPlayer = g_player[playerNum].ps;
4341     ControlInfo info;
4342 
4343     if ((pPlayer->gm & (MODE_MENU|MODE_TYPE)) || (ud.pause_on && !KB_KeyPressed(sc_Pause)))
4344     {
4345         if (!(pPlayer->gm&MODE_MENU))
4346             CONTROL_GetInput(&info);
4347 
4348         Bmemset(&localInput, 0, sizeof(input_t));
4349 
4350         localInput.bits    = (((int32_t)g_gameQuit) << SK_GAMEQUIT);
4351         localInput.extbits |= (1 << 7);
4352 
4353         return;
4354     }
4355 
4356     CONTROL_ProcessBinds();
4357 
4358     if (ud.mouseaiming)
4359         g_myAimMode = BUTTON(gamefunc_Mouse_Aiming);
4360     else
4361     {
4362         g_oldAimStat = g_myAimStat;
4363         g_myAimStat  = BUTTON(gamefunc_Mouse_Aiming);
4364 
4365         if (g_myAimStat > g_oldAimStat)
4366         {
4367             g_myAimMode ^= 1;
4368             P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_myAimMode, pPlayer);
4369         }
4370     }
4371 
4372     CONTROL_GetInput(&info);
4373 
4374     if (ud.config.MouseDeadZone)
4375     {
4376         if (info.mousey > 0)
4377             info.mousey = max(info.mousey - ud.config.MouseDeadZone, 0);
4378         else if (info.mousey < 0)
4379             info.mousey = min(info.mousey + ud.config.MouseDeadZone, 0);
4380 
4381         if (info.mousex > 0)
4382             info.mousex = max(info.mousex - ud.config.MouseDeadZone, 0);
4383         else if (info.mousex < 0)
4384             info.mousex = min(info.mousex + ud.config.MouseDeadZone, 0);
4385     }
4386 
4387     if (ud.config.MouseBias)
4388     {
4389         if (klabs(info.mousex) > klabs(info.mousey))
4390             info.mousey = tabledivide32_noinline(info.mousey, ud.config.MouseBias);
4391         else
4392             info.mousex = tabledivide32_noinline(info.mousex, ud.config.MouseBias);
4393     }
4394 
4395     // JBF: Run key behaviour is selectable
4396     int const playerRunning = (ud.runkey_mode) ? (BUTTON(gamefunc_Run) | ud.auto_run) : (ud.auto_run ^ BUTTON(gamefunc_Run));
4397     int const playerCrouch = sub_299D8();
4398     int const playerJump = BUTTON(gamefunc_Jump) && !(pPlayer->cursectnum >= 0 && sector[pPlayer->cursectnum].hitag == 2003);
4399     int const turnAmount = playerCrouch ? 2 : (playerRunning ? 16 : 8);
4400     constexpr int const analogTurnAmount = 16;
4401     int const keyMove    = playerCrouch ? 3 : (playerRunning ? 24 : 12);
4402     constexpr int const analogExtent = 32767; // KEEPINSYNC sdlayer.cpp
4403 
4404     input_t input {};
4405 
4406     if (BUTTON(gamefunc_Strafe))
4407     {
4408         static int strafeyaw;
4409 
4410         input.svel = -(info.mousex + strafeyaw) >> 3;
4411         strafeyaw  = (info.mousex + strafeyaw) % 8;
4412 
4413         input.svel -= info.dyaw * keyMove / analogExtent;
4414     }
4415     else
4416     {
4417         input.q16avel = fix16_div(fix16_from_int(info.mousex), F16(32));
4418         input.q16avel += fix16_from_int(info.dyaw) / analogExtent * (analogTurnAmount << 1);
4419     }
4420 
4421     if (g_myAimMode)
4422         input.q16horz = fix16_div(fix16_from_int(info.mousey), F16(64));
4423     else
4424         input.fvel = -(info.mousey >> 6);
4425 
4426     if (ud.mouseflip) input.q16horz = -input.q16horz;
4427 
4428     input.q16horz -= fix16_from_int(info.dpitch) / analogExtent * analogTurnAmount;
4429     input.svel -= info.dx * keyMove / analogExtent;
4430     input.fvel -= info.dz * keyMove / analogExtent;
4431 
4432     if (BUTTON(gamefunc_Strafe))
4433     {
4434         if (BUTTON(gamefunc_Turn_Left) && !(pPlayer->movement_lock&4))
4435             input.svel -= -keyMove;
4436 
4437         if (BUTTON(gamefunc_Turn_Right) && !(pPlayer->movement_lock&8))
4438             input.svel -= keyMove;
4439     }
4440     else
4441     {
4442         static int32_t turnHeldTime   = 0;
4443         static int32_t lastInputClock = 0;  // MED
4444         int32_t const  elapsedTics    = (int32_t) totalclock - lastInputClock;
4445 
4446         lastInputClock = (int32_t) totalclock;
4447 
4448         if (BUTTON(gamefunc_Turn_Left))
4449         {
4450             turnHeldTime += elapsedTics;
4451             input.q16avel -= fix16_from_int((turnHeldTime >= TURBOTURNTIME) ? (turnAmount << 1) : (PREAMBLETURN << 1));
4452         }
4453         else if (BUTTON(gamefunc_Turn_Right))
4454         {
4455             turnHeldTime += elapsedTics;
4456             input.q16avel += fix16_from_int((turnHeldTime >= TURBOTURNTIME) ? (turnAmount << 1) : (PREAMBLETURN << 1));
4457         }
4458         else
4459             turnHeldTime=0;
4460     }
4461 
4462     if (BUTTON(gamefunc_Strafe_Left) && !(pPlayer->movement_lock & 4))
4463         input.svel += keyMove;
4464 
4465     if (BUTTON(gamefunc_Strafe_Right) && !(pPlayer->movement_lock & 8))
4466         input.svel += -keyMove;
4467 
4468     if (BUTTON(gamefunc_Move_Forward) && !(pPlayer->movement_lock & 1))
4469         input.fvel += keyMove;
4470 
4471     if (BUTTON(gamefunc_Move_Backward) && !(pPlayer->movement_lock & 2))
4472         input.fvel += -(keyMove >> 1);
4473 
4474     input.fvel = clamp(input.fvel, -MAXVEL, MAXVEL);
4475     input.svel = clamp(input.svel, -MAXSVEL, MAXSVEL);
4476 
4477     if (playerRunning && sub_535EC())
4478         input.fvel <<= 3;
4479 
4480     input.q16avel = fix16_clamp(input.q16avel, F16(-MAXANGVEL), F16(MAXANGVEL));
4481     input.q16horz = fix16_clamp(input.q16horz, F16(-MAXHORIZ), F16(MAXHORIZ));
4482 
4483     localInput.bits = (BUTTON(gamefunc_Fire) << SK_FIRE);
4484 
4485     localInput.bits |= (playerJump << SK_JUMP) | (playerCrouch << SK_CROUCH);
4486 
4487     localInput.bits |= (BUTTON(gamefunc_Aim_Up) || (BUTTON(gamefunc_Dpad_Aiming) && input.fvel > 0)) << SK_AIM_UP;
4488     localInput.bits |= (BUTTON(gamefunc_Aim_Down) || (BUTTON(gamefunc_Dpad_Aiming) && input.fvel < 0)) << SK_AIM_DOWN;
4489     localInput.bits |= (BUTTON(gamefunc_Center_View) << SK_CENTER_VIEW);
4490 
4491     localInput.bits |= (BUTTON(gamefunc_Look_Left) << SK_LOOK_LEFT) | (BUTTON(gamefunc_Look_Right) << SK_LOOK_RIGHT);
4492     localInput.bits |= (BUTTON(gamefunc_Look_Up) << SK_LOOK_UP) | (BUTTON(gamefunc_Look_Down) << SK_LOOK_DOWN);
4493 
4494     localInput.bits |= (playerRunning << SK_RUN);
4495 
4496     localInput.bits |= BUTTON(gamefunc_TurnAround) << SK_TURNAROUND;
4497 
4498     localInput.bits |= (g_myAimMode << SK_AIMMODE);
4499     localInput.bits |= (g_gameQuit << SK_GAMEQUIT);
4500     localInput.bits |= KB_KeyPressed(sc_Pause) << SK_PAUSE;
4501     localInput.bits |= ((uint32_t)KB_KeyPressed(sc_Escape)) << SK_ESCAPE;
4502 
4503     if (BUTTON(gamefunc_Dpad_Aiming))
4504         input.fvel = 0;
4505 
4506     localInput.extbits = (BUTTON(gamefunc_Move_Forward) || (input.fvel > 0));
4507     localInput.extbits |= (BUTTON(gamefunc_Move_Backward) || (input.fvel < 0)) << 1;
4508     localInput.extbits |= (BUTTON(gamefunc_Strafe_Left) || (input.svel > 0)) << 2;
4509     localInput.extbits |= (BUTTON(gamefunc_Strafe_Right) || (input.svel < 0)) << 3;
4510     localInput.extbits |= BUTTON(gamefunc_Turn_Left)<<4;
4511     localInput.extbits |= BUTTON(gamefunc_Turn_Right)<<5;
4512 
4513     if (pPlayer->cursectnum >= 0 && sector[pPlayer->cursectnum].hitag == 2003)
4514         input.fvel >>= 1;
4515 
4516     int16_t const q16ang = fix16_to_int(pPlayer->q16ang);
4517 
4518     localInput.fvel = mulscale9(input.fvel, sintable[(q16ang + 2560) & 2047]) +
4519                       mulscale9(input.svel, sintable[(q16ang + 2048) & 2047]) +
4520                       pPlayer->fric.x;
4521 
4522     localInput.svel = mulscale9(input.fvel, sintable[(q16ang + 2048) & 2047]) +
4523                       mulscale9(input.svel, sintable[(q16ang + 1536) & 2047]) +
4524                       pPlayer->fric.y;
4525 
4526     localInput.q16avel = input.q16avel;
4527     localInput.q16horz = input.q16horz;
4528 
4529     if (input.fvel || input.svel || input.q16avel || TEST_SYNC_KEY(input.bits, SK_FIRE) || dword_A99E0 != pPlayer->pos.z)
4530         pPlayer->dhat60f = 1;
4531     dword_A99E0 = pPlayer->pos.z;
4532     pPlayer->dhat617 = playerRunning;
4533     if (!input.fvel)
4534         pPlayer->dhat617 = 0;
4535     pPlayer->dhat613 = BUTTON(gamefunc_Move_Forward) | BUTTON(gamefunc_Move_Backward);
4536     if (pPlayer->dhat60f)
4537         sub_5A250(256);
4538     //dword_A99D4++;
4539     //if (dword_A99D4 == 2)
4540     //{
4541     //    sub_53304();
4542     //    dword_A99D4 = 0;
4543     //}
4544 }
4545 
P_MadeNoise(int playerNum)4546 void P_MadeNoise(int playerNum)
4547 {
4548     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
4549     pPlayer->make_noise = 1;
4550     pPlayer->noise_x = pPlayer->pos.x;
4551     pPlayer->noise_y = pPlayer->pos.y;
4552 }
4553 
P_Thrust(DukePlayer_t * const pPlayer,int shift)4554 static void P_Thrust(DukePlayer_t *const pPlayer, int shift)
4555 {
4556     pPlayer->vel.x += sintable[(fix16_to_int(pPlayer->q16ang)+512)&2047] << shift;
4557     pPlayer->vel.y += sintable[fix16_to_int(pPlayer->q16ang)&2047] << shift;
4558 }
4559 
P_DoCounters(int playerNum)4560 static int32_t P_DoCounters(int playerNum)
4561 {
4562     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
4563 
4564     if (RRRA)
4565     {
4566         if (g_windTime > 0)
4567             g_windTime--;
4568         else if ((krand2() & 127) == 8)
4569         {
4570             g_windTime = 120+((krand2()&63)<<2);
4571             g_windDir = krand2()&2047;
4572         }
4573 
4574         if (g_bellTime > 0)
4575         {
4576             g_bellTime--;
4577             if (g_bellTime == 0)
4578                 sprite[g_bellSprite].picnum++;
4579         }
4580 
4581         if (playerNum == 0 && g_chickenWeaponTimer > 0)
4582             g_chickenWeaponTimer--;
4583 
4584         if (pPlayer->sea_sick)
4585         {
4586             pPlayer->sea_sick--;
4587             if (pPlayer->sea_sick)
4588                 pPlayer->sea_sick_stat = 0;
4589         }
4590 
4591     }
4592 
4593     if (RR)
4594     {
4595         if (pPlayer->yehaa_timer)
4596             pPlayer->yehaa_timer--;
4597 
4598         if (pPlayer->hbomb_offset > 0)
4599         {
4600             pPlayer->hbomb_offset++;
4601             pPlayer->hbomb_time--;
4602         }
4603 
4604         if (--pPlayer->drink_timer <= 0)
4605         {
4606             pPlayer->drink_timer = 1024;
4607             if (pPlayer->drink_amt)
4608                 pPlayer->drink_amt--;
4609         }
4610 
4611         if (--pPlayer->eat_timer <= 0)
4612         {
4613             pPlayer->eat_timer = 1024;
4614             if (pPlayer->eat_amt)
4615                 pPlayer->eat_amt--;
4616         }
4617 
4618         if (pPlayer->drink_amt == 100)
4619         {
4620             if (!A_CheckSoundPlaying(pPlayer->i, 420))
4621                 A_PlaySound(420, pPlayer->i);
4622             pPlayer->drink_amt -= 9;
4623             pPlayer->eat_amt >>= 1;
4624         }
4625         pPlayer->eat_ang = (1647 + pPlayer->eat_amt * 8) & 2047;
4626 
4627         if (pPlayer->eat_amt >= 100)
4628             pPlayer->eat_amt = 100;
4629 
4630         if (pPlayer->eat_amt >= 31 && krand2() < pPlayer->eat_amt)
4631         {
4632             switch (krand2()&3)
4633             {
4634                 case 0:
4635                     A_PlaySound(404, pPlayer->i);
4636                     break;
4637                 case 1:
4638                     A_PlaySound(422, pPlayer->i);
4639                     break;
4640                 case 2:
4641                     A_PlaySound(423, pPlayer->i);
4642                     break;
4643                 case 3:
4644                     A_PlaySound(424, pPlayer->i);
4645                     break;
4646             }
4647             if (!g_netServer && numplayers < 2)
4648             {
4649                 pPlayer->noise_radius = 16384;
4650                 P_MadeNoise(playerNum);
4651                 P_Thrust(pPlayer, 4);
4652             }
4653             pPlayer->eat_amt -= 4;
4654             if (pPlayer->eat_amt < 0)
4655                 pPlayer->eat_amt = 0;
4656         }
4657     }
4658 
4659     if (pPlayer->invdisptime > 0)
4660         pPlayer->invdisptime--;
4661 
4662     if (pPlayer->tipincs > 0)
4663         pPlayer->tipincs--;
4664 
4665     if (pPlayer->last_pissed_time > 0)
4666     {
4667         if (RR)
4668         {
4669             --pPlayer->last_pissed_time;
4670 
4671             if (pPlayer->drink_amt > 66 && (pPlayer->last_pissed_time % GAMETICSPERSEC) == 0)
4672                 pPlayer->drink_amt--;
4673 
4674             if (!ud.lockout)
4675             {
4676                 switch (pPlayer->last_pissed_time)
4677                 {
4678                     case 5662:
4679                         A_PlaySound(434, pPlayer->i);
4680                         break;
4681                     case 5567:
4682                         A_PlaySound(434, pPlayer->i);
4683                         break;
4684                     case 5472:
4685                         A_PlaySound(433, pPlayer->i);
4686                         break;
4687                     case 5072:
4688                         A_PlaySound(435, pPlayer->i);
4689                         break;
4690                     case 5014:
4691                         A_PlaySound(434, pPlayer->i);
4692                         break;
4693                     case 4919:
4694                         A_PlaySound(433, pPlayer->i);
4695                         break;
4696                 }
4697             }
4698             if (pPlayer->last_pissed_time == 5668)
4699             {
4700                 pPlayer->holster_weapon = 0;
4701                 pPlayer->weapon_pos     = WEAPON_POS_RAISE;
4702             }
4703         }
4704         else
4705             switch (--pPlayer->last_pissed_time)
4706             {
4707                 case GAMETICSPERSEC * 219:
4708                 {
4709                     A_PlaySound(REALITY ? 53 : FLUSH_TOILET, pPlayer->i);
4710                     if (playerNum == screenpeek || GTFLAGS(GAMETYPE_COOPSOUND))
4711                         A_PlaySound(REALITY ? 175 : DUKE_PISSRELIEF, pPlayer->i);
4712                 }
4713                 break;
4714                 case GAMETICSPERSEC * 218:
4715                 {
4716                     pPlayer->holster_weapon = 0;
4717                     pPlayer->weapon_pos     = WEAPON_POS_RAISE;
4718                 }
4719                 break;
4720             }
4721     }
4722 
4723     if (pPlayer->crack_time > 0)
4724     {
4725         if (--pPlayer->crack_time == 0)
4726         {
4727             pPlayer->knuckle_incs = 1;
4728             pPlayer->crack_time   = 777;
4729             if (REALITY)
4730                 pPlayer->crack_time += krand2() & 255;
4731         }
4732     }
4733 
4734     if (pPlayer->inv_amount[GET_STEROIDS] > 0 && pPlayer->inv_amount[GET_STEROIDS] < 400)
4735     {
4736         if (--pPlayer->inv_amount[GET_STEROIDS] == 0)
4737         {
4738             P_SelectNextInvItem(pPlayer);
4739             if (RR)
4740             {
4741                 pPlayer->eat_amt = pPlayer->drink_amt = 0;
4742                 pPlayer->eat_ang = pPlayer->drink_ang = 1647;
4743             }
4744         }
4745 
4746         if (!(pPlayer->inv_amount[GET_STEROIDS] & (RR ? 14 : 7)))
4747             if (playerNum == screenpeek || GTFLAGS(GAMETYPE_COOPSOUND))
4748                 A_PlaySound(RR ? DUKE_TAKEPILLS : (REALITY ? 32 : DUKE_HARTBEAT), pPlayer->i);
4749     }
4750 
4751     if (!RR)
4752     {
4753         if (pPlayer->heat_on && pPlayer->inv_amount[GET_HEATS] > 0)
4754         {
4755             if (--pPlayer->inv_amount[GET_HEATS] == 0)
4756             {
4757                 pPlayer->heat_on = 0;
4758                 P_SelectNextInvItem(pPlayer);
4759                 A_PlaySound(REALITY ? 170 : NITEVISION_ONOFF, pPlayer->i);
4760                 P_UpdateScreenPal(pPlayer);
4761             }
4762         }
4763 
4764         if (pPlayer->holoduke_on >= 0)
4765         {
4766             if (--pPlayer->inv_amount[GET_HOLODUKE] <= 0)
4767             {
4768                 A_PlaySound(REALITY ? 45 : TELEPORTER, pPlayer->i);
4769                 pPlayer->holoduke_on = -1;
4770                 P_SelectNextInvItem(pPlayer);
4771             }
4772         }
4773 
4774         if (pPlayer->jetpack_on && pPlayer->inv_amount[GET_JETPACK] > 0)
4775         {
4776             if (--pPlayer->inv_amount[GET_JETPACK] <= 0)
4777             {
4778                 pPlayer->jetpack_on = 0;
4779                 P_SelectNextInvItem(pPlayer);
4780                 A_PlaySound(REALITY ? 40 : DUKE_JETPACK_OFF, pPlayer->i);
4781                 S_StopEnvSound(REALITY ? 39 : DUKE_JETPACK_IDLE, pPlayer->i);
4782                 S_StopEnvSound(REALITY ? 38 : DUKE_JETPACK_ON, pPlayer->i);
4783             }
4784         }
4785 
4786         if (pPlayer->quick_kick > 0 && sprite[pPlayer->i].pal != 1)
4787         {
4788             pPlayer->last_quick_kick = pPlayer->quick_kick + 1;
4789 
4790             if (--pPlayer->quick_kick == 8)
4791                 A_Shoot(pPlayer->i, KNEE);
4792         }
4793         else if (pPlayer->last_quick_kick > 0)
4794             --pPlayer->last_quick_kick;
4795     }
4796 
4797     if (pPlayer->access_incs && sprite[pPlayer->i].pal != 1)
4798     {
4799         if (REALITY)
4800         {
4801             if (pPlayer->dn_388)
4802             {
4803                 FX_StopSound(pPlayer->dn_388);
4804                 pPlayer->dn_388 = 0;
4805             }
4806         }
4807         ++pPlayer->access_incs;
4808 
4809         if (sprite[pPlayer->i].extra <= 0)
4810             pPlayer->access_incs = 12;
4811 
4812         if (pPlayer->access_incs == 12)
4813         {
4814             if (pPlayer->access_spritenum >= 0)
4815             {
4816                 P_ActivateSwitch(playerNum, pPlayer->access_spritenum, 1);
4817                 switch (sprite[pPlayer->access_spritenum].pal)
4818                 {
4819                     case 0:  RR ? pPlayer->keys[1] = 1 : pPlayer->got_access &= (0xffff - 0x1); break;
4820                     case 21: RR ? pPlayer->keys[2] = 1 : pPlayer->got_access &= (0xffff - 0x2); break;
4821                     case 23: RR ? pPlayer->keys[3] = 1 : pPlayer->got_access &= (0xffff - 0x4); break;
4822                 }
4823                 pPlayer->access_spritenum = -1;
4824             }
4825             else
4826             {
4827                 P_ActivateSwitch(playerNum,pPlayer->access_wallnum,0);
4828                 switch (wall[pPlayer->access_wallnum].pal)
4829                 {
4830                     case 0:  RR ? pPlayer->keys[1] = 1 : pPlayer->got_access &= (0xffff - 0x1); break;
4831                     case 21: RR ? pPlayer->keys[2] = 1 : pPlayer->got_access &= (0xffff - 0x2); break;
4832                     case 23: RR ? pPlayer->keys[3] = 1 : pPlayer->got_access &= (0xffff - 0x4); break;
4833                 }
4834             }
4835         }
4836 
4837         if (pPlayer->access_incs > 20)
4838         {
4839             pPlayer->access_incs  = 0;
4840             pPlayer->weapon_pos   = WEAPON_POS_RAISE;
4841             pPlayer->kickback_pic = 0;
4842         }
4843     }
4844 
4845     if (pPlayer->cursectnum >= 0 && pPlayer->scuba_on == 0 && sector[pPlayer->cursectnum].lotag == ST_2_UNDERWATER)
4846     {
4847         if (pPlayer->inv_amount[GET_SCUBA] > 0)
4848         {
4849             pPlayer->scuba_on   = 1;
4850             pPlayer->inven_icon = ICON_SCUBA;
4851             P_DoQuote(QUOTE_SCUBA_ON, pPlayer);
4852         }
4853         else
4854         {
4855             if (pPlayer->airleft > 0)
4856                 --pPlayer->airleft;
4857             else
4858             {
4859                 pPlayer->extra_extra8 += 32;
4860                 if (pPlayer->last_extra < (pPlayer->max_player_health >> 1) && (pPlayer->last_extra & 3) == 0)
4861                     A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN, pPlayer->i);
4862             }
4863         }
4864     }
4865     else if (pPlayer->inv_amount[GET_SCUBA] > 0 && pPlayer->scuba_on)
4866     {
4867         pPlayer->inv_amount[GET_SCUBA]--;
4868         if (pPlayer->inv_amount[GET_SCUBA] == 0)
4869         {
4870             pPlayer->scuba_on = 0;
4871             P_SelectNextInvItem(pPlayer);
4872         }
4873     }
4874 
4875     if (pPlayer->knuckle_incs)
4876     {
4877         if (++pPlayer->knuckle_incs == 10)
4878         {
4879             if (RR && !g_wupass)
4880             {
4881                 int soundId = 391;
4882                 g_wupass = 1;
4883                 if (!g_lastLevel) switch (ud.volume_number)
4884                 {
4885                     case 0:
4886                         switch (ud.level_number)
4887                         {
4888                             case 0:
4889                                 soundId = RRRA ? 63 : 391;
4890                                 break;
4891                             case 1:
4892                                 soundId = 64;
4893                                 break;
4894                             case 2:
4895                                 soundId = 77;
4896                                 break;
4897                             case 3:
4898                                 soundId = 80;
4899                                 break;
4900                             case 4:
4901                                 soundId = 102;
4902                                 break;
4903                             case 5:
4904                                 soundId = 103;
4905                                 break;
4906                             case 6:
4907                                 soundId = 104;
4908                                 break;
4909                         }
4910                         break;
4911                     case 1:
4912                         switch (ud.level_number)
4913                         {
4914                             case 0:
4915                                 soundId = 105;
4916                                 break;
4917                             case 1:
4918                                 soundId = 176;
4919                                 break;
4920                             case 2:
4921                                 soundId = 177;
4922                                 break;
4923                             case 3:
4924                                 soundId = 198;
4925                                 break;
4926                             case 4:
4927                                 soundId = 230;
4928                                 break;
4929                             case 5:
4930                                 soundId = 255;
4931                                 break;
4932                             case 6:
4933                                 soundId = 283;
4934                                 break;
4935                         }
4936                         break;
4937                 }
4938                 A_PlaySound(soundId, pPlayer->i);
4939             }
4940             else if (!WW2GI)
4941             {
4942                 if (totalclock > 1024 && (!REALITY || (krand2()&3) == 0))
4943                     if (playerNum == screenpeek || GTFLAGS(GAMETYPE_COOPSOUND))
4944                     {
4945                         if ((REALITY ? krand2() : rand())&1)
4946                             A_PlaySound(REALITY ? 165 : DUKE_CRACK,pPlayer->i);
4947                         else A_PlaySound(REALITY ? 26 : DUKE_CRACK2,pPlayer->i);
4948                     }
4949 
4950                 A_PlaySound(REALITY ? 172 : DUKE_CRACK_FIRST, pPlayer->i);
4951             }
4952         }
4953         else if (pPlayer->knuckle_incs == 22 || TEST_SYNC_KEY(g_player[playerNum].inputBits->bits, SK_FIRE))
4954             pPlayer->knuckle_incs=0;
4955 
4956         return 1;
4957     }
4958 
4959     return 0;
4960 }
4961 
4962 int16_t WeaponPickupSprites[MAX_WEAPONS] = { KNEE__STATIC, FIRSTGUNSPRITE__STATIC, SHOTGUNSPRITE__STATIC,
4963         CHAINGUNSPRITE__STATIC, RPGSPRITE__STATIC, HEAVYHBOMB__STATIC, SHRINKERSPRITE__STATIC, DEVISTATORSPRITE__STATIC,
4964         TRIPBOMBSPRITE__STATIC, FREEZESPRITE__STATIC, HEAVYHBOMB__STATIC, SHRINKERSPRITE__STATIC
4965                                            };
4966 // this is used for player deaths
P_DropWeapon(int const playerNum)4967 void P_DropWeapon(int const playerNum)
4968 {
4969     DukePlayer_t *const pPlayer       = g_player[playerNum].ps;
4970     int const currentWeapon = WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : pPlayer->curr_weapon;
4971 
4972     if (RRRA && (g_netServer || numplayers > 1))
4973     {
4974         if (pPlayer->on_motorcycle)
4975         {
4976             int const newSprite = A_Spawn(pPlayer->i, EMPTYBIKE);
4977             sprite[newSprite].ang = fix16_to_int(pPlayer->q16ang);
4978             sprite[newSprite].owner = pPlayer->ammo_amount[MOTORCYCLE_WEAPON];
4979             pPlayer->on_motorcycle = 0;
4980             pPlayer->gotweapon &= ~(1<<MOTORCYCLE_WEAPON);
4981             pPlayer->q16horiz = F16(100);
4982             pPlayer->moto_do_bump = 0;
4983             pPlayer->moto_speed = 0;
4984             pPlayer->tilt_status = 0;
4985             pPlayer->moto_drink = 0;
4986             pPlayer->moto_bump_target = 0;
4987             pPlayer->moto_bump = 0;
4988             pPlayer->moto_turb = 0;
4989         }
4990         else if (pPlayer->on_boat)
4991         {
4992             int const newSprite = A_Spawn(pPlayer->i, EMPTYBOAT);
4993             sprite[newSprite].ang = fix16_to_int(pPlayer->q16ang);
4994             sprite[newSprite].owner = pPlayer->ammo_amount[BOAT_WEAPON];
4995             pPlayer->on_boat = 0;
4996             pPlayer->gotweapon &= ~(1<<BOAT_WEAPON);
4997             pPlayer->q16horiz = F16(100);
4998             pPlayer->moto_do_bump = 0;
4999             pPlayer->moto_speed = 0;
5000             pPlayer->tilt_status = 0;
5001             pPlayer->moto_drink = 0;
5002             pPlayer->moto_bump_target = 0;
5003             pPlayer->moto_bump = 0;
5004             pPlayer->moto_turb = 0;
5005         }
5006     }
5007 
5008     if (currentWeapon == KNEE_WEAPON || (unsigned)currentWeapon >= MAX_WEAPONS)
5009         return;
5010 
5011     if (krand2() & 1)
5012     {
5013         int weaponTile = WeaponPickupSprites[currentWeapon];
5014         if (REALITY && weaponTile == GROWSPRITEICON)
5015             weaponTile = SHRINKERSPRITE;
5016         A_Spawn(pPlayer->i, weaponTile);
5017     }
5018     else
5019         switch (DYNAMICWEAPONMAP(currentWeapon))
5020         {
5021             case CHICKEN_WEAPON__STATIC:
5022                 if (!RRRA) break;
5023                 fallthrough__;
5024             case RPG_WEAPON__STATIC:
5025             case HANDBOMB_WEAPON__STATIC: A_Spawn(pPlayer->i, EXPLOSION2); break;
5026             case DEVISTATOR_WEAPON__STATIC:
5027             case MOTORCYCLE_WEAPON__STATIC:
5028                 if (REALITY)
5029                     A_Spawn(pPlayer->i, EXPLOSION2);
5030                 break;
5031         }
5032 
5033     if (RR)
5034     {
5035         for (bssize_t key = 0; key < 5; key++)
5036         {
5037             if (pPlayer->keys[key] == 1)
5038             {
5039                 int const newSprite = A_Spawn(pPlayer->i, ACCESSCARD);
5040                 switch (key)
5041                 {
5042                     case 1:
5043                         sprite[newSprite].lotag = 100;
5044                         break;
5045                     case 2:
5046                         sprite[newSprite].lotag = 101;
5047                         break;
5048                     case 3:
5049                         sprite[newSprite].lotag = 102;
5050                         break;
5051                     case 4:
5052                         sprite[newSprite].lotag = 103;
5053                         break;
5054                 }
5055             }
5056         }
5057     }
5058 }
5059 
P_AddAmmo(DukePlayer_t * const pPlayer,int const weaponNum,int const addAmount)5060 void P_AddAmmo(DukePlayer_t * const pPlayer, int const weaponNum, int const addAmount)
5061 {
5062     pPlayer->ammo_amount[weaponNum] += addAmount;
5063 
5064     if (pPlayer->ammo_amount[weaponNum] > pPlayer->max_ammo_amount[weaponNum])
5065         pPlayer->ammo_amount[weaponNum] = pPlayer->max_ammo_amount[weaponNum];
5066 }
5067 
P_AddWeapon(DukePlayer_t * pPlayer,int weaponNum)5068 void P_AddWeapon(DukePlayer_t *pPlayer, int weaponNum)
5069 {
5070     int8_t curr_weapon = pPlayer->curr_weapon;
5071 
5072     if (pPlayer->on_motorcycle || pPlayer->on_boat)
5073     {
5074         pPlayer->gotweapon |= (1<<weaponNum);
5075 
5076         if (weaponNum == SHRINKER_WEAPON)
5077         {
5078             pPlayer->gotweapon |= (1<<GROW_WEAPON);
5079             pPlayer->ammo_amount[GROW_WEAPON] = 1;
5080         }
5081         else if (weaponNum == RPG_WEAPON)
5082             pPlayer->gotweapon |= (1<<CHICKEN_WEAPON);
5083         else if (weaponNum == SLINGBLADE_WEAPON)
5084             pPlayer->ammo_amount[SLINGBLADE_WEAPON] = 1;
5085         return;
5086     }
5087 
5088     if ((pPlayer->gotweapon & (1<<weaponNum)) == 0)
5089     {
5090         pPlayer->gotweapon |= (1<<weaponNum);
5091 
5092         if (weaponNum == SHRINKER_WEAPON)
5093         {
5094             pPlayer->gotweapon |= (1<<GROW_WEAPON);
5095             if (RR)
5096                 pPlayer->ammo_amount[GROW_WEAPON] = 1;
5097         }
5098         if (RRRA)
5099         {
5100             if (weaponNum == RPG_WEAPON)
5101                 pPlayer->gotweapon |= (1<<CHICKEN_WEAPON);
5102             else if (weaponNum == SLINGBLADE_WEAPON)
5103                 pPlayer->ammo_amount[SLINGBLADE_WEAPON] = 50;
5104         }
5105         if (REALITY)
5106         {
5107             if (weaponNum == GROW_WEAPON)
5108                 pPlayer->gotweapon |= (1<<SHRINKER_WEAPON);
5109             if (weaponNum == PISTOL_WEAPON)
5110                 pPlayer->gotweapon |= (1<<BOWLINGBALL_WEAPON);
5111             if (weaponNum == SHOTGUN_WEAPON)
5112                 pPlayer->gotweapon |= (1<<MOTORCYCLE_WEAPON);
5113             if (weaponNum == RPG_WEAPON)
5114                 pPlayer->gotweapon |= (1<<BOAT_WEAPON);
5115             if (weaponNum == HANDBOMB_WEAPON)
5116                 pPlayer->gotweapon |= (1<<HANDREMOTE_WEAPON);
5117 
5118             return;
5119         }
5120 
5121         if (!RR || weaponNum != HANDBOMB_WEAPON)
5122             curr_weapon = weaponNum;
5123     }
5124     else
5125         curr_weapon = weaponNum;
5126 
5127     if (RR && weaponNum == HANDBOMB_WEAPON)
5128         pPlayer->last_weapon = -1;
5129 
5130     pPlayer->random_club_frame = 0;
5131 
5132     if (pPlayer->holster_weapon == 0)
5133     {
5134         pPlayer->weapon_pos = -1;
5135         pPlayer->last_weapon = pPlayer->curr_weapon;
5136     }
5137     else
5138     {
5139         pPlayer->weapon_pos = WEAPON_POS_RAISE;
5140         pPlayer->holster_weapon = 0;
5141         pPlayer->last_weapon = -1;
5142     }
5143 
5144     pPlayer->kickback_pic = 0;
5145     pPlayer->curr_weapon = curr_weapon;
5146     if (REALITY)
5147         pPlayer->dn64_372 = curr_weapon;
5148 
5149     switch (DYNAMICWEAPONMAP(weaponNum))
5150     {
5151     case SLINGBLADE_WEAPON__STATIC:
5152     case KNEE_WEAPON__STATIC:
5153     case TRIPBOMB_WEAPON__STATIC:
5154     case HANDREMOTE_WEAPON__STATIC:
5155     case HANDBOMB_WEAPON__STATIC:     break;
5156     case SHOTGUN_WEAPON__STATIC:      A_PlaySound(REALITY ? 131 : SHOTGUN_COCK, pPlayer->i); break;
5157     case PISTOL_WEAPON__STATIC:       A_PlaySound(REALITY ? 4 : INSERT_CLIP, pPlayer->i); break;
5158                 default:      A_PlaySound(RR ? EJECT_CLIP : (REALITY ? 176 : SELECT_WEAPON), pPlayer->i); break;
5159     }
5160 }
5161 
P_SelectNextInvItem(DukePlayer_t * pPlayer)5162 void P_SelectNextInvItem(DukePlayer_t *pPlayer)
5163 {
5164     if (pPlayer->inv_amount[GET_FIRSTAID] > 0)
5165         pPlayer->inven_icon = ICON_FIRSTAID;
5166     else if (pPlayer->inv_amount[GET_STEROIDS] > 0)
5167         pPlayer->inven_icon = ICON_STEROIDS;
5168     else if (pPlayer->inv_amount[GET_HOLODUKE] > 0)
5169         pPlayer->inven_icon = ICON_HOLODUKE;
5170     else if (pPlayer->inv_amount[GET_JETPACK] > 0)
5171         pPlayer->inven_icon = ICON_JETPACK;
5172     else if (pPlayer->inv_amount[GET_HEATS] > 0)
5173         pPlayer->inven_icon = ICON_HEATS;
5174     else if (pPlayer->inv_amount[GET_SCUBA] > 0)
5175         pPlayer->inven_icon = ICON_SCUBA;
5176     else if (pPlayer->inv_amount[GET_BOOTS] > 0)
5177         pPlayer->inven_icon = ICON_BOOTS;
5178     else
5179         pPlayer->inven_icon = ICON_NONE;
5180 }
5181 
P_CheckWeapon(DukePlayer_t * pPlayer)5182 void P_CheckWeapon(DukePlayer_t *pPlayer)
5183 {
5184     int playerNum;
5185     int weaponNum;
5186 
5187     // if (pPlayer->reloading)
5188     //     return;
5189 
5190     if (pPlayer->wantweaponfire >= 0)
5191     {
5192         weaponNum = pPlayer->wantweaponfire;
5193         pPlayer->wantweaponfire = -1;
5194 
5195         if (weaponNum == pPlayer->curr_weapon)
5196             return;
5197 
5198         if (REALITY && (weaponNum == KNEE_WEAPON || weaponNum == HANDREMOTE_WEAPON))
5199         {
5200             P_AddWeapon(pPlayer, weaponNum);
5201             return;
5202         }
5203 
5204         if ((pPlayer->gotweapon & (1<<weaponNum)) && pPlayer->ammo_amount[weaponNum] > 0)
5205         {
5206             P_AddWeapon(pPlayer, weaponNum);
5207             return;
5208         }
5209     }
5210 
5211     weaponNum = pPlayer->curr_weapon;
5212 
5213     if ((pPlayer->gotweapon & (1<<weaponNum)) && pPlayer->ammo_amount[weaponNum] > 0)
5214         return;
5215 
5216     playerNum  = P_Get(pPlayer->i);
5217 
5218     int wpnInc = 0;
5219 
5220     for (wpnInc = 0; wpnInc <= (REALITY ? 13 : 9); ++wpnInc)
5221     {
5222         weaponNum = g_player[playerNum].wchoice[wpnInc];
5223         if (VOLUMEONE && weaponNum > SHRINKER_WEAPON)
5224             continue;
5225 
5226         if (!REALITY)
5227         {
5228             if (weaponNum == KNEE_WEAPON)
5229                 weaponNum = RR ? DEVISTATOR_WEAPON : FREEZE_WEAPON;
5230             else weaponNum--;
5231         }
5232 
5233         if (weaponNum == KNEE_WEAPON || ((pPlayer->gotweapon & (1<<weaponNum)) && pPlayer->ammo_amount[weaponNum] > 0))
5234             break;
5235     }
5236 
5237     if (!REALITY && wpnInc == HANDREMOTE_WEAPON)
5238         weaponNum = KNEE_WEAPON;
5239 
5240     // Found the weapon
5241 
5242     pPlayer->last_weapon = pPlayer->curr_weapon;
5243     pPlayer->random_club_frame = 0;
5244     pPlayer->curr_weapon = weaponNum;
5245     if (REALITY)
5246         pPlayer->dn64_372 = weaponNum;
5247     P_SetWeaponGamevars(playerNum, pPlayer);
5248     VM_OnEvent(EVENT_CHANGEWEAPON, pPlayer->i, playerNum);
5249     pPlayer->kickback_pic = 0;
5250     if (pPlayer->holster_weapon == 1)
5251     {
5252         pPlayer->holster_weapon = 0;
5253         pPlayer->weapon_pos = 10;
5254     }
5255     else pPlayer->weapon_pos = -1;
5256 }
5257 
DoWallTouchDamage(const DukePlayer_t * pPlayer,int32_t wallNum)5258 static void DoWallTouchDamage(const DukePlayer_t *pPlayer, int32_t wallNum)
5259 {
5260     vec3_t const davect = { pPlayer->pos.x + (sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] >> 9),
5261                       pPlayer->pos.y + (sintable[fix16_to_int(pPlayer->q16ang) & 2047] >> 9), pPlayer->pos.z };
5262 
5263     A_DamageWall(pPlayer->i, wallNum, &davect, -1);
5264 }
5265 
P_CheckTouchDamage(DukePlayer_t * pPlayer,int touchObject)5266 static void P_CheckTouchDamage(DukePlayer_t *pPlayer, int touchObject)
5267 {
5268     if (touchObject == -1)
5269         return;
5270 
5271     if ((touchObject & 49152) == 49152)
5272     {
5273         int const touchSprite = touchObject & (MAXSPRITES - 1);
5274 
5275         if (RRRA)
5276         {
5277             switch (DYNAMICTILEMAP(sprite[touchSprite].picnum))
5278             {
5279                 case RRTILE2430__STATICRR:
5280                 case RRTILE2431__STATICRR:
5281                 case RRTILE2432__STATICRR:
5282                 case RRTILE2443__STATICRR:
5283                 case RRTILE2446__STATICRR:
5284                 case RRTILE2451__STATICRR:
5285                 case RRTILE2455__STATICRR:
5286                     if (pPlayer->hurt_delay2 < 8)
5287                     {
5288                         sprite[pPlayer->i].extra -= 5;
5289 
5290                         pPlayer->hurt_delay2 = 16;
5291                         P_PalFrom(pPlayer, 32, 32, 0, 0);
5292                         A_PlaySound(DUKE_LONGTERM_PAIN, pPlayer->i);
5293                     }
5294                     break;
5295             }
5296             return;
5297         }
5298         if (sprite[touchSprite].picnum == CACTUS)
5299         {
5300             if (pPlayer->hurt_delay < 8)
5301             {
5302                 sprite[pPlayer->i].extra -= 5;
5303 
5304                 pPlayer->hurt_delay = 16;
5305                 P_PalFrom(pPlayer, 32, 32, 0, 0);
5306                 A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN, pPlayer->i);
5307             }
5308         }
5309         return;
5310     }
5311 
5312     if ((touchObject & 49152) != 32768)
5313         return;
5314 
5315     int const touchWall = touchObject & (MAXWALLS-1);
5316 
5317     if (pPlayer->hurt_delay > 0)
5318         pPlayer->hurt_delay--;
5319     else if (wall[touchWall].cstat & FORCEFIELD_CSTAT)
5320     {
5321         int const forcePic = G_GetForcefieldPicnum(touchWall);
5322 
5323         switch (DYNAMICTILEMAP(forcePic))
5324         {
5325         case W_FORCEFIELD__STATIC:
5326             if (RR) break;
5327             sprite[pPlayer->i].extra -= 5;
5328 
5329             pPlayer->hurt_delay = 16;
5330             P_PalFrom(pPlayer, 32, 32,0,0);
5331 
5332             pPlayer->vel.x = -(sintable[(fix16_to_int(pPlayer->q16ang)+512)&2047]<<8);
5333             pPlayer->vel.y = -(sintable[(fix16_to_int(pPlayer->q16ang))&2047]<<8);
5334             A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN,pPlayer->i);
5335 
5336             DoWallTouchDamage(pPlayer, touchWall);
5337             break;
5338 
5339         case BIGFORCE__STATIC:
5340             pPlayer->hurt_delay = GAMETICSPERSEC;
5341             DoWallTouchDamage(pPlayer, touchWall);
5342             break;
5343         }
5344     }
5345 }
5346 
P_CheckFloorDamage(DukePlayer_t * pPlayer,int floorTexture)5347 static int P_CheckFloorDamage(DukePlayer_t *pPlayer, int floorTexture)
5348 {
5349     spritetype * const pSprite = &sprite[pPlayer->i];
5350 
5351     if ((unsigned)(floorTexture) >= MAXTILES)
5352         return 0;
5353 
5354     switch (DYNAMICTILEMAP(floorTexture))
5355     {
5356         case HURTRAIL__STATIC:
5357             if (rnd(32))
5358             {
5359                 if (pPlayer->inv_amount[GET_BOOTS] > 0)
5360                     return 1;
5361                 else
5362                 {
5363                     if (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 168 : DUKE_LONGTERM_PAIN))
5364                         A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN, pPlayer->i);
5365 
5366                     P_PalFrom(pPlayer, 32, 64, 64, 64);
5367 
5368                     pSprite->extra -= 1 + (krand2() & 3);
5369                     if (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 19 : SHORT_CIRCUIT))
5370                         A_PlaySound(REALITY ? 19 : SHORT_CIRCUIT, pPlayer->i);
5371 
5372                     return 0;
5373                 }
5374             }
5375             break;
5376 
5377         case FLOORSLIME__STATIC:
5378             if (rnd(16))
5379             {
5380                 if (pPlayer->inv_amount[GET_BOOTS] > 0)
5381                     return 1;
5382                 else
5383                 {
5384                     if (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 168 : DUKE_LONGTERM_PAIN))
5385                         A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN, pPlayer->i);
5386 
5387                     P_PalFrom(pPlayer, 32, 0, 8, 0);
5388                     pSprite->extra -= 1 + (krand2() & 3);
5389 
5390                     return 0;
5391                 }
5392             }
5393             break;
5394 
5395         case FLOORPLASMA__STATIC:
5396             if (rnd(32))
5397             {
5398                 if (pPlayer->inv_amount[GET_BOOTS] > 0)
5399                     return 1;
5400                 else
5401                 {
5402                     if (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 168 : DUKE_LONGTERM_PAIN))
5403                         A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN, pPlayer->i);
5404 
5405                     P_PalFrom(pPlayer, 32, 8, 0, 0);
5406                     pSprite->extra -= 1 + (krand2() & 3);
5407 
5408                     return 0;
5409                 }
5410             }
5411             break;
5412         case DN64TILE4250__STATIC:
5413             if (!REALITY) break;
5414             if (rnd(16))
5415             {
5416                 if (pPlayer->inv_amount[GET_BOOTS] > 0)
5417                     return 1;
5418                 else
5419                 {
5420                     if (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 168 : DUKE_LONGTERM_PAIN))
5421                         A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN, pPlayer->i);
5422 
5423                     P_PalFrom(pPlayer, 32, 8, 0, 0);
5424                     pSprite->extra -= 1 + (krand2() & 3);
5425 
5426                     return 0;
5427                 }
5428             }
5429             break;
5430     }
5431 
5432     return 0;
5433 }
5434 
5435 
P_FindOtherPlayer(int playerNum,int32_t * pDist)5436 int P_FindOtherPlayer(int playerNum, int32_t *pDist)
5437 {
5438     int closestPlayer     = playerNum;
5439     int closestPlayerDist = INT32_MAX;
5440 
5441     for (bssize_t TRAVERSE_CONNECT(otherPlayer))
5442     {
5443         if (playerNum != otherPlayer && sprite[g_player[otherPlayer].ps->i].extra > 0)
5444         {
5445             int otherPlayerDist = klabs(g_player[otherPlayer].ps->opos.x - g_player[playerNum].ps->pos.x) +
5446                                   klabs(g_player[otherPlayer].ps->opos.y - g_player[playerNum].ps->pos.y) +
5447                                   (klabs(g_player[otherPlayer].ps->opos.z - g_player[playerNum].ps->pos.z) >> 4);
5448 
5449             if (otherPlayerDist < closestPlayerDist)
5450             {
5451                 closestPlayer     = otherPlayer;
5452                 closestPlayerDist = otherPlayerDist;
5453             }
5454         }
5455     }
5456 
5457     *pDist = closestPlayerDist;
5458 
5459     return closestPlayer;
5460 }
5461 
P_FragPlayer(int playerNum)5462 void P_FragPlayer(int playerNum)
5463 {
5464     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
5465     spritetype *const   pSprite = &sprite[pPlayer->i];
5466 
5467     //if (g_netClient) // [75] The server should not overwrite its own randomseed
5468     //    randomseed = ticrandomseed;
5469 
5470     if (pSprite->pal != 1 || REALITY)
5471     {
5472         P_PalFrom(pPlayer, 63, 63, 0, 0);
5473 
5474         pPlayer->pos.z -= ZOFFSET2;
5475         pSprite->z -= ZOFFSET2;
5476 
5477         int32_t r1 = krand2(), r2 = krand2();
5478         if (REALITY)
5479             swap(&r1, &r2);
5480         pPlayer->dead_flag = (512 - ((r2 & 1) << 10) + (r1 & 255) - 512) & 2047;
5481 
5482         // if (pPlayer->dead_flag == 0)
5483         //     pPlayer->dead_flag++;
5484 
5485 #ifndef NETCODE_DISABLE
5486         //if (g_netServer)
5487         //{
5488         //    packbuf[0] = PACKET_FRAG;
5489         //    packbuf[1] = playerNum;
5490         //    packbuf[2] = pPlayer->frag_ps;
5491         //    packbuf[3] = actor[pPlayer->i].picnum;
5492         //    B_BUF32(&packbuf[4], ticrandomseed);
5493         //    packbuf[8] = myconnectindex;
5494         //
5495         //    enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(packbuf, 9, ENET_PACKET_FLAG_RELIABLE));
5496         //}
5497 #endif
5498     }
5499 
5500     pPlayer->jetpack_on  = 0;
5501     pPlayer->holoduke_on = -1;
5502 
5503     if (!RR)
5504         S_StopEnvSound(REALITY ? 39 : DUKE_JETPACK_IDLE, pPlayer->i);
5505 
5506     if (pPlayer->scream_voice > FX_Ok)
5507     {
5508         FX_StopSound(pPlayer->scream_voice);
5509         S_Cleanup();
5510         pPlayer->scream_voice = -1;
5511     }
5512 
5513     if (REALITY && pPlayer->dn_388)
5514     {
5515         FX_StopSound(pPlayer->dn_388);
5516         pPlayer->dn_388 = 0;
5517     }
5518 
5519     if ((REALITY || pSprite->pal != 1) && (pSprite->cstat & 32768) == 0)
5520         pSprite->cstat = 0;
5521 
5522     if ((g_netServer || ud.multimode > 1) && (REALITY || (pSprite->pal != 1 || (pSprite->cstat & 32768))))
5523     {
5524         if (pPlayer->frag_ps != playerNum)
5525         {
5526             if (GTFLAGS(GAMETYPE_TDM) && g_player[pPlayer->frag_ps].ps->team == g_player[playerNum].ps->team)
5527                 g_player[pPlayer->frag_ps].ps->fraggedself++;
5528             else
5529             {
5530                 g_player[pPlayer->frag_ps].ps->frag++;
5531                 g_player[pPlayer->frag_ps].frags[playerNum]++;
5532                 g_player[playerNum].frags[playerNum]++;  // deaths
5533             }
5534 
5535             if (playerNum == screenpeek)
5536             {
5537                 Bsprintf(apStrings[QUOTE_RESERVED], "Killed by %s", &g_player[pPlayer->frag_ps].user_name[0]);
5538                 P_DoQuote(QUOTE_RESERVED, pPlayer);
5539             }
5540             else
5541             {
5542                 Bsprintf(apStrings[QUOTE_RESERVED2], "Killed %s", &g_player[playerNum].user_name[0]);
5543                 P_DoQuote(QUOTE_RESERVED2, g_player[pPlayer->frag_ps].ps);
5544             }
5545 
5546             if (ud.obituaries)
5547             {
5548                 Bsprintf(tempbuf, apStrings[OBITQUOTEINDEX + (g_globalRandom % g_numObituaries)],
5549                          &g_player[pPlayer->frag_ps].user_name[0], &g_player[playerNum].user_name[0]);
5550                 G_AddUserQuote(tempbuf);
5551             }
5552         }
5553         else
5554         {
5555             if (actor[pPlayer->i].picnum != APLAYERTOP)
5556             {
5557                 pPlayer->fraggedself++;
5558                 if ((unsigned)pPlayer->wackedbyactor < MAXTILES && A_CheckEnemyTile(sprite[pPlayer->wackedbyactor].picnum))
5559                     Bsprintf(tempbuf, apStrings[OBITQUOTEINDEX + (krand2() % g_numObituaries)], "A monster",
5560                              &g_player[playerNum].user_name[0]);
5561                 else if (actor[pPlayer->i].picnum == NUKEBUTTON)
5562                     Bsprintf(tempbuf, "^02%s^02 tried to leave", &g_player[playerNum].user_name[0]);
5563                 else
5564                 {
5565                     // random suicide death string
5566                     Bsprintf(tempbuf, apStrings[SUICIDEQUOTEINDEX + (krand2() % g_numSelfObituaries)],
5567                              &g_player[playerNum].user_name[0]);
5568                 }
5569             }
5570             else
5571                 Bsprintf(tempbuf, "^02%s^02 switched to team %d", &g_player[playerNum].user_name[0], pPlayer->team + 1);
5572 
5573             if (ud.obituaries)
5574                 G_AddUserQuote(tempbuf);
5575         }
5576         pPlayer->frag_ps = playerNum;
5577         pus              = NUMPAGES;
5578     }
5579 }
5580 
5581 # define PIPEBOMB_CONTROL(playerNum) (Gv_GetVarByLabel("PIPEBOMB_CONTROL", PIPEBOMB_REMOTE, -1, playerNum))
5582 
P_ProcessWeapon(int playerNum)5583 static void P_ProcessWeapon(int playerNum)
5584 {
5585     DukePlayer_t *const pPlayer      = g_player[playerNum].ps;
5586     int16_t *const      weaponFrame  = &pPlayer->kickback_pic;
5587     int const           playerShrunk = (sprite[pPlayer->i].yrepeat < (RR ? 8 : 32));
5588     uint32_t            playerBits   = g_player[playerNum].inputBits->bits;
5589     int const           sectorLotag  = sector[pPlayer->cursectnum].lotag;
5590 
5591     if (REALITY)
5592         return RT_P_ProcessWeapon(playerNum);
5593 
5594     if (RR)
5595     {
5596         if (pPlayer->hbomb_offset > 0)
5597         {
5598             if (ud.god)
5599             {
5600                 pPlayer->hbomb_time = 45;
5601                 pPlayer->hbomb_offset = 0;
5602             }
5603             else if (pPlayer->hbomb_time <= 0 && (*weaponFrame) < 5)
5604             {
5605                 S_PlaySound(PIPEBOMB_EXPLODE);
5606                 P_QuickKill(pPlayer);
5607             }
5608         }
5609     }
5610 #define WEAPON2_CLIP 20
5611     if (NAM_WW2GI && TEST_SYNC_KEY(playerBits, SK_HOLSTER))   // 'Holster Weapon
5612     {
5613         if (NAM)
5614         {
5615             if (pPlayer->curr_weapon == PISTOL_WEAPON)
5616             {
5617                 if (pPlayer->ammo_amount[PISTOL_WEAPON] > WEAPON2_CLIP)
5618                 {
5619                     // throw away the remaining clip
5620                     pPlayer->ammo_amount[PISTOL_WEAPON] -= pPlayer->ammo_amount[PISTOL_WEAPON] % WEAPON2_CLIP;
5621                     (*weaponFrame) = 3;
5622                     playerBits &= ~BIT(SK_FIRE);
5623                 }
5624                 return;
5625             }
5626         }
5627         else
5628         {
5629             P_SetWeaponGamevars(playerNum, pPlayer);
5630 
5631             if (VM_OnEvent(EVENT_HOLSTER, pPlayer->i, playerNum) == 0)
5632             {
5633                 if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_HOLSTER_CLEARS_CLIP)
5634                 {
5635                     int const weap = pPlayer->curr_weapon, clipcnt = PWEAPON(playerNum, weap, Clip);
5636 
5637                     if (pPlayer->ammo_amount[weap] > clipcnt && (pPlayer->ammo_amount[weap] % clipcnt) != 0)
5638                     {
5639                         pPlayer->ammo_amount[weap] -= pPlayer->ammo_amount[weap] % clipcnt;
5640                         *weaponFrame                = PWEAPON(playerNum, weap, TotalTime)+1;
5641                         playerBits                 &= ~BIT(SK_FIRE);  // not firing...
5642                     }
5643 
5644                     return;
5645                 }
5646             }
5647         }
5648     }
5649 #undef WEAPON2_CLIP
5650     if (WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_GLOWS :
5651         (pPlayer->curr_weapon == SHRINKER_WEAPON || pPlayer->curr_weapon == GROW_WEAPON
5652         || (RR && (pPlayer->curr_weapon == TRIPBOMB_WEAPON || pPlayer->curr_weapon == BOWLINGBALL_WEAPON))
5653         || (RRRA && (pPlayer->curr_weapon == KNEE_WEAPON || pPlayer->curr_weapon == SLINGBLADE_WEAPON))))
5654     {
5655         pPlayer->random_club_frame += 64; // Glowing
5656 
5657 #ifdef POLYMER
5658         if (pPlayer->kickback_pic == 0 && !RR)
5659         {
5660             spritetype *const pSprite     = &sprite[pPlayer->i];
5661             int const         glowXOffset = ((sintable[(pSprite->ang + 512) & 2047]) >> 7);
5662             int const         glowYOffset = ((sintable[(pSprite->ang) & 2047]) >> 7);
5663             int const         glowRange   = 1024 + (sintable[pPlayer->random_club_frame & 2047] >> 3);
5664             int const         flashColor  = (pPlayer->curr_weapon == GROW_WEAPON) ? 216+(52<<8)+(20<<16) : 176+(252<<8)+(120<<16);
5665 
5666             pSprite->x += glowXOffset;
5667             pSprite->y += glowYOffset;
5668 
5669             G_AddGameLight(0, pPlayer->i, PHEIGHT, max(glowRange, 0), flashColor, PR_LIGHT_PRIO_HIGH_GAME);
5670 
5671             actor[pPlayer->i].lightcount = 2;
5672 
5673             pSprite->x -= glowXOffset;
5674             pSprite->y -= glowYOffset;
5675         }
5676 #endif
5677     }
5678 
5679     if (pPlayer->rapid_fire_hold == 1)
5680     {
5681         if (TEST_SYNC_KEY(playerBits, SK_FIRE))
5682             return;
5683         pPlayer->rapid_fire_hold = 0;
5684     }
5685 
5686     if (playerShrunk || pPlayer->tipincs || pPlayer->access_incs)
5687         playerBits &= ~BIT(SK_FIRE);
5688     else if (playerShrunk == 0 && (playerBits & (1 << 2)) && (*weaponFrame) == 0 && pPlayer->fist_incs == 0 &&
5689              pPlayer->last_weapon == -1 && (pPlayer->weapon_pos == 0 || pPlayer->holster_weapon == 1))
5690     {
5691         pPlayer->crack_time = 777;
5692 
5693         if (pPlayer->holster_weapon == 1)
5694         {
5695             if (pPlayer->last_pissed_time <= (GAMETICSPERSEC * 218) && pPlayer->weapon_pos == WEAPON_POS_LOWER)
5696             {
5697                 pPlayer->holster_weapon = 0;
5698                 pPlayer->weapon_pos     = WEAPON_POS_RAISE;
5699                 P_DoQuote(QUOTE_WEAPON_RAISED, pPlayer);
5700             }
5701         }
5702         else
5703         {
5704             P_SetWeaponGamevars(playerNum, pPlayer);
5705             if (VM_OnEvent(EVENT_FIRE, pPlayer->i, playerNum) == 0)
5706             {
5707                 switch (DYNAMICWEAPONMAP(WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : pPlayer->curr_weapon))
5708                 {
5709                     case HANDBOMB_WEAPON__STATIC:
5710                         pPlayer->hbomb_hold_delay = 0;
5711                         if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
5712                         {
5713                             (*weaponFrame) = 1;
5714                             if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5715                                 A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5716                         }
5717                         break;
5718 
5719                     case HANDREMOTE_WEAPON__STATIC:
5720                         pPlayer->hbomb_hold_delay = 0;
5721                         (*weaponFrame)            = 1;
5722                         if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5723                             A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5724                         break;
5725 
5726                     case PISTOL_WEAPON__STATIC:
5727                         if (pPlayer->ammo_amount[PISTOL_WEAPON] > 0)
5728                         {
5729                             if (!WW2GI)
5730                                 pPlayer->ammo_amount[PISTOL_WEAPON]--;
5731                             (*weaponFrame) = 1;
5732                             if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5733                                 A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5734                         }
5735                         break;
5736 
5737                     case SHOTGUN_WEAPON__STATIC:
5738                         if (pPlayer->ammo_amount[SHOTGUN_WEAPON] > 0 && pPlayer->random_club_frame == 0)
5739                         {
5740                             (*weaponFrame) = 1;
5741                             if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5742                                 A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5743                         }
5744                         break;
5745 
5746                     case TRIPBOMB_WEAPON__STATIC:
5747                     case BOWLINGBALL_WEAPON__STATIC:
5748                         if (RR)
5749                         {
5750                             if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
5751                             {
5752                                 //pPlayer->ammo_amount[pPlayer->curr_weapon]--;
5753                                 (*weaponFrame) = 1;
5754                             }
5755                             break;
5756                         }
5757                         if (pPlayer->curr_weapon == BOWLINGBALL)
5758                             break;
5759                         if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
5760                         {
5761                             hitdata_t hitData;
5762 
5763                             hitscan((const vec3_t *)pPlayer, pPlayer->cursectnum, sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047],
5764                                     sintable[fix16_to_int(pPlayer->q16ang) & 2047], fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 32, &hitData,
5765                                     CLIPMASK1);
5766 
5767                             if ((hitData.sect < 0 || hitData.sprite >= 0) ||
5768                                 (hitData.wall >= 0 && sector[hitData.sect].lotag > 2))
5769                                 break;
5770 
5771                             if (hitData.wall >= 0 && wall[hitData.wall].overpicnum >= 0)
5772                                 if (wall[hitData.wall].overpicnum == BIGFORCE)
5773                                     break;
5774 
5775                             int spriteNum = headspritesect[hitData.sect];
5776                             while (spriteNum >= 0)
5777                             {
5778                                 if (sprite[spriteNum].picnum == TRIPBOMB && klabs(sprite[spriteNum].z - hitData.pos.z) < ZOFFSET4 &&
5779                                     ((sprite[spriteNum].x - hitData.pos.x) * (sprite[spriteNum].x - hitData.pos.x) +
5780                                         (sprite[spriteNum].y - hitData.pos.y) * (sprite[spriteNum].y - hitData.pos.y)) < (290 * 290))
5781                                     break;
5782                                 spriteNum = nextspritesect[spriteNum];
5783                             }
5784 
5785                             // ST_2_UNDERWATER
5786                             if (spriteNum == -1 && hitData.wall >= 0 && (wall[hitData.wall].cstat & 16) == 0)
5787                                 if ((wall[hitData.wall].nextsector >= 0 && sector[wall[hitData.wall].nextsector].lotag <= 2) ||
5788                                     (wall[hitData.wall].nextsector == -1 && sector[hitData.sect].lotag <= 2))
5789                                     if (((hitData.pos.x - pPlayer->pos.x) * (hitData.pos.x - pPlayer->pos.x) +
5790                                             (hitData.pos.y - pPlayer->pos.y) * (hitData.pos.y - pPlayer->pos.y)) < (290 * 290))
5791                                     {
5792                                         pPlayer->pos.z = pPlayer->opos.z;
5793                                         pPlayer->vel.z = 0;
5794                                         (*weaponFrame) = 1;
5795                                         if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5796                                         {
5797                                             A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5798                                         }
5799                                     }
5800                         }
5801                         break;
5802 
5803                     case SHRINKER_WEAPON__STATIC:
5804                         if (pPlayer->ammo_amount[SHRINKER_WEAPON] > 0)
5805                         {
5806                             (*weaponFrame) = 1;
5807                             if (!WW2GI)
5808                                 A_PlaySound(SHRINKER_FIRE, pPlayer->i);
5809                             else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5810                                 A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5811                         }
5812                         break;
5813 
5814                     case GROW_WEAPON__STATIC:
5815                         if (pPlayer->ammo_amount[GROW_WEAPON] > 0)
5816                         {
5817                             (*weaponFrame) = 1;
5818                             if (!WW2GI)
5819                                 A_PlaySound(RR ? 431 : EXPANDERSHOOT, pPlayer->i);
5820                             else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5821                                 A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5822                         }
5823                         break;
5824 
5825                     case FREEZE_WEAPON__STATIC:
5826                         if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
5827                         {
5828                             (*weaponFrame) = 1;
5829                             if (!RR)
5830                             {
5831                                 if (!WW2GI)
5832                                     A_PlaySound(CAT_FIRE, pPlayer->i);
5833                                 else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5834                                     A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5835                             }
5836                         }
5837                         break;
5838 
5839                     case RPG_WEAPON__STATIC:
5840                     case CHAINGUN_WEAPON__STATIC:
5841                         if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
5842                         {
5843                             (*weaponFrame) = 1;
5844                             if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5845                                 A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5846                         }
5847                         break;
5848 
5849                     case DEVISTATOR_WEAPON__STATIC:
5850                         if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
5851                         {
5852                             (*weaponFrame)            = 1;
5853                             pPlayer->hbomb_hold_delay = !pPlayer->hbomb_hold_delay;
5854                             if (!RR)
5855                             {
5856                                 if (!WW2GI)
5857                                     A_PlaySound(CAT_FIRE, pPlayer->i);
5858                                 else if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5859                                     A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5860                             }
5861                         }
5862                         break;
5863 
5864                     case KNEE_WEAPON__STATIC:
5865                     case SLINGBLADE_WEAPON__STATIC:
5866                         if (RRRA)
5867                         {
5868                             if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0 && !pPlayer->quick_kick)
5869                                 (*weaponFrame) = 1;
5870                             break;
5871                         }
5872                         if (RRRA && pPlayer->curr_weapon == SLINGBLADE) break;
5873                         if (pPlayer->quick_kick == 0)
5874                         {
5875                             (*weaponFrame) = 1;
5876                             if (WW2GI && PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0)
5877                                 A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
5878                         }
5879                         break;
5880 
5881                     case CHICKEN_WEAPON__STATIC:
5882                     case MOTORCYCLE_WEAPON__STATIC:
5883                     case BOAT_WEAPON__STATIC:
5884                         if (!RRRA) break;
5885                         if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
5886                         {
5887                             (*weaponFrame) = 1;
5888                         }
5889                         break;
5890                 }
5891             }
5892         }
5893     }
5894     else if (*weaponFrame)
5895     {
5896         int spriteNum;
5897         int flashColor = 0;
5898 
5899         if (RR)
5900         {
5901             switch (DYNAMICWEAPONMAP(pPlayer->curr_weapon))
5902             {
5903             case HANDBOMB_WEAPON__STATIC:
5904                 if (*weaponFrame == 1)
5905                     S_PlaySound(401);
5906 
5907                 if ((*weaponFrame) == 6 && TEST_SYNC_KEY(playerBits, SK_FIRE))
5908                     pPlayer->rapid_fire_hold = 1;
5909 
5910                 if (++(*weaponFrame) > 19)
5911                 {
5912                     *weaponFrame = 0;
5913                     pPlayer->curr_weapon = HANDREMOTE_WEAPON;
5914                     pPlayer->last_weapon = -1;
5915                     pPlayer->weapon_pos = WEAPON_POS_RAISE;
5916                     pPlayer->hbomb_time = 45;
5917                     pPlayer->hbomb_offset = 1;
5918                     S_PlaySound(402);
5919                 }
5920                 break;
5921 
5922             case HANDREMOTE_WEAPON__STATIC:
5923                 (*weaponFrame)++;
5924 
5925                 if (pPlayer->hbomb_time < 0)
5926                     pPlayer->hbomb_on = 0;
5927 
5928                 if ((*weaponFrame) == 39)
5929                 {
5930                     pPlayer->hbomb_on = 0;
5931                     pPlayer->noise_radius = 8192;
5932                     P_MadeNoise(playerNum);
5933                 }
5934                 if ((*weaponFrame) == 12)
5935                 {
5936                     pPlayer->ammo_amount[HANDBOMB_WEAPON]--;
5937                     if (pPlayer->ammo_amount[RPG_WEAPON])
5938                         pPlayer->ammo_amount[RPG_WEAPON]--;
5939 
5940                     //if (numplayers < 2 || g_netServer)
5941                     {
5942                         int pipeBombZvel;
5943                         int pipeBombFwdVel;
5944 
5945                         if (pPlayer->on_ground && TEST_SYNC_KEY(playerBits, SK_CROUCH))
5946                         {
5947                             pipeBombFwdVel = 15;
5948                             pipeBombZvel   = (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
5949                         }
5950                         else
5951                         {
5952                             pipeBombFwdVel = 140;
5953                             pipeBombZvel   = -512 - (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
5954                         }
5955 
5956                         int pipeSpriteNum = A_InsertSprite(pPlayer->cursectnum,
5957                                            pPlayer->pos.x+(sintable[(fix16_to_int(pPlayer->q16ang)+512)&2047]>>6),
5958                                            pPlayer->pos.y+(sintable[fix16_to_int(pPlayer->q16ang)&2047]>>6),
5959                                            pPlayer->pos.z,HEAVYHBOMB,-16,9,9,
5960                                            fix16_to_int(pPlayer->q16ang),(pipeBombFwdVel+(pPlayer->hbomb_hold_delay<<5))*2,pipeBombZvel,pPlayer->i,1);
5961 
5962                         if (pipeBombFwdVel == 15)
5963                         {
5964                             sprite[pipeSpriteNum].yvel = 3;
5965                             sprite[pipeSpriteNum].z += ZOFFSET3;
5966                         }
5967 
5968                         if (A_GetHitscanRange(pPlayer->i) < 512)
5969                         {
5970                             sprite[pipeSpriteNum].ang += 1024;
5971                             sprite[pipeSpriteNum].zvel /= 3;
5972                             sprite[pipeSpriteNum].xvel /= 3;
5973                         }
5974                     }
5975 
5976                     pPlayer->hbomb_on = 1;
5977                 }
5978                 else if (*weaponFrame < 12 && TEST_SYNC_KEY(playerBits, SK_FIRE))
5979                     pPlayer->hbomb_hold_delay++;
5980 
5981                 if (*weaponFrame == 40)
5982                 {
5983                     (*weaponFrame) = 0;
5984                     pPlayer->curr_weapon = HANDBOMB_WEAPON;
5985                     pPlayer->last_weapon = -1;
5986                     pPlayer->hbomb_offset = 0;
5987                     pPlayer->hbomb_time = 45;
5988                     if (pPlayer->ammo_amount[HANDBOMB_WEAPON] > 0)
5989                     {
5990                         P_AddWeapon(pPlayer, HANDBOMB_WEAPON);
5991                         pPlayer->weapon_pos = WEAPON_POS_LOWER;
5992                     }
5993                     else
5994                         P_CheckWeapon(pPlayer);
5995                 }
5996                 break;
5997 
5998             case PISTOL_WEAPON__STATIC:
5999                 if ((*weaponFrame) == 1)
6000                 {
6001                     A_Shoot(pPlayer->i, SHOTSPARK1);
6002                     A_PlaySound(PISTOL_FIRE, pPlayer->i);
6003                     pPlayer->noise_radius = 8192;
6004                     P_MadeNoise(playerNum);
6005 
6006                     lastvisinc = (int32_t) totalclock+32;
6007                     pPlayer->visibility = 0;
6008                     flashColor = 255+(95<<8);
6009                     if (sectorLotag != 857)
6010                     {
6011                         pPlayer->vel.x -= sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] << 4;
6012                         pPlayer->vel.y -= sintable[fix16_to_int(pPlayer->q16ang) & 2047] << 4;
6013                     }
6014                 }
6015                 else if ((*weaponFrame) == 2 && pPlayer->ammo_amount[PISTOL_WEAPON] <= 0)
6016                 {
6017                     (*weaponFrame) = 0;
6018                     P_CheckWeapon(pPlayer);
6019                 }
6020 
6021                 if (++(*weaponFrame) >= 22)
6022                 {
6023                     if (pPlayer->ammo_amount[PISTOL_WEAPON] <= 0)
6024                     {
6025                         (*weaponFrame) = 0;
6026                         P_CheckWeapon(pPlayer);
6027                         break;
6028                     }
6029                     else if ((pPlayer->ammo_amount[PISTOL_WEAPON]%6) == 0)
6030                     {
6031                         switch ((*weaponFrame))
6032                         {
6033                         case 24:
6034                             A_PlaySound(EJECT_CLIP, pPlayer->i);
6035                             break;
6036                         case 30:
6037                             A_PlaySound(INSERT_CLIP, pPlayer->i);
6038                             break;
6039                         }
6040                     }
6041                     else
6042                         (*weaponFrame) = 38;
6043                 }
6044 
6045                 if ((*weaponFrame) == 38)
6046                 {
6047                     (*weaponFrame) = 0;
6048                     P_CheckWeapon(pPlayer);
6049                 }
6050                 break;
6051 
6052             case SHOTGUN_WEAPON__STATIC:
6053 
6054                 if (++(*weaponFrame) == 6 && pPlayer->shotgun_state[0] == 0 && pPlayer->ammo_amount[SHOTGUN_WEAPON] > 1 && TEST_SYNC_KEY(playerBits, SK_FIRE))
6055                     pPlayer->shotgun_state[1] = 1;
6056                 if ((*weaponFrame) == 4)
6057                 {
6058                     A_Shoot(pPlayer->i, SHOTGUN);
6059                     A_Shoot(pPlayer->i, SHOTGUN);
6060                     A_Shoot(pPlayer->i, SHOTGUN);
6061                     A_Shoot(pPlayer->i, SHOTGUN);
6062                     A_Shoot(pPlayer->i, SHOTGUN);
6063                     A_Shoot(pPlayer->i, SHOTGUN);
6064                     A_Shoot(pPlayer->i, SHOTGUN);
6065                     A_Shoot(pPlayer->i, SHOTGUN);
6066                     A_Shoot(pPlayer->i, SHOTGUN);
6067                     A_Shoot(pPlayer->i, SHOTGUN);
6068 
6069                     pPlayer->ammo_amount[SHOTGUN_WEAPON]--;
6070 
6071                     A_PlaySound(SHOTGUN_FIRE, pPlayer->i);
6072 
6073                     pPlayer->noise_radius = 8192;
6074                     P_MadeNoise(playerNum);
6075 
6076                     lastvisinc = (int32_t) totalclock + 32;
6077                     pPlayer->visibility = 0;
6078                     flashColor = 255+(95<<8);
6079                 }
6080 
6081                 if ((*weaponFrame) == 7)
6082                 {
6083                     if (pPlayer->shotgun_state[1])
6084                     {
6085                         A_Shoot(pPlayer->i, SHOTGUN);
6086                         A_Shoot(pPlayer->i, SHOTGUN);
6087                         A_Shoot(pPlayer->i, SHOTGUN);
6088                         A_Shoot(pPlayer->i, SHOTGUN);
6089                         A_Shoot(pPlayer->i, SHOTGUN);
6090                         A_Shoot(pPlayer->i, SHOTGUN);
6091                         A_Shoot(pPlayer->i, SHOTGUN);
6092                         A_Shoot(pPlayer->i, SHOTGUN);
6093                         A_Shoot(pPlayer->i, SHOTGUN);
6094                         A_Shoot(pPlayer->i, SHOTGUN);
6095 
6096                         pPlayer->ammo_amount[SHOTGUN_WEAPON]--;
6097 
6098                         A_PlaySound(SHOTGUN_FIRE, pPlayer->i);
6099                         if (sectorLotag != 857)
6100                         {
6101                             pPlayer->vel.x -= sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] << 5;
6102                             pPlayer->vel.y -= sintable[fix16_to_int(pPlayer->q16ang) & 2047] << 5;
6103                         }
6104                     } else if (sectorLotag != 857)
6105                     {
6106                         pPlayer->vel.x -= sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] << 4;
6107                         pPlayer->vel.y -= sintable[fix16_to_int(pPlayer->q16ang) & 2047] << 4;
6108                     }
6109                     flashColor = 255+(95<<8);
6110                 }
6111 
6112                 if (pPlayer->shotgun_state[0])
6113                 {
6114                     switch (*weaponFrame)
6115                     {
6116                     case 16:
6117                         P_CheckWeapon(pPlayer);
6118                         break;
6119                     case 17:
6120                         A_PlaySound(SHOTGUN_COCK, pPlayer->i);
6121                         break;
6122                     case 28:
6123                         *weaponFrame = 0;
6124                         pPlayer->shotgun_state[0] = 0;
6125                         pPlayer->shotgun_state[1] = 0;
6126                         break;
6127                     }
6128                 }
6129                 else if (pPlayer->shotgun_state[1])
6130                 {
6131                     switch (*weaponFrame)
6132                     {
6133                     case 26:
6134                         P_CheckWeapon(pPlayer);
6135                         break;
6136                     case 27:
6137                         A_PlaySound(SHOTGUN_COCK, pPlayer->i);
6138                         break;
6139                     case 38:
6140                         *weaponFrame = 0;
6141                         pPlayer->shotgun_state[0] = 0;
6142                         pPlayer->shotgun_state[1] = 0;
6143                         break;
6144                     }
6145                 }
6146                 else
6147                 {
6148                     switch (*weaponFrame)
6149                     {
6150                     case 16:
6151                         P_CheckWeapon(pPlayer);
6152                         *weaponFrame = 0;
6153                         pPlayer->shotgun_state[0] = 1;
6154                         pPlayer->shotgun_state[1] = 0;
6155                         break;
6156                     }
6157                 }
6158                 break;
6159 
6160             case CHAINGUN_WEAPON__STATIC:
6161                 pPlayer->q16horiz += F16(1);
6162                 pPlayer->recoil++;
6163                 if (++(*weaponFrame) <= 12)
6164                 {
6165                     if (((*weaponFrame) % 3) == 0)
6166                     {
6167                         pPlayer->ammo_amount[CHAINGUN_WEAPON]--;
6168 
6169                         if (((*weaponFrame) % 3) == 0)
6170                         {
6171                             spriteNum = A_Spawn(pPlayer->i, SHELL);
6172 
6173                             sprite[spriteNum].ang += 1024;
6174                             sprite[spriteNum].ang &= 2047;
6175                             sprite[spriteNum].xvel += 32;
6176                             sprite[spriteNum].z += (3 << 8);
6177                             A_SetSprite(spriteNum, CLIPMASK0);
6178                         }
6179 
6180                         A_PlaySound(CHAINGUN_FIRE, pPlayer->i);
6181                         A_Shoot(pPlayer->i, CHAINGUN);
6182                         pPlayer->noise_radius = 8192;
6183                         P_MadeNoise(playerNum);
6184                         lastvisinc = (int32_t) totalclock + 32;
6185                         pPlayer->visibility = 0;
6186                         flashColor = 255+(95<<8);
6187                         if (sectorLotag != 857)
6188                         {
6189                             pPlayer->vel.x -= sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] << 4;
6190                             pPlayer->vel.y -= sintable[fix16_to_int(pPlayer->q16ang) & 2047] << 4;
6191                         }
6192                         P_CheckWeapon(pPlayer);
6193 
6194                         if (!TEST_SYNC_KEY(playerBits, SK_FIRE))
6195                         {
6196                             (*weaponFrame) = 0;
6197                             break;
6198                         }
6199                     }
6200                 }
6201                 else if ((*weaponFrame) > 10)
6202                 {
6203                     if (TEST_SYNC_KEY(playerBits, SK_FIRE))
6204                     {
6205                         (*weaponFrame) = 1;
6206                     }
6207                     else
6208                     {
6209                         (*weaponFrame) = 0;
6210                     }
6211                 }
6212 
6213                 break;
6214 
6215             case GROW_WEAPON__STATIC:
6216                 if ((*weaponFrame) > 3)
6217                 {
6218                     (*weaponFrame) = 0;
6219                     if (screenpeek == playerNum)
6220                     {
6221                         pus = 1;
6222                     }
6223 
6224                     A_Shoot(pPlayer->i, GROWSPARK);
6225 
6226                     pPlayer->noise_radius = 1024;
6227                     P_MadeNoise(playerNum);
6228                     P_CheckWeapon(pPlayer);
6229                 }
6230                 else
6231                 {
6232                     (*weaponFrame)++;
6233                 }
6234                 break;
6235 
6236             case SHRINKER_WEAPON__STATIC:
6237                 if ((*weaponFrame) == 1)
6238                 {
6239                     pPlayer->ammo_amount[SHRINKER_WEAPON]--;
6240 
6241                     A_Shoot(pPlayer->i, SHRINKSPARK);
6242                     P_CheckWeapon(pPlayer);
6243                 }
6244                 if (++(*weaponFrame) > 20)
6245                     (*weaponFrame) = 0;
6246                 break;
6247 
6248             case DEVISTATOR_WEAPON__STATIC:
6249                 (*weaponFrame)++;
6250                 if ((*weaponFrame) == 2 || (*weaponFrame) == 4)
6251                 {
6252                     pPlayer->visibility = 0;
6253                     flashColor = 255 + (95 << 8);
6254                     lastvisinc = (int32_t) totalclock + 32;
6255                     A_PlaySound(CHAINGUN_FIRE, pPlayer->i);
6256                     A_Shoot(pPlayer->i, SHOTSPARK1);
6257                     pPlayer->noise_radius = 16384;
6258                     P_MadeNoise(playerNum);
6259                     pPlayer->ammo_amount[DEVISTATOR_WEAPON]--;
6260                     P_CheckWeapon(pPlayer);
6261                 }
6262                 if ((*weaponFrame) == 2)
6263                 {
6264                     pPlayer->q16ang += F16(16);
6265                 }
6266                 else if ((*weaponFrame) == 4)
6267                 {
6268                     pPlayer->q16ang -= F16(16);
6269                 }
6270                 if ((*weaponFrame) > 4)
6271                     (*weaponFrame) = 1;
6272                 if (!TEST_SYNC_KEY(playerBits, SK_FIRE))
6273                     (*weaponFrame) = 0;
6274                 break;
6275 
6276             case MOTORCYCLE_WEAPON__STATIC:
6277                 if (!RRRA) break;
6278                 (*weaponFrame)++;
6279                 if ((*weaponFrame) == 2 || (*weaponFrame) == 4)
6280                 {
6281                     pPlayer->visibility = 0;
6282                     flashColor = 255 + (95 << 8);
6283                     lastvisinc = (int32_t) totalclock + 32;
6284                     A_PlaySound(CHAINGUN_FIRE, pPlayer->i);
6285                     A_Shoot(pPlayer->i, CHAINGUN);
6286                     pPlayer->noise_radius = 16384;
6287                     P_MadeNoise(playerNum);
6288                     pPlayer->ammo_amount[MOTORCYCLE_WEAPON]--;
6289                     if (pPlayer->ammo_amount[MOTORCYCLE_WEAPON] <= 0)
6290                         *weaponFrame = 0;
6291                     else
6292                         P_CheckWeapon(pPlayer);
6293                 }
6294                 if ((*weaponFrame) == 2)
6295                 {
6296                     pPlayer->q16ang += F16(4);
6297                 }
6298                 else if ((*weaponFrame) == 4)
6299                 {
6300                     pPlayer->q16ang -= F16(4);
6301                 }
6302                 if ((*weaponFrame) > 4)
6303                     (*weaponFrame) = 1;
6304                 if (!TEST_SYNC_KEY(playerBits, SK_FIRE))
6305                     (*weaponFrame) = 0;
6306                 break;
6307 
6308             case BOAT_WEAPON__STATIC:
6309                 if (!RRRA) break;
6310                 if (*weaponFrame == 3)
6311                 {
6312                     pPlayer->moto_speed -= 20;
6313                     pPlayer->ammo_amount[BOAT_WEAPON]--;
6314                     A_Shoot(pPlayer->i, RRTILE1790);
6315                 }
6316                 (*weaponFrame)++;
6317                 if ((*weaponFrame) > 20)
6318                 {
6319                     (*weaponFrame) = 0;
6320                     P_CheckWeapon(pPlayer);
6321                 }
6322                 if (pPlayer->ammo_amount[BOAT_WEAPON] <= 0)
6323                     (*weaponFrame) = 0;
6324                 else
6325                     P_CheckWeapon(pPlayer);
6326                 break;
6327 
6328             case FREEZE_WEAPON__STATIC:
6329                 (*weaponFrame)++;
6330                 if ((*weaponFrame) >= 7 && (*weaponFrame) <= 11)
6331                     A_Shoot(pPlayer->i, FIRELASER);
6332 
6333                 if ((*weaponFrame) == 5)
6334                 {
6335                     A_PlaySound(CAT_FIRE, pPlayer->i);
6336                     pPlayer->noise_radius = 2048;
6337                     P_MadeNoise(playerNum);
6338                 }
6339                 else if ((*weaponFrame) == 9)
6340                 {
6341                     pPlayer->ammo_amount[FREEZE_WEAPON]--;
6342                     pPlayer->visibility = 0;
6343                     flashColor = 72 + (88 << 8) + (140 << 16);
6344                     lastvisinc = (int32_t) totalclock + 32;
6345                     P_CheckWeapon(pPlayer);
6346                 }
6347                 else if ((*weaponFrame) == 12)
6348                 {
6349                     pPlayer->vel.x -= sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] << 4;
6350                     pPlayer->vel.y -= sintable[fix16_to_int(pPlayer->q16ang) & 2047] << 4;
6351                     pPlayer->q16horiz += F16(20);
6352                     pPlayer->recoil += 20;
6353                 }
6354                 if ((*weaponFrame) > 20)
6355                     (*weaponFrame) = 0;
6356                 break;
6357 
6358             case TRIPBOMB_WEAPON__STATIC:
6359                 if ((*weaponFrame) == 3)
6360                 {
6361                     int Zvel;
6362                     int FwdVel;
6363 
6364                     if (playerNum == screenpeek)
6365                         pus = 1;
6366                     pPlayer->ammo_amount[TRIPBOMB_WEAPON]--;
6367                     pPlayer->gotweapon &= ~(1<<TRIPBOMB_WEAPON);
6368                     if (pPlayer->on_ground && TEST_SYNC_KEY(playerBits, SK_CROUCH) && (!RRRA || !pPlayer->on_motorcycle))
6369                     {
6370                         FwdVel = 15;
6371                         Zvel = (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
6372                     }
6373                     else
6374                     {
6375                         FwdVel = 32;
6376                         Zvel = -512 - (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
6377                     }
6378 
6379                     A_InsertSprite(pPlayer->cursectnum,
6380                                    pPlayer->pos.x+(sintable[(fix16_to_int(pPlayer->q16ang)+512)&2047]>>6),
6381                                    pPlayer->pos.y+(sintable[fix16_to_int(pPlayer->q16ang)&2047]>>6),
6382                                    pPlayer->pos.z,TRIPBOMBSPRITE,-16,9,9,
6383                                    fix16_to_int(pPlayer->q16ang),FwdVel*2,Zvel,pPlayer->i,1);
6384                 }
6385                 (*weaponFrame)++;
6386                 if ((*weaponFrame) > 20)
6387                 {
6388                     (*weaponFrame) = 0;
6389                     P_CheckWeapon(pPlayer);
6390                 }
6391                 break;
6392 
6393             case BOWLINGBALL_WEAPON__STATIC:
6394                 if ((*weaponFrame) == 30)
6395                 {
6396                     pPlayer->ammo_amount[BOWLINGBALL_WEAPON]--;
6397                     A_PlaySound(354, pPlayer->i);
6398                     A_Shoot(pPlayer->i, BOWLINGBALL);
6399                     pPlayer->noise_radius = 1024;
6400                     P_MadeNoise(playerNum);
6401                 }
6402                 if ((*weaponFrame) < 30)
6403                     P_Thrust(pPlayer, 4);
6404                 (*weaponFrame)++;
6405                 if ((*weaponFrame) > 40)
6406                 {
6407                     (*weaponFrame) = 0;
6408                     pPlayer->gotweapon &= ~(1 << BOWLINGBALL_WEAPON);
6409                     P_CheckWeapon(pPlayer);
6410                 }
6411                 break;
6412 
6413             case KNEE_WEAPON__STATIC:
6414                 if (++(*weaponFrame) == 3)
6415                     A_PlaySound(426, pPlayer->i);
6416 
6417                 if ((*weaponFrame) == 12)
6418                 {
6419                     A_Shoot(pPlayer->i, KNEE);
6420                     pPlayer->noise_radius = 1024;
6421                     P_MadeNoise(playerNum);
6422                 }
6423                 else if ((*weaponFrame) == 16)
6424                     (*weaponFrame) = 0;
6425 
6426                 if (pPlayer->wantweaponfire >= 0)
6427                     P_CheckWeapon(pPlayer);
6428                 break;
6429 
6430             case SLINGBLADE_WEAPON__STATIC:
6431                 if (!RRRA) break;
6432                 if (++(*weaponFrame) == 3)
6433                     A_PlaySound(252, pPlayer->i);
6434 
6435                 if ((*weaponFrame) == 8)
6436                 {
6437                     A_Shoot(pPlayer->i, SLINGBLADE);
6438                     pPlayer->noise_radius = 1024;
6439                     P_MadeNoise(playerNum);
6440                 }
6441                 else if ((*weaponFrame) == 16)
6442                     (*weaponFrame) = 0;
6443 
6444                 if (pPlayer->wantweaponfire >= 0)
6445                     P_CheckWeapon(pPlayer);
6446                 break;
6447 
6448             case RPG_WEAPON__STATIC:
6449                 if (++(*weaponFrame) == 4)
6450                 {
6451                     pPlayer->ammo_amount[RPG_WEAPON]--;
6452                     if (pPlayer->ammo_amount[HANDBOMB_WEAPON])
6453                         pPlayer->ammo_amount[HANDBOMB_WEAPON]--;
6454                     lastvisinc = (int32_t) totalclock + 32;
6455                     pPlayer->visibility = 0;
6456                     flashColor = 255+(95<<8);
6457                     A_Shoot(pPlayer->i, RPG);
6458                     pPlayer->noise_radius = 32768;
6459                     P_MadeNoise(playerNum);
6460                     P_CheckWeapon(pPlayer);
6461                 }
6462                 else if ((*weaponFrame) == 16)
6463                     A_PlaySound(450, pPlayer->i);
6464                 else if ((*weaponFrame) == 34)
6465                     (*weaponFrame) = 0;
6466                 break;
6467 
6468             case CHICKEN_WEAPON__STATIC:
6469                 if (!RRRA) break;
6470                 if (++(*weaponFrame) == 4)
6471                 {
6472                     pPlayer->ammo_amount[CHICKEN_WEAPON]--;
6473                     lastvisinc = (int32_t) totalclock + 32;
6474                     pPlayer->visibility = 0;
6475                     flashColor = 255+(95<<8);
6476                     A_Shoot(pPlayer->i, RPG2);
6477                     pPlayer->noise_radius = 32768;
6478                     P_MadeNoise(playerNum);
6479                     P_CheckWeapon(pPlayer);
6480                 }
6481                 else if ((*weaponFrame) == 16)
6482                     A_PlaySound(450, pPlayer->i);
6483                 else if ((*weaponFrame) == 34)
6484                     (*weaponFrame) = 0;
6485                 break;
6486             }
6487         }
6488         else if (WW2GI)
6489         {
6490             if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) == HANDBOMB_WEAPON)
6491             {
6492                 if (PWEAPON(playerNum, pPlayer->curr_weapon, HoldDelay) && ((*weaponFrame) == PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay)) && TEST_SYNC_KEY(playerBits, SK_FIRE))
6493                 {
6494                     pPlayer->rapid_fire_hold = 1;
6495                     return;
6496                 }
6497 
6498                 if (++(*weaponFrame) == PWEAPON(playerNum, pPlayer->curr_weapon, HoldDelay))
6499                 {
6500                     pPlayer->ammo_amount[pPlayer->curr_weapon]--;
6501 
6502                     int pipeBombType;
6503                     int pipeBombZvel;
6504                     int pipeBombFwdVel;
6505 
6506                     if (pPlayer->on_ground && TEST_SYNC_KEY(playerBits, SK_CROUCH))
6507                     {
6508                         pipeBombFwdVel = 15;
6509                         pipeBombZvel   = (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
6510                     }
6511                     else
6512                     {
6513                         pipeBombFwdVel = 140;
6514                         pipeBombZvel   = -512 - (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
6515                     }
6516 
6517                     int pipeSpriteNum = A_InsertSprite(pPlayer->cursectnum,
6518                                         pPlayer->pos.x+(sintable[(fix16_to_int(pPlayer->q16ang)+512)&2047]>>6),
6519                                         pPlayer->pos.y+(sintable[fix16_to_int(pPlayer->q16ang)&2047]>>6),
6520                                         pPlayer->pos.z,PWEAPON(playerNum, pPlayer->curr_weapon, Shoots),-16,9,9,
6521                                         fix16_to_int(pPlayer->q16ang),(pipeBombFwdVel+(pPlayer->hbomb_hold_delay<<5)),pipeBombZvel,pPlayer->i,1);
6522 
6523                     int pipeLifeTime     = Gv_GetVarByLabel("GRENADE_LIFETIME", NAM_GRENADE_LIFETIME, -1, playerNum);
6524                     int pipeLifeVariance = Gv_GetVarByLabel("GRENADE_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, -1, playerNum);
6525                     sprite[pipeSpriteNum].extra = pipeLifeTime
6526                                         + mulscale14(krand2(), pipeLifeVariance)
6527                                         - pipeLifeVariance;
6528 
6529                     if (pipeBombFwdVel == 15)
6530                     {
6531                         sprite[pipeSpriteNum].yvel = 3;
6532                         sprite[pipeSpriteNum].z += ZOFFSET3;
6533                     }
6534 
6535                     if (A_GetHitscanRange(pPlayer->i) < 512)
6536                     {
6537                         sprite[pipeSpriteNum].ang += 1024;
6538                         sprite[pipeSpriteNum].zvel /= 3;
6539                         sprite[pipeSpriteNum].xvel /= 3;
6540                     }
6541 
6542                     pPlayer->hbomb_on = 1;
6543                 }
6544                 else if ((*weaponFrame) < PWEAPON(playerNum, pPlayer->curr_weapon, HoldDelay) && TEST_SYNC_KEY(playerBits, SK_FIRE))
6545                     pPlayer->hbomb_hold_delay++;
6546                 else if ((*weaponFrame) > PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime))
6547                 {
6548                     (*weaponFrame) = 0;
6549                     P_CheckWeapon(pPlayer);
6550                 }
6551             }
6552             else if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) == HANDREMOTE_WEAPON)
6553             {
6554                 if (++(*weaponFrame) == PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay))
6555                 {
6556                     if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_BOMB_TRIGGER)
6557                         pPlayer->hbomb_on = 0;
6558 
6559                     if (PWEAPON(playerNum, pPlayer->curr_weapon, Shoots) != 0)
6560                     {
6561                         if (!(PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_NOVISIBLE))
6562                         {
6563                             lastvisinc = (int32_t) totalclock+32;
6564                             pPlayer->visibility = 0;
6565                         }
6566 
6567                         P_SetWeaponGamevars(playerNum, pPlayer);
6568                         A_Shoot(pPlayer->i, PWEAPON(playerNum, pPlayer->curr_weapon, Shoots));
6569                     }
6570                 }
6571 
6572                 if ((*weaponFrame) >= PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime))
6573                 {
6574                     (*weaponFrame) = 0;
6575                     if (pPlayer->ammo_amount[HANDBOMB_WEAPON] > 0)
6576                         P_AddWeapon(pPlayer, HANDBOMB_WEAPON);
6577                     else P_CheckWeapon(pPlayer);
6578                 }
6579             }
6580             else
6581             {
6582                 // the basic weapon...
6583                 (*weaponFrame)++;
6584 
6585                 if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_CHECKATRELOAD)
6586                 {
6587                     if (*weaponFrame == PWEAPON(playerNum, pPlayer->curr_weapon, Reload))
6588                         P_CheckWeapon(pPlayer);
6589                 }
6590 
6591                 if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_STANDSTILL
6592                         && *weaponFrame < (PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay)+1))
6593                 {
6594                     pPlayer->pos.z = pPlayer->opos.z;
6595                     pPlayer->vel.z = 0;
6596                 }
6597 
6598                 if (*weaponFrame == PWEAPON(playerNum, pPlayer->curr_weapon, Sound2Time))
6599                     if (PWEAPON(playerNum, pPlayer->curr_weapon, Sound2Sound) > 0)
6600                         A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, Sound2Sound),pPlayer->i);
6601 
6602                 if (*weaponFrame == PWEAPON(playerNum, pPlayer->curr_weapon, SpawnTime))
6603                     P_DoWeaponSpawn(playerNum);
6604 
6605                 if (*weaponFrame == PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay))
6606                     P_FireWeapon(playerNum);
6607 
6608                 if (*weaponFrame > PWEAPON(playerNum, pPlayer->curr_weapon, FireDelay)
6609                          && *weaponFrame < PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime))
6610                 {
6611                     if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_AUTOMATIC)
6612                     {
6613                         if (TEST_SYNC_KEY(playerBits, SK_FIRE) == 0)
6614                             *weaponFrame = PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime);
6615                         if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_FIREEVERYTHIRD)
6616                         {
6617                             if (((*(weaponFrame))%3) == 0)
6618                             {
6619                                 P_FireWeapon(playerNum);
6620                                 P_DoWeaponSpawn(playerNum);
6621                             }
6622                         }
6623                         if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_FIREEVERYOTHER)
6624                         {
6625                             P_FireWeapon(playerNum);
6626                             P_DoWeaponSpawn(playerNum);
6627                         }
6628                     }
6629                 }
6630                 else if (*weaponFrame >= PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime))
6631                 {
6632                     if (PWEAPON(playerNum, pPlayer->curr_weapon, Reload) > PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime) && pPlayer->ammo_amount[pPlayer->curr_weapon] > 0
6633                         && PWEAPON(playerNum, pPlayer->curr_weapon, Clip) && pPlayer->ammo_amount[pPlayer->curr_weapon] % PWEAPON(playerNum, pPlayer->curr_weapon, Clip) == 0)
6634                     {
6635                         int const weaponReloadTime = PWEAPON(playerNum, pPlayer->curr_weapon, Reload)
6636                                                    - PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime);
6637 
6638                         if ((*weaponFrame) == (PWEAPON(playerNum, pPlayer->curr_weapon, TotalTime)+1))
6639                         {
6640                             A_PlaySound(EJECT_CLIP, pPlayer->i);
6641                         }
6642                         else if ((*weaponFrame) ==
6643                                     (PWEAPON(playerNum, pPlayer->curr_weapon, Reload) - (weaponReloadTime / 3)))
6644                         {
6645                             A_PlaySound(INSERT_CLIP, pPlayer->i);
6646                         }
6647                         if ((*weaponFrame) >= (PWEAPON(playerNum, pPlayer->curr_weapon, Reload)))
6648                         {
6649                             *weaponFrame       = 0;
6650                         }
6651                     }
6652                     else
6653                     {
6654                         if (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_AUTOMATIC)
6655                         {
6656                             if (TEST_SYNC_KEY(playerBits, SK_FIRE))
6657                             {
6658                                 *weaponFrame =
6659                                 (PWEAPON(playerNum, pPlayer->curr_weapon, Flags) & WEAPON_RANDOMRESTART) ? 1 + (krand2() & 3) : 1;
6660                             }
6661                             else *weaponFrame = 0;
6662                         }
6663                         else *weaponFrame = 0;
6664                     }
6665                 }
6666             }
6667         }
6668         else
6669         {
6670             switch (DYNAMICWEAPONMAP(pPlayer->curr_weapon))
6671             {
6672             case HANDBOMB_WEAPON__STATIC:
6673                 if ((*weaponFrame) == 6 && TEST_SYNC_KEY(playerBits, SK_FIRE))
6674                 {
6675                     pPlayer->rapid_fire_hold = 1;
6676                     break;
6677                 }
6678 
6679                 if (++(*weaponFrame) == 12)
6680                 {
6681                     pPlayer->ammo_amount[pPlayer->curr_weapon]--;
6682 
6683                     //if (numplayers < 2 || g_netServer)
6684                     {
6685                         int pipeBombZvel;
6686                         int pipeBombFwdVel;
6687 
6688                         if (pPlayer->on_ground && TEST_SYNC_KEY(playerBits, SK_CROUCH))
6689                         {
6690                             pipeBombFwdVel = 15;
6691                             pipeBombZvel   = (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
6692                         }
6693                         else
6694                         {
6695                             pipeBombFwdVel = 140;
6696                             pipeBombZvel   = -512 - (fix16_to_int(pPlayer->q16horiz + pPlayer->q16horizoff - F16(100)) * 20);
6697                         }
6698 
6699                         int pipeSpriteNum = A_InsertSprite(pPlayer->cursectnum,
6700                                            pPlayer->pos.x+(sintable[(fix16_to_int(pPlayer->q16ang)+512)&2047]>>6),
6701                                            pPlayer->pos.y+(sintable[fix16_to_int(pPlayer->q16ang)&2047]>>6),
6702                                            pPlayer->pos.z,HEAVYHBOMB,-16,9,9,
6703                                            fix16_to_int(pPlayer->q16ang),(pipeBombFwdVel+(pPlayer->hbomb_hold_delay<<5)),pipeBombZvel,pPlayer->i,1);
6704 
6705                         if (NAM)
6706                             sprite[pipeSpriteNum].extra = mulscale(krand2(), 30, 14)+90;
6707 
6708                         if (pipeBombFwdVel == 15)
6709                         {
6710                             sprite[pipeSpriteNum].yvel = 3;
6711                             sprite[pipeSpriteNum].z += ZOFFSET3;
6712                         }
6713 
6714                         if (A_GetHitscanRange(pPlayer->i) < 512)
6715                         {
6716                             sprite[pipeSpriteNum].ang += 1024;
6717                             sprite[pipeSpriteNum].zvel /= 3;
6718                             sprite[pipeSpriteNum].xvel /= 3;
6719                         }
6720                     }
6721 
6722                     pPlayer->hbomb_on = 1;
6723                 }
6724                 else if ((*weaponFrame) < 12 && TEST_SYNC_KEY(playerBits, SK_FIRE))
6725                     pPlayer->hbomb_hold_delay++;
6726                 else if ((*weaponFrame) > 19)
6727                 {
6728                     (*weaponFrame) = 0;
6729                     if (NAM)
6730                     {
6731                         // don't change to remote when in NAM: grenades are timed
6732                         P_CheckWeapon(pPlayer);
6733                     }
6734                     else
6735                     {
6736                         pPlayer->weapon_pos = WEAPON_POS_RAISE;
6737                         pPlayer->curr_weapon = HANDREMOTE_WEAPON;
6738                         pPlayer->last_weapon = -1;
6739                     }
6740                 }
6741                 break;
6742 
6743             case HANDREMOTE_WEAPON__STATIC:
6744                 if (++(*weaponFrame) == 2)
6745                 {
6746                     pPlayer->hbomb_on = 0;
6747                 }
6748 
6749                 if ((*weaponFrame) == 10)
6750                 {
6751                     (*weaponFrame) = 0;
6752                     /// WHAT THE HELL DOES THIS DO....?????????????
6753                     int weapon = NAM ? TRIPBOMB_WEAPON : HANDBOMB_WEAPON;
6754                     if (pPlayer->ammo_amount[weapon] > 0)
6755                     {
6756                         P_AddWeapon(pPlayer, weapon);
6757                     }
6758                     else
6759                     {
6760                         P_CheckWeapon(pPlayer);
6761                     }
6762                 }
6763                 break;
6764 
6765             case PISTOL_WEAPON__STATIC:
6766                 if ((*weaponFrame) == 1)
6767                 {
6768                     A_Shoot(pPlayer->i, SHOTSPARK1);
6769                     A_PlaySound(PISTOL_FIRE, pPlayer->i);
6770                     lastvisinc = (int32_t) totalclock+32;
6771                     pPlayer->visibility = 0;
6772                     flashColor = 255+(95<<8);
6773                 }
6774                 else if ((*weaponFrame) == 2)
6775                 {
6776                     A_Spawn(pPlayer->i, SHELL);
6777                 }
6778 
6779                 if (++(*weaponFrame) >= 5)
6780                 {
6781                     if (pPlayer->ammo_amount[PISTOL_WEAPON] <= 0 || (pPlayer->ammo_amount[PISTOL_WEAPON]%(NAM ? 20 : 12)))
6782                     {
6783                         (*weaponFrame) = 0;
6784                         P_CheckWeapon(pPlayer);
6785                     }
6786                     else
6787                     {
6788                         switch ((*weaponFrame))
6789                         {
6790                         case 5:
6791                             A_PlaySound(EJECT_CLIP, pPlayer->i);
6792                             break;
6793                         case 8:
6794                             A_PlaySound(INSERT_CLIP, pPlayer->i);
6795                             break;
6796                         }
6797                     }
6798                 }
6799 
6800                 if ((*weaponFrame) == (NAM ? 50 : 27))
6801                 {
6802                     (*weaponFrame) = 0;
6803                     P_CheckWeapon(pPlayer);
6804                 }
6805                 break;
6806 
6807             case SHOTGUN_WEAPON__STATIC:
6808                 if (++(*weaponFrame) == 4)
6809                 {
6810                     A_Shoot(pPlayer->i, SHOTGUN);
6811                     A_Shoot(pPlayer->i, SHOTGUN);
6812                     A_Shoot(pPlayer->i, SHOTGUN);
6813                     A_Shoot(pPlayer->i, SHOTGUN);
6814                     A_Shoot(pPlayer->i, SHOTGUN);
6815                     A_Shoot(pPlayer->i, SHOTGUN);
6816                     A_Shoot(pPlayer->i, SHOTGUN);
6817 
6818                     pPlayer->ammo_amount[SHOTGUN_WEAPON]--;
6819 
6820                     A_PlaySound(SHOTGUN_FIRE, pPlayer->i);
6821 
6822                     lastvisinc = (int32_t) totalclock + 32;
6823                     pPlayer->visibility = 0;
6824                     flashColor = 255+(95<<8);
6825                 }
6826 
6827                 switch ((*weaponFrame))
6828                 {
6829                 case 13:
6830                     P_CheckWeapon(pPlayer);
6831                     break;
6832                 case 15:
6833                     A_PlaySound(SHOTGUN_COCK, pPlayer->i);
6834                     break;
6835                 case 17:
6836                 case 20:
6837                     pPlayer->kickback_pic++;
6838                     break;
6839                 case 24:
6840                     spriteNum = A_Spawn(pPlayer->i, SHOTGUNSHELL);
6841                     sprite[spriteNum].ang += 1024;
6842                     A_SetSprite(spriteNum, CLIPMASK0);
6843                     sprite[spriteNum].ang += 1024;
6844                     pPlayer->kickback_pic++;
6845                     break;
6846                 case 31:
6847                     (*weaponFrame) = 0;
6848                     return;
6849                 }
6850                 break;
6851 
6852             case CHAINGUN_WEAPON__STATIC:
6853                 if (++(*weaponFrame) <= 12)
6854                 {
6855                     if (((*weaponFrame) % 3) == 0)
6856                     {
6857                         pPlayer->ammo_amount[CHAINGUN_WEAPON]--;
6858 
6859                         if (((*weaponFrame) % 3) == 0)
6860                         {
6861                             spriteNum = A_Spawn(pPlayer->i, SHELL);
6862 
6863                             sprite[spriteNum].ang += 1024;
6864                             sprite[spriteNum].ang &= 2047;
6865                             sprite[spriteNum].xvel += 32;
6866                             sprite[spriteNum].z += (3 << 8);
6867                             A_SetSprite(spriteNum, CLIPMASK0);
6868                         }
6869 
6870                         A_PlaySound(CHAINGUN_FIRE, pPlayer->i);
6871                         A_Shoot(pPlayer->i, CHAINGUN);
6872                         lastvisinc = (int32_t) totalclock + 32;
6873                         pPlayer->visibility = 0;
6874                         flashColor = 255+(95<<8);
6875                         P_CheckWeapon(pPlayer);
6876 
6877                         if (!TEST_SYNC_KEY(playerBits, SK_FIRE))
6878                         {
6879                             (*weaponFrame) = 0;
6880                             break;
6881                         }
6882                     }
6883                 }
6884                 else if ((*weaponFrame) > 10)
6885                 {
6886                     if (TEST_SYNC_KEY(playerBits, SK_FIRE))
6887                     {
6888                         (*weaponFrame) = 1;
6889                     }
6890                     else
6891                     {
6892                         (*weaponFrame) = 0;
6893                     }
6894                 }
6895 
6896                 break;
6897 
6898             case GROW_WEAPON__STATIC:
6899                 if ((!NAM && (*weaponFrame) > 3) || (NAM && ++(*weaponFrame) == 3))
6900                 {
6901                     if (NAM)
6902                     {
6903                         (*weaponFrame)++;
6904                         if (pPlayer->ammo_amount[GROW_WEAPON] <= 1)
6905                             (*weaponFrame) = 0;
6906                     }
6907                     else
6908                         (*weaponFrame) = 0;
6909                     if (screenpeek == playerNum)
6910                     {
6911                         pus = 1;
6912                     }
6913 
6914                     pPlayer->ammo_amount[GROW_WEAPON]--;
6915 
6916                     A_Shoot(pPlayer->i, GROWSPARK);
6917 
6918                     pPlayer->visibility = 0;
6919                     flashColor = 216+(52<<8)+(20<<16);
6920                     lastvisinc = (int32_t) totalclock + 32;
6921                     P_CheckWeapon(pPlayer);
6922                 }
6923                 else if (!NAM)
6924                 {
6925                     (*weaponFrame)++;
6926                 }
6927                 if (NAM && (*weaponFrame) > 30)
6928                 {
6929                     // reload now...
6930                     (*weaponFrame) = 0;
6931 
6932                     pPlayer->visibility = 0;
6933                     flashColor = 216+(52<<8)+(20<<16);
6934                     lastvisinc = (int32_t) totalclock + 32;
6935                     P_CheckWeapon(pPlayer);
6936                     P_CheckWeapon(pPlayer);
6937                 }
6938                 break;
6939 
6940             case SHRINKER_WEAPON__STATIC:
6941                 if ((!NAM && (*weaponFrame) > 10) || (NAM && (*weaponFrame) == 10))
6942                 {
6943                     if (NAM)
6944                     {
6945                         // fire now, but wait for reload...
6946                         (*weaponFrame)++;
6947                     }
6948                     else
6949                         (*weaponFrame) = 0;
6950 
6951                     pPlayer->ammo_amount[SHRINKER_WEAPON]--;
6952 
6953                     A_Shoot(pPlayer->i, SHRINKER);
6954 
6955                     if (!NAM)
6956                     {
6957                         pPlayer->visibility = 0;
6958                         flashColor = 176+(252<<8)+(120<<16);
6959                         lastvisinc = (int32_t) totalclock + 32;
6960                         P_CheckWeapon(pPlayer);
6961                     }
6962                 }
6963                 else if (NAM && (*weaponFrame) > 30)
6964                 {
6965                     (*weaponFrame) = 0;
6966                     pPlayer->visibility = 0;
6967                     flashColor = 176+(252<<8)+(120<<16);
6968                     lastvisinc = (int32_t) totalclock + 32;
6969                     P_CheckWeapon(pPlayer);
6970                 }
6971                 else
6972                 {
6973                     (*weaponFrame)++;
6974                 }
6975                 break;
6976 
6977             case DEVISTATOR_WEAPON__STATIC:
6978                 if ((*weaponFrame) > 0)
6979                 {
6980                     if (++(*weaponFrame) & 1)
6981                     {
6982                         pPlayer->visibility = 0;
6983                         flashColor = 255+(95<<8);
6984                         lastvisinc = (int32_t) totalclock + 32;
6985                         A_Shoot(pPlayer->i, RPG);
6986                         pPlayer->ammo_amount[DEVISTATOR_WEAPON]--;
6987                         P_CheckWeapon(pPlayer);
6988                     }
6989                     if ((*weaponFrame) > 5)
6990                     {
6991                         (*weaponFrame) = 0;
6992                     }
6993                 }
6994                 break;
6995 
6996             case FREEZE_WEAPON__STATIC:
6997                 if ((*weaponFrame) < 4)
6998                 {
6999                     if (++(*weaponFrame) == 3)
7000                     {
7001                         pPlayer->ammo_amount[FREEZE_WEAPON]--;
7002                         pPlayer->visibility = 0;
7003                         flashColor = 72+(88<<8)+(140<<16);
7004                         lastvisinc = (int32_t) totalclock + 32;
7005                         A_Shoot(pPlayer->i, FREEZEBLAST);
7006                         P_CheckWeapon(pPlayer);
7007                     }
7008                     if (sprite[pPlayer->i].xrepeat < 32)
7009                     {
7010                         (*weaponFrame) = 0;
7011                     }
7012                 }
7013                 else
7014                 {
7015                     if (TEST_SYNC_KEY(playerBits, SK_FIRE))
7016                     {
7017                         (*weaponFrame) = 1;
7018                         A_PlaySound(CAT_FIRE, pPlayer->i);
7019                     }
7020                     else
7021                     {
7022                         (*weaponFrame) = 0;
7023                     }
7024                 }
7025                 break;
7026 
7027             case TRIPBOMB_WEAPON__STATIC:
7028                 if ((*weaponFrame) < 4)
7029                 {
7030                     pPlayer->pos.z = pPlayer->opos.z;
7031                     pPlayer->vel.z = 0;
7032                     if ((*weaponFrame) == 3)
7033                     {
7034                         A_Shoot(pPlayer->i, HANDHOLDINGLASER);
7035                     }
7036                 }
7037                 if ((*weaponFrame) == 16)
7038                 {
7039                     (*weaponFrame) = 0;
7040                     P_CheckWeapon(pPlayer);
7041                     pPlayer->weapon_pos = WEAPON_POS_LOWER;
7042                 }
7043                 else
7044                 {
7045                     (*weaponFrame)++;
7046                 }
7047                 break;
7048 
7049             case KNEE_WEAPON__STATIC:
7050                 if (++(*weaponFrame) == 7)
7051                 {
7052                     A_Shoot(pPlayer->i, KNEE);
7053                 }
7054                 else if ((*weaponFrame) == 14)
7055                 {
7056                     if (TEST_SYNC_KEY(playerBits, SK_FIRE))
7057                     {
7058                         (*weaponFrame) = 1+(krand2()&3);
7059                     }
7060                     else
7061                     {
7062                         (*weaponFrame) = 0;
7063                     }
7064                 }
7065 
7066                 if (pPlayer->wantweaponfire >= 0)
7067                 {
7068                     P_CheckWeapon(pPlayer);
7069                 }
7070                 break;
7071 
7072             case RPG_WEAPON__STATIC:
7073                 if (++(*weaponFrame) == 4)
7074                 {
7075                     pPlayer->ammo_amount[RPG_WEAPON]--;
7076                     lastvisinc = (int32_t) totalclock + 32;
7077                     pPlayer->visibility = 0;
7078                     flashColor = 255+(95<<8);
7079                     A_Shoot(pPlayer->i, RPG);
7080                     P_CheckWeapon(pPlayer);
7081                 }
7082                 else if ((*weaponFrame) == 20)
7083                 {
7084                     (*weaponFrame) = 0;
7085                 }
7086                 break;
7087             }
7088         }
7089 #ifdef POLYMER
7090         if (flashColor)
7091         {
7092             spritetype *s = &sprite[pPlayer->i];
7093             int32_t     x = ((sintable[(s->ang + 512) & 2047]) >> 7), y = ((sintable[(s->ang) & 2047]) >> 7);
7094 
7095             s->x += x;
7096             s->y += y;
7097             G_AddGameLight(0, pPlayer->i, PHEIGHT, 8192, flashColor, PR_LIGHT_PRIO_MAX_GAME);
7098             actor[pPlayer->i].lightcount = 2;
7099             s->x -= x;
7100             s->y -= y;
7101         }
7102 #endif  // POLYMER
7103     }
7104 }
7105 
P_EndLevel(void)7106 void P_EndLevel(void)
7107 {
7108     // if (REALITY)
7109     // {
7110     //     if (ud.multimode != 1 && ud.coop != 1 && dukematch_mode != 1)
7111     //         return;
7112     // }
7113     for (bssize_t TRAVERSE_CONNECT(playerNum))
7114         g_player[playerNum].ps->gm = MODE_EOL;
7115 
7116     if (ud.from_bonus)
7117     {
7118         ud.level_number   = ud.from_bonus;
7119         ud.m_level_number = ud.level_number;
7120         ud.from_bonus     = 0;
7121     }
7122     else
7123     {
7124         ud.level_number   = (++ud.level_number < MAXLEVELS) ? ud.level_number : 0;
7125         ud.m_level_number = ud.level_number;
7126     }
7127 }
7128 
P_DoFist(DukePlayer_t * pPlayer)7129 static int P_DoFist(DukePlayer_t *pPlayer)
7130 {
7131     // the fist punching NUKEBUTTON
7132 
7133     if (++(pPlayer->fist_incs) == 28)
7134     {
7135         if (ud.recstat == 1)
7136             G_CloseDemoWrite();
7137 
7138         S_PlaySound(REALITY ? 12 : PIPEBOMB_EXPLODE);
7139         P_PalFrom(pPlayer, 48, 64, 64, 64);
7140     }
7141 
7142     if (pPlayer->fist_incs > 42)
7143     {
7144         if (REALITY)
7145             pPlayer->timebeforeexit = 17;
7146         else if (pPlayer->buttonpalette && ud.from_bonus == 0)
7147         {
7148             for (bssize_t TRAVERSE_CONNECT(playerNum))
7149                 g_player[playerNum].ps->gm = MODE_EOL;
7150 
7151             ud.from_bonus = ud.level_number + 1;
7152 
7153             if ((unsigned)ud.secretlevel <= MAXLEVELS)
7154                 ud.level_number = ud.secretlevel - 1;
7155 
7156             ud.m_level_number = ud.level_number;
7157         }
7158         else
7159             P_EndLevel();
7160 
7161         pPlayer->fist_incs = 0;
7162 
7163         return 1;
7164     }
7165 
7166     return 0;
7167 }
7168 
7169 #ifdef YAX_ENABLE
getzsofslope_player(int sectNum,int playerX,int playerY,int32_t * pCeilZ,int32_t * pFloorZ)7170 void getzsofslope_player(int sectNum, int playerX, int playerY, int32_t *pCeilZ, int32_t *pFloorZ)
7171 {
7172     int didCeiling = 0;
7173 
7174     if ((sector[sectNum].ceilingstat & 512) == 0)
7175     {
7176         int const neighborSect = yax_getneighborsect(playerX, playerY, sectNum, YAX_CEILING);
7177 
7178         if (neighborSect >= 0)
7179         {
7180             *pCeilZ    = getceilzofslope(neighborSect, playerX, playerY);
7181             didCeiling = 1;
7182         }
7183     }
7184 
7185     int didFloor   = 0;
7186 
7187     if ((sector[sectNum].floorstat & 512) == 0)
7188     {
7189         int const neighborSect = yax_getneighborsect(playerX, playerY, sectNum, YAX_FLOOR);
7190 
7191         if (neighborSect >= 0)
7192         {
7193             *pFloorZ = getflorzofslope(neighborSect, playerX, playerY);
7194             didFloor = 1;
7195         }
7196     }
7197 
7198     if (!didCeiling || !didFloor)
7199     {
7200         int32_t ceilingZ, floorZ;
7201         getzsofslope(sectNum, playerX, playerY, &ceilingZ, &floorZ);
7202 
7203         if (!didCeiling)
7204             *pCeilZ = ceilingZ;
7205 
7206         if (!didFloor)
7207             *pFloorZ = floorZ;
7208     }
7209 }
7210 #endif
7211 
P_UpdatePosWhenViewingCam(DukePlayer_t * pPlayer)7212 void P_UpdatePosWhenViewingCam(DukePlayer_t *pPlayer)
7213 {
7214     int const newOwner      = pPlayer->newowner;
7215     if (!REALITY)
7216     {
7217         pPlayer->pos            = *(vec3_t *)&sprite[newOwner];
7218         pPlayer->q16ang           = fix16_from_int(SA(newOwner));
7219     }
7220     pPlayer->vel.x          = 0;
7221     pPlayer->vel.y          = 0;
7222     sprite[pPlayer->i].xvel = 0;
7223     pPlayer->look_ang       = 0;
7224     pPlayer->rotscrnang     = 0;
7225 }
7226 
P_DoWater(int const playerNum,int const playerBits,int const floorZ,int const ceilZ)7227 static void P_DoWater(int const playerNum, int const playerBits, int const floorZ, int const ceilZ)
7228 {
7229     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7230 
7231     // under water
7232     pPlayer->pycount        += 32;
7233     pPlayer->pycount        &= 2047;
7234     pPlayer->jumping_counter = 0;
7235     pPlayer->pyoff           = sintable[pPlayer->pycount] >> 7;
7236 
7237     if (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 37 : DUKE_UNDERWATER))
7238         A_PlaySound(REALITY ? 37 : DUKE_UNDERWATER, pPlayer->i);
7239 
7240     if (TEST_SYNC_KEY(playerBits, SK_JUMP) && (!RRRA || !pPlayer->on_motorcycle))
7241     {
7242         pPlayer->vel.z = max(min(-348, pPlayer->vel.z - 348), -(256 * 6));
7243     }
7244     else if ((TEST_SYNC_KEY(playerBits, SK_CROUCH) && (!RRRA || !pPlayer->on_motorcycle))
7245         || (RRRA && pPlayer->on_motorcycle))
7246     {
7247         pPlayer->vel.z = min(max(348, pPlayer->vel.z + 348), (256 * 6));
7248     }
7249     else
7250     {
7251         // normal view
7252         if (pPlayer->vel.z < 0)
7253             pPlayer->vel.z = min(0, pPlayer->vel.z + 256);
7254 
7255         if (pPlayer->vel.z > 0)
7256             pPlayer->vel.z = max(0, pPlayer->vel.z - 256);
7257     }
7258 
7259     if (pPlayer->vel.z > 2048)
7260         pPlayer->vel.z >>= 1;
7261 
7262     pPlayer->pos.z += pPlayer->vel.z;
7263 
7264     if (pPlayer->pos.z > (floorZ-(15<<8)))
7265         pPlayer->pos.z += ((floorZ-(15<<8))-pPlayer->pos.z)>>1;
7266 
7267     if (pPlayer->pos.z < ceilZ+ZOFFSET6)
7268     {
7269         pPlayer->pos.z = ceilZ+ZOFFSET6;
7270         pPlayer->vel.z = 0;
7271     }
7272 
7273     if (pPlayer->scuba_on && (krand2()&255) < 8)
7274     {
7275         int const spriteNum = A_Spawn(pPlayer->i, WATERBUBBLE);
7276         int const q16ang      = fix16_to_int(pPlayer->q16ang);
7277 
7278         sprite[spriteNum].x      += sintable[(q16ang + 512 + 64 - (g_globalRandom & 128)+(RR ? 128 : 0)) & 2047] >> 6;
7279         sprite[spriteNum].y      += sintable[(q16ang + 64 - (g_globalRandom & 128)+(RR ? 128 : 0)) & 2047] >> 6;
7280         sprite[spriteNum].xrepeat = 3;
7281         sprite[spriteNum].yrepeat = 2;
7282         sprite[spriteNum].z       = pPlayer->pos.z + ZOFFSET3;
7283         if (RR)
7284             sprite[spriteNum].cstat = 514;
7285     }
7286 }
P_DoJetpack(int const playerNum,int const playerBits,int const playerShrunk,int const sectorLotag,int const floorZ)7287 static void P_DoJetpack(int const playerNum, int const playerBits, int const playerShrunk, int const sectorLotag, int const floorZ)
7288 {
7289     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7290 
7291     pPlayer->on_ground       = 0;
7292     pPlayer->jumping_counter = 0;
7293     pPlayer->hard_landing    = 0;
7294     pPlayer->falling_counter = 0;
7295     pPlayer->pycount        += 32;
7296     pPlayer->pycount        &= 2047;
7297     pPlayer->pyoff           = sintable[pPlayer->pycount] >> 7;
7298 
7299     if (pPlayer->jetpack_on < 11)
7300     {
7301         pPlayer->jetpack_on++;
7302         pPlayer->pos.z -= (pPlayer->jetpack_on<<7); //Goin up
7303     }
7304     else if (pPlayer->jetpack_on == 11 && !A_CheckSoundPlaying(pPlayer->i, REALITY ? 39 : DUKE_JETPACK_IDLE))
7305         A_PlaySound(REALITY ? 39 : DUKE_JETPACK_IDLE, pPlayer->i);
7306 
7307     int const zAdjust = playerShrunk ? 512 : 2048;
7308 
7309     if (TEST_SYNC_KEY(playerBits, SK_JUMP))  // jumping, flying up
7310     {
7311         if (VM_OnEvent(EVENT_SOARUP, pPlayer->i, playerNum) == 0)
7312         {
7313             pPlayer->pos.z -= zAdjust;
7314             pPlayer->crack_time = 777 + (REALITY ? (krand2()&255) : 0);
7315         }
7316     }
7317 
7318     if (TEST_SYNC_KEY(playerBits, SK_CROUCH))  // crouching, flying down
7319     {
7320         if (VM_OnEvent(EVENT_SOARDOWN, pPlayer->i, playerNum) == 0)
7321         {
7322             pPlayer->pos.z += zAdjust;
7323             pPlayer->crack_time = 777 + (REALITY ? (krand2()&255) : 0);
7324         }
7325     }
7326 
7327     int const Zdiff = (playerShrunk == 0 && (sectorLotag == 0 || sectorLotag == ST_2_UNDERWATER)) ? 32 : 16;
7328 
7329     if (sectorLotag != ST_2_UNDERWATER && pPlayer->scuba_on == 1)
7330         pPlayer->scuba_on = 0;
7331 
7332     if (pPlayer->pos.z > (floorZ - (Zdiff << 8)))
7333         pPlayer->pos.z += ((floorZ - (Zdiff << 8)) - pPlayer->pos.z) >> 1;
7334 
7335     if (pPlayer->pos.z < (actor[pPlayer->i].ceilingz + (18 << 8)))
7336         pPlayer->pos.z = actor[pPlayer->i].ceilingz + (18 << 8);
7337 }
7338 
P_Dead(int const playerNum,int const sectorLotag,int const floorZ,int const ceilZ)7339 static void P_Dead(int const playerNum, int const sectorLotag, int const floorZ, int const ceilZ)
7340 {
7341     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7342     spritetype *const   pSprite = &sprite[pPlayer->i];
7343 
7344     if (ud.recstat == 1 && (!g_netServer && ud.multimode < 2))
7345         G_CloseDemoWrite();
7346 
7347     if (REALITY)
7348     {
7349         pPlayer->pals.f = 64;
7350         pPlayer->pals.r = max<int>(pPlayer->pals.r - 1, 0);
7351         pPlayer->pals.g = max<int>(pPlayer->pals.g - 1, 0);
7352         pPlayer->pals.b = max<int>(pPlayer->pals.b - 1, 0);
7353         // if (ud.multimode)
7354         //     rt_pfade = 0;
7355     }
7356 
7357     if (/*(numplayers < 2 || g_netServer) && */pPlayer->dead_flag == 0)
7358         P_FragPlayer(playerNum);
7359 
7360     if (REALITY)
7361     {
7362         Bmemcpy(&pPlayer->opos, &pPlayer->pos, sizeof(vec3_t));
7363         pPlayer->oq16ang = pPlayer->q16ang;
7364         pPlayer->opyoff = pPlayer->pyoff;
7365 
7366         pPlayer->on_warping_sector = 0;
7367         return;
7368     }
7369 
7370     if (sectorLotag == ST_2_UNDERWATER)
7371     {
7372         if (pPlayer->on_warping_sector == 0)
7373         {
7374             if (klabs(pPlayer->pos.z-floorZ) >(PHEIGHT>>1))
7375                 pPlayer->pos.z += 348;
7376         }
7377         else
7378         {
7379             pSprite->z -= 512;
7380             pSprite->zvel = -348;
7381         }
7382 
7383         clipmove((vec3_t *) pPlayer, &pPlayer->cursectnum,
7384             0, 0, 164, (4L<<8), (4L<<8), CLIPMASK0);
7385         //                        p->bobcounter += 32;
7386     }
7387 
7388     Bmemcpy(&pPlayer->opos, &pPlayer->pos, sizeof(vec3_t));
7389     pPlayer->oq16ang = pPlayer->q16ang;
7390     pPlayer->opyoff = pPlayer->pyoff;
7391 
7392     pPlayer->q16horiz = F16(100);
7393     pPlayer->q16horizoff = 0;
7394 
7395     updatesector(pPlayer->pos.x, pPlayer->pos.y, &pPlayer->cursectnum);
7396 
7397     pushmove((vec3_t *) pPlayer, &pPlayer->cursectnum, 128L, (4L<<8), (20L<<8), CLIPMASK0);
7398 
7399     if (floorZ > ceilZ + ZOFFSET2 && pSprite->pal != 1)
7400         pPlayer->rotscrnang = (pPlayer->dead_flag + ((floorZ+pPlayer->pos.z)>>7))&2047;
7401 
7402     pPlayer->on_warping_sector = 0;
7403 }
7404 
7405 
P_HandlePal(DukePlayer_t * const pPlayer)7406 static void P_HandlePal(DukePlayer_t *const pPlayer)
7407 {
7408     pPlayer->pals.f--;
7409 }
7410 
7411 extern char g_demo_legacy;
7412 
P_ProcessInput(int playerNum)7413 void P_ProcessInput(int playerNum)
7414 {
7415     if (DEER)
7416     {
7417         P_DHProcessInput(playerNum);
7418         return;
7419     }
7420     if (g_player[playerNum].playerquitflag == 0)
7421         return;
7422 
7423     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
7424     spritetype *const   pSprite = &sprite[pPlayer->i];
7425 
7426     ++pPlayer->player_par;
7427 
7428     uint32_t playerBits = g_player[playerNum].inputBits->bits;
7429 
7430     if (RR)
7431     {
7432         if (RRRA)
7433             g_canSeePlayer = 1;
7434         else
7435             g_canSeePlayer = playerNum;
7436     }
7437 
7438     if (pPlayer->cheat_phase > 0)
7439         playerBits = 0;
7440 
7441     if (RRRA)
7442     {
7443         if (pPlayer->on_motorcycle && pSprite->extra > 0)
7444         {
7445             int var64, var68, var6c, var74, var7c;
7446             int16_t var84;
7447             if (pPlayer->moto_speed < 0)
7448                 pPlayer->moto_speed = 0;
7449             if (TEST_SYNC_KEY(playerBits, SK_CROUCH))
7450             {
7451                 var64 = 1;
7452                 playerBits &= ~(1<<SK_CROUCH);
7453             }
7454             else
7455                 var64 = 0;
7456 
7457             if (TEST_SYNC_KEY(playerBits, SK_JUMP))
7458             {
7459                 var68 = 1;
7460                 playerBits &= ~(1<< SK_JUMP);
7461                 if (pPlayer->on_ground)
7462                 {
7463                     if (pPlayer->moto_speed == 0 && var64)
7464                     {
7465                         if (!A_CheckSoundPlaying(pPlayer->i, 187))
7466                             A_PlaySound(187,pPlayer->i);
7467                     }
7468                     else if (pPlayer->moto_speed == 0 && !A_CheckSoundPlaying(pPlayer->i, 214))
7469                     {
7470                         if (A_CheckSoundPlaying(pPlayer->i, 187))
7471                             S_StopEnvSound(187, pPlayer->i);
7472                         A_PlaySound(214,pPlayer->i);
7473                     }
7474                     else if (pPlayer->moto_speed >= 50 && !A_CheckSoundPlaying(pPlayer->i, 188))
7475                     {
7476                         A_PlaySound(188,pPlayer->i);
7477                     }
7478                     else if (!A_CheckSoundPlaying(pPlayer->i, 188) && !A_CheckSoundPlaying(pPlayer->i, 214))
7479                     {
7480                         A_PlaySound(188,pPlayer->i);
7481                     }
7482                 }
7483             }
7484             else
7485             {
7486                 var68 = 0;
7487                 if (A_CheckSoundPlaying(pPlayer->i, 214))
7488                 {
7489                     S_StopEnvSound(214, pPlayer->i);
7490                     if (!A_CheckSoundPlaying(pPlayer->i, 189))
7491                         A_PlaySound(189,pPlayer->i);
7492                 }
7493                 if (A_CheckSoundPlaying(pPlayer->i, 188))
7494                 {
7495                     S_StopEnvSound(188, pPlayer->i);
7496                     if (!A_CheckSoundPlaying(pPlayer->i, 189))
7497                         A_PlaySound(189, pPlayer->i);
7498                 }
7499                 if (!A_CheckSoundPlaying(pPlayer->i, 189) && !A_CheckSoundPlaying(pPlayer->i, 187))
7500                     A_PlaySound(187,pPlayer->i);
7501             }
7502             if (TEST_SYNC_KEY(playerBits, SK_AIM_UP))
7503             {
7504                 var6c = 1;
7505                 playerBits &= ~(1<<SK_AIM_UP);
7506             }
7507             else
7508                 var6c = 0;
7509             if (TEST_SYNC_KEY(playerBits, SK_AIM_DOWN))
7510             {
7511                 var74 = 1;
7512                 playerBits &= ~(1<<SK_AIM_DOWN);
7513             }
7514             else
7515             {
7516                 var74 = 0;
7517             }
7518             if (TEST_SYNC_KEY(playerBits, SK_LOOK_LEFT))
7519             {
7520                 var7c = 1;
7521                 playerBits &= ~(1<<SK_LOOK_LEFT);
7522             }
7523             else
7524             {
7525                 var7c = 0;
7526             }
7527             if (pPlayer->drink_amt > 88 && pPlayer->moto_drink == 0)
7528             {
7529                 var84 = krand2() & 63;
7530                 if (var84 == 1)
7531                     pPlayer->moto_drink = -10;
7532                 else if (var84 == 2)
7533                     pPlayer->moto_drink = 10;
7534             }
7535             else if (pPlayer->drink_amt > 99 && pPlayer->moto_drink == 0)
7536             {
7537                 var84 = krand2() & 31;
7538                 if (var84 == 1)
7539                     pPlayer->moto_drink = -20;
7540                 else if (var84 == 2)
7541                     pPlayer->moto_drink = 20;
7542             }
7543             if (pPlayer->on_ground == 1)
7544             {
7545                 if (var64 && pPlayer->moto_speed > 0)
7546                 {
7547                     if (pPlayer->moto_on_oil)
7548                         pPlayer->moto_speed -= 2;
7549                     else
7550                         pPlayer->moto_speed -= 4;
7551                     if (pPlayer->moto_speed < 0)
7552                         pPlayer->moto_speed = 0;
7553                     pPlayer->moto_bump_target = -30;
7554                     pPlayer->moto_do_bump = 1;
7555                 }
7556                 else if (var68 && !var64)
7557                 {
7558                     if (pPlayer->moto_speed < 40)
7559                     {
7560                         pPlayer->moto_bump_target = 70;
7561                         pPlayer->moto_bump_fast = 1;
7562                     }
7563                     pPlayer->moto_speed += 2;
7564                     if (pPlayer->moto_speed > 120)
7565                         pPlayer->moto_speed = 120;
7566                     if (!pPlayer->not_on_water)
7567                         if (pPlayer->moto_speed > 80)
7568                             pPlayer->moto_speed = 80;
7569                 }
7570                 else if (pPlayer->moto_speed > 0)
7571                     pPlayer->moto_speed--;
7572                 if (pPlayer->moto_do_bump && (!var64 || pPlayer->moto_speed == 0))
7573                 {
7574                     pPlayer->moto_bump_target = 0;
7575                     pPlayer->moto_do_bump = 0;
7576                 }
7577                 if (var6c && pPlayer->moto_speed <= 0 && !var64)
7578                 {
7579                     int var88;
7580                     pPlayer->moto_speed = -15;
7581                     var88 = var7c;
7582                     var7c = var74;
7583                     var74 = var88;
7584                 }
7585             }
7586             if (pPlayer->moto_speed != 0 && pPlayer->on_ground == 1)
7587             {
7588                 if (!pPlayer->moto_bump)
7589                     if ((krand2() & 3) == 2)
7590                         pPlayer->moto_bump_target = (pPlayer->moto_speed>>4)*((krand2()&7)-4);
7591                 if (var74 || pPlayer->moto_drink < 0)
7592                 {
7593                     if (pPlayer->moto_drink < 0)
7594                         pPlayer->moto_drink++;
7595                 }
7596                 else if (var7c || pPlayer->moto_drink > 0)
7597                 {
7598                     if (pPlayer->moto_drink > 0)
7599                         pPlayer->moto_drink--;
7600                 }
7601             }
7602             if (pPlayer->moto_turb)
7603             {
7604                 if (pPlayer->moto_turb <= 1)
7605                 {
7606                     pPlayer->q16horiz = F16(100);
7607                     pPlayer->moto_turb = 0;
7608                     pPlayer->moto_bump_target = 0;
7609                     pPlayer->moto_bump = 0;
7610                 }
7611                 else
7612                 {
7613                     pPlayer->q16horiz = F16(100+((krand2()&15)-7));
7614                     pPlayer->moto_turb--;
7615                     pPlayer->moto_drink = (krand2()&3)-2;
7616                 }
7617             }
7618             else if (pPlayer->moto_bump_target > pPlayer->moto_bump)
7619             {
7620                 if (pPlayer->moto_bump_fast)
7621                     pPlayer->moto_bump += 6;
7622                 else
7623                     pPlayer->moto_bump++;
7624                 if (pPlayer->moto_bump_target < pPlayer->moto_bump)
7625                     pPlayer->moto_bump = pPlayer->moto_bump_target;
7626                 pPlayer->q16horiz = F16(100+pPlayer->moto_bump/3);
7627             }
7628             else if (pPlayer->moto_bump_target < pPlayer->moto_bump)
7629             {
7630                 if (pPlayer->moto_bump_fast)
7631                     pPlayer->moto_bump -= 6;
7632                 else
7633                     pPlayer->moto_bump--;
7634                 if (pPlayer->moto_bump_target > pPlayer->moto_bump)
7635                     pPlayer->moto_bump = pPlayer->moto_bump_target;
7636                 pPlayer->q16horiz = F16(100+pPlayer->moto_bump/3);
7637             }
7638             else
7639             {
7640                 pPlayer->moto_bump_target = 0;
7641                 pPlayer->moto_bump_fast = 0;
7642             }
7643             if (pPlayer->moto_speed >= 20 && pPlayer->on_ground == 1 && (var74 || var7c))
7644             {
7645                 short var8c, var90, var94, var98;
7646                 var8c = pPlayer->moto_speed;
7647                 var90 = fix16_to_int(pPlayer->q16ang);
7648                 if (var74)
7649                     var94 = -10;
7650                 else
7651                     var94 = 10;
7652                 if (var94 < 0)
7653                     var98 = 350;
7654                 else
7655                     var98 = -350;
7656                 if (pPlayer->moto_on_mud || pPlayer->moto_on_oil || !pPlayer->not_on_water)
7657                 {
7658                     if (pPlayer->moto_on_oil)
7659                         var8c <<= 3;
7660                     else
7661                         var8c <<= 2;
7662                     if (pPlayer->moto_do_bump)
7663                     {
7664                         pPlayer->vel.x += (var8c>>5)*(sintable[(var94*-51+var90+512)&2047]<<4);
7665                         pPlayer->vel.y += (var8c>>5)*(sintable[(var94*-51+var90)&2047]<<4);
7666                         pPlayer->q16ang = F16((var90-(var98>>2))&2047);
7667                     }
7668                     else
7669                     {
7670                         pPlayer->vel.x += (var8c>>7)*(sintable[(var94*-51+var90+512)&2047]<<4);
7671                         pPlayer->vel.y += (var8c>>7)*(sintable[(var94*-51+var90)&2047]<<4);
7672                         pPlayer->q16ang = F16((var90-(var98>>6))&2047);
7673                     }
7674                     pPlayer->moto_on_mud = 0;
7675                     pPlayer->moto_on_oil = 0;
7676                 }
7677                 else
7678                 {
7679                     if (pPlayer->moto_do_bump)
7680                     {
7681                         pPlayer->vel.x += (var8c >> 5)*(sintable[(var94*-51 + var90 + 512) & 2047] << 4);
7682                         pPlayer->vel.y += (var8c>>5)*(sintable[(var94*-51+var90)&2047]<<4);
7683                         pPlayer->q16ang = F16((var90-(var98>>4))&2047);
7684                         if (!A_CheckSoundPlaying(pPlayer->i, 220))
7685                             A_PlaySound(220,pPlayer->i);
7686                     }
7687                     else
7688                     {
7689                         pPlayer->vel.x += (var8c >> 7)*(sintable[(var94*-51 + var90 + 512) & 2047] << 4);
7690                         pPlayer->vel.y += (var8c>>7)*(sintable[(var94*-51+var90)&2047]<<4);
7691                         pPlayer->q16ang = F16((var90-(var98>>7))&2047);
7692                     }
7693                 }
7694             }
7695             else if (pPlayer->moto_speed >= 20 && pPlayer->on_ground == 1 && (pPlayer->moto_on_mud || pPlayer->moto_on_oil))
7696             {
7697                 short var9c, vara0, vara4;
7698                 var9c = pPlayer->moto_speed;
7699                 vara0 = fix16_to_int(pPlayer->q16ang);
7700                 var84 = krand2()&1;
7701                 if (var84 == 0)
7702                     vara4 = -10;
7703                 else if (var84 == 1)
7704                     vara4 = 10;
7705                 if (pPlayer->moto_on_oil)
7706                     var9c *= 10;
7707                 else
7708                     var9c *= 5;
7709                 pPlayer->vel.x += (var9c>>7)*(sintable[(vara4*-51+vara0+512)&2047]<<4);
7710                 pPlayer->vel.y += (var9c>>7)*(sintable[(vara4*-51+vara0)&2047]<<4);
7711             }
7712             pPlayer->moto_on_mud = 0;
7713             pPlayer->moto_on_oil = 0;
7714         }
7715         else if (pPlayer->on_boat && pSprite->extra > 0)
7716         {
7717             int vara8, varac, varb0, varb4, varbc, varc4;
7718             int16_t varcc;
7719             if (pPlayer->not_on_water)
7720             {
7721                 if (pPlayer->moto_speed > 0)
7722                 {
7723                     if (!A_CheckSoundPlaying(pPlayer->i, 88))
7724                         A_PlaySound(88,pPlayer->i);
7725                 }
7726                 else
7727                 {
7728                     if (!A_CheckSoundPlaying(pPlayer->i, 87))
7729                         A_PlaySound(87,pPlayer->i);
7730                 }
7731             }
7732             if (pPlayer->moto_speed < 0)
7733                 pPlayer->moto_speed = 0;
7734             if (TEST_SYNC_KEY(playerBits, SK_CROUCH) && TEST_SYNC_KEY(playerBits, SK_JUMP))
7735             {
7736                 vara8 = 1;
7737                 varac = 0;
7738                 playerBits &= ~(1<<SK_JUMP);
7739                 varb0 = 0;
7740                 playerBits &= ~(1<<SK_CROUCH);
7741             }
7742             else
7743                 vara8 = 0;
7744             if (TEST_SYNC_KEY(playerBits, SK_JUMP))
7745             {
7746                 varac = 1;
7747                 playerBits &= ~(1<<SK_JUMP);
7748                 if (pPlayer->moto_speed == 0 && !A_CheckSoundPlaying(pPlayer->i, 89))
7749                 {
7750                     if (A_CheckSoundPlaying(pPlayer->i, 87))
7751                         S_StopEnvSound(pPlayer->i, 87);
7752                     A_PlaySound(89,pPlayer->i);
7753                 }
7754                 else if (pPlayer->moto_speed >= 50 && !A_CheckSoundPlaying(pPlayer->i, 88))
7755                     A_PlaySound(88,pPlayer->i);
7756                 else if (!A_CheckSoundPlaying(pPlayer->i, 88) && !A_CheckSoundPlaying(pPlayer->i, 89))
7757                     A_PlaySound(88,pPlayer->i);
7758             }
7759             else
7760             {
7761                 varac = 0;
7762                 if (A_CheckSoundPlaying(pPlayer->i, 89))
7763                 {
7764                     S_StopEnvSound(pPlayer->i, 89);
7765                     if (!A_CheckSoundPlaying(pPlayer->i, 90))
7766                         A_PlaySound(90,pPlayer->i);
7767                 }
7768                 if (A_CheckSoundPlaying(pPlayer->i, 88))
7769                 {
7770                     S_StopEnvSound(pPlayer->i, 88);
7771                     if (!A_CheckSoundPlaying(pPlayer->i, 90))
7772                         A_PlaySound(90,pPlayer->i);
7773                 }
7774                 if (!A_CheckSoundPlaying(pPlayer->i, 90) && !A_CheckSoundPlaying(pPlayer->i, 87))
7775                     A_PlaySound(87,pPlayer->i);
7776             }
7777             if (TEST_SYNC_KEY(playerBits, SK_CROUCH))
7778             {
7779                 varb0 = 1;
7780                 playerBits &= ~(1<<SK_CROUCH);
7781             }
7782             else
7783                 varb0 = 0;
7784             if (TEST_SYNC_KEY(playerBits, SK_AIM_UP))
7785             {
7786                 varb4 = 1;
7787                 playerBits &= ~(1<<SK_AIM_UP);
7788             }
7789             else varb4 = 0;
7790             if (TEST_SYNC_KEY(playerBits, SK_AIM_DOWN))
7791             {
7792                 varbc = 1;
7793                 playerBits &= ~(1<<SK_AIM_DOWN);
7794                 if (!A_CheckSoundPlaying(pPlayer->i, 91) && pPlayer->moto_speed > 30 && !pPlayer->not_on_water)
7795                     A_PlaySound(91,pPlayer->i);
7796             }
7797             else
7798             {
7799                 varbc = 0;
7800             }
7801             if (TEST_SYNC_KEY(playerBits, SK_LOOK_LEFT))
7802             {
7803                 varc4 = 1;
7804                 playerBits &= ~(1<< SK_LOOK_LEFT);
7805                 if (!A_CheckSoundPlaying(pPlayer->i, 91) && pPlayer->moto_speed > 30 && !pPlayer->not_on_water)
7806                     A_PlaySound(91,pPlayer->i);
7807             }
7808             else
7809             {
7810                 varc4 = 0;
7811             }
7812             if (!pPlayer->not_on_water)
7813             {
7814                 if (pPlayer->drink_amt > 88 && pPlayer->moto_drink == 0)
7815                 {
7816                     varcc = krand2() & 63;
7817                     if (varcc == 1)
7818                         pPlayer->moto_drink = -10;
7819                     else if (varcc == 2)
7820                         pPlayer->moto_drink = 10;
7821                 }
7822                 else if (pPlayer->drink_amt > 99 && pPlayer->moto_drink == 0)
7823                 {
7824                     varcc = krand2() & 31;
7825                     if (varcc == 1)
7826                         pPlayer->moto_drink = -20;
7827                     else if (varcc == 2)
7828                         pPlayer->moto_drink = 20;
7829                 }
7830             }
7831             if (pPlayer->on_ground == 1)
7832             {
7833                 if (vara8)
7834                 {
7835                     if (pPlayer->moto_speed <= 25)
7836                     {
7837                         pPlayer->moto_speed++;
7838                         if (!A_CheckSoundPlaying(pPlayer->i, 182))
7839                             A_PlaySound(182, pPlayer->i);
7840                     }
7841                     else
7842                     {
7843                         pPlayer->moto_speed -= 2;
7844                         if (pPlayer->moto_speed < 0)
7845                             pPlayer->moto_speed = 0;
7846                         pPlayer->moto_bump_target = 30;
7847                         pPlayer->moto_do_bump = 1;
7848                     }
7849                 }
7850                 else if (varb0 && pPlayer->moto_speed > 0)
7851                 {
7852                     pPlayer->moto_speed -= 2;
7853                     if (pPlayer->moto_speed < 0)
7854                         pPlayer->moto_speed = 0;
7855                     pPlayer->moto_bump_target = 30;
7856                     pPlayer->moto_do_bump = 1;
7857                 }
7858                 else if (varac)
7859                 {
7860                     if (pPlayer->moto_speed < 40)
7861                         if (!pPlayer->not_on_water)
7862                         {
7863                             pPlayer->moto_bump_target = -30;
7864                             pPlayer->moto_bump_fast = 1;
7865                         }
7866                     pPlayer->moto_speed++;
7867                     if (pPlayer->moto_speed > 120)
7868                         pPlayer->moto_speed = 120;
7869                 }
7870                 else if (pPlayer->moto_speed > 0)
7871                     pPlayer->moto_speed--;
7872                 if (pPlayer->moto_do_bump && (!varb0 || pPlayer->moto_speed == 0))
7873                 {
7874                     pPlayer->moto_bump_target = 0;
7875                     pPlayer->moto_do_bump = 0;
7876                 }
7877                 if (varb4 && pPlayer->moto_speed == 0 && !varb0)
7878                 {
7879                     int vard0;
7880                     if (!pPlayer->not_on_water)
7881                         pPlayer->moto_speed = -25;
7882                     else
7883                         pPlayer->moto_speed = -20;
7884                     vard0 = varc4;
7885                     varc4 = varbc;
7886                     varbc = vard0;
7887                 }
7888             }
7889             if (pPlayer->moto_speed != 0 && pPlayer->on_ground == 1)
7890             {
7891                 if (!pPlayer->moto_bump)
7892                     if ((krand2() & 15) == 14)
7893                         pPlayer->moto_bump_target = (pPlayer->moto_speed>>4)*((krand2()&3)-2);
7894                 if (varbc || pPlayer->moto_drink < 0)
7895                 {
7896                     if (pPlayer->moto_drink < 0)
7897                         pPlayer->moto_drink++;
7898                 }
7899                 else if (varc4 || pPlayer->moto_drink > 0)
7900                 {
7901                     if (pPlayer->moto_drink > 0)
7902                         pPlayer->moto_drink--;
7903                 }
7904             }
7905             if (pPlayer->moto_turb)
7906             {
7907                 if (pPlayer->moto_turb <= 1)
7908                 {
7909                     pPlayer->q16horiz = F16(100);
7910                     pPlayer->moto_turb = 0;
7911                     pPlayer->moto_bump_target = 0;
7912                     pPlayer->moto_bump = 0;
7913                 }
7914                 else
7915                 {
7916                     pPlayer->q16horiz = F16(100+((krand2()&15)-7));
7917                     pPlayer->moto_turb--;
7918                     pPlayer->moto_drink = (krand2()&3)-2;
7919                 }
7920             }
7921             else if (pPlayer->moto_bump_target > pPlayer->moto_bump)
7922             {
7923                 if (pPlayer->moto_bump_fast)
7924                     pPlayer->moto_bump += 6;
7925                 else
7926                     pPlayer->moto_bump++;
7927                 if (pPlayer->moto_bump_target < pPlayer->moto_bump)
7928                     pPlayer->moto_bump = pPlayer->moto_bump_target;
7929                 pPlayer->q16horiz = F16(100+pPlayer->moto_bump/3);
7930             }
7931             else if (pPlayer->moto_bump_target < pPlayer->moto_bump)
7932             {
7933                 if (pPlayer->moto_bump_fast)
7934                     pPlayer->moto_bump -= 6;
7935                 else
7936                     pPlayer->moto_bump--;
7937                 if (pPlayer->moto_bump_target > pPlayer->moto_bump)
7938                     pPlayer->moto_bump = pPlayer->moto_bump_target;
7939                 pPlayer->q16horiz = F16(100+pPlayer->moto_bump/3);
7940             }
7941             else
7942             {
7943                 pPlayer->moto_bump_target = 0;
7944                 pPlayer->moto_bump_fast = 0;
7945             }
7946             if (pPlayer->moto_speed > 0 && pPlayer->on_ground == 1 && (varbc || varc4))
7947             {
7948                 short vard4, vard8, vardc, vare0;
7949                 vard4 = pPlayer->moto_speed;
7950                 vard8 = fix16_to_int(pPlayer->q16ang);
7951                 if (varbc)
7952                     vardc = -10;
7953                 else
7954                     vardc = 10;
7955                 if (vardc < 0)
7956                     vare0 = 350;
7957                 else
7958                     vare0 = -350;
7959                 vard4 <<= 2;
7960                 if (pPlayer->moto_do_bump)
7961                 {
7962                     pPlayer->vel.x += (vard4>>6)*(sintable[(vardc*-51+vard8+512)&2047]<<4);
7963                     pPlayer->vel.y += (vard4>>6)*(sintable[(vardc*-51+vard8)&2047]<<4);
7964                     pPlayer->q16ang = F16((vard8-(vare0>>5))&2047);
7965                 }
7966                 else
7967                 {
7968                     pPlayer->vel.x += (vard4>>7)*(sintable[(vardc*-51+vard8+512)&2047]<<4);
7969                     pPlayer->vel.y += (vard4>>7)*(sintable[(vardc*-51+vard8)&2047]<<4);
7970                     pPlayer->q16ang = F16((vard8-(vare0>>6))&2047);
7971                 }
7972             }
7973             if (pPlayer->not_on_water)
7974                 if (pPlayer->moto_speed > 50)
7975                     pPlayer->moto_speed -= (pPlayer->moto_speed>>1);
7976         }
7977     }
7978 
7979     if (REALITY && playerBits)
7980         pPlayer->crack_time = 777 + (krand2() & 255);
7981 
7982     if (pPlayer->cursectnum == -1)
7983     {
7984         if (pSprite->extra > 0 && ud.noclip == 0)
7985         {
7986             P_QuickKill(pPlayer);
7987             A_PlaySound(REALITY ? 44 : SQUISHED, pPlayer->i);
7988         }
7989 
7990         pPlayer->cursectnum = 0;
7991     }
7992 
7993     int sectorLotag       = sector[pPlayer->cursectnum].lotag;
7994 
7995     if (RR)
7996     {
7997         if (sectorLotag == 867)
7998         {
7999             int spriteNum = headspritesect[pPlayer->cursectnum];
8000             while (spriteNum >= 0)
8001             {
8002                 int const nextSprite = nextspritesect[spriteNum];
8003                 if (sprite[spriteNum].picnum == RRTILE380)
8004                     if (sprite[spriteNum].z - ZOFFSET3 < pPlayer->pos.z)
8005                         sectorLotag = 2;
8006                 spriteNum = nextSprite;
8007             }
8008         }
8009         else if (sectorLotag == 7777)
8010             if (ud.volume_number == 1 && ud.level_number == 6)
8011                 g_lastLevel = 1;
8012 
8013         if (sectorLotag == 848 && sector[pPlayer->cursectnum].floorpicnum == WATERTILE2)
8014             sectorLotag = 1;
8015 
8016         if (sectorLotag == 857)
8017             pSprite->clipdist = 1;
8018         else
8019             pSprite->clipdist = 64;
8020     }
8021 
8022     pPlayer->spritebridge = 0;
8023     //pPlayer->sbs          = 0;
8024 
8025     int32_t floorZ, ceilZ, highZhit, lowZhit;
8026     if (!RR || pSprite->clipdist == 64)
8027         getzrange((vec3_t *)pPlayer, pPlayer->cursectnum, &ceilZ, &highZhit, &floorZ, &lowZhit, 163, CLIPMASK0);
8028     else
8029         getzrange((vec3_t *)pPlayer, pPlayer->cursectnum, &ceilZ, &highZhit, &floorZ, &lowZhit, 4, CLIPMASK0);
8030 
8031 #ifdef YAX_ENABLE
8032     getzsofslope_player(pPlayer->cursectnum, pPlayer->pos.x, pPlayer->pos.y, &pPlayer->truecz, &pPlayer->truefz);
8033 #else
8034     getzsofslope(pPlayer->cursectnum, pPlayer->pos.x, pPlayer->pos.y, &pPlayer->truecz, &pPlayer->truefz);
8035 #endif
8036     int const trueFloorZ    = pPlayer->truefz;
8037     int const trueFloorDist = klabs(pPlayer->pos.z - trueFloorZ);
8038 
8039     if ((lowZhit & 49152) == 16384 && sectorLotag == 1 && trueFloorDist > PHEIGHT + ZOFFSET2)
8040         sectorLotag = 0;
8041 
8042     actor[pPlayer->i].floorz   = floorZ;
8043     actor[pPlayer->i].ceilingz = ceilZ;
8044 
8045     pPlayer->oq16horiz            = pPlayer->q16horiz;
8046     pPlayer->oq16horizoff         = pPlayer->q16horizoff;
8047 
8048     // calculates automatic view angle for playing without a mouse
8049     if (pPlayer->aim_mode == 0 && pPlayer->on_ground && sectorLotag != ST_2_UNDERWATER
8050         && (sector[pPlayer->cursectnum].floorstat & 2))
8051     {
8052         vec2_t const adjustedPlayer = { pPlayer->pos.x + (sintable[(fix16_to_int(pPlayer->q16ang) + 512) & 2047] >> 5),
8053                                         pPlayer->pos.y + (sintable[fix16_to_int(pPlayer->q16ang) & 2047] >> 5) };
8054         int16_t curSectNum = pPlayer->cursectnum;
8055 
8056         updatesector(adjustedPlayer.x, adjustedPlayer.y, &curSectNum);
8057 
8058         if (curSectNum >= 0)
8059         {
8060             int const slopeZ = getflorzofslope(pPlayer->cursectnum, adjustedPlayer.x, adjustedPlayer.y);
8061             if ((pPlayer->cursectnum == curSectNum) ||
8062                 (klabs(getflorzofslope(curSectNum, adjustedPlayer.x, adjustedPlayer.y) - slopeZ) <= ZOFFSET6))
8063                 pPlayer->q16horizoff += fix16_from_int(mulscale16(trueFloorZ - slopeZ, 160));
8064         }
8065     }
8066 
8067     if (ud.recstat == 2 && g_demo_legacy)
8068     {
8069         int horizoff = fix16_to_int(pPlayer->q16horizoff);
8070         if (horizoff > 0)
8071             horizoff -= ((horizoff >> 3) + 1);
8072         else if (horizoff < 0)
8073             horizoff += (((-horizoff) >> 3) + 1);
8074         pPlayer->q16horizoff = F16(horizoff);
8075     }
8076     else
8077     {
8078         if (pPlayer->q16horizoff > 0)
8079         {
8080             pPlayer->q16horizoff -= ((pPlayer->q16horizoff >> 3) + fix16_one);
8081             pPlayer->q16horizoff = max(pPlayer->q16horizoff, 0);
8082         }
8083         else if (pPlayer->q16horizoff < 0)
8084         {
8085             pPlayer->q16horizoff += (((-pPlayer->q16horizoff) >> 3) + fix16_one);
8086             pPlayer->q16horizoff = min(pPlayer->q16horizoff, 0);
8087         }
8088     }
8089 
8090     if (highZhit >= 0 && (highZhit&49152) == 49152)
8091     {
8092         highZhit &= (MAXSPRITES-1);
8093 
8094         if (sprite[highZhit].statnum == STAT_ACTOR && sprite[highZhit].extra >= 0)
8095         {
8096             highZhit = 0;
8097             ceilZ    = pPlayer->truecz;
8098         }
8099         if (RR)
8100         {
8101             if (sprite[highZhit].picnum == RRTILE3587)
8102             {
8103                 if (!pPlayer->stairs)
8104                 {
8105                     pPlayer->stairs = 10;
8106                     if (TEST_SYNC_KEY(playerBits, SK_JUMP) && (!RRRA || !pPlayer->on_motorcycle))
8107                     {
8108                         highZhit = 0;
8109                         ceilZ = pPlayer->truecz;
8110                     }
8111                 }
8112                 else
8113                     pPlayer->stairs--;
8114             }
8115         }
8116     }
8117 
8118     if (lowZhit >= 0 && (lowZhit&49152) == 49152)
8119     {
8120         int spriteNum = lowZhit&(MAXSPRITES-1);
8121 
8122         if ((sprite[spriteNum].cstat&33) == 33)
8123         {
8124             sectorLotag             = 0;
8125             pPlayer->footprintcount = 0;
8126             pPlayer->spritebridge   = 1;
8127             //pPlayer->sbs            = spriteNum;
8128         }
8129         else if (!RRRA)
8130             goto check_enemy_sprite;
8131 
8132         if (RRRA)
8133         {
8134             if (pPlayer->on_motorcycle)
8135             {
8136                 if (A_CheckEnemySprite(&sprite[spriteNum]))
8137                 {
8138                     actor[spriteNum].picnum = MOTOHIT;
8139                     actor[spriteNum].extra = 2+(pPlayer->moto_speed>>1);
8140                     pPlayer->moto_speed -= pPlayer->moto_speed >> 4;
8141                 }
8142             }
8143             if (pPlayer->on_boat)
8144             {
8145                 if (A_CheckEnemySprite(&sprite[spriteNum]))
8146                 {
8147                     actor[spriteNum].picnum = MOTOHIT;
8148                     actor[spriteNum].extra = 2+(pPlayer->moto_speed>>1);
8149                     pPlayer->moto_speed -= pPlayer->moto_speed >> 4;
8150                 }
8151             }
8152             else
8153             {
8154 check_enemy_sprite:
8155                 if (A_CheckEnemySprite(&sprite[spriteNum]) && sprite[spriteNum].xrepeat > 24
8156                      && klabs(pSprite->z - sprite[spriteNum].z) < (84 << 8))
8157                 {
8158                     // TX: I think this is what makes the player slide off enemies... might
8159                     // be a good sprite flag to add later.
8160                     // Helix: there's also SLIDE_ABOVE_ENEMY.
8161                     int spriteAng = getangle(sprite[spriteNum].x - pPlayer->pos.x,
8162                                                sprite[spriteNum].y - pPlayer->pos.y);
8163                     pPlayer->vel.x -= sintable[(spriteAng + 512) & 2047] << 4;
8164                     pPlayer->vel.y -= sintable[spriteAng & 2047] << 4;
8165                 }
8166             }
8167         }
8168         if (RR)
8169         {
8170             if (sprite[spriteNum].picnum == RRTILE3587)
8171             {
8172                 if (!pPlayer->stairs)
8173                 {
8174                     pPlayer->stairs = 10;
8175                     if (TEST_SYNC_KEY(playerBits, SK_CROUCH) && (!RRRA || !pPlayer->on_motorcycle))
8176                     {
8177                         ceilZ = sprite[spriteNum].z;
8178                         highZhit = 0;
8179                         floorZ = sprite[spriteNum].z + ZOFFSET6;
8180                     }
8181                 }
8182                 else
8183                     pPlayer->stairs--;
8184             }
8185             else if (sprite[spriteNum].picnum == TOILET || sprite[spriteNum].picnum == RRTILE2121)
8186             {
8187                 if (TEST_SYNC_KEY(playerBits, SK_CROUCH) && (!RRRA || !pPlayer->on_motorcycle))
8188                 {
8189                     A_PlaySound(436, pPlayer->i);
8190                     pPlayer->last_pissed_time = 4000;
8191                     pPlayer->eat_amt = 0;
8192                 }
8193             }
8194         }
8195     }
8196 
8197     if (pSprite->extra > 0)
8198         P_IncurDamage(pPlayer);
8199     else
8200     {
8201         pSprite->extra                  = 0;
8202         pPlayer->inv_amount[GET_SHIELD] = 0;
8203     }
8204 
8205     pPlayer->last_extra = pSprite->extra;
8206     pPlayer->loogcnt    = (pPlayer->loogcnt > 0) ? pPlayer->loogcnt - 1 : 0;
8207 
8208     if (pPlayer->fist_incs && P_DoFist(pPlayer) && !RR) return;
8209 
8210     if (pPlayer->timebeforeexit > 1 && (pPlayer->last_extra > 0 || (REALITY && ud.multimode > 1)))
8211     {
8212         pPlayer->timebeforeexit--;
8213         if (REALITY && pPlayer->timebeforeexit < 19)
8214         {
8215             // rt_pfade = 1;
8216             for (bssize_t TRAVERSE_CONNECT(i))
8217             {
8218                 DukePlayer_t *const pPlayer2 = g_player[i].ps;
8219                 pPlayer2->pals.r = max<int>(pPlayer2->pals.r - 6, 0);
8220                 pPlayer2->pals.g = max<int>(pPlayer2->pals.g - 6, 0);
8221                 pPlayer2->pals.b = max<int>(pPlayer2->pals.b - 6, 0);
8222                 pPlayer2->pals.f = max<int>(pPlayer2->pals.f, 73 - pPlayer->timebeforeexit * 4);
8223             }
8224         }
8225         if (pPlayer->timebeforeexit == GAMETICSPERSEC*5)
8226         {
8227             if (!REALITY)
8228             {
8229                 FX_StopAllSounds();
8230                 S_ClearSoundLocks();
8231             }
8232 
8233             if (pPlayer->customexitsound >= 0)
8234             {
8235                 S_PlaySound(REALITY ? 156 : pPlayer->customexitsound);
8236                 P_DoQuote(QUOTE_WEREGONNAFRYYOURASS,pPlayer);
8237             }
8238         }
8239         else if (pPlayer->timebeforeexit == 1)
8240         {
8241             if (REALITY)
8242             {
8243                 FX_StopAllSounds();
8244                 S_ClearSoundLocks();
8245             }
8246             for (bssize_t TRAVERSE_CONNECT(playerNum))
8247                 g_player[playerNum].ps->gm = MODE_EOL;
8248 
8249             if (RR && ud.level_number == 6 && ud.volume_number == 0)
8250                 g_turdLevel = 1;
8251             if (!RR && ud.from_bonus)
8252             {
8253                 ud.level_number   = ud.from_bonus;
8254                 ud.m_level_number = ud.level_number;
8255                 ud.from_bonus     = 0;
8256             }
8257             else
8258             {
8259                 ud.level_number   = (++ud.level_number < MAXLEVELS) ? ud.level_number : 0;
8260                 ud.m_level_number = ud.level_number;
8261             }
8262             return;
8263         }
8264     }
8265 
8266     if (pPlayer->pals.f > 0)
8267         P_HandlePal(pPlayer);
8268     else if (REALITY)
8269     {
8270         pPlayer->pals.r = 0;
8271         pPlayer->pals.g = 0;
8272         pPlayer->pals.b = 0;
8273         // rt_pfade = 0;
8274     }
8275 
8276     if (pPlayer->fta > 0 && --pPlayer->fta == 0)
8277     {
8278         pub = pus = NUMPAGES;
8279         pPlayer->ftq = 0;
8280     }
8281 
8282     if (g_levelTextTime > 0)
8283         g_levelTextTime--;
8284 
8285     if (pSprite->extra <= 0)
8286     {
8287         P_Dead(playerNum, sectorLotag, floorZ, ceilZ);
8288         return;
8289     }
8290 
8291     if (pPlayer->transporter_hold > 0)
8292     {
8293         pPlayer->transporter_hold--;
8294         if (pPlayer->transporter_hold == 0 && pPlayer->on_warping_sector)
8295             pPlayer->transporter_hold = 2;
8296     }
8297     else if (pPlayer->transporter_hold < 0)
8298         pPlayer->transporter_hold++;
8299 
8300     if (pPlayer->newowner >= 0)
8301     {
8302         P_UpdatePosWhenViewingCam(pPlayer);
8303         P_DoCounters(playerNum);
8304 
8305         if ((WW2GI ? PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) : pPlayer->curr_weapon) == HANDREMOTE_WEAPON)
8306             P_ProcessWeapon(playerNum);
8307 
8308         return;
8309     }
8310 
8311     pPlayer->rotscrnang -= (pPlayer->rotscrnang >> 1);
8312 
8313     if (pPlayer->rotscrnang && !(pPlayer->rotscrnang >> 1))
8314         pPlayer->rotscrnang -= ksgn(pPlayer->rotscrnang);
8315 
8316     pPlayer->look_ang -= (pPlayer->look_ang >> 2);
8317 
8318     if (pPlayer->look_ang && !(pPlayer->look_ang >> 2))
8319         pPlayer->look_ang -= ksgn(pPlayer->look_ang);
8320 
8321     if (TEST_SYNC_KEY(playerBits, SK_LOOK_LEFT) && (!RRRA || !pPlayer->on_motorcycle))
8322     {
8323         // look_left
8324         if (VM_OnEvent(EVENT_LOOKLEFT,pPlayer->i,playerNum) == 0)
8325         {
8326             pPlayer->look_ang -= 152;
8327             pPlayer->rotscrnang += 24;
8328         }
8329     }
8330 
8331     if (TEST_SYNC_KEY(playerBits, SK_LOOK_RIGHT) && (!RRRA || !pPlayer->on_motorcycle))
8332     {
8333         // look_right
8334         if (VM_OnEvent(EVENT_LOOKRIGHT,pPlayer->i,playerNum) == 0)
8335         {
8336             pPlayer->look_ang += 152;
8337             pPlayer->rotscrnang -= 24;
8338         }
8339     }
8340 
8341     if (RRRA && pPlayer->sea_sick)
8342     {
8343         if (pPlayer->sea_sick < 250)
8344         {
8345             if (pPlayer->sea_sick >= 180)
8346                 pPlayer->rotscrnang += 24;
8347             else if (pPlayer->sea_sick >= 130)
8348                 pPlayer->rotscrnang -= 24;
8349             else if (pPlayer->sea_sick >= 70)
8350                 pPlayer->rotscrnang += 24;
8351             else if (pPlayer->sea_sick >= 20)
8352                 pPlayer->rotscrnang += 24;
8353         }
8354         if (pPlayer->sea_sick < 250)
8355             pPlayer->look_ang += (krand2()&255)-128;
8356     }
8357 
8358     int                  velocityModifier = TICSPERFRAME;
8359     const int16_t *const weaponFrame      = &pPlayer->kickback_pic;
8360     int                  floorZOffset     = 40;
8361     int const            playerShrunk     = (pSprite->yrepeat < (RR ? 8 : 32));
8362 
8363     if (pPlayer->on_crane >= 0)
8364         goto HORIZONLY;
8365 
8366     pPlayer->weapon_sway = (pSprite->xvel < 32 || pPlayer->on_ground == 0 || pPlayer->bobcounter == 1024)
8367                            ? (((pPlayer->weapon_sway & 2047) > (1024 + 96))
8368                            ? (pPlayer->weapon_sway - 96)
8369                            : (((pPlayer->weapon_sway & 2047) < (1024 - 96)))
8370                            ? (pPlayer->weapon_sway + 96)
8371                            : 1024)
8372                            : pPlayer->bobcounter;
8373 
8374     // NOTE: This silently wraps if the difference is too great, e.g. used to do
8375     // that when teleported by silent SE7s.
8376     pSprite->xvel = ksqrt(uhypsq(pPlayer->pos.x - pPlayer->bobpos.x, pPlayer->pos.y - pPlayer->bobpos.y));
8377 
8378     if (pPlayer->on_ground)
8379         pPlayer->bobcounter += sprite[pPlayer->i].xvel>>1;
8380 
8381     if (ud.noclip == 0 && ((uint16_t)pPlayer->cursectnum >= MAXSECTORS || sector[pPlayer->cursectnum].floorpicnum == MIRROR))
8382     {
8383         pPlayer->pos.x = pPlayer->opos.x;
8384         pPlayer->pos.y = pPlayer->opos.y;
8385     }
8386     else
8387     {
8388         pPlayer->opos.x = pPlayer->pos.x;
8389         pPlayer->opos.y = pPlayer->pos.y;
8390     }
8391 
8392     pPlayer->bobpos.x = pPlayer->pos.x;
8393     pPlayer->bobpos.y = pPlayer->pos.y;
8394     pPlayer->opos.z   = pPlayer->pos.z;
8395     pPlayer->opyoff   = pPlayer->pyoff;
8396     pPlayer->oq16ang    = pPlayer->q16ang;
8397 
8398     if (/*!REALITY && */pPlayer->one_eighty_count < 0)
8399     {
8400         pPlayer->one_eighty_count += 128;
8401         pPlayer->q16ang += F16(128);
8402     }
8403 
8404     // Shrinking code
8405 
8406     if (RR)
8407     {
8408         if (sectorLotag == 17 || (RRRA && sectorLotag == 18))
8409         {
8410             if (GetAnimationGoal(&sector[pPlayer->cursectnum].floorz) >= 0)
8411             {
8412                 if (!S_CheckSoundPlaying(pPlayer->i, 432))
8413                     A_PlaySound(432, pPlayer->i);
8414             }
8415             else
8416                 S_StopSound(432);
8417         }
8418         if (pPlayer->sea_sick_stat)
8419         {
8420             pPlayer->pycount += 32;
8421             pPlayer->pycount &= 2047;
8422             if (pPlayer->sea_sick)
8423                 pPlayer->pyoff = sintable[pPlayer->pycount]>>2;
8424             else
8425                 pPlayer->pyoff = sintable[pPlayer->pycount]>>7;
8426         }
8427     }
8428 
8429     if (sectorLotag == ST_2_UNDERWATER)
8430         P_DoWater(playerNum, playerBits, floorZ, ceilZ);
8431     else if (!RR && pPlayer->jetpack_on)
8432         P_DoJetpack(playerNum, playerBits, playerShrunk, sectorLotag, floorZ);
8433     else
8434     {
8435         pPlayer->airleft  = 15 * GAMETICSPERSEC;  // 13 seconds
8436         pPlayer->scuba_on = 0;
8437 
8438         if (sectorLotag == ST_1_ABOVE_WATER && pPlayer->spritebridge == 0)
8439         {
8440             floorZOffset = 12;
8441 
8442             if (playerShrunk == 0)
8443             {
8444                 floorZOffset      = 34;
8445                 pPlayer->pycount += 32;
8446                 pPlayer->pycount &= 2047;
8447                 pPlayer->pyoff    = sintable[pPlayer->pycount] >> 6;
8448             }
8449 
8450             if (playerShrunk == 0 && trueFloorDist <= PHEIGHT)
8451             {
8452                 if (pPlayer->on_ground == 1)
8453                 {
8454                     if (!REALITY && pPlayer->dummyplayersprite < 0)
8455                         pPlayer->dummyplayersprite = A_Spawn(pPlayer->i,PLAYERONWATER);
8456 
8457                     pPlayer->footprintcount = 6;
8458                     //sprite[pPlayer->dummyplayersprite].cstat |= 32768;
8459                     //sprite[pPlayer->dummyplayersprite].pal = sprite[pPlayer->i].pal;
8460                     pPlayer->footprintpal                  = 0;
8461                     pPlayer->footprintshade                = 0;
8462                     if (sector[pPlayer->cursectnum].floorpicnum == FLOORSLIME)
8463                     {
8464                         pPlayer->footprintpal = 8;
8465                         pPlayer->footprintshade = 0;
8466                     }
8467                     else if (RRRA && (sector[pPlayer->cursectnum].floorpicnum == RRTILE7756 || sector[pPlayer->cursectnum].floorpicnum == RRTILE7888))
8468                     {
8469                         pPlayer->footprintpal = 0;
8470                         pPlayer->footprintshade = 40;
8471                     }
8472                 }
8473             }
8474         }
8475         else if ((!RRRA || pPlayer->on_motorcycle) && pPlayer->footprintcount > 0 && pPlayer->on_ground)
8476         {
8477             if (pPlayer->cursectnum >= 0 && (sector[pPlayer->cursectnum].floorstat & 2) != 2)
8478             {
8479                 int spriteNum = -1;
8480 
8481                 for (spriteNum = headspritesect[pPlayer->cursectnum]; spriteNum >= 0; spriteNum = nextspritesect[spriteNum])
8482                 {
8483                     if (sprite[spriteNum].picnum == FOOTPRINTS || sprite[spriteNum].picnum == FOOTPRINTS2 ||
8484                         sprite[spriteNum].picnum == FOOTPRINTS3 || sprite[spriteNum].picnum == FOOTPRINTS4)
8485                     {
8486                         if (klabs(sprite[spriteNum].x - pPlayer->pos.x) < 384 &&
8487                             klabs(sprite[spriteNum].y - pPlayer->pos.y) < 384)
8488                             break;
8489                     }
8490                 }
8491 
8492                 if (spriteNum < 0)
8493                 {
8494                     pPlayer->footprintcount--;
8495                     if (pPlayer->cursectnum >= 0 && sector[pPlayer->cursectnum].lotag == 0 &&
8496                         sector[pPlayer->cursectnum].hitag == 0)
8497 #ifdef YAX_ENABLE
8498                         if (yax_getbunch(pPlayer->cursectnum, YAX_FLOOR) < 0 || (sector[pPlayer->cursectnum].floorstat & 512))
8499 #endif
8500                         {
8501                             switch (krand2() & 3)
8502                             {
8503                                 case 0: spriteNum  = A_Spawn(pPlayer->i, FOOTPRINTS); break;
8504                                 case 1: spriteNum  = A_Spawn(pPlayer->i, FOOTPRINTS2); break;
8505                                 case 2: spriteNum  = A_Spawn(pPlayer->i, FOOTPRINTS3); break;
8506                                 default: spriteNum = A_Spawn(pPlayer->i, FOOTPRINTS4); break;
8507                             }
8508                             sprite[spriteNum].pal   = pPlayer->footprintpal;
8509                             sprite[spriteNum].shade = pPlayer->footprintshade;
8510                         }
8511                 }
8512             }
8513         }
8514 
8515         if (pPlayer->pos.z < (floorZ-(floorZOffset<<8)))  //falling
8516         {
8517             // not jumping or crouching
8518 
8519             if ((!TEST_SYNC_KEY(playerBits, SK_JUMP) && !TEST_SYNC_KEY(playerBits, SK_CROUCH)) && pPlayer->on_ground &&
8520                 (sector[pPlayer->cursectnum].floorstat & 2) && pPlayer->pos.z >= (floorZ - (floorZOffset << 8) - ZOFFSET2))
8521                 pPlayer->pos.z = floorZ - (floorZOffset << 8);
8522             else
8523             {
8524                 pPlayer->on_ground = 0;
8525                 if (RRRA && (pPlayer->on_motorcycle || pPlayer->on_boat) && floorZ - (floorZOffset << 9) > pPlayer->pos.z)
8526                 {
8527                     if (pPlayer->moto_on_ground)
8528                     {
8529                         pPlayer->moto_bump_target = 80;
8530                         pPlayer->moto_bump_fast = 1;
8531                         pPlayer->vel.z -= g_spriteGravity*(pPlayer->moto_speed>>4);
8532                         pPlayer->moto_on_ground = 0;
8533                         if (A_CheckSoundPlaying(pPlayer->i, 188))
8534                             S_StopEnvSound(188, pPlayer->i);
8535                         A_PlaySound(189, pPlayer->i);
8536                     }
8537                     else
8538                     {
8539                         pPlayer->vel.z += g_spriteGravity-80+(120-pPlayer->moto_speed);
8540                         if (!A_CheckSoundPlaying(pPlayer->i, 189) && !A_CheckSoundPlaying(pPlayer->i, 190))
8541                             A_PlaySound(190, pPlayer->i);
8542                     }
8543                 }
8544                 else
8545                     pPlayer->vel.z    += (g_spriteGravity + 80);  // (TICSPERFRAME<<6);
8546 
8547                 if (pPlayer->vel.z >= (4096 + 2048))
8548                     pPlayer->vel.z = (4096 + 2048);
8549 
8550                 if (pPlayer->vel.z > 2400 && pPlayer->falling_counter < 255)
8551                 {
8552                     pPlayer->falling_counter++;
8553                     if (pPlayer->falling_counter >= 38 && pPlayer->scream_voice <= FX_Ok)
8554                     {
8555                         int32_t voice = A_PlaySound(REALITY ? 196 : DUKE_SCREAM,pPlayer->i);
8556                         if (voice <= 127)  // XXX: p->scream_voice is an int8_t
8557                             pPlayer->scream_voice = voice;
8558                     }
8559                 }
8560 
8561                 if ((pPlayer->pos.z + pPlayer->vel.z) >= (floorZ - (floorZOffset << 8)) && pPlayer->cursectnum >= 0)  // hit the ground
8562                 {
8563                     if (sector[pPlayer->cursectnum].lotag != ST_1_ABOVE_WATER)
8564                     {
8565                         if (RRRA)
8566                             pPlayer->moto_on_ground = 1;
8567                         if (pPlayer->falling_counter > 62 || (RRRA && pPlayer->falling_counter > 2 && sector[pPlayer->cursectnum].lotag == 802))
8568                             P_QuickKill(pPlayer);
8569                         else if (pPlayer->falling_counter > 9)
8570                         {
8571                             // Falling damage.
8572                             pSprite->extra -= pPlayer->falling_counter - (krand2() & 3);
8573 
8574                             if (pSprite->extra <= 0)
8575                                 A_PlaySound(REALITY ? 44 : SQUISHED, pPlayer->i);
8576                             else
8577                             {
8578                                 A_PlaySound(REALITY ? 35 : DUKE_LAND, pPlayer->i);
8579                                 A_PlaySound(REALITY ? 158 : DUKE_LAND_HURT, pPlayer->i);
8580                             }
8581 
8582                             P_PalFrom(pPlayer, 32, 16, 0, 0);
8583                         }
8584                         else if (pPlayer->vel.z > 2048)
8585                         {
8586                             if (RRRA && pPlayer->on_motorcycle)
8587                             {
8588                                 if (A_CheckSoundPlaying(pPlayer->i, 190))
8589                                     S_StopEnvSound(pPlayer->i, 190);
8590                                 A_PlaySound(191, pPlayer->i);
8591                                 pPlayer->moto_turb = 12;
8592                             }
8593                             else
8594                                 A_PlaySound(REALITY ? 35 : DUKE_LAND, pPlayer->i);
8595                         }
8596                         else if (RRRA && pPlayer->vel.z > 1024 && pPlayer->on_motorcycle)
8597                         {
8598                             A_PlaySound(DUKE_LAND, pPlayer->i);
8599                             pPlayer->moto_turb = 12;
8600                         }
8601                     }
8602                 }
8603             }
8604         }
8605         else
8606         {
8607             pPlayer->falling_counter = 0;
8608 
8609             if (pPlayer->scream_voice > FX_Ok)
8610             {
8611                 FX_StopSound(pPlayer->scream_voice);
8612                 S_Cleanup();
8613                 pPlayer->scream_voice = -1;
8614             }
8615 
8616             if ((sectorLotag != ST_1_ABOVE_WATER && sectorLotag != ST_2_UNDERWATER) &&
8617                 (pPlayer->on_ground == 0 && pPlayer->vel.z > (6144 >> 1)))
8618                 pPlayer->hard_landing = pPlayer->vel.z>>10;
8619 
8620             pPlayer->on_ground = 1;
8621 
8622             if (floorZOffset==40)
8623             {
8624                 //Smooth on the ground
8625                 int Zdiff = ((floorZ - (floorZOffset << 8)) - pPlayer->pos.z) >> 1;
8626 
8627                 if (klabs(Zdiff) < 256)
8628                     Zdiff = 0;
8629 
8630                 pPlayer->pos.z += ((klabs(Zdiff) >= 256) ? (((floorZ - (floorZOffset << 8)) - pPlayer->pos.z) >> 1) : 0);
8631                 pPlayer->vel.z -= 768;
8632 
8633                 if (pPlayer->vel.z < 0)
8634                     pPlayer->vel.z = 0;
8635             }
8636             else if (pPlayer->jumping_counter == 0)
8637             {
8638                 pPlayer->pos.z += ((floorZ - (floorZOffset << 7)) - pPlayer->pos.z) >> 1;  // Smooth on the water
8639 
8640                 if (pPlayer->on_warping_sector == 0 && pPlayer->pos.z > floorZ - ZOFFSET2)
8641                 {
8642                     pPlayer->pos.z = floorZ - ZOFFSET2;
8643                     pPlayer->vel.z >>= 1;
8644                 }
8645             }
8646 
8647             pPlayer->on_warping_sector = 0;
8648 
8649             if (TEST_SYNC_KEY(playerBits, SK_CROUCH) && (!RRRA || !pPlayer->on_motorcycle))
8650             {
8651                 // crouching
8652                 if (VM_OnEvent(EVENT_CROUCH,pPlayer->i,playerNum) == 0)
8653                 {
8654                     pPlayer->pos.z += (2048+768);
8655                     pPlayer->crack_time = 777 + (REALITY ? (krand2()&255) : 0);
8656                 }
8657             }
8658 
8659             // jumping
8660             if (!TEST_SYNC_KEY(playerBits, SK_JUMP) && (!RRRA || !pPlayer->on_motorcycle) && pPlayer->jumping_toggle == 1)
8661                 pPlayer->jumping_toggle = 0;
8662             else if (TEST_SYNC_KEY(playerBits, SK_JUMP) && (!RRRA || !pPlayer->on_motorcycle) && pPlayer->jumping_toggle == 0)
8663             {
8664                 if (pPlayer->jumping_counter == 0)
8665                     if ((floorZ-ceilZ) > (56<<8))
8666                     {
8667                         if (VM_OnEvent(EVENT_JUMP,pPlayer->i,playerNum) == 0)
8668                         {
8669                             pPlayer->jumping_counter = 1;
8670                             pPlayer->jumping_toggle = 1;
8671                         }
8672                     }
8673             }
8674 
8675             if (!RR && pPlayer->jumping_counter && !TEST_SYNC_KEY(playerBits, SK_JUMP))
8676                 pPlayer->jumping_toggle = 0;
8677         }
8678 
8679         if (pPlayer->jumping_counter)
8680         {
8681             if (!TEST_SYNC_KEY(playerBits, SK_JUMP) && (!RRRA || !pPlayer->on_motorcycle) && pPlayer->jumping_toggle == 1)
8682                 pPlayer->jumping_toggle = 0;
8683 
8684             if (pPlayer->jumping_counter < (RR ? 768 : (1024+256)))
8685             {
8686                 if (sectorLotag == ST_1_ABOVE_WATER && pPlayer->jumping_counter > 768)
8687                 {
8688                     pPlayer->jumping_counter = 0;
8689                     pPlayer->vel.z = -512;
8690                 }
8691                 else
8692                 {
8693                     pPlayer->vel.z -= (sintable[(2048-128+pPlayer->jumping_counter)&2047])/12;
8694                     pPlayer->jumping_counter += 180;
8695                     pPlayer->on_ground = 0;
8696                 }
8697             }
8698             else
8699             {
8700                 pPlayer->jumping_counter = 0;
8701                 pPlayer->vel.z = 0;
8702             }
8703         }
8704 
8705         pPlayer->pos.z += pPlayer->vel.z;
8706 
8707         if (pPlayer->pos.z < (ceilZ+ZOFFSET6))
8708         {
8709             pPlayer->jumping_counter = 0;
8710             if (pPlayer->vel.z < 0)
8711                 pPlayer->vel.x = pPlayer->vel.y = 0;
8712             pPlayer->vel.z = 128;
8713             pPlayer->pos.z = ceilZ+ZOFFSET6;
8714         }
8715     }
8716 
8717     if (pPlayer->fist_incs || pPlayer->transporter_hold > 2 || pPlayer->hard_landing || pPlayer->access_incs > 0 ||
8718         pPlayer->knee_incs > 0 || (!RR && pPlayer->curr_weapon == TRIPBOMB_WEAPON &&
8719                                    *weaponFrame > 1 && *weaponFrame < 4))
8720     {
8721         velocityModifier = 0;
8722         pPlayer->vel.x   = 0;
8723         pPlayer->vel.y   = 0;
8724     }
8725     else if (g_player[playerNum].inputBits->q16avel)            //p->ang += syncangvel * constant
8726     {
8727         fix16_t const inputAng  = g_player[playerNum].inputBits->q16avel;
8728 
8729         if (ud.recstat == 2 && g_demo_legacy)
8730             pPlayer->q16angvel = (sectorLotag == ST_2_UNDERWATER) ? ((fix16_to_int(inputAng) - (fix16_to_int(inputAng) >> 3))*fix16_from_int(ksgn(velocityModifier)))
8731                                                                : (fix16_to_int(inputAng) * fix16_from_int(ksgn(velocityModifier)));
8732         else
8733             pPlayer->q16angvel = (sectorLotag == ST_2_UNDERWATER) ? fix16_mul(inputAng - (inputAng >> 3), fix16_from_int(ksgn(velocityModifier)))
8734                                                                : fix16_mul(inputAng, fix16_from_int(ksgn(velocityModifier)));
8735         pPlayer->q16ang       += pPlayer->q16angvel;
8736         pPlayer->q16ang       &= 0x7FFFFFF;
8737         pPlayer->crack_time = 777 + (REALITY ? (krand2()&255) : 0);
8738     }
8739 
8740     if (pPlayer->spritebridge == 0)
8741     {
8742         int const floorPicnum = sector[pSprite->sectnum].floorpicnum;
8743 
8744         if (!RR && (floorPicnum == PURPLELAVA || sector[pSprite->sectnum].ceilingpicnum == PURPLELAVA))
8745         {
8746             if (pPlayer->inv_amount[GET_BOOTS] > 0)
8747             {
8748                 pPlayer->inv_amount[GET_BOOTS]--;
8749                 pPlayer->inven_icon = ICON_BOOTS;
8750                 if (pPlayer->inv_amount[GET_BOOTS] <= 0)
8751                     P_SelectNextInvItem(pPlayer);
8752             }
8753             else
8754             {
8755                 if (!A_CheckSoundPlaying(pPlayer->i,REALITY ? 168 : DUKE_LONGTERM_PAIN))
8756                     A_PlaySound(REALITY ? 168 : DUKE_LONGTERM_PAIN,pPlayer->i);
8757                 P_PalFrom(pPlayer, 32, 0, 8, 0);
8758                 pSprite->extra--;
8759             }
8760         }
8761 
8762         if (RRRA && pPlayer->on_ground && trueFloorDist <= PHEIGHT+ZOFFSET2 && (floorPicnum == RRTILE7768 || floorPicnum == RRTILE7820))
8763         {
8764             if ((krand2() & 3) == 1)
8765             {
8766                 if (pPlayer->on_motorcycle)
8767                     pSprite->extra -= 2;
8768                 else
8769                     pSprite->extra -= 4;
8770                 A_PlaySound(DUKE_LONGTERM_PAIN, pPlayer->i);
8771             }
8772         }
8773         else if (pPlayer->on_ground && trueFloorDist <= PHEIGHT+ZOFFSET2 && P_CheckFloorDamage(pPlayer, floorPicnum))
8774         {
8775             P_DoQuote(QUOTE_BOOTS_ON, pPlayer);
8776             pPlayer->inv_amount[GET_BOOTS] -= 2;
8777             if (pPlayer->inv_amount[GET_BOOTS] <= 0)
8778             {
8779                 pPlayer->inv_amount[GET_BOOTS] = 0;
8780                 P_SelectNextInvItem(pPlayer);
8781             }
8782         }
8783     }
8784 
8785     if (pPlayer->vel.x || pPlayer->vel.y || g_player[playerNum].inputBits->fvel || g_player[playerNum].inputBits->svel)
8786     {
8787         pPlayer->crack_time = 777 + (REALITY ? (krand2()&255) : 0);
8788 
8789         int const checkWalkSound = sintable[pPlayer->bobcounter & 2047] >> 12;
8790 
8791         if (RRRA)
8792         {
8793             if (pPlayer->spritebridge == 0 && pPlayer->on_ground)
8794             {
8795                 if (sectorLotag == ST_1_ABOVE_WATER)
8796                     pPlayer->not_on_water = 0;
8797                 else if (pPlayer->on_boat)
8798                 {
8799                     if (sectorLotag == 1234)
8800                         pPlayer->not_on_water = 0;
8801                     else
8802                         pPlayer->not_on_water = 1;
8803                 }
8804                 else
8805                     pPlayer->not_on_water = 1;
8806             }
8807         }
8808 
8809         if ((trueFloorDist < PHEIGHT + ZOFFSET3))
8810         {
8811             if (checkWalkSound == 1 || checkWalkSound == 3)
8812             {
8813                 if (pPlayer->spritebridge == 0 && pPlayer->walking_snd_toggle == 0 && pPlayer->on_ground)
8814                 {
8815                     switch (sectorLotag)
8816                     {
8817                         case 0:
8818                         {
8819                             int const walkPicnum = (lowZhit >= 0 && (lowZhit & 49152) == 49152)
8820                                                    ? TrackerCast(sprite[lowZhit & (MAXSPRITES - 1)].picnum)
8821                                                    : TrackerCast(sector[pPlayer->cursectnum].floorpicnum);
8822 
8823                             if (!RR)
8824                                 switch (DYNAMICTILEMAP(walkPicnum))
8825                                 {
8826                                     case PANNEL1__STATIC:
8827                                     case PANNEL2__STATIC:
8828                                         A_PlaySound(REALITY ? 36 : DUKE_WALKINDUCTS, pPlayer->i);
8829                                         pPlayer->walking_snd_toggle = 1;
8830                                         break;
8831                                 }
8832                         }
8833                         break;
8834 
8835                         case ST_1_ABOVE_WATER:
8836                             if ((krand2() & 1) == 0 && (!RRRA || (!pPlayer->on_boat && !pPlayer->on_motorcycle && sector[pPlayer->cursectnum].lotag != 321)))
8837                                 A_PlaySound(REALITY ? 33 : DUKE_ONWATER, pPlayer->i);
8838                             pPlayer->walking_snd_toggle = 1;
8839                             break;
8840                     }
8841                 }
8842             }
8843             else if (pPlayer->walking_snd_toggle > 0)
8844                 pPlayer->walking_snd_toggle--;
8845         }
8846 
8847         if (pPlayer->jetpack_on == 0 && pPlayer->inv_amount[GET_STEROIDS] > 0 && pPlayer->inv_amount[GET_STEROIDS] < 400)
8848             velocityModifier <<= 1;
8849 
8850         pPlayer->vel.x += (((g_player[playerNum].inputBits->fvel) * velocityModifier) << 6);
8851         pPlayer->vel.y += (((g_player[playerNum].inputBits->svel) * velocityModifier) << 6);
8852 
8853         int playerSpeedReduction = 0;
8854 
8855         if (!RRRA && pPlayer->on_ground && (TEST_SYNC_KEY(playerBits, SK_CROUCH)
8856                   || (*weaponFrame > 10 && pPlayer->curr_weapon == KNEE_WEAPON)))
8857             playerSpeedReduction = 0x2000;
8858         else if (sectorLotag == ST_2_UNDERWATER)
8859             playerSpeedReduction = 0x1400;
8860 
8861         pPlayer->vel.x = mulscale16(pPlayer->vel.x, pPlayer->runspeed - playerSpeedReduction);
8862         pPlayer->vel.y = mulscale16(pPlayer->vel.y, pPlayer->runspeed - playerSpeedReduction);
8863 
8864         if (RR)
8865         {
8866             if (RRRA)
8867             {
8868                 if (sector[pPlayer->cursectnum].floorpicnum == RRTILE7888)
8869                 {
8870                     if (pPlayer->on_motorcycle && pPlayer->on_ground)
8871                         pPlayer->moto_on_oil = 1;
8872                 }
8873                 else if (sector[pPlayer->cursectnum].floorpicnum == RRTILE7889)
8874                 {
8875                     if (pPlayer->on_motorcycle)
8876                     {
8877                         if (pPlayer->on_ground)
8878                             pPlayer->moto_on_mud = 1;
8879                     }
8880                     else if (pPlayer->inv_amount[GET_BOOTS] > 0)
8881                         pPlayer->inv_amount[GET_BOOTS]--;
8882                     else
8883                     {
8884                         pPlayer->vel.x = mulscale16(pPlayer->vel.x, pPlayer->runspeed);
8885                         pPlayer->vel.y = mulscale16(pPlayer->vel.y, pPlayer->runspeed);
8886                     }
8887                 }
8888             }
8889             if (sector[pPlayer->cursectnum].floorpicnum == RRTILE3073 || sector[pPlayer->cursectnum].floorpicnum == RRTILE2702)
8890             {
8891                 if (RRRA && pPlayer->on_motorcycle)
8892                 {
8893                     if (pPlayer->on_ground)
8894                     {
8895                         pPlayer->vel.x = mulscale16(pPlayer->vel.x, pPlayer->runspeed-0x1800);
8896                         pPlayer->vel.y = mulscale16(pPlayer->vel.y, pPlayer->runspeed-0x1800);
8897                     }
8898                 }
8899                 else if (pPlayer->inv_amount[GET_BOOTS] > 0)
8900                     pPlayer->inv_amount[GET_BOOTS]--;
8901                 else
8902                 {
8903                     pPlayer->vel.x = mulscale16(pPlayer->vel.x, pPlayer->runspeed-0x1800);
8904                     pPlayer->vel.y = mulscale16(pPlayer->vel.y, pPlayer->runspeed-0x1800);
8905                 }
8906             }
8907         }
8908 
8909         if (klabs(pPlayer->vel.x) < 2048 && klabs(pPlayer->vel.y) < 2048)
8910             pPlayer->vel.x = pPlayer->vel.y = 0;
8911 
8912         if (playerShrunk)
8913         {
8914             pPlayer->vel.x = mulscale16(pPlayer->vel.x, pPlayer->runspeed - (pPlayer->runspeed >> 1) + (pPlayer->runspeed >> 2));
8915             pPlayer->vel.y = mulscale16(pPlayer->vel.y, pPlayer->runspeed - (pPlayer->runspeed >> 1) + (pPlayer->runspeed >> 2));
8916         }
8917     }
8918 
8919 HORIZONLY:;
8920     int stepHeight = (sectorLotag == ST_1_ABOVE_WATER || pPlayer->spritebridge == 1) ? pPlayer->autostep_sbw : pPlayer->autostep;
8921 
8922 #ifdef EDUKE32_TOUCH_DEVICES
8923     if (TEST_SYNC_KEY(playerBits, SK_CROUCH))
8924         stepHeight = pPlayer->autostep_sbw;
8925 #endif
8926 
8927     if (ud.noclip)
8928     {
8929         pPlayer->pos.x += pPlayer->vel.x >> 14;
8930         pPlayer->pos.y += pPlayer->vel.y >> 14;
8931         updatesector(pPlayer->pos.x, pPlayer->pos.y, &pPlayer->cursectnum);
8932         changespritesect(pPlayer->i, pPlayer->cursectnum);
8933         // This makes the player view lower when shrunk.  NOTE that it can get the
8934         // view below the sector floor (and does, when on the ground).
8935         if (pPlayer->jetpack_on == 0 && sectorLotag != ST_2_UNDERWATER && sectorLotag != ST_1_ABOVE_WATER && playerShrunk)
8936             pPlayer->pos.z += ZOFFSET5;
8937         if (RRRA && pPlayer->hurt_delay2 > 0)
8938             pPlayer->hurt_delay2--;
8939     }
8940     else
8941     {
8942 #ifdef YAX_ENABLE
8943         int const playerSectNum = pPlayer->cursectnum;
8944         int16_t   ceilingBunch, floorBunch;
8945 
8946         if (playerSectNum >= 0)
8947             yax_getbunches(playerSectNum, &ceilingBunch, &floorBunch);
8948 
8949         // This updatesectorz conflicts with Duke3D's way of teleporting through water,
8950         // so make it a bit conditional... OTOH, this way we have an ugly z jump when
8951         // changing from above water to underwater
8952 
8953         if ((playerSectNum >= 0 && !(sector[playerSectNum].lotag == ST_1_ABOVE_WATER && pPlayer->on_ground && floorBunch >= 0))
8954             && ((floorBunch >= 0 && !(sector[playerSectNum].floorstat & 512))
8955                 || (ceilingBunch >= 0 && !(sector[playerSectNum].ceilingstat & 512))))
8956         {
8957             pPlayer->cursectnum += MAXSECTORS;  // skip initial z check, restored by updatesectorz
8958             updatesectorz(pPlayer->pos.x, pPlayer->pos.y, pPlayer->pos.z, &pPlayer->cursectnum);
8959         }
8960 #endif
8961         int spriteNum = clipmove((vec3_t *)pPlayer, &pPlayer->cursectnum, pPlayer->vel.x, pPlayer->vel.y, 164,
8962                                  (4L << 8), stepHeight, CLIPMASK0);
8963 
8964         // This makes the player view lower when shrunk.  NOTE that it can get the
8965         // view below the sector floor (and does, when on the ground).
8966         if (pPlayer->jetpack_on == 0 && sectorLotag != ST_2_UNDERWATER && sectorLotag != ST_1_ABOVE_WATER && playerShrunk)
8967             pPlayer->pos.z += ZOFFSET5;
8968 
8969         if (spriteNum)
8970             P_CheckTouchDamage(pPlayer, spriteNum);
8971         else if(RRRA && pPlayer->hurt_delay2 > 0)
8972             pPlayer->hurt_delay2--;
8973 
8974         if (RR)
8975         {
8976             if ((spriteNum & 49152) == 32768)
8977             {
8978                 int const wallNum = spriteNum&(MAXWALLS-1);
8979                 if (RRRA && pPlayer->on_motorcycle)
8980                 {
8981                     int16_t var104, var108, var10c;
8982                     var104 = 0;
8983                     var108 = getangle(wall[wall[wallNum].point2].x-wall[wallNum].x,wall[wall[wallNum].point2].y-wall[wallNum].y);
8984                     var10c = klabs(fix16_to_int(pPlayer->q16ang)-var108);
8985                     switch (krand2()&1)
8986                     {
8987                         case 0:
8988                             pPlayer->q16ang += F16(pPlayer->moto_speed>>1);
8989                             break;
8990                         case 1:
8991                             pPlayer->q16ang -= F16(pPlayer->moto_speed>>1);
8992                             break;
8993                     }
8994                     if (var10c >= 441 && var10c <= 581)
8995                     {
8996                         var104 = (pPlayer->moto_speed*pPlayer->moto_speed)>>8;
8997                         pPlayer->moto_speed = 0;
8998                         if (A_CheckSoundPlaying(pPlayer->i, 238) == 0)
8999                             A_PlaySound(238,pPlayer->i);
9000                     }
9001                     else if (var10c >= 311 && var10c <= 711)
9002                     {
9003                         var104 = (pPlayer->moto_speed*pPlayer->moto_speed)>>11;
9004                         pPlayer->moto_speed -= (pPlayer->moto_speed>>1)+(pPlayer->moto_speed>>2);
9005                         if (A_CheckSoundPlaying(pPlayer->i, 238) == 0)
9006                             A_PlaySound(238,pPlayer->i);
9007                     }
9008                     else if (var10c >= 111 && var10c <= 911)
9009                     {
9010                         var104 = (pPlayer->moto_speed*pPlayer->moto_speed)>>14;
9011                         pPlayer->moto_speed -= (pPlayer->moto_speed>>1);
9012                         if (A_CheckSoundPlaying(pPlayer->i, 239) == 0)
9013                             A_PlaySound(239,pPlayer->i);
9014                     }
9015                     else
9016                     {
9017                         var104 = (pPlayer->moto_speed*pPlayer->moto_speed)>>15;
9018                         pPlayer->moto_speed -= (pPlayer->moto_speed>>3);
9019                         if (A_CheckSoundPlaying(pPlayer->i, 240) == 0)
9020                             A_PlaySound(240,pPlayer->i);
9021                     }
9022                     pSprite->extra -= var104;
9023                     if (pSprite->extra <= 0)
9024                     {
9025                         A_PlaySound(SQUISHED,pPlayer->i);
9026                         P_PalFrom(pPlayer,63,63,0,0);
9027                     }
9028                     else if (var104)
9029                         A_PlaySound(DUKE_LAND_HURT,pPlayer->i);
9030                 }
9031                 else if (RRRA && pPlayer->on_boat)
9032                 {
9033                     short var114, var118;
9034                     var114 = getangle(wall[wall[wallNum].point2].x-wall[wallNum].x,wall[wall[wallNum].point2].y-wall[wallNum].y);
9035                     var118 = klabs(fix16_to_int(pPlayer->q16ang)-var114);
9036                     switch (krand2()&1)
9037                     {
9038                         case 0:
9039                             pPlayer->q16ang += F16(pPlayer->moto_speed>>2);
9040                             break;
9041                         case 1:
9042                             pPlayer->q16ang -= F16(pPlayer->moto_speed>>2);
9043                             break;
9044                     }
9045                     if (var118 >= 441 && var118 <= 581)
9046                     {
9047                         pPlayer->moto_speed = ((pPlayer->moto_speed>>1)+(pPlayer->moto_speed>>2))>>2;
9048                         if (sectorLotag == 1)
9049                             if (A_CheckSoundPlaying(pPlayer->i, 178) == 0)
9050                                 A_PlaySound(178,pPlayer->i);
9051                     }
9052                     else if (var118 >= 311 && var118 <= 711)
9053                     {
9054                         pPlayer->moto_speed -= ((pPlayer->moto_speed>>1)+(pPlayer->moto_speed>>2))>>3;
9055                         if (sectorLotag == 1)
9056                             if (A_CheckSoundPlaying(pPlayer->i, 179) == 0)
9057                                 A_PlaySound(179,pPlayer->i);
9058                     }
9059                     else if (var118 >= 111 && var118 <= 911)
9060                     {
9061                         pPlayer->moto_speed -= (pPlayer->moto_speed>>4);
9062                         if (sectorLotag == 1)
9063                             if (A_CheckSoundPlaying(pPlayer->i, 180) == 0)
9064                                 A_PlaySound(180,pPlayer->i);
9065                     }
9066                     else
9067                     {
9068                         pPlayer->moto_speed -= (pPlayer->moto_speed>>6);
9069                         if (sectorLotag == 1)
9070                             if (A_CheckSoundPlaying(pPlayer->i, 181) == 0)
9071                                 A_PlaySound(181,pPlayer->i);
9072                     }
9073                 }
9074                 else
9075                 {
9076                     if (wall[wallNum].lotag >= 40 && wall[wallNum].lotag <= 44)
9077                     {
9078                         if (wall[wallNum].lotag < 44)
9079                             G_DoFurniture(wallNum,pPlayer->cursectnum,playerNum);
9080                         pushmove(&pPlayer->pos,&pPlayer->cursectnum,172L,(4L<<8),(4L<<8),CLIPMASK0);
9081                     }
9082                 }
9083             }
9084             else if ((spriteNum & 49152) == 49152)
9085             {
9086                 spriteNum &= (MAXSPRITES-1);
9087 
9088                 if (RRRA && pPlayer->on_motorcycle)
9089                 {
9090                     if (A_CheckEnemySprite(&sprite[spriteNum]) || sprite[spriteNum].picnum == APLAYER)
9091                     {
9092                         if (sprite[spriteNum].picnum != APLAYER)
9093                         {
9094                             if (numplayers == 1)
9095                             {
9096                                 vec3_t const vect = {
9097                                     sintable[(pPlayer->tilt_status*20+fix16_to_int(pPlayer->q16ang)+512)&2047]>>8,
9098                                     sintable[(pPlayer->tilt_status*20+fix16_to_int(pPlayer->q16ang))&2047]>>8,sprite[spriteNum].zvel
9099                                 };
9100 
9101                                 A_MoveSprite(spriteNum,&vect,CLIPMASK0);
9102                             }
9103                         }
9104                         else
9105                             actor[spriteNum].owner = pPlayer->i;
9106                         actor[spriteNum].picnum = MOTOHIT;
9107                         actor[spriteNum].extra = pPlayer->moto_speed>>1;
9108                         pPlayer->moto_speed -= pPlayer->moto_speed>>2;
9109                         pPlayer->moto_turb = 6;
9110                     }
9111                     else if ((sprite[spriteNum].picnum == RRTILE2431 || sprite[spriteNum].picnum == RRTILE2443 || sprite[spriteNum].picnum == RRTILE2451 || sprite[spriteNum].picnum == RRTILE2455)
9112                         && sprite[spriteNum].picnum != ACTIVATORLOCKED && pPlayer->moto_speed > 45)
9113                     {
9114                         A_PlaySound(SQUISHED,spriteNum);
9115                         if (sprite[spriteNum].picnum == RRTILE2431 || sprite[spriteNum].picnum == RRTILE2451)
9116                         {
9117                             if (sprite[spriteNum].lotag != 0)
9118                             {
9119                                 for(bssize_t otherSprite = 0; otherSprite < MAXSPRITES; otherSprite++)
9120                                 {
9121                                     if ((sprite[otherSprite].picnum == RRTILE2431 || sprite[otherSprite].picnum == RRTILE2451) && sprite[otherSprite].pal == 4)
9122                                     {
9123                                         if (sprite[spriteNum].lotag == sprite[otherSprite].lotag)
9124                                         {
9125                                             sprite[otherSprite].xrepeat = 0;
9126                                             sprite[otherSprite].yrepeat = 0;
9127                                         }
9128                                     }
9129                                 }
9130                             }
9131                             A_DoGuts(spriteNum,RRTILE2460,12);
9132                             A_DoGuts(spriteNum,RRTILE2465,3);
9133                         }
9134                         else
9135                             A_DoGuts(spriteNum,RRTILE2465,3);
9136                         A_DoGuts(spriteNum,RRTILE2465,3);
9137                         sprite[spriteNum].xrepeat = 0;
9138                         sprite[spriteNum].yrepeat = 0;
9139                     }
9140                 }
9141                 else if (RRRA && pPlayer->on_boat)
9142                 {
9143                     if (A_CheckEnemySprite(&sprite[spriteNum]) || sprite[spriteNum].picnum == APLAYER)
9144                     {
9145                         if (sprite[spriteNum].picnum != APLAYER)
9146                         {
9147                             if (numplayers == 1)
9148                             {
9149                                 vec3_t const vect = {
9150                                     sintable[(pPlayer->tilt_status*20+fix16_to_int(pPlayer->q16ang)+512)&2047]>>9,
9151                                     sintable[(pPlayer->tilt_status*20+fix16_to_int(pPlayer->q16ang))&2047]>>9,sprite[spriteNum].zvel
9152                                 };
9153 
9154                                 A_MoveSprite(spriteNum,&vect,CLIPMASK0);
9155                             }
9156                         }
9157                         else
9158                             actor[spriteNum].owner = pPlayer->i;
9159                         actor[spriteNum].picnum = MOTOHIT;
9160                         actor[spriteNum].extra = pPlayer->moto_speed>>2;
9161                         pPlayer->moto_speed -= pPlayer->moto_speed>>2;
9162                         pPlayer->moto_turb = 6;
9163                     }
9164                 }
9165                 else if (A_CheckEnemySprite(&sprite[spriteNum]))
9166                 {
9167                     if (sprite[spriteNum].statnum != STAT_ACTOR)
9168                     {
9169                         actor[spriteNum].timetosleep = 0;
9170                         if (sprite[spriteNum].picnum == BILLYRAY)
9171                             A_PlaySound(404, spriteNum);
9172                         else
9173                             A_PlayAlertSound(spriteNum);
9174                         changespritestat(spriteNum, STAT_ACTOR);
9175                     }
9176                 }
9177                 if (sprite[spriteNum].picnum == RRTILE3410)
9178                 {
9179                     P_QuickKill(pPlayer);
9180                     A_PlaySound(446, pPlayer->i);
9181                 }
9182                 else if (RRRA && sprite[spriteNum].picnum == RRTILE2443 && sprite[spriteNum].pal == 19)
9183                 {
9184                     sprite[spriteNum].pal = 0;
9185                     pPlayer->drug_mode = 5;
9186                     pPlayer->drug_timer = (int32_t) totalclock;
9187                     sprite[pPlayer->i].extra = pPlayer->max_player_health;
9188                 }
9189             }
9190         }
9191     }
9192 
9193     if (pPlayer->jetpack_on == 0)
9194     {
9195         if (pSprite->xvel > 16)
9196         {
9197             if (sectorLotag != ST_1_ABOVE_WATER && sectorLotag != ST_2_UNDERWATER && pPlayer->on_ground && (!RRRA || !pPlayer->sea_sick_stat))
9198             {
9199                 pPlayer->pycount += 52;
9200                 pPlayer->pycount &= 2047;
9201                 pPlayer->pyoff   = klabs(pSprite->xvel * sintable[pPlayer->pycount]) / 1596;
9202             }
9203         }
9204         else if (sectorLotag != ST_2_UNDERWATER && sectorLotag != ST_1_ABOVE_WATER && (!RRRA || !pPlayer->sea_sick_stat))
9205             pPlayer->pyoff = 0;
9206     }
9207 
9208     pPlayer->pos.z += PHEIGHT;
9209     setsprite(pPlayer->i, &pPlayer->pos);
9210     pPlayer->pos.z -= PHEIGHT;
9211 
9212     if (RR)
9213     {
9214         if (sectorLotag == 800 && (!RRRA || !pPlayer->lotag800kill))
9215         {
9216             if (RRRA)
9217                 pPlayer->lotag800kill = 1;
9218             P_QuickKill(pPlayer);
9219             return;
9220         }
9221     }
9222 
9223     // ST_2_UNDERWATER
9224     if (pPlayer->cursectnum >= 0 && sectorLotag < 3)
9225     {
9226         usectortype const *pSector = (usectortype *)&sector[pPlayer->cursectnum];
9227 
9228         // TRAIN_SECTOR_TO_SE_INDEX
9229         if ((!ud.noclip && pSector->lotag == ST_31_TWO_WAY_TRAIN) &&
9230             ((unsigned)pSector->hitag < MAXSPRITES && sprite[pSector->hitag].xvel && actor[pSector->hitag].t_data[0] == 0))
9231         {
9232             P_QuickKill(pPlayer);
9233             return;
9234         }
9235     }
9236 
9237     if ((pPlayer->cursectnum >= 0 && trueFloorDist < PHEIGHT && pPlayer->on_ground && sectorLotag != ST_1_ABOVE_WATER &&
9238          playerShrunk == 0 && sector[pPlayer->cursectnum].lotag == ST_1_ABOVE_WATER) && (!A_CheckSoundPlaying(pPlayer->i, REALITY ? 33 : DUKE_ONWATER)))
9239         if (!RRRA || (!pPlayer->on_boat && !pPlayer->on_motorcycle && sector[pPlayer->cursectnum].lotag != 321))
9240             A_PlaySound(REALITY ? 33 : DUKE_ONWATER, pPlayer->i);
9241 
9242     if (pPlayer->cursectnum >= 0 && pPlayer->cursectnum != pSprite->sectnum)
9243         changespritesect(pPlayer->i, pPlayer->cursectnum);
9244 
9245     if (pPlayer->cursectnum >= 0 && ud.noclip == 0)
9246     {
9247         int const squishPlayer = (pushmove((vec3_t *)pPlayer, &pPlayer->cursectnum, (!RR || pSprite->clipdist == 64) ? 164 : 16, (4L << 8), (4L << 8), CLIPMASK0) < 0 &&
9248                                  A_GetFurthestAngle(pPlayer->i, 8) < 512);
9249 
9250         if (squishPlayer || klabs(actor[pPlayer->i].floorz-actor[pPlayer->i].ceilingz) < (48<<8))
9251         {
9252             if (!(sector[pSprite->sectnum].lotag & 0x8000u) &&
9253                 (isanunderoperator(sector[pSprite->sectnum].lotag) || isanearoperator(sector[pSprite->sectnum].lotag)))
9254                 G_ActivateBySector(pSprite->sectnum, pPlayer->i);
9255 
9256             if (squishPlayer)
9257             {
9258                 P_QuickKill(pPlayer);
9259                 return;
9260             }
9261         }
9262         else if (klabs(floorZ - ceilZ) < ZOFFSET5 && isanunderoperator(sector[pPlayer->cursectnum].lotag))
9263             G_ActivateBySector(pPlayer->cursectnum, pPlayer->i);
9264 
9265         if (RR && sector[pPlayer->cursectnum].ceilingz > (sector[pPlayer->cursectnum].floorz-ZOFFSET4))
9266         {
9267             P_QuickKill(pPlayer);
9268             return;
9269         }
9270     }
9271 
9272     int centerHoriz = 0;
9273 
9274     if (TEST_SYNC_KEY(playerBits, SK_CENTER_VIEW) || pPlayer->hard_landing)
9275         if (VM_OnEvent(EVENT_RETURNTOCENTER, pPlayer->i,playerNum) == 0)
9276             pPlayer->return_to_center = 9;
9277 
9278     if (TEST_SYNC_KEY(playerBits, SK_LOOK_UP))
9279     {
9280         if (VM_OnEvent(EVENT_LOOKUP, pPlayer->i, playerNum) == 0)
9281         {
9282             pPlayer->return_to_center = 9;
9283             pPlayer->q16horiz += fix16_from_int(12<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
9284             centerHoriz++;
9285         }
9286     }
9287     else if (TEST_SYNC_KEY(playerBits, SK_LOOK_DOWN))
9288     {
9289         if (VM_OnEvent(EVENT_LOOKDOWN,pPlayer->i,playerNum) == 0)
9290         {
9291             pPlayer->return_to_center = 9;
9292             pPlayer->q16horiz -= fix16_from_int(12<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
9293             centerHoriz++;
9294         }
9295     }
9296     else if (TEST_SYNC_KEY(playerBits, SK_AIM_UP) && (!RRRA || !pPlayer->on_motorcycle))
9297     {
9298         if (VM_OnEvent(EVENT_AIMUP,pPlayer->i,playerNum) == 0)
9299         {
9300             pPlayer->q16horiz += fix16_from_int(6<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
9301             centerHoriz++;
9302         }
9303     }
9304     else if (TEST_SYNC_KEY(playerBits, SK_AIM_DOWN) && (!RRRA || !pPlayer->on_motorcycle))
9305     {
9306         if (VM_OnEvent(EVENT_AIMDOWN,pPlayer->i,playerNum) == 0)
9307         {
9308             pPlayer->q16horiz -= fix16_from_int(6<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
9309             centerHoriz++;
9310         }
9311     }
9312     if (RR && pPlayer->recoil && *weaponFrame == 0)
9313     {
9314         int delta = pPlayer->recoil >> 1;
9315         if (!delta) delta++;
9316         pPlayer->recoil -= delta;
9317         pPlayer->q16horiz -= F16(delta);
9318     }
9319     else if (pPlayer->return_to_center > 0 && !TEST_SYNC_KEY(playerBits, SK_LOOK_UP) && !TEST_SYNC_KEY(playerBits, SK_LOOK_DOWN))
9320     {
9321         pPlayer->return_to_center--;
9322         if (ud.recstat == 2 && g_demo_legacy)
9323             pPlayer->q16horiz += F16(33-fix16_to_int(pPlayer->q16horiz) / 3);
9324         else
9325             pPlayer->q16horiz += F16(33)-fix16_div(pPlayer->q16horiz, F16(3));
9326         centerHoriz++;
9327     }
9328 
9329     if (REALITY)
9330     {
9331         if (pPlayer->dn64_370 > 0)
9332         {
9333             pPlayer->dn64_370 -= max(pPlayer->dn64_370/3, 1);
9334         }
9335         else if (pPlayer->dn64_370 < 0)
9336         {
9337             pPlayer->dn64_370 -= min(pPlayer->dn64_370/3, -1);
9338         }
9339     }
9340 
9341     if (pPlayer->hard_landing > 0)
9342     {
9343         pPlayer->hard_landing--;
9344         pPlayer->q16horiz -= fix16_from_int(pPlayer->hard_landing<<4);
9345     }
9346 
9347     const fix16_t horiz_max = REALITY ? F16(228) : F16(HORIZ_MAX);
9348     const fix16_t horiz_min = REALITY ? F16(-28) : F16(HORIZ_MIN);
9349     pPlayer->q16horiz = fix16_clamp(pPlayer->q16horiz + ((ud.recstat == 2 && g_demo_legacy && !pPlayer->aim_mode) ? 0 : g_player[playerNum].inputBits->q16horz), horiz_min, horiz_max);
9350 
9351     if (ud.recstat == 2 && g_demo_legacy) centerHoriz = !pPlayer->aim_mode;
9352 
9353     if (centerHoriz && (!RR || !pPlayer->recoil))
9354     {
9355         if (pPlayer->q16horiz > F16(95) && pPlayer->q16horiz < F16(105)) pPlayer->q16horiz = F16(100);
9356         if (pPlayer->q16horizoff > F16(-5) && pPlayer->q16horizoff < F16(5)) pPlayer->q16horizoff = 0;
9357     }
9358 
9359     //Shooting code/changes
9360 
9361     if (pPlayer->show_empty_weapon > 0)
9362     {
9363         --pPlayer->show_empty_weapon;
9364 
9365         if (!RR && pPlayer->show_empty_weapon == 0)
9366         {
9367             if (pPlayer->last_full_weapon == GROW_WEAPON)
9368                 pPlayer->subweapon |= (1 << GROW_WEAPON);
9369             else if (pPlayer->last_full_weapon == SHRINKER_WEAPON)
9370                 pPlayer->subweapon &= ~(1 << GROW_WEAPON);
9371 
9372             P_AddWeapon(pPlayer, pPlayer->last_full_weapon);
9373             return;
9374         }
9375     }
9376 
9377     if (RR && pPlayer->show_empty_weapon == 1)
9378     {
9379         P_AddWeapon(pPlayer, pPlayer->last_full_weapon);
9380         return;
9381     }
9382 
9383     if (pPlayer->knee_incs > 0)
9384     {
9385         pPlayer->q16horiz -= F16(48);
9386         pPlayer->return_to_center = 9;
9387 
9388         if (++pPlayer->knee_incs > 15)
9389         {
9390             pPlayer->knee_incs      = 0;
9391             pPlayer->holster_weapon = 0;
9392             pPlayer->weapon_pos     = klabs(pPlayer->weapon_pos);
9393 
9394             if (pPlayer->actorsqu >= 0 && sprite[pPlayer->actorsqu].statnum != MAXSTATUS &&
9395                 dist(&sprite[pPlayer->i], &sprite[pPlayer->actorsqu]) < 1400)
9396             {
9397                 A_DoGuts(pPlayer->actorsqu, JIBS6, 7);
9398                 A_Spawn(pPlayer->actorsqu, BLOODPOOL);
9399                 A_PlaySound(REALITY ? 44 : SQUISHED, pPlayer->actorsqu);
9400                 switch (DYNAMICTILEMAP(sprite[pPlayer->actorsqu].picnum))
9401                 {
9402                     case FEM1__STATIC:
9403                     case FEM2__STATIC:
9404                     case FEM3__STATIC:
9405                     case FEM4__STATIC:
9406                     case FEM5__STATIC:
9407                     case FEM6__STATIC:
9408                     case FEM7__STATIC:
9409                     case FEM8__STATIC:
9410                     case FEM9__STATIC:
9411                     case PODFEM1__STATIC:
9412                         if (RR)
9413                             break;
9414                         fallthrough__;
9415                     case FEM10__STATIC:
9416                     case NAKED1__STATIC:
9417                     case STATUE__STATIC:
9418                         if (sprite[pPlayer->actorsqu].yvel)
9419                             G_OperateRespawns(sprite[pPlayer->actorsqu].yvel);
9420                         A_DeleteSprite(pPlayer->actorsqu);
9421                         break;
9422                     case APLAYER__STATIC:
9423                     {
9424                         int playerSquished = P_Get(pPlayer->actorsqu);
9425                         P_QuickKill(g_player[playerSquished].ps);
9426                         g_player[playerSquished].ps->frag_ps = playerNum;
9427                         break;
9428                     }
9429                     default:
9430                         if (A_CheckEnemySprite(&sprite[pPlayer->actorsqu]))
9431                             P_AddKills(pPlayer, 1);
9432                         A_DeleteSprite(pPlayer->actorsqu);
9433                         break;
9434                 }
9435             }
9436             pPlayer->actorsqu = -1;
9437         }
9438         else if (pPlayer->actorsqu >= 0)
9439             pPlayer->q16ang += fix16_from_int(
9440             G_GetAngleDelta(fix16_to_int(pPlayer->q16ang),
9441                             getangle(sprite[pPlayer->actorsqu].x - pPlayer->pos.x, sprite[pPlayer->actorsqu].y - pPlayer->pos.y))
9442             >> 2);
9443     }
9444 
9445     if (P_DoCounters(playerNum))
9446         return;
9447 
9448     switch (pPlayer->weapon_pos)
9449     {
9450         case WEAPON_POS_LOWER:
9451             if (pPlayer->last_weapon >= 0)
9452             {
9453                 pPlayer->weapon_pos  = WEAPON_POS_RAISE;
9454                 pPlayer->last_weapon = -1;
9455             }
9456             else if (pPlayer->holster_weapon == 0)
9457                 pPlayer->weapon_pos = WEAPON_POS_RAISE;
9458             break;
9459         case 0: break;
9460         default: pPlayer->weapon_pos--; break;
9461     }
9462 
9463     P_ProcessWeapon(playerNum);
9464 }
9465 
P_DHProcessInput(int playerNum)9466 void P_DHProcessInput(int playerNum)
9467 {
9468     if (g_player[playerNum].playerquitflag == 0)
9469         return;
9470 
9471     DukePlayer_t *const pPlayer = g_player[playerNum].ps;
9472     spritetype *const   pSprite = &sprite[pPlayer->i];
9473 
9474     ++pPlayer->player_par;
9475 
9476     uint32_t playerBits = g_player[playerNum].inputBits->bits;
9477 
9478     pSprite->cstat = 0;
9479 
9480     if (pPlayer->cheat_phase > 0)
9481         playerBits = 0;
9482 
9483     if (pPlayer->cursectnum == -1)
9484     {
9485         return;
9486     }
9487 
9488     int sectorLotag       = sector[pPlayer->cursectnum].lotag;
9489 
9490     pSprite->clipdist = 64;
9491 
9492     pPlayer->spritebridge = 0;
9493     //pPlayer->sbs          = 0;
9494 
9495     int32_t floorZ, ceilZ, highZhit, lowZhit;
9496     getzrange((vec3_t *)pPlayer, pPlayer->cursectnum, &ceilZ, &highZhit, &floorZ, &lowZhit, 163, CLIPMASK0);
9497 
9498 #ifdef YAX_ENABLE
9499     getzsofslope_player(pPlayer->cursectnum, pPlayer->pos.x, pPlayer->pos.y, &pPlayer->truecz, &pPlayer->truefz);
9500 #else
9501     getzsofslope(pPlayer->cursectnum, pPlayer->pos.x, pPlayer->pos.y, &pPlayer->truecz, &pPlayer->truefz);
9502 #endif
9503     int const trueFloorZ    = pPlayer->truefz;
9504     int const trueFloorDist = klabs(pPlayer->pos.z - trueFloorZ);
9505 
9506     if ((lowZhit & 49152) == 16384 && sectorLotag == 1 && trueFloorDist > PHEIGHT + ZOFFSET2)
9507         sectorLotag = 0;
9508 
9509     actor[pPlayer->i].floorz   = floorZ;
9510     actor[pPlayer->i].ceilingz = ceilZ;
9511 
9512     pPlayer->oq16horiz            = pPlayer->q16horiz;
9513     pPlayer->oq16horizoff         = pPlayer->q16horizoff;
9514 
9515     if (ud.recstat == 2 && g_demo_legacy)
9516     {
9517         int horizoff = fix16_to_int(pPlayer->q16horizoff);
9518         if (horizoff > 0)
9519             horizoff -= ((horizoff >> 3) + 1);
9520         else if (horizoff < 0)
9521             horizoff += (((-horizoff) >> 3) + 1);
9522         pPlayer->q16horizoff = F16(horizoff);
9523     }
9524     else
9525     {
9526         if (pPlayer->q16horizoff > 0)
9527         {
9528             pPlayer->q16horizoff -= ((pPlayer->q16horizoff >> 3) + fix16_one);
9529             pPlayer->q16horizoff = max(pPlayer->q16horizoff, 0);
9530         }
9531         else if (pPlayer->q16horizoff < 0)
9532         {
9533             pPlayer->q16horizoff += (((-pPlayer->q16horizoff) >> 3) + fix16_one);
9534             pPlayer->q16horizoff = min(pPlayer->q16horizoff, 0);
9535         }
9536     }
9537 
9538     if (highZhit >= 0 && (highZhit&49152) == 49152)
9539     {
9540         highZhit &= (MAXSPRITES-1);
9541 
9542         if (sprite[highZhit].statnum == STAT_ACTOR && sprite[highZhit].extra >= 0)
9543         {
9544             highZhit = 0;
9545             ceilZ    = pPlayer->truecz;
9546         }
9547     }
9548 
9549     if (lowZhit >= 0 && (lowZhit&49152) == 49152)
9550     {
9551         int spriteNum = lowZhit&(MAXSPRITES-1);
9552 
9553         if ((sprite[spriteNum].cstat&33) == 33)
9554         {
9555             sectorLotag             = 0;
9556             pPlayer->footprintcount = 0;
9557             pPlayer->spritebridge   = 1;
9558             //pPlayer->sbs            = spriteNum;
9559         }
9560         if (A_CheckEnemySprite(&sprite[spriteNum]) && sprite[spriteNum].xrepeat > 24
9561                 && klabs(pSprite->z - sprite[spriteNum].z) < (84 << 8))
9562         {
9563             // TX: I think this is what makes the player slide off enemies... might
9564             // be a good sprite flag to add later.
9565             // Helix: there's also SLIDE_ABOVE_ENEMY.
9566             int spriteAng = getangle(sprite[spriteNum].x - pPlayer->pos.x,
9567                                         sprite[spriteNum].y - pPlayer->pos.y);
9568             pPlayer->vel.x -= sintable[(spriteAng + 512) & 2047] << 4;
9569             pPlayer->vel.y -= sintable[spriteAng & 2047] << 4;
9570         }
9571     }
9572 
9573     pSprite->extra                  = 32;
9574     pPlayer->inv_amount[GET_SHIELD] = 0;
9575 
9576     pPlayer->last_extra = pSprite->extra;
9577     pPlayer->loogcnt    = (pPlayer->loogcnt > 0) ? pPlayer->loogcnt - 1 : 0;
9578 
9579     if (pPlayer->timebeforeexit > 1 && pPlayer->last_extra > 0)
9580     {
9581         if (--pPlayer->timebeforeexit == GAMETICSPERSEC*5)
9582         {
9583             FX_StopAllSounds();
9584             S_ClearSoundLocks();
9585 
9586             if (pPlayer->customexitsound >= 0)
9587             {
9588                 S_PlaySound(pPlayer->customexitsound);
9589                 P_DoQuote(QUOTE_WEREGONNAFRYYOURASS,pPlayer);
9590             }
9591         }
9592         else if (pPlayer->timebeforeexit == 1)
9593         {
9594             for (bssize_t TRAVERSE_CONNECT(playerNum))
9595                 g_player[playerNum].ps->gm = MODE_EOL;
9596 
9597             ud.level_number   = (++ud.level_number < MAXLEVELS) ? ud.level_number : 0;
9598             ud.m_level_number = ud.level_number;
9599             return;
9600         }
9601     }
9602 
9603     if (pPlayer->pals.f > 0)
9604         P_HandlePal(pPlayer);
9605 
9606     if (pPlayer->fta > 0 && --pPlayer->fta == 0)
9607     {
9608         pub = pus = NUMPAGES;
9609         pPlayer->ftq = 0;
9610     }
9611 
9612     if (g_levelTextTime > 0)
9613         g_levelTextTime--;
9614 
9615     if (pPlayer->newowner >= 0)
9616     {
9617         P_UpdatePosWhenViewingCam(pPlayer);
9618         P_DoCounters(playerNum);
9619 
9620         return;
9621     }
9622 
9623     pPlayer->rotscrnang -= (pPlayer->rotscrnang >> 1);
9624 
9625     if (pPlayer->rotscrnang && !(pPlayer->rotscrnang >> 1))
9626         pPlayer->rotscrnang -= ksgn(pPlayer->rotscrnang);
9627 
9628     pPlayer->look_ang -= (pPlayer->look_ang >> 2);
9629 
9630     if (pPlayer->look_ang && !(pPlayer->look_ang >> 2))
9631         pPlayer->look_ang -= ksgn(pPlayer->look_ang);
9632 
9633     if (TEST_SYNC_KEY(playerBits, SK_LOOK_LEFT) && !pPlayer->on_motorcycle)
9634     {
9635         // look_left
9636         pPlayer->look_ang -= 152;
9637         pPlayer->rotscrnang += 24;
9638     }
9639 
9640     if (TEST_SYNC_KEY(playerBits, SK_LOOK_RIGHT) && !pPlayer->on_motorcycle)
9641     {
9642         // look_right
9643         pPlayer->look_ang += 152;
9644         pPlayer->rotscrnang -= 24;
9645     }
9646 
9647     int                  velocityModifier = TICSPERFRAME;
9648     const int16_t *const weaponFrame      = &pPlayer->kickback_pic;
9649     int                  floorZOffset     = 40;
9650     int const            playerShrunk     = (pSprite->yrepeat < 8);
9651 
9652     pPlayer->weapon_sway = (pSprite->xvel < 32 || pPlayer->on_ground == 0 || pPlayer->bobcounter == 1024)
9653                            ? (((pPlayer->weapon_sway & 2047) > (1024 + 96))
9654                            ? (pPlayer->weapon_sway - 96)
9655                            : (((pPlayer->weapon_sway & 2047) < (1024 - 96)))
9656                            ? (pPlayer->weapon_sway + 96)
9657                            : 1024)
9658                            : pPlayer->bobcounter;
9659 
9660     // NOTE: This silently wraps if the difference is too great, e.g. used to do
9661     // that when teleported by silent SE7s.
9662     pSprite->xvel = ksqrt(uhypsq(pPlayer->pos.x - pPlayer->bobpos.x, pPlayer->pos.y - pPlayer->bobpos.y));
9663 
9664     if (pPlayer->on_ground)
9665         pPlayer->bobcounter += sprite[pPlayer->i].xvel>>1;
9666 
9667     if (ud.noclip == 0 && ((uint16_t)pPlayer->cursectnum >= MAXSECTORS || sector[pPlayer->cursectnum].floorpicnum == MIRROR))
9668     {
9669         pPlayer->pos.x = pPlayer->opos.x;
9670         pPlayer->pos.y = pPlayer->opos.y;
9671     }
9672     else
9673     {
9674         pPlayer->opos.x = pPlayer->pos.x;
9675         pPlayer->opos.y = pPlayer->pos.y;
9676     }
9677 
9678     pPlayer->bobpos.x = pPlayer->pos.x;
9679     pPlayer->bobpos.y = pPlayer->pos.y;
9680     pPlayer->opos.z   = pPlayer->pos.z;
9681     pPlayer->opyoff   = pPlayer->pyoff;
9682     pPlayer->oq16ang    = pPlayer->q16ang;
9683 
9684     if (pPlayer->one_eighty_count < 0)
9685     {
9686         pPlayer->one_eighty_count += 128;
9687         pPlayer->q16ang += F16(128);
9688     }
9689 
9690     // Shrinking code
9691 
9692     if (sectorLotag == ST_2_UNDERWATER)
9693     {
9694     }
9695     else
9696     {
9697         pPlayer->scuba_on = 0;
9698 
9699         if (pPlayer->pos.z < (floorZ-(floorZOffset<<8)))  //falling
9700         {
9701             // not jumping or crouching
9702 
9703             if ((!TEST_SYNC_KEY(playerBits, SK_JUMP) && !TEST_SYNC_KEY(playerBits, SK_CROUCH)) && pPlayer->on_ground &&
9704                 (sector[pPlayer->cursectnum].floorstat & 2) && pPlayer->pos.z >= (floorZ - (floorZOffset << 8) - ZOFFSET2))
9705                 pPlayer->pos.z = floorZ - (floorZOffset << 8);
9706             else
9707             {
9708                 pPlayer->on_ground = 0;
9709                 pPlayer->vel.z    += (g_spriteGravity + 80);  // (TICSPERFRAME<<6);
9710 
9711                 if (pPlayer->vel.z >= (4096 + 2048))
9712                     pPlayer->vel.z = (4096 + 2048);
9713 
9714                 if (pPlayer->vel.z > 2400 && pPlayer->falling_counter < 255)
9715                 {
9716                     pPlayer->falling_counter++;
9717                     if (pPlayer->falling_counter >= 38 && pPlayer->scream_voice <= FX_Ok)
9718                     {
9719                         int32_t voice = A_PlaySound(DUKE_SCREAM,pPlayer->i);
9720                         if (voice <= 127)  // XXX: p->scream_voice is an int8_t
9721                             pPlayer->scream_voice = voice;
9722                     }
9723                 }
9724 
9725                 if ((pPlayer->pos.z + pPlayer->vel.z) >= (floorZ - (floorZOffset << 8)) && pPlayer->cursectnum >= 0)  // hit the ground
9726                 {
9727                     ghsound_footstepsound(playerNum, 1);
9728                 }
9729             }
9730         }
9731         else
9732         {
9733             pPlayer->falling_counter = 0;
9734 
9735             if ((sectorLotag != ST_1_ABOVE_WATER && sectorLotag != ST_2_UNDERWATER) &&
9736                 (pPlayer->on_ground == 0 && pPlayer->vel.z > (6144 >> 1)))
9737                 pPlayer->hard_landing = pPlayer->vel.z>>10;
9738 
9739             pPlayer->on_ground = 1;
9740 
9741             if (floorZOffset==40)
9742             {
9743                 //Smooth on the ground
9744                 int Zdiff = ((floorZ - (floorZOffset << 8)) - pPlayer->pos.z) >> 1;
9745 
9746                 if (klabs(Zdiff) < 256)
9747                     Zdiff = 0;
9748 
9749                 pPlayer->pos.z += ((klabs(Zdiff) >= 256) ? (((floorZ - (floorZOffset << 8)) - pPlayer->pos.z) >> 1) : 0);
9750                 pPlayer->vel.z -= 768;
9751 
9752                 if (pPlayer->vel.z < 0)
9753                     pPlayer->vel.z = 0;
9754             }
9755             else if (pPlayer->jumping_counter == 0)
9756             {
9757                 pPlayer->pos.z += ((floorZ - (floorZOffset << 7)) - pPlayer->pos.z) >> 1;  // Smooth on the water
9758 
9759                 if (pPlayer->on_warping_sector == 0 && pPlayer->pos.z > floorZ - ZOFFSET2)
9760                 {
9761                     pPlayer->pos.z = floorZ - ZOFFSET2;
9762                     pPlayer->vel.z >>= 1;
9763                 }
9764             }
9765 
9766             pPlayer->on_warping_sector = 0;
9767 
9768             if (TEST_SYNC_KEY(playerBits, SK_CROUCH) && !pPlayer->on_motorcycle)
9769             {
9770                 // crouching
9771                 pPlayer->pos.z += (2048+768);
9772                 pPlayer->crack_time = 777;
9773             }
9774 
9775             // jumping
9776             if (!TEST_SYNC_KEY(playerBits, SK_JUMP) && !pPlayer->on_motorcycle && pPlayer->jumping_toggle == 1)
9777                 pPlayer->jumping_toggle = 0;
9778             else if (TEST_SYNC_KEY(playerBits, SK_JUMP) && !pPlayer->on_motorcycle && pPlayer->jumping_toggle == 0)
9779             {
9780                 if (pPlayer->jumping_counter == 0)
9781                     if ((floorZ-ceilZ) > (56<<8))
9782                     {
9783                         pPlayer->jumping_counter = 1;
9784                         pPlayer->jumping_toggle = 1;
9785                     }
9786             }
9787         }
9788 
9789         if (pPlayer->jumping_counter)
9790         {
9791             if (!TEST_SYNC_KEY(playerBits, SK_JUMP) && !pPlayer->on_motorcycle && pPlayer->jumping_toggle == 1)
9792                 pPlayer->jumping_toggle = 0;
9793 
9794             if (pPlayer->jumping_counter < 768)
9795             {
9796                 if (sectorLotag == ST_1_ABOVE_WATER && pPlayer->jumping_counter > 768)
9797                 {
9798                     pPlayer->jumping_counter = 0;
9799                     pPlayer->vel.z = -512;
9800                 }
9801                 else
9802                 {
9803                     pPlayer->vel.z -= (sintable[(2048-128+pPlayer->jumping_counter)&2047])/12;
9804                     pPlayer->jumping_counter += 180;
9805                     pPlayer->on_ground = 0;
9806                 }
9807             }
9808             else
9809             {
9810                 pPlayer->jumping_counter = 0;
9811                 pPlayer->vel.z = 0;
9812             }
9813         }
9814 
9815         pPlayer->pos.z += pPlayer->vel.z;
9816 
9817         if (pPlayer->pos.z < (ceilZ+ZOFFSET6))
9818         {
9819             pPlayer->jumping_counter = 0;
9820             if (pPlayer->vel.z < 0)
9821                 pPlayer->vel.x = pPlayer->vel.y = 0;
9822             pPlayer->vel.z = 128;
9823             pPlayer->pos.z = ceilZ+ZOFFSET6;
9824         }
9825     }
9826 
9827     if (pPlayer->fist_incs || pPlayer->transporter_hold > 2 || pPlayer->hard_landing || pPlayer->access_incs > 0 ||
9828         pPlayer->knee_incs > 0 || (!RR && pPlayer->curr_weapon == TRIPBOMB_WEAPON &&
9829                                    *weaponFrame > 1 && *weaponFrame < 4))
9830     {
9831         velocityModifier = 0;
9832         pPlayer->vel.x   = 0;
9833         pPlayer->vel.y   = 0;
9834     }
9835     else if (g_player[playerNum].inputBits->q16avel)            //p->ang += syncangvel * constant
9836     {
9837         fix16_t const inputAng  = g_player[playerNum].inputBits->q16avel;
9838 
9839         if (ud.recstat == 2 && g_demo_legacy)
9840             pPlayer->q16angvel = (sectorLotag == ST_2_UNDERWATER) ? ((fix16_to_int(inputAng) - (fix16_to_int(inputAng) >> 3))*fix16_from_int(ksgn(velocityModifier)))
9841                                                                : (fix16_to_int(inputAng) * fix16_from_int(ksgn(velocityModifier)));
9842         else
9843             pPlayer->q16angvel = (sectorLotag == ST_2_UNDERWATER) ? fix16_mul(inputAng - (inputAng >> 3), fix16_from_int(ksgn(velocityModifier)))
9844                                                                : fix16_mul(inputAng, fix16_from_int(ksgn(velocityModifier)));
9845         pPlayer->q16ang       += pPlayer->q16angvel;
9846         pPlayer->q16ang       &= 0x7FFFFFF;
9847         pPlayer->crack_time = 777;
9848     }
9849 
9850     if (pPlayer->vel.x || pPlayer->vel.y || g_player[playerNum].inputBits->fvel || g_player[playerNum].inputBits->svel)
9851     {
9852         pPlayer->crack_time = 777;
9853 
9854         pPlayer->not_on_water = 1;
9855 
9856         pPlayer->vel.x += (((g_player[playerNum].inputBits->fvel) * velocityModifier) << 6);
9857         pPlayer->vel.y += (((g_player[playerNum].inputBits->svel) * velocityModifier) << 6);
9858 
9859         pPlayer->vel.x = mulscale16(pPlayer->vel.x, pPlayer->runspeed);
9860         pPlayer->vel.y = mulscale16(pPlayer->vel.y, pPlayer->runspeed);
9861 
9862         if (klabs(pPlayer->vel.x) < 2048 && klabs(pPlayer->vel.y) < 2048)
9863             pPlayer->vel.x = pPlayer->vel.y = 0;
9864     }
9865 
9866 HORIZONLY:;
9867     int stepHeight = (sectorLotag == ST_1_ABOVE_WATER || pPlayer->spritebridge == 1) ? pPlayer->autostep_sbw : pPlayer->autostep;
9868 
9869 #ifdef EDUKE32_TOUCH_DEVICES
9870     if (TEST_SYNC_KEY(playerBits, SK_CROUCH))
9871         stepHeight = pPlayer->autostep_sbw;
9872 #endif
9873 
9874     int spriteNum;
9875 
9876     if (ud.noclip)
9877     {
9878         spriteNum = 0;
9879         pPlayer->pos.x += pPlayer->vel.x >> 14;
9880         pPlayer->pos.y += pPlayer->vel.y >> 14;
9881         updatesector(pPlayer->pos.x, pPlayer->pos.y, &pPlayer->cursectnum);
9882         changespritesect(pPlayer->i, pPlayer->cursectnum);
9883     }
9884     else
9885     {
9886 #ifdef YAX_ENABLE
9887         int const playerSectNum = pPlayer->cursectnum;
9888         int16_t   ceilingBunch, floorBunch;
9889 
9890         if (playerSectNum >= 0)
9891             yax_getbunches(playerSectNum, &ceilingBunch, &floorBunch);
9892 
9893         // This updatesectorz conflicts with Duke3D's way of teleporting through water,
9894         // so make it a bit conditional... OTOH, this way we have an ugly z jump when
9895         // changing from above water to underwater
9896 
9897         if ((playerSectNum >= 0 && !(sector[playerSectNum].lotag == ST_1_ABOVE_WATER && pPlayer->on_ground && floorBunch >= 0))
9898             && ((floorBunch >= 0 && !(sector[playerSectNum].floorstat & 512))
9899                 || (ceilingBunch >= 0 && !(sector[playerSectNum].ceilingstat & 512))))
9900         {
9901             pPlayer->cursectnum += MAXSECTORS;  // skip initial z check, restored by updatesectorz
9902             updatesectorz(pPlayer->pos.x, pPlayer->pos.y, pPlayer->pos.z, &pPlayer->cursectnum);
9903         }
9904 #endif
9905         int const oldSector = pPlayer->cursectnum;
9906         spriteNum = clipmove((vec3_t *)pPlayer, &pPlayer->cursectnum, pPlayer->vel.x, pPlayer->vel.y, 164,
9907                                  (4L << 8), stepHeight, CLIPMASK0);
9908 
9909         if (pPlayer->cursectnum >= 0 && pPlayer->cursectnum < numsectors && sector[pPlayer->cursectnum].hitag == 2002)
9910         {
9911             pPlayer->pos = pPlayer->opos;
9912             pPlayer->cursectnum = oldSector;
9913             P_DoQuote(152, pPlayer);
9914             clipmove((vec3_t*)pPlayer, &pPlayer->cursectnum, 0, 0, 164, (4L << 8), stepHeight, CLIPMASK0);
9915         }
9916     }
9917 
9918     int waterSector = (sector[pPlayer->cursectnum].hitag == 2003);
9919 
9920     if (waterSector)
9921         pPlayer->pos.z += 2048;
9922 
9923     if ((spriteNum & 49152) == 32768)
9924     {
9925     }
9926     else if ((spriteNum & 49152) == 49152)
9927     {
9928         spriteNum &= (MAXSPRITES-1);
9929 
9930         ghsound_plrtouchedsprite(spriteNum, playerNum);
9931         ghdeploy_plrtouchedsprite(spriteNum, playerNum);
9932     }
9933 
9934     if (pPlayer->jetpack_on == 0)
9935     {
9936         if (g_player[playerNum].inputBits->fvel && pPlayer->on_ground)
9937         {
9938             pPlayer->pycount += 64;
9939             pPlayer->pycount &= 2047;
9940             if (TEST_SYNC_KEY(playerBits, SK_CROUCH))
9941             {
9942                 pPlayer->pyoff = klabs(sintable[pPlayer->pycount]) >> 6;
9943                 ghsound_footstepsound(playerNum, 2);
9944             }
9945             else if (TEST_SYNC_KEY(playerBits, SK_RUN))
9946             {
9947                 pPlayer->pyoff = klabs(sintable[pPlayer->pycount]) >> 5;
9948                 pPlayer->pyoff += 256;
9949                 if (waterSector)
9950                     pPlayer->pyoff += 512;
9951                 ghsound_footstepsound(playerNum, 1);
9952             }
9953             else
9954             {
9955                 pPlayer->pyoff = klabs(sintable[pPlayer->pycount]) >> 6;
9956                 pPlayer->pyoff += 16;
9957                 if (waterSector)
9958                     pPlayer->pyoff += 512;
9959                 ghsound_footstepsound(playerNum, 0);
9960             }
9961         }
9962         else
9963             pPlayer->pyoff = 0;
9964     }
9965 
9966     pPlayer->pos.z += PHEIGHT;
9967     setsprite(pPlayer->i, &pPlayer->pos);
9968     pPlayer->pos.z -= PHEIGHT;
9969 
9970     if (pPlayer->cursectnum >= 0 && pPlayer->cursectnum != pSprite->sectnum)
9971         changespritesect(pPlayer->i, pPlayer->cursectnum);
9972 
9973     if (pPlayer->cursectnum >= 0 && ud.noclip == 0)
9974     {
9975         int const squishPlayer = (pushmove((vec3_t *)pPlayer, &pPlayer->cursectnum, (!RR || pSprite->clipdist == 64) ? 164 : 16, (4L << 8), (4L << 8), CLIPMASK0) < 0 &&
9976                                  A_GetFurthestAngle(pPlayer->i, 8) < 512);
9977     }
9978 
9979     int centerHoriz = 0;
9980 
9981     if (TEST_SYNC_KEY(playerBits, SK_CENTER_VIEW) || pPlayer->hard_landing)
9982         pPlayer->return_to_center = 9;
9983 
9984     if (TEST_SYNC_KEY(playerBits, SK_LOOK_UP))
9985     {
9986         pPlayer->return_to_center = 9;
9987         pPlayer->q16horiz += fix16_from_int(12<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
9988         centerHoriz++;
9989     }
9990     else if (TEST_SYNC_KEY(playerBits, SK_LOOK_DOWN))
9991     {
9992         pPlayer->return_to_center = 9;
9993         pPlayer->q16horiz -= fix16_from_int(12<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
9994         centerHoriz++;
9995     }
9996     else if (TEST_SYNC_KEY(playerBits, SK_AIM_UP) && !pPlayer->on_motorcycle)
9997     {
9998         pPlayer->q16horiz += fix16_from_int(6<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
9999         centerHoriz++;
10000     }
10001     else if (TEST_SYNC_KEY(playerBits, SK_AIM_DOWN) && !pPlayer->on_motorcycle)
10002     {
10003         pPlayer->q16horiz -= fix16_from_int(6<<(int)(TEST_SYNC_KEY(playerBits, SK_RUN)));
10004         centerHoriz++;
10005     }
10006     if (RR && pPlayer->recoil && *weaponFrame == 0)
10007     {
10008         int delta = pPlayer->recoil >> 1;
10009         if (!delta) delta++;
10010         pPlayer->recoil -= delta;
10011         pPlayer->q16horiz -= F16(delta);
10012     }
10013     else if (pPlayer->return_to_center > 0 && !TEST_SYNC_KEY(playerBits, SK_LOOK_UP) && !TEST_SYNC_KEY(playerBits, SK_LOOK_DOWN))
10014     {
10015         pPlayer->return_to_center--;
10016         if (ud.recstat == 2 && g_demo_legacy)
10017             pPlayer->q16horiz += F16(33-fix16_to_int(pPlayer->q16horiz) / 3);
10018         else
10019             pPlayer->q16horiz += F16(33)-fix16_div(pPlayer->q16horiz, F16(3));
10020         centerHoriz++;
10021     }
10022 
10023     if (pPlayer->hard_landing > 0)
10024     {
10025         pPlayer->hard_landing--;
10026         pPlayer->q16horiz -= fix16_from_int(pPlayer->hard_landing<<4);
10027     }
10028 
10029     pPlayer->q16horiz = fix16_clamp(pPlayer->q16horiz + ((ud.recstat == 2 && g_demo_legacy && !pPlayer->aim_mode) ? 0 : g_player[playerNum].inputBits->q16horz), F16(HORIZ_MIN), F16(HORIZ_MAX));
10030 
10031     if (ud.recstat == 2 && g_demo_legacy) centerHoriz = !pPlayer->aim_mode;
10032 
10033     if (centerHoriz && (!RR || !pPlayer->recoil))
10034     {
10035         if (pPlayer->q16horiz > F16(95) && pPlayer->q16horiz < F16(105)) pPlayer->q16horiz = F16(100);
10036         if (pPlayer->q16horizoff > F16(-5) && pPlayer->q16horizoff < F16(5)) pPlayer->q16horizoff = 0;
10037     }
10038 
10039     if (TEST_SYNC_KEY(playerBits, SK_FIRE))
10040         A_DHShoot(playerNum);
10041 }
10042 
P_HasKey(int sectNum,int playerNum)10043 int P_HasKey(int sectNum, int playerNum)
10044 {
10045     if (g_sectorExtra[sectNum] == 0)
10046         return 1;
10047     if (g_sectorExtra[sectNum] > 6)
10048         return 1;
10049 
10050     int key = g_sectorExtra[sectNum];
10051     if (key > 3)
10052         key -= 3;
10053 
10054     if (g_player[playerNum].ps->keys[key] == 1)
10055     {
10056         g_sectorExtra[sectNum] = 0;
10057         return 1;
10058     }
10059     return 0;
10060 }
10061