Quake math functions
        /// <summary>
        /// SV_AirAccelerate
        /// </summary>
        static void AirAccelerate(Vector3 wishveloc)
        {
            float wishspd = Mathlib.Normalize(ref wishveloc);

            if (wishspd > 30)
            {
                wishspd = 30;
            }
            float currentspeed = Vector3.Dot(Common.ToVector(ref _Player.v.velocity), wishveloc);
            float addspeed     = wishspd - currentspeed;

            if (addspeed <= 0)
            {
                return;
            }
            float accelspeed = (float)(_Accelerate.Value * _WishSpeed * Host.FrameTime);

            if (accelspeed > addspeed)
            {
                accelspeed = addspeed;
            }

            wishveloc            *= accelspeed;
            _Player.v.velocity.x += wishveloc.X;
            _Player.v.velocity.y += wishveloc.Y;
            _Player.v.velocity.z += wishveloc.Z;
        }
Exemple #2
0
        /// <summary>
        /// SV_HullPointContents
        /// </summary>
        static int HullPointContents(hull_t hull, int num, ref Vector3 p)
        {
            while (num >= 0)
            {
                if (num < hull.firstclipnode || num > hull.lastclipnode)
                {
                    Sys.Error("SV_HullPointContents: bad node number");
                }

                short[]  node_children = hull.clipnodes[num].children;
                mplane_t plane         = hull.planes[hull.clipnodes[num].planenum];
                float    d;
                if (plane.type < 3)
                {
                    d = Mathlib.Comp(ref p, plane.type) - plane.dist;
                }
                else
                {
                    d = Vector3.Dot(plane.normal, p) - plane.dist;
                }
                if (d < 0)
                {
                    num = node_children[1];
                }
                else
                {
                    num = node_children[0];
                }
            }

            return(num);
        }
Exemple #3
0
        // Chase_Update
        public static void Update()
        {
            // if can't see player, reset
            Vector3 forward, up, right;

            Mathlib.AngleVectors(ref Client.cl.viewangles, out forward, out right, out up);

            // calc exact destination
            _Dest   = Render.RefDef.vieworg - forward * _Back.Value - right * _Right.Value;
            _Dest.Z = Render.RefDef.vieworg.Z + _Up.Value;

            // find the spot the player is looking at
            Vector3 dest = Render.RefDef.vieworg + forward * 4096;

            Vector3 stop;

            TraceLine(ref Render.RefDef.vieworg, ref dest, out stop);

            // calculate pitch to look at the same spot from camera
            stop -= Render.RefDef.vieworg;
            float dist;

            Vector3.Dot(ref stop, ref forward, out dist);
            if (dist < 1)
            {
                dist = 1;
            }

            Render.RefDef.viewangles.X = (float)(-Math.Atan(stop.Z / dist) / Math.PI * 180.0);
            //r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180;

            // move towards destination
            Render.RefDef.vieworg = _Dest; //VectorCopy(chase_dest, r_refdef.vieworg);
        }
        /// <summary>
        /// SV_ReadClientMove
        /// </summary>
        static void ReadClientMove(ref usercmd_t move)
        {
            client_t client = Host.HostClient;

            // read ping time
            client.ping_times[client.num_pings % NUM_PING_TIMES] = (float)(sv.time - Net.Reader.ReadFloat());
            client.num_pings++;

            // read current angles
            Vector3 angles = Net.Reader.ReadAngles();

            Mathlib.Copy(ref angles, out client.edict.v.v_angle);

            // read movement
            move.forwardmove = Net.Reader.ReadShort();
            move.sidemove    = Net.Reader.ReadShort();
            move.upmove      = Net.Reader.ReadShort();

            // read buttons
            int bits = Net.Reader.ReadByte();

            client.edict.v.button0 = bits & 1;
            client.edict.v.button2 = (bits & 2) >> 1;

            int i = Net.Reader.ReadByte();

            if (i != 0)
            {
                client.edict.v.impulse = i;
            }
        }
Exemple #5
0
        static void Test5_f()
        {
            Entity p = Client.ViewEntity;

            if (p == null)
            {
                return;
            }

            OpenTK.Vector3 org = p.origin;

            for (int i = 0; i < Server.sv.edicts.Length; i++)
            {
                edict_t ed = Server.sv.edicts[i];

                if (ed.free)
                {
                    continue;
                }

                OpenTK.Vector3 vmin, vmax;
                Mathlib.Copy(ref ed.v.absmax, out vmax);
                Mathlib.Copy(ref ed.v.absmin, out vmin);

                if (org.X >= vmin.X && org.Y >= vmin.Y && org.Z >= vmin.Z &&
                    org.X <= vmax.X && org.Y <= vmax.Y && org.Z <= vmax.Z)
                {
                    Con.Print("{0}\n", i);
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// R_TeleportSplash
        /// </summary>
        public static void TeleportSplash(ref Vector3 org)
        {
            for (int i = -16; i < 16; i += 4)
            {
                for (int j = -16; j < 16; j += 4)
                {
                    for (int k = -24; k < 32; k += 4)
                    {
                        particle_t p = AllocParticle();
                        if (p == null)
                        {
                            return;
                        }

                        p.die   = (float)(Client.cl.time + 0.2 + (Sys.Random() & 7) * 0.02);
                        p.color = 7 + (Sys.Random() & 7);
                        p.type  = ptype_t.pt_slowgrav;

                        Vector3 dir = new Vector3(j * 8, i * 8, k * 8);

                        p.org = org + new Vector3(i + (Sys.Random() & 3), j + (Sys.Random() & 3), k + (Sys.Random() & 3));

                        Mathlib.Normalize(ref dir);
                        float vel = 50 + (Sys.Random() & 63);
                        p.vel = dir * vel;
                    }
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// R_LavaSplash
        /// </summary>
        public static void LavaSplash(ref Vector3 org)
        {
            Vector3 dir;

            for (int i = -16; i < 16; i++)
            {
                for (int j = -16; j < 16; j++)
                {
                    for (int k = 0; k < 1; k++)
                    {
                        particle_t p = AllocParticle();
                        if (p == null)
                        {
                            return;
                        }

                        p.die   = (float)(Client.cl.time + 2 + (Sys.Random() & 31) * 0.02);
                        p.color = 224 + (Sys.Random() & 7);
                        p.type  = ptype_t.pt_slowgrav;

                        dir.X = j * 8 + (Sys.Random() & 7);
                        dir.Y = i * 8 + (Sys.Random() & 7);
                        dir.Z = 256;

                        p.org    = org + dir;
                        p.org.Z += Sys.Random() & 63;

                        Mathlib.Normalize(ref dir);
                        float vel = 50 + (Sys.Random() & 63);
                        p.vel = dir * vel;
                    }
                }
            }
        }
Exemple #8
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]);
            }
        }
        /// <summary>
        /// PushEntity
        /// Does not change the entities velocity at all
        /// </summary>
        private static trace_t PushEntity(edict_t ent, ref v3f push)
        {
            v3f end;

            Mathlib.VectorAdd(ref ent.v.origin, ref push, out end);

            trace_t trace;

            if (ent.v.movetype == Movetypes.MOVETYPE_FLYMISSILE)
            {
                trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, MOVE_MISSILE, ent);
            }
            else if (ent.v.solid == Solids.SOLID_TRIGGER || ent.v.solid == Solids.SOLID_NOT)
            {
                // only clip against bmodels
                trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, MOVE_NOMONSTERS, ent);
            }
            else
            {
                trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, MOVE_NORMAL, ent);
            }

            Mathlib.Copy(ref trace.endpos, out ent.v.origin);
            LinkEdict(ent, true);

            if (trace.ent != null)
            {
                Impact(ent, trace.ent);
            }

            return(trace);
        }
Exemple #10
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);
            }
        }
Exemple #11
0
 // angledelta()
 static float AngleDelta(float a)
 {
     a = Mathlib.AngleMod(a);
     if (a > 180)
     {
         a -= 360;
     }
     return(a);
 }
Exemple #12
0
        /*
         * =================
         * PF_normalize
         *
         * vector normalize(vector)
         * =================
         */
        static unsafe void PF_normalize()
        {
            float * value1 = GetVector(OFS.OFS_PARM0);
            Vector3 tmp;

            Copy(value1, out tmp);
            Mathlib.Normalize(ref tmp);

            ReturnVector(ref tmp);
        }
        static trace_t Move(ref v3f start, ref v3f mins, ref v3f maxs, ref v3f end, int type, edict_t passedict)
        {
            Vector3 vstart, vmins, vmaxs, vend;

            Mathlib.Copy(ref start, out vstart);
            Mathlib.Copy(ref mins, out vmins);
            Mathlib.Copy(ref maxs, out vmaxs);
            Mathlib.Copy(ref end, out vend);
            return(Move(ref vstart, ref vmins, ref vmaxs, ref vend, type, passedict));
        }
Exemple #14
0
        /*
         * ==============
         * PF_makevectors
         *
         * Writes new values for v_forward, v_up, and v_right based on angles
         * makevectors(vector)
         * ==============
         */
        static unsafe void PF_makevectors()
        {
            float * av = GetVector(OFS.OFS_PARM0);
            Vector3 a = new Vector3(av[0], av[1], av[2]);
            Vector3 fw, right, up;

            Mathlib.AngleVectors(ref a, out fw, out right, out up);
            Mathlib.Copy(ref fw, out Progs.GlobalStruct.v_forward);
            Mathlib.Copy(ref right, out Progs.GlobalStruct.v_right);
            Mathlib.Copy(ref up, out Progs.GlobalStruct.v_up);
        }
Exemple #15
0
        /// <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]);
            }
        }
Exemple #16
0
        // CL_AdjustAngles
        //
        // Moves the local angle positions
        static void AdjustAngles()
        {
            float speed = (float)Host.FrameTime;

            if (ClientInput.SpeedBtn.IsDown)
            {
                speed *= _AngleSpeedKey.Value;
            }

            if (!ClientInput.StrafeBtn.IsDown)
            {
                Cl.viewangles.Y -= speed * _YawSpeed.Value * KeyState(ref ClientInput.RightBtn);
                Cl.viewangles.Y += speed * _YawSpeed.Value * KeyState(ref ClientInput.LeftBtn);
                Cl.viewangles.Y  = Mathlib.AngleMod(Cl.viewangles.Y);
            }

            if (ClientInput.KLookBtn.IsDown)
            {
                View.StopPitchDrift();
                Cl.viewangles.X -= speed * _PitchSpeed.Value * KeyState(ref ClientInput.ForwardBtn);
                Cl.viewangles.X += speed * _PitchSpeed.Value * KeyState(ref ClientInput.BackBtn);
            }

            float up   = KeyState(ref ClientInput.LookUpBtn);
            float down = KeyState(ref ClientInput.LookDownBtn);

            Cl.viewangles.X -= speed * _PitchSpeed.Value * up;
            Cl.viewangles.X += speed * _PitchSpeed.Value * down;

            if (up != 0 || down != 0)
            {
                View.StopPitchDrift();
            }

            if (Cl.viewangles.X > 80)
            {
                Cl.viewangles.X = 80;
            }

            if (Cl.viewangles.X < -70)
            {
                Cl.viewangles.X = -70;
            }

            if (Cl.viewangles.Z > 50)
            {
                Cl.viewangles.Z = 50;
            }

            if (Cl.viewangles.Z < -50)
            {
                Cl.viewangles.Z = -50;
            }
        }
        /// <summary>
        /// SV_Physics_Noclip
        /// A moving object that doesn't obey physics
        /// </summary>
        static void Physics_Noclip(edict_t ent)
        {
            // regular thinking
            if (!RunThink(ent))
            {
                return;
            }

            Mathlib.VectorMA(ref ent.v.angles, (float)Host.FrameTime, ref ent.v.avelocity, out ent.v.angles);
            Mathlib.VectorMA(ref ent.v.origin, (float)Host.FrameTime, ref ent.v.velocity, out ent.v.origin);
            LinkEdict(ent, false);
        }
Exemple #18
0
        /// <summary>
        /// SV_ClientThink
        /// the move fields specify an intended velocity in pix/sec
        /// the angle fields specify an exact angular motion in degrees
        /// </summary>
        static void ClientThink()
        {
            if (_Player.v.movetype == Movetypes.MOVETYPE_NONE)
            {
                return;
            }

            _OnGround = ((int)_Player.v.flags & EdictFlags.FL_ONGROUND) != 0;

            DropPunchAngle();

            //
            // if dead, behave differently
            //
            if (_Player.v.health <= 0)
            {
                return;
            }

            //
            // angles
            // show 1/3 the pitch angle and all the roll angle
            _Cmd = Host.HostClient.cmd;

            v3f v_angle;

            Mathlib.VectorAdd(ref _Player.v.v_angle, ref _Player.v.punchangle, out v_angle);
            Vector3 pang = Common.ToVector(ref _Player.v.angles);
            Vector3 pvel = Common.ToVector(ref _Player.v.velocity);

            _Player.v.angles.z = View.CalcRoll(ref pang, ref pvel) * 4;
            if (_Player.v.fixangle == 0)
            {
                _Player.v.angles.x = -v_angle.x / 3;
                _Player.v.angles.y = v_angle.y;
            }

            if (((int)_Player.v.flags & EdictFlags.FL_WATERJUMP) != 0)
            {
                WaterJump();
                return;
            }
            //
            // walk
            //
            if ((_Player.v.waterlevel >= 2) && (_Player.v.movetype != Movetypes.MOVETYPE_NOCLIP))
            {
                WaterMove();
                return;
            }

            AirMove();
        }
Exemple #19
0
        static void DropPunchAngle()
        {
            Vector3 v   = Common.ToVector(ref _Player.v.punchangle);
            double  len = Mathlib.Normalize(ref v) - 10 * Host.FrameTime;

            if (len < 0)
            {
                len = 0;
            }
            v *= (float)len;
            Mathlib.Copy(ref v, out _Player.v.punchangle);
        }
Exemple #20
0
        static bool IsCollinear(float[] prev, float[] cur, float[] next)
        {
            Vector3 v1 = new Vector3(cur[0] - prev[0], cur[1] - prev[1], cur[2] - prev[2]);

            Mathlib.Normalize(ref v1);
            Vector3 v2 = new Vector3(next[0] - prev[0], next[1] - prev[1], next[2] - prev[2]);

            Mathlib.Normalize(ref v2);
            v1 -= v2;
            return((Math.Abs(v1.X) <= COLINEAR_EPSILON) &&
                   (Math.Abs(v1.Y) <= COLINEAR_EPSILON) &&
                   (Math.Abs(v1.Z) <= COLINEAR_EPSILON));
        }
Exemple #21
0
        /// <summary>
        /// SV_AirMove
        /// </summary>
        static void AirMove()
        {
            Vector3 pangles = Common.ToVector(ref _Player.v.angles);

            Mathlib.AngleVectors(ref pangles, out _Forward, out _Right, out _Up);

            float fmove = _Cmd.forwardmove;
            float smove = _Cmd.sidemove;

            // hack to not let you back into teleporter
            if (sv.time < _Player.v.teleport_time && fmove < 0)
            {
                fmove = 0;
            }

            Vector3 wishvel = _Forward * fmove + _Right * smove;

            if ((int)_Player.v.movetype != Movetypes.MOVETYPE_WALK)
            {
                wishvel.Z = _Cmd.upmove;
            }
            else
            {
                wishvel.Z = 0;
            }

            _WishDir   = wishvel;
            _WishSpeed = Mathlib.Normalize(ref _WishDir);
            if (_WishSpeed > _MaxSpeed.Value)
            {
                wishvel   *= _MaxSpeed.Value / _WishSpeed;
                _WishSpeed = _MaxSpeed.Value;
            }

            if (_Player.v.movetype == Movetypes.MOVETYPE_NOCLIP)
            {
                // noclip
                Mathlib.Copy(ref wishvel, out _Player.v.velocity);
            }
            else if (_OnGround)
            {
                UserFriction();
                Accelerate();
            }
            else
            {   // not on ground, so little effect on velocity
                AirAccelerate(wishvel);
            }
        }
Exemple #22
0
        // SND_Spatialize
        static void Spatialize(channel_t ch)
        {
            // anything coming from the view entity will allways be full volume
            if (ch.entnum == Client.Cl.viewentity)
            {
                ch.leftvol  = ch.master_vol;
                ch.rightvol = ch.master_vol;
                return;
            }

            // calculate stereo seperation and distance attenuation
            SFX     snd        = ch.sfx;
            Vector3 source_vec = ch.origin - _ListenerOrigin;

            float dist = Mathlib.Normalize(ref source_vec) * ch.dist_mult;
            float dot  = Vector3.Dot(_ListenerRight, source_vec);

            float rscale, lscale;

            if (_shm.channels == 1)
            {
                rscale = 1.0f;
                lscale = 1.0f;
            }
            else
            {
                rscale = 1.0f + dot;
                lscale = 1.0f - dot;
            }

            // add in distance effect
            float scale = (1.0f - dist) * rscale;

            ch.rightvol = (int)(ch.master_vol * scale);
            if (ch.rightvol < 0)
            {
                ch.rightvol = 0;
            }

            scale      = (1.0f - dist) * lscale;
            ch.leftvol = (int)(ch.master_vol * scale);
            if (ch.leftvol < 0)
            {
                ch.leftvol = 0;
            }
        }
Exemple #23
0
        /*
         * ==============
         * PF_changeyaw
         *
         * This was a major timewaster in progs, so it was converted to C
         * ==============
         */
        public static void PF_changeyaw()
        {
            edict_t ent     = Server.ProgToEdict(Progs.GlobalStruct.self);
            float   current = Mathlib.AngleMod(ent.v.angles.y);
            float   ideal   = ent.v.ideal_yaw;
            float   speed   = ent.v.yaw_speed;

            if (current == ideal)
            {
                return;
            }

            float move = ideal - current;

            if (ideal > current)
            {
                if (move >= 180)
                {
                    move = move - 360;
                }
            }
            else
            {
                if (move <= -180)
                {
                    move = move + 360;
                }
            }
            if (move > 0)
            {
                if (move > speed)
                {
                    move = speed;
                }
            }
            else
            {
                if (move < -speed)
                {
                    move = -speed;
                }
            }

            ent.v.angles.y = Mathlib.AngleMod(current + move);
        }
Exemple #24
0
        static void PF_makestatic()
        {
            edict_t       ent = GetEdict(OFS.OFS_PARM0);
            MessageWriter msg = Server.sv.signon;

            msg.WriteByte(Protocol.svc_spawnstatic);
            msg.WriteByte(Server.ModelIndex(Progs.GetString(ent.v.model)));
            msg.WriteByte((int)ent.v.frame);
            msg.WriteByte((int)ent.v.colormap);
            msg.WriteByte((int)ent.v.skin);
            for (int i = 0; i < 3; i++)
            {
                msg.WriteCoord(Mathlib.Comp(ref ent.v.origin, i));
                msg.WriteAngle(Mathlib.Comp(ref ent.v.angles, i));
            }

            // throw the entity away now
            Server.FreeEdict(ent);
        }
        /// <summary>
        /// SV_CheckVelocity
        /// </summary>
        static void CheckVelocity(edict_t ent)
        {
            //
            // bound velocity
            //
            if (Mathlib.CheckNaN(ref ent.v.velocity, 0))
            {
                Con.Print("Got a NaN velocity on {0}\n", Progs.GetString(ent.v.classname));
            }

            if (Mathlib.CheckNaN(ref ent.v.origin, 0))
            {
                Con.Print("Got a NaN origin on {0}\n", Progs.GetString(ent.v.classname));
            }

            Vector3 max = Vector3.One * _MaxVelocity.Value;
            Vector3 min = -Vector3.One * _MaxVelocity.Value;

            Mathlib.Clamp(ref ent.v.velocity, ref min, ref max, out ent.v.velocity);
        }
Exemple #26
0
        /// <summary>
        /// V_CalcRoll
        /// Used by view and sv_user
        /// </summary>
        public static float CalcRoll(ref Vector3 angles, ref Vector3 velocity)
        {
            Mathlib.AngleVectors(ref angles, out _Forward, out _Right, out _Up);
            float side = Vector3.Dot(velocity, _Right);
            float sign = side < 0 ? -1 : 1;

            side = Math.Abs(side);

            float value = _ClRollAngle.Value;

            if (side < _ClRollSpeed.Value)
            {
                side = side * value / _ClRollSpeed.Value;
            }
            else
            {
                side = value;
            }

            return(side * sign);
        }
Exemple #27
0
        /// <summary>
        /// SV_FindTouchedLeafs
        /// </summary>
        static void FindTouchedLeafs(edict_t ent, mnodebase_t node)
        {
            if (node.contents == Contents.CONTENTS_SOLID)
            {
                return;
            }

            // add an efrag if the node is a leaf

            if (node.contents < 0)
            {
                if (ent.num_leafs == Progs.MAX_ENT_LEAFS)
                {
                    return;
                }

                mleaf_t leaf    = (mleaf_t)node;
                int     leafnum = Array.IndexOf(sv.worldmodel.leafs, leaf) - 1;

                ent.leafnums[ent.num_leafs] = (short)leafnum;
                ent.num_leafs++;
                return;
            }

            // NODE_MIXED
            mnode_t  n          = (mnode_t)node;
            mplane_t splitplane = n.plane;
            int      sides      = Mathlib.BoxOnPlaneSide(ref ent.v.absmin, ref ent.v.absmax, splitplane);

            // recurse down the contacted sides
            if ((sides & 1) != 0)
            {
                FindTouchedLeafs(ent, n.children[0]);
            }

            if ((sides & 2) != 0)
            {
                FindTouchedLeafs(ent, n.children[1]);
            }
        }
        /// <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);
        }
Exemple #29
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);
        }
        /// <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);
        }