Пример #1
0
    public static void SV_UserFriction()
    {
        float speed = Mathlib.LengthXY(ref sv_player.v.velocity);

        if (speed == 0)
        {
            return;
        }

        // if the leading edge is over a dropoff, increase friction
        Vector3 start, stop;

        start.X = stop.X = sv_player.v.origin.x + sv_player.v.velocity.x / speed * 16;
        start.Y = stop.Y = sv_player.v.origin.y + sv_player.v.velocity.y / speed * 16;
        start.Z = sv_player.v.origin.z + sv_player.v.mins.z;
        stop.Z  = start.Z - 34;

        trace_t trace    = SV_Move(ref start, ref q_shared.ZeroVector, ref q_shared.ZeroVector, ref stop, 1, sv_player);
        float   friction = sv_friction.value;

        if (trace.fraction == 1.0)
        {
            friction *= edgefriction.value;
        }

        // apply friction
        float control  = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
        float newspeed = (float)(speed - host_framtime * control * friction);

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

        Mathlib.VectorScale(ref sv_player.v.velocity, newspeed, out sv_player.v.velocity);
    }
Пример #2
0
    static void PF_aim()
    {
        edict_t ent   = G_EDICT(q_shared.OFS_PARM0);
        float   speed = G_FLOAT(q_shared.OFS_PARM1);

        Vector3 start = ToVector(ref ent.v.origin);

        start.Z += 20;

        // try sending a trace straight
        Vector3 dir;

        Mathlib.Copy(ref pr_global_struct.v_forward, out dir);
        Vector3 end = start + dir * 2048;
        trace_t tr  = SV_Move(ref start, ref q_shared.ZeroVector, ref q_shared.ZeroVector, ref end, 0, ent);

        if (tr.ent != null && tr.ent.v.takedamage == q_shared.DAMAGE_AIM &&
            (teamplay.value == 0 || ent.v.team <= 0 || ent.v.team != tr.ent.v.team))
        {
            G_VECTOR(ref pr_global_struct.v_forward);
            return;
        }

        // try all possible entities
        Vector3 bestdir  = dir;
        float   bestdist = sv_aim.value;
        edict_t bestent  = null;

        for (int i = 1; i < sv.num_edicts; i++)
        {
            edict_t check = sv.edicts[i];
            if (check.v.takedamage != q_shared.DAMAGE_AIM)
            {
                continue;
            }
            if (check == ent)
            {
                continue;
            }
            if (teamplay.value != 0 && ent.v.team > 0 && ent.v.team == check.v.team)
            {
                continue;       // don't aim at teammate
            }
            v3f tmp;
            Mathlib.VectorAdd(ref check.v.mins, ref check.v.maxs, out tmp);
            Mathlib.VectorMA(ref check.v.origin, 0.5f, ref tmp, out tmp);
            Mathlib.Copy(ref tmp, out end);

            dir = end - start;
            Mathlib.Normalize(ref dir);
            float dist = Vector3.Dot(dir, ToVector(ref pr_global_struct.v_forward));
            if (dist < bestdist)
            {
                continue;       // to far to turn
            }
            tr = SV_Move(ref start, ref q_shared.ZeroVector, ref q_shared.ZeroVector, ref end, 0, ent);
            if (tr.ent == check)
            {   // can shoot at this one
                bestdist = dist;
                bestent  = check;
            }
        }

        if (bestent != null)
        {
            v3f dir2, end2;
            Mathlib.VectorSubtract(ref bestent.v.origin, ref ent.v.origin, out dir2);
            float dist = Mathlib.DotProduct(ref dir2, ref pr_global_struct.v_forward);
            Mathlib.VectorScale(ref pr_global_struct.v_forward, dist, out end2);
            end2.z = dir2.z;
            Mathlib.Normalize(ref end2);
            G_VECTOR(ref end2);
        }
        else
        {
            G_VECTOR(ref bestdir);
        }
    }
Пример #3
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;
            }
        }
    }
Пример #4
0
    public static void SV_Physics_Toss(edict_t ent)
    {
        // regular thinking
        if (!SV_RunThink(ent))
        {
            return;
        }

        // if onground, return without moving
        if (((int)ent.v.flags & q_shared.FL_ONGROUND) != 0)
        {
            return;
        }

        SV_CheckVelocity(ent);

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


        // move angles
        Mathlib.VectorMA(ref ent.v.angles, (float)host_framtime, ref ent.v.avelocity, out ent.v.angles);

        // move origin
        v3f move;

        Mathlib.VectorScale(ref ent.v.velocity, (float)host_framtime, out move);
        trace_t trace = PushEntity(ent, ref move);

        if (trace.fraction == 1)
        {
            return;
        }
        if (ent.free)
        {
            return;
        }

        float backoff;

        if (ent.v.movetype == q_shared.MOVETYPE_BOUNCE)
        {
            backoff = 1.5f;
        }
        else
        {
            backoff = 1;
        }

        ClipVelocity(ref ent.v.velocity, ref trace.plane.normal, out ent.v.velocity, backoff);

        // stop if on ground
        if (trace.plane.normal.Z > 0.7f)
        {
            if (ent.v.velocity.z < 60 || ent.v.movetype != q_shared.MOVETYPE_BOUNCE)
            {
                ent.v.flags        = (int)ent.v.flags | q_shared.FL_ONGROUND;
                ent.v.groundentity = EDICT_TO_PROG(trace.ent);
                ent.v.velocity     = default(v3f);
                ent.v.avelocity    = default(v3f);
            }
        }

        // check for in water
        SV_CheckWaterTransition(ent);
    }
Пример #5
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);
    }
Пример #6
0
    public static void SV_WaterMove()
    {
        //
        // user intentions
        //
        Vector3 pangle = ToVector(ref sv_player.v.v_angle);

        Mathlib.AngleVectors(ref pangle, out forward, out right, out up);
        Vector3 wishvel = forward * cmd.forwardmove + right * cmd.sidemove;

        if (cmd.forwardmove == 0 && cmd.sidemove == 0 && cmd.upmove == 0)
        {
            wishvel.Z -= 60;        // drift towards bottom
        }
        else
        {
            wishvel.Z += cmd.upmove;
        }

        float wishspeed = wishvel.Length;

        if (wishspeed > sv_maxspeed.value)
        {
            wishvel  *= sv_maxspeed.value / wishspeed;
            wishspeed = sv_maxspeed.value;
        }
        wishspeed *= 0.7f;

        //
        // water friction
        //
        float newspeed, speed = Mathlib.Length(ref sv_player.v.velocity);

        if (speed != 0)
        {
            newspeed = (float)(speed - host_framtime * speed * sv_friction.value);
            if (newspeed < 0)
            {
                newspeed = 0;
            }
            Mathlib.VectorScale(ref sv_player.v.velocity, newspeed / speed, out sv_player.v.velocity);
        }
        else
        {
            newspeed = 0;
        }

        //
        // water acceleration
        //
        if (wishspeed == 0)
        {
            return;
        }

        float addspeed = wishspeed - newspeed;

        if (addspeed <= 0)
        {
            return;
        }

        Mathlib.Normalize(ref wishvel);
        float accelspeed = (float)(sv_accelerate.value * wishspeed * host_framtime);

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

        wishvel *= accelspeed;
        sv_player.v.velocity.x += wishvel.X;
        sv_player.v.velocity.y += wishvel.Y;
        sv_player.v.velocity.z += wishvel.Z;
    }