00001
00002
00003
00004
00005
00006
00007
00008 #include "cg_local.h"
00009
00010
00011
00012
00013
00014
00015
00016
00017 void CG_CheckAmmo( void ) {
00018 #if 0
00019 int i;
00020 int total;
00021 int previous;
00022 int weapons;
00023
00024
00025 weapons = cg.snap->ps.stats[ STAT_WEAPONS ];
00026 total = 0;
00027 for ( i = WP_BRYAR_PISTOL; i < WP_NUM_WEAPONS ; i++ ) {
00028 if ( ! ( weapons & ( 1 << i ) ) ) {
00029 continue;
00030 }
00031 switch ( i )
00032 {
00033 case WP_BRYAR_PISTOL:
00034 case WP_CONCUSSION:
00035 case WP_BRYAR_OLD:
00036 case WP_BLASTER:
00037 case WP_DISRUPTOR:
00038 case WP_BOWCASTER:
00039 case WP_REPEATER:
00040 case WP_DEMP2:
00041 case WP_FLECHETTE:
00042 case WP_ROCKET_LAUNCHER:
00043 case WP_THERMAL:
00044 case WP_TRIP_MINE:
00045 case WP_DET_PACK:
00046 case WP_EMPLACED_GUN:
00047 total += cg.snap->ps.ammo[weaponData[i].ammoIndex] * 1000;
00048 break;
00049 default:
00050 total += cg.snap->ps.ammo[weaponData[i].ammoIndex] * 200;
00051 break;
00052 }
00053 if ( total >= 5000 ) {
00054 cg.lowAmmoWarning = 0;
00055 return;
00056 }
00057 }
00058
00059 previous = cg.lowAmmoWarning;
00060
00061 if ( total == 0 ) {
00062 cg.lowAmmoWarning = 2;
00063 } else {
00064 cg.lowAmmoWarning = 1;
00065 }
00066
00067 if (cg.snap->ps.weapon == WP_SABER)
00068 {
00069 cg.lowAmmoWarning = 0;
00070 }
00071
00072
00073 if ( cg.lowAmmoWarning != previous ) {
00074 trap_S_StartLocalSound( cgs.media.noAmmoSound, CHAN_LOCAL_SOUND );
00075 }
00076 #endif
00077
00078 }
00079
00080
00081
00082
00083
00084
00085 void CG_DamageFeedback( int yawByte, int pitchByte, int damage ) {
00086 float left, front, up;
00087 float kick;
00088 int health;
00089 float scale;
00090 vec3_t dir;
00091 vec3_t angles;
00092 float dist;
00093 float yaw, pitch;
00094
00095
00096 cg.attackerTime = cg.time;
00097
00098
00099 health = cg.snap->ps.stats[STAT_HEALTH];
00100 if ( health < 40 ) {
00101 scale = 1;
00102 } else {
00103 scale = 40.0 / health;
00104 }
00105 kick = damage * scale;
00106
00107 if (kick < 5)
00108 kick = 5;
00109 if (kick > 10)
00110 kick = 10;
00111
00112
00113 if ( yawByte == 255 && pitchByte == 255 ) {
00114 cg.damageX = 0;
00115 cg.damageY = 0;
00116 cg.v_dmg_roll = 0;
00117 cg.v_dmg_pitch = -kick;
00118 } else {
00119
00120 pitch = pitchByte / 255.0 * 360;
00121 yaw = yawByte / 255.0 * 360;
00122
00123 angles[PITCH] = pitch;
00124 angles[YAW] = yaw;
00125 angles[ROLL] = 0;
00126
00127 AngleVectors( angles, dir, NULL, NULL );
00128 VectorSubtract( vec3_origin, dir, dir );
00129
00130 front = DotProduct (dir, cg.refdef.viewaxis[0] );
00131 left = DotProduct (dir, cg.refdef.viewaxis[1] );
00132 up = DotProduct (dir, cg.refdef.viewaxis[2] );
00133
00134 dir[0] = front;
00135 dir[1] = left;
00136 dir[2] = 0;
00137 dist = VectorLength( dir );
00138 if ( dist < 0.1 ) {
00139 dist = 0.1f;
00140 }
00141
00142 cg.v_dmg_roll = kick * left;
00143
00144 cg.v_dmg_pitch = -kick * front;
00145
00146 if ( front <= 0.1 ) {
00147 front = 0.1f;
00148 }
00149 cg.damageX = -left / front;
00150 cg.damageY = up / dist;
00151 }
00152
00153
00154 if ( cg.damageX > 1.0 ) {
00155 cg.damageX = 1.0;
00156 }
00157 if ( cg.damageX < - 1.0 ) {
00158 cg.damageX = -1.0;
00159 }
00160
00161 if ( cg.damageY > 1.0 ) {
00162 cg.damageY = 1.0;
00163 }
00164 if ( cg.damageY < - 1.0 ) {
00165 cg.damageY = -1.0;
00166 }
00167
00168
00169 if ( kick > 10 ) {
00170 kick = 10;
00171 }
00172 cg.damageValue = kick;
00173 cg.v_dmg_time = cg.time + DAMAGE_TIME;
00174 cg.damageTime = cg.snap->serverTime;
00175
00176
00177 #ifdef _XBOX
00178 extern void FF_XboxShake(float intensity, int duration);
00179 extern void FF_XboxDamage(int damage, float xpos);
00180
00181
00182 FF_XboxDamage(damage, -left);
00183
00184
00185 #endif
00186
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 void CG_Respawn( void ) {
00200
00201 cg.thisFrameTeleport = qtrue;
00202
00203
00204 cg.weaponSelectTime = cg.time;
00205
00206
00207 cg.weaponSelect = cg.snap->ps.weapon;
00208 }
00209
00210 extern char *eventnames[];
00211
00212
00213
00214
00215
00216
00217 void CG_CheckPlayerstateEvents( playerState_t *ps, playerState_t *ops ) {
00218 int i;
00219 int event;
00220 centity_t *cent;
00221
00222 if ( ps->externalEvent && ps->externalEvent != ops->externalEvent ) {
00223 cent = &cg_entities[ ps->clientNum ];
00224 cent->currentState.event = ps->externalEvent;
00225 cent->currentState.eventParm = ps->externalEventParm;
00226 CG_EntityEvent( cent, cent->lerpOrigin );
00227 }
00228
00229 cent = &cg_entities[ ps->clientNum ];
00230
00231 for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ ) {
00232
00233 if ( i >= ops->eventSequence
00234
00235
00236 || (i > ops->eventSequence - MAX_PS_EVENTS && ps->events[i & (MAX_PS_EVENTS-1)] != ops->events[i & (MAX_PS_EVENTS-1)]) ) {
00237
00238 event = ps->events[ i & (MAX_PS_EVENTS-1) ];
00239 cent->currentState.event = event;
00240 cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
00241
00242 cent->playerState = ps;
00243 CG_EntityEvent( cent, cent->lerpOrigin );
00244
00245 cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
00246
00247 cg.eventSequence++;
00248 }
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257 void CG_CheckChangedPredictableEvents( playerState_t *ps ) {
00258 int i;
00259 int event;
00260 centity_t *cent;
00261
00262 cent = &cg_entities[ps->clientNum];
00263 for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ ) {
00264
00265 if (i >= cg.eventSequence) {
00266 continue;
00267 }
00268
00269 if (i > cg.eventSequence - MAX_PREDICTED_EVENTS) {
00270
00271 if ( ps->events[i & (MAX_PS_EVENTS-1)] != cg.predictableEvents[i & (MAX_PREDICTED_EVENTS-1) ] ) {
00272
00273 event = ps->events[ i & (MAX_PS_EVENTS-1) ];
00274 cent->currentState.event = event;
00275 cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
00276 CG_EntityEvent( cent, cent->lerpOrigin );
00277
00278 cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
00279
00280 if ( cg_showmiss.integer ) {
00281 CG_Printf("WARNING: changed predicted event\n");
00282 }
00283 }
00284 }
00285 }
00286 }
00287
00288
00289
00290
00291
00292
00293 #ifdef JK2AWARDS
00294 static void pushReward(sfxHandle_t sfx, qhandle_t shader, int rewardCount) {
00295 if (cg.rewardStack < (MAX_REWARDSTACK-1)) {
00296 cg.rewardStack++;
00297 cg.rewardSound[cg.rewardStack] = sfx;
00298 cg.rewardShader[cg.rewardStack] = shader;
00299 cg.rewardCount[cg.rewardStack] = rewardCount;
00300 }
00301 }
00302 #endif
00303
00304 int cgAnnouncerTime = 0;
00305
00306
00307
00308
00309
00310
00311 void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) {
00312 int highScore, health, armor, reward;
00313 #ifdef JK2AWARDS
00314 sfxHandle_t sfx;
00315 #endif
00316
00317
00318 if ( ps->persistant[PERS_TEAM] != ops->persistant[PERS_TEAM] ) {
00319 return;
00320 }
00321
00322
00323 if ( ps->persistant[PERS_HITS] > ops->persistant[PERS_HITS] ) {
00324 armor = ps->persistant[PERS_ATTACKEE_ARMOR] & 0xff;
00325 health = ps->persistant[PERS_ATTACKEE_ARMOR] >> 8;
00326
00327 if (armor > health/2)
00328 {
00329
00330 }
00331 else
00332 {
00333
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 } else if ( ps->persistant[PERS_HITS] < ops->persistant[PERS_HITS] ) {
00347
00348 }
00349
00350
00351 if (cg_oldPainSounds.integer)
00352 {
00353 if ( ps->stats[STAT_HEALTH] < (ops->stats[STAT_HEALTH] - 3))
00354 {
00355 if ( ps->stats[STAT_HEALTH] > 0 )
00356 {
00357 CG_PainEvent( &cg_entities[cg.predictedPlayerState.clientNum], ps->stats[STAT_HEALTH] );
00358 }
00359 }
00360 }
00361
00362
00363 if ( cg.intermissionStarted ) {
00364 return;
00365 }
00366
00367 #ifdef JK2AWARDS
00368
00369 reward = qfalse;
00370 if (ps->persistant[PERS_CAPTURES] != ops->persistant[PERS_CAPTURES]) {
00371 pushReward(cgs.media.captureAwardSound, cgs.media.medalCapture, ps->persistant[PERS_CAPTURES]);
00372 reward = qtrue;
00373
00374 }
00375 if (ps->persistant[PERS_IMPRESSIVE_COUNT] != ops->persistant[PERS_IMPRESSIVE_COUNT]) {
00376 sfx = cgs.media.impressiveSound;
00377
00378 pushReward(sfx, cgs.media.medalImpressive, ps->persistant[PERS_IMPRESSIVE_COUNT]);
00379 reward = qtrue;
00380
00381 }
00382 if (ps->persistant[PERS_EXCELLENT_COUNT] != ops->persistant[PERS_EXCELLENT_COUNT]) {
00383 sfx = cgs.media.excellentSound;
00384 pushReward(sfx, cgs.media.medalExcellent, ps->persistant[PERS_EXCELLENT_COUNT]);
00385 reward = qtrue;
00386
00387 }
00388 if (ps->persistant[PERS_GAUNTLET_FRAG_COUNT] != ops->persistant[PERS_GAUNTLET_FRAG_COUNT]) {
00389 sfx = cgs.media.humiliationSound;
00390 pushReward(sfx, cgs.media.medalGauntlet, ps->persistant[PERS_GAUNTLET_FRAG_COUNT]);
00391 reward = qtrue;
00392
00393 }
00394 if (ps->persistant[PERS_DEFEND_COUNT] != ops->persistant[PERS_DEFEND_COUNT]) {
00395 pushReward(cgs.media.defendSound, cgs.media.medalDefend, ps->persistant[PERS_DEFEND_COUNT]);
00396 reward = qtrue;
00397
00398 }
00399 if (ps->persistant[PERS_ASSIST_COUNT] != ops->persistant[PERS_ASSIST_COUNT]) {
00400
00401
00402
00403 }
00404
00405 if (ps->persistant[PERS_PLAYEREVENTS] != ops->persistant[PERS_PLAYEREVENTS]) {
00406 if ((ps->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_DENIEDREWARD) !=
00407 (ops->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_DENIEDREWARD)) {
00408 trap_S_StartLocalSound( cgs.media.deniedSound, CHAN_ANNOUNCER );
00409 }
00410 else if ((ps->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_GAUNTLETREWARD) !=
00411 (ops->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_GAUNTLETREWARD)) {
00412 trap_S_StartLocalSound( cgs.media.humiliationSound, CHAN_ANNOUNCER );
00413 }
00414 reward = qtrue;
00415 }
00416 #else
00417 reward = qfalse;
00418 #endif
00419
00420 if (!reward && cgAnnouncerTime < cg.time) {
00421
00422 if ( !cg.warmup && cgs.gametype != GT_POWERDUEL ) {
00423
00424 if ( ps->persistant[PERS_RANK] != ops->persistant[PERS_RANK] ) {
00425 if ( cgs.gametype < GT_TEAM) {
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 }
00443 }
00444 }
00445 }
00446
00447
00448 if ( cgs.timelimit > 0 && cgAnnouncerTime < cg.time ) {
00449 int msec;
00450
00451 msec = cg.time - cgs.levelStartTime;
00452 if ( !( cg.timelimitWarnings & 4 ) && msec > ( cgs.timelimit * 60 + 2 ) * 1000 ) {
00453 cg.timelimitWarnings |= 1 | 2 | 4;
00454
00455 }
00456 else if ( !( cg.timelimitWarnings & 2 ) && msec > (cgs.timelimit - 1) * 60 * 1000 ) {
00457 cg.timelimitWarnings |= 1 | 2;
00458 trap_S_StartLocalSound( cgs.media.oneMinuteSound, CHAN_ANNOUNCER );
00459 cgAnnouncerTime = cg.time + 3000;
00460 }
00461 else if ( cgs.timelimit > 5 && !( cg.timelimitWarnings & 1 ) && msec > (cgs.timelimit - 5) * 60 * 1000 ) {
00462 cg.timelimitWarnings |= 1;
00463 trap_S_StartLocalSound( cgs.media.fiveMinuteSound, CHAN_ANNOUNCER );
00464 cgAnnouncerTime = cg.time + 3000;
00465 }
00466 }
00467
00468
00469 if ( cgs.fraglimit > 0 && cgs.gametype < GT_CTF && cgs.gametype != GT_DUEL && cgs.gametype != GT_POWERDUEL && cgs.gametype != GT_SIEGE && cgAnnouncerTime < cg.time) {
00470 highScore = cgs.scores1;
00471 if ( !( cg.fraglimitWarnings & 4 ) && highScore == (cgs.fraglimit - 1) ) {
00472 cg.fraglimitWarnings |= 1 | 2 | 4;
00473 CG_AddBufferedSound(cgs.media.oneFragSound);
00474 cgAnnouncerTime = cg.time + 3000;
00475 }
00476 else if ( cgs.fraglimit > 2 && !( cg.fraglimitWarnings & 2 ) && highScore == (cgs.fraglimit - 2) ) {
00477 cg.fraglimitWarnings |= 1 | 2;
00478 CG_AddBufferedSound(cgs.media.twoFragSound);
00479 cgAnnouncerTime = cg.time + 3000;
00480 }
00481 else if ( cgs.fraglimit > 3 && !( cg.fraglimitWarnings & 1 ) && highScore == (cgs.fraglimit - 3) ) {
00482 cg.fraglimitWarnings |= 1;
00483 CG_AddBufferedSound(cgs.media.threeFragSound);
00484 cgAnnouncerTime = cg.time + 3000;
00485 }
00486 }
00487 }
00488
00489
00490
00491
00492
00493
00494
00495 void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops ) {
00496
00497 if ( ps->clientNum != ops->clientNum ) {
00498 cg.thisFrameTeleport = qtrue;
00499
00500 *ops = *ps;
00501 }
00502
00503
00504 if ( ps->damageEvent != ops->damageEvent && ps->damageCount ) {
00505 CG_DamageFeedback( ps->damageYaw, ps->damagePitch, ps->damageCount );
00506 }
00507
00508
00509 if ( ps->persistant[PERS_SPAWN_COUNT] != ops->persistant[PERS_SPAWN_COUNT] ) {
00510 CG_Respawn();
00511 }
00512
00513 if ( cg.mapRestart ) {
00514 CG_Respawn();
00515 cg.mapRestart = qfalse;
00516 }
00517
00518 if ( cg.snap->ps.pm_type != PM_INTERMISSION
00519 && ps->persistant[PERS_TEAM] != TEAM_SPECTATOR ) {
00520 CG_CheckLocalSounds( ps, ops );
00521 }
00522
00523
00524 CG_CheckAmmo();
00525
00526
00527 CG_CheckPlayerstateEvents( ps, ops );
00528
00529
00530 if ( ps->viewheight != ops->viewheight ) {
00531 cg.duckChange = ps->viewheight - ops->viewheight;
00532 cg.duckTime = cg.time;
00533 }
00534 }
00535