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.198 by root, Tue Jul 31 02:45:39 2007 UTC vs.
Revision 1.225 by root, Fri Aug 31 08:03:10 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;
165our $STATUSBOX; 169our $STATUSBOX;
166our $DEBUG_STATUS; 170our $DEBUG_STATUS;
167 171
168our $INV; 172our $INV;
169our $INVR; 173our $INVR;
170our $INV_RIGHT_HB; 174our $INVR_HB;
171
172our $PICKUP_CFG;
173 175
174############################################################################# 176#############################################################################
175 177
176sub status { 178sub status {
177 $STATUSBOX->add (CFPlus::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]); 179 $STATUSBOX->add (CFPlus::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]);
180sub debug { 182sub debug {
181 $DEBUG_STATUS->set_text ($_[0]); 183 $DEBUG_STATUS->set_text ($_[0]);
182} 184}
183 185
184sub message { 186sub message {
185 my ($para) = @_;
186 $MESSAGE_WINDOW->message ($para); 187 $MESSAGE_WINDOW->message (@_);
187} 188}
188 189
189############################################################################# 190#############################################################################
190#TODO: maybe move into own audio module... 191#TODO: maybe move into own audio module...
191 192
211} 212}
212 213
213sub audio_sound_push($) { 214sub audio_sound_push($) {
214 my ($face) = @_; 215 my ($face) = @_;
215 216
217 $CFG->{effects_enable}
218 or return;
219
220 $AUDIO_PLAY{$face}
221 or return;
222
216 if (my $chunk = $AUDIO_CHUNK{$face}) { 223 if (my $chunk = $AUDIO_CHUNK{$face}) {
217 for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) { 224 for (grep $_->[0] >= Event::time, @{(delete $AUDIO_PLAY{$face}) || []}) {
218 my (undef, $dx, $dy, $vol) = @$_; 225 my (undef, $dx, $dy, $vol) = @$_;
219 226
220 my $channel = CFPlus::Channel::find; 227 my $channel = CFPlus::Channel::find;
221 $channel->volume ($vol * 128 / 255); 228 $channel->volume ($vol * $CFG->{effects_volume} * 128 / 255);
222 $dx = $dx / 10 * 255;
223 $channel->set_panning (255 - $dx, 255 + $dx);
224
225# my $angle = $dx ? : $dx < 0 ?
226# my $distance = -$vol;
227# $channel->set_position ($angle, $distance); 229 $channel->set_position_r ($dx, $dy, 20);
228
229 $chunk->play ($channel); 230 $chunk->play ($channel);
230 } 231 }
231 } else { 232 } else {
232 # sound_meta not set means data is in flight either way 233 # sound_meta not set means data is in flight either way
233 my $meta = $CONN->{sound_meta}{$face} 234 my $meta = $CONN->{face}[$face]
234 or return; 235 or return;
235 236
237 $meta->{data}
238 or return;
239
236 # if its a jingle, play it as ambient music 240 # if its a jingle, play it as ambient music
237 if ($meta->{meta}{jingle}) { 241 if ($meta->{data}{jingle}) {
238 delete $AUDIO_PLAY{$face}; # take the jingle out of the sound queue 242 if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue
239 push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue 243 push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue
240 &audio_music_push ($face); 244 &audio_music_push ($face);
245 }
241 } else { 246 } else {
242 # fetch from database 247 # fetch from database
243 CFPlus::DB::get res_data => $meta->{name}, sub { 248 CFPlus::DB::get res_data => $meta->{name}, sub {
244 my $rwops = new CFPlus::RW $_[0]; 249 my $rwops = new CFPlus::RW $_[0];
245 my $chunk = new CFPlus::MixChunk $rwops; 250 my $chunk = new CFPlus::MixChunk $rwops
251 or Carp::confess "sound face " . (JSON::XS::to_json $meta) . " unloadable: " . CFPlus::Mix_GetError;
246 $chunk->volume (($meta->{meta}{volume} || 1) * 128); 252 $chunk->volume (($meta->{data}{volume} || 1) * 128);
247 $AUDIO_CHUNK{$face} = $chunk; 253 $AUDIO_CHUNK{$face} = $chunk;
248 254
249 audio_sound_push ($face); 255 audio_sound_push ($face);
250 }; 256 };
251 } 257 }
255sub audio_sound_play { 261sub audio_sound_play {
256 my ($face, $dx, $dy, $vol) = @_; 262 my ($face, $dx, $dy, $vol) = @_;
257 263
258 $SDL_MIXER 264 $SDL_MIXER
259 or return; 265 or return;
266 $CFG->{effects_enable}
267 or return;
260 268
261 my $queue = $AUDIO_PLAY{$face} ||= []; 269 my $queue = $AUDIO_PLAY{$face} ||= [];
262 push @$queue, [Event::time + 0.2, $dx, $dy, $vol]; # delay sound by max. 0.2s 270 push @$queue, [Event::time + 0.6, $dx, $dy, $vol]; # do not play sound for outdated events
263 audio_sound_push $face 271 audio_sound_push $face
264 unless @$queue > 1; 272 unless @$queue > 1;
265} 273}
266 274
275sub audio_music_set_meta {
276 my ($meta) = @_;
277
278 $MUSIC_PLAYING_META = $meta;
279 $MUSIC_PLAYING_WIDGET->set_markup (
280 "<b>Name</b>: " . (CFPlus::asxml $meta->{data}{name}) . "\n"
281 . "<b>Author</b>: " . (CFPlus::asxml $meta->{data}{author}) . "\n"
282 . "<b>Source</b>: " . (CFPlus::asxml $meta->{data}{source}) . "\n"
283 . "<b>License</b>: " . (CFPlus::asxml $meta->{data}{license})
284 );
285}
286
267sub audio_music_update_volume { 287sub audio_music_update_volume {
268 return unless $MUSIC_PLAYING_META; 288 return unless $MUSIC_PLAYING_META;
269 my $volume = $MUSIC_PLAYING_META->{meta}{volume} || 1; 289 my $volume = $MUSIC_PLAYING_META->{data}{volume} || 1;
270 my $base = $MUSIC_PLAYING_META->{meta}{jingle} ? 1 : $CFG->{bgm_volume}; 290 my $base = $MUSIC_PLAYING_META->{data}{jingle} ? 1 : $CFG->{bgm_volume};
271 CFPlus::MixMusic::volume $base * $volume * 128; 291 CFPlus::MixMusic::volume $base * $volume * 128;
272} 292}
273 293
274sub audio_music_start { 294sub audio_music_start {
275 my $meta = $MUSIC_PLAYING_META; 295 my $meta = $MUSIC_PLAYING_META;
288 my $rwops = $meta->{path} 308 my $rwops = $meta->{path}
289 ? new_from_file CFPlus::RW $meta->{path} 309 ? new_from_file CFPlus::RW $meta->{path}
290 : new CFPlus::RW $$MUSIC_PLAYING_DATA; 310 : new CFPlus::RW $$MUSIC_PLAYING_DATA;
291 311
292 $MUSIC_PLAYER = new CFPlus::MixMusic $rwops 312 $MUSIC_PLAYER = new CFPlus::MixMusic $rwops
293 or ((warn CFPlus::Mix_GetError), return); # pretty fatal error 313 or Carp::confess "music face $meta->{face} unloadable: " . CFPlus::Mix_GetError;
294 314
295 my $NOW = time; 315 my $NOW = time;
296 316
297 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) { 317 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) {
298 my $pos = $MUSIC_PLAYING_META->{stop_pos}; 318 my $pos = $MUSIC_PLAYING_META->{stop_pos};
299 $MUSIC_PLAYER->fade_in_pos (0, 1000, $pos); 319 $MUSIC_PLAYER->fade_in_pos (0, 700, $pos);
300 $MUSIC_START = time - $pos; 320 $MUSIC_START = time - $pos;
301 } else { 321 } else {
302 $MUSIC_PLAYER->play (0); 322 $MUSIC_PLAYER->play (0);
303 $MUSIC_START = time; 323 $MUSIC_START = time;
304 } 324 }
305 325
306 delete $MUSIC_PLAYING_META->{stop_time}; 326 delete $meta->{stop_time};
307 delete $MUSIC_PLAYING_META->{stop_pos}; 327 delete $meta->{stop_pos};
308 } 328 }
309} 329}
310 330
311sub audio_music_push { 331sub audio_music_push {
312 return unless $SDL_MIXER; 332 return unless $SDL_MIXER;
318 $fade_out = 333; 338 $fade_out = 333;
319 } else { 339 } else {
320 return unless $CFG->{bgm_enable}; 340 return unless $CFG->{bgm_enable};
321 341
322 my @have = 342 my @have =
323 grep $_, 343 grep $_ && $_->{data},
324 map $CONN->{music_meta}{$_}, 344 map $CONN->{face}[$_],
325 @$MUSIC_WANT; 345 @$MUSIC_WANT;
346
347 # randomize music a bit so that the order is not always the same
348 $_->{stop_time} ||= rand for @have;
326 349
327 @MUSIC_HAVE = @have 350 @MUSIC_HAVE = @have
328 if @have; 351 if @have;
329 352
330 # default MUSIC_HAVE == MUSIC_DEFAULT 353 # default MUSIC_HAVE == MUSIC_DEFAULT
331 @MUSIC_HAVE = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_HAVE; 354 @MUSIC_HAVE = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_HAVE;
332 $fade_out = 1000; 355 $fade_out = 700;
333 } 356 }
334 357
335 # if the currently playing song is acceptable, let it continue 358 # if the currently playing song is acceptable, let it continue
336 return if $MUSIC_PLAYING_META
337 && grep $MUSIC_PLAYING_META == $_, @MUSIC_HAVE; 359 return if grep $MUSIC_PLAYING_META == $_, @MUSIC_HAVE;
338 360
339 my $NOW = time; 361 my $NOW = time;
340 362
341 if ($MUSIC_PLAYING_META) { 363 if ($MUSIC_PLAYING_META) {
342 $MUSIC_PLAYING_META->{stop_time} = $NOW; 364 $MUSIC_PLAYING_META->{stop_time} = $NOW;
346 # sort by stop time, oldest first 368 # sort by stop time, oldest first
347 @MUSIC_HAVE = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_HAVE; 369 @MUSIC_HAVE = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_HAVE;
348 370
349 # if the most recently-played piece played very recently, 371 # if the most recently-played piece played very recently,
350 # resume it, else choose the oldest piece for rotation. 372 # resume it, else choose the oldest piece for rotation.
351 $MUSIC_PLAYING_META = 373 audio_music_set_meta
352 $MUSIC_HAVE[-1]{stop_time} > $NOW - $MUSIC_RESUME 374 $MUSIC_HAVE[-1]{stop_pos} && $MUSIC_HAVE[-1]{stop_time} > $NOW - $MUSIC_RESUME
353 ? $MUSIC_HAVE[-1] 375 ? $MUSIC_HAVE[-1]
354 : $MUSIC_HAVE[0]; 376 : $MUSIC_HAVE[0];
355 377
356 audio_music_start; 378 audio_music_start;
357 } 379 }
363 $MUSIC_WANT = $songs; 385 $MUSIC_WANT = $songs;
364 audio_music_push; 386 audio_music_push;
365} 387}
366 388
367sub audio_music_finished { 389sub audio_music_finished {
390 if ($MUSIC_PLAYING_META) {
391 $MUSIC_PLAYING_META->{stop_time} = time;
392 }
393
368 # we compress multiple jingles of the same type 394 # we compress multiple jingles of the same type
369 shift @MUSIC_JINGLE 395 shift @MUSIC_JINGLE
370 while @MUSIC_JINGLE && $MUSIC_PLAYING_META == $MUSIC_JINGLE[0]; 396 while @MUSIC_JINGLE && $MUSIC_PLAYING_META == $MUSIC_JINGLE[0];
397
398 $MUSIC_PLAYING_WIDGET->clear;
371 399
372 undef $MUSIC_PLAYER; 400 undef $MUSIC_PLAYER;
373 undef $MUSIC_PLAYING_META; 401 undef $MUSIC_PLAYING_META;
374 undef $MUSIC_PLAYING_DATA; 402 undef $MUSIC_PLAYING_DATA;
375 403
750 state => $CFG->{fullscreen}, 778 state => $CFG->{fullscreen},
751 tooltip => "Bring the client into fullscreen mode.", 779 tooltip => "Bring the client into fullscreen mode.",
752 on_changed => sub { my ($self, $value) = @_; $CFG->{fullscreen} = $value; 0 } 780 on_changed => sub { my ($self, $value) = @_; $CFG->{fullscreen} = $value; 0 }
753 ); 781 );
754 782
783 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Force OpenGL 1.1");
784 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
785 state => $CFG->{force_opengl11},
786 tooltip => "Limit CFPlus to use OpenGL 1.1 features only. This will normally result in "
787 . "higher memory usage and slower performance. It will, however, help tremendously on "
788 . "cards that claim to support a feature but fall back to software rendering. "
789 . "Nvidia Geforce FX cards are known to claim features the hardware doesn't support, "
790 . "but cards and drivers from other vendors (ATI) are often just as bad. <b>If you "
791 . "experience extremely low framerates and your card should do better, try this option.</b>",
792 on_changed => sub { my ($self, $value) = @_; $CFG->{force_opengl11} = $value; 0 }
793 );
794
795 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Compress Textures");
796 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
797 state => $CFG->{texture_compression},
798 tooltip => "Use texture compression. Normally this will not reduce visual quality noticable but "
799 . "will save a lot of memory and increase performance. The compression algorithm "
800 . "can differ form card to card, so your mileage may vary. This setting is ignored in "
801 . "forced OpenGL 1.1 mode.",
802 on_changed => sub { my ($self, $value) = @_; $CFG->{texture_compression} = $value; 0 }
803 );
804
755 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fast & Ugly"); 805 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fast & Ugly");
756 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 806 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
757 state => $CFG->{fast}, 807 state => $CFG->{fast},
758 tooltip => "Lower the visual quality considerably to speed up rendering.", 808 tooltip => "Lower the visual quality considerably to speed up rendering.",
759 on_changed => sub { my ($self, $value) = @_; $CFG->{fast} = $value; 0 } 809 on_changed => sub { my ($self, $value) = @_; $CFG->{fast} = $value; 0 }
785 835
786 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Map Smoothing"); 836 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Map Smoothing");
787 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 837 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
788 state => $CFG->{map_smoothing}, 838 state => $CFG->{map_smoothing},
789 tooltip => "<b>Map Smoothing</b> tries to make tile borders less square. " 839 tooltip => "<b>Map Smoothing</b> tries to make tile borders less square. "
790 . "This increases load on the graphics subsystem and works only with 2.x servers. " 840 . "This increases load on the graphics subsystem and works only with TRT servers. "
791 . "Changes take effect at next connection only.", 841 . "Changes take effect at next login only.",
792 on_changed => sub { my ($self, $value) = @_; $CFG->{map_smoothing} = $value; 0 } 842 on_changed => sub { my ($self, $value) = @_; $CFG->{map_smoothing} = $value; 0 }
793 ); 843 );
794 844
795 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fog of War"); 845 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Fog of War");
796 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 846 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
807 ); 857 );
808 858
809 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Message Fontsize"); 859 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Message Fontsize");
810 $table->add_at (1, $row++, new CFPlus::UI::Slider 860 $table->add_at (1, $row++, new CFPlus::UI::Slider
811 range => [$CFG->{log_fontsize}, 0.5, 2, 0, 0.1], 861 range => [$CFG->{log_fontsize}, 0.5, 2, 0, 0.1],
812 tooltip => "The font size used by the <b>message/server log</b> window only. Changes are instant.", 862 tooltip => "The font size used by the <b>message/server log</b> window only. Changes are instant, "
863 . "but you still need to press apply to correctly re-layout the widget.",
813 on_changed => sub { $MESSAGE_WINDOW->set_fontsize ($CFG->{log_fontsize} = $_[1]); 0 }, 864 on_changed => sub { $MESSAGE_WINDOW->set_fontsize ($CFG->{log_fontsize} = $_[1]); 0 },
814 ); 865 );
815 866
816 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Gauge fontsize"); 867 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Gauge fontsize");
817 $table->add_at (1, $row++, new CFPlus::UI::Slider 868 $table->add_at (1, $row++, new CFPlus::UI::Slider
839} 890}
840 891
841sub audio_setup { 892sub audio_setup {
842 my $vbox = new CFPlus::UI::VBox; 893 my $vbox = new CFPlus::UI::VBox;
843 894
844 $vbox->add (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 1]); 895 $vbox->add (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 0, 1]);
845 896
846 my $row = 0; 897 my $row = 0;
847 898
848 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Audio Enable"); 899 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Audio Enable");
849 $table->add_at (1, $row++, new CFPlus::UI::CheckBox 900 $table->add_at (1, $row++, new CFPlus::UI::CheckBox
853 ); 904 );
854# $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume"); 905# $table->add_at (0, 9, new CFPlus::UI::Label valign => 0, align => 1, text => "Effects Volume");
855# $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub { 906# $table->add_at (1, 8, new CFPlus::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub {
856# $CFG->{effects_volume} = $_[1]; 907# $CFG->{effects_volume} = $_[1];
857# }); 908# });
909
910 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Sound Effects");
911 $table->add_at (1, $row, new CFPlus::UI::CheckBox
912 expand => 1, state => $CFG->{effects_enable},
913 tooltip => "If enabled, sound effects are enabled. If disabled, no sound effects will be played.",
914 on_changed => sub {
915 $CFG->{effects_enable} = $_[1];
916 $CONN->update_fx_want if $CONN;
917 0
918 }
919 );
920 $table->add_at (2, $row++, new CFPlus::UI::Slider
921 expand => 1, range => [$CFG->{effects_volume}, 0, 1, 0, 1/128],
922 tooltip => "The relative volume of sound effects. Best audio quality is achieved if this "
923 . "is set highest (rightmost) and you use your operating system volume setting. Changes are instant.",
924 on_changed => sub { $CFG->{effects_volume} = $_[1]; 0 }
925 );
926
858 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music"); 927 $table->add_at (0, $row, new CFPlus::UI::Label valign => 0, align => 1, text => "Background Music");
859 $table->add_at (1, $row++, my $hbox = new CFPlus::UI::HBox); 928 $table->add_at (1, $row, new CFPlus::UI::CheckBox
860 $hbox->add (new CFPlus::UI::CheckBox
861 expand => 1, state => $CFG->{bgm_enable}, 929 expand => 1, state => $CFG->{bgm_enable},
862 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.", 930 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.",
863 on_changed => sub { $CFG->{bgm_enable} = $_[1]; 0 } 931 on_changed => sub {
932 $CFG->{bgm_enable} = $_[1];
933 $CONN->update_fx_want if $CONN;
934 audio_music_push;
935 0
936 }
864 ); 937 );
865 $hbox->add (new CFPlus::UI::Slider 938 $table->add_at (2, $row++, new CFPlus::UI::Slider
866 expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128], 939 expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128],
867 tooltip => "The volume of the background music. Changes are instant.", 940 tooltip => "The volume of the background music. Changes are instant.",
868 on_changed => sub { $CFG->{bgm_volume} = $_[1]; audio_music_update_volume; 0 } 941 on_changed => sub { $CFG->{bgm_volume} = $_[1]; audio_music_update_volume; 0 }
869 ); 942 );
870 943
871 $table->add_at (1, $row++, new CFPlus::UI::Button 944 $table->add_at (1, $row++, new CFPlus::UI::Button
872 expand => 1, align => 0, text => "Apply", 945 c_colspan => 2, expand => 1, align => 0, text => "Apply",
873 tooltip => "Apply the audio settings", 946 tooltip => "Apply the audio settings",
874 on_activate => sub { 947 on_activate => sub {
875 audio_shutdown (); 948 audio_shutdown ();
876 audio_init (); 949 audio_init ();
877 0 950 0
919 $hb->add (my $hg = new CFPlus::UI::Gauge type => 'hp', tooltip => "#stat_health"); 992 $hb->add (my $hg = new CFPlus::UI::Gauge type => 'hp', tooltip => "#stat_health");
920 $hb->add (my $mg = new CFPlus::UI::Gauge type => 'mana', tooltip => "#stat_mana"); 993 $hb->add (my $mg = new CFPlus::UI::Gauge type => 'mana', tooltip => "#stat_mana");
921 $hb->add (my $gg = new CFPlus::UI::Gauge type => 'grace', tooltip => "#stat_grace"); 994 $hb->add (my $gg = new CFPlus::UI::Gauge type => 'grace', tooltip => "#stat_grace");
922 $hb->add (my $fg = new CFPlus::UI::Gauge type => 'food', tooltip => "#stat_food"); 995 $hb->add (my $fg = new CFPlus::UI::Gauge type => 'food', tooltip => "#stat_food");
923 996
924 $vbox->add (my $exp = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_exp"); 997 $vbox->add (my $exp = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_exp");
998 $vbox->add (my $prg = new CFPlus::UI::ExperienceProgress);
999 $vbox->add (my $sklprg = new CFPlus::UI::ExperienceProgress);
925 $vbox->add (my $rng = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_ranged"); 1000 $vbox->add (my $rng = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_ranged");
926 1001
927 $GAUGES = { 1002 $GAUGES = {
1003 exp => $exp, prg => $prg, sklprg => $sklprg,
928 exp => $exp, win => $win, range => $rng, 1004 win => $win, range => $rng,
929 food => $fg, mana => $mg, hp => $hg, grace => $gg 1005 hp => $hg, mana => $mg, grace => $gg, food => $fg,
930 }; 1006 };
931 1007
932 &set_gauge_window_fontsize; 1008 &set_gauge_window_fontsize;
933 1009
934 $win 1010 $win
948 $table->add_at (0, 4, new CFPlus::UI::Button text => "die on click(tm)", on_activate => sub { &CFPlus::debug() } ); 1024 $table->add_at (0, 4, new CFPlus::UI::Button text => "die on click(tm)", on_activate => sub { &CFPlus::debug() } );
949 1025
950 $table->add_at (0, 5, new CFPlus::UI::TextEdit text => "line1\0152\0153");#d# 1026 $table->add_at (0, 5, new CFPlus::UI::TextEdit text => "line1\0152\0153");#d#
951 1027
952 $table->add_at (7,7, my $t = new CFPlus::UI::Table expand => 0); 1028 $table->add_at (7,7, my $t = new CFPlus::UI::Table expand => 0);
953 $t->add_at (0,0, new CFPlus::UI::Label text => "a a a a", rowspan => 1, colspan => 2); 1029 $t->add_at (0,0, new CFPlus::UI::Label text => "a a a a", c_rowspan => 1, c_colspan => 2);
954 $t->add_at (2,0, new CFPlus::UI::Label text => "b\nb", rowspan => 2, colspan => 1); 1030 $t->add_at (2,0, new CFPlus::UI::Label text => "b\nb", c_rowspan => 2, c_colspan => 1);
955 $t->add_at (1,2, new CFPlus::UI::Label text => "c c c c", rowspan => 1, colspan => 2); 1031 $t->add_at (1,2, new CFPlus::UI::Label text => "c c c c", c_rowspan => 1, c_colspan => 2);
956 $t->add_at (0,1, new CFPlus::UI::Label text => "d\nd", rowspan => 2, colspan => 1); 1032 $t->add_at (0,1, new CFPlus::UI::Label text => "d\nd", c_rowspan => 2, c_colspan => 1);
957 $t->add_at (1,1, new CFPlus::UI::Label text => "e"); 1033 $t->add_at (1,1, new CFPlus::UI::Label text => "e");
958 1034
959 $table->add_at (7, 6, my $c = new CFPlus::UI::Canvas); 1035 $table->add_at (7, 6, my $c = new CFPlus::UI::Canvas);
960 1036
961 $c->add_items ({ 1037 $c->add_items ({
1135 $r 1211 $r
1136} 1212}
1137 1213
1138sub skill_window { 1214sub skill_window {
1139 my $sw = new CFPlus::UI::ScrolledWindow (expand => 1); 1215 my $sw = new CFPlus::UI::ScrolledWindow (expand => 1);
1216
1140 $sw->add ($STATWIDS->{skill_tbl} = new CFPlus::UI::Table expand => 1, col_expand => [0, 0, 1, 0, 0, 1]); 1217 $sw->add ($STATWIDS->{skill_tbl} = new CFPlus::UI::Table expand => 1, col_expand => [0, 0, 1, .1, 0, 0, 1, .1]);
1218
1141 $sw 1219 $sw
1142} 1220}
1143 1221
1144sub formsep($) { 1222sub formsep($) {
1145 scalar reverse join ",", unpack "(A3)*", reverse $_[0] * 1 1223 scalar reverse join ",", unpack "(A3)*", reverse $_[0] * 1
1557 $sw1->add ($INV = new CFPlus::UI::Inventory); 1635 $sw1->add ($INV = new CFPlus::UI::Inventory);
1558 $INV->set_sort_order ($SORT_ORDER{$::CFG->{inv_sort}}); 1636 $INV->set_sort_order ($SORT_ORDER{$::CFG->{inv_sort}});
1559 1637
1560 $hb->add (my $vb2 = new CFPlus::UI::VBox); 1638 $hb->add (my $vb2 = new CFPlus::UI::VBox);
1561 1639
1562 $vb2->add ($INV_RIGHT_HB = new CFPlus::UI::HBox); 1640 $vb2->add ($INVR_HB = new CFPlus::UI::HBox);
1563 1641
1564 $vb2->add (my $sw2 = new CFPlus::UI::ScrolledWindow expand => 1, scroll_y => 1); 1642 $vb2->add (my $sw2 = new CFPlus::UI::ScrolledWindow expand => 1, scroll_y => 1);
1565 $sw2->add ($INVR = new CFPlus::UI::Inventory); 1643 $sw2->add ($INVR = new CFPlus::UI::Inventory);
1566 1644
1567 # XXX: Call after $INVR = ... because set_opencont sets the items 1645 # XXX: Call after $INVR = ... because set_opencont sets the items
1568 CFPlus::Protocol::set_opencont ($::CONN, 0, "Floor"); 1646 CFPlus::Protocol::set_opencont ($::CONN, 0, "Floor");
1569 1647
1570 $hb 1648 $hb
1649}
1650
1651sub media_window {
1652 my $vb = new CFPlus::UI::VBox;
1653
1654 $vb->add (new CFPlus::UI::FancyFrame
1655 label => "Currently playing music",
1656 child => new CFPlus::UI::ScrolledWindow scroll_x => 1, scroll_y => 0,
1657 child => ($MUSIC_PLAYING_WIDGET = new CFPlus::UI::Label ellipsise => 0, fontsize => 0.8),
1658 );
1659
1660 $vb->add (new CFPlus::UI::FancyFrame
1661 label => "Other media used in this session",
1662 expand => 1,
1663 child => ($LICENSE_WIDGET = new CFPlus::UI::TextScroller
1664 expand => 1, fontsize => 0.8, padding_x => 4, padding_y => 4),
1665 );
1666
1667 $vb
1668}
1669
1670sub add_license {
1671 my ($meta) = @_;
1672
1673 $meta = $meta->{data}
1674 or return;
1675
1676 $meta->{license} || $meta->{author} || $meta->{source}
1677 or return;
1678
1679 $LICENSE_WIDGET->add_paragraph ({
1680 fg => [1, 1, 1, 1],
1681 markup => "<small>"
1682 . "<b>Name:</b> " . (CFPlus::asxml $meta->{name}) . "\n"
1683 . "<b>Author:</b> " . (CFPlus::asxml $meta->{author}) . "\n"
1684 . "<b>Source:</b> " . (CFPlus::asxml $meta->{source}) . "\n"
1685 . "<b>License:</b> " . (CFPlus::asxml $meta->{license}) . "\n"
1686 . "</small>",
1687 });
1688 $LICENSE_WIDGET->scroll_to_bottom;
1571} 1689}
1572 1690
1573sub toggle_player_page { 1691sub toggle_player_page {
1574 my ($widget) = @_; 1692 my ($widget) = @_;
1575 1693
1614 $ntb->add_tab ( 1732 $ntb->add_tab (
1615 "Inventory (F5)" => $INVENTORY_PAGE = inventory_widget, 1733 "Inventory (F5)" => $INVENTORY_PAGE = inventory_widget,
1616 "Toggles the inventory window, where you can manage your loot (or treasures :). " 1734 "Toggles the inventory window, where you can manage your loot (or treasures :). "
1617 . "You can also hit the <b>Tab</b>-key to show/hide the Inventory." 1735 . "You can also hit the <b>Tab</b>-key to show/hide the Inventory."
1618 ); 1736 );
1619 $ntb->add_tab (Pickup => autopickup_setup, 1737 $ntb->add_tab (Pickup => $PICKUP_PAGE = autopickup_setup,
1620 "Configure autopickup settings, i.e. which items you will pick up automatically when walking (or running) over them."); 1738 "Configure autopickup settings, i.e. which items you will pick up automatically when walking (or running) over them.");
1739
1740 $ntb->add_tab (Media => media_window,
1741 "License, Author and Source info for media sent by the server.");
1621 1742
1622 $ntb->set_current_page ($INVENTORY_PAGE); 1743 $ntb->set_current_page ($INVENTORY_PAGE);
1623 1744
1624 $plwin->add ($ntb); 1745 $plwin->add ($ntb);
1625 $plwin 1746 $plwin
1779 on_activate => sub { $QUIT_DIALOG->hide; 0 }, 1900 on_activate => sub { $QUIT_DIALOG->hide; 0 },
1780 ); 1901 );
1781 $hb->add (new CFPlus::UI::Button 1902 $hb->add (new CFPlus::UI::Button
1782 text => "Quit anyway", 1903 text => "Quit anyway",
1783 expand => 1, 1904 expand => 1,
1784 on_activate => sub { exit }, 1905 on_activate => sub { Event::unloop_all },
1785 ); 1906 );
1786 } 1907 }
1787 1908
1788 $QUIT_DIALOG->show; 1909 $QUIT_DIALOG->show;
1789 $QUIT_DIALOG->grab_focus; 1910 $QUIT_DIALOG->grab_focus;
1862 1983
1863 $SDL_ACTIVE = 1; 1984 $SDL_ACTIVE = 1;
1864 $LAST_REFRESH = time - 0.01; 1985 $LAST_REFRESH = time - 0.01;
1865 1986
1866 CFPlus::OpenGL::init; 1987 CFPlus::OpenGL::init;
1988 CFPlus::Macro::init;
1867 1989
1868 $FONTSIZE = int $HEIGHT / 40 * $CFG->{gui_fontsize}; 1990 $FONTSIZE = int $HEIGHT / 40 * $CFG->{gui_fontsize};
1869 1991
1870 $CFPlus::UI::ROOT->configure (0, 0, $WIDTH, $HEIGHT);#d# 1992 $CFPlus::UI::ROOT->configure (0, 0, $WIDTH, $HEIGHT);#d#
1871 1993
1872 ############################################################################# 1994 #############################################################################
1873 1995
1874 if ($DEBUG_STATUS) { 1996 if ($DEBUG_STATUS) {
1875 CFPlus::UI::rescale_widgets $WIDTH / $old_w, $HEIGHT / $old_h; 1997 CFPlus::UI::rescale_widgets $WIDTH / $old_w, $HEIGHT / $old_h;
1876 } else { 1998 } else {
1877 # create the widgets 1999 # create/configure the widgets
2000
2001 $CFPlus::UI::ROOT->connect (key_down => sub {
2002 my (undef, $ev) = @_;
2003
2004 if (my @macros = CFPlus::Macro::find $ev) {
2005 CFPlus::Macro::execute $_ for @macros;
2006
2007 return 1;
2008 }
2009
2010 0
2011 });
1878 2012
1879 $DEBUG_STATUS = new CFPlus::UI::Label 2013 $DEBUG_STATUS = new CFPlus::UI::Label
1880 padding => 0, 2014 padding => 0,
1881 z => 100, 2015 z => 100,
1882 force_x => "max", 2016 force_x => "max",
1912 $MESSAGE_WINDOW->activate_console ($preset) 2046 $MESSAGE_WINDOW->activate_console ($preset)
1913 if $MESSAGE_WINDOW; 2047 if $MESSAGE_WINDOW;
1914 }); 2048 });
1915 $MAPWIDGET->show; 2049 $MAPWIDGET->show;
1916 $MAPWIDGET->grab_focus; 2050 $MAPWIDGET->grab_focus;
2051
2052 $COMPLETER = new CFPlus::MapWidget::Command::
2053 command => { },
2054 tooltip => "#completer_help",
2055 ;
1917 2056
1918 $SETUP_DIALOG = new CFPlus::UI::Toplevel 2057 $SETUP_DIALOG = new CFPlus::UI::Toplevel
1919 title => "Setup", 2058 title => "Setup",
1920 name => "setup_dialog", 2059 name => "setup_dialog",
1921 x => 'center', 2060 x => 'center',
1983 tooltip => "Terminates the program", 2122 tooltip => "Terminates the program",
1984 on_activate => sub { 2123 on_activate => sub {
1985 if ($CONN) { 2124 if ($CONN) {
1986 open_quit_dialog; 2125 open_quit_dialog;
1987 } else { 2126 } else {
1988 exit; 2127 Event::unloop_all;
1989 } 2128 }
1990 0 2129 0
1991 }, 2130 },
1992 ); 2131 );
1993 2132
1994 $BUTTONBAR->show; 2133 $BUTTONBAR->show;
1995 $SETUP_DIALOG->show; 2134 $SETUP_DIALOG->show;
2135 $MESSAGE_WINDOW->show;
1996 } 2136 }
1997 2137
1998 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); 2138 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]);
1999} 2139}
2000 2140
2008my $animate_timer; 2148my $animate_timer;
2009 2149
2010my $fps = 9; 2150my $fps = 9;
2011 2151
2012sub force_refresh { 2152sub force_refresh {
2153 if ($ENV{CFPLUS_DEBUG} & 4) {
2013 $fps = $fps * 0.95 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.05; 2154 $fps = $fps * 0.98 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.02;
2014 debug sprintf "%3.2f", $fps if $ENV{CFPLUS_DEBUG} & 4; 2155 debug sprintf "%3.2f", $fps;
2156 }
2015 2157
2016 $CFPlus::UI::ROOT->draw; 2158 $CFPlus::UI::ROOT->draw;
2017 2159 CFPlus::SDL_GL_SwapBuffers;
2018 $WANT_REFRESH = 0;
2019 $CAN_REFRESH = 0;
2020 $LAST_REFRESH = $NOW; 2160 $LAST_REFRESH = $NOW;
2021 2161 $WANT_REFRESH->stop;
2022 CFPlus::SDL_GL_SwapBuffers;
2023} 2162}
2024 2163
2164$WANT_REFRESH = Event->idle (min => 0.001, max => 0.06, parked => 1, cb => \&force_refresh);
2165
2025my $refresh_watcher = Event->timer (after => 0, hard => 0, interval => 1 / $MAX_FPS, cb => sub { 2166my $input = Event->timer (after => 0, hard => 0, interval => 1 / 50, cb => sub {
2026 $NOW = time; 2167 $NOW = time;
2027 2168
2028 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_) 2169 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_)
2029 for CFPlus::poll_events; 2170 for CFPlus::poll_events;
2030 2171
2031 if (%animate_object) { 2172 if (%animate_object) {
2032 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object; 2173 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object;
2033 ++$WANT_REFRESH; 2174 $WANT_REFRESH->start;
2034 }
2035
2036 if ($WANT_REFRESH) {
2037 force_refresh;
2038 } else {
2039 $CAN_REFRESH = 1;
2040 } 2175 }
2041}); 2176});
2042 2177
2043sub animation_start { 2178sub animation_start {
2044 my ($widget) = @_; 2179 my ($widget) = @_;
2050 delete $animate_object{$widget}; 2185 delete $animate_object{$widget};
2051} 2186}
2052 2187
2053%SDL_CB = ( 2188%SDL_CB = (
2054 CFPlus::SDL_QUIT => sub { 2189 CFPlus::SDL_QUIT => sub {
2055 exit; 2190 Event::unloop_all;
2056 }, 2191 },
2057 CFPlus::SDL_VIDEORESIZE => sub { 2192 CFPlus::SDL_VIDEORESIZE => sub {
2058 }, 2193 },
2059 CFPlus::SDL_VIDEOEXPOSE => sub { 2194 CFPlus::SDL_VIDEOEXPOSE => sub {
2060 CFPlus::UI::full_refresh; 2195 CFPlus::UI::full_refresh;
2099 CFPlus::DB::Server::run; 2234 CFPlus::DB::Server::run;
2100 2235
2101 CFPlus::UI::set_layout ($::CFG->{layout}); 2236 CFPlus::UI::set_layout ($::CFG->{layout});
2102 2237
2103 my %DEF_CFG = ( 2238 my %DEF_CFG = (
2104 sdl_mode => 0, 2239 sdl_mode => 0,
2105 fullscreen => 0, 2240 fullscreen => 0,
2106 fast => 0, 2241 fast => 0,
2242 force_opengl11 => undef,
2243 texture_compression => 1,
2107 map_scale => 1, 2244 map_scale => 1,
2108 fow_enable => 1, 2245 fow_enable => 1,
2109 fow_intensity => 0, 2246 fow_intensity => 0,
2110 map_smoothing => 1, 2247 map_smoothing => 1,
2111 gui_fontsize => 1, 2248 gui_fontsize => 1,
2112 log_fontsize => 0.7, 2249 log_fontsize => 0.7,
2113 gauge_fontsize => 1, 2250 gauge_fontsize => 1,
2114 gauge_size => 0.35, 2251 gauge_size => 0.35,
2115 stat_fontsize => 0.7, 2252 stat_fontsize => 0.7,
2116 mapsize => 100, 2253 mapsize => 100,
2117 audio_enable => 1, 2254 audio_enable => 1,
2255 effects_enable => 1,
2256 effects_volume => 1,
2118 bgm_enable => 1, 2257 bgm_enable => 1,
2119 bgm_volume => 0.25, 2258 bgm_volume => 0.5,
2120 output_sync => 1, 2259 output_sync => 1,
2121 output_count => 1, 2260 output_count => 1,
2122 output_rate => "", 2261 output_rate => "",
2123 pickup => 0, 2262 pickup => 0,
2124 inv_sort => "mtime", 2263 inv_sort => "mtime",
2125 default => "profile", # default profile 2264 default => "profile", # default profile
2126 show_tips => 1, 2265 show_tips => 1,
2127 logview_max_par => 1000, 2266 logview_max_par => 1000,
2128 ); 2267 );
2129 2268
2130 while (my ($k, $v) = each %DEF_CFG) { 2269 while (my ($k, $v) = each %DEF_CFG) {
2131 $CFG->{$k} = $v unless exists $CFG->{$k}; 2270 $CFG->{$k} = $v unless exists $CFG->{$k};
2132 } 2271 }
2189# } 2328# }
2190# my $t2 = Time::HiRes::time; 2329# my $t2 = Time::HiRes::time;
2191# warn $t2-$t1; 2330# warn $t2-$t1;
2192# } 2331# }
2193 2332
2194 $startup_done->();
2195
2196 video_init; 2333 video_init;
2197 audio_init; 2334 audio_init;
2198} 2335}
2199 2336
2200show_tip_of_the_day if $CFG->{show_tips}; 2337show_tip_of_the_day if $CFG->{show_tips};
2201 2338
2339Event->idle (cb => sub {
2340 $_[0]->w->cancel;
2341 $startup_done->();
2342});
2343
2202Event::loop; 2344Event::loop;
2345
2346#video_shutdown;
2347#audio_shutdown;
2203#CFPlus::SDL_Quit; 2348CFPlus::SDL_Quit;
2204#CFPlus::_exit 0;
2205
2206END {
2207 CFPlus::SDL_Quit;
2208 CFPlus::DB::Server::stop; 2349CFPlus::DB::Server::stop;
2209}
2210 2350
2211=head1 NAME 2351=head1 NAME
2212 2352
2213cfplus - A Crossfire+ and Crossfire game client 2353cfplus - A Crossfire TRT and Crossfire game client
2214 2354
2215=head1 SYNOPSIS 2355=head1 SYNOPSIS
2216 2356
2217Just run it - no commandline arguments are supported. 2357Just run it - no commandline arguments are supported.
2218 2358
2219=head1 USAGE 2359=head1 USAGE
2220 2360
2221cfplus utilises OpenGL for all UI elements and the game. It is supposed to be used 2361cfplus utilises OpenGL for all UI elements and the game. It is supposed to
2222fullscreen and interactively. 2362be used in fullscreen mode and interactively.
2223 2363
2224=head1 DEBUGGING 2364=head1 DEBUGGING
2225 2365
2226 2366
2227CFPLUS_DEBUG - environment variable 2367CFPLUS_DEBUG - environment variable

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines