X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=895e6876a9d1ef12179624abdb243757c27881e3;hb=036aa9ae859c21a8a89730b5ebd5f3dc6da0e973;hp=e505b28949676e0c6c359d6dc7f5ddeef6369156;hpb=43484d755f33629395d8dba63cf9b3515222d21c;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index e505b289..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,12 +47,15 @@ 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"}; cvar_t sv_playerphysicsqc = {CVAR_NOTIFY, "sv_playerphysicsqc", "1", "enables QuakeC function to override player physics"}; +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)"}; + #define MOVE_EPSILON 0.01 void SV_Physics_Toss (prvm_edict_t *ent); @@ -64,6 +69,25 @@ void SV_Phys_Init (void) Cvar_RegisterVariable(&sv_freezenonclients); Cvar_RegisterVariable(&sv_playerphysicsqc); + + Cvar_RegisterVariable(&sv_sound_watersplash); + Cvar_RegisterVariable(&sv_sound_land); +} + +/* +============ +SV_TestEntityPosition + +returns true if the entity is in solid currently +============ +*/ +static int SV_TestEntityPosition (prvm_edict_t *ent) +{ + 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; } /* @@ -169,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"); } @@ -298,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) @@ -359,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) @@ -512,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; } @@ -560,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]; @@ -657,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) @@ -690,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; @@ -700,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; @@ -709,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 @@ -823,12 +895,12 @@ void SV_CheckStuck (prvm_edict_t *ent) VectorCopy (ent->fields.server->oldorigin, ent->fields.server->origin); 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++) { @@ -837,24 +909,28 @@ void SV_CheckStuck (prvm_edict_t *ent) ent->fields.server->origin[2] = org[2] + z; 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)); } -void SV_UnstickEntity (prvm_edict_t *ent) +static void SV_UnstickEntity (prvm_edict_t *ent) { int i, j, z; vec3_t org; + // if not stuck in a bmodel, just return + 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++) { @@ -863,7 +939,7 @@ void SV_UnstickEntity (prvm_edict_t *ent) ent->fields.server->origin[2] = org[2] + z; 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; } @@ -1102,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) { @@ -1109,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 { @@ -1199,8 +1279,8 @@ void SV_CheckWaterTransition (prvm_edict_t *ent) } // check if the entity crossed into or out of water - if (gamemode != GAME_NEXUIZ && ((ent->fields.server->watertype == CONTENTS_WATER || ent->fields.server->watertype == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME))) - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + if (sv_sound_watersplash.string && ((ent->fields.server->watertype == CONTENTS_WATER || ent->fields.server->watertype == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME))) + SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1); if (cont <= CONTENTS_WATER) { @@ -1263,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); @@ -1381,8 +1461,8 @@ void SV_Physics_Step (prvm_edict_t *ent) SV_LinkEdict(ent, true); // just hit ground - if (hitsound && (int)ent->fields.server->flags & FL_ONGROUND && gamemode != GAME_NEXUIZ) - SV_StartSound(ent, 0, "demon/dland2.wav", 255, 1); + if (hitsound && (int)ent->fields.server->flags & FL_ONGROUND && sv_sound_land.string) + SV_StartSound(ent, 0, sv_sound_land.string, 255, 1); } } @@ -1617,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; @@ -1643,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; }