297
309
if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_BLUE &&
298
310
item->giTag == PW_BLUEFLAG)
312
//Even in instantgib, we can predict our enemy flag
313
if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_RED &&
314
item->giTag == PW_BLUEFLAG && (!cgs.oneway || cgs.attackingTeam == TEAM_RED))
316
if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_BLUE &&
317
item->giTag == PW_REDFLAG && (!cgs.oneway || cgs.attackingTeam == TEAM_BLUE))
319
if (item->giTag == WP_RAILGUN)
320
canBePicked = qfalse;
321
if (item->giTag == WP_PLASMAGUN)
322
canBePicked = qfalse;
325
//Currently we don't predict anything in Double Domination because it looks like we take a flag
326
if( cgs.gametype == GT_DOUBLE_D ) {
327
if(cgs.redflag == TEAM_NONE)
328
return; //Can never pick if just one flag is NONE (because then the other is too)
329
if(item->giTag == PW_REDFLAG){ //at point A
330
//if(cgs.redflag == cg.predictedPlayerState.persistant[PERS_TEAM]) //already taken
333
if(item->giTag == PW_BLUEFLAG){ //at point B
334
//if(cgs.blueflag == cg.predictedPlayerState.persistant[PERS_TEAM]) //already taken
303
BG_AddPredictableEventToPlayerstate( EV_ITEM_PICKUP, cent->currentState.modelindex , &cg.predictedPlayerState);
305
// remove it from the frame so it won't be drawn
306
cent->currentState.eFlags |= EF_NODRAW;
308
// don't touch it again this prediction
309
cent->miscTime = cg.time;
311
// if its a weapon, give them some predicted ammo so the autoswitch will work
312
if ( item->giType == IT_WEAPON ) {
313
cg.predictedPlayerState.stats[ STAT_WEAPONS ] |= 1 << item->giTag;
314
if ( !cg.predictedPlayerState.ammo[ item->giTag ] ) {
315
cg.predictedPlayerState.ammo[ item->giTag ] = 1;
342
BG_AddPredictableEventToPlayerstate( EV_ITEM_PICKUP, cent->currentState.modelindex , &cg.predictedPlayerState);
344
// remove it from the frame so it won't be drawn
345
cent->currentState.eFlags |= EF_NODRAW;
347
// don't touch it again this prediction
348
cent->miscTime = cg.time;
350
// if its a weapon, give them some predicted ammo so the autoswitch will work
351
if ( item->giType == IT_WEAPON ) {
352
cg.predictedPlayerState.stats[ STAT_WEAPONS ] |= 1 << item->giTag;
353
if ( !cg.predictedPlayerState.ammo[ item->giTag ] ) {
354
cg.predictedPlayerState.ammo[ item->giTag ] = 1;
426
//unlagged - optimized prediction
427
#define ABS(x) ((x) < 0 ? (-(x)) : (x))
429
static int IsUnacceptableError( playerState_t *ps, playerState_t *pps ) {
433
if ( pps->pm_type != ps->pm_type ||
434
pps->pm_flags != ps->pm_flags ||
435
pps->pm_time != ps->pm_time ) {
439
VectorSubtract( pps->origin, ps->origin, delta );
440
if ( VectorLengthSquared( delta ) > 0.1f * 0.1f ) {
441
if ( cg_showmiss.integer ) {
442
CG_Printf("delta: %.2f ", VectorLength(delta) );
447
VectorSubtract( pps->velocity, ps->velocity, delta );
448
if ( VectorLengthSquared( delta ) > 0.1f * 0.1f ) {
449
if ( cg_showmiss.integer ) {
450
CG_Printf("delta: %.2f ", VectorLength(delta) );
455
if ( pps->weaponTime != ps->weaponTime ||
456
pps->gravity != ps->gravity ||
457
pps->speed != ps->speed ||
458
pps->delta_angles[0] != ps->delta_angles[0] ||
459
pps->delta_angles[1] != ps->delta_angles[1] ||
460
pps->delta_angles[2] != ps->delta_angles[2] ||
461
pps->groundEntityNum != ps->groundEntityNum ) {
465
if ( pps->legsTimer != ps->legsTimer ||
466
pps->legsAnim != ps->legsAnim ||
467
pps->torsoTimer != ps->torsoTimer ||
468
pps->torsoAnim != ps->torsoAnim ||
469
pps->movementDir != ps->movementDir ) {
473
VectorSubtract( pps->grapplePoint, ps->grapplePoint, delta );
474
if ( VectorLengthSquared( delta ) > 0.1f * 0.1f ) {
478
if ( pps->eFlags != ps->eFlags ) {
482
if ( pps->eventSequence != ps->eventSequence ) {
486
for ( i = 0; i < MAX_PS_EVENTS; i++ ) {
487
if ( pps->events[i] != ps->events[i] ||
488
pps->eventParms[i] != ps->eventParms[i] ) {
493
if ( pps->externalEvent != ps->externalEvent ||
494
pps->externalEventParm != ps->externalEventParm ||
495
pps->externalEventTime != ps->externalEventTime ) {
499
if ( pps->clientNum != ps->clientNum ||
500
pps->weapon != ps->weapon ||
501
pps->weaponstate != ps->weaponstate ) {
505
if ( ABS(pps->viewangles[0] - ps->viewangles[0]) > 1.0f ||
506
ABS(pps->viewangles[1] - ps->viewangles[1]) > 1.0f ||
507
ABS(pps->viewangles[2] - ps->viewangles[2]) > 1.0f ) {
511
if ( pps->viewheight != ps->viewheight ) {
515
if ( pps->damageEvent != ps->damageEvent ||
516
pps->damageYaw != ps->damageYaw ||
517
pps->damagePitch != ps->damagePitch ||
518
pps->damageCount != ps->damageCount ) {
522
for ( i = 0; i < MAX_STATS; i++ ) {
523
if ( pps->stats[i] != ps->stats[i] ) {
528
for ( i = 0; i < MAX_PERSISTANT; i++ ) {
529
if ( pps->persistant[i] != ps->persistant[i] ) {
534
for ( i = 0; i < MAX_POWERUPS; i++ ) {
535
if ( pps->powerups[i] != ps->powerups[i] ) {
540
for ( i = 0; i < MAX_WEAPONS; i++ ) {
541
if ( pps->ammo[i] != ps->ammo[i] ) {
546
if ( pps->generic1 != ps->generic1 ||
547
pps->loopSound != ps->loopSound ||
548
pps->jumppad_ent != ps->jumppad_ent ) {
554
//unlagged - optimized prediction
389
557
=================
499
671
cg_pmove.pmove_fixed = pmove_fixed.integer;// | cg_pmove_fixed.integer;
500
672
cg_pmove.pmove_msec = pmove_msec.integer;
674
//unlagged - optimized prediction
675
// Like the comments described above, a player's state is entirely
676
// re-predicted from the last valid snapshot every client frame, which
677
// can be really, really, really slow. Every old command has to be
678
// run again. For every client frame that is *not* directly after a
679
// snapshot, this is unnecessary, since we have no new information.
680
// For those, we'll play back the predictions from the last frame and
681
// predict only the newest commands. Essentially, we'll be doing
682
// an incremental predict instead of a full predict.
684
// If we have a new snapshot, we can compare its player state's command
685
// time to the command times in the queue to find a match. If we find
686
// a matching state, and the predicted version has not deviated, we can
687
// use the predicted state as a base - and also do an incremental predict.
689
// With this method, we get incremental predicts on every client frame
690
// except a frame following a new snapshot in which there was a prediction
691
// error. This yeilds anywhere from a 15% to 40% performance increase,
692
// depending on how much of a bottleneck the CPU is.
694
if ( cg_optimizePrediction.integer ) {
695
if ( cg.nextFrameTeleport || cg.thisFrameTeleport ) {
697
cg.lastPredictedCommand = 0;
698
cg.stateTail = cg.stateHead;
699
predictCmd = current - CMD_BACKUP + 1;
701
// cg.physicsTime is the current snapshot's serverTime
702
// if it's the same as the last one
703
else if ( cg.physicsTime == cg.lastServerTime ) {
704
// we have no new information, so do an incremental predict
705
predictCmd = cg.lastPredictedCommand + 1;
708
// we have a new snapshot
711
qboolean error = qtrue;
713
// loop through the saved states queue
714
for ( i = cg.stateHead; i != cg.stateTail; i = (i + 1) % NUM_SAVED_STATES ) {
715
// if we find a predicted state whose commandTime matches the snapshot player state's commandTime
716
if ( cg.savedPmoveStates[i].commandTime == cg.predictedPlayerState.commandTime ) {
717
// make sure the state differences are acceptable
718
int errorcode = IsUnacceptableError( &cg.predictedPlayerState, &cg.savedPmoveStates[i] );
722
if ( cg_showmiss.integer ) {
723
CG_Printf("errorcode %d at %d\n", errorcode, cg.time);
725
// yeah, so do a full predict
729
// this one is almost exact, so we'll copy it in as the starting point
730
*cg_pmove.ps = cg.savedPmoveStates[i];
732
cg.stateHead = (i + 1) % NUM_SAVED_STATES;
734
// set the next command to predict
735
predictCmd = cg.lastPredictedCommand + 1;
737
// a saved state matched, so flag it
743
// if no saved states matched
746
cg.lastPredictedCommand = 0;
747
cg.stateTail = cg.stateHead;
748
predictCmd = current - CMD_BACKUP + 1;
752
// keep track of the server time of the last snapshot so we
753
// know when we're starting from a new one in future calls
754
cg.lastServerTime = cg.physicsTime;
755
stateIndex = cg.stateHead;
757
//unlagged - optimized prediction
504
761
for ( cmdNum = current - CMD_BACKUP + 1 ; cmdNum <= current ; cmdNum++ ) {
581
838
cg_pmove.cmd.serverTime = ((cg_pmove.cmd.serverTime + pmove_msec.integer-1) / pmove_msec.integer) * pmove_msec.integer;
841
//unlagged - optimized prediction
842
if ( cg_optimizePrediction.integer ) {
843
// if we need to predict this command, or we've run out of space in the saved states queue
844
if ( cmdNum >= predictCmd || (stateIndex + 1) % NUM_SAVED_STATES == cg.stateHead ) {
848
numPredicted++; // debug code
850
// record the last predicted command
851
cg.lastPredictedCommand = cmdNum;
853
// if we haven't run out of space in the saved states queue
854
if ( (stateIndex + 1) % NUM_SAVED_STATES != cg.stateHead ) {
855
// save the state for the false case (of cmdNum >= predictCmd)
856
// in later calls to this function
857
cg.savedPmoveStates[stateIndex] = *cg_pmove.ps;
858
stateIndex = (stateIndex + 1) % NUM_SAVED_STATES;
859
cg.stateTail = stateIndex;
863
numPlayedBack++; // debug code
865
if ( cg_showmiss.integer &&
866
cg.savedPmoveStates[stateIndex].commandTime != cg_pmove.cmd.serverTime) {
867
// this should ONLY happen just after changing the value of pmove_fixed
868
CG_Printf( "saved state miss\n" );
871
// play back the command from the saved states
872
*cg_pmove.ps = cg.savedPmoveStates[stateIndex];
874
// go to the next element in the saved states array
875
stateIndex = (stateIndex + 1) % NUM_SAVED_STATES;
882
numPredicted++; // debug code
884
//unlagged - optimized prediction
592
892
//CG_CheckChangedPredictableEvents(&cg.predictedPlayerState);
895
//unlagged - optimized prediction
896
// do a /condump after a few seconds of this
897
//CG_Printf("cg.time: %d, numPredicted: %d, numPlayedBack: %d\n", cg.time, numPredicted, numPlayedBack); // debug code
898
// if everything is working right, numPredicted should be 1 more than 98%
899
// of the time, meaning only ONE predicted move was done in the frame
900
// you should see other values for numPredicted after IsUnacceptableError
901
// returns nonzero, and that's it
902
//unlagged - optimized prediction
595
904
if ( cg_showmiss.integer > 1 ) {
596
905
CG_Printf( "[%i : %i] ", cg_pmove.cmd.serverTime, cg.time );