mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
squashed into a single commit because doing it in steps that all
compiled involved a lot of boilerplate that is pointless to commit to
the repository. GH still has the PR for reference.
g_lang, MAX_MESSAGES_ON_MAP_BOTTOM, and GetLanguagePrefix() were
compile-time constants selected by the ENGLISH/GERMAN/... build
define. They're now runtime, defaulting to the same per-exe value the
define used to pick, and overridable at startup from [Ja2 Settings]
LANGUAGE in Ja2.ini.
-
XMLTacticalMessages is filled at runtime from NewTacticalMessages.xml,
never from compiled-in per-language data: all 8 per-language definitions
were the identical all-zero { L"" }. Delete them and define one shared
buffer in Utils/XML_Language.cpp (the loader) instead of pointer-rebinding
it like the static tables — this drops 9 dead 800KB zero-buffers (8
namespaced copies in LanguageStrings.cpp plus the standalone one) and
leaves no bind-ordering hazard for the XML load path.
-
ExportStrings.cpp privately recompiled one language's full text table
by #including the raw _<LANG>Text.cpp inside namespace Loc, keyed off
the exe-level ENGLISH/GERMAN/... compile macro (whichever the build
happened to select). That's redundant with the pointer globals every
other subsystem already uses (Text.h / LanguageStrings.cpp).
Drop the private copy; the unqualified table names in Loc::ExportStrings
now resolve to the global pointer externs, which BindLanguageStrings has
already rebound to the runtime g_lang by the time this runs (EXPORT_STRINGS
ini flag, checked after GetRuntimeSettings in sgp.cpp). gs_Lang (used only
by Loc::Translate for the Polish/Russian byte remap on raw .edt exports) is
now derived from g_lang via ToLocLanguage, so the export always matches
whatever language is actually active instead of a compile-time pick.
-
Editor/popupmenu.cpp and Strategic/Scheduling.cpp kept their own
call-site extern of gszScheduleActions as CHAR16[NUM_SCHEDULE_ACTIONS][20]
after the real definition changed into a rebindable pointer
(CHAR16 (*)[20], LanguageStrings.cpp). MSVC decays the outer array
dimension when mangling globals, so both declarations produce the same
symbol (?gszScheduleActions@@3PAY0BE@_WA) and the mismatch linked
silently -- but the array-typed TUs then indexed the 4-byte pointer
slot itself as string data, so the editor schedule popup and the map
schedule message text read garbage.
-
add text.def to be single-source of truth on symbol names and use it
.much simpler, less error prone if adding more strings
-
add pseudo interface for language state. MAX_SAGES_ON_BOTTOM must always
change in lockstep with g_lang. this isn't foolproof but better
---------
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
725 lines
16 KiB
C++
725 lines
16 KiB
C++
#include "builddefines.h"
|
|
|
|
#include "Ambient Control.h"
|
|
#include "Sound Control.h"
|
|
#include "Game Events.h"
|
|
#include "lighting.h"
|
|
#include "random.h"
|
|
// sevenfm
|
|
#include "SmokeEffects.h"
|
|
#include "Overhead.h"
|
|
#include "Strategic Movement.h"
|
|
#include "Game Clock.h"
|
|
#include "Strategic Mines.h"
|
|
|
|
AMBIENTDATA_STRUCT gAmbData[ MAX_AMBIENT_SOUNDS ];
|
|
INT16 gsNumAmbData = 0;
|
|
|
|
// sevenfm
|
|
UINT32 guiAmbientFire = NO_SAMPLE;
|
|
UINT8 gubAmbientFutureFireVolume = 0;
|
|
UINT32 guiFireAmbientLastUpdate = 0;
|
|
|
|
extern STR8 pVertStrings[];
|
|
extern STR8 pHortStrings[];
|
|
extern CHAR16 (*pTownNames)[MAX_TOWN_NAME_LENGHT];
|
|
|
|
UINT8 gubCurrentSteadyStateAmbience = SSA_NONE;
|
|
UINT8 gubCurrentSteadyStateSound = 0;
|
|
UINT32 guiCurrentSteadyStateSoundHandle = NO_SAMPLE;
|
|
STEADY_STATE_AMBIENCE gSteadyStateAmbientTable[ NUM_STEADY_STATE_AMBIENCES ] =
|
|
{
|
|
// NONE
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
// NIGHT
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
// COUNTRYSIZE
|
|
// DAY
|
|
"SOUNDS\\SSA\\insects Day 01.wav",
|
|
"",
|
|
"",
|
|
"",
|
|
// NIGHT
|
|
"SOUNDS\\SSA\\night_crickets_01D.wav",
|
|
"SOUNDS\\SSA\\night_crickets_01B.wav",
|
|
"SOUNDS\\SSA\\night_crickets_01C.wav",
|
|
"SOUNDS\\SSA\\night_crickets_01A.wav",
|
|
// NEAR WATER
|
|
// DAY
|
|
"SOUNDS\\SSA\\swamp_day_01a.wav",
|
|
"SOUNDS\\SSA\\swamp_day_01b.wav",
|
|
"SOUNDS\\SSA\\swamp_day_01c.wav",
|
|
"SOUNDS\\SSA\\swamp_day_01d.wav",
|
|
//NIGHT
|
|
"SOUNDS\\SSA\\marsh_at_night_01a.wav",
|
|
"SOUNDS\\SSA\\marsh_at_night_01b.wav",
|
|
"SOUNDS\\SSA\\marsh_at_night_01c.wav",
|
|
"SOUNDS\\SSA\\marsh_at_night_01d.wav",
|
|
//INWATER
|
|
//DAY
|
|
"SOUNDS\\SSA\\middle_of_water_01d.wav",
|
|
"SOUNDS\\SSA\\middle_of_water_01c.wav",
|
|
"SOUNDS\\SSA\\middle_of_water_01b.wav",
|
|
"SOUNDS\\SSA\\middle_of_water_01a.wav",
|
|
// night
|
|
"SOUNDS\\SSA\\middle_of_water_01d.wav",
|
|
"SOUNDS\\SSA\\middle_of_water_01c.wav",
|
|
"SOUNDS\\SSA\\middle_of_water_01b.wav",
|
|
"SOUNDS\\SSA\\middle_of_water_01a.wav",
|
|
// HEAVY FOREST
|
|
// day
|
|
"SOUNDS\\SSA\\JUNGLE_DAY_01a.wav",
|
|
"SOUNDS\\SSA\\JUNGLE_DAY_01b.wav",
|
|
"SOUNDS\\SSA\\JUNGLE_DAY_01c.wav",
|
|
"SOUNDS\\SSA\\JUNGLE_DAY_01d.wav",
|
|
// night
|
|
"SOUNDS\\SSA\\night_crickets_03a.wav",
|
|
"SOUNDS\\SSA\\night_crickets_03b.wav",
|
|
"SOUNDS\\SSA\\night_crickets_03c.wav",
|
|
"SOUNDS\\SSA\\night_crickets_03d.wav",
|
|
// PINE FOREST
|
|
// DAY
|
|
"SOUNDS\\SSA\\pine_forest_01a.wav",
|
|
"SOUNDS\\SSA\\pine_forest_01b.wav",
|
|
"SOUNDS\\SSA\\pine_forest_01c.wav",
|
|
"SOUNDS\\SSA\\pine_forest_01d.wav",
|
|
// NIGHT
|
|
"SOUNDS\\SSA\\night_crickets_02a.wav",
|
|
"SOUNDS\\SSA\\night_crickets_02b.wav",
|
|
"SOUNDS\\SSA\\night_crickets_02c.wav",
|
|
"SOUNDS\\SSA\\night_crickets_02d.wav",
|
|
// ABANDANDED
|
|
// DAY
|
|
"SOUNDS\\SSA\\metal_wind_01a.wav",
|
|
"SOUNDS\\SSA\\metal_wind_01b.wav",
|
|
"SOUNDS\\SSA\\metal_wind_01c.wav",
|
|
"SOUNDS\\SSA\\metal_wind_01d.wav",
|
|
// NIGHT
|
|
"SOUNDS\\SSA\\night_insects_01a.wav",
|
|
"SOUNDS\\SSA\\night_insects_01b.wav",
|
|
"SOUNDS\\SSA\\night_insects_01c.wav",
|
|
"SOUNDS\\SSA\\night_insects_01d.wav",
|
|
// AIRPORT
|
|
// DAY
|
|
"SOUNDS\\SSA\\rotating radar dish.wav",
|
|
"",
|
|
"",
|
|
"",
|
|
// NIGHT
|
|
"SOUNDS\\SSA\\rotating radar dish.wav",
|
|
"",
|
|
"",
|
|
"",
|
|
// WASTE LAND
|
|
// DAY
|
|
"SOUNDS\\SSA\\gentle_wind.wav",
|
|
"",
|
|
"",
|
|
"",
|
|
// NIGHT
|
|
"SOUNDS\\SSA\\insects_at_night_04.wav",
|
|
"",
|
|
"",
|
|
"",
|
|
// UNDERGROUND
|
|
// DAY
|
|
"SOUNDS\\SSA\\low ominous ambience.wav",
|
|
"",
|
|
"",
|
|
"",
|
|
// NIGHT
|
|
"SOUNDS\\SSA\\low ominous ambience.wav",
|
|
"",
|
|
"",
|
|
"",
|
|
// OCEAN
|
|
// DAY
|
|
"SOUNDS\\SSA\\sea_01a.wav",
|
|
"SOUNDS\\SSA\\sea_01b.wav",
|
|
"SOUNDS\\SSA\\sea_01c.wav",
|
|
"SOUNDS\\SSA\\sea_01d.wav",
|
|
// NIGHT
|
|
"SOUNDS\\SSA\\ocean_waves_01a.wav",
|
|
"SOUNDS\\SSA\\ocean_waves_01b.wav",
|
|
"SOUNDS\\SSA\\ocean_waves_01c.wav",
|
|
"SOUNDS\\SSA\\ocean_waves_01d.wav",
|
|
};
|
|
|
|
|
|
BOOLEAN LoadAmbientControlFile( UINT8 ubAmbientID )
|
|
{
|
|
SGPFILENAME zFilename;
|
|
HWFILE hFile;
|
|
INT32 cnt;
|
|
|
|
|
|
|
|
// BUILD FILENAME
|
|
sprintf( zFilename, "AMBIENT\\%d.bad", ubAmbientID );
|
|
|
|
// OPEN, LOAD
|
|
hFile = FileOpen( zFilename, FILE_ACCESS_READ, FALSE);
|
|
if ( !hFile )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// READ #
|
|
if( !FileRead( hFile, &gsNumAmbData, sizeof( INT16 ), NULL ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// LOOP FOR OTHERS
|
|
for ( cnt = 0; cnt < gsNumAmbData; cnt++ )
|
|
{
|
|
if( !FileRead( hFile, &(gAmbData[ cnt ]), sizeof( AMBIENTDATA_STRUCT ), NULL ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
sprintf( zFilename, "AMBIENT\\%s", gAmbData[ cnt ].zFilename );
|
|
strcpy( gAmbData[ cnt ].zFilename, zFilename );
|
|
}
|
|
|
|
FileClose( hFile );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
void GetAmbientDataPtr( AMBIENTDATA_STRUCT **ppAmbData, UINT16 *pusNumData )
|
|
{
|
|
*ppAmbData = gAmbData;
|
|
*pusNumData = gsNumAmbData;
|
|
}
|
|
|
|
|
|
void StopAmbients( )
|
|
{
|
|
SoundStopAllRandom( );
|
|
}
|
|
|
|
void HandleNewSectorAmbience( UINT8 ubAmbientID )
|
|
{
|
|
// OK, we could have just loaded a sector, erase all ambient sounds from queue, shutdown all ambient groupings
|
|
SoundStopAllRandom( );
|
|
|
|
DeleteAllStrategicEventsOfType( EVENT_AMBIENT );
|
|
|
|
if( !gfBasement && !gfCaves )
|
|
{
|
|
if( LoadAmbientControlFile( ubAmbientID ) )
|
|
{
|
|
// OK, load them up!
|
|
BuildDayAmbientSounds( );
|
|
}
|
|
else
|
|
{
|
|
DebugMsg(TOPIC_JA2, DBG_LEVEL_0, String("Cannot load Ambient data for tileset" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeleteAllAmbients()
|
|
{
|
|
// JA2Gold: it seems that ambient sounds don't get unloaded when we exit a sector!?
|
|
SoundStopAllRandom();
|
|
DeleteAllStrategicEventsOfType( EVENT_AMBIENT );
|
|
}
|
|
|
|
UINT32 SetupNewAmbientSound( UINT32 uiAmbientID )
|
|
{
|
|
RANDOMPARMS rpParms;
|
|
|
|
//SoundLog((CHAR8 *)String(" SetupNewAmbientSound()1: uiAmbientID: '%d'", uiAmbientID ) );
|
|
|
|
memset(&rpParms, 0xff, sizeof(RANDOMPARMS));
|
|
|
|
rpParms.uiTimeMin = gAmbData[ uiAmbientID ].uiMinTime;
|
|
rpParms.uiTimeMax = gAmbData[ uiAmbientID ].uiMaxTime;
|
|
rpParms.uiVolMin = CalculateSoundEffectsVolume( gAmbData[ uiAmbientID ].uiVol );
|
|
rpParms.uiVolMax = CalculateSoundEffectsVolume( gAmbData[ uiAmbientID ].uiVol );
|
|
rpParms.uiPriority = GROUP_AMBIENT;
|
|
|
|
//SoundLog((CHAR8 *)String(" SetupNewAmbientSound()2: gAmbData[ uiAmbientID ].zFilename: '%s', Params: '%s'", gAmbData[ uiAmbientID ].zFilename, &rpParms ) );
|
|
|
|
return SoundPlayRandom( gAmbData[ uiAmbientID ].zFilename, &rpParms ); //bug Nr14
|
|
}
|
|
|
|
|
|
UINT32 StartSteadyStateAmbient( UINT32 ubVolume, UINT32 ubLoops)
|
|
{
|
|
SOUNDPARMS spParms;
|
|
|
|
memset(&spParms, 0xff, sizeof(SOUNDPARMS));
|
|
|
|
spParms.uiVolume = CalculateSoundEffectsVolume( ubVolume );
|
|
spParms.uiLoop = ubLoops;
|
|
spParms.uiPriority=GROUP_AMBIENT;
|
|
|
|
return(SoundPlay(gSteadyStateAmbientTable[gubCurrentSteadyStateAmbience].zSoundNames[gubCurrentSteadyStateSound], &spParms));
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN SetSteadyStateAmbience(UINT8 ubAmbience)
|
|
{
|
|
BOOLEAN fInNight = FALSE;
|
|
INT32 cnt;
|
|
UINT8 ubNumSounds = 0;
|
|
UINT8 ubChosenSound;
|
|
|
|
// Stop all ambients...
|
|
if (guiCurrentSteadyStateSoundHandle != NO_SAMPLE)
|
|
{
|
|
SoundStop(guiCurrentSteadyStateSoundHandle);
|
|
guiCurrentSteadyStateSoundHandle = NO_SAMPLE;
|
|
}
|
|
|
|
// Determine what time of day we are in ( day/night)
|
|
if (gubEnvLightValue >= LIGHT_DUSK_CUTOFF)
|
|
{
|
|
fInNight = TRUE;
|
|
}
|
|
|
|
// loop through listing to get num sounds...
|
|
// sevenfm: bugfix for night ambients
|
|
for (cnt = fInNight * 4; cnt < fInNight * 4 + NUM_SOUNDS_PER_TIMEFRAME / 2; cnt++)
|
|
//for (cnt = (fInNight * 4); cnt < (NUM_SOUNDS_PER_TIMEFRAME / 2); cnt++)
|
|
{
|
|
if (gSteadyStateAmbientTable[ubAmbience].zSoundNames[cnt][0] == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
ubNumSounds++;
|
|
}
|
|
|
|
if (ubNumSounds == 0)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
// Pick one
|
|
ubChosenSound = (UINT8)Random(ubNumSounds);
|
|
|
|
// Set!
|
|
gubCurrentSteadyStateAmbience = ubAmbience;
|
|
gubCurrentSteadyStateSound = ubChosenSound;
|
|
|
|
guiCurrentSteadyStateSoundHandle = StartSteadyStateAmbient(LOWVOLUME, 0);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
void UpdateFireAmbient(void)
|
|
{
|
|
INT32 iVolume;
|
|
UINT32 uiClock;
|
|
|
|
if (!gGameExternalOptions.fEnableTA)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (guiCurrentScreen != GAME_SCREEN)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uiClock = GetJA2Clock();
|
|
|
|
if (uiClock - guiFireAmbientLastUpdate < 50)
|
|
{
|
|
return;
|
|
}
|
|
|
|
guiFireAmbientLastUpdate = uiClock;
|
|
|
|
if (FindVisibleSmokeEffect(BURNABLEGAS_SMOKE_EFFECT))
|
|
{
|
|
gubAmbientFutureFireVolume = CalculateSoundEffectsVolume(gGameExternalOptions.ubVolumeTA);
|
|
|
|
if (guiAmbientFire == NO_SAMPLE)
|
|
{
|
|
StartFireAmbient();
|
|
}
|
|
|
|
// check if successfully started
|
|
if (guiAmbientFire != NO_SAMPLE)
|
|
{
|
|
iVolume = SoundGetVolume(guiAmbientFire);
|
|
|
|
if (iVolume != gubAmbientFutureFireVolume)
|
|
{
|
|
// increase volume until it reaches desired level
|
|
iVolume = min((INT32)gubAmbientFutureFireVolume, iVolume + 4);
|
|
SoundSetVolume(guiAmbientFire, iVolume);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gubAmbientFutureFireVolume = 0;
|
|
|
|
// check if ambient sound is playing
|
|
if (guiAmbientFire != NO_SAMPLE)
|
|
{
|
|
iVolume = SoundGetVolume(guiAmbientFire);
|
|
|
|
if (iVolume != gubAmbientFutureFireVolume)
|
|
{
|
|
// increase volume until it reaches desired level
|
|
iVolume = max((INT32)gubAmbientFutureFireVolume, iVolume - 4);
|
|
SoundSetVolume(guiAmbientFire, iVolume);
|
|
}
|
|
|
|
if (iVolume == 0)
|
|
{
|
|
StopFireAmbient();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StopFireAmbient(void)
|
|
{
|
|
if (guiAmbientFire != NO_SAMPLE)
|
|
{
|
|
SoundStop(guiAmbientFire);
|
|
guiAmbientFire = NO_SAMPLE;
|
|
}
|
|
}
|
|
|
|
void StartFireAmbient(void)
|
|
{
|
|
CHAR8 filename[1024];
|
|
SOUNDPARMS spParms;
|
|
|
|
// Stop ambient
|
|
if (guiAmbientFire != NO_SAMPLE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
strcpy(filename, "Ambient\\fire.ogg");
|
|
//gubAmbientFireVolume = LOWVOLUME;
|
|
|
|
// start sound
|
|
memset(&spParms, 0xff, sizeof(SOUNDPARMS));
|
|
//spParms.uiVolume = CalculateSoundEffectsVolume( LOWVOLUME );
|
|
spParms.uiVolume = 0;
|
|
spParms.uiLoop = 0;
|
|
spParms.uiPriority = GROUP_AMBIENT;
|
|
|
|
//guiAmbientFire = SoundPlay( zFileName, &spParms );
|
|
guiAmbientFire = SoundPlayStreamedFile(filename, &spParms);
|
|
}
|
|
|
|
#define MAX_SSA_SOUNDS 10
|
|
extern BOOLEAN AreInMeanwhile();
|
|
|
|
void SetSSA(void)
|
|
{
|
|
BOOLEAN fNight = FALSE;
|
|
BOOLEAN fCombat = FALSE;
|
|
UINT8 ubNumSounds = 0;
|
|
UINT8 ubChosenSound;
|
|
CHAR8 filename[1024];
|
|
CHAR16 name16[1024];
|
|
CHAR8 SectorName[1024];
|
|
CHAR8 TownName[1024];
|
|
CHAR8 GenericName[1024];
|
|
CHAR8 UnderGround[1024];
|
|
BOOLEAN fUnderground = FALSE;
|
|
SGPFILENAME zFileName;
|
|
UINT8 ubSectorID;
|
|
SOUNDPARMS spParms;
|
|
|
|
SECTORINFO *pSector = NULL;
|
|
//UNDERGROUND_SECTORINFO *pUnderground;
|
|
//CHAR16 zString[1024];
|
|
UINT16 usTownSectorIndex;
|
|
BOOLEAN fFoundSAM = FALSE;
|
|
UINT8 ubMineIndex;
|
|
//MINE_STATUS_TYPE *pMineStatus;
|
|
|
|
memset(TownName, 0, 1024 * sizeof(char));
|
|
memset(name16, 0, 1024 * sizeof(wchar_t));
|
|
|
|
// Stop all ambients...
|
|
if (guiCurrentSteadyStateSoundHandle != NO_SAMPLE)
|
|
{
|
|
SoundStop(guiCurrentSteadyStateSoundHandle);
|
|
guiCurrentSteadyStateSoundHandle = NO_SAMPLE;
|
|
}
|
|
|
|
if (!gGameExternalOptions.fEnableSSA)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// no ambients in the rain
|
|
if (GetWeatherInCurrentSector() != WEATHER_FORECAST_NORMAL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// no ambients in cutscenes
|
|
if(AreInMeanwhile())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Determine what time of day we are in ( day/night)
|
|
if (gubEnvLightValue >= LIGHT_DUSK_CUTOFF)
|
|
{
|
|
fNight = TRUE;
|
|
}
|
|
|
|
// determine combat state
|
|
if( gTacticalStatus.uiFlags & INCOMBAT)// || NumCapableEnemyInSector( ) || HostileZombiesPresent() )
|
|
{
|
|
fCombat = TRUE;
|
|
}
|
|
|
|
// determine sector name
|
|
UINT8 ubTownID = GetTownIdForSector(gWorldSectorX, gWorldSectorY);
|
|
|
|
if (ubTownID != BLANK_SECTOR && gbWorldSectorZ == 0)
|
|
{
|
|
//wcstombs(TownName, pTownNames[ubTownID], wcslen(pTownNames[ubTownID])+1);
|
|
wcstombs(TownName, pTownNames[ubTownID], 1024 - 1);
|
|
//ScreenMsg(FONT_ORANGE, MSG_INTERFACE, L"%s", pTownNames[ubTownID]);
|
|
}
|
|
|
|
// check sector file
|
|
sprintf(SectorName, "%s%s", pVertStrings[gWorldSectorY], pHortStrings[gWorldSectorX]);
|
|
|
|
// determine underground
|
|
if (gbWorldSectorZ > 0)
|
|
{
|
|
fUnderground = TRUE;
|
|
}
|
|
|
|
// determine town name
|
|
// check town file
|
|
|
|
// determine generic name
|
|
// check generic file
|
|
|
|
// prepare name
|
|
strcpy(filename, "Ambient\\SSA\\");
|
|
strcat(filename, SectorName);
|
|
if (fUnderground)
|
|
{
|
|
sprintf(UnderGround, "u%d", gbWorldSectorZ + 1);
|
|
strcat(filename, UnderGround);
|
|
}
|
|
strcat(filename, "_");
|
|
if (!fUnderground)
|
|
{
|
|
if (fNight)
|
|
strcat(filename, "night_");
|
|
else
|
|
strcat(filename, "day_");
|
|
}
|
|
|
|
// find number of files
|
|
ubNumSounds = 0;
|
|
for (UINT8 i = 1; i <= MAX_SSA_SOUNDS; i++)
|
|
{
|
|
sprintf(zFileName, "%s%d.ogg", filename, i);
|
|
|
|
if (!FileExists(zFileName))
|
|
break;
|
|
else
|
|
ubNumSounds++;
|
|
}
|
|
|
|
// check town name
|
|
if (ubNumSounds == 0 && !fUnderground && ubTownID != BLANK_SECTOR)
|
|
{
|
|
// prepare name
|
|
strcpy(filename, "Ambient\\SSA\\");
|
|
strcat(filename, TownName);
|
|
strcat(filename, "_");
|
|
if (fNight)
|
|
strcat(filename, "night_");
|
|
else
|
|
strcat(filename, "day_");
|
|
|
|
// find number of files
|
|
ubNumSounds = 0;
|
|
for (UINT8 i = 1; i <= MAX_SSA_SOUNDS; i++)
|
|
{
|
|
sprintf(zFileName, "%s%d.ogg", filename, i);
|
|
|
|
if (!FileExists(zFileName))
|
|
break;
|
|
else
|
|
ubNumSounds++;
|
|
}
|
|
}
|
|
|
|
// check generic name
|
|
if (ubNumSounds == 0)
|
|
{
|
|
ubSectorID = SECTOR(gWorldSectorX, gWorldSectorY);
|
|
|
|
// underground sectors
|
|
if (fUnderground)
|
|
{
|
|
strcpy(GenericName, "");
|
|
|
|
for (ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++)
|
|
{
|
|
// pMineStatus = &(gMineStatus[ ubMineIndex ]);
|
|
if (gMineStatus[ubMineIndex].sSectorX == gWorldSectorX && gMineStatus[ubMineIndex].sSectorY == gWorldSectorY)
|
|
{
|
|
if (gMineStatus[ubMineIndex].fEmpty)
|
|
{
|
|
strcpy(GenericName, "EmptyMine");
|
|
}
|
|
else
|
|
{
|
|
strcpy(GenericName, "Mine");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (ubTownID != BLANK_SECTOR)
|
|
{
|
|
// always use town if defined
|
|
strcpy(GenericName, "Town");
|
|
}
|
|
else
|
|
{
|
|
usTownSectorIndex = SECTOR(gWorldSectorX, gWorldSectorY);
|
|
|
|
// Test for known SAM Site at this location
|
|
for (UINT16 x = 0; x < MAX_NUMBER_OF_SAMS; x++)
|
|
{
|
|
if (pSamList[x] == usTownSectorIndex) // && fSamSiteFound[ x ]
|
|
{
|
|
fFoundSAM = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (fFoundSAM)
|
|
{
|
|
strcpy(GenericName, "SAM");
|
|
}
|
|
else
|
|
{
|
|
// make generic name from <Here> movement type in MovementCosts.xml
|
|
switch (SectorInfo[ubSectorID].ubTraversability[THROUGH_STRATEGIC_MOVE])
|
|
{
|
|
case TOWN:
|
|
strcpy(GenericName, "Town");
|
|
break;
|
|
case SAND:
|
|
case SAND_ROAD:
|
|
strcpy(GenericName, "Desert");
|
|
break;
|
|
case FARMLAND:
|
|
case FARMLAND_ROAD:
|
|
strcpy(GenericName, "Farmland");
|
|
break;
|
|
case PLAINS:
|
|
case PLAINS_ROAD:
|
|
case ROAD:
|
|
strcpy(GenericName, "Plains");
|
|
break;
|
|
break;
|
|
case HILLS:
|
|
case HILLS_ROAD:
|
|
strcpy(GenericName, "Hills");
|
|
break;
|
|
case SPARSE:
|
|
case SPARSE_ROAD:
|
|
case DENSE:
|
|
case DENSE_ROAD:
|
|
strcpy(GenericName, "Forest");
|
|
break;
|
|
case SWAMP:
|
|
case SWAMP_ROAD:
|
|
strcpy(GenericName, "Swamp");
|
|
break;
|
|
case TROPICS:
|
|
case TROPICS_ROAD:
|
|
strcpy(GenericName, "Tropical");
|
|
break;
|
|
case WATER:
|
|
strcpy(GenericName, "Water");
|
|
break;
|
|
case NS_RIVER:
|
|
case EW_RIVER:
|
|
strcpy(GenericName, "River");
|
|
break;
|
|
case COASTAL:
|
|
case COASTAL_ROAD:
|
|
strcpy(GenericName, "Coastal");
|
|
break;
|
|
default:
|
|
strcpy(GenericName, "");
|
|
}
|
|
}
|
|
}
|
|
|
|
// prepare name
|
|
strcpy(filename, "Ambient\\SSA\\");
|
|
strcat(filename, GenericName);
|
|
strcat(filename, "_");
|
|
if (!fUnderground)
|
|
{
|
|
if (fNight)
|
|
strcat(filename, "night_");
|
|
else
|
|
strcat(filename, "day_");
|
|
}
|
|
|
|
// find number of files
|
|
ubNumSounds = 0;
|
|
for (UINT8 i = 1; i <= MAX_SSA_SOUNDS; i++)
|
|
{
|
|
sprintf(zFileName, "%s%d.ogg", filename, i);
|
|
|
|
if (!FileExists(zFileName))
|
|
break;
|
|
else
|
|
ubNumSounds++;
|
|
}
|
|
}
|
|
|
|
if (ubNumSounds == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// pick random file
|
|
ubChosenSound = (guiHour % ubNumSounds) + 1;
|
|
//ubChosenSound = Random(ubNumSounds) + 1;
|
|
|
|
// make a file name
|
|
sprintf(zFileName, "%s%d.ogg", filename, ubChosenSound);
|
|
|
|
// start sound
|
|
memset(&spParms, 0xff, sizeof(SOUNDPARMS));
|
|
//spParms.uiVolume = CalculateSoundEffectsVolume( LOWVOLUME );
|
|
spParms.uiVolume = CalculateSoundEffectsVolume(gGameExternalOptions.ubVolumeSSA);
|
|
spParms.uiLoop = 0;
|
|
spParms.uiPriority = GROUP_AMBIENT;
|
|
|
|
//guiCurrentSteadyStateSoundHandle = SoundPlay( zFileName, &spParms );
|
|
guiCurrentSteadyStateSoundHandle = SoundPlayStreamedFile(zFileName, &spParms);
|
|
}
|