11#include "city.h"
22
3+ #include "graphics/window.h"
4+
35#include "building/properties.h"
46#include "city/figures.h"
7+ #include "city/population.h"
58#include "core/file.h"
69#include "core/random.h"
710#include "core/time.h"
1316#define SOUND_VIEWS_THRESHOLD 200
1417#define SOUND_DELAY_MILLIS 30000
1518#define SOUND_PLAY_INTERVAL_MILLIS 2000
19+ #define AMBIENT_PLAY_INTERVAL_MILLIS 5000
1620
1721typedef enum {
1822 SOUND_AMBIENT_NONE = 0 ,
@@ -22,6 +26,7 @@ typedef enum {
2226 SOUND_AMBIENT_EMPTY_LAND3 , // SOUND_AMBIENT_RIVER,
2327 SOUND_AMBIENT_EMPTY_TERRAIN01 ,
2428 SOUND_AMBIENT_EMPTY_TERRAIN02 ,
29+ SOUND_AMBIENT_EMPTY_LAND ,
2530 SOUND_AMBIENT_MAX
2631} sound_ambient_type ;
2732
@@ -43,6 +48,7 @@ static struct {
4348 background_sound city_sounds [SOUND_CITY_MAX ];
4449 background_sound ambient_sounds [SOUND_AMBIENT_MAX ];
4550 time_millis last_update_time ;
51+ time_millis ambient_last_played_time ;
4652} data = {
4753 .city_sounds = {
4854 [SOUND_CITY_HOUSE_SLUM ] = { .filenames .total = 8 , .filenames .list = (sound_filenames []) { "wavs/house_slum1.wav" , "wavs/house_slum2.wav" , "wavs/house_slum3.wav" , "wavs/house_slum4.wav" , "wavs/house_poor1.wav" , "wavs/house_poor2.wav" , "wavs/house_poor3.wav" , "wavs/house_poor4.wav" } },
@@ -61,7 +67,7 @@ static struct {
6167 [SOUND_CITY_GARDEN ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/gardens1.wav" } },
6268 [SOUND_CITY_CLINIC ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/clinic.wav" } },
6369 [SOUND_CITY_HOSPITAL ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/hospital.wav" } },
64- [SOUND_CITY_BATHHOUSE ] = { .filenames .total = 2 , .filenames .list = (sound_filenames []) { "wavs/baths.wav" , "wavs/aquaduct .wav" } },
70+ [SOUND_CITY_BATHHOUSE ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/baths.wav" } },
6571 [SOUND_CITY_BARBER ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/barber.wav" } },
6672 [SOUND_CITY_SCHOOL ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/school.wav" } },
6773 [SOUND_CITY_ACADEMY ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/academy.wav" } },
@@ -92,7 +98,7 @@ static struct {
9298 [SOUND_CITY_FORUM ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/forum.wav" } },
9399 [SOUND_CITY_RESERVOIR ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/resevoir.wav" } },
94100 [SOUND_CITY_FOUNTAIN ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/fountain.wav" } },
95- [SOUND_CITY_WELL ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/well1 .wav" } },
101+ [SOUND_CITY_WELL ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/well .wav" } },
96102 [SOUND_CITY_MILITARY_ACADEMY ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/mil_acad.wav" } },
97103 [SOUND_CITY_BARRACKS ] = { .filenames .total = 2 , .filenames .list = (sound_filenames []) { "wavs/barracks.wav" , "wavs/marching.wav" } },
98104 [SOUND_CITY_ORACLE ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/oracle.wav" } },
@@ -119,14 +125,18 @@ static struct {
119125 [SOUND_CITY_DEPOT ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/Ox.ogg" } },
120126 [SOUND_CITY_CONCRETE_MAKER ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/ConcreteMaker.ogg" } },
121127 [SOUND_CITY_CONSTRUCTION_SITE ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/Engineer.ogg" } },
122- [SOUND_CITY_NATIVE_HUT ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/NativeHut.ogg" } }
128+ [SOUND_CITY_NATIVE_HUT ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/NativeHut.ogg" } },
129+ [SOUND_CITY_AQUEDUCT ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/aquaduct.wav" } },
130+ [SOUND_CITY_ARENA ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/colloseum.wav" } }, //Dummy. If a separate sound appears, place it in the ASSETS_DIRECTORY
131+ [SOUND_CITY_NATIVE_DECORATION ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/park.wav" } },
123132 },
124133 .ambient_sounds = {
125- [SOUND_AMBIENT_EMPTY_LAND1 ] = {.filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/empty_land1.wav" } },
126- [SOUND_AMBIENT_EMPTY_LAND2 ] = {.filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/empty_land2.wav" } },
127- [SOUND_AMBIENT_EMPTY_LAND3 ] = {.filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/empty_land3.wav" } },
128- [SOUND_AMBIENT_EMPTY_TERRAIN01 ] = {.filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/Terrain01.ogg" } },
129- [SOUND_AMBIENT_EMPTY_TERRAIN02 ] = {.filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/Terrain02.ogg" } }
134+ [SOUND_AMBIENT_EMPTY_LAND1 ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/empty_land1.wav" } },
135+ [SOUND_AMBIENT_EMPTY_LAND2 ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/empty_land2.wav" } },
136+ [SOUND_AMBIENT_EMPTY_LAND3 ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/empty_land3.wav" } },
137+ [SOUND_AMBIENT_EMPTY_TERRAIN01 ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/Terrain01.ogg" } },
138+ [SOUND_AMBIENT_EMPTY_TERRAIN02 ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { ASSETS_DIRECTORY "/Sounds/Terrain02.ogg" } },
139+ [SOUND_AMBIENT_EMPTY_LAND ] = { .filenames .total = 1 , .filenames .list = (sound_filenames []) { "wavs/empty_land.wav" } },
130140 }
131141};
132142
@@ -156,19 +166,59 @@ void sound_city_set_volume(int percentage)
156166 sound_device_set_volume_for_type (SOUND_TYPE_CITY , percentage );
157167}
158168
159- void sound_city_mark_building_view (building_type type , int num_workers , int direction )
169+ void sound_city_mark_building_view (building_type type , int num_workers , int direction , int has_water_access )
160170{
161171 sound_city_type sound = building_properties_for_type (type )-> sound_id ;
162172
163173 if (sound == SOUND_CITY_NONE ) {
164174 return ;
165175 }
166- if (type == BUILDING_THEATER || type == BUILDING_AMPHITHEATER ||
167- type == BUILDING_GLADIATOR_SCHOOL || type == BUILDING_HIPPODROME ) {
168- // entertainment is shut off when caesar invades
169- if (num_workers <= 0 || city_figures_imperial_soldiers () > 0 ) {
170- return ;
171- }
176+ const model_building * model = model_get_building (type );
177+ int enemies_present = city_figures_enemies () > 0 || city_figures_imperial_soldiers () > 0 ;
178+
179+ // Buildings for which sound is disabled during enemy attacks
180+ int mute_on_enemies = 0 ;
181+ int always_play = 0 ;
182+ switch (type ) {
183+ case BUILDING_BATHHOUSE :
184+ case BUILDING_SCHOOL :
185+ case BUILDING_THEATER :
186+ case BUILDING_AMPHITHEATER :
187+ case BUILDING_ARENA :
188+ case BUILDING_COLOSSEUM :
189+ case BUILDING_HIPPODROME :
190+ case BUILDING_ACTOR_COLONY :
191+ case BUILDING_GLADIATOR_SCHOOL :
192+ case BUILDING_CHARIOT_MAKER :
193+ case BUILDING_GOVERNORS_HOUSE :
194+ case BUILDING_GOVERNORS_VILLA :
195+ case BUILDING_GOVERNORS_PALACE :
196+ mute_on_enemies = 1 ;
197+ break ;
198+ // Buildings that always produce sound
199+ case BUILDING_NATIVE_HUT :
200+ case BUILDING_NATIVE_MEETING :
201+ case BUILDING_NATIVE_CROPS :
202+ case BUILDING_NATIVE_WATCHTOWER :
203+ case BUILDING_NATIVE_MONUMENT :
204+ case BUILDING_NATIVE_DECORATION :
205+ always_play = 1 ;
206+ break ;
207+ default :
208+ break ;
209+ }
210+ // Mute building sounds when there is no access to water
211+ if ((type == BUILDING_BATHHOUSE || type == BUILDING_CONCRETE_MAKER || type == BUILDING_FOUNTAIN ||
212+ type == BUILDING_LARGE_STATUE || type == BUILDING_SMALL_POND || type == BUILDING_LARGE_POND ) &&
213+ !has_water_access ) {
214+ return ;
215+ }
216+
217+ // Shut off when:
218+ if (!always_play && ((model -> laborers > 0 && num_workers <= 0 )
219+ || city_population () <= 0
220+ || (enemies_present && mute_on_enemies ))) {
221+ return ;
172222 }
173223
174224 data .city_sounds [sound ].available = 1 ;
@@ -247,41 +297,35 @@ static void play_sound(background_sound *sound, int direction)
247297 setting_sound (SOUND_TYPE_CITY )-> volume , left_pan , right_pan , 0 );
248298}
249299
250- void sound_city_play (void )
300+ static void sound_city_play_city (void )
251301{
252302 time_millis now = time_get_millis ();
303+
304+ if (now - data .last_update_time < SOUND_PLAY_INTERVAL_MILLIS ) {
305+ // Only play 1 sound every 2 seconds
306+ return ;
307+ }
308+
253309 time_millis max_delay = 0 ;
254310 background_sound * sound_to_play = 0 ;
255311 for (sound_city_type sound = SOUND_CITY_FIRST ; sound < SOUND_CITY_MAX ; sound ++ ) {
256312 background_sound * current_sound = & data .city_sounds [sound ];
257- if (current_sound -> available ) {
258- current_sound -> available = 0 ;
259- if (current_sound -> total_views >= SOUND_VIEWS_THRESHOLD ) {
260- if (now - current_sound -> last_played_time >= SOUND_DELAY_MILLIS ) {
261- if (now - current_sound -> last_played_time > max_delay ) {
262- max_delay = now - current_sound -> last_played_time ;
263- sound_to_play = current_sound ;
264- }
265- }
266- }
267- } else {
268- current_sound -> total_views = 0 ;
269- for (int d = 0 ; d < 5 ; d ++ ) {
270- current_sound -> direction_views [d ] = 0 ;
313+ if (!current_sound -> available ) {
314+ continue ;
315+ }
316+ current_sound -> available = 0 ;
317+ if (current_sound -> total_views >= SOUND_VIEWS_THRESHOLD &&
318+ now - current_sound -> last_played_time >= SOUND_DELAY_MILLIS ) {
319+ if (now - current_sound -> last_played_time > max_delay ) {
320+ max_delay = now - current_sound -> last_played_time ;
321+ sound_to_play = current_sound ;
271322 }
272323 }
273324 }
274325
275- if (now - data .last_update_time < SOUND_PLAY_INTERVAL_MILLIS ) {
276- // Only play 1 sound every 2 seconds
277- return ;
278- }
279-
280326 if (!sound_to_play ) {
281- // progress_ambient();
282327 return ;
283328 }
284-
285329 // always only one channel available... use it
286330 int direction ;
287331 if (sound_to_play -> direction_views [SOUND_DIRECTION_CENTER ] > 10 ) {
@@ -295,10 +339,62 @@ void sound_city_play(void)
295339 }
296340
297341 play_sound (sound_to_play , direction );
342+ sound_to_play -> last_played_time = now ;
343+ sound_to_play -> total_views = 0 ;
344+ for (int d = 0 ; d < 5 ; d ++ ) {
345+ sound_to_play -> direction_views [d ] = 0 ;
346+ }
298347 data .last_update_time = now ;
348+ }
349+
350+ static void sound_city_play_ambient (void )
351+ {
352+ if (!window_is (WINDOW_CITY )) {
353+ return ;
354+ }
355+
356+ time_millis now = time_get_millis ();
357+
358+ // Skip if ambient interval not reached or too soon after a city sound
359+ if (now - data .ambient_last_played_time < AMBIENT_PLAY_INTERVAL_MILLIS * 2 ) {
360+ return ;
361+ }
362+ if (now - data .last_update_time < SOUND_PLAY_INTERVAL_MILLIS ) {
363+ return ;
364+ }
365+
366+ sound_city_progress_ambient ();
367+ time_millis max_delay = 0 ;
368+ background_sound * sound_to_play = 0 ;
369+ for (sound_ambient_type sound = SOUND_AMBIENT_FIRST ; sound < SOUND_AMBIENT_MAX ; sound ++ ) {
370+ background_sound * current_sound = & data .ambient_sounds [sound ];
371+ if (!current_sound -> available ) {
372+ continue ;
373+ }
374+
375+ if (now - current_sound -> last_played_time >= AMBIENT_PLAY_INTERVAL_MILLIS ) {
376+ if (now - current_sound -> last_played_time > max_delay ) {
377+ max_delay = now - current_sound -> last_played_time ;
378+ sound_to_play = current_sound ;
379+ }
380+ }
381+ }
382+
383+ if (!sound_to_play ) {
384+ return ;
385+ }
386+
387+ play_sound (sound_to_play , SOUND_DIRECTION_CENTER );
299388 sound_to_play -> last_played_time = now ;
300389 sound_to_play -> total_views = 0 ;
301390 for (int d = 0 ; d < 5 ; d ++ ) {
302391 sound_to_play -> direction_views [d ] = 0 ;
303392 }
393+ data .ambient_last_played_time = now ;
394+ }
395+
396+ void sound_city_play (void )
397+ {
398+ sound_city_play_city ();
399+ sound_city_play_ambient ();
304400}
0 commit comments