2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // world.c -- world query functions
26 entities never clip against themselves, or their owner
28 line of sight checks trace->inopen and trace->inwater, but bullets don't
32 cvar_t sv_useareanodes = {CVAR_NOTIFY, "sv_useareanodes", "1"};
33 cvar_t sv_polygoncollisions = {CVAR_NOTIFY, "sv_polygoncollisions", "0"};
35 void SV_World_Init(void)
37 Cvar_RegisterVariable(&sv_useareanodes);
38 Cvar_RegisterVariable(&sv_polygoncollisions);
44 // bounding box of entire move area
45 vec3_t boxmins, boxmaxs;
47 // size of the moving object
50 // size when clipping against monsters
53 // size when clipping against brush models
54 vec3_t hullmins, hullmaxs;
56 // start and end origin of move
62 // type of move (like ignoring monsters, or similar)
65 // the edict that is moving (if any)
70 //#define EDICT_FROM_AREA(l) ((edict_t *)((qbyte *)l - (int)&(((edict_t *)0)->area)))
71 #define EDICT_FROM_AREA(l) ((edict_t *)l->entity)
73 //============================================================================
75 // ClearLink is used for new headnodes
76 void ClearLink (link_t *l)
79 l->prev = l->next = l;
82 void RemoveLink (link_t *l)
84 l->next->prev = l->prev;
85 l->prev->next = l->next;
88 void InsertLinkBefore (link_t *l, link_t *before, void *ent)
92 l->prev = before->prev;
97 void InsertLinkAfter (link_t *l, link_t *after)
99 l->next = after->next;
107 ===============================================================================
111 ===============================================================================
114 typedef struct areanode_s
119 struct areanode_s *children[2];
120 link_t trigger_edicts;
126 #define AREA_NODES (1 << (AREA_DEPTH + 1))
128 static areanode_t sv_areanodes[AREA_NODES];
129 static int sv_numareanodes;
137 areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs)
140 vec3_t size, mins1, maxs1, mins2, maxs2;
142 anode = &sv_areanodes[sv_numareanodes];
145 ClearLink (&anode->trigger_edicts);
146 ClearLink (&anode->solid_edicts);
148 if (depth == AREA_DEPTH)
151 anode->children[0] = anode->children[1] = NULL;
155 VectorSubtract (maxs, mins, size);
156 if (size[0] > size[1])
161 anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
162 VectorCopy (mins, mins1);
163 VectorCopy (mins, mins2);
164 VectorCopy (maxs, maxs1);
165 VectorCopy (maxs, maxs2);
167 maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
169 anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
170 anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
175 typedef struct areagrid_s
177 link_t trigger_edicts;
183 #define AREA_GRIDNODES (AREA_GRID * AREA_GRID)
185 static areagrid_t sv_areagrid[AREA_GRIDNODES];
186 static vec3_t sv_areagridbias, sv_areagridscale;
188 void SV_CreateAreaGrid (vec3_t mins, vec3_t maxs)
191 VectorNegate(mins, sv_areagridbias);
192 sv_areagridscale[0] = AREA_GRID / (maxs[0] + sv_areagridbias[0]);
193 sv_areagridscale[1] = AREA_GRID / (maxs[1] + sv_areagridbias[1]);
194 sv_areagridscale[2] = AREA_GRID / (maxs[2] + sv_areagridbias[2]);
195 for (i = 0;i < AREA_GRIDNODES;i++)
197 ClearLink (&sv_areagrid[i].trigger_edicts);
198 ClearLink (&sv_areagrid[i].solid_edicts);
208 void SV_ClearWorld (void)
210 memset(sv_areanodes, 0, sizeof(sv_areanodes));
212 Mod_CheckLoaded(sv.worldmodel);
213 SV_CreateAreaNode(0, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs);
214 SV_CreateAreaGrid(sv.worldmodel->normalmins, sv.worldmodel->normalmaxs);
224 void SV_UnlinkEdict (edict_t *ent)
227 for (i = 0;i < ENTITYGRIDAREAS;i++)
229 if (ent->areagrid[i].prev)
231 RemoveLink (&ent->areagrid[i]);
232 ent->areagrid[i].prev = ent->areagrid[i].next = NULL;
237 RemoveLink (&ent->area);
238 ent->area.prev = ent->area.next = NULL;
248 void SV_TouchAreaNodes ( edict_t *ent, areanode_t *node )
252 int old_self, old_other;
255 // touch linked edicts
256 for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next)
259 touch = EDICT_FROM_AREA(l);
262 if (!touch->v->touch || touch->v->solid != SOLID_TRIGGER)
264 if (ent->v->absmin[0] > touch->v->absmax[0]
265 || ent->v->absmin[1] > touch->v->absmax[1]
266 || ent->v->absmin[2] > touch->v->absmax[2]
267 || ent->v->absmax[0] < touch->v->absmin[0]
268 || ent->v->absmax[1] < touch->v->absmin[1]
269 || ent->v->absmax[2] < touch->v->absmin[2])
271 old_self = pr_global_struct->self;
272 old_other = pr_global_struct->other;
274 pr_global_struct->self = EDICT_TO_PROG(touch);
275 pr_global_struct->other = EDICT_TO_PROG(ent);
276 pr_global_struct->time = sv.time;
277 PR_ExecuteProgram (touch->v->touch, "");
279 pr_global_struct->self = old_self;
280 pr_global_struct->other = old_other;
283 // recurse down both sides
284 if (node->axis == -1)
287 if (ent->v->absmax[node->axis] > node->dist)
289 if (ent->v->absmin[node->axis] < node->dist)
290 SV_TouchAreaNodes(ent, node->children[1]); // order reversed to reduce code
291 node = node->children[0];
296 if (ent->v->absmin[node->axis] < node->dist)
298 node = node->children[1];
304 void SV_TouchAreaGrid(edict_t *ent, areanode_t *node)
309 int old_self, old_other, igrid[3], igridmins[3], igridmaxs[3];
311 igridmins[0] = (int) ((ent->v->absmin[0] + sv_areagridbias[0]) * sv_areagridscale[0]);
312 igridmins[1] = (int) ((ent->v->absmin[1] + sv_areagridbias[1]) * sv_areagridscale[1]);
313 //igridmins[2] = (int) ((ent->v->absmin[2] + sv_areagridbias[2]) * sv_areagridscale[2]);
314 igridmaxs[0] = (int) ((ent->v->absmax[0] + sv_areagridbias[0]) * sv_areagridscale[0]) + 1;
315 igridmaxs[1] = (int) ((ent->v->absmax[1] + sv_areagridbias[1]) * sv_areagridscale[1]) + 1;
316 //igridmaxs[2] = (int) ((ent->v->absmax[2] + sv_areagridbias[2]) * sv_areagridscale[2]) + 1;
317 igridmins[0] = max(0, igridmins[0]);
318 igridmins[1] = max(0, igridmins[1]);
319 //igridmins[2] = max(0, igridmins[2]);
320 igridmaxs[0] = min(AREA_GRID, igridmaxs[0]);
321 igridmaxs[1] = min(AREA_GRID, igridmaxs[1]);
322 //igridmaxs[2] = min(AREA_GRID, igridmaxs[2]);
324 for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
326 grid = sv_areagrid + igrid[1] * AREA_GRID + igridmins[0];
327 for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++)
329 for (l = grid->trigger_edicts.next;l != &grid->trigger_edicts;l = next)
332 touch = EDICT_FROM_AREA(l);
335 if (!touch->v->touch || touch->v->solid != SOLID_TRIGGER)
337 if (ent->v->absmin[0] > touch->v->absmax[0]
338 || ent->v->absmin[1] > touch->v->absmax[1]
339 || ent->v->absmin[2] > touch->v->absmax[2]
340 || ent->v->absmax[0] < touch->v->absmin[0]
341 || ent->v->absmax[1] < touch->v->absmin[1]
342 || ent->v->absmax[2] < touch->v->absmin[2])
344 old_self = pr_global_struct->self;
345 old_other = pr_global_struct->other;
347 pr_global_struct->self = EDICT_TO_PROG(touch);
348 pr_global_struct->other = EDICT_TO_PROG(ent);
349 pr_global_struct->time = sv.time;
350 PR_ExecuteProgram (touch->v->touch, "");
352 pr_global_struct->self = old_self;
353 pr_global_struct->other = old_other;
359 void SV_LinkEdict_AreaNode(edict_t *ent)
362 // find the first node that the ent's box crosses
366 if (node->axis == -1)
368 if (ent->v->absmin[node->axis] > node->dist)
369 node = node->children[0];
370 else if (ent->v->absmax[node->axis] < node->dist)
371 node = node->children[1];
373 break; // crosses the node
378 if (ent->v->solid == SOLID_TRIGGER)
379 InsertLinkBefore (&ent->area, &node->trigger_edicts, ent);
381 InsertLinkBefore (&ent->area, &node->solid_edicts, ent);
384 int SV_LinkEdict_AreaGrid(edict_t *ent)
387 int igrid[3], igridmins[3], igridmaxs[3], gridnum;
389 igridmins[0] = (int) ((ent->v->absmin[0] + sv_areagridbias[0]) * sv_areagridscale[0]);
390 igridmins[1] = (int) ((ent->v->absmin[1] + sv_areagridbias[1]) * sv_areagridscale[1]);
391 //igridmins[2] = (int) ((ent->v->absmin[2] + sv_areagridbias[2]) * sv_areagridscale[2]);
392 igridmaxs[0] = (int) ((ent->v->absmax[0] + sv_areagridbias[0]) * sv_areagridscale[0]) + 1;
393 igridmaxs[1] = (int) ((ent->v->absmax[1] + sv_areagridbias[1]) * sv_areagridscale[1]) + 1;
394 //igridmaxs[2] = (int) ((ent->v->absmax[2] + sv_areagridbias[2]) * sv_areagridscale[2]) + 1;
395 if (igridmins[0] < 0 || igridmaxs[0] > AREA_GRID || igridmins[1] < 0 || igridmaxs[1] > AREA_GRID || ((igridmaxs[0] - igridmins[0]) * (igridmaxs[1] - igridmins[1])) > ENTITYGRIDAREAS)
399 for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
401 grid = sv_areagrid + igrid[1] * AREA_GRID + igridmins[0];
402 for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++, gridnum++)
404 if (ent->v->solid == SOLID_TRIGGER)
405 InsertLinkBefore (&ent->areagrid[gridnum], &grid->trigger_edicts, ent);
407 InsertLinkBefore (&ent->areagrid[gridnum], &grid->solid_edicts, ent);
419 void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
423 if (ent->area.prev || ent->areagrid[0].prev)
424 SV_UnlinkEdict (ent); // unlink from old position
426 if (ent == sv.edicts)
427 return; // don't add the world
434 if (ent->v->solid == SOLID_BSP)
436 if (ent->v->modelindex < 0 || ent->v->modelindex > MAX_MODELS)
437 Host_Error("SOLID_BSP with invalid modelindex!\n");
438 model = sv.models[(int) ent->v->modelindex];
441 if (model->type != mod_brush)
442 Host_Error("SOLID_BSP with non-BSP model\n");
444 if (ent->v->angles[0] || ent->v->angles[2] || ent->v->avelocity[0] || ent->v->avelocity[2])
446 VectorAdd(ent->v->origin, model->rotatedmins, ent->v->absmin);
447 VectorAdd(ent->v->origin, model->rotatedmaxs, ent->v->absmax);
449 else if (ent->v->angles[1] || ent->v->avelocity[1])
451 VectorAdd(ent->v->origin, model->yawmins, ent->v->absmin);
452 VectorAdd(ent->v->origin, model->yawmaxs, ent->v->absmax);
456 VectorAdd(ent->v->origin, model->normalmins, ent->v->absmin);
457 VectorAdd(ent->v->origin, model->normalmaxs, ent->v->absmax);
462 // SOLID_BSP with no model is valid, mainly because some QC setup code does so temporarily
463 VectorAdd(ent->v->origin, ent->v->mins, ent->v->absmin);
464 VectorAdd(ent->v->origin, ent->v->maxs, ent->v->absmax);
469 VectorAdd(ent->v->origin, ent->v->mins, ent->v->absmin);
470 VectorAdd(ent->v->origin, ent->v->maxs, ent->v->absmax);
474 // to make items easier to pick up and allow them to be grabbed off
475 // of shelves, the abs sizes are expanded
477 if ((int)ent->v->flags & FL_ITEM)
479 ent->v->absmin[0] -= 15;
480 ent->v->absmin[1] -= 15;
481 ent->v->absmin[2] -= 1;
482 ent->v->absmax[0] += 15;
483 ent->v->absmax[1] += 15;
484 ent->v->absmax[2] += 1;
488 // because movement is clipped an epsilon away from an actual edge,
489 // we must fully check even when bounding boxes don't quite touch
490 ent->v->absmin[0] -= 1;
491 ent->v->absmin[1] -= 1;
492 ent->v->absmin[2] -= 1;
493 ent->v->absmax[0] += 1;
494 ent->v->absmax[1] += 1;
495 ent->v->absmax[2] += 1;
498 if (ent->v->solid == SOLID_NOT)
501 // try to link into areagrid, if that fails fall back on areanode
502 if (!SV_LinkEdict_AreaGrid(ent))
503 SV_LinkEdict_AreaNode(ent);
505 // if touch_triggers, touch all entities at this node and descend for more
508 SV_TouchAreaNodes(ent, sv_areanodes);
509 SV_TouchAreaGrid(ent, sv_areanodes);
516 ===============================================================================
518 POINT TESTING IN HULLS
520 ===============================================================================
525 SV_TestEntityPosition
527 This could be a lot more efficient...
530 int SV_TestEntityPosition (edict_t *ent)
532 return SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, ent->v->origin, MOVE_NORMAL, ent).startsolid;
537 ===============================================================================
539 LINE TESTING IN HULLS
541 ===============================================================================
548 Handles selection or creation of a clipping hull, and offseting (and
549 eventually rotation) of the end points
552 trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
558 i = ent->v->modelindex;
559 if ((unsigned int) i >= MAX_MODELS)
560 Host_Error("SV_ClipMoveToEntity: invalid modelindex\n");
561 model = sv.models[i];
562 if (i != 0 && model == NULL)
563 Host_Error("SV_ClipMoveToEntity: invalid modelindex\n");
565 if ((int) ent->v->solid == SOLID_BSP)
567 Mod_CheckLoaded(model);
568 if (model->type != mod_brush)
570 Con_Printf ("SV_ClipMoveToEntity: SOLID_BSP with a non bsp model, entity dump:\n");
572 Host_Error ("SV_ClipMoveToEntity: SOLID_BSP with a non bsp model\n");
574 if (ent->v->movetype != MOVETYPE_PUSH)
575 Host_Error ("SV_ClipMoveToEntity: SOLID_BSP without MOVETYPE_PUSH");
578 if (sv_polygoncollisions.integer && (mins[0] != maxs[0] || mins[1] != maxs[1] || mins[2] != maxs[2]))
579 Collision_PolygonClipTrace(&trace, ent, model, ent->v->origin, ent->v->angles, ent->v->mins, ent->v->maxs, start, mins, maxs, end);
581 Collision_ClipTrace(&trace, ent, model, ent->v->origin, ent->v->angles, ent->v->mins, ent->v->maxs, start, mins, maxs, end);
586 //===========================================================================
592 Mins and maxs enclose the entire area swept by the move
595 void SV_ClipToAreaNodes ( areanode_t *node, moveclip_t *clip )
602 if (clip->trace.allsolid)
604 // touch linked edicts
605 for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
608 touch = EDICT_FROM_AREA(l);
609 if (touch->v->solid == SOLID_NOT)
611 if (touch == clip->passedict)
613 if (touch->v->solid == SOLID_TRIGGER)
616 Host_Error ("Trigger in clipping list");
619 if (clip->type == MOVE_NOMONSTERS && touch->v->solid != SOLID_BSP)
622 if (clip->boxmins[0] > touch->v->absmax[0]
623 || clip->boxmaxs[0] < touch->v->absmin[0]
624 || clip->boxmins[1] > touch->v->absmax[1]
625 || clip->boxmaxs[1] < touch->v->absmin[1]
626 || clip->boxmins[2] > touch->v->absmax[2]
627 || clip->boxmaxs[2] < touch->v->absmin[2])
632 if (clip->passedict->v->size[0] && !touch->v->size[0])
633 continue; // points never interact
634 if (PROG_TO_EDICT(touch->v->owner) == clip->passedict)
635 continue; // don't clip against own missiles
636 if (PROG_TO_EDICT(clip->passedict->v->owner) == touch)
637 continue; // don't clip against owner
638 // LordHavoc: corpse code
639 if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE))
641 if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE)
645 // might interact, so do an exact clip
646 if (touch->v->solid == SOLID_BSP)
647 trace = SV_ClipMoveToEntity (touch, clip->start, clip->hullmins, clip->hullmaxs, clip->end);
648 else if ((int)touch->v->flags & FL_MONSTER)
649 trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end);
651 trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end);
652 // LordHavoc: take the 'best' answers from the new trace and combine with existing data
654 clip->trace.allsolid = true;
655 if (trace.startsolid)
657 clip->trace.startsolid = true;
658 if (!clip->trace.ent)
659 clip->trace.ent = trace.ent;
662 clip->trace.inopen = true;
664 clip->trace.inwater = true;
665 if (trace.fraction < clip->trace.fraction)
667 clip->trace.fraction = trace.fraction;
668 VectorCopy(trace.endpos, clip->trace.endpos);
669 clip->trace.plane = trace.plane;
670 clip->trace.endcontents = trace.endcontents;
671 clip->trace.ent = trace.ent;
675 // recurse down both sides
676 if (node->axis == -1)
679 if (clip->boxmaxs[node->axis] > node->dist)
681 if (clip->boxmins[node->axis] < node->dist)
682 SV_ClipToAreaNodes(node->children[1], clip);
683 node = node->children[0];
686 else if (clip->boxmins[node->axis] < node->dist)
688 node = node->children[1];
697 Mins and maxs enclose the entire area swept by the move
700 void SV_ClipToAreaGrid(moveclip_t *clip)
705 int igrid[3], igridmins[3], igridmaxs[3];
708 if (clip->trace.allsolid)
711 igridmins[0] = (int) ((clip->boxmins[0] + sv_areagridbias[0]) * sv_areagridscale[0]);
712 igridmins[1] = (int) ((clip->boxmins[1] + sv_areagridbias[1]) * sv_areagridscale[1]);
713 //igridmins[2] = (int) ((clip->boxmins[2] + sv_areagridbias[2]) * sv_areagridscale[2]);
714 igridmaxs[0] = (int) ((clip->boxmaxs[0] + sv_areagridbias[0]) * sv_areagridscale[0]) + 1;
715 igridmaxs[1] = (int) ((clip->boxmaxs[1] + sv_areagridbias[1]) * sv_areagridscale[1]) + 1;
716 //igridmaxs[2] = (int) ((clip->boxmaxs[2] + sv_areagridbias[2]) * sv_areagridscale[2]) + 1;
717 igridmins[0] = max(0, igridmins[0]);
718 igridmins[1] = max(0, igridmins[1]);
719 //igridmins[2] = max(0, igridmins[2]);
720 igridmaxs[0] = min(AREA_GRID, igridmaxs[0]);
721 igridmaxs[1] = min(AREA_GRID, igridmaxs[1]);
722 //igridmaxs[2] = min(AREA_GRID, igridmaxs[2]);
724 for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
726 grid = sv_areagrid + igrid[1] * AREA_GRID + igridmins[0];
727 for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++)
729 for (l = grid->solid_edicts.next;l != &grid->solid_edicts;l = next)
732 touch = EDICT_FROM_AREA(l);
733 if (touch->v->solid == SOLID_NOT)
735 if (touch == clip->passedict)
737 if (touch->v->solid == SOLID_TRIGGER)
740 Host_Error ("Trigger in clipping list");
743 if (clip->type == MOVE_NOMONSTERS && touch->v->solid != SOLID_BSP)
746 if (clip->boxmins[0] > touch->v->absmax[0]
747 || clip->boxmaxs[0] < touch->v->absmin[0]
748 || clip->boxmins[1] > touch->v->absmax[1]
749 || clip->boxmaxs[1] < touch->v->absmin[1]
750 || clip->boxmins[2] > touch->v->absmax[2]
751 || clip->boxmaxs[2] < touch->v->absmin[2])
756 if (clip->passedict->v->size[0] && !touch->v->size[0])
757 continue; // points never interact
758 if (PROG_TO_EDICT(touch->v->owner) == clip->passedict)
759 continue; // don't clip against own missiles
760 if (PROG_TO_EDICT(clip->passedict->v->owner) == touch)
761 continue; // don't clip against owner
762 // LordHavoc: corpse code
763 if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE))
765 if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE)
769 // might interact, so do an exact clip
770 if (touch->v->solid == SOLID_BSP)
771 trace = SV_ClipMoveToEntity (touch, clip->start, clip->hullmins, clip->hullmaxs, clip->end);
772 else if ((int)touch->v->flags & FL_MONSTER)
773 trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end);
775 trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end);
776 // LordHavoc: take the 'best' answers from the new trace and combine with existing data
778 clip->trace.allsolid = true;
779 if (trace.startsolid)
781 clip->trace.startsolid = true;
782 if (!clip->trace.ent)
783 clip->trace.ent = trace.ent;
786 clip->trace.inopen = true;
788 clip->trace.inwater = true;
789 if (trace.fraction < clip->trace.fraction)
791 clip->trace.fraction = trace.fraction;
792 VectorCopy(trace.endpos, clip->trace.endpos);
793 clip->trace.plane = trace.plane;
794 clip->trace.endcontents = trace.endcontents;
795 clip->trace.ent = trace.ent;
797 if (clip->trace.allsolid)
810 void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
812 if (sv_useareanodes.integer)
816 for (i=0 ; i<3 ; i++)
818 if (end[i] > start[i])
820 boxmins[i] = start[i] + mins[i] - 1;
821 boxmaxs[i] = end[i] + maxs[i] + 1;
825 boxmins[i] = end[i] + mins[i] - 1;
826 boxmaxs[i] = start[i] + maxs[i] + 1;
832 // debug to test against everything
833 boxmins[0] = boxmins[1] = boxmins[2] = -999999999;
834 boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 999999999;
843 trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict)
846 vec3_t bigmins, bigmaxs;
849 memset ( &clip, 0, sizeof ( moveclip_t ) );
851 VectorCopy(start, clip.start);
852 VectorCopy(end, clip.end);
853 VectorCopy(mins, clip.mins);
854 VectorCopy(maxs, clip.maxs);
856 clip.passedict = passedict;
858 Collision_RoundUpToHullSize(sv.worldmodel, clip.mins, clip.maxs, clip.hullmins, clip.hullmaxs);
860 if (type == MOVE_MISSILE)
862 // LordHavoc: modified this, was = -15, now = clip.mins[i] - 15
863 for (i=0 ; i<3 ; i++)
865 clip.mins2[i] = clip.mins[i] - 15;
866 clip.maxs2[i] = clip.maxs[i] + 15;
871 VectorCopy (clip.mins, clip.mins2);
872 VectorCopy (clip.maxs, clip.maxs2);
875 bigmins[0] = min(clip.mins2[0], clip.hullmins[0]);
876 bigmaxs[0] = max(clip.maxs2[0], clip.hullmaxs[0]);
877 bigmins[1] = min(clip.mins2[1], clip.hullmins[1]);
878 bigmaxs[1] = max(clip.maxs2[1], clip.hullmaxs[1]);
879 bigmins[2] = min(clip.mins2[2], clip.hullmins[2]);
880 bigmaxs[2] = max(clip.maxs2[2], clip.hullmaxs[2]);
883 clip.trace = SV_ClipMoveToEntity (sv.edicts, start, mins, maxs, end);
886 // create the bounding box of the entire move
887 SV_MoveBounds ( start, bigmins, bigmaxs, end, clip.boxmins, clip.boxmaxs );
889 SV_ClipToAreaNodes(sv_areanodes, &clip);
890 SV_ClipToAreaGrid(&clip);