예제 #1
0
파일: ServerMain.cs 프로젝트: Scrama/Quarp
        static byte[] _FatPvs = new byte[BspFile.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();
            }
        }
예제 #2
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]);
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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);
            }
        }
예제 #5
0
        /// <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]);
            }
        }