~ubuntu-branches/ubuntu/jaunty/openarena/jaunty

« back to all changes in this revision

Viewing changes to code/cgame/cg_predict.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert, Bruno "Fuddl" Kleinert
  • Date: 2008-04-24 14:33:54 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080424143354-0cuxsalv98ajw2js
Tags: 0.7.6-1
[ Bruno "Fuddl" Kleinert ]
* New upstream release
* Freshen 10_fix_build_and_binary_on_alpha.dpatch to apply to latest
  upstream sources
* Remove 10-fix_menudef.h_includes.dpatch which pulled in a missing header
  file. The header is now included in the upstream tarball.
* Remove debian/watch, because upstream places its new releases too often to
  different download locations
* Updated debian/copyright to reflect the download location
* Expand copyright years in debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
260
260
*/
261
261
static void CG_TouchItem( centity_t *cent ) {
262
262
        gitem_t         *item;
 
263
        //For instantgib
 
264
        qboolean        canBePicked;
 
265
 
 
266
        if(cgs.gametype == GT_ELIMINATION || cgs.gametype == GT_LMS)
 
267
                return; //No weapon pickup in elimination
 
268
 
 
269
        //normally we can
 
270
        canBePicked = qtrue;
 
271
 
 
272
        //But in instantgib, rocket arena, and CTF_ELIMINATION we normally can't:
 
273
        if(cgs.instantgib || cgs.rockets || cgs.gametype == GT_CTF_ELIMINATION)
 
274
                canBePicked = qfalse;
263
275
 
264
276
        if ( !cg_predictItems.integer ) {
265
277
                return;
287
299
                        return;
288
300
                }
289
301
        }
290
 
        if( cgs.gametype == GT_CTF || cgs.gametype == GT_HARVESTER ) {
 
302
        if( cgs.gametype == GT_CTF || cgs.gametype == GT_CTF_ELIMINATION || cgs.gametype == GT_HARVESTER ) {
291
303
#else
292
 
        if( cgs.gametype == GT_CTF ) {
 
304
        if( cgs.gametype == GT_CTF || cgs.gametype == GT_CTF_ELIMINATION ) {
293
305
#endif
294
306
                if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_RED &&
295
307
                        item->giTag == PW_REDFLAG)
297
309
                if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_BLUE &&
298
310
                        item->giTag == PW_BLUEFLAG)
299
311
                        return;
 
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))
 
315
                        canBePicked = qtrue;
 
316
                if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_BLUE &&
 
317
                        item->giTag == PW_REDFLAG && (!cgs.oneway || cgs.attackingTeam == TEAM_BLUE))
 
318
                        canBePicked = qtrue;
 
319
                if (item->giTag == WP_RAILGUN)
 
320
                        canBePicked = qfalse;
 
321
                if (item->giTag == WP_PLASMAGUN)
 
322
                        canBePicked = qfalse;
 
323
        }
 
324
 
 
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
 
331
                                return;
 
332
                }       
 
333
                if(item->giTag == PW_BLUEFLAG){ //at point B
 
334
                        //if(cgs.blueflag == cg.predictedPlayerState.persistant[PERS_TEAM]) //already taken
 
335
                                return;
 
336
                }       
300
337
        }
301
338
 
302
339
        // grab it
303
 
        BG_AddPredictableEventToPlayerstate( EV_ITEM_PICKUP, cent->currentState.modelindex , &cg.predictedPlayerState);
304
 
 
305
 
        // remove it from the frame so it won't be drawn
306
 
        cent->currentState.eFlags |= EF_NODRAW;
307
 
 
308
 
        // don't touch it again this prediction
309
 
        cent->miscTime = cg.time;
310
 
 
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;
 
340
        if(canBePicked)
 
341
        {
 
342
                BG_AddPredictableEventToPlayerstate( EV_ITEM_PICKUP, cent->currentState.modelindex , &cg.predictedPlayerState);
 
343
 
 
344
                // remove it from the frame so it won't be drawn
 
345
                cent->currentState.eFlags |= EF_NODRAW;
 
346
 
 
347
                // don't touch it again this prediction
 
348
                cent->miscTime = cg.time;
 
349
 
 
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;
 
355
                        }
316
356
                }
317
357
        }
318
358
}
383
423
        }
384
424
}
385
425
 
386
 
 
 
426
//unlagged - optimized prediction
 
427
#define ABS(x) ((x) < 0 ? (-(x)) : (x))
 
428
 
 
429
static int IsUnacceptableError( playerState_t *ps, playerState_t *pps ) {
 
430
        vec3_t delta;
 
431
        int i;
 
432
 
 
433
        if ( pps->pm_type != ps->pm_type ||
 
434
                        pps->pm_flags != ps->pm_flags ||
 
435
                        pps->pm_time != ps->pm_time ) {
 
436
                return 1;
 
437
        }
 
438
 
 
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) );
 
443
                }
 
444
                return 2;
 
445
        }
 
446
 
 
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) );
 
451
                }
 
452
                return 3;
 
453
        }
 
454
 
 
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 ) {
 
462
                return 4;
 
463
        }
 
464
 
 
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 ) {
 
470
                return 5;
 
471
        }
 
472
 
 
473
        VectorSubtract( pps->grapplePoint, ps->grapplePoint, delta );
 
474
        if ( VectorLengthSquared( delta ) > 0.1f * 0.1f ) {
 
475
                return 6;
 
476
        }
 
477
 
 
478
        if ( pps->eFlags != ps->eFlags ) {
 
479
                return 7;
 
480
        }
 
481
 
 
482
        if ( pps->eventSequence != ps->eventSequence ) {
 
483
                return 8;
 
484
        }
 
485
 
 
486
        for ( i = 0; i < MAX_PS_EVENTS; i++ ) {
 
487
                if ( pps->events[i] != ps->events[i] ||
 
488
                                pps->eventParms[i] != ps->eventParms[i] ) {
 
489
                        return 9;
 
490
                }
 
491
        }
 
492
 
 
493
        if ( pps->externalEvent != ps->externalEvent ||
 
494
                        pps->externalEventParm != ps->externalEventParm ||
 
495
                        pps->externalEventTime != ps->externalEventTime ) {
 
496
                return 10;
 
497
        }
 
498
 
 
499
        if ( pps->clientNum != ps->clientNum ||
 
500
                        pps->weapon != ps->weapon ||
 
501
                        pps->weaponstate != ps->weaponstate ) {
 
502
                return 11;
 
503
        }
 
504
 
 
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 ) {
 
508
                return 12;
 
509
        }
 
510
 
 
511
        if ( pps->viewheight != ps->viewheight ) {
 
512
                return 13;
 
513
        }
 
514
 
 
515
        if ( pps->damageEvent != ps->damageEvent ||
 
516
                        pps->damageYaw != ps->damageYaw ||
 
517
                        pps->damagePitch != ps->damagePitch ||
 
518
                        pps->damageCount != ps->damageCount ) {
 
519
                return 14;
 
520
        }
 
521
 
 
522
        for ( i = 0; i < MAX_STATS; i++ ) {
 
523
                if ( pps->stats[i] != ps->stats[i] ) {
 
524
                        return 15;
 
525
                }
 
526
        }
 
527
 
 
528
        for ( i = 0; i < MAX_PERSISTANT; i++ ) {
 
529
                if ( pps->persistant[i] != ps->persistant[i] ) {
 
530
                        return 16;
 
531
                }
 
532
        }
 
533
 
 
534
        for ( i = 0; i < MAX_POWERUPS; i++ ) {
 
535
                if ( pps->powerups[i] != ps->powerups[i] ) {
 
536
                        return 17;
 
537
                }
 
538
        }
 
539
 
 
540
        for ( i = 0; i < MAX_WEAPONS; i++ ) {
 
541
                if ( pps->ammo[i] != ps->ammo[i] ) {
 
542
                        return 18;
 
543
                }
 
544
        }
 
545
 
 
546
        if ( pps->generic1 != ps->generic1 ||
 
547
                        pps->loopSound != ps->loopSound ||
 
548
                        pps->jumppad_ent != ps->jumppad_ent ) {
 
549
                return 19;
 
550
        }
 
551
 
 
552
        return 0;
 
553
}
 
554
//unlagged - optimized prediction
387
555
 
388
556
/*
389
557
=================
417
585
        qboolean        moved;
418
586
        usercmd_t       oldestCmd;
419
587
        usercmd_t       latestCmd;
 
588
//unlagged - optimized prediction
 
589
        int stateIndex = 0, predictCmd = 0; //Sago: added initializing
 
590
        int numPredicted = 0, numPlayedBack = 0; // debug code
 
591
//unlagged - optimized prediction
420
592
 
421
593
        cg.hyperspace = qfalse; // will be set if touching a trigger_teleport
422
594
 
499
671
        cg_pmove.pmove_fixed = pmove_fixed.integer;// | cg_pmove_fixed.integer;
500
672
        cg_pmove.pmove_msec = pmove_msec.integer;
501
673
 
 
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.
 
683
        //
 
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.
 
688
        //
 
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.
 
693
 
 
694
        if ( cg_optimizePrediction.integer ) {
 
695
                if ( cg.nextFrameTeleport || cg.thisFrameTeleport ) {
 
696
                        // do a full predict
 
697
                        cg.lastPredictedCommand = 0;
 
698
                        cg.stateTail = cg.stateHead;
 
699
                        predictCmd = current - CMD_BACKUP + 1;
 
700
                }
 
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;
 
706
                }
 
707
                else {
 
708
                        // we have a new snapshot
 
709
 
 
710
                        int i;
 
711
                        qboolean error = qtrue;
 
712
 
 
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] );
 
719
 
 
720
                                        // too much change?
 
721
                                        if ( errorcode ) {
 
722
                                                if ( cg_showmiss.integer ) {
 
723
                                                        CG_Printf("errorcode %d at %d\n", errorcode, cg.time);
 
724
                                                }
 
725
                                                // yeah, so do a full predict
 
726
                                                break;
 
727
                                        }
 
728
 
 
729
                                        // this one is almost exact, so we'll copy it in as the starting point
 
730
                                        *cg_pmove.ps = cg.savedPmoveStates[i];
 
731
                                        // advance the head
 
732
                                        cg.stateHead = (i + 1) % NUM_SAVED_STATES;
 
733
 
 
734
                                        // set the next command to predict
 
735
                                        predictCmd = cg.lastPredictedCommand + 1;
 
736
 
 
737
                                        // a saved state matched, so flag it
 
738
                                        error = qfalse;
 
739
                                        break;
 
740
                                }
 
741
                        }
 
742
 
 
743
                        // if no saved states matched
 
744
                        if ( error ) {
 
745
                                // do a full predict
 
746
                                cg.lastPredictedCommand = 0;
 
747
                                cg.stateTail = cg.stateHead;
 
748
                                predictCmd = current - CMD_BACKUP + 1;
 
749
                        }
 
750
                }
 
751
 
 
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;
 
756
        }
 
757
//unlagged - optimized prediction
 
758
 
502
759
        // run cmds
503
760
        moved = qfalse;
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;
582
839
                }
583
840
 
584
 
                Pmove (&cg_pmove);
 
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 ) {
 
845
                                // run the Pmove
 
846
                                Pmove (&cg_pmove);
 
847
 
 
848
                                numPredicted++; // debug code
 
849
 
 
850
                                // record the last predicted command
 
851
                                cg.lastPredictedCommand = cmdNum;
 
852
 
 
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;
 
860
                                }
 
861
                        }
 
862
                        else {
 
863
                                numPlayedBack++; // debug code
 
864
 
 
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" );
 
869
                                }
 
870
 
 
871
                                // play back the command from the saved states
 
872
                                *cg_pmove.ps = cg.savedPmoveStates[stateIndex];
 
873
 
 
874
                                // go to the next element in the saved states array
 
875
                                stateIndex = (stateIndex + 1) % NUM_SAVED_STATES;
 
876
                        }
 
877
                }
 
878
                else {
 
879
                        // run the Pmove
 
880
                        Pmove (&cg_pmove);
 
881
 
 
882
                        numPredicted++; // debug code
 
883
                }
 
884
//unlagged - optimized prediction
585
885
 
586
886
                moved = qtrue;
587
887
 
592
892
                //CG_CheckChangedPredictableEvents(&cg.predictedPlayerState);
593
893
        }
594
894
 
 
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
 
903
 
595
904
        if ( cg_showmiss.integer > 1 ) {
596
905
                CG_Printf( "[%i : %i] ", cg_pmove.cmd.serverTime, cg.time );
597
906
        }