/// <summary> /// SV_Move /// mins and maxs are relative /// if the entire move stays in a solid volume, trace.allsolid will be set /// if the starting point is in a solid, it will be allowed to move out to an open area /// nomonsters is used for line of sight or edge testing, where mosnters /// shouldn't be considered solid objects /// passedict is explicitly excluded from clipping checks (normally NULL) /// </summary> public Trace_t Move(ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end, Int32 type, MemoryEdict passedict) { var clip = new moveclip_t(); // clip to world clip.trace = ClipMoveToEntity(sv.edicts[0], ref start, ref mins, ref maxs, ref end); clip.start = start; clip.end = end; clip.mins = mins; clip.maxs = maxs; clip.type = type; clip.passedict = passedict; if (type == MOVE_MISSILE) { clip.mins2 = Vector3.One * -15; clip.maxs2 = Vector3.One * 15; } else { clip.mins2 = mins; clip.maxs2 = maxs; } // create the bounding box of the entire move MoveBounds(ref start, ref clip.mins2, ref clip.maxs2, ref end, out clip.boxmins, out clip.boxmaxs); // clip to entities ClipToLinks(_AreaNodes[0], clip); return(clip.trace); }
public static trace_t SV_Move(ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end, int type, edict_t passedict) { moveclip_t clip = new moveclip_t(); // clip to world clip.trace = SV_ClipMoveToEntity(sv.edicts[0], ref start, ref mins, ref maxs, ref end); clip.start = start; clip.end = end; clip.mins = mins; clip.maxs = maxs; clip.type = type; clip.passedict = passedict; if (type == q_shared.MOVE_MISSILE) { clip.mins2 = Vector3.One * -15; clip.maxs2 = Vector3.One * 15; } else { clip.mins2 = mins; clip.maxs2 = maxs; } // create the bounding box of the entire move SV_MoveBounds(ref start, ref clip.mins2, ref clip.maxs2, ref end, out clip.boxmins, out clip.boxmaxs); // clip to entities SV_ClipToLinks(sv_areanodes[0], clip); return(clip.trace); }
/// <summary> /// SV_ClipToLinks /// Mins and maxs enclose the entire area swept by the move /// </summary> private void ClipToLinks(areanode_t node, moveclip_t clip) { Link next; Trace_t trace; // touch linked edicts for (var l = node.solid_edicts.Next; l != node.solid_edicts; l = next) { next = l.Next; var touch = ( MemoryEdict )l.Owner; // EDICT_FROM_AREA(l); if (touch.v.solid == Solids.SOLID_NOT) { continue; } if (touch == clip.passedict) { continue; } if (touch.v.solid == Solids.SOLID_TRIGGER) { Utilities.Error("Trigger in clipping list"); } if (clip.type == MOVE_NOMONSTERS && touch.v.solid != Solids.SOLID_BSP) { continue; } if (clip.boxmins.X > touch.v.absmax.x || clip.boxmins.Y > touch.v.absmax.y || clip.boxmins.Z > touch.v.absmax.z || clip.boxmaxs.X < touch.v.absmin.x || clip.boxmaxs.Y < touch.v.absmin.y || clip.boxmaxs.Z < touch.v.absmin.z) { continue; } if (clip.passedict != null && clip.passedict.v.size.x != 0 && touch.v.size.x == 0) { continue; // points never interact } // might intersect, so do an exact clip if (clip.trace.allsolid) { return; } if (clip.passedict != null) { if (ProgToEdict(touch.v.owner) == clip.passedict) { continue; // don't clip against own missiles } if (ProgToEdict(clip.passedict.v.owner) == touch) { continue; // don't clip against owner } } if ((( Int32 )touch.v.flags & EdictFlags.FL_MONSTER) != 0) { trace = ClipMoveToEntity(touch, ref clip.start, ref clip.mins2, ref clip.maxs2, ref clip.end); } else { trace = ClipMoveToEntity(touch, ref clip.start, ref clip.mins, ref clip.maxs, ref clip.end); } if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { trace.ent = touch; if (clip.trace.startsolid) { clip.trace = trace; clip.trace.startsolid = true; } else { clip.trace = trace; } } else if (trace.startsolid) { clip.trace.startsolid = true; } } // recurse down both sides if (node.axis == -1) { return; } if (MathLib.Comp(ref clip.boxmaxs, node.axis) > node.dist) { ClipToLinks(node.children[0], clip); } if (MathLib.Comp(ref clip.boxmins, node.axis) < node.dist) { ClipToLinks(node.children[1], clip); } }
/// <summary> /// SV_ClipToLinks /// Mins and maxs enclose the entire area swept by the move /// </summary> static void ClipToLinks(areanode_t node, moveclip_t clip) { link_t next; trace_t trace; // touch linked edicts for (link_t l = node.solid_edicts.Next; l != node.solid_edicts; l = next) { next = l.Next; edict_t touch = (edict_t)l.Owner;// EDICT_FROM_AREA(l); if (touch.v.solid == Solids.SOLID_NOT) continue; if (touch == clip.passedict) continue; if (touch.v.solid == Solids.SOLID_TRIGGER) Sys.Error("Trigger in clipping list"); if (clip.type == MOVE_NOMONSTERS && touch.v.solid != Solids.SOLID_BSP) continue; if (clip.boxmins.X > touch.v.absmax.x || clip.boxmins.Y > touch.v.absmax.y || clip.boxmins.Z > touch.v.absmax.z || clip.boxmaxs.X < touch.v.absmin.x || clip.boxmaxs.Y < touch.v.absmin.y || clip.boxmaxs.Z < touch.v.absmin.z) continue; if (clip.passedict != null && clip.passedict.v.size.x != 0 && touch.v.size.x == 0) continue; // points never interact // might intersect, so do an exact clip if (clip.trace.allsolid) return; if (clip.passedict != null) { if (ProgToEdict(touch.v.owner) == clip.passedict) continue; // don't clip against own missiles if (ProgToEdict(clip.passedict.v.owner) == touch) continue; // don't clip against owner } if (((int)touch.v.flags & EdictFlags.FL_MONSTER) != 0) trace = ClipMoveToEntity(touch, ref clip.start, ref clip.mins2, ref clip.maxs2, ref clip.end); else trace = ClipMoveToEntity(touch, ref clip.start, ref clip.mins, ref clip.maxs, ref clip.end); if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { trace.ent = touch; if (clip.trace.startsolid) { clip.trace = trace; clip.trace.startsolid = true; } else clip.trace = trace; } else if (trace.startsolid) clip.trace.startsolid = true; } // recurse down both sides if (node.axis == -1) return; if (Mathlib.Comp(ref clip.boxmaxs, node.axis) > node.dist) ClipToLinks(node.children[0], clip); if (Mathlib.Comp(ref clip.boxmins, node.axis) < node.dist) ClipToLinks(node.children[1], clip); }
/// <summary> /// SV_Move /// mins and maxs are relative /// if the entire move stays in a solid volume, trace.allsolid will be set /// if the starting point is in a solid, it will be allowed to move out to an open area /// nomonsters is used for line of sight or edge testing, where mosnters /// shouldn't be considered solid objects /// passedict is explicitly excluded from clipping checks (normally NULL) /// </summary> public static trace_t Move(ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end, int type, edict_t passedict) { moveclip_t clip = new moveclip_t(); // clip to world clip.trace = ClipMoveToEntity(sv.edicts[0], ref start, ref mins, ref maxs, ref end); clip.start = start; clip.end = end; clip.mins = mins; clip.maxs = maxs; clip.type = type; clip.passedict = passedict; if (type == MOVE_MISSILE) { clip.mins2 = Vector3.One * -15; clip.maxs2 = Vector3.One * 15; } else { clip.mins2 = mins; clip.maxs2 = maxs; } // create the bounding box of the entire move MoveBounds(ref start, ref clip.mins2, ref clip.maxs2, ref end, out clip.boxmins, out clip.boxmaxs); // clip to entities ClipToLinks(_AreaNodes[0], clip); return clip.trace; }
/* ================== SV_Move ================== */ public static trace_t SV_Move(double[] start, double[] mins, double[] maxs, double[] end, int type, prog.edict_t passedict) { moveclip_t clip; int i; clip = new moveclip_t(); // clip to world //Debug.WriteLine("SV_Move ?? SV_ClipMoveToEntity"); clip.trace = SV_ClipMoveToEntity(server.sv.edicts[0], start, mins, maxs, end); clip.start = start; clip.end = end; clip.mins = mins; clip.maxs = maxs; clip.type = type; clip.passedict = passedict; if (type == MOVE_MISSILE) { for (i = 0; i < 3; i++) { clip.mins2[i] = -15; clip.maxs2[i] = 15; } } else { mathlib.VectorCopy(mins, clip.mins2); mathlib.VectorCopy(maxs, clip.maxs2); } // create the bounding box of the entire move SV_MoveBounds(start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs); // clip to entities //Debug.WriteLine("SV_Move - SV_ClipToLinks"); SV_ClipToLinks(sv_areanodes[0], clip); return clip.trace; }
static void SV_ClipToLinks(areanode_t node, moveclip_t clip) { common.link_t l, next; prog.edict_t touch; trace_t trace; // touch linked edicts for (l = node.solid_edicts.next; l != node.solid_edicts; l = next) { //Debug.WriteLine("ClipToLinks_for_num " + ClipToLinks_for_num); ClipToLinks_for_num++; next = l.next; touch = prog. EDICT_FROM_AREA(l); if (touch.v.solid == server.SOLID_NOT) { continue; } if (touch == clip.passedict) { continue; } if (touch.v.solid == server. SOLID_TRIGGER) sys_linux. Sys_Error ("Trigger in clipping list"); if (clip.type == MOVE_NOMONSTERS && touch.v.solid != server.SOLID_BSP) continue; if (clip.boxmins[0] > touch.v.absmax[0] || clip.boxmins[1] > touch.v.absmax[1] || clip.boxmins[2] > touch.v.absmax[2] || clip.boxmaxs[0] < touch.v.absmin[0] || clip.boxmaxs[1] < touch.v.absmin[1] || clip.boxmaxs[2] < touch.v.absmin[2]) { continue; } //if (clip.passedict && clip.passedict.v.size[0] && !touch.v.size[0]) if (clip.passedict !=null && clip.passedict.v.size[0] != 0 && !(touch.v.size[0] != 0)) { continue; // points never interact } // might intersect, so do an exact clip if (clip.trace.allsolid) { return; } if (clip.passedict != null) { if (prog.PROG_TO_EDICT(touch.v.owner) == clip.passedict) { continue; // don't clip against own missiles } if (prog.PROG_TO_EDICT(clip.passedict.v.owner) == touch) { continue; // don't clip against owner } } if (((int)touch.v.flags & server.FL_MONSTER) != 0) trace = SV_ClipMoveToEntity (touch, clip.start, clip.mins2, clip.maxs2, clip.end); else trace = SV_ClipMoveToEntity (touch, clip.start, clip.mins, clip.maxs, clip.end); if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { trace.ent = touch; if (clip.trace.startsolid) { clip.trace = trace; clip.trace.startsolid = true; } else clip.trace = trace; } else if (trace.startsolid) clip.trace.startsolid = true; } // recurse down both sides if (node.axis == -1) return; if (clip.boxmaxs[node.axis] > node.dist) { SV_ClipToLinks(node.children[0], clip); } if (clip.boxmins[node.axis] < node.dist) { SV_ClipToLinks(node.children[1], clip); } }
public static void SV_ClipToLinks(areanode_t node, moveclip_t clip) { link_t next; trace_t trace; // touch linked edicts for (link_t l = node.solid_edicts.Next; l != node.solid_edicts; l = next) { next = l.Next; edict_t touch = (edict_t)l.Owner;// EDICT_FROM_AREA(l); if (touch.v.solid == q_shared.SOLID_NOT) { continue; } if (touch == clip.passedict) { continue; } if (touch.v.solid == q_shared.SOLID_TRIGGER) { Sys_Error("Trigger in clipping list"); } if (clip.type == q_shared.MOVE_NOMONSTERS && touch.v.solid != q_shared.SOLID_BSP) { continue; } if (clip.boxmins.X > touch.v.absmax.x || clip.boxmins.Y > touch.v.absmax.y || clip.boxmins.Z > touch.v.absmax.z || clip.boxmaxs.X < touch.v.absmin.x || clip.boxmaxs.Y < touch.v.absmin.y || clip.boxmaxs.Z < touch.v.absmin.z) { continue; } if (clip.passedict != null && clip.passedict.v.size.x != 0 && touch.v.size.x == 0) { continue; // points never interact } // might intersect, so do an exact clip if (clip.trace.allsolid) { return; } if (clip.passedict != null) { if (PROG_TO_EDICT(touch.v.owner) == clip.passedict) { continue; // don't clip against own missiles } if (PROG_TO_EDICT(clip.passedict.v.owner) == touch) { continue; // don't clip against owner } } if (((int)touch.v.flags & q_shared.FL_MONSTER) != 0) { trace = SV_ClipMoveToEntity(touch, ref clip.start, ref clip.mins2, ref clip.maxs2, ref clip.end); } else { trace = SV_ClipMoveToEntity(touch, ref clip.start, ref clip.mins, ref clip.maxs, ref clip.end); } if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { trace.ent = touch; if (clip.trace.startsolid) { clip.trace = trace; clip.trace.startsolid = true; } else { clip.trace = trace; } } else if (trace.startsolid) { clip.trace.startsolid = true; } } // recurse down both sides if (node.axis == -1) { return; } if (Mathlib.Comp(ref clip.boxmaxs, node.axis) > node.dist) { SV_ClipToLinks(node.children[0], clip); } if (Mathlib.Comp(ref clip.boxmins, node.axis) < node.dist) { SV_ClipToLinks(node.children[1], clip); } }
public static void SV_ClipMoveToEntities(moveclip_t clip) { int i, num; edict_t touch; trace_t trace; int headnode; float[] angles; num = SV_WORLD.SV_AreaEdicts(clip.boxmins, clip.boxmaxs, SV_WORLD.touchlist, Defines.MAX_EDICTS, Defines.AREA_SOLID); // be careful, it is possible to have an entity in this // list removed before we get to it (killtriggered) for (i = 0; i < num; i++) { touch = SV_WORLD.touchlist[i]; if (touch.solid == Defines.SOLID_NOT) { continue; } if (touch == clip.passedict) { continue; } if (clip.trace.allsolid) { return; } if (clip.passedict != null) { if (touch.owner == clip.passedict) { continue; // don't clip against own missiles } if (clip.passedict.owner == touch) { continue; // don't clip against owner } } if (0 == (clip.contentmask & Defines.CONTENTS_DEADMONSTER) && 0 != (touch.svflags & Defines.SVF_DEADMONSTER)) { continue; } // might intersect, so do an exact clip headnode = SV_WORLD.SV_HullForEntity(touch); angles = touch.s.angles; if (touch.solid != Defines.SOLID_BSP) { angles = Globals.vec3_origin; // boxes don't rotate } if ((touch.svflags & Defines.SVF_MONSTER) != 0) { trace = CM.TransformedBoxTrace(clip.start, clip.end, clip.mins2, clip.maxs2, headnode, clip.contentmask, touch.s.origin, angles); } else { trace = CM.TransformedBoxTrace(clip.start, clip.end, clip.mins, clip.maxs, headnode, clip.contentmask, touch.s.origin, angles); } if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { trace.ent = touch; if (clip.trace.startsolid) { clip.trace = trace; clip.trace.startsolid = true; } else { clip.trace.set(trace); } } else if (trace.startsolid) { clip.trace.startsolid = true; } } }