]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_move.c
Fix setinfo.
[xonotic/darkplaces.git] / sv_move.c
index 87f3ed434a38ab1cd53b99de326a0701472b501c..ced05ac1b1ca03260b359dfb716b6cba8cd9e273 100644 (file)
--- a/sv_move.c
+++ b/sv_move.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
 
 See the GNU General Public License for more details.
 
@@ -20,8 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // sv_move.c -- monster movement
 
 #include "quakedef.h"
 // sv_move.c -- monster movement
 
 #include "quakedef.h"
-
-#define        STEPSIZE        18
+#include "prvm_cmds.h"
 
 /*
 =============
 
 /*
 =============
@@ -34,15 +33,16 @@ is not a staircase.
 */
 int c_yes, c_no;
 
 */
 int c_yes, c_no;
 
-qboolean SV_CheckBottom (edict_t *ent)
+qboolean SV_CheckBottom (prvm_edict_t *ent)
 {
 {
+       prvm_prog_t *prog = SVVM_prog;
        vec3_t  mins, maxs, start, stop;
        trace_t trace;
        int             x, y;
        float   mid, bottom;
        vec3_t  mins, maxs, start, stop;
        trace_t trace;
        int             x, y;
        float   mid, bottom;
-       
-       VectorAdd (ent->v.origin, ent->v.mins, mins);
-       VectorAdd (ent->v.origin, ent->v.maxs, maxs);
+
+       VectorAdd (PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), mins);
+       VectorAdd (PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, maxs), maxs);
 
 // if all of the points under the corners are solid world, don't bother
 // with the tougher checks
 
 // if all of the points under the corners are solid world, don't bother
 // with the tougher checks
@@ -53,7 +53,7 @@ qboolean SV_CheckBottom (edict_t *ent)
                {
                        start[0] = x ? maxs[0] : mins[0];
                        start[1] = y ? maxs[1] : mins[1];
                {
                        start[0] = x ? maxs[0] : mins[0];
                        start[1] = y ? maxs[1] : mins[1];
-                       if (SV_PointContents (start) != CONTENTS_SOLID)
+                       if (!(SV_PointSuperContents(start) & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY)))
                                goto realcheck;
                }
 
                                goto realcheck;
                }
 
@@ -66,29 +66,29 @@ realcheck:
 // check it for real...
 //
        start[2] = mins[2];
 // 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;
 // 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 = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
+       stop[2] = start[2] - 2*sv_stepheight.value;
+       trace = SV_TraceLine(start, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
 
        if (trace.fraction == 1.0)
                return false;
        mid = bottom = trace.endpos[2];
 
        if (trace.fraction == 1.0)
                return false;
        mid = bottom = trace.endpos[2];
-       
-// the corners must be within 16 of the midpoint       
+
+// 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 ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
        for     (x=0 ; x<=1 ; x++)
                for     (y=0 ; y<=1 ; y++)
                {
                        start[0] = stop[0] = x ? maxs[0] : mins[0];
                        start[1] = stop[1] = y ? maxs[1] : mins[1];
-                       
-                       trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
-                       
+
+                       trace = SV_TraceLine(start, stop, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
+
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
                                bottom = trace.endpos[2];
-                       if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
+                       if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
                                return false;
                }
 
                                return false;
                }
 
@@ -103,85 +103,96 @@ SV_movestep
 
 Called by monster program code.
 The move will be adjusted for slopes and stairs, but if the move isn't
 
 Called by monster program code.
 The move will be adjusted for slopes and stairs, but if the move isn't
-possible, no move is done, false is returned, and
-pr_global_struct->trace_normal is set to the normal of the blocking wall
+possible, no move is done and false is returned
 =============
 */
 =============
 */
-qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
+qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean settrace)
 {
 {
+       prvm_prog_t *prog = SVVM_prog;
        float           dz;
        float           dz;
-       vec3_t          oldorg, neworg, end;
+       vec3_t          oldorg, neworg, end, traceendpos, entorigin, entmins, entmaxs;
        trace_t         trace;
        int                     i;
        trace_t         trace;
        int                     i;
-       edict_t         *enemy;
+       prvm_edict_t            *enemy;
 
 
-// try the move        
-       VectorCopy (ent->v.origin, oldorg);
-       VectorAdd (ent->v.origin, move, neworg);
+// try the move
+       VectorCopy (PRVM_serveredictvector(ent, origin), oldorg);
+       VectorAdd (PRVM_serveredictvector(ent, origin), move, neworg);
+       VectorCopy(PRVM_serveredictvector(ent, mins), entmins);
+       VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs);
 
 // flying monsters don't step up
 
 // flying monsters don't step up
-       if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) )
+       if ( (int)PRVM_serveredictfloat(ent, flags) & (FL_SWIM | FL_FLY) )
        {
        // try one move with vertical motion, then one without
                for (i=0 ; i<2 ; i++)
                {
        {
        // try one move with vertical motion, then one without
                for (i=0 ; i<2 ; i++)
                {
-                       VectorAdd (ent->v.origin, move, neworg);
-                       enemy = PROG_TO_EDICT(ent->v.enemy);
-                       if (i == 0 && enemy != sv.edicts)
+                       VectorAdd (PRVM_serveredictvector(ent, origin), move, neworg);
+                       if (noenemy)
+                               enemy = prog->edicts;
+                       else
                        {
                        {
-                               dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2];
-                               if (dz > 40)
-                                       neworg[2] -= 8;
-                               if (dz < 30)
-                                       neworg[2] += 8;
+                               enemy = PRVM_PROG_TO_EDICT(PRVM_serveredictedict(ent, enemy));
+                               if (i == 0 && enemy != prog->edicts)
+                               {
+                                       dz = PRVM_serveredictvector(ent, origin)[2] - PRVM_serveredictvector(enemy, origin)[2];
+                                       if (dz > 40)
+                                               neworg[2] -= 8;
+                                       if (dz < 30)
+                                               neworg[2] += 8;
+                               }
                        }
                        }
-                       trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
-       
+                       VectorCopy(PRVM_serveredictvector(ent, origin), entorigin);
+                       trace = SV_TraceBox(entorigin, entmins, entmaxs, neworg, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
+
                        if (trace.fraction == 1)
                        {
                        if (trace.fraction == 1)
                        {
-                               if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY )
+                               VectorCopy(trace.endpos, traceendpos);
+                               if (((int)PRVM_serveredictfloat(ent, flags) & FL_SWIM) && !(SV_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
                                        return false;   // swim monster left water
                                        return false;   // swim monster left water
-       
-                               VectorCopy (trace.endpos, ent->v.origin);
+
+                               VectorCopy (traceendpos, PRVM_serveredictvector(ent, origin));
                                if (relink)
                                if (relink)
-                                       SV_LinkEdict (ent, true);
+                               {
+                                       SV_LinkEdict(ent);
+                                       SV_LinkEdict_TouchAreaGrid(ent);
+                               }
                                return true;
                        }
                                return true;
                        }
-                       
-                       if (enemy == sv.edicts)
+
+                       if (enemy == prog->edicts)
                                break;
                }
                                break;
                }
-               
+
                return false;
        }
 
 // push down from a step height above the wished position
                return false;
        }
 
 // push down from a step height above the wished position
-       neworg[2] += STEPSIZE;
+       neworg[2] += sv_stepheight.value;
        VectorCopy (neworg, end);
        VectorCopy (neworg, end);
-       end[2] -= STEPSIZE*2;
-
-       trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
+       end[2] -= sv_stepheight.value*2;
 
 
-       if (trace.allsolid)
-               return false;
+       trace = SV_TraceBox(neworg, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
 
        if (trace.startsolid)
        {
 
        if (trace.startsolid)
        {
-               neworg[2] -= STEPSIZE;
-               trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
-               if (trace.allsolid || trace.startsolid)
+               neworg[2] -= sv_stepheight.value;
+               trace = SV_TraceBox(neworg, entmins, entmaxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value);
+               if (trace.startsolid)
                        return false;
        }
        if (trace.fraction == 1)
        {
        // if monster had the ground pulled out, go ahead and fall
                        return false;
        }
        if (trace.fraction == 1)
        {
        // if monster had the ground pulled out, go ahead and fall
-               if ( (int)ent->v.flags & FL_PARTIALGROUND )
+               if ( (int)PRVM_serveredictfloat(ent, flags) & FL_PARTIALGROUND )
                {
                {
-                       VectorAdd (ent->v.origin, move, ent->v.origin);
+                       VectorAdd (PRVM_serveredictvector(ent, origin), move, PRVM_serveredictvector(ent, origin));
                        if (relink)
                        if (relink)
-                               SV_LinkEdict (ent, true);
-                       ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
-//     Con_Printf ("fall down\n"); 
+                       {
+                               SV_LinkEdict(ent);
+                               SV_LinkEdict_TouchAreaGrid(ent);
+                       }
+                       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_ONGROUND;
                        return true;
                }
 
                        return true;
                }
 
@@ -189,31 +200,45 @@ qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
        }
 
 // check point traces down for dangling corners
        }
 
 // check point traces down for dangling corners
-       VectorCopy (trace.endpos, ent->v.origin);
-       
+       VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin));
+
        if (!SV_CheckBottom (ent))
        {
        if (!SV_CheckBottom (ent))
        {
-               if ( (int)ent->v.flags & FL_PARTIALGROUND )
+               if ( (int)PRVM_serveredictfloat(ent, flags) & FL_PARTIALGROUND )
                {       // entity had floor mostly pulled out from underneath it
                        // and is trying to correct
                        if (relink)
                {       // entity had floor mostly pulled out from underneath it
                        // and is trying to correct
                        if (relink)
-                               SV_LinkEdict (ent, true);
+                       {
+                               SV_LinkEdict(ent);
+                               SV_LinkEdict_TouchAreaGrid(ent);
+                       }
                        return true;
                }
                        return true;
                }
-               VectorCopy (oldorg, ent->v.origin);
+               VectorCopy (oldorg, PRVM_serveredictvector(ent, origin));
                return false;
        }
 
                return false;
        }
 
-       if ( (int)ent->v.flags & FL_PARTIALGROUND )
+       if ( (int)PRVM_serveredictfloat(ent, flags) & FL_PARTIALGROUND )
+               PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) & ~FL_PARTIALGROUND;
+
+// gameplayfix: check if reached pretty steep plane and bail
+       if ( ! ( (int)PRVM_serveredictfloat(ent, flags) & (FL_SWIM | FL_FLY) ) && sv_gameplayfix_nostepmoveonsteepslopes.integer )
        {
        {
-//             Con_Printf ("back on ground\n"); 
-               ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
+               if (trace.plane.normal[ 2 ] < 0.5)
+               {
+                       VectorCopy (oldorg, PRVM_serveredictvector(ent, origin));
+                       return false;
+               }
        }
        }
-       ent->v.groundentity = EDICT_TO_PROG(trace.ent);
+
+       PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent);
 
 // the move is ok
        if (relink)
 
 // the move is ok
        if (relink)
-               SV_LinkEdict (ent, true);
+       {
+               SV_LinkEdict(ent);
+               SV_LinkEdict_TouchAreaGrid(ent);
+       }
        return true;
 }
 
        return true;
 }
 
@@ -229,33 +254,35 @@ facing it.
 
 ======================
 */
 
 ======================
 */
-void PF_changeyaw (void);
-qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
+static qboolean SV_StepDirection (prvm_edict_t *ent, float yaw, float dist)
 {
 {
+       prvm_prog_t *prog = SVVM_prog;
        vec3_t          move, oldorigin;
        float           delta;
        vec3_t          move, oldorigin;
        float           delta;
-       
-       ent->v.ideal_yaw = yaw;
-       PF_changeyaw();
-       
+
+       PRVM_serveredictfloat(ent, ideal_yaw) = yaw;
+       VM_changeyaw(prog);
+
        yaw = yaw*M_PI*2 / 360;
        move[0] = cos(yaw)*dist;
        move[1] = sin(yaw)*dist;
        move[2] = 0;
 
        yaw = yaw*M_PI*2 / 360;
        move[0] = cos(yaw)*dist;
        move[1] = sin(yaw)*dist;
        move[2] = 0;
 
-       VectorCopy (ent->v.origin, oldorigin);
-       if (SV_movestep (ent, move, false))
+       VectorCopy (PRVM_serveredictvector(ent, origin), oldorigin);
+       if (SV_movestep (ent, move, false, false, false))
        {
        {
-               delta = ent->v.angles[YAW] - ent->v.ideal_yaw;
+               delta = PRVM_serveredictvector(ent, angles)[YAW] - PRVM_serveredictfloat(ent, ideal_yaw);
                if (delta > 45 && delta < 315)
                {               // not turned far enough, so don't take the step
                if (delta > 45 && delta < 315)
                {               // not turned far enough, so don't take the step
-                       VectorCopy (oldorigin, ent->v.origin);
+                       VectorCopy (oldorigin, PRVM_serveredictvector(ent, origin));
                }
                }
-               SV_LinkEdict (ent, true);
+               SV_LinkEdict(ent);
+               SV_LinkEdict_TouchAreaGrid(ent);
                return true;
        }
                return true;
        }
-       SV_LinkEdict (ent, true);
-               
+       SV_LinkEdict(ent);
+       SV_LinkEdict_TouchAreaGrid(ent);
+
        return false;
 }
 
        return false;
 }
 
@@ -265,11 +292,10 @@ SV_FixCheckBottom
 
 ======================
 */
 
 ======================
 */
-void SV_FixCheckBottom (edict_t *ent)
+static void SV_FixCheckBottom (prvm_edict_t *ent)
 {
 {
-//     Con_Printf ("SV_FixCheckBottom\n");
-       
-       ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND;
+       prvm_prog_t *prog = SVVM_prog;
+       PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_PARTIALGROUND;
 }
 
 
 }
 
 
@@ -281,17 +307,18 @@ SV_NewChaseDir
 ================
 */
 #define        DI_NODIR        -1
 ================
 */
 #define        DI_NODIR        -1
-void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
+static void SV_NewChaseDir (prvm_edict_t *actor, prvm_edict_t *enemy, float dist)
 {
 {
+       prvm_prog_t *prog = SVVM_prog;
        float           deltax,deltay;
        float                   d[3];
        float           tdir, olddir, turnaround;
 
        float           deltax,deltay;
        float                   d[3];
        float           tdir, olddir, turnaround;
 
-       olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 );
-       turnaround = anglemod(olddir - 180);
+       olddir = ANGLEMOD((int)(PRVM_serveredictfloat(actor, ideal_yaw)/45)*45);
+       turnaround = ANGLEMOD(olddir - 180);
 
 
-       deltax = enemy->v.origin[0] - actor->v.origin[0];
-       deltay = enemy->v.origin[1] - actor->v.origin[1];
+       deltax = PRVM_serveredictvector(enemy, origin)[0] - PRVM_serveredictvector(actor, origin)[0];
+       deltay = PRVM_serveredictvector(enemy, origin)[1] - PRVM_serveredictvector(actor, origin)[1];
        if (deltax>10)
                d[1]= 0;
        else if (deltax<-10)
        if (deltax>10)
                d[1]= 0;
        else if (deltax<-10)
@@ -312,20 +339,20 @@ void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
                        tdir = d[2] == 90 ? 45 : 315;
                else
                        tdir = d[2] == 90 ? 135 : 215;
                        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 (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
                        return;
        }
 
 // try other directions
-       if ( ((rand()&3) & 1) ||  abs(deltay)>abs(deltax))
+       if ( ((rand()&3) & 1) ||  fabs(deltay)>fabs(deltax))
        {
                tdir=d[1];
                d[1]=d[2];
                d[2]=tdir;
        }
 
        {
                tdir=d[1];
                d[1]=d[2];
                d[2]=tdir;
        }
 
-       if (d[1]!=DI_NODIR && d[1]!=turnaround 
+       if (d[1]!=DI_NODIR && d[1]!=turnaround
        && SV_StepDirection(actor, d[1], dist))
                        return;
 
        && SV_StepDirection(actor, d[1], dist))
                        return;
 
@@ -354,7 +381,7 @@ void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
        if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
                        return;
 
        if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
                        return;
 
-       actor->v.ideal_yaw = olddir;            // can't move
+       PRVM_serveredictfloat(actor, 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 a bridge was pulled out from underneath a monster, it may not have
 // a valid standing position at all
@@ -370,15 +397,15 @@ SV_CloseEnough
 
 ======================
 */
 
 ======================
 */
-qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
+static qboolean SV_CloseEnough (prvm_edict_t *ent, prvm_edict_t *goal, float dist)
 {
        int             i;
 {
        int             i;
-       
+
        for (i=0 ; i<3 ; i++)
        {
        for (i=0 ; i<3 ; i++)
        {
-               if (goal->v.absmin[i] > ent->v.absmax[i] + dist)
+               if (goal->priv.server->areamins[i] > ent->priv.server->areamaxs[i] + dist)
                        return false;
                        return false;
-               if (goal->v.absmax[i] < ent->v.absmin[i] - dist)
+               if (goal->priv.server->areamaxs[i] < ent->priv.server->areamins[i] - dist)
                        return false;
        }
        return true;
                        return false;
        }
        return true;
@@ -390,28 +417,30 @@ SV_MoveToGoal
 
 ======================
 */
 
 ======================
 */
-void SV_MoveToGoal (void)
+void VM_SV_MoveToGoal(prvm_prog_t *prog)
 {
 {
-       edict_t         *ent, *goal;
+       prvm_edict_t            *ent, *goal;
        float           dist;
 
        float           dist;
 
-       ent = PROG_TO_EDICT(pr_global_struct->self);
-       goal = PROG_TO_EDICT(ent->v.goalentity);
-       dist = G_FLOAT(OFS_PARM0);
+       VM_SAFEPARMCOUNT(1, SV_MoveToGoal);
+
+       ent = PRVM_PROG_TO_EDICT(PRVM_serverglobaledict(self));
+       goal = PRVM_PROG_TO_EDICT(PRVM_serveredictedict(ent, goalentity));
+       dist = PRVM_G_FLOAT(OFS_PARM0);
 
 
-       if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
+       if ( !( (int)PRVM_serveredictfloat(ent, flags) & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
        {
        {
-               G_FLOAT(OFS_RETURN) = 0;
+               PRVM_G_FLOAT(OFS_RETURN) = 0;
                return;
        }
 
 // if the next step hits the enemy, return immediately
                return;
        }
 
 // if the next step hits the enemy, return immediately
-       if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts &&  SV_CloseEnough (ent, goal, dist) )
+       if ( PRVM_PROG_TO_EDICT(PRVM_serveredictedict(ent, enemy)) != prog->edicts &&  SV_CloseEnough (ent, goal, dist) )
                return;
 
 // bump around...
        if ( (rand()&3)==1 ||
                return;
 
 // bump around...
        if ( (rand()&3)==1 ||
-       !SV_StepDirection (ent, ent->v.ideal_yaw, dist))
+       !SV_StepDirection (ent, PRVM_serveredictfloat(ent, ideal_yaw), dist))
        {
                SV_NewChaseDir (ent, goal, dist);
        }
        {
                SV_NewChaseDir (ent, goal, dist);
        }