DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

p_sight.c (6483B)


      1 #include "doomdef.h"
      2 #include "p_local.h"
      3 
      4 fixed_t sightzstart;            //800A5F20 // eye z of looker
      5 fixed_t topslope, bottomslope;	//800A5F24 ,800A5F28 // slopes to top and bottom of target
      6 
      7 divline_t strace;				//800A5F30 // from t1 to t2
      8 fixed_t t2x, t2y;				//800A5F40, 800A5F44
      9 
     10 int t1xs,t1ys,t2xs,t2ys;        //800A5F48,800A5F4C,800A5F50,800A5F54
     11 
     12 
     13 /*
     14 ===============
     15 =
     16 = P_CheckSights
     17 =
     18 = Check sights of all mobj thinkers that are going to change state this
     19 = tic and have MF_COUNTKILL set
     20 ===============
     21 */
     22 
     23 void P_CheckSights(void) // 8001EB00
     24 {
     25 	mobj_t *mobj;
     26 
     27 	for (mobj = mobjhead.next; mobj != &mobjhead; mobj = mobj->next)
     28 	{
     29 		// must be killable
     30 		if (!(mobj->flags & MF_COUNTKILL))
     31 			continue;
     32 
     33 		// must be about to change states
     34 		if (mobj->tics != 1)
     35 			continue;
     36 
     37 		mobj->flags &= ~MF_SEETARGET;
     38 
     39 		// must have a target
     40 		if (!mobj->target)
     41 			continue;
     42 
     43 		if (P_CheckSight(mobj, mobj->target))
     44 			mobj->flags |= MF_SEETARGET;
     45 	}
     46 }
     47 
     48 
     49 /**********************************
     50 
     51 Returns true if a straight line between t1 and t2 is unobstructed
     52 
     53 **********************************/
     54 
     55 boolean P_CheckSight(mobj_t *t1, mobj_t *t2) // 8001EBCC
     56 {
     57 	int	s1, s2;
     58 	int	pnum, bytenum, bitnum;
     59 
     60 	//
     61 	// check for trivial rejection
     62 	//
     63 	s1 = (t1->subsector->sector - sectors);
     64 	s2 = (t2->subsector->sector - sectors);
     65 	pnum = s1*numsectors + s2;
     66 	bytenum = pnum >> 3;
     67 	bitnum = 1 << (pnum & 7);
     68 
     69 	if (rejectmatrix[bytenum] & bitnum) {
     70 		return false;	// can't possibly be connected
     71 	}
     72 
     73 	// look from eyes of t1 to any part of t2
     74 
     75 	++validcount;
     76 
     77 	// make sure it never lies exactly on a vertex coordinate
     78 
     79 	strace.x = (t1->x & ~0x1ffff) | 0x10000;
     80 	strace.y = (t1->y & ~0x1ffff) | 0x10000;
     81 	t2x = (t2->x & ~0x1ffff) | 0x10000;
     82 	t2y = (t2->y & ~0x1ffff) | 0x10000;
     83 	strace.dx = t2x - strace.x;
     84 	strace.dy = t2y - strace.y;
     85 
     86 	t1xs = strace.x >> FRACBITS;
     87 	t1ys = strace.y >> FRACBITS;
     88 	t2xs = t2x >> FRACBITS;
     89 	t2ys = t2y >> FRACBITS;
     90 
     91 	sightzstart = (t1->z + t1->height) - (t1->height >> 2);
     92 	topslope = (t2->z + t2->height) - sightzstart;
     93 	bottomslope = (t2->z) - sightzstart;
     94 
     95 	return PS_CrossBSPNode(numnodes - 1);
     96 }
     97 
     98 /*
     99 =================
    100 =
    101 = PS_SightCrossLine
    102 =
    103 = First checks the endpoints of the line to make sure that they cross the
    104 = sight trace treated as an infinite line.
    105 =
    106 = If so, it calculates the fractional distance along the sight trace that
    107 = the intersection occurs at.  If 0 < intercept < 1.0, the line will block
    108 = the sight.
    109 =================
    110 */
    111 
    112 fixed_t PS_SightCrossLine (line_t *line) // 8001EDD8
    113 {
    114 	int			s1, s2;
    115 	int			p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y,dx,dy,ndx,ndy;
    116 
    117 	// p1, p2 are line endpoints
    118 	p1x = line->v1->x >> FRACBITS;
    119 	p1y = line->v1->y >> FRACBITS;
    120 	p2x = line->v2->x >> FRACBITS;
    121 	p2y = line->v2->y >> FRACBITS;
    122 
    123 	// p3, p4 are sight endpoints
    124 	p3x = t1xs;
    125 	p3y = t1ys;
    126 	p4x = t2xs;
    127 	p4y = t2ys;
    128 
    129 	dx = p2x - p3x;
    130 	dy = p2y - p3y;
    131 
    132 	ndx = p4x - p3x;		// this can be precomputed if worthwhile
    133 	ndy = p4y - p3y;
    134 
    135 	s1 =  (ndy * dx) <  (dy * ndx);
    136 
    137 	dx = p1x - p3x;
    138 	dy = p1y - p3y;
    139 
    140 	s2 =  (ndy * dx) <  (dy * ndx);
    141 
    142 	if (s1 == s2)
    143 		return -1;			// line isn't crossed
    144 
    145 	ndx = p1y - p2y;		// vector normal to world line
    146 	ndy = p2x - p1x;
    147 
    148 	s1 = ndx*dx + ndy*dy;	// distance projected onto normal
    149 
    150 	dx = p4x - p1x;
    151 	dy = p4y - p1y;
    152 
    153 	s2 = ndx*dx + ndy*dy;	// distance projected onto normal
    154 
    155 	s2 = FixedDiv(s1,(s1+s2));
    156 
    157 	return s2;
    158 }
    159 
    160 /*
    161 =================
    162 =
    163 = PS_CrossSubsector
    164 =
    165 = Returns true if strace crosses the given subsector successfuly
    166 =================
    167 */
    168 
    169 boolean PS_CrossSubsector(subsector_t *sub) // 8001EF10
    170 {
    171 	seg_t		*seg;
    172 	line_t		*line;
    173 	int			count;
    174 	sector_t	*front, *back;
    175 	fixed_t		opentop, openbottom;
    176 	fixed_t		frac, slope;
    177 
    178 	//
    179 	// check lines
    180 	//
    181 	count = sub->numlines;
    182 	seg = &segs[sub->firstline];
    183 
    184 	for ( ; count ; seg++, count--)
    185 	{
    186 		line = seg->linedef;
    187 
    188 		if (line->validcount == validcount)
    189 			continue;		// allready checked other side
    190 		line->validcount = validcount;
    191 
    192 		frac = PS_SightCrossLine (line);
    193 
    194 		if (frac < 4 || frac >= (FRACUNIT+1))
    195 			continue;
    196 
    197 		//
    198 		// crosses line
    199 		//
    200 		back = line->backsector;
    201 		if (!back)
    202 			return false;	// one sided line
    203 		front = line->frontsector;
    204 
    205 		if (front->floorheight == back->floorheight
    206 		&& front->ceilingheight == back->ceilingheight)
    207 			continue;		// no wall to block sight with
    208 
    209 		if (front->ceilingheight < back->ceilingheight)
    210 			opentop = front->ceilingheight;
    211 		else
    212 			opentop = back->ceilingheight;
    213 		if (front->floorheight > back->floorheight)
    214 			openbottom = front->floorheight;
    215 		else
    216 			openbottom = back->floorheight;
    217 
    218 		if (openbottom >= opentop)	// quick test for totally closed doors
    219 			return false;	// stop
    220 
    221 		frac >>= 2;
    222 
    223 		if (front->floorheight != back->floorheight)
    224 		{
    225 			slope =  (((openbottom - sightzstart)<<6) / frac) << 8;
    226 			if (slope > bottomslope)
    227 				bottomslope = slope;
    228 		}
    229 
    230 		if (front->ceilingheight != back->ceilingheight)
    231 		{
    232 			slope = (((opentop - sightzstart)<<6) / frac) << 8;
    233 			if (slope < topslope)
    234 				topslope = slope;
    235 		}
    236 
    237 		if (topslope <= bottomslope)
    238 			return false;	// stop
    239 	}
    240 
    241 	return true;			// passed the subsector ok
    242 }
    243 
    244 /*
    245 =================
    246 =
    247 = PS_CrossBSPNode
    248 =
    249 = Returns true if strace crosses the given node successfuly
    250 =================
    251 */
    252 
    253 boolean PS_CrossBSPNode(int bspnum) // 8001F15C
    254 {
    255 	node_t  *bsp;
    256 	int     side1, side2;
    257 	int     bsp_num;
    258 	fixed_t dx, dy;
    259     fixed_t left, right;
    260 
    261 	if (bspnum & NF_SUBSECTOR)
    262 	{
    263 		bsp_num = (bspnum & ~NF_SUBSECTOR);
    264 		if (bsp_num >= numsubsectors)
    265 		{
    266 			I_Error("PS_CrossSubsector: ss %i with numss = %i", bsp_num, numsubsectors);
    267 		}
    268 
    269 		return PS_CrossSubsector(&subsectors[bsp_num]);
    270 	}
    271 
    272 	bsp = &nodes[bspnum];
    273 
    274 	// decide which side the start point is on
    275     side1 = 1;
    276 
    277     dx = (strace.x - bsp->line.x);
    278     dy = (strace.y - bsp->line.y);
    279 
    280     left  = (bsp->line.dy>>FRACBITS) * (dx>>FRACBITS);
    281     right = (dy>>FRACBITS) * (bsp->line.dx>>FRACBITS);
    282 
    283     if(right < left)
    284         side1 = 0;    // front side
    285 
    286 	// cross the starting side
    287 	if (!PS_CrossBSPNode(bsp->children[side1]))
    288 		return false;
    289 
    290 	// the partition plane is crossed here
    291 	side2 = 1;
    292 
    293     dx = (t2x - bsp->line.x);
    294     dy = (t2y - bsp->line.y);
    295 
    296     left  = (bsp->line.dy>>FRACBITS) * (dx>>FRACBITS);
    297     right = (dy>>FRACBITS) * (bsp->line.dx>>FRACBITS);
    298 
    299     if(right < left)
    300         side2 = 0;    // front side
    301 
    302 	if (side1 == side2)
    303 		return true; // the line doesn't touch the other side
    304 
    305 	// cross the ending side
    306 	return PS_CrossBSPNode(bsp->children[side1 ^ 1]);
    307 }