diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index e181e356..5d72b5b4 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -219,17 +219,43 @@ void movelocalplayer() } // use physics to extrapolate player position +VARP(smoothmove, 0, 75, 100); +VARP(smoothdist, 0, 8, 16); + void moveotherplayers() { loopv(players) if(players[i] && players[i]->type==ENT_PLAYER) { - const int lagtime = lastmillis-players[i]->lastupdate; - if(lagtime>1000 && players[i]->state==CS_ALIVE) + playerent *d = players[i]; + const int lagtime = lastmillis-d->lastupdate; + if(!lagtime || intermission) continue; + else if(lagtime>1000 && d->state==CS_ALIVE) { - players[i]->state = CS_LAGGED; + d->state = CS_LAGGED; continue; } - if(lagtime && (players[i]->state==CS_ALIVE || (players[i]->state==CS_DEAD && lastmillis-players[i]->lastpain<2000)) && !intermission) moveplayer(players[i], 2, false); + if(d->state==CS_ALIVE) + { + if(smoothmove && d->smoothmillis>0) + { + d->o = d->newpos; + d->yaw = d->newyaw; + d->pitch = d->newpitch; + moveplayer(d, 2, false); + d->newpos = d->o; + float k = 1.0f - float(lastmillis - d->smoothmillis)/smoothmove; + if(k>0) + { + d->o.add(vec(d->deltapos).mul(k)); + d->yaw += d->deltayaw*k; + if(d->yaw<0) d->yaw += 360; + else if(d->yaw>=360) d->yaw -= 360; + d->pitch += d->deltapitch*k; + } + } + else moveplayer(d, 2, false); + } + else if(d->state==CS_DEAD && lastmillis-d->lastpain<2000) moveplayer(d, 2, false); } } diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index ead6303d..a558766c 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -80,6 +80,8 @@ void parsepositions(ucharbuf &p) int f = getuint(p), seqcolor = (f>>6)&1; playerent *d = getclient(cn); if(!d || seqcolor!=(d->lifesequence&1)) continue; + vec oldpos(d->o); + float oldyaw = d->yaw, oldpitch = d->pitch; d->o = o; d->yaw = yaw; d->pitch = pitch; @@ -96,6 +98,23 @@ void parsepositions(ucharbuf &p) updatecrouch(d, f&1); updatepos(d); updatelagtime(d); + extern int smoothmove, smoothdist; + if(smoothmove && d->smoothmillis>=0 && oldpos.dist(d->o) < smoothdist) + { + d->newpos = d->o; + d->newyaw = d->yaw; + d->newpitch = d->pitch; + d->o = oldpos; + d->yaw = oldyaw; + d->pitch = oldpitch; + (d->deltapos = oldpos).sub(d->newpos); + d->deltayaw = oldyaw - d->newyaw; + if(d->deltayaw > 180) d->deltayaw -= 360; + else if(d->deltayaw < -180) d->deltayaw += 360; + d->deltapitch = oldpitch - d->newpitch; + d->smoothmillis = lastmillis; + } + else d->smoothmillis = 0; if(d->state==CS_LAGGED || d->state==CS_SPAWNING) d->state = CS_ALIVE; break; } diff --git a/source/src/entity.h b/source/src/entity.h index 99819d13..6469f8f2 100644 --- a/source/src/entity.h +++ b/source/src/entity.h @@ -344,9 +344,14 @@ struct playerent : dynent, playerstate poshist history; // Previous stored locations of this player + vec deltapos, newpos; + float deltayaw, deltapitch, newyaw, newpitch; + int smoothmillis; + playerent() : clientnum(-1), plag(0), ping(0), lifesequence(0), frags(0), flagscore(0), lastpain(0), clientrole(CR_DEFAULT), skin(0), nextskin(0), spectating(SM_NONE), followplayercn(0), - weaponsel(NULL), nextweaponsel(NULL), primweap(NULL), nextprimweap(NULL), lastattackweapon(NULL) + weaponsel(NULL), nextweaponsel(NULL), primweap(NULL), nextprimweap(NULL), lastattackweapon(NULL), + smoothmillis(-1) { type = ENT_PLAYER; name[0] = team[0] = 0;