diff -r openArenaEliminationB15/code/cgame/cg_ents.c openArenaEliminationB16/code/cgame/cg_ents.c 739,746c739,757 < // if this player does not want to see extrapolated players < if ( !cg_smoothClients.integer ) { < // make sure the clients use TR_INTERPOLATE < if ( cent->currentState.number < MAX_CLIENTS ) { < cent->currentState.pos.trType = TR_INTERPOLATE; < cent->nextState.pos.trType = TR_INTERPOLATE; < } < } --- > //unlagged - projectile nudge > // this will be set to how far forward projectiles will be extrapolated > int timeshift = 0; > //unlagged - projectile nudge > > //unlagged - smooth clients #2 > // this is done server-side now - cg_smoothClients is undefined > // players will always be TR_INTERPOLATE > /* > // if this player does not want to see extrapolated players > if ( !cg_smoothClients.integer ) { > // make sure the clients use TR_INTERPOLATE > if ( cent->currentState.number < MAX_CLIENTS ) { > cent->currentState.pos.trType = TR_INTERPOLATE; > cent->nextState.pos.trType = TR_INTERPOLATE; > } > } > */ > //unlagged - smooth clients #2 761,763c772,823 < // just use the current frame and evaluate as best we can < BG_EvaluateTrajectory( ¢->currentState.pos, cg.time, cent->lerpOrigin ); < BG_EvaluateTrajectory( ¢->currentState.apos, cg.time, cent->lerpAngles ); --- > //unlagged - timenudge extrapolation > // interpolating failed (probably no nextSnap), so extrapolate > // this can also happen if the teleport bit is flipped, but that > // won't be noticeable > if ( cent->currentState.number < MAX_CLIENTS && > cent->currentState.clientNum != cg.predictedPlayerState.clientNum ) { > cent->currentState.pos.trType = TR_LINEAR_STOP; > cent->currentState.pos.trTime = cg.snap->serverTime; > cent->currentState.pos.trDuration = 1000 / sv_fps.integer; > } > //unlagged - timenudge extrapolation > > //unlagged - projectile nudge > // if it's a missile but not a grappling hook > if ( cent->currentState.eType == ET_MISSILE && cent->currentState.weapon != WP_GRAPPLING_HOOK ) { > // if it's one of ours > if ( cent->currentState.otherEntityNum == cg.clientNum ) { > // extrapolate one server frame's worth - this will correct for tiny > // visual inconsistencies introduced by backward-reconciling all players > // one server frame before running projectiles > timeshift = 1000 / sv_fps.integer; > } > // if it's not, and it's not a grenade launcher > else if ( cent->currentState.weapon != WP_GRENADE_LAUNCHER ) { > // extrapolate based on cg_projectileNudge > timeshift = cg_projectileNudge.integer + 1000 / sv_fps.integer; > } > } > > // just use the current frame and evaluate as best we can > // BG_EvaluateTrajectory( ¢->currentState.pos, cg.time, cent->lerpOrigin ); > // BG_EvaluateTrajectory( ¢->currentState.apos, cg.time, cent->lerpAngles ); > BG_EvaluateTrajectory( ¢->currentState.pos, cg.time + timeshift, cent->lerpOrigin ); > BG_EvaluateTrajectory( ¢->currentState.apos, cg.time + timeshift, cent->lerpAngles ); > > // if there's a time shift > if ( timeshift != 0 ) { > trace_t tr; > vec3_t lastOrigin; > > BG_EvaluateTrajectory( ¢->currentState.pos, cg.time, lastOrigin ); > > CG_Trace( &tr, lastOrigin, vec3_origin, vec3_origin, cent->lerpOrigin, cent->currentState.number, MASK_SHOT ); > > // don't let the projectile go through the floor > if ( tr.fraction < 1.0f ) { > cent->lerpOrigin[0] = lastOrigin[0] + tr.fraction * ( cent->lerpOrigin[0] - lastOrigin[0] ); > cent->lerpOrigin[1] = lastOrigin[1] + tr.fraction * ( cent->lerpOrigin[1] - lastOrigin[1] ); > cent->lerpOrigin[2] = lastOrigin[2] + tr.fraction * ( cent->lerpOrigin[2] - lastOrigin[2] ); > } > } > //unlagged - projectile nudge 1030a1091,1106 > //unlagged - early transitioning > if ( cg.nextSnap ) { > // pre-add some of the entities sent over by the server > // we have data for them and they don't need to interpolate > for ( num = 0 ; num < cg.nextSnap->numEntities ; num++ ) { > cent = &cg_entities[ cg.nextSnap->entities[ num ].number ]; > if ( cent->nextState.eType == ET_MISSILE || cent->nextState.eType == ET_GENERAL ) { > // transition it immediately and add it > CG_TransitionEntity( cent ); > cent->interpolate = qtrue; > CG_AddCEntity( cent ); > } > } > } > //unlagged - early transitioning > 1034c1110,1114 < CG_AddCEntity( cent ); --- > //unlagged - early transitioning > if ( !cg.nextSnap || (cent->nextState.eType != ET_MISSILE && cent->nextState.eType != ET_GENERAL) ) { > //unlagged - early transitioning > CG_AddCEntity( cent ); > } //Also unlagged diff -r openArenaEliminationB15/code/cgame/cg_event.c openArenaEliminationB16/code/cgame/cg_event.c 942,947c942,960 < // if the end was on a nomark surface, don't make an explosion < CG_RailTrail( ci, es->origin2, es->pos.trBase ); < if ( es->eventParm != 255 ) { < ByteToDir( es->eventParm, dir ); < CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT ); < } --- > //unlagged - attack prediction #2 > // if the client is us, unlagged is on server-side, and we've got it client-side > if ( es->clientNum == cg.predictedPlayerState.clientNum && > cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 16) ) { > // do nothing, because it was already predicted > //Com_Printf("Ignoring rail trail event\n"); > } > else { > // draw a rail trail, because it wasn't predicted > CG_RailTrail( ci, es->origin2, es->pos.trBase ); > > // if the end was on a nomark surface, don't make an explosion > if ( es->eventParm != 255 ) { > ByteToDir( es->eventParm, dir ); > CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT ); > } > //Com_Printf("Non-predicted rail trail\n"); > } > //unlagged - attack prediction #2 952,953c965,978 < ByteToDir( es->eventParm, dir ); < CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD ); --- > //unlagged - attack prediction #2 > // if the client is us, unlagged is on server-side, and we've got it client-side > if ( es->clientNum == cg.predictedPlayerState.clientNum && > cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 2) ) { > // do nothing, because it was already predicted > //Com_Printf("Ignoring bullet event\n"); > } > else { > // do the bullet, because it wasn't predicted > ByteToDir( es->eventParm, dir ); > CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD ); > //Com_Printf("Non-predicted bullet\n"); > } > //unlagged - attack prediction #2 958c983,995 < CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm ); --- > //unlagged - attack prediction #2 > // if the client is us, unlagged is on server-side, and we've got it client-side > if ( es->clientNum == cg.predictedPlayerState.clientNum && > cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 2) ) { > // do nothing, because it was already predicted > //Com_Printf("Ignoring bullet event\n"); > } > else { > // do the bullet, because it wasn't predicted > CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm ); > //Com_Printf("Non-predicted bullet\n"); > } > //unlagged - attack prediction #2 963c1000,1012 < CG_ShotgunFire( es ); --- > //unlagged - attack prediction #2 > // if the client is us, unlagged is on server-side, and we've got it client-side > if ( es->otherEntityNum == cg.predictedPlayerState.clientNum && > cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 4) ) { > // do nothing, because it was already predicted > //Com_Printf("Ignoring shotgun event\n"); > } > else { > // do the shotgun pattern, because it wasn't predicted > CG_ShotgunFire( es ); > //Com_Printf("Non-predicted shotgun pattern\n"); > } > //unlagged - attack prediction #2 diff -r openArenaEliminationB15/code/cgame/cg_local.h openArenaEliminationB16/code/cgame/cg_local.h 455a456,459 > > //unlagged - optimized prediction > #define NUM_SAVED_STATES (CMD_BACKUP + 2) > //unlagged - optimized prediction 650a655,661 > //unlagged - optimized prediction > int lastPredictedCommand; > int lastServerTime; > playerState_t savedPmoveStates[NUM_SAVED_STATES]; > int stateHead, stateTail; > //unlagged - optimized prediction > 1107a1119,1122 > //unlagged - client options > // this will be set to the server's g_delagHitscan > int delagHitscan; > //unlagged - client options 1192c1207,1210 < extern vmCvar_t cg_smoothClients; --- > //unlagged - smooth clients #2 > // this is done server-side now > //extern vmCvar_t cg_smoothClients; > //unlagged - smooth clients #2 1223a1242,1264 > //unlagged - client options > extern vmCvar_t cg_delag; > extern vmCvar_t cg_debugDelag; > extern vmCvar_t cg_drawBBox; > extern vmCvar_t cg_cmdTimeNudge; > extern vmCvar_t sv_fps; > extern vmCvar_t cg_projectileNudge; > extern vmCvar_t cg_optimizePrediction; > extern vmCvar_t cl_timeNudge; > extern vmCvar_t cg_latentSnaps; > extern vmCvar_t cg_latentCmds; > extern vmCvar_t cg_plOut; > //unlagged - client options > > //extra CVARS elimination > extern vmCvar_t cg_alwaysWeaponBar; > > //unlagged - cg_unlagged.c > void CG_PredictWeaponEffects( centity_t *cent ); > void CG_AddBoundingBox( centity_t *cent ); > qboolean CG_Cvar_ClampInt( const char *name, vmCvar_t *vmCvar, int min, int max ); > //unlagged - cg_unlagged.c > 1461a1503,1505 > //unlagged - early transitioning > void CG_TransitionEntity( centity_t *cent ); > //unlagged - early transitioning diff -r openArenaEliminationB15/code/cgame/cg_main.c openArenaEliminationB16/code/cgame/cg_main.c 166c166,169 < vmCvar_t cg_smoothClients; --- > //unlagged - smooth clients #2 > // this is done server-side now > //vmCvar_t cg_smoothClients; > //unlagged - smooth clients #2 199a203,218 > //unlagged - client options > vmCvar_t cg_delag; > vmCvar_t cg_debugDelag; > vmCvar_t cg_drawBBox; > vmCvar_t cg_cmdTimeNudge; > vmCvar_t sv_fps; > vmCvar_t cg_projectileNudge; > vmCvar_t cg_optimizePrediction; > vmCvar_t cl_timeNudge; > vmCvar_t cg_latentSnaps; > vmCvar_t cg_latentCmds; > vmCvar_t cg_plOut; > //unlagged - client options > > //elimination addition > vmCvar_t cg_alwaysWeaponBar; 284a304 > { &cg_alwaysWeaponBar, "cg_alwaysWeaponBar", "0", CVAR_ARCHIVE}, //Elimination 307c327,330 < { &cg_smoothClients, "cg_smoothClients", "0", CVAR_USERINFO | CVAR_ARCHIVE}, --- > //unlagged - smooth clients #2 > // this is done server-side now > // { &cg_smoothClients, "cg_smoothClients", "0", CVAR_USERINFO | CVAR_ARCHIVE}, > //unlagged - smooth clients #2 318a342,355 > //unlagged - client options > { &cg_delag, "cg_delag", "1", CVAR_ARCHIVE | CVAR_USERINFO }, > { &cg_debugDelag, "cg_debugDelag", "0", CVAR_USERINFO | CVAR_CHEAT }, > { &cg_drawBBox, "cg_drawBBox", "0", CVAR_CHEAT }, > { &cg_cmdTimeNudge, "cg_cmdTimeNudge", "0", CVAR_ARCHIVE | CVAR_USERINFO }, > // this will be automagically copied from the server > { &sv_fps, "sv_fps", "20", 0 }, > { &cg_projectileNudge, "cg_projectileNudge", "0", CVAR_ARCHIVE }, > { &cg_optimizePrediction, "cg_optimizePrediction", "1", CVAR_ARCHIVE }, > { &cl_timeNudge, "cl_timeNudge", "0", CVAR_ARCHIVE }, > { &cg_latentSnaps, "cg_latentSnaps", "0", CVAR_USERINFO | CVAR_CHEAT }, > { &cg_latentCmds, "cg_latentCmds", "0", CVAR_USERINFO | CVAR_CHEAT }, > { &cg_plOut, "cg_plOut", "0", CVAR_USERINFO | CVAR_CHEAT }, > //unlagged - client options 380a418,444 > //unlagged - client options > // clamp the value between 0 and 999 > // negative values would suck - people could conceivably shoot other > // players *long* after they had left the area, on purpose > if ( cv->vmCvar == &cg_cmdTimeNudge ) { > CG_Cvar_ClampInt( cv->cvarName, cv->vmCvar, 0, 999 ); > } > // cl_timenudge less than -50 or greater than 50 doesn't actually > // do anything more than -50 or 50 (actually the numbers are probably > // closer to -30 and 30, but 50 is nice and round-ish) > // might as well not feed the myth, eh? > else if ( cv->vmCvar == &cl_timeNudge ) { > CG_Cvar_ClampInt( cv->cvarName, cv->vmCvar, -50, 50 ); > } > // don't let this go too high - no point > else if ( cv->vmCvar == &cg_latentSnaps ) { > CG_Cvar_ClampInt( cv->cvarName, cv->vmCvar, 0, 10 ); > } > // don't let this get too large > else if ( cv->vmCvar == &cg_latentCmds ) { > CG_Cvar_ClampInt( cv->cvarName, cv->vmCvar, 0, MAX_LATENT_CMDS - 1 ); > } > // no more than 100% packet loss > else if ( cv->vmCvar == &cg_plOut ) { > CG_Cvar_ClampInt( cv->cvarName, cv->vmCvar, 0, 100 ); > } > //unlagged - client options diff -r openArenaEliminationB15/code/cgame/cg_predict.c openArenaEliminationB16/code/cgame/cg_predict.c 426c426,554 < --- > //unlagged - optimized prediction > #define ABS(x) ((x) < 0 ? (-(x)) : (x)) > > static int IsUnacceptableError( playerState_t *ps, playerState_t *pps ) { > vec3_t delta; > int i; > > if ( pps->pm_type != ps->pm_type || > pps->pm_flags != ps->pm_flags || > pps->pm_time != ps->pm_time ) { > return 1; > } > > VectorSubtract( pps->origin, ps->origin, delta ); > if ( VectorLengthSquared( delta ) > 0.1f * 0.1f ) { > if ( cg_showmiss.integer ) { > CG_Printf("delta: %.2f ", VectorLength(delta) ); > } > return 2; > } > > VectorSubtract( pps->velocity, ps->velocity, delta ); > if ( VectorLengthSquared( delta ) > 0.1f * 0.1f ) { > if ( cg_showmiss.integer ) { > CG_Printf("delta: %.2f ", VectorLength(delta) ); > } > return 3; > } > > if ( pps->weaponTime != ps->weaponTime || > pps->gravity != ps->gravity || > pps->speed != ps->speed || > pps->delta_angles[0] != ps->delta_angles[0] || > pps->delta_angles[1] != ps->delta_angles[1] || > pps->delta_angles[2] != ps->delta_angles[2] || > pps->groundEntityNum != ps->groundEntityNum ) { > return 4; > } > > if ( pps->legsTimer != ps->legsTimer || > pps->legsAnim != ps->legsAnim || > pps->torsoTimer != ps->torsoTimer || > pps->torsoAnim != ps->torsoAnim || > pps->movementDir != ps->movementDir ) { > return 5; > } > > VectorSubtract( pps->grapplePoint, ps->grapplePoint, delta ); > if ( VectorLengthSquared( delta ) > 0.1f * 0.1f ) { > return 6; > } > > if ( pps->eFlags != ps->eFlags ) { > return 7; > } > > if ( pps->eventSequence != ps->eventSequence ) { > return 8; > } > > for ( i = 0; i < MAX_PS_EVENTS; i++ ) { > if ( pps->events[i] != ps->events[i] || > pps->eventParms[i] != ps->eventParms[i] ) { > return 9; > } > } > > if ( pps->externalEvent != ps->externalEvent || > pps->externalEventParm != ps->externalEventParm || > pps->externalEventTime != ps->externalEventTime ) { > return 10; > } > > if ( pps->clientNum != ps->clientNum || > pps->weapon != ps->weapon || > pps->weaponstate != ps->weaponstate ) { > return 11; > } > > if ( ABS(pps->viewangles[0] - ps->viewangles[0]) > 1.0f || > ABS(pps->viewangles[1] - ps->viewangles[1]) > 1.0f || > ABS(pps->viewangles[2] - ps->viewangles[2]) > 1.0f ) { > return 12; > } > > if ( pps->viewheight != ps->viewheight ) { > return 13; > } > > if ( pps->damageEvent != ps->damageEvent || > pps->damageYaw != ps->damageYaw || > pps->damagePitch != ps->damagePitch || > pps->damageCount != ps->damageCount ) { > return 14; > } > > for ( i = 0; i < MAX_STATS; i++ ) { > if ( pps->stats[i] != ps->stats[i] ) { > return 15; > } > } > > for ( i = 0; i < MAX_PERSISTANT; i++ ) { > if ( pps->persistant[i] != ps->persistant[i] ) { > return 16; > } > } > > for ( i = 0; i < MAX_POWERUPS; i++ ) { > if ( pps->powerups[i] != ps->powerups[i] ) { > return 17; > } > } > > for ( i = 0; i < MAX_WEAPONS; i++ ) { > if ( pps->ammo[i] != ps->ammo[i] ) { > return 18; > } > } > > if ( pps->generic1 != ps->generic1 || > pps->loopSound != ps->loopSound || > pps->jumppad_ent != ps->jumppad_ent ) { > return 19; > } > > return 0; > } > //unlagged - optimized prediction 459a588,591 > //unlagged - optimized prediction > int stateIndex = 0, predictCmd = 0; //Sago: added initializing > int numPredicted = 0, numPlayedBack = 0; // debug code > //unlagged - optimized prediction 541a674,760 > //unlagged - optimized prediction > // Like the comments described above, a player's state is entirely > // re-predicted from the last valid snapshot every client frame, which > // can be really, really, really slow. Every old command has to be > // run again. For every client frame that is *not* directly after a > // snapshot, this is unnecessary, since we have no new information. > // For those, we'll play back the predictions from the last frame and > // predict only the newest commands. Essentially, we'll be doing > // an incremental predict instead of a full predict. > // > // If we have a new snapshot, we can compare its player state's command > // time to the command times in the queue to find a match. If we find > // a matching state, and the predicted version has not deviated, we can > // use the predicted state as a base - and also do an incremental predict. > // > // With this method, we get incremental predicts on every client frame > // except a frame following a new snapshot in which there was a prediction > // error. This yeilds anywhere from a 15% to 40% performance increase, > // depending on how much of a bottleneck the CPU is. > > // we check for cg_latentCmds because it'll mess up the optimization > // FIXME: make cg_latentCmds work with cg_optimizePrediction? > if ( cg_optimizePrediction.integer && !cg_latentCmds.integer ) { > if ( cg.nextFrameTeleport || cg.thisFrameTeleport ) { > // do a full predict > cg.lastPredictedCommand = 0; > cg.stateTail = cg.stateHead; > predictCmd = current - CMD_BACKUP + 1; > } > // cg.physicsTime is the current snapshot's serverTime > // if it's the same as the last one > else if ( cg.physicsTime == cg.lastServerTime ) { > // we have no new information, so do an incremental predict > predictCmd = cg.lastPredictedCommand + 1; > } > else { > // we have a new snapshot > > int i; > qboolean error = qtrue; > > // loop through the saved states queue > for ( i = cg.stateHead; i != cg.stateTail; i = (i + 1) % NUM_SAVED_STATES ) { > // if we find a predicted state whose commandTime matches the snapshot player state's commandTime > if ( cg.savedPmoveStates[i].commandTime == cg.predictedPlayerState.commandTime ) { > // make sure the state differences are acceptable > int errorcode = IsUnacceptableError( &cg.predictedPlayerState, &cg.savedPmoveStates[i] ); > > // too much change? > if ( errorcode ) { > if ( cg_showmiss.integer ) { > CG_Printf("errorcode %d at %d\n", errorcode, cg.time); > } > // yeah, so do a full predict > break; > } > > // this one is almost exact, so we'll copy it in as the starting point > *cg_pmove.ps = cg.savedPmoveStates[i]; > // advance the head > cg.stateHead = (i + 1) % NUM_SAVED_STATES; > > // set the next command to predict > predictCmd = cg.lastPredictedCommand + 1; > > // a saved state matched, so flag it > error = qfalse; > break; > } > } > > // if no saved states matched > if ( error ) { > // do a full predict > cg.lastPredictedCommand = 0; > cg.stateTail = cg.stateHead; > predictCmd = current - CMD_BACKUP + 1; > } > } > > // keep track of the server time of the last snapshot so we > // know when we're starting from a new one in future calls > cg.lastServerTime = cg.physicsTime; > stateIndex = cg.stateHead; > } > //unlagged - optimized prediction > 624c843,887 < Pmove (&cg_pmove); --- > //unlagged - optimized prediction > // we check for cg_latentCmds because it'll mess up the optimization > if ( cg_optimizePrediction.integer && !cg_latentCmds.integer ) { > // if we need to predict this command, or we've run out of space in the saved states queue > if ( cmdNum >= predictCmd || (stateIndex + 1) % NUM_SAVED_STATES == cg.stateHead ) { > // run the Pmove > Pmove (&cg_pmove); > > numPredicted++; // debug code > > // record the last predicted command > cg.lastPredictedCommand = cmdNum; > > // if we haven't run out of space in the saved states queue > if ( (stateIndex + 1) % NUM_SAVED_STATES != cg.stateHead ) { > // save the state for the false case (of cmdNum >= predictCmd) > // in later calls to this function > cg.savedPmoveStates[stateIndex] = *cg_pmove.ps; > stateIndex = (stateIndex + 1) % NUM_SAVED_STATES; > cg.stateTail = stateIndex; > } > } > else { > numPlayedBack++; // debug code > > if ( cg_showmiss.integer && > cg.savedPmoveStates[stateIndex].commandTime != cg_pmove.cmd.serverTime) { > // this should ONLY happen just after changing the value of pmove_fixed > CG_Printf( "saved state miss\n" ); > } > > // play back the command from the saved states > *cg_pmove.ps = cg.savedPmoveStates[stateIndex]; > > // go to the next element in the saved states array > stateIndex = (stateIndex + 1) % NUM_SAVED_STATES; > } > } > else { > // run the Pmove > Pmove (&cg_pmove); > > numPredicted++; // debug code > } > //unlagged - optimized prediction 634a898,906 > //unlagged - optimized prediction > // do a /condump after a few seconds of this > //CG_Printf("cg.time: %d, numPredicted: %d, numPlayedBack: %d\n", cg.time, numPredicted, numPlayedBack); // debug code > // if everything is working right, numPredicted should be 1 more than 98% > // of the time, meaning only ONE predicted move was done in the frame > // you should see other values for numPredicted after IsUnacceptableError > // returns nonzero, and that's it > //unlagged - optimized prediction > diff -r openArenaEliminationB15/code/cgame/cg_servercmds.c openArenaEliminationB16/code/cgame/cg_servercmds.c 267a268,273 > > //unlagged - server options > // we'll need this for deciding whether or not to predict weapon effects > cgs.delagHitscan = atoi( Info_ValueForKey( info, "g_delagHitscan" ) ); > trap_Cvar_Set("g_delagHitscan", va("%i", cgs.delagHitscan)); > //unlagged - server options diff -r openArenaEliminationB15/code/cgame/cg_snapshot.c openArenaEliminationB16/code/cgame/cg_snapshot.c 58c58,60 < static void CG_TransitionEntity( centity_t *cent ) { --- > //unlagged - early transitioning > // used to be static, now needed to transition entities from within cg_ents.c > void CG_TransitionEntity( centity_t *cent ) { diff -r openArenaEliminationB15/code/cgame/cg_weapons.c openArenaEliminationB16/code/cgame/cg_weapons.c 985a986,996 > //unlagged - attack prediction #1 > // if the entity is us, unlagged is on server-side, and we've got it on for the lightning gun > if ( (cent->currentState.number == cg.predictedPlayerState.clientNum) && cgs.delagHitscan && > ( cg_delag.integer & 1 || cg_delag.integer & 8 ) ) { > // always shoot straight forward from our current position > AngleVectors( cg.predictedPlayerState.viewangles, forward, NULL, NULL ); > VectorCopy( cg.predictedPlayerState.origin, muzzlePoint ); > } > else > //unlagged - attack prediction #1 > 990a1002,1007 > //unlagged - true lightning > // might as well fix up true lightning while we're at it > vec3_t viewangles; > VectorCopy( cg.predictedPlayerState.viewangles, viewangles ); > //unlagged - true lightning > 1010,1011c1027,1032 < VectorCopy(cent->lerpOrigin, muzzlePoint ); < // VectorCopy(cg.refdef.vieworg, muzzlePoint ); --- > //unlagged - true lightning > // VectorCopy(cent->lerpOrigin, muzzlePoint ); > // VectorCopy(cg.refdef.vieworg, muzzlePoint ); > // *this* is the correct origin for true lightning > VectorCopy(cg.predictedPlayerState.origin, muzzlePoint ); > //unlagged - true lightning 1473a1495 > vec4_t realColor; 1480a1503,1512 > > //Elimination: Always show weapon bar > if(cg_alwaysWeaponBar.integer) { > realColor[0] = 1.0; > realColor[1] = 1.0; > realColor[2] = 1.0; > realColor[3] = 1.0; > color = realColor; > } > 1744a1777,1780 > > //unlagged - attack prediction #1 > CG_PredictWeaponEffects( cent ); > //unlagged - attack prediction #1 2054c2090,2092 < static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum ) { --- > //unlagged - attack prediction > // made this non-static for access from cg_unlagged.c > void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum ) { diff -r openArenaEliminationB15/code/game/ai_dmq3.c openArenaEliminationB16/code/game/ai_dmq3.c 3059a3060,3064 > //Neil Torontos unlagged > //unlagged - misc > // this has nothing to do with lag compensation, but it's great for testing > if ( g_entities[i].flags & FL_NOTARGET ) continue; > //unlagged - misc diff -r openArenaEliminationB15/code/game/g_active.c openArenaEliminationB16/code/game/g_active.c 812a813,924 > //Here comes the unlagged bit! > //unlagged - backward reconciliation #4 > // frameOffset should be about the number of milliseconds into a frame > // this command packet was received, depending on how fast the server > // does a G_RunFrame() > client->frameOffset = trap_Milliseconds() - level.frameStartTime; > //unlagged - backward reconciliation #4 > > > //unlagged - lag simulation #3 > // if the client wants to simulate outgoing packet loss > if ( client->pers.plOut ) { > // see if a random value is below the threshhold > float thresh = (float)client->pers.plOut / 100.0f; > if ( random() < thresh ) { > // do nothing at all if it is - this is a lost command > return; > } > } > //unlagged - lag simulation #3 > > > //unlagged - true ping > // save the estimated ping in a queue for averaging later > > // we use level.previousTime to account for 50ms lag correction > // besides, this will turn out numbers more like what players are used to > client->pers.pingsamples[client->pers.samplehead] = level.previousTime + client->frameOffset - ucmd->serverTime; > client->pers.samplehead++; > if ( client->pers.samplehead >= NUM_PING_SAMPLES ) { > client->pers.samplehead -= NUM_PING_SAMPLES; > } > > // initialize the real ping > if ( g_truePing.integer ) { > int i, sum = 0; > > // get an average of the samples we saved up > for ( i = 0; i < NUM_PING_SAMPLES; i++ ) { > sum += client->pers.pingsamples[i]; > } > > client->pers.realPing = sum / NUM_PING_SAMPLES; > } > else { > // if g_truePing is off, use the normal ping > client->pers.realPing = client->ps.ping; > } > //unlagged - true ping > > > //unlagged - lag simulation #2 > // keep a queue of past commands > client->pers.cmdqueue[client->pers.cmdhead] = client->pers.cmd; > client->pers.cmdhead++; > if ( client->pers.cmdhead >= MAX_LATENT_CMDS ) { > client->pers.cmdhead -= MAX_LATENT_CMDS; > } > > // if the client wants latency in commands (client-to-server latency) > if ( client->pers.latentCmds ) { > // save the actual command time > int time = ucmd->serverTime; > > // find out which index in the queue we want > int cmdindex = client->pers.cmdhead - client->pers.latentCmds - 1; > while ( cmdindex < 0 ) { > cmdindex += MAX_LATENT_CMDS; > } > > // read in the old command > client->pers.cmd = client->pers.cmdqueue[cmdindex]; > > // adjust the real ping to reflect the new latency > client->pers.realPing += time - ucmd->serverTime; > } > //unlagged - lag simulation #2 > > > //unlagged - backward reconciliation #4 > // save the command time *before* pmove_fixed messes with the serverTime, > // and *after* lag simulation messes with it :) > // attackTime will be used for backward reconciliation later (time shift) > client->attackTime = ucmd->serverTime; > //unlagged - backward reconciliation #4 > > > //unlagged - smooth clients #1 > // keep track of this for later - we'll use this to decide whether or not > // to send extrapolated positions for this client > client->lastUpdateFrame = level.framenum; > //unlagged - smooth clients #1 > > > //unlagged - lag simulation #1 > // if the client is adding latency to received snapshots (server-to-client latency) > if ( client->pers.latentSnaps ) { > // adjust the real ping > client->pers.realPing += client->pers.latentSnaps * (1000 / sv_fps.integer); > // adjust the attack time so backward reconciliation will work > client->attackTime -= client->pers.latentSnaps * (1000 / sv_fps.integer); > } > //unlagged - lag simulation #1 > > > //unlagged - true ping > // make sure the true ping is over 0 - with cl_timenudge it can be less > if ( client->pers.realPing < 0 ) { > client->pers.realPing = 0; > } > //unlagged - true ping > 979,984c1091,1104 < if (g_smoothClients.integer) { < BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qtrue ); < } < else { < BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue ); < } --- > //unlagged - smooth clients #2 > // clients no longer do extrapolation if cg_smoothClients is 1, because > // skip correction is all handled server-side now > // since that's the case, it makes no sense to store the extra info > // in the client's snapshot entity, so let's save a little bandwidth > /* > if (g_smoothClients.integer) { > BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qtrue ); > } > else { > */ > BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qtrue ); > // } > //unlagged - smooth clients #2 1065a1186 > //Unlagged: commented out 1068c1189 < ent->client->lastCmdTime = level.time; --- > //ent->client->lastCmdTime = level.time; 1156a1278,1281 > //unlagged - smooth clients #1 > int frames; > //unlagged - smooth clients #1 > 1211a1337 > //Unlagged: Commented out 1213c1339 < if ( level.time - ent->client->lastCmdTime > 1000 ) { --- > /*if ( level.time - ent->client->lastCmdTime > 1000 ) { 1217c1343 < } --- > }*/ 1222a1349 > //Unlagged: Always do the else clause 1224c1351 < if (g_smoothClients.integer) { --- > /* if (g_smoothClients.integer) { 1227c1354 < else { --- > else { */ 1229c1356 < } --- > // } 1231a1359,1388 > //unlagged - smooth clients #1 > // mark as not missing updates initially > ent->client->ps.eFlags &= ~EF_CONNECTION; > > // see how many frames the client has missed > frames = level.framenum - ent->client->lastUpdateFrame - 1; > > // don't extrapolate more than two frames > if ( frames > 2 ) { > frames = 2; > > // if they missed more than two in a row, show the phone jack > ent->client->ps.eFlags |= EF_CONNECTION; > ent->s.eFlags |= EF_CONNECTION; > } > > // did the client miss any frames? > if ( frames > 0 && g_smoothClients.integer ) { > // yep, missed one or more, so extrapolate the player's movement > G_PredictPlayerMove( ent, (float)frames / sv_fps.integer ); > // save network bandwidth > SnapVector( ent->s.pos.trBase ); > } > //unlagged - smooth clients #1 > > //unlagged - backward reconciliation #1 > // store the client's position for backward reconciliation later > G_StoreHistory( ent ); > //unlagged - backward reconciliation #1 > diff -r openArenaEliminationB15/code/game/g_client.c openArenaEliminationB16/code/game/g_client.c 1028a1029,1063 > //unlagged - client options > // see if the player has opted out > s = Info_ValueForKey( userinfo, "cg_delag" ); > if ( !atoi( s ) ) { > client->pers.delag = 0; > } else { > client->pers.delag = atoi( s ); > } > > // see if the player is nudging his shots > s = Info_ValueForKey( userinfo, "cg_cmdTimeNudge" ); > client->pers.cmdTimeNudge = atoi( s ); > > // see if the player wants to debug the backward reconciliation > s = Info_ValueForKey( userinfo, "cg_debugDelag" ); > if ( !atoi( s ) ) { > client->pers.debugDelag = qfalse; > } > else { > client->pers.debugDelag = qtrue; > } > > // see if the player is simulating incoming latency > s = Info_ValueForKey( userinfo, "cg_latentSnaps" ); > client->pers.latentSnaps = atoi( s ); > > // see if the player is simulating outgoing latency > s = Info_ValueForKey( userinfo, "cg_latentCmds" ); > client->pers.latentCmds = atoi( s ); > > // see if the player is simulating outgoing packet loss > s = Info_ValueForKey( userinfo, "cg_plOut" ); > client->pers.plOut = atoi( s ); > //unlagged - client options > 1281a1317,1327 > //Sago: Changed the message > //unlagged - backward reconciliation #5 > // announce it > if ( g_delagHitscan.integer ) { > trap_SendServerCommand( clientNum, "print \"Full lag compensation is ON!\n\"" ); > } > else { > trap_SendServerCommand( clientNum, "print \"Full lag compensation is OFF!\n\"" ); > } > //unlagged - backward reconciliation #5 > 1497a1544,1550 > //unlagged - backward reconciliation #3 > // we don't want players being backward-reconciled to the place they died > G_ResetHistory( ent ); > // and this is as good a time as any to clear the saved state > ent->client->saved.leveltime = 0; > //unlagged - backward reconciliation #3 > diff -r openArenaEliminationB15/code/game/g_cmds.c openArenaEliminationB16/code/game/g_cmds.c 56c56,59 < ping = cl->ps.ping < 999 ? cl->ps.ping : 999; --- > //unlagged - true ping > //ping = cl->ps.ping < 999 ? cl->ps.ping : 999; > ping = cl->pers.realPing < 999 ? cl->pers.realPing : 999; > //unlagged - true ping diff -r openArenaEliminationB15/code/game/g_combat.c openArenaEliminationB16/code/game/g_combat.c 462a463,467 > //unlagged - backward reconciliation #2 > // make sure the body shows up in the client's current position > G_UnTimeShiftClient( self ); > //unlagged - backward reconciliation #2 > diff -r openArenaEliminationB15/code/game/g_local.h openArenaEliminationB16/code/game/g_local.h 241a242,245 > //unlagged - true ping > #define NUM_PING_SAMPLES 64 > //unlagged - true ping > 260a265,283 > > //unlagged - client options > // these correspond with variables in the userinfo string > int delag; > int debugDelag; > int cmdTimeNudge; > //unlagged - client options > //unlagged - lag simulation #2 > int latentSnaps; > int latentCmds; > int plOut; > usercmd_t cmdqueue[MAX_LATENT_CMDS]; > int cmdhead; > //unlagged - lag simulation #2 > //unlagged - true ping > int realPing; > int pingsamples[NUM_PING_SAMPLES]; > int samplehead; > //unlagged - true ping 262a286,296 > //unlagged - backward reconciliation #1 > // the size of history we'll keep > #define NUM_CLIENT_HISTORY 17 > > // everything we need to know to backward reconcile > typedef struct { > vec3_t mins, maxs; > vec3_t currentOrigin; > int leveltime; > } clientHistory_t; > //unlagged - backward reconciliation #1 278c312,313 < int lastCmdTime; // level.time of last usercmd_t, for EF_CONNECTION --- > //Unlagged - commented out - handled differently > //int lastCmdTime; // level.time of last usercmd_t, for EF_CONNECTION 336a372,391 > > //unlagged - backward reconciliation #1 > // the serverTime the button was pressed > // (stored before pmove_fixed changes serverTime) > int attackTime; > // the head of the history queue > int historyHead; > // the history queue > clientHistory_t history[NUM_CLIENT_HISTORY]; > // the client's saved position > clientHistory_t saved; // used to restore after time shift > // an approximation of the actual server time we received this > // command (not in 50ms increments) > int frameOffset; > //unlagged - backward reconciliation #1 > > //unlagged - smooth clients #1 > // the last frame number we got an update from this client > int lastUpdateFrame; > //unlagged - smooth clients #1 447a503,507 > > //unlagged - backward reconciliation #4 > // actual time this server frame started > int frameStartTime; > //unlagged - backward reconciliation #4 594c654,657 < void SnapVectorTowards( vec3_t v, vec3_t to ); --- > //unlagged - attack prediction #3 > // we're making this available to both games > //void SnapVectorTowards( vec3_t v, vec3_t to ); > //unlagged - attack prediction #3 598a662,671 > //unlagged - g_unlagged.c > void G_ResetHistory( gentity_t *ent ); > void G_StoreHistory( gentity_t *ent ); > void G_TimeShiftAllClients( int time, gentity_t *skip ); > void G_UnTimeShiftAllClients( gentity_t *skip ); > void G_DoTimeShiftFor( gentity_t *ent ); > void G_UndoTimeShiftFor( gentity_t *ent ); > void G_UnTimeShiftClient( gentity_t *client ); > void G_PredictPlayerMove( gentity_t *ent, float frametime ); > //unlagged - g_unlagged.c 859a933,944 > //unlagged - server options > // some new server-side variables > extern vmCvar_t g_delagHitscan; > extern vmCvar_t g_unlaggedVersion; > extern vmCvar_t g_truePing; > // server admins can adjust this if they *believe* the lightning > // gun is too powerful with lag compensation > extern vmCvar_t g_lightningDamage; > // this is for convenience - using "sv_fps.integer" is nice :) > extern vmCvar_t sv_fps; > //unlagged - server options > diff -r openArenaEliminationB15/code/game/g_main.c openArenaEliminationB16/code/game/g_main.c 137a138,145 > //unlagged - server options > vmCvar_t g_delagHitscan; > vmCvar_t g_unlaggedVersion; > vmCvar_t g_truePing; > vmCvar_t g_lightningDamage; > vmCvar_t sv_fps; > //unlagged - server options > 220a229,237 > //unlagged - server options > { &g_delagHitscan, "g_delagHitscan", "1", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qtrue }, > { &g_unlaggedVersion, "g_unlaggedVersion", "2.0", CVAR_ROM | CVAR_SERVERINFO, 0, qfalse }, > { &g_truePing, "g_truePing", "1", CVAR_ARCHIVE, 0, qtrue }, > { &g_lightningDamage, "g_lightningDamage", "8", 0, 0, qtrue }, > // it's CVAR_SYSTEMINFO so the client's sv_fps will be automagically set to its value > { &sv_fps, "sv_fps", "20", CVAR_SYSTEMINFO | CVAR_ARCHIVE, 0, qfalse }, > //unlagged - server options > 2356,2359c2373,2381 < if ( ent->s.eType == ET_MISSILE ) { < G_RunMissile( ent ); < continue; < } --- > //unlagged - backward reconciliation #2 > // we'll run missiles separately to save CPU in backward reconciliation > /* > if ( ent->s.eType == ET_MISSILE ) { > G_RunMissile( ent ); > continue; > } > */ > //unlagged - backward reconciliation #2 2377a2400,2425 > > //unlagged - backward reconciliation #2 > // NOW run the missiles, with all players backward-reconciled > // to the positions they were in exactly 50ms ago, at the end > // of the last server frame > G_TimeShiftAllClients( level.previousTime, NULL ); > > ent = &g_entities[0]; > for (i=0 ; i if ( !ent->inuse ) { > continue; > } > > // temporary entities don't think > if ( ent->freeAfterEvent ) { > continue; > } > > if ( ent->s.eType == ET_MISSILE ) { > G_RunMissile( ent ); > } > } > > G_UnTimeShiftAllClients( NULL ); > //unlagged - backward reconciliation #2 > 2427a2476,2482 > > //unlagged - backward reconciliation #4 > // record the time at the end of this frame - it should be about > // the time the next frame begins - when the server starts > // accepting commands from connected clients > level.frameStartTime = trap_Milliseconds(); > //unlagged - backward reconciliation #4 diff -r openArenaEliminationB15/code/game/g_misc.c openArenaEliminationB16/code/game/g_misc.c 106a107,111 > //unlagged - backward reconciliation #3 > // we don't want players being backward-reconciled back through teleporters > G_ResetHistory( player ); > //unlagged - backward reconciliation #3 > diff -r openArenaEliminationB15/code/game/g_missile.c openArenaEliminationB16/code/game/g_missile.c 533a534,537 > //unlagged - projectile nudge > // we'll need this for nudging projectiles later > bolt->s.otherEntityNum = self->s.number; > //unlagged - projectile nudge 575a580,583 > //unlagged - projectile nudge > // we'll need this for nudging projectiles later > bolt->s.otherEntityNum = self->s.number; > //unlagged - projectile nudge 616a625,628 > //unlagged - projectile nudge > // we'll need this for nudging projectiles later > bolt->s.otherEntityNum = self->s.number; > //unlagged - projectile nudge 656a669,672 > //unlagged - projectile nudge > // we'll need this for nudging projectiles later > bolt->s.otherEntityNum = self->s.number; > //unlagged - projectile nudge 682a699,701 > //unlagged - grapple > int hooktime; > //unlagged - grapple 698a718,734 > //unlagged - grapple > // we might want this later > hook->s.otherEntityNum = self->s.number; > > // setting the projectile base time back makes the hook's first > // step larger > > if ( self->client ) { > hooktime = self->client->pers.cmd.serverTime + 50; > } > else { > hooktime = level.time - MISSILE_PRESTEP_TIME; > } > > hook->s.pos.trTime = hooktime; > //unlagged - grapple > 700c736,738 < hook->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame --- > //unlagged - grapple > //hook->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame > //unlagged - grapple 734a773,776 > //unlagged - projectile nudge > // we'll need this for nudging projectiles later > bolt->s.otherEntityNum = self->s.number; > //unlagged - projectile nudge 782a825,828 > //unlagged - projectile nudge > // we'll need this for nudging projectiles later > bolt->s.otherEntityNum = self->s.number; > //unlagged - projectile nudge diff -r openArenaEliminationB15/code/game/g_team.c openArenaEliminationB16/code/game/g_team.c 699a700,701 > > flag = NULL; diff -r openArenaEliminationB15/code/game/g_weapon.c openArenaEliminationB16/code/game/g_weapon.c 143,153c143,158 < void SnapVectorTowards( vec3_t v, vec3_t to ) { < int i; < < for ( i = 0 ; i < 3 ; i++ ) { < if ( to[i] <= v[i] ) { < v[i] = (int)v[i]; < } else { < v[i] = (int)v[i] + 1; < } < } < } --- > //unlagged - attack prediction #3 > // moved to q_shared.c > /* > void SnapVectorTowards( vec3_t v, vec3_t to ) { > int i; > > for ( i = 0 ; i < 3 ; i++ ) { > if ( to[i] <= v[i] ) { > v[i] = (int)v[i]; > } else { > v[i] = (int)v[i] + 1; > } > } > } > */ > //unlagged - attack prediction #3 173a179,183 > //unlagged - attack prediction #2 > // we have to use something now that the client knows in advance > int seed = ent->client->attackTime % 256; > //unlagged - attack prediction #2 > 176,178c186,197 < r = random() * M_PI * 2.0f; < u = sin(r) * crandom() * spread * 16; < r = cos(r) * crandom() * spread * 16; --- > //unlagged - attack prediction #2 > // this has to match what's on the client > /* > r = random() * M_PI * 2.0f; > u = sin(r) * crandom() * spread * 16; > r = cos(r) * crandom() * spread * 16; > */ > r = Q_random(&seed) * M_PI * 2.0f; > u = sin(r) * Q_crandom(&seed) * spread * 16; > r = cos(r) * Q_crandom(&seed) * spread * 16; > //unlagged - attack prediction #2 > 185a205,209 > //unlagged - backward reconciliation #2 > // backward-reconcile the other clients > G_DoTimeShiftFor( ent ); > //unlagged - backward reconciliation #2 > 199a224,228 > //unlagged - attack prediction #2 > // we need the client number to determine whether or not to > // suppress this event > tent->s.clientNum = ent->s.clientNum; > //unlagged - attack prediction #2 205a235,239 > //unlagged - attack prediction #2 > // we need the client number to determine whether or not to > // suppress this event > tent->s.clientNum = ent->s.clientNum; > //unlagged - attack prediction #2 332a367,371 > //unlagged - attack prediction #2 > // use this for testing > //Com_Printf( "Server seed: %d\n", seed ); > //unlagged - attack prediction #2 > 340a380,384 > //unlagged - backward reconciliation #2 > // backward-reconcile the other clients > G_DoTimeShiftFor( ent ); > //unlagged - backward reconciliation #2 > 352a397,401 > > //unlagged - backward reconciliation #2 > // put them back > G_UndoTimeShiftFor( ent ); > //unlagged - backward reconciliation #2 363c412,417 < tent->s.eventParm = rand() & 255; // seed for spread pattern --- > //Sago: This sound like a bad idea... > //unlagged - attack prediction #2 > // this has to be something the client can predict now > //tent->s.eventParm = rand() & 255; // seed for spread pattern > tent->s.eventParm = ent->client->attackTime % 256; // seed for spread pattern > //unlagged - attack prediction #2 464a519,523 > //unlagged - backward reconciliation #2 > // backward-reconcile the other clients > G_DoTimeShiftFor( ent ); > //unlagged - backward reconciliation #2 > 518a578,582 > //unlagged - backward reconciliation #2 > // put them back > G_UndoTimeShiftFor( ent ); > //unlagged - backward reconciliation #2 > 626c690,695 < damage = 8 * s_quadFactor; --- > //Sago: This sound like a workaround for the lightning killing people before they know it > //unlagged - server options > // this is configurable now > // damage = 8 * s_quadFactor; > damage = g_lightningDamage.integer * s_quadFactor; > //unlagged - server options 631a701,706 > //Sago: I'm not sure this should recieve backward reconciliation. It is not a real instant hit weapon, it can normally be dogded > //unlagged - backward reconciliation #2 > // backward-reconcile the other clients > G_DoTimeShiftFor( ent ); > //unlagged - backward reconciliation #2 > 633a709,713 > //unlagged - backward reconciliation #2 > // put them back > G_UndoTimeShiftFor( ent ); > //unlagged - backward reconciliation #2 > diff -r openArenaEliminationB15/code/q3_ui/ui_main.c openArenaEliminationB16/code/q3_ui/ui_main.c 118d117 < vmCvar_t ui_elimination_friendly; 122d120 < vmCvar_t ui_ctf_elimination_friendly; 186,192c184,185 < { &ui_team_fraglimit, "ui_elimination_capturelimit", "0", CVAR_ARCHIVE }, < { &ui_team_timelimit, "ui_elimination_timelimit", "20", CVAR_ARCHIVE }, < { &ui_team_friendly, "ui_elimination_friendly", "1", CVAR_ARCHIVE }, < < { &ui_ctf_capturelimit, "ui_ctf_elimination_capturelimit", "8", CVAR_ARCHIVE }, < { &ui_ctf_timelimit, "ui_ctf_elimination_timelimit", "30", CVAR_ARCHIVE }, < { &ui_ctf_friendly, "ui_ctf_elimination_friendly", "0", CVAR_ARCHIVE }, --- > { &ui_elimination_capturelimit, "ui_elimination_capturelimit", "8", CVAR_ARCHIVE }, > { &ui_elimination_timelimit, "ui_elimination_timelimit", "20", CVAR_ARCHIVE }, 194,195c187,191 < { &ui_ffa_fraglimit, "ui_lms_fraglimit", "20", CVAR_ARCHIVE }, < { &ui_ffa_timelimit, "ui_lms_timelimit", "0", CVAR_ARCHIVE }, --- > { &ui_ctf_elimination_capturelimit, "ui_ctf_elimination_capturelimit", "8", CVAR_ARCHIVE }, > { &ui_ctf_elimination_timelimit, "ui_ctf_elimination_timelimit", "30", CVAR_ARCHIVE }, > > { &ui_lms_fraglimit, "ui_lms_fraglimit", "20", CVAR_ARCHIVE }, > { &ui_lms_timelimit, "ui_lms_timelimit", "0", CVAR_ARCHIVE }, diff -r openArenaEliminationB15/code/q3_ui/ui_sound.c openArenaEliminationB16/code/q3_ui/ui_sound.c 47c47,49 < #define ID_BACK 18 --- > //Sago: Here I do some stuff! > #define ID_OPENAL 18 > #define ID_BACK 19 69a72 > menuradiobutton_s openal; 136a140,150 > > case ID_OPENAL: > if( soundOptionsInfo.openal.curvalue ) { > trap_Cmd_ExecuteText( EXEC_NOW, "s_useopenal 1\n" ); > } > else { > trap_Cmd_ExecuteText( EXEC_NOW, "s_useopenal 0\n" ); > } > soundOptionsInfo.openal.curvalue = (int)trap_Cvar_VariableValue( "s_useopenal" ); > break; > 262a277,285 > y += BIGCHAR_HEIGHT+2; > soundOptionsInfo.openal.generic.type = MTYPE_RADIOBUTTON; > soundOptionsInfo.openal.generic.name = "OpenAL:"; > soundOptionsInfo.openal.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; > soundOptionsInfo.openal.generic.callback = UI_SoundOptionsMenu_Event; > soundOptionsInfo.openal.generic.id = ID_OPENAL; > soundOptionsInfo.openal.generic.x = 400; > soundOptionsInfo.openal.generic.y = y; > 284a308 > Menu_AddItem( &soundOptionsInfo.menu, ( void * ) &soundOptionsInfo.openal ); 290a315 > soundOptionsInfo.openal.curvalue = (int)trap_Cvar_VariableValue( "s_useopenal" ); diff -r openArenaEliminationB15/code/q3_ui/ui_startserver.c openArenaEliminationB16/code/q3_ui/ui_startserver.c 826c826 < trap_Cvar_SetValue( "ui_elimination_friendlt", friendlyfire ); --- > //trap_Cvar_SetValue( "ui_elimination_friendlt", friendlyfire ); 832c832 < trap_Cvar_SetValue( "ui_ctf_elimination_friendlt", friendlyfire ); --- > //trap_Cvar_SetValue( "ui_ctf_elimination_friendlt", friendlyfire ); 1223c1223 < s_serveroptions.friendlyfire.curvalue = (int)Com_Clamp( 0, 1, trap_Cvar_VariableValue( "ui_elimination_friendly" ) ); --- > //s_serveroptions.friendlyfire.curvalue = (int)Com_Clamp( 0, 1, trap_Cvar_VariableValue( "ui_elimination_friendly" ) ); 1229c1229 < s_serveroptions.friendlyfire.curvalue = (int)Com_Clamp( 0, 1, trap_Cvar_VariableValue( "ui_ctf_elimination_friendly" ) ); --- > //s_serveroptions.friendlyfire.curvalue = (int)Com_Clamp( 0, 1, trap_Cvar_VariableValue( "ui_ctf_elimination_friendly" ) ); 1359c1359 < if( s_serveroptions.gametype < GT_CTF ) { --- > if( s_serveroptions.gametype < GT_CTF || s_serveroptions.gametype== GT_LMS) { 1390c1390 < if( s_serveroptions.gametype >= GT_TEAM && s_serveroptions.gametype != GT_LMS) { --- > if( s_serveroptions.gametype >= GT_TEAM && s_serveroptions.gametype != GT_LMS && s_serveroptions.gametype != GT_ELIMINATION && s_serveroptions.gametype != GT_CTF_ELIMINATION) { 1429c1429 < y += BIGCHAR_HEIGHT+2; --- > /*y += BIGCHAR_HEIGHT+2; 1436c1436 < s_serveroptions.punkbuster.itemnames = punkbuster_items; --- > s_serveroptions.punkbuster.itemnames = punkbuster_items;*/ 1539c1539 < if( s_serveroptions.gametype < GT_CTF ) { --- > if( s_serveroptions.gametype < GT_CTF || s_serveroptions.gametype == GT_LMS ) { 1546c1546 < if( s_serveroptions.gametype >= GT_TEAM && s_serveroptions.gametype != GT_LMS ) { --- > if( s_serveroptions.gametype >= GT_TEAM && s_serveroptions.gametype != GT_LMS && s_serveroptions.gametype != GT_ELIMINATION && s_serveroptions.gametype != GT_CTF_ELIMINATION) { 1561c1561 < Menu_AddItem( &s_serveroptions.menu, (void*) &s_serveroptions.punkbuster ); --- > //Menu_AddItem( &s_serveroptions.menu, (void*) &s_serveroptions.punkbuster ); diff -r openArenaEliminationB15/code/qcommon/q_shared.c openArenaEliminationB16/code/qcommon/q_shared.c 1264a1265,1289 > //unlagged - attack prediction #3 > // moved from g_weapon.c > /* > ====================== > SnapVectorTowards > > Round a vector to integers for more efficient network > transmission, but make sure that it rounds towards a given point > rather than blindly truncating. This prevents it from truncating > into a wall. > ====================== > */ > void SnapVectorTowards( vec3_t v, vec3_t to ) { > int i; > > for ( i = 0 ; i < 3 ; i++ ) { > if ( to[i] <= v[i] ) { > v[i] = (int)v[i]; > } else { > v[i] = (int)v[i] + 1; > } > } > } > //unlagged - attack prediction #3 > diff -r openArenaEliminationB15/code/qcommon/q_shared.h openArenaEliminationB16/code/qcommon/q_shared.h 40a41,44 > //unlagged - lag simulation #2 > #define MAX_LATENT_CMDS 64 > //unlagged - lag simulation #2 > 450a455,460 > > //unlagged - attack prediction #3 > // moved from g_weapon.c > void SnapVectorTowards( vec3_t v, vec3_t to ); > //unlagged - attack prediction #3 >