mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-25 11:10:47 +00:00
efdd31d5a9
It is unacceptable that yvel is on one hand modifiable without restriction from scripting, but can be used as an array index without prior bound check in the C code. Because that member has an overloaded meaning and is also used for innocuous purposes such as the green color intensity of an SE light, it's infeasible to restrict access from scripting. Consequently, we must add bound checks on the C side. This is the first part of the effort to make .yvel safe, adding two functions P_Get() and P_GetP(). There are a couple of other uses as some kind of index. git-svn-id: https://svn.eduke32.com/eduke32@4226 1a8010ca-5511-0410-912e-c29ae57300e0
3363 lines
104 KiB
C
3363 lines
104 KiB
C
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 2010 EDuke32 developers and contributors
|
|
|
|
This file is part of EDuke32.
|
|
|
|
EDuke32 is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License version 2
|
|
as published by the Free Software Foundation.
|
|
|
|
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.
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "duke3d.h"
|
|
#include "sector.h"
|
|
#include "gamedef.h"
|
|
#include "gameexec.h"
|
|
#include "premap.h"
|
|
#include "osd.h"
|
|
#include "common_game.h"
|
|
#include "input.h"
|
|
|
|
// PRIMITIVE
|
|
|
|
static int32_t g_haltSoundHack = 0;
|
|
|
|
// this function activates a sector's MUSICANDSFX sprite
|
|
int32_t A_CallSound(int32_t sn,int32_t whatsprite)
|
|
{
|
|
int32_t i;
|
|
|
|
if (g_haltSoundHack)
|
|
{
|
|
g_haltSoundHack = 0;
|
|
return -1;
|
|
}
|
|
|
|
for (SPRITES_OF_SECT(sn, i))
|
|
{
|
|
if (PN == MUSICANDSFX && (unsigned)SLT < 1000) // XXX: in other places, 999
|
|
{
|
|
if (whatsprite == -1) whatsprite = i;
|
|
|
|
if (T1 == 0)
|
|
{
|
|
if ((g_sounds[SLT].m & SF_GLOBAL) == 0)
|
|
{
|
|
if (SLT)
|
|
{
|
|
A_PlaySound(SLT,whatsprite);
|
|
if (SHT && SLT != SHT && SHT < MAXSOUNDS)
|
|
S_StopEnvSound(SHT,T6);
|
|
T6 = whatsprite;
|
|
}
|
|
|
|
if ((sector[SECT].lotag&0xff) != ST_22_SPLITTING_DOOR)
|
|
T1 = 1;
|
|
}
|
|
}
|
|
else if (SHT < MAXSOUNDS)
|
|
{
|
|
if (SHT) A_PlaySound(SHT,whatsprite);
|
|
if ((g_sounds[SLT].m & SF_LOOP) || (SHT && SHT != SLT))
|
|
S_StopEnvSound(SLT,T6);
|
|
T6 = whatsprite;
|
|
T1 = 0;
|
|
}
|
|
return SLT;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int32_t G_CheckActivatorMotion(int32_t lotag)
|
|
{
|
|
int32_t i = headspritestat[STAT_ACTIVATOR], j;
|
|
spritetype *s;
|
|
|
|
while (i >= 0)
|
|
{
|
|
if (sprite[i].lotag == lotag)
|
|
{
|
|
s = &sprite[i];
|
|
|
|
for (j = g_animateCount-1; j >= 0; j--)
|
|
if (s->sectnum == animatesect[j])
|
|
return(1);
|
|
|
|
j = headspritestat[STAT_EFFECTOR];
|
|
while (j >= 0)
|
|
{
|
|
if (s->sectnum == sprite[j].sectnum)
|
|
switch (sprite[j].lotag)
|
|
{
|
|
case SE_11_SWINGING_DOOR:
|
|
case SE_30_TWO_WAY_TRAIN:
|
|
if (actor[j].t_data[4])
|
|
return(1);
|
|
break;
|
|
case SE_20_STRETCH_BRIDGE:
|
|
case SE_31_FLOOR_RISE_FALL:
|
|
case SE_32_CEILING_RISE_FALL:
|
|
case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
|
|
if (actor[j].t_data[0])
|
|
return(1);
|
|
break;
|
|
}
|
|
|
|
j = nextspritestat[j];
|
|
}
|
|
}
|
|
i = nextspritestat[i];
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int32_t CheckDoorTile(int32_t dapic)
|
|
{
|
|
switch (DYNAMICTILEMAP(dapic))
|
|
{
|
|
case DOORTILE1__STATIC:
|
|
case DOORTILE2__STATIC:
|
|
case DOORTILE3__STATIC:
|
|
case DOORTILE4__STATIC:
|
|
case DOORTILE5__STATIC:
|
|
case DOORTILE6__STATIC:
|
|
case DOORTILE7__STATIC:
|
|
case DOORTILE8__STATIC:
|
|
case DOORTILE9__STATIC:
|
|
case DOORTILE10__STATIC:
|
|
case DOORTILE11__STATIC:
|
|
case DOORTILE12__STATIC:
|
|
case DOORTILE14__STATIC:
|
|
case DOORTILE15__STATIC:
|
|
case DOORTILE16__STATIC:
|
|
case DOORTILE17__STATIC:
|
|
case DOORTILE18__STATIC:
|
|
case DOORTILE19__STATIC:
|
|
case DOORTILE20__STATIC:
|
|
case DOORTILE21__STATIC:
|
|
case DOORTILE22__STATIC:
|
|
case DOORTILE23__STATIC:
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int32_t isanunderoperator(int32_t lotag)
|
|
{
|
|
switch (lotag&0xff)
|
|
{
|
|
case ST_15_WARP_ELEVATOR:
|
|
case ST_16_PLATFORM_DOWN:
|
|
case ST_17_PLATFORM_UP:
|
|
case ST_18_ELEVATOR_DOWN:
|
|
case ST_19_ELEVATOR_UP:
|
|
case ST_22_SPLITTING_DOOR:
|
|
case ST_26_SPLITTING_ST_DOOR:
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int32_t isanearoperator(int32_t lotag)
|
|
{
|
|
switch (lotag&0xff)
|
|
{
|
|
case ST_9_SLIDING_ST_DOOR:
|
|
case ST_15_WARP_ELEVATOR:
|
|
case ST_16_PLATFORM_DOWN:
|
|
case ST_17_PLATFORM_UP:
|
|
case ST_18_ELEVATOR_DOWN:
|
|
case ST_19_ELEVATOR_UP:
|
|
case ST_20_CEILING_DOOR:
|
|
case ST_21_FLOOR_DOOR:
|
|
case ST_22_SPLITTING_DOOR:
|
|
case ST_23_SWINGING_DOOR:
|
|
case ST_25_SLIDING_DOOR:
|
|
case ST_26_SPLITTING_ST_DOOR:
|
|
case ST_29_TEETH_DOOR://Toothed door
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline int32_t A_FP_ManhattanDist(const DukePlayer_t *ps, const spritetype *s)
|
|
{
|
|
return klabs(ps->opos.x-s->x)
|
|
+ klabs(ps->opos.y-s->y)
|
|
+ ((klabs(ps->opos.z-s->z+(28<<8)))>>4);
|
|
}
|
|
|
|
int32_t __fastcall A_FindPlayer(const spritetype *s, int32_t *d)
|
|
{
|
|
if (!g_netServer && ud.multimode < 2)
|
|
{
|
|
DukePlayer_t *const myps = g_player[myconnectindex].ps;
|
|
|
|
if (d)
|
|
*d = A_FP_ManhattanDist(myps, s);
|
|
return myconnectindex;
|
|
}
|
|
|
|
{
|
|
int32_t j;
|
|
int32_t closest_player=0, closest=INT32_MAX;
|
|
|
|
for (TRAVERSE_CONNECT(j))
|
|
{
|
|
DukePlayer_t *const ps = g_player[j].ps;
|
|
int32_t x = A_FP_ManhattanDist(ps, s);
|
|
|
|
if (x < closest && sprite[ps->i].extra > 0)
|
|
{
|
|
closest_player = j;
|
|
closest = x;
|
|
}
|
|
}
|
|
|
|
if (d)
|
|
*d = closest;
|
|
return closest_player;
|
|
}
|
|
}
|
|
|
|
void G_DoSectorAnimations(void)
|
|
{
|
|
int32_t i, j, a, p, v, dasect;
|
|
|
|
for (i=g_animateCount-1; i>=0; i--)
|
|
{
|
|
a = *animateptr[i];
|
|
v = animatevel[i]*TICSPERFRAME;
|
|
dasect = animatesect[i];
|
|
|
|
if (a == animategoal[i])
|
|
{
|
|
G_StopInterpolation(animateptr[i]);
|
|
|
|
// This fixes a bug where wall or floor sprites contained in
|
|
// elevator sectors (ST 16-19) would jitter vertically after the
|
|
// elevator had stopped.
|
|
if (animateptr[i] == §or[animatesect[i]].floorz)
|
|
for (j=headspritesect[dasect]; j>=0; j=nextspritesect[j])
|
|
if (sprite[j].statnum != STAT_EFFECTOR)
|
|
actor[j].bpos.z = sprite[j].z;
|
|
|
|
g_animateCount--;
|
|
animateptr[i] = animateptr[g_animateCount];
|
|
animategoal[i] = animategoal[g_animateCount];
|
|
animatevel[i] = animatevel[g_animateCount];
|
|
animatesect[i] = animatesect[g_animateCount];
|
|
if (sector[animatesect[i]].lotag == ST_18_ELEVATOR_DOWN || sector[animatesect[i]].lotag == ST_19_ELEVATOR_UP)
|
|
if (animateptr[i] == §or[animatesect[i]].ceilingz)
|
|
continue;
|
|
|
|
if ((sector[dasect].lotag&0xff) != ST_22_SPLITTING_DOOR)
|
|
A_CallSound(dasect,-1);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (v > 0)
|
|
{
|
|
a = min(a+v,animategoal[i]);
|
|
}
|
|
else
|
|
{
|
|
a = max(a+v,animategoal[i]);
|
|
}
|
|
|
|
if (animateptr[i] == §or[animatesect[i]].floorz)
|
|
{
|
|
for (TRAVERSE_CONNECT(p))
|
|
if (g_player[p].ps->cursectnum == dasect)
|
|
if ((sector[dasect].floorz-g_player[p].ps->pos.z) < (64<<8))
|
|
if (sprite[g_player[p].ps->i].owner >= 0)
|
|
{
|
|
g_player[p].ps->pos.z += v;
|
|
g_player[p].ps->vel.z = 0;
|
|
if (p == myconnectindex)
|
|
{
|
|
my.z += v;
|
|
myvel.z = 0;
|
|
}
|
|
}
|
|
|
|
for (j=headspritesect[dasect]; j>=0; j=nextspritesect[j])
|
|
if (sprite[j].statnum != STAT_EFFECTOR)
|
|
{
|
|
actor[j].bpos.z = sprite[j].z;
|
|
sprite[j].z += v;
|
|
actor[j].floorz = sector[dasect].floorz+v;
|
|
}
|
|
}
|
|
|
|
*animateptr[i] = a;
|
|
}
|
|
}
|
|
|
|
int32_t GetAnimationGoal(const int32_t *animptr)
|
|
{
|
|
int32_t i = g_animateCount-1;
|
|
|
|
for (; i>=0; i--)
|
|
if (animptr == animateptr[i])
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
int32_t SetAnimation(int32_t animsect,int32_t *animptr, int32_t thegoal, int32_t thevel)
|
|
{
|
|
int32_t i = 0, j = g_animateCount;
|
|
|
|
if (g_animateCount >= MAXANIMATES)
|
|
return(-1);
|
|
|
|
for (; i<g_animateCount; i++)
|
|
if (animptr == animateptr[i])
|
|
{
|
|
j = i;
|
|
break;
|
|
}
|
|
|
|
animatesect[j] = animsect;
|
|
animateptr[j] = animptr;
|
|
animategoal[j] = thegoal;
|
|
animatevel[j] = (thegoal >= *animptr) ? thevel : -thevel;
|
|
|
|
if (j == g_animateCount) g_animateCount++;
|
|
|
|
G_SetInterpolation(animptr);
|
|
|
|
return(j);
|
|
}
|
|
|
|
void G_AnimateCamSprite(void)
|
|
{
|
|
int32_t i = g_curViewscreen;
|
|
|
|
#ifdef DEBUG_VALGRIND_NO_SMC
|
|
return;
|
|
#endif
|
|
if (g_curViewscreen < 0)
|
|
return;
|
|
|
|
if (T1 >= 4)
|
|
{
|
|
const DukePlayer_t *ps = g_player[screenpeek].ps;
|
|
T1 = 0;
|
|
|
|
if (ps->newowner >= 0)
|
|
OW = ps->newowner;
|
|
else if (OW >= 0 && dist(&sprite[ps->i], &sprite[i]) < 8192)
|
|
{
|
|
if (waloff[TILE_VIEWSCR] == 0)
|
|
allocatepermanenttile(TILE_VIEWSCR,tilesizx[PN],tilesizy[PN]);
|
|
else
|
|
walock[TILE_VIEWSCR] = 255;
|
|
|
|
G_SetupCamTile(OW, TILE_VIEWSCR);
|
|
#ifdef POLYMER
|
|
// HACK: force texture update on viewscreen sprite in Polymer!
|
|
if (getrendermode() == REND_POLYMER)
|
|
sprite[i].filler ^= (1<<1);
|
|
#endif
|
|
}
|
|
}
|
|
else T1++;
|
|
}
|
|
|
|
void G_AnimateWalls(void)
|
|
{
|
|
int32_t i, j, p = g_numAnimWalls-1, t;
|
|
|
|
for (; p>=0; p--)
|
|
// for(p=g_numAnimWalls-1;p>=0;p--)
|
|
{
|
|
i = animwall[p].wallnum;
|
|
j = wall[i].picnum;
|
|
|
|
switch (DYNAMICTILEMAP(j))
|
|
{
|
|
case SCREENBREAK1__STATIC:
|
|
case SCREENBREAK2__STATIC:
|
|
case SCREENBREAK3__STATIC:
|
|
case SCREENBREAK4__STATIC:
|
|
case SCREENBREAK5__STATIC:
|
|
|
|
case SCREENBREAK9__STATIC:
|
|
case SCREENBREAK10__STATIC:
|
|
case SCREENBREAK11__STATIC:
|
|
case SCREENBREAK12__STATIC:
|
|
case SCREENBREAK13__STATIC:
|
|
case SCREENBREAK14__STATIC:
|
|
case SCREENBREAK15__STATIC:
|
|
case SCREENBREAK16__STATIC:
|
|
case SCREENBREAK17__STATIC:
|
|
case SCREENBREAK18__STATIC:
|
|
case SCREENBREAK19__STATIC:
|
|
|
|
if ((krand()&255) < 16)
|
|
{
|
|
animwall[p].tag = wall[i].picnum;
|
|
wall[i].picnum = SCREENBREAK6;
|
|
}
|
|
|
|
continue;
|
|
|
|
case SCREENBREAK6__STATIC:
|
|
case SCREENBREAK7__STATIC:
|
|
case SCREENBREAK8__STATIC:
|
|
|
|
if (animwall[p].tag >= 0 && wall[i].extra != FEMPIC2 && wall[i].extra != FEMPIC3)
|
|
wall[i].picnum = animwall[p].tag;
|
|
else
|
|
{
|
|
wall[i].picnum++;
|
|
if (wall[i].picnum == (SCREENBREAK6+3))
|
|
wall[i].picnum = SCREENBREAK6;
|
|
}
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((wall[i].cstat&16) && G_GetForcefieldPicnum(i)==W_FORCEFIELD)
|
|
{
|
|
t = animwall[p].tag;
|
|
|
|
if (wall[i].cstat&254)
|
|
{
|
|
wall[i].xpanning -= t>>10; // sintable[(t+512)&2047]>>12;
|
|
wall[i].ypanning -= t>>10; // sintable[t&2047]>>12;
|
|
|
|
if (wall[i].extra == 1)
|
|
{
|
|
wall[i].extra = 0;
|
|
animwall[p].tag = 0;
|
|
}
|
|
else
|
|
animwall[p].tag+=128;
|
|
|
|
if (animwall[p].tag < (128<<4))
|
|
{
|
|
if (animwall[p].tag&128)
|
|
wall[i].overpicnum = W_FORCEFIELD;
|
|
else wall[i].overpicnum = W_FORCEFIELD+1;
|
|
}
|
|
else
|
|
{
|
|
if ((krand()&255) < 32)
|
|
animwall[p].tag = 128<<(krand()&3);
|
|
else wall[i].overpicnum = W_FORCEFIELD+1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int32_t G_ActivateWarpElevators(int32_t s, int32_t d) //Parm = sectoreffectornum
|
|
{
|
|
int32_t i = headspritestat[STAT_EFFECTOR], sn = sprite[s].sectnum;
|
|
|
|
while (i >= 0)
|
|
{
|
|
if (SLT == SE_17_WARP_ELEVATOR && SHT == sprite[s].hitag)
|
|
if ((klabs(sector[sn].floorz-actor[s].t_data[2]) > SP) ||
|
|
(sector[SECT].hitag == (sector[sn].hitag-d)))
|
|
break;
|
|
i = nextspritestat[i];
|
|
}
|
|
|
|
if (i == -1)
|
|
return 1; // No find
|
|
else
|
|
A_PlaySound(d ? ELEVATOR_ON : ELEVATOR_OFF, s);
|
|
|
|
i = headspritestat[STAT_EFFECTOR];
|
|
do
|
|
{
|
|
if (SLT == SE_17_WARP_ELEVATOR && SHT == sprite[s].hitag)
|
|
T1 = T2 = d; //Make all check warp
|
|
i = nextspritestat[i];
|
|
}
|
|
while (i >= 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void G_OperateSectors(int32_t sn, int32_t ii)
|
|
{
|
|
int32_t j=0, l, q, startwall, endwall;
|
|
int32_t i;
|
|
sectortype *sptr = §or[sn];
|
|
|
|
switch (sptr->lotag&(0xffff-49152))
|
|
{
|
|
|
|
case ST_30_ROTATE_RISE_BRIDGE:
|
|
j = sector[sn].hitag;
|
|
if (actor[j].tempang == 0 || actor[j].tempang == 256)
|
|
A_CallSound(sn,ii);
|
|
if (sprite[j].extra == 1)
|
|
sprite[j].extra = 3;
|
|
else sprite[j].extra = 1;
|
|
break;
|
|
|
|
case ST_31_TWO_WAY_TRAIN:
|
|
|
|
j = sector[sn].hitag;
|
|
if (actor[j].t_data[4] == 0)
|
|
actor[j].t_data[4] = 1;
|
|
|
|
A_CallSound(sn,ii);
|
|
break;
|
|
|
|
case ST_26_SPLITTING_ST_DOOR: //The split doors
|
|
if (GetAnimationGoal(&sptr->ceilingz) == -1) //if the door has stopped
|
|
{
|
|
g_haltSoundHack = 1;
|
|
sptr->lotag &= 0xff00;
|
|
sptr->lotag |= ST_22_SPLITTING_DOOR;
|
|
G_OperateSectors(sn,ii);
|
|
sptr->lotag &= 0xff00;
|
|
sptr->lotag |= ST_9_SLIDING_ST_DOOR;
|
|
G_OperateSectors(sn,ii);
|
|
sptr->lotag &= 0xff00;
|
|
sptr->lotag |= ST_26_SPLITTING_ST_DOOR;
|
|
}
|
|
return;
|
|
|
|
case ST_9_SLIDING_ST_DOOR:
|
|
{
|
|
int32_t dax,day,dax2,day2,sp;
|
|
int32_t wallfind[2];
|
|
|
|
startwall = sptr->wallptr;
|
|
endwall = startwall+sptr->wallnum-1;
|
|
|
|
sp = sptr->extra>>4;
|
|
|
|
//first find center point by averaging all points
|
|
dax = 0L, day = 0L;
|
|
for (i=startwall; i<=endwall; i++)
|
|
{
|
|
dax += wall[i].x;
|
|
day += wall[i].y;
|
|
}
|
|
dax /= (endwall-startwall+1);
|
|
day /= (endwall-startwall+1);
|
|
|
|
//find any points with either same x or same y coordinate
|
|
// as center (dax, day) - should be 2 points found.
|
|
wallfind[0] = -1;
|
|
wallfind[1] = -1;
|
|
for (i=startwall; i<=endwall; i++)
|
|
if ((wall[i].x == dax) || (wall[i].y == day))
|
|
{
|
|
if (wallfind[0] == -1)
|
|
wallfind[0] = i;
|
|
else wallfind[1] = i;
|
|
}
|
|
|
|
if (wallfind[1] == -1)
|
|
return;
|
|
|
|
for (j=0; j<2; j++)
|
|
{
|
|
if ((wall[wallfind[j]].x == dax) && (wall[wallfind[j]].y == day))
|
|
{
|
|
//find what direction door should open by averaging the
|
|
// 2 neighboring points of wallfind[0] & wallfind[1].
|
|
i = wallfind[j]-1;
|
|
if (i < startwall) i = endwall;
|
|
dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
|
|
day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
|
|
if (dax2 != 0)
|
|
{
|
|
dax2 = wall[wall[wall[wallfind[j]].point2].point2].x;
|
|
dax2 -= wall[wall[wallfind[j]].point2].x;
|
|
SetAnimation(sn,&wall[wallfind[j]].x,wall[wallfind[j]].x+dax2,sp);
|
|
SetAnimation(sn,&wall[i].x,wall[i].x+dax2,sp);
|
|
SetAnimation(sn,&wall[wall[wallfind[j]].point2].x,wall[wall[wallfind[j]].point2].x+dax2,sp);
|
|
A_CallSound(sn,ii);
|
|
}
|
|
else if (day2 != 0)
|
|
{
|
|
day2 = wall[wall[wall[wallfind[j]].point2].point2].y;
|
|
day2 -= wall[wall[wallfind[j]].point2].y;
|
|
SetAnimation(sn,&wall[wallfind[j]].y,wall[wallfind[j]].y+day2,sp);
|
|
SetAnimation(sn,&wall[i].y,wall[i].y+day2,sp);
|
|
SetAnimation(sn,&wall[wall[wallfind[j]].point2].y,wall[wall[wallfind[j]].point2].y+day2,sp);
|
|
A_CallSound(sn,ii);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i = wallfind[j]-1;
|
|
if (i < startwall) i = endwall;
|
|
dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
|
|
day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
|
|
if (dax2 != 0)
|
|
{
|
|
SetAnimation(sn,&wall[wallfind[j]].x,dax,sp);
|
|
SetAnimation(sn,&wall[i].x,dax+dax2,sp);
|
|
SetAnimation(sn,&wall[wall[wallfind[j]].point2].x,dax+dax2,sp);
|
|
A_CallSound(sn,ii);
|
|
}
|
|
else if (day2 != 0)
|
|
{
|
|
SetAnimation(sn,&wall[wallfind[j]].y,day,sp);
|
|
SetAnimation(sn,&wall[i].y,day+day2,sp);
|
|
SetAnimation(sn,&wall[wall[wallfind[j]].point2].y,day+day2,sp);
|
|
A_CallSound(sn,ii);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
return;
|
|
|
|
case ST_15_WARP_ELEVATOR://Warping elevators
|
|
|
|
if (sprite[ii].picnum != APLAYER) return;
|
|
|
|
i = headspritesect[sn];
|
|
while (i >= 0)
|
|
{
|
|
if (PN==SECTOREFFECTOR && SLT == SE_17_WARP_ELEVATOR) break;
|
|
i = nextspritesect[i];
|
|
}
|
|
|
|
if (sprite[ii].sectnum == sn)
|
|
{
|
|
if (G_ActivateWarpElevators(i,-1))
|
|
G_ActivateWarpElevators(i,1);
|
|
else if (G_ActivateWarpElevators(i,1))
|
|
G_ActivateWarpElevators(i,-1);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (sptr->floorz > SZ)
|
|
G_ActivateWarpElevators(i,-1);
|
|
else
|
|
G_ActivateWarpElevators(i,1);
|
|
}
|
|
|
|
return;
|
|
|
|
case ST_16_PLATFORM_DOWN:
|
|
case ST_17_PLATFORM_UP:
|
|
|
|
i = GetAnimationGoal(&sptr->floorz);
|
|
|
|
if (i == -1)
|
|
{
|
|
i = nextsectorneighborz(sn,sptr->floorz,1,1);
|
|
if (i == -1)
|
|
{
|
|
i = nextsectorneighborz(sn,sptr->floorz,1,-1);
|
|
if (i == -1) return;
|
|
j = sector[i].floorz;
|
|
SetAnimation(sn,&sptr->floorz,j,sptr->extra);
|
|
}
|
|
else
|
|
{
|
|
j = sector[i].floorz;
|
|
SetAnimation(sn,&sptr->floorz,j,sptr->extra);
|
|
}
|
|
A_CallSound(sn,ii);
|
|
}
|
|
|
|
return;
|
|
|
|
case ST_18_ELEVATOR_DOWN:
|
|
case ST_19_ELEVATOR_UP:
|
|
|
|
i = GetAnimationGoal(&sptr->floorz);
|
|
|
|
if (i==-1)
|
|
{
|
|
i = nextsectorneighborz(sn,sptr->floorz,1,-1);
|
|
if (i==-1) i = nextsectorneighborz(sn,sptr->floorz,1,1);
|
|
if (i==-1) return;
|
|
j = sector[i].floorz;
|
|
q = sptr->extra;
|
|
l = sptr->ceilingz-sptr->floorz;
|
|
SetAnimation(sn,&sptr->floorz,j,q);
|
|
SetAnimation(sn,&sptr->ceilingz,j+l,q);
|
|
A_CallSound(sn,ii);
|
|
}
|
|
return;
|
|
|
|
case ST_29_TEETH_DOOR:
|
|
|
|
i = headspritestat[STAT_EFFECTOR]; //Effectors
|
|
while (i >= 0)
|
|
{
|
|
if ((SLT == SE_22_TEETH_DOOR) &&
|
|
(SHT == sptr->hitag))
|
|
{
|
|
sector[SECT].extra = -sector[SECT].extra;
|
|
|
|
T1 = sn;
|
|
T2 = 1;
|
|
}
|
|
i = nextspritestat[i];
|
|
}
|
|
|
|
A_CallSound(sn, ii);
|
|
|
|
sptr->lotag ^= 0x8000;
|
|
|
|
if (sptr->lotag&0x8000)
|
|
{
|
|
j = nextsectorneighborz(sn,sptr->ceilingz,-1,-1);
|
|
if (j == -1) j = nextsectorneighborz(sn,sptr->ceilingz,1,1);
|
|
if (j == -1)
|
|
{
|
|
OSD_Printf("WARNING: ST29: null sector!\n");
|
|
return;
|
|
}
|
|
j = sector[j].ceilingz;
|
|
}
|
|
else
|
|
{
|
|
j = nextsectorneighborz(sn,sptr->ceilingz,1,1);
|
|
if (j == -1) j = nextsectorneighborz(sn,sptr->ceilingz,-1,-1);
|
|
if (j == -1)
|
|
{
|
|
OSD_Printf("WARNING: ST29: null sector!\n");
|
|
return;
|
|
}
|
|
j = sector[j].floorz;
|
|
}
|
|
|
|
SetAnimation(sn,&sptr->ceilingz,j,sptr->extra);
|
|
|
|
return;
|
|
|
|
case ST_20_CEILING_DOOR:
|
|
|
|
REDODOOR:
|
|
|
|
if (sptr->lotag&0x8000)
|
|
{
|
|
i = headspritesect[sn];
|
|
while (i >= 0)
|
|
{
|
|
if (sprite[i].statnum == STAT_EFFECTOR && SLT==SE_9_DOWN_OPEN_DOOR_LIGHTS)
|
|
{
|
|
j = SZ;
|
|
break;
|
|
}
|
|
i = nextspritesect[i];
|
|
}
|
|
if (i==-1)
|
|
j = sptr->floorz;
|
|
}
|
|
else
|
|
{
|
|
j = nextsectorneighborz(sn,sptr->ceilingz,-1,-1);
|
|
|
|
if (j >= 0) j = sector[j].ceilingz;
|
|
else
|
|
{
|
|
sptr->lotag |= 32768;
|
|
goto REDODOOR;
|
|
}
|
|
}
|
|
|
|
sptr->lotag ^= 0x8000;
|
|
|
|
SetAnimation(sn,&sptr->ceilingz,j,sptr->extra);
|
|
A_CallSound(sn,ii);
|
|
|
|
return;
|
|
|
|
case ST_21_FLOOR_DOOR:
|
|
i = GetAnimationGoal(&sptr->floorz);
|
|
if (i >= 0)
|
|
{
|
|
if (animategoal[sn] == sptr->ceilingz)
|
|
animategoal[i] = sector[nextsectorneighborz(sn,sptr->ceilingz,1,1)].floorz;
|
|
else animategoal[i] = sptr->ceilingz;
|
|
j = animategoal[i];
|
|
}
|
|
else
|
|
{
|
|
if (sptr->ceilingz == sptr->floorz)
|
|
j = sector[nextsectorneighborz(sn,sptr->ceilingz,1,1)].floorz;
|
|
else j = sptr->ceilingz;
|
|
|
|
sptr->lotag ^= 0x8000;
|
|
|
|
if (SetAnimation(sn,&sptr->floorz,j,sptr->extra) >= 0)
|
|
A_CallSound(sn,ii);
|
|
}
|
|
return;
|
|
|
|
case ST_22_SPLITTING_DOOR:
|
|
|
|
// REDODOOR22:
|
|
|
|
if ((sptr->lotag&0x8000))
|
|
{
|
|
q = (sptr->ceilingz+sptr->floorz)>>1;
|
|
j = SetAnimation(sn,&sptr->floorz,q,sptr->extra);
|
|
j = SetAnimation(sn,&sptr->ceilingz,q,sptr->extra);
|
|
}
|
|
else
|
|
{
|
|
int32_t fneigh=nextsectorneighborz(sn,sptr->floorz,1,1);
|
|
int32_t cneigh=nextsectorneighborz(sn,sptr->ceilingz,-1,-1);
|
|
|
|
if (fneigh>=0 && cneigh>=0)
|
|
{
|
|
j = SetAnimation(sn, &sptr->floorz, sector[fneigh].floorz, sptr->extra);
|
|
j = SetAnimation(sn, &sptr->ceilingz, sector[cneigh].ceilingz, sptr->extra);
|
|
}
|
|
else
|
|
{
|
|
OSD_Printf("WARNING: ST22: null sector: floor neighbor=%d, ceiling neighbor=%d!\n",
|
|
fneigh, cneigh);
|
|
sptr->lotag ^= 0x8000;
|
|
}
|
|
}
|
|
|
|
sptr->lotag ^= 0x8000;
|
|
|
|
A_CallSound(sn,ii);
|
|
|
|
return;
|
|
|
|
case ST_23_SWINGING_DOOR: //Swingdoor
|
|
|
|
j = -1;
|
|
q = 0;
|
|
|
|
i = headspritestat[STAT_EFFECTOR];
|
|
while (i >= 0)
|
|
{
|
|
if (SLT == SE_11_SWINGING_DOOR && SECT == sn && !T5)
|
|
{
|
|
j = i;
|
|
break;
|
|
}
|
|
i = nextspritestat[i];
|
|
}
|
|
if (i<0)
|
|
{
|
|
OSD_Printf("WARNING: SE23 i<0!\n");
|
|
return;
|
|
} // JBF
|
|
l = sector[SECT].lotag&0x8000;
|
|
|
|
if (j >= 0)
|
|
{
|
|
i = headspritestat[STAT_EFFECTOR];
|
|
while (i >= 0)
|
|
{
|
|
if (l == (sector[SECT].lotag&0x8000) && SLT == SE_11_SWINGING_DOOR && sprite[j].hitag == SHT && !T5)
|
|
{
|
|
if (sector[SECT].lotag&0x8000) sector[SECT].lotag &= 0x7fff;
|
|
else sector[SECT].lotag |= 0x8000;
|
|
T5 = 1;
|
|
T4 = -T4;
|
|
if (q == 0)
|
|
{
|
|
A_CallSound(sn,i);
|
|
q = 1;
|
|
}
|
|
}
|
|
i = nextspritestat[i];
|
|
}
|
|
}
|
|
return;
|
|
|
|
case ST_25_SLIDING_DOOR: //Subway type sliding doors
|
|
|
|
j = headspritestat[STAT_EFFECTOR];
|
|
while (j >= 0)//Find the sprite
|
|
{
|
|
if ((sprite[j].lotag) == SE_15_SLIDING_DOOR && sprite[j].sectnum == sn)
|
|
break; //Found the sectoreffector.
|
|
j = nextspritestat[j];
|
|
}
|
|
|
|
if (j < 0)
|
|
return;
|
|
|
|
i = headspritestat[STAT_EFFECTOR];
|
|
while (i >= 0)
|
|
{
|
|
if (SHT==sprite[j].hitag)
|
|
{
|
|
if (SLT == SE_15_SLIDING_DOOR)
|
|
{
|
|
sector[SECT].lotag ^= 0x8000; // Toggle the open or close
|
|
SA += 1024;
|
|
if (T5) A_CallSound(SECT,i);
|
|
A_CallSound(SECT,i);
|
|
if (sector[SECT].lotag&0x8000) T5 = 1;
|
|
else T5 = 2;
|
|
}
|
|
}
|
|
i = nextspritestat[i];
|
|
}
|
|
return;
|
|
|
|
case ST_27_STRETCH_BRIDGE: //Extended bridge
|
|
|
|
j = headspritestat[STAT_EFFECTOR];
|
|
while (j >= 0)
|
|
{
|
|
if ((sprite[j].lotag&0xff)==SE_20_STRETCH_BRIDGE && sprite[j].sectnum == sn) //Bridge
|
|
{
|
|
|
|
sector[sn].lotag ^= 0x8000;
|
|
if (sector[sn].lotag&0x8000) //OPENING
|
|
actor[j].t_data[0] = 1;
|
|
else actor[j].t_data[0] = 2;
|
|
A_CallSound(sn,ii);
|
|
break;
|
|
}
|
|
j = nextspritestat[j];
|
|
}
|
|
return;
|
|
|
|
|
|
case ST_28_DROP_FLOOR:
|
|
//activate the rest of them
|
|
|
|
j = headspritesect[sn];
|
|
while (j >= 0)
|
|
{
|
|
if (sprite[j].statnum==STAT_EFFECTOR && (sprite[j].lotag&0xff)==SE_21_DROP_FLOOR)
|
|
break; //Found it
|
|
j = nextspritesect[j];
|
|
}
|
|
|
|
if (j >= 0) // PK: The matching SE21 might have gone, see SE_21_KILLIT in actors.c
|
|
{
|
|
j = sprite[j].hitag;
|
|
|
|
l = headspritestat[STAT_EFFECTOR];
|
|
while (l >= 0)
|
|
{
|
|
if ((sprite[l].lotag&0xff)==SE_21_DROP_FLOOR && !actor[l].t_data[0] &&
|
|
(sprite[l].hitag) == j)
|
|
actor[l].t_data[0] = 1;
|
|
l = nextspritestat[l];
|
|
}
|
|
|
|
A_CallSound(sn,ii);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
void G_OperateRespawns(int32_t low)
|
|
{
|
|
int32_t j, nexti, i = headspritestat[STAT_FX];
|
|
|
|
while (i >= 0)
|
|
{
|
|
nexti = nextspritestat[i];
|
|
if ((SLT == low) && (PN == RESPAWN))
|
|
{
|
|
if (A_CheckEnemyTile(SHT) && ud.monsters_off) break;
|
|
|
|
j = A_Spawn(i,TRANSPORTERSTAR);
|
|
sprite[j].z -= (32<<8);
|
|
|
|
sprite[i].extra = 66-12; // Just a way to killit
|
|
}
|
|
i = nexti;
|
|
}
|
|
}
|
|
|
|
void G_OperateActivators(int32_t low,int32_t snum)
|
|
{
|
|
int32_t i, j, k;
|
|
int16_t *p;
|
|
walltype *wal;
|
|
|
|
for (i=g_numCyclers-1; i>=0; i--)
|
|
{
|
|
p = &cyclers[i][0];
|
|
|
|
if (p[4] == low)
|
|
{
|
|
p[5] = !p[5];
|
|
|
|
sector[p[0]].floorshade = sector[p[0]].ceilingshade = p[3];
|
|
wal = &wall[sector[p[0]].wallptr];
|
|
for (j=sector[p[0]].wallnum; j > 0; j--,wal++)
|
|
wal->shade = p[3];
|
|
}
|
|
}
|
|
|
|
i = headspritestat[STAT_ACTIVATOR];
|
|
k = -1;
|
|
|
|
while (i >= 0)
|
|
{
|
|
if (sprite[i].lotag == low)
|
|
{
|
|
if (sprite[i].picnum == ACTIVATORLOCKED)
|
|
{
|
|
if (sector[SECT].lotag&16384)
|
|
sector[SECT].lotag &= ~16384;
|
|
else
|
|
sector[SECT].lotag |= 16384;
|
|
|
|
if (snum >= 0 && snum < ud.multimode)
|
|
{
|
|
if (sector[SECT].lotag&16384)
|
|
P_DoQuote(QUOTE_LOCKED,g_player[snum].ps);
|
|
else P_DoQuote(QUOTE_UNLOCKED,g_player[snum].ps);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (SHT)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
if (sector[SECT].floorz != sector[SECT].ceilingz)
|
|
{
|
|
i = nextspritestat[i];
|
|
continue;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (sector[SECT].floorz == sector[SECT].ceilingz)
|
|
{
|
|
i = nextspritestat[i];
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// ST_2_UNDERWATER
|
|
if (sector[sprite[i].sectnum].lotag < 3)
|
|
{
|
|
j = headspritesect[sprite[i].sectnum];
|
|
while (j >= 0)
|
|
{
|
|
if (sprite[j].statnum == STAT_EFFECTOR) switch (sprite[j].lotag)
|
|
{
|
|
case SE_36_PROJ_SHOOTER:
|
|
case SE_31_FLOOR_RISE_FALL:
|
|
case SE_32_CEILING_RISE_FALL:
|
|
case SE_18_INCREMENTAL_SECTOR_RISE_FALL:
|
|
actor[j].t_data[0] = 1-actor[j].t_data[0];
|
|
A_CallSound(SECT,j);
|
|
break;
|
|
}
|
|
j = nextspritesect[j];
|
|
}
|
|
}
|
|
|
|
if (k == -1 && (sector[SECT].lotag&0xff) == ST_22_SPLITTING_DOOR)
|
|
k = A_CallSound(SECT,i);
|
|
|
|
G_OperateSectors(SECT,i);
|
|
}
|
|
}
|
|
i = nextspritestat[i];
|
|
}
|
|
|
|
G_OperateRespawns(low);
|
|
}
|
|
|
|
void G_OperateMasterSwitches(int32_t low)
|
|
{
|
|
int32_t i = headspritestat[STAT_STANDABLE];
|
|
while (i >= 0)
|
|
{
|
|
if (PN == MASTERSWITCH && SLT == low && SP == 0)
|
|
SP = 1;
|
|
i = nextspritestat[i];
|
|
}
|
|
}
|
|
|
|
void G_OperateForceFields(int32_t s, int32_t low)
|
|
{
|
|
int32_t i, p=g_numAnimWalls;
|
|
|
|
for (; p>=0; p--)
|
|
{
|
|
i = animwall[p].wallnum;
|
|
|
|
if (low == wall[i].lotag || low == -1)
|
|
if (G_GetForcefieldPicnum(i) == W_FORCEFIELD
|
|
|| (wall[i].overpicnum == BIGFORCE))
|
|
{
|
|
animwall[p].tag = 0;
|
|
|
|
if (wall[i].cstat)
|
|
{
|
|
wall[i].cstat = 0;
|
|
|
|
if (s >= 0 && sprite[s].picnum == SECTOREFFECTOR && sprite[s].lotag == SE_30_TWO_WAY_TRAIN)
|
|
wall[i].lotag = 0;
|
|
}
|
|
else
|
|
wall[i].cstat = FORCEFIELD_CSTAT;
|
|
}
|
|
}
|
|
}
|
|
|
|
int32_t P_ActivateSwitch(int32_t snum,int32_t w,int32_t switchissprite)
|
|
{
|
|
int32_t switchpal, switchpicnum;
|
|
int32_t i, x, lotag,hitag,picnum,correctdips = 1, numdips = 0;
|
|
vec3_t davector;
|
|
|
|
if (w < 0) return 0;
|
|
|
|
if (switchissprite == 1) // A wall sprite
|
|
{
|
|
if (actor[w].lasttransport == totalclock) return 0;
|
|
actor[w].lasttransport = totalclock;
|
|
lotag = sprite[w].lotag;
|
|
if (lotag == 0) return 0;
|
|
hitag = sprite[w].hitag;
|
|
|
|
// sx = sprite[w].x;
|
|
// sy = sprite[w].y;
|
|
Bmemcpy(&davector, &sprite[w], sizeof(vec3_t));
|
|
picnum = sprite[w].picnum;
|
|
switchpal = sprite[w].pal;
|
|
}
|
|
else
|
|
{
|
|
lotag = wall[w].lotag;
|
|
if (lotag == 0) return 0;
|
|
hitag = wall[w].hitag;
|
|
// sx = wall[w].x;
|
|
// sy = wall[w].y;
|
|
Bmemcpy(&davector, &wall[w], sizeof(int32_t) * 2);
|
|
davector.z = g_player[snum].ps->pos.z;
|
|
picnum = wall[w].picnum;
|
|
switchpal = wall[w].pal;
|
|
}
|
|
// initprintf("P_ActivateSwitch called picnum=%i switchissprite=%i\n",picnum,switchissprite);
|
|
switchpicnum = picnum;
|
|
if ((picnum==DIPSWITCH+1)
|
|
|| (picnum==TECHSWITCH+1)
|
|
|| (picnum==ALIENSWITCH+1)
|
|
|| (picnum==DIPSWITCH2+1)
|
|
|| (picnum==DIPSWITCH3+1)
|
|
|| (picnum==PULLSWITCH+1)
|
|
|| (picnum==HANDSWITCH+1)
|
|
|| (picnum==SLOTDOOR+1)
|
|
|| (picnum==LIGHTSWITCH+1)
|
|
|| (picnum==SPACELIGHTSWITCH+1)
|
|
|| (picnum==SPACEDOORSWITCH+1)
|
|
|| (picnum==FRANKENSTINESWITCH+1)
|
|
|| (picnum==LIGHTSWITCH2+1)
|
|
|| (picnum==POWERSWITCH1+1)
|
|
|| (picnum==LOCKSWITCH1+1)
|
|
|| (picnum==POWERSWITCH2+1)
|
|
|| (picnum==LIGHTSWITCH+1)
|
|
)
|
|
{
|
|
switchpicnum--;
|
|
}
|
|
if (picnum > MULTISWITCH && picnum <= MULTISWITCH+3)
|
|
{
|
|
switchpicnum = MULTISWITCH;
|
|
}
|
|
|
|
switch (DYNAMICTILEMAP(switchpicnum))
|
|
{
|
|
case DIPSWITCH__STATIC:
|
|
// case DIPSWITCH+1:
|
|
case TECHSWITCH__STATIC:
|
|
// case TECHSWITCH+1:
|
|
case ALIENSWITCH__STATIC:
|
|
// case ALIENSWITCH+1:
|
|
break;
|
|
case ACCESSSWITCH__STATIC:
|
|
case ACCESSSWITCH2__STATIC:
|
|
if (g_player[snum].ps->access_incs == 0)
|
|
{
|
|
if (switchpal == 0)
|
|
{
|
|
if ((g_player[snum].ps->got_access&1))
|
|
g_player[snum].ps->access_incs = 1;
|
|
else P_DoQuote(QUOTE_NEED_BLUE_KEY,g_player[snum].ps);
|
|
}
|
|
|
|
else if (switchpal == 21)
|
|
{
|
|
if (g_player[snum].ps->got_access&2)
|
|
g_player[snum].ps->access_incs = 1;
|
|
else P_DoQuote(QUOTE_NEED_RED_KEY,g_player[snum].ps);
|
|
}
|
|
|
|
else if (switchpal == 23)
|
|
{
|
|
if (g_player[snum].ps->got_access&4)
|
|
g_player[snum].ps->access_incs = 1;
|
|
else P_DoQuote(QUOTE_NEED_YELLOW_KEY,g_player[snum].ps);
|
|
}
|
|
|
|
if (g_player[snum].ps->access_incs == 1)
|
|
{
|
|
if (switchissprite == 0)
|
|
g_player[snum].ps->access_wallnum = w;
|
|
else
|
|
g_player[snum].ps->access_spritenum = w;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
case DIPSWITCH2__STATIC:
|
|
//case DIPSWITCH2+1:
|
|
case DIPSWITCH3__STATIC:
|
|
//case DIPSWITCH3+1:
|
|
case MULTISWITCH__STATIC:
|
|
//case MULTISWITCH+1:
|
|
//case MULTISWITCH+2:
|
|
//case MULTISWITCH+3:
|
|
case PULLSWITCH__STATIC:
|
|
//case PULLSWITCH+1:
|
|
case HANDSWITCH__STATIC:
|
|
//case HANDSWITCH+1:
|
|
case SLOTDOOR__STATIC:
|
|
//case SLOTDOOR+1:
|
|
case LIGHTSWITCH__STATIC:
|
|
//case LIGHTSWITCH+1:
|
|
case SPACELIGHTSWITCH__STATIC:
|
|
//case SPACELIGHTSWITCH+1:
|
|
case SPACEDOORSWITCH__STATIC:
|
|
//case SPACEDOORSWITCH+1:
|
|
case FRANKENSTINESWITCH__STATIC:
|
|
//case FRANKENSTINESWITCH+1:
|
|
case LIGHTSWITCH2__STATIC:
|
|
//case LIGHTSWITCH2+1:
|
|
case POWERSWITCH1__STATIC:
|
|
//case POWERSWITCH1+1:
|
|
case LOCKSWITCH1__STATIC:
|
|
//case LOCKSWITCH1+1:
|
|
case POWERSWITCH2__STATIC:
|
|
//case POWERSWITCH2+1:
|
|
if (G_CheckActivatorMotion(lotag)) return 0;
|
|
break;
|
|
default:
|
|
if (CheckDoorTile(picnum) == 0) return 0;
|
|
break;
|
|
}
|
|
|
|
i = headspritestat[STAT_DEFAULT];
|
|
while (i >= 0)
|
|
{
|
|
|
|
if (lotag == SLT)
|
|
{
|
|
int32_t switchpicnum=PN; // put it in a variable so later switches don't trigger on the result of changes
|
|
if ((switchpicnum >= MULTISWITCH) && (switchpicnum <=MULTISWITCH+3))
|
|
{
|
|
sprite[i].picnum++;
|
|
if (sprite[i].picnum > (MULTISWITCH+3))
|
|
sprite[i].picnum = MULTISWITCH;
|
|
|
|
}
|
|
switch (DYNAMICTILEMAP(switchpicnum))
|
|
{
|
|
case DIPSWITCH__STATIC:
|
|
case TECHSWITCH__STATIC:
|
|
case ALIENSWITCH__STATIC:
|
|
if (switchissprite == 1 && w == i) PN++;
|
|
else if (SHT == 0) correctdips++;
|
|
numdips++;
|
|
break;
|
|
case ACCESSSWITCH__STATIC:
|
|
case ACCESSSWITCH2__STATIC:
|
|
case SLOTDOOR__STATIC:
|
|
case LIGHTSWITCH__STATIC:
|
|
case SPACELIGHTSWITCH__STATIC:
|
|
case SPACEDOORSWITCH__STATIC:
|
|
case FRANKENSTINESWITCH__STATIC:
|
|
case LIGHTSWITCH2__STATIC:
|
|
case POWERSWITCH1__STATIC:
|
|
case LOCKSWITCH1__STATIC:
|
|
case POWERSWITCH2__STATIC:
|
|
case HANDSWITCH__STATIC:
|
|
case PULLSWITCH__STATIC:
|
|
case DIPSWITCH2__STATIC:
|
|
case DIPSWITCH3__STATIC:
|
|
sprite[i].picnum++;
|
|
break;
|
|
default:
|
|
if (switchpicnum <= 0) // oob safety
|
|
break;
|
|
|
|
switch (DYNAMICTILEMAP(switchpicnum-1))
|
|
{
|
|
case TECHSWITCH__STATIC:
|
|
case DIPSWITCH__STATIC:
|
|
case ALIENSWITCH__STATIC:
|
|
if (switchissprite == 1 && w == i) PN--;
|
|
else if (SHT == 1) correctdips++;
|
|
numdips++;
|
|
break;
|
|
case PULLSWITCH__STATIC:
|
|
case HANDSWITCH__STATIC:
|
|
case LIGHTSWITCH2__STATIC:
|
|
case POWERSWITCH1__STATIC:
|
|
case LOCKSWITCH1__STATIC:
|
|
case POWERSWITCH2__STATIC:
|
|
case SLOTDOOR__STATIC:
|
|
case LIGHTSWITCH__STATIC:
|
|
case SPACELIGHTSWITCH__STATIC:
|
|
case SPACEDOORSWITCH__STATIC:
|
|
case FRANKENSTINESWITCH__STATIC:
|
|
case DIPSWITCH2__STATIC:
|
|
case DIPSWITCH3__STATIC:
|
|
sprite[i].picnum--;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
i = nextspritestat[i];
|
|
}
|
|
|
|
for (i=numwalls-1; i>=0; i--)
|
|
{
|
|
x = i;
|
|
if (lotag == wall[x].lotag)
|
|
{
|
|
if ((wall[x].picnum >= MULTISWITCH) && (wall[x].picnum <=MULTISWITCH+3))
|
|
{
|
|
wall[x].picnum++;
|
|
if (wall[x].picnum > (MULTISWITCH+3))
|
|
wall[x].picnum = MULTISWITCH;
|
|
|
|
}
|
|
|
|
switch (DYNAMICTILEMAP(wall[x].picnum))
|
|
{
|
|
case DIPSWITCH__STATIC:
|
|
case TECHSWITCH__STATIC:
|
|
case ALIENSWITCH__STATIC:
|
|
if (switchissprite == 0 && i == w) wall[x].picnum++;
|
|
else if (wall[x].hitag == 0) correctdips++;
|
|
numdips++;
|
|
break;
|
|
case ACCESSSWITCH__STATIC:
|
|
case ACCESSSWITCH2__STATIC:
|
|
case SLOTDOOR__STATIC:
|
|
case LIGHTSWITCH__STATIC:
|
|
case SPACELIGHTSWITCH__STATIC:
|
|
case SPACEDOORSWITCH__STATIC:
|
|
case FRANKENSTINESWITCH__STATIC:
|
|
case LIGHTSWITCH2__STATIC:
|
|
case POWERSWITCH1__STATIC:
|
|
case LOCKSWITCH1__STATIC:
|
|
case POWERSWITCH2__STATIC:
|
|
case HANDSWITCH__STATIC:
|
|
case PULLSWITCH__STATIC:
|
|
case DIPSWITCH2__STATIC:
|
|
case DIPSWITCH3__STATIC:
|
|
wall[x].picnum++;
|
|
break;
|
|
default:
|
|
if (wall[x].picnum <= 0) // oob safety
|
|
break;
|
|
|
|
switch (DYNAMICTILEMAP(wall[x].picnum-1))
|
|
{
|
|
case TECHSWITCH__STATIC:
|
|
case DIPSWITCH__STATIC:
|
|
case ALIENSWITCH__STATIC:
|
|
if (switchissprite == 0 && i == w) wall[x].picnum--;
|
|
else if (wall[x].hitag == 1) correctdips++;
|
|
numdips++;
|
|
break;
|
|
case PULLSWITCH__STATIC:
|
|
case HANDSWITCH__STATIC:
|
|
case LIGHTSWITCH2__STATIC:
|
|
case POWERSWITCH1__STATIC:
|
|
case LOCKSWITCH1__STATIC:
|
|
case POWERSWITCH2__STATIC:
|
|
case SLOTDOOR__STATIC:
|
|
case LIGHTSWITCH__STATIC:
|
|
case SPACELIGHTSWITCH__STATIC:
|
|
case SPACEDOORSWITCH__STATIC:
|
|
case FRANKENSTINESWITCH__STATIC:
|
|
case DIPSWITCH2__STATIC:
|
|
case DIPSWITCH3__STATIC:
|
|
wall[x].picnum--;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lotag == 65535)
|
|
{
|
|
|
|
g_player[myconnectindex].ps->gm = MODE_EOL;
|
|
if (ud.from_bonus)
|
|
{
|
|
ud.level_number = ud.from_bonus;
|
|
ud.m_level_number = ud.level_number;
|
|
ud.from_bonus = 0;
|
|
}
|
|
else
|
|
{
|
|
ud.level_number++;
|
|
if (ud.level_number > MAXLEVELS-1)
|
|
ud.level_number = 0;
|
|
ud.m_level_number = ud.level_number;
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
|
|
switchpicnum = picnum;
|
|
|
|
if ((picnum==DIPSWITCH+1)
|
|
|| (picnum==TECHSWITCH+1)
|
|
|| (picnum==ALIENSWITCH+1)
|
|
|| (picnum==DIPSWITCH2+1)
|
|
|| (picnum==DIPSWITCH3+1)
|
|
|| (picnum==PULLSWITCH+1)
|
|
|| (picnum==HANDSWITCH+1)
|
|
|| (picnum==SLOTDOOR+1)
|
|
|| (picnum==LIGHTSWITCH+1)
|
|
|| (picnum==SPACELIGHTSWITCH+1)
|
|
|| (picnum==SPACEDOORSWITCH+1)
|
|
|| (picnum==FRANKENSTINESWITCH+1)
|
|
|| (picnum==LIGHTSWITCH2+1)
|
|
|| (picnum==POWERSWITCH1+1)
|
|
|| (picnum==LOCKSWITCH1+1)
|
|
|| (picnum==POWERSWITCH2+1)
|
|
|| (picnum==LIGHTSWITCH+1)
|
|
)
|
|
{
|
|
switchpicnum--;
|
|
}
|
|
if (picnum > MULTISWITCH && picnum <= MULTISWITCH+3)
|
|
{
|
|
switchpicnum = MULTISWITCH;
|
|
}
|
|
|
|
switch (DYNAMICTILEMAP(switchpicnum))
|
|
{
|
|
default:
|
|
if (CheckDoorTile(picnum) == 0) break;
|
|
case DIPSWITCH__STATIC:
|
|
//case DIPSWITCH+1:
|
|
case TECHSWITCH__STATIC:
|
|
//case TECHSWITCH+1:
|
|
case ALIENSWITCH__STATIC:
|
|
//case ALIENSWITCH+1:
|
|
if (picnum == DIPSWITCH || picnum == DIPSWITCH+1 ||
|
|
picnum == ALIENSWITCH || picnum == ALIENSWITCH+1 ||
|
|
picnum == TECHSWITCH || picnum == TECHSWITCH+1)
|
|
{
|
|
if (picnum == ALIENSWITCH || picnum == ALIENSWITCH+1)
|
|
{
|
|
if (switchissprite == 1)
|
|
S_PlaySound3D(ALIEN_SWITCH1, w, &davector);
|
|
else S_PlaySound3D(ALIEN_SWITCH1,g_player[snum].ps->i,&davector);
|
|
}
|
|
else
|
|
{
|
|
if (switchissprite == 1)
|
|
S_PlaySound3D(SWITCH_ON, w, &davector);
|
|
else S_PlaySound3D(SWITCH_ON,g_player[snum].ps->i,&davector);
|
|
}
|
|
if (numdips != correctdips) break;
|
|
S_PlaySound3D(END_OF_LEVEL_WARN,g_player[snum].ps->i,&davector);
|
|
}
|
|
case DIPSWITCH2__STATIC:
|
|
//case DIPSWITCH2+1:
|
|
case DIPSWITCH3__STATIC:
|
|
//case DIPSWITCH3+1:
|
|
case MULTISWITCH__STATIC:
|
|
//case MULTISWITCH+1:
|
|
//case MULTISWITCH+2:
|
|
//case MULTISWITCH+3:
|
|
case ACCESSSWITCH__STATIC:
|
|
case ACCESSSWITCH2__STATIC:
|
|
case SLOTDOOR__STATIC:
|
|
//case SLOTDOOR+1:
|
|
case LIGHTSWITCH__STATIC:
|
|
//case LIGHTSWITCH+1:
|
|
case SPACELIGHTSWITCH__STATIC:
|
|
//case SPACELIGHTSWITCH+1:
|
|
case SPACEDOORSWITCH__STATIC:
|
|
//case SPACEDOORSWITCH+1:
|
|
case FRANKENSTINESWITCH__STATIC:
|
|
//case FRANKENSTINESWITCH+1:
|
|
case LIGHTSWITCH2__STATIC:
|
|
//case LIGHTSWITCH2+1:
|
|
case POWERSWITCH1__STATIC:
|
|
//case POWERSWITCH1+1:
|
|
case LOCKSWITCH1__STATIC:
|
|
//case LOCKSWITCH1+1:
|
|
case POWERSWITCH2__STATIC:
|
|
//case POWERSWITCH2+1:
|
|
case HANDSWITCH__STATIC:
|
|
//case HANDSWITCH+1:
|
|
case PULLSWITCH__STATIC:
|
|
//case PULLSWITCH+1:
|
|
|
|
if (picnum == MULTISWITCH || picnum == (MULTISWITCH+1) ||
|
|
picnum == (MULTISWITCH+2) || picnum == (MULTISWITCH+3))
|
|
lotag += picnum-MULTISWITCH;
|
|
|
|
x = headspritestat[STAT_EFFECTOR];
|
|
while (x >= 0)
|
|
{
|
|
if (((sprite[x].hitag) == lotag))
|
|
{
|
|
switch (sprite[x].lotag)
|
|
{
|
|
case SE_12_LIGHT_SWITCH:
|
|
sector[sprite[x].sectnum].floorpal = 0;
|
|
actor[x].t_data[0]++;
|
|
if (actor[x].t_data[0] == 2)
|
|
actor[x].t_data[0]++;
|
|
|
|
break;
|
|
case SE_24_CONVEYOR:
|
|
case SE_34:
|
|
case SE_25_PISTON:
|
|
actor[x].t_data[4] = !actor[x].t_data[4];
|
|
if (actor[x].t_data[4])
|
|
P_DoQuote(QUOTE_DEACTIVATED,g_player[snum].ps);
|
|
else P_DoQuote(QUOTE_ACTIVATED,g_player[snum].ps);
|
|
break;
|
|
case SE_21_DROP_FLOOR:
|
|
P_DoQuote(QUOTE_ACTIVATED,g_player[screenpeek].ps);
|
|
break;
|
|
}
|
|
}
|
|
x = nextspritestat[x];
|
|
}
|
|
|
|
G_OperateActivators(lotag,snum);
|
|
G_OperateForceFields(g_player[snum].ps->i,lotag);
|
|
G_OperateMasterSwitches(lotag);
|
|
|
|
if (picnum == DIPSWITCH || picnum == DIPSWITCH+1 ||
|
|
picnum == ALIENSWITCH || picnum == ALIENSWITCH+1 ||
|
|
picnum == TECHSWITCH || picnum == TECHSWITCH+1) return 1;
|
|
|
|
if (hitag == 0 && CheckDoorTile(picnum) == 0)
|
|
{
|
|
if (switchissprite == 1)
|
|
S_PlaySound3D(SWITCH_ON,w,&davector);
|
|
else S_PlaySound3D(SWITCH_ON,g_player[snum].ps->i,&davector);
|
|
}
|
|
else if (hitag != 0)
|
|
{
|
|
if (switchissprite == 1 && (g_sounds[hitag].m & SF_TALK) == 0)
|
|
S_PlaySound3D(hitag,w,&davector);
|
|
else A_PlaySound(hitag,g_player[snum].ps->i);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void G_ActivateBySector(int32_t sect,int32_t j)
|
|
{
|
|
int32_t i = headspritesect[sect];
|
|
int32_t didit = 0;
|
|
|
|
while (i >= 0)
|
|
{
|
|
if (PN == ACTIVATOR)
|
|
{
|
|
G_OperateActivators(SLT,-1);
|
|
didit = 1;
|
|
// return;
|
|
}
|
|
i = nextspritesect[i];
|
|
}
|
|
|
|
if (didit == 0)
|
|
G_OperateSectors(sect,j);
|
|
}
|
|
|
|
static void BreakWall(int32_t newpn,int32_t spr,int32_t dawallnum)
|
|
{
|
|
wall[dawallnum].picnum = newpn;
|
|
A_PlaySound(VENT_BUST,spr);
|
|
A_PlaySound(GLASS_HEAVYBREAK,spr);
|
|
A_SpawnWallGlass(spr,dawallnum,10);
|
|
}
|
|
|
|
void A_DamageWall(int32_t spr,int32_t dawallnum,const vec3_t *pos,int32_t atwith)
|
|
{
|
|
int16_t sn = -1;
|
|
int32_t j, i, darkestwall;
|
|
walltype *wal = &wall[dawallnum];
|
|
|
|
if (wal->overpicnum == MIRROR && wal->pal != 4 && A_CheckSpriteTileFlags(atwith,SPRITE_PROJECTILE) && (SpriteProjectile[spr].workslike & PROJECTILE_RPG))
|
|
{
|
|
if (wal->nextwall == -1 || wall[wal->nextwall].pal != 4)
|
|
{
|
|
A_SpawnWallGlass(spr,dawallnum,70);
|
|
wal->cstat &= ~16;
|
|
wal->overpicnum = MIRRORBROKE;
|
|
A_PlaySound(GLASS_HEAVYBREAK,spr);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (wal->overpicnum == MIRROR && wal->pal != 4)
|
|
{
|
|
switch (DYNAMICTILEMAP(atwith))
|
|
{
|
|
case HEAVYHBOMB__STATIC:
|
|
case RADIUSEXPLOSION__STATIC:
|
|
case RPG__STATIC:
|
|
case HYDRENT__STATIC:
|
|
case SEENINE__STATIC:
|
|
case OOZFILTER__STATIC:
|
|
case EXPLODINGBARREL__STATIC:
|
|
if (wal->nextwall == -1 || wall[wal->nextwall].pal != 4)
|
|
{
|
|
A_SpawnWallGlass(spr,dawallnum,70);
|
|
wal->cstat &= ~16;
|
|
wal->overpicnum = MIRRORBROKE;
|
|
A_PlaySound(GLASS_HEAVYBREAK,spr);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (((wal->cstat&16) || wal->overpicnum == BIGFORCE) && wal->nextsector >= 0)
|
|
if (sector[wal->nextsector].floorz > pos->z)
|
|
if (sector[wal->nextsector].floorz-sector[wal->nextsector].ceilingz)
|
|
{
|
|
int32_t switchpicnum = wal->overpicnum;
|
|
if (switchpicnum > W_FORCEFIELD && switchpicnum <= W_FORCEFIELD+2)
|
|
switchpicnum = W_FORCEFIELD;
|
|
|
|
switch (DYNAMICTILEMAP(switchpicnum))
|
|
{
|
|
case W_FORCEFIELD__STATIC:
|
|
wal->extra = 1; // tell the forces to animate
|
|
/* fall-through */
|
|
case BIGFORCE__STATIC:
|
|
updatesector(pos->x, pos->y, &sn);
|
|
if (sn < 0)
|
|
return;
|
|
|
|
{
|
|
int32_t xr=32, yr=32;
|
|
|
|
if (atwith == -1)
|
|
xr = yr = 8;
|
|
else if (atwith == CHAINGUN)
|
|
{
|
|
xr = 16+sprite[spr].xrepeat;
|
|
yr = 16+sprite[spr].yrepeat;
|
|
}
|
|
|
|
i = A_InsertSprite(sn, pos->x,pos->y,pos->z, FORCERIPPLE,
|
|
-127, xr,yr, 0,0,0,spr,5);
|
|
}
|
|
|
|
CS |= 18+128;
|
|
SA = getangle(wal->x-wall[wal->point2].x,
|
|
wal->y-wall[wal->point2].y)-512;
|
|
|
|
A_PlaySound(SOMETHINGHITFORCE,i);
|
|
return;
|
|
|
|
case FANSPRITE__STATIC:
|
|
wal->overpicnum = FANSPRITEBROKE;
|
|
wal->cstat &= 65535-65;
|
|
if (wal->nextwall >= 0)
|
|
{
|
|
wall[wal->nextwall].overpicnum = FANSPRITEBROKE;
|
|
wall[wal->nextwall].cstat &= 65535-65;
|
|
}
|
|
A_PlaySound(VENT_BUST,spr);
|
|
A_PlaySound(GLASS_BREAKING,spr);
|
|
return;
|
|
|
|
case GLASS__STATIC:
|
|
updatesector(pos->x,pos->y,&sn);
|
|
if (sn < 0) return;
|
|
wal->overpicnum=GLASS2;
|
|
A_SpawnWallGlass(spr,dawallnum,10);
|
|
wal->cstat = 0;
|
|
|
|
if (wal->nextwall >= 0)
|
|
wall[wal->nextwall].cstat = 0;
|
|
|
|
i = A_InsertSprite(sn,pos->x,pos->y,pos->z,SECTOREFFECTOR,0,0,0,g_player[0].ps->ang,0,0,spr,3);
|
|
SLT = 128;
|
|
T2 = 5;
|
|
T3 = dawallnum;
|
|
A_PlaySound(GLASS_BREAKING,i);
|
|
return;
|
|
|
|
case STAINGLASS1__STATIC:
|
|
updatesector(pos->x,pos->y,&sn);
|
|
if (sn < 0)
|
|
return;
|
|
A_SpawnRandomGlass(spr,dawallnum,80);
|
|
wal->cstat = 0;
|
|
if (wal->nextwall >= 0)
|
|
wall[wal->nextwall].cstat = 0;
|
|
A_PlaySound(VENT_BUST,spr);
|
|
A_PlaySound(GLASS_BREAKING,spr);
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (DYNAMICTILEMAP(wal->picnum))
|
|
{
|
|
case COLAMACHINE__STATIC:
|
|
case VENDMACHINE__STATIC:
|
|
BreakWall(wal->picnum+2,spr,dawallnum);
|
|
A_PlaySound(VENT_BUST,spr);
|
|
return;
|
|
|
|
case OJ__STATIC:
|
|
case FEMPIC2__STATIC:
|
|
case FEMPIC3__STATIC:
|
|
|
|
case SCREENBREAK6__STATIC:
|
|
case SCREENBREAK7__STATIC:
|
|
case SCREENBREAK8__STATIC:
|
|
|
|
case SCREENBREAK1__STATIC:
|
|
case SCREENBREAK2__STATIC:
|
|
case SCREENBREAK3__STATIC:
|
|
case SCREENBREAK4__STATIC:
|
|
case SCREENBREAK5__STATIC:
|
|
|
|
case SCREENBREAK9__STATIC:
|
|
case SCREENBREAK10__STATIC:
|
|
case SCREENBREAK11__STATIC:
|
|
case SCREENBREAK12__STATIC:
|
|
case SCREENBREAK13__STATIC:
|
|
case SCREENBREAK14__STATIC:
|
|
case SCREENBREAK15__STATIC:
|
|
case SCREENBREAK16__STATIC:
|
|
case SCREENBREAK17__STATIC:
|
|
case SCREENBREAK18__STATIC:
|
|
case SCREENBREAK19__STATIC:
|
|
case BORNTOBEWILDSCREEN__STATIC:
|
|
|
|
A_SpawnWallGlass(spr,dawallnum,30);
|
|
wal->picnum=W_SCREENBREAK+(krand()%3);
|
|
A_PlaySound(GLASS_HEAVYBREAK,spr);
|
|
return;
|
|
|
|
case W_TECHWALL5__STATIC:
|
|
case W_TECHWALL6__STATIC:
|
|
case W_TECHWALL7__STATIC:
|
|
case W_TECHWALL8__STATIC:
|
|
case W_TECHWALL9__STATIC:
|
|
BreakWall(wal->picnum+1,spr,dawallnum);
|
|
return;
|
|
case W_MILKSHELF__STATIC:
|
|
BreakWall(W_MILKSHELFBROKE,spr,dawallnum);
|
|
return;
|
|
|
|
case W_TECHWALL10__STATIC:
|
|
BreakWall(W_HITTECHWALL10,spr,dawallnum);
|
|
return;
|
|
|
|
case W_TECHWALL1__STATIC:
|
|
case W_TECHWALL11__STATIC:
|
|
case W_TECHWALL12__STATIC:
|
|
case W_TECHWALL13__STATIC:
|
|
case W_TECHWALL14__STATIC:
|
|
BreakWall(W_HITTECHWALL1,spr,dawallnum);
|
|
return;
|
|
|
|
case W_TECHWALL15__STATIC:
|
|
BreakWall(W_HITTECHWALL15,spr,dawallnum);
|
|
return;
|
|
|
|
case W_TECHWALL16__STATIC:
|
|
BreakWall(W_HITTECHWALL16,spr,dawallnum);
|
|
return;
|
|
|
|
case W_TECHWALL2__STATIC:
|
|
BreakWall(W_HITTECHWALL2,spr,dawallnum);
|
|
return;
|
|
|
|
case W_TECHWALL3__STATIC:
|
|
BreakWall(W_HITTECHWALL3,spr,dawallnum);
|
|
return;
|
|
|
|
case W_TECHWALL4__STATIC:
|
|
BreakWall(W_HITTECHWALL4,spr,dawallnum);
|
|
return;
|
|
|
|
case ATM__STATIC:
|
|
wal->picnum = ATMBROKE;
|
|
A_SpawnMultiple(spr, MONEY, 1+(krand()&7));
|
|
A_PlaySound(GLASS_HEAVYBREAK,spr);
|
|
break;
|
|
|
|
case WALLLIGHT1__STATIC:
|
|
case WALLLIGHT2__STATIC:
|
|
case WALLLIGHT3__STATIC:
|
|
case WALLLIGHT4__STATIC:
|
|
case TECHLIGHT2__STATIC:
|
|
case TECHLIGHT4__STATIC:
|
|
|
|
if (rnd(128))
|
|
A_PlaySound(GLASS_HEAVYBREAK,spr);
|
|
else A_PlaySound(GLASS_BREAKING,spr);
|
|
A_SpawnWallGlass(spr,dawallnum,30);
|
|
|
|
if (wal->picnum == WALLLIGHT1)
|
|
wal->picnum = WALLLIGHTBUST1;
|
|
|
|
if (wal->picnum == WALLLIGHT2)
|
|
wal->picnum = WALLLIGHTBUST2;
|
|
|
|
if (wal->picnum == WALLLIGHT3)
|
|
wal->picnum = WALLLIGHTBUST3;
|
|
|
|
if (wal->picnum == WALLLIGHT4)
|
|
wal->picnum = WALLLIGHTBUST4;
|
|
|
|
if (wal->picnum == TECHLIGHT2)
|
|
wal->picnum = TECHLIGHTBUST2;
|
|
|
|
if (wal->picnum == TECHLIGHT4)
|
|
wal->picnum = TECHLIGHTBUST4;
|
|
|
|
if (wal->lotag == 0)
|
|
return;
|
|
|
|
sn = wal->nextsector;
|
|
if (sn < 0)
|
|
return;
|
|
darkestwall = 0;
|
|
|
|
wal = &wall[sector[sn].wallptr];
|
|
for (i=sector[sn].wallnum; i > 0; i--,wal++)
|
|
if (wal->shade > darkestwall)
|
|
darkestwall=wal->shade;
|
|
|
|
j = krand()&1;
|
|
|
|
for (SPRITES_OF(STAT_EFFECTOR, i))
|
|
if (SHT == wall[dawallnum].lotag && SLT == SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT)
|
|
{
|
|
T3 = j;
|
|
T4 = darkestwall;
|
|
T5 = 1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// NOTE: return value never examined in any of the callers.
|
|
int32_t Sect_DamageCeilingOrFloor(int32_t floorp, int32_t sn)
|
|
{
|
|
int32_t i, j;
|
|
|
|
const int32_t RETURN_in = floorp ? 131072+sn : 65536+sn;
|
|
// NOTE: pass RETURN in the dist argument, too.
|
|
int32_t ret = VM_OnEvent(EVENT_DAMAGEHPLANE, g_player[screenpeek].ps->i, screenpeek,
|
|
RETURN_in, RETURN_in);
|
|
|
|
if (ret < 0)
|
|
return 0;
|
|
|
|
if (floorp)
|
|
return 0;
|
|
|
|
if (ret == (1<<20))
|
|
{
|
|
// Execute the hard-coded stuff without changing picnum (expected to
|
|
// have been done by the event).
|
|
goto GLASSBREAK_CODE;
|
|
}
|
|
|
|
switch (DYNAMICTILEMAP(sector[sn].ceilingpicnum))
|
|
{
|
|
case WALLLIGHT1__STATIC:
|
|
case WALLLIGHT2__STATIC:
|
|
case WALLLIGHT3__STATIC:
|
|
case WALLLIGHT4__STATIC:
|
|
case TECHLIGHT2__STATIC:
|
|
case TECHLIGHT4__STATIC:
|
|
|
|
if (sector[sn].ceilingpicnum == WALLLIGHT1)
|
|
sector[sn].ceilingpicnum = WALLLIGHTBUST1;
|
|
|
|
if (sector[sn].ceilingpicnum == WALLLIGHT2)
|
|
sector[sn].ceilingpicnum = WALLLIGHTBUST2;
|
|
|
|
if (sector[sn].ceilingpicnum == WALLLIGHT3)
|
|
sector[sn].ceilingpicnum = WALLLIGHTBUST3;
|
|
|
|
if (sector[sn].ceilingpicnum == WALLLIGHT4)
|
|
sector[sn].ceilingpicnum = WALLLIGHTBUST4;
|
|
|
|
if (sector[sn].ceilingpicnum == TECHLIGHT2)
|
|
sector[sn].ceilingpicnum = TECHLIGHTBUST2;
|
|
|
|
if (sector[sn].ceilingpicnum == TECHLIGHT4)
|
|
sector[sn].ceilingpicnum = TECHLIGHTBUST4;
|
|
|
|
GLASSBREAK_CODE:
|
|
A_SpawnCeilingGlass(g_player[myconnectindex].ps->i,sn,10);
|
|
A_PlaySound(GLASS_BREAKING,g_player[screenpeek].ps->i);
|
|
|
|
if (sector[sn].hitag == 0)
|
|
{
|
|
for (SPRITES_OF_SECT(sn, i))
|
|
{
|
|
if (PN == SECTOREFFECTOR && SLT == SE_12_LIGHT_SWITCH)
|
|
{
|
|
for (SPRITES_OF(STAT_EFFECTOR, j))
|
|
if (sprite[j].hitag == SHT)
|
|
actor[j].t_data[3] = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
j = krand()&1;
|
|
|
|
for (SPRITES_OF(STAT_EFFECTOR, i))
|
|
if (SHT == sector[sn].hitag && SLT == SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT)
|
|
{
|
|
T3 = j;
|
|
T5 = 1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// hard coded props... :(
|
|
void A_DamageObject(int32_t i,int32_t sn)
|
|
{
|
|
int16_t j;
|
|
int32_t k, rpg=0;
|
|
spritetype *s;
|
|
|
|
if (g_netClient)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// int32_t switchpicnum = PN;
|
|
|
|
i &= (MAXSPRITES-1);
|
|
|
|
if (A_CheckSpriteFlags(sn,SPRITE_PROJECTILE))
|
|
if (SpriteProjectile[sn].workslike & PROJECTILE_RPG)
|
|
rpg = 1;
|
|
/*
|
|
switchpicnum = PN;
|
|
if (PN > WATERFOUNTAIN && PN < WATERFOUNTAIN+3)
|
|
{
|
|
switchpicnum = WATERFOUNTAIN;
|
|
}
|
|
*/
|
|
switch (DYNAMICTILEMAP(PN))
|
|
{
|
|
case OCEANSPRITE1__STATIC:
|
|
case OCEANSPRITE2__STATIC:
|
|
case OCEANSPRITE3__STATIC:
|
|
case OCEANSPRITE4__STATIC:
|
|
case OCEANSPRITE5__STATIC:
|
|
A_Spawn(i,SMALLSMOKE);
|
|
A_DeleteSprite(i);
|
|
break;
|
|
case QUEBALL__STATIC:
|
|
case STRIPEBALL__STATIC:
|
|
if (sprite[sn].picnum == QUEBALL || sprite[sn].picnum == STRIPEBALL)
|
|
{
|
|
sprite[sn].xvel = (sprite[i].xvel>>1)+(sprite[i].xvel>>2);
|
|
sprite[sn].ang -= (SA<<1)+1024;
|
|
SA = getangle(SX-sprite[sn].x,SY-sprite[sn].y)-512;
|
|
if (S_CheckSoundPlaying(i,POOLBALLHIT) < 2)
|
|
A_PlaySound(POOLBALLHIT,i);
|
|
}
|
|
else
|
|
{
|
|
if (krand()&3)
|
|
{
|
|
sprite[i].xvel = 164;
|
|
sprite[i].ang = sprite[sn].ang;
|
|
}
|
|
else
|
|
{
|
|
A_SpawnWallGlass(i,-1,3);
|
|
A_DeleteSprite(i);
|
|
}
|
|
}
|
|
break;
|
|
case TREE1__STATIC:
|
|
case TREE2__STATIC:
|
|
case TIRE__STATIC:
|
|
case CONE__STATIC:
|
|
case BOX__STATIC:
|
|
{
|
|
if (rpg == 1)
|
|
if (T1 == 0)
|
|
{
|
|
CS &= ~257;
|
|
T1 = 1;
|
|
A_Spawn(i,BURNING);
|
|
}
|
|
switch (DYNAMICTILEMAP(sprite[sn].picnum))
|
|
{
|
|
case RADIUSEXPLOSION__STATIC:
|
|
case RPG__STATIC:
|
|
case FIRELASER__STATIC:
|
|
case HYDRENT__STATIC:
|
|
case HEAVYHBOMB__STATIC:
|
|
if (T1 == 0)
|
|
{
|
|
CS &= ~257;
|
|
T1 = 1;
|
|
A_Spawn(i,BURNING);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case CACTUS__STATIC:
|
|
{
|
|
if (rpg == 1)
|
|
for (k=64; k>0; k--)
|
|
{
|
|
j = A_InsertSprite(SECT,SX,SY,SZ-(krand()%(48<<8)),SCRAP3+(krand()&3),-8,48,48,krand()&2047,(krand()&63)+64,-(krand()&4095)-(sprite[i].zvel>>2),i,5);
|
|
sprite[j].pal = 8;
|
|
}
|
|
// case CACTUSBROKE:
|
|
switch (DYNAMICTILEMAP(sprite[sn].picnum))
|
|
{
|
|
case RADIUSEXPLOSION__STATIC:
|
|
case RPG__STATIC:
|
|
case FIRELASER__STATIC:
|
|
case HYDRENT__STATIC:
|
|
case HEAVYHBOMB__STATIC:
|
|
for (k=64; k>0; k--)
|
|
{
|
|
j = A_InsertSprite(SECT,SX,SY,SZ-(krand()%(48<<8)),SCRAP3+(krand()&3),-8,48,48,krand()&2047,(krand()&63)+64,-(krand()&4095)-(sprite[i].zvel>>2),i,5);
|
|
sprite[j].pal = 8;
|
|
}
|
|
|
|
if (PN == CACTUS)
|
|
PN = CACTUSBROKE;
|
|
CS &= ~257;
|
|
// else A_DeleteSprite(i);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case HANGLIGHT__STATIC:
|
|
case GENERICPOLE2__STATIC:
|
|
for (k=6; k>0; k--)
|
|
A_InsertSprite(SECT,SX,SY,SZ-(8<<8),SCRAP1+(krand()&15),-8,48,48,krand()&2047,(krand()&63)+64,-(krand()&4095)-(sprite[i].zvel>>2),i,5);
|
|
A_PlaySound(GLASS_HEAVYBREAK,i);
|
|
A_DeleteSprite(i);
|
|
break;
|
|
|
|
|
|
case FANSPRITE__STATIC:
|
|
PN = FANSPRITEBROKE;
|
|
CS &= (65535-257);
|
|
if (sector[SECT].floorpicnum == FANSHADOW)
|
|
sector[SECT].floorpicnum = FANSHADOWBROKE;
|
|
|
|
A_PlaySound(GLASS_HEAVYBREAK,i);
|
|
s = &sprite[i];
|
|
for (j=16; j>0; j--) RANDOMSCRAP;
|
|
|
|
break;
|
|
case WATERFOUNTAIN__STATIC:
|
|
// case WATERFOUNTAIN+1:
|
|
// case WATERFOUNTAIN+2:
|
|
// case __STATIC:
|
|
PN = WATERFOUNTAINBROKE;
|
|
A_Spawn(i,TOILETWATER);
|
|
break;
|
|
case SATELITE__STATIC:
|
|
case FUELPOD__STATIC:
|
|
case SOLARPANNEL__STATIC:
|
|
case ANTENNA__STATIC:
|
|
if (sprite[sn].extra != G_InitialActorStrength(SHOTSPARK1))
|
|
{
|
|
for (j=15; j>0; j--)
|
|
A_InsertSprite(SECT,SX,SY,sector[SECT].floorz-(12<<8)-(j<<9),SCRAP1+(krand()&15),-8,64,64,
|
|
krand()&2047,(krand()&127)+64,-(krand()&511)-256,i,5);
|
|
A_Spawn(i,EXPLOSION2);
|
|
A_DeleteSprite(i);
|
|
}
|
|
break;
|
|
case BOTTLE1__STATIC:
|
|
case BOTTLE2__STATIC:
|
|
case BOTTLE3__STATIC:
|
|
case BOTTLE4__STATIC:
|
|
case BOTTLE5__STATIC:
|
|
case BOTTLE6__STATIC:
|
|
case BOTTLE8__STATIC:
|
|
case BOTTLE10__STATIC:
|
|
case BOTTLE11__STATIC:
|
|
case BOTTLE12__STATIC:
|
|
case BOTTLE13__STATIC:
|
|
case BOTTLE14__STATIC:
|
|
case BOTTLE15__STATIC:
|
|
case BOTTLE16__STATIC:
|
|
case BOTTLE17__STATIC:
|
|
case BOTTLE18__STATIC:
|
|
case BOTTLE19__STATIC:
|
|
case WATERFOUNTAINBROKE__STATIC:
|
|
case DOMELITE__STATIC:
|
|
case SUSHIPLATE1__STATIC:
|
|
case SUSHIPLATE2__STATIC:
|
|
case SUSHIPLATE3__STATIC:
|
|
case SUSHIPLATE4__STATIC:
|
|
case SUSHIPLATE5__STATIC:
|
|
case WAITTOBESEATED__STATIC:
|
|
case VASE__STATIC:
|
|
case STATUEFLASH__STATIC:
|
|
case STATUE__STATIC:
|
|
if (PN == BOTTLE10)
|
|
A_SpawnMultiple(i, MONEY, 4+(krand()&3));
|
|
else if (PN == STATUE || PN == STATUEFLASH)
|
|
{
|
|
A_SpawnRandomGlass(i,-1,40);
|
|
A_PlaySound(GLASS_HEAVYBREAK,i);
|
|
}
|
|
else if (PN == VASE)
|
|
A_SpawnWallGlass(i,-1,40);
|
|
|
|
A_PlaySound(GLASS_BREAKING,i);
|
|
SA = krand()&2047;
|
|
A_SpawnWallGlass(i,-1,8);
|
|
A_DeleteSprite(i);
|
|
break;
|
|
case FETUS__STATIC:
|
|
PN = FETUSBROKE;
|
|
A_PlaySound(GLASS_BREAKING,i);
|
|
A_SpawnWallGlass(i,-1,10);
|
|
break;
|
|
case FETUSBROKE__STATIC:
|
|
for (j=48; j>0; j--)
|
|
{
|
|
A_Shoot(i,BLOODSPLAT1);
|
|
SA += 333;
|
|
}
|
|
A_PlaySound(GLASS_HEAVYBREAK,i);
|
|
A_PlaySound(SQUISHED,i);
|
|
case BOTTLE7__STATIC:
|
|
A_PlaySound(GLASS_BREAKING,i);
|
|
A_SpawnWallGlass(i,-1,10);
|
|
A_DeleteSprite(i);
|
|
break;
|
|
case HYDROPLANT__STATIC:
|
|
PN = BROKEHYDROPLANT;
|
|
A_PlaySound(GLASS_BREAKING,i);
|
|
A_SpawnWallGlass(i,-1,10);
|
|
break;
|
|
|
|
case FORCESPHERE__STATIC:
|
|
sprite[i].xrepeat = 0;
|
|
actor[OW].t_data[0] = 32;
|
|
actor[OW].t_data[1] = !actor[OW].t_data[1];
|
|
actor[OW].t_data[2] ++;
|
|
A_Spawn(i,EXPLOSION2);
|
|
break;
|
|
|
|
case BROKEHYDROPLANT__STATIC:
|
|
A_PlaySound(GLASS_BREAKING,i);
|
|
A_SpawnWallGlass(i,-1,5);
|
|
A_DeleteSprite(i);
|
|
break;
|
|
|
|
case TOILET__STATIC:
|
|
PN = TOILETBROKE;
|
|
CS |= (krand()&1)<<2;
|
|
CS &= ~257;
|
|
A_Spawn(i,TOILETWATER);
|
|
A_PlaySound(GLASS_BREAKING,i);
|
|
break;
|
|
|
|
case STALL__STATIC:
|
|
PN = STALLBROKE;
|
|
CS |= (krand()&1)<<2;
|
|
CS &= ~257;
|
|
A_Spawn(i,TOILETWATER);
|
|
A_PlaySound(GLASS_HEAVYBREAK,i);
|
|
break;
|
|
|
|
case HYDRENT__STATIC:
|
|
PN = BROKEFIREHYDRENT;
|
|
A_Spawn(i,TOILETWATER);
|
|
|
|
// for(k=0;k<5;k++)
|
|
// {
|
|
// j = A_InsertSprite(SECT,SX,SY,SZ-(krand()%(48<<8)),SCRAP3+(krand()&3),-8,48,48,krand()&2047,(krand()&63)+64,-(krand()&4095)-(sprite[i].zvel>>2),i,5);
|
|
// sprite[j].pal = 2;
|
|
// }
|
|
A_PlaySound(GLASS_HEAVYBREAK,i);
|
|
break;
|
|
|
|
case GRATE1__STATIC:
|
|
PN = BGRATE1;
|
|
CS &= (65535-256-1);
|
|
A_PlaySound(VENT_BUST,i);
|
|
break;
|
|
|
|
case CIRCLEPANNEL__STATIC:
|
|
PN = CIRCLEPANNELBROKE;
|
|
CS &= (65535-256-1);
|
|
A_PlaySound(VENT_BUST,i);
|
|
break;
|
|
case PANNEL1__STATIC:
|
|
case PANNEL2__STATIC:
|
|
PN = BPANNEL1;
|
|
CS &= (65535-256-1);
|
|
A_PlaySound(VENT_BUST,i);
|
|
break;
|
|
case PANNEL3__STATIC:
|
|
PN = BPANNEL3;
|
|
CS &= (65535-256-1);
|
|
A_PlaySound(VENT_BUST,i);
|
|
break;
|
|
case PIPE1__STATIC:
|
|
case PIPE2__STATIC:
|
|
case PIPE3__STATIC:
|
|
case PIPE4__STATIC:
|
|
case PIPE5__STATIC:
|
|
case PIPE6__STATIC:
|
|
switch (DYNAMICTILEMAP(PN))
|
|
{
|
|
case PIPE1__STATIC:
|
|
PN=PIPE1B;
|
|
break;
|
|
case PIPE2__STATIC:
|
|
PN=PIPE2B;
|
|
break;
|
|
case PIPE3__STATIC:
|
|
PN=PIPE3B;
|
|
break;
|
|
case PIPE4__STATIC:
|
|
PN=PIPE4B;
|
|
break;
|
|
case PIPE5__STATIC:
|
|
PN=PIPE5B;
|
|
break;
|
|
case PIPE6__STATIC:
|
|
PN=PIPE6B;
|
|
break;
|
|
}
|
|
|
|
j = A_Spawn(i,STEAM);
|
|
sprite[j].z = sector[SECT].floorz-(32<<8);
|
|
break;
|
|
|
|
case MONK__STATIC:
|
|
case LUKE__STATIC:
|
|
case INDY__STATIC:
|
|
case JURYGUY__STATIC:
|
|
A_PlaySound(SLT,i);
|
|
A_Spawn(i,SHT);
|
|
case SPACEMARINE__STATIC:
|
|
sprite[i].extra -= sprite[sn].extra;
|
|
if (sprite[i].extra > 0) break;
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT1);
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT2);
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT3);
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT4);
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT1);
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT2);
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT3);
|
|
SA = krand()&2047;
|
|
A_Shoot(i,BLOODSPLAT4);
|
|
A_DoGuts(i,JIBS1,1);
|
|
A_DoGuts(i,JIBS2,2);
|
|
A_DoGuts(i,JIBS3,3);
|
|
A_DoGuts(i,JIBS4,4);
|
|
A_DoGuts(i,JIBS5,1);
|
|
A_DoGuts(i,JIBS3,6);
|
|
S_PlaySound(SQUISHED);
|
|
A_DeleteSprite(i);
|
|
break;
|
|
case CHAIR1__STATIC:
|
|
case CHAIR2__STATIC:
|
|
PN = BROKENCHAIR;
|
|
CS = 0;
|
|
break;
|
|
case CHAIR3__STATIC:
|
|
case MOVIECAMERA__STATIC:
|
|
case SCALE__STATIC:
|
|
case VACUUM__STATIC:
|
|
case CAMERALIGHT__STATIC:
|
|
case IVUNIT__STATIC:
|
|
case POT1__STATIC:
|
|
case POT2__STATIC:
|
|
case POT3__STATIC:
|
|
case TRIPODCAMERA__STATIC:
|
|
A_PlaySound(GLASS_HEAVYBREAK,i);
|
|
s = &sprite[i];
|
|
for (j=16; j>0; j--) RANDOMSCRAP;
|
|
A_DeleteSprite(i);
|
|
break;
|
|
case PLAYERONWATER__STATIC:
|
|
i = OW;
|
|
default:
|
|
if ((sprite[i].cstat&16) && SHT == 0 && SLT == 0 && sprite[i].statnum == STAT_DEFAULT)
|
|
break;
|
|
|
|
if ((sprite[sn].picnum == FREEZEBLAST || sprite[sn].owner != i) && sprite[i].statnum != STAT_PROJECTILE)
|
|
{
|
|
if (A_CheckEnemySprite(&sprite[i]) == 1)
|
|
{
|
|
if (sprite[sn].picnum == RPG) sprite[sn].extra <<= 1;
|
|
|
|
if ((PN != DRONE) && (PN != ROTATEGUN) && (PN != COMMANDER) && (PN < GREENSLIME || PN > GREENSLIME+7))
|
|
if (sprite[sn].picnum != FREEZEBLAST)
|
|
if (!A_CheckSpriteTileFlags(PN, SPRITE_BADGUY))
|
|
{
|
|
j = A_Spawn(sn,JIBS6);
|
|
if (sprite[sn].pal == 6)
|
|
sprite[j].pal = 6;
|
|
sprite[j].z += (4<<8);
|
|
sprite[j].xvel = 16;
|
|
sprite[j].xrepeat = sprite[j].yrepeat = 24;
|
|
sprite[j].ang += 32-(krand()&63);
|
|
}
|
|
|
|
j = sprite[sn].owner;
|
|
|
|
if (j >= 0 && sprite[j].picnum == APLAYER && PN != ROTATEGUN && PN != DRONE)
|
|
if (g_player[P_Get(j)].ps->curr_weapon == SHOTGUN_WEAPON)
|
|
{
|
|
A_Shoot(i,BLOODSPLAT3);
|
|
A_Shoot(i,BLOODSPLAT1);
|
|
A_Shoot(i,BLOODSPLAT2);
|
|
A_Shoot(i,BLOODSPLAT4);
|
|
}
|
|
|
|
if (PN != TANK && PN != BOSS1 && PN != BOSS4 && PN != BOSS2 && PN != BOSS3 && PN != RECON && PN != ROTATEGUN)
|
|
{
|
|
if (sprite[i].extra > 0)
|
|
{
|
|
if ((sprite[i].cstat&48) == 0)
|
|
SA = (sprite[sn].ang+1024)&2047;
|
|
sprite[i].xvel = -(sprite[sn].extra<<2);
|
|
j = SECT;
|
|
pushmove((vec3_t *)&sprite[i],&j,128L,(4L<<8),(4L<<8),CLIPMASK0);
|
|
if (j != SECT && (unsigned)j < MAXSECTORS)
|
|
changespritesect(i,j);
|
|
}
|
|
}
|
|
|
|
if (sprite[i].statnum == STAT_ZOMBIEACTOR)
|
|
{
|
|
changespritestat(i, STAT_ACTOR);
|
|
actor[i].timetosleep = SLEEPTIME;
|
|
}
|
|
if ((sprite[i].xrepeat < 24 || PN == SHARK) && sprite[sn].picnum == SHRINKSPARK)
|
|
return;
|
|
}
|
|
|
|
if (sprite[i].statnum != STAT_ZOMBIEACTOR)
|
|
{
|
|
if (sprite[sn].picnum == FREEZEBLAST && ((PN == APLAYER && sprite[i].pal == 1) || (g_freezerSelfDamage == 0 && sprite[sn].owner == i)))
|
|
return;
|
|
|
|
actor[i].picnum = sprite[sn].picnum;
|
|
actor[i].extra += sprite[sn].extra;
|
|
actor[i].ang = sprite[sn].ang;
|
|
actor[i].owner = sprite[sn].owner;
|
|
}
|
|
|
|
if (sprite[i].statnum == STAT_PLAYER)
|
|
{
|
|
DukePlayer_t *ps = g_player[P_Get(i)].ps;
|
|
|
|
if (ps->newowner >= 0)
|
|
G_ClearCameraView(ps);
|
|
|
|
if (sprite[i].xrepeat < 24 && sprite[sn].picnum == SHRINKSPARK)
|
|
return;
|
|
|
|
if (sprite[actor[i].owner].picnum != APLAYER)
|
|
if (ud.player_skill >= 3)
|
|
sprite[sn].extra += (sprite[sn].extra>>1);
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void G_AlignWarpElevators(void)
|
|
{
|
|
int32_t i, j;
|
|
|
|
for (SPRITES_OF(STAT_EFFECTOR, i))
|
|
{
|
|
if (SLT == SE_17_WARP_ELEVATOR && SS > 16)
|
|
{
|
|
for (SPRITES_OF(STAT_EFFECTOR, j))
|
|
{
|
|
if (i != j && sprite[j].lotag == SE_17_WARP_ELEVATOR && SHT == sprite[j].hitag)
|
|
{
|
|
sector[sprite[j].sectnum].floorz = sector[SECT].floorz;
|
|
sector[sprite[j].sectnum].ceilingz = sector[SECT].ceilingz;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void P_HandleSharedKeys(int32_t snum)
|
|
{
|
|
int32_t i, k = 0, dainv;
|
|
uint32_t sb_snum = g_player[snum].sync->bits, j;
|
|
DukePlayer_t *p = g_player[snum].ps;
|
|
|
|
if (p->cheat_phase == 1) return;
|
|
|
|
// 1<<0 = jump
|
|
// 1<<1 = crouch
|
|
// 1<<2 = fire
|
|
// 1<<3 = aim up
|
|
// 1<<4 = aim down
|
|
// 1<<5 = run
|
|
// 1<<6 = look left
|
|
// 1<<7 = look right
|
|
// 15<<8 = !weapon selection (bits 8-11)
|
|
// 1<<12 = !steroids
|
|
// 1<<13 = look up
|
|
// 1<<14 = look down
|
|
// 1<<15 = !nightvis
|
|
// 1<<16 = !medkit
|
|
// 1<<17 = (multiflag==1) ? changes meaning of bits 18 and 19
|
|
// 1<<18 = centre view
|
|
// 1<<19 = !holster weapon
|
|
// 1<<20 = !inventory left
|
|
// 1<<21 = !pause
|
|
// 1<<22 = !quick kick
|
|
// 1<<23 = aim mode
|
|
// 1<<24 = !holoduke
|
|
// 1<<25 = !jetpack
|
|
// 1<<26 = g_gameQuit
|
|
// 1<<27 = !inventory right
|
|
// 1<<28 = !turn around
|
|
// 1<<29 = !open
|
|
// 1<<30 = !inventory
|
|
// 1<<31 = !escape
|
|
|
|
i = p->aim_mode;
|
|
p->aim_mode = (sb_snum>>SK_AIMMODE)&1;
|
|
if (p->aim_mode < i)
|
|
p->return_to_center = 9;
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_QUICK_KICK) && p->quick_kick == 0)
|
|
if (p->curr_weapon != KNEE_WEAPON || p->kickback_pic == 0)
|
|
{
|
|
if (VM_OnEvent(EVENT_QUICKKICK,g_player[snum].ps->i,snum, -1, 0) == 0)
|
|
{
|
|
p->quick_kick = 14;
|
|
if (p->fta == 0 || p->ftq == 80)
|
|
P_DoQuote(QUOTE_MIGHTY_FOOT,p);
|
|
}
|
|
}
|
|
|
|
j = sb_snum & ((15u<<SK_WEAPON_BITS)|BIT(SK_STEROIDS)|BIT(SK_NIGHTVISION)|BIT(SK_MEDKIT)|BIT(SK_QUICK_KICK)| \
|
|
BIT(SK_HOLSTER)|BIT(SK_INV_LEFT)|BIT(SK_PAUSE)|BIT(SK_HOLODUKE)|BIT(SK_JETPACK)|BIT(SK_INV_RIGHT)| \
|
|
BIT(SK_TURNAROUND)|BIT(SK_OPEN)|BIT(SK_INVENTORY)|BIT(SK_ESCAPE));
|
|
sb_snum = j & ~p->interface_toggle_flag;
|
|
p->interface_toggle_flag |= sb_snum | ((sb_snum&0xf00)?0xf00:0);
|
|
p->interface_toggle_flag &= j | ((j&0xf00)?0xf00:0);
|
|
|
|
if (sb_snum && TEST_SYNC_KEY(sb_snum, SK_MULTIFLAG) == 0)
|
|
{
|
|
if (TEST_SYNC_KEY(sb_snum, SK_PAUSE))
|
|
{
|
|
KB_ClearKeyDown(sc_Pause);
|
|
if (ud.pause_on)
|
|
ud.pause_on = 0;
|
|
else ud.pause_on = 1+SHIFTS_IS_PRESSED;
|
|
if (ud.pause_on)
|
|
{
|
|
S_PauseMusic(1);
|
|
FX_StopAllSounds();
|
|
S_ClearSoundLocks();
|
|
}
|
|
else
|
|
{
|
|
if (ud.config.MusicToggle) S_PauseMusic(0);
|
|
pub = NUMPAGES;
|
|
pus = NUMPAGES;
|
|
}
|
|
}
|
|
|
|
if (ud.pause_on) return;
|
|
|
|
if (sprite[p->i].extra <= 0) return; // if dead...
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_INVENTORY) && p->newowner == -1) // inventory button generates event for selected item
|
|
{
|
|
if (VM_OnEvent(EVENT_INVENTORY,g_player[snum].ps->i,snum, -1, 0) == 0)
|
|
{
|
|
switch (p->inven_icon)
|
|
{
|
|
case ICON_JETPACK:
|
|
sb_snum |= BIT(SK_JETPACK);
|
|
break;
|
|
case ICON_HOLODUKE:
|
|
sb_snum |= BIT(SK_HOLODUKE);
|
|
break;
|
|
case ICON_HEATS:
|
|
sb_snum |= BIT(SK_NIGHTVISION);
|
|
break;
|
|
case ICON_FIRSTAID:
|
|
sb_snum |= BIT(SK_MEDKIT);
|
|
break;
|
|
case ICON_STEROIDS:
|
|
sb_snum |= BIT(SK_STEROIDS);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_NIGHTVISION))
|
|
{
|
|
if (VM_OnEvent(EVENT_USENIGHTVISION,g_player[snum].ps->i,snum, -1, 0) == 0
|
|
&& p->inv_amount[GET_HEATS] > 0)
|
|
{
|
|
p->heat_on = !p->heat_on;
|
|
P_UpdateScreenPal(p);
|
|
p->inven_icon = ICON_HEATS;
|
|
A_PlaySound(NITEVISION_ONOFF,p->i);
|
|
P_DoQuote(QUOTE_NVG_OFF-!!p->heat_on,p);
|
|
}
|
|
}
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_STEROIDS))
|
|
{
|
|
if (VM_OnEvent(EVENT_USESTEROIDS,g_player[snum].ps->i,snum, -1, 0) == 0)
|
|
{
|
|
if (p->inv_amount[GET_STEROIDS] == 400)
|
|
{
|
|
p->inv_amount[GET_STEROIDS]--;
|
|
A_PlaySound(DUKE_TAKEPILLS,p->i);
|
|
P_DoQuote(QUOTE_USED_STEROIDS,p);
|
|
}
|
|
if (p->inv_amount[GET_STEROIDS] > 0)
|
|
p->inven_icon = ICON_STEROIDS;
|
|
}
|
|
return; // is there significance to returning?
|
|
}
|
|
if (p->refresh_inventory)
|
|
sb_snum |= BIT(SK_INV_LEFT); // emulate move left...
|
|
|
|
if (p->newowner == -1 && (TEST_SYNC_KEY(sb_snum, SK_INV_LEFT) || TEST_SYNC_KEY(sb_snum, SK_INV_RIGHT)))
|
|
{
|
|
p->invdisptime = GAMETICSPERSEC*2;
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_INV_RIGHT)) k = 1;
|
|
else k = 0;
|
|
|
|
if (p->refresh_inventory) p->refresh_inventory = 0;
|
|
dainv = p->inven_icon;
|
|
|
|
i = 0;
|
|
|
|
CHECKINV1:
|
|
if (i < 9)
|
|
{
|
|
i++;
|
|
|
|
switch (dainv)
|
|
{
|
|
case ICON_JETPACK:
|
|
if (p->inv_amount[GET_JETPACK] > 0 && i > 1)
|
|
break;
|
|
if (k) dainv++;
|
|
else dainv--;
|
|
goto CHECKINV1;
|
|
case ICON_SCUBA:
|
|
if (p->inv_amount[GET_SCUBA] > 0 && i > 1)
|
|
break;
|
|
if (k) dainv++;
|
|
else dainv--;
|
|
goto CHECKINV1;
|
|
case ICON_STEROIDS:
|
|
if (p->inv_amount[GET_STEROIDS] > 0 && i > 1)
|
|
break;
|
|
if (k) dainv++;
|
|
else dainv--;
|
|
goto CHECKINV1;
|
|
case ICON_HOLODUKE:
|
|
if (p->inv_amount[GET_HOLODUKE] > 0 && i > 1)
|
|
break;
|
|
if (k) dainv++;
|
|
else dainv--;
|
|
goto CHECKINV1;
|
|
case ICON_NONE:
|
|
case ICON_FIRSTAID:
|
|
if (p->inv_amount[GET_FIRSTAID] > 0 && i > 1)
|
|
break;
|
|
if (k) dainv = 2;
|
|
else dainv = 7;
|
|
goto CHECKINV1;
|
|
case ICON_HEATS:
|
|
if (p->inv_amount[GET_HEATS] > 0 && i > 1)
|
|
break;
|
|
if (k) dainv++;
|
|
else dainv--;
|
|
goto CHECKINV1;
|
|
case ICON_BOOTS:
|
|
if (p->inv_amount[GET_BOOTS] > 0 && i > 1)
|
|
break;
|
|
if (k) dainv = 1;
|
|
else dainv = 6;
|
|
goto CHECKINV1;
|
|
}
|
|
}
|
|
else dainv = 0;
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_INV_LEFT)) // Inventory_Left
|
|
{
|
|
/*Gv_SetVar(g_iReturnVarID,dainv,g_player[snum].ps->i,snum);*/
|
|
dainv = VM_OnEvent(EVENT_INVENTORYLEFT,g_player[snum].ps->i,snum, -1, dainv);
|
|
}
|
|
else if (TEST_SYNC_KEY(sb_snum, SK_INV_RIGHT)) // Inventory_Right
|
|
{
|
|
/*Gv_SetVar(g_iReturnVarID,dainv,g_player[snum].ps->i,snum);*/
|
|
dainv = VM_OnEvent(EVENT_INVENTORYRIGHT,g_player[snum].ps->i,snum, -1, dainv);
|
|
}
|
|
|
|
if (dainv >= 1)
|
|
{
|
|
p->inven_icon = dainv;
|
|
|
|
if (dainv || p->inv_amount[GET_FIRSTAID])
|
|
{
|
|
static const int32_t i[8] = { QUOTE_MEDKIT, QUOTE_STEROIDS, QUOTE_HOLODUKE,
|
|
QUOTE_JETPACK, QUOTE_NVG, QUOTE_SCUBA, QUOTE_BOOTS, 0 };
|
|
if (dainv>=1 && dainv<=9)
|
|
P_DoQuote(i[dainv-1], p);
|
|
}
|
|
}
|
|
}
|
|
|
|
j = ((sb_snum&(15<<SK_WEAPON_BITS))>>SK_WEAPON_BITS) - 1;
|
|
|
|
switch ((int32_t)j)
|
|
{
|
|
case -1:
|
|
break;
|
|
default:
|
|
j = VM_OnEvent(EVENT_WEAPKEY1+j,p->i,snum, -1, j);
|
|
break;
|
|
case 10:
|
|
j = VM_OnEvent(EVENT_PREVIOUSWEAPON,p->i,snum, -1, j);
|
|
break;
|
|
case 11:
|
|
j = VM_OnEvent(EVENT_NEXTWEAPON,p->i,snum, -1, j);
|
|
break;
|
|
}
|
|
|
|
// NOTE: it is assumed that the above events return either -1 or a
|
|
// valid weapon index. Presumably, neither other negative numbers nor
|
|
// positive ones >= MAX_WEAPONS are allowed. However, the code below is
|
|
// a bit inconsistent in checking "j".
|
|
|
|
if (p->reloading == 1)
|
|
j = -1;
|
|
else if ((uint32_t)j < MAX_WEAPONS && p->kickback_pic == 1 && p->weapon_pos == 1)
|
|
{
|
|
p->wantweaponfire = j;
|
|
p->kickback_pic = 0;
|
|
}
|
|
|
|
if ((int32_t)j != -1 && p->last_pissed_time <= (GAMETICSPERSEC*218) && p->show_empty_weapon == 0 /*&& p->kickback_pic == 0*/ &&
|
|
p->quick_kick == 0 && sprite[p->i].xrepeat > 32 && p->access_incs == 0 && p->knee_incs == 0)
|
|
{
|
|
// if( ( p->weapon_pos == 0 || ( p->holster_weapon && p->weapon_pos == WEAPON_POS_LOWER ) ))
|
|
{
|
|
if (j == 10 || j == 11)
|
|
{
|
|
k = p->curr_weapon;
|
|
j = (j == 10 ? -1 : 1); // JBF: prev (-1) or next (1) weapon choice
|
|
i = 0;
|
|
|
|
while ((k >= 0 && k < 10) || (PLUTOPAK && k == GROW_WEAPON && (p->subweapon&(1<<GROW_WEAPON)))) // JBF 20040116: so we don't select grower with v1.3d
|
|
{
|
|
if (k == GROW_WEAPON) // JBF: this is handling next/previous with the grower selected
|
|
{
|
|
if ((int32_t)j == -1)
|
|
k = 5;
|
|
else k = 7;
|
|
}
|
|
else
|
|
{
|
|
k += j;
|
|
if (PLUTOPAK) // JBF 20040116: so we don't select grower with v1.3d
|
|
if (k == SHRINKER_WEAPON && (p->subweapon&(1<<GROW_WEAPON))) // JBF: activates grower
|
|
k = GROW_WEAPON; // if enabled
|
|
}
|
|
|
|
if (k == -1) k = 9;
|
|
else if (k == 10) k = 0;
|
|
|
|
if ((p->gotweapon & (1<<k)) && p->ammo_amount[k] > 0)
|
|
{
|
|
if (PLUTOPAK) // JBF 20040116: so we don't select grower with v1.3d
|
|
if (k == SHRINKER_WEAPON && (p->subweapon&(1<<GROW_WEAPON)))
|
|
k = GROW_WEAPON;
|
|
j = k;
|
|
break;
|
|
}
|
|
else // JBF: grower with no ammo, but shrinker with ammo, switch to shrink
|
|
if (PLUTOPAK && k == GROW_WEAPON && p->ammo_amount[GROW_WEAPON] == 0 &&
|
|
(p->gotweapon & (1<<SHRINKER_WEAPON)) && p->ammo_amount[SHRINKER_WEAPON] > 0) // JBF 20040116: added PLUTOPAK so we don't select grower with v1.3d
|
|
{
|
|
j = SHRINKER_WEAPON;
|
|
p->subweapon &= ~(1<<GROW_WEAPON);
|
|
break;
|
|
}
|
|
else // JBF: shrinker with no ammo, but grower with ammo, switch to grow
|
|
if (PLUTOPAK && k == SHRINKER_WEAPON && p->ammo_amount[SHRINKER_WEAPON] == 0 &&
|
|
(p->gotweapon & (1<<SHRINKER_WEAPON)) && p->ammo_amount[GROW_WEAPON] > 0) // JBF 20040116: added PLUTOPAK so we don't select grower with v1.3d
|
|
{
|
|
j = GROW_WEAPON;
|
|
p->subweapon |= (1<<GROW_WEAPON);
|
|
break;
|
|
}
|
|
|
|
if (++i == 10) // absolutely no weapons, so use foot
|
|
{
|
|
j = KNEE_WEAPON;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
P_SetWeaponGamevars(snum, p);
|
|
|
|
j = VM_OnEvent(EVENT_SELECTWEAPON,p->i,snum, -1, j);
|
|
|
|
// XXX: any signifcance to "<= MAX_WEAPONS" instead of "<"?
|
|
if ((int32_t)j != -1 && j <= MAX_WEAPONS)
|
|
{
|
|
if (j == HANDBOMB_WEAPON && p->ammo_amount[HANDBOMB_WEAPON] == 0)
|
|
{
|
|
k = headspritestat[STAT_ACTOR];
|
|
while (k >= 0)
|
|
{
|
|
if (sprite[k].picnum == HEAVYHBOMB && sprite[k].owner == p->i)
|
|
{
|
|
p->gotweapon |= (1<<HANDBOMB_WEAPON);
|
|
j = HANDREMOTE_WEAPON;
|
|
break;
|
|
}
|
|
k = nextspritestat[k];
|
|
}
|
|
}
|
|
|
|
if (j == SHRINKER_WEAPON && PLUTOPAK) // JBF 20040116: so we don't select the grower with v1.3d
|
|
{
|
|
if (screenpeek == snum) pus = NUMPAGES;
|
|
|
|
if (p->curr_weapon != GROW_WEAPON && p->curr_weapon != SHRINKER_WEAPON)
|
|
{
|
|
if (p->ammo_amount[GROW_WEAPON] > 0)
|
|
{
|
|
if ((p->subweapon&(1<<GROW_WEAPON)) == (1<<GROW_WEAPON))
|
|
j = GROW_WEAPON;
|
|
else if (p->ammo_amount[SHRINKER_WEAPON] == 0)
|
|
{
|
|
j = GROW_WEAPON;
|
|
p->subweapon |= (1<<GROW_WEAPON);
|
|
}
|
|
}
|
|
else if (p->ammo_amount[SHRINKER_WEAPON] > 0)
|
|
p->subweapon &= ~(1<<GROW_WEAPON);
|
|
}
|
|
else if (p->curr_weapon == SHRINKER_WEAPON)
|
|
{
|
|
p->subweapon |= (1<<GROW_WEAPON);
|
|
j = GROW_WEAPON;
|
|
}
|
|
else
|
|
p->subweapon &= ~(1<<GROW_WEAPON);
|
|
}
|
|
|
|
if (p->holster_weapon)
|
|
{
|
|
sb_snum |= BIT(SK_HOLSTER);
|
|
p->weapon_pos = WEAPON_POS_LOWER;
|
|
}
|
|
else if ((uint32_t)j < MAX_WEAPONS && (p->gotweapon & (1<<j)) && (uint32_t)p->curr_weapon != j)
|
|
switch (j)
|
|
{
|
|
case PISTOL_WEAPON:
|
|
case SHOTGUN_WEAPON:
|
|
case CHAINGUN_WEAPON:
|
|
case RPG_WEAPON:
|
|
case DEVISTATOR_WEAPON:
|
|
case FREEZE_WEAPON:
|
|
case GROW_WEAPON:
|
|
case SHRINKER_WEAPON:
|
|
if (p->ammo_amount[j] == 0 && p->show_empty_weapon == 0)
|
|
{
|
|
p->last_full_weapon = p->curr_weapon;
|
|
p->show_empty_weapon = 32;
|
|
}
|
|
case KNEE_WEAPON:
|
|
P_AddWeapon(p, j, 1);
|
|
break;
|
|
case HANDREMOTE_WEAPON:
|
|
if (k >= 0) // Found in list of [1]'s
|
|
{
|
|
p->curr_weapon = j;
|
|
p->last_weapon = -1;
|
|
p->weapon_pos = WEAPON_POS_RAISE;
|
|
}
|
|
break;
|
|
case HANDBOMB_WEAPON:
|
|
case TRIPBOMB_WEAPON:
|
|
if (p->ammo_amount[j] > 0 && (p->gotweapon & (1<<j)))
|
|
P_AddWeapon(p, j, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_HOLODUKE) && p->newowner == -1)
|
|
{
|
|
if (p->holoduke_on == -1)
|
|
{
|
|
if (VM_OnEvent(EVENT_HOLODUKEON,g_player[snum].ps->i,snum, -1, 0) == 0)
|
|
{
|
|
if (p->inv_amount[GET_HOLODUKE] > 0)
|
|
{
|
|
p->inven_icon = ICON_HOLODUKE;
|
|
|
|
if (p->cursectnum > -1)
|
|
{
|
|
p->holoduke_on = i = A_InsertSprite(p->cursectnum,p->pos.x,p->pos.y,
|
|
p->pos.z+(30<<8),APLAYER,-64,0,0,p->ang,0,0,-1,10);
|
|
T4 = T5 = 0;
|
|
SP = snum;
|
|
sprite[i].extra = 0;
|
|
P_DoQuote(QUOTE_HOLODUKE_ON,p);
|
|
A_PlaySound(TELEPORTER,p->holoduke_on);
|
|
}
|
|
}
|
|
else P_DoQuote(QUOTE_HOLODUKE_NOT_FOUND,p);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (VM_OnEvent(EVENT_HOLODUKEOFF,g_player[snum].ps->i,snum, -1, 0) == 0)
|
|
{
|
|
A_PlaySound(TELEPORTER,p->holoduke_on);
|
|
p->holoduke_on = -1;
|
|
P_DoQuote(QUOTE_HOLODUKE_OFF,p);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_MEDKIT))
|
|
{
|
|
if (VM_OnEvent(EVENT_USEMEDKIT,g_player[snum].ps->i,snum, -1, 0) == 0)
|
|
{
|
|
if (p->inv_amount[GET_FIRSTAID] > 0 && sprite[p->i].extra < p->max_player_health)
|
|
{
|
|
j = p->max_player_health-sprite[p->i].extra;
|
|
|
|
if ((uint32_t)p->inv_amount[GET_FIRSTAID] > j)
|
|
{
|
|
p->inv_amount[GET_FIRSTAID] -= j;
|
|
sprite[p->i].extra = p->max_player_health;
|
|
p->inven_icon = ICON_FIRSTAID;
|
|
}
|
|
else
|
|
{
|
|
sprite[p->i].extra += p->inv_amount[GET_FIRSTAID];
|
|
p->inv_amount[GET_FIRSTAID] = 0;
|
|
P_SelectNextInvItem(p);
|
|
}
|
|
A_PlaySound(DUKE_USEMEDKIT,p->i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p->newowner == -1 && TEST_SYNC_KEY(sb_snum, SK_JETPACK))
|
|
{
|
|
if (VM_OnEvent(EVENT_USEJETPACK,g_player[snum].ps->i,snum, -1, 0) == 0)
|
|
{
|
|
if (p->inv_amount[GET_JETPACK] > 0)
|
|
{
|
|
p->jetpack_on = !p->jetpack_on;
|
|
if (p->jetpack_on)
|
|
{
|
|
p->inven_icon = ICON_JETPACK;
|
|
if (p->scream_voice > FX_Ok)
|
|
{
|
|
FX_StopSound(p->scream_voice);
|
|
p->scream_voice = -1;
|
|
}
|
|
|
|
A_PlaySound(DUKE_JETPACK_ON,p->i);
|
|
|
|
P_DoQuote(QUOTE_JETPACK_ON,p);
|
|
}
|
|
else
|
|
{
|
|
p->hard_landing = 0;
|
|
p->vel.z = 0;
|
|
A_PlaySound(DUKE_JETPACK_OFF,p->i);
|
|
S_StopEnvSound(DUKE_JETPACK_IDLE,p->i);
|
|
S_StopEnvSound(DUKE_JETPACK_ON,p->i);
|
|
P_DoQuote(QUOTE_JETPACK_OFF,p);
|
|
}
|
|
}
|
|
else P_DoQuote(QUOTE_JETPACK_NOT_FOUND,p);
|
|
}
|
|
}
|
|
|
|
if (TEST_SYNC_KEY(sb_snum, SK_TURNAROUND) && p->one_eighty_count == 0)
|
|
if (VM_OnEvent(EVENT_TURNAROUND,p->i,snum, -1, 0) == 0)
|
|
p->one_eighty_count = -1024;
|
|
}
|
|
}
|
|
|
|
int32_t A_CheckHitSprite(int32_t i, int16_t *hitsp)
|
|
{
|
|
hitdata_t hit;
|
|
int32_t zoff = 0;
|
|
|
|
if (A_CheckEnemySprite(&sprite[i]))
|
|
zoff = (42<<8);
|
|
else if (PN == APLAYER)
|
|
zoff = (39<<8);
|
|
|
|
SZ -= zoff;
|
|
hitscan((const vec3_t *)&sprite[i],SECT,
|
|
sintable[(SA+512)&2047],
|
|
sintable[SA&2047],
|
|
0,&hit,CLIPMASK1);
|
|
SZ += zoff;
|
|
|
|
if (hitsp)
|
|
*hitsp = hit.sprite;
|
|
|
|
if (hit.wall >= 0 && (wall[hit.wall].cstat&16) && A_CheckEnemySprite(&sprite[i]))
|
|
return 1<<30;
|
|
|
|
return FindDistance2D(hit.pos.x-SX,hit.pos.y-SY);
|
|
}
|
|
|
|
static int32_t P_FindWall(DukePlayer_t *p,int16_t *hitw)
|
|
{
|
|
hitdata_t hit;
|
|
|
|
hitscan((const vec3_t *)p,p->cursectnum,
|
|
sintable[(p->ang+512)&2047],
|
|
sintable[p->ang&2047],
|
|
0,&hit,CLIPMASK0);
|
|
|
|
*hitw = hit.wall;
|
|
if (hit.wall < 0)
|
|
return INT32_MAX;
|
|
|
|
return FindDistance2D(hit.pos.x-p->pos.x,hit.pos.y-p->pos.y);
|
|
}
|
|
|
|
// returns 1 if sprite i should not be considered by neartag
|
|
static int32_t our_neartag_blacklist(int32_t i)
|
|
{
|
|
return sprite[i].picnum >= SECTOREFFECTOR__STATIC && sprite[i].picnum <= GPSPEED__STATIC;
|
|
}
|
|
|
|
void P_CheckSectors(int32_t snum)
|
|
{
|
|
int32_t i = -1,oldz;
|
|
DukePlayer_t *p = g_player[snum].ps;
|
|
int16_t j,hitscanwall;
|
|
|
|
if (p->cursectnum > -1)
|
|
switch (sector[p->cursectnum].lotag)
|
|
{
|
|
|
|
case 32767:
|
|
sector[p->cursectnum].lotag = 0;
|
|
P_DoQuote(QUOTE_FOUND_SECRET,p);
|
|
p->secret_rooms++;
|
|
return;
|
|
case UINT16_MAX:
|
|
for (TRAVERSE_CONNECT(i))
|
|
g_player[i].ps->gm = MODE_EOL;
|
|
sector[p->cursectnum].lotag = 0;
|
|
if (ud.from_bonus)
|
|
{
|
|
ud.level_number = ud.from_bonus;
|
|
ud.m_level_number = ud.level_number;
|
|
ud.from_bonus = 0;
|
|
}
|
|
else
|
|
{
|
|
ud.level_number++;
|
|
if (ud.level_number > MAXLEVELS-1)
|
|
ud.level_number = 0;
|
|
ud.m_level_number = ud.level_number;
|
|
}
|
|
return;
|
|
case UINT16_MAX-1:
|
|
sector[p->cursectnum].lotag = 0;
|
|
p->timebeforeexit = GAMETICSPERSEC*8;
|
|
p->customexitsound = sector[p->cursectnum].hitag;
|
|
return;
|
|
default:
|
|
if (sector[p->cursectnum].lotag >= 10000 && sector[p->cursectnum].lotag < 16383)
|
|
{
|
|
if (snum == screenpeek || (GametypeFlags[ud.coop]&GAMETYPE_COOPSOUND))
|
|
A_PlaySound(sector[p->cursectnum].lotag-10000,p->i);
|
|
sector[p->cursectnum].lotag = 0;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
//After this point the the player effects the map with space
|
|
|
|
if (p->gm &MODE_TYPE || sprite[p->i].extra <= 0) return;
|
|
|
|
if (TEST_SYNC_KEY(g_player[snum].sync->bits, SK_OPEN))
|
|
{
|
|
if (VM_OnEvent(EVENT_USE, p->i, snum, -1, 0) != 0)
|
|
g_player[snum].sync->bits &= ~BIT(SK_OPEN);
|
|
}
|
|
|
|
if (ud.cashman && TEST_SYNC_KEY(g_player[snum].sync->bits, SK_OPEN))
|
|
A_SpawnMultiple(p->i, MONEY, 2);
|
|
|
|
if (p->newowner >= 0)
|
|
{
|
|
if (klabs(g_player[snum].sync->svel) > 768 || klabs(g_player[snum].sync->fvel) > 768)
|
|
{
|
|
i = -1;
|
|
goto CLEARCAMERAS;
|
|
}
|
|
}
|
|
|
|
if (!TEST_SYNC_KEY(g_player[snum].sync->bits, SK_OPEN) && !TEST_SYNC_KEY(g_player[snum].sync->bits, SK_ESCAPE))
|
|
p->toggle_key_flag = 0;
|
|
else if (!p->toggle_key_flag)
|
|
{
|
|
|
|
if (TEST_SYNC_KEY(g_player[snum].sync->bits, SK_ESCAPE))
|
|
{
|
|
if (p->newowner >= 0)
|
|
{
|
|
i = -1;
|
|
goto CLEARCAMERAS;
|
|
}
|
|
return;
|
|
}
|
|
|
|
neartagsprite = -1;
|
|
p->toggle_key_flag = 1;
|
|
hitscanwall = -1;
|
|
|
|
i = P_FindWall(p,&hitscanwall);
|
|
|
|
if (hitscanwall >= 0 && i < 1280 && wall[hitscanwall].overpicnum == MIRROR)
|
|
if (wall[hitscanwall].lotag > 0 && !A_CheckSoundPlaying(p->i,wall[hitscanwall].lotag) && snum == screenpeek)
|
|
{
|
|
A_PlaySound(wall[hitscanwall].lotag,p->i);
|
|
return;
|
|
}
|
|
|
|
if (hitscanwall >= 0 && (wall[hitscanwall].cstat&16))
|
|
switch (wall[hitscanwall].overpicnum)
|
|
{
|
|
default:
|
|
if (wall[hitscanwall].lotag)
|
|
return;
|
|
}
|
|
|
|
if (p->newowner >= 0)
|
|
neartag(p->opos.x,p->opos.y,p->opos.z,sprite[p->i].sectnum,p->oang,&neartagsector,
|
|
&neartagwall,&neartagsprite,&neartaghitdist, 1280, 1, our_neartag_blacklist);
|
|
else
|
|
{
|
|
neartag(p->pos.x,p->pos.y,p->pos.z,sprite[p->i].sectnum,p->oang,&neartagsector,
|
|
&neartagwall,&neartagsprite,&neartaghitdist, 1280, 1, our_neartag_blacklist);
|
|
if (neartagsprite == -1 && neartagwall == -1 && neartagsector == -1)
|
|
neartag(p->pos.x,p->pos.y,p->pos.z+(8<<8),sprite[p->i].sectnum,p->oang,&neartagsector,
|
|
&neartagwall,&neartagsprite,&neartaghitdist, 1280, 1, our_neartag_blacklist);
|
|
if (neartagsprite == -1 && neartagwall == -1 && neartagsector == -1)
|
|
neartag(p->pos.x,p->pos.y,p->pos.z+(16<<8),sprite[p->i].sectnum,p->oang,&neartagsector,
|
|
&neartagwall,&neartagsprite,&neartaghitdist, 1280, 1, our_neartag_blacklist);
|
|
if (neartagsprite == -1 && neartagwall == -1 && neartagsector == -1)
|
|
{
|
|
neartag(p->pos.x,p->pos.y,p->pos.z+(16<<8),sprite[p->i].sectnum,p->oang,&neartagsector,
|
|
&neartagwall,&neartagsprite,&neartaghitdist, 1280, 3, our_neartag_blacklist);
|
|
if (neartagsprite >= 0)
|
|
{
|
|
switch (DYNAMICTILEMAP(sprite[neartagsprite].picnum))
|
|
{
|
|
case FEM1__STATIC:
|
|
case FEM2__STATIC:
|
|
case FEM3__STATIC:
|
|
case FEM4__STATIC:
|
|
case FEM5__STATIC:
|
|
case FEM6__STATIC:
|
|
case FEM7__STATIC:
|
|
case FEM8__STATIC:
|
|
case FEM9__STATIC:
|
|
case FEM10__STATIC:
|
|
case PODFEM1__STATIC:
|
|
case NAKED1__STATIC:
|
|
case STATUE__STATIC:
|
|
case TOUGHGAL__STATIC:
|
|
return;
|
|
}
|
|
}
|
|
|
|
neartagsprite = -1;
|
|
neartagwall = -1;
|
|
neartagsector = -1;
|
|
}
|
|
}
|
|
|
|
if (p->newowner == -1 && neartagsprite == -1 && neartagsector == -1 && neartagwall == -1)
|
|
if (isanunderoperator(sector[sprite[p->i].sectnum].lotag))
|
|
neartagsector = sprite[p->i].sectnum;
|
|
|
|
if (neartagsector >= 0 && (sector[neartagsector].lotag&16384))
|
|
return;
|
|
|
|
if (neartagsprite == -1 && neartagwall == -1)
|
|
if (p->cursectnum >= 0 && sector[p->cursectnum].lotag == 2)
|
|
{
|
|
oldz = A_CheckHitSprite(p->i,&neartagsprite);
|
|
if (oldz > 1280) neartagsprite = -1;
|
|
}
|
|
|
|
if (neartagsprite >= 0)
|
|
{
|
|
if (P_ActivateSwitch(snum,neartagsprite,1)) return;
|
|
|
|
switch (DYNAMICTILEMAP(sprite[neartagsprite].picnum))
|
|
{
|
|
case TOILET__STATIC:
|
|
case STALL__STATIC:
|
|
if (p->last_pissed_time == 0)
|
|
{
|
|
if (ud.lockout == 0) A_PlaySound(DUKE_URINATE,p->i);
|
|
|
|
p->last_pissed_time = GAMETICSPERSEC*220;
|
|
p->transporter_hold = 29*2;
|
|
if (p->holster_weapon == 0)
|
|
{
|
|
p->holster_weapon = 1;
|
|
p->weapon_pos = -1;
|
|
}
|
|
if (sprite[p->i].extra <= (p->max_player_health-(p->max_player_health/10)))
|
|
{
|
|
sprite[p->i].extra += p->max_player_health/10;
|
|
p->last_extra = sprite[p->i].extra;
|
|
}
|
|
else if (sprite[p->i].extra < p->max_player_health)
|
|
sprite[p->i].extra = p->max_player_health;
|
|
}
|
|
else if (!A_CheckSoundPlaying(neartagsprite,FLUSH_TOILET))
|
|
A_PlaySound(FLUSH_TOILET,neartagsprite);
|
|
return;
|
|
|
|
case NUKEBUTTON__STATIC:
|
|
P_FindWall(p,&j);
|
|
if (j >= 0 && wall[j].overpicnum == 0)
|
|
if (actor[neartagsprite].t_data[0] == 0)
|
|
{
|
|
if (ud.noexits && (g_netServer || ud.multimode > 1))
|
|
{
|
|
// NUKEBUTTON frags the player
|
|
actor[p->i].picnum = NUKEBUTTON;
|
|
actor[p->i].extra = 250;
|
|
}
|
|
else
|
|
{
|
|
actor[neartagsprite].t_data[0] = 1;
|
|
sprite[neartagsprite].owner = p->i;
|
|
ud.secretlevel =
|
|
(p->buttonpalette = sprite[neartagsprite].pal) ? sprite[neartagsprite].lotag : 0;
|
|
}
|
|
}
|
|
return;
|
|
|
|
case WATERFOUNTAIN__STATIC:
|
|
if (actor[neartagsprite].t_data[0] != 1)
|
|
{
|
|
actor[neartagsprite].t_data[0] = 1;
|
|
sprite[neartagsprite].owner = p->i;
|
|
|
|
if (sprite[p->i].extra < p->max_player_health)
|
|
{
|
|
sprite[p->i].extra++;
|
|
A_PlaySound(DUKE_DRINKING,p->i);
|
|
}
|
|
}
|
|
return;
|
|
|
|
case PLUG__STATIC:
|
|
A_PlaySound(SHORT_CIRCUIT,p->i);
|
|
sprite[p->i].extra -= 2+(krand()&3);
|
|
|
|
P_PalFrom(p, 32, 48,48,64);
|
|
break;
|
|
|
|
case VIEWSCREEN__STATIC:
|
|
case VIEWSCREEN2__STATIC:
|
|
{
|
|
// Try to find a camera sprite for the viewscreen.
|
|
for (SPRITES_OF(STAT_ACTOR, i))
|
|
{
|
|
if (PN == CAMERA1 && SP == 0 && sprite[neartagsprite].hitag == SLT)
|
|
{
|
|
SP = 1; //Using this camera
|
|
A_PlaySound(MONITOR_ACTIVE,p->i);
|
|
|
|
sprite[neartagsprite].owner = i;
|
|
sprite[neartagsprite].yvel = 1;
|
|
|
|
|
|
j = p->cursectnum;
|
|
p->cursectnum = SECT;
|
|
P_UpdateScreenPal(p);
|
|
p->cursectnum = j;
|
|
|
|
// parallaxtype = 2;
|
|
p->newowner = i;
|
|
|
|
P_UpdatePosWhenViewingCam(p);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
CLEARCAMERAS:
|
|
|
|
if (i < 0)
|
|
G_ClearCameraView(p);
|
|
else if (p->newowner >= 0)
|
|
p->newowner = -1;
|
|
|
|
if (I_EscapeTrigger())
|
|
I_EscapeTriggerClear();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (TEST_SYNC_KEY(g_player[snum].sync->bits, SK_OPEN) == 0) return;
|
|
else if (p->newowner >= 0)
|
|
{
|
|
i = -1;
|
|
goto CLEARCAMERAS;
|
|
}
|
|
|
|
if (neartagwall == -1 && neartagsector == -1 && neartagsprite == -1)
|
|
if (klabs(A_GetHitscanRange(p->i)) < 512)
|
|
{
|
|
if ((krand()&255) < 16)
|
|
A_PlaySound(DUKE_SEARCH2,p->i);
|
|
else A_PlaySound(DUKE_SEARCH,p->i);
|
|
return;
|
|
}
|
|
|
|
if (neartagwall >= 0)
|
|
{
|
|
if (wall[neartagwall].lotag > 0 && CheckDoorTile(wall[neartagwall].picnum))
|
|
{
|
|
if (hitscanwall == neartagwall || hitscanwall == -1)
|
|
P_ActivateSwitch(snum,neartagwall,0);
|
|
return;
|
|
}
|
|
else if (p->newowner >= 0)
|
|
{
|
|
i = -1;
|
|
goto CLEARCAMERAS;
|
|
}
|
|
}
|
|
|
|
if (neartagsector >= 0 && (sector[neartagsector].lotag&16384) == 0 && isanearoperator(sector[neartagsector].lotag))
|
|
{
|
|
i = headspritesect[neartagsector];
|
|
while (i >= 0)
|
|
{
|
|
if (PN == ACTIVATOR || PN == MASTERSWITCH)
|
|
return;
|
|
i = nextspritesect[i];
|
|
}
|
|
G_OperateSectors(neartagsector,p->i);
|
|
}
|
|
else if ((sector[sprite[p->i].sectnum].lotag&16384) == 0)
|
|
{
|
|
if (isanunderoperator(sector[sprite[p->i].sectnum].lotag))
|
|
{
|
|
i = headspritesect[sprite[p->i].sectnum];
|
|
while (i >= 0)
|
|
{
|
|
if (PN == ACTIVATOR || PN == MASTERSWITCH) return;
|
|
i = nextspritesect[i];
|
|
}
|
|
G_OperateSectors(sprite[p->i].sectnum,p->i);
|
|
}
|
|
else P_ActivateSwitch(snum,neartagwall,0);
|
|
}
|
|
}
|
|
}
|
|
|