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

Comparing deliantra/Deliantra-Client/bin/deliantra (file contents):
Revision 1.79 by root, Fri Dec 19 22:06:53 2008 UTC vs.
Revision 1.111 by root, Mon Apr 12 02:46:55 2010 UTC

17 $zip->extractMember ("SPLASH.bmp", "$ENV{PAR_TEMP}/SPLASH.bmp"); 17 $zip->extractMember ("SPLASH.bmp", "$ENV{PAR_TEMP}/SPLASH.bmp");
18 } 18 }
19 19
20 require Win32::GUI::SplashScreen; 20 require Win32::GUI::SplashScreen;
21 21
22 # initialise the resolver now, as vista forces us back to the desktop
23 # when doing this.
24 use AnyEvent::DNS ();
25 AnyEvent::DNS::resolver;
26
22 Win32::GUI::SplashScreen::Show ( 27 Win32::GUI::SplashScreen::Show (
23 -file => "$ENV{PAR_TEMP}/SPLASH.bmp", 28 -file => "$ENV{PAR_TEMP}/SPLASH.bmp",
24 ); 29 );
25 30
26 $startup_done = sub { 31 $startup_done = sub {
27 Win32::GUI::SplashScreen::Done (1); 32 Win32::GUI::SplashScreen::Done (1);
28 }; 33 };
29 } 34 }
30} 35}
31 36
32use strict; 37use common::sense;
33use utf8;
34 38
35use Carp 'verbose'; 39use Carp 'verbose';
36 40
37# do things only needed for single-binary version (par) 41# do things only needed for single-binary version (par)
38BEGIN { 42BEGIN {
51 55
52 if ($^O eq "MSWin32") { 56 if ($^O eq "MSWin32") {
53 # pango is relocatable on win32 57 # pango is relocatable on win32
54 } else { 58 } else {
55 # OS X 59 # OS X
56 $ENV{FONTCONFIG_FILE} = "$root/fonts.conf"; # no effect??!?!
57 $ENV{FONTCONFIG_DIR} = $root; # no effect??!?!
58 $ENV{PANGO_RC_FILE} = "$root/pango.rc"; 60 $ENV{PANGO_RC_FILE} = "$root/pango.rc";
59 $ENV{DYLD_LIBRARY_PATH} = $root; 61 $ENV{DYLD_LIBRARY_PATH} = $root;
60 chdir $root; # for pango modules, maybe other things 62 chdir $root; # for pango modules, maybe other things
61 } 63 }
62 64
63 unshift @INC, $root; 65 unshift @INC, $root;
64 } 66 }
65} 67}
66 68
67# prepend private library directory 69# prepend private library directory and prepare env
68BEGIN { 70BEGIN {
69 for (grep !ref, @INC) { 71 for (grep !ref, @INC) {
70 my $path = "$_/Deliantra/Client/private"; 72 my $path = "$_/Deliantra/Client/private";
71 if (-d $path) { 73 if (-d $path) {
72 unshift @INC, $path; 74 unshift @INC, $path;
86 88
87use Deliantra; 89use Deliantra;
88use Deliantra::Protocol::Constants; 90use Deliantra::Protocol::Constants;
89 91
90use AnyEvent::Util (); 92use AnyEvent::Util ();
91use AnyEvent::DNS;
92use AnyEvent::Socket (); 93use AnyEvent::Socket ();
94use AnyEvent::DNS ();
93 95
94use Compress::LZF; 96use Compress::LZF;
95use JSON::XS; 97use JSON::XS;
96 98
97use DC; 99use DC;
125 127
126$SIG{QUIT} = sub { Carp::cluck "QUIT" }; 128$SIG{QUIT} = sub { Carp::cluck "QUIT" };
127$SIG{PIPE} = 'IGNORE'; 129$SIG{PIPE} = 'IGNORE';
128 130
129$EV::DIED = sub { 131$EV::DIED = sub {
130 crash "CRASH/EV::DIED: $@" => 1; 132 crash "CRASH/EV::DIED: $@" => 0;
131 DC::fatal Carp::longmess $@; 133 DC::fatal Carp::longmess $@;
132}; 134};
133 135
134my $MAX_FPS = 60; 136my $MAX_FPS = 60;
137
138our $DEFAULT_SERVER = "gameserver.deliantra.net";
135 139
136our $META_SERVER = "http://metaserver.schmorp.de/current.json"; 140our $META_SERVER = "http://metaserver.schmorp.de/current.json";
137 141
138our $LAST_REFRESH; 142our $LAST_REFRESH;
139our $NOW; 143our $NOW;
140 144
141our $CFG; 145our $CFG;
142our $PROFILE; # current profile 146our $PROFILE; # current profile
143our $FAST; # fast, low-quality mode, possibly useful for software-rendering 147our $FAST; # fast, low-quality mode, possibly useful for software-rendering
148our $DELIANTRA_DEBUG = $ENV{DELIANTRA_DEBUG} * 1;
144 149
145our $WANT_REFRESH; 150our $WANT_REFRESH;
146 151
147our $MODE_SLIDER; 152our $MODE_SLIDER;
148our $CAVEAT_LABEL; 153our $CAVEAT_LABEL;
161 166
162our $MAP; 167our $MAP;
163our $MAPMAP; 168our $MAPMAP;
164our $MAPWIDGET; 169our $MAPWIDGET;
165our $COMPLETER; 170our $COMPLETER;
166our $BUTTONBAR; 171our $MENUFRAME; # the rectangle at the top
172our $MENUBAR; # the hbox at the top
173our $MENUPOPUP;
174our $BUTTONBAR; # the menu buttons
167our $METASERVER; 175our $METASERVER;
168our $LOGIN_BUTTON; 176our $LOGIN_BUTTON;
169our $QUIT_DIALOG; 177our $QUIT_DIALOG;
170our $HOST_ENTRY; 178our $HOST_ENTRY;
171our $FULLSCREEN_ENABLE; 179our $FULLSCREEN_ENABLE;
197our $FLOORBOX; 205our $FLOORBOX;
198our $GAUGES; 206our $GAUGES;
199our $STATWIDS; 207our $STATWIDS;
200 208
201our $SDL_ACTIVE; 209our $SDL_ACTIVE;
202our %SDL_CB; 210our @SDL_CB;
203 211
204our $ALT_ENTER_MESSAGE; 212our $ALT_ENTER_MESSAGE;
205our $STATUSBOX; 213our $STATUSBOX;
206our $MODBOX; 214our $MODBOX;
207our $DEBUG_STATUS; 215our $DEBUG_STATUS;
215# write a crash message blockingly to the socket, if possible 223# write a crash message blockingly to the socket, if possible
216# this is a bit too complicated for my tastes, but it was easy. 224# this is a bit too complicated for my tastes, but it was easy.
217*crash = sub($;$) { 225*crash = sub($;$) {
218 my ($msg, $backtrace) = @_; 226 my ($msg, $backtrace) = @_;
219 227
228 warn $msg;
229
220 return unless $CONN; 230 return unless $CONN;
221 231
222 my $fh = $CONN->{fh} 232 my $fh = $CONN->{fh}
223 or return; 233 or return;
224 234
234 244
235 # backtrace as second step, in case it crashes, too 245 # backtrace as second step, in case it crashes, too
236 crash Carp::longmess "$msg\nbacktrace, for client version $DC::VERSION, generated" 246 crash Carp::longmess "$msg\nbacktrace, for client version $DC::VERSION, generated"
237 if $backtrace; 247 if $backtrace;
238}; 248};
249
250sub clienterror($;$) {
251 my ($msg, $backtrace) = @_;
252
253 warn $msg;
254
255 return unless $CONN;
256
257 $CONN->send_exti_msg (clientlog => $msg);
258 $CONN->send_exti_msg (clientlog => Carp::longmess "$msg\nbacktrace, for client version $DC::VERSION, generated") if $backtrace;
259}
239 260
240############################################################################# 261#############################################################################
241 262
242sub status { 263sub status {
243 $STATUSBOX->add (DC::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]); 264 $STATUSBOX->add (DC::asxml $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]);
325 or return; 346 or return;
326 347
327 $meta->{data} 348 $meta->{data}
328 or return; 349 or return;
329 350
330 # if its a jingle, play it as ambient music 351 # if it's a jingle, play it as ambient music
331 if ($meta->{data}{jingle}) { 352 if ($meta->{data}{jingle}) {
332 if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue 353 if (delete $AUDIO_PLAY{$face}) { # take the jingle out of the sound queue
333 push @MUSIC_JINGLE, $meta; # push it oto the music/jingle queue 354 push @MUSIC_JINGLE, $meta; # push it unto the music/jingle queue
334 &audio_music_push ($face); 355 &audio_music_push ($face);
335 } 356 }
336 } else { 357 } else {
337 # fetch from database 358 # fetch from database
338 DC::DB::get res_data => $meta->{name}, sub { 359 DC::DB::get res_data => $meta->{name}, sub {
339 my $rwops = new DC::RW $_[0]; 360 my $rwops = new DC::RW $_[0];
340 my $chunk = new DC::MixChunk $rwops 361 my $chunk = new DC::MixChunk $rwops
341 or Carp::confess "sound face " . (JSON::XS::encode_json $meta) . " unloadable: " . DC::Mix_GetError; 362 or Carp::confess "sound face " . (JSON::XS::encode_json $meta) . " (" . (unpack "H64", $_[0]) . ") unloadable: " . DC::Mix_GetError;
342 $chunk->volume (($meta->{data}{volume} || 1) * 128); 363 $chunk->volume (($meta->{data}{volume} || 1) * 128);
343 $AUDIO_CHUNK{$face} = $chunk; 364 $AUDIO_CHUNK{$face} = $chunk;
344 365
345 audio_sound_push ($face); 366 audio_sound_push ($face);
346 }; 367 };
393 414
394 audio_music_update_volume; 415 audio_music_update_volume;
395 416
396 $MUSIC_PLAYING_DATA = \$_[0]; 417 $MUSIC_PLAYING_DATA = \$_[0];
397 418
419 $meta->{path} or length $_[0]
420 or return clienterror "empty music face from res_data ($meta->{face})";#d#
421
398 my $rwops = $meta->{path} 422 my $rwops = $meta->{path}
399 ? new_from_file DC::RW $meta->{path} 423 ? (new_from_file DC::RW $meta->{path} or return clienterror "unable to load music face $meta->{path}: $!")#d#clienterror
400 : new DC::RW $$MUSIC_PLAYING_DATA; 424 : new DC::RW $$MUSIC_PLAYING_DATA;
401 425
402 $MUSIC_PLAYER = new DC::MixMusic $rwops 426 $MUSIC_PLAYER = new DC::MixMusic $rwops
403 or Carp::confess "music face $meta->{face} unloadable: " . DC::Mix_GetError; 427 or return clienterror "music face $meta->{face} unloadable: " . DC::Mix_GetError => 1;
404 428
405 my $NOW = time; 429 my $NOW = time;
406 430
407 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) { 431 if ($MUSIC_PLAYING_META->{stop_time} > $NOW - $MUSIC_RESUME) {
408 my $pos = $MUSIC_PLAYING_META->{stop_pos}; 432 my $pos = $MUSIC_PLAYING_META->{stop_pos};
517 sub audio_tab_update; 541 sub audio_tab_update;
518 audio_tab_update; 542 audio_tab_update;
519} 543}
520 544
521sub audio_shutdown { 545sub audio_shutdown {
546 if ($SDL_MIXER) {
547 DC::MixMusic::halt;
548 DC::Mix_AllocateChannels 0;
549 }
550
522 undef $MUSIC_PLAYER; 551 undef $MUSIC_PLAYER;
523 undef $MUSIC_PLAYING_META; 552 undef $MUSIC_PLAYING_META;
524 undef $MUSIC_PLAYING_DATA; 553 undef $MUSIC_PLAYING_DATA;
525 554
526 $MUSIC_WANT = []; 555 $MUSIC_WANT = [];
766} 795}
767 796
768sub dc_connect { 797sub dc_connect {
769 my ($host, $port) = @_; 798 my ($host, $port) = @_;
770 799
771 my $mapw = List::Util::min 48, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32; 800 my $mapw = List::Util::min 48, List::Util::max 11, int 1.5 + $WIDTH * $CFG->{mapsize} * 0.01 / 32;
772 my $maph = List::Util::min 48, List::Util::max 11, int $HEIGHT * $CFG->{mapsize} * 0.01 / 32; 801 my $maph = List::Util::min 48, List::Util::max 11, int 1.5 + $HEIGHT * $CFG->{mapsize} * 0.01 / 32;
773 802
774 $CONN = 803 $CONN =
775 new DC::Protocol 804 new DC::Protocol
776 host => $host, 805 host => $host,
777 port => $port, 806 port => $port,
778 user => $PROFILE->{user}, 807 user => $PROFILE->{user},
779 pass => $PROFILE->{password}, 808 pass => $PROFILE->{password},
780 mapw => $mapw, 809 mapw => $mapw,
781 maph => $maph, 810 maph => $maph,
782 811
812 c_version => {
813 client => "deliantra",
783 client => "$DC::VERSION $] $^O", 814 clientver => $DC::VERSION,
815 gl_vendor => DC::OpenGL::gl_vendor,
816 gl_version => DC::OpenGL::gl_version,
817 },
784 818
785 map_widget => $MAPWIDGET, 819 map_widget => $MAPWIDGET,
786 statusbox => $STATUSBOX, 820 statusbox => $STATUSBOX,
787 map => $MAP, 821 map => $MAP,
788 mapmap => $MAPMAP, 822 mapmap => $MAPMAP,
794 828
795 on_connect => sub { 829 on_connect => sub {
796 if ($_[0]) { 830 if ($_[0]) {
797 DC::lowdelay fileno $CONN->{fh}; 831 DC::lowdelay fileno $CONN->{fh};
798 832
799 status "login successful"; 833 status "successfully connected to the server";
800 } else { 834 } else {
801 undef $CONN; 835 undef $CONN;
802 status "unable to connect: $!"; 836 status "unable to connect: $!";
803 stop_game(); 837 stop_game();
804 } 838 }
806 ; 840 ;
807} 841}
808 842
809sub start_game { 843sub start_game {
810 status "logging in..."; 844 status "logging in...";
845
846 my $server = $PROFILE->{host} || $DEFAULT_SERVER;
847 my ($host, $port) = AnyEvent::Socket::parse_hostport $server, "deliantra=13327"
848 or return status "$server: unable to parse server address, try an empty field.";
811 849
812 $LOGIN_BUTTON->set_text ("Logout"); 850 $LOGIN_BUTTON->set_text ("Logout");
813 $SETUP_DIALOG->hide; 851 $SETUP_DIALOG->hide;
814
815 my ($host, $port) = AnyEvent::Socket::parse_hostport $PROFILE->{host}, "deliantra=13327";
816 852
817 $MAP = new DC::Map; 853 $MAP = new DC::Map;
818 854
819 # hack to make SURE we find the IP address all right 855 # hack to make SURE we find the IP address all right
820 # can be removed once AnyEvent::DNS is proven stable. 856 # can be removed once AnyEvent::DNS is proven stable.
821 if ($host eq "gameserver.deliantra.net") { 857 if ($host eq "gameserver.deliantra.net") {
822 AnyEvent::DNS::a "dnstest.deliantra.net", sub { 858 AnyEvent::DNS::a "dnstest.deliantra.net", sub {
823 if ($_[0] ne "80.101.114.108") { # Perl 859 if ($_[0] ne "80.101.114.108") { # P-e-r-l
860 status "dns failure, trying differently";
861 $host = eval { Socket::inet_ntoa Socket::inet_aton "gameserver.deliantra.net" };
862 unless (defined $host) {
824 status "dns failure, using hardcoded address"; 863 status "dns failure, using hardcoded address";
825 $host = "129.13.162.95"; 864 $host = "194.126.175.154";
865 }
826 } 866 }
827 867
828 dc_connect $host, $port; 868 dc_connect $host, $port;
829 }; 869 };
830 } else { 870 } else {
897 937
898 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Video Mode"); 938 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Video Mode");
899 $table->add_at (1, $row++, my $hbox = new DC::UI::HBox); 939 $table->add_at (1, $row++, my $hbox = new DC::UI::HBox);
900 940
901 $hbox->add ($MODE_SLIDER = new DC::UI::Slider 941 $hbox->add ($MODE_SLIDER = new DC::UI::Slider
942 c_rescale => 1,
902 force_w => $WIDTH * 0.1, expand => 1, 943 force_w => $WIDTH * 0.1, expand => 1,
903 range => [ ($CFG->{sdl_mode}) x 3 ], 944 range => [ ($CFG->{sdl_mode}) x 3 ],
904 tooltip => $vidmode_tooltip); 945 tooltip => $vidmode_tooltip);
905 $hbox->add (my $mode_label = new DC::UI::Label 946 $hbox->add (my $mode_label = new DC::UI::Label
906 height => 0.8, template => "9999x9999@9+9", 947 height => 0.8, template => "9999x9999@9+9",
934 ); 975 );
935 976
936 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Forbid Alpha"); 977 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Forbid Alpha");
937 $table->add_at (1, $row++, new DC::UI::CheckBox 978 $table->add_at (1, $row++, new DC::UI::CheckBox
938 state => $CFG->{disable_alpha}, 979 state => $CFG->{disable_alpha},
939 tooltip => "Forbid off the use of the alpha channel. This makes Deliantra look a lot worse " 980 tooltip => "Forbid the use of the alpha channel. This makes Deliantra look a lot worse "
940 . "by disabling a number of textures and transparency effects. Normally, these " 981 . "by disabling a number of textures and transparency effects. Normally, these "
941 . "effects do not cost a lot of resources, but some graphics cards might fall " 982 . "effects do not cost a lot of resources, but some graphics cards might fall "
942 . "back to extremely slow rendering if this is enabled. If disabling this option " 983 . "back to extremely slow rendering if this is enabled. If disabling this option "
943 . "noticably improves the framerate of the client please report this! " 984 . "noticably improves the framerate of the client please report this! "
944 . "<b>If you experience extremely low framerates and your card should do better, try this option.</b>", 985 . "<b>If you experience extremely low framerates and your card should do better, try this option.</b>",
998 . "If you have a very slow system, non-accelerated drivers or plain dislike smooth scrolling, " 1039 . "If you have a very slow system, non-accelerated drivers or plain dislike smooth scrolling, "
999 . "then disable this option. Changes take effect immdiately.", 1040 . "then disable this option. Changes take effect immdiately.",
1000 on_changed => sub { my ($self, $value) = @_; $CFG->{smooth_movement} = $value; 0 } 1041 on_changed => sub { my ($self, $value) = @_; $CFG->{smooth_movement} = $value; 0 }
1001 ); 1042 );
1002 1043
1044 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Smooth Transitions");
1045 $table->add_at (1, $row++, new DC::UI::CheckBox
1046 state => $CFG->{smooth_transitions},
1047 tooltip => "<b>Smooth Transitions</b> tries to blend the fog of war and lighting smoothly between updates. "
1048 . "If you have a very slow system, non-accelerated drivers or plain dislike smooth scrolling, "
1049 . "then disable this option. Requires Smooth Movement and OpenGL Multitexturing. Changes take effect immdiately.",
1050 on_changed => sub { my ($self, $value) = @_; $CFG->{smooth_transitions} = $value; 0 }
1051 );
1052
1053
1003 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Map Scale"); 1054 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Map Scale");
1004 $table->add_at (1, $row++, new DC::UI::Slider 1055 $table->add_at (1, $row++, new DC::UI::Slider
1005 range => [(log $CFG->{map_scale}) / (log 2), -3, 1, 0, 1], 1056 range => [(log $CFG->{map_scale}) / (log 2), -3, 1, 0, 1],
1006 tooltip => "Enlarge or shrink the displayed map. Changes are instant.", 1057 tooltip => "Enlarge or shrink the displayed map. Changes are instant.",
1007 on_changed => sub { my ($self, $value) = @_; $CFG->{map_scale} = 2 ** $value; 0 } 1058 on_changed => sub { my ($self, $value) = @_; $CFG->{map_scale} = 2 ** $value; 0 }
1019 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Fog of War"); 1070 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Fog of War");
1020 $table->add_at (1, $row++, new DC::UI::CheckBox 1071 $table->add_at (1, $row++, new DC::UI::CheckBox
1021 state => $CFG->{fow_enable}, 1072 state => $CFG->{fow_enable},
1022 tooltip => "<b>Fog-of-War</b> marks areas that cannot be seen by the player. Changes are instant.", 1073 tooltip => "<b>Fog-of-War</b> marks areas that cannot be seen by the player. Changes are instant.",
1023 on_changed => sub { my ($self, $value) = @_; $CFG->{fow_enable} = $value; 0 } 1074 on_changed => sub { my ($self, $value) = @_; $CFG->{fow_enable} = $value; 0 }
1075 );
1076
1077 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "FoW Pattern");
1078 $table->add_at (1, $row++, new DC::UI::ImageButton
1079 tex => $DC::MapWidget::TEX_HIDDEN[$CFG->{fow_texture}],
1080 bg => [0.3, 0.3, 0.2],
1081 force_w => 64,
1082 force_h => 64,
1083 tooltip => "<b>Fog of War Pattern.</b> The pattern that is overlaid over areas hidden from view. Click to cycle through various alternatives. Changes are instant.",
1084 on_activate => sub {
1085 my ($self) = @_;
1086 $CFG->{fow_texture} = ($CFG->{fow_texture} + 1) % @DC::MapWidget::TEX_HIDDEN;
1087 $self->set_texture ($DC::MapWidget::TEX_HIDDEN[$CFG->{fow_texture}]);
1088 $MAPWIDGET->update;
1089 }
1024 ); 1090 );
1025 1091
1026 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "FoW Intensity"); 1092 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "FoW Intensity");
1027 $table->add_at (1, $row++, new DC::UI::Slider 1093 $table->add_at (1, $row++, new DC::UI::Slider
1028 range => [$CFG->{fow_intensity}, 0, 1, 0, 1 / 256], 1094 range => [$CFG->{fow_intensity}, 0, 1, 0, 1 / 256],
1080 1146
1081 my $text = !$freq 1147 my $text = !$freq
1082 ? "audio is off" 1148 ? "audio is off"
1083 : "audio is enabled\n" 1149 : "audio is enabled\n"
1084 . "frequency (Hz): $freq\n" 1150 . "frequency (Hz): $freq\n"
1085 . "channels: $chans"; 1151 . "channels: $chans\n"
1152 . "chunk decoders available: " . (join ", ", DC::MixChunk::decoders) . "\n"
1153 . "music decoders available: " . (join ", ", DC::MixMusic::decoders);
1086 1154
1087 $AUDIO_INFO->set_text ($text); 1155 $AUDIO_INFO->set_text ($text);
1088} 1156}
1089 1157
1090sub audio_setup { 1158sub audio_setup {
1119 ); 1187 );
1120 1188
1121 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Background Music"); 1189 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Background Music");
1122 $table->add_at (1, $row, new DC::UI::CheckBox 1190 $table->add_at (1, $row, new DC::UI::CheckBox
1123 expand => 1, state => $CFG->{bgm_enable}, 1191 expand => 1, state => $CFG->{bgm_enable},
1124 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.", 1192 tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played. Needs server reconnect to take effect.",
1125 on_changed => sub { 1193 on_changed => sub {
1126 $CFG->{bgm_enable} = $_[1]; 1194 $CFG->{bgm_enable} = $_[1];
1127 $CONN->update_fx_want if $CONN; 1195 $CONN->update_fx_want if $CONN;
1128 audio_music_push; 1196 audio_music_push;
1129 1 1197 1
1230} 1298}
1231 1299
1232sub make_gauge_window { 1300sub make_gauge_window {
1233 my $gh = int $HEIGHT * $CFG->{gauge_size}; 1301 my $gh = int $HEIGHT * $CFG->{gauge_size};
1234 1302
1235 my $win = new DC::UI::Frame ( 1303 $GAUGES->{win} = my $win = new DC::UI::Frame (
1236 force_x => 0, 1304 force_x => 0,
1237 force_y => "max", 1305 force_y => "max",
1238 force_w => $WIDTH, 1306 force_w => $WIDTH,
1239 force_h => $gh, 1307 force_h => $gh,
1240 ); 1308 );
1256 (new DC::UI::Empty expand => 1), 1324 (new DC::UI::Empty expand => 1),
1257 (my $hb = new DC::UI::HBox), 1325 (my $hb = new DC::UI::HBox),
1258 ], 1326 ],
1259 ); 1327 );
1260 1328
1261 $hb->add (my $hg = new DC::UI::Gauge type => 'hp', tooltip => "#stat_health"); 1329 $hb->add ($GAUGES->{hp} = new DC::UI::Gauge type => 'hp', tooltip => "#stat_health");
1262 $hb->add (my $mg = new DC::UI::Gauge type => 'mana', tooltip => "#stat_mana"); 1330 $hb->add ($GAUGES->{mana} = new DC::UI::Gauge type => 'mana', tooltip => "#stat_mana");
1263 $hb->add (my $gg = new DC::UI::Gauge type => 'grace', tooltip => "#stat_grace"); 1331 $hb->add ($GAUGES->{grace} = new DC::UI::Gauge type => 'grace', tooltip => "#stat_grace");
1264 $hb->add (my $fg = new DC::UI::Gauge type => 'food', tooltip => "#stat_food"); 1332 $hb->add ($GAUGES->{food} = new DC::UI::Gauge type => 'food', tooltip => "#stat_food");
1265
1266 $vbox->add (my $exp = new DC::UI::Label align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_exp");
1267 $vbox->add (my $prg = new DC::UI::ExperienceProgress);
1268 $vbox->add (my $sklprg = new DC::UI::ExperienceProgress);
1269 $vbox->add (my $rng = new DC::UI::Label align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_ranged");
1270
1271 $GAUGES = {
1272 exp => $exp, prg => $prg, sklprg => $sklprg,
1273 win => $win, range => $rng,
1274 hp => $hg, mana => $mg, grace => $gg, food => $fg,
1275 };
1276 1333
1277 &set_gauge_window_fontsize; 1334 &set_gauge_window_fontsize;
1278 1335
1279 $win 1336 $win
1337}
1338
1339our $BW_WATCHER;
1340
1341sub debug_toggle($) {
1342 $DELIANTRA_DEBUG ^= $_[0];
1343
1344 if ($DELIANTRA_DEBUG & 16) {
1345 $BW_WATCHER = EV::periodic 0, 1, 0, sub {
1346 return unless $CONN;
1347 debug sprintf "%8.2gKB/s", $CONN->{octets_in} / 1e3;
1348 $CONN->{octets_in} = 0;
1349 };
1350 } else {
1351 undef $BW_WATCHER;
1352 }
1353
1280} 1354}
1281 1355
1282sub debug_setup { 1356sub debug_setup {
1283 my $table = new DC::UI::Table; 1357 my $table = new DC::UI::Table;
1284 1358
1285 $table->add_at (0, 0, new DC::UI::Label text => "Widget Borders"); 1359 $table->add_at (0, 0, new DC::UI::Label text => "Widget Borders");
1286 $table->add_at (1, 0, new DC::UI::CheckBox on_changed => sub { $ENV{CFPLUS_DEBUG} ^= 1; 0 }); 1360 $table->add_at (1, 0, new DC::UI::CheckBox on_changed => sub { debug_toggle 1; 0 });
1287 $table->add_at (0, 1, new DC::UI::Label text => "Tooltip Widget Info"); 1361 $table->add_at (0, 1, new DC::UI::Label text => "Tooltip Widget Info");
1288 $table->add_at (1, 1, new DC::UI::CheckBox on_changed => sub { $ENV{CFPLUS_DEBUG} ^= 2; 0 }); 1362 $table->add_at (1, 1, new DC::UI::CheckBox on_changed => sub { debug_toggle 2; 0 });
1289 $table->add_at (0, 2, new DC::UI::Label text => "Show FPS"); 1363 $table->add_at (0, 2, new DC::UI::Label text => "Show FPS");
1290 $table->add_at (1, 2, new DC::UI::CheckBox on_changed => sub { $ENV{CFPLUS_DEBUG} ^= 4; 0 }); 1364 $table->add_at (1, 2, new DC::UI::CheckBox on_changed => sub { debug_toggle 4; 0 });
1291 $table->add_at (0, 3, new DC::UI::Label text => "Suppress Tooltips"); 1365 $table->add_at (0, 3, new DC::UI::Label text => "Suppress Tooltips");
1292 $table->add_at (1, 3, new DC::UI::CheckBox on_changed => sub { $ENV{CFPLUS_DEBUG} ^= 8; 0 }); 1366 $table->add_at (1, 3, new DC::UI::CheckBox on_changed => sub { debug_toggle 8; 0 });
1367 $table->add_at (0, 4, new DC::UI::Label text => "Show Bandwidth");
1368 $table->add_at (1, 4, new DC::UI::CheckBox on_changed => sub { debug_toggle 16; 0 });
1369
1293 $table->add_at (0, 4, new DC::UI::Button text => "die on click(tm)", on_activate => sub { &DC::debug() } ); 1370 $table->add_at (0, 6, new DC::UI::Button text => "die on click(tm)", on_activate => sub { &DC::debug() } );
1294
1295 $table->add_at (0, 5, new DC::UI::TextEdit text => "line1\0152\0153\nµikachu\nづx゙つ゛");#d# 1371 $table->add_at (0, 7, new DC::UI::TextEdit text => "line1\0152\0153\nµikachu\nづx゙つ゛");#d#
1296 1372
1297 $table->add_at (7,7, my $t = new DC::UI::Table expand => 0); 1373 $table->add_at (7,7, my $t = new DC::UI::Table expand => 0);
1298 $t->add_at (0,0, new DC::UI::Label text => "a a", c_rowspan => 1, c_colspan => 2); 1374 $t->add_at (0,0, new DC::UI::Label text => "a a", c_rowspan => 1, c_colspan => 2);
1299 $t->add_at (2,0, new DC::UI::Label text => "b\nb", c_rowspan => 2, c_colspan => 1, ellipsise => 0 ); 1375 $t->add_at (2,0, new DC::UI::Label text => "b\nb", c_rowspan => 2, c_colspan => 1, ellipsise => 0 );
1300 $t->add_at (1,2, new DC::UI::Label text => "c c", c_rowspan => 1, c_colspan => 2); 1376 $t->add_at (1,2, new DC::UI::Label text => "c c", c_rowspan => 1, c_colspan => 2);
1621 child => (my $table = new DC::UI::Table expand => 1, col_expand => [0, 1]), 1697 child => (my $table = new DC::UI::Table expand => 1, col_expand => [0, 1]),
1622 ); 1698 );
1623 1699
1624 $table->add_at (0, 4, new DC::UI::Label align => 1, text => "Username"); 1700 $table->add_at (0, 4, new DC::UI::Label align => 1, text => "Username");
1625 $table->add_at (1, 4, new DC::UI::Entry 1701 $table->add_at (1, 4, new DC::UI::Entry
1626 text => $CFG->{profile}{default}{user}, 1702 text => $PROFILE->{user},
1627 tooltip => "The name of your character on the server.", 1703 tooltip => "The name of your character on the server. The name is case-sensitive!",
1628 on_changed => sub { my ($self, $value) = @_; $CFG->{profile}{default}{user} = $value; 1 } 1704 on_changed => sub { my ($self, $value) = @_; $PROFILE->{user} = $value; 1 }
1629 ); 1705 );
1630 1706
1631 $table->add_at (0, 5, new DC::UI::Label align => 1, text => "Password"); 1707 $table->add_at (0, 5, new DC::UI::Label align => 1, text => "Password");
1632 $table->add_at (1, 5, new DC::UI::Entry 1708 $table->add_at (1, 5, new DC::UI::Entry
1633 text => $CFG->{profile}{default}{password}, 1709 text => $PROFILE->{password},
1634 hidden => 1, 1710 hidden => 1,
1635 tooltip => "The password for your character.", 1711 tooltip => "The password for your character.",
1636 on_changed => sub { my ($self, $value) = @_; $CFG->{profile}{default}{password} = $value; 1 } 1712 on_changed => sub { my ($self, $value) = @_; $PROFILE->{password} = $value; 1 }
1637 ); 1713 );
1638 1714
1639 $table->add_at (1, 11, $LOGIN_BUTTON = new DC::UI::Button 1715 $table->add_at (1, 11, $LOGIN_BUTTON = new DC::UI::Button
1640 expand => 1, 1716 expand => 1,
1641 text => "Login / Register", 1717 text => "Login / Register",
1677 $table->add_at (1, $row, my $vbox = new DC::UI::VBox); 1753 $table->add_at (1, $row, my $vbox = new DC::UI::VBox);
1678 1754
1679 $vbox->add ( 1755 $vbox->add (
1680 $HOST_ENTRY = new DC::UI::Entry 1756 $HOST_ENTRY = new DC::UI::Entry
1681 expand => 1, 1757 expand => 1,
1682 text => $CFG->{profile}{default}{host}, 1758 text => $PROFILE->{host},
1683 tooltip => "The hostname or ip address of the Deliantra server to connect to (e.g. <b>gameserver.deliantra.net</b>)", 1759 tooltip => "The hostname or ip address of the Deliantra server to connect to (e.g. <b>gameserver.deliantra.net</b>)",
1684 on_changed => sub { 1760 on_changed => sub {
1685 my ($self, $value) = @_; 1761 my ($self, $value) = @_;
1686 $CFG->{profile}{default}{host} = $value; 1762 $PROFILE->{host} = $value;
1687 1 1763 1
1688 } 1764 }
1689 ); 1765 );
1690 1766
1691 if (0) { #d# disabled 1767 if (0) { #d# disabled
1734 1810
1735 my $row = 0; 1811 my $row = 0;
1736 1812
1737 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Tip of the day"); 1813 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Tip of the day");
1738 $table->add_at (1, $row++, new DC::UI::CheckBox 1814 $table->add_at (1, $row++, new DC::UI::CheckBox
1815 c_colspan => 2,
1739 state => $CFG->{show_tips}, 1816 state => $CFG->{show_tips},
1740 tooltip => "Show the <b>Tip of the day</b> window at startup?", 1817 tooltip => "Show the <b>Tip of the day</b> window at startup?",
1741 on_changed => sub { 1818 on_changed => sub {
1742 my ($self, $value) = @_; 1819 my ($self, $value) = @_;
1743 $CFG->{show_tips} = $value; 1820 $CFG->{show_tips} = $value;
1745 } 1822 }
1746 ); 1823 );
1747 1824
1748 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Message Window Size"); 1825 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Message Window Size");
1749 $table->add_at (1, $row++, my $saycmd = new DC::UI::Entry 1826 $table->add_at (1, $row++, my $saycmd = new DC::UI::Entry
1827 c_colspan => 2,
1750 text => $CFG->{logview_max_par}, 1828 text => $CFG->{logview_max_par},
1751 tooltip => "This is maximum number of messages remembered in the <b>Message</b> window. If the server " 1829 tooltip => "This is maximum number of messages remembered in the <b>Message</b> window. If the server "
1752 . "sends more messages than this number, older messages get removed to save memory and " 1830 . "sends more messages than this number, older messages get removed to save memory and "
1753 . "computing time. A value of <b>0</b> disables this feature, but that is not recommended.", 1831 . "computing time. A value of <b>0</b> disables this feature, but that is not recommended.",
1754 on_changed => sub { 1832 on_changed => sub {
1756 $MESSAGE_DIST->set_max_par ($CFG->{logview_max_par} = $value*1); 1834 $MESSAGE_DIST->set_max_par ($CFG->{logview_max_par} = $value*1);
1757 0 1835 0
1758 }, 1836 },
1759 ); 1837 );
1760 1838
1839 $table->add_at (0, $row, new DC::UI::Label align => 1, text => "Config Autosave");
1840 $table->add_at (1, $row, new DC::UI::CheckBox
1841 state => $CFG->{config_autosave},
1842 tooltip => "Normally, configuration settings and the user interface layout "
1843 . "are saved on client exit. You can disable this behaviour by "
1844 . "unchecking this checkbox.",
1845 on_changed => sub {
1846 my ($self, $value) = @_;
1847 $CFG->{config_autosave} = $value;
1848 0
1849 }
1850 );
1851 $table->add_at (2, $row++, new DC::UI::Button
1852 text => "Save Now",
1853 tooltip => "Use this to manually save configuration and UI layout when "
1854 . "autosave is disabled.",
1855 on_activate => sub {
1856 DC::write_cfg;
1857 0
1858 }
1859 );
1860
1761 $table 1861 $table
1762} 1862}
1763 1863
1764sub autopickup_setup { 1864sub autopickup_setup {
1765 my $r = new DC::UI::ScrolledWindow ( 1865 my $r = new DC::UI::ScrolledWindow (
1771 col_expand => [0, 1, 0, 1], 1871 col_expand => [0, 1, 0, 1],
1772 ); 1872 );
1773 1873
1774 for ( 1874 for (
1775 ["General", 0, 0, 1875 ["General", 0, 0,
1776 ["Enable autopickup" => PICKUP_NEWMODE, \$PICKUP_ENABLE],
1777 ["Inhibit autopickup" => PICKUP_INHIBIT], 1876# ["Inhibit autopickup" => PICKUP_INHIBIT],
1778 ["Stop before pickup" => PICKUP_STOP], 1877 ["Stop before pickup" => PICKUP_STOP],
1779 ["Debug autopickup" => PICKUP_DEBUG], 1878 ["Debug autopickup" => PICKUP_DEBUG],
1780 ], 1879 ],
1781 ["Weapons", 0, 6, 1880 ["Weapons", 0, 6,
1782 ["All weapons" => PICKUP_ALLWEAPON], 1881 ["All weapons" => PICKUP_ALLWEAPON],
1830 $::CFG->{pickup} |= $mask; 1929 $::CFG->{pickup} |= $mask;
1831 } else { 1930 } else {
1832 $::CFG->{pickup} &= ~$mask; 1931 $::CFG->{pickup} &= ~$mask;
1833 } 1932 }
1834 1933
1835 $::CONN->send_command ("pickup $::CFG->{pickup}") 1934 $::CONN->send_pickup ($::CFG->{pickup})
1836 if defined $::CONN; 1935 if defined $::CONN;
1837 1936
1838 0 1937 0
1839 }); 1938 });
1840 1939
1857 }); 1956 });
1858 1957
1859 $table->add_at (3, 18, new DC::UI::Button 1958 $table->add_at (3, 18, new DC::UI::Button
1860 text => "set", 1959 text => "set",
1861 on_activate => sub { 1960 on_activate => sub {
1862 $::CONN->send_command ("pickup $::CFG->{pickup}") 1961 $::CONN->send_pickup ($::CFG->{pickup})
1863 if defined $::CONN; 1962 if defined $::CONN;
1864 0 1963 0
1865 }); 1964 });
1866 1965
1867 $r 1966 $r
1868} 1967}
1869 1968
1870my %SORT_ORDER = ( 1969my %SORT_ORDER = (
1871 type => sub { 1970 type => sub {
1971 use sort 'stable';
1872 sort { $a->{type} <=> $b->{type} or $a->{name} cmp $b->{name} } @_ 1972 sort { $a->{type} <=> $b->{type} or $a->{name} cmp $b->{name} } @_
1873 }, 1973 },
1874 mtime => sub { 1974 mtime => sub {
1975 use sort 'stable';
1875 my $NOW = time; 1976 my $NOW = time;
1876 sort { 1977 sort {
1877 my $atime = $a->{mtime} - $NOW; $atime = $atime < 5 * 60 ? int $atime / 60 : 6; 1978 my $atime = $a->{mtime} - $NOW; $atime = $atime < 5 * 60 ? int $atime / 60 : 6;
1878 my $btime = $b->{mtime} - $NOW; $btime = $btime < 5 * 60 ? int $btime / 60 : 6; 1979 my $btime = $b->{mtime} - $NOW; $btime = $btime < 5 * 60 ? int $btime / 60 : 6;
1879 1980
1880 ($a->{flags} & F_LOCKED) <=> ($b->{flags} & F_LOCKED) 1981 ($a->{flags} & F_LOCKED) <=> ($b->{flags} & F_LOCKED)
1881 or $btime <=> $atime 1982 or $btime <=> $atime
1882 or $a->{type} <=> $b->{type} 1983 or $a->{type} <=> $b->{type}
1883 } @_ 1984 } @_
1884 }, 1985 },
1885 weight => sub { sort { 1986 weight => sub {
1987 use sort 'stable';
1988 sort {
1886 $a->{weight} * ($a->{nrof} || 1) <=> $b->{weight} * ($b->{nrof} || 1) 1989 $a->{weight} * ($a->{nrof} || 1) <=> $b->{weight} * ($b->{nrof} || 1)
1887 or $a->{type} <=> $b->{type} 1990 or $a->{type} <=> $b->{type}
1888 } @_ }, 1991 } @_
1992 },
1889); 1993);
1890 1994
1891sub inventory_widget { 1995sub inventory_widget {
1892 my $hb = new DC::UI::HBox homogeneous => 1; 1996 my $hb = new DC::UI::HBox homogeneous => 1;
1893 1997
1980 $PL_NOTEBOOK->set_current_page ($widget); 2084 $PL_NOTEBOOK->set_current_page ($widget);
1981 $PL_WINDOW->show; 2085 $PL_WINDOW->show;
1982 } 2086 }
1983} 2087}
1984 2088
1985sub player_window { 2089sub make_playerbook {
1986 my $plwin = $PL_WINDOW = new DC::UI::Toplevel 2090 my $plwin = $PL_WINDOW = new DC::UI::Toplevel
1987 x => "center", 2091 x => "center",
1988 y => "center", 2092 y => "center",
1989 force_w => $WIDTH * 9/10, 2093 force_w => $WIDTH * 9/10,
1990 force_h => $HEIGHT * 9/10, 2094 force_h => $HEIGHT * 9/10,
2024 "License, Author and Source info for media sent by the server."); 2128 "License, Author and Source info for media sent by the server.");
2025 2129
2026 $ntb->set_current_page ($INVENTORY_PAGE); 2130 $ntb->set_current_page ($INVENTORY_PAGE);
2027 2131
2028 $plwin->add ($ntb); 2132 $plwin->add ($ntb);
2029 $plwin
2030} 2133}
2031 2134
2032sub keyboard_setup { 2135sub keyboard_setup {
2033 DC::Macro::keyboard_setup 2136 DC::Macro::keyboard_setup
2034} 2137}
2035 2138
2036sub help_window { 2139sub make_help_window {
2037 my $win = new DC::UI::Toplevel 2140 my $win = new DC::UI::Toplevel
2038 x => 'center', 2141 x => 'center',
2039 y => 'center', 2142 y => 'center',
2040 z => 4, 2143 z => 4,
2041 name => 'doc_browser', 2144 name => 'doc_browser',
2130 2233
2131 $load_node->((DC::Pod::find @path)[0]); 2234 $load_node->((DC::Pod::find @path)[0]);
2132 $win->show; 2235 $win->show;
2133 }; 2236 };
2134 2237
2135 $win 2238 $HELP_WINDOW = $win;
2136}
2137
2138sub open_string_query {
2139 my ($title, $cb, $txt, $tooltip) = @_;
2140 my $dialog = new DC::UI::Toplevel
2141 x => "center",
2142 y => "center",
2143 z => 50,
2144 force_w => $WIDTH * 4/5,
2145 title => $title;
2146
2147 $dialog->add (
2148 my $e = new DC::UI::Entry
2149 on_activate => sub { $cb->(@_); $dialog->hide; 0 },
2150 on_key_down => sub { $_[1]->{sym} == 27 and $dialog->hide; 0 },
2151 tooltip => $tooltip
2152 );
2153
2154 $e->grab_focus;
2155 $e->set_text ($txt) if $txt;
2156 $dialog->show;
2157} 2239}
2158 2240
2159sub open_quit_dialog { 2241sub open_quit_dialog {
2160 unless ($QUIT_DIALOG) { 2242 unless ($QUIT_DIALOG) {
2161 $QUIT_DIALOG = new DC::UI::Toplevel 2243 $QUIT_DIALOG = new DC::UI::Toplevel
2194 2276
2195 $QUIT_DIALOG->show; 2277 $QUIT_DIALOG->show;
2196 $QUIT_DIALOG->grab_focus; 2278 $QUIT_DIALOG->grab_focus;
2197} 2279}
2198 2280
2281sub make_menubar {
2282 $MENUFRAME = new DC::UI::Toplevel
2283 border => 0,
2284 force_x => 0,
2285 force_y => 0,
2286 force_w => $::WIDTH,
2287 child => ($MENUBAR = new DC::UI::HBox),
2288 ;
2289
2290 $MENUBAR->add ($BUTTONBAR = new DC::UI::Buttonbar);
2291
2292 # XXX: this has to be done before make_stats_window as make_stats_window calls update_stats_window which updated the gauges also X-D
2293 make_gauge_window->show;
2294
2295# $BUTTONBAR->add (new DC::UI::Flopper text => "Message Window", other => $MESSAGE_WINDOW,
2296# tooltip => "Toggles the server message log, where the client collects <i>all</i> messages from the server.");
2297
2298 make_playerbook;
2299
2300 $MENUPOPUP = DC::UI::Menu->new (items => [
2301 ["Setup…\tF9" , sub { $SETUP_DIALOG->toggle_visibility }],
2302 ["Playerbook…\tTab" , sub { $PL_WINDOW ->toggle_visibility }],
2303 ["…Statistics\tF2" , sub { toggle_player_page ($::STATS_PAGE) }],
2304 ["…Skills\tF3" , sub { toggle_player_page ($::SKILL_PAGE) }],
2305 ["…Spells\tF4" , sub { toggle_player_page ($::SPELL_PAGE) }],
2306 ["…Inventory\tF5" , sub { toggle_player_page ($::INVENTORY_PAGE) }],
2307 ["Help Browser…\tF1" , sub { $HELP_WINDOW ->toggle_visibility }],
2308 ["Quit…" , sub {
2309 if ($CONN) {
2310 open_quit_dialog;
2311 } else {
2312 EV::unloop EV::UNLOOP_ALL;
2313 }
2314 }],
2315 ]);
2316
2317 $BUTTONBAR->add (new DC::UI::Button text => "Menu…",
2318 tooltip => "Shows the main menu",
2319 on_button_down => sub {
2320 my ($self, $ev) = @_;
2321 local $ev->{x} = 0;
2322 local $ev->{y} = 0;
2323 $MENUPOPUP->popup ($ev);
2324 },
2325 );
2326
2327 $MENUBAR->add ($GAUGES->{exp} = new DC::UI::ExperienceProgress
2328 padding_x => 6,
2329 padding_y => 3,
2330 tooltip => "This progress bar shows your overall experience and your progress towards the next character level.",
2331 template => " Exp: 888,888,888,888 (lvl 188) ",
2332 );
2333
2334 $MENUBAR->add ($PICKUP_ENABLE = new DC::UI::CheckBox # checkbox bad, button better?
2335 tooltip => "Automatic Pickup Enable - when this checkbox is enabled, then your character "
2336 . "will automatically pick up items as defined by your item pickup settings "
2337 . "in the playerbook. Often (e.g. in apartments) you want to temporarily "
2338 . "disable autopickup by disabling this checkbox.",
2339 state => $CFG->{pickup} & PICKUP_INHIBIT ? 0 : 1,
2340 on_changed => sub {
2341 my ($self, $value) = @_;
2342 $CFG->{pickup} &= ~PICKUP_INHIBIT;
2343 $CFG->{pickup} |= PICKUP_INHIBIT unless $_[1];
2344 $CONN->send_pickup ($CFG->{pickup})
2345 if $CONN;
2346 },
2347 );
2348
2349 $MENUBAR->add ($GAUGES->{skillexp} = new DC::UI::ExperienceProgress
2350 c_rescale => 1,
2351 padding_x => 6,
2352 padding_y => 3,
2353 force_w => $::WIDTH * 0.2,
2354 tooltip => "This progress bar shows the currently used skill and your progress towards the next skill level of that skill.",
2355 template => "two handed weapons 99%",
2356 );
2357
2358 $MENUBAR->add ($GAUGES->{range} = new DC::UI::Label
2359 expand => 1,
2360 align => 1, can_hover => 1, can_events => 1,
2361 text => "Range and Combat Slots",
2362 tooltip => "#stat_ranged",
2363 );
2364
2365 $MENUFRAME->show;
2366}
2367
2368sub open_string_query {
2369 my ($title, $cb, $txt, $tooltip) = @_;
2370 my $dialog = new DC::UI::Toplevel
2371 x => "center",
2372 y => "center",
2373 z => 50,
2374 force_w => $WIDTH * 4/5,
2375 title => $title;
2376
2377 $dialog->add (
2378 my $e = new DC::UI::Entry
2379 on_activate => sub { $cb->(@_); $dialog->hide; 0 },
2380 on_key_down => sub { $_[1]->{sym} == 27 and $dialog->hide; 0 },
2381 tooltip => $tooltip
2382 );
2383
2384 $e->grab_focus;
2385 $e->set_text ($txt) if $txt;
2386 $dialog->show;
2387}
2388
2199sub show_tip_of_the_day { 2389sub show_tip_of_the_day {
2200 # find all tips 2390 # find all tips
2201 my @tod = DC::Pod::find tip_of_the_day => "*"; 2391 my @tod = DC::Pod::find tip_of_the_day => "*";
2202 2392
2203 DC::DB::get state => "tip_of_the_day", sub { 2393 DC::DB::get state => "tip_of_the_day", sub {
2321 2511
2322 $DEBUG_STATUS = new DC::UI::Label 2512 $DEBUG_STATUS = new DC::UI::Label
2323 padding => 0, 2513 padding => 0,
2324 z => 100, 2514 z => 100,
2325 force_x => "max", 2515 force_x => "max",
2326 force_y => 0; 2516 force_y => 20;
2327 $DEBUG_STATUS->show; 2517 $DEBUG_STATUS->show;
2328 2518
2329 $STATUSBOX = new DC::UI::Statusbox; 2519 $STATUSBOX = new DC::UI::Statusbox;
2330 2520
2331 $MODBOX = new DC::UI::Label 2521 $MODBOX = new DC::UI::Label
2342 2532
2343 (new DC::UI::Frame 2533 (new DC::UI::Frame
2344 bg => [0, 0, 0, 0.4], 2534 bg => [0, 0, 0, 0.4],
2345 force_x => 0, 2535 force_x => 0,
2346 force_y => "max", 2536 force_y => "max",
2347 child => (my $LR = new DC::UI::VBox), 2537 child => (my $LL = new DC::UI::VBox),
2348 )->show; 2538 )->show;
2349 2539
2350 $LR->add ($STATUSBOX); 2540 $LL->add ($STATUSBOX);
2351 $LR->add ($MODBOX); 2541 $LL->add ($MODBOX);
2352 $LR->add (new DC::UI::Label 2542 $LL->add (new DC::UI::Label
2353 align => 0, 2543 align => 0,
2354 markup => "Use <b>Alt-Enter</b> to toggle fullscreen mode", 2544 markup => "Use <b>Alt-Enter</b> to toggle fullscreen mode",
2355 fontsize => 0.5, 2545 fontsize => 0.5,
2356 fg => [1, 1, 0, 0.7], 2546 fg => [1, 1, 0, 0.7],
2357 ); 2547 );
2358 2548
2359 DC::UI::Toplevel->new ( 2549 DC::UI::Toplevel->new (
2360 title => "Minimap", 2550 title => "Minimap",
2361 name => "mapmap", 2551 name => "mapmap",
2362 x => 0, 2552 x => 0,
2363 y => $FONTSIZE + 8, 2553 y => $::FONTSIZE + 8,#d# hack to move messages window below the menubar
2364 border_bg => [1, 1, 1, 192/255], 2554 border_bg => [1, 1, 1, 192/255],
2365 bg => [1, 1, 1, 0], 2555 bg => [1, 1, 1, 0],
2366 child => ($MAPMAP = new DC::MapWidget::MapMap 2556 child => ($MAPMAP = new DC::MapWidget::MapMap
2367 tooltip => "<b>Minimap</b>. This will display an overview of the surrounding areas.", 2557 tooltip => "<b>Minimap</b>. This will display an overview of the surrounding areas.",
2368 ), 2558 ),
2397 $METASERVER = metaserver_dialog; 2587 $METASERVER = metaserver_dialog;
2398 # the name is changed to not conflict with the older name as users could have hidden it 2588 # the name is changed to not conflict with the older name as users could have hidden it
2399 $MESSAGE_WINDOW = new DC::UI::Dockbar 2589 $MESSAGE_WINDOW = new DC::UI::Dockbar
2400 name => "message_window2", 2590 name => "message_window2",
2401 title => 'Messages', 2591 title => 'Messages',
2592 y => $::FONTSIZE + 8,#d# hack to move messages window below the menubar
2402 force_w => $::WIDTH * 0.6, 2593 force_w => $::WIDTH * 0.6,
2403 force_h => $::HEIGHT * 0.25, 2594 force_h => $::HEIGHT * 0.25,
2404 ; 2595 ;
2405 2596
2406 $MESSAGE_DIST = new DC::MessageDistributor dockbar => $MESSAGE_WINDOW; 2597 $MESSAGE_DIST = new DC::MessageDistributor dockbar => $MESSAGE_WINDOW;
2426 . "After pressing the combo the binding will be saved automatically and the " 2617 . "After pressing the combo the binding will be saved automatically and the "
2427 . "binding editor closes"); 2618 . "binding editor closes");
2428 $SETUP_NOTEBOOK->add_tab (Debug => debug_setup, 2619 $SETUP_NOTEBOOK->add_tab (Debug => debug_setup,
2429 "Some debuggin' options. Do not ask."); 2620 "Some debuggin' options. Do not ask.");
2430 2621
2431 $BUTTONBAR = new DC::UI::Buttonbar x => 0, y => 0, z => 200; # put on top 2622 make_help_window;
2623 make_menubar;
2432 2624
2433 $BUTTONBAR->add (new DC::UI::Flopper text => "Setup", other => $SETUP_DIALOG,
2434 tooltip => "Toggles a dialog where you can configure all aspects of this client.");
2435
2436# $BUTTONBAR->add (new DC::UI::Flopper text => "Message Window", other => $MESSAGE_WINDOW,
2437# tooltip => "Toggles the server message log, where the client collects <i>all</i> messages from the server.");
2438
2439 make_gauge_window->show; # XXX: this has to be set before make_stats_window as make_stats_window calls update_stats_window which updated the gauges also X-D
2440
2441 $BUTTONBAR->add (new DC::UI::Flopper text => "Playerbook", other => player_window,
2442 tooltip => "Toggles the player view, where you can manage Inventory, Spells, Skills and see your Stats.");
2443
2444 $BUTTONBAR->add (new DC::UI::Button
2445 text => "Save Config",
2446 tooltip => "Saves the options chosen in the client setting, server settings and the window layout to be restored on later runs.",
2447 on_activate => sub {
2448 $::CFG->{layout} = DC::UI::get_layout;
2449 DC::write_cfg;
2450 status "Configuration Saved";
2451 0
2452 },
2453 );
2454
2455 $BUTTONBAR->add (new DC::UI::Flopper text => "Help!", other => $HELP_WINDOW = help_window,
2456 tooltip => "View Documentation");
2457
2458 $BUTTONBAR->add (new DC::UI::Button
2459 text => "Quit",
2460 tooltip => "Terminates the program",
2461 on_activate => sub {
2462 if ($CONN) {
2463 open_quit_dialog;
2464 } else {
2465 EV::unloop EV::UNLOOP_ALL;
2466 }
2467 0
2468 },
2469 );
2470
2471 $BUTTONBAR->show;
2472 $SETUP_DIALOG->show; 2625 $SETUP_DIALOG->show;
2473 $MESSAGE_WINDOW->show; 2626 $MESSAGE_WINDOW->show;
2474 } 2627 }
2475 2628
2476 $MODE_SLIDER->set_range ([$CFG->{sdl_mode}, 0, scalar @SDL_MODES, 1, 1]); 2629 $MODE_SLIDER->set_range ([$CFG->{sdl_mode}, 0, scalar @SDL_MODES, 1, 1]);
2477 $MODE_SLIDER->emit (changed => $CFG->{sdl_mode}); 2630 $MODE_SLIDER->emit (changed => $CFG->{sdl_mode});
2478 2631
2479 $CAVEAT_LABEL->set_text ("None :)"); 2632 $CAVEAT_LABEL->set_text ("None :)");
2633 $CAVEAT_LABEL->set_text ("Apple/NVIDIA Texture bug (slow)")
2634 if $DC::OpenGL::APPLE_NVIDIA_BUG;
2480 $CAVEAT_LABEL->set_text ("Software Rendering (very slow)") 2635 $CAVEAT_LABEL->set_text ("Software Rendering (very slow)")
2481 unless DC::SDL_GL_GetAttribute DC::SDL_GL_ACCELERATED_VISUAL; 2636 unless DC::SDL_GL_GetAttribute DC::SDL_GL_ACCELERATED_VISUAL;
2482 2637
2483 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); 2638 $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]);
2484} 2639}
2494my $animate_timer; 2649my $animate_timer;
2495 2650
2496my $fps = 9; 2651my $fps = 9;
2497 2652
2498sub force_refresh { 2653sub force_refresh {
2499 if ($ENV{CFPLUS_DEBUG} & 4) { 2654 if ($DELIANTRA_DEBUG & 4) {
2500 $fps = $fps * 0.98 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.02; 2655 $fps = $fps * 0.98 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.02;
2501 debug sprintf "%3.2f", $fps; 2656 debug sprintf "%3.2f", $fps;
2502 } 2657 }
2503 2658
2504 undef $WANT_REFRESH; 2659 undef $WANT_REFRESH;
2512my $want_refresh = EV::prepare_ns \&force_refresh; 2667my $want_refresh = EV::prepare_ns \&force_refresh;
2513 2668
2514my $input = EV::periodic 0, 1 / $MAX_FPS, undef, sub { 2669my $input = EV::periodic 0, 1 / $MAX_FPS, undef, sub {
2515 $NOW = EV::now; 2670 $NOW = EV::now;
2516 2671
2517 ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_) 2672 ($SDL_CB[$_->{type}] || sub { warn "unhandled event $_->{type}" })->($_)
2518 for DC::poll_events; 2673 for DC::poll_events;
2519 2674
2520 if (%animate_object) { 2675 if (%animate_object) {
2521 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object; 2676 $_->animate ($LAST_REFRESH - $NOW) for values %animate_object;
2522 $WANT_REFRESH = 1; 2677 $WANT_REFRESH = 1;
2534sub animation_stop { 2689sub animation_stop {
2535 my ($widget) = @_; 2690 my ($widget) = @_;
2536 delete $animate_object{$widget}; 2691 delete $animate_object{$widget};
2537} 2692}
2538 2693
2539%SDL_CB = (
2540 DC::SDL_QUIT => sub { 2694$SDL_CB[DC::SDL_QUIT] = sub {
2541 crash "SDL_QUIT"; 2695 crash "SDL_QUIT";
2542 EV::unloop EV::UNLOOP_ALL; 2696 EV::unloop EV::UNLOOP_ALL;
2543 }, 2697};
2544 DC::SDL_VIDEORESIZE => sub { 2698$SDL_CB[DC::SDL_VIDEORESIZE] = sub { };
2545 },
2546 DC::SDL_VIDEOEXPOSE => sub { 2699$SDL_CB[DC::SDL_VIDEOEXPOSE] = sub {
2547 DC::UI::full_refresh; 2700 DC::UI::full_refresh;
2548 }, 2701};
2549 DC::SDL_ACTIVEEVENT => sub { 2702$SDL_CB[DC::SDL_ACTIVEEVENT] = sub {
2550# not useful, as APPACTIVE includes only iconified state, not unmapped 2703# not useful, as APPACTIVE includes only iconified state, not unmapped
2551# printf "active %x %x %x\n", $_[0]{gain}, $_[0]{state}, DC::SDL_GetAppState;#d# 2704# printf "active %x %x %x\n", $_[0]{gain}, $_[0]{state}, DC::SDL_GetAppState;#d#
2552# printf "a %x\n", DC::SDL_GetAppState & DC::SDL_APPACTIVE;#d# 2705# printf "a %x\n", DC::SDL_GetAppState & DC::SDL_APPACTIVE;#d#
2553# printf "A\n" if $_[0]{state} & DC::SDL_APPACTIVE; 2706# printf "A\n" if $_[0]{state} & DC::SDL_APPACTIVE;
2554# printf "K\n" if $_[0]{state} & DC::SDL_APPINPUTFOCUS; 2707# printf "K\n" if $_[0]{state} & DC::SDL_APPINPUTFOCUS;
2555# printf "M\n" if $_[0]{state} & DC::SDL_APPMOUSEFOCUS; 2708# printf "M\n" if $_[0]{state} & DC::SDL_APPMOUSEFOCUS;
2556 }, 2709};
2557 DC::SDL_KEYDOWN => sub { 2710$SDL_CB[DC::SDL_KEYDOWN] = sub {
2558 if ($_[0]{mod} & DC::KMOD_ALT && $_[0]{sym} == 13) { 2711 if ($_[0]{mod} & DC::KMOD_ALT && $_[0]{sym} == 13) {
2559 # alt-enter 2712 # alt-enter
2560 video_shutdown; 2713 video_shutdown;
2561 $FULLSCREEN_ENABLE->toggle; 2714 $FULLSCREEN_ENABLE->toggle;
2562 video_init; 2715 video_init;
2563 } else { 2716 } else {
2564 &DC::UI::feed_sdl_key_down_event; 2717 &DC::UI::feed_sdl_key_down_event;
2565 } 2718 }
2566 update_modbox; 2719 update_modbox;
2567 }, 2720};
2568 DC::SDL_KEYUP => sub { 2721$SDL_CB[DC::SDL_KEYUP] = sub {
2569 &DC::UI::feed_sdl_key_up_event; 2722 &DC::UI::feed_sdl_key_up_event;
2570 update_modbox; 2723 update_modbox;
2571 }, 2724};
2572 DC::SDL_MOUSEMOTION => \&DC::UI::feed_sdl_motion_event, 2725$SDL_CB[DC::SDL_MOUSEMOTION] = \&DC::UI::feed_sdl_motion_event,
2573 DC::SDL_MOUSEBUTTONDOWN => \&DC::UI::feed_sdl_button_down_event, 2726$SDL_CB[DC::SDL_MOUSEBUTTONDOWN] = \&DC::UI::feed_sdl_button_down_event,
2574 DC::SDL_MOUSEBUTTONUP => \&DC::UI::feed_sdl_button_up_event, 2727$SDL_CB[DC::SDL_MOUSEBUTTONUP] = \&DC::UI::feed_sdl_button_up_event,
2575 DC::SDL_USEREVENT => sub { 2728$SDL_CB[DC::SDL_USEREVENT] = sub {
2576 if ($_[0]{code} == 1) { 2729 if ($_[0]{code} == 1) {
2577 audio_channel_finished $_[0]{data1}; 2730 audio_channel_finished $_[0]{data1};
2578 } elsif ($_[0]{code} == 0) { 2731 } elsif ($_[0]{code} == 0) {
2579 audio_music_finished; 2732 audio_music_finished;
2580 }
2581 }, 2733 }
2582); 2734};
2583 2735
2584############################################################################# 2736#############################################################################
2585 2737
2586$SIG{INT} = $SIG{TERM} = sub { 2738$SIG{INT} = $SIG{TERM} = sub {
2587 EV::unloop; 2739 EV::unloop;
2588 #d# TODO calling exit here hangs the process in some futex 2740 #d# TODO calling exit here hangs the process in some futex
2589}; 2741};
2590 2742
2591# due to mac os x + sdl combined briandamage, we need this contortion 2743# due to mac os x + sdl combined braindamage, we need this contortion
2592sub main { 2744sub main {
2593 { 2745 {
2594 DC::Pod::load_docwiki DC::find_rcfile "docwiki.pst"; 2746 DC::Pod::load_docwiki DC::find_rcfile "docwiki.pst";
2595 2747
2596 if (-e "$Deliantra::VARDIR/client.cf") { 2748 if (-e "$Deliantra::VARDIR/client.cf") {
2613 DC::DB::open_db; 2765 DC::DB::open_db;
2614 2766
2615 DC::UI::set_layout ($::CFG->{layout}); 2767 DC::UI::set_layout ($::CFG->{layout});
2616 2768
2617 my %DEF_CFG = ( 2769 my %DEF_CFG = (
2770 config_autosave => 1,
2618 sdl_mode => undef, 2771 sdl_mode => undef,
2619 fullscreen => 1, 2772 fullscreen => 1,
2620 fast => 0, 2773 fast => 0,
2621 force_opengl11 => undef, 2774 force_opengl11 => undef,
2622 disable_alpha => 0, 2775 disable_alpha => 0,
2623 smooth_movement => 1, 2776 smooth_movement => 1,
2777 smooth_transitions => 1,
2624 texture_compression => 1, 2778 texture_compression => 1,
2625 map_scale => 1, 2779 map_scale => 1,
2626 fow_enable => 1, 2780 fow_enable => 1,
2627 fow_intensity => 0, 2781 fow_intensity => 0,
2782 fow_texture => 0,
2628 map_smoothing => 1, 2783 map_smoothing => 1,
2629 gui_fontsize => 1, 2784 gui_fontsize => 1,
2630 log_fontsize => 0.7, 2785 log_fontsize => 0.7,
2631 gauge_fontsize => 1, 2786 gauge_fontsize => 1,
2632 gauge_size => 0.35, 2787 gauge_size => 0.35,
2640 effects_enable => 1, 2795 effects_enable => 1,
2641 effects_volume => 1, 2796 effects_volume => 1,
2642 bgm_enable => 1, 2797 bgm_enable => 1,
2643 bgm_volume => 0.5, 2798 bgm_volume => 0.5,
2644 output_rate => "", 2799 output_rate => "",
2645 pickup => 0, 2800 pickup => PICKUP_SPELLBOOK | PICKUP_SKILLSCROLL | PICKUP_VALUABLES,
2646 inv_sort => "mtime", 2801 inv_sort => "mtime",
2647 default => "profile", # default profile 2802 default => "profile", # default profile
2648 show_tips => 1, 2803 show_tips => 1,
2649 logview_max_par => 1000, 2804 logview_max_par => 1000,
2650 shift_fire_stop => 0, 2805 shift_fire_stop => 0,
2651 uitheme => "wood", 2806 uitheme => "wood",
2652 ); 2807 map_shift_x => -24, # arbitrary
2808 map_shift_y => +24, # arbitrary
2653 2809 );
2810
2654 while (my ($k, $v) = each %DEF_CFG) { 2811 while (my ($k, $v) = each %DEF_CFG) {
2655 $CFG->{$k} = $v unless exists $CFG->{$k}; 2812 $CFG->{$k} = $v unless exists $CFG->{$k};
2656 } 2813 }
2657 2814
2658 $CFG->{profile}{default}{host} ||= "gameserver.deliantra.net"; 2815 my @args = @ARGV;
2816
2817 my $profile = 'default';
2818
2819 for (my $i = 0; $i < @args; $i++) {
2820 if ($args[$i] =~ /^--?profile$/) {
2821 $profile = $args[$i + 1];
2822 splice @args, $i, 2, ();
2823 $i = 0;
2824 } elsif ($args[$i] =~ /^--?h/) {
2825 print STDERR "Usage: $0 [--profile name] [host [user [password]]]\n";
2826 exit 0;
2827 }
2828 }
2829
2830 $CFG->{profile}{$profile} ||= {};
2659 $PROFILE = $CFG->{profile}{default}; 2831 $PROFILE = $CFG->{profile}{$profile};
2832 $PROFILE->{host} ||= "gameserver.deliantra.net";
2833
2834 $PROFILE->{host} = $args[0] if @args > 0;
2835 $PROFILE->{user} = $args[1] if @args > 1;
2836 $PROFILE->{password} = $args[2] if @args > 2;
2660 2837
2661 # convert old bindings (only default profile matters) 2838 # convert old bindings (only default profile matters)
2662 if (my $bindings = delete $PROFILE->{bindings}) { 2839 if (my $bindings = delete $PROFILE->{bindings}) {
2663 while (my ($mod, $syms) = each %$bindings) { 2840 while (my ($mod, $syms) = each %$bindings) {
2664 while (my ($sym, $cmds) = each %$syms) { 2841 while (my ($sym, $cmds) = each %$syms) {
2670 } 2847 }
2671 } 2848 }
2672 2849
2673 sdl_init; 2850 sdl_init;
2674 2851
2852 $ENV{FONTCONFIG_FILE} = DC::find_rcfile "fonts/fonts.conf";
2853 $ENV{FONTCONFIG_DIR} = DC::find_rcfile "fonts";
2854
2675 { 2855 {
2676 my @fonts = map DC::find_rcfile "fonts/$_", qw( 2856 my @fonts = map DC::find_rcfile "fonts/$_", qw(
2677 DejaVuSans.ttf 2857 DejaVuSans.ttf
2678 DejaVuSansMono.ttf 2858 DejaVuSansMono.ttf
2679 DejaVuSans-Bold.ttf 2859 DejaVuSans-Bold.ttf
2680 DejaVuSansMono-Bold.ttf 2860 DejaVuSansMono-Bold.ttf
2681 DejaVuSans-Oblique.ttf 2861 DejaVuSans-Oblique.ttf
2682 DejaVuSansMono-Oblique.ttf 2862 DejaVuSansMono-Oblique.ttf
2683 DejaVuSans-BoldOblique.ttf 2863 DejaVuSans-BoldOblique.ttf
2684 DejaVuSansMono-BoldOblique.ttf 2864 DejaVuSansMono-BoldOblique.ttf
2865 mona.ttf
2685 ); 2866 );
2686 2867
2687 DC::add_font $_ for @fonts; 2868 DC::add_font $_ for @fonts;
2688 2869
2689 $FONT_PROP = new_from_file DC::Font $fonts[0]; 2870 $FONT_PROP = new_from_file DC::Font $fonts[0];
2690 $FONT_FIXED = new_from_file DC::Font $fonts[1]; 2871 $FONT_FIXED = new_from_file DC::Font $fonts[1];
2691 2872
2692 $FONT_PROP->make_default; 2873 $FONT_PROP->make_default;
2693 2874
2716 our $STARTUP_CANCEL = EV::idle sub { 2897 our $STARTUP_CANCEL = EV::idle sub {
2717 undef $::STARTUP_CANCEL; 2898 undef $::STARTUP_CANCEL;
2718 $startup_done->(); 2899 $startup_done->();
2719 }; 2900 };
2720 2901
2902 debug_toggle 0;
2903
2721 delete $SIG{__DIE__}; 2904 delete $SIG{__DIE__};
2722 EV::loop; 2905 EV::loop;
2723 2906
2907 DC::write_cfg if $CFG->{config_autosave};
2908
2724#video_shutdown; 2909 #video_shutdown;
2725#audio_shutdown; 2910 #audio_shutdown;
2911
2726 DC::OpenGL::quit; 2912 DC::OpenGL::quit;
2727 DC::SDL_Quit; 2913 DC::SDL_Quit;
2728 DC::DB::Server::stop; 2914 DC::DB::Server::stop;
2729} 2915}
2730 2916
2734 2920
2735deliantra - A Deliantra MORPG game client 2921deliantra - A Deliantra MORPG game client
2736 2922
2737=head1 SYNOPSIS 2923=head1 SYNOPSIS
2738 2924
2739Just run it - no commandline arguments are supported. 2925 deliantra [--profile name] [host [user [password]]]
2926 deliantra --help
2740 2927
2741=head1 USAGE 2928=head1 USAGE
2742 2929
2743deliantra utilises OpenGL for all UI elements and the game. It is supposed to 2930The deliantra client utilises OpenGL for all UI elements and the game. It
2744be used in fullscreen mode and interactively. 2931is supposed to be used in fullscreen mode and interactively.
2745 2932
2746=head1 DEBUGGING 2933=head1 DEBUGGING
2747 2934
2748
2749CFPLUS_DEBUG - environment variable 2935DELIANTRA_DEBUG - environment variable
2750 2936
2751 1 draw borders around widgets 2937 1 draw borders around widgets
2752 2 add low-level widget info to tooltips 2938 2 add low-level widget info to tooltips
2753 4 show fps 2939 4 show fps
2754 8 suppress tooltips 2940 8 suppress tooltips
2941 16 show bandwidth downstream
2755 2942
2756=head1 AUTHOR 2943=head1 AUTHOR
2757 2944
2758Marc Lehmann <deliantra@schmorp.de>, Robin Redeker <elmex@ta-sa.org> 2945Marc Lehmann <deliantra@schmorp.de>, Robin Redeker <elmex@ta-sa.org>
2759 2946

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines