|
|
1.1 ! root 1: // world.c -- world query functions ! 2: ! 3: #include "quakedef.h" ! 4: ! 5: /* ! 6: ! 7: entities never clip against themselves, or their owner ! 8: ! 9: line of sight checks trace->crosscontent, but bullets don't ! 10: ! 11: */ ! 12: ! 13: ! 14: typedef struct ! 15: { ! 16: vec3_t boxmins, boxmaxs;// enclose the test object along entire move ! 17: float *mins, *maxs; // size of the moving object ! 18: vec3_t mins2, maxs2; // size when clipping against mosnters ! 19: float *start, *end; ! 20: trace_t trace; ! 21: int type; ! 22: edict_t *passedict; ! 23: } moveclip_t; ! 24: ! 25: ! 26: int SV_HullPointContents (hull_t *hull, int num, vec3_t p); ! 27: ! 28: /* ! 29: =============================================================================== ! 30: ! 31: HULL BOXES ! 32: ! 33: =============================================================================== ! 34: */ ! 35: ! 36: ! 37: static hull_t box_hull; ! 38: static dclipnode_t box_clipnodes[6]; ! 39: static mplane_t box_planes[6]; ! 40: ! 41: /* ! 42: =================== ! 43: SV_InitBoxHull ! 44: ! 45: Set up the planes and clipnodes so that the six floats of a bounding box ! 46: can just be stored out and get a proper hull_t structure. ! 47: =================== ! 48: */ ! 49: void SV_InitBoxHull (void) ! 50: { ! 51: int i; ! 52: int side; ! 53: ! 54: box_hull.clipnodes = box_clipnodes; ! 55: box_hull.planes = box_planes; ! 56: box_hull.firstclipnode = 0; ! 57: box_hull.lastclipnode = 5; ! 58: ! 59: for (i=0 ; i<6 ; i++) ! 60: { ! 61: box_clipnodes[i].planenum = i; ! 62: ! 63: side = i&1; ! 64: ! 65: box_clipnodes[i].children[side] = CONTENTS_EMPTY; ! 66: if (i != 5) ! 67: box_clipnodes[i].children[side^1] = i + 1; ! 68: else ! 69: box_clipnodes[i].children[side^1] = CONTENTS_SOLID; ! 70: ! 71: box_planes[i].type = i>>1; ! 72: box_planes[i].normal[i>>1] = 1; ! 73: } ! 74: ! 75: } ! 76: ! 77: ! 78: /* ! 79: =================== ! 80: SV_HullForBox ! 81: ! 82: To keep everything totally uniform, bounding boxes are turned into small ! 83: BSP trees instead of being compared directly. ! 84: =================== ! 85: */ ! 86: hull_t *SV_HullForBox (vec3_t mins, vec3_t maxs) ! 87: { ! 88: box_planes[0].dist = maxs[0]; ! 89: box_planes[1].dist = mins[0]; ! 90: box_planes[2].dist = maxs[1]; ! 91: box_planes[3].dist = mins[1]; ! 92: box_planes[4].dist = maxs[2]; ! 93: box_planes[5].dist = mins[2]; ! 94: ! 95: return &box_hull; ! 96: } ! 97: ! 98: ! 99: ! 100: /* ! 101: ================ ! 102: SV_HullForEntity ! 103: ! 104: Returns a hull that can be used for testing or clipping an object of mins/maxs ! 105: size. ! 106: Offset is filled in to contain the adjustment that must be added to the ! 107: testing object's origin to get a point to use with the returned hull. ! 108: ================ ! 109: */ ! 110: hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) ! 111: { ! 112: model_t *model; ! 113: vec3_t size; ! 114: vec3_t hullmins, hullmaxs; ! 115: hull_t *hull; ! 116: ! 117: // decide which clipping hull to use, based on the size ! 118: if (ent->v.solid == SOLID_BSP) ! 119: { // explicit hulls in the BSP model ! 120: if (ent->v.movetype != MOVETYPE_PUSH) ! 121: Sys_Error ("SOLID_BSP without MOVETYPE_PUSH"); ! 122: ! 123: model = sv.models[ (int)ent->v.modelindex ]; ! 124: ! 125: if (!model || model->type != mod_brush) ! 126: Sys_Error ("MOVETYPE_PUSH with a non bsp model"); ! 127: ! 128: VectorSubtract (maxs, mins, size); ! 129: if (size[0] < 3) ! 130: hull = &model->hulls[0]; ! 131: else if (size[0] <= 32) ! 132: hull = &model->hulls[1]; ! 133: else ! 134: hull = &model->hulls[2]; ! 135: ! 136: // calculate an offset value to center the origin ! 137: VectorSubtract (hull->clip_mins, mins, offset); ! 138: VectorAdd (offset, ent->v.origin, offset); ! 139: } ! 140: else ! 141: { // create a temp hull from bounding box sizes ! 142: ! 143: VectorSubtract (ent->v.mins, maxs, hullmins); ! 144: VectorSubtract (ent->v.maxs, mins, hullmaxs); ! 145: hull = SV_HullForBox (hullmins, hullmaxs); ! 146: ! 147: VectorCopy (ent->v.origin, offset); ! 148: } ! 149: ! 150: ! 151: return hull; ! 152: } ! 153: ! 154: /* ! 155: =============================================================================== ! 156: ! 157: ENTITY AREA CHECKING ! 158: ! 159: =============================================================================== ! 160: */ ! 161: ! 162: typedef struct areanode_s ! 163: { ! 164: int axis; // -1 = leaf node ! 165: float dist; ! 166: struct areanode_s *children[2]; ! 167: link_t trigger_edicts; ! 168: link_t solid_edicts; ! 169: } areanode_t; ! 170: ! 171: #define AREA_DEPTH 4 ! 172: #define AREA_NODES 32 ! 173: ! 174: static areanode_t sv_areanodes[AREA_NODES]; ! 175: static int sv_numareanodes; ! 176: ! 177: /* ! 178: =============== ! 179: SV_CreateAreaNode ! 180: ! 181: =============== ! 182: */ ! 183: areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs) ! 184: { ! 185: areanode_t *anode; ! 186: vec3_t size; ! 187: vec3_t mins1, maxs1, mins2, maxs2; ! 188: ! 189: anode = &sv_areanodes[sv_numareanodes]; ! 190: sv_numareanodes++; ! 191: ! 192: ClearLink (&anode->trigger_edicts); ! 193: ClearLink (&anode->solid_edicts); ! 194: ! 195: if (depth == AREA_DEPTH) ! 196: { ! 197: anode->axis = -1; ! 198: anode->children[0] = anode->children[1] = NULL; ! 199: return anode; ! 200: } ! 201: ! 202: VectorSubtract (maxs, mins, size); ! 203: if (size[0] > size[1]) ! 204: anode->axis = 0; ! 205: else ! 206: anode->axis = 1; ! 207: ! 208: anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]); ! 209: VectorCopy (mins, mins1); ! 210: VectorCopy (mins, mins2); ! 211: VectorCopy (maxs, maxs1); ! 212: VectorCopy (maxs, maxs2); ! 213: ! 214: maxs1[anode->axis] = mins2[anode->axis] = anode->dist; ! 215: ! 216: anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2); ! 217: anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1); ! 218: ! 219: return anode; ! 220: } ! 221: ! 222: /* ! 223: =============== ! 224: SV_ClearWorld ! 225: ! 226: =============== ! 227: */ ! 228: void SV_ClearWorld (void) ! 229: { ! 230: SV_InitBoxHull (); ! 231: ! 232: memset (sv_areanodes, 0, sizeof(sv_areanodes)); ! 233: sv_numareanodes = 0; ! 234: SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs); ! 235: } ! 236: ! 237: ! 238: /* ! 239: =============== ! 240: SV_UnlinkEdict ! 241: ! 242: =============== ! 243: */ ! 244: void SV_UnlinkEdict (edict_t *ent) ! 245: { ! 246: if (!ent->area.prev) ! 247: return; // not linked in anywhere ! 248: RemoveLink (&ent->area); ! 249: ent->area.prev = ent->area.next = NULL; ! 250: } ! 251: ! 252: ! 253: /* ! 254: ==================== ! 255: SV_TouchLinks ! 256: ==================== ! 257: */ ! 258: void SV_TouchLinks ( edict_t *ent, areanode_t *node ) ! 259: { ! 260: link_t *l, *next; ! 261: edict_t *touch; ! 262: int old_self, old_other; ! 263: ! 264: // touch linked edicts ! 265: for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next) ! 266: { ! 267: next = l->next; ! 268: touch = EDICT_FROM_AREA(l); ! 269: if (touch == ent) ! 270: continue; ! 271: if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER) ! 272: continue; ! 273: if (ent->v.absmin[0] > touch->v.absmax[0] ! 274: || ent->v.absmin[1] > touch->v.absmax[1] ! 275: || ent->v.absmin[2] > touch->v.absmax[2] ! 276: || ent->v.absmax[0] < touch->v.absmin[0] ! 277: || ent->v.absmax[1] < touch->v.absmin[1] ! 278: || ent->v.absmax[2] < touch->v.absmin[2] ) ! 279: continue; ! 280: ! 281: old_self = pr_global_struct->self; ! 282: old_other = pr_global_struct->other; ! 283: ! 284: pr_global_struct->self = EDICT_TO_PROG(touch); ! 285: pr_global_struct->other = EDICT_TO_PROG(ent); ! 286: pr_global_struct->time = sv.time; ! 287: PR_ExecuteProgram (touch->v.touch); ! 288: ! 289: pr_global_struct->self = old_self; ! 290: pr_global_struct->other = old_other; ! 291: } ! 292: ! 293: // recurse down both sides ! 294: if (node->axis == -1) ! 295: return; ! 296: ! 297: if ( ent->v.absmax[node->axis] > node->dist ) ! 298: SV_TouchLinks ( ent, node->children[0] ); ! 299: if ( ent->v.absmin[node->axis] < node->dist ) ! 300: SV_TouchLinks ( ent, node->children[1] ); ! 301: } ! 302: ! 303: ! 304: /* ! 305: =============== ! 306: SV_FindTouchedLeafs ! 307: ! 308: =============== ! 309: */ ! 310: void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) ! 311: { ! 312: mplane_t *splitplane; ! 313: mleaf_t *leaf; ! 314: int sides; ! 315: int leafnum; ! 316: ! 317: if (node->contents == CONTENTS_SOLID) ! 318: return; ! 319: ! 320: // add an efrag if the node is a leaf ! 321: ! 322: if ( node->contents < 0) ! 323: { ! 324: if (ent->num_leafs == MAX_ENT_LEAFS) ! 325: return; ! 326: ! 327: leaf = (mleaf_t *)node; ! 328: leafnum = leaf - sv.worldmodel->leafs - 1; ! 329: ! 330: ent->leafnums[ent->num_leafs] = leafnum; ! 331: ent->num_leafs++; ! 332: return; ! 333: } ! 334: ! 335: // NODE_MIXED ! 336: ! 337: splitplane = node->plane; ! 338: sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane); ! 339: ! 340: // recurse down the contacted sides ! 341: if (sides & 1) ! 342: SV_FindTouchedLeafs (ent, node->children[0]); ! 343: ! 344: if (sides & 2) ! 345: SV_FindTouchedLeafs (ent, node->children[1]); ! 346: } ! 347: ! 348: /* ! 349: =============== ! 350: SV_LinkEdict ! 351: ! 352: =============== ! 353: */ ! 354: void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) ! 355: { ! 356: areanode_t *node; ! 357: ! 358: if (ent->area.prev) ! 359: SV_UnlinkEdict (ent); // unlink from old position ! 360: ! 361: if (ent == sv.edicts) ! 362: return; // don't add the world ! 363: ! 364: if (ent->free) ! 365: return; ! 366: ! 367: // set the abs box ! 368: VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin); ! 369: VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax); ! 370: ! 371: // ! 372: // to make items easier to pick up and allow them to be grabbed off ! 373: // of shelves, the abs sizes are expanded ! 374: // ! 375: if ((int)ent->v.flags & FL_ITEM) ! 376: { ! 377: ent->v.absmin[0] -= 15; ! 378: ent->v.absmin[1] -= 15; ! 379: ent->v.absmax[0] += 15; ! 380: ent->v.absmax[1] += 15; ! 381: } ! 382: else ! 383: { // because movement is clipped an epsilon away from an actual edge, ! 384: // we must fully check even when bounding boxes don't quite touch ! 385: ent->v.absmin[0] -= 1; ! 386: ent->v.absmin[1] -= 1; ! 387: ent->v.absmin[2] -= 1; ! 388: ent->v.absmax[0] += 1; ! 389: ent->v.absmax[1] += 1; ! 390: ent->v.absmax[2] += 1; ! 391: } ! 392: ! 393: // link to PVS leafs ! 394: ent->num_leafs = 0; ! 395: if (ent->v.modelindex) ! 396: SV_FindTouchedLeafs (ent, sv.worldmodel->nodes); ! 397: ! 398: if (ent->v.solid == SOLID_NOT) ! 399: return; ! 400: ! 401: // find the first node that the ent's box crosses ! 402: node = sv_areanodes; ! 403: while (1) ! 404: { ! 405: if (node->axis == -1) ! 406: break; ! 407: if (ent->v.absmin[node->axis] > node->dist) ! 408: node = node->children[0]; ! 409: else if (ent->v.absmax[node->axis] < node->dist) ! 410: node = node->children[1]; ! 411: else ! 412: break; // crosses the node ! 413: } ! 414: ! 415: // link it in ! 416: ! 417: if (ent->v.solid == SOLID_TRIGGER) ! 418: InsertLinkBefore (&ent->area, &node->trigger_edicts); ! 419: else ! 420: InsertLinkBefore (&ent->area, &node->solid_edicts); ! 421: ! 422: // if touch_triggers, touch all entities at this node and decend for more ! 423: if (touch_triggers) ! 424: SV_TouchLinks ( ent, sv_areanodes ); ! 425: } ! 426: ! 427: ! 428: ! 429: /* ! 430: =============================================================================== ! 431: ! 432: POINT TESTING IN HULLS ! 433: ! 434: =============================================================================== ! 435: */ ! 436: ! 437: #if !id386 ! 438: ! 439: /* ! 440: ================== ! 441: SV_HullPointContents ! 442: ! 443: ================== ! 444: */ ! 445: int SV_HullPointContents (hull_t *hull, int num, vec3_t p) ! 446: { ! 447: float d; ! 448: dclipnode_t *node; ! 449: mplane_t *plane; ! 450: ! 451: while (num >= 0) ! 452: { ! 453: if (num < hull->firstclipnode || num > hull->lastclipnode) ! 454: Sys_Error ("SV_HullPointContents: bad node number"); ! 455: ! 456: node = hull->clipnodes + num; ! 457: plane = hull->planes + node->planenum; ! 458: ! 459: if (plane->type < 3) ! 460: d = p[plane->type] - plane->dist; ! 461: else ! 462: d = DotProduct (plane->normal, p) - plane->dist; ! 463: if (d < 0) ! 464: num = node->children[1]; ! 465: else ! 466: num = node->children[0]; ! 467: } ! 468: ! 469: return num; ! 470: } ! 471: ! 472: #endif // !id386 ! 473: ! 474: ! 475: /* ! 476: ================== ! 477: SV_PointContents ! 478: ! 479: ================== ! 480: */ ! 481: int SV_PointContents (vec3_t p) ! 482: { ! 483: return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); ! 484: } ! 485: ! 486: //=========================================================================== ! 487: ! 488: /* ! 489: ============ ! 490: SV_TestEntityPosition ! 491: ! 492: A small wrapper around SV_BoxInSolidEntity that never clips against the ! 493: supplied entity. ! 494: ============ ! 495: */ ! 496: edict_t *SV_TestEntityPosition (edict_t *ent) ! 497: { ! 498: trace_t trace; ! 499: ! 500: trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent); ! 501: ! 502: if (trace.startsolid) ! 503: return sv.edicts; ! 504: ! 505: return NULL; ! 506: } ! 507: ! 508: ! 509: /* ! 510: =============================================================================== ! 511: ! 512: LINE TESTING IN HULLS ! 513: ! 514: =============================================================================== ! 515: */ ! 516: ! 517: // 1/32 epsilon to keep floating point happy ! 518: #define DIST_EPSILON (0.03125) ! 519: ! 520: /* ! 521: ================== ! 522: SV_RecursiveHullCheck ! 523: ! 524: ================== ! 525: */ ! 526: qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace) ! 527: { ! 528: dclipnode_t *node; ! 529: mplane_t *plane; ! 530: float t1, t2; ! 531: float frac; ! 532: int i; ! 533: vec3_t mid; ! 534: int side; ! 535: float midf; ! 536: ! 537: // check for empty ! 538: if (num < 0) ! 539: { ! 540: if (num != CONTENTS_SOLID) ! 541: { ! 542: trace->allsolid = false; ! 543: if (num == CONTENTS_EMPTY) ! 544: trace->inopen = true; ! 545: else ! 546: trace->inwater = true; ! 547: } ! 548: else ! 549: trace->startsolid = true; ! 550: return true; // empty ! 551: } ! 552: ! 553: if (num < hull->firstclipnode || num > hull->lastclipnode) ! 554: Sys_Error ("SV_RecursiveHullCheck: bad node number"); ! 555: ! 556: // ! 557: // find the point distances ! 558: // ! 559: node = hull->clipnodes + num; ! 560: plane = hull->planes + node->planenum; ! 561: ! 562: if (plane->type < 3) ! 563: { ! 564: t1 = p1[plane->type] - plane->dist; ! 565: t2 = p2[plane->type] - plane->dist; ! 566: } ! 567: else ! 568: { ! 569: t1 = DotProduct (plane->normal, p1) - plane->dist; ! 570: t2 = DotProduct (plane->normal, p2) - plane->dist; ! 571: } ! 572: ! 573: #if 1 ! 574: if (t1 >= 0 && t2 >= 0) ! 575: return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); ! 576: if (t1 < 0 && t2 < 0) ! 577: return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); ! 578: #else ! 579: if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) ) ! 580: return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); ! 581: if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) ) ! 582: return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); ! 583: #endif ! 584: ! 585: // put the crosspoint DIST_EPSILON pixels on the near side ! 586: if (t1 < 0) ! 587: frac = (t1 + DIST_EPSILON)/(t1-t2); ! 588: else ! 589: frac = (t1 - DIST_EPSILON)/(t1-t2); ! 590: if (frac < 0) ! 591: frac = 0; ! 592: if (frac > 1) ! 593: frac = 1; ! 594: ! 595: midf = p1f + (p2f - p1f)*frac; ! 596: for (i=0 ; i<3 ; i++) ! 597: mid[i] = p1[i] + frac*(p2[i] - p1[i]); ! 598: ! 599: side = (t1 < 0); ! 600: ! 601: // move up to the node ! 602: if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) ! 603: return false; ! 604: ! 605: #ifdef PARANOID ! 606: if (SV_HullPointContents (sv_hullmodel, mid, node->children[side]) ! 607: == CONTENTS_SOLID) ! 608: { ! 609: Con_Printf ("mid PointInHullSolid\n"); ! 610: return false; ! 611: } ! 612: #endif ! 613: ! 614: if (SV_HullPointContents (hull, node->children[side^1], mid) ! 615: != CONTENTS_SOLID) ! 616: // go past the node ! 617: return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); ! 618: ! 619: if (trace->allsolid) ! 620: return false; // never got out of the solid area ! 621: ! 622: //================== ! 623: // the other side of the node is solid, this is the impact point ! 624: //================== ! 625: if (!side) ! 626: { ! 627: VectorCopy (plane->normal, trace->plane.normal); ! 628: trace->plane.dist = plane->dist; ! 629: } ! 630: else ! 631: { ! 632: VectorSubtract (vec3_origin, plane->normal, trace->plane.normal); ! 633: trace->plane.dist = -plane->dist; ! 634: } ! 635: ! 636: while (SV_HullPointContents (hull, hull->firstclipnode, mid) ! 637: == CONTENTS_SOLID) ! 638: { // shouldn't really happen, but does occasionally ! 639: frac -= 0.1; ! 640: if (frac < 0) ! 641: { ! 642: trace->fraction = midf; ! 643: VectorCopy (mid, trace->endpos); ! 644: Con_Printf ("backup past 0\n"); ! 645: return false; ! 646: } ! 647: midf = p1f + (p2f - p1f)*frac; ! 648: for (i=0 ; i<3 ; i++) ! 649: mid[i] = p1[i] + frac*(p2[i] - p1[i]); ! 650: } ! 651: ! 652: trace->fraction = midf; ! 653: VectorCopy (mid, trace->endpos); ! 654: ! 655: return false; ! 656: } ! 657: ! 658: ! 659: /* ! 660: ================== ! 661: SV_ClipMoveToEntity ! 662: ! 663: Handles selection or creation of a clipping hull, and offseting (and ! 664: eventually rotation) of the end points ! 665: ================== ! 666: */ ! 667: trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) ! 668: { ! 669: trace_t trace; ! 670: vec3_t offset; ! 671: vec3_t start_l, end_l; ! 672: hull_t *hull; ! 673: ! 674: // fill in a default trace ! 675: memset (&trace, 0, sizeof(trace_t)); ! 676: trace.fraction = 1; ! 677: trace.allsolid = true; ! 678: VectorCopy (end, trace.endpos); ! 679: ! 680: // get the clipping hull ! 681: hull = SV_HullForEntity (ent, mins, maxs, offset); ! 682: ! 683: VectorSubtract (start, offset, start_l); ! 684: VectorSubtract (end, offset, end_l); ! 685: ! 686: // trace a line through the apropriate clipping hull ! 687: SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace); ! 688: ! 689: // fix trace up by the offset ! 690: if (trace.fraction != 1) ! 691: VectorAdd (trace.endpos, offset, trace.endpos); ! 692: ! 693: // did we clip the move? ! 694: if (trace.fraction < 1 || trace.startsolid ) ! 695: trace.ent = ent; ! 696: ! 697: return trace; ! 698: } ! 699: ! 700: //=========================================================================== ! 701: ! 702: /* ! 703: ==================== ! 704: SV_ClipToLinks ! 705: ! 706: Mins and maxs enclose the entire area swept by the move ! 707: ==================== ! 708: */ ! 709: void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip ) ! 710: { ! 711: link_t *l, *next; ! 712: edict_t *touch; ! 713: trace_t trace; ! 714: ! 715: // touch linked edicts ! 716: for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) ! 717: { ! 718: next = l->next; ! 719: touch = EDICT_FROM_AREA(l); ! 720: if (touch->v.solid == SOLID_NOT) ! 721: continue; ! 722: if (touch == clip->passedict) ! 723: continue; ! 724: if (touch->v.solid == SOLID_TRIGGER) ! 725: Sys_Error ("Trigger in clipping list"); ! 726: ! 727: if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP) ! 728: continue; ! 729: ! 730: if (clip->boxmins[0] > touch->v.absmax[0] ! 731: || clip->boxmins[1] > touch->v.absmax[1] ! 732: || clip->boxmins[2] > touch->v.absmax[2] ! 733: || clip->boxmaxs[0] < touch->v.absmin[0] ! 734: || clip->boxmaxs[1] < touch->v.absmin[1] ! 735: || clip->boxmaxs[2] < touch->v.absmin[2] ) ! 736: continue; ! 737: ! 738: if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0]) ! 739: continue; // points never interact ! 740: ! 741: // might intersect, so do an exact clip ! 742: if (clip->trace.allsolid) ! 743: return; ! 744: if (clip->passedict) ! 745: { ! 746: if (PROG_TO_EDICT(touch->v.owner) == clip->passedict) ! 747: continue; // don't clip against own missiles ! 748: if (PROG_TO_EDICT(clip->passedict->v.owner) == touch) ! 749: continue; // don't clip against owner ! 750: } ! 751: ! 752: if ((int)touch->v.flags & FL_MONSTER) ! 753: trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end); ! 754: else ! 755: trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end); ! 756: if (trace.allsolid || trace.startsolid || ! 757: trace.fraction < clip->trace.fraction) ! 758: { ! 759: trace.ent = touch; ! 760: if (clip->trace.startsolid) ! 761: { ! 762: clip->trace = trace; ! 763: clip->trace.startsolid = true; ! 764: } ! 765: else ! 766: clip->trace = trace; ! 767: } ! 768: else if (trace.startsolid) ! 769: clip->trace.startsolid = true; ! 770: } ! 771: ! 772: // recurse down both sides ! 773: if (node->axis == -1) ! 774: return; ! 775: ! 776: if ( clip->boxmaxs[node->axis] > node->dist ) ! 777: SV_ClipToLinks ( node->children[0], clip ); ! 778: if ( clip->boxmins[node->axis] < node->dist ) ! 779: SV_ClipToLinks ( node->children[1], clip ); ! 780: } ! 781: ! 782: ! 783: /* ! 784: ================== ! 785: SV_MoveBounds ! 786: ================== ! 787: */ ! 788: void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs) ! 789: { ! 790: #if 0 ! 791: // debug to test against everything ! 792: boxmins[0] = boxmins[1] = boxmins[2] = -9999; ! 793: boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999; ! 794: #else ! 795: int i; ! 796: ! 797: for (i=0 ; i<3 ; i++) ! 798: { ! 799: if (end[i] > start[i]) ! 800: { ! 801: boxmins[i] = start[i] + mins[i] - 1; ! 802: boxmaxs[i] = end[i] + maxs[i] + 1; ! 803: } ! 804: else ! 805: { ! 806: boxmins[i] = end[i] + mins[i] - 1; ! 807: boxmaxs[i] = start[i] + maxs[i] + 1; ! 808: } ! 809: } ! 810: #endif ! 811: } ! 812: ! 813: /* ! 814: ================== ! 815: SV_Move ! 816: ================== ! 817: */ ! 818: trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict) ! 819: { ! 820: moveclip_t clip; ! 821: int i; ! 822: ! 823: memset ( &clip, 0, sizeof ( moveclip_t ) ); ! 824: ! 825: // clip to world ! 826: clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end ); ! 827: ! 828: clip.start = start; ! 829: clip.end = end; ! 830: clip.mins = mins; ! 831: clip.maxs = maxs; ! 832: clip.type = type; ! 833: clip.passedict = passedict; ! 834: ! 835: if (type == MOVE_MISSILE) ! 836: { ! 837: for (i=0 ; i<3 ; i++) ! 838: { ! 839: clip.mins2[i] = -15; ! 840: clip.maxs2[i] = 15; ! 841: } ! 842: } ! 843: else ! 844: { ! 845: VectorCopy (mins, clip.mins2); ! 846: VectorCopy (maxs, clip.maxs2); ! 847: } ! 848: ! 849: // create the bounding box of the entire move ! 850: SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); ! 851: ! 852: // clip to entities ! 853: SV_ClipToLinks ( sv_areanodes, &clip ); ! 854: ! 855: return clip.trace; ! 856: } ! 857:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.