Ejemplo n.º 1
0
        /// <summary>
        /// SV_ClipMoveToEntity
        /// Handles selection or creation of a clipping hull, and offseting (and
        /// eventually rotation) of the end points
        /// </summary>
        private Trace_t ClipMoveToEntity(MemoryEdict ent, ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end)
        {
            var trace = new Trace_t();

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

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

            var start_l = start - offset;
            var 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);
        }
Ejemplo n.º 2
0
        private void TraceLine(ref Vector3 start, ref Vector3 end, out Vector3 impact)
        {
            var trace = new Trace_t();

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

            impact = trace.endpos; // VectorCopy(trace.endpos, impact);
        }
Ejemplo n.º 3
0
		/// <summary>
		/// SV_WallFriction
		/// </summary>
		private void WallFriction( MemoryEdict ent, Trace_t trace )
		{
			Vector3 forward, right, up, vangle = Utilities.ToVector( ref ent.v.v_angle );
			MathLib.AngleVectors( ref vangle, out forward, out right, out up );
			var d = Vector3.Dot( trace.plane.normal, forward );

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

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

			ent.v.velocity.x = side.X * ( 1 + d );
			ent.v.velocity.y = side.Y * ( 1 + d );
		}
Ejemplo n.º 4
0
        /// <summary>
        /// SV_RecursiveHullCheck
        /// </summary>
        public Boolean RecursiveHullCheck(BspHull hull, Int32 num, Single p1f, Single p2f, ref Vector3 p1, ref Vector3 p2, Trace_t trace)
        {
            // check for empty
            if (num < 0)
            {
                if (num != ( Int32 )Q1Contents.Solid)
                {
                    trace.allsolid = false;
                    if (num == ( Int32 )Q1Contents.Empty)
                    {
                        trace.inopen = true;
                    }
                    else
                    {
                        trace.inwater = true;
                    }
                }
                else
                {
                    trace.startsolid = true;
                }
                return(true);                       // empty
            }

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

            //
            // find the point distances
            //
            var    node_children = hull.clipnodes[num].children;
            var    plane = hull.planes[hull.clipnodes[num].planenum];
            Single 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
            Single 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;
            }

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

            var 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) != ( Int32 )Q1Contents.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) == ( Int32 )Q1Contents.Solid)
            {
                // shouldn't really happen, but does occasionally
                frac -= 0.1f;
                if (frac < 0)
                {
                    trace.fraction = midf;
                    trace.endpos   = mid;
                    Host.Console.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);
        }
Ejemplo n.º 5
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>
        private Int32 FlyMove(MemoryEdict ent, Single time, Trace_t steptrace)
        {
            var original_velocity = ent.v.velocity;
            var primal_velocity   = ent.v.velocity;

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

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

                Vector3f end;
                MathLib.VectorMA(ref ent.v.origin, time_left, ref ent.v.velocity, out end);

                var 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(Vector3f);
                    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)
                {
                    Utilities.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        = ( Int32 )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(Vector3f);
                    return(3);
                }

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

                //
                // modify original_velocity so it parallels all of the clip planes
                //
                var   new_velocity = default(Vector3f);
                Int32 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)
                        {
                            var 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(Vector3f);
                        return(7);
                    }
                    var dir = Vector3.Cross(planes[0], planes[1]);
                    var 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(Vector3f);
                    return(blocked);
                }
            }

            return(blocked);
        }
Ejemplo n.º 6
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>
        private Int32 TryUnstick(MemoryEdict ent, ref Vector3f oldvel)
        {
            var oldorg = ent.v.origin;
            var dir    = Utilities.ZeroVector3f;

            var steptrace = new Trace_t();

            for (var 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;
                var 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 = Utilities.ZeroVector3f;
            return(7);                  // still not moving
        }
Ejemplo n.º 7
0
        /// <summary>
        /// SV_WalkMove
        /// Only used by players
        /// </summary>
        private void WalkMove(MemoryEdict ent)
        {
            //
            // do a regular slide move unless it looks like you ran into a step
            //
            var oldonground = ( Int32 )ent.v.flags & EdictFlags.FL_ONGROUND;

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

            var oldorg    = ent.v.origin;
            var oldvel    = ent.v.velocity;
            var steptrace = new Trace_t();
            var clip      = FlyMove(ent, ( Single )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 (Host.Cvars.NoStep.Get <Boolean>())
            {
                return;
            }

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

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

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

            var upmove   = Utilities.ZeroVector3f;
            var downmove = upmove;

            upmove.z   = STEPSIZE;
            downmove.z = ( Single )(-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, ( Single )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
            var 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        = ( Int32 )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;
            }
        }
Ejemplo n.º 8
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>
        private int TryUnstick(MemoryEdict ent, ref Vector3 oldvel)
        {
            var oldorg = ent.v.origin;
            var dir    = Utilities.ZeroVector3f;

            var steptrace = new Trace_t();

            for (var 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;
                }

                this.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;
                var clip = this.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 = Utilities.ZeroVector3f;
            return(7);                  // still not moving
        }