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, §Num);
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(§or[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 *)§or[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