|
|
1.1 root 1: 1.1.1.3 ! root 2: //************************************************************************** ! 3: //** ! 4: //** p_maputl.c : Heretic 2 : Raven Software, Corp. ! 5: //** ! 6: //** $RCSfile: p_maputl.c,v $ ! 7: //** $Revision: 1.11 $ ! 8: //** $Date: 95/10/04 02:39:28 $ ! 9: //** $Author: paul $ ! 10: //** ! 11: //************************************************************************** 1.1 root 12: 1.1.1.3 ! root 13: #include "h2def.h" ! 14: #include "p_local.h" 1.1 root 15: 1.1.1.3 ! root 16: static mobj_t *RoughBlockCheck(mobj_t *mo, int index); 1.1 root 17: 18: /* 19: =================== 20: = 21: = P_AproxDistance 22: = 23: = Gives an estimation of distance (not exact) 24: = 25: =================== 26: */ 27: 28: fixed_t P_AproxDistance (fixed_t dx, fixed_t dy) 29: { 30: dx = abs(dx); 31: dy = abs(dy); 32: if (dx < dy) 33: return dx+dy-(dx>>1); 34: return dx+dy-(dy>>1); 35: } 36: 37: 38: /* 39: ================== 40: = 41: = P_PointOnLineSide 42: = 43: = Returns 0 or 1 44: ================== 45: */ 46: 47: int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line) 48: { 1.1.1.3 ! root 49: fixed_t dx,dy; ! 50: fixed_t left, right; ! 51: 1.1 root 52: if (!line->dx) 53: { 54: if (x <= line->v1->x) 55: return line->dy > 0; 56: return line->dy < 0; 57: } 58: if (!line->dy) 59: { 60: if (y <= line->v1->y) 61: return line->dx < 0; 62: return line->dx > 0; 63: } 1.1.1.3 ! root 64: 1.1 root 65: dx = (x - line->v1->x); 66: dy = (y - line->v1->y); 1.1.1.3 ! root 67: 1.1.1.2 root 68: left = FixedMul ( line->dy>>FRACBITS , dx ); 69: right = FixedMul ( dy , line->dx>>FRACBITS ); 1.1.1.3 ! root 70: 1.1 root 71: if (right < left) 1.1.1.3 ! root 72: return 0; // front side ! 73: return 1; // back side 1.1 root 74: } 75: 76: 77: /* 1.1.1.2 root 78: ================= 79: = 80: = P_BoxOnLineSide 81: = 82: = Considers the line to be infinite 83: = Returns side 0 or 1, -1 if box crosses the line 84: ================= 85: */ 86: 87: int P_BoxOnLineSide (fixed_t *tmbox, line_t *ld) 88: { 1.1.1.3 ! root 89: int p1, p2; ! 90: 1.1.1.2 root 91: switch (ld->slopetype) 92: { 93: case ST_HORIZONTAL: 94: p1 = tmbox[BOXTOP] > ld->v1->y; 95: p2 = tmbox[BOXBOTTOM] > ld->v1->y; 96: if (ld->dx < 0) 97: { 98: p1 ^= 1; 99: p2 ^= 1; 100: } 101: break; 102: case ST_VERTICAL: 103: p1 = tmbox[BOXRIGHT] < ld->v1->x; 104: p2 = tmbox[BOXLEFT] < ld->v1->x; 105: if (ld->dy < 0) 106: { 107: p1 ^= 1; 108: p2 ^= 1; 109: } 110: break; 111: case ST_POSITIVE: 112: p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld); 113: p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); 114: break; 115: case ST_NEGATIVE: 116: p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld); 117: p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); 118: break; 119: } 120: 121: if (p1 == p2) 122: return p1; 123: return -1; 124: } 125: 126: /* 1.1 root 127: ================== 128: = 129: = P_PointOnDivlineSide 130: = 131: = Returns 0 or 1 132: ================== 133: */ 134: 135: int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line) 136: { 1.1.1.3 ! root 137: fixed_t dx,dy; ! 138: fixed_t left, right; ! 139: 1.1 root 140: if (!line->dx) 141: { 142: if (x <= line->x) 143: return line->dy > 0; 144: return line->dy < 0; 145: } 146: if (!line->dy) 147: { 148: if (y <= line->y) 149: return line->dx < 0; 150: return line->dx > 0; 151: } 1.1.1.3 ! root 152: 1.1 root 153: dx = (x - line->x); 154: dy = (y - line->y); 1.1.1.3 ! root 155: 1.1.1.2 root 156: // try to quickly decide by looking at sign bits 1.1 root 157: if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) 158: { 159: if ( (line->dy ^ dx) & 0x80000000 ) 1.1.1.3 ! root 160: return 1; // (left is negative) 1.1 root 161: return 0; 162: } 1.1.1.3 ! root 163: 1.1 root 164: left = FixedMul ( line->dy>>8, dx>>8 ); 165: right = FixedMul ( dy>>8 , line->dx>>8 ); 1.1.1.3 ! root 166: 1.1 root 167: if (right < left) 1.1.1.3 ! root 168: return 0; // front side ! 169: return 1; // back side 1.1 root 170: } 171: 172: 173: 174: /* 175: ============== 176: = 177: = P_MakeDivline 178: = 179: ============== 180: */ 181: 182: void P_MakeDivline (line_t *li, divline_t *dl) 183: { 184: dl->x = li->v1->x; 185: dl->y = li->v1->y; 186: dl->dx = li->dx; 187: dl->dy = li->dy; 188: } 189: 190: 191: /* 1.1.1.2 root 192: =============== 193: = 194: = P_InterceptVector 195: = 196: = Returns the fractional intercept point along the first divline 197: = 198: = This is only called by the addthings and addlines traversers 199: =============== 200: */ 201: 202: fixed_t P_InterceptVector (divline_t *v2, divline_t *v1) 203: { 204: #if 1 1.1.1.3 ! root 205: fixed_t frac, num, den; ! 206: 1.1.1.2 root 207: den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); 208: if (den == 0) 209: return 0; 1.1.1.3 ! root 210: // I_Error ("P_InterceptVector: parallel"); ! 211: num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + 1.1.1.2 root 212: FixedMul ( (v2->y - v1->y)>>8 , v1->dx); 213: frac = FixedDiv (num , den); 214: 215: return frac; 216: #else 1.1.1.3 ! root 217: float frac, num, den, v1x,v1y,v1dx,v1dy,v2x,v2y,v2dx,v2dy; 1.1.1.2 root 218: 219: v1x = (float)v1->x/FRACUNIT; 220: v1y = (float)v1->y/FRACUNIT; 221: v1dx = (float)v1->dx/FRACUNIT; 222: v1dy = (float)v1->dy/FRACUNIT; 223: v2x = (float)v2->x/FRACUNIT; 224: v2y = (float)v2->y/FRACUNIT; 225: v2dx = (float)v2->dx/FRACUNIT; 226: v2dy = (float)v2->dy/FRACUNIT; 1.1.1.3 ! root 227: 1.1.1.2 root 228: den = v1dy*v2dx - v1dx*v2dy; 229: if (den == 0) 1.1.1.3 ! root 230: return 0; // parallel 1.1.1.2 root 231: num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx; 232: frac = num / den; 233: 234: return frac*FRACUNIT; 235: #endif 236: } 237: 238: /* 1.1 root 239: ================== 240: = 241: = P_LineOpening 242: = 243: = Sets opentop and openbottom to the window through a two sided line 244: = OPTIMIZE: keep this precalculated 245: ================== 246: */ 247: 248: fixed_t opentop, openbottom, openrange; 1.1.1.3 ! root 249: fixed_t lowfloor; 1.1 root 250: 251: void P_LineOpening (line_t *linedef) 252: { 1.1.1.3 ! root 253: sector_t *front, *back; ! 254: 1.1 root 255: if (linedef->sidenum[1] == -1) 1.1.1.3 ! root 256: { // single sided line 1.1 root 257: openrange = 0; 258: return; 259: } 1.1.1.3 ! root 260: 1.1 root 261: front = linedef->frontsector; 262: back = linedef->backsector; 1.1.1.3 ! root 263: 1.1 root 264: if (front->ceilingheight < back->ceilingheight) 265: opentop = front->ceilingheight; 266: else 267: opentop = back->ceilingheight; 268: if (front->floorheight > back->floorheight) 269: { 270: openbottom = front->floorheight; 271: lowfloor = back->floorheight; 1.1.1.3 ! root 272: tmfloorpic = front->floorpic; 1.1 root 273: } 274: else 275: { 276: openbottom = back->floorheight; 277: lowfloor = front->floorheight; 1.1.1.3 ! root 278: tmfloorpic = back->floorpic; 1.1 root 279: } 1.1.1.3 ! root 280: 1.1 root 281: openrange = opentop - openbottom; 282: } 283: 284: /* 285: =============================================================================== 286: 287: THING POSITION SETTING 288: 289: =============================================================================== 290: */ 291: 292: /* 293: =================== 294: = 1.1.1.3 ! root 295: = P_UnsetThingPosition 1.1 root 296: = 297: = Unlinks a thing from block map and sectors 298: = 299: =================== 300: */ 301: 302: void P_UnsetThingPosition (mobj_t *thing) 303: { 1.1.1.3 ! root 304: int blockx, blocky; 1.1 root 305: 306: if ( ! (thing->flags & MF_NOSECTOR) ) 1.1.1.3 ! root 307: { // inert things don't need to be in blockmap 1.1.1.2 root 308: // unlink from subsector 1.1 root 309: if (thing->snext) 310: thing->snext->sprev = thing->sprev; 311: if (thing->sprev) 312: thing->sprev->snext = thing->snext; 313: else 314: thing->subsector->sector->thinglist = thing->snext; 315: } 1.1.1.3 ! root 316: 1.1 root 317: if ( ! (thing->flags & MF_NOBLOCKMAP) ) 1.1.1.3 ! root 318: { // inert things don't need to be in blockmap 1.1.1.2 root 319: // unlink from block map 1.1 root 320: if (thing->bnext) 321: thing->bnext->bprev = thing->bprev; 322: if (thing->bprev) 323: thing->bprev->bnext = thing->bnext; 324: else 325: { 326: blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; 327: blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; 1.1.1.2 root 328: if (blockx>=0 && blockx < bmapwidth 329: && blocky>=0 && blocky <bmapheight) 1.1 root 330: blocklinks[blocky*bmapwidth+blockx] = thing->bnext; 331: } 332: } 333: } 334: 335: 336: /* 337: =================== 338: = 1.1.1.3 ! root 339: = P_SetThingPosition 1.1 root 340: = 341: = Links a thing into both a block and a subsector based on it's x y 342: = Sets thing->subsector properly 343: = 344: =================== 345: */ 346: 347: void P_SetThingPosition (mobj_t *thing) 348: { 1.1.1.3 ! root 349: subsector_t *ss; ! 350: sector_t *sec; ! 351: int blockx, blocky; ! 352: mobj_t **link; ! 353: 1.1.1.2 root 354: // 355: // link into subsector 356: // 1.1 root 357: ss = R_PointInSubsector (thing->x,thing->y); 358: thing->subsector = ss; 359: if ( ! (thing->flags & MF_NOSECTOR) ) 1.1.1.3 ! root 360: { // invisible things don't go into the sector links 1.1 root 361: sec = ss->sector; 1.1.1.3 ! root 362: 1.1 root 363: thing->sprev = NULL; 364: thing->snext = sec->thinglist; 365: if (sec->thinglist) 366: sec->thinglist->sprev = thing; 367: sec->thinglist = thing; 368: } 1.1.1.3 ! root 369: 1.1.1.2 root 370: // 371: // link into blockmap 372: // 1.1 root 373: if ( ! (thing->flags & MF_NOBLOCKMAP) ) 1.1.1.3 ! root 374: { // inert things don't need to be in blockmap 1.1 root 375: blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; 376: blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; 377: if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky <bmapheight) 378: { 379: link = &blocklinks[blocky*bmapwidth+blockx]; 380: thing->bprev = NULL; 381: thing->bnext = *link; 382: if (*link) 383: (*link)->bprev = thing; 384: *link = thing; 385: } 386: else 1.1.1.3 ! root 387: { // thing is off the map 1.1 root 388: thing->bnext = thing->bprev = NULL; 389: } 390: } 391: } 392: 393: 394: 395: /* 396: =============================================================================== 397: 398: BLOCK MAP ITERATORS 399: 400: For each line/thing in the given mapblock, call the passed function. 401: If the function returns false, exit with false without checking anything else. 402: 403: =============================================================================== 404: */ 405: 406: /* 407: ================== 408: = 409: = P_BlockLinesIterator 410: = 411: = The validcount flags are used to avoid checking lines 412: = that are marked in multiple mapblocks, so increment validcount before 413: = the first call to P_BlockLinesIterator, then make one or more calls to it 414: =================== 415: */ 416: 417: boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ) 418: { 1.1.1.3 ! root 419: int offset; ! 420: short *list; ! 421: line_t *ld; ! 422: ! 423: int i; ! 424: polyblock_t *polyLink; ! 425: seg_t **tempSeg; ! 426: extern polyblock_t **PolyBlockMap; ! 427: ! 428: if (x < 0 || y<0 || x>=bmapwidth || y>=bmapheight) 1.1 root 429: return true; 430: offset = y*bmapwidth+x; 1.1.1.3 ! root 431: ! 432: polyLink = PolyBlockMap[offset]; ! 433: while(polyLink) ! 434: { ! 435: if(polyLink->polyobj) ! 436: { ! 437: if(polyLink->polyobj->validcount != validcount) ! 438: { ! 439: polyLink->polyobj->validcount = validcount; ! 440: tempSeg = polyLink->polyobj->segs; ! 441: for(i = 0; i < polyLink->polyobj->numsegs; i++, tempSeg++) ! 442: { ! 443: if((*tempSeg)->linedef->validcount == validcount) ! 444: { ! 445: continue; ! 446: } ! 447: (*tempSeg)->linedef->validcount = validcount; ! 448: if(!func((*tempSeg)->linedef)) ! 449: { ! 450: return false; ! 451: } ! 452: } ! 453: } ! 454: } ! 455: polyLink = polyLink->next; ! 456: } ! 457: 1.1 root 458: offset = *(blockmap+offset); 459: 460: for ( list = blockmaplump+offset ; *list != -1 ; list++) 461: { 462: ld = &lines[*list]; 463: if (ld->validcount == validcount) 1.1.1.3 ! root 464: continue; // line has already been checked 1.1 root 465: ld->validcount = validcount; 1.1.1.3 ! root 466: 1.1 root 467: if ( !func(ld) ) 468: return false; 469: } 1.1.1.3 ! root 470: ! 471: return true; // everything was checked 1.1 root 472: } 473: 474: 475: /* 476: ================== 477: = 478: = P_BlockThingsIterator 479: = 480: ================== 481: */ 482: 483: boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ) 484: { 1.1.1.3 ! root 485: mobj_t *mobj; ! 486: 1.1 root 487: if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) 488: return true; 489: 490: for (mobj = blocklinks[y*bmapwidth+x] ; mobj ; mobj = mobj->bnext) 491: if (!func( mobj ) ) 1.1.1.3 ! root 492: return false; 1.1 root 493: 494: return true; 495: } 496: 1.1.1.2 root 497: /* 498: =============================================================================== 499: 500: INTERCEPT ROUTINES 501: 502: =============================================================================== 503: */ 504: 1.1.1.3 ! root 505: intercept_t intercepts[MAXINTERCEPTS], *intercept_p; 1.1.1.2 root 506: 1.1.1.3 ! root 507: divline_t trace; ! 508: boolean earlyout; ! 509: int ptflags; 1.1.1.2 root 510: 511: /* 512: ================== 513: = 514: = PIT_AddLineIntercepts 515: = 516: = Looks for lines in the given block that intercept the given trace 517: = to add to the intercepts list 518: = A line is crossed if its endpoints are on opposite sides of the trace 519: = Returns true if earlyout and a solid line hit 520: ================== 521: */ 522: 523: boolean PIT_AddLineIntercepts (line_t *ld) 524: { 1.1.1.3 ! root 525: int s1, s2; ! 526: fixed_t frac; ! 527: divline_t dl; ! 528: 1.1.1.2 root 529: // avoid precision problems with two routines 530: if ( trace.dx > FRACUNIT*16 || trace.dy > FRACUNIT*16 531: || trace.dx < -FRACUNIT*16 || trace.dy < -FRACUNIT*16) 532: { 533: s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); 534: s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); 535: } 536: else 537: { 538: s1 = P_PointOnLineSide (trace.x, trace.y, ld); 539: s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); 540: } 541: if (s1 == s2) 1.1.1.3 ! root 542: return true; // line isn't crossed 1.1.1.2 root 543: 544: // 545: // hit the line 546: // 547: P_MakeDivline (ld, &dl); 548: frac = P_InterceptVector (&trace, &dl); 549: if (frac < 0) 1.1.1.3 ! root 550: return true; // behind source ! 551: 1.1.1.2 root 552: // try to early out the check 553: if (earlyout && frac < FRACUNIT && !ld->backsector) 1.1.1.3 ! root 554: return false; // stop checking ! 555: 1.1.1.2 root 556: intercept_p->frac = frac; 557: intercept_p->isaline = true; 558: intercept_p->d.line = ld; 559: intercept_p++; 560: 1.1.1.3 ! root 561: return true; // continue 1.1.1.2 root 562: } 563: 564: 565: 566: /* 567: ================== 568: = 569: = PIT_AddThingIntercepts 570: = 571: ================== 572: */ 573: 1.1.1.3 ! root 574: boolean PIT_AddThingIntercepts (mobj_t *thing) 1.1.1.2 root 575: { 1.1.1.3 ! root 576: fixed_t x1,y1, x2,y2; ! 577: int s1, s2; ! 578: boolean tracepositive; ! 579: divline_t dl; ! 580: fixed_t frac; ! 581: 1.1.1.2 root 582: tracepositive = (trace.dx ^ trace.dy)>0; 1.1.1.3 ! root 583: 1.1.1.2 root 584: // check a corner to corner crossection for hit 1.1.1.3 ! root 585: 1.1.1.2 root 586: if (tracepositive) 587: { 588: x1 = thing->x - thing->radius; 589: y1 = thing->y + thing->radius; 1.1.1.3 ! root 590: 1.1.1.2 root 591: x2 = thing->x + thing->radius; 1.1.1.3 ! root 592: y2 = thing->y - thing->radius; 1.1.1.2 root 593: } 594: else 595: { 596: x1 = thing->x - thing->radius; 597: y1 = thing->y - thing->radius; 1.1.1.3 ! root 598: 1.1.1.2 root 599: x2 = thing->x + thing->radius; 1.1.1.3 ! root 600: y2 = thing->y + thing->radius; 1.1.1.2 root 601: } 602: s1 = P_PointOnDivlineSide (x1, y1, &trace); 603: s2 = P_PointOnDivlineSide (x2, y2, &trace); 604: if (s1 == s2) 1.1.1.3 ! root 605: return true; // line isn't crossed ! 606: 1.1.1.2 root 607: dl.x = x1; 608: dl.y = y1; 609: dl.dx = x2-x1; 610: dl.dy = y2-y1; 611: frac = P_InterceptVector (&trace, &dl); 612: if (frac < 0) 1.1.1.3 ! root 613: return true; // behind source 1.1.1.2 root 614: intercept_p->frac = frac; 615: intercept_p->isaline = false; 616: intercept_p->d.thing = thing; 617: intercept_p++; 618: 1.1.1.3 ! root 619: return true; // keep going 1.1.1.2 root 620: } 621: 622: 623: /* 624: ==================== 625: = 626: = P_TraverseIntercepts 627: = 628: = Returns true if the traverser function returns true for all lines 629: ==================== 630: */ 631: 632: boolean P_TraverseIntercepts ( traverser_t func, fixed_t maxfrac ) 633: { 1.1.1.3 ! root 634: int count; ! 635: fixed_t dist; ! 636: intercept_t *scan, *in; ! 637: 1.1.1.2 root 638: count = intercept_p - intercepts; 1.1.1.3 ! root 639: in = 0; // shut up compiler warning ! 640: 1.1.1.2 root 641: while (count--) 642: { 643: dist = MAXINT; 644: for (scan = intercepts ; scan<intercept_p ; scan++) 645: if (scan->frac < dist) 646: { 647: dist = scan->frac; 648: in = scan; 649: } 1.1.1.3 ! root 650: 1.1.1.2 root 651: if (dist > maxfrac) 1.1.1.3 ! root 652: return true; // checked everything in range 1.1.1.2 root 653: #if 0 1.1.1.3 ! root 654: { // don't check these yet, ther may be others inserted 1.1.1.2 root 655: in = scan = intercepts; 656: for ( scan = intercepts ; scan<intercept_p ; scan++) 657: if (scan->frac > maxfrac) 658: *in++ = *scan; 659: intercept_p = in; 660: return false; 661: } 662: #endif 663: 664: if ( !func (in) ) 1.1.1.3 ! root 665: return false; // don't bother going farther 1.1.1.2 root 666: in->frac = MAXINT; 667: } 1.1.1.3 ! root 668: ! 669: return true; // everything was traversed 1.1.1.2 root 670: } 671: 672: 673: 674: /* 675: ================== 676: = 677: = P_PathTraverse 678: = 679: = Traces a line from x1,y1 to x2,y2, calling the traverser function for each 680: = Returns true if the traverser function returns true for all lines 681: ================== 682: */ 683: 684: boolean P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, 685: int flags, boolean (*trav) (intercept_t *)) 686: { 1.1.1.3 ! root 687: fixed_t xt1,yt1,xt2,yt2; ! 688: fixed_t xstep,ystep; ! 689: fixed_t partial; ! 690: fixed_t xintercept, yintercept; ! 691: int mapx, mapy, mapxstep, mapystep; ! 692: int count; ! 693: 1.1.1.2 root 694: earlyout = flags & PT_EARLYOUT; 1.1.1.3 ! root 695: 1.1.1.2 root 696: validcount++; 697: intercept_p = intercepts; 1.1.1.3 ! root 698: 1.1.1.2 root 699: if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) 1.1.1.3 ! root 700: x1 += FRACUNIT; // don't side exactly on a line 1.1.1.2 root 701: if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) 1.1.1.3 ! root 702: y1 += FRACUNIT; // don't side exactly on a line 1.1.1.2 root 703: trace.x = x1; 704: trace.y = y1; 705: trace.dx = x2 - x1; 706: trace.dy = y2 - y1; 707: 708: x1 -= bmaporgx; 709: y1 -= bmaporgy; 710: xt1 = x1>>MAPBLOCKSHIFT; 711: yt1 = y1>>MAPBLOCKSHIFT; 712: 713: x2 -= bmaporgx; 714: y2 -= bmaporgy; 715: xt2 = x2>>MAPBLOCKSHIFT; 716: yt2 = y2>>MAPBLOCKSHIFT; 717: 718: if (xt2 > xt1) 719: { 720: mapxstep = 1; 721: partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); 722: ystep = FixedDiv (y2-y1,abs(x2-x1)); 723: } 724: else if (xt2 < xt1) 725: { 726: mapxstep = -1; 727: partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); 728: ystep = FixedDiv (y2-y1,abs(x2-x1)); 729: } 730: else 731: { 732: mapxstep = 0; 733: partial = FRACUNIT; 734: ystep = 256*FRACUNIT; 1.1.1.3 ! root 735: } 1.1.1.2 root 736: yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep); 737: 1.1.1.3 ! root 738: 1.1.1.2 root 739: if (yt2 > yt1) 740: { 741: mapystep = 1; 742: partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); 743: xstep = FixedDiv (x2-x1,abs(y2-y1)); 744: } 745: else if (yt2 < yt1) 746: { 747: mapystep = -1; 748: partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); 749: xstep = FixedDiv (x2-x1,abs(y2-y1)); 750: } 751: else 752: { 753: mapystep = 0; 754: partial = FRACUNIT; 755: xstep = 256*FRACUNIT; 1.1.1.3 ! root 756: } 1.1.1.2 root 757: xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep); 758: 759: 760: // 761: // step through map blocks 762: // Count is present to prevent a round off error from skipping the break 763: mapx = xt1; 764: mapy = yt1; 765: 766: for (count = 0 ; count < 64 ; count++) 767: { 768: if (flags & PT_ADDLINES) 769: { 770: if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts)) 1.1.1.3 ! root 771: return false; // early out 1.1.1.2 root 772: } 773: if (flags & PT_ADDTHINGS) 774: { 775: if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts)) 1.1.1.3 ! root 776: return false; // early out 1.1.1.2 root 777: } 778: 779: if (mapx == xt2 && mapy == yt2) 780: break; 781: 782: if ( (yintercept >> FRACBITS) == mapy) 783: { 784: yintercept += ystep; 785: mapx += mapxstep; 786: } 787: else if ( (xintercept >> FRACBITS) == mapx) 788: { 789: xintercept += xstep; 790: mapy += mapystep; 791: } 792: 793: } 794: 795: 796: // 797: // go through the sorted list 798: // 799: return P_TraverseIntercepts ( trav, FRACUNIT ); 800: } 801: 1.1.1.3 ! root 802: //=========================================================================== ! 803: // ! 804: // P_RoughMonsterSearch ! 805: // ! 806: // Searches though the surrounding mapblocks for monsters/players ! 807: // distance is in MAPBLOCKUNITS ! 808: //=========================================================================== ! 809: ! 810: mobj_t *P_RoughMonsterSearch(mobj_t *mo, int distance) ! 811: { ! 812: int blockX; ! 813: int blockY; ! 814: int startX, startY; ! 815: int blockIndex; ! 816: int firstStop; ! 817: int secondStop; ! 818: int thirdStop; ! 819: int finalStop; ! 820: int count; ! 821: mobj_t *target; ! 822: ! 823: startX = (mo->x-bmaporgx)>>MAPBLOCKSHIFT; ! 824: startY = (mo->y-bmaporgy)>>MAPBLOCKSHIFT; ! 825: ! 826: if(startX >= 0 && startX < bmapwidth && startY >= 0 && startY < bmapheight) ! 827: { ! 828: if(target = RoughBlockCheck(mo, startY*bmapwidth+startX)) ! 829: { // found a target right away ! 830: return target; ! 831: } ! 832: } ! 833: for(count = 1; count <= distance; count++) ! 834: { ! 835: blockX = startX-count; ! 836: blockY = startY-count; 1.1.1.2 root 837: 1.1.1.3 ! root 838: if(blockY < 0) ! 839: { ! 840: blockY = 0; ! 841: } ! 842: else if(blockY >= bmapheight) ! 843: { ! 844: blockY = bmapheight-1; ! 845: } ! 846: if(blockX < 0) ! 847: { ! 848: blockX = 0; ! 849: } ! 850: else if(blockX >= bmapwidth) ! 851: { ! 852: blockX = bmapwidth-1; ! 853: } ! 854: blockIndex = blockY*bmapwidth+blockX; ! 855: firstStop = startX+count; ! 856: if(firstStop < 0) ! 857: { ! 858: continue; ! 859: } ! 860: if(firstStop >= bmapwidth) ! 861: { ! 862: firstStop = bmapwidth-1; ! 863: } ! 864: secondStop = startY+count; ! 865: if(secondStop < 0) ! 866: { ! 867: continue; ! 868: } ! 869: if(secondStop >= bmapheight) ! 870: { ! 871: secondStop = bmapheight-1; ! 872: } ! 873: thirdStop = secondStop*bmapwidth+blockX; ! 874: secondStop = secondStop*bmapwidth+firstStop; ! 875: firstStop += blockY*bmapwidth; ! 876: finalStop = blockIndex; 1.1.1.2 root 877: 1.1.1.3 ! root 878: // Trace the first block section (along the top) ! 879: for(; blockIndex <= firstStop; blockIndex++) ! 880: { ! 881: if(target = RoughBlockCheck(mo, blockIndex)) ! 882: { ! 883: return target; ! 884: } ! 885: } ! 886: // Trace the second block section (right edge) ! 887: for(blockIndex--; blockIndex <= secondStop; blockIndex += bmapwidth) ! 888: { ! 889: if(target = RoughBlockCheck(mo, blockIndex)) ! 890: { ! 891: return target; ! 892: } ! 893: } ! 894: // Trace the third block section (bottom edge) ! 895: for(blockIndex -= bmapwidth; blockIndex >= thirdStop; blockIndex--) ! 896: { ! 897: if(target = RoughBlockCheck(mo, blockIndex)) ! 898: { ! 899: return target; ! 900: } ! 901: } ! 902: // Trace the final block section (left edge) ! 903: for(blockIndex++; blockIndex > finalStop; blockIndex -= bmapwidth) ! 904: { ! 905: if(target = RoughBlockCheck(mo, blockIndex)) ! 906: { ! 907: return target; ! 908: } ! 909: } ! 910: } ! 911: return NULL; ! 912: } ! 913: ! 914: //=========================================================================== ! 915: // ! 916: // RoughBlockCheck ! 917: // ! 918: //=========================================================================== ! 919: ! 920: static mobj_t *RoughBlockCheck(mobj_t *mo, int index) ! 921: { ! 922: mobj_t *link; ! 923: mobj_t *master; ! 924: angle_t angle; ! 925: ! 926: link = blocklinks[index]; ! 927: while(link) ! 928: { ! 929: if (mo->player) // Minotaur looking around player ! 930: { ! 931: if ((link->flags&MF_COUNTKILL) || ! 932: (link->player && (link != mo))) ! 933: { ! 934: if (!(link->flags&MF_SHOOTABLE)) ! 935: { ! 936: link = link->bnext; ! 937: continue; ! 938: } ! 939: if (link->flags2&MF2_DORMANT) ! 940: { ! 941: link = link->bnext; ! 942: continue; ! 943: } ! 944: if ((link->type == MT_MINOTAUR) && ! 945: (((mobj_t *)link->special1) == mo)) ! 946: { ! 947: link = link->bnext; ! 948: continue; ! 949: } ! 950: if(netgame && !deathmatch && link->player) ! 951: { ! 952: link = link->bnext; ! 953: continue; ! 954: } ! 955: if(P_CheckSight(mo, link)) ! 956: { ! 957: return link; ! 958: } ! 959: } ! 960: link = link->bnext; ! 961: } ! 962: else if (mo->type == MT_MINOTAUR) // looking around minotaur ! 963: { ! 964: master = (mobj_t *)mo->special1; ! 965: if ((link->flags&MF_COUNTKILL) || ! 966: (link->player && (link != master))) ! 967: { ! 968: if (!(link->flags&MF_SHOOTABLE)) ! 969: { ! 970: link = link->bnext; ! 971: continue; ! 972: } ! 973: if (link->flags2&MF2_DORMANT) ! 974: { ! 975: link = link->bnext; ! 976: continue; ! 977: } ! 978: if ((link->type == MT_MINOTAUR) && ! 979: (link->special1 == mo->special1)) ! 980: { ! 981: link = link->bnext; ! 982: continue; ! 983: } ! 984: if(netgame && !deathmatch && link->player) ! 985: { ! 986: link = link->bnext; ! 987: continue; ! 988: } ! 989: if(P_CheckSight(mo, link)) ! 990: { ! 991: return link; ! 992: } ! 993: } ! 994: link = link->bnext; ! 995: } ! 996: else if (mo->type == MT_MSTAFF_FX2) // bloodscourge ! 997: { ! 998: if ((link->flags&MF_COUNTKILL || ! 999: (link->player && link != mo->target)) ! 1000: && !(link->flags2&MF2_DORMANT)) ! 1001: { ! 1002: if (!(link->flags&MF_SHOOTABLE)) ! 1003: { ! 1004: link = link->bnext; ! 1005: continue; ! 1006: } ! 1007: if(netgame && !deathmatch && link->player) ! 1008: { ! 1009: link = link->bnext; ! 1010: continue; ! 1011: } ! 1012: else if(P_CheckSight(mo, link)) ! 1013: { ! 1014: master = mo->target; ! 1015: angle = R_PointToAngle2(master->x, master->y, ! 1016: link->x, link->y) - master->angle; ! 1017: angle >>= 24; ! 1018: if (angle>226 || angle<30) ! 1019: { ! 1020: return link; ! 1021: } ! 1022: } ! 1023: } ! 1024: link = link->bnext; ! 1025: } ! 1026: else // spirits ! 1027: { ! 1028: if ((link->flags&MF_COUNTKILL || ! 1029: (link->player && link != mo->target)) ! 1030: && !(link->flags2&MF2_DORMANT)) ! 1031: { ! 1032: if (!(link->flags&MF_SHOOTABLE)) ! 1033: { ! 1034: link = link->bnext; ! 1035: continue; ! 1036: } ! 1037: if(netgame && !deathmatch && link->player) ! 1038: { ! 1039: link = link->bnext; ! 1040: continue; ! 1041: } ! 1042: if (link == mo->target) ! 1043: { ! 1044: link = link->bnext; ! 1045: continue; ! 1046: } ! 1047: else if(P_CheckSight(mo, link)) ! 1048: { ! 1049: return link; ! 1050: } ! 1051: } ! 1052: link = link->bnext; ! 1053: } ! 1054: } ! 1055: return NULL; ! 1056: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.