ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/bin/cfplus
(Generate patch)

Comparing deliantra/Deliantra-Client/bin/cfplus (file contents):
Revision 1.193 by root, Tue Jul 31 00:30:16 2007 UTC vs.
Revision 1.223 by root, Tue Aug 28 01:23:47 2007 UTC

113our $CONN; 113our $CONN;
114our $PROFILE; # current profile 114our $PROFILE; # current profile
115our $FAST; # fast, low-quality mode, possibly useful for software-rendering 115our $FAST; # fast, low-quality mode, possibly useful for software-rendering
116 116
117our $WANT_REFRESH; 117our $WANT_REFRESH;
118our $CAN_REFRESH;
119 118
120our @SDL_MODES; 119our @SDL_MODES;
121our $WIDTH; 120our $WIDTH;
122our $HEIGHT; 121our $HEIGHT;
123our $FULLSCREEN; 122our $FULLSCREEN;
127our $FONT_FIXED; 126our $FONT_FIXED;
128 127
129our $MAP; 128our $MAP;
130our $MAPMAP; 129our $MAPMAP;
131our $MAPWIDGET; 130our $MAPWIDGET;
131our $COMPLETER;
132our $BUTTONBAR; 132our $BUTTONBAR;
133our $METASERVER; 133our $METASERVER;
134our $LOGIN_BUTTON; 134our $LOGIN_BUTTON;
135our $QUIT_DIALOG; 135our $QUIT_DIALOG;
136our $HOST_ENTRY; 136our $HOST_ENTRY;
144our $SETUP_KEYBOARD; 144our $SETUP_KEYBOARD;
145 145
146our $PL_NOTEBOOK; 146our $PL_NOTEBOOK;
147our $PL_WINDOW; 147our $PL_WINDOW;
148 148
149our $MUSIC_PLAYING_WIDGET;
150our $LICENSE_WIDGET;
151
152our $PICKUP_PAGE;
149our $INVENTORY_PAGE; 153our $INVENTORY_PAGE;
150our $STATS_PAGE; 154our $STATS_PAGE;
151our $SKILL_PAGE; 155our $SKILL_PAGE;
152our $SPELL_PAGE; 156our $SPELL_PAGE;
153our $SPELL_LIST; 157our $SPELL_LIST;
159our $STATWIDS; 163our $STATWIDS;
160 164
161our $SDL_ACTIVE; 165our $SDL_ACTIVE;
162our %SDL_CB; 166our %SDL_CB;
163 167
168our $ALT_ENTER_MESSAGE;
169our $STATUSBOX;
170our $DEBUG_STATUS;
171
172our $INV;
173our $INVR;
174our $INVR_HB;
175
176#############################################################################
177
178sub status {
179 $STATUSBOX->add (CFPlus::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]);
180}
181
182sub debug {
183 $DEBUG_STATUS->set_text ($_[0]);
184}
185
186sub message {
187 my ($para) = @_;
188 $MESSAGE_WINDOW->message ($para);
189}
190
191#############################################################################
192#TODO: maybe move into own audio module...
193
164our $SDL_MIXER; 194our $SDL_MIXER;
195
165our $MUSIC_DEFAULT = "in_a_heartbeat.ogg"; 196our $MUSIC_DEFAULT = "in_a_heartbeat.ogg";
166our @MUSIC_WANT; 197our $MUSIC_WANT; # arryref of ambient music we want to play
198our @MUSIC_HAVE; # ambient music we have on disk
167our $MUSIC_START; 199our $MUSIC_START;
200our @MUSIC_JINGLE; # which jingles to play next
168our $MUSIC_PLAYING_DATA; 201our $MUSIC_PLAYING_DATA;
169our $MUSIC_PLAYING_META; 202our $MUSIC_PLAYING_META;
170our $MUSIC_PLAYER; 203our $MUSIC_PLAYER;
171our $MUSIC_RESUME = 30; # resume music when players less than these many seconds before 204our $MUSIC_RESUME = 30; # resume music when played less than these many seconds before
172our @SOUNDS; # event => file mapping 205
173our %AUDIO_CHUNKS; # audio files 206our %AUDIO_CHUNK; # audio "files"
207our %AUDIO_PLAY; # which audio faces should be played
174 208
175our $ALT_ENTER_MESSAGE; 209sub audio_channel_finished {
176our $STATUSBOX; 210 my ($channel) = @_;
177our $DEBUG_STATUS;
178 211
179our $INV; 212# warn "channel $channel finished\n";#d#
180our $INVR;
181our $INV_RIGHT_HB;
182
183our $PICKUP_CFG;
184
185sub status {
186 $STATUSBOX->add (CFPlus::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]);
187} 213}
188 214
189sub debug { 215sub audio_sound_push($) {
190 $DEBUG_STATUS->set_text ($_[0]);
191}
192
193sub message {
194 my ($para) = @_; 216 my ($face) = @_;
195 $MESSAGE_WINDOW->message ($para); 217
218 $CFG->{effects_enable}
219 or return;
220
221 $AUDIO_PLAY{$face}
222 or return;
223
224 if (my $chunk = $AUDIO_CHUNK{$face}) {
225 for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) {
226 my (undef, $dx, $dy, $vol) = @$_;
227
228 my $channel = CFPlus::Channel::find;
229 $channel->volume ($vol * $CFG->{effects_volume} * 128 / 255);
230 $channel->set_position_r ($dx, $dy, 20);
231 $chunk->play ($channel);
232 }
233 } else {
234 # sound_meta not set means data is in flight either way
235 my $meta = $CONN->{face}[$face]
236 or return;
237
238 $meta->{data}
239 or return;
240
241 # if its a jingle, play it as ambient music
242 if ($meta->{data}{jingle}) {
243 if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue
244 push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue
245 &audio_music_push ($face);
246 }
247 } else {
248 # fetch from database
249 CFPlus::DB::get res_data => $meta->{name}, sub {
250 my $rwops = new CFPlus::RW $_[0];
251 my $chunk = new CFPlus::MixChunk $rwops
252 or Carp::confess "sound face " . (JSON::XS::to_json $meta) . " unloadable: " . CFPlus::Mix_GetError;
253 $chunk->volume (($meta->{data}{volume} || 1) * 128);
254 $AUDIO_CHUNK{$face} = $chunk;
255
256 audio_sound_push ($face);
257 };
258 }
259 }
196} 260}
261
262sub audio_sound_play {
263 my ($face, $dx, $dy, $vol) = @_;
264
265 $SDL_MIXER
266 or return;
267 $CFG->{effects_enable}
268 or return;
269
270 my $queue = $AUDIO_PLAY{$face} ||= [];
271 push @$queue, [Event::time + 0.6, $dx, $dy, $vol]; # do not play sound for outdated events
272 audio_sound_push $face
273 unless @$queue > 1;
274}
275
276sub audio_music_set_meta {
277 my ($meta) = @_;
278
279 $MUSIC_PLAYING_META = $meta;
280 $MUSIC_PLAYING_WIDGET->set_markup (
281 "<b>Name</b>: " . (CFPlus::asxml $meta->{data}{name}) . "\n"
282 . "<b>Author</b>: " . (CFPlus::asxml $meta->{data}{author}) . "\n"
283 . "<b>Source</b>: " . (CFPlus::asxml $meta->{data}{source}) . "\n"
284 . "<b>License</b>: " . (CFPlus::asxml $meta->{data}{license})
285 );
286}
287
288sub audio_music_update_volume {
289 return unless $MUSIC_PLAYING_META;
290 my $volume = $MUSIC_PLAYING_META->{data}{volume} || 1;
291 my $base = $MUSIC_PLAYING_META->{data}{jingle} ? 1 : $CFG->{bgm_volume};
292 CFPlus::MixMusic::volume $base * $volume * 128;
293}
294
295sub audio_music_start {
296 my $meta = $MUSIC_PLAYING_META;
297
298 CFPlus::DB::get res_data => $meta->{name}, sub {
299 return unless $SDL_MIXER;
300
301 # music might have changed...
302 $meta eq $MUSIC_PLAYING_META
303 or return &audio_music_start ();
304
305 audio_music_update_volume;
306
307 $MUSIC_PLAYING_DATA = \$_[0];
308
309 my $rwops = $meta->{path}
310 ? new_from_file CFPlus::RW $meta->{path}
311 : new CFPlus::RW $$MUSIC_PLAYING_DATA;
312
313 $MUSIC_PLAYER = new CFPlus::MixMusic $rwops
314 or Carp::confess "music face $meta->{face} unloadable: " . CFPlus::Mix_GetError;
315
316 my $NOW = time;
317
318 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) {
319 my $pos = $MUSIC_PLAYING_META->{stop_pos};
320 $MUSIC_PLAYER->fade_in_pos (0, 1000, $pos);
321 $MUSIC_START = time - $pos;
322 } else {
323 $MUSIC_PLAYER->play (0);
324 $MUSIC_START = time;
325 }
326
327 delete $meta->{stop_time};
328 delete $meta->{stop_pos};
329 }
330}
331
332sub audio_music_push {
333 return unless $SDL_MIXER;
334
335 my $fade_out;
336
337 if (@MUSIC_JINGLE) {
338 @MUSIC_HAVE = $MUSIC_JINGLE[0];
339 $fade_out = 333;
340 } else {
341 return unless $CFG->{bgm_enable};
342
343 my @have =
344 grep $_ && $_->{data},
345 map $CONN->{face}[$_],
346 @$MUSIC_WANT;
347
348 @MUSIC_HAVE = @have
349 if @have;
350
351 # default MUSIC_HAVE == MUSIC_DEFAULT
352 @MUSIC_HAVE = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_HAVE;
353 $fade_out = 1000;
354 }
355
356 # if the currently playing song is acceptable, let it continue
357 return if grep $MUSIC_PLAYING_META == $_, @MUSIC_HAVE;
358
359 my $NOW = time;
360
361 if ($MUSIC_PLAYING_META) {
362 $MUSIC_PLAYING_META->{stop_time} = $NOW;
363 $MUSIC_PLAYING_META->{stop_pos} = $NOW - $MUSIC_START;
364 CFPlus::MixMusic::fade_out $fade_out;
365 } else {
366 # sort by stop time, oldest first
367 @MUSIC_HAVE = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_HAVE;
368
369 # if the most recently-played piece played very recently,
370 # resume it, else choose the oldest piece for rotation.
371 audio_music_set_meta
372 $MUSIC_HAVE[-1]{stop_time} > $NOW - $MUSIC_RESUME
373 ? $MUSIC_HAVE[-1]
374 : $MUSIC_HAVE[0];
375
376 audio_music_start;
377 }
378}
379
380sub audio_music_set_ambient {
381 my ($songs) = @_;
382
383 $MUSIC_WANT = $songs;
384 audio_music_push;
385}
386
387sub audio_music_finished {
388 # we compress multiple jingles of the same type
389 shift @MUSIC_JINGLE
390 while @MUSIC_JINGLE && $MUSIC_PLAYING_META == $MUSIC_JINGLE[0];
391
392 $MUSIC_PLAYING_WIDGET->clear;
393
394 undef $MUSIC_PLAYER;
395 undef $MUSIC_PLAYING_META;
396 undef $MUSIC_PLAYING_DATA;
397
398 audio_music_push;
399}
400
401sub audio_init {
402 if ($CFG->{audio_enable}) {
403 $ENV{MIX_EFFECTSMAXSPEED} = 1;
404 $SDL_MIXER = !CFPlus::Mix_OpenAudio;
405
406 unless ($SDL_MIXER) {
407 status "Unable to open sound device: there will be no sound";
408 return;
409 }
410
411 CFPlus::Mix_AllocateChannels 16;
412
413 audio_music_finished;
414 } else {
415 undef $SDL_MIXER;
416 }
417}
418
419sub audio_shutdown {
420 undef $MUSIC_PLAYER;
421 undef $MUSIC_PLAYING_META;
422 undef $MUSIC_PLAYING_DATA;
423
424 $MUSIC_WANT = [];
425 @MUSIC_JINGLE = ();
426 %AUDIO_PLAY = ();
427 %AUDIO_CHUNK = ();
428
429 CFPlus::Mix_CloseAudio if $SDL_MIXER;
430 undef $SDL_MIXER;
431}
432
433#############################################################################
197 434
198sub destroy_query_dialog { 435sub destroy_query_dialog {
199 (delete $_[0]{query_dialog})->destroy 436 (delete $_[0]{query_dialog})->destroy
200 if $_[0]{query_dialog}; 437 if $_[0]{query_dialog};
201} 438}
481 $SETUP_DIALOG->show; 718 $SETUP_DIALOG->show;
482 $PL_WINDOW->hide; 719 $PL_WINDOW->hide;
483 $SPELL_LIST->clear_spells; 720 $SPELL_LIST->clear_spells;
484 $CFPlus::UI::ROOT->emit (stop_game => ! ! $CONN); 721 $CFPlus::UI::ROOT->emit (stop_game => ! ! $CONN);
485 722
486 &audio_music_set ([]); 723 &audio_music_set_ambient ([]);
487 724
488 return unless $CONN; 725 return unless $CONN;
489 726
490 status "connection closed"; 727 status "connection closed";
491 728
533 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fullscreen"); 770 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fullscreen");
534 $table->add_at (1, $row++, $FULLSCREEN_ENABLE = new CFPlus::UI::CheckBox 771 $table->add_at (1, $row++, $FULLSCREEN_ENABLE = new CFPlus::UI::CheckBox
535 state => $CFG->{fullscreen}, 772 state => $CFG->{fullscreen},
536 tooltip => "Bring the client into fullscreen mode.", 773 tooltip => "Bring the client into fullscreen mode.",
537 on_changed => sub { my ($self, $value) = @_; $CFG->{fullscreen} = $value; 0 } 774 on_changed => sub { my ($self, $value) = @_; $CFG->{fullscreen} = $value; 0 }
775 );
776
777 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Force OpenGL 1.1");
778 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
779 state => $CFG->{force_opengl11},
780 tooltip => "Limit CFPlus to use OpenGL 1.1 features only. This will normally result in "
781 . "higher memory usage and slower performance. It will, however, help tremendously on "
782 . "cards that claim to support a feature but fall back to software rendering. "
783 . "Nvidia Geforce FX cards are known to claim features the hardware doesn't support, "
784 . "but cards and drivers from other vendors (ATI) are often just as bad. <b>If you "
785 . "experience extremely low framerates and your card should do better, try this option.</b>",
786 on_changed => sub { my ($self, $value) = @_; $CFG->{force_opengl11} = $value; 0 }
787 );
788
789 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Compress Textures");
790 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
791 state => $CFG->{texture_compression},
792 tooltip => "Use texture compression. Normally this will not reduce visual quality noticable but "
793 . "will save a lot of memory and increase performance. The compression algorithm "
794 . "can differ form card to card, so your mileage may vary. This setting is ignored in "
795 . "forced OpenGL 1.1 mode.",
796 on_changed => sub { my ($self, $value) = @_; $CFG->{texture_compression} = $value; 0 }
538 ); 797 );
539 798
540 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fast & Ugly"); 799 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fast & Ugly");
541 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 800 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
542 state => $CFG->{fast}, 801 state => $CFG->{fast},
570 829
571 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Map Smoothing"); 830 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Map Smoothing");
572 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 831 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
573 state => $CFG->{map_smoothing}, 832 state => $CFG->{map_smoothing},
574 tooltip => "<b>Map Smoothing</b> tries to make tile borders less square. " 833 tooltip => "<b>Map Smoothing</b> tries to make tile borders less square. "
575 . "This increases load on the graphics subsystem and works only with 2.x servers. " 834 . "This increases load on the graphics subsystem and works only with TRT servers. "
576 . "Changes take effect at next connection only.", 835 . "Changes take effect at next login only.",
577 on_changed => sub { my ($self, $value) = @_; $CFG->{map_smoothing} = $value; 0 } 836 on_changed => sub { my ($self, $value) = @_; $CFG->{map_smoothing} = $value; 0 }
578 ); 837 );
579 838
580 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fog of War"); 839 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fog of War");
581 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 840 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
592 ); 851 );
593 852
594 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Message Fontsize"); 853 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Message Fontsize");
595 $table->add_at (1, $row++, new CFPlus::UI::Slider 854 $table->add_at (1, $row++, new CFPlus::UI::Slider
596 range => [$CFG->{log_fontsize}, 0.5, 2, 0, 0.1], 855 range => [$CFG->{log_fontsize}, 0.5, 2, 0, 0.1],
597 tooltip => "The font size used by the <b>message/server log</b> window only. Changes are instant.", 856 tooltip => "The font size used by the <b>message/server log</b> window only. Changes are instant, "
857 . "but you still need to press apply to correctly re-layout the widget.",
598 on_changed => sub { $MESSAGE_WINDOW->set_fontsize ($CFG->{log_fontsize} = $_[1]); 0 }, 858 on_changed => sub { $MESSAGE_WINDOW->set_fontsize ($CFG->{log_fontsize} = $_[1]); 0 },
599 ); 859 );
600 860
601 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Gauge fontsize"); 861 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Gauge fontsize");
602 $table->add_at (1, $row++, new CFPlus::UI::Slider 862 $table->add_at (1, $row++, new CFPlus::UI::Slider
624} 884}
625 885
626sub audio_setup { 886sub audio_setup {
627 my $vbox = new CFPlus::UI::VBox; 887 my $vbox = new CFPlus::UI::VBox;
628 888
629 $vbox->add (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 1]); 889 $vbox->add (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 0, 1]);
630 890
631 my $row = 0; 891 my $row = 0;
632 892
633 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Audio Enable"); 893 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Audio Enable");
634 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 894 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
638 ); 898 );
639# $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume"); 899# $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume");
640# $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub { 900# $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub {
641# $CFG->{effects_volume} = $_[1]; 901# $CFG->{effects_volume} = $_[1];
642# }); 902# });
903
904 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Sound Effects");
905 $table->add_at (1, $row, new CFPlus::UI::CheckBox
906 expand => 1, state => $CFG->{effects_enable},
907 tooltip => "If enabled, sound effects are enabled. If disabled, no sound effects will be played.",
908 on_changed => sub {
909 $CFG->{effects_enable} = $_[1];
910 $CONN->update_fx_want if $CONN;
911 0
912 }
913 );
914 $table->add_at (2, $row++, new CFPlus::UI::Slider
915 expand => 1, range => [$CFG->{effects_volume}, 0, 1, 0, 1/128],
916 tooltip => "The relative volume of sound effects. Best audio quality is achieved if this "
917 . "is set highest (rightmost) and you use your operating system volume setting. Changes are instant.",
918 on_changed => sub { $CFG->{effects_volume} = $_[1]; 0 }
919 );
920
643 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music"); 921 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music");
644 $table->add_at (1, $row++, my $hbox = new CFPlus::UI::HBox); 922 $table->add_at (1, $row, new CFPlus::UI::CheckBox
645 $hbox->add (new CFPlus::UI::CheckBox
646 expand => 1, state => $CFG->{bgm_enable}, 923 expand => 1, state => $CFG->{bgm_enable},
647 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.", 924 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.",
648 on_changed => sub { $CFG->{bgm_enable} = $_[1]; 0 } 925 on_changed => sub {
926 $CFG->{bgm_enable} = $_[1];
927 $CONN->update_fx_want if $CONN;
928 audio_music_push;
929 0
930 }
649 ); 931 );
650 $hbox->add (new CFPlus::UI::Slider 932 $table->add_at (2, $row++, new CFPlus::UI::Slider
651 expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128], 933 expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128],
652 tooltip => "The volume of the background music. Changes are instant.", 934 tooltip => "The volume of the background music. Changes are instant.",
653 on_changed => sub { $CFG->{bgm_volume} = $_[1]; CFPlus::MixMusic::volume $_[1] * 128; 0 } 935 on_changed => sub { $CFG->{bgm_volume} = $_[1]; audio_music_update_volume; 0 }
654 ); 936 );
655 937
656 $table->add_at (1, $row++, new CFPlus::UI::Button 938 $table->add_at (1, $row++, new CFPlus::UI::Button
657 expand => 1, align => 0, text => "Apply", 939 c_colspan => 2, expand => 1, align => 0, text => "Apply",
658 tooltip => "Apply the audio settings", 940 tooltip => "Apply the audio settings",
659 on_activate => sub { 941 on_activate => sub {
660 audio_shutdown (); 942 audio_shutdown ();
661 audio_init (); 943 audio_init ();
662 0 944 0
704 $hb->add (my $hg = new CFPlus::UI::Gauge type => 'hp', tooltip => "#stat_health"); 986 $hb->add (my $hg = new CFPlus::UI::Gauge type => 'hp', tooltip => "#stat_health");
705 $hb->add (my $mg = new CFPlus::UI::Gauge type => 'mana', tooltip => "#stat_mana"); 987 $hb->add (my $mg = new CFPlus::UI::Gauge type => 'mana', tooltip => "#stat_mana");
706 $hb->add (my $gg = new CFPlus::UI::Gauge type => 'grace', tooltip => "#stat_grace"); 988 $hb->add (my $gg = new CFPlus::UI::Gauge type => 'grace', tooltip => "#stat_grace");
707 $hb->add (my $fg = new CFPlus::UI::Gauge type => 'food', tooltip => "#stat_food"); 989 $hb->add (my $fg = new CFPlus::UI::Gauge type => 'food', tooltip => "#stat_food");
708 990
709 $vbox->add (my $exp = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_exp"); 991 $vbox->add (my $exp = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_exp");
992 $vbox->add (my $prg = new CFPlus::UI::ExperienceProgress);
993 $vbox->add (my $sklprg = new CFPlus::UI::ExperienceProgress);
710 $vbox->add (my $rng = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_ranged"); 994 $vbox->add (my $rng = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_ranged");
711 995
712 $GAUGES = { 996 $GAUGES = {
997 exp => $exp, prg => $prg, sklprg => $sklprg,
713 exp => $exp, win => $win, range => $rng, 998 win => $win, range => $rng,
714 food => $fg, mana => $mg, hp => $hg, grace => $gg 999 hp => $hg, mana => $mg, grace => $gg, food => $fg,
715 }; 1000 };
716 1001
717 &set_gauge_window_fontsize; 1002 &set_gauge_window_fontsize;
718 1003
719 $win 1004 $win
733 $table->add_at (0, 4, new CFPlus::UI::Button text => "die on click(tm)", on_activate => sub { &CFPlus::debug() } ); 1018 $table->add_at (0, 4, new CFPlus::UI::Button text => "die on click(tm)", on_activate => sub { &CFPlus::debug() } );
734 1019
735 $table->add_at (0, 5, new CFPlus::UI::TextEdit text => "line1\0152\0153");#d# 1020 $table->add_at (0, 5, new CFPlus::UI::TextEdit text => "line1\0152\0153");#d#
736 1021
737 $table->add_at (7,7, my $t = new CFPlus::UI::Table expand => 0); 1022 $table->add_at (7,7, my $t = new CFPlus::UI::Table expand => 0);
738 $t->add_at (0,0, new CFPlus::UI::Label text => "a a a a", rowspan => 1, colspan => 2); 1023 $t->add_at (0,0, new CFPlus::UI::Label text => "a a a a", c_rowspan => 1, c_colspan => 2);
739 $t->add_at (2,0, new CFPlus::UI::Label text => "b\nb", rowspan => 2, colspan => 1); 1024 $t->add_at (2,0, new CFPlus::UI::Label text => "b\nb", c_rowspan => 2, c_colspan => 1);
740 $t->add_at (1,2, new CFPlus::UI::Label text => "c c c c", rowspan => 1, colspan => 2); 1025 $t->add_at (1,2, new CFPlus::UI::Label text => "c c c c", c_rowspan => 1, c_colspan => 2);
741 $t->add_at (0,1, new CFPlus::UI::Label text => "d\nd", rowspan => 2, colspan => 1); 1026 $t->add_at (0,1, new CFPlus::UI::Label text => "d\nd", c_rowspan => 2, c_colspan => 1);
742 $t->add_at (1,1, new CFPlus::UI::Label text => "e"); 1027 $t->add_at (1,1, new CFPlus::UI::Label text => "e");
743 1028
744 $table->add_at (7, 6, my $c = new CFPlus::UI::Canvas); 1029 $table->add_at (7, 6, my $c = new CFPlus::UI::Canvas);
745 1030
746 $c->add_items ({ 1031 $c->add_items ({
920 $r 1205 $r
921} 1206}
922 1207
923sub skill_window { 1208sub skill_window {
924 my $sw = new CFPlus::UI::ScrolledWindow (expand => 1); 1209 my $sw = new CFPlus::UI::ScrolledWindow (expand => 1);
1210
925 $sw->add ($STATWIDS->{skill_tbl} = new CFPlus::UI::Table expand => 1, col_expand => [0, 0, 1, 0, 0, 1]); 1211 $sw->add ($STATWIDS->{skill_tbl} = new CFPlus::UI::Table expand => 1, col_expand => [0, 0, 1, .1, 0, 0, 1, .1]);
1212
926 $sw 1213 $sw
927} 1214}
928 1215
929sub formsep($) { 1216sub formsep($) {
930 scalar reverse join ",", unpack "(A3)*", reverse $_[0] * 1 1217 scalar reverse join ",", unpack "(A3)*", reverse $_[0] * 1
1342 $sw1->add ($INV = new CFPlus::UI::Inventory); 1629 $sw1->add ($INV = new CFPlus::UI::Inventory);
1343 $INV->set_sort_order ($SORT_ORDER{$::CFG->{inv_sort}}); 1630 $INV->set_sort_order ($SORT_ORDER{$::CFG->{inv_sort}});
1344 1631
1345 $hb->add (my $vb2 = new CFPlus::UI::VBox); 1632 $hb->add (my $vb2 = new CFPlus::UI::VBox);
1346 1633
1347 $vb2->add ($INV_RIGHT_HB = new CFPlus::UI::HBox); 1634 $vb2->add ($INVR_HB = new CFPlus::UI::HBox);
1348 1635
1349 $vb2->add (my $sw2 = new CFPlus::UI::ScrolledWindow expand => 1, scroll_y => 1); 1636 $vb2->add (my $sw2 = new CFPlus::UI::ScrolledWindow expand => 1, scroll_y => 1);
1350 $sw2->add ($INVR = new CFPlus::UI::Inventory); 1637 $sw2->add ($INVR = new CFPlus::UI::Inventory);
1351 1638
1352 # XXX: Call after $INVR = ... because set_opencont sets the items 1639 # XXX: Call after $INVR = ... because set_opencont sets the items
1353 CFPlus::Protocol::set_opencont ($::CONN, 0, "Floor"); 1640 CFPlus::Protocol::set_opencont ($::CONN, 0, "Floor");
1354 1641
1355 $hb 1642 $hb
1643}
1644
1645sub media_window {
1646 my $vb = new CFPlus::UI::VBox;
1647
1648 $vb->add (new CFPlus::UI::FancyFrame
1649 label => "Currently playing music",
1650 child => new CFPlus::UI::ScrolledWindow scroll_x => 1, scroll_y => 0,
1651 child => ($MUSIC_PLAYING_WIDGET = new CFPlus::UI::Label ellipsise => 0, fontsize => 0.8),
1652 );
1653
1654 $vb->add (new CFPlus::UI::FancyFrame
1655 label => "Other media used in this session",
1656 expand => 1,
1657 child => ($LICENSE_WIDGET = new CFPlus::UI::TextScroller
1658 expand => 1, fontsize => 0.8, padding_x => 4, padding_y => 4),
1659 );
1660
1661 $vb
1662}
1663
1664sub add_license {
1665 my ($meta) = @_;
1666
1667 $meta = $meta->{data}
1668 or return;
1669
1670 $meta->{license} || $meta->{author} || $meta->{source}
1671 or return;
1672
1673 $LICENSE_WIDGET->add_paragraph ({
1674 fg => [1, 1, 1, 1],
1675 markup => "<small>"
1676 . "<b>Name:</b> " . (CFPlus::asxml $meta->{name}) . "\n"
1677 . "<b>Author:</b> " . (CFPlus::asxml $meta->{author}) . "\n"
1678 . "<b>Source:</b> " . (CFPlus::asxml $meta->{source}) . "\n"
1679 . "<b>License:</b> " . (CFPlus::asxml $meta->{license}) . "\n"
1680 . "</small>",
1681 });
1682 $LICENSE_WIDGET->scroll_to_bottom;
1356} 1683}
1357 1684
1358sub toggle_player_page { 1685sub toggle_player_page {
1359 my ($widget) = @_; 1686 my ($widget) = @_;
1360 1687
1399 $ntb->add_tab ( 1726 $ntb->add_tab (
1400 "Inventory (F5)" => $INVENTORY_PAGE = inventory_widget, 1727 "Inventory (F5)" => $INVENTORY_PAGE = inventory_widget,
1401 "Toggles the inventory window, where you can manage your loot (or treasures :). " 1728 "Toggles the inventory window, where you can manage your loot (or treasures :). "
1402 . "You can also hit the <b>Tab</b>-key to show/hide the Inventory." 1729 . "You can also hit the <b>Tab</b>-key to show/hide the Inventory."
1403 ); 1730 );
1404 $ntb->add_tab (Pickup => autopickup_setup, 1731 $ntb->add_tab (Pickup => $PICKUP_PAGE = autopickup_setup,
1405 "Configure autopickup settings, i.e. which items you will pick up automatically when walking (or running) over them."); 1732 "Configure autopickup settings, i.e. which items you will pick up automatically when walking (or running) over them.");
1733
1734 $ntb->add_tab (Media => media_window,
1735 "License, Author and Source info for media sent by the server.");
1406 1736
1407 $ntb->set_current_page ($INVENTORY_PAGE); 1737 $ntb->set_current_page ($INVENTORY_PAGE);
1408 1738
1409 $plwin->add ($ntb); 1739 $plwin->add ($ntb);
1410 $plwin 1740 $plwin
1564 on_activate => sub { $QUIT_DIALOG->hide; 0 }, 1894 on_activate => sub { $QUIT_DIALOG->hide; 0 },
1565 ); 1895 );
1566 $hb->add (new CFPlus::UI::Button 1896 $hb->add (new CFPlus::UI::Button
1567 text => "Quit anyway", 1897 text => "Quit anyway",
1568 expand => 1, 1898 expand => 1,
1569 on_activate => sub { exit }, 1899 on_activate => sub { Event::unloop_all },
1570 ); 1900 );
1571 } 1901 }
1572 1902
1573 $QUIT_DIALOG->show; 1903 $QUIT_DIALOG->show;
1574 $QUIT_DIALOG->grab_focus; 1904 $QUIT_DIALOG->grab_focus;
1647 1977
1648 $SDL_ACTIVE = 1; 1978 $SDL_ACTIVE = 1;
1649 $LAST_REFRESH = time - 0.01; 1979 $LAST_REFRESH = time - 0.01;
1650 1980
1651 CFPlus::OpenGL::init; 1981 CFPlus::OpenGL::init;
1982 CFPlus::Macro::init;
1652 1983
1653 $FONTSIZE = int $HEIGHT / 40 * $CFG->{gui_fontsize}; 1984 $FONTSIZE = int $HEIGHT / 40 * $CFG->{gui_fontsize};
1654 1985
1655 $CFPlus::UI::ROOT->configure (0, 0, $WIDTH, $HEIGHT);#d# 1986 $CFPlus::UI::ROOT->configure (0, 0, $WIDTH, $HEIGHT);#d#
1656 1987
1657 ############################################################################# 1988 #############################################################################
1658 1989
1659 if ($DEBUG_STATUS) { 1990 if ($DEBUG_STATUS) {
1660 CFPlus::UI::rescale_widgets $WIDTH / $old_w, $HEIGHT / $old_h; 1991 CFPlus::UI::rescale_widgets $WIDTH / $old_w, $HEIGHT / $old_h;
1661 } else { 1992 } else {
1662 # create the widgets 1993 # create/configure the widgets
1994
1995 $CFPlus::UI::ROOT->connect (key_down => sub {
1996 my (undef, $ev) = @_;
1997
1998 if (my @macros = CFPlus::Macro::find $ev) {
1999 CFPlus::Macro::execute $_ for @macros;
2000
2001 return 1;
2002 }
2003
2004 0
2005 });
1663 2006
1664 $DEBUG_STATUS = new CFPlus::UI::Label 2007 $DEBUG_STATUS = new CFPlus::UI::Label
1665 padding => 0, 2008 padding => 0,
1666 z => 100, 2009 z => 100,
1667 force_x => "max", 2010 force_x => "max",
1697 $MESSAGE_WINDOW->activate_console ($preset) 2040 $MESSAGE_WINDOW->activate_console ($preset)
1698 if $MESSAGE_WINDOW; 2041 if $MESSAGE_WINDOW;
1699 }); 2042 });
1700 $MAPWIDGET->show; 2043 $MAPWIDGET->show;
1701 $MAPWIDGET->grab_focus; 2044 $MAPWIDGET->grab_focus;
2045
2046 $COMPLETER = new CFPlus::MapWidget::Command::
2047 command => { },
2048 tooltip => "#completer_help",
2049 ;
1702 2050
1703 $SETUP_DIALOG = new CFPlus::UI::Toplevel 2051 $SETUP_DIALOG = new CFPlus::UI::Toplevel
1704 title => "Setup", 2052 title => "Setup",
1705 name => "setup_dialog", 2053 name => "setup_dialog",
1706 x => 'center', 2054 x => 'center',
1768 tooltip => "Terminates the program", 2116 tooltip => "Terminates the program",
1769 on_activate => sub { 2117 on_activate => sub {
1770 if ($CONN) { 2118 if ($CONN) {
1771 open_quit_dialog; 2119 open_quit_dialog;
1772 } else { 2120 } else {
1773 exit; 2121 Event::unloop_all;
1774 } 2122 }
1775 0 2123 0
1776 }, 2124 },
1777 ); 2125 );
1778 2126
1779 $BUTTONBAR->show; 2127 $BUTTONBAR->show;
1780 $SETUP_DIALOG->show; 2128 $SETUP_DIALOG->show;
2129 $MESSAGE_WINDOW->show;
1781 } 2130 }
1782 2131
1783 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); 2132 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]);
1784} 2133}
1785 2134
1787 CFPlus::OpenGL::shutdown; 2136 CFPlus::OpenGL::shutdown;
1788 2137
1789 undef $SDL_ACTIVE; 2138 undef $SDL_ACTIVE;
1790} 2139}
1791 2140
1792sub audio_channel_finished {
1793 my ($channel) = @_;
1794
1795# warn "channel $channel finished\n";#d#
1796}
1797
1798our %AUDIO_PLAY;
1799our %AUDIO_CHUNK;
1800
1801sub audio_sound_push($) {
1802 my ($face) = @_;
1803
1804 if (my $chunk = $AUDIO_CHUNK{$face}) {
1805 for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) {
1806 my (undef, $dx, $dy, $vol) = @$_;
1807
1808 my $channel = $chunk->play
1809 or return;
1810
1811 $channel->volume (128 + $vol);
1812 $dx = $dx / 10 * 255;
1813 $channel->set_panning ((min 255, 255 - $dx), (min 255, 255 + $dx));
1814# my $angle = $dx ? : $dx < 0 ?
1815# my $distance = -$vol;
1816# $channel->set_position ($angle, $distance);
1817 }
1818 } else {
1819 # sound_meta not set means data is in flight either way
1820 my $meta = $CONN->{sound_meta}{$face}
1821 or return;
1822
1823 # fetch from database
1824 CFPlus::DB::get res_data => $meta->{name}, sub {
1825 my $vol = $meta->{meta}{volume} || 1;
1826 my $rwops = new CFPlus::RW $_[0];
1827 my $chunk = new CFPlus::MixChunk $rwops;
1828 $chunk->volume ($vol * 128);
1829 $AUDIO_CHUNK{$face} = $chunk;
1830
1831 audio_sound_push ($face);
1832 };
1833 }
1834}
1835
1836sub audio_sound_play {
1837 my ($face, $dx, $dy, $vol) = @_;
1838
1839 $SDL_MIXER
1840 or return;
1841
1842 my $queue = $AUDIO_PLAY{$face} ||= [];
1843 push @$queue, [Event::time + 0.2, $dx, $dy, $vol]; # delay sound by max. 0.2s
1844 audio_sound_push $face
1845 unless @$queue > 1;
1846}
1847
1848sub audio_music_set {
1849 my ($songs) = @_;
1850
1851 my @want =
1852 grep $_,
1853 map $CONN->{music_meta}{$_},
1854 @$songs;
1855
1856 if (@want) {
1857 @MUSIC_WANT = @want;
1858 &audio_music_changed ();
1859 }
1860}
1861
1862sub audio_music_start {
1863 my $meta = $MUSIC_PLAYING_META;
1864
1865 CFPlus::DB::get res_data => $meta->{name}, sub {
1866 return unless $SDL_MIXER;
1867
1868 # music might have changed...
1869 $meta eq $MUSIC_PLAYING_META
1870 or return &audio_music_start ();
1871
1872 $MUSIC_PLAYING_DATA = \$_[0];
1873
1874 my $rwops = $meta->{path}
1875 ? new_from_file CFPlus::RW $meta->{path}
1876 : new CFPlus::RW $$MUSIC_PLAYING_DATA;
1877
1878 $MUSIC_PLAYER = new CFPlus::MixMusic $rwops
1879 or ((warn CFPlus::Mix_GetError), return); # pretty fatal error
1880
1881 my $NOW = time;
1882
1883 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) {
1884 my $pos = $MUSIC_PLAYING_META->{stop_pos};
1885 $MUSIC_PLAYER->fade_in_pos (0, 1000, $pos);
1886 $MUSIC_START = time - $pos;
1887 } else {
1888 $MUSIC_PLAYER->play (0);
1889 $MUSIC_START = time;
1890 }
1891
1892 delete $MUSIC_PLAYING_META->{stop_time};
1893 delete $MUSIC_PLAYING_META->{stop_pos};
1894 }
1895}
1896
1897sub audio_music_changed {
1898 return unless $CFG->{bgm_enable};
1899 return unless $SDL_MIXER;
1900
1901 # default MUSIC_WANT == MUSIC_DEFAULT
1902 @MUSIC_WANT = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_WANT;
1903
1904 # if the currently playing song is acceptable, let it continue
1905 return if $MUSIC_PLAYING_META
1906 && grep $MUSIC_PLAYING_META == $_, @MUSIC_WANT;
1907
1908 my $NOW = time;
1909
1910 if ($MUSIC_PLAYING_META) {
1911 $MUSIC_PLAYING_META->{stop_time} = $NOW;
1912 $MUSIC_PLAYING_META->{stop_pos} = $NOW - $MUSIC_START;
1913 CFPlus::MixMusic::fade_out 1000;
1914 } else {
1915 # sort by stop time, oldest first
1916 @MUSIC_WANT = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_WANT;
1917
1918 # if the most recently-played piece played very recently,
1919 # resume it, else choose the oldest piece for rotation.
1920 $MUSIC_PLAYING_META =
1921 $MUSIC_WANT[-1]{stop_time} > $NOW - $MUSIC_RESUME
1922 ? $MUSIC_WANT[-1]
1923 : $MUSIC_WANT[0];
1924
1925 audio_music_start;
1926 }
1927}
1928
1929sub audio_music_finished {
1930 undef $MUSIC_PLAYER;
1931 undef $MUSIC_PLAYING_META;
1932 undef $MUSIC_PLAYING_DATA;
1933
1934 audio_music_changed;
1935}
1936
1937sub audio_init {
1938 if ($CFG->{audio_enable}) {
1939 $ENV{MIX_EFFECTSMAXSPEED} = 1;
1940 $SDL_MIXER = !CFPlus::Mix_OpenAudio;
1941
1942 unless ($SDL_MIXER) {
1943 status "Unable to open sound device: there will be no sound";
1944 return;
1945 }
1946
1947 CFPlus::Mix_AllocateChannels 16;
1948 CFPlus::MixMusic::volume $CFG->{bgm_volume} * 128;
1949
1950 audio_music_finished;
1951 } else {
1952 undef $SDL_MIXER;
1953 }
1954}
1955
1956sub audio_shutdown {
1957 CFPlus::Mix_CloseAudio if $SDL_MIXER;
1958 undef $SDL_MIXER;
1959 @SOUNDS = ();
1960 %AUDIO_CHUNKS = ();
1961}
1962
1963my %animate_object; 2141my %animate_object;
1964my $animate_timer; 2142my $animate_timer;
1965 2143
1966my $fps = 9; 2144my $fps = 9;
1967 2145
1968sub force_refresh { 2146sub force_refresh {
2147 if ($ENV{CFPLUS_DEBUG} & 4) {
1969 $fps = $fps * 0.95 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.05; 2148 $fps = $fps * 0.98 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.02;
1970 debug sprintf "%3.2f", $fps if $ENV{CFPLUS_DEBUG} & 4; 2149 debug sprintf "%3.2f", $fps;
2150 }
1971 2151
1972 $CFPlus::UI::ROOT->draw; 2152 $CFPlus::UI::ROOT->draw;
1973 2153 CFPlus::SDL_GL_SwapBuffers;
1974 $WANT_REFRESH = 0;
1975 $CAN_REFRESH = 0;
1976 $LAST_REFRESH = $NOW; 2154 $LAST_REFRESH = $NOW;
1977 2155 $WANT_REFRESH->stop;
1978 CFPlus::SDL_GL_SwapBuffers;
1979} 2156}
1980 2157
2158$WANT_REFRESH = Event->idle (min => 0.001, max => 0.06, parked => 1, cb => \&force_refresh);
2159
1981my $refresh_watcher = Event->timer (after => 0, hard => 0, interval => 1 / $MAX_FPS, cb => sub { 2160my $input = Event->timer (after => 0, hard => 0, interval => 1 / 50, cb => sub {
1982 $NOW = time; 2161 $NOW = time;
1983 2162
1984 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_) 2163 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_)
1985 for CFPlus::poll_events; 2164 for CFPlus::poll_events;
1986 2165
1987 if (%animate_object) { 2166 if (%animate_object) {
1988 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object; 2167 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object;
1989 ++$WANT_REFRESH; 2168 $WANT_REFRESH->start;
1990 }
1991
1992 if ($WANT_REFRESH) {
1993 force_refresh;
1994 } else {
1995 $CAN_REFRESH = 1;
1996 } 2169 }
1997}); 2170});
1998 2171
1999sub animation_start { 2172sub animation_start {
2000 my ($widget) = @_; 2173 my ($widget) = @_;
2006 delete $animate_object{$widget}; 2179 delete $animate_object{$widget};
2007} 2180}
2008 2181
2009%SDL_CB = ( 2182%SDL_CB = (
2010 CFPlus::SDL_QUIT => sub { 2183 CFPlus::SDL_QUIT => sub {
2011 exit; 2184 Event::unloop_all;
2012 }, 2185 },
2013 CFPlus::SDL_VIDEORESIZE => sub { 2186 CFPlus::SDL_VIDEORESIZE => sub {
2014 }, 2187 },
2015 CFPlus::SDL_VIDEOEXPOSE => sub { 2188 CFPlus::SDL_VIDEOEXPOSE => sub {
2016 CFPlus::UI::full_refresh; 2189 CFPlus::UI::full_refresh;
2055 CFPlus::DB::Server::run; 2228 CFPlus::DB::Server::run;
2056 2229
2057 CFPlus::UI::set_layout ($::CFG->{layout}); 2230 CFPlus::UI::set_layout ($::CFG->{layout});
2058 2231
2059 my %DEF_CFG = ( 2232 my %DEF_CFG = (
2060 sdl_mode => 0, 2233 sdl_mode => 0,
2061 fullscreen => 0, 2234 fullscreen => 0,
2062 fast => 0, 2235 fast => 0,
2236 force_opengl11 => undef,
2237 texture_compression => 1,
2063 map_scale => 1, 2238 map_scale => 1,
2064 fow_enable => 1, 2239 fow_enable => 1,
2065 fow_intensity => 0, 2240 fow_intensity => 0,
2066 map_smoothing => 1, 2241 map_smoothing => 1,
2067 gui_fontsize => 1, 2242 gui_fontsize => 1,
2068 log_fontsize => 0.7, 2243 log_fontsize => 0.7,
2069 gauge_fontsize => 1, 2244 gauge_fontsize => 1,
2070 gauge_size => 0.35, 2245 gauge_size => 0.35,
2071 stat_fontsize => 0.7, 2246 stat_fontsize => 0.7,
2072 mapsize => 100, 2247 mapsize => 100,
2073 audio_enable => 1, 2248 audio_enable => 1,
2249 effects_enable => 1,
2250 effects_volume => 1,
2074 bgm_enable => 1, 2251 bgm_enable => 1,
2075 bgm_volume => 0.25, 2252 bgm_volume => 0.5,
2076 output_sync => 1, 2253 output_sync => 1,
2077 output_count => 1, 2254 output_count => 1,
2078 output_rate => "", 2255 output_rate => "",
2079 pickup => 0, 2256 pickup => 0,
2080 inv_sort => "mtime", 2257 inv_sort => "mtime",
2081 default => "profile", # default profile 2258 default => "profile", # default profile
2082 show_tips => 1, 2259 show_tips => 1,
2083 logview_max_par => 1000, 2260 logview_max_par => 1000,
2084 ); 2261 );
2085 2262
2086 while (my ($k, $v) = each %DEF_CFG) { 2263 while (my ($k, $v) = each %DEF_CFG) {
2087 $CFG->{$k} = $v unless exists $CFG->{$k}; 2264 $CFG->{$k} = $v unless exists $CFG->{$k};
2088 } 2265 }
2145# } 2322# }
2146# my $t2 = Time::HiRes::time; 2323# my $t2 = Time::HiRes::time;
2147# warn $t2-$t1; 2324# warn $t2-$t1;
2148# } 2325# }
2149 2326
2150 $startup_done->();
2151
2152 video_init; 2327 video_init;
2153 audio_init; 2328 audio_init;
2154} 2329}
2155 2330
2156show_tip_of_the_day if $CFG->{show_tips}; 2331show_tip_of_the_day if $CFG->{show_tips};
2157 2332
2333Event->idle (cb => sub {
2334 $_[0]->w->cancel;
2335 $startup_done->();
2336});
2337
2158Event::loop; 2338Event::loop;
2339
2340#video_shutdown;
2341#audio_shutdown;
2159#CFPlus::SDL_Quit; 2342CFPlus::SDL_Quit;
2160#CFPlus::_exit 0;
2161
2162END {
2163 CFPlus::SDL_Quit;
2164 CFPlus::DB::Server::stop; 2343CFPlus::DB::Server::stop;
2165}
2166 2344
2167=head1 NAME 2345=head1 NAME
2168 2346
2169cfplus - A Crossfire+ and Crossfire game client 2347cfplus - A Crossfire TRT and Crossfire game client
2170 2348
2171=head1 SYNOPSIS 2349=head1 SYNOPSIS
2172 2350
2173Just run it - no commandline arguments are supported. 2351Just run it - no commandline arguments are supported.
2174 2352
2175=head1 USAGE 2353=head1 USAGE
2176 2354
2177cfplus utilises OpenGL for all UI elements and the game. It is supposed to be used 2355cfplus utilises OpenGL for all UI elements and the game. It is supposed to
2178fullscreen and interactively. 2356be used in fullscreen mode and interactively.
2179 2357
2180=head1 DEBUGGING 2358=head1 DEBUGGING
2181 2359
2182 2360
2183CFPLUS_DEBUG - environment variable 2361CFPLUS_DEBUG - environment variable

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines