示例#1
0
        /*
         * =================
         * PF_traceline
         *
         * Used for use tracing and shot targeting
         * Traces are blocked by bbox and exact bsp entityes, and also slide box entities
         * if the tryents flag is set.
         *
         * traceline (vector1, vector2, tryents)
         * =================
         */
        static unsafe void PF_traceline()
        {
            float * v1         = GetVector(OFS.OFS_PARM0);
            float * v2         = GetVector(OFS.OFS_PARM1);
            int     nomonsters = (int)GetFloat(OFS.OFS_PARM2);
            edict_t ent        = GetEdict(OFS.OFS_PARM3);

            Vector3 vec1, vec2;

            Copy(v1, out vec1);
            Copy(v2, out vec2);
            trace_t trace = Server.Move(ref vec1, ref Common.ZeroVector, ref Common.ZeroVector, ref vec2, nomonsters, ent);

            Progs.GlobalStruct.trace_allsolid   = trace.allsolid ? 1 : 0;
            Progs.GlobalStruct.trace_startsolid = trace.startsolid ? 1 : 0;
            Progs.GlobalStruct.trace_fraction   = trace.fraction;
            Progs.GlobalStruct.trace_inwater    = trace.inwater ? 1 : 0;
            Progs.GlobalStruct.trace_inopen     = trace.inopen ? 1 : 0;
            Mathlib.Copy(ref trace.endpos, out Progs.GlobalStruct.trace_endpos);
            Mathlib.Copy(ref trace.plane.normal, out Progs.GlobalStruct.trace_plane_normal);
            Progs.GlobalStruct.trace_plane_dist = trace.plane.dist;
            if (trace.ent != null)
            {
                Progs.GlobalStruct.trace_ent = Server.EdictToProg(trace.ent);
            }
            else
            {
                Progs.GlobalStruct.trace_ent = Server.EdictToProg(Server.sv.edicts[0]);
            }
        }
示例#2
0
        /*
         * ===============
         * PF_droptofloor
         *
         * void() droptofloor
         * ===============
         */
        static void PF_droptofloor()
        {
            edict_t ent = Server.ProgToEdict(Progs.GlobalStruct.self);

            Vector3 org, mins, maxs;

            Mathlib.Copy(ref ent.v.origin, out org);
            Mathlib.Copy(ref ent.v.mins, out mins);
            Mathlib.Copy(ref ent.v.maxs, out maxs);
            Vector3 end = org;

            end.Z -= 256;

            trace_t trace = Server.Move(ref org, ref mins, ref maxs, ref end, 0, ent);

            if (trace.fraction == 1 || trace.allsolid)
            {
                ReturnFloat(0);
            }
            else
            {
                Mathlib.Copy(ref trace.endpos, out ent.v.origin);
                Server.LinkEdict(ent, false);
                ent.v.flags        = (int)ent.v.flags | EdictFlags.FL_ONGROUND;
                ent.v.groundentity = Server.EdictToProg(trace.ent);
                ReturnFloat(1);
            }
        }
示例#3
0
        /// <summary>
        /// SV_ClipMoveToEntity
        /// Handles selection or creation of a clipping hull, and offseting (and
        /// eventually rotation) of the end points
        /// </summary>
        static trace_t ClipMoveToEntity(edict_t ent, ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end)
        {
            trace_t trace = new trace_t();

            // fill in a default trace
            trace.fraction = 1;
            trace.allsolid = true;
            trace.endpos   = end;

            // get the clipping hull
            Vector3 offset;
            hull_t  hull = HullForEntity(ent, ref mins, ref maxs, out offset);

            Vector3 start_l = start - offset;
            Vector3 end_l   = end - offset;

            // trace a line through the apropriate clipping hull
            RecursiveHullCheck(hull, hull.firstclipnode, 0, 1, ref start_l, ref end_l, trace);

            // fix trace up by the offset
            if (trace.fraction != 1)
            {
                trace.endpos += offset;
            }

            // did we clip the move?
            if (trace.fraction < 1 || trace.startsolid)
            {
                trace.ent = ent;
            }

            return(trace);
        }
示例#4
0
        private static void TraceLine(ref Vector3 start, ref Vector3 end, out Vector3 impact)
        {
            trace_t trace = new trace_t();

            Server.RecursiveHullCheck(Client.cl.worldmodel.hulls[0], 0, 0, 1, ref start, ref end, trace);

            impact = trace.endpos; // VectorCopy(trace.endpos, impact);
        }
示例#5
0
        public edict_t ent;     // entity the surface is on

        public void CopyFrom(trace_t src)
        {
            this.allsolid   = src.allsolid;
            this.startsolid = src.startsolid;
            this.inopen     = src.inopen;
            this.inwater    = src.inwater;
            this.fraction   = src.fraction;
            this.endpos     = src.endpos;
            this.plane      = src.plane;
            this.ent        = src.ent;
        }
示例#6
0
        /// <summary>
        /// SV_TestEntityPosition
        /// This could be a lot more efficient...
        /// </summary>
        static edict_t TestEntityPosition(edict_t ent)
        {
            trace_t trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref ent.v.origin, 0, ent);

            if (trace.startsolid)
            {
                return(sv.edicts[0]);
            }

            return(null);
        }
示例#7
0
        public bool startsolid; // if true, the initial point was in a solid area

        #endregion Fields

        #region Methods

        public void CopyFrom(trace_t src)
        {
            this.allsolid = src.allsolid;
            this.startsolid = src.startsolid;
            this.inopen = src.inopen;
            this.inwater = src.inwater;
            this.fraction = src.fraction;
            this.endpos = src.endpos;
            this.plane = src.plane;
            this.ent = src.ent;
        }
示例#8
0
        public edict_t ent;     // entity the surface is on

        public void CopyFrom(trace_t src)
        {
            allsolid   = src.allsolid;
            startsolid = src.startsolid;
            inopen     = src.inopen;
            inwater    = src.inwater;
            fraction   = src.fraction;
            endpos     = src.endpos;
            plane      = src.plane;
            ent        = src.ent;
        }
示例#9
0
        /// <summary>
        /// SV_TryUnstick
        /// Player has come to a dead stop, possibly due to the problem with limited
        /// float precision at some angle joins in the BSP hull.
        ///
        /// Try fixing by pushing one pixel in each direction.
        ///
        /// This is a hack, but in the interest of good gameplay...
        /// </summary>
        static int TryUnstick(edict_t ent, ref v3f oldvel)
        {
            v3f oldorg = ent.v.origin;
            v3f dir    = Common.ZeroVector3f;

            trace_t steptrace = new trace_t();

            for (int i = 0; i < 8; i++)
            {
                // try pushing a little in an axial direction
                switch (i)
                {
                case 0: dir.x = 2; dir.y = 0; break;

                case 1: dir.x = 0; dir.y = 2; break;

                case 2: dir.x = -2; dir.y = 0; break;

                case 3: dir.x = 0; dir.y = -2; break;

                case 4: dir.x = 2; dir.y = 2; break;

                case 5: dir.x = -2; dir.y = 2; break;

                case 6: dir.x = 2; dir.y = -2; break;

                case 7: dir.x = -2; dir.y = -2; break;
                }

                PushEntity(ent, ref dir);

                // retry the original move
                ent.v.velocity.x = oldvel.x;
                ent.v.velocity.y = oldvel.y;
                ent.v.velocity.z = 0;
                int clip = FlyMove(ent, 0.1f, steptrace);

                if (Math.Abs(oldorg.y - ent.v.origin.y) > 4 || Math.Abs(oldorg.x - ent.v.origin.x) > 4)
                {
                    return(clip);
                }

                // go back to the original pos and try again
                ent.v.origin = oldorg;
            }

            ent.v.velocity = Common.ZeroVector3f;
            return(7);           // still not moving
        }
示例#10
0
        /// <summary>
        /// SV_WallFriction
        /// </summary>
        static void WallFriction(edict_t ent, trace_t trace)
        {
            Vector3 forward, right, up, vangle = Common.ToVector(ref ent.v.v_angle);

            Mathlib.AngleVectors(ref vangle, out forward, out right, out up);
            float d = Vector3.Dot(trace.plane.normal, forward);

            d += 0.5f;
            if (d >= 0)
            {
                return;
            }

            // cut the tangential velocity
            Vector3 vel  = Common.ToVector(ref ent.v.velocity);
            float   i    = Vector3.Dot(trace.plane.normal, vel);
            Vector3 into = trace.plane.normal * i;
            Vector3 side = vel - into;

            ent.v.velocity.x = side.X * (1 + d);
            ent.v.velocity.y = side.Y * (1 + d);
        }
示例#11
0
        /// <summary>
        /// SV_UserFriction
        /// </summary>
        static void UserFriction()
        {
            float speed = Mathlib.LengthXY(ref _Player.v.velocity);

            if (speed == 0)
            {
                return;
            }

            // if the leading edge is over a dropoff, increase friction
            Vector3 start, stop;

            start.X = stop.X = _Player.v.origin.x + _Player.v.velocity.x / speed * 16;
            start.Y = stop.Y = _Player.v.origin.y + _Player.v.velocity.y / speed * 16;
            start.Z = _Player.v.origin.z + _Player.v.mins.z;
            stop.Z  = start.Z - 34;

            trace_t trace    = Move(ref start, ref Common.ZeroVector, ref Common.ZeroVector, ref stop, 1, _Player);
            float   friction = _Friction.Value;

            if (trace.fraction == 1.0)
            {
                friction *= _EdgeFriction.Value;
            }

            // apply friction
            float control  = speed < _StopSpeed.Value ? _StopSpeed.Value : speed;
            float newspeed = (float)(speed - Host.FrameTime * control * friction);

            if (newspeed < 0)
            {
                newspeed = 0;
            }

            newspeed /= speed;

            Mathlib.VectorScale(ref _Player.v.velocity, newspeed, out _Player.v.velocity);
        }
示例#12
0
        /// <summary>
        /// SV_FlyMove
        /// The basic solid body movement clip that slides along multiple planes
        /// Returns the clipflags if the velocity was modified (hit something solid)
        /// 1 = floor
        /// 2 = wall / step
        /// 4 = dead stop
        /// If steptrace is not NULL, the trace of any vertical wall hit will be stored
        /// </summary>
        static int FlyMove(edict_t ent, float time, trace_t steptrace)
        {
            v3f original_velocity = ent.v.velocity;
            v3f primal_velocity   = ent.v.velocity;

            int numbumps = 4;
            int blocked  = 0;

            Vector3[] planes    = new Vector3[MAX_CLIP_PLANES];
            int       numplanes = 0;
            float     time_left = time;

            for (int bumpcount = 0; bumpcount < numbumps; bumpcount++)
            {
                if (ent.v.velocity.IsEmpty)
                {
                    break;
                }

                v3f end;
                Mathlib.VectorMA(ref ent.v.origin, time_left, ref ent.v.velocity, out end);

                trace_t trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent);

                if (trace.allsolid)
                {       // entity is trapped in another solid
                    ent.v.velocity = default(v3f);
                    return(3);
                }

                if (trace.fraction > 0)
                {       // actually covered some distance
                    Mathlib.Copy(ref trace.endpos, out ent.v.origin);
                    original_velocity = ent.v.velocity;
                    numplanes         = 0;
                }

                if (trace.fraction == 1)
                {
                    break;              // moved the entire distance
                }
                if (trace.ent == null)
                {
                    Sys.Error("SV_FlyMove: !trace.ent");
                }

                if (trace.plane.normal.Z > 0.7)
                {
                    blocked |= 1;               // floor
                    if (trace.ent.v.solid == Solids.SOLID_BSP)
                    {
                        ent.v.flags        = (int)ent.v.flags | EdictFlags.FL_ONGROUND;
                        ent.v.groundentity = EdictToProg(trace.ent);
                    }
                }

                if (trace.plane.normal.Z == 0)
                {
                    blocked |= 2;               // step
                    if (steptrace != null)
                    {
                        steptrace.CopyFrom(trace);      // save for player extrafriction
                    }
                }

                //
                // run the impact function
                //
                Impact(ent, trace.ent);
                if (ent.free)
                {
                    break;              // removed by the impact function
                }
                time_left -= time_left * trace.fraction;

                // cliped to another plane
                if (numplanes >= MAX_CLIP_PLANES)
                {
                    // this shouldn't really happen
                    ent.v.velocity = default(v3f);
                    return(3);
                }

                planes[numplanes] = trace.plane.normal;
                numplanes++;

                //
                // modify original_velocity so it parallels all of the clip planes
                //
                v3f new_velocity = default(v3f);
                int i, j;
                for (i = 0; i < numplanes; i++)
                {
                    ClipVelocity(ref original_velocity, ref planes[i], out new_velocity, 1);
                    for (j = 0; j < numplanes; j++)
                    {
                        if (j != i)
                        {
                            float dot = new_velocity.x * planes[j].X + new_velocity.y * planes[j].Y + new_velocity.z * planes[j].Z;
                            if (dot < 0)
                            {
                                break;  // not ok
                            }
                        }
                    }
                    if (j == numplanes)
                    {
                        break;
                    }
                }

                if (i != numplanes)
                {
                    // go along this plane
                    ent.v.velocity = new_velocity;
                }
                else
                {
                    // go along the crease
                    if (numplanes != 2)
                    {
                        ent.v.velocity = default(v3f);
                        return(7);
                    }
                    Vector3 dir = Vector3.Cross(planes[0], planes[1]);
                    float   d   = dir.X * ent.v.velocity.x + dir.Y * ent.v.velocity.y + dir.Z * ent.v.velocity.z;
                    Mathlib.Copy(ref dir, out ent.v.velocity);
                    Mathlib.VectorScale(ref ent.v.velocity, d, out ent.v.velocity);
                }

                //
                // if original velocity is against the original velocity, stop dead
                // to avoid tiny occilations in sloping corners
                //
                if (Mathlib.DotProduct(ref ent.v.velocity, ref primal_velocity) <= 0)
                {
                    ent.v.velocity = default(v3f);
                    return(blocked);
                }
            }

            return(blocked);
        }
示例#13
0
        /// <summary>
        /// SV_TryUnstick
        /// Player has come to a dead stop, possibly due to the problem with limited
        /// float precision at some angle joins in the BSP hull.
        ///
        /// Try fixing by pushing one pixel in each direction.
        ///
        /// This is a hack, but in the interest of good gameplay...
        /// </summary>
        static int TryUnstick(edict_t ent, ref v3f oldvel)
        {
            v3f oldorg = ent.v.origin;
            v3f dir = Common.ZeroVector3f;

            trace_t steptrace = new trace_t();
            for (int i = 0; i < 8; i++)
            {
                // try pushing a little in an axial direction
                switch (i)
                {
                    case 0: dir.x = 2; dir.y = 0; break;
                    case 1: dir.x = 0; dir.y = 2; break;
                    case 2: dir.x = -2; dir.y = 0; break;
                    case 3: dir.x = 0; dir.y = -2; break;
                    case 4: dir.x = 2; dir.y = 2; break;
                    case 5: dir.x = -2; dir.y = 2; break;
                    case 6: dir.x = 2; dir.y = -2; break;
                    case 7: dir.x = -2; dir.y = -2; break;
                }

                PushEntity(ent, ref dir);

                // retry the original move
                ent.v.velocity.x = oldvel.x;
                ent.v.velocity.y = oldvel.y;
                ent.v.velocity.z = 0;
                int clip = FlyMove(ent, 0.1f, steptrace);

                if (Math.Abs(oldorg.y - ent.v.origin.y) > 4 || Math.Abs(oldorg.x - ent.v.origin.x) > 4)
                {
                    return clip;
                }

                // go back to the original pos and try again
                ent.v.origin = oldorg;
            }

            ent.v.velocity = Common.ZeroVector3f;
            return 7;		// still not moving
        }
示例#14
0
        /// <summary>
        /// SV_FlyMove
        /// The basic solid body movement clip that slides along multiple planes
        /// Returns the clipflags if the velocity was modified (hit something solid)
        /// 1 = floor
        /// 2 = wall / step
        /// 4 = dead stop
        /// If steptrace is not NULL, the trace of any vertical wall hit will be stored
        /// </summary>
        static int FlyMove(edict_t ent, float time, trace_t steptrace)
        {
            v3f original_velocity = ent.v.velocity;
            v3f primal_velocity = ent.v.velocity;

            int numbumps = 4;
            int blocked = 0;
            Vector3[] planes = new Vector3[MAX_CLIP_PLANES];
            int numplanes = 0;
            float time_left = time;

            for (int bumpcount = 0; bumpcount < numbumps; bumpcount++)
            {
                if (ent.v.velocity.IsEmpty)
                    break;

                v3f end;
                Mathlib.VectorMA(ref ent.v.origin, time_left, ref ent.v.velocity, out end);

                trace_t trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent);

                if (trace.allsolid)
                {	// entity is trapped in another solid
                    ent.v.velocity = default(v3f);
                    return 3;
                }

                if (trace.fraction > 0)
                {	// actually covered some distance
                    Mathlib.Copy(ref trace.endpos, out ent.v.origin);
                    original_velocity = ent.v.velocity;
                    numplanes = 0;
                }

                if (trace.fraction == 1)
                    break;		// moved the entire distance

                if (trace.ent == null)
                    Sys.Error("SV_FlyMove: !trace.ent");

                if (trace.plane.normal.Z > 0.7)
                {
                    blocked |= 1;		// floor
                    if (trace.ent.v.solid == Solids.SOLID_BSP)
                    {
                        ent.v.flags = (int)ent.v.flags | EdictFlags.FL_ONGROUND;
                        ent.v.groundentity = EdictToProg(trace.ent);
                    }
                }

                if (trace.plane.normal.Z == 0)
                {
                    blocked |= 2;		// step
                    if (steptrace != null)
                        steptrace.CopyFrom(trace);	// save for player extrafriction
                }

                //
                // run the impact function
                //
                Impact(ent, trace.ent);
                if (ent.free)
                    break;		// removed by the impact function

                time_left -= time_left * trace.fraction;

                // cliped to another plane
                if (numplanes >= MAX_CLIP_PLANES)
                {
                    // this shouldn't really happen
                    ent.v.velocity = default(v3f);
                    return 3;
                }

                planes[numplanes] = trace.plane.normal;
                numplanes++;

                //
                // modify original_velocity so it parallels all of the clip planes
                //
                v3f new_velocity = default(v3f);
                int i, j;
                for (i = 0; i < numplanes; i++)
                {
                    ClipVelocity(ref original_velocity, ref planes[i], out new_velocity, 1);
                    for (j = 0; j < numplanes; j++)
                        if (j != i)
                        {
                            float dot = new_velocity.x * planes[j].X + new_velocity.y * planes[j].Y + new_velocity.z * planes[j].Z;
                            if (dot < 0)
                                break;	// not ok
                        }
                    if (j == numplanes)
                        break;
                }

                if (i != numplanes)
                {
                    // go along this plane
                    ent.v.velocity = new_velocity;
                }
                else
                {
                    // go along the crease
                    if (numplanes != 2)
                    {
                        ent.v.velocity = default(v3f);
                        return 7;
                    }
                    Vector3 dir = Vector3.Cross(planes[0], planes[1]);
                    float d = dir.X * ent.v.velocity.x + dir.Y * ent.v.velocity.y + dir.Z * ent.v.velocity.z;
                    Mathlib.Copy(ref dir, out ent.v.velocity);
                    Mathlib.VectorScale(ref ent.v.velocity, d, out ent.v.velocity);
                }

                //
                // if original velocity is against the original velocity, stop dead
                // to avoid tiny occilations in sloping corners
                //
                if (Mathlib.DotProduct(ref ent.v.velocity, ref primal_velocity) <= 0)
                {
                    ent.v.velocity = default(v3f);
                    return blocked;
                }
            }

            return blocked;
        }
示例#15
0
        /// <summary>
        /// SV_Physics_Toss
        /// Toss, bounce, and fly movement.  When onground, do nothing.
        /// </summary>
        private static void Physics_Toss(edict_t ent)
        {
            // regular thinking
            if (!RunThink(ent))
            {
                return;
            }

            // if onground, return without moving
            if (((int)ent.v.flags & EdictFlags.FL_ONGROUND) != 0)
            {
                return;
            }

            CheckVelocity(ent);

            // add gravity
            if (ent.v.movetype != Movetypes.MOVETYPE_FLY && ent.v.movetype != Movetypes.MOVETYPE_FLYMISSILE)
            {
                AddGravity(ent);
            }


            // move angles
            Mathlib.VectorMA(ref ent.v.angles, (float)Host.FrameTime, ref ent.v.avelocity, out ent.v.angles);

            // move origin
            v3f move;

            Mathlib.VectorScale(ref ent.v.velocity, (float)Host.FrameTime, out move);
            trace_t trace = PushEntity(ent, ref move);

            if (trace.fraction == 1)
            {
                return;
            }
            if (ent.free)
            {
                return;
            }

            float backoff;

            if (ent.v.movetype == Movetypes.MOVETYPE_BOUNCE)
            {
                backoff = 1.5f;
            }
            else
            {
                backoff = 1;
            }

            ClipVelocity(ref ent.v.velocity, ref trace.plane.normal, out ent.v.velocity, backoff);

            // stop if on ground
            if (trace.plane.normal.Z > 0.7f)
            {
                if (ent.v.velocity.z < 60 || ent.v.movetype != Movetypes.MOVETYPE_BOUNCE)
                {
                    ent.v.flags        = (int)ent.v.flags | EdictFlags.FL_ONGROUND;
                    ent.v.groundentity = EdictToProg(trace.ent);
                    ent.v.velocity     = default(v3f);
                    ent.v.avelocity    = default(v3f);
                }
            }

            // check for in water
            CheckWaterTransition(ent);
        }
示例#16
0
        /// <summary>
        /// SV_WalkMove
        /// Only used by players
        /// </summary>
        static void WalkMove(edict_t ent)
        {
            //
            // do a regular slide move unless it looks like you ran into a step
            //
            int oldonground = (int)ent.v.flags & EdictFlags.FL_ONGROUND;

            ent.v.flags = (int)ent.v.flags & ~EdictFlags.FL_ONGROUND;

            v3f     oldorg    = ent.v.origin;
            v3f     oldvel    = ent.v.velocity;
            trace_t steptrace = new trace_t();
            int     clip      = FlyMove(ent, (float)Host.FrameTime, steptrace);

            if ((clip & 2) == 0)
            {
                return;         // move didn't block on a step
            }
            if (oldonground == 0 && ent.v.waterlevel == 0)
            {
                return;         // don't stair up while jumping
            }
            if (ent.v.movetype != Movetypes.MOVETYPE_WALK)
            {
                return;         // gibbed by a trigger
            }
            if (_NoStep.Value != 0)
            {
                return;
            }

            if (((int)_Player.v.flags & EdictFlags.FL_WATERJUMP) != 0)
            {
                return;
            }

            v3f nosteporg = ent.v.origin;
            v3f nostepvel = ent.v.velocity;

            //
            // try moving up and forward to go up a step
            //
            ent.v.origin = oldorg;      // back to start pos

            v3f upmove   = Common.ZeroVector3f;
            v3f downmove = upmove;

            upmove.z   = STEPSIZE;
            downmove.z = (float)(-STEPSIZE + oldvel.z * Host.FrameTime);

            // move up
            PushEntity(ent, ref upmove);        // FIXME: don't link?

            // move forward
            ent.v.velocity.x = oldvel.x;
            ent.v.velocity.y = oldvel.y;
            ent.v.velocity.z = 0;
            clip             = FlyMove(ent, (float)Host.FrameTime, steptrace);

            // check for stuckness, possibly due to the limited precision of floats
            // in the clipping hulls
            if (clip != 0)
            {
                if (Math.Abs(oldorg.y - ent.v.origin.y) < 0.03125 && Math.Abs(oldorg.x - ent.v.origin.x) < 0.03125)
                {
                    // stepping up didn't make any progress
                    clip = TryUnstick(ent, ref oldvel);
                }
            }

            // extra friction based on view angle
            if ((clip & 2) != 0)
            {
                WallFriction(ent, steptrace);
            }

            // move down
            trace_t downtrace = PushEntity(ent, ref downmove);  // FIXME: don't link?

            if (downtrace.plane.normal.Z > 0.7)
            {
                if (ent.v.solid == Solids.SOLID_BSP)
                {
                    ent.v.flags        = (int)ent.v.flags | EdictFlags.FL_ONGROUND;
                    ent.v.groundentity = EdictToProg(downtrace.ent);
                }
            }
            else
            {
                // if the push down didn't end up on good ground, use the move without
                // the step up.  This happens near wall / slope combinations, and can
                // cause the player to hop up higher on a slope too steep to climb
                ent.v.origin   = nosteporg;
                ent.v.velocity = nostepvel;
            }
        }
示例#17
0
        /// <summary>
        /// SV_RecursiveHullCheck
        /// </summary>
        public static bool RecursiveHullCheck(hull_t hull, int num, float p1f, float p2f, ref Vector3 p1, ref Vector3 p2, trace_t trace)
        {
            // check for empty
            if (num < 0)
            {
                if (num != Contents.CONTENTS_SOLID)
                {
                    trace.allsolid = false;
                    if (num == Contents.CONTENTS_EMPTY)
                    {
                        trace.inopen = true;
                    }
                    else
                    {
                        trace.inwater = true;
                    }
                }
                else
                {
                    trace.startsolid = true;
                }
                return(true);            // empty
            }

            if (num < hull.firstclipnode || num > hull.lastclipnode)
            {
                Sys.Error("SV_RecursiveHullCheck: bad node number");
            }

            //
            // find the point distances
            //
            short[]  node_children = hull.clipnodes[num].children;
            mplane_t plane = hull.planes[hull.clipnodes[num].planenum];
            float    t1, t2;

            if (plane.type < 3)
            {
                t1 = Mathlib.Comp(ref p1, plane.type) - plane.dist;
                t2 = Mathlib.Comp(ref p2, plane.type) - plane.dist;
            }
            else
            {
                t1 = Vector3.Dot(plane.normal, p1) - plane.dist;
                t2 = Vector3.Dot(plane.normal, p2) - plane.dist;
            }

            if (t1 >= 0 && t2 >= 0)
            {
                return(RecursiveHullCheck(hull, node_children[0], p1f, p2f, ref p1, ref p2, trace));
            }
            if (t1 < 0 && t2 < 0)
            {
                return(RecursiveHullCheck(hull, node_children[1], p1f, p2f, ref p1, ref p2, trace));
            }

            // put the crosspoint DIST_EPSILON pixels on the near side
            float frac;

            if (t1 < 0)
            {
                frac = (t1 + DIST_EPSILON) / (t1 - t2);
            }
            else
            {
                frac = (t1 - DIST_EPSILON) / (t1 - t2);
            }
            if (frac < 0)
            {
                frac = 0;
            }
            if (frac > 1)
            {
                frac = 1;
            }

            float   midf = p1f + (p2f - p1f) * frac;
            Vector3 mid  = p1 + (p2 - p1) * frac;

            int side = (t1 < 0) ? 1 : 0;

            // move up to the node
            if (!RecursiveHullCheck(hull, node_children[side], p1f, midf, ref p1, ref mid, trace))
            {
                return(false);
            }

            if (HullPointContents(hull, node_children[side ^ 1], ref mid) != Contents.CONTENTS_SOLID)
            {
                // go past the node
                return(RecursiveHullCheck(hull, node_children[side ^ 1], midf, p2f, ref mid, ref p2, trace));
            }

            if (trace.allsolid)
            {
                return(false);           // never got out of the solid area
            }
            //==================
            // the other side of the node is solid, this is the impact point
            //==================
            if (side == 0)
            {
                trace.plane.normal = plane.normal;
                trace.plane.dist   = plane.dist;
            }
            else
            {
                trace.plane.normal = -plane.normal;
                trace.plane.dist   = -plane.dist;
            }

            while (HullPointContents(hull, hull.firstclipnode, ref mid) == Contents.CONTENTS_SOLID)
            {
                // shouldn't really happen, but does occasionally
                frac -= 0.1f;
                if (frac < 0)
                {
                    trace.fraction = midf;
                    trace.endpos   = mid;
                    Con.DPrint("backup past 0\n");
                    return(false);
                }
                midf = p1f + (p2f - p1f) * frac;
                mid  = p1 + (p2 - p1) * frac;
            }

            trace.fraction = midf;
            trace.endpos   = mid;

            return(false);
        }
示例#18
0
        /// <summary>
        /// SV_WalkMove
        /// Only used by players
        /// </summary>
        static void WalkMove(edict_t ent)
        {
            //
            // do a regular slide move unless it looks like you ran into a step
            //
            int oldonground = (int)ent.v.flags & EdictFlags.FL_ONGROUND;
            ent.v.flags = (int)ent.v.flags & ~EdictFlags.FL_ONGROUND;

            v3f oldorg = ent.v.origin;
            v3f oldvel = ent.v.velocity;
            trace_t steptrace = new trace_t();
            int clip = FlyMove(ent, (float)Host.FrameTime, steptrace);

            if ((clip & 2) == 0)
                return;		// move didn't block on a step

            if (oldonground == 0 && ent.v.waterlevel == 0)
                return;		// don't stair up while jumping

            if (ent.v.movetype != Movetypes.MOVETYPE_WALK)
                return;		// gibbed by a trigger

            if (_NoStep.Value != 0)
                return;

            if (((int)_Player.v.flags & EdictFlags.FL_WATERJUMP) != 0)
                return;

            v3f nosteporg = ent.v.origin;
            v3f nostepvel = ent.v.velocity;

            //
            // try moving up and forward to go up a step
            //
            ent.v.origin = oldorg;	// back to start pos

            v3f upmove = Common.ZeroVector3f;
            v3f downmove = upmove;
            upmove.z = STEPSIZE;
            downmove.z = (float)(-STEPSIZE + oldvel.z * Host.FrameTime);

            // move up
            PushEntity(ent, ref upmove);	// FIXME: don't link?

            // move forward
            ent.v.velocity.x = oldvel.x;
            ent.v.velocity.y = oldvel.y;
            ent.v.velocity.z = 0;
            clip = FlyMove(ent, (float)Host.FrameTime, steptrace);

            // check for stuckness, possibly due to the limited precision of floats
            // in the clipping hulls
            if (clip != 0)
            {
                if (Math.Abs(oldorg.y - ent.v.origin.y) < 0.03125 && Math.Abs(oldorg.x - ent.v.origin.x) < 0.03125)
                {
                    // stepping up didn't make any progress
                    clip = TryUnstick(ent, ref oldvel);
                }
            }

            // extra friction based on view angle
            if ((clip & 2) != 0)
                WallFriction(ent, steptrace);

            // move down
            trace_t downtrace = PushEntity(ent, ref downmove);	// FIXME: don't link?

            if (downtrace.plane.normal.Z > 0.7)
            {
                if (ent.v.solid == Solids.SOLID_BSP)
                {
                    ent.v.flags = (int)ent.v.flags | EdictFlags.FL_ONGROUND;
                    ent.v.groundentity = EdictToProg(downtrace.ent);
                }
            }
            else
            {
                // if the push down didn't end up on good ground, use the move without
                // the step up.  This happens near wall / slope combinations, and can
                // cause the player to hop up higher on a slope too steep to climb
                ent.v.origin = nosteporg;
                ent.v.velocity = nostepvel;
            }
        }
示例#19
0
        /// <summary>
        /// SV_ClipMoveToEntity
        /// Handles selection or creation of a clipping hull, and offseting (and
        /// eventually rotation) of the end points
        /// </summary>
        static trace_t ClipMoveToEntity(edict_t ent, ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end)
        {
            trace_t trace = new trace_t();
            // fill in a default trace
            trace.fraction = 1;
            trace.allsolid = true;
            trace.endpos = end;

            // get the clipping hull
            Vector3 offset;
            hull_t hull = HullForEntity(ent, ref mins, ref maxs, out offset);

            Vector3 start_l = start - offset;
            Vector3 end_l = end - offset;

            // trace a line through the apropriate clipping hull
            RecursiveHullCheck(hull, hull.firstclipnode, 0, 1, ref start_l, ref end_l, trace);

            // fix trace up by the offset
            if (trace.fraction != 1)
                trace.endpos += offset;

            // did we clip the move?
            if (trace.fraction < 1 || trace.startsolid)
                trace.ent = ent;

            return trace;
        }
示例#20
0
        /// <summary>
        /// SV_WallFriction
        /// </summary>
        static void WallFriction(edict_t ent, trace_t trace)
        {
            Vector3 forward, right, up, vangle = Common.ToVector(ref ent.v.v_angle);
            Mathlib.AngleVectors(ref vangle, out forward, out right, out up);
            float d = Vector3.Dot(trace.plane.normal, forward);

            d += 0.5f;
            if (d >= 0)
                return;

            // cut the tangential velocity
            Vector3 vel = Common.ToVector(ref ent.v.velocity);
            float i = Vector3.Dot(trace.plane.normal, vel);
            Vector3 into = trace.plane.normal * i;
            Vector3 side = vel - into;

            ent.v.velocity.x = side.X * (1 + d);
            ent.v.velocity.y = side.Y * (1 + d);
        }
示例#21
0
        /// <summary>
        /// SV_RecursiveHullCheck
        /// </summary>
        public static bool RecursiveHullCheck(hull_t hull, int num, float p1f, float p2f, ref Vector3 p1, ref Vector3 p2, trace_t trace)
        {
            // check for empty
            if (num < 0)
            {
                if (num != Contents.CONTENTS_SOLID)
                {
                    trace.allsolid = false;
                    if (num == Contents.CONTENTS_EMPTY)
                        trace.inopen = true;
                    else
                        trace.inwater = true;
                }
                else
                    trace.startsolid = true;
                return true;		// empty
            }

            if (num < hull.firstclipnode || num > hull.lastclipnode)
                Sys.Error("SV_RecursiveHullCheck: bad node number");

            //
            // find the point distances
            //
            short[] node_children = hull.clipnodes[num].children;
            mplane_t plane = hull.planes[hull.clipnodes[num].planenum];
            float t1, t2;

            if (plane.type < 3)
            {
                t1 = Mathlib.Comp(ref p1, plane.type) - plane.dist;
                t2 = Mathlib.Comp(ref p2, plane.type) - plane.dist;
            }
            else
            {
                t1 = Vector3.Dot(plane.normal, p1) - plane.dist;
                t2 = Vector3.Dot(plane.normal, p2) - plane.dist;
            }

            if (t1 >= 0 && t2 >= 0)
                return RecursiveHullCheck(hull, node_children[0], p1f, p2f, ref p1, ref p2, trace);
            if (t1 < 0 && t2 < 0)
                return RecursiveHullCheck(hull, node_children[1], p1f, p2f, ref p1, ref p2, trace);

            // put the crosspoint DIST_EPSILON pixels on the near side
            float frac;
            if (t1 < 0)
                frac = (t1 + DIST_EPSILON) / (t1 - t2);
            else
                frac = (t1 - DIST_EPSILON) / (t1 - t2);
            if (frac < 0)
                frac = 0;
            if (frac > 1)
                frac = 1;

            float midf = p1f + (p2f - p1f) * frac;
            Vector3 mid = p1 + (p2 - p1) * frac;

            int side = (t1 < 0) ? 1 : 0;

            // move up to the node
            if (!RecursiveHullCheck(hull, node_children[side], p1f, midf, ref p1, ref mid, trace))
                return false;

            if (HullPointContents(hull, node_children[side ^ 1], ref mid) != Contents.CONTENTS_SOLID)
                // go past the node
                return RecursiveHullCheck(hull, node_children[side ^ 1], midf, p2f, ref mid, ref p2, trace);

            if (trace.allsolid)
                return false;		// never got out of the solid area

            //==================
            // the other side of the node is solid, this is the impact point
            //==================
            if (side == 0)
            {
                trace.plane.normal = plane.normal;
                trace.plane.dist = plane.dist;
            }
            else
            {
                trace.plane.normal = -plane.normal;
                trace.plane.dist = -plane.dist;
            }

            while (HullPointContents(hull, hull.firstclipnode, ref mid) == Contents.CONTENTS_SOLID)
            {
                // shouldn't really happen, but does occasionally
                frac -= 0.1f;
                if (frac < 0)
                {
                    trace.fraction = midf;
                    trace.endpos = mid;
                    Con.DPrint("backup past 0\n");
                    return false;
                }
                midf = p1f + (p2f - p1f) * frac;
                mid = p1 + (p2 - p1) * frac;
            }

            trace.fraction = midf;
            trace.endpos = mid;

            return false;
        }
示例#22
0
        /// <summary>
        /// SV_CheckBottom
        /// </summary>
        public static bool CheckBottom(edict_t ent)
        {
            v3f mins, maxs;

            Mathlib.VectorAdd(ref ent.v.origin, ref ent.v.mins, out mins);
            Mathlib.VectorAdd(ref ent.v.origin, ref ent.v.maxs, out maxs);

            // if all of the points under the corners are solid world, don't bother
            // with the tougher checks
            // the corners must be within 16 of the midpoint
            Vector3 start;

            start.Z = mins.z - 1;
            for (int x = 0; x <= 1; x++)
            {
                for (int y = 0; y <= 1; y++)
                {
                    start.X = (x != 0 ? maxs.x : mins.x);
                    start.Y = (y != 0 ? maxs.y : mins.y);
                    if (PointContents(ref start) != Contents.CONTENTS_SOLID)
                    {
                        goto RealCheck;
                    }
                }
            }

            return(true);                // we got out easy

RealCheck:

            //
            // check it for real...
            //
            start.Z = mins.z;

            // the midpoint must be within 16 of the bottom
            start.X = (mins.x + maxs.x) * 0.5f;
            start.Y = (mins.y + maxs.y) * 0.5f;
            Vector3 stop = start;

            stop.Z -= 2 * STEPSIZE;
            trace_t trace = Move(ref start, ref Common.ZeroVector, ref Common.ZeroVector, ref stop, 1, ent);

            if (trace.fraction == 1.0)
            {
                return(false);
            }

            float mid    = trace.endpos.Z;
            float bottom = mid;

            // the corners must be within 16 of the midpoint
            for (int x = 0; x <= 1; x++)
            {
                for (int y = 0; y <= 1; y++)
                {
                    start.X = stop.X = (x != 0 ? maxs.x : mins.x);
                    start.Y = stop.Y = (y != 0 ? maxs.y : mins.y);

                    trace = Move(ref start, ref Common.ZeroVector, ref Common.ZeroVector, ref stop, 1, ent);

                    if (trace.fraction != 1.0 && trace.endpos.Z > bottom)
                    {
                        bottom = trace.endpos.Z;
                    }
                    if (trace.fraction == 1.0 || mid - trace.endpos.Z > STEPSIZE)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#23
0
        static void TraceLine(ref Vector3 start, ref Vector3 end, out Vector3 impact)
        {
            trace_t trace = new trace_t();

            Server.RecursiveHullCheck(Client.cl.worldmodel.hulls[0], 0, 0, 1, ref start, ref end, trace);

            impact = trace.endpos; // VectorCopy(trace.endpos, impact);
        }
示例#24
0
        /*
         * =============
         * PF_aim
         *
         * Pick a vector for the player to shoot along
         * vector aim(entity, missilespeed)
         * =============
         */
        static void PF_aim()
        {
            edict_t ent   = GetEdict(OFS.OFS_PARM0);
            float   speed = GetFloat(OFS.OFS_PARM1);

            Vector3 start = Common.ToVector(ref ent.v.origin);

            start.Z += 20;

            // try sending a trace straight
            Vector3 dir;

            Mathlib.Copy(ref Progs.GlobalStruct.v_forward, out dir);
            Vector3 end = start + dir * 2048;
            trace_t tr  = Server.Move(ref start, ref Common.ZeroVector, ref Common.ZeroVector, ref end, 0, ent);

            if (tr.ent != null && tr.ent.v.takedamage == Damages.DAMAGE_AIM &&
                (Host.TeamPlay == 0 || ent.v.team <= 0 || ent.v.team != tr.ent.v.team))
            {
                ReturnVector(ref Progs.GlobalStruct.v_forward);
                return;
            }

            // try all possible entities
            Vector3 bestdir  = dir;
            float   bestdist = Server.Aim;
            edict_t bestent  = null;

            for (int i = 1; i < Server.sv.num_edicts; i++)
            {
                edict_t check = Server.sv.edicts[i];
                if (check.v.takedamage != Damages.DAMAGE_AIM)
                {
                    continue;
                }

                if (check == ent)
                {
                    continue;
                }

                if (Host.TeamPlay != 0 && ent.v.team > 0 && ent.v.team == check.v.team)
                {
                    continue;   // don't aim at teammate
                }

                v3f tmp;
                Mathlib.VectorAdd(ref check.v.mins, ref check.v.maxs, out tmp);
                Mathlib.VectorMA(ref check.v.origin, 0.5f, ref tmp, out tmp);
                Mathlib.Copy(ref tmp, out end);

                dir = end - start;
                Mathlib.Normalize(ref dir);
                float dist = Vector3.Dot(dir, Common.ToVector(ref Progs.GlobalStruct.v_forward));
                if (dist < bestdist)
                {
                    continue;   // to far to turn
                }

                tr = Server.Move(ref start, ref Common.ZeroVector, ref Common.ZeroVector, ref end, 0, ent);
                if (tr.ent == check)
                {       // can shoot at this one
                    bestdist = dist;
                    bestent  = check;
                }
            }

            if (bestent != null)
            {
                v3f dir2, end2;
                Mathlib.VectorSubtract(ref bestent.v.origin, ref ent.v.origin, out dir2);
                float dist = Mathlib.DotProduct(ref dir2, ref Progs.GlobalStruct.v_forward);
                Mathlib.VectorScale(ref Progs.GlobalStruct.v_forward, dist, out end2);
                end2.z = dir2.z;
                Mathlib.Normalize(ref end2);
                ReturnVector(ref end2);
            }
            else
            {
                ReturnVector(ref bestdir);
            }
        }
示例#25
0
        /// <summary>
        /// SV_SetIdealPitch
        /// </summary>
        public static void SetIdealPitch()
        {
            if (((int)_Player.v.flags & EdictFlags.FL_ONGROUND) == 0)
            {
                return;
            }

            double angleval = _Player.v.angles.y * Math.PI * 2 / 360;
            double sinval   = Math.Sin(angleval);
            double cosval   = Math.Cos(angleval);

            float[] z = new float[MAX_FORWARD];
            for (int i = 0; i < MAX_FORWARD; i++)
            {
                v3f top = _Player.v.origin;
                top.x += (float)(cosval * (i + 3) * 12);
                top.y += (float)(sinval * (i + 3) * 12);
                top.z += _Player.v.view_ofs.z;

                v3f bottom = top;
                bottom.z -= 160;

                trace_t tr = Move(ref top, ref Common.ZeroVector3f, ref Common.ZeroVector3f, ref bottom, 1, _Player);
                if (tr.allsolid)
                {
                    return;     // looking at a wall, leave ideal the way is was
                }
                if (tr.fraction == 1)
                {
                    return;     // near a dropoff
                }
                z[i] = top.z + tr.fraction * (bottom.z - top.z);
            }

            float dir   = 0; // Uze: int in original code???
            int   steps = 0;

            for (int j = 1; j < MAX_FORWARD; j++)
            {
                float step = z[j] - z[j - 1];                          // Uze: int in original code???
                if (step > -QDef.ON_EPSILON && step < QDef.ON_EPSILON) // Uze: comparing int with ON_EPSILON (0.1)???
                {
                    continue;
                }

                if (dir != 0 && (step - dir > QDef.ON_EPSILON || step - dir < -QDef.ON_EPSILON))
                {
                    return;             // mixed changes
                }
                steps++;
                dir = step;
            }

            if (dir == 0)
            {
                _Player.v.idealpitch = 0;
                return;
            }

            if (steps < 2)
            {
                return;
            }
            _Player.v.idealpitch = -dir * _IdealPitchScale.Value;
        }