2020-05-14 10:14:03 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1996, 2003 - 3D Realms Entertainment
|
|
|
|
Copyright (C) 2000, 2003 - Matt Saettler (EDuke Enhancements)
|
2020-06-28 07:03:31 +00:00
|
|
|
Copyright (C) 2020 - Christoph Oelckers
|
2020-05-14 10:14:03 +00:00
|
|
|
|
|
|
|
This file is part of Enhanced Duke Nukem 3D version 1.5 - Atomic Edition
|
|
|
|
|
|
|
|
Duke Nukem 3D is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
Original Source: 1996 - Todd Replogle
|
|
|
|
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|
|
|
|
|
|
|
EDuke enhancements integrated: 04/13/2003 - Matt Saettler
|
|
|
|
|
|
|
|
Note: EDuke source was in transition. Changes are in-progress in the
|
|
|
|
source as it is released.
|
|
|
|
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
#include "ns.h"
|
|
|
|
#include "global.h"
|
2020-07-07 15:56:20 +00:00
|
|
|
#include "mapinfo.h"
|
2020-05-14 10:14:03 +00:00
|
|
|
|
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
2020-07-15 16:10:31 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// callback for playercolor CVAR
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
inline int playercolor2lookup(int color)
|
|
|
|
{
|
|
|
|
static int8_t player_pals[] = { 0, 9, 10, 11, 12, 13, 14, 15, 16, 21, 23, };
|
|
|
|
if (color >= 0 && color < 10) return player_pals[color];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerColorChanged(void)
|
|
|
|
{
|
|
|
|
if (ud.recstat != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ud.multimode > 1)
|
|
|
|
{
|
|
|
|
//Net_SendClientInfo();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ps[myconnectindex].palookup = ud.user_pals[myconnectindex] = playercolor2lookup(playercolor);
|
|
|
|
}
|
|
|
|
if (sprite[ps[myconnectindex].i].picnum == TILE_APLAYER && sprite[ps[myconnectindex].i].pal != 1)
|
|
|
|
sprite[ps[myconnectindex].i].pal = ud.user_pals[myconnectindex];
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Sync local player with CVARs.
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void setlocalplayerinput(player_struct* pp)
|
|
|
|
{
|
|
|
|
pp->aim_mode = in_mousemode;
|
|
|
|
pp->auto_aim = cl_autoaim;
|
|
|
|
}
|
|
|
|
|
2020-07-16 22:32:26 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// calculates automatic view pitch for playing without a mouse
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-07-17 22:34:20 +00:00
|
|
|
void calcviewpitch(player_struct *p, double factor)
|
2020-07-16 22:32:26 +00:00
|
|
|
{
|
|
|
|
int psect = p->cursectnum;
|
2020-07-17 22:34:20 +00:00
|
|
|
int psectlotag = sector[psect].lotag;
|
2020-07-16 22:32:26 +00:00
|
|
|
if (p->aim_mode == 0 && p->on_ground && psectlotag != ST_2_UNDERWATER && (sector[psect].floorstat & 2))
|
|
|
|
{
|
|
|
|
int x = p->posx + (sintable[(p->getang() + 512) & 2047] >> 5);
|
|
|
|
int y = p->posy + (sintable[p->getang() & 2047] >> 5);
|
|
|
|
short tempsect = psect;
|
|
|
|
updatesector(x, y, &tempsect);
|
|
|
|
|
|
|
|
if (tempsect >= 0)
|
|
|
|
{
|
|
|
|
int k = getflorzofslope(psect, x, y);
|
|
|
|
if (psect == tempsect || abs(getflorzofslope(tempsect, x, y) - k) <= (4 << 8))
|
|
|
|
p->addhorizoff(factor * mulscale16(p->truefz - k, 160));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p->q16horizoff > 0)
|
|
|
|
{
|
|
|
|
p->addhorizoff(-factor * fix16_to_dbl((p->q16horizoff >> 3) + FRACUNIT));
|
|
|
|
if (p->q16horizoff < 0) p->q16horizoff = 0;
|
|
|
|
}
|
|
|
|
else if (p->q16horizoff < 0)
|
|
|
|
{
|
|
|
|
p->addhorizoff(-factor * fix16_to_dbl((p->q16horizoff >> 3) + FRACUNIT));
|
|
|
|
if (p->q16horizoff > 0) p->q16horizoff = 0;
|
|
|
|
}
|
|
|
|
}
|
2020-07-15 16:10:31 +00:00
|
|
|
|
2020-05-16 21:55:21 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2020-07-03 14:17:37 +00:00
|
|
|
// why is this such a mess?
|
2020-05-16 21:55:21 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-07-03 14:17:37 +00:00
|
|
|
void setpal(struct player_struct* p)
|
2020-05-16 21:55:21 +00:00
|
|
|
{
|
2020-07-03 14:17:37 +00:00
|
|
|
int palette;
|
2020-05-16 21:55:21 +00:00
|
|
|
if (p->DrugMode) palette = DRUGPAL;
|
2020-07-03 14:17:37 +00:00
|
|
|
else if (p->heat_on) palette = SLIMEPAL;
|
|
|
|
else if (p->cursectnum < 0) palette = BASEPAL; // don't crash if out of range.
|
2020-07-07 02:54:12 +00:00
|
|
|
else if (sector[p->cursectnum].ceilingpicnum >= TILE_FLOORSLIME && sector[p->cursectnum].ceilingpicnum <= TILE_FLOORSLIME + 2) palette = SLIMEPAL;
|
|
|
|
else if (sector[p->cursectnum].lotag == ST_2_UNDERWATER) palette = WATERPAL;
|
2020-05-16 21:55:21 +00:00
|
|
|
else palette = BASEPAL;
|
2020-07-03 14:17:37 +00:00
|
|
|
p->palette = palette;
|
2020-05-16 21:55:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void quickkill(struct player_struct* p)
|
|
|
|
{
|
|
|
|
SetPlayerPal(p, PalEntry(48, 48, 48, 48));
|
|
|
|
|
|
|
|
sprite[p->i].extra = 0;
|
|
|
|
sprite[p->i].cstat |= 32768;
|
|
|
|
if (ud.god == 0) fi.guts(&sprite[p->i], TILE_JIBS6, 8, myconnectindex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void forceplayerangle(struct player_struct* p)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = 128 - (krand() & 255);
|
|
|
|
|
2020-05-18 16:41:48 +00:00
|
|
|
p->addhoriz(64);
|
2020-05-16 21:55:21 +00:00
|
|
|
p->return_to_center = 9;
|
2020-05-18 20:28:12 +00:00
|
|
|
p->setlookang(n >> 1);
|
|
|
|
p->setrotscrnang(n >> 1);
|
2020-05-16 21:55:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void tracers(int x1, int y1, int z1, int x2, int y2, int z2, int n)
|
|
|
|
{
|
|
|
|
int i, xv, yv, zv;
|
|
|
|
short sect = -1;
|
|
|
|
|
|
|
|
i = n + 1;
|
|
|
|
xv = (x2 - x1) / i;
|
|
|
|
yv = (y2 - y1) / i;
|
|
|
|
zv = (z2 - z1) / i;
|
|
|
|
|
|
|
|
if ((abs(x1 - x2) + abs(y1 - y2)) < 3084)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = n; i > 0; i--)
|
|
|
|
{
|
|
|
|
x1 += xv;
|
|
|
|
y1 += yv;
|
|
|
|
z1 += zv;
|
|
|
|
updatesector(x1, y1, §);
|
|
|
|
if (sect >= 0)
|
|
|
|
{
|
|
|
|
if (sector[sect].lotag == 2)
|
|
|
|
EGS(sect, x1, y1, z1, TILE_WATERBUBBLE, -32, 4 + (krand() & 3), 4 + (krand() & 3), krand() & 2047, 0, 0, ps[0].i, 5);
|
|
|
|
else
|
|
|
|
EGS(sect, x1, y1, z1, TILE_SMALLSMOKE, -32, 14, 14, 0, 0, 0, ps[0].i, 5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int hits(int i)
|
|
|
|
{
|
|
|
|
auto sp = &sprite[i];
|
|
|
|
int sx, sy, sz;
|
|
|
|
short sect;
|
|
|
|
short hw, hs;
|
|
|
|
int zoff;
|
|
|
|
|
|
|
|
if (sp->picnum == TILE_APLAYER) zoff = (40 << 8);
|
|
|
|
else zoff = 0;
|
|
|
|
|
|
|
|
hitscan(sp->x, sp->y, sp->z - zoff, sp->sectnum, sintable[(sp->ang + 512) & 2047], sintable[sp->ang & 2047], 0, §, &hw, &hs, &sx, &sy, &sz, CLIPMASK1);
|
|
|
|
|
|
|
|
return (FindDistance2D(sx - sp->x, sy - sp->y));
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int hitasprite(int i, short* hitsp)
|
|
|
|
{
|
|
|
|
auto sp = &sprite[i];
|
|
|
|
int sx, sy, sz, zoff;
|
|
|
|
short sect, hw;
|
|
|
|
|
|
|
|
if (badguy(&sprite[i]))
|
|
|
|
zoff = (42 << 8);
|
|
|
|
else if (sp->picnum == TILE_APLAYER) zoff = (39 << 8);
|
|
|
|
else zoff = 0;
|
|
|
|
|
|
|
|
hitscan(sp->x, sp->y, sp->z - zoff, sp->sectnum, sintable[(sp->ang + 512) & 2047], sintable[sp->ang & 2047], 0, §, &hw, hitsp, &sx, &sy, &sz, CLIPMASK1);
|
|
|
|
|
|
|
|
if (hw >= 0 && (wall[hw].cstat & 16) && badguy(&sprite[i]))
|
|
|
|
return((1 << 30));
|
|
|
|
|
|
|
|
return (FindDistance2D(sx - sp->x, sy - sp->y));
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int hitawall(struct player_struct* p, int* hitw)
|
|
|
|
{
|
|
|
|
int sx, sy, sz;
|
|
|
|
short sect, hs, hitw1;
|
|
|
|
|
|
|
|
hitscan(p->posx, p->posy, p->posz, p->cursectnum,
|
|
|
|
sintable[(p->getang() + 512) & 2047], sintable[p->getang() & 2047], 0, §, &hitw1, &hs, &sx, &sy, &sz, CLIPMASK0);
|
|
|
|
*hitw = hitw1;
|
|
|
|
|
|
|
|
return (FindDistance2D(sx - p->posx, sy - p->posy));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int aim(spritetype* s, int aang)
|
|
|
|
{
|
|
|
|
char gotshrinker, gotfreezer;
|
|
|
|
int i, j, a, k, cans;
|
2020-07-26 07:06:08 +00:00
|
|
|
int aimstats[] = { STAT_PLAYER, STAT_DUMMYPLAYER, STAT_ACTOR, STAT_ZOMBIEACTOR };
|
2020-05-16 21:55:21 +00:00
|
|
|
int dx1, dy1, dx2, dy2, dx3, dy3, smax, sdist;
|
|
|
|
int xv, yv;
|
|
|
|
|
|
|
|
a = s->ang;
|
|
|
|
|
|
|
|
// Autoaim from DukeGDX.
|
2020-07-26 07:06:08 +00:00
|
|
|
if (s->picnum == TILE_APLAYER)
|
|
|
|
{
|
|
|
|
if (ps[s->yvel].auto_aim == 0)
|
|
|
|
{
|
|
|
|
// The chickens in RRRA are homing and must always autoaim.
|
|
|
|
if (!isRRRA() || ps[s->yvel].curr_weapon != CHICKEN_WEAPON)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (ps[s->yvel].auto_aim == 2)
|
|
|
|
{
|
|
|
|
int weap;
|
|
|
|
if (!isWW2GI())
|
|
|
|
{
|
|
|
|
weap = ps[s->yvel].curr_weapon;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
weap = aplWeaponWorksLike[ps[s->yvel].curr_weapon][s->yvel];
|
|
|
|
}
|
|
|
|
if (weap > CHAINGUN_WEAPON || weap == KNEE_WEAPON)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
2020-05-16 21:55:21 +00:00
|
|
|
|
2020-07-26 07:06:08 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-16 21:55:21 +00:00
|
|
|
j = -1;
|
2020-07-04 20:44:33 +00:00
|
|
|
// if(s->picnum == TILE_APLAYER && ps[s->yvel].aim_mode) return -1;
|
2020-05-16 21:55:21 +00:00
|
|
|
|
|
|
|
if (isRR())
|
|
|
|
{
|
|
|
|
gotshrinker = 0;
|
|
|
|
gotfreezer = 0;
|
|
|
|
}
|
|
|
|
else if (isWW2GI())
|
|
|
|
{
|
|
|
|
gotshrinker = s->picnum == TILE_APLAYER && aplWeaponWorksLike[ps[s->yvel].curr_weapon][s->yvel] == SHRINKER_WEAPON;
|
|
|
|
gotfreezer = s->picnum == TILE_APLAYER && aplWeaponWorksLike[ps[s->yvel].curr_weapon][s->yvel] == FREEZE_WEAPON;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gotshrinker = s->picnum == TILE_APLAYER && ps[s->yvel].curr_weapon == SHRINKER_WEAPON;
|
|
|
|
gotfreezer = s->picnum == TILE_APLAYER && ps[s->yvel].curr_weapon == FREEZE_WEAPON;
|
|
|
|
}
|
|
|
|
|
|
|
|
smax = 0x7fffffff;
|
|
|
|
|
|
|
|
dx1 = sintable[(a + 512 - aang) & 2047];
|
|
|
|
dy1 = sintable[(a - aang) & 2047];
|
|
|
|
dx2 = sintable[(a + 512 + aang) & 2047];
|
|
|
|
dy2 = sintable[(a + aang) & 2047];
|
|
|
|
|
|
|
|
dx3 = sintable[(a + 512) & 2047];
|
|
|
|
dy3 = sintable[a & 2047];
|
|
|
|
|
|
|
|
for (k = 0; k < 4; k++)
|
|
|
|
{
|
|
|
|
if (j >= 0)
|
|
|
|
break;
|
|
|
|
for (i = headspritestat[aimstats[k]]; i >= 0; i = nextspritestat[i])
|
|
|
|
if (sprite[i].xrepeat > 0 && sprite[i].extra >= 0 && (sprite[i].cstat & (257 + 32768)) == 257)
|
|
|
|
if (badguy(&sprite[i]) || k < 2)
|
|
|
|
{
|
|
|
|
auto sp = &sprite[i];
|
|
|
|
if (badguy(&sprite[i]) || sp->picnum == TILE_APLAYER)
|
|
|
|
{
|
|
|
|
if (sp->picnum == TILE_APLAYER &&
|
|
|
|
(isRR() && ud.ffire == 0) &&
|
|
|
|
ud.coop == 1 &&
|
|
|
|
s->picnum == TILE_APLAYER &&
|
|
|
|
s != &sprite[i])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (gotshrinker && sprite[i].xrepeat < 30 && !(actorinfo[sp->picnum].flags & SFLAG_SHRINKAUTOAIM)) continue;
|
|
|
|
if (gotfreezer && sprite[i].pal == 1) continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
xv = (sp->x - s->x);
|
|
|
|
yv = (sp->y - s->y);
|
|
|
|
|
|
|
|
if ((dy1 * xv) <= (dx1 * yv))
|
|
|
|
if ((dy2 * xv) >= (dx2 * yv))
|
|
|
|
{
|
|
|
|
sdist = mulscale(dx3, xv, 14) + mulscale(dy3, yv, 14);
|
|
|
|
if (sdist > 512 && sdist < smax)
|
|
|
|
{
|
|
|
|
if (s->picnum == TILE_APLAYER)
|
2020-05-18 20:28:12 +00:00
|
|
|
a = (abs(scale(sp->z - s->z, 10, sdist) - (ps[s->yvel].gethorizsum() - 100)) < 100);
|
2020-05-16 21:55:21 +00:00
|
|
|
else a = 1;
|
|
|
|
|
|
|
|
cans = cansee(sp->x, sp->y, sp->z - (32 << 8) + actorinfo[sp->picnum].aimoffset, sp->sectnum, s->x, s->y, s->z - (32 << 8), s->sectnum);
|
|
|
|
|
|
|
|
if (a && cans)
|
|
|
|
{
|
|
|
|
smax = sdist;
|
|
|
|
j = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
|
2020-05-17 21:44:53 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void dokneeattack(int snum, int pi, const std::initializer_list<int> & respawnlist)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
|
|
|
|
if (p->knee_incs > 0)
|
|
|
|
{
|
|
|
|
p->knee_incs++;
|
2020-07-28 11:38:20 +00:00
|
|
|
if (cl_syncinput)
|
2020-07-16 15:59:25 +00:00
|
|
|
p->addhoriz(-48);
|
|
|
|
else
|
|
|
|
{
|
2020-07-26 11:49:25 +00:00
|
|
|
p->horizSkew = -48 * FRACUNIT;
|
2020-07-16 15:59:25 +00:00
|
|
|
}
|
|
|
|
|
2020-05-17 21:44:53 +00:00
|
|
|
p->return_to_center = 9;
|
|
|
|
if (p->knee_incs > 15)
|
|
|
|
{
|
|
|
|
p->knee_incs = 0;
|
|
|
|
p->holster_weapon = 0;
|
|
|
|
if (p->weapon_pos < 0)
|
|
|
|
p->weapon_pos = -p->weapon_pos;
|
|
|
|
if (p->actorsqu >= 0 && dist(&sprite[pi], &sprite[p->actorsqu]) < 1400)
|
|
|
|
{
|
|
|
|
fi.guts(&sprite[p->actorsqu], TILE_JIBS6, 7, myconnectindex);
|
|
|
|
fi.spawn(p->actorsqu, TILE_BLOODPOOL);
|
2020-07-25 07:32:54 +00:00
|
|
|
S_PlayActorSound(SQUISHED, p->actorsqu);
|
2020-05-17 21:44:53 +00:00
|
|
|
if (isIn(sprite[p->actorsqu].picnum, respawnlist))
|
|
|
|
{
|
|
|
|
if (sprite[p->actorsqu].yvel)
|
|
|
|
fi.operaterespawns(sprite[p->actorsqu].yvel);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sprite[p->actorsqu].picnum == TILE_APLAYER)
|
|
|
|
{
|
|
|
|
quickkill(&ps[sprite[p->actorsqu].yvel]);
|
|
|
|
ps[sprite[p->actorsqu].yvel].frag_ps = snum;
|
|
|
|
}
|
|
|
|
else if (badguy(&sprite[p->actorsqu]))
|
|
|
|
{
|
|
|
|
deletesprite(p->actorsqu);
|
|
|
|
p->actors_killed++;
|
|
|
|
}
|
|
|
|
else deletesprite(p->actorsqu);
|
|
|
|
}
|
|
|
|
p->actorsqu = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int makepainsounds(int snum, int type)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
auto pi = p->i;
|
|
|
|
auto s = &sprite[pi];
|
|
|
|
int k = 0;
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
if (rnd(32))
|
|
|
|
{
|
|
|
|
if (p->boot_amount > 0)
|
|
|
|
k = 1;
|
|
|
|
else
|
|
|
|
{
|
2020-07-25 07:32:54 +00:00
|
|
|
if (!S_CheckActorSoundPlaying(pi, DUKE_LONGTERM_PAIN))
|
|
|
|
S_PlayActorSound(DUKE_LONGTERM_PAIN, pi);
|
2020-05-17 21:44:53 +00:00
|
|
|
SetPlayerPal(p, PalEntry(32, 64, 64, 64));
|
|
|
|
s->extra -= 1 + (krand() & 3);
|
2020-07-25 07:32:54 +00:00
|
|
|
if (!S_CheckActorSoundPlaying(pi, SHORT_CIRCUIT))
|
|
|
|
S_PlayActorSound(SHORT_CIRCUIT, pi);
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (rnd(16))
|
|
|
|
{
|
|
|
|
if (p->boot_amount > 0)
|
|
|
|
k = 1;
|
|
|
|
else
|
|
|
|
{
|
2020-07-25 07:32:54 +00:00
|
|
|
if (!S_CheckActorSoundPlaying(pi, DUKE_LONGTERM_PAIN))
|
|
|
|
S_PlayActorSound(DUKE_LONGTERM_PAIN, pi);
|
2020-05-17 21:44:53 +00:00
|
|
|
SetPlayerPal(p, PalEntry(32, 0, 8, 0));
|
|
|
|
s->extra -= 1 + (krand() & 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (rnd(32))
|
|
|
|
{
|
|
|
|
if (p->boot_amount > 0)
|
|
|
|
k = 1;
|
|
|
|
else
|
|
|
|
{
|
2020-07-25 07:32:54 +00:00
|
|
|
if (!S_CheckActorSoundPlaying(pi, DUKE_LONGTERM_PAIN))
|
|
|
|
S_PlayActorSound(DUKE_LONGTERM_PAIN, pi);
|
2020-05-17 21:44:53 +00:00
|
|
|
SetPlayerPal(p, PalEntry(32, 8, 0, 0));
|
|
|
|
s->extra -= 1 + (krand() & 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if ((krand() & 3) == 1)
|
|
|
|
if (p->on_ground)
|
|
|
|
{
|
|
|
|
if (p->OnMotorcycle)
|
|
|
|
s->extra -= 2;
|
|
|
|
else
|
|
|
|
s->extra -= 4;
|
2020-07-25 07:32:54 +00:00
|
|
|
S_PlayActorSound(DUKE_LONGTERM_PAIN, pi);
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return k;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void footprints(int snum)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
auto pi = p->i;
|
|
|
|
auto s = &sprite[pi];
|
|
|
|
auto psect = s->sectnum;
|
|
|
|
|
|
|
|
if (p->footprintcount > 0 && p->on_ground)
|
|
|
|
if ((sector[p->cursectnum].floorstat & 2) != 2)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
for (j = headspritesect[psect]; j >= 0; j = nextspritesect[j])
|
|
|
|
if (sprite[j].picnum == TILE_FOOTPRINTS || sprite[j].picnum == TILE_FOOTPRINTS2 || sprite[j].picnum == TILE_FOOTPRINTS3 || sprite[j].picnum == TILE_FOOTPRINTS4)
|
|
|
|
if (abs(sprite[j].x - p->posx) < 384)
|
|
|
|
if (abs(sprite[j].y - p->posy) < 384)
|
|
|
|
break;
|
|
|
|
if (j < 0)
|
|
|
|
{
|
|
|
|
p->footprintcount--;
|
|
|
|
if (sector[p->cursectnum].lotag == 0 && sector[p->cursectnum].hitag == 0)
|
|
|
|
{
|
|
|
|
switch (krand() & 3)
|
|
|
|
{
|
2020-07-04 20:44:33 +00:00
|
|
|
case 0: j = fi.spawn(pi, TILE_FOOTPRINTS); break;
|
|
|
|
case 1: j = fi.spawn(pi, TILE_FOOTPRINTS2); break;
|
|
|
|
case 2: j = fi.spawn(pi, TILE_FOOTPRINTS3); break;
|
2020-05-17 21:44:53 +00:00
|
|
|
default: j = fi.spawn(pi, TILE_FOOTPRINTS4); break;
|
|
|
|
}
|
|
|
|
sprite[j].pal = p->footprintpal;
|
|
|
|
sprite[j].shade = p->footprintshade;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void playerisdead(int snum, int psectlotag, int fz, int cz)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
auto pi = p->i;
|
|
|
|
auto s = &sprite[pi];
|
|
|
|
|
|
|
|
if (p->dead_flag == 0)
|
|
|
|
{
|
|
|
|
if (s->pal != 1)
|
|
|
|
{
|
|
|
|
SetPlayerPal(p, PalEntry(63, 63, 0, 0));
|
|
|
|
p->posz -= (16 << 8);
|
|
|
|
s->z -= (16 << 8);
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
if (ud.recstat == 1 && ud.multimode < 2)
|
|
|
|
closedemowrite();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (s->pal != 1)
|
|
|
|
p->dead_flag = (512 - ((krand() & 1) << 10) + (krand() & 255) - 512) & 2047;
|
|
|
|
|
|
|
|
p->jetpack_on = 0;
|
|
|
|
p->holoduke_on = -1;
|
|
|
|
|
2020-07-25 07:32:54 +00:00
|
|
|
if (!isRR())S_StopSound(DUKE_JETPACK_IDLE, pi);
|
|
|
|
S_StopSound(-1, pi, CHAN_VOICE);
|
2020-05-17 21:44:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (s->pal != 1 && (s->cstat & 32768) == 0) s->cstat = 0;
|
|
|
|
|
|
|
|
if (ud.multimode > 1 && (s->pal != 1 || (s->cstat & 32768)))
|
|
|
|
{
|
|
|
|
if (p->frag_ps != snum)
|
|
|
|
{
|
|
|
|
ps[p->frag_ps].frag++;
|
2020-07-14 19:42:46 +00:00
|
|
|
frags[p->frag_ps][snum]++;
|
2020-05-17 21:44:53 +00:00
|
|
|
|
2020-07-15 16:10:31 +00:00
|
|
|
auto pname = &ud.user_name[p->frag_ps][0];
|
2020-05-17 21:44:53 +00:00
|
|
|
if (snum == screenpeek)
|
|
|
|
{
|
2020-07-21 19:32:38 +00:00
|
|
|
Printf(PRINT_NOTIFY, "Killed by %s", pname);
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-21 19:32:38 +00:00
|
|
|
Printf(PRINT_NOTIFY, "Killed %s", pname);
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else p->fraggedself++;
|
2020-05-16 21:55:21 +00:00
|
|
|
|
2020-05-17 21:44:53 +00:00
|
|
|
#if 0
|
|
|
|
if (myconnectindex == connecthead)
|
|
|
|
{
|
|
|
|
sprintf(tempbuf, "frag %d killed %d\n", p->frag_ps + 1, snum + 1);
|
|
|
|
sendscore(tempbuf);
|
2020-07-04 20:44:33 +00:00
|
|
|
// printf(tempbuf);
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
#endif
|
2020-05-16 21:55:21 +00:00
|
|
|
|
2020-05-17 21:44:53 +00:00
|
|
|
p->frag_ps = snum;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (psectlotag == ST_2_UNDERWATER)
|
|
|
|
{
|
|
|
|
if (p->on_warping_sector == 0)
|
|
|
|
{
|
|
|
|
if (abs(p->posz - fz) > (PHEIGHT >> 1))
|
|
|
|
p->posz += 348;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s->z -= 512;
|
|
|
|
s->zvel = -348;
|
|
|
|
}
|
|
|
|
|
|
|
|
clipmove(&p->posx, &p->posy,
|
|
|
|
&p->posz, &p->cursectnum,
|
|
|
|
0, 0, 164L, (4L << 8), (4L << 8), CLIPMASK0);
|
2020-07-04 20:44:33 +00:00
|
|
|
// p->bobcounter += 32;
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
p->oposx = p->posx;
|
|
|
|
p->oposy = p->posy;
|
|
|
|
p->oposz = p->posz;
|
|
|
|
p->oq16ang = p->q16ang;
|
|
|
|
p->opyoff = p->pyoff;
|
|
|
|
|
2020-05-18 16:41:48 +00:00
|
|
|
p->sethoriz(100);
|
2020-05-17 21:44:53 +00:00
|
|
|
p->q16horizoff = 0;
|
|
|
|
|
|
|
|
updatesector(p->posx, p->posy, &p->cursectnum);
|
|
|
|
|
|
|
|
pushmove(&p->posx, &p->posy, &p->posz, &p->cursectnum, 128L, (4L << 8), (20L << 8), CLIPMASK0);
|
|
|
|
|
|
|
|
if (fz > cz + (16 << 8) && s->pal != 1)
|
2020-05-18 20:28:12 +00:00
|
|
|
p->setrotscrnang((p->dead_flag + ((fz + p->posz) >> 7)) & 2047);
|
2020-05-17 21:44:53 +00:00
|
|
|
|
|
|
|
p->on_warping_sector = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int endoflevel(int snum)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
|
|
|
|
// the fist puching the end-of-level thing...
|
|
|
|
p->fist_incs++;
|
|
|
|
if (p->fist_incs == 28)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
if (ud.recstat == 1) closedemowrite();
|
|
|
|
#endif
|
2020-07-25 07:32:54 +00:00
|
|
|
S_PlaySound(PIPEBOMB_EXPLODE);
|
2020-05-17 21:44:53 +00:00
|
|
|
SetPlayerPal(p, PalEntry(48, 64, 64, 64));
|
|
|
|
}
|
|
|
|
if (p->fist_incs > 42)
|
|
|
|
{
|
2020-07-07 15:56:20 +00:00
|
|
|
setnextmap(!!p->buttonpalette);
|
2020-05-17 21:44:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-05-18 22:26:07 +00:00
|
|
|
int timedexit(int snum)
|
2020-05-17 21:44:53 +00:00
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
p->timebeforeexit--;
|
|
|
|
if (p->timebeforeexit == 26 * 5)
|
|
|
|
{
|
|
|
|
FX_StopAllSounds();
|
|
|
|
if (p->customexitsound >= 0)
|
|
|
|
{
|
2020-07-25 07:32:54 +00:00
|
|
|
S_PlaySound(p->customexitsound);
|
2020-05-17 21:44:53 +00:00
|
|
|
FTA(102, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (p->timebeforeexit == 1)
|
|
|
|
{
|
2020-07-07 15:56:20 +00:00
|
|
|
setnextmap(false);
|
2020-05-18 22:26:07 +00:00
|
|
|
return true;
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
2020-05-18 22:26:07 +00:00
|
|
|
return false;
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
|
2020-05-18 06:26:09 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-05-17 21:44:53 +00:00
|
|
|
void playerCrouch(int snum)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
// crouching
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_CROUCH, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
|
|
|
p->posz += (2048 + 768);
|
|
|
|
p->crack_time = 777;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void playerJump(int snum, int fz, int cz)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
if (p->jumping_toggle == 0 && p->jumping_counter == 0)
|
|
|
|
{
|
|
|
|
if ((fz - cz) > (56 << 8))
|
|
|
|
{
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_JUMP, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
|
|
|
p->jumping_counter = 1;
|
|
|
|
p->jumping_toggle = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-17 01:00:43 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void apply_seasick(player_struct* p, double factor)
|
|
|
|
{
|
|
|
|
if (isRRRA() && p->SeaSick)
|
|
|
|
{
|
|
|
|
if (p->SeaSick < 250)
|
|
|
|
{
|
|
|
|
if (p->SeaSick >= 180)
|
|
|
|
p->addrotscrnang(24 * factor);
|
|
|
|
else if (p->SeaSick >= 130)
|
|
|
|
p->addrotscrnang(-24 * factor);
|
|
|
|
else if (p->SeaSick >= 70)
|
|
|
|
p->addrotscrnang(24 * factor);
|
|
|
|
else if (p->SeaSick >= 20)
|
|
|
|
p->addrotscrnang(-24 * factor);
|
|
|
|
}
|
|
|
|
if (p->SeaSick < 250)
|
|
|
|
p->addlookang(((krand() & 255) - 128) * factor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// split off because it can be called from multiple places.
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void applylook(int snum, double factor)
|
2020-05-17 21:44:53 +00:00
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
2020-07-17 01:00:43 +00:00
|
|
|
|
2020-07-29 08:57:06 +00:00
|
|
|
if (p->dead_flag == 0)
|
2020-07-28 02:30:09 +00:00
|
|
|
{
|
|
|
|
p->addrotscrnang(factor * -0.5 * fix16_to_dbl(p->q16rotscrnang));
|
|
|
|
if (abs(p->q16rotscrnang) < FRACUNIT) p->q16rotscrnang = 0;
|
2020-07-17 01:00:43 +00:00
|
|
|
|
2020-07-28 02:30:09 +00:00
|
|
|
p->addlookang(factor * -0.25 * fix16_to_dbl(p->q16look_ang));
|
|
|
|
if (abs(p->q16look_ang) < FRACUNIT) p->q16look_ang = 0;
|
2020-07-17 01:00:43 +00:00
|
|
|
|
2020-07-28 02:30:09 +00:00
|
|
|
if (p->lookLeft)
|
|
|
|
{
|
|
|
|
p->addlookang(factor * -152);
|
|
|
|
p->addrotscrnang(factor * 24);
|
|
|
|
}
|
2020-07-17 01:00:43 +00:00
|
|
|
|
2020-07-28 02:30:09 +00:00
|
|
|
if (p->lookRight)
|
|
|
|
{
|
|
|
|
p->addlookang(factor * 152);
|
|
|
|
p->addrotscrnang(factor * -24);
|
|
|
|
}
|
2020-07-17 01:00:43 +00:00
|
|
|
|
2020-07-28 02:30:09 +00:00
|
|
|
if (p->actorsqu >= 0)
|
|
|
|
{
|
|
|
|
p->q16ang += fix16_from_dbl(factor * (getincangle(p->getang(), getangle(sprite[p->actorsqu].x - p->posx, sprite[p->actorsqu].y - p->posy)) >> 2));
|
|
|
|
}
|
2020-07-28 02:21:35 +00:00
|
|
|
|
2020-07-28 02:30:09 +00:00
|
|
|
if (p->one_eighty_count < 0 && p->on_crane < 0)
|
|
|
|
{
|
|
|
|
fixed_t add = fix16_from_dbl(factor * 128);
|
|
|
|
p->one_eighty_count += add;
|
|
|
|
if (p->one_eighty_count > 0)
|
|
|
|
{
|
|
|
|
// Don't overshoot our target. With variable factor this is possible.
|
|
|
|
add -= p->one_eighty_count;
|
|
|
|
p->one_eighty_count = 0;
|
|
|
|
}
|
|
|
|
p->q16ang += add;
|
|
|
|
}
|
|
|
|
apply_seasick(p, factor);
|
|
|
|
}
|
|
|
|
else
|
2020-07-17 01:00:43 +00:00
|
|
|
{
|
2020-07-28 02:30:09 +00:00
|
|
|
if (p->wackedbyactor >= 0 && sprite[p->wackedbyactor].statnum < MAXSTATUS)
|
2020-07-16 15:59:25 +00:00
|
|
|
{
|
2020-07-28 02:30:09 +00:00
|
|
|
p->q16ang += fix16_from_dbl(factor * (getincangle(p->getang(), getangle(sprite[p->wackedbyactor].x - p->posx, sprite[p->wackedbyactor].y - p->posy)) >> 1));
|
2020-07-16 15:59:25 +00:00
|
|
|
}
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-17 01:00:43 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void checklook(int snum, int sb_snum)
|
2020-05-17 21:44:53 +00:00
|
|
|
{
|
2020-05-18 06:26:09 +00:00
|
|
|
auto p = &ps[snum];
|
2020-07-17 01:00:43 +00:00
|
|
|
|
2020-07-19 17:52:16 +00:00
|
|
|
p->lookLeft = false;
|
2020-07-23 03:34:47 +00:00
|
|
|
p->lookRight = false;
|
2020-07-17 01:00:43 +00:00
|
|
|
if ((sb_snum & SKB_LOOK_LEFT) && !p->OnMotorcycle)
|
2020-05-17 21:44:53 +00:00
|
|
|
{
|
2020-07-17 01:00:43 +00:00
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_LOOKLEFT, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
2020-07-16 15:59:25 +00:00
|
|
|
{
|
2020-07-19 17:52:16 +00:00
|
|
|
p->lookLeft = true;
|
2020-07-16 15:59:25 +00:00
|
|
|
}
|
2020-07-17 01:00:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((sb_snum & SKB_LOOK_RIGHT) && !p->OnMotorcycle)
|
|
|
|
{
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_LOOKRIGHT, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
2020-07-19 17:52:16 +00:00
|
|
|
p->lookRight = true;
|
2020-07-17 01:00:43 +00:00
|
|
|
}
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
2020-07-17 01:00:43 +00:00
|
|
|
p->oq16ang = p->q16ang;
|
2020-07-28 12:12:09 +00:00
|
|
|
p->oq16look_ang = p->q16look_ang;
|
2020-07-28 12:24:30 +00:00
|
|
|
p->oq16rotscrnang = p->q16rotscrnang;
|
2020-07-17 01:00:43 +00:00
|
|
|
|
2020-07-28 11:38:20 +00:00
|
|
|
if (cl_syncinput)
|
2020-07-17 01:00:43 +00:00
|
|
|
applylook(snum, 1);
|
2020-05-17 21:44:53 +00:00
|
|
|
}
|
2020-05-18 06:26:09 +00:00
|
|
|
|
2020-07-17 01:00:43 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void sethorizon(int snum, int sb_snum, double factor, bool frominput)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
|
|
|
|
// Calculate adjustment as true pitch (Fixed point nath really sucks...)
|
2020-07-19 17:52:16 +00:00
|
|
|
if (p->horizAngleAdjust)
|
2020-07-17 01:00:43 +00:00
|
|
|
{
|
2020-07-19 17:52:16 +00:00
|
|
|
double horizAngle = atan2(p->q16horiz - F16(100), F16(128)) * (512. / pi::pi()) +factor * p->horizAngleAdjust;
|
2020-07-17 01:00:43 +00:00
|
|
|
p->q16horiz = F16(100) + int(F16(128) * tan(horizAngle * (pi::pi() / 512.)));
|
|
|
|
}
|
|
|
|
else if (p->return_to_center > 0 && (sb_snum & (SKB_LOOK_UP | SKB_LOOK_DOWN)) == 0) // only snap back if no relevant button is pressed.
|
|
|
|
{
|
2020-07-18 12:30:17 +00:00
|
|
|
if (!frominput) p->return_to_center--;
|
2020-07-17 01:00:43 +00:00
|
|
|
p->q16horiz += factor * (frominput? 2.016 : 1.) * (F16(33) - (p->q16horiz / 3)); // in P_GetInput this used different factors than in the original code. Hm...
|
|
|
|
}
|
|
|
|
|
2020-07-19 17:52:16 +00:00
|
|
|
p->q16horiz += int(factor * p->horizSkew);
|
2020-07-17 01:00:43 +00:00
|
|
|
|
|
|
|
if (p->aim_mode == 0)
|
|
|
|
{
|
|
|
|
// threshold was 5
|
|
|
|
if (p->q16horiz > F16(99) && p->q16horiz < F16(101)) p->sethoriz(100);
|
|
|
|
if (p->q16horizoff > F16(-1) && p->q16horizoff < F16(1)) p->sethorizoff(0);
|
|
|
|
}
|
|
|
|
p->q16horiz = clamp(p->q16horiz, F16(HORIZ_MIN), F16(HORIZ_MAX));
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-05-18 06:26:09 +00:00
|
|
|
void playerCenterView(int snum)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_RETURNTOCENTER, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
|
|
|
p->return_to_center = 9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-18 22:26:07 +00:00
|
|
|
void horizAngleAdjust(int snum, int delta)
|
|
|
|
{
|
2020-07-19 17:52:16 +00:00
|
|
|
ps[snum].horizAngleAdjust = delta;
|
2020-05-18 22:26:07 +00:00
|
|
|
}
|
|
|
|
|
2020-07-06 11:26:26 +00:00
|
|
|
void playerLookUp(int snum, ESyncBits sb_snum)
|
2020-05-18 06:26:09 +00:00
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_LOOKUP, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
|
|
|
p->return_to_center = 9;
|
2020-05-18 22:26:07 +00:00
|
|
|
horizAngleAdjust(snum, (sb_snum & SKB_RUN) ? 12 : 24);
|
2020-05-18 06:26:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-06 11:26:26 +00:00
|
|
|
void playerLookDown(int snum, ESyncBits sb_snum)
|
2020-05-18 06:26:09 +00:00
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_LOOKDOWN, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
|
|
|
p->return_to_center = 9;
|
2020-05-18 22:26:07 +00:00
|
|
|
horizAngleAdjust(snum, (sb_snum & SKB_RUN) ? -12 : -24);
|
2020-05-18 06:26:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-06 11:26:26 +00:00
|
|
|
void playerAimUp(int snum, ESyncBits sb_snum)
|
2020-05-18 06:26:09 +00:00
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_AIMUP, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
2020-05-18 22:26:07 +00:00
|
|
|
horizAngleAdjust(snum, (sb_snum & SKB_RUN) ? 6 : 12);
|
2020-05-18 06:26:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-06 11:26:26 +00:00
|
|
|
void playerAimDown(int snum, ESyncBits sb_snum)
|
2020-05-18 06:26:09 +00:00
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
SetGameVarID(g_iReturnVarID, 0, p->i, snum);
|
|
|
|
OnEvent(EVENT_AIMDOWN, p->i, snum, -1);
|
|
|
|
if (GetGameVarID(g_iReturnVarID, p->i, snum) == 0)
|
|
|
|
{
|
2020-05-18 22:26:07 +00:00
|
|
|
horizAngleAdjust(snum, (sb_snum & SKB_RUN) ? -6 : -12);
|
2020-05-18 06:26:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-17 23:34:13 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// split out so that the weapon check can be done right.
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool movementBlocked(int snum)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
|
|
|
|
|
|
|
auto blockingweapon = [=]()
|
|
|
|
{
|
|
|
|
if (isRR()) return false;
|
|
|
|
if (isWW2GI()) return aplWeaponWorksLike[p->curr_weapon][snum] == TRIPBOMB_WEAPON;
|
|
|
|
else return p->curr_weapon == TRIPBOMB_WEAPON;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto weapondelay = [=]()
|
|
|
|
{
|
|
|
|
if (isWW2GI()) return aplWeaponFireDelay[p->curr_weapon][snum];
|
|
|
|
else return 4;
|
|
|
|
};
|
|
|
|
|
|
|
|
return (p->fist_incs ||
|
|
|
|
p->transporter_hold > 2 ||
|
|
|
|
p->hard_landing ||
|
|
|
|
p->access_incs > 0 ||
|
|
|
|
p->knee_incs > 0 ||
|
|
|
|
(blockingweapon() && p->kickback_pic > 1 && p->kickback_pic < weapondelay()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-19 19:21:55 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int haskey(int sect, int snum)
|
|
|
|
{
|
|
|
|
auto p = &ps[snum];
|
2020-07-19 21:09:10 +00:00
|
|
|
if (!sectorextra[sect])
|
2020-05-19 19:21:55 +00:00
|
|
|
return 1;
|
2020-07-19 21:09:10 +00:00
|
|
|
if (sectorextra[sect] > 6)
|
2020-05-19 19:21:55 +00:00
|
|
|
return 1;
|
2020-07-19 21:09:10 +00:00
|
|
|
int wk = sectorextra[sect];
|
2020-05-19 19:21:55 +00:00
|
|
|
if (wk > 3)
|
|
|
|
wk -= 3;
|
|
|
|
|
|
|
|
if (p->keys[wk] == 1)
|
|
|
|
{
|
2020-07-19 21:09:10 +00:00
|
|
|
sectorextra[sect] = 0;
|
2020-05-19 19:21:55 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-04 20:44:33 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// view - as in third person view (stupid name for this function)
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool view(struct player_struct* pp, int* vx, int* vy, int* vz, short* vsectnum, int ang, int horiz)
|
|
|
|
{
|
|
|
|
spritetype* sp;
|
2020-07-05 06:58:13 +00:00
|
|
|
int i, nx, ny, nz, hx, hy, hitx, hity, hitz;
|
2020-07-04 20:44:33 +00:00
|
|
|
short bakcstat, hitsect, hitwall, hitsprite, daang;
|
|
|
|
|
|
|
|
nx = (sintable[(ang + 1536) & 2047] >> 4);
|
|
|
|
ny = (sintable[(ang + 1024) & 2047] >> 4);
|
|
|
|
nz = (horiz - 100) * 128;
|
|
|
|
|
|
|
|
sp = &sprite[pp->i];
|
|
|
|
|
|
|
|
bakcstat = sp->cstat;
|
|
|
|
sp->cstat &= (short)~0x101;
|
|
|
|
|
|
|
|
updatesectorz(*vx, *vy, *vz, vsectnum);
|
|
|
|
hitscan(*vx, *vy, *vz, *vsectnum, nx, ny, nz, &hitsect, &hitwall, &hitsprite, &hitx, &hity, &hitz, CLIPMASK1);
|
|
|
|
|
|
|
|
if (*vsectnum < 0)
|
|
|
|
{
|
|
|
|
sp->cstat = bakcstat;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
hx = hitx - (*vx); hy = hity - (*vy);
|
|
|
|
if (abs(nx) + abs(ny) > abs(hx) + abs(hy))
|
|
|
|
{
|
|
|
|
*vsectnum = hitsect;
|
|
|
|
if (hitwall >= 0)
|
|
|
|
{
|
|
|
|
daang = getangle(wall[wall[hitwall].point2].x - wall[hitwall].x,
|
|
|
|
wall[wall[hitwall].point2].y - wall[hitwall].y);
|
|
|
|
|
|
|
|
i = nx * sintable[daang] + ny * sintable[(daang + 1536) & 2047];
|
|
|
|
if (abs(nx) > abs(ny)) hx -= mulscale28(nx, i);
|
|
|
|
else hy -= mulscale28(ny, i);
|
|
|
|
}
|
|
|
|
else if (hitsprite < 0)
|
|
|
|
{
|
|
|
|
if (abs(nx) > abs(ny)) hx -= (nx >> 5);
|
|
|
|
else hy -= (ny >> 5);
|
|
|
|
}
|
|
|
|
if (abs(nx) > abs(ny)) i = divscale16(hx, nx);
|
|
|
|
else i = divscale16(hy, ny);
|
|
|
|
if (i < cameradist) cameradist = i;
|
|
|
|
}
|
|
|
|
*vx = (*vx) + mulscale16(nx, cameradist);
|
|
|
|
*vy = (*vy) + mulscale16(ny, cameradist);
|
|
|
|
*vz = (*vz) + mulscale16(nz, cameradist);
|
|
|
|
|
|
|
|
cameradist = min(cameradist + (((int)totalclock - cameraclock) << 10), 65536);
|
|
|
|
cameraclock = (int)totalclock;
|
|
|
|
|
|
|
|
updatesectorz(*vx, *vy, *vz, vsectnum);
|
|
|
|
|
|
|
|
sp->cstat = bakcstat;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-14 10:14:03 +00:00
|
|
|
END_DUKE_NS
|