p_sight.c (4774B)
1 #include "doomdef.h" 2 3 #include "i_system.h" 4 #include "p_local.h" 5 6 7 #include "r_state.h" 8 9 10 11 12 fixed_t sightzstart; 13 fixed_t topslope; 14 fixed_t bottomslope; 15 16 divline_t strace; 17 fixed_t t2x; 18 fixed_t t2y; 19 20 int sightcounts[2]; 21 22 23 24 25 26 27 int 28 P_DivlineSide 29 ( fixed_t x, 30 fixed_t y, 31 divline_t* node ) 32 { 33 fixed_t dx; 34 fixed_t dy; 35 fixed_t left; 36 fixed_t right; 37 38 if (!node->dx) 39 { 40 if (x==node->x) 41 return 2; 42 43 if (x <= node->x) 44 return node->dy > 0; 45 46 return node->dy < 0; 47 } 48 49 if (!node->dy) 50 { 51 if (x==node->y) 52 return 2; 53 54 if (y <= node->y) 55 return node->dx < 0; 56 57 return node->dx > 0; 58 } 59 60 dx = (x - node->x); 61 dy = (y - node->y); 62 63 left = (node->dy>>FRACBITS) * (dx>>FRACBITS); 64 right = (dy>>FRACBITS) * (node->dx>>FRACBITS); 65 66 if (right < left) 67 return 0; 68 69 if (left == right) 70 return 2; 71 return 1; 72 } 73 74 75 76 77 78 79 80 81 fixed_t 82 P_InterceptVector2 83 ( divline_t* v2, 84 divline_t* v1 ) 85 { 86 fixed_t frac; 87 fixed_t num; 88 fixed_t den; 89 90 den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); 91 92 if (den == 0) 93 return 0; 94 95 96 num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + 97 FixedMul ( (v2->y - v1->y)>>8 , v1->dx); 98 frac = FixedDiv (num , den); 99 100 return frac; 101 } 102 103 104 105 106 107 108 boolean P_CrossSubsector (int num) 109 { 110 seg_t* seg; 111 line_t* line; 112 int s1; 113 int s2; 114 int count; 115 subsector_t* sub; 116 sector_t* front; 117 sector_t* back; 118 fixed_t opentop; 119 fixed_t openbottom; 120 divline_t divl; 121 vertex_t* v1; 122 vertex_t* v2; 123 fixed_t frac; 124 fixed_t slope; 125 126 #ifdef RANGECHECK 127 if (num>=numsubsectors) 128 I_Error ("P_CrossSubsector: ss %i with numss = %i", 129 num, 130 numsubsectors); 131 #endif 132 133 sub = &subsectors[num]; 134 135 136 count = sub->numlines; 137 seg = &segs[sub->firstline]; 138 139 for ( ; count ; seg++, count--) 140 { 141 line = seg->linedef; 142 143 144 if (line->validcount == validcount) 145 continue; 146 147 line->validcount = validcount; 148 149 v1 = line->v1; 150 v2 = line->v2; 151 s1 = P_DivlineSide (v1->x,v1->y, &strace); 152 s2 = P_DivlineSide (v2->x, v2->y, &strace); 153 154 155 if (s1 == s2) 156 continue; 157 158 divl.x = v1->x; 159 divl.y = v1->y; 160 divl.dx = v2->x - v1->x; 161 divl.dy = v2->y - v1->y; 162 s1 = P_DivlineSide (strace.x, strace.y, &divl); 163 s2 = P_DivlineSide (t2x, t2y, &divl); 164 165 166 if (s1 == s2) 167 continue; 168 169 170 171 if ( !(line->flags & ML_TWOSIDED) ) 172 return false; 173 174 175 front = seg->frontsector; 176 back = seg->backsector; 177 178 179 if (front->floorheight == back->floorheight 180 && front->ceilingheight == back->ceilingheight) 181 continue; 182 183 184 185 if (front->ceilingheight < back->ceilingheight) 186 opentop = front->ceilingheight; 187 else 188 opentop = back->ceilingheight; 189 190 191 if (front->floorheight > back->floorheight) 192 openbottom = front->floorheight; 193 else 194 openbottom = back->floorheight; 195 196 197 if (openbottom >= opentop) 198 return false; 199 200 frac = P_InterceptVector2 (&strace, &divl); 201 202 if (front->floorheight != back->floorheight) 203 { 204 slope = FixedDiv (openbottom - sightzstart , frac); 205 if (slope > bottomslope) 206 bottomslope = slope; 207 } 208 209 if (front->ceilingheight != back->ceilingheight) 210 { 211 slope = FixedDiv (opentop - sightzstart , frac); 212 if (slope < topslope) 213 topslope = slope; 214 } 215 216 if (topslope <= bottomslope) 217 return false; 218 } 219 220 return true; 221 } 222 223 224 225 226 227 228 229 230 boolean P_CrossBSPNode (int bspnum) 231 { 232 node_t* bsp; 233 int side; 234 235 if (bspnum & NF_SUBSECTOR) 236 { 237 if (bspnum == -1) 238 return P_CrossSubsector (0); 239 else 240 return P_CrossSubsector (bspnum&(~NF_SUBSECTOR)); 241 } 242 243 bsp = &nodes[bspnum]; 244 245 246 side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp); 247 if (side == 2) 248 side = 0; 249 250 251 if (!P_CrossBSPNode (bsp->children[side]) ) 252 return false; 253 254 255 if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp)) 256 { 257 258 return true; 259 } 260 261 262 return P_CrossBSPNode (bsp->children[side^1]); 263 } 264 265 266 267 268 269 270 271 272 boolean 273 P_CheckSight 274 ( mobj_t* t1, 275 mobj_t* t2 ) 276 { 277 int s1; 278 int s2; 279 int pnum; 280 int bytenum; 281 int bitnum; 282 283 284 285 286 s1 = (t1->subsector->sector - sectors); 287 s2 = (t2->subsector->sector - sectors); 288 pnum = s1*numsectors + s2; 289 bytenum = pnum>>3; 290 bitnum = 1 << (pnum&7); 291 292 293 if (rejectmatrix[bytenum]&bitnum) 294 { 295 sightcounts[0]++; 296 297 298 return false; 299 } 300 301 302 303 sightcounts[1]++; 304 305 validcount++; 306 307 sightzstart = t1->z + t1->height - (t1->height>>2); 308 topslope = (t2->z+t2->height) - sightzstart; 309 bottomslope = (t2->z) - sightzstart; 310 311 strace.x = t1->x; 312 strace.y = t1->y; 313 t2x = t2->x; 314 t2y = t2->y; 315 strace.dx = t2->x - t1->x; 316 strace.dy = t2->y - t1->y; 317 318 319 return P_CrossBSPNode (numnodes-1); 320 } 321 322