]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_phys.c
implemented sv_gameplayfix_multiplethinksperframe
[xonotic/darkplaces.git] / sv_phys.c
index f1b9b0b7d696c9972df248825c35715ebdcc06f6..3a4a8b005e6e94bb66c847999b3eb47f99f5a26a 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -39,44 +39,10 @@ solid_edge items only clip against bsp models.
 
 */
 
-cvar_t sv_friction = {CVAR_NOTIFY, "sv_friction","4", "how fast you slow down"};
-cvar_t sv_waterfriction = {CVAR_NOTIFY, "sv_waterfriction","-1", "how fast you slow down, if less than 0 the sv_friction variable is used instead"};
-cvar_t sv_stopspeed = {CVAR_NOTIFY, "sv_stopspeed","100", "how fast you come to a complete stop"};
-cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800", "how fast you fall (512 = roughly earth gravity)"};
-cvar_t sv_maxvelocity = {CVAR_NOTIFY, "sv_maxvelocity","2000", "universal speed limit on all entities"};
-cvar_t sv_nostep = {CVAR_NOTIFY, "sv_nostep","0", "prevents MOVETYPE_STEP entities (monsters) from moving"};
-cvar_t sv_stepheight = {CVAR_NOTIFY, "sv_stepheight", "18", "how high you can step up (TW_SV_STEPCONTROL extension)"};
-cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping (sv_gameplayfix_stepwhilejumping must also be 1)"};
-cvar_t sv_wallfriction = {CVAR_NOTIFY, "sv_wallfriction", "1", "how much you slow down when sliding along a wall"};
-cvar_t sv_newflymove = {CVAR_NOTIFY, "sv_newflymove", "0", "enables simpler/buggier player physics (not recommended)"};
-cvar_t sv_freezenonclients = {CVAR_NOTIFY, "sv_freezenonclients", "0", "freezes time, except for players, allowing you to walk around and take screenshots of explosions"};
-cvar_t sv_playerphysicsqc = {CVAR_NOTIFY, "sv_playerphysicsqc", "1", "enables QuakeC function to override player physics"};
-cvar_t sv_debugmove = {CVAR_NOTIFY, "sv_debugmove", "0", "disables collision detection optimizations for debugging purposes"};
-
-cvar_t sv_sound_watersplash = {0, "sv_sound_watersplash", "misc/h2ohit1.wav", "sound to play when MOVETYPE_FLY/TOSS/BOUNCE/STEP entity enters or leaves water (empty cvar disables the sound)"};
-cvar_t sv_sound_land = {0, "sv_sound_land", "demon/dland2.wav", "sound to play when MOVETYPE_STEP entity hits the ground at high speed (empty cvar disables the sound)"};
-
-// TODO: move this extern to server.h
-extern cvar_t sv_clmovement_waitforinput;
-
 #define        MOVE_EPSILON    0.01
 
 void SV_Physics_Toss (prvm_edict_t *ent);
 
-void SV_Phys_Init (void)
-{
-       Cvar_RegisterVariable(&sv_stepheight);
-       Cvar_RegisterVariable(&sv_jumpstep);
-       Cvar_RegisterVariable(&sv_wallfriction);
-       Cvar_RegisterVariable(&sv_newflymove);
-       Cvar_RegisterVariable(&sv_freezenonclients);
-       Cvar_RegisterVariable(&sv_playerphysicsqc);
-       Cvar_RegisterVariable(&sv_debugmove);
-
-       Cvar_RegisterVariable(&sv_sound_watersplash);
-       Cvar_RegisterVariable(&sv_sound_land);
-}
-
 /*
 ===============================================================================
 
@@ -303,7 +269,7 @@ void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
        prvm_edict_t *touch, *touchedicts[MAX_EDICTS];
 
        // build a list of edicts to touch, because the link loop can be corrupted
-       // by SV_IncreaseEdicts called during touch functions
+       // by IncreaseEdicts called during touch functions
        numtouchedicts = World_EntitiesInBox(&sv.world, ent->priv.server->areamins, ent->priv.server->areamaxs, MAX_EDICTS, touchedicts);
        if (numtouchedicts > MAX_EDICTS)
        {
@@ -617,22 +583,27 @@ Returns false if the entity removed itself.
 */
 qboolean SV_RunThink (prvm_edict_t *ent)
 {
-       float thinktime;
-
-       thinktime = ent->fields.server->nextthink;
-       if (thinktime <= 0 || thinktime > sv.time + sv.frametime)
-               return true;
+       int iterations;
 
        // don't let things stay in the past.
        // it is possible to start that way by a trigger with a local time.
-       if (thinktime < sv.time)
-               thinktime = sv.time;
+       if (ent->fields.server->nextthink <= 0 || ent->fields.server->nextthink > sv.time + sv.frametime)
+               return true;
 
-       ent->fields.server->nextthink = 0;
-       prog->globals.server->time = thinktime;
-       prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
-       prog->globals.server->other = PRVM_EDICT_TO_PROG(prog->edicts);
-       PRVM_ExecuteProgram (ent->fields.server->think, "QC function self.think is missing");
+       for (iterations = 0;iterations < 128  && !ent->priv.server->free;iterations++)
+       {
+               prog->globals.server->time = max(sv.time, ent->fields.server->nextthink);
+               ent->fields.server->nextthink = 0;
+               prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
+               prog->globals.server->other = PRVM_EDICT_TO_PROG(prog->edicts);
+               PRVM_ExecuteProgram (ent->fields.server->think, "QC function self.think is missing");
+               // mods often set nextthink to time to cause a think every frame,
+               // we don't want to loop in that case, so exit if the new nextthink is
+               // <= the time the qc was told, also exit if it is past the end of the
+               // frame
+               if (ent->fields.server->nextthink <= prog->globals.server->time || ent->fields.server->nextthink > sv.time + sv.frametime || !sv_gameplayfix_multiplethinksperframe.integer)
+                       break;
+       }
        return !ent->priv.server->free;
 }
 
@@ -644,14 +615,17 @@ Two entities have touched, so run their touch functions
 ==================
 */
 extern void VM_SetTraceGlobals(const trace_t *trace);
+extern sizebuf_t vm_tempstringsbuf;
 void SV_Impact (prvm_edict_t *e1, trace_t *trace)
 {
+       int restorevm_tempstringsbuf_cursize;
        int old_self, old_other;
        prvm_edict_t *e2 = (prvm_edict_t *)trace->ent;
        prvm_eval_t *val;
 
        old_self = prog->globals.server->self;
        old_other = prog->globals.server->other;
+       restorevm_tempstringsbuf_cursize = vm_tempstringsbuf.cursize;
 
        VM_SetTraceGlobals(trace);
 
@@ -684,6 +658,7 @@ void SV_Impact (prvm_edict_t *e1, trace_t *trace)
 
        prog->globals.server->self = old_self;
        prog->globals.server->other = old_other;
+       vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
 }
 
 
@@ -1029,6 +1004,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
        model_t *pushermodel;
        trace_t trace;
        matrix4x4_t pusherfinalmatrix, pusherfinalimatrix;
+       unsigned short moved_edicts[MAX_EDICTS];
 
        if (!pusher->fields.server->velocity[0] && !pusher->fields.server->velocity[1] && !pusher->fields.server->velocity[2] && !pusher->fields.server->avelocity[0] && !pusher->fields.server->avelocity[1] && !pusher->fields.server->avelocity[2])
        {
@@ -1182,7 +1158,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
 
                VectorCopy (check->fields.server->origin, check->priv.server->moved_from);
                VectorCopy (check->fields.server->angles, check->priv.server->moved_fromangles);
-               sv.moved_edicts[num_moved++] = check;
+               moved_edicts[num_moved++] = PRVM_NUM_FOR_EDICT(check);
 
                // try moving the contacted entity
                pusher->fields.server->solid = SOLID_NOT;
@@ -1244,7 +1220,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime)
                                        // move back any entities we already moved
                                        for (i = 0;i < num_moved;i++)
                                        {
-                                               prvm_edict_t *ed = sv.moved_edicts[i];
+                                               prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]);
                                                VectorCopy (ed->priv.server->moved_from, ed->fields.server->origin);
                                                VectorCopy (ed->priv.server->moved_fromangles, ed->fields.server->angles);
                                                SV_LinkEdict (ed, false);