--- deliantra/Deliantra-Client/bin/cfplus 2006/05/30 07:13:09 1.33 +++ deliantra/Deliantra-Client/bin/cfplus 2006/06/05 01:59:59 1.54 @@ -43,6 +43,7 @@ $Event::DIED = sub { # TODO: display dialog box or so + Carp::confess $_[1];#d#TODO: remove when stable CFClient::error $_[1]; }; @@ -83,7 +84,13 @@ our $METASERVER; our $LOGIN_BUTTON; our $QUIT_DIALOG; -our $SERVER_SETUP; +our $HOST_ENTRY; + +our $SETUP_DIALOG; +our $SETUP_NOTEBOOK; +our $SETUP_SERVER; +our $SETUP_KEYBOARD; +our $SETUP_SPELLS; our $FLOORBOX; our $GAUGES; @@ -105,7 +112,9 @@ our $INVR; our $INV_RIGHT_HB; -our $BIND_WINDOW; +our $BIND_EDITOR; + +our $PICKUP_CFG; sub status { $STATUSBOX->add (CFClient::UI::Label::escape $_[0], pri => -10, group => "status", timeout => 10, fg => [1, 1, 0, 1]); @@ -119,7 +128,7 @@ status "logging in..."; $LOGIN_BUTTON->set_text ("Logout"); - $SERVER_SETUP->hide; + $SETUP_DIALOG->hide; my $mapsize = List::Util::min 32, List::Util::max 11, int $WIDTH * $CFG->{mapsize} * 0.01 / 32; @@ -167,9 +176,9 @@ sub stop_game { $LOGIN_BUTTON->set_text ("Login"); - $SERVER_SETUP->show; + $SETUP_NOTEBOOK->set_current_page ($SETUP_SERVER); + $SETUP_DIALOG->show; $INV_WINDOW->hide; - $LOGVIEW->hide; return unless $CONN; @@ -179,13 +188,8 @@ $CONN = 0; # false, does not autovivify } -sub client_setup { - my $dialog = new CFClient::UI::FancyFrame - x => 1, - y => $HEIGHT * (1/8), - name => "client_setup", - title => "Client Setup", - child => (my $vbox = new CFClient::UI::VBox); +sub graphics_setup { + my $vbox = new CFClient::UI::VBox; $vbox->add (my $table = new CFClient::UI::Table expand => 1, col_expand => [0, 1]); @@ -320,6 +324,16 @@ } ); + $vbox +} + +sub audio_setup { + my $vbox = new CFClient::UI::VBox; + + $vbox->add (my $table = new CFClient::UI::Table expand => 1, col_expand => [0, 1]); + + my $row = 0; + $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Audio Enable"); $table->add (1, $row++, new CFClient::UI::CheckBox state => $CFG->{audio_enable}, @@ -359,19 +373,7 @@ } ); - $table->add (0, $row, new CFClient::UI::Label valign => 0, align => 1, text => "Chat Command"); - $table->add (1, $row++, my $saycmd = new CFClient::UI::Entry - 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.", - on_changed => sub { - my ($self, $value) = @_; - $CFG->{say_command} = $value; - } - ); - - $dialog + $vbox } sub set_stats_window_fontsize { @@ -554,8 +556,8 @@ $tgw } -sub formsep { - reverse join ",", grep length, split /(...)/, reverse $_[0] * 1 +sub formsep($) { + scalar reverse join ",", unpack "(A3)*", reverse $_[0] * 1 } sub update_stats_window { @@ -627,21 +629,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; @@ -703,7 +693,8 @@ $table->add (0, $y, new CFClient::UI::VBox children => [ (new CFClient::UI::Button text => "Use", on_activate => sub { - $HOST->set_text ($CFG->{host} = $host); + $HOST_ENTRY->set_text ($CFG->{host} = $host); + $METASERVER->toggle_visibility; }), (new CFClient::UI::Empty expand => 1), ]); @@ -716,15 +707,26 @@ }); } -sub server_setup { - my $dialog = $SERVER_SETUP = new CFClient::UI::FancyFrame - x => "center", - y => "center", - name => "server_setup", - title => "Server Setup", +sub metaserver_dialog { + my $dialog = new CFClient::UI::FancyFrame + 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 $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"); @@ -732,7 +734,7 @@ $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", @@ -744,14 +746,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", - on_open => sub { - update_metaserver $HOST; - } + on_activate => sub { $METASERVER->toggle_visibility }, ); } @@ -828,7 +828,19 @@ }, ); - $dialog + $table->add (0, 12, new CFClient::UI::Label valign => 0, align => 1, text => "Chat Command"); + $table->add (1, 12, my $saycmd = new CFClient::UI::Entry + 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.", + on_changed => sub { + my ($self, $value) = @_; + $CFG->{say_command} = $value; + } + ); + + $vbox } sub message_window { @@ -864,9 +876,7 @@ my ($input, $text) = @_; $input->set_text (''); - if ($text =~ /^\/bind\s+(.*)$/) { - CFClient::Recorder::open_binding_dialog ([$1]); - } elsif ($text =~ /^\/(.*)/) { + if ($text =~ /^\/(.*)/) { $::CONN->user_send ($1); } else { my $say_cmd = $::CFG->{say_command} || 'say'; @@ -921,6 +931,75 @@ $QUIT_DIALOG->show; } +sub autopickup_setup { + my $table = new CFClient::UI::Table; + + for ( + ["General", 0, 0, + ["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", 0, 6, + ["All weapons" => CFClient::Pickup::PU_ALLWEAPON], + ["Missile weapons" => CFClient::Pickup::PU_MISSILEWEAPON], + ["Bows" => CFClient::Pickup::PU_BOW], + ["Arrows" => CFClient::Pickup::PU_ARROW], + ], + ["Armour", 0, 12, + ["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", 2, 2, + ["Spellbooks" => CFClient::Pickup::PU_SPELLBOOK], + ["Skillscrolls" => CFClient::Pickup::PU_SKILLSCROLL], + ["Normal Books/Scrolls" => CFClient::Pickup::PU_READABLES], + ], + ["Misc", 2, 7, + ["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], + ], + ) + { + my ($title, $x, $y, @bits) = @$_; + $table->add ($x, $y, new CFClient::UI::Label text => $title, align => 1, fg => [1, 1, 0]); + + for (@bits) { + ++$y; + + my $mask = $_->[1]; + $table->add ($x , $y, new CFClient::UI::Label text => $_->[0], align => 1, expand => 1); + $table->add ($x+1, $y, 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; + }); + } + } + + $table +} + sub make_inventory_window { my $invwin = $INV_WINDOW = new CFClient::UI::FancyFrame x => "center", @@ -928,7 +1007,6 @@ force_w => $WIDTH * 9/10, force_h => $HEIGHT * 9/10, title => "Inventory", - name => "inventory_window", ; $invwin->add (my $hb = new CFClient::UI::HBox homogeneous => 1); @@ -949,10 +1027,15 @@ $invwin } -sub make_binding_window { +sub spell_setup { + new CFClient::UI::SpellList +} + +sub keyboard_setup { my $binding_list = new CFClient::UI::VBox; - my $refresh = sub { + my $refresh; + $refresh = sub { $binding_list->clear (); for my $mod (keys %{$::CFG->{bindings}}) { @@ -961,41 +1044,93 @@ next unless ref $cmds eq 'ARRAY' and @$cmds > 0; my $lbl = join "; ", @$cmds; - my $nam = CFClient::Recorder::keycombo_to_name ($mod, $sym); + 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::Label text => "($nam)"); + + $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->(); + $SETUP_NOTEBOOK->set_current_page ($SETUP_KEYBOARD); + $SETUP_DIALOG->show; + }, + sub { + $SETUP_NOTEBOOK->set_current_page ($SETUP_KEYBOARD); + $SETUP_DIALOG->show; + }); + $::BIND_EDITOR->show; + $SETUP_DIALOG->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; - }; + 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->(); + $SETUP_NOTEBOOK->set_current_page ($SETUP_KEYBOARD); + $SETUP_DIALOG->show; + }, + sub { + $SETUP_NOTEBOOK->set_current_page ($SETUP_KEYBOARD); + $SETUP_DIALOG->show; + }, + ); + $SETUP_DIALOG->hide; + $::BIND_EDITOR->show; + }, + ); + + $hb->add (new CFClient::UI::Button + text => "close", + tooltip => "Closes the binding window", + expand => 1, + on_activate => sub { + $SETUP_DIALOG->hide; + } + ); - $BIND_WINDOW->add ($binding_list); $refresh->(); - $BIND_WINDOW + + $vb } sub make_help_window { my $win = new CFClient::UI::FancyFrame - def_w => int $WIDTH * 7/8, - def_h => int $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); @@ -1072,9 +1207,11 @@ 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]); + $STATUSBOX->add ("Use Alt-Enter to toggle fullscreen mode", timeout => 864000, pri => -100, color => [1, 1, 1, 0.8]); (new CFClient::UI::Frame bg => [0, 0, 0, 0.4], @@ -1084,6 +1221,8 @@ )->show; CFClient::UI::FancyFrame->new ( + title => "Map", + name => "mapmap", x => 0, y => $FONTSIZE + 8, border_bg => [1, 1, 1, 192/255], @@ -1118,12 +1257,42 @@ tooltip => "Server Log. This text viewer contains all the messages sent by the server.", ; + $SETUP_DIALOG = new CFClient::UI::FancyFrame + title => "Setup", + name => "setup_dialog", + x => 'center', + y => 'center', + z => 2, + force_w => $::WIDTH * 0.6, + force_h => $::HEIGHT * 0.6, + ; + + $SETUP_DIALOG->add ($SETUP_NOTEBOOK = new CFClient::UI::Notebook expand => 1, debug => 1, + filter => new CFClient::UI::ScrolledWindow xxx => 1, expand => 1, scroll_y => 1); + + $SETUP_NOTEBOOK->add (Server => $SETUP_SERVER = server_setup, + "Configure the server to play on, your username, password and other server-related options."); + $SETUP_NOTEBOOK->add (Pickup => autopickup_setup, + "Configure autopicking stetings, i.e. which items you will pick up automatically when walking over them."); + $SETUP_NOTEBOOK->add (Graphics => graphics_setup, + "Configure the video mode, performance, fonts and other graphical aspects of the game."); + $SETUP_NOTEBOOK->add (Audio => audio_setup, + "Configure the use of audio, sound effects and background music."); + $SETUP_NOTEBOOK->add (Keyboard => $SETUP_KEYBOARD = keyboard_setup, + "Lets you define, edit and delete bindings." + . "There is a shortcut for making bindings: Left Control + 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"); + $SETUP_NOTEBOOK->add (Spells => $SETUP_SPELLS = spell_setup, + "Displays all spells you have and lets you edit keyboard shortcuts for them."); + $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."); - $BUTTONBAR->add (new CFClient::UI::Flopper text => "Server Setup", other => server_setup, - tooltip => "Toggles a dialog where you can configure the server to play on, your username, password and other server-related options."); + $BUTTONBAR->add (new CFClient::UI::Flopper text => "Setup", other => $SETUP_DIALOG, + tooltip => "Toggles a dialog where you can configure all aspects of this client."); + $BUTTONBAR->add (new CFClient::UI::Flopper text => "Message Window", other => message_window, tooltip => "Toggles the server message log, where the client collects all messages from the server."); @@ -1132,7 +1301,8 @@ $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 treasures :). " + . "You can also hit the Tab-key to show/hide the Inventory."); $BUTTONBAR->add (new CFClient::UI::Button text => "Save Config", @@ -1147,14 +1317,6 @@ $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 delete bindings you have made with the recorder" - ); - $BUTTONBAR->add (new CFClient::UI::Flopper text => "[Rec]", other => CFClient::Recorder::make_window, - tooltip => "This feature lets you record a series of actions (eg. walking a path or ready a skill) and bind them to keys"); - $BUTTONBAR->add (new CFClient::UI::Button text => "Quit", tooltip => "Terminates the program", @@ -1168,10 +1330,10 @@ ); $BUTTONBAR->show; - $SERVER_SETUP->show; - - $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); + $SETUP_DIALOG->show; } + + $STATUSBOX->add ("Set video mode $WIDTH×$HEIGHT", timeout => 10, fg => [1, 1, 1, 0.5]); } sub video_shutdown { @@ -1313,7 +1475,7 @@ CFClient::SDL_GL_SwapBuffers; } -my $refresh_watcher = Event->timer (after => 0, hard => 1, interval => 1 / $MAX_FPS, cb => sub { +my $refresh_watcher = Event->timer (after => 0, hard => 0, interval => 1 / $MAX_FPS, cb => sub { $NOW = time; ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_) @@ -1390,7 +1552,11 @@ $SIG{INT} = $SIG{TERM} = sub { exit }; { - local $SIG{__DIE__} = sub { CFClient::fatal $_[0] if defined $^S && !$^S }; + local $SIG{__DIE__} = sub { + return unless defined $^S && !$^S; + Carp::confess $_[1];#d#TODO: remove when stable + CFClient::fatal $_[0]; + }; CFClient::read_cfg "$Crossfire::VARDIR/cfplusrc"; CFClient::UI::set_layout ($::CFG->{layout}); @@ -1491,6 +1657,16 @@ 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