Based on Neil Toronto's Unlagged project:
http://www.ra.is/unlagged/
G_UnlaggedStore()
Whenever a server frame is run (usually every 50ms) record the position data for
for each active client. Save up to 10 of these markers (or 500ms) for each client.
G_UnlaggedCalc(ent)
Whenever the server processes a command for the client, we look at the serverTime attached to that command and calculate the best guess position for all active clients at that time.
G_UnlaggedOn()
Moves all clients to the positions calculated the last time G_UnlaggedCalc() was run.
G_UnlaggedOff()
Moves all clients back to where they were before G_UnlaggedOn() was run.
For tremulous, most traces that benefit from this happen inside of ClientEvents(), so we wrap that call between G_UnlaggedOn() and G_UnlaggedOff() calls. Dretch bites, Adv. Basilisk gas, and pouncing are handled outside of ClientEvents, so these calls are added to those functions as well.
This behaviour is toggled with the g_unlagged cvar.
NOTE: this patch hasn't got much testing yet, and no review, so it's probably going to see quite a few changes. apply with care.
Created attachment 1141[details]
svn838 unlagged
* calls to unlagged functions are more fine grained (instead of just
wrapping ClientEvents()). This prevents the issue with people getting
stuck on a door, etc. This is from WolfWings.
* Multiple calls to G_UnlaggedOn() before G_UnlaggedOff() is now safe although
it is not used currently. This is from WolfWings.
Created attachment 1143[details]
svn838 unlagged
* Don't bother with lerping between most recent marker and current position.
It won't be accurate and it only appears to happen in LAN games anyway.
Created attachment 1152[details]
svn844 g_unlagged
There is a unique problem that comes up with the melee-type attacks of tremulous and unlagged. Since short range attacks are tied heavily to player movement (unlagged doesn't and shouldn't effect movement), it is very common for an attacker to be put in a position where he either moves over his target's unlagged position or cannot reach it because movement is restricted by their real position.
I've tried a few complex solutions:
1) Use the attacker's unlagged position for the origin of attack.
This fails because it does not take into account the Pmove of the current
command and even if the calculated unlagged position were very accurate it
still feels very clucky since things like impact events are in the wrong
place.
2) Block player movement from overlapping an unlagged position
This would be very hard to do correctly with Pmove() and even if it were to
work it wouldn't solve the problem of not being able to reach the target
if blocked by their real position.
3) Try to detect overlap between attacker and victims unlagged position
Complicated and doesn't prevent the issue of being blocked by a real position
when trying to hit the targets unlagged position.
The best solution I've come up with is to use a hack: allow the attacker to hit either the unlagged or real position of his target. In order to make it a bit more fair the range is reduced by half when searching for the real position. It plays pretty well and considering how deadly unlagged makes the human's hitscan weapons it seems pretty fair.
Created attachment 1165[details]
svn848 g_unlagged
* honour the teleport bit
* instead of doing both traces for melee attacks, collisions are not detected
with the G_UnlaggedCollisions() function and any calculated position that
intersects the attackers position will be invalidated.
* account for the built-in 50ms lag on ucmd->serverTime
* account for the built-in 50ms lag when running ET_MISSILE's
Created attachment 1173[details]
svn852 g_unlagged
* forget all that collision crap, simply taking on 100ms (actually 2
server frames) to the serverTime that the client sends seems to fix this
issue entirely. I did some testing with Enemy Territory which has
the ability to draw bounding box outlines with a server event and it
seems accurate to do this. I'm still not sure why this time is so lagged,
but so far, all testing with this new value has been positive using
various fake latency values (sv_packetdelay/cl_packetdelay).
I think this is ready for inclusion, but I will give it some more testing
on trem.tjw.org first.
Created attachment 1188[details]
svn861 g_unlagged
* finally sorted out the (cgame Pmove) -> (game Pmove) collision problem
that's been plaguing unlagged melee attacks.
* used WolfWing's suggestion of limiting trap_LinkEntity() by only
adjusting other clients who have an unlagged position that is in
range of the pending trace.
Created attachment 1192[details]
svn865 g_unlagged
* stop adding a server frame time to the ucmd->serverTime
* use unlagged position for calculating the damage modifier
This is committed to SVN as revision 866
Created attachment 1141 [details] svn838 unlagged * calls to unlagged functions are more fine grained (instead of just wrapping ClientEvents()). This prevents the issue with people getting stuck on a door, etc. This is from WolfWings. * Multiple calls to G_UnlaggedOn() before G_UnlaggedOff() is now safe although it is not used currently. This is from WolfWings.
Created attachment 1143 [details] svn838 unlagged * Don't bother with lerping between most recent marker and current position. It won't be accurate and it only appears to happen in LAN games anyway.
Created attachment 1152 [details] svn844 g_unlagged There is a unique problem that comes up with the melee-type attacks of tremulous and unlagged. Since short range attacks are tied heavily to player movement (unlagged doesn't and shouldn't effect movement), it is very common for an attacker to be put in a position where he either moves over his target's unlagged position or cannot reach it because movement is restricted by their real position. I've tried a few complex solutions: 1) Use the attacker's unlagged position for the origin of attack. This fails because it does not take into account the Pmove of the current command and even if the calculated unlagged position were very accurate it still feels very clucky since things like impact events are in the wrong place. 2) Block player movement from overlapping an unlagged position This would be very hard to do correctly with Pmove() and even if it were to work it wouldn't solve the problem of not being able to reach the target if blocked by their real position. 3) Try to detect overlap between attacker and victims unlagged position Complicated and doesn't prevent the issue of being blocked by a real position when trying to hit the targets unlagged position. The best solution I've come up with is to use a hack: allow the attacker to hit either the unlagged or real position of his target. In order to make it a bit more fair the range is reduced by half when searching for the real position. It plays pretty well and considering how deadly unlagged makes the human's hitscan weapons it seems pretty fair.
Created attachment 1165 [details] svn848 g_unlagged * honour the teleport bit * instead of doing both traces for melee attacks, collisions are not detected with the G_UnlaggedCollisions() function and any calculated position that intersects the attackers position will be invalidated. * account for the built-in 50ms lag on ucmd->serverTime * account for the built-in 50ms lag when running ET_MISSILE's
Created attachment 1173 [details] svn852 g_unlagged * forget all that collision crap, simply taking on 100ms (actually 2 server frames) to the serverTime that the client sends seems to fix this issue entirely. I did some testing with Enemy Territory which has the ability to draw bounding box outlines with a server event and it seems accurate to do this. I'm still not sure why this time is so lagged, but so far, all testing with this new value has been positive using various fake latency values (sv_packetdelay/cl_packetdelay). I think this is ready for inclusion, but I will give it some more testing on trem.tjw.org first.
Created attachment 1188 [details] svn861 g_unlagged * finally sorted out the (cgame Pmove) -> (game Pmove) collision problem that's been plaguing unlagged melee attacks. * used WolfWing's suggestion of limiting trap_LinkEntity() by only adjusting other clients who have an unlagged position that is in range of the pending trace.
Created attachment 1192 [details] svn865 g_unlagged * stop adding a server frame time to the ucmd->serverTime * use unlagged position for calculating the damage modifier This is committed to SVN as revision 866