// SV_Init public void Initialise( ) { for (var i = 0; i < _BoxClipNodes.Length; i++) { _BoxClipNodes[i].children = new Int16[2]; } for (var i = 0; i < _BoxPlanes.Length; i++) { _BoxPlanes[i] = new Plane(); } for (var i = 0; i < _AreaNodes.Length; i++) { _AreaNodes[i] = new areanode_t(); } if (Host.Cvars.Friction == null) { Host.Cvars.Friction = Host.CVars.Add("sv_friction", 4f, ClientVariableFlags.Server); Host.Cvars.EdgeFriction = Host.CVars.Add("edgefriction", 2f); Host.Cvars.StopSpeed = Host.CVars.Add("sv_stopspeed", 100f); Host.Cvars.Gravity = Host.CVars.Add("sv_gravity", 800f, ClientVariableFlags.Server); Host.Cvars.MaxVelocity = Host.CVars.Add("sv_maxvelocity", 2000f); Host.Cvars.NoStep = Host.CVars.Add("sv_nostep", false); Host.Cvars.MaxSpeed = Host.CVars.Add("sv_maxspeed", 320f, ClientVariableFlags.Server); Host.Cvars.Accelerate = Host.CVars.Add("sv_accelerate", 10f); Host.Cvars.Aim = Host.CVars.Add("sv_aim", 0.93f); Host.Cvars.IdealPitchScale = Host.CVars.Add("sv_idealpitchscale", 0.8f); } for (var i = 0; i < QDef.MAX_MODELS; i++) { _LocalModels[i] = "*" + i.ToString(); } }
private static byte[] _FatPvs = new byte[bsp_file.MAX_MAP_LEAFS / 8]; // fatpvs // SV_Init public static void Init() { for (int i = 0; i < _BoxClipNodes.Length; i++) { _BoxClipNodes[i].children = new short[2]; } for (int i = 0; i < _BoxPlanes.Length; i++) { _BoxPlanes[i] = new mplane_t(); } for (int i = 0; i < _AreaNodes.Length; i++) { _AreaNodes[i] = new areanode_t(); } if (_Friction == null) { _Friction = new cvar("sv_friction", "4", false, true); _EdgeFriction = new cvar("edgefriction", "2"); _StopSpeed = new cvar("sv_stopspeed", "100"); _Gravity = new cvar("sv_gravity", "800", false, true); _MaxVelocity = new cvar("sv_maxvelocity", "2000"); _NoStep = new cvar("sv_nostep", "0"); _MaxSpeed = new cvar("sv_maxspeed", "320", false, true); _Accelerate = new cvar("sv_accelerate", "10"); _Aim = new cvar("sv_aim", "0.93"); _IdealPitchScale = new cvar("sv_idealpitchscale", "0.8"); } for (int i = 0; i < QDef.MAX_MODELS; i++) { _LocalModels[i] = "*" + i.ToString(); } }
/// <summary> /// SV_TouchLinks /// </summary> static void TouchLinks(edict_t ent, areanode_t node) { // touch linked edicts LinkList next; for (LinkList l = node.trigger_edicts.Next; l != node.trigger_edicts; l = next) { next = l.Next; edict_t touch = (edict_t)l.Owner;// EDICT_FROM_AREA(l); if (touch == ent) { continue; } if (touch.v.touch == 0 || touch.v.solid != Solids.SOLID_TRIGGER) { continue; } if (ent.v.absmin.x > touch.v.absmax.x || ent.v.absmin.y > touch.v.absmax.y || ent.v.absmin.z > touch.v.absmax.z || ent.v.absmax.x < touch.v.absmin.x || ent.v.absmax.y < touch.v.absmin.y || ent.v.absmax.z < touch.v.absmin.z) { continue; } int old_self = Progs.GlobalStruct.self; int old_other = Progs.GlobalStruct.other; Progs.GlobalStruct.self = EdictToProg(touch); Progs.GlobalStruct.other = EdictToProg(ent); Progs.GlobalStruct.time = (float)sv.time; Progs.Execute(touch.v.touch); Progs.GlobalStruct.self = old_self; Progs.GlobalStruct.other = old_other; } // recurse down both sides if (node.axis == -1) { return; } if (Mathlib.Comp(ref ent.v.absmax, node.axis) > node.dist) { TouchLinks(ent, node.children[0]); } if (Mathlib.Comp(ref ent.v.absmin, node.axis) < node.dist) { TouchLinks(ent, node.children[1]); } }
/// <summary> /// SV_TouchLinks /// </summary> private void TouchLinks(MemoryEdict ent, areanode_t node) { // touch linked edicts Link next; for (var l = node.trigger_edicts.Next; l != node.trigger_edicts; l = next) { next = l.Next; var touch = ( MemoryEdict )l.Owner; // EDICT_FROM_AREA(l); if (touch == ent) { continue; } if (touch.v.touch == 0 || touch.v.solid != Solids.SOLID_TRIGGER) { continue; } if (ent.v.absmin.x > touch.v.absmax.x || ent.v.absmin.y > touch.v.absmax.y || ent.v.absmin.z > touch.v.absmax.z || ent.v.absmax.x < touch.v.absmin.x || ent.v.absmax.y < touch.v.absmin.y || ent.v.absmax.z < touch.v.absmin.z) { continue; } var old_self = Host.Programs.GlobalStruct.self; var old_other = Host.Programs.GlobalStruct.other; Host.Programs.GlobalStruct.self = EdictToProg(touch); Host.Programs.GlobalStruct.other = EdictToProg(ent); Host.Programs.GlobalStruct.time = ( Single )sv.time; Host.Programs.Execute(touch.v.touch); Host.Programs.GlobalStruct.self = old_self; Host.Programs.GlobalStruct.other = old_other; } // recurse down both sides if (node.axis == -1) { return; } if (MathLib.Comp(ref ent.v.absmax, node.axis) > node.dist) { TouchLinks(ent, node.children[0]); } if (MathLib.Comp(ref ent.v.absmin, node.axis) < node.dist) { TouchLinks(ent, node.children[1]); } }
/// <summary> /// SV_CreateAreaNode /// </summary> static areanode_t CreateAreaNode(int depth, ref Vector3 mins, ref Vector3 maxs) { areanode_t anode = _AreaNodes[_NumAreaNodes]; _NumAreaNodes++; anode.trigger_edicts.Clear(); anode.solid_edicts.Clear(); if (depth == AREA_DEPTH) { anode.axis = -1; anode.children[0] = anode.children[1] = null; return(anode); } Vector3 size = maxs - mins; Vector3 mins1 = mins; Vector3 mins2 = mins; Vector3 maxs1 = maxs; Vector3 maxs2 = maxs; if (size.X > size.Y) { anode.axis = 0; anode.dist = 0.5f * (maxs.X + mins.X); maxs1.X = mins2.X = anode.dist; } else { anode.axis = 1; anode.dist = 0.5f * (maxs.Y + mins.Y); maxs1.Y = mins2.Y = anode.dist; } anode.children[0] = CreateAreaNode(depth + 1, ref mins2, ref maxs2); anode.children[1] = CreateAreaNode(depth + 1, ref mins1, ref maxs1); return(anode); }
/// <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_LinkEdict /// /// Needs to be called any time an entity changes origin, mins, maxs, or solid /// flags ent->v.modified /// sets ent->v.absmin and ent->v.absmax /// if touchtriggers, calls prog functions for the intersected triggers /// </summary> public static void LinkEdict(edict_t ent, bool touch_triggers) { if (ent.area.Prev != null) { UnlinkEdict(ent); // unlink from old position } if (ent == sv.edicts[0]) { return; // don't add the world } if (ent.free) { return; } // set the abs box Mathlib.VectorAdd(ref ent.v.origin, ref ent.v.mins, out ent.v.absmin); Mathlib.VectorAdd(ref ent.v.origin, ref ent.v.maxs, out ent.v.absmax); // // to make items easier to pick up and allow them to be grabbed off // of shelves, the abs sizes are expanded // if (((int)ent.v.flags & EdictFlags.FL_ITEM) != 0) { ent.v.absmin.x -= 15; ent.v.absmin.y -= 15; ent.v.absmax.x += 15; ent.v.absmax.y += 15; } else { // because movement is clipped an epsilon away from an actual edge, // we must fully check even when bounding boxes don't quite touch ent.v.absmin.x -= 1; ent.v.absmin.y -= 1; ent.v.absmin.z -= 1; ent.v.absmax.x += 1; ent.v.absmax.y += 1; ent.v.absmax.z += 1; } // link to PVS leafs ent.num_leafs = 0; if (ent.v.modelindex != 0) { FindTouchedLeafs(ent, sv.worldmodel.nodes[0]); } if (ent.v.solid == Solids.SOLID_NOT) { return; } // find the first node that the ent's box crosses areanode_t node = _AreaNodes[0]; while (true) { if (node.axis == -1) { break; } if (Mathlib.Comp(ref ent.v.absmin, node.axis) > node.dist) { node = node.children[0]; } else if (Mathlib.Comp(ref ent.v.absmax, node.axis) < node.dist) { node = node.children[1]; } else { break; // crosses the node } } // link it in if (ent.v.solid == Solids.SOLID_TRIGGER) { ent.area.InsertBefore(node.trigger_edicts); } else { ent.area.InsertBefore(node.solid_edicts); } // if touch_triggers, touch all entities at this node and decend for more if (touch_triggers) { TouchLinks(ent, _AreaNodes[0]); } }
/// <summary> /// SV_TouchLinks /// </summary> static void TouchLinks(edict_t ent, areanode_t node) { // touch linked edicts link_t next; for (link_t l = node.trigger_edicts.Next; l != node.trigger_edicts; l = next) { next = l.Next; edict_t touch = (edict_t)l.Owner;// EDICT_FROM_AREA(l); if (touch == ent) continue; if (touch.v.touch == 0 || touch.v.solid != Solids.SOLID_TRIGGER) continue; if (ent.v.absmin.x > touch.v.absmax.x || ent.v.absmin.y > touch.v.absmax.y || ent.v.absmin.z > touch.v.absmax.z || ent.v.absmax.x < touch.v.absmin.x || ent.v.absmax.y < touch.v.absmin.y || ent.v.absmax.z < touch.v.absmin.z) continue; int old_self = Progs.GlobalStruct.self; int old_other = Progs.GlobalStruct.other; Progs.GlobalStruct.self = EdictToProg(touch); Progs.GlobalStruct.other = EdictToProg(ent); Progs.GlobalStruct.time = (float)sv.time; Progs.Execute(touch.v.touch); Progs.GlobalStruct.self = old_self; Progs.GlobalStruct.other = old_other; } // recurse down both sides if (node.axis == -1) return; if (Mathlib.Comp(ref ent.v.absmax, node.axis) > node.dist) TouchLinks(ent, node.children[0]); if (Mathlib.Comp(ref ent.v.absmin, node.axis) < node.dist) TouchLinks(ent, node.children[1]); }
/// <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); }