--- deliantra/Deliantra-Client/bin/cfplus 2006/05/27 20:26:22 1.17 +++ deliantra/Deliantra-Client/bin/cfplus 2006/06/02 16:52:49 1.45 @@ -83,6 +83,8 @@ our $METASERVER; our $LOGIN_BUTTON; our $QUIT_DIALOG; +our $HOST_ENTRY; +our $SERVER_SETUP; our $FLOORBOX; our $GAUGES; @@ -99,9 +101,16 @@ our $STATUSBOX; our $DEBUG_STATUS; +our $INV_WINDOW; our $INV; our $INVR; -our $INVR_LBL; +our $INV_RIGHT_HB; + +our $BIND_WINDOW; +our $BIND_EDITOR; + +our $SPELL_LIST; +our $PICKUP_CFG; sub status { $STATUSBOX->add (CFClient::UI::Label::escape $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]); @@ -109,13 +118,14 @@ sub debug { $DEBUG_STATUS->set_text ($_[0]); - my ($w, $h) = $DEBUG_STATUS->size_request; - $DEBUG_STATUS->move ($WIDTH - $w, 0); } sub start_game { status "logging in..."; + $LOGIN_BUTTON->set_text ("Logout"); + $SERVER_SETUP->hide; + my $mapsize = List::Util::min 32, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32; my ($host, $port) = split /:/, $CFG->{host}; @@ -153,12 +163,7 @@ if ($CONN) { CFClient::lowdelay fileno $CONN->{fh}; - $LOGIN_BUTTON->set_text ("Logout"); status "login successful"; - - $BUTTONBAR->{children}[1]->emit ("activate") - if $BUTTONBAR->{children}[1]->{state}; - } else { status "unable to connect"; stop_game(); @@ -166,28 +171,33 @@ } sub stop_game { + $LOGIN_BUTTON->set_text ("Login"); + $SERVER_SETUP->show; + $INV_WINDOW->hide; + $LOGVIEW->hide; + return unless $CONN; status "connection closed"; - $LOGIN_BUTTON->set_text ("Login"); + $CONN->destroy; $CONN = 0; # false, does not autovivify - - $BUTTONBAR->{children}[1]->emit ("activate") - unless $BUTTONBAR->{children}[1]->{state}; } sub client_setup { my $dialog = new CFClient::UI::FancyFrame - name => "client_setup", + x => 1, + y => $HEIGHT * (1/8), + name => "client_setup", title => "Client Setup", child => (my $vbox = new CFClient::UI::VBox); + $vbox->add (my $table = new CFClient::UI::Table expand => 1, col_expand => [0, 1]); $table->add (0, 0, new CFClient::UI::Label valign => 0, align => 1, text => "Video Mode"); $table->add (1, 0, my $hbox = new CFClient::UI::HBox); - $hbox->add (my $mode_slider = new CFClient::UI::Slider expand => 1, req_w => 100, range => [$CFG->{sdl_mode}, 0, $#SDL_MODES, 0, 1]); + $hbox->add (my $mode_slider = new CFClient::UI::Slider force_w => $WIDTH * 0.1, expand => 1, range => [$CFG->{sdl_mode}, 0, $#SDL_MODES, 0, 1]); $hbox->add (my $mode_label = new CFClient::UI::Label align => 0, valign => 0, height => 0.8, template => "9999x9999"); $mode_slider->connect (changed => sub { @@ -204,7 +214,7 @@ $table->add (1, $row++, new CFClient::UI::CheckBox state => $CFG->{fullscreen}, tooltip => "Bring the client into fullscreen mode.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{fullscreen} = $value; } @@ -214,7 +224,7 @@ $table->add (1, $row++, new CFClient::UI::CheckBox state => $CFG->{fast}, tooltip => "Lower the visual quality considerably to speed up rendering.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{fast} = $value; } @@ -224,7 +234,7 @@ $table->add (1, $row++, new CFClient::UI::Slider range => [(log $CFG->{map_scale}) / (log 2), -3, 1, 0, 1], tooltip => "Enlarge or shrink the displayed map. Changes are instant.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{map_scale} = 2 ** $value; } @@ -234,7 +244,7 @@ $table->add (1, $row++, new CFClient::UI::CheckBox state => $CFG->{fow_enable}, tooltip => "Fog-of-War marks areas that cannot be seen by the player. Changes are instant.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{fow_enable} = $value; } @@ -244,7 +254,7 @@ $table->add (1, $row++, new CFClient::UI::Slider range => [$CFG->{fow_intensity}, 0, 1, 0, 1 / 256], tooltip => "Fog of War Lightness. The higher the intensity, the lighter the Fog-of-War color. Changes are instant.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{fow_intensity} = $value; } @@ -254,7 +264,7 @@ $table->add (1, $row++, new CFClient::UI::CheckBox state => $CFG->{fow_smooth}, tooltip => "Smooth the Fog-of-War a bit to make it more realistic. Changes are instant.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{fow_smooth} = $value; status "Fog of War smoothing requires OpenGL 1.2 or higher" if $CFClient::OpenGL::GL_VERSION < 1.2; @@ -265,14 +275,14 @@ $table->add (1, $row++, new CFClient::UI::Slider range => [$CFG->{gui_fontsize}, 0.5, 2, 0, 0.1], tooltip => "The base font size used by most GUI elements that do not have their own setting.", - connect_changed => sub { $CFG->{gui_fontsize} = $_[1] }, + on_changed => sub { $CFG->{gui_fontsize} = $_[1] }, ); $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Message Fontsize"); $table->add (1, $row++, new CFClient::UI::Slider range => [$CFG->{log_fontsize}, 0.5, 2, 0, 0.1], tooltip => "The font size used by the message/server log window only. Changes are instant.", - connect_changed => sub { $LOGVIEW->set_fontsize ($CFG->{log_fontsize} = $_[1]) }, + on_changed => sub { $LOGVIEW->set_fontsize ($CFG->{log_fontsize} = $_[1]) }, ); $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Stats Fontsize"); @@ -280,7 +290,7 @@ $table->add (1, $row++, new CFClient::UI::Slider range => [$CFG->{stat_fontsize}, 0.5, 2, 0, 0.1], tooltip => "The font size used by the statistics window only. Changes are instant.", - connect_changed => sub { + on_changed => sub { $CFG->{stat_fontsize} = $_[1]; &set_stats_window_fontsize; } @@ -290,7 +300,7 @@ $table->add (1, $row++, new CFClient::UI::Slider range => [$CFG->{gauge_fontsize}, 0.5, 2, 0, 0.1], tooltip => "Adjusts the fontsize of the gauges at the bottom right. Changes are instant.", - connect_changed => sub { + on_changed => sub { $CFG->{gauge_fontsize} = $_[1]; &set_gauge_window_fontsize; } @@ -298,9 +308,9 @@ $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Gauge size"); $table->add (1, $row++, new CFClient::UI::Slider - range => [$CFG->{gauge_size}, 0.2, 0.8], - tooltip => "Adjust the size of the stats gauges at the bottom right. Changes are instant.", - connect_changed => sub { + range => [$CFG->{gauge_size}, 0.2, 0.8], + tooltip => "Adjust the size of the stats gauges at the bottom right. Changes are instant.", + on_changed => sub { $CFG->{gauge_size} = $_[1]; $GAUGES->{win}->set_size ($WIDTH, int $HEIGHT * $CFG->{gauge_size}); } @@ -309,7 +319,7 @@ $table->add (1, $row++, new CFClient::UI::Button expand => 1, align => 0, text => "Apply", tooltip => "Apply the video settings", - connect_activate => sub { + on_activate => sub { video_shutdown (); video_init (); } @@ -319,12 +329,12 @@ $table->add (1, $row++, new CFClient::UI::CheckBox state => $CFG->{audio_enable}, tooltip => "Master Audio Enable. If enabled, sound effects and music will be played. If disabled, no audio will be used and the soundcard will not be opened.", - connect_changed => sub { + on_changed => sub { $CFG->{audio_enable} = $_[1]; } ); # $table->add (0, 9, new CFClient::UI::Label valign => 0, align => 1, text => "Effects Volume"); -# $table->add (1, 8, new CFClient::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], connect_changed => sub { +# $table->add (1, 8, new CFClient::UI::Slider range => [$CFG->{effects_volume}, 0, 128, 1], on_changed => sub { # $CFG->{effects_volume} = $_[1]; # }); $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Background Music"); @@ -332,14 +342,14 @@ $hbox->add (new CFClient::UI::CheckBox expand => 1, state => $CFG->{bgm_enable}, tooltip => "If enabled, playing of background music is enabled. If disabled, no background music will be played.", - connect_changed => sub { + on_changed => sub { $CFG->{bgm_enable} = $_[1]; } ); $hbox->add (new CFClient::UI::Slider expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0, 1/128], tooltip => "The volume of the background music. Changes are instant.", - connect_changed => sub { + on_changed => sub { $CFG->{bgm_volume} = $_[1]; CFClient::MixMusic::volume $_[1] * 128; } @@ -348,7 +358,7 @@ $table->add (1, $row++, new CFClient::UI::Button expand => 1, align => 0, text => "Apply", tooltip => "Apply the audio settings", - connect_activate => sub { + on_activate => sub { audio_shutdown (); audio_init (); } @@ -360,7 +370,7 @@ 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.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{say_command} = $value; } @@ -385,9 +395,10 @@ my $gh = int $HEIGHT * $CFG->{gauge_size}; my $win = new CFClient::UI::Frame ( - req_y => -1, - user_w => $WIDTH, - user_h => $gh, + force_x => 0, + force_y => "max", + force_w => $WIDTH, + force_h => $gh, ); $win->add (my $hbox = new CFClient::UI::HBox @@ -433,8 +444,13 @@ $win } + sub make_stats_window { - my $tgw = new CFClient::UI::FancyFrame title => "Stats", name => "stats_window"; + my $tgw = new CFClient::UI::FancyFrame + y => $HEIGHT * (2/8), + x => "max", + title => "Stats", + name => "stats_window"; $tgw->add (new CFClient::UI::Window child => my $vb = new CFClient::UI::VBox); $vb->add ($STATWIDS->{title} = new CFClient::UI::Label valign => 0, align => -1, text => "Title:", expand => 1, @@ -616,21 +632,9 @@ for keys %tbl; } -sub metaserver_dialog { - my $dialog = new CFClient::UI::FancyFrame - title => "Server List", - child => (my $vbox = new CFClient::UI::VBox); - - $vbox->add ($dialog->{table} = new CFClient::UI::Table); - - $dialog -} - my $METASERVER_ATIME; sub update_metaserver { - my ($HOST) = @_; - return if $METASERVER_ATIME > time; $METASERVER_ATIME = time + 60; @@ -691,8 +695,9 @@ $y++; $table->add (0, $y, new CFClient::UI::VBox children => [ - (new CFClient::UI::Button text => "Use", connect_activate => sub { - $HOST->set_text ($CFG->{host} = $host); + (new CFClient::UI::Button text => "Use", on_activate => sub { + $HOST_ENTRY->set_text ($CFG->{host} = $host); + $METASERVER->toggle_visibility; }), (new CFClient::UI::Empty expand => 1), ]); @@ -705,12 +710,32 @@ }); } -sub server_setup { +sub metaserver_dialog { my $dialog = new CFClient::UI::FancyFrame - name => "server_setup", + title => "Server List", + name => 'metaserver_dialog', + x => 'center', + y => 'center', + child => (my $vbox = new CFClient::UI::VBox), + on_visibility_change => sub { + update_metaserver if $_[1]; + }, + ; + + $vbox->add ($dialog->{table} = new CFClient::UI::Table); + + $dialog +} + +sub server_setup { + my $dialog = $SERVER_SETUP = new CFClient::UI::FancyFrame + x => "center", + y => "center", + name => "server_setup", title => "Server Setup", - child => (my $vbox = new CFClient::UI::VBox); - + child => (my $vbox = new CFClient::UI::VBox), + ; + $vbox->add (my $table = new CFClient::UI::Table expand => 1, col_expand => [0, 1]); $table->add (0, 2, new CFClient::UI::Label valign => 0, align => 1, text => "Host:Port"); @@ -718,11 +743,11 @@ $table->add (1, 2, my $vbox = new CFClient::UI::VBox); $vbox->add ( - my $HOST = new CFClient::UI::Entry + $HOST_ENTRY = new CFClient::UI::Entry expand => 1, text => $CFG->{host}, tooltip => "The hostname or ip address of the Crossfire(+) server to connect to", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{host} = $value; } @@ -730,14 +755,12 @@ $METASERVER = metaserver_dialog; - $vbox->add (new CFClient::UI::Flopper - expand => 1, - text => "Server List", - other => $METASERVER, + $vbox->add (new CFClient::UI::Button + expand => 1, + text => "Server List", + other => $METASERVER, tooltip => "Show a list of available crossfire servers", - connect_open => sub { - update_metaserver $HOST; - } + on_activate => sub { $METASERVER->toggle_visibility }, ); } @@ -745,7 +768,7 @@ $table->add (1, 4, new CFClient::UI::Entry text => $CFG->{user}, tooltip => "The name of your character on the server", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{user} = $value; } @@ -756,7 +779,7 @@ text => $CFG->{password}, hidden => 1, tooltip => "The password for your character", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{password} = $value; } @@ -764,13 +787,13 @@ $table->add (0, 7, new CFClient::UI::Label valign => 0, align => 1, text => "Map Size"); $table->add (1, 7, new CFClient::UI::Slider - req_w => 100, + force_w => 100, range => [$CFG->{mapsize}, 10, 100, 0, 1], tooltip => "This is the size of the portion of the map update the server sends you. " . "If you set this to a high value you will be able to see further, " . "but you also increase bandwidth requirements and latency. " . "This option is only used once at log-in.", - connect_changed => sub { + on_changed => sub { my ($self, $value) = @_; $CFG->{mapsize} = $self->{range}[0] = $value = int $value; @@ -787,28 +810,28 @@ . "It also uses up server bandwidth on every connect, " . "so only set it if you really need to prefetch images. " . "This option can be set and unset any time.", - connect_changed => sub { $CFG->{face_prefetch} = $_[1] }, + on_changed => sub { $CFG->{face_prefetch} = $_[1] }, ); $table->add (0, 9, new CFClient::UI::Label valign => 0, align => 1, text => "Output-Count"); $table->add (1, 9, new CFClient::UI::Entry text => $CFG->{output_count}, tooltip => "Should be set to 1 unless you know what you are doing. This option is only used once at log-in.", - connect_changed => sub { $CFG->{output_count} = $_[1] }, + on_changed => sub { $CFG->{output_count} = $_[1] }, ); $table->add (0, 10, new CFClient::UI::Label valign => 0, align => 1, text => "Output-Sync"); $table->add (1, 10, new CFClient::UI::Entry text => $CFG->{output_sync}, tooltip => "Should be set to 1 unless you know what you are doing. This option is only used once at log-in.", - connect_changed => sub { $CFG->{output_sync} = $_[1] }, + on_changed => sub { $CFG->{output_sync} = $_[1] }, ); $table->add (1, 11, $LOGIN_BUTTON = new CFClient::UI::Button expand => 1, align => 0, text => "Login", - connect_activate => sub { + on_activate => sub { $CONN ? stop_game : start_game; }, @@ -823,8 +846,10 @@ title => "Messages", border_bg => [1, 1, 1, 1], bg => [0, 0, 0, 0.75], - user_w => int $::WIDTH / 3, - user_h => int $::HEIGHT / 5, + x => "max", + y => 0, + force_w => $::WIDTH / 3, + force_h => $::HEIGHT / 5, child => (my $vbox = new CFClient::UI::VBox); $vbox->add ($LOGVIEW); @@ -834,7 +859,7 @@ . "from the client setup will be prepended (e.g. shout, chat...). " . "If you prepend a slash (/), you will submit a command instead (similar to IRC). " . "A better way to submit commands (and the occasional chat command) is often the map command completer.", - connect_focus_in => sub { + on_focus_in => sub { my ($input, $prev_focus) = @_; delete $input->{refocus_map}; @@ -844,11 +869,16 @@ } delete $input->{auto_activated}; }, - connect_activate => sub { + on_activate => sub { my ($input, $text) = @_; $input->set_text (''); - if ($text =~ /^\/(.*)/) { + if ($text =~ /^\/bind\s+(.*)$/) { + CFClient::Binder::open_binding_dialog (sub { + my ($mod, $sym) = @_; + $::CFG->{bindings}->{$mod}->{$sym} = [$1]; + }); + } elsif ($text =~ /^\/(.*)/) { $::CONN->user_send ($1); } else { my $say_cmd = $::CFG->{say_command} || 'say'; @@ -859,14 +889,14 @@ $MAPWIDGET->focus_in } }, - connect_escape => sub { + on_escape => sub { $MAPWIDGET->focus_in }, ); $CONSOLE = { window => $window, - input => $input + input => $input, }; $window @@ -874,8 +904,11 @@ sub open_quit_dialog { unless ($QUIT_DIALOG) { - - $QUIT_DIALOG = new CFClient::UI::FancyFrame title => "Really Quit?"; + $QUIT_DIALOG = new CFClient::UI::FancyFrame + x => "center", + y => "center", + title => "Really Quit?", + ; $QUIT_DIALOG->add (my $vb = new CFClient::UI::VBox expand => 1); @@ -888,53 +921,234 @@ $hb->add (new CFClient::UI::Button text => "Ok", expand => 1, - connect_activate => sub { $QUIT_DIALOG->hide }, + on_activate => sub { $QUIT_DIALOG->hide }, ); $hb->add (new CFClient::UI::Button text => "Quit anyway", expand => 1, - connect_activate => sub { exit }, + on_activate => sub { exit }, ); + } - $QUIT_DIALOG->show_centered; - } else { - $QUIT_DIALOG->show_centered; + $QUIT_DIALOG->show; +} + +sub make_pickup_cfg_window { + $PICKUP_CFG = new CFClient::UI::FancyFrame + title => "Autopickup configuration", + x => "center", + y => "center", + force_w => $WIDTH * 6/10, + force_h => $HEIGHT * 9/10; + + + $PICKUP_CFG->add (my $vb = new CFClient::UI::VBox); + $vb->add (my $gen_tbl = new CFClient::UI::Table expand => 1); + $vb->add (my $hb = new CFClient::UI::HBox expand => 1); + $hb->add (my $ltbl = new CFClient::UI::Table expand => 1); + $hb->add (my $rtbl = new CFClient::UI::Table expand => 1); + + my $tbl = 0; + my $tblrow = 0; + + for ( + ["General", $gen_tbl], + ["Enable autopickup" => CFClient::Pickup::PU_NEWMODE], + ["Inhibit autopickup" => CFClient::Pickup::PU_INHIBIT], + ["Stop before pickup" => CFClient::Pickup::PU_STOP], + ["Debug autopickup" => CFClient::Pickup::PU_DEBUG], + ["Weapons", $ltbl], + ["All weapons" => CFClient::Pickup::PU_ALLWEAPON], + ["Missile weapons" => CFClient::Pickup::PU_MISSILEWEAPON], + ["Bows" => CFClient::Pickup::PU_BOW], + ["Arrows" => CFClient::Pickup::PU_ARROW], + ["Armour"], + ["Helmets" => CFClient::Pickup::PU_HELMET], + ["Shields" => CFClient::Pickup::PU_SHIELD], + ["Body Armour" => CFClient::Pickup::PU_ARMOUR], + ["Boots" => CFClient::Pickup::PU_BOOTS], + ["Gloves" => CFClient::Pickup::PU_GLOVES], + ["Cloaks" => CFClient::Pickup::PU_CLOAK], + ["Readables", $rtbl], + ["Spellbooks" => CFClient::Pickup::PU_SPELLBOOK], + ["Skillscrolls" => CFClient::Pickup::PU_SKILLSCROLL], + ["Normal Books/Scrolls" => CFClient::Pickup::PU_READABLES], + ["Misc"], + ["Food" => CFClient::Pickup::PU_FOOD], + ["Drinks" => CFClient::Pickup::PU_DRINK], + ["Valuables (Money, Gems)" => CFClient::Pickup::PU_VALUABLES], + ["Keys" => CFClient::Pickup::PU_KEY], + ["Magical Items" => CFClient::Pickup::PU_MAGICAL], + ["Potions" => CFClient::Pickup::PU_POTION], + ["Magic Devices" => CFClient::Pickup::PU_MAGIC_DEVICE], + ["Ignore cursed" => CFClient::Pickup::PU_NOT_CURSED], + ["Jewelery" => CFClient::Pickup::PU_JEWELS], + ) + { + if (ref $_->[1]) { + $tbl = $_->[1]; + $tblrow = 0; + $tbl->add (0, $tblrow++, new CFClient::UI::Label text => $_->[0], align => -1); + } elsif (not defined $_->[1]) { + $tbl->add (0, $tblrow++, new CFClient::UI::Label text => $_->[0], align => -1); + } else { + my $mask = $_->[1]; + $tbl->add (0, $tblrow, new CFClient::UI::Label text => $_->[0], align => 1, expand => 1); + $tbl->add (1, $tblrow++, new CFClient::UI::CheckBox + state => $CFG->{pickup} & $mask, + on_changed => sub { + my ($box, $value) = @_; + if ($value) { + $::CFG->{pickup} |= $mask; + } else { + $::CFG->{pickup} = $::CFG->{pickup} & ~$mask; + } + $::CONN->send (sprintf "command pickup %u", $::CFG->{pickup}) + if defined $::CONN; + }); + } } + + $PICKUP_CFG } sub make_inventory_window { - my $invwin = new CFClient::UI::FancyFrame - user_w => $WIDTH * (7/8), user_h => $HEIGHT * (7/8), title => "Inventory", name => "inventory_window"; + my $invwin = $INV_WINDOW = new CFClient::UI::FancyFrame + x => "center", + y => "center", + force_w => $WIDTH * 9/10, + force_h => $HEIGHT * 9/10, + title => "Inventory", + ; + + $invwin->add (my $hb = new CFClient::UI::HBox homogeneous => 1); + + $hb->add (my $vb1 = new CFClient::UI::VBox); + $vb1->add (new CFClient::UI::Label align => 0, text => "Player"); + $vb1->add ($INV = new CFClient::UI::Inventory expand => 1); - $invwin->add (my $hb = new CFClient::UI::HBox expand => 1); + $hb->add (my $vb2 = new CFClient::UI::VBox); - $hb->add (my $vb1 = new CFClient::UI::VBox expand => 1); - $vb1->add (my $lbl = new CFClient::UI::Label align => 0); - $lbl->set_text ("Player"); - $vb1->add ($INV = new CFClient::UI::Inventory expand => 1); - - $hb->add (my $vb2 = new CFClient::UI::VBox expand => 1); - - $vb2->add (my $hb2 = new CFClient::UI::HBox); - $hb2->add ($INVR_LBL = new CFClient::UI::Label align => 0, expand => 1); - $hb2->add (new CFClient::UI::Button - text => "Close", - tooltip => "Close the currently open container (if one is open)", - connect_activate => sub { - $CONN->send ("apply $CONN->{open_container}") - if $CONN->{open_container} != 0; - }, - ); + $vb2->add ($INV_RIGHT_HB = new CFClient::UI::HBox); - $INVR_LBL->set_text ("Floor"); $vb2->add ($INVR = new CFClient::UI::Inventory expand => 1); + # XXX: Call after $INVR = ... because set_opencont sets the items + CFClient::Protocol::set_opencont ($::CONN, 0, "Floor"); + $invwin } +sub make_spell_list { + $SPELL_LIST = new CFClient::UI::SpellList + force_w => $WIDTH * (9/10), + force_h => $HEIGHT * (9/10); + $SPELL_LIST +} + +sub make_binding_window { + my $binding_list = new CFClient::UI::VBox; + + my $refresh; + $refresh = sub { + $binding_list->clear (); + + for my $mod (keys %{$::CFG->{bindings}}) { + for my $sym (keys %{$::CFG->{bindings}->{$mod}}) { + my $cmds = $::CFG->{bindings}->{$mod}->{$sym}; + next unless ref $cmds eq 'ARRAY' and @$cmds > 0; + + my $lbl = join "; ", @$cmds; + my $nam = CFClient::Binder::keycombo_to_name ($mod, $sym); + $binding_list->add (my $hb = new CFClient::UI::HBox); + $hb->add (new CFClient::UI::Button + text => "delete", + tooltip => "Deletes the binding", + on_activate => sub { + $binding_list->remove ($hb); + delete $::CFG->{bindings}->{$mod}->{$sym}; + }); + + $hb->add (new CFClient::UI::Button + text => "edit", + tooltip => "Edits the binding", + on_activate => sub { + $::BIND_EDITOR->set_binding ( + $mod, $sym, $::CFG->{bindings}->{$mod}->{$sym}, + sub { + my ($nmod, $nsym, $ncmds) = @_; + delete $::CFG->{bindings}->{$mod}->{$sym}; + $::CFG->{bindings}->{$nmod}->{$nsym} = $ncmds; + $refresh->(); + $::BIND_WINDOW->show; + }, + sub { + $::BIND_WINDOW->show; + }); + $::BIND_EDITOR->show; + $::BIND_WINDOW->hide; + }); + + $hb->add (new CFClient::UI::Label text => "(Key: $nam)"); + $hb->add (new CFClient::UI::Label text => $lbl, expand => 1); + } + } + }; + + $BIND_WINDOW = new CFClient::UI::FancyFrame + title => "Bindings", + x => "center", + y => "center", + def_w => int $WIDTH * 9/10, + def_h => int $HEIGHT * 9/10, + on_visibility_change => sub { + my ($self, $visible) = @_; + $refresh->() if $visible; + }; + + $BIND_WINDOW->add (my $vb = new CFClient::UI::VBox); + $vb->add ($binding_list); + $vb->add (my $hb = new CFClient::UI::HBox); + $hb->add (new CFClient::UI::Button + text => "record new", + expand => 1, + tooltip => "This button opens the binding editor with an empty binding.", + on_activate => sub { + $::BIND_EDITOR->set_binding (undef, undef, [], + sub { + my ($mod, $sym, $cmds) = @_; + $::CFG->{bindings}->{$mod}->{$sym} = $cmds; + $refresh->(); + $::BIND_WINDOW->show; + }, + sub { + $::BIND_WINDOW->show; + }); + $::BIND_WINDOW->hide; + $::BIND_EDITOR->show; + }, + ); + $hb->add (new CFClient::UI::Button + text => "close", + tooltip => "Closes the binding window", + expand => 1, + on_activate => sub { + $::BIND_WINDOW->hide; + } + ); + + $refresh->(); + $BIND_WINDOW +} + sub make_help_window { my $win = new CFClient::UI::FancyFrame - user_w => $WIDTH * (7/8), user_h => $HEIGHT * (7/8), title => "Documentation"; + x => 'center', + y => 'center', + name => 'doc_browser', + force_w => int $WIDTH * 7/8, + force_h => int $HEIGHT * 7/8, + title => "Documentation"; $win->add (my $vbox = new CFClient::UI::VBox); @@ -951,7 +1165,7 @@ $buttons->add (new CFClient::UI::Button text => $label, - connect_activate => sub { + on_activate => sub { my $parser = new Pod::POM; my $pom = $parser->parse_file (CFClient::find_rcfile "pod/$pod.pod"); @@ -1005,19 +1219,30 @@ } else { # create the widgets - $DEBUG_STATUS = new CFClient::UI::Label padding => 0, z => 100, req_x => -1; + $DEBUG_STATUS = new CFClient::UI::Label + padding => 0, + z => 100, + force_x => "max", + force_y => 0; $DEBUG_STATUS->show; - + + $BIND_EDITOR = new CFClient::UI::BindEditor (x => "max", y => 0); + $STATUSBOX = new CFClient::UI::Statusbox; $STATUSBOX->add ("Use Alt-Enter to toggle fullscreen mode", pri => -100, color => [1, 1, 1, 0.8]); (new CFClient::UI::Frame bg => [0, 0, 0, 0.4], - req_y => -1, + force_x => 0, + force_y => "max", child => $STATUSBOX, )->show; CFClient::UI::FancyFrame->new ( + title => "Mini Map", + name => "mapmap", + x => 0, + y => $FONTSIZE + 8, border_bg => [1, 1, 1, 192/255], bg => [1, 1, 1, 0], child => ($MAPMAP = new CFClient::MapWidget::MapMap @@ -1050,7 +1275,7 @@ tooltip => "Server Log. This text viewer contains all the messages sent by the server.", ; - $BUTTONBAR = new CFClient::UI::HBox; + $BUTTONBAR = new CFClient::UI::HBox x => 0, y => 0; $BUTTONBAR->add (new CFClient::UI::Flopper text => "Client Setup", other => client_setup, tooltip => "Toggles a dialog where you can configure various aspects of the client, such as graphics mode, performance, and audio options."); @@ -1064,14 +1289,15 @@ $BUTTONBAR->add (new CFClient::UI::Flopper text => "Stats Window", other => make_stats_window, tooltip => "Toggles the statistics window, where all your Stats and Resistances are being displayed at all times."); $BUTTONBAR->add (new CFClient::UI::Flopper text => "Inventory", other => make_inventory_window, - tooltip => "Toggles the inventory window, where you can manage your loot (or treaures :)."); + tooltip => "Toggles the inventory window, where you can manage your loot (or treaures :)." + ."You can also hit the Tab-key to show/hide the Inventory."); $BUTTONBAR->add (new CFClient::UI::Button text => "Save Config", tooltip => "Saves the options chosen in the client setting, server settings and the window layout to be restored on later runs.", - connect_activate => sub { + on_activate => sub { $::CFG->{layout} = CFClient::UI::get_layout; - CFClient::write_cfg "$Crossfire::VARDIR/pclientrc"; + CFClient::write_cfg "$Crossfire::VARDIR/cfplusrc"; status "Configuration Saved"; }, ); @@ -1079,10 +1305,32 @@ $BUTTONBAR->add (new CFClient::UI::Flopper text => "Help!", other => make_help_window, tooltip => "View Documentation"); + $BUTTONBAR->add (new CFClient::UI::Flopper + text => "Bindings", + other => make_binding_window, + tooltip => + "Lets you define, edit and delete bindings." + ."There is a shortcut for making bindings: LCTRL+Insert opens the binding editor " + ."with nothing set and the recording started. After doing the actions you " + ."want to record press Insert and you will be asked to press a key-combo." + ."After pressing the combo the binding will be saved automatically and the " + ."binding editor closes"); + + $BUTTONBAR->add (new CFClient::UI::Flopper + text => "Spells", + other => make_spell_list, + tooltip => "The spell list"); + + $BUTTONBAR->add (new CFClient::UI::Flopper + text => "Pickup", + other => make_pickup_cfg_window, + tooltip => "The pickup dialog"); + + $BUTTONBAR->add (new CFClient::UI::Button - text => "Quit", - tooltip => "Terminates the program", - connect_activate => sub { + text => "Quit", + tooltip => "Terminates the program", + on_activate => sub { if ($CONN) { open_quit_dialog; } else { @@ -1092,16 +1340,9 @@ ); $BUTTONBAR->show; + $SERVER_SETUP->show; $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); - - # delay till geometry is constant - $CFClient::UI::ROOT->on_post_alloc (startup => sub { - $BUTTONBAR->{children}[1]->emit ("activate"); # pop up server setup - my $widget = $GAUGES->{win}; - $widget->move (0, $HEIGHT - $widget->{h});#d# to in toplevel - }); - force_refresh (); } } @@ -1179,7 +1420,7 @@ sub force_refresh { $fps = $fps * 0.95 + 1 / (($NOW - $LAST_REFRESH) || 0.1) * 0.05; - debug sprintf "%3.2f", $fps; + debug sprintf "%3.2f", $fps if $ENV{CFPLUS_DEBUG} & 4; $CFClient::UI::ROOT->draw; @@ -1321,9 +1562,9 @@ $SIG{INT} = $SIG{TERM} = sub { exit }; { - local $SIG{__DIE__} = sub { CFClient::fatal $_[0] }; + local $SIG{__DIE__} = sub { CFClient::fatal $_[0] if defined $^S && !$^S }; - CFClient::read_cfg "$Crossfire::VARDIR/pclientrc"; + CFClient::read_cfg "$Crossfire::VARDIR/cfplusrc"; CFClient::UI::set_layout ($::CFG->{layout}); my %DEF_CFG = ( @@ -1411,7 +1652,7 @@ =head1 NAME -pclient - A Crossfire+ and Crossfire game client +cfplus - A Crossfire+ and Crossfire game client =head1 SYNOPSIS @@ -1419,9 +1660,19 @@ =head1 USAGE -Pclient utilises OpenGL for all UI elements and the game. It is supposed to be used +cfplus utilises OpenGL for all UI elements and the game. It is supposed to be used fullscreen and interactively. +=head1 DEBUGGING + + +CFPLUS_DEBUG - environment variable + + 1 draw borders around widgets + 2 add low-level widget info to tooltips + 4 show fps + 8 suppress tooltips + =head1 AUTHOR Marc Lehmann , Robin Redeker