]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - world.c
physics: fix and refactor unsticking
[xonotic/darkplaces.git] / world.c
diff --git a/world.c b/world.c
index 39e0102cf63943b243bd7d8ade49681acdb7eb33..a95330fae99a4ba0ed9dc3d138d7038a6dcb9b78 100644 (file)
--- a/world.c
+++ b/world.c
@@ -32,29 +32,45 @@ line of sight checks trace->inopen and trace->inwater, but bullets don't
 
 */
 
+#ifdef USEODE
 static void World_Physics_Init(void);
+#endif
 void World_Init(void)
 {
        Collision_Init();
+#ifdef USEODE
        World_Physics_Init();
+#endif
 }
 
+#ifdef USEODE
 static void World_Physics_Shutdown(void);
+#endif
 void World_Shutdown(void)
 {
+#ifdef USEODE
        World_Physics_Shutdown();
+#endif
 }
 
+#ifdef USEODE
 static void World_Physics_Start(world_t *world);
+#endif
 void World_Start(world_t *world)
 {
+#ifdef USEODE
        World_Physics_Start(world);
+#endif
 }
 
+#ifdef USEODE
 static void World_Physics_End(world_t *world);
+#endif
 void World_End(world_t *world)
 {
+#ifdef USEODE
        World_Physics_End(world);
+#endif
 }
 
 //============================================================================
@@ -103,7 +119,7 @@ void World_SetSize(world_t *world, const char *filename, const vec3_t mins, cons
 {
        int i;
 
-       strlcpy(world->filename, filename, sizeof(world->filename));
+       dp_strlcpy(world->filename, filename, sizeof(world->filename));
        VectorCopy(mins, world->mins);
        VectorCopy(maxs, world->maxs);
        world->prog = prog;
@@ -215,7 +231,7 @@ int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t r
        if (world->areagrid_outside.list.next)
        {
                grid = &world->areagrid_outside;
-               List_For_Each_Entry(l, &grid->list, list)
+               List_For_Each_Entry(l, &grid->list, link_t, list)
                {
                        ent = PRVM_EDICT_NUM(l->entitynumber);
                        if (ent->priv.server->areagridmarknumber != world->areagrid_marknumber)
@@ -239,7 +255,7 @@ int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t r
                {
                        if (grid->list.next)
                        {
-                               List_For_Each_Entry(l, &grid->list, list)
+                               List_For_Each_Entry(l, &grid->list, link_t, list)
                                {
                                        ent = PRVM_EDICT_NUM(l->entitynumber);
                                        if (ent->priv.server->areagridmarknumber != world->areagrid_marknumber)
@@ -301,13 +317,17 @@ World_LinkEdict
 
 ===============
 */
-void World_LinkEdict(world_t *world, prvm_edict_t *ent, const vec3_t mins, const vec3_t maxs)
+void World_LinkEdict(world_t *world, prvm_edict_t *ent, const vec3_t mins, const vec3_t maxs, qbool link_solid_not)
 {
        prvm_prog_t *prog = world->prog;
        // unlink from old position first
        if (ent->priv.server->areagrid[0].list.prev)
                World_UnlinkEdict(ent);
 
+       // some games don't want SOLID_NOT entities linked
+       if (!link_solid_not && PRVM_serveredictfloat(ent, solid) == SOLID_NOT)
+               return;
+
        // don't add the world
        if (ent == prog->edicts)
                return;
@@ -1459,15 +1479,12 @@ static dllfunction_t odefuncs[] =
 //     {"dGeomTriMeshDataUpdate",                      (void **) &dGeomTriMeshDataUpdate},
        {NULL, NULL}
 };
-
 // Handle for ODE DLL
 dllhandle_t ode_dll = NULL;
 #endif
-#endif
 
 static void World_Physics_Init(void)
 {
-#ifdef USEODE
 #ifndef LINK_TO_LIBODE
        const char* dllnames [] =
        {
@@ -1551,12 +1568,9 @@ static void World_Physics_Init(void)
                }
 #endif
        }
-#endif
 }
-
 static void World_Physics_Shutdown(void)
 {
-#ifdef USEODE
 #ifndef LINK_TO_LIBODE
        if (ode_dll)
 #endif
@@ -1567,10 +1581,8 @@ static void World_Physics_Shutdown(void)
                ode_dll = NULL;
 #endif
        }
-#endif
 }
 
-#ifdef USEODE
 static void World_Physics_UpdateODE(world_t *world)
 {
        dWorldID odeworld;
@@ -1627,20 +1639,16 @@ static void World_Physics_EnableODE(world_t *world)
 
        World_Physics_UpdateODE(world);
 }
-#endif
 
 static void World_Physics_Start(world_t *world)
 {
-#ifdef USEODE
        if (world->physics.ode)
                return;
        World_Physics_EnableODE(world);
-#endif
 }
 
 static void World_Physics_End(world_t *world)
 {
-#ifdef USEODE
        if (world->physics.ode)
        {
                dWorldDestroy((dWorldID)world->physics.ode_world);
@@ -1648,17 +1656,14 @@ static void World_Physics_End(world_t *world)
                dJointGroupDestroy((dJointGroupID)world->physics.ode_contactgroup);
                world->physics.ode = false;
        }
-#endif
 }
 
 void World_Physics_RemoveJointFromEntity(world_t *world, prvm_edict_t *ed)
 {
        ed->priv.server->ode_joint_type = 0;
-#ifdef USEODE
        if(ed->priv.server->ode_joint)
                dJointDestroy((dJointID)ed->priv.server->ode_joint);
        ed->priv.server->ode_joint = NULL;
-#endif
 }
 
 void World_Physics_RemoveFromEntity(world_t *world, prvm_edict_t *ed)
@@ -1667,7 +1672,6 @@ void World_Physics_RemoveFromEntity(world_t *world, prvm_edict_t *ed)
 
        // entity is not physics controlled, free any physics data
        ed->priv.server->ode_physics = false;
-#ifdef USEODE
        if (ed->priv.server->ode_geom)
                dGeomDestroy((dGeomID)ed->priv.server->ode_geom);
        ed->priv.server->ode_geom = NULL;
@@ -1697,7 +1701,6 @@ void World_Physics_RemoveFromEntity(world_t *world, prvm_edict_t *ed)
                dBodyDestroy((dBodyID)ed->priv.server->ode_body);
        }
        ed->priv.server->ode_body = NULL;
-#endif
        if (ed->priv.server->ode_vertex3f)
                Mem_Free(ed->priv.server->ode_vertex3f);
        ed->priv.server->ode_vertex3f = NULL;
@@ -1720,7 +1723,6 @@ void World_Physics_RemoveFromEntity(world_t *world, prvm_edict_t *ed)
 
 void World_Physics_ApplyCmd(prvm_edict_t *ed, edict_odefunc_t *f)
 {
-#ifdef USEODE
        dBodyID body = (dBodyID)ed->priv.server->ode_body;
 
        switch(f->type)
@@ -1742,10 +1744,8 @@ void World_Physics_ApplyCmd(prvm_edict_t *ed, edict_odefunc_t *f)
        default:
                break;
        }
-#endif
 }
 
-#ifdef USEODE
 static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed)
 {
        prvm_prog_t *prog = world->prog;
@@ -2733,17 +2733,17 @@ treatasbox:
        if (physics_ode_trick_fixnan.integer)
        {
                test = VectorLength2(origin) + VectorLength2(forward) + VectorLength2(left) + VectorLength2(up) + VectorLength2(velocity) + VectorLength2(spinvelocity);
-               if (VEC_IS_NAN(test))
+               if (isnan(test))
                {
                        modified = true;
                        //Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .axis_forward = '%f %f %f' .axis_left = '%f %f %f' .axis_up = %f %f %f' .spinvelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_gameedictstring(ed, classname)), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], forward[0], forward[1], forward[2], left[0], left[1], left[2], up[0], up[1], up[2], spinvelocity[0], spinvelocity[1], spinvelocity[2]);
                        if (physics_ode_trick_fixnan.integer >= 2)
                                Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .angles = '%f %f %f' .avelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], angles[0], angles[1], angles[2], avelocity[0], avelocity[1], avelocity[2]);
                        test = VectorLength2(origin);
-                       if (VEC_IS_NAN(test))
+                       if (isnan(test))
                                VectorClear(origin);
                        test = VectorLength2(forward) * VectorLength2(left) * VectorLength2(up);
-                       if (VEC_IS_NAN(test))
+                       if (isnan(test))
                        {
                                VectorSet(angles, 0, 0, 0);
                                VectorSet(forward, 1, 0, 0);
@@ -2751,10 +2751,10 @@ treatasbox:
                                VectorSet(up, 0, 0, 1);
                        }
                        test = VectorLength2(velocity);
-                       if (VEC_IS_NAN(test))
+                       if (isnan(test))
                                VectorClear(velocity);
                        test = VectorLength2(spinvelocity);
-                       if (VEC_IS_NAN(test))
+                       if (isnan(test))
                        {
                                VectorClear(avelocity);
                                VectorClear(spinvelocity);
@@ -3006,11 +3006,9 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2)
                dJointAttach(c, b1, b2);
        }
 }
-#endif
 
 void World_Physics_Frame(world_t *world, double frametime, double gravity)
 {
-#ifdef USEODE
        prvm_prog_t *prog = world->prog;
        double tdelta, tdelta2, tdelta3, simulationtime, collisiontime;
 
@@ -3117,5 +3115,5 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity)
                        }
                }
        }
-#endif
 }
+#endif