Пример #1
0
        void PlayerMoveSingle(pmove_t pmove)
        {
            pm = pmove;

            // clear all pmove local vars
            pml = new pml_t();
            pml.forward = Vector3.Zero;
            pml.up = Vector3.Zero;
            pml.right = Vector3.Zero;
            pm.upmove = pm.cmd.upmove;
            pm.rightmove = pm.cmd.rightmove;
            pm.forwardmove = pm.cmd.forwardmove;

            // determine the time
            pml.msec = pm.cmd.serverTime - pm.ps.commandTime;
            if (pml.msec < 1)
                pml.msec = 1;
            else if (pml.msec > 200)
                pml.msec = 200;
            pm.ps.commandTime = pm.cmd.serverTime;
            // save old org in case we get stuck
            pml.previous_origin = pm.ps.origin;

            // save old velocity for crashlanding
            pml.previous_velocity = pm.ps.velocity;

            pml.frametime = pml.msec * 0.001f;

            UpdateViewAngles(ref pm.ps, pm.cmd);
            // Convert view angles to vectors
            AngleVectors(pm.ps.viewangles, ref pml.forward, ref pml.right, ref pml.up);

            // Adjust speeds etc.
            CheckParameters();

            // Assume we don't touch anything
            pm.numtouch = 0;

            DropTimers();

            pm.mins = Common.playerMins;
            pm.maxs = Common.playerMaxs;

            // UnStuck

            // Now that we are "unstuck", see where we are ( waterlevel and type, pmove->onground ).
            CategorizePosition();

            // If we are not on ground, store off how fast we are moving down
            if (!pml.groundPlane)
                pml.fallVelocity = -pm.ps.velocity[2];

            Duck();

            if (LadderMove())
            {

            }
            else if(pm.ps.pm_type == PMType.LADDER)
            {
                // clear ladder stuff unless player is noclipping or being lifted by barnacle.
                // it will be set immediately again next frame if necessary
                pm.ps.pm_type = PMType.NORMAL;

            }
            //

            if (pml.groundPlane && (pm.cmd.buttons & (int)Input.ButtonDef.USE) > 0 && !speedCropped)
            {
                float frac = 1f / 3.0f;
                pm.rightmove *= frac;
                pm.upmove *= frac;
                pm.forwardmove *= frac;
                speedCropped = true;
            }

            switch (pm.ps.pm_type)
            {
                case PMType.SPECTATOR:
                    TryPlayerMove();
                    DropTimers();
                    break;
                case PMType.LADDER:
                    FullLadderMove(false);
                    break;
                case PMType.NORMAL:
                    FullWalkMove(false);
                    break;
                default:
                    Common.Instance.WriteLine("Unknown movetype: " + Enum.GetName(typeof(PMType), pm.ps.pm_type));
                    break;
            }
        }
Пример #2
0
        void SpectatorThink(gentity_t ent, Input.UserCommand ucmd)
        {
            gclient_t client = ent.client;
            if (client.sess.spectatorState != spectatorState_t.SPECTATOR_FOLLOW)
            {
                client.ps.pm_type = Common.PMType.SPECTATOR;
                client.ps.speed = sv_speed.Integer;  // faster than normal

                // set up for pmove
                pmove_t pm = new pmove_t();
                pm.Trace = new TraceDelegate(Server.Instance.SV_Trace);
                pm.ps = client.ps;
                pm.cmd = ucmd;
                pm.tracemask = (int)(brushflags.CONTENTS_SOLID | brushflags.CONTENTS_MOVEABLE | brushflags.CONTENTS_SLIME | brushflags.CONTENTS_OPAQUE);
                pm.pmove_fixed = CVars.Instance.VariableIntegerValue("pmove_fixed");
                pm.pmove_msec = CVars.Instance.VariableIntegerValue("pmove_msec");
                //pm.Trace += new TraceDelegate(Server.Instance.Trace);
                //pm.PointContents += new TraceContentsDelegate(Server.Instance.PointContents);
                pm.mins = Common.playerMins;
                pm.maxs = Common.playerMaxs;
                // perform a pmove
                Common.Instance.Pmove(pm);
                //if(!pm.ps.velocity.Equals(Vector3.Zero))
                //Common.Instance.WriteLine("vel: {0}", pm.ps.velocity);
                // save results of pmove
                ent.s.origin = client.ps.origin;

                Server.Instance.UnlinkEntity(GEntityToSharedEntity(ent));
            }
            client.oldbuttons = client.buttons;
            client.buttons = ucmd.buttons;
        }
Пример #3
0
        //float pm_duckScale = 0.25f;
        //int c_pmove = 0;
        /*
        ================
        Pmove

        Can be called by either the server or the client
        ================
        */
        public void Pmove(pmove_t pm)
        {
            //this.pm = pm;
            speedCropped = false;
            int finalTime = pm.cmd.serverTime;

            if (finalTime < pm.ps.commandTime)
                return; // should not happen

            if (finalTime > pm.ps.commandTime + 1000)
                pm.ps.commandTime = finalTime - 1000;

            pm.ps.speed = 320;
            pm.ps.gravity = CVars.Instance.VariableIntegerValue("sv_gravity");

            pm.ps.pmove_framecount = (pm.ps.pmove_framecount + 1) & ((1 << 6) - 1);
            // chop the move up if it is too long, to prevent framerate
            // dependent behavior

            while (pm.ps.commandTime != finalTime)
            {
                int msec = finalTime - pm.ps.commandTime;

                if (pm.pmove_fixed > 0)
                {
                    if (msec > pm.pmove_msec)
                        msec = pm.pmove_msec;
                }
                else
                {
                    if (msec > 50)
                        msec = 50;
                }
                pm.cmd.serverTime = pm.ps.commandTime + msec;
                pm.maxSpeed = pm_maxspeed;
                PlayerMoveSingle(pm);
                //PmoveSingle(pm);

                //if ((pm.ps.pm_flags & PMFlags.JUMP_HELD) == PMFlags.JUMP_HELD)
                //    pm.cmd.upmove = 20;
            }
            //pm.ps.OldButtons = pm.cmd.buttons;
        }
Пример #4
0
        /*
        ==================
        ClientThink

        A new command has arrived from the client
        This will be called once for each client frame, which will
        usually be a couple times for each server frame on fast clients.
        ==================
        */
        public void Client_Think(gentity_t ent)
        {
            gclient_t client = ent.client;

            // don't think if the client is not yet connected (and thus not yet spawned in)
            if (client.pers.connected != clientConnected_t.CON_CONNECTED)
                return;

            Input.UserCommand ucmd = ent.client.pers.cmd;
            // sanity check the command time to prevent speedup cheating
            if(ucmd.serverTime > level.time + 200)
                ucmd.serverTime = (int)level.time + 200;
            if (ucmd.serverTime < level.time - 1000)
                ucmd.serverTime = (int)level.time - 1000;

            // mark the time we got info, so we can display the
            //ent.client.pers.cmd = Server.Instance.GetUsercmd(ent.s.clientNum);

            // phone jack if they don't get any for a while
            ent.client.lastCmdTime = (int)level.time;

            int msec = ucmd.serverTime - ent.client.ps.commandTime;
            // following others may result in bad times, but we still want
            // to check for follow toggles
            if (msec < 1 && ent.client.sess.spectatorState != spectatorState_t.SPECTATOR_FOLLOW)
                return;
            if (msec > 200)
                msec = 200;

            CVar pmove_msec = CVars.Instance.FindVar("pmove_msec");
            if (pmove_msec.Integer < 8)
                CVars.Instance.Set("pmove_msec", "8");
            else if (pmove_msec.Integer > 33)
                CVars.Instance.Set("pmove_msec", "33");

            if (CVars.Instance.FindVar("pmove_fixed").Bool || client.pers.pmoveFixed)
            {
                ucmd.serverTime = ((ucmd.serverTime + pmove_msec.Integer - 1) / pmove_msec.Integer) * pmove_msec.Integer;
            }

            //
            // check for exiting intermission
            //
            if (level.intermissiontime > 0)
            {
                //ClientIntermissionThink(client);
                return;
            }

            // spectators don't do much
            if (client.sess.sessionTeam == team_t.TEAM_SPECTATOR)
            {
                if (client.sess.spectatorState == spectatorState_t.SPECTATOR_SCOREBOARD)
                    return;
                //client.ps.speed = sv_speed.Integer;
                SpectatorThink(ent, ucmd);
                return;
            }

            // check for inactivity timer, but never drop the local client of a non-dedicated server
            //if (!ClientInactivityTimer(ent.client))
            //    return;

            if (client.noclip)
                client.ps.pm_type = Common.PMType.NOCLIP;
            else if (client.ps.stats[0] <= 0)
                client.ps.pm_type = Common.PMType.DEAD;
            else
                client.ps.pm_type = Common.PMType.NORMAL;

            // Gravity & speed
            client.ps.gravity = sv_gravity.Integer;
            client.ps.speed = sv_speed.Integer;

            // Set up for pmove
            int oldEventSequence = client.ps.eventSequence;
            pmove_t pm = new pmove_t();
               //#define	MASK_ALL				(-1)
            //#define	MASK_SOLID				(1)
            //#define	MASK_PLAYERSOLID		(1|0x10000|0x2000000)
            //#define	MASK_DEADSOLID			(1|0x10000)
            //#define	MASK_WATER				(32)
            //#define	MASK_OPAQUE				(1)
            //#define	MASK_SHOT				(1|0x2000000|0x4000000)
            pm.Trace = new TraceDelegate(Server.Instance.SV_Trace);
            pm.ps = client.ps;
            pm.cmd = ucmd;
            if (pm.ps.pm_type == Common.PMType.DEAD)
                pm.tracemask = (int)brushflags.MASK_PLAYERSOLID & ~(int)brushflags.CONTENTS_MONSTER;
            else
                pm.tracemask = (int)brushflags.MASK_PLAYERSOLID;
            pm.pmove_fixed = ((CVars.Instance.FindVar("pmove_fixed").Bool) | client.pers.pmoveFixed)?1:0;
            pm.pmove_msec = pmove_msec.Integer;
            client.oldOrigin = client.ps.origin;
            //pm.mins = Common.playerMins;
            //pm.maxs = Common.playerMaxs;
            Common.Instance.Pmove(pm);

            //client.ps.pm_type = Common.PMType.SPECTATOR;
            //client.ps.speed = 400;  // faster than normal

            // save results of pmove
            if (ent.client.ps.eventSequence != oldEventSequence)
                ent.eventTime = (int)level.time;
            if (g_smoothClients.Integer == 1)
            {

            }
            else
            {
                CGame.PlayerStateToEntityState(ent.client.ps, ent.s, true);
            }
            SendPredictableEvents(ent.client.ps);

            ent.r.currentOrigin = ent.s.pos.trBase;
            ent.r.mins = pm.mins;
            ent.r.maxs = pm.maxs;

            // execute client events
            //ClientEvents(ent, oldEventSequence);

            // link entity now, after any personal teleporters have been used
            Server.Instance.LinkEntity(GEntityToSharedEntity(ent));
            if (!ent.client.noclip)
            {
                //TouchTriggers(ent);
            }

            // NOTE: now copy the exact origin over otherwise clients can be snapped into solid
            ent.r.currentOrigin = ent.client.ps.origin;

            // touch other objects
            //ClientImpacts(ent, pm);

            // save results of triggers and client events
            if (ent.client.ps.eventSequence != oldEventSequence)
            {
                ent.eventTime = (int)level.time;
            }

            // swap and latch button actions
            client.oldbuttons = client.buttons;
            client.buttons = ucmd.buttons;
            client.latched_buttons |= client.buttons & ~client.oldbuttons;

            // check for respawning
            if (client.ps.stats[0] <= 0)
            {
                // wait for the attack button to be pressed
                if (level.time > client.respawnTime)
                {
                    // forcerespawn is to prevent users from waiting out powerups
                    if (g_forcerespawn.Integer > 0 && level.time - client.respawnTime > g_forcerespawn.Integer * 1000)
                    {
                        respawn(ent);
                        return;
                    }

                    // pressing attack or use is the normal respawn method
                    if ((ucmd.buttons & ((int)Input.ButtonDef.ATTACK | (int)Input.ButtonDef.USE)) > 0)
                        respawn(ent);

                }
                return;
            }

            ClientTimerActions(ent, msec);
        }