1 line
5.8 KiB
C++
1 line
5.8 KiB
C++
#include "doomdef.h"
|
|
#include "p_local.h"
|
|
|
|
/*
|
|
==============================================================================
|
|
|
|
P_CheckSight
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
fixed_t sightzstart; // eye z of looker
|
|
fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
|
|
|
divline_t strace; // from t1 to t2
|
|
fixed_t t2x, t2y;
|
|
|
|
int sightcounts[2];
|
|
|
|
/*
|
|
===============================================================================
|
|
=
|
|
= P_DivlineSide
|
|
=
|
|
= Returns side 0 (front), 1 (back), or 2 (on)
|
|
===============================================================================
|
|
*/
|
|
|
|
int P_DivlineSide (fixed_t x, fixed_t y, divline_t *node)
|
|
{
|
|
fixed_t dx,dy;
|
|
fixed_t left, right;
|
|
|
|
if (!node->dx)
|
|
{
|
|
if (x==node->x)
|
|
return 2;
|
|
if (x <= node->x)
|
|
return node->dy > 0;
|
|
return node->dy < 0;
|
|
}
|
|
if (!node->dy)
|
|
{
|
|
if (x==node->y)
|
|
return 2;
|
|
if (y <= node->y)
|
|
return node->dx < 0;
|
|
return node->dx > 0;
|
|
}
|
|
|
|
dx = (x - node->x);
|
|
dy = (y - node->y);
|
|
|
|
left = (node->dy>>FRACBITS) * (dx>>FRACBITS);
|
|
right = (dy>>FRACBITS) * (node->dx>>FRACBITS);
|
|
|
|
if (right < left)
|
|
return 0; // front side
|
|
if (left == right)
|
|
return 2;
|
|
return 1; // back side
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= P_InterceptVector2
|
|
=
|
|
= Returns the fractional intercept point along the first divline
|
|
=
|
|
= This is only called by the addthings and addlines traversers
|
|
===============
|
|
*/
|
|
|
|
fixed_t P_InterceptVector2 (divline_t *v2, divline_t *v1)
|
|
{
|
|
fixed_t frac, num, den;
|
|
|
|
den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
|
|
if (den == 0)
|
|
return 0;
|
|
// I_Error ("P_InterceptVector: parallel");
|
|
num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) +
|
|
FixedMul ( (v2->y - v1->y)>>8 , v1->dx);
|
|
frac = FixedDiv (num , den);
|
|
|
|
return frac;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= P_CrossSubsector
|
|
=
|
|
= Returns true if strace crosses the given subsector successfuly
|
|
=================
|
|
*/
|
|
|
|
boolean P_CrossSubsector (int num)
|
|
{
|
|
seg_t *seg;
|
|
line_t *line;
|
|
int s1, s2;
|
|
int count;
|
|
subsector_t *sub;
|
|
sector_t *front, *back;
|
|
fixed_t opentop, openbottom;
|
|
divline_t divl;
|
|
vertex_t *v1, *v2;
|
|
fixed_t frac, slope;
|
|
|
|
#ifdef RANGECHECK
|
|
if (num>=numsubsectors)
|
|
I_Error ("P_CrossSubsector: ss %i with numss = %i",num, numsubsectors);
|
|
#endif
|
|
|
|
sub = &subsectors[num];
|
|
|
|
//
|
|
// check lines
|
|
//
|
|
count = sub->numlines;
|
|
seg = &segs[sub->firstline];
|
|
|
|
for ( ; count ; seg++, count--)
|
|
{
|
|
line = seg->linedef;
|
|
if (line->validcount == validcount)
|
|
continue; // allready checked other side
|
|
line->validcount = validcount;
|
|
|
|
v1 = line->v1;
|
|
v2 = line->v2;
|
|
s1 = P_DivlineSide (v1->x,v1->y, &strace);
|
|
s2 = P_DivlineSide (v2->x, v2->y, &strace);
|
|
if (s1 == s2)
|
|
continue; // line isn't crossed
|
|
divl.x = v1->x;
|
|
divl.y = v1->y;
|
|
divl.dx = v2->x - v1->x;
|
|
divl.dy = v2->y - v1->y;
|
|
s1 = P_DivlineSide (strace.x, strace.y, &divl);
|
|
s2 = P_DivlineSide (t2x, t2y, &divl);
|
|
if (s1 == s2)
|
|
continue; // line isn't crossed
|
|
|
|
if ( !(line->flags & ML_TWOSIDED) )
|
|
return false; // stop
|
|
|
|
//
|
|
// crosses a two sided line
|
|
//
|
|
|
|
front = seg->frontsector;
|
|
back = seg->backsector;
|
|
|
|
if (front->floorheight == back->floorheight
|
|
&& front->ceilingheight == back->ceilingheight)
|
|
continue; // no wall to block sight with
|
|
|
|
if (front->ceilingheight < back->ceilingheight)
|
|
opentop = front->ceilingheight;
|
|
else
|
|
opentop = back->ceilingheight;
|
|
if (front->floorheight > back->floorheight)
|
|
openbottom = front->floorheight;
|
|
else
|
|
openbottom = back->floorheight;
|
|
|
|
if (openbottom >= opentop) // quick test for totally closed doors
|
|
return false; // stop
|
|
|
|
frac = P_InterceptVector2 (&strace, &divl);
|
|
|
|
if (front->floorheight != back->floorheight)
|
|
{
|
|
slope = FixedDiv (openbottom - sightzstart , frac);
|
|
if (slope > bottomslope)
|
|
bottomslope = slope;
|
|
}
|
|
|
|
if (front->ceilingheight != back->ceilingheight)
|
|
{
|
|
slope = FixedDiv (opentop - sightzstart , frac);
|
|
if (slope < topslope)
|
|
topslope = slope;
|
|
}
|
|
|
|
if (topslope <= bottomslope)
|
|
return false; // stop
|
|
}
|
|
|
|
|
|
return true; // passed the subsector ok
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= P_CrossBSPNode
|
|
=
|
|
= Returns true if strace crosses the given node successfuly
|
|
=================
|
|
*/
|
|
|
|
boolean P_CrossBSPNode (int bspnum)
|
|
{
|
|
node_t *bsp;
|
|
int side;
|
|
|
|
if (bspnum & NF_SUBSECTOR)
|
|
{
|
|
if (bspnum == -1)
|
|
return P_CrossSubsector (0);
|
|
else
|
|
return P_CrossSubsector (bspnum&(~NF_SUBSECTOR));
|
|
}
|
|
|
|
bsp = &nodes[bspnum];
|
|
|
|
//
|
|
// decide which side the start point is on
|
|
//
|
|
side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp);
|
|
if (side == 2)
|
|
side = 0; // an "on" should cross both sides
|
|
|
|
// cross the starting side
|
|
|
|
if (!P_CrossBSPNode (bsp->children[side]) )
|
|
return false;
|
|
|
|
// the partition plane is crossed here
|
|
|
|
if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp))
|
|
return true; // the line doesn't touch the other side
|
|
|
|
// cross the ending side
|
|
return P_CrossBSPNode (bsp->children[side^1]);
|
|
}
|
|
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= P_CheckSight
|
|
=
|
|
= Returns true if a straight line between t1 and t2 is unobstructed
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
boolean P_CheckSight (mobj_t *t1, mobj_t *t2)
|
|
{
|
|
int s1, s2;
|
|
int pnum, bytenum, bitnum;
|
|
|
|
//
|
|
// check for trivial rejection
|
|
//
|
|
s1 = (t1->subsector->sector - sectors);
|
|
s2 = (t2->subsector->sector - sectors);
|
|
pnum = s1*numsectors + s2;
|
|
bytenum = pnum>>3;
|
|
bitnum = 1 << (pnum&7);
|
|
|
|
if (rejectmatrix[bytenum]&bitnum)
|
|
{
|
|
sightcounts[0]++;
|
|
return false; // can't possibly be connected
|
|
}
|
|
|
|
// look from eyes of t1 to any part of t2
|
|
sightcounts[1]++;
|
|
|
|
validcount++;
|
|
|
|
sightzstart = t1->z + t1->height - (t1->height>>2);
|
|
topslope = (t2->z+t2->height) - sightzstart;
|
|
bottomslope = (t2->z) - sightzstart;
|
|
|
|
strace.x = t1->x;
|
|
strace.y = t1->y;
|
|
t2x = t2->x;
|
|
t2y = t2->y;
|
|
strace.dx = t2->x - t1->x;
|
|
strace.dy = t2->y - t1->y;
|
|
|
|
return P_CrossBSPNode (numnodes-1); // the head node is the last node output
|
|
}
|
|
|
|
|