… | |
… | |
217 | my ($face) = @_; |
217 | my ($face) = @_; |
218 | |
218 | |
219 | $CFG->{effects_enable} |
219 | $CFG->{effects_enable} |
220 | or return; |
220 | or return; |
221 | |
221 | |
|
|
222 | $AUDIO_PLAY{$face} |
|
|
223 | or return; |
|
|
224 | |
222 | if (my $chunk = $AUDIO_CHUNK{$face}) { |
225 | if (my $chunk = $AUDIO_CHUNK{$face}) { |
223 | for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) { |
226 | for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) { |
224 | my (undef, $dx, $dy, $vol) = @$_; |
227 | my (undef, $dx, $dy, $vol) = @$_; |
225 | |
228 | |
226 | my $channel = CFPlus::Channel::find; |
229 | my $channel = CFPlus::Channel::find; |
227 | $channel->volume ($vol * $CFG->{effects_volume} * 128 / 255); |
230 | $channel->volume ($vol * $CFG->{effects_volume} * 128 / 255); |
228 | $dx = $dx / 10 * 255; |
|
|
229 | $channel->set_panning (255 - $dx, 255 + $dx); |
|
|
230 | |
|
|
231 | # my $angle = $dx ? : $dx < 0 ? |
|
|
232 | # my $distance = -$vol; |
|
|
233 | # $channel->set_position ($angle, $distance); |
231 | $channel->set_position_r ($dx, $dy, 20); |
234 | |
|
|
235 | $chunk->play ($channel); |
232 | $chunk->play ($channel); |
236 | } |
233 | } |
237 | } else { |
234 | } else { |
238 | # sound_meta not set means data is in flight either way |
235 | # sound_meta not set means data is in flight either way |
239 | my $meta = $CONN->{sound_meta}{$face} |
236 | my $meta = $CONN->{sound_meta}{$face} |
240 | or return; |
237 | or return; |
241 | |
238 | |
242 | # if its a jingle, play it as ambient music |
239 | # if its a jingle, play it as ambient music |
243 | if ($meta->{meta}{jingle}) { |
240 | if ($meta->{meta}{jingle}) { |
244 | delete $AUDIO_PLAY{$face}; # take the jingle out of the sound queue |
241 | if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue |
245 | push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue |
242 | push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue |
246 | &audio_music_push ($face); |
243 | &audio_music_push ($face); |
|
|
244 | } |
247 | } else { |
245 | } else { |
248 | # fetch from database |
246 | # fetch from database |
249 | CFPlus::DB::get res_data => $meta->{name}, sub { |
247 | CFPlus::DB::get res_data => $meta->{name}, sub { |
250 | my $rwops = new CFPlus::RW $_[0]; |
248 | my $rwops = new CFPlus::RW $_[0]; |
251 | my $chunk = new CFPlus::MixChunk $rwops; |
249 | my $chunk = new CFPlus::MixChunk $rwops |
|
|
250 | or Carp::confess "sound face " . (JSON::XS::to_json $meta) . " unloadable: " . CFPlus::Mix_GetError; |
252 | $chunk->volume (($meta->{meta}{volume} || 1) * 128); |
251 | $chunk->volume (($meta->{meta}{volume} || 1) * 128); |
253 | $AUDIO_CHUNK{$face} = $chunk; |
252 | $AUDIO_CHUNK{$face} = $chunk; |
254 | |
253 | |
255 | audio_sound_push ($face); |
254 | audio_sound_push ($face); |
256 | }; |
255 | }; |
… | |
… | |
308 | my $rwops = $meta->{path} |
307 | my $rwops = $meta->{path} |
309 | ? new_from_file CFPlus::RW $meta->{path} |
308 | ? new_from_file CFPlus::RW $meta->{path} |
310 | : new CFPlus::RW $$MUSIC_PLAYING_DATA; |
309 | : new CFPlus::RW $$MUSIC_PLAYING_DATA; |
311 | |
310 | |
312 | $MUSIC_PLAYER = new CFPlus::MixMusic $rwops |
311 | $MUSIC_PLAYER = new CFPlus::MixMusic $rwops |
313 | or ((warn CFPlus::Mix_GetError), return); # pretty fatal error |
312 | or Carp::confess "music face $meta->{face} unloadable: " . CFPlus::Mix_GetError; |
314 | |
313 | |
315 | my $NOW = time; |
314 | my $NOW = time; |
316 | |
315 | |
317 | if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) { |
316 | if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) { |
318 | my $pos = $MUSIC_PLAYING_META->{stop_pos}; |
317 | my $pos = $MUSIC_PLAYING_META->{stop_pos}; |
… | |
… | |
417 | |
416 | |
418 | sub audio_shutdown { |
417 | sub audio_shutdown { |
419 | undef $MUSIC_PLAYER; |
418 | undef $MUSIC_PLAYER; |
420 | undef $MUSIC_PLAYING_META; |
419 | undef $MUSIC_PLAYING_META; |
421 | undef $MUSIC_PLAYING_DATA; |
420 | undef $MUSIC_PLAYING_DATA; |
422 | |
|
|
423 | audio_music_set_meta { }; |
|
|
424 | |
421 | |
425 | $MUSIC_WANT = []; |
422 | $MUSIC_WANT = []; |
426 | @MUSIC_JINGLE = (); |
423 | @MUSIC_JINGLE = (); |
427 | %AUDIO_PLAY = (); |
424 | %AUDIO_PLAY = (); |
428 | %AUDIO_CHUNK = (); |
425 | %AUDIO_CHUNK = (); |
… | |
… | |
877 | # $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume"); |
874 | # $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume"); |
878 | # $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub { |
875 | # $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub { |
879 | # $CFG->{effects_volume} = $_[1]; |
876 | # $CFG->{effects_volume} = $_[1]; |
880 | # }); |
877 | # }); |
881 | |
878 | |
882 | $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume"); |
879 | $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Sound Effects"); |
883 | $table->add_at (1, $row, new CFPlus::UI::CheckBox |
880 | $table->add_at (1, $row, new CFPlus::UI::CheckBox |
884 | expand => 1, state => $CFG->{effects_enable}, |
881 | expand => 1, state => $CFG->{effects_enable}, |
885 | tooltip => "If enabled, sound effects are enabled. If disabled, no sound effects will be played.", |
882 | tooltip => "If enabled, sound effects are enabled. If disabled, no sound effects will be played.", |
|
|
883 | on_changed => sub { |
886 | on_changed => sub { $CFG->{effects_enable} = $_[1]; 0 } |
884 | $CFG->{effects_enable} = $_[1]; |
|
|
885 | $CONN->update_fx_want if $CONN; |
|
|
886 | 0 |
|
|
887 | } |
887 | ); |
888 | ); |
888 | $table->add_at (2, $row++, new CFPlus::UI::Slider |
889 | $table->add_at (2, $row++, new CFPlus::UI::Slider |
889 | expand => 1, range => [$CFG->{effects_volume}, 0, 1, 0, 1/128], |
890 | expand => 1, range => [$CFG->{effects_volume}, 0, 1, 0, 1/128], |
890 | tooltip => "The relative volume of sound effects. Best audio quality is achieved if this " |
891 | tooltip => "The relative volume of sound effects. Best audio quality is achieved if this " |
891 | . "is set highest and you use your operating system volume setting. Changes are instant.", |
892 | . "is set highest (rightmost) and you use your operating system volume setting. Changes are instant.", |
892 | on_changed => sub { $CFG->{effects_volume} = $_[1]; 0 } |
893 | on_changed => sub { $CFG->{effects_volume} = $_[1]; 0 } |
893 | ); |
894 | ); |
894 | |
895 | |
895 | $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music"); |
896 | $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music"); |
896 | $table->add_at (1, $row, new CFPlus::UI::CheckBox |
897 | $table->add_at (1, $row, new CFPlus::UI::CheckBox |
897 | expand => 1, state => $CFG->{bgm_enable}, |
898 | expand => 1, state => $CFG->{bgm_enable}, |
898 | tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.", |
899 | tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.", |
899 | on_changed => sub { $CFG->{bgm_enable} = $_[1]; 0 } |
900 | on_changed => sub { |
|
|
901 | $CFG->{bgm_enable} = $_[1]; |
|
|
902 | $CONN->update_fx_want if $CONN; |
|
|
903 | 0 |
|
|
904 | } |
900 | ); |
905 | ); |
901 | $table->add_at (2, $row++, new CFPlus::UI::Slider |
906 | $table->add_at (2, $row++, new CFPlus::UI::Slider |
902 | expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128], |
907 | expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128], |
903 | tooltip => "The volume of the background music. Changes are instant.", |
908 | tooltip => "The volume of the background music. Changes are instant.", |
904 | on_changed => sub { $CFG->{bgm_volume} = $_[1]; audio_music_update_volume; 0 } |
909 | on_changed => sub { $CFG->{bgm_volume} = $_[1]; audio_music_update_volume; 0 } |
… | |
… | |
2283 | Event::loop; |
2288 | Event::loop; |
2284 | #CFPlus::SDL_Quit; |
2289 | #CFPlus::SDL_Quit; |
2285 | #CFPlus::_exit 0; |
2290 | #CFPlus::_exit 0; |
2286 | |
2291 | |
2287 | END { |
2292 | END { |
|
|
2293 | video_shutdown; |
|
|
2294 | audio_shutdown; |
2288 | CFPlus::SDL_Quit; |
2295 | CFPlus::SDL_Quit; |
2289 | CFPlus::DB::Server::stop; |
2296 | CFPlus::DB::Server::stop; |
2290 | } |
2297 | } |
2291 | |
2298 | |
2292 | =head1 NAME |
2299 | =head1 NAME |
2293 | |
2300 | |
2294 | cfplus - A Crossfire+ and Crossfire game client |
2301 | cfplus - A Crossfire TRT and Crossfire game client |
2295 | |
2302 | |
2296 | =head1 SYNOPSIS |
2303 | =head1 SYNOPSIS |
2297 | |
2304 | |
2298 | Just run it - no commandline arguments are supported. |
2305 | Just run it - no commandline arguments are supported. |
2299 | |
2306 | |
2300 | =head1 USAGE |
2307 | =head1 USAGE |
2301 | |
2308 | |
2302 | cfplus utilises OpenGL for all UI elements and the game. It is supposed to be used |
2309 | cfplus utilises OpenGL for all UI elements and the game. It is supposed to |
2303 | fullscreen and interactively. |
2310 | be used in fullscreen mode and interactively. |
2304 | |
2311 | |
2305 | =head1 DEBUGGING |
2312 | =head1 DEBUGGING |
2306 | |
2313 | |
2307 | |
2314 | |
2308 | CFPLUS_DEBUG - environment variable |
2315 | CFPLUS_DEBUG - environment variable |