2020-05-14 10:14:03 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1996, 2003 - 3D Realms Entertainment
|
|
|
|
Copyright (C) 2000, 2003 - Matt Saettler (EDuke Enhancements)
|
|
|
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
2020-05-16 21:55:21 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// setpal
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void setpal_(struct player_struct* p) // cannot be activated yet.
|
|
|
|
{
|
|
|
|
int palette;;
|
|
|
|
if (p->DrugMode) palette = DRUGPAL;
|
|
|
|
else if (p->heat_on || (sector[p->cursectnum].ceilingpicnum >= TILE_FLOORSLIME && sector[p->cursectnum].ceilingpicnum <= TILE_FLOORSLIME+2)) palette = SLIMEPAL;
|
|
|
|
else if (sector[p->cursectnum].lotag == 2) palette = WATERPAL;
|
|
|
|
else palette = BASEPAL;
|
|
|
|
videoSetPalette(palette, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
p->q16horiz += 64 << FRACBITS;
|
|
|
|
p->return_to_center = 9;
|
|
|
|
p->look_ang = n >> 1;
|
|
|
|
p->rotscrnang = n >> 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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;
|
|
|
|
int aimstats[] = { 10,13,1,2 };
|
|
|
|
int dx1, dy1, dx2, dy2, dx3, dy3, smax, sdist;
|
|
|
|
int xv, yv;
|
|
|
|
|
|
|
|
a = s->ang;
|
|
|
|
|
|
|
|
// Autoaim from DukeGDX.
|
|
|
|
if (s->picnum == TILE_APLAYER && ps[s->yvel].auto_aim == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
j = -1;
|
|
|
|
// if(s->picnum == TILE_APLAYER && ps[s->yvel].aim_mode) return -1;
|
|
|
|
|
|
|
|
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)
|
|
|
|
a = (abs(scale(sp->z - s->z, 10, sdist) - (ps[s->yvel].gethorizdiff() - 100)) < 100);
|
|
|
|
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-14 10:14:03 +00:00
|
|
|
END_DUKE_NS
|