/* ================= CG_ParseVoice voice clientNum vChan cmdNum trackNum [sayText] ================= */ static void CG_ParseVoice( void ) { int clientNum; voiceChannel_t vChan; char sayText[ MAX_SAY_TEXT ] = { "" }; voiceTrack_t *track; clientInfo_t *ci; if ( trap_Argc() < 5 || trap_Argc() > 6 ) { return; } if ( trap_Argc() == 6 ) { Q_strncpyz( sayText, CG_Argv( 5 ), sizeof( sayText ) ); } clientNum = atoi( CG_Argv( 1 ) ); if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) { return; } vChan = atoi( CG_Argv( 2 ) ); if ( ( unsigned ) vChan >= VOICE_CHAN_NUM_CHANS ) { return; } if ( cg_teamChatsOnly.integer && vChan != VOICE_CHAN_TEAM ) { return; } ci = &cgs.clientinfo[ clientNum ]; // this joker is still talking if ( ci->voiceTime > cg.time ) { return; } track = CG_VoiceTrack( ci->voice, atoi( CG_Argv( 3 ) ), atoi( CG_Argv( 4 ) ) ); // keep track of how long the player will be speaking // assume it takes 3s to say "*unintelligible gibberish*" if ( track ) { ci->voiceTime = cg.time + track->duration; } else { ci->voiceTime = cg.time + 3000; } if ( !sayText[ 0 ] ) { if ( track ) { Q_strncpyz( sayText, track->text, sizeof( sayText ) ); } else { Q_strncpyz( sayText, "*unintelligible gibberish*", sizeof( sayText ) ); } } if ( !cg_noVoiceText.integer ) { switch ( vChan ) { case VOICE_CHAN_ALL: CG_Say( NULL, clientNum, SAY_ALL, sayText ); break; case VOICE_CHAN_TEAM: CG_Say( NULL, clientNum, SAY_TEAM, sayText ); break; case VOICE_CHAN_LOCAL: CG_Say( NULL, clientNum, SAY_AREA_TEAM, sayText ); break; default: break; } } // playing voice audio tracks disabled if ( cg_noVoiceChats.integer ) { return; } // no audio track to play if ( !track ) { return; } // don't play audio track for lamers if ( Com_ClientListContains( &cgs.ignoreList, clientNum ) ) { return; } switch ( vChan ) { case VOICE_CHAN_ALL: trap_S_StartLocalSound( track->track, CHAN_VOICE ); break; case VOICE_CHAN_TEAM: trap_S_StartLocalSound( track->track, CHAN_VOICE ); break; case VOICE_CHAN_LOCAL: trap_S_StartSound( NULL, clientNum, CHAN_VOICE, track->track ); break; default: break; } }
/* ============== CG_DrawPlayerWeaponIcon ============== */ void CG_DrawPlayerWeaponIcon(rectDef_t *rect, int align, vec4_t *refcolor) { int size; int realweap; // DHM - Nerve qhandle_t icon; float scale, halfScale; vec4_t hcolor; VectorCopy(*refcolor, hcolor); hcolor[3] = 1.f; if (cg.predictedPlayerEntity.currentState.eFlags & EF_MG42_ACTIVE || cg.predictedPlayerEntity.currentState.eFlags & EF_MOUNTEDTANK) { realweap = WP_MOBILE_MG42; } else { realweap = cg.predictedPlayerState.weapon; } size = weapIconDrawSize(realweap); if (!size) { return; } if (cg.predictedPlayerEntity.currentState.eFlags & EF_MOUNTEDTANK && cg_entities[cg_entities[cg_entities[cg.snap->ps.clientNum].tagParent].tankparent].currentState.density & 8) { icon = cgs.media.browningIcon; } else { icon = cg_weapons[realweap].weaponIcon[1]; } // pulsing grenade icon to help the player 'count' in their head if (cg.predictedPlayerState.grenadeTimeLeft) { // grenades and dynamite set this // these time differently if (realweap == WP_DYNAMITE) { if (((cg.grenLastTime) % 1000) > ((cg.predictedPlayerState.grenadeTimeLeft) % 1000)) { trap_S_StartLocalSound(cgs.media.grenadePulseSound4, CHAN_LOCAL_SOUND); } } else { if (((cg.grenLastTime) % 1000) < ((cg.predictedPlayerState.grenadeTimeLeft) % 1000)) { switch (cg.predictedPlayerState.grenadeTimeLeft / 1000) { case 3: trap_S_StartLocalSound(cgs.media.grenadePulseSound4, CHAN_LOCAL_SOUND); break; case 2: trap_S_StartLocalSound(cgs.media.grenadePulseSound3, CHAN_LOCAL_SOUND); break; case 1: trap_S_StartLocalSound(cgs.media.grenadePulseSound2, CHAN_LOCAL_SOUND); break; case 0: trap_S_StartLocalSound(cgs.media.grenadePulseSound1, CHAN_LOCAL_SOUND); break; } } } scale = (float)((cg.predictedPlayerState.grenadeTimeLeft) % 1000) / 100.0f; halfScale = scale * 0.5f; cg.grenLastTime = cg.predictedPlayerState.grenadeTimeLeft; } else { scale = halfScale = 0; } if (icon) { float x, y, w, h; if (size == 1) { // draw half width to match the icon asset // start at left x = rect->x - halfScale; y = rect->y - halfScale; w = rect->w / 2 + scale; h = rect->h + scale; switch (align) { case ITEM_ALIGN_CENTER: x += rect->w / 4; break; case ITEM_ALIGN_RIGHT: x += rect->w / 2; break; case ITEM_ALIGN_LEFT: default: break; } } else { x = rect->x - halfScale; y = rect->y - halfScale; w = rect->w + scale; h = rect->h + scale; } trap_R_SetColor(hcolor); // JPW NERVE CG_DrawPic(x, y, w, h, icon); } }
/* =============== UI_DrawPlayer =============== */ void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs; refEntity_t torso; refEntity_t head; refEntity_t gun; refEntity_t flash; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) { return; } // this allows the ui to cache the player model on the main menu if (w == 0 || h == 0) { return; } dp_realtime = time; if ( pi->pendingWeapon != -1 && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = -1; pi->weaponTimer = 0; if( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL ); } } UI_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f); xx = refdef.width / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height, xx ); refdef.fov_y *= ( 360 / (float)M_PI ); // calculate distance so the player nearly fills the box len = 0.72 * ( maxs[2] - mins[2] ); origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_ClearScene(); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the legs // legs.hModel = pi->legsModel; legs.customSkin = pi->legsSkin; VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); legs.renderfx = renderfx; VectorCopy (legs.origin, legs.oldorigin); trap_R_AddRefEntityToScene( &legs ); if (!legs.hModel) { return; } // // add the torso // torso.hModel = pi->torsoModel; if (!torso.hModel) { return; } torso.customSkin = pi->torsoSkin; VectorCopy( origin, torso.lightingOrigin ); UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso"); torso.renderfx = renderfx; trap_R_AddRefEntityToScene( &torso ); // // add the head // head.hModel = pi->headModel; if (!head.hModel) { return; } head.customSkin = pi->headSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head"); head.renderfx = renderfx; trap_R_AddRefEntityToScene( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { memset( &gun, 0, sizeof(gun) ); gun.hModel = pi->weaponModel; VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon"); gun.renderfx = renderfx; trap_R_AddRefEntityToScene( &gun ); } // // add the spinning barrel // // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { if ( pi->flashModel ) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel; VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash"); flash.renderfx = renderfx; trap_R_AddRefEntityToScene( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddLightToScene( flash.origin, 200 + (rand()&31), pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2] ); } } // // add the chat icon // if ( pi->chat ) { UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); } // // add an accent light // origin[0] -= 100; // + = behind, - = in front origin[1] += 100; // + = left, - = right origin[2] += 100; // + = above, - = below trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 1.0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddLightToScene( origin, 500, 1.0, 0.0, 0.0 ); trap_R_RenderScene( &refdef ); }
void CG_SiegeRoundOver(centity_t *ent, int won) { int myTeam; char teamstr[64]; char appstring[1024]; char soundstr[1024]; int success = 0; playerState_t *ps = NULL; if (!siege_valid) { CG_Error("ERROR: Siege data does not exist on client!\n"); return; } if (cg.snap) { //this should always be true, if it isn't though use the predicted ps as a fallback ps = &cg.snap->ps; } else { ps = &cg.predictedPlayerState; } if (!ps) { assert(0); return; } myTeam = ps->persistant[PERS_TEAM]; if (myTeam == TEAM_SPECTATOR) { return; } if (myTeam == SIEGETEAM_TEAM1) { Com_sprintf(teamstr, sizeof(teamstr), team1); } else { Com_sprintf(teamstr, sizeof(teamstr), team2); } if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives)) { if (won == myTeam) { success = BG_SiegeGetPairedValue(cgParseObjectives, "wonround", appstring); } else { success = BG_SiegeGetPairedValue(cgParseObjectives, "lostround", appstring); } if (success) { CG_DrawSiegeMessage(appstring, 0); } appstring[0] = 0; soundstr[0] = 0; if (myTeam == won) { Com_sprintf(teamstr, sizeof(teamstr), "roundover_sound_wewon"); } else { Com_sprintf(teamstr, sizeof(teamstr), "roundover_sound_welost"); } if (BG_SiegeGetPairedValue(cgParseObjectives, teamstr, appstring)) { Com_sprintf(soundstr, sizeof(soundstr), appstring); } /* else { if (myTeam != won) { Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_LOSE_ROUND); } else { Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_WIN_ROUND); } } */ if (soundstr[0]) { trap_S_StartLocalSound(trap_S_RegisterSound(soundstr), CHAN_ANNOUNCER); } } }
/* ================== CG_CheckLocalSounds ================== */ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) { int reward, delta; // don't play the sounds if the player just spawned if( ps->persistant[ PERS_SPECSTATE ] != ops->persistant[ PERS_SPECSTATE ] ) return; //hitsound delta = ps->persistant[PERS_HITS] - ops->persistant[PERS_HITS]; if (cg_hitsound.integer == 3) { if (delta > 165) //125 trap_S_StartLocalSound( cgs.media.hitSound[8], CHAN_LOCAL_SOUND ); else if (delta > 120) //100 trap_S_StartLocalSound( cgs.media.hitSound[7], CHAN_LOCAL_SOUND ); else if (delta > 85) //75 trap_S_StartLocalSound( cgs.media.hitSound[6], CHAN_LOCAL_SOUND ); else if (delta > 50) trap_S_StartLocalSound( cgs.media.hitSound[5], CHAN_LOCAL_SOUND ); else if (delta > 25) trap_S_StartLocalSound( cgs.media.hitSound[4], CHAN_LOCAL_SOUND ); else if (delta > 12) trap_S_StartLocalSound( cgs.media.hitSound[3], CHAN_LOCAL_SOUND ); else if (delta > 8) trap_S_StartLocalSound( cgs.media.hitSound[2], CHAN_LOCAL_SOUND ); else if (delta > 4) trap_S_StartLocalSound( cgs.media.hitSound[1], CHAN_LOCAL_SOUND ); else if (delta > 0) //0 = no events trap_S_StartLocalSound( cgs.media.hitSound[0], CHAN_LOCAL_SOUND ); } else if (cg_hitsound.integer == 2) { if (delta > 8) trap_S_StartLocalSound( cgs.media.hitSound[8], CHAN_LOCAL_SOUND ); else if (delta > 7) trap_S_StartLocalSound( cgs.media.hitSound[7], CHAN_LOCAL_SOUND ); else if (delta > 6) trap_S_StartLocalSound( cgs.media.hitSound[6], CHAN_LOCAL_SOUND ); else if (delta > 5) trap_S_StartLocalSound( cgs.media.hitSound[5], CHAN_LOCAL_SOUND ); else if (delta > 4) trap_S_StartLocalSound( cgs.media.hitSound[4], CHAN_LOCAL_SOUND ); else if (delta > 3) trap_S_StartLocalSound( cgs.media.hitSound[3], CHAN_LOCAL_SOUND ); else if (delta > 2) trap_S_StartLocalSound( cgs.media.hitSound[2], CHAN_LOCAL_SOUND ); else if (delta > 1) trap_S_StartLocalSound( cgs.media.hitSound[1], CHAN_LOCAL_SOUND ); else if (delta > 0) //0 = no events trap_S_StartLocalSound( cgs.media.hitSound[0], CHAN_LOCAL_SOUND ); } else if (cg_hitsound.integer && (delta > 0)) //no tonal change trap_S_StartLocalSound( cgs.media.hitSound[4], CHAN_LOCAL_SOUND ); //health changes of more than -1 should make pain sounds //and don't play hurt sound if evolving if( ps->stats[ STAT_HEALTH ] < ops->stats[ STAT_HEALTH ] - 1 && ps->stats[ STAT_CLASS ] == ops->stats[ STAT_CLASS ] ) { float healthlost = ((ops->stats[ STAT_HEALTH ] - ps->stats[ STAT_HEALTH ])/ps->stats[ STAT_MAX_HEALTH ]); if( ps->stats[ STAT_HEALTH ] > 0 ) { CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[ STAT_HEALTH ] ); //play critical hit! sound if lost > 30% hp if (healthlost > 0.3) trap_S_StartLocalSound( cgs.media.hitSound[9], CHAN_LOCAL_SOUND ); } } //Don't spam it if the user is spamming spacebar up a stair (Urasai! Annoying!) if(cg_doublejumpsound.integer && ps->persistant[PERS_DOUBLEJUMPED] > ops->persistant[PERS_DOUBLEJUMPED]) { trap_S_StartLocalSound( cgs.media.doublejumpsound, CHAN_LOCAL_SOUND ); } // health changes of more than -1 should make pain sounds if( ps->stats[ STAT_HEALTH ] < ops->stats[ STAT_HEALTH ] - 1 ) { if( ps->stats[ STAT_HEALTH ] > 0 ) CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[ STAT_HEALTH ] ); } if( ( BG_UpgradeIsActive( UP_JETPACK, ps->stats ) || ( cg.predictedPlayerEntity.jetPackJumpTime + 1000 > cg.time && cg.predictedPlayerEntity.jetPackJumpTime + 250 < cg.time ) ) && ps->stats[ STAT_FUEL ] <= JETPACK_FUEL_LOW ) { static int last = 0; if( last + 740 < cg.time ) { trap_S_StartSound( NULL, cg.predictedPlayerState.clientNum, CHAN_AUTO, cgs.media.jetpackLowFuelSound ); last = cg.time; } } // if we are going into the intermission, don't start any voices if( cg.intermissionStarted ) return; // reward sounds reward = qfalse; }
/** The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv() */ static void CG_ServerCommand(void) { const char *cmd; char text[MAX_SAY_TEXT]; cmd = BG_Argv(0); if (!cmd[0]) { // server claimed the command return; } if (!strcmp(cmd, "cp")) { CG_CenterPrint(BG_Argv(1)); return; } if (!strcmp(cmd, "cs")) { CG_ConfigStringModified(); return; } if (!strcmp(cmd, "pings")) { CG_ParsePings(); return; } if (!strcmp(cmd, "tinfo")) { CG_ParseTeamInfo(); } if (!strcmp(cmd, "print")) { CG_Printf("%s", BG_Argv(1)); return; } if (!strcmp(cmd, "screenprint")) { Q_strncpyz(text, BG_Argv(1), sizeof text); CG_AddScreenMessage(text, qfalse); CG_Printf("%s\n", text); return; } if (!strcmp(cmd, "s")) { CG_ParseScores(); return; } if (!strcmp(cmd, "stats")) { CG_ParseStats(); return; } if (!strcmp(cmd, "chat")) { if (cg_teamChatsOnly.integer) { return; } if (cg_teamChatBeep.integer) { trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); } Q_strncpyz(text, BG_Argv(1), sizeof text); CG_RemoveChatEscapeChar(text); CG_AddScreenMessage(text, qfalse); CG_Printf("%s\n", text); return; } if (!strcmp(cmd, "tchat")) { if (cg_chatBeep.integer) { trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); } Q_strncpyz(text, BG_Argv(1), sizeof text); CG_RemoveChatEscapeChar(text); CG_AddScreenMessage(text, qtrue); CG_Printf("%s\n", text); return; } if (!strcmp(cmd, "map_restart")) { CG_MapRestart(); return; } if (!strcmp(cmd, "remapShader") == 0) { if (trap_Argc() == 4) { char shader1[MAX_QPATH]; char shader2[MAX_QPATH]; char shader3[MAX_QPATH]; Q_strncpyz(shader1, BG_Argv(1), sizeof(shader1)); Q_strncpyz(shader2, BG_Argv(2), sizeof(shader2)); Q_strncpyz(shader3, BG_Argv(3), sizeof(shader3)); trap_R_RemapShader(shader1, shader2, shader3); } return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if (!strcmp(cmd, "clientLevelShot")) { cg.levelShot = qtrue; return; } CG_Printf("Unknown client game command: %s\n", cmd); }
/* ============== CG_EntityEvent An entity has an event value also called by CG_CheckPlayerstateEvents ============== */ void CG_EntityEvent( centity_t *cent, vec3_t position ) { entityState_t *es; int event; vec3_t dir; const char *s; int clientNum; clientInfo_t *ci; int steptime; if ( cg.snap->ps.persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT ) { steptime = 200; } else { steptime = BG_Class( cg.snap->ps.stats[ STAT_CLASS ] )->steptime; } es = ¢->currentState; event = es->event & ~EV_EVENT_BITS; if ( cg_debugEvents.integer ) { CG_Printf( "ent:%3i event:%3i %s\n", es->number, event, BG_EventName( event ) ); } if ( !event ) { return; } clientNum = es->clientNum; if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) { clientNum = 0; } ci = &cgs.clientinfo[ clientNum ]; switch ( event ) { case EV_FOOTSTEP: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { if ( ci->footsteps == FOOTSTEP_CUSTOM ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, ci->customFootsteps[ rand() & 3 ] ); } else { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ ci->footsteps ][ rand() & 3 ] ); } } break; case EV_FOOTSTEP_METAL: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { if ( ci->footsteps == FOOTSTEP_CUSTOM ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, ci->customMetalFootsteps[ rand() & 3 ] ); } else { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_METAL ][ rand() & 3 ] ); } } break; case EV_FOOTSTEP_SQUELCH: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_FLESH ][ rand() & 3 ] ); } break; case EV_FOOTSPLASH: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand() & 3 ] ); } break; case EV_FOOTWADE: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand() & 3 ] ); } break; case EV_SWIM: if ( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand() & 3 ] ); } break; case EV_FALL_SHORT: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.landSound ); if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -8; cg.landTime = cg.time; } break; case EV_FALL_MEDIUM: // use a general pain sound trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*pain100_1.wav" ) ); if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -16; cg.landTime = cg.time; } break; case EV_FALL_FAR: trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*fall1.wav" ) ); cent->pe.painTime = cg.time; // don't play a pain sound right after this if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -24; cg.landTime = cg.time; } break; case EV_FALLING: trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*falling1.wav" ) ); break; case EV_STEP_4: case EV_STEP_8: case EV_STEP_12: case EV_STEP_16: // smooth out step up transitions case EV_STEPDN_4: case EV_STEPDN_8: case EV_STEPDN_12: case EV_STEPDN_16: // smooth out step down transitions { float oldStep; int delta; int step; if ( clientNum != cg.predictedPlayerState.clientNum ) { break; } // if we are interpolating, we don't need to smooth steps if ( cg.demoPlayback || ( cg.snap->ps.pm_flags & PMF_FOLLOW ) || cg_nopredict.integer || cg_synchronousClients.integer ) { break; } // check for stepping up before a previous step is completed delta = cg.time - cg.stepTime; if ( delta < steptime ) { oldStep = cg.stepChange * ( steptime - delta ) / steptime; } else { oldStep = 0; } // add this amount if ( event >= EV_STEPDN_4 ) { step = 4 * ( event - EV_STEPDN_4 + 1 ); cg.stepChange = oldStep - step; } else { step = 4 * ( event - EV_STEP_4 + 1 ); cg.stepChange = oldStep + step; } if ( cg.stepChange > MAX_STEP_CHANGE ) { cg.stepChange = MAX_STEP_CHANGE; } else if ( cg.stepChange < -MAX_STEP_CHANGE ) { cg.stepChange = -MAX_STEP_CHANGE; } cg.stepTime = cg.time; break; } case EV_JUMP: trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); if ( BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_CLASS ], SCA_WALLJUMPER ) ) { vec3_t surfNormal, refNormal = { 0.0f, 0.0f, 1.0f }; vec3_t rotAxis; if ( clientNum != cg.predictedPlayerState.clientNum ) { break; } //set surfNormal VectorCopy( cg.predictedPlayerState.grapplePoint, surfNormal ); //if we are moving from one surface to another smooth the transition if ( !VectorCompare( surfNormal, cg.lastNormal ) && surfNormal[ 2 ] != 1.0f ) { CrossProduct( refNormal, surfNormal, rotAxis ); VectorNormalize( rotAxis ); //add the op CG_addSmoothOp( rotAxis, 15.0f, 1.0f ); } //copy the current normal to the lastNormal VectorCopy( surfNormal, cg.lastNormal ); } break; case EV_LEV1_GRAB: trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL1Grab ); break; case EV_LEV4_TRAMPLE_PREPARE: trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargePrepare ); break; case EV_LEV4_TRAMPLE_START: //FIXME: stop cgs.media.alienL4ChargePrepare playing here trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargeStart ); break; case EV_TAUNT: if ( !cg_noTaunt.integer ) { trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*taunt.wav" ) ); } break; case EV_WATER_TOUCH: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrInSound ); break; case EV_WATER_LEAVE: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound ); break; case EV_WATER_UNDER: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound ); break; case EV_WATER_CLEAR: trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*gasp.wav" ) ); break; case EV_JETPACK_ENABLE: // TODO: Trigger jetpack enable animation break; case EV_JETPACK_DISABLE: // TODO: Trigger jetpack disable animation break; case EV_JETPACK_START: // TODO: Start jetpack gfx/sfx break; case EV_JETPACK_STOP: // TODO: Stop jetpack gfx/sfx break; case EV_NOAMMO: trap_S_StartSound( NULL, es->number, CHAN_WEAPON, cgs.media.weaponEmptyClick ); break; case EV_CHANGE_WEAPON: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.selectSound ); break; case EV_FIRE_WEAPON: CG_HandleFireWeapon( cent, WPM_PRIMARY ); break; case EV_FIRE_WEAPON2: CG_HandleFireWeapon( cent, WPM_SECONDARY ); break; case EV_FIRE_WEAPON3: CG_HandleFireWeapon( cent, WPM_TERTIARY ); break; case EV_WEAPON_RELOAD: if ( cg_weapons[ es->eventParm ].wim[ WPM_PRIMARY ].reloadSound ) { trap_S_StartSound( NULL, es->number, CHAN_WEAPON, cg_weapons[ es->eventParm ].wim[ WPM_PRIMARY ].reloadSound ); } break; case EV_PLAYER_TELEPORT_IN: //deprecated break; case EV_PLAYER_TELEPORT_OUT: CG_PlayerDisconnect( position ); break; case EV_BUILD_CONSTRUCT: break; case EV_BUILD_DESTROY: break; case EV_AMMO_REFILL: case EV_CLIPS_REFILL: case EV_FUEL_REFILL: // TODO: Add different sounds for EV_AMMO_REFILL, EV_CLIPS_REFILL, EV_FUEL_REFILL trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.repeaterUseSound ); break; case EV_GRENADE_BOUNCE: if ( rand() & 1 ) { trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.hardBounceSound1 ); } else { trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.hardBounceSound2 ); } break; case EV_WEAPON_HIT_ENTITY: CG_HandleWeaponHitEntity( es, position ); break; case EV_WEAPON_HIT_ENVIRONMENT: CG_HandleWeaponHitWall( es, position ); break; case EV_MISSILE_HIT_ENTITY: CG_HandleMissileHitEntity( es, position ); break; // currently there is no support for metal sounds case EV_MISSILE_HIT_ENVIRONMENT: case EV_MISSILE_HIT_METAL: CG_HandleMissileHitWall( es, position ); break; case EV_SHOTGUN: CG_HandleFireShotgun( es ); break; case EV_HUMAN_BUILDABLE_DYING: CG_HumanBuildableDying( (buildable_t) es->modelindex, position ); break; case EV_HUMAN_BUILDABLE_EXPLOSION: ByteToDir( es->eventParm, dir ); CG_HumanBuildableExplosion( (buildable_t) es->modelindex, position, dir ); break; case EV_ALIEN_BUILDABLE_EXPLOSION: ByteToDir( es->eventParm, dir ); CG_AlienBuildableExplosion( position, dir ); break; case EV_TESLATRAIL: cent->currentState.weapon = WP_TESLAGEN; { centity_t *source = &cg_entities[ es->generic1 ]; centity_t *target = &cg_entities[ es->clientNum ]; vec3_t sourceOffset = { 0.0f, 0.0f, 28.0f }; if ( !CG_IsTrailSystemValid( &source->muzzleTS ) ) { source->muzzleTS = CG_SpawnNewTrailSystem( cgs.media.teslaZapTS ); if ( CG_IsTrailSystemValid( &source->muzzleTS ) ) { CG_SetAttachmentCent( &source->muzzleTS->frontAttachment, source ); CG_SetAttachmentCent( &source->muzzleTS->backAttachment, target ); CG_AttachToCent( &source->muzzleTS->frontAttachment ); CG_AttachToCent( &source->muzzleTS->backAttachment ); CG_SetAttachmentOffset( &source->muzzleTS->frontAttachment, sourceOffset ); source->muzzleTSDeathTime = cg.time + cg_teslaTrailTime.integer; } } } break; case EV_GENERAL_SOUND: if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.gameSounds[ es->eventParm ] ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, s ) ); } break; case EV_GLOBAL_SOUND: // play from the player's head so it never diminishes if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.gameSounds[ es->eventParm ] ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, CG_CustomSound( es->number, s ) ); } break; case EV_PAIN: // local player sounds are triggered in CG_CheckLocalSounds, // so ignore events on the player if ( cent->currentState.number != cg.snap->ps.clientNum ) { CG_PainEvent( cent, es->eventParm ); } break; case EV_DEATH1: case EV_DEATH2: case EV_DEATH3: trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, va( "*death%i.wav", event - EV_DEATH1 + 1 ) ) ); break; case EV_OBITUARY: CG_Obituary( es ); break; case EV_GIB_PLAYER: // no gibbing break; case EV_STOPLOOPINGSOUND: trap_S_StopLoopingSound( es->number ); es->loopSound = 0; break; case EV_DEBUG_LINE: CG_Beam( cent ); break; case EV_BUILD_DELAY: if ( clientNum == cg.predictedPlayerState.clientNum ) { trap_S_StartLocalSound( cgs.media.buildableRepairedSound, CHAN_LOCAL_SOUND ); cg.lastBuildAttempt = cg.time; } break; case EV_BUILD_REPAIR: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairSound ); break; case EV_BUILD_REPAIRED: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairedSound ); break; case EV_OVERMIND_ATTACK_1: case EV_OVERMIND_ATTACK_2: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienOvermindAttack, CHAN_ANNOUNCER ); CG_CenterPrint( va( "^%c%s", "31"[ event - EV_OVERMIND_ATTACK_1 ], _( "The Overmind is under attack!" ) ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_OVERMIND_DYING: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienOvermindDying, CHAN_ANNOUNCER ); CG_CenterPrint( _( "^1The Overmind is dying!" ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_REACTOR_ATTACK_1: case EV_REACTOR_ATTACK_2: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_HUMANS ) { CG_CenterPrint( va( "^%c%s", "31"[ event - EV_REACTOR_ATTACK_1 ], _( "The reactor is under attack!" ) ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_REACTOR_DYING: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_HUMANS ) { CG_CenterPrint( _( "^1The reactor is about to explode!" ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_WARN_ATTACK: // if eventParm is non-zero, this is for humans and there's a nearby reactor or repeater, otherwise it's for aliens if ( es->eventParm >= MAX_CLIENTS && es->eventParm < MAX_GENTITIES ) { const char *location; qboolean base = cg_entities[ es->eventParm ].currentState.modelindex == BA_H_REACTOR; centity_t *locent = CG_GetLocation( cg_entities[ es->eventParm ].currentState.origin ); CG_CenterPrint( base ? _( "Our base is under attack!" ) : _( "A forward base is under attack!" ), 200, GIANTCHAR_WIDTH * 4 ); if ( locent ) { location = CG_ConfigString( CS_LOCATIONS + locent->currentState.generic1 ); } else { location = CG_ConfigString( CS_LOCATIONS ); } if ( location && *location ) { Com_Printf( _( "%s Under attack – %s\n" ), base ? "[reactor]" : "[repeater]", location ); } else { Com_Printf( _( "%s Under attack\n" ), base ? "[reactor]" : "[repeater]" ); } } else // this is for aliens, and the overmind is in range { CG_CenterPrint( _( "Our base is under attack!" ), 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_MGTURRET_SPINUP: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.turretSpinupSound ); break; case EV_OVERMIND_SPAWNS: if ( cg.predictedPlayerState.persistant[ PERS_TEAM ] == TEAM_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienOvermindSpawns, CHAN_ANNOUNCER ); CG_CenterPrint( "The Overmind needs spawns!", 200, GIANTCHAR_WIDTH * 4 ); } break; case EV_ALIEN_EVOLVE: trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienEvolveSound ); { particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.alienEvolvePS ); if ( CG_IsParticleSystemValid( &ps ) ) { CG_SetAttachmentCent( &ps->attachment, cent ); CG_AttachToCent( &ps->attachment ); } } if ( es->number == cg.clientNum ) { CG_ResetPainBlend(); cg.spawnTime = cg.time; } break; case EV_ALIEN_EVOLVE_FAILED: if ( clientNum == cg.predictedPlayerState.clientNum ) { //FIXME: change to "negative" sound trap_S_StartLocalSound( cgs.media.buildableRepairedSound, CHAN_LOCAL_SOUND ); cg.lastEvolveAttempt = cg.time; } break; case EV_ALIEN_ACIDTUBE: { particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.alienAcidTubePS ); if ( CG_IsParticleSystemValid( &ps ) ) { CG_SetAttachmentCent( &ps->attachment, cent ); ByteToDir( es->eventParm, dir ); CG_SetParticleSystemNormal( ps, dir ); CG_AttachToCent( &ps->attachment ); } } break; case EV_MEDKIT_USED: trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.medkitUseSound ); break; case EV_PLAYER_RESPAWN: if ( es->number == cg.clientNum ) { cg.spawnTime = cg.time; } break; case EV_LEV2_ZAP: CG_Level2Zap( es ); break; case EV_HIT: cg.hitTime = cg.time; break; case EV_MOMENTUM: CG_Momentum( es ); break; default: CG_Error( "Unknown event: %i", event ); } }
/* ================ CG_ConfigStringModified ================ */ static void CG_ConfigStringModified( void ) { const char *str; int num; num = atoi( CG_Argv( 1 ) ); // get the gamestate from the client system, which will have the // new configstring already integrated trap_GetGameState( &cgs.gameState ); // look up the individual string that was modified str = CG_ConfigString( num ); // do something with it if necessary if ( num == CS_MUSIC ) { CG_StartMusic(); } else if ( num == CS_SERVERINFO ) { CG_ParseServerinfo(); } else if ( num == CS_WARMUP ) { CG_ParseWarmup(); } else if ( num == CS_SCORES1 ) { cgs.scores1 = atoi( str ); } else if ( num == CS_SCORES2 ) { cgs.scores2 = atoi( str ); } else if ( num == CS_LEVEL_START_TIME ) { cgs.levelStartTime = atoi( str ); } else if ( num == CS_VOTE_TIME ) { cgs.voteTime = atoi( str ); cgs.voteModified = qtrue; } else if ( num == CS_VOTE_YES ) { cgs.voteYes = atoi( str ); cgs.voteModified = qtrue; } else if ( num == CS_VOTE_NO ) { cgs.voteNo = atoi( str ); cgs.voteModified = qtrue; } else if ( num == CS_VOTE_STRING ) { Q_strncpyz( cgs.voteString, str, sizeof( cgs.voteString ) ); #ifdef MISSIONPACK trap_S_StartLocalSound( cgs.media.voteNow, CHAN_ANNOUNCER ); #endif //MISSIONPACK } else if ( num >= CS_TEAMVOTE_TIME && num <= CS_TEAMVOTE_TIME + 1) { cgs.teamVoteTime[num-CS_TEAMVOTE_TIME] = atoi( str ); cgs.teamVoteModified[num-CS_TEAMVOTE_TIME] = qtrue; } else if ( num >= CS_TEAMVOTE_YES && num <= CS_TEAMVOTE_YES + 1) { cgs.teamVoteYes[num-CS_TEAMVOTE_YES] = atoi( str ); cgs.teamVoteModified[num-CS_TEAMVOTE_YES] = qtrue; } else if ( num >= CS_TEAMVOTE_NO && num <= CS_TEAMVOTE_NO + 1) { cgs.teamVoteNo[num-CS_TEAMVOTE_NO] = atoi( str ); cgs.teamVoteModified[num-CS_TEAMVOTE_NO] = qtrue; } else if ( num >= CS_TEAMVOTE_STRING && num <= CS_TEAMVOTE_STRING + 1) { Q_strncpyz( cgs.teamVoteString[num-CS_TEAMVOTE_STRING], str, sizeof( cgs.teamVoteString ) ); #ifdef MISSIONPACK trap_S_StartLocalSound( cgs.media.voteNow, CHAN_ANNOUNCER ); #endif } else if ( num == CS_INTERMISSION ) { cg.intermissionStarted = atoi( str ); } else if ( num >= CS_MODELS && num < CS_MODELS+MAX_MODELS ) { cgs.gameModels[ num-CS_MODELS ] = trap_R_RegisterModel( str ); } else if ( num >= CS_SOUNDS && num < CS_SOUNDS+MAX_MODELS ) { if ( str[0] != '*' ) { // player specific sounds don't register here cgs.gameSounds[ num-CS_SOUNDS] = trap_S_RegisterSound( str, qfalse ); } } else if ( num >= CS_PLAYERS && num < CS_PLAYERS+MAX_CLIENTS ) { CG_NewClientInfo( num - CS_PLAYERS ); CG_BuildSpectatorString(); } else if ( num == CS_FLAGSTATUS ) { if( cgs.gametype == GT_CTF ) { // format is rb where its red/blue, 0 is at base, 1 is taken, 2 is dropped cgs.redflag = str[0] - '0'; cgs.blueflag = str[1] - '0'; } #ifdef MISSIONPACK else if( cgs.gametype == GT_1FCTF ) { cgs.flagStatus = str[0] - '0'; } #endif } else if ( num == CS_SHADERSTATE ) { CG_ShaderStateChanged(); } }
/* ================= CG_ServerCommand The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv() ================= */ static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_SAY_TEXT]; cmd = CG_Argv(0); if ( !cmd[0] ) { // server claimed the command return; } if ( !strcmp( cmd, "cp" ) ) { CG_CenterPrint( CG_Argv(1), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { CG_Printf( "%s", CG_Argv(1) ); #ifdef MISSIONPACK cmd = CG_Argv(1); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if ( !Q_stricmpn( cmd, "vote failed", 11 ) || !Q_stricmpn( cmd, "team vote failed", 16 )) { trap_S_StartLocalSound( cgs.media.voteFailed, CHAN_ANNOUNCER ); } else if ( !Q_stricmpn( cmd, "vote passed", 11 ) || !Q_stricmpn( cmd, "team vote passed", 16 ) ) { trap_S_StartLocalSound( cgs.media.votePassed, CHAN_ANNOUNCER ); } #endif return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_Printf( "%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_AddToTeamChat( text ); CG_Printf( "%s\n", text ); return; } if ( !strcmp( cmd, "vchat" ) ) { CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp (cmd, "remapShader") == 0 ) { if (trap_Argc() == 4) { trap_R_RemapShader(CG_Argv(1), CG_Argv(2), CG_Argv(3)); } } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } // CORKSCREW accuracy challenge if ( !strcmp( cmd, "drawchallengeinfo" ) ) { cg.encryptChallengeInfo = ( rand() % 9000 ) + 1000; cg.drawChallengeInfoScreenshotTime = 0; cg.drawChallengeInfo = qtrue; cg.drawChallengeInfoScreenshot = qtrue; cg.showScores = qtrue; return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
/* ================= CG_ServerCommand The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv() ================= */ static void CG_ServerCommand( void ) { const char *cmd; char text[MAX_SAY_TEXT]; cmd = CG_Argv(0); if ( !cmd[0] ) { // server claimed the command return; } if ( !strcmp( cmd, "cp" ) ) { CG_CenterPrint( CG_Argv(1), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); return; } if ( !strcmp( cmd, "cs" ) ) { CG_ConfigStringModified(); return; } if ( !strcmp( cmd, "print" ) ) { CG_Printf( "%s", CG_Argv(1) ); #ifdef MISSIONPACK cmd = CG_Argv(1); // yes, this is obviously a hack, but so is the way we hear about // votes passing or failing if ( !Q_stricmpn( cmd, "vote failed", 11 ) || !Q_stricmpn( cmd, "team vote failed", 16 )) { trap_S_StartLocalSound( cgs.media.voteFailed, CHAN_ANNOUNCER ); } else if ( !Q_stricmpn( cmd, "vote passed", 11 ) || !Q_stricmpn( cmd, "team vote passed", 16 ) ) { trap_S_StartLocalSound( cgs.media.votePassed, CHAN_ANNOUNCER ); } #endif return; } if ( !strcmp( cmd, "chat" ) ) { if ( !cg_teamChatsOnly.integer ) { if( cg_chatBeep.integer ) trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_Printf( "%s\n", text ); } return; } if ( !strcmp( cmd, "tchat" ) ) { if( cg_teamChatBeep.integer ) trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT ); CG_RemoveChatEscapeChar( text ); CG_AddToTeamChat( text ); CG_Printf( "%s\n", text ); return; } if ( !strcmp( cmd, "vchat" ) ) { CG_VoiceChat( SAY_ALL ); return; } if ( !strcmp( cmd, "vtchat" ) ) { CG_VoiceChat( SAY_TEAM ); return; } if ( !strcmp( cmd, "vtell" ) ) { CG_VoiceChat( SAY_TELL ); return; } if ( !strcmp( cmd, "scores" ) ) { CG_ParseScores(); return; } if ( !strcmp( cmd, "accs" ) ) { CG_ParseAccuracy(); return; } if ( !strcmp( cmd, "ddtaken" ) ) { CG_ParseDDtimetaken(); return; } if ( !strcmp( cmd, "dompointnames" ) ) { CG_ParseDomPointNames(); return; } if ( !strcmp( cmd, "domStatus" ) ) { CG_ParseDomStatus(); return; } if ( !strcmp( cmd, "elimination" ) ) { CG_ParseElimination(); return; } if ( !strcmp( cmd, "mappage" ) ) { CG_ParseMappage(); return; } if ( !strcmp( cmd, "attackingteam" ) ) { CG_ParseAttackingTeam(); return; } if ( !strcmp( cmd, "tinfo" ) ) { CG_ParseTeamInfo(); return; } if ( !strcmp( cmd, "map_restart" ) ) { CG_MapRestart(); return; } if ( Q_stricmp (cmd, "remapShader") == 0 ) { if (trap_Argc() == 4) { char shader1[MAX_QPATH]; char shader2[MAX_QPATH]; char shader3[MAX_QPATH]; Q_strncpyz(shader1, CG_Argv(1), sizeof(shader1)); Q_strncpyz(shader2, CG_Argv(2), sizeof(shader2)); Q_strncpyz(shader3, CG_Argv(3), sizeof(shader3)); trap_R_RemapShader(shader1, shader2, shader3); } return; } // loaddeferred can be both a servercmd and a consolecmd if ( !strcmp( cmd, "loaddefered" ) ) { // FIXME: spelled wrong, but not changing for demo CG_LoadDeferredPlayers(); return; } // clientLevelShot is sent before taking a special screenshot for // the menu system during development if ( !strcmp( cmd, "clientLevelShot" ) ) { cg.levelShot = qtrue; return; } // challenge completed is determened by the server. A client should consider this message valid: if ( !strcmp( cmd, "ch" ) ) { CG_ParseChallenge(); return; } if ( !strcmp (cmd, "oh") ) { CG_ParseObeliskHealth(); return; } if ( !strcmp( cmd, "respawn" ) ) { CG_ParseRespawnTime(); return; } if ( !strcmp( cmd, "team" ) ) { CG_ParseTeam(); return; } if ( !strcmp( cmd, "customvotes" ) ) { char infoString[1024]; int i; //TODO: Create a ParseCustomvotes function memset(&infoString,0,sizeof(infoString)); for(i=1;i<=12;i++) { Q_strcat(infoString,sizeof(infoString),CG_Argv( i )); Q_strcat(infoString,sizeof(infoString)," "); } trap_Cvar_Set("cg_vote_custom_commands",infoString); return; } CG_Printf( "Unknown client game command: %s\n", cmd ); }
/* ================== CG_CheckLocalSounds ================== */ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) { if ( cg_hitsounds.integer && ps->clientNum == ops->clientNum && ps->persistant[PERS_SPAWN_COUNT] == ops->persistant[PERS_SPAWN_COUNT] ) { int* const h = ps->holdable; int* const oh = ops->holdable; /////////////////////////////////////////////////////////////////// if ((h[HOLDABLE_HIT] & 0x000f) > (oh[HOLDABLE_HIT] & 0x000f)) trap_S_StartLocalSound( cgs.media.hitsound_head, CHAN_LOCAL_SOUND ); if (cg_hitsounds.integer != 2) { if ((h[HOLDABLE_HIT] & 0x00f0) != (oh[HOLDABLE_HIT] & 0x00f0)) trap_S_StartLocalSound( cgs.media.hitsound_hand, CHAN_LOCAL_SOUND ); if ((h[HOLDABLE_HIT] & 0x0f00) != (oh[HOLDABLE_HIT] & 0x0f00)) trap_S_StartLocalSound( cgs.media.hitsound_torso, CHAN_LOCAL_SOUND ); if ((h[HOLDABLE_HIT] & 0xf000) != (oh[HOLDABLE_HIT] & 0xf000)) trap_S_StartLocalSound( cgs.media.hitsound_foot, CHAN_LOCAL_SOUND ); } /////////////////////////////////////////////////////////////////// if ((h[HOLDABLE_HITF] & 0x000f) != (oh[HOLDABLE_HITF] & 0x000f)) trap_S_StartLocalSound( cgs.media.hitsound_fhead, CHAN_LOCAL_SOUND ); if (cg_hitsounds.integer != 2) { if ((h[HOLDABLE_HITF] & 0x00f0) != (oh[HOLDABLE_HITF] & 0x00f0)) trap_S_StartLocalSound( cgs.media.hitsound_fhand, CHAN_LOCAL_SOUND ); if ((h[HOLDABLE_HITF] & 0x0f00) != (oh[HOLDABLE_HITF] & 0x0f00)) trap_S_StartLocalSound( cgs.media.hitsound_ftorso, CHAN_LOCAL_SOUND ); if ((h[HOLDABLE_HITF] & 0xf000) != (oh[HOLDABLE_HITF] & 0xf000)) trap_S_StartLocalSound( cgs.media.hitsound_ffoot, CHAN_LOCAL_SOUND ); } } // health changes of more than -1 should make pain sounds if ( ps->stats[STAT_HEALTH] < ops->stats[STAT_HEALTH] - 1 ) { if ( ps->stats[STAT_HEALTH] > 0 ) { CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH], qfalse ); cg.painTime = cg.time; } } // timelimit warnings if ( cgs.timelimit > 0 && cgs.gamestate == GS_PLAYING) { int msec; msec = cg.time - cgs.levelStartTime; if ( cgs.timelimit > 5 && !( cg.timelimitWarnings & 1 ) && (msec > (cgs.timelimit - 5) * 60 * 1000) && ( msec < (cgs.timelimit-5)*60*1000+1000 ) ) { cg.timelimitWarnings |= 1; if( ps->persistant[PERS_TEAM] == TEAM_AXIS ) { if( cgs.media.fiveMinuteSound_g == -1 ) { CG_SoundPlaySoundScript( cg.fiveMinuteSound_g, NULL, -1, qtrue ); } else if( cgs.media.fiveMinuteSound_g ) { trap_S_StartLocalSound( cgs.media.fiveMinuteSound_g, CHAN_ANNOUNCER ); } } else if( ps->persistant[PERS_TEAM] == TEAM_ALLIES ) { if( cgs.media.fiveMinuteSound_a == -1 ) { CG_SoundPlaySoundScript( cg.fiveMinuteSound_a, NULL, -1, qtrue ); } else if( cgs.media.fiveMinuteSound_a ) { trap_S_StartLocalSound( cgs.media.fiveMinuteSound_a, CHAN_ANNOUNCER ); } } } if ( cgs.timelimit > 2 && !( cg.timelimitWarnings & 2 ) && (msec > (cgs.timelimit - 2) * 60 * 1000) && ( msec < (cgs.timelimit-2)*60*1000+1000 ) ) { cg.timelimitWarnings |= 2; if( ps->persistant[PERS_TEAM] == TEAM_AXIS ) { if( cgs.media.twoMinuteSound_g == -1 ) { CG_SoundPlaySoundScript( cg.twoMinuteSound_g, NULL, -1, qtrue ); } else if( cgs.media.twoMinuteSound_g ) { trap_S_StartLocalSound( cgs.media.twoMinuteSound_g, CHAN_ANNOUNCER ); } } else if( ps->persistant[PERS_TEAM] == TEAM_ALLIES ) { if( cgs.media.twoMinuteSound_a == -1 ) { CG_SoundPlaySoundScript( cg.twoMinuteSound_a, NULL, -1, qtrue ); } else if( cgs.media.twoMinuteSound_a ) { trap_S_StartLocalSound( cgs.media.twoMinuteSound_a, CHAN_ANNOUNCER ); } } } if ( !( cg.timelimitWarnings & 4 ) && (msec > (cgs.timelimit) * 60 * 1000 - 30000) && (msec < (cgs.timelimit) * 60 * 1000 - 29000 ) ) { cg.timelimitWarnings |= 4; if( ps->persistant[PERS_TEAM] == TEAM_AXIS ) { if( cgs.media.thirtySecondSound_g == -1 ) { CG_SoundPlaySoundScript( cg.thirtySecondSound_g, NULL, -1, qtrue ); } else if( cgs.media.thirtySecondSound_g ) { trap_S_StartLocalSound( cgs.media.thirtySecondSound_g, CHAN_ANNOUNCER ); } } else if( ps->persistant[PERS_TEAM] == TEAM_ALLIES ) { if( cgs.media.thirtySecondSound_a == -1 ) { CG_SoundPlaySoundScript( cg.thirtySecondSound_a, NULL, -1, qtrue ); } else if( cgs.media.thirtySecondSound_a ) { trap_S_StartLocalSound( cgs.media.thirtySecondSound_a, CHAN_ANNOUNCER ); } } } } }
static void InformUnlockableStatusChanges( int *statusChanges, int count ) { char text[ MAX_STRING_CHARS ]; char *textptr = text; int unlockableNum; bool firstPass = true, unlocked = true; unlockable_t *unlockable; for ( unlockableNum = 0; unlockableNum < NUM_UNLOCKABLES; unlockableNum++ ) { unlockable = &unlockables[ unlockableNum ]; if ( !statusChanges[ unlockableNum ] || Disabled( unlockable ) ) { continue; } if ( firstPass ) { if ( statusChanges[ unlockableNum ] > 0 ) { Com_sprintf( text, sizeof( text ), S_COLOR_GREEN "ITEM%s UNLOCKED: " S_COLOR_WHITE, ( count > 1 ) ? "S" : "" ); } else { unlocked = false; Com_sprintf( text, sizeof( text ), S_COLOR_RED "ITEM%s LOCKED: " S_COLOR_WHITE, ( count > 1 ) ? "S" : "" ); } textptr = text + strlen( text ); firstPass = false; } else { Com_sprintf( textptr, sizeof( text ) - ( textptr - text ), ", " ); textptr += 2; } Com_sprintf( textptr, sizeof( text ) - ( textptr - text ), "%s", UnlockableHumanName( unlockable ) ); textptr += strlen( textptr ); } // TODO: Add sound for items being locked for each team switch ( cg.snap->ps.persistant[ PERS_TEAM ] ) { case TEAM_ALIENS: if ( unlocked ) { trap_S_StartLocalSound( cgs.media.weHaveEvolved, CHAN_ANNOUNCER ); } break; case TEAM_HUMANS: default: if ( unlocked ) { trap_S_StartLocalSound( cgs.media.reinforcement, CHAN_ANNOUNCER ); } break; } CG_CenterPrint( text, SCREEN_HEIGHT * 0.3, GIANTCHAR_WIDTH * 2 ); }
/* ================= UI_SPPostgameMenu_MenuDraw ================= */ static void UI_SPPostgameMenu_MenuDraw( void ) { int timer; int serverId; int n; char info[MAX_INFO_STRING]; trap_GetConfigString( CS_SYSTEMINFO, info, sizeof(info) ); serverId = atoi( Info_ValueForKey( info, "sv_serverid" ) ); if( serverId != postgameMenuInfo.serverId ) { UI_PopMenu(); return; } // phase 1 if ( postgameMenuInfo.numClients > 2 ) { UI_DrawProportionalString( 510, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[2], UI_CENTER, color_white ); } UI_DrawProportionalString( 130, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[1], UI_CENTER, color_white ); UI_DrawProportionalString( 320, 480 - 64 - 2 * PROP_HEIGHT, postgameMenuInfo.placeNames[0], UI_CENTER, color_white ); if( postgameMenuInfo.phase == 1 ) { timer = uis.realtime - postgameMenuInfo.starttime; if( timer >= 1000 && postgameMenuInfo.winnerSound ) { trap_S_StartLocalSound( postgameMenuInfo.winnerSound, CHAN_ANNOUNCER ); postgameMenuInfo.winnerSound = 0; } if( timer < 5000 ) { return; } postgameMenuInfo.phase = 2; postgameMenuInfo.starttime = uis.realtime; } // phase 2 if( postgameMenuInfo.phase == 2 ) { timer = uis.realtime - postgameMenuInfo.starttime; if( timer >= ( postgameMenuInfo.numAwards * AWARD_PRESENTATION_TIME ) ) { if( timer < 5000 ) { return; } postgameMenuInfo.phase = 3; postgameMenuInfo.starttime = uis.realtime; } else { UI_SPPostgameMenu_DrawAwardsPresentation( timer ); } } // phase 3 if( postgameMenuInfo.phase == 3 ) { if( uis.demoversion ) { if( postgameMenuInfo.won == 1 && UI_ShowTierVideo( 8 )) { trap_Cvar_Set( "nextmap", "" ); trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; cinematic demoEnd.RoQ\n" ); return; } } else if( postgameMenuInfo.won > -1 && UI_ShowTierVideo( postgameMenuInfo.won + 1 )) { if( postgameMenuInfo.won == postgameMenuInfo.lastTier ) { trap_Cvar_Set( "nextmap", "" ); trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; cinematic end.RoQ\n" ); return; } trap_Cvar_SetValue( "ui_spSelection", postgameMenuInfo.won * ARENAS_PER_TIER ); trap_Cvar_Set( "nextmap", "levelselect" ); trap_Cmd_ExecuteText( EXEC_APPEND, va( "disconnect; cinematic tier%i.RoQ\n", postgameMenuInfo.won + 1 ) ); return; } postgameMenuInfo.item_again.generic.flags &= ~QMF_INACTIVE; postgameMenuInfo.item_next.generic.flags &= ~QMF_INACTIVE; postgameMenuInfo.item_menu.generic.flags &= ~QMF_INACTIVE; UI_SPPostgameMenu_DrawAwardsMedals( postgameMenuInfo.numAwards ); Menu_Draw( &postgameMenuInfo.menu ); } // draw the scoreboard if( !trap_Cvar_VariableValue( "ui_spScoreboard" ) ) { return; } timer = uis.realtime - postgameMenuInfo.scoreboardtime; if( postgameMenuInfo.numClients <= 3 ) { n = 0; } else { n = timer / 1500 % (postgameMenuInfo.numClients + 2); } UI_SPPostgameMenu_MenuDrawScoreLine( n, 0 ); UI_SPPostgameMenu_MenuDrawScoreLine( n + 1, 0 + SMALLCHAR_HEIGHT ); UI_SPPostgameMenu_MenuDrawScoreLine( n + 2, 0 + 2 * SMALLCHAR_HEIGHT ); }
/* ================= CG_Say ================= */ static void CG_Say( const char *name, int clientNum, saymode_t mode, const char *text ) { char prefix[ 21 ] = ""; char *ignore = ""; char *location = ""; char color; char *maybeColon; if ( clientNum >= 0 && clientNum < MAX_CLIENTS ) { clientInfo_t *ci = &cgs.clientinfo[ clientNum ]; char *tcolor = S_COLOR_WHITE; name = ci->name; if ( ci->team == TEAM_ALIENS ) { tcolor = S_COLOR_RED; } else if ( ci->team == TEAM_HUMANS ) { tcolor = S_COLOR_CYAN; } if ( cg_chatTeamPrefix.integer ) { Com_sprintf( prefix, sizeof( prefix ), "[%s%c" S_COLOR_WHITE "] ", tcolor, toupper( * ( BG_TeamName( ci->team ) ) ) ); } if ( Com_ClientListContains( &cgs.ignoreList, clientNum ) ) { ignore = "[skipnotify]"; } if ( ( mode == SAY_TEAM || mode == SAY_AREA ) && cg.snap->ps.pm_type != PM_INTERMISSION ) { int locationNum; if ( clientNum == cg.snap->ps.clientNum ) { centity_t *locent; locent = CG_GetPlayerLocation(); if ( locent ) { locationNum = locent->currentState.generic1; } else { locationNum = 0; } } else { locationNum = ci->location; } if ( locationNum > 0 && locationNum < MAX_LOCATIONS ) { const char *s = CG_ConfigString( CS_LOCATIONS + locationNum ); if ( *s ) { location = va( " (%s" S_COLOR_WHITE ")", s ); } } } } else if ( name ) { Q_strcat( prefix, sizeof( prefix ), "[ADMIN]" ); } else { name = "console"; } // IRC-like /me parsing if ( mode != SAY_RAW && Q_stricmpn( text, "/me ", 4 ) == 0 ) { text += 4; Q_strcat( prefix, sizeof( prefix ), "* " ); maybeColon = ""; } else { maybeColon = ":"; } color = '0' + UI_GetChatColour( mode, cgs.clientinfo[ clientNum ].team ); switch ( mode ) { case SAY_ALL: // might already be ignored but in that case no harm is done if ( cg_teamChatsOnly.integer ) { ignore = "[skipnotify]"; } case SAY_ALL_ADMIN: CG_Printf( "%s%s%s^7%s ^%c%s\n", ignore, prefix, name, maybeColon, color, text ); break; case SAY_TEAM: CG_Printf( "%s%s(%s^7)%s%s ^%c%s\n", ignore, prefix, name, location, maybeColon, color, text ); break; case SAY_ADMINS: case SAY_ADMINS_PUBLIC: CG_Printf( "%s%s%s%s^7%s ^%c%s\n", ignore, prefix, ( mode == SAY_ADMINS ) ? "[ADMIN]" : "[PLAYER]", name, maybeColon, color, text ); break; case SAY_AREA: case SAY_AREA_TEAM: CG_Printf( "%s%s<%s^7>%s%s ^%c%s\n", ignore, prefix, name, location, maybeColon, color, text ); break; case SAY_PRIVMSG: case SAY_TPRIVMSG: CG_Printf( "%s%s[%s^7 -> %s^7]%s ^%c%s\n", ignore, prefix, name, cgs.clientinfo[ cg.clientNum ].name, maybeColon, color, text ); if ( !ignore[ 0 ] ) { CG_CenterPrint( va( "^%cPrivate message from: " S_COLOR_WHITE "%s", color, name ), 200, GIANTCHAR_WIDTH * 4 ); if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) { clientNum = cg.clientNum; } CG_Printf(_( ">> to reply, say: /m %d [your message] <<\n"), clientNum ); } break; case SAY_RAW: CG_Printf( "%s\n", text ); break; case SAY_DEFAULT: default: break; } switch ( mode ) { case SAY_TEAM: case SAY_AREA: case SAY_TPRIVMSG: if ( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_ALIENS ) { trap_S_StartLocalSound( cgs.media.alienTalkSound, CHAN_LOCAL_SOUND ); break; } else if ( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_HUMANS ) { trap_S_StartLocalSound( cgs.media.humanTalkSound, CHAN_LOCAL_SOUND ); break; } default: trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); } }
/* ============== CG_CheckAmmo If the ammo has gone low enough to generate the warning, play a sound ============== */ void CG_CheckAmmo( void ) { int i; int total; int weapons[MAX_WEAPONS / ( sizeof( int ) * 8 )]; // see about how many seconds of ammo we have remaining memcpy( weapons, cg.snap->ps.weapons, sizeof( weapons ) ); if ( !weapons[0] && !weapons[1] ) { // (SA) we start out with no weapons, so don't make a click on startup return; } total = 0; // first weap now WP_LUGER for ( i = WP_FIRST ; i < WP_NUM_WEAPONS ; i++ ) { if ( !( weapons[0] & ( 1 << i ) ) ) { continue; } switch ( i ) { case WP_PANZERFAUST: case WP_GRENADE_LAUNCHER: case WP_GRENADE_PINEAPPLE: case WP_LUGER: case WP_COLT: case WP_AKIMBO: case WP_SILENCER: case WP_FG42: case WP_FG42SCOPE: case WP_MP40: case WP_THOMPSON: case WP_STEN: case WP_VENOM: case WP_TESLA: case WP_MAUSER: case WP_GARAND: default: total += cg.snap->ps.ammo[BG_FindAmmoForWeapon( i )] * 1000; // break; // default: // total += cg.snap->ps.ammo[BG_FindAmmoForWeapon(i)] * 200; // break; } if ( total >= 5000 ) { cg.lowAmmoWarning = 0; return; } } if ( !cg.lowAmmoWarning ) { // play a sound on this transition trap_S_StartLocalSound( cgs.media.noAmmoSound, CHAN_LOCAL_SOUND ); } if ( total == 0 ) { cg.lowAmmoWarning = 2; } else { cg.lowAmmoWarning = 1; } }
/* =============== UI_DrawPlayer =============== */ void UI_DrawPlayer( float x, float y, float w, float h, uiPlayerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs = {0}; refEntity_t torso = {0}; refEntity_t head = {0}; #ifdef TA_WEAPSYS refEntity_t gun[MAX_HANDS] = {0}; #else refEntity_t gun = {0}; #endif refEntity_t barrel = {0}; refEntity_t flash = {0}; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; float xscale; float yscale; #ifdef TA_WEAPSYS int i; vec3_t angles; #ifdef TURTLEARENA // PLAYERS char *newTagNames[3] = { "tag_hand_primary", "tag_hand_secondary", NULL }; #endif char *originalTagNames[3] = { "tag_weapon", "tag_flag", NULL }; #endif if ( !pi->legsModel || !pi->torsoModel || !pi->headModel #ifdef TA_PLAYERSYS || !pi->playercfg.animations[0].numFrames ) { #else || !pi->animations[0].numFrames ) { #endif return; } // this allows the ui to cache the player model on the main menu if (w == 0 || h == 0) { return; } dp_realtime = time; if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = WP_NUM_WEAPONS; pi->weaponTimer = 0; #ifndef TA_WEAPSYS_EX if( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL ); } #endif } CG_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; if ( ui_stretch.integer ) { xscale = cgs.screenXScaleStretch; yscale = cgs.screenYScaleStretch; } else { xscale = cgs.screenXScale; yscale = cgs.screenYScale; } refdef.fov_x = (int)((float)refdef.width / xscale / 640.0f * 90.0f); xx = refdef.width / xscale / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height / yscale, xx ); refdef.fov_y *= ( 360 / (float)M_PI ); // calculate distance so the player nearly fills the box len = 0.7 * ( maxs[2] - mins[2] ); origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_ClearScene(); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the legs // legs.hModel = pi->legsModel; legs.customSkin = CG_AddSkinToFrame( &pi->modelSkin ); VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); legs.renderfx = renderfx; VectorCopy (legs.origin, legs.oldorigin); Byte4Copy( pi->c1RGBA, legs.shaderRGBA ); CG_AddRefEntityWithMinLight( &legs ); if (!legs.hModel) { return; } // // add the torso // torso.hModel = pi->torsoModel; if (!torso.hModel) { return; } torso.customSkin = legs.customSkin; VectorCopy( origin, torso.lightingOrigin ); UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso"); torso.renderfx = renderfx; Byte4Copy( pi->c1RGBA, torso.shaderRGBA ); CG_AddRefEntityWithMinLight( &torso ); // // add the head // head.hModel = pi->headModel; if (!head.hModel) { return; } head.customSkin = legs.customSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head"); head.renderfx = renderfx; Byte4Copy( pi->c1RGBA, head.shaderRGBA ); CG_AddRefEntityWithMinLight( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { #ifdef TA_WEAPSYS // get hands from cent for (i = 0; i < MAX_HANDS; i++) { memset( &gun[i], 0, sizeof(gun[i]) ); gun[i].hModel = pi->weaponModel[i]; VectorCopy( origin, gun[i].lightingOrigin ); gun[i].renderfx = renderfx; Byte4Copy( pi->c1RGBA, gun[i].shaderRGBA ); if (!originalTagNames[i] #ifdef TURTLEARENA // PLAYERS || !newTagNames[i] #endif ) { break; } if (!gun[i].hModel) { continue; } if ( #ifdef TURTLEARENA // PLAYERS !UI_PositionEntityOnTag( &gun[i], &torso, pi->torsoModel, newTagNames[i]) && #endif !UI_PositionEntityOnTag( &gun[i], &torso, pi->torsoModel, originalTagNames[i])) { // Failed to find tag continue; } CG_AddRefEntityWithMinLight( &gun[i] ); } #else memset( &gun, 0, sizeof(gun) ); gun.hModel = pi->weaponModel; Byte4Copy( pi->c1RGBA, gun.shaderRGBA ); VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon"); gun.renderfx = renderfx; CG_AddRefEntityWithMinLight( &gun ); #endif } // // add the spinning barrel // #ifdef TA_WEAPSYS for (i = 0; i < MAX_HANDS; i++) #else if ( pi->barrelModel ) #endif { #ifdef TA_WEAPSYS if (!pi->barrelModel[i]) continue; #else vec3_t angles; #endif memset( &barrel, 0, sizeof(barrel) ); VectorCopy( origin, barrel.lightingOrigin ); barrel.renderfx = renderfx; #ifdef TA_WEAPSYS barrel.hModel = pi->barrelModel[i]; VectorClear(angles); if (bg_weapongroupinfo[pi->realWeapon].weapon[0]->barrelSpin != BS_NONE) { angles[bg_weapongroupinfo[pi->realWeapon].weapon[0]->barrelSpin] = UI_MachinegunSpinAngle( pi ); } #else barrel.hModel = pi->barrelModel; angles[YAW] = 0; angles[PITCH] = 0; angles[ROLL] = UI_MachinegunSpinAngle( pi ); #endif AnglesToAxis( angles, barrel.axis ); #ifdef TA_WEAPSYS UI_PositionRotatedEntityOnTag( &barrel, &gun[i], pi->weaponModel[i], "tag_barrel"); #else UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, "tag_barrel"); #endif CG_AddRefEntityWithMinLight( &barrel ); } // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { #ifdef TA_WEAPSYS vec3_t *flashDlightColor; for (i = 0; i < MAX_HANDS; i++) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel[i]; flashDlightColor = &pi->flashDlightColor[i]; Byte4Copy( pi->c1RGBA, flash.shaderRGBA ); if (!flash.hModel) continue; VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun[i], pi->weaponModel[i], "tag_flash"); flash.renderfx = renderfx; trap_R_AddRefEntityToScene( &flash ); // make a dlight for the flash if ( *flashDlightColor[0] || *flashDlightColor[1] || *flashDlightColor[2] ) { trap_R_AddLightToScene( flash.origin, 200 + (rand()&31), 1.0f, *flashDlightColor[0], *flashDlightColor[1], *flashDlightColor[2] ); } } #else if ( pi->flashModel ) { memset( &flash, 0, sizeof(flash) ); flash.hModel = pi->flashModel; Byte4Copy( pi->c1RGBA, flash.shaderRGBA ); VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash"); flash.renderfx = renderfx; CG_AddRefEntityWithMinLight( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddJuniorLightToScene( flash.origin, 200 + (rand()&31), 1.0f, pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2] ); } #endif } // // add the chat icon // if ( pi->chat ) { #ifdef TA_DATA // shaders UI_PlayerFloatSprite( pi, torso.origin, trap_R_RegisterShaderNoMip( "sprites/talkBalloon" ) ); #else UI_PlayerFloatSprite( pi, torso.origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); #endif } // // add an accent light // origin[0] -= 100; // + = behind, - = in front origin[1] += 100; // + = left, - = right origin[2] += 100; // + = above, - = below trap_R_AddJuniorLightToScene( origin, 500, 1.0, 1.0, 1.0, 1.0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddJuniorLightToScene( origin, 500, 1.0, 1.0, 0.0, 0.0 ); trap_R_RenderScene( &refdef ); } /* ========================== UI_FileExists ========================== */ static qboolean UI_FileExists(const char *filename) { int len; len = trap_FS_FOpenFile( filename, NULL, FS_READ ); if (len>0) { return qtrue; } return qfalse; }
static void CG_ConfigStringModified(void) { const char *str; int num; num = atoi(BG_Argv(1)); // get the gamestate from the client system, which will have the // new configstring already integrated trap_GetGameState(&cgs.gameState); // look up the individual string that was modified str = CG_ConfigString(num); // do something with it if necessary if (num == CS_SERVERINFO) { CG_ParseServerinfo(); } else if (num == CS_WARMUP) { CG_SetWarmup(atoi(str)); } else if (num == CS_SCORES1) { cgs.scores1 = atoi(str); } else if (num == CS_SCORES2) { cgs.scores2 = atoi(str); } else if (num == CS_LEVEL_START_TIME) { cgs.levelStartTime = atoi(str); } else if (num == CS_VOTE_TIME) { if (!strcmp(str, "failed")) { cgs.voteTime = 0; CG_Printf("Vote failed.\n"); CG_AddBufferedSound(cgs.media.voteFailed); } else if (!strcmp(str, "passed")) { cgs.voteTime = 0; CG_Printf("Vote passed.\n"); CG_AddBufferedSound(cgs.media.votePassed); } else if (*str) { cgs.voteTime = atoi(str); CG_Printf("Vote cast.\n"); CG_AddBufferedSound(cgs.media.voteNow); } } else if (num == CS_VOTE_YES) { cgs.voteYes = atoi(str); trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); } else if (num == CS_VOTE_NO) { cgs.voteNo = atoi(str); trap_S_StartLocalSound(cgs.media.talkSound, CHAN_LOCAL_SOUND); } else if (num == CS_VOTE_STRING) { Q_strncpyz(cgs.voteString, str, sizeof(cgs.voteString)); } else if (num == CS_INTERMISSION) { cg.intermissionStarted = atoi(str); } else if (num >= CS_MODELS && num < CS_MODELS+MAX_MODELS) { cgs.gameModels[num-CS_MODELS] = trap_R_RegisterModel(str); } else if (num >= CS_SOUNDS && num < CS_SOUNDS+MAX_SOUNDS) { if (str[0] != '*') { // player specific sounds don't register here cgs.gameSounds[num-CS_SOUNDS] = trap_S_RegisterSound(str, qfalse); } } else if (num >= CS_PLAYERS && num < CS_PLAYERS+MAX_CLIENTS) { CG_NewClientInfo(num - CS_PLAYERS); } else if (num == CS_FLAGSTATUS) { // format is rb where its red/blue, 0 is at base, 1 is taken, 2 is dropped if (cgs.gametype == GT_CTF) { team_t team; team = cgs.clientinfo[cg.clientNum].team; if ((cgs.redflag == 1 && str[0] - '0' == 2 && team == TEAM_RED) || (cgs.blueflag == 1 && str[1] - '0' == 2 && team == TEAM_BLUE)) { CG_CenterPrint("^2The enemy dropped your flag"); } else if ((cgs.redflag == 1 && str[0] - '0' == 2 && team == TEAM_BLUE) || (cgs.blueflag == 1 && str[1] - '0' == 2 && team == TEAM_RED)) { CG_CenterPrint("^1You team dropped the flag"); } cgs.redflag = str[0] - '0'; cgs.blueflag = str[1] - '0'; } } else if (num == CS_SHADERSTATE) { CG_ShaderStateChanged(); } else if (num == CS_ROUND_START) { cg.countdownCount = -1; cgs.roundStartTime = atoi(str); } else if (num == CS_LIVING_COUNT) { int newRed, newBlue; newRed = atoi(COM_Parse((char **) &str)); newBlue = atoi(COM_Parse((char **) &str)); if (!cgs.warmup && cg.time >= cgs.roundStartTime) { team_t team; team = cg.snap->ps.persistant[PERS_TEAM]; if ((newRed == 1 && cgs.redLivingCount != 1 && team == TEAM_RED) || (newBlue == 1 && cgs.blueLivingCount != 1 && team == TEAM_BLUE)) { CG_CenterPrint("You are the last in your team"); } } cgs.redLivingCount = newRed; cgs.blueLivingCount = newBlue; } else if (num == CS_OVERTIME) { cgs.overtimeStart = atoi(str); trap_S_StartLocalSound(cgs.media.protectSound, CHAN_ANNOUNCER); CG_CenterPrint(va("^3OVERTIME^7 - %d seconds added", cgs.overtimeLimit)); } else if (num >= CS_RESPAWN_TIMERS && num < CS_RESPAWN_TIMERS + MAX_RESPAWN_TIMERS) { CG_ParseRespawnTimer(num - CS_RESPAWN_TIMERS, str); } else if (num == CS_PAUSE_START) { cgs.pauseStart = atoi(str); if (cgs.pauseStart > 0) { trap_S_StartLocalSound(cgs.media.pauseSound, CHAN_LOCAL_SOUND); } } else if (num == CS_PAUSE_END) { cg.countdownCount = -1; cgs.pauseEnd = atoi(str); } else if (num == CS_PAUSE_TIME) { cgs.pauseTime = atoi(str); } }
/* ================== CG_CheckLocalSounds ================== */ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) { // health changes of more than -1 should make pain sounds if ( ps->stats[STAT_HEALTH] < ops->stats[STAT_HEALTH] - 1 ) { if ( ps->stats[STAT_HEALTH] > 0 ) { CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH], qfalse ); cg.painTime = cg.time; } } // timelimit warnings if ( cgs.timelimit > 0 && cgs.gamestate == GS_PLAYING) { int msec; msec = cg.time - cgs.levelStartTime; if ( cgs.timelimit > 5 && !( cg.timelimitWarnings & 1 ) && (msec > (cgs.timelimit - 5) * 60 * 1000) && ( msec < (cgs.timelimit-5)*60*1000+1000 ) ) { cg.timelimitWarnings |= 1; if( ps->persistant[PERS_TEAM] == TEAM_AXIS ) { if( cgs.media.fiveMinuteSound_g == -1 ) { CG_SoundPlaySoundScript( cg.fiveMinuteSound_g, NULL, -1, qtrue ); } else if( cgs.media.fiveMinuteSound_g ) { trap_S_StartLocalSound( cgs.media.fiveMinuteSound_g, CHAN_ANNOUNCER ); } } else if( ps->persistant[PERS_TEAM] == TEAM_ALLIES ) { if( cgs.media.fiveMinuteSound_a == -1 ) { CG_SoundPlaySoundScript( cg.fiveMinuteSound_a, NULL, -1, qtrue ); } else if( cgs.media.fiveMinuteSound_a ) { trap_S_StartLocalSound( cgs.media.fiveMinuteSound_a, CHAN_ANNOUNCER ); } } } if ( cgs.timelimit > 2 && !( cg.timelimitWarnings & 2 ) && (msec > (cgs.timelimit - 2) * 60 * 1000) && ( msec < (cgs.timelimit-2)*60*1000+1000 ) ) { cg.timelimitWarnings |= 2; if( ps->persistant[PERS_TEAM] == TEAM_AXIS ) { if( cgs.media.twoMinuteSound_g == -1 ) { CG_SoundPlaySoundScript( cg.twoMinuteSound_g, NULL, -1, qtrue ); } else if( cgs.media.twoMinuteSound_g ) { trap_S_StartLocalSound( cgs.media.twoMinuteSound_g, CHAN_ANNOUNCER ); } } else if( ps->persistant[PERS_TEAM] == TEAM_ALLIES ) { if( cgs.media.twoMinuteSound_a == -1 ) { CG_SoundPlaySoundScript( cg.twoMinuteSound_a, NULL, -1, qtrue ); } else if( cgs.media.twoMinuteSound_a ) { trap_S_StartLocalSound( cgs.media.twoMinuteSound_a, CHAN_ANNOUNCER ); } } } if ( !( cg.timelimitWarnings & 4 ) && (msec > (cgs.timelimit) * 60 * 1000 - 30000) && (msec < (cgs.timelimit) * 60 * 1000 - 29000 ) ) { cg.timelimitWarnings |= 4; if( ps->persistant[PERS_TEAM] == TEAM_AXIS ) { if( cgs.media.thirtySecondSound_g == -1 ) { CG_SoundPlaySoundScript( cg.thirtySecondSound_g, NULL, -1, qtrue ); } else if( cgs.media.thirtySecondSound_g ) { trap_S_StartLocalSound( cgs.media.thirtySecondSound_g, CHAN_ANNOUNCER ); } } else if( ps->persistant[PERS_TEAM] == TEAM_ALLIES ) { if( cgs.media.thirtySecondSound_a == -1 ) { CG_SoundPlaySoundScript( cg.thirtySecondSound_a, NULL, -1, qtrue ); } else if( cgs.media.thirtySecondSound_a ) { trap_S_StartLocalSound( cgs.media.thirtySecondSound_a, CHAN_ANNOUNCER ); } } } } }
/* ==================== CG_AddKamikaze ==================== */ void CG_AddKamikaze( localEntity_t *le ) { refEntity_t *re; refEntity_t shockwave; float c; vec3_t test, axis[3]; int t; re = &le->refEntity; t = cg.time - le->startTime; VectorClear( test ); AnglesToAxis( test, axis ); if (t > KAMI_SHOCKWAVE_STARTTIME && t < KAMI_SHOCKWAVE_ENDTIME) { if (!(le->leFlags & LEF_SOUND1)) { // trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeExplodeSound ); trap_S_StartLocalSound(cgs.media.kamikazeExplodeSound, CHAN_AUTO); le->leFlags |= LEF_SOUND1; } // 1st kamikaze shockwave memset(&shockwave, 0, sizeof(shockwave)); shockwave.hModel = cgs.media.kamikazeShockWave; shockwave.reType = RT_MODEL; shockwave.shaderTime = re->shaderTime; VectorCopy(re->origin, shockwave.origin); c = (float)(t - KAMI_SHOCKWAVE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVE_STARTTIME); VectorScale( axis[0], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] ); VectorScale( axis[1], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] ); VectorScale( axis[2], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] ); shockwave.nonNormalizedAxes = qtrue; if (t > KAMI_SHOCKWAVEFADE_STARTTIME) { c = (float)(t - KAMI_SHOCKWAVEFADE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVEFADE_STARTTIME); } else { c = 0; } c *= 0xff; shockwave.shaderRGBA[0] = 0xff - c; shockwave.shaderRGBA[1] = 0xff - c; shockwave.shaderRGBA[2] = 0xff - c; shockwave.shaderRGBA[3] = 0xff - c; CG_AddRefEntityWithMinLight( &shockwave ); } if (t > KAMI_EXPLODE_STARTTIME && t < KAMI_IMPLODE_ENDTIME) { // explosion and implosion c = ( le->endTime - cg.time ) * le->lifeRate; c *= 0xff; re->shaderRGBA[0] = le->color[0] * c; re->shaderRGBA[1] = le->color[1] * c; re->shaderRGBA[2] = le->color[2] * c; re->shaderRGBA[3] = le->color[3] * c; if( t < KAMI_IMPLODE_STARTTIME ) { c = (float)(t - KAMI_EXPLODE_STARTTIME) / (float)(KAMI_IMPLODE_STARTTIME - KAMI_EXPLODE_STARTTIME); } else { if (!(le->leFlags & LEF_SOUND2)) { // trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeImplodeSound ); trap_S_StartLocalSound(cgs.media.kamikazeImplodeSound, CHAN_AUTO); le->leFlags |= LEF_SOUND2; } c = (float)(KAMI_IMPLODE_ENDTIME - t) / (float) (KAMI_IMPLODE_ENDTIME - KAMI_IMPLODE_STARTTIME); } VectorScale( axis[0], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[0] ); VectorScale( axis[1], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[1] ); VectorScale( axis[2], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[2] ); re->nonNormalizedAxes = qtrue; CG_AddRefEntityWithMinLight( re ); // add the dlight trap_R_AddLightToScene( re->origin, c * 1000.0, 1.0, 1.0, 1.0, c ); } if (t > KAMI_SHOCKWAVE2_STARTTIME && t < KAMI_SHOCKWAVE2_ENDTIME) { // 2nd kamikaze shockwave if (le->angles.trBase[0] == 0 && le->angles.trBase[1] == 0 && le->angles.trBase[2] == 0) { le->angles.trBase[0] = random() * 360; le->angles.trBase[1] = random() * 360; le->angles.trBase[2] = random() * 360; } memset(&shockwave, 0, sizeof(shockwave)); shockwave.hModel = cgs.media.kamikazeShockWave; shockwave.reType = RT_MODEL; shockwave.shaderTime = re->shaderTime; VectorCopy(re->origin, shockwave.origin); test[0] = le->angles.trBase[0]; test[1] = le->angles.trBase[1]; test[2] = le->angles.trBase[2]; AnglesToAxis( test, axis ); c = (float)(t - KAMI_SHOCKWAVE2_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2_STARTTIME); VectorScale( axis[0], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] ); VectorScale( axis[1], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] ); VectorScale( axis[2], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] ); shockwave.nonNormalizedAxes = qtrue; if (t > KAMI_SHOCKWAVE2FADE_STARTTIME) { c = (float)(t - KAMI_SHOCKWAVE2FADE_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2FADE_STARTTIME); } else { c = 0; } c *= 0xff; shockwave.shaderRGBA[0] = 0xff - c; shockwave.shaderRGBA[1] = 0xff - c; shockwave.shaderRGBA[2] = 0xff - c; shockwave.shaderRGBA[3] = 0xff - c; CG_AddRefEntityWithMinLight( &shockwave ); } }
void UI_StartSound( qhandle_t sound ) { if ( soundTime > uis.realtime ) return; trap_S_StartLocalSound( sound, CHAN_LOCAL_SOUND ); }
void CG_SiegeObjectiveCompleted(centity_t *ent, int won, int objectivenum) { int myTeam; char teamstr[64]; char objstr[256]; char foundobjective[MAX_SIEGE_INFO_SIZE]; char appstring[1024]; char soundstr[1024]; int success = 0; playerState_t *ps = NULL; if (!siege_valid) { CG_Error("Siege data does not exist on client!\n"); return; } if (cg.snap) { //this should always be true, if it isn't though use the predicted ps as a fallback ps = &cg.snap->ps; } else { ps = &cg.predictedPlayerState; } if (!ps) { assert(0); return; } myTeam = ps->persistant[PERS_TEAM]; if (myTeam == TEAM_SPECTATOR) { return; } if (won == SIEGETEAM_TEAM1) { Com_sprintf(teamstr, sizeof(teamstr), team1); } else { Com_sprintf(teamstr, sizeof(teamstr), team2); } if (BG_SiegeGetValueGroup(siege_info, teamstr, cgParseObjectives)) { Com_sprintf(objstr, sizeof(objstr), "Objective%i", objectivenum); if (BG_SiegeGetValueGroup(cgParseObjectives, objstr, foundobjective)) { if (myTeam == SIEGETEAM_TEAM1) { success = BG_SiegeGetPairedValue(foundobjective, "message_team1", appstring); } else { success = BG_SiegeGetPairedValue(foundobjective, "message_team2", appstring); } if (success) { CG_DrawSiegeMessageNonMenu(appstring); } appstring[0] = 0; soundstr[0] = 0; if (myTeam == SIEGETEAM_TEAM1) { Com_sprintf(teamstr, sizeof(teamstr), "sound_team1"); } else { Com_sprintf(teamstr, sizeof(teamstr), "sound_team2"); } if (BG_SiegeGetPairedValue(foundobjective, teamstr, appstring)) { Com_sprintf(soundstr, sizeof(soundstr), appstring); } /* else { if (myTeam != won) { Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_LOSE_OBJECTIVE); } else { Com_sprintf(soundstr, sizeof(soundstr), DEFAULT_WIN_OBJECTIVE); } } */ if (soundstr[0]) { trap_S_StartLocalSound(trap_S_RegisterSound(soundstr), CHAN_ANNOUNCER); } } } }
/* ================== CG_CheckLocalSounds ================== */ void CG_CheckLocalSounds(playerState_t *ps, playerState_t *ops) { // health changes of more than -1 should make pain sounds if (ps->stats[STAT_HEALTH] < ops->stats[STAT_HEALTH] - 1) { if (ps->stats[STAT_HEALTH] > 0) { CG_PainEvent(&cg.predictedPlayerEntity, ps->stats[STAT_HEALTH], qfalse); cg.painTime = cg.time; } } // hitsounds // add server control cvars?! - no, admins just have to force cg_hitSounds if (ops->persistant[PERS_HITS] != ps->persistant[PERS_HITS] && (cg_hitSounds.integer & HITSOUNDS_ON)) { if (ps->persistant[PERS_HITS] < ops->persistant[PERS_HITS]) { if (!(cg_hitSounds.integer & HITSOUNDS_NOTEAMSHOT)) { trap_S_StartSound(NULL, ps->clientNum, CHAN_AUTO, cgs.media.teamShot); } } else if (ps->persistant[PERS_HEADSHOTS] > ops->persistant[PERS_HEADSHOTS]) { if (!(cg_hitSounds.integer & HITSOUNDS_NOHEADSHOT)) { trap_S_StartSound(NULL, ps->clientNum, CHAN_AUTO, cgs.media.headShot); } else if (!(cg_hitSounds.integer & HITSOUNDS_NOBODYSHOT)) { trap_S_StartSound(NULL, ps->clientNum, CHAN_AUTO, cgs.media.bodyShot); } } else { if (!(cg_hitSounds.integer & HITSOUNDS_NOBODYSHOT)) { trap_S_StartSound(NULL, ps->clientNum, CHAN_AUTO, cgs.media.bodyShot); } } } // timelimit warnings if (cgs.timelimit > 0 && cgs.gamestate == GS_PLAYING) { int msec = cg.time - cgs.levelStartTime; if (cgs.timelimit > 5 && !(cg.timelimitWarnings & 1) && (msec > (cgs.timelimit - 5) * 60 * 1000) && (msec < (cgs.timelimit - 5) * 60 * 1000 + 1000)) { cg.timelimitWarnings |= 1; if (ps->persistant[PERS_TEAM] == TEAM_AXIS) { if (cgs.media.fiveMinuteSound_g == -1) { CG_SoundPlaySoundScript(cg.fiveMinuteSound_g, NULL, -1, qtrue); } else if (cgs.media.fiveMinuteSound_g) { trap_S_StartLocalSound(cgs.media.fiveMinuteSound_g, CHAN_ANNOUNCER); } } else if (ps->persistant[PERS_TEAM] == TEAM_ALLIES) { if (cgs.media.fiveMinuteSound_a == -1) { CG_SoundPlaySoundScript(cg.fiveMinuteSound_a, NULL, -1, qtrue); } else if (cgs.media.fiveMinuteSound_a) { trap_S_StartLocalSound(cgs.media.fiveMinuteSound_a, CHAN_ANNOUNCER); } } } if (cgs.timelimit > 2 && !(cg.timelimitWarnings & 2) && (msec > (cgs.timelimit - 2) * 60 * 1000) && (msec < (cgs.timelimit - 2) * 60 * 1000 + 1000)) { cg.timelimitWarnings |= 2; if (ps->persistant[PERS_TEAM] == TEAM_AXIS) { if (cgs.media.twoMinuteSound_g == -1) { CG_SoundPlaySoundScript(cg.twoMinuteSound_g, NULL, -1, qtrue); } else if (cgs.media.twoMinuteSound_g) { trap_S_StartLocalSound(cgs.media.twoMinuteSound_g, CHAN_ANNOUNCER); } } else if (ps->persistant[PERS_TEAM] == TEAM_ALLIES) { if (cgs.media.twoMinuteSound_a == -1) { CG_SoundPlaySoundScript(cg.twoMinuteSound_a, NULL, -1, qtrue); } else if (cgs.media.twoMinuteSound_a) { trap_S_StartLocalSound(cgs.media.twoMinuteSound_a, CHAN_ANNOUNCER); } } } if (!(cg.timelimitWarnings & 4) && (msec > (cgs.timelimit) * 60 * 1000 - 30000) && (msec < (cgs.timelimit) * 60 * 1000 - 29000)) { cg.timelimitWarnings |= 4; if (ps->persistant[PERS_TEAM] == TEAM_AXIS) { if (cgs.media.thirtySecondSound_g == -1) { CG_SoundPlaySoundScript(cg.thirtySecondSound_g, NULL, -1, qtrue); } else if (cgs.media.thirtySecondSound_g) { trap_S_StartLocalSound(cgs.media.thirtySecondSound_g, CHAN_ANNOUNCER); } } else if (ps->persistant[PERS_TEAM] == TEAM_ALLIES) { if (cgs.media.thirtySecondSound_a == -1) { CG_SoundPlaySoundScript(cg.thirtySecondSound_a, NULL, -1, qtrue); } else if (cgs.media.thirtySecondSound_a) { trap_S_StartLocalSound(cgs.media.thirtySecondSound_a, CHAN_ANNOUNCER); } } } } }
/* ============== CG_CheckAmmo If the ammo has gone low enough to generate the warning, play a sound ============== */ void CG_CheckAmmo( void ) { #if 0 int i; int total; int previous; int weapons; // see about how many seconds of ammo we have remaining weapons = cg.snap->ps.stats[ STAT_WEAPONS ]; total = 0; for ( i = WP_BRYAR_PISTOL; i < WP_NUM_WEAPONS ; i++ ) { if ( ! ( weapons & ( 1 << i ) ) ) { continue; } switch ( i ) { case WP_BRYAR_PISTOL: case WP_CONCUSSION: case WP_BRYAR_OLD: case WP_BLASTER: case WP_DISRUPTOR: case WP_BOWCASTER: case WP_REPEATER: case WP_DEMP2: case WP_FLECHETTE: case WP_ROCKET_LAUNCHER: case WP_THERMAL: case WP_TRIP_MINE: case WP_DET_PACK: case WP_EMPLACED_GUN: total += cg.snap->ps.ammo[weaponData[i].ammoIndex] * 1000; break; default: total += cg.snap->ps.ammo[weaponData[i].ammoIndex] * 200; break; } if ( total >= 5000 ) { cg.lowAmmoWarning = 0; return; } } previous = cg.lowAmmoWarning; if ( total == 0 ) { cg.lowAmmoWarning = 2; } else { cg.lowAmmoWarning = 1; } if (cg.snap->ps.weapon == WP_SABER) { cg.lowAmmoWarning = 0; } // play a sound on transitions if ( cg.lowAmmoWarning != previous ) { trap_S_StartLocalSound( cgs.media.noAmmoSound, CHAN_LOCAL_SOUND ); } #endif //disabled silly ammo warning stuff for now }
/* ================= UI_SPSkillMenu_Key ================= */ static sfxHandle_t UI_SPSkillMenu_Key( int key ) { if( key == K_MOUSE2 || key == K_ESCAPE ) { trap_S_StartLocalSound( skillMenuInfo.silenceSound, CHAN_ANNOUNCER ); } return Menu_DefaultKey( &skillMenuInfo.menu, key ); }
void CG_EntityEvent( centity_t *cent, vec3_t position ) { entityState_t *es; int event; vec3_t dir; const char *s; int clientNum; clientInfo_t *ci; es = ¢->currentState; event = es->event & ~EV_EVENT_BITS; if ( cg_debugEvents.integer ) { CG_Printf( "ent:%3i event:%3i ", es->number, event ); } if ( !event ) { DEBUGNAME("ZEROEVENT"); return; } clientNum = es->clientNum; if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) { clientNum = 0; } ci = &cgs.clientinfo[ clientNum ]; switch ( event ) { // // movement generated events // case EV_FOOTSTEP: DEBUGNAME("EV_FOOTSTEP"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ ci->footsteps ][rand()&3] ); } break; case EV_FOOTSTEP_METAL: DEBUGNAME("EV_FOOTSTEP_METAL"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_METAL ][rand()&3] ); } break; case EV_FOOTSPLASH: DEBUGNAME("EV_FOOTSPLASH"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] ); } break; case EV_FOOTWADE: DEBUGNAME("EV_FOOTWADE"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] ); } break; case EV_SWIM: DEBUGNAME("EV_SWIM"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] ); } break; case EV_FALL_SHORT: DEBUGNAME("EV_FALL_SHORT"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.landSound ); if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -8; cg.landTime = cg.time; } break; case EV_FALL_MEDIUM: DEBUGNAME("EV_FALL_MEDIUM"); // use normal pain sound trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*pain100_1.wav" ) ); if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -16; cg.landTime = cg.time; } break; case EV_FALL_FAR: DEBUGNAME("EV_FALL_FAR"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*fall1.wav" ) ); cent->pe.painTime = cg.time; // don't play a pain sound right after this if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -24; cg.landTime = cg.time; } break; case EV_STEP_4: case EV_STEP_8: case EV_STEP_12: case EV_STEP_16: // smooth out step up transitions DEBUGNAME("EV_STEP"); { float oldStep; int delta; int step; if ( clientNum != cg.predictedPlayerState.clientNum ) { break; } // if we are interpolating, we don't need to smooth steps if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW) || cg_nopredict.integer || cg_synchronousClients.integer ) { break; } // check for stepping up before a previous step is completed delta = cg.time - cg.stepTime; if (delta < STEP_TIME) { oldStep = cg.stepChange * (STEP_TIME - delta) / STEP_TIME; } else { oldStep = 0; } // add this amount step = 4 * (event - EV_STEP_4 + 1 ); cg.stepChange = oldStep + step; if ( cg.stepChange > MAX_STEP_CHANGE ) { cg.stepChange = MAX_STEP_CHANGE; } cg.stepTime = cg.time; break; } case EV_JUMP_PAD: DEBUGNAME("EV_JUMP_PAD"); // CG_Printf( "EV_JUMP_PAD w/effect #%i\n", es->eventParm ); { localEntity_t *smoke; vec3_t up = {0, 0, 1}; smoke = CG_SmokePuff( cent->lerpOrigin, up, 32, 1, 1, 1, 0.33f, 1000, cg.time, 0, LEF_PUFF_DONT_SCALE, cgs.media.smokePuffShader ); } // boing sound at origin, jump sound on player trap_S_StartSound ( cent->lerpOrigin, -1, CHAN_VOICE, cgs.media.jumpPadSound ); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); break; case EV_JUMP: DEBUGNAME("EV_JUMP"); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); break; case EV_TAUNT: DEBUGNAME("EV_TAUNT"); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*taunt.wav" ) ); break; #ifdef MISSIONPACK case EV_TAUNT_YES: DEBUGNAME("EV_TAUNT_YES"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_YES); break; case EV_TAUNT_NO: DEBUGNAME("EV_TAUNT_NO"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_NO); break; case EV_TAUNT_FOLLOWME: DEBUGNAME("EV_TAUNT_FOLLOWME"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_FOLLOWME); break; case EV_TAUNT_GETFLAG: DEBUGNAME("EV_TAUNT_GETFLAG"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONGETFLAG); break; case EV_TAUNT_GUARDBASE: DEBUGNAME("EV_TAUNT_GUARDBASE"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONDEFENSE); break; case EV_TAUNT_PATROL: DEBUGNAME("EV_TAUNT_PATROL"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONPATROL); break; #endif case EV_WATER_TOUCH: DEBUGNAME("EV_WATER_TOUCH"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrInSound ); break; case EV_WATER_LEAVE: DEBUGNAME("EV_WATER_LEAVE"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound ); break; case EV_WATER_UNDER: DEBUGNAME("EV_WATER_UNDER"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound ); break; case EV_WATER_CLEAR: DEBUGNAME("EV_WATER_CLEAR"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*gasp.wav" ) ); break; case EV_ITEM_PICKUP: DEBUGNAME("EV_ITEM_PICKUP"); { gitem_t *item; int index; index = es->eventParm; // player predicted if ( index < 1 || index >= bg_numItems ) { break; } item = &bg_itemlist[ index ]; // powerups and team items will have a separate global sound, this one // will be played at prediction time if ( item->giType == IT_POWERUP || item->giType == IT_TEAM) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.n_healthSound ); } else if (item->giType == IT_PERSISTANT_POWERUP) { #ifdef MISSIONPACK switch (item->giTag ) { case PW_SCOUT: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.scoutSound ); break; case PW_GUARD: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.guardSound ); break; case PW_DOUBLER: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.doublerSound ); break; case PW_AMMOREGEN: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.ammoregenSound ); break; } #endif } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, trap_S_RegisterSound( item->pickup_sound, qfalse ) ); } // show icon and name on status bar if ( es->number == cg.snap->ps.clientNum ) { CG_ItemPickup( index ); } } break; case EV_GLOBAL_ITEM_PICKUP: DEBUGNAME("EV_GLOBAL_ITEM_PICKUP"); { gitem_t *item; int index; index = es->eventParm; // player predicted if ( index < 1 || index >= bg_numItems ) { break; } item = &bg_itemlist[ index ]; // powerup pickups are global if( item->pickup_sound ) { trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_AUTO, trap_S_RegisterSound( item->pickup_sound, qfalse ) ); } // show icon and name on status bar if ( es->number == cg.snap->ps.clientNum ) { CG_ItemPickup( index ); } } break; // // weapon events // case EV_NOAMMO: DEBUGNAME("EV_NOAMMO"); // trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.noAmmoSound ); if ( es->number == cg.snap->ps.clientNum ) { CG_OutOfAmmoChange(); } break; case EV_CHANGE_WEAPON: DEBUGNAME("EV_CHANGE_WEAPON"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.selectSound ); break; case EV_FIRE_WEAPON: DEBUGNAME("EV_FIRE_WEAPON"); CG_FireWeapon( cent ); break; case EV_USE_ITEM0: DEBUGNAME("EV_USE_ITEM0"); CG_UseItem( cent ); break; case EV_USE_ITEM1: DEBUGNAME("EV_USE_ITEM1"); CG_UseItem( cent ); break; case EV_USE_ITEM2: DEBUGNAME("EV_USE_ITEM2"); CG_UseItem( cent ); break; case EV_USE_ITEM3: DEBUGNAME("EV_USE_ITEM3"); CG_UseItem( cent ); break; case EV_USE_ITEM4: DEBUGNAME("EV_USE_ITEM4"); CG_UseItem( cent ); break; case EV_USE_ITEM5: DEBUGNAME("EV_USE_ITEM5"); CG_UseItem( cent ); break; case EV_USE_ITEM6: DEBUGNAME("EV_USE_ITEM6"); CG_UseItem( cent ); break; case EV_USE_ITEM7: DEBUGNAME("EV_USE_ITEM7"); CG_UseItem( cent ); break; case EV_USE_ITEM8: DEBUGNAME("EV_USE_ITEM8"); CG_UseItem( cent ); break; case EV_USE_ITEM9: DEBUGNAME("EV_USE_ITEM9"); CG_UseItem( cent ); break; case EV_USE_ITEM10: DEBUGNAME("EV_USE_ITEM10"); CG_UseItem( cent ); break; case EV_USE_ITEM11: DEBUGNAME("EV_USE_ITEM11"); CG_UseItem( cent ); break; case EV_USE_ITEM12: DEBUGNAME("EV_USE_ITEM12"); CG_UseItem( cent ); break; case EV_USE_ITEM13: DEBUGNAME("EV_USE_ITEM13"); CG_UseItem( cent ); break; case EV_USE_ITEM14: DEBUGNAME("EV_USE_ITEM14"); CG_UseItem( cent ); break; //================================================================= // // other events // case EV_PLAYER_TELEPORT_IN: DEBUGNAME("EV_PLAYER_TELEPORT_IN"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleInSound ); CG_SpawnEffect( position); break; case EV_PLAYER_TELEPORT_OUT: DEBUGNAME("EV_PLAYER_TELEPORT_OUT"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleOutSound ); CG_SpawnEffect( position); break; case EV_ITEM_POP: DEBUGNAME("EV_ITEM_POP"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound ); break; case EV_ITEM_RESPAWN: DEBUGNAME("EV_ITEM_RESPAWN"); cent->miscTime = cg.time; // scale up from this trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound ); break; case EV_GRENADE_BOUNCE: DEBUGNAME("EV_GRENADE_BOUNCE"); if ( rand() & 1 ) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.hgrenb1aSound ); } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.hgrenb2aSound ); } break; case EV_PROXIMITY_MINE_STICK: DEBUGNAME("EV_PROXIMITY_MINE_STICK"); if( es->eventParm & SURF_FLESH ) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbimplSound ); } else if( es->eventParm & SURF_METALSTEPS ) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbimpmSound ); } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbimpdSound ); } break; case EV_PROXIMITY_MINE_TRIGGER: DEBUGNAME("EV_PROXIMITY_MINE_TRIGGER"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbactvSound ); break; case EV_KAMIKAZE: DEBUGNAME("EV_KAMIKAZE"); CG_KamikazeEffect( cent->lerpOrigin ); break; case EV_OBELISKEXPLODE: DEBUGNAME("EV_OBELISKEXPLODE"); CG_ObeliskExplode( cent->lerpOrigin, es->eventParm ); break; case EV_OBELISKPAIN: DEBUGNAME("EV_OBELISKPAIN"); CG_ObeliskPain( cent->lerpOrigin ); break; case EV_INVUL_IMPACT: DEBUGNAME("EV_INVUL_IMPACT"); CG_InvulnerabilityImpact( cent->lerpOrigin, cent->currentState.angles ); break; case EV_JUICED: DEBUGNAME("EV_JUICED"); CG_InvulnerabilityJuiced( cent->lerpOrigin ); break; case EV_LIGHTNINGBOLT: DEBUGNAME("EV_LIGHTNINGBOLT"); CG_LightningBoltBeam(es->origin2, es->pos.trBase); break; case EV_SCOREPLUM: DEBUGNAME("EV_SCOREPLUM"); CG_ScorePlum( cent->currentState.otherEntityNum, cent->lerpOrigin, cent->currentState.time ); break; // // missile impacts // case EV_MISSILE_HIT: DEBUGNAME("EV_MISSILE_HIT"); ByteToDir( es->eventParm, dir ); CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum ); break; case EV_MISSILE_MISS: DEBUGNAME("EV_MISSILE_MISS"); ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT ); break; case EV_MISSILE_MISS_METAL: DEBUGNAME("EV_MISSILE_MISS_METAL"); ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_METAL ); break; case EV_RAILTRAIL: DEBUGNAME("EV_RAILTRAIL"); cent->currentState.weapon = WP_RAILGUN; //unlagged - attack prediction #2 // if the client is us, unlagged is on server-side, and we've got it client-side if ( es->clientNum == cg.predictedPlayerState.clientNum && cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 16) ) { // do nothing, because it was already predicted //Com_Printf("Ignoring rail trail event\n"); } else { if(es->clientNum == cg.snap->ps.clientNum && !cg.renderingThirdPerson) { if(cg_drawGun.integer == 2) VectorMA(es->origin2, 8, cg.refdef.viewaxis[1], es->origin2); else if(cg_drawGun.integer == 3) VectorMA(es->origin2, 4, cg.refdef.viewaxis[1], es->origin2); } // draw a rail trail, because it wasn't predicted CG_RailTrail( ci, es->origin2, es->pos.trBase ); // if the end was on a nomark surface, don't make an explosion if ( es->eventParm != 255 ) { ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT ); } //Com_Printf("Non-predicted rail trail\n"); } //unlagged - attack prediction #2 break; case EV_BULLET_HIT_WALL: DEBUGNAME("EV_BULLET_HIT_WALL"); //unlagged - attack prediction #2 // if the client is us, unlagged is on server-side, and we've got it client-side if ( es->clientNum == cg.predictedPlayerState.clientNum && cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 2) ) { // do nothing, because it was already predicted //Com_Printf("Ignoring bullet event\n"); } else { // do the bullet, because it wasn't predicted ByteToDir( es->eventParm, dir ); CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD ); //Com_Printf("Non-predicted bullet\n"); } //unlagged - attack prediction #2 break; case EV_BULLET_HIT_FLESH: DEBUGNAME("EV_BULLET_HIT_FLESH"); //unlagged - attack prediction #2 // if the client is us, unlagged is on server-side, and we've got it client-side if ( es->clientNum == cg.predictedPlayerState.clientNum && cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 2) ) { // do nothing, because it was already predicted //Com_Printf("Ignoring bullet event\n"); } else { // do the bullet, because it wasn't predicted CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm ); //Com_Printf("Non-predicted bullet\n"); } //unlagged - attack prediction #2 break; case EV_SHOTGUN: DEBUGNAME("EV_SHOTGUN"); //unlagged - attack prediction #2 // if the client is us, unlagged is on server-side, and we've got it client-side if ( es->otherEntityNum == cg.predictedPlayerState.clientNum && cgs.delagHitscan && (cg_delag.integer & 1 || cg_delag.integer & 4) ) { // do nothing, because it was already predicted //Com_Printf("Ignoring shotgun event\n"); } else { // do the shotgun pattern, because it wasn't predicted CG_ShotgunFire( es ); //Com_Printf("Non-predicted shotgun pattern\n"); } //unlagged - attack prediction #2 break; case EV_GENERAL_SOUND: DEBUGNAME("EV_GENERAL_SOUND"); if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartSound (NULL, es->number, CHAN_VOICE, cgs.gameSounds[ es->eventParm ] ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, s ) ); } break; case EV_GLOBAL_SOUND: // play from the player's head so it never diminishes DEBUGNAME("EV_GLOBAL_SOUND"); if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.gameSounds[ es->eventParm ] ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_AUTO, CG_CustomSound( es->number, s ) ); } break; case EV_GLOBAL_TEAM_SOUND: // play from the player's head so it never diminishes { DEBUGNAME("EV_GLOBAL_TEAM_SOUND"); switch( es->eventParm ) { case GTS_RED_CAPTURE: // CTF: red team captured the blue flag, 1FCTF: red team captured the neutral flag if ( cgs.clientinfo[cg.clientNum].team == TEAM_RED ) CG_AddBufferedSound( cgs.media.captureYourTeamSound ); else CG_AddBufferedSound( cgs.media.captureOpponentSound ); break; case GTS_BLUE_CAPTURE: // CTF: blue team captured the red flag, 1FCTF: blue team captured the neutral flag if ( cgs.clientinfo[cg.clientNum].team == TEAM_BLUE ) CG_AddBufferedSound( cgs.media.captureYourTeamSound ); else CG_AddBufferedSound( cgs.media.captureOpponentSound ); break; case GTS_RED_RETURN: // CTF: blue flag returned, 1FCTF: never used if ( cgs.clientinfo[cg.clientNum].team == TEAM_RED ) CG_AddBufferedSound( cgs.media.returnYourTeamSound ); else CG_AddBufferedSound( cgs.media.returnOpponentSound ); // CG_AddBufferedSound( cgs.media.blueFlagReturnedSound ); break; case GTS_BLUE_RETURN: // CTF red flag returned, 1FCTF: neutral flag returned if ( cgs.clientinfo[cg.clientNum].team == TEAM_BLUE ) CG_AddBufferedSound( cgs.media.returnYourTeamSound ); else CG_AddBufferedSound( cgs.media.returnOpponentSound ); // CG_AddBufferedSound( cgs.media.redFlagReturnedSound ); break; case GTS_RED_TAKEN: // CTF: red team took blue flag, 1FCTF: blue team took the neutral flag // if this player picked up the flag then a sound is played in CG_CheckLocalSounds if (cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_NEUTRALFLAG]) { } else { if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) { //#ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.yourTeamTookTheFlagSound ); else //#endif CG_AddBufferedSound( cgs.media.enemyTookYourFlagSound ); } else if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) { //#ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.enemyTookTheFlagSound ); else //#endif CG_AddBufferedSound( cgs.media.yourTeamTookEnemyFlagSound ); } } break; case GTS_BLUE_TAKEN: // CTF: blue team took the red flag, 1FCTF red team took the neutral flag // if this player picked up the flag then a sound is played in CG_CheckLocalSounds if (cg.snap->ps.powerups[PW_REDFLAG] || cg.snap->ps.powerups[PW_NEUTRALFLAG]) { } else { if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) { //#ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.yourTeamTookTheFlagSound ); else //#endif CG_AddBufferedSound( cgs.media.enemyTookYourFlagSound ); } else if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) { //#ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.enemyTookTheFlagSound ); else //#endif CG_AddBufferedSound( cgs.media.yourTeamTookEnemyFlagSound ); } } break; case GTS_REDOBELISK_ATTACKED: // Overload: red obelisk is being attacked if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) { CG_AddBufferedSound( cgs.media.yourBaseIsUnderAttackSound ); } break; case GTS_BLUEOBELISK_ATTACKED: // Overload: blue obelisk is being attacked if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) { CG_AddBufferedSound( cgs.media.yourBaseIsUnderAttackSound ); } break; case GTS_REDTEAM_SCORED: CG_AddBufferedSound(cgs.media.redScoredSound); break; case GTS_BLUETEAM_SCORED: CG_AddBufferedSound(cgs.media.blueScoredSound); break; case GTS_REDTEAM_TOOK_LEAD: CG_AddBufferedSound(cgs.media.redLeadsSound); break; case GTS_BLUETEAM_TOOK_LEAD: CG_AddBufferedSound(cgs.media.blueLeadsSound); break; case GTS_TEAMS_ARE_TIED: CG_AddBufferedSound( cgs.media.teamsTiedSound ); break; case GTS_KAMIKAZE: trap_S_StartLocalSound(cgs.media.kamikazeFarSound, CHAN_ANNOUNCER); break; default: break; } break; } case EV_PAIN: // local player sounds are triggered in CG_CheckLocalSounds, // so ignore events on the player DEBUGNAME("EV_PAIN"); if ( cent->currentState.number != cg.snap->ps.clientNum ) { CG_PainEvent( cent, es->eventParm ); } break; case EV_DEATH1: case EV_DEATH2: case EV_DEATH3: DEBUGNAME("EV_DEATHx"); if (CG_WaterLevel(cent) >= 1) { trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, "*drown.wav")); } else { trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, va("*death%i.wav", event - EV_DEATH1 + 1))); } break; case EV_OBITUARY: DEBUGNAME("EV_OBITUARY"); CG_Obituary( es ); break; // // powerup events // case EV_POWERUP_QUAD: DEBUGNAME("EV_POWERUP_QUAD"); if ( es->number == cg.snap->ps.clientNum ) { cg.powerupActive = PW_QUAD; cg.powerupTime = cg.time; } trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.quadSound ); break; case EV_POWERUP_BATTLESUIT: DEBUGNAME("EV_POWERUP_BATTLESUIT"); if ( es->number == cg.snap->ps.clientNum ) { cg.powerupActive = PW_BATTLESUIT; cg.powerupTime = cg.time; } trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.protectSound ); break; case EV_POWERUP_REGEN: DEBUGNAME("EV_POWERUP_REGEN"); if ( es->number == cg.snap->ps.clientNum ) { cg.powerupActive = PW_REGEN; cg.powerupTime = cg.time; } trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.regenSound ); break; case EV_GIB_PLAYER: DEBUGNAME("EV_GIB_PLAYER"); // don't play gib sound when using the kamikaze because it interferes // with the kamikaze sound, downside is that the gib sound will also // not be played when someone is gibbed while just carrying the kamikaze if ( !(es->eFlags & EF_KAMIKAZE) ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.gibSound ); } CG_GibPlayer( cent->lerpOrigin ); break; case EV_STOPLOOPINGSOUND: DEBUGNAME("EV_STOPLOOPINGSOUND"); trap_S_StopLoopingSound( es->number ); es->loopSound = 0; break; case EV_DEBUG_LINE: DEBUGNAME("EV_DEBUG_LINE"); CG_Beam( cent ); break; default: DEBUGNAME("UNKNOWN"); CG_Error( "Unknown event: %i", event ); break; } }
/* ================= UI_SPSkillMenu_Init ================= */ static void UI_SPSkillMenu_Init( void ) { int skill; memset( &skillMenuInfo, 0, sizeof(skillMenuInfo) ); skillMenuInfo.menu.fullscreen = qtrue; skillMenuInfo.menu.key = UI_SPSkillMenu_Key; UI_SPSkillMenu_Cache(); skillMenuInfo.art_frame.generic_mc.type = MTYPE_BITMAP; skillMenuInfo.art_frame.generic_mc.name = ART_FRAME; skillMenuInfo.art_frame.generic_mc.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE; skillMenuInfo.art_frame.generic_mc.x = 142; skillMenuInfo.art_frame.generic_mc.y = 118; skillMenuInfo.art_frame.width = 359; skillMenuInfo.art_frame.height = 256; skillMenuInfo.art_banner.generic_mc.type = MTYPE_BTEXT; skillMenuInfo.art_banner.generic_mc.flags = QMF_CENTER_JUSTIFY; skillMenuInfo.art_banner.generic_mc.x = 320; skillMenuInfo.art_banner.generic_mc.y = 16; skillMenuInfo.art_banner.string = "DIFFICULTY"; skillMenuInfo.art_banner.color = color_white; skillMenuInfo.art_banner.style = UI_CENTER; skillMenuInfo.item_baby.generic_mc.type = MTYPE_PTEXT; skillMenuInfo.item_baby.generic_mc.flags = QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS; skillMenuInfo.item_baby.generic_mc.x = 320; skillMenuInfo.item_baby.generic_mc.y = 170; skillMenuInfo.item_baby.generic_mc.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_baby.generic_mc.id = ID_BABY; skillMenuInfo.item_baby.string = "I Can Win"; skillMenuInfo.item_baby.color = color_red; skillMenuInfo.item_baby.style = UI_CENTER; skillMenuInfo.item_easy.generic_mc.type = MTYPE_PTEXT; skillMenuInfo.item_easy.generic_mc.flags = QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS; skillMenuInfo.item_easy.generic_mc.x = 320; skillMenuInfo.item_easy.generic_mc.y = 198; skillMenuInfo.item_easy.generic_mc.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_easy.generic_mc.id = ID_EASY; skillMenuInfo.item_easy.string = "Bring It On"; skillMenuInfo.item_easy.color = color_red; skillMenuInfo.item_easy.style = UI_CENTER; skillMenuInfo.item_medium.generic_mc.type = MTYPE_PTEXT; skillMenuInfo.item_medium.generic_mc.flags = QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS; skillMenuInfo.item_medium.generic_mc.x = 320; skillMenuInfo.item_medium.generic_mc.y = 227; skillMenuInfo.item_medium.generic_mc.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_medium.generic_mc.id = ID_MEDIUM; skillMenuInfo.item_medium.string = "Hurt Me Plenty"; skillMenuInfo.item_medium.color = color_red; skillMenuInfo.item_medium.style = UI_CENTER; skillMenuInfo.item_hard.generic_mc.type = MTYPE_PTEXT; skillMenuInfo.item_hard.generic_mc.flags = QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS; skillMenuInfo.item_hard.generic_mc.x = 320; skillMenuInfo.item_hard.generic_mc.y = 255; skillMenuInfo.item_hard.generic_mc.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_hard.generic_mc.id = ID_HARD; skillMenuInfo.item_hard.string = "Hardcore"; skillMenuInfo.item_hard.color = color_red; skillMenuInfo.item_hard.style = UI_CENTER; skillMenuInfo.item_nightmare.generic_mc.type = MTYPE_PTEXT; skillMenuInfo.item_nightmare.generic_mc.flags = QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS; skillMenuInfo.item_nightmare.generic_mc.x = 320; skillMenuInfo.item_nightmare.generic_mc.y = 283; skillMenuInfo.item_nightmare.generic_mc.callback = UI_SPSkillMenu_SkillEvent; skillMenuInfo.item_nightmare.generic_mc.id = ID_NIGHTMARE; skillMenuInfo.item_nightmare.string = "NIGHTMARE!"; skillMenuInfo.item_nightmare.color = color_red; skillMenuInfo.item_nightmare.style = UI_CENTER; skillMenuInfo.item_back.generic_mc.type = MTYPE_BITMAP; skillMenuInfo.item_back.generic_mc.name = ART_BACK; skillMenuInfo.item_back.generic_mc.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; skillMenuInfo.item_back.generic_mc.x = 0; skillMenuInfo.item_back.generic_mc.y = 480-64; skillMenuInfo.item_back.generic_mc.callback = UI_SPSkillMenu_BackEvent; skillMenuInfo.item_back.generic_mc.id = ID_BACK; skillMenuInfo.item_back.width = 128; skillMenuInfo.item_back.height = 64; skillMenuInfo.item_back.focuspic = ART_BACK_FOCUS; skillMenuInfo.art_skillPic.generic_mc.type = MTYPE_BITMAP; skillMenuInfo.art_skillPic.generic_mc.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE; skillMenuInfo.art_skillPic.generic_mc.x = 320-64; skillMenuInfo.art_skillPic.generic_mc.y = 368; skillMenuInfo.art_skillPic.width = 128; skillMenuInfo.art_skillPic.height = 96; skillMenuInfo.item_fight.generic_mc.type = MTYPE_BITMAP; skillMenuInfo.item_fight.generic_mc.name = ART_FIGHT; skillMenuInfo.item_fight.generic_mc.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS; skillMenuInfo.item_fight.generic_mc.callback = UI_SPSkillMenu_FightEvent; skillMenuInfo.item_fight.generic_mc.id = ID_FIGHT; skillMenuInfo.item_fight.generic_mc.x = 640; skillMenuInfo.item_fight.generic_mc.y = 480-64; skillMenuInfo.item_fight.width = 128; skillMenuInfo.item_fight.height = 64; skillMenuInfo.item_fight.focuspic = ART_FIGHT_FOCUS; Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.art_frame ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.art_banner ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.item_baby ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.item_easy ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.item_medium ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.item_hard ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.item_nightmare ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.art_skillPic ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.item_back ); Menu_AddItem( &skillMenuInfo.menu, ( void * )&skillMenuInfo.item_fight ); skill = (int)Com_Clamp( 1, 5, trap_Cvar_VariableValue( "g_spSkill" ) ); SetSkillColor( skill, color_white ); skillMenuInfo.art_skillPic.shader = skillMenuInfo.skillpics[skill - 1]; if( skill == 5 ) { trap_S_StartLocalSound( skillMenuInfo.nightmareSound, CHAN_ANNOUNCER ); } }
void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) { refdef_t refdef; refEntity_t legs = {0}; refEntity_t torso = {0}; refEntity_t head = {0}; refEntity_t gun = {0}; refEntity_t backpack = {0}; refEntity_t helmet = {0}; // refEntity_t barrel = {0}; refEntity_t flash = {0}; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; float len; float xx; vec4_t hcolor = { 1, 0, 0, 0.5 }; const char *torso_anim = NULL, *legs_anim = NULL; if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) { return; } dp_realtime = time; if ( pi->pendingWeapon != WP_NUM_WEAPONS && dp_realtime > pi->weaponTimer ) { pi->weapon = pi->pendingWeapon; pi->lastWeapon = pi->pendingWeapon; pi->pendingWeapon = WP_NUM_WEAPONS; pi->weaponTimer = 0; if ( pi->currentWeapon != pi->weapon ) { trap_S_StartLocalSound( trap_S_RegisterSound( "sound/weapons/change.wav" ), CHAN_LOCAL ); } } UI_AdjustFrom640( &x, &y, &w, &h ); y -= jumpHeight; memset( &refdef, 0, sizeof( refdef ) ); memset( &legs, 0, sizeof( legs ) ); memset( &torso, 0, sizeof( torso ) ); memset( &head, 0, sizeof( head ) ); refdef.rdflags = RDF_NOWORLDMODEL; AxisClear( refdef.viewaxis ); refdef.x = x; refdef.y = y; refdef.width = w; refdef.height = h; refdef.fov_x = (int)((float)refdef.width / uiInfo.uiDC.xscale / 640.0f * 90.0f); xx = refdef.width / uiInfo.uiDC.xscale / tan( refdef.fov_x / 360 * M_PI ); refdef.fov_y = atan2( refdef.height / uiInfo.uiDC.yscale, xx ); refdef.fov_y *= ( 360 / M_PI ); // calculate distance so the player nearly fills the box len = 1.01 * ( maxs[2] - mins[2] ); // NERVE - SMF - changed from 0.7 origin[0] = len / tan( DEG2RAD( refdef.fov_x ) * 0.5 ); origin[1] = 0.5 * ( mins[1] + maxs[1] ); origin[2] = -0.5 * ( mins[2] + maxs[2] ); refdef.time = dp_realtime; trap_R_SetColor( hcolor ); trap_R_ClearScene(); trap_R_SetColor( NULL ); // get the rotation information UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis ); // get the animation state (after rotation, to allow feet shuffle) // UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp, // &torso.oldframe, &torso.frame, &torso.backlerp ); renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW; // // add the body // legs.hModel = pi->legsModel; legs.customSkin = pi->legsSkin; legs.renderfx = renderfx; VectorCopy( origin, legs.origin ); VectorCopy( origin, legs.lightingOrigin ); VectorCopy( legs.origin, legs.oldorigin ); WM_getWeaponAnim( &torso_anim, &legs_anim ); if ( torso_anim ) { legs.torsoFrame = UI_GetAnimation( pi, torso_anim ); legs.oldTorsoFrame = UI_GetAnimation( pi, torso_anim ); } legs.torsoBacklerp = 0; //torso.backlerp; if ( legs_anim ) { legs.frame = UI_GetAnimation( pi, legs_anim ); legs.oldframe = UI_GetAnimation( pi, legs_anim ); } legs.backlerp = 0; memcpy( legs.torsoAxis, torso.axis, sizeof( torso.axis ) ); torso = legs; trap_R_AddRefEntityToScene( &torso ); // // add the head // head.hModel = pi->headModel; if ( !head.hModel ) { return; } head.customSkin = pi->headSkin; VectorCopy( origin, head.lightingOrigin ); UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head" ); head.renderfx = renderfx; trap_R_AddRefEntityToScene( &head ); // // add the gun // if ( pi->currentWeapon != WP_NONE ) { memset( &gun, 0, sizeof( gun ) ); gun.hModel = pi->weaponModel; VectorCopy( origin, gun.lightingOrigin ); UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon" ); gun.renderfx = renderfx; trap_R_AddRefEntityToScene( &gun ); } // // add muzzle flash // if ( dp_realtime <= pi->muzzleFlashTime ) { if ( pi->flashModel ) { memset( &flash, 0, sizeof( flash ) ); flash.hModel = pi->flashModel; VectorCopy( origin, flash.lightingOrigin ); UI_PositionEntityOnTag( &flash, &gun, pi->weaponModel, "tag_flash" ); flash.renderfx = renderfx; trap_R_AddRefEntityToScene( &flash ); } // make a dlight for the flash if ( pi->flashDlightColor[0] || pi->flashDlightColor[1] || pi->flashDlightColor[2] ) { trap_R_AddLightToScene( flash.origin, 200 + ( rand() & 31 ), pi->flashDlightColor[0], pi->flashDlightColor[1], pi->flashDlightColor[2], 0 ); } } // // add the backpack // if ( pi->backpackModel ) { memset( &backpack, 0, sizeof( backpack ) ); backpack.hModel = pi->backpackModel; VectorCopy( origin, backpack.lightingOrigin ); UI_PositionEntityOnTag( &backpack, &torso, pi->torsoModel, "tag_back" ); backpack.renderfx = renderfx; trap_R_AddRefEntityToScene( &backpack ); } // // add the helmet // if ( pi->helmetModel ) { memset( &helmet, 0, sizeof( helmet ) ); helmet.hModel = pi->helmetModel; VectorCopy( origin, helmet.lightingOrigin ); UI_PositionEntityOnTag( &helmet, &head, pi->headModel, "tag_mouth" ); helmet.renderfx = renderfx; trap_R_AddRefEntityToScene( &helmet ); } // // add the chat icon // if ( pi->chat ) { UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) ); } // // add an accent light // // origin[0] -= 100; // + = behind, - = in front // origin[1] += 100; // + = left, - = right // origin[2] += 100; // + = above, - = below trap_R_AddLightToScene( origin, 500, 1.0, 1.0, 1.0, 0 ); origin[0] -= 100; origin[1] -= 100; origin[2] -= 100; trap_R_AddLightToScene( origin, 500, 1.0, 0.0, 0.0, 0 ); trap_R_RenderScene( &refdef ); }
/* ================== CG_CheckLocalSounds ================== */ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) { const char *s; int highScore; // hit changes if ( ps->persistant[PERS_HITS] > ops->persistant[PERS_HITS] ) { trap_S_StartLocalSound( cgs.media.hitSound, CHAN_LOCAL_SOUND ); } else if ( ps->persistant[PERS_HITS] < ops->persistant[PERS_HITS] ) { trap_S_StartLocalSound( cgs.media.hitTeamSound, CHAN_LOCAL_SOUND ); } // health changes of more than -1 should make pain sounds if ( ps->stats[STAT_HEALTH] < ops->stats[STAT_HEALTH] - 1 ) { if ( ps->stats[STAT_HEALTH] > 0 ) { CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH], qfalse ); } } // if we are going into the intermission, don't start any voices if ( cg.intermissionStarted ) { return; } // reward sounds if ( ps->persistant[PERS_REWARD_COUNT] > ops->persistant[PERS_REWARD_COUNT] ) { switch ( ps->persistant[PERS_REWARD] ) { case REWARD_IMPRESSIVE: trap_S_StartLocalSound( cgs.media.impressiveSound, CHAN_ANNOUNCER ); cg.rewardTime = cg.time; cg.rewardShader = cgs.media.medalImpressive; cg.rewardCount = ps->persistant[PERS_IMPRESSIVE_COUNT]; break; case REWARD_EXCELLENT: trap_S_StartLocalSound( cgs.media.excellentSound, CHAN_ANNOUNCER ); cg.rewardTime = cg.time; cg.rewardShader = cgs.media.medalExcellent; cg.rewardCount = ps->persistant[PERS_EXCELLENT_COUNT]; break; case REWARD_DENIED: trap_S_StartLocalSound( cgs.media.deniedSound, CHAN_ANNOUNCER ); break; case REWARD_GAUNTLET: trap_S_StartLocalSound( cgs.media.humiliationSound, CHAN_ANNOUNCER ); // if we are the killer and not the killee, show the award if ( ps->stats[STAT_HEALTH] ) { cg.rewardTime = cg.time; cg.rewardShader = cgs.media.medalGauntlet; cg.rewardCount = ps->persistant[PERS_GAUNTLET_FRAG_COUNT]; } break; default: CG_Error( "Bad reward_t" ); } } else { // lead changes (only if no reward) s = CG_ConfigString( CS_WARMUP ); if ( !s[0] ) { // never play lead changes during warmup if ( ps->persistant[PERS_RANK] != ops->persistant[PERS_RANK] ) { if ( cgs.gametype >= GT_TEAM ) { if ( ps->persistant[PERS_RANK] == 2 ) { trap_S_StartLocalSound( cgs.media.teamsTiedSound, CHAN_ANNOUNCER ); } else if ( ps->persistant[PERS_RANK] == 0 ) { trap_S_StartLocalSound( cgs.media.redLeadsSound, CHAN_ANNOUNCER ); } else if ( ps->persistant[PERS_RANK] == 1 ) { trap_S_StartLocalSound( cgs.media.blueLeadsSound, CHAN_ANNOUNCER ); } } else { if ( ps->persistant[PERS_RANK] == 0 ) { trap_S_StartLocalSound( cgs.media.takenLeadSound, CHAN_ANNOUNCER ); } else if ( ps->persistant[PERS_RANK] == RANK_TIED_FLAG ) { trap_S_StartLocalSound( cgs.media.tiedLeadSound, CHAN_ANNOUNCER ); } else if ( ( ops->persistant[PERS_RANK] & ~RANK_TIED_FLAG ) == 0 ) { trap_S_StartLocalSound( cgs.media.lostLeadSound, CHAN_ANNOUNCER ); } } } } } // timelimit warnings if ( cgs.timelimit > 0 ) { int msec; msec = cg.time - cgs.levelStartTime; if ( cgs.timelimit > 5 && !( cg.timelimitWarnings & 1 ) && msec > ( cgs.timelimit - 5 ) * 60 * 1000 ) { cg.timelimitWarnings |= 1; trap_S_StartLocalSound( cgs.media.fiveMinuteSound, CHAN_ANNOUNCER ); } if ( !( cg.timelimitWarnings & 2 ) && msec > ( cgs.timelimit - 1 ) * 60 * 1000 ) { cg.timelimitWarnings |= 2; trap_S_StartLocalSound( cgs.media.oneMinuteSound, CHAN_ANNOUNCER ); } if ( !( cg.timelimitWarnings & 4 ) && msec > ( cgs.timelimit * 60 + 2 ) * 1000 ) { cg.timelimitWarnings |= 4; trap_S_StartLocalSound( cgs.media.suddenDeathSound, CHAN_ANNOUNCER ); } } // fraglimit warnings if ( cgs.fraglimit > 0 && cgs.gametype != GT_CTF ) { highScore = cgs.scores1; if ( cgs.fraglimit > 3 && !( cg.fraglimitWarnings & 1 ) && highScore == ( cgs.fraglimit - 3 ) ) { cg.fraglimitWarnings |= 1; trap_S_StartLocalSound( cgs.media.threeFragSound, CHAN_ANNOUNCER ); } if ( cgs.fraglimit > 2 && !( cg.fraglimitWarnings & 2 ) && highScore == ( cgs.fraglimit - 2 ) ) { cg.fraglimitWarnings |= 2; trap_S_StartLocalSound( cgs.media.twoFragSound, CHAN_ANNOUNCER ); } if ( !( cg.fraglimitWarnings & 4 ) && highScore == ( cgs.fraglimit - 1 ) ) { cg.fraglimitWarnings |= 4; trap_S_StartLocalSound( cgs.media.oneFragSound, CHAN_ANNOUNCER ); } } }
void CG_EntityEvent( centity_t *cent, vec3_t position ) { entityState_t *es; int event; vec3_t dir; const char *s; int playerNum; playerInfo_t *pi; int i; es = ¢->currentState; event = es->event & ~EV_EVENT_BITS; if ( cg_debugEvents.integer ) { CG_Printf( "ent:%3i event:%3i ", es->number, event ); } if ( !event ) { DEBUGNAME("ZEROEVENT"); return; } playerNum = es->playerNum; if ( playerNum < 0 || playerNum >= MAX_CLIENTS ) { playerNum = 0; } pi = &cgs.playerinfo[ playerNum ]; switch ( event ) { // // movement generated events // case EV_FOOTSTEP: DEBUGNAME("EV_FOOTSTEP"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ pi->footsteps ][rand()&3] ); } break; case EV_FOOTSTEP_METAL: DEBUGNAME("EV_FOOTSTEP_METAL"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_METAL ][rand()&3] ); } break; case EV_FOOTSPLASH: DEBUGNAME("EV_FOOTSPLASH"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] ); } break; case EV_FOOTWADE: DEBUGNAME("EV_FOOTWADE"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] ); } break; case EV_SWIM: DEBUGNAME("EV_SWIM"); if (cg_footsteps.integer) { trap_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] ); } break; case EV_FALL_SHORT: DEBUGNAME("EV_FALL_SHORT"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.landSound ); for (i = 0; i < CG_MaxSplitView(); i++) { if ( playerNum == cg.snap->pss[i].playerNum ) { // smooth landing z changes cg.localPlayers[i].landChange = -8; cg.localPlayers[i].landTime = cg.time; } } break; case EV_FALL_MEDIUM: DEBUGNAME("EV_FALL_MEDIUM"); // use normal pain sound if (cgs.fallDamage) { trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*pain100_1.wav" ) ); } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.landSound ); } for (i = 0; i < CG_MaxSplitView(); i++) { if ( playerNum == cg.snap->pss[i].playerNum ) { // smooth landing z changes cg.localPlayers[i].landChange = -16; cg.localPlayers[i].landTime = cg.time; } } break; case EV_FALL_FAR: DEBUGNAME("EV_FALL_FAR"); if (cgs.fallDamage) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*fall1.wav" ) ); } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.landSound ); } cent->pe.painTime = cg.time; // don't play a pain sound right after this for (i = 0; i < CG_MaxSplitView(); i++) { if ( playerNum == cg.snap->pss[i].playerNum ) { // smooth landing z changes cg.localPlayers[i].landChange = -24; cg.localPlayers[i].landTime = cg.time; } } break; case EV_STEP_4: case EV_STEP_8: case EV_STEP_12: case EV_STEP_16: // smooth out step up transitions DEBUGNAME("EV_STEP"); { float oldStep; int delta; int step; localPlayer_t *player; playerState_t *ps; for (i = 0; i < CG_MaxSplitView(); i++) { player = &cg.localPlayers[i]; ps = &cg.snap->pss[i]; if ( playerNum != ps->playerNum ) { continue; } // if we are interpolating, we don't need to smooth steps if ( cg.demoPlayback || (ps->pm_flags & PMF_FOLLOW) || cg_nopredict.integer || cg_synchronousClients.integer ) { continue; } // check for stepping up before a previous step is completed delta = cg.time - player->stepTime; if (delta < STEP_TIME) { oldStep = player->stepChange * (STEP_TIME - delta) / STEP_TIME; } else { oldStep = 0; } // add this amount step = 4 * (event - EV_STEP_4 + 1 ); player->stepChange = oldStep + step; if ( player->stepChange > MAX_STEP_CHANGE ) { player->stepChange = MAX_STEP_CHANGE; } player->stepTime = cg.time; } break; } case EV_JUMP_PAD: DEBUGNAME("EV_JUMP_PAD"); // CG_Printf( "EV_JUMP_PAD w/effect #%i\n", es->eventParm ); { vec3_t up = {0, 0, 1}; CG_SmokePuff( cent->lerpOrigin, up, 32, 1, 1, 1, 0.33f, 1000, cg.time, 0, LEF_PUFF_DONT_SCALE, cgs.media.smokePuffShader ); } // boing sound at origin, jump sound on player trap_S_StartSound ( cent->lerpOrigin, -1, CHAN_VOICE, cgs.media.jumpPadSound ); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); break; case EV_JUMP: DEBUGNAME("EV_JUMP"); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); break; case EV_TAUNT: DEBUGNAME("EV_TAUNT"); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*taunt.wav" ) ); break; #ifdef MISSIONPACK case EV_TAUNT_YES: DEBUGNAME("EV_TAUNT_YES"); CG_VoiceChatLocal(~0, SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_YES); break; case EV_TAUNT_NO: DEBUGNAME("EV_TAUNT_NO"); CG_VoiceChatLocal(~0, SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_NO); break; case EV_TAUNT_FOLLOWME: DEBUGNAME("EV_TAUNT_FOLLOWME"); CG_VoiceChatLocal(~0, SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_FOLLOWME); break; case EV_TAUNT_GETFLAG: DEBUGNAME("EV_TAUNT_GETFLAG"); CG_VoiceChatLocal(~0, SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONGETFLAG); break; case EV_TAUNT_GUARDBASE: DEBUGNAME("EV_TAUNT_GUARDBASE"); CG_VoiceChatLocal(~0, SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONDEFENSE); break; case EV_TAUNT_PATROL: DEBUGNAME("EV_TAUNT_PATROL"); CG_VoiceChatLocal(~0, SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONPATROL); break; #endif case EV_WATER_TOUCH: DEBUGNAME("EV_WATER_TOUCH"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrInSound ); break; case EV_WATER_LEAVE: DEBUGNAME("EV_WATER_LEAVE"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound ); break; case EV_WATER_UNDER: DEBUGNAME("EV_WATER_UNDER"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound ); break; case EV_WATER_CLEAR: DEBUGNAME("EV_WATER_CLEAR"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*gasp.wav" ) ); break; case EV_ITEM_PICKUP: DEBUGNAME("EV_ITEM_PICKUP"); { gitem_t *item; int index; index = es->eventParm; // player predicted if ( index < 1 || index >= BG_NumItems() ) { break; } item = BG_ItemForItemNum( index ); // powerups and team items will have a separate global sound, this one // will be played at prediction time if ( item->giType == IT_POWERUP || item->giType == IT_TEAM) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.n_healthSound ); } else if (item->giType == IT_PERSISTANT_POWERUP) { #ifdef MISSIONPACK switch (item->giTag ) { case PW_SCOUT: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.scoutSound ); break; case PW_GUARD: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.guardSound ); break; case PW_DOUBLER: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.doublerSound ); break; case PW_AMMOREGEN: trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.ammoregenSound ); break; } #endif } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.itemPickupSounds[ index ] ); } // show icon and name on status bar for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->number == cg.snap->pss[i].playerNum ) { CG_ItemPickup( i, index ); } } } break; case EV_GLOBAL_ITEM_PICKUP: DEBUGNAME("EV_GLOBAL_ITEM_PICKUP"); { int index; index = es->eventParm; // player predicted if ( index < 1 || index >= BG_NumItems() ) { break; } // powerup pickups are global trap_S_StartLocalSound( cgs.media.itemPickupSounds[ index ], CHAN_AUTO ); // show icon and name on status bar for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->number == cg.snap->pss[i].playerNum ) { CG_ItemPickup( i, index ); } } } break; // // weapon events // case EV_NOAMMO: DEBUGNAME("EV_NOAMMO"); // trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.noAmmoSound ); for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->number == cg.snap->pss[i].playerNum ) { CG_OutOfAmmoChange(i); } } break; case EV_CHANGE_WEAPON: DEBUGNAME("EV_CHANGE_WEAPON"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.selectSound ); break; case EV_FIRE_WEAPON: DEBUGNAME("EV_FIRE_WEAPON"); CG_FireWeapon( cent ); break; case EV_USE_ITEM0: case EV_USE_ITEM1: case EV_USE_ITEM2: case EV_USE_ITEM3: case EV_USE_ITEM4: case EV_USE_ITEM5: case EV_USE_ITEM6: case EV_USE_ITEM7: case EV_USE_ITEM8: case EV_USE_ITEM9: case EV_USE_ITEM10: case EV_USE_ITEM11: case EV_USE_ITEM12: case EV_USE_ITEM13: case EV_USE_ITEM14: case EV_USE_ITEM15: DEBUGNAME2("EV_USE_ITEM%d", event - EV_USE_ITEM0); CG_UseItem( cent ); break; //================================================================= // // other events // case EV_PLAYER_TELEPORT_IN: DEBUGNAME("EV_PLAYER_TELEPORT_IN"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleInSound ); CG_SpawnEffect( position); break; case EV_PLAYER_TELEPORT_OUT: DEBUGNAME("EV_PLAYER_TELEPORT_OUT"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleOutSound ); CG_SpawnEffect( position); break; case EV_ITEM_POP: DEBUGNAME("EV_ITEM_POP"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound ); break; case EV_ITEM_RESPAWN: DEBUGNAME("EV_ITEM_RESPAWN"); cent->miscTime = cg.time; // scale up from this trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound ); break; case EV_GRENADE_BOUNCE: DEBUGNAME("EV_GRENADE_BOUNCE"); if ( rand() & 1 ) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.hgrenb1aSound ); } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.hgrenb2aSound ); } break; #ifdef MISSIONPACK case EV_PROXIMITY_MINE_STICK: DEBUGNAME("EV_PROXIMITY_MINE_STICK"); if( es->eventParm & SURF_FLESH ) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbimplSound ); } else if( es->eventParm & SURF_METALSTEPS ) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbimpmSound ); } else { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbimpdSound ); } break; case EV_PROXIMITY_MINE_TRIGGER: DEBUGNAME("EV_PROXIMITY_MINE_TRIGGER"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.wstbactvSound ); break; case EV_KAMIKAZE: DEBUGNAME("EV_KAMIKAZE"); CG_KamikazeEffect( cent->lerpOrigin ); break; case EV_OBELISKEXPLODE: DEBUGNAME("EV_OBELISKEXPLODE"); CG_ObeliskExplode( cent->lerpOrigin, es->eventParm ); break; case EV_OBELISKPAIN: DEBUGNAME("EV_OBELISKPAIN"); CG_ObeliskPain( cent->lerpOrigin ); break; case EV_INVUL_IMPACT: DEBUGNAME("EV_INVUL_IMPACT"); CG_InvulnerabilityImpact( cent->lerpOrigin, cent->currentState.angles ); break; case EV_JUICED: DEBUGNAME("EV_JUICED"); CG_InvulnerabilityJuiced( cent->lerpOrigin ); break; case EV_LIGHTNINGBOLT: DEBUGNAME("EV_LIGHTNINGBOLT"); CG_LightningBoltBeam(es->origin2, es->pos.trBase); break; #endif case EV_SCOREPLUM: DEBUGNAME("EV_SCOREPLUM"); CG_ScorePlum( cent->currentState.otherEntityNum, cent->lerpOrigin, cent->currentState.time ); break; // // missile impacts // case EV_MISSILE_HIT: DEBUGNAME("EV_MISSILE_HIT"); ByteToDir( es->eventParm, dir ); CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum ); break; case EV_MISSILE_MISS: DEBUGNAME("EV_MISSILE_MISS"); ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT ); break; case EV_MISSILE_MISS_METAL: DEBUGNAME("EV_MISSILE_MISS_METAL"); ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_METAL ); break; case EV_RAILTRAIL: DEBUGNAME("EV_RAILTRAIL"); cent->currentState.weapon = WP_RAILGUN; if ( es->playerNum >= 0 && es->playerNum < MAX_CLIENTS ) { for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->playerNum == cg.snap->pss[i].playerNum && !cg.localPlayers[i].renderingThirdPerson) { if(cg_drawGun[i].integer == 2) VectorMA(es->origin2, 8, cg.refdef.viewaxis[1], es->origin2); else if(cg_drawGun[i].integer == 3) VectorMA(es->origin2, 4, cg.refdef.viewaxis[1], es->origin2); break; } } } CG_RailTrail(pi, es->origin2, es->pos.trBase); // if the end was on a nomark surface, don't make an explosion if ( es->eventParm != 255 ) { ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, es->playerNum, position, dir, IMPACTSOUND_DEFAULT ); } break; case EV_BULLET_HIT_WALL: DEBUGNAME("EV_BULLET_HIT_WALL"); ByteToDir( es->eventParm, dir ); CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD ); break; case EV_BULLET_HIT_FLESH: DEBUGNAME("EV_BULLET_HIT_FLESH"); CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm ); break; case EV_SHOTGUN: DEBUGNAME("EV_SHOTGUN"); CG_ShotgunFire( es ); break; case EV_GENERAL_SOUND: DEBUGNAME("EV_GENERAL_SOUND"); if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartSound (NULL, es->number, CHAN_VOICE, cgs.gameSounds[ es->eventParm ] ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, s ) ); } break; case EV_GLOBAL_SOUND: // play as a local sound so it never diminishes DEBUGNAME("EV_GLOBAL_SOUND"); if ( cgs.gameSounds[ es->eventParm ] ) { trap_S_StartLocalSound( cgs.gameSounds[ es->eventParm ], CHAN_AUTO ); } else { s = CG_ConfigString( CS_SOUNDS + es->eventParm ); trap_S_StartLocalSound( CG_CustomSound( es->number, s ), CHAN_AUTO ); } break; case EV_GLOBAL_TEAM_SOUND: // play as a local sound so it never diminishes DEBUGNAME("EV_GLOBAL_TEAM_SOUND"); { qboolean blueTeam = qfalse; qboolean redTeam = qfalse; qboolean localHasBlue = qfalse; qboolean localHasRed = qfalse; qboolean localHasNeutral = qfalse; // Check if any local player is on blue/red team or has flags. for (i = 0; i < CG_MaxSplitView(); i++) { if (cg.snap->playerNums[i] == -1) { continue; } if (cg.snap->pss[i].persistant[PERS_TEAM] == TEAM_BLUE) { blueTeam = qtrue; } if (cg.snap->pss[i].persistant[PERS_TEAM] == TEAM_RED) { redTeam = qtrue; } if (cg.snap->pss[i].powerups[PW_BLUEFLAG]) { localHasBlue = qtrue; } if (cg.snap->pss[i].powerups[PW_REDFLAG]) { localHasRed = qtrue; } if (cg.snap->pss[i].powerups[PW_NEUTRALFLAG]) { localHasNeutral = qtrue; } } // ZTM: NOTE: Some of these sounds don't really work with local player on different teams. // New games might want to replace you/enemy sounds with red/blue. // See http://github.com/zturtleman/spearmint/wiki/New-Sounds switch( es->eventParm ) { case GTS_RED_CAPTURE: // CTF: red team captured the blue flag, 1FCTF: red team captured the neutral flag if ( redTeam ) CG_AddBufferedSound( cgs.media.captureYourTeamSound ); else CG_AddBufferedSound( cgs.media.captureOpponentSound ); break; case GTS_BLUE_CAPTURE: // CTF: blue team captured the red flag, 1FCTF: blue team captured the neutral flag if ( blueTeam ) CG_AddBufferedSound( cgs.media.captureYourTeamSound ); else CG_AddBufferedSound( cgs.media.captureOpponentSound ); break; case GTS_RED_RETURN: // CTF: blue flag returned, 1FCTF: never used if ( redTeam ) CG_AddBufferedSound( cgs.media.returnYourTeamSound ); else CG_AddBufferedSound( cgs.media.returnOpponentSound ); // CG_AddBufferedSound( cgs.media.blueFlagReturnedSound ); break; case GTS_BLUE_RETURN: // CTF red flag returned, 1FCTF: neutral flag returned if ( blueTeam ) CG_AddBufferedSound( cgs.media.returnYourTeamSound ); else CG_AddBufferedSound( cgs.media.returnOpponentSound ); // CG_AddBufferedSound( cgs.media.redFlagReturnedSound ); break; case GTS_RED_TAKEN: // CTF: red team took blue flag, 1FCTF: blue team took the neutral flag // if this player picked up the flag then a sound is played in CG_CheckLocalSounds if (localHasBlue || localHasNeutral) { } else if (!(redTeam && blueTeam)) { if (blueTeam) { #ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.yourTeamTookTheFlagSound ); else #endif CG_AddBufferedSound( cgs.media.enemyTookYourFlagSound ); } else if (redTeam) { #ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.enemyTookTheFlagSound ); else #endif CG_AddBufferedSound( cgs.media.yourTeamTookEnemyFlagSound ); } } else { // ZTM: NOTE: There are local players on both teams, so have no correct sound to play. New games should fix this. } break; case GTS_BLUE_TAKEN: // CTF: blue team took the red flag, 1FCTF red team took the neutral flag // if this player picked up the flag then a sound is played in CG_CheckLocalSounds if (localHasRed || localHasNeutral) { } else if (!(redTeam && blueTeam)) { if (redTeam) { #ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.yourTeamTookTheFlagSound ); else #endif CG_AddBufferedSound( cgs.media.enemyTookYourFlagSound ); } else if (blueTeam) { #ifdef MISSIONPACK if (cgs.gametype == GT_1FCTF) CG_AddBufferedSound( cgs.media.enemyTookTheFlagSound ); else #endif CG_AddBufferedSound( cgs.media.yourTeamTookEnemyFlagSound ); } } else { // ZTM: NOTE: There are local players on both teams, so have no correct sound to play. New games should fix this. } break; #ifdef MISSIONPACK // ZTM: NOTE: These are confusing when there are players on both teams (players don't know which base is attacked). New games should fix this. case GTS_REDOBELISK_ATTACKED: // Overload: red obelisk is being attacked if (redTeam) { CG_AddBufferedSound( cgs.media.yourBaseIsUnderAttackSound ); } break; case GTS_BLUEOBELISK_ATTACKED: // Overload: blue obelisk is being attacked if (blueTeam) { CG_AddBufferedSound( cgs.media.yourBaseIsUnderAttackSound ); } break; #endif case GTS_REDTEAM_SCORED: CG_AddBufferedSound(cgs.media.redScoredSound); break; case GTS_BLUETEAM_SCORED: CG_AddBufferedSound(cgs.media.blueScoredSound); break; case GTS_REDTEAM_TOOK_LEAD: if ( cgs.gametype != GT_TEAM || cg_teamDmLeadAnnouncements.integer ) { CG_AddBufferedSound(cgs.media.redLeadsSound); } break; case GTS_BLUETEAM_TOOK_LEAD: if ( cgs.gametype != GT_TEAM || cg_teamDmLeadAnnouncements.integer ) { CG_AddBufferedSound(cgs.media.blueLeadsSound); } break; case GTS_TEAMS_ARE_TIED: if ( cgs.gametype != GT_TEAM || cg_teamDmLeadAnnouncements.integer ) { CG_AddBufferedSound( cgs.media.teamsTiedSound ); } break; #ifdef MISSIONPACK case GTS_KAMIKAZE: trap_S_StartLocalSound(cgs.media.kamikazeFarSound, CHAN_ANNOUNCER); break; #endif default: break; } break; } case EV_PAIN: // local player sounds are triggered in CG_CheckLocalSounds, // so ignore events on the player DEBUGNAME("EV_PAIN"); if ( !CG_LocalPlayerState( es->number ) ) { CG_PainEvent( cent, es->eventParm ); } break; case EV_DEATH1: case EV_DEATH2: case EV_DEATH3: DEBUGNAME2("EV_DEATH%d", event - EV_DEATH1 + 1); // check if gibbed // eventParm 1 = living player gibbed // eventParm 2 = corpse gibbed // eventParm 3 = living person gib headshot if ( es->eventParm >= 1 ) { CG_GibPlayer( cent->lerpOrigin, (es->eventParm == 3) ? qtrue : qfalse ); if ( cg_blood.integer && cg_gibs.integer ) { // don't play gib sound when using the kamikaze because it interferes // with the kamikaze sound, downside is that the gib sound will also // not be played when someone is gibbed while just carrying the kamikaze if ( !(es->eFlags & EF_KAMIKAZE) ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.gibSound ); } // don't play death sound break; } // don't play death sound if already dead if ( es->eventParm == 2 ) { break; } } if (CG_WaterLevel(cent) >= 1) { trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, "*drown.wav")); } else { trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, va("*death%i.wav", event - EV_DEATH1 + 1))); } break; case EV_OBITUARY: DEBUGNAME("EV_OBITUARY"); CG_ParseObituary( es ); break; // // powerup events // case EV_POWERUP_QUAD: DEBUGNAME("EV_POWERUP_QUAD"); for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->number == cg.snap->pss[i].playerNum ) { cg.localPlayers[i].powerupActive = PW_QUAD; cg.localPlayers[i].powerupTime = cg.time; } } trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.quadSound ); break; case EV_POWERUP_BATTLESUIT: DEBUGNAME("EV_POWERUP_BATTLESUIT"); for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->number == cg.snap->pss[i].playerNum ) { cg.localPlayers[i].powerupActive = PW_BATTLESUIT; cg.localPlayers[i].powerupTime = cg.time; } } trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.protectSound ); break; case EV_POWERUP_REGEN: DEBUGNAME("EV_POWERUP_REGEN"); for (i = 0; i < CG_MaxSplitView(); i++) { if ( es->number == cg.snap->pss[i].playerNum ) { cg.localPlayers[i].powerupActive = PW_REGEN; cg.localPlayers[i].powerupTime = cg.time; } } trap_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.regenSound ); break; case EV_STOPLOOPINGSOUND: DEBUGNAME("EV_STOPLOOPINGSOUND"); trap_S_StopLoopingSound( es->number ); es->loopSound = 0; break; case EV_DEBUG_LINE: DEBUGNAME("EV_DEBUG_LINE"); CG_Beam( cent ); break; default: DEBUGNAME("UNKNOWN"); CG_Error( "Unknown event: %i", event ); break; } }
void CG_EntityEvent(centity_t *cent, vec3_t position) { entityState_t *es; int event; vec3_t dir; const char *s; int clientNum; clientInfo_t *ci; es = ¢->currentState; event = es->event & ~EV_EVENT_BITS; if (cg_debugEvents.integer) { CG_Printf("ent:%3i event:%3i ", es->number, event); } if (!event) { DEBUGNAME("ZEROEVENT"); return; } clientNum = es->clientNum; if (clientNum < 0 || clientNum >= MAX_CLIENTS) { clientNum = 0; } ci = &cgs.clientinfo[ clientNum ]; switch (event) { // // movement generated events // case EV_BANDAGE: DEBUGNAME("EV_BANDAGE"); if (clientNum == cg.predictedPlayerState.clientNum) { CG_ZoomReset_f(); } trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.bandageSound); break; case EV_FOOTSTEP: DEBUGNAME("EV_FOOTSTEP"); if (cg_footsteps.integer) { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.footsteps[ ci->footsteps ][rand()&3]); } break; case EV_FOOTSTEP_METAL: DEBUGNAME("EV_FOOTSTEP_METAL"); if (cg_footsteps.integer) { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_METAL ][rand()&3]); } break; case EV_FOOTSPLASH: DEBUGNAME("EV_FOOTSPLASH"); if (cg_footsteps.integer) { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3]); } break; case EV_FOOTWADE: DEBUGNAME("EV_FOOTWADE"); if (cg_footsteps.integer) { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3]); } break; case EV_SWIM: DEBUGNAME("EV_SWIM"); if (cg_footsteps.integer) { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3]); } break; case EV_FOOTSTEP_LADDER: //Xamis DEBUGNAME("EV_FOOTSTEP_LADDER"); { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.ladderSound[rand()&3]); } break; case EV_LEDGEGRAB: //Xamis DEBUGNAME("EV_LEDGEGRAB"); { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.ledgeSound); } break; case EV_FALL_SHORT: DEBUGNAME("EV_FALL_SHORT"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.landSound); if (clientNum == cg.predictedPlayerState.clientNum) { // smooth landing z changes cg.landChange = -8; cg.landTime = cg.time; } break; case EV_FALL_MEDIUM: DEBUGNAME("EV_FALL_MEDIUM"); // use normal pain sound trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, "*pain100_1.wav")); if (clientNum == cg.predictedPlayerState.clientNum) { // smooth landing z changes cg.landChange = -16; cg.landTime = cg.time; } break; case EV_FALL_FAR: DEBUGNAME("EV_FALL_FAR"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, CG_CustomSound(es->number, "*fall1.wav")); cent->pe.painTime = cg.time; // don't play a pain sound right after this if (clientNum == cg.predictedPlayerState.clientNum) { // smooth landing z changes cg.landChange = -32; cg.landTime = cg.time; } break; case EV_CURBSTOMP: DEBUGNAME("EV_CURBSTOMP"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.stompSound); break; case EV_STEP_4: case EV_STEP_8: case EV_STEP_12: case EV_STEP_16: // smooth out step up transitions DEBUGNAME("EV_STEP"); { float oldStep; int delta; int step; if (clientNum != cg.predictedPlayerState.clientNum) { break; } // if we are interpolating, we don't need to smooth steps if (cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW) || cg_nopredict.integer || cg_synchronousClients.integer) { break; } // check for stepping up before a previous step is completed delta = cg.time - cg.stepTime; if (delta < STEP_TIME) { oldStep = cg.stepChange * (STEP_TIME - delta) / STEP_TIME; } else { oldStep = 0; } // add this amount step = 4 * (event - EV_STEP_4 + 1); cg.stepChange = oldStep + step; if (cg.stepChange > MAX_STEP_CHANGE) { cg.stepChange = MAX_STEP_CHANGE; } cg.stepTime = cg.time; break; } case EV_JUMP_PAD: DEBUGNAME("EV_JUMP_PAD"); // CG_Printf( "EV_JUMP_PAD w/effect #%i\n", es->eventParm ); { localEntity_t *smoke; vec3_t up = {0, 0, 1}; smoke = CG_SmokePuff(cent->lerpOrigin, up, 32, 1, 1, 1, 0.33f, 1000, cg.time, 0, LEF_PUFF_DONT_SCALE, cgs.media.smokePuffShader); } // boing sound at origin, jump sound on player trap_S_StartSound(cent->lerpOrigin, -1, CHAN_VOICE, cgs.media.jumpPadSound); trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, "*jump1.wav")); break; case EV_JUMP: DEBUGNAME("EV_JUMP"); //trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); //Xamis { vec3_t surfNormal, refNormal = {0.0f, 0.0f, 1.0f}; vec3_t rotAxis; if (clientNum != cg.predictedPlayerState.clientNum) break; //set surfNormal VectorCopy(cg.predictedPlayerState.grapplePoint, surfNormal); //if we are moving from one surface to another smooth the transition if (!VectorCompare(surfNormal, cg.lastNormal) && surfNormal[ 2 ] != 1.0f) { CrossProduct(refNormal, surfNormal, rotAxis); VectorNormalize(rotAxis); //add the op CG_addSmoothOp(rotAxis, 15.0f, 1.0f); } //copy the current normal to the lastNormal VectorCopy(surfNormal, cg.lastNormal); } break; case EV_BLEED: DEBUGNAME("EV_BLEED"); CG_CreateBleeder(es->pos.trBase, 10, cent->currentState.clientNum); // CG_PlayerBleed(cent->currentState.clientNum, 10, es->pos.trBase, dir ); break; case EV_WALLJUMP: DEBUGNAME("EV_WALLJUMP") break; case EV_TAUNT: DEBUGNAME("EV_TAUNT"); trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, "*taunt.wav")); break; #ifdef MISSIONPACK case EV_TAUNT_YES: DEBUGNAME("EV_TAUNT_YES"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_YES); break; case EV_TAUNT_NO: DEBUGNAME("EV_TAUNT_NO"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_NO); break; case EV_TAUNT_FOLLOWME: DEBUGNAME("EV_TAUNT_FOLLOWME"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_FOLLOWME); break; case EV_TAUNT_GETFLAG: DEBUGNAME("EV_TAUNT_GETFLAG"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONGETFLAG); break; case EV_TAUNT_GUARDBASE: DEBUGNAME("EV_TAUNT_GUARDBASE"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONDEFENSE); break; case EV_TAUNT_PATROL: DEBUGNAME("EV_TAUNT_PATROL"); CG_VoiceChatLocal(SAY_TEAM, qfalse, es->number, COLOR_CYAN, VOICECHAT_ONPATROL); break; #endif case EV_WATER_TOUCH: DEBUGNAME("EV_WATER_TOUCH"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.watrInSound); break; case EV_WATER_LEAVE: DEBUGNAME("EV_WATER_LEAVE"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound); break; case EV_WATER_UNDER: DEBUGNAME("EV_WATER_UNDER"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound); break; case EV_WATER_CLEAR: DEBUGNAME("EV_WATER_CLEAR"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, CG_CustomSound(es->number, "*gasp.wav")); break; case EV_ITEM_PICKUP: DEBUGNAME("EV_ITEM_PICKUP"); { gitem_t *item; int index; index = es->eventParm; // player predicted if (index < 1 || index >= bg_numItems) { break; } item = &bg_itemlist[ index ]; // trap_S_StartSound (NULL, es->number, CHAN_AUTO, trap_S_RegisterSound( item->pickup_sound, qfalse ) ); //Disable sounds for powerup -- Xamis // powerups and team items will have a separate global sound, this one // will be played at prediction time if (item->giType == IT_POWERUP || item->giType == IT_TEAM) { //trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.n_healthSound ); } else { trap_S_StartSound(NULL, es->number, CHAN_AUTO, trap_S_RegisterSound(item->pickup_sound, qfalse)); } // show icon and name on status bar if (es->number == cg.snap->ps.clientNum) { CG_ItemPickup(index); } } break; case EV_GLOBAL_ITEM_PICKUP: DEBUGNAME("EV_GLOBAL_ITEM_PICKUP"); { gitem_t *item; int index; index = es->eventParm; // player predicted if (index < 1 || index >= bg_numItems) { break; } item = &bg_itemlist[ index ]; // powerup pickups are global if (item->pickup_sound) { trap_S_StartSound(NULL, cg.snap->ps.clientNum, CHAN_AUTO, trap_S_RegisterSound(item->pickup_sound, qfalse)); } // show icon and name on status bar if (es->number == cg.snap->ps.clientNum) { CG_ItemPickup(index); } } break; // // weapon events // case EV_NOAMMO: DEBUGNAME("EV_NOAMMO"); // trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.noAmmoSound ); if (es->number == cg.snap->ps.clientNum) { trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.noammoSound); } break; case EV_NONADES: DEBUGNAME("EV_NONADES"); if (clientNum == cg.predictedPlayerState.clientNum) { CG_WeaponSort(); } break; case EV_POWERSLIDE: CG_HasteTrail(cent); break; case EV_CHANGE_WEAPON: DEBUGNAME("EV_CHANGE_WEAPON"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.selectSound); break; case EV_WEAPON_DROPPED: DEBUGNAME("EV_WEAPON_DROPPED"); if (clientNum == cg.predictedPlayerState.clientNum) { //CG_Printf("EV_WEAPON_DROPPED\n"); CG_WeaponSort(); } break; case EV_FIRE_WEAPON: DEBUGNAME("EV_FIRE_WEAPON"); CG_FireWeapon(cent); break; case EV_ZOOM_RESET: if (clientNum == cg.predictedPlayerState.clientNum) { CG_ZoomReset_f(); } break; case EV_EJECT_CASING: { entityState_t *ent; weaponInfo_t *weap; ent = ¢->currentState; weap = &cg_weapons[ ent->weapon ]; weap->ejectBrassFunc(cent); break; } case EV_USE_ITEM0: DEBUGNAME("EV_USE_ITEM0"); CG_UseItem(cent); break; case EV_USE_ITEM1: DEBUGNAME("EV_USE_ITEM1"); CG_UseItem(cent); break; case EV_USE_ITEM2: DEBUGNAME("EV_USE_ITEM2"); CG_UseItem(cent); break; case EV_USE_ITEM3: DEBUGNAME("EV_USE_ITEM3"); CG_UseItem(cent); break; case EV_USE_ITEM4: DEBUGNAME("EV_USE_ITEM4"); CG_UseItem(cent); break; case EV_USE_ITEM5: DEBUGNAME("EV_USE_ITEM5"); CG_UseItem(cent); break; case EV_USE_ITEM6: DEBUGNAME("EV_USE_ITEM6"); CG_UseItem(cent); break; case EV_USE_ITEM7: DEBUGNAME("EV_USE_ITEM7"); CG_UseItem(cent); break; case EV_USE_ITEM8: DEBUGNAME("EV_USE_ITEM8"); CG_UseItem(cent); break; case EV_USE_ITEM9: DEBUGNAME("EV_USE_ITEM9"); CG_UseItem(cent); break; case EV_USE_ITEM10: DEBUGNAME("EV_USE_ITEM10"); CG_UseItem(cent); break; case EV_USE_ITEM11: DEBUGNAME("EV_USE_ITEM11"); CG_UseItem(cent); break; case EV_USE_ITEM12: DEBUGNAME("EV_USE_ITEM12"); CG_UseItem(cent); break; case EV_USE_ITEM13: DEBUGNAME("EV_USE_ITEM13"); CG_UseItem(cent); break; case EV_USE_ITEM14: DEBUGNAME("EV_USE_ITEM14"); CG_UseItem(cent); break; //================================================================= // // other events // case EV_PLAYER_TELEPORT_IN: DEBUGNAME("EV_PLAYER_TELEPORT_IN"); //trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleInSound ); //disable sound --Xamis CG_SpawnEffect(position); break; case EV_PLAYER_TELEPORT_OUT: DEBUGNAME("EV_PLAYER_TELEPORT_OUT"); //trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.teleOutSound );//disable sound --Xamis CG_SpawnEffect(position); break; case EV_ITEM_POP: DEBUGNAME("EV_ITEM_POP"); //trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound ); break; case EV_ITEM_RESPAWN: DEBUGNAME("EV_ITEM_RESPAWN"); cent->miscTime = cg.time; // scale up from this //trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.respawnSound ); break; case EV_GRENADE_BOUNCE: DEBUGNAME("EV_GRENADE_BOUNCE"); if (rand() & 1) { trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.hgrenb1aSound); } else { trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.hgrenb2aSound); } break; #ifdef MISSIONPACK case EV_PROXIMITY_MINE_STICK: DEBUGNAME("EV_PROXIMITY_MINE_STICK"); if (es->eventParm & SURF_FLESH) { trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.wstbimplSound); } else if (es->eventParm & SURF_METALSTEPS) { trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.wstbimpmSound); } else { trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.wstbimpdSound); } break; case EV_PROXIMITY_MINE_TRIGGER: DEBUGNAME("EV_PROXIMITY_MINE_TRIGGER"); trap_S_StartSound(NULL, es->number, CHAN_AUTO, cgs.media.wstbactvSound); break; case EV_KAMIKAZE: DEBUGNAME("EV_KAMIKAZE"); CG_KamikazeEffect(cent->lerpOrigin); break; case EV_OBELISKEXPLODE: DEBUGNAME("EV_OBELISKEXPLODE"); CG_ObeliskExplode(cent->lerpOrigin, es->eventParm); break; case EV_OBELISKPAIN: DEBUGNAME("EV_OBELISKPAIN"); CG_ObeliskPain(cent->lerpOrigin); break; case EV_INVUL_IMPACT: DEBUGNAME("EV_INVUL_IMPACT"); CG_InvulnerabilityImpact(cent->lerpOrigin, cent->currentState.angles); break; case EV_JUICED: DEBUGNAME("EV_JUICED"); CG_InvulnerabilityJuiced(cent->lerpOrigin); break; case EV_LIGHTNINGBOLT: DEBUGNAME("EV_LIGHTNINGBOLT"); CG_LightningBoltBeam(es->origin2, es->pos.trBase); break; #endif case EV_SCOREPLUM: DEBUGNAME("EV_SCOREPLUM"); CG_ScorePlum(cent->currentState.otherEntityNum, cent->lerpOrigin, cent->currentState.time); break; // // missile impacts // case EV_MISSILE_HIT: DEBUGNAME("EV_MISSILE_HIT"); ByteToDir(es->eventParm, dir); CG_MissileHitPlayer(es->weapon, position, dir, es->otherEntityNum); break; case EV_MISSILE_MISS: DEBUGNAME("EV_MISSILE_MISS"); ByteToDir(es->eventParm, dir); CG_MissileHitWall(es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT); break; case EV_MISSILE_MISS_METAL: DEBUGNAME("EV_MISSILE_MISS_METAL"); ByteToDir(es->eventParm, dir); CG_MissileHitWall(es->weapon, 0, position, dir, IMPACTSOUND_METAL); break; case EV_BULLET_HIT_WALL: DEBUGNAME("EV_BULLET_HIT_WALL"); ByteToDir(es->eventParm, dir); CG_Bullet(es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD); break; case EV_BULLET_HIT_FLESH: DEBUGNAME("EV_BULLET_HIT_FLESH"); CG_Bullet(es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm); break; case EV_SHOTGUN: DEBUGNAME("EV_SHOTGUN"); CG_ShotgunFire(es); break; case EV_GAMESTATE: trap_Cvar_Set("ui_gamestate", va("%i", es->eventParm)); break; case EV_GENERAL_SOUND: DEBUGNAME("EV_GENERAL_SOUND"); if (cgs.gameSounds[ es->eventParm ]) { trap_S_StartSound(NULL, es->number, CHAN_VOICE, cgs.gameSounds[ es->eventParm ]); } else { s = CG_ConfigString(CS_SOUNDS + es->eventParm); trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, s)); } break; case EV_GLOBAL_SOUND: // play from the player's head so it never diminishes DEBUGNAME("EV_GLOBAL_SOUND"); if (cgs.gameSounds[ es->eventParm ]) { trap_S_StartSound(NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.gameSounds[ es->eventParm ]); } else { s = CG_ConfigString(CS_SOUNDS + es->eventParm); trap_S_StartSound(NULL, cg.snap->ps.clientNum, CHAN_AUTO, CG_CustomSound(es->number, s)); } break; case EV_GLOBAL_TEAM_SOUND: // play from the player's head so it never diminishes { DEBUGNAME("EV_GLOBAL_TEAM_SOUND"); switch (es->eventParm) { case GTS_DRAW_ROUND: CG_AddBufferedSound(cgs.media.roundDrawSound); break; case GTS_RED_CAPTURE: // CTF: red team captured the blue flag, 1FCTF: red team captured the neutral flag if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) CG_AddBufferedSound(cgs.media.captureYourTeamSound); else CG_AddBufferedSound(cgs.media.captureOpponentSound); break; case GTS_BLUE_CAPTURE: // CTF: blue team captured the red flag, 1FCTF: blue team captured the neutral flag if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) CG_AddBufferedSound(cgs.media.captureYourTeamSound); else CG_AddBufferedSound(cgs.media.captureOpponentSound); break; case GTS_RED_RETURN: // CTF: blue flag returned, 1FCTF: never used if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) CG_AddBufferedSound(cgs.media.returnYourTeamSound); else CG_AddBufferedSound(cgs.media.returnOpponentSound); // CG_AddBufferedSound(cgs.media.blueFlagReturnedSound); break; case GTS_BLUE_RETURN: // CTF red flag returned, 1FCTF: neutral flag returned if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) CG_AddBufferedSound(cgs.media.returnYourTeamSound); else CG_AddBufferedSound(cgs.media.returnOpponentSound); // CG_AddBufferedSound(cgs.media.redFlagReturnedSound); break; case GTS_RED_TAKEN: // CTF: red team took blue flag, 1FCTF: blue team took the neutral flag // if this player picked up the flag then a sound is played in CG_CheckLocalSounds if (cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_NEUTRALFLAG]) { } else { if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) { #ifdef MISSIONPACK if (cgs.gametype == GT_BOMB) CG_AddBufferedSound(cgs.media.yourTeamTookTheFlagSound); else #endif CG_AddBufferedSound(cgs.media.enemyTookYourFlagSound); } else if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) { #ifdef MISSIONPACK if (cgs.gametype == GT_BOMB) CG_AddBufferedSound(cgs.media.enemyTookTheFlagSound); else #endif CG_AddBufferedSound(cgs.media.yourTeamTookEnemyFlagSound); } } break; case GTS_BLUE_TAKEN: // CTF: blue team took the red flag, 1FCTF red team took the neutral flag // if this player picked up the flag then a sound is played in CG_CheckLocalSounds if (cg.snap->ps.powerups[PW_REDFLAG] || cg.snap->ps.powerups[PW_NEUTRALFLAG]) { } else { if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) { #ifdef MISSIONPACK if (cgs.gametype == GT_BOMB) CG_AddBufferedSound(cgs.media.yourTeamTookTheFlagSound); else #endif CG_AddBufferedSound(cgs.media.enemyTookYourFlagSound); } else if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) { #ifdef MISSIONPACK if (cgs.gametype == GT_BOMB) CG_AddBufferedSound(cgs.media.enemyTookTheFlagSound); else #endif CG_AddBufferedSound(cgs.media.yourTeamTookEnemyFlagSound); } } break; case GTS_REDOBELISK_ATTACKED: // Overload: red obelisk is being attacked if (cgs.clientinfo[cg.clientNum].team == TEAM_RED) { CG_AddBufferedSound(cgs.media.yourBaseIsUnderAttackSound); } break; case GTS_BLUEOBELISK_ATTACKED: // Overload: blue obelisk is being attacked if (cgs.clientinfo[cg.clientNum].team == TEAM_BLUE) { CG_AddBufferedSound(cgs.media.yourBaseIsUnderAttackSound); } break; case GTS_REDTEAM_SCORED: CG_AddBufferedSound(cgs.media.redScoredSound); break; case GTS_BLUETEAM_SCORED: CG_AddBufferedSound(cgs.media.blueScoredSound); break; case GTS_REDTEAM_TOOK_LEAD: CG_AddBufferedSound(cgs.media.redLeadsSound); break; case GTS_BLUETEAM_TOOK_LEAD: CG_AddBufferedSound(cgs.media.blueLeadsSound); break; case GTS_TEAMS_ARE_TIED: CG_AddBufferedSound(cgs.media.teamsTiedSound); break; #ifdef MISSIONPACK case GTS_KAMIKAZE: trap_S_StartLocalSound(cgs.media.kamikazeFarSound, CHAN_ANNOUNCER); break; #endif default: break; } break; } case EV_PAIN: // local player sounds are triggered in CG_CheckLocalSounds, // so ignore events on the player DEBUGNAME("EV_PAIN"); if (cent->currentState.number != cg.snap->ps.clientNum) { CG_PainEvent(cent, es->eventParm); } break; case EV_DEATH1: case EV_DEATH2: case EV_DEATH3: DEBUGNAME("EV_DEATHx"); if (clientNum == cg.predictedPlayerState.clientNum) { CG_ZoomReset_f(); } trap_S_StartSound(NULL, es->number, CHAN_VOICE, CG_CustomSound(es->number, va("*death%i.wav", event - EV_DEATH1 + 1))); break; case EV_OBITUARY: DEBUGNAME("EV_OBITUARY"); CG_Obituary(es); break; // // powerup events // case EV_GIB_PLAYER: DEBUGNAME("EV_GIB_PLAYER"); // don't play gib sound when using the kamikaze because it interferes // with the kamikaze sound, downside is that the gib sound will also // not be played when someone is gibbed while just carrying the kamikaze if (!(es->eFlags & EF_KAMIKAZE)) { trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.gibSound); } CG_GibPlayer(cent->lerpOrigin); break; //Xamis case EV_BREAK_GLASS: DEBUGNAME("EV_BREAK_GLASS"); trap_S_StartSound(NULL, es->number, CHAN_BODY, cgs.media.glassSound); CG_BreakGlass(cent->lerpOrigin); break; case EV_STOPLOOPINGSOUND: DEBUGNAME("EV_STOPLOOPINGSOUND"); trap_S_StopLoopingSound(es->number); es->loopSound = 0; break; case EV_DEBUG_LINE: DEBUGNAME("EV_DEBUG_LINE"); CG_Beam(cent); break; default: DEBUGNAME("UNKNOWN"); CG_Error("Unknown event: %i", event); break; } }