X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=895e6876a9d1ef12179624abdb243757c27881e3;hb=036aa9ae859c21a8a89730b5ebd5f3dc6da0e973;hp=4e17bc92d5907a43bc7f4660aab542b3d8a98df9;hpb=e80a362bdb11a1192b828defe4ecc6953a4b8dbe;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index 4e17bc92..895e6876 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // sv_phys.c #include "quakedef.h" +// used only for VM_GetTempString +#include "prvm_cmds.h" /* @@ -45,7 +47,7 @@ cvar_t sv_gravity = {CVAR_NOTIFY, "sv_gravity","800", "how fast you fall (512 = 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", "1", "whether you can step up while jumping (sv_gameplayfix_stepwhilejumping must also be 1)"}; +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"}; @@ -79,9 +81,13 @@ SV_TestEntityPosition returns true if the entity is in solid currently ============ */ -static int SV_TestEntityPosition (prvm_edict_t *ent, int movemode) +static int SV_TestEntityPosition (prvm_edict_t *ent) { - return SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, movemode, ent).startsolid; + trace_t trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->origin, MOVE_NOMONSTERS, ent); + if (trace.startsupercontents & SUPERCONTENTS_SOLID) + return true; + else + return false; } /* @@ -106,7 +112,7 @@ void SV_CheckAllEnts (void) || check->fields.server->movetype == MOVETYPE_NOCLIP) continue; - if (SV_TestEntityPosition (check, MOVE_NORMAL)) + if (SV_TestEntityPosition (check)) Con_Print("entity in invalid position\n"); } } @@ -187,25 +193,73 @@ SV_Impact Two entities have touched, so run their touch functions ================== */ -void SV_Impact (prvm_edict_t *e1, prvm_edict_t *e2) +void SV_Impact (prvm_edict_t *e1, trace_t *trace) { 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; prog->globals.server->time = sv.time; - if (e1->fields.server->touch && e1->fields.server->solid != SOLID_NOT) + if (!e1->priv.server->free && !e2->priv.server->free && e1->fields.server->touch && e1->fields.server->solid != SOLID_NOT) { prog->globals.server->self = PRVM_EDICT_TO_PROG(e1); prog->globals.server->other = PRVM_EDICT_TO_PROG(e2); + prog->globals.server->trace_allsolid = trace->allsolid; + prog->globals.server->trace_startsolid = trace->startsolid; + prog->globals.server->trace_fraction = trace->fraction; + prog->globals.server->trace_inwater = trace->inwater; + prog->globals.server->trace_inopen = trace->inopen; + VectorCopy (trace->endpos, prog->globals.server->trace_endpos); + VectorCopy (trace->plane.normal, prog->globals.server->trace_plane_normal); + prog->globals.server->trace_plane_dist = trace->plane.dist; + if (trace->ent) + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace->ent); + else + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents))) + val->_float = trace->startsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents))) + val->_float = trace->hitsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags))) + val->_float = trace->hitq3surfaceflags; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename))) + { + if (trace->hittexture) + { + char *s = VM_GetTempString(); + strlcpy(s, trace->hittexture->name, VM_STRINGTEMP_LENGTH); + val->string = PRVM_SetEngineString(s); + } + else + val->string = 0; + } PRVM_ExecuteProgram (e1->fields.server->touch, "QC function self.touch is missing"); } - if (e2->fields.server->touch && e2->fields.server->solid != SOLID_NOT) + if (!e1->priv.server->free && !e2->priv.server->free && e2->fields.server->touch && e2->fields.server->solid != SOLID_NOT) { prog->globals.server->self = PRVM_EDICT_TO_PROG(e2); prog->globals.server->other = PRVM_EDICT_TO_PROG(e1); + prog->globals.server->trace_allsolid = false; + prog->globals.server->trace_startsolid = false; + prog->globals.server->trace_fraction = 1; + prog->globals.server->trace_inwater = false; + prog->globals.server->trace_inopen = true; + VectorCopy (e2->fields.server->origin, prog->globals.server->trace_endpos); + VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1); + prog->globals.server->trace_plane_dist = 0; + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(e1); + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents))) + val->_float = 0; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents))) + val->_float = 0; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags))) + val->_float = 0; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename))) + val->string = 0; PRVM_ExecuteProgram (e2->fields.server->touch, "QC function self.touch is missing"); } @@ -316,15 +370,15 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal) Con_Print("\n"); #endif - /* - if (trace.startsolid) + if (trace.bmodelstartsolid) { - // LordHavoc: note: this code is what makes entities stick in place if embedded in another object (which can be the world) + // LordHavoc: note: this code is what makes entities stick in place + // if embedded in world only (you can walk through other objects if + // stuck) // entity is trapped in another solid VectorClear(ent->fields.server->velocity); return 3; } - */ // break if it moved the entire distance if (trace.fraction == 1) @@ -377,7 +431,7 @@ int SV_FlyMove (prvm_edict_t *ent, float time, float *stepnormal) // run the impact function if (impact) { - SV_Impact(ent, (prvm_edict_t *)trace.ent); + SV_Impact(ent, &trace); // break if removed by the impact function if (ent->priv.server->free) @@ -530,7 +584,7 @@ trace_t SV_PushEntity (prvm_edict_t *ent, vec3_t push) SV_LinkEdict (ent, true); if (trace.ent && (!((int)ent->fields.server->flags & FL_ONGROUND) || ent->fields.server->groundentity != PRVM_EDICT_TO_PROG(trace.ent))) - SV_Impact (ent, (prvm_edict_t *)trace.ent); + SV_Impact (ent, &trace); return trace; } @@ -578,13 +632,13 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) SV_LinkEdict (pusher, false); return; default: - Con_Printf("SV_PushMove: unrecognized solid type %f\n", pusher->fields.server->solid); + Con_Printf("SV_PushMove: entity #%i, unrecognized solid type %f\n", PRVM_NUM_FOR_EDICT(pusher), pusher->fields.server->solid); return; } index = (int) pusher->fields.server->modelindex; if (index < 1 || index >= MAX_MODELS) { - Con_Printf("SV_PushMove: invalid modelindex %f\n", pusher->fields.server->modelindex); + Con_Printf("SV_PushMove: entity #%i has an invalid modelindex %f\n", PRVM_NUM_FOR_EDICT(pusher), pusher->fields.server->modelindex); return; } pushermodel = sv.models[index]; @@ -675,7 +729,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) if (!(((int)check->fields.server->flags & FL_ONGROUND) && PRVM_PROG_TO_EDICT(check->fields.server->groundentity) == pusher)) { // if the entity is not inside the pusher's final position, leave it alone - if (!SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID).startsolid) + if (!SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) continue; // remove the onground flag for non-players if (check->fields.server->movetype != MOVETYPE_WALK) @@ -708,7 +762,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) pusher->fields.server->solid = savesolid; // was SOLID_BSP // if it is still inside the pusher, block - if (SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID).startsolid) + if (SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) { // try moving the contacted entity a tiny bit further to account for precision errors vec3_t move2; @@ -718,7 +772,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles); SV_PushEntity (check, move2); pusher->fields.server->solid = savesolid; - if (SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID).startsolid) + if (SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) { // try moving the contacted entity a tiny bit less to account for precision errors pusher->fields.server->solid = SOLID_NOT; @@ -727,7 +781,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) VectorCopy (check->priv.server->moved_fromangles, check->fields.server->angles); SV_PushEntity (check, move2); pusher->fields.server->solid = savesolid; - if (SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID).startsolid) + if (SV_ClipMoveToEntity(pusher, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, 0, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY).startsolid) { // still inside pusher, so it's really blocked @@ -831,7 +885,7 @@ void SV_CheckStuck (prvm_edict_t *ent) int i, j, z; vec3_t org; - if (!SV_TestEntityPosition(ent, MOVE_NORMAL)) + if (!SV_TestEntityPosition(ent)) { VectorCopy (ent->fields.server->origin, ent->fields.server->oldorigin); return; @@ -839,30 +893,30 @@ void SV_CheckStuck (prvm_edict_t *ent) VectorCopy (ent->fields.server->origin, org); VectorCopy (ent->fields.server->oldorigin, ent->fields.server->origin); - if (!SV_TestEntityPosition(ent, MOVE_NORMAL)) + if (!SV_TestEntityPosition(ent)) { - Con_DPrintf("Unstuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname)); + Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname)); SV_LinkEdict (ent, true); return; } - for (z=0 ; z< 18 ; z++) + for (z=-1 ; z< 18 ; z++) for (i=-1 ; i <= 1 ; i++) for (j=-1 ; j <= 1 ; j++) { ent->fields.server->origin[0] = org[0] + i; ent->fields.server->origin[1] = org[1] + j; ent->fields.server->origin[2] = org[2] + z; - if (!SV_TestEntityPosition(ent, MOVE_NORMAL)) + if (!SV_TestEntityPosition(ent)) { - Con_DPrintf("Unstuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname)); + Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname), (float)i, (float)j, (float)z); SV_LinkEdict (ent, true); return; } } VectorCopy (org, ent->fields.server->origin); - Con_DPrintf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname)); + 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) @@ -871,21 +925,21 @@ static void SV_UnstickEntity (prvm_edict_t *ent) vec3_t org; // if not stuck in a bmodel, just return - if (!SV_TestEntityPosition(ent, MOVE_NOMONSTERS)) + if (!SV_TestEntityPosition(ent)) return; VectorCopy (ent->fields.server->origin, org); - for (z=0 ; z< 18 ; z += 6) + for (z=-1 ; z< 18 ; z += 6) for (i=-1 ; i <= 1 ; i++) for (j=-1 ; j <= 1 ; j++) { ent->fields.server->origin[0] = org[0] + i; ent->fields.server->origin[1] = org[1] + j; ent->fields.server->origin[2] = org[2] + z; - if (!SV_TestEntityPosition(ent, MOVE_NOMONSTERS)) + if (!SV_TestEntityPosition(ent)) { - Con_DPrintf("Unstuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(ent->fields.server->classname)); + 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), (float)i, (float)j, (float)z); SV_LinkEdict (ent, true); return; } @@ -1124,6 +1178,9 @@ void SV_WalkMove (prvm_edict_t *ent) if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7) { + // this has been disabled so that you can't jump when you are stepping + // up while already jumping (also known as the Quake2 stair jump bug) +#if 0 // LordHavoc: disabled this check so you can walk on monsters/players //if (ent->fields.server->solid == SOLID_BSP) { @@ -1131,6 +1188,7 @@ void SV_WalkMove (prvm_edict_t *ent) ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(downtrace.ent); } +#endif } else { @@ -1285,7 +1343,7 @@ void SV_Physics_Toss (prvm_edict_t *ent) trace = SV_PushEntity (ent, move); if (ent->priv.server->free) return; - if (trace.startsolid) + if (trace.bmodelstartsolid) { // try to unstick the entity SV_UnstickEntity(ent); @@ -1639,23 +1697,20 @@ void SV_Physics (void) trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore) { int i; - float gravity, savesolid; + float gravity; vec3_t move, end; - prvm_edict_t tempent, *tent; - entvars_t vars; + vec3_t original_origin; + vec3_t original_velocity; + vec3_t original_angles; + vec3_t original_avelocity; prvm_eval_t *val; trace_t trace; - // copy the vars over - memcpy(&vars, tossent->fields.server, sizeof(entvars_t)); - // set up the temp entity to point to the copied vars - tent = &tempent; - tent->fields.server = &vars; - - savesolid = tossent->fields.server->solid; - tossent->fields.server->solid = SOLID_NOT; + VectorCopy(tossent->fields.server->origin , original_origin ); + VectorCopy(tossent->fields.server->velocity , original_velocity ); + VectorCopy(tossent->fields.server->angles , original_angles ); + VectorCopy(tossent->fields.server->avelocity, original_avelocity); - // this has to fetch the field from the original edict, since our copy is truncated val = PRVM_GETEDICTFIELDVALUE(tossent, eval_gravity); if (val != NULL && val->_float != 0) gravity = val->_float; @@ -1665,19 +1720,23 @@ trace_t SV_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore) for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds { - SV_CheckVelocity (tent); - tent->fields.server->velocity[2] -= gravity; - VectorMA (tent->fields.server->angles, 0.05, tent->fields.server->avelocity, tent->fields.server->angles); - VectorScale (tent->fields.server->velocity, 0.05, move); - VectorAdd (tent->fields.server->origin, move, end); - trace = SV_Move (tent->fields.server->origin, tent->fields.server->mins, tent->fields.server->maxs, end, MOVE_NORMAL, tent); - VectorCopy (trace.endpos, tent->fields.server->origin); - - if (trace.fraction < 1 && trace.ent && trace.ent != ignore) + SV_CheckVelocity (tossent); + tossent->fields.server->velocity[2] -= gravity; + VectorMA (tossent->fields.server->angles, 0.05, tossent->fields.server->avelocity, tossent->fields.server->angles); + VectorScale (tossent->fields.server->velocity, 0.05, move); + VectorAdd (tossent->fields.server->origin, move, end); + trace = SV_Move (tossent->fields.server->origin, tossent->fields.server->mins, tossent->fields.server->maxs, end, MOVE_NORMAL, tossent); + VectorCopy (trace.endpos, tossent->fields.server->origin); + + if (trace.fraction < 1) break; } - tossent->fields.server->solid = savesolid; - trace.fraction = 0; // not relevant + + VectorCopy(original_origin , tossent->fields.server->origin ); + VectorCopy(original_velocity , tossent->fields.server->velocity ); + VectorCopy(original_angles , tossent->fields.server->angles ); + VectorCopy(original_avelocity, tossent->fields.server->avelocity); + return trace; }