]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_phys.c
fix return value of FS_WhichPack to NOT include the -basedir
[xonotic/darkplaces.git] / sv_phys.c
index a08f5d8bd39c60de43bebdf9e0ea5ed88b19058e..39cb72ad9309ec8e5d70d4084a9444ede18d103b 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -107,7 +107,7 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const
        // matrices to transform into/out of other entity's space
        matrix4x4_t matrix, imatrix;
        // model of other entity
-       model_t *model;
+       dp_model_t *model;
        // list of entities to test for collisions
        int numtouchedicts;
        prvm_edict_t *touchedicts[MAX_EDICTS];
@@ -255,6 +255,63 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const
 }
 #endif
 
+int SV_PointSuperContents(const vec3_t point)
+{
+       int supercontents = 0;
+       int i;
+       prvm_edict_t *touch;
+       vec3_t transformed;
+       // matrices to transform into/out of other entity's space
+       matrix4x4_t matrix, imatrix;
+       // model of other entity
+       dp_model_t *model;
+       unsigned int modelindex;
+       int frame;
+       // list of entities to test for collisions
+       int numtouchedicts;
+       prvm_edict_t *touchedicts[MAX_EDICTS];
+
+       // get world supercontents at this point
+       if (sv.worldmodel && sv.worldmodel->PointSuperContents)
+               supercontents = sv.worldmodel->PointSuperContents(sv.worldmodel, 0, point);
+
+       // if sv_gameplayfix_swiminbmodels is off we're done
+       if (!sv_gameplayfix_swiminbmodels.integer)
+               return supercontents;
+
+       // get list of entities at this point
+       numtouchedicts = World_EntitiesInBox(&sv.world, point, point, MAX_EDICTS, touchedicts);
+       if (numtouchedicts > MAX_EDICTS)
+       {
+               // this never happens
+               Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
+               numtouchedicts = MAX_EDICTS;
+       }
+       for (i = 0;i < numtouchedicts;i++)
+       {
+               touch = touchedicts[i];
+
+               // we only care about SOLID_BSP for pointcontents
+               if (touch->fields.server->solid != SOLID_BSP)
+                       continue;
+
+               // might interact, so do an exact clip
+               modelindex = (unsigned int)touch->fields.server->modelindex;
+               if (modelindex >= MAX_MODELS)
+                       continue;
+               model = sv.models[(int)touch->fields.server->modelindex];
+               if (!model || !model->PointSuperContents)
+                       continue;
+               Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
+               Matrix4x4_Invert_Simple(&imatrix, &matrix);
+               Matrix4x4_Transform(&imatrix, point, transformed);
+               frame = (int)touch->fields.server->frame;
+               supercontents |= model->PointSuperContents(model, bound(0, frame, (model->numframes - 1)), transformed);
+       }
+
+       return supercontents;
+}
+
 /*
 ===============================================================================
 
@@ -321,7 +378,7 @@ SV_LinkEdict
 */
 void SV_LinkEdict (prvm_edict_t *ent, qboolean touch_triggers)
 {
-       model_t *model;
+       dp_model_t *model;
        vec3_t mins, maxs;
 
        if (ent == prog->edicts)
@@ -343,7 +400,7 @@ void SV_LinkEdict (prvm_edict_t *ent, qboolean touch_triggers)
                model = sv.models[modelindex];
                if (model != NULL)
                {
-                       if (!model->TraceBox)
+                       if (!model->TraceBox && developer.integer >= 1)
                                Con_Printf("edict %i: SOLID_BSP with non-collidable model\n", PRVM_NUM_FOR_EDICT(ent));
 
                        if (ent->fields.server->angles[0] || ent->fields.server->angles[2] || ent->fields.server->avelocity[0] || ent->fields.server->avelocity[2])
@@ -552,12 +609,12 @@ void SV_CheckVelocity (prvm_edict_t *ent)
        {
                if (IS_NAN(ent->fields.server->velocity[i]))
                {
-                       Con_Printf("Got a NaN velocity on %s\n", PRVM_GetString(ent->fields.server->classname));
+                       Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(ent->fields.server->classname));
                        ent->fields.server->velocity[i] = 0;
                }
                if (IS_NAN(ent->fields.server->origin[i]))
                {
-                       Con_Printf("Got a NaN origin on %s\n", PRVM_GetString(ent->fields.server->classname));
+                       Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(ent->fields.server->classname));
                        ent->fields.server->origin[i] = 0;
                }
        }
@@ -921,7 +978,7 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal, int hitsuperco
        */
 
        // LordHavoc: this came from QW and allows you to get out of water more easily
-       if (sv_gameplayfix_qwplayerphysics.integer && ((int)ent->fields.server->flags & FL_WATERJUMP))
+       if (sv_gameplayfix_easierwaterjump.integer && ((int)ent->fields.server->flags & FL_WATERJUMP))
                VectorCopy(primal_velocity, ent->fields.server->velocity);
        return blocked;
 }
@@ -998,12 +1055,14 @@ SV_PushMove
 void SV_PushMove (prvm_edict_t *pusher, float movetime)
 {
        int i, e, index;
+       int checkcontents;
+       qboolean rotated;
        float savesolid, movetime2, pushltime;
        vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org;
        int num_moved;
        int numcheckentities;
        static prvm_edict_t *checkentities[MAX_EDICTS];
-       model_t *pushermodel;
+       dp_model_t *pushermodel;
        trace_t trace;
        matrix4x4_t pusherfinalmatrix, pusherfinalimatrix;
        unsigned short moved_edicts[MAX_EDICTS];
@@ -1045,6 +1104,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
        }
        pushermodel = sv.models[index];
 
+       rotated = VectorLength2(pusher->fields.server->angles) + VectorLength2(pusher->fields.server->avelocity) > 0;
+
        movetime2 = movetime;
        VectorScale(pusher->fields.server->velocity, movetime2, move1);
        VectorScale(pusher->fields.server->avelocity, movetime2, moveangle);
@@ -1126,7 +1187,6 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
        for (e = 0;e < numcheckentities;e++)
        {
                prvm_edict_t *check = checkentities[e];
-               int checkcontents = SV_GenericHitSuperContentsMask(check);
                if (check->fields.server->movetype == MOVETYPE_NONE
                 || check->fields.server->movetype == MOVETYPE_PUSH
                 || check->fields.server->movetype == MOVETYPE_FOLLOW
@@ -1134,18 +1194,28 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                 || check->fields.server->movetype == MOVETYPE_FAKEPUSH)
                        continue;
 
+               //Con_Printf("%i %s ", PRVM_NUM_FOR_EDICT(check), PRVM_GetString(check->fields.server->classname));
+
+               // tell any MOVETYPE_STEP entity that it may need to check for water transitions
+               check->priv.server->waterposition_forceupdate = true;
+
+               checkcontents = SV_GenericHitSuperContentsMask(check);
+
                // if the entity is standing on the pusher, it will definitely be moved
                // if the entity is not standing on the pusher, but is in the pusher's
                // final position, move it
                if (!((int)check->fields.server->flags & FL_ONGROUND) || PRVM_PROG_TO_EDICT(check->fields.server->groundentity) != pusher)
                {
                        Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, checkcontents);
+                       //trace = SV_Move(check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, MOVE_NOMONSTERS, check, checkcontents);
                        if (!trace.startsolid)
+                       {
+                               //Con_Printf("- not in solid\n");
                                continue;
+                       }
                }
 
-
-               if (forward[0] != 1 || left[1] != 1) // quick way to check if any rotation is used
+               if (rotated)
                {
                        vec3_t org2;
                        VectorSubtract (check->fields.server->origin, pusher->fields.server->origin, org);
@@ -1158,6 +1228,8 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                else
                        VectorCopy (move1, move);
 
+               //Con_Printf("- pushing %f %f %f\n", move[0], move[1], move[2]);
+
                VectorCopy (check->fields.server->origin, check->priv.server->moved_from);
                VectorCopy (check->fields.server->angles, check->priv.server->moved_fromangles);
                moved_edicts[num_moved++] = PRVM_NUM_FOR_EDICT(check);
@@ -1302,21 +1374,37 @@ static float unstickoffsets[] =
         1,  1,  0,
         0,  0,  -1,
         0,  0,  1,
+        0,  0,  -2,
         0,  0,  2,
+        0,  0,  -3,
         0,  0,  3,
+        0,  0,  -4,
         0,  0,  4,
+        0,  0,  -5,
         0,  0,  5,
+        0,  0,  -6,
         0,  0,  6,
+        0,  0,  -7,
         0,  0,  7,
+        0,  0,  -8,
         0,  0,  8,
+        0,  0,  -9,
         0,  0,  9,
+        0,  0,  -10,
         0,  0,  10,
+        0,  0,  -11,
         0,  0,  11,
+        0,  0,  -12,
         0,  0,  12,
+        0,  0,  -13,
         0,  0,  13,
+        0,  0,  -14,
         0,  0,  14,
+        0,  0,  -15,
         0,  0,  15,
+        0,  0,  -16,
         0,  0,  16,
+        0,  0,  -17,
         0,  0,  17,
 };
 
@@ -1360,13 +1448,13 @@ void SV_CheckStuck (prvm_edict_t *ent)
        Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
 }
 
-static void SV_UnstickEntity (prvm_edict_t *ent)
+qboolean SV_UnstickEntity (prvm_edict_t *ent)
 {
        int i;
 
        // if not stuck in a bmodel, just return
        if (!SV_TestEntityPosition(ent, vec3_origin))
-               return;
+               return true;
 
        for (i = 0;i < (int)(sizeof(unstickoffsets) / sizeof(unstickoffsets[0]));i += 3)
        {
@@ -1374,12 +1462,13 @@ static void SV_UnstickEntity (prvm_edict_t *ent)
                {
                        Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname), unstickoffsets[i+0], unstickoffsets[i+1], unstickoffsets[i+2]);
                        SV_LinkEdict (ent, true);
-                       return;
+                       return true;
                }
        }
 
        if (developer.integer >= 100)
                Con_Printf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname));
+       return false;
 }
 
 
@@ -1902,6 +1991,13 @@ will fall if the floor is pulled out from under them.
 void SV_Physics_Step (prvm_edict_t *ent)
 {
        int flags = (int)ent->fields.server->flags;
+
+       // DRESK
+       // Backup Velocity in the event that movetypesteplandevent is called,
+       // to provide a parameter with the entity's velocity at impact.
+       prvm_eval_t *movetypesteplandevent;
+       vec3_t backupVelocity;
+       VectorCopy(ent->fields.server->velocity, backupVelocity);
        // don't fall at all if fly/swim
        if (!(flags & (FL_FLY | FL_SWIM)))
        {
@@ -1916,6 +2012,7 @@ void SV_Physics_Step (prvm_edict_t *ent)
                                SV_CheckVelocity(ent);
                                SV_FlyMove(ent, sv.frametime, NULL, SV_GenericHitSuperContentsMask(ent));
                                SV_LinkEdict(ent, true);
+                               ent->priv.server->waterposition_forceupdate = true;
                        }
                }
                else
@@ -1929,15 +2026,42 @@ void SV_Physics_Step (prvm_edict_t *ent)
                        SV_LinkEdict(ent, true);
 
                        // just hit ground
-                       if (hitsound && (int)ent->fields.server->flags & FL_ONGROUND && sv_sound_land.string)
-                               SV_StartSound(ent, 0, sv_sound_land.string, 255, 1);
+                       if (hitsound && (int)ent->fields.server->flags & FL_ONGROUND)
+                       {
+                               // DRESK - Check for Entity Land Event Function
+                               movetypesteplandevent = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.movetypesteplandevent);
+
+                               if(movetypesteplandevent->function)
+                               { // Valid Function; Execute
+                                       // Prepare Parameters
+                                               // Assign Velocity at Impact
+                                               PRVM_G_VECTOR(OFS_PARM0)[0] = backupVelocity[0];
+                                               PRVM_G_VECTOR(OFS_PARM0)[1] = backupVelocity[1];
+                                               PRVM_G_VECTOR(OFS_PARM0)[2] = backupVelocity[2];
+                                               // Assign Self
+                                               prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
+                                       // Execute VM Function
+                                       PRVM_ExecuteProgram(movetypesteplandevent->function, "movetypesteplandevent: NULL function");
+                               }
+                               else
+                               // Check for Engine Landing Sound
+                               if(sv_sound_land.string)
+                                       SV_StartSound(ent, 0, sv_sound_land.string, 255, 1);
+                       }
+                       ent->priv.server->waterposition_forceupdate = true;
                }
        }
 
 // regular thinking
-       SV_RunThink(ent);
+       if (!SV_RunThink(ent))
+               return;
 
-       SV_CheckWaterTransition(ent);
+       if (ent->priv.server->waterposition_forceupdate || !VectorCompare(ent->fields.server->origin, ent->priv.server->waterposition_origin))
+       {
+               ent->priv.server->waterposition_forceupdate = false;
+               VectorCopy(ent->fields.server->origin, ent->priv.server->waterposition_origin);
+               SV_CheckWaterTransition(ent);
+       }
 }
 
 //============================================================================