Example #1
0
        /**
         * Monsters freefall when they don't have a ground entity, otherwise all
         * movement is done with discrete steps.
         *
         * This is also used for objects that have become still on the ground, but
         * will fall if the floor is pulled out from under them. FIXME: is this
         * true?
         */
        public static void SV_Physics_Step(edict_t ent)
        {
            bool wasonground;
            var  hitsound = false;

            float[] vel;
            float   speed, newspeed, control;
            float   friction;
            edict_t groundentity;
            int     mask;

            // airborn monsters should always check for ground
            if (ent.groundentity == null)
            {
                M.M_CheckGround(ent);
            }

            groundentity = ent.groundentity;

            SV.SV_CheckVelocity(ent);

            if (groundentity != null)
            {
                wasonground = true;
            }
            else
            {
                wasonground = false;
            }

            if (ent.avelocity[0] != 0 || ent.avelocity[1] != 0 || ent.avelocity[2] != 0)
            {
                SV.SV_AddRotationalFriction(ent);
            }

            // add gravity except:
            //   flying monsters
            //   swimming monsters who are in the water
            if (!wasonground)
            {
                if (0 == (ent.flags & Defines.FL_FLY))
                {
                    if (!((ent.flags & Defines.FL_SWIM) != 0 && ent.waterlevel > 2))
                    {
                        if (ent.velocity[2] < GameBase.sv_gravity.value * -0.1)
                        {
                            hitsound = true;
                        }

                        if (ent.waterlevel == 0)
                        {
                            SV.SV_AddGravity(ent);
                        }
                    }
                }
            }

            // friction for flying monsters that have been given vertical velocity
            if ((ent.flags & Defines.FL_FLY) != 0 && ent.velocity[2] != 0)
            {
                speed    = Math.Abs(ent.velocity[2]);
                control  = speed < Defines.sv_stopspeed ? Defines.sv_stopspeed : speed;
                friction = Defines.sv_friction / 3;
                newspeed = speed - Defines.FRAMETIME * control * friction;

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

                newspeed        /= speed;
                ent.velocity[2] *= newspeed;
            }

            // friction for flying monsters that have been given vertical velocity
            if ((ent.flags & Defines.FL_SWIM) != 0 && ent.velocity[2] != 0)
            {
                speed    = Math.Abs(ent.velocity[2]);
                control  = speed < Defines.sv_stopspeed ? Defines.sv_stopspeed : speed;
                newspeed = speed - Defines.FRAMETIME * control * Defines.sv_waterfriction * ent.waterlevel;

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

                newspeed        /= speed;
                ent.velocity[2] *= newspeed;
            }

            if (ent.velocity[2] != 0 || ent.velocity[1] != 0 || ent.velocity[0] != 0)
            {
                // apply friction
                // let dead monsters who aren't completely onground slide
                if (wasonground || 0 != (ent.flags & (Defines.FL_SWIM | Defines.FL_FLY)))
                {
                    if (!(ent.health <= 0.0 && !M.M_CheckBottom(ent)))
                    {
                        vel   = ent.velocity;
                        speed = (float)Math.Sqrt(vel[0] * vel[0] + vel[1] * vel[1]);

                        if (speed != 0)
                        {
                            friction = Defines.sv_friction;

                            control  = speed < Defines.sv_stopspeed ? Defines.sv_stopspeed : speed;
                            newspeed = speed - Defines.FRAMETIME * control * friction;

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

                            newspeed /= speed;

                            vel[0] *= newspeed;
                            vel[1] *= newspeed;
                        }
                    }
                }

                if ((ent.svflags & Defines.SVF_MONSTER) != 0)
                {
                    mask = Defines.MASK_MONSTERSOLID;
                }
                else
                {
                    mask = Defines.MASK_SOLID;
                }

                SV.SV_FlyMove(ent, Defines.FRAMETIME, mask);

                GameBase.gi.linkentity(ent);
                GameBase.G_TouchTriggers(ent);

                if (!ent.inuse)
                {
                    return;
                }

                if (ent.groundentity != null)
                {
                    if (!wasonground)
                    {
                        if (hitsound)
                        {
                            GameBase.gi.sound(ent, 0, GameBase.gi.soundindex("world/land.wav"), 1, 1, 0);
                        }
                    }
                }
            }

            // regular thinking
            SV.SV_RunThink(ent);
        }
Example #2
0
        /**
         * Toss, bounce, and fly movement. When onground, do nothing.
         */
        public static void SV_Physics_Toss(edict_t ent)
        {
            trace_t trace;

            float[] move = { 0, 0, 0 };
            float   backoff;
            edict_t slave;
            bool    wasinwater;
            bool    isinwater;

            float[] old_origin = { 0, 0, 0 };

            //	   regular thinking
            SV.SV_RunThink(ent);

            // if not a team captain, so movement will be handled elsewhere
            if ((ent.flags & Defines.FL_TEAMSLAVE) != 0)
            {
                return;
            }

            if (ent.velocity[2] > 0)
            {
                ent.groundentity = null;
            }

            //	check for the groundentity going away
            if (ent.groundentity != null)
            {
                if (!ent.groundentity.inuse)
                {
                    ent.groundentity = null;
                }
            }

            //	   if onground, return without moving
            if (ent.groundentity != null)
            {
                return;
            }

            Math3D.VectorCopy(ent.s.origin, old_origin);

            SV.SV_CheckVelocity(ent);

            //	   add gravity
            if (ent.movetype != Defines.MOVETYPE_FLY && ent.movetype != Defines.MOVETYPE_FLYMISSILE)
            {
                SV.SV_AddGravity(ent);
            }

            //	   move angles
            Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles);

            //	   move origin
            Math3D.VectorScale(ent.velocity, Defines.FRAMETIME, move);
            trace = SV.SV_PushEntity(ent, move);

            if (!ent.inuse)
            {
                return;
            }

            if (trace.fraction < 1)
            {
                if (ent.movetype == Defines.MOVETYPE_BOUNCE)
                {
                    backoff = 1.5f;
                }
                else
                {
                    backoff = 1;
                }

                GameBase.ClipVelocity(ent.velocity, trace.plane.normal, ent.velocity, backoff);

                // stop if on ground
                if (trace.plane.normal[2] > 0.7)
                {
                    if (ent.velocity[2] < 60 || ent.movetype != Defines.MOVETYPE_BOUNCE)
                    {
                        ent.groundentity           = trace.ent;
                        ent.groundentity_linkcount = trace.ent.linkcount;
                        Math3D.VectorCopy(Globals.vec3_origin, ent.velocity);
                        Math3D.VectorCopy(Globals.vec3_origin, ent.avelocity);
                    }
                }

                // if (ent.touch)
                //	ent.touch (ent, trace.ent, &trace.plane, trace.surface);
            }

            //	   check for water transition
            wasinwater    = (ent.watertype & Defines.MASK_WATER) != 0;
            ent.watertype = GameBase.gi.pointcontents(ent.s.origin);
            isinwater     = (ent.watertype & Defines.MASK_WATER) != 0;

            if (isinwater)
            {
                ent.waterlevel = 1;
            }
            else
            {
                ent.waterlevel = 0;
            }

            if (!wasinwater && isinwater)
            {
                GameBase.gi.positioned_sound(old_origin, ent, Defines.CHAN_AUTO, GameBase.gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
            }
            else if (wasinwater && !isinwater)
            {
                GameBase.gi.positioned_sound(ent.s.origin, ent, Defines.CHAN_AUTO, GameBase.gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
            }

            //	   move teamslaves
            for (slave = ent.teamchain; slave != null; slave = slave.teamchain)
            {
                Math3D.VectorCopy(ent.s.origin, slave.s.origin);
                GameBase.gi.linkentity(slave);
            }
        }