Ejemplo n.º 1
0
//ported from SP
void G_DynamicMusicUpdate( void )
{
	int			battle = 0;
	vec3_t		center;
	qboolean	clearLOS = qfalse;
	int			distSq, radius = 2048;
	int			i, e, x;
	gentity_t	*ent;
	int entityList[MAX_GENTITIES];
	int			entTeam;
	vec3_t		mins, maxs;
	int			numListedEntities;
	gentity_t	*player;

	if( DMSData.dmDebounceTime >= 0 && DMSData.dmDebounceTime < level.time )
	{//debounce over, reset to default music
		DMSData.dmDebounceTime = -1;
		DMSData.dmState = DM_AUTO;
		DMSData.olddmState = DM_AUTO;
	}

	if ( DMSData.dmState == DM_DEATH)
	{//Play the death music
		if(DMSData.olddmState != DM_DEATH)
		{//haven't set the state yet
			trap_SetConfigstring( CS_MUSIC, DMS_DEATH_MUSIC );
			DMSData.olddmState = DM_DEATH;
			DMSData.dmDebounceTime = level.time + DMS_DEATH_MUSIC_TIME;
		}
		return;
	}

	if ( DMSData.dmState == DM_BOSS )
	{
		if(DMSData.olddmState != DM_BOSS)
		{
			trap_SetConfigstring( CS_MUSIC, DMSData.bossMusic.fileName );
			DMSData.olddmState = DM_BOSS;
		}
		return;
	}

	if ( DMSData.dmState == DM_SILENCE )
	{//turn off the music
		if(DMSData.olddmState != DM_SILENCE)
		{
			trap_SetConfigstring( CS_MUSIC, "" );
			DMSData.olddmState = DM_SILENCE;
		}
		return;
	}

	if ( DMSData.dmBeatTime > level.time )
	{//not on a beat
		return;
	}

	DMSData.dmBeatTime = level.time + 1000;//1 second beats

	for(i = 0; i < MAX_CLIENTS; i++)
	{
		player = &g_entities[i];

		//check to make sure this player is valid
		if(!player || !player->inuse 
			|| player->client->pers.connected == CON_DISCONNECTED
			|| player->client->sess.sessionTeam == TEAM_SPECTATOR)
		{
			continue;
		}

		//enemy-based
		VectorCopy( player->r.currentOrigin, center );
		for ( x = 0 ; x < 3 ; x++ ) 
		{
			mins[x] = center[x] - radius;
			maxs[x] = center[x] + radius;
		}
	
		numListedEntities = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
		for ( e = 0 ; e < numListedEntities ; e++ ) 
		{
			ent = &g_entities[entityList[e]];
			if ( !ent || !ent->inuse )
			{
				continue;
			}

			if ( !ent->client || !ent->NPC )
			{
				if ( ent->classname && (!Q_stricmp( "PAS", ent->classname )||!Q_stricmp( "misc_turret", ent->classname )) )
				{//a turret
					entTeam = ent->teamnodmg;
					//entTeam = ent->noDamageTeam;
				}
				else
				{
					continue;
				}
			}
			else
			{//an NPC
				entTeam = ent->client->playerTeam;
			}

			if ( entTeam == player->client->playerTeam )
			{//ally
				continue;
			}

			if ( entTeam == TEAM_FREE && (!ent->enemy || !ent->enemy->client || ent->enemy->client->playerTeam != player->client->playerTeam) )
			{//a droid that is not mad at me or my allies
				continue;
			}

			if ( !trap_InPVS( player->r.currentOrigin, ent->r.currentOrigin ) )
			{//not potentially visible
				continue;
			}

			if ( ent->client && ent->s.weapon == WP_NONE )
			{//they don't have a weapon... FIXME: only do this for droids?
				continue;
			}

			clearLOS = qfalse;
			if ( (ent->enemy==player&&(!ent->NPC||ent->NPC->confusionTime<level.time)) || (ent->client&&ent->client->ps.weaponTime) || (!ent->client&&ent->attackDebounceTime>level.time))
			{//mad
				if ( ent->health > 0 )
				{//alive
					//FIXME: do I really need this check?
					if ( ent->s.weapon == WP_SABER && ent->client && ent->client->ps.saberHolstered == 2 && ent->enemy != player )
					{//a Jedi who has not yet gotten mad at me
						continue;
					}
					if ( ent->NPC && ent->NPC->behaviorState == BS_CINEMATIC )
					{//they're not actually going to do anything about being mad at me...
						continue;
					}
					//okay, they're in my PVS, but how close are they?  Are they actively attacking me?
					if ( !ent->client && ent->s.weapon == WP_TURRET && ent->fly_sound_debounce_time && ent->fly_sound_debounce_time - level.time < 10000 )
					{//a turret that shot at me less than ten seconds ago
					}
					else if( ent->NPC && level.time < ent->NPC->shotTime )
					{//npc that fired recently
					}
					/* changed from SP
					else if ( ent->client && ent->client->ps.lastShotTime && ent->client->ps.lastShotTime - level.time < 10000 )
					{//an NPC that shot at me less than ten seconds ago
					}
					*/
					else
					{//not actively attacking me lately, see how far away they are
						distSq = DistanceSquared( ent->r.currentOrigin, player->r.currentOrigin );
						if ( distSq > 4194304 )
						{//> 2048 away
							continue;
						}
						else if ( distSq > 1048576 )
						{//> 1024 away
							clearLOS = G_ClearLOS3( player, player->client->renderInfo.eyePoint, ent );
							if ( clearLOS == qfalse )
							{//No LOS
								continue;
							}
						}
					}
					battle++;
				}
			}
		}

		if ( !battle )
		{//no active enemies, but look for missiles, shot impacts, etc...
			//[CoOp]
			int alert = G_CheckAlertEvents( player, qtrue, qtrue, 1024, 1024, -1, qfalse, AEL_SUSPICIOUS, qfalse );
			//int alert = G_CheckAlertEvents( player, qtrue, qtrue, 1024, 1024, -1, qfalse, AEL_SUSPICIOUS );
			//[/CoOp]
			if ( alert != -1 )
			{//FIXME: maybe tripwires and other FIXED things need their own sound, some kind of danger/caution theme
				if ( G_CheckForDanger( player, alert ) )
				{//found danger near by
					battle = 1;
				}
			}
		}
	}

	if ( battle )
	{
		SetDMSState(DM_ACTION);
	}
	else 
	{//switch to explore
		SetDMSState(DM_EXPLORE);
	}

	if(DMSData.dmState != DMSData.olddmState)
	{//switching between action and explore modes
		TransitionBetweenState();
	}
}
Ejemplo n.º 2
0
/*
static void G_DynamicMusicUpdate( usercmd_t *ucmd )

  FIXME: can we merge any of this with the G_ChooseLookEnemy stuff?
*/
static void G_DynamicMusicUpdate( void )
{
	gentity_t	*ent;
	gentity_t	*entityList[MAX_GENTITIES];
	int			numListedEntities;
	vec3_t		mins, maxs;
	int			i, e;
	int			distSq, radius = 2048;
	vec3_t		center;
	int			danger = 0;
	int			battle = 0;
	int			entTeam;
	qboolean	dangerNear = qfalse;
	qboolean	suspicious = qfalse;
	qboolean	LOScalced = qfalse, clearLOS = qfalse;

	//FIXME: intro and/or other cues? (one-shot music sounds)

	//loops

	//player-based
	if ( !player )
	{//WTF?
		player = &g_entities[0];
		return;
	}

	if ( !player->client 
		|| player->client->pers.teamState.state != TEAM_ACTIVE 
		|| level.time - player->client->pers.enterTime < 100 )
	{//player hasn't spawned yet
		return;
	}

	if ( player->health <= 0 && player->max_health > 0 )
	{//defeat music
		if ( level.dmState != DM_DEATH )
		{
			level.dmState = DM_DEATH;
		}
	}

	if ( level.dmState == DM_DEATH )
	{
		gi.SetConfigstring( CS_DYNAMIC_MUSIC_STATE, "death" );
		return;
	}

	if ( level.dmState == DM_BOSS )
	{
		gi.SetConfigstring( CS_DYNAMIC_MUSIC_STATE, "boss" );
		return;
	}

	if ( level.dmState == DM_SILENCE )
	{
		gi.SetConfigstring( CS_DYNAMIC_MUSIC_STATE, "silence" );
		return;
	}

	if ( level.dmBeatTime > level.time )
	{//not on a beat
		return;
	}

	level.dmBeatTime = level.time + 1000;//1 second beats

	if ( player->health <= 20 )
	{
		danger = 1;
	}

	//enemy-based
	VectorCopy( player->currentOrigin, center );
	for ( i = 0 ; i < 3 ; i++ ) 
	{
		mins[i] = center[i] - radius;
		maxs[i] = center[i] + radius;
	}
	
	numListedEntities = gi.EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
	for ( e = 0 ; e < numListedEntities ; e++ ) 
	{
		ent = entityList[ e ];
		if ( !ent || !ent->inuse )
		{
			continue;
		}

		if ( !ent->client || !ent->NPC )
		{
			if ( ent->classname && (!Q_stricmp( "PAS", ent->classname )||!Q_stricmp( "misc_turret", ent->classname )) )
			{//a turret
				entTeam = ent->noDamageTeam;
			}
			else
			{
				continue;
			}
		}
		else
		{//an NPC
			entTeam = ent->client->playerTeam;
		}

		if ( entTeam == player->client->playerTeam )
		{//ally
			continue;
		}

		if ( entTeam == TEAM_NEUTRAL && (!ent->enemy || !ent->enemy->client || ent->enemy->client->playerTeam != player->client->playerTeam) )
		{//a droid that is not mad at me or my allies
			continue;
		}

		if ( !gi.inPVS( player->currentOrigin, ent->currentOrigin ) )
		{//not potentially visible
			continue;
		}

		if ( ent->client && ent->s.weapon == WP_NONE )
		{//they don't have a weapon... FIXME: only do this for droids?
			continue;
		}

		LOScalced = clearLOS = qfalse;
		if ( (ent->enemy==player&&(!ent->NPC||ent->NPC->confusionTime<level.time)) || (ent->client&&ent->client->ps.weaponTime) || (!ent->client&&ent->attackDebounceTime>level.time))
		{//mad
			if ( ent->health > 0 )
			{//alive
				//FIXME: do I really need this check?
				if ( ent->s.weapon == WP_SABER && ent->client && !ent->client->ps.saberActive && ent->enemy != player )
				{//a Jedi who has not yet gotten made at me
					continue;
				}
				if ( ent->NPC && ent->NPC->behaviorState == BS_CINEMATIC )
				{//they're not actually going to do anything about being mad at me...
					continue;
				}
				//okay, they're in my PVS, but how close are they?  Are they actively attacking me?
				if ( !ent->client && ent->s.weapon == WP_TURRET && ent->fly_sound_debounce_time && ent->fly_sound_debounce_time - level.time < 10000 )
				{//a turret that shot at me less than ten seconds ago
				}
				else if ( ent->client && ent->client->ps.lastShotTime && ent->client->ps.lastShotTime - level.time < 10000 )
				{//an NPC that shot at me less than ten seconds ago
				}
				else
				{//not actively attacking me lately, see how far away they are
					distSq = DistanceSquared( ent->currentOrigin, player->currentOrigin );
					if ( distSq > 4194304/*2048*2048*/ )
					{//> 2048 away
						continue;
					}
					else if ( distSq > 1048576/*1024*1024*/ )
					{//> 1024 away
						clearLOS = G_ClearLOS( player, player->client->renderInfo.eyePoint, ent );
						LOScalced = qtrue;
						if ( clearLOS == qfalse )
						{//No LOS
							continue;
						}
					}
				}
				battle++;
			}
		}

		if ( level.dmState == DM_EXPLORE )
		{//only do these visibility checks if you're still in exploration mode
			if ( !InFront( ent->currentOrigin, player->currentOrigin, player->client->ps.viewangles, 0.0f) )
			{//not in front
				continue;
			}

			if ( !LOScalced )
			{
				clearLOS = G_ClearLOS( player, player->client->renderInfo.eyePoint, ent );
			}
			if ( !clearLOS ) 
			{//can't see them directly
				continue;
			}
		}

		if ( ent->health <= 0 )
		{//dead
			if ( !ent->client || level.time - ent->s.time > 10000 )
			{//corpse has been dead for more than 10 seconds
				//FIXME: coming across corpses should cause danger sounds too?
				continue;
			}
		}
		//we see enemies and/or corpses
		danger++;
	}

	if ( !battle )
	{//no active enemies, but look for missiles, shot impacts, etc...
		int alert = G_CheckAlertEvents( player, qtrue, qtrue, 1024, 1024, -1, qfalse, AEL_SUSPICIOUS );
		if ( alert != -1 )
		{//FIXME: maybe tripwires and other FIXED things need their own sound, some kind of danger/caution theme
			if ( G_CheckForDanger( player, alert ) )
			{//found danger near by
				danger++;
				battle = 1;
			}
			else if ( level.alertEvents[alert].owner && (level.alertEvents[alert].owner == player->enemy || (level.alertEvents[alert].owner->client && level.alertEvents[alert].owner->client->playerTeam == player->client->enemyTeam) ) )
			{//NPC on enemy team of player made some noise
				switch ( level.alertEvents[alert].level )
				{
				case AEL_DISCOVERED:
					dangerNear = qtrue;
					break;
				case AEL_SUSPICIOUS:
					suspicious = qtrue;
					break;
				case AEL_MINOR:
					//distraction = qtrue;
					break;
				}
			}
		}
	}

	if ( battle )
	{//battle - this can interrupt level.dmDebounceTime of lower intensity levels
		//play battle
		if ( level.dmState != DM_ACTION )
		{
			gi.SetConfigstring( CS_DYNAMIC_MUSIC_STATE, "action" );
		}
		level.dmState = DM_ACTION;
		if ( battle > 5 )
		{
			//level.dmDebounceTime = level.time + 8000;//don't change again for 5 seconds
		}
		else
		{
			//level.dmDebounceTime = level.time + 3000 + 1000*battle;
		}
	}
	else 
	{
		if ( level.dmDebounceTime > level.time )
		{//not ready to switch yet
			return;
		}
		else
		{//at least 1 second (for beats)
			//level.dmDebounceTime = level.time + 1000;//FIXME: define beat time?
		}
		/*
		if ( danger || dangerNear )
		{//danger
			//stay on whatever we were on, action or exploration
			if ( !danger )
			{//minimum
				danger = 1;
			}
			if ( danger > 3 )
			{
				level.dmDebounceTime = level.time + 5000;
			}
			else
			{
				level.dmDebounceTime = level.time + 2000 + 1000*danger;
			}
		}
		else
		*/
		{//still nothing dangerous going on
			if ( level.dmState != DM_EXPLORE )
			{//just went to explore, hold it for a couple seconds at least
				//level.dmDebounceTime = level.time + 2000;
				gi.SetConfigstring( CS_DYNAMIC_MUSIC_STATE, "explore" );
			}
			level.dmState = DM_EXPLORE;
			//FIXME: look for interest points and play "mysterious" music instead of exploration?
			//FIXME: suspicious and distraction sounds should play some cue or change music in a subtle way?
			//play exploration
		}
		//FIXME: when do we go to silence?
	}
}
Ejemplo n.º 3
0
qboolean NPC_CheckForDanger( int alertEvent )
{//FIXME: more bStates need to call this?
	return G_CheckForDanger( NPC, alertEvent );
}