예제 #1
0
 public static void VectorSubtract(ref v3f a, ref v3f b, out v3f c)
 {
     c.x = a.x - b.x;
     c.y = a.y - b.y;
     c.z = a.z - b.z;
 }
예제 #2
0
 public static void Clamp(ref v3f src, ref Vector3 min, ref Vector3 max, out v3f dest)
 {
     dest.x = Math.Max(Math.Min(src.x, max.X), min.X);
     dest.y = Math.Max(Math.Min(src.y, max.Y), min.Y);
     dest.z = Math.Max(Math.Min(src.z, max.Z), min.Z);
 }
예제 #3
0
 public static void VectorScale(ref v3f a, float scale, out v3f b)
 {
     b.x = a.x * scale;
     b.y = a.y * scale;
     b.z = a.z * scale;
 }
예제 #4
0
 public static void VectorAdd(ref v3f a, ref v3f b, out v3f c)
 {
     c.x = a.x + b.x;
     c.y = a.y + b.y;
     c.z = a.z + b.z;
 }
예제 #5
0
 public static float LengthXY(ref v3f v)
 {
     return((float)Math.Sqrt(v.x * v.x + v.y * v.y));
 }
예제 #6
0
 public static void VectorMA(ref v3f a, float scale, ref v3f b, out v3f c)
 {
     c.x = a.x + b.x * scale;
     c.y = a.y + b.y * scale;
     c.z = a.z + b.z * scale;
 }
예제 #7
0
 public static void Copy(ref v3f src, out Vector3 dest)
 {
     dest.X = src.x;
     dest.Y = src.y;
     dest.Z = src.z;
 }
예제 #8
0
    public static bool SV_movestep(edict_t ent, ref v3f move, bool relink)
    {
        trace_t trace;

        // try the move
        v3f oldorg = ent.v.origin;
        v3f neworg;

        Mathlib.VectorAdd(ref ent.v.origin, ref move, out neworg);

        // flying monsters don't step up
        if (((int)ent.v.flags & (q_shared.FL_SWIM | q_shared.FL_FLY)) != 0)
        {
            // try one move with vertical motion, then one without
            for (int i = 0; i < 2; i++)
            {
                Mathlib.VectorAdd(ref ent.v.origin, ref move, out neworg);
                edict_t enemy = PROG_TO_EDICT(ent.v.enemy);
                if (i == 0 && enemy != sv.edicts[0])
                {
                    float dz = ent.v.origin.z - enemy.v.origin.z;
                    if (dz > 40)
                    {
                        neworg.z -= 8;
                    }
                    if (dz < 30)
                    {
                        neworg.z += 8;
                    }
                }

                trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref neworg, 0, ent);
                if (trace.fraction == 1)
                {
                    if (((int)ent.v.flags & q_shared.FL_SWIM) != 0 &&
                        SV_PointContents(ref trace.endpos) == q_shared.CONTENTS_EMPTY)
                    {
                        return(false);   // swim monster left water
                    }
                    Mathlib.Copy(ref trace.endpos, out ent.v.origin);
                    if (relink)
                    {
                        SV_LinkEdict(ent, true);
                    }
                    return(true);
                }

                if (enemy == sv.edicts[0])
                {
                    break;
                }
            }

            return(false);
        }

        // push down from a step height above the wished position
        neworg.z += q_shared.STEPSIZE;
        v3f end = neworg;

        end.z -= q_shared.STEPSIZE * 2;

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

        if (trace.allsolid)
        {
            return(false);
        }

        if (trace.startsolid)
        {
            neworg.z -= q_shared.STEPSIZE;
            trace     = Move(ref neworg, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent);
            if (trace.allsolid || trace.startsolid)
            {
                return(false);
            }
        }
        if (trace.fraction == 1)
        {
            // if monster had the ground pulled out, go ahead and fall
            if (((int)ent.v.flags & q_shared.FL_PARTIALGROUND) != 0)
            {
                Mathlib.VectorAdd(ref ent.v.origin, ref move, out ent.v.origin);
                if (relink)
                {
                    SV_LinkEdict(ent, true);
                }
                ent.v.flags = (int)ent.v.flags & ~q_shared.FL_ONGROUND;
                return(true);
            }

            return(false);               // walked off an edge
        }

        // check point traces down for dangling corners
        Mathlib.Copy(ref trace.endpos, out ent.v.origin);

        if (!SV_CheckBottom(ent))
        {
            if (((int)ent.v.flags & q_shared.FL_PARTIALGROUND) != 0)
            {
                // entity had floor mostly pulled out from underneath it
                // and is trying to correct
                if (relink)
                {
                    SV_LinkEdict(ent, true);
                }
                return(true);
            }
            ent.v.origin = oldorg;
            return(false);
        }

        if (((int)ent.v.flags & q_shared.FL_PARTIALGROUND) != 0)
        {
            ent.v.flags = (int)ent.v.flags & ~q_shared.FL_PARTIALGROUND;
        }
        ent.v.groundentity = EDICT_TO_PROG(trace.ent);

        // the move is ok
        if (relink)
        {
            SV_LinkEdict(ent, true);
        }
        return(true);
    }
예제 #9
0
    public static void SV_PushMove(edict_t pusher, float movetime)
    {
        if (pusher.v.velocity.IsEmpty)
        {
            pusher.v.ltime += movetime;
            return;
        }

        v3f move, mins, maxs;

        Mathlib.VectorScale(ref pusher.v.velocity, movetime, out move);
        Mathlib.VectorAdd(ref pusher.v.absmin, ref move, out mins);
        Mathlib.VectorAdd(ref pusher.v.absmax, ref move, out maxs);

        v3f pushorig = pusher.v.origin;

        edict_t[] moved_edict = new edict_t[q_shared.MAX_EDICTS];
        v3f[]     moved_from  = new v3f[q_shared.MAX_EDICTS];

        // move the pusher to it's final position

        Mathlib.VectorAdd(ref pusher.v.origin, ref move, out pusher.v.origin);
        pusher.v.ltime += movetime;
        SV_LinkEdict(pusher, false);


        // see if any solid entities are inside the final position
        int num_moved = 0;

        for (int e = 1; e < sv.num_edicts; e++)
        {
            edict_t check = sv.edicts[e];
            if (check.free)
            {
                continue;
            }
            if (check.v.movetype == q_shared.MOVETYPE_PUSH ||
                check.v.movetype == q_shared.MOVETYPE_NONE ||
                check.v.movetype == q_shared.MOVETYPE_NOCLIP)
            {
                continue;
            }

            // if the entity is standing on the pusher, it will definately be moved
            if (!(((int)check.v.flags & q_shared.FL_ONGROUND) != 0 && PROG_TO_EDICT(check.v.groundentity) == pusher))
            {
                if (check.v.absmin.x >= maxs.x || check.v.absmin.y >= maxs.y ||
                    check.v.absmin.z >= maxs.z || check.v.absmax.x <= mins.x ||
                    check.v.absmax.y <= mins.y || check.v.absmax.z <= mins.z)
                {
                    continue;
                }

                // see if the ent's bbox is inside the pusher's final position
                if (SV_TestEntityPosition(check) == null)
                {
                    continue;
                }
            }

            // remove the onground flag for non-players
            if (check.v.movetype != q_shared.MOVETYPE_WALK)
            {
                check.v.flags = (int)check.v.flags & ~q_shared.FL_ONGROUND;
            }

            v3f entorig = check.v.origin;
            moved_from[num_moved]  = entorig;
            moved_edict[num_moved] = check;
            num_moved++;

            // try moving the contacted entity
            pusher.v.solid = q_shared.SOLID_NOT;
            PushEntity(check, ref move);
            pusher.v.solid = q_shared.SOLID_BSP;

            // if it is still inside the pusher, block
            edict_t block = SV_TestEntityPosition(check);
            if (block != null)
            {
                // fail the move
                if (check.v.mins.x == check.v.maxs.x)
                {
                    continue;
                }
                if (check.v.solid == q_shared.SOLID_NOT || check.v.solid == q_shared.SOLID_TRIGGER)
                {
                    // corpse
                    check.v.mins.x = check.v.mins.y = 0;
                    check.v.maxs   = check.v.mins;
                    continue;
                }

                check.v.origin = entorig;
                SV_LinkEdict(check, true);

                pusher.v.origin = pushorig;
                SV_LinkEdict(pusher, false);
                pusher.v.ltime -= movetime;

                // if the pusher has a "blocked" function, call it
                // otherwise, just stay in place until the obstacle is gone
                if (pusher.v.blocked != 0)
                {
                    pr_global_struct.self  = EDICT_TO_PROG(pusher);
                    pr_global_struct.other = EDICT_TO_PROG(check);
                    PR_ExecuteProgram(pusher.v.blocked);
                }

                // move back any entities we already moved
                for (int i = 0; i < num_moved; i++)
                {
                    moved_edict[i].v.origin = moved_from[i];
                    SV_LinkEdict(moved_edict[i], false);
                }
                return;
            }
        }
    }
예제 #10
0
 public static float DotProduct(ref v3f a, ref v3f b)
 {
     return(a.x * b.x + a.y * b.y + a.z * b.z);
 }
예제 #11
0
    public static int SV_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[q_shared.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 == q_shared.SOLID_BSP)
                {
                    ent.v.flags        = (int)ent.v.flags | q_shared.FL_ONGROUND;
                    ent.v.groundentity = EDICT_TO_PROG(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
            //
            SV_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 >= q_shared.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);
    }
예제 #12
0
    public static void SV_WalkMove(edict_t ent)
    {
        //
        // do a regular slide move unless it looks like you ran into a step
        //
        int oldonground = (int)ent.v.flags & q_shared.FL_ONGROUND;

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

        v3f     oldorg    = ent.v.origin;
        v3f     oldvel    = ent.v.velocity;
        trace_t steptrace = new trace_t();
        int     clip      = SV_FlyMove(ent, (float)host_framtime, 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 != q_shared.MOVETYPE_WALK)
        {
            return;             // gibbed by a trigger
        }
        if (sv_nostep.value != 0)
        {
            return;
        }

        if (((int)sv_player.v.flags & q_shared.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   = q_shared.ZeroVector3f;
        v3f downmove = upmove;

        upmove.z   = q_shared.STEPSIZE;
        downmove.z = (float)(-q_shared.STEPSIZE + oldvel.z * host_framtime);

        // 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             = SV_FlyMove(ent, (float)host_framtime, 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 = SV_TryUnstick(ent, ref oldvel);
            }
        }

        // extra friction based on view angle
        if ((clip & 2) != 0)
        {
            SV_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 == q_shared.SOLID_BSP)
            {
                ent.v.flags        = (int)ent.v.flags | q_shared.FL_ONGROUND;
                ent.v.groundentity = EDICT_TO_PROG(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;
        }
    }
예제 #13
0
        private void ParseClustersPacket(BinaryReader br)
        {
            ClusterMsg msg = new ClusterMsg();

            // read the header

            byte packetType = br.ReadByte();

            if (packetType != CLUSTER_PACKET_TYPE)
            {
                Debug.WriteLine("ERROR: cluster parser got packet starting with " + packetType.ToString());
                return;
            }

            UInt16 packetNum = br.ReadUInt16();
            UInt16 tsSeconds = br.ReadUInt16();
            UInt32 tsTicks   = br.ReadUInt32();

            UInt16 numPts      = br.ReadUInt16();
            UInt16 numClusters = br.ReadUInt16();

            msg.timestamp = (double)tsSeconds + (double)tsTicks / 10000.0;
            // now for the red meat..

            v3f[] pts = new v3f[numPts];
            for (int i = 0; i < numPts; i++)
            {
                pts[i].x = (float)(br.ReadInt16()) / 100.0f;
                pts[i].y = (float)(br.ReadInt16()) / 100.0f;
                pts[i].z = (float)(br.ReadInt16()) / 100.0f;
            }

            msg.clusters = new List <LidarCluster>();

            for (int i = 0; i < numClusters; i++)
            {
                LidarCluster lc = new LidarCluster();
                UInt16       firstPtIndex, lastPtIndex;
                byte         flags;

                firstPtIndex = br.ReadUInt16();
                lastPtIndex  = br.ReadUInt16();
                flags        = br.ReadByte();

                lc.pts           = new v3f[lastPtIndex - firstPtIndex + 1];
                lc.stable        = (flags & 0x01) == 0;
                lc.leftOccluded  = (flags & 0x02) != 0;
                lc.rightOccluded = (flags & 0x04) != 0;
                lc.highObstacle  = (flags & 0x08) != 0;

                lc.bb_low.x = lc.bb_high.x = pts[firstPtIndex].x;
                lc.bb_low.y = lc.bb_high.y = pts[firstPtIndex].y;
                lc.bb_low.z = lc.bb_high.z = pts[firstPtIndex].z;

                for (int j = firstPtIndex; j <= lastPtIndex; j++)
                {
                    lc.pts[j - firstPtIndex] = pts[j];
                    lc.bb_low.x  = Math.Min(lc.bb_low.x, pts[j].x);
                    lc.bb_low.y  = Math.Min(lc.bb_low.y, pts[j].y);
                    lc.bb_low.z  = Math.Min(lc.bb_low.z, pts[j].z);
                    lc.bb_high.x = Math.Max(lc.bb_high.x, pts[j].x);
                    lc.bb_high.y = Math.Max(lc.bb_high.y, pts[j].y);
                    lc.bb_high.z = Math.Max(lc.bb_high.z, pts[j].z);
                }

                msg.clusters.Add(lc);
            }

            if (ClustersReceived != null)
            {
                ClustersReceived(this, new ClusterRXEventArgs(msg));
            }
        }
예제 #14
0
 public static Vector3 ToVector(ref v3f v)
 {
     return(new Vector3(v.x, v.y, v.z));
 }
예제 #15
0
 public static void Copy(ref Vector3 src, out v3f dest)
 {
     dest.x = src.X;
     dest.y = src.Y;
     dest.z = src.Z;
 }
예제 #16
0
 static unsafe void Copy(float *src, ref v3f dest)
 {
     dest.x = src[0];
     dest.y = src[1];
     dest.z = src[2];
 }
예제 #17
0
    public static void SV_SetIdealPitch()
    {
        if (((int)sv_player.v.flags & q_shared.FL_ONGROUND) == 0)
        {
            return;
        }

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

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

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

            trace_t tr = Move(ref top, ref q_shared.ZeroVector3f, ref q_shared.ZeroVector3f, ref bottom, 1, sv_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 < q_shared.MAX_FORWARD; j++)
        {
            float step = z[j] - z[j - 1];                                  // Uze: int in original code???
            if (step > -q_shared.ON_EPSILON && step < q_shared.ON_EPSILON) // Uze: comparing int with ON_EPSILON (0.1)???
            {
                continue;
            }

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

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

        if (steps < 2)
        {
            return;
        }
        sv_player.v.idealpitch = -dir * sv_idealpitchscale.value;
    }