//NPC's eyes to entity qboolean G_ClearLOS4( gentity_t *self, gentity_t *ent ) { vec3_t eyes; //Calculate my position CalcEntitySpot( self, SPOT_HEAD_LEAN, eyes ); return G_ClearLOS3( self, eyes, ent ); }
//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(); } }
qboolean NPC_ClearLOS3( const vec3_t start, gentity_t *ent ) { return G_ClearLOS3( NPC, start, ent ); }