Ejemplo n.º 1
0
        public static void SV_LinkEdict(prog.edict_t ent, bool touch_triggers)
        {
            areanode_t node;

            //Debug.WriteLine("SV_LinkEdict_count " + SV_LinkEdict_count);
            SV_LinkEdict_count++;

            if (ent.area.prev != null)
                world.SV_UnlinkEdict(ent);	// unlink from old position

            if (ent == server.sv.edicts[0])
                return;		// don't add the world

            if (ent.free)
                return;

            // set the abs box
            {
                mathlib.VectorAdd(ent.v.origin, ent.v.mins, ent.v.absmin);
                mathlib.VectorAdd(ent.v.origin, ent.v.maxs, ent.v.absmax);
            }

                //Debug.WriteLine(string.Format("VectorAdd origin{0:F6}", ent.v.origin[0]));
                //Debug.WriteLine(string.Format("VectorAdd absmin {0:F6}", ent.v.absmin[0]));
            //
            // to make items easier to pick up and allow them to be grabbed off
            // of shelves, the abs sizes are expanded
            //
            if (((int)ent.v.flags & server.FL_ITEM) != 0)
            {
                ent.v.absmin[0] -= 15;
                ent.v.absmin[1] -= 15;
                ent.v.absmax[0] += 15;
                ent.v.absmax[1] += 15;
                //Debug.WriteLine(string.Format("(int)ent->v.flags & FL_ITEM {0:F6}", ent.v.absmin[0]));
            }
            else
            {	// because movement is clipped an epsilon away from an actual edge,
                // we must fully check even when bounding boxes don't quite touch
                ent.v.absmin[0] -= 1;
                ent.v.absmin[1] -= 1;
                ent.v.absmin[2] -= 1;
                ent.v.absmax[0] += 1;
                ent.v.absmax[1] += 1;
                ent.v.absmax[2] += 1;
                //Debug.WriteLine(string.Format("nerp {0:F6}", ent.v.absmin[0]));
            }

            // link to PVS leafs
            ent.num_leafs = 0;
            if (ent.v.modelindex != 0)
                SV_FindTouchedLeafs(ent, server.sv.worldmodel.nodes[0]);

            if (ent.v.solid ==server. SOLID_NOT)
                return;

            // find the first node that the ent's box crosses
            node = sv_areanodes[0];
            while (true)
            {
                if (node.axis == -1)
                    break;
                if (ent.v.absmin[node.axis] > node.dist)
                    node = node.children[0];
                else if (ent.v.absmax[node.axis] < node.dist)
                    node = node.children[1];
                else
                    break;		// crosses the node
            }

            // link it in	

            if (ent.v.solid == server.SOLID_TRIGGER)
            {
                //Debug.WriteLine("ent.v.solid == server.SOLID_TRIGGER");
                common.InsertLinkBefore(ent.area, node.trigger_edicts);
            }
            else
            {
                //Debug.WriteLine("ELSE!");
                common.InsertLinkBefore(ent.area, node.solid_edicts);
            }

            // if touch_triggers, touch all entities at this node and decend for more
            if (touch_triggers)
                SV_TouchLinks(ent, sv_areanodes[0]);
        }
Ejemplo n.º 2
0
        private static void SV_Physics_Step(prog.edict_t ent)
        {
            bool hitsound;

            // freefall if not onground
            if (!(((int)ent.v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM)) != 0))
            {
                if (ent.v.velocity[2] < sv_gravity.value * -0.1)
                    hitsound = true;
                else
                    hitsound = false;

                SV_AddGravity(ent);
                SV_CheckVelocity(ent);
                var unused_trace_t = new world.trace_t(); // null was passed into SV_FlyMove in original
                SV_FlyMove(ent, host.host_frametime, ref unused_trace_t);
                world.SV_LinkEdict(ent, true);

                if (((int)ent.v.flags & FL_ONGROUND) != 0) // just hit ground
                {
                    if (hitsound)
                        SV_StartSound(ent, 0, "demon/dland2.wav", 255, 1);
                }
            }

            // regular thinking
            SV_RunThink(ent);

            SV_CheckWaterTransition(ent);
        }
Ejemplo n.º 3
0
        /*
        ===============================================================================

        PUSHMOVE

        ===============================================================================
        */
        /*
        ============
        SV_PushEntity

        Does not change the entities velocity at all
        ============
        */
        static world.trace_t SV_PushEntity(prog.edict_t ent, double[] push)
        {
            world.trace_t trace;
            double[] end = new double[3] {0, 0, 0};

            mathlib.VectorAdd(ent.v.origin, push, end);

            if (ent.v.movetype == MOVETYPE_FLYMISSILE)
            trace = world.SV_Move(ent.v.origin, ent.v.mins, ent.v.maxs, end, world.MOVE_MISSILE, ent);
            else if (ent.v.solid == SOLID_TRIGGER || ent.v.solid == SOLID_NOT)
            // only clip against bmodels
            trace = world.SV_Move(ent.v.origin, ent.v.mins, ent.v.maxs, end, world.MOVE_NOMONSTERS, ent);
            else
            trace = world.SV_Move(ent.v.origin, ent.v.mins, ent.v.maxs, end, world.MOVE_NORMAL, ent);

            mathlib.VectorCopy(trace.endpos, ent.v.origin);
            world.SV_LinkEdict(ent, true);

            if (trace.ent != null)
            SV_Impact(ent, trace.ent);

            return trace;
        }
Ejemplo n.º 4
0
        /*
        ================
        SV_Physics_Client

        Player character actions
        ================
        */
        static void SV_Physics_Client(prog.edict_t ent, int num)
        {
            //Debug.WriteLine("SV_Physics_Client");
            if ( ! svs.clients[num-1].active )
                return;		// unconnected slot

            //
            // call standard client pre-think
            //
            prog.pr_global_struct[0].time = sv.time;
            prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(ent);
            prog.PR_ExecuteProgram(prog.pr_functions[prog.pr_global_struct[0].PlayerPreThink]);

            //
            // do a move
            //
            SV_CheckVelocity (ent);

            //
            // decide which move function to call
            //
            switch ((int)ent.v.movetype)
            {
            case MOVETYPE_NONE:
                if (!SV_RunThink (ent))
                    return;
                break;

            case MOVETYPE_WALK:
                if (!SV_RunThink (ent))
                    return;
                if (!SV_CheckWater (ent) && ! (((int)ent.v.flags & FL_WATERJUMP) != 0) )
                    SV_AddGravity (ent);
                SV_CheckStuck (ent);
                SV_WalkMove (ent);
                break;

            case MOVETYPE_TOSS:
            case MOVETYPE_BOUNCE:
                SV_Physics_Toss (ent);
                break;

            case MOVETYPE_FLY:
                if (!SV_RunThink (ent))
                    return;
                var unused_trace_t = new world.trace_t(); // null was passed into SV_FlyMove in original
                SV_FlyMove(ent, host.host_frametime, ref unused_trace_t);
                break;

            case MOVETYPE_NOCLIP:
                if (!SV_RunThink (ent))
                    return;
                mathlib.VectorMA (ent.v.origin, host.host_frametime, ent.v.velocity, ent.v.origin);
                break;

            default:
                sys_linux.Sys_Error ("SV_Physics_client: bad movetype " + (int)ent.v.movetype);
                break;
            }

            //
            // call standard player post-think
            //
               world.SV_LinkEdict (ent, true);

            prog.pr_global_struct[0].time = sv.time;
            prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(ent);
            prog.PR_ExecuteProgram(prog.pr_functions[prog.pr_global_struct[0].PlayerPostThink]);
        }
Ejemplo n.º 5
0
        //============================================================================
        /*
        =============
        SV_Physics_None

        Non moving objects can only think
        =============
        */
        static void SV_Physics_None(prog.edict_t ent)
        {
            // regular thinking
            SV_RunThink (ent);
        }
Ejemplo n.º 6
0
        /*
        =============
        SV_CheckWater
        =============
        */
        static bool SV_CheckWater(prog.edict_t ent)
        {
            //Debug.WriteLine("SV_CheckWater");
            double[] point = new double[3] {0, 0, 0};
            int cont;

            point[0] = ent.v.origin[0];
            point[1] = ent.v.origin[1];
            point[2] = ent.v.origin[2] + ent.v.mins[2] + 1;

            ent.v.waterlevel = 0;
            ent.v.watertype = bspfile.CONTENTS_EMPTY;
            cont = world.SV_PointContents(point);
            if (cont <= bspfile.CONTENTS_WATER)
            {
                ent.v.watertype = cont;
                ent.v.waterlevel = 1;
                point[2] = ent.v.origin[2] + (ent.v.mins[2] + ent.v.maxs[2]) * 0.5;
                cont = world.SV_PointContents(point);
                if (cont <= bspfile.CONTENTS_WATER)
                {
                    ent.v.waterlevel = 2;
                    point[2] = ent.v.origin[2] + ent.v.view_ofs[2];
                    cont = world.SV_PointContents(point);
                    if (cont <= bspfile.CONTENTS_WATER)
                        ent.v.waterlevel = 3;
                }
            }

            return ent.v.waterlevel > 1;
        }
Ejemplo n.º 7
0
        private static int SV_FlyMove(prog.edict_t ent, double time /*was float*/, ref world.trace_t steptrace)
        {
            int bumpcount, numbumps;
            double[] dir = new double[3] {0, 0, 0};
            double d;
            int numplanes;
            double[][] planes =
                {
                    ArrayHelpers.ExplcitDoubleArray(3), ArrayHelpers.ExplcitDoubleArray(3),
                    ArrayHelpers.ExplcitDoubleArray(3), ArrayHelpers.ExplcitDoubleArray(3),
                    ArrayHelpers.ExplcitDoubleArray(3)
                };
            double[] primal_velocity = new double[3] {0, 0, 0}, original_velocity = new double[3] {0, 0, 0}, new_velocity = new double[3] {0, 0, 0};
            int i, j;
            world.trace_t trace;
            double[] end = new double[3] {0, 0, 0};
            double time_left;
            int blocked;

            numbumps = 4;

            blocked = 0;
            mathlib.VectorCopy(ent.v.velocity, original_velocity);
            mathlib.VectorCopy(ent.v.velocity, primal_velocity);
            numplanes = 0;

            time_left = time;

            //Debug.WriteLine("SV_FlyMove");
            for (bumpcount = 0; bumpcount < numbumps; bumpcount++)
            {
                if (ent.v.velocity[0] == 0.0 && ent.v.velocity[1] == 0.0 && ent.v.velocity[2] == 0.0)
                    break;

                for (i = 0; i < 3; i++)
                    end[i] = ent.v.origin[i] + time_left * ent.v.velocity[i];

                trace = world.SV_Move(ent.v.origin, ent.v.mins, ent.v.maxs, end, 0, ent);

                if (trace.allsolid)
                {
                    //Debug.WriteLine("allsolid");
                    // entity is trapped in another solid
                    mathlib.VectorCopy(mathlib.vec3_origin, ent.v.velocity);
                    return 3;
                }

                //Debug.WriteLine(string.Format("fraction {0}", trace.fraction));
                if (trace.fraction > 0)
                {
                    // actually covered some distance
                    mathlib.VectorCopy(trace.endpos, ent.v.origin);
                    mathlib.VectorCopy(ent.v.velocity, original_velocity);
                    numplanes = 0;
                }

                if (trace.fraction == 1.0)
                    break; // moved the entire distance

                if (trace.ent == null)
                    sys_linux.Sys_Error("SV_FlyMove: !trace.ent");

                if (trace.plane.normal[2] > 0.7)
                {
                    //Debug.WriteLine("trace.plane.normal[2] > 0.7");
                    blocked |= 1; // floor
                    if (trace.ent.v.solid == SOLID_BSP)
                    {
                        ent.v.flags = (int)ent.v.flags | FL_ONGROUND;
                        ent.v.groundentity = prog.EDICT_TO_PROG(trace.ent);
                    }
                }
                if (!(trace.plane.normal[2] != 0.0))
                {
                    //Debug.WriteLine("!trace.plane.normal[2]");
                    blocked |= 2; // step
                    if (steptrace != null)
                        steptrace = trace; // save for player extrafriction
                }

                //
                // run the impact function
                //
                //Debug.WriteLine("SV_Impact");
                SV_Impact(ent, trace.ent);
                if (ent.free)
                {
                    //Debug.WriteLine("ent.fre");
                    break; // removed by the impact function
                }

                time_left -= time_left * trace.fraction;

                // cliped to another plane
                if (numplanes >= MAX_CLIP_PLANES)
                {
                    //Debug.WriteLine("numplanes >= MAX_CLIP_PLANES");
                    // this shouldn't really happen
                    mathlib.VectorCopy(mathlib.vec3_origin, ent.v.velocity);
                    return 3;
                }

                mathlib.VectorCopy(trace.plane.normal, planes[numplanes]);
                numplanes++;

                //
                // modify original_velocity so it parallels all of the clip planes
                //
                for (i = 0; i < numplanes; i++)
                {
                    ClipVelocity(original_velocity, planes[i], new_velocity, 1);
                    for (j = 0; j < numplanes; j++)
                        if (j != i)
                        {
                            if (mathlib.DotProduct(new_velocity, planes[j]) < 0)
                                break; // not ok
                        }
                    if (j == numplanes)
                        break;
                }

                if (i != numplanes)
                {
                    // go along this plane
                    //Debug.WriteLine("i != numplanes");
                    mathlib.VectorCopy(new_velocity, ent.v.velocity);
                }
                else
                {
                    // go along the crease
                    if (numplanes != 2)
                    {
                        //				Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
                        mathlib.VectorCopy(mathlib.vec3_origin, ent.v.velocity);
                        return 7;
                    }
                    mathlib.CrossProduct(planes[0], planes[1], dir);
                    d = mathlib.DotProduct(dir, ent.v.velocity);
                    mathlib.VectorScale(dir, d, ent.v.velocity);
                }

                //
                // if original velocity is against the original velocity, stop dead
                // to avoid tiny occilations in sloping corners
                //
                if (mathlib.DotProduct(ent.v.velocity, primal_velocity) <= 0)
                {
                    //Debug.WriteLine("DotProductstuff");
                    mathlib.VectorCopy(mathlib.vec3_origin, ent.v.velocity);
                    return blocked;
                }
            }

            return blocked;
        }
Ejemplo n.º 8
0
        /*
        ======================
        SV_CloseEnough

        ======================
        */
        static bool SV_CloseEnough(prog.edict_t ent, prog.edict_t goal, double dist)
        {
            int i;

            for (i = 0; i < 3; i++)
            {
                if (goal.v.absmin[i] > ent.v.absmax[i] + dist)
                    return false;
                if (goal.v.absmax[i] < ent.v.absmin[i] - dist)
                    return false;
            }
            return true;
        }
Ejemplo n.º 9
0
        /*
        ======================
        SV_FixCheckBottom

        ======================
        */
        static void SV_FixCheckBottom(prog.edict_t ent)
        {
            //	Con_Printf ("SV_FixCheckBottom\n");

            ent.v.flags = (int)ent.v.flags | FL_PARTIALGROUND;
        }
Ejemplo n.º 10
0
        public static bool SV_Movestep(prog.edict_t ent, double[] move, bool relink)
        {
            double dz;
            double[] oldorg = ArrayHelpers.ExplcitDoubleArray(3), neworg = ArrayHelpers.ExplcitDoubleArray(3), end = ArrayHelpers.ExplcitDoubleArray(3);
            world.trace_t trace;
            int i;
            prog.edict_t enemy;

            SV_Movestep_count++;
            Debug.WriteLine("SV_Movestep " + SV_Movestep_count);

            // try the move
            mathlib.VectorCopy(ent.v.origin, oldorg);
            mathlib.VectorAdd(ent.v.origin, move, neworg);

            // flying monsters don't step up
            if (((int)ent.v.flags & (FL_SWIM | FL_FLY)) != 0)
            {
                // try one move with vertical motion, then one without
                for (i = 0; i < 2; i++)
                {
                    mathlib.VectorAdd(ent.v.origin, move, neworg);
                    enemy = prog.PROG_TO_EDICT(ent.v.enemy);
                    if (i == 0 && enemy != sv.edicts[0])
                    {
                        dz = ent.v.origin[2] - prog.PROG_TO_EDICT(ent.v.enemy).v.origin[2];
                        if (dz > 40)
                            neworg[2] -= 8;
                        if (dz < 30)
                            neworg[2] += 8;
                    }
                    trace = world.SV_Move(ent.v.origin, ent.v.mins, ent.v.maxs, neworg, 0, ent);

                    if (trace.fraction == 1)
                    {
                        if (((int)ent.v.flags & FL_SWIM) != 0
                            && world.SV_PointContents(trace.endpos) == bspfile.CONTENTS_EMPTY)
                        {
                            Debug.WriteLine("bspfile.CONTENTS_EMPTY etc");
                            return false;	// swim monster left water
                        }

                        Debug.WriteLine("NOT bspfile.CONTENTS_EMPTY etc");

                        mathlib.VectorCopy(trace.endpos, ent.v.origin);
                        if (relink)
                            world.SV_LinkEdict(ent, true);
                        return true;
                    }

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

                Debug.WriteLine("dfasdgsdfgdf sdsdfasdsdf");
                return false;
            }

            // push down from a step height above the wished position
            neworg[2] += STEPSIZE;
            mathlib.VectorCopy(neworg, end);
            end[2] -= STEPSIZE * 2;

            trace = world.SV_Move(neworg, ent.v.mins, ent.v.maxs, end, 0, ent);

            if (trace.allsolid)
            {
                Debug.WriteLine("trace.allsolid");
                return false;
            }

            if (trace.startsolid)
            {
                Debug.WriteLine("trace.startsolid");
                neworg[2] -= STEPSIZE;
                trace = world.SV_Move(neworg, ent.v.mins, ent.v.maxs, end, 0, ent);
                if (trace.allsolid || trace.startsolid)
                {
                    Debug.WriteLine("trace.startsolid return false");
                    return false;
                }
            }
            if (trace.fraction == 1)
            {
                Debug.WriteLine("trace.fraction == 1");
                // if monster had the ground pulled out, go ahead and fall
                if (((int)ent.v.flags & FL_PARTIALGROUND )!= 0)
                {
                    mathlib.VectorAdd(ent.v.origin, move, ent.v.origin);
                    if (relink)
                        world.SV_LinkEdict(ent, true);
                    ent.v.flags = (int)ent.v.flags & ~FL_ONGROUND;
                    //	Con_Printf ("fall down\n");
                    Debug.WriteLine("trace.fraction == 1 return true");
                    return true;
                }

                Debug.WriteLine("walked off an edge");
                return false;		// walked off an edge
            }

            // check point traces down for dangling corners
            mathlib.VectorCopy(trace.endpos, ent.v.origin);

            if (!SV_CheckBottom(ent))
            {
                Debug.WriteLine("!SV_CheckBottom(ent)");
                if (((int)ent.v.flags & FL_PARTIALGROUND) != 0)
                {	// entity had floor mostly pulled out from underneath it
                    // and is trying to correct
                    if (relink)
                        world.SV_LinkEdict(ent, true);

                    Debug.WriteLine("!SV_CheckBottom(ent) return true");
                    return true;
                }
                mathlib.VectorCopy(oldorg, ent.v.origin);

                Debug.WriteLine("!SV_CheckBottom(ent) return false");
                return false;
            }

            if (((int)ent.v.flags & FL_PARTIALGROUND) != 0)
            {
                //		Con_Printf ("back on ground\n");
                ent.v.flags = (int)ent.v.flags & ~FL_PARTIALGROUND;
            }
            ent.v.groundentity = prog.EDICT_TO_PROG(trace.ent);

            // the move is ok
            if (relink)
                world.SV_LinkEdict(ent, true);
            Debug.WriteLine(" return true");
            return true;
        }
Ejemplo n.º 11
0
        public static void SV_NewChaseDir(prog.edict_t actor, prog.edict_t enemy, double dist)
        {
            double		deltax,deltay;
            double[]	d = new double[3] {0, 0, 0};
            double		tdir, olddir, turnaround;

            olddir = mathlib. anglemod( (int)(actor.v.ideal_yaw/45)*45 );
            turnaround = mathlib.anglemod(olddir - 180);

            deltax = enemy.v.origin[0] - actor.v.origin[0];
            deltay = enemy.v.origin[1] - actor.v.origin[1];
            if (deltax>10)
                d[1]= 0;
            else if (deltax<-10)
                d[1]= 180;
            else
                d[1]= DI_NODIR;
            if (deltay<-10)
                d[2]= 270;
            else if (deltay>10)
                d[2]= 90;
            else
                d[2]= DI_NODIR;

            // try direct route
            if (d[1] != DI_NODIR && d[2] != DI_NODIR)
            {
                if (d[1] == 0)
                    tdir = d[2] == 90 ? 45 : 315;
                else
                    tdir = d[2] == 90 ? 135 : 215;

                if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
                    return;
            }

            // try other directions
            if ((((Helper.helper.rand() & 3) & 1) != 0) || (Math.Abs(deltay) > Math.Abs(deltax)))
            {
                tdir=d[1];
                d[1]=d[2];
                d[2]=tdir;
            }

            if (d[1]!=DI_NODIR && d[1]!=turnaround
            && SV_StepDirection(actor, d[1], dist))
                    return;

            if (d[2]!=DI_NODIR && d[2]!=turnaround
            && SV_StepDirection(actor, d[2], dist))
                    return;

            /* there is no direct path to the player, so pick another direction */

            if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
                    return;

            if ((Helper.helper.rand() & 1) != 0) 	/*randomly determine direction of search*/
            {
                for (tdir=0 ; tdir<=315 ; tdir += 45)
                    if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
                            return;
            }
            else
            {
                for (tdir=315 ; tdir >=0 ; tdir -= 45)
                    if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
                            return;
            }

            if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
                    return;

            actor.v.ideal_yaw = olddir;		// can't move

            // if a bridge was pulled out from underneath a monster, it may not have
            // a valid standing position at all

            if (!SV_CheckBottom (actor))
                SV_FixCheckBottom (actor);
        }
Ejemplo n.º 12
0
        /*
        ==================
        SV_Move
        ==================
        */
        public static trace_t SV_Move(double[]  start, double[]  mins, double[] maxs, double[]  end, int type, prog.edict_t passedict)
        {
            moveclip_t clip;
            int i;

            clip = new moveclip_t();

            // clip to world
            //Debug.WriteLine("SV_Move ?? SV_ClipMoveToEntity");
            clip.trace = SV_ClipMoveToEntity(server.sv.edicts[0], start, mins, maxs, end);

            clip.start = start;
            clip.end = end;
            clip.mins = mins;
            clip.maxs = maxs;
            clip.type = type;
            clip.passedict = passedict;

            if (type == MOVE_MISSILE)
            {
                for (i = 0; i < 3; i++)
                {
                    clip.mins2[i] = -15;
                    clip.maxs2[i] = 15;
                }
            }
            else
            {
             mathlib.VectorCopy(mins, clip.mins2);
             mathlib.VectorCopy(maxs, clip.maxs2);
            }

            // create the bounding box of the entire move
            SV_MoveBounds(start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs);

            // clip to entities
            //Debug.WriteLine("SV_Move - SV_ClipToLinks");
            SV_ClipToLinks(sv_areanodes[0], clip);

            return clip.trace;
        }
Ejemplo n.º 13
0
        /*
        ==================
        SV_ClipMoveToEntity

        Handles selection or creation of a clipping hull, and offseting (and
        eventually rotation) of the end points
        ==================
        */
        public static trace_t SV_ClipMoveToEntity(prog.edict_t ent, double[] start, double[] mins, double[] maxs, double[] end)
        {
            trace_t trace;
            double[] offset = new double[3] {0, 0, 0};
            double[] start_l = new double[3] {0, 0, 0}, end_l = new double[3] {0, 0, 0};
            model.hull_t hull;

            // fill in a default trace
            trace = new trace_t();
            trace.fraction = 1;
            trace.allsolid = true;
            mathlib.VectorCopy(end, trace.endpos);

            // get the clipping hull
            hull = SV_HullForEntity(ent, mins, maxs, offset);

            mathlib.VectorSubtract(start, offset, start_l);
            mathlib.VectorSubtract(end, offset, end_l);
            //Debug.WriteLine(string.Format("end[2] {0:F6}", (float)end[2]));

            // trace a line through the apropriate clipping hull
            //Debug.WriteLine(string.Format("end_l[2] {0:F6}",(float)  end_l[2]));
            SV_RecursiveHullCheck(hull, hull.firstclipnode, 0, 1, start_l, end_l, trace);


            // fix trace up by the offset
            if (trace.fraction != 1)
                mathlib.VectorAdd(trace.endpos, offset, trace.endpos);

            // did we clip the move?
            if (trace.fraction < 1 || trace.startsolid)
                trace.ent = ent;

            return trace;
        }
Ejemplo n.º 14
0
        //===========================================================================

        /*
        ============
        SV_TestEntityPosition

        This could be a lot more efficient...
        ============
        */
        public static prog.edict_t SV_TestEntityPosition(prog.edict_t ent)
        {
            trace_t trace;

            trace = SV_Move(ent.v.origin, ent.v.mins, ent.v.maxs, ent.v.origin, 0, ent);

            if (trace.startsolid)
                return server.sv.edicts[0];

            return null;
        }
Ejemplo n.º 15
0
        /*
        ===============================================================================

        CLIENT MOVEMENT

        ===============================================================================
        */
        /*
        =============
        SV_CheckStuck

        This is a big hack to try and fix the rare case of getting stuck in the world
        clipping hull.
        =============
        */
        private static void SV_CheckStuck(prog.edict_t ent)
        {
            //Debug.WriteLine("SV_CheckStuck");
            int i, j;
            int z;
            double[] org = new double[3] {0, 0, 0};

            if (world.SV_TestEntityPosition(ent) == null)
            {
                mathlib.VectorCopy(ent.v.origin, ent.v.oldorigin);
                return;
            }

            mathlib.VectorCopy(ent.v.origin, org);
            mathlib.VectorCopy(ent.v.oldorigin, ent.v.origin);
            if (world.SV_TestEntityPosition(ent) == null)
            {
                console.Con_DPrintf("Unstuck.\n");
                world.SV_LinkEdict(ent, true);
                return;
            }

            for (z = 0; z < 18; z++)
                for (i = -1; i <= 1; i++)
                    for (j = -1; j <= 1; j++)
                    {
                        ent.v.origin[0] = org[0] + i;
                        ent.v.origin[1] = org[1] + j;
                        ent.v.origin[2] = org[2] + z;
                        if (world.SV_TestEntityPosition(ent) != null)
                        {
                            console.Con_DPrintf("Unstuck.\n");
                            world.SV_LinkEdict(ent, true);
                            return;
                        }
                    }

            mathlib.VectorCopy(org, ent.v.origin);
            console.Con_DPrintf("player is stuck.\n");
        }
Ejemplo n.º 16
0
        //============================================================================
        /*
        ======================
        SV_StepDirection

        Turns to the movement direction, and walks the current distance if
        facing it.

        ======================
        */
        static bool SV_StepDirection(prog.edict_t ent, double yaw, double dist)
        {
            double[]		move = new double[3] {0, 0, 0}, oldorigin = new double[3] {0, 0, 0};
            double		delta;

            ent.v.ideal_yaw = yaw;
            prog.PF_changeyaw();

            yaw = yaw*mathlib.M_PI*2 / 360;
            move[0] = Math.Cos(yaw)*dist;
            move[1] = Math.Sin(yaw)*dist;
            move[2] = 0;

            mathlib.VectorCopy (ent.v.origin, oldorigin);
            if (server.SV_Movestep (ent, move, false))
            {
                delta = ent.v.angles[quakedef.YAW] - ent.v.ideal_yaw;
                if (delta > 45 && delta < 315)
                {		// not turned far enough, so don't take the step
                    mathlib.VectorCopy (oldorigin, ent.v.origin);
                }
                world.SV_LinkEdict (ent, true);
                return true;
            }
            world.SV_LinkEdict (ent, true);

            return false;
        }
Ejemplo n.º 17
0
        /*
        ================
        SV_CheckVelocity
        ================
        */
        static void SV_CheckVelocity(prog.edict_t ent)
        {
            int		i;

            //
            // bound velocity
            //
            for (i=0 ; i<3 ; i++)
            {
                if (double.IsNaN(ent.v.velocity[i]))
                {
                    console.Con_Printf ("Got a NaN velocity on " + prog.pr_string(ent.v.classname) + "\n");
                    ent.v.velocity[i] = 0;
                }
                if (double.IsNaN(ent.v.origin[i]))
                {
                    console.Con_Printf("Got a NaN origin on " + prog.pr_string(ent.v.classname) + "\n");
                    ent.v.origin[i] = 0;
                }
                if (ent.v.velocity[i] > sv_maxvelocity.value)
                    ent.v.velocity[i] = sv_maxvelocity.value;
                else if (ent.v.velocity[i] < -sv_maxvelocity.value)
                    ent.v.velocity[i] = -sv_maxvelocity.value;
            }
        }
Ejemplo n.º 18
0
        public static bool SV_CheckBottom(prog.edict_t ent)
        {
            double[] mins = ArrayHelpers.ExplcitDoubleArray(3), maxs = ArrayHelpers.ExplcitDoubleArray(3), start = ArrayHelpers.ExplcitDoubleArray(3), stop = ArrayHelpers.ExplcitDoubleArray(3);
            world.trace_t trace;
            int x, y;
            double mid, bottom;

            mathlib.VectorAdd(ent.v.origin, ent.v.mins, mins);
            mathlib.VectorAdd(ent.v.origin, ent.v.maxs, maxs);

            // if all of the points under the corners are solid world, don't bother
            // with the tougher checks
            // the corners must be within 16 of the midpoint
            start[2] = mins[2] - 1;
            for (x = 0; x <= 1; x++)
                for (y = 0; y <= 1; y++)
                {
                    start[0] = x != 0 ? maxs[0] : mins[0];
                    start[1] = y != 0 ? maxs[1] : mins[1];
                    if (world.SV_PointContents(start) != bspfile.CONTENTS_SOLID)
                        goto realcheck;
                }

            c_yes++;
            return true;		// we got out easy

            realcheck:
            c_no++;
            //
            // check it for real...
            //
            start[2] = mins[2];

            // the midpoint must be within 16 of the bottom
            start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5;
            start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5;
            stop[2] = start[2] - 2 * STEPSIZE;
            trace = world.SV_Move(start, mathlib.vec3_origin, mathlib.vec3_origin, stop, 1, ent);

            if (trace.fraction == 1.0)
                return false;
            mid = bottom = trace.endpos[2];

            // the corners must be within 16 of the midpoint
            for (x = 0; x <= 1; x++)
                for (y = 0; y <= 1; y++)
                {
                    start[0] = stop[0] = x != 0 ? maxs[0] : mins[0];
                    start[1] = stop[1] = y != 0 ? maxs[1] : mins[1];

                    trace = world.SV_Move(start, mathlib.vec3_origin, mathlib.vec3_origin, stop, 1, ent);

                    if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                        bottom = trace.endpos[2];
                    if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
                        return false;
                }

            c_yes++;
            return true;
        }
Ejemplo n.º 19
0
        /*
        ==============================================================================

        TOSS / BOUNCE

        ==============================================================================
        */
        /*
        =============
        SV_CheckWaterTransition

        =============
        */
        static void SV_CheckWaterTransition(prog.edict_t ent)
        {
            int		cont;
            cont = world.SV_PointContents (ent.v.origin);
            if (! (ent.v.watertype != 0))
            {	// just spawned here
                ent.v.watertype = cont;
                ent.v.waterlevel = 1;
                return;
            }

            if (cont <= bspfile.CONTENTS_WATER)
            {
                if (ent.v.watertype == bspfile.CONTENTS_EMPTY)
                {	// just crossed into water
                    SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
                }
                ent.v.watertype = cont;
                ent.v.waterlevel = 1;
            }
            else
            {
                if (ent.v.watertype != bspfile.CONTENTS_EMPTY)
                {	// just crossed into water
                    SV_StartSound(ent, 0, "misc/h2ohit1.wav", 255, 1);
                }
                ent.v.watertype = bspfile.CONTENTS_EMPTY;
                ent.v.waterlevel = cont;
            }
        }
Ejemplo n.º 20
0
        /*
        =============
        SV_RunThink

        Runs thinking code if time.  There is some play in the exact time the think
        function will be called, because it is called before any movement is done
        in a frame.  Not used for pushmove objects, because they must be exact.
        Returns false if the entity removed itself.
        =============
        */
        static bool SV_RunThink(prog.edict_t ent)
        {
            //Debug.WriteLine("SV_RunThink");
            float thinktime;

            thinktime = (float)ent.v.nextthink;
            /*not ">" like ordiginal to fix rounding difference, mainly for debugging*/
            //if (thinktime <= 0 || thinktime > sv.time + host_frametime)
            if (thinktime <= 0 || thinktime >= sv.time + host.host_frametime)
                return true;

            if (thinktime < sv.time)
                thinktime = (float)sv.time;	// don't let things stay in the past.
            // it is possible to start that way
            // by a trigger with a local time.
            ent.v.nextthink = 0;
            prog.pr_global_struct[0].time = thinktime;
            prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(ent);
            prog.pr_global_struct[0].other = prog.EDICT_TO_PROG(sv.edicts[0]);
            prog.PR_ExecuteProgram(prog.pr_functions[ent.v.think]);
            return !ent.free;
        }
Ejemplo n.º 21
0
        /*
        ==================
        SV_Impact

        Two entities have touched, so run their touch functions
        ==================
        */
        static void SV_Impact(prog.edict_t e1, prog.edict_t e2)
        {
            int old_self, old_other;

            old_self = prog.pr_global_struct[0].self;
            old_other = prog.pr_global_struct[0].other;

            prog.pr_global_struct[0].time = sv.time;
            if (e1.v.touch !=0  && e1.v.solid != SOLID_NOT)
            {
            prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(e1);
            prog.pr_global_struct[0].other = prog.EDICT_TO_PROG(e2);
            prog.PR_ExecuteProgram(prog.pr_functions[e1.v.touch]);
            }

            if (e2.v.touch !=0 && e2.v.solid != SOLID_NOT)
            {
            prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(e2);
            prog.pr_global_struct[0].other = prog.EDICT_TO_PROG(e1);
            prog.PR_ExecuteProgram(prog.pr_functions[e2.v.touch]);
            }

            prog.pr_global_struct[0].self = old_self;
            prog.pr_global_struct[0].other = old_other;
        }
Ejemplo n.º 22
0
        /*
        =====================
        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...
        ======================
        */
        static int SV_TryUnstick(prog.edict_t ent, double[] oldvel)
        {
            int		i;
            double[]	oldorg = new double[3] {0, 0, 0};
            double[]	dir = new double[3] {0, 0, 0};
            int		clip;
            world.trace_t	steptrace = new world.trace_t();

            mathlib.VectorCopy (ent.v.origin, oldorg);
            mathlib.VectorCopy (mathlib.vec3_origin, dir);

            for (i=0 ; i<8 ; i++)
            {
            // try pushing a little in an axial direction
                switch (i)
                {
                    case 0:	dir[0] = 2; dir[1] = 0; break;
                    case 1:	dir[0] = 0; dir[1] = 2; break;
                    case 2:	dir[0] = -2; dir[1] = 0; break;
                    case 3:	dir[0] = 0; dir[1] = -2; break;
                    case 4:	dir[0] = 2; dir[1] = 2; break;
                    case 5:	dir[0] = -2; dir[1] = 2; break;
                    case 6:	dir[0] = 2; dir[1] = -2; break;
                    case 7:	dir[0] = -2; dir[1] = -2; break;
                }

                SV_PushEntity (ent, dir);

            // retry the original move
                ent.v.velocity[0] = oldvel[0];
                ent.v. velocity[1] = oldvel[1];
                ent.v. velocity[2] = 0;
                clip = SV_FlyMove (ent, 0.1f, ref steptrace);

                if (  Math.Abs(oldorg[1] - ent.v.origin[1]) > 4
                ||  Math.Abs(oldorg[0] - ent.v.origin[0]) > 4 )
                {
            //Con_DPrintf ("unstuck!\n");
                    return clip;
                }

            // go back to the original pos and try again
                mathlib.VectorCopy (oldorg, ent.v.origin);
            }

            mathlib.VectorCopy (mathlib.vec3_origin, ent.v.velocity);
            return 7;		// still not moving
        }
Ejemplo n.º 23
0
        /*
        =============
        SV_Physics_Noclip

        A moving object that doesn't obey physics
        =============
        */
        static void SV_Physics_Noclip(prog.edict_t ent)
        {
            // regular thinking
            if (!SV_RunThink (ent))
                return;

            mathlib.VectorMA (ent.v.angles, host.host_frametime, ent.v.avelocity, ent.v.angles);
            mathlib.VectorMA(ent.v.origin, host.host_frametime, ent.v.velocity, ent.v.origin);

            world.SV_LinkEdict(ent, false);
        }
Ejemplo n.º 24
0
        /*
        ============
        SV_WallFriction

        ============
        */
        static void SV_WallFriction(prog.edict_t ent, world.trace_t trace)
        {
            double[] forward = new double[3] {0, 0, 0}, right = new double[3] {0, 0, 0}, up = new double[3] {0, 0, 0};
            double d, i;
            double[] into = new double[3] {0, 0, 0}, side = new double[3] {0, 0, 0};

            mathlib.AngleVectors(ent.v.v_angle, forward, right, up);
            d = mathlib.DotProduct(trace.plane.normal, forward);

            d += 0.5;
            if (d >= 0)
                return;

            // cut the tangential velocity
            i = mathlib.DotProduct(trace.plane.normal, ent.v.velocity);
            mathlib.VectorScale(trace.plane.normal, i, into);
            mathlib.VectorSubtract(ent.v.velocity, into, side);

            ent.v.velocity[0] = side[0] * (1 + d);
            ent.v.velocity[1] = side[1] * (1 + d);
        }
Ejemplo n.º 25
0
        /*
        ================
        SV_Physics_Pusher

        ================
        */
        static void SV_Physics_Pusher(prog.edict_t ent)
        {
            double	thinktime;
            double	oldltime;
            double	movetime;

            oldltime = ent.v.ltime;

            thinktime = ent.v.nextthink;
            if (thinktime < ent.v.ltime + host.host_frametime)
            {
                movetime = thinktime - ent.v.ltime;
                if (movetime < 0)
                    movetime = 0;
            }
            else
                movetime = host.host_frametime;

            if (movetime != 0)
            {
                SV_PushMove (ent, movetime);	// advances ent.v.ltime if not blocked
            }

            if ((float)thinktime > (float)oldltime && (float)thinktime <= (float)ent.v.ltime)
            {
                ent.v.nextthink = 0;
                prog.pr_global_struct[0].time = sv.time;
                prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(ent);
                prog.pr_global_struct[0].other = prog.EDICT_TO_PROG(sv.edicts[0]);
                prog.PR_ExecuteProgram(prog.pr_functions[ent.v.think]);
                if (ent.free)
                    return;
            }
        }
Ejemplo n.º 26
0
        /*
        =====================
        SV_WalkMove

        Only used by players
        ======================
        */
        public static void SV_WalkMove(prog.edict_t ent)
        {
            double[] upmove = new double[3] {0, 0, 0}, downmove = new double[3] {0, 0, 0};
            double[] oldorg = new double[3] {0, 0, 0}, oldvel = new double[3] {0, 0, 0};
            double[] nosteporg = new double[3] {0, 0, 0}, nostepvel = new double[3] {0, 0, 0};
            int clip;
            int oldonground;
            world.trace_t steptrace = new world.trace_t(), downtrace = new world.trace_t();

            //
            // do a regular slide move unless it looks like you ran into a step
            //
            oldonground = (int)ent.v.flags & FL_ONGROUND;
            ent.v.flags = (int)ent.v.flags & ~FL_ONGROUND;

            mathlib.VectorCopy(ent.v.origin, oldorg);
            mathlib.VectorCopy(ent.v.velocity, oldvel);

            clip = SV_FlyMove(ent, host.host_frametime, ref 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 != MOVETYPE_WALK)
                return; // gibbed by a trigger

            if (sv_nostep.value != 0.0)
                return;

            if (((int)sv_player.v.flags & FL_WATERJUMP) != 0)
                return;

            mathlib.VectorCopy(ent.v.origin, nosteporg);
            mathlib.VectorCopy(ent.v.velocity, nostepvel);

            //
            // try moving up and forward to go up a step
            //
            mathlib.VectorCopy(oldorg, ent.v.origin); // back to start pos

            mathlib.VectorCopy(mathlib.vec3_origin, upmove);
            mathlib.VectorCopy(mathlib.vec3_origin, downmove);
            upmove[2] = STEPSIZE;
            downmove[2] = -STEPSIZE + oldvel[2] * host.host_frametime;

            // move up
            SV_PushEntity(ent, upmove); // FIXME: don't link?

            // move forward
            ent.v.velocity[0] = oldvel[0];
            ent.v.velocity[1] = oldvel[1];
            ent.v.velocity[2] = 0;
            clip = SV_FlyMove(ent, host.host_frametime, ref steptrace);

            // check for stuckness, possibly due to the limited precision of floats
            // in the clipping hulls
            if (clip != 0)
            {
                if ( Math.Abs(oldorg[1] - ent.v.origin[1]) < 0.03125 &&  Math.Abs(oldorg[0] - ent.v.origin[0]) < 0.03125)
                {
                    // stepping up didn't make any progress
                    clip = SV_TryUnstick(ent, oldvel);
                }
            }

            // extra friction based on view angle
            if ((clip & 2) != 0)
                SV_WallFriction(ent, steptrace);

            // move down
            downtrace = SV_PushEntity(ent, downmove); // FIXME: don't link?

            if (downtrace.plane.normal[2] > 0.7)
            {
                if (ent.v.solid == SOLID_BSP)
                {
                    ent.v.flags = (int)ent.v.flags | FL_ONGROUND;
                    ent.v.groundentity = prog.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
                mathlib.VectorCopy(nosteporg, ent.v.origin);
                mathlib.VectorCopy(nostepvel, ent.v.velocity);
            }
        }
Ejemplo n.º 27
0
        /*
        =============
        SV_Physics_Toss

        Toss, bounce, and fly movement.  When onground, do nothing.
        =============
        */
        static void SV_Physics_Toss(prog.edict_t ent)
        {
            world.trace_t	trace= new world.trace_t();
            double[]	move = new double[3] {0, 0, 0};
            double      backoff;

            // regular thinking
            if (!SV_RunThink (ent))
                return;

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

            SV_CheckVelocity (ent);

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

            // move angles
            mathlib.VectorMA (ent.v.angles, host.host_frametime, ent.v.avelocity, ent.v.angles);

            // move origin
            mathlib.VectorScale (ent.v.velocity, host.host_frametime, move);
            trace = SV_PushEntity (ent, move);
            if (trace.fraction == 1)
                return;
            if (ent.free)
                return;

            if (ent.v.movetype == MOVETYPE_BOUNCE)
                backoff = 1.5;
            else
                backoff = 1;

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

            // stop if on ground
            if (trace.plane.normal[2] > 0.7)
            {
                if (ent.v.velocity[2] < 60 || ent.v.movetype != MOVETYPE_BOUNCE)
                {
                    ent.v.flags = (int)ent.v.flags | FL_ONGROUND;
                    ent.v.groundentity = prog.EDICT_TO_PROG(trace.ent);
                    mathlib.VectorCopy(mathlib.vec3_origin, ent.v.velocity);
                    mathlib.VectorCopy(mathlib.vec3_origin, ent.v.avelocity);
                }
            }

            // check for in water
            SV_CheckWaterTransition(ent);
        }
Ejemplo n.º 28
0
        /*
        ============
        SV_AddGravity

        ============
        */
        static void SV_AddGravity(prog.edict_t ent)
        {
            double	ent_gravity;

            /*eval_t	*val;

            val = GetEdictFieldValue(ent, "gravity"); //TODO GetEdictFieldValue and gravity
            if (val && val._float)
                ent_gravity = val._float;
            else*/
            ent_gravity = 1.0;
            ent.v.velocity[2] -= ent_gravity * sv_gravity.value * host.host_frametime;
        }
Ejemplo n.º 29
0
        /*
        ============
        SV_PushMove

        ============
        */
        static void SV_PushMove(prog.edict_t pusher, Double movetime)
        {
            int			i, e;
            prog.edict_t		check, block;
            double[]		mins = new double[3] {0, 0, 0}, maxs = new double[3] {0, 0, 0}, move = new double[3] {0, 0, 0};
            double[]		entorig = new double[3] {0, 0, 0}, pushorig = new double[3] {0, 0, 0};
            int			num_moved;
            prog.edict_t[] moved_edict = new prog.edict_t[quakedef.MAX_EDICTS];
            double[][]		moved_from = new double[quakedef.MAX_EDICTS][];

            if (pusher.v.velocity[0]==0 && pusher.v.velocity[1]==0 && pusher.v.velocity[2]==0)
            {
            pusher.v.ltime += movetime;
            return;
            }

            for (i=0 ; i<3 ; i++)
            {
            move[i] = pusher.v.velocity[i] * movetime;
            mins[i] = pusher.v.absmin[i] + move[i];
            maxs[i] = pusher.v.absmax[i] + move[i];
            }

            mathlib.VectorCopy (pusher.v.origin, pushorig);

            // move the pusher to it's final position

            mathlib.VectorAdd (pusher.v.origin, move, pusher.v.origin);
            pusher.v.ltime += movetime;
            world.SV_LinkEdict (pusher, false);

            // see if any solid entities are inside the final position
            num_moved = 0;
            check = prog.NEXT_EDICT(sv.edicts[0]);
            for (e=1 ; e<sv.num_edicts ; e++, check = prog.NEXT_EDICT(check))
            {
            if (check.free)
            continue;
            //Debug.WriteLine(string.Format("e: {0} movetype:{1}", e, (int)check.v.movetype));

            if (check.v.movetype == MOVETYPE_PUSH
            || check.v.movetype == MOVETYPE_NONE

            || check.v.movetype == MOVETYPE_NOCLIP)
            continue;

            // if the entity is standing on the pusher, it will definately be moved
            if ( ! ( ((int)check.v.flags & FL_ONGROUND) != 0
            && prog.PROG_TO_EDICT(check.v.groundentity) == pusher) )
            {
            if ( check.v.absmin[0] >= maxs[0]
            || check.v.absmin[1] >= maxs[1]
            || check.v.absmin[2] >= maxs[2]
            || check.v.absmax[0] <= mins[0]
            || check.v.absmax[1] <= mins[1]
            || check.v.absmax[2] <= mins[2] )
                continue;

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

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

            for (int j = 0; j < moved_from.Length; j++)
            {
            moved_from[j] = new double[3] {0, 0, 0};
            }

            mathlib.VectorCopy (check.v.origin, entorig);
            mathlib.VectorCopy (check.v.origin, moved_from[num_moved]);
            moved_edict[num_moved] = check;
            num_moved++;

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

            // if it is still inside the pusher, block
            block = world.SV_TestEntityPosition (check);
            if (block != null)
            {	// fail the move
            if (check.v.mins[0] == check.v.maxs[0])
                continue;
            if (check.v.solid == SOLID_NOT || check.v.solid == SOLID_TRIGGER)
            {	// corpse
                check.v.mins[0] = check.v.mins[1] = 0;
                mathlib.VectorCopy (check.v.mins, check.v.maxs);
                continue;
            }

            mathlib.VectorCopy (entorig, check.v.origin);
            world.SV_LinkEdict (check, true);

            mathlib.VectorCopy (pushorig, pusher.v.origin);
            world.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 != null)
            {
                prog.pr_global_struct[0].self = prog.EDICT_TO_PROG(pusher);
               prog.pr_global_struct[0].other = prog.EDICT_TO_PROG(check);
                prog.PR_ExecuteProgram (prog.pr_functions[pusher.v.blocked]);
            }

            // move back any entities we already moved
            for (i=0 ; i<num_moved ; i++)
            {
                mathlib.VectorCopy (moved_from[i], moved_edict[i].v.origin);
                world.SV_LinkEdict (moved_edict[i], false);
            }
            return;
            }
            }
        }
Ejemplo n.º 30
0
       /*
       ===============
       SV_FindTouchedLeafs

       ===============
       */
       static void SV_FindTouchedLeafs(prog.edict_t ent, model.node_or_leaf_t node)
       {
           model.mplane_t splitplane;
           model.node_or_leaf_t leaf;
           int sides;
           int leafnum;

           if (node.contents == bspfile.CONTENTS_SOLID)
               return;

           // add an efrag if the node is a leaf

           if (node.contents < 0)
           {
               if (ent.num_leafs == prog.MAX_ENT_LEAFS)
                   return;

               leaf = (model.node_or_leaf_t)node;
               int i;
               for ( i = 0; i < server.sv.worldmodel.leafs.Length; i++)
               {
                   var mleafT = server.sv.worldmodel.leafs[i];
                   if (mleafT == leaf)
                   {
                       break;
                   }
               }
               leafnum = i - 1;
               ent.leafnums[ent.num_leafs] = (short)leafnum;
               ent.num_leafs++;
               //Debug.WriteLine("num_leafs " + ent.num_leafs);
               //Debug.WriteLine("leafnum_ " + leafnum);
               return;
           }

           // NODE_MIXED

           splitplane = ((model.mnode_t)node).plane;
           sides = mathlib.BOX_ON_PLANE_SIDE(ent.v.absmin, ent.v.absmax, splitplane);

           // recurse down the contacted sides
           if ((sides & 1) != 0)
               SV_FindTouchedLeafs(ent, ((model.mnode_t)node).children[0]);

           if ((sides & 2) !=0)
               SV_FindTouchedLeafs(ent, ((model.mnode_t)node).children[1]);
       }