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 }