Exemplo n.º 1
0
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 = &cent->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 );
		{
			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(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;

#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->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);
		}

		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 );
		}
		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 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 ( cg.snap->ps.persistant[PERS_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 ( cg.snap->ps.persistant[PERS_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 ( cg.snap->ps.persistant[PERS_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 ( cg.snap->ps.persistant[PERS_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 (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE) {
#ifdef MISSIONPACK
							if (cgs.gametype == GT_1FCTF) 
								CG_AddBufferedSound( cgs.media.yourTeamTookTheFlagSound );
							else
#endif
							CG_AddBufferedSound( cgs.media.enemyTookYourFlagSound );
						}
						else if (cg.snap->ps.persistant[PERS_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 (cg.snap->ps.persistant[PERS_TEAM] == TEAM_RED) {
#ifdef MISSIONPACK
							if (cgs.gametype == GT_1FCTF)
								CG_AddBufferedSound( cgs.media.yourTeamTookTheFlagSound );
							else
#endif
							CG_AddBufferedSound( cgs.media.enemyTookYourFlagSound );
						}
						else if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE) {
#ifdef MISSIONPACK
							if (cgs.gametype == GT_1FCTF)
								CG_AddBufferedSound( cgs.media.enemyTookTheFlagSound );
							else
#endif
							CG_AddBufferedSound( cgs.media.yourTeamTookEnemyFlagSound );
						}
					}
					break;
#ifdef MISSIONPACK
				case GTS_REDOBELISK_ATTACKED: // Overload: red obelisk is being attacked
					if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_RED) {
						CG_AddBufferedSound( cgs.media.yourBaseIsUnderAttackSound );
					}
					break;
				case GTS_BLUEOBELISK_ATTACKED: // Overload: blue obelisk is being attacked
					if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE) {
						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:
					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 (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;
	}

}
Exemplo n.º 2
0
/*
================
CG_AddMissile
================
*/
static void CG_AddMissile( localEntity_t *le ) {
	refEntity_t			*re;
	const weaponInfo_t	*weapon;
	trace_t				trace;
	centity_t			*other;
	qboolean			inWater;

	// just existing for server entity deletion
	if ( le->leFlags & LEF_FINISHED ) {
		return;
	}

	// get weapon info
	if ( le->ti.weapon > WP_NUM_WEAPONS ) {
		le->ti.weapon = 0;
	}
	weapon = &cg_weapons[le->ti.weapon];

	re = &le->refEntity;

	// calculate position
	BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );

	// special case for flames
	if ( re->reType == RT_SPRITE ) {
		int deltaTime;

		// check for water
		if ( trap_CM_PointContents( re->origin, 0 ) & CONTENTS_WATER ) {
			// do a trace to get water surface normals
			CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_WATER );
			CG_FreeLocalEntity( le );

			CG_MakeExplosion( trace.endpos, trace.plane.normal, 
				cgs.media.ringFlashModel, cgs.media.vaporShader,
				500, qfalse, qtrue );
			return;
		}

		// change radius over time
		deltaTime = cg.time - le->startTime;
		re->radius = deltaTime * deltaTime * ( random()*0.4f + 0.8f ) / 2000.0f + 9;

		// do a trace sometimes
		if ( le->ti.trailTime++ > 5 ) {
			le->ti.trailTime = 0;

			CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_SHOT );
			VectorCopy( re->origin, re->oldorigin );

			// hit something
			if ( trace.fraction < 1.0 ) {
				CG_MissileHitWall( le->ti.weapon, 0, trace.endpos, trace.plane.normal, IMPACTSOUND_DEFAULT );
				CG_FreeLocalEntity( le );
				return;
			}
		}

		// add to refresh list
		trap_R_AddRefEntityToScene( re );
		return;
	}

	// add trails
	if ( weapon->missileTrailFunc ) weapon->missileTrailFunc( &le->ti, cg.time );

	// add dynamic light
	if ( weapon->missileDlight ) {
		trap_R_AddLightToScene( re->origin, weapon->missileDlight, 
			weapon->missileDlightColor[0], weapon->missileDlightColor[1], weapon->missileDlightColor[2] );
	}

	// flicker between two skins
	re->skinNum = cg.clientFrame & 1;

	// convert direction of travel into axis
	if ( VectorNormalize2( le->pos.trDelta, re->axis[0] ) == 0 ) {
		re->axis[0][2] = 1;
	}

	// spin as it moves
	if ( le->pos.trType != TR_STATIONARY ) {
		if ( le->pos.trType == TR_GRAVITY ) {
			RotateAroundDirection( re->axis, cg.time / 4 );
		} else if ( le->pos.trType == TR_WATER_GRAVITY ) {
			RotateAroundDirection( re->axis, cg.time / 8 );
		} else {
			RotateAroundDirection( re->axis, cg.time );
		}
	} else {
		RotateAroundDirection( re->axis, 0 );
	}

	// trace a line from previous position to new position
	CG_Trace( &trace, re->oldorigin, NULL, NULL, re->origin, le->owner, MASK_SHOT );
	VectorCopy( re->origin, re->oldorigin );

	// draw BIG grenades
	if ( weLi[le->ti.weapon].category == CT_EXPLOSIVE ) {
		AxisScale( re->axis, GRENADE_SCALE, re->axis );
	}

	if ( trace.fraction != 1.0 ) {
		// hit the sky or something like that
		if ( trace.surfaceFlags & SURF_NOIMPACT ) {
			le->leFlags |= LEF_FINISHED;
			le->endTime = cg.time + 500;
			return;
		}

		// impact
		other = &cg_entities[trace.entityNum];

		if ( le->bounceFactor > 0 && ( le->bounceFactor == BOUNCE_FACTOR_HALF || other->currentState.eType != ET_PLAYER ) ) {
			// reflect the velocity on the trace plane
			CG_ReflectVelocity( le, &trace );
			if ( cg.predictedImpacts < MAX_PREDICTED_IMPACTS ) {
				cg.predictedImpacts++;
				cg.predictedImpactsDecTime = cg.time;
			}

			// do bounce sound
			if ( rand() & 1 ) {
				trap_S_StartSound( le->pos.trBase, 0, CHAN_AUTO, cgs.media.hgrenb1aSound );
			} else {
				trap_S_StartSound( le->pos.trBase, 0, CHAN_AUTO, cgs.media.hgrenb2aSound );
			}
		} else {
			// explode missile
			if ( cg.predictedImpacts < MAX_PREDICTED_IMPACTS ) {
				cg.predictedImpacts++;
				cg.predictedImpactsDecTime = cg.time;
			}

			if ( other->currentState.eType == ET_PLAYER ) {
				CG_MissileHitPlayer( le->ti.weapon, 0, trace.endpos, trace.plane.normal, trace.entityNum );
			} else if ( !(trace.surfaceFlags & SURF_NOIMPACT) ) {
				CG_MissileHitWall( le->ti.weapon, 0, trace.endpos, trace.plane.normal, 
					(trace.surfaceFlags & SURF_METALSTEPS) ? IMPACTSOUND_METAL : IMPACTSOUND_DEFAULT );
			}
			// store the entity for deleting the server entity
			le->leFlags |= LEF_FINISHED;
			le->endTime = cg.time + 500;
			return;
		}
	}

	// check for medium change
	if ( trap_CM_PointContents( re->origin, 0 ) & CONTENTS_WATER ) inWater = qtrue;
	else inWater = qfalse;

	if (  ( !inWater && le->pos.trType == TR_WATER_GRAVITY )
		|| ( inWater && le->pos.trType == TR_GRAVITY ) ) {
		// setup new tr
		vec3_t	newDelta;

		BG_EvaluateTrajectoryDelta( &le->pos, cg.time, newDelta );
		VectorCopy( re->origin, le->pos.trBase );
		VectorCopy( newDelta, le->pos.trDelta );
		le->pos.trTime = cg.time;
		if ( inWater ) le->pos.trType = TR_WATER_GRAVITY;
		else le->pos.trType = TR_GRAVITY;
	}	

	// add to refresh list
	trap_R_AddRefEntityToScene( re );
}
Exemplo n.º 3
0
void CG_EntityEvent( centity_t *cent, vec3_t position ) {
	entityState_t	*es;
	int				event;
	vec3_t			axis[3];
	const char		*s, *s2;
	int				clientNum;
	//clientInfo_t	*ci;

	es = &cent->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;
	}

	if ( !cent->gent )//|| !cent->gent->client )
	{
		return;
	}

	//ci = &cent->gent->client->clientInfo;
	clientNum = cent->gent->s.number;

	switch ( event ) {
	//
	// movement generated events
	//
/*	case EV_FOOTSTEP:
		DEBUGNAME("EV_FOOTSTEP");
		if (cg_footsteps.integer) {
			if ( cent->gent && cent->gent->s.number == 0 && !cg.renderingThirdPerson )//!cg_thirdPerson.integer )
			{//Everyone else has keyframed footsteps in animevents.cfg
#ifdef _IMMERSION
				int index = rand()&3;
				cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_NORMAL ][index] );
				cgi_FF_Start( cgs.media.footstepForces[ FOOTSTEP_NORMAL ][ index ], es->number );
#else
				cgi_S_StartSound (NULL, es->number, CHAN_BODY, 
					cgs.media.footsteps[ FOOTSTEP_NORMAL ][rand()&3] );
#endif // _IMMERSION
			}
		}
		break;
	case EV_FOOTSTEP_METAL:
		DEBUGNAME("EV_FOOTSTEP_METAL");
		if (cg_footsteps.integer) 
		{
			if ( cent->gent && cent->gent->s.number == 0 && !cg.renderingThirdPerson )
			{//Everyone else has keyframed footsteps in animevents.cfg
#ifdef _IMMERSION
				int index = rand()&3;
				cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_METAL ][index] );
				cgi_FF_Start( cgs.media.footstepForces[ FOOTSTEP_METAL ][ index ], es->number );
#else
				cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_METAL ][rand()&3] );
#endif // _IMMERSION
			}
		}
		break;
*/
	case EV_FOOTSPLASH:
		DEBUGNAME("EV_FOOTSPLASH");
		if (cg_footsteps.integer) {
#ifdef _IMMERSION
			int index = rand()&3;
			cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][index] );
			cgi_FF_Start( cgs.media.footstepForces[ FOOTSTEP_SPLASH ][ index ], es->number );
#else
			cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SPLASH ][rand()&3] );
#endif // _IMMERSION
		}
		break;
	case EV_FOOTWADE:
		DEBUGNAME("EV_FOOTWADE");
		if (cg_footsteps.integer) {
#ifdef _IMMERSION
			int index = rand()&3;
			cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_WADE ][index] );
			cgi_FF_Start( cgs.media.footstepForces[ FOOTSTEP_WADE ][ index ], es->number );
#else
			cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_WADE ][rand()&3] );
#endif // _IMMERSION
		}
		break;
	case EV_SWIM:
		DEBUGNAME("EV_SWIM");
		if (cg_footsteps.integer) {
#ifdef _IMMERSION
				int index = rand()&3;
				cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SWIM ][index] );
				cgi_FF_Start( cgs.media.footstepForces[ FOOTSTEP_SWIM ][ index ], es->number );
#else
			cgi_S_StartSound (NULL, es->number, CHAN_BODY, cgs.media.footsteps[ FOOTSTEP_SWIM ][rand()&3] );
#endif // _IMMERSION
		}
		break;


	case EV_FALL_SHORT:
		DEBUGNAME("EV_FALL_SHORT");
		cgi_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.landSound  );
#ifdef _IMMERSION
		cgi_FF_Start( cgs.media.landForce, es->number );
#endif // _IMMERSION
		if ( clientNum == cg.predicted_player_state.clientNum ) {
			// smooth landing z changes
			cg.landChange = -8;
			cg.landTime = cg.time;
		}
		//FIXME: maybe kick up some dust?
		break;
	case EV_FALL_MEDIUM:
		DEBUGNAME("EV_FALL_MEDIUM");
		// use normal pain sound - 
		if ( g_entities[es->number].health <= 0 ) 
		{//dead
			cgi_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.landSound  );
#ifdef _IMMERSION
			cgi_FF_Start( cgs.media.landForce, es->number );
#endif // _IMMERSION
		}
		else if ( g_entities[es->number].s.weapon == WP_SABER 
			|| (g_entities[es->number].client && (g_entities[es->number].client->ps.forcePowersKnown&(1<<FP_LEVITATION))) )
		{//jedi or someone who has force jump (so probably took no damage)
			CG_TryPlayCustomSound( NULL, es->number, CHAN_BODY, "*land1.wav", CS_BASIC );
		}
		else
		{//still alive
			CG_TryPlayCustomSound( NULL, es->number, CHAN_BODY, "*pain100.wav", CS_BASIC );
		}
		if ( clientNum == cg.predicted_player_state.clientNum ) {
			// smooth landing z changes
			cg.landChange = -16;
			cg.landTime = cg.time;
		}
#ifdef _XBOX
		cgi_FF_StartFX( fffx_FallingMedium );
#endif
		//FIXME: maybe kick up some dust?
		break;
	case EV_FALL_FAR:
		DEBUGNAME("EV_FALL_FAR");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_BODY, "*land1.wav", CS_BASIC );
		cgi_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.landSound  );
		cent->pe.painTime = cg.time;	// don't play a pain sound right after this
		if ( clientNum == cg.predicted_player_state.clientNum ) {
			// smooth landing z changes
			cg.landChange = -24;
			cg.landTime = cg.time;
		}
#ifdef _XBOX
		cgi_FF_StartFX( fffx_FallingFar );
#endif
		//FIXME: maybe kick up some dust?
		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.predicted_player_state.clientNum ) {
			break;
		}
		// if we are interpolating, we don't need to smooth steps
		if ( cg_timescale.value >= 1.0f )
		{
			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:
		DEBUGNAME("EV_JUMP");
		CG_TryPlayCustomSound(NULL, es->number, CHAN_AUTO, "*jump1.wav", CS_BASIC );//CHAN_VOICE
		break;

	case EV_ROLL:
		DEBUGNAME("EV_ROLL");
		CG_TryPlayCustomSound(NULL, es->number, CHAN_AUTO, "*jump1.wav", CS_BASIC );//CHAN_VOICE
		cgi_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.rollSound  );//CHAN_AUTO
		//FIXME: need some sort of body impact on ground sound and maybe kick up some dust?
		break;

	case EV_LAVA_TOUCH:
		DEBUGNAME("EV_LAVA_TOUCH");
		cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.lavaInSound );
#ifdef _IMMERSION
		cgi_FF_Start( cgs.media.watrInSound, es->number );
#endif // _IMMERSION
		break;
	
	case EV_LAVA_LEAVE:
		DEBUGNAME("EV_LAVA_LEAVE");
		cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.lavaOutSound );
#ifdef _IMMERSION
		cgi_FF_Start( cgs.media.watrOutSound, es->number );
#endif // _IMMERSION
		break;
	
	case EV_LAVA_UNDER:
		DEBUGNAME("EV_LAVA_UNDER");
		cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.lavaUnSound );
#ifdef _IMMERSION
		cgi_FF_Start( cgs.media.watrUnSound, es->number );
#endif // _IMMERSION
		break;
	
	case EV_WATER_TOUCH:
		DEBUGNAME("EV_WATER_TOUCH");
		cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrInSound );
#ifdef _IMMERSION
		cgi_FF_Start( cgs.media.watrInSound, es->number );
#endif // _IMMERSION
		break;
	
	case EV_WATER_LEAVE:
		DEBUGNAME("EV_WATER_LEAVE");
		cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound );
#ifdef _IMMERSION
		cgi_FF_Start( cgs.media.watrOutSound, es->number );
#endif // _IMMERSION
		break;
	
	case EV_WATER_UNDER:
		DEBUGNAME("EV_WATER_UNDER");
		cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound );
#ifdef _IMMERSION
		cgi_FF_Start( cgs.media.watrUnSound, es->number );
#endif // _IMMERSION
		break;
	
	case EV_WATER_CLEAR:
		DEBUGNAME("EV_WATER_CLEAR");
		CG_TryPlayCustomSound(NULL, es->number, CHAN_AUTO, "*gasp.wav", CS_BASIC );
		break;

	case EV_WATER_GURP1:
	case EV_WATER_GURP2:
		DEBUGNAME("EV_WATER_GURPx");
		CG_TryPlayCustomSound(NULL, es->number, CHAN_AUTO, va("*gurp%d.wav",event-EV_WATER_GURP1+1), CS_BASIC );
		break;

	case EV_WATER_DROWN:
		DEBUGNAME("EV_WATER_DROWN");
		CG_TryPlayCustomSound(NULL, es->number, CHAN_AUTO, "*drown.wav", CS_BASIC );
		break;

	case EV_ITEM_PICKUP:
		DEBUGNAME("EV_ITEM_PICKUP");
		{
			gitem_t	*item;
			int		index;
			qboolean bHadItem = qfalse;
					
			index = es->eventParm;		// player predicted

			if ( (char)index < 0 ) 
			{
				index = -(char)index;
				bHadItem = qtrue;
			}

			if ( index >= bg_numItems ) {
				break;
			}
			item = &bg_itemlist[ index ];
			cgi_S_StartSound (NULL, es->number, CHAN_AUTO,	cgi_S_RegisterSound( item->pickup_sound ) );
#ifdef _IMMERSION
			cgi_FF_Start( cgi_FF_Register( item->pickup_force, FF_CHANNEL_TOUCH ), es->number );
#endif // _IMMERSION

			// show icon and name on status bar
			if ( es->number == cg.snap->ps.clientNum ) {
				CG_ItemPickup( index, bHadItem );
			}
		}
		break;

	//
	// weapon events
	//
	case EV_NOAMMO:
		DEBUGNAME("EV_NOAMMO");
		//cgi_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");
		if ( es->weapon == WP_SABER )
		{
			/*
			if ( !cent->gent || !cent->gent->client || (cent->currentState.saberInFlight == qfalse && cent->currentState.saberActive == qtrue) )
			{
				cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgi_S_RegisterSound( "sound/weapons/saber/saberoffquick.wav" ) );
			}
			*/
			if ( cent->gent && cent->gent->client )
			{
				//if ( cent->gent->client->ps.saberInFlight )
				{//if it's not in flight or lying around, turn it off!
					cent->currentState.saberActive = qfalse;
				}
			}
		}

		// FIXME: if it happens that you don't want the saber to play the switch sounds, feel free to modify this bit.
		if ( weaponData[cg.weaponSelect].selectSnd[0] )
		{
			// custom select sound
			cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgi_S_RegisterSound( weaponData[cg.weaponSelect].selectSnd ));
#ifdef _IMMERSION
			cgi_FF_Start( cgi_FF_Register( weaponData[cg.weaponSelect].selectFrc, FF_CHANNEL_WEAPON ), es->number );
#endif // _IMMERSION
		}
		else
		{
			// generic sound
			cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.selectSound );
#ifdef _IMMERSION
			cgi_FF_Start( cgs.media.selectForce, es->number );
#endif // _IMMERSION
		}
		break;

	case EV_FIRE_WEAPON:
		DEBUGNAME("EV_FIRE_WEAPON");
		CG_FireWeapon( cent, qfalse );
		break;

	case EV_ALT_FIRE:
		DEBUGNAME("EV_ALT_FIRE");
		CG_FireWeapon( cent, qtrue );
		break;

	case EV_DISRUPTOR_MAIN_SHOT:
		DEBUGNAME("EV_DISRUPTOR_MAIN_SHOT");
		FX_DisruptorMainShot( cent->currentState.origin2, cent->lerpOrigin ); 
		break;

	case EV_DISRUPTOR_SNIPER_SHOT:
		DEBUGNAME("EV_DISRUPTOR_SNIPER_SHOT");
		FX_DisruptorAltShot( cent->currentState.origin2, cent->lerpOrigin, cent->gent->alt_fire );
		break;

	case EV_DISRUPTOR_SNIPER_MISS:
		DEBUGNAME("EV_DISRUPTOR_SNIPER_MISS");
		FX_DisruptorAltMiss( cent->lerpOrigin, cent->gent->pos1 );
		break;

	case EV_DEMP2_ALT_IMPACT:
		FX_DEMP2_AltDetonate( cent->lerpOrigin, es->eventParm );
		break;

	case EV_CONC_ALT_SHOT:
		DEBUGNAME("EV_CONC_ALT_SHOT");
		FX_ConcAltShot( cent->currentState.origin2, cent->lerpOrigin );
		break;

	case EV_CONC_ALT_MISS:
		DEBUGNAME("EV_CONC_ALT_MISS");
		FX_ConcAltMiss( cent->lerpOrigin, cent->gent->pos1 );
		break;

//	case EV_POWERUP_SEEKER_FIRE:
//		DEBUGNAME("EV_POWERUP_SEEKER_FIRE");
//		CG_FireSeeker( cent ); 
//		break;

	case EV_POWERUP_BATTLESUIT:
		DEBUGNAME("EV_POWERUP_BATTLESUIT");
		if ( es->number == cg.snap->ps.clientNum ) {
			cg.powerupActive = PW_BATTLESUIT;
			cg.powerupTime = cg.time;
		}
		//cgi_S_StartSound (NULL, es->number, CHAN_ITEM, cgs.media.invulnoProtectSound );
		break;

	case EV_KOTHOS_BEAM:
		DEBUGNAME("EV_KOTHOS_BEAM");
		if ( Q_irand( 0, 1 ) )
		{
			FX_KothosBeam( cg_entities[cent->currentState.otherEntityNum].gent->client->renderInfo.handRPoint, cg_entities[cent->currentState.otherEntityNum2].lerpOrigin ); 
		}
		else
		{
			FX_KothosBeam( cg_entities[cent->currentState.otherEntityNum].gent->client->renderInfo.handLPoint, cg_entities[cent->currentState.otherEntityNum2].lerpOrigin ); 
		}
		break;
	//=================================================================

	//
	// other events
	//
	case EV_REPLICATOR:
		DEBUGNAME("EV_REPLICATOR");
//		FX_Replicator( cent, position );
		break;

	case EV_BATTERIES_CHARGED:
		cg.batteryChargeTime = cg.time + 3000;
		cgi_S_StartSound( vec3_origin, es->number, CHAN_AUTO, cgs.media.batteryChargeSound );
		break;

	case EV_DISINTEGRATION:
		{
			DEBUGNAME("EV_DISINTEGRATION");
			qboolean makeNotSolid = qfalse;
			int disintPW = es->eventParm;
			int disintEffect = 0;
			int disintLength = 0;
			qhandle_t disintSound1 = NULL;
			qhandle_t disintSound2 = NULL;
			qhandle_t disintSound3 = NULL;

			switch( disintPW )
			{
			case PW_DISRUPTION:// sniper rifle
				disintEffect = EF_DISINTEGRATION;//ef_
				disintSound1 = cgs.media.disintegrateSound;//with scream
				disintSound2 = cgs.media.disintegrate2Sound;//no scream
				disintSound3 = cgs.media.disintegrate3Sound;//with inhuman scream
				disintLength = 2000;
				makeNotSolid = qtrue;
				break;
/*			case PW_SHOCKED:// arc welder
				disintEffect = EF_DISINT_1;//ef_
				disintSound1 = NULL;//with scream
				disintSound2 = NULL;//no scream
				disintSound3 = NULL;//with inhuman scream
				disintLength = 4000;
				break;
*/
			default:
				return;
				break;
			}

			if ( cent->gent->owner )
			{
				cent->gent->owner->fx_time = cg.time;
				if ( cent->gent->owner->client )
				{
					if ( disintSound1 && disintSound2 )
					{//play an extra sound
					/*
						if ( cent->gent->owner->client->playerTeam == TEAM_STARFLEET ||
								cent->gent->owner->client->playerTeam == TEAM_SCAVENGERS ||
								cent->gent->owner->client->playerTeam == TEAM_MALON ||
								cent->gent->owner->client->playerTeam == TEAM_IMPERIAL ||
								cent->gent->owner->client->playerTeam == TEAM_HIROGEN ||
								cent->gent->owner->client->playerTeam == TEAM_DISGUISE ||
								cent->gent->owner->client->playerTeam == TEAM_KLINGON )
					*/
						// listed all the non-humanoids, because there's a lot more humanoids
						class_t	npc_class = cent->gent->owner->client->NPC_class;
						if( npc_class != CLASS_ATST && npc_class != CLASS_GONK &&
							npc_class != CLASS_INTERROGATOR && npc_class != CLASS_MARK1 &&
							npc_class != CLASS_MARK2 && npc_class != CLASS_MOUSE &&
							npc_class != CLASS_PROBE && npc_class != CLASS_PROTOCOL &&
							npc_class != CLASS_R2D2 && npc_class != CLASS_R5D2 &&
							npc_class != CLASS_SEEKER && npc_class != CLASS_SENTRY)
						{//Only the humanoids scream
							cgi_S_StartSound ( NULL, cent->gent->owner->s.number, CHAN_VOICE, disintSound1 );
						}
						// no more forge or 8472
					//	else if ( cent->gent->owner->client->playerTeam == TEAM_FORGE ||
					//			cent->gent->owner->client->playerTeam == TEAM_8472 )
					//	{
					//		cgi_S_StartSound ( NULL, cent->gent->s.number, CHAN_VOICE, disintSound3 );
					//	}
						else
						{
							cgi_S_StartSound ( NULL, cent->gent->s.number, CHAN_AUTO, disintSound2 );
						}
					}
					cent->gent->owner->s.powerups |= ( 1 << disintPW );
					cent->gent->owner->client->ps.powerups[disintPW] = cg.time + disintLength;

					// Things that are being disintegrated should probably not be solid...
					if ( makeNotSolid && cent->gent->owner->client->playerTeam != TEAM_NEUTRAL )
					{
						cent->gent->contents = CONTENTS_NONE;
					}
				}
				else
				{
					cent->gent->owner->s.eFlags = disintEffect;//FIXME: |= ?
					cent->gent->owner->delay = cg.time + disintLength;
				}
			}
		}
		break;

	// This does not necessarily have to be from a grenade...
	case EV_GRENADE_BOUNCE:
		DEBUGNAME("EV_GRENADE_BOUNCE");
		CG_BounceEffect( cent, es->weapon, position, cent->gent->pos1 );
		break;

	//
	// missile impacts
	//

	case EV_MISSILE_STICK:
		DEBUGNAME("EV_MISSILE_STICK");
		CG_MissileStick( cent, es->weapon, position );
		break;

	case EV_MISSILE_HIT:
		DEBUGNAME("EV_MISSILE_HIT");
		CG_MissileHitPlayer( cent, es->weapon, position, cent->gent->pos1, cent->gent->alt_fire );
		break;

	case EV_MISSILE_MISS:
		DEBUGNAME("EV_MISSILE_MISS");
		CG_MissileHitWall( cent, es->weapon, position, cent->gent->pos1, cent->gent->alt_fire );
		break;

	case EV_BMODEL_SOUND:
		DEBUGNAME("EV_BMODEL_SOUND");
		cgi_S_StartSound( NULL, es->number, CHAN_AUTO, es->eventParm );
		break;

	case EV_GENERAL_SOUND:
		DEBUGNAME("EV_GENERAL_SOUND");
		if ( cgs.sound_precache[ es->eventParm ] ) 
		{
			cgi_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.sound_precache[ es->eventParm ] );
		} 
		else 
		{
			s = CG_ConfigString( CS_SOUNDS + es->eventParm );
			CG_TryPlayCustomSound(NULL, es->number, CHAN_AUTO, s, CS_BASIC );
		}
		break;

	case EV_GLOBAL_SOUND:	// play from the player's head so it never diminishes
		DEBUGNAME("EV_GLOBAL_SOUND");
		if ( cgs.sound_precache[ es->eventParm ] ) {
			cgi_S_StartSound (NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.sound_precache[ es->eventParm ] );
		} else {
			s = CG_ConfigString( CS_SOUNDS + es->eventParm );
			CG_TryPlayCustomSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, s, CS_BASIC );
		}
		break;

#ifdef _IMMERSION
	case EV_ENTITY_FORCE:				// Plays force on entity
		DEBUGNAME("EV_ENTITY_FORCE");
		if ( !cgs.force_precache[ es->eventParm ] )
		{
			const char *name;
			int channel;
			if ( CG_ConfigForce( es->eventParm, name, channel ) )
			{
				cgs.force_precache[ es->eventParm ] = cgi_FF_Register( name, channel );
			}
		}
		cgi_FF_Start( cgs.force_precache[ es->eventParm ], es->number );
		break;

	case EV_GLOBAL_FORCE:
	case EV_AREA_FORCE:
		DEBUGNAME("EV_AREA_FORCE");	// Plays force for anyone
		if ( !cgs.force_precache[ es->eventParm ] )
		{
			const char *name;
			int channel;
			if ( CG_ConfigForce( es->eventParm, name, channel ) )
			{
				cgs.force_precache[ es->eventParm ] = cgi_FF_Register( name, channel );
			}
		}
		cgi_FF_Start( cgs.force_precache[ es->eventParm ], es->number );
		break;

	case EV_FORCE_STOP:
		DEBUGNAME("EV_FORCE_STOP");
		if ( es->eventParm < 0 )
		{
			cgi_FF_StopAll( );
		}
		else if ( es->eventParm < MAX_FORCES && cgs.force_precache[ es->eventParm ] )
		{
			cgi_FF_Stop( cgs.force_precache[ es->eventParm ], es->number );
		}
		
		break;
#endif // _IMMERSION
	case EV_DRUGGED:
		DEBUGNAME("EV_DRUGGED");
		if ( cent->gent && cent->gent->owner && cent->gent->owner->s.number == 0 )
		{
			// Only allow setting up the wonky vision on the player..do it for 10 seconds...must be synchronized with calcs done in cg_view.  Just search for cg.wonkyTime to find 'em.
			cg.wonkyTime = cg.time + 10000;
		}
		break;

	case EV_PAIN:
		{
		char	*snd;
		const int health = es->eventParm;

		if ( cent->gent && cent->gent->NPC && (cent->gent->NPC->aiFlags & NPCAI_DIE_ON_IMPACT) )
		{
			return;
		}
		//FIXME: don't do this if we're falling to our deaths...
		DEBUGNAME("EV_PAIN");
		// don't do more than two pain sounds a second
		if ( cg.time - cent->pe.painTime < 500 ) {
			return;
		}

		if ( health < 25 ) {
			snd = "*pain100.wav";
		} else if ( health < 50 ) {
			snd = "*pain75.wav";
		} else if ( health < 75 ) {
			snd = "*pain50.wav";
		} else {
			snd = "*pain25.wav";
		}
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, snd, CS_BASIC );

		// save pain time for programitic twitch animation
		cent->pe.painTime = cg.time;
		cent->pe.painDirection ^= 1;
		}
		break;

	case EV_DEATH1:
	case EV_DEATH2:
	case EV_DEATH3:
		DEBUGNAME("EV_DEATHx");
		/*
		if ( cent->gent && cent->gent->NPC && (cent->gent->NPC->aiFlags & NPCAI_DIE_ON_IMPACT) )
		{
			return;
		}
		*/
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*death%i.wav", event - EV_DEATH1 + 1), CS_BASIC );
		break;

	// Called by the FxRunner entity...usually for Environmental FX Events
	case EV_PLAY_EFFECT:
		DEBUGNAME("EV_PLAY_EFFECT");
		{
			const bool portalEnt = !!es->isPortalEnt; //the fxrunner spawning this effect is within a skyportal, so only render this effect within that portal.

			s = CG_ConfigString( CS_EFFECTS + es->eventParm );
	// Ghoul2 Insert Start
			if (es->boltInfo != 0)
			{
				const bool isRelative = !!es->weapon;
				theFxScheduler.PlayEffect( s, cent->lerpOrigin, axis, es->boltInfo, -1, portalEnt, es->loopSound, isRelative );	//loopSound 0 = not looping, 1 for infinite, else duration
			}
			else
			{
				VectorCopy( cent->gent->pos3, axis[0] );
				VectorCopy( cent->gent->pos4, axis[1] );
				CrossProduct( axis[0], axis[1], axis[2] );

				// the entNum the effect may be attached to
	#ifdef _IMMERSION
				if ( es->saberActive )
				{
					theFxScheduler.PlayEffect( s, cent->lerpOrigin, axis, -1, FF_CLIENT( es->otherEntityNum ), portalEnt );
				}
				else
	#endif // _IMMERSION
				if ( es->otherEntityNum )
				{
					theFxScheduler.PlayEffect( s, cent->lerpOrigin, axis, -1, es->otherEntityNum, portalEnt );
				}
				else
				{
					theFxScheduler.PlayEffect( s, cent->lerpOrigin, axis, -1, -1, portalEnt );
				}
			}
		}
// Ghoul2 Insert End
		break;

		// play an effect bolted onto a muzzle
	case EV_PLAY_MUZZLE_EFFECT:
		DEBUGNAME("EV_PLAY_MUZZLE_EFFECT");
		s = CG_ConfigString( CS_EFFECTS + es->eventParm );

		theFxScheduler.PlayEffect( s, es->otherEntityNum );
		break;

	case EV_STOP_EFFECT:
		DEBUGNAME("EV_STOP_EFFECT");
		{
			bool portalEnt = false;

			if ( es->isPortalEnt )
			{ //the fxrunner spawning this effect is within a skyportal, so only render this effect within that portal.
				portalEnt = true;
			}

			s = CG_ConfigString( CS_EFFECTS + es->eventParm );
			if ( es->boltInfo != 0 )
			{
				theFxScheduler.StopEffect( s, es->boltInfo, portalEnt );
			}
		}
		break;

	case EV_TARGET_BEAM_DRAW:
		DEBUGNAME("EV_TARGET_BEAM_DRAW");
		if ( cent->gent )
		{
			s = CG_ConfigString( CS_EFFECTS + es->eventParm );

			if ( s && s[0] )
			{
				if ( cent->gent->delay )
				{
					s2 = CG_ConfigString( CS_EFFECTS + cent->gent->delay );
				}
				else
				{
					s2 = NULL;
				}

				CG_DrawTargetBeam( cent->lerpOrigin, cent->gent->s.origin2, cent->gent->pos1, s, s2 );
			}
/*			else
			{
				int gack = 0; // this is bad if it get's here
			}
*/
		}
		break;

	case EV_ANGER1:	//Say when acquire an enemy when didn't have one before
	case EV_ANGER2:
	case EV_ANGER3:
		DEBUGNAME("EV_ANGERx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*anger%i.wav", event - EV_ANGER1 + 1), CS_COMBAT );
		break;

	case EV_VICTORY1:	//Say when killed an enemy
	case EV_VICTORY2:
	case EV_VICTORY3:
		DEBUGNAME("EV_VICTORYx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*victory%i.wav", event - EV_VICTORY1 + 1), CS_COMBAT );
		break;

	case EV_CONFUSE1:	//Say when confused
	case EV_CONFUSE2:
	case EV_CONFUSE3:
		DEBUGNAME("EV_CONFUSEDx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*confuse%i.wav", event - EV_CONFUSE1 + 1), CS_COMBAT );
		break;

	case EV_PUSHED1:	//Say when pushed
	case EV_PUSHED2:
	case EV_PUSHED3:
		DEBUGNAME("EV_PUSHEDx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*pushed%i.wav", event - EV_PUSHED1 + 1), CS_COMBAT );
		break;

	case EV_CHOKE1:	//Say when choking
	case EV_CHOKE2:
	case EV_CHOKE3:
		DEBUGNAME("EV_CHOKEx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*choke%i.wav", event - EV_CHOKE1 + 1), CS_COMBAT );
		break;

	case EV_FFWARN:	//Warn ally to stop shooting you
		DEBUGNAME("EV_FFWARN");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*ffwarn.wav", CS_COMBAT );
		break;

	case EV_FFTURN:	//Turn on ally after being shot by them
		DEBUGNAME("EV_FFTURN");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*ffturn.wav", CS_COMBAT );
		break;

	//extra sounds for ST
	case EV_CHASE1:
	case EV_CHASE2:
	case EV_CHASE3:
		DEBUGNAME("EV_CHASEx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*chase%i.wav", event - EV_CHASE1 + 1), CS_EXTRA );
		break;
	case EV_COVER1:
	case EV_COVER2:
	case EV_COVER3:
	case EV_COVER4:
	case EV_COVER5:
		DEBUGNAME("EV_COVERx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*cover%i.wav", event - EV_COVER1 + 1), CS_EXTRA );
		break;
	case EV_DETECTED1:
	case EV_DETECTED2:
	case EV_DETECTED3:
	case EV_DETECTED4:
	case EV_DETECTED5:
		DEBUGNAME("EV_DETECTEDx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*detected%i.wav", event - EV_DETECTED1 + 1), CS_EXTRA );
		break;
	case EV_GIVEUP1:
	case EV_GIVEUP2:
	case EV_GIVEUP3:
	case EV_GIVEUP4:
		DEBUGNAME("EV_GIVEUPx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*giveup%i.wav", event - EV_GIVEUP1 + 1), CS_EXTRA );
		break;
	case EV_LOOK1:
	case EV_LOOK2:
		DEBUGNAME("EV_LOOKx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*look%i.wav", event - EV_LOOK1 + 1), CS_EXTRA );
		break;
	case EV_LOST1:
		DEBUGNAME("EV_LOST1");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*lost1.wav", CS_EXTRA );
		break;
	case EV_OUTFLANK1:
	case EV_OUTFLANK2:
		DEBUGNAME("EV_OUTFLANKx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*outflank%i.wav", event - EV_OUTFLANK1 + 1), CS_EXTRA );
		break;
	case EV_ESCAPING1:
	case EV_ESCAPING2:
	case EV_ESCAPING3:
		DEBUGNAME("EV_ESCAPINGx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*escaping%i.wav", event - EV_ESCAPING1 + 1), CS_EXTRA );
		break;
	case EV_SIGHT1:
	case EV_SIGHT2:
	case EV_SIGHT3:
		DEBUGNAME("EV_SIGHTx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*sight%i.wav", event - EV_SIGHT1 + 1), CS_EXTRA );
		break;
	case EV_SOUND1:
	case EV_SOUND2:
	case EV_SOUND3:
		DEBUGNAME("EV_SOUNDx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*sound%i.wav", event - EV_SOUND1 + 1), CS_EXTRA );
		break;
	case EV_SUSPICIOUS1:
	case EV_SUSPICIOUS2:
	case EV_SUSPICIOUS3:
	case EV_SUSPICIOUS4:
	case EV_SUSPICIOUS5:
		DEBUGNAME("EV_SUSPICIOUSx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*suspicious%i.wav", event - EV_SUSPICIOUS1 + 1), CS_EXTRA );
		break;
	//extra sounds for Jedi
	case EV_COMBAT1:
	case EV_COMBAT2:
	case EV_COMBAT3:
		DEBUGNAME("EV_COMBATx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*combat%i.wav", event - EV_COMBAT1 + 1), CS_JEDI );
		break;
	case EV_JDETECTED1:
	case EV_JDETECTED2:
	case EV_JDETECTED3:
		DEBUGNAME("EV_JDETECTEDx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*jdetected%i.wav", event - EV_JDETECTED1 + 1), CS_JEDI );
		break;
	case EV_TAUNT1:
	case EV_TAUNT2:
	case EV_TAUNT3:
		DEBUGNAME("EV_TAUNTx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*taunt%i.wav", event - EV_TAUNT1 + 1), CS_JEDI );
		break;
	case EV_JCHASE1:
	case EV_JCHASE2:
	case EV_JCHASE3:
		DEBUGNAME("EV_JCHASEx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*jchase%i.wav", event - EV_JCHASE1 + 1), CS_JEDI );
		break;
	case EV_JLOST1:
	case EV_JLOST2:
	case EV_JLOST3:
		DEBUGNAME("EV_JLOSTx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*jlost%i.wav", event - EV_JLOST1 + 1), CS_JEDI );
		break;
	case EV_DEFLECT1:
	case EV_DEFLECT2:
	case EV_DEFLECT3:
		DEBUGNAME("EV_DEFLECTx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*deflect%i.wav", event - EV_DEFLECT1 + 1), CS_JEDI );
		break;
	case EV_GLOAT1:
	case EV_GLOAT2:
	case EV_GLOAT3:
		DEBUGNAME("EV_GLOATx");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, va("*gloat%i.wav", event - EV_GLOAT1 + 1), CS_JEDI );
		break;
	case EV_PUSHFAIL:
		DEBUGNAME("EV_PUSHFAIL");
		CG_TryPlayCustomSound( NULL, es->number, CHAN_VOICE, "*pushfail.wav", CS_JEDI );
		break;

	case EV_USE_FORCE:
		DEBUGNAME("EV_USE_FORCEITEM");
		CG_UseForce( cent );
		break;

	case EV_USE_ITEM:
		DEBUGNAME("EV_USE_ITEM");
		CG_UseItem( cent );
		break;

	case EV_USE_INV_BINOCULARS:
		DEBUGNAME("EV_USE_INV_BINOCULARS");
		UseItem(INV_ELECTROBINOCULARS );
		break;

	case EV_USE_INV_BACTA:
		DEBUGNAME("EV_USE_INV_BACTA");
		UseItem(INV_BACTA_CANISTER );
		break;

	case EV_USE_INV_SEEKER:
		DEBUGNAME("EV_USE_INV_SEEKER");
		UseItem(INV_SEEKER );
		break;

	case EV_USE_INV_LIGHTAMP_GOGGLES:
		DEBUGNAME("EV_USE_INV_LIGHTAMP_GOGGLES");
		UseItem(INV_LIGHTAMP_GOGGLES );
		break;
	
	case EV_USE_INV_SENTRY:
		DEBUGNAME("EV_USE_INV_SENTRY");
		UseItem(INV_SENTRY );
		break;
	
	case EV_DEBUG_LINE:
		DEBUGNAME("EV_DEBUG_LINE");
		CG_TestLine(position, es->origin2, es->time, (unsigned int)(es->time2), es->weapon);
		break;

	default:
		DEBUGNAME("UNKNOWN");
		CG_Error( "Unknown event: %i", event );
		break;
	}

}
Exemplo n.º 4
0
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_TEAM ] == TEAM_SPECTATOR )
    steptime = 200;
  else
    steptime = BG_FindSteptimeForClass( cg.snap->ps.stats[ STAT_PCLASS ] );

  es = &cent->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 && 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:
      DEBUGNAME( "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:
      DEBUGNAME( "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:
      DEBUGNAME( "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:
      DEBUGNAME( "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:
      DEBUGNAME( "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:
      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_FALLING:
      DEBUGNAME( "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
      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 < 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:
      DEBUGNAME( "EV_JUMP" );
      trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) );

      if( BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], 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:
      DEBUGNAME( "EV_LEV1_GRAB" );
      trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL1Grab );
      break;

    case EV_LEV4_CHARGE_PREPARE:
      DEBUGNAME( "EV_LEV4_CHARGE_PREPARE" );
      trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargePrepare );
      break;

    case EV_LEV4_CHARGE_START:
      DEBUGNAME( "EV_LEV4_CHARGE_START" );
      //FIXME: stop cgs.media.alienL4ChargePrepare playing here
      trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargeStart );
      break;

    case EV_TAUNT:
      DEBUGNAME( "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:
      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;

    //
    // weapon events
    //
    case EV_NOAMMO:
      DEBUGNAME( "EV_NOAMMO" );
      {
      }
      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, WPM_PRIMARY );
      break;

    case EV_FIRE_WEAPON2:
      DEBUGNAME( "EV_FIRE_WEAPON2" );
      CG_FireWeapon( cent, WPM_SECONDARY );
      break;

    case EV_FIRE_WEAPON3:
      DEBUGNAME( "EV_FIRE_WEAPON3" );
      CG_FireWeapon( cent, WPM_TERTIARY );
      break;

    //=================================================================

    //
    // other events
    //
    case EV_PLAYER_TELEPORT_IN:
      DEBUGNAME( "EV_PLAYER_TELEPORT_IN" );
      //deprecated
      break;

    case EV_PLAYER_TELEPORT_OUT:
      DEBUGNAME( "EV_PLAYER_TELEPORT_OUT" );
      CG_PlayerDisconnect( position );
      break;

    case EV_BUILD_CONSTRUCT:
      DEBUGNAME( "EV_BUILD_CONSTRUCT" );
      //do something useful here
      break;

    case EV_BUILD_DESTROY:
      DEBUGNAME( "EV_BUILD_DESTROY" );
      //do something useful here
      break;

    case EV_RPTUSE_SOUND:
      DEBUGNAME( "EV_RPTUSE_SOUND" );
      trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.repeaterUseSound );
      break;

    case EV_GRENADE_BOUNCE:
      DEBUGNAME( "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;

    //
    // missile impacts
    //
    case EV_MISSILE_HIT:
      DEBUGNAME( "EV_MISSILE_HIT" );
      ByteToDir( es->eventParm, dir );
      CG_MissileHitPlayer( es->weapon, es->generic1, position, dir, es->otherEntityNum );
      break;

    case EV_MISSILE_MISS:
      DEBUGNAME( "EV_MISSILE_MISS" );
      ByteToDir( es->eventParm, dir );
      CG_MissileHitWall( es->weapon, es->generic1, 0, position, dir, IMPACTSOUND_DEFAULT );
      break;

    case EV_MISSILE_MISS_METAL:
      DEBUGNAME( "EV_MISSILE_MISS_METAL" );
      ByteToDir( es->eventParm, dir );
      CG_MissileHitWall( es->weapon, es->generic1, 0, position, dir, IMPACTSOUND_METAL );
      break;

    case EV_HUMAN_BUILDABLE_EXPLOSION:
      DEBUGNAME( "EV_HUMAN_BUILDABLE_EXPLOSION" );
      ByteToDir( es->eventParm, dir );
      CG_HumanBuildableExplosion( position, dir );
      break;

    case EV_ALIEN_BUILDABLE_EXPLOSION:
      DEBUGNAME( "EV_ALIEN_BUILDABLE_EXPLOSION" );
      ByteToDir( es->eventParm, dir );
      CG_AlienBuildableExplosion( position, dir );
      break;

    case EV_TESLATRAIL:
      DEBUGNAME( "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_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 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_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" );
      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;

    case EV_GIB_PLAYER:
      DEBUGNAME( "EV_GIB_PLAYER" );
      // no gibbing
      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;

    case EV_BUILD_DELAY:
      DEBUGNAME( "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:
      DEBUGNAME( "EV_BUILD_REPAIR" );
      trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairSound );
      break;

    case EV_BUILD_REPAIRED:
      DEBUGNAME( "EV_BUILD_REPAIRED" );
      trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairedSound );
      break;

    case EV_OVERMIND_ATTACK:
      DEBUGNAME( "EV_OVERMIND_ATTACK" );
      if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS )
      {
        trap_S_StartLocalSound( cgs.media.alienOvermindAttack, CHAN_ANNOUNCER );
        CG_CenterPrint( "The Overmind is under attack!", 200, GIANTCHAR_WIDTH * 4 );
      }
      break;

    case EV_OVERMIND_DYING:
      DEBUGNAME( "EV_OVERMIND_DYING" );
      if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS )
      {
        trap_S_StartLocalSound( cgs.media.alienOvermindDying, CHAN_ANNOUNCER );
        CG_CenterPrint( "The Overmind is about to die!", 200, GIANTCHAR_WIDTH * 4 );
      }
      break;

    case EV_DCC_ATTACK:
      DEBUGNAME( "EV_DCC_ATTACK" );
      if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS )
      {
        //trap_S_StartLocalSound( cgs.media.humanDCCAttack, CHAN_ANNOUNCER );
        CG_CenterPrint( "Aliens has been detetected attacking our base!", 200, GIANTCHAR_WIDTH * 4 );
      }
      break;

    case EV_OVERMIND_SPAWNS:
      DEBUGNAME( "EV_OVERMIND_SPAWNS" );
      if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS )
      {
        trap_S_StartLocalSound( cgs.media.alienOvermindSpawns, CHAN_ANNOUNCER );
        CG_CenterPrint( "The Overmind needs eggs!", 200, GIANTCHAR_WIDTH * 4 );
      }
      break;

    case EV_ALIEN_EVOLVE:
      DEBUGNAME( "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:
      DEBUGNAME( "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:
      DEBUGNAME( "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:
      DEBUGNAME( "EV_MEDKIT_USED" );
      trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.medkitUseSound );
      break;

    case EV_PLAYER_RESPAWN:
      DEBUGNAME( "EV_PLAYER_RESPAWN" );
      if( es->number == cg.clientNum )
        cg.spawnTime = cg.time;
      break;

    default:
      DEBUGNAME( "UNKNOWN" );
      CG_Error( "Unknown event: %i", event );
      break;
  }
}