--- deliantra/Deliantra-Client/bin/cfplus 2006/08/13 02:43:22 1.106 +++ deliantra/Deliantra-Client/bin/cfplus 2006/11/18 22:36:00 1.127 @@ -1,5 +1,26 @@ #!/opt/bin/perl +my $startup_done = sub { }; + +# do splash-screen thingy on win32 +BEGIN { + if (%PAR::LibCache && $^O eq "MSWin32") { + while (my ($filename, $zip) = each %PAR::LibCache) { + $zip->extractMember ("SPLASH.bmp", "$ENV{PAR_TEMP}/SPLASH.bmp"); + } + + require Win32::GUI::SplashScreen; + + Win32::GUI::SplashScreen::Show ( + -file => "$ENV{PAR_TEMP}/SPLASH.bmp", + ); + + $startup_done = sub { + Win32::GUI::SplashScreen::Done (1); + }; + } +} + use strict; use utf8; @@ -10,7 +31,7 @@ while (my ($filename, $zip) = each %PAR::LibCache) { for ($zip->memberNames) { - next unless /^\/root\/(.*)/; + next unless /^root\/(.*)/; $zip->extractMember ($_, "$ENV{PAR_TEMP}/$1") unless -e "$ENV{PAR_TEMP}/$1"; } @@ -49,30 +70,21 @@ $Event::DIED = sub { # TODO: display dialog box or so Carp::cluck $_[1];#d#TODO: remove when stable - CFPlus::error $_[1]; -}; - -$SIG{__DIE__} = sub { - return if CFPlus::in_destruct; - Carp::cluck $_[0]; - CFPlus::error $_[0]; return;#d# - #return unless defined $^S && !$^S; - $Event::DIED->(undef, $_[0]); + CFPlus::fatal ($_[1]); }; -our $VERSION = '0.1'; - my $MAX_FPS = 60; my $MIN_FPS = 5; # unused as of yet -our $META_SERVER = "crossfire.real-time.com:13326"; +our $META_SERVER = "http://metaserver.schmorp.de/current.json"; our $LAST_REFRESH; our $NOW; our $CFG; our $CONN; +our $PROFILE; # current profile our $FAST; # fast, low-quality mode, possibly useful for software-rendering our $WANT_REFRESH; @@ -148,6 +160,17 @@ $DEBUG_STATUS->set_text ($_[0]); } +sub message { + my ($para) = @_; + + my $time = sprintf "%02d:%02d:%02d", (localtime time)[2,1,0]; + + $para->{markup} = "$time $para->{markup}"; + + $LOGVIEW->add_paragraph ($para); + $LOGVIEW->scroll_to_bottom; +} + sub destroy_query_dialog { (delete $_[0]{query_dialog})->destroy if $_[0]{query_dialog}; @@ -157,7 +180,7 @@ sub server_query { my ($conn, $flags, $prompt) = @_; - $conn->{query_dialog} = my $dialog = new CFPlus::UI::FancyFrame + $conn->{query_dialog} = my $dialog = new CFPlus::UI::Toplevel x => "center", y => "center", title => "Server Query", @@ -192,7 +215,7 @@ $dialog->grab_focus; } elsif ($flags & CS_QUERY_SINGLECHAR) { - $dialog->{tooltip} = "Press a key (click on the entry to make sure it has keyboard focus)"; + $dialog->{tooltip} = "#charcreation_focus"; if ($prompt =~ /Now choose a character|Press any key for the next race/i) { $MESSAGE_WINDOW->show; @@ -224,14 +247,7 @@ unshift @dialog, new CFPlus::UI::Label max_w => $::WIDTH * 0.4, ellipsise => 0, - markup => - "Character Creation: Race\n\n" - . "Look at the Messages window to see a description of this race " - . "and the center of the screen to see how this race looks like " - . "(below this dialog window: you may need to move the dialog away and " - . "click into the display area to make it visible).\n\n" - . "You can look at another race, or accept this race (you will cycle back to " - . "this race eventually, so you can take your time making this important choice." + markup => (CFPlus::Pod::section_label ui => "chargen_race"), ; } elsif ($prompt =~ /roll new stats/) { @@ -315,19 +331,14 @@ expand => 1, can_events => 1, can_hover => 1, - tooltip => $CFPlus::STAT_TOOLTIP{$name}, + tooltip => "#stat_$name", ); } unshift @dialog, new CFPlus::UI::Label max_w => $::WIDTH * 0.4, ellipsise => 0, - markup => - "Character Creation: Stats\n\n" - . "Stats are a very important aspect of your character. You can use the tooltips to learn what each Stat governs.\n\n" - . "The stats generated by the server are always sorted from Str (highest) to Cha (lowest). " - . "They will be modified later by both the race and the class you choose.\n\n" - . "You can create another set of stats, swap two stat values with each other or accept the stats as shown below and continue.\n" + markup => (CFPlus::Pod::section_label ui => "chargen_stats"), ; } @@ -366,21 +377,25 @@ $LOGIN_BUTTON->set_text ("Logout"); $SETUP_DIALOG->hide; + $PROFILE = $CFG->{profile}{default}; + my $mapsize = List::Util::min 32, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32; - my ($host, $port) = split /:/, $CFG->{profile}{default}{host}; + my ($host, $port) = split /:/, $PROFILE->{host}; - $MAP = new CFPlus::Map $mapsize, $mapsize; + $MAP = new CFPlus::Map; $CONN = eval { new CFPlus::Protocol host => $host, port => $port || 13327, - user => $CFG->{profile}{default}{user}, - pass => $CFG->{profile}{default}{password}, + user => $PROFILE->{user}, + pass => $PROFILE->{password}, mapw => $mapsize, maph => $mapsize, + client => "cfplus $CFPlus::VERSION $] $^O", + map_widget => $MAPWIDGET, logview => $LOGVIEW, statusbox => $STATUSBOX, @@ -624,19 +639,13 @@ ], ); - $hb->add (my $hg = new CFPlus::UI::Gauge type => 'hp', - tooltip => "Health points. Measures of how much damage you can take before dying. Hit points are determined from your level and are influenced by the value of your Con. Hp value may range between 1 to beyond 500 and higher values indicate a greater ability to withstand punishment."); - $hb->add (my $mg = new CFPlus::UI::Gauge type => 'mana', - tooltip => "Spell points. Measures of how much \"fuel\" you have for casting spells and incantations. Mana is calculated from your level and your Pow. Mana values can range between 1 to beyond 500 (glowing crystals can increase the current spell points beyond your normal maximum). Higher values indicate greater amounts of mana."); - $hb->add (my $gg = new CFPlus::UI::Gauge type => 'grace', - tooltip => "Grace points - how favored you are by your god. In game terms, how much divine magic you can cast. Your level, Wis and Pow effect what the value of grace is. Prayong on an altar of your god can increase this value beyond your normal maximum. Grace can take on large positive and negative values. Positive values indicate favor by the gods."); - $hb->add (my $fg = new CFPlus::UI::Gauge type => 'food', - tooltip => "Food. Ranges between 0 (starving) and 999 (satiated). At a value of 0 the character begins to die. Some magic can speed up or slow down the character digestion. Healing wounds will speed up digestion too."); - - $vbox->add (my $exp = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, - tooltip => "Experience points and overall level - experience is increased as a reward for appropriate action (such as killing monsters) and may decrease as a result of a magical attack or dying. Level is directly derived from the experience value. As the level of the character increases, the character becomes able to succeed at more difficult tasks. A character's level starts at a value of 0 and may range up beyond 100."); - $vbox->add (my $rng = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, - tooltip => "Ranged attack - how you attack when you press shift-cursor (spell, skill, weapon etc.)"); + $hb->add (my $hg = new CFPlus::UI::Gauge type => 'hp', tooltip => "#stat_health"); + $hb->add (my $mg = new CFPlus::UI::Gauge type => 'mana', tooltip => "#stat_mana"); + $hb->add (my $gg = new CFPlus::UI::Gauge type => 'grace', tooltip => "#stat_grace"); + $hb->add (my $fg = new CFPlus::UI::Gauge type => 'food', tooltip => "#stat_food"); + + $vbox->add (my $exp = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_exp"); + $vbox->add (my $rng = new CFPlus::UI::Label valign => 0, align => 1, can_hover => 1, can_events => 1, tooltip => "#stat_ranged"); $GAUGES = { exp => $exp, win => $win, range => $rng, @@ -683,14 +692,19 @@ ); $r->add (my $vb = new CFPlus::UI::VBox); - $vb->add ($STATWIDS->{title} = new CFPlus::UI::Label valign => 0, align => -1, text => "Title:", expand => 1, + $vb->add (new CFPlus::UI::FancyFrame + label => "Player", + child => (my $pi = new CFPlus::UI::VBox), + ); + + $pi->add ($STATWIDS->{title} = new CFPlus::UI::Label valign => 0, align => -1, text => "Title:", expand => 1, can_hover => 1, can_events => 1, tooltip => "Your name and title. You can change your title by using the title command, if supported by the server."); - $vb->add ($STATWIDS->{map} = new CFPlus::UI::Label valign => 0, align => -1, text => "Map:", expand => 1, + $pi->add ($STATWIDS->{map} = new CFPlus::UI::Label valign => 0, align => -1, text => "Map:", expand => 1, can_hover => 1, can_events => 1, tooltip => "The map you are currently on (if supported by the server)."); - $vb->add (my $hb0 = new CFPlus::UI::HBox); + $pi->add (my $hb0 = new CFPlus::UI::HBox); $hb0->add ($STATWIDS->{weight} = new CFPlus::UI::Label valign => 0, align => -1, text => "Weight:", expand => 1, can_hover => 1, can_events => 1, tooltip => "The weight of the player including all inventory items."); @@ -698,7 +712,10 @@ can_hover => 1, can_events => 1, tooltip => "The weight limit: you cannot carry more than this."); - $vb->add (my $hb = new CFPlus::UI::HBox expand => 1); + $vb->add (new CFPlus::UI::FancyFrame + label => "Primary/Secondary Statistics", + child => (my $hb = new CFPlus::UI::HBox expand => 1), + ); $hb->add (my $tbl = new CFPlus::UI::Table expand => 1); my $color2 = [1, 1, 0]; @@ -723,13 +740,16 @@ $tbl->add ($col , $row, $STATWIDS->{$id} = new CFPlus::UI::Label font => $FONT_FIXED, can_hover => 1, can_events => 1, valign => 0, - align => +1, template => $template, tooltip => $CFPlus::STAT_TOOLTIP{$label}); + align => +1, template => $template, tooltip => "#stat_$label"); $tbl->add ($col + 1, $row, $STATWIDS->{"$id\_lbl"} = new CFPlus::UI::Label font => $FONT_FIXED, can_hover => 1, can_events => 1, fg => $color2, valign => 0, - align => -1, text => $label, tooltip => $CFPlus::STAT_TOOLTIP{$label}); + align => -1, text => $label, tooltip => "#stat_$label"); } - $vb->add (my $tbl2 = new CFPlus::UI::Table expand => 1); + $vb->add (new CFPlus::UI::FancyFrame + label => "Resistancies", + child => (my $tbl2 = new CFPlus::UI::Table expand => 1), + ); my $row = 0; my $col = 0; @@ -839,27 +859,15 @@ $table->clear; $table->add (0, 0, my $label = new CFPlus::UI::Label max_w => $WIDTH * 0.8, text => "fetching server list..."); - my $buf; + my $ok = 0; - my $fh = new IO::Socket::INET PeerHost => $META_SERVER, Blocking => 0; - - unless ($fh) { - $label->set_text ("unable to contact metaserver: $!"); - return; - } - - Event->io (fd => $fh, poll => 'r', cb => sub { - my $res = sysread $fh, $buf, 8192, length $buf; - - if (!defined $res) { - $_[0]->w->cancel; - $label->set_text ("error while retrieving server list: $!"); - } elsif ($res == 0) { - $_[0]->w->cancel; - status "server list retrieved"; - - utf8::decode $buf if utf8::valid $buf; + CFPlus::background { + my $ua = CFPlus::lwp_useragent; + CFPlus::background_msg CFPlus::from_json +(CFPlus::lwp_check $ua->get ($META_SERVER))->decoded_content; + } sub { + my ($msg) = @_; + if ($msg) { $table->clear; my @tip = ( @@ -879,23 +887,30 @@ my @align = qw(1 0 1 1 -1); my $y = 0; - for my $m (sort { $b->[3] <=> $a->[3] } map [split /\|/], split /\015?\012/, $buf) { - my ($ip, $last, $host, $users, $version, $desc, $ibytes, $obytes, $uptime) = @$m; + for my $m ( + sort { + $b->{version} <=> $a->{version} + or $b->{users} <=> $a->{users} + } + @{ $msg->{servers} } + ) { + my ($ip, $last, $host, $users, $version, $desc, $ibytes, $obytes, $uptime) = + @$m{qw(ip age hostname users version description ibytes obytes uptime)}; for ($desc) { s/
/\n/gi; s/
  • /\n· /gi; s/<.*?>//sgi; - s/&/&/g; - s//>/g; + s/&/&/g; + s/<//g; } $uptime = sprintf "%dd %02d:%02d:%02d", - (int $m->[8] / 86400), - (int $m->[8] / 3600) % 24, - (int $m->[8] / 60) % 60, - $m->[8] % 60; + (int $uptime / 86400), + (int $uptime / 3600) % 24, + (int $uptime / 60) % 60, + $uptime % 60; $m = [$users, $host, $uptime, $version, $desc]; @@ -915,17 +930,22 @@ ]); $table->add ($_, $y, new CFPlus::UI::Label + max_w => $::WIDTH * 0.4, ellipsise => 0, align => $align[$_], text => $m->[$_], tooltip => $tip[$_], + fg => ($m->[3] =~ /\+$/ ? [1, 1, 1] : [.7, .7, .7]), can_hover => 1, can_events => 1, fontsize => 0.8) for 0 .. $#$m; } + } else { + $ok or $label->set_text ("error while contacting metaserver"); } - }); + }; + } sub metaserver_dialog { @@ -933,13 +953,14 @@ my $table = new CFPlus::UI::Table; $vbox->add (new CFPlus::UI::ScrolledWindow expand => 1, child => $table); - my $dialog = new CFPlus::UI::FancyFrame + my $dialog = new CFPlus::UI::Toplevel title => "Server List", name => 'metaserver_dialog', x => 'center', y => 'center', z => 3, - force_h => $::HEIGHT * 0.4, + force_w => $::WIDTH * 0.9, + force_h => $::HEIGHT * 0.7, child => $vbox, has_close_button => 1, table => $table, @@ -955,7 +976,10 @@ sub server_setup { my $vbox = new CFPlus::UI::VBox; - $vbox->add (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 1]); + $vbox->add (new CFPlus::UI::FancyFrame + label => "Connection Settings", + child => (my $table = new CFPlus::UI::Table expand => 1, col_expand => [0, 1]), + ); $table->add (0, 2, new CFPlus::UI::Label valign => 0, align => 1, text => "Host:Port"); { @@ -1049,7 +1073,7 @@ $table->add (0, 12, new CFPlus::UI::Label valign => 0, align => 1, text => "Chat Command"); $table->add (1, 12, my $saycmd = new CFPlus::UI::Entry - text => $CFG->{say_command}, + text => $CFG->{say_command}, tooltip => "This is the command that will be used if you write a line in the message window entry or press \" in the map window. " . "Usually you want to enter something like 'say' or 'shout' or 'gsay' here. " . "But you could also set it to tell playername to only chat with that user.", @@ -1060,20 +1084,27 @@ } ); - $vbox->add (new CFPlus::UI::Label - text => "Server Info", - fontsize => 1.2, - padding_y => 8, - fg => [1, 1, 0, 1], + $table->add (0, 13, new CFPlus::UI::Label valign => 0, align => 1, text => "Tip of the day"); + $table->add (1, 13, my $saycmd = new CFPlus::UI::CheckBox + state => $CFG->{show_tips}, + tooltip => "Show the Tip of the day window at startup?", + on_changed => sub { + my ($self, $value) = @_; + $CFG->{show_tips} = $value; + 0 + } ); - $vbox->add ($SERVER_INFO = new CFPlus::UI::Label ellipsise => 0); + $vbox->add (new CFPlus::UI::FancyFrame + label => "Server Info", + child => ($SERVER_INFO = new CFPlus::UI::Label ellipsise => 0), + ); $vbox } sub message_window { - my $window = new CFPlus::UI::FancyFrame + my $window = new CFPlus::UI::Toplevel name => "message_window", title => "Messages", border_bg => [1, 1, 1, 1], @@ -1135,62 +1166,6 @@ $window } -sub open_string_query { - my $cb = $_[1]; - my $dialog = new CFPlus::UI::FancyFrame - x => "center", - y => "center", - z => 50, - force_w => $WIDTH * 4/5, - title => $_[0]; - - $dialog->add ( - my $e = new CFPlus::UI::Entry - on_activate => sub { $cb->(@_); $dialog->hide; 0 }, - on_key_down => sub { $_[1]->{sym} == 27 and $dialog->hide; 0 }, - ); - - $e->grab_focus; - $dialog->show; -} - -sub open_quit_dialog { - unless ($QUIT_DIALOG) { - $QUIT_DIALOG = new CFPlus::UI::FancyFrame - x => "center", - y => "center", - z => 50, - title => "Really Quit?", - on_key_down => sub { - my ($dialog, $ev) = @_; - $ev->{sym} == 27 and $dialog->hide; - } - ; - - $QUIT_DIALOG->add (my $vb = new CFPlus::UI::VBox expand => 1); - - $vb->add (new CFPlus::UI::Label - text => "You should find a savebed and apply it first!", - max_w => $WIDTH * 0.25, - ellipsize => 0, - ); - $vb->add (my $hb = new CFPlus::UI::HBox expand => 1); - $hb->add (new CFPlus::UI::Button - text => "Ok", - expand => 1, - on_activate => sub { $QUIT_DIALOG->hide; 0 }, - ); - $hb->add (new CFPlus::UI::Button - text => "Quit anyway", - expand => 1, - on_activate => sub { exit }, - ); - } - - $QUIT_DIALOG->show; - $QUIT_DIALOG->grab_focus; -} - sub autopickup_setup { my $table = new CFPlus::UI::Table; @@ -1329,6 +1304,7 @@ $vb1->add (my $sw1 = new CFPlus::UI::ScrolledWindow expand => 1, scroll_y => 1); $sw1->add ($INV = new CFPlus::UI::Inventory); + $INV->set_sort_order ($SORT_ORDER{$::CFG->{inv_sort}}); $hb->add (my $vb2 = new CFPlus::UI::VBox); @@ -1355,7 +1331,7 @@ } sub player_window { - my $plwin = $PL_WINDOW = new CFPlus::UI::FancyFrame + my $plwin = $PL_WINDOW = new CFPlus::UI::Toplevel x => "center", y => "center", force_w => $WIDTH * 9/10, @@ -1407,9 +1383,11 @@ $refresh = $BIND_UPD_CB = sub { $binding_list->clear (); - for my $mod (keys %{$::CFG->{profile}{default}{bindings}}) { - for my $sym (keys %{$::CFG->{profile}{default}{bindings}{$mod}}) { - my $cmds = $::CFG->{profile}{default}{bindings}{$mod}{$sym}; + return unless $PROFILE; + + for my $mod (keys %{$PROFILE->{bindings}}) { + for my $sym (keys %{$PROFILE->{bindings}{$mod}}) { + my $cmds = $PROFILE->{bindings}{$mod}{$sym}; next unless ref $cmds eq 'ARRAY' and @$cmds > 0; my $lbl = join "; ", @$cmds; @@ -1420,7 +1398,7 @@ tooltip => "Deletes the binding", on_activate => sub { $binding_list->remove ($hb); - delete $::CFG->{profile}{default}{bindings}{$mod}{$sym}; + delete $PROFILE->{bindings}{$mod}{$sym}; 0 }); @@ -1429,7 +1407,7 @@ tooltip => "Edits the binding", on_activate => sub { $::BIND_EDITOR->set_binding ( - $mod, $sym, $::CFG->{profile}{default}{bindings}{$mod}{$sym}, + $mod, $sym, $PROFILE->{bindings}{$mod}{$sym}, sub { my ($nmod, $nsym, $ncmds) = @_; $::BIND_EDITOR->cfg_unbind ($mod, $sym); @@ -1454,7 +1432,10 @@ }; my $vb = new CFPlus::UI::VBox; - $vb->add (my $hb = new CFPlus::UI::HBox); + $vb->add (new CFPlus::UI::FancyFrame + label => "Options", + child => (my $hb = new CFPlus::UI::HBox), + ); $hb->add (new CFPlus::UI::Label text => "only shift-up stops fire"); $hb->add (new CFPlus::UI::CheckBox expand => 1, @@ -1466,7 +1447,9 @@ 0 }); - $vb->add ($binding_list); + $vb->add (new CFPlus::UI::FancyFrame + label => "Bindings", + child => $binding_list); $vb->add (my $hb = new CFPlus::UI::HBox); $hb->add (new CFPlus::UI::Button @@ -1509,10 +1492,10 @@ } sub help_window { - my $win = new CFPlus::UI::FancyFrame + my $win = new CFPlus::UI::Toplevel x => 'center', y => 'center', - z => 2, + z => 4, name => 'doc_browser', force_w => int $WIDTH * 7/8, force_h => int $HEIGHT * 7/8, @@ -1521,40 +1504,203 @@ $win->add (my $vbox = new CFPlus::UI::VBox); - $vbox->add (my $buttons = new CFPlus::UI::HBox); + $vbox->add (new CFPlus::UI::FancyFrame + label => "Navigation", + child => (my $buttons = new CFPlus::UI::HBox), + ); $vbox->add (my $viewer = new CFPlus::UI::TextScroller - expand => 1, fontsize => 0.8, padding_x => 4); + expand => 1, fontsize => 0.8, padding_x => 4, padding_y => 4); - $buttons->add (new CFPlus::UI::Label text => "Choose a document to display: "); - $buttons->add (my $combo = new CFPlus::UI::Selector - value => undef, - options => [ - [intro => "Introduction"], - [manual => "Main Manual"], - [skill_help => "Skill Reference"], - [command_help => "Command Reference"], - [dmcommand_help => "DM Commands"], - [COPYING => "License Terms"], - ], - on_changed => sub { - my ($self, $pod) = @_; + my @history; + my @future; + my $curnode; - $viewer->clear; - $viewer->add_paragraph (CFPlus::Pod::section pod => $pod); - $viewer->set_offset (0); + my $load_node; $load_node = sub { + my ($node, $para) = @_; - 0 - }, - on_visibility_change => sub { - my ($self, $visible) = @_; - return unless $visible; - return if $self->{value}; - $self->set_value ("intro"); - 0 + $buttons->clear; + + $buttons->add (new CFPlus::UI::Button + text => "⇤", + tooltip => "back to the starting page", + on_activate => sub { + unshift @future, [$curnode, $viewer->current_paragraph] if $curnode; + unshift @future, @history; + @history = (); + $load_node->(@{shift @future}); + }, + ); + + if (@history) { + $buttons->add (new CFPlus::UI::Button + text => "⋘", + tooltip => "back to " . (CFPlus::asxml CFPlus::Pod::full_path $history[-1][0]) . "", + on_activate => sub { + unshift @future, [$curnode, $viewer->current_paragraph] if $curnode; + $load_node->(@{pop @history}); + }, + ); + } + + if (@future) { + $buttons->add (new CFPlus::UI::Button + text => "⋙", + tooltip => "forward to " . (CFPlus::asxml CFPlus::Pod::full_path $future[0][0]) . "", + on_activate => sub { + push @history, [$curnode, $viewer->current_paragraph]; + $load_node->(@{shift @future}); + }, + ); + } + + $buttons->add (new CFPlus::UI::Label text => " "); + + my @path = CFPlus::Pod::full_path_of $node; + pop @path; # drop current node + + for my $node (@path) { + $buttons->add (new CFPlus::UI::Button + text => $node->{kw}[0], + tooltip => "go to " . (CFPlus::asxml CFPlus::Pod::full_path $node) . "", + on_activate => sub { + push @history, [$curnode, $viewer->current_paragraph] if $curnode; @future = (); + $load_node->($node); + }, + ); + $buttons->add (new CFPlus::UI::Label text => "/"); + } + + $buttons->add (new CFPlus::UI::Label text => $node->{kw}[0], padding_x => 4, padding_y => 4); + + $curnode = $node; + + $viewer->clear; + $viewer->add_paragraph (CFPlus::Pod::as_paragraphs CFPlus::Pod::section_of $curnode); + $viewer->scroll_to ($para); + }; + + $load_node->(CFPlus::Pod::find pod => "mainpage"); + + $CFPlus::Pod::goto_document = sub { + my (@path) = @_; + + push @history, [$curnode, $viewer->current_paragraph] if $curnode; @future = (); + + $load_node->((CFPlus::Pod::find @path)[0]); + $win->show; + }; + + $win +} + +sub open_string_query { + my ($title, $cb, $txt, $tooltip) = @_; + my $dialog = new CFPlus::UI::Toplevel + x => "center", + y => "center", + z => 50, + force_w => $WIDTH * 4/5, + title => $title; + + $dialog->add ( + my $e = new CFPlus::UI::Entry + on_activate => sub { $cb->(@_); $dialog->hide; 0 }, + on_key_down => sub { $_[1]->{sym} == 27 and $dialog->hide; 0 }, + tooltip => $tooltip + ); + + $e->grab_focus; + $e->set_text ($txt) if $txt; + $dialog->show; +} + +sub open_quit_dialog { + unless ($QUIT_DIALOG) { + $QUIT_DIALOG = new CFPlus::UI::Toplevel + x => "center", + y => "center", + z => 50, + title => "Really Quit?", + on_key_down => sub { + my ($dialog, $ev) = @_; + $ev->{sym} == 27 and $dialog->hide; + } + ; + + $QUIT_DIALOG->add (my $vb = new CFPlus::UI::VBox expand => 1); + + $vb->add (new CFPlus::UI::Label + text => "You should find a savebed and apply it first!", + max_w => $WIDTH * 0.25, + ellipsize => 0, + ); + $vb->add (my $hb = new CFPlus::UI::HBox expand => 1); + $hb->add (new CFPlus::UI::Button + text => "Ok", + expand => 1, + on_activate => sub { $QUIT_DIALOG->hide; 0 }, + ); + $hb->add (new CFPlus::UI::Button + text => "Quit anyway", + expand => 1, + on_activate => sub { exit }, + ); + } + + $QUIT_DIALOG->show; + $QUIT_DIALOG->grab_focus; +} + +sub show_tip_of_the_day { + # find all tips + my @tod = CFPlus::Pod::find tip_of_the_day => "*"; + + my $todindex = $CFPlus::DB_STATE->get ("tip_of_the_day"); + $todindex = 0 if $todindex >= @tod; + $CFPlus::DB_STATE->put (tip_of_the_day => $todindex + 1); + + # create dialog + my $dialog; + + my $close = sub { + $dialog->destroy; + }; + + $dialog = new CFPlus::UI::Toplevel + x => "center", + y => "center", + z => 3, + name => 'tip_of_the_day', + force_w => int $WIDTH * 4/9, + force_h => int $WIDTH * 2/9, + title => "Tip of the day #" . (1 + $todindex), + child => my $vbox = new CFPlus::UI::VBox, + has_close_button => 1, + on_delete => $close, + ; + + $vbox->add (my $viewer = new CFPlus::UI::TextScroller + expand => 1, fontsize => 0.8, padding_x => 4, padding_y => 4); + $viewer->add_paragraph (CFPlus::Pod::as_paragraphs CFPlus::Pod::section_of $tod[$todindex]); + + $vbox->add (my $table = new CFPlus::UI::Table); + + $table->add (0, 0, new CFPlus::UI::Button + text => "Close", + tooltip => "Close the tip of the day window. To never see it again, disable the tip of the day in the Server Setup.", + on_activate => $close, + ); + + $table->add (2, 0, new CFPlus::UI::Button + text => "Next", + tooltip => "Show the next Tip of the day.", + on_activate => sub { + $close->(); + &show_tip_of_the_day; }, ); - $win + $dialog->show; } sub sdl_init { @@ -1611,7 +1757,7 @@ child => $STATUSBOX, )->show; - CFPlus::UI::FancyFrame->new ( + CFPlus::UI::Toplevel->new ( title => "Map", name => "mapmap", x => 0, @@ -1649,7 +1795,7 @@ tooltip => "Server Log. This text viewer contains all the messages sent by the server.", ; - $SETUP_DIALOG = new CFPlus::UI::FancyFrame + $SETUP_DIALOG = new CFPlus::UI::Toplevel title => "Setup", name => "setup_dialog", x => 'center', @@ -1913,7 +2059,7 @@ gauge_size => 0.35, stat_fontsize => 0.7, mapsize => 100, - say_command => 'say', + say_command => 'chat', audio_enable => 1, bgm_enable => 1, bgm_volume => 0.25, @@ -1923,6 +2069,7 @@ pickup => 0, inv_sort => "mtime", default => "profile", # default profile + show_tips => 1, ); while (my ($k, $v) = each %DEF_CFG) { @@ -1976,10 +2123,14 @@ # warn $t2-$t1; # } + $startup_done->(); + video_init; audio_init; } +show_tip_of_the_day if $CFG->{show_tips}; + Event::loop; #CFPlus::SDL_Quit; #CFPlus::_exit 0;