diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 4caf9953..52cea488 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -3390,6 +3390,8 @@ void CL_ParsePlayerinfo (void) state->pm_type = PM_NONE; else if (pm_code == PMC_FREEZE) state->pm_type = PM_FREEZE; + else if (pm_code == PMC_WALLWALK) + state->pm_type = PM_WALLWALK; else { // future extension? goto guess_pm_type; diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index df8a7ea5..a4d8d8f5 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -606,11 +606,14 @@ void CL_ClampPitch (int pnum) vec3_t view[4]; vec3_t impact, norm; float mat[16], mat2[16]; + vec3_t cross; + float roll; + float dot; static float oldtime; float timestep = realtime - oldtime; oldtime = realtime; - if (1) + if (cl.pmovetype[pnum] == PM_WALLWALK) { AngleVectors(cl.viewangles[pnum], view[0], view[1], view[2]); Matrix4x4_RM_FromVectors(mat, view[0], view[1], view[2], vec3_origin); @@ -628,19 +631,13 @@ void CL_ClampPitch (int pnum) norm[2] = 1; } - { - vec3_t cross; - float roll; - float dot; - /*keep the roll relative to the 'ground'*/ - CrossProduct(norm, view[2], cross); - dot = DotProduct(view[0], cross); - roll = timestep * 720/M_PI * -(dot); - Con_Printf("%f %f\n", dot, roll); - Matrix4_Multiply(Matrix4x4_CM_NewRotation(roll, 1, 0, 0), mat, mat2); - Matrix3x4_RM_ToVectors(mat2, view[0], view[1], view[2], view[3]); - } + /*keep the roll relative to the 'ground'*/ + CrossProduct(norm, view[2], cross); + dot = DotProduct(view[0], cross); + roll = timestep * 360 * -(dot); + Matrix4_Multiply(Matrix4x4_CM_NewRotation(roll, 1, 0, 0), mat, mat2); + Matrix3x4_RM_ToVectors(mat2, view[0], view[1], view[2], view[3]); VectorAngles(view[0], view[2], cl.viewangles[pnum]); cl.viewangles[pnum][PITCH]=360 - cl.viewangles[pnum][PITCH]; VectorClear(cl.viewanglechange[pnum]); @@ -689,10 +686,15 @@ void CL_ClampPitch (int pnum) cl.viewangles[pnum][PITCH] = cl.minpitch; } - if (cl.viewangles[pnum][ROLL] > 50) - cl.viewangles[pnum][ROLL] = 50; - if (cl.viewangles[pnum][ROLL] < -50) - cl.viewangles[pnum][ROLL] = -50; +// if (cl.viewangles[pnum][ROLL] > 50) +// cl.viewangles[pnum][ROLL] = 50; +// if (cl.viewangles[pnum][ROLL] < -50) +// cl.viewangles[pnum][ROLL] = -50; + roll = timestep*cl.viewangles[pnum][ROLL]*30; + if ((cl.viewangles[pnum][ROLL]-roll < 0) != (cl.viewangles[pnum][ROLL]<0)) + cl.viewangles[pnum][ROLL] = 0; + else + cl.viewangles[pnum][ROLL] -= timestep*cl.viewangles[pnum][ROLL]*3; } /* diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index e027f478..c4a4108f 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -531,7 +531,7 @@ void CL_SendConnectPacket (int mtu, Q_strncatz(data, va("0x%x 0x%x\n", PROTOCOL_VERSION_FTE2, fteprotextsupported2), sizeof(data)); #endif - if (mtu >= 0) + if (mtu > 0) { if (adr.type == NA_LOOPBACK) mtu = 8192; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index d31ba43e..ec9c7d96 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -831,8 +831,12 @@ qboolean CL_CheckQ2BspWals(char *file) break; if (i == j) - if (!CL_CheckOrEnqueDownloadFile(tinf[i].texture, NULL, 0)) - gotone = true; + { + if (!CL_CheckDLFile(va("textures/%s.wal", tinf[i].texture))) + if (!CL_CheckDLFile(va("textures/%s.tga", tinf[i].texture))) + if (!CL_CheckOrEnqueDownloadFile(tinf[i].texture, NULL, 0)) + gotone = true; + } } return gotone; } diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 9198e57a..71c2daf0 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -767,21 +767,32 @@ void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int s { /*update the prediction info*/ int pmtype, i; - if (state->u.q1.pmovetype == MOVETYPE_NOCLIP) + switch(state->u.q1.pmovetype) { + case MOVETYPE_NOCLIP: if (cls.z_ext & Z_EXT_PM_TYPE_NEW) pmtype = PM_SPECTATOR; else pmtype = PM_OLD_SPECTATOR; - } - else if (state->u.q1.pmovetype == MOVETYPE_FLY) + break; + + case MOVETYPE_FLY: pmtype = PM_FLY; - else if (state->u.q1.pmovetype == MOVETYPE_NONE) + break; + case MOVETYPE_NONE: pmtype = PM_NONE; - else if (state->u.q1.pmovetype == MOVETYPE_BOUNCE || state->u.q1.pmovetype == MOVETYPE_TOSS) + break; + case MOVETYPE_BOUNCE: + case MOVETYPE_TOSS: pmtype = PM_DEAD; - else + break; + case MOVETYPE_WALLWALK: + pmtype = PM_WALLWALK; + break; + default: pmtype = PM_NORMAL; + break; + } plstate->pm_type = pmtype; VectorCopy(state->origin, plstate->origin); @@ -1015,6 +1026,7 @@ fixedorg: org = lrp; vel = lrpv; + cl.pmovetype[pnum] = PM_NONE; goto fixedorg; } else @@ -1054,6 +1066,7 @@ fixedorg: , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); } cl.onground[pnum] = pmove.onground; + cl.pmovetype[pnum] = to->playerstate[cl.playernum[pnum]].pm_type; stepheight = to->playerstate[cl.playernum[pnum]].origin[2] - from->playerstate[cl.playernum[pnum]].origin[2]; if (cl.nolocalplayer[pnum]) diff --git a/engine/client/client.h b/engine/client/client.h index cdf34c5d..025eb73a 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -658,6 +658,7 @@ typedef struct qboolean oldfixangle[MAX_SPLITS]; //received a fixangle - so disable prediction till the next packet. vec3_t fixangles[MAX_SPLITS]; //received a fixangle - so disable prediction till the next packet. vec3_t oldfixangles[MAX_SPLITS]; //received a fixangle - so disable prediction till the next packet. + int pmovetype[MAX_SPLITS]; int teamplay; int deathmatch; diff --git a/engine/common/pmove.c b/engine/common/pmove.c index 4254aaf3..a654615f 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -1090,9 +1090,6 @@ void PM_PlayerMove (float gamespeed) frametime = pmove.cmd.msec * 0.001*gamespeed; pmove.numtouch = 0; - //TEMP - pmove.pm_type = PM_WALLWALK; - if (pmove.pm_type == PM_NONE || pmove.pm_type == PM_FREEZE) { PM_CategorizePosition (); return; diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 0d10abaf..e91d24e5 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -358,6 +358,7 @@ pbool ED_CanFree (edict_t *ed); #define MOVETYPE_FOLLOW 12 // track movement of aiment #define MOVETYPE_H2PUSHPULL 13 // pushable/pullable object #define MOVETYPE_H2SWIM 14 // should keep the object in water +#define MOVETYPE_WALLWALK 31 // walks up walls and along ceilings #define MOVETYPE_PHYSICS 32 // edict->solid values diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 01c442e9..d5439190 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -424,7 +424,7 @@ enum clcq2_ops_e #define PMC_FLY 4 // fly, bump into walls #define PMC_NONE 5 // can't move (client had better lerp the origin...) #define PMC_FREEZE 6 // TODO: lerp movement and viewangles -#define PMC_EXTRA3 7 // future extension +#define PMC_WALLWALK 7 // future extension //any more will require a different protocol message. diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 139e50fd..abe37daa 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1761,9 +1761,13 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) case PM_NONE: pm_code = PMC_NONE; break; + case PM_WALLWALK: + pm_code = PMC_WALLWALK; + break; default: - Sys_Error("SV_WritePlayersToClient: unexpected pm_type"); - pm_code=0; +// Sys_Error("SV_WritePlayersToClient: unexpected pm_type"); + pm_code=PMC_NORMAL; + break; } } else diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index bb2cb08e..1255b89c 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1874,7 +1874,7 @@ client_t *SVC_DirectConnect(void) case PROTOCOL_VERSION_FRAGMENT: mtu = Q_atoi(Cmd_Argv(1)) & ~7; if (mtu < 64) - mtu = 64; + mtu = 0; Con_DPrintf("Client supports fragmentation. mtu %i.\n", mtu); break; case PROTOCOL_INFO_GUID: @@ -2323,7 +2323,7 @@ client_t *SVC_DirectConnect(void) newcl->netchan.compress = true; else newcl->netchan.compress = false; - if (mtu >= 0) + if (mtu >= 64) newcl->netchan.fragmentsize = mtu; newcl->protocol = protocol; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index b48b8d2a..9aee3232 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1743,6 +1743,7 @@ void SV_Begin_Core(client_t *split) split->edict->v->maxs[0] = 16; split->edict->v->maxs[1] = 16; split->edict->v->maxs[2] = 32; + split->edict->v->movetype = MOVETYPE_NOCLIP; } } @@ -5453,23 +5454,30 @@ int SV_PMTypeForClient (client_t *cl) return PM_NORMAL; } - if (cl->edict->v->movetype == MOVETYPE_NOCLIP) + switch((int)cl->edict->v->movetype) { + case MOVETYPE_NOCLIP: + /*older/vanilla clients have a b0rked spectator mode that we don't want to break*/ if (cl->zquake_extensions & Z_EXT_PM_TYPE_NEW) return PM_SPECTATOR; return PM_OLD_SPECTATOR; - } - if (cl->edict->v->movetype == MOVETYPE_FLY) + case MOVETYPE_WALLWALK: + return PM_WALLWALK; + + case MOVETYPE_FLY: return PM_FLY; - if (cl->edict->v->movetype == MOVETYPE_NONE) + case MOVETYPE_NONE: return PM_NONE; - if (cl->edict->v->health <= 0) - return PM_DEAD; + case MOVETYPE_WALK: + default: + if (cl->edict->v->health <= 0) + return PM_DEAD; - return PM_NORMAL; + return PM_NORMAL; + } } @@ -5839,6 +5847,28 @@ if (sv_player->v->health > 0 && before && !after ) VectorCopy (pmove.origin, sv_player->v->origin); VectorCopy (pmove.angles, sv_player->v->v_angle); + if (pmove.pm_type == PM_WALLWALK) + { + if (!sv_player->v->fixangle) + { + //FIXME: bound to pmove.gravitydir + vec3_t view[3]; + vec3_t surf[3]; + vec3_t fwd, up; + AngleVectors(sv_player->v->v_angle, view[0], view[1], view[2]); + /*calculate the surface axis with up from the pmove code and right/forwards relative to the player's directions*/ + VectorNegate(pmove.gravitydir, surf[2]); + CrossProduct(view[0], surf[2], surf[1]); + VectorNormalize(surf[1]); + CrossProduct(surf[2], surf[1], surf[0]); + /*interpolate the forward direction to be 1/3rd the player, and 2/3rds the surface forward*/ + VectorInterpolate(surf[0], 0.333, view[0], fwd); + CrossProduct(surf[1], fwd, up); + /*we have our player's new axis*/ + VectorAngles(fwd, up, sv_player->v->angles); + } + } + player_mins[0] = -16; player_mins[1] = -16; player_mins[2] = -24; @@ -6223,6 +6253,8 @@ haveannothergo: if (c == -1) break; +// Con_Printf("(%s) %i: %i\n", cl->name, msg_readcount, c); + switch (c) { default: diff --git a/engine/server/world.c b/engine/server/world.c index 9e84bb4e..0ace69f8 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -1016,11 +1016,12 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v { trace_t trace; model_t *model; + int mdlidx = ent->v->modelindex; // get the clipping hull - if (ent->v->solid == SOLID_BSP) + if (ent->v->solid == SOLID_BSP && mdlidx) { - model = w->Get_CModel(w, ent->v->modelindex); + model = w->Get_CModel(w, mdlidx); if (!model || (model->type != mod_brush && model->type != mod_heightmap)) Host_Error("SOLID_BSP with non bsp model (classname: %s)", PR_GetString(w->progs, ent->v->classname)); } @@ -1046,12 +1047,10 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v } // if using hitmodel, we know it hit the bounding box, so try a proper trace now. - if (hitmodel && trace.fraction != 1 && ent->v->solid != SOLID_BSP && ent->v->modelindex != 0) + if (hitmodel && trace.fraction != 1 && ent->v->solid != SOLID_BSP && mdlidx != 0) { //okay, we hit the bbox - - model_t *model; - model = w->Get_CModel(w, ent->v->modelindex); + model = w->Get_CModel(w, mdlidx); if (model && model->funcs.NativeTrace) {