codemp/cgame/cg_event.c

Go to the documentation of this file.
00001 // Copyright (C) 1999-2000 Id Software, Inc.
00002 //
00003 // cg_event.c -- handle entity events at snapshot or playerstate transitions
00004 
00005 #include "cg_local.h"
00006 #include "fx_local.h"
00007 #include "../ui/ui_shared.h"
00008 #include "../ui/ui_public.h"
00009 
00010 // for the voice chats
00011 #include "../../ui/menudef.h"
00012 
00013 #include "../ghoul2/G2.h"
00014 //==========================================================================
00015 
00016 extern qboolean WP_SaberBladeUseSecondBladeStyle( saberInfo_t *saber, int bladeNum );
00017 extern qboolean CG_VehicleWeaponImpact( centity_t *cent );
00018 extern qboolean CG_InFighter( void );
00019 extern qboolean CG_InATST( void );
00020 extern int cg_saberFlashTime;
00021 extern vec3_t cg_saberFlashPos;
00022 extern char *showPowersName[];
00023 
00024 extern int cg_siegeDeathTime;
00025 extern int cg_siegeDeathDelay;
00026 extern int cg_vehicleAmmoWarning;
00027 extern int cg_vehicleAmmoWarningTime;
00028 
00029 //I know, not siege, but...
00030 typedef enum
00031 {
00032         TAUNT_TAUNT = 0,
00033         TAUNT_BOW,
00034         TAUNT_MEDITATE,
00035         TAUNT_FLOURISH,
00036         TAUNT_GLOAT
00037 };
00038 /*
00039 ===================
00040 CG_PlaceString
00041 
00042 Also called by scoreboard drawing
00043 ===================
00044 */
00045 const char      *CG_PlaceString( int rank ) {
00046         static char     str[64];
00047         char    *s, *t;
00048         // number extenstions, eg 1st, 2nd, 3rd, 4th etc.
00049         // note that the rules are different for french, but by changing the required strip strings they seem to work
00050         char sST[10];
00051         char sND[10];
00052         char sRD[10];
00053         char sTH[10];
00054         char sTiedFor[64];      // german is much longer, super safe...
00055 
00056         trap_SP_GetStringTextString("MP_INGAME_NUMBER_ST",sST, sizeof(sST) );
00057         trap_SP_GetStringTextString("MP_INGAME_NUMBER_ND",sND, sizeof(sND) );
00058         trap_SP_GetStringTextString("MP_INGAME_NUMBER_RD",sRD, sizeof(sRD) );
00059         trap_SP_GetStringTextString("MP_INGAME_NUMBER_TH",sTH, sizeof(sTH) );
00060         trap_SP_GetStringTextString("MP_INGAME_TIED_FOR" ,sTiedFor,sizeof(sTiedFor) );
00061         strcat(sTiedFor," ");   // save worrying about translators adding spaces or not
00062 
00063         if ( rank & RANK_TIED_FLAG ) {
00064                 rank &= ~RANK_TIED_FLAG;
00065                 t = sTiedFor;//"Tied for ";
00066         } else {
00067                 t = "";
00068         }
00069 
00070         if ( rank == 1 ) {
00071                 s = va("1%s",sST);//S_COLOR_BLUE "1st" S_COLOR_WHITE;           // draw in blue
00072         } else if ( rank == 2 ) {
00073                 s = va("2%s",sND);//S_COLOR_RED "2nd" S_COLOR_WHITE;            // draw in red
00074         } else if ( rank == 3 ) {
00075                 s = va("3%s",sRD);//S_COLOR_YELLOW "3rd" S_COLOR_WHITE;         // draw in yellow
00076         } else if ( rank == 11 ) {
00077                 s = va("11%s",sTH);
00078         } else if ( rank == 12 ) {
00079                 s = va("12%s",sTH);
00080         } else if ( rank == 13 ) {
00081                 s = va("13%s",sTH);
00082         } else if ( rank % 10 == 1 ) {
00083                 s = va("%i%s", rank,sST);
00084         } else if ( rank % 10 == 2 ) {
00085                 s = va("%i%s", rank,sND);
00086         } else if ( rank % 10 == 3 ) {
00087                 s = va("%i%s", rank,sRD);
00088         } else {
00089                 s = va("%i%s", rank,sTH);
00090         }
00091 
00092         Com_sprintf( str, sizeof( str ), "%s%s", t, s );
00093         return str;
00094 }
00095 
00096 qboolean CG_ThereIsAMaster(void);
00097 
00098 /*
00099 =============
00100 CG_Obituary
00101 =============
00102 */
00103 static void CG_Obituary( entityState_t *ent ) {
00104         int                     mod;
00105         int                     target, attacker;
00106         char            *message;
00107         const char      *targetInfo;
00108         const char      *attackerInfo;
00109         char            targetName[32];
00110         char            attackerName[32];
00111         gender_t        gender;
00112         clientInfo_t    *ci;
00113 
00114 
00115         target = ent->otherEntityNum;
00116         attacker = ent->otherEntityNum2;
00117         mod = ent->eventParm;
00118 
00119         if ( target < 0 || target >= MAX_CLIENTS ) {
00120                 CG_Error( "CG_Obituary: target out of range" );
00121         }
00122         ci = &cgs.clientinfo[target];
00123 
00124         if ( attacker < 0 || attacker >= MAX_CLIENTS ) {
00125                 attacker = ENTITYNUM_WORLD;
00126                 attackerInfo = NULL;
00127         } else {
00128                 attackerInfo = CG_ConfigString( CS_PLAYERS + attacker );
00129         }
00130 
00131         targetInfo = CG_ConfigString( CS_PLAYERS + target );
00132         if ( !targetInfo ) {
00133                 return;
00134         }
00135         Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof(targetName) - 2);
00136         strcat( targetName, S_COLOR_WHITE );
00137 
00138         // check for single client messages
00139 
00140         switch( mod ) {
00141         case MOD_SUICIDE:
00142         case MOD_FALLING:
00143         case MOD_CRUSH:
00144         case MOD_WATER:
00145         case MOD_SLIME:
00146         case MOD_LAVA:
00147         case MOD_TRIGGER_HURT:
00148                 message = "DIED_GENERIC";
00149                 break;
00150         case MOD_TARGET_LASER:
00151                 message = "DIED_LASER";
00152                 break;
00153         default:
00154                 message = NULL;
00155                 break;
00156         }
00157 
00158         // Attacker killed themselves.  Ridicule them for it.
00159         if (attacker == target) {
00160                 gender = ci->gender;
00161                 switch (mod) {
00162                 case MOD_BRYAR_PISTOL:
00163                 case MOD_BRYAR_PISTOL_ALT:
00164                 case MOD_BLASTER:
00165                 case MOD_TURBLAST:
00166                 case MOD_DISRUPTOR:
00167                 case MOD_DISRUPTOR_SPLASH:
00168                 case MOD_DISRUPTOR_SNIPER:
00169                 case MOD_BOWCASTER:
00170                 case MOD_REPEATER:
00171                 case MOD_REPEATER_ALT:
00172                 case MOD_FLECHETTE:
00173                         if ( gender == GENDER_FEMALE )
00174                                 message = "SUICIDE_SHOT_FEMALE";
00175                         else if ( gender == GENDER_NEUTER )
00176                                 message = "SUICIDE_SHOT_GENDERLESS";
00177                         else
00178                                 message = "SUICIDE_SHOT_MALE";
00179                         break;
00180                 case MOD_REPEATER_ALT_SPLASH:
00181                 case MOD_FLECHETTE_ALT_SPLASH:
00182                 case MOD_ROCKET:
00183                 case MOD_ROCKET_SPLASH:
00184                 case MOD_ROCKET_HOMING:
00185                 case MOD_ROCKET_HOMING_SPLASH:
00186                 case MOD_THERMAL:
00187                 case MOD_THERMAL_SPLASH:
00188                 case MOD_TRIP_MINE_SPLASH:
00189                 case MOD_TIMED_MINE_SPLASH:
00190                 case MOD_DET_PACK_SPLASH:
00191                 case MOD_VEHICLE:
00192                 case MOD_CONC:
00193                 case MOD_CONC_ALT:
00194                         if ( gender == GENDER_FEMALE )
00195                                 message = "SUICIDE_EXPLOSIVES_FEMALE";
00196                         else if ( gender == GENDER_NEUTER )
00197                                 message = "SUICIDE_EXPLOSIVES_GENDERLESS";
00198                         else
00199                                 message = "SUICIDE_EXPLOSIVES_MALE";
00200                         break;
00201                 case MOD_DEMP2:
00202                         if ( gender == GENDER_FEMALE )
00203                                 message = "SUICIDE_ELECTROCUTED_FEMALE";
00204                         else if ( gender == GENDER_NEUTER )
00205                                 message = "SUICIDE_ELECTROCUTED_GENDERLESS";
00206                         else
00207                                 message = "SUICIDE_ELECTROCUTED_MALE";
00208                         break;
00209                 case MOD_FALLING:
00210                         if ( gender == GENDER_FEMALE )
00211                                 message = "SUICIDE_FALLDEATH_FEMALE";
00212                         else if ( gender == GENDER_NEUTER )
00213                                 message = "SUICIDE_FALLDEATH_GENDERLESS";
00214                         else
00215                                 message = "SUICIDE_FALLDEATH_MALE";
00216                         break;
00217                 default:
00218                         if ( gender == GENDER_FEMALE )
00219                                 message = "SUICIDE_GENERICDEATH_FEMALE";
00220                         else if ( gender == GENDER_NEUTER )
00221                                 message = "SUICIDE_GENERICDEATH_GENDERLESS";
00222                         else
00223                                 message = "SUICIDE_GENERICDEATH_MALE";
00224                         break;
00225                 }
00226         }
00227 
00228         if (target != attacker && target < MAX_CLIENTS && attacker < MAX_CLIENTS)
00229         {
00230                 goto clientkilled;
00231         }
00232 
00233         if (message) {
00234                 gender = ci->gender;
00235 
00236                 if (!message[0])
00237                 {
00238                         if ( gender == GENDER_FEMALE )
00239                                 message = "SUICIDE_GENERICDEATH_FEMALE";
00240                         else if ( gender == GENDER_NEUTER )
00241                                 message = "SUICIDE_GENERICDEATH_GENDERLESS";
00242                         else
00243                                 message = "SUICIDE_GENERICDEATH_MALE";
00244                 }
00245                 message = (char *)CG_GetStringEdString("MP_INGAME", message);
00246 
00247                 CG_Printf( "%s %s\n", targetName, message);
00248                 return;
00249         }
00250 
00251 clientkilled:
00252 
00253         // check for kill messages from the current clientNum
00254         if ( attacker == cg.snap->ps.clientNum ) {
00255                 char    *s;
00256 
00257                 if ( cgs.gametype < GT_TEAM && cgs.gametype != GT_DUEL && cgs.gametype != GT_POWERDUEL ) {
00258                         if (cgs.gametype == GT_JEDIMASTER &&
00259                                 attacker < MAX_CLIENTS &&
00260                                 !ent->isJediMaster &&
00261                                 !cg.snap->ps.isJediMaster &&
00262                                 CG_ThereIsAMaster())
00263                         {
00264                                 char part1[512];
00265                                 char part2[512];
00266                                 trap_SP_GetStringTextString("MP_INGAME_KILLED_MESSAGE", part1, sizeof(part1));
00267                                 trap_SP_GetStringTextString("MP_INGAME_JMKILLED_NOTJM", part2, sizeof(part2));
00268                                 s = va("%s %s\n%s\n", part1, targetName, part2);
00269                         }
00270                         else if (cgs.gametype == GT_JEDIMASTER &&
00271                                 attacker < MAX_CLIENTS &&
00272                                 !ent->isJediMaster &&
00273                                 !cg.snap->ps.isJediMaster)
00274                         { //no JM, saber must be out
00275                                 char part1[512];
00276                                 trap_SP_GetStringTextString("MP_INGAME_KILLED_MESSAGE", part1, sizeof(part1));
00277                                 /*
00278                                 kmsg1 = "for 0 points.\nGo for the saber!";
00279                                 strcpy(part2, kmsg1);
00280 
00281                                 s = va("%s %s %s\n", part1, targetName, part2);
00282                                 */
00283                                 s = va("%s %s\n", part1, targetName);
00284                         }
00285                         else if (cgs.gametype == GT_POWERDUEL)
00286                         {
00287                                 s = "";
00288                         }
00289                         else
00290                         {
00291                                 char sPlaceWith[256];
00292                                 char sKilledStr[256];
00293                                 trap_SP_GetStringTextString("MP_INGAME_PLACE_WITH",     sPlaceWith, sizeof(sPlaceWith));
00294                                 trap_SP_GetStringTextString("MP_INGAME_KILLED_MESSAGE", sKilledStr, sizeof(sKilledStr));
00295 
00296                                 s = va("%s %s.\n%s %s %i.", sKilledStr, targetName, 
00297                                         CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), 
00298                                         sPlaceWith,
00299                                         cg.snap->ps.persistant[PERS_SCORE] );
00300                         }
00301                 } else {
00302                         char sKilledStr[256];
00303                         trap_SP_GetStringTextString("MP_INGAME_KILLED_MESSAGE", sKilledStr, sizeof(sKilledStr));
00304                         s = va("%s %s", sKilledStr, targetName );
00305                 }
00306                 //if (!(cg_singlePlayerActive.integer && cg_cameraOrbit.integer)) {
00307                         CG_CenterPrint( s, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
00308                 //} 
00309                 // print the text message as well
00310         }
00311 
00312         // check for double client messages
00313         if ( !attackerInfo ) {
00314                 attacker = ENTITYNUM_WORLD;
00315                 strcpy( attackerName, "noname" );
00316         } else {
00317                 Q_strncpyz( attackerName, Info_ValueForKey( attackerInfo, "n" ), sizeof(attackerName) - 2);
00318                 strcat( attackerName, S_COLOR_WHITE );
00319                 // check for kill messages about the current clientNum
00320                 if ( target == cg.snap->ps.clientNum ) {
00321                         Q_strncpyz( cg.killerName, attackerName, sizeof( cg.killerName ) );
00322                 }
00323         }
00324 
00325         if ( attacker != ENTITYNUM_WORLD ) {
00326                 switch (mod) {
00327                 case MOD_STUN_BATON:
00328                         message = "KILLED_STUN";
00329                         break;
00330                 case MOD_MELEE:
00331                         message = "KILLED_MELEE";
00332                         break;
00333                 case MOD_SABER:
00334                         message = "KILLED_SABER";
00335                         break;
00336                 case MOD_BRYAR_PISTOL:
00337                 case MOD_BRYAR_PISTOL_ALT:
00338                         message = "KILLED_BRYAR";
00339                         break;
00340                 case MOD_BLASTER:
00341                         message = "KILLED_BLASTER";
00342                         break;
00343                 case MOD_TURBLAST:
00344                         message = "KILLED_BLASTER";
00345                         break;
00346                 case MOD_DISRUPTOR:
00347                 case MOD_DISRUPTOR_SPLASH:
00348                         message = "KILLED_DISRUPTOR";
00349                         break;
00350                 case MOD_DISRUPTOR_SNIPER:
00351                         message = "KILLED_DISRUPTORSNIPE";
00352                         break;
00353                 case MOD_BOWCASTER:
00354                         message = "KILLED_BOWCASTER";
00355                         break;
00356                 case MOD_REPEATER:
00357                         message = "KILLED_REPEATER";
00358                         break;
00359                 case MOD_REPEATER_ALT:
00360                 case MOD_REPEATER_ALT_SPLASH:
00361                         message = "KILLED_REPEATERALT";
00362                         break;
00363                 case MOD_DEMP2:
00364                 case MOD_DEMP2_ALT:
00365                         message = "KILLED_DEMP2";
00366                         break;
00367                 case MOD_FLECHETTE:
00368                         message = "KILLED_FLECHETTE";
00369                         break;
00370                 case MOD_FLECHETTE_ALT_SPLASH:
00371                         message = "KILLED_FLECHETTE_MINE";
00372                         break;
00373                 case MOD_ROCKET:
00374                 case MOD_ROCKET_SPLASH:
00375                         message = "KILLED_ROCKET";
00376                         break;
00377                 case MOD_ROCKET_HOMING:
00378                 case MOD_ROCKET_HOMING_SPLASH:
00379                         message = "KILLED_ROCKET_HOMING";
00380                         break;
00381                 case MOD_THERMAL:
00382                 case MOD_THERMAL_SPLASH:
00383                         message = "KILLED_THERMAL";
00384                         break;
00385                 case MOD_TRIP_MINE_SPLASH:
00386                         message = "KILLED_TRIPMINE";
00387                         break;
00388                 case MOD_TIMED_MINE_SPLASH:
00389                         message = "KILLED_TRIPMINE_TIMED";
00390                         break;
00391                 case MOD_DET_PACK_SPLASH:
00392                         message = "KILLED_DETPACK";
00393                         break;
00394                 case MOD_VEHICLE:
00395                 case MOD_CONC:
00396                 case MOD_CONC_ALT:
00397                         message = "KILLED_GENERIC";
00398                         break;
00399                 case MOD_FORCE_DARK:
00400                         message = "KILLED_DARKFORCE";
00401                         break;
00402                 case MOD_SENTRY:
00403                         message = "KILLED_SENTRY";
00404                         break;
00405                 case MOD_TELEFRAG:
00406                         message = "KILLED_TELEFRAG";
00407                         break;
00408                 case MOD_CRUSH:
00409                         message = "KILLED_GENERIC";//"KILLED_FORCETOSS";
00410                         break;
00411                 case MOD_FALLING:
00412                         message = "KILLED_FORCETOSS";
00413                         break;
00414                 case MOD_TRIGGER_HURT:
00415                         message = "KILLED_GENERIC";//"KILLED_FORCETOSS";
00416                         break;
00417                 default:
00418                         message = "KILLED_GENERIC";
00419                         break;
00420                 }
00421 
00422                 if (message) {
00423                         message = (char *)CG_GetStringEdString("MP_INGAME", message);
00424 
00425                         CG_Printf( "%s %s %s\n", 
00426                                 targetName, message, attackerName);
00427                         return;
00428                 }
00429         }
00430 
00431         // we don't know what it was
00432         CG_Printf( "%s %s\n", targetName, (char *)CG_GetStringEdString("MP_INGAME", "DIED_GENERIC") );
00433 }
00434 
00435 //==========================================================================
00436 
00437 void CG_ToggleBinoculars(centity_t *cent, int forceZoom)
00438 {
00439         if (cent->currentState.number != cg.snap->ps.clientNum)
00440         {
00441                 return;
00442         }
00443 
00444         if (cg.snap->ps.weaponstate != WEAPON_READY)
00445         { //So we can't fool it and reactivate while switching to the saber or something.
00446                 return;
00447         }
00448 
00449         /*
00450         if (cg.snap->ps.weapon == WP_SABER)
00451         { //No.
00452                 return;
00453         }
00454         */
00455 
00456         if (forceZoom)
00457         {
00458                 if (forceZoom == 2)
00459                 {
00460                         cg.snap->ps.zoomMode = 0;
00461                 }
00462                 else if (forceZoom == 1)
00463                 {
00464                         cg.snap->ps.zoomMode = 2;
00465                 }
00466         }
00467 
00468         if (cg.snap->ps.zoomMode == 0)
00469         {
00470                 trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.media.zoomStart );
00471         }
00472         else if (cg.snap->ps.zoomMode == 2)
00473         {
00474                 trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.media.zoomEnd );
00475         }
00476 }
00477 
00478 //set the local timing bar
00479 extern int cg_genericTimerBar;
00480 extern int cg_genericTimerDur;
00481 extern vec4_t cg_genericTimerColor;
00482 void CG_LocalTimingBar(int startTime, int duration)
00483 {
00484     cg_genericTimerBar = startTime + duration;
00485         cg_genericTimerDur = duration;
00486 
00487         cg_genericTimerColor[0] = 1.0f;
00488         cg_genericTimerColor[1] = 1.0f;
00489         cg_genericTimerColor[2] = 0.0f;
00490         cg_genericTimerColor[3] = 1.0f;
00491 }
00492 
00493 /*
00494 ===============
00495 CG_UseItem
00496 ===============
00497 */
00498 static void CG_UseItem( centity_t *cent ) {
00499         clientInfo_t *ci;
00500         int                     itemNum, clientNum;
00501         gitem_t         *item;
00502         entityState_t *es;
00503 
00504         es = &cent->currentState;
00505         
00506         itemNum = (es->event & ~EV_EVENT_BITS) - EV_USE_ITEM0;
00507         if ( itemNum < 0 || itemNum > HI_NUM_HOLDABLE ) {
00508                 itemNum = 0;
00509         }
00510 
00511         // print a message if the local player
00512         if ( es->number == cg.snap->ps.clientNum ) {
00513                 if ( !itemNum ) {
00514                         //CG_CenterPrint( "No item to use", SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
00515                 } else {
00516                         item = BG_FindItemForHoldable( itemNum );
00517                 }
00518         }
00519 
00520         switch ( itemNum ) {
00521         default:
00522         case HI_NONE:
00523                 //trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.useNothingSound );
00524                 break;
00525 
00526         case HI_BINOCULARS:
00527                 CG_ToggleBinoculars(cent, es->eventParm);
00528                 break;
00529 
00530         case HI_SEEKER:
00531                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.deploySeeker );
00532                 break;
00533 
00534         case HI_SHIELD:
00535         case HI_SENTRY_GUN:
00536                 break;
00537 
00538 //      case HI_MEDKIT:
00539         case HI_MEDPAC:
00540         case HI_MEDPAC_BIG:
00541                 clientNum = cent->currentState.clientNum;
00542                 if ( clientNum >= 0 && clientNum < MAX_CLIENTS ) {
00543                         ci = &cgs.clientinfo[ clientNum ];
00544                         ci->medkitUsageTime = cg.time;
00545                 }
00546                 //Different sound for big bacta?
00547                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.medkitSound );
00548                 break;
00549         case HI_JETPACK:
00550                 break; //Do something?
00551         case HI_HEALTHDISP:
00552                 //CG_LocalTimingBar(cg.time, TOSS_DEBOUNCE_TIME);
00553                 break;
00554         case HI_AMMODISP:
00555                 //CG_LocalTimingBar(cg.time, TOSS_DEBOUNCE_TIME);
00556                 break;
00557         case HI_EWEB:
00558                 break;
00559         case HI_CLOAK:
00560                 break; //Do something?
00561         }
00562 
00563         if (cg.snap && cg.snap->ps.clientNum == cent->currentState.number && itemNum != HI_BINOCULARS &&
00564                 itemNum != HI_JETPACK && itemNum != HI_HEALTHDISP && itemNum != HI_AMMODISP && itemNum != HI_CLOAK && itemNum != HI_EWEB)
00565         { //if not using binoculars/jetpack/dispensers/cloak, we just used that item up, so switch
00566                 BG_CycleInven(&cg.snap->ps, 1);
00567                 cg.itemSelect = -1; //update the client-side selection display
00568         }
00569 }
00570 
00571 
00572 /*
00573 ================
00574 CG_ItemPickup
00575 
00576 A new item was picked up this frame
00577 ================
00578 */
00579 static void CG_ItemPickup( int itemNum ) {
00580         cg.itemPickup = itemNum;
00581         cg.itemPickupTime = cg.time;
00582         cg.itemPickupBlendTime = cg.time;
00583         // see if it should be the grabbed weapon
00584         if ( cg.snap && bg_itemlist[itemNum].giType == IT_WEAPON ) {
00585 
00586                 // 0 == no switching
00587                 // 1 == automatically switch to best SAFE weapon
00588                 // 2 == automatically switch to best weapon, safe or otherwise
00589                 // 3 == if not saber, automatically switch to best weapon, safe or otherwise
00590 
00591                 if (0 == cg_autoswitch.integer)
00592                 {
00593                         // don't switch
00594                 }
00595                 else if ( cg_autoswitch.integer == 1)
00596                 { //only autoselect if not explosive ("safe")
00597                         if (bg_itemlist[itemNum].giTag != WP_TRIP_MINE &&
00598                                 bg_itemlist[itemNum].giTag != WP_DET_PACK &&
00599                                 bg_itemlist[itemNum].giTag != WP_THERMAL &&
00600                                 bg_itemlist[itemNum].giTag != WP_ROCKET_LAUNCHER &&
00601                                 bg_itemlist[itemNum].giTag > cg.snap->ps.weapon &&
00602                                 cg.snap->ps.weapon != WP_SABER)
00603                         {
00604                                 if (!cg.snap->ps.emplacedIndex)
00605                                 {
00606                                         cg.weaponSelectTime = cg.time;
00607                                 }
00608                                 cg.weaponSelect = bg_itemlist[itemNum].giTag;
00609                         }
00610                 }
00611                 else if ( cg_autoswitch.integer == 2)
00612                 { //autoselect if better
00613                         if (bg_itemlist[itemNum].giTag > cg.snap->ps.weapon &&
00614                                 cg.snap->ps.weapon != WP_SABER)
00615                         {
00616                                 if (!cg.snap->ps.emplacedIndex)
00617                                 {
00618                                         cg.weaponSelectTime = cg.time;
00619                                 }
00620                                 cg.weaponSelect = bg_itemlist[itemNum].giTag;
00621                         }
00622                 }
00623                 /*
00624                 else if ( cg_autoswitch.integer == 3)
00625                 { //autoselect if better and not using the saber as a weapon
00626                         if (bg_itemlist[itemNum].giTag > cg.snap->ps.weapon &&
00627                                 cg.snap->ps.weapon != WP_SABER)
00628                         {
00629                                 if (!cg.snap->ps.emplacedIndex)
00630                                 {
00631                                         cg.weaponSelectTime = cg.time;
00632                                 }
00633                                 cg.weaponSelect = bg_itemlist[itemNum].giTag;
00634                         }
00635                 }
00636                 */
00637                 //No longer required - just not switching ever if using saber
00638         }
00639 
00640         //rww - print pickup messages
00641         if (bg_itemlist[itemNum].classname && bg_itemlist[itemNum].classname[0] &&
00642                 (bg_itemlist[itemNum].giType != IT_TEAM || (bg_itemlist[itemNum].giTag != PW_REDFLAG && bg_itemlist[itemNum].giTag != PW_BLUEFLAG)) )
00643         { //don't print messages for flags, they have their own pickup event broadcasts
00644                 char    text[1024];
00645                 char    upperKey[1024];
00646 
00647                 strcpy(upperKey, bg_itemlist[itemNum].classname);
00648 
00649                 if ( trap_SP_GetStringTextString( va("SP_INGAME_%s",Q_strupr(upperKey)), text, sizeof( text )))
00650                 {
00651                         Com_Printf("%s %s\n", CG_GetStringEdString("MP_INGAME", "PICKUPLINE"), text);
00652                 }
00653                 else
00654                 {
00655                         Com_Printf("%s %s\n", CG_GetStringEdString("MP_INGAME", "PICKUPLINE"), bg_itemlist[itemNum].classname);
00656                 }
00657         }
00658 }
00659 
00660 
00661 /*
00662 ================
00663 CG_PainEvent
00664 
00665 Also called by playerstate transition
00666 ================
00667 */
00668 void CG_PainEvent( centity_t *cent, int health ) {
00669         char    *snd;
00670 
00671         // don't do more than two pain sounds a second
00672         if ( cg.time - cent->pe.painTime < 500 ) {
00673                 return;
00674         }
00675 
00676         if ( health < 25 ) {
00677                 snd = "*pain25.wav";
00678         } else if ( health < 50 ) {
00679                 snd = "*pain50.wav";
00680         } else if ( health < 75 ) {
00681                 snd = "*pain75.wav";
00682         } else {
00683                 snd = "*pain100.wav";
00684         }
00685         trap_S_StartSound( NULL, cent->currentState.number, CHAN_VOICE, 
00686                 CG_CustomSound( cent->currentState.number, snd ) );
00687 
00688         // save pain time for programitic twitch animation
00689         cent->pe.painTime = cg.time;
00690         cent->pe.painDirection  ^= 1;
00691 }
00692 
00693 extern qboolean BG_GetRootSurfNameWithVariant( void *ghoul2, const char *rootSurfName, char *returnSurfName, int returnSize );
00694 void CG_ReattachLimb(centity_t *source)
00695 {
00696         clientInfo_t *ci = NULL;
00697         
00698         if ( source->currentState.number >= MAX_CLIENTS )
00699         {
00700                 ci = source->npcClient;
00701         }
00702         else
00703         {
00704                 ci = &cgs.clientinfo[source->currentState.number];
00705         }
00706         if ( ci )
00707         {//re-apply the skin
00708                 if ( ci->torsoSkin > 0 )
00709                 {
00710                         trap_G2API_SetSkin(source->ghoul2,0,ci->torsoSkin,ci->torsoSkin);
00711                 }
00712         }
00713                 
00714         /*
00715         char *limbName;
00716         char *stubCapName;
00717         int i = G2_MODELPART_HEAD;
00718 
00719         //rww NOTE: Assumes G2_MODELPART_HEAD is first and G2_MODELPART_RLEG is last
00720         while (i <= G2_MODELPART_RLEG)
00721         {
00722                 if (source->torsoBolt & (1 << (i-10)))
00723                 {
00724                         switch (i)
00725                         {
00726                         case G2_MODELPART_HEAD:
00727                                 limbName = "head";
00728                                 stubCapName = "torso_cap_head";
00729                                 break;
00730                         case G2_MODELPART_WAIST:
00731                                 limbName = "torso";
00732                                 stubCapName = "hips_cap_torso";
00733                                 break;
00734                         case G2_MODELPART_LARM:
00735                                 limbName = "l_arm";
00736                                 stubCapName = "torso_cap_l_arm";
00737                                 break;
00738                         case G2_MODELPART_RARM:
00739                                 limbName = "r_arm";
00740                                 stubCapName = "torso_cap_r_arm";
00741                                 break;
00742                         case G2_MODELPART_RHAND:
00743                                 limbName = "r_hand";
00744                                 stubCapName = "r_arm_cap_r_hand";
00745                                 break;
00746                         case G2_MODELPART_LLEG:
00747                                 limbName = "l_leg";
00748                                 stubCapName = "hips_cap_l_leg";
00749                                 break;
00750                         case G2_MODELPART_RLEG:
00751                                 limbName = "r_leg";
00752                                 stubCapName = "hips_cap_r_leg";
00753                                 break;
00754                         default:
00755                                 source->torsoBolt = 0;
00756                                 source->ghoul2weapon = NULL;
00757                                 return;
00758                         }
00759 
00760                         trap_G2API_SetSurfaceOnOff(source->ghoul2, limbName, 0);
00761                         trap_G2API_SetSurfaceOnOff(source->ghoul2, stubCapName, 0x00000100);
00762                 }
00763                 i++;
00764         }
00765         */
00766         source->torsoBolt = 0;
00767 
00768         source->ghoul2weapon = NULL;
00769 }
00770 
00771 const char *CG_TeamName(int team)
00772 {
00773         if (team==TEAM_RED)
00774                 return "RED";
00775         else if (team==TEAM_BLUE)
00776                 return "BLUE";
00777         else if (team==TEAM_SPECTATOR)
00778                 return "SPECTATOR";
00779         return "FREE";
00780 }
00781 
00782 void CG_PrintCTFMessage(clientInfo_t *ci, const char *teamName, int ctfMessage)
00783 {
00784         char printMsg[1024];
00785         char *refName = NULL;
00786         const char *psStringEDString = NULL;
00787 
00788         switch (ctfMessage)
00789         {
00790         case CTFMESSAGE_FRAGGED_FLAG_CARRIER:
00791                 refName = "FRAGGED_FLAG_CARRIER";
00792                 break;
00793         case CTFMESSAGE_FLAG_RETURNED:
00794                 refName = "FLAG_RETURNED";
00795                 break;
00796         case CTFMESSAGE_PLAYER_RETURNED_FLAG:
00797                 refName = "PLAYER_RETURNED_FLAG";
00798                 break;
00799         case CTFMESSAGE_PLAYER_CAPTURED_FLAG:
00800                 refName = "PLAYER_CAPTURED_FLAG";
00801                 break;
00802         case CTFMESSAGE_PLAYER_GOT_FLAG:
00803                 refName = "PLAYER_GOT_FLAG";
00804                 break;
00805         default:
00806                 return;
00807         }
00808 
00809         psStringEDString = CG_GetStringEdString("MP_INGAME", refName);
00810 
00811         if (!psStringEDString || !psStringEDString[0])
00812         {
00813                 return;
00814         }
00815 
00816         if (teamName && teamName[0])
00817         {
00818                 const char *f = strstr(psStringEDString, "%s");
00819 
00820                 if (f)
00821                 {
00822                         int strLen = 0;
00823                         int i = 0;
00824 
00825                         if (ci)
00826                         {
00827                                 Com_sprintf(printMsg, sizeof(printMsg), "%s ", ci->name);
00828                                 strLen = strlen(printMsg);
00829                         }
00830 
00831                         while (psStringEDString[i] && i < 512)
00832                         {
00833                                 if (psStringEDString[i] == '%' &&
00834                                         psStringEDString[i+1] == 's')
00835                                 {
00836                                         printMsg[strLen] = '\0';
00837                                         Q_strcat(printMsg, sizeof(printMsg), teamName);
00838                                         strLen = strlen(printMsg);
00839 
00840                                         i++;
00841                                 }
00842                                 else
00843                                 {
00844                                         printMsg[strLen] = psStringEDString[i];
00845                                         strLen++;
00846                                 }
00847 
00848                                 i++;
00849                         }
00850 
00851                         printMsg[strLen] = '\0';
00852 
00853                         goto doPrint;
00854                 }
00855         }
00856 
00857         if (ci)
00858         {
00859                 Com_sprintf(printMsg, sizeof(printMsg), "%s %s", ci->name, psStringEDString);
00860         }
00861         else
00862         {
00863                 Com_sprintf(printMsg, sizeof(printMsg), "%s", psStringEDString);
00864         }
00865 
00866 doPrint:
00867         Com_Printf("%s\n", printMsg);
00868 }
00869 
00870 void CG_GetCTFMessageEvent(entityState_t *es)
00871 {
00872         int clIndex = es->trickedentindex;
00873         int teamIndex = es->trickedentindex2;
00874         clientInfo_t *ci = NULL;
00875         const char *teamName = NULL;
00876 
00877         if (clIndex < MAX_CLIENTS)
00878         {
00879                 ci = &cgs.clientinfo[clIndex];
00880         }
00881 
00882         if (teamIndex < 50)
00883         {
00884                 teamName = CG_TeamName(teamIndex);
00885         }
00886 
00887         if (!ci)
00888         {
00889                 return;
00890         }
00891 
00892         CG_PrintCTFMessage(ci, teamName, es->eventParm);
00893 }
00894 
00895 #include "../namespace_begin.h"
00896 qboolean BG_InKnockDownOnly( int anim );
00897 #include "../namespace_end.h"
00898 
00899 //JLFRUMBLE
00900 #ifdef _XBOX
00901 extern void FF_XboxDamage(int damage, float xpos);
00902 #endif
00903 
00904 void DoFall(centity_t *cent, entityState_t *es, int clientNum)
00905 {
00906         int delta = es->eventParm;
00907 
00908         if (cent->currentState.eFlags & EF_DEAD)
00909         { //corpses crack into the ground ^_^
00910                 if (delta > 25)
00911                 {
00912                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.fallSound );
00913                 }
00914                 else
00915                 {
00916                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, trap_S_RegisterSound( "sound/movers/objects/objectHit.wav" ) );
00917                 }
00918         }
00919         else if (BG_InKnockDownOnly(es->legsAnim))
00920         {
00921                 if (delta > 14)
00922                 {
00923                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.fallSound );
00924                 }
00925                 else
00926                 {
00927                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, trap_S_RegisterSound( "sound/movers/objects/objectHit.wav" ) );
00928                 }
00929         }
00930         else if (delta > 50)
00931         {
00932                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.fallSound );
00933                 trap_S_StartSound( NULL, cent->currentState.number, CHAN_VOICE, 
00934                         CG_CustomSound( cent->currentState.number, "*land1.wav" ) );
00935                 cent->pe.painTime = cg.time;    // don't play a pain sound right after this
00936         }
00937         else if (delta > 44)
00938         {
00939                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.fallSound );
00940                 trap_S_StartSound( NULL, cent->currentState.number, CHAN_VOICE, 
00941                         CG_CustomSound( cent->currentState.number, "*land1.wav" ) );
00942                 cent->pe.painTime = cg.time;    // don't play a pain sound right after this
00943         }
00944         else
00945         {
00946                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.landSound );
00947         }
00948         
00949         if ( clientNum == cg.predictedPlayerState.clientNum )
00950         {
00951                 // smooth landing z changes
00952                 cg.landChange = -delta;
00953                 if (cg.landChange > 32)
00954                 {
00955                         cg.landChange = 32;
00956                 }
00957                 if (cg.landChange < -32)
00958                 {
00959                         cg.landChange = -32;
00960                 }
00961                 cg.landTime = cg.time;
00962         }
00963 //JLFRUMBLE
00964 #ifdef _XBOX
00965         if ( cent->playerState)
00966         {
00967 
00968                 if (BG_InKnockDownOnly(es->legsAnim))
00969                 {
00970                         if (delta > 14)
00971                         {
00972                                 FF_XboxDamage(20, 0);
00973                         }
00974                         else
00975                         {
00976                                 FF_XboxDamage(14, 0);
00977                         }
00978                         return;
00979                 }
00980                 if ( delta > 50)
00981                         FF_XboxDamage(50, 0);
00982                 else 
00983                         FF_XboxDamage(delta, 0);
00984 /*              else if (delta > 44)
00985                         FF_XboxDamage(44, 0);
00986                 else 
00987                         FF_XboxDamage(20, 0);
00988 */
00989         }
00990 #endif
00991 
00992 
00993 
00994 }
00995 
00996 int CG_InClientBitflags(entityState_t *ent, int client)
00997 {
00998         int checkIn;
00999         int sub = 0;
01000 
01001         if (client > 47)
01002         {
01003                 checkIn = ent->trickedentindex4;
01004                 sub = 48;
01005         }
01006         else if (client > 31)
01007         {
01008                 checkIn = ent->trickedentindex3;
01009                 sub = 32;
01010         }
01011         else if (client > 15)
01012         {
01013                 checkIn = ent->trickedentindex2;
01014                 sub = 16;
01015         }
01016         else
01017         {
01018                 checkIn = ent->trickedentindex;
01019         }
01020 
01021         if (checkIn & (1 << (client-sub)))
01022         {
01023                 return 1;
01024         }
01025         
01026         return 0;
01027 }
01028 
01029 void CG_PlayDoorLoopSound( centity_t *cent );
01030 void CG_PlayDoorSound( centity_t *cent, int type );
01031 
01032 void CG_TryPlayCustomSound( vec3_t origin, int entityNum, int channel, const char *soundName )
01033 {
01034         sfxHandle_t cSound = CG_CustomSound(entityNum, soundName);
01035 
01036         if (cSound <= 0)
01037         {
01038                 return;
01039         }
01040 
01041         trap_S_StartSound(origin, entityNum, channel, cSound);
01042 }
01043 
01044 void CG_G2MarkEvent(entityState_t *es)
01045 {
01046         //es->origin should be the hit location of the projectile,
01047         //whereas es->origin2 is the predicted position of the
01048         //projectile. (based on the trajectory upon impact) -rww
01049         centity_t *pOwner = &cg_entities[es->otherEntityNum];
01050         vec3_t startPoint;
01051         float   size = 0.0f;
01052         qhandle_t shader = 0;
01053 
01054         if (!pOwner->ghoul2)
01055         { //can't do anything then...
01056                 return;
01057         }
01058 
01059         //es->eventParm being non-0 means to do a special trace check
01060         //first. This will give us an impact right at the surface to
01061         //project the mark on. Typically this is used for radius
01062         //explosions and such, where the source position could be
01063         //way outside of model space.
01064         if (es->eventParm)
01065         {
01066                 trace_t tr;
01067                 int ignore = ENTITYNUM_NONE;
01068 
01069                 CG_G2Trace(&tr, es->origin, NULL, NULL, es->origin2, ignore, MASK_PLAYERSOLID);
01070 
01071                 if (tr.entityNum != es->otherEntityNum)
01072                 { //try again if we hit an ent but not the one we wanted.
01073                         //CG_TestLine(es->origin, es->origin2, 2000, 0x0000ff, 1);
01074                         if (tr.entityNum < ENTITYNUM_WORLD)
01075                         {
01076                                 ignore = tr.entityNum;
01077                                 CG_G2Trace(&tr, es->origin, NULL, NULL, es->origin2, ignore, MASK_PLAYERSOLID);
01078                                 if (tr.entityNum != es->otherEntityNum)
01079                                 { //try extending the trace a bit.. or not
01080                                         /*
01081                                         vec3_t v;
01082 
01083                                         VectorSubtract(es->origin2, es->origin, v);
01084                                         VectorScale(v, 64.0f, v);
01085                                         VectorAdd(es->origin2, v, es->origin2);
01086 
01087                                         CG_G2Trace(&tr, es->origin, NULL, NULL, es->origin2, ignore, MASK_PLAYERSOLID);
01088                                         if (tr.entityNum != es->otherEntityNum)
01089                                         {
01090                                                 return;
01091                                         }
01092                                         */
01093                                         //didn't manage to collide with the desired person. No mark will be placed then.
01094                                         return;
01095                                 }
01096                         }
01097                 }
01098 
01099                 //otherwise we now have a valid starting point.
01100                 VectorCopy(tr.endpos, startPoint);
01101         }
01102         else
01103         {
01104                 VectorCopy(es->origin, startPoint);
01105         }
01106 
01107         if ( (es->eFlags&EF_JETPACK_ACTIVE) )
01108         {// a vehicle weapon, make it a larger size mark
01109                 //OR base this on the size of the thing you hit?
01110                 if ( g_vehWeaponInfo[es->otherEntityNum2].fG2MarkSize )
01111                 {
01112                         size = flrand( 0.6f, 1.4f )*g_vehWeaponInfo[es->otherEntityNum2].fG2MarkSize;
01113                 }
01114                 else
01115                 {       
01116                         size = flrand( 32.0f, 72.0f );
01117                 }
01118                 //specify mark shader in vehWeapon file
01119                 if ( g_vehWeaponInfo[es->otherEntityNum2].iG2MarkShaderHandle )
01120                 {//have one we want to use instead of defaults
01121                         shader = g_vehWeaponInfo[es->otherEntityNum2].iG2MarkShaderHandle;
01122                 }
01123         }
01124         switch(es->weapon)
01125         {
01126         case WP_BRYAR_PISTOL:
01127         case WP_CONCUSSION:
01128         case WP_BRYAR_OLD:
01129         case WP_BLASTER:
01130         case WP_DISRUPTOR:
01131         case WP_BOWCASTER:
01132         case WP_REPEATER:
01133         case WP_TURRET:
01134                 if ( !size )
01135                 {
01136                         size = 4.0f;
01137                 }
01138                 if ( !shader )
01139                 {
01140                         shader = cgs.media.bdecal_bodyburn1;
01141                 }
01142                 CG_AddGhoul2Mark(shader, size, 
01143                         startPoint, es->origin2, es->owner, pOwner->lerpOrigin,
01144                         pOwner->lerpAngles[YAW], pOwner->ghoul2,
01145                         pOwner->modelScale, Q_irand(10000, 20000));
01146                 break;
01147         case WP_ROCKET_LAUNCHER:
01148         case WP_THERMAL:
01149                 if ( !size )
01150                 {
01151                         size = 24.0f;
01152                 }
01153                 if ( !shader )
01154                 {
01155                         shader = cgs.media.bdecal_burn1;
01156                 }
01157                 CG_AddGhoul2Mark(shader, size, 
01158                         startPoint, es->origin2, es->owner, pOwner->lerpOrigin,
01159                         pOwner->lerpAngles[YAW], pOwner->ghoul2,
01160                         pOwner->modelScale, Q_irand(10000, 20000));
01161                 break;
01162                 /*
01163         case WP_FLECHETTE:
01164                 CG_AddGhoul2Mark(cgs.media.bdecal_bodyburn1, flrand(0.5f, 1.0f), 
01165                         startPoint, es->origin2, es->owner, pOwner->lerpOrigin,
01166                         pOwner->lerpAngles[YAW], pOwner->ghoul2,
01167                         pOwner->modelScale);
01168                 break;
01169                 */
01170                 //Issues with small scale?
01171         default:
01172                 break;
01173         }
01174 }
01175 
01176 void CG_CalcVehMuzzle(Vehicle_t *pVeh, centity_t *ent, int muzzleNum)
01177 {
01178         mdxaBone_t boltMatrix;
01179         vec3_t  vehAngles;
01180 
01181         assert(pVeh);
01182 
01183         if (pVeh->m_iMuzzleTime[muzzleNum] == cg.time)
01184         { //already done for this frame, don't need to do it again
01185                 return;
01186         }
01187         //Uh... how about we set this, hunh...?  :)
01188         pVeh->m_iMuzzleTime[muzzleNum] = cg.time;
01189 
01190         VectorCopy( ent->lerpAngles, vehAngles );
01191         if ( pVeh->m_pVehicleInfo )
01192         {
01193                 if (pVeh->m_pVehicleInfo->type == VH_ANIMAL
01194                          ||pVeh->m_pVehicleInfo->type == VH_WALKER)
01195                 {
01196                         vehAngles[PITCH] = vehAngles[ROLL] = 0.0f;
01197                 }
01198                 else if (pVeh->m_pVehicleInfo->type == VH_SPEEDER)
01199                 {
01200                         vehAngles[PITCH] = 0.0f;
01201                 }
01202         }
01203         trap_G2API_GetBoltMatrix_NoRecNoRot(ent->ghoul2, 0, pVeh->m_iMuzzleTag[muzzleNum], &boltMatrix, vehAngles,
01204                 ent->lerpOrigin, cg.time, NULL, ent->modelScale);
01205         BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, pVeh->m_vMuzzlePos[muzzleNum]);
01206         BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, pVeh->m_vMuzzleDir[muzzleNum]);
01207 }
01208 
01209 //corresponds to G_VehMuzzleFireFX -rww
01210 void CG_VehMuzzleFireFX(centity_t *veh, entityState_t *broadcaster)
01211 {
01212         Vehicle_t *pVeh = veh->m_pVehicle;
01213         int curMuz = 0, muzFX = 0;
01214 
01215         if (!pVeh || !veh->ghoul2)
01216         {
01217                 return;
01218         }
01219 
01220         for ( curMuz = 0; curMuz < MAX_VEHICLE_MUZZLES; curMuz++ )
01221         {//go through all muzzles and 
01222                 if ( pVeh->m_iMuzzleTag[curMuz] != -1//valid muzzle bolt
01223                         && (broadcaster->trickedentindex&(1<<curMuz)) )//fired
01224                 {//this muzzle fired
01225                         muzFX = 0;
01226                         if ( pVeh->m_pVehicleInfo->weapMuzzle[curMuz] == 0 )
01227                         {//no weaopon for this muzzle?  check turrets
01228                                 int i, j;
01229                                 for ( i = 0; i < MAX_VEHICLE_TURRETS; i++ )
01230                                 {
01231                                         for ( j = 0; j < MAX_VEHICLE_TURRETS; j++ )
01232                                         {
01233                                                 if ( pVeh->m_pVehicleInfo->turret[i].iMuzzle[j]-1 == curMuz )
01234                                                 {//this muzzle belongs to this turret
01235                                                         muzFX = g_vehWeaponInfo[pVeh->m_pVehicleInfo->turret[i].iWeapon].iMuzzleFX;
01236                                                         break;
01237                                                 }
01238                                         }
01239                                 }
01240                         }
01241                         else
01242                         {
01243                                 muzFX = g_vehWeaponInfo[pVeh->m_pVehicleInfo->weapMuzzle[curMuz]].iMuzzleFX;
01244                         }
01245                         if ( muzFX )
01246                         {
01247                                 //CG_CalcVehMuzzle(pVeh, veh, curMuz);
01248                                 //trap_FX_PlayEffectID(muzFX, pVeh->m_vMuzzlePos[curMuz], pVeh->m_vMuzzleDir[curMuz], -1, -1);
01249                                 trap_FX_PlayBoltedEffectID(muzFX, veh->currentState.origin, veh->ghoul2, pVeh->m_iMuzzleTag[curMuz], veh->currentState.number, 0, 0, qtrue);
01250                         }
01251                 }
01252         }
01253 }
01254 
01255 const char      *cg_stringEdVoiceChatTable[MAX_CUSTOM_SIEGE_SOUNDS] = 
01256 {
01257         "VC_ATT",//"*att_attack",
01258         "VC_ATT_PRIMARY",//"*att_primary",
01259         "VC_ATT_SECONDARY",//"*att_second",
01260         "VC_DEF_GUNS",//"*def_guns",
01261         "VC_DEF_POSITION",//"*def_position",
01262         "VC_DEF_PRIMARY",//"*def_primary",
01263         "VC_DEF_SECONDARY",//"*def_second",
01264         "VC_REPLY_COMING",//"*reply_coming",
01265         "VC_REPLY_GO",//"*reply_go",
01266         "VC_REPLY_NO",//"*reply_no",
01267         "VC_REPLY_STAY",//"*reply_stay",
01268         "VC_REPLY_YES",//"*reply_yes",
01269         "VC_REQ_ASSIST",//"*req_assist",
01270         "VC_REQ_DEMO",//"*req_demo",
01271         "VC_REQ_HVY",//"*req_hvy",
01272         "VC_REQ_MEDIC",//"*req_medic",
01273         "VC_REQ_SUPPLY",//"*req_sup",
01274         "VC_REQ_TECH",//"*req_tech",
01275         "VC_SPOT_AIR",//"*spot_air",
01276         "VC_SPOT_DEF",//"*spot_defenses",
01277         "VC_SPOT_EMPLACED",//"*spot_emplaced",
01278         "VC_SPOT_SNIPER",//"*spot_sniper",
01279         "VC_SPOT_TROOP",//"*spot_troops",
01280         "VC_TAC_COVER",//"*tac_cover",
01281         "VC_TAC_FALLBACK",//"*tac_fallback",
01282         "VC_TAC_FOLLOW",//"*tac_follow",
01283         "VC_TAC_HOLD",//"*tac_hold",
01284         "VC_TAC_SPLIT",//"*tac_split",
01285         "VC_TAC_TOGETHER",//"*tac_together",
01286         NULL
01287 };
01288 
01289 //stupid way of figuring out what string to use for voice chats
01290 const char *CG_GetStringForVoiceSound(const char *s)
01291 {
01292         int i = 0;
01293         while (i < MAX_CUSTOM_SIEGE_SOUNDS)
01294         {
01295                 if (bg_customSiegeSoundNames[i] &&
01296                         !Q_stricmp(bg_customSiegeSoundNames[i], s))
01297                 { //get the matching reference name
01298                         assert(cg_stringEdVoiceChatTable[i]);
01299                         return CG_GetStringEdString("MENUS", (char *)cg_stringEdVoiceChatTable[i]);
01300                 }
01301                 i++;
01302         }
01303 
01304         return "voice chat";
01305 }
01306 
01307 /*
01308 ==============
01309 CG_EntityEvent
01310 
01311 An entity has an event value
01312 also called by CG_CheckPlayerstateEvents
01313 ==============
01314 */
01315 #define DEBUGNAME(x) if(cg_debugEvents.integer){CG_Printf(x"\n");}
01316 extern void CG_ChatBox_AddString(char *chatStr); //cg_draw.c
01317 void CG_EntityEvent( centity_t *cent, vec3_t position ) {
01318         entityState_t   *es;
01319         int                             event;
01320         vec3_t                  dir;
01321         const char              *s;
01322         int                             clientNum;
01323         clientInfo_t    *ci;
01324         int                             eID = 0;
01325         int                             isnd = 0;
01326         centity_t               *cl_ent;
01327 
01328         es = &cent->currentState;
01329         event = es->event & ~EV_EVENT_BITS;
01330 
01331         if ( cg_debugEvents.integer ) {
01332                 CG_Printf( "ent:%3i  event:%3i ", es->number, event );
01333         }
01334 
01335         if ( !event ) {
01336                 DEBUGNAME("ZEROEVENT");
01337                 return;
01338         }
01339 
01340         clientNum = es->clientNum;
01341         if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) {
01342                 clientNum = 0;
01343         }
01344 
01345         if (es->eType == ET_NPC)
01346         {
01347                 clientNum = es->number;
01348 
01349                 if (!cent->npcClient)
01350                 {
01351                         CG_CreateNPCClient(&cent->npcClient); //allocate memory for it
01352 
01353                         if (!cent->npcClient)
01354                         {
01355                                 assert(0);
01356                                 return;
01357                         }
01358 
01359                         memset(cent->npcClient, 0, sizeof(clientInfo_t));
01360                         cent->npcClient->ghoul2Model = NULL;
01361                 }
01362 
01363                 ci = cent->npcClient;
01364 
01365                 assert(ci);
01366         }
01367         else
01368         {
01369                 ci = &cgs.clientinfo[ clientNum ];
01370         }
01371 
01372         switch ( event ) {
01373         //
01374         // movement generated events
01375         //
01376         case EV_CLIENTJOIN:
01377                 DEBUGNAME("EV_CLIENTJOIN");
01378 
01379                 //Slight hack to force a local reinit of client entity on join.
01380                 cl_ent = &cg_entities[es->eventParm];
01381 
01382                 if (cl_ent)
01383                 {
01384                         //cl_ent->torsoBolt = 0;
01385                         cl_ent->bolt1 = 0;
01386                         cl_ent->bolt2 = 0;
01387                         cl_ent->bolt3 = 0;
01388                         cl_ent->bolt4 = 0;
01389                         cl_ent->bodyHeight = 0;//SABER_LENGTH_MAX;
01390                         //cl_ent->saberExtendTime = 0;
01391                         cl_ent->boltInfo = 0;
01392                         cl_ent->frame_minus1_refreshed = 0;
01393                         cl_ent->frame_minus2_refreshed = 0;
01394                         cl_ent->frame_hold_time = 0;
01395                         cl_ent->frame_hold_refreshed = 0;
01396                         cl_ent->trickAlpha = 0;
01397                         cl_ent->trickAlphaTime = 0;
01398                         cl_ent->ghoul2weapon = NULL;
01399                         cl_ent->weapon = WP_NONE;
01400                         cl_ent->teamPowerEffectTime = 0;
01401                         cl_ent->teamPowerType = 0;
01402                         cl_ent->numLoopingSounds = 0;
01403                         //cl_ent->localAnimIndex = 0;
01404                 }
01405                 break;
01406 
01407         case EV_FOOTSTEP:
01408                 DEBUGNAME("EV_FOOTSTEP");
01409                 if (cg_footsteps.integer) {
01410                         footstep_t      soundType;
01411                         switch( es->eventParm )
01412                         {
01413                         case MATERIAL_MUD:
01414                                 soundType = FOOTSTEP_MUDWALK;
01415                                 break;
01416                         case MATERIAL_DIRT:                     
01417                                 soundType = FOOTSTEP_DIRTWALK;
01418                                 break;
01419                         case MATERIAL_SAND:                     
01420                                 soundType = FOOTSTEP_SANDWALK;
01421                                 break;
01422                         case MATERIAL_SNOW:                     
01423                                 soundType = FOOTSTEP_SNOWWALK;
01424                                 break;
01425                         case MATERIAL_SHORTGRASS:               
01426                         case MATERIAL_LONGGRASS:                
01427                                 soundType = FOOTSTEP_GRASSWALK;
01428                                 break;
01429                         case MATERIAL_SOLIDMETAL:               
01430                                 soundType = FOOTSTEP_METALWALK;
01431                                 break;
01432                         case MATERIAL_HOLLOWMETAL:      
01433                                 soundType = FOOTSTEP_PIPEWALK;
01434                                 break;
01435                         case MATERIAL_GRAVEL:
01436                                 soundType = FOOTSTEP_GRAVELWALK;
01437                                 break;
01438                         case MATERIAL_CARPET:
01439                         case MATERIAL_FABRIC:
01440                         case MATERIAL_CANVAS:
01441                         case MATERIAL_RUBBER:
01442                         case MATERIAL_PLASTIC:
01443                                 soundType = FOOTSTEP_RUGWALK;
01444                                 break;
01445                         case MATERIAL_SOLIDWOOD:
01446                         case MATERIAL_HOLLOWWOOD:
01447                                 soundType = FOOTSTEP_WOODWALK;
01448                                 break;
01449 
01450                         default:
01451                                 soundType = FOOTSTEP_STONEWALK;
01452                                 break;
01453                         }
01454 
01455                         trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ soundType ][rand()&3] );
01456                 }
01457                 break;
01458         case EV_FOOTSTEP_METAL:
01459                 DEBUGNAME("EV_FOOTSTEP_METAL");
01460                 if (cg_footsteps.integer) {
01461                         trap_S_StartSound (NULL, es->number, CHAN_BODY, 
01462                                 cgs.media.footsteps[ FOOTSTEP_METALWALK ][rand()&3] );
01463                 }
01464                 break;
01465         case EV_FOOTSPLASH:
01466                 DEBUGNAME("EV_FOOTSPLASH");
01467                 if (cg_footsteps.integer) {
01468                         trap_S_StartSound (NULL, es->number, CHAN_BODY, 
01469                                 cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] );
01470                 }
01471                 break;
01472         case EV_FOOTWADE:
01473                 DEBUGNAME("EV_FOOTWADE");
01474                 if (cg_footsteps.integer) {
01475                         trap_S_StartSound (NULL, es->number, CHAN_BODY, 
01476                                 cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] );
01477                 }
01478                 break;
01479         case EV_SWIM:
01480                 DEBUGNAME("EV_SWIM");
01481                 if (cg_footsteps.integer) {
01482                         trap_S_StartSound (NULL, es->number, CHAN_BODY, 
01483                                 cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] );
01484                 }
01485                 break;
01486 
01487 
01488         case EV_FALL:
01489                 DEBUGNAME("EV_FALL");
01490                 if (es->number == cg.snap->ps.clientNum && cg.snap->ps.fallingToDeath)
01491                 {
01492                         break;
01493                 }
01494                 DoFall(cent, es, clientNum);
01495                 break;
01496         case EV_STEP_4:
01497         case EV_STEP_8:
01498         case EV_STEP_12:
01499         case EV_STEP_16:                // smooth out step up transitions
01500                 DEBUGNAME("EV_STEP");
01501         {
01502                 float   oldStep;
01503                 int             delta;
01504                 int             step;
01505 
01506                 if ( clientNum != cg.predictedPlayerState.clientNum ) {
01507                         break;
01508                 }
01509                 // if we are interpolating, we don't need to smooth steps
01510                 if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW) ||
01511                         cg_nopredict.integer || cg_synchronousClients.integer ) {
01512                         break;
01513                 }
01514                 // check for stepping up before a previous step is completed
01515                 delta = cg.time - cg.stepTime;
01516                 if (delta < STEP_TIME) {
01517                         oldStep = cg.stepChange * (STEP_TIME - delta) / STEP_TIME;
01518                 } else {
01519                         oldStep = 0;
01520                 }
01521 
01522                 // add this amount
01523                 step = 4 * (event - EV_STEP_4 + 1 );
01524                 cg.stepChange = oldStep + step;
01525                 if ( cg.stepChange > MAX_STEP_CHANGE ) {
01526                         cg.stepChange = MAX_STEP_CHANGE;
01527                 }
01528                 cg.stepTime = cg.time;
01529                 break;
01530         }
01531 
01532         case EV_JUMP_PAD:
01533                 DEBUGNAME("EV_JUMP_PAD");
01534                 break;
01535 
01536         case EV_GHOUL2_MARK:
01537                 DEBUGNAME("EV_GHOUL2_MARK");
01538 
01539                 if (cg_ghoul2Marks.integer)
01540                 { //Can we put a burn mark on him?
01541                         CG_G2MarkEvent(es);
01542                 }
01543                 break;
01544 
01545         case EV_GLOBAL_DUEL:
01546                 DEBUGNAME("EV_GLOBAL_DUEL");
01547                 //used for beginning of power duels
01548                 //if (cg.predictedPlayerState.persistant[PERS_TEAM] != TEAM_SPECTATOR)
01549                 if (es->otherEntityNum == cg.predictedPlayerState.clientNum ||
01550                         es->otherEntityNum2 == cg.predictedPlayerState.clientNum ||
01551                         es->groundEntityNum == cg.predictedPlayerState.clientNum)
01552                 {
01553                         CG_CenterPrint( CG_GetStringEdString("MP_SVGAME", "BEGIN_DUEL"), 120, GIANTCHAR_WIDTH*2 );                              
01554                         trap_S_StartLocalSound( cgs.media.countFightSound, CHAN_ANNOUNCER );
01555                 }
01556                 break;
01557 
01558         case EV_PRIVATE_DUEL:
01559                 DEBUGNAME("EV_PRIVATE_DUEL");
01560 
01561                 if (cg.snap->ps.clientNum != es->number)
01562                 {
01563                         break;
01564                 }
01565 
01566                 if (es->eventParm)
01567                 { //starting the duel
01568                         if (es->eventParm == 2)
01569                         {
01570                                 CG_CenterPrint( CG_GetStringEdString("MP_SVGAME", "BEGIN_DUEL"), 120, GIANTCHAR_WIDTH*2 );                              
01571                                 trap_S_StartLocalSound( cgs.media.countFightSound, CHAN_ANNOUNCER );
01572                         }
01573                         else
01574                         {
01575                                 trap_S_StartBackgroundTrack( "music/mp/duel.mp3", "music/mp/duel.mp3", qfalse );
01576                         }
01577                 }
01578                 else
01579                 { //ending the duel
01580                         CG_StartMusic(qtrue);
01581                 }
01582                 break;
01583 
01584         case EV_JUMP:
01585                 DEBUGNAME("EV_JUMP");
01586                 if (cg_jumpSounds.integer)
01587                 {
01588                         trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) );
01589                 }
01590                 break;
01591         case EV_ROLL:
01592                 DEBUGNAME("EV_ROLL");
01593                 if (es->number == cg.snap->ps.clientNum && cg.snap->ps.fallingToDeath)
01594                 {
01595                         break;
01596                 }
01597                 if (es->eventParm)
01598                 { //fall-roll-in-one event
01599                         DoFall(cent, es, clientNum);
01600                 }
01601 
01602                 trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) );
01603                 trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.rollSound  );
01604 
01605                 //FIXME: need some sort of body impact on ground sound and maybe kick up some dust?
01606                 break;
01607 
01608         case EV_TAUNT:
01609                 DEBUGNAME("EV_TAUNT");
01610                 {
01611                         int soundIndex = 0;
01612                         if ( cgs.gametype != GT_DUEL
01613                                 && cgs.gametype != GT_POWERDUEL
01614                                 && es->eventParm == TAUNT_TAUNT )
01615                         {//normal taunt
01616                                 soundIndex = CG_CustomSound( es->number, "*taunt.wav" );
01617                         }
01618                         else
01619                         {
01620                                 switch ( es->eventParm )
01621                                 {
01622                                 case TAUNT_TAUNT:
01623                                 default:
01624                                         if ( Q_irand( 0, 1 ) )
01625                                         {
01626                                                 soundIndex = CG_CustomSound( es->number, va("*anger%d.wav", Q_irand(1,3)) );
01627                                         }
01628                                         else
01629                                         {
01630                                                 soundIndex = CG_CustomSound( es->number, va("*taunt%d.wav", Q_irand(1,3)) );
01631                                                 if ( !soundIndex )
01632                                                 {
01633                                                         soundIndex = CG_CustomSound( es->number, va("*anger%d.wav", Q_irand(1,3)) );
01634                                                 }
01635                                         }
01636                                         break;
01637                                 case TAUNT_BOW:
01638                                         //soundIndex = CG_CustomSound( es->number, va("*respect%d.wav", Q_irand(1,3)) );
01639                                         break;
01640                                 case TAUNT_MEDITATE:
01641                                         //soundIndex = CG_CustomSound( es->number, va("*meditate%d.wav", Q_irand(1,3)) );
01642                                         break;
01643                                 case TAUNT_FLOURISH:
01644                                         if ( Q_irand( 0, 1 ) )
01645                                         {
01646                                                 soundIndex = CG_CustomSound( es->number, va("*deflect%d.wav", Q_irand(1,3)) );
01647                                                 if ( !soundIndex )
01648                                                 {
01649                                                         soundIndex = CG_CustomSound( es->number, va("*gloat%d.wav", Q_irand(1,3)) );
01650                                                         if ( !soundIndex )
01651                                                         {
01652                                                                 soundIndex = CG_CustomSound( es->number, va("*anger%d.wav", Q_irand(1,3)) );
01653                                                         }
01654                                                 }
01655                                         }
01656                                         else
01657                                         {
01658                                                 soundIndex = CG_CustomSound( es->number, va("*gloat%d.wav", Q_irand(1,3)) );
01659                                                 if ( !soundIndex )
01660                                                 {
01661                                                         soundIndex = CG_CustomSound( es->number, va("*deflect%d.wav", Q_irand(1,3)) );
01662                                                         if ( !soundIndex )
01663                                                         {
01664                                                                 soundIndex = CG_CustomSound( es->number, va("*anger%d.wav", Q_irand(1,3)) );
01665                                                         }
01666                                                 }
01667                                         }
01668                                         break;
01669                                 case TAUNT_GLOAT:
01670                                         soundIndex = CG_CustomSound( es->number, va("*victory%d.wav", Q_irand(1,3)) );
01671                                         break;
01672                                 }
01673                         }
01674                         if ( !soundIndex )
01675                         {
01676                                 soundIndex = CG_CustomSound( es->number, "*taunt.wav" );
01677                         }
01678                         if ( soundIndex )
01679                         {
01680                                 trap_S_StartSound (NULL, es->number, CHAN_VOICE, soundIndex );
01681                         }
01682                 }
01683                 break;
01684 
01685                 //Begin NPC sounds
01686         case EV_ANGER1: //Say when acquire an enemy when didn't have one before
01687         case EV_ANGER2:
01688         case EV_ANGER3:
01689                 DEBUGNAME("EV_ANGERx");
01690                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*anger%i.wav", event - EV_ANGER1 + 1) );
01691                 break;
01692 
01693         case EV_VICTORY1:       //Say when killed an enemy
01694         case EV_VICTORY2:
01695         case EV_VICTORY3:
01696                 DEBUGNAME("EV_VICTORYx");
01697                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*victory%i.wav", event - EV_VICTORY1 + 1) );
01698                 break;
01699 
01700         case EV_CONFUSE1:       //Say when confused
01701         case EV_CONFUSE2:
01702         case EV_CONFUSE3:
01703                 DEBUGNAME("EV_CONFUSEDx");
01704                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*confuse%i.wav", event - EV_CONFUSE1 + 1) );
01705                 break;
01706 
01707         case EV_PUSHED1:        //Say when pushed
01708         case EV_PUSHED2:
01709         case EV_PUSHED3:
01710                 DEBUGNAME("EV_PUSHEDx");
01711                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*pushed%i.wav", event - EV_PUSHED1 + 1) );
01712                 break;
01713 
01714         case EV_CHOKE1: //Say when choking
01715         case EV_CHOKE2:
01716         case EV_CHOKE3:
01717                 DEBUGNAME("EV_CHOKEx");
01718                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*choke%i.wav", event - EV_CHOKE1 + 1) );
01719                 break;
01720 
01721         case EV_FFWARN: //Warn ally to stop shooting you
01722                 DEBUGNAME("EV_FFWARN");
01723                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*ffwarn.wav" );
01724                 break;
01725 
01726         case EV_FFTURN: //Turn on ally after being shot by them
01727                 DEBUGNAME("EV_FFTURN");
01728                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*ffturn.wav" );
01729                 break;
01730 
01731         //extra sounds for ST
01732         case EV_CHASE1:
01733         case EV_CHASE2:
01734         case EV_CHASE3:
01735                 DEBUGNAME("EV_CHASEx");
01736                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*chase%i.wav", event - EV_CHASE1 + 1) );
01737                 break;
01738         case EV_COVER1:
01739         case EV_COVER2:
01740         case EV_COVER3:
01741         case EV_COVER4:
01742         case EV_COVER5:
01743                 DEBUGNAME("EV_COVERx");
01744                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*cover%i.wav", event - EV_COVER1 + 1) );
01745                 break;
01746         case EV_DETECTED1:
01747         case EV_DETECTED2:
01748         case EV_DETECTED3:
01749         case EV_DETECTED4:
01750         case EV_DETECTED5:
01751                 DEBUGNAME("EV_DETECTEDx");
01752                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*detected%i.wav", event - EV_DETECTED1 + 1) );
01753                 break;
01754         case EV_GIVEUP1:
01755         case EV_GIVEUP2:
01756         case EV_GIVEUP3:
01757         case EV_GIVEUP4:
01758                 DEBUGNAME("EV_GIVEUPx");
01759                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*giveup%i.wav", event - EV_GIVEUP1 + 1) );
01760                 break;
01761         case EV_LOOK1:
01762         case EV_LOOK2:
01763                 DEBUGNAME("EV_LOOKx");
01764                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*look%i.wav", event - EV_LOOK1 + 1) );
01765                 break;
01766         case EV_LOST1:
01767                 DEBUGNAME("EV_LOST1");
01768                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*lost1.wav" );
01769                 break;
01770         case EV_OUTFLANK1:
01771         case EV_OUTFLANK2:
01772                 DEBUGNAME("EV_OUTFLANKx");
01773                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*outflank%i.wav", event - EV_OUTFLANK1 + 1) );
01774                 break;
01775         case EV_ESCAPING1:
01776         case EV_ESCAPING2:
01777         case EV_ESCAPING3:
01778                 DEBUGNAME("EV_ESCAPINGx");
01779                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*escaping%i.wav", event - EV_ESCAPING1 + 1) );
01780                 break;
01781         case EV_SIGHT1:
01782         case EV_SIGHT2:
01783         case EV_SIGHT3:
01784                 DEBUGNAME("EV_SIGHTx");
01785                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*sight%i.wav", event - EV_SIGHT1 + 1) );
01786                 break;
01787         case EV_SOUND1:
01788         case EV_SOUND2:
01789         case EV_SOUND3:
01790                 DEBUGNAME("EV_SOUNDx");
01791                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*sound%i.wav", event - EV_SOUND1 + 1) );
01792                 break;
01793         case EV_SUSPICIOUS1:
01794         case EV_SUSPICIOUS2:
01795         case EV_SUSPICIOUS3:
01796         case EV_SUSPICIOUS4:
01797         case EV_SUSPICIOUS5:
01798                 DEBUGNAME("EV_SUSPICIOUSx");
01799                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*suspicious%i.wav", event - EV_SUSPICIOUS1 + 1) );
01800                 break;
01801         //extra sounds for Jedi
01802         case EV_COMBAT1:
01803         case EV_COMBAT2:
01804         case EV_COMBAT3:
01805                 DEBUGNAME("EV_COMBATx");
01806                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*combat%i.wav", event - EV_COMBAT1 + 1) );
01807                 break;
01808         case EV_JDETECTED1:
01809         case EV_JDETECTED2:
01810         case EV_JDETECTED3:
01811                 DEBUGNAME("EV_JDETECTEDx");
01812                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*jdetected%i.wav", event - EV_JDETECTED1 + 1) );
01813                 break;
01814         case EV_TAUNT1:
01815         case EV_TAUNT2:
01816         case EV_TAUNT3:
01817                 DEBUGNAME("EV_TAUNTx");
01818                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*taunt%i.wav", event - EV_TAUNT1 + 1) );
01819                 break;
01820         case EV_JCHASE1:
01821         case EV_JCHASE2:
01822         case EV_JCHASE3:
01823                 DEBUGNAME("EV_JCHASEx");
01824                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*jchase%i.wav", event - EV_JCHASE1 + 1) );
01825                 break;
01826         case EV_JLOST1:
01827         case EV_JLOST2:
01828         case EV_JLOST3:
01829                 DEBUGNAME("EV_JLOSTx");
01830                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*jlost%i.wav", event - EV_JLOST1 + 1) );
01831                 break;
01832         case EV_DEFLECT1:
01833         case EV_DEFLECT2:
01834         case EV_DEFLECT3:
01835                 DEBUGNAME("EV_DEFLECTx");
01836                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*deflect%i.wav", event - EV_DEFLECT1 + 1) );
01837                 break;
01838         case EV_GLOAT1:
01839         case EV_GLOAT2:
01840         case EV_GLOAT3:
01841                 DEBUGNAME("EV_GLOATx");
01842                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*gloat%i.wav", event - EV_GLOAT1 + 1) );
01843                 break;
01844         case EV_PUSHFAIL:
01845                 DEBUGNAME("EV_PUSHFAIL");
01846                 CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*pushfail.wav" );
01847                 break;
01848                 //End NPC sounds
01849 
01850         case EV_SIEGESPEC:
01851                 DEBUGNAME("EV_SIEGESPEC");
01852                 if ( es->owner == cg.predictedPlayerState.clientNum )
01853                 {
01854                         cg_siegeDeathTime = es->time;
01855                 }
01856 
01857                 break;
01858                 
01859         case EV_WATER_TOUCH:
01860                 DEBUGNAME("EV_WATER_TOUCH");
01861                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrInSound );
01862                 break;
01863         case EV_WATER_LEAVE:
01864                 DEBUGNAME("EV_WATER_LEAVE");
01865                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound );
01866                 break;
01867         case EV_WATER_UNDER:
01868                 DEBUGNAME("EV_WATER_UNDER");
01869                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound );
01870                 break;
01871         case EV_WATER_CLEAR:
01872                 DEBUGNAME("EV_WATER_CLEAR");
01873                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*gasp.wav" ) );
01874                 break;
01875 
01876         case EV_ITEM_PICKUP:
01877                 DEBUGNAME("EV_ITEM_PICKUP");
01878                 {
01879                         gitem_t *item;
01880                         int             index;
01881                         qboolean        newindex = qfalse;
01882 
01883                         index = cg_entities[es->eventParm].currentState.modelindex;             // player predicted
01884 
01885                         if (index < 1 && cg_entities[es->eventParm].currentState.isJediMaster)
01886                         { //a holocron most likely
01887                                 index = cg_entities[es->eventParm].currentState.trickedentindex4;
01888                                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.holocronPickup );
01889                                                                 
01890                                 if (es->number == cg.snap->ps.clientNum && showPowersName[index])
01891                                 {
01892                                         const char *strText = CG_GetStringEdString("MP_INGAME", "PICKUPLINE");
01893 
01894                                         //Com_Printf("%s %s\n", strText, showPowersName[index]);
01895                                         CG_CenterPrint( va("%s %s\n", strText, CG_GetStringEdString("SP_INGAME",showPowersName[index])), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
01896                                 }
01897 
01898                                 //Show the player their force selection bar in case picking the holocron up changed the current selection
01899                                 if (index != FP_SABER_OFFENSE && index != FP_SABER_DEFENSE && index != FP_SABERTHROW &&
01900                                         index != FP_LEVITATION &&
01901                                         es->number == cg.snap->ps.clientNum &&
01902                                         (index == cg.snap->ps.fd.forcePowerSelected || !(cg.snap->ps.fd.forcePowersActive & (1 << cg.snap->ps.fd.forcePowerSelected))))
01903                                 {
01904                                         if (cg.forceSelect != index)
01905                                         {
01906                                                 cg.forceSelect = index;
01907                                                 newindex = qtrue;
01908                                         }
01909                                 }
01910 
01911                                 if (es->number == cg.snap->ps.clientNum && newindex)
01912                                 {
01913                                         if (cg.forceSelectTime < cg.time)
01914                                         {
01915                                                 cg.forceSelectTime = cg.time;
01916                                         }
01917                                 }
01918 
01919                                 break;
01920                         }
01921 
01922                         if (cg_entities[es->eventParm].weapon >= cg.time)
01923                         { //rww - an unfortunately necessary hack to prevent double item pickups
01924                                 break;
01925                         }
01926 
01927                         //Hopefully even if this entity is somehow removed and replaced with, say, another
01928                         //item, this time will have expired by the time that item needs to be picked up.
01929                         //Of course, it's quite possible this will fail miserably, so if you've got a better
01930                         //solution then please do use it.
01931                         cg_entities[es->eventParm].weapon = cg.time+500;
01932 
01933                         if ( index < 1 || index >= bg_numItems ) {
01934                                 break;
01935                         }
01936                         item = &bg_itemlist[ index ];
01937 
01938                         if ( /*item->giType != IT_POWERUP && */item->giType != IT_TEAM) {
01939                                 if (item->pickup_sound && item->pickup_sound[0])
01940                                 {
01941                                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, trap_S_RegisterSound( item->pickup_sound ) );
01942                                 }
01943                         }
01944 
01945                         // show icon and name on status bar
01946                         if ( es->number == cg.snap->ps.clientNum ) {
01947                                 CG_ItemPickup( index );
01948                         }
01949                 }
01950                 break;
01951 
01952         case EV_GLOBAL_ITEM_PICKUP:
01953                 DEBUGNAME("EV_GLOBAL_ITEM_PICKUP");
01954                 {
01955                         gitem_t *item;
01956                         int             index;
01957 
01958                         index = es->eventParm;          // player predicted
01959 
01960                         if ( index < 1 || index >= bg_numItems ) {
01961                                 break;
01962                         }
01963                         item = &bg_itemlist[ index ];
01964                         // powerup pickups are global
01965                         if( item->pickup_sound && item->pickup_sound[0] ) {
01966                                 trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_AUTO, trap_S_RegisterSound( item->pickup_sound) );
01967                         }
01968 
01969                         // show icon and name on status bar
01970                         if ( es->number == cg.snap->ps.clientNum ) {
01971                                 CG_ItemPickup( index );
01972                         }
01973                 }
01974                 break;
01975 
01976         case EV_VEH_FIRE:
01977                 DEBUGNAME("EV_VEH_FIRE");
01978                 {
01979                         centity_t *veh = &cg_entities[es->owner];
01980                         CG_VehMuzzleFireFX(veh, es);
01981                 }
01982                 break;
01983 
01984         //
01985         // weapon events
01986         //
01987         case EV_NOAMMO:
01988                 DEBUGNAME("EV_NOAMMO");
01989 //              trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.noAmmoSound );
01990                 if ( es->number == cg.snap->ps.clientNum )
01991                 {
01992                         if ( CG_InFighter() || CG_InATST() || cg.snap->ps.weapon == WP_NONE )
01993                         {//just letting us know our vehicle is out of ammo
01994                                 //FIXME: flash something on HUD or give some message so we know we have no ammo
01995                                 centity_t *localCent = &cg_entities[cg.snap->ps.clientNum];
01996                                 if ( localCent->m_pVehicle 
01997                                         && localCent->m_pVehicle->m_pVehicleInfo
01998                                         && localCent->m_pVehicle->m_pVehicleInfo->weapon[es->eventParm].soundNoAmmo )
01999                                 {//play the "no Ammo" sound for this weapon
02000                                         trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_AUTO, localCent->m_pVehicle->m_pVehicleInfo->weapon[es->eventParm].soundNoAmmo );
02001                                 }
02002                                 else
02003                                 {//play the default "no ammo" sound
02004                                         trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.media.noAmmoSound );
02005                                 }
02006                                 //flash the HUD so they associate the sound with the visual indicator that they don't have enough ammo
02007                                 if ( cg_vehicleAmmoWarningTime < cg.time
02008                                         || cg_vehicleAmmoWarning != es->eventParm )
02009                                 {//if there's already one going, don't interrupt it (unless they tried to fire another weapon that's out of ammo)
02010                                         cg_vehicleAmmoWarning = es->eventParm;
02011                                         cg_vehicleAmmoWarningTime = cg.time+500;
02012                                 }
02013                         }
02014                         else if ( cg.snap->ps.weapon == WP_SABER )
02015                         {
02016                                 cg.forceHUDTotalFlashTime = cg.time + 1000;
02017                         }
02018                         else
02019                         {
02020                                 int weap = 0;
02021 
02022                                 if (es->eventParm && es->eventParm < WP_NUM_WEAPONS)
02023                                 {
02024                                         cg.snap->ps.stats[STAT_WEAPONS] &= ~(1 << es->eventParm);
02025                                         weap = cg.snap->ps.weapon;
02026                                 }
02027                                 else if (es->eventParm)
02028                                 {
02029                                         weap = (es->eventParm-WP_NUM_WEAPONS);
02030                                 }
02031                                 CG_OutOfAmmoChange(weap);
02032                         }
02033                 }
02034                 break;
02035         case EV_CHANGE_WEAPON:
02036                 DEBUGNAME("EV_CHANGE_WEAPON");
02037                 {
02038                         int weapon = es->eventParm;
02039                         weaponInfo_t *weaponInfo;
02040                         
02041                         assert(weapon >= 0 && weapon < MAX_WEAPONS);
02042 
02043                         weaponInfo = &cg_weapons[weapon];
02044 
02045                         assert(weaponInfo);
02046 
02047                         if (weaponInfo->selectSound)
02048                         {
02049                                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, weaponInfo->selectSound );
02050                         }
02051                         else if (weapon != WP_SABER)
02052                         { //not sure what SP is doing for this but I don't want a select sound for saber (it has the saber-turn-on)
02053                                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.selectSound );
02054                         }
02055                 }
02056                 break;
02057         case EV_FIRE_WEAPON:
02058                 DEBUGNAME("EV_FIRE_WEAPON");
02059                 if (cent->currentState.number >= MAX_CLIENTS && cent->currentState.eType != ET_NPC)
02060                 { //special case for turret firing
02061                         vec3_t gunpoint, gunangle;
02062                         mdxaBone_t matrix;
02063 
02064                         weaponInfo_t *weaponInfo = &cg_weapons[WP_TURRET];
02065 
02066                         if ( !weaponInfo->registered )
02067                         {
02068                                 CG_RegisterWeapon(WP_TURRET);
02069                         }
02070 
02071                         if (cent->ghoul2)
02072                         {
02073                                 if (!cent->bolt1)
02074                                 {
02075                                         cent->bolt1 = trap_G2API_AddBolt(cent->ghoul2, 0, "*flash01");
02076                                 }
02077                                 if (!cent->bolt2)
02078                                 {
02079                                         cent->bolt2 = trap_G2API_AddBolt(cent->ghoul2, 0, "*flash02");
02080                                 }
02081                                 trap_G2API_SetBoneAnim(cent->ghoul2, 0, "Bone02", 1, 4, BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND,
02082                                         1.0f, cg.time, -1, 300);
02083                         }
02084                         else
02085                         {
02086                                 break;
02087                         }
02088 
02089                         if (cent->currentState.eventParm)
02090                         {
02091                                 trap_G2API_GetBoltMatrix(cent->ghoul2, 0, cent->bolt2, &matrix, cent->currentState.angles, cent->currentState.origin, cg.time, cgs.gameModels, cent->modelScale);
02092                         }
02093                         else
02094                         {
02095                                 trap_G2API_GetBoltMatrix(cent->ghoul2, 0, cent->bolt1, &matrix, cent->currentState.angles, cent->currentState.origin, cg.time, cgs.gameModels, cent->modelScale);
02096                         }
02097 
02098                         gunpoint[0] = matrix.matrix[0][3];
02099                         gunpoint[1] = matrix.matrix[1][3];
02100                         gunpoint[2] = matrix.matrix[2][3];
02101 
02102                         gunangle[0] = -matrix.matrix[0][0];
02103                         gunangle[1] = -matrix.matrix[1][0];
02104                         gunangle[2] = -matrix.matrix[2][0];
02105 
02106                         trap_FX_PlayEffectID(cgs.effects.mEmplacedMuzzleFlash, gunpoint, gunangle, -1, -1);
02107                 }
02108                 else if (cent->currentState.weapon != WP_EMPLACED_GUN || cent->currentState.eType == ET_NPC)
02109                 {
02110                         if (cent->currentState.eType == ET_NPC &&
02111                                 cent->currentState.NPC_class == CLASS_VEHICLE &&
02112                                 cent->m_pVehicle)
02113                         { //vehicles do nothing for clientside weapon fire events.. at least for now.
02114                                 break;
02115                         }
02116                         CG_FireWeapon( cent, qfalse );
02117                 }
02118                 break;
02119 
02120         case EV_ALT_FIRE:
02121                 DEBUGNAME("EV_ALT_FIRE");
02122 
02123                 if (cent->currentState.weapon == WP_EMPLACED_GUN)
02124                 { //don't do anything for emplaced stuff
02125                         break;
02126                 }
02127 
02128                 if (cent->currentState.eType == ET_NPC &&
02129                         cent->currentState.NPC_class == CLASS_VEHICLE &&
02130                         cent->m_pVehicle)
02131                 { //vehicles do nothing for clientside weapon fire events.. at least for now.
02132                         break;
02133                 }
02134 
02135                 CG_FireWeapon( cent, qtrue );
02136 
02137                 //if you just exploded your detpacks and you have no ammo left for them, autoswitch
02138                 if ( cg.snap->ps.clientNum == cent->currentState.number &&
02139                         cg.snap->ps.weapon == WP_DET_PACK )
02140                 {
02141                         if (cg.snap->ps.ammo[weaponData[WP_DET_PACK].ammoIndex] == 0) 
02142                         {
02143                                 CG_OutOfAmmoChange(WP_DET_PACK);
02144                         }
02145                 }
02146 
02147                 break;
02148 
02149         case EV_SABER_ATTACK:
02150                 DEBUGNAME("EV_SABER_ATTACK");
02151                 {
02152                         qhandle_t swingSound = trap_S_RegisterSound(va("sound/weapons/saber/saberhup%i.wav", Q_irand(1, 8)));
02153                         clientInfo_t *client = NULL;
02154                         if ( cg_entities[es->number].currentState.eType == ET_NPC )
02155                         {
02156                                 client = cg_entities[es->number].npcClient;
02157                         }
02158                         else if ( es->number < MAX_CLIENTS )
02159                         {
02160                                 client = &cgs.clientinfo[es->number];
02161                         }
02162                         if ( client && client->infoValid && client->saber[0].swingSound[0] )
02163                         {//custom swing sound
02164                                 swingSound = client->saber[0].swingSound[Q_irand(0,2)];
02165                         }
02166             trap_S_StartSound(es->pos.trBase, es->number, CHAN_WEAPON, swingSound );
02167                 }
02168                 break;
02169 
02170         case EV_SABER_HIT:
02171                 DEBUGNAME("EV_SABER_HIT");
02172                 {
02173                         int hitPersonFxID = cgs.effects.mSaberBloodSparks;
02174                         int hitPersonSmallFxID = cgs.effects.mSaberBloodSparksSmall;
02175                         int hitPersonMidFxID = cgs.effects.mSaberBloodSparksMid;
02176                         int hitOtherFxID = cgs.effects.mSaberCut;
02177                         int hitSound = trap_S_RegisterSound(va("sound/weapons/saber/saberhit%i.wav", Q_irand(1, 3)));
02178                         
02179                         if ( es->otherEntityNum2 >= 0
02180                                 && es->otherEntityNum2 < ENTITYNUM_NONE )
02181                         {//we have a specific person who is causing this effect, see if we should override it with any custom saber effects/sounds
02182                                 clientInfo_t *client = NULL;
02183                                 if ( cg_entities[es->otherEntityNum2].currentState.eType == ET_NPC )
02184                                 {
02185                                         client = cg_entities[es->otherEntityNum2].npcClient;
02186                                 }
02187                                 else if ( es->otherEntityNum2 < MAX_CLIENTS )
02188                                 {
02189                                         client = &cgs.clientinfo[es->otherEntityNum2];
02190                                 }
02191                                 if ( client && client->infoValid )
02192                                 {
02193                                         int saberNum = es->weapon;
02194                                         int bladeNum = es->legsAnim;
02195                                         if ( WP_SaberBladeUseSecondBladeStyle( &client->saber[saberNum], bladeNum ) )
02196                                         {//use second blade style values
02197                                                 if ( client->saber[saberNum].hitPersonEffect2 )
02198                                                 {//custom hit person effect
02199                                                         hitPersonFxID = hitPersonSmallFxID = hitPersonMidFxID = client->saber[saberNum].hitPersonEffect2;
02200                                                 }
02201                                                 if ( client->saber[saberNum].hitOtherEffect2 )
02202                                                 {//custom hit other effect
02203                                                         hitOtherFxID = client->saber[saberNum].hitOtherEffect2;
02204                                                 }
02205                                                 if ( client->saber[saberNum].hit2Sound[0] )
02206                                                 {//custom hit sound
02207                                                         hitSound = client->saber[saberNum].hit2Sound[Q_irand(0,2)];
02208                                                 }
02209                                         }
02210                                         else
02211                                         {//use first blade style values
02212                                                 if ( client->saber[saberNum].hitPersonEffect )
02213                                                 {//custom hit person effect
02214                                                         hitPersonFxID = hitPersonSmallFxID = hitPersonMidFxID = client->saber[saberNum].hitPersonEffect;
02215                                                 }
02216                                                 if ( client->saber[saberNum].hitOtherEffect )
02217                                                 {//custom hit other effect
02218                                                         hitOtherFxID = client->saber[0].hitOtherEffect;
02219                                                 }
02220                                                 if ( client->saber[saberNum].hitSound[0] )
02221                                                 {//custom hit sound
02222                                                         hitSound = client->saber[saberNum].hitSound[Q_irand(0,2)];
02223                                                 }
02224                                         }
02225                                 }
02226                         }
02227 
02228                         if (es->eventParm == 16)
02229                         { //Make lots of sparks, something special happened
02230                                 vec3_t fxDir;
02231                                 VectorCopy(es->angles, fxDir);
02232                                 if (!fxDir[0] && !fxDir[1] && !fxDir[2])
02233                                 {
02234                                         fxDir[1] = 1;
02235                                 }
02236                                 trap_S_StartSound(es->origin, es->number, CHAN_AUTO, hitSound );
02237                                 trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02238                                 trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02239                                 trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02240                                 trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02241                                 trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02242                                 trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02243                         }
02244                         else if (es->eventParm)
02245                         { //hit a person
02246                                 vec3_t fxDir;
02247                                 VectorCopy(es->angles, fxDir);
02248                                 if (!fxDir[0] && !fxDir[1] && !fxDir[2])
02249                                 {
02250                                         fxDir[1] = 1;
02251                                 }
02252                                 trap_S_StartSound(es->origin, es->number, CHAN_AUTO, hitSound );
02253                                 if ( es->eventParm == 3 )
02254                                 {       // moderate or big hits.
02255                                         trap_FX_PlayEffectID( hitPersonSmallFxID, es->origin, fxDir, -1, -1 );
02256                                 }
02257                                 else if ( es->eventParm == 2 )
02258                                 {       // this is for really big hits.
02259                                         trap_FX_PlayEffectID( hitPersonMidFxID, es->origin, fxDir, -1, -1 );
02260                                 }
02261                                 else
02262                                 {       // this should really just be done in the effect itself, no?
02263                                         trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02264                                         trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02265                                         trap_FX_PlayEffectID( hitPersonFxID, es->origin, fxDir, -1, -1 );
02266                                 }
02267                         }
02268                         else
02269                         { //hit something else
02270                                 vec3_t fxDir;
02271                                 VectorCopy(es->angles, fxDir);
02272                                 if (!fxDir[0] && !fxDir[1] && !fxDir[2])
02273                                 {
02274                                         fxDir[1] = 1;
02275                                 }
02276                                 //old jk2mp method
02277                                 /*
02278                                 trap_S_StartSound(es->origin, es->number, CHAN_AUTO, trap_S_RegisterSound("sound/weapons/saber/saberhit.wav"));
02279                                 trap_FX_PlayEffectID( trap_FX_RegisterEffect("saber/spark.efx"), es->origin, fxDir, -1, -1 );
02280                                 */
02281 
02282                                 trap_FX_PlayEffectID( hitOtherFxID, es->origin, fxDir, -1, -1 );
02283                         }
02284 
02285                         //rww - this means we have the number of the ent being hit and the ent that owns the saber doing
02286                         //the hit. This being the case, we can store these indecies and the current time in order to do
02287                         //some visual tricks on the client between frames to make it look like we're actually continuing
02288                         //to hit between server frames.
02289                         if (es->otherEntityNum != ENTITYNUM_NONE && es->otherEntityNum2 != ENTITYNUM_NONE)
02290                         {
02291                                 centity_t *saberOwner;
02292 
02293                                 saberOwner = &cg_entities[es->otherEntityNum2];
02294 
02295                                 saberOwner->serverSaberHitIndex = es->otherEntityNum;
02296                                 saberOwner->serverSaberHitTime = cg.time;
02297 
02298                                 if (es->eventParm)
02299                                 {
02300                                         saberOwner->serverSaberFleshImpact = qtrue;
02301                                 }
02302                                 else
02303                                 {
02304                                         saberOwner->serverSaberFleshImpact = qfalse;
02305                                 }
02306                         }
02307                 }
02308                 break;
02309 
02310         case EV_SABER_BLOCK:
02311                 DEBUGNAME("EV_SABER_BLOCK");
02312                 {
02313                         if (es->eventParm)
02314                         { //saber block
02315                                 qboolean cullPass = qfalse;
02316                                 int                     blockFXID = cgs.effects.mSaberBlock;
02317                                 qhandle_t       blockSound = trap_S_RegisterSound(va( "sound/weapons/saber/saberblock%d.wav", Q_irand(1, 9) ));
02318                                 qboolean        noFlare = qfalse;
02319 
02320                                 if ( es->otherEntityNum2 >= 0
02321                                         && es->otherEntityNum2 < ENTITYNUM_NONE )
02322                                 {//we have a specific person who is causing this effect, see if we should override it with any custom saber effects/sounds
02323                                         clientInfo_t *client = NULL;
02324                                         if ( cg_entities[es->otherEntityNum2].currentState.eType == ET_NPC )
02325                                         {
02326                                                 client = cg_entities[es->otherEntityNum2].npcClient;
02327                                         }
02328                                         else if ( es->otherEntityNum2 < MAX_CLIENTS )
02329                                         {
02330                                                 client = &cgs.clientinfo[es->otherEntityNum2];
02331                                         }
02332                                         if ( client && client->infoValid )
02333                                         {
02334                                                 int saberNum = es->weapon;
02335                                                 int bladeNum = es->legsAnim;
02336                                                 if ( WP_SaberBladeUseSecondBladeStyle( &client->saber[saberNum], bladeNum ) )
02337                                                 {//use second blade style values
02338                                                         if ( client->saber[saberNum].blockEffect2 )
02339                                                         {//custom saber block effect
02340                                                                 blockFXID = client->saber[saberNum].blockEffect2;
02341                                                         }
02342                                                         if ( client->saber[saberNum].block2Sound[0] )
02343                                                         {//custom hit sound
02344                                                                 blockSound = client->saber[saberNum].block2Sound[Q_irand(0,2)];
02345                                                         }
02346                                                 }
02347                                                 else
02348                                                 {
02349                                                         if ( client->saber[saberNum].blockEffect )
02350                                                         {//custom saber block effect
02351                                                                 blockFXID = client->saber[saberNum].blockEffect;
02352                                                         }
02353                                                         if ( client->saber[saberNum].blockSound[0] )
02354                                                         {//custom hit sound
02355                                                                 blockSound = client->saber[saberNum].blockSound[Q_irand(0,2)];
02356                                                         }
02357                                                 }
02358                                                 if ( (client->saber[saberNum].saberFlags2&SFL2_NO_CLASH_FLARE) )
02359                                                 {
02360                                                         noFlare = qtrue;
02361                                                 }
02362                                         }
02363                                 }
02364                                 if (cg.mInRMG)
02365                                 {
02366                                         trace_t tr;
02367                                         vec3_t vecSub;
02368 
02369                                         VectorSubtract(cg.refdef.vieworg, es->origin, vecSub);
02370 
02371                                         if (VectorLength(vecSub) < 5000)
02372                                         {
02373                                                 CG_Trace(&tr, cg.refdef.vieworg, NULL, NULL, es->origin, ENTITYNUM_NONE, CONTENTS_TERRAIN|CONTENTS_SOLID);
02374 
02375                                                 if (tr.fraction == 1.0 || tr.entityNum < MAX_CLIENTS)
02376                                                 {
02377                                                         cullPass = qtrue;
02378                                                 }
02379                                         }
02380                                 }
02381                                 else
02382                                 {
02383                                         cullPass = qtrue;
02384                                 }
02385 
02386                                 if (cullPass)
02387                                 {
02388                                         vec3_t fxDir;
02389 
02390                                         VectorCopy(es->angles, fxDir);
02391                                         if (!fxDir[0] && !fxDir[1] && !fxDir[2])
02392                                         {
02393                                                 fxDir[1] = 1;
02394                                         }
02395                                         trap_S_StartSound(es->origin, es->number, CHAN_AUTO, blockSound );
02396                                         trap_FX_PlayEffectID( blockFXID, es->origin, fxDir, -1, -1 );
02397 
02398                                         if ( !noFlare )
02399                                         {
02400                                                 cg_saberFlashTime = cg.time-50;
02401                                                 VectorCopy( es->origin, cg_saberFlashPos );
02402                                         }
02403                                 }
02404                         }
02405                         else
02406                         { //projectile block
02407                                 vec3_t fxDir;
02408                                 VectorCopy(es->angles, fxDir);
02409                                 if (!fxDir[0] && !fxDir[1] && !fxDir[2])
02410                                 {
02411                                         fxDir[1] = 1;
02412                                 }
02413                                 trap_FX_PlayEffectID(cgs.effects.mBlasterDeflect, es->origin, fxDir, -1, -1);
02414                         }
02415                 }
02416                 break;
02417 
02418         case EV_SABER_CLASHFLARE:
02419                 DEBUGNAME("EV_SABER_CLASHFLARE");
02420                 {
02421                         qboolean cullPass = qfalse;
02422 
02423                         if (cg.mInRMG)
02424                         {
02425                                 trace_t tr;
02426                                 vec3_t vecSub;
02427 
02428                                 VectorSubtract(cg.refdef.vieworg, es->origin, vecSub);
02429 
02430                                 if (VectorLength(vecSub) < 5000)
02431                                 {
02432                                         CG_Trace(&tr, cg.refdef.vieworg, NULL, NULL, es->origin, ENTITYNUM_NONE, CONTENTS_TERRAIN|CONTENTS_SOLID);
02433 
02434                                         if (tr.fraction == 1.0 || tr.entityNum < MAX_CLIENTS)
02435                                         {
02436                                                 cullPass = qtrue;
02437                                         }
02438                                 }
02439                         }
02440                         else
02441                         {
02442                                 cullPass = qtrue;
02443                         }
02444 
02445                         if (cullPass)
02446                         {
02447                                 cg_saberFlashTime = cg.time-50;
02448                                 VectorCopy( es->origin, cg_saberFlashPos );
02449                         }
02450                         trap_S_StartSound ( es->origin, -1, CHAN_WEAPON, trap_S_RegisterSound( va("sound/weapons/saber/saberhitwall%i", Q_irand(1, 3)) ) );
02451                 }
02452                 break;
02453 
02454         case EV_SABER_UNHOLSTER:
02455                 DEBUGNAME("EV_SABER_UNHOLSTER");
02456                 {
02457                         clientInfo_t *ci = NULL;
02458 
02459                         if (es->eType == ET_NPC)
02460                         {
02461                                 ci = cg_entities[es->number].npcClient;
02462                         }
02463                         else if (es->number < MAX_CLIENTS)
02464                         {
02465                                 ci = &cgs.clientinfo[es->number];
02466                         }
02467 
02468                         if (ci)
02469                         {
02470                                 if (ci->saber[0].soundOn)
02471                                 {
02472                                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, ci->saber[0].soundOn );
02473                                 }
02474                                 if (ci->saber[1].soundOn)
02475                                 {
02476                                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, ci->saber[1].soundOn );
02477                                 }
02478                         }
02479                 }
02480                 break;
02481 
02482         case EV_BECOME_JEDIMASTER:
02483                 DEBUGNAME("EV_SABER_UNHOLSTER");
02484                 {
02485                         trace_t tr;
02486                         vec3_t playerMins = {-15, -15, DEFAULT_MINS_2+8};
02487                         vec3_t playerMaxs = {15, 15, DEFAULT_MAXS_2};
02488                         vec3_t ang, pos, dpos;
02489 
02490                         VectorClear(ang);
02491                         ang[ROLL] = 1;
02492 
02493                         VectorCopy(position, dpos);
02494                         dpos[2] -= 4096;
02495 
02496                         CG_Trace(&tr, position, playerMins, playerMaxs, dpos, es->number, MASK_SOLID);
02497                         VectorCopy(tr.endpos, pos);
02498                         
02499                         if (tr.fraction == 1)
02500                         {
02501                                 break;
02502                         }
02503                         trap_FX_PlayEffectID(cgs.effects.mJediSpawn, pos, ang, -1, -1);
02504 
02505                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, trap_S_RegisterSound( "sound/weapons/saber/saberon.wav" ) );
02506 
02507                         if (cg.snap->ps.clientNum == es->number)
02508                         {
02509                                 trap_S_StartLocalSound(cgs.media.happyMusic, CHAN_LOCAL);
02510                                 CGCam_SetMusicMult(0.3, 5000);
02511                         }
02512                 }
02513                 break;
02514 
02515         case EV_DISRUPTOR_MAIN_SHOT:
02516                 DEBUGNAME("EV_DISRUPTOR_MAIN_SHOT");
02517                 if (cent->currentState.eventParm != cg.snap->ps.clientNum ||
02518                         cg.renderingThirdPerson)
02519                 { //h4q3ry
02520                         CG_GetClientWeaponMuzzleBoltPoint(cent->currentState.eventParm, cent->currentState.origin2);
02521                 }
02522                 else
02523                 {
02524                         if (cg.lastFPFlashPoint[0] ||cg.lastFPFlashPoint[1] || cg.lastFPFlashPoint[2])
02525                         { //get the position of the muzzle flash for the first person weapon model from the last frame
02526                                 VectorCopy(cg.lastFPFlashPoint, cent->currentState.origin2);
02527                         }
02528                 }
02529                 FX_DisruptorMainShot( cent->currentState.origin2, cent->lerpOrigin ); 
02530                 break;
02531 
02532         case EV_DISRUPTOR_SNIPER_SHOT:
02533                 DEBUGNAME("EV_DISRUPTOR_SNIPER_SHOT");
02534                 if (cent->currentState.eventParm != cg.snap->ps.clientNum ||
02535                         cg.renderingThirdPerson)
02536                 { //h4q3ry
02537                         CG_GetClientWeaponMuzzleBoltPoint(cent->currentState.eventParm, cent->currentState.origin2);
02538                 }
02539                 else
02540                 {
02541                         if (cg.lastFPFlashPoint[0] ||cg.lastFPFlashPoint[1] || cg.lastFPFlashPoint[2])
02542                         { //get the position of the muzzle flash for the first person weapon model from the last frame
02543                                 VectorCopy(cg.lastFPFlashPoint, cent->currentState.origin2);
02544                         }
02545                 }
02546                 FX_DisruptorAltShot( cent->currentState.origin2, cent->lerpOrigin, cent->currentState.shouldtarget );
02547                 break;
02548 
02549         case EV_DISRUPTOR_SNIPER_MISS:
02550                 DEBUGNAME("EV_DISRUPTOR_SNIPER_MISS");
02551                 ByteToDir( es->eventParm, dir );
02552                 if (es->weapon)
02553                 { //primary
02554                         FX_DisruptorHitWall( cent->lerpOrigin, dir );
02555                 }
02556                 else
02557                 { //secondary
02558                         FX_DisruptorAltMiss( cent->lerpOrigin, dir );
02559                 }
02560                 break;
02561 
02562         case EV_DISRUPTOR_HIT:
02563                 DEBUGNAME("EV_DISRUPTOR_HIT");
02564                 ByteToDir( es->eventParm, dir );
02565                 if (es->weapon)
02566                 { //client
02567                         FX_DisruptorHitPlayer( cent->lerpOrigin, dir, qtrue );
02568                 }
02569                 else
02570                 { //non-client
02571                         FX_DisruptorHitWall( cent->lerpOrigin, dir );
02572                 }
02573                 break;
02574 
02575         case EV_DISRUPTOR_ZOOMSOUND:
02576                 DEBUGNAME("EV_DISRUPTOR_ZOOMSOUND");
02577                 if (es->number == cg.snap->ps.clientNum)
02578                 {
02579                         if (cg.snap->ps.zoomMode)
02580                         {
02581                                 trap_S_StartLocalSound(trap_S_RegisterSound("sound/weapons/disruptor/zoomstart.wav"), CHAN_AUTO);
02582                         }
02583                         else
02584                         {
02585                                 trap_S_StartLocalSound(trap_S_RegisterSound("sound/weapons/disruptor/zoomend.wav"), CHAN_AUTO);
02586                         }
02587                 }
02588                 break;
02589         case EV_PREDEFSOUND:
02590                 DEBUGNAME("EV_PREDEFSOUND");
02591                 {
02592                         int sID = -1;
02593 
02594                         switch (es->eventParm)
02595                         {
02596                         case PDSOUND_PROTECTHIT:
02597                                 sID = trap_S_RegisterSound("sound/weapons/force/protecthit.mp3");
02598                                 break;
02599                         case PDSOUND_PROTECT:
02600                                 sID = trap_S_RegisterSound("sound/weapons/force/protect.mp3");
02601                                 break;
02602                         case PDSOUND_ABSORBHIT:
02603                                 sID = trap_S_RegisterSound("sound/weapons/force/absorbhit.mp3");
02604                                 if (es->trickedentindex >= 0 && es->trickedentindex < MAX_CLIENTS)
02605                                 {
02606                                         int clnum = es->trickedentindex;
02607 
02608                                         cg_entities[clnum].teamPowerEffectTime = cg.time + 1000;
02609                                         cg_entities[clnum].teamPowerType = 3;
02610                                 }
02611                                 break;
02612                         case PDSOUND_ABSORB:
02613                                 sID = trap_S_RegisterSound("sound/weapons/force/absorb.mp3");
02614                                 break;
02615                         case PDSOUND_FORCEJUMP:
02616                                 sID = trap_S_RegisterSound("sound/weapons/force/jump.mp3");
02617                                 break;
02618                         case PDSOUND_FORCEGRIP:
02619                                 sID = trap_S_RegisterSound("sound/weapons/force/grip.mp3");
02620                                 break;
02621                         default:
02622                                 break;
02623                         }
02624 
02625                         if (sID != 1)
02626                         {
02627                                 trap_S_StartSound(es->origin, es->number, CHAN_AUTO, sID);
02628                         }
02629                 }
02630                 break;
02631 
02632         case EV_TEAM_POWER:
02633                 DEBUGNAME("EV_TEAM_POWER");
02634                 {
02635                         int clnum = 0;
02636 
02637                         while (clnum < MAX_CLIENTS)
02638                         {
02639                                 if (CG_InClientBitflags(es, clnum))
02640                                 {
02641                                         if (es->eventParm == 1)
02642                                         { //eventParm 1 is heal
02643                                                 trap_S_StartSound (NULL, clnum, CHAN_AUTO, cgs.media.teamHealSound );
02644                                                 cg_entities[clnum].teamPowerEffectTime = cg.time + 1000;
02645                                                 cg_entities[clnum].teamPowerType = 1;
02646                                         }
02647                                         else
02648                                         { //eventParm 2 is force regen
02649                                                 trap_S_StartSound (NULL, clnum, CHAN_AUTO, cgs.media.teamRegenSound );
02650                                                 cg_entities[clnum].teamPowerEffectTime = cg.time + 1000;
02651                                                 cg_entities[clnum].teamPowerType = 0;
02652                                         }
02653                                 }
02654                                 clnum++;
02655                         }
02656                 }
02657                 break;
02658 
02659         case EV_SCREENSHAKE:
02660                 DEBUGNAME("EV_SCREENSHAKE");
02661                 if (!es->modelindex || cg.predictedPlayerState.clientNum == es->modelindex-1)
02662                 {
02663                         CGCam_Shake(es->angles[0], es->time);
02664                 }
02665                 break;
02666         case EV_LOCALTIMER:
02667                 DEBUGNAME("EV_LOCALTIMER");
02668                 if (es->owner == cg.predictedPlayerState.clientNum)
02669                 {
02670                         CG_LocalTimingBar(es->time, es->time2);
02671                 }
02672                 break;
02673         case EV_USE_ITEM0:
02674                 DEBUGNAME("EV_USE_ITEM0");
02675                 CG_UseItem( cent );
02676                 break;
02677         case EV_USE_ITEM1:
02678                 DEBUGNAME("EV_USE_ITEM1");
02679                 CG_UseItem( cent );
02680                 break;
02681         case EV_USE_ITEM2:
02682                 DEBUGNAME("EV_USE_ITEM2");
02683                 CG_UseItem( cent );
02684                 break;
02685         case EV_USE_ITEM3:
02686                 DEBUGNAME("EV_USE_ITEM3");
02687                 CG_UseItem( cent );
02688                 break;
02689         case EV_USE_ITEM4:
02690                 DEBUGNAME("EV_USE_ITEM4");
02691                 CG_UseItem( cent );
02692                 break;
02693         case EV_USE_ITEM5:
02694                 DEBUGNAME("EV_USE_ITEM5");
02695                 CG_UseItem( cent );
02696                 break;
02697         case EV_USE_ITEM6:
02698                 DEBUGNAME("EV_USE_ITEM6");
02699                 CG_UseItem( cent );
02700                 break;
02701         case EV_USE_ITEM7:
02702                 DEBUGNAME("EV_USE_ITEM7");
02703                 CG_UseItem( cent );
02704                 break;
02705         case EV_USE_ITEM8:
02706                 DEBUGNAME("EV_USE_ITEM8");
02707                 CG_UseItem( cent );
02708                 break;
02709         case EV_USE_ITEM9:
02710                 DEBUGNAME("EV_USE_ITEM9");
02711                 CG_UseItem( cent );
02712                 break;
02713         case EV_USE_ITEM10:
02714                 DEBUGNAME("EV_USE_ITEM10");
02715                 CG_UseItem( cent );
02716                 break;
02717         case EV_USE_ITEM11:
02718                 DEBUGNAME("EV_USE_ITEM11");
02719                 CG_UseItem( cent );
02720                 break;
02721         case EV_USE_ITEM12:
02722                 DEBUGNAME("EV_USE_ITEM12");
02723                 CG_UseItem( cent );
02724                 break;
02725         case EV_USE_ITEM13:
02726                 DEBUGNAME("EV_USE_ITEM13");
02727                 CG_UseItem( cent );
02728                 break;
02729         case EV_USE_ITEM14:
02730                 DEBUGNAME("EV_USE_ITEM14");
02731                 CG_UseItem( cent );
02732                 break;
02733 
02734         case EV_ITEMUSEFAIL:
02735                 DEBUGNAME("EV_ITEMUSEFAIL");
02736                 if (cg.snap->ps.clientNum == es->number)
02737                 {
02738                         char *psStringEDRef = NULL;
02739 
02740                         switch(es->eventParm)
02741                         {
02742                         case SENTRY_NOROOM:
02743                                 psStringEDRef = (char *)CG_GetStringEdString("MP_INGAME", "SENTRY_NOROOM");
02744                                 break;
02745                         case SENTRY_ALREADYPLACED:
02746                                 psStringEDRef = (char *)CG_GetStringEdString("MP_INGAME", "SENTRY_ALREADYPLACED");
02747                                 break;
02748                         case SHIELD_NOROOM:
02749                                 psStringEDRef = (char *)CG_GetStringEdString("MP_INGAME", "SHIELD_NOROOM");
02750                                 break;
02751                         case SEEKER_ALREADYDEPLOYED:
02752                                 psStringEDRef = (char *)CG_GetStringEdString("MP_INGAME", "SEEKER_ALREADYDEPLOYED");
02753                                 break;
02754                         default:
02755                                 break;
02756                         }
02757 
02758                         if (!psStringEDRef)
02759                         {
02760                                 break;
02761                         }
02762 
02763                         Com_Printf("%s\n", psStringEDRef);
02764                 }
02765                 break;
02766 
02767         //=================================================================
02768 
02769         //
02770         // other events
02771         //
02772         case EV_PLAYER_TELEPORT_IN:
02773                 DEBUGNAME("EV_PLAYER_TELEPORT_IN");
02774                 {
02775                         trace_t tr;
02776                         vec3_t playerMins = {-15, -15, DEFAULT_MINS_2+8};
02777                         vec3_t playerMaxs = {15, 15, DEFAULT_MAXS_2};
02778                         vec3_t ang, pos, dpos;
02779 
02780                         VectorClear(ang);
02781                         ang[ROLL] = 1;
02782 
02783                         VectorCopy(position, dpos);
02784                         dpos[2] -= 4096;
02785 
02786                         CG_Trace(&tr, position, playerMins, playerMaxs, dpos, es->number, MASK_SOLID);
02787                         VectorCopy(tr.endpos, pos);
02788                         
02789                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleInSound );
02790 
02791                         if (tr.fraction == 1)
02792                         {
02793                                 break;
02794                         }
02795                         trap_FX_PlayEffectID(cgs.effects.mSpawn, pos, ang, -1, -1);
02796                 }
02797                 break;
02798 
02799         case EV_PLAYER_TELEPORT_OUT:
02800                 DEBUGNAME("EV_PLAYER_TELEPORT_OUT");
02801                 {
02802                         trace_t tr;
02803                         vec3_t playerMins = {-15, -15, DEFAULT_MINS_2+8};
02804                         vec3_t playerMaxs = {15, 15, DEFAULT_MAXS_2};
02805                         vec3_t ang, pos, dpos;
02806 
02807                         VectorClear(ang);
02808                         ang[ROLL] = 1;
02809 
02810                         VectorCopy(position, dpos);
02811                         dpos[2] -= 4096;
02812 
02813                         CG_Trace(&tr, position, playerMins, playerMaxs, dpos, es->number, MASK_SOLID);
02814                         VectorCopy(tr.endpos, pos);
02815 
02816                         trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleOutSound );
02817 
02818                         if (tr.fraction == 1)
02819                         {
02820                                 break;
02821                         }
02822                         trap_FX_PlayEffectID(cgs.effects.mSpawn, pos, ang, -1, -1);
02823                 }
02824                 break;
02825 
02826         case EV_ITEM_POP:
02827                 DEBUGNAME("EV_ITEM_POP");
02828                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound );
02829                 break;
02830         case EV_ITEM_RESPAWN:
02831                 DEBUGNAME("EV_ITEM_RESPAWN");
02832                 cent->miscTime = cg.time;       // scale up from this
02833                 trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound );
02834                 break;
02835 
02836         case EV_GRENADE_BOUNCE:
02837                 DEBUGNAME("EV_GRENADE_BOUNCE");
02838                 //Do something here?
02839                 break;
02840 
02841         case EV_SCOREPLUM:
02842                 DEBUGNAME("EV_SCOREPLUM");
02843                 CG_ScorePlum( cent->currentState.otherEntityNum, cent->lerpOrigin, cent->currentState.time );
02844                 break;
02845 
02846         case EV_CTFMESSAGE:
02847                 DEBUGNAME("EV_CTFMESSAGE");
02848                 CG_GetCTFMessageEvent(es);
02849                 break;
02850 
02851         case EV_BODYFADE:
02852                 if (es->eType != ET_BODY)
02853                 {
02854                         assert(!"EV_BODYFADE event from a non-corpse");
02855                         break;
02856                 }
02857                 
02858                 if (cent->ghoul2 && trap_G2_HaveWeGhoul2Models(cent->ghoul2))
02859                 {
02860                         //turn the inside of the face off, to avoid showing the mouth when we start alpha fading the corpse
02861                         trap_G2API_SetSurfaceOnOff( cent->ghoul2, "head_eyes_mouth", 0x00000002/*G2SURFACEFLAG_OFF*/ );
02862                 }
02863 
02864                 cent->bodyFadeTime = cg.time + 60000;
02865                 break;
02866 
02867         //
02868         // siege gameplay events
02869         //
02870         case EV_SIEGE_ROUNDOVER:
02871                 DEBUGNAME("EV_SIEGE_ROUNDOVER");
02872                 CG_SiegeRoundOver(&cg_entities[cent->currentState.weapon], cent->currentState.eventParm);
02873                 break;
02874         case EV_SIEGE_OBJECTIVECOMPLETE:
02875                 DEBUGNAME("EV_SIEGE_OBJECTIVECOMPLETE");
02876                 CG_SiegeObjectiveCompleted(&cg_entities[cent->currentState.weapon], cent->currentState.eventParm, cent->currentState.trickedentindex);
02877                 break;
02878 
02879         case EV_DESTROY_GHOUL2_INSTANCE:
02880                 DEBUGNAME("EV_DESTROY_GHOUL2_INSTANCE");
02881                 if (cg_entities[es->eventParm].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[es->eventParm].ghoul2))
02882                 {
02883                         if (es->eventParm < MAX_CLIENTS)
02884                         { //You try to do very bad thing!
02885 #ifdef _DEBUG
02886                                 Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a server event!\n");
02887 #endif
02888                                 break;
02889                         }
02890                         trap_G2API_CleanGhoul2Models(&(cg_entities[es->eventParm].ghoul2));
02891                 }
02892                 break;
02893 
02894         case EV_DESTROY_WEAPON_MODEL:
02895                 DEBUGNAME("EV_DESTROY_WEAPON_MODEL");
02896                 if (cg_entities[es->eventParm].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[es->eventParm].ghoul2) &&
02897                         trap_G2API_HasGhoul2ModelOnIndex(&(cg_entities[es->eventParm].ghoul2), 1))
02898                 {
02899                         trap_G2API_RemoveGhoul2Model(&(cg_entities[es->eventParm].ghoul2), 1);
02900                 }
02901                 break;
02902 
02903         case EV_GIVE_NEW_RANK:
02904                 DEBUGNAME("EV_GIVE_NEW_RANK");
02905                 if (es->trickedentindex == cg.snap->ps.clientNum)
02906                 {
02907                         trap_Cvar_Set("ui_rankChange", va("%i", es->eventParm));
02908 
02909                         trap_Cvar_Set("ui_myteam", va("%i", es->bolt2));
02910 
02911                         if (!( trap_Key_GetCatcher() & KEYCATCH_UI ) && !es->bolt1)
02912                         {
02913                                 trap_OpenUIMenu(UIMENU_PLAYERCONFIG);
02914                         }
02915                 }
02916                 break;
02917 
02918         case EV_SET_FREE_SABER:
02919                 DEBUGNAME("EV_SET_FREE_SABER");
02920 
02921                 trap_Cvar_Set("ui_freeSaber", va("%i", es->eventParm));
02922                 break;
02923 
02924         case EV_SET_FORCE_DISABLE:
02925                 DEBUGNAME("EV_SET_FORCE_DISABLE");
02926 
02927                 trap_Cvar_Set("ui_forcePowerDisable", va("%i", es->eventParm));
02928                 break;
02929 
02930         //
02931         // missile impacts
02932         //
02933         case EV_CONC_ALT_IMPACT:
02934                 DEBUGNAME("EV_CONC_ALT_IMPACT");
02935                 {
02936                         float dist;
02937                         float shotDist = VectorNormalize(es->angles);
02938                         vec3_t spot;
02939 
02940                         for (dist = 0.0f; dist < shotDist; dist += 64.0f)
02941                         { //one effect would be.. a whole lot better
02942                                 VectorMA( es->origin2, dist, es->angles, spot );
02943                 trap_FX_PlayEffectID(cgs.effects.mConcussionAltRing, spot, es->angles2, -1, -1);
02944                         }
02945 
02946                         ByteToDir( es->eventParm, dir );
02947                         CG_MissileHitWall(WP_CONCUSSION, es->owner, position, dir, IMPACTSOUND_DEFAULT, qtrue, 0);
02948 
02949                         FX_ConcAltShot(es->origin2, spot);
02950 
02951                         //steal the bezier effect from the disruptor
02952                         FX_DisruptorAltMiss(position, dir);
02953                 }
02954                 break;
02955 
02956         case EV_MISSILE_STICK:
02957                 DEBUGNAME("EV_MISSILE_STICK");
02958 //              trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.missileStick );
02959                 break;
02960 
02961         case EV_MISSILE_HIT:
02962                 DEBUGNAME("EV_MISSILE_HIT");
02963                 ByteToDir( es->eventParm, dir );
02964                 if ( es->emplacedOwner )
02965                 {//hack: this is an index to a custom effect to use
02966                         trap_FX_PlayEffectID(cgs.gameEffects[es->emplacedOwner], position, dir, -1, -1);
02967                 }
02968                 else if ( CG_VehicleWeaponImpact( cent ) )
02969                 {//a vehicle missile that uses an overridden impact effect...
02970                 }
02971                 else if (cent->currentState.eFlags & EF_ALT_FIRING)
02972                 {
02973                         CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum, qtrue);
02974                 }
02975                 else
02976                 {
02977                         CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum, qfalse);
02978                 }
02979 
02980                 if (cg_ghoul2Marks.integer &&
02981                         es->trickedentindex)
02982                 { //flag to place a ghoul2 mark
02983                         CG_G2MarkEvent(es);
02984                 }
02985                 break;
02986 
02987         case EV_MISSILE_MISS:
02988                 DEBUGNAME("EV_MISSILE_MISS");
02989                 ByteToDir( es->eventParm, dir );
02990                 if ( es->emplacedOwner )
02991                 {//hack: this is an index to a custom effect to use
02992                         trap_FX_PlayEffectID(cgs.gameEffects[es->emplacedOwner], position, dir, -1, -1);
02993                 }
02994                 else if ( CG_VehicleWeaponImpact( cent ) )
02995                 {//a vehicle missile that used an overridden impact effect...
02996                 }
02997                 else if (cent->currentState.eFlags & EF_ALT_FIRING)
02998                 {
02999                         CG_MissileHitWall(es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT, qtrue, es->generic1);
03000                 }
03001                 else
03002                 {
03003                         CG_MissileHitWall(es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT, qfalse, 0);
03004                 }
03005 
03006                 if (cg_ghoul2Marks.integer &&
03007                         es->trickedentindex)
03008                 { //flag to place a ghoul2 mark
03009                         CG_G2MarkEvent(es);
03010                 }
03011                 break;
03012 
03013         case EV_MISSILE_MISS_METAL:
03014                 DEBUGNAME("EV_MISSILE_MISS_METAL");
03015                 ByteToDir( es->eventParm, dir );
03016                 if ( es->emplacedOwner )
03017                 {//hack: this is an index to a custom effect to use
03018                         trap_FX_PlayEffectID(cgs.gameEffects[es->emplacedOwner], position, dir, -1, -1);
03019                 }
03020                 else if ( CG_VehicleWeaponImpact( cent ) )
03021                 {//a vehicle missile that used an overridden impact effect...
03022                 }
03023                 else if (cent->currentState.eFlags & EF_ALT_FIRING)
03024                 {
03025                         CG_MissileHitWall(es->weapon, 0, position, dir, IMPACTSOUND_METAL, qtrue, es->generic1);
03026                 }
03027                 else
03028                 {
03029                         CG_MissileHitWall(es->weapon, 0, position, dir, IMPACTSOUND_METAL, qfalse, 0);
03030                 }
03031                 break;
03032 
03033         case EV_PLAY_EFFECT:
03034                 DEBUGNAME("EV_PLAY_EFFECT");
03035                 switch(es->eventParm)
03036                 { //it isn't a hack, it's ingenuity!
03037                 case EFFECT_SMOKE:
03038                         eID = cgs.effects.mEmplacedDeadSmoke;
03039                         break;
03040                 case EFFECT_EXPLOSION:
03041                         eID = cgs.effects.mEmplacedExplode;
03042                         break;
03043                 case EFFECT_EXPLOSION_PAS:
03044                         eID = cgs.effects.mTurretExplode;
03045                         break;
03046                 case EFFECT_SPARK_EXPLOSION:
03047                         eID = cgs.effects.mSparkExplosion;
03048                         break;
03049                 case EFFECT_EXPLOSION_TRIPMINE:
03050                         eID = cgs.effects.mTripmineExplosion;
03051                         break;
03052                 case EFFECT_EXPLOSION_DETPACK:
03053                         eID = cgs.effects.mDetpackExplosion;
03054                         break;
03055                 case EFFECT_EXPLOSION_FLECHETTE:
03056                         eID = cgs.effects.mFlechetteAltBlow;
03057                         break;
03058                 case EFFECT_STUNHIT:
03059                         eID = cgs.effects.mStunBatonFleshImpact;
03060                         break;
03061                 case EFFECT_EXPLOSION_DEMP2ALT:
03062                         FX_DEMP2_AltDetonate( cent->lerpOrigin, es->weapon );
03063                         eID = cgs.effects.mAltDetonate;
03064                         break;
03065                 case EFFECT_EXPLOSION_TURRET:
03066                         eID = cgs.effects.mTurretExplode;
03067                         break;
03068                 case EFFECT_SPARKS:
03069                         eID = cgs.effects.mSparksExplodeNoSound;
03070                         break;
03071                 case EFFECT_WATER_SPLASH:
03072                         eID = cgs.effects.waterSplash;
03073                         break;
03074                 case EFFECT_ACID_SPLASH:
03075                         eID = cgs.effects.acidSplash;
03076                         break;
03077                 case EFFECT_LAVA_SPLASH:
03078                         eID = cgs.effects.lavaSplash;
03079                         break;
03080                 case EFFECT_LANDING_MUD:
03081                         eID = cgs.effects.landingMud;
03082                         break;
03083                 case EFFECT_LANDING_SAND:
03084                         eID = cgs.effects.landingSand;
03085                         break;
03086                 case EFFECT_LANDING_DIRT:
03087                         eID = cgs.effects.landingDirt;
03088                         break;
03089                 case EFFECT_LANDING_SNOW:
03090                         eID = cgs.effects.landingSnow;
03091                         break;
03092                 case EFFECT_LANDING_GRAVEL:
03093                         eID = cgs.effects.landingGravel;
03094                         break;
03095                 default:
03096                         eID = -1;
03097                         break;
03098                 }
03099 
03100                 if (eID != -1)
03101                 {
03102                         vec3_t fxDir;
03103 
03104                         VectorCopy(es->angles, fxDir);
03105 
03106                         if (!fxDir[0] && !fxDir[1] && !fxDir[2])
03107                         {
03108                                 fxDir[1] = 1;
03109                         }
03110 
03111                         trap_FX_PlayEffectID(eID, es->origin, fxDir, -1, -1);
03112                 }
03113                 break;
03114 
03115         case EV_PLAY_EFFECT_ID:
03116         case EV_PLAY_PORTAL_EFFECT_ID:
03117                 DEBUGNAME("EV_PLAY_EFFECT_ID");
03118                 {
03119                         vec3_t fxDir;
03120                         qboolean portalEffect = qfalse;
03121                         int efxIndex = 0;
03122 
03123                         if (event == EV_PLAY_PORTAL_EFFECT_ID)
03124                         { //This effect should only be played inside sky portals.
03125                                 portalEffect = qtrue;
03126                         }
03127 
03128                         AngleVectors(es->angles, fxDir, 0, 0);
03129                         
03130                         if (!fxDir[0] && !fxDir[1] && !fxDir[2])
03131                         {
03132                                 fxDir[1] = 1;
03133                         }
03134 
03135                         if ( cgs.gameEffects[ es->eventParm ] )
03136                         {
03137                                 efxIndex = cgs.gameEffects[es->eventParm];
03138                         }
03139                         else
03140                         {
03141                                 s = CG_ConfigString( CS_EFFECTS + es->eventParm );
03142                                 if (s && s[0])
03143                                 {
03144                                         efxIndex = trap_FX_RegisterEffect(s);
03145                                 }
03146                         }
03147 
03148                         if (efxIndex)
03149                         {
03150                                 if (portalEffect)
03151                                 {
03152                                         trap_FX_PlayPortalEffectID(efxIndex, position, fxDir, -1, -1 );
03153                                 }
03154                                 else
03155                                 {
03156                                         trap_FX_PlayEffectID(efxIndex, position, fxDir, -1, -1 );
03157                                 }
03158                         }
03159                 }
03160                 break;
03161 
03162         case EV_PLAYDOORSOUND:
03163                 CG_PlayDoorSound(cent, es->eventParm);
03164                 break;
03165         case EV_PLAYDOORLOOPSOUND:
03166                 CG_PlayDoorLoopSound(cent);
03167                 break;
03168         case EV_BMODEL_SOUND:
03169                 DEBUGNAME("EV_BMODEL_SOUND");
03170                 {
03171                         sfxHandle_t sfx;
03172                         const char *soundSet;
03173                         
03174                         soundSet = CG_ConfigString( CS_AMBIENT_SET + es->soundSetIndex );
03175 
03176                         if (!soundSet || !soundSet[0])
03177                         {
03178                                 break;
03179                         }
03180 
03181                         sfx = trap_AS_GetBModelSound(soundSet, es->eventParm);
03182 
03183                         if (sfx == -1)
03184                         {
03185                                 break;
03186                         }
03187 
03188                         trap_S_StartSound( NULL, es->number, CHAN_AUTO, sfx );
03189                 }
03190                 break;
03191 
03192 
03193         case EV_MUTE_SOUND:
03194                 DEBUGNAME("EV_MUTE_SOUND");
03195                 if (cg_entities[es->trickedentindex2].currentState.eFlags & EF_SOUNDTRACKER)
03196                 {
03197                         cg_entities[es->trickedentindex2].currentState.eFlags -= EF_SOUNDTRACKER;
03198                 }
03199                 trap_S_MuteSound(es->trickedentindex2, es->trickedentindex);
03200                 CG_S_StopLoopingSound(es->trickedentindex2, -1);
03201                 break;
03202 
03203         case EV_VOICECMD_SOUND:
03204                 DEBUGNAME("EV_VOICECMD_SOUND");
03205                 if (es->groundEntityNum >= MAX_CLIENTS)
03206                 { //don't ever use this unless it is being used on a real client
03207                         break;
03208                 }
03209                 {
03210                         sfxHandle_t sfx = cgs.gameSounds[ es->eventParm ];
03211                         clientInfo_t *ci = &cgs.clientinfo[es->groundEntityNum];
03212                         centity_t *vChatEnt = &cg_entities[es->groundEntityNum];
03213                         char descr[1024];
03214 
03215                         strcpy(descr, CG_GetStringForVoiceSound(CG_ConfigString( CS_SOUNDS + es->eventParm )));
03216 
03217                         if (!sfx)
03218                         {
03219                                 s = CG_ConfigString( CS_SOUNDS + es->eventParm );
03220                                 sfx = CG_CustomSound( es->groundEntityNum, s );
03221                         }
03222 
03223                         if (sfx)
03224                         {
03225                                 if (es->groundEntityNum != cg.predictedPlayerState.clientNum)
03226                                 { //play on the head as well to simulate hearing in radio and in world
03227                                         if (ci->team == cg.predictedPlayerState.persistant[PERS_TEAM])
03228                                         { //don't hear it if this person is on the other team, but they can still
03229                                                 //hear it in the world spot.
03230                                                 trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_MENU1, sfx);
03231                                         }
03232                                 }
03233                                 if (ci->team == cg.predictedPlayerState.persistant[PERS_TEAM])
03234                                 { //add to the chat box
03235                                         //hear it in the world spot.
03236                                         char vchatstr[1024];
03237                                         strcpy(vchatstr, va("<%s: %s>\n", ci->name, descr));
03238                                         CG_Printf(vchatstr);
03239                                         CG_ChatBox_AddString(vchatstr);
03240                                 }
03241 
03242                                 //and play in world for everyone
03243                                 trap_S_StartSound (NULL, es->groundEntityNum, CHAN_VOICE, sfx);
03244                                 vChatEnt->vChatTime = cg.time + 1000;
03245                         }
03246                 }
03247                 break;
03248 
03249         case EV_GENERAL_SOUND:
03250                 DEBUGNAME("EV_GENERAL_SOUND");
03251                 if (es->saberEntityNum == TRACK_CHANNEL_2 || es->saberEntityNum == TRACK_CHANNEL_3 ||
03252                         es->saberEntityNum == TRACK_CHANNEL_5)
03253                 { //channels 2 and 3 are for speed and rage, 5 for sight
03254                         if ( cgs.gameSounds[ es->eventParm ] )
03255                         {
03256                                 CG_S_AddRealLoopingSound(es->number, es->pos.trBase, vec3_origin, cgs.gameSounds[ es->eventParm ] );
03257                         }
03258                 }
03259                 else
03260                 {
03261                         if ( cgs.gameSounds[ es->eventParm ] ) {
03262                                 trap_S_StartSound (NULL, es->number, es->saberEntityNum, cgs.gameSounds[ es->eventParm ] );
03263                         } else {
03264                                 s = CG_ConfigString( CS_SOUNDS + es->eventParm );
03265                                 trap_S_StartSound (NULL, es->number, es->saberEntityNum, CG_CustomSound( es->number, s ) );
03266                         }
03267                 }
03268                 break;
03269 
03270         case EV_GLOBAL_SOUND:   // play from the player's head so it never diminishes
03271                 DEBUGNAME("EV_GLOBAL_SOUND");
03272                 if ( cgs.gameSounds[ es->eventParm ] ) {
03273                         trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_MENU1, cgs.gameSounds[ es->eventParm ] );
03274                 } else {
03275                         s = CG_ConfigString( CS_SOUNDS + es->eventParm );
03276                         trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_MENU1, CG_CustomSound( es->number, s ) );
03277                 }
03278                 break;
03279 
03280         case EV_GLOBAL_TEAM_SOUND:      // play from the player's head so it never diminishes
03281                 {
03282                         DEBUGNAME("EV_GLOBAL_TEAM_SOUND");
03283                         switch( es->eventParm ) {
03284                                 case GTS_RED_CAPTURE: // CTF: red team captured the blue flag, 1FCTF: red team captured the neutral flag
03285                                         //CG_AddBufferedSound( cgs.media.redScoredSound );
03286                                         break;
03287                                 case GTS_BLUE_CAPTURE: // CTF: blue team captured the red flag, 1FCTF: blue team captured the neutral flag
03288                                         //CG_AddBufferedSound( cgs.media.blueScoredSound );
03289                                         break;
03290                                 case GTS_RED_RETURN: // CTF: blue flag returned, 1FCTF: never used
03291                                         if (cgs.gametype == GT_CTY)
03292                                         {
03293                                                 CG_AddBufferedSound( cgs.media.blueYsalReturnedSound );
03294                                         }
03295                                         else
03296                                         {
03297                                                 CG_AddBufferedSound( cgs.media.blueFlagReturnedSound );
03298                                         }
03299                                         break;
03300                                 case GTS_BLUE_RETURN: // CTF red flag returned, 1FCTF: neutral flag returned
03301                                         if (cgs.gametype == GT_CTY)
03302                                         {
03303                                                 CG_AddBufferedSound( cgs.media.redYsalReturnedSound );
03304                                         }
03305                                         else
03306                                         {
03307                                                 CG_AddBufferedSound( cgs.media.redFlagReturnedSound );
03308                                         }
03309                                         break;
03310 
03311                                 case GTS_RED_TAKEN: // CTF: red team took blue flag, 1FCTF: blue team took the neutral flag
03312                                         // if this player picked up the flag then a sound is played in CG_CheckLocalSounds
03313                                         if (cgs.gametype == GT_CTY)
03314                                         {
03315                                                 CG_AddBufferedSound( cgs.media.redTookYsalSound );
03316                                         }
03317                                         else
03318                                         {
03319                                                 CG_AddBufferedSound( cgs.media.redTookFlagSound );
03320                                         }
03321                                         break;
03322                                 case GTS_BLUE_TAKEN: // CTF: blue team took the red flag, 1FCTF red team took the neutral flag
03323                                         // if this player picked up the flag then a sound is played in CG_CheckLocalSounds
03324                                         if (cgs.gametype == GT_CTY)
03325                                         {
03326                                                 CG_AddBufferedSound( cgs.media.blueTookYsalSound );
03327                                         }
03328                                         else
03329                                         {
03330                                                 CG_AddBufferedSound( cgs.media.blueTookFlagSound );
03331                                         }
03332                                         break;
03333                                 case GTS_REDTEAM_SCORED:
03334                                         CG_AddBufferedSound(cgs.media.redScoredSound);
03335                                         break;
03336                                 case GTS_BLUETEAM_SCORED:
03337                                         CG_AddBufferedSound(cgs.media.blueScoredSound);
03338                                         break;
03339                                 case GTS_REDTEAM_TOOK_LEAD:
03340                                         CG_AddBufferedSound(cgs.media.redLeadsSound);
03341                                         break;
03342                                 case GTS_BLUETEAM_TOOK_LEAD:
03343                                         CG_AddBufferedSound(cgs.media.blueLeadsSound);
03344                                         break;
03345                                 case GTS_TEAMS_ARE_TIED:
03346                                         CG_AddBufferedSound( cgs.media.teamsTiedSound );
03347                                         break;
03348                                 default:
03349                                         break;
03350                         }
03351                         break;
03352                 }
03353 
03354         case EV_ENTITY_SOUND:
03355                 DEBUGNAME("EV_ENTITY_SOUND");
03356                 //somewhat of a hack - weapon is the caller entity's index, trickedentindex is the proper sound channel
03357                 if ( cgs.gameSounds[ es->eventParm ] ) {
03358                         trap_S_StartSound (NULL, es->clientNum, es->trickedentindex, cgs.gameSounds[ es->eventParm ] );
03359                 } else {
03360                         s = CG_ConfigString( CS_SOUNDS + es->eventParm );
03361                         trap_S_StartSound (NULL, es->clientNum, es->trickedentindex, CG_CustomSound( es->clientNum, s ) );
03362                 }
03363                 break;
03364 
03365         case EV_PLAY_ROFF:
03366                 DEBUGNAME("EV_PLAY_ROFF");
03367                 trap_ROFF_Play(es->weapon, es->eventParm, es->trickedentindex);
03368                 break;
03369 
03370         case EV_GLASS_SHATTER:
03371                 DEBUGNAME("EV_GLASS_SHATTER");
03372                 CG_GlassShatter(es->genericenemyindex, es->origin, es->angles, es->trickedentindex, es->pos.trTime);
03373                 break;
03374 
03375         case EV_DEBRIS:
03376                 DEBUGNAME("EV_DEBRIS");
03377                 CG_Chunks(es->owner, es->origin, es->angles, es->origin2, es->angles2, es->speed,
03378                         es->eventParm, es->trickedentindex, es->modelindex, es->apos.trBase[0]);
03379                 break;
03380 
03381         case EV_MISC_MODEL_EXP:
03382                 DEBUGNAME("EV_MISC_MODEL_EXP");
03383                 CG_MiscModelExplosion(es->origin2, es->angles2, es->time, es->eventParm);
03384                 break;
03385 
03386         case EV_PAIN:
03387                 // local player sounds are triggered in CG_CheckLocalSounds,
03388                 // so ignore events on the player
03389                 DEBUGNAME("EV_PAIN");
03390 
03391                 if ( !cg_oldPainSounds.integer || (cent->currentState.number != cg.snap->ps.clientNum) )
03392                 {
03393                         CG_PainEvent( cent, es->eventParm );
03394                 }
03395                 break;
03396 
03397         case EV_DEATH1:
03398         case EV_DEATH2:
03399         case EV_DEATH3:
03400                 DEBUGNAME("EV_DEATHx");
03401                 trap_S_StartSound( NULL, es->number, CHAN_VOICE, 
03402                                 CG_CustomSound( es->number, va("*death%i.wav", event - EV_DEATH1 + 1) ) );
03403                 if (es->eventParm && es->number == cg.snap->ps.clientNum)
03404                 {
03405                         trap_S_StartLocalSound(cgs.media.dramaticFailure, CHAN_LOCAL);
03406                         CGCam_SetMusicMult(0.3, 5000);
03407                 }
03408                 break;
03409 
03410 
03411         case EV_OBITUARY:
03412                 DEBUGNAME("EV_OBITUARY");
03413                 CG_Obituary( es );
03414                 break;
03415 
03416         //
03417         // powerup events
03418         //
03419         case EV_POWERUP_QUAD:
03420                 DEBUGNAME("EV_POWERUP_QUAD");
03421                 if ( es->number == cg.snap->ps.clientNum ) {
03422                         cg.powerupActive = PW_QUAD;
03423                         cg.powerupTime = cg.time;
03424                 }
03425                 //trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.quadSound );
03426                 break;
03427         case EV_POWERUP_BATTLESUIT:
03428                 DEBUGNAME("EV_POWERUP_BATTLESUIT");
03429                 if ( es->number == cg.snap->ps.clientNum ) {
03430                         cg.powerupActive = PW_BATTLESUIT;
03431                         cg.powerupTime = cg.time;
03432                 }
03433                 //trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.protectSound );
03434                 break;
03435 
03436         case EV_FORCE_DRAINED:
03437                 DEBUGNAME("EV_FORCE_DRAINED");
03438                 ByteToDir( es->eventParm, dir );
03439                 //FX_ForceDrained(position, dir);
03440                 trap_S_StartSound (NULL, es->owner, CHAN_AUTO, cgs.media.drainSound );
03441                 cg_entities[es->owner].teamPowerEffectTime = cg.time + 1000;
03442                 cg_entities[es->owner].teamPowerType = 2;
03443                 break;
03444 
03445         case EV_GIB_PLAYER:
03446                 DEBUGNAME("EV_GIB_PLAYER");
03447                 //trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.gibSound );
03448                 //CG_GibPlayer( cent->lerpOrigin );
03449                 break;
03450 
03451         case EV_STARTLOOPINGSOUND:
03452                 DEBUGNAME("EV_STARTLOOPINGSOUND");
03453                 if ( cgs.gameSounds[ es->eventParm ] )
03454                 {
03455                         isnd = cgs.gameSounds[es->eventParm];
03456                 }
03457                 else
03458                 {
03459                         s = CG_ConfigString( CS_SOUNDS + es->eventParm );
03460                         isnd = CG_CustomSound(es->number, s);
03461                 }
03462 
03463                 CG_S_AddRealLoopingSound( es->number, es->pos.trBase, vec3_origin, isnd );
03464                 es->loopSound = isnd;
03465                 break;
03466 
03467         case EV_STOPLOOPINGSOUND:
03468                 DEBUGNAME("EV_STOPLOOPINGSOUND");
03469                 CG_S_StopLoopingSound( es->number, -1 );
03470                 es->loopSound = 0;
03471                 break;
03472 
03473         case EV_WEAPON_CHARGE:
03474                 DEBUGNAME("EV_WEAPON_CHARGE");
03475                 assert(es->eventParm > WP_NONE && es->eventParm < WP_NUM_WEAPONS);
03476                 if (cg_weapons[es->eventParm].chargeSound)
03477                 {
03478                         trap_S_StartSound(NULL, es->number, CHAN_WEAPON, cg_weapons[es->eventParm].chargeSound);
03479                 }
03480                 else if (es->eventParm == WP_DISRUPTOR)
03481                 {
03482                         trap_S_StartSound(NULL, es->number, CHAN_WEAPON, cgs.media.disruptorZoomLoop);
03483                 }
03484                 break;
03485 
03486         case EV_WEAPON_CHARGE_ALT:
03487                 DEBUGNAME("EV_WEAPON_CHARGE_ALT");
03488                 assert(es->eventParm > WP_NONE && es->eventParm < WP_NUM_WEAPONS);
03489                 if (cg_weapons[es->eventParm].altChargeSound)
03490                 {
03491                         trap_S_StartSound(NULL, es->number, CHAN_WEAPON, cg_weapons[es->eventParm].altChargeSound);
03492                 }
03493                 break;
03494 
03495         case EV_SHIELD_HIT:
03496                 DEBUGNAME("EV_SHIELD_HIT");
03497                 ByteToDir(es->eventParm, dir);
03498                 CG_PlayerShieldHit(es->otherEntityNum, dir, es->time2);
03499                 break;
03500 
03501         case EV_DEBUG_LINE:
03502                 DEBUGNAME("EV_DEBUG_LINE");
03503                 CG_Beam( cent );
03504                 break;
03505 
03506         case EV_TESTLINE:
03507                 DEBUGNAME("EV_TESTLINE");
03508                 CG_TestLine(es->origin, es->origin2, es->time2, es->weapon, 1);
03509                 break;
03510 
03511         default:
03512                 DEBUGNAME("UNKNOWN");
03513                 CG_Error( "Unknown event: %i", event );
03514                 break;
03515         }
03516 
03517 }
03518 
03519 
03520 /*
03521 ==============
03522 CG_CheckEvents
03523 
03524 ==============
03525 */
03526 void CG_CheckEvents( centity_t *cent ) {
03527         // check for event-only entities
03528         if ( cent->currentState.eType > ET_EVENTS ) {
03529                 if ( cent->previousEvent ) {
03530                         return; // already fired
03531                 }
03532                 // if this is a player event set the entity number of the client entity number
03533                 if ( cent->currentState.eFlags & EF_PLAYER_EVENT ) {
03534                         cent->currentState.number = cent->currentState.otherEntityNum;
03535                 }
03536 
03537                 cent->previousEvent = 1;
03538 
03539                 cent->currentState.event = cent->currentState.eType - ET_EVENTS;
03540         } else {
03541                 // check for events riding with another entity
03542                 if ( cent->currentState.event == cent->previousEvent ) {
03543                         return;
03544                 }
03545                 cent->previousEvent = cent->currentState.event;
03546                 if ( ( cent->currentState.event & ~EV_EVENT_BITS ) == 0 ) {
03547                         return;
03548                 }
03549         }
03550 
03551         // calculate the position at exactly the frame time
03552         BG_EvaluateTrajectory( &cent->currentState.pos, cg.snap->serverTime, cent->lerpOrigin );
03553         CG_SetEntitySoundPosition( cent );
03554 
03555         CG_EntityEvent( cent, cent->lerpOrigin );
03556 }
03557