示例#1
0
        public static int BoxOnPlaneSide(ref v3f emins, ref v3f emaxs, mplane_t p)
        {
            float mindist, maxdist;
            switch (p.type)
            {
                case 0:
                    mindist = emins.x;
                    maxdist = emaxs.x;
                    break;

                case 1:
                    mindist = emins.y;
                    maxdist = emaxs.y;
                    break;

                case 2:
                    mindist = emins.z;
                    maxdist = emaxs.z;
                    break;

                default:
                    Vector3 mins, maxs;
                    Copy(ref emins, out mins);
                    Copy(ref emaxs, out maxs);
                    return _BoxOnPlaneSide(ref mins, ref maxs, p);
            }
            return (p.dist <= mindist ? 1 : (p.dist >= maxdist ? 2 : 3));
        }
示例#2
0
 /// <summary>
 /// c = a + b * scale;
 /// </summary>
 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;
 }
示例#3
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;
            }
        }
示例#4
0
 public static float LengthXY(ref v3f v)
 {
     return((float)Math.Sqrt(v.x * v.x + v.y * v.y));
 }
示例#5
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;
 }
示例#6
0
 /// <summary>
 /// c = a + b * scale;
 /// </summary>
 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 float Normalize(ref v3f v)
 {
     float length = (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
     if (length != 0)
     {
         float ool = 1 / length;
         v.x *= ool;
         v.y *= ool;
         v.z *= ool;
     }
     return length;
 }
示例#8
0
 public static void Copy(ref v3f src, out Vector3 dest)
 {
     dest.X = src.x;
     dest.Y = src.y;
     dest.Z = src.z;
 }
示例#9
0
        /// <summary>
        /// SV_PushMove
        /// </summary>
        static void 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[QDef.MAX_EDICTS];
            v3f[] moved_from = new v3f[QDef.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;
            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 == Movetypes.MOVETYPE_PUSH ||
                    check.v.movetype == Movetypes.MOVETYPE_NONE ||
                    check.v.movetype == Movetypes.MOVETYPE_NOCLIP)
                    continue;

                // if the entity is standing on the pusher, it will definately be moved
                if (!(((int)check.v.flags & EdictFlags.FL_ONGROUND) != 0 && ProgToEdict(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 (TestEntityPosition(check) == null)
                        continue;
                }

                // remove the onground flag for non-players
                if (check.v.movetype != Movetypes.MOVETYPE_WALK)
                    check.v.flags = (int)check.v.flags & ~EdictFlags.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 = Solids.SOLID_NOT;
                PushEntity(check, ref move);
                pusher.v.solid = Solids.SOLID_BSP;

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

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

                    pusher.v.origin = pushorig;
                    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)
                    {
                        Progs.GlobalStruct.self = EdictToProg(pusher);
                        Progs.GlobalStruct.other = EdictToProg(check);
                        Progs.Execute(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];
                        LinkEdict(moved_edict[i], false);
                    }
                    return;
                }
            }
        }
示例#10
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;
        }
示例#11
0
 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);
 }
示例#12
0
        /// <summary>
        /// ClipVelocity
        /// Slide off of the impacting object
        /// returns the blocked flags (1 = floor, 2 = step / wall)
        /// </summary>
        static int ClipVelocity(ref v3f src, ref Vector3 normal, out v3f dest, float overbounce)
        {
            int blocked = 0;
            if (normal.Z > 0)
                blocked |= 1;		// floor
            if (normal.Z == 0)
                blocked |= 2;		// step

            float backoff = (src.x * normal.X + src.y * normal.Y + src.z * normal.Z) * overbounce;

            dest.x = src.x - normal.X * backoff;
            dest.y = src.y - normal.Y * backoff;
            dest.z = src.z - normal.Z * backoff;

            if (dest.x > -STOP_EPSILON && dest.x < STOP_EPSILON) dest.x = 0;
            if (dest.y > -STOP_EPSILON && dest.y < STOP_EPSILON) dest.y = 0;
            if (dest.z > -STOP_EPSILON && dest.z < STOP_EPSILON) dest.z = 0;

            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>
        private 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
 static unsafe void Copy(float* src, ref v3f dest)
 {
     dest.x = src[0];
     dest.y = src[1];
     dest.z = src[2];
 }
示例#15
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;
 }
示例#16
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);
 }
示例#17
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
        }
示例#18
0
 /// <summary>
 /// G_VECTOR(OFS_RETURN) = value
 /// </summary>
 public static unsafe void ReturnVector(ref v3f value)
 {
     float* ptr = (float*)Progs.GlobalStructAddr;
     ptr[OFS.OFS_RETURN + 0] = value.x;
     ptr[OFS.OFS_RETURN + 1] = value.y;
     ptr[OFS.OFS_RETURN + 2] = value.z;
 }
示例#19
0
        /// <summary>
        /// SV_movestep
        /// Called by monster program code.
        /// The move will be adjusted for slopes and stairs, but if the move isn't
        /// possible, no move is done, false is returned, and
        /// pr_global_struct.trace_normal is set to the normal of the blocking wall
        /// </summary>
        public static bool 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 & (EdictFlags.FL_SWIM | EdictFlags.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 = ProgToEdict(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 & EdictFlags.FL_SWIM) != 0 &&
                            PointContents(ref trace.endpos) == Contents.CONTENTS_EMPTY)
                        {
                            return(false);       // swim monster left water
                        }
                        Mathlib.Copy(ref trace.endpos, out ent.v.origin);
                        if (relink)
                        {
                            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 += STEPSIZE;
            v3f end = neworg;

            end.z -= 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 -= 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 & EdictFlags.FL_PARTIALGROUND) != 0)
                {
                    Mathlib.VectorAdd(ref ent.v.origin, ref move, out ent.v.origin);
                    if (relink)
                    {
                        LinkEdict(ent, true);
                    }
                    ent.v.flags = (int)ent.v.flags & ~EdictFlags.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 (!CheckBottom(ent))
            {
                if (((int)ent.v.flags & EdictFlags.FL_PARTIALGROUND) != 0)
                {
                    // entity had floor mostly pulled out from underneath it
                    // and is trying to correct
                    if (relink)
                    {
                        LinkEdict(ent, true);
                    }
                    return(true);
                }
                ent.v.origin = oldorg;
                return(false);
            }

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

            // the move is ok
            if (relink)
            {
                LinkEdict(ent, true);
            }
            return(true);
        }
示例#20
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;
 }
示例#21
0
 static unsafe void Copy(float *src, ref v3f dest)
 {
     dest.x = src[0];
     dest.y = src[1];
     dest.z = src[2];
 }
示例#22
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;
 }
示例#23
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;
        }
示例#24
0
 public static bool CheckNaN(ref v3f v, float defValue)
 {
     bool flag = false;
     if (float.IsNaN(v.x))
     {
         flag = true;
         v.x = defValue;
     }
     if (float.IsNaN(v.y))
     {
         flag = true;
         v.y = defValue;
     }
     if (float.IsNaN(v.z))
     {
         flag = true;
         v.z = defValue;
     }
     return flag;
 }
示例#25
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);
 }
示例#26
0
        /// <summary>
        /// SV_PushMove
        /// </summary>
        static void 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[QDef.MAX_EDICTS];
            v3f[]     moved_from  = new v3f[QDef.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;
            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 == Movetypes.MOVETYPE_PUSH ||
                    check.v.movetype == Movetypes.MOVETYPE_NONE ||
                    check.v.movetype == Movetypes.MOVETYPE_NOCLIP)
                {
                    continue;
                }

                // if the entity is standing on the pusher, it will definately be moved
                if (!(((int)check.v.flags & EdictFlags.FL_ONGROUND) != 0 && ProgToEdict(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 (TestEntityPosition(check) == null)
                    {
                        continue;
                    }
                }

                // remove the onground flag for non-players
                if (check.v.movetype != Movetypes.MOVETYPE_WALK)
                {
                    check.v.flags = (int)check.v.flags & ~EdictFlags.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 = Solids.SOLID_NOT;
                PushEntity(check, ref move);
                pusher.v.solid = Solids.SOLID_BSP;

                // if it is still inside the pusher, block
                edict_t block = TestEntityPosition(check);
                if (block != null)
                {
                    // fail the move
                    if (check.v.mins.x == check.v.maxs.x)
                    {
                        continue;
                    }

                    if (check.v.solid == Solids.SOLID_NOT || check.v.solid == Solids.SOLID_TRIGGER)
                    {
                        // corpse
                        check.v.mins.x = check.v.mins.y = 0;
                        check.v.maxs   = check.v.mins;
                        continue;
                    }

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

                    pusher.v.origin = pushorig;
                    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)
                    {
                        Progs.GlobalStruct.self  = EdictToProg(pusher);
                        Progs.GlobalStruct.other = EdictToProg(check);
                        Progs.Execute(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];
                        LinkEdict(moved_edict[i], false);
                    }
                    return;
                }
            }
        }
示例#27
0
 public static float Comp(ref v3f a, int index)
 {
     if (index < 0 || index > 2)
         throw new ArgumentOutOfRangeException("index");
     return (index == 0 ? a.x : (index == 1 ? a.y : a.z));
 }
示例#28
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);
        }
示例#29
0
 //static Vector3 PerpendicularVector(ref Vector3 src)
 //{
 //    float minelem = 1.0f;
 //    // find the smallest magnitude axially aligned vector
 //    Vector3 tempvec = Vector3.Zero;
 //    if (Math.Abs(src.X) < minelem)
 //    {
 //        minelem = Math.Abs(src.X);
 //        tempvec.X = 1;
 //    }
 //    if (Math.Abs(src.Y) < minelem)
 //    {
 //        minelem = Math.Abs(src.Y);
 //        tempvec = new Vector3(0, 1, 0);
 //    }
 //    else if (Math.Abs(src.Z) < minelem)
 //    {
 //        tempvec = new Vector3(0, 0, 1);
 //    }
 //    // project the point onto the plane defined by src
 //    Vector3 dst = ProjectPointOnPlane(ref tempvec, ref src);
 //    Normalize(ref dst);
 //    return dst;
 //}
 //static Vector3 ProjectPointOnPlane(ref Vector3 p, ref Vector3 normal)
 //{
 //    float inv_denom = 1.0f / normal.LengthSquared;
 //    float d = Vector3.Dot(normal, p) * inv_denom;
 //    Vector3 n = normal * inv_denom;
 //    return p - d * n;
 //}
 public static void Copy(ref v3f src, out Vector3 dest)
 {
     dest.X = src.x;
     dest.Y = src.y;
     dest.Z = src.z;
 }
示例#30
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;
 }
示例#31
0
 public static void Copy(ref Vector3 src, out v3f dest)
 {
     dest.x = src.X;
     dest.y = src.Y;
     dest.z = src.Z;
 }
示例#32
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;
 }
示例#33
0
 public static float DotProduct(ref v3f a, ref v3f b)
 {
     return a.x * b.x + a.y * b.y + a.z * b.z;
 }
示例#34
0
 public static float DotProduct(ref v3f a, ref v3f b)
 {
     return(a.x * b.x + a.y * b.y + a.z * b.z);
 }
示例#35
0
 public static float LengthXY(ref v3f v)
 {
     return (float)Math.Sqrt(v.x * v.x + v.y * v.y);
 }
示例#36
0
 //    return p - d * n;
 //}
 public static void Copy(ref Vector3 src, out v3f dest)
 {
     dest.x = src.X;
     dest.y = src.Y;
     dest.z = src.Z;
 }
示例#37
0
        /// <summary>
        /// SV_movestep
        /// Called by monster program code.
        /// The move will be adjusted for slopes and stairs, but if the move isn't
        /// possible, no move is done, false is returned, and
        /// pr_global_struct.trace_normal is set to the normal of the blocking wall
        /// </summary>
        public static bool 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 & (EdictFlags.FL_SWIM | EdictFlags.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 = ProgToEdict(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 & EdictFlags.FL_SWIM) != 0 &&
                            PointContents(ref trace.endpos) == Contents.CONTENTS_EMPTY)
                            return false;	// swim monster left water

                        Mathlib.Copy(ref trace.endpos, out ent.v.origin);
                        if (relink)
                            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 += STEPSIZE;
            v3f end = neworg;
            end.z -= 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 -= 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 & EdictFlags.FL_PARTIALGROUND) != 0)
                {
                    Mathlib.VectorAdd(ref ent.v.origin, ref move, out ent.v.origin);
                    if (relink)
                        LinkEdict(ent, true);
                    ent.v.flags = (int)ent.v.flags & ~EdictFlags.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 (!CheckBottom(ent))
            {
                if (((int)ent.v.flags & EdictFlags.FL_PARTIALGROUND) != 0)
                {
                    // entity had floor mostly pulled out from underneath it
                    // and is trying to correct
                    if (relink)
                        LinkEdict(ent, true);
                    return true;
                }
                ent.v.origin = oldorg;
                return false;
            }

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

            // the move is ok
            if (relink)
                LinkEdict(ent, true);
            return true;
        }