crossfire-client-1.75.3/cmake/000755 001751 001751 00000000000 14605665664 017044 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/cmake/FindVala.cmake000644 001751 001751 00000006113 14045044330 021506 0ustar00kevinzkevinz000000 000000 ## # Find module for the Vala compiler (valac) # # This module determines wheter a Vala compiler is installed on the current # system and where its executable is. # # Call the module using "find_package(Vala) from within your CMakeLists.txt. # # The following variables will be set after an invocation: # # VALA_FOUND Whether the vala compiler has been found or not # VALA_EXECUTABLE Full path to the valac executable if it has been found # VALA_VERSION Version number of the available valac # VALA_USE_FILE Include this file to define the vala_precompile function ## ## # Copyright 2009-2010 Jakob Westhoff. All rights reserved. # Copyright 2010-2011 Daniel Pfeifer # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # The views and conclusions contained in the software and documentation are those # of the authors and should not be interpreted as representing official policies, # either expressed or implied, of Jakob Westhoff ## # Search for the valac executable in the usual system paths # Some distributions rename the valac to contain the major.minor in the binary name find_program(VALA_EXECUTABLE NAMES valac valac-0.20 valac-0.18 valac-0.16 valac-0.14 valac-0.12 valac-0.10) mark_as_advanced(VALA_EXECUTABLE) # Determine the valac version if(VALA_EXECUTABLE) execute_process(COMMAND ${VALA_EXECUTABLE} "--version" OUTPUT_VARIABLE VALA_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE "Vala " "" VALA_VERSION "${VALA_VERSION}") endif(VALA_EXECUTABLE) # Handle the QUIETLY and REQUIRED arguments, which may be given to the find call. # Furthermore set VALA_FOUND to TRUE if Vala has been found (aka. # VALA_EXECUTABLE is set) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Vala REQUIRED_VARS VALA_EXECUTABLE VERSION_VAR VALA_VERSION) set(VALA_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseVala.cmake") crossfire-client-1.75.3/cmake/UseVala.cmake000644 001751 001751 00000016371 14045044330 021371 0ustar00kevinzkevinz000000 000000 ## # Compile vala files to their c equivalents for further processing. # # The "vala_precompile" function takes care of calling the valac executable on # the given source to produce c files which can then be processed further using # default cmake functions. # # The first parameter provided is a variable, which will be filled with a list # of c files outputted by the vala compiler. This list can than be used in # conjuction with functions like "add_executable" or others to create the # neccessary compile rules with CMake. # # The following sections may be specified afterwards to provide certain options # to the vala compiler: # # SOURCES # A list of .vala files to be compiled. Please take care to add every vala # file belonging to the currently compiled project or library as Vala will # otherwise not be able to resolve all dependencies. # # PACKAGES # A list of vala packages/libraries to be used during the compile cycle. The # package names are exactly the same, as they would be passed to the valac # "--pkg=" option. # # OPTIONS # A list of optional options to be passed to the valac executable. This can be # used to pass "--thread" for example to enable multi-threading support. # # DEFINITIONS # A list of symbols to be used for conditional compilation. They are the same # as they would be passed using the valac "--define=" option. # # CUSTOM_VAPIS # A list of custom vapi files to be included for compilation. This can be # useful to include freshly created vala libraries without having to install # them in the system. # # GENERATE_VAPI # Pass all the needed flags to the compiler to create a vapi for # the compiled library. The provided name will be used for this and a # .vapi file will be created. # # GENERATE_HEADER # Let the compiler generate a header file for the compiled code. There will # be a header file as well as an internal header file being generated called # .h and _internal.h # # The following call is a simple example to the vala_precompile macro showing # an example to every of the optional sections: # # find_package(Vala "0.12" REQUIRED) # include(${VALA_USE_FILE}) # # vala_precompile(VALA_C # SOURCES # source1.vala # source2.vala # source3.vala # PACKAGES # gtk+-2.0 # gio-1.0 # posix # DIRECTORY # gen # OPTIONS # --thread # CUSTOM_VAPIS # some_vapi.vapi # GENERATE_VAPI # myvapi # GENERATE_HEADER # myheader # ) # # Most important is the variable VALA_C which will contain all the generated c # file names after the call. ## ## # Copyright 2009-2010 Jakob Westhoff. All rights reserved. # Copyright 2010-2011 Daniel Pfeifer # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # The views and conclusions contained in the software and documentation are those # of the authors and should not be interpreted as representing official policies, # either expressed or implied, of Jakob Westhoff ## include(CMakeParseArguments) function(vala_precompile output) cmake_parse_arguments(ARGS "" "DIRECTORY;GENERATE_HEADER;GENERATE_VAPI" "SOURCES;PACKAGES;OPTIONS;DEFINITIONS;CUSTOM_VAPIS" ${ARGN}) if(ARGS_DIRECTORY) get_filename_component(DIRECTORY ${ARGS_DIRECTORY} ABSOLUTE) else(ARGS_DIRECTORY) set(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endif(ARGS_DIRECTORY) include_directories(${DIRECTORY}) set(vala_pkg_opts "") foreach(pkg ${ARGS_PACKAGES}) list(APPEND vala_pkg_opts "--pkg=${pkg}") endforeach(pkg ${ARGS_PACKAGES}) set(vala_define_opts "") foreach(def ${ARGS_DEFINTIONS}) list(APPEND vala_define_opts "--define=${def}") endforeach(def ${ARGS_DEFINTIONS}) set(in_files "") set(out_files "") foreach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS}) list(APPEND in_files "${CMAKE_CURRENT_SOURCE_DIR}/${src}") string(REPLACE ".vala" ".c" src ${src}) string(REPLACE ".gs" ".c" src ${src}) set(out_file "${DIRECTORY}/${src}") list(APPEND out_files "${DIRECTORY}/${src}") endforeach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS}) set(custom_vapi_arguments "") if(ARGS_CUSTOM_VAPIS) foreach(vapi ${ARGS_CUSTOM_VAPIS}) if(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR}) list(APPEND custom_vapi_arguments ${vapi}) else (${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR}) list(APPEND custom_vapi_arguments ${CMAKE_CURRENT_SOURCE_DIR}/${vapi}) endif(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR}) endforeach(vapi ${ARGS_CUSTOM_VAPIS}) endif(ARGS_CUSTOM_VAPIS) set(vapi_arguments "") if(ARGS_GENERATE_VAPI) list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_VAPI}.vapi") set(vapi_arguments "--vapi=${ARGS_GENERATE_VAPI}.vapi") # Header and internal header is needed to generate internal vapi if (NOT ARGS_GENERATE_HEADER) set(ARGS_GENERATE_HEADER ${ARGS_GENERATE_VAPI}) endif(NOT ARGS_GENERATE_HEADER) endif(ARGS_GENERATE_VAPI) set(header_arguments "") if(ARGS_GENERATE_HEADER) list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}.h") list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h") list(APPEND header_arguments "--header=${DIRECTORY}/${ARGS_GENERATE_HEADER}.h") list(APPEND header_arguments "--internal-header=${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h") endif(ARGS_GENERATE_HEADER) add_custom_command(OUTPUT ${out_files} COMMAND ${VALA_EXECUTABLE} ARGS "-C" ${header_arguments} ${vapi_arguments} "-b" ${CMAKE_CURRENT_SOURCE_DIR} "-d" ${DIRECTORY} ${vala_pkg_opts} ${vala_define_opts} ${ARGS_OPTIONS} ${in_files} ${custom_vapi_arguments} DEPENDS ${in_files} ${ARGS_CUSTOM_VAPIS} ) set(${output} ${out_files} PARENT_SCOPE) endfunction(vala_precompile) crossfire-client-1.75.3/ChangeLog000644 001751 001751 00001056312 14605664052 017534 0ustar00kevinzkevinz000000 000000 1.75.3 ====== 2024-04-10 **Added** - Add 'mapedit' command to launch map editor on current map - Implement smooth lighting for new Pixmap (Cairo) renderer - Add additional protocol debugging flags - Automatically set 'away' if idle for some time - Add pop-up action menu when left-clicking on items. Can be disabled with the inv_menu configuration option - Add default bindings for 'reply' and 'get all' - Add "scriptkillall" command **Changed** - Lighting defaults to per-pixel lighting - Improve movement prediction and enable it by default 1.75.2 ====== 2022-01-06 **Added** - Added 'mapscale' command to change map scaling - Right-click a tile to walk to it, double right-click to attack - Spells window shows spell icons **Changed** - All commands, not just key bindings, are shown when command echo is enabled - Improve text readability in the 'Black' theme - Image caching has been disabled until some bugs can be fixed **Removed** - OpenGL and SDL renderers have been removed **Fixed** - Fixed several bugs in the Pixmap renderer - Fixed mouse-click examine showing the wrong tile 1.75.1 ====== 2021-08-19 **Added** - Remember the most recently-connected server - Display "read" flag for books in the inventory that have been read - Add JXClient-like mouse bindings to support inventory operations without middle-click - Add local map scroll prediction (disabled by default) **Changed** - Request extended text information from older servers **Fixed** - Fixed several repeated error messages - Fixed build on big-endian architectures - Fixed keybindings and sounds on Windows - Fixed several crashes 1.75.0 ====== 2021-01-01 **Added** - Added '--script' command-line option to pre-launch scripts - Added client scripting support for drop, take, and apply - Added metaserver refresh button - Added support for face sets of any reasonable size; 24x24 has been tested **Changed** - 'request map pos' for client scripting uses relative coordinates - Item highlight color in inventory view is easier to read - Sound works without a separate sound server binary **Fixed** - Correctly wrap long words when the message pane is narrow - Fixed compile errors with recent compilers - Fixed faceset drop-down menu - Fixed some crashes - Pixmap renderer smooths correctly - Removed unused fields in all layouts except gtk-v1 and gtk-v2 1.74.0 ====== 2019-12-25 **Added** - Add "--debug-protocol" command-line option - Add "--profile-latency" command-line option - Resurrect "--server" option to connect to a server directly **Changed** - Rename "--time-redraw" to "--profile-redraw" - Report UI layout in client version string - Trim trailing whitespace from spell descriptions - Use one window for metaserver and login dialogs - Change key handling to reduce lag after holding down a key - Inventory table view no longer has a column limit **Fixed** - Handle previously unhandled 'newmapcmd' and 'tick' setup commands - Functionality and performance fixes for inventory table view with large inventories 1.73.0 ====== 2019-01-06 **Added** - Pass player and server name to client scripts **Changed** - Add text for blessed items in inventory views - Client window stays hidden until after player selection - Install sound files when SOUND is enabled - Show open containers in unlocked inventory view **Fixed** - Enable sound with older (< 0.25.3) versions of Vala - Fix delayed weight limit update when strength attribute changes - Speed up inventory redraw when picking up and dropping many items 1.72.0 ====== 2017-08-13 **Added** - Display numerical stats on HP, mana, grace, and experience bars - Fade music in and out - Highlight applied items in the inventory icon view - Speed up Pixmap rendering using Cairo - Update metaservers **Changed** - Clean up command-line arguments - Enable smoothing by default - Move music directory to *share/crossfire-client/sounds/music/* - Reduce default logging verbosity. Run with '-v 0' to show all messages. - Replace autoconf/automake build system with CMake - Save client settings in .ini format - Set default layout to *gtk-v2* - Update UI dialogs - Update sound effects - Use XDG-compliant directories for configuration and cache files. Users who wish to keep their configuration files need to manually move them to the new location. For Unix-like systems, the new location is *~/.config/crossfire*. **Removed** - Remove old metaserver (metaserver1) support **Fixed** - Fix potential socket buffer overflows - Fix various protocol-related bugs - Hide character selection window reliably after logging in - Update build for Windows ============================================================================== Changes for 1.71.0 ============================================================================== 2014-03-17 Kevin Zheng * gtk-v2/ui/gtk-v2.ui: Improve core stats display. 2014-01-26 Kevin Zheng * configure.ac: Add `configure` flag to disable OpenGL. * configure.ac: Use pkgconf to find SDL_mixer and OpenGL. 2014-01-02 Kevin Zheng * gtk-v2/src/keys.c: Fix various keybinding issues. 2014-01-01 Kevin Zheng * gtk-v2/src/config.c: Do not store last server in gdefaults2. 2013-12-30 Karla Stenger * gtk-v2/src/keys.c: Add character-specific keybindings. 2013-12-26 Kevin Zheng * gtk-v2/: Convert widgets to use GtkBuilder. 2013-09-05 Kevin Zheng * sound-src/cfsndserv.c: Drop support for legacy sound systems. 2012-11-30 Karla Stenger * gtk-v2/src/inventory.c: draw_lists() was redrawing the look window every time it was called. This caused a jumping effect when scrolling the look window. Middle clicking could get you to apply the wrong item. It made it barely imposible to look at the next pages. Now it will get redrawn only if items are uptated "below". ============================================================================== Changes for 1.70.0 ============================================================================== Apply patch #3428070: Autoreconf Warnings, by Steven Johnson. Nicolas Weeger 2011-10-27 Fix metaserver not correctly displaying everything. Maurice Massar 2011-09-10 Add timestamping option. Nicolas Weeger 2011-06-06 Add account password change logic and dialogs. Nicolas Weeger 2011-05-23 ============================================================================== Changes for 1.60.0 ============================================================================== Minor bugfixes/improvements: common/cconfig.h: Turn off metaserver1 support - will remove code in future, but will see what effect this has. gtk-v2/src/create_char.c: Remove call setting starting map combox box active - this is done elsewhere, and that call generates an error since the widget isn't realized yet, so isn't doing anything in any case. gtk-v2/src/info.c: Handle client generated messages at startup - removes a bunch of errors going to console about invalid type/subtype. gtk-v2/src/gtk2proto.h: Add missing prototypes. gtk-v2/src/main.h: Change default layout to be gtk-v1 MSW 2011-01-23 Fix theme handling so it is properly loaded/processed at client start up. Remove the theme lookup from the init_...() routines and load the theme after all the initialization routines are done. MSW 2011-01-11 common/client.h: Update race & class structures to hold choice information from server. common/commands.c: Add handling of choice information from server. gtk-v2/src/create_char.c: Add handling of choice option lists. gtk-v2/glade/dialogs.glade - add labels and combo boxes for the choice options. MSW 2010-11-14 Fix client crash on empty magic map. This fixes bug #3098933: invoking magic mapping crashes client. Fix building client with build directory separate from source directory. Arvid Norlander 2010-10-24 Commit client side support for new in client character creation. common/client.h: Add various new globals for map, race, and class info. common/commands.c: Move Race_Class_Info structure to header file, add new global declarations. Add handling of requesting and storing starting map information from server. Handle newcharinfo protocol command. common/external.h: Add new external calls. common/init.c: Add calls to free race and class data. common/proto.h: Add new prototype gtk-v2/glade/dialogs.glade: Update dialogs.glade file with new window for creating character. gtk-v2/src/Makefile.am: Add create_char.c file gtk-v2/src/account.c: Add calls for popups and to show the choose character window. Add handling for new character creation method. gtk-v2/src/create_char.c: New file that handles character creation logic. gtk-v2/src/gtk2proto.h: Update with new functions gtk-v2/src/main.c: update loginmethod to 2, add call to init_create_character_window() gtk-v2/src/main.h: Add global reference to account password gtk-v2/src/stats.c: Make some widgets static to the file. MSW 2010-10-20 Commit basic, functional music support via cfsndserv when the client is built with SDL_mixer sound support. Music support is not presently planned for any of the legacy sound systems: Alsa, Alsa9 (cfsndserv_alsa9), OSS, SGI, and Sun. Neither cfsndserv nor cfsndserv_alsa9 yet support playing sound effects. NOTE: `/configure --enable-sdl_mixer` is required to enable building with the SDL_mixer library since the present default is to not use it (but the default will change shortly as music is now functional, and since all other sound support is still broken for all of the sound systems (including SDL_mixer). NOTE: cfsndserv looks for .ogg or .wav files based on whether the OS is WIN32 or not. The sound files are expected to be in either ${HOME}/sound.cache/ or CF_DATADIR/sounds/. No provision exists yet for sound file installation. Kevin Bulgrien 2010-10-13 Fix some bugs found by static analysis (dead assignment, NULL dereference) using clang-analyzer. Arvid Norlander 2010-10-10 Fix a number of serious compiler warnings (passing pointer to integer of different size, discarding const qualifiers). Arvid Norlander 2010-10-09 gtk-v2/src/sound.c: Converted the Sound2Cmd() and play_sound() functions to correspond with the sound2 protocol. Neither the client nor the server support the legacy sound protocol. Sound has been broken in this client ever since the legacy protocol was removed. This change is made in preparation for a cfsndserv re-write that is necessary to support sounds. Added a MusicCmd() function to accept music commands from the server and to pass them on to cfsndserv. Kevin Bulgrien 2010-10-06 Fix out of tree build. common/Makefile.am called some scripts that were not properly handling the case of source directory and build directory differing. Arvid Norlander 2010-10-06 Add 'containers' pickup menu item. Nicolas Weeger 2010-10-02 configure.ac - Back out the 2.18.0 dependency by converting the dependent functions to code that is compatible with older GTK. This was positively tested on both 2.20 and 2.14. On both systems the spell dialog functions as intended... resizing the description column and reflowing the text into it. Kevin Bulgrien 2010-09-14 configure.ac: - Use the gtk-2.0.m4 macro to test for a usable version of GTK+ 2.0. mmetson found that build fails on Fedora Core 11. It turns out the spells dialog uses two functions first provided by GTK+ 2.18.0 in the code that wraps the description and auto-grows/shrinks the column when the player resizes the dialog. It is known that one of the calls is pretty easy to rewrite for build with pre-2.18.0, but converting the other call has not been reviewed. Until further notice, GTK-V2 now requires GTK+ 2.18.0 or newer. Kevin Bulgrien 2010-09-13 gtk-v2/src/spells.c: The spells dialog description text now dynamically alters line wrap width and table row heights when the dialog is re-sized by the user. Kevin Bulgrien 2010-08-25 gtk-v2/src/spells.c: 1) The spells dialog now defaults to wrap the description at 300 pixels or so as before, but dynamically re-calculates the wrap width based on the dialog width and the width of the other columns. Presently the code does not reclaim extra vertical height when the dialog is widened, so the dynamic wrap is a bit pointless except for shrinking the dialog down. More work is needed to get the description field to shrink vertically. 2) Three of the columns now have their values centered under the column title to try to improve aesthetics. 3) The SP/Mana column title is renamed "Cast/Cost" as SP/Mana was redundant and Grace was unmentioned. This new title also goes along with Spellmon 2 changes in the pipeline that support setting ingredients as additional casting costs. Ingredient data is expected to merge with the mana/grace data in this dialog, and go in the same column as mana/grace cost. Kevin Bulgrien 2010-08-24 gtk-v2/src/spells.c: Adjust the spell dialog to align all data in the top right corner, and to aauto-wrap the description (at a fixed width). Though a dynamic wrap width would be ideal, this at least returns the dialog to a manageable width after the spell descriptions were purged of line breaks. Even with a fixed wrap width, the dialog is improved by the alignment change. Previously the alignment was in the middle, which put the spell name and data below the first line of the description. Kevin Bulgrien 2010-08-22 gtk-v2/src/account.c: Fix client malfunction on [X] closing of account system dialogs. Though the dialogs have the Deletable property set to No, some window managers do not honor this setting, and put the [X] close icon on the window frame. Added new on_window_delete_event() callback and connected it to all of the account system dialogs so their delete_events are trapped and ignored. The dialogs now only dismiss in the manner the designer intended. Kevin Bulgrien 2010-08-19 gtk-v2/src: about.c, config.c, info.c, keys.c, skills.c, spells.c: Fix segfault and/or client malfunction when [X] closing dialogs on window managers that do not honor setting their GTK deletable property to No. Kevin Bulgrien 2010-08-18 gtk-v2/glade/*.glade: Change design up to support GTK 2.16 and add orientation properties so the files load up and render properly in Glade-3 ver 3.6.7. Fix some more widget names to remove trailing whitespace. Set the login dialog deleteable property to false so window (some) window managers do not show the [X] close icon. The client can't handle the dialog being closed. This is a partial fix only. Some window managers (or whatever) do not honor the GTK property. Clean up a widget name in the config dialog. Kevin Bulgrien 2010-08-16/17 gtk-v2/glade/dialogs.glade: Fix for bug 3020531 - The Create Character button does nothing. Trailing space in widget name resulted in code not finding the widget and attaching callback to it. MSW 2010-07-12 Remove disabled GTK and X11 clients. Nicolas Weeger 2010-06-19 gtk-v2/win32/gtkclient.nsi: Include theme files in the package script, these don't seem to actually work under a windows build yet though. Brendan Lally 2010-05-21 gtk-v2/win32/gdefaults2: Use a better default value for map height on win32 Brendan Lally 2010-05-20 gtk-v2/win32: remove old-style icon and a compiled windows package I'd accidentally included. Brendan Lally 2010-05-20 gtk-v2/win32/gtkclient.nsi: Merge some changes to the nsi file from the one from the 1.12 branch Brendan Lally 2010-05-20 Win32Readme.txt, gtk-v2/win32/Running.txt: Merge the contents of win32Readme into the Running.txt file. Brendan Lally 2010-05-20 common/client-types.h: Define sleep in a way that can be compilied for windows. Brendan Lally 2010-05-20 common/client.h: Use a more explicit type in a struct definition (doesn't compile on windows otherwise) Brendan Lally 2010-05-20 gtk-v2/win32: Remove .gladep files from the win32 nsi file, these are not needed by an end-user. Brendan Lally 2010-05-20 gtk-v2/win32: Add some support files for building on win32 Brendan Lally 2010-05-19 common/commands.c: Add code to process & store race_info and class_info data. Still TODO is actually write code that will use this information (new character creator) MSW 2010-05-17 common/client.c: Fix connection logic which failed if system was using ipv6 + ipv4 (and trying ipv6 first) - code was not properly re-setting variables and trying the next protocol in the list. Also clean up some formatting. MSW 2010-05-15 GTK-V2 client now converts paths to WIN32 format as needed on such platforms. This should fix Bug ID: 2933761 and 2913885. Kevin Bulgrien 2010-05-06 The GTK-V2 client now updates the player's ~/.crossfire/servers.cache file whenever a successful server connection is established. Kevin Bulgrien 2010-04-29 Fixed a logic bug in the loader that reads player .crossfire/servers.cache files. The loader wrongly ignored the last valid entry in a cache when it contained an odd number of lines. I.e. if the servers.cache file had only one valid two-line entry, and an extra blank line, the loader ignored the the valid entry and it would not show up in the client. With this change, it does show up. Kevin Bulgrien 2010-04-28 In the case where HAVE_GETADDRINFO is available (not WIN32), a timeout is now implemented when establishing a connection with a server. The timeout is presently hard-coded at 30 seconds. Prior to this, if a connection attempt failed, the client was observed to lock up hard for three minutes. Half a minute is still pretty harsh, but a DNS lookup failure can take 30 seconds, so it may be wiser to wait at least as long before bailing out on the attempt. Kevin Bulgrien 2010-04-28 ============================================================================== Changes for 1.50.0 ============================================================================== common/client.c: Send server deprecated 'newmpcmd 1' setup option - this lets the client work properly on old servers. MSW 2010-04-25 Add missing code for account login to display character icons (note server code won't be checked in until after 1.50 release). Add missing function declarations to external.h to remove compiler warnings. Update common/shared to latest version. common/commands.c: Add support for new attribute. common/external.h: Add missing declarations. gtk-v2/src/account.c: Update update_character_choose() to display icon. MSW 2010-04-24 Remove the Skills/Experience tab from the core stats notebook in gtk-v2.glade as the skills window is better to use. Tested at 1400x1050, 640x480. At 640x480, the inventory/message panel is all the way to the left, but the hpane grab bar is visible. At default client size with no gdefaults2 or gtk-v2.pos, the map is to small to work properly, but, if the corestats are pushed down or hidden at the bottom of the screen it is playable. Kevin Bulgrien 2010-04-23 common/metaserver.c: Update the standalone metaserver code so that it works properly, merge the standalone versions of for both metaservers, and add a some more explanatory text to stdout. Brendan Lally 2010-04-24 gtk-v2/src/main.c, common/client.h: Put the name of the glade layout file that is being used in the version string that the client sends to the server. Brendan Lally 2010-04-24 - Remove the disfunctional scrollbars from around the map in most gtk-v2 .glade files. The layout acts better under different circumstances when they aren't there. After all these years they've never been used, so no point in keeping them around as they just take up space. Kevin Bulgrien 2010-04-23 gtk-v2/src/config.c Extend the client theme handling by adding support for player-accessible style file support. load_theme() is modified to always look in the player ${HOME}/.crossfire folder for a gtkrc file even when the client theme is None. This file can serve as a player's private theme file, or could be used just to tweak certain aspects of the client in the same way any other .gtkrc file would. After looking for the gtkrc file, load_theme() also now looks for a .gtkrc file. I.e. If sixforty.glade is in use, a corresponding ${HOME}/sixforty.gtkrc is processed to make it possible to create layout-specific adjustments. Both files have the same capabilities as a client theme file, and, in cases where a player might not have write access to the client theme folder, this modification allows the player to use themes by putting them in the .crossfire folder, albeit under fixed names. This also sets up a mechanism by which the client could one day actually actively maintain (write/update) per-user GTK rc files, but the current goal is primarily to make it easier to customize the client's presentation without having to put a bunch of highly customized files in the distribution. An in-client-selected theme is loaded last, so as to have a higher priority than either the gtkrc or layout-specific rc files. Kevin Bulgrien 2010-04-22 gtk-v2/glade/vi-redux.glade gtk-v2/glade/un-deux.glade gtk-v2/glade/AUTHORS - Remove the skills/experience table from these layout as a result of the new skills window. A significant design point for both of these layouts was to try to remove the vertical space constraints that the skills & experience information placed on the layout when it was used on smaller displays. - Update the AUTHORS notes for both of these layouts. Kevin Bulgrien 2010-04-19 gtk-v2/glade/chthonic.glade gtk-v2/glade/AUTHORS - Remove the skills/experience table from this layout as a result of the new skills window. At least one user desires this change also. - Give meaningful names to various widgets that had generic names. - Add a note to the AUTHORS file that notes a minor save/restore issue with the protections/core statistics notebook area in the lower right corner. It seems as though nesting hpaned or vpaned within each other may be part of why some layouts have restore issues that need to be dealt with. Kevin Bulgrien 2010-04-18 gtk-v2/glade/sixforty.glade - Fix issue with spinbutton_count to avoid run-time message regarding non-zero page size. - Remove the table_skills_exp and enclosing structures now that the skills window is available. gtk-v2/glade/AUTHORS - Add note that sixforty.glade has save/restore window position issues at this time. This issue has been present prior to this, so until it is fixed, just document it as a known issue so it doesn't get forgotten (again). Also do not mention a map dimension less than allowed (8 vs. minimum 11), and add mention of use of map and icon scale to improve usability. Kevin Bulgrien 2010-04-18 gtk-v2/glade/AUTHORS Update the description of oroboros.glade. gtk-v2/glade/oroboros.glade Removed the skills and experience table per creation of the new skills window. This in turn allowed the four tab notebook in the top right to change to a 2 tab notebook to improve accessibility of vital statistics. This redesign also seems to improve the sizability of the client, possibly making it easier to shrink below the default 1024x768 dimensions and opening the door to improvements in other layouts. gtk-v2/glade/dialogs.glade A complete rework of the client configuration dialog to make it take up less vertical space. Netbook users with a screen height of 600 pixels could not access all items in the dialog. The dialog was also pretty ugly and the controls were not organized as well as they could be. The overall design of the dialog now matches the design principles used for the account dialogs. Kevin Bulgrien 2010-04-17 gtk-v2/src/skills.c Fix broken build (perhaps only on older gtk/libglade versions?). Replaced gtk_widget_get_visible() with GTK_WIDGET_VISIBLE(). gtk-v2/src/stats.c Allow the table_skills_exp to be missing from a main window .glade layout without generating stderr spew like (crossfire-client-gtk2:*): Gtk-CRITICAL **: gtk_label_set_text: assertion `GTK_IS_LABEL (label)' failed. The new skills window means this table is optional, so there is no point to make noise or do extra work if it is absent from the window definition. Kevin Bulgrien 2010-04-17 gtk-v2/src/Makefile.am Yet another attempt to fix builds after disable of x11 and gtk-v1 clients. configure.ac Second attempt to fix builds after disable of x11 and gtk-v1 clients. crossfire-client.spec First attempt at disabling x11 and gtk-v1 clients. Kevin Bulgrien 2010-04-17 gtk-v2/src/stats.c, gtk-v2/src/skills.c If the player has left the skill window open whilst playing, update the exp/level values. Brendan Lally 2010-04-17 gtk-v2/glade/dialogs.glade Dress up the dialogs related to the account code. A few items are moved to make better use of space, but this mostly adds containers, attributes, padding, etc. that improves the dialog aesthetics. Orientation properties are removed to reduce libglade spew when running on older versions. They aren't needed anyway. The other major change is that now all widgets have logical names. Kevin Bulgrien 2010-04-15 common/client.c: File that was missed in the previous commit Brendan Lally 2010-04-15 Add a skill window for the gtk-v2 client gtk-v2/src/skills.c: file added gtk-v2/src/stats.c, gtk-v2/src/gtk2proto.h gtk-v2/src/Makefile.am gtk-v2/src/menubar.c - add menu entry callback common/client.h gtk-v2/glade/dialogs.glade - new window gtk-v2/glade/*.glade - update layouts to include new menu entry Brendan Lally 2010-04-15 Fix for bug 1845694 - improper inventory/map redraws in cache mode. gtk-v2/src/image.c: Add a variable to track if we have gotten new images. gtk-v2/src/image.h: Add declaration for above variable. gtk-v2/src/main.c: If we have new images, force full map and inventory redraws in main loop. MSW 2010-04-11 gtk-v2/src/account.c: Clear new account names/status when activating window. Otherwise, odd to have info filled in from account created on previous server. MSW 2010-04-11 common/client.c: Mostly whitespace changes. Make minor improvment to -download_all_faces to request 1 set more than being worked on. common/image.c: Whitespace change - fix formatting. common/newsocket.c: Whitespace change - fix formatting. gtk-v2/src/image.c: Fix for bug 2938906 - don't free pixmap data when using cache mode. gtk-v2/src/info.c: Remove useless message about not fine (sic) color. MSW 2010-04-11 gtk-v2/src/info.c: Fix problem with crashes on some systems - initialization was outside of for loop which set the variable. Should fix bug 2984398. MSW 2010-04-09 Add error message and quit client if user has out of date dialog.glade file installed. Make error_dialog non static so account.c can use this, add check in account.c to see if we found required window, and change order if initialization of account windows to do login window first (as that is where the check is). Files changed: gtk-v2/src/account.c gtk-v2/src/main.c gtk-v2/src/gtk2proto.h MSW 2010-04-09 Add account based support to gtk2 client & common code. Remove support for gtk1 and X11 clients --- configure.ac: Remove check for gtk1, cfgtk2 option, X11 libraries, and checks related to those clients. common/client.c: Add tracking of loginmethod. Update setup to send loginmethod, update dispatch table for new commands. Add close_server_connection() so duplicate code does not need to be repeated. Don't send addme command when using new login method. common/client.h: Add globals for motd, news, rules, loginmethods, INFO_... types. common/commands.c: Add processing of requestinfo for motd, rules, news. Add handling of loginmethod setup. Add call to hde_all_login_windows() when play starts. Add FailureCmd(), AccountPlayersCmd() to handle protocol commands. common/init.c: Free motd/news/rules data when changing servers. common/metaserver.c: Move meta_sort() to this file, don't make it static - removes compiler warnings. common/metaserver.h: Remove static declaration of meta_sort, and function prototype for it. common/p_cmd.c: Update do_disconnect() to use close_server_connection() common/proto.h: Updated with new functions. gtk-v2/glade/dialogs.glade: Add new windows for account login code. gtk-v2/src/Makefile.am: Add account.c file. gtk-v2/src/gtk2proto.h: Update with new functions. gtk-v2/src/account.c: New file - does account logic. gtk-v2/src/info.c: Change order of includes. Move some declarations from this file to info.h. Generalize some of the handling so other functions can use textbuffer but take advantage of the markup processing provided in this file gtk-v2/src/info.h: New file - declarations from info.c moved here. gtk-v2/src/keys.c: Change order if include of main.h. Update to use close_server_connection() gtk-v2/src/main.c: Change order of includes. Add sample use of custom glib log handler. Update to try and use loginmethod 1 gtk-v2/src/main.h: Add extern for csocket_fd so a bunch of files don't have to declare it itself. gtk-v2/src/map.c: Change ordering of includes. gtk-v2/src/menubar.c: Update to sue close_server_connection() gtk-v2/src/metaserver.c: change order of includes. Call hide_all_login_windows() when bringing up metaserver window. gtk-v2/src/opengl.c: Change order of includes. gtk-v2/src/pickup.c: Change order of includes. gtk-v2/src/spells.c: Change order of include of gtk2proto.h ---- MSW 2010-04-08 gtk-v2/glade/dialogs.glade - Convert tooltip_text fields to tooltip fields as mwedel reports that newer versions of glade3 have issues with it (though the version I have does not). - Remove has_tooltip settings not needed by the tooltip fields. - Make sure all the tooltips have a Translatable property. Kevin Bulgrien 2010-04-04 common/commands.c common/client.c - Add debugged trunk server code for spellmon 2 request to handle the extended data in AddspellCmd(). The extended information is currently not exposed to the user interface, but this commit makes it available. - The original idea to look at data on the fly instead of tracking spellmon command response did not work out. It turns out to be very easy to track server response anyway, so there is not much point in trying to figure things out dynamically. - These changes have been tested on old and new servers - including logging in and out of each on the same client session. The data in the Spell struct has been confirmed to hold data (by testing with spells found in the test/spell_requirements map). - LOG message for spellmon FALSE is changed from WARNING to INFO. It's not clear that a server's failure to support spellmon is really that bad. It mostly seems to mean that spell information dialog will not be populated. Also with the addition of spellmon 2, it is normal for older servers to not support it, so that does not seem to warrant the error being a warning anymore. Kevin Bulgrien 2010-04-03 gtk-v2/themes/Black gtk-v2/themes/Standard - Fix [ INFO ] (spells.c::spell_get_styles) Unable to find style for spell_normal Kevin Bulgrien 2010-04-02 common/client.h - Reformat of a lot of comments to ~ 80 cols to reduce vertical text spacing. - Fix some spelling/grammar issues in comments, and improve readability in various places. - Fill out the doxygen comments to the Spell structure by adding information found in the server documentation of the protocol. - Add usage and requirements members to the structure that will support the spellmon 2 extended information. - Convert some variable comments to doxygen style. common/client.c - Reformat of a lot of comments to ~ 80 cols to reduce vertical text spacing. - Add a TODO at the spot where spellmon 2 will be requested when the code is ready. common/commands.c - Update SetupCmd() to get ready to handle spellmon 2. Non-functional changes are comment reformatting/rewriting, and addition of spellmon 2 comments. Code change to separate darkness and spellmon done, but presently no actual functional change occurs except there is a minor duplication of an identical LOG() call. - Update AddspellCmd() to get ready to handle spellmon 2. Non-functional changes are comment reformatting/rewriting/addition. Stubs are added to initialize the spellmon 2 data fields in the Spell structure. Kevin Bulgrien 2010-03-30 common - Update the link to the server/trunk/include/shared folder to revision 12770 to pull in a new revision of shared/newclient.h for the purpose of updating the message type/subtype for magic ears and magic mouths. common/msgtypes.h - Regenerate to capture the changes from the updated shared/newclient.h file. gtk-v2/themes/Standard gtk-v2/themes/Black - Rename msg_dialog_magic_mouth to msg_dialog_magic_ear to more accurately identify what is being themed. Magic mouths are signs, not dialogs. It is the magic ears that are dialogs. gtk-v2/src/info.c - Fix msgctrl_defaults[] to list magic ears as a subtype but not magic mouths. Magic mouths are signs, so add that to the sign message descriptive text. This results in a change to the message control dialog. Kevin Bulgrien 2010-03-30 common/command.c - use the map2 type defines in the parsing code Brendan Lally 2010-03-28 common/client.c common/commands.c common/client.h gtk/gx11.c x11/x11.c gtk-v2/sound.c: Remove the use of the setup flag sexp - The server doesn't respond to it any more and the clients don't use it. Brendan Lally 2010-03-18 Protocol cleanup - remove code that supports protocol commands that are out of date. Also change setup to only request current options. MSW 2010-01-18 --- common/client.c: Remove handling of obsolete protocol commands. Clean up setup logic - do it all in one setup command instead of several, don't send options to server which are now standard. common/client.h: remove extern command_inscribe declaration. common/commands.c: Fix up a lot of setup logic - remove fallbacks to protocol commands that predate the setup replacements. Remove handling of settings which are now standard. common/init.c: Remove SendSetFaceMode() common/item.c: Presume all servers support inscribe protocol command. gtk/gx11.c: Presume all servers support inscribe protocol command. gtk/sound.c: remove SoundCmd() gtk/win32/porting.c: Remove SoundCmd() gtk-v2/src/sound.c: Remove SoundCmd() --- gtk-v2/src/info.c: off duplicate supression of command responses by default. Otherwise, things like statistics output ends up in what effectively looks like random order, which isn't good when you have a table. MSW 2009-12-07 macros/ax_pthread.m4: Add a new m4 macro ax_pthread.m4 to (hopefully) better suport detection of pthreads. See: SF tracker ID 2850517 for info: crossfire-client-1.12.0 build failure under Slackware 12.2 - ID: 2850517. Note that ax_thread.m4 is itself licensed under GPLv3. Note a possibility for license confusion, but also note that a review of various projects shows a fairly common precedent of allowing mixed licenses in the m4 macro directory - not all explicitly documenting the fact that different licenses are used. Other projects maintain a file identifying copyright and licensing provisions for various parts of the project. Whereas it is very likely other sources will be modified, it is highly unlikely anyone will expect to modify the .m4 macros in this project. aclocal.m4: Rebuilt file after incorporation of macros/ax_pthread.m4. configure.ac: Replace AC_CHECK_LIB(pthread, pthread_create) method of detecting pthreads with AX_PTHREAD(). Now halt the build if pthreads is not found since presently all clients are required to use metaserver code that uses pthreads. Also modify the configure.ac file to create a configure script that reports if the x11 client is built. There is no reason to avoid this since it reports other clients that are or are not built. The notices at the end of the configure script that say "Will build * renderer" are changed to say "With * renderer" since it looks silly in the case where no clients are built that use the renderers. common/Makefile.am x11/Makefile.am gtk/Makefile.am gtk-v2/src/Makefile.am: - Modify files to use PTHREAD_CFLAGS and PTHREAD_LIBS variables as advised by the new macros/ax_pthread.m4 file. It is advised that both CFLAGS and LIBS variables be used (even though on some systems both are not needed). gtk-v2/glade/un-deux.glade gtk-v2/glade/gtk-v1.glade gtk-v2/glade/v1-redux.glade: This is a resumption of the rework of all .glade layouts to support SVN revision 11699 changes to GTK-V2 client code. HP/SP/Grace/Food/Exp label is split up into four labels each, and the encumbrance data is also split. This change fixes all zeroes reported by knotwork/mark metson. The other layouts in the V1 theme need similar updates. Kevin Bulgrien 2009/09/04 gtk-v2/glade/dialogs.glade: The msgctrl_window now has more padding around the title label to improve aesthetics. The header of the dialog is modified to make room for two new spinbutton controls: msgctrl_spinbutton_count and msgctrl_spinbutton_timer. The spinbuttons allow user access to the output count and time controls previously hardcoded. The controls have tooltips that explain what they are for. Both spinbuttons allow pasting new values, clicking the value up/down, or using PgUp/PgDn to adjust the values in one second increments (8 client ticks). The tooltips for all of the column labels are reworked. Padding is added to numerous widgets to improve the overall appearance of the dialog. Tool tips have been added to all the buttons to give some indication of what they do. gtk-v2/src/info.c: Add output count and timer spinbutton control capability to the new message control dialog by adding a buffer_parameter_t struct typedef and buffer_control initialize structure that contains space for the pointer, state variable, and a default value. The message_control struct is initialized with the #defines that controlled the system previously. Renamed checkbox_t to boolean_widget_t since it doesn't really matter what kind of control is used as we only care whether it supports some kind of on/off capability. msgctrl_init() initializes the state and ptr members of the buffer_control structure. Comments are also added to the function header. update_msgctrl_configuration() now updates the count and timer spinbuttons. save_msgctrl_configuration() has improved comments, and also reads the dialog to assure saving of the currently displayed settings and not just the last applied settings. The save file format is modified to add the spinbutton values. The format of the file is slightly changed to include a record type so that it is easier to validate the file format. load_msgctrl_configuration() is heavily modified to improve the savefile error detection, and to support the new file format. The load process is a bit more strict about the file being in the right format. Saved values are only read from records that are in the correct format. Spinbutton initialization is added to default_msgctrl_configuration(). The comment header for read_msgctrl_configuration() is improved and spinbutton support added. Comment improvements are made for all the button handlers, and now on_msgctrl_button_close_clicked() automatically applies the current values displayed on the control. Kevin Bulgrien 2009/09/03 gtk-v2/src/info.c: Support autoload of Message Control dialog settings by reading the configuration file in msgctrl_init(). gtk-v2/src/main.c: Move msgctrl_init() later in client start up so that auto- load of Message Control dialog settings does not segfault. Kevin Bulgrien 2009/09/02 gtk-v2/src/info.c: The Message Control dialog Load button is now functional. Changed some of the struct definitions to be compatible with use to allocate a buffer in load_msgctrl_configuration() by making them typedefs and then by declaring the msgctrl_widgets[] separately. Remove various instances of end-of-line whitespace. Fix the update_msgctrl_configuration() truncated header comment. save_msgctrl_configuration() client message format changed to report the save file path/filename. Add load_msgctrl_configuration() data parsing using strtok() and only report settings were loaded if at least some valid data records were processed. If any data records are not in the expected format, the file is reported as corrupt. Add comments to local variables in several message control system functions. Kevin Bulgrien 2009/09/01 gtk-v2/src/info.c: The Save and Load buttons are now enabled. The Save button is fully functional, but the Load button only opens the save file and scans it without actually loading the data. The Load data parsing is not yet implemented. For now, it counts the number of non-comment and non-blank lines and outputs a message if it does not match the number of message types the system supports. msgctrl_init() no longer de-sensitizes the Save and Load buttons. save_msgctrl_configuration() now supports saving the message control configuration to ./crossfire/msgs. load_msgctrl_configuration() does read the ./crossfire/msgs file, but does not update the client message control configuration yet (though it does reset the control to match the msgctrl_widgets[] state variables). on_msgctrl_button_load_clicked() now calls the load_msgctrl_configuration() function. Kevin Bulgrien 2009/08/31 gtk-v2/glade/dialogs.glade: Add Defaults and Load buttons to the Message Control dialog. Add some space between the buttons so they are not crammed completely together when the dialog is small. gtk-v2/src/gtk2proto.h: Update for addition of Defaults button support in the Message Control dialog. gtk-v2/src/info.c: Rename msgctrl_data[] to msgctrl_defaults[] to better indicate current function and make all values const. This data is never modified at run-time. In msgctrl_init(), connect the Load and Defaults buttons, but in the case of the Load button, desensitize it until the functionality is present. Replace widget and state variable initialization code with a call to a new default_msgctrl_configuration(). This is now the method by which msgctrl_widgets[] state is initialized, and is the method invoked when the Defaults button is pressed. It invokes another new function, update_msgctrl_configuration(), that loads all msgctrl_widgets[] state variables with values stored in msgctrl_defaults[]. Added also are on_msgctrl_button_load_clicked() and on_msgctrl_button_defaults_clicked(). Kevin Bulgrien 2009/08/30 gtk-v2/src/info.c: Rework the data structures for the Message Control dialog to prepare for supporting return to default. msgctrl_data[] is now only used to hold the defaults. Also convert the buffer empty code to use the flush function to centralize that operation in one place. Kevin Bulgrien 2009/08/30 gtk-v2/glade/oroboros.glade gtk-v2/glade/lobotomy.glade gtk-v2/glade/gtk-v1.glade gtk-v2/glade/meflin.glade gtk-v2/glade/gtk-v2.glade gtk-v2/glade/v1-redux.glade gtk-v2/glade/caelestis.glade gtk-v2/glade/eureka.glade gtk-v2/glade/un-deux.glade gtk-v2/glade/sixforty.glade gtk-v2/glade/chthonic.glade: Link the new Message Control dialog to the Client menu. gtk-v2/src/info.c: Begin referring to the in-client output-count and message routing as the "Message Control System", and add support for in-client, player configuration via a new dialog to replace previously hard-coded settings. Change some previously selected data types to GTK data types to make interfacing with the UI require fewer casts. Instead of continuing to use the info_ prefix for this functionality, start using a msgctrl_ prefix. Added new functions to support the Message Control dialog: msgctrl_init() which does the dialog setup on client start; save_msgctrl_configuration(), and load_msgctrl_configuration() that are presently stubs, but are intended to be used to allow the message control configuration to be saved and restored. read_msgctrl_configuration() obtains the state of the Message Control dialog checkboxes, and dynamically, at run-time, allows the player to reconfigure which message types undergo duplicate suppression, and to which message panels they are routed to. on_msgctrl_button_save_clicked(), on_msgctrl_button_apply_clicked(), and on_msgctrl_button_close_clicked() support the dialog buttons (though presently the save button is disabled as saving and loading is not yet supported). on_msgctrl_activate() displays the new dialog when the Client | Message Control menu option is selected. All data structures and functions are heavily commented in the doxygen style. gtk-v2/src/main.c: Added a call to msgctrl_init() during client startup to construct the checkbox table and preset all the checkboxes to match the hardcoded defaults in info.c. gtk-v2/src/menubar.c: Link the new Message Control dialog into the client menu. gtk-v2/src/gtk2proto.h: Update to include prototypes for the new Message Control system in-client configuration support. gtk-v2/glade/dialog.glade: Dress up the about, metaserver, spell, and keybinding dialogs by adding a couple of horizontal separator bars and by replacing an HBoxes with HButtonBoxes. Adjust padding here and there as well (also on the config dialog). Rename widget names that were "typenumber" to "dialog_type_description". Add a new Message Control dialog that is for configuring the client-side output-count and message routing. Kevin Bulgrien 2009/08/29 gtk-v2/src/info.c: Set up an info_control[] array of structs, one element for each message MSG_TYPE_* in common/shared/newclient.h. This array contains enable/disable flags that determine whether or not a message shows up in any of the message panels (and it is possible to route message types to both panels). The array also determines which of the message types are processed for duplicate message reduction. There are still a few conditions that override the info_control[] settings. Presently the array is filled with hard-coded defaults, but they will ultimately become defaults that can be over-ridden by an in-client control panel and, eventually, by settings saved to a configuration file. message_callback() and draw_ext_info() are now modified to use info_control[] instead of the hard-coded settings they used previously. Kevin Bulgrien 2009/08/25 Adjust the client-side output-count implementation to always output a message the first time it occurs when it first enters the buffering system. After the initial display, the output-count and sync settings determine display time. With the new scheme, inactive buffers are also aged and discarded by age so that the content can be re-used if the message recurs before it is pushed out of the buffer. The "initial" display of a message is not done if the message buffer is re-activated after having been inactivated by output-count or sync. Meflin also pointed out the trailing " (Nx)" differed from the original server implementation, so now the count is prefixed on the message as "N times ". This changed the size of the count buffer, and affected the output buffering method - making it more logical to avoid allocating the count buffer in each message buffer, but rather only one time in the info_buffer_flush() function. This implementation is a bit heavier since buffers are now processed more when they are inactive, but it does get unique messages to the player more quickly even if they happen to pass through the duplicate suppression system. gtk-v2/src/info.c Kevin Bulgrien 2009/08/23 Implement a client-side replacement for the recently removed output-count and output-sync commands. The client implementation matches the basic operation of the server feature. Output-count determines the highest number of messages that can to coalesce into one. The output-sync determines the maximum amount of time a message stays in a buffer until it is displayed. The present code has output-count hardcoded to 16 (info.c: MESSAGE_COUNT_MAX) and output-sync to 16 client ticks, or about 2 seconds (info.c: MESSAGE_AGE_MAX). Messages ARE NOT considered for duplicate suppression if: define MESSAGE_COUNT_MAX <= 1; the message is sourced from client code; the hinted color of the message is NDI_UNIQUE; the message length is greater than 56 characters. Messages are displayed if either output-count or output-sync limits are reached. Either or both client command configuration and GUI configuration is planned. Probably GUI configuration will be implemented with an ability to configure message routing as well. gtk-v2/src/gtk2proto.h: Re-ran `make proto` to update prototypes. gtk-v2/src/main.c: Addied a call to the output-count/sync maintenance function info_buffer_tick() from client_tick(). gtk-v2/src/info.c: All output count/sync functionality is implemented in this file. Presently the feature is configured by adjusting defines in this file. The new defines, variables, and code are fully commented in the doxygen style. The system is initialized by calling info_buffer_init() from info_init(). To further support the system, info_buffer_flush() ejects messages from the buffers to the client display, and info_buffer_tick() both ages the buffers and evaluates them to determine if they need to be flushed. The old message_callback() is renamed draw_ext_info() and all messages still pass through it for routing and styling. The pre-existing draw_ext_info() function is removed. A replacement message_callback() is the front-end for the buffering system, and all messages except client-sourced messages pass through it. Kevin Bulgrien 2009/08/17 gtk-v2/glade/*.glade: Finish an incomplete rename of ratio_pickup_off1 to ratio_pickup_off in the pickup menu. Kevin Bulgrien 2009/08/09 common/metaserver.c: Fix bug 2806906- gcfclient hangs on exit when offline. Limit number of attempts to get metaserver2 data - was trying perpetually before. MSW 2009-07-27 gtk-v2/src/keys.c: Always extract spinbutton count and send it to server when doing commands - fixes 'invoke dimension door' spacing issue. MSW 2009-07-13 gtk-v2/glade/sixforty.glade: This started out as a rework for the new stat.c and pickup.c code, but became a general improvement effort. The layout has some issues in that saving windows position seems unreliable - possibly due to a need for constraining containers (viewport?) in the vpaned widgets. To debug, experimentation with scrolled windows can show when widgets might be have a size that subverts sizing. The default layout with no sixforty.pos is sane. The stats panel is changed the most with scroll bars added so the wide stats can be viewed in a small client. Both message panels are not in a notebook anymore to support recent chat/tell/say changes. Kevin Bulgrien 2009/05/25 gtk-v2/glade/lobotomy.glade gtk-v2/glade/oroboros.glade gtk-v2/glade/gtk-v1.glade gtk-v2/glade/gtk-v2.glade gtk-v2/glade/meflin.glade gtk-v2/glade/v1-redux.glade gtk-v2/glade/eureka.glade gtk-v2/glade/caelestis.glade gtk-v2/glade/un-deux.glade gtk-v2/glade/sixforty.glade gtk-v2/glade/chthonic.glade: Fix an omitted change in the menubar edits made prior to support changes in pickup.c. Kevin Bulgrien 2009/05/24 gtk-v2/glade/lobotomy.glade: A significant dress-up of the layout and general reduction of various container widgets that are not necessary for one reason or another. An issue with chat panels was discovered and fixed. Under some circumstances, the vertical scroll bar would disappear due to the horizontal scroll bar policy being set to never. The policy is now set to automatic to prevent the issue. Unused menu bar widgets are removed, and the menu widgets names are made more consistent. This drove widget name changes in menubar.c and pickup.c. gtk-v2/src/pickup.c gtk-v2/src/menubar.c: Menubar widgets are renamed to remove numeric suffixes and improve uniformity. gtk-v2/glade/oroboros.glade gtk-v2/glade/gtk-v1.glade gtk-v2/glade/meflin.glade gtk-v2/glade/gtk-v2.glade gtk-v2/glade/v1-redux.glade gtk-v2/glade/caelestis.glade gtk-v2/glade/eureka.glade gtk-v2/glade/un-deux.glade gtk-v2/glade/sixforty.glade gtk-v2/glade/chthonic.glade: All of the .glade files have the same menubar as made for lobotomy.glade to correspond with the above changes in menubar.c and pickup.c Kevin Bulgrien 2009/05/23 gtk-v2/glade/oroboros.glade: This update supports recent client code changes. The layout is basically the same as before the the update but viewports are added in a number of places to improve the aesthetics of the UI. The stat bar numeric data has been moved to the left of the bars. Kevin Bulgrien 2009/05/23 gtk-v2/glade/eureka.glade: This update supports recent client code changes. The stat bar display is moderately reorganized to allow very long experience data to be covered by the neighboring hpane panel as needed. The critical and normal message panels have swapped positions due to recent use of the critical panel for chat, tell, and say messages (placed nearer the command entry control). gtk-v2/glade/lobotomy.glade: This update includes both stylistic changes and updates to support recent client code changes. Though the lobotomy layout was unique in certain respects, the notorious skills and stats carry-overs from the original gtk-v2 layout were ugly. This commit introduces statistic panels that are completely unique. The skills and protections areas still take up the bulk of the bottom row, but they are designed to better avoid the overlap that so easily occurs in gtk-v2. A stats cluster in the bottom right corner explores a new method of organizing all character stats and any related stat bars in a small area, while tending to avoid the width problems that can so easily crop up with the stat bar numeric data. Another notable change is that all notebooks except the map/magic map notebook are gone. The critical and normal message panels have swapped positions to put chat, tell, and say messages closer to the command entry box. gtk-v2/glade/AUTHORS: The lobotomy.glade section has been updated to match the changes made to the layout. gtk-v2/glade/caelestis.glade gtk-v2/glade/chthonic.glade: Glade3 Designer apparently does not work well with single column tables, so a vbox was substituted to avoid misbehavior in the designer. The presentation to the player is basically unchanged except the critical and normal message panels have swapped positions to put chat, tell, and say messages closer to the command entry box. Kevin Bulgrien 2009/05/22 gtk-v2/glade/caelestis.glade gtk-v2/glade/chthonic.glade gtk-v2/glade/gtk-v2.glade: This is the beginning of the rework of all .glade layouts to support SVN revision 11699 changes to GTK-V2 client code. All of the files are changed using Glade3 Designer, so are about half their former size. The files target Glade 2.12 and do not contain deprecations or version conflicts. The HP/SP/Grace/Food/Exp label is split up into four labels each, and the encumbrance data is also split. Though gtk-v2.glade has been changed subtly, the data is still in the same relative location as the original layout. The caelestis and chthonic relocate stat numeric data to the right side of the progress bars to achieve the same improvements originally developed for meflin.glade. All layouts have had some viewports added in various places to give the UI an overall better, more polished appearance. Kevin Bulgrien 2009/05/21 The following commit introduces a code incompatibility with existing .glade layouts. All layouts must be updated to match this code to retain encumbrance display and the numerical data next to the stat progressbar widgets. This change is made because it allows much greater flexibility in the UI layout. The motive was to reduce bad UI behavior when a character had very large amounts of XP, but a side-effect is that layout density can be improved for those wanting a small UI footprint. The existing .glade layouts may still be used, but some numeric data will not be available until the layout is updated. meflin.glade rework sparked the idea for this change, and was used to test the code, so is hereby committed. The other layouts will be changed in relatively short order. gtk-v2/src/stats.c: The stat_label pointer was split into two pointers called stat_current and stat_max. The widget that stat_label pointed to used to be set with a programmatically defined stat name, current value/max value all as a single string. With the Exp: data in particular, this resulted in a very wide string that tended be be quite problematic. Not only that, but it forced client layouts to use a hardcoded name for stats instead of allowing the layout to define (or omit) the name. In the .glade file, the change corresponds with the splitting of the label_stats_* widgets each into four separate widget sets wth the names: label_stat_name_*, label_stat_current_*, label_stat_ratio_*, and label_stat_max_*. label_stat_name_* is no longer programmatically set by the client code. The current/max data formerly in the split widget is now divided between the other newly created widgets. The *_ratio_* widgets are generally defined in the .glade file as a "/", and the client code does not modify it. Various block comments were reformatted to wider margins to reduce vertical height of the comments. One spelling error was fixed in a code comment. gtk-v2/src/inventory.c: The changes closely match the changes described for stats.c except that they change the behavior of the weight or encumbrance data shown in the client. The pointer weight_label is split into two pointers: encumbrance_current and encumbrance_max. This makes it possible to split the two numbers formerly displayed as current/max in a single string. The widget name label_inv_weight was replaced by widgets with the the names label_stat_encumbrance_current, label_stat_ratio_encumbrance, and label_stat_encumbrance_max. The stat name label was not programmatically set for encumbrance, but was renamed to label_stat_encumbrance_name to match the stats.c changes. Block comments were reformatted to wider margins to decrease their vertical height. gtk-v2/glade/meflin.glade: The stats panel has been reorganized to make use of and test the above changes. The stat labels for the progressbars are still to the left of the progress bar, but the associated numeric ratio is now to the right of the progress bar. This allows the player adjust the hpane to cover extremely long experience/next_level strings to increase the area available for critical messages. The stat columns are moved from the right side of the progress bars to the left side. Fire/Run and the active ranged skill are now shown below the progress bars and separated from them by a blank line (to improve readability). The overall appearance of this layout was also improved by introducing into the design more viewports with borders. Kevin Bulgrien 2009/05/21 gtk-v2/glade/meflin.glade: Swapped position of Messages and Look/Inventory at Meflin's request. The Range: slot in the stats table caused some expanding and contracting of the stats panel when rotating through ranged skills, so it is now assigned a row of its own. After adding this row, the table now has seven rows, so the Str/Dex/Con/Int/Wis/Pow/Cha can now be laid out in a vertical fashion. The addition of a row also leaves a cell above WSp blank, so Run/Fire is moved from the menubar to this cell. The cell where Range: used to be is now blank. Added separators between the menu and the player information items in the menu bar. Now that the look/inventory panel is at the bottom, it makes more sense to put the notebook tabs next to the command input, so the tabs are change to the bottom of the notebook, and to maintain a consistent appearance, the stats/prot/skills notebook also has the tabs moved to the bottom. Kevin Bulgrien 2009/05/17 gtk-v2/glade/meflin.glade: Reworked this layout which was not used (probably because messages were not visible when clicking or examining items with the mouse). The changes from sixforty involve making sure critical messages and regular messages are both visible at the same time. The critical messages are put on the stats pane below the maps. The other big change is to try putting ground view and inventory on their own tabbed notebook with the ground view the default. This layout makes more use of viewports to make the UI look nicer. There are still areas for improvement like the menubar. The command input box seems small too, but its worth getting other feedback before messing around too much more with it. gtk-v2/glade/sixforty.glade gtk-v2/glade/sixforty.gladep: Add a four-quadrant layout that seems workable at a 640x480 screen resolution. It has some innovations for tightening up stats display, and will likely be nice for larger resolutions also. This layout actually appears to be different enough to inspire some ideas on how to make a few code changes to improve the ability to tighten up the displays even more. This layout was developed with glade2, but resaved using glade3 prior to commit. The XML targets GTK+ 2.12 and fully passes glade3s deprecation and version mismatch checks. gtk-v2/glade/Makefile.am: Incorporate the new sixforty.glade into the build. gtk-v2/glade/AUTHORS: Add a descriptive summary of the new sixforty layout. crossfire-client.spec: Add sixforty.glade to the package, and update the internal changelog. gtk-v2/glade/meflin.glade: Open in glade3 and save changes after verifying GTK+ target 2.12 and that deprecation and version mismatch checks pass. Kevin Bulgrien 2009/05/16 gtk-v2/glade/dialogs.glade: Set the About dialog window_position property to center for more logical and natural positioning of an infrequently viewed dialog. The other dialogs seem to try to position themselves in corners of the screen, which makes sense so they do not overlay each other, but it doesn't make a lot of sense for the About dialog, and looks better this way. Kevin Bulgrien 2009/05/15 gto-v2/glade/dialogs.glade: Set the deletable property False on all dialogs to fix Tracker ID: 2784779 GTK-V2 loses dialogs if closed with X control. It looks like glade3 is going to be annoying. The diff is huge, but if you sort the old file and new file, the real difference is only one line of text for each dialog. Kevin Bulgrien 2009/05/14 gtk-v2/glade/dialogs.glade: Open/save using glade3 so that later modifications may be better identified in a diff. Glade3 appears to save widgets in alpha order. Glade3 also seemed to remove quite a bit of content, but so far what I have seen indicates that glade2 to glade3 migration is pretty safe. Kevin Bulgrien 2009/05/14 crossfire-client.spec: Change some of the RPM .spec file BuildRequires to be more flexible after after testing on Mandriva 2009.0 (local machine) and Centos (Invidious). Centos build failed with requires libcurl-devel and libglade2.0-devel but both succeed if the requires are changed to curl-devel and libglade2-devel. These new requires also work on fedora10. Kevin Bulgrien 2009/05/10 common/shared/newclient.h: After coming to the realization that this file is better sourced in the server so that different client codebases could conceptually use different versions of the file depending on their development state, this file is now moved to server/include/shared. common/shared: Removed to allow the server/include/shared directory to be made and external reference here. common: Added an svn:externals property to use server/include/shared revision 11676 to create and populate client/common/shared so that newclient.h is a direct copy of the file maintained in the server area. Kevin Bulgrien 2009/05/09 common/shared/newclient.h: Removed comment that talked about the file being separately controlled in client and server. Add a comment to the #ifdef that switches the content of one typedef depending on where it is compiled. Kevin Bulgrien 2009/05/09 common/newclient.h: Moved to the new common/shared subdirectory because svn externals work on a directories only. It is planned to share this file between the server and client to assure synchronization. common/shared/newclient.h: Moved from common. common/item.c common/msgtypes.pl common/client.h common/newsocket.h common/Makefile.am sound-src/alsa9.c sound-src/cfsndserv.c: changed all #includes to reference newclient.h in its new location (common/shared/newclient.h). common/msgtypes.h: Changes resulting from merge of server newclient.h with the client newclient.h. Kevin Bulgrien 2009/05/08 common/newclient.h: Merge differences from server/trunk/include/newclient.h in preparation for correcting the fact that the two files are separately maintained - allowing divergence in implementation. One apparent required conflict is handled by detecting a define present only in the client. Kevin Bulgrien 2009/05/08 The following commit converts all common code and GTK-V2 draw_info() calls to draw_ext_info() calls so that support for untyped draw_info() messages can be completely removed from GTK-V2. While converting the draw_info() calls, also get rid of the deprecated draw_color_info() use in common so that the clients can have this deprecated function removed. This conversion also requires all clients provide a draw_ext_info() for common code to use. In the X11 and the GTK-V1 client, draw_ext_info() discards the message type information and just uses its existing draw_info() function. To support this change, new message types and subtypes have been added to support client-sourced messages. More than likely the client-side message subtypes could be fine tuned, but GTK-V2 also has changed to allow the draw_info() colors to be used until style data is set up for the client message types. draw_info() is removed from GTK-V2. common/item.c: draw_info() --> draw_ext_info(). common/commands.c: draw_info() --> draw_ext_info(); Remove draw_color_info(). Remove commented code used to develop skills report. common/script.c: draw_info() --> draw_ext_info(). common/client.c: draw_info() --> draw_ext_info(). common/msgtypes.h: Regenerated with `make msgtypes.h`. common/p_cmd.c: draw_info() --> draw_ext_info(). common/image.c: draw_info() --> draw_ext_info(). common/player.c: draw_info() --> draw_ext_info(). common/script_lua.c: draw_info() --> draw_ext_info(). common/metaserver.c: draw_info() --> draw_ext_info(); comment updates. common/external.h: Remove draw_info(); remove draw_color_info(); add draw_ext_info(). common/newclient.h: Add/tweak comments for pre-existing message types. Add a new message type for client-sourced messages along with some subtypes that seemed reasonable when reviewing the kinds of messages the client spawns. x11/x11proto.h: Regenerated with `make proto`. x11/x11.c: Remove draw_color_info(). Add draw_ext_info(). gtk/gtkproto.h: Rebuilt file with `make proto`. gtk/gx11.c: Remove draw_color_info(). Add draw_ext_info(). gtk-v2/src/gtk2proto.h: Regenerated with `make proto`. gtk-v2/src/config.c: draw_info() --> draw_ext_info(). gtk-v2/src/keys.c: draw_info() --> draw_ext_info(). Fix a misspelling in a message. gtk-v2/src/info.c: Fix the message_callback() prototype to match the function declaration and add a draw_ext_info() prototype. Modify message_callback() to honor the orig_color parameter in cases where a style has not been set for a particular message type/subtype so that draw_info() texts converted to draw_ext_info() will not lose their color just because the themes are not updated. To make this work, the message routing code was moved to run earlier. draw_info() is removed from the GTK-V2 client to strongly show that any new client messages need to be typed. This enhances the value and coverage of the theme support in the client. In fact, draw_info() comments hinted that draw_info() has been considered questionable in various ways before this conversion was conceived. Add a draw_ext_info() call that simply uses the message_callback(). Really the message_callback() should probably be renamed draw_ext_info() instead of putting this extra call in. gtk-v2/src/pickup.c: draw_info() --> draw_ext_info(). gtk-v2/src/inventory.c: draw_info() --> draw_ext_info(). Kevin Bulgrien 2009/04/22 gtk-v2/src/info.c: After some play-testing, its kind of wierd for say to go to one window and NPC/Magic Mouth stuff to go to the other, so MSG_TYPE_DIALOG is now also routed to the critical messages pane. Kevin Bulgrien 2009/04/16 gtk-v2/src/info.c: Per mailing list discussion on or about 2008/12/22, route MSG_TYPE_ATTRIBUTE (Changes to attributes: stats, resistances, etc), MSG_TYPE_COMMUNICATION (Communication between players), and MSG_TYPE_VICTIM (Something bad is happening to the player) to the critical messages pane. As stated on the ML, there are other potentially superior solutions to chats tells not getting drowned out by other messages, but this is a very simple one. The critical messages pane gets very little activity, unlike the regular messages pane. Addition of a chat-specific panel, or client-side routing configuration is not considered precluded by this quick fix. Kevin Bulgrien 2009/04/16 Fix typo in scripting protocol: send "watch stats maxsp" rather than "watch stats maxspp". Andreas Kirschbaum 2009-01-19 Send correct coordinates for "request map pos" script command. Do not crash for "request items cont" if there is no opened container. Report weight in grams in "request items" commands. Previously a localized floating point number in kg was passed. Add checks for incorrect parameters to scripttell command. Do not pass the script ID to the script. common/script.c Andreas Kirschbaum 2009-01-18 Various fixes and improvements, mostly related to map handling in gtk2 client. Main change is that the map area can now be resized during play and it will draw things as expected. Note server change is needed for map to not appear jumbled after initial resize. Fix bug 2476715: Image display problem when not sized to a multiple of 32 -- configure.ac: Move evaluation of extra includes and extra linker flags ( --with-..) options before lua/opengl checks - if those libraries are not in usual location, still want to be able to use them. gtk-v2/src/gtk2proto.h: callback for configure event added. gtk-v2/src/map.c: map_init(): Remove explicit call to set map area size. display_mapcell(): Fix drawing of images not a multiple of 32. resize_map_window(): Additional processing after resize event. on_drawingarea_map_configure_event(): New function - gets resize event and makes necessary updates. gtk-v2/glade/gtk-v2.glade: Remove explicit size value from layout. This gives more resize flexibility. MSW 2009-01-04 gtk-v2/src/info.c: Add missing initializer to pane variable. Without it, we are passing in garbage value to functions, which results in crashes. MSW 2008-12-29 make proto in the GTK-V2 source directory yielded an error about a missing about.h file. Additional includes are passed to cproto to remove this error. gtk-v2/src/Makefile.am Kevin Bulgrien 2008-12-21 The GTK-V2 client for some reason saved the window positions file multiple times per use of menubar Client | Save Window Position. Adding a call to g_signal_stop_emission_by_name() in on_save_window_position_activate() puts this silliness to an end. The file is now only saved one time. gtk-v2/src/config.c Kevin Bulgrien 2008-12-21 Remove "(crossfire-client-gtk2:2088): Gtk-WARNING **: GtkSpinButton: setting an adjustment with non-zero page size is deprecated run-time warnings for the GTK-V2 client. gtk-v2/glade/lobotomy.glade gtk-v2/glade/oroboros.glade gtk-v2/glade/gtk-v1.glade gtk-v2/glade/gtk-v2.glade gtk-v2/glade/meflin.glade gtk-v2/glade/v1-redux.glade gtk-v2/glade/eureka.glade gtk-v2/glade/caelestis.glade gtk-v2/glade/dialogs.glade gtk-v2/glade/un-deux.glade gtk-v2/glade/chthonic.glade Kevin Bulgrien 2008-12-20 Complete fixing GTK-V1 issue [ 1876788 ] Doubled characters in GTK clients (unusable). Tested with --enable-cfgtk2 compiled as RPM. gtk/keys.c Kevin Bulgrien 2008-12-16 Misc compilation tweaks, no functional change. common/init.c mapdata.c: remove redundant Win32 macros. common/metaserver.c: add dummy return values to make the compiler happy. Nicolas Weeger 2008-12-14 gtk_signal_emit_stop_by_name() was poorly placed and is moved to a location where it will help fix the [ 1876788 ] Doubled characters in GTK clients (unusable) for the GTK-V1 client. gtk/keys.c Kevin Bulgrien 2008-12-13 Fix for [ 2022488 ] 2.x GTKv1 client built with --enable-cfgtk2 cannot login and for [ 1862055 ] GTKv1 client built with --enable-cfgtk2 cannot login so it is no longer necessary to run the client with Popup Windows. gtk/keys.c Kevin Bulgrien 2008-12-13 Pending fix for [ 1876788 ] Doubled characters in GTK clients (unusable). mwedel noted gtk_signal_emit_stop_by_name() was not used consistently everywhere keypresses were consumed by the client. Patches were written and tested to show that consistent use of gtk_signal_emit_stop_by_name() caused the doubled character problem to disappear. Then a new patch was written to replace redundant call/return pairs with fall-through logic. http://www.gtk.org/api/2.6/gtk/gtk-Signals.html#gtk-signal-emit-stop-by-name also states this is a deprecated function, g_signal_stop_emission_by_name() is now used instead of gtk_signal_emit_stop_by_name(). gtk-v2/src/keys.c Kevin Bulgrien 2008-12-04 To satisfy rpmlint and remove the error "E: no-packager-tag", add the packager tag and define it to a sane default. crossfire-client.spec Kevin Bulgrien 2008-11-28 To satisfy rpmlint and remove the error "E: non-standard-group X11/Games", all package groups are changed from "X11/Games" to "Games/Adventure". Choices offered by rpmlint were "Games/Adventure", "Games/Arcade", "Games/Boards", "Games/Cards", "Games/Other", "Games/Puzzles", "Games/Sports", and "Games/Strategy" crossfire-client.spec Kevin Bulgrien 2008-11-28 Update all client .desktop files so they do not trigger rpmlint messages like ".desktop file is not valid, check with desktop-file-validate": Terminate the Categories key/value with a semicolon; remove the deprecated Encoding key. Unify the Comment for all three clients. Add an appropriate GenericName key. Add [en] localestrings for the Name, GenericName, and Comment keys to help make it more obvious that translations may be placed in this file. Put the keys in order as listed in http://standards.freedesktop.org/desktop-entry-spec These changes are tested with desktop-file-validate. x11/crossfire-client.desktop gtk/crossfire-client.desktop gtk-v2/crossfire-client.desktop Kevin Bulgrien 2008-11-28 Eliminate rpmlint message W: mixed-use-of-spaces-and-tabs (spaces: line 159, tab: line 169) by converting tabs to spaces. No functional change. crossfire-client.spec Kevin Bulgrien 2008-11-28 Remove remaining vestiges of the old gcfclient/gcfclient2 naming convention. This does also slightly change the default gdefaults2 file generated by the client, and removes a blank line from the help output of the gtk-v2 client. INSTALL gtk-v2/src/config.c gtk-v2/src/main.c Kevin Bulgrien 2008-11-26 Win32 updates. common/commands.c: variables declaration at top gtk/sound.c: empty stubs gtk/win32/config.h: vsnprintf exists under another name gtk/win32/GTKClient.dsp: update gtk/win32/GTKClient.dsw: update gtk/win32/gtkclient.nsi: update gtk/win32/Win32Changes.txt: update Nicolas Weeger 2008-08-04 Update crossfire-client.desktop files by using consistent names; making sure all have categories; and adding a new file for the X11 client. x11/crossfire-client.desktop x11/Makefile.am gtk/crossfire-client.desktop gtk-v2/Makefile.am gtk/crossfire-client.desktop Change the default version for the client to 2.0.dev instead of 2.0-dev as the dash is incompatible with modern RPM tools. Dash is reserved for separating things in the RPM file name, and must not be embedded in the version string. Also rework datadir computation, and report where client data files will be placed. Improve reporting of the bindir to be used. configure.ac Fix RPM creation for the client release procedure. Add new .desktop files and package them with the clients rather than in the common package. Change the location for the .desktop files to /usr/share/applications. Update the list of .glade files for the GTK client V2. Correct the RPM build process by adding a _datadir definition, and modify all file specifications accordingly. Fix the build specs so a crossfire-client-x11 package is made. Swap the gtk client build to use GTK V2 by default. Change versions to 2.0.dev instead of 2.0-dev, which is invalid for current versions of rpmbuild. crossfire-client.spec Kevin Bulgrien 2008/07/19 Fix Makefile.am per use of configure.ac vs. configure.in. Makefile.am Fix release procedure support (make dist) for script_lua.h. Fix release procedure support (make dist) for msgtypes.h. common/Makefile.am GTK-v1 client name changes from gcfclient to crossfire-client-gtk. gtk/crossfire-client.desktop gtk/config.c gtk/gx11.c gtk/win32/config.h gtk/crossfire-client-gtk.man Add -popups to the default startup options as a partial workaround for Bug #2022488 2.x GTKv1 client built --enable-cfgtk2 cannot login. gtk/crossfire-client.desktop Spelling, capitalization, and some whitespace modifications. No functional code changes. gtk/gx11.c common/init.c Override common/init.c default for popups for GTKv1 client only as a partial workaround for Bug #2022488 2.x GTKv1 client built --enable-cfgtk2 cannot login. This actually changes the behavior to agree with the man page that states popups on is the default. Naturally this will not work if a player has a ~/.crossfire/gdefaults file with popups off, but this ensures a new player with have a working client with popups on. gtk/gx11.c Kevin Bulgrien 2008-07-19 common/newsocket.c: Improve error message (print out actual error) on failed write. Also, try to write again on errno==EAGAIN - fixes problem for systems that return EAGAIN instead of 0 when a write fails on a non blocking device. MSW 2008-07-07 Allow scripts to retrieve information that was previously unavailable: tag of the player object (used in move commands), title, list of known spells, names of the known skills, and attuned/repelled/denied spell paths. common/script.c Raphael Quinet 2008-06-22 Clean up configure.ac and add a missing test for size_t. configure.ac common/config.h.in Arvid Norlander 2008-06-05 Fix a valgrind error (uninitialised value) in smoothing code. gtk-v2/src/config.c gtk-v2/src/map.c Arvid Norlander 2008-06-03 Fix a valgrind error in the common metaserver code. For some reason sc_version and cs_version fields were not always properly initialized when check_server_version() was called. common/metaserver.c Arvid Norlander 2008-06-03 Add stub support for sound2/music commands, I was unable to make server send the actual commands except "music NONE" (and jxclient that do have sounds don't get these commands either, but decides locally to play some sounds it seems) so was not able to debug it beyond making sure it compiled and ran. When the server actually sends these commands someone need to fill in the implementations and check the parsing code is correct for sound2. gtk/gtkproto.h gtk/sound.c common/commands.c common/client.c common/external.h x11/x11proto.h x11/sound.c gtk-v2/src/gtk2proto.h gtk-v2/src/sound.c Arvid Norlander 2008-06-02 Unbreak LUA check in configure. Also update autogen.sh to mention that autoreconf should be used instead and make the call aclocal in the script correct. autogen.sh configure.ac Arvid Norlander 2008-06-01 Remove acinclude.m4 and add macros/libcurl.m4 (as acinclude.m4 just contained a copy of what should have been in macros/libcurl.m4). aclocal.m4 Added: macros/libcurl.m4 Removed: acinclude.m4 Arvid Norlander 2008-06-01 Normalize the *.xpm and *.xbm files by opening them in gimp and resaving them. Then readd "const" as needed in a text editor. Also had to update some source files because the name of the array for the xpm changed in some cases. pixmaps/applied.xpm pixmaps/magic.xpm pixmaps/unpaid.xpm pixmaps/cursed.xpm pixmaps/lock.xpm pixmaps/bg.xpm pixmaps/skull.xpm pixmaps/unlock.xpm pixmaps/mag.xpm pixmaps/question.xpm pixmaps/clear.xbm pixmaps/hand.xpm pixmaps/damned.xbm pixmaps/sign_east.xpm pixmaps/stipple.111 pixmaps/nonmag.xpm pixmaps/stipple.112 pixmaps/test.xpm pixmaps/locked.xbm pixmaps/dot.xpm pixmaps/close.xbm pixmaps/damned.xpm pixmaps/coin.xpm pixmaps/hand2.xpm pixmaps/applied.xbm pixmaps/locked.xpm pixmaps/crossfiretitle.xpm pixmaps/magic.xbm pixmaps/sign_west.xpm pixmaps/unpaid.xbm pixmaps/question.111 pixmaps/close.xpm pixmaps/sign_flat.xpm pixmaps/cursed.xbm pixmaps/all.xpm gtk/gx11.c x11/clientbmap.h gtk-v2/src/about.c gtk-v2/src/map.c gtk-v2/src/image.c Arvid Norlander 2008-06-01 Run protoize on code to add missing void in prototypes. Run the png_compress script from arch on some *.png files in the tree to reduce their size. pixmaps/48x48.png pixmaps/32x32.png pixmaps/16x16.png gtk/config.c gtk/keys.c gtk/map.c gtk/gx11.c gtk/image.c gtk/inventory.c common/item.c common/init.c common/mapdata.c common/image.c common/player.c common/metaserver.c x11/xutil.c x11/x11.c gtk-v2/src/stats.c gtk-v2/src/spells.c gtk-v2/src/config.c gtk-v2/src/keys.c gtk-v2/src/map.c gtk-v2/src/metaserver.c gtk-v2/src/image.c gtk-v2/src/opengl.c gtk-v2/src/main.c gtk-v2/src/info.c gtk-v2/src/inventory.c Arvid Norlander 2008-06-01 Some changes to use snprintf instead of sprintf. gtk-v2/src/stats.c gtk-v2/src/spells.c gtk-v2/src/config.c gtk-v2/src/keys.c gtk-v2/src/sdl.c gtk-v2/src/sound.c gtk-v2/src/info.c gtk-v2/src/pickup.c gtk-v2/src/inventory.c Arvid Norlander 2008-06-01 Set svn:eol-style to native on *.c and *.h files that were missing it. common/msgtypes.h common/script_lua.c common/script_lua.h common/version.h Arvid Norlander 2008-06-01 Add some missing "extern" keywords that caused warnings. Remove some extern variable definitions in source file that were already found in headers. gtk/map.c gtk/image.c common/client.c common/client.h x11/xutil.c gtk-v2/src/image.c gtk-v2/src/main.c gtk-v2/src/main.h Arvid Norlander 2008-06-01 Run make proto in subdirs. Make sure make doesn't error out on some subdirs when running make proto in top directory. pixmaps/Makefile.am gtk/gtkproto.h help/Makefile.am utils/Makefile.am x11/x11proto.h gtk-v2/src/gtk2proto.h Arvid Norlander 2008-06-01 Use the -combine option of gcc to find code (mostly extern inside source instead of headers), where the definitions didn't agree with each other. Fix most of them. One (hard to fix) is left, I will look at it later. Also use cproto in common/. Two sprintf changed to snprintf as well. gtk/keys.c gtk/gx11.c common/proto.h x11/x11proto.h x11/png.c x11/xutil.c gtk-v2/src/gtk2proto.h gtk-v2/src/keys.c gtk-v2/src/info.c gtk-v2/src/inventory.c Arvid Norlander 2008-06-01 Some changes to use snprintf instead of sprintf. common/item.c common/commands.c common/script.c common/client.c common/image.c common/p_cmd.c common/player.c common/script_lua.c common/metaserver.c common/misc.c Arvid Norlander 2008-06-01 Run a script to clean up trailing whitespaces. In this list below "ChangeLog" is listed due to script cleaning up some whitespaces. gtk/gx11.c ChangeLog help/about.h help/shelp.h common/item-types.h common/mapdata.c common/metaserver.c gtk-v2/src/stats.c gtk-v2/src/spells.c gtk-v2/src/config.c gtk-v2/src/about.c gtk-v2/src/keys.c gtk-v2/src/map.c gtk-v2/src/metaserver.c gtk-v2/src/magicmap.c gtk-v2/src/image.c gtk-v2/src/png.c gtk-v2/src/opengl.c gtk-v2/src/main.c gtk-v2/src/sound.c gtk-v2/src/main.h gtk-v2/src/menubar.c gtk-v2/src/info.c gtk-v2/src/pickup.c gtk-v2/src/inventory.c gtk-v2/glade/README Arvid Norlander 2008-06-01 Reorder some structs to waste less memory, also cosmetic changes to struct definitions. common/client.h gtk-v2/src/image.h Arvid Norlander 2008-06-01 More changes of char* to const char*. common/item-types.h common/items.pl gtk-v2/src/stats.c gtk-v2/src/config.c gtk-v2/src/image.c gtk-v2/src/main.c Arvid Norlander 2008-06-01 Change some char* to const char*. This reduces memory usage when serveral copies are running as const data can be shared between the copies. gtk/config.c gtk/keys.c gtk/map.c gtk/gx11.c gtk/image.c gtk/sdl.c gtk/text.c gtk/png.c gtk/sound.c common/item.c common/commands.c common/init.c common/script.c common/msgtypes.pl common/proto.h common/client.c common/msgtypes.h common/image.c common/client.h common/player.c common/newsocket.c common/script_lua.c common/metaserver.c common/misc.c gtk-v2/src/stats.c gtk-v2/src/spells.c gtk-v2/src/config.c gtk-v2/src/about.c gtk-v2/src/keys.c gtk-v2/src/metaserver.c gtk-v2/src/map.c gtk-v2/src/magicmap.c gtk-v2/src/image.c gtk-v2/src/sdl.c gtk-v2/src/main.c gtk-v2/src/opengl.c gtk-v2/src/png.c gtk-v2/src/sound.c gtk-v2/src/menubar.c gtk-v2/src/info.c gtk-v2/src/pickup.c gtk-v2/src/inventory.c Arvid Norlander 2008-06-01 Move configure.in to configure.ac (the new name since a few years). Update configure.ac syntax with autoupdate. Make help strings use AS_HELP_STRING. common/config.h.in aclocal.m4 configure.ac Moved: configure.in to configure.ac Arvid Norlander 2008-06-01 Yet more fixes of Makefile.am/aclocal stuff: Make aclocal install needed macros into the macros directory. Makefile.am aclocal.m4 Added: macros/pkg.m4 Arvid Norlander 2008-06-01 Fix Makefile.am so aclocal.m4 generation works correctly. Makefile.am aclocal.m4 Arvid Norlander 2008-06-01 Seems like the autotools define for LUA changed, update source to properly use LUA. common/commands.c common/p_cmd.c common/script_lua.c common/config.h.in aclocal.m4 Arvid Norlander 2008-06-01 More cleanup of autotools mess. Also update svn:ignore where needed. svn:ignore updated: . pixmaps gtk help common utils x11 gtk-v2 gtk-v2/themes gtk-v2/src gtk-v2/glade sound-src Removed: utils/mkinstalldirs utils/depcomp utils/missing utils/install-sh Arvid Norlander 2008-06-01 Remove some auto generated autotools files from the tree. Just run autogen.sh to create them. This prevents the mess of different developers using different versions of autotools, making commits a mess. utils/Makefile.in utils/config.guess utils/config.sub x11/Makefile.in gtk-v2/Makefile.in gtk-v2/themes/Makefile.in gtk-v2/src/Makefile.in gtk-v2/glade/Makefile.in sound-src/Makefile.in pixmaps/Makefile.in configure Makefile.in gtk/Makefile.in common/Makefile.in help/Makefile.in Arvid Norlander 2008-06-01 Fix bug #1871476:] client script 'watch stats' error. common/script.c: don't work on initial length, as it'll affect other scripts. Make parameters const to avoid issues. common/script.h: change function definition. Nicolas Weeger 2008-05-09 Apply patch by Jochen Suckfüll to move recently updated skills to top of list for X11 client (could possibly be used for other clients). common/client.c client.h commands.c init.c x11/x11.c Nicolas Weeger 2008-05-07 configure.in: detect lua 5.0 and 5.x as the build broke on some systems if the liblua stuff was loaded. For 5.0, libm and libdl are added to LUA_LIBS for liblualib to be usable. The summary report for ./configure now reports if lua scripting support is included in the build. gtk/Makefile.am, gtk-v2/src/Makefile.am, x11/Makefile.am: Add @LUA_LIBS@ into the link library list to fix build problems when lua is detected. Kevin Bulgrien 2008-04-26 gtk-v2/src/main.c gtk-v2/src/sound.c: Move the signal handler for SIGPIPE in main so that it can be used both for sounds and for scripts. Raphael Quinet 2008-04-26 Apply patch #1878451: Let crossfire client compile with OSS4's soundcard.h Courtesy anonymous. sound-src/cfsndserv.c Nicolas Weeger 2008-03-29 gtk-v2/src/main.c: Change the minimum window size to 640x480 since a window layout has been made that shows it is possible. There seem to be people out there that like small... Kevin Bulgrien 2008-02-17 gtk-v2/glade/gtk-v2.glade: Primarily a rename of widgets that had generic names (Eg. vbox2 --> vbox_all). The corestats tab changed to cuddle the stat value with the stat name for readability. Numeric values beside the stat bars is now left justified. Fire/Run indicator positions slightly altered. Presently the window will not shrink smaller than 800x600. This is due to the size set in main.c (geometry.min_width and geometry.min_height). Kevin Bulgrien 2008-02-17 gtk-v2/glade/AUTHORS: Update the descriptions of recently modified client layout files. Kevin Bulgrien 2008-02-12 gtk-v2/glade/un-deux.glade: This is an aethsetic overhaul, adding viewports with insets to set different screen elements off. Key widgets are moved to a common centerline below the map notebook to keep critical information at a consistent eye-level to improve visibility during play. The encumbrance and count box is now between the inventory and ground view, and the fire/run indicators are just below the command entry box. Kevin Bulgrien 2008-02-12 gtk-v2/glade/v1-redux.glade: Roll in the changes from gtk-v1.glade that make the layout more true to the original GTK V1 layout while keeping the tab notebook improvement. The encumbrance display and count box has had a slight aesthetic improvement also. Kevin Bulgrien 2008-02-12 gtk-v2/glade/gtk-v1.glade, gtk-v2/glade/gtk-v2.gladep: A major facelift brings this client layout much closer to the appearance of the GTK V1 client layout with a few exceptions like the XP bar and the Magic Map in the tab notebook. Kevin Bulgrien 2008-02-12 gtk-v2/glade/meflin.glade, gtk-v2/glade/meflin.gladep: Miscellaneous fixes to add previously invisible or missing widgets: Run/Fire labels, Count input, and encumbrance. Kevin Bulgrien 2008-02-12 gtk-v2/crossfire-client-gtk2.man gtk/crossfire-client-gtk.man x11/crossfire-client-x11.man: Escape the apostrophe when it starts a line to avoid confusing man or nroff ('help -> \'help). Reported by Kari Pahula. Raphael Quinet 2008-02-11 gtk-v2/crossfire-client-gtk2.man: Change more instances of gcfclient to crossfire-client-gtk2, and change the title to specify that this client is a second-generation GTK client. Update the client option list, and add or remove descriptions to match the client's capabilities. Some additional work may be needed to be sure the information is up to date and accurate, but this is a first pass at an update. Change some capitalization, and document the new window position save file conventions. gtk-v2/src/main.c: Add some doxygen comments to variable definitions. LOG() calls are reformatted to break long lines and convert instances of "gtk::" to "main.c::" for consistency with other LOG() messages. Change the title bar of the client from "GTK2 ... Client" to "GTK V2 ... Client" to make it a little less likely that people will assume that the 2 means GTK version 2 (especially since this client may eventually be built with a different version of GTK). gtk-v2/src/config.c: Reformat LOG() calls to break long lines, and convert all instances of "gtk::" to "config.c::" for better consistency with other LOG() messages. Also change all "config.c:" to "config.c::". Player visible change in load_winpos() and save_winpos() changes the window position save file from gwinpos2 to a name based on the window layout file name. For example, if the default window layout (gtk-v2.glade) is used, the window positions are now saved to gtk-v2.pos. This allows retention of saved window sizes for all window layouts, and has a side benefit of making sure that the default window positions are all used the first time a window layout is selected. Providing that the player's screen size is large enough, this will tend to reduce difficulty in setting up window positions for the first time. Kevin Bulgrien 2008-02-10 Doxyfile: Remove the .xpm files from the list of files to parse as it is painfully slow to do so. Kevin Bulgrien 2008-02-06 gtk-v2/src/info.c: Factor out redundancy in draw_info() in both cases of an if/else statement. Kevin Bulgrien 2008-02-05 gtk-v2/src/info.c: Prepare to work on this file. Break long lines; indention fixes; commenting changes; addition of new doxygen content. No code changed in this commit. Kevin Bulgrien 2008-02-05 common/Makefile.am: Use hint at http://www.in-ulm.de/~mascheck/various/echo/ to try to remove a portability issue regarding use of echo -n. Kevin Bulgrien 2008-01-29 gtk-v2/glade: gtk-v1.glade, un-deux.glade: Rename widgets to use a proper name instead of the numbered names. gtk-v2/glade/v1-redux.glade: Add missing label_cha for Charisma stat. Rename widgets to use a proper name instead of the numbered names. gtk-v2/glade: gtk-v1.gladep, v1-redux.glade, un-deux.glade: Edit program_name to see if it shows up in the title bar. Kevin Bulgrien gtk-v2/glade/Makefile.am: Fix non portable usage of foreach, use makes built in variable substitution instead. MSW 2008-01-27 gtk-v2/glade/un-deux.glade: Fix missing label_cha for Charisma value to be shown. gtk-v2/glade/un-deux.glade: The original design did not allow the ground view to be expanded optimally, the layout was changed to remove this limitation. gtk-v2/glade/AUTHORS: Update the description of the un-deux layout. gtk-v2/glade/README: Updated this file with new hints and information. Some spelling fixed. gtk-v2/glade/un-deux.glade, gtk-v2/glade/un-deux.gladep: This layout is a heavily modified v1-redux that places the critical messages, stat bars, protections, and ground view all in horizontally adjustable boxes. It still vaguely reminiscent of the original GTK V1 client, but only slightly so. The message boxes are to the left of the map, and the inventory view is to the right. The command input box is between the tall message pane and the short critical message pane, at the bottom left corner of the map. This puts chat messages right next to the command input box. The window size defaults to 1180x925 and comfortably handles a 19x17 map pane. gtk-v2/glade/Makefile.am: Add support for un-deux.glade gtk-v2/glade/AUTHORS: Describe the un-deux window. Kevin Bulgrien gtk-v2/glade/lobotomy.glade, gtk-v2/glade/lobotomy.gladep: A slightly variant layout that challenges the tradition of those that came before. gtk-v2/glade/AUTHORS: Describe the lobotomy layout. gtk-v2/glade/Makefile.am: Lobotomize me? Kevin Bulgrien gtk-v2/glade/gtk-v1.glade, gtk-v2/glade/AUTHORS, gtk-v2/glade/eureka.glade: Standardize these layouts at 1180x925 so they easily fit 1280x1024 screens and allow for a either a vertical or horizontal menu bar. Document the map pane sizes and overall window sizes for the different layout files. Kevin Bulgrien gtk-v2/glade/v1-redux.glade, gtk-v2/glade/v1-redux.gladep: Add a new layout that revisits the legacy GTK V1 client look, but saves on vertical space by using a tab notebook for the character and skill information. gtk-v2/glade/eureka.glade, gtk-v2/glade/eureka.gladep: Add a new layout to SVN that has just been sitting on my system for ages. gtk-v2/glade/AUTHORS: Add and describe the eureka and v1-redux layouts. gtk-v2/glade/Makefile.am: Add support for the eureka and v1-redux layouts. gtk-v2/glade/README: Remove no longer relevant comment about inability to restore screen positions. Kevin Bulgrien General cleanup with propset svn:ignore && fixup oops due to not quite getting how svn:ignore works. Kevin Bulgrien Packaging update work. crossfire-client-spec: An initial attempt to bring the .spec file up to date with the libglade/libcurl/pthread requirements and for packaging the theme and window layout files. It has not been tested yet and probably needs more work. gtk-v2/crossfire-client-gtk2.man: For now, this is really only a slightly modified copy of gtk/crossfire-client-gtk. It needs an update, but then so do all the other client man pages. gtk-v2/crossfire-client.desktop: An executable file name change. Really, I think this file needs a rename to be correct. gtk-v2/Makefile.am: Support for the new crossfire-client-gtk2.man file. gtk/crossfire-client-gtk.man: Client name changes for trunk, and a number of spelling errors fixed and .crossfire file names fixed like winpos->gwinpos. x11/crossfire-client-x11.man: Client name changes for trunk, and a number of spelling errors fixed. Kevin Bulgrien [ 1839894 ] Keybind editor flaw (gtk2, gtkv2) appears fixed by prior commit. This is basically a doxygen documentation commit. gtk-v2/keys.c: Remove erroneous comment. Document Key_Entry struct typedef. Fix @defgroup syntax. Fix @todo items with #if 0 in description by quoting the hash mark. Line length adjustments and notation consistency fixes for LOG() calls. Other miscellaneous line length adjustments. Add descriptions for more functions. Enhance one function descriptions. Kevin Bulgrien This should fix remaining issues in [ 1527973 ] bind command does not work, & also is a general doxygen update for keys.c files. help/chelp: Add the additional flags supported by the GTK V2 client and a note that says each client may not support all flags, and to use bind w/o any parameters for client specific help, otherwise there is no verbose help for the GTK V2 enhancements, and no explanation for why -g doesn't work. gtk/keys.c: doxygen @file added. gtk-v2/keys.c: In parse_keybind_line(), A is for all flags, so add KEYF_META and KEYF_ALT when it is the flag in a keybinding entry. Add function descriptions for various previously undocumented one, or improve/add detail to others. Various minor reformatting including spacing and line length changes. In bind_key(), remove spurious line break and whitespace from bind help text. Indentation fixes. In keybinding_get_data() change up the logic for use of the checkboxes in the keybinding dialog so that flags are set consistently. The new logic is very intuitive. KEYF_NORMAL is set if none or all of the Run/Fire/Alt/Meta checkboxes are checked. In update_keybinding_list(), "All " is now used to indicate when all of these flags are set to differentiate from only the normal flag being set. Kevin Bulgrien 2008-01-21 gtk-v2/src/keys.c: Saved work-in-progress. Long lines shortened. Added doxygen modules definition. More comments converted to doxygen form. Improved the style of some previously converted commenting. Reordered some declarations to move them with other similar ones. Started to use column 41 for end-of- line comments where reasonable for cleaner read. Rewrote some function comment descriptions. Added new function and parameter descriptions. Some indentation corrections. Kevin Bulgrien 2008-01-20 gtk-v2/src/keys.c: Fix for [ 1875657 ] Bogus keybinding too long errors. Made more truncation messages consistent, and fixed an inconsistently formatted LOG message. Fixed case and shortened message when keybinds are saved. Kevin Bulgrien 2008-01-20 gtk-v2/glade/dialogs.xml: Change Update Keybindings button to Update Bindings for consistency with the Remove Bindings button. Kevin Bulgrien 2008-01-19 gtk-v2/glade/dialogs.xml: Dress up the dialog for the libglade client by adding some padding in various places. Fixed some spelling and reworked various texts on the dialogs. Kevin Bulgrien 2008-01-19 Per-character keybind support. gtk-v2/src/keys.c: In save_keys() and keys_init(), a pointless #ifdef WIN32 was used to attempt to implement per-character keybind files but keys_init() is called long before a player can log in, so this had the effect of writing keybinds to a file that cannot be loaded. Oddly, this was under a #ifdef WIN32 which is quite inappropriate as if supported, it should be for all platforms. The support is commented out with #if 0 until it can be fixed and then re-enabled for all clients. Meanwhile, it surely fixes a WIN32 bug. General doxygen update: gtk/sound.c: Convert function description comments to doxygen form. common/client.h: Convert comments to doxygen form. x11/sound.c: Add doxygen file header. Makefile.am: Add target dox to generate doxygen files and output errors to doxygen.err gtk-v2/src/stats.c: Add doxygen file header. Convert function description comments to doxygen form. Fix missing doxygen @param for update_stat(). Add stubs for missing function descriptions. gtk-v2/src/spells.c: Add doxygen file header. Convert comments to doxygen form. Convert function description comments to doxygen form. gtk-v2/src/about.c: Whitespace only. gtk-v2/src/keys.c: Convert comments to doxygen form. Convert function description comments to doxygen form. Define groups for the functions in this file. In parse_keybind_line, add a parameter description. In init_default_keybindings, add to the function description. gtk-v2/src/image.c: Minor reformatting. In image_update_download_status() description, remove erroneous @param items. gtk-v2/src/sdl.c: Add doxygen file header. Convert comments to doxygen form. Convert function description comments to doxygen form. Add stubs for missing function descriptions. Move some defines from between a function description and the function code to above the description to help out doxygen. gtk-v2/src/png.c: Add doxygen file header. Convert comments to doxygen form. Add stubs for missing function descriptions. Move some defines from between a function description and the function code to above the description to help out doxygen. gtk-v2/src/sound.c: Rework the doxygen file header. Kevin Bulgrien 2008-01-19 Undo unintentional change from prior commit. gtk-v2/glade/caelestis.glade Kevin Bulgrien 2008-01-18 Fix: [ 1806282 ] Libglade client screen position saving faulty The root window "visible" property must be set to "no" in order for saved screen size settings to be restored when the application starts up. gtk-v2/glade/*.glade gtk-v2/glade/README Kevin Bulgrien 2008-01-18 Fix for bug [ 1810609 ] menu items don't work if metaserver is bypassed - move call to enable_menu_items() into main.c, and call it even if we are doing direct connection (-server option). gtk-v2/src/metaserver.c: Remove call to enable_menu_items() gtk-v2/src/main.c: Add calls to enable_menu_items() MSW 2008-01-15 Various bugfixes mostly: common/client.c: If servername is (null), don't both trying to connect - this happens when the NULL value is saved out on some systems. common/client.h: Update VERSION_SC to 1029 common/metaserver.c: Add more code since this client (at version_sc 1029) can still play on 1027 and 1028 servers. gtk-v2/src/stats.c: Fix stat bar handling for exp - it now shows a progression relative to currently level (so the instance you gain a new level, stat bar goes back to zero) - this is more how things are expected to work. Also, handle weapon_speed properly based on sc_version. gtk-v2/src/gtk2proto.h: Rebuilt MSW 2008-01-15 common/image.c, README: Rename client '.crossfire/crossfire-images/' to '.crossfire/image-cache/' to make backups avoid backing it up with a generic exclude like "*/*cache*/*" that works for many other packages that employ caching. Kevin Bulgrien 2008-01-04 Win32 compilation fixes. Remove superflous includes messing everything. (merge from 1.x) common/client.c commands.c item.c metaserver.c newsocket.c p_cmd.c player.c script.c gtk/win32/config.h porting.c Nicolas Weeger 2008-01-03 Fix smoothing code so it take into account smoothing on layers >0 if there is something drawn at lower layers. gtk-v2/src/map.c gtk-v2/src/sdl.c gtk-v2/src/opengl.c Tchize 2007-12-24 Fix for bug #1825653: Odd number problem with nrof. common/item.c: nrof is unsigned int32. Nicolas Weeger 2007-12-01 gtk/text.c: Add missing write_media() calls in handling of admin messages. Results in news and rules not being displayed. Fixes bug 1657000 MSW 2007-10-03 gtk-v2/src/info.c - Change error message when the client gets a message with a [] text format tag that is not valid to make it more obvious what is wrong. This can help determine the error faster if the server inadvertently sends the client a message with displayed text that has square brackets around it. Kevin Bulgrien 2007-09-30 Fix for bug 1800702 - gdk_draw_drawable: assertion `src != NULL' failed. gtk/gx11.c: Call sdl_gen_map() or gtk_draw_map() based on displaymode in use. gtk-v2/src/main.c: Call draw_map() instead of gtk_draw_map(). draw_map() will figure out what function (sdl, opengl, gtk) to call do actually draw the map. MSW 2007-09-25 gtk-v2/src/info.c gtk-v2/src/inventory.c gtk-v2/src/keys.c gtk-v2/src/magicmap.c gtk-v2/src/main.c gtk-v2/src/menubar.c gtk-v2/src/metaserver.c gtk-v2/src/opengl.c gtk-v2/src/pickup.c - Spelling/grammar fixes. - Doxygen commenting work. - Some indentation adjustments. - Reformat block comments to use 79 columns. - else block structures changed to comply with project coding standards. Kevin Bulgrien 2007-09-25 gtk-v2/src/about.c - Doxygen commenting work. gtk-v2/src/config.c gtk-v2/src/image.c - Spelling/grammar fixes. - Doxygen commenting work. - Some indentation adjustments. - Reformat block comments to use 79 columns. Kevin Bulgrien 2007-09-24 gtk/text.c: Remove call to void_callback() for MSG_TYPE_MONUMENT - if there is no code to handle it, no reason to set the callback. Fixes bug 1759860 - gravestone messages go to stdout and not client window. MSW 2007-09-23 gtk-v2/src/map.c - Doxygen commenting work. - Spelling fix visable --> visible. - Reformat block comments to use 79 columns. Kevin Bulgrien 2007-09-23 gtk-v2/src/metaserver.c: Modify metaserver_connect_to so it can connect to servers running on different ports (eg, localhost:13328). Gtk1 client already handles this fine, so this is only a change for the gtk2 client. MSW 2007-09-16 gtk-v2/src/stats.c gtk-v2/src/spells.c gtk-v2/src/keys.c gtk-v2/src/map.c gtk-v2/src/metaserver.c gtk-v2/src/magicmap.c gtk-v2/src/image.c gtk-v2/src/sdl.c gtk-v2/src/opengl.c gtk-v2/src/png.c gtk-v2/src/sound.c gtk-v2/src/main.h gtk-v2/src/info.c gtk-v2/src/pickup.c - Tabs --> spaces. gtk-v2/src/config.c gtk-v2/src/inventory.c - Tabs --> spaces. - End-of-line whitespace removed. Kevin Bulgrien 2007-09-16 gtk-v2/src/map.c gtk-v2/src/main.c - Fix for SourceForge Bugs Tracker #1794455 Libglade client Magic Map: cannot return to Map. During the libglade conversion, and incorrect g_signal_connect() call was placed in map.c. The corrected connection is now made in main.c where the magic_map pointer is initialized. gtk-v2/glade/README - Add a note for glade file developers concerning the MAGIC_MAP_PAGE define that constrains the tab on which magic maps must appear. Kevin Bulgrien 2007-09-14 Improve metaserver handling some - in particular, if server is listed on both metaserver 1 & 2, listed it only once. Also, for gtk2 client, fix handling of not showing cached entries if they are listed on the metaserver. Add filtering of protocol versions, so we only show player compatible servers. -- common/metaserver.c: Add check_server_version() to do version checking. Add checks to find duplicate server entries. gtk-v2/src/metaserver.c: Move retrieval of data from metaserver before adding cached entries to table - otherwise, can not detect duplicates. Add check to proper version information. MSW 2007-09-13 common/client.h - Add doxygen file header. gtk-v2/src/gtk2proto.h gtk-v2/src/main.c gtk-v2/src/metaserver.c - Remove unused return value for get_metaserver(). gtk-v2/src/metaserver.c - Doxygen commenting, and add comment headers for all functions. - Remove commented-out IP Address column formerly shown in metaserver dialog. Kevin Bulgrien 2007-09-05 gtk-v2/src/menubar.c - Doxygenification of source/comments. Kevin Bulgrien 2007-09-04 gtk-v2/src/about.c gtk-v2/src/image.h gtk-v2/src/sound.c gtk-v2/src/main.h - Doxygenification of comments and files. Kevin Bulgrien 2007-09-03 gtk-v2/glade/AUTHORS - Adjust some glade file descriptions. gtk-v2/glade/oroboros.glade - Reorder character data tabs. Kevin Bulgrien 2007-09-03 gtk-v2/glade/AUTHORS - Add oroboros.glade and add short paragraph descriptions of each of the new layout files. gtk-v2/glade/Makefile.am gtk-v2/glade/Makefile.in gtk-v2/glade/oroboros.glade gtk-v2/glade/oroboros.gladep - A layout designed expressly for clients running with 1024x768 resolution. Doxyfile - Copied from server; modified and added for client. prop svn:ignore - Add autom4te gtk-v2/src/main.c - Tabs --> spaces, commenting, and doxygenation. No functional code changes. Kevin Bulgrien 2007-09-03 configure configure.in - Tabs --> spaces, indenting uniformity, and typo corrections only. Kevin Bulgrien 2007-09-02 aclocal.m4 configure Makefile.in common/Makefile.in gtk/Makefile.in gtk-v2/Makefile.in gtk-v2/themes/Makefile.in gtk-v2/src/Makefile.in gtk-v2/glade/Makefile.in help/Makefile.in pixmaps/Makefile.in sound-src/Makefile.in utils/Makefile.in x11/Makefile.in - Result of new and fixed m4 files. autogen.sh - Point aclocal at macros so that undefined macros do not crash ./configure macros/gtk.m4 macros/sdl.m4 - ./configure should never crash, so add to remove errors as follows: aclocal:configure.in:?: warning: macro `AM_PATH_GTK' not found in library ./configure: line ?: syntax error near unexpected token `1.0.0' ./configure: line ?: ` AM_PATH_GTK(1.0.0)' aclocal:configure.in:?: warning: macro `AM_PATH_SDL' not found in library ./configure: line ?: syntax error near unexpected token `1.1.3' ./configure: line ?: ` AM_PATH_SDL(1.1.3)' macros/curses.m4 macros/gnome-print-check.m4 macros/gnome-gettext.m4 macros/linger.m4 macros/need-declaration.m4 - Update .m4 files from a newer glade package to remove many warnings like the following: macros/linger.m4:4: warning: underquoted definition of AC_STRUCT_LINGER Kevin Bulgrien 2007-09-02 gtk-v2/src/main.c - Add error_dialog() to notify the user via a graphical dialog that a Glade layout file failed to open. The dialog displayed the client version information, a brief error description, and the file that failed to load. Kevin Bulgrien 2007-09-02 gtk-v2/glade/AUTHORS - Add attribution for caelestis.glade project files. Kevin Bulgrien 2007-09-01 ChangeLog - Summarize gtk-v2-libglade branch merge to trunk. Kevin Bulgrien 2007-09-01 This is a merge of client/branches/gtk-v2-libglade to trunk. It converts the GTK-V2 client to a libglade-2.0 client that supports changing the UI layout with glade-2 generated .glade XML files. Various alternate client layouts are included. AUTHORS - Reformatted for aesthetics. - Added libglade-2.0 conversion author. common/init.c - Typo corrected in LOG message (inic.c --> init.c). configure - LIBGLADE_CFLAGS/LIBS addition. - gtkv2 checks converted to HAVE_GTK2. - gtk-v2/glade directory addition now supported. - V2 client now depends on libglade2.0 instead of GTK+ 2.0. - Some reformatting resulting from autoconf/automake changes flowing down. configure.in - gtk-v2/glade directory addition now supported. - Update indenting; tab->space conversion for readability. - Minor message updates for consistency like GTK2 -> GTK+ 2.0. - V2 client dependency checks changed to require libglade-2.0 vs. gtk+-2.0. gtk-v2/glade gtk-v2/glade/Makefile gtk-v2/glade/Makefile.am gtk-v2/glade/Makefile.in - A fully autoconf/automake supported directory to be used for the control of glade-2 layouts compatible with this client. gtk-v2/glade/AUTHORS - A file to attribute the authors of the glade-2 XML layout projects in this directory. gtk-v2/glade/README - A help file for prospective glade-2 XML layout creation that describes how to create a new layout and workarounds for various issues that may arise. gtk-v2/glade/caelestis.glade gtk-v2/glade/caelestis.gladep gtk-v2/glade/chthonic.glade gtk-v2/glade/chthonic.gladep gtk-v2/glade/gtk-v1.glade gtk-v2/glade/gtk-v1.gladep gtk-v2/glade/meflin.glade gtk-v2/glade/meflin.gladep - New layout files for the V2 client. make install places the .glade files in the crossfire-client data directory, where they are detected by the client in order to allow a user to select a new layout from the configuration popup dialog. gtk-v2/glade/dialogs.glade gtk-v2/glade/dialogs.gladep - This glade-2 XML layout project contains pop-up dialogs formerly contained in the ../gtk-v2.glade files. It was created to reduce the overhead in setting up a new main window layout. The client allows a user to specify a new file at the command-line, but does not attempt to support in-client selection of an alternate file. - Various modification to the original pop-up dialogs have been made to support the libglade-2.0 conversion. The generated code allowed the XML file to have variations in it that cause problems for libglade. - Minor alterations have been mode to appearance and/or text on various dialogs. gtk-v2/glade/gtk-v2.glade gtk-v2/glade/gtk-v2.gladep gtk-v2/gtk-v2.glade gtk-v2/gtk-v2.gladep - Moved to gtk-v2/glade sub-directory. - This is the original gtk-v2 client layout by mwedel. - All popup dialogs have moved into gtk-v2/glade/dialogs.glade. gtk-v2/Makefile.am gtk-v2/Makefile.in - LIBGLADE_CFLAGS/LIBS addition - gtk-v2/glade directory addition now supported. - DIST_COMMON modifications by autoconf/automake to remove files not under SVN control. - Remove gtk-v2/gtk-v2.glade and gtk-v2/gtk-v2.gladep from EXTRA_DIST as they are now located in the gtk-v2/glade subdirectory. gtk-v2/README-dev - Reformat for aesthetics and readability. - Various updates to content based upon IRC or mailing list discussions. - Rework content to third-party point-of-view to make it easier for other developers to modify the document. gtk-v2/src - Inexplicable property changes to svn:ignore simply reposition .deps entry. gtk-v2/src/about.c gtk-v2/src/inventory.c gtk-v2/src/keys.c gtk-v2/src/map.c gtk-v2/src/metaserver.c gtk-v2/src/spells.c - Include glade.h - Remove includes of glade-2 generated source files. - Conversion to libglade-2.0 requires use of glade_get_widget_tree() and change from lookup_widget() to glade_xml_get_widget() and insertion of g_signal_connect() to replace functionality previously found in glade-2 generated source files. gtk-v2/src/config.c - Include glade.h - Various code comment improvements. - Remove includes of glade-2 generated source files. - All functions without a comment header now have one. - Significant code comment reformatting to use of a 79 character line width and to reduce line lengths over 80 characters. - Add static char pointers themedir and gladedir to better support loading combo box widgets from the crossfire-client data directory, and to reduce the number of redundant hard-coded strings. - The configuration popup dialog now supports in-client selection of an XML layout file to redefine the root window appearance. Modified functions include load_defaults(), save_defaults(), setup_config_window(), and read_config_window(). New functions are scandir_glade_filter, fill_combobox_from_datadir() which is derived from code factored out of setup_config_window() so it can be used multiple times. Modifications to save_winpos() and load_window_positions() alters screen position saving to remove hard-coded copy/pasted code and more flexibly support multiple XML UI layout files. - Conversion to libglade-2.0 requires use of glade_get_widget_tree() and change from lookup_widget() to glade_xml_get_widget() and insertion of g_signal_connect() to replace functionality previously found in glade-2 generated source files. - scandir_filter() renamed to scandir_theme_filter() for more consistent naming for multiple scandir filter functions now required since the window layout combo box also requires on. gtk-v2/src/image.c gtk-v2/src/opengl.c gtk-v2/src/sdl.c - Include glade.h gtk-v2/src/info.c gtk-v2/src/pickup.c gtk-v2/src/stats.c - Include glade.h - Remove includes of glade-2 generated source files. - Conversion to libglade-2.0 requires use of glade_get_widget_tree() and change from lookup_widget() to glade_xml_get_widget(). gtk-v2/src/interface.c gtk-v2/src/interface.h gtk-v2/src/callbacks.h gtk-v2/src/support.c gtk-v2/src/support.h - Remove glade-2 generated source files. gtk-v2/src/magicmap.c - Include glade.h - Remove includes of glade-2 generated source files. gtk-v2/src/main.c gtk-v2/src/main.h - Include glade.h - General changes to support the conversion to libglade-2.0 require runtime processing of the glade-2 XML layout file names and locations. - Add support for command-line specification of glade-2 generated XML files that describe the UI windows and pop-up dialogs. - Conversion to libglade-2.0 requires use of glade_get_widget_tree() and change from lookup_widget() to glade_xml_get_widget() and insertion of g_signal_connect() to replace functionality previously found in glade-2 generated source files. gtk-v2/src/Makefile.am gtk-v2/src/Makefile.in - LIBGLADE_CFLAGS/LIBS addition. - Replace GTK2_CFLAGS/LIBS with LIBGLADE_CFLAGS/LIBS. - Changes resulting from removal of glade-2 generated source files. gtk-v2/src/menubar.c - Include glade.h - Remove includes of glade-2 generated source files. - Include image.h and gtk2proto.h as support the libglade-2.0 conversion. - Conversion to libglade-2.0 requires use of glade_get_widget_tree() and change from lookup_widget() to glade_xml_get_widget() and insertion of g_signal_connect() to replace functionality previously found in glade-2 generated source files. gtk-v2/TODO - Reformat for aesthetics and readability. - Add todo for non-functional scroll bar handles on the map display. - Adjust todo for lower screen resolution support since the libglade-2.0 port at least partially addresses usability on smaller desktops. help/about.h - EOL whitespace removed. - Minor reformat for aesthetics. - Added libglade-2.0 conversion author. Makefile.in common/Makefile.in gtk/Makefile.in gtk/themes/Makefile.in help/Makefile.in pixmaps/Makefile.in sound-src/Makefile.in - LIBGLADE_CFLAGS/LIBS addition x11/Makefile.in - LIBGLADE_CFLAGS/LIBS addition - DIST_COMMON modifications by autoconf/automake to remove files not under SVN control. Kevin Bulgrien 2007-09-01 common/metaserver.c: Update to use official and not test metaserver2 location. MSW 2007-08-31 Fix map not updated at tick causing items to appear non animated. gtk/gx11.c gtk-v2/src/main.c Nicolas Weeger 2007-08-15 Partial fix for bug #1772759: Too much alchemy causes client crash. common/item.c: find item in container too. Nicolas Weeger 2007-08-15 Make metaserver1 gather it's data in its own thread. common/metaserver.c: Add ms1_is_running flag, re-work some of the metaserver1 logic so the function structure makes it easy to spawn the thread, rename metaserver2_check_status() to just metaserver_check_status() gtk-v2/src/metaserver.c: Change call to metaserver_check_status(), resort data after getting all info from sever. SMW 2007-08-14 gtk-v2/src/metaserver.c: Add missing pthread_mutex_unlock() - resulted in client hanging after disconnecting from server. MSW 2007-08-14 Add support for metaserver2 in client. For the X11/C clients, they use basic interface (drawn in text window, select a number), so no changes to the GUI portions of those clients was done - gtk2 uses window, so some extra work there. -- acinclude.m4: New file - added for LIBCURL_CHECK_CONFIG macro support. aclocal.m4: Rebuilt configure: Add --disable-metaserver2 option, check for Curl, pthread. Make sure user either has curl installed or has used --disable-metaserver2 configure, */Makefile.in: Rebuilt with Curl support common/cconfig.h: Add note about METASERVER2 (controlled via configure) common/client.c: Add metaserver2 global common/client.h: Add metaserver2 global common/config.h.in: Rebuilt by autoheader. common/init.c: Add call to init_metaserver() common/metaserver.c: Support for metaserver2. More fields in Meta_Info. Re-arrange file a little so logical functions are together. common/metaserver.h: New fields in Meta_Info, some renamed to keep it consistent accross all of metaserver2. common/proto.h: rebuilt gtk-v2/src/metaserver.c: Add support for threaded metaserver2 retrievals - need to make sure data is accessed in thread safe way, also need to add check for status of retrieval thread. MSW 2007-08-08 Fix bug #1735271: Version numbers of client and server do not match. common/client.h: make S->C version 1028 for coherence with server. Nicolas Weeger 2007-08-05 gtk-v2/src/stats.c - Applied patch by "Olivier Huet" to fix experience label and progress bar for high levels (int -> sint64, %d -> %"FMT64"). Kevin R. Bulgrien 2007-07-24 gtk-v2/gtk-v2.glade gtk-v2/src/interface.c - Minor rework of prompt texts. - Add Escape key accelerator for the Quit button. - Add tooltip to the Quit button to tell a user about the accelerator. - Cosmetic improvement to the metaserver dialog done by adding padding or border width to some widgets so there is spacing between them. gtk-v2/src/metaserver.c - Make more room for "Server Comments" by removing the redundant "IP Addr" field, renaming "Last Update (Sec)" to "Updated (Sec)", and renaming "# Players" to "Players". gtk-v2/src/callbacks.h - Glade generated changes. Kevin R. Bulgrien 2007-07-22 gtk-v2/src/inventory.c: Adjust GTK2 client setup_list_columns() so "Weight" column titles are no longer truncated (on some systems). Kevin R. Bulgrien 2007-07-22 gtk/gx11.c: fix memory leak. Nicolas Weeger 2007-07-11 gtk-v2/src/inventory.c: Add support for client side animation of look window. MSW 2007-07-09 Fix various GAIM/GTK links. gtk/win32/gtkclient.nsi Running.txt Nicolas Weeger 2007-07-05 utils/mdk.sh: Make script work again. Andreas Kirschbaum 2007-06-27 Remove Gnome client, which is not built anyway. Deleted: gnome Modified: aclocal.m4 configure configure.in Nicolas Weeger 2007-06-18 Trash obsolete junk. common/client.c image.c item.c misc.c p_cmd.c proto.h Nicolas Weeger 2007-06-18 Remove 'map1cmd' variable which is always 1. common/client.c client.h commands.c gnome/map.c Nicolas Weeger 2007-06-18 Remove map1cmd, face, face1, item1 and some obsolete stuff. common/client.c commands.c image.c mapdata.c mapdata.h proto.h Nicolas Weeger 2007-06-18 common/p_cmd.c: remove 'resist' command, duplicates server-side 'resistances' giving more info. Nicolas Weeger 2007-06-18 configure.in: Add another eval $ndatadir line so properly resolve all the shell variable names so that CF_DATADIR is set properly in common/config.h -- MSW 2007-06-11 gtk-v2/src/inventory.c: Add tooltips to the inventory tabs, to make it clearer what the different tabs do. -- MSW 2007-06-11 Add pick up menu updating support for gtk2 client - when you log in, it will get your character pickup mode and update the check boxes accordingly. --- gtk-v2/gtk-v2.glade: Change "don't_pickup1" widget name to "do_not_pickup" gtk-v2/src/interface.c: Rebuilt gtk-v2/src/main.c: Remove empty client_pickup() function, add pickup_init() gtk-v2/src/pickup.c: Bunch of new code to support pickup updating - mostly a mapping from menu items to pickup modes, since glade doesn't let us store those attributes in the menu item. MSW 2007-06-11 Remove obsolete mapredraw command (empty on server-side). common/p_cmd.c gnome/map.c gtk/config.c map.c gtk-v2/src/config.c map.c x11/xutil.c Nicolas Weeger 2007-06-02 Apply patch #1720388: data len in client.c is calculated wrong courtesy Jürgen Kahnert. common/client.c Nicolas Weeger 2007-05-16 gtk/text.c: fix callback that was eating a word. Nicolas Weeger 2007-05-03 Change the version string from 1.9.1 to 2.0-dev for trunk. Alex Schultz 2007-04-28 Implement feature request #1560389: improve inscription logic. gtk/gx11.c inventory.c common/client.c client.h commands.c item.c item.h proto.h Nicolas Weeger 2007-04-23 Fix memory overrun errors. --- gtk/gx11.c: Allocate enough space in pickup_menus/value to store all allocated entries. gtk-v2/src/stats.c: Allocate enough skill boxes to store MAX_SKILL skills. gtk-v2/src/info.c: Allocate enough memory in info_pane[] to not cause memory overruns. gtk-v2/src/config.c: Allocate enough memory to not cause memory overrun when loading gtk rc files. Andreas Kirschbaum 2007-04-23 autogen.sh: Add script to rebuild autoconf files. configure, aclocal.m4, */Makefile.in: Rebuilt. common/Makefile.am: Rewrite commands to build svnversion.h to not generate an error message the first time they are run. configure.in: Remove duplicate use of AC_CONFIG_SRCDIR. configure.in: Add template comments to AC_DEFINEs. Now autoheader and ./configure --enable-maintainer-mode does work again. --- Andreas Kirschbaum 2007-04-16 Use #include instead #include "config.h" to support multiple configurations outside the source directory. --- Andreas Kirschbaum 2007-04-16 Rename DATADIR to CF_DATADIR to avoid name clashes when cross-compiling to Win32. --- gtk/win32/config.h, configure.in, common/image.c, common/config.h.in, gnome/gnome.c, gnome/gnome-sound.c, gtk-v2/src/config.c: Replace DATADIR by CF_DATADIR. Andreas Kirschbaum 2007-04-16 Add theme support to the gtk2 client spell window. gtk-v2/gtk-v2.glade: Remove the drawingarea boxes, add eventboxes and put the labels in the eventbox - the labels now act as key, as it is easier to do all of foreground, background, and font style there. gtk-v2/src/config.c: Add calls to set spell styles and redraw spell window gtk-v2/src/interface.c: Rebuilt gtk-v2/src/inventory.c: Declare Style_Names static, since it is a generic name and spells.c uses same name. Linewrap a long line. gtk-v2/src/spells.c: Add theme handling - load up theme data, set entries in the treeview widget, update code to draw keys. gtk-v2/themes/Black, gtk-v2/themes/Standard: Add style information for the spells. MSW 2007-02-25 configure, configure.in: Fix broken check for liblua - not all systems have liblualib, so assuming they do if liblua exists breaks compilation. And separate check for lualib. MSW 2007-02-25 Fix missing liblua when linking. configure,configure.in: rebuilt */Makefile.am, */Makefile.in: rebuilt Ryo 2007-02-23 Remove hard dependancy of LUA - instead, have configure check for it and just don't compile in the LUA bits if we don't have lua installed. -- configure,configure.in: Add lua checks. */Makefile.am, */Makefile.in: Remove hard coded links of -llua common/config.h.in: Add HAVE_LIBLUA define common/commands.c, common/p_cmd.c, common/script_lua.c: Add #ifdef HAVE_LIBLUA checks MSW 2007-02-20 Implement feature request 1025952: GTK Client - Save Pickup options. New external command, 'client_pickup(uint32 pickup)', which is called when player logged in. common/client.c commands.c external.h proto.h gtk/gx11.c gtk-v2/src/gtk2proto.h main.c x11/xutil.c Ryo 2007-02-18 Apply patch #1560052: LUA client-side support. New commands: lua_list, lua_load, lua_kill. pixmaps/Makefile.in configure gtk/Makefile.am Makefile.in common/commands.c Makefile.am Makefile.in proto.h p_cmd.c Makefile.am help/Makefile.in utils/Makefile.in x11/Makefile.am Makefile.in gtk-v2/Makefile.in gtk-v2/src/Makefile.am Makefile.in sound-src/Makefile.in Ryo 2007-02-10 gtk-v2/gtk-v2.glade: Apply patch 1636013 - standardize on underscored widget names. Patch by Veli-Matti Valtonen - maligor. MSW 2007-02-06 Add support for different themes in the gtk2 client. A lot of compiled in defaults have also moved to the the theme file. --- INSTALL: Added file - wanted by automake. README: Move install directions to INSTALL file. configure.in, configure: Add gtk-v2/themes/Makefile to list of Makefiles. common/Makefile.in, common/Makefile.am: Add rule to make msgtypes.h file. common/client.h: Add Msg_Type_Names file, used by msgtypes.h file. common/msgtypes.h: File that holds names for the message type/subtype values. common/msgtypes.pl: Script to make msgtypes.h file - basically parses newclient.h, pulling out the MSG_ structures. common/newclient.h: Update to match server version. gtk-v2/Makefile.am, gtk-v2/Makefile.in: Add themes to list of subdirectories. gtk-v2/gtk-v2.glade: Add theme selection to config window. gtk-v2/src/config.c: Add support for loading/saving theme to gdefaults2 file. Add support for getting theme from config window, and changing appearance without need for restart. gtk-v2/src/gtk2proto.h: rebuilt for theme related functions. gtk-v2/src/info.c: Remove hard coded font values. Add code to load color, font, and msg type/subtype from theme file. Remove a lot of the hardcoding for having 2 textviews - removes a lot of redundant code. Change processing for adding messages to to text buffers - don't create a new text tag - use the various textags we have that match. gtk-v2/src/interface.c: Rebuilt with theme selection for config window. gtk-v2/src/inventory.c: Remove hard coded values for color on inventory status. Add ability to specify more than just background color for different status - can now also change font & foreground color. Add code to load up style information. Change processing for getting row style. Update code that adds entries to the rows. gtk-v2/src/main.c: Ad usercolorname global array that provides a name to color number mapping to be used in theme files. Add code to load up user theme. gtk-v2/src/stats.c: Add support for parsing theme data. Remove hard coded color values for the stat bars. Removed hard coded value on number of stat bars in lots of places. gtk-v2/themes: New directory to hold the theme files. --- MSW 2007-02-04 Fix for bug #1538948: Assertion failure for map2 command. Add checks for x,y and layer validity in the Map2Cmd. Note that invalid values are not discarded, but clipped to valid ones. common/commands.c: add checks. common/mapdata.[ch]: move #define to header for access outside .c. Ryo 2007-01-07 Improve command completion: display matching commands. common/p_cmd.c Fix bug with autocompletion: don't change focus, don't select text. gtk/gx11.c keys.c Ryo 2007-01-01 Merge patch #1558073: newpickup flesh courtesy bencha gtk/gx11.c gtk-v2/gtk-v2.glade gtk-v2/src/callbacks.h gtk2proto.h interface.c pickup.c Ryo 2006-11-29 common/Makefile.am: Change svnversion.h generation to not update the file unless it needs updating. Alex Schultz 2006-11-09 Fix problem in display logic when the size of the image was not a multiple of the map_image_size. This shows up when using tall character images. It also shows up when using different -mapscale options due to rounding errors - in both cases now, things are drawn correctly. -- gtk/map.c: Add size parameters to draw_pixmap(). Add logic to figure out proper offsets for drawing odd sized images. gtk/sdl.c: Add logic to figure out proper offsets for drawing these odd sized images. gtk-v2/src/map.c: Add size parameters to draw_pixmap(). Add logic to figure out proper offsets for drawing odd sized images. gtk-v2/src/sdl.c: Add logic to figure out proper offsets for drawing these odd sized images. MSW 2006-11-05 gtk/image.c: Fix bug that results in SDL mode not working if map_scale and icon_scale are the same - can't use GDK pixmaps for SDL drawing. MSW 2006-11-05 Fix bug 1559804 - unable to drop items from inventory into open container on the ground. gtk-v2/src/inventory.c: Add check to see if container is on the ground in addition to being in the player inventory as a valid drop target. MSW 2006-11-03 Add ability for client to get exp table from server. Add exp progressbar to GTK2 client. -- common/client.c: Add declarations for exp_table, exp_table_max, and call to send 'requestinfo exp_table' to server. common/client.h: Add extern declarations for exp_table, exp_table_max common/commands.c: Add get_exp_info() function to get exp table from server in replyinfo command. Fix crash bug in ReplyInfoCmd() if replyinfo with no parameters is sent to client. common/init.c: Add code to clear/initialize exp_table, exp_table_max gtk-v2/gtk-v2.glade: Add exp progessbar widget. gtk-v2/src/gtk2proto.h: rebuilt gtk-v2/src/interface.c: Rebuilt gtk-v2/src/stats.c: Add code to draw/update the exp progressbar. Replace some static numeric constants with #define values instead. Add can_alert option to update_stat() MSW 2006-11-03 common/newclient.h: Merge/copy over file from server to get it synced up. gtk-v2/src/info.c: Modify so that it sets the text manager for all the types so it can use extended markup language. MSW 2006-10-30 Fix annoying bug where popups appear all the time. common/newclient.h: add some missing message types. gtk/text.c: by default, admin commands are just sent to draw_info. This prevents annoying popups. Ryo 2006-10-29 common/Makefile.am: Make sure svnversion.h rebuilds every time. Alex Schultz 2006-10-29 gtk/rcs-id.h, common/rcs-id.h, x11/rcs-id.h, gtk/gx11.c, x11/x11.c: Remove rcs-id code. gtk/Makefile.am, common/Makefile.am, x11/Makefile.am: Remove references to rcs-id.h files. -- configure.in, common/Makefile.am: Generate svnversion.h to define SVN_REV from running the svnversion command if avaliable. common/version.h: Add FULL_VERSION macro, to include SVN_REV if avaliable. gtk/gx11.c, x11/x11.c, gtk-v2/src/main.c: Use FULL_VERSION instead of VERSION. Alex Schultz 2006-10-20 common/client.c, gtk-v2/src/main.c: Remove excess log messages that flood console. Alex Schultz 2006-10-12 Apply patches #1562945, #1562947, #1563796, and #1566467 to allow the gtk2 client to be built in mingw. Courtesy of Kurt Fitzner. --- configure.in, gtk-v2/src/Makefile.in: Clean up build system a little and add mingw supports. common/item.c, common/commands.c, common/init.c, common/script.c, common/mapdata.c, common/client.c, common/p_cmd.c, common/player.c, common/newsocket.c, common/metaserver.c: Add mingw/win32 support. gtk-v2/src/keys.c, gtk-v2/src/map.c, gtk-v2/src/image.c, gtk-v2/src/sdl.c, gtk-v2/src/main.c, gtk-v2/src/opengl.c, gtk-v2/src/png.c, gtk-v2/src/Makefile.am, gtk-v2/src/sound.c, gtk-v2/src/menubar.c: Add win32 support to gtk2 client code, including for sdl and opengl. Alex Schultz 2006-10-07 common/mapdata.c, common/proto.h: Move clearing of old map data from mapdata_set_face_layer() to a new mapdata_clear_old() function. common/commands.c: Call mapdata_clear_old() in Map2Cmd() instead of relying on mapdata_set_face_layer() to clear it. Fixes bug #1559683. x11/x11.c: Fix display_mapscroll() to handle scrolling by greater than 1 tile at a time. Fixes bug #1564584. Alex Schultz 2006-09-26 gtk-v2/src/info.c: Add some notes about downloading font. Add support for underline in extended text modes. MSW 2006-09-17 configure.in: Fix opengl checks. Alex Schultz 2006-09-17 Fix bug 1531060 - metaserver selection button is improperly activated. Fix this by clearing the text box if an entry in the tree widget is selected - if text is entered in the text box, unselect any selection - keeps it very consistent what the connect button does. Have it greyed out until there is either text in the text box or something selected in the treeview. -- gtk-v2/gtk-v2.glade: add callback for key press events for text entry box. gtk-v2/src/callbacks.h,gtk-v2/src/interface.c: Rebuilt gtk-v2/src/metaserver.c: Add code to activate/disable button based on status. Add code to clear text box when treeview selected. Add code to deselect treeview if data is entered in textbox. MSW 2006-09-05 gtk-v2/src/stats.c: Fix bug 1527966 - protections window not properly updated. Wrong variable was being used in loop. MSW 2006-09-05 gtk-v2/src/map.c: Clear clipmask and clear window in draw_splash() so that splash is correctly redrawn. gtk-v2/src/metaserver.c: Add call to draw_map() in metaserver selection just to make sure splash is drawn correctly. MSW 2006-09-04 gtk-v2/src/inventory.c: Fix bug 1528014 - when dropping all objects, display isn't updated correctly. Remove checks for cpl.ob->inv - relying on cpl.ob->inv_updated appears to work fine. gtk-v2/src/keys.c: Fix bug 1527988 - message about unused keys isn't very useful. Include meta and alt information about unused keys. Add warning message to bind when trying to bind a key that may conflict with an existing binding. MSW 2006-09-04 Add suggestion from bug 1528536 - some menu items should be disabled during metaserver selection. -- gtk-v2/gtk-v2.glade: Fix some incorrect name (meny vs menu) gtk-v2/src/interface.c: Rebuilt gtk-v2/src/menubar.c: Add enable_menu_items(), which enables/disables some menu items. gtk-v2/src/metaserver.c: Add calls to enable_menu_items() to disable some menu items before metaserver selection, and to enable them after. MSW 2006-09-04 gtk-v2/gtk-v2.glade: Add callback for pressed event on metaserver quit button - allows alt-Q to work - fix for bug 1551373 gtk-v2/src/interface.c: Rebuilt -- gtk-v2/server/metaserver.c: Make some changes related to bug 1548290 - cached entries show 0 value in players. Add code to check list of servers from metaserver - if we have a match in the cached server list, don't display the cached entry - use the one from the metaserver instead. Also, add logic to not display empty server if the default server is null. -- gtk-v2/src/config.c: Make save_winpos() do actual saving, have on_save_window_position_activate() call save_winpos() - fixes bug 1551395 where savewinpos command does not work. gtk-v2/src/main.c: Remove empty function save_winpos() MSW 2006-09-04 gtk-v2/src/stats.c: Remove extra Player: in the player name. Fixes bug 1528011. MSW 2006-09-03 This change mainly adds support for the extended info messages for the gtkv2 client. Note that unlike the gtkv1 client, the gtkv2 client doesn't in any way try to do pop up windows or fancy graphics - rather, the support is there just so it can do font changes, color changes, etc, within the normal text window. -- common/newclient.h: Sync it back up with server version. Several new MSG_ types added. gtk-v2/src/info.c: Redo info pane handling - move all the relevant variables into a structure - this should make it easier to add more panes in the future, but right now, it means an integer can be passed in to functions to control what pane to draw in. Add support for extended draw info - notably, this means listing alternative fonts, and adding support for different tags. Add callsbacks for the different message types. Add code to process extended text message tags. gtk-v2/src/keys.c: Change the grab focus after user enters command to use the treeview_look widget instead fo the textview - given that the textview is now stored away in a structure, harder to get to that variable. MSW 2006-09-03 common/client.c: fix Win32 compilation. Ryo 2006-09-03 gtk-v2: Fix bug 1528540 - if metaserver window is closed, client is unusable. Take suggested fix - if metaserver window is closed, exit client. Just another hook to last commit. gtk-v2/gtk-v2.glade: Add callback for destroy event on metaserver window. gtk-v2/src/interface.c: rebuilt. MSW 2006-08-21 gtk-v2: Fix bug 1530024 - errors when manually closing a window. gtk-v2/gtk-v2.glade: Add callback for destroy event on main window. gtk-v2/src/callbacks.h, gtk-v2/src/interface.c: Updated by glade with new callback gtk-v2/src/main.c: Code to handle callback MSW 2006-08-20 gtk/gx11.c: if cpl.no_echo is set, hide input. Ryo 2006-08-08 configure: add --enable-cfgtk2 flag, to build gtk1 client with gtk2. configure.in: add --enable-cfgtk2 flag. Add getaddrinfo check. common/commands.c: check buffer length. common/init.c: free allocated memory. gtk/gx11.c: replace some WIN32 with CFGTK2. gtk/win32/config.c: add #define CFGTK2. Ryo 2006-07-29 Make common/cconfig.h act as the default server if set, if not set, connect to metaserver. Prior to this, it always went to the metaserver unless -server option was given. -- common/cconfig.h: Comment out SERVER so by default it connects to metaserver common/client.c: Add handling to initialize server from SERVER if defined, null otherwise. common/metaserver.c: Don't present default server in metaserver selection default is null. gtk/gx11.c, gtk-v2/src/main.c, x11/x11.c: Change command line handling - if server is set, use that as default to connect to. -- MSW 2006-07-17 gtk-v2/src/inventory.c: Add another invisible column to inventory/look lists for sorting based on name without nrof clogging results. Comment out code that makes image fixed width. MSW 2006-07-17 x11/xutil.c: Use snprintf() to avoid possible buffer overflows. gtk/image.c gtk-v2/src/image.c gtk-v2/src/opengl.c: Remove superfluous casts. common/item.h, gnome/gnome.c, gtk/gx11.c, x11/x11.c: Remove unused macros. common/commands.c: Unify/fix calls to LOG(). common/commands.c: In DeleteItem() and DeleteInventory() do not crash if an invalid object tag was received. Andreas Kirschbaum 2006-07-16 Fix problem in gtk1 & gtk2 client when player issues disconnect command - client would hang and consume all CPU time. --- common/external.h: Add declaration to cleanup_connection() common/p_cmd.c: In disconnect command, add call to cleanup_connection() gtk/gx11.c, gtk-v2/src/main.c: Add cleanup_connection() - removes socket from one of the gdk input device, call gtk_main_quit so it returns to metaserver selection. x11/x11.c: Add empty cleanup_connection() - x11 client doesn't need to do anything special. MSW 2006-07-06 More changes related to default logging. Able to specify default log level with configure. Note: you will need to re-run configure after this change, as otherwise MINLOGLEVEL will not be defined in config.h. --- configure.in, configure: Add --with-loglevel= to specify default loglevel. crossfire-client.spec: Update to include --with-loglevel for building RPMs common/config.h.in: Add MINLOGLEVEL #define. common/misc.c: Modify to use the MINLOGLEVEL #define MSW 2006-07-05 Clean up some compile warnings. They generally fall into either wrong form for variable (%lld vs %ld), or cast for data (char* vs uint8*) --- common/client-types.h: Add FMT64 defines like done in the server. Removes need for #ifdef WIN32 in many places. common/client.c: Remove unneeded cast for ReplyInfoCmd(). Change type of length parameter passed to getsockopt() to be a socklen_t. common/commands.c: Change ReplyInfoCmd() to take a uint8*. Add several char*/uint8* casts. Change TickCmd() to also take uint8* common/external.h: Add extern void client_tick(uint32 tick). common/image.c: load_image() so that its fourth param (checksum) is a uint32. In finish_face_cmd() change filename to be a char*. Add some casts in ImageCmd() & Image2Cmd(). Change display_newpng() so its first param (face) is just a int, not a long. Change get_image_info() to take in a uint8* for data, add some casts. Change get_image_sums() to take in a char* common/item.c: Change several buffers used by the socklist structure to be uint8, add casts as needed. common/newsocket.c: Change SockList_Init() so that the passed in buffer is a uint8*, so that is what the target buffer type is. Add some casts and update some types within the program. common/player.c: Change a buffer from char to uint8. common/proto.h: Rebuilt. common/script.c: Change it to take in a uint8 for data. Change %lld to use FMT64 common/script.h: Update declaration of script_watch() gtk/config.c: Remove const from titles. While they may be used as a const, the gtk function they are passed to isn't declared that way. gtk/gx11.c: Remove unused function end_windows(). Replace %lld with FMT64. Removed const from title declaration. gtk/inventory.c: Remove const from titles declaration. re-enable cast for image creation for tabs. gtk/keys.c: Add note about compiler warning and bad code technique for for getting the selection. gtk/png.c: Removed unused variables/function - png_to_gdkpixmap() gtk/text.c: Change void_callback() to match format of other callbacks to prevent warning. gtk-v2/src/gtk2proto.h: Rebuilt. gtk-v2/src/png.c: Remove unused variable. gtk-v2/src/stats.c: Replace %lld with FMT64. pixmaps/question.111, pixmaps/stipple.111, pixmaps/stipple.112: Change types to be char and not unsigned char, since that is what the function tha uses this data expects. x11/x11.c: Replace %lld with FMT64 --- MSW 2006-07-04 Changes related to logging of version information. aclocal, Makefiles.*: Rebuilt for new file in gtk-v2/src. common/misc.c: Change MINLOG to be a variable so it can be changed via command line options. gtk/gx11.c: Have bug window display rcsid versions. Add -loglevel command line option. Move printing of some log messages until after we process command line options since that can change the log level. gtk-v2/gtk-v2.glade: Add an about window for the gtkv2 client. gtk-v2/src/Makefile.am: Add about.c file. gtk-v2/src/about.c: file for about window. gtk-v2/src/callbacks.h: on_about_close_clicked() added by glade. gtk-v2/src/interface.c, interface.c: New logic for about window. New function - create_about_window() gtk-v2/src/main.c: Add -loglevel command line option. Move printing of some log messages after we process command line options. gtk-v2/src/menubar.c: remove menu_about() - now in about.c MSW 2006-07-04 common/misc.c: Make default log level 2 when not in debug mode. Normal users probably don't want all the INFO log messages, and it never makes a good impression about stability/quality if a program spews out lots of errors or other messages. MSW 2006-07-01 Make some changes to the defaults so that the game is a bit more user friendly to completely new users (eg, those that don't have a settings file): -- common/init.c: Turn off popups (gtkv1 client) by default - general seems that it isn't popular, and placement of the popups needs to be fixed. gtk-v2/src/main.c: Change default map size to ask from server to be 25x25 - the gtkv2 client has default window size for that, so lets use it. x11/x11.c: Turn on scroll of text by default - non scroll is really ugly and doesn't make any sense give the power of even very slow cpus now. MSW 2006-07-01 gtk-v2/src/config.c: Fix bug resulting in a crash when opening the configuration dialogue if you have an empty gdefaults2 file. MSW 2006-06-30 Changes for 1.9.1: ------------------------------------------------------------------------------ sound-src/alsa9.c: Fix up sound for alsa9+. Not positive exact change that fixed the problem, but following changes made: Add SOUND_DEBUG_WRITES to separate the debug from writes vs all the other debug messags. If using 16 bit data, always use unsigned no matter wit the sign config option says. In alsa_recover(), if error is EAGAIN, just do nothing and return. In audio_play(), don't write more bytes than chunk size (basically largest block that alsa wants at one time). In play_sound(), don't decrease volume based on maximum number of sounds that may be played at once - this makes things too quiet. MSW 2006-06-25 gtk/gx11.c, gtk-v2/src/main.c: Add checks for csocket.fd==-1 after return of DoClient. With change in DoClient to close the socket, the network routines are not called again (like they used to be), and thus the GUI was't really aware the socket was closed, and wouldn't prompt for metaserver selection. MSW 2006-05-21 Make socket handling more robust. --- common/client.c: In DoClient() properly close the socket if an invalid packet was received. common/newclient.h: Increase the receive buffer size to 65535 bytes. This allows the client to receive any valid packet (even if no currently existing server is supposed to send such big packets). common/newsocket.c: Fix definitions of llevDebug and llevError to make error messages visible. Andreas Kirschbaum 2006-05-21 common/mapdata.c: fix unitialized variable. Ryo 2006-05-17 This commit adds client side support for the map2 & tick protocol commands. In additional the the necessary decode logic, more layers are also added to the map. -- common/Makefile.am/.in: Fix proto directive common/client.c: Add global tick variable. Add links to handle map2 and tick protocol commands. Update setup request sent to server to request to use the tick and map2 commands. common/client.h: Add additional fields to Animations structure. Increase MAX_MAP_OFFSET to match the value on the server. common/commands.c: Add parsing of return of map2 failures on setup command so that client can fall back. Add additional initializations for new fields in AnimCmd(). Change definition of NUM_LAYERS to match what the map1 command wants/expects. Add Map2Cmd() to decode map2 protocol command. Do some whitepsace clean of ExtSmooth(). Add TickCmd() common/init.c: Add seeing of random number generator. common/mapdata.c: Rewrite CLEAR_CELLS macro to handle additional layers. Clear animation data in expand_clear_face(). Change MAXLAYERS to MAP1_LAYERS since map2 increase MAXLAYERS. Add support functions for setting data in the map2 command. common/mapdata.h: Increase MAXLAYERS, add MAP1_LAYERS define to old number of layers. Add animation data to MapCellLayer. common/newclient.h: Add various defines related to the map2 data. common/proto.h: Rebuilt gtk/gx11.c: Add cleint_tick() to handle map animations. Update do_timeout() to not do animations if we are getting tick data. gtk-v2/src/config.c: Fix bug in config code where it wasn't enabling darkness when player switched back from no darkness mode to some mode. gtk-v2/src/main.c: Add client_tick() to handle animations. Update do_timeout() to not do animations if tick is set. gtk-v2/src/opengl.c: Fix drawing logic where objects which were visible but in which the bottom right corner was off the map was not being drawn - only a problem in opengl since it only draws the object when it finds the head, does not draw each piece. sound-src/Makefile.am/.in: Fix creation of sounds file - was using wrong variable name. x11/xutil.c: Add basic client_tick() that is a callback from the common code. MSW 2006-05-14 common/image.c: use the same image hashing algorithm that the server uses for archetypes, increase the table size to 8192 to reduce collisions Brendan Lally 2006-04-12 common/item.c: fix unitialized variable. common/p_cmd.c: fix memory leak. gtk/keys.c: fix memory leak. Ryo 2006-03-14 Yet more changes for gtkv2 clients, mostly aimed at making it usable on lower resolution displays. Window can now be resized to 800x600, added save window positions so it will remember where you moved the panes to (as well as root window size). Unrelated change to this is that now the inventory list is sortable like the metaserver and spell lists are - you can sort by name, weight, or by item type (click on the icon for item type). -- gtk-v2/gtk-v2.glade: Add new menu item for save window positions. Change statbar area so there is a pane between stat bar and stat notebooks. Change statbars so they resize smaller/larger. gtk-v2/src/callbacks.h: callback for on_save_window_position_activate() added. gtk-v2/src/config.c: Add on_save_window_position_activate() and load_window_positions() gtk-v2/src/interface.c: rebuilt. gtk-v2/src/inventory.c: Add LIST_TYPE column for sorting. Change table definitions so columns are sortable. gtk-v2/src/main.c: Add code to allow resizing down to 800x600. Add call to load_window_positions() gtk-v2/src/map.c: Try to set map size based on window size - save some memory. --- MSW 2006-03-10 More updates for the gtkv2 client. Add a config window to change the config options. Note this isn't quite as cluttered as the gtkv1 config window because only the options that affect the gtkv2 client are presented. --- common/client.h: Add CFG_LT_NONE to use instead of 0. common/init.c: Change 'sdl' config name to 'displaymode'. the CONFIG_ parameter was changed a while back, but still used this old name in the save file. gtk/config.c: Add some logic to handle 'sdl' legacy config mode. gtk-v2/gtk-v2.glade: Updated with new config window. gtk-v2/src/callbacks.h: rebuilt by glade-2 gtk-v2/src/config.c: Lots of new code to handle setting/getting of config values in config window. gtk-v2/src/gtk2proto.h: Rebuilt. gtk-v2/src/interface.c: Rebuilt by glade-2 gtk-v2/src/interface.h: Rebuilt by glade-2 gtk-v2/src/main.c: Add call to config_init() to initialize config window. MSW 2006-02-27 ------------------------------------------------------------------------------ sound-src/Makefile.in: replaced SOUNDDIR with SOUND_DIR, so that --with-sound-dir will work now Klaus Elsbernd 2006-03-07 common/p_cmd.c: Update command table for auto-completion to all (non-DM) server side commands. Also check for client side commands. Add a space after a completed command so the player can enter arguments. Andreas Kirschbaum 2006-03-04 Fix bug #1442523 (Crash when pressing TAB during login). Also fix undefined behavior due to overlapping strings passed to strncpy(). common/p_cmd.c: In complete_command() remove hack for x11 client and return NULL if no match was found. gtk/gx11.c, gtk-v2/src/keys.c, x11/x11.c: Adapt to changes in complete_command(). x11/x11.c: Replace strncpy() with memmove() to cope with overlapping strings. Andreas Kirschbaum 2006-03-04 Apply patch #1424583 (IPv6 patch for client) courtesy Christoph Hohmann - (reboot) common/client.c common/config.h.in Ryo 2006-02-26 Changes for 1.9.0: Fix server cache which was broken for some reason. common/metaserver.c Ryo 2006-02-25 Apply patch #1433271 (code-cleanup) by Stefan Huehner: Add const and static, remove unused variables --- Affected files: common/{client.c,commands.c,image.c,init.c,item.c,metaserver.c}, common/{misc.c,newsocket.c,player.c,proto.h,rcs-id.h,script.c,script.h}, gtk/{config.c,gtkproto.h,gx11.c,image.c,inventory.c,keys.c,map.c,png.c}, gtk/{rcs-id.h,sdl.c,sound.c,text.c,win32/soundsdef.h}, gtk-v2/src/{main.c,sdl.c}, x11/{png.c,rcs-id.h,sound.c,x11.c,xutil.c} Andreas Kirschbaum 2006-02-23 More improvements to the gtk-v2 client: - Add spell selection window similar to that in the gtk-v1 client. - Make it so that clicking on the headers in the metaserver and keybinding selection windows will result in table be sorted by that header. -- */Makefile.in: Rebuilt by automake. aclocal.m4: Updated by aclocal. gtk-v2/TODO: Remove things that have been done, add other things mentioned on mailing list that should be done. gtk-v2/gtk-v2.glade: Updated with new spell selection window. gtk-v2/src/Makefile.am: Add spells.c file gtk-v2/src/spells.c: File that handles spell selection window. gtk-v2/src/callbacks.h: Updated by glade gtk-v2/src/gtk2proto.h: rebuilt gtk-v2/src/interface.c: Updated by glade. gtk-v2/src/interface.h: Updated by glade. gtk-v2/src/keys.c: Add necessary calls to enable sorting of table by clicking on headers. gtk-v2/src/main.c: Add call to update_spell_information() if spell information has changed. gtk-v2/src/metaserver.c: Add necessary calls to enable sorting of table by clicking on headers. Convert the idletime and number of players columns to be ints - this makes the sort work as expected, and actually simplifies the code a little. gtk-v2/src/support.h: Rebuilt by glade. MSW 2006-02-22 common/player.c: Fix bug in that spell data wasn't being cleared when logging on. Thus, if you logged on as one character, then another, etc, it would just keep adding to the spell list, not being a representative list of spells character knows. MSW 2006-02-20 gtk/gx11.c: when no skill is sent in a addspell packet, display the skill as 'generic' in the Spell window Brendan Lally 2006-02-20 Improvements to the gtkv2 client - Add free form text box to metaserver selection window so server name can be manually entered, add keybinding interface window to client similar to one in gtkv1 client, and disconnect menu item to client. Note that this keybinding interfaces allows for ALT and META modifiers in addition to SHIFT and CONTROL, hence minor changes to the common code. --- common/client.h: Add meta_on, alt_on to player structure. gtk-v2/gtk-v2.glade: Updated with new elements - keybinding window, new menubar, text box for metaserver window. gtk-v2/src/callbacks.h: Generated by glade for new function prototypes gtk-v2/src/gtk2proto.h: rebuilt for new function definitions. gtk-v2/src/interface.c: Generated by glade for new features. gtk-v2/src/interface.h: Generated by glade for new function prototypes gtk-v2/src/keys.c: New initialization code for keybinding window. New KEYF_ modifiers. New handling for meta and alt keys. Many new callbacks for new code. gtk-v2/src/main.c: Remove unused extern declartions. gtk-v2/src/menubar.c: Add function for disconnect menu item. gtk-v2/src/metaserver.c: Add metaserver_connect_to() to handle common connection logic (pulled from on_treeview_metaserver_row_activated(). Add on_metaserver_text_entry_activate() for text entry server connections. MSW 2006-02-19 Apply modified patch #1432404 (Solve bug in watch stats script function) by Benjamin Lerman: make watch stats command work if more than one stat changes simultaneously. --- common/script.c: In script_watch() do not overwrite but append multiple watch stats commands. Andreas Kirschbaum 2006-02-17 Apply patch #1430279 (code-cleanup: const, static, etc) by Stefan Huehner. --- Affected files: common/{client.c,client.h,commands.c,def-keys.h,external.h, init.c,item-types.h,item.c,metaserver.c,misc.c,p_cmd.c,player.c,proto.h}, gtk/{config.c,gtkproto.h,gx11.c,help.c,inventory.c,keys.c,png.c,sdl.c,sound.c, text.c,win32/soundsdef.h}, gtk-v2/src/{inventory.c,keys.c,magicmap.c,main.c,sdl.c,sound.c,stats.c}, pixmaps/{all.xpm,close.xpm,coin.xpm,crossfiretitle.xpm,hand.xpm,hand2.xpm, lock.xpm,mag.xpm,nonmag.xpm,question.xpm,sign_east.xpm,sign_flat.xpm, sign_west.xpm,skull.xpm,unlock.xpm}, sound-src/{alsa9.c,cfsndserv.c,common.c}, utils/mdk.sh, x11/{sound.c,x11.c,xutil.c} Andreas Kirschbaum 2006-02-16 Apply patch #1429975 (patch to support port numbers in metaserver host names) by Marc Lehmann. --- common/metaserver.c: In metaserver_select() allow a port number in the server string. Andreas Kirschbaum 2006-02-12 common/metaserver.c, common/metaserver.h: Make cached_servers_loaded static since it is not used elsewhere. Andreas Kirschbaum 2006-02-12 gtk/inventory.c, gtk-v2/src/inventory.c, x11/x11.c: Make the message displayed for locked items more descriptive. Brendan Lally 2005-02-09 Remove unscrollable single column resistances option from gcfclient. Change the setting name in the config file and convert old values. Reduce MAX_BUTTONS to 33. Replace radio buttons with a single push button. Remove legacy lighting save code. Remove SHOW_RESISTS, use NUM_RESISTS instead (this reduces the blank space at the bottom of the resistances window). Call resize_resistance_table from get_message_display, remove duplicated code from the latter. Affected files: gtk/gx11.c, config.c common/init.c -- Remove coloured inventory and text options, as well as all supporting code for them. Make text always print in colour. Remove special code for initialising black and white monitors in cfclient, and change its background colour to colour number 9 (to not be the same as so many draw_info's from the server). Change colour number 9 to a pale grey to make text show up better. Affected files: common/client.h, init.c gtk/config.c, gtkproto.h, gx11.c, inventory.c gtk-v2/src/info.c, inventory.c x11/x11.c, x11proto.h, xutil.c Brendan Lally 2006-01-31 gtk-v2/src/opengl.c: For opengl mode, create a subwindow of the map window with the needed visual. On many systems, the visual that glXChooseVisual() returns doesn't match the default visual of the system, thus resulting in opengl not being able to create a context. MSW 2006-01-28 gtk/gx11.c: add a 'spell options' box to allow extra options to be passed to spells, make any mouse button change the spell description, not just the left one and reorder some gtk function calls to improve clarity Brendan Lally 2006-10-21 Fixed compilation for some compilers. gtk/gx11.c inventory.c Ryo 2006-01-19 common/commands.c: actually read the right amount of data on an updspell -- Add spell listing support to gcfclient and common, in particular: common/client.c: addspell, updspell, delspell function pointers, send spellmon in setup common/client.h: Spell struct, add attuned, repelled, denied to stats, add spelldata and spells_updated to player struct common/commands.c: parse stat details concerning spell paths, addspell, delspell, and updspell packet handling common/newclient.h: new flags related to this common/proto.h: function declarations gtk/gx11.c: make the client->spells menu option show a window displaying all spells known to the player, have a function update_spell_list to update it, add a call to this to do_timeout. Brendan Lally 2006-01-19 gtk/gx11.c: make skills display in a scroll pane, display all known skills, not just those with exp Brendan Lally 2006-01-17 gtk/inventory.c: grey out close button when it won't do anything Brendan Lally 2006-01-16 common/commands.c: In DeleteItem() properly handle more than one item. Andreas Kirschbaum 2006-01-13 x11/png.c: Add same workaround from gtk/png.c to make it work on 64 bit systems. MSW 2006-01-01 Made item's nrof uint32, like server-side. Fix a crash in get_number if nrof < 0 (not supposed to happen, server bug, but still). Modified files: common/commands.c item.c item.h proto.h Ryo 2005-12-27 gtk-v2/src/image.c: Remove call to free fog pixels (SDL) - with call in place, client crashes on double free in SDL mode after disconnecting from server. MSW 2005-12-11 gtk/{map.c,sdl.c}, x11/x11.c: General cleanup - just whitespace changes. Andreas Kirschbaum 2005-12-11 Apply patch 1352490 "newpickup rings/amulets client side" courtesy anonymous. Modified files: gtk/gx11.c Ryo 2005-11-12 common/player.c: Properly ignore received comc commands with invalid length. gtk/gx11.c, gtk-v2/src/image.c: Initialize smooth_face field when allocating pixmaps array. Andreas Kirschbaum 2005-11-02 Add support for newpickup PU_NOT_CURSED (ignore cursed items) flag. -- gtk/gx11.c: Add flag #define and menu entry. gtk-v2/gtk-v2.glade: Add menu entry. gtk-v2/src/{callbacks.h,interface.c}: Rebuilt. gtk-v2/src/gtk2proto.h: Add prototype for menu callback. gtk-v2/src/pickup.c: Add #define and menu callback function. Andreas Kirschbaum 2005-11-01 gtk/config.c: fallback to PIXMAP display mode when SDL is not built in. Ryo 2005-11-01 Fix bug #1288647 (typing text in password mode). Now hidden input (for password entry) is reliably turned off afterwards. -- common/command.c: Enable hidden input before printing the query; this allows the gtk client to enable it in his callback function. Also: reset hidden input mode after sending a reply to the server. gtk/gx11.c: Enable/disable hidden input in non-popup input area even if popup mode is enabled. Otherwise hidden input mode will not be disabled when switching to popup mode while entering a password. Andreas Kirschbaum 2005-10-29 common/p_cmd.{c,h}: Remove superfluous "const" from get_num_commands() return value. Andreas Kirschbaum 2005-10-29 gtk/text.c: Print MOTD into text window if using -nopopups mode. Previously it was discarded in -nopopups mode. Andreas Kirschbaum 2005-10-28 Documentation/Scripting.html: Clarify the repeat parameter for the issue command. Andreas Kirschbaum 2005-10-28 common/script.c: Make parameters passed to scripts work again. Andreas Kirschbaum 2005-10-28 common/script.c: fix Win32 that didn't detect end of script correctly. Ryo 2005-10-16 Avoid using c++ reserved words, in case one wants to link a c++ program to client.h Alex Schultz 2005-09-22 common/{client.h, init.c}, gtk/{config.c, gx11.c}: Add configuration option to allow clients to timestamp incoming coloured messages. This implements RFE #1090049 Brendan Lally 2005-09-22 gtk-v2/src/image.c copy part of gtk1 image.c to fix a compile issue on mac. Brendan Lally 2005-09-21 common/external.h: add definition of addsmooth. gtl/inventory.c: explicit cast of parameters. Ryo 2005-09-10 configure, configure.in: Move check for X11 early in the process so that gtk dependencies on them should be resolved. MSW 2005-09-05 x11/x11.c: Fix similar problem for x11 client: need_update needs to be cleared too. Andreas Kirschbaum 2005-09-04 gtk/map.c: need_resmooth needs to be cleared too, else drawing routines called all the time. common/misc.c: LOG buffer made static to avoid stack creation/destruction. common/script.c: removed unused variable/call. gtk/gx11.c: no need to refresh game area when window gets focus. gtk/gx11.h: add cache fields for listinfo. gtk/inventory.c: don't refresh list labels if not changed. common/mapdata.c: remove parasite #define NDEBUG gtk/image.c: if icon and map scales are the same, just gdk_pixmap_ref image and mask. This saves graphical resources and time. gtk/map.c: don't draw black rectangle if no face with transparency. Ryo 2005-09-04 *Makefile.in, aclocal.m4, configure: Rebuilt. Andreas Kirschbaum 2005-09-03 Fix bug #1102991 (Duplicate grapical display of the same monster): common/Makefile.am: Add new files mapdata.c and mapdata.h. common/{client.c, commands.c}: Tell mapdata module the current display size. common/commands.c: Remove functions to handle map updates. Rewrite map1_common() to pass information into mapdata module. common/init.c, gtk/gx11.c: Add new config options -mapscroll and -nomapscroll to enable/disable scrolling the map view with bitmap operations. common/mapdata.[ch]: Add new module to handle all updates to the_map. gtk/gx11.c: Remove code for #if ALTERNATE_MAP_REDRAW. Initialize question mark face for fog of war. Remove code to allocate the_map. gtk/image.c: Do not clear the_map in reset_image_data() anymore. gtk/map.c: Move code to update map data into mapdata module. draw_pixmap(): New function to draw one face. drawsmooth(): Check correct layer instead of fixed layer zero. Fix out of bounds array access. display_mapcell(): New function to draw one cell. gtk_draw_map(): Move map drawing code into display_mapcell(). gtk/sdl.c: Basically the same changes as in gtk/map.c gtk-v2/src/image.c: Basically the same changes as in gtk/gx11.c. gtk-v2/src/main.c: Add config options -smooth/-nosmooth to enable/disable smoothing. Remove code to allocate the_map. gtk-v2/src/map.c: Basically the same changes as in gtk/map.c. gtk-v2/src/opengl.c: Fix out of bounds array access. Initialize question mark face for fog of war. gtk-v2/src/sdl.c: Basically the same changes as in gtk/map.c. x11/x11.c: Implement map scrolling by using XCopyArea(). Add config options -mapscroll/-nomapscroll to enable/disable this. Remove code to allocate or clear the_map. Add new function display_mapcell() to draw one cell. Move map drawing code from display_map_doneupdate() into display_mapcell(). Remove two pixel border around map window; is was used inconsistently, and the window size was four pixels too small. x11/xutil.c: Move code to update map data into mapdata module. Andreas Kirschbaum 2005-08-31 Fix bug #1245535 (negative grace showss up as positive amount): gtk-v2/src/stats.c: Clip negative stat values to zero. Andreas Kirschbaum 2005-08-30 Fix sound compilation so it only tries to compile alsa9 helper if we in fact have alsa 9 libs. */Makefile.in: Rebuilt configure.in, configure: Add ALSA9_TARGET, replacing SOUND_TARGETS which was no longer being used. sound-src/Makefile.am: add EXTRA_PROGRAMS line for cfsndserv_alsa9 so don't get errors from automake, add @ALSA9_TARGET@ to bin_PROGRAMS. MSW 2005-08-28 gtk/config.c, gtkproto.h, gx11.c, inventory.c: Commit patch #1265199 from Kevin Rudat to fix client crash when using split window mode Brendan Lally 2005-08-21 common/misc.c, gtk/{gx11.c,sdl.c,text.c}, gtk-v2/src/sdl.c, x11/sound.c: Fix non-Ansi C89 code: remove "inline" function specifier, replace "//" comments. common/metaserver.c: Fix buffer overflow in metaserver_get_info(). x11/x11proto.h, x11/xutil.c: Use correct parameter type "uint16" for addsmooth(). Andreas Kirschbaum 2005-08-14 This commit adds full automake support for the client - previously, only the gtk-v2 directory used automake, rest was Makefile.in - now everything is automake - makes maintenance and distributions easier. -- common/Makefile.am gtk/Makefile.am help/Makefile.am pixmaps/Makefile.am sound-src/Makefile.am utils/Makefile.am x11/Makefile.am pixmaps/Makefile.in utils/Makefile.in help/Makefile.in: New Makefiles Makefile.am, Makefile.in: Removed unneeded rules, move pixmap, help, util handling to makefiles in their own directories. configure, configure.in: Update to include pixmap, help, util as directories. gtk-v2/Makefile.am, gtk-v2/Makefile.in: Clean up some rules in this makefile. common/Makefile.in, gtk/Makefile.in, sound-src/Makefile.in, x11/Makefile.in: Rebuilt as part of automake. gtk-v2/src/Makefile.am, gtk-v2/src/Makefile.in: Add banner copyright, remove uneeded rules. MSW 2005-08-11 ------------------------------------------------------------------------------ Changes for 1.8.0: Makefile.am, Makefile.in: Add missing pixmaps, change CHANGES to ChangeLog, update archive directive so it works. aclocal.m4: updated configure, configure.in: Updated for 1.8.0 release. Remove gnome/Makefile from list of Makefiles to create. gtk-v2/Makefile.am, gtk-v2/Makefile.in: Add archive directive. gtk-v2/src/Makefile.{am|in}: Add missing soruces to list so that archive works correctly. Add archive directive. MSW 2005-08-10 gtk/keys.c: don't select text in widget under Windows. Ryo 2005-07-30 gtk/gx11.c: fix a crash if closing login window. Weird behaviour, but no crash. Ryo 2005-07-29 gtk/image.c: Remove stray '+' at beginning of line. Andreas Kirschbaum 2005-07-21 x11/x11.c: Fix crash if display cannot be opened. common/script.c: Properly terminate string with '\0' in script_init(). Andreas Kirschbaum 2005-07-18 gtk/sdl.c, gtk-v2/src/sdl.c: Fix printf like format specifiers. Andreas Kirschbaum 2005-07-16 common/init.c: Win32 should use %APPDATA% instead of . for home directory. Ryo 2005-07-10 Bulk of this change is the addition of a pop up window in the gtk-v2 client for metaserver selection, as well as other updates. The files to the common area was really to pull the metaserver defines and data structures from the C file to a header file so that the gtk-v2 code can access them: -- AUTHORS: New file, required by automake, data pulled README file. NEWS: New file, required by automake. Makefile.in, aclocal.m4: Rebuilt README: Remove author info from this file, move it to AUTHORS. common/Makefile.in: add metaserver.h file common/metaserver.h: New file containing metaserver defines and structures. common/metaserver.c: Pull out defines/structures from this file, moved to metaserver.h. Have it strip packets/byte count info from comment section that metaserver reports. gtk-v2/Makefile.in: Rebuilt. gtk-v2/gtk-v2.glade: Added new metaserver window. gtk-v2/src/Makefile.am: Add metaserver.c as a standalone file that gets compiled gtk-v2/src/Makefile.in: Rebuilt gtk-v2/src/callbacks.h, gtk-v2/src/interface.c, gtk-v2/src/interface.h: Updated by glade2 gtk-v2/src/main.c: Remove metaserver.c inclusion. Initialize cached_server_file. Change metaserver selection/display code. gtk-v2/src/metaserver.c: Lots of new code - have it display window, handle selections, connect to server, etc. MSW 2005-07-04 gtk-v2/src/info.c: Remove extra lines of code for scrolling. Have newlines be inserted in the correct place for the color info tab. gtk-v2/src/inventory.c: Remove call to check to display object in inventory tab for container objects - if we show the container object, so all objects within the container (bug 1226968) gtk-v2/src/keys.c: Move initialization of global widges to before loading keybindings - otherwise, they can end up not being initialized. MSW 2005-06-29 Add inventory animation to the gtk2 client. gtk2proto.h: rebuilt inventory.c: Add new function that animates inventory. Have draw_table() take a second param that determines if it is doing an animation run or just a normal draw. main.c: Move PACKAGE_DATA_DIR to be within WIN32 defines. Add call to inventory_tick() in do_timeout() MSW 2005-06-26 common/metaserver.c: wrong number displayed for cached servers. Ryo 2005-06-25 configure.in, configure: Turn of the use of dmalloc as the default - if dmalloc is disabled, it has to be intentionally set. gtkv2 client runs dog slow if dmalloc is used, so that isn't a good default common/item.c: Fix bug that resulted in the item names not being updated properly - bug introduced in patch 1197437. MSW 2005-06-04 crossfire-client.spec, gnome/Makefile.in, x11/Makefile.in: Patch from Kari Pahula to fix manpage paths. gtk/gx11.h: Patch from Kari Pahula to remove incorrect variable declaration. Andreas Kirschbaum 2005-06-01 Committed patch #1197437 courtesy Kevin Rudat (krudat). This patch moves inventory-related functions in GTK client to one specific file. Also makes inventory refresh less often. Affected files: * common: client.h item.c item.h p_cmd.c proto.h * gtk: config.c gtkproto.h gx11.c gx11.h inventory.c Makefile.in * x11: x11.c x11proto.h common/metaserver.c: add server cache. gtk/gx11.c: initialize server cache filename. Ryo 2005-05-23 gtk/gx11.c: Windows has player-specific keys, get'em (was broken with new login window) Ryo 2005-05-12 Add newpickup support to the gtkv2 client. Didn't add old support (still available by specific commands) as I think the interface gets confusing to have them both - would be better to extend newpickup logic if necessary to support anything old pickup does that newpickup doesn't. -- gtk-v2/Makefile.in: Rebuilt gtk-v2/gtk-v2.glade: Add menu options for newpickup gtk-v2/src/Makefile.am, gtk-v2/src/Makefile.in: Add pickup.c file gtk-v2/src/callbacks.h, gtk-v2/src/interface.c: Rebuilt by glade-2 gtk-v2/src/pickup.c: New file - handles pickup logic. MSW 2005-04-17 gtk/image.c: Apply patch from bug 1120881 that fixes pointer operations on netbsd/macppc. Changed code still works on linux/x86. MSW 2005-04-16 Improve behaviour of information windows on gtkv2 client - before this patch, they would always scroll to bottom when getting new output, making it difficult to look at shop listings or other long listings that require going back in the scroll buffer. With this change, if the buffer isn't at the end, the scroll position isn't changed. IF it it at the end, it keeps it at the end. -- gtk-v2/gtk-v2.glade: Chane scrolledwindows used by the textbuffers to have a meaningful name. gtk-v2/src/info.c: Add code that gets position of scroll bar (adjustment) and compares it with maximum, and if not at end, don't scroll window. gtk-v2/src/interface.c: Rebuilt. MSW 2005-04-11 Fix so that magic map works properly on the gtkv2 client. gtk-v2/gtk-v2.glade: change name of map notebook to map_notebook. Add signal to handle expose events of the magic map area. gtk-v2/src/callbacks.h: Rebuilt with addition of expose callback. gtk-v2/src/interface.c: Rebuilt with addition of expose, change of name. gtk-v2/src/magicmap.c: Have magic map switch the notebook page to the magic map page to ensure widget is realized - also good for expected behaviour. Add some checks for null values so if user switches before getting magic map data, doesn't crash. Add check in magic_map_flash_pos() to see if still on the magic map notebook page. Add expose callback. gtk-v2/src/main.h: Add MAGIC_MAP_PAGE which defines which notebook page is the magic map one. gtk-v2/src/map.c: Have it look up the map_notebook widget. MSW 2005-04-05 Various minor bugfixes: configure.in, configure: Add warning message if we can't find gtk+ 2.0 or later, but continue configure process instead of exiting. common/misc.c: Fix code so that it compiles with older C compilers. gtk-v2/src/map.c: Change code on need_recenter_map() - use MAX_MAP_OFFSET instead of hard coded value of 2 - found a crash here when running around the world map - could have been caused by a big image and/or the fact my character moved 2 spaces in one tick. either way, this change shouldn't impact things, as it is seldom the virtual map needs to be recentered. MSW 2005-03-27 This patch fixes a few memory leaks related to image caching in all clients. common/image.c: Declare facetoname[] as static. Add all code accessing this array. Print warning if image cannot be created. gtk/gx11.c, gtk/image.c, gtk-v2/src/image.c, x11/x11.c, x11/xutil.c: Remove code accessing facetoname[]. gtk/gx11.c, gtk-v2/src/main.c, x11/x11.c: Always call init_cache_data() to initialize pixmaps[] array. gtk/image.c, gtk-v2/src/image.c, x11/png.c: Reject invalid face numbers and fix resource leak in create_and_rescale_image_from_data(). gtk/image.c, gtk-v2/src/image.c, get_map_image_size: Pretend invalid faces to be of size 1x1 in get_map_image_size(). gtk-v2/src/image.c: Properly free opengl resources in free_pixmap(). Fix resource leak when freeing old pixmaps in reset_image_data(). x11/png.c: Properly free resources if an error occurs. x11/x11.c: Ignore invalid face numbers. x11/x11.h Remove duplicate definition of MAXPIXMAPNUM and facetoname[]. x11/xutil.c: Initialize size of pixmaps[0]. Andreas Kirschbaum 2005-03-27 gtk-v2/src/map.c: Fix typo to make it compile without opengl. Andreas Kirschbaum 2005-03-26 Main change of this is addition of opengl drawing for the map in the gtk-v2 client. On my system, the opengl code is about 10 times faster than the sdl code was, making it so I can turn on all the bells and whistles (smoothing, best lighting) and still use less than 10% cpu time. As part of this, I redid the smoothing logic, so the client now requires a new server for smoothing to work (needs push logic, as client won't request smoothing info as that adds a lot of complication). This change was done because the old smoothing code wasn't that efficient - now, we store the smoothing face along with the face it smooths, so finding the smoothing info is much faster. -- configure.in, configure: Add check for -lglut - indication we have opengl libraries available. common/client.h: Remove Smooths struct. Change CONFIG_SDL to CONFIG_DISPLAY, and add CFG_DM_... to denote different display modes, since there is more than just sdl and not sdl now. common/commands.c: Don't have SmoothCmd try to update what spaces need to be redrawn - for opengl, it doesn't care about that, and for most other maps, it will figure it out when it needs to redraw anyways. common/config.h.in: Addition of HAVE_OPENGL line. common/image.c: Remove getsmooth() - rely on push logic. common/init.c: Update want_config[CONFIG_SDL] to want_config[CONFIG_DISPLAYMODE] gtk/config.c: Change access to CONFIG_DISPLAYMODE gtk/gx11.c: Change access to CONFIG_DISPLAYMODE. Add -smooth command line option. gtk/gx11.h: Add smooth_face to PixmapInfo struct. gtk/image.c: Change access to CONFIG_DISPLAYMODE. When getting new PixmapInfo struct, use calloc so we are sure all fields are initialized to zero. Add addsmooth(). gtk/map.c: Change access to CONFIG_DISPLAYMODE. Change how we access smooth face info. gtk/sdl.c: Change how we access smooth face info. gtk-v2/src/Makefile.am, gtk-v2/src/Makefile.in: Add addition of OPENGL_LIBS to link libs. Add opengl.c file. gtk-v2/src/config.c: Add image.h include. gtk-v2/src/gtk2proto.h: Rebuilt. gtk-v2/src/image.c: Change access to CONFIG_DISPLAYMODE. Add hooks for opengl image generation. Change call for pixmap creation from malloc to calloc. Add addsmooth(). gtk-v2/src/image.h. If we have opengl, include GL/gl.h. Add fields for opengl texture maps. gtk-v2/src/info.c: Update so text line wraps if it is too long. gtk-v2/src/inventory.c: Add checks to make sure object face is valid before trying to draw. In icon mode, add code to cleanup old fields (if you drop an item, it wouldn't erase the list item in the list). Also, free callbacks, as they effectively stack, and we were using incorrect object pointers (pointer from first callback, which didn't match current one). gtk-v2/src/keys.c: Add image.h to includes. gtk-v2/src/main.c: Add image.h to includes. Change access to CONFIG_DISPLAYMODE. Add -opengl command switch. Remove +sdl and popups command line options. Relocate setup of cache call setup to after we know all windows have been created. gtk-v2/src/map.c: Change access to CONFIG_DISPLAYMODE. Add opengl drawing hooks. Change access for smooth info. Implement button press code for map window (basically grabbed from gtk/map.c) gtk-v2/src/opengl.c: New file containing opengl draw code. gtk-v2/src/png.c: Remove some unused code resulting in compile warnings. gtk-v2/src/sdl.c: Remove some commented out code. Change access method for smoothing code. x11/xutil.c: Change access to CONFIG_DISPLAYMODE. Add addsmooth() function. MSW 2005-03-20 Applied patch #1161817 (cowboyatheart): Add wands/staves/rods/horns to new pickup (client). gtk/gx11.c: add new 'magic devices' menu option. Ryo 2005-03-13 More improvements for the gtkv2 client, mostly adding SDL support: gtk-v2/TODO: updated gtk-v2/src/logfile: Removed - don't need dmalloc logfile. gtk-v2/src/Makefile.am, gtk-v2/src/Makefile.in: Change program name from 'gtk-v2' to 'gcfclient2'. Add sdl.c to list of files. gtk-v2/src/gtk2proto.h: Rebuilt gtk-v2/src/inventory.c: Fix bug in show_nonmagical() (which corresponds to inventory tab) - was showing unpaid objects, not nonmagical objects. gtk-v2/src/main.c: Remove time_map_redraw declaration from function, since it is declared in map.c. Change map logic to draw when we finish processing network data. Change client naem as it reports itself to server to GTK2 ... Client. gtk-v2/src/map.c: Add map_updated variable which is set by display_map_doneupdate - used by map draw function to know if anything has changed. Clean up some formatting, remove unused code. gtk-v2/src/sdl.c: New file containing sdl support. MSW 2005-03-07 Commit for GTKv2 client - please read gtk-v2/README before using this client. The bulk of the changes are limited to the gtk-v2 directory (addition), but some changes elsewhere as related to using automake. You will need to run configure for the gtk-v2 client to be built (it should be built automatically if you have the needed libraries) -- Changelog: Replaces CHANGES file to meet automake standards. Makefile.am: New file for use with automake. Makefile.in: rebult from Makefile.am aclocal.m4: Updated with macros to check for gtk-v2. configure.in: checks for gtk-v2 added. Chane SUBDIRS to CF_SUBDIRS as using SUBDIRS causes conflicts. utils/config.guess, utils/config.sub, utils/missing: Updated as part of automake changes. gtk-v2/*, gtk-v2/src/*: Files related to gtk-v2 client. MSW 2005-03-01 crossfire-client.spec: Update for 1.7.1 release, make some other changes that better match my system since I don't think anyone else is using it. gtk/Makefile.in: Add crossfire-client.desktop to list of files to add to distribution. README.rpm: removed - had info that didn't really apply to me making RPM files configure.in, configure: Add --disable-dmalloc option to configure. MSW 2005-02-28 ------------------------------------------------------------------------------ Changes for 1.7.1: configure, configure.in: Rev for 1.7.1 release sound-src/Makefile.in: Add files to EXTRA_DIST, fix typo so that make arhive works. MSW 2005-02-27 Add 'show' command back in to list of commands. common/external.h: Change prototype of command_show() to match p_cmd.c prototype. common/p_cmd.c: Add 'show' to command dispatch table. gtk/gtkproto.h: rebuilt gtk/gx11.c: change declaration of command_show() to take const char *. gtk/sdl.c: Make drawsmooth_sdl() static so it won't be put into gtkproto.h file, which causes compilations to fail. x11/x11.c: change declaration of command_show() to take const char *. x11/x11proto.h: rebuilt MSW 2005-02-26 common/metaserver.c: Once we have read in limit of number of metaservers, don't do anymore processing - otherwise, client just crashes. MSW 2005-02-19 Sound cleanup and redo for ALSA9. The bulk of this is to break out the alsa9 code from the cfsndser.c and compile its own separate cfsndserv-alsa9 executable. Add options to config file/gtk client to support setting which sound daemon to use. Note that ALSA9 sound now works all properly - significant changes had to get made to the code for this to happen. -- configure, configure.in: The existence of ALSA9 sound does not preclude compilation of OSS sound support (or others for that matter), so change the logic accordingly to set variables only used for ALSA9. Add SOUND_TARGETS that can be used by the makefile, change logic of setting SUBDIRS so we don't put sound-src in multiple times. common/client.c, common/client.h: Add sound_server variable. gtk/config.c: Add support for loading/saving sound_server line in gdefaults file. gtk/gcfclient.man: Update about -sound_server option. gtk/gx11.c: Update help and command line processing to support -sound_server option. gtk/sound.c: Change initialization of sound pipe to use sound_server variable (set by options above) instead of hard coded cfsndserv. Path can be either be absolute or relative to to bindir. Also change code so that pipe is set for non blocking output, so if the sound daemon gets hung up, won't effect rest of the client. sound-src/Makefile.in: Redone to handle cfsnserv-alsa9 binary. uses SOUND_TARGETS to know what to build. sound-src/cfsndserv.c: Remove all ALSA9 code, since that is now in alsa9.c file. sound-src/alsa9.c, sound-src/common.c: Nwe files - alsa9.c contains logic for playing sound. common.c is common routines. Idea being that other code could get pulled from cfsndserv.c and use the common.c routines for parsing sound file, etc. MSW 2005-02-13 common/script.c: fix broken script with a parameter change. gtk/help.c: use 'const gchar' instead of 'gchar' as widget text. gtk/win32/config.h: snprintf => _snprintf Ryo 2005-02-12 Makefile.in, common/Makefile.in, gnome/Makefile.in, gtk/Makefile.in, sound-src/Makefile.in, x11/Makefile.in: Add ${DESTDIR} prefix for installation into other directories. Patch from sourcefore #1061895 MSW 2005-02-09 common/external.h, common/init.c, common/player.c, common/proto.h, common/script.c, common/script.h, common/p_cmd.c (new file), common/p_cmd.h (new file), gtk/gtkproto.h, gtk/gx11.c, gtk/help.c (new file), gtk/keys.c, help/chelp.h, x11/x11.c, x11/x11proto.h, x11/xutil.c: Install command table for client side commands - makes adding commands a little easier, but also makes it easier to have better help. Bulk of the changes are in p_cmd.c file, which pulled some code out of player.c. Other source files modified to clean up function parameters (all now take const char * as the command options). Patch from sourceforge 1022245, with some work done by me. Addition fix in gtk/keys.c unbind - buffer overflow would result if unbinding very long binding. MSW 2005-02-09 common/client-types.h: use char instead of __int8 under Windows. common/commands.c: use 'const' for strings when possible. common/misc.c: use 'const' for strings when possible. common/newsocket.c: use 'const' for strings when possible. common/player.c: use 'const' for strings when possible. common/proto.h: use 'const' for strings when possible. gtk/gx11.c: use 'const' for strings when possible. gtk/keys.c: fix a buffer overflow in 'unbind' when displaying keys. Use 'const' for strings when possible. gtk/win32/config.h: don't define 'G_DISABLE_CONST_RETURNS' anymore, strings are now correctly const. Ryo 2005-02-05 Makefile.in: Fix up distclean directive to go into all directories. configure.in, configure: Fix configure so the --enable-feature and --disable-feature flags follow proper standard (from patch on sourceforge). Add check for -lossaudio. Modify check for -lSDL_image library - don't require it for SDL support (if we have it, we'll use it, but for newer versions of SDL, it doesn't seem to exist anymore) common/client-types.h: Minor formatting change. common/script.h: add defines for PF_LOCAL and AF_LOCAL if they are missing. gtk/Makefile.in: Install man page into section 6. sound-src/Makefile.in: Fix up depend command - had wrong variable. Fix up distclean to remove automatically generated files. x11/Makefile.in: Install man page into section 6. MSW 2005-02-04 gtk/gx11.c: send text first, then close popup. Else won't work under some circumstances, text is empty. Fix party password dialog containing only ':' (missing case in dialog handling). Ryo 2005-01-07 common/script.c: add 'signal.h' header, needed for NetBSD. gtk/keys.c: fix buffer overflow when binding a very long command. This fixes bug #1085729. gtk/win32/config.h: fix S_ISDIR macro, even if not used. Ryo 2004-12-21 gtk/win32/config.h: Add parentheses around arguments of sleep and usleep macros. Andreas Kirschbaum 2004-09-19 common/script.c: warn when script start failure (Linux), patch courtesy Kevin Rudat. Check there actually is a parameter to 'script', else that'd crash nicely. Ryo 2004-08-16 gnome/gnome.c, gtk/gx11.c: Fix improper access to history buffer variable. Andreas Kirschbaum 2004-05-24 gtk/gx11.c: Comment out printing of size when we receive config event. gtk/image.c: Remove some superfluos LIL_ENDIAN code that would never be used because it was already in an #ifdef LIL_ENDIAN/#else block. Fix up freeing of data - need to free the pixel info before freeing the surface, don't free the fog pixels since SDL will do that for us. MSW 2004-05-15 gtk/image.c: Patch from bug list to fix compilation on big endian machines. MSW 2004-05-11 gtk/gx11.c: Fix configure_event() to only allocate new data structures if the size of the map area has in fact change. This fixes a major memory leak, as it seems gtk erroneously generates configure events. gtk/map.c: Clean out some commented out code, clean up the formatting of the draw_map function - no actual code change. MSW 2004-05-08 ------------------------------------------------------------------------------ Changes for 1.7.0: common/client.h: synced client version to 1023. gtk/win32/config.h: changed version numbers. gtk/win32/gtkclient.nsi: added scripting documentation. Checks for GTK. gtk/win32/Win32Changes.txt: updated. Ryo 2004-04-25 gtk/win32/porting.c: tweaked SDL's sound support to use panning information. Added missing header files. Ryo 2004-04-11 gtk/win32/porting.c: implemented basic sound with PlaySound. gtk/win32/gtkclient.dsp: added winmm.lib to link list. Ryo 2004-04-11 This is related to Win32 scripting. It now works correctly thanks to archaios's patch. I tweaked it some, so if it doesn't work, my mistake :) common/metaserver.c: call 'script_killall' under Win32 when exiting. common/script.c: some Win32-specific magic to make it work. common/script.h: add Win32-specific function. gtk/gtkproto.h: Win32-specific function. gtk/gx11.c: call the scripting functions for Win32, not like other platforms. Ryo 2004-04-04 common/metaserver.c: use 'draw_info' to report being unable to connect to metaserver. Also changed failure color from red to black, so it appears after the 'trying to connect' even in split window mode. gtk/gx11.c: correctly refresh text windows so failure messages appear. Ryo 2004-03-12 gtk/keys.c: Windows now uses default 'keys' file if player file not found for key loading. Ryo 2004-03-04 configure.in: Remove checks for gnome libraries, since we no longer use gnome/build a gnome client. aclocal.m4: downgrade requirement for needed autoconf version. MSW 2004-02-05 common/init.c: changed 'printf' to 'LOG' for HOME Win32-warning Ryo 2004-02-01 common/image.c: fix stupid crashing mistake. common/rcs-id.h: remove ; after #define gtk/rcs-id.h: remove ; after #define gtk/sound.c: #ifndef WIN32 for cfsndserv specific parts Ryo 2004-01-30 all .c files: all Makefile.in: all rcs-id.h: Basic logging is now complete. All console messages sent by client are now sent to LOG(). All source files versions have are sent to LOG() at startup too (except for the still non compilable gnome client!). Gtk client can show the Logs in 'Help -> Report a Bug' along with a small doc on how to bug report Tchize 2004-01-30 Documentation/ Have added a Documentation directory. It contains a first basic how-to related to client side scripting with two examples. Tchize 2004-01-29 Those fixes are all Win32-specific, except the last one on keys.c common/commands.c: Use correct Win32 function for closing socket. common/image.c: Added missing headers, use correct mkdir syntax. Change a call to 'read', to be on the safe side. common/misc.c: Added missing headers, use correct mkdir syntax, stub functions not yet ported. common/player.c: Use correct Win32 function for closing socket. gtk/gx11.c: Disabled bug window font setting, as GTK2 apparently doesn't use the same fonts. Use correct function for closing socket. gtk/keys.c: Don't display 'Key unused' for left-alt & windows key (as they are often used to switch away from CF). Also fix a potential use of a variable not initialized (rare line corruption case) Ryo 2004-01-29 common/client.c: Win32-specific fixes. common/metaserver.c: small Win32 fixes, explicitely cast meta_sort in qsort. gtk/config.c: Win32-specific fixes. gtk/map.c: added Win32-specific header. Ryo 2004-01-27 common/item.c: check supplied argument to remove_item_inventory is not NULL. Ryo 2004-01-25 gtk/map.c, gnome/map.c: Apply patch by kirschbaum@myrealbox.com which fixes improper coordinate comparision. gtk/gx11.c: Remove some unused declarations. gtk/map.c: always set the cleared flag as spaces come into view. MSW 2003-11-28 gtk/gx11.c: fixed invalid level display for skills under Win32 (int64 issue, %lld doesn't work under Win32) Also removed dumb Win-newlines from previous commits. Ryo 2003-11-22 common/client.h: readded (Win32 only) player's name. Used for specific key bindings file loading/saving. common/script.c: made dummy functions to correctly compile under Win32. Actual implementation will come someday :) Ryo 2003-11-10 x11/x11.c: Fix button pressing in the game window so it properly deals with non standard size maps. MSW 2003-10-26 Those fixes are for Windows compilation ('for Windows' is implicit everywhere). Most code was borrowed from Philip aka Somebdy's previous GTK port. Note: the changed code is embedded in #if(n)def WIN32 / #endif. --- Win32-Readme.txt: added to tell about supported clients under Windows. common/client-types.h: Windows-specific typedefs. common/client.c: missing include fixed, changed fcntl for ioctlsocket. common/image.c: forced opening of files in binary mode to avoid bad troubles. common/init.c: make sure HOME is set, to correctly find paths. common/metaserver.c: made it work, with a specific function (fgets can't work). common/newsocket.c: fix GetInt64_String. Make write_socket and SockList_ReadPacket work. gtk/config.c: use correct header file gtk/gx11.c: fix bad header files. Fix g_free() / free() issue. Catch player's name to load specific keys. Fix score display issue. Other specific stuff. gtk/gx11.h: fix undefined X-Window specific type (Window). gtk/image.c: fix headers. gtk/keys.c: fix headers. Key file uses player's name, when known. Fix input issue with 'entrytext'. Fix missing KeyCode type. gtk/map.c: fix headers. gtk/png.c: fix headers. gtk/win32: Windows specific files. Ryo 2003-10-26 common/client.h, common/newsocket.c: Remove 'extern in errno' lines - errno.h is included, which takes care of the problem. MSW 2003-10-25 ------------------------------------------------------------------------------ Changes for 1.6.0: common/commands.c: Clean up some formatting. common/item.c: Add num_free_items() to try and help see some memory laakage. common/player.c: Add num_free_items command which calls above routine. gtk/gx11.c: Fix movement/firing by using mouse pointer. Map size was hard coded in, so didn't work correct if non standard map size was used. MSW 2003-10-09 Add an option to the gtk client which controls what happens when you use apply to cycle through containers. It used to be closed->applied->open->applied. Now, if you select the config option, it goes closed->applied->open->close->.. common/client.h: Add new config variable. common/commands.c: Remove some dead commented out code. common/init.c: Update save name for config value. gtk/config.c: Update to have menu option in config window. gtk/gx11.c: Change close_container() to send/not send apply based on setting. Add close_container_callback() which is used for the 'close' button, which has to always send the apply command. MSW 2003-10-08 common/commands.c: improve expand_face() - there was the problem if multipart object that overlapped not always being drawn properly. This is because expand_face would basicaly put the first one it received on the lower stack - this is fine if you came from above, but was incorrect if you approached from the south. expand_face() now checks to see which one should overlap the other, based on where the coordinates would put it. MSW 2003-10-07 Bulk of this commit is to fix big image support for the X11 client. common/client.h: Add a couple new defines to denote how big the largest image may be, minimum reasonable map size for the_map structure, and how far off the map a head could be. x11/png.c: Remove hard coded values of images being 32 pixels wide/high. Also, store away actual size of images, needed for big image stuff to get filled in properly. x11/x11.c: Add an error handler to make it easier to catch bugs (gets real stack trace instead of the program exiting). Fix up the gen_draw_face to properly draw big images, change call to allocate map to pass in new larger values. x11/x11.h: Add width, height values to Pixmap data structure. x11/xutil.c: Change the routine to recenter virtual map some - we need to take into account that there can be big images, so include that value in when seeing if we are too close to the map edge. MSW 2003-10-05 common/commands.c: Add call to reset_player_data() - necessarily for data to be sanely displayed for next time player logs in. common/init.c: add reset_player_data - clears out skill data. gtk/gx11.c: Add code to erase skills that current player doesn't know. Some alternative map drawing code also in place, but disabled. gtk/gx11.h: Add ALTERNATE_MAP_REDRAW define. gtk/sdl.c: Add check for ALTERNATE_MAP_REDRAW. MSW 2003-09-12 common and gtk: Client understand the smoothing protocol and the gtk client is able to draw the smoothing information. Tchize 2003-07-08 gtk/gx11.c: Change skill experience display - instead of skill name and exp/level being the same string and same table element, add additional columns, so the skill name is in one, the exp/level in another. IMO, this makes for cleaner display, as the exp totals for the different skills then line up better. Also, fix some display bug when new skills need to be displayed. x11/x11.c: Fix bug where stipple patterns where being improperly displayed/retained in fog of war and darkness modes. x11/xutil.c: always set cleared and need_update flag for map scrolls - fixes bug of big objects (griffons for example) not being drawn properly. MSW 2003-05-25 x11/x11.c: Add darkness and fog of war tiling stipling, so it is now clearer what spaces are dark and which spaces are fog of war spaces. Add -fogofwar and -nofogofwar command line options. MSW 2003-05-18 Bulk of this change is to support the upcoming split skill experience system. skill names are now sent to the client. Backwards compatibility with older servers is in place - however, the client will now only show those skills which the player has a non zero exp total in the stat window. -- configure, configure.in: Add checks for size of long and long long - needed to have 64 bit types. common/Makefile.in: modify proto to define CPROTO so we can avoid including proto.h when cproto runs. common/client-types.h: Add checks to define uint64/sint64 types. common/client.c: Modify setup command to send 'exp64' request. Change definition of skill_names. common/client.h: Make MAX skilled tied in with CS_NUM_SKILLS. update exp and skill_exp to 64 bit types. Don't include proto.h if CPROTO is defined. common/commands.c: Add get_skill_info() which gets skill number->name mapping. Add code to handle exp64 setup request/failure. Update StatsCmd to support 64 bit exp for new skill mapping, as well as 64 bit overall exp for player. common/config.h.in: Add SIZEOF_LONG and SIZEOF_LONG_LONG for autoconf. common/external.h: Add menu_clear() protoype. common/init.c: Add code to init skill values/names. common/newclient.h: Resync from server code. common/newsocket.c: Add GetInt64_String() function. common/proto.h: rebuilt. gtk/gx11.c: always include errno.h. Modify layout of skill exp table (properly set up rows/columns). Add some padding to the entries, and don't pre-set the names. Modify draw logic to handle 64 bit values. Modify draw to only draw skills which player has exp in. x11/x11.c: update draw logic to handle 64 bit exp values, only draw skill exp when player has exp in the category. MSW 2003-05-17 common/client.c: Add some usleeps() in negotiate_connection() - this reduces cpu load when negotiating the connection (given 10 ms for data to actually come in before checking for new data). Also, add a count and if we don't get a response back from the server in the time frame, bail out. MSW 2003-03-24 configure.in, configure: checks added for alsa9 sound - update for cfsndserv.c should come shortly. common/client.c: Fix setup problem - it was using FOGWAR setting when determining if client wanted darkness - should have been using darkness setting. This was resulting in darkness not being used if fog of war was turned off. x11/x11.c: Modify handling of mouse button press logic - rather than only modifier being shift, do appropriate logic if the shift mask is set, but does not have to be only modifier set. -- The following bits changes how fog of war looks in SDL mode. Now, fog of war spaces are drawn in greyscale, instead of half darkness. This makes it clearer what the status of the space is (fog of war/darkness). This change probably uses less cpu to draw, but uses more memory for the images (as it now has to store a rendered greyscale image). If not using SDL, you'll still have the old behaviour (dimmed spaces for fog of war), and no significant amount of extra memory will be used. -- gtk/gx11.h: Add fog_image pointer to PixmapInfo structure. gtk/image.c: Add code to render greyscale image. Also add code to free greyscale image. gtk/sdl.c: Modify map draw code to use grey fog image if space is fog of war space. Disable dimming of fog spaces - no longer necessary as space now looks different. MSW 2003-03-24 ------------------------------------------------------------------------------ Changes for 1.5.0: gtk/png.c, x11/png.c: Fix bug in rescale_rgba_data() that was potentially causing a 1 byte overrun of malloc'd data, that could result in crashes or other odd problems. MSW 2003-02-19 common/init.c: Make sure we initalize all the config values. gtk/gx11.c: fix foodbeep - now only beep when food is low, and continue to beep when food reaches 0. sound-src/Makefile.in: Remove gx11.c in depend statement. MSW 2003-02-04 gtk/config.c, gtk/gx11.c: remove including some files which we don't need included. gtk/keys.c: Modify to not use X11 for keybinding - instead, uses gdk functionality - this should make it more portable. MSW 2003-01-22 Patch by scachi@gmx.de to add different display options for the players resistances. common/client.h: increase CONFIG_NUMS and add CONFIG_RESISTS common/init.c: extend resists_table, initialize resist value to proper value. gtk/config.c: Add config option for selecting different options for resistance displays. Add comment about radio button usage. Increase size of config window. gtk/gtkproto.h: rebuilt. gtk/gx11.c: Update get_message_display to support different resistance display options. Add resisze_resistance_table function. Disable code the causes the message window to get relocated next to the stats display on wide displays. MSW 2003-01-12 x11/x11.c: Patch by Jochen Suckfuell that fixes problem of lines printed out while entering extended commands causes the extended command line to get overwritten - the extended command line is now copied to the next line. common/client.c: Add handling of client if it loses its connection to server during setup phase. common/newsocket.c: Have SockList_ReadPacket return -1 if it gets a real error on read - in this way, callers can tell if error is terminal or retryable (return code 0) MSW 2003-01-03 common/player.c: Break out some of the extended commands into there own function to make the extended_command function more readable. Alphabetize strcmps in extended_command. Add special processing for the 'take' command so that it handles open containers properly. gtk/gx11.c: Add version information to the About dialogue box. gtk/key.c: Fix bug in that extended commands (') didn't work right and would crash the client if not entered in info window. Entering these now works properly, and crashes are removed. Clean up formatting of affected function keyfunc(). help/about.h: Add extra newline to text to make it look better with the version string above. MSW 2002-11-30 gtk/gx11.c: Add patch by jshelley@ictransnet.com that fixes save window positions. MSW 2002-10-03 ------------------------------------------------------------------------------ Changes for 1.4.0: common/image.c: Fix bug of not fulling clearing the cache entry data after allocation. This resulted in various random crashes when using cached image mode. x11/x11.c: Add note about -facset. CHANGES, Makefile.in, configure, configure.in: Update for 1.4 release MSW 2002-09-14 common/item.c: Update comment about possible sorting improvements. gtk/gx11.c: Add missing foodbeep functionality to GTK client. MSW 2002-08-13 gtk/config.c: Fix crash when trying to apply config changes when compiled with SDL support but user is not using it. Fix bug where settings were not being properly updated. gtk/sound.c: initialize sound_pipe to NULL, and have init_sounds close the sound pipe if there is currently one open - fixes bug when switching sound control many times in that multiple cfsndserv processes could get started. MSW 2002-07-25 Makefile.in: if no makedepend, don't run make depend directive. README: Add not about ALSA revisions and possible problems compiling. MSW 2002-07-10 This commit adds graduated colored statbars to the gtk client. What this means is that the color of the statbar goes smoothly from red to yellow to green depending on what percentage of your hp/sp/grace/food is compared to your maximum. To use this, you need to go to the config pane and hit the 'gradually change stat bar color' button. common/client.h: Add CONFIG_ value for this, increase CONFIG_NUMS. common/init.c: Add "grad_color_bars" to config_names array. gtk/config.c: Add button to select this behaviour. Move all the special config checks to beyond the for loop that checks the values in apply_config(). There is no need to check all the values on each loop. gtk/gtkproto.h: Rebuilt for inclusion of reset_stat_bars() gtk/gx11.c: Add two styles to the Vitals (stat bar) structure so we can alternate between them. Default is to initialize one for green and the other for red (in non graduated color mode). This should be more efficient then allocating a new one each time we need to change the value. add reset_stat_bars() to reset the colors of the styles to red and green - needed because the graduated color code will change the colors of these. Remove code that freed these styles. Modify draw_stat_bar() to draw them in color or simple mode, in simple mode, we now just need to use the appropriate style and not allocated a new one. Modify draw_message_window() to pass bar values greater than 1 to the draw_stat_bar() function - in graduated color mode, we draw such values with a blue tinting (more blue the more over it is). draw_stat_bar() knows how to properly deal with these higher values. MSW 2002-07-04 gtk/config.c: Fix setting of radio button set state - it was always setting the same (last) radio button as the active button, which did not match state - now it sets the proper button active - this is for the lighting control toggle. gtk/map.c: Add/subtract 2 to the need_recenter_map function - in this way, code that checks known display position +/-1 will still be within map array. gtk/sdl.c: Fix per pixel (fastest and best) lighting code - this got broken quite a while - it was looking to see if the coordinates for the map structure where within range, and not the real coordinates. Since the map coordinates would almost never be within range, the effect was that the per pixel effects more ore less looked like the per tile effects. MSW 2002-07-03 ------------------------------------------------------------------------------ Changes for 1.3.0: Add support for the 'item2' command. This lets us get the item type from the server so that we don't need to figure it out for ourselves. Also, remove support for the 'item' command - that has long since been obseleted by the 'item1' command. -- common/client.c: Remove 'item' from dispatch table, add 'item2'. Add 'itemcmd 2' as part of setup command we send to server. common/commands.c: Add handling for response of 'itemcmd' setup command from server. Remove ItemCmd() function. Add type to calls to update_item(). Change Item1Cmd() function to be called common_item_command() since both item1 and item2 use almost exactly the same logic. Add Item1Cmd() and Item2Cmd() which just call common_item_command() common/item.c: Init item types to 'NO_ITEM_TYPE'. Remove get_nrof() as it was no longer being used. Add type argument to set_item_values() and update_item(). Simplify code in case of name handling, since we know that we will be using at least the 'itemcmd'. Don't worry about getting proper nrof for the player object - its nrof isn't really meaningful anyways. common/item.h: Add #define NO_ITEM_TYPE. Update type field in item to be 16 bits. common/proto.h: rebuilt. MSW 2002-05-30 The bulk of this checkin adds support in the client for the map1a protocol command and the display of big images properly in the map window. A lot of code cleanup was also done however, including removal for the support of the 'map' (original) command. The map1 has been in the server code for quite a while. TODO: Update what needs to be done for the x11 client. common/client.c: Remove map command, add map1a command to dispatch table. Modify setup we send to server to always try to use the map1a command - there is no reason not to use it. common/client.h: Change some of the CONFIG_ values - basically, change it so that there is just one entry for lighting configuration, but it can have any number of values. Modify MapCell so that instead of having multiple arrays for the different values (faces, sizes), add a MapCellLayer structure that contains the specific face information for that layer. Move the PlayerPosition struct and value to this function so that more of the map decompress logic can be handled in the common code. Remove count value from MapCell since it wasn't really being used. common/commands.c: Add code to set the use_config[CONFIG_CACHE] value based on what we get back from the server. Add code to check the setup response for the for the map1a and map1 options. Add code to deal with expanding big images into appropriate spaces. Move some functions from the gui portion to (display_map_clearcell, set_map_face). Add code for map1_common function to deal with map1a extensions. common/external.h: Remove display_map_clearcell and set_map_face from list of external functions. Add get_map_image_size function. common/init.c: change some values of the config values. Update initialization of config values for lighting. common/proto.h: rebuilt. gtk/config.c: Add new button for lighting - best per pixel. Modify code to properly deal with how lighting preference is now stored. Add legacy support for loading of per_tile_lighting and per_pixel_lighting values from config file. Add diagnostic of bad value if selected map/width is out of range. gtk/gtkproto.h: rebuilt. gtk/gx11.c: Change formatting of draw_list. Modify it so that it adjusts the column/row width based on the largest image it needs to display - In this way, if a player stands on a big building, the entire building is displayed in the look list. add row_height and column_width values so we only need to call the function to change them if they are in fact different. Add +sdl command line option to disable sdl code. Modify gtk_draw_map to include redraw parameter. gtk/gx11.h: remove PlayerPosition structure. add row_height, column_width elements to itemlist structure. gtk/image.c: Add table that is used to determine the scaling used for big images in the look list - in this way, big images still appear big, but not necessary 2 or 3 times bigger. Modify create_and_rescale_image_from_data to use this logic. Add get_map_image_size which the common code uses to determine the number of spaces an image may be. gtk/map.c: remove display_map_clearcell and set_map_face functions - now in common code. Modify the dump map/darkness routines to use the new format of the MapCell structure. Modify set_darkness to only set adjoining spaces for needing an update if lighting type is set that needs this. Remove display_map_addbelow - only used for 'map' command. Modify logic of fog of war code to have it done all at display time - not when setting/clearing a cells contents. Modify gtk_draw_map - this basically follows the same logic of sdl_draw_map - it is now better optimized to only draw the spaces that have changed, and not the entire map - this should improve performance considerably. gtk/sdl.c: Remove #if 0 around putpixel - used for best lighting. Change indention of init_SDL - modify it so that if just_lightmap is true, that really is the only thing that is changed. Modify per_pixel_light code to use both methods of per pixel lighting depending on player prefernce. Modify sdl_gen_map to properly handle draw portion of big images. x11/png.c: Add get_map_image_size function. x11/x11.c: modify display_mapcell_pixmap to use new format of MapCell structure. Remove reference to count in MapCell structure. x11/x11.h: Remove PlayerPosition information - now in common code. x11/x11proto.h: rebuilt. x11/xutil.c: Remove display_map_clearcell and set_map_face functions. Modify dump map code for new MapCell structure layout. Remove display_map_addbelow funtion. MSW 2002-05-21 ------------------------------------------------------------------------------ Changes for 1.2.1: Makefile.in: Add pixmaps/question.sdl to archive list. configure, configure.in: Update for 1.2.1 release. MSW 2002-04-28 gtk/config.c: Allocate string data for want_faceset - data returned by gtk_entry_get_text is non persistent. MSW 2002-04-28 gtk/gx11.c: Fix bug in that the wrong variable was being passed to negotiate_connection, resulting in the sound not being properly communicated to the client. MSW 2002-04-19 Main change is to make all the configuration options now available in the configure window in the gtk client. The way all the various values was stored was changed around, so it is now pretty trivial to add any future options. For the most part, most of the logic of the other code is unchanged - one thing that is different is that the clients use the larger virtual maps that are normally used for fog of map - this means that fog of war can be turned on and off. There are probably some bugs in this, but it seems to basically work - no horrendous bugs that I noticed that prevent it from working at all. - common/client.c: replaced config values with new system. Always send setup mapredraw 1 to server to make toggling for fog of war easier, and it doesn't use any significant bandwidth. common/client.h: Add new value configuration system/defines. remove the old values. common/commands.c, common/image.c,common/metaserver.c,common/player.c : update for new configuration value system common/init.c: Add config_names which is used for the load/save logic. update the init and clear functions to set up new values. gtk/Makefile.in: add config.c file. gtk/gtkproto.h: rebuilt. gtk/config.c: New file - holds the config creating code, as well as the load and save for the gdefaults file. gtk/gx11.c: Remove some widgets now in config.c, move itemlist to gx11.h, remove some other values that are in the new configuration scheme. gtk/gx11.h: Moved several structures and externs from gx11.c to gx11.h so they are available to config.c. Remove several values that are done with the new config arrays. gtk/image.c, gtk/keys.c, gtk/sdl.c, gtk/sound.c: : update for new configuration value system gtk/map.c: update for new configuration value system, modified so that fog of war map logic is used all the time. Change allocate_map to no longer refer to map_size global - use the x and y values in the map structure. x11/x11.c: update for new configuration value system - the x11 portion still uses the old load/save method - this should get converted. Many of the options available in the gtk client have no corresponding use in the x11 client. x11/x11.h: update for new configuration value system x11/xutil.c: update for new configuration value system. Most of the map logic is now synced up with the gtk/map.c MSW 2002-04-03 configure.in, configure: Fix the --disable-sound configure option (when used, it won't look for sound support, and will not build the sound-src directory). Likewise, if that option is not used but configure does not find any supported sound systems, it also will not build the sound-src directory. MSW 2002-03-31 Various fixes/enhancements: 1) For the files stored in the players cache, include the image set suffix (eg, base, clsc) when saving the file. 2) Add a gui update element to the gtk client when running with -download_all_faces. For the cfclient, print the updates to the window. 3) Apply patch by 'Alfie' that shows skill experience in the cfclientp 4) Fix caching bugs with the cfclient that caused it to not work right. common/client.c: Add callbacks to image_update_download_status from the download all image routine. It is this callback that provides whatever update mechanism for the player. common/external.h: add image_update_download_status common/image.c: Modify display_newpng to put in the image set name of the saved cache files if that information is available. gtk/gtkproto.h: rebuilt. gtk/gx11.c: Make get_window_coord non static so other files can use it. gtk/image.c: Add image_update_download_status that draws a progress bar. Convenient side effect is that other GUI elements are now updated as part of this, so player can access other menu items. x11/png.c: Fix some bugs when using cached images - rgba_to_xpixmap was using initialized bpp value - we now know this is always 4. create_and_rescale_image_from_data did not match the parameters as the common routines use. Also missing some logic for allocating the data and linking it back to the cache entry. x11/x11.c: Add display for skill experience. This necessitated making some of the windows bigger. x11/x11.h: Remove now unused fields from PixmapInfo structure (fg, bg, bitmap) x11/x11proto.h: rebuilt x11/xutil.c: Remove code that was storing data into the unusued fields in the PixmapInfo structure. Add missing call to init_common_cache_data. Add image_update_download_status function that just does a draw info. MSW 2002-03-26 Many changes to image handling. The most noteworthy are: 1) Ability to use different image sets. 2) Ability to get checksums of all images and download missing images before play starts. 3) Storing cache information for images in a bmaps.client file so that it can know if it has a match without needing to load the image and checksum it. 4) Can use crossfire-image archives to bootstrap the client with a large number of images to save the time of downloading them later. README: Update some out of data information about sounds, add section describing the image handling. configure,configure.in: Make the SOUNDDIR be based and datadir and not an absolute path - this means using a different -prefix changes the location of where it will find the sound file. Moved some of the defines into the config.h file so that we don't need to pass them as -D compiler options. Add code to properly substitute DATADIR and BINDIR values. common/Makefile.in: Add image.c to list of files. Fix depend directive. common/cconfig.h: Remove some options that no longer did anything. common/client.c: clean up some unused global variables, add a few new ones. and support for replyinfo protocol command. Modify negotiate connection to issue requestinfo requests, set up face set to use, use setup command to set caching behaviour, and support for it to download all image sums and missing images before play starts. common/client.h: Update VERSION_SC to 1027. Remove some unused global externs. Add FaceSets structure, Face_Information structure, the later which holds some user preferences. Add Cache_Entry structure, as well as some state when negotiating the connection. common/commands.c: Add ReplyInfoCmd function. Move FaceCmd to common/image.c. Add handling of received setup command for faceache and faceset information. Remove some dead code. common/config.h.in: Add BINDIR and DATADIR defines so we don't need to pass them on the command line. common/external.h: Add some more functions that are called back from the common area. common/image.c: New file - cache logic, png image load code, and protocol image related commands in this file. This removes some of the code that was previously in the GUI area of the client into a common area. common/init.c: Add TEST_FREE_AND_CLEAR macro. Add code to clear some of the newly added structures. common/proto.h: rebuilt. gnome/gnome-cf.h: remove cache_images extern. gtk/gcfclient.man: Update man page for new options (-download_all_faces, -faceset) gtk/gtkproto.h: rebuilt. gtk/gx11.c: add redraw_needed flag so the map window is properly redrawn when caching images and new images show up. Change some other variables to deal with new image code. pixmaps changed to a pointer so that a copy can be held in the common cache structure. Add support for new options. Remove some code that is now in the common/image.c file. gtk/gx11.h: Remove keepcache, change cache_images, add redraw_needed, and change type of pixmaps to be a pointer. gtk/image.c: Move requestface to the common/image.c, change pixmaps to pointer type. remove finish_face_cmd and ReadImages command. gtk/map.c: Change pixmaps to pointer types. gtk/sdl.c: add redraw paramter to sdl_gen_map. change pixmaps type to pointer. gtk/sound.c: Add missing / when running cfsndserv. x11/png.c: Remove gdk related code from the file. Add rgba_to_xpixmap data so tha the common area can load the png file. x11/sound.c: Add missing / when running cfsndserv. x11/x11.c: change pixmap type to pointer. Add new options (-faceset and -download_all_faces). Remove -keepcache option. change cache_images to face_info.cache_images. Change how the pixmaps are generated x11/x11.h: remove keepcache and cache_images variables. Change pixmaps to pointer type. x11/x11proto.h: rebuilt. x11/xutil.c: remove keepcache option. Change pixmap type to pointer. Move requestface and finish_face_cmd to common/image.c MSW 2002-03-25 ------------------------------------------------------------------------------ Changes for 1.2.0: Makefile.in: add missing pixmaps file for archive. crossfire-client.spec, configure.in: Update for 1.2.0 release. MSW 2002-03-19 Most of the changes are by Edgar Toernig - I've just applied them and checked them in. The stripping out of the display_mode variable is my doing however. configure.in, configure: Add check for zlib before png lib check, as on some systems, png requires -lz. common/client-types.h: Add #ifdef check for SOL_TCP common/client.c: Add fast_tcp_send variable, comment out printing of error from socket EOF. Use TCP_NODELAY for sending data to the server if TCP_NODELAY is available. cs_write_string modified to use cs_print_string. common/client.h: Remove display_mode enum, add fast_tcp_send extern. common/commands.c, common/init.c,gtk/image.c, gtk/map.c cs_write_sting modified to use cs_print_string common/external.h: set_autorepeat extern added. common/newsocket.c: Modified to be better optimized for using TCP_NODELAY - cs_print_string function added. common/player.c: modified to use cs_print_string , autorepeat client side command added. common/proto.h, gtk/gtkproto.h: updated with new functions gnome/gnome.c: display_mode variable removed, cs_write_string replaced with cs_print_string gtk/gx11.c: display_mode variable removed, cs_write_string replaced with cs_print_string, -nofog option added pixmaps/question.111: Resized to be 32x32 pixmaps/*.xbm - used for inventory icons in X11 client, replacing xpm files sound-src/cfsndserv.c: Better error handling, include time.h x11/cfclient.man: -font and -noautorepeat options added. x11/png.c: better error checking for rescaling images x11/x11.c: noautorepeat variable added, display_mode removed, image icon functionality re-enabled, images now created from xbm files, set_autorepeat function added, add ability to set font, add mouse wheel support x11/x11.h: remove screen_num extern. x11/x11proto.h: Updated with new functions. x11/xutil.c: Modified to use image_size instead of hardcoded 24x24 value for the status icons. cs_write_replaced with cs_print_string, no auto repeat functionality added. MSW 2001-01-14 ------------------------------------------------------------------------------ Changes for 1.1.0: README: Update notes on needing png (and not xpm) library. Update mailing alias. configure.in, configure: As the separate sound program (cfsndserv) is the only supported sound configuration, remove new_sound_system defines and ability to use the old (now non existant) sound system. Have configure exit with error message if png library is not found, as it is critical to the build process. Change it so that gnome/Makefile is always built so that making of releases works. gnome/gnome-cfclient.man, help/about.h, x11/cfclient.man: Update mail address. gtk/gtkproto.h, x11/x11proto.h: Rebuilt, prototypes for some changed for signed to unsigned characters. gtk/gx11.c, gtk/png.c, pixmaps/stipple.111, x11/png.c, x11/x11.c, x11/xutil.c, pixmaps/stipple.111 pixmaps/stipple.112: Mostly changes to fix compile warnings and make sure we are passing the right types to the various image creation functions (8 bit data). sound-src/Makefile.in: Add soundsdef.h to list of things to build. x11/x11.h: Remove extra semicolon. MSW 2001-12-28 common/config.h, gnome/gnome-cfclient.soundlist, sound-src/sounds, sound-src/soundsdef.h: Remove from CVS as it gets automatically generated as part of configure/build process. common/player.c, gtk/keys.c: Send valid count values when sending a fire command. Some spells use the count value (eg dimension door). gtk/gx11.c: Minor change to the trim_info_window code - still causes periodic crashes in the gtk code however. Modify style code so that if we don't get a valid style, we don't crash the client. MSW 2001-11-25 gtk/gx11.c: Made the inventory lists respect the user's GTK font settings, and made the various window parts use the font size to decide what size to make the displays and the window. TSB 2001-11-21 configure.in, configure: Modified so that if not compiling the gnome client, we don't create the gnome Makefile. MSW 2001-11-05 gtk/gcfclient.man: Add -timemapredraw documentation to man page. gtk/gx11.c: Update size of buffers to 100k, instead of 10k. Add some debugging information to when info window is trimmed. Add -timemapredraw command instead of it being a compile time option. gtk/gx11.h: Add extern for time_map_redraw. gtk/map.c,gtk/sdl.c: use time_map_redraw variable instead of define option. MSW 2001-11-04 gtk/gcfclient.man: Update man page to include all options supported by gtk client. gtk/gx11.c: remove some unused #defines. add -trim_info_window option which takes place of compile time option. Re-order command line switches to be in alphabetical order. Add support for client to load/save most all new options to the gdefaults file. gtk/map.c: Some refinements to fog of war so if a space is empty, don't mark it as a fog space to improve performance. Modify gdk draw routine so that it also supports fog of war. There is still some problem in that the client will really bog down in some circumstances when drawing the map. x11/Makefile.in: Add cfclient.man to list of files. MSW 2001-11-03 Complete client re-org. Create common, gtk, gnome, sounds, and x11 subdirs. Gtk client: only image support is png. Also add resizing options for the images (-mapscale/-iconscale), remove pngximage, update sdl image and normal draw image to support arbitrary image sizes. sound: Only support new sound system. MSW 2001-11-01 gx11.c: Modified to know about new pickup mode (frontend - most all the work is still done on the server). Patch by Nils Lohner. MSW 2001-08-28 Add reset_map_function into xutil.c that gets called after we lose a connection to the server. This fixes a problem of some leftover images from the previous session appearing in the map windows. MSW 2001-08-12 client.c: add call to reset_map_data proto.h: rebuilt xutil.c: Add reset_map_function (mostly a copy of reset_map), make some other functions 'static' so they don't show up in proto.h Fog of war code checkin. This is a fairly complex check in so hopefully not too much breaks. This adds the feature where tiles that have been seen but have since moved out of LOS are still shown on screen but with a 50% transparent black tile over it show it is no longer in LOS. Whatever was in that tile is still shown until a new update comes in from the server at which point the tile is cleared of all old info. The old way was to just paint an opaque black tile. To do this the client now keeps state of as many tiles as it can and remembers which tiles have been marked as cleared. This is a fair amount of memory so when -fog is not specified, the code reverts back to a much smaller in memory map. To allow this, the map structure is now dynamically allocated. I also had to add a new protocol command "newmap" so the client knows when to reinit its map state. NOTE: This feature only works when the client is using SDL. No reason the other blitters can't take advantage of it, just hasn't been done yet. client.c: fog_of_war global variable and newmap cmd added to CmdMapping Added "newmapcmd" to SetUp command. client.h: FOG_MAP_SIZE macro and Player_Position struct commands.c: handled "newmapcmd" sent from server, added NewmapCmd which just calls display_map_newmap(); gnome.c: stub function for display_map_newmap(); gx11.c: Modified all commands that take x,y coordinates to convert to the virtual coordinate system if fog_of_war is active. Added code to sdl_add_png_face to paint a fog_of_war cell over cleared but still in view tiles. Added handling of Control-shift-i to simulate a newmap cmd. Added -fog cmd line option. Added display_map_newmap() function that resets the virtual map state. Correctly deal with dynamically allocate map structure. proto.h: Added new prototypes by hand. x11.c: Added code to dynamically allocate map structure. Added stub function for display_map_newmap(); xutil.c: Modified functions to convert to virtual coordinate system when fog_of_war is active. Modified display_map_clearcell to not clear cell when fog_of_war is active, now just marks the tile as cleared. New function "allocate_map" to dynamically allocate a new map structure and setup the 2 dimensional array pointers correctly. New function, reset_map that clears out the map structure and resets to coordinate system if fog_of_war is active. Changed map_scroll to only update the virtual coordinates on scroll instead of moving memory around if fog_of_war is active. Also checks if the view is close to the edge of the virtual map and recenters it if so. SMACFIGGEN 2001-07-21 Speed optimization to the SDL rendering code. sdl_add_png_face now exits when all 5 dark[] array values are set to full bright. gx11.c: Added a line in the per_pixel lighting section that exits right away if all darkness values are set to 255. SMACFIGGEN 2001-06-23 Quick fix to the get_metaserver function. It was originally calling gtk_main_interation() in a while loop. This is really really really slooooow. I replaced it with a call to gtk_main(). gtk_main_quit for this invocation of gtk_main is called in enter_callback() when the user types in the metaserver he wants to play on. This is WAY faster then the old method. gx11.c: Changed get_main_interation to gtk_main in get_metaserver. Added call to gtk_main_quit() in enter_callback() when state changes from Metaserver_Select to Playing. SMACFIGGEN 2001-06-19 Fix for the sdl/pngximage clients where the client would draw stale data on blank squares after a mapscroll. Basically if you had say an image of a wall on the bottom of your screen and you walked down one tile. If the new tile on the bottom of the screen is now blank, the client would have drawn the wall again and you get a funky recursive effect. The fix is in the display_mapscroll function in xutil.c. xutil.c: Modifed display_mapscroll so that new cells just coming onto the screen would be marked as the_map.cells[ax][ay].need_update= 1. For cells that are already on screen and just moving, we still leave need_update= 0. SMACFIGGEN 2001-06-19 This checkin puts Scott MacFiggen's SDL support into the gtk client. I've made some enhancements to the code - it can now co-exist with the other image formats (so if all the libraries are available, you can choose from -xpm, vanilla -png, -png -pngximage or -sdl (which also forces -png). aclocal.m4, configure, configure.in: Add checks for SDL. client.man: Update with -sdl option. config.h, config.h.in: Add HAVE_SDL define gx11.c, xutil.c: Support for SDL drawing. A lot of the code in xutil.c is command with that of pngximage. gx11.c adds some additional options beyond just the drawing - per tile darkness and gridline options available under the client config window. MSW 2001-06-17 client.c,client.h: Add want_darkness global variable, include when in setup command we send server. client.man,gx11.c,x11.c: Update to include -darkness/-nodarkness command line options commands.c: Change handling of negative results from server on setup command. MSW 2001-06-16 The main thing this fixes is a major memory corruption problem when using -pngximage with the client. Better darkness display is also when using -pngximage, but it depends on a server change (the change basically lets the client do blending from completely dark spaces. ++ cconfig.h: add METASERVER define option which determines if client should try to contact metaserver or not (useful to turn off if behind a firewall so you don't have to wait for the timeout) client.c: add metaserver_on, map1cmd to global variables commands.c: divide by mapy value instead of 11 when using old map command - needed if playing with smaller maps. set map1cmd value on/off depending on type of map command we receive from server. gx11.c: Add BPP define for internal testing to see if using 4 bytes/pixel gives any speed of 3 (answer is performance is the same or slightly worse with 4bpp). when run with mapsize with x>15, create windows with bigmap outlook (message & stats above map, and not above/below). Fix bug in -mapsize processing which would set invalid sizes. Various cleanups to use image_size instead of 32. Changes in drawing to also use BPP define value instead of 3 is various areas. Optimizations for darkness rendering. Use map1cmd global variable to know the packing form instead of looking at map size. Improved darkness handling to know if adjoining spaces have valid darkness information instead of looking at number of tiles. metaserver.c: if metaserver_on isn't set, don't try to get metaserver information. png.c: remove end_ptr processing - wasn't getting used, so not allocating/ freeing it should improve performance a little. Also, move png_set_filler call to before calling png_read_update_info - this fixes a memory corruption problem. x11.c: use map1cmd for determine packing information in map, fix bug in -mapsize command processing which could result in invalid values being used. xutil.c: add have_darkness value to mapcell structure. Set value when we have valid darkness information for this space. This allows the client to use darkness for blocked spaces if the server provides it. update to use BPP instead of 3 for copies of image data. MSW 2001-06-12 This is actually a fairly big checkin: 1) add large map support into the client (use -mapsize option) 2) using GdkRgb structure for drawing the map. This prevents some more advanced map handling functions (like true alpha) as well as much better darkness support (use -pngximage option) cconfig.h: add TIME_MAP_REDRAW define. I originally used this to benchmark my improvements with the gdkrgb code, but throught it may be useful to others client.c: add map sizing global variables. Add map1 protocol pointer. request different mapsize of server. client.h: add map sizing variables to extern declarations. client.man: add description of -mapsize and -pngximage commands.c: Make it more forgiving about extra spaces in setu command. and support for mapsize option of setup command. Add option to map_doneupdate which controls if we want a full redraw or not. Add Map1Cmd command which handles map1 protocol command. gx11.c: Add support for big maps as well as gdkrgb backing images. Add support for -mapsize and -pngximage command line options. Lots of new image drawing code for pngximage. Add resize_map_window function which is called when new map size is negotiated with server - depending on new and old values, re-arrange some windows. png.c: add png_to_data function which takes the png image and and returns rgba data. used by pngximage code. x11.c Add big map support (-mapsize option). It otherewise lacks many of the other features I added to gx11.c xutil.c: add png_data to image structure, and have data put here when using pngximage mode. Move some of the basic map handling functions here - not the stuff that draws the map, but what sets up the server idea of wha the map looks like in terms of spaces. MSW 2001-06-04 The three main things this checkin does: Ability to save relative sizes of gtk subwindows, and have those restored when re-running the client. Use of the setup protocol command to set configuration values. Receipt of skill experience information, and display of that in the gtk client. ++ Makefile.in: Remove Protocol entry Protocol: Removed - now located in server/doc directory. client.c: Add value to determine if we want this option, initialize global array that maps the number to skill names. Add support for 'setup' protocol command. Send sound selection using new setup command. client.h: add MAX_SKILL to no max number of skills. And skill experience and level total to Stats structure, put extern for skill_names array and want_skill_exp value. commands.c: Add SetupCmd function which handles processing of 'setup' protocol command. If sound setting fails with setup command, fall back to old method. In StatsCmd, add code to get skill experience and level totals. gx11.c: Add ability to save window size and relative pane positions in non split mode, as well as loading and setting of those values (required moving pane information widgets from create_windows to global values) - while at it, renamed this to be more descriptive. Have client now display skill experience totals in stats window. metaserver.c: Make meta_sort a static function so that it does not get put into proto files. Its only used within the metaserver.c file in any case. newclient.h: Add CS_STAT_SKILL* values (to keep in sync with server version of this file) proto.h: automatic rebuild needed for SetupCmd function. MSW 2001-05-28 gx11.c: remove some unused code. Add color for cursed/magic items in the unlocked inventory pane (makes it easier to sort items picked up) Add support for trimming the info window buffers - now gtk just has to be fixed. Have the second information window do the seem freeze logic as the first. Fix problem of trying to access to many resistance labels (may fix some reliability problems). Remove -scrolllines command line option since the client does not use it. xutil.c: Don't load/save scrolllines line in config file when included with gx11.c - gtk client has no use for it. Add newline to error message about lines in default file we did not process. MSW 2001-05-25 client.c: update call to metaserver_show client.h: make meta_server, meta_port vars available to other files. gx11.c: clear echo hiding after user completes entry in text window. metaserver.c: Add parameter to metaserver_show which determines if we display instructions for selecting metaserver. Re-get metaserver information if user hits enter on metaserver selection. player.c: Add metaserver command that gets updated metaserver information. proto.h: rebuilt. MSW 2001-04-29 gx11.c: Add disconnect menu item and callback function to disconnect from server. player.c: Fix/improve firing logic. Was problem with gtk client in that it would stop firing after a little while when holding shift direction. This was because the outgoing command queue got filled up and never emptied because it still sent fire_stop commands. Add 'disconnect command to disconnect from server. MSW 2001-04-28 Makefile.in: Add gx11.c to depend directive, so it recompiles properly on changes to png.c, xutil.c command.c: clear no_echo instead of letting the graphic handler do this. also add call to x_set_echo - this fixes cases in nopopups mode of it not switching to echo things properly. gx11.c: Add nopopups/splitinfo options to configure menu. Add x_set_echo function, and remove detection of this from do_timeout. proto.h: automatic rebuild. x11.c: Add setup x_set_echo function. xutil.c: Add saving/loading of splitinfo and nopopups value to/from ~/.crossfire/gdefaults file. MSW 2001-04-27 Note: by default, the command history forward/back keys are not bound to anything. At least on Sparc/Solaris systems, the up key in the cluster of 4 arrow keys is the same keysym as the the key on the keypad, so by automatically binding these, you basically make it so the player can not move north/south, so I figure its better to let players bind them safely. gx11.c: Make the command completion key as well as history move backwards/ forwards custom settable by the player. Also, resize the width of the name/weight window for the look window the same way we do for the inv window. xutil.c: Add support for binding command completion and history scroll keys. Also, add support of loading/saving these bindings (As well as those for fire keys, run keys, command keys. MSW 2001-04-20 gx11.c: Have it hide password entered when using -nopopups mode. Add command completion with tab. remove some dead code. Add command history. Accessible through the up/down arrow keys (the 4 keys between the standard keys and the keypad, not the arrow keys on the keypad.) This feature is barely tested. Most of the editing functionality used here is what gtk provides. MSW 2001-04-20 client.c: add image_file declaration. Also, properly handle cases where the option given by -server (or config file) is not a valid server - go back to metaserver selection instead of looping infinitely. client.h: add image_file declaration. gx11.c: Lots of changes. remove duplicate code between this file and xutil.c. Add show_unlocked inventory tab selection. Add -nopopups command line option which prevents pop up windows. Also results in the count value getting cleared when used. Add -splitinfo command line option that results in two info (Text) windows - one for colored text, one for normal text. When resizing pane that has inventory listing, now updates inventory headings so weight keeps constant width so that the space for the name increases. Implement command_show options so that 'show' command will rotate through tabs (or goes directly to tab if right name is given) of inventory display options. Add handling for -pngfile option. player.c: add complete_command function that returns complete server command when partial string is passed to it (currently only used by x11.c) x11.c: Add unlocked inventory show option. Add command completion via tab key when entering an extended command. Add -pngfile support processing. xutil.c: Modified with #ifdef GDK_XUTIL so the gx11.c file can include this file to reduce duplicate code. Have cache code look in gfx directory first for images to load. Also have cache code then look at images loaded by -pngfile for match before looking in images previously download, then request image from server if we still don't have an image. MSW 2001-04-19 ------------------------------------------------------------------------------ Changes for 1.0.0: player.c: Fix for client crashes if player enters really long commands (like say .....). MSW 2001-05-08 gx11.c,command.c: Remove some debug statements which really should not be there for 1.0, and which are not really useful anyways. items_types, item_types.h: Varioius minor updates. MSW 2001-05-04 gx11.c: Fix bug that causes gtk client not to update weapon speed. metaserver.c: Have the listing get sorted by hostname to make it easier to find the host the user may want. MSW 2001-05-02 ------------------------------------------------------------------------------ Changes for 0.98.0: item_types,item_types.h: Change matching for sword - hopefully this should fix problems with dancing sword spellbooks. MSW 2001/04/06 gx11.c, item.c: move animations of the look window to the client. All the necessary was already being sent to the client - it was just needed for the client to use this information. Also remove some #if 0 code from gx11.c. MSW 2001/03/28 item.c: set_item_values - only resort items based on name if the name has changed. This fixes a problem with items moving around in the inventory if you lock/apply/unapply/unlock them. MSW 2001/03/23 ------------------------------------------------------------------------------ Changes for 0.97.0: MSW 2001/03/18 Change so that containers on the ground still keep proper contents even if the map space itself changes (spells or other objects going onto the space). This is done by using the cpl.container pointer and when getting an updated map space, seeing if one of the map space object tags match that. commands.c: update the cpl.container tags when opening/closing containers. item.c: Have locate_object see if the container matches the tag. Don't have remove_item remove the object contents of other attributes if it is the container, but still remove it from the list it is on. item.h: remove function prototypes - these are in proto.h MSW 2001/03/13: png.c: New png -> X11 (or gdk) creation routines that are much faster. This should make a noticable difference in performance. Note that the X11 and gdk implementations are very different now - the gdk implementation lets the gdk library do most of the work. gx11.c: remove some dead code, add call to gdk_rgb_init() if using png images - needed by new png loader. x11.c: Add call to init_pngx_loader if running in png mode. Also pass colormap by pointer so png_to_xpixmap can modify it. xutil.c: pass colormap by pointer to init_pngx_loader (same reason as above) MSW 2001/03/06: Makefile.in: Add DMALLOC_LIB definition instead of it going in with the the default libraries. cfsndserv will now get properly linked with dmalloc. configure.in, configure: add --disable-sound option, and make relevant changes to use that option (which basically amounts to not checking for any of the sound systems). Add check for dmalloc.h. change substitution for -ldmalloc. cfsndserv.c: Modified so it now compiles with the modern ALSA sound system. No idea if it actually works. MSW 2001/03/04 metaserver.c: Modified so it uses the value of -port if that command line option is given by a user. MSW 2001/03/01 x11.c: Fixes for info window resizing. This should fix some crashes and the code is a bit simpler now. MSW 2001/02/28 Makefile.in: Modify so that it installs the target (cfclient, gcfclient, cfsndserv) one at a time so it works with the install script. item.c: add insert_item_before_item function. Modify the sorting function so it first sorts by type, then by locked/unlocked status, and then by alphabetical order (not including the number prefix). item_types, item_types.h: More updates of missing objects or ones that need more specific matching rules. x11.c: Remove a lot of duplicate code that was in place for metaserver support - instead, just add checks to the existing X event handling code to know not to do some things if we're in metaserver selection mode. This fixes a bug in that resize events would not be handled if in metaserver selection mode. MSW 2001/02/22 ------------------------------------------------------------------------------ Changes for 0.96.0: MSW 2001/02/02: Protocol: Update with new face1 command that includes checksum. client.c: add face1 protocol command. client.h: Update version_sc to 1026. commands.c: Move FaceCmd from gx11.c/x11.c to this file, since it now only does decoding of data and passes rendering off to appropriate file. Also add Face1Cmd function that deals with checksum. Both of these functions pass off the rendering to the same function. gx11.c: add keepcache variable, re-do facing loading/caching - if we have local version of face, generate checksum of it and compare to that against what server has. finish_face_command added to do this - called by the face functions in commands.c. Add -keepcache command line option which will have it not request images from server if checksum is different. Add usleep in metserver selection area to prevent client from hogging all the cpu time. item.c: Add support for ^ in items file to say only match at start of line. Useful for 'bolt' - doing substring also matched against firebolt. item_types, item_types.h: make bolt ^bolt, add Head and hauberk to matching criteria. proto.h: automatic regen. x11.c: As gx11.c above, plus: Use one font for all windows - reduces complexity. Add easy selection of font to use with -font command line option. xutil.c: As gx11.c for relevant functions that are located in this file and not x11.c End of MSW 2001/02/02 checkin. MSW 2001/01/31: client.c: Clear player inventory and look windows after disconnection from server. Prevents client crashes. gx11.c: various fixes - window placement no longer always centered on screen (very obnoxious if running xinerama), various prototypes fixed up, clear map data after clearing image data. player.c: Add suport for 'mapredraw' command. Not that this should ever really be needed, but the server supports it, so its nice to be able to use it. x11.c: Fixes prototype/casting problems when clearing pixmaps. Like gx11.c, clear map data. xutil.c: add better description to the unbind command. MSW 2001/1/13 (except as mentioned, all changes by MSW): Makefile.in: Create destination dirs, remove extra tab. Patch also by Dave. Protocol: typo fixed. config.h, config.h.in: Add HVAE_DMALLOC_H #ifdefs. Checks currently disable in configure.in, as with it, the sound won't like properly since it needs -ldmalloc, and I haven't bothered investing that much time into fixing the Makefile. gx11.c: Patches by Dave Peticolas - mostly code cleanup, but one new feature is support of wheel mice to move the scrollbars. png.c: No real code change, just adjustments in some ordering which I think makes the code appear a little simpler. x11.c: Minor code cleanups, some formatting changes, some to make better error messages. End of MSW 2000/1/13 checkin. MSW 2001/1/8: client.h: Change damage type to be 16 bits. MSW 2000/12/24: png.c: Fix a major memory corruption issue - the png function was re-allocing for a larger hunk of data, but did not update the pointer and was still using the pointer to the smaller hunk. Severity of this bug depended on luck - if the first png downloaded happened to have the full 4 bytes/pixel, it never needed to do a realloc so would work fine. Otherwise, a matter of luck what data got stomped over. Also, modified the main function in this file so that it you can compile against it and it now works with the new in memory data read. MSW 2000/12/19: Metaserver update. Most files updated. This change has the client connect the metaserver and lets the user choose which server to connect to. Also, if the client loses a connection (either because the player has quit playing or the server died), the client will no longer exit and instead go back to the server selection screen. A few unrelated changes (cfclient): when running cache, non downloaded images should look better. Also, client starts up with larger window in Png mode to take into account the extra space png images takes up in the game window. Changes by file: Makefile.in: Add metaserver.c file. cconfig.h: Add metaserver configuration information. client.c: Add meta_ variables, move resists_name to this file, no longer have DoClient exit if it gets an error on the socket (instead mark the fd as -1 and return), change main loop such that if connection to server has been lost, go through loop to establish a new connection. client.h: Add Metaserver_Select input state. Change resists_name from a static to extern. gx11.c: Remove some unused code, various code cleanups, and additions to support the metaserver connection process. init.c: Add reset_client_vars - call it between connections to servers. proto.h: rebuilt for new functions. x11.c: Update for metaserver connection status. If running Png mode, have windows created larger. xutil.c: When creating default images for cache, create 32x32 images for png mode, not 24x24 images. metaserver.c: New file for metaserver code. End MSW 2000/12/19 checkin. MSW 2000/12/10: png.c, gx11.c, x11.c, xutil.c: modified to use in memory loading of png's. This means that if not caching images, we don't need to write it out to a temp file. This should result in a minor performance gain, but also remove the need of using tmpnam. Also, modified gx11.c so that it uses same logic as the x11 client for extended command key ('). Before gx11.c client would use both ' and ", and there was no way to unbind the later - since one can always bind the command key, I found that a bit annoying. Updated to display resistance values in the message window. Except for armour, this is only displayed when running against serves with PR code. Change for both cfclient and gcfclient. Files affected: Protocol client.h commands.c gx11.c newclient.h player.c sounds soundsdef.h x11.c MSW 12-3-2000 ------------------------------------------------------------------------------ Changes for 0.95.8: Checkin on 2000-11-7 by MSW: item.h: Update NAME_LEN to 128, as the server may send us names that long. Also, terminate the name after we copy it. Checkin on 11/3 by MSW: Remove remaining font support for x11 client. Allow setting default display mode and server to connect to in the cconfig.h file. Files affected: CHANGES, cconfig.h, client.c, client.h, gx11.c, x11.c, xutil.c ------------------------------------------------------------------------------ Changes for 0.95.7: Makefile.in: Update to include png.c when packing up distributions. configure.in, configure: Move check for -lm before png check, and libpng on sparc/solaris systems require math library for proper linking. Also, change the -with-xpm* to -with-ldflags and -with-includes to be more general since extra values may be needed for more than just xpm library. client.man: Updated for information about png images and cwindow command. README: Updated with changes mentioned above with the --with-png options. gx11.c: Remove all support for pixmap images. They didn't work anyways, but you could specify -pix on the command line and get no images - now it will at least result in an error message. Also, savedefaults will now save png status properly. xutil.c: Modified so that it will save png status when savedefaults is issued. MSW 8/24/2000 The following change removes imlib as are png loading/rendering library - instead, we use our own local function located in png.c. libpng is still needed, but it removes the dependancy on imlib. Also, my home spun function renders all the png images crossfire uses correctly, while imlib had several it did not do properly. MSW 8/13/2000 Files affected: config.h, config.h.in: Change HAVE_IMLIB_H to HAVE_LIBPNG configure, configure.in: Change check from imlib to libpng. gx11.c,x11.c,xutil.c: Changed to use our functions and not imlib. png.c: new file that has our png support in it. cfsndserv.c: Make some changes so that sound on ultrasparc systems is played properly. Missing FD_SET call to re-add the soundfd, as well as a missing wrap check for first_free_buffer. MSW 8/10/2000 The following matches a change made to the server which includes two piece item names to make the item names in the client appear more perfect. Protocol: Updated to document the new item name transmission method. client.h: Update SC version to 1024. item.h: Remove name and o_name from item structure, instead there is now d_name, s_name, and p_name, representing the display name, singular name, and plural name. display name is derived from the s/p names plus nrof value. commands.c: Chance strncpy to memcpy, as a null character is used to separate the two name values. UpdateItemCmd is also modified to supply an empty string to set_item_values instead of the same name if the name is unchanged. gx11.c, player.c, x11.c: use d_name instead of name to correspond with changes to item.h item.c: Update item initialization and clearing functions with new name elements. Update set_item_values with new two piece name support. remove adding 'a' and 'an' prefix to singular objects, as it generally doesn't look good in the look window and isn't all that useful in the inventory window either. Mark Wedel 8/6/2000 item_types, item_types.h: Update with new item types - MSW 7/19/2000 player.c: Comment out command buffering output - MSW 7/19/2000 ------------------------------------------------------------------------------ Changes for 0.95.6: configure.in: Update for 0.95.6 release. x11.c: Change MAX_BUF definition in to match that in config.h Update README for necessary libraries. configure.in, configure: Re-order testing of Xext, Imlib where we still have the any special link flags set. Also, when finding these, explicity set them in the X_LIBS variable and not the default, since they are only needed for the X11 client. MSW 6/16/2000 Protocol: Update for png information - addition of image command. client.c: Add support for image command. Change initializing so we get the protocol from the server early on - we need to know it before we tell it what facemode we want, as it may not support png images. do protocol version check and if the server does not support it and the user request png, fail out. client.h: Increase versions of protocol. Add Png_Display to possible display modes. command.c: Add ImageCmd function which processes the image command (used for receipt of png images). the use of the image command can be abstracted in the future for other image formats quite easily. config.h.in (& config.h): Add HAVE_IMLIB_H define which lets us know if the imlib is available. configure.in (& configure): Add detection for imlib and set the appropriate variables so that they get linked properly. Also add check for Imlib.h gx11.c: Update for png support - add display_newpng command, change XPM_SIZE to image_size and make it a variable and not a define. Pull in appropriate imlib support, as well as rendering of png data. Some dead code removed. display_usepng, display_usxpm, and display_newpng functions added. newclient.h: Add CF_FACE_PNG constant for CS communication. proto.h: Updated for new png functions. x11.c: Many of the same changes as gx11.c above. More work was done here as the 24 image size was hardcoded into this file - it is now a variable also, so supporting other image sizes in the future should also be quite easy. Once the Png's are rendered, they are drawn the same was as the Xpm's are, so many checks for display_mode==Xpm_Display also check for Png_Display. xutil.c: Support for PNG images added. Changes are mostly related to caching code. Changes by Mark Wedel, 6/2/2000 Makfile.in: Have cfsndserv.o removed when make clean is done. Also add a 'distclean' directive which removes the config.cache/log/status files as well as the executables. MSW 5/29/2000 x11.c: Fix bug introduced in 4/20 update which would cause xpm display mode to fail with no such face warnings - code check was in the wrong place - MSW 5/7/2000 xutil.c: Improve logic for built in keybindings - if the def_keys specifies a unique keycode, we don't update the keycode - this is necessary for some keyboards to have working keybindings (for example, sun Type 5 keyboards use the Up keysym for both the arrows and the keypad, so we can't get the keycode for both with the XKeysymToKeycode file - MSW 5/7/2000 Add key ring to item_types and item_types.h file in the container category. MSW 4/21/2000 Change Makefile.in to use perl that configure has found when running items.pl script - MSW 4/21/2000 License: Add license file for the client - MSW 4/20/2000 cfsndserv.c: Various changes 1) Add support for sound on Sun (solaris) systems - another init_audio function added. 2) If in SOUND_DEBUG mode, also print out the audio device we would try to use. Also, add x,y coordinates when printing debug information when playing a sound. 3) Add various casts to reduce compiler warnings on going from signed char to unsigned char data types. 4) For 16 bit output, big endian (sparc) should now work - have two sections when packing the sound information to pack it the write direction depending on endianess of the machine. 5) Ignore the device entry in the .crossfire/sndstat file - using that resulted in incompatibilities between system types. If player needs to use a specific audio device, the AUDIODEV environmental variable can be used. --MSW 4/20/2000 configure.in (and configure): Many fixes: 1) On solaris, add -R flag to linker options if --with-xpm-lib=dir is used - needed to run the client when dynamic linking is used. 2) Add AC_C_BIGENDIAN check - we need to know the byte order for sound to work on both sparc and other systems properly. NOTE - when running autoconf, you will get a warning about that line. 3) Add detecition for solaris audio include, and add appropriate declarations to use it. 4) Fix for xpm check - if X11 includes are in a nonstandard place, it would fail to find xpm.h since that includes some standard X11 files. Add X_CFLAGS which includes any necessary -I options for this to work. --MSW 4/20/2000 config.h, config.h.in: Add WORDS_BIGENDIAN define to file. MSW 4/20/2000 x11.c, xutil.c, client.h, client.man: Only update keycodes for the local keyboard for standard keybindings. Custom keybindings will keep their old/original keycodes, which is often needed. Add -updatekeycodes option so have it update all keycodes. client.man updated to describe the -updatekeycodes command. MSW 4/20/2000 gx11.c: Above update for keycodes added. Also, update so that it has the same set of command line options that x11.c does (-nocache, -nosound) MSW 4/20/2000 x11.c:add closing comment - the missing close comment was just resulting in warnings of 'comment detected inside comment' - the change does not affect the execution of the code. MSW 4/20/2000 item.c: Remove extra semicolon that was resulting in compiler warnings. Update mail address/copyright date. Mark Wedel 4/18/2000 Makefile, config.cache, config.status: Removed from CVS tree it should not be distributed - rather each person should generate it on their own by using the configure script. One advantage of removing these is that a 'cvs diff' of the directory won't show the diffs of these automatically generated files. Mark Wedel, 4/12/2000 commands.c, client.h: Change animation code to dynamically allocate space needed for animations instead of using a statically defined/sized array to contain the face information. This fixes a bug with icors causing the client to crash (it had more animations than the static array had), and this method is just generally a good idea. Mark Wedel, 4/12/2000 x11.c: Add code into gen_draw_face so if a request to draw a nonexistant face is performed, it will handle the problem gracefully. Mark Wedel, 4/12/2000 ------------------------------------------------------------------------------ Changes for 0.95.4: README updated to give better install directions - msw. Add checks to xutil.c to verify we have a valid keysym before trying to convert it to a string and print it out. Before, this could result in trying to print null strings, which would cause a crash - msw. fix unbind and bind in xutil.c so they properly skip over leading spaces - msw. fix Makefile.in so make depend will pick up x11.c dependencies - msw. Fix 'help command so that the draw info commands are formatted to fit on the default window width (player.c - msw). Fix so that cwindow without options results in a message that an option is needed instead of causing the program to crash (player.c - msw) Update Makefile.in so that make install works again - msw Updated gtk client with speedups in text handling and drawing. It should now remain responsive during massive text updates on slower machines. Prepared with a single define (XPM_SIZE) for 32x32 graphic tiles. /David ------------------------------------------------------------------------------ Changes for 0.95.3: Don't link in -lnsl -lsocket on sgi systems. Don't link in -lnsl on linux systems. This list probably needs to be expanded. Gracefully handle failures of the sound daemon for whatever reason (most likely because there is no good sound support). Client should now detect write errors and just stop trying to write stuff to the sound daemon. Improve logic in cfsndserv when adding to the buffers. Prior, it would actually skip over buffers, and logic on determine the amount of data was faulty if a short sound was played after a long song. Fix in cfsndserv.c so that it will read the device entry in the ~.crossfire/sndconfig properly. Include sys/select.h if we have it in cfsndserv.c. Some systems appear to need to for proper compilation of that file. Also, #ifdef for checks already done to determine if we should include some includes or not. Status line should now show hp/sp/gr successfully when player has totals greater than 100 in those stats (From Timo Kokkonen) Option to have system beep when low on food - setable via foodbeep command. (From Timo Kokkonen) Better logic to prevent 'You can not issue commands - state is not ST_PLAYING' warning from Timo Kokkonen) Various non functional changes that should prevent warnings during compile (From Timo Kokkonen) Have client create the ~/.crossfire directory if needed prior to saving keys. Change client help command so it will not display client side help information if the user is requesting help on a specific command. Ability to specify location of sound files at the configure state with --with-sound-dir=/some/path Support for SGI sound system added by Paul Mikell, configure detection for sgi sound by Pertti Karppinen (both untested by me since I don't have an sgi handy) ------------------------------------------------------------------------------ Changes for 0.95.2: Improve item_actions so it can handle getting pashed null objects (just return then) In create_item, only add to an objects environment if we actually have an environment to add to. configure.in changes - special check for alpha systems. Add configure option for new/old sound, and auto detection of alsa (hopefully - untested) Build both gcf and cfclient if possible. Improved Makefile.in - more dependancies and automatic defaults have rules. Support for building both the gcfclient and cfclient with the same common object files. Support for building in other directories. Include aclocal.m4 file in distribution so autoconf can be re-run Improved fire/run handling. Previously, due to the auto repeat of the x-server, numerous fire starts and stops would be continuously sent because the code would see a keypress and keyrelease events. Logic changed to eliminate that constant sending - only send the actual run/fire stop if when all x-events have been processed, the specific key is no longer being pressed. This also seems to improve interact performance when using run to move in the game. This is only fixed in the X11 client - wasn't able to figure out where in the gtk client to call the functions after all events had been processed. Size of command window setable. The command window is the number of commands the client will let go unanswered before it stops sending commands. This is setable with the 'cwindow' command, and will be saved into the defaults file so it stays constant across multiple runs. Fixes to work on black and white systems (cfclient, both pixmap and xpm) Change update_item function to update open/close containers if the flags change. Remove rotateinventory from default keybindings - no reason to keep it around, since it isn't used anymore. Increase buffer size used when reading in key bindings. Fix for x11.c to hopefully prevent FPE's - it seems that at times the players weapon speed could be zero, and dividing by that resulted in the Fpe. If the players weapon speed is zero, then we just display 0 as the speed. Remove instruction from README telling the player to copy the def_keys into their custom key file. Not needed, and clutters up the unbind list quite a bit. Patches from Tero Kivinen: Fix help files so that they do not have embedded new lines (under ansi C, strings can not span multiple lines unless continued with a \ - gcc lets this behaviour go through however). Also, change to configure.in to add -std1 to cc on digital unix. Include aclocal.m4 in distribution so end users can remake configure.in Strip leading spaces when sending complex commands. Parsing of complex commands made a bit cleaner (patch from Maciej Kalisiak) GTK changes by David Sundqvist: Compiles for both gtk+-1.0 and development gtk+-1.1.12 and onwards. Close button for open things in the look window added. Included various patches by Maciej Kalisiak for locking and marking in inventory, as well as coloring damned items too. Some cosmetic code cleanups by Charles Duffy. Tearoff menus for development version of GTK. Some small tooltips. I'd like more, but gtk is picky about what widgets it accepts tooltips for. Some fixup for drop count. Not entirely sure how that should work to be practical. Menu choice to clear info window. Speedup for image creation in non-cached mode. Main loop moved into gx11.c to allow both clients to be built at once. ------------------------------------------------------------------------------ Changes for 0.95.1: Add 'depend' directive to makefile. remove 'includes.h' as a distributed file. -nosplit option added to x11 client. Useful if you don't want split modes but your default file is set for it. resizing of main window in non split mode for x11 client supported. The sub windows will try to be maintained in the same proportions. use autoconf to determine if we have sysconf instead of by system type. Check to see if the item has an environment before setting the inv_updated flag of that environment. This should fix some crashes. Add #ifdef of SOUND_DEBUG so we don't get verbose notifications in the sound code unless we want them. Clear item attributes after the item has been freed. When the items are first created, they are initialized to sane values, and many areas of the code expect that new item will be initialized properly. This change seems to fix the problem with item names being incorrect (ie, "two" and the like). Expanded item_types file to be more complete. GTK changes by David Sundqvist: 981127 Further GUI configuration (keybindings too, needs more work tho) XPM caching now implemented Color text in info window (warning: this may trigger a bug in pre 1.0.5 gtk, but you can turn it off in the GUI config :) ) Menu reorganizations and additions 981114 Split windows mode For those who want new fun layouts. (still has some problems with focus here) Color coded inventory Now you can see cursed and magic items in color coding. Smart dialogs It will actually try to figure out what options you have in dialogs. Fix for inventory count Now pressing 0-9 should update count. Configuration dialog GUI configuration for some options. ------------------------------------------------------------------------------ Changes for 0.94.4: Set receive socket buf to 64K. Added item type detection and sorting (prior, items basically appeared in the inventory in which they were sent.) Ordering can be changed/extended- see item_types file. Incorporate gtk version 0.94.3auto into this release to have one common client source base. Support for complex keybindings (more than one command bound to the same key, separated by semicolons) added -nocache command line option (default behaviour, but option needed if your defaults file is set to cache). When receiving new xpm image from server, create xpm data from the data provided instead of saving it to a file and creating it from the file. This should be much faster. If we are caching images, we still save the data to a file but use the buffer to create the image (this is the same thing that pixmap display does). This is only true for the x11 client - I am not sure what the gtk client does. Added support in the client to understand the 'goodbye' command from the server. This is to allow the client clean exits. SC protocol updated for 1022 for this. 'goodbye' will be in the 0.95.0 server. ------------------------------------------------------------------------------ Changes for 0.94.3: Only print debugging output on runs if compiled with -DDEBUG option. Most fprintf(stderr,...) changed to use the LOG call instead. Updated protocol version to 1021. This is for the ncom and commc commands (command windowing). Support for the ncom and comc functions above added to client. Client will now stop sending repeat commands at a certain point. README cleaned up - README now contains more of the first level type instructions, where README.old contains some of the older discussion and background notes. README now includes very good notes on extracting keybindings from save files for use with client. ------------------------------------------------------------------------------ Changes for 0.94.2: Change Version command to include 2 versions strings - version of of C->S commands and version of S->C commands. Allows for better handling when versions are mismatched. Current versions for both set to 1020. Also, version command can now take an optional string describing the client and server (ie, X11 C client, or Java client, etc) Client query command now will handle multi line text fields (separated by newlines) as sent in the query command. Before, it was never explicity set that this should be done, and was never an issue because there never was multiple lines sent. However, to make input handling on some clients easier, text describing what the query is for is not sent via drawinfo, but now sent via the query command. When user enters the help command, send any options along to the server (ie, send 'help asdf' to server. Before, it only sent the help. Added ability to mark items similar to server. 'mark' command added to protocol. Bug fix when using commans bound with 'bind -e'.Prior, when hitting return to finish the command, it would not advance to a new line. It now does. nrof and item name with nrof now properly updated in inventory window when server sends and update command (prior, the client internally know the correct nrof, but the item name in the window was not properly updated) Changed local showicons command to showicon instead. The later is what it should have been in the first place. ------------------------------------------------------------------------------ Changes for 0.94.1: CS_STAT_WEIGHT_LIM added to stats command. Client will store value, and print it at top of inventory window (carried weight/limit) Handling of dmalloc library in makefiles better done. Don't assume gcc on mips machines. Minor updates to protocol file (more accurate, no change in actual commands save for weight limit above) Only send fire start/stop commands if in play state. cleaned up overly verbose messages in sound.c (comment out). Also, soundcard.h assumed to only exist on linux systems. ------------------------------------------------------------------------------ Changes for 0.94.0: Client will handle item1, upditem, face, sound, and anim commands from server (new commands) Client will now animate objects. Fully handles caching of images - should be a big speed improvement over slow links. Client now handles numbering of commands on its own (item1 will send nrof) Handling of locked items now also handled on client. Created misc.c file - handles things like strdup, and creation of directories. Client will now send lookat command to server. sound.c file added - handles playing of sounds. This should work on most systems that have a /dev/audio which can play .au files. On linux (open sound system), more sophisticated handling is added (stereo support and volume control). soundsdef.h file added which contains default sound information. -nosound option added to disable sounds. Added inventory show options (ie, magical, nonmagical, etc) - equivalant of 'x' command on oldserver. Bug fix that would cause grace bar to always be drawn same color as sp bar. Print fire on/run on informatin in the message window. Add KEYF_STANDARD flag to keybindings, so when do an unbind, we can only show custom keybindings. Can now save window positions (in -split mode) accross runs. Saved in ~/.crossfire/winpos Can now save standard defaults (sound, scrollboard, port, tec) in ~/.crossfire/defaults Protocol file updated with new commands. Added some client side 'help command - shows commands the client handles locally. New local commands added: savewinpos, savedefaults, help, show. ------------------------------------------------------------------------------ Changes for 0.93.7: Fixed make proto directive to exclude inline functions in the proto.h file. Added support to using debug malloc library (dmalloc.) Change Extra_Flags, LOCAL_LIBRARIES in the Imakefile to disable this. made update_item a non static function in item.c. Also, no will probably find the player object for weight updates. Removed carrying field in the item structure. Fixed bugs in resizing the info window which would cause program to crash - left over problems from when the scrollbar was added. Can now drop a portion of a group of objects (ie, 50 of 100 arrows) ------------------------------------------------------------------------------ Changes for 0.93.6: Change the select loop to reset the timeout each time - looks like linux select resets this to zero (undocumented feature?) Use correct length in SendAddMe function. Started adding code for local face caching. Protocol file updated to be more accurate/complete. ------------------------------------------------------------------------------ Changes for 0.93.5: Added support for multi line input. ------------------------------------------------------------------------------ Changes of 0.92.2-a: Scrollback buffer for the info window added. crossfire-client-1.75.3/README.rst000644 001751 001751 00000004507 14605665645 017460 0ustar00kevinzkevinz000000 000000 ================ Crossfire Client ================ Crossfire is a free, open-source, cooperative multi-player RPG and adventure game. Since its initial release, Crossfire has grown to encompass over 150 monsters, 3000 areas to explore, an elaborate magic system, 13 races, 15 character classes, and many powerful artifacts scattered far and wide. Set in a fantastical medieval world, it blends the style of Gauntlet, NetHack, Moria, and Angband. - Website: http://crossfire.real-time.com/ - Wiki: http://wiki.cross-fire.org/ Installation ============ To build with the default options, change to the source directory and run:: $ mkdir build && cd build/ $ cmake .. $ make # make install To build with minimal dependencies, use this CMake command instead:: $ cmake -DLUA=OFF -DMETASERVER2=OFF -DSOUND=OFF .. To build with debugging symbols:: $ cmake -DCMAKE_BUILD_TYPE=Debug .. Use **ccmake** instead of **cmake** to change these options and more interactively. For more details, see `Compiling the Crossfire Client `_ on the Crossfire Wiki. Dependencies ------------ - C compiler supporting C99 - CMake - GTK+ 2 - libpng - Perl - pkg-config - Vala Optional: - libcurl (for metaserver support) - Lua 5 (for client-side Lua scripting) - SDL2_mixer (for sound support) Sounds ------ To play with sounds, make sure the client is compiled with ``SOUND`` enabled. Download the sound archive and extract it to *${PREFIX}/share/crossfire-client*. Then enable sound effects in the client preferences. License ======= This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See *COPYING*. Release ======= To tag and prepare a client release: 1. Update *ChangeLog* 2. Update ``VERSION`` string in *CMakeLists.txt* 3. Create an annotated tag (e.g. ``git tag -a v1.2.3 -m "Tag 1.2.3 release"``) 4. Build the client normally (see above) 5. Run ``git clean -fx`` to clean up local files 6. Download/check out current sounds into **sounds/** for inclusion in the source release 7. In the build directory, run ``make package_source`` 8. Inspect resulting source tarball, extract, build, test crossfire-client-1.75.3/gtk-v2/000755 001751 001751 00000000000 14605665664 017076 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/gtk-v2/win32/000755 001751 001751 00000000000 14605665664 020040 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/gtk-v2/win32/nsis.txt000644 001751 001751 00000000667 14323707640 021552 0ustar00kevinzkevinz000000 000000 To create a Windows client installer, you need NSIS. First build the client, then put all its required files into a "files" subdirectory of the directory containing this readme. Adjust, if needed, the trunk version in the .nsi file. Then run NSIS on the .nsi file. If using the Powershell autobuild script written by DraugTheWhopper, it will tell NSIS where to find and put everything. Check the comments of that script for more info. crossfire-client-1.75.3/gtk-v2/win32/win32-package.sh000644 001751 001751 00000001326 14323707640 022715 0ustar00kevinzkevinz000000 000000 #!/bin/sh # This script has been deprecated by the addition of a powershell build script. --DraugTheWhopper # win32-package -- run this in the build directory function gather_deps() { mkdir -p lib share cp -R /mingw64/lib/gdk-pixbuf-2.0 lib cp -R /mingw64/lib/gtk-2.0 lib cp -R /mingw64/share/themes share } function gather_dlls() { dlls=`ldd $1 | grep mingw | awk '{print $3}'` for f in $dlls; do cp $f . done } set -e make install gather_deps gather_dlls gtk-v2/src/crossfire-client-gtk2.exe version="r`cd .. && svnversion`" target="crossfire-client-$version-win`uname -m`" mkdir -p $target cp -R *.dll lib share $target for bin in `ls bin`; do cp "bin/$bin" $target/$bin.exe done crossfire-client-1.75.3/gtk-v2/win32/client.nsi000644 001751 001751 00000007716 14323707640 022030 0ustar00kevinzkevinz000000 000000 !include "MUI.nsh" ;If the user passed "/DGITVERSION=something" when invoking the script, use that. Else, use a placeholder. !ifdef GITVERSION !define REVISION "git-${GITVERSION}" !else !define REVISION "git-unknown" !endif ;Title Of Your Application Name "Crossfire GTKClient" VIAddVersionKey "ProductName" "Crossfire client installer" VIAddVersionKey "Comments" "Website: http://crossfire.real-time.com" VIAddVersionKey "FileDescription" "Crossfire client installer" VIAddVersionKey "FileVersion" "${REVISION}" VIAddVersionKey "LegalCopyright" "Crossfire is released under the GPL." ;If the user passed "/DVERSION=something" when invoking the script, use that. Else, use a placeholder. ;Note that it must be numerals, in the format x.x.x.x !ifdef VERSION VIProductVersion ${VERSION} !else VIProductVersion 1.99.99.99 !endif ;Do A CRC Check CRCCheck On SetCompressor /SOLID lzma ;Output File Name ;If the user passed "/DOUTPUTDIR=something" when invoking the script, use that. Else, use the current working directory. !ifdef OUTPUTDIR OutFile "${OUTPUTDIR}\CrossfireClient-${REVISION}.exe" !else OutFile "CrossfireClient-${REVISION}.exe" !endif ;The Default Installation Directory InstallDir "$PROGRAMFILES\Crossfire Client" InstallDirRegKey HKCU "Software\Crossfire Client" "" !define MUI_ABORTWARNING !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_FINISH !insertmacro MUI_LANGUAGE "English" Section "Crossfire Client (required)" cf SectionIn RO ;Install Files SetOutPath $INSTDIR SetCompress Auto SetOverwrite IfNewer ;If the user passed "/DINPUTDIR=something" when invoking the script, use that. Else, find the files in ".\files\" !ifdef INPUTDIR File /r "${INPUTDIR}\*.*" !else File /r "files\*.*" !endif ;If the user passed "/DSOURCELOCATION=something" when invoking the script, use that. Else, find the icon in "..\..\pixmaps\client.ico" !ifdef SOURCELOCATION File ${SOURCELOCATION}\pixmaps\client.ico !else File ..\..\pixmaps\client.ico !endif ; Write the uninstall keys for Windows WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Crossfire Client" "DisplayName" "Crossfire Client (remove only)" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Crossfire Client" "UninstallString" "$INSTDIR\Uninst.exe" WriteUninstaller "Uninst.exe" SectionEnd Section "Menu and Desktop Shortcuts" menus ;Add Shortcuts SetOutPath $INSTDIR CreateDirectory "$SMPROGRAMS\Crossfire Client" CreateShortCut "$SMPROGRAMS\Crossfire Client\Crossfire Client.lnk" "$INSTDIR\crossfire-client-gtk2.exe" "" "$INSTDIR\client.ico" 0 CreateShortCut "$SMPROGRAMS\Crossfire Client\Uninstall.lnk" "$INSTDIR\uninst.exe" "" "$INSTDIR\uninst.exe" 0 SetShellVarContext all CreateShortcut "$desktop\Crossfire Client.lnk" "$INSTDIR\crossfire-client-gtk2.exe" "" "$INSTDIR\client.ico" 0 SectionEnd UninstallText "This will uninstall Crossfire Client from your system" Section "un.Crossfire Client" un_cf SectionIn RO ;Delete Files RmDir /r $INSTDIR ;Delete Start Menu Shortcuts RmDir /r "$SMPROGRAMS\Crossfire Client" ;Delete Desktop Shortcut SetShellVarContext all Delete "$desktop\Crossfire Client.lnk" ;Delete Uninstaller And Unistall Registry Entries Delete "$INSTDIR\Uninst.exe" DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Crossfire Client" DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Crossfire Client" SectionEnd !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${cf} "Crossfire Client (required)." !insertmacro MUI_DESCRIPTION_TEXT ${menus} "Create icons in Start Menu and on Desktop." !insertmacro MUI_FUNCTION_DESCRIPTION_END crossfire-client-1.75.3/gtk-v2/win32/autobuild.ps1000644 001751 001751 00000065337 14457055163 022463 0ustar00kevinzkevinz000000 000000 # A few assumptions made in this script: # You're running Windows 10 x64 # You've installed MSYS2 x64 into C:\msys64. MSYS2 should install MinGW64 into C:\msys64\mingw64. Use of MSYS2's installer is recommended, instead of installing from a third-party repo or tool. # You've installed CMake for Windows # You've installed 7-zip # You've installed NSIS # The MINGW "bin" folder must be in your PATH. Typically this is C:\msys64\mingw64\bin # The CMake "bin" folder must be in your PATH. Typically this is C:\Program Files\CMake\bin # You have a working git # You've already 'git clone' the client and sounds repos, into the "sourcedir" and "sounddir" directories listed below # We have write permission into the C:\autobuild folder # Nothing major has changed since git bae2a4a7ba2ad5454920ad6f7153a0b8063cc24c. That's the last time this script was more or less debugged. # In MSYS' MinGW, you've installed: # mingw-w64-x86_64-SDL2_mixer # mingw-w64-x86_64-gcc # mingw-w64-x86_64-make # mingw-w64-x86_64-perl # mingw-w64-x86_64-pkg-config # mingw-w64-x86_64-vala # (The oneliner for these is here:) # pacman -S mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-gcc mingw-w64-x86_64-make mingw-w64-x86_64-perl mingw-w64-x86_64-pkg-config mingw-w64-x86_64-vala $sourcedir = "C:\autobuild\cfsource" $releasedir = "C:\autobuild\cfrelease" $builddir = "C:\autobuild\cfbuild" $sounddir = "C:\autobuild\cfsounds" $packagedir = "C:\autobuild\cfpackage" $7zipbinary = "$env:ProgramFiles\7-Zip\7z.exe" $nsisbinary = "$env:ProgramFiles (x86)\NSIS\makensis.exe" # A handy function to see if something is a command, or is in our PATH. Returns a simple $true/$false. # If we want to know *where* the executable was, then we'd use "Get-Command" by itself, which is similar to the Unix "which" command. Function Test-CommandExists { Param ($command) $oldPreference = $ErrorActionPreference $ErrorActionPreference = ‘stop’ try {if(Get-Command $command){RETURN $true}} Catch {Write-Host “$command does not exist”; RETURN $false} Finally {$ErrorActionPreference=$oldPreference} } #end function test-CommandExists Write-Progress -Activity "Building Crossfire Client" -Status "Checking prereqs" -PercentComplete 0 # Before we even get started, lets run a bunch of sanity checks. Note that several items must be in your PATH. if (!(Test-Path $sourcedir\.git\config)) {throw "Can't confirm the source dir is a git dir."} if (!(Test-CommandExists cmake.exe)) {throw "cmake.exe is not in your PATH."} if (!(Test-CommandExists mingw32-make.exe)) {throw "mingw32-make.exe is not in your PATH."} if (!(Test-CommandExists pkg-config.exe)) {throw "pkg-config.exe is not in your PATH."} if (!(Test-Path C:\msys64\mingw64\lib)) {throw "Can't find MinGW's lib folder. Make sure it's in C:\msys64\mingw64\lib\"} if (!(Test-Path C:\msys64\mingw64\share)) {throw "Can't find MinGW's share folder. Make sure it's in C:\msys64\mingw64\share\"} Write-Progress -Activity "Building Crossfire Client" -Status "Fetching latest source" -PercentComplete 5 # Update the source tree pushd $sourcedir git pull --quiet $cfgitversion = (git rev-parse --short HEAD) popd Write-Progress -Activity "Building Crossfire Client" -Status "Running CMake" -PercentComplete 10 # Clean the build dir If (Test-Path $builddir) {Remove-Item $builddir -recurse} New-Item -Path $builddir -ItemType Directory | Out-Null # run CMake. Turn off OpenGL because it's broken on Windows as of Aug 2021. $cmakeoutput = ( cmake.exe ` -S C:\autobuild\cfsource -B C:\autobuild\cfbuild\ ` -G "MinGW Makefiles" ` 2>&1 ) $cmakeoutput | Out-File -FilePath C:\autobuild\cmakeoutput.txt if ($LASTEXITCODE -eq $true) {Write-Warning -Message "The CMake process may not have exited cleanly. Check C:\autobuild\cmakeoutput.txt for more info."} # If CMake gives an error about pkg-config or PKG_CONFIG_EXCEUTABLE, # make sure you don't have another pkg-config in your PATH, such as # one supplied by a third-party PERL. # Run Make Write-Progress -Activity "Building Crossfire Client" -Status "Running make" -PercentComplete 15 pushd $builddir $makeoutput = (mingw32-make.exe -j 4 2>&1 ) # if you have more cores, turn up the number of jobs with the "j" flag $makeoutput | Out-File -FilePath C:\autobuild\makeoutput.txt if ($LASTEXITCODE -eq $true) {Write-Warning -Message "The make process may not have exited cleanly. Check C:\autobuild\makeoutput.txt for more info."} Write-Progress -Activity "Building Crossfire Client" -Status "Running make install" -PercentComplete 30 $makeinstalloutput = (mingw32-make.exe install 2>&1) $makeinstalloutput | Out-File -FilePath C:\autobuild\makeinstalloutput.txt if ($LASTEXITCODE -eq $true) {Write-Warning -Message "The make install process may not have exited cleanly. Check C:\autobuild\makeinstalloutput.txt for more info."} popd # Get a rough count of compile warnings and errors $makewarnings = ($makeoutput | select-string -pattern ": warning:").count $makeerrors = ($makeoutput | select-string -pattern ": error:").count if ($makeerrors -gt 0) {Write-Warning -Message "The make process had errors. The build was probably not successful."} # We're done with the build and need to assemble all it's components into one place. Write-Progress -Activity "Building Crossfire Client" -Status "Assembling dependencies" -PercentComplete 35 # First, a few sanity checks. if (!(Test-Path C:\msys64\mingw64\lib)) {throw "Can't find MinGW's lib folder. Make sure it's in C:\msys64\mingw64\lib\"} if (!(Test-Path C:\msys64\mingw64\share)) {throw "Can't find MinGW's share folder. Make sure it's in C:\msys64\mingw64\share\"} if (!(Test-Path C:\msys64\mingw64\bin)) {throw "Can't find MinGW's bin folder. Make sure it's in C:\msys64\mingw64\bin\"} if (!(Test-Path C:\autobuild\cfbuild\share)) {throw "'make install' didn't create a 'share' directory in $builddir. Check the content of $makeoutput and $makeinstalloutput"} if (!(Test-Path $builddir\bin\crossfire-client-gtk2.exe)) {throw "Can't find the Crossfire binary. It should be in $builddir\bin\crossfire-client-gtk2.exe"} if (!(Test-CommandExists C:\msys64\usr\bin\ldd.exe)) {throw "Can't find ldd.exe. It should be in C:\msys64\usr\bin\"} # Clean the directory to prepare for assembling the release If (Test-Path $releasedir) { Remove-Item $releasedir -recurse} New-Item -Path $releasedir -ItemType Directory | Out-Null # Pull in some CF stuff Copy-Item -Path C:\autobuild\cfbuild\share -Destination $releasedir -Recurse # Need a few GTK things from MinGW New-Item -Path $releasedir\lib -ItemType Directory | Out-Null Copy-Item -Path "C:\msys64\mingw64\lib\gtk-2.0" -Destination $releasedir\lib -Recurse Copy-Item -Path "C:\msys64\mingw64\lib\gdk-pixbuf-2.0" -Destination $releasedir\lib -Recurse Copy-Item -Path "C:\msys64\mingw64\share\themes" -Destination $releasedir\share -Recurse # Make sure the sounds exist... Write-Progress -Activity "Building Crossfire Client" -Status "Assembling sounds" -PercentComplete 40 if (Test-Path $sounddir\.git\config) { # ...before updating them... pushd $sounddir git pull --quiet popd # ...and copying them into the release folder. New-Item -Path "$releasedir\share\crossfire-client\sounds" -ItemType Directory | Out-Null Copy-Item -Path $sounddir\* -Destination $releasedir\share\crossfire-client\sounds\ -Recurse } else {Write-Warning -Message "Couldn't find the sounds, so we won't copy them into the build."} # Pull in the compiled binary. No need for a sound server binary anymore, since # git 1c9ba67464bf845ac1cc8bf4d7fb80774756cece or SVN 21700 Write-Progress -Activity "Building Crossfire Client" -Status "Assembling binary and DLLs" -PercentComplete 45 Copy-Item $builddir\bin\crossfire-client-gtk2.exe $releasedir # call ldd to find DLLs recursively C:\msys64\usr\bin\ldd.exe $releasedir\crossfire-client-gtk2.exe | # trim ldd's output to get the filename of each DLL. Roughly equivalent to: awk '{print $3}' ForEach-Object {$_.Split(' ')[2]; } | # use Regex to find DLLs that A) are being pulled from MinGW, and B) regex match on only the filename, not the path. Select-String -Pattern "(?<=\/mingw64\/bin\/).*" | # We can't use the full path because ldd returns Unix-style paths. Return only what the regex found, not the whole line. ForEach-Object {$_.Matches.Value} | # Now that we have a list of DLLs being pulled from MinGW, lets just dump them all in the release folder. ForEach-Object {Copy-Item C:\msys64\mingw64\bin\$_ $releasedir} # SDL pulls a sneaky one, and doesn't load the ogg/vorbis DLLs until you actually feed it an OGG file. So, ldd doesn't know, and we gotta get them manually. Copy-Item C:\msys64\mingw64\bin\libvorbis-0.dll $releasedir Copy-Item C:\msys64\mingw64\bin\libvorbisfile-3.dll $releasedir Copy-Item C:\msys64\mingw64\bin\libogg-0.dll $releasedir # We're done with assembling the release. You should now be able to take $releasedir and run it on another system safely. # Let's do a few sanity checks before trying to make the package. Write-Progress -Activity "Building Crossfire Client" -Status "Checking packaging prereqs" -PercentComplete 50 if (!(Test-CommandExists $7zipbinary)) {throw "Can't find 7-zip."} if (!(Test-CommandExists C:\msys64\usr\bin\sha256sum.exe)) {throw "Can't find sha256sum.exe in the MSYS bin directory."} if (!(Test-CommandExists $nsisbinary)) {throw "Can't find NSIS."} # Time to make a zip package # Create the package directory if it doesn't exist If (!(Test-Path $packagedir)) {mkdir $packagedir} Write-Progress -Activity "Building Crossfire Client" -Status "Building zip archive" -PercentComplete 55 # Use 7-zip to make a zip archive If (Test-Path $packagedir\crossfire-client-git-$cfgitversion-win32_amd64.zip) { Write-Warning -Message "A zipfile already exists for this version, we'll delete and recreate it." Remove-Item $packagedir\crossfire-client-git-$cfgitversion-win32_amd64.zip } Set-Alias 7z $7zipbinary $7zoutput = (7z a -mx9 -mmt1 -r -- $packagedir\crossfire-client-git-$cfgitversion-win32_amd64.zip $releasedir) $7zoutput | Out-File -FilePath C:\autobuild\7zoutput.txt if ($LASTEXITCODE -eq $true) {Write-Warning -Message "The 7-zip process may not have exited cleanly. Check C:\autobuild\7zoutput.txt for more info."} # Take the SHA256 of the zip If (Test-Path $packagedir\crossfire-client-git-$cfgitversion-win32_amd64.sha256) { Write-Warning -Message "A sha file already exists for this version's zipfile, we'll delete and recreate it." Remove-Item $packagedir\crossfire-client-git-$cfgitversion-win32_amd64.sha256 } pushd $packagedir C:\msys64\usr\bin\sha256sum.exe "crossfire-client-git-$cfgitversion-win32_amd64.zip" > $packagedir\crossfire-client-git-$cfgitversion-win32_amd64.sha256 popd Write-Progress -Activity "Building Crossfire Client" -Status "Building NSIS installer" -PercentComplete 80 # If an NSIS package exists, delete it If (Test-Path $packagedir\CrossfireClient-git-$cfgitversion.exe) { Write-Warning -Message "An NSIS installer file already exists for this version, we'll delete and recreate it." Remove-Item $packagedir\CrossfireClient-git-$cfgitversion.exe } # Let's get the current version string from CMakeLists.txt $version = (Get-Content $sourcedir\CMakeLists.txt | # Use Regex to find the current version string. Select-String -Pattern "(?<=set\(VERSION ).*(?=\))" | # Return only what the regex found, not the whole line. ForEach-Object {$_.Matches.Value}) # NSIS is very particular about how to format the version string. Must be numerical, and in the format x.x.x.x $nsisversion = $version + ".0" # Now build an NSIS package. Set-Alias nsis $nsisbinary $OUTDIR = $packagedir $nsisoutput = (nsis /NOCD /DVERSION=$nsisversion /DGITVERSION=$cfgitversion /DINPUTDIR=$releasedir /DSOURCELOCATION=$sourcedir /DOUTPUTDIR=$packagedir $sourcedir\gtk-v2\win32\client.nsi) $nsisoutput | Out-File -FilePath C:\autobuild\nsisoutput.txt if ($LASTEXITCODE -eq $true) {Write-Warning -Message "The NSIS process may not have exited cleanly. Check C:\autobuild\nsisoutput.txt for more info."} # Take the SHA256 of the NSIS file. If (Test-Path $packagedir\CrossfireClient-git-$cfgitversion.sha256) { Write-Warning -Message "A sha file already exists for this version's zipfile, we'll delete and recreate it." Remove-Item $packagedir\CrossfireClient-git-$cfgitversion.sha256 } pushd $packagedir C:\msys64\usr\bin\sha256sum.exe "CrossfireClient-git-$cfgitversion.exe" > $packagedir\CrossfireClient-git-$cfgitversion.sha256 popd Write-Progress -Activity "Building Crossfire Client" -Status "Finished!" -PercentComplete 100 Start-Sleep -Seconds 1 # If you modify this script, and can no longer run it due to an invalid signature, try removing everything below this line, to remove the signature entirely. # SIG # Begin signature block # MIImqQYJKoZIhvcNAQcCoIImmjCCJpYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUCVEIH86yt61oRy6EdCFlVCnv # Bx6ggh+7MIIFbzCCBFegAwIBAgIQSPyTtGBVlI02p8mKidaUFjANBgkqhkiG9w0B # AQwFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVy # MRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEh # MB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTIxMDUyNTAwMDAw # MFoXDTI4MTIzMTIzNTk1OVowVjELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3Rp # Z28gTGltaXRlZDEtMCsGA1UEAxMkU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5n # IFJvb3QgUjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjeeUEiIE # JHQu/xYjApKKtq42haxH1CORKz7cfeIxoFFvrISR41KKteKW3tCHYySJiv/vEpM7 # fbu2ir29BX8nm2tl06UMabG8STma8W1uquSggyfamg0rUOlLW7O4ZDakfko9qXGr # YbNzszwLDO/bM1flvjQ345cbXf0fEj2CA3bm+z9m0pQxafptszSswXp43JJQ8mTH # qi0Eq8Nq6uAvp6fcbtfo/9ohq0C/ue4NnsbZnpnvxt4fqQx2sycgoda6/YDnAdLv # 64IplXCN/7sVz/7RDzaiLk8ykHRGa0c1E3cFM09jLrgt4b9lpwRrGNhx+swI8m2J # mRCxrds+LOSqGLDGBwF1Z95t6WNjHjZ/aYm+qkU+blpfj6Fby50whjDoA7NAxg0P # OM1nqFOI+rgwZfpvx+cdsYN0aT6sxGg7seZnM5q2COCABUhA7vaCZEao9XOwBpXy # bGWfv1VbHJxXGsd4RnxwqpQbghesh+m2yQ6BHEDWFhcp/FycGCvqRfXvvdVnTyhe # Be6QTHrnxvTQ/PrNPjJGEyA2igTqt6oHRpwNkzoJZplYXCmjuQymMDg80EY2NXyc # uu7D1fkKdvp+BRtAypI16dV60bV/AK6pkKrFfwGcELEW/MxuGNxvYv6mUKe4e7id # FT/+IAx1yCJaE5UZkADpGtXChvHjjuxf9OUCAwEAAaOCARIwggEOMB8GA1UdIwQY # MBaAFKARCiM+lvEH7OKvKe+CpX/QMKS0MB0GA1UdDgQWBBQy65Ka/zWWSC8oQEJw # IDaRXBeF5jAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUE # DDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEMGA1Ud # HwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FBQUNlcnRpZmlj # YXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUAA4IBAQASv6Hvi3Sa # mES4aUa1qyQKDKSKZ7g6gb9Fin1SB6iNH04hhTmja14tIIa/ELiueTtTzbT72ES+ # BtlcY2fUQBaHRIZyKtYyFfUSg8L54V0RQGf2QidyxSPiAjgaTCDi2wH3zUZPJqJ8 # ZsBRNraJAlTH/Fj7bADu/pimLpWhDFMpH2/YGaZPnvesCepdgsaLr4CnvYFIUoQx # 2jLsFeSmTD1sOXPUC4U5IOCFGmjhp0g4qdE2JXfBjRkWxYhMZn0vY86Y6GnfrDyo # XZ3JHFuu2PMvdM+4fvbXg50RlmKarkUT2n/cR/vfw1Kf5gZV6Z2M8jpiUbzsJA8p # 1FiAhORFe1rYMIIGGjCCBAKgAwIBAgIQYh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG # 9w0BAQwFADBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk # MS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYw # HhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEY # MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1Ymxp # YyBDb2RlIFNpZ25pbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB # igKCAYEAmyudU/o1P45gBkNqwM/1f/bIU1MYyM7TbH78WAeVF3llMwsRHgBGRmxD # eEDIArCS2VCoVk4Y/8j6stIkmYV5Gej4NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk # 9vT0k2oWJMJjL9G//N523hAm4jF4UjrW2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7Xw # iunD7mBxNtecM6ytIdUlh08T2z7mJEXZD9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ # 0arWZVeffvMr/iiIROSCzKoDmWABDRzV/UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZX # nYvZQgWx/SXiJDRSAolRzZEZquE6cbcH747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+t # AfiWu01TPhCr9VrkxsHC5qFNxaThTG5j4/Kc+ODD2dX/fmBECELcvzUHf9shoFvr # n35XGf2RPaNTO2uSZ6n9otv7jElspkfK9qEATHZcodp+R4q2OIypxR//YEb3fkDn # 3UayWW9bAgMBAAGjggFkMIIBYDAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaR # XBeF5jAdBgNVHQ4EFgQUDyrLIIcouOxvSK4rVKYpqhekzQwwDgYDVR0PAQH/BAQD # AgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYD # VR0gBBQwEjAGBgRVHSAAMAgGBmeBDAEEATBLBgNVHR8ERDBCMECgPqA8hjpodHRw # Oi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RS # NDYuY3JsMHsGCCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5z # ZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LnA3YzAj # BggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEM # BQADggIBAAb/guF3YzZue6EVIJsT/wT+mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXK # ZDk8+Y1LoNqHrp22AKMGxQtgCivnDHFyAQ9GXTmlk7MjcgQbDCx6mn7yIawsppWk # vfPkKaAQsiqaT9DnMWBHVNIabGqgQSGTrQWo43MOfsPynhbz2Hyxf5XWKZpRvr3d # MapandPfYgoZ8iDL2OR3sYztgJrbG6VZ9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwF # kvjFV3jS49ZSc4lShKK6BrPTJYs4NG1DGzmpToTnwoqZ8fAmi2XlZnuchC4NPSZa # PATHvNIzt+z1PHo35D/f7j2pO1S8BCysQDHCbM5Mnomnq5aYcKCsdbh0czchOm8b # kinLrYrKpii+Tk7pwL7TjRKLXkomm5D1Umds++pip8wH2cQpf93at3VDcOK4N7Ew # oIJB0kak6pSzEu4I64U6gZs7tS/dGNSljf2OSSnRr7KWzq03zl8l75jy+hOds9TW # SenLbjBQUGR96cFr6lEUfAIEHVC1L68Y1GGxx4/eRI82ut83axHMViw1+sVpbPxg # 51Tbnio1lB93079WPFnYaOvfGAA0e0zcfF/M9gXr+korwQTh2Prqooq2bYNMvUoU # KD85gnJ+t0smrWrb8dee2CvYZXD5laGtaAxOfy/VKNmwuWuAh9kcMIIGPTCCBKWg # AwIBAgIQHTQSaFFD0/dtUy63brV68DANBgkqhkiG9w0BAQwFADBUMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTIyMDkwMTAwMDAwMFoXDTIz # MDkwMTIzNTk1OVowVDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCFZpcmdpbmlhMRgw # FgYDVQQKDA9OYXRoYW5pZWwgS2lwcHMxGDAWBgNVBAMMD05hdGhhbmllbCBLaXBw # czCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfdlvg7QFIfRd1c0nA5 # EjzQTls+2aEpgvDRpgl9zAljNLXYTgvQJfWT0/SJEAPKAewsIB9nVVjPSSe1qFak # db47cWj8zgLfRWwa6pnfu+ng4G7fOW7/2RrUVNfU+eO2Z1Yo7Iy/W2RUsayUxH+2 # hVt65O93t7PZiQ3MAGTQF80yTitkW8Omd/IgRo+MpETSCwKsaQzJUtFsW0Onzy9s # nkPJhs6bbg+YNoqVggkqvJZ8GlU2Ulv18jXqQMBruAJgaakoessmbL2eBgyYTtJf # R/rLK+D5EWnp0ZmTK2rDs8JhuxDhoRK2/5wiCwr3GhmYk2iZP/l0z0LM/zd2TkPF # 8TBsFczliBxd71AhjeZ9DtCrQR0ZlvxT+ycUENBPeLtroYf8kU2d/EWqWlLEw8C7 # B2rTJolV5Zb7CwMU3L99YZW9oRFrRrKLKCen2G2UEdCePMR4cGewnKxGOY2qHGIg # lb42S/yLPgl9nV9Pzkg6GPOoIrXFOaJWhppTjJvqaaxafmV0iOvabdgM3lLEElWb # PXubi36PNcZ8BTJDPvJ8clJIYrIqGO4OLoJ6vJVycZLJca+ClKSFFuC4aKU602Ge # uG26qtKuyKr7wo0Aa5OhmI2yahp9kk5wfVmlXcc+CBGV5XOdognmp3zjUoj4MoLN # ya6cB0BUZ8H5EdKp9JPnEMERAgMBAAGjggGJMIIBhTAfBgNVHSMEGDAWgBQPKssg # hyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQUtNsk0/UyW7UozUSsTrgdHL8NOPQw # DgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUH # AwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAjBggrBgEFBQcCARYXaHR0 # cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkGA1UdHwRCMEAwPqA8oDqG # OGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5n # Q0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEFBQcwAoY4aHR0cDovL2Ny # dC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcnQw # IwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMA0GCSqGSIb3DQEB # DAUAA4IBgQAuQ7bCCANjgqc+UXd1pquMpDuYP+f3G0TLei6KlwORGwAEZ5OcrCCI # NEtyPQ//pB/EkrAywwuAJklQ1ov7M6zm2YwRhJ6NFjxeeaBhZ3J9Y6doPabzGiYB # DuwYOGiUrXg/cI0yE66CtW9PmGK2pnZpG9L/0CnihBS2/aMxzHQP/JIVHIxTcXBX # Xa+LJ78M3CrpcAAs0EF3BUrFboqVp8AT+OgAzAvAXB+mOxK1oYBsrmF/C2FEh9aY # HCkk0lKjVauux4mVHNi3c3Tlj1Nq4RY0Z3GFybJCD5hUL7lW2xPPrwiv95NfccSd # TgQbGMfj0QRgYAq5paZuULEAQrIrE1pJUn4vH8nLwUD0A8mSnR6uwFHEvmeGMCx2 # 6UeZ5l1BfLpwVhbQGPVusDfPn07pogjX7vMZtgxEyCJacof7YBpNaoqT8K0wAzhn # WevGe06pGGF8VOoq2frqp4Ad2TUTQcX44MnTXL9VLsmJMoxhmJywHzPw5ss5CLl8 # Sh6YZAcyKiYwggbsMIIE1KADAgECAhAwD2+s3WaYdHypRjaneC25MA0GCSqGSIb3 # DQEBDAUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIG # A1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29y # azEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 # eTAeFw0xOTA1MDIwMDAwMDBaFw0zODAxMTgyMzU5NTlaMH0xCzAJBgNVBAYTAkdC # MRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQx # GDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDElMCMGA1UEAxMcU2VjdGlnbyBSU0Eg # VGltZSBTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB # AMgbAa/ZLH6ImX0BmD8gkL2cgCFUk7nPoD5T77NawHbWGgSlzkeDtevEzEk0y/NF # Zbn5p2QWJgn71TJSeS7JY8ITm7aGPwEFkmZvIavVcRB5h/RGKs3EWsnb111JTXJW # D9zJ41OYOioe/M5YSdO/8zm7uaQjQqzQFcN/nqJc1zjxFrJw06PE37PFcqwuCnf8 # DZRSt/wflXMkPQEovA8NT7ORAY5unSd1VdEXOzQhe5cBlK9/gM/REQpXhMl/VuC9 # RpyCvpSdv7QgsGB+uE31DT/b0OqFjIpWcdEtlEzIjDzTFKKcvSb/01Mgx2Bpm1gK # VPQF5/0xrPnIhRfHuCkZpCkvRuPd25Ffnz82Pg4wZytGtzWvlr7aTGDMqLufDRTU # GMQwmHSCIc9iVrUhcxIe/arKCFiHd6QV6xlV/9A5VC0m7kUaOm/N14Tw1/AoxU9k # gwLU++Le8bwCKPRt2ieKBtKWh97oaw7wW33pdmmTIBxKlyx3GSuTlZicl57rjsF4 # VsZEJd8GEpoGLZ8DXv2DolNnyrH6jaFkyYiSWcuoRsDJ8qb/fVfbEnb6ikEk1Bv8 # cqUUotStQxykSYtBORQDHin6G6UirqXDTYLQjdprt9v3GEBXc/Bxo/tKfUU2wfeN # gvq5yQ1TgH36tjlYMu9vGFCJ10+dM70atZ2h3pVBeqeDAgMBAAGjggFaMIIBVjAf # BgNVHSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUGqH4YRkg # D8NBd0UojtE1XwYSBFUwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8C # AQAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEQYDVR0gBAowCDAGBgRVHSAAMFAGA1Ud # HwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RS # U0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2BggrBgEFBQcBAQRqMGgwPwYI # KwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FB # ZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0 # LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAbVSBpTNdFuG1U4GRdd8DejILLSWEEbKw # 2yp9KgX1vDsn9FqguUlZkClsYcu1UNviffmfAO9Aw63T4uRW+VhBz/FC5RB9/7B0 # H4/GXAn5M17qoBwmWFzztBEP1dXD4rzVWHi/SHbhRGdtj7BDEA+N5Pk4Yr8TAcWF # o0zFzLJTMJWk1vSWVgi4zVx/AZa+clJqO0I3fBZ4OZOTlJux3LJtQW1nzclvkD1/ # RXLBGyPWwlWEZuSzxWYG9vPWS16toytCiiGS/qhvWiVwYoFzY16gu9jc10rTPa+D # BjgSHSSHLeT8AtY+dwS8BDa153fLnC6NIxi5o8JHHfBd1qFzVwVomqfJN2Udvuq8 # 2EKDQwWli6YJ/9GhlKZOqj0J9QVst9JkWtgqIsJLnfE5XkzeSD2bNJaaCV+O/fex # UpHOP4n2HKG1qXUfcb9bQ11lPVCBbqvw0NP8srMftpmWJvQ8eYtcZMzN7iea5aDA # DHKHwW5NWtMe6vBE5jJvHOsXTpTDeGUgOw9Bqh/poUGd/rG4oGUqNODeqPk85sEw # u8CgYyz8XBYAqNDEf+oRnR4GxqZtMl20OAkrSQeq/eww2vGnL8+3/frQo4TZJ577 # AWZ3uVYQ4SBuxq6x+ba6yDVdM3aO8XwgDCp3rrWiAoa6Ke60WgCxjKvj+QrJVF3U # uWp0nr1Irpgwggb1MIIE3aADAgECAhA5TCXhfKBtJ6hl4jvZHSLUMA0GCSqGSIb3 # DQEBDAUAMH0xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0 # ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEl # MCMGA1UEAxMcU2VjdGlnbyBSU0EgVGltZSBTdGFtcGluZyBDQTAeFw0yMzA1MDMw # MDAwMDBaFw0zNDA4MDIyMzU5NTlaMGoxCzAJBgNVBAYTAkdCMRMwEQYDVQQIEwpN # YW5jaGVzdGVyMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLDAqBgNVBAMMI1Nl # Y3RpZ28gUlNBIFRpbWUgU3RhbXBpbmcgU2lnbmVyICM0MIICIjANBgkqhkiG9w0B # AQEFAAOCAg8AMIICCgKCAgEApJMoUkvPJ4d2pCkcmTjA5w7U0RzsaMsBZOSKzXew # cWWCvJ/8i7u7lZj7JRGOWogJZhEUWLK6Ilvm9jLxXS3AeqIO4OBWZO2h5YEgciBk # QWzHwwj6831d7yGawn7XLMO6EZge/NMgCEKzX79/iFgyqzCz2Ix6lkoZE1ys/Oer # 6RwWLrCwOJVKz4VQq2cDJaG7OOkPb6lampEoEzW5H/M94STIa7GZ6A3vu03lPYxU # A5HQ/C3PVTM4egkcB9Ei4GOGp7790oNzEhSbmkwJRr00vOFLUHty4Fv9GbsfPGoZ # e267LUQqvjxMzKyKBJPGV4agczYrgZf6G5t+iIfYUnmJ/m53N9e7UJ/6GCVPE/Je # fKmxIFopq6NCh3fg9EwCSN1YpVOmo6DtGZZlFSnF7TMwJeaWg4Ga9mBmkFgHgM1C # daz7tJHQxd0BQGq2qBDu9o16t551r9OlSxihDJ9XsF4lR5F0zXUS0Zxv5F4Nm+x1 # Ju7+0/WSL1KF6NpEUSqizADKh2ZDoxsA76K1lp1irScL8htKycOUQjeIIISoh67D # uiNye/hU7/hrJ7CF9adDhdgrOXTbWncC0aT69c2cPcwfrlHQe2zYHS0RQlNxdMLl # NaotUhLZJc/w09CRQxLXMn2YbON3Qcj/HyRU726txj5Ve/Fchzpk8WBLBU/vuS/s # CRMCAwEAAaOCAYIwggF+MB8GA1UdIwQYMBaAFBqh+GEZIA/DQXdFKI7RNV8GEgRV # MB0GA1UdDgQWBBQDDzHIkSqTvWPz0V1NpDQP0pUBGDAOBgNVHQ8BAf8EBAMCBsAw # DAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBKBgNVHSAEQzBB # MDUGDCsGAQQBsjEBAgEDCDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28u # Y29tL0NQUzAIBgZngQwBBAIwRAYDVR0fBD0wOzA5oDegNYYzaHR0cDovL2NybC5z # ZWN0aWdvLmNvbS9TZWN0aWdvUlNBVGltZVN0YW1waW5nQ0EuY3JsMHQGCCsGAQUF # BwEBBGgwZjA/BggrBgEFBQcwAoYzaHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0 # aWdvUlNBVGltZVN0YW1waW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2Nz # cC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEATJtlWPrgec/vFcMybd4z # ket3WOLrvctKPHXefpRtwyLHBJXfZWlhEwz2DJ71iSBewYfHAyTKx6XwJt/4+DFl # DeDrbVFXpoyEUghGHCrC3vLaikXzvvf2LsR+7fjtaL96VkjpYeWaOXe8vrqRZIh1 # /12FFjQn0inL/+0t2v++kwzsbaINzMPxbr0hkRojAFKtl9RieCqEeajXPawhj3DD # JHk6l/ENo6NbU9irALpY+zWAT18ocWwZXsKDcpCu4MbY8pn76rSSZXwHfDVEHa1Y # GGti+95sxAqpbNMhRnDcL411TCPCQdB6ljvDS93NkiZ0dlw3oJoknk5fTtOPD+UT # T1lEZUtDZM9I+GdnuU2/zA2xOjDQoT1IrXpl5Ozf4AHwsypKOazBpPmpfTXQMkCg # sRkqGCGyyH0FcRpLJzaq4Jgcg3Xnx35LhEPNQ/uQl3YqEqxAwXBbmQpA+oBtlGF7 # yG65yGdnJFxQjQEg3gf3AdT4LhHNnYPl+MolHEQ9J+WwhkcqCxuEdn17aE+Nt/cT # tO2gLe5zD9kQup2ZLHzXdR+PEMSU5n4k5ZVKiIwn1oVmHfmuZHaR6Ej+yFUK7SnD # H944psAU+zI9+KmDYjbIw74Ahxyr+kpCHIkD3PVcfHDZXXhO7p9eIOYJanwrCKNI # 9RX8BE/fzSEceuX1jhrUuUAxggZYMIIGVAIBATBoMFQxCzAJBgNVBAYTAkdCMRgw # FgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGlj # IENvZGUgU2lnbmluZyBDQSBSMzYCEB00EmhRQ9P3bVMut261evAwCQYFKw4DAhoF # AKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisG # AQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcN # AQkEMRYEFP9G24ZEM+XbJIdxDCXKVODhr0fUMA0GCSqGSIb3DQEBAQUABIICACrV # 21fcI4CVKCB3eSyiAjADo3NM3H4HbsOieCfaXVGzqL+RL1UxM/7UrqIr4WsO+AVa # WOOwdnfP8iOyp2Saus30CJ6ube6dQhiktsqdFZfU45H6TYZYngwlHeRj/LoXhJE1 # MmjPUximyVGaMXphmjaYOAQu+EvWr/T4TTXSc25pkHZmR1jY+kdD80+OhdPJrTr2 # dWGmuyZU1/4K8rTDyyRFUI0gUroDWya3nvvylU/LYj3McmzUHEbNUq5P1SPic9Jk # CIep6ej2DvMDni+JKcDAq3jCa88dQV3xuwAtZ+Nb/jmFduGM+BTQCcJYWGMSA1o0 # N3I1wYU0TTe+4RmwRcVQkfx0zqPnEBW2AW/3GQ9eipwP7aZOi/g4qZd8Of2x4UDw # 4NIp/DZJNoHX9sCps3AAHxaBcVVt2DHVVD4h4l9kcPspIoXIo/DZUlt0LOFYISzD # NEi1dbjQNptkIV5Ev7Qcto1addOcOJTYL247tx8uoUn5i3v7hkTQ4ssdD69XSoQY # kDMTmjJ3pO1qQT4wtvOoF29L8zyHlNHE2uhD1lqfvkw/QY6oxhQOTePW55cJNaUa # rGmeQGYULeS8eqsAqjnqB2Egqjj+2RVE3npl2cpQmAHy35DOJMjohgr1ejWo/TEv # 10aMo4t+MPeYttO+xSXzgQPfxwKJCkgG8GPUOgCVoYIDSzCCA0cGCSqGSIb3DQEJ # BjGCAzgwggM0AgEBMIGRMH0xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVy # IE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28g # TGltaXRlZDElMCMGA1UEAxMcU2VjdGlnbyBSU0EgVGltZSBTdGFtcGluZyBDQQIQ # OUwl4XygbSeoZeI72R0i1DANBglghkgBZQMEAgIFAKB5MBgGCSqGSIb3DQEJAzEL # BgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIzMDYxOTIxNDE0N1owPwYJKoZI # hvcNAQkEMTIEMOQf41fIgghI2b73/kAw43xp4xw3igpiB9ogHNNuhDQzGHm1Qxng # xyVgOFHQlINepzANBgkqhkiG9w0BAQEFAASCAgBsYrfMRDWMxQwXQwL8f9SiOD03 # zn0yZOBJL/fQvl8c/cjDbVNZud897UtrHxzMVLXNGOdS6w+oGtnuV0ASafvP2Zxh # xLN2jp2hxBxwSutOOZAO0shVvqd8J3PK1kPTSeLwIStlz+gnAFIlHOAWcC/Sbk9e # KgIkJ18mexZXOtCv7JTGPb7ICUZIj5ZpCBEkRiWOoUnj1TLGUceNzq/uRl9EWSxW # 4lV0trTI6tt8KoP63pip2OiC1kdY+dyyAmzNllb6z/gW6lLekJ2/+qyHJUpoZ5EN # jh8FFK+MZhN1V01AoX3sTMiTOr8H2vu35zGj5OZwXgieGXncRJFrVCWfhnbhu49x # xuTC0rfdMI8YZ7r+mVpe5Eqoqr0X7BVeLD0ekM+wAaNrhCtR0e19fA09jqRs/2D/ # hI/fBixRV9m170fL2NGgMIIgXLLDADaizFFwA6GjSiiompJNt+Zqvy5akkNWMayp # ceNeAKG9bxqBfPZmVIR6d5HZdX9Gu0W7Dr6zxt48IFg7mIkvAlOHNGKkalXLRYHV # PhLNM11EQWmIdg7zIaIThGPoJo30XPHV0vNetk87llFUOLGCnAb2LsGoDre+UpLd # WlwHct5UlCdps9f+aK3Ups2Xguemh5Xtlh4u60Yx8U5KdvKnnEQ1y1wqQcCFy/QU # 6DR4O1+hUajAEJt8ag== # SIG # End signature block crossfire-client-1.75.3/gtk-v2/crossfire-client.desktop000644 001751 001751 00000000367 14045044330 023725 0ustar00kevinzkevinz000000 000000 [Desktop Entry] Name=Crossfire Client GenericName=Crossfire Client Comment=Cooperative multi-player RPG and adventure game Exec=crossfire-client-gtk2 Icon=crossfire-client Terminal=false Type=Application Categories=Game;AdventureGame;RolePlaying; crossfire-client-1.75.3/gtk-v2/src/000755 001751 001751 00000000000 14605665664 017665 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/gtk-v2/src/keys.c000644 001751 001751 00000254562 14323707640 021006 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file gtk-v2/src/keys.c * Handles most of the keyboard related functions - binding and unbinding keys, * and handling keypresses and looking up the keys. */ #include "client.h" #include #include #ifndef WIN32 #include #else #include #define NoSymbol 0L /**< Special KeySym */ typedef int KeyCode; /**< Undefined type */ #endif #include "main.h" #include "proto.h" #include "image.h" #include "gtk2proto.h" #include "p_cmd.h" struct keybind; static int keybind_remove(struct keybind *entry); static void keybind_free(struct keybind **entry); /** * @{ * @name UI Widgets * Widgets for the keybinding dialog */ static GtkWidget *fire_label, *run_label, *keybinding_window, *kb_scope_togglebutton_global, *kb_scope_togglebutton_character, *keybinding_checkbutton_any, *keybinding_checkbutton_control, *keybinding_checkbutton_shift, *keybinding_checkbutton_alt, *keybinding_checkbutton_meta, *keybinding_checkbutton_edit, *keybinding_entry_key, *keybinding_entry_command, *keybinding_treeview, *keybinding_button_remove, *keybinding_button_update, *keybinding_button_bind; static GtkListStore *keybinding_store; /**= 0.*/ guint32 keysym; /**< Key this binding record is for. */ char *command; /**< Command string bound to a key. */ struct keybind *next; }; /*********************************************************************** * * Key board input translations are handled here. We don't deal with * the events, but rather KeyCodes and KeySyms. * * It would be nice to deal with only KeySyms, but many keyboards * have keys that do not correspond to a KeySym, so we do need to * support KeyCodes. * ***********************************************************************/ static guint32 firekeysym[2], runkeysym[2], commandkeysym, *bind_keysym, prevkeysym, nextkeysym, completekeysym, altkeysym[2], metakeysym[2], cancelkeysym; static int bind_flags = 0; static char bind_buf[MAX_BUF]; /* * Key modifiers * * The Run, Fire, Alt and/or Meta keys can be used to qualify a key * (i.e. a keybinding of the key 's' with the KEYF_RUN and KEYF_FIRE * flags set will only match if both Run and Fire are held while 's' is * pressed). * * If the user wants a key to match no matter the state of the modifier * keys, the KEYF_ANY flag must be set in the binding. */ #define KEYF_MOD_SHIFT (1 << 0) /**< Used in fire mode */ #define KEYF_MOD_CTRL (1 << 1) /**< Used in run mode */ #define KEYF_MOD_ALT (1 << 2) /**< For ALT key modifier */ #define KEYF_MOD_META (1 << 3) /**< For Meta key modifier */ #define KEYF_MOD_MASK (KEYF_MOD_SHIFT | \ KEYF_MOD_CTRL | \ KEYF_MOD_ALT | \ KEYF_MOD_META) #define KEYF_ANY (1 << 4) /**< Don't care about modifiers */ #define KEYF_EDIT (1 << 5) /**< Enter command mode */ /* Keybinding's scope, decides where the binding will be saved */ #define KEYF_R_GLOBAL (1 << 6) /**< Save at user's file */ #define KEYF_R_CHAR (1 << 7) /**< Character specific */ extern const char *const directions[9]; #define KEYHASH 257 /** * Will hold the keybindings into two separate hashes depending on * the scope they afect (global or character). * This allows editting both scopes at the same time and switch scopes * for a certain binding with ease. * * Platform independence defines that we can't use keycodes. Instead, * make it a hash, and set KEYHASH to a prime number for this purpose. */ static struct keybind *keys_global[KEYHASH], *keys_char[KEYHASH]; /** * @defgroup GtkV2KeyBinding GTK-V2 client keybinding functions. * @{ */ #define EKEYBIND_NOMEM 1 /** * When a key is held down, prevent multiple commands from being sent without * server acknowledgement by setting debounce when keys are pressed, and * clearing it when the server acknowledges or when a key is released. */ static bool debounce = false; /** * Find a keybinding for keysym. * * Make it possible to match a specific keysym-and-key-modifier combo * (useful in game play), or to match keysym regardless of modifier. * * @param flags If flags has got KEYF_ANY set, the keybinding's own * flags are ignored and any match is returned. * If a keybinding matching keysym which has got KEYF_ANY * set is found, the flags param is ignored and the binding * is returned. * Otherwise, return only bindings with matching modifier * flags. * @param scope Determines which scope to search for the binding. * 0 meaning char scope, non zero meaning global scope. */ static struct keybind *keybind_find(guint32 keysym, unsigned int flags, int scope) { struct keybind *kb; kb = scope ? keys_global[keysym % KEYHASH] : keys_char[keysym % KEYHASH]; while (kb != NULL) { if (kb->keysym == 0 || kb->keysym == keysym) { if ((kb->flags & KEYF_ANY) || (flags & KEYF_ANY)) { return kb; } if ((kb->flags & KEYF_MOD_MASK) == (flags & KEYF_MOD_MASK)) { return kb; } } kb = kb->next; } return NULL; } /** * Updates the keys array with the keybinding that is passed. It allocates * memory for the array entry, then uses strdup_local() to allocate memory * for the command being bound. This function is common to both gdk and x11 * client. * * @param keysym A key to bind. * @param flags State that the keyboard is in. * @param command A command to bind to the key specified in keysym. */ static int keybind_insert(guint32 keysym, unsigned int flags, const char *command) { struct keybind **next_ptr, *kb; int slot; int i; int dir; kb = keybind_find(keysym, flags, (flags & KEYF_R_GLOBAL)); while (kb != NULL) { /* * Keep the last binding instead of the first (backwards compatible). * * Also, if the new binding has the ANY flag, remove all matching * previous bindings and keep this one. */ LOG(LOG_DEBUG, "gtk-v2::keybind_insert", "Overwriting previous binding for key %s with command %s ", gdk_keyval_name(keysym), kb->command); keybind_remove(kb); keybind_free(&kb); kb = keybind_find(keysym, flags, (flags & KEYF_R_GLOBAL)); } slot = keysym % KEYHASH; next_ptr = (flags & KEYF_R_GLOBAL) ? &keys_global[slot] : &keys_char[slot]; while (*next_ptr) { next_ptr = &(*next_ptr)->next; } *next_ptr = calloc(1, sizeof(**next_ptr)); if (*next_ptr == NULL) { return -EKEYBIND_NOMEM; } (*next_ptr)->keysym = keysym; (*next_ptr)->flags = flags; (*next_ptr)->command = g_strdup(command); /* * Try to find out if the command is a direction command. If so, keep * track of this fact, so in fire or run mode, things work correctly. */ dir = -1; for (i = 0; i < 9; i++) { if (!strcmp(command, directions[i])) { dir = i; break; } } (*next_ptr)->direction = dir; return 0; } static int keybind_remove(struct keybind *entry) { struct keybind **next_ptr; int slot; slot = entry->keysym % KEYHASH; next_ptr = (entry->flags & KEYF_R_GLOBAL) ? &keys_global[slot] : &keys_char[slot]; while (*next_ptr) { if (*next_ptr == entry) { *next_ptr = entry->next; return 0; } next_ptr = &(*next_ptr)->next; } /* No such key entry */ return -1; } static void keybind_free(struct keybind **entry) { free((*entry)->command); (*entry)->command = NULL; free(*entry); *entry = NULL; } /** * This function is common to both gdk and x11 client * * @param buf * @param line * @param scope_flag KEYF_R_GLOBAL or KEYF_R_CHAR determining scope. */ static void parse_keybind_line(char *buf, int line, unsigned int scope_flag) { char *cp, *cpnext; guint32 keysym, low_keysym; int flags; /* * There may be a rare error case when cp is used uninitialized. So let's * be safe */ cp = NULL; if (buf[0] == '\0' || buf[0] == '#' || buf[0] == '\n') { return; } cpnext = strchr(buf, ' '); if (cpnext == NULL) { LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Line %d (%s) corrupted in keybinding file.", line, buf); return; } /* Special keybinding line */ if (buf[0] == '!') { char *cp1; while (*cpnext == ' ') { ++cpnext; } cp = strchr(cpnext, ' '); if (!cp) { LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Line %d (%s) corrupted in keybinding file.", line, buf); return; } *cp++ = 0; /* Null terminate it */ cp1 = strchr(cp, ' '); if (!cp1) { LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Line %d (%s) corrupted in keybinding file.", line, buf); return; } *cp1++ = 0; /* Null terminate it */ keysym = gdk_keyval_from_name(cp); /* As of now, all these keys must have keysyms */ if (keysym == 0) { LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Could not convert %s into keysym", cp); return; } if (!strcmp(cpnext, "commandkey")) { commandkeysym = keysym; return; } if (!strcmp(cpnext, "altkey0")) { altkeysym[0] = keysym; return; } if (!strcmp(cpnext, "altkey1")) { altkeysym[1] = keysym; return; } if (!strcmp(cpnext, "firekey0")) { firekeysym[0] = keysym; return; } if (!strcmp(cpnext, "firekey1")) { firekeysym[1] = keysym; return; } if (!strcmp(cpnext, "metakey0")) { metakeysym[0] = keysym; return; } if (!strcmp(cpnext, "metakey1")) { metakeysym[1] = keysym; return; } if (!strcmp(cpnext, "runkey0")) { runkeysym[0] = keysym; return; } if (!strcmp(cpnext, "runkey1")) { runkeysym[1] = keysym; return; } if (!strcmp(cpnext, "completekey")) { completekeysym = keysym; return; } if (!strcmp(cpnext, "nextkey")) { nextkeysym = keysym; return; } if (!strcmp(cpnext, "prevkey")) { prevkeysym = keysym; return; } } else { *cpnext++ = '\0'; keysym = gdk_keyval_from_name(buf); if (!keysym) { LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Unable to convert line %d (%s) into keysym", line, buf); return; } cp = cpnext; cpnext = strchr(cp, ' '); if (cpnext == NULL) { LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Line %d (%s) corrupted in keybinding file.", line, cp); return; } *cpnext++ = '\0'; cp = cpnext; cpnext = strchr(cp, ' '); if (cpnext == NULL) { LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Line %d (%s) corrupted in keybinding file.", line, cp); return; } *cpnext++ = '\0'; flags = 0; low_keysym = gdk_keyval_to_lower(keysym); if (low_keysym != keysym) { /* This binding is uppercase, switch to lowercase and flag the shift modifier */ flags |= KEYF_MOD_SHIFT; keysym = low_keysym; } while (*cp != '\0') { switch (*cp) { case 'A': flags |= KEYF_ANY; break; case 'E': flags |= KEYF_EDIT; break; case 'F': flags |= KEYF_MOD_SHIFT; break; case 'L': /* A is used, so using L for alt */ flags |= KEYF_MOD_ALT; break; case 'M': flags |= KEYF_MOD_META; break; case 'N': /* Nothing to do */ break; case 'R': flags |= KEYF_MOD_CTRL; break; case 'S': LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Deprecated flag (S) ignored at line %d in key binding file", line); break; default: LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Unknown flag (%c) line %d in key binding file", *cp, line); } cp++; } if (strlen(cpnext) > (sizeof(bind_buf) - 1)) { cpnext[sizeof(bind_buf) - 1] = '\0'; LOG(LOG_WARNING, "gtk-v2::parse_keybind_line", "Command too long! Truncated."); } flags |= scope_flag; /* add the corresponding scope flag */ // If there is a trailing CR, remove it. cpnext[strcspn(cpnext, "\r")] = 0; keybind_insert(keysym, flags, cpnext); } /* else if not special binding line */ } /** * Opens a file and loads the keybinds contained in it. * * @param filename Name of the file to open. * @param scope_flag The scope this bindings should be loaded with. * Should be one of KEYF_R_GLOBAL or KEYF_R_CHAR. * Every binding in the file will have the same scope. */ static int parse_keys_file(GInputStream *in, unsigned int scope_flag) { GDataInputStream *stream = g_data_input_stream_new(in); int line_no = 0; char *line; while ((line = g_data_input_stream_read_line(stream, NULL, NULL, NULL)) != NULL) { line_no++; parse_keybind_line(line, line_no, scope_flag); } return 0; } /** * Load pre-compiled built-in default keybindings. */ static void init_default_keybindings() { LOG(LOG_DEBUG, "init_default_keybindings", "Loading default keybindings"); GInputStream *in = g_resources_open_stream("/org/crossfire/client/common/def-keys", 0, NULL); if (in == NULL) { g_error("could not load default keybindings"); } parse_keys_file(in, KEYF_R_GLOBAL); g_object_unref(in); } /** * Reads in the keybindings, and initializes special values. Called * from main() as part of the client start up. The function is common to both * the x11 and gdk clients. */ void keybindings_init(const char *character_name) { char buf[BIG_BUF]; int i; /* Clear out the bind history. */ for (i = 0; i < MAX_HISTORY; i++) { history[i][0] = 0; } commandkeysym = GDK_KEY_apostrophe; firekeysym[0] = GDK_KEY_Shift_L; firekeysym[1] = GDK_KEY_Shift_R; runkeysym[0] = GDK_KEY_Control_L; runkeysym[1] = GDK_KEY_Control_R; metakeysym[0] = GDK_KEY_Meta_L; metakeysym[1] = GDK_KEY_Meta_R; altkeysym[0] = GDK_KEY_Alt_L; altkeysym[1] = GDK_KEY_Alt_R; completekeysym = GDK_KEY_Tab; cancelkeysym = GDK_KEY_Escape; /* * Don't set these to anything by default. At least on Sun keyboards, the * keysym for up on both the keypad and arrow keys is the same, so player * needs to rebind this so we get proper keycode. Very unfriendly to log * in and not be able to move north/south. */ nextkeysym = NoSymbol; prevkeysym = NoSymbol; for (i = 0; i < KEYHASH; i++) { while (keys_global[i]) { keybind_remove(keys_global[i]); } while (keys_char[i]) { keybind_remove(keys_char[i]); } } /* * If we were supplied with a character name, store it so that we * can load and save a character-specific keys file. */ if (cpl.name) { free(cpl.name); cpl.name = NULL; } if (character_name) { cpl.name = g_strdup(character_name); } /* * We now try to load the keybindings. First load defaults. * Then go through the more specific files in the home directory: * 1) user wide "~/.crossfire/keys". * 2) and, if character name is known, "~/.crossfire/.keys" * * The format is described in the def_keys file. Note that this file is * the same as what it was in the server distribution. To convert bindings * in character files to this format, all that needs to be done is remove * the 'key ' at the start of each line. */ init_default_keybindings(); /* Try to load global keybindings. */ snprintf(buf, sizeof(buf), "%s/keys", config_dir); GFile *f = g_file_new_for_path(buf); GFileInputStream * fs = g_file_read(f, NULL, NULL); if (fs != NULL) { GInputStream *in = G_INPUT_STREAM(fs); if (in != NULL) { LOG(LOG_DEBUG, "keybindings_init", "Loading global keybindings"); parse_keys_file(in, KEYF_R_GLOBAL); g_object_unref(in); } g_object_unref(fs); } g_object_unref(f); /* Try to load the character-specific keybindings. */ if (cpl.name) { snprintf(buf, sizeof(buf), "%s/%s.%s.keys", config_dir, csocket.servername, cpl.name); GFile *f = g_file_new_for_path(buf); GFileInputStream * fs = g_file_read(f, NULL, NULL); if (fs != NULL) { GInputStream *in = G_INPUT_STREAM(fs); if (in != NULL) { LOG(LOG_DEBUG, "keybindings_init", "Loading character keybindings for '%s'", cpl.name); parse_keys_file(in, KEYF_R_CHAR); g_object_unref(in); } g_object_unref(fs); } else { LOG(LOG_DEBUG, "keybindings_init", "No character keybindings for '%s' found", cpl.name); } g_object_unref(f); } else { LOG(LOG_DEBUG, "keybindings_init", "No character name"); } } static void on_count_changed(GtkSpinButton *spinbutton, gpointer *data) { cpl.count = gtk_spin_button_get_value_as_int(spinbutton); } /** * One-time initialization of windows and signals for the keybindings * dialog. It is called from main() as part of the client start up. The * function is common to both the x11 and gdk clients. * * @param window_root The client's main window. */ void keys_init(GtkWidget *window_root) { GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkWidget *widget; int i; fire_label = GTK_WIDGET(gtk_builder_get_object(window_xml, "fire_label")); run_label = GTK_WIDGET(gtk_builder_get_object(window_xml, "run_label")); entry_commands = GTK_WIDGET(gtk_builder_get_object(window_xml, "entry_commands")); spinbutton_count = GTK_WIDGET(gtk_builder_get_object(window_xml, "spinbutton_count")); g_signal_connect(spinbutton_count, "value-changed", G_CALLBACK(on_count_changed), NULL); g_signal_connect((gpointer) entry_commands, "activate", G_CALLBACK(on_entry_commands_activate), NULL); keybinding_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_window")); kb_scope_togglebutton_global = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "kb_scope_togglebutton_global")); kb_scope_togglebutton_character = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "kb_scope_togglebutton_character")); keybinding_checkbutton_any = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_checkbutton_any")); keybinding_checkbutton_control = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_checkbutton_control")); keybinding_checkbutton_shift = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_checkbutton_shift")); keybinding_checkbutton_alt = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_checkbutton_alt")); keybinding_checkbutton_meta = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_checkbutton_meta")); keybinding_checkbutton_edit = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_checkbutton_stayinedit")); keybinding_entry_key = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_entry_key")); keybinding_entry_command = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_entry_command")); keybinding_treeview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_treeview")); keybinding_button_remove = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_button_remove")); keybinding_button_update = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_button_update")); keybinding_button_bind = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_button_bind")); g_signal_connect((gpointer) keybinding_window, "delete_event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect((gpointer) keybinding_entry_key, "key_press_event", G_CALLBACK(on_keybinding_entry_key_key_press_event), NULL); g_signal_connect((gpointer) keybinding_button_remove, "clicked", G_CALLBACK(on_keybinding_button_remove_clicked), NULL); g_signal_connect((gpointer) keybinding_button_update, "clicked", G_CALLBACK(on_keybinding_button_update_clicked), NULL); g_signal_connect((gpointer) keybinding_button_bind, "clicked", G_CALLBACK(on_keybinding_button_bind_clicked), NULL); g_signal_connect((gpointer) kb_scope_togglebutton_character, "toggled", G_CALLBACK(on_kb_scope_togglebutton_character_toggled), NULL); g_signal_connect((gpointer) kb_scope_togglebutton_global, "toggled", G_CALLBACK(on_kb_scope_togglebutton_global_toggled), NULL); g_signal_connect((gpointer) keybinding_checkbutton_any, "clicked", G_CALLBACK(on_keybinding_checkbutton_any_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_button_clear")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_keybinding_button_clear_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "keybinding_button_close")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_keybinding_button_close_clicked), NULL); gtk_widget_set_sensitive(keybinding_button_remove, FALSE); gtk_widget_set_sensitive(keybinding_button_update, FALSE); keybinding_store = gtk_list_store_new(7, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER ); gtk_tree_view_set_model(GTK_TREE_VIEW(keybinding_treeview), GTK_TREE_MODEL(keybinding_store)); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", KLIST_KEY, NULL); gtk_tree_view_column_set_sort_column_id(column, KLIST_KEY); gtk_tree_view_append_column(GTK_TREE_VIEW(keybinding_treeview), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Modifiers", renderer, "text", KLIST_MODS, NULL); gtk_tree_view_column_set_sort_column_id(column, KLIST_MODS); gtk_tree_view_append_column(GTK_TREE_VIEW(keybinding_treeview), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Scope", renderer, "text", KLIST_SCOPE, NULL); gtk_tree_view_column_set_sort_column_id(column, KLIST_SCOPE); gtk_tree_view_append_column(GTK_TREE_VIEW(keybinding_treeview), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Edit Mode", renderer, "text", KLIST_EDIT, NULL); gtk_tree_view_column_set_sort_column_id(column, KLIST_EDIT); gtk_tree_view_append_column(GTK_TREE_VIEW(keybinding_treeview), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Command", renderer, "text", KLIST_COMMAND, NULL); gtk_tree_view_column_set_sort_column_id(column, KLIST_COMMAND); gtk_tree_view_append_column(GTK_TREE_VIEW(keybinding_treeview), column); keybinding_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW( keybinding_treeview)); gtk_tree_selection_set_mode(keybinding_selection, GTK_SELECTION_BROWSE); gtk_tree_selection_set_select_function(keybinding_selection, keybinding_selection_func, NULL, NULL); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(keybinding_store), KLIST_KEY, GTK_SORT_ASCENDING); for (i = 0; i < KEYHASH; i++) { keys_global[i] = NULL; keys_char[i] = NULL; } } /** * The only things we actually care about is the run and fire keys. Other key * releases are not important. If it is the release of a run or fire key, we * tell the client to stop firing or running. In some cases, it is possible * that we actually are not running or firing, and in such cases, the server * will just ignore the command. * * This code is used by gdk and x11 client, but has a fair number of ifdefs to * get the right behavior. * * @param ks */ static void parse_key_release(guint32 keysym) { /* * Only send stop firing/running commands if we are in actual play mode. * Something smart does need to be done when the character enters a non * play mode with fire or run mode already set, however. */ if (keysym == firekeysym[0] || keysym == firekeysym[1]) { cpl.fire_on = 0; clear_fire(); gtk_label_set_text(GTK_LABEL(fire_label), " "); } else if (keysym == runkeysym[0] || keysym == runkeysym[1]) { cpl.run_on = 0; clear_run(); gtk_label_set_text(GTK_LABEL(run_label), " "); } else if (keysym == altkeysym[0] || keysym == altkeysym[1]) { cpl.alt_on = 0; } else if (keysym == metakeysym[0] || keysym == metakeysym[1]) { cpl.meta_on = 0; } /* * Firing is handled on server side. However, to keep more like the old * version, if you release the direction key, you want the firing to stop. * This should do that. */ else if (cpl.fire_on) { clear_fire(); } } /** * Parses a keypress. It should only be called when in Playing mode. * * @param key * @param keysym */ static void parse_key(char key, guint32 keysym) { struct keybind *kb; int present_flags = 0; char buf[MAX_BUF], tmpbuf[MAX_BUF]; /* We handle the Shift key separately */ keysym = gdk_keyval_to_lower(keysym); if (keysym == commandkeysym) { gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); gtk_entry_set_visibility(GTK_ENTRY(entry_commands), 1); cpl.input_state = Command_Mode; cpl.no_echo = FALSE; return; } if (keysym == altkeysym[0] || keysym == altkeysym[1]) { cpl.alt_on = 1; return; } if (keysym == metakeysym[0] || keysym == metakeysym[1]) { cpl.meta_on = 1; return; } if (keysym == firekeysym[0] || keysym == firekeysym[1]) { cpl.fire_on = 1; gtk_label_set_text(GTK_LABEL(fire_label), "Fire"); return; } if (keysym == runkeysym[0] || keysym == runkeysym[1]) { cpl.run_on = 1; gtk_label_set_text(GTK_LABEL(run_label), "Run"); return; } present_flags = 0; if (cpl.run_on) { present_flags |= KEYF_MOD_CTRL; } if (cpl.fire_on) { present_flags |= KEYF_MOD_SHIFT; } if (cpl.alt_on) { present_flags |= KEYF_MOD_ALT; } if (cpl.meta_on) { present_flags |= KEYF_MOD_META; } kb = keybind_find(keysym, present_flags, 0); /* char scope */ if (kb == NULL) { kb = keybind_find(keysym, present_flags, 1); /* global scope */ } if (kb != NULL) { if (kb->flags & KEYF_EDIT) { strcpy(cpl.input_text, kb->command); cpl.input_state = Command_Mode; gtk_entry_set_text(GTK_ENTRY(entry_commands), cpl.input_text); gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); gtk_editable_select_region(GTK_EDITABLE(entry_commands), 0, 0); gtk_editable_set_position(GTK_EDITABLE(entry_commands), -1); return; } if (kb->direction >= 0) { if (cpl.fire_on) { snprintf(buf, sizeof(buf), "fire %s", kb->command); fire_dir(kb->direction); } else if (cpl.run_on) { snprintf(buf, sizeof(buf), "run %s", kb->command); run_dir(kb->direction); } else { extended_command(kb->command); } } else { extended_command(kb->command); } return; } if (key >= '0' && key <= '9') { cpl.count = cpl.count * 10 + (key - '0'); if (cpl.count > 100000) { cpl.count %= 100000; } gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton_count), (float) cpl.count); return; } tmpbuf[0] = 0; if (cpl.fire_on) { strcat(tmpbuf, "fire+"); } if (cpl.run_on) { strcat(tmpbuf, "run+"); } if (cpl.alt_on) { strcat(tmpbuf, "alt+"); } if (cpl.meta_on) { strcat(tmpbuf, "meta+"); } snprintf(buf, sizeof(buf), "Key %s%s is not bound to any command. Use 'bind' to associate this keypress with a command", tmpbuf, keysym == NoSymbol ? "unknown" : gdk_keyval_name(keysym)); #ifdef WIN32 if ((65513 != keysym) && (65511 != keysym)) #endif draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); cpl.count = 0; } static void get_key_modchars(struct keybind *kb, int save_mode, char *buf) { int bi = 0; if (kb->flags & KEYF_ANY) { buf[bi++] = 'A'; } if (save_mode || !(kb->flags & KEYF_ANY)) { if ((kb->flags & KEYF_MOD_MASK) == 0) { buf[bi++] = 'N'; } if (kb->flags & KEYF_MOD_SHIFT) { buf[bi++] = 'F'; } if (kb->flags & KEYF_MOD_CTRL) { buf[bi++] = 'R'; } if (kb->flags & KEYF_MOD_ALT) { buf[bi++] = 'L'; } if (kb->flags & KEYF_MOD_META) { buf[bi++] = 'M'; } } if (kb->flags & KEYF_EDIT) { buf[bi++] = 'E'; } buf[bi] = '\0'; } /** * * @param key * @param save_mode If true, it means that the format used for saving the * information is used, instead of the usual format for displaying the * information in a friendly manner. * @return A character string describing the key. */ static char *get_key_info(struct keybind *kb, int save_mode) { /* bind buf is the maximum space allowed for a * bound command. We will add additional data to * it so we increase its size by MAX_BUF*/ static char buf[MAX_BUF + sizeof(bind_buf)]; char buff[MAX_BUF]; get_key_modchars(kb, save_mode, buff); if (save_mode) { if (kb->keysym == NoSymbol) { snprintf(buf, sizeof(buf), "(null) %i %s %s", 0, buff, kb->command); } else { snprintf(buf, sizeof(buf), "%s %i %s %s", gdk_keyval_name(kb->keysym), 0, buff, kb->command); } } else { if (kb->keysym == NoSymbol) { snprintf(buf, sizeof(buf), "key (null) %s %s", buff, kb->command); } else { snprintf(buf, sizeof(buf), "key %s %s %s", gdk_keyval_name(kb->keysym), buff, kb->command); } } return buf; } /** * Shows all the keybindings. * * @param allbindings Also shows the standard (default) keybindings. */ static void show_keys(void) { int i, j, count = 1; struct keybind *kb; char buf[MAX_BUF]; snprintf(buf, sizeof(buf), "Commandkey %s", commandkeysym == NoSymbol ? "unknown" : gdk_keyval_name(commandkeysym)); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); snprintf(buf, sizeof(buf), "Firekeys 1: %s, 2: %s", firekeysym[0] == NoSymbol ? "unknown" : gdk_keyval_name(firekeysym[0]), firekeysym[1] == NoSymbol ? "unknown" : gdk_keyval_name(firekeysym[1])); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); snprintf(buf, sizeof(buf), "Altkeys 1: %s, 2: %s", altkeysym[0] == NoSymbol ? "unknown" : gdk_keyval_name(altkeysym[0]), altkeysym[1] == NoSymbol ? "unknown" : gdk_keyval_name(altkeysym[1])); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); snprintf(buf, sizeof(buf), "Metakeys 1: %s, 2: %s", metakeysym[0] == NoSymbol ? "unknown" : gdk_keyval_name(metakeysym[0]), metakeysym[1] == NoSymbol ? "unknown" : gdk_keyval_name(metakeysym[1])); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); snprintf(buf, sizeof(buf), "Runkeys 1: %s, 2: %s", runkeysym[0] == NoSymbol ? "unknown" : gdk_keyval_name(runkeysym[0]), runkeysym[1] == NoSymbol ? "unknown" : gdk_keyval_name(runkeysym[1])); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); snprintf(buf, sizeof(buf), "Command Completion Key %s", completekeysym == NoSymbol ? "unknown" : gdk_keyval_name(completekeysym)); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); snprintf(buf, sizeof(buf), "Next Command in History Key %s", nextkeysym == NoSymbol ? "unknown" : gdk_keyval_name(nextkeysym)); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); snprintf(buf, sizeof(buf), "Previous Command in History Key %s", prevkeysym == NoSymbol ? "unknown" : gdk_keyval_name(prevkeysym)); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); /* * Perhaps we should start at 8, so that we only show 'active' keybindings? */ for (i = 0; i < KEYHASH; i++) { for (j = 0; j < 2; j++) { for (kb = (j == 0) ? keys_global[i] : keys_char[i]; kb != NULL; kb = kb->next) { snprintf(buf, sizeof(buf), "%3d %s", count, get_key_info(kb, 0)); draw_ext_info( NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); count++; } } } } /** * Implements the "bind" command when entered as a text command. It parses the * command options, records the command to bind, then prompts the user to press * a key to bind. It also shows help for the bind command if the player types * bind with no parameters. * * @param params If null, show bind command help in the message pane. */ void bind_key(char *params) { char buf[MAX_BUF + 16]; if (!params) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Usage: 'bind -ei {,commandkey,firekey{1,2},runkey{1,2},altkey{1,2},metakey{1,2},completekey,nextkey,prevkey}'\n" "Where\n" " -e means enter edit mode\n" " -g means this binding should be global (used for all your characters)\n" " -i means ignore modifier keys (keybinding works no matter if Ctrl/Alt etc are held)"); return; } /* Skip over any spaces we may have */ while (*params == ' ') { params++; } if (!strcmp(params, "commandkey")) { bind_keysym = &commandkeysym; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new commandkey."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "firekey1")) { bind_keysym = &firekeysym[0]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new firekey 1."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "firekey2")) { bind_keysym = &firekeysym[1]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new firekey 2."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "metakey1")) { bind_keysym = &metakeysym[0]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new metakey 1."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "metakey2")) { bind_keysym = &metakeysym[1]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new metakey 2."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "altkey1")) { bind_keysym = &altkeysym[0]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new altkey 1."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "altkey2")) { bind_keysym = &altkeysym[1]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new altkey 2."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "runkey1")) { bind_keysym = &runkeysym[0]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new runkey 1."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "runkey2")) { bind_keysym = &runkeysym[1]; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new runkey 2."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "completekey")) { bind_keysym = &completekeysym; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new command completion key"); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "prevkey")) { bind_keysym = &prevkeysym; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new previous command in history key."); cpl.input_state = Configure_Keys; return; } if (!strcmp(params, "nextkey")) { bind_keysym = &nextkeysym; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, "Push key to bind new next command in history key."); cpl.input_state = Configure_Keys; return; } bind_keysym = NULL; bind_flags = 0; if (params[0] == '-') { for (params++; *params != ' '; params++) switch (*params) { case 'e': bind_flags |= KEYF_EDIT; break; case 'i': bind_flags |= KEYF_ANY; break; case 'g': bind_flags |= KEYF_R_GLOBAL; break; case '\0': draw_ext_info( NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Use unbind to remove bindings."); return; default: snprintf(buf, sizeof(buf), "Unsupported or invalid bind flag: '%c'", *params); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, buf); return; } params++; } if (!params[0]) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Use unbind to remove bindings."); return; } if (strlen(params) >= sizeof(bind_buf)) { params[sizeof(bind_buf) - 1] = '\0'; draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, "Keybinding too long! Truncated:"); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, params); } snprintf(buf, sizeof(buf), "Push key to bind '%s'.", params); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, buf); strcpy(bind_buf, params); cpl.input_state = Configure_Keys; return; } /** * A recursive function that saves all the entries for a particular entry. We * save the first element first, and then go through and save the rest of the * elements. In this way, the ordering of the key entries in the file remains * the same. * * @param fp Pointer to an open file for writing key bind settings into. * @param key Pointer of a key hash record to save to the key bind file. * During recursion, key takes the value key->next, and then * returns when it becomes a NULL pointer. * @param kc */ static void save_individual_key(FILE *fp, struct keybind *kb, KeyCode kc) { while (kb) { fprintf(fp, "%s\n", get_key_info(kb, 1)); kb = kb->next; } } /** * Saves the keybindings into the user's .crossfire/keys file. The output * file is opened, then the special shift/modifier keys are written first. * Next, the entire key hash is traversed and the contents of each slot is * dumped to the file, and the output file is closed. Success or failure is * reported to the message pane. */ static void save_keys(void) { char buf[MAX_BUF], buf2[MAX_BUF]; int i; FILE *fp; /* If we are logged in open file to save character specific bindings */ if (cpl.name) { snprintf(buf, sizeof(buf), "%s/%s.%s.keys", config_dir, csocket.servername, cpl.name); LOG(LOG_INFO, "gtk-v2::save_keys", "Saving character specific keybindings to %s", buf); if (make_path_to_file(buf) == -1) { LOG(LOG_WARNING, "gtk-v2::save_keys", "Could not create %s", buf); } fp = fopen(buf, "w"); if (fp == NULL) { snprintf(buf2, sizeof(buf2), "Could not open %s, character bindings not saved\n", buf); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, buf2); } else { for (i = 0; i < KEYHASH; i++) { save_individual_key(fp, keys_char[i], 0); } fclose(fp); } } /* Open file to save global user bindings */ snprintf(buf, sizeof(buf), "%s/keys", config_dir); LOG(LOG_INFO, "gtk-v2::save_keys", "Saving global user's keybindings to %s", buf); if (make_path_to_file(buf) == -1) { LOG(LOG_WARNING, "gtk-v2::save_keys", "Could not create %s", buf); } else { fp = fopen(buf, "w"); if (fp == NULL) { snprintf(buf2, sizeof(buf2), "Could not open %s, global key bindings not saved\n", buf); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, buf2); } else { /* Save default bindings as part of the global scope */ if (firekeysym[0] != GDK_KEY_Shift_L && firekeysym[0] != NoSymbol) fprintf(fp, "! firekey0 %s %d\n", gdk_keyval_name(firekeysym[0]), 0); if (firekeysym[1] != GDK_KEY_Shift_R && firekeysym[1] != NoSymbol) fprintf(fp, "! firekey1 %s %d\n", gdk_keyval_name(firekeysym[1]), 0); if (metakeysym[0] != GDK_KEY_Shift_L && metakeysym[0] != NoSymbol) fprintf(fp, "! metakey0 %s %d\n", gdk_keyval_name(metakeysym[0]), 0); if (metakeysym[1] != GDK_KEY_Shift_R && metakeysym[1] != NoSymbol) fprintf(fp, "! metakey1 %s %d\n", gdk_keyval_name(metakeysym[1]), 0); if (altkeysym[0] != GDK_KEY_Shift_L && altkeysym[0] != NoSymbol) fprintf(fp, "! altkey0 %s %d\n", gdk_keyval_name(altkeysym[0]), 0); if (altkeysym[1] != GDK_KEY_Shift_R && altkeysym[1] != NoSymbol) fprintf(fp, "! altkey1 %s %d\n", gdk_keyval_name(altkeysym[1]), 0); if (runkeysym[0] != GDK_KEY_Control_L && runkeysym[0] != NoSymbol) fprintf(fp, "! runkey0 %s %d\n", gdk_keyval_name(runkeysym[0]), 0); if (runkeysym[1] != GDK_KEY_Control_R && runkeysym[1] != NoSymbol) fprintf(fp, "! runkey1 %s %d\n", gdk_keyval_name(runkeysym[1]), 0); if (completekeysym != GDK_KEY_Tab && completekeysym != NoSymbol) fprintf(fp, "! completekey %s %d\n", gdk_keyval_name(completekeysym), 0); /* No defaults for these, so if it is set to anything, assume its valid */ if (nextkeysym != NoSymbol) fprintf(fp, "! nextkey %s %d\n", gdk_keyval_name(nextkeysym), 0); if (prevkeysym != NoSymbol) fprintf(fp, "! prevkey %s %d\n", gdk_keyval_name(prevkeysym), 0); for (i = 0; i < KEYHASH; i++) { save_individual_key(fp, keys_global[i], 0); } fclose(fp); } } /* Should probably check return value on all writes to be sure, but... */ draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, "Key bindings saved."); } /** * * @param keysym */ static void configure_keys(guint32 keysym) { char buf[MAX_BUF]; struct keybind *kb; /* We handle the Shift key separately */ keysym = gdk_keyval_to_lower(keysym); /* * I think that basically if we are not rebinding the special control keys * (in which case bind_keysym would be set to something) we just want to * handle these keypresses as normal events. */ if (bind_keysym == NULL) { if (keysym == altkeysym[0] || keysym == altkeysym[1]) { cpl.alt_on = 1; return; } if (keysym == metakeysym[0] || keysym == metakeysym[1]) { cpl.meta_on = 1; return; } if (keysym == firekeysym[0] || keysym == firekeysym[1]) { cpl.fire_on = 1; draw_message_window(0); return; } if (keysym == runkeysym[0] || keysym == runkeysym[1]) { cpl.run_on = 1; draw_message_window(0); return; } } /* * Take shift/control keys into account when binding keys. */ if (!(bind_flags & KEYF_ANY)) { if (cpl.fire_on) { bind_flags |= KEYF_MOD_SHIFT; } if (cpl.run_on) { bind_flags |= KEYF_MOD_CTRL; } if (cpl.meta_on) { bind_flags |= KEYF_MOD_META; } if (cpl.alt_on) { bind_flags |= KEYF_MOD_ALT; } } /* Reset state now. We might return early if bind fails. */ cpl.input_state = Playing; if (bind_keysym != NULL) { *bind_keysym = keysym; bind_keysym = NULL; } else { kb = keybind_find(keysym, bind_flags, (bind_flags & KEYF_R_GLOBAL)); if (kb) { snprintf(buf, sizeof(buf), "Error: Key already used for command \"%s\". Use unbind first.", kb->command); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, buf); return; } else { keybind_insert(keysym, bind_flags, bind_buf); } } snprintf(buf, sizeof(buf), "Bound to key '%s' (%i)", keysym == NoSymbol ? "unknown" : gdk_keyval_name(keysym), keysym); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, buf); draw_message_window(0); /* * Do this each time a new key is bound. This way, we are never actually * storing any information that needs to be saved when the connection dies * or the player quits. */ save_keys(); return; } /** * Show help for the unbind command in the message pane. */ static void unbind_usage(void) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Usage: 'unbind ' or"); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Usage: 'unbind' to show existing bindings"); } /** * * @param params */ void unbind_key(const char *params) { int count = 0, keyentry, slot, j; int res; struct keybind *kb; char buf[MAX_BUF]; if (params == NULL) { show_keys(); return; } /* Skip over any spaces we may have */ while (*params == ' ') { params++; } if (params[0] == '\0') { show_keys(); return; } if ((keyentry = atoi(params)) == 0) { unbind_usage(); return; } for (slot = 0; slot < KEYHASH; slot++) { for (j = 0; j < 2; j++) { for (kb = (j == 0) ? keys_global[slot] : keys_char[slot]; kb != NULL; kb = kb->next) { count++; if (keyentry == count) { /* We found the key we want to unbind */ snprintf(buf, sizeof(buf), "Removing binding: %3d %s", count, get_key_info(kb, 0)); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, buf); res = keybind_remove(kb); if (res < 0) LOG(LOG_ERROR, "gtk-v2::unbind_key", "found number entry, but could not find actual key"); keybind_free(&kb); save_keys(); return; } } } } /* Not found */ /* Makes things look better to draw the blank line */ draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, ""); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Not found. Try 'unbind' with no options to find entry."); return; } /** * When the main window looses its focus, act as if all keys have been released */ void focusoutfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window) { if (cpl.fire_on == 1) { cpl.fire_on = 0; clear_fire(); gtk_label_set_text(GTK_LABEL(fire_label), " "); } if (cpl.run_on == 1) { cpl.run_on = 0; clear_run(); gtk_label_set_text(GTK_LABEL(run_label), " "); } if (cpl.alt_on == 1) { cpl.alt_on = 0; } if (cpl.meta_on == 1) { cpl.meta_on = 0; } } /** * GTK callback function used to handle client key release events. * * @param widget * @param event GDK Key Release Event * @param window */ void keyrelfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window) { if (event->keyval > 0 && !gtk_widget_has_focus(entry_commands)) { parse_key_release(event->keyval); debounce = false; } g_signal_stop_emission_by_name(GTK_WIDGET(window), "key_release_event"); } /** * GTK Callback function used to handle client key press events. * * @param widget * @param event GDK Key Press Event * @param window */ void keyfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window) { char *text; if (!use_config[CONFIG_POPUPS]) { if (((cpl.input_state == Reply_One) || (cpl.input_state == Reply_Many)) && (event->keyval == cancelkeysym)) { /* * Player hit cancel button during input. Disconnect it (code from * menubar) */ client_disconnect(); g_signal_stop_emission_by_name( GTK_WIDGET(window), "key_press_event"); return; } if (cpl.input_state == Reply_One) { text = gdk_keyval_name(event->keyval); send_reply(text); cpl.input_state = Playing; g_signal_stop_emission_by_name( GTK_WIDGET(window), "key_press_event"); return; } else if (cpl.input_state == Reply_Many) { if (gtk_widget_has_focus(entry_commands)) { gtk_widget_event(GTK_WIDGET(entry_commands), (GdkEvent *)event); } else { gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); } g_signal_stop_emission_by_name( GTK_WIDGET(window), "key_press_event"); return; } } /* * Better check for really weirdo keys, X doesnt like keyval 0 so avoid * handling these key values. */ if (event->keyval > 0) { if (gtk_widget_has_focus(entry_commands)) { if (event->keyval == completekeysym) { gtk_complete_command(); } if (event->keyval == prevkeysym || event->keyval == nextkeysym) { gtk_command_history(event->keyval == nextkeysym ? 0 : 1); } else { gtk_widget_event(GTK_WIDGET(entry_commands), (GdkEvent *)event); } } else { switch (cpl.input_state) { case Playing: /* * Specials - do command history - many times, the player * will want to go the previous command when nothing is * entered in the command window. */ if ((event->keyval == prevkeysym) || (event->keyval == nextkeysym)) { gtk_command_history(event->keyval == nextkeysym ? 0 : 1); } else { if (cpl.run_on) { if (!(event->state & GDK_CONTROL_MASK)) { /* printf("Run is on while ctrl is not\n"); */ gtk_label_set_text(GTK_LABEL(run_label), " "); cpl.run_on = 0; stop_run(); } } if (cpl.fire_on) { if (!(event->state & GDK_SHIFT_MASK)) { /* printf("Fire is on while shift is not\n");*/ gtk_label_set_text(GTK_LABEL(fire_label), " "); cpl.fire_on = 0; stop_fire(); } } if (csocket.command_received >= csocket.command_sent) { debounce = false; } if (!debounce) { parse_key(event->string[0], event->keyval); debounce = true; } } break; case Configure_Keys: configure_keys(event->keyval); break; case Command_Mode: if (event->keyval == completekeysym) { gtk_complete_command(); } if ((event->keyval == prevkeysym) || (event->keyval == nextkeysym)) { gtk_command_history(event->keyval == nextkeysym ? 0 : 1); } else { gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); /* * When running in split windows mode, entry_commands * can't get focus because it is in a different * window. So we have to pass the event to it * explicitly. */ if (gtk_widget_has_focus(entry_commands) == 0) gtk_widget_event( GTK_WIDGET(entry_commands), (GdkEvent *)event); } /* * Don't pass signal along to default handlers - * otherwise, we get get crashes in the clist area (gtk * fault I believe) */ break; case Metaserver_Select: gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); break; default: LOG(LOG_ERROR, "gtk-v2::keyfunc", "Unknown input state: %d", cpl.input_state); } } } g_signal_stop_emission_by_name( GTK_WIDGET(window), "key_press_event"); } /** * */ void x_set_echo(void) { gtk_entry_set_visibility(GTK_ENTRY(entry_commands), !cpl.no_echo); } /** * Draws a prompt. Don't deal with popups for the time being. * * @param str */ void draw_prompt(const char *str) { draw_ext_info(NDI_WHITE, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, str); gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); } /** * Deals with command history. * * @param direction If 0, we are going backwards, if 1, we are moving forward. */ void gtk_command_history(int direction) { int i = scroll_history_position; if (direction) { i--; if (i < 0) { i += MAX_HISTORY; } if (i == cur_history_position) { return; } } else { i++; if (i >= MAX_HISTORY) { i = 0; } if (i == cur_history_position) { /* * User has forwarded to what should be current entry - reset it * now. */ gtk_entry_set_text(GTK_ENTRY(entry_commands), ""); gtk_editable_set_position(GTK_EDITABLE(entry_commands), 0); scroll_history_position = cur_history_position; return; } } if (history[i][0] == 0) { return; } scroll_history_position = i; /* fprintf(stderr, "resetting postion to %d, data = %s\n", i, history[i]);*/ gtk_entry_set_text(GTK_ENTRY(entry_commands), history[i]); gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); gtk_editable_select_region(GTK_EDITABLE(entry_commands), 0, 0); gtk_editable_set_position(GTK_EDITABLE(entry_commands), -1); cpl.input_state = Command_Mode; } /** * Executes when the TAB key is pressed while the command input box has focus * to give hints on what commands begin with the text already entered to this * point. It is almost like tab completion, except for the completion. The TAB * key is also known by GDK_Tab, completekey, or completekeysym. */ void gtk_complete_command(void) { const gchar *entry_text, *newcommand; entry_text = gtk_entry_get_text(GTK_ENTRY(entry_commands)); newcommand = complete_command(entry_text); /* value differ, so update window */ if (newcommand != NULL) { gtk_entry_set_text(GTK_ENTRY(entry_commands), newcommand); gtk_widget_grab_focus(GTK_WIDGET(entry_commands)); gtk_editable_select_region(GTK_EDITABLE(entry_commands), 0, 0); gtk_editable_set_position(GTK_EDITABLE(entry_commands), -1); } } /** * Used to process keyboard input whenever the player types commands into the * command entry box. * * @param entry * @param user_data */ void on_entry_commands_activate(GtkEntry *entry, gpointer user_data) { const gchar *entry_text; extern GtkWidget *treeview_look; /* Next reply will reset this as necessary */ if (!use_config[CONFIG_POPUPS]) { gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE); } entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); if (cpl.input_state == Metaserver_Select) { strcpy(cpl.input_text, entry_text); } else if (cpl.input_state == Reply_One || cpl.input_state == Reply_Many) { cpl.input_state = Playing; strcpy(cpl.input_text, entry_text); if (cpl.input_state == Reply_One) { cpl.input_text[1] = 0; } send_reply(cpl.input_text); } else { cpl.input_state = Playing; /* No reason to do anything for a null string */ if (entry_text[0] != 0) { strncpy(history[cur_history_position], entry_text, MAX_COMMAND_LEN); history[cur_history_position][MAX_COMMAND_LEN - 1] = 0; cur_history_position++; cur_history_position %= MAX_HISTORY; scroll_history_position = cur_history_position; extended_command(entry_text); } } gtk_entry_set_text(GTK_ENTRY(entry), ""); /* * This grab focus is really just so the entry box doesn't have focus - * this way, keypresses are used to play the game, and not as stuff that * goes into the entry box. It doesn't make much difference what widget * this is set to, as long as it is something that can get focus. */ gtk_widget_grab_focus(GTK_WIDGET(treeview_look)); if (cpl.input_state == Metaserver_Select) { cpl.input_state = Playing; /* * This is the gtk_main that is started up by get_metaserver The client * will start another one once it is connected to a crossfire server */ gtk_main_quit(); } } /** * @} EndOf GtkV2KeyBinding */ /** * @defgroup GtkV2KeyBindingWindow GTK-V2 client keybinding window functions. * @{ */ /** * Update the keybinding dialog to reflect the current state of the keys file. */ void update_keybinding_list(void) { int i, j; struct keybind *kb; char *modifier_label, *scope_label; GtkTreeIter iter; gtk_list_store_clear(keybinding_store); for (i = 0; i < KEYHASH; i++) { for (j = 0; j < 2; j++) { for (kb = (j == 0) ? keys_global[i] : keys_char[i]; kb != NULL; kb = kb->next) { if (j == 0) { kb->flags |= KEYF_R_GLOBAL; } else { kb->flags |= KEYF_R_CHAR; } if (kb->flags & KEYF_ANY) { modifier_label = "Any"; } else if ((kb->flags & KEYF_MOD_MASK) == 0) { modifier_label = "None"; } else { if (kb->flags & KEYF_MOD_ALT) { modifier_label = "Alt"; if (kb->flags & (KEYF_MOD_SHIFT | KEYF_MOD_CTRL | KEYF_MOD_META)) { modifier_label = " + "; } } if (kb->flags & KEYF_MOD_SHIFT) { modifier_label = "Fire"; if (kb->flags & (KEYF_MOD_CTRL | KEYF_MOD_META)) { modifier_label = " + "; } } if (kb->flags & KEYF_MOD_CTRL) { modifier_label = "Run"; if (kb->flags & KEYF_MOD_META) { modifier_label = " + "; } } if (kb->flags & KEYF_MOD_META) { modifier_label = "Meta"; } } if (!(kb->flags & KEYF_R_GLOBAL)) { scope_label = "char"; } else { scope_label = "global"; } gtk_list_store_append(keybinding_store, &iter); gtk_list_store_set(keybinding_store, &iter, KLIST_ENTRY, i, KLIST_KEY, gdk_keyval_name(kb->keysym), KLIST_MODS, modifier_label, KLIST_SCOPE, scope_label, KLIST_EDIT, (kb->flags & KEYF_EDIT) ? "Yes" : "No", KLIST_COMMAND, kb->command, KLIST_KEY_ENTRY, kb, -1); } } } reset_keybinding_status(); } /** * Menubar item to activate keybindings window * * @param menuitem * @param user_data */ void on_keybindings_activate(GtkMenuItem *menuitem, gpointer user_data) { gtk_widget_show(keybinding_window); update_keybinding_list(); } /** * Respond to a key press in the "Key" input box. If the keyboard has modifier * keys pressed, set the appropriate "Keybinding Modifiers" checkboxes if the * shift or control keys happens to be pressed at the time. Oddly, the Alt and * Meta keys are not similarly handled. Checkboxes are never cleared here in * case the user had just set the checkboxes ahead of time. * * @param widget * @param event * @param user_data * @return TRUE (Returning TRUE prevents widget from getting this event.) */ gboolean on_keybinding_entry_key_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { gtk_entry_set_text( GTK_ENTRY(keybinding_entry_key), gdk_keyval_name(event->keyval)); /* * This code is basically taken from the GTKv1 client. However, at some * level it is broken, since the control/shift/etc masks are hardcoded, yet * we do let the users redefine them. * * The clearing of the modifiers is disabled. In my basic testing, I * checked the modifiers and then pressed the key - have those modifiers go * away I think is less intuitive. */ if (event->state & GDK_CONTROL_MASK) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), TRUE); #if 0 else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), FALSE); #endif if (event->state & GDK_SHIFT_MASK) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), TRUE); #if 0 else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), FALSE); } /* The GDK_MOD_MASK* will likely correspond to alt and meta, yet there is * no way to be sure what goes to what, so easiest to just not allow them. */ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), FALSE); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), FALSE); #endif /* Returning TRUE prevents widget from getting this event */ return TRUE; } /** * Toggles buttons state to reflect a scope state. * Both togglebuttons change accordingly. * @param scope - State to apply to the "All characters" togglebutton. * The "This character" togglebutton will get the opposite state. */ void toggle_buttons_scope(int scope) { int state_u, state_c; state_u = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_global)); state_c = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_character)); /* If the states of the buttons are not already what we are asked for, or if * they are equal (which is inconsistent) then update them. Deactivate the * callbacks for the "toggled" events temporarily to avoid an infinite loop. */ if (state_u != scope || state_u == state_c) { g_signal_handlers_block_by_func( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_character), G_CALLBACK(on_kb_scope_togglebutton_character_toggled), NULL); g_signal_handlers_block_by_func( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_global), G_CALLBACK(on_kb_scope_togglebutton_global_toggled), NULL); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_character), !scope); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_global), scope); g_signal_handlers_unblock_by_func( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_character), G_CALLBACK(on_kb_scope_togglebutton_character_toggled), NULL); g_signal_handlers_unblock_by_func( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_global), G_CALLBACK(on_kb_scope_togglebutton_global_toggled), NULL); } } /** * Shows a dialog that prompts for confirmation before overwriting a keybind, * showing details of the keybind we are about to overwrite. * @param kb The keybind we are about to overwrite. * * @return TRUE if the user chooses to overwrite kb, else FALSE. */ static int keybind_overwrite_confirm(struct keybind *kb) { GtkWidget *dialog, *label; int result; char buf[MAX_BUF], buf2[MAX_BUF]; dialog = gtk_dialog_new_with_buttons( "Key already in use", GTK_WINDOW(keybinding_window), GTK_DIALOG_MODAL, GTK_STOCK_YES, 1, GTK_STOCK_NO, 2, NULL); get_key_modchars(kb, 1, buf2); snprintf(buf, sizeof(buf), "Overwrite this binding?\n (%s) %s\n%s", buf2, gdk_keyval_name(kb->keysym), kb->command); label = gtk_label_new(buf); gtk_box_pack_start( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), label, TRUE, TRUE, 0); gtk_widget_show_all(dialog); result = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return (result == 1); } /** * Toggles a keybinding's scope to the desired value. * First checks for existance of another binding with the desired scope * and asks for confirmation before overwriting anything. * * @scope The new scope to apply to this keybind, * 0 meaning char scope, non zero meaning global scope. * @kb Keybinding to modify scope. */ void toggle_keybind_scope(int scope, struct keybind *kb) { struct keybind *kb_old, **next_ptr; int ret, flags; char buf[MAX_BUF]; /* First check for matching bindings in the new scope */ kb_old = keybind_find(kb->keysym, kb->flags, scope); while (kb_old) { if (!keybind_overwrite_confirm(kb_old)) { /* Restore all bindings and buttons state. * Need to call keybindings_init() because we may have already * removed some bindings from memory */ toggle_buttons_scope(!scope); keybindings_init(cpl.name); update_keybinding_list(); return; } /* Completely remove the old binding */ keybind_remove(kb_old); keybind_free(&kb_old); kb_old = keybind_find(kb->keysym, kb->flags, scope); } /* If the new scope is 'global' we remove the binding from keys_char (don't * free it), switch scope flags and rehash in keys_global. * * Else just make a copy into keys_char only switching the state flags. */ if (scope) { if ((kb->flags & KEYF_R_GLOBAL) == 0) { /* Remove kb from keys_char, don't free it. */ ret = keybind_remove(kb); if (ret == -1) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, "\nCould not remove keybind. Operation failed.\n"); toggle_buttons_scope(!scope); keybindings_init(cpl.name); update_keybinding_list(); return; } /* Place the modified kb in keys_global */ kb->flags ^= KEYF_R_CHAR; kb->flags |= KEYF_R_GLOBAL; next_ptr = &keys_global[kb->keysym % KEYHASH]; kb->next = NULL; if (*next_ptr) { while ((*next_ptr)->next) { next_ptr = &(*next_ptr)->next; } (*next_ptr)->next = kb; } else { keys_global[kb->keysym % KEYHASH] = kb; } } } else { if ((kb->flags & KEYF_R_GLOBAL) != 0) { /* Copy the selected binding in the char's scope with the right flags. */ snprintf(buf, sizeof(buf), "%s", kb->command); flags = kb->flags; flags |= KEYF_R_CHAR; flags ^= KEYF_R_GLOBAL; keybind_insert(kb->keysym, flags, buf); } } save_keys(); update_keybinding_list(); } /** * Called when "This character" is clicked. * Toggles scope of the selected binding and handles the togglebuttons' state. * * @param toggle_button * @param user_data */ void on_kb_scope_togglebutton_character_toggled(GtkToggleButton *toggle_button, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; struct keybind *kb; gboolean scope; if (gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) { gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &kb, -1); scope = !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_character)); toggle_buttons_scope(scope); toggle_keybind_scope(scope, kb); } } /** * Called when "All characters" is clicked. * Toggles scope of the selected binding and handles the togglebuttons' state. * * @param toggle_button * @param user_data */ void on_kb_scope_togglebutton_global_toggled(GtkToggleButton *toggle_button, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; struct keybind *kb; gboolean scope; if (gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) { gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &kb, -1); scope = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_global)); toggle_buttons_scope(scope); toggle_keybind_scope(scope, kb); } } /** * Implements the "Remove Binding" button function that unbinds the currently * selected keybinding. * * @param button * @param user_data */ void on_keybinding_button_remove_clicked(GtkButton *button, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; struct keybind *kb; int res; if (!gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) { LOG(LOG_ERROR, "keys.c::on_keybinding_button_remove_clicked", "Function called with nothing selected\n"); return; } gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &kb, -1); res = keybind_remove(kb); if (res < 0) LOG(LOG_ERROR, "keys.c::on_keybinding_button_remove_clicked", "Unable to find matching key entry\n"); keybind_free(&kb); save_keys(); update_keybinding_list(); } /** * Gets the state information from checkboxes and other data in the window * and puts it in the variables passed. This is used by both the update * and add functions. * * @param keysym * @param flags * @param command */ static void keybinding_get_data(guint32 *keysym, guint8 *flags, const char **command) { static char bind_buf[MAX_BUF]; const char *ed; *flags = 0; if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_any))) { *flags |= KEYF_ANY; } if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(kb_scope_togglebutton_global))) { *flags |= KEYF_R_GLOBAL; } if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_control))) { *flags |= KEYF_MOD_CTRL; } if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift))) { *flags |= KEYF_MOD_SHIFT; } if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt))) { *flags |= KEYF_MOD_ALT; } if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta))) { *flags |= KEYF_MOD_META; } if (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit))) { *flags |= KEYF_EDIT; } ed = gtk_entry_get_text(GTK_ENTRY(keybinding_entry_command)); if (strlen(ed) >= sizeof(bind_buf)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, "Keybinding too long! Truncated."); strncpy(bind_buf, ed, MAX_BUF - 1); bind_buf[MAX_BUF - 1] = 0; *command = bind_buf; } else { *command = ed; } /* * This isn't ideal - when the key is pressed, we convert it to a string, * and now we are converting it back. It'd be nice to tuck the keysym * itself away someplace. */ *keysym = gdk_keyval_from_name( gtk_entry_get_text(GTK_ENTRY(keybinding_entry_key))); if (*keysym == GDK_KEY_VoidSymbol) { LOG(LOG_ERROR, "keys.c::keybinding_get_data", "Cannot get valid keysym from selection"); } } /** * Sets up a new binding when the "Add" button is clicked. * * @param button * @param user_data */ void on_keybinding_button_bind_clicked(GtkButton *button, gpointer user_data) { guint32 keysym; guint8 flags; const char *command; struct keybind *kb; keybinding_get_data(&keysym, &flags, &command); /* keybind_insert will do a g_strdup of command for us */ kb = keybind_find(keysym, flags, (flags & KEYF_R_GLOBAL)); if (kb && (!keybind_overwrite_confirm(kb))) { return; } keybind_insert(keysym, flags, command); /* * I think it is more appropriate to clear the fields once the user adds * it. I suppose the ideal case would be to select the newly inserted * keybinding. */ reset_keybinding_status(); save_keys(); update_keybinding_list(); } /** * Implements the "Update Binding" button to update the currently selected * keybinding to match the currently shown identifiers, key, or command input * fields. If a keybinding is highlighted, so something. If not, log an error * since the "Update Binding" button should have been disabled. * * @param button * @param user_data */ void on_keybinding_button_update_clicked(GtkButton *button, gpointer user_data) { GtkTreeIter iter; struct keybind *kb; GtkTreeModel *model; guint32 keysym; guint8 flags; const char *buf; int res; if (gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) { gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &kb, -1); if (!kb) { LOG(LOG_ERROR, "keys.c::on_keybinding_button_update_clicked", "Unable to get key_entry structure\n"); return; } /* We need to rehash the binding (remove the old and add the * new) since the keysym might have changed. */ keybind_remove(kb); keybinding_get_data(&keysym, &flags, &buf); res = keybind_insert(keysym, flags, buf); if (res == 0) { keybind_free(&kb); } else { /* Re-enter old binding if the update failed */ keybind_insert(kb->keysym, kb->flags, kb->command); // FIXME: Popup dialog key in use } save_keys(); update_keybinding_list(); } else { LOG(LOG_ERROR, "keys.c::on_keybinding_button_update_clicked", "Nothing selected to update\n"); } } /** * Deactivates the keybinding dialog when the "Close Window" button is clicked. * * @param button * @param user_data */ void on_keybinding_button_close_clicked(GtkButton *button, gpointer user_data) { gtk_widget_hide(keybinding_window); } /** * Deactivate the modifier checkboxes if "Any" is selected. * * @param button * @param user_data */ void on_keybinding_checkbutton_any_clicked(GtkCheckButton *cb, gpointer user_data) { gboolean enabled; enabled = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb)); gtk_widget_set_sensitive(GTK_WIDGET(keybinding_checkbutton_control), enabled); gtk_widget_set_sensitive(GTK_WIDGET(keybinding_checkbutton_shift), enabled); gtk_widget_set_sensitive(GTK_WIDGET(keybinding_checkbutton_alt), enabled); gtk_widget_set_sensitive(GTK_WIDGET(keybinding_checkbutton_meta), enabled); } /** * Called when the user clicks one of the entries in the list of keybindings * and places information about it into the input fields on the dialog. This * allows the player to edit and update, or remove bindings. * * @param selection * @param model * @param path * @param path_currently_selected * @param userdata * @return TRUE */ gboolean keybinding_selection_func( GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; struct keybind *kb; gtk_widget_set_sensitive(keybinding_button_remove, TRUE); gtk_widget_set_sensitive(keybinding_button_update, TRUE); if (gtk_tree_model_get_iter(model, &iter, path)) { gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &kb, -1); if (!kb) { LOG(LOG_ERROR, "keys.c::keybinding_selection_func", "Unable to get key_entry structure\n"); return FALSE; } if (kb->flags & KEYF_ANY) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_any), TRUE); else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_any), FALSE); if (kb->flags & KEYF_MOD_CTRL) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), TRUE); else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), FALSE); if (kb->flags & KEYF_MOD_SHIFT) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), TRUE); else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), FALSE); if (kb->flags & KEYF_MOD_ALT) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), TRUE); else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), FALSE); if (kb->flags & KEYF_MOD_META) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), TRUE); else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), FALSE); if (kb->flags & KEYF_EDIT) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit), TRUE); else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit), FALSE); gtk_entry_set_text( GTK_ENTRY(keybinding_entry_key), gdk_keyval_name(kb->keysym)); gtk_entry_set_text( GTK_ENTRY(keybinding_entry_command), kb->command); toggle_buttons_scope((kb->flags & KEYF_R_GLOBAL) != 0); } return TRUE; } /** * Reset the state of the keybinding dialog. Uncheck all modifier checkboxes, * clear the key input box, clear the command input box, and disable the two * update and remove keybinding buttons. */ void reset_keybinding_status(void) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_any), FALSE); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), FALSE); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), FALSE); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), FALSE); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), FALSE); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit), FALSE); gtk_entry_set_text(GTK_ENTRY(keybinding_entry_key), ""); gtk_entry_set_text(GTK_ENTRY(keybinding_entry_command), ""); toggle_buttons_scope(FALSE); gtk_widget_set_sensitive(keybinding_button_remove, FALSE); gtk_widget_set_sensitive(keybinding_button_update, FALSE); } /** * Implements the "Clear Fields" button function on the keybinding dialog. If * a keybinding is highlighted (selected), de-select it first, then clear all * of * the input boxes and reset any buttons to an appropriate state. * * @param button * @param user_data */ void on_keybinding_button_clear_clicked(GtkButton *button, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; /* * As the cleared state is not supposed to have a keybinding selected, * deselect the currently selected keybinding if there is one. */ if (gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) { gtk_tree_selection_unselect_iter(keybinding_selection, &iter); } reset_keybinding_status(); /* Clear inputs and reset buttons. */ } /** * @} EndOf GtkV2KeyBindingWindow */ crossfire-client-1.75.3/gtk-v2/src/main.c000644 001751 001751 00000044556 14353774325 020766 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Client startup and main loop. */ #include "client.h" #include #include #include #ifndef WIN32 #include #endif #include "client-vala.h" #include "image.h" #include "main.h" #include "mapdata.h" #include "metaserver.h" #include "script.h" #include "sound.h" #include "gtk2proto.h" /* Sets up the basic colors. */ static const char *const colorname[NUM_COLORS] = { "Black", /* 0 */ "White", /* 1 */ "Navy", /* 2 */ "Red", /* 3 */ "Orange", /* 4 */ "DodgerBlue", /* 5 */ "DarkOrange2", /* 6 */ "SeaGreen", /* 7 */ "DarkSeaGreen", /* 8 *//* Used for window background color */ "Grey50", /* 9 */ "Sienna", /* 10 */ "Gold", /* 11 */ "Khaki" /* 12 */ }; static gboolean updatekeycodes = FALSE; /* TODO: Move these declarations to actual header files. */ extern bool time_map_redraw; extern bool profile_latency; extern int MINLOG; bool debug_protocol; static char *connect_server = NULL; static gboolean script_launch(const gchar *option_name, const gchar *value, gpointer data, GError **error); /** Command line options, descriptions, and parameters. */ static GOptionEntry options[] = { { "server", 's', 0, G_OPTION_ARG_STRING, &connect_server, "Connect to the given server", "SERVER[:PORT]" }, { "cache", 0, 0, G_OPTION_ARG_NONE, &want_config[CONFIG_CACHE], "Cache images", NULL }, { "prefetch", 0, 0, G_OPTION_ARG_NONE, &want_config[CONFIG_DOWNLOAD], "Download images before playing", NULL }, { "faceset", 0, 0, G_OPTION_ARG_STRING, &face_info.want_faceset, "Use the given faceset (if available)", "FACESET" }, { "sound_server", 0, 0, G_OPTION_ARG_FILENAME, &sound_server, "Path to the sound server", "PATH" }, { "updatekeycodes", 0, 0, G_OPTION_ARG_NONE, &updatekeycodes, "Update the saved bindings for this keyboard", NULL }, { "loginmethod", 0, 0, G_OPTION_ARG_INT, &wantloginmethod, "Login method to request from server", NULL }, { "profile-latency", 0, 0, G_OPTION_ARG_NONE, &profile_latency, "Log command acknowledgement latency to stdout", NULL }, { "profile-redraw", 0, 0, G_OPTION_ARG_NONE, &time_map_redraw, "Print map redraw times to stdout", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_INT, &MINLOG, "Set verbosity (0 is the most verbose)", "LEVEL" }, { "debug-protocol", 0, 0, G_OPTION_ARG_NONE, &debug_protocol, "Print commands to and from the server", NULL }, { "script", 0, 0, G_OPTION_ARG_CALLBACK, &script_launch, "Launch client script at start (can be used multiple times)", "SCRIPT_NAME" }, { NULL } }; char window_xml_file[MAX_BUF]; GdkColor root_color[NUM_COLORS]; GtkBuilder *dialog_xml, *window_xml; GtkWidget *window_root, *magic_map, *connect_window; GtkNotebook *main_notebook; extern time_t last_command_sent; extern bool is_afk; #ifdef WIN32 /* Win32 scripting support */ static int do_scriptout() { script_process(NULL); return (TRUE); } #endif /* WIN32 */ static gboolean script_launch(const gchar *option_name, const gchar *value, gpointer data, GError **error) { (void)option_name; // always "--script" (void)data; // Not used (void)error; // Not used script_init(value); return TRUE; } /** * Redraw the map. Do a full redraw if there are new images to show. Return * false to unregister this event source after one redraw. */ static gboolean redraw(gpointer data) { // Add a check for client_is_connected so that forced socket termination // does not erroneously attempt to redraw the map after it has been destroyed. if (client_is_connected()) { if (have_new_image) { if (cpl.container) { cpl.container->inv_updated = 1; } cpl.ob->inv_updated = 1; have_new_image = 0; } draw_map(); draw_lists(); } return FALSE; } static void on_auto_afk_response(GtkDialog *self, gint response_id, gpointer user_data) { // It is possible for is_afk to be false because dialog is non-modal. switch (response_id) { case 1: gtk_widget_destroy(GTK_WIDGET(self)); break; case 2: if (is_afk) { send_command("afk", 0, true); } want_config[CONFIG_AUTO_AFK] = 0; config_check(); save_defaults(); gtk_widget_destroy(GTK_WIDGET(self)); break; default: // includes closing the pop-up if (is_afk) { send_command("afk", 0, true); } gtk_widget_destroy(GTK_WIDGET(self)); break; } } static void auto_afk() { send_command("afk", 0, true); GtkWidget *dialog = gtk_dialog_new_with_buttons("Auto-AFK", GTK_WINDOW(window_root), GTK_DIALOG_DESTROY_WITH_PARENT, "Return to game", 0, "Return to game, but stay AFK", 1, "Return to game, disable auto-AFK", 2, NULL); GtkWidget *label, *content_area; content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); label = gtk_label_new("You have been automatically marked as being away."); gtk_container_add(GTK_CONTAINER(content_area), label); g_signal_connect_swapped(dialog, "response", G_CALLBACK(on_auto_afk_response), dialog); gtk_widget_show_all(dialog); } /** * Called whenever the server sends a tick command. */ void client_tick(guint32 tick) { if (cpl.showmagic) { if (gtk_notebook_get_current_page(GTK_NOTEBOOK(map_notebook)) != MAGIC_MAP_PAGE) { // Stop flashing when the user switches back to the map window. cpl.showmagic = 0; } else { magic_map_flash_pos(); cpl.showmagic ^= 2; } } if (cpl.spells_updated) { update_spell_information(); } info_buffer_tick(); inventory_tick(); mapdata_animation(); g_idle_add(redraw, NULL); if (!is_afk && use_config[CONFIG_AUTO_AFK] != 0 && time(NULL) > (last_command_sent + use_config[CONFIG_AUTO_AFK])) { auto_afk(); } } /** * Handles client shutdown. */ void on_window_destroy_event(GtkWidget *object, gpointer user_data) { script_killall(); LOG(LOG_DEBUG, "main.c::client_exit", "Exiting with return value 0."); exit(0); } /** * Callback from the event loop triggered when server input is available. */ static gboolean do_network(GObject *stream, gpointer data) { struct timeval timeout = {0, 0}; fd_set tmp_read; int pollret; if (!client_is_connected()) { gtk_main_quit(); LOG(LOG_INFO, "main.c::do_network", "Trying to do network when not connected."); return FALSE; } client_run(); FD_ZERO(&tmp_read); int maxfd; script_fdset(&maxfd, &tmp_read); pollret = select(maxfd, &tmp_read, NULL, NULL, &timeout); if (pollret < 0) { #ifndef WIN32 // FIXME: For whatever reason, we get errors claiming "no error" here in Windows LOG(LOG_ERROR, "do_network", "script select() failed: %s", strerror(errno)); #endif } else if (pollret > 0) { script_process(&tmp_read); } return TRUE; } /** * Set up, enter, and exit event loop. Blocks until event loop returns. */ static void event_loop() { #ifdef WIN32 g_timeout_add(250, G_SOURCE_FUNC(do_scriptout), NULL); #endif GSource *net_source = client_get_source(); if (net_source == NULL) { error_dialog("Server unexpectedly disconnected", "The server unexpectedly disconnected."); client_disconnect(); return; } g_source_set_callback(net_source, (GSourceFunc)do_network, NULL, NULL); g_source_attach(net_source, NULL); gtk_main(); LOG(LOG_DEBUG, "event_loop", "Disconnected"); } /** * parse_args: Parses command line options, and does variable initialization. * @param argc * @param argv */ /** * Parse command-line arguments and store settings in want_config. * * This function should be called after config_load(). */ static void parse_args(int argc, char *argv[]) { GOptionContext *context = g_option_context_new("- Crossfire GTKv2 Client"); GError *error = NULL; g_option_context_add_main_entries(context, options, NULL); g_option_context_add_group(context, gtk_get_option_group(TRUE)); if (!g_option_context_parse(context, &argc, &argv, &error)) { g_print("%s\n", error->message); g_error_free(error); exit(EXIT_FAILURE); } g_option_context_free(context); /* * Move this after the parsing of command line options, since that can * change the default log level. */ LOG(LOG_DEBUG, "Client Version", VERSION_INFO); if (MINLOG <= 0) { g_setenv("CF_SOUND_DEBUG", "yes", false); } } /** * Display an error message dialog. The dialog contains a multi-line, bolded * heading that includes the client version information, an error description, * and information relevant to the error condition. */ void error_dialog(char *error, char *message) { GtkWidget *dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", error); gtk_window_set_title(GTK_WINDOW(dialog), "Crossfire Client"); gtk_message_dialog_format_secondary_markup( GTK_MESSAGE_DIALOG(dialog), "%s", message); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } /** * This goes with the g_log_set_handler below in main(). I leave it here * since it may be useful - basically, it can prove handy to try and track * down error messages like: * * file gtklabel.c: line 1845: assertion `GTK_IS_LABEL (label)' failed * * In the debugger, you can set a breakpoint in this function, and then see * the stacktrace on what is trying to access a widget that isn't set or * otherwise having issues. */ void my_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { g_usleep(1 * 1e6); } static void init_sockets() { #ifndef WIN32 signal(SIGPIPE, SIG_IGN); #endif } /** * Load the UI from the given path. On success, store path in window_xml_file. */ static char *init_ui_layout(const char *name) { guint retval = gtk_builder_add_from_file(window_xml, name, NULL); if (retval > 0 && strlen(name) > 0) { if (window_xml_file != name) { // FIXME: caught by Valgrind strncpy(window_xml_file, name, sizeof(window_xml_file)); } return window_xml_file; } else { return NULL; } } static void init_ui() { GError *error = NULL; GdkGeometry geometry; int i; /* Load dialog windows using GtkBuilder. */ dialog_xml = gtk_builder_new(); if (!gtk_builder_add_from_file(dialog_xml, DIALOG_FILENAME, &error)) { error_dialog("Couldn't load UI dialogs.", error->message); g_warning("Couldn't load UI dialogs: %s", error->message); g_error_free(error); exit(EXIT_FAILURE); } LOG(LOG_DEBUG, "init_ui", "loaded dialog_xml '%s'", DIALOG_FILENAME); /* Load main window using GtkBuilder. */ window_xml = gtk_builder_new(); if (init_ui_layout(window_xml_file) == NULL) { LOG(LOG_DEBUG, "init_ui_layout", "Could not initialize '%s', using default layout", window_xml_file); if (init_ui_layout(DEFAULT_UI) == NULL) { g_error("Could not load default layout!"); } } LOG(LOG_DEBUG, "init_ui", "loaded window_xml '%s'", window_xml_file); connect_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "connect_window")); gtk_window_set_transient_for(GTK_WINDOW(connect_window), GTK_WINDOW(window_root)); g_signal_connect(connect_window, "destroy", G_CALLBACK(on_window_destroy_event), NULL); main_notebook = GTK_NOTEBOOK(gtk_builder_get_object(dialog_xml, "main_notebook")); /* Begin connecting signals for the root window. */ window_root = GTK_WIDGET(gtk_builder_get_object(window_xml, "window_root")); if (window_root == NULL) { error_dialog("Could not load main window", "Check that your layout files are not corrupt."); exit(EXIT_FAILURE); } /* Request the window to receive focus in and out events */ gtk_widget_add_events((gpointer) window_root, GDK_FOCUS_CHANGE_MASK); g_signal_connect((gpointer) window_root, "focus-out-event", G_CALLBACK(focusoutfunc), NULL); g_signal_connect_swapped((gpointer) window_root, "key_press_event", G_CALLBACK(keyfunc), GTK_WIDGET(window_root)); g_signal_connect_swapped((gpointer) window_root, "key_release_event", G_CALLBACK(keyrelfunc), GTK_WIDGET(window_root)); g_signal_connect((gpointer) window_root, "destroy", G_CALLBACK(on_window_destroy_event), NULL); /* Purely arbitrary min window size */ geometry.min_width=640; geometry.min_height=480; gtk_window_set_geometry_hints(GTK_WINDOW(window_root), window_root, &geometry, GDK_HINT_MIN_SIZE); magic_map = GTK_WIDGET(gtk_builder_get_object(window_xml, "drawingarea_magic_map")); g_signal_connect((gpointer) magic_map, "expose_event", G_CALLBACK(on_drawingarea_magic_map_expose_event), NULL); /* Set up colors before doing the other initialization functions */ for (i = 0; i < NUM_COLORS; i++) { if (!gdk_color_parse(colorname[i], &root_color[i])) { fprintf(stderr, "gdk_color_parse failed (%s)\n", colorname[i]); } if (!gdk_colormap_alloc_color(gtk_widget_get_colormap(window_root), &root_color[i], FALSE, FALSE)) { fprintf(stderr, "gdk_color_alloc failed\n"); } } LOG(LOG_DEBUG, "init_ui", "sub init"); inventory_init(window_root); info_init(window_root); keys_init(window_root); stats_init(window_root); config_init(window_root); pickup_init(window_root); msgctrl_init(window_root); init_create_character_window(); metaserver_ui_init(); LOG(LOG_DEBUG, "init_ui", "window positions"); load_window_positions(window_root); LOG(LOG_DEBUG, "init_ui", "init themes"); init_theme(); LOG(LOG_DEBUG, "init_ui", "load themes"); load_theme(TRUE); LOG(LOG_DEBUG, "init_ui", "menu items"); init_menu_items(); } /** * Show main client window. Called after connect if server does not support * new loginmethod, or after character is selected. */ void show_main_client() { hide_all_login_windows(); gtk_widget_show(window_root); clear_stat_mapping(); map_init(window_root); } /** * Called if event_loop() exits, or whenever the character selection window * comes up (before logging in, or after having applied a bed). */ void hide_main_client() { gtk_widget_hide(window_root); remove_item_inventory(cpl.ob); /* * We know the following is the private map structure in item.c. But * we don't have direct access to it, so we still use locate. */ remove_item_inventory(locate_item(0)); cf_play_music("NONE"); gtk_widget_show(connect_window); } /** * Main client entry point. */ int main(int argc, char *argv[]) { global_time = g_timer_new(); #ifdef ENABLE_NLS bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); textdomain(GETTEXT_PACKAGE); #endif // Initialize GTK and client library. gtk_init(&argc, &argv); parse_args(argc, argv); client_init(); // Set defaults, load configuration, and parse arguments. config_load(); config_check(); char *layout = g_path_get_basename(window_xml_file); snprintf(VERSION_INFO, MAX_BUF, "GTKv2 Client " FULL_VERSION " (%s)", layout); g_free(layout); // Initialize UI, sockets, and sound server. LOG(LOG_DEBUG, "main", "init UI"); init_ui(); LOG(LOG_DEBUG, "main", "init sockets"); init_sockets(); LOG(LOG_DEBUG, "main", "init sound"); if (!want_config[CONFIG_SOUND] || !init_sounds()) { use_config[CONFIG_SOUND] = FALSE; } else { use_config[CONFIG_SOUND] = TRUE; } /* Load cached pixmaps. */ LOG(LOG_DEBUG, "main", "init image cache"); init_image_cache_data(); LOG(LOG_DEBUG, "main", "init done"); while (true) { gtk_widget_show(connect_window); if (connect_server == NULL) { metaserver_show_prompt(); gtk_main(); } else { client_connect(connect_server); if (csocket.fd == NULL) { LOG(LOG_ERROR, "main", "Unable to connect to %s!", connect_server); break; } cpl.input_state = Playing; } client_negotiate(use_config[CONFIG_SOUND]); if (serverloginmethod) { account_show_login(); } else { show_main_client(); } /* The event_loop will block until connection to the server is lost. */ event_loop(); hide_main_client(); /* * Need to reset the images so they match up properly and prevent * memory leaks. */ reset_image_data(); client_reset(); } } /** * Gets the coordinates of a specified window. * * @param win Pass in a GtkWidget pointer to get its coordinates. * @param x Parent-relative window x coordinate * @param y Parent-relative window y coordinate * @param wx ? * @param wy ? * @param w Window width * @param h Window height */ void get_window_coord(GtkWidget *win, int *x, int *y, int *wx, int *wy, int *w, int *h) { /* Position of a window relative to its parent window. */ gdk_window_get_geometry(gtk_widget_get_window(win), x, y, w, h, NULL); /* Position of the window in root window coordinates. */ gdk_window_get_origin(gtk_widget_get_window(win), wx, wy); *wx -= *x; *wy -= *y; } crossfire-client-1.75.3/gtk-v2/src/stats.c000644 001751 001751 00000064622 14045044330 021154 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Support for character statistics. */ #include "client.h" #include #include #include "main.h" #include "image.h" #include "gtk2proto.h" #define STAT_BAR_HP 0 #define STAT_BAR_SP 1 #define STAT_BAR_GRACE 2 #define STAT_BAR_FOOD 3 #define STAT_BAR_EXP 4 #define MAX_STAT_BARS 5 static const char * const stat_bar_names[MAX_STAT_BARS] = { "hp", "sp", "grace", "food", "exp" }; static GtkWidget *stat_bar[MAX_STAT_BARS]; #define STYLE_NORMAL 0 #define STYLE_LOW 1 #define STYLE_SUPER 2 #define STYLE_GRAD_NORMAL 3 #define STYLE_GRAD_LOW 4 #define STYLE_GRAD_SUPER 5 #define NUM_STYLES 6 /* The name of the symbolic widget names we try to look up the styles of * (these will be prefixed with hp_, sp_, etc). This should always match * NUM_STYLES. */ static const char * const stat_style_names[NUM_STYLES] = { "bar_normal", "bar_low", "bar_super", "gradual_bar_normal", "gradual_bar_low", "gradual_bar_super" }; /* We really only care about the colors, as there isn't anything else we can * change about the progressbar widget itself. */ GdkColor *bar_colors[MAX_STAT_BARS][NUM_STYLES]; /* The table for showing skill exp is an x & y grid. Note for proper * formatting, SKILL_BOXES_X must be even. Hmmm - perhaps these should * instead be dynamically generated? */ #define SKILL_BOXES_X 6 #define SKILL_BOXES_Y 17 #define PROTECTION_BOXES_X 6 #define PROTECTION_BOXES_Y 6 typedef struct { GtkWidget *playername; GtkWidget *Str; GtkWidget *Dex; GtkWidget *Con; GtkWidget *Int; GtkWidget *Wis; GtkWidget *Cha; GtkWidget *Pow; GtkWidget *wc; GtkWidget *dam; GtkWidget *ac; GtkWidget *armor; GtkWidget *speed; GtkWidget *weapon_speed; GtkWidget *range; GtkWidget *exp; GtkWidget *level; GtkWidget *table_skills_exp; GtkWidget *table_protections; GtkWidget *skill_exp[SKILL_BOXES_X * SKILL_BOXES_Y]; GtkWidget *resists[PROTECTION_BOXES_X * PROTECTION_BOXES_Y]; } StatWindow; static StatWindow statwindow; static gboolean need_mapping_update; static int lastval[MAX_STAT_BARS], lastmax[MAX_STAT_BARS]; /** * Gets the style information for the stat bars (only portion of the window * right now that has custom style support. */ void stats_get_styles(void) { static int has_init=0; int stat_bar, sub_style; char buf[MAX_BUF]; GtkStyle *tmp_style; if (!has_init) { memset(bar_colors, 0, sizeof(GdkColor*) * MAX_STAT_BARS * NUM_STYLES); } for (stat_bar=0; stat_bar < MAX_STAT_BARS; stat_bar++) { for (sub_style=0; sub_style < NUM_STYLES; sub_style++) { snprintf(buf, sizeof(buf), "%s_%s", stat_bar_names[stat_bar], stat_style_names[sub_style]); tmp_style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL, buf, G_TYPE_NONE); if (!tmp_style) { if (bar_colors[stat_bar][sub_style]) { free(bar_colors[stat_bar][sub_style]); bar_colors[stat_bar][sub_style] = NULL; } LOG(LOG_INFO, "stats.c::stats_get_styles()", "Unable to find style '%s'", buf); } else { if (!bar_colors[stat_bar][sub_style]) { bar_colors[stat_bar][sub_style] = calloc(1, sizeof(GdkColor)); } memcpy(bar_colors[stat_bar][sub_style], &tmp_style->base[GTK_STATE_SELECTED], sizeof(GdkColor)); } } } } /** * Associate the XML-defined widgets with pointers by name reference. * @param *window_root */ void stats_init(GtkWidget *window_root) { int i, x, y; char buf[MAX_BUF]; for (i=0; i 0; i--) { if (number / SI_VALUE[i] >= 10) { suffix = i; break; } } value = number / SI_VALUE[suffix]; /* If possible, trim the trailing zero decimal. */ if (value - (int)value == 0) { return g_strdup_printf("%.0f%c", value, SI_SUFFIX[suffix]); } else { return g_strdup_printf("%.1f%c", value, SI_SUFFIX[suffix]); } } /** * Updates the stat bar and text display as it pertains to a specific stat. * * @param stat_no * The stat number to update. * @param max_stat * The normal maximum value this stat can have. Note that within game terms, * the actual value can go above this via supercharging stats. * @param current_stat * current value of the stat. * @param statbar_max * @param statbar_stat * this is the stat value to use for drawing the statbar. For most * stats, this is same as current stat, but for the exp bar, * we basically want it to be a graph relative to amount for next level. * @param can_alert * Whether this stat can go on alert when it gets low. It doesn't make * sense for this to happen on exp (not really an alert if you gain a * level). Note: This is no longer used with the new style code - if * a stat shouldn't ever change color when it is low, the style should * dictate that. */ void update_stat(int stat_no, gint64 max_stat, gint64 current_stat, gint64 statbar_max, gint64 statbar_stat, int can_alert) { float bar; GdkColor ncolor, *set_color=NULL; /* If nothing changed, don't need to do anything */ if (lastval[stat_no] == current_stat && lastmax[stat_no] == max_stat) { return; } lastval[stat_no] = current_stat; lastmax[stat_no] = max_stat; if (statbar_max > 0) { bar = (float) statbar_stat / (float) statbar_max; } else { bar = 0.0; } if (use_config[CONFIG_GRAD_COLOR]) { /* In this mode, the color of the stat bar were go between red and green * in a gradual style. Color is blended from low to high */ GdkColor *hcolor, *lcolor; float diff; /* First thing we do is figure out current values, and thus what color * bases we use (based on super charged or normal value). We also set * up diff as where we are between those two points. In this way, the * blending logic below is the same regardless of actual value. */ if (bar > 1.0) { if (bar>2.0) { bar=2.0; /* Display unaffected; just calculations */ } hcolor = bar_colors[stat_no][STYLE_GRAD_SUPER]; lcolor = bar_colors[stat_no][STYLE_GRAD_NORMAL]; diff = bar - 1.0; } else { if (bar < 0.0) { bar=0.0; /* Like above, does not affect display */ } hcolor = bar_colors[stat_no][STYLE_GRAD_NORMAL]; lcolor = bar_colors[stat_no][STYLE_GRAD_LOW]; diff = bar; } /* Now time to blend. First, make sure colors are set. then, we use * the lcolor as the base, making adjustments based on hcolor. Values * in hcolor may be lower than lcolor, but that just means we * substract from lcolor, not add. */ if (lcolor && hcolor) { #if 1 memcpy(&ncolor, lcolor, sizeof(GdkColor)); ncolor.red += (hcolor->red - lcolor->red) * diff; ncolor.green += (hcolor->green - lcolor->green) * diff; ncolor.blue += (hcolor->blue - lcolor->blue) * diff; #else /* This is an alternate coloring method that works when using * saturated colors for the base points. This mimics the old * code, and works good when using such saturated colors (eg, one * of the RGB triplets being 255, others 0, like red, green, or * blue). However, this doesn't produce very good results when * not using those colors - if say magenta and yellow are chosen * as the two colors, this code results in the colors basically * getting near white in the middle values. For saturated colors, * the code below would produce nice bright yellow for the middle * values, where as the code above produces more a dark yellow, * since it only takes half the red and half the green. However, * the code above still produces useful results even with that * limitation, and it works for all colors, so it is the code * enabled. It perhaps be interesting to have some detection * logic on how the colors are actually set - if only a single * r/g/b value is set for the two colors, then use this logic * here, otherwise the above logic or something. * MSW 2007-01-24 */ if (diff > 0.5) { memcpy(&ncolor, hcolor, sizeof(GdkColor)); if (lcolor->red > hcolor->red) { ncolor.red = 2 * lcolor->red * (1.0 - diff); } if (lcolor->green > hcolor->green) { ncolor.green = 2 * lcolor->green * (1.0 - diff); } if (lcolor->blue > hcolor->blue) { ncolor.blue = 2 * lcolor->blue * (1.0 - diff); } } else { memcpy(&ncolor, lcolor, sizeof(GdkColor)); if (hcolor->red > lcolor->red) { ncolor.red = 2 * hcolor->red * diff; } if (hcolor->green > lcolor->green) { ncolor.green = 2 * hcolor->green * diff; } if (hcolor->blue > lcolor->blue) { ncolor.blue = 2 * hcolor->blue * diff; } } #endif #if 0 fprintf(stderr,"stat %d, val %d, r/g/b=%d/%d/%d\n", stat_no, current_stat, ncolor.red, ncolor.green, ncolor.blue); #endif set_color = &ncolor; } } else { if (statbar_stat * 4 < statbar_max) { set_color = bar_colors[stat_no][STYLE_LOW]; } else if (statbar_stat > statbar_max) { set_color = bar_colors[stat_no][STYLE_SUPER]; } else { set_color = bar_colors[stat_no][STYLE_NORMAL]; } } if (bar > 1.0) { bar = 1.0; } if (bar < 0.0) { bar = 0.0; } GtkProgressBar *curr_bar = GTK_PROGRESS_BAR(stat_bar[stat_no]); /* It may be a waste, but we set the color everytime here - it isn't very * costly, and keeps us from tracing the last color we set. Note that * set_color could be null, which means it reverts back to normal color. */ gtk_widget_modify_base(stat_bar[stat_no], GTK_STATE_SELECTED, set_color); /* The line above doesn't work sometimes, but then, the next one does. */ gtk_widget_modify_bg(stat_bar[stat_no], GTK_STATE_PRELIGHT, set_color); char *label; // Display experience using SI prefixes; everything else normally. if (stat_no == STAT_BAR_EXP) { char *exp_curr = format_si_number(current_stat); char *exp_max = format_si_number(max_stat); label = g_strdup_printf("%s/%s", exp_curr, exp_max); g_free(exp_curr); g_free(exp_max); } else { label = g_strdup_printf("%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, current_stat, max_stat); } gtk_progress_bar_set_fraction(curr_bar, bar); gtk_progress_bar_set_text(curr_bar, label); g_free(label); } /** * Updates the stats pane - hp, sp, etc labels * * @param redraw */ void draw_message_window(int redraw) { static int lastbeep=0; static gint64 level_diff; update_stat(STAT_BAR_HP, cpl.stats.maxhp, cpl.stats.hp, cpl.stats.maxhp, cpl.stats.hp, TRUE); update_stat(STAT_BAR_SP, cpl.stats.maxsp, cpl.stats.sp, cpl.stats.maxsp, cpl.stats.sp, TRUE); update_stat(STAT_BAR_GRACE, cpl.stats.maxgrace, cpl.stats.grace, cpl.stats.maxgrace, cpl.stats.grace, TRUE); update_stat(STAT_BAR_FOOD, 999, cpl.stats.food, 999, cpl.stats.food, TRUE); /* We may or may not have an exp table from the server. If we don't, just * use current exp value so it will always appear maxed out. */ /* We calculate level_diff here just so it makes the update_stat() * call below less messy. */ if ((cpl.stats.level+1) < exp_table_max) { level_diff = exp_table[cpl.stats.level+1] - exp_table[cpl.stats.level]; } else { level_diff=cpl.stats.exp; } update_stat(STAT_BAR_EXP, (cpl.stats.level+1) < exp_table_max ? exp_table[cpl.stats.level+1]:cpl.stats.exp, cpl.stats.exp, level_diff, (cpl.stats.level+1) < exp_table_max ? (cpl.stats.exp - exp_table[cpl.stats.level]):cpl.stats.exp, FALSE); if (use_config[CONFIG_FOODBEEP] && (cpl.stats.food%4==3) && (cpl.stats.food < 200)) { gdk_beep( ); } else if (use_config[CONFIG_FOODBEEP] && cpl.stats.food == 0 && ++lastbeep == 5) { lastbeep = 0; gdk_beep( ); } } /** * The mapping tables may not be completely full, so handle null values. * Always treat null values as later in the sort order. */ static int mapping_sort(NameMapping *a, NameMapping *b) { if (!a->name && !b->name) { return 0; } if (!a->name) { return 1; } if (!b->name) { return -1; } else { return g_ascii_strcasecmp(a->name, b->name); } } /** * */ static void update_stat_mapping(void) { int i; for (i=0; i < MAX_SKILL; i++) { skill_mapping[i].value=i; if (skill_names[i]) { skill_mapping[i].name = skill_names[i]; } else { skill_mapping[i].name = NULL; } } qsort(skill_mapping, MAX_SKILL, sizeof(NameMapping), (int (*)(const void*, const void*))mapping_sort); for (i=0; i < NUM_RESISTS; i++) { resist_mapping[i].value=i; if (resists_name[i]) { resist_mapping[i].name = resists_name[i]; } else { resist_mapping[i].name = NULL; } } qsort(resist_mapping, NUM_RESISTS, sizeof(NameMapping), (int (*)(const void*, const void*))mapping_sort); need_mapping_update = FALSE; } /** * Draws the stats window. If redraw is true, it means we need to redraw the * entire thing, and not just do an updated */ void draw_stats(int redraw) { static Stats last_stats; static char last_name[MAX_BUF]="", last_range[MAX_BUF]=""; static int init_before=0, max_drawn_skill=0, max_drawn_resists=0; float weap_sp; char buff[MAX_BUF]; int i, on_skill, sk; if (!init_before) { init_before=1; memset(&last_stats, 0, sizeof(Stats)); } /* skill_names gets set as part of the initialization with the * client - however, right now, there is no callback when * it is set, so instead, just track that wee need to update * and see if it changes. */ if (need_mapping_update && skill_names[1] != NULL) { update_stat_mapping(); } if (strcmp(cpl.title, last_name) || redraw) { strcpy(last_name, cpl.title); gtk_label_set_text(GTK_LABEL(statwindow.playername), cpl.title); } if (redraw || cpl.stats.exp != last_stats.exp) { last_stats.exp = cpl.stats.exp; snprintf(buff, sizeof(buff), "Experience: %5" G_GINT64_FORMAT, cpl.stats.exp); gtk_label_set_text(GTK_LABEL(statwindow.exp), buff); } if (redraw || cpl.stats.level != last_stats.level) { last_stats.level = cpl.stats.level; snprintf(buff, sizeof(buff), "Level: %d", cpl.stats.level); gtk_label_set_text(GTK_LABEL(statwindow.level), buff); } if (redraw || cpl.stats.Str != last_stats.Str) { last_stats.Str = cpl.stats.Str; snprintf(buff, sizeof(buff), "%2d", cpl.stats.Str); gtk_label_set_text(GTK_LABEL(statwindow.Str), buff); } if (redraw || cpl.stats.Dex != last_stats.Dex) { last_stats.Dex = cpl.stats.Dex; snprintf(buff, sizeof(buff), "%2d", cpl.stats.Dex); gtk_label_set_text(GTK_LABEL(statwindow.Dex), buff); } if (redraw || cpl.stats.Con != last_stats.Con) { last_stats.Con = cpl.stats.Con; snprintf(buff, sizeof(buff), "%2d", cpl.stats.Con); gtk_label_set_text(GTK_LABEL(statwindow.Con), buff); } if (redraw || cpl.stats.Int != last_stats.Int) { last_stats.Int = cpl.stats.Int; snprintf(buff, sizeof(buff), "%2d", cpl.stats.Int); gtk_label_set_text(GTK_LABEL(statwindow.Int), buff); } if (redraw || cpl.stats.Wis != last_stats.Wis) { last_stats.Wis = cpl.stats.Wis; snprintf(buff, sizeof(buff), "%2d", cpl.stats.Wis); gtk_label_set_text(GTK_LABEL(statwindow.Wis), buff); } if (redraw || cpl.stats.Pow != last_stats.Pow) { last_stats.Pow = cpl.stats.Pow; snprintf(buff, sizeof(buff), "%2d", cpl.stats.Pow); gtk_label_set_text(GTK_LABEL(statwindow.Pow), buff); } if (redraw || cpl.stats.Cha != last_stats.Cha) { last_stats.Cha = cpl.stats.Cha; snprintf(buff, sizeof(buff), "%2d", cpl.stats.Cha); gtk_label_set_text(GTK_LABEL(statwindow.Cha), buff); } if (redraw || cpl.stats.wc != last_stats.wc) { last_stats.wc = cpl.stats.wc; snprintf(buff, sizeof(buff), "%2d", cpl.stats.wc); gtk_label_set_text(GTK_LABEL(statwindow.wc), buff); } if (redraw || cpl.stats.dam != last_stats.dam) { last_stats.dam = cpl.stats.dam; snprintf(buff, sizeof(buff), "%d", cpl.stats.dam); gtk_label_set_text(GTK_LABEL(statwindow.dam), buff); } if (redraw || cpl.stats.ac != last_stats.ac) { last_stats.ac = cpl.stats.ac; snprintf(buff, sizeof(buff), "%d", cpl.stats.ac); gtk_label_set_text(GTK_LABEL(statwindow.ac), buff); } if (redraw || cpl.stats.resists[0] != last_stats.resists[0]) { last_stats.resists[0] = cpl.stats.resists[0]; snprintf(buff, sizeof(buff), "%d", cpl.stats.resists[0]); gtk_label_set_text(GTK_LABEL(statwindow.armor), buff); } if (redraw || cpl.stats.speed != last_stats.speed) { last_stats.speed = cpl.stats.speed; snprintf(buff, sizeof(buff), "%3.2f", (float)cpl.stats.speed / FLOAT_MULTF); gtk_label_set_text(GTK_LABEL(statwindow.speed), buff); } /* sc_version >= 1029 reports real value of weapon speed - * not as a factor of player speed. Handle accordingly. */ if (csocket.sc_version >= 1029) { weap_sp = (float)cpl.stats.weapon_sp / FLOAT_MULTF; } else { weap_sp = (float)cpl.stats.speed / ((float)cpl.stats.weapon_sp); } if (redraw || weap_sp != last_stats.weapon_sp) { last_stats.weapon_sp = weap_sp; snprintf(buff, sizeof(buff), "%3.2f", weap_sp); gtk_label_set_text(GTK_LABEL(statwindow.weapon_speed), buff); } if (redraw || strcmp(cpl.range, last_range)) { strcpy(last_range, cpl.range); snprintf(buff, sizeof(buff), "Range: %s", cpl.range); gtk_label_set_text(GTK_LABEL(statwindow.range), cpl.range); } update_skill_information(); if (statwindow.table_skills_exp) { /* Do not attempt to set up the table_skills_exp widget if it was not * defined in the layout. */ on_skill=0; assert(sizeof(statwindow.skill_exp)/sizeof(*statwindow.skill_exp) >= 2*MAX_SKILL); for (i=0; i= PROTECTION_BOXES_X * PROTECTION_BOXES_Y) { break; } } } /* Erase old/unused resistances */ if (j < max_drawn_resists) { for (int i = j; i <= max_drawn_resists; i++) { gtk_label_set_text(GTK_LABEL(statwindow.resists[i]), ""); } } max_drawn_resists = j; } /* if we draw the resists */ /* Don't need to worry about hp, sp, grace, food - update_stat() * deals with that as part of the stat bar logic. */ } void clear_stat_mapping() { need_mapping_update = TRUE; } crossfire-client-1.75.3/gtk-v2/src/account.c000644 001751 001751 00000140164 14323707640 021457 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Handle account creation, login, and character selection */ #include "client.h" #include #include #include "image.h" #include "main.h" #include "metaserver.h" #include "gtk2proto.h" #include "script.h" /* These are in the login_window */ static GtkWidget *button_login, *button_create_account, *button_go_metaserver, *entry_account_name, *entry_account_password, *label_account_login_status; /* These are in the create_account_window */ static GtkWidget *button_new_create_account, *button_new_cancel, *entry_new_account_name, *entry_new_account_password, *entry_new_confirm_password, *label_create_account_status; /* These are in the choose_character window */ static GtkWidget *button_play_character, *button_create_character, *button_add_character, *button_return_login, *button_account_password, *treeview_choose_character; /* These are in the new_character window */ static GtkWidget *entry_new_character_name, *new_character_window, *label_new_char_status, *button_create_new_char, *button_new_char_cancel; /* These are in the account_password window */ static GtkWidget *entry_account_password_current, *entry_account_password_new, *entry_account_password_confirm, *button_account_password_confirm, *button_account_password_cancel, *label_account_password_status; GtkListStore *character_store; /* create_char.c also uses this */ char account_password[256]; /* This enum just maps the columns in the list store to their position. */ enum {CHAR_IMAGE, CHAR_NAME, CHAR_CLASS, CHAR_RACE, CHAR_LEVEL, CHAR_PARTY, CHAR_MAP, CHAR_ICON }; #define CHAR_NUM_COLUMNS 8 /* These are in the add_character window */ static GtkWidget *button_do_add_character, *button_return_character_select, *entry_character_name, *entry_character_password, *label_add_status; GtkTextBuffer *textbuf_motd, *textbuf_news, *textbuf_rules_account, *textbuf_rules_char; /* These are used as offsets for num_text_views - we share the drawing code in * info.c if more textviews are added, note that NUM_TEXT_VIEWS in info.c * needs to be increased. */ #define TEXTVIEW_MOTD 0 #define TEXTVIEW_NEWS 1 #define TEXTVIEW_RULES_ACCOUNT 2 #define TEXTVIEW_RULES_CHAR 3 Info_Pane login_pane[4]; extern int num_text_views; static int has_init = 0; /** * Hides all the login related windows. This is needed in case the client * loses the connection to the server (either through player going to * client/disconnect or network failure). get_metaserver() calls this, as * well as AddMeSuccess */ void hide_all_login_windows() { extern GtkWidget *treeview_look; gtk_widget_hide(connect_window); if (has_init) { /* If we have not initialized, nothing to hide */ gtk_widget_hide(new_character_window); create_character_window_hide(); /* create_char.c */ /* If the player has started playing (this function being called from * AddMeSuccess), we want to make sure that the extended command entry * widget is not activated - we want normal command entry. Where this * shows up is if the player was playing before and uses a savebed - * now the last thing activated is that entry widget. */ gtk_widget_grab_focus(GTK_WIDGET(treeview_look)); } } /** * Prevent delete_event closure and/or hiding of account windows. All account * system windows ignore delete events and remain visible unless the user * clicks an appropriate button. * * @param window Pointer to an account window that received a delete_event. * @param user_data Unused. */ gboolean on_window_delete_event(GtkWidget *window, gpointer *user_data) { return TRUE; } /***************************************************************************** * New character window functions *****************************************************************************/ /** * Pop up a dialog window with the error from the server. * Since both v1 and v2 character creation are supported, * either the new_character_window or the create_character_window * may be up, so we can not easily display an in window message - * a pop up is probably better, but it will also work no matter * what window is up. * * @param message * message - this comes from the server. */ void create_new_character_failure(char *message) { hide_main_client(); GtkWidget *dialog; dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK, "Error: %s", message); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } static void create_new_character() { const char *name; guint8 buf[MAX_BUF]; SockList sl; SockList_Init(&sl, buf); name = gtk_entry_get_text(GTK_ENTRY(entry_new_character_name)); if (!name || *name == 0) { gtk_label_set_text(GTK_LABEL(label_new_char_status), "You must enter a character name."); return; } else { gtk_label_set_text(GTK_LABEL(label_new_char_status), ""); SockList_AddString(&sl, "createplayer "); SockList_AddChar(&sl, strlen(name)); SockList_AddString(&sl, name); SockList_AddChar(&sl, strlen(account_password)); SockList_AddString(&sl, account_password); SockList_Send(&sl, csocket.fd); } } /** * User hit the create character button. Get data, send to server. * @param button * @param user_data */ void on_button_create_new_char_clicked(GtkButton *button, gpointer user_data) { create_new_character(); } /** * User hit return in the new character name box. Like above, get data and * send to server. * @param entry * @param user_data */ void on_entry_new_character_name(GtkEntry *entry, gpointer user_data) { create_new_character(); } /** * User his hit the cancel button in the new character window, so hide the new * character window, show the choose character window. * @param button * @param user_data */ void on_button_new_char_cancel_clicked(GtkButton *button, gpointer user_data) { gtk_widget_hide(new_character_window); choose_char_window_show(); } /** * Initializes the new character window. */ static void init_new_character_window() { new_character_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "create_character_window")); gtk_window_set_transient_for( GTK_WINDOW(new_character_window), GTK_WINDOW(window_root)); button_create_new_char = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_character")); button_new_char_cancel = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_cc_cancel")); entry_new_character_name = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "cc_entry_new_character_name")); label_new_char_status = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_cc_status_update")); g_signal_connect((gpointer) new_character_window, "delete_event", G_CALLBACK(on_window_delete_event), NULL); g_signal_connect((gpointer) button_create_new_char, "clicked", G_CALLBACK(on_button_create_new_char_clicked), NULL); g_signal_connect((gpointer) button_new_char_cancel, "clicked", G_CALLBACK(on_button_new_char_cancel_clicked), NULL); g_signal_connect((gpointer) entry_new_character_name, "activate", G_CALLBACK(on_entry_new_character_name), NULL); } /****************************************************************************** * add_character_window functions *****************************************************************************/ /** * Sends a request to the server add add the character to this account. * @param name * @param password * @param force */ static void add_character_to_account(const char *name, const char *password, int force) { SockList sl; guint8 buf[MAX_BUF]; if (!name || !password || *name == 0 || *password == 0) { gtk_label_set_text(GTK_LABEL(label_add_status), "You must enter both a name and password!"); } else { gtk_label_set_text(GTK_LABEL(label_add_status), ""); SockList_Init(&sl, buf); SockList_AddString(&sl, "accountaddplayer "); SockList_AddChar(&sl, force); SockList_AddChar(&sl, strlen(name)); SockList_AddString(&sl, name); SockList_AddChar(&sl, strlen(password)); SockList_AddString(&sl, password); SockList_Send(&sl, csocket.fd); } } /** * Handles a failure from the server - pretty basic - just throw up the * message and let the user try again. This is a response to the 'failure * accountaddplayer' command. Calling this account_add_character_failure may * be a little bit of a misnomer, but all the other routines in this area * refer to character, not player. * * @param message Message to display. Unlike other messages, the first word * of this message should be an integer, which denotes if using the 'force' * option would allow the user to override this. */ void account_add_character_failure(char *message) { char *cp; int retry; retry = atoi(message); cp = strchr(message, ' '); if (cp) { cp++; } else { cp = message; } if (!retry) { gtk_label_set_text(GTK_LABEL(label_add_status), cp); } else { /* In this case, we can retry it and it should work if we set force. * So bring up a dialog, as the user what to do - if they enter yes, * we use force. If not, we clear the entry fields and just continue * onward. */ GtkWidget *dialog; int result; const char *name, *password; /* Bring up a dialog window */ dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s\n%s", cp, "Apply anyways?"); result = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if (result == GTK_RESPONSE_YES) { name = gtk_entry_get_text(GTK_ENTRY(entry_character_name)); password = gtk_entry_get_text(GTK_ENTRY(entry_character_password)); add_character_to_account(name, password, 1); } else { gtk_entry_set_text(GTK_ENTRY(entry_character_name), ""); gtk_entry_set_text(GTK_ENTRY(entry_character_password), ""); gtk_widget_grab_focus(entry_character_name); } } } /** * User has hit the add character button. Let add_character_to_account() * do all the work. * * @param button * @param user_data */ void on_button_do_add_character_clicked(GtkButton *button, gpointer user_data) { add_character_to_account( gtk_entry_get_text(GTK_ENTRY(entry_character_name)), gtk_entry_get_text(GTK_ENTRY(entry_character_password)), 0); } /** * User has hit the return to character selection button. Pretty simple - * just hide this window, activate the other window. * * @param button * @param user_data */ void on_button_return_character_select_clicked(GtkButton *button, gpointer user_data) { gtk_notebook_set_current_page(main_notebook, 3); } /** * User has hit return in either name or password box. If both boxes have non * empty data, process request. Otherwise, either stay in same box if this * box is empty, or move to the other box. * * @param entry Entry widget which generated this callback. * @param user_data */ void on_entry_character(GtkEntry *entry, gpointer user_data) { const char *name, *password; name = gtk_entry_get_text(GTK_ENTRY(entry_character_name)); password = gtk_entry_get_text(GTK_ENTRY(entry_character_password)); if (name && name[0] && password && password[0]) { add_character_to_account(name, password, 0); } else { const char *cp; /* First case - this widget is empty - do nothing */ cp = gtk_entry_get_text(entry); if (!cp || !cp[0]) { return; } /* In this case, this widget is not empty - means the other one is. */ if (entry == GTK_ENTRY(entry_character_name)) { gtk_widget_grab_focus(entry_character_password); } else { gtk_widget_grab_focus(entry_character_name); } } } static void init_add_character_window() { button_do_add_character = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_do_add_character")); button_return_character_select = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_return_character_select")); entry_character_name = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_character_name")); entry_character_password = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_character_password")); label_add_status = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_add_status")); g_signal_connect((gpointer) button_do_add_character, "clicked", G_CALLBACK(on_button_do_add_character_clicked), NULL); g_signal_connect((gpointer) button_return_character_select, "clicked", G_CALLBACK(on_button_return_character_select_clicked), NULL); g_signal_connect((gpointer) entry_character_name, "activate", G_CALLBACK(on_entry_character), NULL); g_signal_connect((gpointer) entry_character_password, "activate", G_CALLBACK(on_entry_character), NULL); } /***************************************************************************** * choose_char_window ****************************************************************************/ /** * Called when we get the accountplayers command from the server (indirectly * via AccountPlayersCmd). This tells us to wipe any data from the treeview, * but also hide any other windows and make the choose_character_window * visible. */ void choose_character_init() { hide_main_client(); choose_char_window_show(); /* Store any old/stale entries */ gtk_list_store_clear(character_store); } /** * Basic little function - this is used because * we make the choose_char_window widget private to this * file, but the create_char.c file will need to show * this if the user decides to abandon creation of a new * character. */ void choose_char_window_show() { gtk_notebook_set_current_page(main_notebook, 3); } /** * User has done necessary steps to play a character. * @param name */ static void play_character(const char *name) { SockList sl; guint8 buf[MAX_BUF]; SockList_Init(&sl, buf); SockList_AddString(&sl, "accountplay "); SockList_AddString(&sl, name); SockList_Send(&sl, csocket.fd); } /** * User has hit the play character button. Grab the selected entry, if there * is one. * @param button * @param user_data */ void on_button_play_character_clicked(GtkButton *button, gpointer user_data) { GtkTreeSelection *selected; GtkTreeModel *model; GtkTreeIter iter; char *name; selected = gtk_tree_view_get_selection(GTK_TREE_VIEW( treeview_choose_character)); if (gtk_tree_selection_get_selected(selected, &model, &iter)) { gtk_tree_model_get(model, &iter, CHAR_NAME, &name, -1); show_main_client(); play_character(name); } } /** * * @param button * @param user_data */ void on_button_create_character_clicked(GtkButton *button, gpointer user_data) { if (serverloginmethod >= 2) { create_character_window_show(); } else { gtk_widget_show(new_character_window); gtk_entry_set_text(GTK_ENTRY(entry_new_character_name), ""); } } /** * User has hit the add character button, so hide this window, show the add * character window. * @param button * @param user_data */ void on_button_add_character_clicked(GtkButton *button, gpointer user_data) { gtk_notebook_set_current_page(main_notebook, 5); gtk_entry_set_text(GTK_ENTRY(entry_character_name), ""); gtk_entry_set_text(GTK_ENTRY(entry_character_password), ""); gtk_widget_grab_focus(entry_character_name); } /** * User has hit the return to login window, so hide this window, show the * account login window. * @param button * @param user_data */ void on_button_return_login_clicked(GtkButton *button, gpointer user_data) { gtk_notebook_set_current_page(main_notebook, 1); } /** * User has hit the change account password, so hide this window, show the * account password change dialog. * @param button * @param user_data */ void on_button_account_password_clicked(GtkButton *button, gpointer user_data) { gtk_notebook_set_current_page(main_notebook, 4); /* reset previous values */ gtk_entry_set_text(GTK_ENTRY(entry_account_password_current), ""); gtk_entry_set_text(GTK_ENTRY(entry_account_password_new), ""); gtk_entry_set_text(GTK_ENTRY(entry_account_password_confirm), ""); } /** * This gets data and adds it to the list store. This is called from * AccountPlayersCmd and data is from the accountplayers protocol command. * The parameters are data to add to the list store. * * @param name * @param class * @param race * @param face * @param party * @param map * @param level * @param faceno */ void update_character_choose(const char *name, const char *class, const char *race, const char *face, const char *party, const char *map, int level, int faceno) { GtkTreeIter iter; gtk_list_store_append(character_store, &iter); /* If this pixmap matches pixmap[0], it means we are caching images and * this image hasn't been set up. It looks better in this case to just * leave that area of the window blank vs drawing a question mark there. */ if (pixmaps[faceno] == pixmaps[0]) { gtk_list_store_set(character_store, &iter, CHAR_NAME, name, CHAR_CLASS, class, CHAR_RACE, race, CHAR_IMAGE, face, CHAR_PARTY, party, CHAR_MAP, map, CHAR_LEVEL, level, -1); } else { gtk_list_store_set(character_store, &iter, CHAR_ICON, pixmaps[faceno]->icon_image, CHAR_NAME, name, CHAR_CLASS, class, CHAR_RACE, race, CHAR_IMAGE, face, CHAR_PARTY, party, CHAR_MAP, map, CHAR_LEVEL, level, -1); } } static void init_choose_char_window() { GtkTextIter end; GtkCellRenderer *renderer; GtkTreeViewColumn *column; button_play_character = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_play_character")); button_create_character = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_character")); button_add_character = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_add_character")); button_return_login = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_return_login")); button_account_password = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_account_password")); login_pane[TEXTVIEW_RULES_CHAR].textview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_char")); textbuf_rules_char = gtk_text_view_get_buffer( GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_CHAR].textview)); treeview_choose_character = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "treeview_choose_character")); add_tags_to_textbuffer( &login_pane[TEXTVIEW_RULES_CHAR], textbuf_rules_char); add_style_to_textbuffer(&login_pane[TEXTVIEW_RULES_CHAR], NULL); gtk_text_buffer_get_end_iter( login_pane[TEXTVIEW_RULES_CHAR].textbuffer, &end); login_pane[TEXTVIEW_RULES_CHAR].textmark = gtk_text_buffer_create_mark( login_pane[TEXTVIEW_RULES_CHAR].textbuffer, NULL, &end, FALSE); g_signal_connect((gpointer) button_play_character, "clicked", G_CALLBACK(on_button_play_character_clicked), NULL); g_signal_connect((gpointer) button_create_character, "clicked", G_CALLBACK(on_button_create_character_clicked), NULL); g_signal_connect((gpointer) button_add_character, "clicked", G_CALLBACK(on_button_add_character_clicked), NULL); g_signal_connect((gpointer) button_return_login, "clicked", G_CALLBACK(on_button_return_login_clicked), NULL); g_signal_connect((gpointer) button_account_password, "clicked", G_CALLBACK(on_button_account_password_clicked), NULL); g_signal_connect((gpointer) treeview_choose_character, "row_activated", G_CALLBACK(on_button_play_character_clicked), NULL); character_store = gtk_list_store_new(CHAR_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_OBJECT); gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_choose_character), GTK_TREE_MODEL(character_store)); renderer = gtk_cell_renderer_pixbuf_new(); column = gtk_tree_view_column_new_with_attributes("?", renderer, "pixbuf", CHAR_ICON, NULL); gtk_tree_view_column_set_min_width(column, image_size); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Character Name", renderer, "text", CHAR_NAME, NULL); gtk_tree_view_column_set_sort_column_id(column, CHAR_NAME); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Class", renderer, "text", CHAR_CLASS, NULL); gtk_tree_view_column_set_sort_column_id(column, CHAR_CLASS); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Race", renderer, "text", CHAR_RACE, NULL); gtk_tree_view_column_set_sort_column_id(column, CHAR_RACE); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Level", renderer, "text", CHAR_LEVEL, NULL); gtk_tree_view_column_set_sort_column_id(column, CHAR_LEVEL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Party", renderer, "text", CHAR_PARTY, NULL); gtk_tree_view_column_set_sort_column_id(column, CHAR_PARTY); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Map", renderer, "text", CHAR_MAP, NULL); gtk_tree_view_column_set_sort_column_id(column, CHAR_MAP); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column); } /****************************************************************************** * create_account_window ******************************************************************************/ /** * Handles a failure from the server - pretty basic - just throw up the * message and let the user try again. * @param message */ void account_creation_failure(char *message) { gtk_label_set_text(GTK_LABEL(label_create_account_status), message); } /** * This does sanity checking of the passed in data, and if all is good, sends * the request to the server to create an account. If all the data isn't * good, it puts up an error message. In this routine, none of the entries * should be NULL - the caller should verify that before callin * do_account_create(); * * @param name Desired account name - must not be NULL. * @param p1 First password - must not be NULL * @param p2 Second (confirmed) password. This routine checks that p1 & p2 * are the same, and if not, puts up an error. p2 must not be NULL */ static void do_account_create(const char *name, const char *p1, const char *p2) { SockList sl; guint8 buf[MAX_BUF]; if (strcmp(p1, p2)) { gtk_label_set_text(GTK_LABEL(label_create_account_status), "The passwords you entered do not match!"); return; } else { gtk_label_set_text(GTK_LABEL(label_create_account_status), ""); SockList_Init(&sl, buf); SockList_AddString(&sl, "accountnew "); SockList_AddChar(&sl, strlen(name)); SockList_AddString(&sl, name); SockList_AddChar(&sl, strlen(p1)); SockList_AddString(&sl, p1); SockList_Send(&sl, csocket.fd); /* Store password away for new character creation */ snprintf(account_password, sizeof(account_password), "%s", p1); } } /** * User clicked on the create account button. In this case, we just process * the data and call do_account_create(); * @param button * @param user_data */ void on_button_new_create_account_clicked(GtkButton *button, gpointer user_data) { const char *password1, *password2, *name; password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password)); password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password)); name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name)); if (name && name[0] && password1 && password1[0] && password2 && password2[0]) { do_account_create(name, password1, password2); } else { gtk_label_set_text(GTK_LABEL(label_create_account_status), "You must fill in all three entries!"); } } /** * * @param button * @param user_data */ void on_button_new_cancel_clicked(GtkButton *button, gpointer user_data) { gtk_notebook_set_current_page(main_notebook, 1); } /** * This handles cases where the user hits return in one of the entry boxes. * We use the same callback for all 3 entry boxes, since the processing is * basically the same - if there is valid data in all of them, we try to * create an account - otherwise, we move to the next box. * * @param entry Entry box used to figure out what the next box is. * @param user_data Not used. */ void on_entry_new_account(GtkEntry *entry, gpointer user_data) { const char *password1, *password2, *name, *cp; password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password)); password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password)); name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name)); if (name && name[0] && password1 && password1[0] && password2 && password2[0]) { do_account_create(name, password1, password2); } else { /* In this case, one, or more, of the fields is blank. If there were * more than 3 widgets, I might but them into an array to make cycling * easier */ /* First case - if the currently active one is blank, no reason to * move onward. */ cp = gtk_entry_get_text(entry); if (!cp || !cp[0]) { return; } /* I'm not sure if it would make more sense to advance to the first * NULL entry - but in that case, the pointer may hop in non intuitive * ways - in this case, the user may just need to hit return a few * times - MSW 2010/03/29 */ if (entry == GTK_ENTRY(entry_new_account_name)) { gtk_widget_grab_focus(entry_new_account_password); } else if (entry == GTK_ENTRY(entry_new_account_password)) { gtk_widget_grab_focus(entry_new_confirm_password); } else if (entry == GTK_ENTRY(entry_new_confirm_password)) { gtk_widget_grab_focus(entry_new_account_name); } } } /** * This initializes the create account window and sets up the various * callbacks. */ static void init_create_account_window() { GtkTextIter end; button_new_create_account = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_create_account")); button_new_cancel = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_cancel")); login_pane[TEXTVIEW_RULES_ACCOUNT].textview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_account")); textbuf_rules_account = gtk_text_view_get_buffer( GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_ACCOUNT].textview)); entry_new_account_name = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_name")); entry_new_account_password = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_password")); entry_new_confirm_password = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_confirm_password")); label_create_account_status = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_create_account_status")); add_tags_to_textbuffer( &login_pane[TEXTVIEW_RULES_ACCOUNT], textbuf_rules_account); add_style_to_textbuffer(&login_pane[TEXTVIEW_RULES_ACCOUNT], NULL); gtk_text_buffer_get_end_iter( login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, &end); login_pane[TEXTVIEW_RULES_ACCOUNT].textmark = gtk_text_buffer_create_mark( login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, NULL, &end, FALSE); g_signal_connect((gpointer) button_new_create_account, "clicked", G_CALLBACK(on_button_new_create_account_clicked), NULL); g_signal_connect((gpointer) button_new_cancel, "clicked", G_CALLBACK(on_button_new_cancel_clicked), NULL); g_signal_connect((gpointer) entry_new_account_name, "activate", G_CALLBACK(on_entry_new_account), NULL); g_signal_connect((gpointer) entry_new_account_password, "activate", G_CALLBACK(on_entry_new_account), NULL); g_signal_connect((gpointer) entry_new_confirm_password, "activate", G_CALLBACK(on_entry_new_account), NULL); } /***************************************************************************** * login_window *****************************************************************************/ /** * Handles a failure from the server - pretty basic - just throw up the * message and let the user try again. * @param message */ void account_login_failure(char *message) { gtk_label_set_text(GTK_LABEL(label_account_login_status), message); } /** * User hit the create account button. So we need to hide the login window * and bring up the create login window. * @param button * @param user_data */ void on_button_create_account_clicked(GtkButton *button, gpointer user_data) { gtk_label_set_text(GTK_LABEL(label_create_account_status), ""); gtk_entry_set_text(GTK_ENTRY(entry_new_account_name), ""); gtk_entry_set_text(GTK_ENTRY(entry_new_account_password), ""); gtk_entry_set_text(GTK_ENTRY(entry_new_confirm_password), ""); gtk_notebook_set_current_page(main_notebook, 2); } /** * User hit the go to metaserver button. Need to disconnect from The server, * and by clearing the csocket_fd, the main loop routine will bring up the * metaserver window. * @param button * @param user_data */ void on_button_go_metaserver_clicked(GtkButton *button, gpointer user_data) { client_disconnect(); } /** * User hit the exit client button. Pretty simple in this case. * @param button * @param user_data */ void on_button_exit_client_clicked(GtkButton *button, gpointer user_data) { script_killall(); exit(0); } /** * This does the work of doing the login - mostly it just sends the request to * the server. However, this might be called from either hitting the login * button or entering data in name/password and hitting return. * @param name * @param password */ static void do_account_login(const char *name, const char *password) { SockList sl; guint8 buf[MAX_BUF]; if (!name || !password || *name == 0 || *password == 0) { gtk_label_set_text(GTK_LABEL(label_account_login_status), "You must enter both a name and password!"); } else { gtk_label_set_text(GTK_LABEL(label_account_login_status), ""); SockList_Init(&sl, buf); SockList_AddString(&sl, "accountlogin "); SockList_AddChar(&sl, strlen(name)); SockList_AddString(&sl, name); SockList_AddChar(&sl, strlen(password)); SockList_AddString(&sl, password); SockList_Send(&sl, csocket.fd); /* Store password away for new character creation */ snprintf(account_password, sizeof(account_password), "%s", password); } } /** * User hit the login button - just call do_account_login() * @param button * @param user_data */ void on_button_login_clicked(GtkButton *button, gpointer user_data) { do_account_login(gtk_entry_get_text(GTK_ENTRY(entry_account_name)), gtk_entry_get_text(GTK_ENTRY(entry_account_password))); } /** * User hit return in the name entry box. * @param entry * @param user_data */ void on_entry_account_name_activate(GtkEntry* entry, gpointer user_data) { gtk_widget_grab_focus(entry_account_password); } /** * Sets up all the widget pointers, as well as setting up the callbacks for * the login windows widgets. */ static void init_login_window() { GtkTextIter end; button_login = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_login")); button_create_account = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_account")); button_go_metaserver = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_go_metaserver")); label_account_login_status = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_login_status")); login_pane[TEXTVIEW_MOTD].textview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_motd")); textbuf_motd = gtk_text_view_get_buffer( GTK_TEXT_VIEW(login_pane[TEXTVIEW_MOTD].textview)); add_tags_to_textbuffer(&login_pane[TEXTVIEW_MOTD], textbuf_motd); add_style_to_textbuffer(&login_pane[TEXTVIEW_MOTD], NULL); gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_MOTD].textbuffer, &end); login_pane[TEXTVIEW_MOTD].textmark = gtk_text_buffer_create_mark( login_pane[TEXTVIEW_MOTD].textbuffer, NULL, &end, FALSE); login_pane[TEXTVIEW_NEWS].textview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_news")); textbuf_news = gtk_text_view_get_buffer( GTK_TEXT_VIEW(login_pane[TEXTVIEW_NEWS].textview)); add_tags_to_textbuffer(&login_pane[TEXTVIEW_NEWS], textbuf_news); add_style_to_textbuffer(&login_pane[TEXTVIEW_NEWS], NULL); gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_NEWS].textbuffer, &end); login_pane[TEXTVIEW_NEWS].textmark = gtk_text_buffer_create_mark( login_pane[TEXTVIEW_NEWS].textbuffer, NULL, &end, FALSE); entry_account_name = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_name")); entry_account_password = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password")); g_signal_connect((gpointer) entry_account_name, "activate", G_CALLBACK(on_entry_account_name_activate), NULL); // entry_account_password is the default action in GtkBuilder g_signal_connect((gpointer) button_login, "clicked", G_CALLBACK(on_button_login_clicked), NULL); g_signal_connect((gpointer) button_create_account, "clicked", G_CALLBACK(on_button_create_account_clicked), NULL); g_signal_connect((gpointer) button_go_metaserver, "clicked", G_CALLBACK(on_button_go_metaserver_clicked), NULL); } /***************************************************************************** * Account password change ****************************************************************************/ /** * This does sanity checking of the passed in data, and if all is good, sends * the request to the server to change an account password. If all the data isn't * good, it puts up an error message. In this routine, none of the entries * should be NULL - the caller should verify that before callin * do_account_change(); * * @param old Current password. * @param p1 First password - must not be NULL * @param p2 Second (confirmed) password. This routine checks that p1 & p2 * are the same, and if not, puts up an error. p2 must not be NULL */ static void do_account_change(const char *old, const char *p1, const char *p2) { SockList sl; guint8 buf[MAX_BUF]; if (strcmp(p1, p2)) { gtk_label_set_text(GTK_LABEL(label_account_password_status), "The passwords you entered do not match!"); return; } else { gtk_label_set_text(GTK_LABEL(label_account_password_status), ""); SockList_Init(&sl, buf); SockList_AddString(&sl, "accountpw "); SockList_AddChar(&sl, strlen(old)); SockList_AddString(&sl, old); SockList_AddChar(&sl, strlen(p1)); SockList_AddString(&sl, p1); SockList_Send(&sl, csocket.fd); /* Store password away for new character creation */ snprintf(account_password, sizeof(account_password), "%s", p1); } } /** * User has hit the cancel account password, so hide this window, show the * account main window. * @param button * @param user_data */ void on_button_account_password_cancel_clicked(GtkButton *button, gpointer user_data) { gtk_notebook_set_current_page(main_notebook, 3); } /** * User has hit the validate account password, so handle that. * @param button * @param user_data */ void on_button_account_password_confirm_clicked(GtkButton *button, gpointer user_data) { do_account_change(gtk_entry_get_text(GTK_ENTRY(entry_account_password_current)), gtk_entry_get_text(GTK_ENTRY(entry_account_password_new)), gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm))); } /** * This handles cases where the user hits return in one of the entry boxes. * We use the same callback for all 3 entry boxes, since the processing is * basically the same - if there is valid data in all of them, we try to * create an account - otherwise, we move to the next box. * * @param entry Entry box used to figure out what the next box is. * @param user_data Not used. */ void on_entry_account_password(GtkEntry *entry, gpointer user_data) { const char *old, *password1, *password2, *cp; old = gtk_entry_get_text(GTK_ENTRY(entry_account_password_current)); password1 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_new)); password2 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm)); if (old && old[0] && password1 && password1[0] && password2 && password2[0]) { do_account_change(old, password1, password2); } else { /* In this case, one, or more, of the fields is blank. If there were * more than 3 widgets, I might but them into an array to make cycling * easier */ /* First case - if the currently active one is blank, no reason to * move onward. */ cp = gtk_entry_get_text(entry); if (!cp || !cp[0]) { return; } if (entry == GTK_ENTRY(entry_account_password_current)) { gtk_widget_grab_focus(entry_account_password_new); } else if (entry == GTK_ENTRY(entry_account_password_new)) { gtk_widget_grab_focus(entry_account_password_confirm); } else if (entry == GTK_ENTRY(entry_account_password_confirm)) { gtk_widget_grab_focus(entry_account_password_current); } } } void account_change_password_failure(char *message) { gtk_label_set_text(GTK_LABEL(label_account_password_status), message); } /** * This initializes the change account password window and sets up the various * callbacks. */ static void init_account_password_window() { button_account_password_confirm = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_account_password_confirm")); button_account_password_cancel = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_account_password_cancel")); entry_account_password_current = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password_current")); entry_account_password_new = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password_new")); entry_account_password_confirm = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password_confirm")); label_account_password_status = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_password_status")); g_signal_connect((gpointer) button_account_password_confirm, "clicked", G_CALLBACK(on_button_account_password_confirm_clicked), NULL); g_signal_connect((gpointer) button_account_password_cancel, "clicked", G_CALLBACK(on_button_account_password_cancel_clicked), NULL); g_signal_connect((gpointer) entry_account_password_current, "activate", G_CALLBACK(on_entry_account_password), NULL); g_signal_connect((gpointer) entry_account_password_new, "activate", G_CALLBACK(on_entry_account_password), NULL); g_signal_connect((gpointer) entry_account_password_confirm, "activate", G_CALLBACK(on_entry_account_password), NULL); } /***************************************************************************** * Common/generic functions ****************************************************************************/ /** * This is called from ReplyInfoCmd when it gets a response from * news/motd/rules. It is very possible that the window will get displayed * before we got a reply response, so this tells the client to update it. * *@param type What data just got updated - text string of motd/news/rules */ void update_login_info(int type) { if (!has_init) { return; } /* In all cases, we clear the buffer, and if we have data, then set it to * that data. This routine could be smarter an */ if (type == INFO_NEWS) { gtk_text_buffer_set_text(textbuf_news, "", 0); if (news) { /* the format of the news entry is special - there are a series of * %entries, and they are in reverse older (newest last) we want * to get rid of the %, make them more visible (convert them to * bold) and reverse the order. */ char *mynews, *cp, *el, big_buf[BIG_BUF], *cp1; mynews = g_strdup(news); /* We basically work from the end of the string going towards the * start looking for % characters. If we find one, we have to * make sure it is at the start of the line or start of the buffer */ for (cp = mynews + strlen(mynews); cp > mynews; cp--) { if (*cp == '%' && (*(cp - 1) == '\n' || cp == mynews)) { /* Find the end of the line */ el = strchr(cp, '\n'); /* null out the newline, put el one char beyond it */ if (el) { *el = 0; el++; } /* There isn't a clear standard - % news may be valid, as * might be %news. If % news is used, it looks better to * get rid of that leading space. */ cp1 = cp + 1; while (isspace(*cp1)) { cp1++; } /* since we've null out the newline, this snprintf will * only get the % line and that is it. Mark it up */ snprintf(big_buf, BIG_BUF, "[b]%s[/b]", cp1); add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], big_buf, 0, 0, 0); /* Now we draw the text that goes with it, if it exists */ if (el) { add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], el, 0, 0, 0); } /* Now we wipe the % out. In this way, the news buffer is * shorter, so when it draws the ext, there will just be * that between the % and the one we just wiped out. */ *cp = 0; } } /* If there are remnants left over, or perhaps the news file isn't * formatted with % headers, display what we have got. */ if (*mynews != 0) { add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], mynews, 0, 0, 0); } } } else if (type == INFO_MOTD) { gtk_text_buffer_set_text(textbuf_motd, "", 0); if (motd) { add_marked_text_to_pane(&login_pane[TEXTVIEW_MOTD], motd, 0, 0, 0); } } else if (type == INFO_RULES) { gtk_text_buffer_set_text(textbuf_rules_account, "", 0); gtk_text_buffer_set_text(textbuf_rules_char, "", 0); if (rules) { add_marked_text_to_pane(&login_pane[TEXTVIEW_RULES_ACCOUNT], rules, 0, 0, 0); add_marked_text_to_pane(&login_pane[TEXTVIEW_RULES_CHAR], rules, 0, 0, 0); } } } /** * Starts the login process. If not already done, gets widgets, sets up * callboacks, etc. This is at the end of the file so all the callbacks are * defined before this function - in that way, we do not need forward * declarations. This is called from SetupCmd in common/commands.c * * @param method Login method that the server suppots. */ void start_login(int method) { /* Store this away - if method is only 1, we can not do smart character * creation. */ serverloginmethod = method; if (!has_init) { /* Since there are 4 windows associated with account and character * login, to make life a little easier, each section here does all the * work for one window, so it is easier to see that everything for a * window is done - don't need to hunt through what would otherwise be * a long routine looking for entries. */ init_login_window(); init_add_character_window(); init_choose_char_window(); init_create_account_window(); init_new_character_window(); init_account_password_window(); has_init = 1; /* In case we have gotten news/motd/rules before getting here, update * it now. */ update_login_info(INFO_NEWS); update_login_info(INFO_RULES); update_login_info(INFO_MOTD); } gtk_entry_set_text(GTK_ENTRY(entry_account_name), ""); gtk_entry_set_text(GTK_ENTRY(entry_account_password), ""); } void account_show_login() { gtk_notebook_set_current_page(main_notebook, 1); /* We set focus to account name - this makes the most sense if user is * logging in again - it is possible that the password is active, but both * fields are blank, which is not what is expected. */ gtk_widget_grab_focus(entry_account_name); gtk_widget_grab_default(button_login); } crossfire-client-1.75.3/gtk-v2/src/menubar.c000644 001751 001751 00000026363 14323707640 021460 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file gtk-v2/src/menubar.c * Sets up menu connections and implements core menu items in the top menubar. * * Quick notes on the menubar: * 1) Using the stock Quit menu item for some reason causes it to take several * seconds of 100% cpu utilization to show the menu. So I don't use the * stock item. */ #include "client.h" #include #ifdef WIN32 # include #endif #include "p_cmd.h" #include "main.h" #include "image.h" #include "gtk2proto.h" #include "script.h" /** * Client | Disconnect * Triggers the client to disconnect from the server. * * @param menuitem * @param user_data */ static void on_disconnect_activate(GtkMenuItem *menuitem, gpointer user_data) { if (client_is_connected()) { client_disconnect(); } } /** * File | Quit * Shuts down the client application. * * @param menuitem * @param user_data */ static void menu_quit_program(GtkMenuItem *menuitem, gpointer user_data) { script_killall(); LOG(LOG_INFO,"gtk-v2::client_exit","Exiting with return value 0."); exit(0); } /** * File | Quit Character * Causes the client to ask the server to delete the current character. * * @param menuitem * @param user_data */ static void menu_quit_character(GtkMenuItem *menuitem, gpointer user_data) { script_killall(); extended_command("quit"); } /** * Display client about dialog. */ static void menu_about(GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *about_window; about_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "about_window")); gtk_dialog_run(GTK_DIALOG(about_window)); gtk_widget_hide(about_window); } /** * Initialize menu bar items and connect their signals to their handlers. */ void init_menu_items() { GtkWidget *widget; widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "quit_character")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (menu_quit_character), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "quit")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (menu_quit_program), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "configure")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_configure_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "disconnect")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_disconnect_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "keybindings")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_keybindings_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "msgctrl")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_msgctrl_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "save_window_position")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_save_window_position_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "spells")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_spells_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "skills")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_skills_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "do_not_pickup")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_dont_pickup_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "stop_before_pickup")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_stop_before_pickup_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "body_armor")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_body_armor_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "boots")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_boots_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "cloaks")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_cloaks_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "gloves")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_gloves_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "helmets")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_helmets_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "shields")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_shields_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "skillscrolls")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_skillscrolls_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "normal_book_scrolls")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_normal_book_scrolls_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "spellbooks")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_spellbooks_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "drinks")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_drinks_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "food")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_food_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "flesh")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_flesh_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "keys")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_keys_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "magical_items")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_magical_items_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "potions")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_potions_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "valuables")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_valuables_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "wands_rods_horns")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_wands_rods_horns_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "jewels")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_jewels_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "containers")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_containers_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "all_weapons")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_all_weapons_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "missile_weapons")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_missile_weapons_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "bows")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_bows_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "arrows")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_arrows_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_pickup_off")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_pickup_off_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_5")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_5_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_10")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_10_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_15")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_15_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_20")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_20_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_25")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_25_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_30")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_35_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_35")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_35_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_40")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_40_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_45")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_45_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_50")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_ratio_50_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "not_cursed")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (on_menu_not_cursed_activate), NULL); widget = GTK_WIDGET(gtk_builder_get_object(window_xml, "about")); g_signal_connect ((gpointer) widget, "activate", G_CALLBACK (menu_about), NULL); } crossfire-client-1.75.3/gtk-v2/src/magicmap.c000644 001751 001751 00000005310 14226677555 021607 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Covers drawing the magic map. */ #include #include "client.h" #include "main.h" void draw_magic_map() { if (!cpl.magicmap) { // Do nothing if player has no magic map data. return; } else { cpl.showmagic = 1; } /* * Have to set this so that the gtk_widget_show below actually creates the * widget. Switch to this page when person actually casts magic map spell. */ gtk_notebook_set_current_page(GTK_NOTEBOOK(map_notebook), MAGIC_MAP_PAGE); GdkWindow *window = gtk_widget_get_window(magic_map); gdk_window_clear(window); cpl.mapxres = gdk_window_get_width(window) / cpl.mmapx; cpl.mapyres = gdk_window_get_height(window) / cpl.mmapy; if (cpl.mapxres < 1 || cpl.mapyres < 1) { LOG(LOG_WARNING, "draw_magic_map", "magic map resolution less than 1, map is %dx%d", cpl.mmapx, cpl.mmapy); return; } /* * In theory, cpl.mapxres and cpl.mapyres do not have to be the same. * However, it probably makes sense to keep them the same value. Need to * take the smaller value. */ if (cpl.mapxres > cpl.mapyres) { cpl.mapxres = cpl.mapyres; } else { cpl.mapyres = cpl.mapxres; } cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(window)); for (int y = 0; y < cpl.mmapy; y++) { for (int x = 0; x < cpl.mmapx; x++) { guint8 val = cpl.magicmap[y * cpl.mmapx + x]; gdk_cairo_set_source_color(cr, &root_color[val & FACE_COLOR_MASK]); cairo_rectangle(cr, cpl.mapxres * x, cpl.mapyres * y, cpl.mapxres, cpl.mapyres); cairo_fill(cr); } } cairo_destroy(cr); } /** * Flash the player's position on the magic map. */ void magic_map_flash_pos() { GdkWindow *window = gtk_widget_get_window(magic_map); cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(window)); gdk_cairo_set_source_color(cr, &root_color[(cpl.showmagic & 2) ? 0 : 1]); cairo_rectangle(cr, cpl.mapxres * cpl.pmapx, cpl.mapyres * cpl.pmapy, cpl.mapxres, cpl.mapyres); cairo_fill(cr); cairo_destroy(cr); } gboolean on_drawingarea_magic_map_expose_event() { draw_magic_map(); return FALSE; } crossfire-client-1.75.3/gtk-v2/src/png.c000644 001751 001751 00000036330 14045044337 020604 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Functions for manipulating graphics in the GTK-V2 client. */ #include "client.h" #include #include #include /* Defines for PNG return values */ /* These should be in a header file, but currently our calling functions * routines just check for nonzero return status and don't really care * why the load failed. */ #define PNGX_NOFILE 1 #define PNGX_OUTOFMEM 2 #define PNGX_DATA 3 static guint8 *data_cp; static int data_len, data_start; /** * * @param png_ptr * @param data * @param length */ static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { memcpy(data, data_cp + data_start, length); data_start += length; } guint8 *png_to_data(guint8 *data, int len, guint32 *width, guint32 *height) { guint8 *pixels = NULL; static png_bytepp rows = NULL; static guint32 rows_byte = 0; png_structp png_ptr; png_infop info_ptr; int bit_depth, color_type, interlace_type; data_len = len; data_cp = data; data_start = 0; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { return NULL; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } png_set_read_fn(png_ptr, NULL, user_read_data); png_read_info(png_ptr, info_ptr); /* * This seems to bug on at least one system (other than mine) * http://www.metalforge.net/cfmb/viewtopic.php?t=1085 * * I think its actually a bug in libpng. This function dies with an * error based on image width. However I've produced a work around * using the indivial functions. Repeated below. * png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)width, (png_unit_32*)height, &bit_depth, &color_type, &interlace_type, NULL, &filter_type); */ *width = png_get_image_width(png_ptr, info_ptr); *height = png_get_image_height(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); interlace_type = png_get_interlace_type(png_ptr, info_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) { /* Convert indexed images to RGB */ png_set_expand (png_ptr); } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { /* Convert grayscale to RGB */ png_set_expand (png_ptr); } else if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { /* If we have transparency header, convert it to alpha channel */ png_set_expand(png_ptr); } else if (bit_depth < 8) { /* If we have < 8 scale it up to 8 */ png_set_expand(png_ptr); /* Conceivably, png_set_packing() is a better idea; * God only knows how libpng works */ } /* If we are 16-bit, convert to 8-bit */ if (bit_depth == 16) { png_set_strip_16(png_ptr); } /* If gray scale, convert to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } /* If interlaced, handle that */ if (interlace_type != PNG_INTERLACE_NONE) { png_set_interlace_handling(png_ptr); } /* pad it to 4 bytes to make processing easier */ if (!(color_type & PNG_COLOR_MASK_ALPHA)) { png_set_filler(png_ptr, 255, PNG_FILLER_AFTER); } /* Update the info the reflect our transformations */ png_read_update_info(png_ptr, info_ptr); /* re-read due to transformations just made */ /* * See above for error description png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)width, (png_uint_32*)height, &bit_depth, &color_type, &interlace_type, NULL, &filter_type); */ *width = png_get_image_width(png_ptr, info_ptr); *height = png_get_image_height(png_ptr, info_ptr); pixels = (guint8*)g_malloc(*width **height * 4); if (!pixels) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); LOG(LOG_CRITICAL,"gtk-v2::png_to_data","Out of memory - exiting"); exit(1); } /* the png library needs the rows, but we will just return the raw data */ if (rows_byte == 0) { rows = (png_bytepp)g_malloc(sizeof(png_byte *) **height); rows_byte = *height; } else if (*height > rows_byte) { rows = (png_bytepp)g_realloc(rows, sizeof(png_byte *) **height); if (rows == NULL) { LOG(LOG_ERROR, "png_to_data", "Could not allocate memory: %s", strerror(errno)); exit(EXIT_FAILURE); } rows_byte = *height; } if (!rows) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); free(pixels); return NULL; } for (guint32 y = 0; y < *height; y++) { rows[y] = pixels + y * *width * 4; } png_read_image(png_ptr, rows); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return pixels; } /* RATIO is used to know what units scale is - in this case, a percentage, so * it is set to 100 */ #define RATIO 100 #define MAX_IMAGE_WIDTH 1024 #define MAX_IMAGE_HEIGHT 1024 #define BPP 4 /** * Takes png data and scales it accordingly. This function is based on * pnmscale, but has been modified to support alpha channel - instead of * blending the alpha channel, it takes the most opaque value - blending it is * not likely to give sane results IMO - for any image that has transparent * information, if we blended the alpha, the result would be the edges of that * region being partially transparent. * This function has also been re-written to use more static data - in the case * of the client, it will be called thousands of times, so it doesn't make * sense to free the data and then re-allocate it. * * For pixels that are fully transparent, the end result after scaling is they * will be tranparent black. This is a needed effect for blending to work * properly. * * This function returns a new pointer to the scaled image data. This is * g_malloc'd data, so should be freed at some point to prevent leaks. This * function does not modify the data passed to it - the caller is responsible * for freeing it if it is no longer needed. * * function arguments: * @param *data PNG data - this is any 4 byte per pixel data, in RGBA format. * @param *width Source width modified to contain the new image size. * @param *height Source height modified to contain the new image size. * @param scale Percentage size that new image should be. 100 is a same size * image - values larger than 100 will result in zoom, values less * than 100 will result in a shrinkage. */ guint8 *rescale_rgba_data(guint8 *data, int *width, int *height, int scale) { static int xrow[BPP * MAX_IMAGE_WIDTH], yrow[BPP*MAX_IMAGE_HEIGHT]; static guint8 *nrows[MAX_IMAGE_HEIGHT]; /* Figure out new height/width */ int new_width = *width * scale / RATIO, new_height = *height * scale / RATIO; int sourcerow=0, ytoleft, ytofill, xtoleft, xtofill, dest_column=0, source_column=0, needcol, destrow=0; int x,y; guint8 *ndata; guint8 r,g,b,a; if (*width > MAX_IMAGE_WIDTH || new_width > MAX_IMAGE_WIDTH || *height > MAX_IMAGE_HEIGHT || new_height > MAX_IMAGE_HEIGHT) { LOG(LOG_CRITICAL,"gtk-v2::rescale_rgba_data","Image too big"); exit(0); } /* clear old values these may have */ memset(yrow, 0, sizeof(int) **height * BPP); ndata = (guint8*)g_malloc(new_width * new_height * BPP); for (y=0; y 0 ) { yrow[x*BPP] += ytoleft * data[(sourcerow **width + x)*BPP]/RATIO; yrow[x*BPP+1] += ytoleft * data[(sourcerow **width + x)*BPP+1]/RATIO; yrow[x*BPP+2] += ytoleft * data[(sourcerow **width + x)*BPP+2]/RATIO; } /* Alpha is a bit special - we don't want to blend it - * we want to take whatever is the more opaque value. */ if (data[(sourcerow **width + x)*BPP+3] > yrow[x*BPP+3]) { yrow[x*BPP+3] = data[(sourcerow **width + x)*BPP+3]; } } ytofill -= ytoleft; ytoleft = scale; if (sourcerow < *height) { sourcerow++; } } for (x=0; x < *width; ++x) { if (data[(sourcerow **width + x)*BPP+3] > 0 ) { xrow[x*BPP] = yrow[x*BPP] + ytofill * data[(sourcerow **width + x)*BPP] / RATIO; xrow[x*BPP+1] = yrow[x*BPP+1] + ytofill * data[(sourcerow **width + x)*BPP+1] / RATIO; xrow[x*BPP+2] = yrow[x*BPP+2] + ytofill * data[(sourcerow **width + x)*BPP+2] / RATIO; } if (data[(sourcerow **width + x)*BPP+3] > xrow[x*BPP+3]) { xrow[x*BPP+3] = data[(sourcerow **width + x)*BPP+3]; } yrow[x*BPP]=0; yrow[x*BPP+1]=0; yrow[x*BPP+2]=0; yrow[x*BPP+3]=0; } ytoleft -= ytofill; if (ytoleft <= 0) { ytoleft = scale; if (sourcerow < *height) { sourcerow++; } } ytofill = RATIO; xtofill = RATIO; dest_column = 0; source_column=0; needcol=0; r=0; g=0; b=0; a=0; for (x=0; x< *width; x++) { xtoleft = scale; while (xtoleft >= xtofill) { if (needcol) { dest_column++; r=0; g=0; b=0; a=0; } if (xrow[source_column*BPP+3] > 0) { r += xtofill * xrow[source_column*BPP] / RATIO; g += xtofill * xrow[1+source_column*BPP] / RATIO; b += xtofill * xrow[2+source_column*BPP] / RATIO; } if (xrow[3+source_column*BPP] > a) { a = xrow[3+source_column*BPP]; } nrows[destrow][dest_column * BPP] = r; nrows[destrow][1+dest_column * BPP] = g; nrows[destrow][2+dest_column * BPP] = b; nrows[destrow][3+dest_column * BPP] = a; xtoleft -= xtofill; xtofill = RATIO; needcol=1; } if (xtoleft > 0 ) { if (needcol) { dest_column++; r=0; g=0; b=0; a=0; needcol=0; } if (xrow[3+source_column*BPP] > 0) { r += xtoleft * xrow[source_column*BPP] / RATIO; g += xtoleft * xrow[1+source_column*BPP] / RATIO; b += xtoleft * xrow[2+source_column*BPP] / RATIO; } if (xrow[3+source_column*BPP] > a) { a = xrow[3+source_column*BPP]; } xtofill -= xtoleft; } source_column++; } if (xtofill > 0 ) { source_column--; if (xrow[3+source_column*BPP] > 0) { r += xtofill * xrow[source_column*BPP] / RATIO; g += xtofill * xrow[1+source_column*BPP] / RATIO; b += xtofill * xrow[2+source_column*BPP] / RATIO; } if (xrow[3+source_column*BPP] > a) { a = xrow[3+source_column*BPP]; } } /* Not positve, but without the bound checking for dest_column, * we were overrunning the buffer. My guess is this only really * showed up if when the images are being scaled - there is probably * something like half a pixel left over. */ if (!needcol && (dest_column < new_width)) { nrows[destrow][dest_column * BPP] = r; nrows[destrow][1+dest_column * BPP] = g; nrows[destrow][2+dest_column * BPP] = b; nrows[destrow][3+dest_column * BPP] = a; } destrow++; } *width = new_width; *height = new_height; return ndata; } /** * Create a GdkPixbuf for the given RGBA data. */ GdkPixbuf *rgba_to_gdkpixbuf(guint8 *data, int width, int height) { /* Our data doesn't have correct stride values, so we can't just create it * from raw data using gdk_pixbuf_new_from_data(). */ GdkPixbuf *pix; pix = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); int rowstride = gdk_pixbuf_get_rowstride(pix); unsigned char *pixels = gdk_pixbuf_get_pixels(pix); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { unsigned char *p = pixels + y * rowstride + x * 4; p[0] = data[4*(x + y * width)]; p[1] = data[4*(x + y * width) + 1 ]; p[2] = data[4*(x + y * width) + 2 ]; p[3] = data[4*(x + y * width) + 3 ]; } } return pix; } /** * Create a Cairo surface for the given RGBA data. */ cairo_surface_t *rgba_to_cairo_surface(guint8 *data, int width, int height) { cairo_surface_t *surface; surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_surface_flush(surface); unsigned char *pixels = cairo_image_surface_get_data(surface); int stride = cairo_image_surface_get_stride(surface); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { guint32 *p = (guint32 *)(pixels + y * stride + x * 4); // Cairo format is native-endian ARGB, but our format is RGBA. guint32 a = data[4 * (x + y * width) + 3]; guint32 r = data[4 * (x + y * width) + 0] * a / 255; guint32 g = data[4 * (x + y * width) + 1] * a / 255; guint32 b = data[4 * (x + y * width) + 2] * a / 255; *p = a << (3 * 8) | r << (2 * 8) | g << (1 * 8) | b << (0 * 8); } } cairo_surface_mark_dirty(surface); return surface; } crossfire-client-1.75.3/gtk-v2/src/pickup.c000644 001751 001751 00000052650 14045044330 021307 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * This file covers the pickup menu items. We only implement the new pickup * code - it seems to me that it should be able to cover everything the old * pickup mode does. */ #include "client.h" #include #include "main.h" #include "image.h" #include "gtk2proto.h" typedef struct { GtkWidget *menuitem; guint32 pickup_mode; } PickupMapping; #define MAX_PICKUPS 50 PickupMapping pickup_mapping[MAX_PICKUPS]; static int num_pickups=0; /* * Definitions for detailed pickup descriptions. The objective is to define * intelligent groups of items that the user can pick up or leave as he likes. */ /* High bit as flag for new pickup options */ #define PU_NOTHING 0x00000000 #define PU_DEBUG 0x10000000 #define PU_INHIBIT 0x20000000 #define PU_STOP 0x40000000 #define PU_NEWMODE 0x80000000 #define PU_RATIO 0x0000000F #define PU_FOOD 0x00000010 #define PU_DRINK 0x00000020 #define PU_VALUABLES 0x00000040 #define PU_BOW 0x00000080 #define PU_ARROW 0x00000100 #define PU_HELMET 0x00000200 #define PU_SHIELD 0x00000400 #define PU_ARMOUR 0x00000800 #define PU_BOOTS 0x00001000 #define PU_GLOVES 0x00002000 #define PU_CLOAK 0x00004000 #define PU_KEY 0x00008000 #define PU_MISSILEWEAPON 0x00010000 #define PU_ALLWEAPON 0x00020000 #define PU_MAGICAL 0x00040000 #define PU_POTION 0x00080000 #define PU_SPELLBOOK 0x00100000 #define PU_SKILLSCROLL 0x00200000 #define PU_READABLES 0x00400000 #define PU_MAGIC_DEVICE 0x00800000 #define PU_NOT_CURSED 0x01000000 #define PU_JEWELS 0x02000000 #define PU_FLESH 0x04000000 #define PU_CONTAINERS 0x08000000 static unsigned int pmode=0, no_recurse=0; /** * Handles the pickup operations. Unfortunately, it isn't easy (possible?) * in layout to attach values to the menu items. * * @param on is TRUE if the button is activated, 0 if it is off. * @param val is the PU_ bitmasks to set/clear. */ static void new_menu_pickup(int on, int val) { char modestr[128]; if (no_recurse) { return; } if (on) { pmode |= val | PU_NEWMODE; } else { pmode &= ~val; } draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "To set this pickup mode to a key, use:"); snprintf(modestr, sizeof(modestr), "bind pickup %u",pmode); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, modestr); snprintf(modestr, sizeof(modestr), "pickup %u",pmode); send_command(modestr, -1, 0); } void on_menu_dont_pickup_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_INHIBIT); } void on_menu_stop_before_pickup_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_STOP); } /*************************************************************************** * armor pickup options **************************************************************************/ void on_menu_body_armor_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_ARMOUR); } void on_menu_boots_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_BOOTS); } void on_menu_cloaks_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_CLOAK); } void on_menu_gloves_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_GLOVES); } void on_menu_helmets_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_HELMET); } void on_menu_shields_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_SHIELD); } /*************************************************************************** * Books submenu ****************************************************************************/ void on_menu_skillscrolls_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_SKILLSCROLL); } void on_menu_normal_book_scrolls_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_READABLES); } void on_menu_spellbooks_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_SPELLBOOK); } /***************************************************************************/ void on_menu_drinks_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_DRINK); } void on_menu_food_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_FOOD); } void on_menu_keys_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_KEY); } void on_menu_magical_items_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_MAGICAL); } void on_menu_potions_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_POTION); } void on_menu_valuables_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_VALUABLES); } void on_menu_wands_rods_horns_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_MAGIC_DEVICE); } void on_menu_not_cursed_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_NOT_CURSED); } void on_menu_jewels_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_JEWELS); } void on_menu_containers_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_CONTAINERS); } void on_menu_flesh_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_FLESH); } /*************************************************************************** * Weapons submenu ***************************************************************************/ void on_menu_all_weapons_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_ALLWEAPON); } void on_menu_missile_weapons_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_MISSILEWEAPON); } void on_menu_bows_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_BOW); } void on_menu_arrows_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), PU_ARROW); } /*************************************************************************** * Weight/value submenu ***************************************************************************/ void on_menu_ratio_pickup_off_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 0); } void on_menu_ratio_5_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 1); } void on_menu_ratio_10_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 2); } void on_menu_ratio_15_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 3); } void on_menu_ratio_20_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 4); } void on_menu_ratio_25_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 5); } void on_menu_ratio_30_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 6); } void on_menu_ratio_35_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 7); } void on_menu_ratio_40_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 8); } void on_menu_ratio_45_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 9); } void on_menu_ratio_50_activate (GtkMenuItem *menuitem, gpointer user_data) { new_menu_pickup(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)), 10); } /** * Maps the menuitem lists into pickup values. In this way, client_pickup * knows what values to change. * * @param window_root */ void pickup_init(GtkWidget *window_root) { static int has_init=0; /* * There isn't really any harm doing this multiple times, but isn't any * point either. */ if (has_init) { return; } has_init=1; /* * The order here really doesn't make much difference. I suppose order * could either be in pickup modes (PU_...) or the list of items in the * menu tree. I chose the later, as easier to make sure all the items are * accounted for. * * In practice, with these values now set up, we could use a single * function to hande all the events from the menubar instead of the values * above - that function basically takes the structure that was clicked, * and finds the value in this array that corresponds to it. But that code * currently works fine and isn't really outdated, so isn't a big reason to * change it. */ pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "do_not_pickup")); pickup_mapping[num_pickups].pickup_mode = PU_INHIBIT; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "stop_before_pickup")); pickup_mapping[num_pickups].pickup_mode = PU_STOP; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "body_armor")); pickup_mapping[num_pickups].pickup_mode = PU_ARMOUR; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "boots")); pickup_mapping[num_pickups].pickup_mode = PU_BOOTS; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "cloaks")); pickup_mapping[num_pickups].pickup_mode = PU_CLOAK; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "gloves")); pickup_mapping[num_pickups].pickup_mode = PU_GLOVES; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "helmets")); pickup_mapping[num_pickups].pickup_mode = PU_HELMET; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "shields")); pickup_mapping[num_pickups].pickup_mode = PU_SHIELD; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "skillscrolls")); pickup_mapping[num_pickups].pickup_mode = PU_SKILLSCROLL; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "normal_book_scrolls")); pickup_mapping[num_pickups].pickup_mode = PU_READABLES; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "spellbooks")); pickup_mapping[num_pickups].pickup_mode = PU_SPELLBOOK; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "drinks")); pickup_mapping[num_pickups].pickup_mode = PU_DRINK; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "food")); pickup_mapping[num_pickups].pickup_mode = PU_FOOD; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "flesh")); pickup_mapping[num_pickups].pickup_mode = PU_FLESH; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "keys")); pickup_mapping[num_pickups].pickup_mode = PU_KEY; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "magical_items")); pickup_mapping[num_pickups].pickup_mode = PU_MAGICAL; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "potions")); pickup_mapping[num_pickups].pickup_mode = PU_POTION; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "valuables")); pickup_mapping[num_pickups].pickup_mode = PU_VALUABLES; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "wands_rods_horns")); pickup_mapping[num_pickups].pickup_mode = PU_MAGIC_DEVICE; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "jewels")); pickup_mapping[num_pickups].pickup_mode = PU_JEWELS; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "containers")); pickup_mapping[num_pickups].pickup_mode = PU_CONTAINERS; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "all_weapons")); pickup_mapping[num_pickups].pickup_mode = PU_ALLWEAPON; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "missile_weapons")); pickup_mapping[num_pickups].pickup_mode = PU_MISSILEWEAPON; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "bows")); pickup_mapping[num_pickups].pickup_mode = PU_BOW; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "arrows")); pickup_mapping[num_pickups].pickup_mode = PU_ARROW; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_pickup_off")); pickup_mapping[num_pickups].pickup_mode = ~PU_RATIO; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_5")); pickup_mapping[num_pickups].pickup_mode = 1; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_10")); pickup_mapping[num_pickups].pickup_mode = 2; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_15")); pickup_mapping[num_pickups].pickup_mode = 3; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_20")); pickup_mapping[num_pickups].pickup_mode = 4; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_25")); pickup_mapping[num_pickups].pickup_mode = 5; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_30")); pickup_mapping[num_pickups].pickup_mode = 6; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_35")); pickup_mapping[num_pickups].pickup_mode = 7; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_40")); pickup_mapping[num_pickups].pickup_mode = 8; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_45")); pickup_mapping[num_pickups].pickup_mode = 9; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "ratio_50")); pickup_mapping[num_pickups].pickup_mode = 10; num_pickups++; pickup_mapping[num_pickups].menuitem = GTK_WIDGET(gtk_builder_get_object(window_xml, "not_cursed")); pickup_mapping[num_pickups].pickup_mode = PU_NOT_CURSED; num_pickups++; /* * Do some bounds checking. We could actually set this exactly right, * since additional menu entries are not likely to be added often. We exit * because if we overrun that structure, we've screwed up memory and will * likely crash or otherwise have odd behaviour. */ if (num_pickups>=MAX_PICKUPS) { LOG(LOG_ERROR, "pickup.c::pickup_init", "num_pickups (%d) >= MAX_PICKUPS (%d)\n", num_pickups, MAX_PICKUPS); exit(1); } } /** * We get pickup information from server, update our status. */ void client_pickup(guint32 pickup) { int i; /* * no_recurse is used to limit callbacks - otherwise what happens is when * we call set_active below, it emits the appropriate signal, which results * in new_menu_pickup() getting called, which then sends a new pickup * command to the server, which then results in server sending data to * client, etc. */ no_recurse=1; pmode=pickup; for (i=0; i < num_pickups; i++) { if ((pickup & ~PU_RATIO) & pickup_mapping[i].pickup_mode || (pickup & PU_RATIO) == pickup_mapping[i].pickup_mode) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pickup_mapping[i].menuitem), 1); } else { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pickup_mapping[i].menuitem), 0); } } no_recurse=0; } crossfire-client-1.75.3/gtk-v2/src/image.c000644 001751 001751 00000030113 14457055163 021101 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Contains highlevel image related functions and mostly deals with the image * caching, processing the image commands from the server, etc. It is * gtk-specific as it returns gtk pixmaps. */ #include "client.h" #include #include "image.h" #include "main.h" #include "gtk2proto.h" extern GtkWidget *window_root; /**< In main.c */ int image_size=DEFAULT_IMAGE_SIZE; #define BPP 4 PixmapInfo *pixmaps[MAXPIXMAPNUM]; /* Do we have new images to display? */ int have_new_image=0; /* * this is used to rescale big images that will be drawn in the inventory/look * lists. What the code further below basically does is figure out how big the * object is (in squares), and this looks at the icon_rescale_factor to figure * what scale factor it gives. Not that the icon_rescale_factor values are * passed directly to the rescale routines. These represent percentages - so * even taking into account that the values diminish as the table grows, they * will still appear larger if the location in the table times the factor is * greater than 100. We find the largest dimension that the image has. The * values in the comment is the effective scaling compared to the base image * size that this big image will appear as. Using a table makes it easier to * adjust the values so things look right. */ #define MAX_ICON_SPACES 10 static const int icon_rescale_factor[MAX_ICON_SPACES] = { 100, 100, 80 /* 2 = 160 */, 60 /* 3 = 180 */, 50 /* 4 = 200 */, 45 /* 5 = 225 */, 40 /* 6 = 240 */, 35 /* 7 = 259 */, 35 /* 8 = 280 */, 33 /* 9 = 300 */ }; /****************************************************************************** * * Code related to face caching. * *****************************************************************************/ /* Does not appear to be used anywhere typedef struct Keys { uint8 flags; sint8 direction; KeySym keysym; char *command; struct Keys *next; } Key_Entry; */ /* Rotate right from bsd sum. */ #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x80000000; else (c) >>= 1; /*#define CHECKSUM_DEBUG*/ /** * Helper function to make the code more readable */ static void create_icon_image(guint8 *data, PixmapInfo *pi) { pi->icon_image = rgba_to_gdkpixbuf(data, pi->icon_width, pi->icon_height); } static void create_full_icon_image(guint8 *data, PixmapInfo *pi) { pi->full_icon_image = rgba_to_gdkpixbuf(data, pi->full_icon_width, pi->full_icon_height); } /** * Helper function to make the code more readable * * @param data * @param pi */ static void create_map_image(guint8 *data, PixmapInfo *pi) { pi->map_image = rgba_to_cairo_surface(data, pi->full_icon_width, pi->full_icon_height); } /** * Wrapper for accessing outside this file. */ void do_new_image(guint8 *data, PixmapInfo *pi) { create_icon_image(data, pi); create_full_icon_image(data, pi); create_map_image(data, pi); } /** * Memory management. * * @param pi */ static void free_pixmap(PixmapInfo *pi) { if (pi->icon_image) { g_object_unref(pi->icon_image); } if (pi->full_icon_image) { g_object_unref(pi->full_icon_image); } if (pi->map_image) { cairo_surface_destroy(pi->map_image); } } /** * Takes the pixmap to put the data into, as well as the rgba data (ie, already * loaded with png_to_data). Scales and stores the relevant data into the * pixmap structure. * * @param ce can be NULL * @param pixmap_num * @param rgba_data * @param width * @param height * * @return 1 on failure. */ int create_and_rescale_image_from_data(Cache_Entry *ce, int pixmap_num, guint8 *rgba_data, int width, int height) { int nx, ny, iscale, factor; PixmapInfo *pi; if (pixmap_num <= 0 || pixmap_num >= MAXPIXMAPNUM) { return 1; } if (pixmaps[pixmap_num] != pixmaps[0]) { /* As per bug 2938906, one can see image corruption when switching between * servers. The cause is that the cache table stores away * a pointer to the pixmap[] entry - if we go and free it, * the cache table can point to garbage, so don't free it. * This causes some memory leak, but if/when there is good * cache support for multiple servers, eventually the amount * of memory consumed will reach a limit (it has every image of * every server in memory * * The cause of image corruption requires a few different things: * 1) images of the same name have different numbers on the 2 serves. * 2) the image number is higher on the first than second server * 3) the image using the high number does not exist/is different * on the second server, causing this routine to be called. */ if (!use_config[CONFIG_CACHE]) { free_pixmap(pixmaps[pixmap_num]); free(pixmaps[pixmap_num]); } pixmaps[pixmap_num] = pixmaps[0]; } pi = calloc(1, sizeof(PixmapInfo)); iscale = use_config[CONFIG_ICONSCALE]; /* * If the image is big, figure out what we should scale it to so it fits * better display */ if (width > DEFAULT_IMAGE_SIZE || height>DEFAULT_IMAGE_SIZE) { int ts = 100; factor = width / DEFAULT_IMAGE_SIZE; if (factor >= MAX_ICON_SPACES) { factor = MAX_ICON_SPACES - 1; } if (icon_rescale_factor[factor] < ts) { ts = icon_rescale_factor[factor]; } factor = height / DEFAULT_IMAGE_SIZE; if (factor >= MAX_ICON_SPACES) { factor = MAX_ICON_SPACES - 1; } if (icon_rescale_factor[factor] < ts) { ts = icon_rescale_factor[factor]; } iscale = ts * use_config[CONFIG_ICONSCALE] / 100; } /* In all cases, the icon images are in native form. */ pi->full_icon_width = width; pi->full_icon_height = height; create_full_icon_image(rgba_data, pi); if (iscale != 100) { nx=width; ny=height; guint8 *png_tmp = rescale_rgba_data(rgba_data, &nx, &ny, iscale); pi->icon_width = nx; pi->icon_height = ny; create_icon_image(png_tmp, pi); free(png_tmp); } else { pi->icon_width = width; pi->icon_height = height; create_icon_image(rgba_data, pi); } create_map_image(rgba_data, pi); /* * Not ideal, but if it is missing the map or icon image, presume something * failed. However, opengl doesn't set the map_image, so if using that * display mode, don't make this check. */ if (!pi->icon_image || (!pi->map_image && use_config[CONFIG_DISPLAYMODE]!=CFG_DM_OPENGL)) { free_pixmap(pi); free(pi); return 1; } if (ce) { ce->image_data = pi; } pixmaps[pixmap_num] = pi; if (use_config[CONFIG_CACHE]) { have_new_image++; } return 0; } /** * Referenced from common/commands.c * * @param face * @param smooth_face */ void addsmooth(guint16 face, guint16 smooth_face) { pixmaps[face]->smooth_face = smooth_face; } /** * This functions associates image_data in the cache entry with the specific * pixmap number. Currently, there is no failure condition, but there is the * potential that in the future, we want to more closely look at the data and * if it isn't valid, return the failure code. * * @return 0 on success, -1 on failure. */ int associate_cache_entry(Cache_Entry *ce, int pixnum) { pixmaps[pixnum] = ce->image_data; return 0; } /** * Connecting to different servers, try to clear out any old images. Try to * free the data to prevent memory leaks. This could be more clever, ie, if * we're caching images and go to a new server and get a name, we should try to * re-arrange our cache or the like. */ void reset_image_data(void) { int i; reset_image_cache_data(); /* * The entries in the pixmaps array are also tracked in the image cache in * the common area. We will try to recycle those images that we can. * Thus, if we connect to a new server, we can just re-use the images we * have already rendered. */ for (i=1; i= MAXPIXMAPNUM) { *w = 1; *h = 1; } else { // Try to make this not jank out so much. // unscaled image dimension / tile size should be more sensible and less prone to breakage. *w = pixmaps[face]->full_icon_width / map_image_size; *h = pixmaps[face]->full_icon_height / map_image_size; } } /****************************************************************************** * * Code related to face caching. * *****************************************************************************/ /** * Initializes the data for image caching * Create question mark to display in each supported rendering mode when an * image is not cached. When image caching is enabled, if a needed image is * not yet in the cache, a question mark image is displayed instead. The * image displayed is unique to the display mode. This function creates * the image to use when OpenGL mode is in effect. * */ void init_image_cache_data(void) { #include "../../pixmaps/question.xpm" pixmaps[0] = g_new(PixmapInfo, 1); pixmaps[0]->icon_image = gdk_pixbuf_new_from_xpm_data((const gchar **)question_xpm); pixmaps[0]->full_icon_image = gdk_pixbuf_new_from_xpm_data((const gchar **)question_xpm); pixmaps[0]->map_image = pixmaps[0]->icon_image; pixmaps[0]->icon_width = pixmaps[0]->icon_height = pixmaps[0]->full_icon_width = pixmaps[0]->full_icon_height = map_image_size; pixmaps[0]->smooth_face = 0; /* Initialize all the images to be of the same value. */ for (int i = 1; i < MAXPIXMAPNUM; i++) { pixmaps[i] = pixmaps[0]; } init_common_cache_data(); } crossfire-client-1.75.3/gtk-v2/src/snd.vala000644 001751 001751 00000002201 14323707640 021275 0ustar00kevinzkevinz000000 000000 public struct SoundInfo { string file; uint vol; } /** * Load sound configuration file into a hash table of sound info structs. */ public HashTable? load_snd_config() { unowned string snd_dir = GLib.Environment.get_variable("CF_SOUND_DIR"); var snd_config = @"$snd_dir/sounds.conf"; string contents; try { FileUtils.get_contents(snd_config, out contents); } catch (FileError e) { stderr.printf("Could not read '%s'\n", snd_config); return null; } var sounds = new HashTable (str_hash, str_equal); var lines = contents.split("\n"); foreach (var line in lines) { // In Windows, it there can be a \r before the \n. pull that out too. line = line.chomp(); if (line[0] == '#' || line.length == 0) { continue; } var entries = line.split(":"); if (entries.length != 3) { stderr.printf("Parse error in sound configuration: '%s'\n", line); continue; } SoundInfo si = {entries[2], int.parse(entries[1])}; sounds.insert(entries[0], si); } return sounds; } crossfire-client-1.75.3/gtk-v2/src/CMakeLists.txt000644 001751 001751 00000002547 14323707640 022421 0ustar00kevinzkevinz000000 000000 vala_precompile(VALA_C snd.vala OPTIONS -g GENERATE_HEADER client-vala) add_custom_command( OUTPUT resources.c COMMAND ${GLIB_COMPILE_RESOURCES} --generate-source --target ${CMAKE_CURRENT_BINARY_DIR}/resources.c --sourcedir=${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/resources.xml ) add_executable(crossfire-client-gtk2 ${VALA_C} account.c config.c create_char.c gtk2proto.h image.c image.h info.c info.h inventory.c keys.c magicmap.c main.c main.h map.c menubar.c metaserver.c pickup.c png.c skills.c sound.c spells.c stats.c sound.h cfsndserv.c resources.c ) target_include_directories(crossfire-client-gtk2 PRIVATE ${PROJECT_BINARY_DIR} ${PROJECT_BINARY_DIR}/common ${PROJECT_SOURCE_DIR}/common ${GTK_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${SDLMIXER_INCLUDE_DIRS} ${SDL_INCLUDE_DIR} ) target_link_libraries(crossfire-client-gtk2 cfclient ${CURL_LDFLAGS} ${GTK_LDFLAGS} ${LUA_LIBRARIES} ${PNG_LIBRARIES} ${SDL_LDFLAGS} ${SDLMIXER_LDFLAGS} ${X11_LIBRARIES} m # math ) if(MINGW OR WIN32) target_link_libraries(crossfire-client-gtk2 wsock32) endif() install(TARGETS crossfire-client-gtk2 DESTINATION ${CMAKE_INSTALL_BINDIR}) crossfire-client-1.75.3/gtk-v2/src/info.h000644 001751 001751 00000004035 14045044275 020756 0ustar00kevinzkevinz000000 000000 /* * char *rcsid_gtk2_info_h = * "$Id$"; */ /* Crossfire client, a client program for the crossfire program. Copyright (C) 2010 Mark Wedel & Crossfire Development Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author can be reached via e-mail to crossfire@metalforge.org */ #ifndef INFO_H #define INFO_H /** * @file info.h * This file is really here to declare the Info_Pane structure. * the account based login code also uses info panes, so it * needs to be declared in a place where both files can access it. */ #include "shared/newclient.h" /** * @{ * @name GTK V2 Font Style Definitions. * Font style support definitions for the info window. * Font style defines are indices into the font_style_names[] array. * The actual fonts that they are bound to are set up in the style file. */ #define FONT_NORMAL 0 #define FONT_ARCANE 1 #define FONT_STRANGE 2 #define FONT_FIXED 3 #define FONT_HAND 4 #define NUM_FONTS 5 typedef struct Info_Pane { GtkWidget *textview; GtkWidget *scrolled_window; GtkTextBuffer *textbuffer; GtkTextMark *textmark; GtkAdjustment *adjustment; GtkTextTag *color_tags[NUM_COLORS]; GtkTextTag *font_tags[NUM_FONTS]; GtkTextTag *bold_tag, *italic_tag, *underline_tag, *default_tag; GtkTextTag **msg_type_tags[MSG_TYPE_LAST]; } Info_Pane; #endif crossfire-client-1.75.3/gtk-v2/src/sound.c000644 001751 001751 00000007421 14110265004 021134 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * This file contains the sound support for the GTK V2 client. It does not * actually play sounds, but rather tries to run cfsndserve, which is * responsible for playing sounds. */ #include "client.h" #include "sound.h" #include "client-vala.h" int init_sounds() { return cf_snd_init() == 0; } /** * Parse the data contained by a sound2 command coming from the server and * handle playing the specified sound. See server doc/Developers/sound for * details. * * @param data Data provided following the sound2 command from the server. * @param len Length of the sound2 command data. */ void Sound2Cmd(unsigned char *data, int len) { gint8 x, y; guint8 dir, vol, type, len_sound, len_source; char *sound = NULL; char *source = NULL; /** * Format of the sound2 command recieved in data: * *
     * sound2 {x}{y}{dir}{volume}{type}{len_sound}{sound}{len_source}{source}
     *         b  b  b    b       b     b          str    b           str
     * 
*/ if (len < 8) { LOG(LOG_WARNING, "gtk-v2::Sound2Cmd", "Sound command too short: %d\n bytes", len); return; } x = data[0]; y = data[1]; dir = data[2]; vol = data[3]; type = data[4]; len_sound = data[5]; /* * The minimum size of data is 1 for each byte in the command (7) plus the * size of the sound string. If we do not have that, the data is bogus. */ if (6 + len_sound + 1 > len) { LOG(LOG_WARNING, "gtk-v2::Sound2Cmd", "sound length check: %i len: %i\n", len_sound, len); return; } len_source = data[6 + len_sound]; if (len_sound != 0) { sound = (char *) data + 6; data[6 + len_sound] = '\0'; } /* * The minimum size of data is 1 for each byte in the command (7) plus the * size of the sound string, and the size of the source string. */ if (6 + len_sound + 1 + len_source > len) { LOG(LOG_WARNING, "gtk-v2::Sound2Cmd", "source length check: %i len: %i\n", len_source, len); return; } /* * Though it looks like there is potential for writing a null off the end * of the buffer, there is always room for a null (see do_client()). */ if (len_source != 0) { source = (char *) data + 6 + len_sound + 1; data[6 + len_sound + 1 + len_source] = '\0'; } if (use_config[CONFIG_SOUND]) { cf_play_sound(x, y, dir, vol, type, sound, source); } } /** * Parse the data contained by a music command coming from the server and * pass the name along to cfsndserv as a quoted string. * * @param data Data provided following the music command from the server * that hints what kind of music should play. NONE is an * indication that music should stop playing. * @param len Length of the string describing the music to play. */ void MusicCmd(const char *data, int len) { /** * Format of the music command received in data: * *
     * music {string}
     * 
*/ // Check for null terminator. if (data[len]) { LOG(LOG_ERROR, "gtk-v2::MusicCmd", "Music command string is not null-terminated."); return; } if (use_config[CONFIG_SOUND]) { cf_play_music(data); } } crossfire-client-1.75.3/gtk-v2/src/gtk2proto.h000644 001751 001751 00000034444 14323707640 021766 0ustar00kevinzkevinz000000 000000 /* account.c */ extern void hide_all_login_windows(void); extern gboolean on_window_delete_event(GtkWidget *window, gpointer *user_data); extern void create_new_character_failure(char *message); extern void on_button_create_new_char_clicked(GtkButton *button, gpointer user_data); extern void on_entry_new_character_name(GtkEntry *entry, gpointer user_data); extern void on_button_new_char_cancel_clicked(GtkButton *button, gpointer user_data); extern void account_add_character_failure(char *message); extern void on_button_do_add_character_clicked(GtkButton *button, gpointer user_data); extern void on_button_return_character_select_clicked(GtkButton *button, gpointer user_data); extern void on_kb_scope_togglebutton_character_toggled(GtkToggleButton *toggle_button, gpointer user_data); extern void on_kb_scope_togglebutton_global_toggled(GtkToggleButton *toggle_button, gpointer user_data); extern void on_entry_character(GtkEntry *entry, gpointer user_data); extern void choose_character_init(void); extern void on_button_play_character_clicked(GtkButton *button, gpointer user_data); extern void on_button_create_character_clicked(GtkButton *button, gpointer user_data); extern void on_button_add_character_clicked(GtkButton *button, gpointer user_data); extern void on_button_return_login_clicked(GtkButton *button, gpointer user_data); extern void update_character_choose(const char *name, const char *class, const char *race, const char *face, const char *party, const char *map, int level, int faceno); extern void on_treeview_choose_character_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data); extern void account_creation_failure(char *message); extern void on_button_new_create_account_clicked(GtkButton *button, gpointer user_data); extern void on_button_new_cancel_clicked(GtkButton *button, gpointer user_data); extern void on_entry_new_account(GtkEntry *entry, gpointer user_data); extern void account_login_failure(char *message); extern void on_button_create_account_clicked(GtkButton *button, gpointer user_data); extern void on_button_go_metaserver_clicked(GtkButton *button, gpointer user_data); extern void on_button_exit_client_clicked(GtkButton *button, gpointer user_data); extern void on_button_login_clicked(GtkButton *button, gpointer user_data); extern void on_entry_account_name_activate(GtkEntry *entry, gpointer user_data); extern void on_entry_account_password_activate(GtkEntry *entry, gpointer user_data); extern void update_login_info(int type); extern void start_login(int method); extern void choose_char_window_show(); extern void account_show_login(void); /* config.c */ extern void load_theme(int reload); extern void config_check(); extern void config_load(void); extern void save_defaults(void); extern void config_init(GtkWidget *window_root); extern void on_configure_activate(GtkWidget *menuitem, gpointer user_data); extern void save_winpos(void); extern void on_save_window_position_activate(GtkMenuItem *menuitem, gpointer user_data); extern void load_window_positions(GtkWidget *window_root); extern void init_theme(); /* create_char.c */ extern void create_character_window_show(); extern void create_character_window_hide(); extern void init_create_character_window(); /* image.c */ extern int create_and_rescale_image_from_data(Cache_Entry *ce, int pixmap_num, guint8 *rgba_data, int width, int height); extern void addsmooth(guint16 face, guint16 smooth_face); extern int associate_cache_entry(Cache_Entry *ce, int pixnum); extern void reset_image_data(void); extern void image_update_download_status(int start, int end, int total); extern void get_map_image_size(int face, guint8 *w, guint8 *h); extern void init_image_cache_data(void); extern void do_new_image(guint8 *data, PixmapInfo *pi); /* info.c */ extern void set_text_tag_from_style(GtkTextTag *tag, GtkStyle *style, const GtkStyle * const base_style); extern void add_tags_to_textbuffer(Info_Pane *pane, GtkTextBuffer *textbuf); extern void add_style_to_textbuffer(Info_Pane *pane, GtkStyle *base_style); extern void info_get_styles(void); extern void info_init(GtkWidget *window_root); extern void add_marked_text_to_pane(Info_Pane *pane, const char *message, int type, int subtype, int orig_color); extern void draw_ext_info(int orig_color, int type, int subtype, const char *message); extern void info_buffer_init(void); extern void info_buffer_flush(const int id); extern void info_buffer_tick(void); extern void menu_clear(void); extern void msgctrl_init(GtkWidget *window_root); extern void update_msgctrl_configuration(void); extern void save_msgctrl_configuration(void); extern void load_msgctrl_configuration(void); extern void default_msgctrl_configuration(void); extern void read_msgctrl_configuration(void); extern void on_msgctrl_button_save_clicked(GtkButton *button, gpointer user_data); extern void on_msgctrl_button_load_clicked(GtkButton *button, gpointer user_data); extern void on_msgctrl_button_defaults_clicked(GtkButton *button, gpointer user_data); extern void on_msgctrl_button_apply_clicked(GtkButton *button, gpointer user_data); extern void on_msgctrl_button_close_clicked(GtkButton *button, gpointer user_data); extern void on_msgctrl_activate(GtkMenuItem *menuitem, gpointer user_data); /* inventory.c */ extern void inventory_get_styles(void); extern void inventory_init(GtkWidget *window_root); extern void close_container(item *op); extern void open_container(item *op); extern void command_show(const char *params); extern void set_weight_limit(guint32 wlim); extern void item_event_item_deleting(item *it); extern void item_event_container_clearing(item *container); extern void item_event_item_changed(item *it); extern void draw_look_list(void); extern void draw_lists(void); extern void inventory_tick(void); /* keys.c */ extern void keybindings_init(const char *character_name); extern void keys_init(GtkWidget *window_root); extern void bind_key(char *params); extern void unbind_key(const char *params); extern void focusoutfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window); extern void keyrelfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window); extern void keyfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window); extern void x_set_echo(void); extern void draw_prompt(const char *str); extern void gtk_command_history(int direction); extern void gtk_complete_command(void); extern void on_entry_commands_activate(GtkEntry *entry, gpointer user_data); extern void update_keybinding_list(void); extern void on_keybindings_activate(GtkMenuItem *menuitem, gpointer user_data); extern gboolean on_keybinding_entry_key_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data); extern void on_keybinding_button_remove_clicked(GtkButton *button, gpointer user_data); extern void on_keybinding_button_bind_clicked(GtkButton *button, gpointer user_data); extern void on_keybinding_button_update_clicked(GtkButton *button, gpointer user_data); extern void on_keybinding_button_close_clicked(GtkButton *button, gpointer user_data); extern void on_keybinding_checkbutton_any_clicked(GtkCheckButton *cb, gpointer user_data); extern gboolean keybinding_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata); extern void reset_keybinding_status(void); extern void on_keybinding_button_clear_clicked(GtkButton *button, gpointer user_data); /* main.c */ extern void client_tick(guint32 tick); extern void on_window_destroy_event(GtkWidget *object, gpointer user_data); extern void error_dialog(char *description, char *information); extern void my_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data); extern int main(int argc, char *argv[]); extern void get_window_coord(GtkWidget *win, int *x, int *y, int *wx, int *wy, int *w, int *h); extern void show_main_client(void); /* map.c */ extern void map_check_resize(void); extern void map_init(GtkWidget *window_root); extern int display_mapscroll(int dx, int dy); extern void resize_map_window(int x, int y); extern void draw_map(void); extern void display_map_doneupdate(int redraw, int notice); /* magicmap.c */ extern void draw_magic_map(void); extern void magic_map_flash_pos(void); extern gboolean on_drawingarea_magic_map_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data); /* menubar.c */ extern void init_menu_items(); /* metaserver.c */ extern void metaserver_ui_init(); extern void metaserver_show_prompt(void); extern void on_metaserver_select_clicked(GtkButton *button, gpointer user_data); extern void on_button_metaserver_quit_pressed(GtkButton *button, gpointer user_data); /* opengl.c */ extern void init_glx_opengl(GtkWidget *drawingarea); extern void init_opengl(GtkWidget *drawingarea); extern void opengl_gen_map(int redraw); extern void create_opengl_map_image(guint8 *data, PixmapInfo *pi); extern void opengl_free_pixmap(PixmapInfo *pi); extern void create_opengl_question_mark(void); /* pickup.c */ extern void on_menu_dont_pickup_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_stop_before_pickup_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_body_armor_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_boots_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_cloaks_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_gloves_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_helmets_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_shields_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_skillscrolls_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_normal_book_scrolls_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_spellbooks_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_drinks_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_food_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_keys_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_magical_items_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_potions_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_valuables_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_wands_rods_horns_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_not_cursed_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_jewels_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_containers_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_flesh_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_all_weapons_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_missile_weapons_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_bows_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_arrows_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_pickup_off_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_5_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_10_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_15_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_20_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_25_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_30_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_35_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_40_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_45_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_menu_ratio_50_activate(GtkMenuItem *menuitem, gpointer user_data); extern void pickup_init(GtkWidget *window_root); extern void client_pickup(guint32 pickup); /* png.c */ extern guint8 *png_to_data(guint8 *data, int len, guint32 *width, guint32 *height); extern guint8 *rescale_rgba_data(guint8 *data, int *width, int *height, int scale); extern GdkPixbuf *rgba_to_gdkpixbuf(guint8 *data, int width, int height); extern cairo_surface_t *rgba_to_cairo_surface(guint8 *data, int width, int height); /* sdl.c */ extern void drawquarterlightmap_sdl(int tl, int tr, int bl, int br, int width, int height, int startx, int starty, int endx, int endy, int destx, int desty); extern void sdl_gen_map(int redraw); extern int sdl_mapscroll(int dx, int dy); /* skills.c */ extern void update_skill_information(void); extern void on_skills_activate(GtkMenuItem *menuitem, gpointer user_data); extern void trigger_skill(GtkTreeIter iter, GtkTreeModel *model, int use_skill); extern void on_skill_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data); extern void on_skill_ready_clicked(GtkButton *button, gpointer user_data); extern void on_skill_use_clicked(GtkButton *button, gpointer user_data); extern void on_skill_close_clicked(GtkButton *button, gpointer user_data); /* sound.c */ extern int init_sounds(void); extern void play_sound_effect(gint8 x, gint8 y, guint8 dir, guint8 vol, guint8 type, const char *sound, const char *source); extern void Sound2Cmd(unsigned char *data, int len); extern void MusicCmd(const char *data, int len); /* spells.c */ extern void spell_get_styles(void); extern void on_spell_window_size_allocate(GtkWidget *widget, gpointer user_data); extern void update_spell_information(void); extern void on_spells_activate(GtkMenuItem *menuitem, gpointer user_data); extern void on_spell_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data); extern void on_spell_cast_clicked(GtkButton *button, gpointer user_data); extern void on_spell_invoke_clicked(GtkButton *button, gpointer user_data); extern void on_spell_close_clicked(GtkButton *button, gpointer user_data); /* stats.c */ extern void stats_get_styles(void); extern void stats_init(GtkWidget *window_root); extern void update_stat(int stat_no, gint64 max_stat, gint64 current_stat, gint64 statbar_max, gint64 statbar_stat, int can_alert); extern void draw_message_window(int redraw); extern void draw_stats(int redraw); extern void clear_stat_mapping(void); crossfire-client-1.75.3/gtk-v2/src/spells.c000644 001751 001751 00000053107 14323707640 021325 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Handles spell related functionality. */ #include "client.h" #include #include #include "image.h" #include "metaserver.h" #include "main.h" #include "gtk2proto.h" enum Styles { Style_Attuned, Style_Repelled, Style_Denied, Style_Normal, Style_Last }; static GtkListStore *spell_store; static GtkTreeSelection *spell_selection; static GtkWidget *spell_window, *spell_invoke, *spell_cast, *spell_options, *spell_treeview, *spell_label[Style_Last], *spell_eventbox[Style_Last]; enum { LIST_IMAGE, LIST_NAME, LIST_LEVEL, LIST_TIME, LIST_COST, LIST_DAMAGE, LIST_SKILL, LIST_PATH, LIST_DESCRIPTION, LIST_BACKGROUND, LIST_MAX_SP, LIST_TAG, LIST_FOREGROUND, LIST_FONT }; static const char *Style_Names[Style_Last] = { "spell_attuned", "spell_repelled", "spell_denied", "spell_normal" }; /**< The names of theme file styles that are used in the spell dialog. */ static gpointer description_renderer = NULL; /**< The cell renderer for the * spell dialog descriptions. */ static GtkStyle *spell_styles[Style_Last]; /**< The actual styles loaded, or * NULL if no styles were found. */ static int has_init = 0; /**< Whether or not the spell * dialog initialized since * the client started up. */ /** * Gets the style information for the inventory windows. This is a separate * function because if the user changes styles, it can be nice to re-load the * configuration. The style for the inventory/look is a bit special. That is * because with gtk, styles are widget wide - all rows in the widget would use * the same style. We want to adjust the styles based on other attributes. */ void spell_get_styles(void) { int i; GtkStyle *tmp_style; static int style_has_init=0; for (i=0; i < Style_Last; i++) { if (style_has_init && spell_styles[i]) { g_object_unref(spell_styles[i]); } tmp_style = gtk_rc_get_style_by_paths( gtk_settings_get_default(), NULL, Style_Names[i], G_TYPE_NONE); if (tmp_style) { spell_styles[i] = g_object_ref(tmp_style); } else { LOG(LOG_INFO, "spells.c::spell_get_styles", "Unable to find style for %s", Style_Names[i]); spell_styles[i] = NULL; } } style_has_init = 1; } /** * Used if a user just single clicks on an entry - at which point, we enable * the cast & invoke buttons. * * @param selection * @param model * @param path * @param path_currently_selected * @param userdata */ static gboolean spell_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { gtk_widget_set_sensitive(spell_invoke, TRUE); gtk_widget_set_sensitive(spell_cast, TRUE); return TRUE; } /** * Adjust the line wrap width used by the spells dialog Description column * text renderer and force redraw of the rows to cause row height adjustment. * To compute the new wrap width, the widths of all other columns are * subtracted from the width of the spells window to determine the available * width for the description column. The remaining space is then configured * as the new wrap width. Once the new wrap is computed, mark all the rows * changed so that the renderer adjusts the row height to expand or contract * to fit the reformatted description. * * @param widget * @param user_data */ void on_spell_window_size_allocate(GtkWidget *widget, gpointer user_data) { guint i; guint width; gboolean valid; GtkTreeIter iter; guint column_count; GList *column_list; GtkTreeViewColumn *column; /* If the spell window has not been set up yet, do nothing. */ if (!has_init) { return; } /* * How wide is the spell window? */ width = spell_treeview->allocation.width; /* * How many columns are in the spell window tree view? */ column_list = gtk_tree_view_get_columns(GTK_TREE_VIEW(spell_treeview)); column_count = g_list_length(column_list); /* * Subtract the width of all but the last (Description) column from the * total window width to figure out how much may be used for the final * description column. */ for (i = 0; i < column_count - 1; i += 1) { column = g_list_nth_data(column_list, i); width -= gtk_tree_view_column_get_width(column); } /* * The column list allocated by gtk_tree_view_get_columns must be freed * when it is no longer needed. */ g_list_free(column_list); /* * Update the global variable used to configure the wrap-width for the * spell dialog description column, then apply it to the cell renderer. */ g_object_set(G_OBJECT(description_renderer), "wrap-width", width, NULL); /* * Traverse the spell store, and mark each row as changed. Get the first * row, mark it, and then process the rest of the rows (if there are any). * This re-flows the spell descriptions to the new wrap-width, and adjusts * the height of each row as needed to optimize the vertical space used. */ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(spell_store), &iter); while (valid) { GtkTreePath *tree_path; tree_path = gtk_tree_model_get_path(GTK_TREE_MODEL(spell_store), &iter); gtk_tree_model_row_changed( GTK_TREE_MODEL(spell_store), tree_path, &iter); gtk_tree_path_free(tree_path); valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(spell_store), &iter); } } /** * When spell information updates, the treeview is cleared and re-populated. * The clear/re-populate is easier than "editing" the contents. */ void update_spell_information(void) { int i; Spell *spell; GtkTreeIter iter; char buf[MAX_BUF]; GtkStyle *row_style; GdkColor *foreground=NULL; GdkColor *background=NULL; PangoFontDescription *font=NULL; /* If the window/spellstore hasn't been created, return. */ if (!has_init) { return; } cpl.spells_updated = 0; /* We could try to do this in spell_get_styles, but if the window isn't * active, it won't work. This is called whenever the window is made * active, so we know it will work, and the time to set this info here, * even though it may not change often, is pretty trivial. */ for (i=0; i < Style_Last; i++) { if (spell_styles[i]) { gtk_widget_modify_fg(spell_label[i], GTK_STATE_NORMAL, &spell_styles[i]->text[GTK_STATE_NORMAL]); gtk_widget_modify_font(spell_label[i], spell_styles[i]->font_desc); gtk_widget_modify_bg(spell_eventbox[i], GTK_STATE_NORMAL, &spell_styles[i]->base[GTK_STATE_NORMAL]); } else { gtk_widget_modify_fg(spell_label[i],GTK_STATE_NORMAL, NULL); gtk_widget_modify_font(spell_label[i], NULL); gtk_widget_modify_bg(spell_eventbox[i],GTK_STATE_NORMAL, NULL); } } gtk_list_store_clear(spell_store); for (spell = cpl.spelldata; spell; spell=spell->next) { gtk_list_store_append(spell_store, &iter); buf[0] = 0; if (spell->sp) { snprintf(buf, sizeof(buf), "%d Mana ", spell->sp); } if (spell->grace) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%d Grace", spell->grace); if (spell->path & cpl.stats.denied) { row_style = spell_styles[Style_Denied]; } else if (spell->path & cpl.stats.repelled) { row_style = spell_styles[Style_Repelled]; } else if (spell->path & cpl.stats.attuned) { row_style = spell_styles[Style_Attuned]; } else { row_style = spell_styles[Style_Normal]; } if (row_style) { foreground = &row_style->text[GTK_STATE_NORMAL]; background = &row_style->base[GTK_STATE_NORMAL]; font = row_style->font_desc; } else { foreground=NULL; background=NULL; font=NULL; } gtk_list_store_set( spell_store, &iter, LIST_IMAGE, (GdkPixbuf*) pixmaps[spell->face]->full_icon_image, LIST_NAME, spell->name, LIST_LEVEL, spell->level, LIST_COST, buf, LIST_DAMAGE, spell->dam, LIST_SKILL, spell->skill, LIST_DESCRIPTION, spell->message, LIST_BACKGROUND, background, LIST_FOREGROUND, foreground, LIST_FONT, font, LIST_MAX_SP, (spell->sp > spell->grace) ? spell->sp : spell->grace, LIST_TAG, spell->tag, -1 ); } } /** * * @param menuitem * @param user_data */ void on_spells_activate(GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *widget; if (!has_init) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; spell_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_window")); spell_invoke = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_invoke")); spell_cast = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_cast")); spell_options = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_options")); spell_treeview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_treeview")); g_signal_connect((gpointer) spell_window, "size-allocate", G_CALLBACK(on_spell_window_size_allocate), NULL); g_signal_connect((gpointer) spell_window, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect((gpointer) spell_treeview, "row_activated", G_CALLBACK(on_spell_treeview_row_activated), NULL); g_signal_connect((gpointer) spell_cast, "clicked", G_CALLBACK(on_spell_cast_clicked), NULL); g_signal_connect((gpointer) spell_invoke, "clicked", G_CALLBACK(on_spell_invoke_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_close")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_spell_close_clicked), NULL); spell_store = gtk_list_store_new( 14, G_TYPE_OBJECT, /* Image - not used */ G_TYPE_STRING, /* Name */ G_TYPE_INT, /* Level */ G_TYPE_INT, /* Time */ G_TYPE_STRING, /* SP/Grace */ G_TYPE_INT, /* Damage */ G_TYPE_STRING, /* Skill name */ G_TYPE_INT, /* Spell path */ G_TYPE_STRING, /* Description */ GDK_TYPE_COLOR, /* Background color of the entry */ G_TYPE_INT, G_TYPE_INT, GDK_TYPE_COLOR, PANGO_TYPE_FONT_DESCRIPTION ); gtk_tree_view_set_model( GTK_TREE_VIEW(spell_treeview), GTK_TREE_MODEL(spell_store)); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(spell_treeview), TRUE); /* Note: it is intentional we don't show (render) some fields: * image - we don't have images right now it seems. * time - not sure if it worth the space. * spell path - done by color * * Note: Cell alignment is set to top right instead of the default, * to improve readability when descriptions wrap to multiple lines. */ renderer = gtk_cell_renderer_pixbuf_new(); renderer->xalign = 0; renderer->yalign = 0; column = gtk_tree_view_column_new_with_attributes( "?", renderer, "pixbuf", LIST_IMAGE, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_IMAGE); renderer = gtk_cell_renderer_text_new(); renderer->xalign = 0; renderer->yalign = 0; column = gtk_tree_view_column_new_with_attributes( "Spell", renderer, "text", LIST_NAME, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_NAME); gtk_tree_view_column_add_attribute( column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute( column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute( column, renderer, "font-desc", LIST_FONT); renderer = gtk_cell_renderer_text_new(); renderer->xalign = 0.4; renderer->yalign = 0; column = gtk_tree_view_column_new_with_attributes( "Level", renderer, "text", LIST_LEVEL, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_LEVEL); gtk_tree_view_column_add_attribute( column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute( column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute( column, renderer, "font-desc", LIST_FONT); renderer = gtk_cell_renderer_text_new(); renderer->xalign = 0.4; renderer->yalign = 0; column = gtk_tree_view_column_new_with_attributes( "Cost/Cast", renderer, "text", LIST_COST, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column); /* Since this is a string column, it would do a string sort. Instead, * we set up a int column and tie this column to sort on that. */ gtk_tree_view_column_set_sort_column_id(column, LIST_MAX_SP); gtk_tree_view_column_add_attribute( column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute( column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute( column, renderer, "font-desc", LIST_FONT); renderer = gtk_cell_renderer_text_new(); renderer->xalign = 0.4; renderer->yalign = 0; column = gtk_tree_view_column_new_with_attributes( "Damage", renderer, "text", LIST_DAMAGE, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_DAMAGE); gtk_tree_view_column_add_attribute( column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute( column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute( column, renderer, "font-desc", LIST_FONT); column = gtk_tree_view_column_new_with_attributes( "Skill", renderer, "text", LIST_SKILL, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_SKILL); gtk_tree_view_column_add_attribute( column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute( column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute( column, renderer, "font-desc", LIST_FONT); renderer = gtk_cell_renderer_text_new(); renderer->xalign = 0; renderer->yalign = 0; column = gtk_tree_view_column_new_with_attributes( "Description", renderer, "text", LIST_DESCRIPTION, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(spell_treeview), column); gtk_tree_view_column_add_attribute( column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute( column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute( column, renderer, "font-desc", LIST_FONT); /* * Set up the description column so it wraps lengthy descriptions over * multiple lines and at word boundaries. A default wrap-width is * applied to constrain the column width to a reasonable value. The * actual value used here is somewhat unimportant since a corrected * width is computed and applied later, but, it does approximate the * column size that is appropriate for the dialog's default width. */ g_object_set(G_OBJECT(renderer), "wrap-width", 300, "wrap-mode", PANGO_WRAP_WORD, NULL); /* * Preserve the description text cell renderer pointer to facilitate * setting the wrap-width relative to the dialog's size and content. */ description_renderer = renderer; spell_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(spell_treeview)); gtk_tree_selection_set_mode(spell_selection, GTK_SELECTION_BROWSE); gtk_tree_selection_set_select_function( spell_selection, spell_selection_func, NULL, NULL); gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(spell_store), LIST_NAME, GTK_SORT_ASCENDING); /* The style code will set the colors for these */ spell_label[Style_Attuned] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_attuned")); spell_label[Style_Repelled] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_repelled")); spell_label[Style_Denied] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_denied")); spell_label[Style_Normal] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_label_normal")); /* We use eventboxes because the label widget is a transparent widget. * We can't set the background in it and have it work. But we can set * the background in the event box, and put the label widget in the * eventbox. */ spell_eventbox[Style_Attuned] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_attuned")); spell_eventbox[Style_Repelled] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_repelled")); spell_eventbox[Style_Denied] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_denied")); spell_eventbox[Style_Normal] = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "spell_eventbox_normal")); } gtk_widget_set_sensitive(spell_invoke, FALSE); gtk_widget_set_sensitive(spell_cast, FALSE); gtk_widget_show(spell_window); spell_get_styles(); has_init = 1; /* Must be called after has_init is set to 1 */ update_spell_information(); } /** * * @param treeview * @param path * @param column * @param user_data */ void on_spell_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) { on_spell_cast_clicked(NULL, NULL); } /** * * @param button * @param user_data */ void on_spell_cast_clicked(GtkButton *button, gpointer user_data) { int tag; char command[MAX_BUF]; const char *options = NULL; GtkTreeIter iter; GtkTreeModel *model; options = gtk_entry_get_text(GTK_ENTRY(spell_options)); if (gtk_tree_selection_get_selected(spell_selection, &model, &iter)) { gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1); if (!tag) { LOG(LOG_ERROR, "spells.c::on_spell_cast_clicked", "Unable to get spell tag\n"); return; } snprintf(command, MAX_BUF-1, "cast %d %s", tag, options); send_command(command, -1, 1); } } /** * * @param button * @param user_data */ void on_spell_invoke_clicked(GtkButton *button, gpointer user_data) { int tag; char command[MAX_BUF]; const char *options=NULL; GtkTreeIter iter; GtkTreeModel *model; options = gtk_entry_get_text(GTK_ENTRY(spell_options)); if (gtk_tree_selection_get_selected(spell_selection, &model, &iter)) { gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1); if (!tag) { LOG(LOG_ERROR, "spells.c::on_spell_invoke_clicked", "Unable to get spell tag\n"); return; } snprintf(command, MAX_BUF-1, "invoke %d %s", tag, options); send_command(command, -1, 1); } } /** * * @param button * @param user_data */ void on_spell_close_clicked(GtkButton *button, gpointer user_data) { gtk_widget_hide(spell_window); } crossfire-client-1.75.3/gtk-v2/src/create_char.c000644 001751 001751 00000077636 14045044337 022276 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Handle new character creation */ #include "client.h" #include #include "image.h" #include "main.h" #include "metaserver.h" #include "gtk2proto.h" /* This corresponds to the number of opt_.. fields in the * create_character_window. In theory, the vbox could be resized * (or add a sub box), and adjust accordingly, * but it is unlikely that number of optional choices is going * to rapidly grow, and making it static makes some things much * easier. * Instead of having two different sets of fields named different, * we just have one set and split it in half, for race and * class. This is done so that boxes don't need to be moved * around - imagine cas where one race has options and * another doesn't, but the currently selected class does - * as player chooses different races, that race choice will * come and go, but we want the class box to remain and to keep * its same value. */ #define NUM_OPT_FIELDS 6 #define RACE_OPT_START 0 #define CLASS_OPT_START NUM_OPT_FIELDS/2 #define RACE_OPT_END CLASS_OPT_START - 1 #define CLASS_OPT_ENG NUM_OPT_FIELDS - 1 /* These are in the create_character_window */ static GtkWidget *spinbutton_cc[NUM_NEW_CHAR_STATS], *label_rs[NUM_NEW_CHAR_STATS], *label_cs[NUM_NEW_CHAR_STATS], *label_tot[NUM_NEW_CHAR_STATS], *label_cc_unspent, *textview_rs_desc, *label_cc_desc, *label_cc_status_update, *button_cc_cancel, *create_character_window, *combobox_rs, *combobox_cs, *textview_cs_desc, *entry_new_character_name, *button_choose_starting_map, *opt_label[NUM_OPT_FIELDS], *opt_combobox[NUM_OPT_FIELDS]; static GtkTextMark *text_mark_cs, *text_mark_rs; /* These are in the choose starting map window */ static GtkWidget *choose_starting_map_window, *button_csm_done, *button_csm_cancel, *combobox_starting_map; GtkTextBuffer *textbuf_starting_map; static int has_init=0, negative_stat=0; #define STARTING_MAP_PANE 0 Info_Pane create_char_pane[1]; #define WINDOW_NONE 0 #define WINDOW_CREATE_CHARACTER 1 #define WINDOW_CHOOSE_MAP 2 /** * This is a little helper window which shows the window * specified and hides the other window(s). This is just * a bit cleaner than having a bunch if gtk_widget_show()/ * gtk_wdiget_hide() calls. * Also, if more than 2 windows are ever used, this will also * make it easier to make sure the correct window is displayed. * * @param window * WINDOW_... define as listed at top of this file which defines * the winow. Special is WINDOW_NONE, which will just result * in this hiding all windows. */ static void show_window(int window) { switch (window) { case WINDOW_NONE: gtk_widget_hide(create_character_window); gtk_widget_hide(choose_starting_map_window); break; case WINDOW_CREATE_CHARACTER: gtk_widget_show(create_character_window); gtk_widget_hide(choose_starting_map_window); break; case WINDOW_CHOOSE_MAP: gtk_widget_hide(create_character_window); gtk_widget_show(choose_starting_map_window); break; } } /** * This function makes the widgets in the window sensitive (or not). * This is used because having the player fiddle with the attributes * before we get the information from the server doesn't make sense. * * @param sensitive * passed to gtk_widget_set_sensitive, to either make the widget * sensitive or not */ static void create_character_set_sensitive(int sensitive) { int i; gtk_widget_set_sensitive(button_choose_starting_map, sensitive); gtk_widget_set_sensitive(entry_new_character_name, sensitive); gtk_widget_set_sensitive(combobox_rs, sensitive); gtk_widget_set_sensitive(combobox_cs, sensitive); /* Note we do not change status of cancel button - let * the player cancel out of the window if they want - * no harm in doing so. */ for (i=0; i= 2, so * we do not have any check here for that, but these * attributes are only valid for loginmethod >= 2 */ i = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox_rs)); snprintf(buf, MAX_BUF, "race %s", races[i].arch_name); SockList_AddChar(&sl, strlen(buf)+1); SockList_AddString(&sl, buf); SockList_AddChar(&sl, 0); /* From a practical standpoint, the server should never send * race/class choices unless it also supports the receipt of * those. So no special checks are needed here. */ for (on_choice = 0; on_choice < races[i].num_rc_choice; on_choice++) { int j; j = gtk_combo_box_get_active(GTK_COMBO_BOX(opt_combobox[on_choice + RACE_OPT_START])); snprintf(buf, MAX_BUF, "choice %s %s", races[i].rc_choice[on_choice].choice_name, races[i].rc_choice[on_choice].value_arch[j]); SockList_AddChar(&sl, strlen(buf)+1); SockList_AddString(&sl, buf); SockList_AddChar(&sl, 0); } i = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox_cs)); snprintf(buf, MAX_BUF, "class %s", classes[i].arch_name); SockList_AddChar(&sl, strlen(buf)+1); SockList_AddString(&sl, buf); SockList_AddChar(&sl, 0); for (on_choice = 0; on_choice < classes[i].num_rc_choice; on_choice++) { int j; j = gtk_combo_box_get_active(GTK_COMBO_BOX(opt_combobox[on_choice + CLASS_OPT_START])); snprintf(buf, MAX_BUF, "choice %s %s", classes[i].rc_choice[on_choice].choice_name, classes[i].rc_choice[on_choice].value_arch[j]); SockList_AddChar(&sl, strlen(buf)+1); SockList_AddString(&sl, buf); SockList_AddChar(&sl, 0); } /* Its possible that the server does not provide a choice of * starting maps - if that is the case, then we will never * display the starting map window. So check for that here. */ if (starting_map_number) { i = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox_starting_map)); if (i != -1) { snprintf(buf, MAX_BUF, "starting_map %s", starting_map_info[i].arch_name); SockList_AddChar(&sl, strlen(buf)+1); SockList_AddString(&sl, buf); SockList_AddChar(&sl, 0); } } for (i=0; i stat_points) { gtk_label_set_text(GTK_LABEL(label_cc_status_update), "You have used more than your allotted total attribute points"); show_window(WINDOW_CREATE_CHARACTER); return FALSE; } /* negative_stat is a global to this file. update_all_stats() * sets it/clears it - rather than doing that work again, just * re-use that value. */ if (negative_stat) { gtk_label_set_text(GTK_LABEL(label_cc_status_update), "Attributes less than 1 are not allowed - adjust your selections before finishing"); show_window(WINDOW_CREATE_CHARACTER); return FALSE; } /* No message is normally displayed for this - the player is * always going to get this case when starting out, but if * they hit done, we want to warn them that they have points * left to spend, since at present time there is no way to spend * these points later. */ if (stat_points_used < stat_points) { GtkWidget *dialog; int result; dialog = gtk_message_dialog_new(GTK_WINDOW(create_character_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s\n%s\n%s", "You have not spent all your attribute points.", "You will be unable to spend these later.", "Create character anyways?"); result = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); if (result == GTK_RESPONSE_NO) { show_window(WINDOW_CREATE_CHARACTER); return FALSE; } /* Otherwise, fall through below */ } /* Check to see starting map - note that start_map_number could * be zero, which means that the server does not have a choice, * and thus we don't have to get anything from the player. * Is throwing a dialog box up here perhaps overkill? */ i = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox_starting_map)); if (starting_map_number && i == -1) { GtkWidget *dialog; show_window(WINDOW_CHOOSE_MAP); dialog = gtk_message_dialog_new(GTK_WINDOW(choose_starting_map_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "You must choose a starting map before you can start playing"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return FALSE; } /* Everything checks out OK */ return TRUE; } /** * User has hit the done button. Need to verify input, and if it * looks good, send it to the server. * Note: This callback is used for the 'Done' button in both * the character character window and starting map window. * * @param button ignored * @param user_data ignored */ void on_button_cc_done(GtkButton *button, gpointer user_data) { if (character_data_ok()) { /* If we get here, everything checks out - now we have to * send the data to the server. */ gtk_label_set_text(GTK_LABEL(label_cc_status_update), "Sending new character information to server"); show_window(WINDOW_CREATE_CHARACTER); send_create_player_to_server(); show_main_client(); } } /** * User has changed one of the spinbutton values. We need to total * back up the values. */ void on_spinbutton_cc (GtkSpinButton *spinbutton, gpointer user_data) { update_all_stats(); } /** * User has changed one of the fields in the race/class * combobox. Since the logic for the two is somewhat * the same, we use one function to handle the event - * as such, we really need to pay attention to what * box is set to. * * @param box * The combobox that generated the event. * @param user_data * ignored */ void on_combobox_rcs_changed(GtkComboBox *box, gpointer user_data) { int active_entry, i, opt_start; GtkWidget **label_stat; Race_Class_Info *rc; char buf[256]; active_entry = gtk_combo_box_get_active(box); /* I don't think this can ever happen - if we get here, * something should be active. */ if (active_entry == -1) { return; } /* since we are using a list store, and we are not re-arranging the order, * the entry number should match our array number. */ if (box == GTK_COMBO_BOX(combobox_cs)) { gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview_cs_desc)), classes[active_entry].description, strlen(classes[active_entry].description)); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(textview_cs_desc), text_mark_cs, 0.0, TRUE, 0.0, 0.0); rc = &classes[active_entry]; label_stat = label_cs; opt_start = CLASS_OPT_START; } else if (box == GTK_COMBO_BOX(combobox_rs)) { gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview_rs_desc)), races[active_entry].description, strlen(races[active_entry].description)); gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(textview_rs_desc), text_mark_rs, 0.0, TRUE, 0.0, 0.0); rc = &races[active_entry]; label_stat = label_rs; opt_start = RACE_OPT_START; } else { LOG(LOG_ERROR, "gtk-v2/src/create_char.c:on_combobox_rcs_changed", "Passed in combobox does not match any combobox"); return; } for (i=0; i < rc->num_rc_choice; i++) { int j; GtkTreeModel *store; GtkTreeIter iter; if (i == (NUM_OPT_FIELDS/2)) { LOG(LOG_ERROR, "gtk-v2/src/create_char.c:on_combobox_rcs_changed", "Number of racial option exceeds allocated amount (%d > %d)", i, NUM_OPT_FIELDS/2); break; } /* Set up the races combobox */ store = gtk_combo_box_get_model(GTK_COMBO_BOX(opt_combobox[i + opt_start])); gtk_list_store_clear(GTK_LIST_STORE(store)); for (j=0; jrc_choice[i].num_values; j++) { gtk_list_store_append(GTK_LIST_STORE(store), &iter); gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, rc->rc_choice[i].value_desc[j], -1); } gtk_combo_box_set_active(GTK_COMBO_BOX(opt_combobox[i+opt_start]), 0); gtk_label_set_text(GTK_LABEL(opt_label[i + opt_start]), rc->rc_choice[i].choice_desc); gtk_widget_show(opt_label[i+opt_start]); gtk_widget_show(opt_combobox[i+opt_start]); /* No signals are connected - the value of the combo * box will be when we send the data to the server. */ } /* Hide any unused fields */ for ( ; i < (NUM_OPT_FIELDS/2); i++) { gtk_widget_hide(opt_label[i + opt_start]); gtk_widget_hide(opt_combobox[i + opt_start]); } /* label_stat now points at the array of stats to update, and rc points * at either the race or class to get values from. */ for (i=0; i < NUM_NEW_CHAR_STATS; i++) { snprintf(buf, sizeof(buf), "%+d", rc->stat_adj[stat_mapping[i].rc_offset]); gtk_label_set_text(GTK_LABEL(label_stat[i]), buf); } update_all_stats(); } /** * We have gotten some new information from * the server, so we need to update the information - * race/class choices or stat points/min stat/max stat * information. * */ void new_char_window_update_info() { char buf[256]; GtkListStore *store; GtkTreeIter iter; GtkCellRenderer *renderer; int i; /* We could do the update as we get the data, but it shouldn't take * too long to get all the data, and simpler to just do one update */ if (!stat_points || num_races != used_races || num_classes != used_classes) { return; } gtk_label_set_text(GTK_LABEL(label_cc_status_update), "Waiting for player selections"); snprintf(buf, sizeof(buf), "%d", stat_points); gtk_label_set_text(GTK_LABEL(label_cc_unspent), buf); /* Set up the races combobox */ store = gtk_list_store_new(1, G_TYPE_STRING); for (i=0; i. */ /** * @file gtk-v2/src/main.h * Contains various global definitions and XML file name and path defaults. */ #ifndef MAIN_H #define MAIN_H #define NUM_COLORS 13 extern GdkColor root_color[NUM_COLORS]; extern GtkWidget *window_root, *spinbutton_count; extern GtkBuilder *dialog_xml, *window_xml; extern GtkNotebook *main_notebook; extern GtkWidget *magic_map; extern GtkWidget *map_notebook; extern GtkWidget *connect_window; #define DEFAULT_IMAGE_SIZE 32 extern int map_image_size, image_size; #define DEFAULT_UI CF_DATADIR "/ui/gtk-v2.ui" #define DIALOG_FILENAME CF_DATADIR "/ui/dialogs.ui" /** Path to the current UI file. */ extern char window_xml_file[MAX_BUF]; #define MAGIC_MAP_PAGE 1 /**< Notebook page of the magic map */ extern char account_password[256]; /* gtk2proto.h depends on this - so may as well just include it here */ #include "info.h" extern void hide_main_client(void); #endif crossfire-client-1.75.3/gtk-v2/src/skills.c000644 001751 001751 00000021531 14045044330 021307 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Handles The callbacks for the skill window. */ #include "client.h" #include #include "image.h" #include "metaserver.h" #include "main.h" #include "gtk2proto.h" static GtkWidget *skill_window, *skill_treeview, *skill_use, *skill_ready; static GtkListStore *skill_store; static GtkTreeSelection *skill_selection; enum {LIST_NAME, LIST_LEVEL, LIST_EXP, LIST_NEXTLEVEL}; static int has_init = 0; /** * Used if a user just single clicks on an entry - at which point, we enable * the cast & invoke buttons. * * @param selection * @param model * @param path * @param path_currently_selected * @param userdata */ static gboolean skill_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { gtk_widget_set_sensitive(skill_ready, TRUE); gtk_widget_set_sensitive(skill_use, TRUE); return TRUE; } /** * Called whenever the skill window is opened or a stats packet is received. * If the skills window has been created and is currently visible, it rebuilds * the list store otherwise nothing happens, because it will be called again * next time the window is opened anyway. */ void update_skill_information(void) { GtkTreeIter iter; char buf[MAX_BUF]; int i, sk, level; guint64 exp_to_next_level; /* If the window/spellstore hasn't been created, or isn't currently being * shown, return. */ if (!has_init || !gtk_widget_get_visible( GTK_WIDGET(gtk_builder_get_object(dialog_xml, "skill_window")))) { return; } gtk_list_store_clear(skill_store); for (i = 0; i < MAX_SKILL; i++) { sk = skill_mapping[i].value; level = cpl.stats.skill_level[sk]; if (level > 0) { gtk_list_store_append(skill_store, &iter); buf[0] = 0; if (level >= exp_table_max) { /* we can't advance any more, so display 0*/ exp_to_next_level = 0; } else { exp_to_next_level = exp_table[level + 1] - cpl.stats.skill_exp[sk]; } gtk_list_store_set(skill_store, &iter, LIST_NAME, skill_mapping[i].name, LIST_LEVEL, level, LIST_EXP, cpl.stats.skill_exp[sk], LIST_NEXTLEVEL, exp_to_next_level, -1); } } } /** * * @param menuitem * @param user_data */ void on_skills_activate(GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *widget; if (! has_init) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; skill_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "skill_window")); skill_use = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "skill_use")); skill_ready = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "skill_ready")); skill_treeview = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "skill_treeview")); g_signal_connect((gpointer) skill_window, "delete_event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect((gpointer) skill_treeview, "row_activated", G_CALLBACK(on_skill_treeview_row_activated), NULL); g_signal_connect((gpointer) skill_ready, "clicked", G_CALLBACK(on_skill_ready_clicked), NULL); g_signal_connect((gpointer) skill_use, "clicked", G_CALLBACK(on_skill_use_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "skill_close")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_skill_close_clicked), NULL); skill_store = gtk_list_store_new(4, G_TYPE_STRING, /* Name */ G_TYPE_INT, /* Level */ G_TYPE_INT64, /* EXP */ G_TYPE_INT64 /* Exp to Next Level */ ); gtk_tree_view_set_model( GTK_TREE_VIEW(skill_treeview), GTK_TREE_MODEL(skill_store)); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(skill_treeview), TRUE); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Skill", renderer, "text", LIST_NAME, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(skill_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_NAME); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Level", renderer, "text", LIST_LEVEL, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(skill_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_LEVEL); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Exp", renderer, "text", LIST_EXP, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(skill_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_EXP); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Needed for next level", renderer, "text", LIST_NEXTLEVEL, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(skill_treeview), column); gtk_tree_view_column_set_sort_column_id(column, LIST_NEXTLEVEL); skill_selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(skill_treeview)); gtk_tree_selection_set_mode(skill_selection, GTK_SELECTION_BROWSE); gtk_tree_selection_set_select_function( skill_selection, skill_selection_func, NULL, NULL); gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(skill_store), LIST_NAME, GTK_SORT_ASCENDING); } gtk_widget_set_sensitive(skill_ready, FALSE); gtk_widget_set_sensitive(skill_use, FALSE); gtk_widget_show(skill_window); has_init = 1; /* has to be called after has_init is set to 1 */ update_skill_information(); } /** * This is where we actually do something with the skill. model and iter tell us * which skill we want to trigger, use_skill is 1 to use the skill, 0 to ready it. * @param iter * @param model * @param use_skill */ void trigger_skill(GtkTreeIter iter, GtkTreeModel *model, int use_skill) { gchar *skname; char command[MAX_BUF]; char *commandname; gtk_tree_model_get(model, &iter, LIST_NAME, &skname, -1); if (! skname) { LOG(LOG_ERROR, "skills.c::trigger_skill", "Unable to get skill name\n"); return; } commandname = use_skill ? "use_skill" : "ready_skill"; snprintf(command, MAX_BUF - 1, "%s %s", commandname, skname); send_command(command, -1, 1); g_free(skname); } /** * * @param treeview * @param path * @param column * @param user_data */ void on_skill_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data) { GtkTreeIter iter; GtkTreeModel *model; model = gtk_tree_view_get_model(treeview); if (gtk_tree_model_get_iter(model, &iter, path)) { trigger_skill(iter, model, 0); } gtk_widget_hide(skill_window); } /** * * @param button * @param user_data */ void on_skill_ready_clicked(GtkButton *button, gpointer user_data) { GtkTreeIter iter; GtkTreeModel *model; if (gtk_tree_selection_get_selected(skill_selection, &model, &iter)) { trigger_skill(iter, model, 0); } gtk_widget_hide(skill_window); } /** * * @param button * @param user_data */ void on_skill_use_clicked(GtkButton *button, gpointer user_data) { GtkTreeIter iter; GtkTreeModel *model; if (gtk_tree_selection_get_selected(skill_selection, &model, &iter)) { trigger_skill(iter, model, 1); } } /** * * @param button * @param user_data */ void on_skill_close_clicked(GtkButton *button, gpointer user_data) { gtk_widget_hide(skill_window); } crossfire-client-1.75.3/gtk-v2/src/info.c000644 001751 001751 00000232416 14575653213 020765 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Text-drawing functions for the message window */ #include "client.h" #include #include "image.h" #include "main.h" #include "gtk2proto.h" /** Color names set by the user in the gtkrc file. */ static const char *const usercolorname[NUM_COLORS] = { "black", /* 0 */ "white", /* 1 */ "darkblue", /* 2 */ "red", /* 3 */ "orange", /* 4 */ "lightblue", /* 5 */ "darkorange", /* 6 */ "green", /* 7 */ "darkgreen", /* 8 *//* Used for window background color */ "grey", /* 9 */ "brown", /* 10 */ "yellow", /* 11 */ "tan" /* 12 */ }; /** * A mapping of font numbers to style based on the rcfile content. */ static const char *font_style_names[NUM_FONTS] = { "info_font_normal", "info_font_arcane", "info_font_strange", "info_font_fixed", "info_font_hand" }; /** * @} EndOf GTK V2 Font Style Definitions. */ /** * The number of supported message panes (normal + critical). This define is * meant to support anything that iterates over all the information panels. * It does nothing to help remove or document hardcoded panel numbers * throughout the code. * * @todo Create defines for each panel and replace panel numbers with the * defines describing the panel. This integer declaration is to that * account.c knows how many are being used here, and can add appropriately. */ #define NUM_TEXT_VIEWS 2 extern const char * const usercolorname[NUM_COLORS]; Info_Pane info_pane[NUM_TEXT_VIEWS]; extern const char * const colorname[NUM_COLORS]; /* * The idea behind the msg_type_names is to provide meaningful names that the * client can use to load/save these values, in particular, the GTK-V2 client * uses these to find styles on how to draw the different msg types. We could * set this up as a two dimension array instead, but that probably is not as * efficient when the number of subtypes varies so wildly. The 0 subtypes are * used for general cases (describe the entire class of those message types). * Note also that the names here are verbose - the actual code that uses these * will expand it further. In practice, there should never be entries with * both the same type/subtype (each subtype should be unique) - if so, the * results are probably unpredictable on which one the code would use. */ #include "msgtypes.h" static int max_subtype=0, has_style=0; /** * @{ * @name GTK V2 Message Control System. * Supports a client-side implementation of what used to be provided by the * server output-count and output-sync commands. These defines presently * control the way the system works. The hardcoded values here are temporary * and shall give way to client commands and/or a GUI method of configuring * the system. Turn off the output count/sync by setting MESSAGE_COUNT_MAX * to 1. It should be safe to experiment with most values as long as none of * them are set less than 1, and as long as the two buffer sizes are set to * reasonable values (buffer sizes include the terminating null character). */ static void message_callback(int orig_color, int type, int subtype, char *message); GtkWidget *msgctrl_window; /**< The message control dialog * where routing and buffer * configuration is set up. */ GtkWidget *msgctrl_table; /**< The message control table * where routing and buffer * configuration is set up. */ #define MESSAGE_BUFFER_COUNT 10 /**< The maximum number of messages * to concurrently monitor for * duplicate occurances. */ #define MESSAGE_BUFFER_SIZE 56 /**< The maximum allowable size of * messages that are checked for * duplicate reduction. */ #define COUNT_BUFFER_SIZE 16 /**< The maximum size of the tag * that indicates the number of * times a message occured while * buffered. Example: "4 times " */ #define MESSAGE_COUNT_MAX 16 /**< The maximum number of times a * buffered message may repeat * before it is sent to a client * panel for for display. */ #define MESSAGE_AGE_MAX 16 /**< The maximum time in client * ticks, that a message resides in * a buffer before it is sent to a * client panel for display. 8 * ticks is roughly 1 second. */ /** @struct info_buffer_t * @brief A buffer record that supports suppression of duplicate messages. * This buffer holds data for messages that are monitored for suppression of * duplicates. The buffer holds all data passed to message_callback(), * including type, subtype, suggested color, and the text. Age and count * fields are provided to track the time a message is in the buffer, and how * many times it occured during the time it is buffered. */ struct info_buffer_t { int age; /**< The length of time a message * spends in the buffer, measured in * client ticks. */ int count; /**< The number of times a buffered * message is detected while it is * buffered. A count of -1 * indicates the buffer is empty. */ int orig_color; /**< Message data: The suggested * color to display the text in. */ int type; /**< Message data: Classification * of the buffered message. */ int subtype; /**< Message data: Sub-class of * the buffered message. */ char message[MESSAGE_BUFFER_SIZE]; /**< Message data: Message text. */ } info_buffer[MESSAGE_BUFFER_COUNT]; /**< Several buffers that support * suppression of duplicates even * even when the duplicates are * alternate with other messages. */ /** @struct buffer_parameter_t * @brief A container for a single buffer control parameter like output count * or time. The structure holds a widget pointer, a state variable to track * the widget value, and a default value. */ typedef struct { GtkWidget* ptr; /**< Spinbutton widget pointer. */ guint state; /**< The state of the spinbutton. */ const guint default_state; /**< The state of the spinbutton. */ } buffer_parameter_t; /** @struct buffer_control_t * @brief A container for all of the buffer control parameters like output * count and time. The structure holds widget pointers, a state variables to * track the parameter values, and the client built-in defaults. Only the * final initializer for output_count and output_time is used as a default. */ struct buffer_control_t { buffer_parameter_t count; /**< Output count control & default */ buffer_parameter_t timer; /**< Output time control & default */ } buffer_control = { /* * { uninitialized_pointer, uninitialized_state, default_value }, */ { NULL, 0, MESSAGE_COUNT_MAX }, { NULL, 0, MESSAGE_AGE_MAX } }; /** @struct boolean_widget_t * @brief A container that holds the pointer and state of a checkbox control. * Each Message Control dialog checkbox is tracked in one of these structs. */ typedef struct { GtkWidget* ptr; /**< Checkbox widget pointer. */ gboolean state; /**< The state of the checkbox. */ } boolean_widget_t; /** @struct message_control_t * @brief A container for all of the checkboxes associated with a single * message type. */ typedef struct { boolean_widget_t buffer; /**< Checkbox widget and state for a * single message type. */ boolean_widget_t pane[NUM_TEXT_VIEWS];/**< Checkbox widgets and state for * each client-supported message * panel. */ } message_control_t; message_control_t msgctrl_widgets[MSG_TYPE_LAST-1]; /**< All of the checkbox widgets for * the entire message control * dialog. */ /** @struct msgctrl_data_t * @brief Descriptive message type names with pane routing and buffer enable. * A single struct defines a hard-coded, player-friendly, descriptive name to * use for a single message type. All other fields in the structure define * routing of messages to either or both client message panels, and whether * or not messages of this type are passed through the duplicate suppression * buffer system. This struct is intended to be used as the base type of an * array that contains one struct per message type defined in newclient.h. * The hard-coding of the descriptive name for the message type here is not * ideal as it would be nicer to have it alongside the MSG_TYPE_* defines. */ struct msgctrl_data_t { const char * description; /**< A descriptive name to give to * a message type when displaying it * for a player. These values * should be kept in sync with the * MSG_TYPE_* declarations in * ../../common/shared/newclient.h */ const gboolean buffer; /**< Whether or not to consider the * message type for output-count * buffering. 0/1 == disable/enable * duplicate suppression * (output-count). */ const gboolean pane[NUM_TEXT_VIEWS]; /**< The routing instructions for a * single message type. For each * pane, 0/1 == disable/enable * display of the message type in * the associated client message * pane. */ } msgctrl_defaults[MSG_TYPE_LAST-1] = /**< A data structure to track how * to handle each message type in * with respect to panel routing and * output count. */ { /* * { "description", buffer, { pane[0], pane[1] } }, */ { "Books", FALSE, { TRUE, FALSE } }, { "Cards", FALSE, { TRUE, FALSE } }, { "Paper", FALSE, { TRUE, FALSE } }, { "Signs & Magic Mouths", FALSE, { TRUE, FALSE } }, { "Monuments", FALSE, { TRUE, FALSE } }, { "Dialogs (Altar/NPC/Magic Ear)" , FALSE, { TRUE, FALSE } }, { "Message of the day", FALSE, { TRUE, FALSE } }, { "Administrative", FALSE, { TRUE, FALSE } }, { "Shops", TRUE, { TRUE, FALSE } }, { "Command responses", FALSE, { TRUE, FALSE } }, { "Changes to attributes", TRUE, { TRUE, TRUE } }, { "Skill-related messages", TRUE, { TRUE, FALSE } }, { "Apply results", TRUE, { TRUE, FALSE } }, { "Attack results", TRUE, { TRUE, FALSE } }, { "Player communication", FALSE, { TRUE, TRUE } }, { "Spell results", TRUE, { TRUE, FALSE } }, { "Item information", TRUE, { TRUE, FALSE } }, { "Miscellaneous", TRUE, { TRUE, FALSE } }, { "Victim notification", FALSE, { TRUE, TRUE } }, { "Client-generated messages", FALSE, { TRUE, FALSE } } }; /** * @} EndOf GTK V2 Message Control System. */ extern bool arm_mapedit; /** * Sets attributes in the text tag from a style. Best I can gather, there is * no way to take all of the attributes from a style and apply them directly to * a text tag, hence this function to do the work. GtkTextTags also know what * attributes are set and which are not set - thus, you can apply multiple tags * to the same text, and get all of the effects. For styles, that isn't the * case - a style contains all of the information. So this function also * compares the loaded style from the base style, and only sets the attributes * that are different. * * @param tag Text tag to set values on. * @param style Style name to get values from. * @param base_style Base style for the widget to compare against. */ void set_text_tag_from_style(GtkTextTag *tag, GtkStyle *style, const GtkStyle * const base_style) { g_object_set(tag, "foreground-set", FALSE, NULL); g_object_set(tag, "background-set", FALSE, NULL); g_object_set(tag, "font-desc", NULL, NULL); if (memcmp( &style->fg[GTK_STATE_NORMAL], &base_style->fg[GTK_STATE_NORMAL], sizeof(GdkColor))) { g_object_set(tag, "foreground-gdk", &style->fg[GTK_STATE_NORMAL], NULL); } if (memcmp( &style->bg[GTK_STATE_NORMAL], &base_style->bg[GTK_STATE_NORMAL], sizeof(GdkColor))) { g_object_set(tag, "background-gdk", &style->bg[GTK_STATE_NORMAL], NULL); } if (style->font_desc != base_style->font_desc) { g_object_set(tag, "font-desc", style->font_desc, NULL); } } /** * Adds the various tags to the next buffer. If textbuf is non-null, then it * also sets the text buffer for that pane to textbuf. This is called right * now by info_get_styles() below and from within the account code. * * @param pane Message panel number to add buffer to. * @param textbuf Text buffer to apply tags to. It is allowed to be null if * info_pane[pane].textbuffer has already been set. */ void add_tags_to_textbuffer(Info_Pane *pane, GtkTextBuffer *textbuf) { int i; if (textbuf) { pane->textbuffer = textbuf; } for (i = 0; i < MSG_TYPE_LAST; i++) pane->msg_type_tags[i] = calloc(max_subtype + 1, sizeof(GtkTextTag*)); for (i = 0; i < NUM_FONTS; i++) { pane->font_tags[i] = NULL; } for (i = 0; i < NUM_COLORS; i++) { pane->color_tags[i] = NULL; } /* * These tag definitions never change - we don't get them from the * settings file (maybe we should), so we only need to allocate them once. */ pane->bold_tag = gtk_text_buffer_create_tag(pane->textbuffer, "bold", "weight", PANGO_WEIGHT_BOLD, NULL); pane->italic_tag = gtk_text_buffer_create_tag(pane->textbuffer, "italic", "style", PANGO_STYLE_ITALIC, NULL); pane->underline_tag = gtk_text_buffer_create_tag(pane->textbuffer, "underline", "underline", PANGO_UNDERLINE_SINGLE, NULL); /* * This is really a convenience - so multiple tags may be passed when * drawing text, but once a NULL tag is found, that signifies no more * tags. Rather than having to set up an array to pass in, instead, an * empty tag is passed in so that calling semantics remain consistent, * just differing in what tags are passed in. */ if (!pane->default_tag) pane->default_tag = gtk_text_buffer_create_tag(pane->textbuffer, "default", NULL); } /** * This is like add_tags_to_textbuffer above, but styles can be changed during * the run of the client. So this has to be separate to note it it might be a * reload. * * @param pane Message panel number to update. * @param base_style Base style if retrieved - may be null. */ void add_style_to_textbuffer(Info_Pane *pane, GtkStyle *base_style) { int i; char style_name[MAX_BUF]; GtkStyle *tmp_style; if (base_style) { /* * Old message/color support. */ for (i = 0; i < NUM_COLORS; i++) { snprintf(style_name, MAX_BUF, "info_%s", usercolorname[i]); tmp_style = gtk_rc_get_style_by_paths( gtk_settings_get_default(), NULL, style_name, G_TYPE_NONE); if (tmp_style) { if (!pane->color_tags[i]) { pane->color_tags[i] = gtk_text_buffer_create_tag( pane->textbuffer, NULL, NULL); } set_text_tag_from_style( pane->color_tags[i], tmp_style, base_style); } else { if (pane->color_tags[i]) { gtk_text_tag_table_remove( gtk_text_buffer_get_tag_table( pane->textbuffer), pane->color_tags[i]); pane->color_tags[i] = NULL; } } } /* Font type support */ for (i = 0; i < NUM_FONTS; i++) { tmp_style = gtk_rc_get_style_by_paths( gtk_settings_get_default(), NULL, font_style_names[i], G_TYPE_NONE); if (tmp_style) { if (!pane->font_tags[i]) { pane->font_tags[i] = gtk_text_buffer_create_tag( pane->textbuffer, NULL, NULL); } set_text_tag_from_style( pane->font_tags[i], tmp_style, base_style); } else { if (pane->font_tags[i]) { gtk_text_tag_table_remove( gtk_text_buffer_get_tag_table(pane->textbuffer), pane->font_tags[i]); pane->font_tags[i] = NULL; } } } } else { for (i = 0; i < NUM_COLORS; i++) { if (pane->color_tags[i]) { gtk_text_tag_table_remove( gtk_text_buffer_get_tag_table( pane->textbuffer), pane->color_tags[i]); pane->color_tags[i] = NULL; } } /* Font type support */ for (i = 0; i < NUM_FONTS; i++) { if (pane->font_tags[i]) { gtk_text_tag_table_remove( gtk_text_buffer_get_tag_table( pane->textbuffer), pane->font_tags[i]); pane->font_tags[i] = NULL; } } } } /** * Loads up values from the style file. Note that the actual name of the * style file is set elsewhere. * * This function is designed so that it should be possible to call it multiple * times - it will release old style data and load up new values. In this * way, a user should be able to change styles on the fly and have things * work. */ void info_get_styles(void) { unsigned int i, j; static int has_init=0; GtkStyle *tmp_style, *base_style; if (!has_init) { /* * We want to set up a 2 dimensional array of msg_type_tags to * correspond to all the types/subtypes, so looking up any value is * really easy. We know the size of the types, but don't know the * number of subtypes - no single declared value. So we just parse * the msg_type_names to find that, then know how big to make the * other dimension. We could allocate different number of entries for * each type, but that makes processing a bit harder (no single value * on the number of subtypes), and this extra memory usage shouldn't * really be at all significant. */ for (i = 0; i < sizeof(msg_type_names) / sizeof(Msg_Type_Names); i++) { if (msg_type_names[i].subtype > max_subtype) { max_subtype = msg_type_names[i].subtype; } } for (j = 0; j < NUM_TEXT_VIEWS; j++) { add_tags_to_textbuffer(&info_pane[j], NULL); } has_init = 1; } base_style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL, "info_default", G_TYPE_NONE); if (!base_style) { LOG(LOG_INFO, "info.c::info_get_styles", "Unable to find base style info_default" " - will not process most info tag styles!"); } has_style = 0; /* * If we don't have a base style tag, we can't process these other tags, * as we need to be able to do a difference, and doing a difference from * nothing (meaning, taking everything in style) still doesn't work really * well. */ if (base_style) { /* * This processes the type/subtype styles. We look up the names in * the array to find what name goes to what number. */ for (i = 0; i < sizeof(msg_type_names) / sizeof(Msg_Type_Names); i++) { int type, subtype; char style_name[MAX_BUF]; snprintf(style_name, sizeof(style_name), "msg_%s", msg_type_names[i].style_name); type = msg_type_names[i].type; subtype = msg_type_names[i].subtype; tmp_style = gtk_rc_get_style_by_paths( gtk_settings_get_default(), NULL, style_name, G_TYPE_NONE); for (j = 0; j < NUM_TEXT_VIEWS; j++) { /* * If we have a style for this, update the tag that goes along * with this. If we don't have a tag for this style, create * it. */ if (tmp_style) { if (!info_pane[j].msg_type_tags[type][subtype]) { info_pane[j].msg_type_tags[type][subtype] = gtk_text_buffer_create_tag( info_pane[j].textbuffer, NULL, NULL); } set_text_tag_from_style( info_pane[j].msg_type_tags[type][subtype], tmp_style, base_style); has_style = 1; } else { /* * No setting for this type/subtype, so remove tag if * there is one. */ if (info_pane[j].msg_type_tags[type][subtype]) { gtk_text_tag_table_remove( gtk_text_buffer_get_tag_table( info_pane[j].textbuffer), info_pane[j].msg_type_tags[type][subtype]); info_pane[j].msg_type_tags[type][subtype] = NULL; } } } } for (j = 0; j < NUM_TEXT_VIEWS; j++) { add_style_to_textbuffer(&info_pane[j], base_style); } } else { /* * There is no base style - this should not normally be the case with * any real setting files, but certainly can be the case if the user * selected the 'None' setting. So in this case, we just free all the * text tags. */ has_style = 0; for (i = 0; i < sizeof(msg_type_names) / sizeof(Msg_Type_Names); i++) { int type, subtype; type = msg_type_names[i].type; subtype = msg_type_names[i].subtype; for (j = 0; j < NUM_TEXT_VIEWS; j++) { if (info_pane[j].msg_type_tags[type][subtype]) { gtk_text_tag_table_remove( gtk_text_buffer_get_tag_table( info_pane[j].textbuffer), info_pane[j].msg_type_tags[type][subtype]); info_pane[j].msg_type_tags[type][subtype] = NULL; } } } for (j = 0; j < NUM_TEXT_VIEWS; j++) { add_style_to_textbuffer(&info_pane[j], NULL); } } } /** * Initialize the information panels in the client. These panels are the * client areas where text is drawn. * * @param window_root Pointer to the parent (root) application window. */ void info_init(GtkWidget *window_root) { int i; GtkTextIter end; char widget_name[MAX_BUF]; for (i = 0; i < NUM_TEXT_VIEWS; i++) { snprintf(widget_name, MAX_BUF, "textview_info%d", i+1); info_pane[i].textview = GTK_WIDGET(gtk_builder_get_object(window_xml, widget_name)); snprintf(widget_name, MAX_BUF, "scrolledwindow_textview%d", i+1); info_pane[i].scrolled_window = GTK_WIDGET(gtk_builder_get_object(window_xml, widget_name)); gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(info_pane[i].textview), GTK_WRAP_WORD_CHAR); info_pane[i].textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(info_pane[i].textview)); info_pane[i].adjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(info_pane[i].scrolled_window)); gtk_text_buffer_get_end_iter(info_pane[i].textbuffer, &end); info_pane[i].textmark = gtk_text_buffer_create_mark( info_pane[i].textbuffer, NULL, &end, FALSE); gtk_widget_realize(info_pane[i].textview); } /*info_get_styles();*/ info_buffer_init(); /* Register callbacks for all message types */ for (i = 0; i < MSG_TYPE_LAST; i++) { setTextManager(i, message_callback); } } /** * Adds some data to the text buffer of the specified information panel using * the appropriate tags to provide the desired formatting. Note that the * style within the users theme determines how a particular type/subtype is * drawn. * * @param pane The client message panel to write a message to. * @param message A pointer to some text to show in a client message window. * @param type The message type - see the MSG_TYPE values in newclient.h. * @param subtype Message subtype - see MSG_TYPE_*_* values in newclient.h. * @param bold If true, should be in bold text. * @param italic If true, should be in italic text * @param font Which font to use - resolved to an actual font style based * on the user's theme file. * @param color String name of the color. * @param underline If true, draw underlined text. */ static void add_to_textbuf(Info_Pane *pane, const char *message, int type, int subtype, int bold, int italic, int font, const char *color, int underline) { GtkTextIter end; GdkRectangle rect; int scroll_to_end=0, color_num; GtkTextTag *color_tag=NULL, *type_tag=NULL; /* * Lets see if the defined color matches any of our defined colors. If we * get a match, set color_tag. If color_tag is null, we either don't have * a match, we don't have a defined tag for the color, or we don't have a * color, use the default tag. It would be nice to know if color is a sub * value set with [color] tag, or is part of the message itself - if we're * just being passed NDI_RED in the draw_ext_info from the server, we * really don't care about that - the type/subtype styles should really be * what determines what color to use. */ if (color) { for (color_num = 0; color_num < NUM_COLORS; color_num++) if (!g_ascii_strcasecmp(usercolorname[color_num], color)) { break; } if (color_num < NUM_COLORS) { color_tag = pane->color_tags[color_num]; } } if (!color_tag) { color_tag = pane->default_tag; } /* * Following block of code deals with the type/subtype. First, we check * and make sure the passed in values are legal. If so, first see if * there is a particular style for the type/subtype combo, if not, fall * back to one just for the type. */ type_tag = pane->default_tag; /* Clear subtype on MSG_TYPE_CLIENT if max_subtype is not set * Errors are generated during initialization, before max_subtype * has been set, so we can not route to a specific pane. * We also want to make sure we do not hit the pane->msg_type_tags * code, as that is not initialzed yet. */ if (type == MSG_TYPE_CLIENT && !max_subtype) { /* We would set subtype = 0, but that'd be a dead assignment. */ } else if (type >= MSG_TYPE_LAST || subtype >= max_subtype || type < 0 || subtype < 0 ) { LOG(LOG_ERROR, "info.c::add_to_textbuf", "type (%d) >= MSG_TYPE_LAST (%d) or " "subtype (%d) >= max_subtype (%d)\n", type, MSG_TYPE_LAST, subtype, max_subtype); } else { if (pane->msg_type_tags[type][subtype]) { type_tag = pane->msg_type_tags[type][subtype]; } else if (pane->msg_type_tags[type][0]) { type_tag = pane->msg_type_tags[type][0]; } } gtk_text_view_get_visible_rect( GTK_TEXT_VIEW(pane->textview), &rect); /* Simple panes (like those of the login windows) don't have adjustments * set (and if they did, we wouldn't want to scroll to end in any case), * so check here on what to do. */ if (pane->adjustment && (gtk_adjustment_get_value(pane->adjustment) + rect.height) >= gtk_adjustment_get_upper(pane->adjustment)) { scroll_to_end = 1; } gtk_text_buffer_get_end_iter(pane->textbuffer, &end); gtk_text_buffer_insert_with_tags( pane->textbuffer, &end, message, strlen(message), bold ? pane->bold_tag : pane->default_tag, italic ? pane->italic_tag : pane->default_tag, underline ? pane->underline_tag : pane->default_tag, pane->font_tags[font] ? pane->font_tags[font] : pane->default_tag, color_tag, type_tag, NULL); if (scroll_to_end) gtk_text_view_scroll_mark_onscreen( GTK_TEXT_VIEW(pane->textview), pane->textmark); } /** * This just does the work of taking text (which may have markup) and putting * it into the target pane. This is a lower level than the draw_ext_info() * below, as it does not do message routing. This is called from * draw_ext_info() below, as well as account.c to update news/motd/rules. * * @param pane Pointer to the pane info to draw info. * @param message Message that is parsed and displayed. * @param type Type of the message - for default coloring information. * @param subtype Subtype of message - used for default coloring information. * @param orig_color Legacy color hint not based on type that is used when a * theme does not define a style for the message. * @note Note both type and subtype are the values passed to draw_ext_info(). */ void add_marked_text_to_pane(Info_Pane *pane, const char *message, int type, int subtype, int orig_color) { char *marker, *current, *original; int bold=0, italic=0, font=0, underline=0; const char *color=NULL; /**< Only if we get a [color] tag should we care, * otherwise, the type/subtype should dictate * color (unless no style set!) */ current = g_strdup(message); original = current; /* Just so we know what to free */ /* * If there is no style information, or if a specific style has not been * set for the type/subtype of this message, allow orig_color to set the * color of the text. The orig_color handling here adds compatibility * with former draw_info() calls that gave a color hint. The color hint * still works now in the event that the theme has not set a style for the * message type. */ if (! has_style || pane->msg_type_tags[type][subtype] == 0) { if (orig_color <0 || orig_color>NUM_COLORS) { LOG(LOG_ERROR, "info.c::draw_ext_info", "Passed invalid color from server: %d, max allowed is %d\n", orig_color, NUM_COLORS); } else { /* * Not efficient - we have a number, but convert it to a string, * at which point add_to_textbuf() converts it back to a number. */ color = usercolorname[orig_color]; } } while ((marker = strchr(current, '[')) != NULL) { *marker = 0; if (strlen(current) > 0) add_to_textbuf(pane, current, type, subtype, bold, italic, font, color, underline); current = marker + 1; if ((marker = strchr(current, ']')) == NULL) { free(original); return; } *marker = 0; if (!strcmp(current, "b")) { bold = TRUE; } else if (!strcmp(current, "/b")) { bold = FALSE; } else if (!strcmp(current, "i")) { italic = TRUE; } else if (!strcmp(current, "/i")) { italic = FALSE; } else if (!strcmp(current, "ul")) { underline = TRUE; } else if (!strcmp(current, "/ul")) { underline = FALSE; } else if (!strcmp(current, "fixed")) { font = FONT_FIXED; } else if (!strcmp(current, "arcane")) { font = FONT_ARCANE; } else if (!strcmp(current, "hand")) { font = FONT_HAND; } else if (!strcmp(current, "strange")) { font = FONT_STRANGE; } else if (!strcmp(current, "print")) { font = FONT_NORMAL; } else if (!strcmp(current, "/color")) { color = NULL; } else if (!strncmp(current, "color=", 6)) { color = current + 6; } else LOG(LOG_INFO, "info.c::message_callback", "unrecognized tag: [%s]\n", current); current = marker + 1; } add_to_textbuf( pane, current, type, subtype, bold, italic, font, color, underline); add_to_textbuf( pane, "\n", type, subtype, bold, italic, font, color, underline); free(original); } /** * A message processor that accepts messages along with meta information color * and type. The message type and subtype are analyzed to select font and * other text attributes. All gtk-v2 client messages pass through this * processor before being output. Before addition of the output buffering * feature, this was the message callback function. It is a separate function * so that it can be called both by the callback, and but buffer maintenance * functions. * * Client-sourced messages generally should be passed directly to this handler * instead of to the callback. This will save some overhead as the callback * implements a system that coalesces duplicate messages - a feature that is * not really applicable to most messages that do not come from the server. * * @param orig_color Suggested text color that type/subtype can over-ride. * @param type Message type. See MSG_TYPE definitions in newclient.h. * @param subtype Message subtype. See MSG_TYPE_*_* values in newclient.h. * @param message The message text to display. */ void draw_ext_info(int orig_color, int type, int subtype, const char *message) { int type_err=0; /**< When 0, the type is valid and may be used to pick * the panel routing, otherwise the message can only * go to the main message pane. */ int pane; char *stamp = NULL; const char *draw = NULL; if (want_config[CONFIG_TIMESTAMP]) { time_t curtime; struct tm *ltime; stamp = calloc(1, strlen(message) + 7); curtime = time(NULL); ltime = localtime(&curtime); strftime(stamp, 6, "%I:%M", ltime); strcat(stamp, " "); strcat(stamp, message); draw = stamp; } else { draw = message; } /* * A valid message type is required to index into the msgctrl_widgets * array. If an invalid type is identified, log an error as any message * without a valid type should be hunted down and assigned an appropriate * type. */ if ((type < 1) || (type >= MSG_TYPE_LAST)) { LOG(LOG_ERROR, "info.c::draw_ext_info", "Invalid message type: %d", type); type_err = 1; } /* * Route messages to any one of the client information panels based on the * type of the message text. If a message with an invalid type comes in, * it goes to the main message panel (0). Messages can actually be sent * to more than one panel if the player so desires. */ for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { /* * If the message type is invalid, then the message must go to pane 0, * otherwise the msgctrl_widgets[].pane[pane].state setting determines * whether to send the message to a particular pane or not. The type * is one-based, so must be decremented when referencing * msgctrl_widgets[]; */ if (type_err != 0) { if (pane != 0) { break; } } else { if (msgctrl_widgets[type - 1].pane[pane].state == FALSE) { continue; } } add_marked_text_to_pane(&info_pane[pane], draw, type, subtype, orig_color); } if (want_config[CONFIG_TIMESTAMP]) { free(stamp); } } /** * @defgroup GTKv2OutputCountSync GTK V2 client output count/sync functions. * @{ */ /** * Output count/sync message buffer initialization to set all buffers empty. * Called only once at client start from info_init(), the function initializes * all message buffers to the empty state (count == -1). At a minimum, age, * count, and message should be initialized. Type, subtype, and orig_color * are also set just for an extra measure of safety. */ void info_buffer_init(void) { int loop; for (loop = 0; loop < MESSAGE_BUFFER_COUNT; loop += 1) { info_buffer[loop].count = -1; info_buffer[loop].age = 0; info_buffer[loop].type = 0; info_buffer[loop].subtype = 0; info_buffer[loop].orig_color = 0; info_buffer[loop].message[0] = '\0'; }; } /** * Handles message buffer flushes, and, as needed, displays the text. Flushed * buffers have their count set to -1. On flush, the message text is output * only when the message count is greater than zero. If the message text is * displayed, and if the count is greater than one, it is prepended to the * message in the form "N * times ". This function is called whenever a * message must be ejected from the output count/sync system buffers. Note * that the message details are preserved when the buffer is flushed. This * allows the buffer contents to be re-used if another message with the same * text comes in before the buffer is re-used for a different message. * * @param id The message control buffer to flush (0 - MESSAGE_BUFFER_COUNT). */ void info_buffer_flush(const int id) { char output_buffer[MESSAGE_BUFFER_SIZE /* Buffer for output big enough */ +COUNT_BUFFER_SIZE]; /* to hold both count and text. */ /* * Messages are output with no output-count at the time they are first * placed in a buffer, so do not bother displaying it again if another * instance of the message was not seen after the initial buffering. */ if (info_buffer[id].count > 0) { /* * Report the number of times the message was seen only if it was seen * after having been initially buffered. */ if (info_buffer[id].count > 1) { snprintf(output_buffer, sizeof(output_buffer), "%u times %s", info_buffer[id].count, info_buffer[id].message); /* * Output the message count and message text. */ draw_ext_info( info_buffer[id].orig_color, info_buffer[id].type, info_buffer[id].subtype, output_buffer); } else /* * Output only the message text. */ draw_ext_info( info_buffer[id].orig_color, info_buffer[id].type, info_buffer[id].subtype, info_buffer[id].message); }; /* * Mark the buffer newly emptied. */ info_buffer[id].count = -1; } /** * Output count/sync buffer maintainer adds buffer time and output messages. * For every tick, age active messages so it eventually gets displayed. If * the data in an buffer reaches the maximum permissible age or message * occurance count, it is ejected and displayed. Inactive buffers are also * aged so that the oldest empty buffer is used first when a new message * comes in. */ void info_buffer_tick(void) { int loop; for (loop = 0; loop < MESSAGE_BUFFER_COUNT; loop += 1) { if (info_buffer[loop].count > -1) { if ((info_buffer[loop].age < (int) buffer_control.timer.state) && (info_buffer[loop].count < (int) buffer_control.count.state)) { /* * The buffer has data in it, and has not reached maximum age, * so bump the age up a notch. */ info_buffer[loop].age += 1; } else { /* * The data has been in the buffer too long, so either display * it (and report how many times it was seen while in the * buffer) or simply expire the buffer content if duplicates * did not occur. */ info_buffer_flush(loop); } } else { /* * Overflow-protected aging of empty or inactive buffers. Aging * of inactive buffers is the reason overflow must be handled. */ if (info_buffer[loop].age < info_buffer[loop].age + 1) { info_buffer[loop].age += 1; } } } } static void launch_mapedit(char *path) { char *editor = getenv("CF_MAP_EDITOR"); if (editor == NULL) { LOG(LOG_ERROR, "mapedit", "CF_MAP_EDITOR is not defined"); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "No map editor is specified in CF_MAP_EDITOR environment variable!"); // If no editor, then we cannot proceed. argv[0] of null crashes the client. return; } LOG(LOG_INFO, "mapedit", "Launching map editor on '%s'", path); char *argv[] = {editor, path, NULL}; GError *err = NULL; if (!g_spawn_async(NULL, argv, NULL, 0, NULL, NULL, NULL, &err)) { LOG(LOG_ERROR, "mapedit", "Could not launch CF_MAP_EDITOR: %s", err->message); } } /** * A callback to accept messages along with meta information color and type. * Unlike the GTK V1 client, we don't do anything tricky like popups with * different message types, but the output-count/sync features do consider * message type, etc. To allow user-defined buffering rules all messages * need to pass through a common processor. This callback is the interface * for the output buffering. Even if output buffering could be bypassed, it * is still necessary to pass messages through a common interface to handle * style, theme, and display panel configuration. This callback routes all * messages to the appropriate handler for pre-display processing * (draw_ext_info()). * * It is recommended that client-sourced messages be passed directly to * draw_ext_info() instead of through the callback to avoid unnecessary * processing. MSG_TYPE_CLIENT messages are deliberately not buffered here * because they are generally unique, adminstrative messages that should not * be delayed. * * @param orig_color Suggested text color that type/subtype can over-ride. * @param type Message type. See MSG_TYPE definitions in newclient.h. * @param subtype Message subtype. See MSG_TYPE_*_* values in newclient.h. * @param message The message text to display. */ static void message_callback(int orig_color, int type, int subtype, char *message) { int search; /* Loop for searching the buffers. */ int found; /* Which buffer a message is in. */ int empty; /* The ID of an empty buffer. */ int oldest; /* Oldest non-empty buffer found. */ int empty_age; /* Age of oldest empty buffer. */ int oldest_age; /* Age of oldest non-empty buffer. */ /* * Any message that has an invalid type cannot be buffered. An error is * not logged here as draw_ext_info() is where all messages pass through. * * A legacy switch to prevent message folding is to set the color of the * message to NDI_UNIQUE. This over-rides the player preferences. * * Usually msgctrl_widgets[] is used to determine whether or not messages * are buffered as it is where the player sets buffering preferences. The * type must be decremented when used to index into msgctrl_widgets[]. * * The system also declines to buffer messages over a set length as most * messages that need coalescing are short. Most messages that are long * are usually unique and should not be delayed. >= allows for the null * at the end of the string in the buffer. IE. If the buffer size is 40, * only 39 chars can be put into it to ensure room for a null character. */ if (arm_mapedit) { arm_mapedit = false; char *msg_cpy = strdup(message); char *ptr = msg_cpy; ptr = strtok(ptr, ")"); if (ptr != NULL) { ptr = strtok(ptr, "("); ptr = strtok(NULL, "("); if (ptr != NULL) { launch_mapedit(ptr); } else { LOG(LOG_INFO, "mapedit", "Could not parse map path from '%s'", message); } } free(msg_cpy); } if ((type < 1) || (type >= MSG_TYPE_LAST) || (orig_color == NDI_UNIQUE) || (msgctrl_widgets[type - 1].buffer.state == FALSE) || (strlen(message) >= MESSAGE_BUFFER_SIZE)) { /* * If the message buffering feature is off, simply pass the message on * to the parser that will determine the panel routing and style. */ draw_ext_info(orig_color, type, subtype, message); } else { empty = -1; /* Default: Buffers are empty until proven full */ found = -1; /* Default: Incoming message is not in a buffer */ oldest = -1; /* Default: Oldest active buffer ID is unknown */ empty_age= -1; /* Default: Oldest empty buffer age is unknown */ oldest_age= -1; /* Default: Oldest active buffer age is unknown */ for (search = 0; search < MESSAGE_BUFFER_COUNT; search += 1) { /* * 1) Find the oldest empty or inactive buffer, if one exists. * 2) Find the oldest non-empty/active buffer in case we need to * eject a message to make room for a new message. * 3) Find a buffer that matches the incoming message, whether the * buffer is active or not. */ if (info_buffer[search].count < 0) { /* * We want to find the oldest empty buffer. If a new message * that is not already buffered comes in, this is the ideal * place to put it. */ if ((info_buffer[search].age > empty_age)) { empty_age = info_buffer[search].age; empty = search; } } else { /* * The buffer is not empty, so process it to find the oldest * buffered message. If a new message comes in that is not * already buffered, and if there are no empty buffers * available, the oldest message will be pushed out to make * room for the new one. */ if (info_buffer[search].age > oldest_age) { oldest_age = (info_buffer[search].age); oldest = search; } } /* * Check all buffers, inactive and active, to see if the incoming * message matches an existing buffer. Because empty buffers are * re-used if they match, it should not be possible for more than * one buffer to match, so do not bother searching after the first * match is found. */ if (found < 0) { if (! strcmp(message, info_buffer[search].message)) { found = search; } } } #if 0 LOG(LOG_DEBUG, "info.c::message_callback", "\n " "type: %d-%d empty: %d found: %d oldest: %d oldest_age: %d", type, subtype, empty, found, oldest, oldest_age); #endif /* * If the incoming message is already buffered, then increment the * message count and exit, otherwise add the message to the buffer. */ if (found > -1) { /* * If the found buffer was inactive, this automatically activates * it, and sets the count to one to ensure printing of the message * occurance as messages are pre-printed only when they are * inserted into a buffer after not being found. */ if (info_buffer[found].count == -1) { info_buffer[found].count += 1; info_buffer[found].age = 0; } info_buffer[found].count += 1; } else { /* * The message was not found in a buffer, so check if there is an * available buffer. If not, dump the oldest buffer to make room, * then mark it empty. */ if (empty == -1) { if (oldest > -1) { /* * The oldest message is getting kicked out of the buffer * to make room for a new message coming in. */ info_buffer_flush(oldest); } else { LOG(LOG_ERROR, "info.c::message_callback", "Buffer full; oldest unknown", strlen(message)); } } /* * To avoid delaying player notification in cases where multiple * messages might not occur, or especially if a message is really * important to get right away, go ahead an output the message * without a count at the time it is first put into a buffer. As * this message has already been output, the buffer count is set * zero, so that info_buffer_flush() will not re-display it if a * duplicate does not occur while this message is in the buffer. */ draw_ext_info(orig_color, type, subtype, message); /* * There should always be an empty buffer at this point, but just * in case, recheck before putting the new message in the buffer. * Do not log another error as one was just logged, but instead * just output the message that came in without passing it through * the buffer system. */ if (empty > -1) { /* * Copy the incoming message to the empty buffer. */ info_buffer[empty].age = 0; info_buffer[empty].count = 0; info_buffer[empty].orig_color = orig_color; info_buffer[empty].type = type; info_buffer[empty].subtype = subtype; strcpy(info_buffer[empty].message, message); } } } } /** * @} */ /* EndOf GTKv2OutputCountSync */ /** * Clears all the message panels. It is not clear why someone would use it, * but is called from the common area, and so is supported here. */ void menu_clear(void) { int i; for (i=0; i < NUM_TEXT_VIEWS; i++) { gtk_text_buffer_set_text(info_pane[i].textbuffer, "", 0); } } /** * Initialize the message control panel by populating it with descriptions of * each message type along with checkboxes that are used to configure the * routing and duplicate suppression system. If previously saved settings are * found on disk, they are loaded and applied, otherwise the built in client * defaults are loaded and applied. This initialization must occur after the * info_init() function runs. * * @param window_root The client main window */ void msgctrl_init(GtkWidget *window_root) { GtkTableChild* child; /* Used to get number of title rows */ GtkWidget* widget; /* Used to connect widgets */ GtkTable* table; /* The table of checkbox controls */ GList* list; /* Iterator: table children */ guint pane; /* Iterator: client message panes */ guint type; /* Iterator: message types */ guint row; /* Attachment for current widget */ guint title_cols; /* Title cols in msgctrl_table */ guint title_rows; /* Title rows in msgctrl_table */ /* The cols/rows will describe the * prefilled table data already in * msgctrl_table when first loaded * from the .ui file containing it. */ /* * Get the window pointer and a pointer to the tree of widgets it contains */ msgctrl_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_window")); g_signal_connect((gpointer) msgctrl_window, "delete_event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); /* * Initialize the spinbutton pointers. */ buffer_control.count.ptr = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_spinbutton_count")); buffer_control.timer.ptr = GTK_WIDGET(gtk_builder_get_object(dialog_xml,"msgctrl_spinbutton_timer")); /* * Locate the table widget to fill with controls and its structure. */ msgctrl_table = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_table")); table = GTK_TABLE(msgctrl_table); /* * How many title rows were set up in the table? The title rows are the * non-empty rows. Row numbers are zero-based. IMPORTANT: It is assumed * any row with at least one widget has widgets in all columns. WARNING: * This assumption is unwise if client layouts begin to be implemented to * have fewer message panes than the code supports! */ gtk_table_get_size(table, &title_rows, &title_cols); /* * The table is defined in the dialog created with the design tool, but * the dimensions of the table are not known at design time, so it must be * resized and built up at run-time. * * The table columns are: message type description, message buffer * enable, and one enable per message pane supported by the client code. * The client layout might not support all of the panes, but all of them * will be put into the table. * * The table rows are: the header rows + the number of message types that * the client and server support. We assume the XML file designer did * properly set up the header rows. Since MSG_TYPE_LAST is 1 more than * the actual number of types, and since title_rows is one less than the * actual number of header rows, they balance out when added together. */ gtk_table_resize(table, (guint)(MSG_TYPE_LAST + title_rows), (guint)(1 + 1 + NUM_TEXT_VIEWS)); /* * Now we need to put labels and checkboxes in each of the empty rows and * initialize the state of the checkboxes to match the default settings. * It helps if we change title_rows to a one-based number. Walk through * each message type and set the corresponding row of the table it needs * to go with. type is one-based. The msgctrl_defaults and _widget * arrays are zero based. */ title_rows += 1; for (type = 0; type < MSG_TYPE_LAST - 1; type += 1) { row = type + title_rows; /* * The message type description. Just put the the message type name * in a label, left-justified with some padding to keep it away from * the dialog frame and perhaps the neighboring checkbox. */ widget = gtk_label_new(msgctrl_defaults[type].description); gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f); gtk_misc_set_padding(GTK_MISC(widget), 2, 0); gtk_table_attach_defaults(table, widget, 0, 1, row, row + 1); gtk_widget_show(widget); /* * The buffer enable/disable. Display a check box that is preset to * the built-in default setting. */ msgctrl_widgets[type].buffer.ptr = gtk_check_button_new(); gtk_table_attach_defaults( table, msgctrl_widgets[type].buffer.ptr, 1, 2, row, row + 1); gtk_widget_show(msgctrl_widgets[type].buffer.ptr); /* * The message pane routings. Display a check box that is preset to * the built in defaults. */ /** * @todo Panes that are unsupported in the current layout should * always have their routing disabled, and should disallow user * interaction with the control but this logic is not yet implemented. */ for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { msgctrl_widgets[type].pane[pane].ptr = gtk_check_button_new(); gtk_table_attach_defaults( table, msgctrl_widgets[type].pane[pane].ptr, pane + 2, pane + 3, row, row + 1); gtk_widget_show(msgctrl_widgets[type].pane[pane].ptr); } } /* * Initialize the state variables for the checkbox and spinbutton controls * on the message control dialog and then set all the widgets to match the * client defautl settings. */ default_msgctrl_configuration(); load_msgctrl_configuration(); /* * Connect the control's buttons to the appropriate handlers. */ widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_button_save")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_msgctrl_button_save_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_button_load")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_msgctrl_button_load_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_button_defaults")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_msgctrl_button_defaults_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_button_apply")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_msgctrl_button_apply_clicked), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "msgctrl_button_close")); g_signal_connect((gpointer) widget, "clicked", G_CALLBACK(on_msgctrl_button_close_clicked), NULL); } /** * Update the state of the message control dialog so the configuration matches * the currently selected settings. Do not call this before msgctrl_widgets[] * is initialized. It also really only makes sense to call it if changes have * been made to msgctrl_widgets[]. */ void update_msgctrl_configuration(void) { guint pane; /* Client-supported message pane */ guint type; /* Message type */ gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_control.count.ptr), (gdouble) buffer_control.count.state); gtk_spin_button_set_value( GTK_SPIN_BUTTON(buffer_control.timer.ptr), (gdouble) buffer_control.timer.state); for (type = 0; type < MSG_TYPE_LAST - 1; type += 1) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(msgctrl_widgets[type].buffer.ptr), msgctrl_widgets[type].buffer.state); for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(msgctrl_widgets[type].pane[pane].ptr), msgctrl_widgets[type].pane[pane].state); } } } /** * Applies the current state of the checkboxes to the msgctrl_widgets state * variables and saves the settings to disk so the configuration persists * across client sessions. */ void save_msgctrl_configuration(void) { char pathbuf[MAX_BUF]; /* Buffer for a save file path name */ char textbuf[MAX_BUF]; /* Buffer for output to save file */ FILE* fptr; /* Message Control savefile pointer */ guint pane; /* Client-supported message pane */ guint type; /* Message type */ read_msgctrl_configuration(); /* Apply the displayed settings 1st */ snprintf(pathbuf, sizeof(pathbuf), "%s/msgs", config_dir); if (make_path_to_file(pathbuf) == -1) { LOG(LOG_WARNING, "gtk-v2::save_msgctrl_configuration","Error creating %s",pathbuf); snprintf(textbuf, sizeof(textbuf), "Error creating %s, Message Control settings not saved.",pathbuf); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, textbuf); return; } if ((fptr = fopen(pathbuf, "w")) == NULL) { snprintf(textbuf, sizeof(textbuf), "Error opening %s, Message Control settings not saved.", pathbuf); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, textbuf); return; } /* * It might be best to check the status of all writes, but it is not done. */ fprintf(fptr, "# Message Control System Configuration\n"); fprintf(fptr, "#\n"); fprintf(fptr, "# Count: 1-96\n"); fprintf(fptr, "#\n"); fprintf(fptr, "C %u\n", buffer_control.count.state); fprintf(fptr, "#\n"); fprintf(fptr, "# Timer: 1-96 (8 ~= one second)\n"); fprintf(fptr, "#\n"); fprintf(fptr, "T %u\n", buffer_control.timer.state); fprintf(fptr, "#\n"); fprintf(fptr, "# type, buffer, pane[0], pane[1]...\n"); fprintf(fptr, "# Do not edit the 'type' field.\n"); fprintf(fptr, "# 0 == disable; 1 == enable.\n"); fprintf(fptr, "#\n"); for (type = 0; type < MSG_TYPE_LAST - 1; type += 1) { fprintf( fptr, "M %02d %d ", type+1, msgctrl_widgets[type].buffer.state); for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { fprintf(fptr, "%d ", msgctrl_widgets[type].pane[pane].state); } fprintf(fptr, "\n"); } fprintf(fptr, "#\n# End of Message Control System Configuration\n"); fclose(fptr); LOG(LOG_DEBUG, "gtk-v2::save_msgctrl_configuration", "Message control settings saved to '%s'", pathbuf); snprintf(textbuf, sizeof(textbuf), "Message control settings saved!"); draw_ext_info(NDI_BLUE, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, textbuf); } /** * Setup the state of the message control dialog so the configuration matches * a previously saved configuration. */ void load_msgctrl_configuration(void) { char pathbuf[MAX_BUF]; /* Buffer for a save file path name */ char textbuf[MAX_BUF]; /* Buffer for input from save file */ char recordtype; /* Savefile data entry type found */ char* cptr; /* Pointer used when reading data */ FILE* fptr; /* Message Control savefile pointer */ guint pane; /* Client-supported message pane */ guint type; /* Message type */ guint error; /* Savefile parsing status */ message_control_t statebuf; /* Holding area for savefile values */ buffer_parameter_t countbuf; /* Holding area for savefile values */ buffer_parameter_t timerbuf; /* Holding area for savefile values */ guint cvalid, tvalid, mvalid; /* Counts the valid entries found */ snprintf(pathbuf, sizeof(pathbuf), "%s/msgs", config_dir); if ((fptr = fopen(pathbuf, "r")) == NULL) { snprintf(textbuf, sizeof(textbuf), "Error opening %s, Message Control settings not loaded.",pathbuf); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, textbuf); return; } /* * When we parse the file we buffer each entire record before any values * are applied to the client message control configuration. If any * problems are found at all, the entire record is skipped and the file * is reported as corrupt. Even if individual records are corrupt, the * rest of the file is processed. * * If more than one record for the same error type exists the last one is * used, but if too many records are found the file is reported as corrupt * even though it accepts all the data. */ error = 0; cvalid = 0; tvalid = 0; mvalid = 0; while(fgets(textbuf, MAX_BUF-1, fptr) != NULL) { if (textbuf[0] == '#' || textbuf[0] == '\n') { continue; } /* * Identify the savefile record type found. */ cptr = strtok(textbuf, "\t "); if ((cptr == NULL) || ((*cptr != 'C') && (*cptr != 'T') && (*cptr != 'M'))) { error += 1; continue; } recordtype = *cptr; /* * Process the following fields by record type */ if (recordtype == 'C') { cptr = strtok(NULL, "\n"); if ((cptr == NULL) || (sscanf(cptr, "%u", &countbuf.state) != 1) || (countbuf.state < 1) || (countbuf.state > 96)) { error += 1; continue; } } if (recordtype == 'T') { cptr = strtok(NULL, "\n"); if ((cptr == NULL) || (sscanf(cptr, "%u", &timerbuf.state) != 1) || (timerbuf.state < 1) || (timerbuf.state > 96)) { error += 1; continue; } } if (recordtype == 'M') { cptr = strtok(NULL, "\t "); if ((cptr == NULL) || (sscanf(cptr, "%d", &type) != 1) || (type < 1) || (type >= MSG_TYPE_LAST)) { error += 1; continue; } cptr = strtok(NULL, "\t "); if ((cptr == NULL) || (sscanf(cptr, "%d", &statebuf.buffer.state) != 1) || (statebuf.buffer.state < 0) || (statebuf.buffer.state > 1)) { error += 1; continue; } for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { cptr = strtok(NULL, "\t "); if ((cptr == NULL) || (sscanf(cptr, "%d", &statebuf.pane[pane].state) != 1) || (statebuf.pane[pane].state < 0) || (statebuf.pane[pane].state > 1)) { error += 1; continue; } } /* * Ignore the record if it has too many fields. This might be a * bit strict, but it does help enforce the file integrity in the * event that the the number of supported panels increases in the * future. */ cptr = strtok(NULL, "\n"); if (cptr != NULL) { error += 1; continue; } } /* * Remember, type is one-based, but the index into an array is zero- * based, so adjust type. Also, since the record parsed out fine, * increment the number of valid records found. Apply all the values * read to the buffer_control structure and msgctrl_widgets[] array so * the dialog can be updated when all data has been read. */ if (recordtype == 'C') { buffer_control.count.state = countbuf.state; cvalid += 1; } if (recordtype == 'T') { buffer_control.timer.state = timerbuf.state; tvalid += 1; } if (recordtype == 'M') { type -= 1; msgctrl_widgets[type].buffer.state = statebuf.buffer.state; for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { msgctrl_widgets[type].pane[pane].state = statebuf.pane[pane].state; } mvalid += 1; } } fclose(fptr); /* * If there was any oddity with the data file, report it as corrupted even * if some of the values were used. A corrupted file can be uncorrupted * by loading it and saving it again. A found value is needed for count, * timer, and each message type. */ if ((error > 0) || (cvalid != 1) || (tvalid != 1) || (mvalid != MSG_TYPE_LAST - 1)) { snprintf(textbuf, sizeof(textbuf), "Corrupted Message Control settings in %s.", pathbuf); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, textbuf); LOG(LOG_ERROR, "gtk-v2::load_msgctrl_configuration", "Error loading %s. %s\n", pathbuf, textbuf); } /* * If any data was accepted from the save file, report that settings were * loaded. Apply the loaded values to the Message Control dialog checkbox * widgets. so they reflect the states that were previously saved. */ if ((cvalid + tvalid + mvalid) > 0) { LOG(LOG_DEBUG, "gtk-v2::load_msgctrl_configuration", "Message control settings loaded from '%s'", pathbuf); update_msgctrl_configuration(); /* Update checkboxes w/ loaded data */ } } /** * Setup the state of the message control dialog so the configuration matches * the default settings built in to the client. * * Iterate through each message type. For each, copy the built-in client * default to the Message Control dialog state variables. All supported * defaults are copied, not just the ones supported by the layout. */ void default_msgctrl_configuration(void) { guint pane; /* Client-supported message pane */ guint type; /* Message type */ buffer_control.count.state = (guint) buffer_control.count.default_state; buffer_control.timer.state = (guint) buffer_control.timer.default_state; for (type = 0; type < MSG_TYPE_LAST - 1; type += 1) { msgctrl_widgets[type].buffer.state = msgctrl_defaults[type].buffer; for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { msgctrl_widgets[type].pane[pane].state = msgctrl_defaults[type].pane[pane]; } } update_msgctrl_configuration(); } /** * Reads the state of the message control dialog and applies the settings to * the msgctrl_widgets[] state variables that control the message routing * and duplicate suppression system. */ void read_msgctrl_configuration(void) { guint pane; /* Client-supported message pane */ guint type; /* Message type */ buffer_control.count.state = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(buffer_control.count.ptr)); buffer_control.timer.state = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(buffer_control.timer.ptr)); /* * Iterate through each message type. For each, record the value of the * message duplicate suppression checkbox, and also obtain the routing * settings for all client supported panels (even if the layout does not * support them all. */ for (type = 0; type < MSG_TYPE_LAST - 1; type += 1) { msgctrl_widgets[type].buffer.state = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(msgctrl_widgets[type].buffer.ptr)); for (pane = 0; pane < NUM_TEXT_VIEWS; pane += 1) { msgctrl_widgets[type].pane[pane].state = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(msgctrl_widgets[type].pane[pane].ptr)); } } } /** * When the message control dialog save button is pressed, the currently shown * settings are applied for immediate use and they are saved to disk so the * settings persist across client sessions. Saved settings automatically * load and apply when the client is started. * * @param button * @param user_data */ void on_msgctrl_button_save_clicked (GtkButton *button, gpointer user_data) { read_msgctrl_configuration(); save_msgctrl_configuration(); } /** * When the message control dialog load button is pressed, the settings last * saved are restored and applied. It may be used to "undo" both applied and * unapplied setting changes. * * @param button * @param user_data */ void on_msgctrl_button_load_clicked (GtkButton *button, gpointer user_data) { load_msgctrl_configuration(); } /** * When the message control dialog defaults button is pressed, the default * settings built into the client are restored and applied. * * @param button * @param user_data */ void on_msgctrl_button_defaults_clicked (GtkButton *button, gpointer user_data) { default_msgctrl_configuration(); } /** * When the message control dialog apply button is pressed, the currently * displayed settings are applied. The dialog is not dismissed, but remains * open for further adjustments to be made. * * @param button * @param user_data */ void on_msgctrl_button_apply_clicked (GtkButton *button, gpointer user_data) { read_msgctrl_configuration(); } /** * When the message control dialog close button is pressed, the currently * displayed settings are applied and the dialog is dismissed. * * @param button * @param user_data */ void on_msgctrl_button_close_clicked (GtkButton *button, gpointer user_data) { read_msgctrl_configuration(); gtk_widget_hide(msgctrl_window); } /** * Shows the message control dialog when the menu item is activated. The * settings shown on the dialog when it is activated are the settings * currently in use. * * @param menuitem * @param user_data */ void on_msgctrl_activate (GtkMenuItem *menuitem, gpointer user_data) { gtk_widget_show(msgctrl_window); } crossfire-client-1.75.3/gtk-v2/src/sound.h000644 001751 001751 00000000551 14110265004 021136 0ustar00kevinzkevinz000000 000000 #ifndef _SOUND_SRC_COMMON_H #define _SOUND_SRC_COMMON_H extern int cf_snd_init(); extern void cf_snd_exit(); extern void cf_play_music(const char *music_name); extern void cf_play_sound(gint8 x, gint8 y, guint8 dir, guint8 vol, guint8 type, char const sound[static 1], char const source[static 1]); #endif crossfire-client-1.75.3/gtk-v2/src/cfsndserv.c000644 001751 001751 00000013614 14443375155 022024 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file sound-src/cfsndserv.c * Implements a server for sound support in the client using SDL_mixer. */ #include "client.h" #include #include #include #include "client-vala.h" #include "sound.h" typedef struct sound_settings { int buflen; //< how big the buffers should be int max_chunk; //< number of sounds that can be played at the same time } sound_settings; static Mix_Music *music = NULL; static sound_settings settings = { 512, 4 }; static GHashTable* chunk_cache; static GHashTable* sounds; /** * Initialize the sound subsystem. * * Currently, this means calling SDL_Init() and Mix_OpenAudio(). * * @return Zero on success, anything else on failure. */ static int init_audio() { if (SDL_Init(SDL_INIT_AUDIO) == -1) { fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); return 1; } if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, settings.buflen)) { fprintf(stderr, "Mix_OpenAudio: %s\n", SDL_GetError()); return 2; } /* Determine if OGG is supported. */ const int mix_flags = MIX_INIT_OGG; int mix_init = Mix_Init(mix_flags); if ((mix_init & mix_flags) != mix_flags) { fprintf(stderr, "OGG support in SDL_mixer is required for sound; aborting!\n"); return 3; } /* Allocate channels and resize buffers accordingly. */ Mix_AllocateChannels(settings.max_chunk); return 0; } /** * Initialize sound server. * * Initialize resource paths, load sound definitions, and ready the sound * subsystem. * * @return Zero on success, anything else on failure. */ int cf_snd_init() { /* Set $CF_SOUND_DIR to something reasonable, if not already set. */ if (!g_setenv("CF_SOUND_DIR", CF_SOUND_DIR, FALSE)) { perror("Couldn't set $CF_SOUND_DIR"); return -1; } /* Initialize sound definitions. */ chunk_cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (void *)Mix_FreeChunk); sounds = load_snd_config(); if (!sounds) { return -1; } /* Initialize audio library. */ if (init_audio()) { return -1; } return 0; } static Mix_Chunk* load_chunk(char const name[static 1]) { Mix_Chunk* chunk = g_hash_table_lookup(chunk_cache, name); if (chunk != NULL) { return chunk; } char path[MAXSOCKBUF]; snprintf(path, sizeof(path), "%s/%s", g_getenv("CF_SOUND_DIR"), name); chunk = Mix_LoadWAV(path); if (!chunk) { fprintf(stderr, "Could not load sound from '%s': %s\n", path, SDL_GetError()); return NULL; } g_hash_table_insert(chunk_cache, &name, chunk); return chunk; } /** * Play a sound effect using the SDL_mixer sound system. * * @param sound The sound to play. * @param type 0 for normal sounds, 1 for spell_sounds. * @param x Offset (assumed from player) to play sound used to * determine value and left vs. right speaker balance. * @param y Offset (assumed from player) to play sound used to * determine value and left vs. right speaker balance. */ void cf_play_sound(gint8 x, gint8 y, guint8 dir, guint8 vol, guint8 type, char const sound[static 1], char const source[static 1]) { LOG(LOG_DEBUG, "cf_play_sound", "Playing sound2 x=%hhd y=%hhd dir=%hhd volume=%hhd type=%hhd sound=%s " "source=%s", x, y, dir, vol, type, sound, source); SoundInfo* si = g_hash_table_lookup(sounds, sound); if (si == NULL) { LOG(LOG_WARNING, "cf_play_sound", "sound not defined: %s", sound); return; } Mix_Chunk* chunk = load_chunk(si->file); if (chunk == NULL) { return; } Mix_VolumeChunk(chunk, si->vol * MIX_MAX_VOLUME / 100); int channel = Mix_GroupAvailable(-1); if (channel == -1) { g_warning("No free channels available to play sound"); return; } Mix_Volume(channel, vol * MIX_MAX_VOLUME / 100); Mix_PlayChannel(channel, chunk, 0); } static bool music_is_different(char const music[static 1]) { static char last_played[MAXSOCKBUF] = ""; if (strcmp(music, last_played) != 0) { g_strlcpy(last_played, music, MAXSOCKBUF); return true; } return false; } /** * Play a music file. * * @param name Name of the song to play, without file paths or extensions. */ void cf_play_music(const char* music_name) { LOG(LOG_DEBUG, "cf_play_music", "\"%s\"", music_name); if (!music_is_different(music_name)) { return; } Mix_FadeOutMusic(500); if (music != NULL) { Mix_FreeMusic(music); music = NULL; } if (strcmp(music_name, "NONE") == 0) { return; } char path[MAXSOCKBUF]; snprintf(path, sizeof(path), "%s/music/%s.ogg", g_getenv("CF_SOUND_DIR"), music_name); music = Mix_LoadMUS(path); if (!music) { fprintf(stderr, "Could not load music: %s\n", Mix_GetError()); return; } Mix_VolumeMusic(MIX_MAX_VOLUME * 3/4); Mix_FadeInMusic(music, -1, 500); } void cf_snd_exit() { Mix_HaltMusic(); Mix_FreeMusic(music); /* Halt all channels that are playing and free remaining samples. */ Mix_HaltChannel(-1); g_hash_table_destroy(chunk_cache); g_hash_table_destroy(sounds); /* Call Mix_Quit() for each time Mix_Init() was called. */ while(Mix_Init(0)) { Mix_Quit(); } } crossfire-client-1.75.3/gtk-v2/src/image.h000644 001751 001751 00000004314 14323707640 021106 0ustar00kevinzkevinz000000 000000 /* * char *rcsid_gtk2_image_h = * "$Id$"; */ /* Crossfire client, a client program for the crossfire program. Copyright (C) 2005-2008,2010 Mark Wedel & Crossfire Development Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author can be reached via e-mail to crossfire@metalforge.org */ /** * @file image.h * Pixmap data. This is abstracted in the sense that the code here does not * care what the data points to (hence the void). The module using this data * should know whether it is these point to png data or image data of whatever * form. The module is not required to use all these fields - as png data * includes transparancy, it will generally not use the mask fields and instead * just put its data into the appropriate image fields. * * As images can now be of variable size (and potentially re-sized), the size * information is stored here. */ #define DEFAULT_IMAGE_SIZE 32 #define MAXPIXMAPNUM 10000 typedef struct PixmapInfo { /* Icons, used in the inventory tree view */ /* Scaled according to inventory scale config */ GdkPixbuf *icon_image; guint16 icon_width, icon_height; /* "Full icons", used in the spell list and inventory table view */ /* Same as above, but not scaled */ GdkPixbuf *full_icon_image; guint16 full_icon_width, full_icon_height; /* Map images */ void *map_image; // same as full_icon_image, but as a cairo_surface_t guint16 smooth_face; /**< A face used for smoothing with this face. */ } PixmapInfo; extern PixmapInfo *pixmaps[MAXPIXMAPNUM]; extern int have_new_image; crossfire-client-1.75.3/gtk-v2/src/metaserver.c000644 001751 001751 00000023017 14323707640 022175 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file gtk-v2/src/metaserver.c * Supports the client's metaserver dialog used to connect to available * servers. */ #include "client.h" #include #include #include "image.h" #include "main.h" #include "metaserver.h" #include "gtk2proto.h" static GtkWidget *treeview_metaserver, *metaserver_button, *metaserver_status, *metaserver_entry; static GtkListStore *store_metaserver; static GtkTreeSelection *metaserver_selection; enum { LIST_HOSTNAME, LIST_IPADDR, LIST_PLAYERS, LIST_VERSION, LIST_COMMENT }; extern char* last_server; static void on_button_refresh(GtkButton *button, gpointer user_data); /** * Copy the selected server to the server entry box. */ static gboolean on_selection_changed() { GtkTreeModel *model; GtkTreeIter iter; char *selection; if (gtk_tree_selection_get_selected(metaserver_selection, &model, &iter)) { gtk_tree_model_get(model, &iter, LIST_HOSTNAME, &selection, -1); gtk_entry_set_text(GTK_ENTRY(metaserver_entry), selection); g_free(selection); gtk_widget_set_sensitive(metaserver_button, TRUE); } return FALSE; } /** * Activate the connect button and unselect servers if keys are pressed to * enter a server name. */ static gboolean on_server_entry_changed() { if (gtk_entry_get_text_length(GTK_ENTRY(metaserver_entry)) != 0) { gtk_tree_selection_unselect_all(metaserver_selection); gtk_widget_set_sensitive(metaserver_button, TRUE); } else { gtk_widget_set_sensitive(metaserver_button, FALSE); } return FALSE; } /** * Initialize the metaserver user interface. */ void metaserver_ui_init() { GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkWidget *widget; treeview_metaserver = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "treeview_metaserver")); metaserver_status = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "metaserver_status")); metaserver_button = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "metaserver_select")); // Server list g_signal_connect(treeview_metaserver, "row_activated", G_CALLBACK(on_metaserver_select_clicked), NULL); // Server entry text box metaserver_entry = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "metaserver_text_entry")); g_signal_connect(metaserver_entry, "key_release_event", G_CALLBACK(on_server_entry_changed), NULL); g_signal_connect(metaserver_button, "clicked", G_CALLBACK(on_metaserver_select_clicked), NULL); // Quit button widget = GTK_WIDGET( gtk_builder_get_object(dialog_xml, "button_metaserver_quit")); g_signal_connect(widget, "clicked", G_CALLBACK(on_button_metaserver_quit_pressed), NULL); // Refresh button g_signal_connect( GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_refresh")), "clicked", G_CALLBACK(on_button_refresh), NULL); // Initialize server list store_metaserver = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING); gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_metaserver), GTK_TREE_MODEL(store_metaserver)); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Server", renderer, "text", LIST_HOSTNAME, NULL); gtk_tree_view_column_set_sort_column_id(column, LIST_HOSTNAME); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_metaserver), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Players", renderer, "text", LIST_PLAYERS, NULL); gtk_tree_view_column_set_sort_column_id(column, LIST_PLAYERS); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_metaserver), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Version", renderer, "text", LIST_VERSION, NULL); gtk_tree_view_column_set_sort_column_id(column, LIST_VERSION); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_metaserver), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( "Description", renderer, "text", LIST_COMMENT, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_metaserver), column); metaserver_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview_metaserver)); gtk_tree_selection_set_mode(metaserver_selection, GTK_SELECTION_BROWSE); g_signal_connect(metaserver_selection, "changed", G_CALLBACK(on_selection_changed), NULL); widget = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_preferences")); g_signal_connect((gpointer)widget, "clicked", G_CALLBACK(on_configure_activate), NULL); } /** * Check if the given server is already in the server list. */ static bool server_exists(const char *server) { GtkTreeModel *model = GTK_TREE_MODEL(store_metaserver); GtkTreeIter iter; bool valid = gtk_tree_model_get_iter_first(model, &iter); while (valid) { char *name; gtk_tree_model_get(GTK_TREE_MODEL(store_metaserver), &iter, LIST_HOSTNAME, &name, -1); if (strcmp(server, name) == 0) { return true; } g_free(name); valid = gtk_tree_model_iter_next(model, &iter); } return false; } static void server_add(char *server, int update, int players, char *version, char *comment, bool compatible) { if (compatible && !server_exists(server)) { GtkTreeIter iter; gtk_list_store_append(store_metaserver, &iter); gtk_list_store_set(store_metaserver, &iter, LIST_HOSTNAME, server, LIST_IPADDR, server, LIST_PLAYERS, players, LIST_VERSION, version, LIST_COMMENT, comment, -1); } } /** * Wrapper on top of ms_fetch() for a GThread. * @return NULL */ static gpointer server_fetch() { ms_fetch(server_add); return NULL; } static void metaserver_refresh(void) { gtk_list_store_clear(store_metaserver); #ifdef HAVE_CURL_CURL_H // Start fetching server information in a separate thread. g_thread_new("server_fetch", server_fetch, NULL); gtk_label_set_text(GTK_LABEL(metaserver_status), ""); #else gtk_widget_set_sensitive(GTK_WIDGET(treeview_metaserver), FALSE); gtk_label_set_text(GTK_LABEL(metaserver_status), "This client doesn't have metaserver support."); #endif } static void on_button_refresh(GtkButton *button, gpointer user_data) { metaserver_refresh(); } /** * Constructs the metaserver dialog and handles metaserver selection. If the * player has a servers.cache file in their .crossfire folder, the cached * server list is added to the contents of the metaserver dialog. */ void metaserver_show_prompt() { gtk_notebook_set_current_page(main_notebook, 0); gtk_widget_grab_default(metaserver_button); gtk_entry_set_text(GTK_ENTRY(metaserver_entry), last_server); // Disable connect button if there is no text in the server entry box. on_server_entry_changed(); metaserver_refresh(); cpl.input_state = Metaserver_Select; } /** * Connect to a server with the given hostname and optional port number. * * @param name The DNS name of a server to connect to. If the server operates * on a non-standard port, a colon and the port number is appended * to the DNS name. For example: localhost:8000 */ static void metaserver_connect_to(const char *name) { char *name_dup = g_strdup(name); g_strstrip(name_dup); char buf[256]; /* Set client status and update GUI before continuing. */ snprintf(buf, sizeof(buf), "Connecting to '%s'...", name_dup); gtk_label_set_text(GTK_LABEL(metaserver_status), buf); gtk_main_iteration(); client_connect(name_dup); if (csocket.fd != NULL) { LOG(LOG_DEBUG, "metaserver_connect_to", "Connected to '%s'!", name_dup); if (last_server != NULL) { g_free(last_server); } last_server = g_strdup(name); save_defaults(); gtk_main_quit(); cpl.input_state = Playing; } else { snprintf(buf, sizeof(buf), "Unable to connect to %s!", name_dup); gtk_label_set_text(GTK_LABEL(metaserver_status), buf); } g_free(name_dup); } /** * Establish a connection with the server when pressing the connect button. * * @param button * @param user_data */ void on_metaserver_select_clicked(GtkButton *button, gpointer user_data) { const char *entry_text = gtk_entry_get_text(GTK_ENTRY(metaserver_entry)); if (*entry_text != '\0') { metaserver_connect_to(entry_text); } } /** * Quits the client application if the quit button is pressed. This is also * used to quit the client if the button's accelerator is pressed. * * @param button * @param user_data */ void on_button_metaserver_quit_pressed(GtkButton *button, gpointer user_data) { on_window_destroy_event(GTK_WIDGET(button), user_data); } crossfire-client-1.75.3/gtk-v2/src/inventory.c000644 001751 001751 00000127461 14444135126 022063 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Draw inventory and 'look' windows */ #include "client.h" #include #include "image.h" #include "main.h" #include "gtk2proto.h" #include "../../pixmaps/all.xpm" #include "../../pixmaps/coin.xpm" #include "../../pixmaps/hand.xpm" #include "../../pixmaps/hand2.xpm" #include "../../pixmaps/lock.xpm" #include "../../pixmaps/mag.xpm" #include "../../pixmaps/nonmag.xpm" #include "../../pixmaps/skull.xpm" #include "../../pixmaps/unlock.xpm" #include "../../pixmaps/unidentified.xpm" GtkWidget *treeview_look; /** Color to use to indicate that an item is applied. */ static const GdkColor applied_color = {0, 50000, 50000, 50000}; static GtkTreeStore *store_look; static GtkWidget *encumbrance_current; static GtkWidget *encumbrance_max; static GtkWidget *inv_notebook; static GtkWidget *inv_table; static double weight_limit; /* * Hopefully, large enough. Trying to do this with g_malloc gets more * complicated because position of elements within the array are important, so * a simple g_realloc won't work. */ #define MAX_INV 2000 static GtkWidget *inv_table_children[MAX_INV]; #define INV_TABLE_AT(x, y, cols) inv_table_children[cols*y + x] /* Different styles we recognize */ enum Styles { Style_Magical = 0, Style_Cursed, Style_Unpaid, Style_Locked, Style_Applied, Style_Last }; /* The name of these styles in the rc file */ static const char *Style_Names[Style_Last] = { "inv_magical", "inv_cursed", "inv_unpaid", "inv_locked", "inv_applied" }; /* Actual styles as loaded. May be null if no style found. */ static GtkStyle *inv_styles[Style_Last]; /* * The basic idea of the NoteBook_Info structure is to hold everything we need * to know about the different inventory notebooks in a module fashion - * instead of hardcoding values, they can be held in the array. */ #define NUM_INV_LISTS 11 #define INV_SHOW_ITEM 0x1 #define INV_SHOW_COLOR 0x2 /** * @enum display_type * Indicate how an inventory tab should be drawn */ enum display_type { INV_TREE, INV_TABLE }; static int num_inv_notebook_pages = 0; typedef struct { const char *name; /**< Name of this page, for the show command */ const char *tooltip; /**< Tooltip for menu */ const char *const *xpm; /**< Icon to draw for the notebook selector */ int(*show_func) (item *it); /**< Function that takes an item and returns * INV_SHOW_* above on whether to show this * item and if it should be shown in color */ enum display_type type; /**< Type of widget */ GtkWidget *treeview; /**< treeview widget for this tab */ } Notebook_Info; static GtkTreeStore *treestore; /**< store of data for treeview */ /* Prototypes for static functions */ static void on_switch_page(GtkNotebook *notebook, gpointer *page, guint page_num, gpointer user_data); static int show_all(item *it) { return INV_SHOW_ITEM | INV_SHOW_COLOR; } static int show_applied(item *it) { return (it->applied ? INV_SHOW_ITEM : 0); } static int show_unapplied(item *it) { return (it->applied ? 0 : INV_SHOW_ITEM); } static int show_unpaid(item *it) { return (it->unpaid ? INV_SHOW_ITEM : 0); } static int show_cursed(item *it) { return ((it->cursed | it->damned) ? INV_SHOW_ITEM : 0); } static int show_magical(item *it) { return (it->magical ? INV_SHOW_ITEM : 0); } static int show_nonmagical(item *it) { return (it->magical ? 0 : INV_SHOW_ITEM); } static int show_locked(item *it) { return (it->locked ? (INV_SHOW_ITEM | INV_SHOW_COLOR) : 0); } static int show_unlocked(item *it) { // Show open containers, even if locked, to make moving items easier. return ((it->locked && !it->open) ? 0 : (INV_SHOW_ITEM | INV_SHOW_COLOR)); } static int show_unidentified(item *it) { return ((it->flagsval & F_UNIDENTIFIED) ? INV_SHOW_ITEM : 0); } static Notebook_Info inv_notebooks[NUM_INV_LISTS] = { {"all", "All", all_xpm, show_all, INV_TREE}, {"applied", "Applied", hand_xpm, show_applied, INV_TREE}, {"unapplied", "Unapplied", hand2_xpm, show_unapplied, INV_TREE}, {"unpaid", "Unpaid", coin_xpm, show_unpaid, INV_TREE}, {"cursed", "Cursed", skull_xpm, show_cursed, INV_TREE}, {"magical", "Magical", mag_xpm, show_magical, INV_TREE}, {"nonmagical", "Non-magical", nonmag_xpm, show_nonmagical, INV_TREE}, {"locked", "Locked", lock_xpm, show_locked, INV_TREE}, {"unlocked", "Unlocked", unlock_xpm, show_unlocked, INV_TREE}, {"unidentified", "Unidentified", unidentified_xpm, show_unidentified, INV_TREE}, {"icons", "Icon View", NULL, show_all, INV_TABLE} }; /** * @enum list_property * Constants used to refer to columns in the inventory list view */ enum list_property { LIST_NONE, LIST_ICON, LIST_NAME, LIST_WEIGHT, LIST_OBJECT, LIST_BACKGROUND, LIST_TYPE, LIST_BASENAME, LIST_FOREGROUND, LIST_FONT, LIST_NUM_COLUMNS }; /** * @enum item_env * Describe where an item is. These constants must be kept as-is for use in * a few bitwise operations. */ enum item_env { ITEM_INVENTORY = 0x1, ITEM_GROUND = 0x2, ITEM_IN_CONTAINER = 0x4 }; /** * Returns information on the environment of the item, using the return values * below. Note that there should never be a case where both ITEM_GROUND and * ITEM_INVENTORY are returned, but I prefer a more active approach in * returning actual values and not presuming that lack of value means it is in * the other location. * * @param it * @return */ static int get_item_env(item *it) { if (it->env == cpl.ob) { return ITEM_INVENTORY; } if (it->env == cpl.below) { return ITEM_GROUND; } if (it->env == NULL) { return 0; } return (ITEM_IN_CONTAINER | get_item_env(it->env)); } static void list_item_drop(item *tmp); static void ma_examine(GtkWidget *widget, item *tmp) { client_send_examine(tmp->tag); } static void ma_apply(GtkWidget *widget, item *tmp) { client_send_apply(tmp->tag); } static void ma_mark(GtkWidget *widget, item *tmp) { send_mark_obj(tmp); } static void ma_lock(GtkWidget *widget, item *tmp) { toggle_locked(tmp); } static void ma_drop(GtkWidget *widget, item *tmp) { list_item_drop(tmp); } static void show_item_menu(GdkEventButton *event, item *tmp) { GtkWidget *menu = gtk_menu_new(); GtkWidget *mi_examine = gtk_menu_item_new_with_mnemonic("_Examine"); GtkWidget *mi_apply = gtk_menu_item_new_with_mnemonic("_Apply"); GtkWidget *mi_mark = gtk_menu_item_new_with_mnemonic("_Mark"); GtkWidget *mi_lock; if (tmp->locked) { mi_lock = gtk_menu_item_new_with_mnemonic("Un_lock"); } else { mi_lock = gtk_menu_item_new_with_mnemonic("_Lock"); } GtkWidget *mi_drop; gchar *drop_action = tmp->env == cpl.ob ? "_Drop" : "_Pick Up"; if (cpl.count != 0) { gchar *drop_label; drop_label = g_strdup_printf("%s %d", drop_action, cpl.count); mi_drop = gtk_menu_item_new_with_mnemonic(drop_label); g_free(drop_label); } else { mi_drop = gtk_menu_item_new_with_mnemonic(drop_action); } gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_examine); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_apply); if (tmp->env == cpl.ob) { // In player's inventory gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_mark); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_lock); } gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi_drop); g_signal_connect(mi_examine, "activate", G_CALLBACK(ma_examine), tmp); g_signal_connect(mi_apply, "activate", G_CALLBACK(ma_apply), tmp); g_signal_connect(mi_mark, "activate", G_CALLBACK(ma_mark), tmp); g_signal_connect(mi_lock, "activate", G_CALLBACK(ma_lock), tmp); g_signal_connect(mi_drop, "activate", G_CALLBACK(ma_drop), tmp); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time); } /** * * @param event * @param tmp */ static void list_item_action(GdkEventButton *event, item *tmp) { /* It'd sure be nice if these weren't hardcoded values for button and * shift presses. */ if (event->button == 1) { // primary/left mouse button if (event->state & GDK_SHIFT_MASK) { toggle_locked(tmp); } else { if (use_config[CONFIG_INV_MENU]) { show_item_menu(event, tmp); } else { client_send_examine(tmp->tag); } } } else if (event->button == 2) { // middle mouse button /* Some mice do not have a functioning middle mouse button, * so all the actions here are duplicated elsewhere */ if (event->state & GDK_SHIFT_MASK) { send_mark_obj(tmp); } else { client_send_apply(tmp->tag); } } else if (event->button == 3) { // secondary/right mouse button if (event->state & GDK_SHIFT_MASK) { client_send_apply(tmp->tag); } else if (event->state & GDK_CONTROL_MASK) { send_mark_obj(tmp); } else { list_item_drop(tmp); } } } static void list_item_drop(item *tmp) { int env; /* We need to know where this item is in fact is */ env = get_item_env(tmp); if (tmp->locked) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "This item is locked. To drop it, first unlock by shift+leftclicking on it."); } else { guint32 dest; /* * Figure out where to move the item to. If it is on the ground, * it is moving to the players inventory. If it is in a container, * it is also moving to players inventory. If it is in the players * inventory (not a container) and the player has an open container * in his inventory, move the object to the container (not ground). * Otherwise, it is moving to the ground (dest=0). Have to look at * the item environment, because what list is no longer accurate. */ if (env & (ITEM_GROUND | ITEM_IN_CONTAINER)) { dest = cpl.ob->tag; } else if (env == ITEM_INVENTORY && cpl.container && (get_item_env(cpl.container) == ITEM_INVENTORY || get_item_env(cpl.container) == ITEM_GROUND)) { dest = cpl.container->tag; } else { dest = 0; } client_send_move(dest, tmp->tag, cpl.count); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbutton_count), 0.0); cpl.count = 0; } } /** * Used when a button is pressed on the inventory or look list. The parameters * are those determined by the callback. Note that this function isn't 100% * ideal - some of the events/handling is only relevant for objects in the * inventory and not the look window (eg, locking items). OTOH, maybe it is * just as well that the behaviour is always consistent. * * @param selection * @param model * @param path * @param path_currently_selected * @param userdata * @return FALSE */ static gboolean list_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata) { GtkTreeIter iter; GdkEventButton *event; /* Get the current event so we can know if shift is pressed */ event = (GdkEventButton*)gtk_get_current_event(); if (!event) { LOG(LOG_ERROR, "inventory.c::list_selection_func", "Unable to get event structure\n"); return FALSE; } if (gtk_tree_model_get_iter(model, &iter, path)) { item *tmp; gtk_tree_model_get(model, &iter, LIST_OBJECT, &tmp, -1); if (!tmp) { LOG(LOG_ERROR, "inventory.c::list_selection_func", "Unable to get item structure\n"); return FALSE; } list_item_action(event, tmp); } /* * Don't want the row toggled - our code above handles what we need to do, * so return false. */ return FALSE; } /** * If the player collapses the row with the little icon, we have to unapply the * object for things to work 'sanely' (eg, items not go into the container * * @param treeview * @param iter * @param path * @param user_data */ static void list_row_collapse(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) { GtkTreeModel *model; item *tmp; model = gtk_tree_view_get_model(treeview); gtk_tree_model_get(GTK_TREE_MODEL(model), iter, LIST_OBJECT, &tmp, -1); client_send_apply(tmp->tag); } /** * * @param treeview */ static void setup_list_columns(GtkWidget *treeview) { GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; #if 0 /* * This is a hack to hide the expander column. We do this because access * via containers need to be handled by the apply/unapply mechanism - * otherwise, I think it will be confusing - people 'closing' the container * with the expander arrow and still having things go into/out of the * container. Unfortunat */ renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("", renderer, "text", LIST_NONE, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); gtk_tree_view_column_set_visible(column, FALSE); gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column); #endif renderer = gtk_cell_renderer_pixbuf_new(); /* * Setting the xalign to 0.0 IMO makes the display better. Gtk * automatically resizes the column to make space based on image size, * however, it isn't really aggressive on shrinking it. IMO, it looks * better for the image to always be at the far left - without this * alignment, the image is centered which IMO doesn't always look good. */ g_object_set(G_OBJECT(renderer), "xalign", 0.0, NULL); column = gtk_tree_view_column_new_with_attributes("?", renderer, "pixbuf", LIST_ICON, NULL); /* gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);*/ gtk_tree_view_column_set_min_width(column, image_size); gtk_tree_view_column_set_sort_column_id(column, LIST_TYPE); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", LIST_NAME, NULL); gtk_tree_view_column_set_expand(column, TRUE); gtk_tree_view_column_set_sort_column_id(column, LIST_BASENAME); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column); gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Weight", renderer, "text", LIST_WEIGHT, NULL); /* * At 50, the title was always truncated on some systems. 64 is the * minimum on those systems for it to be possible to avoid truncation at * all. Truncating the title looks cheesy, especially since heavy items * (100+) need the width of the field anyway. If weight pushed off the * edge is a problem, it would be just better to let the user resize or * find a way to allow rendering with a smaller font. */ gtk_tree_view_column_set_min_width(column, 64); gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_column_set_sort_column_id(column, LIST_WEIGHT); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); /* * Really, we never really do selections - clicking on an object causes a * reaction right then. So grab press before the selection and just negate * the selection - that's more efficient than unselection the item after it * was selected. */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); gtk_tree_selection_set_select_function(selection, list_selection_func, NULL, NULL); } /** * Gets the style information for the inventory windows. This is a separate * function because if the user changes styles, it can be nice to re-load the * configuration. The style for the inventory/look is a bit special. That is * because with gtk, styles are widget wide - all rows in the widget would use * the same style. We want to adjust the styles based on other attributes. */ void inventory_get_styles() { int i; GtkStyle *tmp_style; static int has_init = 0; for (i = 0; i < Style_Last; i++) { if (has_init && inv_styles[i]) { g_object_unref(inv_styles[i]); } tmp_style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL, Style_Names[i], G_TYPE_NONE); if (tmp_style) { inv_styles[i] = g_object_ref(tmp_style); } else { LOG(LOG_INFO, "inventory.c::inventory_get_styles", "Unable to find style for %s", Style_Names[i]); inv_styles[i] = NULL; } } has_init = 1; } /** * Set up the inventory viewer. * * @param window_root The client main window. */ void inventory_init(GtkWidget *window_root) { int i; /*inventory_get_styles();*/ inv_notebook = GTK_WIDGET(gtk_builder_get_object(window_xml, "notebook_inv")); treeview_look = GTK_WIDGET(gtk_builder_get_object(window_xml, "treeview_look")); encumbrance_current = GTK_WIDGET(gtk_builder_get_object(window_xml, "label_stat_encumbrance_current")); encumbrance_max = GTK_WIDGET(gtk_builder_get_object(window_xml, "label_stat_encumbrance_max")); inv_table = GTK_WIDGET(gtk_builder_get_object(window_xml, "inv_table")); g_signal_connect((gpointer)inv_notebook, "switch_page", (GCallback)on_switch_page, NULL); g_signal_connect((gpointer) treeview_look, "row_collapsed", (GCallback) list_row_collapse, NULL); memset(inv_table_children, 0, sizeof (GtkWidget *) * MAX_INV); treestore = gtk_tree_store_new(LIST_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_COLOR, PANGO_TYPE_FONT_DESCRIPTION); store_look = gtk_tree_store_new(LIST_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_COLOR, PANGO_TYPE_FONT_DESCRIPTION); gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_look), GTK_TREE_MODEL(store_look)); setup_list_columns(treeview_look); /* * Glade doesn't let us fully realize a treeview widget - we still need to * to do a bunch of customization just like we do for the look window * above. If we have to do all that work, might as well just put it in the * for loop below vs setting up half realized widgets within layout that we * then need to finish setting up. However, that said, we want to be able * to set up other notebooks within layout for perhaps a true list of just * icons. So we presume that any tabs that exist must already be all set * up. We prepend our tabs to the existing tab - this makes the position * of the array of noteboks correspond to actual data in the tabs. */ for (i = 0; i < NUM_INV_LISTS; i++) { GtkWidget *swindow, *image; if (inv_notebooks[i].type == INV_TREE) { swindow = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(swindow); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); image = gtk_image_new_from_pixbuf( gdk_pixbuf_new_from_xpm_data((const char**) inv_notebooks[i].xpm)); if (inv_notebooks[i].tooltip) { GtkWidget *eb; eb = gtk_event_box_new(); gtk_widget_show(eb); gtk_container_add(GTK_CONTAINER(eb), image); gtk_widget_show(image); image = eb; gtk_widget_set_tooltip_text(image, inv_notebooks[i].tooltip); } gtk_notebook_insert_page(GTK_NOTEBOOK(inv_notebook), swindow, image, i); inv_notebooks[i].treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL( treestore)); g_signal_connect((gpointer) inv_notebooks[i].treeview, "row_collapsed", G_CALLBACK(list_row_collapse), NULL); setup_list_columns(inv_notebooks[i].treeview); gtk_widget_show(inv_notebooks[i].treeview); gtk_container_add(GTK_CONTAINER(swindow), inv_notebooks[i].treeview); } } num_inv_notebook_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(inv_notebook)); /* Make sure we are on the first page */ gtk_notebook_set_current_page(GTK_NOTEBOOK(inv_notebook), 0); /* If all the data is set up properly, these should match */ if (num_inv_notebook_pages != NUM_INV_LISTS) { LOG(LOG_ERROR, "inventory.c::inventory_init", "num_inv_notebook_pages (%d) does not match NUM_INV_LISTS(%d)\n", num_inv_notebook_pages, NUM_INV_LISTS); } } /** * Open and close_container are now no-ops - since these are now drawn inline * as treestores, we don't need to update what we are drawing were. and since * the activation of a container will cause the list to be redrawn, don't need * to worry about making an explicit call here. * * @param op */ void close_container(item *op) { } /** * * @param op */ void open_container(item *op) { } /** * * @param params */ void command_show(const char *params) { if (!params) { /* * Shouldn't need to get current page, but next_page call is not * wrapping like the docs claim it should. */ if (gtk_notebook_get_current_page(GTK_NOTEBOOK(inv_notebook)) == num_inv_notebook_pages) { gtk_notebook_set_current_page(GTK_NOTEBOOK(inv_notebook), 0); } else { gtk_notebook_next_page(GTK_NOTEBOOK(inv_notebook)); } } else { char buf[MAX_BUF]; for (int i = 0; i < NUM_INV_LISTS; i++) { if (!strncmp(params, inv_notebooks[i].name, strlen(params))) { gtk_notebook_set_current_page(GTK_NOTEBOOK(inv_notebook), i); return; } } snprintf(buf, sizeof (buf), "Unknown notebook page %s\n", params); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, buf); } } /** * No reason to divide by 1000 everytime we do the display, so do it once and * store it here. * * @param wlim */ void set_weight_limit(guint32 wlim) { weight_limit = wlim / 1000.0; } /** * * @param it * @return a style based on values in it */ static GtkStyle *get_row_style(item *it) { int style; /* Note that this ordering is documented in the sample rc file. * it would be nice if this precedence could be more easily * setable by the end user. */ if (it->unpaid) { style = Style_Unpaid; } else if (it->cursed || it->damned) { style = Style_Cursed; } else if (it->magical) { style = Style_Magical; } else if (it->applied) { style = Style_Applied; } else if (it->locked) { style = Style_Locked; } else { return NULL; /* No matching style */ } return inv_styles[style]; } /*************************************************************************** * Below are the actual guts for drawing the inventory and look windows. * Some quick notes: * 1) The gtk2 widgets (treeview/treemodel) seem noticably slower than the * older clist widgets in gtk1. This is beyond the code below - just * scrolling the window, which is all done internally by gtk, is * quite slow. Seems especially bad when using the scrollwheel. * 2) documentation suggests the detaching the treemodel and re-attaching * it after insertions would be faster. The problem is that this causes * loss of positioning for the scrollbar. Eg, you eat a food in the middle * of your inventory, and then inventory resets to the top of the inventory. * 3) it'd probably be much more efficient if the code could know what changes * are taking place, instead of rebuilding the tree model each time. For * example, if the only thing that changed is the number of of the object, * we can just update the name and weight, and not rebuild the entire list. * This may be doable in the code below by getting data from the tree store * and comparing it against what we want to show - however, figuring out * insertions and removals are more difficult. */ static void remove_object_from_store(item* it, GtkTreeStore* store) { GtkTreeIter iter; gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); while (valid) { item* curr_item; gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, LIST_OBJECT, &curr_item, -1); if (curr_item == it) { gtk_tree_store_remove(store, &iter); break; } valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); } } void item_event_item_deleting(item* it) { switch (get_item_env(it)) { case ITEM_INVENTORY: remove_object_from_store(it, treestore); cpl.ob->inv_updated = 1; break; case ITEM_GROUND: remove_object_from_store(it, store_look); cpl.below->inv_updated = 1; break; } } void item_event_container_clearing(item * container) { } void item_event_item_changed(item * it) { } /** * Adds a row to the treestore. * * @param it the object to add * @param store The TreeStore object. * @param new Returns the iter used/updated for the store * @param parent The parent iter (can be null). If non null, then this creates * a real tree, for things like containers. * @param color If true, do foreground/background colors, otherwise, just black * & white Normally it is set. However, when showing the cursed inv tab, it * doesn't make a lot of sense to show them all in the special color, since * they all meet that special criteria */ static void add_object_to_store(item *it, GtkTreeStore *store, GtkTreeIter *new, GtkTreeIter *parent, int color) { char buf[256], buf1[256]; GdkColor *foreground = NULL, *background = NULL; PangoFontDescription *font = NULL; GtkStyle *row_style; if (it->weight < 0) { strcpy(buf, " "); } else { snprintf(buf, sizeof (buf), "%6.1f", it->nrof * it->weight); } snprintf(buf1, 255, "%s %s", it->d_name, it->flags); if (color) { row_style = get_row_style(it); if (row_style) { /* * Even if the user doesn't define these, we should still get get * defaults from the system. */ foreground = &row_style->text[GTK_STATE_NORMAL]; background = &row_style->base[GTK_STATE_NORMAL]; font = row_style->font_desc; } } gtk_tree_store_append(store, new, parent); /* Acquire an iterator */ gtk_tree_store_set(store, new, LIST_ICON, (GdkPixbuf*) pixmaps[it->face]->icon_image, LIST_NAME, buf1, LIST_WEIGHT, buf, LIST_BACKGROUND, background, LIST_FOREGROUND, foreground, LIST_FONT, font, LIST_OBJECT, it, LIST_TYPE, it->type, LIST_BASENAME, it->s_name, -1); } /** * Draws the objects beneath the player. */ void draw_look_list() { item *tmp; GtkTreeIter iter; /* * List drawing is actually fairly inefficient - we only know globally if * the objects has changed, but have no idea what specific object has * changed. As such, we are forced to basicly redraw the entire list each * time this is called. */ gtk_tree_store_clear(store_look); for (tmp = cpl.below->inv; tmp; tmp = tmp->next) { add_object_to_store(tmp, store_look, &iter, NULL, 1); if ((cpl.container == tmp) && tmp->open) { item *tmp2; GtkTreeIter iter1; GtkTreePath *path; for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->next) { add_object_to_store(tmp2, store_look, &iter1, &iter, 1); } path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_look), &iter); gtk_tree_view_expand_row(GTK_TREE_VIEW(treeview_look), path, FALSE); gtk_tree_path_free(path); } } } /** * Draws the inventory window. tab is the notebook tab we are drawing. Has to * be passed in because the callback sets this before the notebook is updated. * * @param tab */ static void draw_inv_list(int tab) { item *tmp; GtkTreeIter iter; int rowflag; /* * List drawing is actually fairly inefficient - we only know globally if * the objects has changed, but have no idea what specific object has * changed. As such, we are forced to basicly redraw the entire list each * time this is called. */ gtk_tree_store_clear(treestore); for (tmp = cpl.ob->inv; tmp; tmp = tmp->next) { rowflag = inv_notebooks[tab].show_func(tmp); if (!(rowflag & INV_SHOW_ITEM)) { continue; } add_object_to_store(tmp, treestore, &iter, NULL, rowflag & INV_SHOW_COLOR); if ((cpl.container == tmp) && tmp->open) { item *tmp2; GtkTreeIter iter1; GtkTreePath *path; for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->next) { /* * Wonder if we really want this logic for objects in * containers? my thought is yes - being able to see all * cursed objects in the container could be quite useful. * Unfortunately, that doesn't quite work as intended, because * we will only get here if the container object is being * displayed. Since container objects can't be cursed, can't * use that as a filter. */ /* rowflag = inv_notebooks[tab].show_func(tmp2); */ if (!(rowflag & INV_SHOW_ITEM)) { continue; } add_object_to_store(tmp2, treestore, &iter1, &iter, rowflag & INV_SHOW_COLOR); } path = gtk_tree_model_get_path(GTK_TREE_MODEL(treestore), &iter); gtk_tree_view_expand_row(GTK_TREE_VIEW(inv_notebooks[tab].treeview), path, FALSE); gtk_tree_path_free(path); } } } /** * * @param widget * @param event * @param user_data * @return TRUE */ static gboolean drawingarea_inventory_table_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data) { list_item_action(event, (item*) user_data); return TRUE; } static void draw_inv_table_icon(GdkWindow *dst, const void *image) { cairo_t *cr = gdk_cairo_create(dst); gdk_window_clear(dst); gdk_cairo_set_source_pixbuf(cr, (GdkPixbuf *) image, 0, 0); cairo_paint(cr); cairo_destroy(cr); } /** * * @param widget * @param event * @param user_data * @return TRUE */ static gboolean drawingarea_inventory_table_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { item *tmp; if (cpl.ob->inv_updated != 0) { // Delay drawing until inventory is fully updated. This avoids drawing // previously added items that may now be removed, leading to a heap // use-after-free. return TRUE; } tmp = (item*) user_data; /* * Can get cases when switching tabs that we get an expose event before the * list is updated - if so, don't draw stuff we don't have faces for. */ if (tmp->face) { draw_inv_table_icon(gtk_widget_get_window(widget), pixmaps[tmp->face]->icon_image); } return TRUE; } /** * Draws the table of image icons. * * @param animate If non-zero, then this is an animation run - flip the * animation state of the objects, and only draw those that need to be drawn. */ static void draw_inv_table(int animate) { int x, y, rows, columns, num_items, i; static int max_drawn = 0; item *tmp; char buf[256]; gulong handler; num_items = 0; for (tmp = cpl.ob->inv; tmp; tmp = tmp->next) { num_items++; } if (num_items > MAX_INV) { LOG(LOG_ERROR, "draw_inv_table", "Too many items in inventory!"); return; } GtkAllocation size; gtk_widget_get_allocation(inv_table, &size); columns = size.width / image_size; rows = size.height / image_size; if (columns < 1) { // size.width is occasionally very small after a player applies a bed // to reality and the character selection window comes on. This causes // columns = 0 and a divide by zero a few lines later. return; } if (num_items > columns * rows) { rows = num_items / columns; if (num_items % columns) { rows++; } } gtk_table_resize(GTK_TABLE(inv_table), rows, columns); x = 0; y = 0; for (tmp = cpl.ob->inv; tmp; tmp = tmp->next) { if (INV_TABLE_AT(x, y, columns) == NULL) { INV_TABLE_AT(x, y, columns) = gtk_drawing_area_new(); gtk_widget_set_size_request(INV_TABLE_AT(x, y, columns), image_size, image_size); gtk_table_attach(GTK_TABLE(inv_table), INV_TABLE_AT(x, y, columns), x, x + 1, y, y + 1, GTK_FILL, GTK_FILL, 0, 0); } if (animate) { /* This is an object with animations */ if (tmp->animation_id > 0 && tmp->anim_speed) { tmp->last_anim++; /* Time to change the face for this one */ if (tmp->last_anim >= tmp->anim_speed) { tmp->anim_state++; if (tmp->anim_state >= animations[tmp->animation_id].num_animations) { tmp->anim_state = 0; } tmp->face = animations[tmp->animation_id].faces[tmp->anim_state]; tmp->last_anim = 0; draw_inv_table_icon( gtk_widget_get_window(INV_TABLE_AT(x, y, columns)), pixmaps[tmp->face]->icon_image); } } /* On animation run, so don't do any of the remaining logic */ } else { /* * Need to clear out the old signals, since the signals are * effectively stacked - you can have 6 signal handlers tied to the * same function. */ handler = g_signal_handler_find((gpointer) INV_TABLE_AT(x, y, columns), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(drawingarea_inventory_table_button_press_event), NULL); if (handler) { g_signal_handler_disconnect((gpointer) INV_TABLE_AT(x, y, columns), handler); } handler = g_signal_handler_find((gpointer) INV_TABLE_AT(x, y, columns), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(drawingarea_inventory_table_expose_event), NULL); if (handler) { g_signal_handler_disconnect((gpointer) INV_TABLE_AT(x, y, columns), handler); } /* * Not positive precisely what events are needed, but some events * beyond just the button press are necessary for the tooltips to * work. */ gtk_widget_add_events(INV_TABLE_AT(x, y, columns), GDK_ALL_EVENTS_MASK); g_signal_connect((gpointer) INV_TABLE_AT(x, y, columns), "button_press_event", G_CALLBACK(drawingarea_inventory_table_button_press_event), tmp); g_signal_connect((gpointer) INV_TABLE_AT(x, y, columns), "expose_event", G_CALLBACK(drawingarea_inventory_table_expose_event), tmp); /* Draw the inventory icon image to the table. */ draw_inv_table_icon(gtk_widget_get_window(INV_TABLE_AT(x, y, columns)), pixmaps[tmp->face]->icon_image); // Draw an extra indicator if the item is applied. if (tmp->applied) { gtk_widget_modify_bg(INV_TABLE_AT(x, y, columns), GTK_STATE_NORMAL, &applied_color); } else { gtk_widget_modify_bg(INV_TABLE_AT(x, y, columns), GTK_STATE_NORMAL, NULL); } gtk_widget_show(INV_TABLE_AT(x, y, columns)); /* * Use tooltips to provide additional detail about the icons. * Looking at the code, the tooltip widget will take care of * removing the old tooltip, freeing strings, etc. */ snprintf(buf, 255, "%s %s", tmp->d_name, tmp->flags); gtk_widget_set_tooltip_text(INV_TABLE_AT(x, y, columns), buf); } x++; if (x == columns) { x = 0; y++; } } /* Don't need to do the logic below if only doing animation run */ if (animate) { return; } /* * Need to disconnect the callback functions cells we did not draw. * otherwise, we get errors on objects that are drawn. */ for (i = num_items; i <= max_drawn; i++) { if (INV_TABLE_AT(x, y, columns)) { gtk_widget_destroy(INV_TABLE_AT(x, y, columns)); INV_TABLE_AT(x, y, columns) = NULL; } x++; if (x == columns) { x = 0; y++; } } max_drawn = num_items; gtk_widget_show(inv_table); } /** * Draws the inventory and updates the encumbrance statistics display in the * client. Have to determine how to draw it. * * @param tab */ static void draw_inv(int tab) { char buf[256]; snprintf(buf, sizeof (buf), "%6.1f", cpl.ob->weight); gtk_label_set_text(GTK_LABEL(encumbrance_current), buf); snprintf(buf, sizeof (buf), "%6.1f", weight_limit); gtk_label_set_text(GTK_LABEL(encumbrance_max), buf); if (inv_notebooks[tab].type == INV_TREE) { draw_inv_list(tab); } else if (inv_notebooks[tab].type == INV_TABLE) { draw_inv_table(0); } } /** * Redraws inventory and look windows when necessary */ void draw_lists() { /* * There are some extra complications with container handling and timing. * For example, we draw the window before we get a list of the container, * and then the container contents are not drawn - this can be handled by * looking at container->inv_updated. */ if (cpl.container && cpl.container->inv_updated) { cpl.container->env->inv_updated = 1; cpl.container->inv_updated = 0; } if (cpl.ob->inv_updated) { draw_inv(gtk_notebook_get_current_page(GTK_NOTEBOOK(inv_notebook))); cpl.ob->inv_updated = 0; } if (cpl.below->inv_updated) { draw_look_list(); cpl.below->inv_updated = 0; } } /** * People are likely go to the different tabs much less often than their * inventory changes. So rather than update all the tabs whenever the players * inventory changes, only update the tab the player is viewing, and if they * change tabs, draw the new tab and get rid of the old info. Ideally, I'd * like to call draw_inv() from this function, but there is some oddity * * @param notebook * @param page * @param page_num * @param user_data */ static void on_switch_page(GtkNotebook *notebook, gpointer *page, guint page_num, gpointer user_data) { guint oldpage; oldpage = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); if (oldpage != page_num && inv_notebooks[oldpage].type == INV_TREE) { gtk_tree_store_clear(treestore); } cpl.ob->inv_updated = 1; } /** * */ static void animate_inventory() { gboolean valid; GtkTreeIter iter; item *tmp; int page; GtkTreeStore *store; page = gtk_notebook_get_current_page(GTK_NOTEBOOK(inv_notebook)); /* Still need to do logic for the table view. */ if (inv_notebooks[page].type == INV_TABLE) { draw_inv_table(1); return; } store = treestore; /* Get the first iter in the list */ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); while (valid) { gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, LIST_OBJECT, &tmp, -1); /* This is an object with animations */ if (tmp->animation_id > 0 && tmp->anim_speed && animations[tmp->animation_id].faces != NULL) { tmp->last_anim++; /* Time to change the face for this one */ if (tmp->last_anim >= tmp->anim_speed) { tmp->anim_state++; if (tmp->anim_state >= animations[tmp->animation_id].num_animations) { tmp->anim_state = 0; } tmp->face = animations[tmp->animation_id].faces[tmp->anim_state]; tmp->last_anim = 0; /* Update image in the tree store */ gtk_tree_store_set(store, &iter, LIST_ICON, (GdkPixbuf*) pixmaps[tmp->face]->icon_image, -1); } } valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); } } /** * */ static void animate_look() { gboolean valid; GtkTreeIter iter; item *tmp; /* Get the first iter in the list */ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store_look), &iter); while (valid) { gtk_tree_model_get(GTK_TREE_MODEL(store_look), &iter, LIST_OBJECT, &tmp, -1); /* This is an object with animations */ if (tmp->animation_id > 0 && tmp->anim_speed) { tmp->last_anim++; /* Time to change the face for this one */ if (tmp->last_anim >= tmp->anim_speed) { tmp->anim_state++; if (tmp->anim_state >= animations[tmp->animation_id].num_animations) { tmp->anim_state = 0; } tmp->face = animations[tmp->animation_id].faces[tmp->anim_state]; tmp->last_anim = 0; /* Update image in the tree store */ gtk_tree_store_set(store_look, &iter, LIST_ICON, (GdkPixbuf*) pixmaps[tmp->face]->icon_image, -1); } } valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store_look), &iter); } } /** * This is called periodically from main.c - basically a timeout, used to * animate the inventory. */ void inventory_tick() { animate_inventory(); animate_look(); } crossfire-client-1.75.3/gtk-v2/src/map.c000644 001751 001751 00000050655 14604610133 020575 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, see the * 'LICENSE' and 'COPYING' files. * * The authors can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file * Initializes and renders the map drawing area. Handles map drawing area * events, notably the "click to look at" mouse event. */ #include "client.h" #include #include #include "image.h" #include "main.h" #include "mapdata.h" #include "gtk2proto.h" /* Configuration (from config.c) */ extern int predict_alpha; extern bool time_map_redraw; int map_image_size = DEFAULT_IMAGE_SIZE; static gboolean map_updated = FALSE; GtkWidget *map_notebook; static GtkWidget *map_drawing_area; // Forward declarations for events static gboolean map_button_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data); static gboolean map_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data); /** * Calculate and set desired map size based on map window size. */ void map_check_resize() { if (!GTK_IS_WIDGET(map_drawing_area)) { // Called by config_check(), but main window layout not yet loaded. return; } GtkAllocation size; gtk_widget_get_allocation(map_drawing_area, &size); int scaled_size = map_image_size * use_config[CONFIG_MAPSCALE] / 100; int w = size.width / scaled_size + 1; int h = size.height / scaled_size + 1; w = (w > MAP_MAX_SIZE) ? MAP_MAX_SIZE : w; h = (h > MAP_MAX_SIZE) ? MAP_MAX_SIZE : h; // If request would be even, make it odd so player is centered. if (w % 2 == 0) { w += 1; } if (h % 2 == 0) { h += 1; } if (w != want_config[CONFIG_MAPWIDTH] || h != want_config[CONFIG_MAPHEIGHT]) { want_config[CONFIG_MAPWIDTH] = w; want_config[CONFIG_MAPHEIGHT] = h; if (csocket.fd) { client_mapsize(w, h); } } } /** * This initializes the stuff we need for the map. * * @param window_root The client's main playing window. */ void map_init(GtkWidget *window_root) { static gulong map_button_handler = 0; map_drawing_area = GTK_WIDGET(gtk_builder_get_object( window_xml, "drawingarea_map")); map_notebook = GTK_WIDGET(gtk_builder_get_object( window_xml, "map_notebook")); g_signal_connect(map_drawing_area, "configure_event", G_CALLBACK(map_check_resize), NULL); g_signal_connect(map_drawing_area, "expose_event", G_CALLBACK(map_expose_event), NULL); // Enable event masks and set callbacks to handle mouse events. // If its already connected (e.g. on a second login), then skip // an additional association. if (!g_signal_handler_is_connected(map_drawing_area, map_button_handler)) { gtk_widget_add_events(map_drawing_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); map_button_handler = g_signal_connect(map_drawing_area, "event", G_CALLBACK(map_button_event), NULL); } // Set our image sizes. // IIRC, atoi stops at the first nonnumeric char, so the x in the size will be the end. if (face_info.facesets[face_info.faceset].size != NULL) { image_size = atoi(face_info.facesets[face_info.faceset].size); map_image_size = image_size; // These should be the same. } else { LOG(LOG_ERROR, "map_init", "Invalid faceset size from server"); } // If we are not on the default size, we need to resize pixmaps[0]. if (map_image_size != DEFAULT_IMAGE_SIZE) { int nx = map_image_size, ny = map_image_size; guint8 *png_tmp = rescale_rgba_data(pixmaps[0]->map_image, &nx, &ny, use_config[CONFIG_MAPSCALE]); // Try to affect pixmap[0] in-place, since it is referenced extensively. pixmaps[0]->icon_width = nx; pixmaps[0]->icon_height = ny; // Do not affect full_icon_width/height, since those are expected to be the unscaled size. do_new_image(png_tmp, pixmaps[0]); } // Set map size based on window size and show widget. map_check_resize(); gtk_widget_show(map_drawing_area); } /** * Draw a pixmap to the given map tile on screen. * @param ax Map cell on-screen x-coordinate * @param ay Map cell on-screen y-coordinate */ static void draw_pixmap(cairo_t *cr, PixmapInfo *pixmap, int ax, int ay) { const int dest_x = ax * map_image_size; const int dest_y = ay * map_image_size; cairo_set_source_surface(cr, pixmap->map_image, dest_x, dest_y); cairo_paint(cr); } static void draw_smooth_pixmap(cairo_t* cr, PixmapInfo* pixmap, const int sx, const int sy, const int dx, const int dy) { const int src_x = map_image_size * sx; const int src_y = map_image_size * sy; const int dest_x = map_image_size * dx; const int dest_y = map_image_size * dy; cairo_set_source_surface(cr, pixmap->map_image, dest_x - src_x, dest_y - src_y); cairo_rectangle(cr, dest_x, dest_y, map_image_size, map_image_size); cairo_fill(cr); } int display_mapscroll(int dx, int dy) { return 0; } /** * Draw anything in adjacent squares that could smooth on given square * * @param mx * @param my Square to smooth on. * You should not call this function to smooth on a 'completely black' square. * @param layer Layer to examine (we smooth only one layer at a time) * @param picx * @param picy Place on the map_drawing_area->window to draw */ static void drawsmooth(cairo_t *cr, int mx, int my, int layer, int picx, int picy) { static int dx[8]= {0,1,1,1,0,-1,-1,-1}; static int dy[8]= {-1,-1,0,1,1,1,0,-1}; static int bweights[8]= {2,0,4,0,8,0,1,0}; static int cweights[8]= {0,2,0,4,0,8,0,1}; static int bc_exclude[8]= { 1+2,/*north exclude northwest (bit0) and northeast(bit1)*/ 0, 2+4,/*east exclude northeast and southeast*/ 0, 4+8,/*and so on*/ 0, 8+1, 0 }; int partdone[8]= {0,0,0,0,0,0,0,0}; int slevels[8]; int sfaces[8]; int i,weight,weightC; int emx,emy; int smoothface; int hasFace = 0; for (i=0; i<=layer; i++) { hasFace |= mapdata_cell(mx, my)->heads[i].face; } if (!hasFace || !mapdata_can_smooth(mx, my, layer)) { return; } for (i=0; i<8; i++) { emx=mx+dx[i]; emy=my+dy[i]; if (!mapdata_contains(emx, emy)) { slevels[i]=0; sfaces[i]=0; /*black picture*/ } else if (mapdata_cell(emx, emy)->smooth[layer] <= mapdata_cell(mx, my)->smooth[layer]) { slevels[i]=0; sfaces[i]=0; /*black picture*/ } else { slevels[i]=mapdata_cell(emx, emy)->smooth[layer]; sfaces[i]=pixmaps[mapdata_cell(emx, emy)->heads[layer].face]->smooth_face; } } /* * Now we have a list of smoothlevel higher than current square. There are * at most 8 different levels. so... check 8 times for the lowest one (we * draw from bottom to top!). */ while (1) { int lowest = -1; for (i=0; i<8; i++) { if ( (slevels[i]>0) && (!partdone[i]) && ((lowest<0) || (slevels[i]map_image) || (pixmaps[smoothface] == pixmaps[0])) { continue; /*don't have the picture associated*/ } if (weight > 0) { draw_smooth_pixmap(cr, pixmaps[smoothface], weight, 0, picx, picy); } if (weightC > 0) { draw_smooth_pixmap(cr, pixmaps[smoothface], weightC, 1, picx, picy); } } } /** * Draw a single map layer to the given cairo context. */ static void map_draw_layer(cairo_t *cr, int layer, int mx_start, int nx, int my_start, int ny) { for (int x = 0; x <= nx; x++) { for (int y = 0; y <= ny; y++) { // Translate on-screen coordinates to virtual map coordinates. const int mx = mx_start + x; const int my = my_start + y; // Skip current cell if not visible and not using fog of war. if (!use_config[CONFIG_FOGWAR] && mapdata_cell(mx, my)->state == FOG) { continue; } // Draw pixmaps int dx, dy, face = mapdata_face_info(mx, my, layer, &dx, &dy); if (face > 0 && pixmaps[face]->map_image != NULL) { draw_pixmap(cr, pixmaps[face], x + dx, y + dy); } // Draw smoothing if (use_config[CONFIG_SMOOTH]) { drawsmooth(cr, mx, my, layer, x, y); } } } } static double mapcell_darkness(int mx, int my) { double opacity = mapdata_cell(mx, my)->darkness / 192.0 * 0.6; if (use_config[CONFIG_FOGWAR] && mapdata_cell(mx, my)->state == FOG) { opacity += 0.2; } return opacity; } static void draw_darkness(cairo_t *cr, int nx, int ny, int mx_start, int my_start) { /** * Create light map nx wide, ny tall. Add a border 1px around to get rid * of edge effects. */ cairo_surface_t *cst_lm = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nx+2, ny+2); cairo_t *cr_lm = cairo_create(cst_lm); for (int x = -1; x <= nx+1; x++) { for (int y = -1; y <= ny+1; y++) { const int dx = MIN(MAX(0, x), nx); const int dy = MIN(MAX(0, y), ny); // Map coordinate to get darkness information from const int mx = mx_start + dx; const int my = my_start + dy; // Destination coordinates on light map const int ax = x + 1; const int ay = y + 1; cairo_rectangle(cr_lm, ax, ay, 1, 1); cairo_set_source_rgba(cr_lm, 0, 0, 0, mapcell_darkness(mx, my)); cairo_fill(cr_lm); } } cairo_destroy(cr_lm); // Scale up light map and draw to map. cairo_scale(cr, map_image_size, map_image_size); cairo_translate(cr, -1, -1); cairo_set_source_surface(cr, cst_lm, 0, 0); switch (use_config[CONFIG_LIGHTING]) { case CFG_LT_TILE: cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); break; case CFG_LT_PIXEL: cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_GOOD); break; case CFG_LT_PIXEL_BEST: cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BEST); break; } cairo_paint(cr); cairo_surface_destroy(cst_lm); } // Draw move-to tile. static void draw_move_to(cairo_t *cr, int mx_start, int my_start) { int mx = move_to_x; int my = move_to_y; int x = mx - mx_start; int y = my - my_start; if (!is_at_moveto()) { int sx = x * map_image_size; int sy = y * map_image_size; cairo_rectangle(cr, sx, sy, map_image_size, map_image_size); if (move_to_attack) { cairo_set_source_rgb(cr, 1, 0, 0); // red to attack } else { cairo_set_source_rgb(cr, 1, 1, 0); // yellow to walk } cairo_set_line_width(cr, 2); cairo_stroke(cr); cairo_rectangle(cr, sx + 2, sy + 2, map_image_size - 4, map_image_size - 4); cairo_set_source_rgb(cr, 0, 0, 0); // black cairo_set_line_width(cr, 1); cairo_stroke(cr); } } /** * Redraw the entire map using GTK. */ static void gtk_map_redraw() { if (!map_updated) { return; } GtkAllocation size; gtk_widget_get_allocation(map_drawing_area, &size); // Effective dimensions in pixels, i.e. after adjusting for map scale float scale = use_config[CONFIG_MAPSCALE]/100.0; const double ew = size.width / scale; const double eh = size.height / scale; // Number of tiles to show in x and y dimensions const int nx = (int)ceilf(ew / map_image_size); const int ny = (int)ceilf(eh / map_image_size); // Current viewport dimensions as sent by server, in squares const int vw = use_config[CONFIG_MAPWIDTH]; const int vh = use_config[CONFIG_MAPHEIGHT]; // The server always centers the player in the viewport. However, if our // drawing area shows more tiles than the viewport, then the player is // no longer centered. Correct that here. const int mx_start = (nx > vw) ? pl_pos.x - (nx - vw)/2 : pl_pos.x; const int my_start = (ny > vh) ? pl_pos.y - (ny - vh)/2 : pl_pos.y; // Create double buffer and associated graphics context. cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ew, eh); cairo_t *cr = cairo_create(cst); // Blank graphics context with a solid black background. cairo_set_source_rgb(cr, 0, 0, 0); cairo_rectangle(cr, 0, 0, ew, eh); cairo_fill(cr); // Set global offset (after blanking background) cairo_translate(cr, global_offset_x, global_offset_y); // Draw layer-by-layer. Drawing cell-by-cell, looping over the layers, // doesn't work because big faces need to be correctly layered on top. for (int layer = 0; layer < MAXLAYERS; layer++) { map_draw_layer(cr, layer, mx_start, nx, my_start, ny); } draw_move_to(cr, mx_start, my_start); if (use_config[CONFIG_LIGHTING] != 0) { draw_darkness(cr, nx, ny, mx_start, my_start); } cairo_destroy(cr); // Copy the double buffer on the map drawing area. cairo_t *map_cr = gdk_cairo_create(gtk_widget_get_window(map_drawing_area)); if (use_config[CONFIG_MAPSCALE] != 100) { cairo_scale(map_cr, scale, scale); } cairo_set_source_surface(map_cr, cst, 0, 0); if (use_config[CONFIG_MAPSCALE] % 100 == 0) { cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); } cairo_paint(map_cr); cairo_destroy(map_cr); cairo_surface_destroy(cst); } /** * Resize_map_window is a NOOP for the time being - not sure if it will in fact * need to do something, since there are scrollbars for the map window now. * Note - this is note a window resize request, but rather process the size * (in spaces) of the map - is received from server. */ void resize_map_window(int x, int y) { } static void update_global_offset() { int dx, dy; dx = ((want_offset_x*map_image_size) - global_offset_x)*predict_alpha/100.0; dy = ((want_offset_y*map_image_size) - global_offset_y)*predict_alpha/100.0; global_offset_x += dx; global_offset_y += dy; } /** * Draw the map window using the appropriate backend. */ void draw_map() { gint64 t_start, t_end; t_start = g_get_monotonic_time(); update_global_offset(); gtk_map_redraw(); t_end = g_get_monotonic_time(); gint64 elapsed = t_end - t_start; if (time_map_redraw) { printf("profile/redraw,%"G_GINT64_FORMAT"\n", elapsed); } const unsigned int target_redraw = 100000; const int no_resize_above = 100; // don't resize above this value of mapscale if (elapsed > target_redraw && use_config[CONFIG_MAPSCALE] < no_resize_above) { use_config[CONFIG_MAPSCALE] = MIN(use_config[CONFIG_MAPSCALE] + 5, no_resize_above); LOG(LOG_DEBUG, "draw_map", "Increasing mapscale to %d to reduce draw time below %u us", use_config[CONFIG_MAPSCALE], target_redraw); map_check_resize(); } } static gboolean map_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { draw_map(); return FALSE; } /** * Given a relative tile coordinate, determine its compass direction. * @param dx Relative 'x' coordinate * @param dy Relative 'y' coordinate * @return 0 if x and y are both zero, 1-8 for each compass direction */ int relative_direction(int dx, int dy) { if (dx == 0 && dy == 0) { return 0; } else if (dx == 0 && dy < 0) { return 1; } else if (dx > 0 && dy < 0) { return 2; } else if (dx > 0 && dy == 0) { return 3; } else if (dx > 0 && dy > 0) { return 4; } else if (dx == 0 && dy > 0) { return 5; } else if (dx < 0 && dy > 0) { return 6; } else if (dx < 0 && dy == 0) { return 7; } else if (dx < 0 && dy < 0) { return 8; } else { g_assert_not_reached(); } } /** * Given x, y coordinates on the map drawing area, determine the tile that the * coordinates are on with respect to the player. Clicking on the tile with * the player returns (0, 0). */ static void coord_to_tile(int x, int y, int *dx, int *dy) { // Calculate tile below (x, y) coordinates. The top left corner is (0, 0). // This is easy, just floor divide the coordinates by tile size. const float tile_size = map_image_size * use_config[CONFIG_MAPSCALE]/100.0; int mx = x / tile_size; int my = y / tile_size; // Now calculate where the player is drawn. The code below is copied from // gtk_map_redraw() (see the comments there): GtkAllocation size; gtk_widget_get_allocation(map_drawing_area, &size); float scale = use_config[CONFIG_MAPSCALE]/100.0; const double ew = size.width / scale; const double eh = size.height / scale; const int nx = (int)ceilf(ew / map_image_size); const int ny = (int)ceilf(eh / map_image_size); const int vw = use_config[CONFIG_MAPWIDTH]; const int vh = use_config[CONFIG_MAPHEIGHT]; // Normally, the player is centered in the middle of the server viewport // (with floor division). int ox = vw / 2; int oy = vh / 2; // If mapscale is less than 100, what is shown in the client no longer // matches the viewport. Add the right offset. if (nx > vw) { ox += (nx - vw)/2; } if (ny > vh) { oy += (ny - vh)/2; } // Shift the clicked tile by the player's position. *dx = mx - ox; *dy = my - oy; } /** * Handle a mouse event in the drawing area. */ static gboolean map_button_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { int dx, dy; coord_to_tile((int)event->x, (int)event->y, &dx, &dy); int dir = relative_direction(dx, dy); switch (event->button) { case 1: if (event->type == GDK_BUTTON_PRESS) { look_at(dx,dy); } break; case 2: if (event->type == GDK_BUTTON_RELEASE) { clear_fire(); } else { fire_dir(dir); } break; case 3: if (event->type == GDK_BUTTON_PRESS) { set_move_to(dx, dy); run_move_to(); } break; } return FALSE; } /** * This is called after the map has been all digested. this should perhaps be * removed, and left to being done from from the main event loop. * * @param redraw If set, force redraw of all tiles. * @param notice If set, another call will follow soon. */ void display_map_doneupdate(int redraw, int notice) { map_updated |= redraw || !notice; } crossfire-client-1.75.3/gtk-v2/src/config.c000644 001751 001751 00000077446 14443006275 021303 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Implement client configuration dialog */ #include "client.h" #include #include #include "image.h" #include "main.h" #include "mapdata.h" #include "gtk2proto.h" static GKeyFile *config; static GString *config_path; GtkWidget *config_dialog, *config_button_echo, *config_button_fasttcp, *config_button_timestamp, *config_button_grad_color, *config_button_foodbeep, *config_button_sound, *config_button_cache, *config_button_download, *config_button_fog, *config_button_smoothing; GtkFileChooser *ui_filechooser, *theme_filechooser; GtkComboBoxText *config_combobox_faceset; GtkComboBox *config_combobox_displaymode, *config_combobox_lighting; #define THEME_DEFAULT CF_DATADIR "/themes/Standard" /* Configuration variables initialized to NULL, set by config_load() */ static char *theme; char* last_server; /* * This should really be one of the CONFIG values, or perhaps a checkbox * someplace that displays frame rate. */ bool time_map_redraw = false; /** Speed of local map prediction scrolling, 0-100 (0 to disable). */ int predict_alpha = 10; static void on_config_close(GtkButton *button, gpointer user_data); static bool IS_DIFFERENT(int type) { return want_config[type] != use_config[type]; } /** * Return the basename of the current UI file. */ static char *ui_name() { return g_path_get_basename(window_xml_file); } /** * Sets up player-specific client and layout rc files and handles loading of a * client theme if one is selected. First, the player-specific rc files are * added to the GTK rc default files list. ${HOME}/.crossfire/gtkrc is added * first. All client sessions are affected by this rc file if it exists. * Next, ${HOME}/.crossfire/[layout].gtkrc is added, where [layout] is the * name of the layout file that is loaded. IE. If gtk-v2.ui is loaded, * [layout] is "gtk-v2". This sets up the possibility for a player to make a * layout-specific rc file. Finally, if the client theme is not "None", the * client theme file is added. In most cases, the player-specific files are * probably not going to exist, so the theme system will continue to work the * way it always has. The player will have to "do something" to get the extra * functionality. At some point, conceptually the client itself could be * enhanced to allow it to save some basic settings to either or both of the * player-specific rc files. * * @param reload * If true, user has changed theme after initial startup. In this mode, we * need to call the routines that store away private theme data. When program * is starting up, this is false, because all the widgets haven't been realized * yet, and the initialize routines will get the theme data at that time. */ static char **default_files = NULL; void init_theme() { char path[MAX_BUF]; char **tmp; int i; /* * The GTK man page says copy of this data should be made, so do that. */ tmp = gtk_rc_get_default_files(); i = 0; while (tmp && tmp[i]) { i++; } /* * Add two more GTK rc files that may be used by a player to customize * the client appearance in general, or to customize the appearance * of a specific layout. Allocate pointers to the local copy * of the entire list. */ i += 2; default_files = g_malloc(sizeof(char *) * (i + 1)); /* * Copy in GTK's default list which probably contains system paths * like /gtk-2.0/gtkrc and user-specific files like * ${HOME}/.gtkrc, or even LANGuage-specific ones like * ${HOME}/.gtkrc.en, etc. */ i = 0; while (tmp && tmp[i]) { default_files[i] = g_strdup(tmp[i]); i++; } /* * Add a player-specific gtkrc to the list of default rc files. This * file is probably reserved for player use, though in all liklihood * will not get used that much. Still, it makes it easy for someone * to make their own theme without having to have access to the * system-wide theme folder. This is the lowest priority client rc * file as either a .gtkrc file or a client-configured theme * settings can over-ride it. */ snprintf(path, sizeof(path), "%s/gtkrc", config_dir); default_files[i] = g_strdup(path); i++; /* * Add a UI layout-specific rc file to the list of default list. It * seems reasonable to allow client code to have access to this file * to make some basic changes to fonts, via a graphical interface. * Truncate window_xml_file to remove a .extension if one exists, so * that the window positions file can be created with a .gtkrc suffix. * This is a mid-priority client rc file as its settings supersede the * client gtkrc file, but are overridden by a client-configured theme. */ snprintf(path, sizeof(path), "%s/%s.gtkrc", config_dir, ui_name()); default_files[i] = g_strdup(path); i++; /* * Mark the end of the list of default rc files. */ default_files[i] = NULL; } void load_theme(int reload) { /* * Whether or not this is default and initial run, we want to register * the modified rc search path list, so GTK needs to get the changes. * It is necessary to reset the the list each time through here each * theme change grows the list. Only one theme should be in the list * at a time. */ gtk_rc_set_default_files(default_files); /* * If a client-configured theme has been selected (something other than * "None"), then add it to the list of GTK rc files to process. Since * this file is added last, it takes priority over both the gtkrc and * .gtkrc files. Remember, strcmp returns zero on a match, and * a theme file should not be registered if "None" is selected. */ g_assert(theme != NULL); // ensured by config_load() { /* * Check for existence of the client theme file. Unfortunately, at * initial run time, the window may not be realized yet, so the * message cannot be sent to the user directly. It doesn't hurt to * add the path even if the file isn't there, but the player might * still want to know something is wrong since they picked a theme. */ if (access(theme, R_OK) == -1) { LOG(LOG_ERROR, "load_theme", "Unable to find theme file %s", theme); g_free(theme); theme = g_strdup(THEME_DEFAULT); } gtk_rc_add_default_file(theme); } /* * Require GTK to reparse and rebind all the widget data. */ gtk_rc_reparse_all_for_settings( gtk_settings_get_for_screen(gdk_screen_get_default()), TRUE); gtk_rc_reset_styles( gtk_settings_get_for_screen(gdk_screen_get_default())); /* * Call client functions to reparse the custom widgets it controls. */ info_get_styles(); inventory_get_styles(); stats_get_styles(); spell_get_styles(); update_spell_information(); /* * Set inv_updated to force a redraw - otherwise it will not * necessarily bind the lists with the new widgets. */ cpl.below->inv_updated = 1; cpl.ob->inv_updated = 1; draw_lists(); draw_stats(TRUE); draw_message_window(TRUE); } /** * Load settings from the legacy file format. */ static void config_load_legacy() { char path[MAX_BUF], inbuf[MAX_BUF], *cp; FILE *fp; int i, val; LOG(LOG_INFO, "config_load_legacy", "Configuration not found; trying old configuration files."); LOG(LOG_INFO, "config_load_legacy", "You will need to move your keybindings to the new location."); snprintf(path, sizeof(path), "%s/.crossfire/gdefaults2", g_getenv("HOME")); if ((fp = fopen(path, "r")) == NULL) { return; } while (fgets(inbuf, MAX_BUF - 1, fp)) { inbuf[MAX_BUF - 1] = '\0'; inbuf[strlen(inbuf) - 1] = '\0'; /* kill newline */ if (inbuf[0] == '#') { continue; } /* Skip any setting line that does not contain a colon character */ if (!(cp = strchr(inbuf, ':'))) { continue; } *cp = '\0'; cp += 2; /* colon, space, then value */ val = -1; if (isdigit(*cp)) { val = atoi(cp); } else if (!strcmp(cp, "True")) { val = TRUE; } else if (!strcmp(cp, "False")) { val = FALSE; } for (i = 1; i < CONFIG_NUMS; i++) { if (!strcmp(config_names[i], inbuf)) { if (val == -1) { LOG(LOG_WARNING, "config.c::load_defaults", "Invalid value/line: %s: %s", inbuf, cp); } else { want_config[i] = val; } break; /* Found a match - won't find another */ } } /* We found a match in the loop above, so do not do anything more */ if (i < CONFIG_NUMS) { continue; } /* * Legacy - now use the map_width and map_height values Don't do sanity * checking - that will be done below */ if (!strcmp(inbuf, "mapsize")) { if (sscanf(cp, "%hdx%hd", &want_config[CONFIG_MAPWIDTH], &want_config[CONFIG_MAPHEIGHT]) != 2) { LOG(LOG_WARNING, "config.c::load_defaults", "Malformed mapsize option in gdefaults2. Ignoring"); } } else if (!strcmp(inbuf, "theme")) { if (theme != NULL) { g_free(theme); } theme = g_strdup(cp); continue; } else if (!strcmp(inbuf, "window_layout")) { strncpy(window_xml_file, cp, MAX_BUF - 1); continue; } else if (!strcmp(inbuf, "nopopups")) { /* Changed name from nopopups to popups, so inverse value */ want_config[CONFIG_POPUPS] = !val; continue; } else if (!strcmp(inbuf, "nosplash")) { want_config[CONFIG_SPLASH] = !val; continue; } else if (!strcmp(inbuf, "splash")) { want_config[CONFIG_SPLASH] = val; continue; } else if (!strcmp(inbuf, "faceset")) { face_info.want_faceset = g_strdup(cp); /* memory leak ! */ continue; } /* legacy, as this is now just saved as 'lighting' */ else if (!strcmp(inbuf, "per_tile_lighting")) { if (val) { want_config[CONFIG_LIGHTING] = CFG_LT_TILE; } } else if (!strcmp(inbuf, "per_pixel_lighting")) { if (val) { want_config[CONFIG_LIGHTING] = CFG_LT_PIXEL; } } else if (!strcmp(inbuf, "resists")) { if (val) { want_config[CONFIG_RESISTS] = val; } } else if (!strcmp(inbuf, "sdl")) { if (val) { want_config[CONFIG_DISPLAYMODE] = CFG_DM_SDL; } } else LOG(LOG_WARNING, "config.c::load_defaults", "Unknown line in gdefaults2: %s %s", inbuf, cp); } fclose(fp); } /** * Check that want_config is valid, copy the new configuration to use_config, * and apply the new configuration. Call this after changing want_config, * either through config_load() or on_config_close(). */ void config_check() { if (want_config[CONFIG_ICONSCALE] < 25 || want_config[CONFIG_ICONSCALE] > 200) { LOG(LOG_WARNING, "config_check", "Ignoring invalid 'iconscale' value '%d'; " "must be between 25 and 200.\n", want_config[CONFIG_ICONSCALE]); want_config[CONFIG_ICONSCALE] = use_config[CONFIG_ICONSCALE]; } if (want_config[CONFIG_MAPSCALE] < 10 || want_config[CONFIG_MAPSCALE] > 200) { LOG(LOG_WARNING, "config_check", "Ignoring invalid 'mapscale' value '%d'; " "must be between 10 and 200.\n", want_config[CONFIG_MAPSCALE]); want_config[CONFIG_MAPSCALE] = use_config[CONFIG_MAPSCALE]; } if (!want_config[CONFIG_LIGHTING]) { LOG(LOG_WARNING, "config_check", "No lighting mechanism selected - will not use darkness code"); want_config[CONFIG_DARKNESS] = FALSE; } if (want_config[CONFIG_RESISTS] > 2) { LOG(LOG_WARNING, "config_check", "Ignoring invalid 'resists' value '%d'; " "must be either 0, 1, or 2.\n", want_config[CONFIG_RESISTS]); want_config[CONFIG_RESISTS] = 0; } /* Make sure the map size os OK */ if (want_config[CONFIG_MAPWIDTH] < 9 || want_config[CONFIG_MAPWIDTH] > MAP_MAX_SIZE) { LOG(LOG_WARNING, "config_check", "Invalid map width (%d) " "option in gdefaults2. Valid range is 9 to %d", want_config[CONFIG_MAPWIDTH], MAP_MAX_SIZE); want_config[CONFIG_MAPWIDTH] = use_config[CONFIG_MAPWIDTH]; } if (want_config[CONFIG_MAPHEIGHT] < 9 || want_config[CONFIG_MAPHEIGHT] > MAP_MAX_SIZE) { LOG(LOG_WARNING, "config_check", "Invalid map height (%d) " "option in gdefaults2. Valid range is 9 to %d", want_config[CONFIG_MAPHEIGHT], MAP_MAX_SIZE); want_config[CONFIG_MAPHEIGHT] = use_config[CONFIG_MAPHEIGHT]; } #if !defined(HAVE_OPENGL) if (want_config[CONFIG_DISPLAYMODE] == CFG_DM_OPENGL) { want_config[CONFIG_DISPLAYMODE] = CFG_DM_PIXMAP; LOG(LOG_ERROR, "config_check", "Display mode is set to OpenGL, but client " "is not compiled with OpenGL support. Reverting to pixmap mode."); } #endif #if !defined(HAVE_SDL) if (want_config[CONFIG_DISPLAYMODE] == CFG_DM_SDL) { want_config[CONFIG_DISPLAYMODE] = CFG_DM_PIXMAP; LOG(LOG_ERROR, "config_check", "Display mode is set to SDL, but client " "is not compiled with SDL support. Reverting to pixmap mode."); } #endif if (want_config[CONFIG_CACHE]) { LOG(LOG_ERROR, "config_check", "Image caching is not currently supported in this client. Running without image caching."); want_config[CONFIG_CACHE] = 0; } // Enable darkness if lighting is not 'None'. if (want_config[CONFIG_LIGHTING] != CFG_LT_NONE) { want_config[CONFIG_DARKNESS] = 1; } if (want_config[CONFIG_SOUND] && init_sounds()) { use_config[CONFIG_SOUND] = 1; } else { use_config[CONFIG_SOUND] = 0; } if (csocket.fd) { cs_print_string(csocket.fd, "setup sound %d", use_config[CONFIG_SOUND]); } #ifdef TCP_NODELAY #ifndef WIN32 // TODO: Merge with setsockopt code from client.c int q = want_config[CONFIG_FASTTCP]; if (csocket.fd && setsockopt(csocket.fd, SOL_TCP, TCP_NODELAY, &q, sizeof(q)) == -1) { perror("TCP_NODELAY"); } #endif #endif /* Copy sanitized user settings to current settings. */ memcpy(use_config, want_config, sizeof(use_config)); map_check_resize(); image_size = DEFAULT_IMAGE_SIZE * use_config[CONFIG_ICONSCALE] / 100; if (!use_config[CONFIG_CACHE]) { use_config[CONFIG_DOWNLOAD] = FALSE; } } /** * Load settings from the user's configuration file into want_config. */ void config_load() { GError *error = NULL; /* Copy initial desired settings from current settings. */ memcpy(want_config, use_config, sizeof(want_config)); g_assert(g_file_test(config_dir, G_FILE_TEST_IS_DIR) == TRUE); /* Load existing or create new configuration file. */ config = g_key_file_new(); config_path = g_string_new(config_dir); g_string_append(config_path, "/client.ini"); g_key_file_load_from_file(config, config_path->str, G_KEY_FILE_NONE, &error); /* Load configuration values into settings array. */ if (error == NULL) { LOG(LOG_DEBUG, "config_load", "config_path='%s'", config_path->str); for (int i = 1; i < CONFIG_NUMS; i++) { GError *error = NULL; gint value = g_key_file_get_integer(config, "Client", config_names[i], &error); if (error == NULL) { want_config[i] = value; } } /* Load additional settings. */ if (theme != NULL) { g_free(theme); } theme = g_key_file_get_string(config, "GTKv2", "theme", NULL); if (face_info.want_faceset != NULL) { g_free(face_info.want_faceset); } face_info.want_faceset = g_key_file_get_string(config, "GTKv2", "faceset", NULL); predict_alpha = g_key_file_get_integer(config, "GTKv2", "predict_alpha", NULL); if (last_server != NULL) { g_free(last_server); } last_server = g_key_file_get_string(config, "GTKv2", "last_server", NULL); char *layout = g_key_file_get_string(config, "GTKv2", "window_layout", NULL); g_strlcpy(window_xml_file, layout, sizeof(window_xml_file)); free(layout); } else { g_error_free(error); /* Load legacy configuration file. */ config_load_legacy(); } if (theme == NULL) { theme = g_strdup(THEME_DEFAULT); } if (face_info.want_faceset == NULL) { face_info.want_faceset = g_strdup(""); } if (last_server == NULL) { last_server = g_strdup(""); } } /** * This function saves user settings chosen using the configuration popup * dialog. */ void save_defaults() { GError *error = NULL; /* Save GTKv2 specific client settings. */ g_key_file_set_string(config, "GTKv2", "theme", theme); g_key_file_set_string(config, "GTKv2", "faceset", face_info.want_faceset); g_key_file_set_string(config, "GTKv2", "last_server", last_server); g_key_file_set_integer(config, "GTKv2", "predict_alpha", predict_alpha); g_key_file_set_string(config, "GTKv2", "window_layout", window_xml_file); /* Save the rest of the client settings. */ for (int i = 1; i < CONFIG_NUMS; i++) { g_key_file_set_integer(config, "Client", config_names[i], want_config[i]); } g_file_set_contents(config_path->str, g_key_file_to_data(config, NULL, NULL), -1, &error); if (error != NULL) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, "Could not save settings!"); g_warning("Could not save settings: %s", error->message); g_error_free(error); } } void config_init(GtkWidget *window_root) { config_dialog = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_dialog")); // Initialize file choosers and set filename filters. ui_filechooser = GTK_FILE_CHOOSER(gtk_builder_get_object(dialog_xml, "ui_filechooser")); theme_filechooser = GTK_FILE_CHOOSER( gtk_builder_get_object(dialog_xml, "theme_filechooser")); GtkFileFilter *ui_filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(ui_filter, "*.ui"); gtk_file_chooser_set_filter(ui_filechooser, ui_filter); config_button_echo = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_echo")); config_button_fasttcp = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_fasttcp")); config_button_timestamp = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_timestamp")); config_button_grad_color = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_grad_color")); config_button_foodbeep = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_foodbeep")); config_button_sound = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_sound")); config_button_cache = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_cache")); config_button_download = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_download")); config_button_fog = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_fog")); config_button_smoothing = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_smoothing")); config_combobox_displaymode = GTK_COMBO_BOX( gtk_builder_get_object(dialog_xml, "config_combobox_displaymode")); config_combobox_faceset = GTK_COMBO_BOX_TEXT( gtk_builder_get_object(dialog_xml, "config_combobox_faceset")); config_combobox_lighting = GTK_COMBO_BOX( gtk_builder_get_object(dialog_xml, "config_combobox_lighting")); GtkWidget *config_button_close = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "config_button_close")); g_signal_connect(config_button_close, "clicked", G_CALLBACK(on_config_close), NULL); g_signal_connect(config_dialog, "delete_event", G_CALLBACK(on_config_close), NULL); // Initialize available rendering modes. GtkListStore *display_list = GTK_LIST_STORE(gtk_combo_box_get_model(config_combobox_displaymode)); GtkTreeIter iter; #ifdef HAVE_OPENGL gtk_list_store_append(display_list, &iter); gtk_list_store_set(display_list, &iter, 0, "OpenGL", 1, CFG_DM_OPENGL, -1); #endif #ifdef HAVE_SDL gtk_list_store_append(display_list, &iter); gtk_list_store_set(display_list, &iter, 0, "SDL", 1, CFG_DM_SDL, -1); #endif gtk_list_store_append(display_list, &iter); gtk_list_store_set(display_list, &iter, 0, "Pixmap", 1, CFG_DM_PIXMAP, -1); } /** * Removes all the text entries from the combo box. This function is not * available in GTK+2, so implement it ourselves. */ static void combo_box_text_remove_all(GtkComboBoxText *combo_box) { int count = gtk_tree_model_iter_n_children( gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box)), NULL); for (int i = 0; i < count; i++) { gtk_combo_box_text_remove(combo_box, 0); } } /* * Setup config_dialog sets the buttons, combos, etc, to the state that matches * the want_config[] values. */ static void setup_config_dialog() { GtkTreeIter iter; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_echo), want_config[CONFIG_ECHO]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_fasttcp), want_config[CONFIG_FASTTCP]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_timestamp), want_config[CONFIG_TIMESTAMP]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_grad_color), want_config[CONFIG_GRAD_COLOR]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_foodbeep), want_config[CONFIG_FOODBEEP]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_sound), want_config[CONFIG_SOUND]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_cache), want_config[CONFIG_CACHE]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_download), want_config[CONFIG_DOWNLOAD]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_fog), want_config[CONFIG_FOGWAR]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_button_smoothing), want_config[CONFIG_SMOOTH]); // Fill face set combo box with available face sets from the server. combo_box_text_remove_all(config_combobox_faceset); if (face_info.have_faceset_info) { for (int i = 0; i < MAX_FACE_SETS; i++) { const char *name = face_info.facesets[i].fullname; if (name != NULL) { gtk_combo_box_text_append_text(config_combobox_faceset, name); // g_ascii_strcasecmp expects both arguments to be non-null. // It appears to return 0 when one is null, confounding the result with // that of an actual match. if (face_info.want_faceset && !g_ascii_strcasecmp(face_info.want_faceset, name)) { gtk_combo_box_set_active(GTK_COMBO_BOX(config_combobox_faceset), i); } } else { break; } } } // Set current display mode. GtkTreeModel *model; model = gtk_combo_box_get_model(config_combobox_displaymode); bool next = gtk_tree_model_get_iter_first(model, &iter); while (next) { int current; gtk_tree_model_get(model, &iter, 1, ¤t, -1); if (current == want_config[CONFIG_DISPLAYMODE]) { gtk_combo_box_set_active_iter(config_combobox_displaymode, &iter); break; } next = gtk_tree_model_iter_next(model, &iter); } // Lighting option indexes never change, so set option using index. gtk_combo_box_set_active(config_combobox_lighting, want_config[CONFIG_LIGHTING]); gtk_file_chooser_set_filename(ui_filechooser, window_xml_file); gtk_file_chooser_set_filename(theme_filechooser, theme); } /** * Get an integer value from 'column' of the active field in 'combobox'. */ static int combobox_get_value(GtkComboBox *combobox, int column) { GtkTreeModel *model = gtk_combo_box_get_model(combobox); GtkTreeIter iter; int result; gtk_combo_box_get_active_iter(combobox, &iter); gtk_tree_model_get(model, &iter, column, &result, -1); return result; } /** * This is basically the opposite of setup_config_dialog() above - instead of * setting the display state appropriately, we read the display state and * update the want_config values. */ static void read_config_dialog(void) { want_config[CONFIG_ECHO] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_button_echo)); want_config[CONFIG_FASTTCP] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_button_fasttcp)); want_config[CONFIG_TIMESTAMP] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(config_button_timestamp)); want_config[CONFIG_GRAD_COLOR] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(config_button_grad_color)); want_config[CONFIG_FOODBEEP] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_button_foodbeep)); want_config[CONFIG_SOUND] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_button_sound)); want_config[CONFIG_CACHE] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_button_cache)); want_config[CONFIG_DOWNLOAD] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_button_download)); want_config[CONFIG_FOGWAR] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_button_fog)); want_config[CONFIG_SMOOTH] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(config_button_smoothing)); gchar *buf = 0; GtkTreeIter iter; /** * Since the combo box does not have the "has-entry" property set to TRUE, we cannot use * gtk_combo_box_text_get_active_text to get the currently selected option. * Since we really have no good reason to turn that on and open up the box for * arbitrary faceset strings, we can treat it more like a regular combo box. * We need to use an iterator retrieval and gtk_tree_model_get to fetch the text, * which is significantly more of a pain in the posterior. * * Daniel Hawkins -- 2020-11-21 */ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(config_combobox_faceset), &iter)) { // We have an active selection in our iterator. Now we get the string from the tree model. GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(config_combobox_faceset)); gtk_tree_model_get(model, &iter, 0, &buf, -1); if (buf) { free(face_info.want_faceset); face_info.want_faceset = g_strdup(buf); g_free(buf); } else { LOG(LOG_ERROR, "read_config_dialog", "Failed to get face set string from GTK Widget."); } } want_config[CONFIG_DISPLAYMODE] = combobox_get_value(config_combobox_displaymode, 1); // Lighting option indexes never change, so get option using index. want_config[CONFIG_LIGHTING] = gtk_combo_box_get_active(config_combobox_lighting); // Set UI file. buf = gtk_file_chooser_get_filename(ui_filechooser); if (buf != NULL) { g_strlcpy(window_xml_file, buf, sizeof(window_xml_file)); g_free(buf); } // Set and load theme file. buf = gtk_file_chooser_get_filename(theme_filechooser); if (buf != NULL && g_ascii_strcasecmp(buf, theme) != 0) { g_free(theme); theme = buf; load_theme(TRUE); } if (IS_DIFFERENT(CONFIG_GRAD_COLOR)) { draw_stats(TRUE); } } void on_configure_activate(GtkWidget *menuitem, gpointer user_data) { gtk_widget_show(config_dialog); setup_config_dialog(); } static void on_config_close(GtkButton *button, gpointer user_data) { read_config_dialog(); config_check(); save_defaults(); gtk_widget_hide(config_dialog); } /** * Save client window positions to a file unique to each layout. */ void save_winpos() { GSList *pane_list, *list_loop; int x, y, w, h, wx, wy; /* Save window position and size. */ get_window_coord(window_root, &x, &y, &wx, &wy, &w, &h); GString *window_root_info = g_string_new(NULL); g_string_printf(window_root_info, "+%d+%dx%dx%d", wx, wy, w, h); g_key_file_set_string(config, ui_name(), "window_root", window_root_info->str); g_string_free(window_root_info, TRUE); /* Save the positions of all the HPANEDs and VPANEDs. */ pane_list = gtk_builder_get_objects(window_xml); for (list_loop = pane_list; list_loop != NULL; list_loop = list_loop->next) { GType type = G_OBJECT_TYPE(list_loop->data); if (type == GTK_TYPE_HPANED || type == GTK_TYPE_VPANED) { g_key_file_set_integer(config, ui_name(), gtk_buildable_get_name(list_loop->data), gtk_paned_get_position(GTK_PANED(list_loop->data))); } } g_slist_free(pane_list); save_defaults(); draw_ext_info(NDI_BLUE, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, "Window positions saved!"); } /** * Handles saving of the window positions when the Client | Save Window * Position menu item is activated. * * @param menuitem * @param user_data */ void on_save_window_position_activate(GtkMenuItem *menuitem, gpointer user_data) { save_winpos(); /* * The following prevents multiple saves per menu activation. */ g_signal_stop_emission_by_name(GTK_WIDGET(menuitem), "activate"); } /** * Resize the client window and its panels using saved window positions. * * @param window_root The client's main window. */ void load_window_positions(GtkWidget *window_root) { GSList *pane_list, *list; pane_list = gtk_builder_get_objects(window_xml); // Load and set main window dimensions. gchar *root_size = g_key_file_get_string(config, ui_name(), "window_root", NULL); if (root_size != NULL) { int w, h; if (sscanf(root_size, "+%*d+%*dx%dx%d", &w, &h) == 2) { gtk_window_set_default_size(GTK_WINDOW(window_root), w, h); } g_free(root_size); } // Load and set panel positions. for (list = pane_list; list != NULL; list = list->next) { GType type = G_OBJECT_TYPE(list->data); if (type == GTK_TYPE_HPANED || type == GTK_TYPE_VPANED) { int position = g_key_file_get_integer(config, ui_name(), gtk_buildable_get_name(list->data), NULL); if (position != 0) { gtk_paned_set_position(GTK_PANED(list->data), position); } } } g_slist_free(pane_list); } crossfire-client-1.75.3/gtk-v2/themes/000755 001751 001751 00000000000 14605665664 020363 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/gtk-v2/themes/Standard000644 001751 001751 00000046702 14110265004 022026 0ustar00kevinzkevinz000000 000000 ############################################################################ # http://www.gnu.org/software/emacs/manual/html_node/emacs/GTK-styles.html # has good information that relates to the content of this theme file. # # Where font_name appears, ie. font_name = "Sans Bold Italic 9", the format is # a Pango string, so refer to that documentation for details. One resource is # http://www.gtk.org/api/2.6/pango/PangoMarkupFormat.html, but briefly, there # are various options that can be specified: family, style, weight, size. # # Spaces inside the font name is normal. The font name and options are # generally delimited with space characters. Font-family is a comma separated # list. Style includes things like Italic, Normal, Oblique. Size is in # points with no units. The default size appears to be 10. Weight is also # supported and includes choices like: ultralight, light, normal, bold, # ultrabold, heavy. The font descriptors do not seem to be case sensitive. # It may take experimentation to see what works. It appears, for example, # that all weight identifiers may not be supported for all fonts. ############################################################################ # Start of Stat Bar styles ############################################################################ # The stat bars are the bars at the bottom left of the window - hp, # spell points, grace, food & exp. # The low values are used when the stat is less than 25% of its max. # The super value is used when the stat is above is max. # the normal value is used in the 25%->100% range. # # There is no requirement that these be different colors - if you # want the food value to be brown no matter what, just create # a style for food_bar, and bind that to the normal/low/super values. # this is what is done for exp, since being below 25% exp isn't really # bad. # # If you have configured the client to use gradual shading of the # stat bar colors, the gradual values are used instead. The low # as the 0 point, the normal is 100%, and super is 200%. The client # will then mix the color based on the actual value of the stat. I thought # it better to have different values, as what may look good normally may # not blend well (in particular, the standard values are not 100% # saturated since those would seem too bright. # # the reason base[SELECTED] is used for values is that is what # is used if these were being bound directly to the widget. # # if one of the styles is missing a color, the client will use # standard system wide theme defaults to draw in that state. # For the gradual color, if it is missing a color, it just will # not color it - probably not what you want. # # Note: If you are not seeing colorful stat bars as you expect, # the problem may be with the system wide theme you have chosen. # some themes modify the draw logic for the progressbar and instead # draw pixmaps (if you see striped bars, you are using such a theme). # These themes do no pay any attention to the colors we try to set - # IMO, this is a bug in the theme engine, as there isn't way # to turn that behaviour off. The only way around this would be # for the client to have its own widget to draw the bars, but then # this causes problems for those people that like that theme. # style "low_bar" { #red base[SELECTED] = "#cf0000" } style "normal_bar" { # green base[SELECTED] = "#00cf00" } style "super_bar" { base[SELECTED] = "#00cf00" } style "gradual_low_bar" { base[SELECTED] = "red" } style "gradual_full_bar" { base[SELECTED] = "green" } style "gradual_super_bar" { base[SELECTED] = "blue" } widget_class "hp_bar_normal" style "normal_bar" widget_class "hp_bar_low" style "low_bar" widget_class "hp_bar_super" style "super_bar" widget_class "hp_gradual_bar_normal" style "gradual_full_bar" widget_class "hp_gradual_bar_low" style "gradual_low_bar" widget_class "hp_gradual_bar_super" style "gradual_super_bar" widget_class "sp_bar_normal" style "normal_bar" widget_class "sp_bar_low" style "low_bar" widget_class "sp_bar_super" style "super_bar" widget_class "sp_gradual_bar_normal" style "gradual_full_bar" widget_class "sp_gradual_bar_low" style "gradual_low_bar" widget_class "sp_gradual_bar_super" style "gradual_super_bar" widget_class "grace_bar_normal" style "normal_bar" widget_class "grace_bar_low" style "low_bar" widget_class "grace_bar_super" style "super_bar" widget_class "grace_gradual_bar_normal" style "gradual_full_bar" widget_class "grace_gradual_bar_low" style "gradual_low_bar" widget_class "grace_gradual_bar_super" style "gradual_super_bar" widget_class "food_bar_normal" style "normal_bar" widget_class "food_bar_low" style "low_bar" widget_class "food_bar_super" style "super_bar" widget_class "food_gradual_bar_normal" style "gradual_full_bar" widget_class "food_gradual_bar_low" style "gradual_low_bar" widget_class "food_gradual_bar_super" style "gradual_super_bar" # It doesn't make sense to have an alert for low exp, # so set all the conditions to the same color. For graduated # color, it can IMO still be nice to change colors as you get closer. widget_class "exp_bar_normal" style "normal_bar" widget_class "exp_bar_low" style "normal_bar" widget_class "exp_bar_super" style "normal_bar" widget_class "exp_gradual_bar_normal" style "gradual_full_bar" widget_class "exp_gradual_bar_low" style "gradual_low_bar" widget_class "exp_gradual_bar_super" style "gradual_super_bar" ############################################################################ # Start of inventory/look window styles ############################################################################ # # The inv_ do not get tied to real widgets. This is because we are # controlling individual rows of the widget based on values that the # widget can not know about (magic, cursed, etc). So the client looks # up these special names and then uses the value to control how to # draw the actual rows. Note that there is no requirement that there # be 1 style/widget_class. If you want different object criteria # to use the same style, you can do that, eg, # # widget "inv_cursed" style "inv_mine" # widget "inv_magical" style "inv_mine" # # Is perfectly legal, but probably doesn't make a lot of sense. # # Note that there is no 'default' here - the default values come from # the normal widget binding. # # Note that there is no combining of values - only one of these is # used for any object. The precedence is: # unpaid > cursed > magical > applied > locked # style "inv_cursed" { # "tomato" is a more muted color than "red", better contrast --DTW base[NORMAL] = "tomato" } widget_class "inv_cursed" style "inv_cursed" style "inv_magical" { # "skyblue" is more muted than "blue", *far* better contrast --DTW base[NORMAL] = "skyblue" } widget_class "inv_magical" style "inv_magical" # You owe gold for these style "inv_unpaid" { # Not only is "wheat" more muted than "gold", # but I changed it to color the background, not the text. --DTW base[NORMAL] = "wheat" } widget_class "inv_unpaid" style "inv_unpaid" style "inv_locked" { font_name = "Sans Italic" } widget_class "inv_locked" style "inv_locked" style "inv_applied" { font_name = "Sans Bold" } widget_class "inv_applied" style "inv_applied" ############################################################################ # Start of spell list styles ############################################################################ # like the inventory styles, these do not bind to a specific widget, # but rather the code uses them based on values of the spell. # style "spell_denied" { # "tomato" is more muted than "red", better contrast --DTW base[NORMAL] = "tomato" } widget_class "spell_denied" style "spell_denied" style "spell_repelled" { base[NORMAL] = "orange" } widget_class "spell_repelled" style "spell_repelled" style "spell_attuned" { # "lightgreen" is more muted than "green", better contrast --DTW base[NORMAL] = "lightgreen" } widget_class "spell_attuned" style "spell_attuned" style "spell_normal" { base[NORMAL] = "#F0F0F0" } widget_class "spell_normal" style "spell_normal" ############################################################################ # Start of text info style. The text info are where it actually # displays the messages. ############################################################################ # info_default is a bit special. # What info_default is used for is a supported way for the # code to find out what attributes set in the other info_... # values differ - it will basically compare the values and only set # the ones that are different. This is really just a place holder, # and you probably shouldn't put any actual values within the # style {} area. However, it must be defined for other styles # to work (if it doesn't have anything to get a difference against, # it can not set up the other styles. style "info_default" { } widget_class "info_default" style "info_default" # The extended info has the idea of different fonts: # # Normal: Standard font to use for drawing # Arcane: Perhaps better called 'old style' fonts - still clearly readable, # but should have an 'old' look. # Strange: A runic font that doesn't necessarily need to be readable - could # just be symbols. # Fixed: Fixed width font used for listings of preformatted text. # Hand: A font that should look like handwritten text. # # Note that except for the fixed font, the font you use is not likely # to have a critical effect - if you used the same font for everything, # it is unlikely to affect the play of the game. # Also, while these are defined as font names, you can also define # colors. However, other # styles may take precedence - eg, if you specify a color in the # style definition, and the message itself has color tags, those # may be used instead. # # You can use the gtk character map utility to view the fonts and get # font names. # # Note that the fonts specified here may not be ideal candidates, but # my goal here is to choose fonts that a normal installation would have # installed. You can get better fonts off the web, but since they # are not available by default, it doesn't make sense to make them # the default. # # For normal font, just use the system/theme default. #style "info_font_normal" #{ # font_name = "Sans" #} #widget_class "info_font_normal" style "info_font_normal" style "info_font_arcane" { font_name = "URW Chancery L" } widget_class "info_font_arcane" style "info_font_arcane" # With the different scripts included in unicode (and part # of gtk2), all we really need to do here is change it so that # we use the Runic script instead of Latin. However, there is # no way to do that directly with styles. What needs to be # done is some extra code added to process this as a script and # not a font perhaps. style "info_font_strange" { font_name = "Sans Italic" } widget_class "info_font_strange" style "info_font_strange" style "info_font_fixed" { font_name = "Luxi Mono" } widget_class "info_font_fixed" style "info_font_fixed" # URW Chancery L would also look good for this, but # we're using that for arcane. style "info_font_hand" { font_name = "Century Schoolbook L Italic" } widget_class "info_font_hand" style "info_font_hand" # # The first set of info_ are how to display messages that come # as a certain color from the server. Eg, the server says 'draw this in # black', and this determines how we actually draw it. For example, # when using a black background, you really don't want the text color # to be black. # Note that anything not set here (fg, bg, font) will use default # values as bound to the global widget (*), so you don't need to # specify all the values in each classification. If you don't want # different colored text, just disable all of these. # The values here match the traditional values used. style "black_text" { fg[NORMAL] = "black" } widget_class "info_black" style "black_text" style "white_text" { fg[NORMAL] = "black" font_name = "bold" } widget_class "info_white" style "white_text" style "darkblue_text" { fg[NORMAL] = "navy" } widget_class "info_darkblue" style "darkblue_text" style "red_text" { fg[NORMAL] = "red" } widget_class "info_red" style "red_text" style "orange_text" { fg[NORMAL] = "orange" } widget_class "info_orange" style "orange_text" style "lightblue_text" { fg[NORMAL] = "dodgerblue" } widget_class "info_lightblue" style "lightblue_text" style "darkorange_text" { fg[NORMAL] = "darkorange2" } widget_class "info_darkorange" style "darkorange_text" style "green_text" { fg[NORMAL] = "seagreen" } widget_class "info_green" style "green_text" style "darkgreen_text" { fg[NORMAL] = "darkseagreen" } widget_class "info_darkgreen" style "darkgreen_text" style "grey_text" { fg[NORMAL] = "grey50" } widget_class "info_grey" style "grey_text" style "brown_text" { fg[NORMAL] = "sienna" } widget_class "info_brown" style "brown_text" style "yellow_text" { fg[NORMAL] = "gold" } widget_class "info_yellow" style "yellow_text" style "tan_text" { fg[NORMAL] = "khaki" } widget_class "info_tan" style "tan_text" # these msg_.. values determine how to draw output of the # different message types - see the newclient.h and msgtypes.h file for all # the types/subytpes. With this, you can set different output styles # for all of the different message types. # # A few notes: # # 1) it is the widget_class line that binds the the style to the name that # the client uses to look it up. # Thus, you can do something like: # # style "red_text" .... # widget_class "msg_victim_was_pushed" style "red_text" # widget_class "msg_communication_say" style "red_text" # # In this way, you don't need to have a style for every msg type - a more # likely scenario is a modest number of styles, but then binding these # to the different widget names as how you want that widget to be # drawn. The _text entries used above can be re-used # for the msg types here. # # 2) Beyond normal style inheritence rules, the client itself is coded # to do some - just in that way, you don't need to list every msg # type here. For example: # # widget_class "msg_book" style "green_text" # # will result in every message of the BOOK class to be drawn in green # text. If you then add the line: # # widget_class "msg_book_clasp_1" style "red_text" # # messages of type BOOK, subtype CLASP_1 will be drawn in red, with all # the other BOOK message types being drawn in green. # # Note that this works on a type/subtype level, not a # string level. Thus, # you can not do: # # widget_class "msg_book_clasp" style "red_text" # # and have it work, as the "msg_book_clasp" by itself isn't a valid name. # Basically, you can bind it to the overall type (which covers all the # subtypes), or to specific type/subtypes. The common/msgtypes.h file # contains all the valid names (without the msg_ prefix) that are valid. # # 3) Even with the new message types, the server still sends what color # it thinks they should be drawn (this is basically for older clients # predating extended text support). If you do not specify _ANY_ styles for the # message types here, the client will use that color tag for what color # to draw the text with, as set with the info_ section above. # However, if even a single msg_ style is set, then the client will not # use those values - the presumption being that if a msg_ style # is set, the user knows what they are doing, and any that are not # set they want in default color/style. # # This is because there really isn't any way # for the client to know if it is intentional on the part of the user # that they want to use the default styles for the widgets or if it # should be using that color information - this is especially true # given the inheritence described in point #2 above. # # The entries below try to match what color the server says # to use for these - basically, to keep compatibility without # having to use the passed in color value - in that way, # additions can be made and the expected appearance of messages # will remain. # Given this is compatible type messages, we re-use # the color_text styles above. Note that in some cases, # the same type of message used different colors depending # on where in the code it was called. I've tried to use here # whatever was used the most for a particular message, but # I also took into account the message and other related messages # so the color for good vs bad effects are different, etc. To # some extent, the idea that red messages are bad is put in place # here, with blue being good. # # Note - these should really be re-done, as the current color # scheme often makes no sense (same style for both a level # gain and loss?) But this base file is more as a sample # and also act like things have in the past. # # Some colors, like lightgreen, gold & tan are not used by # any message types right now. And some others are used # in only a few places, like greytext, browntext # # these are in type/subtype order, to match msgtypes.h # BOOK messages widget_class "msg_book" style "darkblue_text" # CARD messages # PAPER messages # SIGN messages widget_class "msg_sign" style "darkblue_text" # MONUMENT messages # DIALOG messages widget_class "msg_dialog_npc" style "darkblue_text" widget_class "msg_dialog_magic_ear" style "darkblue_text" # MOTD messages widget_class "msg_motd" style "green_text" # ADMIN messages widget_class "msg_admin_rules" style "green_text" widget_class "msg_admin_news" style "green_text" widget_class "msg_admin_player" style "darkorange_text" widget_class "msg_admin_dm" style "red_text" # SHOP messages # COMMAND messages widget_class "msg_command_quests" style "white_text" widget_class "msg_command_dm" style "red_text" widget_class "msg_command_newplayer" style "lightblue_text" # ATTRIBUTE messages widget_class "msg_attribute_protection_gain" style "lightblue_text" widget_class "msg_attribute_protection_loss" style "red_text" widget_class "msg_attribute_bad_effect_start" style "red_text" widget_class "msg_attribute_level_gain" style "lightblue_text" widget_class "msg_attribute_level_loss" style "red_text" widget_class "msg_attribute_race" style "lightblue_text" widget_class "msg_attribute_god" style "darkblue_text" # SKILL messages widget_class "msg_skill_pray" style "white_text" widget_class "msg_skill_error" style "red_text" # APPLY messages widget_class "msg_apply_success" style "darkblue_text" widget_class "msg_apply_cursed" style "darkblue_text" widget_class "msg_apply_trap" style "darkblue_text" # ATTACK messages widget_class "msg_attack_did_hit" style "red_text" widget_class "msg_attack_nokey" style "darkblue_text" # COMMUNICATION messages widget_class "msg_communication_random" style "white_text" widget_class "msg_communication_say" style "white_text" widget_class "msg_communication_me" style "lightblue_text" widget_class "msg_communication_tell" style "orange_text" widget_class "msg_communication_emote" style "white_text" widget_class "msg_communication_party" style "white_text" widget_class "msg_communication_shout" style "red_text" widget_class "msg_communication_chat" style "lightblue_text" # SPELL messages widget_class "msg_spell_failure" style "grey_text" widget_class "msg_spell_success" style "darkblue_text" widget_class "msg_spell_error" style "darkblue_text" widget_class "msg_spell_target" style "orange_text" # ITEM messages widget_class "msg_item_remove" style "brown_text" widget_class "msg_item_add" style "lightblue_text" widget_class "msg_item_info" style "brown_text" # MISC messages widget_class "msg_misc" style "darkblue_text" # VICTIM messages widget_class "msg_victim_swamp" style "red_text" widget_class "msg_victim_was_hit" style "red_text" widget_class "msg_victim_died" style "darkblue_text" crossfire-client-1.75.3/gtk-v2/themes/Black000644 001751 001751 00000047171 14323707640 021320 0ustar00kevinzkevinz000000 000000 ############################################################################ # http://www.gnu.org/software/emacs/manual/html_node/emacs/GTK-styles.html # has good information that relates to the content of this theme file. # # Where font_name appears, ie. font_name = "Sans Bold Italic 9", the format is # a Pango string, so refer to that documentation for details. One resource is # http://www.gtk.org/api/2.6/pango/PangoMarkupFormat.html, but briefly, there # are various options that can be specified: family, style, weight, size. # # Spaces inside the font name is normal. The font name and options are # generally delimited with space characters. Font-family is a comma separated # list. Style includes things like Italic, Normal, Oblique. Size is in # points with no units. The default size appears to be 10. Weight is also # supported and includes choices like: ultralight, light, normal, bold, # ultrabold, heavy. The font descriptors do not seem to be case sensitive. # It may take experimentation to see what works. It appears, for example, # that all weight identifiers may not be supported for all fonts. # This makes everything black background and white foreground by # default. # style "black_bg" { # base and text are used for the treeview and entry widgets # Note that the inv_.. values below can adjust these for special # objects base[NORMAL] = "black" text[NORMAL] = "white" # The ACTIVE tabs are used for the unselected tabs in the notebooks. bg[ACTIVE] = "black" fg[ACTIVE] = "white" # foreground/background of pretty much all the other widgets bg[NORMAL] = "black" fg[NORMAL] = "white" } widget_class "*" style "black_bg" ############################################################################ # Start of Stat Bar styles ############################################################################ # The stat bars are the bars at the bottom left of the window - hp, # spell points, grace, food & exp. # The low values are used when the stat is less than 25% of its max. # The super value is used when the stat is above is max. # the normal value is used in the 25%->100% range. # # There is no requirement that these be different colors - if you # want the food value to be brown no matter what, just create # a style for food_bar, and bind that to the normal/low/super values. # this is what is done for exp, since being below 25% exp isn't really # bad. # # If you have configured the client to use gradual shading of the # stat bar colors, the gradual values are used instead. The low # as the 0 point, the normal is 100%, and super is 200%. The client # will then mix the color based on the actual value of the stat. I thought # it better to have different values, as what may look good normally may # not blend well (in particular, the standard values are not 100% # saturated since those would seem too bright. # # the reason base[SELECTED] is used for values is that is what # is used if these were being bound directly to the widget. # # if one of the styles is missing a color, the client will use # standard system wide theme defaults to draw in that state. # For the gradual color, if it is missing a color, it just will # not color it - probably not what you want. # # Note: If you are not seeing colorful stat bars as you expect, # the problem may be with the system wide theme you have chosen. # some themes modify the draw logic for the progressbar and instead # draw pixmaps (if you see striped bars, you are using such a theme). # These themes do no pay any attention to the colors we try to set - # IMO, this is a bug in the theme engine, as there isn't way # to turn that behaviour off. The only way around this would be # for the client to have its own widget to draw the bars, but then # this causes problems for those people that like that theme. # style "low_bar" { #red base[SELECTED] = "#cf0000" } style "normal_bar" { # green base[SELECTED] = "#00cf00" } style "super_bar" { base[SELECTED] = "#00cf00" } style "gradual_low_bar" { base[SELECTED] = "red" } style "gradual_full_bar" { base[SELECTED] = "green" } style "gradual_super_bar" { base[SELECTED] = "blue" } widget_class "hp_bar_normal" style "normal_bar" widget_class "hp_bar_low" style "low_bar" widget_class "hp_bar_super" style "super_bar" widget_class "hp_gradual_bar_normal" style "gradual_full_bar" widget_class "hp_gradual_bar_low" style "gradual_low_bar" widget_class "hp_gradual_bar_super" style "gradual_super_bar" widget_class "sp_bar_normal" style "normal_bar" widget_class "sp_bar_low" style "low_bar" widget_class "sp_bar_super" style "super_bar" widget_class "sp_gradual_bar_normal" style "gradual_full_bar" widget_class "sp_gradual_bar_low" style "gradual_low_bar" widget_class "sp_gradual_bar_super" style "gradual_super_bar" widget_class "grace_bar_normal" style "normal_bar" widget_class "grace_bar_low" style "low_bar" widget_class "grace_bar_super" style "super_bar" widget_class "grace_gradual_bar_normal" style "gradual_full_bar" widget_class "grace_gradual_bar_low" style "gradual_low_bar" widget_class "grace_gradual_bar_super" style "gradual_super_bar" widget_class "food_bar_normal" style "normal_bar" widget_class "food_bar_low" style "low_bar" widget_class "food_bar_super" style "super_bar" widget_class "food_gradual_bar_normal" style "gradual_full_bar" widget_class "food_gradual_bar_low" style "gradual_low_bar" widget_class "food_gradual_bar_super" style "gradual_super_bar" # It doesn't make sense to have an alert for low exp, # so set all the conditions to the same color. For graduated # color, it can IMO still be nice to change colors as you get closer. widget_class "exp_bar_normal" style "normal_bar" widget_class "exp_bar_low" style "normal_bar" widget_class "exp_bar_super" style "normal_bar" widget_class "exp_gradual_bar_normal" style "gradual_full_bar" widget_class "exp_gradual_bar_low" style "gradual_low_bar" widget_class "exp_gradual_bar_super" style "gradual_super_bar" ############################################################################ # Start of inventory/look window styles ############################################################################ # # The inv_ do not get tied to real widgets. This is because we are # controlling individual rows of the widget based on values that the # widget can not know about (magic, cursed, etc). So the client looks # up these special names and then uses the value to control how to # draw the actual rows. Note that there is no requirement that there # be 1 style/widget_class. If you want different object criteria # to use the same style, you can do that, eg, # # widget "inv_cursed" style "inv_mine" # widget "inv_magical" style "inv_mine" # # Is perfectly legal, but probably doesn't make a lot of sense. # # Note that there is no 'default' here - the default values come from # the normal widget binding. # # Note that there is no combining of values - only one of these is # used for any object. The precedence is: # unpaid > cursed > magical > applied > locked # style "inv_cursed" { text[NORMAL] = "red" } widget_class "inv_cursed" style "inv_cursed" style "inv_magical" { text[NORMAL] = "skyblue" } widget_class "inv_magical" style "inv_magical" # You owe gold for these style "inv_unpaid" { text[NORMAL] = "gold" } widget_class "inv_unpaid" style "inv_unpaid" style "inv_locked" { font_name = "Sans Italic" } widget_class "inv_locked" style "inv_locked" style "inv_applied" { font_name = "Sans Bold" } widget_class "inv_applied" style "inv_applied" ############################################################################ # Start of spell list styles ############################################################################ # like the inventory styles, these do not bind to a specific widget, # but rather the code uses them based on values of the spell. # style "spell_denied" { text[NORMAL] = "red" } widget_class "spell_denied" style "spell_denied" style "spell_repelled" { text[NORMAL] = "orange" } widget_class "spell_repelled" style "spell_repelled" style "spell_attuned" { text[NORMAL] = "green" } widget_class "spell_attuned" style "spell_attuned" style "spell_normal" { base[NORMAL] = "black" } widget_class "spell_normal" style "spell_normal" ############################################################################ # Start of text info style. The text info are where it actually # displays the messages. ############################################################################ # info_default is a bit special. # What info_default is used for is a supported way for the # code to find out what attributes set in the other info_... # values differ - it will basically compare the values and only set # the ones that are different. This is really just a place holder, # and you probably shouldn't put any actual values within the # style {} area. However, it must be defined for other styles # to work (if it doesn't have anything to get a difference against, # it can not set up the other styles. style "info_default" { } widget_class "info_default" style "info_default" # The extended info has the idea of different fonts: # # Normal: Standard font to use for drawing # Arcane: Perhaps better called 'old style' fonts - still clearly readable, # but should have an 'old' look. # Strange: A runic font that doesn't necessarily need to be readable - could # just be symbols. # Fixed: Fixed width font used for listings of preformatted text. # Hand: A font that should look like handwritten text. # # Note that except for the fixed font, the font you use is not likely # to have a critical effect - if you used the same font for everything, # it is unlikely to affect the play of the game. # Also, while these are defined as font names, you can also define # colors. However, other # styles may take precedence - eg, if you specify a color in the # style definition, and the message itself has color tags, those # may be used instead. # # You can use the gtk character map utility to view the fonts and get # font names. # # Note that the fonts specified here may not be ideal candidates, but # my goal here is to choose fonts that a normal installation would have # installed. You can get better fonts off the web, but since they # are not available by default, it doesn't make sense to make them # the default. # # For normal font, just use the system/theme default. #style "info_font_normal" #{ # font_name = "Sans" #} #widget_class "info_font_normal" style "info_font_normal" style "info_font_arcane" { font_name = "URW Chancery L" } widget_class "info_font_arcane" style "info_font_arcane" # With the different scripts included in unicode (and part # of gtk2), all we really need to do here is change it so that # we use the Runic script instead of Latin. However, there is # no way to do that directly with styles. What needs to be # done is some extra code added to process this as a script and # not a font perhaps. style "info_font_strange" { font_name = "Sans Italic" } widget_class "info_font_strange" style "info_font_strange" style "info_font_fixed" { font_name = "Luxi Mono" } widget_class "info_font_fixed" style "info_font_fixed" # URW Chancery L would also look good for this, but # we're using that for arcane. style "info_font_hand" { font_name = "Century Schoolbook L Italic" } widget_class "info_font_hand" style "info_font_hand" # # The first set of info_ are how to display messages that come # as a certain color from the server. Eg, the server says 'draw this in # black', and this determines how we actually draw it. For example, # when using a black background, you really don't want the text color # to be black. # Note that anything not set here (fg, bg, font) will use default # values as bound to the global widget (*), so you don't need to # specify all the values in each classification. If you don't want # different colored text, just disable all of these. # The values here match the traditional values used. style "black_text" { fg[NORMAL] = "white" } widget_class "info_black" style "black_text" style "white_text" { fg[NORMAL] = "white" font_name = "bold" } widget_class "info_white" style "white_text" style "darkblue_text" { fg[NORMAL] = {0.4, 0.3, 0.8} } widget_class "info_darkblue" style "darkblue_text" style "red_text" { fg[NORMAL] = "red" } widget_class "info_red" style "red_text" style "orange_text" { fg[NORMAL] = "orange" } widget_class "info_orange" style "orange_text" style "lightblue_text" { fg[NORMAL] = "dodgerblue" } widget_class "info_lightblue" style "lightblue_text" style "darkorange_text" { fg[NORMAL] = "darkorange2" } widget_class "info_darkorange" style "darkorange_text" style "green_text" { fg[NORMAL] = "seagreen" } widget_class "info_green" style "green_text" style "darkgreen_text" { fg[NORMAL] = "darkseagreen" } widget_class "info_darkgreen" style "darkgreen_text" style "grey_text" { fg[NORMAL] = "grey50" } widget_class "info_grey" style "grey_text" style "brown_text" { fg[NORMAL] = "sienna" } widget_class "info_brown" style "brown_text" style "yellow_text" { fg[NORMAL] = "gold" } widget_class "info_yellow" style "yellow_text" style "tan_text" { fg[NORMAL] = "khaki" } widget_class "info_tan" style "tan_text" # these msg_.. values determine how to draw output of the # different message types - see the newclient.h and msgtypes.h file for all # the types/subytpes. With this, you can set different output styles # for all of the different message types. # # A few notes: # # 1) it is the widget_class line that binds the the style to the name that # the client uses to look it up. # Thus, you can do something like: # # style "red_text" .... # widget_class "msg_victim_was_pushed" style "red_text" # widget_class "msg_communication_say" style "red_text" # # In this way, you don't need to have a style for every msg type - a more # likely scenario is a modest number of styles, but then binding these # to the different widget names as how you want that widget to be # drawn. The _text entries used above can be re-used # for the msg types here. # # 2) Beyond normal style inheritence rules, the client itself is coded # to do some - just in that way, you don't need to list every msg # type here. For example: # # widget_class "msg_book" style "green_text" # # will result in every message of the BOOK class to be drawn in green # text. If you then add the line: # # widget_class "msg_book_clasp_1" style "red_text" # # messages of type BOOK, subtype CLASP_1 will be drawn in red, with all # the other BOOK message types being drawn in green. # # Note that this works on a type/subtype level, not a # string level. Thus, # you can not do: # # widget_class "msg_book_clasp" style "red_text" # # and have it work, as the "msg_book_clasp" by itself isn't a valid name. # Basically, you can bind it to the overall type (which covers all the # subtypes), or to specific type/subtypes. The common/msgtypes.h file # contains all the valid names (without the msg_ prefix) that are valid. # # 3) Even with the new message types, the server still sends what color # it thinks they should be drawn (this is basically for older clients # predating extended text support). If you do not specify _ANY_ styles for the # message types here, the client will use that color tag for what color # to draw the text with, as set with the info_ section above. # However, if even a single msg_ style is set, then the client will not # use those values - the presumption being that if a msg_ style # is set, the user knows what they are doing, and any that are not # set they want in default color/style. # # This is because there really isn't any way # for the client to know if it is intentional on the part of the user # that they want to use the default styles for the widgets or if it # should be using that color information - this is especially true # given the inheritence described in point #2 above. # # The entries below try to match what color the server says # to use for these - basically, to keep compatibility without # having to use the passed in color value - in that way, # additions can be made and the expected appearance of messages # will remain. # Given this is compatible type messages, we re-use # the color_text styles above. Note that in some cases, # the same type of message used different colors depending # on where in the code it was called. I've tried to use here # whatever was used the most for a particular message, but # I also took into account the message and other related messages # so the color for good vs bad effects are different, etc. To # some extent, the idea that red messages are bad is put in place # here, with blue being good. # # Note - these should really be re-done, as the current color # scheme often makes no sense (same style for both a level # gain and loss?) But this base file is more as a sample # and also act like things have in the past. # # Some colors, like lightgreen, gold & tan are not used by # any message types right now. And some others are used # in only a few places, like greytext, browntext # # these are in type/subtype order, to match msgtypes.h # BOOK messages widget_class "msg_book" style "darkblue_text" # CARD messages # PAPER messages # SIGN messages widget_class "msg_sign" style "darkblue_text" # MONUMENT messages # DIALOG messages widget_class "msg_dialog_npc" style "darkblue_text" widget_class "msg_dialog_magic_ear" style "darkblue_text" # MOTD messages widget_class "msg_motd" style "green_text" # ADMIN messages widget_class "msg_admin_rules" style "green_text" widget_class "msg_admin_news" style "green_text" widget_class "msg_admin_player" style "darkorange_text" widget_class "msg_admin_dm" style "red_text" # SHOP messages # COMMAND messages widget_class "msg_command_quests" style "white_text" widget_class "msg_command_dm" style "red_text" widget_class "msg_command_newplayer" style "lightblue_text" # ATTRIBUTE messages widget_class "msg_attribute_protection_gain" style "lightblue_text" widget_class "msg_attribute_protection_loss" style "red_text" widget_class "msg_attribute_bad_effect_start" style "red_text" widget_class "msg_attribute_level_gain" style "lightblue_text" widget_class "msg_attribute_level_loss" style "red_text" widget_class "msg_attribute_race" style "lightblue_text" widget_class "msg_attribute_god" style "darkblue_text" # SKILL messages widget_class "msg_skill_pray" style "white_text" widget_class "msg_skill_error" style "red_text" # APPLY messages widget_class "msg_apply_success" style "darkblue_text" widget_class "msg_apply_cursed" style "darkblue_text" widget_class "msg_apply_trap" style "darkblue_text" # ATTACK messages widget_class "msg_attack_did_hit" style "red_text" widget_class "msg_attack_nokey" style "darkblue_text" # COMMUNICATION messages widget_class "msg_communication_random" style "white_text" widget_class "msg_communication_say" style "white_text" widget_class "msg_communication_me" style "lightblue_text" widget_class "msg_communication_tell" style "orange_text" widget_class "msg_communication_emote" style "white_text" widget_class "msg_communication_party" style "white_text" widget_class "msg_communication_shout" style "red_text" widget_class "msg_communication_chat" style "lightblue_text" # SPELL messages widget_class "msg_spell_failure" style "grey_text" widget_class "msg_spell_success" style "darkblue_text" widget_class "msg_spell_error" style "darkblue_text" widget_class "msg_spell_target" style "orange_text" # ITEM messages widget_class "msg_item_remove" style "brown_text" widget_class "msg_item_add" style "lightblue_text" widget_class "msg_item_info" style "brown_text" # MISC messages widget_class "msg_misc" style "darkblue_text" # VICTIM messages widget_class "msg_victim_swamp" style "red_text" widget_class "msg_victim_was_hit" style "red_text" widget_class "msg_victim_died" style "darkblue_text" crossfire-client-1.75.3/gtk-v2/TODO000644 001751 001751 00000003055 14045044275 017554 0ustar00kevinzkevinz000000 000000 This file is meant to be a short list of things that need to be done, in no particular order (thus, unnumbered) Bugs to fix: - Fix or implement the scroll bar handles on the map display. Other work: - Make an image for the 'icons' inventory tab (perhaps an eye?) - Implement the arrow buttons to scroll map around so that the player does not have to be in the middle (eg, after you thing you have completed a level, you should be able to scroll around and look at the fog of war spaces and see if you've missed anything). - Add a window for configuration selection - Perhaps a better splash graphic to show while not connected, since there is a lot more space that is not being used. - Perhaps tie in some display options with scripting? Eg, and inventory tab in which an external script can be used to determine whether to show objects or not, perhaps same for information messages? - Implement drag and drop for the inventory/look windows (would allow moving objects from a container directly to the ground for example. - Change container handling - the client can properly handle multiple containers now. On the client side, not much needs to be changed. On the server side, the server will need to update all active containers when their contents change. - Add support for lower screen resolution (1024x768). With libglade support, this may already be taken care of, or it may also involve things like letting a user pick a smaller font in various places.. - Add split window support (probably requires second glade config file) setup) crossfire-client-1.75.3/gtk-v2/ui/000755 001751 001751 00000000000 14605665664 017513 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/gtk-v2/ui/chthonic.ui000644 001751 001751 00000452611 14226677555 021663 0ustar00kevinzkevinz000000 000000 1000000 1 False Crossfire Client - GTK v2 1275 945 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True False True False 1 True False False True 2 True False False False 3 False False 0 1275 920 True True 320 True True 750 True False True False True True False 0 2 Inventory: True True 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False Count False False 5 2 True True False False True True adjustment1 1 True True True 3 False True 0 True False True True never True True True True 11 10 True False Icons False True True 1 False True True False 0 in True True never True True True False <b>You see:</b> True True True False True True True 750 True True 630 True True 2 False 600 550 True False True False Map False True False 1 True False Magic Map 1 False False True True False True True 200 True False 0 none True False 2 queue True True never True True False False False True False 3 <b>Critical Messages</b> True False True True False 0 none True False 2 queue True True never True True False False False True False 3 <b>Messages</b> True True True True True 0 True True False False True True False False 2 1 True True True True True True 630 True False 0 in True True 250 True True False 2 queue True False True False True False 0 Player: False False 3 0 True False 0 Level: 10 False False 5 1 False False 3 0 True False True False 0 Skill False False 3 0 False False 4 1 True False True False 0 Speed 6 False False 3 0 True False False False 1 False False 3 2 True False True False 0 Weapon Speed False False 3 0 True False False False 1 False False 4 3 True False True False 0 Experience: False False 3 0 False False 3 4 True False True False 0 5 False False 5 0 True False 0 5 False False 5 1 False False 4 5 True True True False 2 queue True False 2 6 3 4 True False 0 3 5 6 GTK_FILL True False 0.10000000149 1 2 2 True False 0.10000000149 1 2 1 2 2 True False 0.10000000149 1 2 2 3 2 True False 0.10000000149 1 2 3 4 2 True False 0.10000000149 1 2 4 5 2 True False 0 2 HP: GTK_FILL True False 0 2 SP: 1 2 GTK_FILL True False 0 2 Grace: 2 3 GTK_FILL True False 0 2 Food: 3 4 GTK_FILL True False 0 2 Exp: 4 5 GTK_FILL True True True False <b>Character</b> True True True True True True False 6 6 True True False Protections False True False 5 7 6 5 5 True False 0 1 6 6 7 GTK_FILL True False 0 1 6 5 6 GTK_FILL True False 0 1 6 4 5 GTK_FILL True False 0 1 6 3 4 GTK_FILL True False 0 1 6 2 3 GTK_FILL True False 0 5 6 1 2 GTK_FILL True False 0 3 4 1 2 GTK_FILL True False 0 Armor 4 5 1 2 GTK_FILL True False 0 Armor Class 2 3 1 2 GTK_FILL True False 0 5 6 GTK_FILL True False 0 Damage 4 5 GTK_FILL True False 0 3 4 GTK_FILL True False 0 Weapon Class 2 3 GTK_FILL True False 0 Charisma 6 7 GTK_FILL True False 0 Power 5 6 GTK_FILL True False 0 Wisdom 4 5 GTK_FILL True False 0 Intelligence 3 4 GTK_FILL True False 0 Constitution 2 3 GTK_FILL True False 0 1 2 1 2 GTK_FILL True False 0 Dexterity 1 2 GTK_FILL True False 0 1 2 GTK_FILL True False 0 Strength GTK_FILL 1 True False Core Statistics 1 False True True True True True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/eureka.ui000644 001751 001751 00000444575 14226677555 021352 0ustar00kevinzkevinz000000 000000 1000000 1 1180 925 False Crossfire Client - GTK v2 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True False True False 1 True False False True 2 True False False False 3 False False 0 True True 750 1275 True True 320 True True 550 True False True False True True False Inventory: False False 10 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False Count False False 5 2 True True False False True True adjustment1 1 True True True 3 False True 0 True False True True never True True True True 11 10 True False Icons False True True 1 False True True False 3 True False You see: False False 2 0 True True never True True True True 1 True True False True True True 570 True True 2 False 550 600 True False True False Map False True False 1 True False Magic Map 1 False False True True False True True 200 True False 0 none True False True True never True True False False False True False 3 <b>Messages</b> True False True True False 0 none True False True True never True True False False False True False 3 <b>Critical Messages</b> True False True True True 0 True True False False True True False False 2 1 True True True True False True True True 450 True False 2 6 3 4 True False 2 3 5 6 GTK_FILL True False 5 6 GTK_FILL True False True False 0 5 False False 5 0 True False 0 5 False False 5 1 1 2 5 6 GTK_FILL True False 0 2 Exp: 4 5 GTK_FILL True False 0 2 Food: 3 4 GTK_FILL True False 0 2 Grace: 2 3 GTK_FILL True False 0 2 SP: 1 2 GTK_FILL True False 0 2 HP: GTK_FILL True False 0.10000000149 1 2 4 5 2 True False 0.10000000149 1 2 3 4 2 True False 0.10000000149 1 2 2 3 2 True False 0.10000000149 1 2 1 2 2 True False 0.10000000149 1 2 2 False True True True 2 True False True True False Player: False False 0 True False True True False Str False False 0 True False False False 1 True False Dex False False 2 True False False False 3 True False Con False False 4 True False False False 5 True False Int False False 6 True False False False 7 True False Wis False False 8 True False False False 9 True False Pow False False 10 True False False False 11 True False Cha False False 12 True False False False 13 True True 1 True False True True False WC False False 0 True False False False 1 True False Dam False False 2 True False False False 3 True False AC False False 4 True False False False 5 True False Armor False False 6 True False False False 7 True True 2 True False True True False Speed False False 0 True False False False 1 True False Weapon Speed False False 2 True False False False 3 False False 3 True False Range: False False 4 True False True True False Experience: False False 0 True False Level: False False 1 True True 5 True False Core Stats False True False 6 6 True 1 True False Skills & Experience 1 False True False 6 6 True 2 True False Protections 2 False True True True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/lobotomy.ui000644 001751 001751 00000537731 14226677555 021737 0ustar00kevinzkevinz000000 000000 1000000 1 10 1280 925 False Crossfire Client - GTK v2 1280 925 True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True True 960 True True 770 True True 620 True True 2 False True False True False Map False True False 1 True False Magic Map 1 False False True True True 600 True False 2 True True never True True True True 11 10 True False Icons False False True True False 2 0 in True True never True True True False <b>View</b> True True True True True False True True False True False 2 0 in True False 2 6 6 2 True False <b>Skills</b> True True True 0 True False 2 0 in True False 2 6 6 2 True False <b>Protections</b> True False True 1 True True False True True False True False 2 True False True False 0 5 Player: True True 0 True False 1 5 Level: right False False 1 False False 0 True True 400 True False 2 0 in True True 2 automatic True in True False False char False False True False 3 <b>Messages</b> True True True True False 2 0 in True True 2 automatic in True False False char False False True False 3 <b>Critical Messages</b> True True True True True 2 1 True False 2 queue True True False False True True False False 2 True True 2 never never in True False none True False True False True False 0 2 Weight: False True 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True True 0 True False True False 1 2 Count: right False False 0 True True False False True True adjustment1 1 True False True 1 False True 1 False True 3 True True 2 never never in True False 2 none True False True False 0 2 Range: False False 1 0 True False False True 1 1 True False True False 1 2 right True True 0 True False 0 2 True True 1 False True 2 True False False True 3 True False True False 0 2 Speed (Weapon): False False 0 True False 0 2 0 right False False 1 True False 2 ( False False 2 True False 0 2 0 right False False 3 True False 0 2 ) True True 4 False True 4 False True 4 True True 2 never never in True False none True False True False True False 2 2 True False 1 2 0 right 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Dam 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 WC GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL False False 0 True False False True 2 1 True False 2 2 True False 1 2 0 right 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Armor 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 AC GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL False False 2 True False False True 2 3 True False False True 2 4 True False 7 2 True False 1 2 0 right 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 6 7 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 5 6 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 4 5 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 3 4 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 1 2 0 right 1 2 2 3 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Cha 6 7 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Pow 5 6 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Wis 4 5 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Int 3 4 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Con 2 3 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Dex 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Str GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL False False 5 False False 0 True False False True 2 1 True False False True 2 2 True False True False True False 0 2 HP: False False 0 False False 1 0 20 True False 0.10000000149 False False 1 True False True False 0 2 SP: False False 0 False False 1 2 20 True False 0.10000000149 False False 3 True False True False 0 2 Grace: False False 0 False False 1 4 20 True False 0.10000000149 False False 5 True False True False 0 2 Food: False False 0 False False 1 6 20 True False 0.10000000149 False False 7 True False True False 0 2 Exp: False False 0 False False 1 8 20 True False 0.10000000149 False False 9 True True 2 3 False False 5 True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/gtk-v2.ui000644 001751 001751 00000302275 14323707640 021161 0ustar00kevinzkevinz000000 000000 1000000 1 False Crossfire Client 1024 640 True False True False True False _File True False gtk-disconnect True False True True accelgroup1 gtk-quit True False True True accelgroup1 True False _Edit True False True False Keybindings True True False Configure message routing and buffering. Message Filters True True False Save Window Position True gtk-preferences True False True True accelgroup1 True False Player True False True False Spells True True False Skills True True False gtk-delete True False Permenantly delete this character True True accelgroup1 True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False gtk-about True False True True accelgroup1 False True 0 True True 820 True True 847 True True False True False True False Map False True False 1 True False Magic Map 1 False True False True True 300 True False 2 queue True False True False 5 2 True False 0.10000000149 1 2 True False 0.10000000149 1 2 1 2 True False 0.10000000149 1 2 2 3 True False 0.10000000149 1 2 3 4 True False 0.10000000149 1 2 4 5 True False 1 5 Health GTK_FILL True False 1 5 Mana 1 2 GTK_FILL True False 1 5 Grace 2 3 GTK_FILL True False 1 5 Food 3 4 GTK_FILL True False 1 5 Exp 4 5 GTK_FILL True True 0 True False True True 1 True False True True 2 True False True True 2 True False True False Player: False True 7 0 True False 5 5 14 True True False Strength 0 5 Str 12 13 True False 0 0 13 14 True False Dexterity 0 5 Dex 4 5 True False 0 0 5 6 True False Constitution 0 5 Con 2 3 True False 0 0 3 4 True False Intelligence 0 5 Int 6 7 True False 0 0 7 8 True False Wisdom 0 5 Wis 10 11 True False 0 0 11 12 True False Power 0 5 Pow 8 9 True False 0 0 9 10 True False Charisma 0 5 Cha True False 0 0 1 2 True False Weapon Class 0 5 WC 5 7 2 3 True False 0 0 7 9 2 3 True False Damage 0 5 Dam 9 11 2 3 True False 0 0 11 13 2 3 True False Armor Class 0 5 AC 1 3 1 2 True False 0 0 3 5 1 2 True False Armor 0 5 Armor 5 7 1 2 True False 0 0 7 9 1 2 True False Movement Speed 0 5 Spd 9 11 1 2 True False 0 0 11 13 1 2 True False Weapon Speed 0 5 WS 1 3 2 3 True False 0 0 3 5 2 3 True False Current Attack 5 Range: 14 3 4 True False 5 Experience: 7 4 5 True False 5 Level: 7 14 4 5 True True 1 True False Core Stats False True False 6 6 True 1 True False Protections 1 False True False False False True False True True True False True True True False 2 queue True True never True True False False False True False Messages False True False 2 queue True True never True True False False False 1 True False Important Messages 1 False True True 0 True True False False True True False False 1 False False True True True False True False True True False 0 2 Inventory: True True 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False 1 5 Count: right False True 2 True True False False True True adjustment1 1 True False True 3 False True 0 True False True True never True True True True 11 10 True False Icons False True True 1 False False True False True False 0 3 You see: False False 0 True True never True True True True 1 True False True False False False True True 1 crossfire-client-1.75.3/gtk-v2/ui/un-deux.ui000644 001751 001751 00000473161 14226677555 021454 0ustar00kevinzkevinz000000 000000 1000000 1 1180 925 False Crossfire Client - GTK v2 1180 925 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True False True False 1 True False False True 2 True False False False 3 False False 0 True True 875 True True 730 True True 240 True False True False 0 none True False True True never in True True False 2 2 False False True False 3 <b>Messages:</b> True True True 0 True True False False True True False False 2 1 True True never never in True False none True False 2 True False 0 True True 0 True False 0 True True 1 False False 2 False True True True 100 True False 0 in True False True True False 5 True False Player: False False 5 0 True False Level: False False 5 1 True False Experience: False False 5 2 False False 0 True False 5 True False Speed False False 5 0 True False False False 1 True False Weapon Speed False False 5 2 True False False False 3 True True 1 True False 5 True False Range: False False 5 0 True True 2 True False 5 True False WC False False 5 0 True False False False 1 True False Dam False False 5 2 True False False False 3 True False AC False False 5 4 True False False False 5 True False Armor False False 5 6 True False False False 7 False False 3 True False 5 True False Str False False 5 0 True False False False 1 True False Dex False False 5 2 True False False False 3 True False Con False False 5 4 True False False False 5 True False Int False False 5 6 True False False False 7 True False Wis False False 5 8 True False False False 9 True False Pow False False 5 10 True False False False 11 True False Cha False False 5 12 True False False False 13 False False 4 True False <b>Core Stats</b> True True True True True 2 False True False True False Map False True False 1 True False Magic Map 1 False True True True True False True True True 240 True False 0 none True False True True never in True True False 2 2 False False True False 3 <b>Critical Messages:</b> True False True True True 280 True False True False True False 0 2 HP: False True 0 False True 0 15 True False 0.10000000149 False False 1 True False True False 0 2 Spell Points: False True 0 False True 2 15 True False 0.10000000149 False False 3 True False True False 0 2 Grace: False True 0 False True 4 15 True False 0.10000000149 False False 5 True False True False 0 2 Food: False True 0 False True 6 15 True False 0.10000000149 False False 7 True False True False 0 2 Exp: False True 0 False True 8 15 True False 0.10000000149 False False 9 False True True False 0 none True False 2 True True never never in True False none True False 6 6 True True False <b>Protections:</b> True True True True True True True False True True True 730 True False 0 none True False True False True False True True never True True True True 11 10 True False Icons False True True 0 True False True True False 0 2 Inventory: True True 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False Count False False 5 2 True True False False True True adjustment1 1 True True True 3 False True 1 True False <b>Inventory:</b> True False True True False 0 none True False True True 2 never in True True True False <b>Ground:</b> True True True True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/gtk-v1.ui000644 001751 001751 00000663054 14226677555 021202 0ustar00kevinzkevinz000000 000000 1000000 1 1180 925 False Crossfire Client - GTK v2 1180 925 True False True False True False True False _File True False gtk-disconnect True False True True accelgroup1 gtk-quit True False True True accelgroup1 True False _Edit True False True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True gtk-preferences True False True True accelgroup1 True False Player True False True False Spells True True False Skills True True False gtk-delete True False Permenantly delete this character True True accelgroup1 True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False gtk-about True False True True accelgroup1 False False 0 True False True False 1 True False False True 2 True False False False 3 False False 0 1601 True True 320 True True 715 True False True False True True False 0 2 Inventory: True True 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False Count False False 5 2 True True False False True True adjustment1 1 True True True 3 False True 0 True False True True never True True True True 11 10 True False Icons False True True 1 False True True False 3 True False You see: False False 2 0 True True never True True True True 1 True True False True True True 575 True True 185 True True 92 True False 2 2 True True False 8 True False Player: False False 0 False False 0 True False 8 True False Score: False False 0 True False 2 Level: False False 1 True True 1 True False 8 True False True False S False False 0 True False 0 False False 1 False True 0 True False True False D False False 0 True False 0 False False 1 False True 1 True False True False Co False False 0 True False 0 False False 1 False True 2 True False True False I False False 0 True False 3 0 False False 1 False True 3 True False True False W False False 0 True False 0 False False 1 False True 4 True False True False P False False 0 True False 0 False False 1 False True 5 True False True False Ch False False 0 True False 0 False False 1 False True 6 True True 2 True False 8 True False True False Wc: False False 0 True False 2 0 False False 1 False True 0 True False True False 2 Dam: False False 0 True False 2 0 False False 1 False True 1 True False True False 2 Ac: False False 0 True False 2 0 False False 1 False True 2 True False True False 2 Armor: False False 0 True False 2 0 False False 1 False True 3 False False 3 True False 8 True False True False Speed: False False 0 True False 2 0 False False 1 False True 0 True False True False ( False False 0 True False 2 0 False False 1 True False ) False False 2 False True 1 False False 4 True False 8 True False Skill: False False 0 True True 5 False True True True 2 never automatic in True False 2 6 6 True True True False True True True 530 True True 2 False True False True False Map False True False 1 False True False Magic Map 1 False True True True True 285 True False True False 5 2 True False 0.10000000149 1 2 True False 0.10000000149 1 2 1 2 True False 0.10000000149 1 2 2 3 True False 0.10000000149 1 2 3 4 True False 0.10000000149 1 2 4 5 True False 1 5 Health GTK_FILL True False 1 5 Mana 1 2 GTK_FILL True False 1 5 Grace 2 3 GTK_FILL True False 1 5 Food 3 4 GTK_FILL True False 1 5 Exp 4 5 GTK_FILL True True 0 True False True False 0 True True 0 True False 0 True True 1 True True 1 False True True True 2 never automatic in True False True False 2 6 6 True True True True True True True False True True False True True 205 True False 0 none True False True True never in True True 2 False 2 2 False False True False 3 <b>Critical Messages</b> True False True True False 0 none True False True True never in True True 2 False 2 2 False False True False 3 <b>Messages</b> True True True True True 0 True True False False True True False False 2 1 True True True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/sixforty.ui000644 001751 001751 00000425213 14226677555 021751 0ustar00kevinzkevinz000000 000000 1000000 1 10 False Crossfire GTK V2 Client - SixForty 640 480 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True True False Ratio >= 10 True True True False Ratio >= 15 True True True False Ratio >= 20 True True True False Ratio >= 25 True True True False Ratio >= 30 True True True False Ratio >= 35 True True True False Ratio >= 40 True True True False Ratio >= 45 True True True False Ratio >= 50 True True True False Ignore cursed True True False _Help True False True False _About True False False 0 True False True False 0 2 True True 0 True False 0 2 True True 1 True True 1 True False 0 2 Player: True True 8 2 True False 0 2 Lvl: True True 3 True False 0 2 Experience: True True 4 False False 0 True True 356 True True 296 True True False True False True False Map False True False 1 True False Magic Map 1 False False True True True 2 True True automatic never True False queue none True False 2 7 8 5 True False True False 0 2 Encumbrance: False False 0 True False 0 0 False False 1 True False 0 / False False 2 True False 0 False False 3 6 8 5 6 GTK_EXPAND | GTK_SHRINK | GTK_FILL True False 5 6 6 GTK_FILL True False 2 3 7 GTK_FILL True False 0 2 Str GTK_FILL True False 0 0 1 2 GTK_FILL True False 0 2 Dex 1 2 GTK_FILL True False 0 2 Con 2 3 GTK_FILL True False 0 2 Int 3 4 GTK_FILL True False 0 2 Wis 4 5 GTK_FILL True False 0 2 Pow 5 6 GTK_FILL 13 True False 0 0.10000000149 HP 6 7 GTK_SHRINK | GTK_FILL 13 True False 0 0.10000000149 SP 6 7 1 2 GTK_SHRINK | GTK_FILL 13 True False 0 0.10000000149 Grace 6 7 2 3 GTK_SHRINK | GTK_FILL 13 True False 0 0.10000000149 Food 6 7 3 4 GTK_SHRINK | GTK_FILL 13 True False 0 0.10000000149 Exp to Next Level 6 7 4 5 GTK_SHRINK | GTK_FILL True False 0 0 1 2 1 2 GTK_FILL True False 0 0 1 2 2 3 GTK_FILL True False 0 0 1 2 3 4 GTK_FILL True False 0 0 1 2 4 5 GTK_FILL True False 0 0 1 2 5 6 GTK_FILL True False 0 2 Cha 6 7 GTK_FILL True False 0 0 1 2 6 7 GTK_FILL True False 0 2 WSp 3 4 GTK_FILL True False 0 0 4 5 GTK_FILL True False 0 2 Sp 3 4 1 2 GTK_FILL True False 0 0 4 5 1 2 GTK_FILL True False 0 2 WC 3 4 2 3 GTK_FILL True False 0 0 4 5 2 3 GTK_FILL True False 0 2 Dam 3 4 3 4 GTK_FILL True False 0 0 4 5 3 4 GTK_FILL True False 0 2 AC 3 4 4 5 GTK_FILL True False 0 0 4 5 4 5 GTK_FILL True False 0 2 Arm 3 4 5 6 GTK_FILL True False 0 0 4 5 5 6 GTK_FILL True False True False 0 2 Range: False False 0 3 8 6 7 GTK_SHRINK | GTK_FILL True False Stats False True True automatic automatic True False queue none True False 6 6 True 1 True False Protections 1 False True True False True True False True True 2 134 True False True True never True True True True 11 10 True False Icons False True True True True 92 True True never True True False True True True 70 True False 0 in True True 2 never in True True False False False True False <b>Messages</b> True False True True False 0 in True True 2 never in True True False False False True False <b>Critical messages</b> True True True True True True True True True 0 True False 2 True True False False True True True True 0 True False 1 5 Count: right False False 1 True True False False True True adjustment1 1 True True True 2 False True 1 True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/dialogs.ui000644 001751 001751 00000777602 14323707640 021503 0ustar00kevinzkevinz000000 000000 False 5 dialog Crossfire Client 1.75.2 Copyright © 1999-2022 Mark Wedel, Crossfire Development Team Copyright © 1992 Frank Tore Johansen A free, open-source, cooperative multi-player RPG and adventure game http://crossfire.real-time.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Mark Wedel <mwedel@sonic.net> David Sundqvist <azzie@netpolicy.com> Raphael Quinet <Raphael.Quinet@eed.ericsson.se> Jacek Konieczny <jajcus@zeus.polsl.gliwice.pl> Eric Anderson Scott MacFiggen <smurf@CSUA.Berkeley.EDU> Kevin Bulgrien <kbulgrien@att.net> Kevin Zheng <kevinz5000@gmail.com> True False False False True end 0 1 20 1 1 10 1 20 1 1 10 1 20 1 1 10 1 96 16 1 8 1 96 16 1 8 False Message Control center-on-parent False True False True False 16 <b>Message Suppression and Routing</b> True False True 0 True False False True 1 True False 3 4 True False 2 2 True False 1 Timer right 1 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_FILL 2 True True The maximum time that a message may reside in the buffer before it must be displayed. 8 ticks is approximately 1 second. 2 True True False False True True adjustment13 True True 1 2 1 2 GTK_SHRINK | GTK_FILL GTK_FILL 2 2 True True The number times a message may occur before it must be displayed. If a message is not already in the buffer, it is always output one time with no delay. 2 True True False False True True adjustment14 True True 1 2 GTK_SHRINK | GTK_FILL GTK_FILL 2 2 True False 1 Output Count right GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_FILL 2 2 GTK_EXPAND | GTK_SHRINK | GTK_FILL GTK_FILL True False 2 3 GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL True False 0 2 Critical 3 4 GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL 2 2 True False Choose one or more message panels that should display each message type. 0 2 Messages 3 4 1 2 GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL 2 2 True False Choose one or more message panels that should display each message type. 0 2 Messages 2 3 1 2 GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL 2 2 True False 4 2 3 GTK_SHRINK | GTK_FILL 2 True False 0 2 Suppress True 1 2 GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL 2 2 True False When identical messages arrive in close succession, do not output them all, but report how many arrived. 0 2 Duplicates 1 2 1 2 GTK_SHRINK | GTK_FILL GTK_SHRINK | GTK_FILL 2 2 False True 2 True False False True 3 True False 2 spread gtk-save True True True Apply and save the currently displayed settings to disk. True False False 0 Load True True True Restore the previously saved settings from disk. False False 1 Defaults True True True Load the default settings built into the client. False False 2 gtk-apply True True True Apply the currently displayed settings. True False False 3 gtk-close True True True True Apply the displayed settings and close the dialog. True False False 4 False True 2 4 1 20 1 1 10 1 20 1 1 10 1 20 1 1 10 1 20 1 1 10 600 False Character Creation center-on-parent False True False 2 2 2 2 True False 2 True False 10 <b>Create a New Character</b> True False True 0 True False False True 1 1 True False True False 2 2 <b>Character Name:</b> True False True 5 0 True True â— False False True True True True 2 1 True True 2 True False 0 in True False 2 2 2 2 True False queue 100 True False 9 5 True False True Strength determines how much a character can carry, as well as how effective the character is with melee weapons. Fighters need a high strength. Strength 1 2 True False True Constitution is the physical hardiness of the character. High constitution will grant extra hit points for each level. Constitution is important for all classes. Constitution 3 4 True False True Wisdom is how in tune the character is with their god. High wisdom makes it easier for a character to learn new prayers and is largely responsible for how many grace points the character has. Wisdom is a key attribute for priests. Wisdom 5 6 True False True Power is a measurement of how in tune the character is with magic forces. It is a major factor in how many mana points the character has, and has a lesser influence on how many grace points the character has. High power is important for wizards. Power 6 7 True False True Charisma is a measurement of likability for the character. If the character has a high charisma, creatures the character meets will act more favorably to the character. The main effect of this is the pricing the character gets in shops. Charisma 7 8 True False True Intelligence is a measure of how smart the character is. High intelligence gives additional mana points for casting spells and makes it easier for the character to learn new spells. Intelligence is a key attribute for wizards. Intelligence 4 5 True False True Dexterity is how quick and nimble the character is. High dexterity makes the character harder to hit, lets the character move faster as well as attack faster. Dexterity 2 3 True True â— False False True True adjustment6 1 2 1 2 2 True True â— False False True True adjustment7 1 2 2 3 2 1 True True â— False False True True adjustment8 1 2 3 4 2 True True â— False False True True adjustment9 1 2 4 5 2 1 True True â— False False True True adjustment10 1 2 5 6 2 True True â— False False True True adjustment11 1 2 6 7 2 1 True True â— False False True True adjustment12 1 2 7 8 2 True False True Adjust your base attributes to be between 1 and 20. The characters final attributes after adjustment for class and race can not be below one, but can be above 20. Base Attribute 1 2 5 2 True False True Select the race you want to play. Different races have different advantages and disadvantages, and some are suited more towards certain classes than others. 2 3 2 2 True False 2 3 2 3 True False 2 3 3 4 True False 2 3 4 5 True False 2 3 5 6 True False 2 3 6 7 True False 2 3 7 8 True False 3 4 2 2 True False 2 3 1 2 True False 3 4 1 2 True False 3 4 2 3 True False 3 4 3 4 True False 3 4 4 5 True False 3 4 5 6 True False 3 4 6 7 True False 3 4 7 8 True False Total 4 5 2 2 True False 4 5 1 2 True False 4 5 2 3 True False 4 5 3 4 True False 4 5 4 5 True False 4 5 6 7 True False 4 5 5 6 True False 4 5 7 8 True False 2 2 True False 3 8 9 GTK_EXPAND | GTK_SHRINK 50 True False 4 5 8 9 GTK_EXPAND | GTK_SHRINK True False True Charisma is a measurement of likability for the character. If the character has a high charisma, creatures the character meet will act more favorably to the character. The main effect of this is the pricing the character gets in shops. Unused Points: 3 4 8 9 True False 2 <b>Character Attributes</b> True False False 2 3 True False True False 0 in True False 2 2 2 2 True True automatic automatic in 100 150 True True False word-char 5 5 True False 2 <b>Race Description</b> True True True 1 0 True False 0 in True False 2 2 2 2 True True automatic automatic in 100 150 True True False word-char True False 2 <b>Class Description</b> True True True 1 1 True True 4 True False 0 in True False 2 2 2 2 True False True False False True True 0 False True True 1 True True 0 True False False True True 0 False True True 1 True True 1 1 True False False True True 0 False True True 1 True True 2 True False False True True 0 False True True 1 True True 1 3 True False False True True 0 False True True 1 True True 4 True False False True True 0 False True True 1 True True 1 5 True False 2 <b>Character Options</b> True True True 2 5 True False True False <b>Status:</b> True False False 5 0 True False True True 1 True True 6 True False False True 1 7 True False 4 gtk-go-back True True True True False False 0 gtk-go-forward True True True True False False 1 True True 8 600 300 False Starting Map center-on-parent False True False 2 2 2 2 True False 1 True False 11 <b>Choose a Map to Start Playing On</b> True False True 0 True False False True 2 1 True False True False 0 0 0 5 5 True False False True 0 True True automatic automatic in True True word-char True True 1 1 True True 1 2 True False False True 2 3 True False 2 spread gtk-go-back True True True True False False 0 gtk-ok True True True True False False 1 False True 2 4 True Crossfire Client center-on-parent 800 400 True False 5 5 5 5 True False True True False True False True False 0 none True False 5 5 5 True True automatic automatic True True True False <b>Select a server:</b> True True True 0 True False 3 True False 10 <b>Or enter your own:</b> True False False 0 True True â— True True False False True True True True 1 gtk-connect True False True True True True True False True 2 False True 1 True False False True 2 True False 0 False True False 5 True True True True never automatic in 350 250 True False False word 5 5 True False News False True True never automatic in 350 99 True False False word 5 5 1 True False Message of the Day 1 False True True never automatic in 300 250 True False False word 5 5 2 True False Rules 2 False True True 0 True False True False 0 none True False 5 5 5 True False True False 0 Name True True 0 True True 30 â— True True False False True True True True 1 True False 0 Password True True 2 True True False â— True True False False True True True True 3 True False 0 5 True word-char 40 True True 4 Login True True True True True True True 5 gtk-disconnect True True True True True True 6 True False <b>Have an account?</b> True False True 0 True False 0 none True False 5 5 5 True False True False If you don't have an account, you can create one and link any existing characters to it. True True True True 0 Create Account True True True 0.56000000238418579 True True 1 True False <b>Don't have an account?</b> True False True 1 False True 1 1 True False 1 1 False True False True False 5 <b>Create New Account</b> True False True 0 True False 5 True False 0 in True False 5 5 5 True False 5 True False 0 Name: True True 0 True True â— True True False False True True True True 1 True False 0 Enter Password: True True 2 True True False â— True False False True True True True 3 True False 0 Confirm Password: True True 4 True True False â— True False False True True True True 5 True False 5 True True 6 True False <b>New Account</b> True False True 0 True False 0 in True False 5 5 5 True True never automatic True False True False word 5 5 True False <b>Rules</b> True True True 1 True True 1 True False spread gtk-go-back True True True True False False 0 Create Account True True True False False 1 False True 2 2 True False 2 2 False True False True False 0 in True False 5 5 5 True True automatic automatic in 500 250 True True True False <b>Choose a character to play:</b> True True True 0 True False spread gtk-go-back True True True True True True 0 gtk-new True True True Create a new character True True True 1 Add Existing True True True Link a character to this account True True 2 Change Password True True True Change account password True True 3 gtk-media-play True True True True True True 4 False True 1 3 True False 3 3 False True False True False 10 <b>Change Account Password</b> True False True 0 True False False True 1 True False 5 True True False 2 2 2 2 True False 5 True False 0 Current password: True True 0 True True False â— True True False False True True True True 1 True False 0 Enter new password: True True 2 True True False â— True False False True True True True 3 True False 0 Confirm Password: True True 4 True True False â— True False False True True True True 5 True False 5 True True 6 False True 0 False True 2 True False False True 5 3 True False 4 spread gtk-go-back True True True True right False False 0 gtk-ok True True True True False False 1 False True 4 4 True False 4 4 False True False 5 5 5 5 True False True False 10 <b>Associate a Character with Your Account</b> True False True 0 True False 0 in True False 5 True False True False True False 5 True False 0 1 Name: False True 0 True True â— True True False False True True False True 1 True False 0 1 Password: False True 2 True True False â— True False False True True False True 3 False True 5 0 True False 5 5 This is where characters are added to an account if they were created before account logins existed. Enter a character name and password to add this account. The character must already exist on the server. True True True 1 False True 0 True False 0 False True 1 True False <b>Character</b> True False True 1 True False spread gtk-go-back True True True True False False 0 gtk-add True True True True False False 1 False True 2 5 True False 5 5 False True True 0 True False spread gtk-quit True False False True True True 0 gtk-refresh True True True True False False 1 gtk-preferences True False False True True True 2 False True 2 1 600 False Keybindings center-on-parent False True False True True in True False True True 1 0 True False 10 10 True False True False True False <b>Scope:</b> True False False 1 0 True False spread char (this character only) True True False True True False False 0 global (all characters) True True False True kb_scope_togglebutton_character False False 1 False True 2 1 False True 0 True False True False <b>Modifiers:</b> True False True 1 0 Any True True False True False True 1 Run True True False True True False True 2 Fire True True False True True False True 3 Alt True True False True True False True 4 Meta True True False True True False True 5 False True 1 True False True False Key: False True 0 True True â— False False True True True True 11 1 True False Command: False True 2 True True â— False False True True True True 5 3 Stay in Edit Mode True True False True True Keybinding will not be executed immediately - instead, will stay in edit mode so additional text can be entered before command is executed. False True 4 False True 1 2 False True 1 True False False True 2 2 True False spread gtk-remove True True False True True False False 0 Update Binding True True False True False False 1 gtk-add True True False True True False False 2 gtk-clear True True False True True False False 3 gtk-close True True False True True False False 4 False True 2 3 None 0 Per Tile 1 Fast Per Pixel (Recommended) 2 Best Per Pixel 3 False 5 Preferences preferences-desktop dialog False True False 2 True False end gtk-apply True True True True True True False False 0 True True 0 True False True False 10 10 True False True False 2 2 True False Requires restart 1 2 True False Requires restart 1 2 1 2 True False Layout True True False Theme 1 2 False True 0 Display timestamps on messages True False False True False True 1 Show sent commands in message window True False False Print the commands that are sent to the server when a keybinding is used. True False True 2 Change status bar color to reflect percentage True False False Only works for some GTK themes True False True 3 True False Sound and general user interface settings. Interface True False True False 10 10 True False Cache images True False False Lowers bandwidth usage, but requires disk space. Map tiles may appear as '?' until they are cached. True False True 0 Prefetch images (when caching is enabled) True False False If caching is enabled, download all images from the server at connection time. This prevents '?' from showing up in the map, but significantly increases startup time. True False True 1 Disable Nagle's algorithm True False False Sets TCP_NODELAY. May decrease latency at the expense of using more out-going bandwidth. True False True 2 1 True False Network 1 False True False 10 10 True False True False 3 2 True False 10 Renderer GTK_FILL True False 10 Lighting 1 2 GTK_FILL True False all sdl_lighting_liststore 0 1 2 1 2 170 True False Requires restart. Not all tile sets are available on all servers. 1 2 2 3 True False Requires restart. SDL is the best, followed by OpenGL. Use Pixmap if neither are available. display_mode_liststore 0 1 2 True False Tile Set 2 3 GTK_FILL False True 0 Enable fog of war True False False Map tiles not in the character's line-of-sight grey out rather than black out. True False True 1 Enable smoothing True False False The map looks nicer, but CPU loading and bandwidth requirements increase. True False True 2 2 True False Rendering 2 False True False 10 10 True False Enable sound effects True False False True False True 0 Beep when food is low True False False True False True 1 3 True False Sound 3 False True True 1 config_button_close False Skill Information center-on-parent 500 600 False True False True True in True True True True 1 0 True False False True 2 2 True False spread Ready Skill True True True True False False 0 Use Skill True True True True False False 1 gtk-close True True True True True False False 2 False True 2 3 False Spell Information center-on-parent 800 600 False True False True True in True False True True 1 0 True False 5 True False 5 True False Attuned False True 0 True False 5 True False Repelled False False 5 1 True False 5 True False Denied False True 2 True False 5 True False Normal False False 5 3 True False Spell Options False False 4 True True False False True True True True 5 5 False True 1 1 True False False True 2 2 True False spread Cast True True False True False False 0 Invoke True True False True False False 1 gtk-close True True False True True False False 2 False True 2 3 Mark Wedel (mwedel@sonic.net) David Sundqvist (azzie@netpolicy.com) Raphael Quinet (Raphael.Quinet@eed.ericsson.se) Jacek Konieczny <jajcus@zeus.polsl.gliwice.pl> Eric Anderson Scott MacFiggen (smurf@CSUA.Berkeley.EDU) Kevin Bulgrien (kbulgrien@att.net) Kevin Zheng (kevinz5000@gmail.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. crossfire-client-1.75.3/gtk-v2/ui/caelestis.ui000644 001751 001751 00000476140 14226677555 022043 0ustar00kevinzkevinz000000 000000 1000000 1 False Crossfire Client - GTK v2 1275 945 1180 925 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True False True False 1 True False False True 2 True False False False 3 False False 0 1275 920 True True 290 True True 700 True False True False True True False 0 2 Inventory: True True 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False Count False False 5 2 True True False False True True adjustment1 1 True True True 3 False True 0 True False True True never True True True True 11 10 True False Icons False True True 1 False True True False 3 True False You see: False False 2 0 True True never True True True True 1 True True False True True True 175 True True 580 True True 2 True True 250 True False 2 queue True False True False True False 0 Player: False False 3 0 True False 0 Level: 10 False False 5 1 False False 3 0 True False True False 0 Skill False False 3 0 False False 4 1 True False True False 0 Speed 6 False False 3 0 True False False False 1 False False 3 2 True False True False 0 Weapon Speed False False 3 0 True False False False 1 False False 4 3 True False True False 0 Experience: False False 3 0 False False 3 4 True False True False 0 5 False False 5 0 True False 0 5 False False 5 1 False False 4 5 False True True False 2 queue True False 2 6 3 4 True False 0 2 Exp: 4 5 GTK_FILL True False 0 2 Food: 3 4 GTK_FILL True False 0 2 Grace: 2 3 GTK_FILL True False 0 2 SP: 1 2 GTK_FILL True False 0 2 HP: GTK_FILL True False 0.10000000149 1 2 4 5 2 True False 0.10000000149 1 2 3 4 2 True False 0.10000000149 1 2 2 3 2 True False 0.10000000149 1 2 1 2 2 True False 0.10000000149 1 2 2 True False 0 3 5 6 GTK_FILL True True True False Character False True False 2 queue True False 6 6 True 1 True False Skills & Experience 1 False False True True True 2 True False 5 7 6 5 5 True False 0 1 6 6 7 GTK_FILL True False 0 1 6 5 6 GTK_FILL True False 0 1 6 4 5 GTK_FILL True False 0 1 6 3 4 GTK_FILL True False 0 1 6 2 3 GTK_FILL True False 0 5 6 1 2 GTK_FILL True False 0 3 4 1 2 GTK_FILL True False 0 Armour 4 5 1 2 GTK_FILL True False 0 Armor Class 2 3 1 2 GTK_FILL True False 0 5 6 GTK_FILL True False 0 Damage 4 5 GTK_FILL True False 0 3 4 GTK_FILL True False 0 Weapon Class 2 3 GTK_FILL True False 0 Charisma 6 7 GTK_FILL True False 0 Power 5 6 GTK_FILL True False 0 Wisdom 4 5 GTK_FILL True False 0 Intelligence 3 4 GTK_FILL True False 0 Constitution 2 3 GTK_FILL True False 0 1 2 1 2 GTK_FILL True False 0 Dexterity 1 2 GTK_FILL True False 0 1 2 GTK_FILL True False 0 Strength GTK_FILL True False Core Statistics False True False 2 queue True True never True True False False False 1 True False 3 Critical Messages True 1 False True False 6 6 True 2 True False Protections 2 False True True False True True True 580 True True 2 False True False True False Map False True False 1 True False Magic Map 1 False False True True False True False 0 none True False 2 queue True True never True True False False False True False 3 <b>Messages</b> True True True 0 True True False False True True False False 2 1 True True True True True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/v1-redux.ui000644 001751 001751 00000475426 14226677555 021550 0ustar00kevinzkevinz000000 000000 1000000 1 1180 925 False Crossfire Client - GTK v2 1180 925 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True False True False 1 True False False True 2 True False False False 3 False False 0 1601 True True 320 True True 720 True False True False True True False 0 2 Inventory: True True 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False Count False False 5 2 True True False False True True adjustment1 1 True True True 3 False True 0 True False True True never True True True True 11 10 True False Icons False True True end 1 True True True False 3 True False 0 1 Ground: False False 2 0 True True never True True True True 1 True True False True True True 575 True True 125 True False 0 in True False 2 2 True True False 8 True False Player: False False 0 False False 0 True False 8 True False Score: False False 0 True False 2 Level: False False 1 True True 1 True False 8 True False True False S False False 0 True False 0 False False 1 False True 0 True False True False D False False 0 True False 0 False False 1 False True 1 True False True False Co False False 0 True False 0 False False 1 False True 2 True False True False I False False 0 True False 3 0 False False 1 False True 3 True False True False W False False 0 True False 0 False False 1 False True 4 True False True False P False False 0 True False 0 False False 1 False True 5 True False True False Ch False False 0 True False 0 False False 1 False True 6 True True 2 True False 8 True False True False Wc: False False 0 True False 2 0 False False 1 False True 0 True False True False 2 Dam: False False 0 True False 2 0 False False 1 False True 1 True False True False 2 Ac: False False 0 True False 2 0 False False 1 False True 2 True False True False 2 Armor: False False 0 True False 2 0 False False 1 False True 3 False False 3 True False 8 True False True False Speed: False False 0 True False 2 0 False False 1 False True 0 True False True False ( False False 0 True False 2 0 False False 1 True False ) False False 2 False True 1 False False 4 True False 8 True False Skill: False False 0 True True 5 True False <b>Core Stats</b> True True True True True 590 True True 2 False True False True False Map False True False 1 False True False Magic Map 1 False True True True True 285 True False True False True False 0 2 HP: False True 0 False True 0 14 True False 0.10000000149 False False 1 1 True False True False 0 2 Spell Points: False True 0 False True 2 14 True False 0.10000000149 False False 1 3 True False True False 0 2 Grace: False True 0 False True 4 14 True False 0.10000000149 False False 1 5 True False True False 0 2 Food: False True 0 False True 6 14 True False 0.10000000149 False False 1 7 True False True False 0 2 Exp: False True 0 False True 8 14 True False 0.10000000149 False False 1 9 True False True False 0 True True 0 True False 0 True True 1 True True 10 False True True True 2 never automatic in True False True False 2 6 6 True True True True True True True False True True False True True 205 True False 0 none True False True True never in True True 2 False 2 2 False False True False 3 <b>Critical Messages</b> True False True True False 0 none True False True True never in True True 2 False 2 2 False False True False 3 <b>Messages</b> True True True True True 0 True True False False True True False False 2 1 True True True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/oroboros.ui000644 001751 001751 00000501715 14226677555 021730 0ustar00kevinzkevinz000000 000000 1000000 1 False Crossfire Client - GTK v2 1019 690 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True False True False 0 5 False False 0 True False 0 5 False False 1 False False 1 False False 0 1019 600 True True 350 True True 540 True True 175 True False True True 2 True False 2 queue True True never True True False False False True False 3 Messages True False True False 2 queue True True never True True False False False 1 True False 3 Critical Messages True 1 False True True 0 True True False False True True False False 2 1 False True True False 2 queue True False 2 True False True True False Inventory: False False 10 0 True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 True True 1 True False Count False False 5 2 True True False False True True adjustment1 1 True True True 3 False True 0 True False True True never True True True True 11 10 True False Icons False True True 1 True True False True True False 2 queue True False 3 True False You see: False False 2 0 True True never True True True True 1 True True False True True True 175 True True 2 True True 200 True False 2 queue True False True False True False 0 Player: False False 3 0 True False 0 Level: 10 False False 5 1 False False 3 0 True False True False 0 Skill False False 3 0 False False 4 1 True False True False 0 Speed 6 False False 3 0 True False False False 1 False False 3 2 True False True False 0 Weapon Speed False False 3 0 True False False False 1 False False 4 3 True False True False 0 Experience: False False 3 0 False False 3 4 False True True False 2 queue True False 2 5 3 4 True False 0 2 Exp: 4 5 GTK_FILL True False 0 2 Food: 3 4 GTK_FILL True False 0 2 Grace: 2 3 GTK_FILL True False 0 2 SP: 1 2 GTK_FILL True False 0 2 HP: GTK_FILL True False 0.10000000149 1 2 4 5 2 True False 0.10000000149 1 2 3 4 2 True False 0.10000000149 1 2 2 3 2 True False 0.10000000149 1 2 1 2 2 True False 0.10000000149 1 2 2 True True True False Character False True False 2 2 2 2 True False 2 True False 0 in True False True False 5 7 6 5 5 True False 0 1 6 6 7 GTK_FILL True False 0 1 6 5 6 GTK_FILL True False 0 1 6 4 5 GTK_FILL True False 0 1 6 3 4 GTK_FILL True False 0 1 6 2 3 GTK_FILL True False 0 5 6 1 2 GTK_FILL True False 0 3 4 1 2 GTK_FILL True False 0 Armour 4 5 1 2 GTK_FILL True False 0 Armor Class 2 3 1 2 GTK_FILL True False 0 5 6 GTK_FILL True False 0 Damage 4 5 GTK_FILL True False 0 3 4 GTK_FILL True False 0 Weapon Class 2 3 GTK_FILL True False 0 Charisma 6 7 GTK_FILL True False 0 Power 5 6 GTK_FILL True False 0 Wisdom 4 5 GTK_FILL True False 0 Intelligence 3 4 GTK_FILL True False 0 Constitution 2 3 GTK_FILL True False 0 1 2 1 2 GTK_FILL True False 0 Dexterity 1 2 GTK_FILL True False 0 1 2 GTK_FILL True False 0 Strength GTK_FILL True False <b>Core Stats</b> True True True 0 True False 0 in True False 5 5 5 5 True False 6 6 True False <b>Protections</b> True True True 1 1 True False Core Stats &amp; Protections True 1 False True True True False 2 queue True True 2 False 500 455 True False True False Map False True False 1 True False Magic Map 1 False True True True True True True 1 crossfire-client-1.75.3/gtk-v2/ui/meflin.ui000644 001751 001751 00000517566 14226677555 021351 0ustar00kevinzkevinz000000 000000 1000000 1 10 False Crossfire GTK V2 Client - Meflin 640 480 True False True False True False True False _File True False True False Quit Character True True False _Quit True True False _Client True False True False Configure True True False Disconnect True True False Keybindings True True False Configure message routing and buffering. Message Control True True False Save Window Position True True False Player True False True False Spells True True False Skills True True False Pickup True False True False Don't Pickup True True False Stop Before Pickup True True False Armor True False True False Body Armor True True False Boots True True False Cloaks True True False Gloves True True False Helmets True True False Shields True True False Books True False True False Skillscrolls True True False Normal Books & Scrolls True True False Spellbooks True True False Drinks True True False Food True True False Flesh True True False Keys True True False Magical Items True True False Potions True True False Valuables (Money & Gems) True True False Wands/Rods/Horns True True False Jewels True True False Containers True True False Weapons True False True False All Weapons True True False Missile Weapons True True False Bows True True False Arrows True True False Weight/Value True False True False Ratio Pickup Off True True True False Ratio >= 5 True True ratio_pickup_off True False Ratio >= 10 True True ratio_pickup_off True False Ratio >= 15 True True ratio_pickup_off True False Ratio >= 20 True True ratio_pickup_off True False Ratio >= 25 True True ratio_pickup_off True False Ratio >= 30 True True ratio_pickup_off True False Ratio >= 35 True True ratio_pickup_off True False Ratio >= 40 True True ratio_pickup_off True False Ratio >= 45 True True ratio_pickup_off True False Ratio >= 50 True True ratio_pickup_off True False Ignore cursed True True False _Help True False True False _About True False False 0 True False False True 1 True False 0 2 Player: False True 8 2 True False False True 3 True False 0 2 Experience: False True 8 4 True False False True 5 True False 2 Lvl: False True 8 6 False True 0 True True 830 True True True 620 True True True bottom False True False 2 queue True False True False Map False True False 2 queue True False 1 True False Magic Map 1 False False True True True 2 bottom True False 2 queue True True True False 2 queue True False 5 8 9 5 True False 5 6 7 GTK_FILL True False 2 3 7 GTK_FILL True False 0 2 Str GTK_FILL True False 0 0 1 2 GTK_FILL True False 0 2 HP: 6 7 GTK_FILL True False 0 2 SP: 6 7 1 2 GTK_FILL True False 0 2 Grace: 6 7 2 3 GTK_FILL True False 0 2 Food: 6 7 3 4 GTK_FILL True False 0 2 Exp: 6 7 4 5 GTK_FILL True False 0 2 Dex 1 2 GTK_FILL True False 0 2 Con 2 3 GTK_FILL True False 0 2 Int 3 4 GTK_FILL True False 0 2 Wis 4 5 GTK_FILL True False 0 2 Pow 5 6 GTK_FILL 12 True False 0.10000000149 7 8 GTK_FILL 12 True False 0.10000000149 7 8 1 2 GTK_FILL 12 True False 0.10000000149 7 8 2 3 GTK_FILL 12 True False 0.10000000149 7 8 3 4 GTK_FILL 12 True False 0.10000000149 7 8 4 5 GTK_FILL True False 0 0 1 2 1 2 GTK_FILL True False 0 0 1 2 2 3 GTK_FILL True False 0 0 1 2 3 4 GTK_FILL True False 0 0 1 2 4 5 GTK_FILL True False 0 0 1 2 5 6 GTK_FILL True False 0 2 Cha 6 7 GTK_FILL True False 0 0 1 2 6 7 GTK_FILL True False True False 0 2 Range: False False 0 6 9 7 8 GTK_FILL True False 0 2 WSp 3 4 GTK_FILL True False 0 0 4 5 GTK_FILL True False 0 2 Sp 3 4 1 2 GTK_FILL True False 0 0 4 5 1 2 GTK_FILL True False 0 2 WC 3 4 2 3 GTK_FILL True False 0 0 4 5 2 3 GTK_FILL True False 0 2 Dam 3 4 3 4 GTK_FILL True False 0 0 4 5 3 4 GTK_FILL True False 0 2 AC 3 4 4 5 GTK_FILL True False 0 0 4 5 4 5 GTK_FILL True False 0 2 Arm 3 4 5 6 GTK_FILL True False 0 0 4 5 5 6 GTK_FILL True False 0 2 Enc: 6 7 6 7 GTK_FILL True False True False 0 0 False False 0 True False 0 / False False 1 True False 0 False False 2 7 9 6 7 GTK_FILL True False True False 0 2 False False 0 True False 0 2 False False 1 6 7 8 GTK_FILL True False 6 9 5 6 GTK_FILL True False 3 5 6 7 GTK_FILL False True True False 2 queue True True never True True 2 False False False True True True False Stats & Important Messages False True False 2 queue True False 6 6 True 1 True False Protections 1 False True False 2 queue True False 6 6 True 2 True False Skills & Experience 2 False True True False True True True 620 True True True bottom True False 2 queue True True never True True False False False True False Messages False False True True False True True bottom True False 2 queue True True never True True True False Look False True False 2 queue True False bottom True True never True True True True 11 10 True False Icons False 1 True False Inventory 1 False True True 0 True False True True False False True True True True 0 True False 1 5 Count: right False False 1 True True False False True True adjustment1 1 True True True 2 False False 2 1 True True True True True True 1 crossfire-client-1.75.3/gtk-v2/CMakeLists.txt000644 001751 001751 00000000613 14045044330 021611 0ustar00kevinzkevinz000000 000000 add_subdirectory(src) install(DIRECTORY themes ui DESTINATION ${CMAKE_INSTALL_DATADIR}) install(FILES crossfire-client.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications) foreach(size 16 32 48) install(FILES ../pixmaps/${size}x${size}.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${size}x${size}/apps RENAME crossfire-client.png) endforeach() crossfire-client-1.75.3/gtk-v2/README000644 001751 001751 00000037405 14350011144 017736 0ustar00kevinzkevinz000000 000000 Crossfire GTKv2 Client ====================== Crossfire Development Team :toc: :numbered: Overview -------- The original author's main motivations for writing the client were: . The old client layout wasn't originally designed for the map window size that people are now using. . Using an interface designer will make it much easier to add new window elements in the future. . Having a GTK 2 compliant client was considered a positive thing. Due to point #1 above, the interface was designed for a window size of about 1200x1000. That is to say, on a system whose resolution is 1280x1024, the window will use almost the entire screen. It is possible to play this client on a 1024x768 desktop, but the default layout is not ideal for such a small screen. Some of the alternative root window layouts are more viable when screen real-estate is on the low side. The original author had no particular interests in patches to make it work on smaller screens, and originally stated that those with a requirement for smaller screens needed to simply use one of the other clients (Gtk v1 client for example). The rationale for this stance was that there is a perception that the older client has a lot of cruft trying to deal with different size screens, options to change various sizing, etc. Though the GTK v2 client is supposed to work at 1280x1000, the information density is far lower than that of the original GTK v1 client, and this is not palatable to some players. The author also has stated that the GTK2 client is the "most official" client, and has put forward the idea that if the newer GTK client could be reworked to resolve differences of opinion about the layout, there may be a benefit to phasing out the older clients. In fact, some Linux distributions appear to be ceasing to build the older GTK client - likely because it is not realized that it may be built with the GTK2 libraries. Considering the above issues, an endeavor was undertaken to convert the client to use the libglade interface to allow players to have an ability to redesign the main window layout without requiring code changes to the clienti, and to preclude a need to recompile the client in order to realize a new layout. The libglade version of the client should make it easier for players to create main window layouts that appeal to a variety of personal preferences. To support redesign of the layout, a prospective UI layout must not rename widgets that accept or display information. For the most part, container widgets may be renamed to suite the author. The main exception is that hpane and vpane widgets must be named with consistent names so that the client can save and restore window positions in the gwinpos2 file. The current client codebase expects hpane and vpane (resizeable) widgets to be named generically in the form "hpaned_*" or "vpaned_*". The code to Save Window Position auto-detects the widgets in order to preserve the user's pane sizing preferences. Design ------ Core Widgets ~~~~~~~~~~~~ window-root: The core window. table-map: table that contains the map and scrollbars. drawingarea-map: The map drawing area. hscrollbar-map: scrollbar to move the map horizontally. vscrollbar-map: scrollbar to move the map horizontally. button-map-recenter: When clicked, map recenters. drawingarea-magic-map: Area to draw the magic map NOTE: The reason scrollbars are used instead of a simple scrolled window is that the author does not believe it is feasible to draw much more than what the player is currently viewing. If a scrolled window is used, then we may end up drawing a lot of stuff the player is not seeing, as well as not redrawing fog stuff the player is seeing. By using scrollbars, it is easier to trap when the player tries to scroll the map, and redraw the new portion, as well as track where the map is currently positioned, without needing a much larger draw area. vpaned-info-inventory: separator for the text window vs inventory area. vbox-info-entry: Top portion is text information, bottom is area for text entry. entry-commands: Where the player enters extended commands. notebook-info: notebook for different text information textview-info1: area where messages are displayed. textview-info2: area where messages are displayed. The two info are in a tabbed area - more tabs could in fact be added. The idea is to keep the two info panes as before, but in less space. The primary tab (1) will get all messages. Important messages (colored in this case) will also go to tab 2. Perhaps down the road, there will be smarter filtering of these messages. label-inv-weight: Shows current weight of characters inventory. spinbutton-count: Current count set by the player. notebook-inv: Notebook for the various inventory panes. label-stats-hp: label-stats-sp: label-stats-grace: label-stats-food: Text label showing hp/sp/ progressbar-hp: progressbar-sp: progressbar-grace: progressbar-food: progressbar for the stats. label-str, label-dex, label-con,label-int, label-wis, label-pow, label-cha, label-wc, label-dam, label-ac, label-armor, label-range, label-exp: Actual stat value for those values. table-stats-exp: Table hold the skills and exp values. Note that initializing this is not done in Glade - it is easier to do on the client side, so that it can make an array of labels for this. table-protections: Like table-stats-exp above, but this is for protections. Note that the inventory tabs are done in the code - Glade really doesn't let one fully set up a gtktreewidget (the number of columns, renderer type, etc), so it just made it easier to do in the actual code.) Layouts ~~~~~~~ Two different layout files are used by the client to build its user interface. One is for building the main window, and the other is for constructing the other dialogs common to different layouts. To start the client using a different layout, use the `-window_xml` flag. crossfire-client-gtk2 -window_xml /path/to/layout.glade If something does not work as expected, be sure to start the client from a console window. The client will report informational and error messages. To specify a different common dialog XML file, append an additional argument on the command-line: -dialog_xml /path/to/dialogs.glade As of SVN revision 8406, crossfire-client-gtk2 saves window position data in a file named per the layout instead of the legacy file '~/crossfire/gwinpos2'. For example, if a player saves window positions while using gtk-v2.glade, they will be stored in '~/.crossfire/gtk-v2.pos', but if playing with a layout called caelestis.glade, they will be saved in caelestis.pos. This means the client is able to remember saved sizes for each layout individually. The first time a layout is used, the '~/.crossfire/.pos' file will not exist so the client will use default sizes that were defined inside the '.glade' file at design time. This means that as long as the defaults are smaller than the desktop, the client window should be laid out nicely. If, however, the desktop size is smaller than the default sizes, the client may look bad, and it may be tricky to find the size bars if panes overlap. With patience, they may be found and used to size the client panes better. Use the Client Save Window Position command to save the adjustments. They will be used to restore the saved settings the next time the client is started. If the desktop is smaller than it was last time the '.pos' file was created, it is possible that the saved positions are no good. In this case, it may be wise to delete the '.pos' file and try out the default settings. Development ----------- Here follow some notes for those wishing to do development: . Send a note to crossfire@metalforge.org about what you plan to work on so that multiple people don't work on the same thing. . Try to work with up to date SVN to minimize merge problems. . If looking for something to work on, look at the TODO file. . Try to add new graphical elements using glade-2 and not coding them in by hand - this will make it easier for future modifications. . gtk2proto.h should be used to collect prototype information needed by the .c sources. It is generated using `make proto`. The cproto program must be installed for this to work. Note that `make proto` generates a lot of error messages on the console during operation, but this does not mean the process failed. . The source files are arranged by functionality, so try to keep new code functionality related to similar elements in the same files, but at the same time, don't put so much stuff in one file to make it unmanageable. . One of the motivations was to use pure GTK v2 calls and not use any of the deprecated wigets/toolkits withing GTK. Please try to keep to that model (note that this does not mean things are 100% perfect, as for widgets that are not deprecated, I often copied the code completely over from the GTGTK client, but certain functions may be deprecated in that copied code). But dealing with that is certainly easier down the road if/when those functions really disappear than having to redo code for a widget that just no longer exists. Designing Layouts ~~~~~~~~~~~~~~~~~ . All windows that should not be initially displayed when the application starts must have the "visible" property set to "no". This property is on the "Common" tab. The following windows should not be initially visible: metaserver_window keybinding_window msgctrl_window config_window spell_window skill_window about_window IMPORTANT: The root window "visible" property must also be set to "no" in order for saved screen size settings to be restorable when the application starts up. This really means that all dialogs and windows should be set as not visible. . All hpane and vpane resizeable widgets that need to be saved when the user selects Client | Save Window Position should have a name that begins with either "hpaned_" or "vpaned_". The client will only save window positions for the widgets named in this way (this is the default naming convention used by the Glade Designer application). . Set all hpaned and vpaned size bars to result in a default layout that has a decent appearance. It is not sufficient to have the layout look good in the layout designer. You must verify that the Position property on the Widget tab is set and that it's checkbox is checked. Also see note 11 for another important tip regarding setting the size of widgets. . When creating tabbed notebooks be sure the first tab is the tab that should be visible when the client starts up or when the dialog is first displayed. . Most layouts may be altered by creatively cut/pasting elements. Do not use copy/paste, as that will cause the widgets to be renamed. . The inventory icon pane is an excellent "temporary" holding area that may be used to hold widgets while other areas of the layout are being worked on. . More complex changes may be made by temporarily expanding the outer vbox container and using the bottom rows to paste things into. Be careful when reducing it back to the original size. Glade Designer deletes the bottom layers first, even if there are empty ones in the middle. Any widgets in the removed layer are lost. . Save periodically, and keep working copies. It is very easy to ruin a layout so that it is hard to return to a proper state, and widget errors may cause the client to crash at run-time when it is most inconvenient. . When adding a combo box that is to be dynamically filled at run-time, be absolutely sure to press the ellipsis "..." button next to the empty Items: box, then press the OK button on the Edit Text Property dialog. This causes the XML file combo box definition to contain an essential property: Without this property, at run-time the following code snippet will set model to NULL. model = gtk_combo_box_get_model(GTK_COMBO_BOX(config_combobox_theme)); count = gtk_tree_model_iter_n_children(model, NULL); This construct is used several times in config.c's setup_config_window(). When model is NULL, the subsequent code that attempts to use the model generates console errors like: (crossfire-client-gtk2:9632): Gtk-CRITICAL **: gtk_tree_model_iter_n_children: assertion `GTK_IS_TREE_MODEL (tree_model)' failed (crossfire-client-gtk2:9632): Gtk-CRITICAL **: gtk_combo_box_append_text: assertion `GTK_IS_LIST_STORE (combo_box->priv->model)' failed (crossfire-client-gtk2:9632): Gtk-CRITICAL **: gtk_combo_box_append_text: assertion `GTK_IS_LIST_STORE (combo_box->priv->model)' failed (crossfire-client-gtk2:9632): Gtk-CRITICAL **: gtk_combo_box_append_text: assertion `GTK_IS_LIST_STORE (combo_box->priv->model)' failed (crossfire-client-gtk2:9632): Gtk-CRITICAL **: gtk_tree_model_iter_n_children: assertion `GTK_IS_TREE_MODEL (tree_model)' failed . The Magic Map page in map_notebook must be the second tab to maintain compatibility with the client's standard main.h define "MAGIC_MAP_PAGE 1". The page/tab number is zero-based, so "1" corresponds to the second tab. . In general, do not set widget Width and Height properties on the Common tab in the Glade Designer. This is in effect placing a size request for the widget, and can prevent the player from sizing the widget smaller than the size set at design time. This is especially important with respect to the map and magic map drawing areas, tables, treeviews, and other large UI elements (hboxes, vboxes, notebooks, etc). A player should generally have the freedom to make a widget smaller than it was originally designed in the layout. . Note, though, that this is not a hard and fast rule. Sometimes setting a size is very helpful. For example, in the GTK V1 layout (and a few others) progressbars are set to use a smaller height dimension size than their default. Since a player never expects to be able to set the thickness of the bar, setting that dimension is useful to attain a particular look (I.E. make the progressbar more compact). . All dialogs defined in dialogs.glade should have their Deletable property set to "No" in the XML (done while working in the Glade-3 designer). This tells window managers not to put an [X] close icon on the window frame. Without this, the [X] close deletes the dialog so it cannot be resurrected without restarting the client. In some cases a segmentation fault occurs and the client crashes. To cover cases where certain window managers do not honor the GTK Deletable property, connect the delete_event for each dialog to gtk_widget_hide_on_delete() in the C code. For example: g_signal_connect((gpointer) about_window, "delete_event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); Other Hints ~~~~~~~~~~~ . Sometimes when making significant layout changes or when glade misbehaves and does not let you visually see an select an empty cell (vboxes have been noted as problematic if an empty cell is bounded by two cells with content). When this happens, it is quite possible to use a text editor to move items into the empty cell. Naturally you have to be able to look at the XML structure to know how to keep it intact. Make backups before making manual edits. . When editing .glade files by hand, use of a text editor that is capable of collapsing XML structures is recommended. Even without such and editor, it can be handle to use a browser alongside the editor. To do so, make a copy of the .glade file, but save it with a .xml extension, and then open it in FireFox or another XML-aware browser. Use the expand/collapse features to learn or reveal the structure of the XML. crossfire-client-1.75.3/gtk-v2/AUTHORS000644 001751 001751 00000027317 14045044323 020135 0ustar00kevinzkevinz000000 000000 Glade Designer Layout Authors ------------------------------------------------------------------------------- If you author a .glade layout file, please feel free to add an attribution for your work here. ------------------------------------------------------------------------------- Mark Wedel ------------------------------------------------------------------------------- The original gtk-v2.glade file by Mark Wedel was the basis for the following layout files. In fact, all layouts for the GTK-v2 client must contain the basic widget set found in that work. - gtk-v2.glade This layout defaults to use of a 25x25 map. The default layout size is configured to 1201x1010. The map itself takes up most of a 1280x1024 screen, and it seems somewhat difficult to use at this resolution and lower. Stat bars reside in the lower left; stat tables share a tabbed notebook in the lower middle. Message panes share a tab notebook in the upper right, with inventory and ground views making up the reset of the left hand side of the window. - dialogs.glade This file contains all of the ancilliary dialogs used by the GTK V2 client. Alternative layouts are not provided. ------------------------------------------------------------------------------- Kevin Bulgrien ------------------------------------------------------------------------------- The conversion of the client to support libglade came shortly after Kevin Bulgrien began developing experimental alternative layouts by copying and modifying the original gtk-v2.glade layout. Some of those initial layouts are are found in the following files: - caelestis.glade A tri-column layout with a tall inventory/floor panels to the right. At the top middle, a two tab notebook for character and skill/experience data sits above map views beneath. To the top left is a three tab notebook for core stats, critical messages, and protections. At the lower left is the messages pane with entry box. The default window setting supports an 19x22 map pane with an overall size of 1275x945. - chthonic.glade A tri-column layout with a tall inventory/floor panels to the right. At the top middle, a two tab notebook holds the map views above character data. To the top left is the critical message box with the standard message box and command input below. The bottom left corner two tab notebook houses protections and core statistics. The default window setting supports an 19x22 map pane with an overall size of 1275x945. NOTE: There seems to be issues with the saving of screen position when resizeable panes are nested. Though saving works fairly well for this layout, the protections/core statistics area does not restore properly, though the misbehavior is not terribly inconvenient. The layout needs some work to improve save/restore. - eureka.glade A U-shaped layout with inventory and ground views at the top and middle left, a critical and regular message area at the top and middle right, with status bars on the bottom left alongside a three tab notebook for core stats, skills & experience, and protections. The map pane is in the middle of the window and may be set for 17x22 tiles at the default 1180x925 settings. - gtk-v1.glade This is a close reproduction of the original GTK V1 client with the main exception being the magic map in a tabbed notebook with the map view, and an experience bar that was not present in the legacy client. At the default settings of 1180x925, the map pane displays a 17x17 view of the world around you. The main drawback of this client layout is probably the quantity of deadi space in the middle column. - lobotomy.glade A layout of a slightly different persuasion. This one sports a map layout on the left. To the right sit the inventory/ground view and message panes. Underscoring this unconventional view is a unique cluster of stats and stat bars not seen in other client layouts. Too round out the uniqueness of this layout, the skill and protections data is laid out below the map in a manner that tends to allow the oversized skills data table to expand naturally while the narrower protections panel shrinks to the data it contains. Unlike many of the other layouts, tabbed notebooks are avoided except in the map panel. Window defaults are set at 1280x925, and sport a map pane of 19x22. - meflin.glade A player-suggested modification of an experimental layout. Send in a suggestion, and you might have a layout tuned to your tastes. Presently a map view notebook is at top right with message, inventory, and ground views sharing a tabbed notebook to the left. At the bottom rest the stat bars and a three tab notebook for character data. This one is custom-sized at 1233x1001, and at these settings, fits a healthy sized 25x25 map view. Send in a suggestion for a layout, and if you're nice about it, the author will likely be able to whip one up to suit your individual tastes. For that matter, SVN contains tips on how to roll your own... - oroboros.glade A layout designed for 1024x768 desktops. On the left are a tabbed message window, inventory, and floor view. To the right, at the top is a two tab notebook that contains all of the character statistics, and below it is the map view. At 1024x768, the map view is 20x13. Since oroboros makes heavy use of tabbed notebooks, it is also appropriate for those that prefer to see less information simultaneously on screen. Recent removal of the skills panel, made possible by a new skills window, helped reduce the notebook pages and improve visibility of vital data. - sixforty.glade This is a layout that defaults to a 640x480 size and was made in response to a request for a small layout. Player name, experience, and level are reported beside the menu bar. The rest of the layout is cut into four zones with a resize bar allowing the left/right sizes to be adjusted. In the top-left quadrant lies the map panel, with a tabbed pane for Stats, Protections, and Skills/Experience in the quadrant below it. The icon view resides in the top right quadrant with the tabbed messages pane and command input occupying the lower right quadrant. At 640x480, a 12x11 map size is workable with inventory views being the big challenge. The most noticable difference in this layout is a more densely packed stats panel that eliminates the Core Statistics panel found in all the previously created layouts. This panel sports 3-columns with the first containing numeric values for encumbrance, HP, Mana, Grace, Food and XP. The top of the middle column indicates the readied skill with bar graphs for the stats in the first column below. The third column lists Speed, WS, WC, Damage, AC, and Armor data. Below these three statistical columns is a row displaying Str, Dex, Con, Int, Wis, Pow, Cha data. It is extraordinarily helpful to set a map and icon scales to 50%. Other scale factors may also work, but many others also distort the map display unpleasantly. NOTE: sixforty.glade in its present form does not save and restore window positions properly. It is best to accept the defaults for the present, and as needed, tweak it at run-time. Plans are to fix this issue eventually. - un-deux.glade This layout is still vaguely reminiscent of the original GTK V1 client with the V1-Redux improvements, but it is unique in that the message panes are to the left of the map while the inventory and ground views are on the right. To help keep the most important information at ready eye-level, the encumbrance display and count input box are between the inventory and ground views. The critical and normal message panes are vertically exchanged, with the entry box between, again, to keep the important controls at a consistent eye-level. The fire/run indicators are moved beneath the command input box as they seem all but invisible below the stat bars. The middle of the screen consists of a frame for core stats and a notebook for the map and magic map display, followed by the status bars and protections table. Notably missing is the skills and experience panel - made possible by the addition of a separate skills window. The window size defaults to 1180x925 and comfortably accepts a 19x19 map display. - v1-redux.glade A slight improvement on the original GTK client layout with a tab notebook above the map view that conserves space by dispensing with the experience and skills information. This is made possible by the addition of a detached skills window. Default window positions fit 1280x1024 or 1400x1050 screens with room to spare for side or bottom panels. A 17x20 map pane fits well on the default 1180x925 window size. crossfire-client-1.75.3/CMakeLists.txt000644 001751 001751 00000005145 14605664064 020522 0ustar00kevinzkevinz000000 000000 cmake_minimum_required(VERSION 3.1) project(crossfire-client C) set(VERSION 1.75.3) list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) option(LUA "Lua scripting" OFF) option(METASERVER2 "Metaserver2 support (requires curl)" ON) option(SOUND "Sound support (requires sdl_mixer)" ON) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) if(UNIX) # If Linux or other Unix-like, get gio to work by defining _BSD_SOURCE add_definitions(-D_DEFAULT_SOURCE) elseif(MINGW OR WIN32) add_definitions(-DWIN32) set(CMAKE_INSTALL_PREFIX ".") endif() include(GNUInstallDirs) set(CMAKE_INSTALL_DATADIR ${CMAKE_INSTALL_DATAROOTDIR}/crossfire-client) # Look for required dependencies. find_program(GLIB_COMPILE_RESOURCES NAMES glib-compile-resources) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK gtk+-2.0 gio-2.0 REQUIRED) find_package(PNG REQUIRED) find_package(Perl REQUIRED) find_package(Vala REQUIRED) find_package(X11 REQUIRED) add_definitions( ${GTK_CFLAGS_OTHER} ${PNG_DEFINITIONS} ) include(${VALA_USE_FILE}) # By default, silence warnings about deprecated definitions. We know we're # using deprecated GTK functions; these just clutter more important warnings. add_compile_options(-Wno-deprecated-declarations) # Look for optional dependencies that are enabled using options. if(LUA) find_package(Lua51 REQUIRED) endif() if(METASERVER2) pkg_check_modules(CURL libcurl REQUIRED) set(HAVE_CURL_CURL_H ${CURL_FOUND}) endif() if(SOUND) pkg_check_modules(SDLMIXER SDL2_mixer REQUIRED) if(EXISTS "${PROJECT_SOURCE_DIR}/sounds") install(DIRECTORY sounds DESTINATION ${CMAKE_INSTALL_DATADIR}) else() message(WARNING "SOUND is enabled, but the sound configuration file " "was not found in ${PROJECT_SOURCE_DIR}/sounds. " "You will need to install sounds yourself.") endif() endif() include(CheckIncludeFiles) set(CMAKE_REQUIRED_INCLUDES ${GTK_INCLUDE_DIRS}) check_include_files(gio/gnetworking.h HAVE_GIO_GNETWORKING_H) include(CheckFunctionExists) check_function_exists(sysconf HAVE_SYSCONF) configure_file( "${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ) add_subdirectory(common) add_subdirectory(gtk-v2) enable_testing() # Build an installation package. include(InstallRequiredSystemLibraries) set(CPACK_GENERATOR "ZIP") set(CPACK_PACKAGE_VERSION "${VERSION}") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_IGNORE_FILES "/build/;.git/;.svn/") set(CPACK_SOURCE_PACKAGE_FILE_NAME "crossfire-client-${CPACK_PACKAGE_VERSION}") include(CPack) crossfire-client-1.75.3/COPYING000644 001751 001751 00000043105 13777711215 017013 0ustar00kevinzkevinz000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. crossfire-client-1.75.3/Doxyfile000644 001751 001751 00000004161 14045044330 017447 0ustar00kevinzkevinz000000 000000 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = "Crossfire Client" PROJECT_NUMBER = "SVN Trunk" PROJECT_LOGO = "pixmaps/48x48.png" OUTPUT_DIRECTORY = "doc" JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES TYPEDEF_HIDES_STRUCT = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_STATIC = NO #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = YES WARN_IF_UNDOCUMENTED = NO #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- RECURSIVE = YES EXCLUDE = random_maps/standalone.c EXCLUDE_SYMLINKS = YES EXCLUDE_PATTERNS = */test/* \ */utils/* #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = NO USE_HTAGS = NO #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_TREEVIEW = NO SEARCHENGINE = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO crossfire-client-1.75.3/resources.xml000644 001751 001751 00000000237 14110265004 020471 0ustar00kevinzkevinz000000 000000 common/def-keys crossfire-client-1.75.3/AUTHORS000644 001751 001751 00000001257 14045044323 017016 0ustar00kevinzkevinz000000 000000 Mark Wedel - Client code, GTK, GTKv2, Xlib, OpenGL for GTKv2 David Sundqvist - GTK+ port Raphael Quinet - Configure scripts and graphics Jacek Konieczny - New sound system Eric Anderson - Did a lot of initial work on the client. Scott MacFiggen - SDL support Kevin Bulgrien - libglade-2.0 conversion Nicolas Weeger Karla Stenger - Per-character keybindings Kevin Zheng - GtkBuilder migration, FreeBSD port maintainer, documentation updates crossfire-client-1.75.3/config.h.in000644 001751 001751 00000000666 14323707640 020003 0ustar00kevinzkevinz000000 000000 /* Crossfire Configuration (for CMake) */ #define VERSION "@VERSION@" /* Paths */ #define BINDIR "@CMAKE_INSTALL_FULL_BINDIR@" #define CF_DATADIR "@CMAKE_INSTALL_FULL_DATADIR@/crossfire-client" #define CF_SOUND_DIR "@CMAKE_INSTALL_FULL_DATADIR@/crossfire-client/sounds" /* Header Files */ #cmakedefine HAVE_CURL_CURL_H #cmakedefine HAVE_GIO_GNETWORKING_H /* Functions */ #cmakedefine HAVE_SYSCONF /* Features */ #cmakedefine HAVE_LUA crossfire-client-1.75.3/TODO000644 001751 001751 00000002067 14350011144 016430 0ustar00kevinzkevinz000000 000000 Things to do in no particular order: Have containers present number of objects/number of different objects in name. Add a damfactor display to the client (this would be weapon speed * damage of the weapon) Allow the separation character for keybinding to be set to things other than semicolon - changes for this would really be to fix up the strtok in extended_command (common/player.c) to pass in the appropriate string, and some option in the config pane or someplace to change it - note that if it is changed by the player, then that function would have to go through all the keybindings updating the current set of complex keybindings for the new characters. MSW 2003-02-19 Have inventory/look/container display mechanism which only show icons and numbers, and not full names - in a sense, a much condensed view of things. Add a separate container view (when one is open) in addition to the ground one, so it is easier to move things here and there (perhaps support drag and drop operations for this) Add a 'paper doll' display which shows what is equipped and where. crossfire-client-1.75.3/.gitignore000644 001751 001751 00000002260 14323707640 017740 0ustar00kevinzkevinz000000 000000 *.kdev4 *.o *.swp /Crossfire.tag /Makefile /Makefile.in /aclocal.m4 /autom4te.cache /common/.deps /common/Makefile /common/Makefile.in /common/config.h /common/def-keys.h /common/libcfclient.a /common/stamp-h1 /common/svnversion.h /common/tags /config.cache /config.log /config.status /configure /doxygen.err /gtk-v2/Makefile /gtk-v2/Makefile.in /gtk-v2/glade/*.bak /gtk-v2/glade/*.c /gtk-v2/glade/*.h /gtk-v2/glade/Makefile /gtk-v2/glade/Makefile.in /gtk-v2/src/.deps /gtk-v2/src/Makefile /gtk-v2/src/Makefile.in /gtk-v2/src/crossfire-client-gtk2 /gtk-v2/src/tags /gtk-v2/themes/Makefile /gtk-v2/themes/Makefile.in /help/Makefile /help/Makefile.in /html /macros/*.bak /macros/*~ /macros/CVS /macros/Makefile /macros/Makefile.in /pixmaps/Makefile /pixmaps/Makefile.in /sound-src/.deps /sound-src/Makefile /sound-src/Makefile.in /sound-src/cfsndserv /sound-src/cfsndserv_alsa9 /sound-src/def_sounds.c /sound-src/def_sounds.h /sound-src/sounds /sound-src/tags /utils/Makefile /utils/Makefile.in /utils/compile /utils/config.guess /utils/config.sub /utils/depcomp /utils/install-sh /utils/ltmain.sh /utils/missing /utils/mkinstalldirs Makefile Makefile.in build/ common/config.h.in cscope.* sounds tags crossfire-client-1.75.3/pixmaps/000755 001751 001751 00000000000 14605665664 017445 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/pixmaps/lock.xpm000644 001751 001751 00000001027 14045044275 021106 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const lock_xpm[] = { "20 16 6 1", " c None", ". c #BFBFBF", "+ c #FFFFFF", "@ c #7F7F7F", "# c #404040", "$ c #000000", " ", " .+..@@ ", " +#@@@@.# ", " .@ .@ ", " .# .# ", " .. @@ ", " +.@...@@@# ", " .@.@##@@@$ ", " +@.#$$#@@@ ", " ..@#$$#@@# ", " +@@@$$@@#$ ", " .@@@$$@@#@ ", " @@@@$$@#@$ ", " .@@@###@## ", " @@@##$@#$# ", " "}; crossfire-client-1.75.3/pixmaps/hand.xpm000644 001751 001751 00000001104 14045044275 021064 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const hand_xpm[] = { "20 16 9 1", " c None", ". c #FFFFFF", "+ c #BFBFBF", "@ c #7F7F7F", "# c #404040", "$ c #A0522D", "% c #000000", "& c #CD853F", "* c #DAA520", " .+@@# .+ ", " .+@@..++# ", " .+@@@+@@# ", " ..@@@@@# ", " .++@@@##$$ ", " .@@@@#%%$$$$ ", " .+@@##$$$$&%*&*&*&", " ++@##%&&&&&**&*&*&*", " +# &&%$%$%$&&&&*&*&", " $&$&$&$&&&&&&&&", " &%&%%%&&&&&&&&&", " $&$&&&&&&$&$&$&", " $&%$%&&&&$&$&$", " $&$&$&$ ", " $$$&@@# ", " .++@@# "}; crossfire-client-1.75.3/pixmaps/32x32.png000644 001751 001751 00000002342 14045044324 020713 0ustar00kevinzkevinz000000 000000 ‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEÝ3+ ÓæoIDATXÃí—]hWÇwvv³ŸÆÄ¤ëGm”ƈIA« ¶"~”X)BúPô±Á J%P-‚‚ûPð©/­àƒÓØØV¤®Z+¥6…b¬dc£IÖ|ìnff¿²§»~„lqvSúä —¹—s~sæÜÿ™‹ˆPì¸së–ÒÑÑ!ÅúИ…{»è8{¶hy’É$Ë.”MM²·µUž_ëù£[êeÛÖfÙtì&]gÛÆòVm­\¾xqÊþ¯Nž”Ɔi¨­•kÁàô`ùÒ’°âȦ­k¦¤7Ôý£Ù·£ÇsíêUb±ýÄÌÙ˜Jc}h“NTÂi)ÏRªì¥T6J1·,†‡†°LË0Ȉü«{Ý^­ª\½*[*7žÎ =ÿ§½x `@¦Éi…LWÓ¼J›z Kšîf£9\(gL‚g)¤¼¼þ³çTàtºð—–á÷ùðxýˆ(J<&ÉT½Äm@áú_þÛÜåÑ#Œõ@îžSèe.ÔÀ]î\=þðVÜd0ÒÇï!Ô{ŸL:Aø±A<ž ápèö¬x–vGó/V’E¯•ãÐ]¼±°Gf’9Þùü¥ŒŽìºG~.p©¤í+ ¡Sêé'bÅq#ÉcÀÛ²0>ú€k>¤¿¯¹ÕÕ¸Ün–­ZÅ$°dÑ"*çÍe0ÔŸcñÛ›©h~Ÿ zîiXœ¼C÷mƒÊWG:HZeD£ÃöаjÁíßÏá¶C¤â&Édœ¸9A,ÁˆŽŒ!‰0‘ŠÀd HE e’IQÈ ã²¶ðÁŽßhiùØþ)Àét>m8Ïä>Æ«ç'ê¹¹“ 06¦v Õ”Öü_˜* ‘ûyд™i•ˆ†X–YÀ²ššÖ¯g š„N*5@ãºÕlxgCaBt ­Mhk㔬nj²ó'ÇfãàW‚í Çüâ¤xάY˜†"fBÆÑ´áðXñ½àÄ©S|qâ=ׯãñûmwâà!ð.{[WQ9¯¶xÏ—§ñq¼>_Þ†3½Ú‰ô,bFäUò[·v­ú¾«KÎ>M¨·—ÅK—æï|OšeI2Jàrð'^)¯R/8&öïq€è‡  Éh$"׃AdÉ®o¤ñ‚ÈÊ.ô:ɺµçS·[R¦aв};ÆÄ‡¤¼¢‚vî °r5×>ÿ ’>ªkê(5 ŠÂo´?tvÊ•K—d]}½h¹äËÀïróü×"’.,«3¹ž¿YW'Þ'EúøDæ— šIEND®B`‚crossfire-client-1.75.3/pixmaps/mag.xpm000644 001751 001751 00000001026 14045044275 020721 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const mag_xpm[] = { "20 16 6 1", " c None", ". c #1E90FF", "+ c #FFFFFF", "@ c #7F7F7F", "# c #404040", "$ c #000000", " ", " ", " . . ", " . . ", " . . . . . . ", " . . . . . . +@ . ", " . +@ .", ". +++++++++++#@$+$ ", " +++@+@+@+@+@+$@+++.", ". ############@$+$ ", " . +@ .", " . . . . . . +@ . ", " . . . . . . ", " . . ", " . . ", " "}; crossfire-client-1.75.3/pixmaps/unlock.xpm000644 001751 001751 00000001031 14045044275 021444 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const unlock_xpm[] = { "20 16 6 1", " c None", ". c #7F7F7F", "+ c #BFBFBF", "@ c #FFFFFF", "# c #404040", "$ c #000000", " .. ", " +. ", " @#. ", " +. ", " +# ", " ++ ", " @+.+++...# ", " +.+.##...$ ", " @.+#$$#... ", " ++.#$$#..# ", " @...$$..#$ ", " +...$$..#. ", " ....$$.#.$ ", " +...###.## ", " ...##$.#$# ", " "}; crossfire-client-1.75.3/pixmaps/48x48.png000644 001751 001751 00000003155 14045044324 020734 0ustar00kevinzkevinz000000 000000 ‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs  šœtIMEÝ2UìÆúIDAThÞíš_ˆT×Ç?çÜ;÷ÎÝ;3;»F&JlµÖF µ4!”6س4‰%%n¤O’¼’‡¼‚P…54±…Ø>ؤÁ 5¥úš’@««.M‚q×–­×MöÏüÙùwgîœsú06EÍ®Î^[èüàÇœ™9çüÎ÷üÎïß¹c QñÏ_~Ù0󳳑ÈDHžçuÚ‰T*P¼}ê­Ž€Cû÷›(¤ØËu¸6=ÍOFFL: ÀÂüùä ç9uò¤Y©¼Ù@ÌqlñgÑ݉:6à^˜E¥›öM&“7ü}ý=÷4嶸ë#$€5d9,òå{?Ï ¦Þú_VKXî{ÿàkßߌi€ð`ñG:óL_½Ê… °l›8€â:»X—HðÄîÝ4ÂÏ÷ùåk¯u ÀtZ`p9r|âŽ$sÿ—¸R·¡ø %hB‚Ñjɤ•BJ‰ÖšjµÊî={øÁSOá8ükrÇqÈår\™œÄ²,¤”Ýk e)€4Æ(àc@a[ÙpA­U=€QFÐ×ÏÒP £5ªÑ T,R«Õp‡üÂÅB×u *´ÖH)išÍÍÞêèèèèèèèø`¯¼["-H6+!vt , ŽDú B>H§o©€I¥šù¬ÖÔk5Å"1ÇÁq¼¾>➇ã8Ô˜ëb[V§˜ê €ÁfßUæ¦\`PT+’¹Ki}h((¹L΃Vb}èËïÒ.f6²Ÿj¥ŒÖ­”ª‹„ºmYÌf K¤”AH>_Ķ-×í€R |óqaH½Þà«÷ß…Ñ!%kÒ$}¥žÇ÷úÑZ“JõsÁ„œ˜hêkä\ée&¤Z“TÇäC°,Ö¹f €$Nƒ¾x–lÐÀÅîh¥ð¥d˶©a²uëVŒ1)ùâæÍd2Â0$™L²aÔR¬[¿ž“o¼Á±?ü |a×ìÁÒ@6ÿü=0¥!&ù\ü#fN_¼ÉÄe²Õ€µÀ¯»P)—‡ŠZãÄãc‚€Ztª¦J¹L¹T" C°X( ”¢Ï÷©V*KQÍ£Ëk1L¨ Ê t#ߺ|qÁ”ÐÆ´v?ÑýúöÐÐÛ¿=q‚Çví`hǤe¡µŽÄ«|Ì›ÇcKÉàš5lÚ´iW É4>3 Þ#"óBÏìÛ'þzîòþè(n<Þ}°"M‚_añ ¶?8Ç7¶?Úƒ$à¬Ââ—´Ðä ·¼–[¦Fëó“™ú| P·šÜ Âa#,¯ã6¯MOGÈÚ.îݱ1ñý{q[mÙ+ÜÑbm¿Ÿ9ÿöÁ"rmÚvß}üèÐ!}䆇‡™½vmEu¬±@Î䮋ð¾X6eŽ4•X˜Ÿï´É$ýé4é|ß¿^X¬D³à×föÈ\.7tÛ‘{%Ï¡>‹Þãä±c&=0ÀØùóÄb1jAÀÐÎÜÉðøð0>p‹/= ‚’à+ë=öìð¹:“ãà‹/ŠÛõf]ø4½uü¸ÉÎÍá¸.¥B×åÃK—p€òƇùÝÁÇ)–«Ôê5¾¾ý;b˶VÁ}Eô¦ÊÙÓ§ `Ò-f™'îÿso«Ôkµ;’NÿE‹ÔèàZîIEND®B`‚crossfire-client-1.75.3/pixmaps/skull.xpm000644 001751 001751 00000001030 14045044275 021302 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const skull_xpm[] = { "20 16 6 1", " c None", ". c #FFFFFF", "+ c #BFBFBF", "@ c #7F7F7F", "# c #000000", "$ c #404040", " ", " .+.++. ", " ....++.+ ", " ..++.+.+.. ", " .+..++..@+ ", " ...##@+##.+@ ", " .+###+@###+@ ", " .+.#+++@#@@@ ", " ....##.@++ ", " +..##.+@ ", " +..##@++ ", " @..++$ ", " .####+ ", " +++@ ", " +@@@ ", " "}; crossfire-client-1.75.3/pixmaps/coin.xpm000644 001751 001751 00000001010 14045044275 021076 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const coin_xpm[] = { "20 16 5 1", " c None", ". c #000000", "+ c #FFD700", "@ c #FFFF00", "# c #DAA520", " ", " ... ", " ..+++.. ", " .+++@#++. ", " .++@++#+... ", " .++@+++..+++.. ", " .++@++.+++@#++. ", " .++@++.++@++#+. ", " .++@.++@+++#++. ", " .+++.++@+++#++. ", " ..+.++@+++#++. ", " ...++@##++. ", " .+++++++. ", " ..+++.. ", " ... ", " "}; crossfire-client-1.75.3/pixmaps/client.ico000644 001751 001751 00000073730 14045044301 021402 0ustar00kevinzkevinz000000 000000  è–(~00¨¦ ¨Nhö Â^!00 ¨% =  ¨Èb hps( @€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿïWxgGhøì`wˆˆ ŽÌp(xˆÎÌd€€XˆˆFŽÌPpWxxø|ÌD`xˆˆîìÄP‡'wˆˆ|Ì|GpWwˆˆFŽÌL@pp7xˆˆÎÎÌappGwˆˆŽÌ\@ppwwˆˆìÌl@€7xˆˆ ~ÌÌD@ww‡fDDDTllfww7LLÎŒˆws@DL|Ì爇wt0LLÎŒˆˆwp@D|ÎÌæˆ‡wwpLLÎŒˆˆwpDLlÌæˆ‡ww0LLn†ˆˆwD\|Ì爈ww@LÆÎŒˆ‡wp0DdÌÌæˆˆww@D@NÇrRV0p€pq€tqðwÿþ?ÿÿøÿÿàÿÿàÿÿÀÿÿ€ÿÿÿü?üüüüøøøøøøøøøøøøøøøxøxÿþ?ÿÿþ?ÿ( €€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿx@ˆNÇ7ˆÄðwˆHÌpwˆÌ wˆNÌ@wˆfÄGLÆqwLçh‡wLÌxwwLçx‡w\ÆxwwDnwwtpwpþ?ÿø?ÿø?ÿð?ÿð?ÿà?ÿà?ÿà?ÿà?ÿà?ÿà?ÿà?ÿà?ÿà?ÿì3?ÿÿ?ÿ(0`   >7 /"((*2 ,4((4//;#08)6=77=FOSV_]G KMainqz} r nG I% g'~/f3f4v?H&M%] pA--ÿX1ÿqQÿŒqÿ¦‘ÿ¿±ÿÚÑÿÿÿÿßãÒÄÆÀ*ÌËÉêç^¾=A<ÂÒ±//,4¼YÄÒñîõÁ¦²°ªyÐÊìçóÁ¦­­¨-éÙÑÙëçóÁ¦­­§¡ˆŒÔÖÒ×ëæóÁ¦®­§ ˆ‹”ÎÓÑØëçóÁ¦­­§¡‡Š“?ÎÓÑØëçóÁ¦­­§Ÿ‡Š“DÄ6>ÇÓÑØëçóÁ¦­­§¡‡Š‘!3àaedÃÓÑØëæóÁ¦®­§Ÿ‡Š~ƒ$O _caÃÓÑØëçóÁ¦­­§¡‡Šq~#´ ZaaÃÓÑØëçóÁ¦­­§Ÿ‡Šq"»Á;daaÃÓÑØëçóÁ¦­­§¡‡Šqs…Ï;caaÃÓÑØëæóÁ¦­®§Ÿ‡Šqsv2Ï;caaÃÓÑØëçóÁ¦­­§¡‡Šqsv2Ï;caaÆÓÑØëçóÁ¦­­§Ÿ‡Šqsv2Ï;caaÃÓÑØëçóÁ¦®­§¡‡Šqsv2Ï;caaÃÓÑØëæóÁ¦­­§Ÿ‡Šqsv2Õ:cacÃÓÑØëçóÁ¦­­§¡‡Šqsv1ÞSQFaaaÃÓÑØëçóÁ¦­­§Ÿ‡ŠqsulkpãQHGeeeÍÙØáïíöÆ«±°©¢‰Œ’~€wmhoæ888CMJN]\¶@0˜—•'%&)!ä !!(&%x—–™+¶]\PMJM9785ènh|€Œ‰¥²¯³›ôïîíÜØÛÃce`GHRèifzsrtŽŠ†£­¬¯šðëëåÓÑÓ¿_cUEFIèifzsrtŽŠ†£®¬¯šðëëåÖÑÓ¿_cUEFQèifzsrtŽŠ†£­¬¯šðëëåÓÑÓ¿_cUEFIèifzsrtŽŠ†£­¬¯šðëëåÖÑÓ¿_cUEFQèifzsrtŽŠ†£­¬¯šðëëåÓÑÓ¿_cUEFIèifzsrtŽŠ†£®¬¯šðëëåÖÑÓ¿_cUEFQèifzsrtŽŠ†£­¬¯šðëëåÓÑÓ¿_cUEFIèifzsrtŽŠ†£­¬¯šðëëåÖÑÓ¿_cUEFQèifzsrtŽŠ†£­¬¯šðëëåÓÑÓ¿_cUEFIèifzsrtŽŠ†£®¬¯šðëëåÖÑÓ¿_cUEFQèifzsrtŽŠ†£®¬¯šðëëåÓÑÓ¿_cUEFIèifzsrtŽŠ†£­¬¯šðëëåÖÑÓ¿_cUEFQèifzsrtŽŠ†£­¬¯šðëëåÓÑÓ¿_cUEFIèifzsrtŽŠ†£­¬¯šðëëåÖÑÓ¿_cUEFQèjg{ƒ‚„Œ‰¤®­±šðìëçÜÝâÈe½`FFQäjg}ž®­¯šòëëìL HFIç  œ÷bãã+÷TÕò[¹¹XÀ·ºV Lº¹bÚí[¹¹XB¸ÊÅôÿÿüÿÿÿÿüÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿþ?ÿÿøÿÿøÿÿøÿÿðÿÿðÿÿðÿÿðÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàðÿàðÿàðÿÿþÿÿÿÿþ?ÿÿÿÿþÿÿ( @   (>##$+++)/1..9110556@IFK XT battql=i(,n27J@@?i@ mD34=B<GLAA@@@IEEMIIMKKQJLRNNSNNUJV[SSSUUU[TTRRXTT[f\_``_T_d\\bU`eaa`ddcaadeefggiekmiijjjneipnnslxsssssttttww{uu|yyxyy}‚Œ‹ ˜ ‰•¨¹¾§§£ª…%¨#ƒ!Ÿ ¢ £%$¦$%ÂÆÏÊð.õ.ê1 î2 ð8õ9ó=õ=ð2 Ä$#È$#Í%#™RS™Z«W«`¬gœ^!Ÿ`"¥i#·r'¹s'¹t(TS÷…!þ†!þ‰!ÿ’'ÿ•'ÿ˜'ÿœ0ÿ 1ñøYtx…p|…~~‚‚‚„„ƒ†††ŠŠŠŒŒŒ„Œ—‹‹‡Ž™“‰Œ’’’”••–˜˜˜Ž• žž¢¥¥¥¥¥©©©©¬¬«««®¬¬¬°°¯­­±±±°´´³··»··¿ÀÀÅÆÆÆÇÇËÊÊÊÍÍÍÐÐÏÑÑÑÔÔÓÔÔÔÔÔÛÓÕÞÙÙØëñûññõôôøÿZÿ1pÿQ†ÿqœÿ‘²ÿ±ÈÿÑßÿÿÿ/ P6pLb°xÏŽð¤ÿ³ÿ1¾ÿQÇÿqÑÿ‘Üÿ±åÿÑðÿÿÿ,/KPip‡¥°ÄÏáððÿò1ÿôQÿöqÿ÷‘ÿù±ÿûÑÿÿÿÿ/-P?pRc°vψð™ÿ¦1ÿ´QÿÂqÿÏ‘ÿܱÿëÑÿÿÿÿ/Pp!°&Ï,ð>ÿX1ÿqQÿŒqÿ¦‘ÿ¿±ÿÚÑÿÿÿÿ+·©-еG:NŸ£¬´¥|‰†pjtY]SB ()3=HŒ“›‹zy_ZTPC PR\[xz"F—•ŒŒ=3*&CQbYhln„‰€𱮥¥N?5+C QbXfkmƒˆ~™®¬¢¡K>4#C QaXfkmƒˆ~™®¬¢¢K>4+C QbXfkmƒˆ~™®¬¢¢K>4#C QaXfkmƒˆ~™®¬¢¢K@4#C QbXfkmƒˆ~™®¬¢¢K>4#C QaXfkmƒˆ~™®¬¢¢K>4#C QaXfkmƒˆ~™®¬¢¢K>4#C QaXfkmƒˆ~™®¬¢¢K>4#C Qbegqn„ˆ™¯­¥¦‘N?4#C Q`^‚ˆ™¯°B+'5#D’vŸ²J/7§86$@71¶œ21³L¶¤ÿþ?ÿÿøÿÿàÿÿàÿÿÀÿÿ€ÿÿÿü?üüüüøøøøøøøøøøøøøøøxøxÿþ?ÿÿþ?ÿ(  ''.((+569VWXeB'N/P1C+$Y='?@FBBHJJNKOQRRSXXWVVZW\^YYZ[[^{QQeeegmottx{{{† • — ‹Œ§º ¬ÁÎ*×$ñ5ô6¹q#ÑN ÜZ÷_ÌyÕ#cf qqÛ‡,Ûˆ,þ—,~~‚{„ƒƒƒ††ˆŠŠ‹Ž—‘‘‘‘–š””˜› ¥¢¥¬¬¬¬­­°®±¶¶¶¹¹¹¹ÀÀÁÍÍÍÐÐÐßÐÔQÿ‡qÿ‘ÿ²±ÿÉÑÿßÿÿÿ/Pp ° Ïð ÿ=ÿ1[ÿQyÿq˜ÿ‘µÿ±ÔÿÑÿÿÿ/"P0p=L°YÏgðxÿŠÿ1œÿQ®ÿqÀÿ‘Òÿ±äÿÑÿÿÿ&/@PZptް©ÏÂðÑÿØÿ1ÞÿQãÿqéÿ‘ïÿ±öÿÑÿÿÿ/&PAp[t°ŽÏ©ðÃÿÒÿØ1ÿÝQÿäqÿê‘ÿð±ÿöÑÿÿÿ/P"p0>°MÏ[ðiÿyÿŠ1ÿQÿ¯qÿÁ‘ÿÒ±ÿåÑÿÿÿ/Pp ° Ï ðÿ ÿ>1ÿ\Qÿzqÿ—‘ÿ¶±ÿÔÑÿÿÿ/Pp!+°6Ï@ðIÿZÿ1pÿQ†ÿqœÿ‘²ÿ±ÈÿÑßÿÿÿ/ P6pLb°xÏŽð¤ÿ³ÿ1¾ÿQÇÿqÑÿ‘Üÿ±åÿÑðÿÿÿ,/KPip‡¥°ÄÏáððÿò1ÿôQÿöqÿ÷‘ÿù±ÿûÑÿÿÿÿ/-P?pRc°vψð™ÿ¦1ÿ´QÿÂqÿÏ‘ÿܱÿëÑÿÿÿÿ/Pp!°&Ï,ð>ÿX1ÿqQÿŒqÿ¦‘ÿ¿±ÿÚÑÿÿÿÿ>DB . 5EF 4)8EF 4(!IEF 4(%jMÄ"RÐv·¬!€&÷™Éd.{ÞøÇrÞß›ç98gÂ99ßïóÄ?¾¾g.çò™óœ3óâ"ÄYtõÕeååårïÚµ†–_²dI˯¶o¯“û!ùù3/ö{C¾z\û ý€¨€¨€¨€¨’o,\X¶råJÀ÷Þkhù«¯ºê£åË–ý›Ü?¸~ýŸ.ö{C¾z€CrÃõ×+Ͼu×]†–_¶lYåo~ó›ò‹ý>s€¨€¨€¨’ÉcG—}ûöÕ €‡ŸxÒÐòKJjÂ]][åþpccåÅ~oÈWpHÒƒmÚ¿ ðòïþÈÆFË_VRBå7ÞÈú'7oÆ>dã`ã9$QÏ!ˆ*Øx @TÁÆsH¢Šm6ÞÖ-[”·±~¶y3›‘‘A©ii†÷\s3ë***ÊOú|íêöɺºŠÊÊʲó»P(DþÎN66ÝʺS].êìÑoÚºÆ3TUsˆtú#Öùµ¿°Ô9’^y%;nìXÖEc1ŠI]$î}r®.-eXÿÿµcG¿¬ÿÏ?ûL~©Tõî»Tô¨®KII¡tm¿2’ööv uw뺲²²Ê¯/Zd¹Û¨°Ë€DØ$$"À& 6É“?^¶|ùr@ÙŠllrr2%%%zÜniC‰¼óÎ;å—–”\4þsË–ŠW_yE@·vµ+^kr2Ÿ‘¬1s{u];üÞKÙØŽ°.@€Ò… ió~ÄÆÞ¹z5ëØ%: …h”ß_øÖÊ•¬ûÝï_¾÷“OúeýW½÷{¹/lßNÔubû•‘ôôô°÷zëªU•ÿºiøªyhÝ:åÀìyóL.ñ ¤å¢°ö¶ÛØ@0¡¶pØÐòžaS)%»P×¥ާ¼™KØØ“[ø'° íL¬6ÖåŠoúžâÇHbýÑÑÑ/ëÿ·•• €§·l¡kjL}q |Õˆ›€DØ$$"À&yxÃ%³æÌacS´?c—‰BŠîbð/wÜRQQ¹S€?¥æî«zŸž‚Ë)%«@ßN llÓ3׳®?Xÿï°N('úé.Ì»o¿ÍØ´y3ýy÷nþ^ >¦ê"(ˆ3ß߸Q Àô™|Vê,íÏØM@"Ÿ¢»ØlZSÎÎÚºct‚ߤTÅòž¡ã(%3O?nX eM_ÆÆžÚÆQèO]·Žubýijê—õ¿¿¦†¯ßì1ú ªJÿ>éË#ëN~PgHD€M@"l`“ˆ›ä‘(˜6s©b´øzé$©ë¡/wm}&Nź–¦­ìØ«ëÄ;Ý„SO¨!V´êнêîœù,õ-ÖuÞá™4fÖ066¦zQš~.é[«=§ŽRàÓ÷ÙÐ3¯ÞÇ:ÿüÍoÒ/ùK6Ö×Òbh(’_¥ýɦM¬«Þ½›ê =n¼)ÌÊbÝDíC%¿¨H׉¯öF#ü.Lzf&ëv}ø!¯¯×u Έ›€DØ$$"À& 6É#¿×7*Fߢý].u?9ù²Á¬;Ùè§öv~dE_òLKá‡uz¾—R³Òu](ꢎ(ëêá¯>|éTŠåé¿Ëï-L¡âéþšË»ÜÚGÈà=6öìëße €ojübÛ66¶­½uâ·ÿª.ªèîßÏ_“ÏGþ€kˆê÷øMMM¬rtƒúåÅïùsDDs,hOdøîF†««€Ùy´¦ö €| ¾õϘ6‰ ~¬a"µ¶åK­êÞDž4¾Så’'7[×ui4‡J(ö?)D_åjþÅSùP½gÒ=«P“à]6ôìëkY§`ñbÚ¦ C1K‘jâÑ…Ÿ -Š3q°º¤ƒULÈ!få‘søðaÖ9s†ü]]†–W=ÿYÅò½g0 @”TUQ=07óë°\æg º `€©—sêÆSk{žÔÆH…@º[Àèaäöêw 4™ÎFÜü¥v+îŒÔvÔýãz{à›Ky°/š@[Gëb} ˜Ð¤Y1+sïZ–.Âõu×ÖÖòÇ<{–ºü~¶|ªbùÖÖVÖ‰™¢ýÒò.šŸ @Ü4v`êå|ªçú†ÒGpïnÉwì¬t¾S º$ŸÜ9zXº¢n:Ä_j·bJ’‘Ú²^ý¯¼. þ\}Ý`œJ -mm¬»TWñU³êöÀ±cÇX'P HwzHå7];€‰³‚ |¡» Ÿ0?°Ë`~`– ÀüÀ:,€ù€uX.óë°\æÖ`¹Ì¬Àr±C5ô;FW4M ‡Æ êñà €uVg‰ ¬Àr˜X€å0?°Ë`~`– ÀüÀ:,€ù€uX.óë°\æ`>ÖY̘œ°ÎŠà 1€uX.óë°\æÖ`¹Ì¬Àr˜X€å0?°Ë`~`– ÀüÌÀ:+€ù€3ÖYœ$&°Ë`~`– ÀüÀ:,€ù€uX.óë°\æÖ`¹Ì¬Àr˜€ùXgE0@bpÀ:+€3€ÄÖ`¹Ì¬Àr˜X€å0?°Ë`~`–Kßܤ}«ö7IêÔL›œÉºcÇ/¡Ö616V À¨‚>Èæ/µ;»ÑÚŽîÕïl¹ÃˆŠ§óÍS@ zšê¨ë¯°¡g^¾—u*n¸áÚ¾};ÛÚÞÎ_“vðÊk*‰¨8y’u=Ú81þüôÀÑ£GY'ð+P-¯À'–¿ªþô'ª—`q¦o–+FߦýM–:5Ó§pêêG C €Ç«ß1:ÅoÂ*ø§%Ö6K®~ÓäÁ‡ tòù÷Ȇ~±ãNÖ©Xºt)½øâ‹l¬ €¨ê  Nª¸€3€#Gް®¿ßÐòí*|>õ@ßÖ*>xÿ}:VW§ë@œ˜X€å0?¶à‘(˜6s±b´¸3P"uâH ²‘—]šÎºÆS…ÔÞ)¬ê»éi|§È*Ì£´,ýÝ…@4•|Ž … ×3[ÿ¸ÙùD#.ãC£=%—xMÉúåÃg©û5llëÛO°N@é´yÓSl¬ê"Z4¦½¦˜þu‰:áœ9ûël>q+.Âohd]Kk«v󋀪‹x]üC¡­µ‚ÝÝúå5’¤gò»H{öì£ÆF=l Î<²q}ÌUŒž©ý —:qU™ßr»$×ͺæÎAèñH­€dâ;Eš¶S¤¤éoãõD“)ñ°±VÜðjŸTýΚ¦y”=‚F8”¬=w’þÓ.Öq†b§±¡±Ãï°Nò¡:iÂ8Zµ”cðwñפ8ˆÅ¢½r:ü "hk[ÿ¾úú>ãã·!A¿†?5RÀÁ ×ÕÐÎBôkàË»ŠmíæûÏ¡ÚÔìÓ¿/gæÖ`¹Ì¬ÀrÙøÐCJfÍžÍÆŽ[DCë¿w/vJùë¥"¡¿2››Mééú S\Ùq)vª¬ŒLrKˆ+Øéž466¢xMi)©Úή 99•{&/Òu½Rôð¢GÑäSûŽwìK¤¨’7„23ô_1NÓ@ÈÎæ¿P½&Ûþ·îÖ:oŽ—Dù4hP¹=ú;§›šèÓÙØGŸÚÄ:AŸ €§dåÞô4›œÃïl¸´õ$ Þ¦?Èw·¦]Š»-Úú$mÙd¾ü$÷iÖ54´P[[@j“ïJ[W™ÖyÜgµõ¯ÿŠp ¥–vŽÑ`E÷Šö÷w]âÌÃëÖ)(½òJ6vÎüù4bÌ]'>iPTT¤Dú3ÕÁ/¢`XAÄív“×Ë`Õó{´ƒWþOOO§!C†°±ª3onnïøóÓxü8íýè#6öÎ5kX'6“5}9 »ûu66e0ŸeÇã;VHû@íä_»§£P¬Ôæ(ÿÝ–xÀ¾®g{øoj?;K¾sò$)Þ•8Ûëd]ºç¥¦èû.„šÏ©ªèžÑþöégæÖ`¹ÌmxðþûËn^¹’°ðškØØ+KKi”Aä‰D ù»XŒT(ÈϧL @Î… ]LÏÈ ¼¼<6Ö('4öýùÏlì=kù¬À*2§ÝDÃî|™MÉås(追çë¯îŠ»Í1‚ô .%³Ü ¬;r¸Ù8^€ÇsF[ÿúëÄ4T{€ €-ôå€ÿˆ3÷ßsò `þµ×²±‹®¿žÆŽ§ëzñß´+¦µV}‚‹3ÕY€êûåù€Lý!Îrrø-³¾ïˆzð`~Ź/<'è¯{ö°±ßݰuJ¦,¡‚oóYS¼Š üŠ3€ºw9ÀäÓº€ô¾\ÚzVÌès…»žuGj›©Å§º ÀÏVÔ´hO¥]~óñçWðïÚßǺÄ€ù€uX.óë°MÞzóMvT>½u+íÙ»×Ðò‹.d]±†Ç`éŠ{_¿%öÀëå¨òüž<)‡u]КZ}Ÿ²±|:¢ŠŠ í³ª¼’lX€m€`<°Û9Àxl@ÅË/³-¸å¹çhï_þÂÞh²bù¥¥¬äJ[¬÷Ÿ¶r& wJ­® úOiðùø?ŒFôÆo”¯\¹ôG^ß±ƒmÁŸýüç´oÿ~]§þ&8ÑüE‹XWóüóH-PÅQ¤*–¿Fñ[‚ââb uÀ8¯¾újù­·Þ ú#ÈÆë°MŒÖ`› ¬À6@0X€m€`<°Û9Àx`¶ r€ñÀ:läã€uØ&ÈÆë°MŒÖ`›übëV¶_xé%:ø·¿Zþºë®c`°€p8ÌÆ{;ØÃº¤ðNJŠþ¯®ëŸ¦ö ±}jÇŽå·ß~;è ¬À6@0X€m²`îÜ2¹«|ë-ªÚµËÐòOmÜX!wSfϦaÇëK—KÛùÁžäâ«X±,?ØSÓø:¹fN#Ñ®ë¢1WÍ?ÝtÃV2öööš»ï¾û„‘±;¶ ÞŒ4ˆAÌš?Ÿ†£ëÄÁŸ’Ê?AT+X±í2øsÑ«¬¹­ç»ù3Ѫeß`]EEEywÊ [Lëo€"àà€ƒsK$)ÆËÿ„˜–e·ÝF_›PΜÁgš]½vmïïÎOï|Šß„(œ€â°ôusĺKVÎQ=~øj;÷kù%_SD¥sæ°î×;w–{GŒNÍ…ÜÌUÔk~˜fΛ§ëÄŠVA¨“‡È“ XÞ ñÒ2þ[Åï+ê>/§–sƎ߯O™Â:q0|ÂàÔ€ƒppÞ|óÍõ;wîœkdl¸µ•A1jüxò¢ërµƒrŒ4G€H ȯ‚{ÜnvPÜp çT5SÜlhq×oùòÑ·kfL œ QF·nxâ‰#ËÛ= ÎüíÀ6£ÐÖ§Ÿ¦½ÒÁ6eÆ ºcͶ|[k+ë222(Uºe(Pðz½l¬­ð¡Jš5ü2©D©Ši½?á»°ø×âˆOðxâ vˆ3Ø9 Î`ç€8€‘žv±fï^Úò쳆ÿî}÷Ѭ+®Ðu¹ƒSñ¥—²±Á?ª, @˜¨Kñ­ßã¿z’uYõ;)­í®‹òù{ƒ}8Ž`å%"Ø$Xy‰6 V^"€M‚•—ˆ`“`å% >_…û _¼ð‚¡å×=ø Í=[×åæåѸñãÙØ â«ÄƒrrÈíÖm¶±¾žjvíbcã uÀ¥ [ S1÷DZmÿÁº”ã¯PR›þßöÓ~ðŨ´´t²ÜE£Ñ†êêê6C+Ûá ȹS§ØÀO>¡^|ÑÐòiå¼¹úŸ"ˆ„tÜ„ ll·€¬ìl@ñc´»ªŠ€´ñP÷ì3¼<þQÛ§†Ö•Ïç»Vî4|ÿ{Íš5_z‡$ Ø% À. v H@\ápÅo¼¡à‡‘¦›šÊÿÍúóçӘѣu]Ö AT¨˜XÀ°ÂÂ^ί¹™ê>ÿœ½ëþûY§`Ú4ìîl¬ÿ\-ÿ}Üð+è®~—uCCQf¤A×E"Q õðË€E—\Â.ö„B ïÙƒ‹€âQ£Ø@ãñã´w÷n6Vܲ“säÈjñùtKÌ*¬˜GÀ¤iÓ¨@Càüôõ[‚å+W²N@öì2*z°‚=´å;|ÄxÑŽÝž ßÝ&ñ}\î¦1ùúWà„È×ÚÅÆþtÛ6ìÃq+/¼Ö V^x¬¬¼ð X3Xy à°f°ò¬˜p˜êî¦Îöv64ÍÍgÊ úý–¦¯?vŒvUW³±ÿóÙg¬‡ž<…y8£€ºó§²±oÿp9ëÁ…¥‰J"шö¶øUüÙWÍg˜Ðã?ü &ôè‡+€~ °bè§+€~ °bè§ & ͽùæ›Gœß‰ƒÚßů‚«xô±ÇÖwttè~L°oß>zö¹çØØpŸfÃE|ÇèIvSÀÍï"Üqí¤r¹ v‡¨'¬  +g0VFkžøñCÿ´_ÀÌ%EEì ⃪*zìñÇÙX¯ÁÇ“wûÕÿ ûƒ7£ÁÆ€ˆÑ`ã ÀÄh°ñ`Š *vJTUWÓžä3ðgo¦ /Tø!=ùÔSl,pv°ñ`b4Øx01l¼€ 6Þ @Œæÿ©§¢X¦ìCIEND®B`‚(0` ¾¾ÂÿÿÿÿÿÅÅÈÿÿÿÿÿ§§«ÿ’’™ÿ™™ŸÿŠŠ“ÿ((4ÿÿÿG ÿš¥·ÿ‘šªÿŠ”£ÿÊÑÚÿÊÊÍÿooxÿ€€ˆÿJJSÿOOXÿGGQÿ‘‘•ÿ¨¨­ÿÿ ÿÿ¦2ÿf4ÿf3ÿg'ÿpA-ÿ{ƒÿjjsÿ’’˜ÿÿÿ««­ÿååãÿÝÝÜÿññïÿŽŽ•ÿÿ ÿê-ÿÿ©3ÿÿ¨5ÿÿœ"ÿ.ÿÿÿîîîD¦¦«ÿÿÿžž¡ÿÕÕÔÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ‘!ÿ~/ÿÿÿÍÍÑÿ(ÿ¸¸·ÿ¨¨¨ÿ¸¸·ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿŽ"ÿùHÿï*ÿÿ1ÿÿÿÿÿ°°­ÿ°°°ÿ««ªÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿùGÿð,ÿö1ÿÿ:3ÿÿÿ//;ÿÿÿ(ÿ¥¥£ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿð72ÿ ÿÿJJUÿÿÿ"ÿ¥¥£ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿð72ÿÿÿHR]ÿ—ÿ77=ÿ99AÿLLSÿœÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿà74ÿVÿaÿ] ÿ¸ÂÆÿÿwwuÿ}ÿ||{ÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿÃÿÓÿqÿVjvÿ ÿppoÿvvuÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿÄÿnÿavÿÿoopÿvvuÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿÄÿiÿg‚‹ÿ—ÿÿÿFFFÿzzzÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿÄÿG ÿÿÿ  ¦ÿÿÿEEFÿyyyÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿ»ÿM%ÿ ÿÿ  ¦ÿÿÿEEFÿyyyÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿ»ÿM%ÿ ÿÿ  ¦ÿÿÿEEFÿyyyÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿ»ÿM%ÿ ÿÿ  ¦ÿÿÿEEFÿyyyÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿ»ÿM%ÿ ÿÿ¡¡§ÿÿÿDDFÿyyyÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿ»ÿM%ÿ ÿÿ©©°ÿÿÿBBDÿyyxÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿ»ÿH&ÿÿÿ»»Àÿÿkkgÿbb`ÿSSRÿvvvÿtttÿvvvÿ———ÿ­­­ÿ¨¨¨ÿ´´´ÿÏÏÏÿÌÌÌÿææäÿŽŽ•ÿÿ ÿê-ÿÿ1ÿÿœ2ÿÿ"ÿ÷Fÿì+ÿò0ÿÒ75ÿµÿ¼ÿ°ÿ—ÿÿ²ÿÿÆÆÊÿ ÿccaÿ[[ZÿVVUÿ~~}ÿ}}|ÿ}ÿ¢¢¡ÿ¹¹¸ÿ´´³ÿÁÁÀÿÞÞÝÿÛÛÚÿõõóÿ˜˜žÿÿ ÿú–/ÿÿ¨3ÿÿ§5ÿÿ—#ÿÿLÿý.ÿÿ3ÿâ;7ÿÃÿÉÿ½ÿ˜ÿ‘ÿ¦ÿÿÉÉÌÿÿ(5<ÿ#08ÿ*2ÿ3DLÿ1BKÿ3DLÿDT_ÿM_lÿJ\iÿRbrÿak}ÿ_i{ÿnw‰ÿEJ[ÿÿ ÿv?ÿ…Hÿ€Gÿ‚@ ÿÿz ÿ} ÿnÿ_ÿaÿ]ÿKÿGÿSÿÿÇÌÏÿÿOÿFÿMÿcÿ`ÿbÿr ÿ} ÿzÿ ÿIÿ€FÿŠKÿJ&ÿÿÿnv‡ÿcl~ÿaj|ÿ]hzÿO_nÿK]iÿN`mÿ?NWÿ0BJÿ2DLÿ-ÿÿÃÌÐÿÿ ÿ‘ÿœ/2ÿÉÿÇÿÉ ÿì9"ÿÿ3ÿý,ÿÿ]ÿÿ©4ÿÿ¤3ÿÿ¯4ÿž_$ÿ ÿÿîîîÿààÞÿÞÞÜÿ××Öÿ¼¼»ÿµµ´ÿ»»ºÿ——–ÿyyxÿ~ÿrrpÿXXVÿ[[ZÿggdÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ–ÿ‡ÿ‘,0ÿ¼ÿ¹ÿ» ÿÜ5!ÿñ0ÿë)ÿüWÿÿž2ÿÿ™0ÿÿ¤2ÿ”Y"ÿ ÿÿààáÿÑÑÐÿÏÏÏÿÉÉÉÿ¯¯¯ÿ¨¨¨ÿ®®®ÿÿpppÿwwwÿjjjÿQQQÿUUUÿaa_ÿÿÃÌÐÿÿ™ÿ‰ÿ”-1ÿÔÿÓÿÕÿû9ÿÿ3ÿÿ,ÿÿYÿÿ¡3ÿÿœ1ÿÿ¦2ÿ”Y"ÿ ÿÿààáÿÔÔÔÿÒÒÒÿÍÍÌÿ¼¼»ÿÀÀ½ÿÆÆÃÿ  ÿ}ÿ……ƒÿttrÿSSSÿVVVÿbb`ÿÿÄÌÏÿÿ˜ÿŠÿ©'*ÿÿ ÿ ÿ ÿ ÿÿÜNÿÿŸ1ÿÿ›0ÿÿ¤1ÿ—[#ÿ ÿÿããäÿÒÒÒÿÒÒÒÿÖÖÕÿZZaÿÿÿÿÿÿ ÿZZYÿUUUÿ``^ÿÿÌÌÎÿÿÿÿÿ/ÿÿ ÿ7 ÿ±j&ÿ ÿÿÿÿÿÿÿÿÿppzÿÇÇËÿÿÿÿÿÆÆÉÿÿÿÿÿÿÿÿI% ÿ½r(ÿ ÿÿÿÿÿÿÿÿÿccmÿ««±ÿÿÿÿÿääåÿlluÿ||„ÿ||„ÿhhqÿ‰‰ÿww€ÿ|~‰ÿ~ndÿ>ÿÿÿZZcÿ}}‡ÿ||„ÿrr{ÿµµ¹ÿØØÙÿnnwÿ||„ÿ||„ÿggpÿIN_ÿÿÿxxÿ£ÿÿÿ””šÿÿÿêêìÌÿÿüÿÿÿÿüÿÿÿÿàÿÿÿÿÿÿÿ?ÿÿÿÿÿþ?ÿÿøÿÿøÿÿøÿÿðÿÿðÿÿðÿÿðÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàðÿàðÿàðÿÿþÿÿÿÿþ?ÿÿÿÿþÿÿ( @ jjnU@@Aÿÿÿúúþ9ïïõª¯¯µÆFFNÿ ÿÿëõªáëúªszƒq[[_Unnsÿ\\bÿyyÿ‹‹ÿ¥¥©ÿÿ¥i#ÿ™Zÿ™RÿmD3ÿJLRÿ::;GGLU556ÿ667ÿÇÇÇÿÙÙØÿ¬¬°ÿÿœ^!ÿÿ 2ÿÿ˜'ÿXÿÿAAA¨¨¨ªªªUuu|ÿ’’”ÿ­­­ÿÆÆÆÿÔÔÔÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿõ>ÿ÷.ÿ^$"ƪªªU‚‚Ž9ªª¬UÿDDMÿ¬¬«ÿ¬¬¬ÿÆÆÆÿÔÔÓÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿô=ÿñ.ÿ£%$ÿÿ””ŸªiimŽÿOOWÿ©©¨ÿ¬¬¬ÿÆÆÆÿÔÔÔÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿ¦$%ÿÿuhqÆ`jn@@Iÿeefÿzz|ÿ¦¦¦ÿ¬¬¬ÿÆÆÆÿÔÔÓÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿÄ$#ÿ¨ÿn27ÿ+;CU..9ÿsssÿÿ¥¥¥ÿ¬¬¬ÿÆÆÆÿÔÔÔÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿÈ$#ÿ¿ÿi(,ÿ %/U¬¬±ªUUUªIIMÿuuuÿÿ¥¥¥ÿ¬¬¬ÿÆÆÆÿÔÔÓÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿÈ$#ÿ»ÿ‰ÿ;.2Æ¡¡¡qjjnÿÿVVWÿuuuÿÿ¥¥¥ÿ¬¬¬ÿÆÆÆÿÔÔÔÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿÈ$#ÿ¹ÿ–ÿ ÿRRRªjjnÿÿVVWÿuuuÿÿ¥¥¥ÿ¬¬¬ÿÆÆÆÿÔÔÓÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿÈ$#ÿ¹ÿ–ÿ ÿRRRªjjnÿÿVVWÿuuuÿÿ¥¥¥ÿ¬¬¬ÿÆÆÆÿÔÔÔÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿÈ$#ÿ¹ÿ–ÿ ÿSSSªnnsÿÿTTUÿuuuÿÿ¥¥¥ÿ¬¬¬ÿÆÆÆÿÔÔÓÿ««¯ÿÿœ^!ÿÿœ1ÿÿ’'ÿó=ÿð.ÿÈ$#ÿ¹ÿ•ÿ ÿTTTªª##$ÿbb`ÿ``_ÿwwwÿ„„ƒÿ©©©ÿ°°¯ÿÊÊÊÿÙÙØÿ¯¯³ÿÿŸ`"ÿÿ 2ÿÿ•'ÿ÷>ÿô/ÿÍ%#ÿ¾ÿªÿ˜ ÿtÿªªªU ªÿ7@Eÿ:BGÿJV[ÿT_dÿlxÿp|…ÿ„Œ—ÿŽ• ÿtx…ÿÿl=ÿ¬gÿ«`ÿ¨#ÿ§ÿÿ‚ÿtÿaÿIÿªªªU!$ª(ÿbÿqÿƒÿ‹ ÿ£ÿ§ÿ«Wÿ¬gÿJÿ ÿeipÿŒ’ÿ‡Ž™ÿq|…ÿq}…ÿU`eÿJV[ÿ>GLÿ4=Bÿ)/1ÿªªªU!%ª@ÿÿ£ ÿ¾ÿÊÿî2 ÿõ9ÿþ‰!ÿÿ 1ÿ¹t(ÿÿ˜˜˜ÿÕÕÔÿÏÏÏÿ±±°ÿ°°°ÿ†††ÿwwwÿddcÿUUUÿBB@ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿŸ ÿºÿÆÿê1 ÿð8ÿþ†!ÿÿœ0ÿ·r'ÿÿ••–ÿÐÐÏÿËËËÿ¬¬¬ÿ¬¬¬ÿƒƒƒÿtttÿaaaÿSSSÿ@@?ÿªªªU!%ª>ÿŒÿ¢ ÿÂÿÏÿð2 ÿõ9ÿþ‡!ÿÿ0ÿ·r'ÿÿ••–ÿÑÑÐÿÌÌÌÿ²²±ÿ´´³ÿ‰‰ˆÿyyxÿddcÿTTTÿ@@?ÿªªªU!$ª?ÿŽÿƒ!ÿFÿK ÿT ÿ…%ÿ÷…!ÿÿž0ÿ¹s'ÿÿ––—ÿÒÒÒÿÒÒÑÿggiÿAA@ÿ110ÿ+++ÿ<%%& =$$-=$.#.#.* ** ..,........... *-*-----* * && && *** ", " ++@@@@++@++@+@@+@+@@@@@@+ &&&%>%&&+'+%>& =$..&.....,..* ,...,.,.,.,.,.,.... *%*-----* * *********** * ", " %+++@@@@@@@@@@@+@+@+@@+& & &&>%%&%%&&+&&%%& #.&&#.#...,..** ..,..*.*.*.*.*.*,.#.** &))*-----* ** *********** ** ", " & %&%%++@@@++@+@@+@+@@@@+% &&%%%%%%&&&%&%&&%>& ........#...,..** *.#..*.,..#..,.....*.. * %));%*---* *** **---**** *** ", " & &&&&%&&&&++@@@@@@@@+@+@@+&%&&%%>%&%%%&&&&%& &%%& ...#.,.#.#.*.**..,. *...,..,...,...,.,.,.*. !!!!!!!!!~~ #)#)%*-*-* **** *-*-*-*** **** ", " & &&&&%&%%>%%%%%%++@@@++@@+@++&&&%%%%&%%%%&& &&%& &%>& *.,.......,.*..*..., * *....,*.*.*.*....,.., !=#==#======#=#==!!~ {=~ %)))# *** ******* *-*-*-** ******* ", " ~!==~ &&&&%&%>%>%&>%>&%&%%%++@@@@@@+@+%%%%%&%%%%%&& &&%& &%& ...,.# ..* ,.*...* ,.,.*...,..,.*,.*..*. !#======#==#=#==========!! ! !=== #)#)% ********{======={,********* ", " !!======$&%&%%>%%&%%%%%%%%&%%#%%%+@@@+@@+&&%%&%%%&%&&& &&%& & ,.... #** .**.,.** ...,.,..#.*....,.,..=============================!~ ~!==!~ !=====~ %)))# *********{{{{{{{*********** ", " ~~!!==========#%>%&%>%>%#&%&%&%&%&&%%%%%%%%%%%%%>%>%%%%&&& &&%& .,. .* ..*... ...*.*..,.* *..-*=======!;;;;;;!;!================!!!========! !======= {&%]!% ,************************** ", " !=========================#%>%%%%%&%#%%%%&%%%%&%&&&%&%%%&%%%&%%&%&&%& &&& . .* ,.,.,.* #.*.#..**. .,-!===!;];];];];];;;];;;;;======================~ !===!;!!===~ {{{)%& ,{{,*************&&********** &&", " !===!==!==!=!=!!!=!;]]]!=!===%%%%%%&%&%%%%%&&%%#%%%%&%%&%&%&%&%&%&&>%%&& , .* .*.*...** #..#.* *. *.!==!];]]])])])])]])]))))]];];;!!!=!=!!==!==;!!==!!===;]])!!!==! ,{,,{% ,,{,,************&{&&&&&&&&&&&&&,&", " !={!!=!=!!!=!=!!!;]]]]);;!!=====&&%%&%&%&%%#%%%%%#%&&%&&&&%>%%&&%&&%%%%%>&& ..#. .,*.#.# * ...*.* *. #={;]])))];!];!];);;);];]))])]];];!=!=!!!!]]];!=!==!=;])])!!!=!=!~ {,,,,{{{ ,{,,,#,************&{{{{{{{{{{{{{{{&", " !!!!!!!!!!=!!;]]]]]])))]));!!!!!==%%%&&%%%&%&%&&%&&&%%%%%&&%&%#%&&&&&&%&%%%%& * ...*.... ,.*,..** * !!!];]));)]);)])])])])]!);])])]))])];]]]]]]]]))#=!!!!;]]))]))!!=!=!~ %.{,,{{,{, {,{,,,,*********$**&{{{{{*****,{,{,&", " !!=]]]]]]]]]]]]]))))))])])]));!!=!!!=%&&#&%%#%%#&%>%%%%&%&%&&%%%%#& &&&&&%%&& ,**.#.#.* * .*...,*. *!=!;])))]);))]))]))])])]);));)])]))])))])))))))!#!!!]]])))])]);;!!!=! ~ %#%.,{{,,{,{,{ ,{,,,,,,#***********&{{{{*-----*{,{,&", " ;!!;])))))))))))))))])])))));))];;!=!=!=&&%#%>%&%%&%&%&%&%&%%&&#%%%& &&&%%%&&&& ...*....** ** ,..#..* !!!;;))])))]))])))]))))))))])))))])))]))))))])]=#!!;]))))]))))))];;!!!~~ ~ %)%%{.{{{,,{,,,{, {,{,,,,{,{********$**&{{{*-------*{,{&", " !!!]])))))))!!!=!!;))))))])))))))];;;!!!!=&%&%%#%#%&&&%&%&%&&&%&%&#%%& &&%%%%%& ,**.,.,. * .... ..,..* !!!;]]))))]))))));)))])])]))))]);)))])))])]))))!##!!;!));)))]))]);!!!!!! &!)%% ,{,#,,,,,,#{{{.,#,,,,{,{*******$$$*&{{{*-**-**-*,{,&", " ;!;]]))))));=,***#;!)))))))))))))))]];;!;!=&>%&%%&&%&%&%&%&%&&&&&%%&%& &%&&&%& ..,.....* ***,.#.,...#.* ** ;!!;!)))))))))!)!)!)))))))))))))))))))))))))));!*{!!=##!!)))))))!=*#=!;~~~~ ~ %&% {{{,,#,,,{,{,#,,,{,{, *****$***$&{{{*-**-**-*{,{&", " !!!]))-)))))!*#!!!##!;))))))))))))))))]];;!;=%&%%%%%>&&%&%&&&&&&%&&%&%>& && &%& .***.#.#...........,....*...-~!;!];))))))!;!!#===!!!))))))))))))))))))))))))]##;!;!!##!]))))!;#,#!;!~~--~ ,{,,{,#,#,,{,,,,{,{ *$$$$*****&{{{*-------*,{,&", " !;;])))))))))=#;;!;!=#{!))))))))))))-))-)]]];!=%&&%#%%&&&&&&&&%%&&%&&%%%& && && ,...*...**,.,*,.,.,..,.,.,.,.*,!;!;!)))))]=#****,****=!;!)))))))))))))))))));#*=!;!!;!=#{!)))],*=;!;~~~~-~~ ~ {{{,,{,#,{#,{,,{, ******&&&*&{{{{**-*-**,{,{&", " );!]))-)))))))##!;!;!;=##])))))))-)))))))))!=!;;=%%&%%&%&&&&&%%%%%&&%&&&%>&& && & ! == .#.*.#*.......*..!...........#];!!!)))!!,*#=!;!;!;;!#*,#!!;)))))-)))-))))!;#*{]!!~!;!;=#!))!#*!!;!!~~~~~-~ ~ {{{{{,#,{,,{,{ *$*$*&***&&{{{{{*---*{,{,{&", " ;];]))-)-)-))],=];]!]!;!##!)))-))))-)-)-);!,#];!&%&#%&;=& &&&%&>%%&=;-&&&%%&& && );! ~);!;! ==.= .***..*.#.,*,...!;!;!..,.,.,...!;;!{));=*#!!;!]!;])))]!=#**,=!!;!))))))));!*,=!;!~{~!];]=#!;#,!!]!!{!{~~~~~~ ;! ; ,{{!!;{{,{, *$$$*&***&&{{{{{*****{{{{,&", " !]!]))-)))))))=#;;!!~!;];!=#!))))-)))))))!=*#!;;~%%%%=!;!$ &&&%%%%&]!] &&&%%&& & !;];;!) )]!;];]!;) ,.# .#..,*.......!;]!]!];!{.....,..!]!;=!!#*=!;]!];]))))-!=]!;!#,**##={;!;!;=,*#!;]{{{{~{!;!;=##*!]!;~{{!{!~~~-~]!]) !;] ;!];]!;{ *****&&*&&*&.{.{.*{*{{{{{& ", " !];])-))-)-)))##!];!!{!!]!;=,#))))-)-)))!,,=;]!!~~&%@;];]!) &&%&%=;!;!; &&&%%&&&& );]!;]!]!;!; ;];;];;];]!;! ==...== .....*,.,.{!!;];!];!];]!{...,.#.!];!##*!]!];!]))))--],!;]!]!];!=#,***#***#!!;]!{{{{{{~!)]!!=!!;!!{{{{!{~~~!];!;]) ;];;; )!;]!;!];]; *$*$**&*&**&{.{.{.{{{{{{{& ", " ;]!)])-)))))-);,!;];~{~{!;;];!##]))))))!=*#=];!!{~~~;];]!];!) &&%&;]]]]!] &&&%%%>&& )!;!];]];];]!]!;) ;!];];]]))]];];];!!.=!..#*,...*..!]];];]]))]]!];]!!=.....!!!!=!];]!]])))--))!,]!;]!]!];!;;];!!=;;;];]{.{{{{{!!;];;])]];]!{{!{{!~~;]!]];];) !]];];] )!;]!];]]];]!;) *$$$$**&***&.{.-{.{.{-,{,& ", " !];))--)-)-)-)]#!;];{{{!!]])))]{#!)-))!#*#!;];{{{!!;]!])))];!) &@];)))]]!; &&%&&%%@)];]]]!])))))]];]!]!;) ]!];];]))))-))];];];];]...*.***..!];!]!]])))-)])]!];]!]]....!;];]!;);;))---)))!#]!]!;;]!]];];];];];];]{{{{{{{{];]!]]))))];]!{{!{!!;];])))];;) ];)))]];; ;]];]!))))))]]]!; ***********&.{--.{.{.--,{& ", " ];]]])-))-))))){#]!]!{{!!;])))-)))-));!*#!]];!{{{{];];)))-)]];]! !]!]))-!];]!) && &$;];];!]))))--)))]];];];) )!;]!])))))---))))]];];];]...*..,!];];]]))))----))])]!];]!]{...!;];);]!)))-))-))!#];]!{{!!;]])];]!];]!;{,{{{{{!]!];))))--);]];!{{!;];])))-)]]!]) !;!]))-!]];]~ ;];];)])))---))];]];) *$*$**&&&**&{.{{-,{,-{.{.& ", " ;];)))-)-)--)-)#=;];!{{];];]--)-)--)]#*#!]!]{{{{{;];])))---)]];])];])))--)!);];! && )]!]!]]))))--)-)--)))])]!]! );]];))))---)-)-)-)))))]!];]!.#--!;];]))))----))-)-))))]!];]]....!;-);]]))--)-)-))#)];;!;];];)))))]!]!{.,{,{.{{];]]))))--)-!!]]]]{);];))))--);]]!);]])))--)!)]!]! )];]]))))----)-))]);];! *$$$*&***&*&{.{.{-.-{.{.{& ", " )!]!))-)-)))-)))#{];){{{;])]!))-)-)]{**{]];!{,,.{;]]))))--)-)!;)];]])))--)))]]]];]~ &&);];)))))----)-))-)--)))]);])~ )];)))))---)-)-)-)-)-))))))]]!---)];])))----)))-))-)-))))))))]]{....*;]!)]-))-))-))=];])]]!);))--)])];]{{{{{{{!])))))---))-))!];;];]!))))--)-)!!]];];)))--)-];]];]; ;;]))))----)))-)--)])]]])~*****&***&**&{{{{{-,{,{,& ", " ])]]])-)-)-))-))#{]!]{{{!;];=!))));=*#!];]!{,{{{]!])))---)))-){];];]))-)-)-)))])]]! @]])))))----)-))-)-)))--))]];]) ~ )];])))--)))-))))))-))-)-))));];~)!]))))--))-)-)-)-)))-)--))));];.#,.{];]))--))-)-)-!!;];;];]]))-)--!]);]{{{{{{];)))----)-))-)!{])!]])))----))-)!)];]]))--)-)-)])]!]! ~ ~]]!)))----)))-)))))-)])];];#****&&*&&**&{{{{-{-,{,{& ", " !]!);-)))))-))))*!];]{{{{!]!!#{;]!,*=;]!!{,{,.{!;)))--)))-)))))!]))))--))))-)))])];]~);!))))--)))))))-))))-)))-))])!]!-);])))--)!#=)))-)-)))-)))---){=]!];])))--)!#=)))))))-)-))))--){=];]..#];]);))))-))))-)!)]];)])))--))))!]!]!{{{!];];!-))))))-))))#;];)))--))))))))!!]))))-)))))-))))]];]~ !];)))-);)))-))-)-)))-))]]!]!,****&&&***&{{--{,{--.{& ", " ];])!-))-)))-))]#;];;{{{{{!!]=#*#*#!!];!>{.{,{;];]!)))-))))-)))=))))-)))-)))))-))];]!;]]))-)-))-))-))))-)))-)))-));];])];]))-)))#**#]))))-)))-))))]!*{]!]!]))-)))#**#]))-))))))-)))]!*{]!!.,.!];]!)-))))-))))))))))))--))-)))!!];;!{{{!];!##)))-)))-))]#!]!]!)))-))-)-)))!))))--))-)))-))));]];~];])))-!*,!))))))))-))))-))]];!#**********&{{-,{,-{.& ", " !!;!])))))))))))!#;!]!,{{{{{!;!!!{!!;]!=>>>>{{,{!;!=#!)))))))))))))--)))))))-))))){!;];!])))!;])))))))))))))))))))));];!];))-))))={!#,=))))))))))))!,#;;!];)))-)))={!#,=])))))))))))!##;!;.*#.;!]]!))))))))))))!]))---)))))))-;#;];!{{{{!;]!=!)))))))))!#;!;!=#!)))))))))))))--))))))))))-)){!;]!;]))-)]###,#;)))))))))-))))]];]!#*********&{{{{{{{{{& ", " !]!;!)-)))))))))!#!;!!,,{{{{~];!;!]!;!~{{>>#,,+*{;!!=#))))))))))-)-))))))))))))]!#*!;];]]))!**,=!;!)))))))))))))))))!!];!]])-))))!!;!=*#!;)))))))))!,!;];!]]))))))!!;;=,#!!)))))))))!*!;]!,,.#];!;!)))))))))))),*,=;))))))))))]#;!;]{~{~!;;!;!)))))))))=#]!]!!=#)))))))))))-)))))))))))))]!#*!!;!]]))-)]*=;!#,!))))))))))))))!!;!!#********&&{{{{{{{&& ", " ;!;]!)))))))))))==!]!!.{{{{~~~!;];!;!~~{~{{,,+++#!;!;!!))))))))))];!;!))))))))!;#*!!;!!]));*#=#,*,#=!)))))))))))))))){;!]]))))))))!;];!#*,=!!;!)));##;!!;]]))))))))!];!!#*,=!!)!)));##;!;#,##.!;!;!))))))))))))!!!##!))))))))!!#!;!!~{~~!!];!]))))))))!{#;!;!;!!!))))))))))];!;!))))))))!;#*{;!]!]))))!=#!;!!=*!])))))))))))!!=!;!!,*****,,,&{{{{{{{& ", " ;!!]!)))))))))))!#!;!!,{{{{{~~~!;!!!~~~~{~{{,#,#,!!;!;!)))))))));=#,#,#=;!)))]!#,!;!!;]]))=,!;!;!=#**#!!!))))))))))))!!;!!)))))))))];];!!=,*,#=!!)]#=!;!!;!)))))))));]]!!!=,**#=!!);#=!!!#~~,.;!!!{)))))))))))))=;!##!!))))));##];!!~{~~;!;!!!))))))));==!;];!!;!)))))))));{#,#*#=;!)))]!#,!!;!!]])-))]#=!!;!;=#{!))))))))!!#*#;!!,,***,#,#,&&,{,{,&& ", "~!;!;!))))))))));{=!!;{{,{{{!~~~-~-~~~~~~{~{~{~{~~!!!;!;))))))))!#*,####,*=])!;#*=!!;!!)]-;#=!!!;!;!!=#**=;!))))))))));{!;!)))))))))))]];;!;!=#**#=!*!!;!;!!)))))))))))]];;!;!=#**#=!,!;!;{~~#,!;!!=))))))))))))){!!!##!])))]!=*=!!!~{~~~!!!;!;))))))))]#=!!!!;!!;))))))))!#**####*,=])!;#*=;!!;;])))));#=;!!;!!=#=])))))!!=*,=!!!,,,,,{{{,{,,&&{,{&& ", "-!!!;!))])););))]{#!!!!{.{{{~~~~~-~--~~~!!!!!!~~~~!;!!!!));));))]#=!!;!!!=#=];=,=;!!;!];))!#=!;!!!!;!!!!=,*#!;])););)))!!!=)])]))]))))))]]];;!;!!=*##!!!!!;=;);))]));))))]]];;!;!!=*##!!!!{{~,##!;!==;!))]));)]));=;!!=#!;);!=*#!;!{{~{~~!;!!!!);))])));#=!;!!;!!!)))]);))]#=!!;!!!=#=];=,=!!!!!];))]))],!!;!!!!!=#!)])]]!**#!!;=,,,,,,,{,,,,,,&&,&& ", "-!;!!!)]))]))););!#!;!!.{{{{~~~-~-~-~~~!!;!!!!!~~~!!!;!;)));)););#=!!!!;!;]]!!*=!!!!!!];));#=!!!)!!!!;!!!!=#,=;]))));)]!#;=!)))]))])])])))]]]]];!!!!=;!!!!!=!));))]))])])))]]]]];!!!!=!;{{{{#,#*!!!=#;)]))])))])))=!!!!=!;!=,*=!!!{{{~{~~!!!;!;))]))]))!#=!!!!!!;!)])!))])!==;!!!!!;]]!!*#!;!!!!];)))])!#!!!!;!;!]]]);];#*#=!!!=,#,,,,,,{,#,#,#,&&& ", "-=!!!!));););))])=#!!!!,.{{{~~~~~--~-!;!!!!;!!=!~-!!!!!!);));)]))#=;!!!!]]))],#!!!!!!!]!));#;!!!~~~!!!=!@!!!=#*!!!])!));#!==!;);)]))]))]))))))]]]];!!!!=;!!==];)]))]!])))))))))]]]]!;!!!!#{#,,#~~!!!==!)])])]);););=;!;==!#*#=!!!{{{{~{~~!!!!!!;))])])]!#!!!;!!!!!))])])]))#=!!!$!]]))]##!!!!!!;]))])]);#;!!!!!;]])))!=**=!!;!=**,,,,,,-,.{#{{,#{ ", "~!!=!=)])]);)!);)!#!!!={{{{~~~~-----!!=!!!!!!!!!!~!=!=!!)]!]);)!]#=!=!!;]));=,=!!!!!!;!]);]==!=!!~~~~!{!!!!!!==,=;);)])]=!!=!!)])])]);););)])))))]];;!!!!=!=#!!););)])!];])]);))))]];;!!!!#,##*~~!=!==!;)]););)])]!=!=!=#*#=!!!!{{{{{{~{~!!!!!;)])])]!]!#!!!!!!!!;]););)]);#=!=!!;]));=,=!!!!!!;!)])););==!=!;]]]));!#*#=!!=!#,,***,,,,~,{,#,,,,{ ", " !!!==])])]);]);]!#=!!!,{{{{~~~~~--~=!!;]]]];;!!!!;!!!=!);])])])]#=!!!!];)]!##!!!{!!!;!;);){=!!=!~~{~~!{{!!!!!!=#=!;);]!#===#!;);)]!)];)];);]);];))]];;!!!!!=#!;);]!])])])]!)!);];))]];;!!!{*{~~~~!!!==;)];)]!]!)])!=!!!!!=!=!!{{{{{{{{~~!!!=!!)!)])])]!#!!=!!=!!!)!);])]]!#=!!=!];])!##!!={!=!;!)]!];);==!!;]])))!=*#==!!!{#**,,,*,,,~-,{,,,,,,{ ", " !==!=;];];])];);!#=!!!{,{{~~~~---!!!;;]])))];;!=!!!=!!;]!];];];!#==!=;]])!=,=!=!{!=!!!;];];=!!=!!~~{~{~!{{!!=!==#!;];)!#=!==#=!];;);])];);];])])];)])!;!!====#=!];]!]!;];);];])]!];)]]!;!=!{{~~~~!=!!=!;])];])];!);!===!!=!=!{{{{***~~!~!=!!!!];];]!])!#=!=!!!!!!];]!];])!#==!!;]])!=,==!!!!!!!;;););])!=;]]])]!=**#=!!=!{,,,*,**#,#,~~~,{,#{,{{ ", " !!!==!!);];];];];#!!=!{{{{{~~~~-~=!!;]]);];]]!=!==!=!=!););])]]!#=!=!;;];!=#!!!{{!!==!)];);!=!==!{~~~{~{~{~{!=!==#!];]!#=====#=!!!];];!]!]!];];]!]!;]]!!!!!==###!!)];];]!]!];];];];!);]!!!=={~~~~~=====!]!]!]!];]!]!=!=!!!={{{{{*****{~~!!!==!]!]!);];!#=!!=!=!=!)];])];]!#=!=!;;];;=#!=!{{!=!=!];];];;!=;]]);=#*#=!==!{{{,,,**,,,,,~~~-,{,,,,,{ ", " !====!;;!];;!]!;!=====.{{{~~~~~-=!==!;];];!];]==!=!==!!;];;]!;;!====!!];]!##==={{==!=!!]!];]!=!=!=!!{~!~~{~{~{====!;!]!===!===##=!!;;];;];;!]!;];;]!;];=!==!=!=##==!!;];;];!];!];;]]!];]=!=!=!~~~~!====!;;;];!]!];]!====={{{{{{{*{{**~~~!===!!;;;]!;];!#==!====!!;];!];!]!#===!!];]!##==={!=!=!!;];;]!];]]);!=*,#===!{{{{***,*,,,,,{~~--.,###,#. ", " !====];!]!];!];!==!=={{{{{~~~~-~===##!!;]!;!]!=======!;];!]!]!;#====!]!;!#==!=!{!===!;;;!;!]=!=!==={{{~~~~~~{!====!;;!#=======##*#=!!!;];];;];;];!];!]!========##*#=!!!;];;];;!]!;;!]!;!=====~~~~!!==#!!];!];;!;!;;==!=={{{{{{{*{{**~~~!!===!!]!;]!;;!#====!===!;!];!];;!#=!==!];;!#==!={{====!;!]!;]!;];!=#*#=====!{{{{*,,*,,,,,#~~~~~ {{,,*** ", " {===#!;;!;!;]!;;=#===={{{~~~~---!===#!!;!;];!!#======!;!;;;!;;!#===!;;!]!======{=====!]!];!;;!=======!!{~~~~~=====;!;!#==========#*,#!!!;;!;;!;;]!;!;;;===========#**#!=!;!;];!;!]!;;];!=====!~~~~=====;;!;!]!];];!=#===={{{{{{{***~~~~!====!;;];!]!]=#========!];!;]!;]!#===!!;!];======!=====;!;;!;;];!=**=====!{{{{{*,{,*,,,#,~~~~ ,.#*~~~* ", " !=====;!;]!;!;];!#====.{{{~~~-~--====#!;!;!;;=#======!]!]!];];!#====!;;!;============;!;!;]!;;;!!========{!!~=====]!;!#============#**#==!!]!]!;!;]!]!;=============##*#==!;!;];!;]!;!];=====!~~~~=====;!];!;;!;!];!#====,{{{***^^^****!====!;;!;;;!;!#========!;];!;!;;!##===!!;!;============;!]!]!;!;;;========={!{!#={#*,#,,,~~~~~ {{,*!{~* ", " ====#!;!;!;]!;;!#===={{{~~~~~---!====!;!]!]!!#======!;!;!;!;;!#=====!;;!;=!;;========;];!;!]!;;;=!===============;!!=#====;;;!=======##,#==!;!;]!;!;!]!#===;;;!!======#,*#==!!;;!;!;!;;!#====~~~-!====!;!;!]!;;;!;!#===={{**^^^^^**{{,#====!;];!]!;!!#========!;;!;]!;!!#=====;!;!;=!!!!=====#!!;;!;]!;];!!==============##,,,,~~~ ~ ,,*~~!* ", " !===#=!!;!;!;!;!====={{{{~~~-~--!====!;!;;!;=#======!!;;!;!!;!##====!;!;];!;;!=======!;];!;!;!;]!;!==============;;=##====!];];;!;!====##,*#=!;!;;!;!;=#===!];;;;!;=====##,##!!!;!;];!;!#====~~~~!====!!;!;!;];!;!!#====**^**,^^^*{{{,#====!!;;!;!;;!#========!;!;!;!;;!##====!;!;];;;;=======#!;!;!;!;!;;];!============###,,,~ ~ ~ ~ {{,*{~* ", " ====#!;!;!;!;!;=#===={{{~~~~---!=====;!;!;!##======!;!;!;;!;!#===##!!;!;!]]!#=====#=!;!;!;!;!;!;;;;!============]!=,======!;];];;;;!=====##*=!!;!;!;!=#====!];];];;!!=====##,#!;!;!;!!=#===={~~~!=====]!;;!;!;!;!=#====,**{~**^**.,,{#====!;!;!;!;!!#========!;!;!;!;!!#===##!!;!;!]]!=#=====#=!;!;!;!;!!!;;!!===========###,~~ ~ ,,,*** ", " ~===##!!;!;!;!;!#==#={{{~~~~-~-!#===!];!;!!*#======!;!]!;!;!!##===##=!;!;!!=##=====#=!;!;!;!;!;!!;;];!$!=======!;!##=====!;!!!;!!;];;!=====##=!!;!;!==#==!=;!!!!;!;];!;======#=!;!;!;==#==={{~=======!;!!;!;!;!;!=#===#*{{{~*^^^*{{.{#=====];!;!;!;!=#========];!;!;!;!##===##=!!;!;==##======#!!;!;!;!;;!;!;;;!;!;!;!$!==#=#-~ ~ ~ {#,#{{ ", " !=#=#=!!;!;!;!;!======{{!~-!~!=====;;!!;=##===#===!;!;!!;!;!##=$==###=====##=====###=!;!;!;!;!;!!;!];];;!$!=!!;!=*#=====!;!;!;!;!!;];;!======!;!;!;!##===!;!;;!;!;!;;]!!======!;!;!;!##=#={{====#===;!;!;!;!;!;=##===#{{{{~**^*^*,{*!====!;!;!;!;!!=#==#====!;!;!;!;!!#===$=###=====###=={===##!!;!;!;!!;!;!];;;;;;;;;!===#{!~ ,{,,,{ ", " !==##=!!;!!;!!;==$#=========#$===!]!;!!=*#=======!!;!;!!;!!##=====##*#,**##=={{===##!!;!!;!!;!;!!;!!!!];];;;!;=###$#===;]!;!;!;!;!;!;;!=====;!;!!!=##===;]!!!;!!;!!!;;;!=====;!;!!==##==={==#=$===!]!;!;!!;!!!!###==,,{{{~*^^^^*{,*!#=#=!;!!;!!;!;=#$==#=#=!;!;!!;!;!##=#===##,##**##=={{!===##!!;!!;!;!!;!;!!!;!]!!=###=#!~ ~ ~ {#,#{, ", " {==###!!;!;!;!;====#===#=#$====!;;!;!=###=#=#$#==;!!;!;!;!##==##===#####===!{~{===##!!;!;!;!;!;!;!;;!!!;!;];!###=====!!;!!;!!;!!;!;!;;;!=;!]!!;==*#===!;!;;!;!;!;!;!!;!;!=;!]!!;!=*#==#{#==#===!;;;!!;!;!!;!=##====,{{{{~~****-**-!=====!;!;!;!;!=#=#======!!;!;!!;!##=#=#===####===={{!~{=####!!;!;!!;!;!;!;!;!!==*##==#~~ .,#,#{ ", " !==###!!!;!;!;;!============!;;];!!=##==={=====!];!]!;!;!##===#=========={{~{~!==###=!;!]!;];!;!;!;;;!;!!==#,#=====!!;!!;!;]!;;!]!;]!;]!;;;!!=###===!!;!!!]!;];!;!;!;!;]!;];!==#*##=={====!;;;;]!];!]!;]!;!=,#===,,,{{{~******---!====!]!;];!;!;;#=======!]!;];;!;!##===#=========={{{~{!{==###=!!];!]!;!;!]!;!=#*##=={,~~~ ~ ~ ,{,,{. ", " !===##=!!;]!;!]!;!=!====;;;;]]!!!=*#==={{{====!!;;!;]!;!#===={,========{{****~{===##==!;!;;];]!]!]!;!!=##*##========##==!=!;];!;!;;;!;]!!==#**#======##===!!;;];]!];];!;!!==#*,#===,=====;];]];!;!;!;!;]!=##===#,{{{{{~******---!====!;;!;]!];!!#=======!;;!;!]!;!====={,========{{{!~~~~{===##=!!;!;;];]!;;!!#*#===#,~~~-~ {#,#,{ ", " !===###=!!;];;;;];;;;;];;]];;!=#,#==={{{=====!;];]!;!]!=#===#*{======*****>***{===##*==!!;!;!;;!;!==#**##===!{{==##***,*,==!;!];];];!==#**##======###**,*,==!;!;;!;;!;!=#**##====,{,===##=!!!]!];]!];!!!###=={,,,,{{{***~-***--====!;];]!;;!;;!#=======!]!];!];!;=#==={.{======{{{{{{{!~~!===###=!;];;!;!]!=#*====#,,~~~~-~ ~ {#,#{. ", " ~ !====#*#==!!!!];]]])]]]]!!!==**#==={{{{====!];]!;];];;!#===#*****************~!====##,#==!!];]!==,*#======!~!{!========#*,#=!!;]!!==#*##======{=========#*,#=!;];]!==**##======{,{{{===###=!!;!;];;!!#*#===#,,,{{{{~***-~***-!===!;];!;]!];];]=#=====!;];!];!];;!#===={{{{{!{{{!{~~!~~~~~!====#*#=!!];]!;=#*====#,,,~~~~-~ {{,#,{ ", " !=====#*,###==!=!=!=!==##,**#===={~~{{=====!==!======!#====************~***~~~!======#*,##=!==**#======={{~{~!!!=========#*#!!;;=**#========,,{{==========###!!;!=,*#========.{{,{{{====#*##=!=====#*#==={,,,,,{{{{**~~ ***!====!!=!===!===!=#======!=!====!==!#===={{{{{{~!{!{!{~{~~~~~!=====#*##!!!!=##====,,,,,,~~~~-~ ~ .{,{,, ", " ~ ~!=!======#,***,#,*#*****#=====!!~{{{{{!==#,*********,#=!{*************~~~~~~~~~!==!====##*##,#====!=!=!{{!{!{{!!!=!=!=====##==#*#====!==!{.{,{{!=!==!======##==#*#===!=!=!{,{,{,{{{{=!====#******,#===!.,,,,{{{{!***-~ *** !===#************#=!===#***********#===.{{{{{{~!~~~~~!~~~~~~~!!===!=##**##*#====*,,*,,,,~-~-~ ,,,,{{ ", " ~!!=!========#=####=!=!==!=!=~~~{{!{{{!==!=!!=!=!===!!=**************~~~~~-~~~~!!=!!!====##====!=!!{{{{{{~{~!{!{!!=!=!!!===##*#!=!!!={{{{{,{.{{{{!{!!!!!!===##*#=!=!!={{{{.{.{{{{{{~!=!====!=!===!!!={,,,,,,{{{{**~~ ~ ** !=!===!!!!!=!=!=!=!{=!!=!!=!==!===!=!{{{{{{~{~~!{~~~~~~~~~-~~~!!!=!====##====#*,**,*,,,~~~-~ ~ {#,#{,, ", " ~~~!=!!!!!!=!=!=!=!!==!=!==!!~~{~~{{{{{!=!=!!=!=!!!!=!!*****{{!~~******~~~~-~-~ ~~!=!!!!!=!==!=!{{{{{{{{~{{~~~~~~~~~~!{!!!!=====!=!!{{{{{{{{{{{{{{{{~{!!!!!!====!!=!={{{{{{{{{{{{{{{~!!!!!!!=!=!=!==!{{,.{.{{{{{~**~ *** !=!!!!==!=!==!!=!,{{!!=!!!=!=!=!=!=.{{{{{{~~~~~~~~~~~~~~-~~~~~!!!!!!!=!=!!!#,***,*,,#,~~~-~ ,,,,#,,{ ", " ~~~!!=!!=!=!=!=!=!!=!=!!!~~~~!~{~{~{{~{!!=!=!=!!!!!!{{***{{{{~~~*****~-~~~-~ ~~~~{!!=!=!!!!{{{{{{{{{{{~{!~{~~~~~~~~~~!=!=!=!=!{{.{.{{{{.{{{{{{~{~{~{!{!!!=!=!=!!{{.{.{{{{{{{{{{!{~~~!!=!!!!!=!=!!{{{{,{{,{{{{~**~~ ~ ** !!=!!!!!=!=!=!={{{{{!!=!=!=!!!=!={{{{{{{{{~~~~~~~~~~-~-~ ~~~!!!!!!!!!!#**,,,,,,,,~~~~~ ~ {,,,,,{,, ", " ~ ~~~~~{!{!!!!!!!!!!!!!!~~~~~{~{{~{~!~~~!!!!!!!=!!!!{{{**{{~~~~~~**~ **-~ ~ ~ ~-~~~~~{!=!=!{{{{{{{{{{{{~{~~~~~~~~~~~~~~~!!=!!!{{{{{{{{{{{{{{{~{~!~~~~~~~{!=!=!={{{{{{{{{{{{{{{~~~~~~~~~~!!=!!!!!{{{{{,{{{{{{~~*** ** !=!=!=!!!!=!!{{{{{{{=!=!!=!=!=!{{{{{{{~~~~~~~-~~-~ ~ ~ ~ ~-~~~~{!!!!!=#*,,,,,,,{~{~~~-~ ,{,{,,,#{ ", " ~~~~~~{~{{{{{{{!~{~~~~~~~~~~~~!{~~~~~~~~~~~~~~~{{{{**{{{{{~~~~**~ ***-~ ~-~~~~~~{{{{{{{{{{{{{{{{{~{~~~~~-~-~~~~~~!{!!!{{{{{{{{{{{{{{{~{~~~~~~~~~~~~{!=!{{{{{{{{{{{{{{~{~{~~~~~ ~-~~~~~~{{{{{{{{{{{{{~~~~~ ~-~~~~~{{{{{{{{{{~~~~~~~{~{{{{{{{{{~{~~~-~-~ ~ ~ ~ ~~~~~~{!{,#,,,,{{{{{~~~~~-~ ~ ,{{{{{{ ", " ~ ~ ~~~~~~~{~{!{!{!~~~~~~~~~~~!~~~~~~~~~~-~-~~~~~{~{{{***{~~~~~ *** ~*** ~ ~ ~ ~~~~!~{~{{{{{{{{{{~{~~~~~~~-~-~-~-~~~~~~{!{{{{{{{{{{{~{~~{~~~~~~~~~~~~~~~~!{{{{{{{{{{{{!{~~~~~~~~ ~ ~ ~-~~~~~{~{{{{{{{{~~~~~ ~ ~-~~~~{~{{{{{{~~!~~~~~~~{~{{{{{{~!~~~~ ~ ~ ~ ~ ~~~~~~~{{{{{{{{{{!{~~~~~-~ ", " ~~~~~~~~!~~~~!{~~~~~~~~~~~~~~~~~~~-~ ~ ~~~~~~~~{~{~~~~~~~ ~ ~~~~~~{~{{{{{~{~{~{~~~~ ~~ ~ ~ ~ ~~~~~~~~{~{{{{{{~{~{!~~~~~~~~~~~~~~~~~~~~!{!{{{{{~{~{~{~~~~~ ~ ~ ~ ~-~~~~~~{~{{{~{~{~~~~~ ~ ~-~~~~~{~{{~{~!{~~~~~~~~~~~{~{~{~~~~~~ ~ ~ ~ ~ ~ ~~~~~~~~{~{{!{!{!~~~~ ~ ~ ", " ~ ~ ~-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-~-~ ~ ~~~~~!~~~~~~~~-~ ~ ~ ~~~~~~~~{~~~{~{~~~~~~~~ ~ ~ ~ ~~~~~~~~~~!~!~~!~~~~~~~-~ ~ ~~~~~~~~~~~~~~~{~~~~~~~~~ ~ ~ ~ ~-~~~~{~~!~{~~~~~~ ~ ~ ~ ~~~~~{~~{~~~~~~~~~~~~~~~~!~~~~~~~-~ ~ ~~~~~~{~~{~{~!~~~~~~~ ~ ", " ~ ~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~ ~ ~ ~~~~~~~~~~~~~~ ~ ~ ~~~~~~~~~~~~~~~~~~-~~ ~ ~ ~ ~ ~ ~~~~~~~~~~~~~~~~~~~-~-~ ~ ~ ~-~~~~~~~~{~~~~~~~~~~-~ ~ ~ ~--~~~~~~~!~~~~~~-~ ~ ~~~~~~~~~~~~~~~~-~~~~~~~~~~~~~~~-~ ~~~~~~~~~~~~~~~~~ ~ ~ ", " ~ ~-~~~~~~~~~~~~~~~~~-~ ~ ~ ~ ~ ~~ ~~~~~~~~ ~ ~ ~ ~~~~~~~~~~~~~~ ~-~ ~ ~-~~~~~~~~~~~~~~-~-~ ~ ~ ~ ~~~~~~~~~~~~~~-~ ~ ~ ~-~ ~~~~~~~~~~-~-~ ~ ~ ~~~~~~~~~~~~ ~~-~ ~ ~~~~~~~~~-~ ~ ~ ~~~~~~~~~~~~~-~ ", " ~--~-~-~ ~ ~~~ ~-~ ~ ~ ~ ~ ~-~~~~ ~~~~ ~ ~-~~~~~~~ ~ ~ ~ ~ ~ ~ ~-~~~~~~~~~~ ~ ~ ~ ~ ~ ~~~~~~~~~ ~ ~ ~ ~~~~~~-~~ ~ ~ ~-~~~~~~ ~ ~-~ ~ ~ ~~~~-~-~ ~ ~ ~~~~~~-~-~ ~ ", " ~~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ", " ~ ~ ~ ~ ~ ~ ~ ~~ ~ ~~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~~ ~ ~ ~ ~ ~ ~ ~ ", " ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ", " ~ ~ ~ "}; crossfire-client-1.75.3/pixmaps/nonmag.xpm000644 001751 001751 00000001012 14045044275 021427 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const nonmag_xpm[] = { "20 16 5 1", " c None", ". c #FFFFFF", "+ c #7F7F7F", "@ c #404040", "# c #000000", " ", " ", " ", " ", " ", " .+ ", " .+ ", " ...........@+#.# ", " ...+.+.+.+.+.#+... ", " @@@@@@@@@@@@+#.# ", " .+ ", " .+ ", " ", " ", " ", " "}; crossfire-client-1.75.3/pixmaps/question.xpm000644 001751 001751 00000001416 14045044275 022027 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const question_xpm[] = { "24 24 3 1", " c None", ". c #FFFFFF", "+ c #000000", "........................", "........................", "........+++++...........", "......+++++++++.........", ".....+++++++++++........", "....+++.......+++.......", "...+++.........+++......", "...+++.........+++......", "...+++.........+++......", "...+++.........+++......", "...+++.........+++......", "....+++.......+++.......", "..............+++.......", "............+++.........", "...........++++.........", ".........+++++..........", ".........+++............", ".........+++............", "........................", "........................", "........................", ".........+++............", ".........+++............", ".........+++............"}; crossfire-client-1.75.3/pixmaps/16x16.png000644 001751 001751 00000001251 14045044324 020715 0ustar00kevinzkevinz000000 000000 ‰PNG  IHDR(-SqPLTEÿúúÿÿÿÂÁ§pR/-jfa;66PRTî4Âÿ<*OQQTQQY[[+¹!æ ^ÿ-¤ùB1$íííµµµ|||QQQUVV³Ú ]þ.¥ùððð®®®uvvRPP­­­uuu/¶!Þaÿ/¨ÿñôö¯°³vwzQQSUUV!ªÈ2ÚvÎH1û׽õ}€}LZW,WWMpl@¡›g˵‰ÿ×¹˜èÞ®¦99[ lmp“”–º¼¾öðì"@Ìÿ#ÿÌ'¹¼¡tuu“““ºººóëæ =Éÿ ùÇ.–™Œº¹¹2..™šš øÔOL[òòëŽŠŠº»»ÿr¯¨ ‚‚oggÒÔÔõíè@Îÿ ÿ åâÙwuu-((óëå&PyÞ…ÿÿüJÂÅ+tRNS@æØfbKGDˆH pHYs  šœtIMEÝ0[y ±IDATÓc`€&`fa`ecgf`àà„pqóðòñ3  CDDÅÄ%$¥¤edå lò ŠJ’Ê*ªj¨ê0M-m]I=}C#ˆ€±‰©™¹…¥•µ-DÀÎÞÁÑÉÙÅÕÍÝ"àéåíãëç uXHhXxDdTtL,D .>$˜”œu{jZ:P #3 æ™ìœÜ¼ü‚¢b¸÷JJËÊ+˜A%Œ / ¦WbËBIEND®B`‚crossfire-client-1.75.3/pixmaps/all.xpm000644 001751 001751 00000000770 14045044275 020732 0ustar00kevinzkevinz000000 000000 /* XPM */ static const char *const all_xpm[] = { "20 16 4 1", " c None", ". c #A0522D", "+ c #CD853F", "@ c #000000", " ", " .+ ", " .+.. ", " @+..@ ", " .@@@ ", " .+.+@+ ", " .+.+.+.. ", " .+.+.+..@. ", " +.+......@. ", " .+......@.@ ", " +.+....@.@. ", " .+....@.@.@ ", " +..@.@.@.@ ", " +@.@.@.@ ", " @.@.@ ", " "}; crossfire-client-1.75.3/pixmaps/question.111000644 001751 001751 00000001575 14045044275 021533 0ustar00kevinzkevinz000000 000000 #define question_width 32 #define question_height 32 static const char question_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x70, 0xc0, 0x01, 0x00, 0x38, 0x80, 0x03, 0x00, 0x38, 0x80, 0x03, 0x00, 0x38, 0x80, 0x03, 0x00, 0x38, 0x80, 0x03, 0x00, 0x38, 0x80, 0x03, 0x00, 0x70, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; crossfire-client-1.75.3/sounds/000755 001751 001751 00000000000 14605665664 017277 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/sounds/COPYING000644 001751 001751 00000000756 14165625676 020342 0ustar00kevinzkevinz000000 000000 Bart K. - fire-spell.wav: http://opengameart.org/content/spell-4-fire Michel Baradari (CC-BY 3.0): - painb.wav: https://opengameart.org/content/15-monster-gruntpaindeath-sounds The following sounds are from The `Battle of Wesnoth`_ (GPLv2): - claws.ogg - fist.ogg - knife.ogg - miss-1.ogg - potion.ogg - sword-1.ogg .. _Battle of Wesnoth: https://github.com/wesnoth/wesnoth/tree/master/data/ https://opengameart.org/content/footsteps-leather-cloth-armor (Public Domain) - step_lth*.ogg crossfire-client-1.75.3/sounds/Tear.wav000644 001751 001751 00000024140 14165625676 020712 0ustar00kevinzkevinz000000 000000 RIFFX(WAVEfmt +"VLISTINFOISFTLavf54.63.104data(þþþþüþþþüþüþüüþüüþüþþþ         þþþþþþþþþüþüþüüúúüúüøúøüüúúüøúøúúüøúúüøüúüúüþüþþú úþþøþþþü      ôþþþþþþþüþúüþúþúüºöþþüþþþüöþüúööìúüô øþæúèöüüþüþþè ðüðþöúú ôôâòì,Š,þøøüâøøÞ"üÆæÔ8äöÜøòêþäðöôêøâôæú 2 ü$0@Bö$0  Â6æþòÒîÚøøÚ$äÂ"èöìèìèþî¼`ð  .Ú * Þ(îöü.Ö$FÂ*ÔöØ&òìêºòâô,èÔäêìî0ìöÊîôÀÐ âì "ðòæþêèøÚúòìòöøüòþúø <þ ö ¢@ü4æüNèÌÀö$Ôà8úðèä ÆÜ>ìþ*’FD¬Ô ÚÌö´*ÔVøøúÔjÖüdìÐLìÌVöìþÚHò8¾($à N î€@(àHòî®ú <‚@¼rÜæÜ*æ@îðêþäDÔ2Îì4òâÄZäú Ô 2ì^î ü ê$Ê ê ÔüHð>òrÊèJ¼ü$ ðôÔbÐì2¼Ö6ÌèâèúÐ,ºêÀ^ÐöÔ.ÂÌ Þî°îâÔÞ ø¶Zìúòôòæ@ì 8œ$ü² BˆâD ,¸ø®,ø$øÚ2ÞþØ, Úäúî"æ0ú øÂ"üj‚2ì" *Œ.2ø0þòô¸2òÜFì2ÂÞV ìþôøäDþæèö*4ðüþú¦n î¬LîüÔ 0ðªÄDÖò("μ’ $ä ú°*€Zþ @ÆàTÌ0äøð&øL–P08òþöîúöÔvìÚüìúò¨Âæ.\¾öþÌ þÖôôúüú®~¾æàò¼vÌÚàžú& äèòH,Øèè<¸$þX¾èÆ þ ööúæê"ðøFèæRöâúò:¼öæÔôÈ@îº  ü$&4RÂ8ð ¶ô úÈ" þVÊðþ¶(ô&Æø@úøàòöšDÀô,< (ü0”DLäÜÄô<Ü(öäHÆì0ÒÚÂbâü°$ü*Àæ4 úÒøöLôðØ0Úü>Üܘ|ê\€j&ØìÐ.þ þ"(°&Röò 6® t¬è|€úÚ Bæêú€¾ÜòÞü:¢* ÐÄüô4Ä ôÌ.ú à<òôÌòÌôð¾òäúÚâ¬@ú ¦ øü È0ô.ð è,ðø¬ö.ðüšúÞ^â Î$ð‚Ú€âÆ$B¨ÜðT6¸p,€Nú8¾äâ0úü:¸þ8 ¢6b€^Z¸0$0:Øò0.žÖÐÊÂþ2B¤ð<üæÚÖ*øÀð&*ôà4ðòHÞòÞÞúòH&Žî¨øö4ä Ðô²Jú âèü€|ÜÜ$ô¸.Î(Î ‚ô²8öän„кäÞ¶ ö"ÞüV†ðòR€,Ž^Â6Dâö"˜î $Ĩ€ *°ü*€ìÔ Ä€€H„j,ÀDúøæ>º> @úà*ü²xb€Fæª<îþàXÒÊtè´äô Æð´Ìö¸ì2ÄðVìÒôÖNöîúú$"à( øVÆ–€œøÜ,P(°6(.òÚø082ºš²¤îîT€Þæ€ü0œÞdØüÞ.ÜôâØDŽþèÀ`êÔÂòêò,Îäd¸þ$Îæ@"2€<üÖFÔ΀€*2 x ÐÔfò¶x¦ìÞøVîê$þ º"*Àôž@ >Â$òLˆúT¸üžä ¸"ööžÚôø î2ÈRº*<”æöv€X®.<Ø€–Ö^¤þÎ,ôÀþö^ÊþÔöäf€ò îôö:°êpâÖàxº¶^üØ&Æ&ü&6úô*þèàŠê,ð &€ôðüÖ, äJþ ÐLÄ2ªò àêâ >ôêð$8ð&€r:Òª2Bž0âÊ(®6ö踾TÞF²:€Ò¾  äÞú.®îF”à\¦üÆ((®âüîäìšpÀêè>ÜÐþöàÞæðÞÈì* –L4Î8ìþ¶êä<Ôôðòüæîð>à4"äÊDü¾\* ÆîôúšôôèT ÞüÖ(ôüöœDf¬Öú6 <¾òF&€H˜dðæº^ þØò"ÖØF þöd2€@,V– ,°T ØöúȺ¼¸ô ü@àêþî.üÈ@àªü&êÌôÚÀØðø¸â4Üìì(€*ü ¾êìôüØêðòüúÎî.(òþÞøâhÒøô$&Öø@œè 0þ\€ôôböøþôª zÌðô&î€rÞ àZþà<¶ðÀR ,,üÖìöìZîÜô XäÜòÖ"àà°ôô,îø6œ&¦*ôÀâèèìþ¼2ÖØö*€(²Jòä0âòúÐöèÈÊ æ8ôô:Þôðê. 8ºà*ÞÔ.úh"Rà, >ZÂ*(\ü` jŒrú Øî 2°0TºèêÖ(\Þàòø ÌHØšJêÀjðà´òüæØxÞÞ8Ì&¨:*€þ¼þDææø¶BòÈN®* º4Þà(ìîüôØôVÎ4 $ðòhŠþÖH¤ôòêôØÎð.ø®ö®,üÂ6êêòüîøÎììÂlþêþ î  :°\(îVìÚ6 XžÄBÚþèø ÖÞ ,檲ò6öÊüøž$ø¢ þìø¶üîÜ8ÖÎ(&¸tâæJøèPÜ8¬6(¼ . üà.~À€\BÎ*¨&òìBúÞ&˜ææô>üœ<âìÌüþôÜÜöìøäöæþæâþòÄ2üÐ ö*èúðöþøúÌìîê8 ðþÈDÚ 2æþô(øö&Üðððòðüüôô"Üìðô øäòòøèìôðøüúâôôòð  "þêþþþöÆ$þèôæî@ÞúÚ&èî ø îÖ ØJòä Ðìø ì DÂ*¢fòüü Ì æäFâ0B XÆð Ælúú¼62Æâ"ÌþÊ2îúâþÔÖ êLÐòöÈ(à(ôî4¶ ¼Z"ôøŽZðîÐL,¾ úðúøòÐòäêîôè Ü0*ÖþòÞ""ÆøìØ(Ðþæàôêô&Þüöòþê(øøþÆ(ä Ò$Ì šÄöÖLä$ÐBððüÎ2 èô ÒþÆPööBøôäò6°6ììü2Æüðð°ü0îö(ØøúØøè"Š"Ð& ð8þì (Ö(Þ ö$ô"&â*ð0ú êVüÜ$0àþäêFâ êüúêî"æ ø&àöÖ æôøèäîðþâîüäô"Üúæò ðøøæâ*Òð&þòúööäðò.òöÚ4¤ øV°ôÜü ìæÞøÒî2¾ôúæðöøôîð0ôì&îþ øþ (Úöþ Þ(ô$èôúòôêTâè êþì0Òêðøìâ4Ä:ðúðüþâîê:àüøþüöèêúì*è Ò24´,Ôú0ðþô( à6ü 2ä8ì6Â" " ìÔdô àFä’ð äøø Ö&ôèüð ê"¸Þ2 ôòì žøêúü$È4–ô2ÜôR´øÞ<ðÊþ øööðÒòþþîü¾*ðôþäðÒô$€,îÚD˜ààÜÚ(Úú,Æðêð òêî ’Zþ â* (ôìH6À:4€LüäúþÎlÚÔJêö ®°îøÊÄ2Úîþæê"Æ*âôôôúüüâ4ø:,&8J2Tòöúðâö^€0 ü@îöŠ @ä"ú¨òþ ¶DÔî "º:Î(úü¤ ØúðôØZªöâøööîòÆÂþöà$öúê º4þ äúÜúêFêúð2úèÒxîÔ~$Øì ÜÊ<<öæªÀüÜŠÔô\èøþ ¼L.Ìúæ(þô.îæZ²Ò6æèþ Ò ä ’î¶L®²ˆPàø¢Úð Ѐ¾þ¨ÀÜ"ìÞô ²ÜøþôÄBü ºHòòÜB¼ü(îðòX¸ú$â ê&î 0" ò$ì8øð8äNÖô$ôúìð(úøì ¾ÒüöØöæ üüì¼2úþúú æô òððøúâ@öè"þ ð â&öîþÜ æ ìüüôôòôúúôüîîüàúöÊþð ðööúüÜðèþöòôäø"îøöÎ .æòþúØ2À ú *¬ úþüúøööþúæ Öþòüôàîþ.ì Ô* ú*ä" ô ò ú úü (ì  ìþüôþüúüúüü öþòþøþöþøþøþòúþþøê   úüþüþôôøøê îöêøþîüøìòööìþþþúüøòüøüþôüúüøþþúúþúø  üþþüþþüþþúþøþþúüþøü         úúüþø crossfire-client-1.75.3/sounds/boink2.wav000644 001751 001751 00000007530 14165625676 021207 0ustar00kevinzkevinz000000 000000 RIFFPWAVEfmt +"Vdata,þÿþÿÿÿþÿüÿþÿþÿýÿüÿþÿÿÿþÿýÿÿÿÿÿþùüþùúúüúüúÿùüþùúÿùþùúúùüûûúÿùüúúÿùüþùúÿûúÿûüÿùúÿ÷úÿùüøÿùøúÿûúýùøÿùÿ÷üý÷úÿùúúýùüü÷úûùúÿûúüúýûüüùúüùúÿùþùüüùúþùüÿùúúÿûúúþûúûùúýûúÿùúýùúÿùÿûúþùúüúýùüýùúÿùüúúüüÿùüúüüúüúúüüúúÿûúüùüüûþúþûüþùüÿûüþûüüÿûþüÿûúÿýüÿûúüþûúüûúüûúüûüüùüúùüýùúüúÿùüþùüúÿùüþùüÿùúÿûúüÿùüýûüÿýüüÿùúþûúþûúþûüÿùüüÿýúüüúüÿûúÿùúþûüúÿûüúÿûúýùüþùúúÿûúúÿùøþùøýùøý÷úÿ÷þùøüûüþùúÿ÷úþ÷üþùøúÿ÷üþùüÿùúüúÿùüþùúýùúþùúúüÿùúÿûüÿùúþûúþùúÿûúúþûúþûüúüþùúüûúÿûÿûúÿýÿùüþûøþÿüÿðîýéèýåôðÿ- úàòÿßòþíîøþÿÿÿüûöýÝìÿåÿëòþçþÿÿÿþÿ÷ôâþéìÿçöæÿ ÿ øîèäðþáôýïÿ,ÿÿÛòþ׿üËöý  ÿ7ÿ)&þÏäþÝÆìÿÓêþç&$8èÿÅâþÍìþ×ö þ8ý)&ýæÿ߯âÐþçàÿÿ&þ-$üûÙÞþÉÞÖþãòýý!(ÿ ôýÝâÊÿåØÿËöÿM6þCýÑÐÿ»ØÀþßþ"080غÌÂê¾ú*<24òܸÜýÇæûÉüý"ÿ?þþíÞüÅÖýËÞþÕÿ$8þ)"ý ìÿãÊÿÑÔÿÕöþ.ÿÿEþ¸ÊÿÁÀÿë ÿ=@þÖÿÛÄÌÞÒÿûÿ$ÿ1*,üôþÙÖÎþÓäÿï *ÿ' üôÿëÚÜþÓàþñøýþ þæþåÜþÛÜûéöýþÿþåæþãÖîÐôúÿ52þ+>þëäÌÎÈÈÔÿþ/*ÿ3ØÔÆÿÍÆÿÏöÿ-.,ÿ1ÿóÔýÉÐüÉÔàÿþ%8ÿ)ÿéØÐÿÏÌÿÝðÿ**þÿõÿãÚýËØýÙêÿÿ&ÿ(ÿÿøÿ»Æÿɾþÿ*þ'@üøûåØÿÁÒÒÜþùý'40ý)ýïØþÓÈÔÿÝöý"ü1,ý!ðþåÒÿÕÎÞþïþ&ÿ'"þÿâÿÝÔÖÚýïû &ý"ÿ÷ÜýçÚýÛðÿÓ2þ9(ý+ÞÿåÈÔÿ»Üîþ'ÿ32*ÿ îÐÿÕÂÿÓÆøþ $û)0ÿ'þòþáÊÔÿÃØà$.ÿ%ÿãÚþËÐÒüåøü"þ#ÿÿðþÛÖüÑÖþßÿ÷ýÿþåæüžýÓÆþþ/(:þäþÕÖÂÿÍÎÿí0ÿ%0,þðý×ÌþÏÆÖÿéÿ/.þ'ÿõæÔÿÍÎÔìÿ(þ)&þþäÿÝÔÿ×Úÿíÿ"ÿ#ýôýíâþÓæÿßòÿèýý+4"ÿñÞý×ÔÿÇÆðÿ%(ÿ/2.ÿûðÿÃâÿÁÒÿÏ2þ%0üüßÞüÉÚúÇèûûÿ0*ÿ)ÿÿîþÕØýÇÖþÛþþ'2ý+èØÎÊÔêúÿþ#(þäàîÒèÂâð(*(*ðÿçÆýÓÂþÏðý0ý+ÿ ìÞÿÍÌþÏÚý÷þ*&ÿîØÿÕÐþÛèþôêÿÙØÚüÿõÿý ýçæâÿÕðÿéÿüÿ#Îÿ÷ý%>þûüÔþÙÎÊÿÉÿÿ3:þ#þÝäþÅÔþËÚþûþ+82ÿ%úþçÌÚÿÁØþãÿ-0þ)öÿáÖÌÐÿ×ô ÿ,þ' ýñÜüÛÐýÛäþþ(ýÿÿäÿÝèÿÑøÿÛèÿ ý þêÜý×Ðþåøÿ þ ôÿïÚýÙØýáöÿÿÿþýìÿáàþÛäöÿ ý ÿýôèàýåæýï ÿ ÿ úüÿçìÿçèýýöü ÿýÿùæþó°ÿÿÿ6ÿ7ýýÖû×Îü·ôÿ/6ÿ/ öÿÛØÿ½ÐÔýóþ+4ÿ-ÿñæþÉÐþÃÞü*.(þ úÿÝÔÒÿÓèÿ$$þ ýïæþÛÐþáæÿýÿþÿÿøàÚäÖþÿý4ÿõøÿÓâýëôþ ÿæýóÞüãîþï ÿþÿòýçâþçðöþ ÿ÷ÿëîÿãìÿùü ÿ  ýÿþÿõîðÿïöü þþÿòúþïîþûöþþ úþóþÕôÎþû(þ!FþõðþÑÔþ¹Òø0,8ÿ/òæÄÐÿ¿Øÿ ÿ/6ÿ#ÿéÎÔý¿Úþí*4ÿ'þïÖÖÿÅØþñ"ÿ- ÿóàþ×Ðàÿí þ$þôÿÝàýÓÞýùÿþ  ÿéðêÆÿÙÒÿÿ)0ýüßÊýÉÌäÿ"þ3&þðÚÿÑÒþ×",ÿêþÝÐþÝîÿÿ!ÿøäþÙàþéøþÿøðÿãàÿçòÿ ýþíøâæÿçÿÿæý¾üI,þûÒþÛÐÿ« ÿ 4FÿýÓÎþÑ´ÿ-DýþÙÒþÃÎæÿ"2ÿ%üþíÖÈÿ׿þ*þ&ÿëÞýÏÖûïüüþ ýçÞÿÛþÕìü ÿ ÿ×èìÿçÿþÑòÿÕô* ÿóöþÍæðø" èîâäþÿûÿ ÿçêÿíìüÿÿ öòþåîýóø þÿÿÿïôÿïòþÿÿýÿùôûóöúýúüúýðûñþüÇþÝ@<ÿÐþÇà¨ÿ9(Xÿ×ðý× þùä4ýCþ%ÎÿÍÞÿ§þ(þGêÿõØþ­ìþáÿA ý%æþÏèÀüû 8û÷úûíÊþ÷ð ÿ)ÿìþßðÿÙÿôþìæÿ æÄÿ &üðþÇòÔÿ $ØêÿßÎÿüýìûÿÖþçüîÿ#ÿÝøþëöþ üÿ üòýûèýÿÿý ÿùüÿùîÿýøÿøýÿöþñÿóúÿðÿúÿçÊþûûTüÇöÿŦÿ ìHþ3ý¬þ×ÄþóRýÿNØþ¿øÿ—6"üDûÃøþÇÆ2ÿ÷Hÿæþ¹ÿÿ 0ÿíÿäüÙþë ÿûâÿõòþ÷ þûöðøòÿýþþÿúöÿùðþêúÿÉê ÿ>âÿïêºÿö*ÿ'êý ¾üïþþù<ìþèÖÿ ò$þÿúþýÚþõþ ôþÿêøüÿøÿÿööþýøýÿøÿûøþóü÷úÿýÿþÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿcrossfire-client-1.75.3/sounds/painb.wav000644 001751 001751 00000211016 14165625676 021110 0ustar00kevinzkevinz000000 000000 RIFFWAVEfmt D¬ˆXdataâtTüÿÈÿÆÿÐÿÎÿÎÿÜÿ,@4úÿðÿþÿüÿüÿúÿðÿòÿêÿþÿäÿÚÿÜÿðÿüÿòÿüÿúÿüÿôÿôÿìÿòÿüÿ úÿþÿøÿøÿòÿðÿòÿüÿ$ìÿàÿìÿìÿúÿúÿúÿúÿþÿ úÿðÿêÿòÿøÿöÿöÿöÿüÿüÿúÿþÿ øÿìÿæÿÚÿàÿôÿúÿúÿüÿ îÿÞÿÞÿäÿôÿúÿ  üÿøÿîÿêÿüÿ öÿìÿäÿæÿæÿòÿúÿüÿòÿìÿîÿòÿúÿþÿöÿüÿöÿüÿêÿèÿèÿôÿþÿúÿüÿüÿþÿðÿäÿèÿøÿüÿôÿöÿþÿüÿúÿòÿìÿðÿîÿòÿìÿðÿðÿêÿèÿìÿúÿ(0&  úÿòÿêÿüÿúÿæÿÚÿÐÿÐÿÔÿâÿ$ôÿèÿòÿ&."2&êÿâÿ4üÿ²ÿ¢ÿ ^:´ÿXÿ„ÿüÿL<æÿèÿÚÿäÿ4@.ðÿúÿ$ Ðÿ¬ÿ²ÿêÿ&H>ÎÿÆÿÒÿîÿ "*êÿÚÿHN(ðÿÜÿêÿúÿòÿîÿæÿðÿþÿÖÿÂÿÄÿÂÿÒÿÔÿîÿ$2@F8ìÿâÿôÿ*28(âÿ¸ÿ ÿžÿÀÿøÿ(:, ôÿàÿÐÿ¾ÿÒÿ8ff@Òÿ¸ÿ´ÿÎÿâÿæÿèÿðÿ üÿàÿÐÿÔÿòÿ"*& ôÿàÿÖÿÎÿÜÿôÿ"òÿÚÿÈÿÀÿ¾ÿ¾ÿÐÿèÿþÿ84B>4 ÚÿÈÿäÿFZ^\@âÿ<ÿvþþ€þ¨ÿôÆðšÒ¦ÿœþ.þšþºÿ0|><ÿÎþêþ0ÿ€ÿøÿ¦Ú¶ÿ’ýêûZüþÔ6Úÿ:þ”ýÞýˆþÿ¶ÿ΢Ž˜~"f"l˜‚"¼ÿÜÿ˜N4ÿØþLÂx6ü0øª÷Ðú.ÿÆ&DV úÔˆZäβºHì¨jÞü‚û¼üðþBަ˜Zèê,æ˜ÿØÿ¦d‚þtü6üNþÂDjÿüvúRùÎøpù ü„ÿH"ÀýüDûàúÎú4û°û°ûNû$ûÌûÒü&ýÄüÂüŒý þvýnüªü6þ’ÿrÿæýtûØøðö®õ~ôó ò®ñ òFó¢ôõ‚ô˜ô˜ö¶ùVüHþ|<š,ÀÊöX`8bÿxý˜ûúfù°ùZúâú`û¦üÔþÖÀ<ŠÐ8 ê T¢öfúŽ„ÿÿÖþŠþvþ<ÿªxD¾þNì¢ö\H vИfÿ,ÿœÿ‚˜¤bÒ Ò¶   € & PbT€œÿ–ý´û¶úû|ü~þ( „XDpòp^Pž0’Bÿ0þ ý”ûú6ù4ùÈù–úzû’üØý ÿüV¾ü ê¦:Â*žÿôþ6þ¢ýTýPýxý¬ýâý*þ~þúþžÿNâJŒ´ªJÄX\ޏ’šÿ,ÿÖþžþ’þ¸þüþZÿœÿÐÿúÿ2Šâ.ZxŠx0Ô‚p ÎêÔ®š¤ºÌâìüöèÖÆØè "$ ìÒ¬€PÞÿ°ÿ†ÿ`ÿLÿ@ÿ<ÿ6ÿÿôþØþÚþÿ\ÿÐÿB~TÜÿ^ÿÿþþÿöþÄþfþþ¬ý†ýœýÜýþ*þúý ýZýfý²ý þ6þ8þ"þþ þ*þþèýˆýý²ürüjüüÜü@ý‚ý ýžýÈý2þ¾þDÿ–ÿÀÿÎÿÎÿÈÿÒÿæÿèÿ–ÿ6ÿüþðþÿ>ÿLÿ&ÿÌþ€þvþàþpÿîÿT°æÊbÒÿHÿÿÿˆÿ$–è6„ŒTÐÿ `¶ÆŠH&˜ðÒl4œt ¤lt >¢Zò8>|öL‚|L†ææj²ðFdäª(tšX"H–ØJj.vÌ`Là0ÿ¢þäÿ¼lj<ÿ¬ü6ûRüÿ0Ô`ÿTýÎüæü’üÊû:û^ûüüÖùúõ‚òÂñ ôÆ÷†ùú÷èôÂóØõ²ùZü8ü^ú”ùûXýþ<ýâüÔýÞþDþ\ûf÷®ô2ôÜô¦ôròÞîžë¸êÔëˆìTëTébèÞèê ë(íxî2ð¼òpõ÷÷Vö¦õ²õ ÷rùxúÄø~õøòøñìñ8ò¾òóó@óôŽõ÷úhüXþv²°H Ê  ¸ F ¾ ŽäÒVf|ÿÈýÄýÿ\,ÿÈþÆÿºÎFrF – r dzú~ š âZð< T ~ |  4,ºŠ~H" 4Z€´  ä rÄH F  ’ z v (’ "Ú`˜  ôžÿ˜ûø†öpõ6õxõö´ö¬÷$ùûý(ÿ0*ÚÖ:&°¦,`ÿbü¤ùh÷ÔõÞô4õ²öPøàøøzøXù(ûýÚýæýþâþ~ÿÿvý>û2ùÚ÷Òöšõôóóžóôó¤óóÈò|óÞôúõ0öŽõÈôŠôèôJõðôâóìò¦òó¨óôHôêô¤ö0ùœûDý8þpÿj®ˆpžžÆò¶êØÒæ~V’ÄŠ˜übŠRú® 4 P ö ’ 4 ®t†‚ü(ž€dœ\vÊRŒÀÔ ” î ö î  â „ Ö  HdHBšà ¸ ä ’ è ¦ J n x . Ä r R H x>Dšý¢û€ú~úìûzþ²è"Î0ÿxýöûPûªûrü¤ü¨û|ù¨ö°óñHï&îHíÜìÄíjðàóžöø÷.øò÷Ò÷øìø|úDü„ý¸ýýÔûšú†ùÄøô÷Ðöšõþô>õöõäö&øÌùûFû˜úèùâù\úÖúüúûBû&û†úVùº÷\öö²ö~÷Î÷øùÄúÎûüü¦üòý~ÿ°”ÔÿÿÊþäþˆÿ˜zø nL–ÿØ2žXì‚Ê2ÆÀ2êvT ìX:6,Dr(tt<R®ìPV þêý2þÜþhÿ–ÿÂÿúÿ*pÒÌÚÌŽzÄìŽ † èì´LôˆBP´ÿTÿ8ÿ6ÿÿÔþŽþRþþHþÿèÿ¬"<ôZŠÿºþèý2ý¬üRü ü°û&û®útú¤úû€ûÎû ü>ü ü ýdý ý²ý¸ýÈýÎý¾ý´ýÎýÞýîýÖý|ý*ýý|ýêýúýÎý„ýnýˆý²ýÞýæýØýâýþBþ–þÿ„ÿ¾XF¦¾¶¬Ò4rž´®ÖDêÐâ¼ T ¬ Ì  j Ì â š Ü Ì € ζ´‚hÿþýýžýÆý0þ¼þRÿÚÿBÞ¢ˆd€`º ˆ˜6Ø:rÂÿbÿdÿªÿìÿöÿâÿàÿŠ@Ê0JøTÿÔýÖütü&üLûìùzø(÷öZõ¶ô6ôòóÔóÌó ó:ó¸ò,òÂñŠñ‚ñ\ñ8ñJñfñdñhñ°ñ°ò‚ô¾öúøÌúäûÜüþrÿÔ<BV°Ä˜Bÿàýnýþœþþý„üLûþúàû¶ý°ÿpðÆ&"¸8œœò<ÿôýRý2ýìü(üÀûüÈü¼ýÒþÚÿʺ¾Ö¸ T & ä 2 â ì š Ê  L 4 Ð \ ô À Ä&^”rÔÚ ¢ø ¨ > ¶¼ >þ@ýXýtýý’ü~üÊü2ý”ý¦ý,ý`ü¶ûXûûÂúZúŠù,ø¾ö°õ^ô,òÀïºîÜïÌñ~òüñÀñÄòºôÀöøløx÷äõÔôõªõ<õ–óÆñvðþîÊì„êúé ì¨ï(òÜñ>ïHìþêøëÔîÂòDö˜÷>öHó’ð2ïÈî¢îhîîjíäìÀì¸í&ð„óžö´ø²ù úŒúü ÿœ´²îjF˜LHÿæÿ,Ò’ PxV°øì ü ¶rî:Ô‚ J\. \ðVýàù ÷ð÷rù´ùVøîö”ö€÷þùýÞþbÿP  ¾F° Ô$&%â$ö& *‚,r-Ö+"(:$r!<núZÔÜv º T¶`ŒÐ´"ä,r*Žî¼€‚ ÄÖÿœù"õ¢ñjîòëNêéè ètéÎëï’óPù ÿh¢ Ô " tÌTÖöîÄ¢J @ JâJÿFýLûŒù(ø<÷ ÷`÷’÷L÷röxõÄôžôTõöö‚øÔøÆ÷$öÚô"ôó<ñïôí"î¾îÈî6îÊí¤ípívìdëlëí>ïØð’ñòñÆòÜó:õ(÷¨ù@üPþÿf´Ú¸Ì v L æÊœLž <  bªÐ¢Xÿ üù`÷(÷N÷v÷"øˆùŒûâý<Ž´zž&J‚Øv.¶8Št,þ0üþúÔú¼û<ýÿêHü V Ø’ìÚp:ôNn ð ˆè â‚Úvÿèþüþ,ÿ(ÿøþ°þPþ°ýÀüúû2ûúÂø´÷l÷v÷¸÷^øBù(úlúÜùTùœùfúûnû.ûìù:øüö öFöhõVôzó(ó¨ó¶ô*öøàù4ûÞû:ü&üü|üýÿ˜ì^*tDþ.üjúZù.ùÂùúPùø ÷®öôõ õªôÄô@õºõÔöPø<ùúPûöü¾ýúüØû€ûÌüôþÄÌT424–rZPŒ~R‚ÐL öVÎB°ºô ¸úš0ªì ¼ °øÿþTý,ütû2ûÈúzúÜúÖû²üýÄýÞþÖÿðÿtÿ˜ÿrŒøâŽ*VÿÄý~üèûÖûüRüLüºûäú0úæù>ú@û,ü¨üâü"ýNý€ýþÿ.ô†þòüääfVÿ¬þþxýüüˆüðû`ûJûüfýdþ&ÿ, zœ‚ ¨RÈRPÿPÿ€þ`ü(úºøˆøtùPú¾úôú¶ûhýJÿæÈzBx L  R Ä HœlØÚTì |  l v – @ Ž ¨ ¼ – º ö 4 À J \ Š ( v   F ¢ & n ’  † ðþ&°þÊþÿ`þý˜ýŒý–üœú øZ÷6÷Š÷@øžùðû þðþþVþ´ÿö¶ ² L l À è ô È pâp><–,þXûjù¤ø*øø÷høtù^úžúú@ùäøxùbûÀüHüŽúÔøø4øø¢öDô ò¢ðÜï¤ïäïŽð”ñ‚ò¼ò òñ"ñÄòhõXøû¸ü<ý^ýˆþJPÒ„ n ðÔ>ð N‚.Â Ä ¨ºxÿ„ûùê÷H÷ ÷üöZ÷‚÷Bø\ú$ýú€ V 4 Ô r $ š ªÎèþÖú`ø÷ú÷ùäùûzý\Ž Â¤Èx²ÞLÆv”â²À F zp€¦ú ÿ´ÿššJˆäfîý ürúùn÷@õ¾òZð$î¸ì¶ìZí¬í\ííÈìüì„î,ñxòòñ°ð’ïžîäíbîØî4îÚì<ëféDèpè,êíxðúóLö´÷>ùLû|ýÈÿ.ÿ†üûˆúhúdúú ø°õðñÔî"í¶í ñxõ˜ø¸ùZúØúÈû<þFÜvÄ&L|Ôºô‚ZBî ` 4ìò€¤úœ‚b¤†ØÞŒd&púú¨¢¢n¼øÀà~.®*~¶œ* Ä &BÚ F:”–†L~\n®òžÐ L : &  ´6þþÔ^`Â`ÿøÎ¾ Öf ò "ÿâþèþšý^úöBòÈðàñÜóÎó°ð*ìLêºììðró¶óúóžõTöô ïìëêÈêÔêpê~ê ë ë†ëBë°ëBívïöñ¶õûj6> €4"òDȸ6°$ºøD &öÿNúäóÌíˆêêôêFédæåæØè€ëí¦íÌîÀð²óøödùúÊùìù úÀúúùŽ÷röÐõÖô®óÌò^òfòòòó(òöñ2ô´÷^û’ÿf` (”Œ¦¼ ¼n@@š^° J ÿ”ûˆ÷æòˆïdîNí êàå¨ãÊä>çšéˆëŠíðšój÷ÒúBýêþx ¢R¨PÌâ\0ÿœý¶û úzù¸ùœúû®ûÚüúýàÿx2NŠ þ ž Ò   ú þ î ô„´h4TþÂûŒøÜõbôˆô,õ õ–óÎòró&ôõèõDöèöøžùrú¦úÞûpý4þ@ýšü ý þÂþ¨þ0þäþž„j®ä6FÖêºÂ2`à²ê¤ÚÈÿ*ÿøþRÿšÿ\ÿ²þ,þ¢ý²ý&þÐýÄü°ûŽû ü0üü üþû.ûRúlùùÊùâúªûŒüýæüÐü>ý¢þjLÿ|þ"ÿÎF>´ ÿ8þ@þ„þÿXÿôþ\þRþFþFþ¬þÿÖÿôÿŠÿ.ÿnþXýàüòüöüØû:ùÖöàõÄö¸ø:ú€úæù"ù&ùú¶û’ýÀþzÿzÿ¸ÿ\6&Â,"PT‚B„ ö*Üz®j €’œ¸t° ê Þ . Ô L è < ¬ X2r ê |† ð Ì ê z è ¸ ê Ð Ø ö f ö º   P">D 2 ª¶V²  T r X \ €–@Â6¸„tø r  : È ü ü  f | X ¼ à L $ R  > Ô  ú lüvTÊZºt†^`@Ôæt"Ät\þhýðýpÿÞÿ|ý¤úŒøPö~özùPý¬ÿâÿ`ýfúªùÎú$üRýàþxðÿ¾û4ö²ñÆï,ðÚðjð†î¬ìÀëžìîŽîï®ïðBòºô ÷Â÷ÊöþõöZ÷êõNóèñÞñ\ò’òŠòìòZôX÷Æû‚x ® Z J!4$b%š%%Z#H!̪¨Øl J ª:¢ <øÿÊÚŽìLbØV´ Ä P"\BÌb¾,®øÌ|ÖÒÚ , Ö à¬üæ¢ÈܶÖÒÚ.B®º,z~~ j hæfýTú~ö¸ñÊì„è$åªâhá~àÌß(ßLÞÞüÞHâÈæ(êìªì$ì¸ì(ï"ñ.ò8ò2ñŽï¬í˜ìì„ë ë”ìÐíŽîôîXï>ïüîðÌñ¸ò óTò¨ñ¼ò ôôóîòüñÔñêñâñ^òóTóàñôïšîîäîÜï´ïÀîíLë2éPç’æ\æÐä¢áß®Þøßâ2ädæ¤é€í<ñ:ö&ü¾ôÞ Î Â¤vê||Žê ò ø º ü ‚ ÚÆ æŒÚ¾–È ¨€ 6 ò^ÖªÿXýLüÆüý\þŠþ¢ýÎüpüÂüþÒÿÒZÄþþÌþꦤ`¦ÒLÈ* †Žâ ’ ~ è î º6ž4 Œtø4ê Êÿ$ý^ûÚú¦û^ýÚþ¸þjüÒøþõõöNø–ù>ø2ôFï¨ì(í$ï(ñ¤ñ4ðRîþí¦ïPòÈôúöèùœüFþ`ÿ’€V6 `âúN>òÌþÿ²þþxÿú’ÿÌýÚü8ý|þX–PRÿzý¦ûxú,ú¶ùø”ööõ¦öšøú¨ùø ö€ôõh÷>úvü¾üèú|úülþ¤ÌغNŒˆÔŒšèv¸`: úÿ’ûlùôø4ùÌø`÷÷Þø®ùàø¼÷€öªõõpôô|ôÔö,û¶ÿ$¤Ôÿ¤ýðúHø÷èöø<ú>üþ0ÿ(ÿöýý*üJûèûNþdx&D¶ÿöþ êþPæþÆû$ù¼÷‚øPúþúªúTùÎ÷Šö@ö¬ö^÷ø÷¢õäóˆóbõŽ÷äø*øÎö‚÷ŒùÚûPþºþúý|þÿ˜þ"ÿ²ø0 2 @ ü ˆ t ZŽ4ü ~îJ4æŽ n < 6²Ø¶®vý$úÜ÷ö"õtõ¨õFõDõ~õøõV÷døúýöÿBVð@®.’F°À6tvŒ €  ®äÚl²\ š ô ÚÄ^L f ¦’’6ÿ2ýZü˜ûrûPûøúÎûŠýÄÿZ’ìþÿœÿ4ÿÿžÿtà¾Ì~˜ÿ þDûô÷nõBôôÒôhö:øHùúøÊ÷üöJ÷øø ÷ö öÖö¾÷Úø>úÆûìüÊüÖúLøÚõôóhñÌîLì\ëˆëðëžì.ì¤éçDænæç¶èäêžì¬î†ñ2õ¢ù¬ýJ6¢tˆ\<Š$ÀüÿDýRûúÈùöù‚ù2øèöÔö.ø*ú^ü@ÿÆ`¾°(œÌ   ² ‚ `  Øè’¢Ð®<öpâÎ"ðüŽè*ò:f<œàŽ:âbrdÔPʰ . Ðþþü¦ýÿ¦ÿPÿ0ÿºÿv8  ` V < ¼  Z¦À d ¦ ž ^ æ X ~ ú dªè¢æd†°Ôþ²ûˆøröNõæóðòîñ ð6îôë4énæä8âbá0áÊáäâÄãäLã¢â4ãä(ä(äÚãÊãHåBèðêFí²ïóœöù¢úBüÀþFôÌö2 Ì n Æòà œ |Hú ¬ ¤ ” t”*¦zþüüfüèûú4÷ÄôLó2óÐó’òhïí¶íñÜô|÷†ùšûVýZþVþpþÿ|0|à ôÆælİîÆ* ¶ ¾pàR – Ð ú Ö t ú€^xdþDý.üdù¢ôæî,êÒæ¬ääöärå|äã â¢áèá.ãªäåÊälåæçbë´íîNíRì¤ìäílï@ñžóTö~øPùdønöäõLù€¾Ž L  F  àôŒ\ bˆ 6 ¦Òìý¸ù¬÷8÷f÷ˆø<ú$ú~÷<óFï`íŠíjî0ïðòñvô@ôÚðÔìüéè¦æ°æé’ìîí¤íî„îvïšñxó(ôTôöœûÜþ X ¬ ^ >œÒ¨Â!*¶3ê:ž>²?AbE¢K’PQÒLŠGÀCÈ?h9d0 &êˆ ¢ý|íæÞ`ÓÌÊTÅ`ÁZ¼B¶*±6®Â­°È´ªºÄ½î¿VÆ’ÐîÛþã~æ æÚçë¢í>îžïÆñõÖø`ù:ö¢òºð¸ð6ò*ñ¨íì¢í®ð²ò&ô€õ¬ô‚ó*óÆòêô¨÷4ùâúNü¢ûùÐõTòXïpìêzçÀâ¨Üˆ×xԘѲÍhÉâÅàÃòÂ<ÂpÁ¤ÁdüÅÉ ÎˆÓ\Ùˆà”èèïb÷¼ÿ0î êTÐ &„*D.61ô1d1¬0ú.Ü,†,,¢*¦'4$ô ªZbð8l æ– ¤ | Z üBÜè4ꆞ, ²Ò2àdšD¨öB &Ä4nZ ü Üè|zîº š$‚'(¾'4'&B$ÔHÈô¬Ê n`þTùröªõRò<í$è®ähäå8åÌå æ èàë@îêï ñÔñ”ó.õìôÞôÄõ^÷DùÄú„ûpûpûŒûxûüzýZþÐþvzÄXLHÚ¤è r * ¦ \ØØ°rVfÿDþèüTûÌùøÔöüõÜó^ñ¾ïDï*ñÄózõœöŒöúõâõ²ö–ùÈüÞýhý®ü”ü®þ*fntŒ¦xxz ¸ ô ð œ ° ¢ h T ÄøÀ. v p¦îìˆÜ*´Ì¦ Ö  ,ì ¾´dBÿ@ÿ –b& ÈôHø¸¼þÌ„^ød¶x(²þ ýfüöûôúŽùô÷2÷j÷hø^ùÒù°ùBù>ù¦ù^ûÊýÄþòþÖÿ2DÚÿÿºþ@þêýìü8úø÷L÷Œöæöø$ø8÷`õ°óPóÚóÎôÀôô`óRònò ôŒô ô:ójñ¾ïï¤ïÚðñ@ñ¼ñ†ññ®ðòðJòèò.òZñÜð¤ñÄó˜öœø"ù¤ø"ø˜ùúüò|„Æ ò ° Ì Ü 0  Ô  p ð – 4 HªæÊÀþfü0ý€ÿÔ\ø¨|(<  B Ž PfŠàÌÒlÚü|øõôšõà÷ºønøÖø&újüŠÿ¶ r t ˜dì(òª  ò ‚ 4„ôÿxüúÄ÷–óHï&ì¢è^åäãÞäØåÞã$à®Û(ÙÐÚjáëHôÆü>, ˜¢è%L,3®9Z>x@šAJAê?¶>|:ˆ2l(Fôð¾ÿ°÷Âï:èØàFÚXØnÙÖÙÞÚÝRàäŽèìæíï&ï‚ïnïâî¢íøë’î¼ñÌñ ïjëdè@ètç0æ ãßTÝüÜ’ÝøÞüߨÞ8߸áÖá`á ã‚æê:ì@íÚñjöúêý¶<bt ¦ î ¦ \Ö>¾üÈôRëdå0áÝ\Ù¬ÔÚÐtϰÍpÍÏ’Ð"ÓÄÔÖèØ<Ý\áåøèí¾ñpöº÷6øŽûhˆztªŒ>( æ^¤ˆv¦bèÎ ê$˜¼ t Ö ^J¦œ¤Œ 8®¼ ÌÞ  :Æ®û&ô˜í éôå áÊݾÚöØÚٜݬáXæ¸ì¸óxúT¢ l* %(È'\%ô#Ð" fhÌà Tòý¬÷‚óxò(ò„ñBñ.òØõfú’þð<Ø$&pÜý|ú.ö6ñtëærãá’Þ8ß àèß:áâ¾âžãBäþäääväXådææ:çbé,ëdì¢í:ïÀðöòöôØö¼øZù”úüüTþžþþRþþÒúäöòôÎñªìféèàäªàÊÞæÞ¢ßþà&ã¦æÎë¶ï`òhöÌùtúêû–ÿœLxÚ¤ÿ†þ ýý„ÿ8ÿû ùûøú¢ùxúøýºH @,H@ˆúvŠ&¦ ô â ² 8 VìRª˜òFÖüvöÞñ¨ðjñZóÄõ˜öºõô¸ó|ôªóäñ òõ¨øÈúVýÞn . :¦ " D¤@t"êbÿØÿDprLî˜ê¦ø,ZÜüBújøœ÷ ø"ú6ü†ý¨ýìý,ü>øVôpñôñ õŠ÷°ø’ùüù úú’ú¦û‚úL÷„ö†÷JøZù²ù¸ú0þž\LÊd*B®P^ö¼þdüûfúû ýÿöü2úlù®úbüžüòú¸÷ˆõH÷ü Ò’ôøè |   8 jRŒZv‚ªÊ„Bò¤Z x Ò  lŒF2ÿ~ÿ¦ÿŠþÄþš^Òv¸¾lľÖf¦Öˆ ÿ8ÿ˜ýÐú<ù6úÒüžþ‚þÄþÿJZÊÒŒì Ì j d ² ¢ ^ x f  2 N |ÂΠºxýðúúÚø4÷´õ8õPôôúódôNõxõ’õÖõbõõšôôHôõ.ö<ø*úHûûhùÂø ù¸ùÈú’û”üÔýzÿ†âÿÒþüþr(âºh¤¸`HØp¬LúÿZÿ|ÿ: Êÿ`ÿ\þ†ý`þàÎ$~".þîý¬þøþ†þ8ÿ ÿÎü0úªø$÷õ~òàð¾ïúîøî*ïïªíàëšëJìÈíâíŽípïLñðñúññjðöï0ð:ñò óÆôšöâøVú¨û8ýlÿøð¤ z ÂäŽÜ   ¬ xžêb¢ÿþhûL÷:ôàó*õÐöÐ÷rùüºý‚þÖþ þýüüý4ýlüDùnö"ôîð~îfìêøè¬ç¾åläãnâtãÀåféÖì ï,ñpô¤ø8ýÆröD $î.öf!”#ª$~%¼&j(Ú)<+ª+,*'„#R ÒZRvT ܲàÿdüøòóºïöëäéê®ëJíêíNîRîXîæîðöðñfï¢ìªéºèÂêÒí®ïÒï*îÂìì°íúï(ó†ö¶ø\øTõöðîÀîJò¼õzøPûîüü ù õ&ñŒîâë"ê–êíððˆôhöüõÌòúíRê è¾æÂãá˜ß^Þ6ݨÜXÜøÛþÙT׎մÔNÔ^ÕìØ>Þžâžä¦å`çtêøînóîöôøŽ÷õ´õ‚ù–þxød.’JÿÐ~ †¢˜:D²þ<þ>ú(Rˆþžü$ùêô†ï¬êˆè êèíNïÐíäìPìxê~éÖìÂó>ù¦ú’úûÀú"ù*÷Bö ù"þÆ,P¾ÀbêÖþ`øö.ùZú V 0 €ô®ù€ôJôbø´üÆþÿRý¸úìúþòxÀº€ÚüžøŠ÷ ø2ûäþºTÿùñ:ìî²óì÷”ø€öæó¾ñÆò‚÷Bûêû~üêýðûöô ïðî òdõ8ø(ù”õÄîìèÞæ¶è ì@íìêÀç|åøåÜéÀî&ó÷®ûæþzÖÿXþäÿ~T  d ÀÞ¨z  Þ h |üòö¾ôð÷ôüâÿ’üNö ï4íâòˆù$üºû€úúöù’ú¨û<üÀýBxÚàÿüÿÄüJöô€ô~öþøøý 8ø. P È$& `#ð'1$8Ž8P7ž79N;²;€7p/%@ ^üTð~äÂÛØÓèÈ”»®¯ ¨È¥t¨N¬´­¸¬–¬°·p¿pÆVÊ(ÍÒÙ^àþæPì ñõdø¬úøùúöhö€ù(üÌûÄ÷ðØéë‚ñtøüû‚ûzúäúÆû´üýbý6ÿ ê6 Ø <Tœ âÄþ4ûûèürýLû€÷ÜòÀîí&í°ìTëüé(ébéŠêöê@ë°íÞð¨óZöô÷ØùZý^Š z44øÖT¶Ô  #Ê&n)Ú*Æ*^) &j#J!8 V†p4"¸øŒ Î"´‚d€râDÞx¼üÿÆÿJÿ¨ývûTù˜øúâúÔù^ø¦÷t÷Þ÷Zú°ý ÿÜþHÿ8Ô® Ì 0² È ’ < ü â˜Xh &ÚŽ°þü úœøúöèôªóvóó¾ñBðvï¢ïèðó õ*önöôö¼÷jø¢øùöùÐú†û:üòübýlþ䀨„0ÿ\ÿfª"`L´‚ ª P Ò 4H¬  rÖÄÆNúVzÎÔþþþþ`ý"ü¦úŽùRùˆùìù"ú(úhùZø~÷àöÔöæ÷´ùûÊûÎû‚û:ûû„û|üTýèý¨ý^ýDýŠýþþ4ýØû’ùl÷8öö¸õ¼ôîòžð>ðÂñzò|ñòïïÚîŠîî`íxí4î>ï¬ïÐîpí¢íð€óLöÀölõ0ôXôþõÎ÷Äøòø†ø÷ÞöúøÒûæý\þÆüÞù¾öpõŒõŒõ¶õ„ö¸÷ù`ùbùtûÿ†àÊjLB²Ä"ž œ¤x¼ý’úºøš÷t÷VøHú¨üNý`üBûŒù¬øùþù^ûVü.üÐúÚøªö¼õäõþó„ð ðôªùþ<Øþ†üÒû¼ü¶þ|ÜF Ú&ÿjýþ"ÿ’ýdùÒô,ô†÷ÈûDÿÔfÿLü8ú®÷xööø ýZVHÿ ý<üÚú6ùö.ñpìPè¼äÄä¶ç$ê€ë’ëêBéžèLè4éÜêŠìòï õnû ÿ$€þ~ûÎùTú’ûþòÀœÐ\Ô0äÿ>ÿ~˜ ž8lû¨ó îØíôí²í^ï0ñbñó*ö”öêô”óóóXô¢õ0òlíxì8ïîñ0ðôëúéŽè°èÞí¨ôLø–ûÄ"úT#p-ê6Ä=ÌA¬F MzQbSnSüNPEØ8l+& àæ´úTê,ÜŽÓ$ÍzÅð¼VµÌ°f±R´îµ·Xº¶¾`ÁžÂÄRÇÂËZÏÓR×*٦؀ØÄÚhß®ávà’Þ¼ÜÚÚæÜdãxç‚æ\åøäªäœä|å”çJé€êí¨ïhñVô¢øðüö ÄÚÿþþ–ÿ‚Þšþ*öšî^ê4è¢ææä.á Û>ÕBÑ´Í˚̨Ï6ÏͼÌÍ®ÏÜÔ²Ûøâ’è¶ç¼äbæê°ð‚ûX Ðr „Ø"´"œ$ &Î)Ê-Î0b1ä.*ì#b ¨Nê°<d‚ Ö \àÆ^ ’Єò¤²üêúþøTö ôÐð`íþêrèlæJäÂárá†ã–æÜêðööü‚všxd#~)à.š3‚6Ê7Ö7˜4~.¼'À!V2² ¬fRý¨ûPùˆöó´î:ëê éNçæåÞääáPÜ×Ó>ÏÀËêȺÅ~Án½n¼ú¾ÎÂ$Æ’È´ÉÄɈÊZÍlшմ؊ڠܜßZâ²åHê>îÒðlóBöÆø:üþpr 2 ø N €  ~Þ "¤¶ý”ùjö:ó ï(êüäLálàRáèâþäç èÈèzêJí*ñ öDü¤è Fî–ˆVp <*Ô"î^Äddè,ĈŠþDÀv@¨¢.â ¸ N xV¬ý$ûÆùÂø¾ö@ôŠòñ`ðÐð\ñvð®í|ëÐë îZòÔõBù¨ü ÿD̦ú6ø > ð è – X š  fD´&²ýDû,údúÄùZönò†ñÜññFñŠñ–ïœí¢íîäí¼íÀîæîÎì ê¨çÌåæ8éPìØí ïRòö÷ ÷2ùRúü|ÿØ¢0Fü D Ä j 0pº¦|r. î ¢ h ê  8 H  X N ` „ ð D Ê*ZzÀH¸ÖК|<ȤØp(dR $ h Ä T`âš*lÀ®Ü´²¶ ‚ ö Ò€ò„ØþLü\ûªú–ùèø>ø ÷÷|ö–öðö„öèõöõˆõtôšó€òÆñ|ñþð\ð¸ï¢îîÔíí¼ëÚê*ë4ì”íÊîï€îÒí€í‚íÒíêîðžðêñLôþö~ùúûˆýDý0ý¢ý”þÞÿ|¼ÿÐþòýüjùööäõ,öÄõ\ô.ó òJñ^ò\ô¢õâ÷ûFý¼þÖÿf¼îr¨òü@ÿ²úÚöžôÄó0óìñ ññúð¬ñ ó(ôÐôXõj÷Xú¦üZÿÒŠ – Ä`2¼Ø´h`Nÿºþäý¬ü4ûºù®ø@øì÷–÷ª÷ª÷Ðöòô¨óàónõdö˜ö&öNõ~õªõvõBõFô\óòLñžð8î®ëÞéüæ&ãèÞÚÛÔÚfÚîÚ*Ýøßlá2â€ã,åðæhéVëHíÌï\òÚõÆ÷d÷÷˜örõô,ó"ò˜ñHòHóâó€ô‚õî÷`úü~ýèþDÿ¸þ@þvý®ü*üÀú*÷üòðBíê è‚æ~äLãfãäåéRî|ñlñîò,÷NüȤ8¶,>N@p2Ê œ NØÎ¬zD¸!Ì$î$ BðdŒj 6 RZúónîþëäèîãöÞ”Û°ØdÕÖÒŽÑÈÏ.ÎÒˈƴÁ À ÀŽÁÂÁ~¿`½î¼X¾¶Â@É¢Î@ÑXÒ\Ôj×jÛáªç ìŒînï”î ìêé¾èèˆçðå¾áÝêÚˆÛŽÝxàæã<åÌåäç6ëºîâð`òžóPóó²óäôN÷ÈøÒöFòÌížéúå*ãâàìÞäÝ&ßÖáàãæ6éÜé@èÄæçdê ñœûúx hêðl fªÞ$°*ò-D-*¬$bzþèþ|| tºˆ–Xˆ\ Ò ¸ ¼ ô ¸ @ . œ ‚ X ˜  L D’ T ÊŠÿøþ*ý"ý¾ÿ’„ @ À ò   Šš¨hþ–, `ÌŒûö÷RõÄópô–õ°ô°òšïdêÞå¤äâæ|êPíàï¢ñ„ñ|ñNò”ñøí²èšã á.ã†æäé¤ìŠîôîxî”î˜ï*ïêìRë”ê6é*éÞì–ò‚÷$úTù®õó¢ôÊù:ÿJf†VýÊúXúDûäûûšúJù|ø.øpùBý®:Hêt  BÆÐ@N"8#P##€#8%Ì%¶#T!0úòbøºð" ö rpHŒTZXlÿ¬þpýlýâþDÔÈ,dªðþŠýxýÿÈÒR†Þ~@zæêþüÆú¬ûÜþª’*R ò–<ŠÞö$Lü€ì 8ÐàøºïÊçÔáŽÝÖØÒöÉØÂ ÀzÁzÃjÃÂNÁÆÂxƾËtÑøÖ–Ûæàøæ8ê´ê*ëºë>í’ïhðÞï0îÜì\î”ñšóüóäòòÈòÈóôþóÞôZ÷°úþ8x6 &äšüH&Ðn¬fض¶þrûàøøÔø¬ùÈ÷hô¨ñ8ïºí„îð¢ð˜ñFóÂô”öùäû´ÿ@ÞŽ È  êÎL\¼ÈòúâìÌàò*Ô„p’ ¦ ² 6 ¤îˆh˜¾À‚Ú&îâÆŒXÆB²ÒX|ÿºþÆý¨û ùbøÌöõ´ôZôÜòÞñ–ó÷’÷zõpõúõ*õpõø÷ôùÄùêøüøÜú˜úXø&ùü®út÷föhöÂö¦øÀùèù~ùÆøŽùûüþ–ÿþàøÿÔüÜý 4ÿýâÿšÿ°û<üšþ„þ@þLþºû²úàüÔýFþ|€<Jÿ>ÿpÿvÿ.ÿxÿŠþ”û¨ù¶ùöùÜøZøè÷bõŠóDóºòjó:õ*õóFññ>òôööÌöúôêô<ô’ò”òfò¸ðÚî8írëXêéäè¬éðç¢ä8â–áÈâ.åðåBã~àdà á.ãPènì6í6îbïòðòõ¨üŒàzš–ž ö ªØ(pÒ ntÞÂôHþzúþø~ûÌÿt"Rÿ~ü,ü„ÿ>ºä Ú 0ð–ÿš¨&þtøüô`õÂ÷âù&únú úpùbùrûÔþLbâlÈÔÿZšV*ü0¾ô X ü‚â*Œî˜Ì\úvõ¶ótô4öÞõ–òÚíÔé°æüâpßvÞÔÞßdÞXÜvÙˆÖ¦ÕJØ4ÚÎØ$ÖîÓPÒÓ8ÕþÕªÕF×(Ú$ÝVàbã8æÚçÖæåNåçêè8ë¾ìÖìBíŽï.óäójñbíêðéÆë<ìÐëìÂíÚîîíüêDè„ä¢à~ÞÞÎÞrà*äòçÞè†ç–æBæ.åšãâšâ¨æLê é´ætå”èÐðÒù<þŒþÊþÎb¨– ~ <> p ® ´¸ž’Àž’ Ô\Üà ˜ ´ d8ýzö8óòòjõ¨÷Èöèó~òtôò÷*ø(õ¤òúñÌñ¢óøÆüÞýÆú÷ õ¢õ®ö˜õôñæí(îÌôŽürþÒûêúàþ~² (¸|þ® ˆÚ ð €ZLFüRrrðT^VÊdø^ð€ëéHæ²áÞÚÔjÑŽÒÆÓ Ñ Ì®É&ÌJÑÕÖ(×^Ú„ß"äòæLèVéôëbïò(ô¶õØöLúv" „äx  Tĺ„ÈØ¬ÎŒ * úÌhÂýûúÜú¬û>ú’÷`ö÷øø2÷ºõ:õ²õòöùôû„þ²þÐüüúÒûBÿƘb œ  è TÜìÒL(Ü<€dœ`"„"ô ®Æ(HšÔ* Âtj¬®þžû²÷ôŒðrí¢êèçrèÎë˜î€ï„îzíªïÊôføÒøD÷:õhõ:øÐú¦û|ûúú„ú8ú*ù8øî÷Ž÷lö€õâõ÷ò÷„÷BöÐôÜòtðèíìêÒéÆëúí$íRé^æÂåfæ„ç|çPå¼âºá â2ã:åâçÜêªí:ðlñNñbòöõ4ú€ý´ÿ® `˜. < Ì òàè¬  ìŠÜ!t#ò#¼"â ¶r‚òˆò„þúNb  °ø6 ¬ , B : T 8 ˆ " °v `´dpD¢ZlJè’¶F€¶ê ÔÐ ( ž°¨ð N¨û”õŒðìbêNë`í8ðÞñˆòfóÄóˆòÄðïðîRð òêôø÷âûfÿlÿÞþ¢þŽü<ûûxú:úÂù>øø~ùxü^ÿ(:ÆþàûhúÊûNý(þÈâÌîH8d¾ˆþÆúà÷2öîôÔôZõbõ2ôPò°ñóö|ùÐú”ù®ø\ú(ýäÿ¦b`¸TÞp0nl²VüÄÀ6Lœ¶òÿ,ÔŽÐøÿ`Fÿ˜þlÿ°þ ý¢û€ù÷Äõ`ô(ò"ñ$ñöï0î˜í8îœïþï*î@ìôìˆîŽî(ïÞïï~íÆìLíŽî ððð òDô(ö÷€÷ù ú¾øøö÷’÷÷ø\ú°ûvü*üâû¨ütüfû²û°üäüJý²ýDýÂüzýðþ0ÿ þNü¬ûôûŠú”÷Pôäñ€ñÞññ ð.îÎê~é˜êœë0íðØòlô–örù†ü þÒü¤úÌùûý€þêþ–þ¢ÿðöœ¢þšüèýÎÞtp´<š* žÔ> ôÐ2 ÊH4ŠrvÿDþ’ýZüžùŽõìñÔî&îPðdñÐï2î¢îˆð ò€òöòZöTú¼ûdúZø¢ø(ûFü.üžüˆû¤ù6ùNøzö`ôÌò@òžñò²òÂñpñ:ótöäø†ù®øÌ÷´øNúôûöüìüÈûzû¶ù~ôÎîÀêŽçÊãàÞlÞ6ߘݬÛHÛÀÛ´Ý*ÞÞ&àÆäöéDì¶ëÖêìë¤ïdõ„ø–ö„ô2ö^ùHù|÷P÷¾øúþù^øR÷røøúÂûÚú–ù ø ÷2øøŒø¦÷÷bö$ô0òójõ°ööÈô>ôÎô`öÎöõ*ô®ôžôòó óxòVòÄòÞòºñ®ïrîœî¦ïð’ïêï.ñîñ¤ò|ó²ôšö¢÷b÷÷tøŠø¬÷¤ö¨õèôTô°óœòtñFðäîòí2ížì~ìàë¤êDé”çÞæþæ²æJåãªáÂànßúÞJà â¶ã(â®ÞÝ\ÞÖáçªëjîÞðó>òŠï¼íøí¶ðÜóôòvï@í¨íÐï2ð¦ë(æå°ç¸êªì4ïóvö²øÄù´ù2û–ÿB \ÿZÿÞ¨r¢,r ¦è" (ÚÈ ª€ VŽˆ<R0æ¬Änr⢺š4l~ØRÀ¸”(ÚÒP¢ü’F@vھ®x~V„ è Œ x Òf>b´Ì¤î¤ÿTünùê÷ŽùýúÿÆ¢þýøü.ü¾úrùÀøzúüJúð÷”øÐúÈú øó”î îfðØñ`ðØìë¦í¢òâ÷púùHøÞø<øè÷ˆ÷\õ˜óZôˆóVñxñþòHôàó´òÈñŽðªïhñ¢õNø¨÷@ö¢öLùLûü$þPÄ žV0Ä@2V\#$ð!n"~%h($+è.01Ž/p,8+t,T-ò*L$tÐ>"¸#Œ!¦š.:0r.fŽ` `8ÔšH j ì x NÂô ú ¾ ŒZ*ê æ B 4 &ª X ìL8êšþÚ º \ Î ˆ ¤ \Æòøhdÿÿbÿ`ýùÞõŒò4ð¾í ê8çLæ²åäœââ â ߊÜpÜúÜpÞ–á’ãNåèê$ìÒñú˜ÿx*T–„ˆ(ä¤ à F @ ¨VÊ´”ðÿÀúÐø8ø õžñ*îêØä0âÜá&á0à˜ßæÞÞ¼ßöãrèVë¶ëëìòîÒñÂô¶÷Šú´ýrV¸x ‚ ¢ tô * 2À¸ T ¤ ®àZtàθ\"¨ è zF6$Jøþþ¬ý„ý°ü>ýÿ‚þæû\úüùœúHüýfüzûÆúúrùVø¢÷ ÷v÷:÷~÷øÌøÄùvúøú¶û€ýÚÿ´öÎ nòXz^è¬ø²šÿÌýÜû>ù*öpó4ò–ò¦óNôÌô¨õºöêö’ô^ñ´ð<òÂóõèõÞõ²ö’ùzûHûºûDü>úÆ÷„øhû€ý ÿÌÿÖþ¸üüèý6.ÈFŠ4¬vR:¬ZNRþBû ù÷H÷ØùúúÀûžýÔþ6ýàû’ûvûÒü†ÿðÿ€þfÿú$Ò²€þ®DpÄÿvü@ù¶÷ôöÞõšõöõ¬óñŠòrõÆô¾ónò(ðàï¶ñ2óJó*ñ°îˆí˜íXïó|ôÆòäð&î´êPéÔêìîî6ìëŽëìLíïbîXì>ë éDèÌéàì¨ïbðêíÈê˜êêì†îïðˆðð$ðPñÖñòèòòðþíî^ñ€õà÷2ù¦ùÚø–ø.úXûpû^ûÞû þ²ž¼ˆ l2 H ~Œ rrÄ¶Ä , j ¤J.@’\@¼ Š"Îÿ@üÜøöÆõœö„ô\ñ–ïNï6ð¼óú ÿJÿbÿòF’Œý8ý’ÿœRÊ^2¼æ®ÿèüôûôü€þÿÌÿ€ÿˆüîøÄôÐï’êèéÈîPõúüLú:öúópô õ òíéè èvè¬èXæþá”ß"ßÈÞŠÝèÛ†ÞãÈèÈðBö÷˜õ õ<ù\˜L8ThX Î0 n&Þ„ †   t¾þÄ Ú à и Öê$ˆ Æ Z B žÀ 2. "Ò’L „ ìbìÊLªx˜ F&2VŠ&äX † 0 ð  Ö þZÀ¢VF Èl®ÿ z Ü\ ö:îúüóbð^ó¼úÒÿþŽø²ô¾ô’÷^÷"ôèôTû®þÚˆþ>þÚ6x ® ÒzœP–ÿˆÿìJŠàûfóðïDïNì¤éëVðòï¤ëðí6õü|þ|üZú üĨˆ œ bXþPû8ù†öòòîæéHêôëªéÚäLáápâ<ã†â*ä>ëópõøóšòìñò óó¸òÀñ¢ð&ñ0óõöö<ú"üdùÈõd÷ÊûÿBLpÜ~ºÜÿpþ$ÿ„@¼¬¨ŒÌèÎrˆø”ðþýÎü@ýÿø|^t~Æ Ö☠ö 𢬠X(f"¶Â$”üžº¨ˆÔºÄŽ´ Ì hfÞRºþ~f&èÿ‚ýæýÿ¸ÿ6ÜàànÊl°ø ¢ ¦ Dœþ*¾ P ê ’B ä äø–˜šäŠÎBŒ¨ªŒ \ˆÿˆþÒþHÿ8øz@úv.  $ *VT r ˆîPè`à,‚>Ìâ´vÒtpì ðÄ € <~8€²"ÿ*þòýÜýrýâüfü û:ûxû€üâþ0bÞþýlÿnjê̜޼ , HÌÌÐ 6 V î 06 D   l ~ 2 êø˜~œ,š úý2ý>ý.ýÈûðùÜøŠ÷‚õìóœó¦ózôvöÖöÐõ6ö2øÌøJø¤ø´ùôúýšÿŽ ºÌöª¬  ^ ú ` p*ÚjtÈÚBÿÜüúø¨ö”õ¼õ6öŒõ<ôôõböö’óŒò~óLóôòÌô$öDõ|ôõõ¶óbò4ò¬ñäðªï®ínëÒêœëíúíÒîñ„ò:òóäôõŽô:õF÷úTüþÌÿÜ$ÿÊýÀüüàúºù÷šô’óŽñºîˆììÄíZïüïHñóÚôöLöXõöó>ó¤òó’ô2ö€øøûTþÆþšþ4ÿìÿ¦ÿ¤ý¦ü–þ@xp . æ € p Ü € d ( J Ž $ Z Ü ê ÊjTpæN¨\º*NŠÿªÿNÿPýýÐýšýÆü4û*ù”÷¶õ²óò–ñ>ò°ò²ñfðlï~î0ïþðìñÆñœñvñ€òºõÂø¦ùVùZùRúþúîûÔü®ûùø€ø´ûÖþ²ÿ¶ýªû<û´ü²"ÿýdþª&ÒZŒJ ò ÌDü†Düæö´òŒïíøé0æ:ãæßâÚžÚrànäÀäÊåbèÞìòâôþö`ûîÿ|D4 J’ ¦ d RÎîÚ,ü ÚNP ,0V"`Vṳ́lXôø< x .¸ÿ”ü€ûšúPøõòó ôvòøïžîHïÞñVõÜ÷¾øjùXü¬À€¦¼ L Èøò" $œl²¼‚HŒ„" #ö!& JÆî†$¨¶&þè V 2 R:ý øö°ô¶óòLñ ñð®îÊîð„ðñ¢òøôôõ ôó˜óöÀøú&û(ûôúäû¦ýîÿ´àè˜DÈvöÞô²~<.ÀìNxœýxú.ùÜùîùùT÷ôôâòîñ˜ñBò‚ôh÷°ú¤ürü0ûÎü2 è . вÂb²¬.œ€¦È!Þ$r&'È'@(â(¨(r'N&&ž&š&~&z%$Z"\‚n!ª!Vð®p¬†Ð˜¤šâ^ ⪊XÖ0 ^h´r><\HB’ÆÂ(VP2p<F,®Ø‚ຠì¾ô”ýœüüùbôPïèìFîìð†óPõªõvô¨ñžïzñÚööû€þ´ÔŽþŠù¢øÊúüüºú>ùLøê÷`úxÿ‚Æü²^pL"ò¢ÐþŠþ²¾´´úõŒò<ó<ödøÜø÷–óàñLó¸õÜ÷îùHýb ÿ’üþT þ æÊ`Ì œ €2T ZζΠ2xòÌ–œâ¼Œ&ü,   „ìæj  Ljtl´DÿVû,øØ÷¨ø\øD÷Æôàð¬îÈïðìíÌìïäñ@ô(÷ùn÷ÞôõÂ÷”÷ÒôJõ¬ø€ù”÷ôôÐòüðÔïðpðŒñ„ôl÷÷°óàð–ñ´ôröõòòïðîï¼îdíì$î2ð2ñŒð,í&ëî"ó²õž÷ûVü:ûüÌýâý¤þÐn޲œˆÿû²ù<ûÒûzüÌý´þÿzÿžþBýý„ÿŽ&r*øhbZšüÀú´û2ü üòûbüzü^ûJúú8û†þð<hÊÿžZÖ2T’ÎZþ<û*ùùæúFûò÷Lôâóèôpõ4ø¬û^üû¶û ü û–ûàû úšùÜødù~ü&š6ÿ¨ÿÚÿzþŠýÎýÔýdþâþrþXþâý ýØüÄýÿ(8FÿÚþ:þ:þÿŠý®úú¨ù$ùFùdù(ù"úüÔý4þdüÐú¦úú†ùúøúèúùøú’ý>¤êÞÜ–v4ÜB   Œnl¤Æ p ¦¤ˆrFÒØîvøln<² 0 æ® @ ð ÄTæÐr < dä:TxÖTÿ¨þ–þRþþý:ÿ~ô Öª€Æp†@ÿòÿzèÿ,ÿÐýÂûÐùøø"øFú6þªJÆJ^ÿDü¸ùlùù–ø|øÊöõböløà÷Vö ö”öÐ÷ªùJûôû\û°ú0ú^ù¨ø0÷xõøôbõœõÄõbôôDõªöþ÷þ÷>õRó8ôüõX÷’ø‚ù”ùrùzùªùbûÌý>ÿøþÆþœ¨´Üî¾¾ö r B X : BHNÎ&Úˆž¼ м"ð$Ô$%à%@%$v#°"þ ä æL ¬ \n„‚p”v 6 Ž žøx à Ä|Šx~šZ  ÎDh"þÀ^|®^` Î Ì ¸ð4ú4Ø ¾ÂüFž*ŽFöÔªðýàü€ûÞøö°õöõõª÷šÿžö<® `Ü V<¢nf¼2¦l¦æ®äDŒ ö ¢ œ€îpd :"¬"’!bâxD|Ä6ˆÈ æîÆà ~ffÔ ÞR®häö0° Òl"B,%À+Ê+ü&ü!œ¸ ðPÜ”V¾`\\V ÆžøˆôÔú.¬ðúÀú”þôÿÚÿ¬JžÈX„þxýÌÿÈÿ^ù6ñ"ìJêêøéXæÎâ|ãzåçlé^íbñ2ôPõ\öTù–ýDòŠFöHýdøêö ÷öþøšûòøˆ÷îùùNöDõìõÎô óšòDï²ëÐêë:êÒçˆäjã ä>äÒãnâ|á~â´ãVäðåÚèî2õ®ûD°¸ð ¸È €#2$®&¾)D,2-ú+>+Ê,¼..Î*¬(Î)À+h,.*(&N"N*ælØ*, r l¶nüö øphô–@ìêÀ:ö æ $ 2 Ð – 6 : Š œ Š & ¶ Þ ‚°Ä”˜@¶Îjfì2 ª . ° r¢ýrúx÷òóvñhðÊï¨ïøï¬ïÔîdîbîÞíœì:ëêºèšç°çŠèºé€ê.êé´èdéêÎê^ìrî†ðòŽò¦òŠóžõÄ÷Ðø˜ùÂú"üÈýÀÿ<Ü’,ÈŽ˜h¼HÌö–´$ÿ´ýTüûúœùfùÄøê÷jöžôÀô&÷öùÔü¾ÿFhÊÔ– ¦Òpf|ènÎÌ´RÂ’–Š8PV*‚ôTZfÎꌦ îð*ÖRxf´¼þ°ý¤ý¦ûúbúNúžøR÷Œø|ùî÷úõbõ€õêôôbó^óÜô†ørü¸þLÿÖþ$ÿLÿJþÚü&ü<üLü*üTü–üûžøŽöºõþô^óêñVðÐíjìTí&ïžïjîíöë¨ê&êTëí:îäî¶ðúò¢ô*õTôŽóJóêòŒòfòDòbóŠõ¬÷ øÜ÷˜ø ú˜üxýÎû¦ùúü^þ~ì¨rxÿ¬ÿ2^Z`ÿ:ý ûîúü ü"ü®üRýªüšúHùvù@úhû0ý|þ¨ý¨ü¬ý\ÿxÿ²þFÿÔ$ð2âþºýØüÌüýÔü|ý¨þ8ÿ¬þÂý ýTü–û4ûøú”ú¶úâúºú4úîø¾÷öövöðõüõzönöìõðôôÄóôèôHöP÷Æ÷ùØûfÿvܸþ$þ°ÿjh:þf(ÐÄÀ@hÿjþªÿxød0Æ | 4 ð Z Ê ŒøZàn.~ÈŠž>. L à  Ø ¦ Fª††2” tª¶(ÒÆ´ænŽênàœúо²†Â„ 2 œ ¾ d °   lœª ” Ô d Œ¶ª€¶ ~ ê r J ŒèÀ°Æ„*þù,õòtî$ìªì>ðôó@öÒõ„ô ôTòîïï”ð°ñŽðrðò”ó"óžðòìÄèúå|æ çäåöãÖáÆßRÞtß.âÔâ¶àßÒáÊçÐìàðüöÀÿÐ@ f8®È|"J$%þ%,'˜(~) (&# p,æðøj° X °f„¸ì®¦æ0 Æ"R#^!jÖÄòÈ ¶"z"Ô <:æ\ "F%'>&Ê$ä%²)š-¼.-È*È( (D)Ž+ô,.Š/(1è1 2Ž1$1Ü0>0ª/&/z.Ð+'Þ!jÚÔ¢ tŽÿ’ý¶ûÞ÷tó„ðžïôîtìXèåÆãäüäÔåÂæpè êtìîRïjïîNìäë¸íñBóªòzðÐïñüó”õJöÐ÷üú¦ý6þˆüdúŒùûòü>ý<ünûrú ùŽø¼ùôútùö ô~ô˜õPö÷ˆ÷žøäúfýÜþ²ÿ Ò€XtÄP„ l ê‚R”ð$Ðn"0%'Æ'n'â%4#|!"L#ª# #Z"¼" #T#L"æ! !Î! #ü#†#˜"¶!h r˜ HŒx¶  $ l v Ê è  H˜æ<â  ˆ † ŠØª&¶þÿf:äÿÒûØø˜øºù„úXûtü$ýÌýäþŽýø,ò¨ïtïDïð<òòŒï¢ï|òüò.ðí°ëVë’êdêÜëšëæèšè´ëî€î î`ìê*éjéèå ä®çì>î`ïjïÎíìèëþë*êžçXèÌìPñðòŒñtî²ê¬çxæ*çjéðìÆðnô"ø’û<þfÿœÿ$¦:Lnº( ê 2 F ¤Æ¼òýÔýPÿFðÿ ÿŽýüü8þ Þÿäýnü*ü.üØûÜû|ü®ýHþÒü²ùb÷8÷”ö4ô,òFòó4õ˜÷ù"ø€õàó ô|ô¤ôöÄø”ûdýÿ‚4Œ°ÿˆ´šˆš2VV‚bp ÿàüúløFøNø4ø’øùöø ÷TóHïìŠê„êìïÚñhófô*õZõ,õœô$ô8ôõ ö÷`ùÞû.ýÊýüüÖúnùöùpûÎû<úxù†ûºþVDlLÞ®¢D–Þ B ÐzŠÊ H l¤¶öæ&*lŽ*^8þýýÊýÿ’ÿÊÿìŠN`&n  & J º ¨ Øl. ²Æ²Òp¢Pêjþ6$Ú,lšl¨*’ ¼  ”–TÔ\&ÞÈ þ < ¬ X<6J¨ÄÔ°tþN$nLÞ†hÂb Z 2 ì " f * î ’ ( d J ¼úhÒÐ@ÖÌâÊÜæèvÿ^þÿjâÆœÐ2¼:¤ÞÊì$žÔ„î2ŠÈÿ(þpýbýÆühüªüýÂýŒþ„þÞþ온R(ÿÿüþÿnþ¾þþÿ^ÿþ.ý^ûÔùüù¼ù°ø¾ø¨ù¾úøû˜ýÿÆÿhÿˆÿÐÿìÿèêÊ–vìÿèþZÿPXàþÖüû´úTû üÈü¤üýòþˆ Üô¼Ê x˜˜†&œ:J˜’¦ìèP‚جघ–\\x~0èÂòfˆz²œj¶ZR`°ìÔò‚h F  x ( 0 8 Ø f ú J Œ È<>z ê ² È Ì þà0üêöÿ,ÿòýìü<û.ù²÷Úõ óñJð†ï’î¼ìøéÄççPçèå,äNå¾è¶ëfìê2çtç4êºìÄìÎëêë^í*îòìNêéLê.ìÊì8ìVìží>ïÊð‚òìôxørû˜ûrùTøìù„üýlú öfóÎô"ø~ú¸ùÈønû|ÿ˜–ýÌùÄøúúýp˜ ´BÜþÐûfùžúÿ6PÜ â¨Ø bøÖbÚ>ì€ZV¢¾ŽÂh0š¦Ú &$Œ#0Ž’6æ®<&¢xÚ ž"þŒþôÿ þ¨ùìõBõ\÷îøšø€øzú„üfüFû:úþøø`÷ö´ò”î$í:ï†òtôþópñxîœíbîšïÊñàô¢õŠñxëìé¦ìÌí~ëpéJêdìnî¾ðdñ¦î ë@êVì0îìí&ìüëÜíVî4éátÜŽÝá†ââ–âJâ°áÌá`ã^åzæ.æhå^æ¨èëhí¸ïPñ òô®÷FûhûZ÷dôP÷ÆýXÆ `èê¨XäÖú â $ ¨ú` € ° n 8  Ž ÌÜR À  6 4 |ø€Öô p">'p)+N/v6n<ª?¬C®HšKàKXK*J´FÒ@@;r6z0:)Œ" Òž¢ 2È®ÿ’þfþ¾”4N¢ÿNû¶ùÆúâû”ú¼õ¼ð<ïtî‚êNäà†ß˜àxàÞLÛøÙöÙÛfÞ´ã0èNêlëªì@î”ïbð~ñ¶órõõó^ðTí8ë‚ê ê¤ééÒænãäá²â8ãxá¢Þ„ÜÒÚšÙ¼ÙbÚ¶Ùœ×¬ÖÆ× Ø°ØªØüذÚfÝàßzââåŽéìîòðNôöõ&öŽöö÷ÚùûPûÖûDþ¶¸@üòà \ \¶È:šŒ2ðØ`œ´®žò"ªŒ. 0 Ø Þ `  X ü ü ” ÞÌzt : €& 2 4 8N¾ ä Š ž &b ü Ä‚†ý’ù4ö¦ópñ„ï.ï*ðÎïÎí„ëÖéBéªé|ëízíjìTë‚ì¶ïÈñšñRð.îXëBé èÀèJéðê†ìâì¨ì ì$í8îªïîðÀòþô´öNø´ùúú,úÀú4ûPûûfûøû†ûòúûü®ýŠÿRÞb(òÊhÜþÆê t Î d ð @ ,  †$ˆ´ræv~ºvÂæ„*¾¼.òb Ì ² , ‚ ú Š î ðTb ú ’ ~ ":,ä¼.¬r,J²æ„ú´ž„pÖZþüœú"ùî÷ ø|ùîù–øtööôFõ\ö¶ö:ö°öàø|ûØüTýþÐþHþÂüîû,ýrþ¨ýzýŽþ þ ýäýêþšþâýˆþnx@ÖZìêàÿ®¤Ö 8HnN8\è–¨ÿþxþâ|dZ®N j Æ z" † Ü8  j ° b ò X î ú l ö V H¢š’üÐhP Ü | ¼ZVŽD¦¨ÿ„ÿôІàþ4ý|ý†ü@úFú|üVýHü*úøøùFú¤üÚÿFäÿdýÖûºúÖø<øzù–úøùøÀõvô¼ó\òð0îRítîøñVõ–öhöþõ4õvóñDð4îâë0ê`évèzç´çŠèèžæDå¸åTænãÖÝÙºÙÐÝØáúãÚåPèâê*îüñˆöüÀ  ‚€âXÀd#Ì& )è)ž(X&è$ä$r$"Vœ Ø äX:ýòö¢óÌórõjöØõÚôÌô:öÒ÷÷óžïìììíRð¸ñ¤òtô¼ö÷îôXóÚô.ø`û>þ´ PÞ F ü 40tR8 ª ¤Ì¾Z È Ä N¬jþ"ù8ôðní’êŽåøÞøØâÓšÏΘȢÅö²Àð¿ªÁ ŦȨÊÖÊhÊÌÆÏèÓ׾شØpغٶÜBà†ãŒæÐé,ìüì°í†ïój÷"û>ýþ¦ÿàDøB ž€¸@Ö Œ   tð d V¾&.þþrý°ü¾ûtúˆùùùùtø¾øÂù>ûÀü¼ýtþZÿ¤<.¢ Œ & ÈpŽè0Ⱥ>^ŒÎ¬°^`ŽÂX ~ìŽþýªû€úèøÌöìóNñðïºìšé çç´æPæšåFä,âà&ß8ßÞèÜDÛtÚÞÚ"ÜÞFàÌâ$å@çŠèbéôéÈéòèHè`é>ìÖî0ïvííÖíFìèâä²âªâîâäâ|ã®äæå&èæêÂê&çä8ä.ä¨â*â„ãXäìäFç6ìêðxóôüóÂô<÷Âúøý¬ÿ¨|Rö.ÎhjèæàJÒb8& ,’<° ô!| :æ.–Ø ò ¸ ¨Æ¤° Z ä 6¤üzb.”  n¢2:Ê ~ 2 Þ ˜T¼ú6 ü¸òÿô@ô\æB€Ö‚ª´`â,¼LþÖúþù û¼ú˜÷0ôó®ó”ô0õÄõªöîöööÌõÚô(ô\õø ùN÷6õôdõ0øü†ÿ"ÔxDü^Š¢r¾þîûVùŒøúöûPüvûâú:ú(ùfù2û6ýÿÆ®\R*H X Ò 6 b ü ˜   ¢°DœXâÎr Ø ú ¬ ˜ € ”  ü ¬vt8DÞ4nìjJ òDªÊ jvD P ¬ º lĬÈÜ>Tl&,ªâØþ.Èÿ ÿàþDÿvÿ<ÿþLýÜüpü"üšûPû>üjþ °¤ìàþýÈüÄý´þ<¢üN4ÖÿbJä ÊþüXú´ùRúRú”ù¾ù˜úûÐúúøù"û´ýZæþúý¤ýþºþðÿê¶ÿJþÒüøûLüý:ýDü(û,ûÖû¸ûèúXúûØûäûîûfüþn<&@VàÖšh Ì<ܼnÿîýýPü4ûjùn÷ªõô0ô†ôØóXóÐóxõÎön÷¶÷:÷òõâôõàõ”öžö¶ö÷"÷ŽööøõHö~õªôõBõFô*óÄòèò óÀóòðXðððÖð®ððð8òóõT÷6ø<ø2øî÷†÷l÷N÷ø÷ŠúÀûöø`õõ–õÀôæó~ô"õªôôzòfñBóØõpøšûâýýü\ý^ÿrRDø&‚ ‚  î°æ”|P |þ€z<°²ÒªÊnN ò Ò D B Ê̆*ØJ Ê œ êÄàðüHø^õó`ñzï°íZì°ìšîpðÀñ4ó¦ó ñðì°évçàåæänã\á àâßßÜÜZÚ´Ø Ø~ØTÙ¼Ù”ÙžØØzÙæÛ~ݴݔ݄Ý@ÝFÝdÞÒßânåbèvé@è6æ¶äˆäæŽçþçŠæ”ãÆà¬ß¢àðâ*æðèœéˆè°ç¦çàæÒäâìá¾âBãvã”ä~æêçdè4ê îrñ¨òþòxóJôÀô~ô\ô’õf÷V÷ôôôºöàúÿ|®: Ö~ÄàVDÐÐú nè6r(ÖØ zn¢ B ÊŽÔÿ@L6þdûžú"úú÷üô ôHõTöZ÷¨ødøNõâñ"ð²í¢éºèîêõ ø8öxõ ø&ûÈú`ù¨øÐø4ûÿ|òÿ.èÿVýfúâùlûpüÞúøøbúŒþ Âýèû°ü ýüùõ¤ïéæâè@íÒë˜æfä–å”å´âRà.áN䨿èìé|íªñ°ó¾ñÚíÄìXïžñÆñØòt÷€üXýû¶ûh004ü˜ä¸ڨ¤š" H ŒR24Ð\|ºnz ô x l ´ ¨ t 0ºØ>°ÿ`b¨   |¤ôFœŠ"´R¬˜Lf2H¢ê|$Ô<ø,¾²v Ú  (00JÿÌÿôÿ²ÿjÿÿLþ€ýdýÀütù˜õ,ôjôÀóÚñžï²íÞìNìøêlé éÀèZçþæTè~é^é¢éôêÞìòîÖð¬òºõ ù‚ûŽýœÿvÿÊý²þÞF>Lþôû>ûšû¾úæù&ú°ùø÷‚÷4øÆù üôý†ûøjöÌõ4õœõüõô¦òõ„øÊùÖúÆý¼ÄŒx̆Æb ~ ¬ ²zBª¦¾z `n$T^°ŒÎì¾ n Ú Ö æ ¾(p"Àž(â¶âŒÞÒÚÚ,„ºŒìþôýþ˜ÿìHd¤bÿÿ„ÿèÿìÿÚÿ(ÿzýürûzûøú¸ø~öLõ.õõ¾ôäóÖòªñ®ðïvî–î˜îÜíŽì0ì íJîtïŽñ¸ójôôó¦óôHôüóõ÷ùxúûÊú6úÈúÜüþþdÒþèý4ýòüØüžü\üüÄû`üÄý:ÿlZÖÿfÿbÿàÿ@ N¸ð.Άì<²È®t* J&V¢F ¦ D – \  0 L@Ô4¾<pNFÚ$Rýnú2ødö˜õäõêõ$õ@ô óô¼õ¶ööõÜô&õFõõö¨÷$ø(øhùÄû€ýPÿ¾ì¸LT2\¢¤¬¤º(@Ú$æäôÿ²þ^ýäüêü˜ü¼û¦úìøþödöøxúêúBú¾ùŒúpû2ûØù˜øŒø ø@ø†ø¨ùúLúû@üLý²ýxþÎÿ*^°T® 8Jàÿöý4ûòøŒ÷Äö@öLöÞöº÷šøâøù6úÔû²ü>üèú2ùÈ÷j÷&÷võ.òfï„î¬î4îítëXêôééPç^çšélìÜíîfîBîzí~íXîîŠíPîêï˜ñèòˆô÷®øöøú²ûDüðûVû¦úæùFù¼øFø~øäùÂù øæøúùüú’ûÎûæú~ùtú(þN0:2”TÈÿŽýzþ²VPÿn¤¸J(n 4`ÿ˜à< ö øjâ8®xbŒêø¬&”ÄØ¼ø4¶,¨&6öŒÈ ž ¶ € ð ú¼Ê¶Â"> 0€úÌî\ãfÚÒ‚Èh¿¹àµ^´„²°Ú¯¨³r¹Ü¾ÊÃFÉ®ÎVÓÖ× ÝÐâœèBíNïðöð‚ðíôçæäå æ:ædåHãŒáâ ãîäøåtèHípòšõÂö¾÷¦ù ûäû€úŽø”öJôÎñšðÔñ@ôìóæïþêPéäë¬ï,ñfñòÔò`ó‚ó²òñÈð¨ò®ô¨õØö:ú<ÿòüà p l$|*Ò0T7ô;0>p?„@6@ >D;9´7þ6\6è4„2$0¨-X+Z*°*¾*Œ)'¬$$ˆ$Ô#ò!¸°x 42Œ ‚ ÔžæâÐÿXûÐø¤÷¼÷žùDüþ@þÀýôýnÿ¢¢$†0b ŒêÿÌÿ˜þ@üxùÌöÒô2óäðÜí¢êÔçþäÈáöÞÜÜþÚºÙBنتÖöÔÕXּצÙÝtàŠálážârå\èê’ê–êšêÂênëíxï$ñ‚ñò¸óhö‚ø,ùúèüxBX” ~àR N ” 6 ‚ \FÔ , „ ˜ œ º l Ö X ž Œþ 8 ž(&þÚž‚øz"j¸!„$^'))ú(Ö)+<+è)î(š(Š'&%ú!ˆ"ìÈüÚÒÀ\Rf¨ Ä Ö º â À > ( ^ Ü  Ú(hrª°nRh²À¤^ÆŒ:øZfnØÂý ù\÷0÷äöõØóPõLøvú´ùÐö˜ô–ô ô@òîï„ïÔíZêäç‚ç é^ì4ïŒï´í@ëÂë.ï”òîô(ønû¤üÂú0÷†ôRô2ö÷*õBó"õøø^õ|óXôÚö€øøŽ÷.øúüpýœý*ý¨ý&ÿ’ÿþ&ü”ûJüâýrÿÊÔÚþöûLúâúöüÿlXÔ¢^vlÖ²B,&ŠˆÄ ÖR8€´(ôèD¤ÒžèT2ðšÿìþ¸ýèüúü ýxü¼ûûúÞø~øjøÐ÷²ö6õôäó–ôNõÜôbópñšïBîÖí°írí\ì¶é¨ç æÚæpçÐçè`çæPåFåæå6çäèüé&ê êÎêŽëàìïÄïðHðœð¤ñžóªõNöÒô®ódó–órô¬ôNõäõ6õ²óóNôDöÆ÷ øâø¾ú0üìû„úŒúûæúÞùHùpú$übýŽýFþ¾þªýü”ú<úlú6ûFüþºÿúþýôûýÔýòüüðûêüfÿælè¨ì®¤X" † Ô*ˆR^<>”ÿ°þˆÿJªþ~üPûDûüžýzÿÒâ*¸þ–ýÞýNÿ44ÿâýLýðüRý.ÿ¬"Ê\êbøŠ Þ  ¢Žˆ¦‚ô¢ŽD4VP¶b*J”¤N>`¦¦ Ê ¦žºj¤ý®ýLÿB ¬î ôd8 €  ˆ ’ ` T x ä d t r º ~ÖÎj0  * .t r ð Ð dDÚn’:ÿFÿ(ÿ¸þbþjþþ ý4ü\üý0ýêüzü ü2ýBýÂüJýÿ>ÐÖänh@®ò Ä Î Ì 4(´$ÿxþöýÌü¤ûvû€üzýòü”ûû´û¼üþpކÈÐ â <ê >  ª¨< È € Î æ è 0hÌî ~PÌjn¼`<>(¦¤özì<€DpÖô HP–´ º rN†žV’tÿ<žâþœýþþxZ„ ( Nœ¦ º\<äܬtît`ý2ü$ý.Ķ D4 VîòZÈ´ÔþZúùêú ýFý"üŒúHùìø°øööõ`õh÷˜÷äõõœõ÷ø¦øÌùøýj ˆ~zªÄDš(ürD n |Dº”‚< ÌîBØ,€ÐÿžØ¤€Øÿäú¶þ䦜Øüjù®öõ®ô¬ôèóXóˆôîöÖ÷òö÷|ùÄüÄþ¬þNþ<(ÄÔý>ýLþvÿ>FîäJÌfvì¬ÄþÐüêýÎÿäþtûÖø(ù(úšùø&ø’ùÀü8ÿäþôüüÞü:þÆÿ Öêþöüüžú’÷`õÌôRó$ðÆí¬íží$ì4ëxì:ïHòÈôòõPöà÷’û ÿpÿýºú@ùù:ûtþJ˜ÿ|ýûðøÐ÷ˆøúûöû8ýJþZþýnû(úú–û°ý¨ýrúÐöTõ^õ\ôHñXîÎíÚï¼ñ¶ð$í<ëòìÞïÀñâò‚ô¢ön÷lõòÀñ"õîøüû<0 jdôž P'ˆ+:+þ(â'î'¢&0"d ’ nÜî’¼Â$ÚäHØÈžÂ4J<,x<pÀÔvÿòûú¼ùèùúŽú¬ûæüþ ÿäÎ\þÖŽºj¬ÜÚ0Jlý`û¦úhú¦ù ø¤õþòñïæì´êhéZéìéjêÖêÎëþíïÎï"ð>ñ\òÌò¨ò~óõ‚öj÷nøÆúšýÿÒÿäþ^ýÔûü.þ6Zþÿxÿîþÿ”ÿ¢¶"<4XÔ‚T(ÒPÌ š‚,ÐøÂÐä¨4¢ ä˜Â8ˆ0Ö*Þ \htŽ8Ê4æt€ F š H ô Œ ÎšÈüþ¶ûìúÎú–úZúêùžøö¼ô@ó2òÎò<ô"õfõäõ°öN÷\øúÐûBülüúýDÞúÔ^ÿþrýþÞþ¤þÌüÂú˜ùÂøê÷Xø²ùvùXøØ÷Ö÷ øpùxûýøýXþ*þŠýÖü¦üjý>þþ¤þvþœý^üRûúTúÄú ûüfüTývþÿÞÿ`>ðÆÌ2âP|æFÂšŠ r6nÈìÿ¸ÿ`ÿðýðû®ûrýÎþüþîþ°‚&üþVþ€ý¬ý¶ÿê~î\ > ÂvŽ ^¬¤à,¤ÈÌPø<¾ýÜû¤û~ýˆ"l` n¼ÿXü.û†ûTü®ýÿÈZJ¦ 4è`èêº Ú 8 *°ªÀÿ(è¨æÔúšà,  æ \ ÌÜ¢ ( f –4 Ä º È 0 X H ”2 þ œ | € l 6 R Ô  øâ À Ž Œ  ( Ø Ì  &ÜB~ìj”€PÊ⎠’ T â ’ Xôx Ž~¬þ t ü  t ¢  Ð † lhÖ n ê ` î’.ÎÜJb ’ , ®:ÿþ4üJûäü*ÿJÿ¶ý<üÄûüÌûˆúžø$öó°ï\ìtêâêÀìœì2érå°ätæ€ç,çzèNìœï‚ñ,òhðàíÖízð²ó€õàõÖô¸ò„ñèòžõt÷òøæúˆýÊÿž®ÿ¢þ,ÿ°Jà „ø:¾ØÄ2–„>öஂք hv ÐÒ¤*Â0`Šr¼|v²˜R > ¨  €" Î D€ ÆV˜´N>| ‚ & ø ² l ¶ † Ö œ ª¶IJþ2ü ùlõ^ñþíPë2èåÂáÖÞÜ‚ÙÌ׸Ö@Õ|Ô^ÕÞÕÕ:ÔîÓŒÓxÓÆÔt×ôÙJÛHÝPààâ¬ä*æžçÞèê¾ìÌðôŒõöúõ&öÜöz÷Ê÷dø2ù˜ù€øöŠó>ñ¸îxíî<ïHï6î”íòívîï°ï ð¶ð ð.ðúï ðúñ$óÄóôô0ô.õ\÷ðù$üÔý ÿ–Ò˜ Rô4¤(,|ŽØŽŽrÈ*ÔØ® v 4 Z Ò Œ Ú Ò Î 0 r r ˜$þ¦^P¨ÿ*ýîû,û^úúžútû&ü¢ü(üìú6úZúÜú~ûàû˜û˜ú<ú¾úûTúîø¤÷ÊöTödöæö†ööô\óÜò,ó&ó ò4òäñêñ:óÄôÖô¨ózòxñòï4îÄìªë ê*è´æˆå¼ääå|äìâðâPåèÆé„ëtí´íìëpê¼êjìÜîªðTñ€ñ°ñÈñ ññdñTðêîØííÌì.îdñ õrøûý,þ¶þÐþHÿ4ÔNl ž œ ” ̲6†š~º|ÆDÖ>¶2Κz8\`ú’ â øþ‚ò Ö " t dÄx \ Þ ´ 6 r $ j ¨ðÖôúÚ ÊvPh0 n PΔÂ< J € ì | .Öþ¼ü´ý(>L*¸^n ÿ„û„øBö†ô>ô>öùPüºý¶ýbýÎüªûjú\ù|øøHø(ù|ú\üœþLššÿèý@ü6ûÒúÎúØú`úFùVø6ø8ùüú¶üÄý¢ýýØü þèÿfTˆ†ºÿ þšý’þøÿ¤¦žÎt°˜2¶¶6ö¬$ˆ¸¨ z4¸Ôb‚¨ ¦ 2 t üÈ^ Ž ò ÒJØ>L~€ @ ¾Ö´~†Ø€4®¢˜ – z ¤ º ôx þÿfÿN8âö:@î2v øÀì Êhrô* Ô 8 ˆ tšÀ–  p  Œš®$ Ô P"Î Â ‚ ~ R Ä ô²n  Ê š Êöº< Ü ît„Œx æhêàLŠ–Šô¤äý´ú0û4þþÿ¢Òê”Fÿžþÿ˜Ð˜þªû0úûý€þ’ý ûàø®÷–öBöÒ÷tû†ÿª>pZÖ<ª,ºþÀûÄøö$ó¤ð(ï8îÊíFîðþòTõ¾ô²ñnîÐì¨íøî`î ì¦ê$ìÌîvïî(í î„ï˜ïØîšî|ðâó*ötöºö„øü`ÿÞÿ°þþý ÿ$LÖ†ˆö°þ–üPü2þ¨V®¨šN2l"$l,ÿ®ý6ý>þâÿN¨¨t`ÔædÒüà$ N f ¢ ~ X D Š z 0  â ܆Òþ@t4â®~¤€6.^þ€ü úd÷€õôò$ðøïZñzñ¢î¢ë€ë îvðñtððìð^òžòjòhófôòóNó`ô’öR÷8öDõjôÐòÀðˆï~ïðñòøò®ôþöî÷B÷ ö^õjõ¤õrö¨õ6òŒîdíŽïÒñBñ€ïï.ðžðÔïð¬òJöôø ú’ú üÈþÜJèýbü”ütýèþrp°Ô8ÿ~ýÀüúüRýxþ¶bFÄýÈúHùú@ü˜ýŠýýÞûBùšöÖö^ùrûšü^þ°ÿ¾ýÈ÷üð:íDíVï¨ðrñòäòóæð2ìÜèöê,ñˆö\ø øÆøzüÖÜÖžîf L hê€þÌž®ôÜ ¶ èPðþôýÒýªþ0ÿýŽùløû*þâýÒû"ûúÚö<ôöóVõö÷€ø`÷ÈópòÌóÒó’òvóPöpøÌødùÐú€üÚý¬þ˜þÀü,ûpû\ýnþŽý¦ü”þ4<&$jØ®ð<b´þPúæøûÚüÈüpýTÿÔþý‚üdüªüþà&ìPúþtzŠ ¨  ¼œº>H ö ˆ  8 V ¢d ÈÜÌž¸p & P $ v‚îÆ¸ š < ŒT 0 بô Ä æDœ N @  $ þêüÚþè ^ ^ p ^ J Ò0ÈnÜæþôþ>þxýîûèù8ø²ö|õðôNõ„öv÷Žø ù<úúúú^ùú÷ÞöP÷:ùûÆûˆû>û˜ûüðû¨ûÜû@üŽüšüòûtûxû.üVýþ¢þLÿðÿ¤ÿ,þNü*ûû²úJúhûý$þÂþèþžÿòP|n6TtèˆÜöúÚÔÊÿÀÿ€¨ÔF ² î@¢þâþ®ÿZ’~$ž¸nò¨nÖØ†.P˜xî–bÒºtˆh.4.ä"‚B’t|Rþb‚ÿLþ¾üˆû8û:û|úHù†ø*ø¢÷´ö†ö¢÷Äøôø–øzø~ù¬ú²ûüûÊû¦û|üîý,ÿ˜ÿNÿÿ þFý4üºüÞþèN¢fÿ@ÿÜÿTÿÚü¤úâùFùlø ÷ÆöÄöd÷j÷‚ö&ö®ö˜÷Døšøîøžøô÷’÷î÷ž÷ØöŠöìöh÷b÷´÷`øùúøúØú”úøûhþD èÔ‚šrŒDÿŒþ¨ÿlú,lòZTúýŒü¼ûû&úäø¶÷zö¼õö÷|÷p÷ÜöÚõ°ôîó~óRóBô‚õ¾ö>ø¢ù´úû¶û&ýšÿœŠÔ ‚ ^ & 4 â þ ò fÎBúŠè Ì p d ¤ÀtÔÂ>ˆŒ 0|”~„|ðû˜ùû"ývýÖübü$ýPþäþ¨þÒýœýDþFÿþìÄhàzâ.B¾zð$.Ìæ†þÌýžþ„¾þ>üÌûªüdý ýrû ú6üþ þ–ü¼útøôõ.ôŽó^ó<òÊð`ñló¨ô¼ô.ôvóÂóõ\öX÷4ø^ùÚùXùZù&úlúÌú ü6þ˜ÆøtTP°N –öÜ\Ìÿ¼þþ¬þÔ>ºÿ>2xÿ¸üBûâûbýnþ†þæýºütúøB÷pù>ýrÿ þýzþd.ðÚÆÞþŠüFúhù6ûÆÿ4²tä $ 6  ð$t°8ò t È Ü  ˆÈŠø<N ø Ü °d²L|‚zf*P¾`ü bfzâ®jD^¶4†Ê„jÊÆT ¦ Ž ‚D2ÿªûäù^÷Øò*îØêTè*æXäãPââ¦àŽÜ&×Ô–Ô–ÖØÚ:ÞÈãè’èºææþçüêí†îPðÜñàñ¤ðÀïðñ`ñšðTïÎíPìüë\ì¢ìöìúírï8ñ4ó~ô@ô*óüñFñÆñ²óöø¸ù(ûnûRúêøføxù ú\ú>ùîø²ú”ý¨ÿê|~$аþ ¤ ŽºØdÆÄÜøì¶Ä ž"r#Ü#º#î"Æ!!$!!Î8¤ÞŠv€¦~n > 6 4 â&– r | öj2–h~¼ðÿîÿêÿæþýLüFý®þÞþ,þòý4þþhýÎü”üþü`ýÀüNûŽú²ú0ú.øúö¾÷üøùHø¶öDô$òÆðäïÎïVðÐðjð ïlíVììœì|íhîôîäîèîÊïñPñHð†ïÜïèð˜ò¾ôÄöløjúäû0ü¼ü"þ²ÿÂ\ âîÄ´V<ìn Ì Š Ü Ü ¬ ~ ì ø Š þ ö 4 0 H V lªÞ  "":0‚¶ZDTŽZà˜@b”| ˆ 6 ® lØš.èæ²dúh¸Œ  Ì p X Zx€Ìânð ÿnjfìÿxÿ,"”¸N&lDÌÜÿXýšúîø´ø†ù¾úôúªúú ù¤øÄøHø`÷B÷Â÷ øØ÷døú|ü\þÿ&ÿþþèþDþdýâüÒü²üü:ûVú$ùÐ÷8÷f÷øHù˜úûêúâúâúôúûîúªúØú2ûªûjûPúNù0ù’ùøùøù\ú:û¦û´ûRû ûûhûÖûPüˆü®üxý¬þbÿºÿrp<ütx`FÔ@ôN b  ’Šbh*VøÒ\òˆÆD„"þ4J€ò®¨l„ÿ0þ²ü`üxýÜþTȦJ¸ýÖútø ÷‚öBöªõÖôPôÆódó”ó€ô°õ†öXö õVóÊñfñ®òŠôâõVöºöB÷÷,ö˜õ<öööžöXöÜöløäù‚ú(ú ùjùŒùúÂúÀû.ýÎþØÿpvèÿ†ÿpÿtþpüúrødø®ù^û¦üþÂÿx°ÿN¢¶FÒ„üJâÚêæ@þlüúûÖüVý¦üûRù–ø’ùDûbüêüöýŠÿ¼ÿàý~ûtù&ø÷ öþõÆö,ølú ü@üôûüFüöû®ûzûžúàøè÷¶øªù ù÷ÈôDóÂò$óÐó,ônôFõ|öŒ÷Jødù,úHú¸ú\ü:þ°þÔý”ü^ûû û¼übý¾ü ûÖøn÷H÷øú”üþlý\ü(ývÿÚàvÂ44¸HlB@â&„x  – ì „:„&@ÒÌÿ„Ò°Ú ì øœzÚ øFäàj.,Öòš˜ÚVÞ Ì ¨ Þ ò Ü’t~ $ j> Ò , X P ž ,PØ2ÔÔÐàÆþ Œ¾ xt”‚4´ì€ 4 ^ ’¼ Ü D ~Þ XÊ €âžýû$úpû¤ý¨þhþ ÿ8VLˆâÆÐTvò~Ôþî&²|– ú V € | Ê  Ò j ’ F Ê ²Ø\l,”Ä>| †¬*ÔR:¼Ä  (>Èê¸Ò r ÆL¬ þ 8 ÖJ¾bºÆ ° 2 ( ÌÞ|þýêüþÒ˜xèØppòÿ”ýÿ:¨ú$Hü&Z&ünùJøXøþø‚ú8ý²ÿŒÿ°üþùÈù¨ûÐýÜþNÿ8”€TàfVVºÿfýàý8Ž"h82¤ôÿ>ýVú®ø¼ùü"ÿÚ´ÿ þŠý–ýöüHû¦ùJùú`ûäüþýrþþÞü’úd÷LôºòóÖôr÷6ú>ü~üRûbúVúHú˜ùhùHúdû ü þŠþöýºý2þ¨þÖþ„þpýèû$ûjüÌþŒPRþ üØûXûJùÌõ>óóÊô÷dùû^üXýýxûðú´üÎþ–ÿ@ÿêþ&ÿÜÿ¶þüîù˜ùÖùèø$÷Òõìõøîúýºýðýîýžü¾úÚùäù$ú¸ú„ûXû6úNùäø²ø(ø"ø~øÞøÂùÚúhûZûxûRü*ýý¾ü¾üBü6û‚ú´ùúøÂøŽùšú2û¦ûXü¤üHý ýîüxûÄúDû¨ûÞûû°úXúdúTú¬ùîøùàùúù´ùDúèúöú”ûÔû†ú^øÚ÷ ùÜùÀùJúdûbüúü¨ünüÀüúýzþ¾ý"üòúdü(ÿÀv^zdfôÖÚPðVĤÒþô°üœîˆ Öþèþ|ÿðÿ8ŠîÞFò0ÖP†: ˜†Tàæÿ¸þþþtþÄþÐþ(ÿ,ÿ ÿ¤$Ðtú@´"ÔÖH(Î.‚lÀ^ü:^ŒÞ¼|B²ö¶p@œ~°ò |  ”TØŽròâ¾P,\‚Ĭˆd$–®b´&Ä– ð¨<*ÂjvX0 ìÿ²þ¶ýØý¸þxÿ¦ÿÿ’ý€üºüHþHšÒôúÿÜ|ºv„6ÿÐýÚü¸üýýžüÌû²ú¸ùBùJùÒøê÷ø÷òødùèøæøìùÔúû^ú‚úÊûîüTý¾ý„ÿÚ>°@š*²˜(²ž Ân˜à¸(Ø<ð&´\Î4  6¼&L|<: V ˆÖšÖîÒ6 ² Z ~ ˆ z ž b"R ª – „ † œ h ž ² ÖžP(Ò€‚¤¾þ6ÿ¤âÿÂüÌùüø„ùxùŽù¦úü¸üâüýÔüNüðüÌþìþœý„ý^þ ýÐûtûšü‚üèù„ö¬ô õ¢öøöXõDô÷¤üòJÆþÎü’þrHN¦2$<4RLXêÄý8üüvüþŒX¾æt6Øÿ.ýÞý6‚Vîb@.HÂTlöhþêà6 @ î n  ÞJ ” ˆ¸jœx@2˜ >  Ô Ì Z âÄ8úp€j âXô,þHÿö Š L Ò 8 6 zІ| <  &È®8º®ÔdÿbûzønöxõÜõš÷ùäøÚ÷¶õ¸ñÈîNñòö\ùdø<ùøû ý<û"øòô’óøô´öøõóðÞðôJø ú4úØø>÷ºõÒó òð˜ïï0ïžïÈïäï®ð¬ò¨ô®õÖõ2õâó–òBñ”ðâð:òJóŠò<ðîØìFìPì íÆîñªò ózóÆõøøæúèúfúú2úüúÈûˆûôútûþBŒLÜÿ¦J8®r€€6€¢: d n âÞLh4  > X  Ì Â Ä Zâœ|8Ž@ˆ"¾ È B¤ b ª x ª P Äœ ô ~  à X t d ¾²8Ì ð  >XÜvæÒ–FÒb0ÿxýLüüû`üBüÞú(øÚôòñ`ñ¬ñ0ñ*ðöîøílíòíxï¢ððî ì²ìî|ï0ðÄð2òBô`õJõ8õfö|øþù>ú$ù:ø²øˆùÂù„ùúþúŽú~ù,ùLùzù~ùùzøøVùúvúòúàú¢úôú˜ûâû’ûû û¼û¶ü¶ýjþzþÎýXýœý2þÆÿ 윦D"6þr Ö Ú Œ „`þ¼Zl 0 tRt DøöÐ„Äæ¸ÐĆJ8r\–”ìÿÎÿÂÿÚÿVî$„”ÿÈþpþœþ<ÿ"¦ÊÿìýZüdû6ûÈû„ü>üúúšùùùdú²úbújù®÷ö–õ6ö÷\÷8÷žö€õ¾ôàô´õHöˆö ÷Ê÷^øføô÷ª÷¾÷ê÷þ÷Þ÷*÷$öNõÈõ÷Æ÷"øžøúø”ø¶÷Æ÷ö÷P÷8÷Àø û²û‚ûüdýŒÿb̲šÿÀÿîv¬š”ÿÂý‚ýBþBÿpìÿPþàý>ÿ>âÿJÿèþ.ÿ²ÿvÿÒþ ”ÞrŒæúZŒØ– ®¾"RÂô ¢ú ô$Êè~Â6êl<ЦЂöl2 >–L<¾øLBþübû0ü®üªû€ú~ú*ûÔûªûtúºøø´ø ùbùÎù¾ùôùÂú¶ûýxþ"ÿ¤ÿ`ÿ þ~ýNýDüü<ý2þvþ¢þ,ÿ,ÿÈþÞþ 枬ºîÊè:`À¦|¤²0R¶äêÀˆÿFý$ü”ûàûVüÀûÖúNûhüŒüüûÚû\ü.ýþÌÿø*оª   L¶T ŒVúDpþýžüýÎýüþøÿ0ÿ¾üûHû*üÚü†ýúýÐþ*¤*|öÿ:ÿDÿ$žàPj4²ý¢ûHùÈöŠö&ùðüâþÀþþxþ¤ÿöÿžþTý–þxŠô’ü®|BBb†v–HÆÿ4Ĉ4²fêýÂü&þ²âò\†x~üJú^ûbþzpàtÆ2° È´vØPvj’ H ¼ ¤ Œ ® j † t  žDÎÒ@ÀÄ,p ê 0 ² ” ` j øD$ä¢püÂý¬ûêùø¬÷ùÂú<ûDúêùbû ýêþ2þtýHþºÿÂv<ºìr6þþlýnûù´÷v÷÷*öbõ õ õ,ôÄñºíêöèôéRëBë$êšé¦éÜèöçè˜è2éäéëPìðìÀíïâïVï¨îŒïÞðòð¤ð4ñ*ò<óFô õ¬õ ÷jùöûœý4þþ(þúþÆr<ÌÈÆ .Vúþ þþÎýdü¼ú$ú<ú úšùnù¨ùìùTùZøøÔøÂúnýT¨ F& Ð Ú š < L t ‚ Òà® ¤   °Î¨z¸ÎòX”„ÿpþhý0ü¦ú(ùrøVø0÷Øô¸òÒñ¦ñêð ï’íí´ìúëâë¾ìÆíJî~îzî”îžïTñºòóÊòÔñêð ñ(ó„õ¶õôªóxôÚô¬ôRô"ôüó òðêîìïòzôÀö ø*ø ÷B÷²õ6óNòróÒóòpðÖðnòNóbóøó¾ônõRöføVúêù¶ø˜ø†ù|ú„û~üjü¬úœø"÷œö$÷øúÐû@þš¤V`f°‚¬B ö .   ¨ìbž ’®´þ8ü‚ühýŒþZ¤TÊÿfþÔþÜÖF¾P€2dTò>òÀ¾ˆ°JŒ8̆®\l^r6†n’ÔjÄþÞüý¶þ ZjÈ0Øàÿ*ÿ2þJühú&ùTø øÌøðúŠý8ÿNø¨úF*Ðÿ̾üð>ZxŽd€(\² ŒÿZÿšþ`ý˜ýÌÿ.Ú´Ḭ̀èþöîN.>.~Ú†¼ð¶ÞØÂb ¸6†@jRt Ø   ê  l " ¤ ÚÊ~ \²TÐÄâ@ Âæ\"D²hât Ü < Æ & ¶ N <¼:¬î~ÿ®ýþzÿ˜   ÿ.ÿzvÔP°èÿv º€¸ÆFxð¨D¾ÿ¨ÿæÿ‚†0Jÿ@þPþ"ÿìÿÊj.¸ÿDþdý¼ü<ü(üüü¼üþÎÿ¢èÞÞF^ ¢ÿ|ÿÿ|þþ4þþÂý4ýjüØûÜütÿ@rŒþÒüšü–üèûjûðû¸üÀüýlþ°zþôdžÆÚ(òÿÖþ|þþ”üÄúÆù~ùÎù¦ù”øÈ÷V÷¤öFõ@ôôónô õœô$óÜñÞðdðøðFò–ózôdõ8öVöÎõ&öŒ÷@ùòù>ù°ø:úý þ|ý¦ü"ürûˆúÎùlù€ù,ùö÷ ö´õ^õ õ¾õòöèö,öàõÚöò÷Â÷`÷¸÷¨øùLøööföhöö˜õö¬÷ ùBù2ù>ùð÷ ööV÷øÖù¶ûFûÈùúúûþþÒÞÜž‚nBŽzJ ÄÄ\Ôˆœÿ<þ4ü¾úXùÐö ô\óäô&÷$ùžú¤úrøÊõõ¨öÊøû¢ýÜÿfÂÿ>ÿâÿœèÿÿ€þfý¨ûú<ø÷Àö ÷¬÷Úøú²ûðû:û:ùÀ÷ ù¸ü”ÿìÿpþòü˜üfü$ü‚üÒýÿ>Þþ~ü ú€ùbøÆöVõ,ôèòñ†ïÌîî^íííÌíÄïòòZö¢ø¬ùBúû~üÖý|þ”þ¢þžþÈþbÿöš ~ æ ,B‚ö.Ô B , fꄬÿÆ~̆ b24D Ü b ö.h¼¢ÿýú´÷ø÷Úùðú.ûLüŒþ¼|rôî  "¬jü ¨ ΄ ü  ”øXÒ tTâ2P ^ & ,ðÿÒý üdüýàýHþöýœýJþRÿžþýˆüÔüÖüzü®û®úLútúVúZú,úZøV÷2ùZû@üÈüèü*ý¢þ´ Òÿ¨(¾l® ø  0 Bà Ž PTÈŠ$ÿ²úv÷NøØû¨ý@û¤öZô,öÞøšùDùÀú0þüZ^ìÿ¾Ðð  Ænz L & ¦„ ˆ° L H * & Ú °bê ” P  „ Ð j Òè|Z & ê Ö ª.h8ÞR ¨6¤$&hÄšœò~ È ´rÔ˜*°¾   b BОžÐÿ<Nÿdý ý„þ¤Jn:žÌnÿøûÔø¶÷Àøúòúœû<ü\üúúrøœ÷:ù†úxùööõ~ô0õôö¸ø´ùXúDû<û^øÆóñòþô´ö2õò²ðhññüî2îðdòxó†ó¬ó^õ>÷H÷¨õÀôõZöàõFôòÎñÜòŽô¬õ¨öÀ÷Üø„ù ùŒø`øÐø`ùÜù8úTúbú&úøùhú üÄþ^¤Öìt’v– , œ*zvˆØÀ8¤†ò€Ôê–’ÿÒÿø–¢Êà’Z2ö–¤Ð è^b&~êŒf4ŒzÞZ6 (²ø˜†ðRTFNäÿÿÿÄþ¢ýüúúLúVú ûJû&ûûæûýèýôýÌüvú’øjøîù`üNþjÿdÿ®ý|û€ú,ûèüÒýÈýýBüpûnú‚útûxü\ýÔý¶ý¨ý¸ý\þÀÿLÖrÚ>²z$’üì|ê& & ¬œ z þ ž`ì$0.ÜDHÈšTª6pæz¢þúý$ÿØ” Pb"ÿlþ¼þ¢ÿ˜Lˆd&Ö–j4Þ€ÆLxÿÿ0ÿ2ÿþ¢ý ü ù¸÷t÷"øÄøúøÜø¤ø ø´öÊõ†ö$ø úðû¼üvüØûšûdû ûûZûâûHü`üâû ûpúðùùæ÷P÷x÷¨÷¶÷¢øÂúnü2ü"ûDû,ýúþ0ÿþ<ýVþ:HTŠbŽàÿ(ÿäþ„ý€úŽ÷Ôö@øüù\útù ø~ùÌû^ý ý@üÂý¶<öØ”n̬ÿ`Æ€&ÿÜü’þFªÒDüþþäýHýèüžý\²løÚÿâÿÂþ¶ý6ÿÖ<Âÿþðý ýÎúæøÌøvù„ø>õ$óÆõ(û²þÿÄþjýûžù úìûJþ²ˆ¤ÆD|šf$ZýýöHR Züžø4öºõ¢ö8øNû~ª îVÿ¸ý"ýjý–ýÌý¤þÀþ@ý$üþhÖ> Z ÔrPXòý4üÿôÐ4 ² l ~"  Z  ä †ÌFˆ¤.PpØLúþöî÷Zü²Þ0ôb”þ–ÿÞÀ^,: $ ø ü® : – xBŒÌ^tÒxt4$ÜbܰdDh˜ ª š Hªÿýöûpû~ûüû`üÚüœþøºšèù€òøí¨í’ï(ñLñ¢ððð´ònôÐô*ô.ôšõ8÷Ò÷š÷€÷Þ÷hù¢ûjý¼þðÿJºÿXÿºÿ¾” œNT  p ’bˆê¢€æd–V:°ú¢œäò.,(ÂŽÀ þæFh 4 >ŠÄžŠ f<j2°Ä„ Z¨vÞL†$´ H ° äÐV . L z .p.ü,H¬ˆz|úú²ÿšüÀùV÷dõ8ôRô õ ö ø†úFüZüHûˆú úû2ûûûôú û üýRýÄüpüÀüÔüšü¾ü–üXû¬ùù¦øTøùpúîúŒú2ú†útú¾ù2úlû,ülýŠÿ<˜ÊÚê¬2š°¶â 4 4 Ô 2 ’tæ\ ª ² , ¤h œ Š (° ž d 2 Œ \êè–b ê Œ .  Ä@¸– . h ¶  ¬ Ô < ¦   ô ’  LºŠ´ ðH¼‚ˆ˜t⤺¤ÿþrý¢ýŠþxÿšÿ4ÿ,ÿPÿ&ÿœþ´ý²üþûXûjúÊù úòúÔû¢üÌý¼ÿö–ö†¦L¼Äºöv$Dèp,4T  ¤ LâèX À¨¨øˆÞ Ü ~pòšžtÐFÀŠr°¤òšZªf\šœÒì¸$j6Ø,x°ªºÖ¤^ÿpþZþ\þ¬ýàüÂüÖýxÿ6>pØ0~œÆ²ÖR–òTÀÿ‚ý˜üJûÊùôøùHú ûúûü,ýÄþÎÿŠÄì´¬î4˜0¦òì’–¸¶öHÚ´d„¨þÞþ®ÿ¢ýpüÖü¸ý‚þèÿ¬ür†ÿŽh’¾¦&À@>ðÿDÿ¤þêüFû^ûfülü û*úJûý²ýdýšý°þÐrªdÒRàŽÿtýÆû~úòø÷Œõõö6øªúÄúøvõõ¨ö¨ø˜ú„üþþÄýæü–üLü„út÷êó0ñ€ð˜ñÄóRõvö^÷ì÷D÷õ2ó ó´óô’ô¤ö¢ø@øö>õ8ö‚ö õ¶òêð~ðfñ²ò(ôHö"ùlû üû`ùRøØølúÖú’ùdø ù0ú ù\ö0ôvòñØïðHò®õœùÆü”þŒÿ¬ˆ²ÎbnÿfþÈÿÒ\ŒÿVÿ"rä6Âÿ†þnþ°ÿ4˜8ølŒèÜî†bÂhþhýöýüþØþèýý.ýþFÿtÿFþ²þül†0 äüLúÐ÷°õ>ôâó õÂö$øhù úÐú¢ùžø*ù¦ú’üHþ`ÿÀÿÚÿ"Úÿ¸ý’ùHõ6ódóêó®óròVñ²ðñjòøóˆõ˜öœ÷úøhúÀûîü†þd¢Œþzû”ùâøøÂöbö’÷$ùÊù®ù¦ù4ú û ýnÿZ°Öhhˆ°þÈü¨ûªû¢ü\ýXýôüŠüý ÿô B´ÀPthຠ¨Ì’â¶¶‚Ș Z z ´ ¨ T 0 Ò  | À Š î  ž ¬ r  ªâÄü~æúÜô$(¼¾ÌÀœ*<¬ÿ†ÿ6b<$tvÐ~¼–4\6&¾*R’VÿºþDþ|þîþüýˆü@ü ýZý(ý ýŠý þäý~üÐúú&ú*úþù<ú&ú^ùžøRùòùPùÒùŽûŠûúÔùhúdú¬úûÎúFûÆûøúrú0ü ýØû0û2üLýüýjÿ~ŽH¨ÿ´þÖþÿ$þýý˜üÀû`û û&ûÄûÚûØûFü ýnýXýVýäýþþÿlÊ,ˆü8ÈþÈÿ°þ þ2þ&ÿL,ÚfDÞœÂv >Zÿÿ>ÿ"ÿÄþˆþ‚þ^þ&þþþ*þbþ`þþ¼ý4ýVüªûPû`ûÊû<üŽü´üþüJýÎý´þJÿvÿJÿrþœýŒý8þdÿhæ*æôÿFÿ>ÿèÿ.®ÿ¾þúý–ýný~ýîýŠþ¼þZþ¶ýpýdý¾ýtþÌþ¸þºþ”þ þÊýþ”þÿ¨ÿ6~nN`¢Òbr,üÿ´ÿ„ÿhÿêþ’þ²þÿ ÿp@`Êøÿ ÿ ÿÜÿ~ðþÚŒnŒr0æÿ ÿæý8ýPýÚýdþ"ÿ0°À"àÊ¢Z~„úfÜâ6xúœžÞhÚ®XÌxbvÎòàn¨ÔBú"f¶\:Ú¼„À€ò˜X6ž”>¤ŒŠ*¶^Ð,ŽÐPÄ¦Þø„4\h–(ÿ`ýý†þúýHüšû²ü$þ‚þÿ>FvÜpB °ÿâþþýŒý.ýBüÈútùÂødøø øVøù–ùpùðø¶øùdù$ùúø:ùÞù¤úžû¾ü(ýôüÂûºùæ÷Œ÷ê÷÷õdõ€ö ÷€öJöº÷¼ùTú\ùÊø>ù€ù˜øÔöÖõæõ\õØôÂõä÷‚ùú*ûrý~ÿ&VšòF~šT (ÿèüfû’û„üpýìýúþf,ÐZÿŠþ:ÿ¶V¤l">šÀFF°þ’ýRýBþàÿ Dbæ^¦rXèê¦<Ú PðÎ „ | Ø  „<Èêlz´úƸPªðzlPÖ  ( t ÎŽÖÿÜühü¬ýÚý’ü.úôö¾óêñjñ‚ïNìlêüê&ì¶ì2ìVëªêbêêÂéÔéJêþê:ìÒí¦ð†ôö†óâð†ñþó^õ ôòîðñòºò¬òFñPî^ëêlêëÖë¨ìèìŽë4épèøè¶çæäØâ â¢â†á>àpß ßrÞØÝHÞ¾ßÔàÎàbàŽàbâðäææ¼æÖèÊëFïhó÷.ù¼ùúùºúvüÐþ ôÿØÿäªÒ¦äÆ<`Ür¾Ø^rº|Pÿ0æ.Œ4úŽˆ Ä z ´  Æ Z ìî~Ò r ¬  f , p  È N ” Þ  *Š~~Ö¼ÿ¬þtþ@þlýÀû0úù`ø–÷ìö>ö¾ô´ò$ñLð ð>ðÞïºîDíìëðêzë®ì’íìíbîï:ñžò”óbô$õ”õÄõ´õÌõ&öxöØö`÷Ô÷løÖøÚøôø0ù4ù´øÚ÷÷P÷nø~ùÜùú4úÐùvù’ùFúXûÈûüˆüªüNüüòûüû4üôü"þÿdÿžÿ X˜PÐ0ÞœX†È¨D ˆ ¦ F Ì î Ø `  B î  6   Þ ’Ò¾jTŒ†ØlÄĸ@4Òºú*¸ –€þVnšVÔ‚ˆ¾øÊL Ô24ÈÄP(â@À¶øœ®„ ¶Î&†ÞhÚ˜8FhšX6ÜÊh¬ÖÜ$Žè,Ú¢îä L.,Œ‚¦LxÂö*j‚ò¾ÿnz& ¼`R²z6r*¶$¸ZÆðÿBÿ®þþ¼ýôýZþþªý„ýˆýþ.ÿ˜ÆzxÂÿâ>*¨L6êÿ68ìØ¼‚šbHvðb¸Ô~HHDÿ0þ þþ þ®ýžüŽûªúÐùLùŠùDúújù®ù^ú®úvû˜üºü`ü6ü:ü6üäûjûVûÊûü<ü®üýýHýZýœüöûèûÈûHû û>ûôú¦ú¤úÄúûäû¤ý~ÿ f,P²hôŠxæ´êÆÐNÿþ~ýæü"üVû¬úVúúÆù`ùnùrùfùxúüâüJý$þ~ÿ°¼Ž Šàÿ¦þ®þ~ÿÆÿTÿ0ÿºÿLr^8Îÿ,ÿœþæþÆÿ¨ÿDþ¬ü¼û4üÚýÿ4^ÿÚýý0ý”ýÞýzý ü.ú”øùTú:ûûrúîùúàúˆûäûüŠü&ýäü4üÌûâûüJýTÿ&L¨>þ&nÊ&àü†p–.ìØ”Î:djœ|8Ô(|46Ø´bd¤¦Š–x\n ® ~  ö œ œ Ì Ö ô ö zÊh@ Â Ú  ~ ‚  \ €\0ö B Z ®¬t|4.þ2ýÔý¤þxþþþ²ýýýôý–ÿ®ÞºüFÖjP̤€ ~\ÜPDLþìûäú¤ûîüÀü*ûFùŒø´øpø@÷þõ8õ^ôVó¤ò†òóâóøôÚõLö^ö,ö:ö*÷Â÷òöœõ õhõŒõõ ô†ôÐô´ôôÒôˆõ8öööö†÷ øù–ú€üèýŒþÐþ(0~tÀFtp2ÚhÊÿÚýÐû¨ú˜úûûbújù²øNøFøLøæ÷ìööìõ¨öNø„ú0ü¤üÌüÂýZÿª*€ú`„H¢è®âž2<¦Ú´®Ž¸~†L B"êÎx|ÿüþXþŒý®üÌû>û:ûhû<û ûˆûÈü^þ&ÿÿhþþ˜þ@ÿ¼ÿ¬Ò,", f¾ÐÜ,˜®†ÂÆhZL2ø6–Øj6F Îæäÿb,”Ä*:FúþÀHânN>äÿÐúJ ¤ÿNÿ´ÿX,šÿ2ÿ ÿ„ÿŒ V<ÿŽþ¤þ¢þVþðý6þ þXþîý`þnÿ@JDb @ÖÀÒŠ¬Î¶2BÈæö¦F|¾,bþxýnþºêºÚ”ÿÌþ’ÿH,DÚžÊT^Üô4¤´Ü¶P âæ„|(L$Ú¶ˆfä B (ôVÿþ@ÿ,PŒ$ŠHtF`N ~ °æV®v2J,ˆ\LdR¢v$êfÐ$ ZÖÂΘl6®>ÿ¨þjÿ –¤º`˜þúüŽü~ý4ÿ >z@<æDþÿD¤~ìÿÿý2ühüþNHø:ÚÿRþæýœþÿàÿBÿJþýìû ü$ýþXþ`þ ÿÞÿþÿzÿ"þðû`úzú¼ûÀýÈÿœ˜ÿ’ýÎû6û üHþ”زDfþÀü¾ûÞûXýÿˆ¢(ÿˆý¾üýDþÀÿTnÿœývûŠù´øœùLüFÿÄ$¶ú,ÿ‚þ.ÿ.LDnxþFýVý®þæ\ ðžþÀûŽúÆû†þ*ÿý¬ýnÿÚ0fÒ†¬ÿ¶ý,ýšýNþÐþÜþTþ0ýæûxúPùÐønùÄúBüýýöûú`øøjù¨ûôýrÿ`ÿøýJü ûrúnúdûýRþôýÔû*ùîö6ö¾öÎ÷ù–úÐûüû’ù ùšù˜ú<û€ûŒû ûú¢øª÷¢÷VøæøJù^ùùø4÷÷â÷ùXúÐû ýZý†üVûØúhû®üÜýŒþbÿæšnúöVšT Æˆâªdrr 4tþæ¾ ú„&D–"D:NÔšÊR â 8 x ^ â Ê Ø V ¶ 4 ( ’ú**r°6>ðVŽÎ&FžnÔúÿäþ¸ýªüÌû2û¸ú"ú˜ùZùˆø÷šõVõ6öT÷Ú÷è÷˜÷4÷–öúõÖõöjöNöÀõ õFõ@ö¸÷ùÊùüùàùÎùœùÈø÷¶ö öêöR÷ª÷Ì÷î÷,øJø²øÄù˜ú(ûlû^ûÞúvú"ûîüLÿVÔ°HR ’ n V z .  ~ R < Ì º :&öjr à T\¬¾ÚF„ º–btÌ2®¢Òô:ì ¢ƌ¶jŽzæÊ´¼*¶Öœ Î ¨ à V | >äÈòvˆ|‚¢h ÿœÿjÿRþúü¨üþüàüðûûžúÆù–øŒ÷Ðöêõxôóªòó óÌò~óÎõ^ø¦ù>úûü<üŒûTûäûnüúûûŒúLúôùú$ûnüvüÂû¼ûLü>ü°ûÆû‚üøü®üZüÄüÞýÿxÿ–ÿ>8‚¢¶ÿüÿ4(xNê0Lʬ†ZÒÂÂþ8v²  D  R h ~  ¾˜Xž¾Šî¬–@|p0–ÊjæîZb¨ XÜøª‚¶\4Ú¤Ü:lÿºþÿÿ`þBý¬ü°ü ý®ý4þXþøý€ýüšúBøH÷TøÀù°ù0ø¨öÈõ8õˆôØóüó"õ*ö¾õô¢òÄòžóöóòóhô\õ¼õòôòóîóÄôŠõözöö¢ôjóÐó8õöüõNö¢÷Êø´øÜ÷ð÷:ùRújúŠúÔû^ýÖýBýý¦ýþÊýÄýÄþ@0€–^z¼ÿ\$Ì2à¤pèP¦äXDÖD\P.V€à*vþ8†2\j†df& |RF¨œppz΀Һ<ÿ”ýüûâú€û„üúü”üäûdûûÊú²úäúæú4ú$ù¢øù úìú\û6û|ú²ùXùzùpùÌø øÒ÷,øàøœù*úXúÚùÀøì÷øèøÖù\ú¤úÚú°úú^ùhù úÀú8ûšû ü"üÔû€û¢û$üžüüüPý”ý¢ývý$ýìü(ýÖýÄþ’ÿôÿbøˆäHìt®Š:Ü@ ,^H¸ð^Z̆Zj8–êVòfb œ$¤L2@NFÊ:^ÿpþÌý°ýþtþŒþ0þýÜülü\üÆüfýäýìýrý´üìû|û^û\ûDûNû¢û<ü¶üÌü„ü8üü6ü¦üpý þöýýü¼û"üäüªýpþôþÿºþ¢þèþZÿÜÿ>h\FBVpŒ†lŒêHTÊÈÿ¼þ@þ~þÿTÿ@ÿÀþâýÎü*üVüfýÐþîÿb>ÌÿhÿdÿàÒØ´€†ælî^Ðô€~r¾šÜ òHÿäý$ýþüzýþŒþäþÿúþ¤þHþþÜýôýxþ&ÿ‚ÿJÿÄþZþþþ€þ"ÿ€ÿÿ8þ–ý¢ý þPþXþlþ²þJÿÎÿ &,äÿÂÿ(¾˜Þ ”ÿ¤ÿB<2ÔæÆ¢|*æDHnØ> 8ð^dhèXp´|ÞÄ–’Ú®ÞÞ†ŽèȪΤÞÀ®02 ÖºFþ@ìzflNúÖt–|nhd00FRPT$ ˜v ’.¶ÿtþ‚ü û´úºúúù†øÖø:ù`ùšùdú®ûàüÂýþ¾ý@ý<ý²ýþý®ýBýœýÿt–|ÿ˜þìþ.¢¦:,¾¤äNrdX‚ú.h:®Øx¼ –Hò`&à(â¸4¢Æ˜àÿ0¼Î"ª” æR l ð@öJ¢¤€B°PlrÄöÿ ¨~<(†îÿNÒþrvÿÎþ(þàüÜúTù@ù”ùHù”øùÜú6ü ü ûÆú4ûüöü¾ü2û~ùJù8ú ûÜúú:ù¨øˆøâø^ùÈùšúØû&ý¢ýýVüÄûdûÈú&ú„ùÐøü÷x÷H÷4÷‚÷ö÷JøHø¾øâù”úrú~úàûþæÿ¾f:¬hx2ÿþÎýÀþôÿfÿvÿ(êZH΂ Ê ˆ ´ð€J¼\ް$†Hˆ4Pö ¶ úªÐ¾&Jxþü~újúBûüPüvüŽüÂüŽýÌþ¶ÿzÿœþ6þ˜þÿtþ&ý ü¤û¾ûÊû®û<ûªúúÆùàùúbúˆú|úbú€úìúrûü’üØü†üÎû ûHúhùžø4øô÷D÷ö²ô˜óòòŽòNòìñ`ñŒð¶ï"ïÎî¨îrîäííHìüëXì$í2îïÄïtðšñ:ó´ôÌõðövø úšû®üZýrýýÌüý¶ýDþzþ¦þÿ¢ÿTšÒâ¬4vÿ®þ*þþþúýÞýÖýÂýtýüü²ü¦üØü"ý†ýþýxþöþJÿLÿÿÈþ°þ´þ¤þnþFþ@þxþâþ|ÿˆºðrf¶,tbô‚: ¼ Ä   ø<XlZ8@Š<(>@îÿTÿÄþŽþ°þÎþ®þ6þŒýøü–üXüüÜûœûJûêú¸úÐú ûNûšûÞû0üŠüý`ýŽýxý2ýòüìü4ýŽýºýˆý*ýÞüÞü ýfýˆýxýXý4ý8ýpýªýÊý¤ý:ý®üFü.ü>ü(üæû¬ûˆûbûTû~ûúû~ü´ü–ü\ü<ü~ü ý”ýæýèýÒýÖýþhþæþFÿ~ÿ¦ÿÞÿlÎ8’à,ˆø^Žx.êÒðè”L>DZ~¢ŽX8>J^NˆàØØÂ¤|dtšÈÜÂfT.îÿˆÿÿ˜þJþ0þ(þüý¨ýtý–ý"þ þþþjÿ¼ÿöÿHÊ’@†Pò¤H–ØÿpÿDÿFÿ‚ÿàÿ:^j\P<,0 ªÿFÿ ÿ8ÿZÿpÿzÿ¢ÿÒÿ2^ÈrRT\„Ø>f:èøî~²Ú¸LÖàjÔÀzfÊ@Zx†d&¾ÿHþúüü\û¶úâùùø„ø~ø†øÔøŠù"úfú¬ú2û¸û üšübýþXþtþ¤þ´þ”þ„þÄþ&ÿhÿ\ÿbÿ”ÿòÿBH(úÿ6R†ÿÿÂþþÂü²ûlû¸ûØûnû„ú`ùXøÆ÷t÷&÷ÚöÚö÷÷¦öÔõnõhõTõõäôTõ&öâö6÷N÷˜÷Nøªù û–ýÄþÿ~ÿ”hJüJRˆD*l°d,bFPÊŒdüöþNþtþ¬þøý¢ü`ûÖúæúBûŠûŽû0ûôúZûüŒüÄüøü.ý|ýþÿlÎŽ<pŠjLrâ42höð&’¶V"ÿXþîýÎý†ý¨ü2ûúÔùNú²úFú(ùøä÷føªøløNøÄø\ùœùlùùÌøù$úüÊýŽþjþ(þxþnÿÊ"RŽT¸DZ – B ŽØB®î4„ªr¼þŒýzüûÚúVúÎùNù´øøô÷LøÌø¸ø8øž÷H÷x÷`ø°ùÎú°ûxüý.ýèüòüŽýZþ°þ4þŠýRýšý þxþ²þ¼þ þLþþRþ„ÿæÖ`\œª.˜>òÿ¶ÿ~ÿ>ÿÊþ þlýœüÚûtûŠû¤ûžûòû ýPþÿdÿêÿÀ$ì¼D\PÞJârÎâðî¢DRØL*œì"\´<æÂÜ"6Âz4Ìÿ&ÿ|þþºýý^ü4üvü¤üjüÞû*ûJúŒùFù„ùÞù@úªú@ûüöüäý¨þ&ÿšÿ*®þ0xÊĈ ”ôÿvÿBÿÿÚþŠþ@þæý€ýýæüöüýý|üÄû0ûÔú‚ú,úú ú*úpú²úªúúœúîú<ûrûÊûü<ü<üFü˜üúü^ý¦ýæý$þFþdþˆþÚþXÿäÿdâR„j8FPÆ„rfNFÖÿŽÿRÿÿÐþ¶þÂþÔþÊþÎþÚþ2ÿÈÿT¾àâJˆŠ˜~z,4ÞlXîà|4®ÐäBjz˜¦Š0ÎŒp†ÔÔ¾ô*,øäÀ ˆ^$ê²t:Ȇ^dx’¤ŠR6Jh`:,<T8¾¼œ\ÆÿÄÿ†Ê¾¨¸úF\f‚®¼–rz–’JÖvXn’–Šv,æÿžÿXÿÿÌþÂþÒþÞþîþÿ8ÿFÿ$ÿàþœþrþbþtþªþîþ:ÿ˜ÿœè:d¤ò\®Þü2|à6HÚÖîüüâ| ÔÞðÔ’R& ÜšFêŒ2 V–®žªðP¢ÒþBn˜´¦„RâÚbÎ&ò FÖ¨†Bö¨rT"Òÿfÿäþnþðýjýøü´ü„üjüdüTü2üöû°û’ûªûèûôûÂûvû:û&ûûðú¸úŽú”úøúnûÊûü@ü¬üPý$þÒþ ÿÒþxþ>þDþxþfþÔýý²üýæý\þþZýÊüØüFýÎý`þúþzÿÚÿNävÞLÖ¾ô@"p‚ºR ¨ è$„Üü¬ 0’þ>ýìûJú²ød÷hö®õŠõúõ¼öD÷Ž÷ øàøôùàú”û üRüŽü¶üªüZüâûlûüú\ú˜ùúø¢ø²øôø(ùþøžø†øùæù®úûJûjû–ûºûàûüü ûû¼úêúêú:ú2ù\øð÷¤÷F÷Êöøõðô ôòóüó²óøò>òÂñ„ñrñšñðñjò ó6ô¦õD÷ìø„úüpýèþZ¨À’*¦,°òÖhÔhZˆ¼ì6|¬ÄâÊ€4Ô*2†^”œLÄ.œâPššŽÈRþh”¼–àúúöøP ö´FÌ\  Ð „  € Ò  ö ¨   ˜Ä\P*˜þ‚ü¸úVùdø÷¾ööæõJöêöx÷Ò÷ö÷øø”øŒùÊúìû˜üÄüìüLýÂýòýºý@ýÐü¢üöü†ýúýúý¶ýžýÜý$þþŽýÚüTüRü üÎü¬ü„ü üôü^ýÊýìýtý¢ü2ü¦üýþÄýÐüÊûÜú6úÜù¶ù¦ù˜ù²ùúù~úfûzühýþ”þ*ÿêÿæøþàìÚN¤:œð<¤2¦æð@äžFü¶`øÿàÿ"`ZþÿðÿäÿØÿÚÿJ¶8šÌØÂ®Ð,v”Œ ö`À b®î6¢*šÞvö<‚ÄLŠvŠ ú¦âbÿÿÿ`ÿØÿ,>\Ö¨V¾0üèªJè~¦, ° & ^  ‚ 0  øŒ~â>Êf6P€rΤrT$öØâÔ–Æ6(JüìÎÀƨLÎÿvÿšÿ¬@¨&¨’Ä’T6>’H\ˆ*V˜B Œÿ¼þêý<ý üdü~üŒühü$ü(üDü2ü üü|üúü~ýþÄþ\ÿ°ÿ´ÿ¶ÿÒ²$€  V2²*ÀvrÊhôD’ð2¶ŠT˜Øf šÿ6ÿÿÿþþôþ ÿ4ÿbÿ¢ÿäÿ0Fl¸:´$4LhZÀh(øìª œÿTÿ\ÿšÿ¶ÿ–ÿXÿÿÿúþÐþ®þªþ¶þœþ^þ$þþ4þVþTþ þäý®ý’ýtýDýúü˜ü8üöûÞûìûü$ü&ü&üü üþûü8üVüZüLüJüTübü€ü°üâüýNý¦ý"þ þÿZÿ®ÿ”úJ†¦¶Ò`¢ÀºªÆn¼ØÐ¨z^vÀä®Z ÔrìfòâÄšdîÿâÿöÿòÿÊÿ²ÿÄÿöÿ*HB@>Jd¢’v^VXflVØÿ–ÿ~ÿ¸ÿ\ hÖ:š* ÞøZŠNÀ*šȦtôÿ>ÿšþ2þþôýþ þ2þBþZþ¦þ*ÿÌÿP¨ôP¸r²º¤„tFènô–pV¦ÿ0ÿìþîþÿRÿrÿbÿbÿÿúÿfÔL¶â¼”€b&Â:†ÿØþ^þþˆýèüfü8üRüjüPü$ü:ü¼üný þ–þ ÿ”ÿîÿj&¼"RH.Ô˜Pî„j°ÿÎþæý0ýÀü„ülühüfüTüVüxü¨üæü*ý ý"þ|þºþÿjÿ~ÿÿRþäýâýþäýtýýýý0ýLýˆý¦ý‚ýýâüüüBýŒýôý„þþþFÿžÿ@ôTN<€ÎêÒÆ¾€´†rJüÿ¬ÿ”ÿ’ÿ”ÿvÿNÿÿöþÿrÿÔÿDÀt*¤ØôR¬<š¬Nè°ÖòŠ>Z´Žj¢ê‚*’€^Nn¦¶pÌ\¾LæNVT´†bªÿ2ÿŽþÜý|ýýÌýÌý¶ýþ|þüþFÿ†ÿÎÿ:`”â6x ÚBžÎθ’v‚° TÄ4~–š¢|œ>úÖ¸Œ:®ðþÿüþþ:ýŽüüÆûžû–ûªûòûNü¨üÀüü6üêûüjü ýüýìþ´ÿ:ÚüÊtL~ØR®ìòÄ‚dŽÿÊþDþþþþ(þLþ|þBþxý¤üVü„ü˜üvü~üúü´ýHþªþþþXÿ¬ÿ(Ú¸š‚Xþhæzú4fÆ nÌ: š æ < „ ¨ † 8 è ª D x†JNž¨ÈnÚ>Ì‚T:’î^ìÿìÿòÿèÿÎÿ¾ÿÈÿêÿÞÿ”*Xê`Nà¦.\L(Ôr(þ¼"Jÿ~þðýfý²üºûÌúúrùùèøîøÀø:ø÷>÷l÷Ö÷Jø¤ø ùpùÂù*ú®ú(ûlûlû„ûÐû&üBüLüfü®üýdý²ýàýþ&þlþ´þðþ ÿ ÿÿèþ¨þ6þ¸ývý”ýàýàýhý¨üü¤û”ûÀû üšüýhýŒýÆýFþäþhÿâÿŠfJ ²2œ`¼&zžz>"NÀTÀΠtV:þ²JÎTÞØª2„Ün@H^>Þr04B4 îúþäÎÖüB|x0ΦÞX˜’^(܆JÊÿ.ÿbþ¶ý\ý4ýýÜü”üLüüÜû°ûûbûNûNûNûZûrû„û„û~ûtûlûTû\ûjûxû†û˜û°û¶ûšûxûlûzû„ûšûÂûúû0üRüdüvü¬üýTý‚ýný4ýòüÜüôü(ý`ýˆýšý¼ýòý&þ@þFþRþtþ¬þèþ.ÿZÿ`ÿPÿHÿ`ÿ¤ÿ^ ÂÚ hâfÒøê¾TüîâÊ¢jŽêÿÌÿ¦ÿVÿÿ´þ‚þvþ†þžþªþ®þÀþÚþèþÚþàþþþHÿ¤ÿÞÿæÿÎÿ¢ÿrÿ<ÿÿèþºþšþ˜þ þ°þ¶þºþ¾þ¶þžþhþ4þþþþþ4þHþDþ,þþüýÖýÂý®ý˜ý€ýrý‚ýšýªýœý|ývýŠý¢ýÎý þˆþøþFÿšÿüÿN†¸‚ÒòìþJ¸.ŠòPpVÒ˜X440º~lÊøìú2jŒ²øL‚–¨œr2ö¼„rnhlxxN⼘tbhxtnÎôÔpì`ì¾¾¾”<êÿ¨ÿxÿ@ÿèþxþ þ¦ýVý ýòüøüúüÈü†ü€üÚüvýúý>þ,þþÒýÚýBþ¸þðþ þäýý ühü`üfüxüŒü~üZü(üöûÞûü^üìüjýÀýâýöý2þŠþÜþZÿðN$ª înÀÜÔîD¶@H Ìv8Òdö®ºœèz®t<†:ž,$vÈÒ”@æ:hf„Öj†ÖÖ¸ÎX:ü&Š øâº"ˆxºÖH@8`¬ÿæþ0þ¢ýHýöüÀüÜüVýÒýÞý–ýRýjý¸ýÖý¾ý¦ý¾ýÈýžýPýîü€ü*üüîû¤ûHûûû ûûû`ûüÞülýTýäüvüNüfüàü¢ýTþªþ¤þ`þþ´ýfýý°üüzû,ûRûÊûüüêûÄû°û®ûÊûþûüØûTû"û°ûÚüºý*þ\þ®þ4ÿ¾ÿTÞpšü^ð’Ðè4šÈ¬¢¼¬DÂŒ–²~üLª–t„’f2°Jôÿ¾ÿnÿ6ÿLÿšÿ¶ÿ‚ÿÿÜþ6ÿ(øtØNæhî\²¼”t >  X~žú‚ ŽÄÊ >ްÿÐþþDýªüRü0üüþûüþûÐûdûÔú@úÔù˜ùšùæù@ú|ú‚úzúFúæùŒù\ùjù„ù´ùèùúVúúœúú–ú’úxúPúZútúnúnú†ú¦ú¤ú|úTú,úÐù0ùø&øð÷Â÷ˆ÷"÷†öâõrõJõFõ@õ^õÊõ^öòö~÷"øÄøHù–ùöùzúû¨û üdüÌü„ý\þÿ~ÿ¼ÿöÿ0€ôˆ"¼ZÖ6DHT`^J:H\V âª` òîøöئrBøèÀv0 êÔì V`D"úàÖê *,þʆ> Üÿ°ÿŽÿnÿFÿÿ²þ\þ$þôýºýjýöü„ü.üüüüúûÆûŽûXû<û@ûNû^ûnû–ûÜû2üjüjü>üüü:üVüjü€ü–ü¦üºüØü ýRýœýìýBþ˜þæþ.ÿ^ÿ„ÿªÿÖÿNnz|dN8>XtІzdf„¶ø,Np’®ÌâöîØÂ°¢žªÂÊÆ¸´Îô&4:Lpœ° l.ö*V~˜Žf2 V ¸€ –F2NvŒjŒ*$FrˆHòÿ²ÿ¤ÿÂÿöÿ&&äÿ‚ÿ$ÿäþÖþîþÿ(ÿ&ÿÿÊþ”þlþ„þàþNÿ¸ÿúÿòÿÊÿ®ÿÀÿúÿ>nrP$úÿÜÿäÿ&Lfh>îÿ”ÿLÿ6ÿ@ÿXÿlÿhÿZÿHÿNÿjÿ ÿàÿ(h„„d.þÿÚÿìÿ Z†¦˜f*(22,öÿîÿLžÞúÚ®¢Ä"$ä¾Òüþêæò:„¸”žr¤äîÀ¨Â|Ìø 04<<ܾö.´P(DjJð”hbtŽ ’dd²*ÚbôÿÂÿÎÿâÿäÿÈÿ®ÿžÿŒÿfÿ<ÿ"ÿ"ÿBÿnÿ~ÿ†ÿ¢ÿÎÿüÿ Z®þ>`r”Ø8Àjü Ö^úš4ÌŠvZ2ÜD"úÿÊÿžÿ¬ÿèÿ"&>†Ü.TT@Æp. Lr€`6,^Â($4DD( êÈ¢RðÿæÿLžž:ÆÿDÿ²þ>þòý¶ýbýòüšüˆüŽüTüøûÀû¼ûÔûìû ü2ühüºüý&ýHý€ýÄýêýþhþÿvÿJÿ¼þ0þìýäýüý*þ0þ$þ0þ^þ¸þÿTÿlÿTÿVÿÿÔÿ0¤$˜TPâz@8<&ØlÊÿ ÿþý\üúû®û„û’û¾ûÀû˜ûrûbûjûdû4ûðúÄúÚúû û2ûBû^û‚ûÂûüû ü ü üPüpüˆü¸üýdýºýþþäý¦ýzýRýVýžý þTþRþ:þ.þ.þ2þ8þPþfþþÈþ&ÿšÿöÿøÿ¼ÿrÿ(ÿÀþ&þ ýpýŒý°ý¶ý¶ýÒýþ,þLþŽþöþ\ÿ´ÿ*à¨@žÔðèÐÀÆØ Dj|†d´J誔’š¨¤p¸p$îÿöÿ,,<fšÂв‚bTNT^LòÿxÿÿÜþ¨þjþJþ>þ:þTþ°þÿ*ÿÿàþàþâþÌþ¤þˆþ–þ¬þ²þ¢þ¨þÀþÂþzþþÆýžýˆýnývý’ý¼ýÌýÀý¼ý¾ý¾ýºýÚýþRþZþ>þ(þþÊýpý.ýýýýDýýìý0þVþPþ0þþþþ0þbþ¬þîþÿ*ÿ>ÿ^ÿ~ÿšÿÂÿâÿìÿìÿŽFHLVtšºàL|¢Äö üÞÒȼ°¾è>H, úòâÆ €nbR6þÞ´ŠbF6(,&üÖÊÚþ"2òȼÐü.ZfHæÌÆÈΰ€N$ :TJ"òÿÔÿ¸ÿšÿŠÿŠÿÿ’ÿÿ€ÿlÿNÿ4ÿ&ÿÿÿòþÎþžþvþ`þdþxþŠþ˜þ˜þ†þhþJþ<þ>þ\þvþþ®þÎþîþÿÿÿÿÿÿ&ÿ6ÿFÿJÿDÿBÿXÿrÿžÿ¾ÿÈÿ¾ÿªÿ¦ÿ´ÿÎÿòÿ$Z°º´ºÐòJZH&"@`t~z€žÎ <^lnR,öêæÚÊÀ¾¾º¼ÂÔèðИhZnŽ˜˜ˆvdZPDBPd‚𢒆´Ð̨~XD.È‚L2$ôÿèÿàÿèÿ"BVbN0$8`~~xt‚¬Òæô  4JTr’œ€XLTl„–šŒ‚ˆš®ÂÖÔœ€b<þ´|>üÿºÿ†ÿTÿÿàþ¼þ¶þÒþòþÿ:ÿ@ÿ&ÿÿòþÿ ÿLÿ‚ÿ´ÿÊÿ¸ÿ”ÿ€ÿŠÿÿ€ÿ\ÿ@ÿDÿVÿrÿ€ÿtÿdÿhÿzÿxÿNÿÿÿ ÿ ÿ*ÿ6ÿNÿhÿbÿ6ÿÿ2ÿXÿZÿDÿ:ÿfÿœÿÄÿÄÿ¸ÿ¦ÿ„ÿHÿÿÒþ¼þ®þ¼þÒþäþÒþ¬þŠþfþ0þþ@þ~þ¨þÂþÔþðþâþ²þfþ(þþòýØýÈýòýHþþªþ¤þ†þNþþúýþ þ>þlþ²þôþ ÿòþ¶þ„þ`þVþ`þ~þ¼þêþøþøþÿ4ÿ:ÿ(ÿÿøþÿVÿxÿ”ÿºÿòÿÚÿœÿ\ÿPÿrÿÀÿRˆªŽ^Ôà.~²Âºx&ö‚ÎЄBF˜ä  Èn¼¤²º´²ÜÞ|Äÿÿ–ÿ®ÿ ÿtÿ6ÿüþ²þpþ<þ þìýîýöýâý¨ý`ý*ý$ýXý ýÆýÆý¸ý ýýžýöýzþØþæþœþ:þþþBþrþþšþ`þ þÐýÔýòýòýîýþ(þ0þúýÔýžývýfýtý’ý®ýÚýúýúýøýôýæýâý*þœþÿ$ÿÿäþþtþ²þ2ÿ¦ÿÚÿÔÿ¾ÿÌÿhrXV‚®ÄÐÚØæ\vRðú( üòÔ¤TþÿÄÿ²ÿÈÿòÿ&Úÿ’ÿJÿÿÿÿdÿàÿ@Bôÿ2„´¶Žnb^TFHP8Öÿ¦ÿvÿ@ÿÿÿ ÿ0ÿ:ÿ@ÿTÿlÿlÿ<ÿìþÎþêþÿ(ÿ.ÿ6ÿÿÈþtþVþnþ”þ¦þªþ¦þ¬þÆþæþÿbÿ ÿÆÿÊÿ¸ÿ¦ÿœÿ¼ÿäÿ(8B, üÿ`š¦„`J2ÞÿÎÿœÿTÿÿ4ÿhÿzÿ^ÿ$ÿÿÿ0ÿ4ÿ&ÿ$ÿNÿnÿrÿ‚ÿÆÿ&@>D`vtŒ¼:\dvš¬˜€’´ÒÚ26ðêàȲ˜vN2*" ðÞè8Pnt\FPbfXNF8.0JRJ>2(&8VptfVL>40BJ@ÎŒRäÿÀÿ ÿˆÿlÿJÿ4ÿ ÿÿèþÂþ’þ`þ@þ4þ6þ>þNþbþvþŽþœþšþþŠþ’þ²þÔþúþ"ÿBÿ\ÿlÿhÿTÿJÿVÿtÿ”ÿ¬ÿÈÿäÿüÿ$"ðÿâÿÔÿØÿôÿ $2:>8,*,8Nfˆ¸äþôâÐÌÎÜèâÔ¾º¾ÊàîèÜÞî@brfZXlrlbZP>.0>HPXlprjV:úÞÊ´ †|hN2þÿÒÿ¢ÿŠÿ†ÿ†ÿ†ÿ~ÿ|ÿrÿhÿRÿ0ÿÿÿÿ$ÿ0ÿ6ÿHÿTÿXÿLÿ:ÿ:ÿ>ÿ>ÿ.ÿ&ÿ4ÿLÿ^ÿbÿbÿRÿDÿ>ÿ@ÿLÿTÿVÿVÿHÿ4ÿÿÿÿÿÿêþºþŠþbþ.þ þþþ*þ"þþþöýêýìý þ$þDþbþˆþ´þÎþÐþÌþÞþÿ$ÿ8ÿ@ÿNÿZÿhÿvÿ„ÿŽÿ–ÿ˜ÿ–ÿ˜ÿœÿ¢ÿ’ÿ„ÿ„ÿ¢ÿÌÿîÿôÿâÿÎÿºÿ¶ÿÂÿÚÿêÿöÿúÿîÿøÿüÿòÿìÿðÿ"FVPPD. ,BNVhjbXN4üÿøÿöÿèÿÔÿ¶ÿŽÿhÿXÿXÿ\ÿRÿ<ÿÿèþ¾þ”þfþ@þ6þXþ„þœþŠþ\þ0þ þþ,þ@þbþˆþ”þšþšþ¢þ´þ°þ²þÆþòþÿúþòþÿ6ÿ^ÿbÿDÿ&ÿÿÿ&ÿ0ÿBÿNÿ\ÿdÿvÿŒÿŽÿtÿVÿbÿÿÈÿîÿ 8blR2 6j Ìäâ̺¾Îú.^fF48DDHF0úª^$"2êÿÀÿŠÿJÿ4ÿ*ÿ$ÿ$ÿ6ÿvÿ¢ÿ‚ÿ ÿ„þ.þþ*þRþtþ€þvþJþþôýþþüýþbþ²þÌþÈþ¬þ„þZþJþfþ˜þÊþÚþ¸þ€þTþ:þ$þ$þþ þþý þ$þ,þ&þ8þZþ‚þ¨þ¼þ¬þ|þ<þþØýêýþòýºýŠýŒý¬ýÒýþ.þTþ~þ¤þÀþ¾þ¢þ|þfþtþ˜þ¾þêþÿ ÿÿÿÿÿ"ÿ<ÿbÿ¢ÿÞÿæÿ®ÿXÿÿþþöþöþêþÆþ†þRþNþ†þÐþòþèþÊþ´þ˜þ†þ–þÈþòþøþðþÿDÿxÿ|ÿXÿ(ÿÿ$ÿDÿpÿ˜ÿ¶ÿÔÿ0:* 26BRV208" øÿâÿÚÿäÿüÿ øÿÈÿÿnÿjÿ€ÿ–ÿ¨ÿžÿˆÿdÿhÿ¤ÿØÿâÿÂÿ¶ÿÆÿÒÿÐÿÊÿÎÿÈÿ¸ÿÄÿôÿ>xšª¨ –”–„hRF<,üÿìÿÞÿÞÿäÿâÿÔÿ´ÿ‚ÿPÿ:ÿFÿTÿZÿZÿfÿ€ÿšÿ¸ÿÚÿðÿîÿÚÿÀÿªÿ¦ÿ´ÿ¾ÿºÿ¬ÿ¬ÿÀÿØÿòÿ&H€ÂðøÖ²”–š’|dZl’¼ØÒ¬‚dRXT@(",Fbx~x~~Š’ˆhRHNbpttpx‚Ž”–šš’Š†|`@6LrˆŒ‚rf\VL4Þÿ°ÿŠÿpÿZÿJÿBÿBÿ@ÿ@ÿDÿFÿDÿBÿBÿBÿFÿLÿ\ÿrÿÿ¦ÿ°ÿ²ÿÄÿîÿ@VVF2êÿÊÿ¨ÿÿ„ÿ~ÿrÿ`ÿZÿLÿ6ÿÿÿúþÿ ÿÿÿÿôþèþæþìþüþÿÿÿðþêþæþìþîþêþìþÿ"ÿ<ÿ>ÿ2ÿ&ÿ,ÿFÿdÿ€ÿÿžÿ¦ÿ¸ÿÎÿæÿüÿ,BNPNHLJJT^\N. èÿÊÿ®ÿ”ÿÿ’ÿ–ÿÿzÿdÿ\ÿjÿzÿˆÿ–ÿ˜ÿœÿ¦ÿ¾ÿØÿìÿöÿøÿöÿîÿÞÿÌÿ´ÿ”ÿvÿdÿhÿ‚ÿœÿ¬ÿ ÿÿ‚ÿ|ÿ|ÿzÿtÿnÿlÿjÿnÿrÿ|ÿ€ÿ€ÿ†ÿˆÿ’ÿÿŽÿ„ÿvÿbÿJÿ.ÿÿÿÿÿüþøþòþðþòþÿ$ÿDÿfÿ€ÿ”ÿ¤ÿ´ÿÐÿúÿ$D`lxvtt€–¦¨š‚dL<@DB, òÿìÿîÿòÿúÿöÿÚÿÀÿ²ÿ®ÿ¨ÿ ÿ–ÿ”ÿ˜ÿšÿ˜ÿŒÿxÿ^ÿNÿLÿNÿXÿ`ÿjÿpÿfÿTÿ8ÿ0ÿ8ÿFÿNÿRÿVÿ\ÿbÿtÿ’ÿ¦ÿ¤ÿœÿ˜ÿ¢ÿ®ÿ¨ÿ–ÿŽÿ’ÿ’ÿ–ÿžÿšÿxÿFÿÿÿÿ(ÿ,ÿ$ÿÿôþÐþ®þ¤þ¤þ¤þžþ¤þ®þ´þ²þ´þÆþàþðþòþðþèþÚþÈþÂþÎþØþÞþØþÖþØþÊþºþ¨þ®þÄþÚþðþÿPÿ`ÿNÿFÿdÿ˜ÿ®ÿ¼ÿÒÿúÿ ,<F@0 äÿ²ÿ’ÿ’ÿ’ÿ€ÿbÿtÿžÿ¤ÿŽÿ~ÿ¢ÿ°ÿÿnÿtÿŽÿ€ÿ\ÿ:ÿ<ÿBÿ.ÿÿÿ>ÿTÿ@ÿ ÿÿÿÿ"ÿ&ÿ8ÿ@ÿBÿHÿRÿPÿ4ÿÿôþôþòþêþØþÎþÎþÔþÎþ¼þžþˆþ€þ€þ’þ´þÐþàþäþìþâþªþ\þþüýâýÀý¼ýÖýúý þþ<þ`þlþBþ$þ2þhþŽþœþ˜þŠþ’þ þºþÜþÿÿ0ÿHÿvÿžÿ”ÿlÿRÿNÿLÿ<ÿ8ÿTÿ€ÿˆÿxÿpÿ‚ÿ ÿœÿÿ„ÿ‚ÿzÿbÿhÿ„ÿ®ÿºÿ²ÿ ÿ–ÿ ÿ¼ÿÜÿôÿ úÿÊÿrÿÿæþøþ2ÿfÿxÿŒÿ¦ÿÊÿÎÿÐÿØÿÎÿ°ÿÿ˜ÿ´ÿÊÿÒÿÜÿøÿ ôÿèÿìÿôÿöÿîÿÔÿºÿ¢ÿšÿ’ÿŠÿrÿPÿ4ÿ8ÿ\ÿŠÿ¦ÿ˜ÿpÿLÿBÿBÿ:ÿ(ÿÿÿÿÿ,ÿ8ÿ,ÿÿÿ"ÿ<ÿNÿXÿ\ÿXÿJÿBÿHÿBÿ.ÿ$ÿ0ÿTÿvÿÿ˜ÿ˜ÿœÿœÿŽÿpÿNÿ8ÿ*ÿ0ÿLÿ~ÿœÿžÿtÿJÿ(ÿÿÿ(ÿ8ÿLÿ\ÿVÿXÿ`ÿXÿ4ÿÿÿ@ÿfÿzÿˆÿœÿ¨ÿ´ÿÀÿÐÿØÿÒÿÔÿàÿüÿ$"".8@@:6*èÿÐÿÆÿÒÿäÿøÿþÿþÿòÿÖÿ¸ÿ¬ÿºÿÒÿàÿàÿîÿþÿþÿâÿÄÿºÿÀÿÀÿ¦ÿŠÿ~ÿ„ÿ”ÿ¤ÿ¬ÿ ÿŽÿ|ÿvÿpÿ`ÿZÿbÿvÿÿœÿ¤ÿžÿ–ÿŠÿtÿ`ÿJÿ<ÿ6ÿ2ÿ2ÿDÿ`ÿ‚ÿ–ÿ¤ÿ¦ÿ¨ÿ¤ÿšÿ–ÿœÿžÿ ÿœÿ–ÿŽÿŽÿšÿ®ÿÂÿÄÿ¼ÿ¸ÿºÿ¶ÿ°ÿ¨ÿ¬ÿºÿÀÿÄÿ¼ÿ®ÿ”ÿŒÿ¢ÿÈÿðÿ &@VhzŽ žŽ†®Ðââêþ*." öêìêââæîîêêîòêÖªŒjJ:88$òÿæÿàÿØÿÎÿÂÿ°ÿ ÿ’ÿŠÿ€ÿvÿvÿrÿlÿ^ÿPÿPÿZÿnÿ€ÿŠÿ–ÿ¤ÿ¬ÿ®ÿ¦ÿ ÿ¨ÿ¨ÿ¬ÿ¤ÿ ÿœÿ’ÿˆÿˆÿ‚ÿxÿnÿbÿNÿ:ÿ0ÿ0ÿ2ÿ2ÿ4ÿ2ÿ4ÿ4ÿ.ÿÿÿ ÿÿ$ÿ2ÿ:ÿ:ÿ@ÿNÿjÿŽÿ°ÿÄÿÌÿÎÿÐÿÚÿæÿøÿ(4BJD:>V|œ®´¬¢šš ¢–zZF>>>><6424428FV`jzŒ–ˆ„š¦ª¢‚vrfP@0& þÿìÿØÿÊÿÆÿ¾ÿ¨ÿŒÿvÿlÿnÿrÿxÿvÿlÿ^ÿRÿRÿ^ÿnÿrÿpÿbÿZÿNÿDÿ@ÿDÿFÿFÿFÿLÿfÿ€ÿ’ÿ”ÿŠÿ‚ÿ€ÿÿªÿÊÿàÿæÿêÿìÿðÿöÿüÿþÿöÿìÿâÿÔÿÄÿ¤ÿ~ÿ\ÿHÿFÿNÿNÿBÿ:ÿ:ÿBÿNÿ\ÿ`ÿ\ÿRÿFÿ8ÿ2ÿ:ÿDÿNÿ^ÿrÿ†ÿ”ÿžÿšÿÿˆÿŽÿœÿªÿ¨ÿœÿˆÿxÿlÿhÿhÿrÿ~ÿ†ÿ~ÿrÿhÿfÿ`ÿ^ÿ\ÿVÿFÿ.ÿ ÿ"ÿ2ÿDÿJÿ>ÿ2ÿ&ÿ ÿÿÿðþÐþ¾þ´þºþÀþ¼þ¦þþŠþšþºþÖþòþÿÿÿÿ&ÿ8ÿ@ÿBÿJÿRÿ\ÿdÿpÿvÿjÿ\ÿPÿTÿVÿ\ÿfÿjÿjÿjÿlÿ|ÿ†ÿˆÿ‚ÿvÿhÿVÿPÿ`ÿ€ÿ–ÿ˜ÿˆÿxÿdÿRÿNÿ\ÿzÿ”ÿœÿžÿžÿžÿ ÿ¬ÿ¾ÿÐÿÖÿÒÿÒÿÞÿðÿêÿÞÿÖÿàÿòÿþÿüÿ6^xxfXJ:üÿâÿâÿòÿüÿôÿâÿÊÿÀÿÂÿÖÿêÿøÿüÿ &Bd€–¢¨ª¢š˜ ¦ž~T2$ üÿòÿêÿäÿÐÿ°ÿŽÿxÿ|ÿ–ÿªÿ¦ÿŠÿvÿ‚ÿžÿªÿ®ÿ¶ÿ¾ÿ¼ÿ¤ÿŽÿ|ÿlÿ^ÿ\ÿfÿlÿ`ÿ@ÿ,ÿ*ÿ<ÿJÿJÿTÿbÿvÿˆÿ˜ÿ¤ÿ¢ÿÿ„ÿœÿÊÿæÿØÿ¨ÿ„ÿxÿ~ÿˆÿŒÿzÿXÿ2ÿ ÿ0ÿ<ÿ(ÿÿâþîþÿ@ÿRÿDÿ8ÿDÿ^ÿ|ÿÿ˜ÿŒÿrÿdÿtÿ’ÿ¤ÿ ÿ–ÿœÿ°ÿ¾ÿ¾ÿ°ÿ¤ÿ˜ÿœÿ´ÿÎÿÞÿÎÿ¶ÿ ÿšÿ’ÿ~ÿnÿjÿpÿ~ÿ‚ÿzÿfÿTÿPÿfÿŽÿ¸ÿÎÿÊÿ¾ÿºÿ¾ÿ¶ÿ¬ÿ¨ÿ˜ÿ„ÿzÿ‚ÿˆÿrÿFÿ ÿÿ4ÿPÿRÿDÿ:ÿBÿNÿbÿ|ÿ–ÿšÿ„ÿrÿ~ÿ¢ÿ¾ÿÂÿÀÿÄÿäÿüÿæÿÌÿ¶ÿ¬ÿªÿ²ÿÀÿÖÿðÿüÿîÿÔÿ²ÿ ÿ¤ÿ°ÿÂÿÊÿÞÿöÿ.:,"$"îÿÎÿ°ÿžÿ˜ÿ–ÿŒÿvÿZÿHÿJÿ\ÿlÿlÿZÿ@ÿ:ÿHÿXÿnÿ†ÿžÿ¦ÿšÿŽÿ„ÿ„ÿÿŽÿ‚ÿ~ÿˆÿ˜ÿ¤ÿ®ÿ´ÿ¨ÿ”ÿ„ÿpÿ`ÿbÿpÿ‚ÿŽÿ¦ÿ¶ÿ²ÿ¬ÿ´ÿÎÿÜÿÐÿÆÿÀÿÆÿÒÿÜÿàÿØÿÒÿÊÿÄÿ¶ÿžÿÿŠÿ˜ÿ¬ÿ¸ÿ¶ÿ¶ÿºÿ¶ÿ¼ÿÌÿÞÿäÿäÿòÿ $0:N\jz’ ”~ptxtnt€„tfhl^F<JPJBJ^nhd|’˜Œ–ª¶¶´ÀƸš€zlZD@@4 *.8FLH<6,($"(,&üÿêÿîÿôÿöÿöÿôÿôÿôÿòÿöÿòÿêÿàÿØÿÐÿÐÿÐÿÐÿÒÿÜÿèÿøÿ*2<8.$  øÿòÿøÿ".:@>60,&"&($   ""  þÿüÿþÿòÿäÿÒÿÄÿ¸ÿ²ÿ¸ÿÂÿÈÿÌÿÎÿÔÿØÿÜÿàÿÞÿÚÿØÿØÿÖÿÐÿÌÿÎÿÐÿÚÿæÿôÿ"&,00.  þÿòÿîÿèÿäÿÞÿØÿÖÿØÿÞÿæÿðÿôÿüÿþÿúÿôÿèÿäÿäÿæÿäÿÞÿØÿÐÿÈÿ¾ÿ¶ÿ´ÿ¶ÿºÿ¼ÿÀÿÈÿÒÿÚÿÚÿØÿÔÿÒÿÌÿ¾ÿ¨ÿ”ÿŠÿŠÿÿžÿ¤ÿ¬ÿ´ÿºÿºÿ¸ÿ¾ÿÆÿÐÿÔÿÖÿÔÿÊÿÂÿ²ÿ¤ÿšÿ˜ÿœÿ¢ÿ¦ÿ ÿ˜ÿ’ÿŽÿˆÿ†ÿ„ÿŠÿ”ÿ ÿªÿ°ÿºÿÆÿÔÿàÿäÿäÿÞÿÒÿÄÿ¶ÿªÿ ÿ˜ÿ”ÿ’ÿŽÿŒÿˆÿ„ÿ~ÿ~ÿ~ÿ„ÿŽÿžÿ®ÿ¸ÿÀÿÂÿÈÿÄÿÈÿÐÿØÿÞÿÞÿÞÿàÿæÿäÿàÿàÿÞÿÖÿÂÿ®ÿ¢ÿ¨ÿ´ÿÂÿÐÿÚÿÚÿÎÿ¶ÿ ÿ˜ÿšÿªÿÀÿÌÿÒÿÐÿÌÿÊÿÆÿÆÿÆÿÈÿÎÿÈÿÆÿÀÿ¸ÿ¦ÿ˜ÿ–ÿ¢ÿ´ÿ¼ÿÀÿÌÿÚÿäÿàÿÖÿÐÿÐÿÖÿàÿìÿôÿîÿÖÿÀÿÄÿÜÿøÿöÿèÿâÿâÿêÿêÿàÿØÿÚÿäÿÜÿÊÿ¼ÿ¼ÿÌÿØÿâÿêÿêÿêÿìÿìÿìÿàÿÊÿ¸ÿ²ÿºÿÄÿÎÿÎÿÎÿÊÿÌÿÎÿÐÿÆÿ¬ÿ–ÿŒÿ’ÿ”ÿ–ÿžÿ¨ÿ°ÿ°ÿ®ÿºÿÈÿÊÿÌÿÊÿÊÿÆÿ²ÿšÿÿ–ÿžÿ¨ÿ¶ÿÄÿÈÿÆÿÄÿÀÿ¶ÿ¢ÿŠÿzÿvÿ|ÿ|ÿtÿjÿhÿhÿdÿnÿ„ÿšÿ¦ÿ²ÿÂÿÈÿ¼ÿ¢ÿ–ÿšÿ¦ÿ²ÿºÿÈÿÊÿÂÿºÿºÿÎÿØÿÌÿºÿ®ÿ¨ÿ¤ÿ˜ÿŒÿŒÿŒÿ–ÿ¢ÿ¸ÿÐÿÖÿÒÿÂÿ²ÿ¨ÿ¤ÿ¦ÿœÿŽÿˆÿÿšÿ˜ÿ–ÿ˜ÿšÿ˜ÿ”ÿ˜ÿ ÿ¦ÿ¤ÿ˜ÿŒÿ”ÿšÿ˜ÿŠÿ~ÿ„ÿ’ÿ”ÿ˜ÿ¦ÿÄÿÔÿÖÿÐÿÖÿäÿîÿðÿòÿüÿ$"ôÿêÿæÿæÿâÿäÿòÿ üÿüÿøÿúÿüÿøÿòÿöÿ"*6BLVVPNR^fj`P@80284*$"þÿòÿàÿÌÿÈÿÂÿ²ÿ˜ÿŠÿŒÿ–ÿ˜ÿŽÿ€ÿpÿ^ÿJÿBÿFÿPÿ\ÿdÿhÿlÿrÿrÿxÿ€ÿxÿjÿ\ÿXÿTÿLÿBÿJÿTÿ^ÿ`ÿ`ÿfÿnÿrÿzÿ†ÿšÿ¬ÿ¶ÿ¸ÿ¼ÿ¾ÿºÿ®ÿ¦ÿªÿ¶ÿºÿ¾ÿÆÿØÿàÿÞÿÖÿÔÿØÿÖÿÖÿÜÿâÿâÿÒÿºÿªÿ´ÿÄÿÌÿÎÿÔÿÚÿÞÿàÿæÿîÿôÿúÿ".:DHLF@84444.$ $ þÿ þÿôÿðÿîÿòÿòÿðÿôÿüÿúÿòÿôÿúÿøÿôÿîÿäÿàÿàÿâÿäÿäÿâÿÞÿÞÿâÿæÿìÿðÿôÿðÿêÿêÿîÿôÿøÿþÿøÿêÿØÿÊÿÂÿ¼ÿ¸ÿ¸ÿ¼ÿ¼ÿ´ÿ¬ÿ²ÿ¼ÿÊÿÔÿàÿêÿôÿôÿøÿþÿ",8@FNT\dhjjntvvzxrh`XPJFB@@@@:.("(*.26:60(&&" þÿúÿòÿìÿæÿæÿêÿòÿôÿìÿâÿÚÿÖÿÖÿÔÿÐÿÐÿÈÿÀÿ¶ÿ´ÿ´ÿ°ÿ¬ÿ¢ÿžÿ˜ÿ–ÿšÿ ÿ¤ÿžÿœÿ˜ÿœÿ¢ÿ¦ÿ¦ÿ¦ÿ¨ÿªÿ¨ÿ¦ÿ¤ÿ¦ÿ¦ÿ¤ÿ¤ÿ¨ÿ®ÿ´ÿ¼ÿÈÿÒÿÚÿäÿèÿäÿâÿäÿèÿìÿòÿöÿúÿüÿúÿþÿ  úÿðÿèÿæÿäÿàÿÜÿØÿÔÿÐÿÒÿÔÿÖÿàÿèÿòÿúÿ"*.462.($"(*(&&&&((&"þÿøÿøÿúÿþÿöÿîÿêÿâÿàÿâÿÞÿÚÿÔÿÒÿÐÿÔÿÔÿØÿÜÿØÿÎÿÂÿºÿ°ÿ¨ÿ¤ÿ¤ÿ¦ÿ¨ÿ¦ÿ¬ÿ®ÿ®ÿ®ÿ²ÿ¸ÿ¼ÿÀÿÀÿÀÿ¾ÿ¾ÿºÿ´ÿ²ÿ´ÿ®ÿ¨ÿžÿœÿšÿ˜ÿ’ÿÿ’ÿšÿžÿ ÿ ÿ¤ÿ¦ÿ ÿ˜ÿ’ÿ”ÿ”ÿ–ÿ˜ÿ ÿ¤ÿ ÿšÿšÿžÿ ÿšÿ’ÿ’ÿœÿ¦ÿ®ÿ²ÿºÿ¾ÿ¾ÿ¼ÿ¼ÿ¾ÿ¼ÿ´ÿ²ÿ¬ÿ°ÿºÿÈÿÔÿÜÿâÿæÿìÿîÿðÿèÿèÿêÿîÿôÿøÿ øÿêÿèÿðÿüÿ   ,*$&(( &042.*" þÿüÿ úÿäÿÖÿÔÿÎÿÂÿ´ÿ¬ÿ¦ÿ¢ÿ ÿ¤ÿ¦ÿžÿ’ÿˆÿ†ÿ†ÿ€ÿtÿhÿhÿhÿlÿtÿ~ÿ„ÿ„ÿˆÿÿžÿ¨ÿ°ÿ¬ÿ¨ÿ¬ÿ¶ÿ¼ÿ¶ÿ®ÿ¨ÿ¦ÿ¤ÿžÿšÿ”ÿ’ÿÿ˜ÿžÿžÿ˜ÿ˜ÿžÿ¦ÿ¬ÿ²ÿ¬ÿžÿ’ÿ–ÿ¨ÿºÿÂÿ¾ÿ´ÿ²ÿ¶ÿºÿ¸ÿ®ÿ ÿ”ÿŠÿ„ÿ†ÿÿ–ÿœÿ¦ÿ¶ÿÊÿÞÿæÿäÿÞÿÞÿäÿêÿöÿüÿúÿþÿøÿòÿèÿàÿâÿìÿôÿøÿüÿþÿüÿôÿêÿàÿÞÿèÿðÿöÿòÿðÿîÿâÿÖÿÒÿÚÿàÿàÿàÿàÿÞÿÚÿÔÿÎÿÎÿÒÿÖÿÞÿâÿæÿæÿèÿìÿöÿþÿöÿæÿÜÿÖÿÐÿÊÿÎÿÜÿæÿêÿäÿÜÿÒÿÆÿ¼ÿ¸ÿ¾ÿÌÿÚÿæÿäÿÚÿÖÿÜÿæÿèÿèÿèÿæÿäÿÞÿÚÿÖÿÚÿÖÿØÿàÿèÿìÿâÿÖÿÒÿÒÿÖÿØÿØÿÒÿÊÿºÿ°ÿ²ÿºÿÄÿÈÿÈÿÐÿØÿÜÿØÿÐÿÎÿÔÿàÿðÿüÿöÿðÿòÿøÿüÿþÿþÿþÿøÿòÿîÿòÿøÿ  øÿðÿîÿìÿîÿêÿèÿæÿèÿæÿîÿúÿúÿôÿòÿòÿüÿ  &" "$"þÿþÿöÿòÿôÿúÿúÿöÿöÿöÿôÿøÿþÿüÿúÿøÿøÿøÿúÿøÿöÿðÿêÿêÿìÿòÿúÿ  üÿúÿôÿöÿöÿôÿîÿêÿèÿèÿìÿêÿêÿêÿèÿèÿæÿâÿâÿäÿæÿèÿêÿèÿèÿèÿèÿèÿìÿîÿðÿðÿðÿôÿôÿöÿüÿþÿþÿ $(($  "þÿöÿôÿòÿôÿöÿúÿüÿüÿöÿôÿðÿîÿêÿæÿàÿÜÿÚÿÜÿÞÿàÿâÿâÿæÿæÿæÿâÿÜÿÞÿàÿäÿìÿòÿúÿüÿøÿôÿôÿøÿüÿ þÿöÿöÿøÿþÿþÿúÿöÿôÿôÿôÿðÿêÿàÿØÿÒÿÌÿÈÿÂÿÀÿ¼ÿºÿ¼ÿ¾ÿÀÿ¾ÿ¼ÿºÿ¼ÿÀÿÆÿÊÿÐÿÐÿÐÿÎÿÐÿÎÿÎÿÒÿØÿäÿîÿøÿþÿþÿúÿôÿòÿöÿúÿ ôÿèÿÞÿÜÿÞÿäÿèÿèÿâÿÜÿØÿÔÿÔÿÔÿÔÿÖÿØÿÔÿÐÿÊÿÈÿÈÿÎÿÒÿÖÿÜÿÜÿÞÿàÿæÿðÿúÿ  (08<>@B@:2,&"   úÿòÿìÿâÿÖÿÐÿÎÿÐÿÔÿÔÿÒÿÎÿÌÿÎÿÔÿÞÿäÿäÿâÿâÿæÿæÿäÿäÿêÿðÿôÿöÿøÿúÿúÿüÿþÿþÿüÿôÿîÿèÿæÿæÿèÿèÿêÿèÿÞÿÒÿÈÿ¾ÿ¸ÿ°ÿ¦ÿ ÿžÿžÿžÿœÿœÿ ÿ ÿ¤ÿ¬ÿ´ÿ¸ÿ¸ÿ¼ÿÂÿÎÿÚÿàÿàÿàÿÞÿàÿèÿöÿüÿ  øÿøÿøÿüÿþÿúÿôÿìÿäÿâÿâÿæÿèÿæÿæÿèÿêÿîÿôÿöÿöÿøÿúÿþÿ".:DHD@<@DJNVXVRNLF@80("øÿðÿîÿðÿðÿîÿîÿðÿîÿêÿäÿæÿäÿÞÿÖÿÒÿÐÿÒÿÒÿÔÿØÿØÿÖÿÚÿÞÿÞÿÚÿØÿÚÿâÿæÿäÿàÿÜÿÞÿâÿäÿàÿÜÿØÿÔÿÔÿØÿÜÿÔÿÄÿ¸ÿºÿÆÿÄÿºÿ¬ÿ¦ÿ¢ÿžÿ ÿœÿ˜ÿŽÿŠÿŠÿ’ÿšÿšÿ–ÿ’ÿ”ÿ–ÿ˜ÿšÿ ÿ¨ÿ´ÿ¼ÿ¼ÿ¾ÿÂÿÌÿÒÿÔÿÖÿÜÿÜÿÞÿâÿìÿöÿüÿüÿúÿþÿ    $&*.,"$** $($"*22,*2:>:6:BFB<<6,&(,*" úÿôÿðÿòÿôÿôÿôÿðÿîÿîÿðÿðÿðÿìÿæÿÜÿÚÿæÿðÿðÿäÿâÿæÿèÿæÿâÿâÿâÿÞÿàÿÞÿØÿÎÿÈÿÆÿÆÿÈÿÊÿÈÿÂÿ¾ÿÄÿÈÿÄÿÀÿ¼ÿÀÿÆÿÈÿÌÿÎÿÎÿÎÿÐÿÔÿÔÿÔÿÔÿÒÿÒÿÐÿÎÿÐÿÖÿÖÿÜÿäÿêÿîÿðÿöÿþÿþÿüÿþÿ úÿøÿúÿøÿöÿôÿøÿúÿüÿüÿ  üÿôÿðÿîÿîÿèÿâÿäÿæÿêÿìÿìÿðÿðÿîÿæÿæÿèÿîÿðÿîÿðÿôÿöÿöÿöÿúÿüÿüÿüÿüÿüÿöÿòÿðÿòÿòÿôÿôÿòÿîÿìÿèÿèÿìÿòÿúÿþÿþÿþÿ þÿþÿþÿüÿøÿöÿôÿôÿòÿìÿêÿìÿòÿöÿøÿúÿúÿüÿøÿôÿôÿöÿöÿôÿúÿúÿôÿðÿîÿîÿòÿøÿþÿüÿúÿþÿþÿ   þÿüÿúÿöÿòÿîÿîÿðÿðÿîÿîÿêÿìÿîÿôÿúÿüÿþÿüÿþÿ þÿþÿ úÿøÿúÿ úÿòÿìÿîÿðÿòÿòÿðÿîÿìÿèÿèÿèÿæÿäÿæÿêÿîÿôÿúÿ  üÿøÿøÿöÿøÿøÿüÿüÿöÿôÿôÿöÿöÿôÿôÿôÿôÿöÿøÿúÿøÿòÿðÿîÿðÿòÿøÿúÿþÿþÿþÿ  þÿüÿþÿþÿþÿþÿ   þÿüÿøÿöÿôÿòÿòÿôÿöÿúÿþÿ    þÿúÿøÿøÿøÿøÿúÿøÿúÿúÿøÿøÿúÿþÿþÿþÿüÿúÿöÿöÿôÿöÿøÿøÿúÿúÿøÿúÿüÿüÿþÿþÿþÿþÿþÿþÿüÿüÿüÿüÿþÿþÿúÿöÿôÿôÿöÿøÿöÿøÿøÿ     þÿøÿöÿôÿòÿòÿòÿòÿòÿðÿòÿöÿôÿðÿîÿìÿêÿêÿêÿêÿêÿèÿèÿèÿèÿêÿèÿæÿäÿæÿæÿæÿæÿæÿæÿæÿäÿæÿêÿìÿîÿîÿòÿôÿòÿîÿìÿìÿîÿîÿðÿòÿðÿðÿòÿöÿøÿüÿøÿøÿøÿøÿúÿüÿþÿüÿüÿúÿúÿúÿúÿúÿøÿôÿòÿðÿîÿìÿðÿòÿðÿêÿèÿîÿôÿúÿüÿ    þÿüÿüÿþÿþÿþÿþÿüÿüÿþÿúÿôÿðÿðÿîÿòÿôÿøÿøÿöÿôÿôÿøÿøÿøÿúÿüÿüÿúÿúÿúÿþÿþÿüÿúÿøÿôÿðÿðÿòÿòÿòÿòÿôÿôÿòÿîÿîÿìÿîÿîÿòÿöÿøÿöÿöÿöÿøÿøÿøÿúÿüÿþÿüÿüÿþÿþÿþÿþÿüÿþÿþÿüÿþÿþÿúÿøÿøÿøÿúÿüÿþÿúÿôÿðÿðÿòÿòÿôÿöÿøÿøÿöÿòÿôÿôÿöÿôÿòÿôÿöÿúÿúÿúÿøÿøÿøÿúÿüÿøÿöÿúÿþÿþÿúÿöÿöÿüÿ  þÿþÿþÿþÿüÿúÿøÿüÿüÿöÿòÿðÿôÿøÿþÿþÿüÿúÿøÿúÿüÿþÿþÿüÿþÿþÿúÿúÿøÿúÿüÿúÿöÿôÿòÿôÿöÿøÿöÿöÿòÿðÿôÿøÿüÿüÿúÿøÿøÿöÿöÿøÿúÿþÿüÿúÿøÿôÿòÿðÿòÿôÿöÿøÿøÿöÿöÿøÿúÿüÿüÿüÿüÿþÿüÿúÿúÿüÿþÿ þÿüÿúÿúÿüÿþÿþÿ þÿþÿþÿþÿþÿþÿþÿþÿþÿþÿüÿüÿúÿúÿúÿúÿüÿüÿüÿüÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿüÿúÿúÿüÿüÿüÿüÿüÿþÿþÿþÿþÿüÿúÿúÿúÿüÿüÿúÿúÿúÿúÿøÿøÿöÿôÿòÿðÿðÿòÿòÿòÿòÿðÿòÿòÿôÿöÿôÿöÿöÿöÿöÿøÿöÿöÿôÿöÿöÿøÿøÿúÿúÿúÿúÿúÿüÿúÿúÿúÿúÿüÿüÿúÿúÿüÿüÿüÿüÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿüÿüÿþÿþÿþÿþÿþÿþÿþÿþÿüÿüÿüÿüÿúÿøÿøÿøÿúÿúÿøÿöÿöÿòÿòÿòÿôÿôÿôÿòÿòÿôÿöÿôÿöÿöÿøÿøÿøÿøÿúÿúÿúÿüÿüÿúÿúÿúÿüÿüÿüÿüÿüÿþÿþÿþÿþÿþÿþÿüÿüÿüÿüÿüÿüÿþÿþÿþÿþÿþÿþÿþÿþÿþÿüÿúÿüÿüÿþÿüÿþÿþÿþÿþÿþÿþÿþÿúÿúÿúÿúÿüÿüÿüÿüÿþÿþÿþÿþÿþÿþÿüÿüÿþÿþÿüÿüÿúÿúÿøÿøÿúÿüÿüÿüÿúÿúÿúÿúÿúÿüÿþÿüÿüÿüÿüÿüÿüÿüÿüÿüÿþÿþÿüÿüÿüÿúÿúÿøÿøÿøÿúÿüÿüÿüÿþÿþÿþÿþÿþÿþÿþÿüÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿüÿúÿúÿúÿüÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿüÿþÿüÿüÿüÿüÿþÿþÿþÿüÿþÿþÿüÿüÿüÿüÿüÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿcrossfire-client-1.75.3/sounds/sounds.conf000644 001751 001751 00000012071 14167727013 021450 0ustar00kevinzkevinz000000 000000 # sounds.conf -- client sound definitions # # This file contains sound definitions that map actions to certain sounds. # Empty lines are ignored, as are lines beginning with the '#' character. # # The volume of 100 means max volume. Anything higher may break the sound # handling. SOUND_CLOCK:130:TowerClock.wav SOUND_NEW_PLAYER:30:su-fanf.wav SOUND_PET_IS_KILLED:80:squish.wav SOUND_PLAYER_HITS1:60:click1.wav SOUND_PLAYER_HITS2:70:click2.wav SOUND_PLAYER_HITS3:80:click1.wav SOUND_PLAYER_HITS4:90:click2.wav SOUND_PLAYER_IS_HIT1:70:FloorTom.wav SOUND_PLAYER_IS_HIT2:80:ouch1.wav SOUND_PLAYER_IS_HIT3:90:thru.wav SOUND_PLAYER_KILLS:80:drip.wav # living death:150:gong.wav push:80:blip.wav # spell fumble:70:Missed.wav learn:100:chord.wav # item evaporate:100:Whoosh.wav explode:100:Explosion.wav fire:80:Teeswing.wav poof:70:Missed.wav turn handle:80:boink2.wav button click:80:click1.wav drink:80:potion.ogg gate moving:80:click2.wav # ground fall hole:200:MetalCrash.wav open:90:Creaky-1.wav poison:130:Puke.wav kill:80:painb.wav miss:50:miss-1.ogg # Skills clawing:50:claws.ogg karate:50:fist.ogg punching:50:fist.ogg one handed weapons:50:knife.ogg two handed weapons:50:sword-1.ogg step:100:step_lth1.ogg # Spells aggravation:100:bugle_charge.wav alchemy:100:magic.wav antimagic rune:100:magic.wav armour:100:magic.wav ball lightning:110:lightning1.wav banishment:100:magic.wav breath flame:100:fire-spell.wav build bullet wall:100:magic.wav build director:100:magic.wav build fireball wall:100:magic.wav build lightning wall:100:magic.wav bullet storm:100:Whoosh.wav burning hands:100:fire-spell.wav cancellation:200:swish.wav cause light wounds:100:magic.wav cause medium wounds:100:magic.wav cause serious wounds:100:magic.wav charging:100:magic.wav charisma:100:magic.wav charm monsters:100:magic.wav color spray:100:magic.wav comet:100:swish.wav confusion:100:Tear.wav constitution:100:magic.wav counterspell:100:magic.wav counterwall:100:magic.wav create bomb:100:magic.wav create earth wall:100:magic.wav create fire wall:100:magic.wav create food:100:magic.wav create frost wall:100:magic.wav create missile:100:magic.wav cure confusion:100:magic.wav cure poison:100:magic.wav defense:100:magic.wav destruction:80:Explosion.wav detect curse:100:magic.wav detect evil:100:magic.wav detect magic:100:magic.wav detect monster:100:magic.wav dexterity:100:magic.wav dimension door:100:first_try.wav disarm:100:magic.wav dragonbreath:170:Missle1.wav earth to dust:60:Explosion.wav face of death:100:magic.wav fear:90:Tear.wav firebolt:100:magic.wav frostbolt:100:magic.wav haste:100:magic.wav heal:100:magic.wav hellfire:150:Missle1.wav heroism:100:Explosion.wav holy word:100:Tear.wav icestorm:80:Missle1.wav identify:100:magic.wav immune attack:100:magic.wav immune cold:100:magic.wav immune drain:100:magic.wav immune electricity:100:magic.wav immune fire:100:magic.wav immune magic:100:magic.wav immune paralysis:100:magic.wav immune poison:100:magic.wav immune slow:100:magic.wav improved invisibility:100:magic.wav invisible to undead:100:magic.wav invisible:100:magic.wav invulnerability:100:magic.wav large bullet:100:swish.wav large fireball:100:swish.wav large icestorm:170:Missle1.wav large lightning:90:lightning1.wav large speedball:130:Gun-5.wav levitate:100:magic.wav magic :100:magic.wav magic bullet:70:swish.wav magic drain:100:magic.wav magic mapping:100:magic.wav magic missile:100:swish.wav major healing:100:magic.wav marking rune:100:magic.wav mass confusion:150:Tear.wav medium fireball:80:swish.wav medium healing:100:magic.wav meteor swarm:100:swish.wav minor healing:100:magic.wav mystic fist:100:magic.wav paralyze:100:Tear.wav perceive self:100:magic.wav poison cloud:100:Missle1.wav polymorph:100:magic.wav pool of chaos:100:magic.wav probe:100:magic.wav protection from attack:100:magic.wav protection from cancellation:100:magic.wav protection from cold:100:magic.wav protection from confusion:100:magic.wav protection from depletion:100:magic.wav protection from draining:100:magic.wav protection from electricity:100:magic.wav protection from fire:100:magic.wav protection from magic:100:magic.wav protection from paralysis:100:magic.wav protection from poison:100:magic.wav protection from slow:100:magic.wav raise dead:100:magic.wav regenerate spellpoints:100:magic.wav reincarnation:100:magic.wav remove curse:100:Evil_Laugh.wav remove damnation:120:Evil_Laugh.wav restoration:100:magic.wav resurrection:100:magic.wav rune blasting:100:magic.wav rune death:100:magic.wav rune fire:100:magic.wav rune frost:100:magic.wav rune of magic drain:100:magic.wav rune shocking:100:magic.wav rune transference:100:magic.wav shockwave:100:Explosion.wav slow:100:magic.wav small fireball:60:swish.wav small lightning:70:lightning1.wav small speedball:100:Gun-5.wav strength:100:magic.wav summon air elemental:100:magic.wav summon earth elemental:100:magic.wav summon evil monster:100:magic.wav summon fire elemental:100:magic.wav summon golem:100:magic.wav summon pet monster:100:magic.wav summon water elemental:100:magic.wav transference:100:magic.wav turn undead:90:Tear.wav wonder:100:magic.wav word of recall:100:sci_fi_gun.wav crossfire-client-1.75.3/sounds/click1.wav000644 001751 001751 00000006532 14165625676 021172 0ustar00kevinzkevinz000000 000000 RIFFR WAVEfmt +"Vdata. ÿÿýÿüÿþÿÿÿþÿþÿÿÿýÿþÿþÿüÿýÿÿÿüÿýÿÿùÿýÿýÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿýÿýÿýÿýþÿÿÿÿÿþÿýÿÿýþþÿÿÿÿøÿ úÿýúÿÿþþÿÿü üþÿòýÿÿÿ þûþüÿþý þÿú ÿúþ üøýúÿÿíüüýóüÿþÿýùÿÿÿþÿ+þÿçÿüÿQ:8ÿM8ÿ¢bÿ;2JþCîýÃÐÿsÎâÿ™ÖÜþK\ÿ÷$ þ ÿõ\(ÿ#\Âÿ嶨ÿUøÀÿí>ý+ýÿöþéÖÿ! 4ÿý'æ(ÿ þ ÿíÒý þÝêýÿ6ýÓîüíÐýÿöþäÿ) &ºþúÿàôþÛ$ÿÿÿéüüÿýû ýïþÿùÿ üöûëüýù þ ýéþÿôÿùüýóúþýþýÿýçêÿûþþþ ôýïðýüþüÿ÷ý òüùÿýûÿñúôÿÿúü%øýÿñþÿýÿ ðÿ þÇýýòþÿ þÿüýïÔþûòàý øüðý' þþþóìÿÜþûîý#þÞÿÿÿýÑýåàÞÿ  ÿåýòÿÿýùþ èÿþÿÿéÿèÿ öÿþÿæÿñþ ÿ ÿÿÿéöìÿôÿÿüþþÿþýÿ ÿ÷ÿûýüüÿÿøÿ ÿÿïÿÿûøÿÿúÿÿ êÿÿ úÿÿþþý ýÿ þÿ þñ ÿôþ  ÿùÿ ÿÿÿÿÿþ üÿúü÷ðþûüþýúüüýÿþøÿÿþþùÿìþûúïúúëþ÷þÿÿýþÿÿüþéþÿïþýþý÷ý øÿÿÿùÿùþûþ òÿÿúÿÿÿõÿþ ÿõ þüÿïþþùþñüÿ ýþÿÿþÿÿùþû ÿðÿÿÿþýþþùþüþôýõþÿþóþÿüþ úþÿúþ üÿþÿ ÿþþþþÿùÿÿýÿÿÿÿüÿþÿüþýþÿþÿûÿ ôü þñþþþÿþÿý øüøÿûÿýþüÿýÿþÿþþÿÿõ ÿÿüþÿþþÿþÿýÿÿüÿüÿþþþÿÿþÿõþ þõþýúûþþÿþþÿþÿþþÿÿÿÿþÿþÿÿüþöþ þþÿúÿÿÿþùÿþþÿÿûþÿýÿþÿùÿÿþþüüÿÿþÿÿýÿúÿýüþþøýÿüþþÿÿÿÿÿüÿ þÿÿüýþÿ÷þýúþÿüþÿÿÿüÿ þ÷þÿÿýÿþÿÿÿÿýÿýþúþÿüþþÿýüÿûÿÿÿÿÿûüþúþþÿÿÿýÿþÿÿýÿÿÿÿþÿþÿÿþþÿýþþýÿþýþÿþÿùÿþÿÿÿÿùþÿÿûÿÿÿþÿýÿõÿÿÿýÿûÿÿ ÿûÿÿüÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿþÿþÿþÿþÿþþÿÿÿþÿþÿÿÿýÿýûýÿÿüÿýÿÿþÿþÿýýûÿüýÿýÿÿÿýþÿýüþüÿÿþÿÿþÿþþÿüþÿþþÿÿþÿÿÿÿþüûÿÿÿÿÿÿÿýÿÿþÿÿÿüÿÿÿÿÿÿþÿÿþÿþÿþÿÿÿýÿýÿþÿÿÿÿýþÿýÿÿÿÿÿþÿÿÿþýÿþÿüùýÿÿÿÿþÿÿþÿÿþÿÿÿÿÿüþÿÿÿÿýýÿþÿÿÿÿþÿýÿþùýÿÿÿþýÿüþÿÿüÿÿýýýÿþþýÿþÿýýÿÿþþýþ ýÿýüÿÿÿÿ þþýÿóÿôþ ÿÿÿýø ÿ÷ÿýúÿÿÿÿÿÿÿþÿýþýÿÿÿþþýÿÿýþþýÿýÿÿÿÿÿþÿÿÿüûÿýýýýÿÿÿüûüÿþÿÿÿÿýÿýýýÿýýýÿýÿÿÿÿüþÿýÿýÿÿÿþÿÿÿýÿýÿþÿÿþþÿþÿýÿýÿýýÿÿþÿÿÿþüÿÿÿüüÿÿþÿýÿÿýþÿüÿýüÿýÿÿÿþñþÿêÿÿþùÿýþÿþýùþýýþþÿÿÿýþÿýýÿÿÿÿ þÿÿýÿþÿþýÿþÿþýÿÿüþÿÿþþýüÿüýÿþÿûýýÿþÿþùýÿþÿÿÿþÿÿÿþÿÿÿýÿÿÿþÿÿÿcrossfire-client-1.75.3/sounds/blip.wav000644 001751 001751 00000002452 14165625676 020747 0ustar00kevinzkevinz000000 000000 RIFF"WAVEfmt +"Vdataþÿÿþÿþÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèþõ*þ Ìþù6ÿåÿýÞþþìâÿ þ#Ôè8ü ÖÚ4þéÿÓÿ%ýÞÿóÿÿüæûùèý1þÿË ÿÿ*øýíðý(ýùÒþý)Úþþí&ÿüìþë$ÿÿÍÿó4öÿÿÞÿ  ÿýØþ/âüÿÜþ' ÿãðþ ÿÛþé4þù ÿÑ ÿ ýÿäÿý0ÿïÒ "äôÿùþîþùâ*ÿÑú(ÿòÿíúþ% ÿÏþû.þëúèÿúýÛý(þÛþç&þèÿï ÿÖüí2üùÜþþþÝýû0üíØÿ ýîýéþ $ÿçÿÝ(ÿÜÿûÿèÿùì,ÿýÿÓýÿ$ýÿîþóþ(ýûÔþý'ìÿõîþ ÿûþþÛþÿ&ÿßÿýîþþýñèýþÙÿï*þåúþÿØÿó.ü÷üßÿþÝÿû,îÿÞÿ ÿõæýÿ%êÿÿÞÿÿêÿï ÿçþã&ÿÿþÝüýþêÿûìÿ'þÿ×ÿÿëøýõ(üûþÕ þ!üðÿóþ#üØÿ#òöðÿþÿÚþ&ÿéúîÿÿüÿÝÿ!äÿýìÿýÿöþå àÿë ðÿëÿßì$ÿÿéôþÿÞÿí&ÿÿæÿùÿ ýáýï(þýâýÿ ý ýáûñ(üûþßþ ÿãþõ(þùýÝþþèÿÿøÿ%øÿÜ þþéþüù&þ÷Úü ýþÿíüþ"úÿÜþ þüþïúÿýÿ!úýÜÿ úÿñø þûüÛýÿúôöþþÜ øÿõôÿþÿÛ ÿý ÿùöýñÿÿÛ þýúû÷ðýÿý Þü üýüÿùðÿ ÞþúýþÿûîÿýþýÝý÷"þÿþüíúýÞþÿþÿþÿýÿþÿýÿýÿÿÿÿÿýÿýÿÿÿcrossfire-client-1.75.3/sounds/ouch1.wav000644 001751 001751 00000022730 14165625676 021041 0ustar00kevinzkevinz000000 000000 RIFFÐ%WAVEfmt +"VLISTINFOISFTLavf54.63.104dataˆ%üöüô üöøþøþ(ÔèÜ ôø èøö ìúôöþþòöôú þøøú üúüúüüøúþþ üøèî LÞòœø8êäîØü>îþâîþøú ìôæêüòüìþøðúÖ ZÞ € 6üÜ&ìøÒ DðØöüúô îøæê þöìêô& @ ðÜ€*üD*ÔèàÒ>(üîÆþìôàÜþü0.ì6€âèNJ*¢öêÞ @þ¦æòþ0ø òþÊlä€ö@úÒ ôÌò HòÒöüüNî˜Ä"`ü Îîúðì:üÜÊ "¬äª& TÖØèôþþ<ÚôÚì  ʸòò2"(Ööðöþô  þÒÜ,2¤öÚ$ÞöÖôìþ4*æàúÜX¸ôžDæäîòôúHàÖø6ö.€$öB.ô ø&ì ø:ò´êúôf4æˆðÌH Òðòòö $È ÎV¼¨<NèÐÔ*þö"øî¼2ø|ºÂ²LNÊôî"ôþòþ4æöÒPüL–ÈüX(¶Ü úòÚðøn¼Š \Äü¼þò(êÒ(‚à60¦ð üøÖèRâÂÌ2FÖæÔú î þðî4øB’òì@2¸äøø øäú6Àô°. BÂþ êøä.,ļô>è¸ è îô þH¸ú²TÎøÎøø"öü ê æ¦ô04þ¦ ì òæþüøD²êÊ0PÔàâæúî ôâìª"$N⨠úþ0êîú"ö4¬Üè:@ÚÊöÞ âü¾è¸.$P² ø2àþú0î ÞR"Òºââ î¦ôÄ&D¬Ì ô,Ö6Ìô übüÎÔæ ð þú"Þž ð.D"˜Úú(ð&Öü(šìÂ2bÌêÔàî&üì ø0òâ¾"BBðþª èú.âð  î ˆöæRJ¶ìêÜôòô" "ö*ÎÂÈÚ,N(Òø¼öü,Ò&ÐîŒh(¸ìöÖ(òö,,ðªÀæî@(HÄþÊþöÒ, ¬Ü¨ læÄìþÚ*èü.6Üö”ÐþúZ(*òÈÎè æ(&0 ô–àÊ0&XÒØàÞÞü($,ÊÚ¦Ô Z&üÐÚþ Üþ&26 ðÖîÞN@ÌèÞÜ à&.. ºÆ´Ø TüÖæðÎ :2ØØìèT8àüÖàôîú$(8 زÈÈ4BôæöüÜÎú 4*&.æî Ææê6",îäöþØöâ $:(ÀЪàúD"òèìüÐö.(,&°ÄÈÜ@,ôæøâúÔø*.ؤÐÐÚ6$TÄÜþÜð &626öšÂÐÀ&R.äÒüäòàö 20&&ú¸ÄĬ ^: Þàäæúâø*& ö2îæÒ8P06øúâÖ Þøâô@0ô *ªÔ°¸ " ÊÔàÜòÚ>6"Ö*"ô”Ô èH4núî¼ ÞÄàòÆ<NðÂT ،Ԗ\4^ðèÀ>àÄÐðºPHâ$ÀT6ò€È˜èn$lüú´Pàкô¤H$4:ÖÈ"b<„´¨˜fx"î¢4¦ð¢ò8 `úÊ` `˜Ò€ö$ê0ØØ.ä^äØÞˆê6Nî2Èþ, ²€æ¨2NFÀúôjè ĦìªB2Òî T\°ÈŽòòlÖ$àø0öhææÜ®ôÞ$òøø 6,8¦ÜºÐî@öúö ÖôÜÒðîúô&2$ÎâÔ¶ðâ$öø&þîÒîèêúö  4LüôÔ¨ÜÄ øì@ òÈæÒôðîì $*.4ÊÔ¼ìþø6$$ööÔÜôèôèîìú( 086øð¼ÀÆÊèö J*æêÐæöÜðÜèô06*.*8èêÆ²ÖÆäþì"L8æâÞÞüÔêÜÒüú4.*@Pîà¤Ê¼öæî$$X$ÒøÐäÜìºôê,>("V ʰ԰îôÒ6L 4òôîÜ ÜðÚÀìØ0ü*,N2ÆÒʸüÞìØî*408øòòêÎÖÞÌ ü ":$LþÖÄìÎúôØðÔ > "üúîìÞÔðäöþ.&"$ôþäðèÞôÚàæôêìäæèæöîø$.".ôþæèèÚòÒÚâð êðäæêäúàîò**"6ööäâêæØàìîüþþðøêæìæâæöþ&,:úúòäþØâÐÜêê " "öüðêîÜàÔêîü ,4.0 ôôøâðÄÔÒâøö, öîìàÜâàôöþ(4 $þþúäæÌØâèöð* êæÞÞäÞìäòþ &$&  þöìæäØÞâìòú  ððèìîìøêòö  üöòðäææîìòúú öøôòìðîòðøü   úöòììîòìòøþ  üþöòììîðòúúþþ  þþþöôôêôòúðøü  þüøúôôöööøþ þøüøþþüüþüþüþþþüþþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüüþþþþþþþþþþþþþþþüþþüþþþþþþþþþþþþþþþüüþþþþþþþþþþþþüþüþþþþþþþþþþcrossfire-client-1.75.3/sounds/chord.wav000644 001751 001751 00000112610 14165625676 021116 0ustar00kevinzkevinz000000 000000 RIFF€•WAVEfmt +"VLISTINFOISFTLavf54.63.104data8•ü  øþü ü üúüöøöôüøöúôúþøüüþðôðôðôöúüøöúúüúøúúüúþ  üüøúöøþúöøøöúþøüúüøôôöôööúüüþöúøþþüüúþüþü þþüúúöúüüöúöøüüþøüúüøöôöôöôúúüþøüôüþúþüþü  þþüüúöüúþøøôøøþþúüúüøøôööøôúøþüúüôþþüüüþþ  þúøüøþüøôøöþüüüüüúøööøøôúøþüüúöüþüþ    þþþúøúöüþüôøôøüüþüüüöööøúöøøþúþøøüþþüþ    þþüþþúúúöþúúööôøúþþüüüöøôúøøøöüúøúúþþ   üþþüþüüøøüüøøôôøöþþüþüøøôüøúøöúúþøüøþ    þþüüþþþüþøúúþøúôöööþüþþüúøôüøþøúøúþúþø þ    ú  úöþþöüøúøøöþòöððøôòöîøöüêðòìþþúüüú  üþþþþþüüúøúüøþüüúöøôþþúüöüüüüúþúþôþþøþúøþúúþúüôúþþú   úþ  þüúþüúöøøúøøøöúöüðòðúøüöþ ê   þ  âøîúþþòêþþþüúúþòòæúèìÞòôôöêîàôööðö   4"îòúèææàêæêäàúðüðêîà ôøøøòîîæèÜîììâðêöþðîØìêø ô þ  ü òøøòôðöþþøþòöþêîøìøúúúþúúêìàäüìüþþ   úîøðäìèêðòèÞîîðâèôÞòî ô $&, þþöðòòæìæèÖÚÐòÌØÒäøîÜèâîîòþü$,þôú úôþèôüþìîòäÞÚììîèþöðöÊæÚüêððü  &$üîöúäòúòÜêØòäääôèòîüþ ðþü &úæ òöêòììîôææàäîÚæî þöüð   þ(ü  þøøöþúüêúîôòú ø êôúöøêôöäüòöèüúìèâöüøþ ööì öìþîìÖèæôøðîæüôæîöøú $& ""(,  ÞúöðêæèäàÞæêÐæÞðÔÔàÜ úøþòþþ  $úìúüôúîôììòîöäêäêÖÞàêæìöúàîîîüþ$þ2 øø øôúèæàêîêîæêæúäðîîþþ üþü þööþüöøòììêæèðööú àîâôþ     þð"øø$àâøæþøÜøäüîÖììü üúîøêüüàøøôöäü$ þúòâÖÈâÖòÜÚæÖôîî òö$.&., 8" * æòîòàäÊâÞæØæäÜÚêòêêööúþèüò úþöúüúô  "*øúè øöàüêþâæäìêîêììòúîúòúäìôô òüòøöòöøúþ "  þìôîîøÀÎÊÖÔÎÖàÔæâ2 "*  üøúâêòÚäêìôüüâúîþò ðüþøüîúðîúðþä( öòæþøöîôöòþæüüøú òæþþîôÖüúøìúüðþøôôþ . . êüøìâòòøÜâØàÞàäìôø<0""ü.," îüúöøÞæòòàÚÜÚÜîîôúÖôìðòþ þòþúþü ìøä &,&(* ø&ØôääöÚúòðÞìøêôúøðòòÒìÞ üôêàðæþÞòò   & 6"(üòøäìæææääðäèàØêäÎðð  $& þ2( ìúìøððôâòþþüöüèþúìúþòôêæôèôþö  0 ( úúøôúøôÒþîøüôúúþ îøøüøòìâððêîàæàòôêîô * ü >üôòôôöøúüîìèâàêèöÜüú  $    îøîîðöôæúúèÚêÞôþðÜîòðèòúþúþþþúðøþø "$úôúèøöúèìâüðøôøôîþêúàèÞÚòæôèæäôúòüþ2.4(" *þ ôôöòäêäêòèúÊêâðêôüò  üüþö òúîúüÒ òøæöäúöþüôòôâèöúðøúè     üøîìèæøàøöìàò èôøôþøüÆöàêÔÞÜâêìúö(468< þ" òøðòøðîîú îøÌ øôöøâêôôþ êþîäêöôöôþø þøòòÜìäÞöàìâ  þüþðäúø âü ,&& îüøôöþôðæôììòòøüþìòæðúôöôüøþâØØâìÚêÐ  (:8R "$ ôöâìîêöþôöþàÜæâðøðîæÖüö  þ þúôðòöôüìêèàöèìèäìâì òäøêÞìþ þð"." üþøüòôÞÔøüì  ò úüüöüøöôìúöìêØêàÒâàöÒÔü(,"(*"&îúöðèòìðæöúúüêôäüöúöøäøø 0ìôøüúøúì øöôàüæöÔÚäìöòöøì üö þþîô(òöèêìæöÄèÖ ø $þîâúôðòôþüøôâøæêæâèÞúôüü0,28*"&   øêêàÞúòäòòøìúÒúðìîòÞöüî üúúòú úøÞêÜþÚæêîòöìúð úü ðþìúôüøüø "  þöâöæúæêøì ., øúÜöòö øöþîâæèÜÖààæÞäú     òð ú äæêæüöèôôòþøòðèüþ.úôìþøøø þþîúþâøîöäÔÚäìðöò ü þüæ  ä  øúôöØæÜîììþê   üüðüîúôèòàüúö úôòâðèîêêîòòøì$$(, ,$þòððööàêêðôìðþüþôøÞöìÜððø$öòüô êòìöàìÞâèÜâìòúþîðøøö þ úø$öìòþêìòÚ ,þøâðâðöðüöøÞììèàäÞîìðÞðêþ & "  êÞææþìþìþ üöâðþôêôø äúòúúú ú òþôîâêæêèäâøÚêàú ö  êèôèììèúÚîü ò þøðàôúöúêþúúîôìêôòüìþ"(&6$"þòìÜÚîìèøìþðúÖìèöòô  øú üüþÞàÞæØââêàîööþ þ$ ðþþîþþìüööìööþþ  ðúøòæàèâøðèîâüîêôêðÞöøúöþö ,êþüúöòôàøö   þòúòüìæðîþòþüþ þ  ö øþâðøöðìààÜÖìèðø   þöôøòêúòþöôöìþôüô  þ úúÔøìúöäðîôôòþèîøü öþøþöôò þôðèæúòôâüúúôøîìöìÚêÞ" úúþ   üäøòöèêææÜÞÞàîòô&  úðòþü  ôþöððüð   øüôöúÖøìüèæèôìêêôêöþüúàøî ðþúú$   þþêøôüú  òúüððòòüæìðæ úøò  üþø úìüèâêæðäêÜèîòôþú  þþèüøö üöøööôö ôø îòêàìèöôôúôúäðôþðøÜ ü  þúøøøøöðøî úúþðôôöòòäööøòìü    "ú èüúôàêÊöÜàÌâèòò   þøþüøöþþòþü þö öðüöüöÒäâäöðèöòöêüüôôôà" üüøø ü úôðäöîêÚøøîüöô öü úøôððèàÖäâèàôö ô üþòüþúúüôüþ ö úööìøðêøâêàòúüþöäøîôôöî  öþþú Þôê   üüþþøúþþøöèôìèôêôäø þ üðìÚàæÜæàÜæòèôæ *ôüôêüüøþøðü    øðììðææêîòìþúúøþîþôôìèþðæþ øüþ üðöþìøúæêæèæìôðö ü ü  úþðòìÜôæüØèæòþ  &þüòþöüüðþüþìþð úþþüøôðôììðîöðü úòö ôúüîîðúüúú þðøöþø þööðòòìæîÞöøþ ú    üøúøðîìÜÞÜþÞðÔþ  þòòîôîþöüü ò øú $úîöøðüðîìêêèôòøüþèúôìôúäúúôþ  ø "þ üþîîìÞîæèàÞòüüøðþú òüøüìöúòîîêøîúôô"   ðüîôìîüøüúò  úþúøü  äúìòîìøìôðþüúüøôøîòæðôþø î " þþüü úþþúîîØìææøæúò  þøü  ðôäúîììòæêêðòôðüþüøüôôèðò   øü   üðîèüîòòêòîü þøúæöþìøòøæôöòú þ þ  øüìøöøöîîæÜèâòøôøöúü þúøèöòøöøúúîüú   öôöîøþöôúöüìúôúüúô  ò ôúøþîôêòúüþööôôúúööðêìììþú  öþüüêôîøðîúâìæ   þô  úüüüòøòúôòòêòìöèòö  ðú ðìäøôþþ þüøú   øúöþüôöòøøüôööþòüøöò üúôöðîîððúöêòì   þöîþüìîäæêèøìôôìþþöþúôøäþøúöôööø  üúüþúòöääîðüþô þúüòüîúøþúðüòöðöìîèøðôúü   þ þüêêüüðôîììêúöú" üþôüôþþøúúîúøöüþøôöäúôøúþüúúöòúüüðúü  þþþôö øüðöüþúöúúþôüôøöþìøôøôðæîèîêôú þö þþæòêøöòôæðîòöþ ú þøüòþüüôüúøøìúü øôöððêðöúòü   øüøúþþúü úúüöüôúôôôòøòøìæèìòðô   þþøþüþþþôòòêöôööúþø  þìüöþúøüüúøþøúäôúøøþö þøøòôöøú   úúüøöþôþòúüúüúþðèêúôúòöìôòôêððòôü $öüüøööúøôðúôúêöøö  úþòøòþþ ðêôôöþüøúøøðøôþöøôúþ þþöüüöü þþ ôúøø  úúòüôøêäêððæîðö  &  þ üô úþöüöøòøúøüúüþøüò üþþþøôôðöüþüüüöüüúòòæüúüþúúøä  þüþöüþþþþþþúøèøüüöøüäööúòêðäôòöúî   þþîöôöîúøøüþúüúüðúüø þøþúøúúþøþ   þôþüúüôôòêþþ þúôúøôúøþôðüþ þ øþôúúü    òøöô üöþüúöúâòðöêìæàôôø    þþøüþüôüöþüüúúôüüþ þþöøöøøúúü üþööôìüôööúüþ þüö úø êöôúþü þ  þüþþôöðúüþøþøöìôðîðøöúìúú üöþôþòøðþþüúúðúúþþüøöúøøöþ  þöúôôôòôôúü üüòúþþîüüüöü  úþþòööú   úüòüúþþöüøôöôôôìîìæúòøèúúþ  þöþþòþ öþúøôøööü  ôþþüþööòòþü þþþöúøôôôüúöø üöüø úö þö þüðüôüôôøþþ øúôøöøþþòôôøòðøöðîøôþþ   üüðòøüþúþúüöþüøüúöôôööúüü ôþòüüúøúô  üúúðúøüööúöôøôüþúþþôüüþþîøöúúú  øúöúôúúþúðîæòìôêúöúúðòòúþ  òüôü  úþüúúöøúüþþöôúøôþúþü òøþøüòòðîüúüþôüþ  üþþ þüþþúüðôìþþ   þþüúôøúúüþþöôôîðìôúüøúú   úôþþüúòþú þúüööòüöúøöþ öú üþüþ  úþúúòðôèôøüöþüþüüþüüþúþòüüüþö þþìüöüøúòøøòúööúîôôôööúüôøú   úôúöüú úúòúúþöüþþþøüþþüúþþþþ þ þüúööúòìîòöúú  þþøþøúøøøòþú   úþöøôüúþøòöúðúúúüüðúøúþü  üüöööþþúþúìîöôüôúþöþþ ü úúøøèôðøîòôö  þþúüþöþîþøúöú    þþþþöúîôöúøøøöööôüôøøøþúøôðø  þø þüþöþöúöøüúüþöüþúüþþþúüüöðôòòîúúúþþøþþ þøúôöúúþúüüþ  ü þòúüøòúúþüüòüúúüöüúúþðþ  þüþôúþüþúöüøüöøúðþüþþü üúþüøöôìððôôúø þúúøþþüþüøþüþþ øüþðòøôüöøôöþúüôüüúüþúðòöüúþ þþü  üøòøúôúðúúþúüþþöþöþþøööôðôôööþþ úþüþüþþüüüúþú øüøôðöøöþþúøüúúþúöøðüüþþþþþüøþþþêøôúöøüúü þþ üúþüöøîøòööòøðü þúüúúþøøúôþþü    úúøôôòòðþúüüúìþúüöúêöú þ þþüþôüøøøòôðøøüüþöþôúúúööðòôúúú  þüúúþüúòüøüþüþüüþúüöòööôøôþüøúøúôüþøöüú úþþ úüüôöööüøúöúüø þþüö þúüöþøüìòòôöþüüþúüøøúúþúúþô ú üþúøôöôüöúüüþüüúüôúøöúøúøúüúþþ ü þüþøüèðîööúúþúþþþöüþøüþòúôü þþüüúúúøúøþþþúüþþ þ öúøøøøúþþüþúþþúúòúöøúüþüüþ   üþúúúöðòìöúü þþþøþøúôôøöúüöüþ þüúøøüüþü üþ   þøøòîøúúüúüöúúöúüúøøôüøüüúþ   ü  úüìöðúöôøðøúþþøþþ øþþþüþøüúüü þüöôöðþüþüöüþüþüü  üþþüüöúúþüþúøúþöøòüøøøúúþøüü    þúüúòðîööüüþ  þúþüüþúúøøþüþüþüþòüúúüþøööúöüúüþüüþúþüüøúúüþþüúüúúöúúøúòøôþüüüüö ôþøþôööôòôøúþøþþþþüüøþþþþüüüøúòúúúüøüüþüþúþ øüþþúþüüüþüüþúøôöôòôôüþ þ  üüþøøøøúøþøôøþ úüþüüþüøþþüúüüüüþúüøúöòþü þþþþþþþüüþüüüúþøþüúúúøööòøðôôøü  öúþööøôòøøúþüüþúüúþþüþþøüþþúüúööðøöþúþøúþúþüøüúþøúøööòöôôöøøü  øüúúüúúøúúúüþü þúüüúüüþþúüüþþöøüþþþþöþüþøþþüúþúüþþüþþøüüüþøøöôòôöôøúü þþôúøøúüôúøöþþúøúøþúþüüúþüþþþüþüüúúúþüþþüüüþüþþþüþúþþöúöüôôðòòööúüüþ  þüüþúöúøþþþþþúüþþüøøøþüüþþöúþþüþþþüúüþþúúþüüþþúüøúúúüöþüüòöúøòôööú  þþøþþüüüüüüüüúþþþ úüþøøúúþþþþôüüþþþþüüúüþþúüüþ þþþúúúüôúøööòôòöööøöþþü úþþþþþþþüú úþúöüöúôþþþþþúúúþüüüþöþþþþþüüøþþúüþüþüôøúøöôöôúþüþþü  þúüüþüøüøúüüþüþüøöúúþüüþüüüøþþþúþüúþüþüúúøþüþ üþüüþüþúúúúøöøüòòîüúþ þþþþþþúþþþþþúþüüüúüúþþþþþúþúüþþþþüþúþüþòöúü þüúþþþþúüúøøøøúôüöøüøþ  þþþþþüþúþþúüúþüþþþüþüüøüþþüþüþþþþüþþþþúþúþøþüüüüüúüüü   þúüúþôööøöøôúúüþøüöþþúþþþüüüüþþþüþþúüúøþþþüüüüþþüþþüþþüþþ üþþøöúøþúüþþüþþüúøúüúúüúúøöúøþþ üüþüþþþþúúúüüþþüþúúüøþþþüþþüüüüþþþüöþþüþþüþþüüöúøüþ  þüþþþþüüúøúööøüüüúþôøöúþþþþþüüþþþøþþþþþüüþüþúþüþþþþüüúüüþüüþþþþþúüüúþúúøüüüüþþüþüüüøüüþúüúúúúüþüþþþüüþúüþüþþüþþþþþþüúþøúöüþþüþüüþþúüþþüüþøüúþþþ  þþøüþøúüþúüôüúüüúúúüúüüþþüþþúúúüüþþüüþþúþþþüüüöüúúüüþþþþüüøþüüüúüüþþþþúúþüüüüüüþþþúþúüöüüþþþþüþþöüúþþþúþþüþüüúþøøøúüþþþþþüþþøþüøüüü þþþúüüüøüüüüþþüþüúüúüúøüüþþþþþþúúøþþþøüþþþþþþüþþþþúúúþþþþüüüüüúüþüüüüþþü þþøúþüþúþþþþüüþþüþöüüþþüþüþþþþþüþüþúþþþþúþþþüüúøøüøüüþþþþøþþúþüþü üöüøþþüþüüüþüþþüöúöüüþúüøüüþüüüüþþþþüüüüþþþþüþúþúúúüþüþþüþúþþþüþüþþþüþþüþþþüúúøþþþúþüüüüüøúþþþþþüúúúúüþþþþþþüþþþüüúúüüþúþúüüþþúüþþþþ þüüüüüüþüþþüþþþüþúüüúüøüþþþþþüúúúúúüüþþüþþüþúþüþøþüþþþþþþüþúüúþþþúüüþþþüþþüþüüúþþþþüúþüþüüüþþþþþþúúúþþþüþüþþüþþþþüúþúþøüüþþüþþþþüþüüüþþþþþþüþþþüþþüþüþþüüüüüüþüüúþúúþúþøøøøþþþüþþþþþüþþþüþþúüüúüüüúþüþþþþþþþþþüþüþþþüüüüüþþþüþüþüþüüúúúúúüüþþþþþüþüüüþþüþüüüüúüüþþþþþþüþþþüüþþüþþüüúüúüúþþüüþüúúúøþúþúüþþþþüþþþþþúþþþþüüüúþþüþþþüüþþüþþþþþþüúøüúþúþþüþüþþþüþøúþþþþþþþþþüüþüþþþþþüþúþüþþüþþþþþþþþþüüüþþüüúüøúúúþþþþüüúþüþüüþþþþþþþþþþþþþþüþþþüüüúþþþþþþþüþþþþþøüúúöúüüúþþþüúþþüþüþþþüþþþþþþþþüþþþüúþúþþþþþþüøøøøúúüüüþþþþþüüüüüþüþüüüþüüüþþþüþüüúþþþþþþþþúþþþþþþüüøúøøöúþüüþüþþþþþþþüþüþüüþüþþþþþþþþþþþþþþþþüþþþþüþþþüþüüúúúúüüþþþþþþþüþüþüþüþþþüþþüþþþþþþüþüþþþþþüúüúøöúúüüþþþþþþþþüüúøþþüüüþþþúüüþþþþþþþþþúüúúúúüüþþþþþþüþüþþþþþþþüüþþüþüþþþþþþþþþþüüüþþüüúþüüüøúøüúüüþþþþþþþþüþüþþþþþüþþþþþþþþúþüüþþþþúüüþüúüüþþþþþüþþüþþüþþþþþþþþþþþüüúüþþþþþþþþþþþúüúþúúúúþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþüüüüþþþþþüþüþþüþüþþþþúþüþþþþþþþþþþþþüþþþþþþþþüüþüþüþþúüüüüüüþþþúþüüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüúúþþþþþüüþþþþüüüþþþþþþþþþþþþüþþþþþþþþþþþüþüþþþþþþþþþþþþþþüüüüþþþþþþþþþþþþþþþþþþüþþþþüüüþþüþþþþþþüþþþþþþþüüþþüþþþþþþþþþþþüþþþüþþþüþüþþþþþþüþþþþþþþüüüþüþþþþþþþþþþþþþüþþþþþþüüþþþþüþþþþþþþþþþþþþþþþþþþþþþüþþþþþüþüüüþþþþþþþþþþþþþþþþüþþþþþþþþþüþþþþþüþþþþþþþþþþþþüþüþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþüüþþþþþþþþþþþþþþþþþþþþüþþþüüüüþþþþþþþþþþþþþþþüüþþþcrossfire-client-1.75.3/sounds/Missle1.wav000644 001751 001751 00000052604 14165625676 021342 0ustar00kevinzkevinz000000 000000 RIFF|UWAVEfmt +"VLISTINFOISFTLavf54.63.104data4Uøæö úôæêúÖøðüæöîÈîââôäþ(ôô0ø "* *êÞôàìôÌþîÐÔÚâÔê¾øîúüä$ð ð ø * ò :$ $úþöÚöèúþìòþøöæòäÜÊÂÐÎÚÒØÚæäôð4*(0.6&"*0**8.<,ü öþ$.êâºÚÐÜàÞà䯨ÌäÞâÜæäÜÐÄÈÆÌàÜæÞàäØâô  öîîìü (8@6B8>:00.4622."îúöþôúâàêèøþîôêö þôäØÚÖàäôüøðîæîîüôàäØèèü<àÆØÄäôä0$4$ää.&4<6F ú ØöüêâÚÒÐÞêì ÔÔ¼ÎÐØäàâÚÎÌÆÔØö @24ê.J.F:6F2B0$*&"$ üîøèæäÖÌÐÀÆÊ¼Ð¼ÐÞêþææØÎÐÊäìôüòþ 6B88:ü:44J"0 4üöø 2 6àÖÚ¦äêºÜ¸Î ü8öòÚÈâÚæ    þ$øèÚ¾îÔðÜÆÚÂæþ(òüêîüø  "4üôÜ òìæ þìÞà®ÚÎ(ðÆØæì$(&&ôà.úøüê<H""þÆÞ¬ 4èøúâòÄÚÜþüö&üìâÆÔä .4J&ØöØ*0,Dþ ìäöØôäî06F24$ôèÈÀÚÔ( 4ìÜÂκÖÔ(ôæÒÈÌÞú282äâÀÈÜø4.LðêôÖôê24@.äðÒàÂ2üØêðäèüôþ,&>>ÒÈʼä4D2(ììØìÎúø* Âæâþ0úäøö.øèêÈöðøäÆðæ2,èôàîø&>::>öìÂØØØìú,öâàÚÞàôBø$øþäÊÞ¦*"&øê8$&îèÜÎôú8&( â䏯ÒÂþ¾ôü*úêÎÊļòöô0824îôD>.Dü,ðú"6âȾÎÄæò(.øæÈÆÆæö (& ìêàú**$úîàâÖâêü ØèÖêØÞâäðÚÖæÒþ (þôÜÂúò,< 4 òà. ((þðÊÚØø ôøðââðÞüüü 6äèúà Öø 8&.4ø¾&4F:$$ÊìÚä6FòüÎþîðüââÚ¼ÊÆÒììüÈÚÌðòö (&:&Øðôú ø   ÔÈÖ¬,þ2 24ôäºÆÒÒ2 Fð¾ÌÎàì$(L" ú "2øâÚèêðF6&$ÒÔÀÂÚî26<@ ðâ¾â¾âà 0<>4üÈÌÀÆÔî( $ôúÎàâþ. îüôðÆÌàüäÜÊ´ìÜè B ÀæÂÞȺâÈ((>@ììðìî<Ô.ö¸ìD22æÔθÜÒB,@B"âàò*è  òîòäÖ..@@ Âξ̾B" ÒöÒØÐÜúúîF@*>ðäÊ´àÞ2>J8*ÜÖÈÈØê,** äÞÀÂÖÚ2FþúêæÞöä øêèØö*682 øîÚÔÊö @0B $&ðF66 Ò Ú¶Ø¼ø:úâļҼÄìÞüþÜäòÞÖ®îâ<þ ì"20úæààÚ"2B@2<ÜÖʸê ( öÔòÔØæäþô.88<>ºàÎ âì .4úâìºÈÚà<"HúüÎØ P&*î æðÐðÀú80..&ìÜÊÆÚÌ*2B0öú,þÈììð , ìÈÈÀÎÔð$" ØÐÄÂèØ8.4JèÚâF&úðìôL2þüúàÄîÎ(6,RîÈÆÀÖð,*@0øþÀðôòö $Bæðìâ¾ú.,,*òÖÊÊÌÞ$HðÊÔÄÔÞò 4&"ÌÔ¼Ò¼ÒÌæ.>>8<ìÞÌæì*<8@4"äæÜðâüô44@4FÎÞÆÜÔàö @0Föò²þÖîâÞ B40N ôìäâè$(*>P úÔÄØÌ ô& ÖþæêÀÈÌ´àÞ øÆêì ôÂÖÆ¾îì  ììâêü$*6>öêüúà,øÀÞà*òÀÖæþ<.&âò¶úæòî,:&F"$ôæêÚà X(2$$(þÞÞØÈú D.òôüæ ðÞȾÐÞ4&,8Øð¾ÜòBìòüîøðüäð 0ÚÐÀÌæð(.,2 䨶Øà ðê $ ÊÒÊÚØ .6>6:êÞ¾ú.(. ììÒÐÖú(4ÞÈÆÔÜü:$þÚÔÐÖD* âæìú  "ìò0"(".þüäîú4 $. ÀÆÂÎÀòø$20ÔðÐØäÂÜÎâþøòîúèä&> öàæ2.ðêæÀü,öø  òúäèâ242JòøØØìò$*êöæøìþ*2" úÞØîÈ0DÖÒâØBÒò¶ðüöüÂÂβH ÄòôæúÒþ <.@²âþôÒþà24<<úöøôÚü"$ü öìÐÒäÐòèö2 Üôâ &æÜ¸Þæ0 ðêØÖ8*þô>0"îèäÒþ2<@,ÚÒÀÂâø6 ø êîÞø:ôÞöâöü ,þêØÌÐÊ  *ôÌâÎÌÚúîàÄÂÖÞ*Dúê<(($êþ8(2 . üèÖÜÚö "  üàÔÎÂÐô"(*üøôðàèîÜúüèþ ðÞÒÄÂÈÌö 4ÞøâüàðòòÈèàâ øüüðêèÖâè0<6&"Úî  :"( ü&."æöÎô$* øäô¾äò(,*&(äì¶Úöê0þ ¼ö.îþÀÆÐ¼ø2øôä ìüæÞ : öòäààÞ ä  8âÞÌÞÎðB.80àðèì 2 >ðòìüÖø :,Öòø(ìöÐØÚÜòìö$ Ðî¸.ôÒÎòìþ àØþ6Àì ¶ÜÀÔøîô2"Hêܨèâ:DJ>(JîÖ0,B&@846ø Ú*&`àøú"ÔÞÊøÜòÔÊȶäì>628òäÊÀÊàú ÄüÎÒª22 úÞö´Öâ6 îèÜÌÞ îò.âÖÚ¾ææD 0üèØþüþ*.úìÌðôôþÚüâüÈØòÎ*$@F Øæòô"$$6üîÔààêâ*$0:Üî øìøàü²$ >\ò"ê ú>ÜðöÒ >þÊúô"$òòàÔ¸àÐH0<Fø èÖîô $.äòÆüþÞ þêºàÒêæú$:8 ÆÂÚÒð ,P">âÐÆÄ 22*ÜÌâæF2ì èää¸ÌÎìì> ÌôÔÔðì 8 àêÜäèò<"4(äÚ̺þþ" èðôÚ RÊÒÊ¼Þøþ$èâÒÚêäN4 ö 6*F$ÎÚÄ(&<$æèâèþ8: øðâæÐ  ìòöîüöÒúÚ8,*B øæÄàæ(þ êê¶ÒÎö  ,êòºÜìÖ> Æö¼ä4üRîÔà˜:ú0ÌúÈâZ*²üÚø8ò$ÌØòü4Öºô&>üÌÔÔäö..4(ê²ØÐHHèüúòð*,\¼ úæÀìøò>ÄàÚÞ2$úìÊÞÜæ42Hþè¾öâè:0ØÒ¸þâôâ.¼äÂ. úöèäþê&>@6(øÎÔ¸Îöðþ &üîè¼ÒÀØV$æêê. 2&àÚöbªôÆîÜÈü2ööª$ò&° îLòò üêøàò 4&:ôðÐæø &.ôêÞÄ F:䨏ÈÎÔ(8&òàÈÄÈÄâü*48B ú¼æ¾ÖÒò H6B.(èÞ¸Ð(òÊ*0Dö´ÊÞè $2üèšÒâîØØð*`äÂÚÈþ>.öúìÖøò0â <üÆÜîø (ü, üÞòÌ´Þ¤ö(fÒÊ ô.:äÐäÄ*: àÎæàD4Ú"øÔÎè¼â(^ò(øJÌþÖÜÊþ4 èÂÚî(âöðþ,Jôøü2 &ÖÆÀÌÜâ,,2"ìʼÒÖÆ:þøîÚâî.üÒàúö"8.PþìÌÐÞè&62:èÐØÂðF..àâÀòÆê:üÒ&¾ú6ÂâØô"<*,üêúàÔô0 èòT&îÜ*(ðÚÎþè þìúÒì8üúòêö*ÔæÊþâ¾àøÂòæþþ& : úÞêÒøÀ*.ìÂàäâ¶ "ö ú2 þüúàööè"ú@6Æþè ðü $(èìÒöðöô $ÜêÚîþ$FâöÜüìø  îØðÆâÌâ T ôàòæ." üòòÒ âÌÎ>ò 4øÎî"ê\*²äBîØèºòÔÎÒÜøH6$&Èäо ô6ÚàìÐDÖÈÔÊò B"öâÊÂâôüæ6bäöÀþ0îòÞâøÀ>PÂÔ8èðÎäîž0ø&àþ ü,(8$Üàäæî0:,&ðäàÈÞìþ(44, ÆÖÈæ .",øàÂÌÎö *04 &äð¬ J 262ôð&àä(0(ö2àäÆºæâ* H¾ä¸È$ü2ú&º 0ÔôúÞÀ øTìÚºöòøÀàÜü òܾȺÖÚ$$$FÀî*22Hè¦: ä àþâìØìì2" àâÖÚ 0Øö Æ"øX6ö°ôðì$ÎÜÒ¾àà:.þØ<þ$ Ò$@0òìúÔ&*4üܼÌÐð&üîæêÐäè0 þêöæJ ìÖöÚâÄÞè ,"(Æè® îööøØ  ÂØÌÂú66þèÖüú(:àÜÒÜüHÐ2æòÎ 4æäÐØâÚ,*äòìÜè $Zþ$þÚÞRäâÔÀðBöÜüèäÐ üHööÌäêæø>âÈÌ*PðþèH"<8$êîÞ".ºú.æÚ 6üòÜÂúêH0Ê&ð6èÔöö* 2ÐäÄÔþ4, ÐÈÖÎ6èüÄîú8î äîð 4 þðÖÎÈÒþ02 Àêü.@"6ÞâÜöäöîüÜøþúÞèæî.&êðþ îúòÞÒÐààJ$Æ ø.Þð  îÐÞÞÞ2$J. Öèöö:(28 þæ²ÜæÖö,üø Æ<DúüàÊüø02 6¾êÌôÎ$4(&êêäÖêÈ6:.(Øä¼Øøè "4ôæÖÊÞØ(TþæÜæèè,$ÄþúôPôøæÖæÚüö<,8Ðê°ìþö8ü$’ú&ìôøäú&H(PòäܤüìòÚ"ðèØÎÞÌ4(ìò8îÔ,,îÖÔÌþ@ "èêäìæÚ4H PÌÔ̤> üÄàÖàè6(RøÜ¶ìØèö0.ÄìÔÞø> 4$ÖÒ¸ÒÂî &>.RôèÀÜæô& *,("øÚ¶îÒ&âüL((ðöдè26˜òÎ \ØÆè$4(ÄÒδJ>(,ºúØèÚò(&*öüÒÄ¾Úæ* , úìÀÔØÌ**4ðÚê¢ 0,Ðô RØèÒ æè.(&ö*òâÚºèÞ.J ÜÖÞô (,ʾÖÌ â&@:<*ÜðÐúÚÞüàø2L2Ì$þ ÎÈâþ&öÆ"æ â> öÂôÌ,$"Tîê6öþÊÜèòPܼڶúâàúÚ" &âà®îÜè (4þ0.,Òð¤&"êä"þÀîÖðàâúÜ4">*ÆÚÞØöÂäîè <úÆâÒHNÆ*:à Ô42.> øÈÎÔÞê.D>þâìÌÜÂò ÐúÖ(èúÎð$L.Þêľúà&ÀôV&¼ÊØ¢ bà¢ú2ø\¸èÜÆZR(è¤ ,"ôèÞÜP.&öúôò¨2ìÚÒê ,&2< üÀÐÂèî B:8*ôòÈüÂÒèè(&42ÚÌØ´ø.F² à,D@ÌÎæè:ööøÌÔò$6è¸ 08ðÎÚÌÌ$. úÜèÎÈôÞ (þðÈÞÜÒð $ öÌ "&øÒºâÆüÞôà >úÄØúò .L´àPî¶äL&6ìöîìæR6$Öàºà2øÜÖÜöâÜôö, F@ÄÞÐØðú&ìæìÆ(ð èàü62:B ÞîâêÒ*&úÀØÂÊÔæ *.ðîÔä¸úBBþ ú Îäî4,H ÚæÐ"ÞêäúF <ÖàêÄòÄðÜò<&ôÔîÈ"(8Àü:,"(ÊÒúJ :Þ&ÈÖìü.âšþÞàöÌøò&æÚ´îè 4"üÐÖìæF>4&æÜÖÞöþ84"*¸â¶òÌðÈ:èôîÄú6>ääèæ&$62ÎÌÊÖÖ"$0< Ö¾ÜÊ":è2ðâ䨨îò."@Büþ¶Îܺ66äæÐðä2èÀÜ B$ÔâÞÜ8>*ü¸Òʲü\ê ¸H&èÜîÖÞü4 öþ(ðîö$ 4âþÖâ"dôöزüèÌðìÜÊàÎî"2 F ôØÂèæ(B<Ìþ&ÌîØöìÂ6"B* ÀضòbÊèRôøÞø((ÚÞ:àÞ ø@Èèð²ü(<æ¤ÖølîÊÈþ:4ø¾ êúê 6JØÖÜÒ 8ö´üÜ äÚâê(Rðèðš"D$èöÚÖöö.@âàÖÈê:6(Àäº "Ô"ôðÎî®,@&þúÚàêò.(6öúÚÌ Öôö&$úî¼ÔÚðâ6$R¬$þ. üöèØº$è"Êø,8":Ææ°àà4 èððø8ø,0ÎÐðÔLÆüìðö4òâðêø2@B*HÚäºÞ2þòðúÊöÞ,ðÞô¾0BðàØìî æÞôÜÚæîDPüèòà$ö Öþè äæÂÄèØ:20JìôÌîü$6 $âÞàÂîîJÖþ(ø0Þ*. ¾Üàþ"Ö¨ .Ôî: â,ö®îî64¤ÌôìVèø´ðêäæè"62üèÖÖðè$B4F* ØÚÌîæ.BÄÚÌØ"üÒêÒâÔþ >84ðêÒØÊÎ66(ÔîðæÐ6 ¾èÔêà$<<2êÆÌÔÜüP 2ðØØÖð48*Òþ "æ"¾ôÐÜ´îæD,¬æ8úÆú  "*þ¼âÞþ*@Ú$2$JøØêRÂ.ü Î,,æ¾8* ÎÞÐØ@ 2Ð̾ÔÄò.2$2ÒØ²ÒÚìü.4öàèÆæÌ2<D(òòøò2òôô¼ðè,:&ÊÚÚüêþòäþàêîÞúú&($øÞ¾ÎØÒD6 ®0êüîê .2øÚÚÊÌöüJ04äè¸Ð&XÚîäÚÌÒêî ø"$J"Öâ¾Ø B ÞäÖÚð 08 4,ôÚøú  &"îØÈÂÐÔð B&LèìÜÜðü0$ ØÖÎÚìø20$ÊüØ,ð¸ÌìèB´ÔZðð´(Úî PüÖìòôæ Bò0Üø´ò  àö$"àòÜèöøÚ  ÖþÜê´Øð$(úöþÞìäü**<BÒÔØè*òÒÎÖÆöö6 äôÆ2úØî. úöúð´ôê0$HæôèÆ N> 2âö <Ìô,"ÊÜôš ø."ðþÌì0&$:òîÒâÜö0:26 äÔ¼ÒêF8üüÀôðøÎD< Àî*ÆîÔ.òö¶ úØð,àÔžî,&ôüÊÖàÚ"^òêÌöâ4ò$º. ÄìØ>0 ØÚÜèüðÖÖÚîbäüÒúøö äøÞú **öø¾èò&> : æìø4"ä*àÚ´Þàöú:ÔÖðàÆ "DD¼öÜ îòêô"òî ü<2 ÄþäüÞæÜ@þâ@Þ ò Ââ <úØâÜæ0þÚÒ 4 F¨æÖþJ<üÜúä P2àÚÚÐRê.†òüØÐÐ äöî4,ð¾.  .¾ôÚ$$þÖêêð **,òÞæ¨ê$êÆôÒH4 Þ &>¶ôèäøÄôBäâöÖ@< ÜòÊø ââ¼üèúúøàäæâ äBF (ÊâØÖô. ðÔÞRÔäê¸4F úæü0ôôȼèð$,Øââ¾6B Öðìøâ Düþ´ääÞôîôèöÜâü 6&V æêòî842 êäܪîæ"îþ°ÎÖÞô .8øö˜2ü""ÒÔêL(øê"ô,âÜæÜÜø&$>Ðì¼æöøøþôè8$Ú"8(îèêªðú2 &B"ìþB (öäÂÆÀ̸XÈöÎ øúö:0 ðþòäÊîà(0(8ÚöÖè  ìèØêÒò*>.*ìæÜàÒ ôܾÄ þòJ.ò:*DúöÜöÒæÐ2æòÐòâøØDìì *"ÌúäôÞîôê0ÐêâêêB&4ÂÆ8þÈúôÐôè0"(0úÌÞìêú $* ìÎÊÆâô äæäìø $:: ÎÜÄìèðÒ*èø ÈÞîÞ ø2&6ôìîÔèÌð<öðÀ: è¾æ(<4Èð :8ÞöÈâþ@( üÐæÖ2øìöìäÚü  ,(ÒèÆ î"ü´Ðìì:äô(Ì(öþÞôö @"æÖÐîêú"ÀÐÒâ,H ø*ú ¼>2öþêà4ìöìò âò¬Þèð$èèØÚöF . :*ìä¾ìî  ÞÐâÌ Ô(âêøäB6 ÌìîØ æÞòìô$8Fö¨( â æ.6òú¾ÖæÖ4êĸôÜ ô$FúÄìøôüöúê ,BòèÊÆêò,& ÖÜÒÔH4*Üâ¬(Nô ÞÎîÎàò4Úâ®àðòÊúþ"Jôèþð& "(ôâ¤øÚöîø  ä.øìÞöðB(ø,úêòÌÖèêú â ö<>üðìÆîøø*ÈêÎìöìøô ÐöúôÂòöú (4ØÞÐÖÊиîÎöDúÞ "þòÊèÈ" úüêÔêèö,*6$Ä2ö¸øúøÞÂæRô$ öþúÚîðÈ$Rêð, $ôÞ$$&Üþòú2 æ&.8>02 ÆÔ¸ÒÈÆÌÒüèøèîÔ öääÒV *&0þÜôÂ"üêþö"8 ʸäÎ $ ÆðÚÐòòòäØäæà0&@6 ÐÌÜÊ(&ÜæúZÜÔ (Öúðø0 øðöäþü îüÄø"êæÚ ì8öæ¶ð êò.*F$"ðð& ÜìØò üü¼ÒàÒî2  Ø æðþR*< øìþîîÜ ø2äܺÐðêô úøìêú:(:,âêþÚöÞòþÌàêö ìÒÚÐÈìÞFþúôôö8*èüäêîüú>4".ÚôÜÖ(îÆÒØÖäøò, ¦ðÈ îúö@"øüÒ& üÔ2ÜúÂêòèöøü*öþ¸îäôÞ 0ò&(@@:2,äèþÒâÒÌÈÖöðú Ìúì úú 6 þ $ÜàæÊîèôøÖ Ö* $îæôèú¼Ðò*ôÞ,òîÞäÞì.(ÔþDþìôî0ÖêÎøØàîÌøêìèøªôôü4îàìD4 Þø0ôæÖÊÂÚÜøÐö"Öâäâ 8îþÚ84**ÄêÌÞüîÖðâ (@ÖôìÖðÞ Êääôþ$îÊÖ<.*úü.>(úò>"ÚàÈàèàööúòö6.ò& $èìÔÒ (þþð :ðÜôÐì¸ÄÚÐ0$ìÜ ( øúîÊöÚâÈÒâè X"*ìêÌúüøîþHæþÐ êîðôöô òðÚäØÖÀøàúüú"J2<ì øú ØüþÒæêúþìô &6ü 60*62*(þÌøòÖ¼ÆØ¤þ8Þ Ô&.">òÖôðL4þ*þÂìà¨úêüø.òîÔÊÜÌè¸êä"ìüø&$HÚ æôþ¶ÜÄøþà 2ðæðäôèÚÞÖ(êúÚü$þúìö°ðúÄðú2ôì   à öþþè<,2,(.þä þ ÞÎμàìöø2&6ð èöäÚòèð  øöä âòÜÞø.ìúúøêÒÚÎô FîøÚúðäâÔÜììø  ðÒâðæÖâúöôîþ öÜü **ìöÀæöø ôòäÎèä"ôâîô .D,Dü öôâÔäÎF" ò ôÒòê"þ úüîþø,Öîðêòú   ôüääð2àúòæò4úöÚæîääÎÐÄȸÜèê ($&.(F êöú ôôøøâòØü,Dòê ú þìÌôàÞîæòø   üàôêèòø:<:@&øøüðüúú  úîâêèøòüúöø äôîþ "üþæ òþøúú "òÚüæÖÖÞ²æÞðúèòØäîò& <  îþÖ*òðúâÜÎêìÚüÎôüòâôÖâöÚ   "&"  þìîÖúàäöäìÞ î,ö øøêÒÞäàö,$  òòÞêöøòîæàðäøÔþôþèôìððìæèðÜúü úüøööòèòÐìì.6òþîþøþèäâü"  üôôúêöúðôøúîîòâ   *öþüþòöôðâòöú ø öîîüòööþä ,, $.6äàüðþð îüìôøôüøàüöþüèøòèðúðþúø ú úèüüöêüöüüö ì òüØÞìôîìêòâèòàö(þðþüúöþðúà üþìöö  ö ð" øâ öîúô þ"þúò& úöþØòîî þôî òôúÎðÞôôàîòÒ þ ü ä .(úþðüøþøð þþòþüðìêèòü ööôôøú æàÞîØîðöøôêòîðøòöú ü    ÒîÚìôøüþþðúô þìôòðþü îôúòøüö$ö ø ò  þ ø  öþòþøþüöêÜäèÖæêîüüôúòúüþ *  üôþî ôøôäôèúìúÖöôüòöèêòî øþôøú ô øøäàÞÒøîèþüüþ þþ þø üþúòúøøþúúôôöøöðôæüøú þöþ øúþþúüúøøüþúüúþcrossfire-client-1.75.3/sounds/Gun-5.wav000644 001751 001751 00000057030 14165625676 020716 0ustar00kevinzkevinz000000 000000 RIFF^WAVEfmt +"VLISTINFOISFTLavf54.63.104dataÈ]þøüúøþúöüüþø  üþþöîúôüþþüòüüôúøüöüþüüþ þþþþøþüò òþô üþöúôþü þþ ü þúúþ úþôþúþüø þ þúþþ  ðþþþþþüþüþüþþþþøþúþøôþ îöîîìäðòôüúø ô2*ðø 4öòö öîèðÜêðèâüØ(öþöòþú àú2öüôøîøúú$þ ôÚþ|òèäö2ìøüàþ $Øö°(þþøø& Æô4*ìîüèàôäúöþÊìÜî*&îô ÐØúJ2xðâèr">¼üØôÞàÆ"$üøþ 6 î2<èì& ÜòÔòúÐàÀÚâüöäÒþÚºÔ >(00, úðøöèôèô äÎʸƸ¾ÌÈÚÞîü  ,6<HLTVX\Z\ZVPJ>6( üøòìâÞÔÌÀº´¬¦ž˜”’ŽŠŠŠˆŒ’˜žª²¸ÄÎÜèö *4>JRV`bhptvvx|vxvxnpfjbXZNJJ6D82^®êìØ¬ªž”ššÎÆÜÈÖÔÒÚÐÒÊÎÊÄʸÀºªÖÎü¼Ä®šª˜¤”–”𦮯Îâòþ.>JV`jtt~xztnj`ZNF@42& þððæÈ¶ÐÖê   ööðâòØäÀ˜ª®Ì¶ÀÐÈÒÆÈòÚ îÐà¶úBÆòì<,` $D\Z( "44V66 ""úüôêìäÞÚÔÐÌÊÆÆ¾ÂľÞÂÐÆÜúê æÌÒŽÎÀúÊÐæöö8Ú`~~Fpò>à\TL"8¼B*X^ü˜àÖθœÞþø2æöôúöðôêèêÚâÖÚîäªä¶ØÔÀ¬°¦¨´°À¼ÎÚâìöú **.8*2(,.&ÖæÈ´6ê&€òØúôúôüòðÔàÒÐÒÀ¼®¾¸ºàÜ𨺼Ȏ²´ àþîú XZ\p|48äP:Lì ÞÔÎÌ€€€€€€€¸¦”€€€€€€€€€Š€Œ¬¼Ò¨ÈÈâöÂ",ÂBjê L êðÌžÜæú 00&:HØöòBN4V.NNfN><@4<6NRRR\\`\PXHRXHrB*Bf0T æ„`8¤âèºêÌðžÚ€´2€ÐŒØ€€€€ÜŠØ–ºàèÀÊð0@&J¶Df"2 z\@JL4RfB<D0*@(Dþ@€\ð¾À´€ âÊÌ€€€€È€š€Úøü ¾ÎÄæ€–ŒPÐÀl(Dô"(Fèüööð*6\>P@PT^DbhRx4<r\<hp"ô6 ¢Â€°òÖ¬€²ž¼š¢¤”š„°š€€€¸¬ÔضԠ¸æî,$þ2D@24,46&(L üðHø´JH’: †ŽÞ^" ä°°œ€À¢ôœˆ´ŒàÐâÐØö<Jèr&&"&,NTNjZÞN&NF:"8Öî¬æj2:2ô€>îF®ÜàÐÖø¢ÜÐIJ¨’®€ª€>èþîþöÜøÜÜø”Ö°& ,:z*€däf€ÞRæêÖ–ÌÒÄî¸F6Xz"â@ôÐ"2´LìüÆjLRFÞêÌöHV|Ú4ìèÆÄ€ÞÎ$< þžd`0¶Ð€.òèôÆ’ìöÄŒŒº Îä\8êàtR Ð 2ú’¶ü†ŠöJÜÎÊ($D4"ìô°¦¸Ú òîØdB:$Ü(l>  àøâÔ¶ä‚ 44âöâ¶ìÌ.èÖìÒ" <êÒ.6âRðêúèºÀ²¢Ð¤Lð€À€´Nb Úðº BJ8v"4 f6@.4V.\.>`*DöPÚòàÔäި€ôÚðÌöÐðŒ€F¼€Ì²ÖŽÒÂôÞø²ÄÖ¾nîкèÎ ,Tf<Hôn6N0R(.âJú ÔJR~(^Z<þB$&BNFò Ò@L úʘüJü쨲†ê4´Þ€8æ ø€ž€”Îò$¤ÒšžÆ®ÌÀ¼ÎĶҢê0ÎðúìîôD,,`hZ\,Bð t>HìhF4ÐØìîÞÎİœ|"$æ*`(Úæ¸®àº2ìÐØÜšêTøÎì¢ôðúêüè>ŠæÊ^þ¾dÄÞ€¤Ütô€È¬ÚNÜ4€î(Ð bB44àÜØ ¼œ^DrFDH> $,”xL|,:öêð@jP€DÀÈÆ¼‚ìÚÖÞ€ø¦â€¶ÊÔÞ┈€€¾Èê âæ®ÒÖêþ ü 2HfFf\XX&T0"V@V>.F884,.üÞÆ¶Òºº ¸ªÎÒ¶¶öÈÚ’ž€Ô´ÌäÈìÎÜ&$8"0ì8xdzT<Päp*ÖüôÚä⸮¦òÎƼ޾ØþŠ€¾®îêØ„ €ìþ¸À¶¸Ô€üFÔÚ0 0üddòtRZî &6P\pVvF Â*äö€*ì€ÆÌÒ"ÈŒ("&6Äâ€Ôôž:\à*ÞØâŽÖ¨îâÐî–R \èªüÜx$ ÜضÄàæ4>T$J2’Ä¢äÆèð8 þ>ä "äþü,ææÔ¢èÔN*ŠZ`&"b<J@.>$ 486Þô¸(ÂèÂÌÎ®Þø¸°€èΦ¾Ô˜€Š”þ–ƲÄÐÊÄ”ª‚Ôü à¤F.H< úPNxzd6(D4|tX`lV@<6ZÞØÔ0Ðð°äþ(, ØâÄÊ”°Ö".,ð(êö€ò¸€Ì€ 䀮€à äÄÜ€ÞÂÂæ€¾ˆÚ,öô4.,*HXR(âRâ T¸ð$<,<VDj6$(æHîþ²ºÞÞ:0l:¢æülÐŒüêl¨ä¨Îþ>ÔþäH˜ì–BðöÄ̾¸ÔÚæðÜRü"þò p "´hô€öäæ&,DÂèÄ8¦â°  Bìê¶žöBìR.zzD0ˆ"ðB`$Ú öþ."HÎ亚ôÔ$6ôÂäâäàøöÜúÜ:Vüò>òî >(^*Èüh,Âܞƨœ„ÚиЀ€¢Ä&üî¬Ø€0þð¸À8hþàêB*<&&N `ø$^6$ HÜú.JòÜâ¾p&06ÌÔš4ìÖ8<ººªÊæúúF ¼Ôþäz&6ÒÖš–†Š Î¢v(’œÌ JìÈìäîÎ&8¸2àú€(îv®(L<nÌD$F""$" ..X2f è  (RL^"$üöÎÜêÞèü.¼´†€€€¤è–Ô€Þöø€ €ððÚÚ´®Æè@6,XHüöü*4h|\B,2\FBPTræê î6 À–.f0&ìØì¬º€²²&r2àî –¸¼.DBJpFbúÀÔ®öàÒì$ÔÂÎìüæöò4ú¢ü&,Äà€&^äÌ îlJ^0&èXÆ*ZL~>2*Ê,rþæò¦(ð>¨êô4öÚܶÒຼʦ¶„€€€‚’èÄøê,îâʸÎÖÞ,J4@èN PJFü@4æî .nfrt&êòÌàZ2hZTnú€ð¬Þ€ÆÎöððê6ì€âºð€¼¦.€Â„à6öà袒´ªê6بúÆB $>Úúf0â2"> ::@T2ðúÀRJBºÔø<î"ܾâÌîèääÒ¶ øÒì’‚¾ÜØòöàÖÀÔ8(,ê*<t\(ptP4B*8". .~LÒæÞ¤°€öмöô¬þòˆ’€€°ªþöòÒøüü*àøÖèüÞæÈæ€âÒìªâ‚".>6*8ò ünN~d6ª8ˆ26Z.("Øè4@œ, HDö  66 :<F&h.>îÂÊ„Úæô0Ö₤Ȁ€”ŠÎúÖ$öºæÞâàôà¨ðÖN& J4\.ö þ:>b&4ôDH’$ RÔüâ,ÖúÜè8>*>àĸ䢦€ê&øêøÞ´´´Úž´´ì0>:*þØÈÞÒüð *$ òÞÞöF.èüú>^JHJ<\.4üêèÒÒÐò 8$0H(bެôæ4Ö윬æ¬èœ’„ºÎÒªðÚÜ¢Žº®ðúúìææ¾ðîþ &ön^,bVJ84" ,v8fª"þdºüâjÜò¶ÆÎŒÔææ(ÜèÐÜ6 ÆÊÜäì€Ð–ø4”ìÖè&ü.ôPJr*H4*h"Fú&p.,ðìèÄJ^4B H òî𶸬°âêöV6Z¾ê°ÄÚÄê¼@úìÜÄÞÞ°Ô´^öú´Ö´º€Þä8n8Àp6²Â¼Æ6úÚ ô"660(â"ØÌÈh2ú6<>RZdTìööðì& þø ÚÌÎæ äþ,Hò2¾Ô,,t>0@ØŽ$*êÜÖî®®ŽØþôôÞöˆÀæú&ò´Ú¬ òâÌìØØ¤¾ÚÜDÚ ê$äøœèÖ&ðòü@20^ÞŠêêVÖæÜä$<Nrþô@*üT*&nzpZàè(<&DJ² ê$ÐðÜ*²º¦€º†¦ž€€ÖÐ(êÚʼ€¼€ÄƸfÈü€ºÊÄÔ FìôÒ<*ìêîØ®öøj4dR|@~>Ì8"Fb ÚÖàè$þ:<dtvL$Þüø08@B&Ö̆ î4J .îþî4*\BÀê°æîöêÚð2ò¤Ì^æàÀÒ¢¢‚ °øìîôÔâ–Ø8rúȨXê6ôÀÞðR,"Þ Ü&€Â€L¾ò¾ØR"$ ªÚ¬4èþ`8JèjNÖòøüX8P Brìö@4,Øäf:4BÚÒÒÚT"ú`(BôþúîhúÖˆ¸€Êêàô€ÄÀâ¶àðJ最ºÄ>¾Ìä,øˆœ€€öè2$üþÞ$ °´èö8R` .Ú Z"6òÊü¾<$ÒÆ,$hFf>~fDòÚ* .þøà"Bþ$&Ô^ú¸Ò(èzöÜÀ´ø:(ðòîìÌì<Ôæ€ä¸®¸ÐüÊôÔLæô¤ Ä΀â²ô Îø:$("ÖüÆXÚ° Fò &l^JF2ìND¾($dD0$Ü$æ¨öþ$ 0nâÐôîÒ4Æò€Èºä$Öö°ÌÜšÒÚð<öÜüîÖ°Jz€(ðTJ°ðÜþ8Lnd$$úúÜÚìâ B6HDÖÄ >Æ$HÌ’°Ä´¾Ä¸úèÜÖÎÆÚôüêîÞüÞøæÈî2( ì˜ØÎø*tf6B ò>¾Ä4.êä à`b|R6 àêÚ ìÚ"<>D "âæÖêàìêNêúŽ&0´ôÖ*LLÀÖÒÄÌŠ®ÒØôââèÀÜÈ$&"B^JX òÖþô*þ"6H0B"úüȶÀ¢þÔøúì0 Z ôæöÂøš~@ldš&4úÆÚæô"0.üðêîÖä¤,Öô°€–€Ôèö>òþìœì08¸b\ø2<dÒäjDFLÞæôú(rJZ@èæÞðÈÐÜÎÆþV$ò âÄæòüàê¼ÒÈÀЀ¦žÈ>>è$øüþ<4dLøò¸üè*Ô^&,øÔìâþüòòæòìè>Bp0.b0ÐÒ¼ÊÆ° îÆà* Zô¸¸ô¾ÀÆÒ6&úØØ¾Öðþ:2húâ*ø$ÒÔôê P(4.B\>JB,¬þÚÒâÎòÊΪÊÞä0öB"îðÐΪ¶º¾ÚÔâ´æ*¾. ò¶€ÚÔLB¬þZ*F üüÌØÐÎðÖ$4VfHF ððâøî2Fd@<0 42ZfR^ öÔøîÞúê&ÖÞÀ¬´¤´ÚÒìØ  öôÖ¬ºÔú€¬ªBú"2$ èØÒÊàô>R<D`J.Êæ¾ìþú4,:8úèÒÒ˜´ø"à(d^hÖ*ìN ô¨¨,jND@ þþüØêðîê öÔÌìô  úÔØìö  üäÚܸäÄ>, ÆèÞì4Jàö”ôÜÞÞê:îR8@®îèÜðBÚØÜˆ6t Ìú€:âÖºâ4@(NôîÚ¾ØÖÔ$èÊøR*~ÀæLØäløö2L<Вܰ<äúh(ÀÚêÎ òîþ¸ÜÌÔ ú" ì4*"èn"HìöÈô–æÈ âîö8üØ@.$úþâèÚ¼ÈöÌ܈ÎÂÞèøæêöÚæ*..Äøæ¶ÖÞ 66$0$(.0,BJd:(<6 60H\V,Üì  ôδôüò0ÎØ€œ¾üÌô¨ÖÚÜ”žÐоòÚ,8*üîÔðf. ¾à,ââæD$öPD0 ö 082.<:à 4Bd ܼڨ ÚÖØºÌ̲ðö àBÚìܦ2î˜èÖ üLÜü¨`8nöôÆæäLXJjþâÒÒÆ ÔüÀøöìîòò¬òJ¼öÚ*ú æä€úÌäÂÆ†ÞºÜÈÔìô2* bîÞN"4"*&$þèü"ò"D>2,Èìàþþ.6& ¾Ì¢¶øôø æöÊÐÚÚèÐð øì"0ÐöÐüäàÒºäÞ*&,8:6NÞÖ @Ôäš0öÀÔÎì (&&&ìè¾ÊôHBL<èîÐÜÖèþòÎξäúH4Høà. $ÚöÂòúô&"4²îF0ZBT$æàìÆÈäÒ,ÐâXúò¼ðàôøøêî þòÈâ¸4èúÈæØê® D$ ÌæÊÒÊÖêþ:,êf.T ú ü4.4R8nJ2.ÆÞÀ¼üèð Ìâôä4ÂÖ¦€Ü úòðÔðêðÆæòø H>:ðæÜî&.(,8F"øüÞÎΰÈÒììÞÚÖèþ60,ôÞÈºÌÆäæÐäèä B öäÖúÒÚÞ(*Þ. <øäö>(, ììúò**H" ö &@(:>P6@.B öðæàÞÊèÒêèæ¦òÈÞ¨º€ªž¶ÄºÌØÎàâÔòÔÈĦÊÈÜ ô06&$:6Ú$$,$Hè&08bV``4B*: X"" ÎôÚì 06*( êܲÀÂÒ$Èð¬(òÞöøø &@( 2 ôÀôð âôþüôÆøêüöèîàðöðÔæÖâ. úæàÎàìú î" @XB4ìèêö ,0æäÌÞöêØ´ªºî(F(.ú¼ÖÚ0$$\0æðÚâ"HLNB Àðøö &0@@: ,ê´¼ŠÚÎÈÚ à¼(ÔÊä€êÔìþÜøîÜò¤âÚð$þØææê6(NBB8îÞÚÚæü &*<<.8üàúü0$PVÆF JDæÜÞÒìôü þüðìðòððö âòÎÎàØâêÖ¸ôô">44îü6F(4úðÌܸÐÞð&"8*úðþàܪƦÖàÖðÄÔÈìÚÚÐ$úüÀþ6(@*F<0 Úöø 2&L"XbvvJL4 ú>ææÌÚöð(2Æž¨€ääòæ4ÖÜ’àÚêäöúþ`ÖÀ8âì"ÜҶڮЬ"4þôèèŒöÒ.ôàâŠàÒú,* úþ$4<"."L&(8(ªF*lX:Dàþî`0òäþ$$: øÒÄš’°¾ÖŒØÒôþÖÎÀÆööúòðìîðúÒÊò.ôì  $ ìèôìèÎîê.(>(& ü ôøÚ¼ÚÚöþìâîàôàÜàîøðúæúü  (<D::24ú&V.J"T^BPúöÀêȪèþ0(6 à΢¦œ¦ÈÂæÚð,úðêÜÜâàöÖêÜØæØH$>æ øòúL öØ ö.ôú ü(0*JäþÐþæêôøøòÀÖÒÐÜîÎØâàè<ø$* þîðìø*06Lô2N.r2>.**. üöúöèÞÀÔÜìØþ,øàâøèèèâð*êæÈàØÞÎØÈâöÌÚ²ÐÜ8æîàâÔ¼Âêêþ0"8.<>>6" ðäÒÚêòþü$  :. ö $&"$öÖðâìÞøüä&"þÔøÒ."ØòÚôüø"2îì òÒØààþ òø*JH84öðüúúäøæö²ÞÊüîÚìžòÜÒêÜÀÖÀôÚêÚôúøÚòä  æìàèàîô   "F,2$(&&HBZB<2$ 8$DòÄüî8Ü"üÖôØòJòæê öìèäìàêðøìÜÚÊäÚÖèÞþºÞöøÌÎÂôîüÈè¾âêäî 6$0$ÔîøþÜôøþ*L@2 .680ü  04*8"êüØ ðîÒØÜìþ &üÔÈÒÊúðü( àäðàÞîÊøþî J.0&2$<þ ôòôú:èà̴̘ÚÒÌÜÔÐÞÎæìø øðÞܘҾäøâà$&F*"êöìüT*ö$2@LT@L:@,Þü"( þäìÄöøôÒâÐèêêôàúú üøìÄæÊêþÔæ¶üü2øÀêÊÞ2   æøüôöÆöîB22þöÂÈÖæþèôîÜèÔü ðôöîö&üþè "Þòü&,**ôöÒèúô . àââÐôÞîìÜî6ôB øöêäÖîú" îú*"4(èèÜÐìàôôÞøÒ*æöÐðÚÖÊÒÒÖôÈêÔ Rø$*ê  øìÜ îÊ  X(H2:,ZøòæÖ" êèæÖ ö &  úâØ¸ÜÐìðÖÜÌêîæò"6øâÞþîìú úäàÔä  üð$6":&* 4èØú&òääÄîøúØìÌòìöþø""þüü îðÐêú( òôàæì *4,, þüþðüêìØð"62DèþøþúþòÔìÐÞÚÚÆâÞöôòþøìþø,*$  þ &(*0 (( þÞÜδàÂÞºØêö&,2ðöäêêîþüèâêêü øøþèââØÞäèöþ ð  òøòòþð& @D"P$ úø  ôòâúîøøÖêèüþ úòæàÚÜæäôôþ $ 0&@, îðÞØàÚìþ üôòðæâäÊìøôüü8úüô " þ üò   öüàìø*4ìêÄÈÒÀøÌÔÌÌîì ðüÚ þøüúøèêèèêôø, 6   $*.806 ,*$: òþ þ,ìò , öþúêæÔÄÊÆàæðú òþæ$æìƤº¨Ø¾ÔÞæú"þìÚôî  &* (&ô  þ $&þô þþþþòü  öøôòøòøü üîäúæèèüúúôöòð (($þöúðô&  èþøþúð ôäÌÐÆÔÊðöøÖîæìêò þþâòòðòüüô0ú&ö îúòôøø , 2øòüþèöàð¼ÞêÂÂÐÐîúü îââÄìð $ þüúðøäþ*.>:@<.$ìøê   øî¶Ä¶âÞòúäîîæ²ÒÄÔÐÔèìèúôüÜêæîü("4"$,4>  $*.:64"üú üþÞìòúîÞðæþþüôèðêöòòèêìæèæäôÎîâæÊÎÌîöþöö &*  þ $&&:(,&$ 6*ððìòü ÔìÖîìèäÐȬÂÀÒâö  îìÞÜÖÞèðúöþîúê øøøú âúú"üü:ð*ì*4(öøôìüîôôêúøô üöôòæúøîòêæ(öêúðööþú öú úøìòØâäîìúôò$0øæèòúúüôÚÌÀºÀÎð "ôìäú ,,.. öôðþ ,4884"úþøüðþø "þ òäÖȼ¾¼Ðäì úðüèèæÌغÚèèèþèôüüÜ6 î ú00*2 ö 0 þþú&öôîðÚàÚÆêä Þðâä ò ðúöòèÐääø øîúÜøü   . ìö 8"*$ &ü úøðøôêðð üòâÚÜÒÔÐàèüÜÐÜèððÒÖÄÂÈÈÞêøööôðøö .::B40.$"ü $0&òâðê &  üþöüþþ  êøöú îúôîøÞôè þøôìðòìþþööüðòþöüøðÌæÒüÚàääüü úü ú.øì(.<8*$üöþìøü "  î  òöìòøìþìøöþ  ðúü  úøìæôö ðü üòðêöøú úìääÚèêú ðäÞÖÖØÖèâæâÞøú þòúø&&"&& ,46:(*"    þþü øüæúòæÞîæøöôðöîðêäââêèôèîîèøäðÌÜêð ( úþìøüö ,  $*.B ôòîâÞöêÞòðô6ð ÆüøÔäÚÞô ø ôøîüæîêö "  ,üöêêÔäâêüðøðèððöúþîôìøþêø ð,&.,  úôðôöüúøüøüüúôæîìþ òììòêðìêôú  üþüþ &þúúúþüööìðòöúþøøþòúöøþøúêææÞôòøòúð &&*2$ì(ðäúð * úøöúüîüðüêêèêìððøüüüþþ   üòòÜüòüòþîú üþæììî øòôðòüþ îòàÜäàìàêîöôü$ *$28úþ þòàêð  öüôþîîôì üìøðð úöîðìììèðîøüðîæòü"&þîðèòøúüúüþöðèæöúþüøîôîðþø þ$*""ú 0 $ô úüþú þæþ þþöòîæìàäÚòìòìêðìþôøøò üþðþòòêðòú "ú  úüü ðîîìþ  øøæðîö þöæôòþøîäàêòöìúôøðòòúúòøòôô $$.   òöìôøòúúü ôààÒäô  úâàÒâææìôüþúøöòìâàÚðö  øüôþ þöôôø."( þüòþøàæÜðööúúúæîúÞêîöôöúèôèìîô *úøöøú  öþîú  øúôôôðôôöúüøþúúüöðüøüþüô úþüòü ìø   þüöþþ  üôþþ  üþøöüðòîòöþüþêèÞÒàÔøôìâÜääêöþ þîîäòöòüøþ   þ  üüîøúúþþþîöþúððììøøúüøøöôøîþþ þúêòîòôúüøøôôîòô    þ"ôîîæîöú üüþúòöîêþ üþúôúú úüööøöüüúðüôô0$6úúöøþú öôìø*$, úúöðòîööþöøäòèôàÚââîîðôîòòôþðöâú  .&   "$"(ðîêêúú þþö  üìòèøÞêèô þ úúøôðøøþôþ òöìîòðúø üø üòøìôâìòö úøöôôöøüüþúúþøþèìäæúü þ  òøòø  ú øôàÞÜèøôüôüøîìÜäøìþðìîò   *úöôôú üøøòþüþöüöúúîöÞüøúüüüúþúüøþ úúöòôöü   þ   üþþüøüúüèúôøøþúúòøcrossfire-client-1.75.3/sounds/bugle_charge.wav000644 001751 001751 00000156646 14165625676 022447 0ustar00kevinzkevinz000000 000000 RIFFžÝWAVEfmt +"VLISTINFOISFTLavf54.63.104dataVÝþþþúôøôþþüþþþúüòöðú  ø þöþòøöèîÞîôøüöúø  þüøøìþæ& üôøøèüÞâFüúþøþðööêüìîøÒòÖ ü  þôêîèÎþ<öðþþòþöèúÚääø6 ø üîüðâöÄ@èüþþöðöúìøÜòX ôÎÞÂîÜâÜ $2ðÔ@2(*6"F>>B@82(öÖÌÂÀÄÀȾÀÂÀÄ¾Â¾ÒØòÖöúN6D><D:B@<D:@B2(¸Ô¸ÆøèºæÖêææâüðòܺʸÈÀ¼Æ¾ÀƺÔÔèúêü.4@B:D><D:@D.<N6BB8DD66ðäÒÆ¾Ä¼ÄÀÀľÄÀ¾ÆºÆÀÜH<>B<@@>@>@@<B>>B<B6*& ðúØÊüüââÆºØÌÂÀÀÂÀÂÀÂÂÀÂÀÂÀ¾ÚÄÜò J:@@<@@><><.8, >6:$:D62@F,2$þÚÔ¾¼Ê¸îºÂľ¾ÎÒ>ü*(2 øPÒúô(D8@0@6*BF2H$:T þôð޾ΨкÒƺÄж֢"êÞÖæÖÚ2,øú"òôܰè¸Ì¼Øðî4ê  R&J0* øø°ÄƶêÖâäøêÜ,D.XþL64 øüÌêâààÔÐäô*þ"0$:.&L4.P$.2Üú6"""H*8ü<" ìþÖ>êô¨ȾƺƾÀÎôâààüääèÆðÒøÒ$àè¤ÜàøZ 444&J<<F<&ÖVú ªÈĺÄÖôľȺÄÀÄÐäôô`.âðúÆ4ÄðÞÂÜØÀöü ú 4:L 846@<B@4* 0ôÞÞмÞÀüäÜÂÔêò0 @ \ üD &î.ø@:::0D64  âðîÌÖÐÚÞâòü,*6ê.îòÎöèö°ÜÒà¾ÖÖêææâòòÚþôôÊhä", è ²èÆæÈÀʺððêþÒ&$0.(úîÚÚîÚàð²Ü¸ æò¸ôäòðâðúÄÚÖð0ä T4BF4H680",, P88("6,èöþ¸æâÊìôÊ* .øêÜøêöôøÖðÆ îú Î*"L:@D2F:0DúöÀâÄì´Â̦èêúÆÐ¼ðÜê "úòÜÒÄÌØÌæþÚÞòø6400(0(B,&0(  öܶþæøØäæÐÄȺöÀà°êöþ àúô,N"*òÜøâ0"ú"& &*öüîôÆî,ÆæÜÒÌÐÊþâê0äà*  ,D0,H",."., ØøÖÀÈÒ¶ÌÔæþÆÔ¼ÚȼòØæÐþúô",<><@"J*:úüúúàööê"äüôþÞàÖÚÞâäÆÐÌàÊÖÜÌúîB$þ":$,*(8$   bÞúþìèÚòðÒÔàÞÀÖÊÚÂÚâÎ$ìöÒüìîðôô0Ü",,4( î  þôþðâÜàÔÚÄÊÒÈØÚÖòàèääôúþ"(ú"& $þüêþ* êþúúþðîòÂèæôâöøüìüâþòüâúø ôæ *ø2 âþôðöþèîêÒêÞÚêÌÚÊÞôòêöú, ..&*,,  ôþìô ôüÐÞÖêèàêÜÒÚÔðäêö  "  øüúü ø&"îúäðòâêèæèÖæîììòöúøúøþüôú&ö úúø àøðâÞèèâàêöôàêîìúþ  ô   $"  þüÜììÞðêäøðøîúþøêîêüèèÚøæìàèî ,&&("( úòøøÐôêêðêîôäîàòôþÜðôöü   öô þúîòðêææêÔØÖÎâÔÒôÞæðæìô  $ $*0úþ ðîêæöäêÐìæìäðôðôôøööîøøôü 8",  þøðüøüøêìêØâÞààäìöú"$ üþúèääâòäîêðøúúþ þ  î  þþöúøäôììäîòøêøöþüüôúþôòôøöîîìòðöè    &ü üüôøúúôôøøúôööú       üôöðìèæðìèàèäöÜêôìüüöúðüô  þú êîæìâæôäÞààÞæìæâêèúîôðþ   üòööúøúøüðöþôúüòø üþþ *    ü üêîêìäèæìÞäÜîèìþöþú   üú  ôôöêîîæþìòàäðîôêìîîìîþüúü  üþ ü âöâòòòêðìüôöôòöôüôúþøúúüööüòðèêêîðîìüìòèúøþìøüþ  þðúðöæêêæêèðäîìöäöìðúøúúøüþþüìþöòþúúê øøìòØÜÜèìÔúö  öúòÒüøþ  " ôÜ6 øìòòÚüæÜð°ÖÄðøêøúî "þîF2"îöðäüâêìÊê &êèîþîüüìúÜôôîüðîþÖðÔ:.ü üüø öìÂþþH ôâøøôüøúØþòþøöêÀ"8   ú äÚjüüþöúòöôöØìÖèüª(F î  äþöúÞ8( öúüøðìêÖäôô ÐüÒ2èþþö öøòÔòÜ.´V àîàÄ êìæ¢D"æööðèòâòèàØØÖðäð0Î(T00,6 0$0&öôÒäÈâðòª"øøîþüæøðêèÒÜîôî& ü& ø þ Î*,F&æþþÒäÀààºÒ°Òæø8üêüüê  $ôü*´ðš$">8 ô ü  üâøøèšä®$> 4Ôðøø üðþæàÔò ÔÔHP"â$øôÎò¦Ò8\àâø èòÆäÆÌF>Öô ôÜüúìôØôäöÌÞäX>Þ((ð øÖèܾüTìêþèæîòôöüÚþòøæÒæÚÔ,>þ *  Úøì @*üò ôøþæöôèöâöÄÔ°Üì<î þêüâüüè" Ôþâ:.>,âðìôúôúèÀò.* þØæüÞôüôôÞêÐÔÀ `  øÀìÔ::òäòðèöàøîöØàìâºþâlôòúþìöôà0. úþò þòèöâÌÚäÔ2ðØòððúøþ  ,üòô0<þþøüèøøöÂìÆôôúòöøþâú¼< òØ((èèÜú´ú ÚòÎæúöòòøð Úî ø øÜäÚäðøôèòôú î úäìæÜúâöôþ  ê  úúöþÜúìøüØìÜ üþòô $ þøàþðöòÈüúúì " úô ÞþÞ0 ðøòþüæèâêÐààÈìüüè B$îì>òðôâ6àìðüæîèöÂ< úøòøÚòîöòÜúæðêäòJ .þúööزVöþôòêêðüúòðÐîøþÚ.þþþêìîâìþÖ2à üèôøÚþøÒ&,òôòôüâþôîôÖàÚìä> ü  èúöìôÒúÔ0 è ôäâÈ êúø îüàôüöìÞ âöÒÐæ (>.ø ü þü Þþ¬ôbèþæþúöìØäæì¬è¾<.4 þæò òæÞâöš(Z (  þ ÞúøÖðÈÆÔÞX$PÚ âÚüä¾â¦âL> üæ.   ææöð¨êŽn"@îØøîòöÞÊè¾¢ "Z(4îòö(2Ôôòܸ֜$<*($üæú, " ðØøüÎܦüþ.>".öþè &ðüøØÂÄÞø"*B6òüþØîâðÂÖ´àô $Üüêò$  òúàÚúôJ Nøúö ðúèöÊÔÞª$æPúøÜ"ö úêÞàÌÞÎTÞN ðB" öúæÞø (ì8"ôüÒöþÔúÖÎä¶ÖØLôð ú" üðîðàØ @* üø ìæÒîÒܾ<Üü\ò òúðêööòæÆîÖê¶êR$$ ìêÖæàÊÖø"*L òúüþ  îèÊöÔø¨îü(ä8*ü ø ææäÚªæÖB^ò "ôÎòب<àúüúøî*üÔôÊ,âØØÌ* 4øöêðÜ  øòÈ$îÜö T.F þþúºØÐÞ´à°ôPøî øÌêöÞÈöä6*ô  "ò ê0ÚòÜØ( \üêîðú þÜÞô èºäØNîþþöðÊîøâ´(<2äüüú êÞ î þÎþP$âôòúö üžèèàþÒè". î  :ÆôÎôøäÞJúúô  (þîìôú Ä2 üÐôô úúþôúòà òêü2 ðþä ðöþîê:ò  òòôúêôøàÚPøæôìþúîúööôöüþâ .ø î$úþüøîöî*úúøôþ öìþèèôÜòô&êðòÒþîð ø. öúúððêîðôîîøâ,ôüÖÞ üêúðüì ø üü"æ  úúþþðüüöúøüòæòööæüòöü þ øþúôòöö Ôþ úüð þøìúòþøöøüøêÚ$öøþô îò ø@òì þ üøüòüþúð öüøðúü èúúîüüìúô úþþüþøøüìþúìøòòþö þ ôüüüöüø úò ü öþúøôä æ ö  úþêüúòööìüøô úôüøþôøüîþþ ü îüôòøü üúîúüøäøüüþò  ðîüøô þúúôþìøøüüüúøüüôúþÚþúüúú üú øüöþúü  üô úüøæøò ôüòôþø þþèþøêúüèüöüø æüþúøþ öúúúüòþðþðüìüþþêúüúîþôþèþ  öþþê úúôüþòô ôúöð þüøøôþ ò øþþþ øòòðÚ öþ ðüþìÜò þþòöúþþþ ôö þöðøúþ æôðøþøøüôþþüüüò ì ôþú úôüîú êþ ðôúòðüü ôþôòüüö  úøþö øúþîøþö  ð üþäüþþ úúöþøöüúøòòüöüþúèüþúø"òøúöüò üþìöòþøöþì ú  þøüì  øøîúî  èìúú ôþ  þ"òüàêþ þøüþþ ÚðÞþøúð þúþôÊøöüòø þ ÚòÒø ò þòþöôöôÈôØ2 ì úüþôèèÔæê.úô úüüþòèöÐê* ð ôöèüì úþøîþèèÔö6ú ö öüêôìÐâ"æ  îøöüôîüàÜ:î ô üöøòöòÒF"üúþúþüèüòôðúØæFìòîôþôø ÞÌ0øèöþþþøþàúúüâÚ8Lô þò äü öÚÜØØX&äèôÞþ þèþôþèòÊ4îÔô ìþôþ Úø8LêüæÚò ø Îúòæøþö,ÊøÚB&èîúè> "æâöôàöÐ86òÔBîÜäêîÚêº ÊÞ (*îþîÜîÎêäB¼æ@Ò ìXæöòä$âþÎÖD@ÜúøÈL 0äôüàðÌâè$ðÚâþ"8òâöðÂúö *èÄ6&Ö ìÚø®üàNþÊôlüöø ðöÆîÌô>ÜôܾPþüô ôð¨öâô0þ$Îîæbô" ÞðöäþšüH0ä‚RHú òôðþðÜöÊ&.ª¸pð öüüîøðÄ °BòêøøòäèÆþ,ðúÞB ðþúôððÌðÞ2ô ¾.(&  þüîøª"öþì 4þô öþöøæÐèÆBÞÜê" Ü þ üøÜÌÜØR  üþôþüöÔæÖî$ö Â$  â þöüðöÐâè4îæò & îøúüæê¼îÈ>à(ø úôòØìÞ$ìÆRêø þþþ þøþðêì¼"òÌÞâ êúÐìâ& .Ú$øü  úôøúöºøþêú äþò îüòôòöÒ êø$øöò øöøäúøþ"èúüðöüòþðþöüððþ "úø üúò þøöðþØ$ü î âþêðÌþüöúäòøîöäæìüþèöÚþ üüüüôüÞêòÜÚîÌ2  ô ú üüôúìêø¼2  ôìøÞÐØÄ8.öüðöú ÞøäúÐÒö$0"þô " ò$úþþÚø¬0üäð üú"üø öòü´ìÀBìô *ì à úêèö°, 0âäòøìöðÒìÔ0 $âêþþ" òüþøìúàÎ6äø $üöîìðÜæ .þøîþ"öòîìÚââ .öìúøúþøò öÈ î  ìúîúØþÈ> øìò èðøÞ(üø¶æ"êøâ$&æúòâ:êøîÊ(ö$Úøú(ô üöêääê82Ââæô.äÒ" ðÐþBâÆì&Æä.ðÜôÈ0ÖôÊüöØ òòòÄ òTüÒúâ2 öþ úîêæÚ: "úðô°ìâúü øîÜØò>þÔöÌ@ðü" þìÌ(úäÄüêè$ø úðÚôÖ"  ðìäÔîð  úþö ÈüDâÜì&üüòþÞþ´H èîÔÔüð ôüîþúÈ öNöêìÎ,â$ê æøÖ@ÔøÒÞ6öôêÆöò4 ìØ,ø$ÀöÜ>*Þâæ²(îú2ððüêð8ä°<$úâ´øôú  ÜìòìÌÆXÜî ø*(Ø.ôÆ2>  ÂÚÈ*ä .øôöÜ&ÞîäìBæê¢äî ìôðäø< ºîØ*Nú þ öîÈ:ìЮòðì4þüêüòæ & ÜÜÞþL øúääüøøúØÊæÞ &2 þêþðê6þúæäÞÖöö*6 êîì ìæ6öæâôÄ B*üàøò äô( üüìøèÜüÆ\( ôâèþä ,öþüúêî°DðúúêÔ Xîòúêê¾F&ÖìôüæâØ*èöþîòàòDòòøêôö2úüøô¼&>öøöîäòÂ& 0øøÒÜhþâôôøÒú:ê úìúÒ* øæòäø$úòüô æêÜ,*âðìæîÜ8âððÄ>þú òðòÔ8æöÞÊHððôÖðôü8þðÞ"úª8þèèòèøBöìöüþöâô:ðøêúö* òæ ôêæð*þâöîøôîò(æöò¤Nâúúð6èúúúø¼üÖFþîðúêðì>þìþò øøª(òæì &Ü,òîþþæÜ2Þúð$ôþþ( äú ðºêö*äüÈü úèþôúþô´* (Ôøè$òþ ü ¬ôB îøò"Øú(èÖ ðæââ¼"ü2äöòüà$ "Þ ôþÔô2$Üüèò þìüø ÀèâöêøôüÚ òþúðö0äðø(úüì*øüîþ üÖþúòòöÖæøøú òö  æþôôðþòöüêøöøúþìüîðüþúÜ  èþîê þüôöòôúþúîüäøüüüüþòòîöèþ  òúþî öôøüúüööü òêôøúø  èüøø ü üþüüöðîòòðþð ìüòüðøüú þþþüúöüúòøôòþü öøþþôôúúþüþþîüòþ î üôþüüü öú îøúøèúþæøøèøüöúøöþ ö þô èøè þüøüþþôöøüæøöøúðúüôüî òøöúøüøòüÞöêøðøþú øüä úþüþòøúüúöø üîìþøôüøøú þþô ööþîþú úô öþ üîööøþüôð üòüüüô ú øöúüè èþøôøüþîþ þøö øþúúþà èþüþøøü ðüôþü ôúîüöò úúð þøüøúüôüü úê øüþþüþú êúúî  üþþþèúüøþøþúüþþô ôø þþøðôøþøþþì þüì þþìüþ üþú þ üþþô úöø öþúòþúþþøþú üúööþüþ  þþüüþúþöúøúúúôúþôþê ò ø ø äøüþúúøøòðúè ô þøúôöæüú$ôúþè üúúôðÐðä üþêþòðØüà*øøòúø ðþðøôÂ4êúúü ðòìòÜðØ<&öôâôîþòþîâæ .êüþèòøÚøÄ"îêúþöþèøöÀäFêþöî öîðúÄ: .üÜöþîøîððÞàü:"úòøèüúö âäæ <ø ðúêøìüÜþäüä(.ôöôæþäþâ ô Ê.2þ Üîþü "þðàìÞÂDÜôÊ0îü, æöðÖ$öÐ" øÊ  8øðè,ð Æ.<èäÜÆ&îNàôðÒìô(šÞ,$ô ÎØê6ê&0ø ôìä&ö¬F,Öœ> HôôöÆ"ô þ¾þö¬öÚ* BìðÜêä.ä¨ú2ðòè®.RÚþþê Ø êü.ÆÖÎ*îLþìÚêÞ$öúðÞ(ì4Ú˜þôjøúêôæüò,Ìþ4òÎöð80RòäþèôÞº8ôöðкü<äüæìúðØ$ î ÄèÖ"Xìâòèîîâ2øàô¦ X âúìäòðø$ðæêìÀèø&Døþàøøô(þÜþ¸ú \êøòàæþ& îðîôÈöÐN*.âÚøêæöúú þîöÐäâÔ<.HòæêöøøæêÊøæbääðøêü úæàØâÐ:@þöìþìêèþÞþÄÚöD*æüôèäü"øîîþÌô¾Z$òþâööúò"ìâôÚè: "úúúìôþúôôæÔòÞHú(ððöððîÈ&"þ$&ÖîàþÜðÀúî:ø&ðöèìî&Ðøìòøü$þÚþö$üòðþì üâðüòêþü ðôþòèöüô   úòìþî òô$þ  àöîøò ôúôøü$âöøæüøúüðü ø øöððü èôúôøìøúúâú þþüöôøòþüþì ø ô úüð ô þôøüþ øè öôêþêþü ò ø îúìô  þþêöôÞ üè üøèèúî0øþêüèðÊ"þü üôúÜèä> î øøúîä¾2ü.ÚþòüôðôžèP þþö îòÊúÀPþðüò&ú¦ , ô þúìø"ÚÂò6 ìøòðàŒJðòî þ¸êÜ:$üìüðø$ðîÖæ: Høúðìüè.üîœ ø:ôþÒ4ʪR$8Øðêüîô(èº "Høøèìì ÖÈê0 ìêæ öÆêð®` DìÖð<âòÌ®(ø\$ü Îúè,ü –ø®L4<ºèü$þÐþœþ*Zð êÞöòܲøp,úÞ ê þÖ€T,BÖÌòò>êîü°þðò8(ðØÞþ¶úÌX "þþêø äÞò*þôþê0äþÜÌ øöøîêþðêÖöÚZ$Ôôþöì"âòú¼F"ì ü¶"þLªòÞºü¨j"üèäÆ.öØ´ú "¶î"îÞ¼ü($ *âúÚâðBàÜð´h èÖöÎ0ôäìž& $úÔö¬úÌR øðÔ.μ,ìâì¾xÆ”< "ö°"øRÔÔò6>øüôðàÖR$îø¶T öâöäÞ0†. 4æòìîòì:¶þ²XÆô öôð¶2 *þÊäî ÀØòB,"Ô äîîÖÚê<6öÜöô8ôôèúöÌ@& øø²Hüæô&¤þL¾äRîö Æ ®T " Ьnòô Îìô¾"> ò¨, ü¸âØ:.úòÐ<"îüÀþðî@>Þúè0ü,ÊüÞæ$Dèþª8ø&ºæö²X øÌ¼bîöìèþ¬$@ Þ ¶&òØú :2ìâÎ $ ¶ØF8¶äâäFâðºôôÂ: \òúð Rü"àŠ" Hè¾&ü:F¦ÖèÚb,¶¤júþÜÆüþþ6ò¨ú,æÀò(2îÎàø(&TðÐD>âìâÞ@ü"Ú¶þ ìnêþä–<þ.ð:ŽþÌ\â¾þØ*8ÒØö@Ê®^ êô¶ ø.^ê¨" 0 0˜ÈR6¶òàBø"Êö²,øôHêÞü(ìüœôDì âÔ(Îðæ úðÖ ö&,ôòÎø&þ<òäžløôð¦þ,òðÌ þ *¶Ð:ÆÚfè úºFÆ ÐJæþ&´àð@䤸 .ð  êìÚþ îæö4ô,ØÚ2>âæØä<úèÐüÚ:üä¾.îÂô¼<ü¢üÖ>ô Ê> âÊH ¬òÜ 8ô& . "úòÞÈZ æìØPÞæDö¸â2äôÞ àø®fî Ø$*ö  âú¼æ*þÐüø ò0Èâàøêúöô àæ®Tþø  ü0üúöÐöèþ Ø&üäøìÞò ü úðöâüøÜ öèì ,äìèúöä öúÜþìôÞúþê ø îüàøþüà2î ðÞøüü è ôôüüêæøøÊúöøòæþèö ò$æøôúüæúøöæðþööú(æîöîúöúòöøúøê4 Þúüðøöþööê Þþø òüôÒüøöô þþâò$ þôøòìðööòìþò ö ò ü úøüðìþìôôþê ö öðüúúþ öúÜ òúÜúüú úÚ þþÒ ò(òìúúêúüþüîîö üöîþ$üðú ðþø$Ö êüäþúâêúøàüäüüüôú&ôúòþæþú0ü òþþüôüæ àúðøþìøþðüúâúþø ðøâüìø(ê þ òüæþþôà ööüòøþìþð"øüòþúô ÞîüþèüÖúðú øò öúêøøþè ê þüüüþø âþê îúøøòòø èì øî  ìøþþúúôþôôþØøþôúüøüöøøöþðþø ø üüþúôþìþöêþþüüüöþüüþð ðúöúöòöþòüô ðü þðþø øþþþþ  üöþúöôþ òöþðúøøøüø üü ðúþèøúôþüôúòøòøüúðîþ øöúÜ úøüü ðîüøþþúêúþøàþ ìüòâþ üþ òü"Ôòþøüúøú äòø úðò üö üþööö  òþîúþ üøÞ$ðöøúüæôôþ üèò þðþúòüúÖììö þîöøü øòú  ìüìôþðþüøêþ øôø øþúèüôþúöîþêìüðøúÞúêä þúèðî(æ  øæî ôúòöú üöôæÔ2üôòøò øòæøþèüèêøôÜø,üôìüèìêÜ DüúðüôèÒþè2ú ðÞþð" üøúØD 2ÞøîìúôüöòØ ìøÌÒ< Ôúà6úøüàúð, ø ÎDÞþüÌôº2"øú¦îðøâê&"Þðìäðà&öÊBþþòÎ ø Ø&ôôîÐð0Öîä8òüÞ2øöÞü8ÖúÐ8ú¸<îîðöæ úÈâ8úøêüÈ,þúÞþDÊÖ:îúêÎüüöÒ :,ôþðöàîêD öÐî^ìÒþþøÐ.ðæöÚ,0"üØ" òôôü¶F.âÜâ°6 Xæ"îðôæêü8öâôØè8&ôð$ðöÚÞläÐðJ ò.üâæêäôHú Äæêð^$ÒüúøæüÆ(ÊöÊJ""öäðèÚþHÞîÆÚ@þòÞøìêBøäìÂ"Jà òàÎú\üÆØ>à0 ØÔôÖ0 æº àföÞèðÔH6ÌèèüPðºT ÎæÄò,.°ø®6 þÈ$ ðìâü:èøÌö0<¶ü.öþÀðæ$ðžüFìæôHòÀÒðÜlæÌÜLè²@ Üôº88üÈæ þâÔDJÀÚÎÆJDàäìðü"Þâ<ìÂþ0ØÌ($Àü^ Øêúþüèøðöä4þòÎþìþÎ è¾X$Þöúþþ øèÜ,"ÔþØúìæúâìð øü*ÐüÜ"ò âÒú$øîüîèøÜ ú@êìúüÚøöâD Úô8ØüêøúàöÒâþî üøüþìüüøøúæ òæúþîúÞ ü îøèüðþþâüî$ò  ú ìòòüøêúüìôþúä îôüô êöúäþúöÚ üþüôòþöúðöòüööää øþÌðö þà"òèàú òæø  ìøÔ>þôøúüôòÊü2öú úäÈæ>øäþúöØú¼P ø òò¨*òòøþöÊâÜJîè þø ôæØî2îÜ, øúè¬& üüðü ¬ò´Nö úüøúàø²"ìòú"ö¦þü2úüðæÖ@ì>öüæ&ðÞº> üüöúêÖä>öîúôÖòÂHìþöüøÈöüâà4ôüøÖ ôöÚì î < ÔèØê ¶&ØDôöÎüþì ®0Äðºæ(òøØ$ô,ôîøÜ Ì$ 2ªL$î¦4Þâ<îð@þúØìê.æîâDþàÔÔ@ôþ Ö*& ú¸þÜDÐæF Ôô¾X¾ð¼:ô¶8úîîôÄôøàèBÌT þ ¶âìNÌèð,âN èèêðì0òî*èðÜÀ0þú° >Ð6è úªþæ@Òäfæ¸läþ®vä¤L6°. üÀ òÆüôRÊþØTôöþØÐÒRÊîØ"(èÖ("èðÞð òÖæ0*úÔúúä¸*òÂRÚHþ¬âÆ2Ðüìdö´VèøªFä Jb¾*þ¾ôT°êfÒBÒàÄ^æüÀP âÖ$þöäÖ úÜØ @úÊ"¶.ÞÊú\Ô´V Ðî¶FÖö°löž(ü êú¨8èø¬ürÂî:ÎÜØRÊàpøº@êèÂ&àü¸L">âÖþØÔ",ÀÜFÎü üÂ<äêò(6öÎ: äòÈDàâÄX¸þø¸.ÚÔþjºàÐîÎ^²þÂxòÂ8üàöØ*êØJ¸ àØ<žþúPðò ðÞèÞöè0HÖ îêô@ÐòD ÂòÄ2þÂPÆô Ðöì:¶öäràÄ2 ìúÀjÎì²8J¦ ê0ìöÐô@®øê^Ö" ºþØl¼øØ6º2úð(ÔðÞê.Ú&,êÌä0ØÞLÞô<àÚÜ$DàúÔDþÞèÔTøîàÞ ØüðÖþÒ Ðø¶äVÆ ôþ0øìÒîÎü ¾@þ Ä 4Æ2ÌôüÌö,îÂJöþîÒæ º2òäìæ ìîö"ø Ô èþ.úêBâììüÖöúä( ìúÂ$ðüö$à,Þþ äþöæøôô:Øþöþê& ÜúèúÖ"üøòÜøôüøúþøô(âúîúöìðöüFìô þè þÀ<,Ôøì Î òBÊúìðþü øÂhÖúÖ øÜöþÞ &Ðæþàú(öòôúüìú þúî"üüèÐüú ê øà êü ì Ü"ðüæ$äì þ ò0òøîòîä  à2úêúöò.Êü öü,Þøìäú ö0âüüþàþú$ÞÜòþôìþ"ÞüôúôìþúöþÎüä4êü  ìüøþüü þîæöÌöü$Øü òøöøîø â,úðìøúàèüøèäúòúî  î*úâþøôâúä ê ôúÖöü "òþüüèüüòìöôòæò"úúø üúðþÚþöþøÊö.Ìþòüòüþô$Øúüüè(øüÞ(Î  üþÜüüüööøüþöîþÞ øúêô òúøØþ$èüüòôþàòöúè æúÚþàüþþèöòþìôôþøüì  üòþþøôêð èàüüúöòþ øØúúö ø Ö ú ìî  þþþè üüôòþìøúê öúüú ìüþþòúüêþþäòüþøôøøüæè æúö ê ð ú üþüò êúþôúÔøöîøäü üþîèþàþüüüæøüÚüôôðöâü&þ æ  üøúÔ*ðþúò Òüèòöôîøðþøúþôôþþð ä öøü îøøîðøìúð,ðÜøüüúþþú ìÚ "ðü"ä "üþþøúüøôþîþ öüðòòúþøþü"øþúüüøôøöþð" úôøþúúø þúüüôþ êòîøîþøþø ðüôøüúøôöúòüþþòþüþúîüôþúüþüþöü îþòþþðþöìüüüèü öþü øþøìîôîþüøøüüôðþ ôìæò ôúþü  ìüÖ&øö üþòøòÎþ4 ìúìþô öúêêö> òøèôìòüüæø" úîîêþê  ðúúô2ü þü øòúâöþ âøüòþôüîêø þúþðúô ô Îü ,êðüôü$¸ò*âðþøêøôÊä¶Z 4ôüðöðüôø¾úZØü äî,öðþ¢êlòìüöðüü úôÎÎôdþÂþøúì"þÒð¶D((ä þôþÞ"úàê¤dfÈ öôþîðòÜðúºä@FÖâòîü*üðÆèlØúèäø6þúÆâÞü`úÈòâð<èÚô¼j*æö úÞ($æôÀÞFN¬öþö ÂòLâêì¶úbìèðÞö ÖøÖRæ¶âhð¼*þòü¸þÊj, ü¼î þêìàÎà` 4Äöðþòúþæàö¶ *6Üøêô üÌäÐÜF$Vìèòúâ0îÔØ²:T(ìôÀêÜúÞö¢ä<^òòæôìÞ ììúœ ö`8 È îêè.ôüªÚÒV6ºîò òÜ$øÚ²æ”x DàÒ*êØ" öÎê¨$0&dà ðÒ*øÎì.èÖÖÀZøòðòü$ôôþÞØðh$âæò ìøüºôüþL$ÞòöúöøòææúÔ4 JðòòöØøø\æòøøàüøìôü ò,>ì úÞúîúöòÆB(Êöþþìü òþôþþä>,Ú úüþøüèìú ò Ø Pôúðøòþöìüþæ0 Öþúöúøòîþöì:ôâöæöüúìÔV $æôòäèôòü2ÜÖ"*,òöîúøþøü ôæÎ2Däüæèòô äøÌ N  ÜòôòèîþÈ D æööööüüêúÚX ôìêöüþüðø üþöîúòþþðêþ  þøôêòøúìüæ øüîôöúÞ òö öþÜþ ôøììòâ  ì èðüðüúüöþþòööþ ìþâ  ðüøúüú Ú( öüâðôúÔþò òþÜúöúö úæööàþòô,úþèøæðþüö êî þüþ ðÒàü øòâÌò²8 "ö üêô´ô*Ò üÆþê* æúþ øôÐöÂ6øúúüê8øÂö äú îúÞæö ò þòüÚð¦@*þü öþôêÂþ  òÂôÂDÔ ú(ÖøÆ&òôúø*îÂì Öü "úúäîì".Ú (ôò*þäÚ¨F$öþôDôþöÖþøÚFÒþÈð¨^üàîNþ ÔêØð ôüöæ8ò°ÐâôJðøÚ(êìäâê²\.îôî&ð(öò¾ª8búüÂLøþ ÞºèBøöþ$Âø¼T,èÐJÞ(Üúªü2(úÖü øðÖ(,ì öäRÆî¼ú6 8úÆ0üð¶¬øh Ôì&,Ü®î¼DÖòøD¸ê¸ $8òèò øð$Œøì<úþÐþ îzˆòàÖ0@Þ¤*þò: ®äú@ Ì úø (ÄÔ Ò\*"ÆøÎ$ôò¶èÐ$,JôÊ ôüHØæÞÎðFü"Òòì0¢üØP 2ÔÐ*8¼ú ¨ôT"¦0æàðÆ 4æìâ ðÚ® &.àÔ:àøèô\ö ܬôúúÆàòH4ÂÞNäòÈ ÂBHòêþÆP ôäì”êb&Š2þ.  ú¼ îÈ<ðôܶä ð¸&æ&ØæþR"¢ ðøÖê®D6 ÎøìDæìÚ.ôü°òJþø ¢PÈ,°æ" ŠîNàòBÚþÌö>ÐÎ@ ¾N.ÈàXî J&àTêìüÎL$æâü"úæÚ@êðìà8ââ(þøÄDîÈôØ."Ò:ö¾ ØüÎ("ÈÚÌ\âúÖüÚTÈü¸^ì ¼,àþæòúò$ÂLÐúòüþòþê8úþþü úôüÂøæøú$ êò*ÊüÌêô$ôüàüè&òø&òîÂHòäüîÎü0òøðø öà8üþæúêþ"â°< *ÞøÚø0þ äüüþöèø üüôúîðìþò8äæ(òüÐüþþà>ÄòîÜæ>úöôôäîâ, Øì ú"(Öôèêúìø "ÖØ æ*æüæú:æ à& Òüøþ2àîþþ6ÔþøÎþî4æâøØ2þÊè"ìâÜþ üêôîÜöæ  ,äþÜ þbÎÜüô úîìòîôêäòÐðäFÆèü22èôÜ ø4ô¼.ö* öêî$òðüêÚ ôöÞ ,þìôâþ,æöÔüôþüÞøèüîôúüøâ Òüüþ¼ô ìüìþþþæüèúæ ü"úôòäþêîø:Äúòê òúî ööþ üö òÖîô üÜþþþöþøüîøøúêüìêìúüøþ ôâ"æþöòüèòôüøþê þ ö Úòüæ6úèö êøòþþ$øúð ôüøôôöüôêþîþüìüúî îì èüî þþòúìúøÞüøæðþüþèøîö ììüøúþúî úöú ìàôöðôêü èèþð ôüþèöîú òò" úþðü øöìü üúþøüö öþþüþüöøþÞö èþòôì  äþôü ìúôüô úòò,ðúúäüìþþàøüîôøþþüúôúþøÚ øðôüúôøð þæöüøôòú&æöî èò þöæòúøúìôúúøü ôèöðò ôêøúüÜú ööþþ&æðð úôðþòþÒðæ òòìæúöüöþü Úò&üôä ðêòúòîü âöìòøøòú þþ þ þøòúîøüöÞö üþüðèöîü øêüþðþüææúúöôúúðôþ üúöäøþú Òøüøøö øàôúöþ þ ä øòì àôîþüøþøúøòø ô þîøüÖüþ êêæø üðøâ òüôøþôþøþþÞüøìþþîþðîøþê Úò øöòþêüþöàôèüøþìøöúøúúþþê ðôèþø úðüàúøòòæúúøþÜö ,îúþøúöòððüð øò üú Æì4úüöúÚ$ðúôìêð$øúöúô îøäôÞþüòøôþÆ@þöòòô úöîàþêF üîøöüþ*öþøØâF&èöììþøÖòôàN.æôò ðÚîàø¾6*ôÞúööþ2âøÌàb øØþìòööþÞî<öòöòðÌ" (Äð,,**Øèò þþâàîÖî: üúîÊ*ðÆøð $ìžN îøôòÚÖNúâÀätöÔâ$ôòÐ(DÒìÚ> Þüðì$æÐè:"Ò’B4øøâøàà>þê´Bn ôìò&äääÖTôäÒæ6øúôüô"æÐ*&âÞÆv"èîðü¶ æNÖòòºRÚü öüÜøð" æ´Jü Ø ôôÔæþàväêü ö4ÖöÞð,âðî>þúòðÐ2.êÚôÌ(DàäþàôøÚâöüÊ0 äôþøÎ ôDúþÜæò@*ìÒôüøôþæ(îøäðø¼tþÐô îþØäúðþ6üüôüöä&èôþJìüäúüÖ úÔ Vî þèðÐúä" Âð&úìþø Ô:üþÜâf .Âüêúæîâúêà6êüèøòæô(øÔ" PòðîüþðîøZØì úþôêúÐ< àò(ìòöþòúæ, îþø, ,Ðüìøôö ô  âþþôüâþü*îø$öÞöô Ôúöú(ÚìÈ"ö öêüä þ ú Òðúúþð æ þÆôæøüþ Ôî òüð ô öÞöøòü Ü$úúÔúü  ö þððøþö ò âî òðüî üøü úðúöòòöüúúþà øüêúð ä þøä ü   üîæôòüøþòúú èøà  úþÞ"ôþôþöòðòøü öüüøðþöþøöþ êüð.òðþüîúø üîøúÜþôúæ*úøþöúúü â6îêøâ øøäø ðôü þô þöúö ðþööôøþúòüæêôèö øüúú þòþþüøþÞþ òÐ þ þæüúþø ðôúü  îþò$îøîøö ôÚôò*ðòî  îðàöîúþ þîðøô*þîøðäîä0 2Üúüø þøàÊîâúî þ" þâìèÔððL*ÞôüøúúäÜØêÖN æü ÚöøèòèØúö@&úô úì ÖìÂâVüö þ êöæôÞÞæÒ6HîøîêìÞüÈØò > "îæ êúöüÔðÌö *ôüä ôòæÈèÒ*$þäü òâêÞ®øôL@ êüò" ìðòÌî¸F$îîôþ öüêèôܸòÀ`($îüô þêüèøæàÞ²X0ÞöþèðàÞÐÊÞÄ0Nôòò ÜöúÖø¾Êüøh.ððô  "ÖúöôÄè°ðd ú þþêêüÜ¢äêÈ\J òþÞ$îþøøàü Úüºð\,þèøÈ&úúîþðÂäÄ00Dôþèú&"ÞòôÔàòÈÌúð&B*. úæü ìäþÞØàâöôLLæþ *îäè äÊú¢&">"æä òôììðÞâÊÆ^4.þ ö ôüððæäÎî2žø^ îø& îüôâöèî&Êð¸N.ö øîú,üüüòÊôäÆdò þ  þüòÖìÒ*ÚöºÖ6,þ èîà¸î:¶ôÆd(  þöæêÜô@Þ˜0 Nî þøÀÚî.òÂú”r0ìø ü*ü øäî¼"èüò ZøüöøòÆþÞRÖúÖøJ:æö øòæÎ6îÆÚÜ.4Ü   ÒìäÒú  6&ðð4 öèú¾0ò òÂÒl*þÜ&î üèÔøÚ4êøäª&Rú üþöúüîüÚööÖðèðR >Øþ&  Äþâ"èþ¼öö8öâ îâæÖìòàúþê*.ä î6úúäÚöî îîèüÌ\ Ö þàüðôÀøò@üø üìþèìôè þ¾R $úò æòÞÚôäþø.Ê ( ò"þüü àòòöüìþîÚ*.Ò ìöêòþîú,àââ0òþôøÜæøÒÒø "(øìàðæÜþÜú8èÄ üöþöìêüîî6 Æìø"öêèòÚôèúô.üòü¼*&ôþøöÒî¼$"Îòöü ø øàÞüö8Ö ø0 Öè *ú ôúüôòúÈþòâ$âòÊ$ôøòþÜðøì2þÀô*úîþìðæêÄ*Øö²:,ôüðøäêØ,ì ê. ¸úî(üþôôäÞ þòÔØ6ìîøúæüÈ ü.ÜòÜ0 øöðüÜø ê4îþ¦ ø,üþî ìðêü Ô" Ìø°L$ø î öÔòê$ô ôôº"$ÒôúÞòÆþ òîÜØ," öþüòÒöìð:üÌæê02 üôòòâêÜ &ê¢"(ôô òøæÞ ¼ôÀBêìÐêôèúøü¾2ð øì æúÞ ö îâêäF0ü ÔöøøÚúüôÎÖú<ü ê ô øòâì ìúêÞôäü*üîô ìèîö ìîúî"øôøèöÞì" ôîêâ@ì ôøüòæôððú äèüÐF. øà&ôúâðüþîôøØDþøö øäìêÞ.òòúà  ðüìöä(Øúôäøèð2*øøðæîþ$þÐ0 îìúÈ .ü ø úúèÞüÞüîúøöþÒ<üìììæø úîâöÖ 4 ôôôîúö0öà öîúÄ:"ö üþìêàþ&Ôúì$ îêà2øþøâôü&öÊ"ôöî""òööÚ ìâ2üþðôà øèöæÖü úöäü" üøþÒþ(úþÖ$úîÄ*  ôþòîôöúâúøäî2 öèì,ðìðüúÂ$ôüâ âØ"øôèôî(úþÚö& Êôö òÞ "ôôôÚþôÈ$þôÚ úúøòìú àò$ÖöäøÚþôþæÜøôÒþøìøÞ êîìð"þ ÜØ2 òþÒ ú ü äðþöÐø(þèöø. îþÜ øøìê òâèøòæè üÚôöü òøàòôðÖþôèÖ (úøè þ" üòÌ4 ÎüÊ ü ÒöôÞþðòÞ "Ìú &ì* öøîÒøôäîÌøüäúèþ üäìèôØè&üôðü$ æ0ú àì*àúìöüúöÚîÔøôÌôÜúÔüú ü ì ÖðæúþøúööðêüÚ&îèðúøþÜìôöøòÚ4 öü"$üôò òúÜü$ÞþôîüöðòìøþÚòê îâúúöüøüöÊ îö" öþöüìþÚüêþèîöúüøòðüòöÔ0êúú þüþúâ ôìüþÞøþúðúøþÞþöþìö   üüúîÐ þ ìèøþøøøòøøêüÚòø  þþôâ òÜîîöþôúøðöøüè úòîîú ôîþ ð ú  þüøôôôîìüúÞôÞôîúþ ðþðæúüüúîúöðþòþ  üøðúìðäðúæìðöðøü     ú þ ôøøðöòêøüøäôêþú þ öþ èþúþøúôþöüîöþø ü üþþ öøôðþüöüöêüüþüþöòþø úôüúêôðòúôöøþþðüøþúø ö   þþìþþêööøþüþþþöøôþþúþüøúøêúøôôüúþ  ôüþöúôøþúøþìôþô þú ðúúþþþôúøúøðöøêþøøøúúüþþüø ôøøúøúþúþ þä  üü øîðþ üþðøþæúöüêöúòòøøîþþøúþ    üþêþ þöèüðþþöúøö øòüîöôîüüöúüüúìþþôþ þòþü öþüò øúòøþôúþþ øþøúüöôöòúôôúòöôøöüüþøðúúþðîþôüüüúþþ ü  üüüúþðþüúöüòþþþþþþðöþüþðþüüøþöúøú ôþü þüòþøþúüòþ úþüþüþôþøþþøþúøú þøþ üþøò òþ ôüøþþþöøøþ  øúþúòüöúúöøúúþþþúþü þü üüüüüöþþúþøöþüüüþþþþüöúüþøþü üüòþöþþüüþøþüþòþöþüúþøþüøúúúþúøþþúüüüþúüøþüþúþúúüüøþüþúöüüþþþüþþúþøüúþúüüøøþþúüþøþþþþúþþúþþüüþúüþüþüþüüþüþþüþþþþúüþþüþüþüþúþüþþþüüþüúþüüþþüþþþúþüþþþþþþþþþþþþþþþþþüþþþþüþþþþþþþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/Evil_Laugh.wav000644 001751 001751 00000154700 14165625676 022044 0ustar00kevinzkevinz000000 000000 RIFF¸ÙWAVEfmt +"VLISTINFOISFTLavf54.63.104datapÙþþþþþþþüüúüþþþþþþþüþþüúøøööòòðððîðîîòôúü   þüòîèêäÞÜÖØÔÖÔÐÒÒÒØÜììø $$**(*"*(&*$&***,$" úòîàäÚÜÒÎÎÌÊÆÄÆÆÄÈÈÎÔàèîüú,(2.6::>6<6:>:66*".úæìââÚÄÈÀÆÄÂÆÄÀÈÀÈÐÜúìð&$,,0::<>><<>:6,$$þüúôÞöÖÔ¾ÈÂÂÊÄÄÊÀÌÆäðòúø:*8.:<8::8:2&úþúþÚðàè¾ÊÀÄÆ¾ÈÄÀÎÄöò 2*:0>><D0(&*þþúþÖþàì¸È¾¾Ê¾ÈÄÀÖàúþü 4.><>B>.0"0øôäòÎÆºÊ¾ÆÆ¾Ì¾äðüüü88><<:62üþêìðÒÊÆÀÊÀÄÆ¼ÔÔøþþ*4D:D<>($&üþúöØôÜܾÈÂÂʼʺàòüüþø0:>B<B::&þþþâðäöÆÌºÆÂÀ̼ÎÊöøþþþüþ,2F:B<8B28""þôàêÞÚ¾ÀÄ¼ÂÆ¾Ì¾ÆÐâþøþþ<::@0:8<<><F"( þìâÖèÐÒ¾ÆÄÀÈÀÄÆºÊ¾æòôþö4>8@<282:8<:B64 ôÜæÖÞÀÄÀÄÄÄÆÊÄÊÈÂÔÐúòþö,<:D6<8.0042*2"284:" üöÎäÔÒÆÄÄÄÄÄÂÀÂÀÀÆÂÊÆèæö(2>@@>@>:66,6,*$,2.*42$ øÜæØÚ¼Ä¾Â¾ÄÀÀľÆÂÂÊÀÌÊÞú &*:@6D<>B::4:6.(0(2$*(.:8:6 øÜÖ¾ÈÄÆÆÆÆÄÄÄÆÂÆÂ¾Ê¾ÊÊÈêú,*<>8@88@8@400**&".&0òÜÒÊÈÄÈÈÂÄÄÄÆÆÄÆÂÈÊÌÞÚ&0(80<<:>0602.*&  þöîäæàèØØÎÔÐÌÊÈÌÐÖÜäèúú""$.,:,,$$$    üêìÞêâÞØÐÐÌÒÐÐÒØÚÞâæìôüþ$"*,0(,*(("   øüüöìîêîæäÜÚÜÚØÔÒÒÒÎÔÐæäðôôþ  $(*,.,,,*&" þþúüþþþüþøøòòòðîêæàÞÜÚÚØÜàääêðôøüþ  üüúøôòòðìèæäÞÞÚØØÖÞàæâäêîøòúú &$(((**($$  þþüüþüøøôòòîðêâàØÞÖØÖÔØÜâäèîöøþ " &$*(&$  üúúôòîèâÞÚÔÖÐÔÌÎÐÔÜÜäæîôú"&*,0..,,((&"   üþîæÞØÚÊÆÂÆÄÊÈÈÌÌÐÔÜàèðþ &(*064668:64*,&$  øòìÒÞÒØÄÆÂÄÄÄÈÈÎÖÚäêîúúú  &**00842*&*"  üîâìÈÈÂÄÆÂÈÈÊÐÔÚäìæôòüêððþøü  &*0:24&4.0$&$(((*&808 úòâä¾ÈÂÄÆÂÄÄÄÈÎÔÜàêêðôòìòôþü*.488<2884:.200648@0.úúîÊľÄÀÀÂÀÀÄÀÂÈÈâàöäìîúôôöø *>4>2>>>8846666.<2D6 Òæö¼ÈÄÀÈÀÀÄÀ¾Ä¼ÈÌØêÜäÜðìöæøø82F8<@<B>>6<<@2<2@H*:Þ ò.èÒÌÀÊÀÀľÀÂÀÂÂÀÖÎäÈÖÔðÚâäö(.6@>B<@@>@>@@<@8>D8H"úâԼȾÀľÂÂÀ¾ÆÂÚÆÆÆÐÞÞæú.24@>B>@@<@@>B<@@:D<>JÌÜð¸ÄÀÂÂÀÂÂÀÀÀÂÀÀÂÂÊÔÞìø (.6:@>@>@>@>@@>:<6@, 0(ÞæÊàÖÄÂÀÀÂÀÀÂÀ¾ÎÈÖÎÖàð ".0@6<@"B2J &&",$"  þüìààØÈöÐØÔØÚÖÚâàèäìôö  ü(  ü**&2 "ü öúäîìæðÚÞâÔÞÞêôæàêèÞÀìØâÌòìüò" 0,.>>>B><>@.0&,(úðÆðÒØÆÈÆÄÀÂÂÀÈÄÐÀÆÄÞÂÖÐðþ">8D>>B>>@>>>8<(  þôÒæêÜìÔÊÀÄÈÀÄÀÎÎÜÖØàÚâò &,(&($( $ þöòòðòðêúøúþüþü üþîöôþüìîîðôêîÖôäðÐææòðøüþ "<,848600.(""þö ðæÎÈÎÄÂÂÂÆÆÄÈÈÈÌÌÐÎÖÖòú(,<2:6@@>B6:6<26.442" üôêâÚØÒÐÖÒÔØØØÖØØÖÜâæðú  "$.,8òôòôúòòîòðîêðêòêêìô "   üúöúö ìèèòâÜààÞæèðèîðúôøðúüø,&2608244042((&  üìêÞÖÖÆÄÀÄÄÊÊÎÐàÒÜÚæèæèêðú .>:B>:@8@24,02.*$"øìæÜØØÒÊÈÈÈ̾ÂÀÀ¾ÌÊÊÖÔôþ *$,(<060:64.2.(,(&$  úúöòôôììæèèääàÜâÂȼÊÒÔìäèäæöòþú"2($&.4 8&, $$(""*  úúúüìêÐÖÊÎÀÄÈÐÔÜÖòððäèöþüø  (**0(668..424*0040...& "þúÞèÐîÔξľÂÀÆÎÎæÞæÜÞððòøò&"066<<82460(0*:46,2($&(þìæÄøÔÞÀÆÄÄÄÄÈÂÖÎÚÄÔÒÞâàèäøôúîüú  $&>8<<880868:><:>&0èÚôèäÄÊÂÆÂÄÄÀÒÔðÈÞÌøîòæÔèêìÌàÞüø  &&&24<0>>>B<D0" * Ôæ ÄÒÂÊÈÂÈÂÌÌêîÚÚÊðÈôâÎäÜêêìúöü. ,(4$,*20024..Læøò ÚÖÔÐØÎÔÐÌØØàöÂúâôòðìîðôþø ð0ú$2 (&$@""üØðÔäØÜÜÚÞÖâÞôþÞð úî ü   $*ð î&ÔêÚðÞÞÜÞâæÞòìúüðü î &$   øà2þìô¾üêæÒÖÔÜÖÜêöøäþú &  $   üäþüîÌØäàÊÌÖÔØÜÖ üìö$ .2 """úò "ìØ, ðþðÐÚìöÐâÒØôò& âþ æ:($ 4îäüÚþ æþô  4ö Ü4ê Þðäþø"Þôìþæ* àâ ÒæÌøêîðÚøð ô "(*&*&0þ$D èþø &ÐìÂÒÈÖÄÎÊØæîôìîôäêèôêöþô$&$4:@<B<@B:H *,  òþøâÈÜÆöÔÔÀÖÎÎÀÄÊÈÞÎÚÐÚôòþ $&.2266@>B8@>@8>:B<B<<F62üÎèÖìÊÐÒÐÔÐÎÔÌÌÎÌÔÔÚâÚÞÞäêôþú 04.4><D2806:2:*  þþîúîèòîêæàæàØÞÖÚÖÜÞèìäêäüöþ""(,.$,üøøüðúðôôööøúü æþäîîúúðòìúôüôòúô ú   þøþòüööêðäâÞèâèèêòî  "$&&&"($," úôîÒÜÒÎÎÐÎÔÐÔÖàÞààìÚâÚîêòø  "(&($&$0*.(0020$& ìþôðôöðöææàÞàÚÜØÜÜÞàââðöø úú  ôöììîò  þöâöâðÐÞÞàèâîÎÜâìðèìæüàêÎØæü *8:D02B $ ôüüþúúæÞàØææäÜöÖæ°ÎÞô   þ" 6*@þúöøúþú&öâäÎÔàØØêòþðü@Ðæ.öôâìôÜòþî*$.6><D<>@0:ðôöºàÆôÊÈÈÆÞÞâÔøðâòøâèâÞàâàÖæîøæôôü*.F><D:@B8H<0&&ÜÞÌÆÔÊÈÎÊÊÌÌÌÒ¼þè"ÚððäêîöÂÔ¸ÖÒÖàüö ö (66D><D:@B6DþÜäÜàÚØÔÔÔÔÈèâàÜ  â$èäü¾Ê¼Â¾ÆÊØìì ,,&22><B<D60øÚìææØÞÞÞàÒâÈþ*ôèè¸ÚÊØÈ¼Ò¼ð $$.(.(*0>òôÂäÖÔØÖÞâæÐÞÖèøúB$.:*J"ºøØØî¾àÈò(6$.(,*,**00þè²ÄļÄÊÊÒÀÊÈØÂÜÜ(*6*H¶öàèêÐòÞ*8D<B>@>B>@@*<úÄÒÚÊ޾ȾÊÀ¾È¶ÒÌ:èþè.ü(äîºÞÎÐÚÈäÚ &4D:B>@>@@<F6J& ØìîÞÚÊØÒÔÔÒÜÌæä4úòàêöüÌҴʼ¾Ê²Ô¶60260***6(6(>(ÚêêââäèæêêæôØþø`&ôÜڴʼ¾È´ÔÆ ",(::&JìÊÜÐÚÖÖÚÖÜÞÔ68@&úúòêÔØØÚÚìò ú&$, " ö ÈÐʾÈÈÊÄÌÞÒìú2>>8ììàþèðþèü.ú>ø (":0øðäò¸ÌÄÄÂÄÔÈÈÔæîÐ<ÒÐðè"ÜÞ&,<"Fî(: $,ððÐÔ¼ÂÒʪúøòüððÌîàÌàæü øD,622484,.0<æîúèô¾ÎÂØÔê þâ*ðúÒþèî¸âàæøöB.4 F24( ., þòÒîØäÐþôöøôð¾ì úöÊòÞ0Øü âúü æ@*:: * ôüü èîäìæäðúèú@*ö$àîÐîØØÄêèØ 42&(ðüæàèìúÞ(* ú"(ä îîÒþâðÖÚì2@B4 âÚÂÂξÊÄÄÒêôú(*.(<ÒæöÖðüð2 ,**&øì (""îææÖâæèüæøâøÌÐÀÚÊÀжôì úH4D  ö "8 4ø * ÖìØÖàÂÐäÚòÊäêü *"*æìÚàÚÞèÖþ (4>>:F $  ôúð   òöêúòôþö"îèÚöæòæäêòü(86F80ôæòöàöþJ,L"ôÆÜôüâøÒìö öúðÜ* 64öþò öú.8:F:$êô¼ÔÈüÜîúþ  Îêäîîìúê öþöþþ>8>F4:úîìüæø@*> øòÊäÌÐʸÞäð2àìÐÞÖìðô.8F4:2æðöþ.8,Júèôð üúæB(<2ööàØÀäÆÌØÈ FêôÔÂȸÊÎÒ 0$ ôüøü22F:D8Jö&üìâî¸ÈÀÐÀÚúòðúîÞÊèÄÊȾÞÂ"Büöô F:D8H44üúôö èäÖøêêòÐÞ¬ææîÞöäâä ÂÌʾÞä ô Î úüø42<:J*(ú öþàäªàÚúâüööâ¼ÆÄÐøæäÚòîúþô .&$, Þòþþ Øü 0ðüøúðÜööÒúºæÈîìÊÔÌêúàôòàà<,4*.ò þÄÔîô ö ðøØöþ®â¦öøÀôÈüøþ 80482$þôúæê ê°þîøúÚúüþúö úæÆîÌÔà¶ö ¾ôÒ" :*,$:&òøôêªìàö"êîòúæðäâèºúúì¦àÂþôêÔàâî& L<<64$,î þüøÞ¸äèòìîæâÌôþìèâìâîèæô°Ô°òôðÊðÔ þ &2D8F8D6$úôèÔðèøúöôôâÄÎøìîþ&èòúÄȼÄÀÀÒ¾úú 4ò@2B88B2@XæúØøúðòœòîúJ¤ðþ à䮨ÂÀ¼ðàÌîJ:>04 >8.( ¶ØÚÞÚäü òìÖÎîäþööþÞöêöÌ ,H>6,êØàÒêÔ,ôÊÖèÞøü,(4üÆÎ¸ØÈÚÔ (J"ÔþäèÜÈôæ,,äæÊàôâÜBD(2úèøÞÌØØ¨öò6",*&äðîäôèæúÌ B.*&æÜܾÀÆÀîì $.*"¼ÜÆðÈæê: ØòìúôäþÂ*J:680øà ÐÌÀ¾ÂÆÄðò  üÄêÒþîäúÒÚØàöÔ $6:88(*öúÞÚÔÀƾºÒÀ" àòôèÚÐÌöììöìîèØÒæÚö,.< > ôôêÞèäìê´ÜÎöþØì þ$ ÜæØòÐÌÚØò($"4" øæüî$þ Øä ®ÚÄââÜêòê,æ, ðþðÎäøâø 8$,þ" :0â&,6êîòàþòîüÄäÖôüøþôêäÜäÒðöüú&øòþÜ $.(:(ôöäàèÔÖÒöêìòüðüÚðÒüøØòðöî" 8,," ò$*þþèúòîüÌÖôî ÞþúþööèêøæØâìî0$  þ "$$*ìüÎüöê ¾ðèò þ îúúþ ôöæðäÞâÚü(6ôðò$ôîÈêððô".,:,N4*ÐòÐøêæìø($6<î" ÚìÊàôØîªØÔþ22 ò àúÔ  â ü 468@ðìÒòðø$*&$* öêÐÈØÐÈÎæøòüþö ÔÞØÎüò "H48 îöòöö N>4VæøêöàØòö "8þÒ²Ö´ÊÔÂðÄüD@D.DÊܲÆÀÂÔðòò22F<>0>ôüîæÚúú222Bîôè ØÒøÒT*0Nòú¶ÈβèÔÊØæ >J.>úúúÔÎÖ¾Ô<(68 üü æÎ0&8BÖúøöî* üÔêÖþòþLòäØÌÐÚä,D@&òöìð æ".Tüüþþøü âÎôÈôêÒ ø& ü $,8 òðòæðØB öüè$ø&œþ"2øîÜàÞä : úøö 4H,Bòú&ØÞàúò4  æìæøú Ìð$ üúþ$8F*,8üüø8ÞîÒòæôêæ: òèÞàòâøâü ð2&6&" üü"ôþþìHþìööæ"êøêîööæöìôððððøì &.&.," êVü ü2úì ìøîúÐôø ÜøèêöÜè820Rúüö> ú îüôPú 俬êúþ þ&ú èîðè 2,øööð@ø þü,*ø ôÖääöð0 þüêöä < ú æ&8.úì$ ôþø(4$îòþÂØÐúÒôüö ôøî$üÞøú >þ üôúìöä 4 .öîÌÞÖìÒÊîú< *ÒôÆæäúN òØÞÔö 6::&ÎâÒÎ2öF,øò¨ÜºÄȲּ,LöêÌÀήð @,<>ðöØÜâ &F<F4FÊÚÜÎÖìÚÜ "",, ÂÊÀ¼ÈÀâ,,< äÂж î þ2ô6F,(" üðêÚàæ¼úöà (âîðàØÒâäæôô6ð üêJ"2 ö ÜØÂÞü&48Nþ üæÒÔ¼òòôþðöúâú$ôøúøüþ üèþþþ*ôüþ6äØúðÚÚÊì &$"þäÀ¾Ê¶ÐÈÂÜÆ(@(*êæúîÔôþü*&ÆêÚøþþ> úúúÔܺÀÜà"2<$, ðÖʺÒÖèöüúÖ¼îîðüBòôöæÚøìô(6HøðèÐìÈÔÖÖ& Ò öúöæîÚî èàÂäÔäÜ Úîìúææâäòô"(( ÐÖÖÒä , üðâÚØÐÔèî (H(üÖØ¼Ôê ,úúÖîÞàð,0V¸ØÔÊÒ¾Øôú 2:<<4 àèÎæèò ( öòÜÞäìðô*ìüààÖÞòø",64H&äüæúêü,&>úèêÞòìöø < èèòØìÒæü2.4(æâææÜþîü âüÌ*(&*2ø þ ö üøîîÚÞâàúþ øàî ðäæ¾*&$"*$úüþæüüþî084.2òüêüòøôÀüöüøúì´Ô¼îú&ø,$>Dòø&ÒôþêÌÄèø>6$.ò ìôÂâÜ î 2ÜúäúäàÖìæðöü Dôìþþüü  øôøü*8$6èàÎìÆÞÈè .<44< üâ´Ð²Îº¾Ú,2D@2*öðÜøú8ðüî""6<0DîöÄæÆÊÄæôöT6B>*(ÌäÆ¼Ê¶ÎÆ .$(42üòôâêð(  2.àðÔôØàè,,^´ÖâÄêÌÊÊà"(("ôþþúêø&úØòòô Ü:8@<L"2¬Ü¾ÒàÔþÔú(*. <ìêÌ´âÌàêþ6(,òæÀÒÚä*2Pâúììäô$6>6N*0ÆÖľÀÒêð,(8<&ÌäÊÒÌÎèÂ,B(òòìð*"<êäöøò&ð ::D4RÈÔÆÌÆÖøH,.$.þ ÒäÖæàÞô2Hòúðî "ðôþü$ :,2,, ÚâÌÞÂÎÐ"L*( äÈÚÐÔàüþB6D(*øôîúæþðLöòòÐ N0JæúôÚâê &4ìæ øâÜÔ   þêêüúÖ:øüæþôðú*H(. üþô ðòìôîúô þà"ðøèúöüèú þ ú8 îÈðöþ$(4ìöòäôÆêö(.¸ÜÌØÜ¾àî$22D&.ÐÞÆÈÖÞ 4B,*üÖÔÆòÐøö82> ÔôÖÊÒ¶êò2*:>DþÂèÄÐÒ¸öü44,JèþÜàì àüþüúØäèþþ "6&(òæÊÚÖòüþ ì,(úöîâæìâúøîþþ *6& ØÔ¸êØò*.26ÔÖ¾ÌÄÎðà$:>:6üìîæîâ úô  üúÜèÚøêàäö 8.*$ööØàæÜÖø "(àîÜúÞêêþ,ú øøøøø òèôÜÞÌÐØàôúòþþòòîàêþüüü"ø "ððàÜØàîô&,6ìöæÜÔØØÖöæøö2ðìòêî4 ðîâäþ4$2þàÖÜÈâÊHþÒÒàÐäàúòüüì  ööêöæ0"&>øøðäþäôÔ . $ôàÚÜØòäú( $* àøêþêìü òøþöÞ0$"$&öÖò 0,&,êÞÄÈԺΰèú,,*<*Òôîæòø.(,> îøþþ ÐØ´èè$ø&4"L(ìÖþàòú68F0XúºÆÀºÜàöêÔ.Üàò@ &  òþüÎæäú :î ü@ôòêæîøâüþþèøÞþø îúöþ.,äüú ÚòâúôÚ R $ô òäðöðô6"þêÒÒ¾ÆÞì $6@ô ò úöÜúö  úê$."ü ô îôÂòî 4 ô ìâÖØØâêúü00 òðÐôîð øú üÌøôä(< $úôæÈêòî8@ÞüòØÔÖÖæþ >"þÒêÊ ðüøæúüÎ20:&:8.2äæ°ÚÞð&0ôö ðÞÄÈÆÜþ4* 0*þöüúôöØþÎB0:>.*2ìòÀðð ò6,<ªþÄо¾ÖÐ &2.&( öäÜÜô , þà 0 2 îò¼öîþþÜü"4êúôøöò0Èúâúþú6ØÖÜ®üòüÚþ4*B  ðøÞâòúüöüüþè üþÄúêú>,.0ÎÒØÒÄÖäôò8üîèúððøîàþ®ø  úô ôîúÄúîHØèÀäøòÜðF îôîÜ2*ö (ºÞæ ô .:8& ÒêÒÖØâøþ öôÞâÞÚ àþð( ââÚ¶èø$*ÔàÄÖþ  þúþìè0*(ZÜÞðÒà¸ÈÚÞúN.*âܲÒÎÒøöüæH(ôðÒþÞ*üþúæD"6ÖþøâäÖÎÒªêà4"äúôÖò¨êúü0èòÜØòâ âúþ$ÜäÎÞöü0,..,"òòêâÚäàôÐüúêìüü þüþÖöø$äôôøüêìúÚüê4>(BBÎÂÜÈèü è  àòÒîöôì .îþþ Úöîöö",*,0:ððìâìØæîúþ"  ì þú$öüìàÎü ""$øþüúìüü(ðððüþþ  ôüúúþîþ æüüüö  úúüúêöê ð èòîøðøôôüøöôú$öúÚüúþþ öþðüúôâêâìþú" 4ðòþîòô8ÔìÎþöò æâèæþ "þêæÈÜÜ öúô  úòèäÖÞì * >.(ììàâüú ü 2 Îì¾ èæöàüü4,*." ðààÜÚôþþôêøäòÒöðö.*"*îÚäÔÚêäüî"(8@00 ìÔÖÔêÈ 6*$ÄôðúÞìÈö ôøü$4üìÔÒºäð"(ô&äôºòø,($èüêìî06,0þè°ÎÆÔ¾ 02(&ìøÜî¸ÒÔæ(.&êô þ4( äÊȰèô.2(8èîÚÐîÐ"$ îøúðèòüøþÞüôþîÔ "îðäîòþ.$ú èê²ÆÞþ(èôüø è *,$òðÀÀ̾ú N8,Ðê¾Úàèò,:00"üöÞààîô *úðèÆÔÚø V "ü ä ÈÒÄøø,æÔÎÈÄB "êüÐìì"8,8ÒʾÀÂÊHÚðäæÜ.,`øòàààô*((6ðêªÖ¼ÀÆÜ*B4&ÞâÞÂÎÚè2&N"îêîìàþðüøâøäÎмðL&8â.ìÌÖÂÖÄ8F*2 êÌæÀÂÔÞ"*ØîØÐô0ÖâÜÜ*ü(îîèÔÄÒÈþ N<,úòÔæ¶ÒÖ L ðÞÖäÂäê ôÞèä þúòêÖâæò ô2úþÔÒÚÎú "0"ºÔÀØÒì,2:ìøÈ¾Ê¸ÚîJ.>úäÒÈÔÜö öü âÜÖÐúîàúàÀÖØþFúþÔÜÄôþþøÜðôØ$ úÞøúêøòºäÐ âÞ¤âô.T ¾ÒÐÒÖ,<øää î4*PøöÖÜÔö:ô¼ÜÎÔü < è ì ÚÞèÜ4*H8 âàÒÚÖìÜêæ DD64ÞäÖôæø  öèþ¦"ö üúÚäÚìèðôúø,ê(èÞüúú2 (àæèÂìôêîæôþ6ØøÌþ8&þîÎîèêêêêÜî ,486îòîØäàþîôú2âèæâö ôøúÞüêæôüöüþøúðþô ôâÚìîô àöøêþþò "&üòöüæîð òþúüô Üðæ  òðâðæöÔ0$$îìØÚæÐ "üîòêÜòðòö"øøþþúüÞðø  úòàìøüþ  øòæîêäèü üöòìèôúöØ ,øüìêêäøþ öøîüðúææøø þðøþüøúúê ìâðîøøøøúøü øþ* òþæþöþææèÐüòþüú$ îìîÜöþðþêêîàðö$  þúèøöôòðøì òþøþôþ öòäæèêö"&   þþöôôîôøþøò úþôêøôø þ àîâøðüþ& ôðúüôúô úîäêèîþ  þîòîü  þúúü òöìôìöîøöþðòôþôüü ôøîîêðúú üòììàôü úþÞöøþ ú  þð òúüôêðæâ 6ìæääæø ,$ ìêâÞîöøæòÂÖÚøðôêúüèìöò"&$òÄÚâúüJ æüæÖêÚâî $$.ìàäÎÆÄä  úâò¼úþ üú Ä̾ºØâ0&&:*ÔäÊè $@" þðòÎîúÂàìêâ$Ü0æð¼êü$  üöîì&&ØòàòÎî ü öìê (,öäîØòÚ8,Nò¼ÄÀÈ®*2ð ôøöôþøîØü*,äÚØÐäÜ&( 2 ÞêÞôôð>&úôÖØºìüP 8ÆèØÐØðüàô&øúÌèàþÒøúèúÐüüèØàÆúD42ÒöÂôôج ,0ÔÔàÜàXèþððöN*ôÒîÆþàøøÞìîæò@ú * Ú´ÜÆ :ÚüÞâ ò.öøHäöî  ìÆÞÖúØòöü6üöØ&.ö úì ú* þüêÖæÈÖðþ .,úêÈîø üü ðòîæÞòàòÜ îööììÀò úÜæÜìâðâ  Øöúüøôð æìäêâìâþ üÞîø Þü$æêÚæöèâ þêòì þàôàúÔöðüÖìæ   øòìàÚèòú äöäôøò Öúî üüöúôðøæòøðüüèöü àì"ÞæØÌîú2æÞÞÞì6üæàÐöêüôþþöâ úüØþüòøîðÎ üêööòöÊðüúð,$äðÜþ& üðâææîðèòþú$øôêúú èæÔôÜ æöþìîôÖðä&òà üäâü Ðêæìðüþ Öôæ êúè üâæêêô  æøêþäìðì& üüîìÜúô êêòüüôþþþüþøþîðò "ððèìà  úøðîööþø  êòìòðö  þìôêðøú  üâððòö ððèôôþú  ôöìîòðúþ("øþúöêêòèúþúæòæöêú òòúúâ æøì þøþöîî øìôüîøèîöô æþêüøúþþ þòðöîþþúþþüøøðôöîþü úüú úòìîðæþ þúì(ææèæâúüøü öüð4&4üêÜò,øøØðêîôêôò êþîöÌÖäô"("êàöòê.0, æþÀÖÆÊþ\ÖôÚø äî*2,@òÖøâþöøöúÞ4"òèöØäøîÚ*:$8æâÒìêð$46ôà¾ÞÎèâú * &ðôØèê$*"ò .æúèîòðú þ âþðÖüòî(ðööðþ üþæÔÌØàä* òÞîþôà(2(ÜæÆ&öèôæÚæöä úøâôØ40(¾îäîü "òüøø  î¶""öþÚäêâæ þ*6îðþÞ8 ìòÖÒüê^ òÜæÄììÞü.*&*êì²Øîò"6" âòÞâ þ üôúâ " Úòüô úúøðôüþü øú ä< äÞÜÐò èúüô  è  òüþÂèÜø( úæôêô üþ êôÞðöô æò øüÜâèô üäôôôò ,ÜÞàâü6òÌö" þ øøö  öäøððâú& ð  îÚêêô$ Úøðüìþ  àìÞèîø (Öððîö Ö úüÖêäðü  ööäÒâÔø .ÎêÔðô äþ  êôîðàü ðèèæøööþö( äêîêüþúôâú ø , úðôêäôôð  öøäìþ&øø,êþðâü(þüðü&ÞöÐæò@ ê ìôìüê *  ðöäüúþîöðò üüöþì úþàøðòÞæêòúüþøüúøþ úøòðêîä  ü ôôâìúø ø øöôàìòìàüô  ôôôøþ  úòöôèöâ$êöèøòö   ðòâæðò êòîþþþüüúúìþüèòôú øâðèöòú þôìðäðèð  êìâæêö ø ôðèêèòàúôðèèøúøúêòúæîæìúòî ðôäú òôÜòþþöö  üüòìþüðôìöô  øüúðú   úþ  öúöüôúÞøø  üôúêôä ò úüþøþþþèòêþ þþú üöìüþþ ôìîêðþôþüúüþôôæú" ôòòêð ôöîôôøþþúøüöøöþ øöîîöôþú þúôôôøþøööôøþø üøøøöþ   úøôöð  úøøøúö üøüòúö üþúþúøüôüòöøþò  øúöðúðøôü øúòðúôö üøúøþþ  îúôþöú øúúø úúôðþöüòüþüôööüúöúôôöúøôôþ üüøøööøøüøöüø þüúøöúòøò þ  úêêìÞþ þþüöúòðòöòúôøôàüðþþ &ìàäÖðþ øöììðöü$&þüúðúìôþúþüúüþ  øúôÞòîúðàòìôðî&öîèîø  þæîêîæ 0 òúòüöòþ ìêèòðøöþòäöäôä "þúöþú  äúòøøîúøøú úüìúò (öò äêîøüî(ÚÞðÜæ& òêîâî öøüè4þâôöî4 $þæúØþö àü$"üüäþúüúúþþúôàòêø2àÚäàöüøøî  þòîìì$""ôöæäòò ôìô  üúööô úöòæþòþúøøúúøüüêüþ þüðîòÞòîøô øööøìøþ þöüüþú þüìøîúö ú ø ôìêîü" êððîò øúôôöä ððîðüþú  îúøøþú  ôôøìøæúäðèòà ôêèæøàøò"üúàöæðìü úôú ü äþöôúøúüüøþ øú þúüðöööþþüþþþ ðþîôü ìþþöîöì òúôüþ üüðôìðò úöðèüúüøìòþøöðôðð þüöúö üôòòöð ðúøúþüøøúöú  øøòöðøò  üøòòúú  üööôðøöü øúîôêú öþòüúøøü  ôôîìöúþúòòôúö ôüðîøè ôøôúöúþ  üüøôúöü öøôúîþþ ðøîòøôø ôòðòðøô ôîòðúð þúîúüòüîúü üöúüüúüìôðôìþúððöò úîôðòúþ  þ úôüî  üøøöôæü øüþúðøôøþüüú þøþøüøúø  ú úþøüüöüþö  øü úþìþþþôôøô üüþúöúú þöüþþøü üüøüüúþüþþþú  þüöøøþ þüøþüüþüþþþôþþþþúúþ þþüúüþüüþúüþþþþüüú öøøøüþúúüüþþüúþú úþþúúüüø  üüüúúüüôþ úüöüþøüþüúøþþ þüüúúúüüúþöþ üþüüþúøüøü ú þþøìòòì  úþüþö üúäððö úúöîôìüöêôîöþöðôðö üðøööæöö  þþúþ âîèìî ôþìòöü  ôúþú þöèøøøþöþúúö"òøæìîðø úðôêôþ  þöþ  úöþîøúøôø ôüð ø öú äêææðö úðèúîþüþìø öôøê üö üöúþôöüöô"ðìðîæ*þöæüðøîþúþøê úôöôþú ìðòòøúòòòöúúôöôü þ üîôøú  þöüòòòô þþþ þüöþ òúüü úúúø ööôòüþ  úæôúü öøþþ öþ úü øúòìúøúüü þøðòîøì üîúôüþ  øüøúøú  üüúúôþ úüþþ þèøúø  øòøöôþ îúüòüðöüü üððòðü öúêúþ øüðöþ  þøöüðþúúüþü þüüüúþúþüüþþøüþ üþþüþþúþþôüöþþøþöôúð þöìüðúô  þðüüþþøüöþ úöôôôøþ òþüúüüþôüúüþøüüöüøúþþúüöþþüüþþöøöúø üúúúøþüúþþúúüüüöüøþþþøúüüüúþúþþøþüþúüøúøøþ úþöúüü úúúþþþöúöúþþþöøüþ þúøöüþþüüúüø úüôöüþ üúúöþþüøúöüüüúüü þúþþøþú úþøþøþþüúüúþþüþü  þüüüüþþþúþúüüþüøþþþþþøúüþþ þôþüúþüþþüþþüþøúúúúþþþüþþþ þþþþþþþüþþüþúüþþüüúþþúüøþþüþúúþüþþüþþþþúþúþþüüþþþüþþþþþþþþþþüþþúüüþü üüüþúüøöôúüüøø  øþøüøüúüúúþòøôøþþøü úøêúúüþüüôüþüþþüþúúüò þøöôôþþøøþþþüüþüü ôþúüúøþüúòþøðòîþüöþî öôøö üþö  øþþøþôøþöüüøüðüþöúòúüüúüôöþþ îøòö øüøüü üúúø  úøüøþúüüüø üøúò úþúúüøþþüüøþúüüþþþþþþþþþþüúþüþ úøüúúúüü òþúþþøúôþþþþøþþþüøòþúþþúúúþþüôüúþþòüøþþôüôþþüþúþøþ þúüøþþþþüþþþþøüüüúþüþþþþúúþüüþþþúþüüþþüúüþúúúþþ úþþüþþüþþþüþüüúüþüþþþþþþþþúþúþüþþþþúþüþúþþþþþþþøúþþþþþøþüþþþþþþüüúþþüþþúüúþþúüþþþþþüüþüþúüüúüüþüþþþþþüþþüþþüüþþþþþþþþúüøþþüþüþþþþþþþüþþþþþþúþüþþþþþüþþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþþüþþüþþþþþþþþþþüþþþþüþþþüþþþþþþüþüúüöþþþþþþþüüþþü þþúüþüþþþüüøþüþþþþüþ úúüúúüüþüúüüüþþþþüüüþøþþöüüþþúüöþþþþþúüþþøüüþüþúþþúþúüüòüøö úøúøþüþþþþüüþþþüüüþþþþþþüþþþþüøþþüúüøþþþþúþþþøþþüþüüþüüþþþþþþþþþþþúþþþþúüüúþúþþþúüøþúüúþþüþúþúþüþþþþþþüþþþþþþüþþþþþþüþúþúüúþüúþ þüúþþþþþþþþüüüþþþþþþþþüüþþþþüþþþúþüþþþþüþþþþþþþþþþüþüþþþüþþþþþþþþþþüþüþþþþüüþþüþþþþþþþþþüüþüþþþþþþüþþþüþþþþþúþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþþþúþþüþþþþþþüþüüþüþþüüþüþþþüþþüüþþüþúüüüþüþþþþþþþþþüúüþþüüþüþüþþþþþþþþþþúüþüüþþüüúüþøüþþúüþþþüþþüþ þúüúúþþþüüþþþüüüþþþþþþüüþþüüþþþþþþþüþüþþþþþþüþüþüþþþþþþþþþþþþüþþþþþþþþþúþþþþþþüþüþüüüþþüþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþþüþþþþþþþþþþþüþþþþüþþþüþüþþüþþþþþþþþþþþþüþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/lightning1.wav000644 001751 001751 00000137656 14165625676 022104 0ustar00kevinzkevinz000000 000000 RIFF¦¿WAVEfmt +"VLISTINFOISFTLavf54.63.104data^¿þþüüüþþþüþúúüöüþþ þ þôþÜ "$öüÂÂØÞ.ô"D$ôìêîú"þøÞÆØÌæàäêêòòöòü$*&" *øúîÜÜÒÊÒÎìò ðøÚæðîü $  üúúôàæÐôòèôÚÜðäÖöò $øöòêöþ".DD40úúºêè úìððÊò<Þò¸þ*úòؤÈÊÐJHü¾ þê>$$ êܾ¼Úæü (>$ìú ÎÚÔÖ 6 ìÚÆÎÔÜôú4(@ ìî´ðö.Ö â.þöêòêø   4ôôÜîÐâüþ>2>,ðøÊà( ÈæÞüâîìæ  îòèÚØöü ü( ÄðêöÌæÊÜ ÞààôÞ: öÊø&òüÄÞæò 2 ìüôè öö èôööø"þ ú$ öàüè&þ*êÜÌÎÖèú$&DþìÚäê& îæÎÞà$"8êæìâòìþ : èîîôàðüúîòì ,&þèæöèäüú.øâêÐòà "î êìúâô úÖðä  þøôàðîôöèòÂîî  òöúü  ôöÎìüúÜüìøøôêþú òîäÜêîþ* øðôìäòîøúêðÞúüüòü þìòòðþþúôæþðüüü &þæÐêä üþúøö üúòúêúúòüþúúäöôêîÞúøôôòøúìðæêæöüúüæäÎÖÜêü("" üêøäêàâþ$ "üàîìöøü òôÔÐØÜöð ôôðúÞüò,ø ò øøàöþòüèêæìîøþ þøäòø þþæòôòòö  þîâÞÜêôþôøàðìâðèú$ øìÖÒäì$ôöêêöð þôôîäð üþöìðüî*îêèúèôø úüîêÚîîúø  èèìâþôúèøüúüþ$þäÜØìöö& òøôòúúþâüì üÞèôð øþòþôæääèþèøøú üêüüîøÞðòüöø Üôêú ìþèìòêüæúú úþøüøâîòü "âðÜþüúòðþþþüøîÜæþþò  ôþüôîòòü ôúâîôúöúîîôòüèèÜôüþðúîúüöøâôôøìæèêøüâàäæü ô þúüîüþþøøøòþü úøöîôôúþ úøòðþü þúììâæìð ôîæÞæâø  úúüþöòöðòîøüîöôúþôøüòöôþü  üúðìòôüþöúøöúüøþø ôòîîîòüüþþþüüòü  øüôòðääÜöþ  øîðúðüô øöììêèìöüü  öøöòüüþêòàøüø  üôèæêîèîðöüîòøü  üúôöò øüòúü üöðàþò úüøúþ ôüøöööôüúüþ þèêöðöÖþô0øòúúðììàðô42 Þòþøüü þôòÞÜðö  þðôêøþþúôæââèôúþðäþôüüþúüðþ þìêàêàðø"öðÞèòþúøðôðöþþúøüþþúüüþøüþúøêøøüúðôöþøò öÖòô * úúÖèöðî(üúäâìæúøüÚ"öàúúüú úîæÞÚÈüðøø  öðäØòö"$þþúüäÜÔÖìöüòúúêþö6 îàèàþæúú üúúüòìòôìâòð üôâøêüìâðò   öòìøüüüúúòúþüôìöô  úöêÖìè  öòúü øü üöôöðôêþøüöîúøþø ø øòðöôúúöøòøþøüôþøúèö òêîäúüþúöðüöòìîìúðúú  ðäØÜôòþ þüôúüöþêìþüøþú üöðúîüøüööðôþ øðøöþô"ìæøúäêææîöþ&üòêäêäìîö  îèÚìæðú üðìÜæêþþ&úîò îôúòìòèøúþøâèêðüü öÞìèøüúøøäôò  òòÞèîòþöðôôø øôàâèòú  üþôöòøþ ôòöøìôúþöüîòøöòüøð"þöôêäøòúþðêîìø öðÞàäèþú ö öòÜäîòôòêòîòúôôþ üöòäúøöüìôôö þøøøüôôðôüþ þöøþàðÞüúþüú  üüêòìþøúüôöòòøüøüøôöð þòî øôæâìîøþö þðþúüüðøøþô ôôðüðúüøàôöèðîðúü  òðæèþúðúüþüüòúúö êæØîòþòöþøüüôúþüô  þúæðäüüúöòðì  úüôüöü þúúúôøúøúòìæäêìú  öøòøîöúþøúîôôþ èöðòøøþþ üþüúúúüúòö üþü úòîîôôúúüþ üþøþþþúøðøôüúúúðîðô þöôöüøøø  üúüþúþþþúøüüþþúúøúöþüþôæðìöðøüú þúöúþþ úüôøìîòðþúøòðîðòúöü üîøê  ÞìÞæøú ìöìöæòêøêþÚèÔþ ôêêìøøúòòèæôö üúôîòôðüøþôøþø úüøöòôþöþúüüþú üôêêèæîðúúôòîø  ôôòðþþü þøöøøøø þþþúþüüüüþúþöì üêôìøü ô úøîììæòòúö   öþôþøøøþ úþöúðæðæ ø  üðòâöøúþ üüðêèêìôø üøøøúô ìôòôúþúúúú ööþôøþððøôüþ  úüüòüþþþþüúòôôöøúþþúöìúúþ  þþøøþþþüøþìê öìèâþìþôþ " úòìäÜþü þúèàúîòú ( ôðìæìòøöðöðúö ðôðòöúúøôôøú üøòìøøþþþüþúøþúþüúüüøþúúþüþöüþøöòøîôøüööúüôööøþö  îüþøüüöôöðìúòúþ.üêÞÔÔÜêþ&(þüöäæÞÞêìø   üòôæàÎÌØØô 82.,öøÌôöüüüôæàÚÚêêö4&ú æðôòüìèÚìØäèHþöôòþöìîèäîèîèìòø  üøøðèæäÞàääüú*.6. öÐÒ¶Ôð4 &èôÖðöþòúôÔæ&êîêööîìêäüüü üúêðÚÚÔäæîô  (..8 üÌîÔìæüæþ 8$,ÔüÌ Òøäúòê  "èäìàèîàøü øø øôäêèâââ üôþúþò$0Öðäìúæü$"úîâÌàÞòöø4ö þúìèàÜèô .ìæÖÖìâüú ""àÞÐÆúö ðêôä  þ"êòâàøöúæðÞ úÖ øöÒèòø êúâòôð4 èÐàØôêòèòôö  þòðìÚæÊâì""þð&òúæêàâîô  òòàâÚÌÜÖô.úúþôüþúæîäâüö ú "øàäèøô Üìêòü  þìèÞÜüþþüôðüô øîâÞàÚôô ôðäÚâêø  øîðÞöô "üúÞøþ0 òÖþàÖêàêüôþðð"ôðæêæîøòü  ðîôäêø øÒþôüøîøø$ àþòìüêîìàöò$öþþòôüôþ öìì øøöü  ôàÞÚêäúú,îììâþòüøòúøææþ ôþøúúæöäúîèÞæàèì"ðôúî  êæÜÔú  ê úüìþêàèæðþøøôú"úâúþ ìúîöæòþôúþöüÜîòô øöþúþøúú þúöüøúþþ üìîäêäæææööüü ü üüúðüüþú üòüøúúúúðüèöàþüúþòòþòþòîôêü üîîúÎìèþü ðúü úôòôîøø  ü úúôêèÚêð  þþüþ üúøîòêúôøððôôôôöúþ þüúþ þüìîâØìêþüú  ( þøüöü ôäêÚøü øúòú  öæÂæàö þøäðÎò4ì ü&üÞÌæØ(òÔîþôôòø<Ðêäô âðÎîúø îü ìüøþöìæøÌðú2ôäòä $ìøìòèðòüâú îüæüâìîöþüêòþüø ôðæêäèÞöð  þþöüôöòæðìôòöüü   þøôîìòâêàîú þüöþðòöôüþþöüêþúðüü ôöèâüÜòÔö øòòþþÜøð üöþôòöòþö øüöúÌøööòØìÖüæ  þöôäöøÚ ôöÞêìþðüøòæ âôÚüòîòäîþþì þòôè þ ( úðîÆàæôþêîàè, ôôü$úþôâôôø$úúØÚìèþúîöîêþôôÌâàìúê "èìâüúð úúöîìäæàøü  ÚìÖôúúúüìüþøøúþööîüøòÎêàþêøþ  ðööîæäþüöþÐäð üüèæøô"úèàô"üöþþöúüöÖîäøüü üô$ôôîöðþþ üÂàÊþ þüðàììø$.æôì êüè  öúüäúî"ðîöúôø  ôÂìØú äüúò úìòúÞìöò " þöþþúööúúöúþúþþ êþüââèì öðòôø ôúòèîêøäêòîþúöîìòöú úøöì  úúðîâòêôä   úòôú  îòèð  òúøöâêâàòð  þ öúìòìèìîòúø  üîðÞÞèæòîþþîøìüôòöúü úúôêþú þúüìþþêüòöúìôüþüøúòúìöôìøðöúú   öúôúìüþúøôþøüüþüêüøúèîèêööøþþúþüúüüúôöììööüöüú ðþöúþüüêôîüþúüöþôþüüðêîúüúúþ  úôîêøôüþüþøúôðöúúüúôòîîîöþ þ òöôòîúøüú öøøöüüðúöøôøúþøüþòüüüòèüòüþòüâööþü  òøöúúüø üúðòäâÞäìôü  øöêøôôøþüüöôþ üþüøøþúüþøþü öúîêþøôøöüúþøþþøúîüþüüøòúü úüÚææêüþ øþðúþúøøú  øôîêø"öðàèìðü èøìô îøøø ôþöúþøîðèøúþôúøþ üöþøðôððþþ  äþöþôþþ þüþúüööþþ  ôøììîæòæðöú öð þöôöøøîþüüþúü ö üöÞôðþòÜèØö öøøü öêòðþþìüøúìêôð þæþðøäöèôþæüòîòèò üôðøöðôòòþþúúúüúöþòüüöèîèúöü üþøðòîúüüøþúìèòêúø  þöîòðþüöòìîüúúüòæüò þìüüö üòþüü Üìðø þðüðü  üþìâîêöþüøôü  ôøîöüþðòèþüüúþúþúúþ þüèòèæòöúè ôèîêúþ  " òäæÜâàúøú  ðÖæàø  ôúþêüòþôþ úòîØêèöô üòêúúþúôüø $ôððüüøüúüôüòøöúþúúôþüüöþäøòððüþðþôøöæúúøøþðúúúþôþþôîöôø øúüüþøðîøöþüúüþúöîîòøø üüüøôôòèêòôüúüþ úüúúúþþøæòîüöüüúúúúüþ ðòàâôðöøîì  úúþøü øîÊÜÐúúæäÊêêô$(ôöîêôöúü  ôÔØÊòðöúúú öàèäìüø&$ èöîüîüØöþ$èöÞØú6ðüò,Úøôäî.öèäääîüøü þöæöòòêîôþòâðæ(üöîâôò þúôú ôîðîôöèö$üêþúôúòöúþâÔääòüüööòæôòîÚäÜúøþüð üÞòîþøúôøôôþú$úüúöþüôðòôäðþ öüðîôúþþ òüèþ ööüôüþúúöðêèèæöü*üøôúüìüòúîøüúþòüîþþèúöòþ øöðêäîîþ þ îòØðúâüò  üøìÜìê þ  ôôØäðòþþøüøúþ  øöîæàââêêøþ  ôöØþêìèàðèþ $òäöêþüøðîòô 0 ÖøÚþ ÔêÖîòì<þ Ìèøø ðêòøúòð ðþöö"êìîâðÞæöô ú ð ðúÌîèêþ  øîöäêðø$èìüøæòþüòøôðü  øúææöæîòþüüô îøìèêâêîð  öÖæèúþ þüøôîìüäøþúø úâðÔüæúêþöôúþ  îðÚüøüòêú  üì øþæôðþòøüöüþúøðòòàðòòò  øúö öøôøüúôìþøúæôêîòàöìø.ôüÞÜèè ü öðððÜ &"þØøúêðêîü"&øÔæôîôúø øâöôðüü üààÐèîøöøôþôæòìþ êúê*þòðöööø üàøäøàèîö " âôðäøüðôæòüþ üàìîêêúöâþúöþø  $*Üúäø Üâêàòôôîêü ìðòúòî$ üüÚäâèöìöüþ üöîúöþúþöüþ þøöøêþø úøìêðò öþøøöú  þøôòôöþüòøúü øìæäîêöú úôü úîöþ öìæêìî þöðîòîîü þôîøôþüþüüúþüöúüúúôôúøþöüþôþüüüôüø  ü úðîìðîîöúþþðöæøüøüüöüüúüþ  üöøðúîòîúòöòöøø þððììðîôüüþþúþú  úèììúöüúø öôðîøèòî þôôêôöúþþþööêÞììôþ ôôøòúþ øüèêöþü òúøþôöîøüþ ðúüúüøìððî îöÚþøìøöäþø ü øøðøúü þøøøúþþþôúòöüòþ üöôþ üøôöú  þôôîôîîìîþøüøüú ðøôþöøþþúúúøüþôøìøúöþöþü üòöøøöþüþüüöðîîöðòúþþþüüþüüòüúþüüøîôöüøþüüüþüôþüþôüòøþüúøüòôþüòþìþøüúòòôööþöúþþòðò êðþôôòôøúþøòüþüúäêàöþ  òöøøööòöêîü üüøþþúþøòøæðîúôþþþúöîîîöòúü öêòèîøöò ø øþìêöòþþø úàòäúôâðòø þøúüúðîøø öøèøôöúôìøî üüüüöþüúöúòþ üúìöøòþöòîòþ îòæöþüèìêÜâæô þôòêòîìüêöú öô îüèæþêþÜêîö øöôöúøþöüôøð þþüøøòðøöþ øòîØìèú þúöúü öøôþ þöîðþìîôðôòòøøüþøöôìòêîäüü øþôúø þøôöîþþþøöôòúú üüøööîøøúüþüúîâîÌôòúöú òúæþúöøöôúèüúúüøôöèîäòúü  üüôèøôþüþþðððöþ öþîþúäøìôôôþþ ôøüüúøþü üüþü þþôòöòúúöøøüòðôôþüöüìúþøüþøþôöèðüúø  þúöôðòðøþþúþþúþþüøøøøøþöü  ôþüþîìôöüüúøüþüüøôòðòòöüþ øúøüúúþþø þüúüôøü þöøøìòøð úöþüúìøôøúöüøü úúìúôöüöüþö ø þüòøøöüúøüþ  þüôòîððîøøúþðøøøüúøüèöðþú öþüþúúòúü öøæîîøüøþüüöøòòöòúèèêøôüúøúþúöæôò   úðäööüþ üüðöü ôøúþòþòêöæþ þøðöîü îþúúøþúþöôüôöüüöþêüøú úþòúøôöôòþüþþööööôüúúüöööúþ üîþôðüÖúþöüæ úøòòúü üüþþþüúöüúüúøòúòüþôþ  öøôúüòøðøúúüþøúúöüôøøúüþ üüþöøêøøúüþð ôüòúüú îðÜôðøüðþööþøþòüôâàèèþ üðâêêîø"6 ØÖìâþäòÞÜðüø.àîÞâ Öèìî Üô "Îèæð úêîäòòþ 2üäÒòî öúôìüîøüü  úöàÚÔ¾êèò & ðîâäêòþ  þôðÖÚºÔàò$ "öðþüôòäæÒøøøÚøöèöôòðöþðþ þîÜâØø& öøþú ìèâÖæìòü .öäâÖàø öæèÔò$ Üì40Øôüð4ôàþìüðäêôò , øìêÞòöòüøþþüò êöÜòôîðÞöúðøêøÔÞèè  úþúþòü ìþâ üúøö $êæÚâìòæôèîøðþ üìæèö ôú  ðüìüæäìÚääøüòþ ø" ððÒöòüòúôþúðêüîöøöü0øòäúþüööôúæðð ìþðúöþâèòòôú  òþüþþþöúòúüþ þþöøòîôæúöúôööüþðöìþðøúúúþú þööúæôîøþþ øüðòöðîþö" ö öþÎôê øîþüþþøôîèðâ þþúðäÞØêðö þüôüü  þþôöúîòòôêòðúþþ þüøöÖèÚþööúôúò"üúø òôÔîìô ôüòö øüÆèèòúÞôÐ&ø ô* ÚðÌðþ"þØèð äú 4ü êâô þÊòæòø êöüöþ îüôúôôææÖü øèü(þøüðìúììüü úð þþàèôô ôèîþþô    ôòèæàÚòòöô üúøöøüþêôîîòîôôúþüòúîêäØöð üþðöêøðôêúü èøêÚòâ äøìþ úðü þöòèèêæø öü( äúèæèæ ìæþüú üþòøîþôöâþø øöæîìüþöøôêòìþ ðüþ ðüîøøþøþ 2ðöèô þðòÖÞìêúøèàúè(êüÞìúðôòæúø   þöÔâÚîþüþüö úðöîþöüþ þ üþôìàÒêîìüô öîòì úöþèîöö üúâÚêìôøüøööü ÚúêüîøìøôÔþöþúôôØòöîöêúüìììêìð ö üêþüæ "êüÀúöüìôäÜîì"Þöúâúþæðôðöî * âÚüêøòèôòòúúøøþøòøú øôöîòøú öòîøðìüôòôîðüø üèþúøìòüø üþðøööúöúöòøô  þôîÞèæôàþþþüø þúôæÞèêòêöìøð   øüôôæòôöþæììòö öðîìðþ þúúöúüüúúøìúòúòöú  üêøö þþòüþþþú ìð úüèòòðúúþøú  þêìàøúþöþøþüüþüþøüäöòòúðöììþþ þþ òôìòøôüüþþüúö òèðèöúüüøúôüþþúþîþøøðüö þúúúþúôöôøôüþüøøîôðüòú  ìøîüööúôøøøüø úüòòøôþøþüúüüøþúüüþþþö ôþòüþöêöîþþü úôöòþüüôøìêààæêòøþ üðôîðæòöþ  øøòòöôøòþþøþøîôðòîôôüþúöîöúþðôôòüúúøøðòööüüþüøü    Þüîøúðòòêôúü þ òôèòø üæþ øøþþúüôôøôþòøêòþôúöüüþ úøööìôþööþòø îööøøîþìüìøþøò äìîèþÜòàþ ôøþ ô  æðüò ÎðÚê ü èöôæþ âôôü øæòöô úüôúøúúðúöþþúèæâÚòò üüú úìüþþ ú þü êòâöðîøêüú üöüú üþüüúüþðøøöôüúþüüøöððþ üüúúüü þööøîôþþòþôú úþòôæòìþþþúþ  üøòúþòþøüðêîäüü úöúúôôüþöüüöþ úþôúðøðîúü*üöþüðîâäðú" ôæèÞúìðòøþ"üþäæöðüüøôôòôþúöþô þæîöðæòâèøòöúæþ þúðöþöøúøúüþüþüüðêâàêîú üòþôøôü  ôöüöüôü þúèìêòþþüúøöúü úúôððôøúþþøúøøúüúüööôöú  îøìäìæèòö òþúîþþ ööìúøüúèàòêøúöüøþþþþøôôüøüúøøòòþ   úüîüüüöúúúþþ úøüþþþþþüòøþøúþþøþþôüüþþüüøööøô þøøêøôþò øöøú îôðø úüööüúððîæôôð êúîþþê öüàðöîúìúú ìæâØöüü$òðøöþúüêæäÜæúü $üðèÚàìôüêôÒææ ìôØìø6üÊò*øØÒêàêøôì 6ðþìâæêðú îþðìöôô  æøÊ þúôâðô4úØöòäþèäîÖúþ * öúüðòòìøüøêì  öøüþðàææôè *ôþìäôìðü þðìäø  üúôúöüüúàôèòââêàÜîþ" þøú üüäæäøþþööþ þòòâôðôøúüüúúð òìøæ êìúôöæüüðôúþöâêâðøôþþþúüüþþ  òòîæêäèìîþüøüöèôìöþ  þôòöð úúüöüþäøîúú úöüîôîìúô òöêøÚìüþþòþþþüòúúøøìîðêòö ü þöòôæìÜðø þþþüúööðúöôððúúüöúøþ üúúüúôèìØêìüþø úòöìþìîäàþúìø øþ èÎÞÚú üüÖâîð& îîø&ìòÄðôú&êöÞîþòîæðöìÔøþ âÞîê ðöþö$èþøèÜâäâ 2úàôþ$þòòþìîúòúòö ôøúäøðòÎöìôâú ú öþ  þ þêðîèâèø  ôþööòîøôøúøþþ   øîôîèðæòØêîôø ú øöþúøþþúþðôøèúüî$øðøø øìæ ò Øø"ðîøòðþî þöòôìöú þøôþÞþî þøìðÔöôúÚüì "ôòöüüîôþøúÜòèþ ôôúàðöþ øòèêòî êúèüþæööúþþ*öâìêö øøòèâîî ø èìââüþ(øâìØ  ðððö  ââÔÜðô  öøöôüüöäòìúüú þ üüüöúìäêê  þìú ôðôôþðôøêðèòþþ òîâÞöòþüôþò üú êôèöüòøú öâæÔúð òüàðôäø øòþ úüôâþöìþþöòüôèüôôüøüàÊêâ ðòèæöüüÚþðîôú öü Òøè øöþè$ìâòôüæø æþäþúìþþ öüúüöüôøöüøöúúøþüúþôôøö þúþö òòæøòüô  øúðöòôöü þöðôúúþ úöêàäØòôú üøþôþü úüúþþ þüþøôèäèìþôþ øôôîöôôôööøüü üöîèêèîðôüþúöúò úúîööôüüòúþúòüöøú úþðþ üöüöþþüþðøöþüþøúþôîðôöøþúþúìøøüðüþþüøþðüöþþþüüú þúü ôôìîèäúôøþôüòúþøþøþ öþî úøîþúúðú öú èøôòúöþþüöøúøþþüøòððòôþ þúüøøðöôðöîòòú  üîøîôøüúüüú üþôüþü þööúöüüøøøøüþ  øþüþúòêòðòüúüüúþøøööø  üúøüüøôúôøøþþþþúôþøøþúôðìîôø  üúöúöúöôúüþöøìêòô üú úöîìòô úôøøúòööêðæðø  øìêÐèâêìôüü  úäèÔøôòüüþøþ ú äðÚöôôüþúð þü öøðêìðòæöôøþþþþòöôÚææêøòþþ þàêîæøþþ&úôþþôúðìîìòøðêæêäììþ ìàÜÐêô úöðîìô   îìâèÚìø øúîð øèìæøüâäüö üúúòöú $ ü俯êð üôîòòøüþüüöòòòðòèöèìðâ&"úúð øìöäôääîî  üúðîîæòæêôî "0öþúúþ üþæøöþôúèäêàî  ò&úÔèÞüèü îöðø  øüøúöòòèêèæ(þìüìüüü üòìêØæâú  þ  ìðäâêêøø øðüîò  üìîâðþ*úÜôèüúêìÔúööòúøþ üòòèêîîöüøú üúìôìôÜðòú îöÖüþøøô ììäîþøöðôôô "òòäþüøôøúð ôúìòöìöðúü  òàÜØæììü(øöîòøüø þ üòðìì üþúúüþüþþþþøüôêöîøôðôôîöð þþúôúö  ôüøîôâèÞòþþ üòüþø ö îîêêúöüþþ  òôøèòþîøþöüæü úø öúúðþúüòøæîøö  òúòöþøøøüüüþþþ  æêàèììþöüüú þüþøôòèüøü þøîðêîøöüøøìòôôôúþòòüøú øöúøüþþö ðøêöòöÞòîüøüðüúüüüþôööøøü üøöúúüúøðøððòêòðüüøøîðæòúúöþøþþ   þüôöôøþþôþøòøìòèæòô   üôðìòôüþþøìòìüöþüþøàâÎêö ìîêê $îøøð  ðîØÜòøöòÜðöö úþôôø$ îôäöúþàìòø þüþ äøîüüøøæúø þüøðòøüþøöðäøîüèþ  þêööú öú øúüüðüþ üøüþúøüüøüüüüþøþúúôôöüöþ üúòöøü  þøôìîêêìðòöúþ  þøöòòôôüúþþ þøøöøüþüüðòððôöúþúþüþþúüüþüúö  úþþúþøúúüþüüøþüþúþöøúú þöðòðððîîêîîðôöøúþ þüöøööôöüúöòúúü þøüúþüüúúøôòðöööôøöúööôôüúüúü  úèäìîüúüøîôøöüø üüúúþþþþüþþþüüøúöôöøüøþø úúþúþúúüöþôôêêðòúøüüþüøüüôüö òüö þøúìòøþüúøþúþþøöøòðôôúþþþþúþþþþþüü úöòîøöüüþúøüøüüøøôøøøþþþþðêäÞÜÜàäðö  úúöüöøöøþüúüôþìüúüòØðäúöøöòüü úþöðèîìòøøþüüþüúüøøúüþþüþþþþþüüüüúþüüüôþþøúüòðêäððúøôúôøúööøöøòøúü òîììòø þöììêôòúþ úöîòöø ú þööôòúøþü  úþþöîìæìòüþðôúôöúöúø" üøìøðüöüþüôôêøüúþôôâòúüþ  üôôøöòøöþöþ øöîîöòúüøúúòüøøæöòþüîôòôþòþú ôúôüøòðòþüþü îøòúúø  øöèèàæòø úúüüüþüúúøòöôúüþþ   øöðôîððüöþòòôöüþ øúðäàäôôúøþ ôöìüôúöüþüøúðøúü  þþüôòðâöðüðòòöø" üàðäúüþðþþôäìàîìèòì þôäúðüöîòìøüþ úþþðöêò üþúøþ úôìèæâæäðö  üúøúþþþþúøôòôöüþþþúþþ úúöþúüôôööüþüúþþþöúøüòþü  øøøöúúüþþþþöúøøüúþôúööîðððêððøúþ þþþúüúøúøúúúþüúöúøúòööøþúúüúúúøþþøöúîðòðøüüþüðôàêöø  òÜâÔòúþ úúîäöð øôðîðððúøþü þøøöööøüüüþüþüîîæäððþü  üüúøüøøøøþüþüöüúúúøúüüúüúøþþüþþüôööôøòôöøúþüöüðüüüìúô  þþü þúðòòöþþþúøðôðòîþ þôöüøþþþúöøððþü öððêþü þþúôøúú þúúþøþþþøîöîüôöúöøúôúôðöøòöøú üüþþüüüüöþ ööüüøüþüüüüúüúúøöôðúøþøþøþúüþúøøúüþúúüþþþþþü ôôèòôöþþüü þüüúþþúøöüþüúöôòúøüúüþúþúöôîîêðöþòö úþüúúþúôöîööîþð  Þîàðþ úúöôöôüüüü  úøüâäÜàøöôèòô  úüôþþ üüüôöþöúòüö  üüúúüþúøøøþö úüäàæàüôüþöü úüþüþ úþþúòüøúúô ìäàÞðò þüüøþþüþüüúüüþþþüüúøøôöøúòôòôøôööøþ  þþúü öþöøøöúúøþüüþôöòøööúúüþþüøôööøöüþøúüþþúöôîüøúüøöüúúöøòööøøøúþþúüöúþüþüøöôîôòøþúòøöþüþúøøøüþ  øöôöüôöòþþþþþþúþôþüüòðîèððúúüúþþøøøúö þüüøúúüôüüþþüüúþúúøúøúúþþòüþþüüþþþüüöüúüüúþúþøúôüúúüúüüþþþþþøöøöøúúüøúüþúþþøòìîìðôøþþþúþþþþþ   öøòôöøüþúøúôüþúøúøøøøüúþþþúüøúþþüþüúôòôôöøúþþþþüüþþþþúþúþþ   üöôìòööþþôüøöôöüþþþþþþúþþ  öúôüôôòöôôôôøøúúúøøüúüøúüþþüüöøúüþþúöüþø  úúðòòòü  þøæòì üþöøøöüüþüöøööüú ôôðîòôúþþþþþüþþú üúþüþþþüúöòòðòôöúþüþþúúþþþúþúþüöüö þúøöþüþþüþúúüüþþ øþþüü öðöðüþúøúúúöúüüúþþúüúþøþöþüþøþüüþüþ üüþþúüøüþüþþþþüþüþüþþüüüüþþþþþüüüüüüþüþüúüøüüþøøôööøúúüþþþþþþþüþþúüööööôøøþüþôöòøøúüüþþþþüúòöøøúøøøöøööøøúúþþþþü úúòôøöþ  þòôôôøøúüúþþþþþüþþüþöøøúþúööúøþþüúøúþøøöôúøþüüüüøüööúöþþúúðúøþü þôôôôþþüþþîòîøøúþþþüüøöúúþüþþþþþþþüüþøúôööüüþþüüúþúüúþþþþþþüþþþþþþüþþúúøþüøüöüöøúøüôøôúþþúþþþüøüüþúþþþþüüþüüúøööúúþüüôúôôøòúòîðìüþ þþüöööøúüþþøøêîúþ þþúüþþþþþüüúøôòèìêüúþþòöìôøôþôòôêþ üþúøüøôöòöúöþúøü êöððøôþüüüúúôøöüüþøüþþüúüúüüþüü ôúðúôöúüþüþøüöúþú þúôîêììöþþüúøöüöøøîöòþüüúöþö þöúöøþþþþþü öòðòòôöþúúøøþúøöúþþ öðìèêøþ üôþôüþ þüúúþ þîöðúþüüúúôòòòü üþþøþþúúøòðìðòðúüüþöþüüþ êòæòäæîöòôòþþ üþþþüüøþ úòðèðôøüúúúöüþúüþøøøüþüüþþüúöööúþþþøüüôôöøüþüþþþþüþüþúøðòôööðôòôìîììúú  üþ üþööøøúøìòîôööüüüþüþòøôüþ þþúøþøüðøøüþüüúúöøøþþüþþüúúúúüüþöúüüøüþüþ úúúøþþüîèîìöú øööòþüøúúôòüøþüøòööúþüþþþþüþþþúøôúüüþúøðöøþþüþþþúúúøüüúúøøúôüúþüøüúþþúøøöþ   ööòøðöúþúüúþþþúøúòööþúøúöúúüüúöøòòòðòôøüüøøøöþþ ööòúøìüþ ü þøøøðôäèìöþüþôüüöþúþðþüôøôüö øøöüþüðòü øöøöòðòööøú úöîêüúþüúòøøüöòîîêòö ððäîøöøø ôüüü þüþþðøööþòü øüöþ þüúüþðúîüþøöìöúø øþìòúø øüôôîòøúøü øüîøþöþúúþöúøüþöúøøúþôòêðöü  úøðêîìööúþüþþüþøþþþþúþüþþþþüüüüþþþþþþþüþüüüþøøôôþüüøöìîêììîôøþüþüþþþþþúüúþüüúüüþþþþüüúúúüúüüúúüüþúþúúúüúþþþþüþüúüöøúøþüüþöüüþþþþüüúúþþþþüúüúüüüþüþüþþøøòöðòöü  ööôôøúúöøöúøúþþüöòôòøúüüü   üþþüüúúüúúüøüúúúìúöòöðòøú úüþöþúøôòòôøüþúþúþöúþúüúöôòòòôôúüþþþú þüôðòòöúüþþþüþþþþþüþþþüþüþþúüøúüøüöúúúøööôòôòöøøüþþþþ øðòðöþ  úòüþüþþüøüúüúüüüøúüþúúôòöôüôøôööúþ  þþúòòðòøöüúúþúþúúøúüüþüüöööúüüþþþüüþúøúøúøþþþþøþ úøüþ þðöòôüü þúøúôúþþüþúøúúüüþþþþüþüüúøúøüúúúúüúúþúüúüüúüüüþþüþüþþþüüøþþþþüüüþúüúúþôôìîôöþüúþúöüìðæêú þþúþþüþúþú  ðöîòøøþþðüüúöòôîðòôþüôìèììôøüüþüüüúüüþþ þþþúüøúþþþöøöüøöòòðòþþþüüúþúúôôööüüþþüþôúø úüúöü üþ úøøôöúú þôôöìþöøîèøôøúøþþüüúúüúüþüþþøþüþøööòøúúþþþþþüüüþþþþþøúøþþúþúþüüüüþþúüú  úöòôöúþþþþüüüüüþüþúúúøüþþþüúúúúøøøúüüüþúúúøúúüüüþüüüüþþüüúþüúöúúúþöúôüúööîôòøcrossfire-client-1.75.3/sounds/su-fanf.wav000644 001751 001751 00000433630 14165625676 021366 0ustar00kevinzkevinz000000 000000 RIFF7WAVEfmt +"VLISTINFOISFTLavf54.63.104dataH7 ïùÛó ý¹öñ4ÖüÊ ç'úõö-êøùêë7íú$ÐýßD´ôÖ:æýúß!)óÏ5ëÜÿþÛ ù$þ÷÷üÝüä$á# Ýâ ññÆ"ùMÇïì ôÓöÍ!ý ïó# Üâüñ*Ìòéøæé ÜÞ$ÌÎ.õõ0Ó÷ÿó-áïäý÷ Éÿö÷õðý&òýñèõ%Òùý 3ýêBÜø¾! öóñúê(ì¯þ×Û&áîúöÍü â÷æéñ;ë1åèä ðéå-Éþ Æòæûýü-÷óùÜ=âóì$þ?°î×üþó ÷ òû¦ð+Ð Ð 8 úÒ!èþÒ. ö ÷ÿàæ±>ÿ.Ö ù+Ææðøãê "Þõñíø ü2û Ïþùïýõìì * ÀéÖû"áî-üÓ ëóð ý)ìðÙîù)â á3ñ÷ÝÝêÞæÌ!0áéîëîöIý ìì ÿ ÷öìæòÄ?ü æê ôîäÒ7ä Òøÿ" ¶ìêíûáý;Âõõåýñ¬ù;$)Ýãüøîô ÿâÿý÷ÿóóà û,õùþí÷Ê×ýàôü ü ö9éæÙöïïÿ2ÑýÕòûÌÜÊ! "'çþ÷âßø û òüó ë÷¾ ñ2çþýÚðõâüþÞ"üï&ãùË/ ù ×ýñÖ Þ$ È+èéñèÚûÒíþþ üèóóæñàÝ(ë éßÔ'ÆëË2ÿ ñù"üþïëúì÷Çê îñí6ÿøþ÷äòä Óòìûûôñáù!ý çóîøðë#ÐêÜ&üùùîûâðí *÷"áàòÞ þþêü&óýìãWÕÿù.Ûðò÷ûûáõñÛëôâ1Û ï òêÅëòÚ øôîë÷èÖ-ÊöîþúÞùôÿç ô(ñøÍÿúô"Òçûúêö Ó û4Ïþôýþ5 ìÿúåôóàóòôý  îöäÿùòòô  â òÂý  ä%ÿëÞçóÿó öêæïßó õ2á÷÷úþ ê ÿòðæÕÒ#ô ø6ìì·ð÷ÿÝøÿCÞ#¬ýêî(÷FèøüÑ÷í ÿÆ'÷ ÍóøÑíëHÏøü/þØþ*Õêô¿þñþ +íýÉüò úí ðï¼ öýMÛ.Ïý·î Ü%íí½õëÚ#×îï7èüúØ ø×&üúÆüüþ õêýÂó¸Cëþü Íæìû ) þÐøîþþþÙ##ØýöÛ"æöòåùHíßÞ"÷ÿ!ê÷í äñâîûóí'úÎùõìëôû #þÙàòç ð íùù· ü ù íÔÛ éÌéóöMõîÆ óäþíþæèóí )ôÿÑÿ÷ëöô åò÷æýô%ùöAÝüþÏ%ù÷õõõçúô øýáó3ÿîóÓ÷ ÿñ 7ßçùØø÷õøìüòðýäç ûéôïìôõöõ(ÿÛüúôù#ü÷Ýððåôý¿ü Á ùöóûñ øøñöúö÷úïÿ!èùïÛÛþ*ç" Ü ûüÿ ðüý»9óåï ïNòôúü öâäÕ÷ö "ýñÔ ûöòâçéú Öêý%óô&ãñÒö ß !íôû øøæöØàõ ú÷ëïìüëôçð õ ù"Ýýî#6 ÖóíêöÏ(Ï& ÷ þôãôóé ù!ûüý Äûö Ðøòõöòúîýõ Óíþö"çóóÿýóþÿõ $öæëöì ×ýþö"ó+ æÿÜöùìú1Çî3ó¶õý òôøñ ßÿ 6¼÷íúÆ%üßÝ"øù ýà' åýýËü Û  ùëìæÓ#ôôöæ$ò7çõ¸ ðúÙûî÷ ïèù õ×ñÔ$ýûìéóüÿÝûïBé ÛöÎéóæ øâùòüþôû  Ôìç @ã ÿø%àüþðóê)óàúëðýèú÷þ%È /òì7Óéâýèóæ çõõëôÇö ø Þ  ùûü×ÿöáõøþí ñääýþðüùóóø æööùú þ îýøæçðúáýßaìå?úø"ðúêÿÿù å:âòÖË #øîöèôþóý ú÷!ðóÞË,åíðò! äúù êø÷ðæäì6òûüöý Ëçóì ôðüæëòñ! ù÷ððßñüüóÜïÜ'ñï $Ç ë-òóóðØøÍRê#ðû%øøÑþøï ÏùýêÖðÜ>ö ûòøáãùý#÷ üïüòãÜåÝ;Óý ÖøÑ÷ ðõ üìíîçéýOÇçü×øïÿûíöù ðþØõ %ðþâöóîûøì*ó ï ëôãÝ ðþýñÿûþ â&ñýüñõê ñõò ûÛøýéøÈõóÒÙû ûþùíðñêøøýîûåèíñýÿûëéãøýõüæúýû îðÝöèô8ù$Ú÷ÝîòÜü&åòàóüè+ù û õÌïåæ.ÕýÂ\çúØñ(ëôòüùÿó,ù ØýâAÝýøò úîëäâúØãì <  ÷åçôñ ô(÷ãFÇùý Ôç â Òþô÷òð"ÿ/ÔùõþõôÛôÿ úäô$¶ÿì é÷! ÷Îöùôòüø ãíÐíôà-Ýÿþñ5Íÿð þ×þüÈùþóüðïñ(Ù ÷Ò õåèñúé -" °ïñäëôýæææøìþ  ËÃ'ÿÇ öð ðù ïùØñ ùýâáðÜü÷õ ý%÷ëÕà õãù  î>åôÞäòòõ÷ñöóôÞ$ïÕùü õ×ð ýóæç-ñÙÿÿ àð òäîÑ þ#  ó ì°ûü5 ó îú·óüý ë3õûéÛþì äöÍîõþâùÝó÷ù ç#Æ ùôùéÑö ùÀçüþúùAîúøñÓÒ÷ý ôð*Âöòûþ ôõ Ùîüûû%éù þ øöñÿå÷çúÿÅöø$ôøÖßæ(ó $Úûþ·ôâý öûùÓôøý ç ýùíéç ÷ õ ìéíÊ 5êßúåìííóûâ)  óõÅ÷ ö" Î/äïäßü  øò óþÏüü Ö óÊøòÿóúÅîõäßðÈ÷F ñþÈ ð:ãã1ÖëìÛ þ äúòöÌ ò÷ëü¾ù #ÃüÜ  ñ ÿüõóí äûâ íìô úåìé.þ áì½óîõ Öðññíøà*þ÷ ó)Çòâþñ Õ"øåÿï òèôîùãð÷LÝ%êöüÞòøì) þïõò¨öùáCûñúüõôöïê+ïýÆñûýþû#éêíýø!ïöçøùóùúð÷, î#ûþãêô÷î+ ÿôêêâí ü.äøîùõúéõ û ÿ!ààâþú$Õá þå ýóßþîêüßïõýêóñõö "üãóæÊðñ  ä÷òøèüì þÿýñ Æöïüáû÷ øýðõôìøóÖ# îôí èÿ  ñ·èþÏ !ûìäþóÿâøê&þ øøíëû ýöäñÿþ óúïïïøÝôûØ) ðøóÝöõ 'íîáÚíç âòüóñ÷ò ú ýìòé÷î=ñùÿðýþ íûùþîû÷ôø÷ð# õë úèø %ìëêùßäï  "úðìçÃûë÷.Ç ýøùøëöôôHÍõ þý ä þ)õûùßñåàðíé 2þJ´ëïñò ÿôæ.Âæ¾8Ùôí éõàü  ó ûûùÝöèîûçûø õüñõúòëøÜ  Öî(àûó úûùí ÝñË ýìøÛñøØÿ Ï  úÞùñøÿäõ üå÷ôïîÃúñ$*þþæ÷ý"Ôû  ÜóôÑüûì è&û Ëòüü÷1éé)ýú äõì÷ÿ ãýûý (ûß÷ð îþÝõí( óëÖ'òâÿõ ê%þíìúôÜÿöø'õôûèéêüù ãþùë û ê óõùý ÿæëõüðèêâ ,àûìý îù é ÚØôûú(ñ  Ûôç ùø,öõþýò ûùùâ×ý ï0êúßîôêïòë ú7ð ÷÷ç ôü ú ü#ïôûÑùóð-ùÿôïÿëõàö)Ìàÿ   üÿþùäíýï ïÿë%Òîìôû÷+)íüÙóýþÑüôÞóòà,íñòúÿöêüþ¯ úûÿöûï÷úôûéùÿÄýìðõö õäÜøï ù  òúÙüõÿÿõû)÷øíùúôÛ÷õÿïåÒ' ô ü ÿÿÖýóÿúÕçÏÿÿæñ$Üöñ ÿøìðáõîøð ( øÚôêøþùòö(úþÝððü,ðûþððæúÿ íööõÙíîåýü"ÿíäñì þ üÿèíñëùÿýýñíôù÷Òû1ýçõÿôó þËö÷ó$ûé íöëáðø÷ôüøèÿöûÿõÿ èåêàñ ó %ÿî÷õþþ%é÷ÿ ÿñüò ÿýêöûþ íýýü÷ÿþîÚööð Ö ÿ áúöù ü ûýîõüæ.Ê2Þüùïûúøõþìòýô%òñû è þîðïü÷ýþ íù øÖòøßÿùð íå øó ðôêôøñùìíÕ÷ôí ÷óøøÿòù üùð Øþëü ýæèòû åü þÖÿñüýþÜôüöþþ öÿÌö6ÚöÜþýôæòÿ ÿúï  ð÷× ù úðþîïáðü'æýôÿþýè  ÷äÛúìùø ÷ü þéúä Þß1ûöðõëïþäö Úí  üþ!ûýïí÷ú ððþ÷þúòøõõþìøèù øùù×ÿøÿîþåù óüñú  ñ øÿÙøùýýþþúýöíüÿü øùüìð1æöüþ ù÷õÿõÿ þñôþý øõñûöýüôëþû øöùüö ôüíû äýýîüÜüüèùýùððÿþúýàùïüûþüæþôûýþýûþüñûô÷øèü÷ óíöþøþ÷óú ÿùýúýþúþòÿûý÷õüø÷ûùÿÿþþöþïö÷óÿ úÿþóýýíúú÷öÿúöþûúüõõÿÿ÷üûüçû ðÿüÿüôýûÿþ þöûø êýøú÷ûúìü üïþúø÷ øÿûû úì úý ÿùñéþ ûÿïúýïýøòû ÿüþîýþêûì ñúí÷ùê øùù öôýÿýýø üóÿø øäüøõøûùöþíÿûþýüóùùþüôôíó üëþñþúüì ÿýùüúëøýûéþõ øýðþûúþÿ÷ÿ ÷ýøúåÿïÿüþõþó  úûôýóýþô øõïþöøöþÿùü ùýüþûþ öÿù ûÿúûüþÿûýùúýòþþü ûúù÷õõ ûüüöÿúùôüùüüûýþýüÿÿüýþþüÿþýüüüýþüüúúüþþÿüÿúÿþýþÿýûûøþóýüýýýùþþüþûðÿþúÿ ÷ýúþûþÿøüúû óþù úþúùÿõøþýùüýÿïþüô ó÷ðûó úÿ öÿûýüðùôûýòü ìþýýöûüô ÿü ñþÿû ÿýûþ ÿýêûüýûù÷ûûûýüþýûùýëþþùûúþûöüñþîõû÷óúûþÿùú÷ò ýóþïôÿþôþþþö ýüøùÿýöý÷ÿÿùÿþùýýû øýûþúþúþý úøýøúùûüúúûþüûúþü ÷ÿÿøýüúüüüüÿÿýüþþ ÿÿþýýþúüþüþýþÿûûÿÿüÿÿþöþûþùüÿü öþüüÿþýÿþþ÷ÿü öÿøýûþþòþûþÿÿÿÿúþüøýüùüýûöýúùÿþýþøõþñÿøþ øøÿóÿþüþþ÷ÿýýùøøüùüüÿþûÿúÿù þùû÷ÿþùúþýüüøþýõþùôüêüôûúôù ñÿü÷üìþùüúôÿòÿôþüõý÷úþõöü ÿùûúúñüò ëñ&ùù ôûõì þÿþ õ$ìüñüúõçý ÷ü!íûö ëýñýû ÿÿ õüûìø$á÷ð é÷åéý üúñíõûôÿèðùôóüä ùÞù÷ùüý ú÷îÿÿè óýëñøÿ$êè* Þõøü  ÿ'éïþíûÝþùùôêòÚ ûòûüïþÝôËó$Ýæøûþüóòâùñûñö÷ô üÞ  ìåÛïüìüòïöìüçüß üíÿþý5ûàùö Íøßýþ Ùî÷Õü ö åþæûùò$!ÿùüù#øýôöðàè÷&ÿèøæ ôüûôö&Éþ  äÓùë øýå "àùÜ2Öè-ÿØíóàôûß:éÛÓüâþùÊìÐ)ýãÿïüÚû1éúß !øîîûôûéíûõãö õ "äÿÿóýüòú÷îþûû Úôáäÿ åùøáûýîþÿÿéõö?Þâ Ûýîö÷÷ûö þ÷ Åïê íñæüúë÷óþ èúþõÔþí÷ûïðñ Þ ç  üýöøñðùåòüõ+þõòðø!þáý çøìÙéúû ñö÷ìçø'ûêýýþëýïóôò í ëó)ôÿëõâèåþ ÷ïã÷õúöúýìýïõì  ûõûòûÛþü ùÿíå÷õ Úçðûõ #ñì÷êûíîì íþë ñöÿù üòöãØß×ü îø÷úú êøõïõóëêþèôì ùüõòðîößü ò!àñßäî'êûòóóøñòü  Ôñïíõåþüýíúìòðû ãúûÿñ öþçöîýÿüñý øû ýòýÑ òþôáìäÿíù    ñøóýõñéê:éüöüûè÷ö öüDÏùûæûø  ùñûÐ ùüåÿôôùüýà ÿ ÿ'þõÕÕúðë $ðçá Üùþú ÿøúøá ùæþýüüþþçíàùü øÿóùúí ôÿ åúö èýöúü÷ùó÷ùó, âÿãôþÐúöæø÷åðóû ùÏ ÿÌùðôýüÞÿýÞöøå.æù ÷Ú Íÿýõ(øÿìä÷â>èÔâöß ÷ó ÷Ð% ø  ð íîìû Þû² 8ì ýûåõíöþ!ëÿÛ)àùØýàÿ øüí ÛÿÜ )ÙþÝ1åöðè0ÉþãôËý ÖÿëðîÊ5 òõÝíò úýñæþ ïôñÿú þÖ÷íüüÛø ÿ÷Ñÿñ Ëú" ù ÔúôÔîó÷ý&÷óöúéøöÿý Æ7èññð õ â ò÷Ø  üñûïõþéíùöóúþê ùúùþëøòøüäü÷üøð ûùú íà üñê ùû ñ5ïùÏôüü âIãöÜíüöúíùã ÿûö þ ÷ý ÿ ôìô ÛìÔ?çÌ 7óûÕîøö %ù ÒóüôÏÝ þÙÿø4ãúð î üÛôûè%*àÖèü-Æöêîû+ßâî /âä õôö ô1/¶òßý þ(õÛýäÙúíì-ö¶ÿ@â ó ïßûü Ùóçó=øäÕ ÕõÎ÷*Úÿù!Úßúì" ùòìÔô6ú ëðÿð*×óâåù)ñõ»ô û îêüû×ìù# óöáþú ÍñÓ*ùþùò÷öäø áñõÇ2éôãýý1íòùÖýû,Ëó>ñöõÔññ üøã1èòúíùßõ'ï¸ <óõøë0Øïá!Û è ç÷Á7éõåü:Ï÷íåý÷ ûïý ýùçýÿòþû)Ýàü:æñ ÷Ý÷ô)÷ð´ =ùÿé8±öìíâM$Ê Éìà ÷÷ ñ*àÚîúî8þöîï?óòÖäüæKåñè ü8Òíúô*ó$üÝÏó6åëïÌü&üóáîòöûçFîÚðµú × æøâõ÷ì:äý ò ý1ýõÛûÿþüþõ*Ïã ø7ùûÃõóï­ý$üþ% þñóÖçÿ#îýê1Ïî©ù!óíô!ðÕÑí!òí .ñÔÐù-Þ ðÿßçÆ). ßýóîîå  ßñÂû(øû ÛÜÆëëüþöÞ×úò ÿÝóôç ùÿïîð+é÷óâÿù÷éóæ% ò!Ô÷óÙþ÷ì/#ýóóöâ¦ìçë& î ÀèÚ þó ÿÑóåþì þòú ùÛöïæöýèò2ðîðú×þ?üÔóì%¥ñÛHå ïû÷ÿÎüóþïú#ªôé# ô æ ñ! Ûîô!ùòáðêýöß àþí û/ðóìÈ8 ùíúñçò÷Óûí-ú*ê ýëéæ øüÝò 9æòòðüîî ø :àö åøùþÜù Û 'úüÚòîóÝýÚ+ä÷Ôúê5±úêü.Ì%Õýòñ ø Ëî5;Áö$Úúöòþôèð5ÿ÷ùõæ!Ùð ê× %ëøÜüíå$ &Ü þøÍ ý·ø ËùöÖúÞæëþÑ KÿÚ þéðíúåþ/  òÌéùûüû8éýþÑòêóÏüùGãáKþ÷ñá $÷éúîÌëÜììMæ÷)ùâÝöüíý) ì÷òóîìéÿ(Æ0ø¶íçí"ûúÕÞîÇýü&õ(üýïèöé(ù  äüÞïðíß ù%ôöæÜøô òë Ûòñê $ûíÓíìõ! àîÛôããçúÿø" ÿûÝóðñÿëùèßò¾û  òôë ñåöÞIõÿõüÿÙó é$ùéâåèÿ#æìø îëÚå'÷ÔÔùìþ õèëõ³ÿ$ ê$ùõðóôçú÷ÿüû ùÀ7û óïðÓûå ðïï ïæìô¿'ìú%ýÿå æëø!ëáîêÞÄ  üññõôÿæ  äÕûÿ( øõøÐþùï/÷ ýãóóùÝä÷ü4 îüòçùê<õ ù  *ÖùèûÝìóøë.ü ôõÿßóæ.äùêäø òõêç8'Ç÷öóøþþüøí ï÷ëýòì üõ% îñöþýÿÙäÎþÛë'ó  ï àõúýë  ýôýãñðý &ìåðÞúÿ;õÿ úïêòÞç òÿ õûùî úÿ   ëèéÖ÷ìòó  úàèêíý ô î ïù÷þöþ  Íìé÷îþþäÿîÚèÝ  ÷þýÞøý ! ö.ùþ×ÉÔôüû õóóÜ ÷èÙö÷Þóûî! &Þòë÷#ýúñ íÍôïüí%òûðýøýü÷þ*à  *ÛÆîãíìô ¸ððó ÿýïïæîæþ ùÑüå îæ÷êBöÙñõýð ö öñð÷ ý ñ øÆïý ë#úÕLû ïèü øòäñéáüøþÿ 1 úÔ í ç ûüã1êöË÷ýö÷õéúðþ ðî:öä +òÙôüåýûïïêó&òÿÒ ýúøüÿûýþïÝ7ýúð -þÈ ôÜõñËüÿâþô5òùþýûýü ôý Õù òßý$óü×ô öçøãûïûìñçç ã ÿ ÿÝòùþòûíüÞùÿïéïüùùÿýõ üøï ê#ñúçýðîÿõ ó÷óÿõúöñ.úýè öÌêïþñèò÷÷ñþùøÿøùîóûíûû  ö õ úö÷ÿöñøÿù ÷íûøþöòëïñéÿóÿ  ëíõó÷óøùûÿó  õöøìôðú ôûü÷ãûåçéüðùø- !éþôÿÿþö  çïöö  Ùö îôûö ÷ûèëçïôüñ þþ Ì÷öù þ"Þêëîùÿí úþýçóøíðöÿ Õýúìöñ÷çôõûû ÷üúôðñ  âøõ ü÷ðåæë þ ý ú ýýôþûòôùÿûò ÿ ñõñòô  ýøûúôöÖþÿô ãùð úüêïØ ÿù üÿôüëþ ýøì þ  ïýùöïü÷ ûþùúõéøöûú úþûý ùåùõ÷üé þóùùúýôûôõþñû÷ú òðÿû íýóø÷öýü ýðó  õüÿü÷ûøü ÷þí öûôü ÿòùûüÿöÿúòüÿùþ þûÿðýûûÿþö þû÷ÿüóüó÷æôôùôüúóüúíþ ýÿöü ç öìûû ùøõòùøî  ÷ûõ÷   øýÿÛ÷þþ ýúúëùöð  é ù ÷÷üÛúþýþúðúþùê ûûßúÿóûÓøù  ÿ÷øçúööøãúùø  úüàú ÷ ýí÷è÷þþü ý öÿå û õøðëùüÿü õøãò÷ö þ  ôøäý ñþö ýøìïÿø ÿüõ òüéýþüü  öùãûüüþ õúãÿ ûÿ  øýéúûþúõ ýùôôû ñüÿ îøþ õ÷ ùñóðý ÷þú þööþõÿü õûìÿÿõóüó ùøôìøûüùþøýÿöüùøüðüùóúûþúù ýÿöýÿüýðøÿÿùÿûþýúûöÿ õüóôùý÷úúø üÿõþúýùûöúÿýöûôüþùþüöþÿôþÿþûÿüúúü÷ýÿþýøþþù þûüüúúÿûýþùüýù üþýýþûýýüþùÿûÿÿúþüüþúÿþþÿÿÿüõúúÿÿÿûûþû÷ûûþüýúþþûûýõýüþþþÿýúÿüüüþýþüüþýúüüûþÿøûùýþúøþúþ÷ûûøÿúÿùüóüüüöþû÷ þýùþùûúùú ÷ü íñýüþü ûþúôýù ôúøüùþÿüüü ýÿþ þÿñÿûüüùÿÿü÷úðÿüþüëô ôøøòÿúüþÿûþþ  ù ôûùûèùûùÿçùùùùÿõýúþôÿùûýþ ö  ôÿüôôòêòäüýùÿüùðï÷ éöú÷ æöïÿö öÿüèûâýüù÷ùþéñ!ûåðöêúãêíú åçþâöîë ç÷å÷($×ù $Òåî÷åé ýéõúùòö ¿ôßð üõ ðÿ øûþùõøóöùâõó  çýÞÕòú î Ç þö(ì2ñ&ìåòí÷  ì×üèì ñ  ñôèà Ì*öü÷  ÿñöýüüâòæñçüÖ æñÚ õíêÜññû ù ùü ó*ýýâóðàüûòúÿêúèÕììõ+ôïõúàóú ¼òâþ ù"õüÙöø*)àþ·ó æðö ßöîöþ@Û ñùà÷ïøÌ éóôÿíóàêî ÷ óú ÷ êþéý÷Ôçàùý  ó öùøåøë6 ã×í1íüÂíÞèà 0ñûÄð+ÿÿÞèÙø øê2óõó ï Å 'þíçßöþÿüþþÿüýîòíöß ÿäïèø÷ô)Áóè ý ý ÷èîß ýú ÿÕ÷êöáû â#èðýìýì ÿé"(æòéÞúõýùÊýö,àõàâùì@ ôåÿ-ëü  ëáâû *ã þúûéþíüþ'ßöÇ æô&ëåúÿØðôðý(èïôãûÿô.Õ÷òñ÷,ôóøûÿþéêó óûñýêøùü ÿÿ÷ýöþù öûå÷ù÷ ýøöêüòôó 4ô æè%¼íÞýðÿþóùùì ûøé! ?Îýçì#øÖ÷Ú û<ö çøßðñÎÿ!ø öï êûþõõüÝýûèòü å÷üú÷úûôø ø ú÷íúüß ü õþùÿàêðÜóå(,1ÚõÒöûùûëéñ 3Ú#ÿÙë ßäèëÒ ñöòáø÷øñ î. ë- ûóúúÞ÷ õéñâøÖ %þÚé" þñë"ö þýæïåàþòÿ û! ÅãÎ!ð Oþ ¯öÜ$åÜîúúèûí FÆÿ8ìè×òõóñ ëþýôÃóðíô%'à û!þäûåòùðäîÝüüú ò<ÿ÷×îß #5üèñúò öíöýøæüôü 6°ìø Ù=ýÔíéóÿ-úìÌ#ù#Ûôä  ó ý ÿ èòÍöÙÛëï 'ÿØ ý ü 8ßþïâ &¯÷ðüå í,0¼ ø½ßøNÜëøÏÒåÿú þ5üÿòøøóú3ÞÛç× & å ëèïôüÄõê"ÿûúøêù÷ÿöøó úøùõóï(Ñ íëõôú%èîÛóèåøáåú ëüÿñ(õ â íõ¹æßè*Ôûùñéüø÷ñèö5ñÐ7ìÜýþóÌÿ1ÿó þýÝ&ßîÎùòìCù F åãòÖ ,ïû ñöÛ·÷"¯?éÿ±ðüøóðîçÌ ý ëñøÙâ1æýîðØãÍâðç)ýëôðî & ú$ ñÞáØÊý ïëúìöä#â ' õññÖ þùÚèëßò &ßÞÛÕþ +øÜóëöúþäöæßø×õô$-ìùâõéúÞüýò ïýöÚ ÿ ÿµáñìò!ú òÙþúã÷Â"$!ÛúÕ)Úï Ü "ûåãý¯÷ú' !8Í ð÷ëàÖ ÿ)áþåóÁù4Öõüééñ ! ðúùìíñÃó+Õó ×ìß & Ù*ñëíûãÕôÿ' ì ÷÷ ÉïÍ) îð2Ûîóä 2ý Ô ûâøüö ÷ ú ðõòÉäÚ>Ë%óóúûñôê.*þì#íèÑðã õþãóñî,üÞ"ñöþûïß þ(ùöóãùöØü÷%Þ÷èéþð(ÿíîö#Ð â  ÐóìØêß # '¾ñëÚ óßíÿùÍùýö# à  ÷üóßî2òïðè æû£ü í ô&$ôÓùè ÆþÙ JïÐüÎÿ÷ý ÷ðøäî ½éöñ_ÖÞÿòý× ýñHËùé ùäý 2ÛéÚõó÷ï 9É÷üòìÓñø÷58÷áèóïþüý öýèýêÒýçûì?/ê õðßëÞAÖõññ÷ú  "¦úâèû&Ù  ÛõöòØÝãû!4%Åòæô á ÒõêìÝäØ 6.ÓúþüúÿõæüòÛÿÞ÷÷õ.ûÐêîíö $ÐèõËîõ þ ûåèÞöøþ öÞæèÕùùò;ëøìþÙíýîìýéÏû ÿ  ú ·ëêïû;ýüüÎíæç-ã )ùþèÚïÝ  û ¼ûç× ï ÷ WäÜûòûßÿù úåãöòþ  ûÝè×þø#þüÁáâø "ôôÝêô úýðÐôßä÷ ÷2LÂõê àêúëôú%øôèäõ÷ ï-èÞëåÿ*   ìßÜóáúú# ÒëúÑ%ì ö'ôßåîãòþ3-Èþýçýüëúýï9Ëøìú þ ý íÊøð÷þ%ùþáëâìþú÷ "ùìôòÜ ÷÷øúíáäíéÿ  øQîöîõãýì÷ûëô )òïúôöôí/Õëû×ý÷,# á5ñò¼ìÚù(ôÿì&Óòñóô2ì ôõÀöòßúü'ÿÝûôóýÒü÷ú ÷ý×òöøüêõíïèÿ2 üýÀóìæú !÷ âð)Êêðæþ ÙÐêíë ÷Áúöðûôæ÷ç   ìèîúü#Üúêùûêò  #üï'öîíäçð ô ì ÷çòô  'îîäé íîó  Eõõùêïñêèôú4ßîâùóü5ÃúÍüúùß×òÍíñå-"àìð$Æîá üâñíêßîû êóÂôæö Ö ó%Òòäêööúú Ù "ä$ô ññÌíõõ í ñåùé  àïîúßðõá  ÍËõ  ò×%÷áèïÛøÂ÷ë  ù+æøìúÍîúö(êûüòàÑîü#  àðåùéåí* ï¢ôö ú!úÿþÄìë)û!ûçôô úü(ïëþ êæîÑù ÷þúõíîÅþý þðÔöã¿þü#ëÜÎöóû öýêí©üò ö;åÿþç ø ìûéÿñâàà $ å÷øåõáë 4&ôûÎç÷ÐýàðìáßÎ!  çÿó ÿöºý ö"Ê-éïô  ûô äóéÔû@ûôþïîñõ÷ÿóçø þúèüðúâÿ ÷ àîà  + ó úÓ"æýµ! &îõïùý  õý÷ æ÷Ù*ò õçïèê×ü  ÁÚÑé üùîóöÌ ö õöìæøÙû ûüöæô÷æ  ûýÖïõÊ'  ëöêçüîá (ïéôñ÷ÚëÝ  ÷úôÚîò!þïãûëÞÖ ÷  !ìüñùîõÞøõü÷òîùô ÿÜëßöóüù " ðâßíì×  êöéÓ÷Ø&ó Üôñåûàíõì Fí!ÝüñÏùþûüðØîîáëèæîöÿ òõéàìçïüþ$ àøýöô ÿ?õþìûÞÊúíöüþCÿêöïçæ÷ ÿ ÿöúòóõ õüÕåëðùýø, áäßòôìð0µðîæ.îõðáÝçîé  Nô ë÷íÜÿóùøøôÿçþÿ  óèâøëÙ÷ùËèäêù 'ëóúù÷ñ ,ì ôðåÔàïö'øÇèãõ%Üøúåòöç õ üäëæóÒè÷0ö÷êÎåÖ 0Ñõðïçþò*ýíóåîÅçæ# ÿÊèôêûö0äÜäöü  ùéì ªô< þ îøÆÒóä3ý #à ÷ ÷×*ð ú óëÕÄùì3ù% ÚêÂç÷ ú ÿä ôóÙõ-éÚýüéú§# åýè÷¼õùáþæ2Ùõîü )ú!èùôÚèÊú ÿü-¼íîÙÿ  Óÿí$öøíÜýúîÚåü3 öô(ÊâÛÞþÿ0ü÷ïýôîþý  ùõ ðÉàãÑ7 "üÝÕáÔýöý(ýÿäóñÿ#ü ÿõ ô¢&üÿêÛëêò 2ìÎ'óæê    êêÔÖèðü- "éåééñïß úþþñøùæ ñ%ð«üã+ ò óîëßñòå  úÞÚñÚ   ýÕÕäèè÷ò- íëÛïäíí ì èýööõüâ& üõóÖÔ/Õ$ý ïòÕÜõò2$öþêêóïùÊäÓïçõú"'øÙéíñùÿùüë  àîäñóåóÝ ö õù $ÀçàÙêò!÷óóÝíé$ÿ ßÛîÞóýÚõçãïïâ Õñùîñýöý@âûêÕýý (ëôûñç÷ì"ßÿ)â ýéäüý  ô  íãàûåæî÷üäêðêýõòúø:æõððñèåÿæöèö ý óö òüäéüüðö ÿ-òçìÐûùû -æóÆæïøò %æóÞññáüö2ìùìõíè ý" 9Çüõú þë ýâéêïùõAïüéâùþ#þ  ÙñôÕæè #ñðåßùîô åûöòãîó ü+ìúýî"ýòóáüÚòöþ8úòÞèêíú$  ñéêÿêòùþ% ã÷óâùñíüÿ ì ùôÙøñð / !Úùõú ôáûúÔññáüý !üññíìë÷ù Éôîîîö" ýîíäÚùñ #úó óØåðù÷%úóûóÿõùñÿÖëãÏ þ&ûÍõíÄ äèèÜù + Òë²ðÿ ÷!àìÅöíõõ þëóõøð÷øÿÖêÍýûöÔ Ðàîÿ ö)ð÷ìáõúý üæ&¸æì þú ûÐÛÒùþ õûï ô÷ôäõúÿÒîÇ,ÿÿé Íäêß )î8°ðë# û óÀéìàñ ýûÈèäÛ î'ÿ ë ûòùèýí Èãæ '#û ÷ûñéóÛîíúù Ãöýê  öøüÍùõï$ ø ö ÕäáÕë1   öüìöãü û÷Òú÷÷=/øÿùûòñþÐâòì ùóá÷ìøð& ìûöú×ûùò ÿûÿ æãöÒñå ü î# ú èõùìðòöçòåö:&ñôãüåã æ #îúûùñ ùõöûæöñïÿÉâíäíýE  æùöûðòßÿöÕþòÿúIóýûíèäìîÎ ðüÚ ðø  ýï÷÷Æø î ûýéØûçìë  &í òþÿ×ÿïì ÔâØôö 5õøÔîð×÷"ñ4 ÿ0Çìùóûù1å îòÿíÞàðú ÿ/ºöõñêñå,Óûù ÿì÷Üõøê ºîã %$ û×òóñ úÿãî'Éùîü#ç ì òðîØøüüî*ù¹ëØô ýú)Ûüú+ äúã"èïÓùñ  åÜÓÿõøø óï )úéõÿù & ù&ö åëéùúí.ûû &ðóÎ Õàôêö-ùûþ÷+ìÿèÿûú÷óúèñ ëÚèÝóõ ïö÷Ýÿþó÷þù 'û! ìýûÿóÿõùúùôÙâîÎùùô ú*ù#þÿþìéëëãçÑü ÷ççôò$"ïÿÒë ù ØÑáèáâó  øôùÖ#ù  øþïâ ýõìýèçÌìÞÙíé("õý þàë ÿ ïù Îóçêêà &öúèþøèÿçíËØÓÜ÷"/ë òÔöäø½éêýò ë ýÔýÖðõÞÏêñø ìðõÕ # íôòÉÓöÝèõÜ)ôÖ #þöÕòÿý"4ÐõìýáìÑçøü þ ÿõ÷îü!Þ ùùî÷ÿ÷ ÷÷þÓáÄûõø/Ôñ,ùöú ôæþõÉååðö/Èíìæðëÿ Ô(ñï&·ÿëûãÝçþç! ïóÒçëéþ øùüÿãü) Ø ÷ÉôñéÞ ÷ò ú íïéþüñ÷ñíÜùì ÷ëéÖòùì  7" ù÷ÝáéÌÿõ ÿöüÙôöÿþ ñ)þ× çôÑùöøî÷çñðîöþ÷ ' ïøéðÜèÏæðíðõÿ+&ÿûðïçîÚôúæòõøëÿã üúï êöö ýûçõôéþö  ýíïíûéõùùÿ "ù ÿùãæÚØÚÖãéü÷ù ûþ. øùñÛåàÓÕÞëçíôýÿê' ûððîðï÷ùøüúùíúçõ +ùìÖÞØäâìõî %ùèèäæúßàÕ øúõýýÿ÷ ÿ  éñãñý ñõíáååüþ üæóæíåî÷ ø  ûøõÚàÑ×êÜ÷ÿóòúñ  éòë ñæùîéÜù   &æêçÚûêò ó   ãÙÜÛßàåêôøõ  õòéèïØÞßáöôùüÿ   õéçÖÃÏáðòì # üñæåêÕîó ùýí àëì÷ïú" û   îÿðÏëëåò÷õôÈúòýü øýýøíôìì÷ãæÛý âûûèþøñðæñô    Õüâ  ú  ÷òÝ÷ÙÞÏéëòü  *$2,  ñçÝßÛØÑÛâäåÝù3!0 üéëÒïèïø  ýòíùö÷åìýÔûÿñüåò÷ ÷ïøö ò ÿÇëèøìúúèÿù ÿþúôýÿõîâÍúþ ÷àôøìø"ôúö !íúøýáÿüôÿþö ì (ý ã"ôÇÛéÛ  ý÷çþîöî úðñùõ ýìîðìûü ó ú÷ðñçé¼÷ßèòö@) 6%3ýîÞâØÉòÑæÒ)íý ú  ÿ'þü ÿûùûøûþööÿÿÿ  û ìöïøö%÷ýôõûÕÉôËá÷å ("( òüüÞåë'´õ ýö üûôßðêøéõæî ðëßèåéâ÷õÛ þçóþØ ò&"ø$ þôßÙÆØøðæñ óü   ûôîéûéäîøúù í  ÿ ùúçâÓäÛÐúèö ñ <$& ôùÌÉØäúáõõþ ùû÷òüôþ!ð ôøýûõüõûôòùÛ ýè  þøêóÍÛáÔóö÷  )! ùðëÙæ¹éìüõ$  ðüèßæîá Ýþÿ þñüöìñö øóíÛÞØÃõëöñýü !% ìèÙñáðÖÿ ú óíðâíí÷úüæ" üüùò÷úü ÿùÿûõåãÞãÚèíÿ  $("  ÚïâìËçíßéøùûüÿ ãëðÕìññïýøì  þóô"ýøãìè÷îõýûüùûôüþ ïúíÞöíóùø . öóìëÔÝáðþô  ûúàêãîóàò! øõ÷Öæèýð $ò#éñùÏöïæúôÖÿû  çñùí ÿòãìçíãüúÿîúôýæô  '& ýúçÙÚØßÅêêòõ()5+%üùíîîÕýàãÞèõú&%%úðøææòêõÿûóõÿúýþ ùúúßöõçúìóðòööüü ú !6ÿ÷ïõòñùëúðêüîÿ ÷àãíèãòôûä ÷ü ÚÿêóØõù þ ýíþõÙùþàôïîû /.)ë÷ïêþéý±ðãêñ $ôûã÷þíôþ õÿñùí×øúõû þòíéÒíèôÔøôýù )%# ýçâìàòêÜÈéßíæ ûóú÷áåü  ÿçþôôñÙøòø ùñò0 üøêõëæçÛü # )ÿ÷æóïìëèöØÿ!+ ûòùøÖÞéôÞîîôé û   Ùÿþ úí %Ìîìöïùðøþ÷þó ð+ø áñöÞÖÚÀàïþ-ò""âÿóòñêëùþúýáúùõìñü ï &ð ôÞþôü ûûÿñóïûçííó($'% ÿôíþìùýÊÜÍÿ /öõýñüúÿú ïíîóýýüó þ ùðïð" àù÷úþñýöúùîþñ9õ* ÿûåýûó øÇäØþï(  õúÙ÷öæû ïþøøøûñêåÉ!/÷ùþóýùùòðèÞõ ø   -õ îþöùñîäÝëðý  #èøöòÖëèôÚðÜûùúúùýú  õéûöûòéçÚïïúôøïÚâàÚ÷ðý÷ñôþù)ü 6þðïø õàæßõûìüøïÿõôüñèþ,ú þïêæèðô÷þòÿü öÿö ÷õÛ÷òÿýõýñõúîý  ùøöüûõùûìý  #üýúòõóñì÷ýý üûþüû öíøôðåôöô ûðñÔáãé þ ûüìÛêéÍããîì þüùúôìôÉèñä ü íîæôöûÿäóôÿë-ÿùäþîçîøðü(ãà Ëßäæ &ôõ ýû÷ûúíýþôúþÿØñöïÿò4ê÷ðø ÿñâíëÿ !æõ÷ü &øþõùûúöýýðúðÐ ü# úøçø× õ úøþþóúþàõõëýÿ ëýþ ÿßÞÝßïø(üý%ÿúÿúôöù÷èìïð÷ý þÿý  'ðëëâñÅÝÒ÷ýûíùýðòçÖüåïûïæùì÷ö ÿúøè û ÜåÙÛù   Ùóÿìôýÿü" ÿøðíèý÷é êüøóöëÐôç   ëûÿõöîêý þÿôýûó ÿÿòøúÿïþ öõðôìáüíöÿø ëôùÿ!  ððçöëêììäëïÚ ÿIâ ý ÿôëíäëòôñúøú(ä ÿóÿöý# òôéüÚñüæ ú ñýþôôÝ÷ êôãôÿÿñ÷øÿõ þúÿëíÝáðñ" þí  õßõãþûãþð  ôúõòøðîÿî"õ  ÿ ÿ Üüø÷ òñð ýøçöó úë     ÿ÷øïòñîúïòõöÿ ø ÷ öæîâÛöÿþòîë÷  ,ûýæäôöñÿíùûõñüôïúÿ + ÿ÷üçûöýûåôêýùúûüô þÿóîóöñ ûþ÷èð óûóððñûêùù ý ÿïþû þÿð   ÷øéèîäøúóû÷ýøþîíûó$õûýû÷åûîÿ çøçæîØèôô ûäì !  þøûöÛíîÜûý þùùïòö'ÿà üýûèíØóú ô úïðñÚ þëôÜóöð!ø (" ÖéÉöÑöíöþøêòòüû îóúð×øùô ÿ àøìú÷ùß÷ê# óöíä ýé¿ö + Ù íôïîûê*öõ×ùë ýÿûìþúæýáÿü(óúéþó!éúêé îäõ!þ½îëø# Ùâ ÿæóìê*óñ$íñéÃüæ-û×ûüü ÜõÛ$åþûôÛüûíþùõ1 çïüþöäÖ÷æÿüÝ ì(ûè þ!þùùí ÖôÅöýçûñíÞö$þýâüûïøæãðéûå"ùý÷ýùê÷ìæèæóþ "Þøñó õþðþéÿöñÿððåýå IôÝíô(ùÔþõö÷ äüüûúð úø çöä ÿïûÿúÿ÷õÙúìîó úþÿ  þüÔèéâüÿíþâüòüùéû óúöí ó êñóçúûþçøïùó õü÷ëööüîë øþûúõ úûäÿ  ÷öåÝåæ $þüîø÷ûæò#ùû÷þõ ÷ÿû öîóù÷ýû þýø ÷û  ûþñôüõùùú÷ø÷ïôüèêûìÿ öüÿ óÿ í ñþôòèïðó  ööòþñ ÿ ÷ïéØù ÿ ë  ëþÿæþöß øøýîÿÙúðêû ö ï Þòòðóùàûûüùìðüë öòýòí ýûÅ õÿÿ÷ëùÿ ñùß òê$ #øùòóûøëðóè(ìçßöÇ)ù ÿõü.í öóøÜäïþ øþóìøöê÷øó  ë"øïúèï å÷áî÷ëìòÙÿíúóöóïýç÷õõÿó ù Óð*×å õûâþþ5ñÝéõøüù ð-þÿ(½ùè ûùóüûÿé û÷ ìôî ×÷ùÆ(üäØ ýúàû úûïûÍøüîüç òøþýúúî ý ÿëøÏïÿùÜñ îïýÛüý ÿöù åýñþýüöÿÀþþ#òþûøø íüøùþí ÷ ôý âúöì ûïïÒ ü'÷ ò ùÿýôø÷ $êÿüØõùïûüéùûòô ó  û5üâúùúôÞýëýöÌöòø0ùñ÷6ý ùèý/ïý ¸ ï.æôÊ$âýÚó ø ÿö/âû¾2èýçÕùõÖÿåÿî' èóýôç(þðßýóûé "ûùìýÞ;ïýòüñùûéýýúýøæúî÷ÿýþ÷æøé  ï õ÷õñïðîöðìðýïóü ðþ(Ò ÿ, ä øøöÞüòýüôùäûúðüûÿ  ÷  ë  æìØæðóüöÿëþõÿ ýò¹ðæô"öÉôûù öùù-æë ÿüø$ãóÁü ãÿýäéÛóëýþí/ñÿøçëðýñé% úæò ïàéíçæôñ$) ï½óø ÷â!úöÉë¾:ö ðD ÈôõëóØ;öö-ÿÞýüôõÌüýýæÞØ ÿôæø÷õûÝ ú$Ü÷òñöýò6ðÝ ã÷×üý÷( òÞêÒëóÇ7üâþÝöû%û éòü*ü Î þCÔòõÅùãùÑþô%øâ 2 åöÚðÞ#æ÷òî÷îëð*ûûâ üÞÿö$ûÅüìýÊ)þ ÐûöñÔü<ðí ÛùòðþîóìÝçùòøð×ø èþñ1èß ýÙüùúÿü ó óüú üíÅíÐ0ýþÐÚú÷Éîó(ùã#*¾þñ÷ö !ê¼ÚÔ(  Ø í(þÞãôãðíîÕ$þ äôë üØ % Ô áï õ¼õâ Ç#èÝDÎ -å ö ÷Îýí ïøâîý'ò ë  êÿñøäýöúãÿ ëêçþï Áø-Öýòø"2ñè  ÎÎñôåáñòüù,ýõàüòùú 4Á1èÜøàKÇû×ýØî ã8úñùúëíëá&æ÷Äëë ëýOÖóIá äóüôýÏýõõöÿÖöÚ* *ëå ýJñ îøõJ×ìߤêõÿêê2Ãøò %ÎìÍ þåýâòôé@ãüÅõ0üß/ëôúùâðïëîñÿö#îë ñ+"µõÝ&ÿÙøêõó  éþûú ñýù!èí# õ鹨ŠûÑý'ùóúù îõüßûÿ ùÿð ÛéûèÕø  øÍÑñ÷AÚùòâûöüÿþì ûü.öíåàÑ"ÿøùêò Îéúóøø Ü óåÃáßÜùü÷÷ þ$ ðúëÔø1Ùûß ñ Ùû 5þõÑ ù Üîæýñÿöüñ½÷ú ïÿ  &ý  õðòÌæäñíüí ø÷éñ4ñýéýö÷Íÿ  ó&ÄãÒêõé% øüýî ñöàüøì ìãúü#üöòáñý"Ò éô îæöðõÎø íÿ (øÜõîÓüöý êéî ß ÷ ýÿýü #Óøúûòüú 'æòÛëÒÿø î û* øý÷øèô÷ýí÷øßñôñÈ(+"éôêåþðððúøÓüøýàøÝJÓÿêáí Ýüðß ìëêõ*ãùÆ.#ëâ Õûúëû ôþ äôô»ó-Û ²éß Ìäìùéòìøã1öüèòîúãî #ïüõ(ü áøóÜòßþ 6÷øßü(ûûõßñòßö ê+çõóò é ,¾ôïïÐõõó>þßâö÷á  ÖóÓö÷ûü ÷ëë ûòõ" ñ ÝHûÚùø éöùæÏ .ô íÛ üïüî ö#áï Ðìòü BäÿÜÚéÚü 5ýúñ%îøÕõþ÷ þêøÝï $óÿûüãòìÃñÞïøð&ÚáòÿýÙ+ëá ÷öÉøÝ)êûûæ#øÿÍÿôùòýþùìæú ë*Àäòÿ ï(Úõà Ö ú.ðôòëúó#ó×õ­) øMÿñø &àúóéö#êÿúå+øîéìË5÷Û9ïüÚùö éþô;àúòæ 6óøü &ü öÙ7þÛãëæ-âèñÿ'áôûùçþñõ(ïÞBüôùÀ ÷1óãùó â÷ý.èòðõòG üõÜìþõÓüß,×øä,þòòåùÓù 1Ø èöùëúêõÄëGîþùéóìèñýôï òûñî ø0öüãÜååúëþòíûñ÷üÊûáúÿû*òàâÞæëþñú+ü àìÜ õöë0Àýû ôüï Úõöþû üñüêþû(Ü Õ ØÞû#ØüçääóÖ!$ üûæþþ/óð Ëêê×ðóöüûúúôîñòôí/ùðóôÚûó&ëýóùöáü÷&Ñùîê,Þ0åçîîúý)ýä÷ð&ôì ùýéíüûí÷ï )åíßîÜäò ;ýôùþÞüøðÿÝðêøõ(íñÙ÷ûðîõ & ïÉüô$úÿðéþþ,Þ÷ò Ëôë  !ýùÕçëü=õ+Äñ èñüñ,ÿëíüÇþ âÌîÜüýÝQõôúìù0ÝÕáéò÷ Ö#ÿõáø÷)ö ü ý%âø÷ú:øÚðìéðæ   üë÷þþ!áøö$ñìß·ó ú (ãçëü ëíõøáþöøõüòá3óøÞèÿ-óóù"/ùæøÔôã àðßþßõ ÿ ö ÷ïíýü Ñæ¡ ø÷7ýàïèñûý÷ÞûòËú÷ù2ïò ïû×ööïïÐúÍïáå%óïùû  .Ø(øúô öùÀ&Ï×íÿüü Îü û õûÂ÷ÔÖúöOòíýÙþöÝ ýøøöøððùï;ç #ã ´ ëìùù÷åFÀþ*àç&ûÖôöî Õ%ìûê*ïýöýç)èÿÔ øÌóÍ óçé;ÿ Ý ô" ßæàñÎìé$0 Ýìçèî ü ìõã<ÒúØ  ñå&òúææö â ß ×ûí÷Þæõðöûù þ ú# þÖþô ïÌ õéôÉôé0÷$ñä$êìõôìÏãî× KÊ8ýßåôæñüóìòîù÷çö ÷íò.üÏîî!ñ óýÃûçýöàý ûöüï* ë!÷ºïçþúÒ÷ì äõÙôýî+ú Å  û!âËÜ÷ÿø  æúïýêþ ë ú*òúÜÔ þÿýåýüñöãñô$éôóý, öÕîÕß÷èôô=ôöÃü* ê úÏóôýùú ñüÈõýòèÕó6Ûÿð  õÝøô íø êúÞ/ãõþëý"ýßòüõãûá4 -¿üýúùöóÊõ1ûï ò@,¿þÓ;ïú Öýüþöëñè,ÿüÝCÔêð×)ü ÞøôÿÛ-ÿü °öø îûþü-ÿåúîõæïä×üü×)ëé åèâûòö ü ü´+ìðÿ #ù÷?æìöÒôúÿøÿúòÿõôõÊ LöùíùøìöçÿþúûÜúú4ñõíùïÝóÿûþþôÿæùüý ÷!ð'Ò%æñÔüýæõôÚûò3îþùúôõ ö êðÒéõøû ýûêâïþðÿå úõâòõõ-# ìêîàöù$ðìü#÷÷!õ íñýÍõôþ êí÷ñ" ÷ Áù÷Þâößþþøðôêêù â-Ü ùõî¿ûÿü:1ÿÖ9ãðÁç+þüðîüòæôòê ü Þ   ò÷óòíþÑ0Àò ëü¶óëý'¾÷éþïëûîÿ÷ûüÏôé2ó ¾ùå0þÙõùãýó+6Ñâ áù ÿõøðùúõòý%ñæÿºþÜïîÞ ãü.õöòûùó ÅýÓüÿÿãüü  ïÿ òóì÷öù8º üæ  ÝÙüð# Úì+éÿýþýøâùþ  1óóçúÕïö ù   ñôÜÿã<ø æýðßîééöó ö  øûúóîæôáî÷Üýíõþÿ ÿýúñß õø!óûþþÿ Ü÷òÖõèêþüÒýíûò +ù üóôääóô"ü ïÚíÊ 5ÂùÿòÜûê÷ü× þ$ûÝ Úþõ ÌñÕþÕøïùõà( ø ÏÖáà+ÿ$ÒþóÊ 5øÛÿùò÷óô Òùùû ã 6ðå!ÿ÷Ýòäîôý+öõæÔýô üçðÝþé ÷ ÷ Ù &üæø øûûñøøâûñ òêéþé òãéáðýû ùïöñë! öþðöÔàýä÷ôùõ ô ÿðøîõ á(ùýÙäãý -çåçÞôó÷ô  ùüøð/Ñþûý åûðë çòâíùî1 ýõõòØþã äüóöù îùøùÿì çüüãáûóûîîÜ÷öý  åô× ñ ÿÿüðìü öèý )Þ) ûüòöãùýþþëóåõòðïû øÞýøøøÿõ*èþúñýö þþù  ï÷ÿò÷ýú þôàîï÷ùðþäöùïí ýý éöòóþùôúüôûéëòø  ÿï úòçûôæîøúîÿê  í áïúìîöò÷ù÷ úú  ëþ èú öýõßÞíÖú þùäùùø þüà öñõêýû ûÿéô÷êöù÷#  øÿÿýîúæüþúøêöôõé ëýû îüëëïóðùþ þ÷ ÿÿâ ñ ùûôùøèô ý ÿÛþó÷  ïñóìøýí êùó ü÷ üø  Û ÷ éüùú ööïöñôþÿ ó þìùüàûòø÷÷ûýøÿø ÿ   óîó æøëçûøñø  ûüþüøæèÿñëùüéîÿëõòýùú÷ñ òÿö÷ùñé öé.ëõéïúó% ýíú îóùüêíáïüöîàIïòó úðêðâýøí& ÿîõ õýêÚ&æõ×ÿ ïôúõäïùçþý!ýøüïõ÷öþýíõû÷þíúöïñòûüúÜõòüùúÕ þ ûðÞýè÷áéðù  êìù úôñìä ÿþûúýþýùýûüýæøúùþ õûøúôþ ýøùúû÷ÿüïüûÿþÿò÷öùùûøþúòþùý úëûìðìò  þÿþþ øúäòôúþö ÿú÷ÿòþþþùõúþÿý  û ùûøõøæêúü÷ü  ûü÷ùÿ ÷þ úÒöýõüÿúüíó÷ùöÿ   ýìøñøô÷÷  ÿúÿÿùüùúöûêÿüòôúîú üùðíúðÿØû õüüÿøþø ù óþ ýÿüöøûóóùòùíùüû øùèõþöû  þêýù ôøùùû þñ÷ñ÷ëöýþñûÿ ÿ÷ìñõç÷ÿ ùõÿóþ ùøòüùÿêüûüùþÿõþúûþû üëûòðô÷úÿþÿ÷üû þ þ üöûüÿø ÿùþÿþìñðêöÿðù ÿúßþ)ì ÿàøí ðõóýýþúÚ úèÿûûÍô ôõïÿû îñîöõ üìÿããøñ% òïòãÿïêþûýõ öõ ÷ùÛëñèäñïä "öÿ óúóîüÔ ò#ôúäý õøüÛúöïØõäÿñ÷,äÿ åÿ9óþð òþýóñóçÝëõïñ ú  ú îüÎïåþ 'ß ìíç×ëæéìèÑöõ5 øü/Î þ ûñûËåæåê íùóèöòùá Ü2çêíøüäø÷-. Í5ÚåÒþ ýðãîÓïôú÷ëø üú ýÖ øàöùüþà4-ôçóêùÓðòç  ì(øý1âøïïòðìýû<âï÷ö -ùß ù8Äûôòñúô÷þ÷õûòêþï é ßþ þ øðîÝñèçûÿ û î÷ùçáðõÚúö%ý+ îúýùðîíÊêÞáðîùÿüþñøÿùù ýòøùôå ÷òäß æóæâýôøý å ô÷ï)Ò  !ëðíûùîý±1ïýÙôô(äøçùðÿÿóÕíóÿàñú6ñåþÿ Üüë&ðÿë ì" øüóØ×ç ûïíÛùöôæíîå÷Úû-  ö å ê øþ ÷ ÆÛÑÄþõËÞYó #î ùóòðèùõÜúê÷þÎü0ç öïæõý í í )ïñãúðÛüëíñõéæðùòãöúùþ*ú øÿçôêò.òîãÿà Þúà àËî×àÛÿõæýûüø ô äõùéê÷ÿØ-)ü óþíÕ8ÃíïÙø ï2íõÞúòýÒ ôé ëöýÿæøïñø÷¹   ù$îùõæüÖæì÷óòàûø ôûüïøÿëîõ (Ì þ ÿ õ éùò¾ðå ÿ'ì-ùòóóàÔêâÕêáçþþ"æ è îìû $þ ê ÿØçÿñÝóóçäëîéûì@þüC î,àéòñãõûøõõò ùûûüëöõ "ç/÷óÓöëþâ÷Ëú óü óòäðìïéëö öýð  þùõÿõø(ùÝñïÜ÷ÑäçÝûÙèÖò +  õ úIñöì $ßýåóùÙèöôÜòæ  :+÷èíèïÃøûøöÍþëóÿúð)ñù÷è!÷ô òõ#ï# ùÎÕÊîÚâß øíùýÄú÷ÿÿþùÿÊöööüæùï %ý ë(ü óøß"ñý!Ü÷à ïôä÷öþêýâúÔæìñù + ùúûîõöïðýî%úþò"ý ûìðâðÐÕðØòåóòúß *ú *øõÿíøûðûþ  %üüù  ýþêØÞÞ ÷ô Ýû÷ðÚçûíæüöûïôöôêÿ !7ù)ú ûõ÷ÔòéêíéììÞöþ×ûä!ëý þ"åîìêéñøóõü×úñü ôüöýÿçè'î.êòûü ó÷ùê×ÑòÚóñúÿ"ë÷Óúü î  ý=üÍúíø åð/$Ïü*é÷ûê¼ãúäóþñ Ôøë"ú çó&ùåþîùøïú %!Aú Ú êÐûÜ+çïå¿ õ÷ñÿÿþò Ûáøà/íúêÚó(óüðþ$ ôøì*ûö""î ÿÿÿüð ßîìÜÜÆüôô× üçûýúúìîõÔùÿ ç+<ùô) åÿ ãñøù ú&&ûþêôÅåýøàëÎËüÞàõÝ !û  ð# Øø#ò6óôðé àíÈïé+çõãøåãÔæüGä ü·÷óíôü Îúóï "Ü 6ðÐ*þöÝðÛîç;¸òÒçóü#Öåõ õèøüþû÷ûöñ ù,ï ôÖ+î÷ý­9îýâ  ûéýö  ÉÙÝ÷'Íï÷0óþâäõð÷ ç"í ûòå&Ï!÷öØ÷ß Ò î9õû ù,áøÓèìØúýÆ÷Ûüá%Üû÷ ßþì Kòæ$÷ÙêÔú žèÝâä úÑûí 0 1­ðüêîó øõþéôã$ .åóÞ )öñ çýÃêö8ëßûüê ýôòýôëóÊøòþê/ çóû   ø úùóìú%îÕÖæøEú õèñÙæú÷Þþé Ýãàçýä û7ðÞî,ó÷×çþþ ýýõûø  Çüâ;êíþçÞÖìûû ÷üìýïéðý 3øøåõ ý ì &à .ë ùìëëÏùñëæíµ ôñ6 'Ûåñëû ýãéìûøý  è÷ü îãõèú (í  þõûøàõû×÷ öÿÞþòÔêåñä  ù÷þ ßÿ ïü +é ÷û þíëúÿòÆäÈüÿ÷ÕòÚÿ  8ùïùôäþéùêýç ôõâþùýõõåüü÷3Åý'ûâøêêì ýû ôöõõ ÿòó ÿçúôòò÷Éóæ ø÷øúúêòÝôöííî÷ùøø 0öù÷Ù&åñ þîðÔ ü  ý'ïøë*àâÎáå;Ùòõàïóóéøù$  ó ! ÿñ÷ê óùýî÷ÿ ÷üûü÷ÿâê÷üøüøù1æûÙõ ýûóñòôðùúøéûä ! :Ýö óúïÞïòëÜðâ þúûëüâ éÿò þ Ùùú ùýÿ !÷ó& õ ô øØ æøèÝðöõüúúïéàáèèûêûù  ù óóøæ ùôïÔù  ú0óæðî&÷çÝ õ ½óìðóñûìôð(ûý Ï*óûü ñ   #üâæù ùô÷)ëúåòþÎöÜúöüù÷ú÷óî÷Øûû ð è? öû ø÷þüóå íÆîòèýû.üþà îýôôáèöäæòíÿÿåí ò$ÿýåþ  ÿü âýìæñ ¹ìÝÿûôÖäâýýö ïúñ#õ ìèçýòüí'  ùóçõþø÷ììÛãü´õóÿ ÿþðõøý úþýüü÷þ î õ þùãùðò÷ÿòñô¾ôíéøÞäñ»õ÷ þ  üüë (âë  Àüôú$ÙïøìýâøùÚôã(ñÛò ö&Õðäñ  (   øøäþîÿþÚ úîûô Úóøòäïíõì:ïþæ÷*åõïýþü÷ú èþ  ø7ùôôä)æòñàöù éóØìöúêÿï÷òóýì õ  ØöÕøûÚ  & þã!ÙýýóþùøÖ ëëÜÛïÉ÷îö÷êöòñõû)ê, û4úý÷÷ôûèùò-õÿ ñýõºûöíý äùéýóþáþþï îóýí" ÿ øó"åõ þ ý6×ÿõþýõßæáð¹ððø Ï þø÷úÙõï%öøé.è2)ý ¹öòþëôóëïó÷ Ðûôüý ý .ïáöêïóáÿù1Ñþùé òÙ"õû ÷ÿùûòôõôþúâìCÚóëÓûô êóßòúñ#×þ ï&*Úìû äøäùþÕ ÷3ú Ú ôøáöïñõáÖþë*àúóû 3øûòCþºõëóöý ù í úúå *òÕÿóïýåòå Òãéõô *þóúþûæ Ý  ü1àüäôýßËûòÍñÏ úýøõÿÿ÷ô÷é(Úüà-öùéü% ýãú'úöôüýÿí ùÿèî ëøåñþÐñäýóññùü ôÿõ óúØ1 ÿæöù!öîÚýö+ û üîäïðËãÞ"êéôØýØ<À  íûÞ&üé÷×Aü  )úÿøêÚ÷ùîüöôÓÒì ö áì åîìõÞõøáýü í $ðêEþ ï,Úõîü øìèâã÷ò Öõ ØñîÿÖæóùï "þï ì*ó÷Óü ÿ êï!úÕ!ýÜÛöæå÷àÛþïèëÞ þø ûìüù öûÿ ý÷ñóö û òÿÈîäþèìÔÓõç öü ðö  ÿéîóúþ þý ÿð÷úÿüôêù×ùóûýþæèáîÚëöí þ+ÿ ùó÷ý úøúì.ñáþ ÿáÿðÿúúöïÿõìýÕ÷ÿÿúîáöðùð+ý ïöû òþýïþýù è Úîï÷ÝÜççýôäøóñüúû+× íöôþ# ððTþ2þÖðë óîÉòöíáýáøõÍ÷ùùÿîËùòÿ%àøéðå Ú*ôî  #ÿìÙòùìûð%ë÷Ëý úúôýÿíûÀþñþú Ôý ÷! ö.ûõÞòï ûù Óñö(ÿ  ÷ÙâóìòûùéúúÙíõ 1Ú ïöÎ ûöò âø  7ýÚýýìá"þëêþö*ô  úßñíçøÓ ¶ùé ú çôìòìþ( $"ã" þçÊ÷ðíß÷ôõ×øó .þ ó ùíõíéúöùãü ÷+ çôü àðýð % ÿùö÷õà æïììíìýûñóûï áñøïþ ú ÿè÷ï   ûüûø Ýïøþî÷ñÿîòÎþÿ÷óùÛ (ð ãñóðü ðàñ+ü ø $ìûýýëõ# Ò"áÿñõúó ÿíïã"ðëÙÿóðãûú ûûþÊ ,ó ðöåèýâÿú Øþï(÷ùýì- ëÿøÜûíïÍöé!ùõõöï"ï *ÿüöûüú ã!  ,íñûõõïëíÞüóÍé÷åAùöûýýåþïÿóÛ ìú üÛóã !éø.ò÷ô ûàîêûéþçô Ûðüåøðâëèë÷òüúûþûû&"5&+Âýá ýýòòç>éýýü  ÜùüóòêÐ öÿàå±%(ú ô<úýÞ(û ÷ ú ýó2ÅóëäùøÚðà÷òðÿôòêöÉûùíýè) ñ  òüÑÿ úþÿ ÿø ýÙøöòÒöÝùûØüî"ùü÷ÿÖîÔü öò ûö)ùü öúæîõæ*éá 6îëõÈïè!×úùüÿôþôý÷úéòíêíçñ;ÿ Ø7ööõ èÿüöøøû.Çóß ìÿÇ×ìéÜòùò  1 "úþöñûôþûê÷ì òéÿ ýô% ðõ÷ëîôñöÿò+÷åê Ëø6ýüÙ÷ñÿù éüú òð*! ùöæöüö3íÔòóøêôäó ,ÝðëÿöàöúîßóÞ# ÷"ìôôÚâÞíôø2üÞá ÿ3îØúôÖäîðóÿîõòöõ Çüé ø( àÿþçüóøøíï÷ êÚè ø ñûïåÝ= ýýùóûæõïûîíßóñýÿù.ö ñðãð÷ðíúô"äüùòÿ!òÿìëüìîÖñê$ " ùù üúìäá óåú3øþÑñØçèüùÿç ö"ëþûú$Ùïêú(ëÿÇüþ< öâôñ"éóóúÄ ò ×éù)* üðöÐêðÿûêûñý Ú&íý& Ùü÷éàúÕ# å *ýÕýï!æö³íûºÿ ÷õëü à6ð Ö0 øëþúÓùüï¼öÛ1 ò "öúôÿðÔêÔ ùÉý&þüú#Þùîùñ÷é  ò & ÿ  èâÚãéûçõçôÐøõýñýÿïòôôòé&-íý üõÿÛè×ôùùûÿ ý þ&õÏý îâüýÚþüô ÷ß÷äôùÿ øõ& ðæÿø$Ôÿþëÿÿ õôðåàÝÝòï àù ûðéûïö ô1ðþùõú ü ÿàùÌüö ûÔùÍ7âúÏ þ õåóð ýõèòýø=òô+àýûüù÷Øëëé Ãøò%Ýò ûßé÷ê ö 'ä ù÷öôûÀ öæñÒ.÷  ÿ ü ÜñäñèÔïÄô!óâóûôÿú"ûõã$ ÿö" %Ò ýêîïÿ.×øö%ÿø»ó Úùù  ´ú ÑôÄ=ä  òûëùþðõ6ô î ÖïKîôé þîòçåûüêé òê ÙüõèûúüÕäÃñþø  ý-äÞýæ þ¿þïîð÷ú÷Ýÿúÿ÷íøã ìþ 0ìõþ úþ÷Ýø×èý òý -Úñ)îüëðøëçàÚÌõøè ù ô2 ë ðóèÿ4Ýÿ5ôùýÒýüóðñÎøéûçèâíçÞ û$ûÿü9ýøýëõ"ùÕ#ü êý $ï 3Ïü÷á=êÛ 2âäðÑ-òùæà÷í öæ&àøá ýùØýùóÕ ò ó'êÿ!õðá÷ùðîþÚ Æÿã'ýçöêéçîçòúð æ÷î!#÷þþ Ýõñôúýóûç þ ó ùõ%úìüæìÿóûþíÿÿýùõøÛÿú àüì ø   þ,ÜùèÿðþÙÚÙ øáíÓùø ý  ''öÖ÷ô òæøÃ%ÿôõó þÞøóðêþÔ#ùáíGþåõ5ôÞ ÷ÇïåÃæáøÞñ +ñ ô(!0áä<òò#óþèýßüøîáôÚØ ï:öïÏÛ øìÿ÷ÿüê (ò  ' úö'ßòéÛòÿÖöë#ÿïïõ$ !öÿóñøÁôìø*÷ Ïþ1Ôõôê!úôöýìûé$ì÷   ÷ù þØñÿõþýúÿö÷æùøûþë  û ( íýÿ ÿ ýûû  ìúúü áó÷ úóÿúô÷üéÿ Dâÿã #¶ôëäþßîÜê ôüØ Ô=ïö ô>ØûìäûÂð'óÿøìþôÿÕøöøþàö ç ÿÜ.òþêëóàêÑýûì êî  Ûü0øÜÿèõè ôîðá÷õ ý!Þò3àóðä%öùèõõ è$ ÷ý% íóîëýðùõôûûèðì üýüûþð ÿ þóøüýúúíÿùÿüç ýî   üü÷üñòþåïíçõìóöàô   ý ð  þÙöêäöçç Ûçðì ëûù   "Øýìøëûùóåñßúûìøí÷ûò * å ÿÿöÿùÄúëýùõ ìÿöøü íúïíý  öùüýêêõùöýîûîöòõú÷ù óÿûúü÷  èøîøéëöþ öÿùðþùû öæýæï õàÚêþÀûæý ýýô ïï âÿøýøóúñ÷÷öüùøýñøøöþÿÿþÿ ! üùéïìðï÷ûòúèü÷øûÿóñ$ø ÷üôòøõúÜôùëøûæÿñþöòíüç$û ó û ÿè ëòÔ÷óíÙöç ûæ ýèþï  ûó÷) ç ü ôíæòèñóïú Üøô  ñúàýöúõöîûñôóåðùúò úëû ÿ úþ ûÿðùãûþøëúöÚïóôýóûûó  ð-ôÿûÿ ÿ ÷úóìøáðòøúð÷ öýó û öÿúðùôìàìíìüþôõóè  ÿ ø ýÿëìíîíóðùñõòãñæ+ú ý ú û ýþòð âþüæíæÚùûùÙÿÿó  û"óðüõÛòàüù Ñøìøòóúï  ÷  üöùÿ øä÷ûïïðúðõùûðÿôþÿþç  øóúóòÙïïÜúöýøøê÷ÿö ë üÿ þþèýùüÙ ôëýðô÷ý÷ ý!õþëüúòòìôôØúúüûîþéùé  ò÷òâ&àüùýþñùñ íüÿû ðþøù üûô÷÷úöøòïýöòööõúüôîôÿþòþü ý û ýÿýöþùýû÷êýïðúþêöòõþõüþ û þ ÿ ùü þÿÝûñòüñüÿü÷þý  ý ýØòîâèêíõûú ü÷ïá ôÙ   ýþüüúôöçêîçòîþýûûýùøþÿ þðóöþìüÿôùÿö ø ãø þõ ÿíùÿúøñþ÷óâêòòéøøþûû% óù÷üûæûí ÿúôóïÿ ûá ÿü ú úÿÿäùúòþäþ÷ úþÚóøüøüüí1 ùýý õ ñýøùüñøùÛ ÷ôúÿé õ õõêüä÷õðóì ñ÷Ï÷üöìýû!ðú  ÿÓÿôíòÅþ íÞüõñèðþùäúô# üíëÿ ðýò÷øøôôùêéíõüþ  / ç öóðáðíðððìëêúù÷Ø  øô  ÿ÷êü ïùïäçøòðòÒ4îû  ÿùúú.äôïûï æö ú ÕøõðòÏüâ÷ûí  ì ÿñ3ðÇ+ðïíçíÿôïéôÑ1Þ÷Ú õåý +  ÿöû Ë õ8áë óßãêôúðüù ðþð ô õãý ôíÜçüñõýùïûþöÐÿ÷&ûýùôý/ö  ýÿø÷éþàóñúÞêèòüñæüî* )ïüüì ÐúùéÑùæ Ì üõùþîøô)øá %Ýõ#þö÷õüðåòöãþöëôåýû û û åùÌíçóûêýÿûëøÁúðþíñøòÿ9ÿü$ýðÿ(ëüêûèâÕíÞóûÿÿý ù æì  Úøÿýê ýõØðÕ ÿýù÷íúæ þùûãÿ  9 ûèïëæõîçîÐ ó÷àïøìõöFíêôòø )#6éýúýôÿÙê Üðßëöôøëøï   åø ó ýÜðÞùíòê   éõöÿîûó ÿ,îûÿÿ ûÿõûþýóóùóûððïüú  ÿ ÷ ûù÷ìîíóåìî÷ûöýý íúóôõÿòÿþûö óòùüõþÒ ÷þúùýí þúø øîýÞðÿ ò õ÷é  ÞñØ êõîî )ïûôâüô òÙüÿ  þúýõçô÷àüøè  ø õ ôßòöïãìõýùýùó áøôëø÷ þú ý ùýýòýúËüùÚ ôúýìæóç è÷ùýúú éýîùÛ ô( üßúû ò Ïøé ÿ·øïèîõ óúûóê ýÿùä$ä,üó ýþû÷ þíé÷æ áúôý%Øþ÷øúðøúöóýüçëû÷ !ô ×%þéùãÿÛßÿ ì #Ùü&íóñöþï)óýúáàñù üóêÝåæúõþó ù ë öøüãþ  øéâû÷øüöñúæûúþ2ëÿòøôìöïõóî÷Þíê Õ  þÿ  ðû  õâ ôòïøØëåæõâèîö7!ûý õ'ú ÏÖðüõÿðôá"   ùïûòôøöãÿÜçÙðóûòÿ ýÙòâ(Ñïá  û/þ ÷  èñôðßêö÷üÛüôÿý ñëðãþéõø#þðúîè÷ ò éÿýù÷õ ýë  þ÷ßôåþãïùñùÿ  Ýý äìïØòýñóí&úþõï7ãòÇ äì ß)ðê éëÚùþþòüÿìÎñÞòíøî  û&÷ûýïøí ñëÿêóòùéÜÞäÞôÿ)Ýîïúäö*Øîè÷î÷ä å  è öÿÚûØöïë÷öüôþúðëùñ çú÷ æõìçGùÿ ù   ùøþýæëøö÷ùÖïêëôõûüÿéûýûñüüåý  3úúøñèûéêô÷î êõùý ùëîö×ùúõþüáùôúøä ïùò÷ú4#  þþôöîíôßæôêöãüø÷ýåëÖüûòòüø ü þ÷ûë   ùðü õúìæñýÖ ðøýïý/ ýõæýòóæô÷ïáîÒòûò öÿïòóõñùûü ù þü÷øìÚöÖ$ *öûòÜêþÎû÷ïùü ïýø õôûõþíöûúú üóõæèæáòñ ëÿóü÷øõùè ÿå ýèö'ë-ùø÷õó ÿðöÕûúîïóëñòéêçú û Êþ=Îÿû òøìùþø ôùú  üöí úðØßÓþ,å ùüøî Üñíúõü¼ü  'ýýûö÷$ø ä! Úþï Ûûëí÷íçêóèïÚ"èúç !öý'òðû Õôàúð ï* ×òè ùñö (ýõ!ñåìðôí òñèì÷ò ëïþ ñ þæôñú /õýþôýèíòÒ5êüøæøì"û Üôêùèìðó+ ýñòÙè÷ýç òýó ùøöøüûüñ òõ îèïÅóï Ò÷å æêîÍ û  òü æëù# "ä#ú÷ úûêëéêôÏÿ;ÈýüàõöúîüïöúòÚíáëï'ö=ùí ê Ü4ü éá 8ÙäûýðþõÿÚöéÒîÛ ñõÚþýìüÿý   ÿýö   õééöíõæòÇ÷ûøöÿøøöóñô   ô öùù÷õí # è ùæþ ùîüÿÒýü'ÝõÊñÔÿëíððÚú÷ þ þá3 ü( ñô óôÕ$ùò)ýÞýõ÷ñêéÏÜÙ ßãöÇ ÿúØñüñ  æùèë#ÿÜíýýó÷õ óîøØØñ üðüÐüûßçùù ëïý "â á ÿ õ ú ýÜìÇù÷ùüé ô÷ÒåÚ.îõðòòúð ô    ûú +üýÿõðÕúñýÜý÷ì÷ùç*ûíàôçðõèÌ ßü- ý.2ÿ ÿþá.¸í Ó%*ûéßÚì Ðûö íßò ïøØ åñèãçè $ü Ø ê÷ ö$ )üëèý#¼ íýü #éþøðØàËêþíâòüð°&úßõöüõë%ó  !ÿðõëôþ üëóêüÔö÷ úäðüòèøÜëõ) æ÷Ø÷ Ûó Ú  1àäèÔò$ïú¾ ÷Íû%Ûöÿõýãû÷  Ö /êûù #ä÷à÷õË öñ' Ìëñß êòíØþï$Öøïö-æûèó÷Üøï ýÿ#! - Ý ðñÞÛÞ÷¹ùñòá ö Ùöí öêðÐô'×þ+  ÿÿíüýìüû ú ô$öý äûù÷Ôóî'Åþíñýúôõüô÷øèÿö!! ô ö& øéêÿ ç ÿÿìÿðÉíèíûêúô)Øøøãúôûúëüÿ øú! òïë ÷ûþíñ ìãó÷æ÷ôþ êäàñç ÐüÞ êÿ( ñýòÿ÷  ÷   ûøóèûáâ éÿî ýþãâþæïíèØåÜüÿ& ô  åîìýàÒ üûýÐûçÕ Óóäü ñÝóÜ!åöé ðïýëü þ,ú$äý÷öøýü ÞüôþöúÜßýãßöéþøÔø÷ùúòúü ðÿÛòùó"&ú1þüëýó ÿøùøéþõßüýËñíúüðäýþÔõð ý   ÷úùúòþü! ûýüüØðûýìúè þþÐîüïóúá øôíýû ôý è í óõÿûúûñçÝìëñôùòþüøðêëèëú û õ   òóÔô íÿõõöïôòóûèÿñçÃïüþÿ ù÷þøü øóûýóüü ÷óñÞøôú øòýñÿüþûìßäÝâñø ýð  ûÿ üÿ  ùöùÜåîÝóôöôùá îñùÞöîþû÷çùøü#  ôûø  ÷üï ò÷æûöóòíõ÷ñàöø æ÷òçúòî ý þÿü   óý ÿ   óüÿìÿöýàêæäòîäöòõðôçúú    ÷ùý  ûù ûû×ÿñíïûíÍöëñúÝûóëúñïþýÿûè ÿåôóó   ûñ÷ ÷÷éìëùùäööîûöùùùäõ÷þú ü  õÿý úý÷ñôáùóûëåéîêñð íþüö øûÿÿÿ ûôùÿ÷ÿû õüúúõöòðéëñóòïôñ÷ö    ÿþÿüýíþþ   øíüõõûýÿÿüäóõóàöïþúïþ÷ùõýò  ý ýõúìöííüâ øöýêòòéÿöôîòðù þû üÿøöüÿö ÿ åø÷òüûïýþÿùùõïóûý÷úûõ øú ýþüýö   úýÿþúÿýõþÿ õúêýöÿîïñëöìíêàñöû     û óúýù ûûù÷ùú÷õöööúüùïøîü  øÿýóüþõý  ÿþý ÿýúøúòôõýûíúôúûé÷ åòîùÿð÷îõþÿý  üÿÿÿ ÿüüÿþùÿûöùüôúù øöõñùøóúüñí÷Ýòùÿ ( ï  ø÷  þûáúÿâßòò÷ñüðöþñûðèßòùë$Ø  òûðþ úíß*ÿ øÿòãõâêíõ×îòà÷òöùì úýØäáç % úñ éòßó #æúóÞò%þú¸õåôù"úüù÷øñâ óâí'û ÿ Ü öÜýúëÝ 9ÿøüïúÙûü øøý&¡õö%ãôòïúöî ½ðç$øû$/¡è õûëñýÜ"òñæí-ëüüÉüìðüúðø4÷úáï0ë %¹ü ðñ¨÷ ï  òü÷èÙòã ÿïäáÖØééæ üõ"'öû$Òðëö, ïïçäïïÑöï üøÞ÷üìõï÷ò#Òÿëïúåÿ1èòèìüà.õýêòóóü&à úÙüù#2þé÷Ý»Þí33Åò$êú þü÷ýû ð ÿûëíåßô í,(ùâÓõë- ÖùÆúôöúäÉÕéÿ (éøäàùÛ÷5ü  ûÿàÍùíÙ!û5Äøøäð ÍÿÞYåúô÷ûü ôüèï /»öóõýõîØôê  ßíèôñðö û ÷Õëïï ôÎÿã-øòò à0øøõøùïàðß î÷ã åÞ ôìççá$4 #êüøÜçø×-ñè¸8ÿÜòðàú% )´ ö þþô ùú çõÈ÷ÿÄêêÜ*é ÿÿÕóçù'î Ú 4óúýòÿô07êý÷ùýê üú)Õë óäßõõçýóë áûúç & % æ"ÙéñÕùöýþøïÿÿ(ìüçùñ  û  "õÖùùÐ"ûø ÅýëûÓþúöúý Õûæâñÿì% 0Þø  ê<üðîÓ,ôöêùñöŸ.çð#ã ñû÷ùÝ.þ$åöáçÝ$ûæÝÿøý äõÓ øé øïòñýã÷9Ò÷æ&úþ úûø,¸ úå&ïö$ÒþòÙôóòîýæ7KÉüýãòúêé ø%ùöõË áùó ÷èïöíöÜ÷$Øëÿñô$øýíöý ;òòó0,¨ö×úù î÷ïàçèüë  "ïæî.ï¼ôé øþ Þ Û)Å ó(ïö#¿Ã/î íë ûæéøÜÑþá5 #ðçî É5êêãÿî þòôûéèùØSÞþþ  Ù÷½LÙæ ýûûä0÷ÙüÚàåý  ýÆùðýø*úúõíøùíðïòõöÞýþù éûõóóò/Ï íè "ê4ê%ñ Ç3ðàñýðÞòïç?â*Òì  îêñ8äÿKÈý%úôûíöâ'æâÏïíéýó#óýàüëÿüþ óþ ßòûßù!Î ÿ òöâüÿàÿûöå ô þÿÿàùúçôñùýóúèóõýÙýû ðùøï ü üøóúíë úæóæñþõßûýÚþí!ñü ô ã úåëëîû#áôüöÞ åïò'óþ  ÷Báýôú)Øÿò%øùáö ŵ$êÞ $ïùûù/Ë, Üýó@Ôïÿ%÷èöïóù Ûõõõôñ åñ ùüûù÷ùùþ-Ûú ßõöû#éõóïûü ëýø øñýö  þÙõïõòþÿüþÙü ãÿñð&ý ê&çòþõÿø÷÷ñáñô ÿèÿ üõ.îåö ÿï æ ôýù è÷õú ÷øøáÿâ;Üöéüüöüíþì é,ûïçÿîþ æ ãÐòøúêùü äù1Èõþþ÷ úCø îîåáïôó+ãöõñéöîîøúú ðûÿ ÿ çèÛäôê5 àõòíýà   ýóýøè ùðýúàîõìüÿ üóôË æç úý Þ òþòýöóßìñûò ú-ïþô  õÜíùåîúúäöïåòüðú  ýùòðùóùñ  ÿëþóüÿèýýêÿýóçïóÛ ýú ö öòù ïÿüòüþñîþüðûæåîóÿëè ý÷ìüãûâ øó&åþùõøóôçúèöþùöþÚù  òôÔëè÷çõ òùîñó   )þ ôþìøýõ  ýðèä×áõ÷ÿëõÿíüþö ÿ  ýûñóø êöû!÷úÜöéñÕ   òûôüã òýûôìîèøö  íçè÷ñ  ôíÿö   çþíýûíûüðý éõí÷ù÷ ùü ÿõö ÿ ù÷ûéòôêýùøé óþúõûûÿþû èðíêúûõþûÿùõþõüîúïÿúæýý é %ðþõÿûßöëîÿíÕïðóü ý ÿü øüùêôçûûøøöñþéùúþõ ûûöþøûû÷ýïûüô ÿùìøôúõü   ÿøøýùüþúüüóùû÷ÿþÿþþ þ  ÿüúÿõúöýýýûùúúúûþ  ùÿüüÿýööïõôøùöùðùúüþ÷üøúýùý üüÿóüüùþøùöþùþó÷ëòÿ þþý ÿýõõêöõò÷éÿÿ û +ýñèçêëñüóý $ýôüôõúôýúýððïÿ  ÷ýþü  þþ ùäîáÜõæüôèüþ* ý"õùøëôù ü÷öøÝçéíõùþõì úð þúþàùý éæùôïûóýÔüê êøöýööñøéóÿçøóö þúóïóì î öýíïÞäðí)õ úðûî ö þ¸ìÅýàô ñÜÅô÷ûûÿÿùþ%%÷ þ ÿúìúêéÖãêùóõëåîãêéþúÙ  å÷åõøö ð&ø ôõûÖþ û÷üûöÍ /ü&þýóýâáýâÙÚÖËÞÁæÕ(ýúí  ù ù ÝúýüïûçþÙ õííóýøíðåïóöíúí Üðòð ûûð Ü÷ö,2ý ëøèèîÌìâíïæì úýçû õýë (ÿúò)úååíÚ+òú ýâúï9íß Ý(õï,ÎëçÇîëóÌïçïüüäï" íL$ï(üÁöóíóòçêñ ùíüïùøøþÕïã.Ý ýÖýî óïê÷óö úÕ -û"ñ ëêêÞÛâí÷ëüç úÜõêý Î ù4 ò ÷æííÜ÷öãÛ $/åõÿüü ÿûö ÿóðàÿîâýÓÀâúîà ß5 &ëþý.ûí=õ æóèîëþïø¾þîÝûåàíôöâ ûÿóñ # A é-îðÿÞáäÆîÙÔÕìÜïß!'  ý ý¸ ÷'ÇÝÔàçÝÿïøËæïôè ÿ5E $)îõJíæô°ÞÝ÷ü óþ ûüáÿÿ& ù×ôâì úÐ×ÿ è!î úûÿêúðøñæâïóè$%Ä'%èãÑæùäÿúòçë÷ÿ$ùÿéóúûð"îÇíóïAÝ÷!ýÿà þ ó÷ðûçùù0úÞ% !Üñö øæ ÿíöñöÝ" ÈØÞÙýüô,óë$ì& þéçú÷øþç÷Å#åã-µûïøòôçíÿúóíÑ îÿ÷îøóÕéãßøéßú *Ø.îù!ãú÷àÿú 6Ä ÷&ùó 8ÕôúòðþÚèöööâû û ùõñ "$ üôøÚêããñýÃýÿð÷( ù/õóýöøõõßó å ü< õ ÿï&Áîíë+àéëõñÿäø*ä þ  þüçïÚ $íûñêæäêBíÞôýúÜõ0øîõöîîó÷ôÚø%Èýûîîÿäçä.ßñ×åøêÇàÀý÷ñÓ %,éäýøîìúïþõØ1îôâÚ .É'ìéPÞóñ!-èÿô ý åôïäñðî ýþøõ üäßÝöú ;:ì+ (ô% òîòÞûûßïæÇ å¿ÿì&Þóùþ× Úùê1íÊÓÝÞ#ÿ ßöô'åïLçùÌ ÿ/ ÿñ æÜáïñÿíôùøóûþÿÙóúÿ " 3ý! óïøÚþ ôõöèùïø ÷äÞÙôô&ìÿ  7æüëäòþñ &áûäÔèè ëúúï  þáüúîôÞ/äßÑôåêøòú ýã/ø ê"  ÿþúí0ÙòêÏíÿøûèôëÞòñÿñþ5Þ+ûøôñ&Ôú8Úõýîüù ûÿë ü÷òæëå Þÿ #÷ßEë ! ûÓ@»æÚ÷üù÷ööüìý üýÒüïõíý/ýúòðû¸#÷ñÖ þB ïðåïòý þéùïàäã 3 2ùúìÿúøêëåÝßí( û   öíìÉ%Üû¶!ó$òéëùÌï ®þü öûúéü âßýøÿ ö "ýâ¯ôè/·öæ5û ÷øûûãæûãÑïº1  $÷îÐôíøÚé ð ïù÷ùØ öáÞÿ÷ ëúê  ÿþøûßûûü øíòóöáãØþßîóï  ý"   Þ"óï ÷ìéýôúèúïùèðõåüùü )ç ð úýßîýîøþôþô åþùùòáÞåÕùî 5," Þýëíãä×*÷ûÝø"çüýäòñÕìåúôúþ øòïé÷Öüø íîåç÷çÿ¿,ù$ ûøéñÿÒà·âéúÿøú   ï&ÿÜùúþûñìèñÕìÈ üðñ"1þøüùÝïÙù¼ øë-Ö÷ñý êùþ üÿòøçóë×çíëòüýÀüöøöãúöÿý ìRêï  ó-#Éõ ïùÜ üúþ¸úóûÿçø áúÝûö"ò ð8 ! ãèÏÿõõóîöèãéËòùè  ?ù)ÆùóêÈ!þ/Û÷ ú¸úäÔâóÕ üúÿ   éúòöü2òüú ÚôòÞåàîòüÝþôàò 2Ð, è"õñ æëèòôùù'ßôî!,×ÿðå#Öûöø Ê'íâûþ$ÛíÌú í ý Àúè"þ   ù Êüøõóçô-ô ûðùÛûÜïýÚ2Ùöß "îøÚò å+ùãùü þþèåâËñïë2 æûA÷0 ó÷Ûòä ùþÚîâöííùÞåçþ$á "ôûéïþû &üäüÿøÏÿ äÿþêàïÖ4×úßÒýþ õþ$ûøèöéÿ ß FÔüóåöðôöô÷Ê é ×  ùÜõäñðÚèõñççþñDéÝò ùõùò ëû ûãÝÅ(þ Ãù2ãõéâüéõóâôýþóö þ'úóãéþ òüÎñ÷/ #ì $ùõâêßÞúñåú´(ý,Öçò    ùùÒûú.ÚëñìAùüñèôÀ $ÿñ3ñøòèê 6äîðâòàüÛ*ðÑÿÿù òèîøóÞô<éøïññã  ?üÈ(üûô¼ëáÓèÔÐæÜûç 0 éüù  ÓùúûüùþÉúòÐ1äýÄüøïÝüï úö ñùëòÿî çþóúßý .÷1 åæöù èçüõÒúà, úù÷éñøòþòóüÜîÊâ ö)"ÿ" ûñ÷öòñþùÛÞ éüèøþïÏíäûõûò(ýý ÿ!Ùùçÿúåööø÷üóõïò*öïñÕù-ÌõïäÞäåàðí ò ù 1áþ ûéöû÷ë÷ õ- ùöøÜáçÜòëóÿÞôü÷ô>ÕôêóíÿüÌ ÿè þ óÞûòú ùîìáãïì"¸ÿÖóÏ#ðùõ á û$ÜüúùêCýê øýøïö×úûôå÷óþ üóúáðë 'ë óóóà÷õâ ÷úêëì êë ÿ& ú ÿÿëùüýïó ýýõýöûýñååêÑéòÝ ÷ûóøø! !á%ë î  AíóÛ øâúøûçß ÕóàèÕóóí ! ãêøì*ÿæùôóßç÷àüúÿìéíÙö .öáé!ðüïõñ÷òëó÷ò¼ ûÎ÷úÂæî û 'î +øØ÷íìðé >Ö׿ó¹ãëL¶ôßþþíõëý&ö*ðÞõõ ú ùäþðï*éüûØíøÙô22ê ìõõßöüîýáõôè&ø åøý éõ3íÚ*áïõëïóÿÿþÑøëåöÇêÙ ÿ òÌ) ü $ò õøâóÝôý× +ø÷íúêôöýÿìúûòæòÜØä,ú ì þüêå÷þ÷äó:&Ñ)ùñ úïÒãâçÓ×!ñÿéì  7áûùüûó÷" üûíýÿøïøöóúåÑñû   ÿöìÝæ üÕø Øüû 8Ñ õï ³ó,ï ü6Û ôìß÷þè $+ëÜí(ôñïéê+û÷ôûüë-ÐíÈ ö ÎüÜ$ Ýþ2åõÐ.÷ ûÿÐéöÝóÜþ áøè5ä÷ ã'þøþûöôãùýÆ"úÂìýîKç Ô  ùöÚý &ã!ç ÷9¸ýí*ÿÐíÿ÷ôÚûï÷ë óúþ øðù+ñýä /ë÷íúÑéìîøú   ü ðóËýõøÃ ëïâüéø  ý$Üý"öà ø1Çôøæ$ â ðòûøññþ÷÷ "êþÇÙþþHî Ú ùøÚ ñéúøØüÿà" #éü%Òüò Þ2Ñôâïÿçöî*ü òôö%ÞðÑüòðùõðòøóõøø&  ÷ ñÿúüéì÷÷0Í(;âÿýÔîæÔõâ÷ Ñûç @çìíÿöóÉäÿ èÿÞý øøýöí$ûí1öËëÜëñÐé/ öÑþÅ,ýã òô òýÓ7îþþæúõüøÔèîàù3 îøîüíÿÐÿü êó÷ó. î ÿìÿòþüõìõ÷ïõúóíýÛóöðþÖ+ -ê ßôòîÿáæ øðôõô Þüí"ëÛÎþï#õÿ 5þ øþÎ öêæâÙïÙþó/ÉþñùÚüú ýþÿîüù ,ÑêÖ ù êëõ×ö Þ ô  û" åúúÿ Áéûó*èýÛäëÛ óÿö 6óø ãî# ¼íÏî÷ àñ!û íÿ/âùÊúÝþî !ûñ øíïÙèåôýïúöý ì;ä÷ú ÿï öþÝ(ðøëÿöþ !ãýåúíÞéü ôîúåó4íì  þçÿú ñþÇ òòôûòï)øï øåøðãóî úú4ÒúLñ÷ê ý áæÓÞÿñÐñï   × ÷ç úøØíöëûøîòòå÷Ðøòýæ # íúÙöï  )÷ ùåøôÛêåá$äïã øüÝ,âîúüÌ ýþûöþøÛÿ÷ôÞðÞú!Ö) ëçõíëÞ2ùôïüíøêñ;ÎüûëúË +îô  üüòðùé óýò#åÿýê÷íêÛðáôçê ìø á  æü(ÇÿõóøþBä öþú5ìúë÷íêôñçÿðÎ3ÐéÿòÂ?ìýííýÿÿÑø #û(ÎýüÅëÏé)åïúú&ýóõýë2ô â óìÉþõ! ñíýêöûà   Üýþúüïÿàÿ ïýüâ5 ò úôóõÆñôØëÓäí Ï ,, ø üëÿíÿ ï ýúþôòóÔòÍ9ùúï òàóíòýüÿãøøæüëÎú â ,ý  âü ðòõõùåñàãÏ-   üþÛëãÛñçðýüùïùóû6&Îüôí! %Íþ øù ëûñù÷éüºããô ç êýýò  ïýðýíóèöÚ.îû  Þ:îûöäþ"ïÿÛýÝÿ&äû± î÷äÿ óîùíöó Ôü/"ÖûîýÞüí)Ùùì òüàðæÖÚÆòûú,ò ÷ ì  ùëÿýëüó ò ÷ï.Æüßõñþý àúóõ÷ôøÍíß * øôäûÛ÷ìðúðûñå óööôøûÆúòñúõ1ùáéùîîûÛÙøò%ò3ï ñ èùýüùÿÄôñè(ó÷ûÊìí êùéñþê þì)Ëòÿý üúþàßÿòë Þ3ß ôÒàäÚåöüâýõÞ$ëúþ, ûÌÖ ¿ðüî!é è  æôùñïùà µ(åâíÿý æýññùðäúä  )ðýßôû ñýùýþùêûùë ýüäýó"ûïäëÜÿòøêýïâöò#6îõûÚÞåÅîôîðö× 2 êî'éòç÷üóÛõæ ýôë8Áòá ÿþ÷÷*ô  ! ðîÓþõ þÝ4ð¨ïïýÝôóãúèÿ "ÙúùýüððÐêåìþüöÚàãòóø <÷×íùûîïóê ìðýÖýÙ:ðõþ  ñøèé ÷ ö &óýýéðìòöèðÿò%âùÓ$æ÷ûð  ö ë9ý:ßùêõ ûþöüúòö Øáôÿ4öçïâöåîäâìóêøå ÚôÏÒåöôíóõôðö & 2  âÓûâ0åðÆþõüùõúõ( äþï æîðúùü ÷ñõíò(/Åùÿú î ì ÿùüëíÊ ÷1óë÷üõ ëéæÛí×áùåò÷ý+õüB ãôíõðüþüþ ûüâìÝû÷ìâùççóéç ùõõùùä"õÿàö&þãþú ú2÷ö öå þ÷þÉîßûøúÖûóö÷ø òãúéñðð%!ý  îôÎëêúýîíÍôÞÿî1 ÿóàñßðóíúúèúé òõ üëñí,úÿßúô ðøíòþ6ØüþìóëûæáåÑäùÔîùø" +üóûãàùú/ñê 3ßæèÙåê íï÷ß ú îò#!ç õê÷ëúîï ÿîõ*  ÿçõýîúâþûøú1öëöíïû÷ö ö Ôñîïýåòâóò ü "+ õåëààòá÷õôõ ùôßåãäåú÷ô û!üóîðñèüööùî  ýýé÷òïðíòêäïôüøùøõææêïù  %øÿ øþÏýû õû!úøøóôÿñÿÍôí ìüç  áçÜÞçæà÷íÿþ 'öôùüëìôüø  þ÷ð÷Ìâå Ùòìõîùúÿéò÷ç  òÿôûéòñã÷ò÷úþ çüèûóöúêçóüëñ$( úùëëìñùþøúùçöÿè5" ûþåïâñîñÚìÿ Ê ùòý Þüöõâòô$þ÷ôåÿ õñ úþõíåèãØáèðþþ.ü Ú÷üöüýðøþþ+&&ûÛìâ ûéÚöøè$Ûû  ïñ×ýèß ÕðÖý 9 îüôíúþõþø$ áï ÿ ÀñäçöÕþöô÷ûùÿóûéø÷îûùûú'. ùýþ ÿêüöùö úü&ö ùÛêíúìþªïî#Üÿàêÿþô ÿððíêøôò 8* õ õ÷ ëøðþõúüðçüä$âüÖîïûÙôí ÿ÷ûþþåïðýçöäù(ú  ò õòñëþ÷+éõùÑí×ïðÁõîôü ùþû öúóßì ôñìõ=  þþåêìîäùáûñ'÷Ôûòó×ùñç é÷öü  àÿ"ðáò *õúþ÷íøóûøÞûõà ;æýÛóþÁëÓôää ÿöß# ÷ï; úëîÿõ'ù  îñðõÔä·æùëýîúÒýóðôúÿóõÿâ3 ÿ Dõ$ùûòþøïìú÷ëýûÖìãòç÷Üúýã ûøáõõøùÜùðùòúô  öþ5Üô(ýåýüì ä!ùâý.ÃóÝêäØâÞäç#üß/ (øüÑóïðÿí'Ûööãéúòûô  Ø÷÷ü ëöüâDåôý æôüüöÿÚ ÿÞùð ß Üú÷Ûöéùùôôò ÿïð×íÖýö÷þõ û$ úòÚôäßÄî®ÿï+ðæöý'Ñð÷J×  åö%ðááþýäÿî>üîüþ÷ôñþøìÜóãÿ¹ýþ#Èèäóõÿãôöà ß (÷Íôáõÿùàæ;òüâýùêÿýéøâ"éðÉøååò((Ùç ÿáõöß/ýëøù ü÷ù7ÿÝÿè>üÓ&ýúçùíîñ éíåûôýßøæöÒOÿæðöþúùúþå*Ø,  #ÿ #óÇæñüðäñÿîõõÐóì æþþÙÜü*÷  öÿõ,ôìþñ øâ û+èøÃõúðýÿ%#Ýèíæßìõÿ÷ûúê÷íé ÷ýü! àþööììúéòèñöâÎ×ó þæ9ð ï ìóêøéìæ òûýýá$ ýù  ÿÿüøìýïæùÙÝÑûú  ûüòøõÿÖû óÿ þù  øûøÝóè Õ9 íöøûñþûíôììÏÕäãèÿáõ þ ñ ôîóó òòõÄøôíÒïöÿþú-þáúù Öûðñ ! õÚóùæõàýÙÂãòæüÜÿ"ïÑ.âý$ å ðïõøæëýë !ÿ Ô!ÿø1þÊøç ðøïþÄÙáÿèÉ úø+àññý÷ÿÔø ó& íûô÷ûðþÒõ÷ô Þé"òóòçéÜíúíåúù "Óì56ý#òøýåþùõýþÿíÿñô ðåúìçúêñÅ&ó ! ãïáõò óù)Æüûî   òôûï -øñ,þö-ñçüìßãæÜåÚáõîô !Ø4Ùòåå!ùõ Ú!ëë# ó$àëãÔùñùñúì÷ ôþ ãúäûííóðçâ*ûîâ #öê÷è$ü  )Æ  ÷öýõÛäÞé%ã êÿú)û ôìéðñèíéæññýð 4 Ïöäÿùü ì!% ýßéÐïýÕëã åøýëýð5ùú å÷ãÿï þõü&éüöüìùõäÇ òñôýÜìïïåÿøô " ööêýüçê×üôûù*úìöòÿøûöü úòóð û ÙÖæÔñùÒþéüù0ÿñû  áúõó!) ýã ýïýçóûî#ûÐÿñå÷ý îðçáçç *¬ òþôùõüøþ#òì #ÚöÐ"ÕäîÓùî&÷ÿÀ ïæ>Ö ÿ4 ñç ëÐóýñ"êýýý ûûýÜøá åóÆDæéìÂü$ñèçõê øøñÆ ùü ÈB òü+Þùùé ùùêö+É÷ó0ü æÚìòÜò®þúÞüäùÿöùEñðþ ò ã'ÿèå0úÝ× íâëóûá Ûáú!ôä î0ëúòë'üíåüô &äöÚýý*Þý7 é  áúéìòåäöñðôÿ¾ ÷3áõìÜëè øï   ó俨óÕò2éùñöÿú ùÜ$õôûýñ Èö÷ û Õë õïôùô  ú ÿø*æð0ûÕçÏÿñö#Èø2öøù Éøøõùààøíõìå þñåòý%úù5Ûûÿ'ùùòïéìöãüöß-×ñ×þ.ý ûäÿúëýÿ ðüûø ôóþþò$ ïìøó>÷óÙéçèìòÚðäöõü#Ó ûÿïûþ ÷êþèßéðô Üýûÿîóä ôôèôêëôúóå4îþÞóý&  ööööúêüúûþýçþ çä ûôð ôêÔâÝççòùýððé+%ï2 Þûþëúó $ýèòØÜæÿðÿ'¹  ð #Öùïêþôí öñûìé &Ì5úþùþûçð÷ÿ  ðÜþð ðôªýêþùõÑðúâìôòù $øýÙ"4& üúÕæðØüúø)áÿè"ñùë.ú Ýìñüôãÿ  õè þúøûüöþü ëéñÀýô ø øöñüé þ ö "ëà5ûáéöþú%§ïïùþû Ô æôúüÿ !òûóÿ ñùîõøïéðëë Ø þý )úõ÷ôóýèÑõì+Ü-ÿ+ Ëùï÷ñÌô ÌìïÆ&ö5ýì úåõæ×ï úéüÊ]Íúú þëýòú/÷ûùµóýüé!Êâëðäá& õëöõØ ÿõê-ãóèýÿö Ùööë 9ë÷)è×þýÿôêúöåáô-ñ ç'öòùñ úÿèûþ ùîýôí ñó÷ì  ÿüÒFÂéçîþØûæ"çôÐô+èæ#ÿóÛ ûû  þÛáèÿ â÷òýåíüõ  ïùò0âúæ&ÿÿô òëßæù ûÿ Êþ íÑ ïþ±þë ÿíóäôè áôøúý/ßúüýð-Ùúòúûøóôì ÷Ð ÿé ò Á,òÇíüÅûõù #  ù)÷üöèù÷âþ7ßñõä èþ÷ýûïç ð1üøð Ñ?÷Ìðóí#îùú êÏëÿ×)"ÿüî ßøîòùøü à÷ùöùüûÿúòêïñýûúõÛ÷ïò,ê ø øõéöÑ×þöùïç ýöÿë+ïäâ&Ð ÿ ÿûôü¿üþìøËêöï % ÜïÝþ ö%'ìõÿá*óøÅúèß÷ ¸öÐþ  ý%ôê øÿêë÷ ò0 ýà ò¶âç!í ð4èúè>öæ÷,ðôóüÄ÷ê÷Ò ôûóÿô óûÙ&ñïñþû 1äàÜéó÷$â 3 ú ©óöíïÍú÷üõøùÿ üéÿç' !¦î7êè8Ý-ÛæíÉþÙò#ñÿëï üÄ +ü þ! úß÷ÜöóõúùÝúî#Ïõ ýÄî?ì ê. úò*ÝìíÚùò ýöúþ ÏâÂ)ë÷ø ý1 Ýÿÿ  ýïøÔñïé ë÷ÕÙø úõ 3.1í ùüòòôõýòÿë!ÅúÍJÝüÒýûÞö ðòù .ùÚùÜú$Ýùìøåù Ûÿù* øó2ñ÷éôäãüúýïó¿ ùú+Ø  ÷íýÖüë ÿ &!çõãÿñáÛ÷úùûè ý4è÷ Ôôþöé-äèÁîô×,  ú îýýç í ÿïÞìÛÿÚèÜ êÿë# &û ôôòå÷üç)÷úÿ !Ð#ðýüóæüýüá ëñÚ õø%îöì1©ðÑ(úèâûòòù ÷÷÷ô  çÔú #ú ÝøñþñÜ  îùóÜó $ÊòÙÿñë²ùÝ<ñûß(ù åøôû üî-úä"ü÷/úîñðèøÀëøëÜë ò âê úÀÿûîêðåÿÿ ù! îý þ'÷Åü ÒùÎEãøçêýøÙ öÄö÷  ùá÷îéõÜäüàù #í úïëøÿûý%îè Û ñ8ûòàþðûçäüøëóÒðð $ óøöûæ0þ ÙñïôõùóöøÿæÿõøìþÝõÿæ÷éü öîñòæöóýú ÿôöôëå>ç    Ûìáíëî÷øûâþ ïã%+áù ýÿóèæèÕðô 3öçÿýî,øæòóõ $÷ääüäýÆöýîíöÓ&þÍþóôú ü ç   *øñí òÿòô äîëýý ë! ýëÞåãîòú áúøÚ:ãüüÿïñðìöçÞ ù *% à ò<àþþÔòæóñöÜüôõýøôô  èõòåôñü%üëúþ þ õøû% Î òäêåõø Úôñë÷'"èêÓåèä  ýþýâÿ#òúùôö÷ ôóô ðñü&!âßøïöØãçÛüüù÷õü ÛÞëæý  òû éü ûìöûòðøÛõìæáèçæûû úß*îøã×ýû ü à òÐöì ëøøäõó úô ùöþïìàÜÌüöýìóÅü"  ) û Ù,õ ºñïûýø ôõÕìëê ÿ þñùüûòÿ ï åü åæÙÝ÷üù  # ì ëæúúüìøéòðß áâûåõýû ÷ óýè  ð÷Æõö ÿúî íýðüÒéèëùú ûþþ÷óþôýä ìüþûýüõýõü à #åìãâûúóõòøïþùéôîë×îðëìðßÿøõîñö-#ç) íõóîõû ô#úííß÷øÿíøîçüàóë'ìýè óóúóýðÿÿûý #Ò âþûûõïööûë ÝêëññòüÝ(÷ç úéïøóïôíîñéîùòÝð,0 õöðãÿîæõ'Ççâáðñöæññ÷ö 5ïýïô$ü  ýï ìñöÔøûûîúüÙþþø Øðëäüèìßüæ%àöí å!ÿ õþþøË #æóïò ý ëõöÖþýëìþöòýóøøìòìúõÓý(ó íëþ÷ î óòØûò à â×úþýè#øêæúåâðê÷ëÿ !êõêPè ð2 ÷÷ñæóõ ï æ!õöõÑþ&óãìèåï æûð, õïø õô&èóïEÜüìïæ !ï ä öôû åú¹÷÷äóßúñóÚ êNÏïã íûäö(ýâ..  #ýî ýé÷õÒîïøöú ñøóøÑ Þùæýöôë? ÷ üòÿÿ'ùú Òþø$éùÑûúõ#îýíú ìýèòûæáÝ÷øäýòòóöý/2ø  øýùÕø÷í*óã!ý Üð÷í ç ÿööçß ùúòðüÿ ÙôüÝæõûü,$<Øý ü öÉñÿóú,âñáê÷ô øåõ ø.Ûðñøÿ åòêóë öþþþù =+÷ óÙðò×ëúß ñ üëïîò÷×-"ëá  éôûÿäïðïñÏôIñ  þã üõ÷äùþ õúáØæõçðëø éâ ïû  ó÷þø÷ð3î ïõñþÚîèüóîõêéóíúù  Þîúóþôí$ ùúî$òÿùýóùþøüüüôÑúñ # á ø$óöÊ(áóõôûæú ÿúåááóõóôF ð ëòìùçü÷üøÞûû÷+÷ Ý Ø÷øÙ;Ì áùà÷ÿ îõñïòúÙôBíü ÷ýëôôÝñòü ÜôðùÖóôý  ïöõüæïì î í, üûýÿáòüâèííëúóÒúó #ïüÿÝ ÿ òþöíé (ðîúþõ÷÷÷ù  õ   ùñåüúâïêÝôßôùì áñò    õööÿ$ ! ý÷ÿòôîè éóçùÞçÈôçÒðâ  ÿêûíü îì$ú èüîøôî×Þ ûýýüõ æ øéóïÛùåæùòðùõý÷ÿ  )Ñä ÿ ïùðòøèóÌôþêôõúù é(ßóþúöûÿúý  ýþðööó òþÊ#  û àôõôÞìÕúèðôòøø  Îÿíô÷õü$î! ü %ïû ýðÝôúôö óÚíëÕñïì-òèý÷øä ö'ãø ùý ø !ô "åõôõêîóïýøäôêóøöòóüþãþÞAÜïöèñøç öþóñÿûúÿôýóúÿè ýöÚëåò û óïùäíòðñó  òù  þ÷óâù÷úîýõúùõïØíîì ÿöþýÿûü-ÿïãíâêîñîüü'ä  0ÿ üþûñü àú÷÷ýöðõöéæèø ëùöïïûáöýèúä ûûó ú  üí ;ÿ ÍüîÞéûãÞ å õ÷ÖéÓòíúÿõáûÙì òþý ýõüüÞ.îø-ÑéùìóöüÅ òó÷ôõðÿáþê;Üô÷ôÙâÒ! $ö øøóøÛ, ú +êÝÌþãúóÓæÐñûúõÿÿ ñûëùúôÛ÷5 ú ßõòýõþôûÿÚõé+ð/é÷ó÷ø¹ïßÖï÷ ùúïû÷ õ2Â&ìûûôýôøóÒóéáúîÆøàìöüÂø<»û ü  åûöìö>íøä4û !öîôÿõÚîíÝììÿâô â Îî ßòÎü)»þû $ö  ñøàï÷òê 7×ùÜ ðíí'èóìòöîþ÷ÝïÎõñùýÚþæ7 ëø:ö(úýìþáÞûùêýé1ÅþÜûâæÿí<Ñ ðû %Üûä îðñÎü;öìûÿ+Ûü<  öååõãåñë ü¼ð(ÝðêýÆþõñ  íýñññþÑ+&ùó,È -Ûõóóþëøùüêôú'ðëó"ìÉýýÇöÜøþÞøúû #÷ ôîÿÞ<ú àìÛý#%ãþëî÷øïæóìÓ ÎþÞ0øþÑ ø3û÷ "ýþþþûèì?ôúßúõïú)ôòÙýîÿòðöëÿð øûùí>È÷)üì÷Êÿõæêô÷ !í'8÷ûâüîÝçìîßâûþ1åûßûðö$þüúúðöúõ;àß #÷ôð!üüñæ ñòÕêéèü ãâö/øïçûðôòçüÝôî ,Õç!òëþõýæ ì(ì'ÿÛèþìÚ îÔîéñ ýùà ùþðùä ø ëüì ß%î ÚèöõÌñýý ììÛàØÝ ú óõ+,ð0ôÄòõ×ô×ãþæíóýö úýçð Åÿúúõ@ìõüëóñûôíÒþùôéÝ&þ å ô÷ù;úú äñéôúüõþøóõõØô.ž ù ò  åþìïçëù ö ëóìòþöÙøÜ5òô ÷ ûüþðõöîþ »óüþðú ò.üòèö+ÖÿøñÙûß ööÉñ1 õëó÷ò Ùõåøù÷é(øû ëõè.ÓêîÈöä÷ø%äØüè ÞïÆ $ýí7óøÞÿ)ûæóîòööýèôå%üúñ* èçÿãøæúýëèç÷ÿøæö¼"  ç ÿìõçç÷1ïóùü0üá ùÿÞô÷ÏçÞø úäß %úåøíæ ã'ûüö%ïóþðõòúøøÙôñúüñ! þý!/Ý  ãðïìöëùýøüÙçîÓöúýáÿÝþó$ÿ ýùùõ ý òõøúýñçõ6ÍèÄéìðöÿýûö õ$ ÿîøÙ$ø æß3Ü ú,ýøþûòêðííü òñõêê ï ×2îúìû Ý×,÷çýôïÿî.òìõó$úá (ùàòêþÜóð ðüíôÏÿìøçôõüúÕ  ú" ãôûáãú Þýå$óéþòõ áüöø÷ðè÷ø"Ìý ôùÞ åú÷ ô â#3Òû+ÞøóÿàïÊíòÖóõ ß ÿ Ùùÿ ýúþîóÿ0ÿ ó úÿëíëóÀôäüûñø)'÷õâöõî÷ûýõî÷þÛ úûøøõ( áöäÿñ îõöõûëüþñèô×!óïðù÷ùýûâõ÷õôÿ  *øú â÷Ü ööÝïþÿûýùÿþùðöÚ êð3 øüîØïô ôðò÷ýûûú÷ 2îç/á ó0ïûÊÿ ìøóòñ÷õýêöï÷òèëøð7éðçþ# ò÷û ë  ý &Ýñêè åÿµùóÚøØ$ ý ó,öÿôýùýóäñï íýé !ç ö5ü Îä"ôêñ èõæ  ÓãÅðÎ ùîùÿ÷ðöÑ öåþø û ðñ&øòá ý+÷û÷  øþñó÷ûùÿôõúùíéïøÒ÷ô$üö  ûÑñÊëðýÿõý ð)ñõ#óìíýöú åýóýýõýøöÙòýõþÖúùò ÷þëØþù  Ý,øþî÷ ßõáÿÿ $ßùð òíóýù ÈýÿÛðÚ ü "ï#$þìçÿîú õ,ÿøéúö éÝøôáíþ ë ÿâ-êú øæýØýð"óë 1íçýúþÿ$Íàþ öÿ øôñ÷òùèëðï.Ïãú#ý7ïëÚüúüóìõÒôù"Þõõáù°&ñÙ÷òÿÿúêøÜúüøÑùê áü7Õ÷ éùúõü ÿåúúúùèøÙäñôùáûôðùôñõïøööì'.â$1Ùÿ üþ÷ò÷Øûþüþûýÿúóâ÷ññùìæû÷%ýõ$ òýýô÷õïíùõôýõ ò  þ'ø ÿõÜÿïÿò üé÷òÜùâ"öóæçüöò  éø öûäû þ øðôùá*ÿúÙêéé÷úåûã÷àþáÛèù×èóö# &ú õëýôùøíúøýö ÿôíüè õÿûç òÜòèùé ýùåôÿûð : óø)þ÷ó÷÷ñôûûùçíáËáòöò ûøúþ Øû þ  øùûøó÷òñõõäü ×ûè,øôýûïíá÷/öûö$âë  éû ÿüýôøÑõýçùøø  ìÿñõ÷óûùöíîåúúùú úùððúà ý íøÏ%åÛãìßôýü÷ ÿ%äýÿþíãúîí öêúýùþ% ðûûÕ÷â3Íìóêéýýüýþû÷øýõö  ò  +þõòüðúñùÔðïíýäöýÀ÷Þöî äý òþçüõüþ#þöüê!àï  ó # ýñýí×ìîñþì ì ù Ûîèñûãçñîþ $úÿ ÷þô÷7õÝöïòëìÙÌ îñöôß( ëúú øÑþ÷íþë ïûùúáõ âòèî þCÕê$þÖõ øóñþçúøÿøøæúõñôòõòÎû öC û/é-öýêø÷þæùâíàüñîú ìú úÒáÞÝùýù  ú úûÜû÷åï8ì ó üûöøþûþõ äòìÕý Åûòñþô   üéúôÿø6 öùâ çíñôïäå÷êôòá÷ç õ  Úõ Ñ   ýþ èØÜáì ö÷ÿ òûøóð  åù"ö Ëö÷ñüð÷çïû   ÿÀ ô ÛÝý÷2 úúØõùèßóõîàîõööõ-Ñ ü4ù ñöðóÝõÑ !ò öØðúã×Öëè!õú " ñîæÿýÎöðõóûû.à/ô áòÝÉ  ö õñðÑâìôÝ$ý 3þûìûö îõÕùéçàüñ&  ø ÷øôàöôïû öøñéâÿðààöõ  üø ãòØéóÏ þ<íëõ5õð ÿðû÷ÿùïèêì"÷õåÿðà ÝëÜ!%í   ûøñò ýùÅ ùø íó åõÞééçüý  7ß "øÚôõÙëíÔ äï ú û! ÷úÝ äõ#îþá)Üÿá$ãóÝÿûù Î(ôôÏúöÍùèéý)ÿá (üü%ùûõïééô)Ý ü2ã Ù$òæìùýóÜúûöüýüöÿô <íýþ'íé ×õòô Ì! ÿ+îô úðøÚ ýè0÷ßëûû% ßÿéæòòØ Ú ðéÞ÷÷÷Óîï ùã þ 0óýûðÿòðäöýÙùÔ í×îíêòåìùñù óäêàõõû%øþø ìòùìÿúö×ðïíÌüÆæú'úö. ôþñçÏï  éó,âúúþèîýû öô"äÿòüüñáùµïïÖøôç ñò % üýÞ ð ïù;Òø)ï÷óïòÍý óúÛæèÿØ&ñê'øèü÷åòûã#ó×ýû*õ ôòùðþùïîíáÑýïûþö çþÿä þ ü ÷ ÿ%ýçòâôøüùþ äöú   ëãîîô÷õûôþõò âüÿý íúó    þ ûýùùÙìóÿ +øýöùýßñèåÞæàéøûõ÷ *ã  û÷û òãÙåêéöøÿúîþð  ý×õøéÿéþøòõñÿ îüüÿ ý öúõüòíôàñõýäóÕíýâøûïùÛùþö ý; ô,ü ëêÿÿïõþ×ÿêÿÓüí íóÚóüæ÷å%óõìúù8ç ÿäüóûöõáú Üùûõ#ûÈñâ Üåæù úÿåûÿ÷øúáôþòøþ 40  ûüøä æðÜõõÝé÷äîê "ôýóùøÔùóîüÿ üâûÚý÷ íôãòëóüõüýÎ÷é"Ïòßþ Ýøøðüÿê+ü   óÐööìã òü ëþóÿÿûþùÿû (¬ýðûó úüÛ÷ëõëðùÜà  !ðúûã ú÷óõòâñãïØëéí÷í ß üï  ø ðæ-ÿÿùöáóñ÷öõâõøú÷Ýû/ïê ñù×.ÉçøÞø÷ ê úûù!ïùó! ã'è 1õöùñôêôíùèâîÕ÷úéÿ êôç1Ìôðí- ó ÿâþî æêåýý3ÿ÷ &ûëçåÝâÞõö'÷ïùÏ<ôæñú úÜûÜñýú3÷ õ 9ãü 0åáòØ øï÷èæèåóñÑéàóüÛþÞ?ö ýþãá&óå <ÿúìÿõ/ðùÌîÚøß-þãé"Üòü4ÿßßþíÏþüÖì3ðüþë'#Íú ÷ùç 8Û  ýö  çëê óáïô ×Ý÷ö çóýø-íöéñÓúû × ûü7Î÷íìÿù ßñéÕôÜäóÖë"Ûì* ñ þ"ëú÷âÝøôüõþ ñ4åùùúïÚÿì Òóé ëóçìåçòãèåÿöÿý ù ó÷æ ó$ öýÎô éîýßÞúú èóû  é÷óþãòèËùAôÿ  6ßüëéñìñøû  Ìûâúôö(þîåóæèðïüýýñýøýÿùõ Õ3 ) ûøçøÝÿøþèèöþëþúøíòù÷ïÿú æø íøóúãáèî æúÖïý øýïô ßìêûëø ÍóÊôõôÏüë*ùêùßîÿ0 úöûñÁï2èö÷íáï&Éñïè4ãùüê õéåôæùØðüAäúü'ý÷ú2úïóûêçö ÿ¬ð !'ß ÿþçñÏùÿ&¿þú ëÛ*/Åòøõìâö0æûÍùã/$ó"þþ×ýÐþ øÝýøúúýãñè¾ óÞòå óýð÷ï úðï%ôî",$ òôÞüèóæö å÷÷Ë íÕãïõ Ö ýîò4'é ëþê  Ðø#äüè üõãïãìÿÿîáþé÷% éøöçöóüùèüÿøêÿ÷öàñïõÔ ÿüøëêå÷óýèëîðûýÿÿý÷úüÿ÷ùé íüèìõé Üüö óý ÿúûÿþÿÕçòîø!êÿïõôîûæÿ ùúð ò÷ðáêêúü ùÿ èÿöóýõýìúÉ ñöìðñ  ôúÝÿùÿðõýúþ    òöãòú  ñøäæûó ÿÿïûÔóïþâØîî òüã îûâùö  üé+éôáò õ é-íâ ( úþúÖòøöéüîàýóÞÿö1 ó#êòëòùøÞõÇÿ"ïëçá ùäåÜ /ü öëøö÷úéëåíýáý$  Üüøüñ Øùúíïãøñúáøù÷Ø÷ÿ úüÿúþøõõóÏþ Øÿ÷þïõí ûÿøößôòýüúôûèõõ÷!å  ô ø÷ øûþçýüõú÷þßøõçñúùúî$  ' ûòé÷ÿüýúôÿòúøø õóüúðþü÷ ýúþðýþ÷ ôøöòÿùîøßáíê"ìëìüÙöö ý óþ'âé(éîòúìèþñÜåëó ùýýþ "ÿ÷ &êúìúçâë×áíïýüïóüì 3îüññ*÷ÿðûûóùþûÿæäêïïüýñôôýÜþûøô÷ô øýóÿÿ ôöÿøø÷úæ íðûû÷  ôêø÷ûøõ  ñ ÿññýüúÿõñøüêùùø  ù þùæòëø÷îæñòóèýþûþ$ ìðçïøöúõúøðóø÷øô ÷÷üùê üä öûûåëåçëââÿûüò + ý÷ýöûòýõðôùýõ ÿ ýúÑýèôöñ ü÷íïûæ÷ûóüþù ÿðñöñ ïûûôþúùóùû÷ü*  õíúûùûû÷ýþõòêïïîôêúø÷& û ÷ô÷òõ÷úüü  ýñþúÿî÷õðøøóøøü ýüüõòãðòôÿç  üôõõýøþåÿ  ûøøõùëþû÷ûûøõòú  ÷ëöòôûýó ÿý ÿÿÿøùúýû îöúý ùüüþøÿ÷ü   åïá÷ûðûóõûõû þ ø÷ì ñýôòäðëõûøýûüþü   êöï÷ööòöýùüúú  ýúëþó÷þîîíþú  ÷þýõýÿý  ûúúÿøæüüüùøùöõóÿ  ùüíýøö ì÷ñöøó÷ôíçñëø     øüûúöîóòòÿþýõùúøòóúÿùøýõþ   ùúööø÷òÿóôôîñêø  õþøùñüûþüùö÷ûêþüÿüõ þ  ý ýù÷ö÷óûùîõö  þ öú÷ûî ÿýûøøòû÷ûÿð üüûýïþþ ùúýöüÿöú öþúûîùûþþÿüýôùöû  ÿ ý÷ùñÿûýøÿûúôýý þø÷þýýüýüÿòÿûþüýòøøûý÷üûøû  ÿýûüýúýÿüþùþÿýüÿÿýþõýþýþýûýûýó    ýüþðùøûøúüûûûÿøþÿøûõý  øÿÿùøòóüùùþþýþôÿ ú  î ÿúôôòóúòõîþõõóñòý  ú úúûöÿý÷úêþÿöýçúý ÿÿùûüýûýöûýóý÷ýîýù üñúì  úüñóûõ í÷ñùþýó ÿÿþï þþ ýûûøÿùöñúöúæõôþûþþýþõÿ öõöïüýùÿûüþûþ ÷ýþ÷ûòôûú ÿþýúöûôúøÿûý ýþÿüùùýüøÿýÿÿüøùúüúÿÿùýÿþûþõÿýûýôý÷þüÿúüö ÿÿùüúýþûôùúûùûö÷ ýÿ÷ö þÿûûý÷øñýüûö þüü öùÿûûúñÿúùýýÿüýý ÿþþþøúúþýùýÿûýùüþÿõùüÿü÷þùýÿúþþÿ ÿÿöÿ üÿüóÿûþõüþûÿúûúøýýÿùýÿü üüüÿ÷üú üøÿùûðýøýõøùöýþ ýûþýÿÿþøüþýÿþÿûÿùüøÿþþþÿûýüüÿýýþúûþÿþúûþþþûþýÿùúúÿÿÿüþûüýýüþÿÿùÿþùýþýÿþþþÿÿúÿøýúÿýþþþýýÿýýÿüÿýÿüûûýüÿúÿþþüÿýÿöÿýþþÿÿüÿÿüûüÿûüøþÿüÿ üþûüÿÿýÿúüþüÿùýÿþýþþûþþÿÿûþüÿýüýÿûýÿüþÿÿþýýÿüüÿùþüÿÿûÿÿüþüûþûþýþþýüþþüþýÿüþüÿÿÿûÿþýÿþÿúÿÿþûþýýþÿýÿýÿýÿþÿþüþûÿþÿÿýÿþÿùýüþþþþüÿÿÿÿýÿþþþÿþþÿÿÿÿþþÿÿýÿÿýÿcrossfire-client-1.75.3/sounds/Creaky-1.wav000644 001751 001751 00000106152 14165625676 021377 0ustar00kevinzkevinz000000 000000 RIFFbŒWAVEfmt +"VLISTINFOISFTLavf54.63.104dataŒ.@0>6NLJVJF>((&ܾÚâ²È¸Ìކ€€€€€€˜š®¤Øìîzü"6Dnpt|ZlnrX$0èðÊìæöæÆÞºêòæôüÞÖÔÚüÒì ðÞöÚÄÆÊÐ¸Ä¸ÈØÐäèðÔÜÎúüþ þ"(&FNjHVBVHN4HTbJTD6úêè¬Þ¾Þ´¨¢¤ÚºÐ®ÈÎìæöôþö&><RBVV\LPNRDD82,ô򮀼ª¤¨ž¨®²ÈÐàÆÞÔôô(&  þþòþêêàÚæêêèìèðôøþ "",06B,>BFH6:**0(.òìÜܾÌÊÎÚÞäòôüò &($0:4H8$"þôêÂØÈ€Æ Â€–ž¼€€€–ˆœšêÞüâ JFx4@f\z\|~vd"8FèôÔæâÜâªÄªô´¾Ô¶ÀÊšœœ²˜¬€°¼ÆÔ°ÀÆÔ¼ÎââN&*@üJR<F&LB<6HDX:<* * *2(&" þìðÀôØôÒº¾¾æÊÜÆÜæìúüüöüæèðú2><@FTDNDXJ:,îâÚèÌØØÔäÞîÈÚÌêêèâîþþ þîöòþêîðìôîöàæâäÖääðîòúô"&66>BDLBNLNF*60.2*2  üôÚÜÎÎ¾ÈÆÂÌÔØÞÜêä & **<DDL@62òòÔÂð€²’”´†€šš€’”š˜¼ÐÞ,<,<XJ6zz|PZLZF* ,âÐòÞîèÔÈÈîÔÀÆÌÀÔš¬Ž°¶¤®€°ªÊIJÎàÚâÖü B..< ,ø04D,$,<..8b80(,ú" ø  ÄêÌúÎΪ°ÎÆä´ÌÒÖÜàÚöÖÚľÊÈèô&*J>V^xz~VT2D* øîæÖÒÞȺ´ ´ª¼ž®²ÄÆÄ̲À¼¸Ò¶ÂÀ¾ÌÈÜÀȾØÐÜöþ*28HP\\^lhv|vpxll`TDBD::8*& &ôîæÜÎľ¼º¶¶¾Â¾ÄºÎÎÐèØèä úîäØÈ¾²¢˜¶€¨¼€¼Ä°öøø  ,Vdph0\LP^vFZRdJ$"úààöê¾¼®º¨¦ €‚€ž€€€€€ž€€€¢¸¤Â¢ìèü 8(B8fxrVj8rXH8.000.6*þôêäÞôú ôöèܨà¼Ü¢˜ˆ†®”¤„ª°¬¶¸¼º¸ºÈ¶Úä .FTvpbFD,ę̀°¦¦”ŽŽŠ–”œ¬´ÄȾʸÞÌÐÖÎÖÞÎèäüæêðòø $(::>H6DBJFFDJRJFH@B<B@@>&,($*$& úðìÖÀ¸¼¶®¶´¶À¼È¾æêôô ""0òæÖÊÀ´ª¢œ˜¤œ¢˜¦¨Ô´ÜÆ@2dz||pjpln\ljb.\4Zòð öúîúÞä¼öèäØÌðÒº¤´®¢°œ”œ˜ºª¢Ò°¶Â˜´ªÎÐÒòÐ:>JPr~`l@pH>$ àìàúÖ¼®Â°º®ÊÎðÜàâÎÔÒÊÜÚØÈ¬ØÄð¶À®¶ÐÆÚ¸Úèìú&HRbjvzhD4 öØÈ¢š†„†€€€€€€€€€€œž²ººÈ¾ÞÞèøô "":,.2*.0>2.0"0&( (&("$""&*0$<6>@8:6BDJP<B664*,ðàκ¦–”ŽŠ„ˆˆ˜” ¨¸ÈÔìØîò  ööîâàäÜÞØÞÞÞêîìøF2@`xt^xZV<.0Fðúòœ¼€¼Ú¬ºÊ¼àÎÒÎÆîîèôÎèôÎöðôôÒÞÐÚØÚ¼ÞÊÊҮĮüÚööô(:^Ld\ztR>NòþîèÒØÀô¼¼®ž¦šªŠª¬ÌÄÈÒºÈÄÈæÜüÆâäöÐà¸âàôðð   (JBZDjxvhV<" èè¾¢š€€€€€€€€€€€€„˜–¸ÄÖâæêì ("00:8<<0<6H:<<00,& $$2&,$*62@@4.(* $øèÖÂ°šš–†ŽŽ– ¤®°ÆÎèôôþ$8*20 þúìääܿܨâÜàÞâìðü *28@4^z*~j`hþöêÞöÖÒÈÚΦä´Â’€¼ÀÔüøü(üöÒîÀÚÊÔÐÊÊ–¾®î®ÎÖÔæü8:(jdrd^vv~hvzdj|N60ÜòØæÞ¶²²¨¦š¤¾²²˜¢š ¢®¶âø.*0 (&4<ò üèúîüúþúöðêðâø$.,*@F2<@J<<6:(ðêØÖ¬¬žž‚ˆ„€ˆ–€ž ÆÊÖàü028@RT`hpln^^VN8,&îìââÜÞàîâìêþ*øüúøþîîØâÎÈÆÂÆÆÐÖÜääîîþ &4:@J>88*.øîêÞØØÖØÒÔÐÎÔØàæìüþ "4.>BBHFFJ8>*<*FÈ àbøÄJÒÐܪ¶¸ª²ÄØì$.jöê0&@$ *ÜðÜîàʰœÈ°¤€¬¤ÆÈ¶ÀäæÚî ,8<H0J>nb`6ZXVNDVZLt\XF ØòèÒÒäÆÖØä üüòìààØàà úììêöè´È²Ü´¾–¬²ÌºÐÔàøöú(,>RDb`|x|z||tjjrf82öÎØÄ²´²¾ÆÀÂÈÊÐèàîö öüüöüôöôìòÞÜÄÞÄÆÂÒÐÖØàæèòöþ$*266@>JDHHHPPRZPR>FB6B60"öêÔÊÒÀ¾¸ÀÌÆÔÀØÚèöô& $ öêâÔľ®¬¢¢”–– ¨®ÀÄòò 4DHVZfltrnpj^`VPH@<(.$ ¬î68þT èììââÒ$ÄäÞØÈ¼êØ’ €Ò¤Øœ¬¶ Ð°Àš¸ÂÎòâúÖ0 2è2,0Z,@ PJl&rdntHD6\4:$48"(ú6" "*"úæÂ¨ÜÀÚ ¾ºÄ¦¶šà¶¼¤¦¦¤¶¬ÈØ &"6Tìü&4"ò"*.&"$**$úüöôü 0  öèÐÞÊĸ¸º²ÀÄÆâÜæàòøþ ú4466,$"(   øþôúøôòêèêÜàÞäâÜÞèðô&( $2,BHF>28.44& úöÚØÌØÀÈÆÎÖÚÚÐêî .2,@:B(& ðæÜÊÆ¾À°°¦¬¬²¨®¸¾ÈÒÖæÚèîü26D<NTZTXZ^h\hVRhPxF<`¤^B~VXR,öþâÚÆÎÎü Ä¼²˜®šÌ€€€®²¸¬š¼¨ÜÔÌÄÄôöô ø0(&ø&*$:& 80H(&Bøøä &þ0$(4*DFNnPP> à&èüêðàîæØÒÌÄÒ¶ÖÖîøêðêØðàî¼®ÆÀô²Ì¢ÌÖÞîÎæêðþüúôöîêøú"420NF~^pxbvthF@ 4 üþöîúìòþüøöîüîôÐöêîðÖкĴ®¶ª®° °®¼ª®¬¶¶¼ÌÌÖÚôæôò  *0BLPVhlx~vl\PHD:&úêÞ¼¼¬ªœœ˜œ®¢¬–¼ºÊàÖèî " úìàÐÈÀ®®¤¶ªªº¶º¼ÂÒÜêüü "*LN\lfpnxzzt|xrv`^JHVBD  üôîèäâÎÚ¸B€Òø²ÆòâÂÊ€˜€„€€€Ò€¤¬ ª¨æÌ’²’úFú4LP|rnp^nz>..üÆæÜê¤Òĺô°Æ´àöêæþ &þ4,$(@&N^NFúμêÈê¦ÀºÄ¨¼¤öÞêÖâÞÖìÚöü4*8R2>0*L.XöþæèÂÌŒ¼®Î¸°¾ÈÐÞìäîèôÚÞÞð ,$<P@|r~vb>B"üâÖ¼À®œ°†Œ€ŠŠŒž†¨²ÆÐÖìÒêêðøø öôêôêäîàèòüú"$(4:::N6@:D>>.,2.*2&$  ðìÒÎÂÎÎÌÒÌèèèæþú& ",&, ôöØÎº´¦¨Š–ޔІŒ¢¬ÆØäþü 6RXjv|~xvpjTR>:<24üòúäèÞôäèÞðîìîøìèàèÚü¸âø‚ö0ÊúæÊº˜”Š€€¶²¢¤ÊÔÆòBÔêüðx8j<Ndt\lV`ltl$6,V þàìÜààüæêÊÖÔâä¸(ü(  .H0 ,êêÀæøÞؼÐ̶¬ÈÀÆÚÊÐàèÜð$ $($þ¨æÆêÔ´¶¨ÜÎîÔêø 4*(0(,8`Xlfnx~bvZP*æÔ²”€€€€€€€€€€‚” ¢²ÐÜøö ø $"$*(",&6.4"$80J.0&$( 4$þòâà¾Â¶¸ª®¦¾¼ÄÄÎâæ02@@62.$þèØÆ¸¨ œ–”¢š¦ž®ÀÌäèö(4BR^p|xrvnp\VX>LH@0úöôêîìêæìòúüòîêàâÐÚÖмÄΖ¾®€Ö¸Ø€È´²¢–’ˆ–𬍠ò4L*~nJB|jnnNJdPNþ"(ÖâÄÚ¾´¦„Œ€ª€ˆ°–ž¬ˆ¤²¼â¾Ü¤üü þ",F&<8HVNlVB<ìêìêøøòì òøêàîèîð$øøø ÜêœàÄྡྷ²¦ÖÀØ¾Üæöú$6Ltb|~vjnJ<æÔÀžŠŽ€€€€Š†”„–”¬¬´ªØÜàòîèàøüü   þ (488B4JLNNDJFDPFTB<:*4,8  ôöÚЬ¼¬ª¢ªª¸º¾ÆÄÞÜÞòô$ êÞʼ²²¦šœ¨  ¢²¬ºÈÒäô  04P\pzrPJ@.$ èèÔàÐÌÆÈÒÐÒÔÞÞâààâÖÖÎÈÆ¾¾ªÆ¸¾ª¶´°°ª¨® ¨¬¢¶®ÌàÈÞ¨P@x"phdr^zZlL~PLèÊ"þÞüæôÖÎÆàÎæ´¸¢Ø¨¤˜´¶²Ì¤¬¤¼ªªœÎ¶Â̶ÔÌúêôú,0N<TLzht|NV(h&$ú ôôÒæÞÔÆ¸š²’˜€®¨È´¾Ä®¼¼°ÚÆÐž®ÌÆð²ÖÄøþú"2*2:.&&(&N>NRLb^tft~r~lxl^P6& èÖÖºªž˜Š˜€‚€€””¤¦ÀÈÐîÖäØöðüüþ     ,28<B<RRRNTPJTPNNN><:64.(úòèÖ¶®¦š¢˜šœ–Žªª¸Â¶ÊÎâðø øøúêòðêìèþâìîø($0BL`\lpt~vtfd\NH0, æÚÔÄÔ¾¼²¶´¶´¼¾ÆÎÎÐÐÎÎÐÎÌÎÎÚÔÜÐÔØÜÚØÜÔÔÚÞäèòô*6FF\bdVhj$LfF`dN* ú޺IJ°Ü²ÀÀÔÖ¶æêðšŽÈ¬&ÖôêØ$ D2>ø.6âòþöüÔâÊÔîüèøôâÔìæðô,:FP4\Vl>NDNVH`:,&öÜÖÒâ°²ž¢œ––À´Â¨¬¢¤¸°¶Èø $,$02$`&:þ0$($ö î ðððØæø"6BDbhfnt~vllRpB:òîÜд¤š„€€€Ž„šˆ”š¦¶¸ÀÚæîòúüþ$.*& ,*8(0"B,., ( 2** $2(8 " úøòêèØÔIJœšŽ€€€‚Š¢ªÄÈÚêò<:H\p~t\TB0 ìÔ̺º¨  ”–˜ ¨¸ÄÂÐÆÞêþ&*>LT\HT>`PL:,0 (&úöüòððøöôü   üþêîæàØÌ´¨žžŠŒŒžœ¢°¶ÒÞöö $".486BHVTXXRPBJ62,& Þ^*ª6$:î âàÂÐÂÆ¼üîþè*ú¤¸ÔÎ0ê îò  üþ ì ,àô  âüÚ4ÐêæØö¾ÂÖÚðÎäÂú ö ,( 8$lP>Pô$*  4,H þüòìèâîâà Îâ’ÞÆäÌ®À´ðÌàÊæêðüöôúìäèÔàîú" :F@fn|nl:2þàи®¨ž®¦ª˜¦ž²¸´²ÊÖÞêüôôþøâäÜààâààààæâèðøü*0<"FNR\N`^nxtnrndfd``NB üâÊȲ°”ž”¢˜˜–š®¬È¶ÆÌäðôøüöòìäÞÌÈÈÀ¼ÀÄÄÌÐÔÐÚÞìü**80FRhrv~ztdtVPB4,æêàÜàÔÔÊØÖÒØâèæðìôÞæÞààÖÖÔàØÔÊÐÊľºÀ¦²²¼¸¼ÀÐÌØÜò& >F\Rbfndjdlprdd`PTB80úðîøÈÎîìààì®Â€øêºúÖäàÜÎÐà Úöì<¨ê¨" ( , N*8,V22 X("øþ àÚÂÈêÔ¶ÜÈÀêž¼žäºÆÄºìôîö*&*6JVP|hjt0@ ^8H&þ øæÜÖÆÎ¶ØÜ  þúüîæÖôê Òà´ÊØÖÚ´ÆÆÊÖÖàÞÚÜÜÈÞÚ ,2HZTzvxrZ8,üâζª–ˆ„‚‚–˜Œ”¬®Ì¾àð.0*44,42,606 äîæàâÜàÎÐÔÖâÐÜèàúü  (.H>HH:JF`FHD0,üüþôðòìüøòøþþþ&"ôøâÒÀÀ²¬˜ š–ŽŠ††Ž”¢ ÊÈØàÜîú.BX`nj|zd|x~pttZn^bH@608*, "   øôìàØÄÈ´ºžžŠ‚€€€€€€€€ˆŽš¬¬ÈÔîô&>BFRZ^fdltz~~ph`PPF8.$ üôîîêìæäÞäàÜØÚÞÜäÜÔÂØ®²òŽÈ°JºòÎÚØôªÆ¾¾´ÄäêÐò èâ^NnX<lbPX0F:pX>, <ÔøÜðÒ¼¶ˆÎº¼¼ÄÆÈ¼¼¤¶ôæÔ4620JB:6FR2fPLN¼ðäêâÀÈÎºÆÆÔ äæÖâÚäêìú:64J.2""("8èÚððÎÀÞÒôÎÚÈìæìÚîÜÖÖ´À²Òäò (.PN\\fptbvt|VR6""ôòÚÖ¶º´¸Â´¸¬¶ºÈÌÎÚô úþøúúööêöðäÒÜÚÌÚØàèæðîòþ (.88FHHVNX@NLHNHJ842&.,(îøÒƺ¶°°¾ÊÎÞÜÞìê"$0*2öàØ¶²¨œ””І„ˆŠŒš ¶Êàæî4HZltdZNHB( üøââÔîÞâàìììúîîÜèÞàÎÒÎÒÎÂÀÀÀ´°¢ªžšŽŒ–šª®²ÄÔìö*4:FPV^`lr|~ztrhZPDF86&þöþÞÚÐÔÌÆÄÂÌÊÖÂÖÔÚÞØØÐÒÒØÖàèêêððîìîîøúüþþ2^$6(RøðìääúìøþÎjÌð¦´<ò,ðþ&, æ*Þø ôì¶úìöâòúðìæÈÂæàæÄäÚþ.8:8Vl\^f,"2þøþÚàÒÒÞÖ¸´¢¨ž¨ªÖäêîþæèÚäèò ¼Þ°üÚêζÚÖàöä ($&&$4DRj`zz~vhN>îÖ¼ Œ€€€€€€€€€€€€¬€ €ÂÆØæþþ*"0:B<DB<2646,2.2,*$$   (0*..",($îâκ°ªªž¦ª°Ä®À´Öäø ü:@DZLJ<<0"øêâÒÌľ´®²®¦®ª¼ÆÌêæòúð64HZTlptprnnrfjRNH:R:BüúêìêìÜäâêèâÞàÖÐÎÆ¼ººÆ¸Â¶¼ÂÈʾƮ®¨®°²¸ÂÀÌÖâô $4DLX^ltvx||~dhXP:0$øöòìîæÜâÖÐÌÈÂ/ÈÈÄÆÌÔÔàÊÖÔÖÚÞäîøúüþþ $,.46282>80(  ðîÒêÖä€ ÚþžèÂú¦žœ––’¼ÐàÜôúb<à$"x^tT~pttHT l>F ú 侸¸Äª´¢†šžÎ¢ªÌªÂàšÎÆ ÐÖâÒ("&R@@PbXzjznr4< øöèêÎäòìÜÚÎÈÆÊºÚìöôÚôÞöþÖЌذޢ–”’вҦàè "2<\nrhztTJðòؼ®˜Žˆ„€ˆ†Š€„€žœ¨ž¼ÌÒêâæÔðððøüöüø$,(*(:8D:HNFZRTNPNL:H:H$  îîæÎ̸¶˜¤žœ¦¨ªºÄÎÐàöø*:<>N86"üÞÖÊÀ®¦œœ’„œ˜žš¤¸ÀÞêô (8ZXlj~j~nn^PN886*&öúøìòìòèêìîîîøêèÞæÜÖÎÌÖÐÔÀƾ¾¸¶°°°¬¬°²¼¼ÆÌÞêø&0@@JT^TZXddhfdd\^PH>4." þøöîìèÜÞÚØÐÊÊÄÚÌÖÌàäìðèìîðîîòööüøþþþ**0420.$0"$ üðìàâÞàÒÔÐØÌÔÔÜÜÞÞäêìêöú  &,0,66><840&ôþìäâÐÜÖàÖâ €@PÈ\8FäèÞÎʸòØàòöÂî,ÀÚèèd@$8@D\&4 ,.:òöð ®¶´Î¾ÌÈœ¶œò¼ÊæêòÒþ08>LVjFPLbBFNBZ4ZNN ÞìæÚÚØÄ¾ÒÈø¶Âº®¬®¢¬Ðìüöðúþ$ÀúàüòÆÌ²øÞôäîüþ$  &NRnlntjf>*þîʸž„€€€€€€€€€€Œ˜”¶¾Öìèäæúö (&" "*(*$$$0,4(006:8@*>><H,0"**"(* þøîÜÎÆ¤¬ž°¢ š ¾¸Ê¶ÖØîþü*0>DTZTBB0( þðìêÔÆÊÄÆ¸¶¸°¼ÀÎäì06DLR\ZdfdZPNFD**"  úðöîôììêðôòîü üðôêæÞàÞÜÚÖÔÎÐȾƸ¸ª®ªª¬¸¸Â¾Öâò$:DTPjlvnlvt~vvh^\JR0( îòìîääæÞÞØÚÄÌÄÖÆÊÒÐØÞæàîðüöøøúøúú $ "öèêÞôÚÚÊÈÊÌÀ¾¾Â¾ÄÀÈÐÔääìòø"*82<<@NT\\d`hd`TJNFB4,$øòâØÎÀ¼¶¼¶º²¾ÀÄÈÌÐÖØÜÜäêäêÜæäêìèðìòøöü 4,@ÂXBXLzàòÚØÂøþêäö4ļذZ4$Fü "(ææ(ÌÜ´ÜÒØÜªÂžú¸ÆÒØÖìºÄÊÄøÚøÊö* (L:L^d~h<B,@ú èÚöæÄÖÀ¸ÄÀ´´ÜêöêòìèœÚÂêଶ¢ØÂÞÈÆØâðìêèìòäîø,,L@RjrXF.ìÖ̰¨’˜˜ž„Š€–œ¢°ªÔàìüúøþúþþòðêææäîòôüìúúü (4<42>:J:@06HBVHF8@:4:."ôèÚȶºž°¨Ä¾ÆÈÐæè .28J44 öòÔ̾¸ª¨”œ”Žž˜ ¤¦¾Èâêô$4JTfr|x~~jXVF@>2(úúðæèèäìÚæâôîîîðèâäæÜÜÒÔÎÒÄľȼº²¾¬®®¦¬¦À¸¾¾ÊÞêü(8:HHd\h^nt~x|zfj\N<2& üôðìèäàÞØÚÞÞâàÜØàÞâÚäèìîÖÜÐäÐÔÎÖÔÖÜàäîðú $"$*,:<BJDJFF@<6, øøêâÒÊ´¶´²²°²°¸¸ºÂÂÈÔÚàêöø($0:@HHLDLHFB@<42("þ üþøþþöòêèâÞÞÔÐÈÊÆÂÈÄÈÈÔØâÞæîôø   ",*.0&22,:4::28, *&&Àú @"^èþæ°Ö°¶ŒÐ¼è¦ÎкÀÒþ¶€²€.ØäêF*"NNj0H0ö0 .ÞøÐäðÞðþÞÌàÈèÞò 2$T&628J6p\FRþèÜÞì¾ÐȾ¬Ê¶ ¬È¸´¾¸¸¸àî $þ 6 0ÐüøÔìÂòöð ìü >:RPPr|n€P~^.4ôøÜº¤Ž€€€€€€€€€€ŽŽ¬š¼Èäìöäþ  .    &&"48<J.LHRTNT8PHJL<:$ âØºÂ˜’ŠˆŠ˜š¢´¨ÆÎÜö þ*8FJN<62$ ööàÚÔºÀº¶°°º²¼ÆÈàèúö &,>HPfjzttjVbR^F@2(, .úøòðîòîòìúþþúôèìàÜÔÔÐØÒÌÌÆÒÆÆ¾ÄÂÂÀÀÂÂÎÌÖÒàêú *4>>JFF<@>@:@>8<0((þüð þôüüø úúððèôîðìîìòâîîúøøúîôîîîìðöúþúüúôôêìêêòêðìôø"""0.:(4,<2."  üôøðææäàÜÐÖÒâÒØÖÞàâèîìòìòòúüöøöþþ$&,$(&0.,,( þüøôðììêêìîîððöööúü   þþøøððìòöôòîøøúúþüþþüøøôøøöøöúþ  ú~€(rü6FP"èÜÎÒ´ÂÄ"ÆæèòÚìä8®ÞŽò*& F42(V"â ²ÞàØúÆÎš¾Ðà‚ÜÌÐ ªÔ²þìþÜVD\$vdxZ|~~z>,è&ààÖڮ¦àÒ¢¨–ˆžˆ¢¢îàðúøòîö"ØêæâøÀØâöðÜììú  ö"2PX`zh~hH8ôâ¾¶ €€€„€€€€ˆ„ ’¦®ÌâäÚúø þüüüüþüúüôöü $.2$>@NNTVL`^bj^bLHB:F2($øÞÚ¸¬¤žœ˜ž¦¤® º¼Òææþð04DFL64  úòÚÌÆ¶´®®˜ª¢¦–¤¨ºÊÔðøö >BXbtzrfTFB02$ôøèæÞÐÊÊÈÆ¼ÖÔÖØÜØÖÒäÚâÚääòòêìæðêâäØÖÈÀ¾ÂÂÄÐÄÚâúü$0:<FLPTVZ\^^`^XN@D& úúæèâæÞÞâÞÞÜÞÔÚØâäæêìú"  þüúüúðôììàäâèøöüü þþòøôþððìèäââàÞâÞææîêðòü&(2<@PFPNRTPPD@6($øîæÜÒÎÈÄÂÆÂÆÂÎÐÒÜäæêìðòòþüþ    ü²øú üüþüþþüüôöôôøöøôööúöüü þúøöôìîÜðêìääîòøöþ  **,&&(($""" þúüøôèèæääàâàææèÞââàîêðôüüþþþüöþþ  ""$&$$$$&"$$  üôøî´ú†8þ,º.æ"ÆÈ¾¸®®¨êÔØàîôÊ2è˜ÖêJ: DP\X2H fT`:>L:ü þþîÆäÎÈÖêÀÜì¢ÀÆèÚÈà¶ 46.>L:bNbPNúø"ìØèÔÖÂÈèèäÂ̸¸À°Òò ôúêò¶ÞÈÈÌÖàöÜ þð$H@Xj^j^2"øÜÀ¬œ€€€€€€€€€€„–’ÂÆÔèâìæøþ """*"" (  ",.2406.<<6<,&  úòÐÚ¼¬¦¢žœ¤¬´ÆÆØÞî"*2HR\ndPP<8(ðæÞʺ²¨ –Ž˜†ŠŒŽ¢¨ÆÄÌØØòü*>FXbhxfpd~ntjdjVnb\D:<,4$  øøîìèÞÚÖÖÎÊÀÀ¸²¤œ–Œ€€€€€€ˆ€ˆ’¤¾Ðèø"0@N^hbpznhXLH>B&*$òîææàÚÔÐÌÊÌÌÐÐÜÜÞÜÜÜÞÜâäèèèêêèêìîôøøúøôüüüü (.62B<<:*( & úöðæâÚÚÖÞÖÖÖÔÒÔÜÚàæèøúþ&(022:<8420&$  ôðêààÚÜÚØÞÔææòðú  þüþüþþüúúüþôþüþüüþøþúþúüôúúüþúþþüþü   & úööôòððòèêêîòöú   üøöðììæèèîäààÜâÞàÞÞäèîîôö"&,022:44.0,,&þøìêäâäÞÞÜààêæìðøúþ úþþþüüþ   üøööîîìêììîôôúü     þþüþúøþþüüúüüøþþþþúüøüþúüüüþúúöøòòôðòöðôöúü  Êüö ¸æÄ @ ø0îâÆÒÀİÚúÞüúÐòª¢äÈBäð,.> 2ä(@ÐúÞì¶âÊ.ÀîòäîÞ. "<246&>*<&.0XF âÔàÚüÌÖÐÖÎÒ¾ôâÆÚÎÀÖÈÖÐ ,*úJòÀøòìâ¨Î°ÐÜÌÖâäòôðôæêìØð B:TjP|lP,$öØÂº˜š”†¨œ€ŽŒœ¨¤²ÀØÜêîÞæêöìòìîòêîòìäØÞàÞâìòú $,0>:D>RNNPRRVZ\`f\PND@B:0(öúÚʰ¬¤žžžž¨ª¦²®ÔÒèæÚöþ&îäÚÎÄ´¬®¬´¬°À´¾ÌÐêö$>HZbvztj^LH:04üöøôäâÚæÜÞÖàÞÞàâàÚÒÒÎÒÄÄÂÌÀ¼º¸º°²®°¢¨ª¬´¸ÄÎÐàê2FTdfv~vh`L:("üöîîìææàÚÒÔÎÄÀÀÆÂÄÆÈÊÚÌÜÞìììêîîðìøúþþ $$$* (&$( þøöðæêâÜÚÔÒÎÐÐÎÖÐÒÖÚêêðöü(*4:BJLLFHD>:4."þøîäâàÞÜÞØàäêìîôü þüúøðôøîööööøúöüüþþþþþþøúöþúüøþþ  $"""" þúöòòìòöôòìøøüüþüúøððêêàâÜÜÒÖÔØÎØÜâæìðú"(00.,22204:000.&($  þøòîêèàæâàÜÞÞâæèêôöúøøþüúüúøøöúîòðôììêèèèæììîööüþ  (,.488:<:842.(("  úöôîêèâÜÜÖÐÐÌÎÐÔØÔØÚàâäîôôúôþþ  "&&$"&& $(*&$  þúøöôòììêêäàâàÜÜÚÞÜÞàÞàäâæêîèîêøòöøúþ """$(*(*,,0(*& þþúüðòððîîîðîîììêêæìêòìðòîüüþþþüþ&,*,*$(&($  øððììòêìÜâÚàØÔÔÔÔØÜâÞâææèêòüü " $&($$&&$$  þþþúöøøôðìèäàÞÜÚÜÚÚÞÞÞàììôöúþ úÌ&("$$     þüúøôðîîêêêèêæîðòøìôðúöôöìòôîúøþþ $&&,*(($"  üþúúðöôöòòòöööøúøúôüúüøüüúþþüüúüúüþüþþ    øôÄö&‚22Ì4$ô(èÌÎʸÒÜøÒüüà2²òÐ8:&. D0VB(2P0L 8üìÔâìÖðÀ¶®ÖäÊÐØââÀòà(ú:2R&@.\<:>F8FPjB>(ÜöÊ ØÚºÊº¾¤ÈÆöÄļ¼²¼¶îø (2 D äôüÈäÄúîîêàøþ üúö6:HXNvr`ZN.þÚÔ¨”Š€€€€€€ˆ€€€”¬ªÂÊöþ $  " üöøúüúþúþ  &,20:DBPDBBDJHPF46*,,*ðêÒ⦦¢®²ÂÄÆÔÖøü"<><R&* êâÀ¸¬¢’ŠŠŠ˜Ž˜¦¨ÈÖî.:L^fx||~j~h^T>>08: ü úöôîüòôìüþþþþìîèèÚÖÒÐÖÄÆ²Â¶¶¤¤œˆŒ€––¨¤¶ÆÖðþ&4FLXhlvnxvtrf`N@0 üúüööôöîèìÜÞØàÜÚÚØââðÚîìþøöîèìèêêêîìîîôèîîøúüúþüþüüþ &,(*  þúöðîæâÞÖÖÒÖÔÔÚÜÞâèìðø(*6082B<:6.*$ þøòêäÞÜÚÚàÜàÞäèêðôööúúüøþþüþþþüþþü   üüúúøúøüöøøöüúþøþþüþ  þü  üôîðòîæîììêêîðúú  ".(*& $ þúúøòøððèîìêìììêììîìòöþ   þüúþúüòðòêüúüþþüþüòòêôðôðêèæäàÞàêæîèîòöü "$$&$("" þþþöøøöøöôööôøîöøüþþüòúúü þ²       þøøöòîìèâèæìàèèêöøþü  " $$  " " ôüüþüüþøòðìæâÞÚÚÒÞÚâÚÜÞàâæêðøþ*,24468:66.0..$ úúììæêâàÞàØØÒÖÚØØÒÔÔØØÚààæêîöú  "&,.08:@>@D:<84.*" úúðòîîîêêèäâÞàÜÜØÖÖÔÔÖÖÜÜàäèðôþ  ""$&&,**"$  úôôìèâäââàèæèèèêìîîðôøöøüøüþüþþþ  " $ þüüúúøþúüúôöôøööúøøöúþþøüúþþþøüúþþþ      þþüúüúúúøøôôöôöþúüòüøôúøüüüüúüþþ   þúøððîðììêêèæèäæäîêìèêìîòòöøúþþ "" "þüøôðìèâäàââààÜâààâäæîîìîêððööôöøúüü   $ üúöøòîîêèêêääèììîðôöúøþüüþúúúøúúüüü  úöôðîêèêâæèêòòøòøøþ   þþþþþúüüüþúúøòòôøôöööøøúüüþ   þþþþþþúöîòððîîìêìêèèìîîôöøöþþ   þüþøöööøøöúööôöððððôôüòöôøüü  üþþþþüþþüþþøúúøúþü    "žü üüúöôîìèêâääêâäêèêìðôøü " üþüúøúøüúúøöôöððððòîîèìêìêìîðöòöîôööü  þüúøööøöøøöøöþøúöøúúüúüü   þþöúúüøúúþúúúüüüþüþüþþþþøüüþþþ  þüþúôôîðîìîìììîðòðööúøøøúøúüþþ  þúøôðîèêèæèææèêêìîøöüôøøüþüþ  þüüüúúôòðîðêêêæèæêèêêîîðòöøú     þþúøôðêæäâäâäèèêêîêìêðîòôúü  þþúøöúøúüøúøúúúøúúüúüþþþ þþüþüüüþúüúüüüúúüüþþüþþþþ     þúööððîìðòöîôøøüþ  þþ þüþþüþþþþþþüþþ     þþüüüþøøøúüøúøüüüþúüúþþþ  þüüøúøöøöôîøòòððòðöôôðöøøüüþ   þüþúüúøöôøöøøôôîòðòðôôöööøøúüþþþþþØö    þüþüþúúøøöôöôôòöôôööòððððòððôöøúþü  þþüþúúøúøøüøøôööööôöøüúúúüúüúüüþ  þúúøüöøöøúøüüúüøúúúþþþ  þþþüøüúøøúúþüþüþþþþþþþþþþþþþ   þüøöôðîìîêêêèèêìììðòðööüþ  þúúøúøøööøöøøöøúüþþüþþüüþþ  þþþúüúúúøöøööòöööúüþü       þþþþüüþþþúþüþþþ  þúüøøúôöòüöøôðòîöôöøöøúøüü     üþúøøöôöòðîîðìîèêìîôôøúú  üþþþþþüüúüüúøúøúöúúüüúüüúüüüþ  þúüúúöøöøööøöúúþúúüúþþüþüþüüüúüúüüüþü þþüøøöøööôôöôøøøøöööøüúüüüþüþüüüúúøüúúøøúøüúüüþþ  þüüúøøöøòòððòððîððöòôöôøøúúüþþüþ êöÊúþ   þüúúööîðîììììðîðîòðòîöòøðöööøúüüúüþü    üüúøöòððîîììêêìêìîîðîððöøúúüþþ      þüþúúöøööøôöîöôöôôööøööúúúþüþ    þþþüþüþúüúúúøöúöøöúøúøüüþþþ   þþüüúüüüüþüüþþþüüüüþþþþþþ   üþúúööôøôöôøöøúøúüþþþ    þþþþþüüúþüþüüþþþþüþüüüþúþüþúþþ þüøøôöòðîðìîðîîòôöøúüþþ   þþüþþüþþüþþüüüüüüþü  þþüþúúúúüüþúüúþüþþþþüüþüþüþþþþþþþþüþüþüþþþüüþúþüþüüüüþþüþþüþþþcrossfire-client-1.75.3/sounds/step_lth1.ogg000644 001751 001751 00000022063 14165625676 021703 0ustar00kevinzkevinz000000 000000 OggSJ0‰]‡ŠtvorbisD¬ÿÿÿÿîÿÿÿÿ¸OggSJ0‰]:y§:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿqvorbis*Xiph.Org libVorbis I 20100325 (Everywhere)vorbis+BCV1L Å€ÐU`$)“fI)¥”¡(y˜”HI)¥”Å0‰˜”‰ÅcŒ1ÆcŒ1ÆcŒ 4d€( Ž£æIjÎ9g'Žr 9iN8§ ŠQà9 Âõ&cn¦´¦knÎ)% Y@H!…RH!…bˆ!†bˆ!‡rÈ!§œr *¨ ‚ 2È ƒL2餓N:騣Ž:ê(´ÐB -´ÒJL1ÕVc®½]|sÎ9çœsÎ9çœsÎ BCV BdB!…Rˆ)¦˜r 2È€ÐU €G‘I±˱ÍÑ$Oò,Q5Ñ3ESTMUUUUu]Wve×vu×v}Y˜…[¸}Y¸…[Ø…]÷…a†a†a†aø}ß÷}ß÷} 4d  #9–ã)¢"¢â9¢„†¬d ’")’£I¦fj®i›¶h«¶m˲,˲ „†¬ iš¦iš¦iš¦iš¦iš¦iš¦išfY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY@hÈ*@@ÇqÇq$ER$Çr, YÈ@R,År4Gs4Çs<Çs6¬ŽpR4XhÈJ 0†1ƘrÎ9¥”sÎ9”H)ç tNJ)=„B„”z!„B))õC(!””R뱆N:¥´Ôk!„”Zj©÷2¨(¥’Rï=µPRj)ÆÞ{K%³ÒZk½çÞK*)ÆÚzï9·’RL-`း`Ãê'Ec…†¬bC BH)¥”RJ)ÆcŒ1ÆcŒ1ÆcŒ1ÆcŒ1€ V°+³´j£¸©“¼èƒÀ'tÄfdÈ¥TÌäDÐ#5Ôb%Ø¡Üà`¡!+2ÄQ¬5Æ^+b„’j, AŒA‰¹eÆ(å$æÖ)¥”“XSÈ”RÌYŠ%tL)F)¦BÆ”¤cŒ)tÒZÎ=·TJ € À@„ÌP` ¤€ÂCÇpKÈ(0(ÎI§ @"3D"b1HL¨ŠŠé`q!246Ò.. Ëtqׂ„ P@N¸á‰7<á'è•:xH6€ˆhfæ8:<>@BDFHJLNPRT>’ "š™9Ž‘’“”•@@OggS@%J0‰]ð“*”ttyÿÿfÿ£ÿ—ÿ¶IJ{ÿ§ÿºÿ¸ÿ«üݲÉ>óèM~ðIÓ²²fuIæd\Émmì€! X%N‰ˆ‰'Ü$EµDlM«½cí:fošö¶¦|šãzåCý²Š:´uhoš¶¶æ¤ýŒöVÓê" ïš™ÓyNØN8ð‹×5 s½«QOÌNŽ\ç8û“PÂc.ó œýI(á±+kÖ¬¡¤ “#ÈHÉ$AÌ",d1š¦h”˜a¡8‰8h&4D„±7,ö¶˜Û¡½é„ÅC{Ó^­vâÀÄ«ÕtÜ·C‡ÕÆbëã—ÕICÓëø“1:§ôÁF ·mIh¿/6b¸mKBÛ°»UŠadE¤”ÇQʧ¬KââEQQ¦i¡8 ‰y”Ú:®Nþ²··Ó)lmm€aõ—˜_V‹½6 ;ṵ³7-¨aX}ø½ŽëÞ„ïKYÙ²ÒFÅ+õ#%ºdºBî; ¼= Ór?4dð½”EeY”áˆÝ=Å<•ë´%l©ŽIÌb€À0Bpyp-". "BZœ!ˆ ;GN`1­"¦XmM±:´µÚZM[[«Õ´ªi+vØš †p&Çf8Â\9˜CAAÂâ„w9Z†Ë‚1ÀÅc®aÈ‘¯O3ǃk 9ŽãÁuM`æb®Ë8Ãx€!¤×1’‘ô 0äz 3×5×k˜Ép<`t:]X:úÝ:::,xD?u ! ¡ péj!2õ.—wD]º -ĉ€êt0ˆ# .cˆkL;V?T§ó4”Á¥'Yo ™À†: ¯g€Ž ‚Ò×z¯Ó92F-t”ƒ×Àp‘\€+Ñ€Aç£a¤ ¸Ö ˆ mD!L¸ @|”ae|.POuT‡aFÏÕ„ØCÒôð¯Pabrí1<Ç&Ô4:˜€ !{‚vâtÀÜ>ø“ ¸ƒ? "À€w3öÔâ´s'I\¸ËdŠLb“ !-Šˆ‹€™fQ1q1Z\„‹ ÅĘÄ,ŠŠcV‹aˆ­6¦­½Å0L‹€ixÌu>d®#×L޹^dæq1]øÂj.£Ó;u$”¸Â8 e$4q9õˆ¬×ÁPAà©C=¡Ä;t‚x„zHz0†ºuCø a4&²CáŒDIæ‘äHHÔiƒ ¡‘\ !] ýýnœÔx½CÀÌ„@u $.â2sñ8¦( Mƒ+d$¼qªE¡ßoBË ¯3N‹±ßFw`(š6nТHÁâÒë(í0ôUŒŽ¾ÆDƒ„0ç-]x4F¥?1BáÙˆ£¹t `Üf4zL`èkðCkAß°h€À—2BZÀI ƒ’„ ˆ1†a‚g$€B^È‹TL¸…¼H5À€}0ºéav˜ÛMÎu5±Yq‹Å$I1hš'¢L3-„ˆ8E‰ŠˆB ´(!¢¢¢ê@Õ4ÅÆÆpÂj±qŠš6v6V‹EL1LŸò¸^WæÊã‚™ãÇ#aæqäЈ0”1¤ y\“p½rÄ0mUÄT1 ÓS˜É‡c& Ã%ŒŒaœaqâ2$3¯¡a"T~Ì“\3¼’+Ç1¯‹0àÓ䆙Ñáà50Iæšô$¤ psÍ×5ùð¸˜Ì<€ ^óHhÆÄÄ„p]È‹G˜aHàâàuE’„dp„Èa¼#xãô.o¼ÎtÞøðj\Þåˆxý˜0Á0"ZŸ‘D…!‘;ú±?Ñt…kŽ0“Œ!zãõÐbC£,¸¨7 .ê]ºÈŒQO t TJ,Zºúj ]NŸ†#Bá"^G¼ÎeHúê!0bíLÄnÐ~‹\ŒwDÏÄ&†g10Ñí!zÀÂj]“µ±ÄŽ~ÇÐ"HHÀlÐt‹4„~ÇÀÞàÞñð€w¸w”¡Šˆ"Ér1O®Ë¥]˜+)NJ,;r@‚¤$)¥”’I¡¨-d ­ªŽ‰Z Ä*vˆ†Š­ŰwÔj£*VÄÀAÄÉɧãÁ‘ ”1Rd£×qpMæ€ÃL.f2¹> †drå1áu\8®œ‘,ú0‹^g‘!2 "¯‹ 0W¯7:1yâõ$üzïf’9^ ×1×uÈ+—1Âpz2< f:ã=õÔ¡a„ñŒ:ZëvãÐy½!ŽÂ}ÝØô†úM$8®Àp1| 3F ’N)‚x—^ÇTgôÆ¿ÆI 7`@½Ëiàxább¤ Fº-öû± ‹ÆûP>ª uy舩§PÀè1àÅ0Öƒd‚‰¬uêû† ê0„(¶0µ€ŒØŒZ"º#3Ž\ÐG‚6FägFw"HÞ©#aôT´zÒ€@5ÂÇÀtXãp€ŒE‹NãHŽëqeæ•#\ä"ðáà€ë˜WCò¸®ydŽG$òÈf®cÔV ºÎð¹x sñÈã&„‹á5„'œ1aôa±àÒ›0á#4L¸=’ž†rÙå™=¡Æ‘Ñ;I»'z¸Ãë]Õ ãÒ½ž2QãÈMOL€w>"ÞaÈ0t˜p¼& úÝh€‚„RC¬ QëŠd˜)¢ ÷BJ:tQäÖOi Ql¡«FG4:pBÇl,z¡ƒ&‚úȰÐýþ®0¦ÚðKÑ1ÑBTcˆUh$§#€ ? ¼å4%µ  Þrš’ZPEÍ(C3f& #1¤¯aæÈLæ1aæ !]#ŒE8ÒE2¡Œˆ0;´Ð¹iº=F#0&âD¼á<(IÆ7œ'%EƲšY]–¤”f,iRH&W(£ Æ¡N®™G®áóaq½È‘âC#…:gH g(ƈB_hîÀÌétPk›`ætº ¨µM°Ó²*ª”Ene¶ ›4bWäY‡,!„”‚…¢bL‰RâDDLœ& L‰ ˆ˜¸-Ê„&Dc¨@œˆˆŠA¢ì&tg°¨8´µØ9rÜÎÎÎÅÆÆtd'aÚ6?áOŠéCþ•× 7e^M¡”åüUAåÞ¥qBÊrþª rïÒ8!Ó"«+ŠÈ"g—êd'¥Ê I‰@T„bQQBsÐŽ@@;t`švN8°µØ[0œ±µ8æÀ1«¦Ø‰ÅGvb`ÚÛª½C‹bo5,X-NŠCÃÅã‘W29rÆ«ã²@æS¹è€/̧r ÐßO%‘Y&…(SˆITØÏ4ÄN®;ÝâXÂáÐ¥HD€>‡á²JX„árÁpù@L(.J(‡8Íb¦agcµµŠa£ª&¶`1ÅÞFmÅ•ÇñáÓ¼òÈÁ\¢ ƒF†Çqäâºæ88æš áÁ áË!a^3ó!ÈÁ1äz]9räš×ÅÄ€È@øLÏ œ H äA† \×u‘ã˜ã‚Ì „^C®3¯áȃ¹8àxÍë"×u f˜"Q¢‹LõNGº>2µÆ8®¹®09æ:^“Ó{ɇœè±éGÖ…F‚Î;4 z‹4$un!¬.O-è½p(„¢€êôIŒEo¼ÓFGŒ+ÎPÓÕ1#00xcœ"é %€Óa‚¾ >Ôit&@)ôT·` 3SE˜Mèˆ}b\±ƒ0B j“…0©O‹hýƒ†: ’Ámõ2±#öiq“cšÜZ›4Z+šnœA v=´~Öc ìðõ(þ‹Œ²¢ª,2”2Lž×Ý=9çº\ˆpD´$ˆ$ IB  [G6Ž9°ÅÖêÈbuäPm0LllÕt U[Á4óx‘<`ŽäÓë0Ì5ä5DF±Ø˜ÌãõáV5«aEÔNÅ4ðz 3.à•+<®ãõÈ•×3×ã8®™Ìõ!\ÇQÁq1G^á¯d®9ŽaF*äSÅA˜/|:ÈJ?®ëÈ—ÕÓDÔêl(bàzL˜/× ¯ãbÆx=£Î‡RIV`È•Ãàb@$XYò 3íÖRÒˆC seÈ+²¨ˆ"ŽVáõ…€H¿«Âd€ ÃcÖ3 pâõÞaÁ;¦c´0ÇÌ+ÌpFèYC­cð®aB·ßB7À1áÌ@&$ ™OaÈ@ŽO@æ4†"ŒžÂPD8½1:'C†ñDOÂDƒ'0b·õ q:¼SïC.›ÈD¯ƒäzèûñ< ¥#vÒ·F£oâ“V¬Œ€ ¡[áÒÁ˜RiÝØÑ:L¸ $\g’3ÊuÛ xZŒWˆØë@߀C€þåƒt˜&Ð}ù & t2ò0IóÔÓT.®ÒiW±+À¢ Å)JTT ¦A‹ˆ‹‰R4ÅŠ ÅLÓôÛ;CLÓP¬6TìÅ!¦½ÅÖ¢``Q{;_jˆ­ÕbQ™ù0Çd†ƒ¼†ðÊõ¸˜ÇÅ•p½¯Ì13XÄÄ1 {‹Š!Ç̼.&ÇÅ µb¨½!5UÄLffŽð‰#¼òÈ5Ifà"yB‰wèCœ«^®Ç$WæÈõ ãáÓWøœz‹>|$ #‰¤3úˆHa1Ç<˜Ìq É2 ¼&¯ƒõ >¤‹ï õat‘ÍE5#+™ä8^¹ÀS‘ „ƒ«‹¬·h„RÉ».ÅS0/Ès\×<®C ™ׂÞGDX`E‰c2Ç^äÀ!C¤v½#cÀjàZ5v½Ë¢Ó<–@;’c|º!™9æŠÑ oAGÞI<ƒ ޢˢ:'#©ˆƒž0‘ú=SÔë¡÷¦Ï Ô`÷ŠÐBL€¦¶èða„f8ŸP÷Þ‹­´ ú]õ½{t†ZB‡'n?jŠHPVÍ^拲Þi„ÆLW拲Þi„ÆLw¬HªT–J{@ÐÕΕ몪8ç’˜…#RBJ! ‚  A˜A‹ „b,nçÈ0ÄÎâ¸HV[;ÊE°80íÄ´³³Q+xðÊÁ#3™y¯\k¯ÒñÂÅãÊõ Ãë1á Õ…ad éò¯cȇkfÈÌ•ƒ\ ¯ãyWïbÄ2¡ ^3É×L†O€E=i†•2º2¹æx>$̃ס/RP$膂RưzJ̓Ç1sèIàš¼˜!ÀÀÁƒY›×äJ†yef€ã"³ÈNBŽ#|w0pª aA‡FQÀÆ 0W!=#¼+ÐgÇ<Èdf,:2‘+Å0ÔI ñˆl `\ Žî½E ½BB† Ed Cœ2 /à5ÀPWHJ-“™aB&4…Â’±:­)\4n2@ºv-ÀÀ{= ©×—;ÂM‡.'ð:\­#ìé<áÞ¹‘7Nè} p %.—ñÐâ³8Áp@gB „´ÂÐ+k3×L2:„ôÀC„OggS+J0‰]õðªƒÿ¶ÿž>æK´ì &ðùíÄþ 9Ç4uWWÚ9ç*å\I‰,$0ÓD(&*&B‹R„ˆRvêÀ‚c¬þˆlíý؆#¬,Ž9a±±µµ8®®9’0ŸŽÇãS^L,¦Ø‚)Bá¯k®GÈc2p1C×5Éõ:È\ á‘kãÁ5ÇLB^ðâbr\™™™„yÌ\—Zt†ÅG0^’Q†yÀä×A®$Ç•ƒk†ù4Ç09¤z½NG,ŽôŒíà ¿Eu~ Ir…×ÅÌ\så8Ç¥s10 Á$ó¸fàJOBFõadªÍL^À\:2 KH7†@DÕumÌ¡0ÓGDè-§ðF ጡÒuÃ<˜crÅH BB§wùHXj˜J@aœáór=^9†ð¬Li&rt5 (ê¡§0a,&\É5]â„E8 ` \U½ø ¬6¦^à/\Ä¢=À ÛFt;Ïöö•øCo›(лájôÞ)}H‹´ß9¼“„ñpöé½CÒýþ³îètå(øÐÉSÝ8ÁÚ=€|r5sÖÖ¾LbB ¬a Å4„’„5á8˜.Ý@wO©xI³™8l$`JT”*Ñ´Š3å%7Iq!¡EÄ„qq"B±TB1q/„"âb¢ƒp=^ÌãõÛÈ`Ž«pý^_^ÇÌãÓ‡O^Ç9®³r\¯c2ä:®ãõxC&L& -Žëx=^+É0Çkcoc51-¶6¶6“®Çëq…9¥,€Îð…Ï¡Óèû»9®Çë¸Âä:nmΨqBÖ°Z„ÓiÂXt…Ï!gø“ÉdŽëñzÌA!Å´ØÚÙÛ˜…“½>LXÃjQygøÂ>‡ËÐëEÒëméàåz¼W˜J§”‰úð9‰Ñëõ¶¨w†ÏItãèëÎü~_ëv»p‹‡Nb:†Uïtrt»h{>Ýn䌾`ÄV‹Ý®ßßÔ¼ÓyƒSêÃj‘z5úaÍ›el'Ì%W±þ&o›ž*èÜÞú¡7þþ³4‡>¬ÖŠ áÃ×e"›íÿ0ôBŸ±õì­ÀétÊÔ1¬¶úQx+Ü'crossfire-client-1.75.3/sounds/phit2.wav000644 001751 001751 00000030014 14165625676 021042 0ustar00kevinzkevinz000000 000000 RIFF0WAVEfmt +"VLISTINFOISFTLavf54.63.104data¼/þþþþþþþþþþþþþþþþþüüþþþþþþþþþþþþþþþþþüüüüþþþþþþþþþþþþüüüüþþüüüüüþþþþþúöøüúüúøúþþþþþþüúøððüþöøúôôüþþüþ þúöøôîðøüúôòôöøúü  úøööôôôðîðôúþúööúüþ  þúøööôòðòöøöôôôòôüþüþ  üøöôîðîæÞØØäöþôêìðòôø   "  þôöôèÞÜØÎÐÞêîêääêðìèòü  "" "" þôðêèèÞÚÜÔÌÐÚäêîòîêèêòúþ "*&$  þúöôðæàâÚÚÞàÞÚÞàÞæðòòððòòú  &&"$$$""  þþøìääâÞÞÚÔÒÎÌÒÚàäèèæäèìòú $.2.,00($$$$"  þøððêâÞÜØÖØÔÌÎÔÒÖÞâæèèèêðøþ (464660*,("$$ þðèêêàØÜÔÆÊÆ¾ÂÎÚäæâÜÜàäîú  ,:@<<>:40,(,0*"úìÞÔÐÖØÒÔÎÂÂÆÀºÂÐÚêøðîòôø  (2>>862042,*&""  öêèàÔÖÆ¸¶¬°²ºÈØÖÌÌÒÒØìúþ$<JJJH@488446.&$ þîäÜÜØÌÄÀÀ¾¼º¼ÄÒÞâàÜÞæðú ",<B@<<6.044,&&"þôèææÜÒÎʸ¶¾ÄÎÞæÞÔÞäâæøþ $4>>>>800000*" øèàÞÜÔÚÚÎÈÌĺÄÊÊÐàðòîððöþ" *:8066.(,.*&" øìâÞØÔÐĸ²°²¶ÂÐÖÐÎÒÐÒÞðøü.DHDDD<4880**&  úîìèâÚÖÎÊÈÄÀ¼ÀÂÐÜêêèææêîôþ"*46:::2,*("$&  úîàÜÚØÒÚÞÎÔÊÊÈÆÈÜêîìîôìöþ$,,00.*&&&&$"òìèàÒʾ´´´ºÌÖÔÌÌÆÂÊØâìöü *6<>><4.,.,*&"úöèàäâÖÖÖÊÊÌÎÊÈØæêðêæêìôú $(***&  ôììäàèìèêäÜÚÒÔÖÜèöööôðöøú " """ üôììäÜÖÐÊÈÌÖâêèÚÔÔÖÜèôöü&(&(*"   øðòèæèæââäàÞÖÒÖÞèòôðòðîòúþ  " "" üüöîðîææèèæâèàÜÖØàèîôôîêðøøü   øôðèææèääÞÔÒÊÆÊØâèìêÞÜäèðôþ"$(($"   üöôìììêìêèäàÞÞÜààäâÜàèðöüúöôôú  ""$  üøöôêêòôòòôôæäîäâîðäâìòðüúööôôúü   üüôîòîèììêâÞÚÖÐÎÐÒÚàààäèââìòðú""&$$öôôðêðôòððîêæêêäêæîèäììîìôøòòöøúú "$&$$$  þþþøúøôòôòöêæêîòîêâäààääæèìèæììîîòðòøþ  þúöôöôîòîîðòòîêðòêðîêîèêîêêìðöòðööðø  $&(***&$$$  þüüöòôôòööôöðììèâèêêðìîêèèèìðìòüü " úöôòììîêææääâàäæääæææâÞÜàØÚâàâææâââäæèìðöúþ  "$$$ úüøöôüüúööòðôøü    þúøöúòîðìîîîîìêèæìêêîìèæêêæäääâèòììæââæêîòöúú   úüúöôôôðêêîîðîîððòððîììðììììêäèêææèêêèèððòøüþ $&,,(*.0,*("""  þüøüüüúöúüôöüôìðððììîîêèîîèêòööú "$&& ""  üüúøúðîòìæêêææääææääâÞÚÜÞÜÚÚÜÚÔÒÔÒÔÖØØØÚÜÞàâèîôúþ  "&&&($&$        þöôøøöööòòôòøúú üúúøôöøòðôôòòöòòööôøøöúúöøøôööøöôòôôìîîîðòôððòòöúøþ  þøòðìæèäÞÜÜÞÜØÖØØÖÖàÞØÚàààääæææèêèæèêêìîìèèèèêêîîðòôøøúþ $(*.2246664400.,($  þþüüüøöøøôôòðòôððôòòöúøöúúþ  þþüüüúúöôööøôðòôòôôòððîððîîðîììêêèêêèæææææêêêìììîìòôöøúü þþþüüúúúøöøööööøööööôööööòôôòòòîìîðìêèèèäæèäàäæææèêìììðòòöüþþ  "$$&&$&&(((*(((&((&$&$ "  þþúúøøøøøøöööôôôôððîêêæäââÞÜÜÚÖÖÔÒÐÎÎÎÌÌÌÎÌÌÌÌÎÎÎÐÐÒÒÖÔÔØÖÚÞÞÞâääæèììîðòôôöüúøüþþ  """""" "  þþþþúúúúúøööøööööôôöööööøøúúúúúüüþþþüüüüúúúúúúúúúúúúúúúüüüüüüüüüüüüüüúúüüüüüüúüþüüüüüþüþþþüþþüüþüüüüüüúúúúúúøööööööôôôôôööôôöööööööøøøøøøúúúúúüüüüüþüüþþþþþ  þþüüúúøøööôöôôôòðððððîðððððððððòòôôôöööööøøúúúüüüþþþ  þüúøöôòðîêèæääàÞÜÜÚØÖÔÒÐÐÎÎÎÌÌÊÊÌÊÊÊÌÌÌÎÎÎÎÎÒÔÔÖØÚÚÞààâäæèìîðòôöúüþ  """$&&&((&&&&&$$$$"   þþþþüüúúøøööôòòððîîìììêêèèæææææäääâââââäââäääæææææèêêêììîîððòòôôöööøúúúüüüüþþ  þþþüüúúøøööôôòòðððîîìììêêêêêêêêêèèêêèèêêêêìììîîîîððòòòòôôôöööøúúúüüþþþ  þþüüúúøøööôôôòòðððîîîîîììììììììììììììììììììììììììììîîîîîîîîîðððòòòòôôôôôöööøøøøúúúüüüþþþ  þþþþþüüüüüúúúúúøøøøøøööööôöôôôôôòòòòòòððððððððððððððððððîððîîððððððððððððòòòòòòòòôôôôôöööööøøøøúúúüüüþþþ   þþþþüüüüüúúúúøøøøøøøöööööööööööööööööööööööööööøøøøøøøøøøúúúúúúüüüüþþþþþþþþþþþþþþþþüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüüüüüüüüüüúúúúúúúúúúúúúúúúúúúúúúúúúúúúúüüüüüüüüüüüüüüüüþþþþþþþþþþþþþþþþþþüüüüüüüüüüüúúúúúúúúúúúúúúúúúúúúúúúúúúúúüüüüüüüüüüüüüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/squish.wav000644 001751 001751 00000017134 14165625676 021340 0ustar00kevinzkevinz000000 000000 RIFFTWAVEfmt +"VLISTINFOISFTLavf54.63.104data  æÖü2äæÖøúô þ8ö ¨$ö ü üþÂô ü üü>Ôò¸(ì òÂð þ&® þ &&ªüèò ö&.²òÜ ìø( $®ôèò *òºø þô>– ôú DÒÐè XŒøÞ î "üüò*ÀÊ6 ö’ òb¬ìÄ,öþ48€ø n¸ö @ô2>€øøj¸æ¤:ð >.€þ&lšæÄ6î Xì€8üü .`€þæ"ô v®ú‚Nøú"Pò*€>üø"(2€ê þjêÌÀþ´‚>ô^öþž ø\îà´,V€ì6 ìð¬P>ÂèÒF$ðø¢NDªþÔbôÀü@š(d ¶xì4DªèTöÐÜ:*àÄ DÈÚ<*àÂ<öÌôLôâÔ\âüÄlÔÎ\Üè,úÀ>ü °ZêúÔDΰNðþÊDÆ ¤TôþÎ> ¾0ª^òâú&¨^èþÖHöºLæÐRÜÐNàÚTÈèJÐö6ÂL° Ø4¢BØÄFðÆPÒúöì>À 6¶* ää&þÒLÔð<ÊìÞÈ8îØBÒþ&Öòðä(îð,ÖÐÞ$òðì øúðîîø"à Üæ"ðøî ôúüþø ôü îîþðòüê ìôøþòò úþüúü ú òò þö öü òò öúþ òöúþþüþþúþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüüþúøþòüøòúöò öüòìòöêæîøúôúþú öôüèàþæìöæì øþúôè â üê&êþä ìø þú øôèÖØ&òè&àæ öðä&îô.Ö "Î"à&öúúþòúÖÆ.úÖ6Þô$ÞüþàÎ:òàBÖ*Øô ÚÎ>àä<ÈØþôÒ.üÔHØö6ÐôØ ÂFìÜ<Úúúø(Ì*°6Ì.òþòöÒVÄöBÂæ4¦<¾4ôè,üÀ`Îò.îþêF¾D²Ø4œDÜ °ZìÌ8ôÌZÒÖTÐêFÀðZ¸þ8¸ N°,°"2²$ª6Â"¦FàüªFöþÚ4Â.þ ¼Löè ¾BôÊHøÚ  ´JòÆFúÔ¨Fö°Läà0"¼ <ž$Fš$8¨"Àô8ÜÒNøø¸Vú ¢Rþ"D>Œ.X–ðl¬ÔtÌþ¬lðŽDPŒæxÄö¸Tª,,ò®b°ü°lú,:¼îàZö(’8 ÀîÖXü0¦ö.2Ô¢T&²ø,(žø 4ö €>ôdÌú¦6öxºèÈ$Vô¶æ þZ¢úÒ $Bâî¤,ú ^€úØ(î &0ôôôøZÔÞ¸&ò Böܶ$ôþúFÜìÆöò(ìÊü ,øþ´øþ"ðÖæöþ ü ø" Àþþ (òØ ü Þøðüúø úôîúòþþþþþþþüþüþúþþþþüöüö  üúìôìüüôÖþ4øüþäþÜ>öòöøòÞòüüôÞüìBþ úôòììú8úøìÊ( 4èö ðÜö>øðêàú.üþöøÜøöF øøþÜøàJê úöÞøÒ<&æ üôàúÆ6.æüöâúÈ02âüöâúÂ24äüø âøÄ:2âøüâîÒ> ê ôþääè@òðîêÔ0 øî ÜòÐBêþî Èúà\ðúøÂ Pú øòÚÞ<þøê´Pî úöæô¼82ê ôøìÎ2(üìÔôÊT ìøòÀú NúüðÈòVþüúæª6@æøúüèÌþ<*þê ÐòÄdîöôºüJøúî´\î þôäô´F*ìøþöêÂ,,&î üìÀúâlöúòüÞÒHþþúè¢0DÞüôæØöD"þðÒôÌjð øò¸Bðúî´ Xèþôâô¸J"êöþôäÈ,.ð þìÀúÞföôöøîÆ0*øþþî®LäþòàðÄJð ôôäÎ&.öîÆøÞbþôüôþ¼@ôøòÎê@öè¶&DêüúâîÐ<&î ôòæØ4úîÚîÒ8ðþðÌøäPð úøþÌNüöôüêØ&,þúîÔð@ þúì Hô úøê Fè öúìúÈ$8è öþðòÒ&(ê ôøðèÞ"îôøöäê"&öööøÞò( öôòúÚò*øöòüÜð. úøôþÞì*úüöäæ &öüöþìÞ*øüøþòÚ 8öøøúúÚúòBüòúøàúà>ì öêüÚ$&î ôîúÜü(þþöôøìÞ&ðþþúüÜüDöúôæøâ.ðòðòìô(úúþôÖ 4ìúôêòô0 üöúêøê6 øþüòÖ .òöôúøÚ ,ôüþþøìüÜ,øöúøúÚ "ð þúöèôî. üöúðþØ.îøöôæüþþúðüÜ&ööüøÖ.ðúøúìðü*þüþöäø&üþüìüÞ,úøüøÖ0òúúîøè0 úüøþüâ öþüúúêôüüøôîðþþúæú þüöøàþúþøìòô" þøàü úüúøæ  üúôìøþüþðä úþüúôöæ þþüêþì(üþúàþò"þþþøæü üüüðî úþúþðúæ úúüúìþè þüøòúþþþæú"üþüþøæüþþüþþøè üþþøäüüþôîüüüöäþüüüøîüüþüöêþúþèþþüüþöò  þüüþøìþüüêþþþüþüðþüööüüþüôüôöò þúî þüüðþ þôú øþöüøþüþþþþúþþþþüþcrossfire-client-1.75.3/sounds/drip.wav000644 001751 001751 00000003724 14165625676 020762 0ustar00kevinzkevinz000000 000000 RIFFÌWAVEfmt +"Vdata¨ÿÿþÿþÿþÿÿÿþÿþÿþÿÿÿýÿüÿþÿÿÿþÿþÿüþþÿÿôÿõööÿÿ#(ÿ#ÿòÿÕÂÿ·²ÿ·ÈÿÝúÿ8ÿSnÿ~þ~lý]:þ Ò¨ÿƒ€€€€€†žýÑý?dý~ý~ý~xþGÚþµˆ€€€€ÿ›¾ÿéýElü~ü~üyVýè´ý€€€€ÿ¹èÿCnþ~ý~ýk4ÿÈÿ£€€€€ÿ‹¸âÿFþiÿ~ÿ~\þ'ö¼þ—€€€€¦Òüÿ6û]þ~ÿ~Xþ+öûÁš€€€ŠÿµÞþHþmþ~ÿm<ÿÕžþ‹€€ÿªÞþ Bþoÿ~b8ÿùÊœÿ€€ ÿÃôÿ)Pÿ~ým:þ Öþ¡Š€„œÿÃúÿ%ÿYzÿ~þ[6ÿû ÿ‚ý°ýÝýGhû~~þa@ýͪþ‡†”´ÿÝþCf~z\8þõ̤þ‡ýŸÄÿó*ÿQpzücFú Øý³”ÿ‘œÿ¿ìþ!Püktýc<ÿ Ò´˜–þ¥Ìüù*ýWhÿmRÿ%øÿè˜ý¾üåDþghþW4ÿÿÔÿ©  ÿ»æþD^hT,üÊ®ž¬ÿÅô$Hÿa\þ?ýç¼ý¥¨ÿ·æý;XýWJ"ÿñÈ´ÿ¥¾àþ8ûMXýEÿïÊÿ­°þÁäÿ7RÿQ6ÿåÀ²þ»Îüý$BÿQ@þ!øÎÿµ¼ýÇôý:NþA&þýÔÀÿ·Êÿï8ÿG@ý!úþÓÀÀÔÿ÷ý=Bþ5ìÿÏÀÿÅæÿ%B6ÿ%ÚÿËÂý×þ9<û#þáÊÎÎÿ÷(B"ÿñÆÒÜÿí"(ÿ1.þùîÒþÇîö:ÿÿ%üüÓàýÉðÿ>þÿÅÞêþí.þ$ÿâîþÕÔþ ÿ+0ý Öÿ×ôâÿ! ÿ)äÿíäÿÑÿ!0ÿõ Úÿ×ýé(üþØÿëìÿß"ÿ"þäýÿÖÿíü2ÿ þþËþüõ.ÿýòÿÛýáþÿßúìÿéþÿ ÿéþÙýþ#òýìþåÿùÿ! úÜÿüþ÷ ýçðþ÷ýýûäýöýþýÿãúÿüý îüõÿûøîÿúþÿìýüý üýÿìüý úÿÿðÿÿÿý øüÿôÿÿÿþ öÿõþÿôÿÿúþÿôþÿþÿþýÿöþÿÿûý÷ýÿýÿúýÿþýÿüüÿÿÿþÿùÿÿùÿûÿÿÿûÿÿþýÿýÿüÿÿþÿÿþþýüÿþýþþÿþÿÿýÿÿÿÿýÿýýýÿýÿÿÿýÿýÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿûÿüÿÿÿþÿýÿþÿÿÿÿÿþÿýÿýÿÿÿÿÿÿÿýÿüÿüÿþÿþÿþÿÿÿþÿýÿþÿÿÿÿÿÿÿÿÿýÿþÿÿÿÿÿýÿûÿüÿþÿÿÿÿÿÿÿþÿÿÿüÿüÿýÿþÿÿÿþÿÿÿþÿüÿýÿþÿüÿûÿÿÿÿÿþÿÿÿÿÿÿÿþÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿþÿÿÿcrossfire-client-1.75.3/sounds/sci_fi_gun.wav000644 001751 001751 00000123022 14165625676 022123 0ustar00kevinzkevinz000000 000000 RIFF ¦WAVEfmt +"VLISTINFOISFTLavf54.63.104dataÂ¥þüúþø þüü úüöúîøîîüþ þðîþ þúææ î Úôâ(öê"ôøîò0Ú ö(ÌâØ$ Ò0öþúþÚDÞúüþð8Ð,ÖÖ(¼.øø¾HòäÚHÞè@Þü*ØúH¼ì4®8ܾHþÌ<ôâ>ìØTÔ äìT¶øô@¬.Ö ¾@Æ8üÜ<øÊPâþ*êÞZÆìøLºîü2´2ÖÄ>Î4üà>ôÖJâú.ææRÐ èüF¼ð 4º0ì ¾Bæ ÎJðæ(àHàð6ðò@Ô4Þ0Î0ÔÒ""Ê(Ü,Ì4þæ4Ö@òô0òâDäþ,æòBÚ &à<ÐÜ0ÌÜ Ì(Þ,Ò. ä2Ú4øè:ðæ6ôì>âö0ôô<Ô,ðü:Ì"ð6Ä"òþ *Â0 øþÆ8úø"Ì>øò,Ø@ôð4òâ:ôì>äô.øîDÖ"úòFÎì@ÌÜ2Ò*Ì"â,Ä,øø(À0 â&Î(Ð8àÆDüøü" Ì@úæ6üÜ.ÖHìòÔLêô4ðä:öâHÞöøâJÞü6âî:îèLÒòìJØ þ6Úþ2ððLÊ äøDØ ü:Ì (øúøH Ú<Ö þ<Äì@Ê*Ì*æ>ºÞ6Î4Âüî:Â&Ê$æ8º& Ø.Î4¾&ê4È&Â&òö 4¼$ Ê"$â 6¼( Ö(Ö 2º*à.Î.º,üè4À ,À(òô8À (Â$ìö :¾ (Ä "îö<¼(Ä$ðø@º.Æ&òôDÀ2Æ&öîþJÆ:Æ$êúHÒ øBÄâôDÞîNÄ*àð>ôäTÔü:Üì,úÖVÞæPäðúÐFòÐTèöø2üÐ0ÀNöÖBà º8¼@øä(È .²2Ä*èò:¾<´ Ð6âúúPÂüFÂÞðDêüà\ÒìNÚô&òÔ@þÄVìÔLöêþ* Ä( ²@¾:öâ"*Ð<´ :´Î4ôîîPÒêXÊúDÚîôÐ>ÄRðÎLúòè4Ò *¶&0². ¼ Ü>ÜüôRÆðRÄ>Øî"ôÔDúÆVìÐLöðî4Ò&¶*.®0"¸"Ø<àøôTÊîRÆüDÖð"òÔ<ÂNö ÂNøÐ< æî$(Ê <¶>°.¾ $ÞòBôöÚXâÐ^ÞÚRîîô6и(.ª2,²(Ä*âøDäøâXÔÜ^ÖæNèìü6к,(®4*®, ¾$Ø>òòæRÜØ\ØÚVäøèFúàþ,È*´ :®">° 2ÂÚê8öÒJúÀPô ¸Nú ¾B Î* îâ8ÜôøPÐæ\ÌàZÖþâRèôÞDòÚ2ìÞ,îâ<òêèDöúÐLú¾D²:,ª*:°þJ¼öNÐüìNæòâDîÞ2ðÚ*öÜ6þäè:ôÒ8 À.´"6´J¾îXÌÚZàÆTò ºD°0,²>ÀFÖöòJîðâ>òÔ.þÎ( ÎþFìÀ $(ÒÆ. þÈäLÞÚLæÔú, 6ÈÜ2¾ ð4"ò¾ <âöÒ:2ìÚüèHþÖÞþLî ÎìFÜÐü. 6ÌúÜ 8&Àüî<ø¼ :æ ¼ 4ØÄ ,ÌÒ, &Âþâ8¾úò@ôÀøDìÈîHèÒæ&HêöäÚ4>ôæòÎ80ÔÌ4 ÆÐ&(&ÄþÞ :.ÎêðòH*èÒàD¾Ú.*"¾üæ@þ,ÖàüæF ÄÔ2" $Âþà>4âàøÖ>$ÊÊ( :ØöàÞ48à¼:âÐÞ úDø¶ø>ôÔÚèDÀþÜ:4ðÜúÈ(2ÞÔÜ"ü<ö ¾úþBúÆØ, 2èèðÌ$ "0êÖØø8 Ìêðî6"ÜþÖð 6öÄðþ< ÒöÚú& 0ðþÌð6 Ôîäö&(òüØâ, âäìæ &þúæÒüø*þâîØ*þÜæðü"úðäØ(þâêÞü&þäàîö öìÚìú"øêââþ"êäàô"öâæè" üîÞæî  øêàêö"ôêàêú"ôèàèø"øìâèô üòÞèì ôæìÚ ""ØÈ6 ÂêPÞÒLèüÐê0>ÌôØ<*¸ôè<ð° >â ¶ 6о 2ÆÐ0 .¾üà>*ÀòôHø"ÊâüNüÞÌðHô¸ð6$ð ² ü@êÀêüJøæÄî@ú ´ôBðÈàðL¾ à&0(ÆìðìB*ÌÌ" :ÚöàÔ,8ä¼þ Hú ðÀ ê$2$ÒäöÞ2"ÔþÔì"<ðÂü@üÊüà , 2úäôÊ :ðÌþî0 $öÞòÖ4þöÎöö.àðÚô ,ØäòöòðäÜ.öàêäü$úàäòüþðæÜò"îèàê " øèäæø îääêþ   þìææò" úêæäò  üìæäðü òêäêö  úðäèîú øêæèî öêææðþøîææðøöêèêðþ òêæêòü ôêèêòþøîèêîø òêèêòüþòìèìòúþôêìêòö  úîîêìöúøìðêîøüøèîêîøü úììèìôú þòîèìîö üôêìêìúþüîîêêòø øòìêêðüþ  úððêêôö øôîêêòöü úöðêìîöú ôòìèòîøþüôîììòòþþúîêììòú üôêîêîøú öòìîêðúü þôðìêìøø  ööîììîöø  ööìêîðôü üôìììðôü üòêîêîöþ üððìêðôþ  üòòêêðòø úøòêîîôø üúðìîìðö üîðêêðôü  þôôêìîòöþ þüôêîìðòü öðîîìðúú  øöîìèðôøøøîêîìòúúðîììîôþþ  øôîêèðòúøöììîìôúøððììðöü  þöòìêêòòüüöìîìêòøþöôîìêòôúúúîìîìòøþöôîîêòöú øøîêîìðö úôîòèîòú üúòðèîðòþ  öðììîìüüüôôìììôòüüüòîîîìôüþ  øöòìêðôø  þüöðîîððúþþöôîîæðôú  üöðêòìòöþ øòôêììöøþúüòîîðîôü  üøòòììòôøþ üüðîìîîòüþ þøôòêìðöøþþòðìîìðüü üöôììîðòú  øöðòêîòôü úüòîîîìòú  üööììêôòú üöðòìîîøú  þüøòìîîðòþ üööðììðôö þúòòîîèòöü   üúðîìòêôø þúôôìêîðôø  þøòôììèööü   þøôîîîêðö  þøøîîìðîôþ  þúöôîêîòöö þöòîðèîðüú  üþöòìîìîòü  øúôòêìðîôú üööðîêòðöú  þôöððèðòøø øôððêìîöúþ   þúøðððìîòúü  þüôðîîîîöú   þüúòîîòìòôþ  þþøöîðîðìøú  úüòðìòîòòþ þþúøðîîðìôö  üüøöîîîòìøü  þøúòðìðððöþ üôøòòêðòöö üøòôðììòôøü  þøòòððêðôüü  üúøîðîðìôøþ   úöôòøìðèòøþ   üöúôøîîêìøú ôúôöôêîêøú üöæØêè þîæÜêî öêæàìò òèèæðö  þòêêêôú"öîæêìöþ" ðìäêîöüêèæèôø øêâèèøþ òìÞèîø ðêäâôö  øæèÞðü þúèâæè þòîâèìö  üðêêæòö" öðæäîîþ  ìêàäòö  úêêâæöþ öòèêìðþ úêêæìøú  øæææèú øôìèìîú þîæêèôú üðæææîüôðìêðòü þðèææòú  úòìèìîö ôêèäìôü  øòìèêîø   òìææîòþ  øòêêêîø  öìææêòü  þúôîêêìðöþúöòðððòöü þøðêèêîöü  úôîììêðöü  þîìäìòöü úúòêêæòö üöìòêîîðüúòêäììüü ðôìîðêôö øöæèæìüþ  üîîâîðöþ üôèðêòöôþòôêðîìøø"øøêòììôòþîòîìôîú ððìèòîøøðêâìîøöîäæêðþøðîêìðö þôèêèðøü ôêææêô   öêêèìöø  ôèæäìô   üôææèîúþ úîèèèòø ôìâæêö   þîêæêòøðìèêðöþìèææòø"þôæâæêø òêäâìò  úêääèöü " øìâàêð üêääèöþ øîâæêô öèäâìö"òæàèìþ þêäàæòú $"ôêÞäèö ìäääôø ""òìàæêö"úêäèêüüæèâìø&üêâàêò$üîÞääò $îääæôþ"üìæàðò$øîàâìö" øæââèþ $ úææàìø$òêâèòø  öèÞèêü øæââêúþ$þîèàìðþ öæèêî üæêâìöþ&òèàæèø  ðèäæìø  þôæêèðþ  êìäêòú üôàèäìüþ&ðîâæêð" ìêäæòôúìèèêøú úôêäîîú " üîêäìîú"þêìäæîôðîæäððþ øêìæîðúþìîêêôøþôìêèðôþüìèèèðöúìêæèòò üììæêìôøòìäììôþ üôîììîöú  þúðèðìòú üðìèèòôþ öîìèêðöþ öîäêæìøþøîêèêîôþ öôêæêêòú ôòêèêðôþ øöîìêìöö  úòîêêðòú úððìêðôø øöîììîöø  üôðìêðòø øöìêìîòúöòìêîìöü öðîêììöü  øøðîìîîðøú  üúôòôìðòöúöôòìîîòòøþüúôòêêììôø úüòîîêìêôú þúôîðììîôøüúöòðîìòðöú þüøôðîòìòöü þøöòðêîðòúþ  üøöðììììôø  þüòðììèîòöú  øöðòèêìîôú  þúöðîðìîðøú  þüøøîîîððöü  þúöòôìððöøü   úüòðîììîöøþ  þúöôîìîìðòü  øôððìêìòöú úüöôîîðìòöüþ  úúöôîððîôöþ  úøôôîìîðôö üøòòîîêòôøþüøöòîììêîôüþ  îìØàèð üìæÚìð ôèæàèö þøæäÞìøöìæêèüòèÞêð úîèâèð  üèèÞìö öèäâäö øîäèìú þòêäæìøòìâæîúðêææòú üôæäàðøòêææìüüôèâäìøôêææèö ôîâèìø ôìèäêðþðêâìòþüîèääîö  øìèâîô øìèææòú þöèæàîôüìêæêðüþòìæâêôþîêäêðú òîèææôü þöêèäðôþüðêèèìö úòêâæîøúðèêêðö öðâäêîúü üðîèèìô üöæèèðü îîèêìîü üðêæèôú  ôðèæððüþüöîðèîîü  þöèêæòø ðìèæððúü  þòîææêêöôú úòðêððôúøöôêèèêøø  üþúòòæìêòúú  þôöðìîèòôþ  úøðôòðòîôø  üîîæèîðüü þþúôøððîêôö þòðèêìîøú üúðöðîòìöú  øòîæêìòþ þöîèêêîöøúôôððòðôøü þþøòðêêìîú üôðìêììòü  üúöððììòö  þøòðêêìòü  þúòðìèêîöþüöòîìîðòú üöòîìîòöü  þøðêèêðö  üöðìêìðøúöðîìðôøþ  üòîèêðôþþ þøîìæîðþ úúððêêðôúòòìðêðôü  öìêèðòú öøîêêæòö þøîæèæòöü üòìîæììôúîîâäêð þîèäâîðþüòèèæìöøúôìèêêôúþ þôîèêîðú øììêìôö øòèêêîúþ úîêäæîö þöðèèæîø þöîêêêîöþüôìææêôü úòðêìîôþ  úòìêìðöüúòêæèêô öîæäæðú øðêêèðö øðêèêîøøðêèêðøúòìèêîø öìæäèðú úðèææêö þöîêèìòú üôêæèêôþ øîæäæðú öîêèêòú  üòîêìòö  øðêèêðú øîèäèîú öìèæêòþ  úðìêìðø øòêæèîø  ôêæâêòþþòèææìø üðêæèîöúðèäæìö  øìäàäîú üðæàâìö   ôìææèôþúòêæèðúþôêèêîø  öìèæîôþüîèæèìú þðêääìö  ôìäæêôþ  öêèæêòþöìææêô òìäæìö   þðèâäìö þîæääìø úîæææðúôîæèìöüîìæêòúøêäæêöþ üòèâèìøøîæäìòþîæäèðú"ôæÞâèö $ úìâÞæêú ôèæäìô  úìæêìø øìæäìò üìäâæòú   úðäâèîþ  þîæâäòø þòæâäìü$îêâèîú üîâææò $øêâÞêî " üìââäôø " öîääìô ðâääðþ& úìâÜèêþ$" þìæâèöü îêâèðü "úêàâäôþ(òêààìò üðâèèô$ðâÜàîò"&öðæâöòþ  úöôîîêèêêîôøü üúöòðîðòôüþ  üøòðîêêêìðôüüüøôððêìîòöú  þøöðîîêîðøü  úöòîêêììòöþ  þúôòðîêîðôöþ  þøöððîîîôøü øöòîîîðîôúþ þúôòîìêîðôú úøòîììîìòøþ úöððîìîðôø üøôòîììððøþ  þüøôðîîêðòúþ  þúöòòêììòöü  üøöðìêìîòø þúöðììêìîøü þüöðììêêðöü  úöîììêêðøü  þúöðììêîðøþ üúôðììììôú  þüöôìêêîîöþ þøôòêêêîòø  øòìêêèìòü  üøòìèêèîò  úöôîìêîðöü üøðêèèêîø  üøôîìèîðöü þøôìêêêðô  úöðîêìðöú þöôîêêîòøþ  þöðîìììöü þøòîîêîðü  þúôðîêêðøþ  úòîêæèìöü úöðîèìîøú  þôòêêäîòüþöòîîîðôþ þúôìêìîòø øôììæêîúþ  øôîìììðø þúôîêêîòø úòìêêîðþ  þøòòêììöüúúîìèêòö  öîêäìîøþ  üîìæèîô þþöðìæìîü þüôôììîò   þúòðèêêòüöîèèèîôü  øòìäìêøþ  þüòðìêîîü öðèæìîú  öôììììôú  þüòêìèòöþôîìèêîôþúðîäææîü ôðèèêìøü þøòòêìîðøþúôêêæêôø öðîêîðôüþ  üöòðììððúþöôìêêêöú  üôðîêðòú  øôîììîôøþúòðìêîðöü þúöòòððòôú üöôîîìîòø  þúôðîììîôú  üöôððîîòøþþøòðìêìîôú þøòîììêîôú üòðìêêîôú  þøòìêèìðøþ  þúòðìîòòúú  üøôöðòîîöú  þþööîìììöø öòìèêêôøþüøîîæìîôþþüüôîîèðòúüüôîîèîðø öøôîîèîðø  þöòòìîîîôöþ  üøðêêæîðö  þúöøòððîòôú  þöðìèêìðøü üööðîîìîòöü  üöòìêììôú  þøôðìììðôúþ þöòðìììðôøþ  þüøôðìììòöþ  üøôðîîìðôú  üøöòðîîòôúþ  üöòîìêìîöü üúöôòðîîòöú  üøôòîìîîôøþ  þúööòòððòôøü  üøôðììîîòøü  þüúøöôòòòòöøü  üøôòîîîðôöü  üøöòðììðòøþ  üúúøöôòððòôúþ  üúôòîêììòöü  þøôðìììðôú  þüöôðîìîðôú  üøöòððìðòöü  üöðîèêìîöøüòèêòü  úìäâæòúîâÜâèú öêâÜèð  òèäâîú  þòäââîþ øîààæî ôêààèð ðæâàìöüîæäâîúúîäâäîü úðââäìü úîäàæìúúîæàæîúøìæàèîüüìäàäîúþîäââìø ôêääêô  øìæèìôøîèèìòúòêæêðü øðæêìòü þöêèêìöþüòêèèîôúðæææîø ôèääèòü üðæââêòüþòèèèìöòîêêðôþ ôðêìîòü  öðêèìòüþôìâæèðüöìäææîú þòêêèîòú úðîèìîôþ þöîæèêòü ôìæêèðú òêæäêîöþôîèììòü øòêèêîöú  úîêèêðôþ  ôòêêîðúþ þöìèêêòø ôðêèêðö þöðæìêîöü  úîîèèîòü  øôìêîîöþ øîêêêðøþ  öðêäèìòüúòêêèìôú  úðîêêòö  öðêæììöþ øðêêêðøþ þôìêèìòøüòìæèèîø üöìîêîöü þöììèêòøþòìææêîú üôìèìîöüþöììêìòú  úîêæêìöòîèèêòü öðêêêòü  öîèèèîúúîèææìö üðêêêðø  øìææèîø  úîèæêîø öîèæìòüþòìæäêòþüðêæèîø  öìèæêòüþôêææîôøðêèèðø òìæèêô  øîèäèðúüòêææîø þòèææìöòêàäêö  ôêæäìò  þôêäâêôòêäâèô  öêææîøúîæàäêúüðèâèðþ ôêäæìøúðæâàêøúðèæêô þðèäæðúöìæäèöúðæäæô þðèâæðü  òæââèø öìääêôôèâÞèö" öêààâòúêäàèôöêàâäö öêäâêøôèääðþ øêâÞæò"ôèàâæø îäàäð$öæÜÜäô " þòäââð ôêääîþ  ôèÞâêø $$úêààæö  úêàÞæö" þîàÞâôìäÞèú øæâÜìü ( ðêØÜèú&òäÞâòþèÞÜêü  öäâÞð üèâäî$þèÜØæö("ðèÚàð""ðâÚäô & òèÖàì ðâÞèú$þêàÔæö"($üêÚÞì$ öèÚÞò$ ìâÔêü$"öäÜÞô" êÜÚâ$* öÞÞÜö $ üêÜæð ""üîÚØìú" ìäÒîþ, êâØà " òÚää &òÚÒêô"îêÎö0ØæÒè6 èœ 60ĸB$ö¼äTöÆÜ Nо"¬ÚPÖÎ0LÈüÌ *¬ðTòòÒè:,° èTúÐø8 ®êTàüÀ(øÂJÄþÂD¾î$ÄðXä¬24Äîö0ÚææJøª,þL¼þÜJþÊ*îÀ 8¼â^æ °:.¶þ@ðÞà,îââ@ °$>²à^ܶF ¬BÊòðDüæÒ $üÐô.îÊÀþ <ÐîêNîöÆB²( 0®üFÀúäVâüÌTü²<¬ ,²DÈôøNèìæDæÚ.äÌ*òÖü:úæâJþöÄD°<þ :.œ.<¨:° 4Æì$äÒ*º6 ª<þ ž<&¤.¼(Ðö@æîÞ\ÐÒhÐÜVÚèò<ôʪ:"¢D°:ôÎ0ÀþþN¦üF¨$Äú<ìîà`ÂâX¼ö 0ÚØFôþÄhÔþÞPÜÚú¸Pêº`èìö4¶<¬^ìòÜ<º2¢TòòØ: ¼(ž\ööâ,¬ .æøÎâ þDôîòÄ ü, ÖþÂ(ÔÎ&6ÔúÜò6:àîðä<,èØúÚ>øÌÜ: ¾Ü( ú ¸ì.î ¼<æ Àô >ÞÌì"@àúÞè4<Þêèâ@4âàøäF àÐæJèÊòLìÀòBüêìÄ,>àöÈ4.üÎþÒB ôÂÜD ô¾ìH úò¼"úFêòÂ06øÖôÌ@*ðÎâNäÈ îNøÜÌ"þLêöÚÜ4<ÖìâòD.ÆîòDì´ô:Þº &ÆÄ.¸ÚF ðºôLøôàÔ6>ÔìâüFþ&¸öð6ä¬4ÒþÂB*êÌèRôÆä Bм"ºÖFêÄ"üTàøÌò2(²Ü6(þ¸&øJèèÜèD.¸þê*(èü°*þ@ìÞìðNú"¶ú,$Üúº:2ÖÜöNê²4ÌöØRü$Àö ,Îúº<,ØÚ JÞ´& 0ðÎüôRè° 0ÊúæTð° 2ÐüàTö°.ÎôÞPø°6ÔòâPú²<üØæðFôªþHæäà<ö²,HÎòÚ*$øêÆ28²ÞLÐö0´ðTÖº.ÚØ4ÂþÒPô° 8îØø@Þø¾Dþ*® öJììØ.üìÆ00²æTä¾.Òä ÂüøNÞºFþ,ªúJàìÜ* öÚê4 ¸B¼ÜZä²8(²Däèê0êÖü4ìÈ,"¶JÆþÖTæ®@,¦üLÀàRæúÀ@¶,Äö>âäè>îÔ&È Òê0îÞü2ÞÞ&ðÌ" Ê (Ðð:ØèîFìîÖFÀ@®2&¨$>¨øN®îTÀþèRÖòæHðææ6Öð &Æü @¼øP¸êX¸ìPÊôþ@äÜ&þ¼(¦>þ¤B¸2òÒ4ÊöúP²øR° *Äð2øèØ\ØÚbÌøö:ÜÐ,þº`æÎVæÞ ²Hô ¼Xðèø,²<ø ²Vòäü* ®Hò¼NôЪZèöä:úºFòÄXâØ ºbÔò(îÈ`Îò:ÔÞRÐîF¾öBÐôB²:Ì þ4¨"&º"´>¼6üÆ>ú´Jâüò4îÐdÄìèN¨0ÈÆ$$¦Höè ÄRÚÖNÌêöJ¬&º(þúðÀLêÔJÐþøúø.Ì0²6Î*îøþüè8Úü<ÀÊ"úî îòì4Ô,Ê Ö&ôîðüþìÞâ*îô(ÜÚæôöðöþþüüþúö ø úþöôøþ üúøüþüþúúúúúúþúþþüüþþþþþþþþþþþþþþþþþüþþüþþüþþþþþþþþþþþþþþþüþþþüþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþüþþþþþþüþþüþþþþþüüøüþþþþüþþüþþþüþþþþþþüüþüþþþþþþüþþþþþþþüþþüþþüþüüþþþüþþþþþþþþþüüþúþþüüüþüüüþþþüþþþþüüþþþþþþþþüüþþüüþþþúþúþüþüþüþþþþþþþþþþüþþþþüþþþþüþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþüþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþüþþþüþþþþþþüþüüþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþüþþþüüþþþþþþúþþþüþüþþþþüþþþþüþþþþþüþþþüþþþüþüþþþþþþþþþüþüþúþüþücrossfire-client-1.75.3/sounds/miss-1.ogg000644 001751 001751 00000011506 14165625676 021111 0ustar00kevinzkevinz000000 000000 OggSŸe ½;vorbis"VPéOggSŸeÉIoÇ-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ vorbisXiph.Org libVorbis I 20020717vorbis$BCV@B*­cŽ:È!Œ¢ BÊ)ÇBÐ!£$Cˆ:Æ5ÇcG¹dŠBÉÐU@¤WPrI-çœs£WÌqè çœså gÌq %çœsŽ9ç’rŽ1çœs£Wr)-çœsGŠq§çœs¤GŠq¨çœsm1·’rÎ9çœsæ ‡Rr®5çœs¤gr %çœsÆ gÌqë çœsŒ5·ÔrÎ9çœsÎ9çœsÎ9çœsŒ1çœsÎ9çœsn1çs®9çœsÎ9çsÎ9çœs 4d ¡(Šâ(² È@qG‘K±ËÑ$  Y H†¤HŠ¥XŽfiž&z¢(š¢*«²iʲ,˲ëº.² HPQÅp Yd`(Š£8ŽäX’¥Yž„†¬€P G±Mñ$Ïò<Ïó<Ïó<Ïó<Ïó<Ïó<Ïó<  Y ‚(dBCV@!CR\ BCBÎC©¥ƒà)…%cÒS¬A!|ï=÷Þ{ïÐUa8ˆÇ$!„b'Dq¦ !„å$XÊyè$݃B¸œ{˹÷Þ{ 4dÀ „B!„B)¤”RH)¦˜bŠ)ÇsÌ1Ç ƒ 2è “N:ɤ’N:Ê$£ŽRk)µSL±åc­µÖœs¯A)cŒ1ÆcŒ1ÆcŒ1Æ# Y€dA!„RH)¦˜rÌ1ÇBCV€ER$Gr$G’$É’,I“<˳<˳ "𙹠‹ Œ Ž‘‘€€„ˆˆff®Ââ#Ccƒ£Ãã$Dd$OggSì Ÿe cWÆ mqo¥“¢nm4H³é?AÁ÷àWüvÇçDo{wŸŸ4}³[ŽæškûóŸ»üÆ–ä4yëÓŸÿìϾlËOW&ã06ª÷êN¿+­[¾ûƒ?ð^i¸¾1D²Û¸$æàû§„®§Mæúÿ¬ûƒ=ÁÿD!Mñ§CPøÌt­—rXqR»N I¿÷tQ‡Ú’×éüyÝóœ¦ÅŒŒ7_ÝóÖ «¯®·L'îâænôNsMÌå7úÌ}§Vy°ÿ„Kžâ‰>5qÞÀjH”ÒÉkT%í^Øùöd B)H+,RÉŽ?m˜õ–O~ý'YŒ×·x|¬Þµ»ÝL$&燈³$ÿ-HdÛ¯×Æâb×o…µNÎ7ÝñsYGãp™ÈøçÛȳ¶Ø6>ýQ_cÚÉF‹ùB €r U•›zIÊÛµGA˜Ô¦êO¢£Sìÿ§»YæläPÙP¥{OûvçÓÛßÞ xÝp[i ÿ¸ÕëeûÎÇÖ]ùŽ_Ü3ÓÍ·:öYÒ²Ýõ“FѼG?P}®i%¹YK"`-*z¤Ù Ó”ŽVW‹ûÞœj*¦Ù1mƒ¢WïB$îÙº†áyP!åÏv.UÇFÉfê¢ù—. õC×Y¾²Ñtb,,âù>9ŠÝ4LĨ¹xpÛ›Ÿ~8 er¶ó ­‡'“A½mÚñÁ`Kg±k³sèE“÷iJÑêÆª‚–oËÊÀ­ ) ¢îÝ,½¼ƒeƒB©­”ͪÛp‚+VÅ—±QÅÉÝ+T‹eφaTroÍR\™ãóIÝxó÷øÍæý¸°Ž‘Ý;•HÝɤ6E@4 5«~(êm{ÝFǵú Z#ÂC ÆìLŽ8±ÛMá"¼pƒ³#ËkÛ_cÝÂÛeðS®óKl½’N“-Êžd²{²wl±Nâ„ìÐB²é¡ÕyÍÆîAù–%£÷+‘ÓÚ~”8ƒùì\*ª˜]"±šB|¦ü0¾Yä‹ V¾6W\ûÆŽr -(ëÑÈV8Â[¾–SÇÄGÆoû è­F3³‘ãp©ü©æÏxLÓÈ¡îŸîïó|r»­^ݺÜöÇ5‘xÛâïFº§ÁGnþ,¾ì}Ò0T5÷¯²ëœsÞ’í³¢¤Lö JŠó<¿×~kxZRºX¡ã :otW¬,ì•oS+e«Õ×øôŸÚœR­½g^èÿ’ƒ7mt¼øm°fŒD¶!.èyAÀü$£çß—f´±Í£êdOòöÌSë|£Ï÷¶Æ-ruQâæËÿ'ÎxX³çdðGL÷ùùÍxj¼š$ódnö¾ónë›Èóôß®ÏëÛ.»»ôf_úÝÈ'ÓÚÕ4N±Nç÷Ûº¸â åÕ<ŸÈ‹M4ª·šÙÖõí­sgýmAûVÁ»¯â²Ú>Nï§¶ËæÓÏL{;æÓ;Ôâ6Ÿ~¶Ëû7có,Yf³¤ÓÒ>mµÑg~skê;¿ê"ÆïY²¾ýéω[¸ú«wžÍ|˜\8hr€u:crossfire-client-1.75.3/sounds/first_try.wav000644 001751 001751 00000214320 14165625676 022045 0ustar00kevinzkevinz000000 000000 RIFFÈWAVEfmt +"VLISTINFOISFTLavf54.63.104data€þþþüúüüþþþþüþþþüüüþþþþþüüüþüüþüúúüþþþþþüöööø üüþüüüþþþüúü þøöøü þúúüþ þúøúüþþúúúþ üøöúþ úøöøü þüúúþüüþ üøöúüþþüþþþþþþþþþþüþþþþþþþúöööü þþüþüüþ þúøøü üúööú  úööúþþüü þúöúü þøôôöü üøöøþ þüþúøøúþþúúü  þüøøøþþþþþþüüúüþþþþüúúü üøøúü üúúþþüúüþúúü  üøööøþüþþþþþþþþüúüþþþüúøúúþ þüúúüþüþþüüüöôøú üøøúþþüüþ þüüüøøöúþþþþ üøööúþüþþüúúþ þøööþ  þøôööüþþþ üøöôøü þüüü þþüþþþþþþþüüüþþüüüþþúøöúü þúúüüüüüþþþþ þúøöøü üüüþþüþüüþ üöööøüþüüü þüüüþþþþþüþþþüúüþþúøøü þüþ üöôôøþ üøôöú üøøü úøøþþ  þøôôöúüúúúþþþþþþ üøööú  þúööúþøôôøúôðôú úôôöþ üøú  üöòôöü þþüþþþþþþþøööøü  üüúþüøööú þüööøþ þúöøúþþüüþ üøööúþþøøøúüþþþþþþüúúü þüúüþþþþ üöôôøú üüüþþüüúúúúüúúüþüüþüøöøüúöòôø  úööü þöòòôþ úøúüþúúúþþúøüþ þ þøôòöø üöôöú üöòòøþôòðöþ  þüööøþúúþ þüüüþþþþüþþüþþúüþ üöôöú úöôöüüúüþ  úúööúþþüúúüþ þüþþþþüúøúüüüüþüøôôöú þüþþþ úøööü úúþ øòðòøþ  üúúü úøøøþüúúþ úôòôøþ úøúü  úððîôþ  üúòòø  þöôöþüøôøúþþ üøôøúüøöüþ  øòðòú  øðîòø üôðòö úöôöüúúøü þþúüþüüúþ  úøòôø  øööüþ øòîôö þúúüþüúøúþþþ þøôôöøþüüþ üøôôøþþüüüþ üúøúüþ üøøøúþüüúüþþþþþþþþþþþ üúøøüþøøúúöööüþþþüúþþ þüüü  øðììðø  üøøøþ þøööú üüüþúöôöü úöîðô þöòôü  þöòööüþúø þøòöø úòððö øðîîôþ þüöôôöþ üúøøþ úôððö  þúøúüþþþþþþøøøüþ  üüúúüþþüúúþþþþþþþþüüüþ üüü øòîòôü  þúúüþúúúþ  øôôöþ  þôðîòü úòðòøüúþ  úôôú öîêîøþ öòòôþ  üüüúöôöü þúöøüøøòòôüþþüüþþþþþþþ üöôôöüüúúþ  þþúôòòöü üòîðö øôöüþ  úôôøü øôòøüøðêìòú  þøøøþ üüúþüøöøú  øøöúþþþüüüþþüüü þúöôöøü  úøòôø úøøþ úöøü ôîìòú þôðîòú üööúþ  úöøü  öîîìôü úúüþþúúúþþþþ  þøòðòöþ þüüüúöøþ  üúòðôþ øòìîòú  üüü  øðììðú úôôöþ üúôöøþþüúüþ þøöøüþ þüüüþþúúøüþ üöôôôú úôòôø  üöôôú üøöü øîêêðúüöðòö þøôöú øôôüþþôîììòú  úööøü þúüúüþüüü  þúüüþþþúúøü  úøòðöü øòðôü  üøúþ øîêìðüøððîöþ þøøöú  þüööú  öòððôøüúúúüþüþ úôòôøþ úöôøþüöòòöþüòîîôü  úöîðôþ úøú øðêîðø  þüüþüüþþþþúöôöøþ þúúúþúôòôøþþøòðôü  þòîîöú üöôüþôìèêòü üúøüúøøúþþúúþ þøôòòôø  þþ üúöôøþ öîìðøþôððôü üôôôþúîîêîô üüþþþüúúúúüþ  úúòòòü þúøü úòîðôü ôîìîö þøööü øðîîòú üúüüüüüüüþþøôððòüþ úôööü øòòôüúðììòüþøòðòú þúøúþ üôòôòøüüþþüþúôòòúü øðìîôü  úöôú  òîæèîú üøøü üúü üøööøøüþþ  üøôöúþúúøüüðìêîö üòòðö  þüöøü þüòîîòöü þúøúþþüüü þøôöüøîììòú úöòöþ öîêèîø þüþþúøúþþþþþþþ üòðîöøúöôüþøîêêòüøòòôü üøôöú  üöööúú üøöøúþüúøøþ úòððúþþòîîðú úòððø  øöðòôüüúü üúüü øöòôú  øôôúþ öîêðöþ üôðòöþüöòòöü  þþüüúôðîðø üüúü øôèèêöüüôôöú üööôúþ þþþ  úðîêîôþ þøôöü  öðèêðüþ  úøøúüüüúôðððüþ øðîðöþ  þöòîôúüöøöúþúøöôø þøøþ  úîæâæðô  þüüþ þúúüþþøôðôöþúîîîòþ  üúòöúüöôôöøúþþþþþ  úööú üöððòú öîêêðü üøôööúüþüöòêìðþ  öððòø üúúü þüüúøøøþ öðêêîö þøòòö úøøúþúôîìðòþþööøþ ôðêêðø  úøööú úöòöú üôîîðúüôòðòöüþ  üúøúüôðêìð öððòø  þüþüøøöøþüüúüúòìäèîüþ úøúüüøøúþþüþ  øðììðú þüðîîôúüúøü þôîêìîö  öðîðö øúüüúúüþüúøøú öìèèìö üúöúü  üøöúþüüúúþ úðììòö  úôòòøþüøöôøü  öòèæèòø þöòðôú þüüþþúúü þôîììòúüôððòøþüþþ þüü üôîêêîú úôðòöú úöòòôü üöòòøþ þòîìðòúþþøööøþ úðððø üôîìðøø øòîìðòþ üöööü  þüòîìðôø üöððôú  øòðîôú üøòòôúü   þòìæèêôþ üöòôø üøøúþþü öìêêìø üúòòöúþüüúü  þúøþ  ôìæäæðúüúøöü þôîìòôþ  þøðòòøþ  þúððìîòúöððòú úöôôøþ  üøîììôø  úððîòøþþüþ  üøøþ úðèæèêö üüþþúøöøü  øôðôöþ üòðîðø  üüþúøòòðô þöððòø úöòðôúþ øðèèêðú úöòôøþüþþ üööøøüôêèèîö  üúôðîòøü  üôòòøþúòòòøúþþþ üôìêìðú  úööúþüøöøüþ þúøúü þòðææêòøþ  þøöòôøþ øòîîòøüøôöøüþüþ  úîêææîô  þúúü  üúüþúòîììòú  úòðòôúþüþ øôððôú üòððòú þüúúüúöòòðòøþöîððøþ üøööúþþúü üðìèèðöþüüúøôôôüøòððöü  úöòòôúþ öîæäæîö  üüþüøøüþ  úòììðö úöòôöúþþ  üðìèæîòþ  þúúúþ  þúúþ øîìèèðú þúøøúüüøøøú þúðììôö þöööøþ þü þôîææêîú  úúüþúôôôúü  üöòòôúúòðòôøþþþþ  þöîêêìôþ úüüþþúôôöú þøôðòö úòôòôøüþþüúøöøü úôîðòø  üøööøüþþøúü  üôîêìòú þúøüþúøôòîòøü üöôôøþ  øöòôöúþúøøúþøðìêîôø þþþ úôððòøþ úôðòôú  þüüüüôòðîòø úòòòôúþþøøöøüúôööúþöòììîôöþ øðìêêôúúøöøúþüúøöúþ  úôðôôü þúôîîðôöüþüü þöòììîøú þøôôöú þüþ úðìêêðöþúöøøúþüúøøúþ þôîìðòú  úöôòöúþ   öîêääèòô þþüüþúöôøü üôðîìòø øòôòöúþüþ  þòìææèìô üúüü üúøôöúþôðîìòø öòòðôøüüúúöüþ úôîîðòú  þöòòòøü üüü þøòîîðôü  øòîîðòöüþþúúü  øöôòöü  þöðêèêîôü   üôðìêìðøü øøðîðôøþ üúúúþþüöööøþ úøîêèêîôü üöðîìêðô  þöòôôú  üöôòöøüüúøøúþ  üôîêæìðúþ  úúúúþüúôöøú  þüôòðôöþ  þøòîîðòøü  úòìèèèîôþþ  úôôöøþ þúúüþüøôðîîôôþ øôîìîðôþ þþ þøôòîðòøþ üöôîòôþ  üøôðôôøúþþüúøúúøòêêêìôø  þúööøúþ þüüü þøôîîîðøþ  üôðîîòôú  øøòîîìðôüüôòòôúþ þøôôôøúüþüúøööøüþ  öòêêêìòø  úøöøúþþüøúúü  þúôðîîðöü þôðììðòöü  þøòîêêìðöþ üöôôôúþ  üøöôôøüþþúúöøøüþöììææìòöü  üüúþüøøöööþ  úøòòòøø øòîììîòøþ  úøòîèææèîôü üøøøúþ  üøøôôöúüþüüþ úøîêæèêîøü  üøøøøüþüøöôööü  þúôôôöþ þøôðìììòòøþ    üøôòððöø   üöòððôøü  þþ üüúüþ  þøôðìêìîòøþ  øöôöøúþþüúúøúü üöòìîìòòøþ  þúüüþ þüøôòðòôöþ úøîêèèêìðôøþüúøúúþþüøööôöøü úøøöôöúüþ þøööôôøúúüüüøúööôòòòøþúøôðîîòòôúþ  þþüüüüþ  üøòððôøþ  úôðîêêîòôüþþüúüúüüþüøôòððôôöøøüþ   üúöööööúüüúôðìîîðôøúþþþþ úöðìêæèêîôôúü þöôðîîðòöúúøööüþ  þþüøøôôôôøúþ úöôöþü  üüøöööøúþþøöôòöø  üöðêêèêðøü  üøøöøúúþüüúöøööôòðîððôø þøöðòîîîòòøü üþøøòìèääæêòö þøúúúþþ üøôôðòôø  þúðòèæäâäèðü üúööìòðöþü þúôðîðöú  üúøúþ  øòìêæèìêöú    þüøøôöôú  øðææâäìîüþ   þöúüú  úøðìîîü "$ þüüøüúþ  øøòôöø  üöîòîôêìêòêòôü  $&$"üöäêêìèììôêúþ þúöôôøôöôøööøøüúòüøþôöôúöøú $&&$úüððîøôüú  üðìêèæêêôøúü þúîòîøþüúüú øðèæàäàæðæòôøþ üðöðüòøì î   þ  þúøú  øöòþêêìøúüô òúúòöúòþ " þü  þöèöæìÔèêüîþ (    úèøøöæôúòðìôøþ  øüüöüüô ê þü úþìüú öþþþüþ ü þò ô þþîúööü ðööúøöúüìüøö  ððêöôüúüôøòü ü& øøðæàÞÜÜàæîø &   &  öð úþúþàèàîôöú "$&,&"úðæàÖÖÔÜÞæìü &üúþþøêðîðøú  þüòôèæææòòôþ èîðâÜÚÜâæèþü "& úòìÜØÒØÜäöö $&&$"þòìèæäæææììòú   úúúúüüþ úüúøêìàîììòêòðü  ðææÞîðúø "  üòôððìæêäôîòîàðêøúúú* ( îüö þþüøðòêöøþ üôöòðêðîþøüü   &&*&" üîöääÞäèìò üòðäêèöòøú þþú  üþ øîîâêêðúòüøþ   úôòðêêâèèðîòðòöðòèììîüú $  öðâàÞØÚÐØÚÞêìúøúþ ôðèæààÞäæðîôþ $ $" "   "$((&&$&"  üþþ úôôðòìêìêðòööòôððêæäààÜæêîôö "$($& úøìîèêèäâÜÞÚÖÔÒÐÒÐÖØääìòòøøüüøøðôôøüúþ $&(..2..*(  îîèäêäæäÜääðöúþ $.,0.**$   " øðèäàâääòîöøø $(&..,0(& úöòòîðîìòðüöôðèæäâîîøþúþúþöþììêìþþ  øüòöôêìàæææîèîìêòîøòðîæôòü &&.,.0,,*$ úôîìääààääêæäæÞääêôðúòú""&*(2,* úðæÐÒÈÊÎÈÒÐÞèö   úþ $$&,(,&   þ  úîäÚÌÒÐØðîþøöüø  üúòìäÞÒÎÊÒÐÚÞèúþ ,&0"þúþþþüöðöðöòäâÐÒÎÎÖÔÚÜÜàâääêêúüþ  úüðîòêøþ & úôøîòèîîúúúü þü  "&2202..,&,$"    $ "$(.,0((&òôöòöæäÞÜÜÞììú úúøüþüüüø "$*0. ôèäÒæâîüø 2.4604.0.&& " " "$2&0((8.>6*((úîôòôúòøòôøôüîøöúôöâààÞôðüööüúþþþú  üüôêèÞÜÜÔââðüèôØÜæÞôÜÚÐÄÎÊØîìúøö  þ þ """ $(  öîâØÚÐÔÐÖàâøöüú $ ìîØêèðôôþ "(.22644,0.02**" þúòøööòôüþ 00@486(4&*òöôîôààÐÔØØÚÜàâèäæêêòôøøðîøð"  $$:002.0.,*,$0üþ  "  &*((4,84,(  þöäØÐÐÊÐÒæêòúìþ    $. ðôúôØàÌÔÚÒêäèôä øòþð èèØÒôêôò øúðöòøø&.8H$("20ââÖÒòæöòàæÊÖØÒÞÚÞâÜàÜÚÜÖØÔÔÒÎÐÊÌÎÊÒÐÔâÔàÒÒâÞèöàö$  $(  **  ü  àêÚäîðþøú&úøôúþôìàØâÔààðþôüÞàâêüøöÎÖØÖâîàÐÌÚâì þøøîò@,8:&4&* úööæÊâÆúìâê¾ÖÎäúö üìêÖèØäÚÚìîúæÞÚÆÌÊØàÞàÒÐÈÒÌØÚîú ìààÎîîüêîÊÐÐÆÐÈÎÐÞÜäâèööüøÞðäòøìúæòöòêðØÜîô  úúþîþâÜμÔÂÔÔÆÞÐÖøôþæÖââô$(þðØÎÜà $, ü$6<,H,>>$D 6$(6üÆô<$.* ú,@,,4 , öþ  (&""$&,&(ôîæô* . .2H0@6.>&2( (&$üÜàðô    øòôîüôàÎØÐÒÐÖÞÞÆÖÄâòòü86686$$êâÚÐàÞèôæôÞâôôäèèä" òæððü"þè@60$öæÖòúòôüðþüìúÔàæòêèÖÒØÚðþú ø(>ö$&H ÔÔâÐ(.< ôèèäô0 *&úòô äâÒàÊÚâä èôÊÀиàüæèÐÌöò&úúæ þúøàÔÐÀÒ¾ØäôþêäÔÌÖÎB2$ 2<,&:6$ òþ6.4*ðàâè*,. úöôð:$44,D&0   ôîêèîòòôøðüøöö&&,:ôîþú8.@4øòîäúô&0 ÚÎÆÈÌæø   ôøêþø þøðôä82.4üæú ìúàÞöÒêÆÄÞ¾ìðÈÖâÚüúêæÊÞÎÒÔÈÎÊÊÊÆÆÄÆÆÈÊÈÐÊÎÖÈìê 6& ð$6>æÜâÀ&0þê"R,:D@$2,þø420ÌØÐ¸ ü&üâÌêÂ&úìºäÐèöðê  îü628:*(öøêúúúúúúþþ862>@6:,ü" þúî2 *.B4@<8B8:<462&0,,.((. **0&6&2.80ü 0öüþ6*.0&úØæì4*6,âØâÔêâÚÞÂÐÈÈÐÊÐÐÐÔÐÔÔÖÖÖÚÔØØÒÖÐòøöòøØÒØâêö0""ÄÞÎè (4(ê&<6*<òôêÚ*,(î¾ÒÊÞ0&B,òÈÚæàJ*>@üø6.(4&....2.04,,>.@.8êìÐ @.,8&<(*8.:.>  òðÎÐÌÂÒÀÌÈÐððöþþøøü &>4D<¼àÌÜèæÚðàú2üêʾââ662D6>,&$J.<6.<*00&4$*0:ü884:* 42(06&,ðÐܾèêðð ö ôäÊäÌ .68ìÂÒÈæ>"<& àäÂþ0:2D,B2( üøôöúøøüòüØÖÂÌÊÎÊÜÜèÐØØÖÖàÜðæìòøþêÚÀ̼ÒÂü :þ¸Þ¾â¾ø&L*:ÐÚâÆúöìø.ðÄÒÈàú&*þ*êøÒ("626>ÀæÊæFN úð¸øê,.ÎÒÀÎÀÒÚ$üÜÂà¾äÄæô@866 44*6&0,$4&0 ôÚÈÐäÚøè" .$îÞÌÜÆÚÂæêüüÖξÌÀÈÈÂÌÈÈÎÈÐÐÎÖÒÒÖÐÖÒÐÔÎÞð.âÜààòÐÔÄÞÂÖÔ¾üþòØÒÂÔÈÊ 28 ðÐÈÖÌÐ .P¼ØÔÎþ üôìÞòü:"00 úøF02F(N ÞüêP(B06, òâÎä 4& ø Üð¼Øâþ0èðø úøêÜèò úúòòêòþüúäÒÊÔÈÚà@4<4 þþ$4ö $(846,*öü ðä$@.0:$@üÜøâ8"66,>.:<(,86<:<6B&, 8" àäîèÐüâ0*îàÈÂèô@*4 : ÜðäööÔÔÆÊÒÔöòöî¶Ô´Ð¾ÈÎú02<&æäÌâ(J,D46,ø8".(FþîFR䨏2N*8:&Nþò¸ÔÒøôì,.(Xàø¶ÚÒÄàÂÚÞø(.üðÌÊÎÜø4.:&Hä$42Nü ü ìòÐðô üÆÌºÐºÆÊ¶àÔüæ¾ÞÀØÒÄäÀô4:$( ü@*.( 8$6$*.6.4üúìòîÈÞØö : êÄÚÂÒÌÆÒÂÔÔæÜìðøþþøÒâÌþú844<&(üþú <<280@ èàÎê ôîäþü2 BôòÈü<2(>*6:.<8,(  H42F P ¼ÆÒÀ$ þ"4øü8Äüæ64:@0H&TÖöÌ>Fø,".>&:ìôæêâÂØ¼ôþ*ÆÆæÌîÈÈÐÆÆÜèÞâ¸ÌÄÄкêêÈÜÂÐÎÈÔÈÎÒÈÔÊÈÒÂÐÈÈîô ìîÐÂμÎÀÐØú úØÌÒÌÆòìæøìîâöºÈÖÌ(D  ÈÌжü D4:<æÆÌÖÂÚîöF"ÜܼæÆÐʶèÚúèê¾ìÜàÞÌÆÚÂÔÚÖì$2(@èè¶òêRòæÀÒÒäîºÔÔºîðÈÞ¼ÔÈÀÖ¶ÞÚþþìÖÖ¼ÎÈÄÔÂÎÔÀN öàÌÒÞî&4<*$üîâØ:04*þÜÄÎÈÔä>.@:âÂÞºà¶@28,ìÚ¶Ô¼ÆÐÆ F6&2ò8öøüèø 2:*D*ÈÒÄÌêÖêÖþìôÊî¼ $4Lò¶ðôìþ.040>ÆÒÀÊÈâüþ &*ü²ÜÆÄÞ²æÀ>42B$þèÒúð"28.<28:(  ::<6Dôê¼Îк⤠>28*ÜäÈâÜàæôúü &øìäØÌÐÒøþ þö¶ÚºÌÊ´êô.*,"Ðâ¸Òêæô"$4F$(úÞâÚòF*F,>2ÜÆÆÂ̸äôF&D,B(âÔÎÂâàN,<D*N&FÚØÊ F.2>&H¸ÎÌÌþî $:6:6ÌÔÊÈÞì  öèàÐÂÊÀÞÐÒÂÈÊÄÊÊÈÌÆÌÌÊÌÒÖâæøþøêÞØÚàððþüüöÚÜÀÌÌÄÎÆÌÎìüþ úèÞØÈ@ òèúäÐøò@.20êð¾ÎÐÀÚÀÔàø 2@6."èè¼ÌÎºØ¸ÎØö êðÔäòô   ,&.  üþ&>288öúðÊ̾Üî8*H48F,RÔÊÎÂÚÐæö48::,"üâÊÊÂÄθúP*D86@, 88:>0Fþ.6:$öÖмÐÌÞú60<,.8<:8:6:6:464þ&.82,ÞÔÂÎÈÊÌÊÜÐÚÆÊÐÀöèþîÈÒºÐÄÀмÊÊÄúöúþú *4B4>:8<68<*..<,D,:>(TüäöJ464öüôØâÜôþôòÜÎÄÈÀÒÎH62D,F0*ü:6<>6>8<86<,:88848 ôøâÜúö*&,>.&öþÒÞòø>(B68888*B04B(J(ê¶æÐþþþ2B"&üú"&>2884866:86>&0 <440üúüô îÂÖ¶ÒÀÂÖö,0<8<*&F8>>8@:<>8>::820@4@8:8. òøÐÖÔÞ $F4<:úæÌØÈ¼âà>2:B,L êÊÆÆºäî428D.D66F$0.(D:<>:<>862*. @86<îÐÒ¾ÄÒ²äà44@8L´ÔÄÒøü"6@8:@0B$ 66:6:>.$ú(@4H0H6,ÆÒ¸Ð¾ÊÂäîü  úþúüøøüþ&F4D6@6 ê¶Ø´Ò¾ØÔ@:04 öüúH8:@:<>:<<<:<:<::<6>82. öøúü âè¶ÐÈÀÒÀÈÒ´òî& øäèÐÌÜÚúö  þøäôîúþþ.2><0, þúüúü þ<4@<8D4D0"üúü$6B24 ú ""8>2H,JæÆÒÒä22**øêæÌØÚæúþþ ððêæöþ&(F88H,L2$öÂÊÆ¾èô868H.F4("úàÔÞÒìôöþ06:><0$êÜÎÆÔÖîúþü(*üðöìòøø  0&*$ìàØÂÎÀÌèî,.@,ÜÂʸҶÔÎ(6B2H.LøÈÄ̼ÎÀÞòüüðÒÄÊÀÊÄÄÄÄÂÆÂÆØèôøþöôÒÐÀÊÂÊÄêìþúèâ¾ÈÆÂÊÂÄÄÂÆÄÄÄÄÄÂÆÆÆÆÆÄÈÆÄÊÀÔÜîúüüþôäÊÂÊÀÆÐ8.J,F2.ðäÊÜäô(>:>8(ØÎ¼Ì¼Îìò"D:<<0üúþüöþ  þ 60F6>B28 úê¾ÈÀȾÒäþö * þìúðúú24@<:@:><<<:@8@0 üú $,,.ìÈʾÆÎÚòþ "üÜÎÀÆÀÒÜ D8:B48 üðòôú$4.. úîøôôäÐÀÄȺκÜèü üôìàÜÖÖäâòô <6>>4J&*òÖʺҸÊÂÎîòòê´Ð¾À̼ÆÈ¸ÞÞüîÒÌÆ¾Ê¾ÄȼâæüþôàØÄÆÄÂÆÌÈÊÀÆÂÄÄÄÄÂÄÄÄÂÆÆÎÈÆÂÆÀÆÄÒèôüúì䨼ÈÀÄÆ¼ÒÔøò þþøôðÚâÔìôú þúüøþ þÞÚ¶Äļƾ¾ÈºÈÎØòàêԾȸȾ¼Ê¸ÊÌäööþþþü.6<D<B>@B<D>>B8B&  2><D<B@>B@>B<86,86B>@><*&þüþ  øìâÐÌÆÒØäü 22@D6&öÞÂÒÊÖìê$(D>:4ôÚÔľƼÄÂ¾Úæððèøøú$",0<<>8B8> þ æÜÊÄÆÂÄÆÂÄȼÌÈðþ" üüüüèøôü""J4<B6@<8>$ôòæèðîüþ  0$  þúüìÜÜÔÞæò08<>:@8B $::@8<$ .0D8<>8@::0 ".:<<><><>:><:6  øöúú.8>:@8( öØÎ¾ÄÆÀÆÒØæòøþþüìæÌÈÂÂÈÀÄÆÀÆÂØÜæöúþþ  26@:><<>:>:<@6B40òüú&D46,üö¾ÌÆºÐºÊØØ 0:** ôðÜìîòüúüêêâÞîô,4@<2&òâÒÎÀÄÊÄêô42H2@>4D"þæàÖÜèô(6<<@8@.(  ,6>8@8<. üúüþþþüúêäÐÊÊÈÔÖÚâÖÔÊÄÊÂÆÈÂÈÆÀÒÔøþ ôüöúþþüøôææàæìòþüüðäØÄÈÀÈÀÆÊÒèî  úàÖÈÈÌÎÞæðü öàØÈÌÊÎÜèîøúþôöäÞÌÆÆÄÈÄÈÄÆÆÄÊÀÊÌÜðôþüøðæèææòòþ (0@:><2"þ$*D8><<>:><<<6@0((66@:>>8B2( ìÚÈÊÈÐâèø&24<2&ðèèâêêîü   $.8<<:. îÞÐÎÌÌØÞêôöþþøøêàÔÂÊÂÈÄÄÈÄÆÆÄÆÄÆÆÄÈÈÄÈÂÈÆÄÊÒäìöøøôêÚÖÎÀÈÂÈÄÄÌÊâæðþþ .2<68888:6<:86,.,.<8><<><<>:><2,  þöðêèàÜÞØÜàèö ",:8882*&"$(.>8<:::::<:<<.*$ $$46<>6@6>0& þüü 0<8<8:," üúöôôòúü úÞÊȾÊÀÈÆÐÞèü &$(&  $08<::6,þüþþ öìÖÒÌÄÌÄÊÈÖæð""üäּʾÆÊÖæð&88<84$ "46<8<4,$üòääÞàèîü ìàÐÆÌÄÊÆÈÒÚèîöøúøòäàÖÈÈÆÆÊÆÊÆÊÊÈÊÊÈÎÈÔÚàæääàØÔÌÎÌÌÐÔØäêü  òìàØÎÌÌÎÒØâîø"&$ úøîèàÜÚÜâòú&022.& øìàÚÚØàêú*.0,&úîèÚÒÎÌÌÔÚêòþ&2444.$  .4<88:6:6686666666:888888<::::<<<<<<>:::<::8888:8866668666:888888<::::<<<<<<<:::<::88888:668666682:,$ þöìèØÒÂÌÆÆÈÄÈÆÊÒÒÖÒÐÎÆÈÆÊÈÐØäîôþ þüüþüþþþþþþþþþúðìæææèìôøüþüúôôîîìðôø&,8264620*(&$$ "$"&&(*,.2688:::860.&"úöòðòôöøüþþúòðäÜÖÔÒÖàèîøøþþþøöîèâØÔÔÖÜæöþ,2<68880,( $*022,("þþþüþþþþþþþüúòêàØÌÌÌÊÌÎÌÎÊÌÎÔÚÞäèèêæäÞØÐÌÈÄÆÆÄÈÄÒØèêúüòæÜÖÐÌÊÎØÚèòþ  ðèÚÒÌÈÌÈÌÒÔÞæòú  "&**02666:888<:::><<8<40,$" $$(.426464464448420.*("   (04:4820$  (2888:<:::::::::<88:88664,&    $,.624628662($ "$,26842( þþ&(068:66.&  $,,,($ òâØÌÊÆÈÈÐØØäìòøøöôìæÞÚÒÐÐÒÔØÜààààÞÜÜÞÞâæìòøú $",026442222240,(&$"&$&$$"  (.04842.," úðèäâêìú (08::::<:8,*"$*,02242224620($  ""&"üøøøúü$*048::::64222246684440422.(  þöîêàØÒÐÌÎÈÈÆÆÆÆÆÈÈÌÊÒÒÔÔØØÚÞàææîôøþøöðêäàààæìòøúþüøôòðôöúþþüüöòìâàÜÜÜâðò&,28:<8:2.$ þþþþþüü$*000.("   þúþþþ $*422.& þøðêäÞÜÜàâêîöøüüüþüþþüúöðêæàÜØØÖÖÔÐÒÎÐÎÎÌÌÊÊÊÈÆÈÊÎÖÞèìöüþþþøòìäàÚÖÖØÞàêö úðæÜÖÒÌÐÖäèü"$  úòæÜØÔÎÒØäæú"&*& ôêÞÔÒÎÌÎÎÔÔàêôúøöôôòððèèâÞØÚÚÜàêìôôøøþ   úîäÚÔÐÌÌÊÎÔÚèöüüîæÞÚÖÔÔÖØâêú(**üôîìææèîîú"$.2666664,$" üüúúüþüþüúüúúüþüöðêæÞÜÖÔÔÒÒÐÔØØâæìòöøøøööööøúþþüøðæäÞÞÞÞääìðôúúþüüüúøôîêàÜØÔØÚââìòøþ þüüüúúüüüþþþ  ,*04444622402.(  úôòöú$,,4444622( üøúü $$(**,***&&$  "$"þìäÚÖÔÐÒÔÒÖÖÜäìòú  òèÞÔÒÎÌÌÌÌÌÐÐÖÜàèðúøôðìêäâÜØØÔÒÖÔØØÞäìðøþ  þþþþþüüúúúúüþ þôìàÞÚÚÚÚÚÚØÖÖÖÖÚØÞÞÞÞÚÜÞäêðöüüüøòêêèèðø$&(&" üöìèæââàäèêôøôèâØÔÐÌÐÎÔÜâòòþ "& øìêèîðö""&("&öèÞÞàäìöþ þþòêàØÖÒÒÔÔÔÔÖÖØÞäìüþòæÞÖÔØÞàìðúüþ øîèæâêîôúüþüþüøòðìîðøü   üúúôøø  þöêæÞÖÖØÞâîø øòèàâÜàÜÜäÞìòöü úòòîîôö "" þúüøôôìîðöü$***&îäÖØÒÔÎÎÎÌÎÎÒÖÞæêöüüüøôòðöúþ þúúöøöööööøøüüþ"(2.0..,(("úüøüþþ  $&(**.,,.***(((&$ üüüþþ  üþøòîààØÐÖÖààêú þôèâÜØÚÚäêôøúúðìââàÞâäææææääæèîôþ üôîìììðôöúøúúüþ "&$"þþüþ &$&  þôòæèèêòôüüü$   øöúöüþ üöððìîîììèììîôöþ þþúüúøúôöøøþ"&,,,*&($"úöîäâÞÞÞÞÞààààæèðôúþüöôîèâÜÜÜàêðü   þôìàÞÖÔÖÜàæìôøúüþ þöðììîòø  üøøøúüüúøôôôôü  þòêâàÞÜÞÞæîô   þ  "$$"    "þööìæèÞâæìø"$2,00&*îêØÚÖÐÔÐÐÔÒàäîòø øþüüþúøøöøøøüúþüúþ &$(&$$    $ $"""      þþøöôòøöøøððìèêèììîðîððòöü  þøúòòèæèâòö øöìððôþ    üúøöúúþþþüüúüü þöôòðôöúøøöðêäàÜÜàèîúþ þøúôîîäììîôòøþ "&(*,***&$ îæÜâàæðú üîìæäèêðòøüüüþúüúþ  úîìäæâäæìðôúøúöøðòðôúþ   øôîèÞÚÚÜàâìð  "*(((üòìêèèèìììääâàèêòôøþüþþøöúþ øîèââàäêðöúüüþøôöôþòðêâæàæèò  øôîîîîðôòôîèèäìîôúú  úôæìèîòôüúøúòôîêîäòô þööôòôìîìêòôøþ þööôôööøöøøúüøúøþöòîæêèòôöüðòìêîêðîîôòüüüþúúöôðîòòøúü   þöøôòôòôúøúøúü  öôèèäâèîôüþ   þüü  øöêäæâìèìððü  üüúööððòðööøúü üöòðìîìðôöøôúú úöìêììîòøþþ  üþöúþüüúöêôðü  öòòîöüöèäÖàÚÞäâîðþ   òîÞæààäÞâÜàâäêîöü üìðêìîèêææèèèìîôöü  úôîæèêêðêòòúþ   þüòðèêìîøøþüú   ôìäììòòððîèèèêîöþ  úìîêæìðôöúúüüþüôôôöøþüøöêêâêðø þúøîðààèðþ   þ  þöêèæÞèÜòøü úþîðüü þöþþüúúôüöúöîôîú    ôòêìîîôòöøøüöòöêìâàèèúþ  ôöììêâèäòþö øôêððöþþþ þúüøöôèêèêðôøþü þööôðòðîòæìêò   þôòòêìâêîø öòòîøòöôö  þþþøúöúüþþ úöæèêìòîòððòôôøþ   þøôèöîòôðööúþüüøþ   øþüþ " ðúðúúöòþøþ  $ þúþ øüúúô   üôðèìîôúòøðúþ úòêæààâæäðîþ üôðäæææìèôö þüüü þúþ  þüîúúôüô   øììèêþöú þ øúðèêêòôü þ þüöüööðîðòòüúôôôøöøöòòîîîîòôþ  "ôöôðôæêäèææèòúþöúüòòæðîøîúú  þôüöþø  üøôîîòòöüøúîôðøüú øøöîòêæèâæììþü þúöøôöòòðîêððúúþøþüüþü   þîèàääèòøþþ  ðêêæôðøúø  þüøôðòòöø  ôüêôêüü þöðìðîòîøúþ  þðòìêîìúøú  ü ôüöúúúüþø ôòêðîðîòúø   þüòðìîôöú ü øîòìøüþþö þ ôúøüþþüüøúøööìððòòøø  òöðøöôòîòòøôúö   ôúúþ   þþôöðòðôöü úúôòòððîòðøòöú  üôðôðöòòöö þüôøþüüøúüòòêúöü  þúüêðììòìôîôþ   þþþþþ  êúòüðôôþ   þøøöôòøú   þööøôöøöüþþ þüôþþþ  üüòøúôðððòööþ   þüøîòìðêîðöôþþ üüøüúúúøþúüøüôôôþþ üúöòôòìððöü  úöîðêêêîôúüþþþ üôððììäøòøø  ôøðøðòòöúþ  þüüöööú þøöøôöøü  øøôðöêîìöüþ þöøòôìôôòøüþþþ   þøøðîæìêêðôø øôòððòöøö üüþôøòøüþ þüöúøúþú   üøôîîîîòòöúü þúøöøôöøüüþþüþüüúüüúöòôììêðôúü  þþòôòðòôøþ üööôôúúüþúøúúüþ öìêæêèîðôúüúöøöüüþüþøúøøøüþ  úöîîìîôöü þöòòððòöúþ  üüüüþþüøöøôöðöø þúôðìêêìððøü  þüüúüþþþøöôôôöúþ  üúôòðòòöüþ úøòðîîðòôøþ þþøôòîîîîðôü øôðììîòöú þþúøöúúþ üøöôöøü  üøôîììîòöþ  þøòòððòôøúþþüþ  üüöðîêêêîòø  üúôòòôöøþ  þúøööøúüþþúúøøúü  þôôìêèèêîôú úøøúúüþþþúøöööøü  üøôðîîòôúþ  üöôðððòøøþ  þüüúüþüúöôôòòôúþþøòìêêêîðöú üúúüü þüööôôöú  þüöòîîðòøü  üøòîêêìîòøü  þúöðîìêìòôú þøòòîðòøú  þúôôôöøüþüúúü  üôòìêæêìðøþ úøôòôôöøüüüúúúüþ  úöððîòôú  þüôòìîîðöü  þúúøúúþþþúúöøôôöüþ üôîèèèêðøú  þúøøüüüúöôööü  úöððîðôúþþøðîêêìðôúþ  üöððêêêîôø úöðòòôøü  þúúôööüüþþúúøúþ  øðìæææèòö üúøúúüþüúööôöøü þúôîîîðøú  þøöðîîòôøü  þþþþúúôðìììîöü øöîìîðòöú þúúüü úøôòôöü  þöòìêêìôú  þööôööúüþþüúøöøü ôðêèèêðöü üöôôôøüþ þüúøúú þúôòðîòöú úðìèèêîôú þ úöòîîîðøþ úôòîîðøú þúöööøüüüøøøü öðèæææîôþ üúøøüüþøöôôöøþ  üöôôôøü ööìèæêêðôü  øøðîììðôü þôòîîðôüøøôöúüþüøøúü  úôìèæèìòþþ úøöøøúüüøöôôöú  úøôòöøþööìèèììòö   þúòðîìîôöþ  üöîìîîôú  þøøúú þúöøúü  úøîìèêìðú þúôööøúþþúúôôòöúþþöòðôôú  øòììêîðøþ   üôôîîìðöü  þôîììîòø þüúüþ úúôööü úòîêæèìôø  üúøúúüüúöòòòôúþ þøòððòúúôðîðòôüü þþ þúôðììîòü  üôðìîðôúüüúü  þøøôôøþ øðìèæêîöú  þüöðîìîòö üôðîîöú þúôôöøüüüøúþ  úôêèæèîøþ üøøúúþþþüöòòòöü øôòöøþ úöìêêððöüúòìææèðø  üøôööú þüúøüþ  þöòîîòöþ  üòììêîòø   þøðìèèìôø þøôòòøü þüúüþüúòòîîðøü  øôîîðöø  þüúüþ üüôôðôøþ  þöòìîðúü  üúøøüþþøöòòðôúþ üøîììôöþ üöôôöü þøü  øîêääæòôþþüüüøöòðöü üôðììòúþ  þøôôôúþþúþ þòêââäèòü  üôòòðøü øîììîöþþøöúúüüúöôøø úöìèèîòú þüüü þøöòöüþ  øðìèêðú þüüüúôðììîòþúòðòôü  üøööúþþøööúþ þôîìèìòþ  üöðìêìòú  úôôöú  þúøôøúúöôðòö üòðìîòøþüúü  øòððôü úöðîðøü üþ þöðèèêðüþøöøúþúôòòôü  øöòôúüòðîðôøþþüøøúþ øîêêðòþ  úøúüþøøôöø üöîîðòþ üööøüüþüøöôðòô  úòððôú þøôôøüþþúúþ öìêæêðü üþþüöòîîôú øòðôúþ  úöòòöúüúúü öìääæìô þüþ úøôöú  þòîêêðø  úöøüþþüøøöüüðêææìòþ üüú  üúøú öìèæäîö þþþøôðòòü  øöêìîöú þøöøú þüü  úòêââæòö üöòîòöþ  þüòðîöú þöòòôøþþüüü üöìææîðüúúúþúøöôúþþöðîòú" üôðîðôøüþüúúþ  öòîòôü þöòîðôü þüþþøôððöú ôðêêîøüüúú  þüøú  øîèæâìò þüüþüöôöø þôðììôþüöðôôú   þôêæäèîø üøøúþþøööøþúöôöúöðèêîòþ þþþþøòððòú  ôòòúü  üòîîîôú øòìæèîúü øôôöü üüüúôôòöþöîææêðú   üöòòðøþ üøðððþ  øððîôöþþüüþ  øöîìðöþôððòúþøøôøüþüüüòêäæèòü  úøøü  þüþúöòîðô ôîêêðø  þøøòôø  öòîôø üôîììîöþ úöòðôüþ  üòìêîôþ üúööüþ üøìäâæðô  þúøúþ þüúüþúöòòòø òìæêîø  üüüüøöøü úöòòø  üòæäèêôþ   üöòðôø þôòìîöþ  úðððôü  þöòìêìòüüôôø úòêììòú  úðîìîô þôðîôþ  þöôöúþ þþøðêêìôþ òòòúþøôðôôú  øòðîôüüòìèêðúþ þüü  þüþþöðîòôþ  þòðêìòú üúüþüü úòðòøþ þôêääèòþ  þøöòöøúöòòö ôìèêðü þúøúúþüøöøü  úøöú üôêæèòöþöøöúþþúúúü þúøúþ  øöììòü  þôêèèîôþ  þúøøüöðìîòüþúîêîöú  üþþþúøúü üøúúþòæääêö üøüüøööüüþü  öðîôö  öìêêîøüúöú  üøòðîòø øðìðôþþöòòôü üöööøþ  úòêêèðú þööø úðìììôúþøöøü  øòðòø  üðìèêòü  üøöúúþüüþ þüúú þöðîòö ôìèêðü úüþüúôôöúþ þúîèêòú  øðîðö üöôøú þþþþüöôòôöþþôôôø öòêîò üôðòòúþþúøüþ üúþ ôæâàäðþúøøþ üöôöúþüøöôøþúððòüþ þôîîôúüôîîðöþ þüþþüöøöü þôìæèîþøôöü üòìêîöú  þþþþ üøööúþ úôôöüøîææêô  üüøü  úöîîòöüüþúü  þüôòòúþþôðòú  üðêêîö úöòôú  üöôòöü þüúúþ þþúþþøòððöþ öðîøú  öðêðôþüòîìòüúøøúüøööøü üööôøü  üøôôú þøôðôúúîèêôøþöôöúöðìîôüþþþþþþþúøøúþüüþþðìèèòü úöòø øðììòøþöòôø þúüüþúøøúþ üòîììòü øøöú  øöîðöòìèîôþúøøüüöôôøü  þþüüúööøúþ üüúþ þúöøü üòêææîú ööø üòîîöøüôòðôú þüþþüüþþüöôðôôü  üøøú þôòðòü øðìîö úòðôø üöôöø þöðððöüþüüüþüüþüúüüþòòìîôü þúööü òìêòú úðîîôú  þúøúþ þôðòôø  þüúøøúüþþ üüü úîîèìô úöòúü úòîôø üòìêîø úöôôü þþþ  üøòðôöú þüúúþüúöúüþúøú  üðêèðö  üöôöü øðììôþ öòîòü  þöôòøþþúøü  þöôôôúþþüþ þüüþþüüþ  þöîêìðú þøúú  öðìîö öòìîö  úôðôøþúöôúü þôòðôü þþþþüúøúüþøòððòø þöööú  üüôöú øöîîò úîèìðú úøøþ  þöòîôø øòðòø üøúüþþþüüúþ üüüþþüúúü üøöøþþ  þúðìêòôþöôôú  üöôôú úòððö  þøîèêôþ úöøþ þøòôøü öòòôü  üôöòôøþ  üúúúüþüüüüþþ þøööøü  úúþúöôôø þôòöþ øîêîòø  üüü  øîììòü øððòú  úøöúþüüþ øöðòôüþ  þþþþüúúúþ üúúúöôììðü úööþþøôúü øðîòö  ôîêðö þøöøü úöøüúôòòø  üöôôøú þüüþþüüüþþ úøöøú üúôöúþþúü þþöøü  þúîêêøúüòôôú úôôôü  þööôú üðìîôþøôðòøþþþþ  üüúþþúöôöúü þþüþüþüþþþöòòôöþ  úööü úöôúú üú  üôðôö üòêêîö üöòôú  úúü úòîððþ øòîòøüôôöþ  þúøüþúúü  úòîòòú üüüþ þþúüüþþþþþþüøúüþ þüüúúüþ  üøøöúþþþþþüøúúþ  úðððôþüøøú úöòôúþ  úòìîô þôîîöú  öòöø úúúþüöòôööòòöþ  øòìîô þúôôøþþúüþ üúööü þøöü öîêìôø üúþ þúüüþþþúöôöú üöøúþþøúöúþ þþþþþþþþþþþþþüúúþüúøøúü þþúúúüü þüüþúôôöøþ þüþ þøôòöü þþþþúøúüþþüúü þöððòú  þøôöø üôôòøþ  þúüþüüúþ þüøúþþøöôöþôðòø  öðìôú  øððòú  üøöúüþøôôøü  üþþøôôöþ øòôöþ úôòòú  øôîðöúøøþ þöôòøú üúúþüøöúú üøüü üôòîòøþúúú üøööøü þüüþþ þüôôöúüþþþüúüþüúøúþþþþþüþþ þüúúüüþüøööøþ  þúüþúöôøü þøôôöü üúüþþüüþ þþüþþüüüþ  úúúþüöööü  øôðòú öòòúþ úöôúþ  øôôòúþþ üúúúüøúúüøúúöôðòø þøööü úöôòøþ üøöúþüþþúúüüþüøúüþþþþüþ úôôôöü þþþþüüü þúúúúþþüþúøøøúþþþøööüþ üüüþþøöøú  úöööü  üúôöúþþúüþ üööøúþþþþþüþþúöòôöþ üúøü úôòôú þöòðôþ þøôöúþúöøü øôöúü þüþþþüúøúüúôòööþ  þøööú  þøøøþ üöôôöüôôôú þüþ þúøøüþ üúúüþþüüüþþþúúüþ þüüüþþøøôöøþ þüþþþþþüúüü þúøöøüþþþþüúþüøúúþ þúøöøüþüüüþüüþþþþþþþþüüþ þüüþ üöôöúþ þü üöôöø  øöôøþ üúúüþþüúøööú þþþþúøööúþ þüüþþüüüúøú  øööøüüüüþüþþþúøúü þúúøüþþþüúþþþþþþþþþþüü úøôöú üúüþüúüþúüþ úøøø þúúúüþþüüúüþþþþþþþúøöøücrossfire-client-1.75.3/sounds/Puke.wav000644 001751 001751 00000100314 14165625676 020721 0ustar00kevinzkevinz000000 000000 RIFFÄ€WAVEfmt +"VLISTINFOISFTLavf54.63.104data|€þüþüüüüúüúþþ   þþþþ þþþüþ þ  ""    þüúöòòîìèììêòîôòöúüú     üøøøöüööðððìðìììîîòôôúþþüþüþþþþ   þ   øúöúúøøöôòòðððòòôöôöøúüþüúöôèðììîðôüüþþüüþüþúøôððððòöööøôìâÞÊȾÂÄÈÌÔÚâêîôü  üòèØ¾ÆºÈ¼ÂÂÐÞæø $&&(((("    ìØÊ¼ÈºÆ¾ÆÒàðú$ "  þüôîîèêìîðâàÖØÜÞäðú &,,,,& üúòðääâæììòòøúø"  þúöððîðîììêîðøôôúü   øðäààÞâæêèìèîêêêòø (&*&*&$"ôæäÚÖÒÔØÜàààÞääìêø*$&&$öôîìèäàÞâÞÞÞäæòìöüþ  $&*$þøööðôòðìèäÞäæäðöü ""( üúòðêæàÞÜÞàâêêôú   þøîôîðöø þôüøü úúöúþþ òöôôøüúþúôìèäîìú þüúüìæØêäîþ ôôðôø ôòêêîôþ ôôðüúêêÞòæö "òôòòú øîæÞäæò þúêîì öüæääðö&"òîðôü  úìààâðö "( øìðîø  úòàâÜâð "& òìîøúøìâÚìèü$$úèðòø üìÚÜÚìò&þöìúþ òæÞâæø øøðø úððääîðþ þøúþüþüêæääòò"üðúü þòäèäêöþ úüôúü þðäÞÜøô  øòøþþ øúîØìäöþ.ôúðúøìäæîðøüüüþþôìÞììü  $ þþüæèÞìôö " øüüü üöæèêæö(üüúü üÞêàìþò  ö  ôîêÚôîô üþþúòêêäúêøþ$øüþ öòêØèäøø"  þüòèæàäúðú $üú üþöôîâääîøö "0ôþüööàäÚòò*$ø üþüöôîàÞèèî, 0ú üüòØäØðöøü(.þüüêêÚÖîäô ,$.üþúþòðÖÜØàì80(*ò öüôðäèÊâäìò 2&F4 úüüöúâÖÜÂÞòìöB0B:ðüôüþæâ¶ÌÄÊ èþ"L>4T ôì ðøüÎØ¸ÀÖÈîô$:J0JöüäôäÆÔ¾¸ÌÀø ø&8H>2^ÞâèàÆÄʶÀÞä,ôø@6BJ,RöâäÜèìø²Î¾´àÎ*üä,,<J:2L¾Ððäø®ÆÊ´Âê :äè$>6DH(\ÀÜÎò.ÄÖº¼ÊÀ°êFàúN4>J4: ¼Üîà¶ÆÈªþî* ÜP::FD¸úÐâÂʺ¼Î°"Æ,$J<@<F00âìüÒ¾ÄÀ¾ÂÆÐòø2,J8B@:H ÚÖ´ÈÀ¼È¸ÊÒàú H2L:<J0JB&"¤Ú°Äȴ̾¶Ø¬ 2N.L>6P0BR ÖººÎ´Äʬڶ66P2DF4J<4X ²Ä̰̾¸Ò°ÄÖðV&P:8L4@L(Z ԲÄʰм°øþ^*FD4J<8P*NòÞØ¬Î¾ºÎ´ÆÈÆüüF>6L8@F4H@.&âⴾ̲Ê´֪ò R.H@6L8<P8ÀÚȴθÀ̰мèV4>J2H@4X êºÐ²ÊÀ¸Î²ÆÌ  J>8J4F@4øÚÄԾθʼ¸âð>.BB<@F*,âþàòÔÊÀÔØÚÆð²* @0, 6 îÄæÜÞâøú&Ü *ôü øøÚôþÞúÚú 2,Æ< 0ÞÖàúæàØòöÒ .$"& & ÚöÜÔ´âÌÔÒÚæ(D 4J" üüøêØÜêäØÞîÐöü ,"$  üòðÚúîøôöúâÚ þ"øôà"äúúþþðüêäÜäþêèî 2üòôàâæêÚü¤ü  >úìúðôøòüÔìü* ø øòôúìêäúúö æúþøüæîÐøö Úü úøøôöøòîüÆüì ò ò:þêüþúöúúèìÔ&äîÞ .ì*øòúþîèøìþÌøâ,òî6 Ìúüú 2öúèèÌàü¸ þ.< ôöüòøðæäøÈø*îö.Ô øôôü ô0èò$ôÈþôäöø êöB   øøüà ôÊò.ðòöÜ Ü ðæüöòò8àöòèîòÆìÔ,(ú2,Úð äîôÒèàDöæòü0 Öè*öàøì üÒF üþðøüÊè¼úô ð48ìð òÞêìþþüøøîô*äüîþ$øÞ üô@Úà*þúòÈòèüü$Úþ0" îúÈìà &âÞ(êøþüôàüø ú ,ðÂ$úþÐîÌþøö <ðø öäØð ,öÐ& òÈúþòüÞ" òö êòðü2ð¾ü î°öôòô":öðòþôêìÖ80Èüø$úÔÂî àîäL ðò*þôô¾ôHâàæì6 Âô´ZþìàÞ(, Êð0ü Àôâ(>â¦&(è žà&<¸ÖlâØðD(Öìð¾<JèÈòPöø¨ø¼xöÈÖòD2¸îZìø¼úô(@Ò’D(*Þ ô(FŒþÔ$`ÎðÖödü"¸ðòÖ@<⬠lüð¼öº42üÊ´ú4*"°úR$ÒôÂþLîš6 FÎúÞÐâbØÔÒÐJ0 öÎ>0¶üÞ"ÒúÚ DÚøæü&èºì4öî*0âàø"Úüö"òèîî¼Øð4î ò6îàèòÞúÆ:( âîÎúäÐàü ø:ôüô òðüøúäôüÒðèRÒÒØDèÌ:".ðîþþÜþ0ØüòæîÊþøÌö4ö$øÐüìüúôüäB ôôúîêæàìðô" úüöøîìð îüÞ öÖú4ÖüÎ  î&6Þúìþü øò üðæ®â8¤ô"þ4 üNþÒòàôþöê,ì øâîà ÜòÖþ ü ööþððêôøþøø úæöîöôâôî òüðòôìü òü¶ðÐ>ÜàØøüH$È@(ìôôÞöòÔ >ðø(úúàºÊþìØ Dä þ0ðîäììæ ðÞ$ü,üþÎæÔøäêþäüú,þÜìêôêêôü$ èÂêÔÖìÔö , 0.ìðâìòâòÜèø. (êô¤ìòî¼øüLô(B$òÖîÚîøÚì¼.þ(""ÞêÒêÚÜèÒîê "" , &" ÚðÜöàØâÒ6$6äêÂäâàð´òê "(,00þÒòÚþÔÒÞÎ H T¼âš>Üü®Ü @*(êN"^æþÔøæÚôØÈÐÆfö²H$>$&0ÔÔîú¶ÔâÚüü>$þR64ðÜÜæ²äÞþ"ö $F( þæÚÎÎÎÞêäúþ$68(,þüàÜÒÞÚäèêD28.îܶà¢ÐÖ($(@D4`®îÖØÎÒÜÖÐ bì:$L,$ØÚ¸ºê¾à¬ÔèL(N<:88 ÎÒØÔê°Ô¾ Nú6JB* ìöÖì¼Àĸæìþ*4@<F"ðØÎºÄÆÚðÞòL0L(<62 üÖÀƺÄÐÐìÄT4BB:<( èØ´ÒºÒºÈâð$*J@$D.Vð¸Î°Î¼ºÒªôô\2>J0N8@öê®Ð¸ÂÈ´ØØ2L H6DB&þîÚÀÆÄ¼ÈÂîþò 0B@<@D$þÈκÂÂÄàæäüH4J8:8.2ü¸Ê¾¾È¸ÎòÞP4F<<H.âļ̴̺ÂÜø&(L::L0N0 êÖжȾÀÀòÞâP2J8B>@èÀĺʶÌÌôP2J<:L,4úæÄ¼Ì´Ìº¾Ò$<@<F6J"ôþÔºÄÀÀÂÜèü02F<@<$(ðÀƶδȼ H D<:L.TúüÔâξÆÀ¾Îð&,<B<D0"êڸȺȺȾ:æîR:>0J Æ:âľÂÀÔ²ìò$F>88*@ÄήäÀÖ®ô<.F$:J.TÖààÊÐ¸ÆÆä & ::>H..øüì ÀÆÄ¾àÔîîÆúXDðL."4øü°èèèä¸äØ $ 8$F8ä îÌÚÄàäÔΦHº84RTêæÆ,øÔÆÂòèÈ,6º\,J,èê¸âöäÐܰlî(òR(ðÎê æÔÔòòø$ì2:øöêþäîèêðîòð¾.$ìú& ä öÞêàâú ì* $ âæôʾԜ\æ4€Z$L:8øþ2.°ÞÎðÊÖ Èþ^ 6øT0,Ú>àЦÖ¼ðþÂä@ &Pú(PÌøàÈÔææÞä&*((âîäúÞæòöòìöþ¬$",þâ &Ü ò$èòæÚü àú ö$.üôð¼ÈȺ¾ö*ú¸@L .L&LÐæªìÞæÖÔø:8.D06úØèØö²ÜÖ¦òäd0 B4$F ÈìäÐÌÚØö 0.@& þôââØæôÞÜêäö¦,LÚ B êøÊê¼è."ü* ðþüÜêöÖæò¾¼J ´øN újÔÜbàü˜*Úö¦*þÖ0.>ü68þ žäö°èð´ìÞ.068 V èæìÚþÆÞÔð$< øâêèÚöÐô&ÀòÔþæ<úôÞîäòöÚ&  îB8äêæ´âÈì®ÊÌ,"F8@JØ(ÚÚ¸ÄÊâìø8.DH( J ÐØÜÌÒî² üôÖúdþ$Æ äþÎ"êèþ& è âþì(è".öÜòÜæ°Ô²Nä°`8:@BÚPòôªÐ¾¸îþøX FN üðäØÚºÔ¢ èòîîb@Æ0ðú´òææþ<$ö6ÖüÔ *ö(> ÚÒôÞØ¶Ìºü ÄL8<F>$ôà:þжÐÊÌîê Ú2*T86. ºÜ¼þØÊÊÌ"öüüê^¸öòÈ,êðöþ Øòæ0ú, ìâôæô¾ÌÚ¶äÞZÜ&J0,6þäÚÔÂÎèèö (@& $ 8âòàìöè Òòð üòÊìúBÎöÖ>&àN ¶öüöòþÞ&üü"Ø"ôþâ ÐøðÚÒðø  2ìðìòâèôòö ö($ øð äêöòèØÞÔèî,$$ è úÀðàðøô2àöî(ÞúúèöèäÒâÒþ "&úôøúâêèô øê$ "ìüô ìøÚøøøæìÐäÚ"*ð"ÎðÚòüæ >ö.ÚúÆHòàþöÔöÔØöì.ô ø, ì ôòðÚäúôè üüDäþæþàüðøôììêêØæ ô(ò þÞìâööþø*  ü ÜôÒ2òôþþøÞøîÞâèÜ$ú.ôþîÞäöôþ *"øøîôüøúþøðððæøÂìÞ:ð$".öîòêàÞöò úþâÖèôî$øêàòèØìðÐ"ô&&îðôÜèèöú $ þîîúü òîîÞÞæÈø*4(üüüôÔâàö, úúöðàîÜ þþ*äæìÂîâôâ ($( øòêÜææðì ððþêîö  üôèèÜÚæÒÜî2 04$ ôîþêÔØØôö 8þöòìÜâìî $6àêæÞÊÖüàòü2*,0ôîÞðØàêîø&þôìàäôì&üêæâÖØÜÔæÆ2 6ú4,6  ØüàìÊÚäø &(4öøââØêòð. "@üðÖâØÚÂôæþæ$ $0,* öÚæÜÜäêúú&"úæääôðîþ ",øèÚÞØÒÜæØøòF66&öôÐúÜêÌîú &0$$öôêîÜäâê*,(2êÞÐæÈÖÒò,&(2 þ öîÐäÜâòø "(ôìÜàæìúü ,&("öôâØÎÒÔÜèüþ <,. " øæÚÌìâøè$"" æêàâèæðô.*$úÒìÚÖÊÜìâ$<øêòÎäâö& ðêäèæìøü&  ÜäØèÎÞäúø(þüòðèêêü üüôèìîòü""ü8 üôÒîêîÌøôö îöòøðü  þúøðôüöø   þøäìêîèðöþ úþòúø úþüôöüüþþ"ü( úâúðôÜüôøú ôþúúúüþ  úøøþúôú  ìòîîèîòúü  þüúúö þüþòúüú þ þúäöîðæôþú øüöþþüöúøúô  úôöêîôúòúüþ öüöü þúúüøþ  üúêúìèôöúúüúöüüü üøúøüüü  üìðôôìôöüú üþüúüü þúþúüúþ þöîøðòîôúø  øüøúþú üüüúüøþø   øìòòöðöúöþúþüüúþþþüúþ ðøðøîòøôúþü  öüþþü üüúüúüúþ  þþêôöðöúú úüøþúøüøúþø þ þüþøôôòøúü þüüþüþþúüúüúþü ú þöüòðôúúú þüüúþüþþüúþúþøüú ü ü ò øþôòôøøøþþþþúþüþþ üþüüüüüüôúøøôòöúþþüþúüüþ þüúüüþü þþüøüúòôôöúüü þþþøúþúþ þüúüúüþúôþôðòôôøüü üþüúþþ þüúúüþþúüü öüþøðòøúüüü þüüö öþö  üüüþüøüþ þþ  üúúúðððüúú þøôþúò   øþúúúúúúö öúüþø úøêðîöøþú  þüîúøðü  úüøöüöüôúöúö  òøêîìôüúþü  úòòþüôü  þøúøøøúø þøüú  ôüúìîòøøø ôöòôþð   üøüöøúøüúúúþòüü  üþòîêòòüøþþ ðøòîüò  þöüøøøöþþþúôøú üöööæôòôø   úîòöôþö   üüîúöüøø øþøðøþüò ìêâòîòü òðìîöö   þøìöòúøøü úøøôðþúþö ô öúØìèòòú úòîäòòþþ  òòðìööþ   üòøîðþö$øðèàææìþüüèèäîøü öòèììöú öòìîòöþþúòúØââèòø"þðìÞêìò þôìêâðòü  úöîìììþþ òúæÞÞàæê " þòæÞæêòü (úðîæèèôúøðìêèî (üðöààÞâòö" öðÜæäô  "úîèâîîü þþêîîôú öúðìâîîøî ôîêäêüþ þ øðäîìúþ þöêìøúø  þúððììê ööèøè þðòðöúöø þööèöôüþ  þúöôòòìøú öüòüþî ôöøôþöþü þøôðòüþ úøøðôòü îôöú  øøîúúü üøúîôöþúøöøöîø  þüúìøôöþööòòüþ ü þøøòþèøüú  þúöòøôòòþ  üúúèòú þ "þøîððú  üôôöîòø úøöòòôð  úôîæüøø úúêððî òôòîòüþ  ööòòîôúúðôêôúþúøôêðò  þþæìöäðøòîúìô úøúòöòòþ  òôðúðøîüæúîîøðü øðîäöðüø  üðôîöòôüú úøâúðúðø  îðèìøü øðìèððô  þòòîôøø úúòúâüúìôòøþ üúüöîîêòø  þþôðòöþ úþþüðúð ôúÎöþú  ðöðôìðîü þöôòúúüðøðþôü öøúìü ðüøøøìöò  úøúôü þþøîü îþöþþüøòþúüþ ôüøöòòüîü þþöúøüüþâøþôþ øúþôüþ þüðþúøðüú   üüüüüú üòøøúöþòþúþ úøúðþúüþþü   þöüìøøúþþ èúòôôêú ê  þöüöìöøì ôþþüþøô öôìò ö ôøúøêöðø úüüþî òü þøúöüöþüüüúü ôúøüúøþüþþüþþþðþúòúî  þþöüø úôôôþ öüúøðøööþþüþöþþöþúøþþü  ôúþ þòøþúøüþôøôüúüôþüðôì üþúüüü úúöðþò  øþþòøôü þþþþúüøþúêúòú øüþúüêü ðüþööøð üö  üüöþþúôúüþ þöþüüìúöþøúôöòòþøüôüøþ øüúþôü þþúúüüþøöòîô  úøúúîøöúþü üúöø öúøüúþþüøúúþ üþðôîü üøøöôòúøúüüôøøü üþúøöøðþ  üúúøüü þúøîúøú üüðöòøþþúþüúöüþúüúøüüþ  üüøøøþ  úöôîþ úþúüüîöòþü þþúôüþ ôúúøöüþ þúþôøüü úöøèþüôøþîôôøøüþøøò ðúúööúú  þþøøúúü  þúúúòîüþøúøþòöôþ öüúþúøþ  üþúøúøüö   þöøüøþ þþøøøôøò þ  þöðþöüîúú úøúôþþúøú  þôúúøþöþü øüøøþúþøþüüþîúò äüôðüìüòîüþþò ú  öúüúð  ôüüþ  üþúþúúúü  òøööüö þöüüú þúúüüú þþúþüþüþúúþúüüüø  òöúøö üþöþüúüüüúúøþþü þöþüþüþúþüþþþúú öööúôþþøþüüüþþüøü úþüþüþúþþþú öøøðüüþøþ øôüüüþ úþúüü þþúþþüþþüþîúøüüüô úþúþöþøþüþüþüúþö  üôüúüúþþþþþþþþþüþüüþþþþþþþú øþøúþøþüúúúúþ üþþüþþúøúúò øøöþøúü øôþþú üþúþþüüþþþúöüìþøþü ô úþüüúúþþþþüþþüüöü öúøüúøúúúþüþþüúþþüþþþþþúþøüöøøþüþôþþúøüüþþþþú þ òþüüþü ôüüöþúüþþü þþþþö ü þô þøþþþ þþþüüþ þþúþø öþòþúúþüúúþþüøúþþþþþþöüúúúøüúþöüöþüþþþþþ üøþüþüüüþþþüüþþþüþúüø  ðö øüøþø úüúüþþúþþþþþ ö öþúúüüúøúöþþþþþúüú úôþøþüüüúúþüþþüþø öîøüþú þô üøþþþþþþþþþþüøôøòúöøüúúþú úþöü üúüþþüþüüþþú îþöøüüü ô þüøþøþüþþþþüþþþþþøþôöîüøüúöþú üú üþúþþþüþö üþ þüôþöþüúüü üþøøþþþþþþþþþòüüþþúøüúøüúþü üþüöþ þþþüþþþþþøþ üüüüþþüþþþþþþôöüôþöøüúþþ ü øüøþúüúüþüþüþþüúüüú øøþðþô ü þúþüúüüþüþþüþþþþþþúþöööööþúüþøþø þúþüþþþþþüøüüøôøöþüúøúþöøþþþþþþþþþüüúöøúþúþúüüøþþþþþþþüþüøôøòøþüú üúþúúþþþþþúþúöôþüüüô øþþþþüþ þþúþþþþþþþþúüøþúøþòüúþ þøþþüþþþüþüþþþþþþþøþúòúøøþúøúþ úþö þüþþþþþþüþúü úðüøüþú þþþþþúüüüþþþþþöþøøøøúþøü úüüøþþþþ þøö ìöø úøüöþ üöþþüúúþþþþþþô î  øüþúöþúüüþüþúúþþþüüø øþúüüüþüüþþþþüþþþþþþþüüøúþø üüþþúöúüüþþþüþþþüþüþø òþüúøþ þþüüþþþüþþþþúøüüöþü øüþþþþþþþüú üþüþüþþþþüþþþþþþþþþþ þüþüþþþþþüþþþþþþþþüþüþüüþüþüþþþüþþþþþþ øþüþüüþþþþþþþþüþþþþüúþú úþþþüüþüþþþþþþú öþüþüúþþþþþþþþþ þü üþþþþ üúüþþþþþþþþøöøþøøcrossfire-client-1.75.3/sounds/knife.ogg000644 001751 001751 00000020247 14165625676 021076 0ustar00kevinzkevinz000000 000000 OggS/ðqi²vorbisD¬à"¸OggS/äëÂÄ-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ_vorbisXiph.Org libVorbis I 20070622vorbis+BCV1L Å€ÐU`$)“fI)¥”¡(y˜”HI)¥”Å0‰˜”‰ÅcŒ1ÆcŒ1ÆcŒ 4d€( Ž£æIjÎ9g'Žr 9iN8§ ŠQà9 Âõ&cn¦´¦knÎ)% Y@H!…RH!…bˆ!†bˆ!‡rÈ!§œr *¨ ‚ 2È ƒL2餓N:騣Ž:ê(´ÐB -´ÒJL1ÕVc®½]|sÎ9çœsÎ9çœsÎ BCV BdB!…Rˆ)¦˜r 2È€ÐU €G‘I±˱ÍÑ$Oò,Q5Ñ3ESTMUUUUu]Wve×vu×v}Y˜…[¸}Y¸…[Ø…]÷…a†a†a†aø}ß÷}ß÷} 4d  #9–ã)¢"¢â9¢„†¬d ’")’£I¦fj®i›¶h«¶m˲,˲ „†¬ iš¦iš¦iš¦iš¦iš¦iš¦išfY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY@hÈ*@@ÇqÇq$ER$Çr, YÈ@R,År4Gs4Çs<Çs|BGlF†\JÅLN=RC-V‚ZÁ ^² @ ÖškÍ92ÊIk5çä$ÅÞKfbb,!3F9i5¦P!¤œÕ˜JÇ”bRcj¥cJAl©¶:)µk*ƒ DÈL P2à!A (,0t ¹„ŒƒÂ1áœtÚ!2C$"ƒÄ„j ¨˜ò Cc#í⺠pAw!Abq$àà„žxÃnp‚NQ©ƒ@€€dˆˆffŽ£Ãã$Dd„¤Ää%E%€à Y"¢™™ãèðø !)19AIQ OggS@#/G½Àili8;kmingeÿ¬ÿhÿNÿPÿ`ÿiÿbÿPÿ¤ùºT*«&Dûëôp`®{{–Ç/4N–ßŒŠ—ò§f=}>_®ÓÃУӅÓx}·éÛån(êÔUãä…å……*>xRF±DjOÛUGëäºsóžJ©~à8ׯœ¬ga†˜%þ~ÅØ˜ žô!+´Åî“”åòø«ýù¶Ž›«ÇvÃö¿¬äõúúÝFjŠ›íÿ¬jÇ›¾^§—––Ú/Nò¥ñÏÞÆ'i)"_ÛÅqÍzäHŽVÎ%KÊÕOã\×—{ì®?]i‹--U/,Ïí¿ô(t„&ۮ†éçµ³Í{MÛO‰ŸŽûýü’îóÛÖo®–·LÿWÝùõëlJW?”N ±X¼§ŸÃ+î\¼àË9¼¦|.„šh‹œêžn–ö­K]&Œ–gïO)e×V»ÂÞeçN{¿ÎÐL!d" °gëïýôF ‡ÕäËšþoU5¤¨Iܸ[e½‰‘Û9²ìÑ]$>€Ûuîô¦N„&Q¨\æƒ,çXé ë´ú飥Å;_:ãËÅö f"dïàí²ìÞݽY€žS˜ wÓáAC= ÂDõl*gÑN<Ñøñç{5w.}vLëåëe‹ø°=1þøóæ»ùÙùãs5þ˜ør¥ F‚_²Õ¡zjNÜ›?Ï=ÕÔ¦_¾TóvŽº¬Üå@ýIGþšûXvq¿â è˜Í5úv·šÕüþ;•2k¶t:-0¦t•œÄùŽéª8RIêØšÚSþz|÷²|ÿRmfã‰| {¶^žÎÑ ”€hh·;N¥”R?f툄mò…y#º*¡Ú ½Mw­ þh憜B›~sD²JˆŸ\+‰'ÎxUÉßг^TWŠS®‰¢¾‡æšÇ%eD.«~—LWÕÛŸ4›Žï÷ûïõÕíQÔœz;{DõH·U¢Êe^Úí¾©ŒíÓ=Ã0YtÕp‹­ó€ÂkŠ*¹¸Û9Q¡ƒÚˆÚ ¤…‰‰mê?¸2&nòÀÝ Ì–Tv’nÙeÀVÇq¡8BœXhú%ÓÅ õÈÓ6ò=Ó©ëH?ÿ;]4üþrÃwcõ»ËÝuá5ð­A®L°‚"~SŠÿcRžØÌg9€ʰsµÚø¡y^£@ÄœkkîúC œ#KÌJ /ï•4è$ª¬*hÃç@|üÖK*ý»êšÏ»zXeH“³­½½Ù÷C˜Ï«„àÒkHßdÌ >÷r¡lOîMu¼wDVš&·zͱeXQßo™OéU7Žb¿Š¹xÅù\øÙ”Ã]"Ó5" 9§ôGÄÍ´;ĵ×9Ök5r»ýeëá“‹ìô9dMKÜÌ!ÿå6¡^‹¯åîf×aÈ…[|¼=ÊñYø €µãŒ7ëœhÉJW¬ª“RÕÁÛñ½ÛÂøti #‹çõ©^ÿöÍPZZÀã]Ñ|´ÑÑðÙ6U4k-—C Á'NT×fFÜ¥ÉëÕœªÝ€—t+Á2µ±Ô4ý!BL̉hû{jã;Ådž´ ;Œ”MÈÈœí¥ oMq/[“ìØÖ„È7Ìž³CL:y˜B'Üžnþó~e6øZ>yä¸<—hV`t2tˆ”Kc–PÁlfõcévwhhí*•T’Œ}y8z*Õ‰îe¸p±ûYïöh gMHÂ…=‰ân:¡“• Þ= F¤'§Êe’’YäæÙ8íÉ?öö§1ÙØÕG¼U×ͳгKvÍ × í¼Ú¿Ð›a@]ÇÃXë…ðÈ*3û­o´=Ù¸•q¯!®‹.pxxs…Iµ]7¿߇ú%²Ø[üñP=óدLÇõ­¯#—#¸ù<ôu”6ÊßÃul$qÈ:#ãx ž×Oo޲/ÿÇvË í7ñtÍéz’²P˜Ó^ưJ6IŒÙË]½™¿‚¯ÑýXjì¾&¢ŽÐÉK¾€0“b*^B›VèËÁë‹Ók„(xµÛɸâs"ëEZúŽÈO· ®-6î“ ;8F8û¡ÕÏiWµuM:%cçx°å^BD_ò¬²ÓðóXBgó^ÛÐ^wÕrjkÅ$’Ç#·›£­ `׌¼ã!–}þÌY*I4lYõÞ˜t$ÍggÛÖ´[ËDXVužŸJêr8˜.ø-<üåÊzÿvÓô8[ŽqïûÅÒÇ=¢"GxPj1\j–·ýÖ~9½-Åß_©Þ9ÎÍò„;³¢ñˆÞ82Ï­Ï-Ö¥-›ãBk·ÎnÞ<él42åWc“TÉ{×]¬ «­¥ÛZ¾ã°ÖjÐY)’ >ÂP 1PkƇíëŒW WdÝ=È]Ú|iþã9sA³èWŒ#‰‘•¦§^(Ô[uÌÛ„lAÈýäØ};‰db€ªM/Úã#Wâ‹–-*ØQŠí*S®0nZ•I¥ðW®ªÒWg‚³P FÞ@c%Œ¸M LwÅœ´yÈ”eJ-j>Ìfôdè £©FýšvÁRÉBÚ; TЬ¨cÀ£Y+ÿÜSE• ZËÕÇY77T‹êxº–Ýò·på<ê†dGJ9™Ç&WCH»´ìÅ4¨†(>C™¡uÌÓÏÙ¿³WkdHç"•ɶ°qwõØ‚.ìEs)J®º¾kÍc£ÍGpãè.uï¼`õf´ _ü’šzì2ú¬p1<Ó~”€aÊÓ»1§6 ZÿÉŸsé´¬Ê`êFÛLl´Û›ºÅôB›¿n%ô^e¨ ¨áJé‘ ™_Ö*1§YL/å¾ Þ,R.Ì4-‘áfc6ß VºÔ^¿>½.z»ß µlo†ñ”DY\åB(‰Ö|RÁ{”ÉÖ†æ·Ù¯ÕštjÛ±ó—vl¶ÎÞUž Kl–IJTr”`DE]$@€ÝGY£ŠìÀΔðæ¦~u2/Çã¶ïžC%œˆ+ž÷#-%qS›Lä¬^ËfŠð}{_оIßÖ3P] â@Ù€Pêºv;zå`¿@p^´UbWe “9¨†î6¶!Ø>´×þ9g–Iäúwã5´³{3>Ë:ߦœ-APÙÂkµfÓŒs†:éù†ð.‹nGÿà-¥_&ÉÜ$MVÞçíg²…ŒU_Gm§ç÷¶hbšŽÉaS♨m¾élꃂ7Ä­íâ J¹Á@¾÷¦t½ýpnçý/£Óͺß,~po©7‡‰~ 4CÞ·ÓÂÁ4‰’-š#>wGbÔO§©Œåçµdd5#¸õ€ xAlòy/+I’’Õýo.ä¡KôÕ–2)ËM ;Šå±¼ zØ=l9®¼4ï’®{ëÙÙZ[ B—2N€É<Êxï¥ñûÌx’HÚ¶mW—š»ï Zg©a.5eïF€ðcìcÊÇã4çÅ$èièVøì^CxtÍ õ.ÆúØš|_Çä\qÆÃ1€ˆ9}ZL}©ÅÀ畜·5å¾N`(×ôG1KÇþ¡çMÜ"BÖcbBe¬ù¿ÿ£ªø¼?Æ)0¬!PÏ5X 9ü=;È…‡«þÞfð ó/k#æ)Z¶"¹>S²¹/ÈHЯ&©nV~Z?',8û:º\ò6-#êúŸ)ºƒ"îŸVp5ïÚׄ¾õ[×[D¬fŽœûg„LÆŽÉWvq$–`b3©*HHãÉ2¦WÑråîôi¶x÷|Û°]ÕÆØÚÙ­;»u/ʯ¾)È¿àÑãlD^š­ýtÞg¹‘ÜoÝj?ÎæpoÊ_/V¯(leÓ+ÏèMÂ3†çã˪1h7öàüã:ã»ZÞœzêɃ ¯_´à¤u&«/Ön1<É7qϵÖK®2†y’og#²“€ïb™WÇ¿·À›G”Q¦cÎî>²ÿváyÇǹ[Šçîn;áŽÕ¬€Åªž¼X®6ß!›%¦Pq +çÖBCW ’›WOggSà%/„Ù¼!S–Œ¬¥zì¾Õ0wÅŽU¬Z!õE5µ=ù1å3À(Pcrossfire-client-1.75.3/sounds/fist.ogg000644 001751 001751 00000014742 14165625676 020752 0ustar00kevinzkevinz000000 000000 OggSèÕÛÁÄvorbisD¬w¸OggSè_J‹ü-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎvorbisXiph.Org libVorbis I 20020717vorbis)BCV1L(Ä€ÐU ˜6k§µÖZk‚¤vZkªµÖZk&µ¶Zk­µÖZk­µÖZk­µÖZc 4d@(J´dRLJ)e GŽrä9HÊ'¥(G bâ9è=õdkM¦¤ä[MJ)% Y@!„RH!…RH!…bˆ!¦˜bÊ)§œrÊ)Ç ƒ 2È ƒL2餣Ž:ꬳÎ: -´ÐB ±ÄSm5ÖÚsÊ(¥”RJ)¥”RJ)¥Œ1ÆBCV BdA!…RŠ)¦œr 2è€ÐU €ÇI±ËÑOò$Ï-Q=Ó3EÓ4MÓ5mUwuUWuÕVuÕVeÓ5mÓVeÓUuW—uW¶u]×u]×u]×u]×u]×uݶm 4d  #9šâ)¢b®â:ª„†¬d  ž!*¢&j¢æižçyžçyžçyžçyž„†¬ iš¦iš¦iš¦iš¦iš¦iš¦išfY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY@hÈ*@@Çq$GR$ER$Çr, YÈ@R,ÅR4ÇsuVåTá£4;¸²nÌ’íŒhrý²Zô>à›µsØU ŸzAÁ‚ô5 = øçH™Ð’ª¥·¿oÊP¬ŠµwಞF­-}œ@»’ì‰ñÕdÕ»4½–›l(Y´üàž_ÿ¢ÄAdióËHï‘4ÀŽÄŠÙ+‰¼ŸÄj¨†×U×M<3Vn‘­ê«l“¢æ÷`²QçðS†«öÌc¢h#ä‚…'XÿX„>”ÿ‚!ï¤ÝL5Ϙ¤ õÔðÖ¾ñ¬ÔÇ š&ñöáVŒWOIñ…ûärÅ Ù—¡ê‚¦ý×ø\燖¦íˆ0Þ ²¼åßÐ{d}ÊÓqœâT_ Ë~3îAÌRK 0ˆkçjÐùðß6c‹¼4d_;/æÅ‰GÍSŸ-S‡6¬×áÏ @F\„%§ ,\J[&× ²ÖgŠŸ¥Y iª¼ªð @íþŒÆôKæÐ)ŽyÁ3î-ÁX ? «pSTŒ:1`†·àê2†‹^rT*,MþYí»{j«ÞþqÌr øÆ/<èùoàƒ¦Ÿ4îÏêÊŒ%¶öcAÃûvú+Ùïó€U E ú–þ$]”v ÐGûW€ª`O0VDºJ>›ÅJ¬Êjª±·=’éâqÛ®á02I'ÀôÈ^Ü^]ô0”ÏñOPŸ[ÌÀ˜¥ó!Di¯¸1ú@ÚB—í=ž½]g<’º…ÂÄ~´^KRðÆõθ¡57fÝO{öÝùx¾u}œN“w›TrY¼"•öõžyû>¬ú)íBY´ƒ :¿'nÝ>˜ÎaÞ>$`šFzqfTÌÀu>õ» náü/x§²½Ë>9¹Ù²6_y—óÍÖßõ£']z2‚Æ SÀ¢Èj‰íŒÎ\H}c?hK¢£,NÛ§OQO©x«dÝwÉî1£êb·u¿Ïùêüž¾SÏÙð¸Å<ü¹Yl*oZÌ ‘R‰D,åçåñ#κÔõX s+7ÒwSc’jáãõ“æpÐ/,d/OcÛÖÓ`@Á ó Þ1‘ë¨FšZxm1Z|¯“ÔrƒÒ5§øè“ÆuÞÊ´«J@¹Ð=…c#Ó¦Ge0_¼?™:Ú—pqïRêÜóôçgûŸ¯ø™÷7y´«¢ŸÇ°#‹˜~ …s×z7É;(¨–«ÍĪ‹ëK¾]öN³BrA±A•™_y,sÁqŽLvç7÷tÀ€Ê]=ßgú¡"ð×´ ÷ö[íLeÆ;KÞ‡ Ô«"ÊGáß £MŒÈý áx‘…UÍ̪y5†¡¥ó‰ð$Æõ‰ˆí…àGœüÛz-ô˜C´÷ ìëÇàhD_] 4K~º RJ〠ÿEÏæ$LÃSs4%“ \ÛòüÓŽ)òå!ùršË_üùPÚ««®fÛlËv·”à™@Š-%<¥Q=}ö1îÌ/“¤'†ÄòãTÌ‘³¾7‘Óì@vFi[±} EkÙMÅW q[½ÏÖu;eÒcŽÆ£UýÔ…&ïØ·Œ6ÊùüfÏ-$O½1éyÈÛì¾m¹S¡KÞ“lð¼aßÚ|]› ë CÀ¶á°à»5¦åçÖm ت@Ð…©ÏÕÆ¬-r$4ÁDWã¯hëLÚ,¤2* E?§‘ÛYÑ“9˜â"36«lØ*Omuaç32Ò¾åša9wèïŸätÇêС|÷D“ÍÌð}‡NCæ=ãë#¶#äðì³zß%È[ R»æÁ†ÑAÕ`ò|©sÜ·b1°ü¨ô/ÍøUûØ[bn‚Nám6K@àÿ[*Œïl®Žùeë»°;ñrűƒ©¦õ;ú6•î†Ã̘(Ì,pv¸+ŽÔ\`Iƒ9Ôë×^CÏÌÙÛ†cÂ#3Õ/¤£LqZ̆¬Ÿ­–'Âà`ûöó—ú=÷GµÝ­Óf͈[Ïÿsp$<—½×ÚÊ&A´Üµ«æ“„çʈÒFOÛºN™‘öÍÊÛ;lÅ$¶¦%˜ˆ3MÌ=ýŒÌ ÞŠË hLŸ# dÃkÊ¿ôïAk%¶ÞD˜eƒu˜4øø¼•yišHË-¡`è-Þž]žÄIêö£µ(ÃÇâȵù¶Ì€‡ê´7y…+ÀècòrVÒOW­©Àa^>ÇcVtÔž—›bàš›¸Q羌´J ¤õ>tä¼P8Z ß\]׌СÜ^¶3ØA9_ pvôîm*ÄñŽ)X` À£xÍ€à9Y ª{¼ów÷°±uÛKfy2[]=ôÚÀ¥úÊÞ"3Ñšáó;\ðEñ*:’˜Gäß<³å¸…vK6ƒV&Þ[Mœñ,ÈÄ*¨úÓ P“ús¯H‡uÙr—è?Yo¶WE‘ßbAj  ­¤» ƒ‚ì ç;j”í Hú¸f  ¦.ŸX²n°¡O|/c-µƒ¬—:¶¸1 ]ÞþDÿÖäv”Ž»ÒºEl‹ãÈͶÀ÷úö0Øyž æ= Œ"„žª”RÙg†zà>%&~îf`x:9yõâÅM™>œ¬ù¬s­¯)×ë5kÌòê¹¹éæ¦›KŽç„v¿6>IÈ9Ií¿I63qz'óz¦Ût=w3+ÝËdžÿÉ5„õ‚ç ã´“§ƒ\ƺɜ“——GÄ1±o°¤àó"%µ…9tâ=?ã×¼¶»`”¡= ë™à€ééi€m¹mz§°K¦-ïZ™öà ¶¥Q+7½àGâÁ/crossfire-client-1.75.3/sounds/swish.wav000644 001751 001751 00000017464 14165625676 021167 0ustar00kevinzkevinz000000 000000 RIFF,WAVEfmt +"VLIST.INFOISFT"Lavf54.63.104 (libsndfile-1.0.25)dataÒþüþöý üÿøýÿøþþÿøüÿüÿþüÿúýüÿñÿ þÿÿòúü úþÿöÿÿïüýýýýþþ üÿÿüþ ÿø ýÿþüþúÿýüþíÿþÿÿúýþùÿÿþý úüÿþüüþ þÿüò üþïþÿüùþýÿ úüùüýÿûîþüÿùÿþü üþÿÿõþþåýÿ þÙ ÿðÿþÿüýïþÿýñûûüúÿýÿþýýþý úÿÿþÿè ÿý÷þ ôÿÿúÿöÿÿêÿ'øÿßþ þõúý÷ÿ üîþ ÿïþþÿûÿýÿ÷ÿñÿûþýýþÿþÿöÿ þñþÿÿýÿþñ ÿÿÿüÿÿÿ öÿ÷ ÿûðÿ þþñ ýðüÿðýòþáýõüÿûôÿ øôöþûøþëÿÿêüþùýÿþþýõ þýÿ÷ÿý ÿùøÿ þýÿöþþöþÿýÿþùüþþýþöÿþüÿÿúþÿÿè ÿ÷ÿõúþ÷ýÿþøüýôþ þþë þÿþõýÿöüþÿãþðþüýçþòÿÿýþõÿóúþÿòþúøÿ üÿÿþÿýþõÿó$ÿçþÿúÿûüÿïý üï ÿêûý÷òýÿîý#ðÿõÿÿþ÷ÿÿ þðýýìþýøýâýÿøýúýÿîþý ýòþóþ üüýûòÿÿÿûüÿúýýûüþý ûûúûñþÿ ôþ ÿûþÿýÿùöÿùþõüþýÿèþ ýÙüòüþ ì ÿíþóö üèýûÿôýÿüÿÿôÿÿøýüþìþ ÿù üÿõÿýúÿøýÿÿüüÿ üþ÷ýÿÿòÿþÿ%âÿ÷ ý üûæüþõàÿúþñøÿøýùòýýùýþþþòÿ!ðýÿöþøýÿøüüüùüþ ÿñúøüþêþýéý þåþêþÿþþúþÿÿüþÿôý÷ÿöòÿ÷"æþþ þ÷ÿýÿÕþÒþ üéÿ úþÿý úÿûüþÿÿðþÿöüÿèýÿýÿúÿÿÿþÿÿòÿþûìý ýÜÿù$ÿåÿûÿïÿýþÿîÿ ÿ âÿÿýùýÜÿÿûÿóÿÿØý3úýÐý;òýõýêÿôúþþýùðþ ýí ýýÿýýûðýÿìýþýÜÿÿüü øùÿðüÿ ÒÿþÿòÿÿöÿøÐþéþúîÿÿòÿðýýøýèûýêú1æþÿüÿþÞÿ ôÿòþöûýìü+üÿåÿÿÿÕþýøþõýÏþÿÿÓÿÞôÿÿ4ÿÙýó2ûÝýï&ÿëþûþÿæð,ÿåþù"ÿíôþöýÿþÿòþ÷ìý+àþñ4ýÓð6þõôÿÛ<ÿýÿÝÿÿØþü,ýÙþñ(ÿëúðÿ5ðÒþüº:þóýã*ÿûþüþÿäþÛÿ!øÿÃ6òÿå0þ÷ÿéÿÿþùûüí ýýÙþGØÿñêÿ=Øþÿç8ÿåøÿ öÿ÷ ÿóÿ úÿúþÿýøÿþùþýØý ÿèÿÿÿãÿýöÿððþñ0üýÊû ÿÐþþóýàÿ/öÿÜÿþÿÿÿýþý®ÿ+0þ· ü÷Pû«ýï0ýáýêýþõêþúþá(þéþÿþÙ þòþþ·Xþý€ÿçæþß@¢NìþÛ"þû üÛúÿBú•0ýþÿÑÿ,Þüúÿýô:ÿÓý÷.þéúÿà þ ÎÿÿPý³ þñJþ£ý/¤þ)Fþ‹.þ ØþßýüÃüþéþèÿ=Øþûøÿ7êìüÿÙ Øÿ/üøôþþÙ6þí¦þQòþ ´þOü¥ZýéþÑFþíÔþþÇ( Ú&ÿûôýï(ü ¼ÿ èÿó ÿâþó6þÙþÿç6ÎöþG®ý ýéòþÿN¬ÿþõÿí¸þcý €þÛÿ×úþ1Ìý÷ÿ5æü¼^ôôÿ±Pþ¼þ "¶>þÿþ»8ÿÄþ%þþìÿ!ÿç&ýïúü¸þEàûÉúüc¶þ &Ì àÿûþ÷ÿÿíþøúÿßæ ýÿ½Lýùðÿ1¦üû=Šþ'þ,ý¹þ÷4Ðþ.¾üþÿÿìÿýÿýÿÿ× þÿ ýñþýñþÿ ý§Vþ÷ÿáÿýäÿøÿQÌÿÿâÿ[¸ÿðÿ êòÿ 6ýLüÿ ýÓü þûÉýõrûŸûítû·ÈûSêüõÌÿ?úÿêÿûìÿQ¬ÿãhÂÿõÿ!æÞÿ#ðÿ"ÿ­ÒÐÿ÷Òþi¾þÿüÿþîûýü öþüìèüÔ þòÿáýûîùóúäþöìÿ!ôýÿþâÿíBÿÓ ÿ´"þÿã"þÃ(ÿù†ÿeÿÅ$ÿ#²,ÿÿ ýáýÿ>þŸ ÿ ÿÝÿôÿ ÿèý ýÕýý úÿÿê$þ÷þ•Jÿÿý½ üýèý½PüýXòÔ(ý÷øüòþý*Ð ÿ ÿÿöÿý(þÉýûðý-òÿûÎýUÈÿëVÿÅþë<ýÕýç:ÿßúÿó"þíÜÿEÒþ7äÿåâNþÙþùþýÝþÿûòüÅ\Ôÿÿ²þ~Ôÿÿ’ÿ~ìþù„hÿýÅþñ*þô’^ €dþÿB€`ýý\þÿ÷ÿ#>þÙªHþý¦F$úÿÁþ¿öý ü¦ýOþ/šüÿÕÿaÎýÝôÿOôÂÿõ@ÿñØÿÿÑ4ýÿÒÿOÊÿë,êøÿ¿HýöüÃ>þÿ ®ÿøöþÿúýýÝ ÿýàðÿõ>Þÿÿòÿ' ÿûÒþs’ÿáLh´¦<ÿ?ò€ÿ¥æ üêûÑVþÇ ÿ¿2ÿÈþÔüÿRÿÕðÌÿ~€ÿÏv¢ÿõÿ/ôÖÿ+ôýáþïþÿWÆþ«þéüý‹ýÕ þµ.ÿ"ÿµÿúýÝ ýæÿÛ ÿ5öÿ¹úý~€ýÞ€ÿ  þÕúýO€üO2ÿ³ÿÿ%ÿßüÈþ[æþ ŽýSþþ'œÿ;æ$ýá²ÿ~ÿ…ü›ÿ›ÿóæû!þ Îÿÿ ÿõøþ-ðöþÃþúXÎþæÿk¬þþÑ0ýÆü ý øâdÒ JΪšþ÷âü9Ôýñ2ýÉÿ%Üúÿ"üÿõúþøþºÿ#þþ!Òþç&þïÚ$ýõþÿåÜý[ÈþÎ|ÿÓ€ýÍýƒÿõØÿÛJü'€û~Úüãÿ þÿ§lÐèTÿ« þ¼üQüÓÿ¤(ÿÿ&ÿÁæ$ þ!Œþeúÿª"ø€H*ý´úxü‹öÿ? ÿüÿúòÿþ©ÿ6ÿÍðÿýÿ àýç(üÛþþíþñþVÿ‰ÿëÿu€ÿxÿ³¸ÿ~¶þË2þÿþ àÿï€ûûTþ‘ÿýøü3Øý÷ þ£@ýg¢ýëþ~€è€&þAÐðÿÿ`þ¹þéx€ÿCÎìú*Èþ+2þƒ@þñ ü“dû€þ~.€ÿç¢þÿÿòÿóþý×üÿéôýýúýEüÿóÿ'ý ÿ¹< ÿÿš(ÿ[žÿí,¬ÿ ý!èþýíöþE®ÿájý¯üÚþÏÜü‰ûëxüýûµòü!þ’&.ÿšÿÿtÿŸÿá€ÿ%0ÿí ÿý6ÿï€ÿé€ÿ~$€ÿ6þI€ÿ}öôþóÞÿéÚüýÿÆÿF”þ%þçþýÃFýÿðäÿþ+Òý(þíìÿÿxžÄÿ#nýѦü"ýŒü~Èü€ÿíàþ-ìý2ýùýÐþT€&ýõPþËììÀþEþ-¤Rü'Èü  þ-¦þþÿÕDýóþÇ Úý€6ÿ÷øÿé,ÿ#ÿ¯ ÿ~€ÿ?$Úÿpÿ~öýšûQÄû ÿÛÿ%ºÿáÔh„Ä€þþÿ€€ü^äþïîý[¶ýýâýÌþçúÀþ ýã þã´"ÿ ý©dýéèÿ3ÿðøÿµ&þ¾þÿJþ¹ö€ý.€€ÿÇÿ~€€ÿmNþbÿE*ÿ5| ÚÚÿ¹Àÿárþíþ—þÏÈ€0ü :€ôþïÊþö€¸ÿ5öþÁ ÿ„ýAúÿM€ý3dðý~ûãRüM@üI¸þ"€Ì ÿñ°ÿ~ðý£>úéÞúºþã¦ý™þÿ-Xªþ›úÿƒ¶žþ³ðü{^ýîÿ~ôþá°ýÿ¾ÿíÊÿQ*ÿY¦ÿGþ~ý-ðÿ5ÿ ýc€ÿõÿÓþüéü1€ÿkúÒêÿ/ªþõBÿ#8ÿßÿ~€ÿÿ„€ý)dþ¹¸ÜýÏÄþ ÿ3òÿþËüÿË ý~VþëþѾÿ»ºìÿßzÿ=Xÿ£êÿõÎÿ ÿ~ÿòÿk”ÞÿÑ4ÿ·Ìÿ+´ÿ“¼ÿÿ€pøÿÿ†ýû~ü!úþuÚºÿ¿äˆÿ àû~0ü÷ôþ€€¶ÿ~€ý~,þ'˜€ýÛ¢þ~dÿ~ÿý€ÿ/Þþ4€ÚžýYžûÝ€ýsÿÿ àæ®ÿïþþbü'Rü׬ûÔý±ÿ~"þÜýƒÖýÓüÿM2ÿM`€Ìÿ‹îþQNÿ~`ý?4üÁ¶þËŠþ Nþ?’þ´ÊþÖü~€ýéêþeþ2ýäüÈüáýÍ^êþõî€lÿ$ÿ~Ôý?€þìÿÓþ[ý˜ÿãŽþëFÿ\hýõ€ÿÔ2ªxâ¾þµÿçÿÆþ þÏØþ/<2€ôûåHýÏàþWØýÎÿ &æ þ_ÿ)€ÿ­€àþ~Rû~ýÿâºÿ¹Úè.ÿ3*þ¾ÿ¿ª þ#lý/Dÿø€Äþ•þS ÿ?þ Ôòþèöæþç¬ýÝìýÓðþ=8þ~ü-Òÿ«ÿ%àý%ÜýŽýñ ÿ5ÿ èÿјÿ“jþþãàæ€øÚÿë8þ:¬ÿ+ø*ÿO ýÐþ¾ÿþ âèÄ® $ÿýÍèýßôýç8þCHÿ=òþï’ÿ³œÿÿ3jý"ýÏÿÿæÿéêÿ/ÿB¾îÿÙþÛÿTÿãÜJøêþ¼ûåû½ÿ ÿÿ ÿÀþÅêÊÿ7ÿý¿üá0þüþÕ$ÿ<ýøÿ ºêÿË4ÿ Dòÿèÿúþÿý(ýòýæÿÝØÜÿïÞÿ#"&ÿûÿëúþýþèþÝþÃêÖÿý üþûÞ4ÿýïþÆþÿÿÿß ý÷àþøÚÿÝàþ ¼û"ü@ý+"μÿׯþñ.þ>êþÛþãöýåöÿ ÿ3(&þýÿ ÌöþñðÿÿÿÿìÿïüþçêûáæüË úÿÿâÿÿîü÷Òûÿ ÿ+6ÿC Bý ýëèýáÒý þý#æ$ÿýÔþצþßô ÿ þ öüÝÖþ×êò ,þìüÿöÿí ÿ!,ðèêØÿýÿÿÜÿýüþëüÿãòýõÚþÿ  ÿÿïýÿüþ øàþåâýíàþïøÿùÿÿ þöÿëðøýüþü üý úÿÿðýéîèÿïæÿ ÿûþþìþ÷ðüýþûÿüõüýÝèý÷þ ÿÿÿÿÿùðÿóÿý ÿÿÚýñäüïøüùÿÿþ ÿ ýýèîþáæÿ þ þýÿìþÿýÿÿþêÿÿÿÿüñýÿ ì òÿÿÛôþÓôýñøþÓüÿÿþþú  þþþñþýþõþúÿÿÿÿãìôþíþüÿÿûþÕþñþþçêþïèþûÿ ÿÿþäÿÿþýûÿòýïÿÿÿÿÿýÿÿþÿíøÿÿÞýöþÿïäýëÜìÿÿüÿÿùøÿüÿÿ  þýþýéüþÿÿýÿ ÿÿðþïüÿ÷þþû þþ-þýüèýôôîöÔòýõü ÿÿöþýôÿûüþ÷þßþ÷ýÿýþ÷ìþþùòþ÷úþëöÿóþøþþÿ ÿ þþüÿý þóþýüû üý  þ ýÿýþþôþõþþþ÷þüûþü÷üÿýÿÿÿ üÿýÿþþðû  û  ÿ ÿöøÿÿÿýúÿþûýöýÿþÿûøøÿýüÿÿúýóôýùòÿ÷ôý÷ýÿÿþÿÿ ü  û ÿ  ÿÿ ý üþ  ÿ ÿõøìÿëâÿ×âÔÿÕäÿíø ÿ .ÿ ôÿ þý+"üý÷þþ ÿúþÿÿÿ ÿðþüÿòìêìîêþëîþûüÿÿÿú úýÿýÿýþþûþþÿþÿþþÿþþ þ üý ÿ ÿÿÿþûÿöüûøÿûúý÷øþïöôøÿõøþûúüùþþÿÿÿÿüû üÿþýÿýÿþüÿüþþýüÿýüøÿÿþþúýÿüüÿüýýþÿÿþþýÿÿþüüücrossfire-client-1.75.3/sounds/Teeswing.wav000644 001751 001751 00000020036 14165625676 021604 0ustar00kevinzkevinz000000 000000 RIFF WAVEfmt +"VLISTINFOISFTLavf54.63.104dataÎþþþþþþþüüüþþþþþþþþþþþþþúúüúþþüøúþþþþüþúúþþþþþþþúüøüþüúúôøüüüþþþþþþþþþþüüþüþúþúöúøøú üø þôü ðüü ôþôúúþôþþþþ øþôðüüöæòú& öðö þöüîðô úÐ üðâþüôöþ úúöîúüþþü üì þþøþúöúê öþüüòþü üôúöôüþàüîüìüúþüÖú2êøÎ  öÚê .ìÞþäüö æ øüøøþþ  þ  øøòîðü úþøüúþúþöôòôüøþøþôúêôöþ þðò úúþþöôøêòêøþîô êúêüüôèêèðüòþÚò,äøòô"4 üÜî(Öøäúøþâòþöþööþþ þüöúìüæü æþòþúðøøæüðüìþî  úüîôüôôþþúþø þôöæúìòö úèääæðú úþüúöô & " øæÒâè .üìðäîìðúüòøìú"òòÔØ 04.*ôèæòâüöø üüÒìØðúæîòÞ&"âþÊ@öðúêì 4 ìæòðèðÐìôø$âð²òüöDìúèNZÄÞ¤æX â¸ôÜ  $ÜîÞÐìô$* öèÜÜôò@þöö ìòìäþæ $ (Îêðì Òþ>ÔôäÆìþÌøüøøèôìøüþþþøôöìôôþôöþúþþàþêüüü ôúúø úìêìî   þðîâö ö þìöúüþ$ø ü  üøþþþþþþþþúøøöüþþöúööüþþ  öøøþòúøüöøöúú þüìööøþþüöøôüþ  þüþøöðü üþüþüøôúüþ úüú  øüþþüì òòòþôþþøøøøüüöðúöüüüüþ üöøúüþúþúøúúü þþüþüþþöþþþúüþ    þüþúúöþúüúöüøúòöôü üøüúüþúþúúúþúþü úþøúúøúúööðòöôòøðôü üúþüþüøþüþþúüüþ þþþúøôúüþüöøþþ  þ öþþúüþþüþööòøôôþöüú  þþüüüþ þþ üþþþäöúúðöðúøøúöüøø ü úüüúöøòüúüüüþþþ   þþúþüþúüúþòüþþüüòøøþøüúþ üþüöúúøüüüúþþüüøüúú  üøüþøøþþþüüøúøþöúüøúúüòþþú øüþþú üþþþöòþøþüøúþüüøþúüþöþøüþ øþî ö   üúúøøøøüöøðþúþþþöþþüþüþöúôøüôøôòöü  þúüøøüúúøüüüüþþþüüüþüþüöüøþþþüüüüüþþþþüúúøøøøøúöøöøüúþ  üúôøôôöúúúüüþþ   úöúöúüúþüüöööøüüþþüüüøúúúþúüúþþþþþþþþþþþüúüüþþþþüüúþüúúôööøøü  þþöôôôöøøüúúþüüþü  þüúþøúúþüüüøüøþþþüüüúüüúüþüþþþþþþþþüþ üúþüþøüüüþüþþüþþþþüüþþþ þþþþ øúöòøôüööøòøøøúøøøøþþüüþüüüúúúøøøøøøüüþþþþþþþüþþþþþþüúúøúüþþþüþúþþüþþþþþþþüþüúüüþüþüþüüüüþüüüüüüüþþþþþüþþþþþþþüþþþþþüüüúüþüúúúúúüüþþüþüþþþþþþþþþþþüþüüþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/Explosion.wav000644 001751 001751 00000143050 14165625676 022001 0ustar00kevinzkevinz000000 000000 RIFF ÆWAVEfmt +"VLISTINFOISFTLavf54.63.104dataØÅþþþüþüþþúþþøþþüþþþøüüüþ  þøöøøþþüúüþþüöüþþöþüþþþúþþþ   öüôþúöúîöþü òúîüÜüæòîêþ$(&ò"þèìØêÜÞàÜèîê &6&<$þÊÚÐÂÖÜðþÐøØ($,4, üìîâ*(ð"$$"øèðòæÚêæìæöüìøîòÖîðôîîúâæäþ ô0"ä""6ú þü¾ÒääæÜèðìú $ 8ü$Xþ2ðþ üôôòðâàäîèöòæâÜÆøþ îúðìæäèú$.4>4úøøêþòêÜÈÚÐÎòêì4ÈðÜøúòøÖ"ü*&@þîúìäêêäüü$ &ôúôúüúôøöîô ÎîÐÖÖæÎ úîîH2*öôôîðâæâäðö  öòöðìðÜÞâÔþúüøô(P2ð6B üêâîÖÜ &úúþ öüäðððøîöòüö ôðöâôöâ:Üú øðê¾Ì¾ÊÆØöÜ R "6,þìøþØ ,J2* îìÒ îðêÄÊÐàêÎòÎ2"6.@4*öìààÞîàðð4 0(,(þàÚ¸äÒâúàD2D(0 üüøôôðòðúøðþÖüþø¾ÜÀ àðÚðøÖ""64,$üöøîèÎäâöòø ìâèàÐøè@êüÎîüìâ6 .*0(6 *4$èþâìîÔìÐê(*0îðÒèüþøÚÀÈØÒôÈμÖîÞÐðT" .B6:<,8þäÀÖÐÜþ&$.&,ÚØÌÚâì $ ì&öê òÞÚ¼àØòòìÐÚÊààê8 ,êøôøø, ÜìôÜÞðàüÜÒÂÄÈÈÖìö &ø&Øöð  ,&(üþðÜðüþ òæÎÚÖâèäüþèØÖÔÔÔØìö$22B66 0(( æèØØÖÐÚÔú..6 èâÐÖÊÆÐÎäìúþúþâþàÞÊÖèò"  öôðòòú($,  èüâäÒÖÜòôêîØÔÐÒξÊÈÚîö  "$.&.ðþî üúü &,.$ üöììàâàÜÞÞäÜèèöèòôø (&8 ðæÜìâòìøöúîþþêèèðÖÚâþüþòþþþö "þòæöö.$:4*, úøþöüâàÔÐèÌÚ¼ÒÚæüüþøêöâÆÜÜâòü$òæØâæúö,F:42ú "0&( 0 öüðêÚÔÊÄÖÎàâî(þîêÜØÒÎÔÜæüô* üúàæäðøðúú üüøþú (òü øðìÆÚîÀÜÜê èúÜîöø(8 6Vþ"þþøòàÜÒàÚæìÚúö ððòÜöôôò´òêôðöè(..4$ð î* ø ü  úêÒÈÄÖÌðü þæàÚÒäü$þüôòìðöòÔüòB  öôàÚêîâÚìôô$&$( "øÊÚÂàÜÖäÐÖØÞôø.þð6 ôìêÔÒÊÖÔÞòòøúôêêêìòú & 0*ð $è&úôæÎÞØìîöüúúþ *, üòèôæöê &ììúúàêÞäæÞÞÔÚÞÚìèÒèæ ôðîâ4,2  þöìü,(Föäþ &,þþöúøøþ ØâÊð¾ÈÆÞÞæôúæðîøúÎöìäÚìðö  þò þö$Üôðþ0( îèòÀòäìêàâÞðÜàÜðêôìÞÞÌÒÐÊîìø(&<<"$ì .&4>.Fúäöö6ø þüÞÚâ¾ððèÎÜò¸ü òäØ$>úò$öþâîìêòú* 0øîÈø(4 üîøüö æøÖüðêèØââàôô$$46,8,2 æàÎÈÐÊÖòÒðÆ&&$$ ÔÐÌÈÔæì4æÐ Þ øöö&0ú *ðøüôîæÜÞÎÐÊÐÞÞøú:84>0& êòîìàÚÔÖÎÞàü ü  6>$&ú(êäÞÊÄÈÀÈÈÖèî .àôøô@*6òê"ØôòØöè Ìüô.@æø  ÜðäøÞîüøúöþú úúüþü "  òìþæøþìòþö Ö"üêòêàú$ôâúèæøàäêÜìÎ  üüöüøòàø æúü(0*$8$0<0&& úúâøøäÞÖÐÞàâüú" ò$ ö¤ÚÚÜìâèÒÒÊÞîæêîüÞüðòîêüþ&*">(2"0"$@4 èúÞÌÜ´àÞââöôúæþì, 0* ÜööîðîøèüòÄÔ¼Ôèä öðòæ&&$ *ôîÖúâÌòþÔ*þÖ üêôøðöþ ÒîÔ"þ@0<<& úðøüöðöøôüüþö þÐæÔèÞÞØøðÜ" ö4 06 $ üöüêöÜ&ìüêôîþ *þþæØîÎܼøøâòÖìäÒàÎÜè8êØ ( $0$8$&",ðêþøú ÔðàÒæÜöæææâìðâ(þÖ  "Þúî$  &" âôÚöôòøÖØØÌìðòìî üôöà *ú"4$" 08,$Ô<Üò$.ÌêÎÚðà,¾êÈ æâäÎòè"ÐòÚêòÌöÎêüêô<* $:2ò,@úúÜô6ÈìöêäØö êöüúúöøüîèîö" ÊÜæ *(þøÈäðúèúè4ÖúÐìÞò¶ààðäò 2*H*">&  üâüæ&Ê þÖòôòúðúòöäôô(æüúüöêôÒôä( &Üâþîòô¾òâöÈúþ þú*è  66(<6   ì ö ÜàÒèäêàæè øðâúòæîÌþú$ø"êøàÜìÚøÚøðþæôø ÞÜàòèÔ  è>&<<(.ü øðæ& þö öÊøè ÒÜÎîÜØÈîúúôöþþäüòü 8:<::* ôâòÞðÀæèüðþ¼öêòÞîèüüüöòü   $ê   þúöúöúü ê Þ þ2 öüô úúîììììâÔÐ&úüÐúæêÞþú ü  úèÜÚôèîèìôÞúîö òþ"4B 4.6(DæîøÔ& öüöææºÔÀÔìðþþøòÞÎÈÆÈ¶üÚìØðúäæô(88&&ê*&H**0üøôâìèìðìðæðúÖðòòþìê$(Ö`BàúìâìÖÜÚÜÔØÔöêüî8îþè üþò"ä>ð" èöìòèÄàÖ ú îðàððøÞèò ðþ ÄêÒ þ "*$Ð(ææüø .üøæ ü üúðæâÔÎÌÄÌÌèìè 6:044þòöäàîâøøêàòâØìò*:4L" þøøâðúÚôî ÐúúâÜâÔêòôüú( ìäð®âäàðîô DÚôúºÖôþü ðø*øðôî æôÞööêðèàêâêüäþô,8L 8"B ö îêàÞèì  ôüúøÊîàèê 6ú ,*<2($äþèäÞÄØÌîúöæöðìææÞââöìúÔúèü þ"< $<*("&úÜêÚøÖÜÞÚìððäüþêòìôöøü ô ò ê .  ôüöðüúòîðèêÞâæàìæâÔìäìòöüúøè ""$&* üøüÚììèüê ü Öðæâ¾êþ ÎìêþìêúÆâÒîàâØÒþ ð"$2(2, þþî8òÎà 064>ðôàðÖØÚîäì俨ÊÄȾҸ6 öè ðà$Î2Hþ&üÄðìÚ $ÒÚ ð0$"ø"( òöðþþúìððÞÚÒìâîäÎÊÈØàð2îîôèüô>òð(úöäöÆ äòâèúú  þæöúê2$>8îúþÈæþææàðöì ööîìÞàìäæâòèäÒöüþ  Þ Ø üô êðàèØÜÞòø ø  ú  &ô& úÜàÊÎÜÚÜüò $0 ä8@Øôâ òîìöîÜÔââÎÆÆÂ̾òîþúþ ."&ô"&ôüðîêäèðæôÖêøì(&, . HþüòöøöôöêþàèÀìÞâÜìæúÈêàÞòôð îúö.&$"þøÖ"6ú òîêÎÖ¸ÔàôÔîàîüÌðÐæàîêö*ð úì  òþê "@2& ,Ú0ÖêüÊææþêòÎÐÚÐö öôôèöø à  ö ìæðÞêôÎîôêðòìüúþ  (* ôüòúöòððòê öÖîìØøöúðøºêðìü4ðþôü$   6þ ê" öø öôâüîüòôÌÞàÜÞàîØêäúèîèúúþþú &$,6", ð îôôúúþÞüøò æôîêÜÒÚîÜôôöüðø öÒÞÐæàÔÊÌôæààôôô*0*F6$  þöúøöø äô$øøÞþØÞ²ÜêðüòôÞìøìôüôÒîâÒðÜðþÜüüüL"8*4" úüäúôðâ ÜâÄüîÖÐøúÞâàèÜææèþââÆæÞäìêöÔöäú &*&4*ô $(öÐ2ìöúðæðô( úúôæøò  (ÆÚÔ°êâúðêþ  þòþþüôðèÜÞÊðò $$ öàââÖþ&þ ,*6úüòÐÜìÎ.(L" ú úüüöêèðòäæÖääòàìôÐê"ìò*ðà úîÜì¼¾ðð:Þìþ<ö 8 &üüôüôöüþ ð þJ,ÞþúèÜÈÎÌÞÞìððòìòòÚ.$èüü  Þö  (è&Ö " ÔæÔæêüÜ&ÜðÜøìØêüüú&&*üFêÊðúÈüàðøü òöþþúòüôêäææîèðöðø*ü ð4"(&äòèúú úÖ ú0àôìî>" üúÔîòÔìêÀâÒìâîÔöæâÞÖÚØÒîÞúþ2&,4$.,*:($(þÚ  øúþF*ú8öÜúÒÔÆàèüøü úæÚÖöò þ úèÞ ðàÆÖÐÆÖÔêÜäòþø6 $&..B:8:((èæâðÞêðêÀмêæú&F2$øè öôÐèò DÔöôä$òæÜöÜøÖæîþ &" ÄÒ¼Èææú  :4 þàèâîÊÒÄââîôô ö"@ þòä¸ÞÐÈââêâäæêîì "(4@8<(.&èôÔÐÀÂÒÖôüüøøÊ>øòàðÒÔ¾ØÞî$*$ þÌÒÊÐì öü (&(6 " ìàÐÊÞÎÎêö "$ð 8ììÚØèâôþòêîòþ$  " þðÒæâöøú âþþ ü2 , öèàÒØ¸ÔÚÜþüøô "<þîüææÞäðò þú40(* þîòòüîþêü  êÞðìðòôôäÜâÐòæêÔèððú $$*0 4"T$ &6þ ôàØ¾ÌÀÊÀÐÞî ,$úÞÞØô6*0úðÖàÚÖèòæèþøþúôþò "   ôäÐÈÈÆäàö úøØ..2èþø öøÊÊÈÐäô üöæâØÒÜâÎÜÒî 6"0&(   òôèôèììîøú ú"((0& " êèÜØÔÔÔàèôöôúöüþü( :6þ öêîÒÔÊÖÔÖÖäÚæØö.4><2" îèØðîü þòìæäèîä  0&(" ÐæÒèÜÜîæìø$ÖèÈäääò òúøüúþ &((.úøüòèâÜÒÐ̸æÚêÈÔ DæÞ*"L (& ("þüÎÊÄÄÈÒØðÖæÚî(ìþæôìèôæ"îðæú *<,>æþÞîúØðìôúèîÜîúâæîòúúþö.ôþØüö,þöôÚæèÞúÎôò ðL* ØèìòàúÜàøÜô"öøøøü68@4,êÚÊÐÖàôü üòüÞððúìèØàÖÔâèúð 240:( ììâØÚÖÞààæîü üôöü úüöøìðôòòöòþþüü 0,00.(þèìÖÎÀÈÂÈÈàäôøøþîþøöàúî   $ ôè 0úþØææâòîúüúüôúôüÖîêþü ðþöÐÞÎÖäÜüàäâÚææèöðø ,0<8:B48îèÞÐÆÌÒèì6<&$øîôòúì  âüôþþþ  ðúúæ ôÎÜÐàìî þøôâðäìèêø  &*(&("$ öôàæìîúú ú ööüþöøôêÞÚÌÐÒÌÜÒäîü" 2,6222* òúÖþöþøðòäêðò $ö öþøîòìîôèê¾àÔÞàâôôòô> $ø ".4.,L òôò,ºääþüèÞøö ðøÚàèäòÞèäðþ  ( & ÌоÌÈÐÎððöôðòêò &$&(2&( îîäÜìâìôäüà0>(, öòèêâöòöèìðòòüþþüòÜêêöøúþô4*40" ðèàÔÔÊÐÚÆîæöêÞÞÖþäøÌ4 <*06þúÚþÖä¼ÔàÞô ,þ"*.,6üþîôÞêìæèêèêÜÞØØæêöü.2B8@88öæÞÎÔÔÜØÄàìú  úüðþôöüÔðöü *<@86 þäòêöøêôðìäàÌÊÈÄÊÒæø 026* ôîâæðêòðøø0"((" èþôêàÞêÆâÜØòø ,.88&*úôææØúîäàÚÒÖÚäî $"*   òüþàäÖÐìØìÆÜÞü&02  ôììäÜäì."("þäòòüøüüüüøîøì ÊÎÊÖîÞèâúööô (**06,.  úîæÞÚÖÔØææòî @$&þúêêìØêÜòôêÖàÌöèðö((0240*úúøþæêââäâæÞâäæäêð$$$ þ $þôÞàÞàæàææàìè ðþú þüþ (*.:6:,*($òêìäêââàÜÞÜÞÜÜØèÞäæâòì ðøöþ  $&8$*"" äúìêöèúìääÎÞÚêêìòòòôüö"   ($þþôäÌàØäÂÊÆÌÈÔÀìô  0 ,.(  þúôòÜøêØììîüêèäììê*$42 òþæôøðþìðìòîäàÞÞàÞÜðîöú$"$ðþüüøþøüØÐÆÄÊÖìúîô üøðúúêü   þôìäàÞÚìÜØÜààÜìöþ$,.$,òøòîêÞèÜÂîâðâ " îêÔ̾ÔÖæú*$"îúúôø  *ö øööüäôÄîöúàôÖôøôú"*$"*, òêòÎäÚüìèäÜÚØØæêøüþ "*"$"üüþ ðîèêäâêö &BFÐêÜð"æöâôüèúèÞÚÀôê úøúêâàØêÚêÔ     & üôÎÜâöì2,.&     üòØÊÊÊÈÂÌÊðîðüðîðîú îöôòðèÚüîòîðòü (,0& $úøØØÈÚÔÚØäæòäæòøþòøòüøþ,,**.$  üþöìâàÜÔÜÖÞÒÞâäèøü    . üþþúúüþôðæàÈÐÈèÊÞààðæúòê>(B.ú$,(.8 øòöäèàæòôþüôþôú üòîÚäððþúÜÚÒÈØäöö  $ îäøä   üôðòèâèöú úþìøúðâàÐÂìîB"*þ *& øôøüêðâÞââæØäÞ*"* þðêêðîâúþúøèúþ  ø îò*øêôìü øäìâØ üú ØèØäÖØÚàäêêôúü     öæÌÎÐÜÚô$$*òðøô..0. òüèîÚÚÞÌæàâòäòâÐúèæÜÆÄÎÔä ($$*ôøöà82262üþìÞîÊØÚÚ   ôüìÔäÚæôô(&> èöúæøøöÔÚÆÖàâìððôîúþ 4 þòþü ôîàÞäæòþü ú "6.<66<2$üöòîÜæÔ ÎìÜôìê"(.&îìÞèÌÖÔàÜèöîøüüüôðôôôþ*þ " øøøüüúüôôüæöðòööðøöø þ üúöøþú òòÜÒÈÈÊÌÐØØòØæèô 822*  äèÜæèô&  úêêàôæøúöøðìèÊàâêòöÜêÚäêêòîþ $022&,ôîæêæðîúöâü  þþúøüüø è $öúÖÖÐÚÊÖÐèìøú úöööøü "228:.6(2ÞðÜîÖÞèÚøèòòê4þüøøêâÐèÖÖÔàìü(8. ,"øðÞÞêêÜöæö*,B*"üìâÔÜÖîÂÜÊê* :Øö6 ìèîâ üö þððîêòöî " ($"þäæâèöðôþüöèôèþâæâäæèîø"6"&$òêäàâÞðèôÞþ @*4.ðæÜÞÖÖäìðæèôêòøîæ.Îôðü   þþ  ööúääèØÔèìÞâÞæÊèæþ$*4&$ðøòööüü& èâ¾öÜôÎÐôÚòôìêúþ$ò. 4äæÞÂèâ&(òøöòôøôøôþþøþþüþî úøäøôöøöüúþèþþþèòòàöö J(.*8842$ôüêäÌÒÜâîþ  úîÚàÐÐÆÎÜØþöþè 4& î  úúòæêæêìôü $,$:,, ÔêêÒèÎÜÜè* ô " úðîêîÖÚÖÖÎÒîôðø   üöøöþòúþöø $ îìæÞÜÂúò úü ,",&"üôúöôòðôðòúò ìöôðüòÞàÔÔÔÖÚòþ  $0:64$ôöü üìêòÖòôþêúÜ,"Þð:$îúööúôæîâðôðêúäú Ø$üîìöÜöðþøâêêòD&."  öü úøöøüþøþöîöüúòîÄÖÐÞÎæôü ,&4,.8*$þîèääâììôèòøüþìò üþðøøââÐÜÞàô üüøþôúú $ ôü .ü üþîäêèòôþøäÚÆÈÖÒÞæêúì  $$" øþþìðèêòòþü  òþúøÞäâÖØÒÐÒÖÚèúüî@ò ü2@"     øöôäîØüöððìîüÌ$*úìòÚø þ  úöôôòôöþþþ òüÌþúöòüþø òúòðúú   ( ôþüøúúüúþðþúþðìææÖÜÚæÞäæèèèìêæäâÔÖØêò$08820  øð 2 öêêÂÒÐÜîäüæ úöàììèüüúì6èæú ðâÎÊàØâÒêöðúú&ü(2"&øôÜèæô,*.@òèðö¼ÖÆàøêøòôøâîøäâòì ü*öðüòäàìöþ":,2èîîöøô üðêÐÞâÜèâêôô(4òêêìöòú üþîòøþþúþöèøêøôðü86,Dúò(  ÐìþêäîìîøòüêæÞîÞìæú , èöäèôÌîôò ìúìü  î *&00 üðêÊÔÆÜÐÎÒØðøð(ô2ô ôþöøÞìò$Ðòâäüîêòú (2 ôôøð úæöèØÒ¸òê*þ&0ðîîðÖöôìþÞ*òöÚâêòî&$Öôääàæöô0$< üô þüòââÚÚââæøòüô:"( üþü ÀÜÊÚîÞîÔæâòäèòø "& 6 0ÜÜâÂøô Þò08(öøøêæÜÖÒÜàêìàþ4,èèÀÎàÜòúöþ þ æ0ô (òàöòæäèèæìöôøþòúþü ðîàöèòîàøúöú ö 02$&þ üþ (0<&( úöäàÜÒÎÎÒÒàòìòèöüü êüÚàÒÚèìò.<&.&úøîöÖØÞÐîðòÆö $*úêøô úÈèÔæÐÄÞÚôB þ"èôî(< $ðÜÎôäê& úîÎÈÜÔâòôúüôôüäôÞàäö&&2,0$æðäòôöðôúò üúøöôúâæÆÊÔÎòü ðì&*&((úæÖÚÖÒàÞòäöþ$,82,"îæÒÌÎÞÚöæîòÞììøîððôîîøÜ8, " öîÜÐÐÌÈàÞüæú $&68&.ô8øÔÖþîüðìôäÔèâ 8öðüøúòôàðîøâúôìô ,þ"2þæÜÜÒÒÒÚâöø "2 ìöêúêöð& þüüÔØÌÎÐÖâè  äîèîü  ìîæâðìúþ&&  úþÒÚÐØÖÖÞìäú ìîèô &$þòìèðöôööàäòðîîþèòôöìô" ,&*&  öúðüöòôàÞÚÖØØâðÔîØ L(($üôòÜ úøòîøôøöèèææôðüþ  .*.üæàÆÒÎÌÜÎÞÞì ø öôðòÞè¾üô,è0"4:$ êúôúàÔààððøüúÞêàì F"(öâÌÔÖðè( ððÞìððôüüö$8&$&öøøîÜÆÜÔèúú  üôöð üüììæôü üäôøðúÆÞèæäþ*(80.0&þÚðêàüîöäþ úòØÜÜÒâøèðÚþ   ðöôúüòòàÚÜìüô $  .ìÜÞàØêà þôàÚÔÐÜìô &""*.,øøäìäòô0" ôüþüìâÌÄúò øôèêìøöþ  ÞàÒÔôÞöäôú8.üîü öþ ò  îúêöæüÂÜÊÔòÜøÒúþ  þîÚúäÎæÞþþðîöÚî@. ìðäô úüîôìèèôôîööäêÜøþ &": øøäàÌÖÚàððþ"$òîöìðô$ þüøÚêÒêôÆîÔæîìüú  ÜúØ"  üôðþüøôüðúôìèäèøüþþøüøôæþü$èüøàèÆÒÜÔêäâæàêðæ þüôþü&0* ôþ&>ö ôôÚÚÖÈâÚæâèðøü úúðööòú ( $"úöîèöðøòþøæàÖÔìÞîäòøü  ìêâò ($(*$Ì( úöÔäÚÖêìðÞÔÒÎÖÞþúþôü & þþüòööðþôîôìúúøÔÖÊÜÖäì "."&  öîöøäîîø öêìÜÜäÐòì øô$$ $ öøðôúþ  ìæÐÚÒÒÐÎâìø(,úòæÜäêþöúþþúôðèöúüî ð&èþêòæÒÞÜêúâêöüü &6þþþüö  ü ððèæøòúìêêÎÎØÒìîú(*.6"øþ: úðìîîøúüþöîÚÞØÖÖØÜæððúú  L îÜþîòøüúøúúìú.ø &0,"2 **"&úâÊÖÎÜôôþ ú& ÚðØèôäÜàæØ,ìøøúôâþôøìøìöÞîð &&þüÒêæèîäòôü üúîèêäàìæêØôðúøöôüôøäìîðøìîæîðøöü  **20,. èêÐæÒÒÐØâìö   úòèâäèâîê ìøüþ2$ ÚæâôÚäÖêòü ü ú òðþþ üþþî.øôòîæúþöøðæîêøö  $ ôüöîúØòòòøääÔÞâê"4,, þúôúê öøðæöÎÜÄðîúöö èôþöæòê   ("" úü úðþòôàèèþêÞìúþúøþüôøöþúþ    "úöÐÜÌÚèØàÐêìîôüäîò*   òúô$î(úøðöþøþòúöüðîèüþþþúôîêìæâØæâäâèòø4$($öüüô" "äôüìöÞäîè ü öòòìèøöøüþüöòîîòòúþ ""& êâÖÐÔÎÖÎâèü üþôþøø ü" 06$ú$ òöÞîþòøæäâÖÚÞàâüü ø " òæØÒÐÖÈîø ú  þöþúøîæòæìâü   þþèìøðèèèîîòúø ((2$&üøâàìàþÖÞÚÖàÞèäèìöòøø  þþúúüêôèøðììîêòì ü öò    ôò þúúèöòúüäìÊääèöæúøôððòþ  úþøøöþþþ öòôàæîöþþüòîêèîêîøîøöþþ * "$  þöüöòôèôìêæâÞèäìîîôøüúööüðôàìîð üøôðäØÊâÜìêìððòðêîòòîôöúôþü  0$     ðøøêðìöâìâöîðèäêèðòòüòüü  "øøôîÚÒÖÎÚÎÖÔÚöôöúøü "&(,,öðäôö $òôêÚØÒÐÜà * öðòè øððêø þöôèìêüììîü( $ øúüÞèØêìêðúòúØþ"  êäÜÔæàìâöòòìòôò*ðöêððôîüêþú  ìêäââæàöèü þü ô  ô ðìÖÖÔÒÞÜêú **" öüú&(òîìØäæòìîúøøôèòòü ð  üþø äþú  îîæàØÖÜèôúö"&øô êöðöþþ ê öúøúììÚÚââððøþ>ú þöÞêæòæöúþü úôúø îðöøôîòü ,$""ðþàæÞòìôæöòúðæòôôúòðöúø üøîôì "&úúðöüôþþøüðöúüþþôöÖðèöòæðêøúúö   øòìøøüîüòèðÒàØäöðþìòôö &*"" îúðìîäòì òþ âòØæêÞüÐèâæBþþúþ øüæüþîüè ü  "úìüðÐîäþ$ ôöðöö þøòâääêìòöòüìøöþú"$ üòìêìèÖÚÖæäðþ*øúðððêøøü(ðòèêÖÔìàúæêììúü (*2þúîèòæôàâô ôôîôîòæÜìðþðüæ  " öúüúþüðìúöüøòþ  ø øôèÜÒÖÖâîòüüüô þüððîøþ"$4&& úþôðþò(þ øüòòðäôòôú  øöæðîÞæÐôö üþöøôøüöþöôîòö $($ þòúþøðîöææöøþÜöäüæìèÞþôúø.üòìúüþ þþüü úúüòðìäèæèæòöüô$"þðúôêêæìæîøöüâøðþ,:ú*"(4òæðäò þöêðâÜÔâäö úôäèêìøúüþúôäøöøò  îìæÒúðÞôøü  üþüîü  *&"þúìðØøðèêäàäàäèþþúüöúüìöúþð&""øøèðüþþøøôôüúúøøèîêìòìöþ2*$(&þøôèâðìòêðøèêîêþìü êðØàâÚìèæêÜ(*"$    øìäæäâäèðö " öööêîìêæðòöú &4 úôîàÔæÞúþðöæîòî $úòîøôüøò(ü üòôêöòôðððöæðêþ  ,, ü þøàêàÖàÔâÜÔèâ " êòôòüîêîþô"üúôøþÞøöôæ$ ðìèìúààæÜìðüüøþþìîòðüüúüâðððø þöæäääÜæô  ê ôæìèüüøìðîò ðøìøâèäìøüöú"( òîØîìøøþ üüìÞòðîòøøôúôôôêÞÐäÞüôöøüò $ øòêêÚàèð  ôø þúúøòøìöþúüìîîâäèüüúúîüòüøöôìþêöÔîòøö (ú   øüîìÜÞäØþîôÎÜàÞøøö *Ð"æ   ôþäèÒêîöüú øúúúôúèüþþ þ þîôìòööþú  þúúîèðìöúøþöðâêæèêðòòúþü " $ ôúüøúþ þþú øèúø  âòèæêðôìêîìòúü øððúôúòøüü   üúøìêÒðäîðêôðòþþîðììêôú$øöîäüðö  òôüþ  úøààÜìðúôòæØàÞîþ üú* üòàîäêøøþøôîÚîêþüòâðîþ$þììÔàèôú úöîúòúü òôøô ðæÜèÜææÞðúîîðøôú   üúúîîòîöðööúþþöúü  üúüîþþîöìþìðòîþ**$$ öôððöòüüìììððôîæêÞÚöî þþø , & òüüîøøúöðòðêêðþøðþü (üîððîöòðøòøüô  þþòüöþìúôôàâÚèäæðäîêô  "$0üðúú üîðèìæèðôôþúìüöòúôúþ úüú ü þæòêüöøüþüøðäàØÞàèòì ô  "úúþøôü ô  òúäôòØäÖÜîèöðôæ "(. ø ìðêú  òôøþüòöúþ êòîððîòòðöø  üòìâÜäÞèîæòæô$ &,  úøòäìêôô ü   þþðîòúððêäääöæîìü&0 üúöüìèìôúþúüüðüþ$òòæØüôúøþ:  ü øêô"èôèüæîòüüòððüúôøö   øòäâÞâèìòðþ  ü òòèîÜÜäìöú$"$ üúúöøðúêüöúüþüþöúþöþòðèìäêæìòê úüþþ" (&$øØôäòôðìüþöîøòþúúü"òøðôðìðâððúþþþ üúüàòèöòøø "$ ðîòúþúèìîòþ øüðèìäôü øææôììöôþ   øøÔàââòìòôèøô"(þ üúæèöôüîþöúðúæøúúôîðèêøàþ  þ öððäôöüúòúü  þøðêðêìîþö üôòìèêæðæêæîöú  úþäðîööìðâððòôü $" þøôäöêðâæêîöôüô  øôþöêò þèêääòöþ þöøðîøêôèúòþöüþú üüìüúüøôðââÜÜàèð&üöîìîîø øüæúô þüþúöôúøúîôìüü   þðöòúöúþ þ("&$ðòìøúðòîðòìòâúðöìäèÞúööüîþôööò.("$ þþêôòü òòØîèòòø ôêðî  úüôúþìòêØöêæðôôðøþöøæèæìú$" þø üúúúüøúðþþúþþ  øôäðòöüüþöþöþþè þüþôøüöðæòâææôüþ üöìøòþöü ðøüöüøþüööðòìðöúæþþ  øþ øøþîðÚââèîôúöþîöøøöòúü " üöìäèêøúòöèúöôøæèàâôòþ   úêêàÚàØäÖâìôøîèØàæðò ü  üø ìøîò þ üþüøúöòøôúø øüúòôêææêæìðþ$"& ðîêæüþþîøþôþðøðèêæòþ  òôôðæÜêìòþ   þðâìèìüööþ*ðþìòäæòò öüö þøòúìòøòüúüö úüüþþþøüüööêêìðæöö þôðîîôðôöúôøþþüúøüôøüøôüú   øøøðòèææÞîðþþîòòòúüðöòòðþþ &üþüúöúäðîôúúþü   äèØæàâäìòüø þ òôþîþø Þôêøòöúþþööþþüòøöüüø úþôôöìöôîúâðòèþú   þþüúüöúüüþüúîüþöòàÖèâòìðôòþ îøô$"üø òîÞúòúúîìîòöþòðêêðò üüìüú& üööîìèäêäêðú  üô ðüúþöööþ øðêêòøøøîìöúöþøøøòþôúøòþ üòîîâìîþü  öòúøüüü  øúÚòêîúøþ øúôúþü þöêèÞæàøþþîìü    üøîèìîðøúþ  úöîììêüîøîüôþú üøúòêàèðì   þ öþ ú  üøôöðîîêîðøøþúþìäìèöú    þþôöôðîàæâèîðøøüú þîîèâðìöòú òúööøòòìöú þêôøúòþúü üîîöö  ôþô þüúþøìîèæðôú þæüþ   øøèòôúüøììèþøøúòôðìöøú  öðêæîî øòìîììöúþ    ðòîèúôöü ü   úîðæîúþøöþúüüøüôøøøþþ  " øöðòôôøúþøüöüòôôîðôú þúöðèèòòòþò ö òúîþþþúøîððúø øúöü  úüìúöúþø üøøîìêîìôîüüüú þþðøòôöøüüüüôúþøðöøþöúü þ úþðæìÚæòòüü þöîððôöú þôìîäòòøòìþø üþ òüôúøòöôüøöú þþöüþ  üúüüþü  üøðøðöðü  øîøòüìüøöúøþüôôîðìòö   úôàú ø üúøüúøúôþöüúþøüüúþöôôîòòôúþ   øüøøþþôüüüôúúü  îðððüðúêøüüöüøþ øþüþúøúððúøüüøöøòðìöú þòöòøþþü þþ üòüöòúüøøøúúôöðîîìòðôöðþ   úöüúþöüþþþøôöðþþþþüøüòúüþúúöôøþðúîøþþ þþòôðîæøôþú  ô þ üþüööôþöþüöêôêðîîúöüþöüøüþøøøîôðþ     üüüêðîîþþøöøüþôüüþôüþüúúðöððöòúú üøüòòôèêôøüúþþþþøöøôøüôøîôðúòþþúòúôúòþúüôöüö  þôîêæêæêìþúþþ þþüðüö ôòììôö üöúêöú  üüúøòöôöôþúúøðôòüþþ øúþüö  úþüü úüôøôðöòðððøøüþþþøúèü  üöúøüüúúòòøòüúöúüøúúü úþüüþüþüþ þüüúüüúòôòöøúüúüîòôôü þúúøüüþüþøúöòôüöøðøöúúòü øüüøüþü   þðúöúôúüüúüîúöøööøöúþþþúøòööþ  þþþüþ üøúôöðòöúüþôþøøúüü   üúúú   þøúôôòôøúüþüþüþøþþüúúöðøöúøüü   üúúöððöúüü  üúþôööúþþ  úüúøúúúþþþþúúøþ  þþüüþþüöòîòòúü  þúúøüüþ úôòðôüüþ öøôôôðòôúü þúüôüþ úøøúüøþ þþüþþüþþþüþþþüüúøòöôþ  úúôüüþþþþøúôüþôúøüúþþüþþúøøüüþ   þüððòôüøüüþúüúüþüüôöòøü þüôü øøòòöôüúþ üþüþþþüüøúüþøüôþúôúôþüþþüþþøüø þüüúúúþúôððôôúúüúøüüþþ þ þøüþôøòòúöòúø üþþøúüúöôøúþþþøøüü þüüúø  þüüþúüüúþúþüüüúúüøüþ  þþþúþüøüúüúúüüüú þüüøöôðôööúüúþüþúþüüþüþþ þüþüüúúúüøúúþþþ þöúüþþþþöøôúüþüüþþþúüøöòôôôøøüþþþþþ þþøúúþüúøúþúüøüüþüþþþþ üü þüüúþþþüúøöôöøú þúøúúüþþúüööúüúøþüþþúþúþúþüþþþúúøøüþþþþþþþþþþüöþüþþþþþüüöüúøøþüúüúþüüúúúüþþüþþþþþüøüúöøòüüþþþþüüþþþþþüúüþþúüúþþþþüüþüþþ   þþþþúøöúþüþüþüøúüüþüþþúþüþþüþþüþüôüüþþþþüüööúøþþþþüþþþúüüþüþüüüþþüøøöøøúúüþüþüüüøúòüþþüüþüúüúþúþúúøúüüþþþþþþþüþúüúþþþüþþþþüüøöøøüþþúúøúþþþüþöúöøþþþüþþþþþþüúþþþøþþþþþþüüüþþþüþþþþþúúúüúúüþþþþüþþþþüüøúúúüüüþþþþþüúüúüüþþüúüüþþþþþþþþüþþþþþüüúüüüþþþþüüúüüüüüüþþþþüþüþþþþþþüüúþüþþþþþþþüþúþúúøþþüþþþþþþþþþþþúþüüþþþþþþþþþþþþüþþþüüüüþüþþüüþþþþþþþüüüþüþþþþþþþþþüþüþüþüþþþþþþþþþüþþþþþþþþüþþþþþüþþþüþþþüüüüþþþþþþþþþþþþþþüþüþþüþþþþþüþþþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/Whoosh.wav000644 001751 001751 00000051430 14165625676 021270 0ustar00kevinzkevinz000000 000000 RIFFSWAVEfmt +"VLISTINFOISFTLavf54.63.104dataÈRþþþþþþþþþþþþþþüüüüüüüüüüüüüüüúúøøøøøøøúúüúþþþþþþþþþþþþþþþþþþþþþþþþþþþüüþþþþþþþþþþüüüüüüþþþþþþþþþüüüüþþþþþüþüþþüüþþþüüüüþþþþþþþþþþþþþüüüüúúüüþüþþþþüþüüþüüøøøøøøøúúúúüüþüþþþþþþþþþþüüúúúúúúúúüúúüúüüþþüüúúöööôöøüüþþüüúöööôôôöøú úúööòòòööúü  þþüúúúúúüúþþþ úúööðòðôôøüþþúøøööøöüþþúúøøøøúþüüúøøøøúü üüøøøúúþ  þüüüüüþþþþüüüüüþüüüüüüþþþúøôòðððôôþ úøòììììððôøúüüúúøöööøøúü þþüüúúüúþþüüúøøööøøüþþþøøøøøúüþüøöðòòöøúþ  þüúøööøøúüüþþþüúúøúúþþ  þøôòðîðîöøþþøøììêêìðúüþüúúøúúüþþüúøøøøøøøøøúüüþþþþþþüüôôòîðððøøþüøôðòòòööþ  þúøòðîîðòôüþ üöôðððòöúú öèèââÜàèôú ôîììêîîöüþþüúöøöú þöôòððòòü þúðääàââäìôøþ ôðîììòòþðìæââæêü  "" öôäÚØÞÞèèþ  ""úøæäàààæêúþ þúøòðîöø  üüöööøúü þþüüúüü þþúúü üððìêêêìðôúööòòòòòôöúúþþþúúööîððúüþøôòìèêêìððúþüüúúøøøööøøúüþúîèæäèðò ððìîðôø úúöúúü üüöøøú úøòòòøú "" üúðîððøôòðôøþøîêêêîîôþôìêäèêôþ ôöîðèèìôø þøòððîððôüü  ôôîðîðòþþüüôòðìîðòþüþüúøöøøøúþöøôöøöúôööøúúþ  üôòööôöòòþ   þüúøòööþ  þþþüüþüøòòòôþ üúöôìâäæèòò..,*êèâàæêðú    üöôòìòðö   üüøúøü  þøöòúü   îðòò þüúþüúìêèîø þöøüü  òôîþþþþøúøú  øøöôööøüúüþúüüúþöüø òòîîòôü øôöôþúöòððöò  üüöòôôú  øúüúøòøöüþüöøðìèäòüüôîèîúþúôîêêîò üþôîöôü ðîäèâ &626ôôôöøàØÒÒäö0284* îðôúüöìààÚòú "&øööøü úøðææêî   òòòò üüôôðöø üþööô öôæèæêòúîòêø $ðöææìèôòø üöôôø  úôîêêêüú þôòèîö ôæèâèôô úððî ðôìðúüðêæèôø øöö  þþüþöúøöüúþ þööòôüòîèîôüôìòêö öðîðüþæòìîúü   úôÒÜàâ$ìðÞàâæø" *öäÐÔÜæ "("äÜÚÔìü"úðêäîþþøðôúþ  òòîòþ þöüöüæÞòü"öìÞäð"(0úøôêðúöþ øèàÌÚâ *0,ôìÔÊÔÎî þôêèìðôþþîòæê( þîæââî& üìæìö$üîôòîúü $ðìàÞäêþ"øæÎÜâî $øôäææöü úøîöøüôúòøüúúüüüúô  ôììæêøøþòêúôþüúþ (" ìÞØèô$üâèììúü üòüüþôêðìðþ üüîöòòþôüüúúìúô úÞâÚÚêôìæÞæöüþ :îêâÞúæòèÜðä8Òêîò.òàþôòòàÎæèþ<4J4ôÊüö ("&(ÞöÐø" æòôì ð úâÐþ,îÒÖÂ& Úðäì üöîöìþÜæðô"&ÞÖôð  þôüøôøü  ö øüêêúü êâÜÄ.<òÎàØì <þøðÆèîô, òÚêÚþ*ÀÊäð$"üð  àììêööÔðî.88B$ Øâðèæìðì .èôàÎ(@((ÚäÀüþöÒæè&üÚàîî úôòø äôâì " àìö ü ú ôúÞÐìD" úÚäÜèþ öôøúòòîäèÎôü6èÖæÈ&B$¸ØÐú2 êþî .îâ$äîÐôî("úðÐæâ4,üúâöüþèâþòþþøú æâòÜàðÚôüúøìòú þððüðøèøöúâ ðüÔêøîþþþîþ"$ìþÖô6ìÚðôôüâüÞþÚ"4ìèô>"ºüì$êÐôFøÊ¸> Ôò ü.üÖ ð&ü ¨èÜH FÖîô>øÖÆú8ÀøÚüòæ ÌD0¦²2Lx¬âÈÂ*þB$ä¼6öþê¢ ê6.ê ®ôöøPîÞ²þÌ*6²òèÐFþ.ö¼ì¬öjÔ¢öÊ*&êÊðüBì øÜø ø¾ÚäÂLHþÚü¸ (èúö(0.üØî>$ ¸øÔü66ìîüÔ6&ÐÌ$Jìþú*.$ö ¾ì 0þìî øüôúðôøô  þìøøä(2úô"òèîêèöøæîøä,ØüÔâT\ðîÊ4*îâüøòúøüúà6.äÄÜ:0$ ÄîÈØ>>Üêºô$î òäð"øÈúöð(ô îÆöÀþ"àÔܪü8RÈø°Æþ>(ÜäÚÌ42,äÆôþì(àòð($îÒð:ìÞìüþòìêÞB"è ä&BÄöæVVàÆòÊ(&:àÐê0Zþüüâ>ðþæê>þDšääÈr ZÞ®òˆR&.BÀÆôú*øþôôòÞ ôúÖ$öæÎèÎ: ìüîäö. þÎöô 0þ$Ö ìøäôøöøúöòüðæNúîà..Èþ&ìæöüôêØòÎ 2`ÜÒè( P úÜ îüúèØ&ð$œÜÄèN dìÆêž:>>ºœ&´êøææàðÒúôÌ Üð´ðú$Þø06$èöÞè*ø*êÒìÈ,4(ÊÊ æþ$ 2úÞ&ÜìÖêòÞòü4þ ôìô*,Úî*Ü üäôÞúø&ÎöèHþÖÒìð,0$ø ÞìîììÚú æüü ööþþ  6  ôN "úÊìÄü ,øöâÎô ú2ºúª$6t®ü¾ø\~žÚÜh H´úúðäøê(ÄøÎ&ºúÞô6ú4¼üüZ4Æú *8üÐ ÖôÖ Üæ"üì® ð(üøþæþ0æöúôæöÖÚÆäìüÜú<âöÔ"ö Èòî(îôü(ò ÔÖì¬âPâÆü$Öþæ<èôBHòú ø ÜvØ´ ¶âLäè,&öø¸öDääêøò,âÚ*^˜æ¨ø  ÖþôêìúDLÎüþæ&öÜð&äþæîØæÚæøú 0$ÚäüÞd2ÈÌÚ|ʪÔtðè¢6ü6HÒ–&\òâØ ì0úü´ ê0úÞÔ¾Bì*–èÚVJÜòÜ.øü"øðòèêìöìòôþèìæP^Þ " î$ øúúÌîè&Ö¾0$P®ü°@ø"ö È66î¨ø¨rØÄÈ\ øÄ¨P VÔîÊþì $Îଠê>âþô Þþæðîæ 8 ôüâð,ÖöèÞT0¶üæüÌä60èìØúHȰ"BÚö¼ì: $¶úÞ ÂòÌFü¼òÖÖòä &æ â"þ ö&æüò¢èLÌþÔä>þLŠä¼þX X–ö(ò¾øRøújØâ ÖÚB>Ʀ,@(¤ôª8&ªØ< Üò îÚÒþØ,BüÈ`TÖêŒ:þbØìÖVðÒÖüÎ\6ú䨮`FЪø’,²ž ì|î Øð,*àèØúN @Æð2ÂèØîDXÀþÞüæÂþö<øòâ"DþòúÎ$>Äî@ÜúØöÎôØþèæþÆò¼tò&¨"8Þâì0ÐÒú^ôú–äZÊäÞL&öÞâèææÞ&ôâ*"îîÔÔì¢4*8èð$øììîòäÌö$öæìÖ@2þüúê(à¨ðhò"¦4,Øüìðôøð(Úþ´ò" HÞäÒDþ6ÒÞàæJ 8$–êVÜôüÒÚú8þìè 4 ¨( "øÚøú8 öüÜö@æ¶L¦Ü À .Bî öæ0 ²2>ªôÖ.Ðø°n:–(HÌèìúþ$ Ô(¼²&04žä´òœü:ÈêjÄöŽ,J¤Üìæúì*ôòòÐðì&øüú"ðØÊæ,ÐöðôT 6´îÜæòô Â\"îÞøèøôê&,øâ"LÊüô8þÜülÚ®öþèÜH:,"èüèDôòæ&ìâä üüôø>´Þ¤(ê ¨D ÐêÖ0è"" ¸èæ*ì"Öêþ´ôv²ð€|ZÌ 4ð ê6æÀÚØ,ò  Üôêä,èì@TÀäÚdÞò¢&ööÔðæ ôö¸úÜ\øÎX"Ò.üÆÜÒ,îôð6î®,"’ ìBüøš>v„ÜtÄø´HæðPþž:LìöHºЮ,`¬ðÀþäêØú öüðèþ*ìòÈ^lŽö¤ê®Ú² &$ø²þúÞòüðöØBú¦øêúúâ:øÜ0 Ê èBâú þüþæúü øæÊú¦DèÞ *@öòæòüì* L¼ØôD.Þö$VøÐî>æ’@`¦þ¶Zð ¢N&DôäFôÒòöT&Ö@òÞæD â\>¾º"üðøîø¾$ú ôîüð4øBÔôâìöÞ,ÚîðìØ($ôÒìÖÐê ê æØÜòLâî¾ZÖö4˜î¢ð ²ü Êä,°è¢èÐ:äòúúÐòôü "ì X úÐ2ÒFR¼ ÆüêR”ô̾üÈ, þ>ÒöÞ@"þlÄøÎPðä üÔ$ üò&ÌèjÆîÐÖ(ô,èÜîø0 Xì¶ üòØ üÜ¢&6þü<Ðö&ìþ¶ú4úä¸"$úÊò"ø4òØÜ*®44î ö06äøJôôúÖþ Üú >ØÚ–6îº..Äüêøøæ.,&î Ò " øøêøôæÖÜÊ &Ú´D2ŠüLÐî,œüæ6 üðèìþüò"æúø Öúø0¼æØlðÜ öâêü" ò Ö ðÜfì"Ì0Üö°¼ìòêÒ@ÈþðPÜúØ4öøÈÜúêÞ Ð àÎÆòîº .&ÚÔ"\Øàò0þÄfÒ®@þîBÒ(ðô08þà$ÖÂ@ @œ<\®D*Lº $àú*Â*BØ<šð âþ¶ð ÚèàNÆô, úJÎî 6âìæèð²ðÚXðú†RÖN êüæîüÈð<¤8<èTî ØT$øôRBúÌZÂú–p êÎøø œ JÎÒ0*HâÚîøì(äìúè, ¸BôÄôÜ"ôöD²â¶¼Îj ö öú òÎ$lºì òð6¸ø`’öÐ2 ææðÄàjæÔÒb "bð¼nÂÞÌ>:èà""& ¸*ü:À6²þ`ªðÚ¦îèÖúbÜäÖNð¶< Ü 2€tøîæþV.ÈîòH˜þòðÔæÊäö Øþ ¼B"*ÔâüÞ0DÐòZ–ì ¨òö®ÊP¨,.4Œ0*ìæôØîÊ&ÊZ®0d€î`´$¢Èô$ìà"ÊìôâþödâÊ øìÜúàD$X”jl€Þ0àòþÚÔàôèìø êÐì&$^êòðþÚ>ÜÖ6ÄþBÌäö.Ôü&2þ²X:¶* &¶þ>DØô ú®&ôøì0Þ2 äèâ.ÜÞtîŒvò&Òò^äÒÊ8ÌVØ " >È@è®päüÊöì è¶`ú .ðüìZÖ üÀö^èìþ\Æúæ6ÒÞÜðêÚòðìøØzʘtþlÞð´pö&&ú äDþþèôFêðæ²&îúšX*¸B,° Ôê ôØè*Üî(& öÌêøö *äôÒò¨ ªÈBz€ æL,è@ ¬:F˜( öÞ$2ÂJöüþ ¬$<â Î&þ(¾æ´R¼öúúÒ(ò ¾<öüÂøêàB ÞîÒÒÂ.Nè Èö¢ø¢"2æ*BþÆ6æì"¼ôìæöÊþ^Ð Ö.ì $ÌúÐh®æ®NÌÄ8°òì(úê*Bº0úôÔØ$Øâäê¾ èð@òÈL00Ò.Ö°:ú àhò&ðÜúúÞî ¶döØJ2ìð.âÖÎø<ÐøêH¨( äæÄf¤øBœæàÌÚ8æ":Þ>2ðJðPÎPÜ,ìøÎîöPªT äFú ÂHähà F.À^€JÆÔ¾Þöê,ÊøH¨þô¸^ÐÒTêöÂÜjü @ž â$¢.Òæ¬Hê2 Øöü 0ÐØü4Èè´Øîì4  Üòîêº6ØÈèÞî\æâhÊ(ö ªDú z¸Ú®îü¾ÊÞÊLø¶<°vÂâRLâ4ø ºXøÊììòâêöî0"ä¤ ê àê J:âò&òRòÖ`èêvŽ$66Ú4èøÊNøÒ0î Šv "°æôäüØð24øNà:,öþ*ðòTâêÒÜÆþø´HøòüúâB È$v”úî>ÆôÒî Vü"ØÈ6ú" Œd.:ÆJüôðÞä( ö > ÜìôæÒÖÒæêÄB, > Ô Ð*œ,òÞÌèú üþ$¤öÐ4êÖD´æþààì.à,FÖTÊàÚ&ììÒ Øä6Œ&$Æ`üÞÞèžXìþüèhú¸*ðºÊèØ¬þæô.Ðüüþ( ÈÔÞæî üì´øô*ü´fö<ÜøÂ0â¼ÖH*@¼ èÂâòàò.ª>¸$°XäüÂ4îì¸æ,ÐØÔ,îäØö:$ öò¢ÖÄ ÀÜ(6ö&Ò ÜÐT¶ì Ìþb€F(þ"úøàøþÞ>*ôÆþî@Š,:Ê"öØÒ¢$üÎJööPê<Ž2,Ê2.ô.ÊÎöøÐð<Þô\àòôÞÚFæÜhèøÈüøLÞèðÀþêøäFðä@ü ÀòTü ÂôÒòèô¦üüäR0üâò>ÂüêÎFð ÞÆ 8úìæÞÔF$"(>@ÖDüô ÎòØ FÜòêÌÊ(èêæ8θìâšD$ XÒ&Ò0 ´zÄÖdÊ(Bú8Â:ØÊtÄP¶H´ø`& ôäøæ4ÎòèÔþèîúÜúœ" ,öü®>BÒ2ö&ò¸2îölÔèÆ@  îøò”úê*®6è¾pÚ:Ôø$ÔòÞ¼ÚæÎÚ 2¤ ôZ”F Ò4ÔÌ*8ÆÒü°ôø  èÜÖâÜÐþBìJÀäܺØðþöÚ øôÊöìà@ð6¼,¾Dþô@ ðÜøöèð¸Hì2æàÞÄð(ðNÌú$Èèô–(&6ÖP¾ÞäH¨RÖìäêàÌ*ø^þøRð”8èÊ2 ÎZòüºè Üðæ\Æö0¤Ä8èþü¢>$"f¼6<ðNÈjÜì¬üüö. ´äìàÔ(ôØ& æ0ÎÄìàæòú,¾.ä¬442@š ÐP ¬vÂÚ.¬ :ôâþôì&$æD ä æ(ÞÀòÌRæþf°":¨âú$(*Òæü4ÖÞæN¨ DÊòîüìò:’ÆæÖþFÚ**äøîÔÔ ôÖ üðþðÎêüº²xØä$¾ðôÜ Z þÚô(,È&èü¾ ôòþ°40Þúüæ6àÜú¶H6ÖôàØü<þ$èê¸ÜnÖþÒþêòþØøò¸ì î~ºþÚô þ0è î8 äDÊÐHÐ**àâBöô.²úæôðöÆ,üâ "&àò,øúÌF$ˆ äv°$@Æö0 *¬ê " ä Þð¸òìúüÒþÚZØþ²<ÞäèÒêÞè (¦ º(îÊ,ìúÄ$Ú,îæà4&4ÄðÌÊ(¼ ä,ôðþä¸>2:®(&.Ôúî¸ìèø8ð*6TÈúôàªæª6Þì(Èô4 ÞàÜÖ Nî æH àòö¸nêöºäÜÒZò°þÀ.œþôü ðÐz°ìÐÞ6Ò&ÖTÜ*>èÒ6èì*¢îVøº êàòþú äÖäúøþ<Ê æ<ØêÚØ"øòöüÌøð.xøä üêøð2ààþêúðìøÔøÞîÔØöìò îúð(âüÜ FÖúþ:ÒþöÐò "öøÒøòê6ôüÊ.þB®þò "îöÚJ(øæB,¾øöòöú" Ôòî(ð ¼öì¨@ôÎüüîôØJÒðìPÖöèÖ öäüîDÆúæüÜPÖøÞÔÜîîòîúúþö êòìðêú ìüöüÜ üôöòøúúú  öðøþüôîüøüôêüô ìúôò öúøúüþøöþúþà êòúþþ îüþöüþþþcrossfire-client-1.75.3/sounds/fire-spell.wav000644 001751 001751 00000147314 14165625676 022072 0ustar00kevinzkevinz000000 000000 RIFFÄÎWAVEfmt "VˆXdata Îþÿþÿ  ÕÿÖÿ¸ÿ²ÿ´ÿ±ÿ¤ÿ¦ÿdÿeÿ3ÿ3ÿüþýþ­þ³þgþkþ)þ(þþþþþLþMþgþgþ[þVþþþÂý½ý‘ý‰ýmýeýqýoý€ý‚ýoýmýuýqý\ý_ýTýYýtývýYýYý7ý5ýAý>ýý}ýÍýÉýîýìý¶ý·ý”ý•ýšý—ýžý˜ý•ýý‰ý†ý’ý’ýýý–ýýýtýRýIý_ýYý¦ýŸýàýÛýþüý þ þ6þ9þoþrþŒþŒþ–þ–þ~þþTþUþ0þ/þþþþüýéýãýöýôýþþGþDþ|þ{þxþzþšþœþÓþÒþöþñþÿ ÿÿúþÎþÊþÂþÂþèþèþØþÚþËþÌþÁþÀþœþ™þŸþ˜þ‰þƒþ6þ6þýýþýïýëýçýâýþýúý1þ+þSþPþaþaþ^þ`þOþQþIþHþKþHþ`þaþzþþiþnþOþPþaþ_þmþkþÅþÅþÿÿöþôþ¸þ·þþþþŠþ®þªþéþëþ÷þýþÿ ÿÿ ÿ@ÿFÿlÿuÿÒÿÒÿ>:&#ðÿìÿáÿßÿèÿéÿîÿñÿ;;c_vq“ª¦ÛÖ    Üà»ÂSXÝÿÝÿÇÿÈÿÔÿÑÿ²ÿ­ÿ†ÿ…ÿkÿkÿ„ÿÿÏÿËÿüÿøÿ )(@=A;óÿïÿÉÿÆÿ¼ÿÀÿûÿêÿðÿùÿüÿäÿåÿ{ÿ}ÿ,ÿ2ÿ>ÿ@ÿHÿDÿ†ÿ†ÿÝÿâÿ38DJ'.‡ŠËÊÈÇŒ‰‰„¨£ ˜ÏÉö÷òõ¼½°²¤¦¡‘–‘À»`_ˆ…ÆÄø÷ ÔÛÊÏò÷úþòôõõééÔÑëãߨÌÍôõOP£hl&$ßß¹»ÿ îꮪ¡›–…ƒwya`gdecŒ‰ÿXSƒ’Š˜•†‚Y[ad²µéíò÷ÿÿý  ÛÝ=>CCNM8<=A‘•àäæêëî0/¢Ÿ³²uw¹·[^ÒÔ_]/0QXv€TY  úü"HK9;ýþÝÙàØ³«7/ <8‰‹ãçØÛôøøýìí1/c`EC=<_a}„–œ¬¬½¹ÜÛØÜçí66_^pt³¶×ØÛÛÔ×ÖØŸ›jd’–•XYËÒKO-+65þûßÚŽ‰GE'"C:Œ„£ ^_ciksbeÕÒêìÊÏ;@¸¸ÞØ3025àäÆÄÝÓãÚêå÷õ/-QP54ùøÿýÿ38­®Ïά«¢¢³³µ¹ßå!NPÀ½ uwtzœ¢ÿîðÚÙ½¿“´®«­rs}€¾¾äàÉý¹ßÜZZ…‡TV..ýþ #8>¿È&zz80+#a_ÐÏ   ¯±./·¸./PSÉÊ›—80¨£oo~€76»ÿºÿVÿWÿ‚ÿÿïÿíÿ ÿ“ÿqÿoÿ½ÿ¸ÿ“ÿŽÿžÿÿÚÿÜÿifwpsmîê3/ÍÌ--5:’š*-wrf\VMÑÓ¸¸þü{z«ªihÕÖsudg¦¨©«|}’äÚPJåä¡£®°’ƒ}¦ŸÎËÕÔOT ¤('~„nuLNUV+*•–ÅÉÚÝ`cýÊР§ˆª±ÍÔìñ‰†ïíLM¶ºôò !  ½¾55ÞÜŸ˜ZT*'NL…„89ŽŒywðñdh®²·¹®­OLÊÊmpVY¢¥ãå10¦¦LN±¯™’êáÿ÷Ÿ– œ]aTW‚ƒXW82@7øö;?12Á¿pm„ƒ  ÃÁ*)xt  ßâuxåæÁÀ’–`fúûÜØðUW,0û¢ŸíçEB*,êèYYר{y¦¨*/ÍÑ::€ kf£¢ˆ‹$"½·+)QRPTà厑~æàïéîèåâêé<9 §©{‚krfl}åæIHc_hdLJ‡†œ™zz,.øô WVjk‚‚ÈÉæèQRÝÜCE —imIMš¡ 8@Ÿ¥"/4¿¿ßå<@\_twzêå()Üß  å⎌CAGC¤¡Â¿îò†ˆÌËÍÓ¬²¾¼è⺹actuø÷ˆ‚[UVR(&õø øü35~ZU40|óskŠ„ ãã!+&¬¨86JJZ[ '$ëêÝá´·ÞÿÜÿüÿùÿ‚ÿƒÿÿÿ€þƒþÿýÿýœý›ýªý¥ý¤ý¡ýZýYý‰ý…ý¶ý´ý0þ6þþþIþLþüþÿŸþ§þþþ*þ&þéþéþ‚ÿ„ÿuÿuÿ5ÿ2ÿ(ÿ%ÿ¥þ¢þVþUþþ‚þ ÿ#ÿ0ÿ3ÿ(ÿ%ÿÿÿ¸þ¹þ”þ™þüýþýÞýÜýþþÙþÛþÿÿ_ÿ\ÿ²ÿ²ÿ”ÿ•ÿÃÄŽ""îì~yLL£¥‡ˆéêjk>:‰ƒàßæì pthiWX66ÖÕuwx{´µy|¢ÞáWUÜÚhg¸»¹¼ˆ‹no‘’20«©66âߢ£¡¡yuLGâß‘‘¨¦–‘øõ# ÑͲ­Š‰__ ŽŠqm¡¡x~ƒ†JL€|ABäå––IFŒ…>8?=™2/•”àÞÆËˆÚÙü——§ª—”®¨@>%'óönp’“/-NM•ÿ“ÿPÿLÿhÿiÿˆÿ‡ÿ¢ÿ›ÿIÿEÿÕþÔþõþöþÚþÝþºþ½þ‰þ‰þ2þ,þOþGþ–ýýÂüÀü¦ü©üñüöü>ýAý$ý&ý€ýý¼ýºýiýgýþþüþüþvÿwÿnÿpÿxÿwÿ5ÿ1ÿøþôþÜþÙþðþñþÿÿ½þ¾þÛþÝþÓþ×þ3ÿ3ÿ˜ÿ–ÿ„ÿƒÿáþåþ€þ†þ{þ~þ þ£þºþ¹þdþ\þ þþ¡ý ýþ þEþLþ½ýÃýJýNý5ý8ýý ý7ýAý¬ý¯ýAý>ýBýBýaýcýôüôü´ü·ünýnýþþëýìýƒý‡ý<ý?ýÈýÉýJþEþÿùþÒþÍþYþWþ²þ¯þ»ÿ·ÿòîçãhf%"ZZKKÚÿÛÿBAd`ÝÿÞÿpÿsÿØþÜþöþùþôþôþŽÿŽÿX[ÉÊðì¡õö %*$+óøíÿïÿ‘ÿ‘ÿPN“–…‹ñöDISTýúŒŠ‘ ~„9:fÿfÿÿÿ°þ¯þ6ÿ4ÿ}ÿzÿŽ‹]]\^ŠŽºÿÁÿ ÿÿ—þþÃþÊþ²þ¹þlþoþþþòþïþŠÿ‡ÿgÿcÿ\ÿWÿÊþÇþYþVþ þ þgÿiÿ 22ÔÿÒÿ-ÿ.ÿèþëþ;þ<þ'þ"þbþ\þhþgþ˜þ–þŒþ‡þþþ¯ý²ýøüüüHüGüjühü€üüiüiüzü{üfýiý·ýÀý?þIþ‡þþþ£þÃýËý‚ü†üZüXüeûcûžúžúIúJúõù÷ùúúßúãúûûû‘ûüü~ü|üÎüÈü ýý¤ý£ýpýrýþþ•þ™þðþòþœÿœÿ:9£  #EA´¶ ‡ˆ˜–QQ¾ÂHNbeþúåÚ^Wõõk h  ü í æ l m Ÿ ¡ 4 4 ™¬¦ s s   ‚ … ¼Ã2 7 ¼ ¶ L A ð ë í î j i ¤ ¥ ß ã ß â   !  b ` ä ä ÁÄëíDEde+-66=7úòYTwuw{’œ–´¶ùû–•SRcbEC(&€üúÏÊd ^ û  ¾ Ê Ì D O $ + ê ç +"ëã 3 0 ç å !  ð ì X P › ‘ ¦ ž v q ÿ ¶µß Û W X í õ }‡UZ31sq² ° U P õ ñ Ù Ø Ã Â ` ` W V / . ù ø ý þ % ' ” – P Q … „ “‘×ÖÓ Ï ½ ´ l e ý ø D A S T X X WXêï)-üÿINØÜ˜—po+*Š„áà:< ¿   k g 32``Æ Ç ;:¯­<8ieonda$’A=è ä , , j q ‡ ‘ G M { z nhxs('‚‡>E " ª « ¬ ­   |  â ã A ? Ž ‹ í ê £ Ÿ ¥ ¦ Ù Ü u x C E ß ã N S [ c ñ ô Š ˆ ùü­²&$/0ÇÊ©«((Z\‚†ßß  ÕÓ)(@?XTYR_ Y ´ ° i i x x £ ¢ í î  Á ~ z … € ß Û , '   < = † ˆ ò ï m m ¡ ¤ Ñ Ó b d ì î È Â = 6   m i | t ª ¤ * ( ' ' ™ œ ¤ § ‰ Œ e g r q ü ü  « ® ¾ ½   % $ jgDGFF95$   ' % Ç Å ttô÷`dÙÚffPRhk™„loCCŠ“'$'KIŸ›’Ž$!lk__–•µ·Ÿ¬®ÃÄêéjiÖ Ô # M H ˜ ˜ g m X ` — š ‰ ‡ Œ ‡ < 7 h b j f {gd]]‚ƒþþ ¥áÿìÿ‰ŒA=òð! ­­›œÞႈx}ÓÔÿ.1öùad XQ jdki]]´²‰‚åÚ=8ƒ‡±¶BC” ’ ¹ ¸ ñ ì ¿ ¼ Ì Ñ ì ò hl»¾     J I T U › + , º » d h Ì Ñ ‡ ‡ „ ‚ Œ Üâ< @ … ‰ µ ¸ ½  |   úåÞ¶­KC-*””ø÷'*Ó×êèçßçá}~ot:;õÿñÿJÿGÿ6ÿ3ÿZÿTÿ31{~éèDÿ>ÿwþoþ<þ9þÙþ×þMK«­ÍҼ¿Ä+)ùõÑЯ°ØÜ„‹WXÚØDD43·µDE++ØÛ…Œ8:ÅÿÀÿóÿïÿ%#þŽþŸü üšûŸû¡û§û^übüÒüØü'ý,ýîþðþ‹ÿÿhþnþ–þ˜þnmìíEGíîKLÖÖ> = ; : þ  ë ì 9 :   ¼ ¹ Š…³´',[Y’ˆ#ÞÖïîÝ Þ ÷ ò ƒ  ¦ ¥   d d ê ð ² ¸ ° ³ Ý Þ ï ì Š ‰ œž|ÓÓ³µ<=ABPP;=ººe`  ¦¦+)øô£¢ý]^ÿùG D © ª S Q ©§@ ? Ú × 7 8 A G L O ;9àÞÜÛ& + éó-2¿¼úö÷÷èí´· Ÿ/1ÿýþ:þ:þWþSþ1ý1ýý•ý‹ýŒýýýuþpþ­²­ÿ³ÿ¸ÿ»ÿÿÿ¥ÿ©ÿÿÿ½û½ûqýtý6:)-éIIÓÒŽ’ùöîð/2B?ÀÁ=?ÉÌ_a<=ø÷]a'Øãëðóí€|OH/(ßݶ³ÓÐýÿüÿàÿßÿЇ??58®«¹µŸzz  A C WUÄ¿FAíéNKâݽ¹ª¯Ô×-+íèÞÙ¡ €¹µž•£œŸrr34£¢÷ô‹‹¡¢õõïðÙÙ  ,-õönoõöÂÁÚØ„€ÕÔÄÄÿÿEþFþ ÿ ÿÿÿÒЇþ„þ”ü”üÚüÙüOüOü3û6ûÚûÙûÍüËüýýßüáü—û–ûãøáøg÷g÷JùMù#ú'úúúBøDøø÷ú÷rúwúêüîüIþLþ 9>äéÝÿåÿU[èèßÝ”’ìíWVz[W”h`ÿ÷þ6ÿ2ÿ=>ãýêýœû¤û&ü(üÊüÈü¯ý°ýiþjþ'þ#þ¿ü¹ü[û\ûáùäùÏøÒø…øø>÷E÷»ôºô½ô¸ô—ô–ô[õ]õÁöÂö@ö>ö¶õ²õ°ö«ö÷÷}õzõŸôžôÃôÉôòôüô%ó/óIòOò}òƒò¼óÄóÖóÜó õ õ¯ô¬ôµó¸ógõnõ`÷c÷D÷I÷¤÷§÷øøàõÜõºô¹ôáòÞòôô-õ(õ†ööP÷H÷s÷l÷øøé÷ì÷¾öÁöÃôÆôqôvô}õõàõßõR÷O÷3ú1ú÷úòú•üü ýý×üÒü‰û‰û6ù:ù÷÷õõKôGô£ô¢ôõõPöQö÷Ž÷xøtøùŒùûùúù×ú×ú¥ù©ùú÷ý÷oöoöI÷I÷ÕöØö¡õ¥õ ÷÷ƒ÷€÷]öZöYôZôôŽôÒ÷Í÷Ÿøšøù ù†û~ûßû×û¨û¡û¯ú®úúûýûQýTýþþpÿqÿ*,ÿ™ÿ¬þ«þÿÿFHþûÿûÿjþlþÉýÏý<ýDýhÿnÿØÛ ¡ûþŒ“hþjþþþçýêýtýzý‰üüéúèú\úWúûû°ùµù'ú*úŠûû.ý4ý4ÿ:ÿ_bòÿðÿéå|z÷öƒ…PVÀį²ŸÿÿØý×ý†þ†þÈÊ"¢ÂÈ[_‰‡¹³Ù×56©¦SÿMÿ#þ!þåüéüJûQû‚ø‡øüöþö“÷•÷·øºøúú#ý!ýýý{ûrû-û(û½ý¼ýWXˆÿÿej¹¹ecfe?<c^‰ † m j ] X Æ Á 36iq<?éë:<oþnþÃþ¿þÏÿÐÿÜÿÝÿØþ×þ'$51€}ØÓƒŸdb…‚•ÄÆïÿøÿ(ÿ0ÿ§ÿªÿ TÿLÿëÿãÿ"ÿ"ÿ þ&þþüýLüHüðüéüaüYüÆû¿û7û1û¾ú¶ú-ü&üýýHûAûÉûÁûõûñûIüKüPýVýÏûÕûqûtû§ý£ý˜‘up–”ÂÁÉË×Ü?D0 1 VTõõÁÃÏÿÔÿ–ÿ–ÿ¼þ»þEÿEÿÿÿÿÿ®ý¯ýIýHý'þ)þgþhþ­ü®üûúþúáüæüÈýÍýîüïüRüRülýnýëí·¸ÑÒ|ÿÿY]¨¬ÐÓomôó~~ÒÓgi '.òò»µµ± ×Ñdk§°PSŒ££76%" êè-.ãÿãÿ0þ.þ^ÿ\ÿ/,mgPK“’  Œ ðïI D ¯ ª ¶ ¶ K J ˆƒ—82P Q _ ^ ¯°CDÏШ§àÿàÿžþþ•”·¸ëì—˜‚ˆÁËžÿ¥ÿÙþÛþvwÿýþrútú>÷=÷”ø’øføhøøø^÷_÷•÷’÷½õ¹õòòóþòÀô»ôfö]öhø_øðúéúwþrþîÿêÿ÷þöþÃÿÇÿLÿUÿYÿ_ÿùþøþòþðþžœ“þ’þûû‘ý”ýûûÚ÷Ü÷…ú…ú:ú8úîûëû˜ü–üCúFú9ù@ùøøÖõÓõTôRôVóUówñuñ‚ñ€ñÎòÐòMñOñ!ó"ó8õ6õ’÷÷Ý÷Û÷]÷\÷6ü5üuüsü ý ý”þ‘þ{ÿyÿ32ÅÆÞâFMÚäºÃÀÄYZðó¹¼ùù41¾¹Û×ii_^“’IÿHÿZû]ûiûoûuû|û€ü†ütÿxÿÅýÄýóûïû%û#û¿úÂúàúåúçúèúø÷ù÷äöéöYù^ù;ù;ù¬õªõ0ô,ôžó˜óññðñxñ~ñ¿ðÂðÿòùòæóßó—ò•ònïmï’ííÇíÈí ë£ëYìXì-î)îùî÷îáðâðññññ òòòòsówóòõõõ­÷¯÷(÷&÷æ÷à÷ˆ÷„÷†ô…ô[ö]öÑøÓø"øøï÷æ÷]øXøôöïö÷÷ô‹ô[ôVôõyõVòUò ò¡òõòòòcð[ðAï:ï®ïªïÈñÅñ"õ õHôJô6ó;óõñøñQòUòùòøòõõaø`ø‰øŠø5ú5ú-ü.üüüUþWþçýçýèûèûëüîü|ýzý#ÿ ÿÿ}ÿCCvwÿŽÿ²ÿ¯ÿ™ÿ—ÿ¬ü®üíùñùüôþôXñYñ’ñ’ñ_ó]óuõpõ×öÕö§ù«ùæùîùùùøøÀøºø?ø:ø ÷÷Œù„ùåûßûüÿûÿFCxr‘þþdÿdÿåã*+//­®˜™­¬¾ÀÙÜüýB=cÿ[ÿ“øøTöUö€÷ƒ÷õøùøýýyzQP½¾´µZ[ÄÿÆÿ)ÿ.ÿêÿéÿŠˆ˜•𔡛 eeŒÍÿÈÿ>ÿ<ÿNÿSÿJÿUÿ{ýˆýAýLý+û3ûXù]ù û£û•ý™ý69„†;>ÞÚ˜ › ý   ; ; è ê  ² ¹ Ú Þ S Q € ‚ ¤ ª î ð ïîéç22£¤uu™™éåa]ö÷kpüÛá~ÿÿÄÆ;=ÆÉ [[}}¡œ>;¤¦KNhnãèP V W ^ „ ‰ g h È Ç XY®±³¹ˆŸ£=@HÿNÿwÿzÿtþtþ ÿ!ÿéýìýûûú út÷w÷IöLöi÷l÷öôõô.ð,ð÷ðúð¥ñ®ñ[ñfñ#ñ,ñAòFòòòžñ›ñéôèôÃôÃô÷÷¶ø·øðúôúøùüù¤÷§÷6û6û°ý°ýêýíý!ÿ"ÿ¤¤¡ü¤üûûvüsüIþDþ`ýYý‚úzú\÷T÷?ù7ù˜ý–ýŒÒÑPPÁÃDDY]­±NUÝÿÞÿ<ü:üúúüú(ú)úÀø¾øxüwüüÿûÿCB»¹S R   t u €yIE„ˆ@ G »¼=:45êíïëpjWYáçsuá⩬urøó35ŠŠÊÇ(!~{¬§!ßÓ2!+!7$4$®#ª#+","¨"«"¹%¶%+'%'9$4$ãßÿHC#ñó—ž 'Ÿ¥Y [ K M Ñ Ó > = 86ææ™šÌИš%,PW²¶IH7 1 ¨ ¥ Š Œ , - { | £ £ 41¡¡vynsê ï â â <;…‚QIéßÕÏè鹿÷û§¥UNÔÌMÿJÿ’”ÀÀþÑ É ½¼df%$¥ ¢ ¬ § )$ŠŠó÷ÍΠ ž d h ª²|‚}þüý¢ÿ¡ÿ··÷ý÷ý½ûÄûTøZøåúçúZþ^þOÿQÿFE87dýbýÉûÇûZýZýº¼ad'ý,ýúúöû÷û³þ±þa] þþãüçü_ú_úO÷M÷›÷œ÷]ô`ôððîî ëëoéné¥ê£ê«í£íŠììvéré›êœê}î€î ó óHò>òÕóÏó]õ_õzññ¿ïÅï„ð‡ðŸóŸó?ö>ö"ö!ö=ö?ö¡÷¤÷€øø ùùŠùù¦ùžùûû÷û üü*û)ûx÷x÷‚ò…ò{óó õ õCõDõôôoónó1ð0ðzìì]îeîòòïòïòññ(ò%ò£õ¢õÚ÷Ö÷ìùèùjúhú/ú0úrýtý  WS  ÎÎokwsù÷’±¶  Ä Ã QN: ; ¥ ¥ 1 3 Ð Ô Î Ñ º»%!ÉÃii“47‡†''il34ÆÇNO($Å¿a_ÓÓLýPýþþ§û¬û˜÷œ÷YöZöVùQù‘ûŠûYúTú)ò%òÅîÁîdðað ì¡ì~ïƒï¤í«í¯î³î?ñAñÿîïƒññéõâõÄ÷À÷ðóóóõõö öÄöÌöûûñýíý±ªÓÿÐÿ;ú:úœ÷Ÿ÷-ö0ööö/ù1ù/ô5ô„î†î¬î¬î`ïbï+í/í%ë*ë–í—í”ïï ïïZñWñLóKóþðùðÄò½ò'ø&ø·º) / Ï Ò S U F L ¡¬X`<9=9CCþþš”Ž‰¨§¨¨œ™_]˜™!y|‰Šz|³¶ÿ#)ÆÈ ><ç"ë"®%´%˜$™$ù"ô"~"v"ÚÔrnih ¨©Ê"Ê"k&k&(’(Ý*à*ï%ò%#!%!ìê A;4/%"VWéíæäY[‚‡Ž‘ô󉃽¸£Ÿ•‘($ÅÂFBqq éï477:36†Œð÷$'‡ˆ ·¿Ž”†§¦ïïÑÓ<@lm!!T#O#&##kc³¬P$I$ó'í'5$4$Ôܤ­¨¯ƒ„/2ÙÛ+*æãf`ÔÏîïRUsl©ªËÌ:9ikÔ×  ¬«ÐÍúø<<Í̾½ýü‰ˆ¡¡llððpoHE:7öôª¨( ' bgÝæqwˆŠmkÊÿÆÿÁÿ½ÿ%$|yÇÆZXúö;4toòñ‘œ›z}Ê Î É Í -2  N O À Å ;>Š «ªŠ‡  ø÷CCÑÔ47âäžž ûò?ÿ;ÿþþVüVüžöžö”õ”õØõØõõõ¢ô ô†ö‡öÆøÈø—÷•÷2ô.ôwñtñ7ë6ëfåfå³ä¶äžä äÄâÀâØâÕâÙáÛáŽáá…á…áTÞTÞcàbàiâgâ«á«á=ä@ä+å3åååææ è èãëçënîpî€õ}õüôøô£÷¢÷‰ýˆýÅüÃü_þ_þþþßùÝùlôiô õ õÜøÜøÜûÝû3ý6ýÿ}ÿ¸µ¡¡²µÂÅVV<::7âÿÛÿ½û³ûlôdôûòòòöñðñ÷ðõðƒð‡ðªï±ïrïxïððqíví«ì±ìIìMìÿìÿì~ï|ïÐêÍêÓêÍêœí˜íyêxê`ë`ëtëuëÇìÉì›éžé§å§årçpçNêNêðçòç‰åŒåããåã‘á‘á‡âˆâÝÝÙ Ù¶Û­ÛöÜîÜTÖPÖàÖÞÖþÛüÛààÔâÚâcàlà¼ãÄã!é)éäíéí ô ô·ô´ô©ï©ïwî}î´ðºðËðÍðSïUï'ñ-ñ‘ó—óÉóÍóœøžøÃøÇødöföö öjøjø<ü<ü…úƒúc÷_÷þõúõ=ù9ù¡üŸü838ý4ýçûæûúÿðü›£…ppW X á â OPkýlý~ù~ù~ú}úüüEþEþÈûËûÃ÷Ì÷ùù§û¨ûþ þYÿTÿ£¥,0©ªÀÅ ! Ë Ð ÌΠ ;ü9üúŒú ûû—ûšûÍüÒüXÿ[ÿ¥ÿ¦ÿ#ÿ"ÿÿŽÿ9>]b/,Ï É – “ ­°ÖÝ./niåâÏÒ14±±ñ ò |~ââ/ / ƒ„íõ FI47¡ £ 0+ *' ||þ’w}pw§­ÒÔu v CIª¯çþîþàüéüåóîóññôñøñ]ï[ïqíní&î'îÜòáòð£ð”î–î_ó_ómökö÷÷ö÷×÷×÷ööÄöÈöóƒó§ð©ðƒð†ðó óÆóÈóð ðÝóàóãúåú½ý½ý´û±ûüüªú¨úHùKù.÷3÷õ õ‘óó$õ%õ[û^ûLüKüýýNJ²°jþhþ•ü—ü;ÿ?ÿØÙ¹¹Ã¼ºÿÿeúnú÷"÷ øøÇóËó òòš÷”÷"#  ÙýÛýTSâÿßÿrpdeIþIþýýø ørñqñ]ì\ìíí¦ì¡ìàæÙæ«â¦â4Þ2ÞÝÝßßà€àUçXçÉëÎëJëPëºí¾í”ô•ôÉöÉö¥ð¦ð êêêéëéEêBêëëºê»ê¦é«éØìÛìYîWîFî@îññ±÷²÷sösöòòCéDéìãóãè%èUïXïTïVïòòËøÆø(ò#òíîíî^ñbñÃôÅôðïòï"í%íÚïÜïñ!ñ5í:íúåæóè÷è–ê“êtënë{êwêeècèüæûæÕæÙæ_èbè1å.彿¸æ ììêîêîœíší‚ê€ê2ê3êöíùíððíðóóiökö:ö;öõî÷îÉêËêÖì×ì»î·îÖðÌðœî™î‚î‡îò$òh÷l÷ùù,ö*ö¼÷»÷%û'û‘ø’ømójóKõEõüü]_q v ·»ß⎠ð팄ÑÊGF76 ! ¦*/Çɼ¾²¶µºy  ‚€}|  ia× Ò ¿ º ž›Á¿¼ý¼ýNR¸Àÿÿìçleõ ô Œ³³&"ÎËÈÈ ]^`gçåS O ÕÑßÚrnr q }þþËýÏýúüþü.ÿ,ÿÌùÄùÄõ»õ^÷X÷…÷÷úùøù›$û)û”÷•÷±ú®ú:7sýuýàùâù÷÷ªö§ösøpø¤ô¢ô!ð!ðËåÎålåråöìüìÆïÈïNëHëÔéÌéèèŠêêqåqåtçwç˜ç™çªá§áõßïßââ:é8é,ä)ä§ä¡ä5â0âMáJáêèéèÏèÏè}é~éŒççÓâÕâeêlê¿éÈé‹ååãŸã—åžåOêSê‰ë…ë´ï¯ïƒï†ïví~íyêzêææŸá¡á€ãƒã¬å¬åEâHââ‘âƒç…çzëzëŠæ…æEà?à”ߒ߷ܺÜmÛpÛÙÙ¾ÖºÖàÖßÖ—Ø•ØÖÖZÖ[Ö=ØBØÔÔ×Ô;Ó<ÓÎ~ÎòÇïǞŞŘǚÇ3Ê6ʤШТҥÒcÓbÓÛÿÚƒÞƒÞÙÙoÕnÕÓÙÎÙ=Û>ÛÙÜÛÜÙÜ×ÜCÝBÝ(â'âîÝëÝSÛNÛzâwâ—å—åXëVëSìLì&ï!ïeøbø{û|ûŒÿÿâ⩬ÿÜàÛÙ¢¥KSXc—¢ þ û ľІTR® © LG]\§§¸´F@¶°‘Œs r '*í í £ Ÿ BAº»{{ppX U åá þ2 , ´¯À º ¶°õõíÿñÿ‡›þ þGýIý¬ü®üŒûû¬ý®ýøùøù™ò•òºî¹îwí{íñ"ñŽú’ú­ø³øàõâõºõ¶õ ó˜ó¾î¼îÓí×íò òôõïõdù_ù¦û£ûÌÈíÿìÿ›ù›ùüüÿ~ÿ‡kf\Y~ { <:-1;@~H#G#Y'Y'Ò'Ð'M)N)Æ'É'‹'Œ'É+É+J,H,ä0Ý0š22t/n/Ð3Ò344]0a0ù0ú0…-…-I,H,¿+¼+j%i%Ï#Ñ#÷ô-%¦›æÜÿ ÷ àÛ¤¤{m#p#È%Ç%–%“%##ge—’ÓÎfb‰%‰%ð ï ýù¥#¡#ÍΑ“!  ž8:Ýæ¾Ä  MHµ%²%©$§$š—¤#¢#¢(ž(¢+¢+Û-Þ-Ù&Ú&Õ%×%3$7$a)d)£-£->4>4{0y0ˆ*Š*g/j/³'¸'8"?"MR¸ » ô ø É%Ë%+)()_(](À/Æ/¾2Æ2æ/í/?.B.ç-ç-‡2Š2˜4œ4Õ/Ô/™-˜-{2}206/6ö8õ825252 274243ÿ2t/t/',',ˆ,Š,*$*-,5,ˆ11°6·6¸1»1Ù5Ø5=6>6ò)ó)V X  ðô•šTXâßÏʹ¼8<™šx"x"º ¹ e!e!<@ÆÇï#í#G(F(++…+~+G#A#6!7!c$j$ò"ú" ùú˜•lhãÞ ¯¨'!H A „}­ © ÌÌÊÉXY‡Šˆ$‰$--/...**j,e,Î-Å-6.3.ð/õ/a+e+›)™)¥'£'b"c"š''Ñ*Ò*Q#Q#î ì XV î õ %%?%<%ü%ù%F$G$_broñî0 1 ’TWwùyù¯õ­õ°ø±øÅôÈôPñTñì†ìêïêïåñãñ¥ñ§ñã÷å÷¢þ¥þ>?C@úóunI D ¦ ¢ Ї#<:ÉþÍþ·¾€ þ ø ³·¢£ïî{~ìî•“  ¬ £ < 6 Ũ§ïíHE  Ç É ½Àlpa f ?@FCSPMJ°°ÊûÈû,ú)ú ü ü3þ2þ½þ»þšøŸø}ô„ôßïâïò’òõñùñùìÿìééïéç”ç^ébé±ë±ëˆë†ëAîAî÷ëòë´ï¨ïÈñ¼ñýìöìªë§ë>è>èÿîï!ò(òÅòÉò§î©îHîLî/ï5ïzô€ô€õ„õ…ï†ï(ô'ôbù]ù:þ5þ)þ*þÊ˺¸þþË÷Ê÷èöçöûû2ú/ú-ú'úÚ×ÒЕÿ“ÿ¹ý¶ýõýóýmûqûþøùùù^ù`ùÀùÁù;ù<ù]]µ³¾ýºý Ž !$07³úºú‡õŒõröxöSðTð^è[èÝêÙêÖôÓô}ø}øèôîôöö÷üóü{{!'os!!53¿ ¼ 65¼ ½ hf‹‹gc„~ddŽ~|vs}{×Ù`a’ ¯®uÿzÿÿ\_ô ÷ “ ‘”qr¡¤ËШ¬r p  |xP N PP…‚jh‚ƒ˜—·´´´òòž œ xv!!EF,/,5¸Åt€ õ þ /6e f C A ¿½ µ¼%…%þ#ÿ#õ÷o$o$ó&ì&i)`)î$ç$k"h"% %ßáðí5.¼²=7ÇÆ02ABccss—–š˜f!d!®­! !¤ÌÒöømm‰‰U(X(*.0.à&ä&++’ß&á&€*…*˜115929eA\AïGæGOOéJëJ L L6O7OßEàEšBšBW9V9×=Õ=óCïCƒB€BBBABtGwGuIzIBCFCÁ@Á@¼@¾@´E¹EII3H/H FF°P´P°W·W¬\¯\Ê`Ë`¨c¨c•c—c]YbYWT`TOQWQ„LˆLÚEØELAKA}:}:;;">#>È=Ê=º7»76,8,ò-ò-¢3¡3[5^5®9±9ç@è@bAbA77}33”+–+<#;#÷"ó"Ë Ë PRUTÂ"À"g!b!þúFD¦¤  ý…}÷÷góióñôóôWóYó³ó²ó&ò$ò~ððÚòÛòFöDö(ú'ú}ýýÙÙ  …} }~ÖÖOMDCOI«!¥!(#'#ÚÝÉÌüýV#U#¤#¤#@!A!˜™¾¾þÿŽ ººÙÕ% ef.-–;7,.biøýs v   Š Œ } ~ žòôùÿ{t v ÛÚ¡žÜÕŸ™wõuõ…ô†ôÃìÀìÂè¿èÛëÚë(î'îéõåõòøñ‘ðŒðòòñžñ%õ"õ¬òªò¹í¹íî îìêçê±æ®æºèµèAå>åFÜFÜWßZß è ètñtñÜõÛõ¿ù¿ù}ÿ€ÿKLòýñýmj¬üªüÔøÔø£ú¨úÂýÇý–ý›ý¼ó¿óØùÙùÞùÞùîôêôýëúëWêVêéé·é·éåÞëÞUÙ_Ùuää é*é/î4îˆí‰ívóuóÄ÷Ã÷K÷J÷²ó²óëñçñYîSîñõïõ¨ù©ùøúùúÑÔhüdü½ùµùSîOîoàsà6à7àyçzçìžìWïXïžêžê±ä³äeâfâãÿâäýãÐæÒæã%ãàÞåÞwæuæ#ê!êÕî×îïï,ï'ïîîRñPñ?ú;úEñAñ¬è¬èyê{ê¸ë¼ëýö÷úúOðGðžë™ëî‹î%ô#ôê êVá^áQäXä7è;è•íí­ñµñBùDù½ö¾ö,ô-ôŸñžñWëYëƒï‡ïòíïíªô¢ôÙñÖñ2ò3òeñiñ òòYþVþûûXÿZÿÍÎ,*:8ýÝ Ý  " “ – ‘ ’ ý]bøú´²ó ë k e cd¢¤B?~ÐÒø"ù"23¶¸%ü%üµ³¶ ´ Û Ú IH5ý5ý€ó€ó¤ñ¥ñ¢ö¥ö4ò6òUìSìwêrêàä×äïï«ö£öëøæøaû_û>û;ûÿôûô¢ð£ðëìòìè è8èBèééÔìÏìWñVñƒó„ó\ü[ü'%_ a ¤ « ¼ÁÎÊü&MHÐ"Í"E$E$)#(#«&­&¤(¨(o%r%V"X"7':'\&[&#%%ZSÒ Ò ¿  ª ¬ b ` t n ýùøøUôTôŒ÷‹÷â÷Ý÷™ù–ùØöÙöïžï"å#åÚèÙèvëuë®ë°ëíínåmå æ æWçYçˆç‹ç¹ä¸ä4á/áYÛRÛÈ×Ã×ÔÕÔÕžÉ¡É ¾¾°½´½PÂWÂ^ÅaÅaÁ`Áö¿ö¿}Á€ÁöÇúÇãÔèÔ`ØaØpÖmÖØÒÙÒ/Ù4ÙcÝlÝœí§í÷ ÷‹ñŠñ|ïyï:ç7çôäñä`ã]ã…éé'ç çÍìÆìÊíÇíåïäïVôXôþóôüúûºôÁôNíRí0î2îUòYòfðgðì÷é÷­©B B >ÿ@ÿôô”é–é¹å¾å´ä¸äðÝóÝàà¶ÕµÕØËÔË÷ËñË Ï ÏûËÌÅÉÎÉ]ÎcÎá×à×gåaåõäðä–ääðçðç@ê?êÃîÁîœë›ëáá@á7á ëëì„ì¼ë½ëÓåÐåîÛéÛ†â…âÈèÉèþëÿëî îðð3ó1ó|ëyë?ã<ãÙßÕß è›èÞïÜïÀðÂð©ø«øDF|€nr …ÏÌ£ ¥ ‹ þ ý áüßüzì|ìïñóñŽùùjÿfÿû‹ûÄÿÂÿ86“ûûºù¶ù][™–VRžÿ˜ÿ‹‘Œë纷ÖÑ60¥¡ÒÒÒ׈©¬øöœ˜Å À ±­’ ‘ • “ G F ÞÞ¨¦ÖÔãáMQ €‚åèøø?ù=ù:ð8ð èè:Ü<ÜZÔXÔoÜmÜ+ã,ãIÞKÞšâžâ³è·è—õ˜õ¹ùºù:÷;÷óöðöxöwöûŠûÓüÌüniÈþÄþÛúÚúwùwùÒðÓðÄìÆìçóëó½ý¿ý9>x V ] ò ô ¨ § ²²ORÄÉå ë Ð Ò ||ËÈ10®±ÍÑ][a\Í Ê !  èä<û2ûÉðÅð—ëšëñêôê‚ééâŽâAä:äiã]ãªè¤è¿ãÁãÔàØàââÛÛÞäàäííòíòíýíúíéÿèˆä†ä$å$åÅçÁç@å:å6Þ3Þ&å$åGáCá‡Ý‰Ý6ì>ì«ðµðµö»ö÷÷™ùùźȿÎ̽ÿ¾ÿ¾öÀööögôiô0ò0òéøäøùóõóÍ÷Ï÷ÖÝê ò Œ  ž–‘ƒ€)*=?··JH43%%((µ%²%5!3!% # VTçä4.˜–||ÑÕð÷•ssŽ  ôû !!D O "','X(`(g'n't&z&C(J(s({(á&æ&s"r"m)j)€9~9žDD7H8H!MMÚMÕMÆDÆDâDçDQÚ=Úàýß!è#è2â9âxì{ì¼ïºïÑíÍíñ ñøêùêÁðÂð’ííPàGàDÞ?ÞààcØfØ Õ Õ¹Û¸Û‡ØˆØÚÚÍãËãÆÛÁÛJÐDн˷ËÖÈÐÈÔ{ÔÖÖåÙèÙbÚdÚPÕQÕiÚmÚÖÑÙÑ·ÒºÒòÖøÖ.Û6ÛgÛiÛ5Ô6ÔÑÑðÑðÑuÊrÊ>¿8¿À¿»¿2½0½¨Å¨ÅÌÌUÉWÉÈÈ»ÆÄÆ{È}ÈUÉTÉtÊxʭưÆËË ÒҎʊʯǬÇÒÒÀÔ¼ÔNÑKÑÇÐÈÐÔÔààæîæîÿúýú22´´¥ÿ¨ÿyyyvéãvt=A **&'''$*þ-þ#ý%ýåôèô_ùbù\ûbû™ó¢ó]ðfðÝóàó·üµü0ÿ+ÿ$!ÇüÉüâ÷â÷ÈúÅúàùÜùkiZYvy±µ±¸Õÿ×ÿ·µ z{››2û5ûô ô ê!ê’é‘é÷é÷é}è}è£ë£ë*â'â¿Þ¼ÞÙâ×â¿Þ½ÞÈàÊà¤ä§ä­å­å¨Þ¬ÞÅâÍâ»è¿èuãrãOìKì\ð^ð”ðœðõ¢õ‚ýƒý=ù@ùtòyòÝíÜíBä>äÙåØå«ä¬äÓÝÖÝWÖ_Ö/Ô8Ô ÓÓrÒwÒßÔâÔøÎúÎðÉòÉáÇæÇÎÎÌýËØÆÑÆûÇöÇåÏÞÏ'Ú"Ú××F×E×@Ø=ØÖÔÐÔÕÕšÚŸÚ•à›à0Ý4ݲձÕÚÚ?ØCØ Ï Ï‚ÌÌáÊàÊìÂí±¶ÂÀÃÅüǺÇGÈBÈÄÁÅÁ{ÀÀ··‚¶}¶³³Í­Í­S¤Q¤¯¢±¢§¦­¦ë¤ñ¤m­t­ ¶¶•¹›¹í»ô»[ÂbÂ^ÁaÁ<Ä=ĨʩÊÏÏFÌBÌ-Ò+Ò-Ü+ܓܔܴ޷ÞLÜNÜ_à]à™à“à ÝÝ|ÝyÝèüçÉèÀèJâEâ\äUä{æuæ]ìZìjðið˜ë–ëææ5ç4ç-é-éÕñÓñ-ú)úôñòðhüdü ùùC;ÈÄÿùüùÁö½öþšþ‚…öŠösóyóö ö÷óûóéùìù  { ~ ¦¥öøÆËB E ~ } „‚MJ*ý&ý- 0 ØÞ$%ÜÙZ W ÁÂjýkýBþBþxyþúþúÑóÎó•òòñùïùÀ÷Â÷ÓõÖõŠõŽõ:ÿCÿT]JOßámo,/îô¼Àáß(#&#""º¼öùþ    þûoo(,_a53¡ŸÏÌ  ÜþÚþRýUý¿ÿÀÿtöpöÛì×ìòïïïÜéáé÷ÚÛzÖ~Ö»×¶×¢Ö›Öå×à×ÙÚØÚUÕYÕ-Õ/ÕÓßÓßjáiá’Ú‘ÚšÛ™ÛÌÞÉÞææÀìÀìyì~ìCéD鬿©æ—è–èiëmëîî“õ‘õðóìóRïNïTõQõ&ñ%ñ4÷1÷™ý–ýØÿÖÿÎûÌû…ï„ï3ò3òäðæðàòÞò ööúú½Âÿÿ{öyö‘ë‘ëlâiâ¯äªäŒé…éôñíñŽù‰ùáùßù<8_X8 5 hgíëDD¬­FE""k*l*7*4*5#.#d$\$¥¡kiÒÑ~  be£¤Ö Õ ;:sr' $ Ï Ê óí™”©¥«¦ÙÕûùe d ¸ ¹ –•=;ÓÔWüZüI÷I÷úÿûÿûú‰ „ ¯ ¨  XTD @ ‡ƒàßÔÓ$ DD†Œ½Ã  l f BA†‹Üáe÷h÷âæãæ7â5â,è-èªé«ésärä½Ö¿Ö!Ö&ÖÂÖÆÖ)Õ(Õóßðßsävää–ä1ë1ëOóOó ï#ï$ç'çyäyäêàçàsàsàæäèäÍæÒæjäoäîäìä´à­à˜ß•ßÕר×\ß_ßuóvóñöóöð–ðèãëãää”è˜èÌïÒïððSöOö=ü;üÔþÖþcücüéúèúŽé ð 6ÿ>ÿ26Ž‹jÿiÿûžûÍüÊüññððCÿHÿÚß"$–˜Š‡Žäç¤ö¤öòò°÷¯÷ŸŸC F †‹ô ù _ ^ ¦ ¡ 1-íì0/wuóõåêZ`¾ Æ %—š ç æ ÊÍ·¹žœLH¨£ÝÖto:8""zwÏΤ&¦&/1/1ì3è3Ã9Â997=7AAˆ?…?9:5:ƒ4„4È3É311b(f(Y`-4ªª ¡\a ýÿ&'NýJý¤úžú:÷7÷ýéüéî~îææfçkçPëQëKêEêjífí¼òºòÐùÐù"ÿ)ÿfm ik±þ±þ^ù]ùºüºü© ¬ ,2ÅËÚáV\SRzu‹†&$;<úúiþfþõõsõvõÎ÷Ô÷ÙúÛú1/JIÊüÊüJñMñsíwíÆèÈè|áá—ã™ãˆð‰ð¼óºói÷g÷/ö,öõ‚õþ•þ˜Ÿ`g ûýkjdein/5ÄÇê#í#61:1M7N7ú>ü>H4H4 22.~.--ˆ.Œ.90;0--¤ ¢ ®«rr{}HHÌ Ê p m zuØþ×þ¥¥\ W øõèè33óó½¼”’†€[T$$q(p(--›$™$PP²¯þ­ª‰‹ž!¤!l#q#O"P"¶!µ!Z[15ÇÇHD·³qo••lp¶ ´ …úú%õ-õHùJù`ûbûý!ý36ý ›“€|? > ÿÿecÒÎæå››VW›˜yuÿjl;=Ò Ó €da» · ä â ge¦¥† ‰ ÒÒw u 9 9 QR¬©NHÖÍ%  Á»% ! -.ÓÒ  ˆƒ‡XZ–™ÍÏÿ·®¼´}y³ ² liW U HNÁÆ‚O)N)00V/T/A+>+`)`)–$›$ÂÇ€‚UV…ŒU^U[_^% %*('(u"u"%$(%WTljÂÄ€…-'/'])^)®'¯'Ä)Ä)£¥ÁÂÕÒ`!`![!_!… € ˆYVÉÿÈÿöýòýC=Î È Ð Í b`¤ ~ | ûþšœa#^#&&Ï+Ê+y-t-$ö#ÿ##YYÅËšŸá à ¹$·$Ó-Ô-R2U2è;ê;AA¡1£1™0–0í+é+l$o$W]‰‹íîpqPQÅ Ä åääå–ùlr†‡kl»¾ nÿvÿ;Cª°úúýú JFŽ Ž ¥¥É Ì ru±µ|ûûáóãó|ö{öÅ÷Á÷èøâøˆ÷…÷¼ô½ôE÷D÷•ø‘øùø÷øgþeþ…ú€ú²ô©ôí÷ä÷wqÔÓ÷ ú ¾Àaf Ž’‚uv|""tuÑÏÐΦ¥¾¾}ÄÊ´¶ù÷120%.%H!C!SNÅ'Å'O T ª¬È!Ã!Ÿ.—.Á8À8$9-9j*r*¢¡¦'œ'U&J&l-e-œ/œ/))Q+S+õ/ù/»0¿0m1n1=.9.¿(¶(É(Á(Ù&Ô&Œ ‰ üú¸¶š˜ ïæ¡›^]Æ Ç % &  /-ìêÖÐý…ý·ù´ùFôFôòòÑóÍó…ù€ù5ö0ö—ô•ôTùRù øø@ý;ýÆÄÖúÙúaóhóò"ò0ø4ø þþ»ø½øüøÿø úúpötö;ï:ïªñ«ñuøwøúðøðoókóÙõ×õ6î4î¢âžâlàfàêêî‰î{ïwï@ñ?ñÝòàòw÷z÷óÿôÿSX ¢_ \ 95^Y»¶D @ ¥§ †ˆqqb_ ,,ïìxvA D ã몲ŒÔÕòñ…‡ÃÉóú ûûÍíÔíŒææ˜æ•æâíäíÿçè”ä•äžäœäâ âIåQåÍåÑå0ç/ç î îRñUñ–ù™ùÎÿËÿ­ªtu–š#$ËÍT!Y!›!›!''ô$ó$}„†\[éèecTSú ü BEYXþE>üëäûùDF…ƒ\Y  úúÀÁ Ÿ¡./°®ê$æ$k2h2[:X:ª>ª>‡;ˆ;[É>á9ä9­C²CýMÿM([([;]=])_+_Q`R`Ó[Ô[ºV¼VÕJÖJYCUCf>`>¿7À7R7V7C›C8E5ED=C=2€2ï,ì,Š$Œ$û"#Ð Õ Ù!Ù!''‰ Œ CEœ¡hj*'ÅÄ•“èæij¯ ¯ o&s&Ã#Æ#ÅÅ01¿¾?<ð#î#°$°$˜™™ š dg33’•EE$%#%è%è% - -hŸ>oEsE IIpOsOlPhP«P£PnNgNÝD×Dj:f:ð=ï=Ž==°;³;•5™52,1,[ X TV)-  Ú×°±ÀÿÄÿ•—ÜõÚõ1ì2ìQñTñÓøÓø:ú8ú0ý2ýŠ’+'£¢ÆÇ¬ ª •‘N M £ £ l l FGÁÆ`-g-J8P8V@W@‹>†>8>2>;;7„7ê;ê;ç:á:œ0™0Ë.É.55‘6‘6 6 62;1;â;ß;Ô;Ï;'?%?/>/>â=à=??›DœDîCèCù>ð>_9Z955@.B.«%ª%!!jj²°õðŠ%†%b%`%tyƒ!Š!''Ð(×(Ü+á+‡.„.Z7U7a?]?›:–:ë5æ5È1Ç1‹/Œ/_1^1¯,¬,ƒ//4ü377<<í=ð=‹7”7Â5Æ5Þ<ÙZ>C8:8 B BQHNHFÿE%D#DcCdCâ?á?¾:»:º6¹6^3b3A8C8[+]+~++ ;¥;FBMBÛ:ß: /Ÿ/·7µ7: :‡88z1u1¶(´(½)½)ò)ô)š,œ,U1X1F6H6œ2™2ä(Þ(k*i*m*o*;;_E[E˜G—GLPOPeLjL°V´VÇSÊS G GCCÝBÞBC C¬<¯<6"6 ::"@&@X:X:r;t; ??«7«7Ö0Ó066ø:ñ:©A§AÝJÛJAH>HTLTLëOìOÚQØQ$U!UÐKÐKµF¸FJHLH F F{H}H´N´NlQkQSSÛOÚO¤I I÷AïA1>)>x8u8Ë4Í4²7·7Ú8Ý8¦<£<…B‚BGGHOHOœO OãIçIã@ã@11%%##!!òñüg g º¸àüáüâýäý¡ ±®i e Ú Ô þ orÉÈ¡   „ƒù ô õñST()ùú» ¶ ]X& & ²³« ª GEÑýÍý£ # # «±ðñçé®¶5>ÒܸÀÁÄËÎfm – EM¡£”$”$ñ"ô"!#!ce{}¬±=D–š~~í ï y | à Ü ×ÍŸ ˜ =9£ A C 3 8 ¾ÂÉËÌ!Ì!cbŽqnwxnnÉÈÌÊõõ\ë_ëŽãŽãKÙFÙ Øÿ×ÛÛ@Ù<ÙóÜòÜ“á’ágçfçÃçÅçê êUéZéììÉíÇí‰ë‰ëeêhêªî«î–ó“ó ùùúùôù\üZüHþFþ½ø»ø=ü;üÍÊnÿnÿ’b j ª¨40WVÚÛFDäàLJIK¿ÄJ Q Ö Ý ÈΤ©W X 0-%&/1êès m ˆ  L D ååáã~~|vÞÕÞØ²¬ysH E  ¦¤ÃÆ?@¼û¸ûüü<ö?ö|ííää{ÝyÝ(ßß[ßNßÞ•Þ&Ô#ÔnÏnÏNÐMÐeÍbÍiÌģ̥Ì)Ð/ÐTËZËÎÍÍÍúÅóżºµº”Ä’ÄzÆ~ÆÓÃØÃÁ‘Á©¿¨¿ü»û»†¶…¶±±Y¯Y¯.­*­›«œ« ª ª ««C©L©Q³Y³‡À‰À'À%À4Ã1óŵŭɰÉpÓkÓ™à‘àëØèØÝÏÝÏIÔFÔÕÕ®Õ°ÕcØ_ØeØ`ØÔÔýÒýÒ7Ú8Ú‰ã‹ãÍçÎçžæžæWãVãØåØåKêMêÚçÝçPãRãAÙ@٤͢Í9Ë8Ë<Í;ÍGÏIÏêÔíԃ؆Ø[Ð]Ъ̩̗ד×ÎØÉØ7Ú6Úãã»ç½çŽäŒäÜ ÜááààëÝëݡܟÜPÝKݡۜÛâÛáÛ¬á¬ádÜf܅ډڪݰÝÝàáàëëç÷ë÷dþlþelÓÙVZƒ~ÈÁ‡ „   ÒÐóóFDñíTR¥ « X_?C::CG£ªjoh j II §°ÆÅR#M#¢#œ#f%e%¾,½,­/¦/7 7Û3ã334:4û2322/‚/q/q/h4e4ž;œ;w?v? 8822%,',÷#ù#f#l#8$?$9&>&G&I&ä ä ùø^ZŒˆ÷÷Ùݸ»ieª¢ÿø¦ £ MJÞ"â"bj5>ð÷;?ÿÿ03ù ü ba50®¬9 : / 1 URÇÿÄÿ‡‡99™ùù÷÷ºû¾ûZûaûùù±ê¯ê§Ü¥ÜèÙæÙiæhæ6ê5ê¼Ü¹ÜÆÞÃÞ·å¸å2ê3ê[íXíîêêêóëôëììOáVáè èˆïï ë$ë’ì•ì×ïØïððUëNë2á-áuàsàyãvã¿à»à—ߔߺصØ>Ö9ÖÙÙ>Ø=ØÌÕÌÕ§×©×·ÕºÕæÑãÑÒÒ¯Ö´ÖÙÙÁÕ½ÕØØ×ØääÏíÒíÝðäðHïOïõò÷ò©ÿ¨ÿ÷ ø œ›-*PMÆÉ|±µI K ò ñ b_ Ê É i l L O ý îø„QW¶µnj-(èåbbJ H §¦21KJ þúýNÿHÿ26{‚•˜ÏËŒ‹17V^MR  £¥ü ü$ûûBû;û°ö­öõõ#ú&ú¿À  ÈÐ+1` _ Ž ˆ ˆ‚ BüDüJõRõÀñÈñ\ø`ø8õ9õYî[înïpïööøýúý!è â ¢ 𠍥öû÷ûˆúŒú—ü˜üŒa e ôõ¤§úÅÍûÿ[þ]þi÷l÷…ò‡òda$ ! é ë GH51œšŽ›œNRmoa`††™™­­ˆ‡ÝÚSOÍÈž™¶¶® ®  e÷]÷îæåæIâAâ½ä¸ä󾆾oæqæ1ç7çï‡ïSòTòü÷û÷bbÛÖÊÄôõ_b[X¿ýºýIHG E G C íë~""R*Q*~,},1252Ç1È1Y2W2//ê/æ/x4w4,,&&¢%ž%%%i0j0Y3\3¡/£/#8&8V:\:#4*4ù0þ0â,à,x%p%Ï#É#j$d$a1^1ñ;ø;.:9:6787Í4Å422g1d1%1 1ø!ñ!ûø-,b^!!ï!ô!TVÔÑðïÊÆa`X [ ËÑ•½Áß á T R ÀÀ $»ÿ¸ÿ¾ý»ý*þ,þBüBüÁû½û6 :  ¢¤ijé ä !­©-/ÄÃuo±°ñôÕÔ**y|—˜%%à-è-ò,ú,‹..ë5é5:141i.d.ê,ç,t&q&=!;!¨!©!»»prìî// $G M ž¥)ù+ùöñóñÜïÛï#ó%óõõùòûò»÷»÷€ô}ôÍíËí'ï(ïžòžò¸ù¶ù++M L &% ûûPïSï¶îµî‘òŒò÷÷júbúòí\]| | žžkmàä¶¶' ( ô÷W!V!—(”(Œ&‹&%'!'Š&&”%%u)x)ü(ÿ(È$Ç$˜$œ$§'±'4$9$ö!ø!),ÈÊz(y(*.$.W3P3ù5ô5;;Þ@ß@JJÂHÂHCC¥C¦CŒG‘GPITI˜GšG6D4D]CXC0:/:õ1ú1Ù2Ø2;; ==ø3ü3é,å,¾'¸'x*t*ã$â$9:PR!BD ¯®:9!$(.ü‘ü@ðBð‰íŠíüðñ¹ó¾óiòhò±ò«ò5õ/õfùdù!.0ÐÑâä  ä&ä&à+ß+11q*l*’*‘*á/ä/ì0ï011Š//W,_,à(è(S*X*Y1]1¹1¸1’..Â-¼-L*K*ù%ÿ%Ã Ë NO ²¯LHˆ…•“ô ñ @B;þ@þMúQúÂïÃïzæxæGéEé æ æVáSáÙâÔâ­áªáqÚqÚþÐÿÐ~ÏÏ0Ò.ÒÔÔŽÐŽÐèÉéÉ[Ç\Ç]È[ÈöÈóÈçÏçÏÕ–Õ¡ÙªÙ)Ý.ÝœàœàXåZåé éôäñäNèEèÁì¼ìíí¨ó¦óññØðßð\ðaðµó¸óãñåñâñâñüñùñ–ï’ïñøîøy{ÀÅ‚èèôð¹µ¥ ž Ê Ä \[suî ò .0š˜Ë Ç 42%(÷ÿ±ü¸üéõêõPñOñÈìÃì4è0è¤â£âÚÜÙÜãØãØÖ֌؎Øy×{×]ÕaÕG×KסդÕÊÓÎÓÑÑîÎèίԮÔMÔSÔ÷ÒûÒÄÎÈÎXÊ[ÊÂÄÀÄÀƼÆ{ÆvÆèÅåŇ̈ÌðÑòÑ;Õ=Õ“Ï—Ï×ÐØÐãÙÝÙÍÖÈÖkÒmҬدØ:Ó=ÓÒÒmÐjÐÌÊÈʢΛδӫӃÙÙ­Þ³Þ…Ù‹ÙrÚuÚÛÛ Ø ØÊÝÒÝUä]ä;ã=ãuÝqÝ»âµâqámá´ã³ãwíuí¡óœó«õ¦õ±÷®÷ ùùSQùøTS©§ <>¦©‹Œ:;‹ÅÇo l :#6#I H 02EFËÍBG¹ý»ýnÿlÿàüàüc÷i÷ëôòôhìoìòò:ø<ø‘ù’ùøüøüãúæúŽü—ü0ü:üflìÿíÿÏúÎúÇþÊþ<ü>üñòðò ó¢ónñuññîøîÓóØó§ï«ï(ñ,ñ÷÷ûøþø[ó]óµçµçbã_ãÈßÈß ÞÞÍÛÑÛdÜjÜä äë"ë>ïCïõíõílòhò÷øöøÀüÃüóúôú¨û§ûuzéþðþ„ú‡úZóXó®ì®ìÿæç!æ æ áá/à/àÃØÆØ%Ó)Ó•ÖšÖÝÏÝÏüÊõÊÒÐËÐ!Ü Ü>ßBßiàhàôàîàÐçÍçñéòéEëHëêóêóÓõÑõôýó’ï‹ï5ó8óàñæñEïEïaîbî]écéîèôè§ïªï…ø†ø«öªö9ø8øãÿâÿ>>ÅÀÙÒð í a_  QM>7D#A#%%¸+´+L+H+øøOTAFÇ Ê . 0   ØÚz|àá`_ýú§¢MH££##çå” ¡##Ã"Á"‰)Š)0 0—,ž,;,>,÷-ø-ý'(]+e+x*|*N.Q.]-[-i+f+´+³+Z,Y,ƒ11u5v5q7v7#8(8s?s?ý;ÿ;ß>â>È7É7-4*46 6Ï4Í4w4x4ù0÷0i5h5$*#*’"Ž"º!µ!¹#·#ò$õ$»»jhÕܤ!¥!‘'‘'R0T0ã,á,%$ $¥ž/(üøá⦫34ï ì ||õýV^ ËÇèüçüõõòò¨ô¨ô¬÷±÷‹÷’÷ª÷¯÷ßùáùÄûËû~‹%0àÿâÿúú+(ô ò lmÜÜÉÊK O  ¹ Á X\  êîÒÖ “v}€ü ú 79;;©©Y\MRñõ14ÛÝËË×ÖöõØØò ñ ™—¥¡HIÑØ9!?!ÿ&'Š$Œ$\\””ÇÆÔÓ—š`!a! $$  ŸÖ×É˾¼|y+,ÉÌjhIûFû:ó=ó‡íŽí è è½éºé}ôyôÝÝ’–…ˆbbPPŠ‹/* ççêúëú›úžú6ö8öïïèðåð®ñ©ñ ò òhòiòAòBò‘ó’ófókóÈëÏëvæuæIæBæ:è5è¿ï¿ï¾óÀóG÷E÷†÷ƒ÷óóòòððóóWñSñ ÷÷PùIùNöHöšî›îÓê×êžó óDóDóòòIñKñ½õ¼õ¹ö´öÖøÒø¾öÀö,ô.ô˜ñ˜ñõðöðŠòŠòìì»ä¶ä”à’àááÄÜÆÜlßnß#ä&äÜÝßÝ3×2×ÔÔÑÔ€Ú€Ú<Ü?ÜþÔÕÏÏ®É²É·È¹È¼É½ÉæËåËQÊOÊÅÉÁÉáÎÛÎΈÎGÌFÌ%Í'Í_Õ\ÕÛ ÛËßÌßkénéßçãç5æ=æÇåÍåææôëöë í íòëõë»èÃè*ê/êÎíÍíìðéðFõAõêòêòŸõ¤õù$ù4÷4÷·õµõñ÷ò÷¿÷Ä÷ê÷ï÷ úúà÷à÷ÛýÕý½µúø×ÛÄÇ“ ‘ %"ÁÂ!#53  Ä Æ € ˆ ÊÓ5ÿ=ÿæüçüïëFC$%  { ‚ ÐÚ("áßâã÷ ø GC  › - (  AF]aô ÷ ÀÃ÷øÈÅÙÖËÎ*1óôg$`$ê å ø!ø!BEŒŽsp¹²º±ÊÄôõ­ ­ í!æ!$PH\W3!2!¦#¨#P"R"æ$æ$„)ƒ)ã+à+ % %ŒŠ|{÷ð º  ±²Ž’” — õôîð»ÃÄ!Å!! !>"="H"C"} | ##\%]%r*q*c/e/}-€-a-e-ù1ÿ111®0¯0¥2¡2Z9Z9±6²6À3¿3K2N2%0&0‰0„0Ç0Ä0ö3õ3N4N499»6½6W6R6£CžCƒI‚I@GC>œ< <´8º8©8®8ç;ê;j:k:l5i5Õ0Ó0Z)Y)Ù!Ø!tpk g -!-!$$³'µ'!!!µ²öö¾Ä˜ tt³°ÑÓÃÉãæÊθºqm‡‚OL46©¯).^"b"¸"º"¼!·!‰‚lhonLO -*ýNJïò]d¦«{zB=µ²ŒˆŠÎÌÎÓêò(,9 9 T X . 4 ‘’¤£Ÿ ¡   L Q ßèS[""«"¦"Y!W!c!f!  ÝÕÖÓY Z % ' ik¶¸c c !üúúöúê÷ì÷ÅôÉôññ]ù^ùMÿWÿÀÿÉÿîÿíÿNýIýXúUú¤ý ý%ÿÿÿÿýý¼ú¿úïøîøìòòòÜðãðóòòòQïPïþìí6î;î©î«îˆè‰èlßkß×á×áááeÞlÞfÞmÞoätäŒééoêoê}ðwðêõâõSøOøìõìõöözúxú-ý(ýñýíýÕúØú"ú,úõýþývÿyÿ±² #.3NþQþ¤£ ¹ºX \ ¨ ¬ ¡ Š‹„‡áàz w áß«©$  kiTM«¤TS´¸ Ýä  «²ü ÿ “ ÿüCH=ýDý¨ø­øžõžõ‰ö„ö™÷—÷LôMô½ë¾ëå!åýèüèÆïÁï?ñ<ñjìiìæìâì=ð7ðBò@ò¥ò¥òçõåõ¦ø§ø:ú@úlúsú×úÙú–ø•øóüò_ðXð’ìŠìïìçì°ê§êÌÞ¿ÞxÔmԴѰÑÍÍÉÉêÐëÐs×r×-Ù+ÙOÚOںݿÝààÝàÝàYÛSÛæÛâÛ’à“àÎßÎßnålå|ázáüáüáœä›ä†æƒærëqëwîzî5ó:ó‰÷Š÷6ø3øòò:ï5ïïùçù«ÿ§ÿ,ú-úþúûû û0û5ûÁý¾ýµü¬ü8ø/øEñBñ è£èÐåÓå€è~èøíöíÿíÿíÖñÕñ&ò!òlëgëë˜ëèèËæÅæ=ä9ä¶Ø¸Ø€Ö…ÖÑÙÖÙEÕIÕ××rÚsÚ\×a×ÐÒÓÒnÓlÓIÕGÕÞÚÜÚyÞvÞÛ ÛUØQØr×nו֖֛ҜÒÍ͔͕ÍüÐчՎÕAÚDÚßÙÝÙøÕùÕGÔNÔËÙ×ÙYÕcÕ_ÐdÐ&Õ+Õ`ßbߊä…äòçìçõïñï‡ï‰ï¦ë­ëþçèè€è5ì5ìªí¦í†ê|êfé]é}ä{äZß`ßTÚYÚÔÔAØ:؛۞۱ܹÜAßCßxßwßÕÚ×Ú³Ù·Ù Û Û¨Ù¨Ùl×n×ãÓçÓþÏÐ Í Í£ËŸËtÉuÉ?ÊDÊÿÉþÉÑËÌË¡ÍÍ8Î4ÎýËûËIËLËËË@Ê@Ê4Ë.ËðÆéÆËÈÈÈCÈEȢŨÅÛÅâÅÇÃÌøÁ¸Á™À”À¿¿‹Å‹ÅdÊeÊÈÈrÈtÈÊÊ‚Ë{ËxËtˣ΢ÎöÎòÎÂ˼ËÊÊ¿ÇÂÇBÆCÆ_Ã\碠ÇÇÁËÂËÎÎmÏoÏÓÓÖ•ÖÈÛÍÛ“Ú•ÚÐØÑØòÖóÖ9Ù9ÙËØÆØXÒNÒÚÑÑѷѲÑÖÖ[ÙSÙØ”ØWÖMÖÍÚÈÚPÞQÞ„ãˆãWâYâKáFá.ä&äüáùá4å6åÍçÐç?ðAð`òaòÀïÁïððÙíÙíÈðÈð?óBóQñTñiðiðŽîŠîÝðÙð!öö³ñ²ñ-ì/ìXð[ð•ð–ð#ð"ð-ó+óÕòÒòPôLôzøwø%þ#þ:6§¦u w ÷úðï´­öð{y•”Ó Ô ! #   e ^ ïèdg6=w w \ [ )-³¹° µ  # à è — œ ¢£vv° ® v u cb¥¤C@KDßÙøø " """zqm¦¨‡ŠÂÆ´¹ŽttœŽá à Õ Õ Žñõ&(}|Œ‹RSssDG†‰ÃÁÚ×Z[deÄÅl r  † !!l"l"@$?$‰'ˆ'C&E&²)µ).'.'1%/%À#½#&"""c!`!Ý"Ü")“)Y0`0 11--k(n(—'™'Ë$È$´¯! !¢ ž 3 0 %&"ÇÒ…‹æç  ÑÔŸ¤©¬Á¾YRŽˆþ;Cß┑}vïëlpHOKQèîÇÇ­ª||Þà€‚·»~~‡ëà%JCª¥$"ØØKHìâ5 ' • Œ  kmâÞ¿¿—™¤Ÿ‘Œ þŸþÂýÂý³ÿ²ÿPOÊÉJGóÿïÿMüJüMüNüÛûáûºù¼ùÂüÀüggvt^bIOk k ¤ £ á䙚54áäè踶to’‹("“ "!PLVS[þYþdû`û þþþþÞûâûlùjùî÷î÷*ù0ùjýlýÝüÙü6ü1ü]\ÆÂ¢Ÿ<ÿ>ÿ½ÂLNÑÏÄÀ¬¬xxNL­¨ vsÒÒŽ Œ NP&)qríïžøö&"n l Ï Ñ orËÑÃÈäâ  ôð89jt—£U\BAûVRóòYYÝÛ70úöëòøÎÏ× Ú ÉÈ ÏÍ ®¶£ëíyv©§½¾×Û\bÑÒÀ»ðõ2.SOOJ3 1 Å Å u w - / }××±«íç\ [ ? < A?12ýýòᄎÿ•“DJrsÛ Ù ›öùUXðõæè‰Œpqõ ò Ú Ô - %   „ ‹ ‘ ˜ Ú á á å ts³²ÌËçäâÜ ÿÊ¿$ $ `ggk³´×Ü  ^![!û#ó#ê"ä"G!E!"ü!m!g!¬ © T T A#B#é'è'}({())€(„(‚'‰'K'O'!""/,Ðϵ·ŒŒ ¢„†ÅÅ""¿)Ä)--//0€0ê+é+ø(ö(§)§)ñ&ó&Ï&Ò&Ü&Ý&p$n$º%·%é#é#°¶CLÊЃ€73éìT%X%@&I&Ó"Ú"ó$ø$ò'ø'F'M'7+<+×-×-Â,½,f-c-‚0‚0¶1¹1Ž00ò4í4ñ5ê5¼4·4Å0Ã0V+X+r'v'ç*ë*À1Â1 4 488-8,8˜3˜3¼/·/ÿ)ô))…)…*„*6$;$†‰$#¶·~./ÎÊGBHE" FFùù1/23:8D@žšv t ` a bdíîUV~€ÜÞ1 / òðÐÐÅÇ ßãP Q ¶ µ ãäbiIPèêhg!!^ _ n!p!Q"N"F?çãõó ~ u!u!¸!º!œ# #ù&'s'{'o&u&»!¿!““NJ!Š!R"P"‰"Ž"˜#£#X#`#– ™  VZáâ" ÒÓD H ŠŒ‰…€|@?DBò96ïëêèux“"-+óóÛ Ý ¨¯Ûçã î d i Ø Ù !  ] X ï ë ¶´…„""“”57knA>NÿEÿ*þ!þVýOýçøàø¤÷ ÷úúù ù©ö®öÜõÜõ_õZõ5ô0ô»ò¸òõõîóäóAô<ô~ú~ú›ùœù ÷ ÷­ö­ö\÷Z÷üüöÿôÿwÿpÿ­¦®¨ÿ^ ` 3 4 § © ÈÍAE:<Ù×ûÞØÅÞ ¡ 9 ; ¶´jj³¸it¼ÁÜÙËÇ- -  ™ Ÿ k p JJfcËÉ€}'+OZFOÂſ¦ªŠjoÿý!Û Ú á à ƒ € ²¶( . ì ð 2 9 ÌÓáæag’˜ila b ¢¦ücf EFþþûûÊúËúû ûJýHý™ÿšÿ‚.+ùüöüxövöŸï¡ïÓíÚí<íEíbëfëèèÙå×åsåxåXã`ãxã|ãåàåàßÞÞޔܒÜCÜAÜZÞZ޼ݻÝÝŽÝõÝôÝ ààÁåËåûäåÓãÛã æ æÖåÔåéŽéëéïé·æ¼æIãKãââaâbâ åå1æ2æŸæœæÑéÌédéaé ííîðððkópóßõãõ÷ ÷õ÷ù÷äöèöÔ÷Ô÷ôôïô/ò)òÚñØñHòFòtðtð_îeîÑïØïžð¢ðZï^ïÏíÓíìì[å\å±ã¯ãmãjãpârâµâ¼â“ášáfágá¦á¡á:å6åAåBåÿæçÜéßéé’éhèmèææêê ë ëªê®ê`í`íHíGícðcðßïÝïÝîÝî,ò/ò{ñ~ñvñuñ£óœóðöëöÆøÄøÊøÈø¹ùµù§ö¢öõõ§õ¥õì÷ð÷ãùèù©ú©úþþ¢ÿ ÿ~{Œ‡£ ž > 9   caµ ° ˜ • ‹‹| ~ F H – ˜ l p öûòóËÈ¥£€ƒaeiÿiÿ’þ“þ+þ/þ‚û‡ûcúeú÷÷ÏôÆôaô[ô+ö*öãùâùãûàûŽûˆû9þ4þWþXþ[ú_úÈúËú_û_ûÈøÉøÝøáøßøåøaødøèõåõiôeôô ôÎóÎó÷÷ýùýùôþõþˆÿ‡ÿGþAþµû­û”û’ûÄÿÇÿšþšþ²û®ûZûWûúŠúõúðú3ü5ü6>§ ª mm$ ( Á È + 2 ; A º ¾ pqëç6/®«ccËͪ¬057<¥¨·¸ns ec±¯Ô͸­I<<2v o ù ð ² ¨ d _ Å Ã ,*ÿ¤¢dd„„~p t þþKEopDÿEÿþþsüqü”ÿ’ÿ,'ÿÿ‚ýˆý‰Žžÿ¡ÿûüüü>þ<þ–ý•ýæüåüÌûÍûVûYû@ûAû€úúU÷V÷ŠöŠöùùªú­úFüEüÍúÊúWýUý}31  ‡ ‡ ®¯«®pp‚|—’.+<8áÞ®­‹ <B¬²™ $ ( d e ,(´¯  ¨ ¨ Ð Ô ¸ ¾ ÌÏû÷êãÆÂvv767 3 ¿¹Ž‰££ŠŒÁÄ÷ûee²¯ÌÌ€ ƒ ¡   #bbœVW£§ÚßTUõø€‰ MM•ÿzÿ›þ™þüûûûÕû×ûSûXû‹ûû þþüýþýüüÞûáû ú ú¼ú¿úùùEù?ù=þ5þQýJýìüçü%þ$þ@ýBý,ø0øÈõÌõ±ó³óEôCôööfö`öÀõ¾õÄòÆò›ð›ðØí×íGðKðððœîî…î€îæìáìëëfèdèzåwåäâãâ;ã;ãåå~å{å\â_âiãoãuäwäã ã=Ý:ݩ֫ÖiÙnÙfÛg۸ܳÜoßkßÿàþàŸââ›â—â–â•âèèžî¢î.ï/ïÝîÜîŒïŽï€ììœì˜ìðð*ñ(ñ^ò`ò°ò°òÞñÛñœò›òíôìôUóUóÝðÞð@ó?ó/ô-ô8ô:ô«ó«ó ôôôóóóóóôô¯ô²ôZö^öõõÁóÀó1ñ4ñBïLïOñ[ñFóKóÓóÎó ññŒî‹îÃî¿îÿïÿïwñyñô$ôø øêúðú_ü`üÚýÙýDÿEÿXÿ\ÿcûfûAùFùùùÂüÇüÿÿª©QQ¼À¡£_\‹ˆR U y‚ˆèê96•’"$î ó m q   áÝ-,fd51“” òõ  ± ¬ µ·ˆ‘7<\]±³fýjý…ûƒûHúJú"ü%ü@ü=üÖúÐúËøÆø7õ5õñ‹ñññðñiõgõ÷÷ÿ÷þ÷ööÞõÞõ¦ô¥ôõõ³ö®öÑöÍöè÷ç÷ÇõÆõðóîó‰ôŠôööžô ôqòqòœð—ðéðäðÒñÔñáñèñtñuñÛðÚðÊòÌò’ò•òXï_ïßíêíÛïâï¿îÅîî îlíií•ì“ìNìMìí íÔîÖî¤í©íJîNîÛîÙî|ïwï\ðXðhòcò¦ò¢ò_ñañòò'ô-ôöö0ö-öõ õEòAòññ`ð^ð ððòšò&÷"÷üüUR¨¥nmLIÅÇóøääge ë í aYÔÒ#$½¼**AB1,mm> A 1"0"™$•$î#í#Û Ý ± ²   7:JNÀ»¶0'HB  ר¯®><îìÚ Û ´ ¶ Ü Ú ðëd`  6 4 Î Î § ¦ Ð Ð 34¼½GGÅÈ``êæÒÏóôöûàà¡£mq') kf­­âã98kgqsÃÃji98%$=<ÌË_\(#Á¿ihíêzwHC¹²“KEI C ¶´*+}€„ˆ £É Ì ãçÊϹ¸½ · ÷ôЉlj’‘l n âã!!:>ŽqþpþFüJüdýhý'(áÞwÿrÿü–üÐûÇûíúéúÀûÃûÿ ÿ=CŒ“ý20§ªææ53$%24²² E@B?  JKÒÑ~zIþDþÿ ÿsmøó ?D`bíëgdÍÿÈÿÜýØý²ý³ýRýVýoýoýÎýÈýôüðü ü ü"ý$ýëþèþ¢žµ²¾ÿÀÿöþüþœþ¡þ ýýÂùÇù!ú$úÛúÚúJýKýóògfÖØûÿþÿŠý‰ýú™úý ý½¹hhËέ­ztƒz-&FDb`èæ% ( ê ó _ g × Ú † † k n :?y~FI#³º£ ¨ ¡£>=ÝÚù»¤¨ ¥§ïí`cÏÖ¬µ˜ ¡© ¢  þ ’ “ l p Ì Ï ÏÖ—L O  Ý Ò  A @ „…PMàÛÝ×íê&%þø[T  ðìðî„„LJ•’() ¯­×Ñ ^bËÎUWì數PO  ýLT±¹io¡WZ¡ ¤Ÿ83ÑÒ$*áâÞ Ù   ¤ ¢ @ B 3 8 Q V M S „‰ÍÑÒÕG G ‚ww  K I  #.,ŠÿŒÿZý\ýüüùü}üzüßøáø•õ›õßôãô+ô*ô~ózó·ó´ó7ó6ówõtõ÷÷5÷5÷y÷z÷õ’õøòýò!ó$óØô×ô`õ^õ¦õ¢õõõ{òwòDïBï~ððþðÿðƒôƒôe÷c÷döcö0÷-÷â÷à÷­ù¬ùªü©üý ý!ûûçùåù(ù*ù3ú4úmünüÅüÍüªú²úªø­øõôõôãóäó.õ,õÊóÇóeòdòfòfòªï¦ï?í7í”ëŽë£ê êûéùé8ê7êCë@ëDíAíEóEóõ õ›ô¢ôÞòáòéñçñ­õªõÛ÷Û÷LõLõ¹õ¹õDôGô…òˆòôô‡ô‹ôn÷r÷ù ùCù@ùiüfü^û`û%ù*ùWýYý)ÿ&ÿùÿ÷ÿÎþÌþíüçüÛúÏúøwø øøöödõeõ=õ?õõõSôXôIóKóYôYôwôvôûò÷òíòçò"ôô õŸõ÷õüõÓöØöù%ù"ú$ú¸ø·ø÷÷”ù—ù)ü*ü}ý~ýþüýEûJû‡û‰ûÑúÒúøø¢÷£÷OúOú¶ûµûÕüÕü–û”ûÀû¼û¤ü£üþýþ‚""— › ç ê l m ò ô   … ƒ  n k Š Š & & êçp p Ð Ð T Q k e î å Á·d]$îÿèÿ–ÿ‘ÿ¤ÿšÿ´ÿ©ÿ–@;{ÿxÿÿÿ,*ÜÿÝÿtþyþ™þœþ&ý(ý*ý-ý™üœü¿üÀüeübüÐýÎýsûrûÖùÓù(þ&þ©®êñ  #ñóÛÚ\[|~ºÀ`hrzÒÔ› ž Ñ Ð ZVsp~{   u t û ì å Ü Ü Ã È . 3  _ ] ö ÷ !#ðî\\§¦˜ÿ”ÿÍýËýZý\ýcýfýiýkýYû[û˜û˜ûöüôüwüvüVþUþÓþÑþrs%*”>C”ÿ—ÿçÿäÿ ÿœÿ_ÿ^ÿjýmý¼þÃþioÊÏÏÍóí"MLÛÝàß™-+´´21ÕÕqsÁÀÝÝéìyy('±¯°®ª­áåþÞܳ®–—))A<DAóõ)))%pjõþóþšÿÿ[^ÜÜVVÙÿÖÿëþçþzývýÐýÍý”þ“þ2þ4þÿüÿümýlýGÿFÿÿÿÎýÐýþþ¨þ¥þaÿ`ÿyþyþœüžüQýQýØÔLN!¡¤¦£ðïÁÁçâYR£žKJSV–òúôö#$–›­²[[ÕÿÔÿØýÖý¼þºþ©ªöøùýòö=<üûzyÖ×:;@>«ªÿ™— S S ^ \ V T C G åë²³êç.,5 7 ÖÛ´¶bbÕÖ¤¦JM\_Žþ”þÆÿÍÿþCEfdûõ5315õ÷×ÔYS±¯ª© 5 0 ÿjd_W- (   ™ Á ¹ XVyz_bÆÌ†ˆÀÂèî69WU‹ŽCH¢¥…ëô«°\þ_þ¾üÄü‡ûûÄúÉú^ý`ýäÿçÿœ¢ëÿëÿ0ÿ,ÿþþ{ý‚ýÌýÓý{u–ÿ‘ÿëþèþgd&$57º » ( ! ² ¨ “ ‹ Á ½ p q ­ ° a d Ò × EKçê  Þäp{R [ “ ™ MP46· » Ì Î   O N ð î Ž ‡ ý × Ô .(ÎËËÎÅÆ0,³¶qsïñ+*@8 ›œœŸšphÀ¿øûrn8/+'³³DA°ª¤ ‘Œ_[øú ÜÞv|Š“ ¨§ÁÁ119 5 " "!!ÏÑ´¶·µ0,j k ± ° ?"="t#t#""t o zxllÅÁ(!2,’8<-3KO[\þý—–stÉÈÝÚÎ̧£$!¢   éåqq˜™|ywG>;4ª¦Š‡jg–˜~ñô¨¨ðèr s # ¼ ¼ [ ]  cenp}¶³² ² ' & _ Z T R Ô Ö >>ZWyzÉÎZ_¨¨A@½»óñLP„„mfÜÖ  | z   ìî. 1 ¡ ¦ Î Ñ # !   ¾ ¾ ``â â ¾ ½ ä㉠Œ ¹ ½ — › Œ Œ ’ ý $ * * - 6 9 .-3.¾¼ $ HO63ÔÐèê<>uvÓÔ  .+^_wxA=öñÌÎ@D‰ˆ¯¬B@64GHK M $ & Î Ò  ZaÝÝŽþˆþ×þÎþ0(óñœžò÷ÊÎ!ÝÖûöÁ¿íí;:)  cb$#ÛÙøú}~:7¤ŸùôÞÿÝÿ‰‹ ¢3724EI€½ºùÿøÿÿÿïýíýoýmýýý“ý–ý¨þ«þ¨ý¦ýXüPü¡úšú‚øƒø›ù ùìúóúrúwúúúùùrùsù$ø%ø÷÷öö¶ö¹ö…ù†ù•û‘û#ûûÌùÉùÇùÄù¥øŸøá÷Ø÷u÷o÷ÓöÓöØ÷Ý÷úžúíûèû°ý­ýÐÐøõþõö¸ÿ¹ÿäýæýTüXü}ü€ügýeý”þ‘þüú=<uy  fh#nn¶ÿ®ÿ€þþÆþÍþfÿjÿ5ÿ9ÿ.4§«ÚÿÛÿ{}ôôøù$#hfÂÂUU¹³þ•”ñõ<?31»¸•’$!­ÿ¦ÿïÿêÿgÿfÿ/ý/ýSüPü£ûûwûuûÅüÆüžþœþÿýýý“ý“ýÄüÄüþþ¾ÿ¾ÿuy!)ËÑbg‘ìê@B£¥Y[„ˆ  óô  ^ ] ( " è á Ñ Ð 8 ; . . ” ’ ‚ € ø ú   ( ) w { « ® #"ÝÝåã*/’”Žîíx v Ë È ˜ ’ | z ðóþmp¡baLMBCMJ{vЉlÿmÿìþìþ#ý&ýÜûãû!þ&þ1ÿ2ÿ¶ý¸ý ûûlúrú úúWù^ù ùù™ú›úDûFûrýrý¼ÿ¼ÿ‚FC÷ó@<s t · · “ ’ ŽŽ]^gjÂ É ¶ ¸ ¡ e b A B _ ` ¶ ³ +(ñíØÓÿû´± 10±³Š  ‹ˆSP½¾“˜IM§¨UT!ä ä T R 8 8  – Ÿ ! & ðî þùxnûÿðÿ•Ž&ÿ(ÿýý&ý(ýÌýÍý<þ:þ_ÿ_ÿ ou6ÿ;ÿüýþýý¹ú¼úvùtùúúŸû£û1ü9üý"ýýýtütü ýýÿ#ÿÿÿýŠýþþ{ýyýsþpþDA“” Ÿ§¥ØÚ]c33ëçÞÚðílj`bš^ ^ Ñ Í Ç Ä ( '   ƒ „ V V Œ ‡ v p ’  Ò Í   \ X j g … ‚ 7 9 + / - 0 ¯ ®   ——âãÈÉÞà—ÈÊ´´65$ ÑÐ>@åáõ í ƒ } è æ ÍÌqmC>ÉÈ    » ¿ &)ä ã ó õ Ò Ô g g J K –šËÎ!ON‘ŒŽŒA@ »¹~~£¡USÉÈLKâß±¬êå »ºÛÚbdöû #jg°­É˧¨/1RTa_{x87†‡úú  ¯±}+-Œot˜—ÉÉCIr{ª°ÙÚ£¦ÅÉ£~„ûý °ªÄ¿ KE»º…‰âåB E   G D f _ k f „ € – ’ ™ š [ _ W X Ò Ò 6 5 ¢ £ L P 6 8 €|© ª > E  qv×Ö?:ƒ}·µ– ™ 7 ; 8 = ` g 5 9 © § tscdËÊ‹‰  HJefÏÓ),mqöö8 3 ÿúâ â # ß ß úú¦¨’•ý7>hmâàâ䄆çéeeØÖ_];8p l n j 8 9 0 2 ÕЂ ~ e a ô î | w ˜ — 7 5 Ç Ã   : 7 ] ] ; @ | Ù޽  11…‚„àâ$%´¸')¿»'#œ9<ovÙ á Ë Ò } † h m   © ¯ › yy Ž ß Ú „ ž å ä ›½¿ ž  s p * + · ¸ ÉÄok÷÷]a€ „ ¿ À þ ú   ß Þ  ˜–c_po° ª "òí & "  14÷òytþøumÎÌ…‹ üûøòÛÕ’“–—¾½ÚØ=:”‘ro+)èèABßá ¢59GIÁÀJJ‰ˆòñPLØÓÃ¾ÊÆËÊ46•—ý½¹¥ § ² º Ú Ü + " J@ó ó a f í ñ F M € † µ¸~~†…a`ÈÅqm¨¦0 / ú ú Š 7 = w z ß Þ ¥ £ $ ! T O mgÊÅýÏÑÁ Å 3 6   ã ä á á à Ý Ë Ð « ´ Ÿ¥EFéìNR ƒ$%UWloÛÝ<<ùú¿ÂCG)+ptÈÍgimn]ÿ^ÿëþìþYWKI“‘ø÷"  “²´ÆÆŠ ˆ ™ — 1 0 ° ² s x Š Œ E B °®POPL•’;:ðïuu.-ÒÒ´·{“”ÒÔhkŒ’‡ÿŠÿigzx¿ÿÁÿÿÿSÿYÿxÿ|ÿžµ±ñþðþúûûûûûýýfýgýRýNýWüYüþ þâÿçÿvÿwÿÈÿÄÿèãÛØ½¼YZ "ÿ!ÿTS ÿÿ2þ1þ«ý©ý;ü;ü-û2ûøûüLýRýdþdþ ÿÿ"ÿ ÿìþêþeÿeÿÿ ÿÜÕ_[PNsm|x‚‚99B=fa|{¹ÿ¸ÿpþrþ¹ýºý ýžýÔýÓýþþ”ý™ýþ þhýiý¿ýÃýeþlþ1þ5þþþtýtýüüƒûzûüüòüäüTþHþ ÿÿƒÿ€ÿff„‚>?¡¤[YÞÙ:4«©äá™’·³  ½º¨¤TN3-Ž‹33[YIC¶±ýü20¿ÿ¼ÿœ›GFSTáÿãÿÊÿÊÿnÿlÿÿÿuþuþ‘þ”þ]þcþý–ýùüÿü ýýÝýâý¨þ©þÿÿ»²¯®¶¹ÈÇ<9]]ÇÿÊÿÓÿÔÿQP~zNKö÷ýâå*+ÆÆ13noùõÏÍÖÖ\ \ GIøûœœde–˜DEäçRR´°ôï¥ £ × Ø ïô’œ@Ga c ··-.}¼½64˜•if××íòÕÚ÷ùrÿnÿ*ÿ(ÿ­þ±þþþ;þ=þtÿoÿåܯ¨ ñïúùjiõïe^Ê È ª «   Æ Å ƒ Ï Ñ ! ! § ©   ¡ ˜ ¡ š á á  L E À ½   5 / ðìfiükl[[m n ë ð U \ ë ñ K P ô ú @AÑÒll¿¼µ²ŒŠ('ƒ‚))¸·ëé,,GJ69µ¶¯±ÖÜ£«ßæMRsyû'"&ŸšçÞTSËѼ¿ba¡ ÔÓÖÔæåœœ?D*2PV81° ¦ ) $ Ø × š™š  ž ´ ° š › U \ º ¿ ¾ à ± ¹ — ë ò U X . -    p n + ) e c _]VTò ð j d D ? LK:;ÃÄ  ¬­vwíóPXéìÿ~ x  B > Ÿ ž PT–™ããÑΜ–ñïIL.1ÝßUTPN§«ÛâôøÓÕnm87Ô×ôù¡£!&#ml\\*&¸±ÊÖ’("›—¤¡0*}téå ©¬PS¢§Y^.1œœ®¬·¸ÌËÔË •NIÏÏÜÚŒ"ÍÒTV•˜ùùÇÅÀ¾ÅÄNKyxPR!$"%ÈÌÃǰ®^\…~,+eb—“77BB»¾22Œ=?@C÷òúõihjlÞàÞà—›XX½ º ½ µ ‰›š« ¬ ž ™ ˜ ‘ "  M M I H ¥ ¡ ± « ] W i f `[LD Ÿ¤/4ÛÜ»¼¹¿‡‹ij±´CI·¸lhzz½»c`ðõ™š('ùö®¨ÛÙ¬±ÏÔ§ÿªÿ|ÿ}ÿüþúþ‹þ‰þœþ—þ7þ1þyþxþ£ÿ¥ÿ=::4UÿTÿ#&**GH––xsC={{{~²³:6ôð/-À½,'–”,.üþÿ þ þ©þ¤þRÿMÿigMO36Y[ÜÚ„^XYWxzDC  > ? ò ñ 3 0 › ÀDz¹øþüÿù÷öõ…ˆŒ½Àÿ§§xvõõZ]»ºÛÒ]T,/|ƒ¨¬º½!¬­}:=OK­¥úö—–((fgÄÈip)-ÝÞ/0jkº¼òôëíÞß  vtPþRþsýwý·û»ûÉúÆúŽûŠûÔûÖû>ûBûWúXú/ú-úÏúÍúúú ù ù?ú:úRúLú7ù6ù(ù(ù‘úúÔûËûvýný~ÿxÿŸ—ýäáþso¯®Š‹·ÿ»ÿHþKþâüäüxü{ü½ýÀýåþæþ¥þ¥þ$þ&þ—ÿ˜ÿÛÚåè]]wsïéXQZUªª\a`f˜œÜàØØ+)mþkþ'ý$ýýýMýIýèýëýäýëýïüôüüüèûèû¨û©ûúúúúAúCúwùwù’ùŒùoùgùúúûû û û–û–û û¡û}ú|ú¤ù¢ùøøÁöÄööŒöÒöÈöÁö½ö9÷>÷’øœøãøêøÍøÏø‡÷ˆ÷ööQöVöèöðöø øð÷ð÷’øøÀù½ùrøvøúõþõ±ô²ô`ôaôõ‘õøõùõûõûõööL÷N÷Ì÷Ï÷‰÷Œ÷A÷E÷÷÷È÷Æ÷š÷•÷Ó÷Ó÷”ø˜ø)ù(ùäøÞøjùfù’ù“ù@úFú‘û”û>û=ûîùîù ùùiømø—÷÷/ø4ø1ù3ùÈúÊúWü[üvüuüŒü‡üÐûÏû{ú{úÙùÖù7ú1úÀú·úPúIúqùrù˜÷Ÿ÷ ÷÷ƒö‰ö:öBöö€öyöyöBöDö›õ›õ¡õ õõõoõnõwõvõ¦õ¦õ©ö«öJøMøÉøÌø~úúëûæû!üüJüJü³üµü‡ü‰üüüÆûÌûú”úëùíùùùPùSù*ù,ù)ø&øV÷U÷ºõ¼õŒõŽõ.ö/ö˜ö›ö}ööiöjö4ö7ö³ö·ö4ø6ø&ù)ù9ú9úóúìú7ü1üWþZþXÿ^ÿVÿYÿMÿOÿPþRþ.ý0ýüü}ûyû‹û‚ûMûJû¬û¯ûëüðüáýäýšÿ™ÿ!**TVôøØÝ+,LKªÿ«ÿlþlþcþaþ™þšþOþPþfýhýýýÙüÞügýlýºý½ýÅýÂýþþUþSþÑþÔþ07úÿ;@ÎÓžžijþÿž˜qiokÁÀ+*LOKO‹‹VRmlç鬬WUqq”˜ðóóí±­SR;<Œ&*¨®‹~}ùöæâšŸ49OV ìÿóÿúþùþäýÜý8ý2ýJýEýý ýŒüˆü:ü:üôúôúÁù¾ùÆøÆøÃ÷Æ÷iömövõ}õ]õcõ¨ö«ö¨ø¨øƒ÷‚÷xõuõõõ&õ,õöŠöö÷û÷ƒù…ùÝúàúkûlûíüëü–þ”þ§þ¤þ"þþVýVý3ý8ý®ý´ýCþCþêþèþjÿlÿ š™GDÿþ,-­³! >C—™qtŒ”–'+×Ùç쬱AIÎÖ  CBÿ#LGþKEõîrlLIa`¶ÿµÿjÿmÿåþíþšþ¢þtÿuÿ><ig²²éé^[YV€rsžžMMJKêëö÷®±-2«°ÒÔSWKÿQÿkÿhÿ7*ñê+-=DÞåûÿþÿžÿþ€=@ÞåþDH#%ÁÄ»¹TT¢¦ˆŽ´·%%×ÕMK¼ÿ»ÿ:þ=þ3ý:ýžü§üåüìüCýEýÍýÌýÚþØþnnuw¦¥%$AAãâôð^Zþ-+ úøº¸ëè CB;DíôâãIEûùIK[\ÇÇSTyy¯±^aïí땚¦ªvz 76uo þ*)ìíVYäè]\utOO)*))67áâÂÄZ[š›~{þùÜÖ.)‰† …ãárt`b%$’ƒÌпÁD?ƾ÷ôÀÄ«±…FFåÿæÿ%ÿ&ÿ´þ±þ\þWþÞþÛþ¶þ²þáþÜþØÿÙÿ!}ÿ{ÿeÿbÿÐÒÖÑ' üú:;56FÿFÿHþIþÏüÏü¬û¨ûœû–û“ûû+ü(üÂü¾ü÷üóüÌýÈý%ÿ!ÿ! ýÿýÿCÿ@ÿ:þ;þeýjý¾ý¿ý@þ?þbþbþßþÞþ%ÿ"ÿÿÿÿ|ÿ¨ÿ¨ÿÿÿ$ÿÿÅÿ¿ÿ$ÜÛ‹¢¥©®Z] |uø÷ÑÖäàÈÂÅÀD<tÿpÿûþûþ°ÿ¯ÿ¯ÿ¬ÿTÿQÿƒÿ}ÿÿŠÿãþãþâþæþÿÿVÿ[ÿÿÿØþßþ¼þÀþQþOþñýîý¦ý£ýwþtþÛýÛýâüäü“ý’ýƒý€ý)ý(ýmükü.û)ûúúGùFù£ù£ù|ú|ú_ú]úúûùÿøûøð÷ð÷†ø‡ø«ø­øPùOùÀú½ú¡û¡ûüügûhûEûAû6û.û=û3û‘ûˆûÞûÛûàüâü”ý–ý¶ý¶ýýýùüýü%þ+þ þþ›ýŸýÃýÅý þ þAþFþ–þþ©þ¯þ™þŸþwsda$#((?@PR¸¹¯¯0.XZðö…‹tvij»½uyŠ‹àß ~v ŽŽ?>gf&$½ÿ¸ÿhÿ`ÿ>ÿ7ÿ1ÿ,ÿLÿFÿrÿnÿ76™šÞÝmj<?ÎÐ.*-(‚|áÜîîüýEB»ÿ¶ÿÿÿ÷þ÷þ±þ±þ×ýÓýºü¶ü}üwü5ü.üºûµûpûmû§û©û'ü.ü¤ü­ü›ý£ýáýéýÜýãýVý[ýTüUüüü¯û¯û#ü'üCüJükûlûû ûDûDûöúöú•ú–úÅúÈúkúlúûû1ü-ü©ü«üÊüÏü§ü¦üJüGütüuü¯ü¯üðûñû²û³ûÕûÙûIûOûÌúÒúû‡ûûûü$ü1üüûüHûEû¥û ûúû÷ûÆüÀüZýSýbý\ýDþ@þëþéþ¿ÿ¾ÿÇÿÆÿ§þ§þžý¡ýùüúütüuüVûWû™úšú@ú?úaú_úÒúÑúû ûnûkûCûEûøúÿú¨ú°úgúmú!ú&úÞùâù ù¢ùÆùÉùÎùÐù ú ú¥ú ú˜ú“ú•úúØúÓú‘úúùù7ø9øTøSøÉøÉø~øøÞ÷Û÷¿÷À÷3÷8÷röuö$õ%õÛôàô¾õÃõöõöõFõCõ<ô>ôîóðó«ô«ôlölöø øqùuùnúnúaú^úÃú¾úîûçûàüÞü®ýµýDÿNÿàꙡƒ‡rvckÎÔÕÿØÿŠÿŒÿ.ÿ-ÿáþàþ³þµþæýçýþþ–þ•þÍÿÑÿêìûúžœMKøõûû»¹ÿü˜—ËÍåçõùGNçíCDjkììxvž¡-2†Š[`±¹ºÄøùýļB?bg{€gh"$ÆÊ®¯20ppáâ-1ADææ œ.)¼¹¤¤rn6 1 û ÷ ( % ¸ ´ ¡ ž b c éïÑ Õ   %&ÝÝ´·^a!#>>ÀÀa_ùò‘ˆkg“Žnlwy<>ÊÉ’ŽÕÐØÔ¦ ¤ ð í Ñ Í Í Î Ô Ù æ ì + 0   M M Ê É  þ  l q ö ü 3 = X c „ … õ ï ² ¯   µ ° g d [YÌÈgcwt þþsr}|MO-/sreaXW¸¹ÃÀnkš™¸ºGHÐÒ‰‹lkÁÀËËii±³‰ˆäßËÄWT ýù-(žÎÓ©­‚âÝG= ¨«44Å¿À»šahâÞ¤¦Ž’¢¦ ÌÍòñÐÍ[ [ î ó H M } ~ ï ò › . ) ¿º°¯ÁÅæê‹‰>8HD40¥£áÞ†jb©¦XYBGafKN9='+@GÝ☗¤£*,"'š›ëê««Ê̱°ùø~|qp1-²¯èçeeBGêï—šÑÐWTÅź½°³çèÍÍËφ‰caeÿgÿªþ®þáýäýÖýÓýÁý¿ýxýxý:ü;üxûyûbûdûQûPûÃû¾ûÁü½ü¦ý§ý.þ0þþ|þJþ@þüýóý}ýwýŒý‚ý;þ4þüþüþ‰ÿŒÿ6ÿ8ÿJþKþýýoýlýNýJýýýäüÝüÆüÂü ýýfý_ýýýƒüü¹üµüzýwý’ýŽýŽýŒý„þ‰þÿÿ`ÿbÿyÿwÿ'ÿ"ÿmÿeÿ-ÿ&ÿ¶þ°þUþRþþþöþöþbÿbÿÏÿÑÿ¶ÿ»ÿÄÿÊÿ³ÿ¸ÿgi‹40œÿÿ”•ÃÄ/1:>ãä+'ÙÖ-.wzw{IÿLÿ]þ]þ¯ý®ýSþRþGÿDÿ‘ŽÏË53WV#!ÌÉ_\•”£¥¶º'%›˜óøCFTP¿ºª¨­®?@vvkjº¹hgáßÊÉÿlj ÒÿÒÿ!ÿ#ÿDþGþµý·ýêýìýSýZýý!ý–üžü&ü-üIüLü¢üŸüòüëü™ü‘ü2ý,ýtýsýýŽýõüôü5ü2ü¥û¢ûšú—ú×ù×ùßùÜùùùù&ù,ù3ùùùùùùù¤ù¡ùéùæùÛùÙùÉùÉùýùÿùFúHú>úAúüùúúúúúúúÌùÑùÛùáù±ùµùùù\ø\øGøHø*ø*ø“÷•÷r÷v÷áöãödöeöDöDö ÷÷ ÷÷ôöôö†ö‡öõõùõˆõ‹õ„ôô@ô9ô`ô]ôMôOôøóûóóóóóŠó‚ópójó ô ôöôøôõ õÉõÌõéöãöøøøŽøŽø‘ø"ø øØ÷Ö÷ˆ÷Œ÷áöäöÞöØö-÷&÷Ÿ÷÷ï÷ï÷øøzøzøùùùù3ù-ù„ù€ù‹ùŠù„ù…ù…ù„ùñùïùÇúÅúYûSûMúEúmùiùèøéø%ø'ø¾÷¾÷aøaøSùTùúúWú]úÛùåù\ùgùø„ø°÷¯÷K÷J÷ÜöàöíõóõÁõÂõHõFõõõööãõãõŒöö ÷ ÷aøcøúú¼úºúûû.û,û‘û‹ûÚûÑû>ü6üªü§üÀü¿üý~ýôýõý6þ9þÿÿqÿoÿ±ÿ­ÿUÿOÿ—þ•þ2þ3þïþóþpx^c55ecOQ—™ÝÝhiýìñ zy;8pÿpÿþƒþ—þ˜þ‡ÿ…ÿ›™àâuxÁ ×ÓJE  ¹¸¾½gjÁÂ¥£11ÿ’‘ŠHCÆÈqtòó10_^&'YZsrDB£ ÆÄËÌxr 7=pv—š\^X]ÈÐ|€ÍÊ©¥gezuóï÷÷[\ÊÈœžÓÕ  {yÏÐTUDF"$ÃÂ;7»ºå蛜nnllÄÅ+(P I 6 5   ´ µ ð ï Ä Á ¼ · œ — » · ( ' Î Ì 1 2 ( ) x y ü õ Ñ Ë ¤ ¢ æ ç ywÅÅþÌÍ60úóòí:9· ¶ C D Y Z - ) “ Ž ¦ ¢ > = ‡ ‡ < = ‡†àß5 7 š ˜ ˆ ‚ Ï É B @ P S t y    ^ a ² ³ ø ù Ç Ê z | „ … ¤ § ¥ ¤ ' $ _ _ ? ? X W Z Y X Y œ ¯ ± © ­   ¾À~ € ” “ À ½ Ë Ì Ž ’ E D ¨ ¥ ù ü Ì Ì ‚ ~ * ' ÚÛ¬¬SRONTT¡¤ùý) 0 ˜Ÿ¿Ã’Š ³º6:VVÓÐtpÐËTMóîa`WV# C@gh›š¬¨ ¥ŸÞ×ÙÖëéebœ˜76ÀÀYYöø  ¶µ££ikŸŸ~öú¿ÂÎÌ88MQ16‹™&%dd¹¹ce dixxþ _XBB°¶ÄÉgh/'ÆÀEG35 öñª©‰‹   ²±úòéàÍÉ¿¾yw))‚Ùݧ«?Fÿb^'#¾¼^_³¶pt`_NKÍÎ)-!Å¿:5öòîÿîÿÿ‘ÿvÿ|ÿyÿ~ÿHG¿¸ÊÈÐÖ(-yÿyÿsÿpÿØÿÕÿ„ÿ„ÿÿÿÓþØþÿ ÿÿ ÿ(ÿ+ÿ¬ÿªÿûÿúÿ¹ÿºÿ|ÿ{ÿrÿqÿ0ÿ1ÿÿÿÃÿÅÿ>ÿAÿUþUþýý/ý1ýeýdýbý_ý³ý­ýý–ýtýoý³ý¯ýšý—ýýýzüzü;ü<üîûðûèûéû¡ûû²û­û_üYüCý>ýSþSþ ÿÿWÿ^ÿóÿ÷ÿY]·ÿ¼ÿÃþÅþÃýÄýýýüüûû–ú•úòùôù¬ù±ù›ùùnùnùù€ùù‰ùöùñùFúFúýùú®ù¸ùúú\ú\úkúoúmúpú%ú&úªù¨ù0ù3ù ùùÃøÇøêøïøGùKùnùmùŠùˆù„ù„ùuùxùùøûø±ø¯øíøêøsùtù úúŒú’ú°ú±úžúšú$ûûûû=ûBûèûìûüü¾ü¿ü–ü˜üçüçü‹üŠü ü"üüüÇûÈûûûúúÝùßù|ú~ú°û³û=ü@üÛûÞû6ü8üýýý‹ýâüÜü¹û´ûrûsûSûUûüü¢ü›ü"ýýýýýý‰ýýAýGý¡ü§ü‘û•û@û?û`ûbûâûçû‘üüòüîü]ýYýéýäýWþUþ—þ˜þÂþÃþ›þšþÓýÑý ý ýÉüÈü_ü[ükûiû?ûAûkûmûQûRûµû²û§û£ûMûIûTûQû4û-ûìúçú¤ú¥ú2ú4úþùÿù.ú/ú°ú±ú½ú¼úÛúÙúêúæúûþúûûçúæú–úšúeúnú¶úºúûþú%û!ûÜúÜúªú¬ú“ú”ú‰ú„úÎúÌúóúöúûû#û"ûûû£ûûü üdüdüfücü­ûªûãúäú[ú\ú ûûüûøûýý3þ:þôþûþgÿfÿ!ÿÿ3ÿ-ÿ±ÿ®ÿëÿêÿ{}—š¬ª_]BBÇÉ &  …€SSfh$'2759+.ïÿïÿèÿäÿ¥ÿ¨ÿ`ÿbÿ_ÿ]ÿ›ÿ—ÿ;ÿ:ÿ6þ6þšý—ý^ýZýãýáý'þ*þ2þ8þ þþÞýâýTþVþºþ·þæþâþ ÿ ÿfÿ`ÿ²ÿ®ÿäÿãÿãÿâÿ'(?Búÿýÿ¬ÿ«ÿÚþØþþþþþDþFþ8þ:þ^þ^þ–þ“þøþöþLÿRÿ8ÿ>ÿÿÿÿ ÿ_ÿeÿÿ&ÿÙþÞþ¯þ±þ3þ.þ)þ%þýýÀüÂüúüûüÈüÍüBüFüôûóû$ü$ü±ü³üŸüüýùü^ýWýäüãüáüäüèüéüÓüÒüÊüÉüküoü¼üÃü«ü­ü¯ü®ü ý ýfýbý&þ þñþîþ˜ÿ—ÿÌÿËÿ<8ëÿåÿ¹ÿ·ÿ$)nvËÐýú¤¡ßÿÝÿ›ÿšÿÀÿ¾ÿñþíþ¢þšþÚþØþGÿJÿƒ„µ±ILÕÔ>6;4MNšŸÉÍÖÛÒÙëô'/X^qsßÞãßifTT>A––”Ž™’OQjq¨­;<®­|~öÿõÿäÿãÿ0.yŸš­«éæHEec98æéÆÊx|÷újj ¡¤«ÓÚÐÕ«ªNLý¢¥º½ÿþ<7•“ññ 6;  æãPP©©´±€€nq=<ƒ~¸´_a¦¬ÎÍæãwu•–efpq32‚el.0”“@=ãÿàÿ 22ÿÿ! Œhl99²®²­öù&--0¡¡QP­®6;.1‰‡¼¼ÐÔ¦¨³³¤¤ff¾ÿ¾ÿ•ÿ”ÿ6ÿ6ÿÎþÎþˆþ‰þÍþÏþ¨þ¨þ~þyþhþdþÀþ¼þ&ÿ%ÿþþÿ§þ§þÓþÑþÿ…ÿ÷ÿýÿIQøÿéÿéÿJG00„ÿ„ÿŠÿŠÿý&ÔÌøÿòÿßþÛþóýñýuýtýÌýÎýEþHþaþcþéþéþÏÿÍÿµÿºÿ#ÿ#ÿwþxþÐýÕýJýMý4ý1ýÆýÀý*þ%þïýòýTýYý7ý8ýƒýýÙý×ý´ý®ýSýKýIýJýÈýÊý9þ3þgþ`þ;þ<þ»ýÁý<ý>ýìüêüýý9ý>ýþüý(ý$ý¢ýýÜýÜý5þ<þþþÍýÓýÌýÎýþþþþLþKþþ{þõýñýýýü«ü¥üýý&ý*ýñüôü”ü”üGüHü)ü)üü ü{û‚û}ûû¦û¥û¦û¥ûëûëûzü}ü#ý&ý=ý;ýRýPý ý ýýýÁüÂü€üüIüGü üükügü)ü(üÒûÒûÙûÛûNüNüFüEüGüFüLüIüïûêûü üáûÜûãûàûwüxüRýUýþ!þ°þ´þÎþÎþ‡þ„þ.ÿ'ÿÌÿÁÿ¦ÿœÿ_ÿXÿíþëþ×þÛþXþ\þßýßý¶ý¹ý[þ\þ•ÿ–ÿúÿüÿŸ¢&+éì…„87<@-37:˜š  )(®­_ZàÖwp§«MMüû”•!$NN‹YUOMÅÁYTǤ¡±­30SU éïľGC££¦©…†xv7501-*ýø:3šÇÊTXY[05¦°)?F#$QQ>?¿¿Ø×HEæê³ ¼ & , V W Z W C C 1 5  e h L N Á Ä d h , - ) ' G D ˜ ˜ « ± Y d J O * ) s p Ä Â   [ U œ ˜ á ä   U X 1 1 Ç Ã a \  þ š — ü ø i i   ¡ œ Ü Ù ÿ ÿ 3 3   « §   æïùû‡€(?:ôòÕÔ1/okííßÝèäÄÊ-/ ”ŽWSÖÙ17TTØÚÎÑJH{yHLÃÈ`^úõ¡™=4öî÷õ)(VT""""  WYÈÈ_fÀÈÿþJG KP¬­]X­©Œˆ…„ÃÃãá»·8 4 y x ý û \ X 9 7 í ð Ý ß   î î K R ¦ ® $ ) » º Ž Ù Þ    Š Œ ÷ûµºùÿþ"okÖÖ1 . jgìî—Ùä!'˜“ ;7baøõ>:ˆ…¯«¢¬ª§¨¡¦›¡suQSåë* / ÛÝNJSQòð–’$ ¿Àúý  ¨¨NQ>C7>18ˆ—™fdQJ6-©¢êæÙÙ- / N Q Q R › ú õ ä Ý Ô Ð ä ã 1 / ž™:3â߇ˆ,0# ®¸Ubpxpsƒ„XZ[^<=ÌÎÁÁ~EC½¿pv.4 EB93"IFtt}}QU34š—crossfire-client-1.75.3/sounds/potion.ogg000644 001751 001751 00000045356 14165625676 021322 0ustar00kevinzkevinz000000 000000 OggSÂóúeóTüvorbisD¬q¸OggSÂóúeŒt?Dÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‘vorbis4Xiph.Org libVorbis I 20200704 (Reducing Environment)vorbis)BCV1L Å€ÐU`$)“fI)¥”¡(y˜”HI)¥”Å0‰˜”‰ÅcŒ1ÆcŒ1ÆcŒ 4d€( Ž£æIjÎ9g'Žr 9iN8§ ŠQà9 Âõ&cn¦´¦knÎ)% Y@H!…RH!…bˆ!†bˆ!‡rÈ!§œr *¨ ‚ 2È ƒL2餓N:騣Ž:ê(´ÐB -´ÒJL1ÕVc®½]|sÎ9çœsÎ9çœsÎ BCV BdB!…Rˆ)¦˜r 2È€ÐU €G‘I±˱ÍÑ$Oò,Q5Ñ3ESTMUUUUu]Wve×vu×v}Y˜…[¸}Y¸…[Ø…]÷…a†a†a†aø}ß÷}ß÷} 4d  #9–ã)¢"¢â9¢„†¬d ’")’£I¦fj®i›¶h«¶m˲,˲ „†¬ iš¦iš¦iš¦iš¦iš¦iš¦išfY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY@hÈ*@@ÇqÇq$ER$Çr, YÈ@R,År4Gs4Çs<Çs@BDFHJLNP@OggSÀ(Âóúe˜ɪ&NHZPQÿGÿTSXVDBPYÿ=EECBEBGRTUÿVÿAÿ?ÿIÿG\uèTQR.J¨ïÀÙzQ†€Í(€Ë­°¹¡W¼Zyɯ_?gç©?õ«vvï«ÙgvçóÔ?÷ߨ}ÁŸ-»+‹û²\$lLý ’ˆ õÃ(A§‘û>eÅ$0'áCA¾}&j§Ÿ¿µQjÄ|YÙ;jøñ¦ÿP¾ç§Ø9ËÝÌþÛ.‘¢*2P±0‹‘ļ-å‡~EÊÒw(ÞXã!1x—€¹^“íå ²´h¥¸W•²TQ4ÊÜýñ§zÏ7qíÓ›SVÞÍë{5Õ˜ÿü©ZQî̙׺[Ø3NpèÔÌÓųS4uÒ8Žt½ÏfÓÔqã8òù=“Ÿ[7#È$ £¤"F¨*ˆ¢TonnŠSÚýà0¶QªUE”W…ë0àŒì(m©‰®–BK+1²›%ù¤buCÛ‰Íú"²JÍꆶ›õƒÈª·Ÿ,²ЄaÚªaŠm¦ˆF™ŒÀÒ­"X£ˆE#W‡¢£V*²V*ªµ3ý+ªj€Q—Z9UŲWíðO­‚´’ªŠ9d¯6šéŸZ…ÐôÈ"£¶H)##cÓ‘øGäGŠY  ¯®—€™I ÔÒ"Z¥—f,Ù4rIqC † áaCIXmS- Û#V ëù`¨,¢*Ö¨ŠªC[T…P‹Ú âe™i$XT±hƒÚÆXÑŠ1 Ê"ZWg@WK`oÿSɳ:´  ‡z$…e8 Gd—ÙTi#™ %™1b½V¯*F¥Ëضm™ÈzÑ Ø6` ƪNW@ mË2&–1:DžÏo)¢„ !2À”±,صXª(ZVYÄbqL+Á^!€‚ ¢ˆ™ÕºµQ¢ªb‚Ê º«läÈÉ ° 9Þ°° :í@Ï[ؽo ©žW€ÖY…u‰Ì~´Uøþ¹ºÎ ~VqÛC)—pþ¹º&@÷ ÐÏÔÇæd駈ꘉTUÊu$IQš2eR³86X¬vjg"ö"T~þè€ Á'%ȵզ–T2d°ª–V2o¡,ˆuØ–e…²<%Eq¨,¬[ˆ1@ àÊ%¢/ :†…E›¸®L¶Ä`E«ØD­³êCJr`Í˲¤MÔ+Å ”Ñ]•Ó¸2ïËR‡€eÜ ô(Ôº ƒzQT±(”e€DЫXi´…*€!í80$m@D(%¨ªÙJD׊Düá^ÝþŽ9&e°d‘T–»`ʇÃY|1Žãïž2Kà¾leýþe,k"9nÙh˜>l¢0r°ø5ÆÂ›58S:£Í¤¢Dœ (ÝW+ä@tVœ!ÖÿqZ±vV\‡x[ù¦XO B—š35K­²q£ÂY¨1gÀj½Z8Ä¢Uµêˆ^‘Ž$¬ )¢Qu­V‚þT÷{S^ þ-ãßzŠj¤ PŒK#ÆZÑØˆíxZ„`¥iD¼j±‹³·G0º²€‹!8¦)tFAµŠœóų°S ²Õ˜û@ñ¨yÈ­( k¼ª@2Äɯɩ²Ç¤¼8CäÑT"áá§mWsÅVÄtZa6i‹ó(DuZa6)sþB,•`cÂZ²ˆð©ÊUŒh E#ˆµX«%"îmåeT—•¤•j¸»éæÓ«`åµ÷ >Õ{ág„F¡" ?¿  à…†0ü˜¿‘içØ°¬„5—¨€™ª%f(„ù`8¬‚­F4¶ C‡Å(ËJ ‚VÚb¯Y-¨*r—ÛYKt{Ás2Ùi29Å®&ä?Ê¥Ì?3•¦ÅÉ)t-eþ‘.mÿ32iZúTk2T !‰ˆ}Š¥ªº󙚚Z0»$“€„ÌY„+ Öˆ5¢`EÀ䉈 pD$q+¶°ÑÂÞ ÓЄm˜vX Xˆ€±ET#hQ-ªVÆö ¨ènBÒ5K ¢S,Bº½-³C,B„¦ ŒÜ!¡0kH…dX,”­ÝQ j0üÏýè"´$â4E–(Žl´yûG0`9ƒUTÅ¢U¬QE·F«Ñ©h­F«We s€Ô’‡ˆ6ï‹-Û3]¦˜äÀ˜hs8 Ô% eâÿ<‚æyÜô×¶öÝq)À1€Á†`u'À~bY&²ý­È ¡ k³Ñ€,êñ8? |>µÃÙ­‹ºG¤§dçS;ÌÝyÐöë©ñà:L*ˆ0‘(kt*`sóUC!µÛ´V!€V5:¥†‡ê#ÇÃßdJ©Õ»÷ËZQ.¡¯Ì(:¹âtnQ,áàp(Ѝ(¡ü ŒX«€B/1Vhk,·a±­€ Îpî3‡oï‹,&}ŽñÀ©=:Þ¡²°ü >¼¼û 2ÅÉh7ÀtfÂ⾎Fô¥Ø­ˆÈþHô‘¡-®´¢éG ÀŠy,J˪½¶ó@{1Zþ¢šëÔ´»üd°¤Ã’Ð@@Š éø1Z±ˆ¬»æ7+[eªC¬c7$“)c]6Ca\6 ¿¶&/Š—ÍÂÓÛÖ"Âþ~ë©›‰”Ö‰d˜;ç jDÄ¢d8ȯ­‘‘1Ü©ÑÑ-X^ F*"äX$ à›I¦Ø þèiŠíqøȹÎ)hJ ,Ê‘ kÅ4–õÒÞ´£=Et5×Bötóž š4F1ÀF6I,.ýCu3§“Š0—þY¼\íPìÀ¥8Å@àð8LÕ‹*£ QÆ1b•ÍÄA‘ÃjÖ“ ߀, «¢h\6áì+º•Òî³²‰¬~2ZÕx6ea ²ÉíBBqÕê¶Nn!†ñÚBU“Zk4µIJ+ª¬­h%«ù¾Åòô‘þˆ@’¾·@òÉÄg•&l6ÅÕ!~>¿„7›âê?ë7¿@˜ú QIÇ@¤…äJ¤ð*"«ŠFTUËÕ™@fÁ´Ñª˜È¤²Fßâìè§îÙ AD­§¨ŠZÝZ, &°Úç=üÒü5‰ôtµ¬öÙnôf˜ÀÐ~XB_¾Õ²ÆZ‹MÄÒ´º”ÂÌ*Š-"£ÌÑŠkTÑT1fðšjͺt®PÞz˜ ÌZº\Z´ç¾a’õ0˜½t1ÑôÕ7šÄü  Bºà½øá¶õj«ªZR‚ÉÌ$€ÑH52‚X ‹ÕjÚŠk: †ˆkX1UÁÄלÁÃr!Èçð¤8–åÛ¶°baXÍl’ÅJ«= @¶h5ªb± ƈL+' 2ÒЃˆß&'¹l°#\VUzEE–‘B¶œEÖ®íƒ1È ÅB¬2 -y±–éÕˆP` 2,Ì‚gQ@aØ"-±²B,èb("¥"…Ë(TSE H,pCæ¦aƒ…i˜¦3µ[à.¥¨©J8xØXÇXÌÂ1ðççaà¼(Vd A a ^YOæmU£udXâÀ€EŒ%™Å@qQ1€‹ë1‚D¿x[š¿wdBþyÄÓ%†§E”®ŸE:Ñ(°=!•¯¤ÝÛ} wˆok&òª*Å‹Q.3“`' XÄÞšŸÚÄUÖ,l²ÚbÅtK ëj‘ÉÒšUÓĪˆ‚¥ l!6©…‰AHŠˆ"K!õ"Qb”JĤ‰Ê£ñZOAƒ AH„²#âüó^¨‹¥^¡*4X¡,Rv2=ªCöŒ´A†´!”„Æ aì@–p‹¡M¡Õ+¬H„ RYP`€0»=0¨(CÔJ;£Ð¥/e –EbІŽK1…ÔêÚ¢˜%2‘A­„UyÓ2@=f¶gðc0xްõ~ LÁ`-`s ÷!k€6@(/Æžß×ÉØ¬Ñ{ÉO³>J>YÄæŒ“lJ=L“Eêö(ŤÄéøUYÍ2ëd‘v_ßðU‘©™¤]fÉL€1Hï¸N F+d²ÇÌhd™w«¹]æË1Æ(+bhY7Môf= mh»šEZQäHÇ^ªÊ`<‘ha1@cPŒ,´šïXj¥ðDfä¹µ¾ßr‰²ˆÊ^sA ° zÓÈ€(„‚À²9È"Ȩ-§°P†¦*¡F øžVp «€„°bƒޱ1Ô¡ší®°OqDt/P*£Oxp_lr­I’• `HùØtoüƒ}~±É0MŸŸÆÔ} Ôžû2-¨òõ\=ãYIOÀ¿z(@ÙÈ« ¬e£¼8²§t6þÝtö^ µd¾œií›Äzm†>Y$üÙº&§:žÌ™E˜¶ îêv+L*_ÉfŸÝ·¾N¼xñѪªtâÒN˜™$Üh˜ª‚w´¸ v¦š†9¶S--ÆN±bÕªUÆdÂÀÌNÚmÛ¤¢¦jaM³Ð0챉ÁYw°Å i £ QˆŠAÀ†±2i‹XA˜í‘l:FŠ6˲,¨íÒXR‹1#",•mžÄt$Ha!ªQ£¾,&)Ê"½UÁ Œˆ[Ru4¦0rH¤ÖßÃ_ ÊÅ‹DÁ`ƒ Sd¢24É`É£…N°5 òJ†ÌN`t>sÀÔøs†=ýÎx®þ¬3Àm=vÎû0|Þ-vqÖ‚…ÆŸb-@62 F.–ò¾P„1–Ap!1î×° ŠBÓ û]ÙØpB«íË€%€YÄf™Ü‡nHÇ“EêÖÖmr3ÜÊwb[m "ØêgÅ—öa¡ª’–,Æ,F@¨‰ b±51M‹ÚZMÔF ÈÌU[±Çb bˆ ¢ÃK{Ó´K  ´ì0U3¡*¢QB± €À²…ʈJGÈ]ãåyËy×€êÌñnOT‘ ¥A±,*fHÁªªØa"``A&ã’H9Fl‰¼†€ A€˜@ò؈ß'N°œË€%#‰°C"dÖ ­@•2A VÕJ½s…tDŒF7€ÐJDf„Õ©Ònaé¹´p3ÛÀ´cZÍ4Ô{þõp³swyXfí=×Ïî±—…€ c·3g켉HM Ò´¯—óŽÑ‰Oó Mâ»Ê¤3"«ô2ÐÜC¶°> }OggS@XÂóúeLîà#ÿLBEUVOLEFBPTÿAÿ*ÿ=ÿCÿIÿ>ÿGÿ@DOOLÿ3vXq &ð„ô\XD~6A 7¤ão€‰mmkm[›Š®…W S•L»Ä”“PA ¶ñÙŒ³¨=†-Ø©1»'4×d†ÌÓ ÈrB̈W»Ê µ´0¬ê&©–²(°¤²R*oL4c…¡X1[Q*ZEìB^0êqJØ(°01ˆêé¶ъAÀ¢ÅdL.:íž:× ÙÎôÌ ¥ì*Äj4$©+05ìH6ÈEŒ0V—Ba AW´R‘bP¨! zd¬˜›uA+2ØØHÙ ¼R3bÕ\²þa 0´+ÀSQÁÄ4• Àšé}8gær›éKvŠ~tÖL‘Éû©¯˜óé”mYÖÍŹö]9ÓÌò$ cl€ÅÀ Ú…{R9¡Ž—³Ù·M¦P¦FÀïê§d œÍþ¼3芸ÅJ/üyf¿¡uuëÖf)H„NÉpºº1d¿hlÁª@E *Y™Z—4 Š1Œ›3œm[´¯Rjø}$Ń“5ùeê uÈšøãú€Í˜ÙîR9V•ŒnÂXФ„ª ÓÈI‡j–;OØŠ®ÍcÊŒ' „ìŦ=—[îpH7Ãs«•w¤É_€ÍeÚ.ƒ' pŽ]ë#¢±NE¼,bŸKÕª©V–žT× üCš=k<"I2Vj+ ÂÕvF+Òj,ÄY¯ÄFˆXÆC{κ;6Ä&âLvïô©¥&ŵØY°´T ¬ë,:Áa¬ˆ°bÄVmÑhD”VD°_﹆ 0d²>ˆˆ’g´3’•êQŒrѦ<¶×zìŒrѪ<¶÷zÜö¶{,÷±},†&-ˆØø`Š@:²Ä4uVT±* ¨ V%ÍR' ÀGÙS,”f©^ ëL¤@%°.ÅRµ<ÖS¤ %¼s–µE$&³!`s³¢ª6Š© (Zl5µ°Ÿw› º `4ÚÌJV+`\ZuKi .5ÅZ!èK«n. Ä©¦X«se½ IærŒbm³FÄ¡ìüOoUçÔR+ª±E¬€Éj„… ¤F…½ëñ½-õ¥:&5*œ®Ç÷X³Õ P•$bÔ\ž †ˆ¨ª€hqÁ°›r––Êqh@Ð@Èdˆ±´¦à°l>Å.?÷í:„ŸoBÅY~î—«¤ž®>€@U *âPB¶•W/Lš¡ÄöŠÕ …2Pö4:Ã`u ’ lB‘…|ÊïÕ´´7¡ÈL>å÷ZJO[–õJB tX…€±VÁ*ŠVM™ú·*Æ ×R5ˆhŠHOWOug±ÃÛk½Z©VUB Ô­¯¬j…cÜ£÷—©„~RµÂ¶Õ£÷OS ]~€­‚ DÒNâëÊðVJ]ªÁ¢CÕa1ãXÅAPÑ«…Šv rÕ²Wµª çm[ç&ZIEþˆ0ÏÒ>Ýã«ZI~”£¥|:ã-ÄYþèõ"zË>bÎQ'6\…ªºbì2 [΂igV[ìm+FbÔ,<>‡O¤Ãqy”J“ƈ¥¥i·Nº®Ú¶°¢0`%{ÔèQvš¦Hî¶VBÒ2€EH ^1FŠ‹4V(‚0Ð(€µ¨ªÅ`‹$FÄ“Šª1ª¢Ø‚`DÕ©\ˆSc° …NF+…v»!ÈÈàh‚ÄØx°±-<d[w*Ä6X®f â@3MJ¯Tq Pq`¡P© …"§Ó€…ü¤€Ó)²”íŠ]82J ¥n-~UYTj,=€Ã syk€…CÀ¿ÒxÄÈHHÚfe.ƒ€öÔ/í ãÖÜU`Å(n PÊÉZÅõÏÒzÓmB ­Âr‹¶Q?ªíiAþ °ùTM Ú›®ª*EÌÌ M‘@”KhhFÊIfr·µ°bŠ1–­–ØjZµ0Õ& C ÜŠU+ƒj…;6a°!) þIåÚ­Ð=öêÞ¤ŸT®Þ ÑuV÷˜¸Š¾Ü˜¦‡”áë‡úª²bbÌ dbÁ׉:½æ˜ÕbŠaØg§Æ™ ¨‚Ðð¹T’/̰İnMÇŒÅ0ÆÂÒŠš X)µÈbAIÁ‚щq`„;P5wC°¢g®‡Ìïiƒ°5H›Œž ‚U}aJíRÉ(q Ù ,H´€‚H³ " †™‹ JØ`É0-؈FQUµV©QÕÊBi9ˆâÂ`°KmÑ „ƒ¦Gô‚ØŠ˜ˆ™líØ¶ª¦Uˆé±4Zp¢@ $€ÀPOWŒp.µÔ¿ Zïª5ûý§oŠ` ’‘W[íØ… ¡òh4rò#“À¿'G•ø9ë ‘2@À¾ÑÌÎ(Ta ßcD³³V¨aú p-ޑà†´6¤K»MaJ`µV«a1kÃfU'–alU“ ‚¸±„Rð„””„8ÃgÄ0,¬6Ùh£ªŠM– ž£,Š% B,0„a@5؆РFDDVFì&T(/³RiD sd$ÝêOFš2[kD#‡£‡¬uá¶°Û—*’æPÑ,­³4ÄòóÙh-SªŠÑ¢(6‚µ†Æ6€‚%„m#2ø€A6‘ðÂVßUO‚ @HÒÚ ±Þ‚|¾¡ „£%¤(:Xðj燾ª#D*ü³Û6Z øZÒɉÿl¼z‘±A&+ðŠlÛ€I°Z‹u¢£Ö©³Ð*Š""©?RÐbÙ (ÞÙäêÛŒÙܲD¼Î&Y—ØRfqË2ÞW€Ã´€u¦r4ÄGÅ»ÃZ-ÓÄÄbÌL”L ñ V×#O³ „剂ç•ð*¾³ÑšXXc K±ŽibŶ[X1Ä0MLµ*b‘"¦¨iìòa @A Ë•€)-zEDk0¨­-hUKГˆF¬æ¸ l­¢ŠmTÁ¶V Š"D`GY¶‚À!€Ü̈ 2€ V ȪLP$ ¨)X C]ÜnÑ€”´`@«± mÄÊ»MЀ1b‘ÂÈØÆÆô‡¨4Š!†6b «R¡¥XF ¬.# :B©Â@[¢.Ü=åA,Ʋ±ÈN±ld¬„+ˆ…í :ž9ï(` 2T©îòéÿ~Xo9¥•}x`¾©Tã”äÊ};›FM¸©Tã”äÊ};›FMøJRDMY*7 õÌTÓA¼øŽ²xŠ‚i1fff¡‰†&Ö¤–»Ú[Ô´·µ±ÃÓjª ˆ€X³ÌD-¬›fb™i” £, T[Ñ¡è[t*ƒb°UkɈ«ÖZ«"DD«Ÿòþ\ªÝE„Ôû  CA¤×¼.!PÌÀ@#2MƒM` „P¡ …„öcˆ H6¶$)0n°áWÑ#\ç\#òc0€“–î_EJF ä8 `dŒ€µŽCqjâ²»£ØÀ$@‹ø¨‹#8!uIûØyº«?õ"dY‚X â@‡¹Â¿Fß—@wk#Êø+§ Â’@^yTt‹u'8ƒ0Í•GE×B@úœA ˜æw‚¬•,3±˜EêdØRæ‡ö3•¶®33‹1“¨ ËXÉÖ¨©sZÒ†ÊcŠÙ‚­ªµªb-‚Ѝ9VF­¨¤eZ·ÁR@M+VTÅ´I§+ *Æ€­ˆQQB!4ª¢¸cÁ‹¢±XêÌÅŠj‹ˆP0R@ƒMcÒ'£(I¬ÄŸ†% Yd@x€€Øb`V( TmE*F1VF…UkP)AF‹ÖU Í|Q‚ðRàH¤ e h! I ´"alB„½bC@@Fjš–1¾kiýU˜$¼X „0AF]é»Én„¾þüþWg|þyÙ¡CH²…W§ÿ'iñ±XL#C)lÅx-—¯WdcÖW&zF ž¾@Ÿ}Åa´e4ùô$DŸ€ƒ60RÕ§¸m ‹#…PZ2‹QÌL@""›™Q€YM [K–ªRDqZFL—!„åžš],âQ3.dXèTØ$ŸZœýœ«ìÕÞÞ4QSÍQ*B%CïQ±ÈÒÂhH®(Æ(+`¾_•$ Pk`Y ¢×öàé±CÖ°U\ãz©Õê¨ÕEŒE,<§·iq`@àÔæÿNBàp*q9 Œ¬°ÀP  D–ƒU²,U± TÄ ’¤±WßÚ»R&*¢¬F• ¾žÊ´Ñ„x§,:'ÖW•h»$. @ÉH‹’è6íˇqW)¥ÿøʧ^òi*m«ä¾~ü,‘@ÇåIàÞsÙåůäï±8g)èš:†ôõÊY{ª-+þþzeÆžl¬Bƪ×ñôV™ + ‹€ó!6U‹H„^°¤ ìBˤ$³äb#$s…:N¤ „àNöè$uÎA†‡QU‡@õDfrŽ0õ{m¹…ðèÏC¶¢¢ˆ•Pt iA£k§ªªªª  ký(SAƒ‰:¨`¤VAŽÍ—HZEA«*Vm&Œ2=+PÚ/B|téÙ€}êýv/s‹6ê Å;´Ö(FшjU#‚5èÑȤb 6è [Æ:ˆZXŠdeAk#¬p)…)2<:ý5˜LÖ±«Ç¦?“Éú"vÙŸMØ!Œ€©XÕ‚(Ö¡j£ jªŠ¢5ˆ Œ\Ëôɘ Clã C/‹1 j&ˆÂÅår*Z˜Ì„-Ŷ[u€ñ&3a‹A±íR`üßÈÌ~^3€Ã‚TŽˆÅD^ÒR]&v™™I@¢ˆ€%QííÅT{[Ó°³3TÔ1Ô@D SJDå0"Bà󄸡„$ SmiE 1°PSÿŠCJ)ï?Y¦‰b)6‰u ,å2 A@ ¢ÑŠV[ðˆ#‹«„;´(«:IŒÛ¯»$|´ÊTàÛ#·Lwc•„ÝáATE ×Ò ‘BhítΆ6`Œ-FÑ„mŒ,¶Œ%ÆI!Y"‹å¨–À`C,‚—¢*À>¢PFçnÚ:·p(#4UÔD¼ä§{ ³)Ä5%øÉ ¤ù¬íâí¤WTÛo=±%ÙKÆ‘oyö)Ð6» ù)êGNÿׯ~;`•S÷ÐOggS€‰Âóúe‚tÇÆ#ÿ><@;;QNÿMÿPÿBÿ?ÿ$ÿGÿ?ÿ#ÿ@>;=G;?AQI¶¸är)…À¿¸$s1…Àÿ)3ŠÚJµ¨-"+eQeQFBÕÊ£ @-2©b$1hMUq¨ .11qÅĘ HN jĨ¨5ˆZQ+FŒ51Æ´5M‹ÕÎ4°¦(FÄ«‚¨ ±ª 5X„‚ ¶<é”à Žd!Xlj*¶ˆ`…  ¨@ˆbAÚXD6¡ ¦Ef†½Ñ…Â`F P¡ ³ª ®5 1€ˆ "I2È€ =Ƀ줖8D’GÙ/2!"€–D¢Œ `Ò«ÓÝ Ä+B˜oHMPMøû¸æ‘WØÑÀ&4šTš­Ü~óv[È#ƒ¼Ê ÄF&Þí9å–™ŽÓ |,KZrH&e BZ@´HŒ)À,»ytâX†­Nßgéi{8¯4ò|8GÂØØó'! ÜéÖ[”Â6Å b ‚ÕH·ÄY-7¡ÌgP ‡)Œå8Ýú©£M<!eÛ¬˜]¢÷D°ÛYåLðnY¡8çdƒEQA#TXñ´’Õúf#ªXmJdeG@íaØý0$â<»ˆÓA @Á=ªÍ*ÒfX{ÑQ‘ˆbƒ"kÈÐÈa+d‘±Tdº?5]åÒ–txˆL<úhc€þ£•öX Ñ¿êF’¬Œ1¥¨ka%°ˆ-/ML`áZŒ3 ‘IÉ‚ƒ!ž¸°•vgØe,wtã(}Û‚“‹;‡q”ޭèw"#‚-„‰Ì««Âßþ{«Z­ºXUmu¼hµ«¥ªUUÕZ .ñT(¬ÉPAF)Âi¡ÖÊB,šg8¤^=Ø;7Êå¥^õæOºÜY­- ècµÂC@Íõ–§&ö ¢b˜&€"ZUêô4¢¢ZUŒA)uìž+í¥9XÔSÚUÀpzI͘=—öKÛ`tI Í÷KûÅ£o€YiÙ¶éGÅi*³p]Y±TbÄb$D)-k“-µf`ïú¸¤ë´WÓ0,V[=ѱóaEÛ£<ʱj)VK1­YµfÕªX¢C§jDJ,¥¢JS!j¡†Fd4G|4¤‚1`D ¨uhEYêU‰$C‰PjƒYŒ\]Œ°´«+,Ää4ea­Á€,ƒ ¬@Ò7/$l@F„ĸ ²#$•%¦Ã¹O·A¹ª ÔIü‰œÊ’²4¡ 0 °7µˆZ& Œ%IâNh“±À¯Šs¦–1hÁVñe‚˜ž™ì„*&B$sj…†ÀÂ’ä@ŠÇY¼"³!_XŒ±E·ˆsœP}aåi»±Õæ–hÀ2_Û0Ñ5o܃0pdgž^Je~ê¥S»-ê1*¥27ަ«?«Ý8ð`OU'£ND­8aÖ¶®X˜@-EœM’Ò™áê®ZZ•ŽØr,5¬Z«ÃˆÕ VÔF±b‰Ö¬˜Ø ¢"‚ŠŠªÃäÓ^ÔgÝš´DAÔ Œ¬P:{E„¡eÓ›.&§ˆˆÁ äÀ¡…fÆ”Œ, œBXÕ8”eÀFf¹þFÒhŒ ¢Á‚ F•Ò²²:Ä"ƒ VhhlPC`ŠÅE#ããhJ2@hš›š$YKKݽ†‰"l\Ê\Œ ÈVØ‘e™¨3*aCÆ€¨(Œb0‘n2;΂Œ«°ˆˆMD€Á@ ŠÀ DQ °d €¢‹Èy€£Š`Ýuã$HZùf›|¥ÿx7Z  >JµË¶ÎÙà;g¥ÚqÛç,6ßÁ8óW€Ý/H%~8xñš8GUN«Í €E#…ñ›þ=RJ6ëå‡oŒÊ-u” mÅNÏáÆ¹f|úUê\L;2Y –YŽÉªˆh©.ä@Œ––6a£U 6$«¢€¨€ N±¶£ Ù Fà@cQlU4èD± Ì(²[_¤æµe"€pˆÄ؉آ1-Lì† CôŽåÔ"j‰XÒ£í y¾#µll#©•¡³­Ö†w€ÐôÒb9CqH -[aW™²B~´ÒB`޲oÄ-“5 ¯q$Q¬¥càþY?ÚÁE@—÷€@^‘À+lÉ´È %ž}Rd#0pÂ@>UÅ^<½‘œÁ'eþŒZô(ž^H6>)óW€=U*‡Öób´T·)Ä,ÆL J G‰—3!Ž SR†Â µS+ØÛ`Elõg5 Ó°®–VÕRE°D,Q«XZ3,U«Š€FÛ* ŠŒ/‹CÄZ‹R¨ZQÄFµX´¨Ú˜•Ò§1†€-%"XkG¡‘@Â^ŒBœ8’÷vêŠ_ïUYFe£Åk‹D³2‹Uªµ»)XXìfÜ”¡CÜ4…YAÐAAÔE¼‚X-„mkëÖ21"»h°Õ6RVJ]²¨EJLZƒPv o–À`“¢“%:bdƒÒ½O7ªYa2`iœ™$Ô Sü €´y3É@ø ù½âøˆ’ÀÛÛÆhëk.í†Ôbb.3»$ `Ó)ršJ 6>Î5›NñqCqŽÍÖ‹uliƒõÑ–ûFåY‡\÷t]³P÷J”*€,bE‹ ÕA¡ ¬ÂrdÁ•@ÁjQ ÂÈ„‘#3XXq+Œ d,cAb·3°a€…:LàÆRb–ˆ¬‚€!…9°ƒXXQ•¥RÛE©)) äÀ¨d p‘¥…t¤YX,ÆÅ§#Û²4 ‘a¸¨Þ{*CP€là XåX'„ ºy½šÜè’åêh)…@‡dX¥…W#FBl,”É“maÈZ ‘õ¯Ðf„=¼‚À˜K¿ ØõÑnuûžOG?s™kµ²@^û•w&ŠÞi”)E‚¤‚,ˆZ§Q¦ ’¢ š_"j2¢öY7\ñtee+Yš™™™d¨‹¤f°¥9 ;«š‹ ¦X·’c³«YhöVͱ ˆ¡b0âD©³@#ˆ"ÚªVõP£ ‚  ÐZÓƒÔadBâÆ Éa(áìêdZ² OZÃ4`-‰(þÖCE–†µöK„Œ„5¬²¥FŽÂ,%[9QޱᣰÚn# D/‹@¦ŒgRn,hŒ&`Œd ˜päñŠd`Fà±½ ¨³ /{ÏŸãŸ_?=97¼$¢1ŸÙ QC"#pl@úÄóü4Ûô ^î> ÃÏ 8‡Øÿ“A˜Ög @ ÔÐÙg @ BŸßÒÌfkâ+^¼¯ñ¨™¤iff# ˆRR ¨£i5;[«E° cÄ±á„ø|³4´€4]J-,L­ZÇŠ… ©¥uT(­¢3Ñ`WHÅ¥*¡–´F4ˆ¢§Ö5mKh)òjîÊ„Œ¥…@B ²ÛÃb…¬aˆ Ø«íö;Æh`L°ˆÄŒ$J$c¤H¶ÒA€0@wj¶´šÔ&€% X„¢l{±]AV5"n³èÝYX 0ˆ„C5+Ë@É6iZ¡l@ŒPÈgrk@Ò" “Î@çëJNšfŒ£E„{«t—ª!%²"»;*Ýòmæ² ƒí8Ïàkßý úŽZÌ}Ûq¿U™îæùSüò­ÜÑäI¹_0ì _í à!¸}ÃW&{Tà!xýv¬¬â‹8ì­ˆ(Œ¸¢…Ý{K¬Ñ‚G=Ž“úvÒ°Œ¶Ltìý®1Êâ°Jßïªaö OÖܬ2¥–œÁ„1HÁ1´ X5b –En™¢^¥u ¤i‹ÓœCYæ~M,îÊYQ(‹»2 $1+Ø[“E‰Í$F c]Á [DªÀ!ŠL­–%Â^lË m4Ç] !á¶”' ²›Œö2‡ÁB£ìœçZ–—½í~(3˜ ¢š­˜ ÖTQËj©Kh ‚+‚u`C݆Å,'pRRÖ7,.ìé®$£“¤íévGàŠv’öÈÆ4"‚Á-K´¶›ngÚ±,}z (+Ûµ§¹ès´n üñv6à\ ‰¼?ÞŽ „H"ÿHP2‰@-RĆ0:„)9D…µX)‘¥îEº¼.‘ÖØ¶ˆ„$òJ»9t»ˆÑD^i3‡n¯Î$49×SWFHÁDáØnÌh½l{V9W¡cÀÔeÅ%s­ fÌѦé-¨B‘Á tg× Ò‘a°te×àdd¨ôû}¶9€Å´ØÛšj-ªÆ¨ZÅuФФ¢IE hEjYSKµ®…jU©%HŒ-`5ƶªªÚUßšó-Œ:ieC‘TU©Uvü@e]µE‘ÁF–€9ö5·©RkU¬Ø±bÛ¥F«ÐªÞb1VtjTUyò© Æ¢UˆÒE#Y·°DiºOggS‰•ÂóúeÜõÉPLTXTPBSRQVZRMÿ:ÿBœ¡.´Ù+âbê)[.0¬^£g”u² !É1°FE6XƒÑ5­Ö T• X„C¢ƒ À ‚)ŠMà^¤gºvßßçÔ<ãT5à ˉx Ô€=–äþôÙŠ<@]Í´±­³*¢ˆ¢¥UcAÕ" ªÖ‚­(¨ZÑ¡‹XŒX·„ ìHÈÑTû\[Ñõ|î‰> SB²¡Nwf1öðY†:ÍcÚó´”Q¡r $HÑ1ÆmÞ †YÖ05¨Š(*(  $*èKfÖÔPÅUcÉxQZW…ÁŠŒQQu”äw 6=.`,'؆ˠS¯rÒ NG”komIfX«PµbMQ4³¢Ô(°VoOi4‘‹*vÖ¬YˆàÕJ;Š^I”±‰ô” – À-²ól ±·>Jý=Ƀ°·“FL‡EO öfQb‚[O¦8fi*,"`èúšu«ºº¨×¶¥@Tµ\©ƒbÅFk&ê 1 ÔS+crÉWŒÀÈ1ÂýaQ!Hê­–üõ9¶,"Sgý u1«„ÇR=ÞºEP¤¼DÀqM4ÚhµUÑbE˜L‚ib´ŠÖª2*Ž•¬0j+­³TyæïSRŠÐh”R üétÜ0B%3êtJÉ*eƤ`s‰ˆ?[Ãs-¶q ¬êÕ²5Æ CuÇ.Š5ŠÉj³U·c“¬XÑò¼Ý¼´ý°)Bƒ´‰»ù»mД E;ó(JJéˆä æ®.<Œ1AYbÛÖ¬‡ž\W¨„J­­XU+P¸7Šív¥TU“Tã(Šˆ¬áÏk÷\DÞP,[!Iÿ‘7†±#ÂÆ~+F߰Ѓ;[KCœSÛžˆ Z¬¨ªP5U³¨‰Æh«z­8ÚJH†¹ UåT"#ˆÅ–Uï‹Å*Z±NAL iÔ!ºBsR( v(¿”¾Ê~¿Ÿ¶€i8MÄÎZ©¥ªQ4 Ö„ÕҮΓêÈ(ØZ¯XaD” =ÄÖ®JU…R¶û¾EÑ¡±@F„.™h߃u¹B—L´ïNˆ<‰4¦È©,j³`Q Œ±`¡‚¥uA¬³èÔ+ÅUD "á0ÕÕ¢b«.Ö*H‘¦û!ÙÖ¬Ù C£("&õþ õÚ®ßÈAc<:Lê ‚ë’îŸø¤7za¢lr™ `+†Å.JM««buz¢„xÅÀZ>Ȧw¥tiå8Ξl]_[Å뢄2ÊÑjJô‹™G’Šxñ¢XBÜ-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎvorbisXiph.Org libVorbis I 20020717vorbis)BCV1L(Ä€ÐU ˜6k§µÖZk‚¤vZkªµÖZk&µ¶Zk­µÖZk­µÖZk­µÖZc 4d@(J´dRLJ)e GŽrä9HÊ'¥(G bâ9è=õdkM¦¤ä[MJ)% Y@!„RH!…RH!…bˆ!¦˜bÊ)§œrÊ)Ç ƒ 2È ƒL2餣Ž:ꬳÎ: -´ÐB ±ÄSm5ÖÚsÊ(¥”RJ)¥”RJ)¥Œ1ÆBCV BdA!…RŠ)¦œr 2è€ÐU €ÇI±ËÑOò$Ï-Q=Ó3EÓ4MÓ5mUwuUWuÕVuÕVeÓ5mÓVeÓUuW—uW¶u]×u]×u]×u]×u]×uݶm 4d  #9šâ)¢b®â:ª„†¬d  ž!*¢&j¢æižçyžçyžçyžçyž„†¬ iš¦iš¦iš¦iš¦iš¦iš¦išfY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY@hÈ*@@Çq$GR$ER$Çr, YÈ@R,ÅR4Çs’: È닪ü.«tX¾â6˜`Q½qzG(å¼`~³Úø†Swë¸æc‡WÎs²þã¡^F Šå›ãÑÉ „:µ« lë»LÐ(PoijÍ™n"Œô·íÀpX=Þ>²5­¢m¢ïH–.hŽMÄRñS2ÙÁ S÷¹L kz"×›²g”³L’ìý#Í`xÜ¥Ú`ÎüÄây>ëoÍŒ^ã§‹1ºü=GNu÷ jܹljH§hÔÛ¬r*9œsJ*txk]kb4^à³Yó°Oö>´f£§É“Î[îÇyãit2`Y»ï-a\‚¯7>'¦ M’îû°yl‹¸´J£»,:x£&«ÂxšõáÃÞãõ¡¯°$¥%^—¸½eÎIîqL&´>õõÉ$?‰2M]0žØÆŒt ÊÄÿƒ3UhGŽlˆ^žñpñ¬åC,‘ò$oÆË÷ó%¾®5}Ÿœ^‹¯ä3yhóXu´¦;»©é<ß Ð¢&–îuE+>I[tl¶‹ ç¦ jR% Ä^Þ…~˜o$©è_‘ šÎH¤"±«ÝÓû&,‡E Ô¹z2'i!YD• âÅû²ûJúgíöÎ äÓÍZz !­6¸_§ª·‡±Cg¶ýSáEDJRJ | ¬ÎŸ}G'¡/öÿ"ü™µ>ùjËý%™«ýä¼&dzÜò˜<&hâˆúÚ±Þ qèx}ðÊüRÎ_8…î$e<çšÖš¨õ¯:õ6´Èí–^AX5GX½Îüò‘fa ? ×]+Á=3…a"¨¶K™KÏÙŽ¼‰’Ú6³ÿ×C¯!,ü*Ðé„oʼn÷m) T‘òE‘R›„Isû’'[©¹õð.ˆG=Lç©f XïB 9 *4&ÞI- @>кEŠÓÆ_çÞ>µ‚GQ("/*EE)Ì{{šñÕNÿ‘öìÈ€ù¬¥VLöÿ|¹ MiT/©ð>éfp ±ÿwÖB“JD%?ÅI=y¢6u°ÜÏÓü)e3Q·v[ܼ¯8÷iÅ’§¹|Tr«vVJÊõø¯>-ÏS³á`E Ö¬²½¾u%6¾£Df‰ŽN®R¾£ðëF)÷ï*É÷êMïþõîÏDò9(…3˜ð^»>.ûIv²f7ÖèRdîPú «%0)àÚøã›ND1Šô‚$’j lœ¥Ù›Þ>½ýÁ#ùOïï_¨?'e5·ÞO;­«lŸèêlN+{uzãì»FNó6ÖY<Æõه瘘ź 5 %˜äk. ²ùù:ôe7ˆ·ÐAMêævBKæ]É[«rD}§ª´F( 6Hï’Ã^ªÎå+Š<ÚÎøÏ;ä¢w¸¨l×YCÙ†ú?»îÀHKŸ_gèŸÕ½¤ðÌž+@gꎼ$ÁöáLÓú²ÅØîr °~ê Ør^€þ<…ÂH˜FfUf• LÏç.ÜMòëqóãÁxðêœçaõ<»Ñ¯Ö97“J…Oµ$Òzôe`Ò»E®¦s×–>GÕ•<"åáÊ(}Å\*=BNïXöç官]É­!ršlQ»ºé’²÷I•WçŒØèB@ž·ía® [À¹v¶Ï·*R¢óEC‹ÎtŠ ¶R TmÏØôÐ>ùHY§Ø^án)Þ v§/÷ç eМ±yf«Æ¦ŸWø—ÑTÿw(·‚Pt¦vÅæ™–³2BšLž µõ15è@;&È ) É" èÝ+‡3͆1®ŸÚhJð/Óþ±,§³™”9½n ¢†8xOˤ܇ó7ÁÏb|²OÑñÊmiôGèJe˾>RfŸ¬b#b»*ÃÓšºîw„Ä_=ˆ¸ˆÆhŒñâ78Šªd jY6ƒ‡^h½áXxç&OÃÐ{û/2™íî±![‹¼‰Û=Äúq„µ°Ð°ÌÇÝ3A‡&…â’úÊWn5· mžèÌ ’ƒ‚aÙœÓcêk Aí÷»xK^º ‰ yÍ–þ  ÜÏÛ¥TidÚê²PI,°÷ùåiæÔóWÆáÖ´yÆ4鯾b¹°Ì:¼ŸÛt^Žm:Ý–Mûf]°náQÖGY–1‰K]Sgº[Z…oãE¯ ÏÙ1 }hÙLû}žÆòwýÌZÃõÏa½ÉzŸ~Ìcî¨(<ÊÞ­)›K5oñ.§_7ô&‡F« nñ…ÖGñç¬;ððÑñq§ ¹žJ7m±Å(…i»!Á£Ý¨À¥‰[K[³êæ-IŠÌ0Ô >„oïñfV.?öþ©, òÉ §ó ¯Q¶£FfR% e¦xØîsš~ðç!»ü _'çwS·~È ËÛƒÏ&çµÿè—¨"] æg€X“¯§n&¡Ý¿-ÜÈÒEªôЕØ3׺;ÀŠÜÔÁˬ OÞ±oˆB’Iå™XËåˆBŒ/ÿ‹a½Gæ ˹Çokb³;D{Àçô0È©–4€V¸eµš3eDtýêw,bWƒ=Ü+)6µ@}¯ì&þ¥!ìîžM3Ë}vÀéŒÙØÝàÛôÿƒ²¯ófn0‘ø>©ì ¯¤G^Òoe­UúJ"k €Ñ»ÑxDð3 ÒøœT}OõutÖ¶íÞh×[°¨$ö­#DŠìÖ0ù®ºFuêZJûB7þ®ICÙ°)©=«ñÍpNI¢ ^å.-¥çAÎ SüÄøê²[áë|< ¼¿K[(1ÝYþÙ|¯â sc+éj†ö×SÆ&£¨×£ÂÚêxxšºÎ}žöêåóXùVÑé>ñ6sIœ©ï¡@ùÒ#{5R-»XÖAÅå=·G½ÐT1T%ÿ¤Â>/þ¸ìšÞ±O‡©‘¯Z¥¯„è,%PF-s,‚ú“,$°MÝ•#Á†S׬§Zýëú,'Û§Oò²Qîšâ€ÂÝWNW_§½„8«šäë}D<÷ücEÛh¬]ŽŠìÙïGm=ÇÙØ‘ÏxÆú§ˆœg¥wwªá€Øžå*ýÊô…mHìÌúšã³öõfTT÷>"tö#L)ÏÝð‚>âÛJA²®ðÂ6³€ôð÷Eÿz®9ÖÐ>â^ æ #ì?›ï–}É’$š«‹ï5”?èÞ—ìvû,˜C?\¨/K]+òŠöêÀg– Sm¦þÓ­íöçW¶vÇ2…³7Ckò{2=|o!YË$Æ-Ø_Ìzø)92Ò´L  †7tˆcT˜ÓI&µ "Ö³¼ˆ¨²ö(æNu³ YÈüÎÃÝÅvñÎdÕ&¯5i™·é‘ÖÖqr¼‡Ã3°UKü.æ1uµÅuÈE¨‘­ÓUÔíýÌæ×°”û!Ö:çrÃ`õ?Xh}—‹_T ¶ÎþdwkÛl.â#µÌÁ´ÛFñ’iíj §ÖIHÈ >™,'²Ç/&ù°Ké¿`.‡Úè­fFêE̬(Ò.A<Üæ-ïJ³ŽÐwóíK9Ï;Í\ ŒäZ±Öôœ‹¼ X5ÏÐ-ŽýÇ'ð=Î{ðv67• #‰‰:bª,g“­m)gÍݓƋyuØä(_0ÞõÖ&$\ » 8½=«áÒ¶˜Ë¨±D+F€¡w—lUX_â.;ýuxã"Ÿ#3²_kQìüm•ŸÌ\‡‰²Ñé¬ò¨LþÊñ´ÇÒ.M­£€òõÒ{"¡*WÅË%(ŸúÞx,ÒéñÊð2JF~o ºíŸlm("If)%Å#WاâOó¿`²u,ŽÕYÓé]ëÔNoÖÃÐARUFÂy¤Df貞sv«ŠØßn`°ùŒD  r#|3m\Òüœ{Db™5ÉFú…:ÑÖÞ-,l´‹qe'5¸Äf%ÿåõ×gGORe+˜Ý4 ®Øâ]™’4ªÊÀ±ñæ9ä6ü‘s¡j°?û©RçUÂ;vÕTT¸¹â÷àº|,i ÷Ù÷F^PÇê¥óÇùœp-,i(^DlF^”þ›îf”Ø{µî77°)õHMƒI!$ðõðàx~næúÎ'ÿdÆÜäµ÷w7®o™ Ú‘0x8e’ˆ“ a2Iï3=}âJÍ=ÝœH@ Úî(9ÍϽ0 ¨³ñ·!B㱨§ÿOò³”±b»¡ª»DœÖýl½BÍø"&6m°ä_÷¡-´<Þ8ps¿Ø¡üÜ<[J#8ûLrzíròN’&¤%’6ç äÔØt,• õ*Rm™+¯}%ɘt†œú¾¿ÓÒ Òµ=Ûñ­/övP¾ø³åótŸžOïƒsŸ2ŸÜs%YØZ¯ "+,K ãå¯ÃöÅ«s“ééù½ý_'cúÓü-‰ÇI¸9epL¶Î4ÔI†+PjÈtréoºõˆÀä?M&½¬OöÝ›:˜õ>¶q” F z=¶W¸du¥”r}‚'µÜQÕrÑ…Á\@Z<·i–¼ÎÔ"bW/ îÖì$R{ú»|27;b’¢•j®·åüñ ÑïG R“ZBjÒ`¹Vñ×^IÙD±¢÷¿÷‹ÞÞ¸….2Hgyk›ì–˜~TâO¿—±™SüçjØlõ,‚W¤²JŠÏŸµJÎþòß4ïÿÚ̇-Þ%Þç¦m|ñTîvVPð+€Êtª¸ ’O·ˆ §¥]CÜ»vg ‹?®qFQ‘ ]+÷~)Ý—‘º‡~†uùÐÍ Ó±gíát/LæVL#ÐPRM«¥4y -BLžXÓoõ“×`P›60 òØÈT™'oö7æ¨2àip!Ro9gñ• 9X y ðr#ÕÐïªLañraƱEFb¼nZ_mæ˜ù•´L}jLOggSÀKÑm˜mêÉþ5dËFëáàÝ.0 SŸi†`3ÄøuôßDòÜÐýã³^Æg—‡_ŸõÏ_åÎçÏ7Ç$+¹Žöu„ŒÌ·5åNƹŽî0¿à Àæ`רøyýóþY#G¤yyã[H¦L§Ì ×¥yyNècôlNXgOË“iž0€õÜÜsž„`dmzdˆ÷¤*…s{²kŸ% 0qÑû/F£K¶á }Cù}†² ëYóÀ 7 Æ&2÷‹crossfire-client-1.75.3/sounds/click2.wav000644 001751 001751 00000010260 14165625676 021164 0ustar00kevinzkevinz000000 000000 RIFF¨WAVEfmt +"Vdata„ÿÿüÿüÿÿÿþÿþÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿþÿÿûÿÿÿÿÿÿÿþüÿýþþÿÿÿþýþÿÿÿÿÿÿÿÿÿýÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿþÿÿÿÿÿÿÿþûûþýûúýýüüÿ úþõðÿ!$Òÿåÿûÿ  ÿÿù$ÿÿÓ, ÿ Äöÿþ ý  þëüÿþáþòþÿþþÿòÿÿ÷ ýßü÷îÿþÿéòüÓý÷ þýüþÿôþ'üûüõøýÿöýýþëýý ýûþ ÿ àúÿëÿùøþÿ÷þþþÿðýïüþûöìÿýý ÿÿþ ÿûþþýôþþ ÿùÿÿþÿÿÿ ý ý  ýüüÿþûùþþóþ ÿÿ üþþîþ÷ðÿñöþñôþùøþýüÿ÷üö þôþûÿÿÿý÷ÿÿ÷ÿýÿ  þÿÿ þ þ ÿÿÿ ÿþü ýÿþÿÿþþýÿýöþþÿþÿÿüþýþþùüüüÿ÷üüþôþùÿÿþþÿþÿýþþûüýýÿÿÿÿýþÿþþþ þÿþÿÿÿÿÿÿþýÿüÿÿÿþþþÿÿþÿÿýþûüÿýÿÿþþüþÿÿýýþýÿþþú ÿÿþÿýùýüÿþ ÿÿÿýÿ þüÿþÿþÿýÿþýýüþÿÿþÿüÿÿÿÿÿÿÿÿþÿþýÿþúþÿþþþþÿþÿýÿÿþüþûÿûýþÿÿþÿÿÿÿýÿþÿÿÿþþþÿÿþüþÿÿþÿþÿÿþûüýüýþüÿþÿÿÿÿÿÿýýÿþÿþÿýÿþýýýüÿÿþÿÿÿÿÿÿÿÿýýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿÿþüýÿþÿþþÿÿÿÿÿþÿþÿÿÿþÿüÿýÿþÿþþÿýüÿþÿÿýÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿýüÿþÿþýüÿþÿþÿþýÿÿüÿþÿþÿÿþÿÿÿÿþÿýÿþÿýüþþÿþÿýýýÿÿÿþ øÿÿúþûêþú ÿ÷ þýöÿûôþüÿÿþâÿýýìü÷þúüôÿýÿüüþþþþ þÿþóþýþÿÿðüûèüúýüÿÿúþýþþÿþ ýøþÿþÿ ÿùÿýÿÿÿýÿû üüÿÿüþý ÿÿøÿÿ ÿþÿýþýþüûü þûÿõÿÿøúþÿþýþôÿýÿÿÿÿÿ ýýÿÿÿþÿÿýÿýþÿÿÿÿÿþþ ýÿÿüÿÿþýÿÿÿûÿüþÿýÿþÿÿþÿÿÿþýÿúþþÿÿÿýÿüþÿÿþÿþÿýúüýýùüý þþþþñýÿÿþþÿûþþÿúüûýüÿùÿÿûÿÿûÿòÿÿ þ ýÿÿøÿÿþÿÿÿþÿÿþÿþÿùÿýüÿÿø ÿýüþúùþÿÿúÿþÿÿüùüÿûþþþ÷þûÿÿþþÿþóÿ üÿ üþóýÿýÿþÿýüüþÿýÿÿøÿÿÿ÷þÿüý ÿû úþþþÿ ýûþüÿþýøÿùþý ÿÿêÿÿüþÿûþùøÿüÿþÿøþ ýúûûüÿþïÿþýÿÿþþöýýø þÿÿùþÿÿþÿþüüýý  ÿûþÿÿþ öÿÿøýüþý üýþþÿþÿþÿÿþÿÿýýþÿÿÿÿþÿþýýüþýþÿÿÿýþÿ÷üÿûÿýÿûüþ÷þþüÿÿþþüÿúþýÿÿþÿþÿÿÿþÿýþÿÿ ÿ ÿþýÿ þ ýþýýÿûùûÿÿÿÿüÿÿýþÿþýÿþüÿÿÿüÿüÿþþýúþûüþýþýþÿýýÿþþÿþÿýÿÿþÿÿþÿÿüüÿÿÿûüÿÿþüþþÿÿþýÿÿþûùüÿþÿüÿÿüýÿýþÿÿþÿÿþÿþÿýÿýÿýÿÿþüÿþÿþÿûþþýþÿýÿÿÿÿþÿÿÿþÿüþþÿ ÿÿÿýÿÿþÿÿÿþÿþÿÿÿýýÿýÿýÿÿÿÿþÿÿþÿÿþþÿÿÿþÿýÿþÿÿÿþÿþÿÿÿÿÿÿþýþÿÿþüþþÿÿÿýÿüþÿþÿþÿþþÿÿÿüÿüÿÿÿþþÿþÿüÿýÿýÿÿÿÿÿÿÿÿÿþýþÿüÿþÿþüýÿÿþýÿÿÿüÿýÿÿþýÿÿÿÿþÿþÿÿÿÿÿþÿþýÿýÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿþÿüÿüÿýÿþÿþÿÿÿÿÿþÿcrossfire-client-1.75.3/sounds/FloorTom.wav000644 001751 001751 00000013046 14165625676 021563 0ustar00kevinzkevinz000000 000000 RIFFWAVEfmt +"VLISTINFOISFTLavf54.63.104dataÖl`f^R`BJà,,J@ÂÖÒ€€€€€€€€€€ª€”Œü"B>zVD\h~l^L²úöRâü κ€€€€€€„€€ž€Æ¬œÜœºÈèzì¾^T>ˆþÐ4^.ÜDxnj.vhhjh\`TPRFH@>:44$"úØÜ”š€Î¶ì¨ÈÐÊ‚îÆ&äÖ¾˜Â¤ÎԪ怀¬Šòìâ €²€ÄôæüþèÌ¶Š ˆ€’€€€†€†ž–®–²âôÀøÒ¶ÊÂÒÖÒÞÜàèî6lpp~bdF48.ú¶ÌÌÆÈîÒܺÀÀ¬êäú$ü *ø*RNZBL@6BÌæ¼´†€€€Œ€˜€€€€€€€€€€€š”€”’˜ž ¬¬²¾ÂÖØð Jb|rp8H22 Îòò¾ÚÆî $ æ6$6,DLZVvdDD""<0:$J..(äêàÌäâøúø8(è öòèìØìÖÖÎºš€€€€€€€€€€€€€€€€€‚„Š˜š¢¦¼¸ÄÐàÚæâ ü,,@8@^LV`TvNL  ,(.lNL@(6 .4N:8( $$H:~^bLZJ2" .**44(" *ø " Ú,êÒÜÊÌâÎêд°¼èÌÈÈÈ´°Š„€ˆ’’ž¦œ¤´¨¶º¼Èº¨¦„ ’ †œ¢œº¶ÜÄÄÆÄÎØàæòâôèèîî .2J.TRf^ZjTvpXfJtlbLXF>|Vh<D:HL28 2",$ü&$*.FFHXJLL@DBJ4F6R>42D88"þêÔØÐÊÀ´¶¬¤¨ž ” ž¤¨žœ˜†ˆ€–’´ ¬¤¸ÈÈÔÊÔØÊÆÈºÆ¾À¬¼ÆÔÐÜèôêøäðôøîÜÜÜÈÒÐØÞàèøâøè *H&D>JhZlTT^:^Zbt\jldzx~||fVHDJ:D:>F<XHH:.8444,.þøøîöôòð"úôúæÞÜÚàÌȸ¢¦ž¬œ¢ Ž¤œª¦ž –šœ˜´¤¤¶–¦Ž¸¶¾Ò¾ÒÎààààäæðäêòòüð  ",, & &,8@L8NLN\BL6TRV\JVVXZZ^Xbd`jb^^PPNRNHND>,,*  þþþüòòîèîäìäÚØÆÌÆÆÔÈв´¦²¼¾ÔºÌÄÈÚÒâÔÒÎÔÜÖÐÌÎÈĸ¸´º¶¼Ä¶ÈÄÒÀ¼ºÈ¾À²´¶´ºÆÔÚâìîòöúú  *$<.04(@Bb\\\`TRFJFBD064$<.4.*00,08$,0*86D><<080480860@6\BF4,:2><6:.,(&úòâÞÔÊÌÈÀ¼º²°¤®¨¦ž”–Žš–ž–œ ¢²´À¾ÄÌÈÚØÜÞÞààÚààäääæâêêîæâààèÞâÚääîðêîêòìîôæðêö *2>PN^L\\Xj\`ZZ^V`RNFBHD::64,"  &,0.226422$& & ""$  ôìØÔÎÎÐÄÄÀ¾º¬¸®ªªž¢¢ ¦¦ª¤¢¢¤¦¦¬¬²¼ÂÈÌÎÈÊÎÐØÖÞàâêìðèîêúøúúúþ &(..$& "(.,44<8<6>>DJBD>8<6<44<6<>JHDBF8:2>662*,(.$" "úüôúúöþððäìèææâàÚÔØÐÖÈÊÄÌÐÎÎÊÌÊÆÈÈÈÊÆÊÌÌÈÈÄÊÆÊÄÄÆÄÊÆÈȾÈÊÌÎÐÒÊÎÌÐÐÔÖÜÞâäææèêöø $(,.*.**00<6882:6:>:@>DDFF<:4,.(4&(*&,,.404,42260446::<64*,,(("$ "&" úììäâÞØÖÎÎÌÆÐÈÊÂÀÄÂÆÀÀ¼¾ºº¸¾¾ÂÄÆÊÊÎÖÚÞÞâÞàææèäèèêêèêâàÞÖÖÖÖÔÔÖÚÒÚØäääæèêððøúþú  "&*.28<@JFFBD@@@@>>@<<::<<@@<<6:2,*$ $ "(&$&  üööðìæäâÞÚÖÐÊÈÂÀ¾¸¼¼¼¼¼¼¼¼¾¼ÂÀÀ¾¼¸¸¼¾ÄÈÎÖÔØÜÖÜÞâæêîôðøøúþþþüþþþ "$(.024666884422444200..0284620002...0.,,****&"  üôöòðòîììîîîìêèäæÞÚÒÐÐÎÒÌÎÌÈÌÊÎÎÎÎÌÎÎÌÐÎÐÎÒÒÒÒÐÒÎÐÔÔØØØØÔÖÖÖØÖØÜÜàæèìðôøúúúüþ"&*(,0..,,.*,*,.046864424220400,*&"&""$ $""   üüøôòîìèæäÞÚØÔÔÒØÔÔÎÎÌÈÈÆÆÈÊÈÌÊÎÎÌÐÐÒÎÌÒÔÚÜÞààâäââääæäæäääæèèèêêìîìðòöøúþ "&.$426220224866666666666442..***&&$ " þþþúúöööööòðêæâÞÚÚÔÔÎÐÎÌÐÐÐÒÒÒÐÒÒÐÒÎÐÐÒÒÔÔÖÖÖÚØÚÜÜàâäääèäæèêêìîîîðòôöúþü  "$$($$$$$(&(**0..0***(***((&&*&*$$""$""$  þþüüüøöòðîèìèæäâäâÞÞÜØÔÔÒÔÐÒÒÔÖÖÖÖÔÔÖØØÚÞàââäæäääääâääæââäâææèèæèæèèèêèèêêìðòöúþ   ""$$$&&&&&&&&&($$$"" " þþüúøúøôòìêäââÜÜÖÖÖÖÔÔÔÔÔÔÔÖØØÖÚÚÚÖÚØØÚÚÜÜÜÞàâäææêîðîîðîîîîðîîðòòòôòöøüþ  "&(**,,,,,,.**********&&" crossfire-client-1.75.3/sounds/gong.wav000644 001751 001751 00000342276 14165625676 020766 0ustar00kevinzkevinz000000 000000 RIFF¶ÄWAVEfmt +"VLISTINFOISFTLavf54.63.104datanÄúøöööøúúúúúúüþþþüúúúøøúúúúúúúüüüøöööüþ   úðèâÞÚÚÚÜâäìòöü  "$$""úôìèææèìðöúþúøöôôöøúüúøöôòôððîðòôöøü ""$  úøöôööúúüþüøôðìêæèæèìîòøü  þúôòîîêìðöüüþúüøüüüüþþþüøòðêèæææêòú  "þøðèæââäæêîðöú úôîìæêèìèðòööüþ&*.0**$  ôèÞÚØÚàèðú üúøööòôîîðòôöøüøúúúþüüúþþþþøöòîîîòúþ $&0064.( üúòîîêðòúüøòæääèðôþüöòèâàÞæêòú $*00222**$($" üðàÔÎÂÈÊÒÜâêìðöö  úúôòæàÖÔÊÈÌÎØâð$"&*&,"$$"0.86*( þøîààÖÚàÞêèìòðôðìðèêîìüü ôôööü(,28840( þðèæâäääêèìðôúúüúþø îîààÞØààäòô úèäÖÖäì&&"$0.4602" øðòìôööüúþþöúîêèâðö þêìèèîâäÚÒÚÖàêðü &,02<8:826.04,$ ôÞ²¨š–ª°ÄÐØèêô"*(4.00üöîòâäÞÔàÚâäÜâØÚèæ$ þ&2@@D>,0""üðêàÖÒÆÂ¶°´²ÂÒâþ $"$ üðòöþ úôúøøüôòêâæâìöøü,..."öâÐÌÊÔÚêìöúúôìääÔØÖØäÞîìò ,6<D22* (*,<02" öúüòäúðöüìòðìøèôò úòêæâÜÚÚÔÖÎÒØÚöþ ">JP\RH>40$ôÞÀœšŽœ¶ÀÞâèðô ,DJVLB6$ üöàÌÀ®¬ž¦ª¸ÂÊÖÞÞêê 24:8:68.0,*, "þúð øúòîÌÀ¸®ÌÎêüî üðþþ øÜØÌØèô&, *&,,("  þìäàÜÒäâöøòøèòú".( æÞÖÎàâîüø îòàîööüøþèøø" ôøàöþ$.LFRH42 òæÞľ¬¤®®ÒØäôäìàâøôþ *.,öèðê  ø*J èÈÖºôþîúæÞøò ( " úöòÖή¶´ºÐÈØÐÔàâð "$",. (*$"" þèæîìúøôìâÖÐÐÖèø üæöüøôʼºÎÈìò..0 .,220&&"$ôêÊÊÎÔîêúøø øüÞìàìø ìèèÞêêèöêêâÐêæ  þ 6@ ö>2ZT$è 0èøÜÞìÌàºÀÎÂòÜêÚÚîöú úðâÒÒÒÜêúü$&2*FB04 ($**öÆÆ¾ºÈÂÞêü "öòÐÔàÜðøüÖðäðÊæîðü ôÚî &ú 4$"FBfP>2ööîòÒÐÆ¼ÊÂÚâðúòÞÜÀæì2"êàâÔú"øææðèü2<N&,  øôòèìúþ ô òøÖäÒÔúðD,2ÖðÈìàØàÈØÔÖÞâðüöæÜèÖ04 $ :FFX&, ø îîì¨È®ÌðÈì´Þìø.* ""ÖξÂÒÔêäîîîöàèÜ4LBT<ZTbXJXLL$Ô¶š†š²Èàôüøü 8,âøðòêÚþ ìêÖÄÔÈêÐÜÜæúþþ ü$",*öî ZHRP8T4.üøüÚöÔþô ÂØØÌü¾È¬ÎÔ"þþøøòîôðÔðØ îÖ*DDXü"ÚüôúâøÌ¾êÌúìÎ(l:XöòÒÎâʾäÒàâÚÊúô ØÞØØúò .@4"üúü<26,**,"@6D&ôÒиª¶¸¼ÂÆèôô,þðþúâÜоìè ØèØÔæè$HJX\L^(>2D& æÚ° ’–ÈÜ & 0üúü(&$ üðöÎÄ̼ܸ¨¬ÌÐâü *0 è6àÞP8PH&L ,îüÚðB*(üúèÒæà°°€„¨¸(LJN:0öþ¬À¾ºÐÜæàììØNB:0 040\R^öüâ¼À¦ÔÎââÔæäôD62 ìäúî¾æžÌòb &èÌìÀöÌúâäöèü &&6þè¼¾Èô<XZfT0B,^^b`,,øØ¸¦¤¢°ÀÊâêâì òÒèÆþ <üòö <ô䯴”¨ÀÖ(@R(lHvb*2îüêÐШØÜ ,(:úìÒèðþ,BFX,*ö¸º®¨Â ²”¾Êòø 0@:Xü ÌæèæîöÆ66ô"Ú&:6` øÖ FVP^J.&êøúâü¤¬€€°ªêì*&X>>ì஼ÂÌê¾èÚò"J  ôúøö:j`z 6ø ôÀдªØÊF*P$ " $ þðܶĴÎÌÔð öæÚäôÚöâ.*þôøú(8Üಠ”šÈæLPxHRT@hb8öJôæÊ´ÂÆØööðøÎ–”¦´Þü(*&,&2,<8ÊĨ¤¢¬°ìþøV24 ¸øÚ,.(&D4>ò®Æ¸Úêì., öæ¤Â¢ÔêÌêªü26(< &"èäÒÚÊÄÐæÜèÈðêþ ì2$ "B,V6PrvjJÔ°Œ€˜ŒÈÆ²Ô¬Ðød:R.úêæÖêøÜþÖ  ôöÖÆÔÂâÀØÜ"2hXz>ZL0"èØ¾†ÞÎ@(*0. $ö ê´ä¤úþêÂþüBx ξ€š¦®öî Þþ&Þ$ "ÈÜŽºâî:FRx@&&rÆââÜ0ü æâ°À¾Æäð&*ðøª°ÀÀÞ¾Òàô"@:<6êè¸Èèö"*2>4 òH2N0 ÜÄʼԸúb>R,.òÒÌÒ¾¸ÎÐúôØÖÈÖèàä&ö0RúÜ„àÂìèÈø6rjnndB0ÖØ¸ÒôøòèØÂ¼ÈÞ* &.¤Ü¶ ä æ8zЀ¬†Ðö4æ04(üàâ¬Ðô \X"`dJJôؾÚÒððöþ &èÜÀ¬–¤®æü,à ò0@,ZÈÔˆ”à¼ú(â4&NØö ªøtHNV Z0\F*òúâöÞÌÞȼÀ² H. ìÞúººÜÞ (äèæ0BöÊÀ’ÔÖ .8þ "$@2&èÊÒÔÚà@dT`J2ðêèÈâºÌàä*6 îì¼ÆÆÄÜÎÞÞÐêÞ,ZNPVúö”¶¾ÀìÆâÊÎô.&*@vB\ üêø"ND&6²ìÐö"(¼â€œèÌbú¢N :€°¶¾$Ô æÆ ÞîÌäÚî0æ¶ÂÚî@2\`vjN0ò"Äæð"4*p Äêöäòм²Š˜œ¤èô , :,8R DÜÈâÀ8øê¼äºØä ¨¸¤¸ÐÚôB6f(vlvJ4J>>N*Ö̺ ®ÂÖ( :æ"Ø<âð”äàüv"dò°Ö’þøü2Òæ¶šôÌ.þ:Ê"$TðÂôÐüü4àBvøüôòà(.Üô’ÊÒиҖÞÖ4":F8\DJ&ôÈ̾Ôà¶Þ¨þö¶è¸úD4æ2,8ld~D,þúêüÎÐÄÄüâòØ6*ØÌè.úP¾Ð¾œ(üV.è  êèâºÜº’þÖ@: 88 d$òÊ ô:X ä°êÀÞœ¦Ä¤úú Ê *@òðìÒìH $ôìòÔ¦¶€ò¾üȜθ 6X`Zn0B:(b".Âä¦ÚVüÈújÒžÊô@6œò¸ä جƔìÜê<ÔÈj$fÜàʤâ4Ô"´B"Üš&úZV"LèÐf<LNàÄÀø¸Ú€¤€äØ \NÞ>Vòà´<útâÞΤâü®Ò–ÈàÞ*ÂìÔò Lh\fhNF & òüþì2HôàÊôÚàîîòðìî¼èÚ(&*@øÒìÜîÔÚôÀ & æôÈðìîòø ,82D<.<þðìòàøÌðüþH4¤Ø”âò à FT2Ðæ¦¸Ü¬Vêôº€Ø˜$>>Î n:Âü¸*$(N(4 J èÞîÐîD $L$¦ìØÎþÀà˜ŽÞò6(&*òð¦ÈÖîúÜô$âÀ$h$ü$ RD*:  üìää Æ®ðø0ÖÒò¬èø@âºú¼><(L°Ò”ˆ¶ưàHJ<<.Fú $(868äàþêæìîÈ(òØð*$@æðØÌ¼ìòòäúð>ØðÎÄæÀ" Ê$P4"" ôÚúÞ( (0.4þêöÚäÀÊÞÜî >ìöêúÈö*ÖêžÄêXú(öÚÄ(ÂÐȸü@<*Ô&&þÀðÐf: ö"TèäÚ²æâÆÎªþ.äüðôîðèÜæØþ8öøèêêòòðöòöø \.XòþÂ4:8þðÚ>pèîܶ” ²àöÜ ð2" Ø"èâžÆŒô$Úü´æ0 ð 2$,:&  üüÞøòþú(:2NèÄÜÄâàÒæÞøô ÚêìÄðæ$äþâÜ bþôÔøÊ*âèÚêB((0(<4,2âøèääÞòúöèôöÜüîöøXèòÎÎRPê€ÜÈì¤Þ¨Èæ<,Ü 2b ,èÔÎP,<$ö îJ \ÜäæÀø,ºØP (ØúÐúèÚäÚäðøúú,ôâþà6ö,¸ØæÄ<HœþŒ<ÊüºÎX r >În2\,Êö–²ÎB°Î´œ6 ~X 6úôÂ@þÚ€Þ¢ì¤ÜÌÔ"âôÀ Ú\@<BÔò&&âä¸Äàè82\üðB D*$ òÜøî ÒøòôêîêâæðúøìðÎòðb4`êæ€Ú(æ´æ¸øøöH^$úÚV(ææèÒöîÆFìÚ (Nðè¶ÖԾʢÖÞðäúö0*0: ²àÒþ $üúÞîô(.òh,ZâòðØâèÄæ¾â$þ(úø ÊdΘòôHö¬ÌFÄ€âò@è–ÊR2Tšøºètð^ÄÖæ~X^xÎ ¨ÔDöHØÀԀ̶œì¢.àþ àöØîÎì”ÔÜò$"ØÞhNLB, 4 "æö ò ¶ÄÜô"Þúàðôäúþ2V úÚüÚîÈòÆÒ®Îü öäðìæ2$\"þþ.JúÈ f ÌàäÖÌ,ü(´Ò¸ÎÖÎÒþ$ ì6LÎæºâö²úœ(þèÂØì¾6&~> èè|4\2òÜÂØšö8J䍸 R(*¦ÀVTšÖʰ6Ü0쀜~$ €¶€Àdò”28Î Ì<nP""Îöæò$*Ú°òäкêòì.<ÚàÔöèæ2òâ,(èòêàÔÜäàúÔüúÚü:üüæP&\(Îô² @*08êøüð 8àºìüè0üä¸ô@þôðÔÊÐàüú(øððÞÞæ Üþ:öðèö,(ú,(úòò¶ÔÈäúèúô.lôøÆ¸äÖ.$ÔäÎÔÜÖè üìîþÖô® T0$"*Þ ð4$hÞÌþ4êö®0ø6 ®øœ4:ìþд<üjòÔʂоüè ö ò"êêÖ¾(H( ÔÎÖÜ2B$D<.þúÈø(8þöæ<Þ¨ÌÀºòTàà’ØÜJ øäðÐê &äìê¬ä¦ú0Øôê¾l0ü€Èøô@b0’øŒ:øXÈîðÖhþ,ÈäæÎÔèèð 8äü (ÔøÂ¼ð`"ޜȲêð  LDÊÚÈî`DzP&&Â(*âê"î²îØb^ªš€êDüüâÜøÆ z&âÒܼôÐÜÔòþæþð ö, ö6V îêtࢬþÌn"ö²8ö0>àšôòÆ* ò€ÆFfd€º¤ÔdRúÜø¶æêâ @þ&Ü4,*:40Â0bÚÌÖªôø*–êŒ .þÂ<<òè øJîØ€Àšä è0ºڲfR.:ì0JTœÜ.R@Ôð DJäÞôþòÞ ö,òÜÊðò(òìè¼øÜ,*øˆÐÆbô0²ÈæÌRþ<ðöPpö€(ünB"¾ÎâäH6ìÎäÜ0 $Êþ¾**6¸ôÂöþÖòúØÀ4ºÖȰ îPþ êÒþÌ$N ÒØ,N"LÐèÂÎäð"0@"(üèøò&ú8ȸˆ.òXÜÚ&  ÆîÚò(ðÖÚì´þÈúP$rú¼*&üØÞ0þFÆâîDîàî²ðöôÖþôîþ.Øò¢ðºðŠü@¢Ø46BäØÌ¸öZÜ&”6:@jøàÚ,öZêÚÆ:ôþòþúòäú4Úòäî0ü,ôÆòºH0θöö(ÄäÞ®JüXâÀä¸*,&ô öØþ< 60 & "@–ì° >0èðªêÐø¨ÈêBìüÞþ &æú¶ÐàÆ<ºÒ6 FôÎо"ô <6ÚF(bÞ Þð@ 6ØæŽòäþú &ÄúHR*>æìºüúæêæ¬ÒÀþ4ú$¾øð.öò0èþîúèôöòðö @288 öî ú®ôÊ.ƦòÆ<ú ê¼"ê0üÖè”ü>P¾ÌæÚ.øüºÞxêþ¸4øü䨸î$B àVZ4Æò€òúbþÚ¦ ÎR4&œè(0Ìö²þþð¦Üîæ 6`ÒêØpJDF¸Ð TTÆ*â .(àôÞàâàô F"ìö6þ¸Ì,èÀÒ¦üòöV΀˜þêt ÂêTP$ $êÔ,ÎøÒä¶ðü&>0>þ úþ$ÒÔÖì""úðÚ Êœ&0@Þ伌ôÞ8N8²¾ÐÈ".FìÆ þ0\>ܺà´>,Nfä<à(<ì4€üä>p (¶˜´€"ò*üžÊ2ü(Òü0NêâîÊ Òâ´ÆÚÖü*<ì: È.æ>ö€ø¾PL*ÜüêôÚêðøäöîBèì**ÌÚÚæÂº¸ÞÈdXþÊþè&" @þðÎæè*D6îJÔÈb<pàÄ€ÜÎP6ŒĆ.. ä& úòþôüæÞðâøÌ ðªÚ´(.*$èø :>H &þÞäÞòüüÌöFB,RòÒ „àHø¾êÂÈ:0&ìÚìœêâ(Dô ÈêðÔ ."Bà øÜ>~Nê–nö¾¼"ü€Ø FHÚä’ú*Nò àöòêøþÜÞ¾þÈàèàÚR$n’ð¦NVöæðÊVBôâôâ Ü ÒÚ:$ööò´8øNȺÆÐö, òòðÂâÚà ò.¦öÖ4P 0Ê$<0üTðøú¾âäæöþðäæúìþþô4(ææö$¬ÔžèúìèôÀÔôò& ò L"H0Ðú€4r6öÚ<èfîÔâ€@úh¨ØŒ@,&"¸Ô&ðÐüöðÎ\êúÞÄäÔþ*ð¸þJÌ ¢6 6<ÞÒ0B þ¬4D4ä´"þþ– ô8,(°Ä€Úê^¼¢*òLÎèÜÊj bšÌ€ 4Ä,”&B@üþ¸<Hôèðþðü&<ÜêÖì@ þÄÚ 0àöú D àԾ”îôd2¤ÌȾúØüL>8æ6âðæÞJö>Äô‚0\®òªØêÒ .ö¤0"4è¸ÜþdÖºöúøøäêºôìî 2.öÐL&d4&øê®âºø zÎÂ8l$ðÒªìÚþø,&òšÆÜþ|&^àÂäªòú*–ÆZDð€èÒ6\ Êú6ò Æ^$F¾È:<&Tغ€ äJ"ìâÔØÈÒôV*Rîæ FöîÈʺаÖÒ êØòâø6 0,,üÈü<@2JîОêÚ$ö Öüöôü Büúüú8ÒèüàúúðÆò&þØÜºÆâô$ $,"Ê 2ºØò(B$üâÜÚî $"ÖêÈø6HÐè¼ø4øæüäÖ¬ø&¶êÈØ&ì*öÖÐ`&>èâþ*ÚòäâàP.Jðòø´ú6ØšÌêÆF:.*ªä þúúÄöÀ.ìþ‚.ðh<Îð€Ðâ>$ÄöÖ.&îþìü(00\´Ôôð4,$ÌìÔÜòþ0 øðôòþ î ʲ´’2PÚêìà$ÎÞ*>à"h*>êÖÚ¼6 žîÎ&.Ôú€ê&ò*æê4þfúìèòìÞæüÐôðúØúòúü ð èì.ìH„ÐÀòV&Z0øºä(òÞüøìþT6  Äþ $šþÔê.êT´ª¸ˆr øÆúª@ *Âê,.ü¸Àºúü Fì ª<,BÆ&ÖøÜö4&@$ è¼úêâôâöð 0øÀÜöúÞ¾.îü¼ÄÜÐò<ü2®òð*ôðþ $>ö Bà Ô&>.êèÞÄø"âúøþîòä úöàðÜ$"(( ÂêæØôܘÂÂì ÔúÆZ<fÈöBîüæ6ò&ÐÄèÈ^$\ÌøÖüú>Òþâ ô ôÎôîØè¨ààúæ Ø Òà6<Ô ô,>,êèþòòª þ:ôüÜ®àÌB.:P ê¸"ôBæö¨ìÚîÞÌÒòÖÜÚ^ú&´ê"t ° ðL2"¨üä "ÜÂ:(è¼æ$<Êþöêþînþ&ÄÚöÔ$ îòà°"ê àìÒÐþô*Øô Êì6X"®ðø 2.dʸ:(ð*,:þ¼øä"NðàÔ¼öPä ºØþæB@†Þ²æ èüÖÖ"îâþðÂÐ6x²ÜôîþäBâÞøØþ4 ð¬Xüȶì¾>J¬úÞâ2öÈì¦ÞDþò¾âÂ^@þØîºâþ:èô"Rþ òú ð,(0&¨ê¶N6¤èÒîÞòðš®èB0Šè ô þ²î¨ø(J°âÂä$X@üö(6ìøèð0üÒþð âüþþBìÚò ðPè¼ì",Üþ¤äòÜB&â¬ðÜÜðà8â ž 6 ,2üîøò,.tÞÀøÞT>¬öêÜêJÖÔèúìþ00ì¾üÄ@:Žîº (Ìò°øÜl,ˆÚ´îr,ü èÆ özòÌâü( êèìòâòüî:âÖþ,6òì² Èê¾´à*Fú,€¾ÄúT4VjО((,2äòÔ$þÂêÞäÞØüÒFøÌF,4B>ÎÜ®¸àØúÆ´Ä´|Ü€´J (" üR*úìº*4âþä¶àÎ 0ÂþÚ:.ôBà„îâ 6úÞ€¾€<PL8 €ÎÔ*^&>8ðþÂê6L.Œ¾èäð*òœ Î|<´äÜð:> þ"̸ÂÂ: @¾ð‚ðú*Àêä¶ ò(Vô(²ìL&8ÞæÆèD@$ 䬸ÜPÞÎ üâöø âþ(*úÀü 6.* ÈœØðø4P žúÖêÐþö8òôÞÞJJ6"Ôþ:òêâø êüÜè20øœúò V4ܾêÈ*øúðúÜèþ 2ÄÚÌ´6ZJ¾øˆÒô(8ä‚ÊF NààòÈ@ êÖìö üÊâ:&ê¢ø (\¬ÐŒÒ¶ÐÒ€þ4rÚ®²Ú:$ú"Êì Ün>L@àð¼¦öp\ ÆàÖ|@ÞÜðìþð þÐ ì\$ü€Ä¨þ<6"Úî–Þ@ü¾Ô¸,6L$$êŒBîôê䬸<î¸ ú>ìÈä¶2"8Ð äøô ê ¶,0"îîüÒÌàò$8Êæž¤ìvòî *| Hìî "2ðªøð\ ÔŽê¾,>äØêÐ8*,êüÂ4ì(΂؊ì:¬Êš€>T¬ªô¼d>6dœú¸ÖPòNæºä¬Ú þ$ôÎ$þ&þÊîØ$42 ääè¾æò*ŽÞ°æB`$äþžðt$(²â®ü>LìüÌü <F(.¤èFü0Æ®ØÄ4 " üðôàôöìúÖæLHðÐà€ºÞrì ®ð ò(LîúôâV(Òðàä0*$È$(ÞòÀ*b öœèžd,ìØÞ€øôXÒ$€¾ðÈ""ú(ŽÆ¼Ö.2TܰæN>8àöÞv JÐüÌä êàâøææèJ(ªîÚì44®Ô€âòfô̬²Ð0Dø¦´ ôh&,BÜtê*ŽÌðþúìÀþ |þÌ€øÂPx8ÒÌÊ€Vh²î¸ÒîT äâè²"8"ºì®äøòHðò>ü6ÄÜêú"`òÀôŽH8L”$¶JZü@¼®ÒŠ` \(¼Þ®¤ ø\0hžž¬€:Bf¶ü€Â&ôPø¢æôø( ôØ6>^ð.”ê"$x ŒôÂXü(ÆÔî¼öfðìÖ€þfl6P®è..(LÜâ²øÐöêäæÔöü0<æ&* &ÜâDêÒ¨îœ^FV`Üò¶Œæhv6€ØÜàJ80Èú¼Þ ðFöêäÔþØêÒäôö"ìðæ@ ÆèLV6ÈäìÖ:,$¾òÂÜôLàò¢äþþV8(>ÌФ„^F¤ÞðèxÔÐÔÂ²Úæ@ðºÔè8 0¼,4Xþ Ú¼þæ<6DÎÔ€úJp 2 ‚Ü€DtHržú¸¾4ìNÐþþê ®èú,HÒü¤ÐôÚ6  ¨ èF< "öâôÔü &ªFøPÌôÌÐ "&ò–Ö°ô6FøÞâžðô$"6Füìæ"ö ÐÀغÒÚâþ öDêÒòl0ÜÞÔÀú2Hþ€Àb(¾²ÄŽ4R.öªÞÆ<*&0ä Úüà Ææ–ö´Ö&öâê üJ&"œ ÒFn.bòÜæœ*þ&ÀäÈ” âd8 ÐÞðê<( pèô˜¶ð8\ü<€ì Üì”ÆRh$*ÞØÞ¬HúàÚÜÚôV \äôöî*& .&üö¬À>®Ê (êîæÈô"î ÜüÔ4 Ú¤ôÐFÜüêð &øôÊÜ2XF ÂÆüì âªÒª"DðäÚìêJ0ÞðÚü®ø:ìØÜöÔúÚú¨ L>È4R0þÌ¢æÂf4@8®è Îä@Þîöð* $6æðö\LÈ¾ÚÆ,üþ¤Ô¨öèö ðê öXü°üö\& òâÖÎâä"ôêìüF*Üîðôúð&úàØòà"ÐäÒÖöôòæø2^ òþÎT"LðòîÆîÞB,ÂÂÀ¾òüX*úÜ&> èþîðèÚÚòêìêæüðþèôð ,4 æò6øÎÚêÈ:4úÆÌD& Î äúêèêö ü0*. úòÆøâ0.èîêÊ ú"ì¼üÐ" ¾Ü$ü&ÒêòìF>Ü â^¸ø$Úö ü0 ¦ò¾üJf°ØÀÚ"<DîÚøØ âêðÚúòúäüî4îÜ&@®"ð(òÎèª ü" Ü Nôò þâæÂºäD æüÂ0¤¬ÔPü¢ä$ÜúÖ  öÄÔèô4$.BÈü¸  D.Ð  ôºèÖú:.ö´(öôÚâ,äðæäôÊîêîþô Êúà0 X4æøþ$ èîþàÊôøFÀÔ Ô>:0ê$"> öÒúÜþØâæððöÜêèÜþèòÜö2(*.&Ðþþ"" ð  æÀôè$âò2üæöüüäô¼&î ì¼îž$Âöæ"øJÀê°" ~"ؾôÖ.HèÊ&B¼ö¢ðø(òþ 4þLàÀD *â Ô* ²ØÄàâò ôðÜ $&âÞîÀ" Àð(>:øêúà<$(þÚÄØ0öòúÐ0"(úÀÄøúòøäîÒ. &Öæ˜Üèø *Þ æäò*.Jðàô¨ØÊÐ ô2þ¸ø¾6(.^ü úú08Pà€ðÌêÊÀêÌ$.ÊìäîJØ Â4J,Nøöä² î,ê Âð,(âðè¾ðô"*þú2,ŠöÖ6ðèàäØÀÚ&"îêÒÞ (&Üþêþöðþä"øôþîöàèÈ>Jðúìþô" ÔðÖþô   P ÄöàòÞøüüüôîîºäÞ",H$ þöþâææÞø öäöÆü*î òú"6ðôÔB,ÌúîüÜôî æöàúäâÐöì ð 0B &þ þôèöÐîôð øüðÈìÜ P òøôìþðB4 Êêâæ üî°Ø¸ òô(þî (.6 ¾ÜÂü  æøèøüÒ æ20ØèæØ(<8èú¶ÊîÔ>,²ìÊÐê"ìäþ&N*þŒüæ.J0Äô¤*$"Dâèà<ì&ܾä¶Zð´¸ôà(.&@î4ÜúÔô,üúÒȶΠôÊúðü.$40 èîÖüþø6ü¼âêðöìü ø."þìúî$"æöúôÜàÚÌÐÆÞú$>,ð¼æäüN&Tüþèþ ì þöæüðüþôìðôÌæè &&J0.þôâü ÄжàÒàäî6àØú.Þ0Jààèö2ôÊàÚìþôðü>ÜìîâüþüúæìÌÞê@¶þÔ06Ðîòð"þØúÚô(P.þü¬ ò$öäæîðö  ü ðü òàôêò (þüÐÐÖÖ $2ü Êìê ÜòèÔJVþúÚ88"üäòä.ÜîÞà( "îþÀÖö"."*àèÖØîT$ÜÞèÌ âòÜØÒúâ,  úüÊþü ðò¨âÒ&þüÐ êD,¾ðÐþðèæþÈDüÞ¸ä86(ÄîÖðÔôØð &äþæî0øöÞêîìö  *ÎàØêúüèòìòöøâòÆì6àÒ(ä ,& üúèþú þòúôâèÊþþ&(ôâòôæ.\ôÚÀä$èäþê" ü¼äÐ0ðòþô* "Üôìþ"J øÐâØæÀ"<(º6nÄ ÎFü:²ÜÐîBîºÜêâ èúâÌúêúîúâ (D8.Úþäôü2ÆêäîøüÌâ>ü øÈÞ@ö ö BöÂèôä$.âèúò(ÈæÖì îìØìä  "ìøî<Bô æ2þÖâÐì"$ðêîêÖìÖö:$ÒþÐ.&²úÌþîÔ ,ðÞääèì2ÚòÞ <üîúîØôðX B°ÊÒÐ>@Ô¾>è´üNH*äüàêÖîüÈÞÄòøô ö00êðÐ... ÎÚ2òø¸&.ô¸Öî, êðúü ôäÒðêì æäÐâÎàè$.ò Ô4*ü¸øàþ2Ú4ÜÆÖdäÆòØ "ú ú( ôôþúêòìÔÀÚÔþüÚÜ0þÌ,"Hx 8ҘΤ<6>ؾìøÎH Öô Ìøê < "¾ðÜê ô,Ü$,Böìä¾ÒÄ ðîðÄÜêÐFt(Äà€0V~JÚðô"¶âÜöêîÊúèÖðÐþ 2r".ääðæ:2P*ðö¬°´¤öôb ÞÌüÐþê ÚD>TXÔú¤ ,*þ è(øÖ¸þô*2˜òÂô &üHøþ¼¾ìì$F86ÔØ ÌØÊð*.æØ¸àÞêø& ðüè*&<î*(öè´üú&F ЮIJ,2"Ìäº".\Ú®4òF°ÚÚÄTb¾ÞˆôøLö* ð(Üäèú(þÔØæòôVþìÌêÒ¾j"(îÎØÆ´,d ¨öÖ ÞìR&8ÎôÜúðÔúÎòNÆì¬úþ 6**ô ìúàîæ>>dFÎæŠÊôDÖæöØäÖâú62<2$èè àê^ Ⱥ¶ôø2ÔÔØâRXüÐ ÌâØôJ68öÈÔÐÖ"è ÚâÖäì>&JæîæòÜÜú $úæÀöø" úìââÖâî6ôþäì æÞ d*¢œþìd$02¼bþÎØÄæfâÜÖÈòþ,>(LÆê”>.Xâ æÄÚ$´ÐÒôð ÜÐðærò,Ð* TN(˜úÐ2$8äè ¸æŽD8æìºÀØÚ (F&&Îì4"04ÂÎ6Àà€âÜbÔвæÒj.î4HFÌüú**0úôÜÎØÞø*îÜàÄøú(æø:êþN &°<ì.ؾâš *8æî¾ªäÔL<:$ø*öüàÜüè*.h"òààÔêÞü .ÚÚú2äø.þ&ÚüæÂÚÀÜþÞÚ @Øøæô&$ôVøÆàòêLFàÚâÈþ8îöìæÐêø ö Úðâ2&42þ® èìÞÚì: @ÂÔ¶´BôôüþÚ6 &þþþø îÚêØÖþðLþôÊ2ø ÞÌ (,ÜìÒäòú,"äʲÔâì*NêìæöÞêòþ2è,ø Öî D*¢Öªà4`ÖöäØâÖâ&6$6èúäü& 4øàÎÂÂþþ&*ü’ÒêÐ884Râþ² âJü(¶Ôàò BþúÀàäôö"&26øþ´âø2âòðüôâìÈ:âúøêü"ÔØ8NÀﻮ Tâîà8T&$¾ÈÄÞÔ ô&*ÒÞÒÚP@ "ØöæòÞøîöüâôèØîÂ2Hèìðäô(îæàþ",xþ²ÞòòþòÎöäþøð æèØü V(:ÚèäìÆèêÌê,Öä¼ (,*äüô.&îøòÚÚòÒÌ 2 ¼ÚØð"&:*"ÈÆÀð: 2, ®æìî þÎö öæúúÒÔX:>àøìÞBîöèà Üú ,,îìªââ $øöÜúäú "&ôä¶îâê,BêæÀ’ðÖT"üúöBîê 4"ÚÚÌÞ$âÈÒÔÜê*"$ (äêà²âÎ,ðèâê¾øø(\0´ôþòHÚ&:>&ÒÞâÞ .,ôþÞêÌÖâü.úøààèôþ,Fîö îööÚ(ðæÒæîìà äò¼â<F@@ÔüÎ &:°äøØîüü ú æÞèØøè64>þæ´æâ*">öüÐÌÔôÜâøÒì( Äöâ*  ðúðþðöì( àþäøîðêüî2*úØÎ²Øê 0äêÀî( $ôêúöÜöîÞø8H ÎîäØ*BÒÜNÒä¾Öäèü,.üþþ*0øìâôòêôÎäàÞüÆüì<*, òü "þàøú ôþòäà¸ÊÎÖTôøöêä.*R(ÒÐÊæ&ìäòúÔîîäðòÎ2 VÞòä&þî þð ØäÜðþþ úìöîü:¼Ôè&öþúÜâèøÞ"RðÞôôêö .þìÜøöòööäè6ô ô* öôòòàðôäìæèâðê( üøìÔðö  "îâÞîôø >48úäêîæüÜ0ôÜôêú îìþà$øððèîèúþâìøøüðøØæò$ Dòð 4@Øúòî¶äÂ&ò ÒìèðNæìôð ööòêîÖðîòìêð î6ø  ôúôäèâìòò Ü,êüú,úöÄðÜøÚ.üà¶äæ0þìâôÞæ .H ðþèôÖ2 èÞâæðúü ðúâî  îö ,þöþþìîìòÚ þøâôäêàØîäôþ6$< ì &. þèÚÜÜà òìàØèöú< þ $Þü0ÎäÄþü üò¶ìæúä6 0Þøü üþ øôäÚìîþ þðòð(,&žÌ¸æ4HäÜ®ÜÚþî(ô2úäàÜöæüâ òÈààô<üü8* ôøöæèÒôüòô àâÚØþ :&&òîöÜF ø üòÖòú ôìòôúØòèðöôôòþ þðâòüÞîøð"ÂèÄø$úúúþ öôîÚð òþìîêðöîìèöô( îîàÚö ô öüöèèôBöøìêî.îæøì:ØÂîä2 ØúØÚüæìø.øèÄþô ÒäÎîÔÚð" öúÆöô8,: àðè ìäúÞÔæÌöþúôø&>.6òøü äöä ÜÞÊêâîðüò6òü"0ìþêðèô  þæîÆÞæú8øâäæðú$(öîÒúêü$ööèäòæ üøÔàèüü öîôè.(4þ& âÐâìö&øìδÔà "þöÒ , ÜØÌÔêö:ÐúâþÚü0  îäúðöâèüÞ ðòðêöú6$*úîêâþü8*âèØÊîö ìþæäæêî, êôðö<> æêìøàøâæüðìÊææúúö(4N.üèòÞæäüðæäÔâôþ þü"öJ ƺøî4äâÚØÚ úü<4(öìÔÈø* êäæâêüþü&ÞüîØ ôúäðâþø úøÞðê " êìäÞâøþ(ìòäüüèú>àâ¾àøðú ô ôàêú üôòúð2þöúòð Öî&ÚØäÔ", öÒôþúøüúò îâÄÖÖæâ&èþü ð82"ÜîØøòÚàÒÞðôÞ à 2 ðîðúöðòæÜØþþÜüö& úêðê üôöîìöü î ö*àôê" îþúèôòèúöÌàæÜðöô6ê$8îÚ ø ðøºäÜúîþþø20øì  âìüðüÌæØúøþø þò0, ôôêÜþüæÂâHÌô.&äÔìÞüèüâî,üþüèôðîêàâêøæ,$ÚìüL*ðæø6üøÜÞàØðþî úêüÐ &8ØÖö( FòîêöæÞîÔê þ òööþ<*úÖ êæ*@úððÞú øèôôüøìøÒôò 6 ÜòþÌè®ô *ìêêðäôø&îþþòøÞÜêìêüÔ ø ì ø "ôîÖ èþÂôêàøò üú$ ü$$øôâèîü& úàò"üøúôäþòþ Êúâ$öòüîüêîüìüèöÐ4$ìôHÌè òÎÞðüèêкê2  öPìÊþ@öôÚšà0 úÈèÞøàøü&ü üþÊîÔ âèìÚJü,ÖøúÜîìB Êêâæà8êî îÜøÊâÆô$ $þæ è0þðÐìèÜ øàäîúò2 öü&((ðÚðüäþÈÞàØü êØ úüê8 â&$öüîêÚÜà úþàðè æðâàü<ÜÒøæ6êÈ þ øüâÒ þ6ð$ ü ööìüöúòø ô úüâèöÐüøèöôüüþòòòøø& 0 ìôöü ø êøúþøÔôè(þ æüþô$ìÚò  ìÜúìàô¼øúúþþèø& ðþÎ$þüÔæÞèþôþüöüàô4 øîúøôìöäö¾&þê úFêäîþð., üÖìÞÖÜîþ,ü ìØúê*&&(òæô&æ$üèÔàæææ ú äüúþ *öøøò üâîìîøðêøööò&"" èììÚúþìòâîþ ú ðúÎ. úþúðþîþüøüðþöþ îüØÞø"ô øüÞ0þÊÚÚìÐøä,Ìþø<<*Þ ¸*NÒðÌ´*öBâ¨ìüúLøðÎþÖ(ü Îþ*"úìÚð<øúèêúðÞ "ØúÎ  üúÚþ  þ0 òüÄüöôèÚøèüîòü2ìööêìÄèú4ÚôÚ úøæø$äøÚôöêööôô  òê("ú Êèîð²âØöþöþ  î$þØöä. "àøðäüìôÔôú ðìþò þÔ" 6þôòþöàä®Öàþ ø ÜÜøî$>"êööÞúèôäÜèîðô$âú"ü üÈþîþâîÚü àþêü,6ðäêÎ (@ØÀè8Îúìô6ø èÆöÎ,"èþäèúþ æþúööüàúôúôøâü$üüúòö@þÚòÚîàþºêìöúê ö&6&êþ*ðÔêÖîààîÖêê ô ü Ôü.8øªêâò4þüòÔòî B4ØÜòXôèÂöÖþàöòü*"þ þ&ìüÊöþþæúê øøô$4àúæ.ð²Úî0 öæôö  æþæüþ.Äî " úìôâøüþ ôü ö æâôêä< HÜäÚÞîøþ&Èöà*0àêÜàøô$úîôèôÒ,üÚÀôÖ4&(8Úâ&.úøüðþøþôæþòþúôøìäèî.$ þ Ôö2 ,ÈÔÈâäàöþôüôì >"4 Üúö òðÂîæúü úøÞöðäèî* Ö"&öÎêÄÖÖøæüôÌ ìæDôìøþúüðÜâÞþäüî2ôàîþø Üê ü äàâÌ&<æúÚü þò8ü "àòÒúúöüðÎö 2 "ÜêêØþÚÞÚú øüìðæâîöÖø*öôòüêþ òúÐâê4"êöúèöøÒúF þêü.ú¼òêøôôüþìøò4.îþÚèö8 þÌì "ìÎÞüæ@äÆð<îèðäú"*îöÜöîðöþÞþöþòäòTüâÄ$ :6$ÞÜèÞðöæêôîôîúò "þ  øäêôæðê  òþÚæôè üúþ$þèæüü& üøúú * æòèúØú."üøìøìä öüôøöðì "æúÞê*üÈØâò " Úðæþþ üöðúêöàüþ 0Úôìþüöèðêèö4 îðüúüüÌöâêæÈú öÚ ø&üüøàìÐú ìêüD øè$üöÞîÔö2âÜæÜöîúø ø "*< ôîâê ôòÌܲþüüæüì$$þ  êÞÞÔöòþúþðüà òîö < öæäæâ ,èöÎüìôìöööúüúþüöüðæøöÞæöøüÚþúôìøôüðôÜÞÄØêþ(2*þìøôø "Ôðèüôöìôîâòè òè4"$úúäôøäöìîöüàìøöøúðð öÔàÐøô$ üêÞòæ ääâÚØêþ$$ ò ( úüöøúòðîæàÚêðüî 0 þ$ ú üìôôü ðîäàêÜ$öú,ìèÖÒü" øþöòüúüø ôðæøøBöÈÜö Èü òúêàôò ìþ4ÞèÔôþîúèöÎüþ Üê:  äôØöòîöêìêèþü  úþ$"&ò þ2 öîêàÞêâ þðèøòö $îüèäþú .èôäøú öøøø þæäÞòüú*òàø$ üö2 Êä¶ì,ÎÚÔöþ úöøþàîöèÖþô ìúöøúøúø ìøîø  öîöüúþöúÚäîð üÞúòüöÞèô þü.àøöø@ ìøôîôôúüøþòðèòüüüö þúðøææðôôôìððæö  "$òô  þôøøöúî üüÞòò üòúððòÜø"ì $"úþôðööüþþüÚäÖ äüä $2üþîòöêôäÔêØúîúþ  öøöòüüúø øüòæôìô,"èîØè üüìúþ êúðþüò èòâø üþþøþð .øòÜúôìèèîòö  âø &þòöâêèêòðøô  ò üðø ôìêÔâäþ þè *$(ðþäôô úÞôÞÞöô4*þøðäôø üèîòòþòè* úþ,öÒüàòÖðàüö"øüèæ > 4ôüê ,ðþÌÜÞÎæØòü  ÚîÞ*L**þþüèîâòúêðàê$øøø& úöøììôöüêö* ä þ$*âôðìæúäüÜèê& þøúøôð¾ÖÐüü ò &6àÜòöúÒâââú ð ü  $òôÜÜðêèðìäøô üþ  üþðòüøþöüàèìò & üììØôòôðøúèú 4úü0ØæâÚöÎìÔì þøØ PL""öððæüêìÚÔÔèìúüöôøæòîêäòÞîú ò "úøü 8öèìêðþüäèìð  òüøâðÔ*úèþðúú  æôâ ìüäøúôèðø ðìæöâîìþôÊôì&4è $êØúöâêØÜèâ " î(&("öæîìøòèøöòþÖöê  þþ ô  Þêâîôø  ðüþ øúÞêêþøúöüæ "þüþþþüòÜàÖòöþøúø &.Üþìþðêðâ þüúøêðôö$þ ò þøúô ìôøú þþø úöàöðþüþüþ  öþä ìüêúêôêøþ*îìððòæöêîööò  üØðêþüþêðØþøüü   ôúàüþðþöüüòìêúü òøøòúðþü øòîüÜúüþæøöèèÚìú6$ üúæüúêôøüþêüòöúîüäòö$*ú&ö Üôüøòþô àô øöþ 0 êòøøìü øôú &üæØ¼þòüÊòðþòö üôúîþüðôðâòüâöæþ üôðöîøìæò öæîØü*ô æâÚÒäàòøäöØ    "üþôôúîöòþÖâàì*Ø öäòüìöü ä*Þö¾ö JôÔâ öúöàøîòäþì 8æþ äúÎâöæø þüâúðøöü ðöüü ìüè ðôæö àôðþ$þè úêò êôôúôâòÔäìÞôòþ æúþöÚöôúÎöü *",(ìÐúò êöðàò þèì 0èÖüì òüøøðêöüøêøøþ* ü îäøú òìöøöîþÄìø( ôúæòöø ìøþ$òîæÔòîü âàôâ æèì  ìúöìðÚèèôöâþ(üîô"*ê þôúæôøþöøôîøô æüö þüøìöèèþüúîüüúðæÖðò &(ðôÌþ@ê Êîò$øúà$"òþÖúüøúü""øöøâúÖøàú>þðøøæêðòêþþ"üæêØ  üúôøøúþþæöÖ ôúþú ôþþòøüæèòö úþêîîú æôú&þøàÚèÜ, $þðîâþööôöø øøö(ôêúî öúöþ îöîðþøöþ  þôü þøø ôðìÞæîúè  þôúöþ úþúìöüâþö  üúîîêêâ öäþ  üü úôöêòäââúôì ðüðúøøîòÞîúúìøòüî êþúüôúîôöäöêþôøøæüú úöøìòðøòþâöú øô øúê þ  üúööðòþðøøö  üìöüîüîì$ úüúøþðúèöúþôüèöþ øúîî "Üæèäú þøþ þøæøîòüâðôò ø  ú úüúêðæøúèøòúôú *   þøîüìþâôøòþø þòììüúþ öðþöô öÜðÔüâ&úÔúî ò úþæøþüäòÜöþäüôúüøü äöòþþþòþø þ  ðøèúòðêðöî þúøúþôò øôôüøòöþòþ  èúü öúèöööüüþöðøø òüøúîþøäöà*üæú * üòèüêòôøêòÚüþ þü  þè䨸úúöòô  îîøîèðüôìü  úê & èÜâÒìþüØøÞò öú "$$ þþüüüäîÜôôôú   þîðîüöô üüìÜôî  üôúäúøôòôúøô"$ö2øÚôêð þøæôâöøü  öþòþ ôôðà$øüüôøüúòüþêäöò,*þþîúúÌæÌü "ôâþô  úþúüþ üúâòÔ "òàô þèààäþþðüú öú"øüòþ ÞèØêîòþü ü(òþäúäòäèðþîìöìü   öæþêòôäþîòÞîöøþúê üäüüøèöìòþ ìîÜþþôþüðØäÒö ( âð úúüêþú öòèÞæèöü $.ööúþ úøþðþÐæÒúèøîüöøôôîèàèòöúþøô òøè úüúôöú úþîüþ þäþúèæöìøþú  úúþÚöüÚîðê ôþö $ $ü ê2îü̾ä0üþÌöîô&$öàî$ úüúôøèòðì ðöú æ* úÎìÔ ððôêúèîþú ü þ ü(æöÖþ îþìèöèüöîøöö   " þðþøþôîêðôìîò êúîþøààâòìæüþôþò øþþ ú äòàþèìè 2 ìööòúôòöòøîòæöþúü"&üúö $øúöðúöþìôâæþø"äòþ$þ "þþööâðìø ü èúþìì þØô þèîö2îþêþüîêþô  ÚêàòðèæòþüøüöüòìþòòøÎøîäúèü     ôþÖæÖÖúàþàØêÖ(ö" 6 êòøô4øàúØòêÒÞÞÒ4F(þÚ $øìÞîúðüæþþäð(.ðüòèüäÊþöäêæÎþ&. î  îòô"øâþ:îþÎäúòþòþðúæ öê  üöììøèôðòôþüîööî**ú ÌðLúâîîöäîôþ þòþð öúôúìþðüøÀ ì2þüð þþþüîôöÞôÚò @ öâú&4"0Þ îüìÞîÜúèúÚòúþ.úìþ$ì öøêþöüàüö  îàðÞ  ò öø ðúàüÜ ,8 ðÖôâ úööØôàôðòìê ,ðøüöþ úèò  ôüðúöüüüòìÞîþüöòêþø .þúâÚîèôüöþü  üöúð öúêööö  êúôèú øÚìööðü ú  ììÒÊì ôÄöîüþ ,  þ þöþöîöøòþÚúðäöÖ .îæö$ðöþèòììÆòð"êâúèöô,èèöð& üîîðêü ðöèüÜà ( Þöðþ$*âæöðð  äúÎ 4îÜøÜú Òü"ôÞüì( þÜüòøèæøäè  þðúð  üòþü îøüèö  îæèÞúþþøþ ø " èüæòþèèèàæôðôö$4þüøú öàöìüòöîúÞâèêúò$þØüì$æö úüøòúðü ôþúòØðèþ.üú  êîÞòúþüè üÚøâ0þìäöþþüøüü ôø&þþâÖò$þüæèôØîúü  ü (öäÐøÜ úÊø $ðÐÞöø" üüüþ öîøâøúòúþöúôöþ öúìêþþ üìðàúöö þôèþô àòÜöðÖòôðö$ êöðüüòðôðøú üøøöôèüøúâÊúêìþ  öøîôþþöúìúòôðþúþüüþüæîòøøÜöÖ(úæôêþÜ èöìúúú öâüìèôöü þúø ôèþ  æìÖîøøòâêðúþöú  þúüöììôîøò øþ 0 øö æòÜâêàðôô"òþÜÞþ:(èþèòúìþúîþôþâúêøâöâúîîúô úþ ôîìîòþüôúêúúöî  úîòò þüøöúü ú þøöôìþòôôôþ äîââöôð ìúôöðøôø þüðàîò   úü ü ú  þþÔîèþ þæêÔôöþü &þöúôþüþþöèàæôö*òüô$,øÞîæðööúþòêî ìîüþôÞúôôôì ø øæöúþôøèîüøîêøòü úüüøþþ üúìöö úþøøâòèü    øþôæ îðàÜòð öúüþ   îúÞôôöîöð îòðü ìîÂàêôþ   úøôÜèêìü äæêîôò  ôîàÜðò öòîè þüì òòàþðüþöòðîòêþ  øøöî ü ìö öòÚìðú  ö öôôàþüüìüêþîîîøîøþòÞðèþþüü  ,ø"*üþÞàîê âèÐäðð   úöüöúöüôøþ üøòðúü  öììîöøþðöòü þüüüòìîæøøìööò üòüöþþìôêøþðøþò "þüþôþêêìêöüêæþô  üüþò  üö&òòÞúú òúôú øþâøúüøîöôþüúúîòð "êöôôäòÚòüú  þü êôîðöðöìòüöêö øøôüüðìþöüúþ üþîôøööôðòòøüìúð(ðæìîø úüìðúöþþìôøöú òü øþ þ êôîòîøþ üþ ê öö òðÐêîüòîäèðø úð îøþúþþþþøúöúðöúü ü þðþø øððèúø  ôúôúòôþüúúìøî . ìúüöâþöþæøöøúüôúöü  êòàò  ððêæüöìòü ðúîîüú üôòòúøøÜîøòðââüö ôøüø âêôð øþìúþü ú þòöøúþôúþüüìúöøôøúþú øüêþ &øüúöìèüðüöîòüìò öòòêþúòòúôø  úþðüüþþúþòö*òðäÜèêü ø òúúôâ& úòúð ôøææþô þôúú þôòôîþòð üüø þðøäòúèòðîôöþü üøâôôìþ ôþüþ" ððöòøþøòôòö öêð( òöþôøôþöúü ôôòúøôêâööôøüüôþô þþü  øôîêôö$ øðøúüøøþúðþð ü . þøòìôæîîìðöøþôø  øú òþúþ øø òòôæ øúôðòøøúúøòþ ø    üòöèìèîúòüèúøü ö&æö ìøòòþøüþþîöòàþ(äúìøþþòîæâìîüüø úöþøüþôþìú òô üôüüú ðìþúîîòæ ð  úæîöôôþääðîü   ôøîúüêøÜúüú êìö"øàø üúöüøþ þöúðôúôøúüîööèøúú úöðüþúúêüüþôþüøî àüì þöôüôü ôøöèüúêüì , úøðøÜþþöäðôîüøþ  üüþ øøúþôöôòü úþîðü üøöðúöúüøþöþ &øòþìôààúð âöêú $ò òö òöàþúôöêôîøðü øøøþðúôøòøøøúöòìüüâþî & àðæð øþú ôô æôÊìú,úâþæ æúøö*òî êîîòòîüøú òêú"ööøþþúðèúÞèèð þêöøð $öîøö ð øþþèþòøüèøàäôð öö þ üüöú øüêØòâúÔúö&ô  "òæîØôúøîüÜÌè&øÎú: ,öøø0ôÎüè Üòððèæ "ðîúöôøòúþðîø ,âøðúúüîèòìð èúòú êòöôôæøêúúø úöúî þîöþ"öÌèðþØþþ( þêðìüðêôàòìü&üüàúîÜú.ìØÞð üüæ&øâô@àúæþüìêðÚúôø*ê öæÜîÔèþöüâþú öúøîôüü òüøúìôþôðøüÚðîú0 &äüÔ(ôîâü$òþØþþøÞþêþêüøþ úøü (êäêØ ôöÜúä$îþðòþîÞ (ðêúø üòúØúöø æêø ö ôø Üîôêþ úÜúèúúöö þüòÜäÞîðöþþ ü þÒâààúìê ø úôúð ôòòîúôüþþðôòð þ ò òþðê$êü*úèäöâ  Ú ôöØèòò,îòîøòìüòæ$úðâ òòúÜþöäàúì ò*& üüøúððìêèèèìòöü þðþ þúöðüøþúöþøü öìøôèòèìüìüøú( $äôÒüòòäöîðþüê $æöôþÜôôü úúøúö  öôþü úìôöðúòúþöþüðüò  þòú   öòôìþøþðüôúüêü þøúþüþòðúþ  øôîìøôüüöþþøú îôö òòîâôòä êüè " ðü üöþúîü ðüðþþúþþþ úøþüþþð üôìüðÜøæü òòúì  øþ øþüìøìúúþôøäü    ô üúîèêäòøüúþüøüþ ôøúþ ôúüúþüúþ ðüþöòþô êüîüúòúê   öþþöøðòúúþø  þþþ úòòþúâþòôêîøò îþòü  øîüúþ îôæúþþüø øþþ úðü þöúôööðþúðöêîþôüü" þü øöþøøîøøö ôîöò ü ú üòðôêðþìüüööøøô  øèôî øäôúú þôúüüôö òþú$ìüþ ôúêöøúþüøúþþ öú( þ üþðúÚöøþâöâîøúþÜ (òöø(þ îêôþüüêþ úäòøêþþúü ôìäîîüìðòöîúä ìò"úöè üþð ôúòü öô üüøêüöøâôôø  øúêöúüòþôòüô ôü üþìòæèþ  ìöìøüþèøööüêôðöò þððøüúúäüôú äþ*øâþöòúøøòüðöþþôüúþðþ üþ ðúôþúööúôüþüøüüøú üööøôúøòøèøøüêþð   úüü òú ôøþøüòèúìîþôþúþðþìüþöìüþ úæ þúöúööèøòúú ü ôìðòðøâüø òäò$  úþüøüüðüðüü ìöðòø  ü úüòîöîöüúüæüôþððþøú  öþðøöúæäøôþþüúìüø&(øþúòúþìþèüàòæö þþ  ôòîèþôþìúæö  öþüüüöôöúôôâöö þøôððöúþþúòôôüúøòîêèêøôþöþ    þöþôôüôøúøø öú ðúöúüþ úüþôøèöö þþüü þþþôöüþäþú & ìööøüúôüðüþöúþúþ þòðüì þ ðêôèúøúú  ú  þ üüöòüþþþþöüöþòüúø îúô øúúü øøîôöúüþúôþö òþæþþøøôþüúøüììøðüþö þü øöøúþþöüîö øòúò ööèöøþþþöèðâöúúôþú úþæèþò øüþî öþò öøìøþúüìäòî þþ úüðððøþüüüü øþöú   üüþþøòöþðþþêþò îøööøô ôòüþð  úþöüü ôððî öøîú  ôø êöôôüöúþúòöîøþ þþ  øøôøþøúøúøúôøô  þ þöôþôøöðøðøþø þüúøúüþôöôüþþøüøüðøòúøìøþü þø øþøúòöþøúüü  þ  úööôüüüøúöðöìôôü ðþúüøðöðôüüüü úøüìøúøðôôðü úòôîøüúðúü ôìò*ðüî þ úúúü  þþøüþ úðöîüüüþîöúúþøôöøüüüøú üøúøþöüöüøúþîþö  úþúüüöøðüþüú üüôúòøþþöü öüöúðîôîôüò þ þøøôôþúôøîòöþþþþþþüúöðþö èôôüòþþþ ôøüú øþòúúðüìøúþú øúúþöüþþþúüôþþ îøø  üúúþ úôòîîøþ  þúþ üþòîîìúþ øøôøôþü òøôüüîþîöüôôþ  öþðöøö òðþúúþúðöðôúþöþôöôþúòüüþþþüúþöþúøúþöþüúúüü üú öúúþðøþôîòðþü  þüúôøôþðøðüþþþ  ðôèìþøúüúöüú  þôúúúüôúöüøþôú öþüúîüö úúþþüþöúêþøîøìúþ úîîôîøø  üüôøöîðòö  öööü öüüü üôüòøö þúðòîúüüö ôúôôôúöòúúüþøððöô üþøø úúöòúüøøþ üüþúøþüúúöþîôìüøüþø  úøúøþôö ö  ø ôæòæôúôîüøþþüúöðöôøúþüþòþ úêôüüþø úøîðúþúöðöì ô þþúò  öîøö úüøüþþúööøòú æöäúþ þîøðü ôôôüúòüüþ ôììîöþúþøü þðòöúþúøæìðö"øþúþ øòúøþøöúþøð öüúúúü øøôøôúþþüúþî úúúø úööôþþ úúøôúúöüø þüøîøòúú þ üöôöøü úüþòúîüöâôê þúþ þþü üüðòøòüøüþòúôþ ôü úôúüüúþîööü  øöèôúúøþö üþæðüþ ôúðúþ  üúòúüüöúôüöúþ øþøüþøôþöúø ôò îöðôþüüøôòøü þöøôþ öúúøüøúøüþ üöòôìþþòüîøöü úþþü úöþüþ øîþþ îöòîþ üòþ þþþüøðöêîüúþìþþþôþüòþòüúü þþüþþúþüúúúúþþþþþü úüøööôöúüþüü þþþüøöôúøþö ìüô þ úòþüþöþøþüúò þøðøêô þþúø  üúþ ööúæôêø ðäþúúøöþøþúúöòþ  îòîô þüüüþ   öüøþúøööüúøúôö ôøøø þøøðþþ üüôþþ øþüøøúþüüüúøþüüúüúüþþúþþ úúøþøúþü òþ  üôþüòòîîþþüüúúøþüúüøúøþü  úüúþþø ðúäîüöúúüò øþþþîôæêüü  þüü üüþü øüðúüüøü þüööüòúþþüøüþöòú öüò  öüìø üþôööôþîúúôøæøúüüøüúþþ üôúüþúîþ úþüþþþôôðòîöü þô þüüþþúüôúþþþøüü öüøöüúþøúúúüøøôöúü  øþüúüüþþþüüúüúúþþ úü üüúüþüüüô òöüøúüúúþúüð þþþðþøúôðøøú þþ òúøúúþüüôü þ  þüòüúøöúúþúüöþ øö þüþüöüúøüòþüþøþúúþøúþüþøúúþü þúúüü ø üöúøþöøöú üøêúö  þìúü úøúþðúøöôþüþüþôþ úðøòúøøüþþúúü úúðöþúþøþòööþü øüøøþ üøüö þúþþþüüüþ üøöòüþ úúøôøøúüþúîøôþüþþúþþþþ üü úþôþüúúøú øøðøüüüúþúüþþ üúþ øúòôüüüþþúüúôúúúüþòüþú üøøôþþöôòô ìúò øüþøþúþüüúðôòöþ ö úøþôúøúþüþþüúúþ üþöþúúúúúüú þúôþ úþþöôþøþúüþ  öþú úúîöøüüüþüôøþü ü üüòøü  þüúôôúôúþö üþøúþþøöôüøüþü üøüú  öøöþ öòîôüúúúôþþ þøüüüôüþü  þô ôøìúøüþøüüü øöüúþþþþöøòþþúôþüüøþþ öüüöòüöøþúðþüôúöþþþ üþþüòúöú þüöòîúôü ìü úöþúðòòî öúúü üü öüîüøøþøþ øöö ìîìðüü  þ øøøþìüúþúøêòðôúøþìüöþúø öþþøðøî úöøøô úú ðøôôîþüþ üú þþðüúþòöúøøúúþöúòüò öþôöü üö úüîîüôþðøøðþö öòúìüôúúüøöîúðü òþþ üøüþúúøúøöôâø òøúò ìð ôþúüüöþþþøøðôööþöþìø úÞúøþôâöè  øøüþ  þþø úòúþðèúòúúøðìøòþöþþôüþöú þþüîüèüê øðú ôöüô üüòúüøøüüìôúøú úöøòþöúøðúæöþþ þêöêþ üöþøøü òø þþøìøüôþ øÞô þîüúø þöüøüúøüúü úìôîòþ úúú þøô   üööüòþþüöúüöþúüøðú  ðøøò ôêòüöò øèò ôþîüüøúüüþòüòþþü úæøê üüòè öüüòúþòþþ þúþúøîúðúöðöüøúþüþîü øøúòø úðüþüöþü øþðøþü öüîôþöüüô  øêøúòúìüþ òüüôúþèúîúøèþ úúþúú úøúüþ öêöòüüú öðþüöþüú úúöüüþþþþþúúüþô öìöêööþ üúöüôþþþòððìöüþþö úöøðüüþþúìøò þô  þöööüúþþòøøüúüúþîøôü üþþô þüúöþúúüôøúüþöü úüúøþîúððúðöü  úööôúþþþöüþþöôððúþþþ þ þüúôúòòøú þ òðÚôð øøöúôúüþôüòúþøöü þøøöüøþøúúøú üøþöüüúìúø üúüü þ þþþò þþôöúøúþúøöþôø üòðúü  öüþ üúúøôöúü ôîöòüþþöþüôøööüþþøðþüðöî  üþúúþ þþüúøöøòöþ þöüøúúüøþüøüêøò ðüøúøøøþ øòôòøüüüþøööòþ  þôðöò  þöòøøøòþôöðúö  ôòòøúðòîüþü   þüúôöøúøüêøú øüöüöúüöþúþ øþøþúüüøüüú üúöþú  þúþþøöøôú üöþüúúþúþðüî øöøøþ òööúúþðþøìø üêøð üôþöüü  üöüòøöúþøü þþôôüúüþþø îøø üúôøøþüþþöøöøüþòøúþôþúøüöüþþþþøüþôøüþúöòòôøþüþô þü òüòôöðþ  úúøöþúöüöøúúöþöú þüúøúüþþüüúôúø üþúôêôòüþþöøþú  úúøô  þúüþúôúúø  þôööø øîüôþþüüüüøüøþþþöúúþþüú øöîîøü  üööîþ  üöþöøþþþüþüþ  úþþ þþüþúøüüøöþþüúøöþ úúòô øöüüüúøøþøúöüü úúúúþ üðôöü úþúöþøþòúô" ðöþú üüöòüú üüøúøþ üúøúöôòòúüþüþø ôúúúþþøôööþþþüü úôþöüîøøø ôô  ü  öîúø þúðú üüúúþþüøôôîþ  üòôðþþ   øøøúþüüüöþøü  üüôþ  øþôîôðúøðöôþ þöüüüúøòøþúüúþø üööòþüüüúöþü ôòðöø øôøú þúòúü þøüòüòòþö ðúô üôúöþ öòîôöþþúøúü  þôþþ  üþúøüþøþôü þüîòøúôøôø üþþ  ðîììøüüúüü úúüúüþôþüúööòúü þüúþ üþüìöðôòþ þöúþþúþþúüøþîöþ øþö øôòòþþ üøøúüúüþüôèòð üúúúööööúü  þü ôöøøþ þþøöøøúþþúþþþþöþöþ øþüøúìøúþ øúöîöòþ üþüþôîìð  þúööþþ þþðüþüôúøôôêîöú úðüôþü   úüúþøúæøøü üþ  þüüøüþüü þþøôþöþúú þþöøþþüüøüöøúúúü úüüþüöôøöþ þúüþüúòôòôöþ þüþü þþúüþøøîðøôúüþø ü  üøîúø úüøþúøüþú þôþþ øúþþþøöþþþüüòöðöüþúø  þþ øþööðîúúþ øôüøúøüòîúøöúôø þúþúú úúúöüü  ìòôö üúüøþü þüööúü üüþúþòþ þø úþúþþþþþþüüúüúþö øôüþöúôüþþøøøúþþþúòøøúöôþþ üüððøö òøìøþþþ  úþúþúôøöþüüøüþüüþøþüüþøþøúöðüúüøþüüü üþöüþüüüþþþþþúúöüüüüþü þüòøøüþþþüþúþþ üôúøüþø üöúøüþüúüöþüþþúþöþìðþþ öüòøúþøöþøþ øøúø þúøþüøþöúþþ    þþþþøúöúôøòüüú þøøþ þøú úúôøüüüøúüüøúüööüøþüøþüþþú þøúô þþüþþþúøþþþþøúüüøúøüüúøþþþ  üüøúúúþþüüúúüúþþüúþúþúþö øúúúþüúüþþþ þúüü þúòôôöüüþþôþüþþ þüøúöúþöü öøöô öü ôþòúøúúøþöüøú þúþú þüüøþöüúüúü üôüúþúüþþøöúüúú úúüþúüøúþúø üúúüüþüúüúü þþüúþþ øîúôþþòôòîþþ þøöôþöü üüú üþòôþþúüöþüþüüúúöòúü üþú þþþúøúúþþúþþþúüöøþ úþüöüþòìþøøþþþüþöøþþþþüüøüüþüþüúþþøüö  ôöúú  þþúøöôúúþúþøüøøü þþþúüøúøúþúúúöôøööþöþþú þöþþúüü þúúøþþþüþüþüøüúøøòþü  ø üøøööüúþþü ôúþü öøþøüîöøüüúöúúüþþúþüþþþúüþþþþü øüúöþþüòôðöü þþüú úþööþøþúþôþþøø üþüþøüþüþþøüúüüþþ þüööúöþþúøþöôöòüþþôúòòþ øúø ôøøòôüêôþü þþòòööþúúüú þôüöúúüøúþþþþüüúüúüúúþþ  úúòøúúöúöúúøþþ  þþøüþþúþúü þþðþúþúþþþ þöøúú üþööüü þ úþøüîúôþþþþþþüòúøþüþüþ þüüþøüþüþþüúüúüþþþúüúþüúøúüüüþþþþ úüüþþþþþþüþøøöôþþüüüüúöòðòôú þúþúúüþøöúøúüúþþ  üúþøöèôöþ þþüüöôòöú    þöþøúúðôôö þöþúþþüþþþüþüþ üîôîú þüþüþüüúþöøþüøþø þøúúúþúöúöúüüüøüö þþþúúøüøúúþüüôüøþøüôüþþüüúøúô  þúþø üü üþüúüüúöþü þüüøòôòòøøþþþ þüúøúöúúþþþþúþþþüþüøøú  øöþ øúæøøüú þþþþüþúøúøüüüüþúúøþüüþøôòôøü ööìöøüþöþø üúüòúú ôüþþúüþþöþø ôôüúúúôüøúüòúøü þ ôöøööüööþüüúüüüøúüþþüþþ òúîüøþüøþúøþþúüöþüüôúöüþüþ úúööüúþ úúòþüþüþüðþôøòþøôü  þúòüöüüþøôúø  üüüøüøþúüüþþþúò  þüøöþüþðúøþþüöúøü îøðú þüþô þúöþúøúü úþøö øüøúüøøôúúúþøüúøþøþü  üüøüøøþúüüúúúüø üþüúòøøüúþøúþøþøú öþöøþøøüúþüüüþüþüþ øþøþþúüþúüþüþòþôþö þüöüêòøöúþ üüü üþþüúôúúüüþüþþþþüüüþþþüøüøüþ þþúüúüüüþþúøôüú  üüüööêúúøøúþúúþöúüúþ  úúþüúöòúöüüþþþüüþüþúüüúþúþþþþüúøüþþüúüú øúúüþþþþüúøøü þþ øòøôôúîøþ þüúöþøþúþöüü øüú  üþòüúøþøüúüþüöøúüþþüüúüúüþþþüþüþþþüüöüüüø úüþüüüúüüôöúø  üòþþþ üøüþüöþúþúüüüüþúú  úüöþþöøôöøø þúúúøüøüþüþöööú þüþüþøöøöüþüüüúþüøüú þþúø øðöð úöúþ   üüþøúøøúþúúþüüþöúþþüþúþþþþþüþþþþüüüüþþüþþþþþþúþþþüøúþøüúüøþøþúüüüþþþþþöøøüþþøþüüüüüþþüþþþþþ þþþôþüúü øþüüöüúúøþþúüøøþþ þüüüüúúüþüüþþþüüþüüòøüþøöúøþú üüúüþþüüüúþüþþþüüþúþ úúúö þöþþüúüúþüúöüøúüþüüþþüüüüþþüþ üôöþøüþúöþüþþüþþúúüúúþþüþþüú úþþüôüòøúüüþòþ   üþúú þþþüüúöúúþüöüüüüþþþüöüöü øúúú þþüüüøþþüüþúüúú üüúúüþúüúþ þþüö þüþøþþöüüþþúþúüöúúú úúüþþúüöþüþüüþþþþþþøüüþþúþüþþþþþöüøüþüüüþ  þúþúüúúþþþþþþþúþþøþþúðú öþüþþøöþø ü þüüþþþþøøüüþþúúþþþþúüúþ þþþþüþúúþôöüüþüþ üþüüüüööøúþþ øþüüþúøüúþþüþúú úü üôþøöøøú  úþþüüþüúþüüþüüþöúøúþüþúþüüüüþþüüúüþþþ þòúøþüúþòüøþüø þüþþüþþüþþþüþ úþþúüüøþúúþúú úüþøúþöþüþþüúþúþþþþþøúöøþþþøþüþþþþþþüüþúúôþüþüþþüüþüöúþüþüü üþþþöüøüüô úôþþúüü øþüüüþøþüþüþþþøúþö  úö úúþúþþüüøþüüþüþþüúþôúþüþþúüüþþþøúþüöüö üøþøúü øúþøþþüúþüüöþúøþüüüþüüþþüþüþþþþþþþþúþüþüþüüüþü þøøüôúþþ úþúüþþüüþüþþúüüþþþþþüúþþüþþþþþþüþüþüþüþþþüúúþúúþúþüþüþ þú úþüøþþþþþþþúþüþúüþúþúüþüþúþþöþüüþþüüüüüüþþþúþþüüþþüþüüþúþúþþþþúþüüþüþþþþþüþþþþþüþúüüüúþøüöü ü úüüþüþüþúþ þúþþþþü úþöøþúüþþþþþþúþüþüüüü üþüüþüúþþþþþþüüüüþþþþüüþþüþþþúúþüüþþøüþúúþüþþüüøüüþþþüþþþþþüþþþþøþøüúüþþüúþúþüüþþüþþþüþþþüþüþøüöúøþ üþþþþüüüþþþþþüþüþþüüúüþþþþüþþüþþüüüúüþþþþøüþúúþúüüþþúúüþþüþþþüþüüþþþþþþþþüþþüþþþþüþþþþþþþþþúüþþüþþþüüüüþüþüüþþþþþþúþüüüþüüüþþúþüþüþþþúþþþüþþþüüþüþþþþþþüþúþüþþüþþþþþüþüüúþþþþþþüþúþþþüþüþþþüþþþþþþþþþüþþþþþþþþþüþþþúþüþþþþþþþþþþüþþþúþþþþþþüþþþúþüþþþþüþþþþþþüøúøüþüüþþüüúúúþþøüüþþþþþþþþþþþþüüúúþþþþúüüüüþþüþþþþþüúþþþþþþúúúüþþüþüþþþþüþþþþþúþþþøþüþþþüþüúøöúüþüþþúüúüþþþþþþþþþþþþþúüþþúþþþþþþþþþþüúþþþüþüþüüüþþüþþüúþüþüþüüþüþúþþþþþüþþþþþþþþþüþþþüüøøüþþþþüøüþþüþüþþþþúúøúüþþþþúüüüúøþþüþþüþüþüþþþþþúüþþþüþþþþþþüþúþþþþþþüþþþþúþþþþþúüþþþüüüþþþúüþþþþþþüüþþþüþþüþþþþþþþþþüüüþüüþüüúþþþúþþþþüþþþüþþüþþþþüþþúþþþþþüþþþüþþþþþþþüúþþþþüþþüþþüøüüþþúþúüúþþþþúþþþþüþüþþüþþþüúüúþþþþþþüþþþøüúþþþüþüþüüþþüúüüþþüüüüþúþþþþþþþþüüþþþþüüüþüþüþþþþþþüþþþþþüüüüüþüþüüüþüþþüüþþüþüüúþüþüüüüþúþþþüþúþþþüþüþþþúþúþþþüþþþüþþþþþüþþüøüüüþþþþþþþþþþþþþüþþþþþüþúüüüþþþþüþþþþþþþþüüþþüüüüþþüüþþþþþþúþüþüþþþüþþþþüþúþþüþüþþúüþüþþþþþüþüþþüþþþüüüþþþüüüúþþþüþüþúüüþþþþüþþþþþþþþþüþþþþþþþþþþþþþüüþþþþüþþþüþüþþþþþþüþþþþþþþþþþþþþþþüþþþüþþþüþþþþþüþþþúüúüüþþþþþþþþþüþþþþþþüþþþüþþþüþþþþüüþþþüþþþüþþþþþüþþþüüüþþþþøþüüüþþþüüüüþþþþþþþüþþþþþþüüüüþþþüþþþþüüþüúüøþþþüüþþþþþüþþþüúþþüþüþüþüüþüüüüüþüüþþþþþüþüþþþþþþþüüþüþöþþþüþ þþþüüþúþþþþþþþþþþüþþþþþþþþþüüþøúøþüüþüüüúþþþþþþüüþþüúüþþþþþþþþþþþþþþøþöüøüþþþþþþþüþþüøþþþøþþþúþüüþþüþüþþþþúüüþþþþüüþþþþüüüüüþ úüøüúþüþþþþüþþþüüþüþüþüþüþþüþþþüþúþüüþþþøþüþþþúüþüþúþþþüþüüþüþþþüþþþþüþþüüþþþþþúþüþþþüþþüúþþþþþþþþþþüþþþþüþþþüúþüþüþþþþþþþþþþþüþúþüþþþþþþúþúþþþþþüþüüþøþþþüüüüþþþüþþþþüþþþþþþþþþþþþþþþüþþþþüüþþþüþþüþþþþþüþþüþþþüþþþþþþüþþüþþþþþüþþþþþþúüúþþþþþþþøþþüüþþþþþþþþþþþþüüþþüþþüüúþþþþþþüþüþúþüþüþþþþþþþüþþþþþþüþþþüþüüüþüüþþþüþþþþþþþþþþþþþþþüüþüþüþüþþþþüþþþþþþþþüþþþþþþþþþþüüüþþþþúþþþþþþþþþþþüþþþþþþþþøþþþþþþþþþþúúüüþþþüþüþþþüúþüþþþþþüþüþþþþüþþþþþþþþüþþþþüþþþþþþþþþþþüþþþþþþúþþþþüþüþþüþüüþþþþüüþþþþþüþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþüúüþþþþþþüþþþþüþþþþþüþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþúüþþüüüþþþþþüþþþþþþþüþúþþþþþþþþþüþüüþþúþþþþþþþþþþþüþþüþüþþþþþþþþþþüüþþþþüþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþüþüþþþþþþþþüþüþþþþþþþþþþþþþþþüþþüþþþþþþþüüþþþüþþþüþþþþþþþþþþþþþþüþþüþüþþþþúþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþüþþüþüüþþþþþþþþþþþþüþþþüþþþþþþþþþþþüþüþþþþþþþþþþþþþþüþüþþüþüþþþþþþþþþþþþþüþþþþþþüþþþþþþþþúüüüþþþþþüúþþþþþþþþþþþþþúþþþþþþþþüþüþþþúüþþþþüþþþþþþþþþþþþþþþüþþþþþþþþþþþüþþþþþþþþþþþþþþþþþþþþþþüüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüüþþþþþþþþþþþþþþþþþþþþþüþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþüþüþüþþþüþþþþþþþþüüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/Missed.wav000644 001751 001751 00000100706 14165625676 021246 0ustar00kevinzkevinz000000 000000 RIFF¾WAVEfmt +"VLISTINFOISFTLavf54.63.104datavþþþþþþþþþþþþþþþþþþüüúüüþþþþþþþþþþþþþþþþþþþþþþüþüþþüþþþþüþþþþþüüøøúúþþüúööôüü  üüøøü  þþüüúøôööøöþüøòðîðòôööøúüþþþüüþþþþúøüøú þþüúþ þþüüüþüþôúôòìðøü þúöðöúöôöøøöþ þþúøøø þúîöòöüüúôôöøþ úòòòôüöþüøöòöúöþîôòúüüüúðøü øøððòúüüüüúúøþ  þúüôøøüööôøøü  úôööüþöööúúèêêòðüôìðöúôîø øôìäðü   öòêòú üôîäìøøîêêòüþðêäæò " üîðèòþ öðêö ôôöþ úìäèèü$"úìæèò  öêÜâèö öìðôþ þüàààð$ðîàâêü öìäàòþ þøôþ üèäæèþ&""ðèäìú úÜàÞäø ööîîôþüüîìôþ üèêðòìäðö öèòò ðèâæô "úèèàìø üìæàâôøæàÖú èèØþ ðìèúòþôèìêø ôòêþ þøðàòü" .$* úÞààìú$ üøüúúöðøöüúôììð  ææÖðö  øöôúüø ææÜìî("øæêîô þôôòòúþúþìòè øòâìô$((ðääêö $$þüüüüüøøúöþöêèÞæðú(,þêèìð  øôúøþððððêþôøìØâàôø øðòìøþ   ôðöøþìîèúþ $èäÜîþ ,,& þôþôäæâèôüþööòú üîêêôü&" üøøîèêäêôþ&èÞÒêòþ ìäÞæô$úàÚÊØÔÚæâæèîèúò&" òú ,øæöô úàìêð$4 àêÔð@0&èêÜê & úîÖÐÊÞøü îüêêììþ&28* úþøþ òæÐÄμÌÒÜú .,2êèàâèúüøúôþüö,,4& òäìÜòàÚÔÎâäö&,&,"üþ òððÜ$( þ äÚÐäèø ôöèìîü,B<2( úêÖèäøþôîôàüüøÔæÜìúþøÞæÌÎÎàú60Fò öúèÞìÞüüÞøô"<$$ôÜàØä.6,8 úô>:öæÔÆÒÌÚðäüü  úðàâÚøð*, üæØÒÂÆ¾Öð*.0 êúè øüÒòö>.J(ÞúðäúÌÒÆ¶ÞÖüîðô ôÞäìæ .üüþæâÄàê,,D:"üü üæüì(,B$üÞðâøþòüâààØôþþòàèöþüüúäÌÔ¼ò(ôööøúòæàÖæÖìè 04 ú"¾æÜüö$ & úöîøÚúæ ö" úøöæìöîêüòìðäÚ ìîêð(&Jþþ0>*üÈÖæî.(ìÚüòêøúæðà´à¸*.T êÆîÚúöÜüÔêèö,,ÜÜÜØðøàòæìü2"úî &ÔÜú&äîèâþæèîì ô &üòØ2<ôüèäòäæôêö,ìøúæòÔÔøòôþ (.,6þøÐàèò$&&üÞÄÀÊâò>,@üÞÖô*þôØìð:$> þòðô öþæðäæü ÜæÈØ:ÐÊÐÐ"&&"þôúðæàø üÜü*R.*ìôâÞø.ØÞÚàÔþ D"4(üðÐôäìèôððàîöðþôþÜà$&"ö úðÞêÜÖü::>B(äØÞÞÜþêê²ÔÞþ(äò  úðìØÎìþ .ìö üìüÚØèÜ(üÔ( 2üºÆØØ.(BNìêîæøââèäøêú"øâÒÐÔÌþþ äÂêÔ"ú öB,âÎкÈäæ  ü :BúÄäØ"2J*òöèØÔì 2<$òöîòäÞüè øâòøð"&òä *0ÒÜØÒ(&øôüôô ðúÜ äâàîö "@ Ìà¸ì <8 ² êôÞÒÖþ"B &ÂÖØº :â´ú&8üð¾ìææ&, ØìÒÜàì $2F&. îÔÌÒÊæòúúæúôìôîþþÌð<*8 þäòúü.üòòÎÖÄü B@2.öà¾ÀÒÚü .ö üèèúÎ@ ôæðÔì(Îö4öÌÈîÞ&.(PîöÐÎØØð4 <"B06öèºÈÈØ ØÜÔÚàøB480èÐÐÆÒÐø*òþ&" ôöòþÒÎÜÐô"D.$îòêà òøÆÆôêîúð:&(ðèÐÊÜÞ *þôøäîòþ*"@2>þêÔÈÔÔ þòìøî:>8&"æÚ¼Ê¼ÈÖôü$ öìèÌöìüòüèîþü ò$êìÚäüêöôþ$.20&æ úöððâÒààú "  "**$JüÄòÔÄÊÂÔîä&86."úöèìüø üÜúöøâèêò &D$öèÆÒââìöðìøüþú"""0$äìÞäàìòöøèÖèè0604&*âØºÄÆÌÜú$ "4">(øðæèú úäàÊÖÚÞþ <.4ìÜöòàÜâÖþ 2 ""æ ò ðøÐÈÖÈø:üþþô îÞþøâàÌÞìö *.þü îüúðêêÞìÆö68>4üÒÎÒÎâþîþú àøø B@îÞäÐ$ úèÀäÜö þþòîîÜððöö ð$:*ØÜÚÜ0þ ìôöìøøúæü"&,8öÊÈÄÂæô    êìþöøôæôüöæÎÄÞæø8øú þððòðæ "" îÐÈÀÐì.,2(êàòèöüöìþüüêäêâòìö$öúþØÜÌò8460ôÚàÔÔàæú (."& Ò¾ÐÄø( ô  ÞøèôòêúÞÜàÔèú úòöø úðÚÎÎÖâ">><8òèôú  "òæèàøäîøð ,þüììöêööôüøêÞâêü *2<úâÐÖÜðòèøúüø àòÖúþüðú&F<64üòØÐàä úúô ðòèüüþööìêØòö  øèäÔêø2. ðòþèæàæøæ. üÜèäöððæü$:0D.0üÒÎÈÒÎ & ôþòþþôìÜÔÔØÜôü  òòäÚÜÚâò úü øþþþ òìàÜÞì2þîìÚî 4. ÞàÌÌÜÞôøêôâþò.2F$<ØÌ¾ÆÀàò "& üúöìøòòêôþ îêêêÜäàìÚâäþø (0."öìðâäàìîúðü"2(2 "ðàÈÊÒÜü 0B84"üîöôúäúäúúô "þúðàêè øäâÜÜèðþþðì$(88üÆÎÂÔì(*.*ðÞèÜêì   öæÒÐÌâò"& îîú   ðþøüúúêøöø öúþàäÜâÚêöôîúôòäúú ôìòòîîÒÞÊ08$(îþÎú &úôüúöî øüüþöøèúÐââö  üöôà<**äæÈâÖð 08B8:üèÐÜì ü $ØäÐäâèü ðúâÐàÚ *úîîØôððòìäÔÜäìö ìøþüòü .2øþòôüâüø* 8"ü$ðòÎÄÖÌþ 0ú þÚòæôðèøÞò òðâøêþð,*Föêæ âØÜÒü"þîìÔäî      úîØàð & äàÚØþú"òôàè  ÄäÒúôìöðìîäðþ"2<.( úîöÖðà úúþòìàìÖî(*L äÊÖÆðþî 4"þÜæÎþî6$@öÖØÔØî 0"øîôðþðîøøêîÞÞ*4<BôÒÜÞèøúþøúêþðêððø îèÞØð öôò$06 øèüêôìîÚêêö &8**ò ðôÜÞæÜòú  ( ôüúúä $&4$öäÈÆÈÌäô &ôêàæôÞìâüö öþò(èâØÐäü :4@þêäâìöøìàâÒþ.,2"þüðòäôøøüìôÞòþ "öþÜ*øøòò úôôÜîäâàô $&"üöîäæâÜÚÚêö $2( êîÊþú þüêøøðôæêäàòöþ&(îþòöúü  öêøôô2þÒæâø ìüÜþþèøú (öììàììö (øúÞðêîþ ,.D:>ìÔÖÖæðøààÞæ ôèÖÐÞâø& ,úöòöú öú4úîâÔÒöüÜðôþ"(&øèÈÌÌÒø(( öòÔúüäö(  ",&âÖÔÀîü."òöèø äêÚÈÊÚê þèÞÎîö,&:&îäÚÜÚæð.J*6 ðêâÌܶâìþü$êäÊâîþ0*èøüÜÜÈÞêô.*ððäæòö $,  ÚÜÜÚî&îîØð$ òúèêêäÒèìþ&$4þàÚÖâä(B$.öøþðøöîÖøô4(þÜì°ò (òö$ üüòæêäðüöèêöòôúüöðæôà&0 $ü üìòæêîð 6ô ìþè &ôèúîþ. âÆàÔêúöþ $èÞÔàÐî&ôÞìî"$Dàêâìîàöþâòèêæêêè  üúððîðÖäÒôB úü úþðøúèìüîø4ÒÐÎÚ82øöþðüæòúòø úöòðþ $&öìä¶âÜþ ÜäÜè $ôüúäî ðîòô " æÚÒÔîú.&2  øÔâÎð,þ úòîîìî. ðÐâÐøþþ,öôøúôöú øþ2ÈàÔè* úâüô& úþæîâþþÞöô úô$ôâоÊÞä&.8NÔÊÐÐü.òð  øüÒò &ú ìþèøöîø$,4 öêÞÚâØðú ööæð ø îæø 2þÊäÖâðòüþîúþ"( þØâÖØðÞòîÐÊæì.6<HÞØîô&""ÞÖºÒàð""úöäØìèø&þ àðØÜ&.(îâÜÂ,& ðüú"øòÜìðú ìðâòøöðþ úÚöê" .úøÔäèì   ööÆÔÆæ B:Ììêî4"ÔüÒô":ìÚ& ìöÈìøþ ðâêüð&*ìê¸Üò .,0üüæÔôìúÞðüîÆúâü(üäâþÌ,$*NîÒÚô4,äîôð. îúÜöôú *,8.üâÜÎâìæø .þâºÖÊæüìþø* &þ ð ÆàæÞ <" Úì4ØèÖà(òþîîêòö ôîì&þþÄìâ 42êöÆäòôÒð "ôüôæø ä ê*2,DþâÖðð.$ þüîþúþ ðü&*4îæÔ´ð.(ÔêôâôúöÐöèøüöèòÚ øòêúèèôö&$  üüúöþîööðÖøö40PîÚìÔÄäî"F ؼÔÄüô&þìòêþ 0 ðöâþòú $", Þèàìôø âÞÒÊòð".øúúèòþðà æîâääø ,.6øÎÞàô îèèÖðö & öÚàØÐ êìú ðæîÚ&B0(àòÜêòððôøüúðúðþ $þúÒäè,(<2øòîââìèüêþ (&$ðìÐÖâäø öüú& þðüäêîô üôêäðþ"&öü$ìÞØÀÞä * øüøüþðîèÚìö, üæðî ðøøôøü þäÞÔÜæð  úü  îúêîøêúêò"..&þæÒÎÖÔ*4&( üúöêæêêòþì2" ÔÒºÔàò$ìêÜôöú þîîêâôô úîìèð  þêìÜ,2"ìàÚÜÜü öèÞàà ôôúêæÊèø,$&ìòâÜøö îêþòäøúú"$28äðîòüþð (ÆÌƺìîüúüü ôúê 46(úðìòú øæààÚüü  þþ øúüúúüð öòöâöô6 "ðö"êæÊÌâæú öüÜèöú& òþðôúððâÔÖÎìð ôü $öþòäòò êìÒôôú0 ðòÂø ö òüô"òäæÚðÒôþ" øäìÐøþâúìô üø,0:2"öòêâÜîö þþòæîêüöüþèòìþ. þôîøêôè  üÜþö( æèÞÔøöúî êö üþÐâàä(äöêæèîö$$.,** øæäÔðìøôüöôúäôÜ üâÐÐØà$<82(ôêôöæÔ$0HÜÈäØ "êÚÐÖØø$üööÜêâðøø öôìîöæ þêòÚì .6((ììàÔòü âôô"<"âðîðüüüâìèòô"öðîèêðèúüüúò  àú " "îòôê $úêþøöØüîþ üìü0*âèÒäæèöüúþúòòüì:< ÜìÌ>ðäæîüðèÞââì><22îìÌÒüø$&Üìæìúöîüöúü üòèØôô$"ìîàîúüþüþüîüø$ âúôðÞèÞü úøðú $þÞìêòòúðòòîþ ìüòðüðúöîþîôèèØæêê ü *òàüö üòòêìøðêò $4üèäÐü .B>6*ðàÚîþ $üÎâÖö6 öÒæäôøøèÜÜàêüôúôðôôú$þìîèôúèúò$"L0êæØäôêú  þúþêÞäÐÔöêú âü&òüþüâÜÆÈÖÔ.*Úðú"öþì""0$*ðæàîú  øääÞä ôðôî ôöúúþøúðü þêêÄÚâî"B"âþüø öøPê&øüÎâ¸üBÔÐìØú úôòðèîôþ úîüìòðøæ þ üüúüøüâððîþø öäòüþðøìøþ  ôöæìøøöôæøðôüø þüòðþî$ ìÖîò "(8ØÞÞêþþþþôøôü ìèàâú"úîðÞôàðøö &"üòÜêÜòööìø öðüôèæÚúö þøúøúþòôèîüþú øúî.$8öäÆÊÒê  ððâæðø úòöøþüìîîìø   þòðæòü üêîÜêðþøü ôúîìöæöøø üö ôþðèþò"&0êàöî ìèäâøðþ  üúüþþðîðæþð**>üì2þäÞÀèâöô"êðÒüîôüâôèì þúîøü  øòæêìîöþ úøðüò( èäêä úððêÔèÒþ":$$ ìô ( þþäêØèæêööüòöøú üøðöþú& ìôú  ðîÚÒÞÐþØäìî*.,øüÞèèèþòþüòððæìúøæâàö**(øö ððêîúöÚæâèìþìòöüþî  (ìîðîæüàèèððþäôô." úâæèì  ôîâîö(,2$þâîìèþììäÜîî "üü 0þüòÒðê òüöäòüö  âîàæøìþô"þîìÞÜæàôîò$öøööèìÆêú ((,øÞàÚØôè$::ôîüôÜôâòøüþúþ  öüôüüôüøúüþêòôôúüôäðäôôîøèôöþ  *" úøèüøôêôì þòþüüøúêìääú,$2 øàÎÔÜò& òîììüüúúþøþþøôððüþ"",ôäâæö"$ úúîðððþ  îæàâæðü úþèôêöøôþ ìðÒæòö îöèìòðþ  ,((" úúôêöèòòô  îîæâððüúúôôòêòðøþöàÔÜÜì*   îæòòþäòäìøü6$ö ð ìöâäøþäôôâöìü&þøäòòøôúèèæÜ&þøðòø ìäÔÞêò øö *ôüüü  øþêîèìÒÐÌÆîô ôøúþ ìèìèúüüèêôô  ðîèâò&$( ø"((øòþþ ææàÞúø úêþøüú öøüîüöàäÈÖìø   øôòîøøúúþö  &("  öôèìàÞØÜâæìîððêêèêúðü4($þöüææðö(6  öþêüúúú îäôâ $ìòÌÔðêúüøø þðìêêööþüêðòú"üþúø ôòöð þøäìêòú úîèèèøúìÌÌÒØöþúöþ  ö úþ   öìôæð òêâÜìö üòîðúúüàäèè øðôø öþöþþøþ "$ "øîØÎÚÔäääêâèæêöú öîôèüôîøú úöèÖæê($ ô$"2 èææàøúúú " üúæöü&"ðøØðôìäæäÔìèøþôòø   üøòêôøþúôîÚôò ôü,üðàêäöòèèú &&üüú èâÚÚêö üòêîôøúþúøøö"úâÚÔØêüòðÞâêú  úü"& øðöð üòæêÞêì&"$ æäÚÞäìþ þöîìîú öòÞâèê úöòþö  úúòöø üüèæü"ööèæþþîâÚäâþ4&* úôæ2>84ôäòö"òÌÆÄÀâìêâÌÊðö" ððââðê  öôæöüøÞìÞ ,èâìäúöôøø þþðúþ &6* þþöüôðêìòþ úæÞàäøòîäÜèèú  æìÐÚø $äâÒÖ(&ôòîè&òøìü þäàÚâøúüø.,,îÊÈÈÞø. øèÒÔÖ0òêäÚì "(þÚÒÎâð  êæÞò $ þöôü"" òìæäîô øìâèâü úðúú $6($þþøòôäÞÒâìü úîèØæâîþúððôäÚòô üôðâööòø " úæÚäìúìÐÞÞì òääÜîü(.4"úèâäèü úôàæèôüøðêúþ& èîðô0Úèèö  úþêÞæàððôæú  ôøìòöúþòúâÜæàò," úúàö2$úøòò þþÞèêæúúîòèò  êìââðö þþô $"üøØæîúîðöôüüüøüøüúüøüòðôòþ øüþ üúèðôô ôðúøþüêîìðüôîðèôþþ  üþòîúüôüüþ êøøøü üîòüüøúðòþþ  øüèðæö òüüúèèÜòôþþòäêäìðöüüþúöøôôöö üú&& ððæîúþ êêÜÜîð   üüöüøúøôôôìòôöþüüöòêòöú òüôôúþöòôðþ  þüúþü   úüþúøèìäêòðüøúþ$0"þþöøöøøöþüþøòúðòîìôêöþüúþôìîôòöþüüòøôüüú" $üòøòöúþ   úööòþ üòîìèòô öüö*& öðøøüøüôööðòöìòêðôöþöüúúöüøü  üðòèðüþòøüòüøòðæøø þòìÐèðüþìâðìø  öøêìðü ( úèÖÐÐèêü þðúøü ìâÜÚìø""øêØèæø$ üþäæòìøîøø $ þîìàäîô*(ôÜÔÈÐÜüþþ îàÖÔÐæô úðèâìôü  öæâæÚôþ öôêþ " øêöðúþ úþòòúêìððüøþþúþ þøøêðöü üòòèôúúøôòöúüîöîöþìèâÜôþ þöâêðô   üøü  öøêôú ööæâââöö  þìðèö    üøøöòúòüüþöòôôüôþþ øöâôø  öüðîòòø øþ úøüöòöôú&öøÚÜÚäôþþþ úöþþ$øôöôðþúþúþþøúîìðêøòúü  ððôú øøúú þúúöþðêÚìîú þúüòîêìêòü öþ".,&úôêîöøêèèèôôôîôòøøþøþþ ðêìè (ôôæîöôöþ ôøôúööðöîöô& $üêòòúüìèæäèêäìææèèòøþ þöææêô îôìîú    üúöúþ    úúööúøþüþüúúöôòôôøø  þþøúüøúþøüüøúòêæâàäêööü  üôôîôúþ   þøþööîôúü  üþþøîôðò þüüìþü   þþþúøöðîêðòöþ üöúøúüüüøüøúôøþ øòøöô øôöì þøúêðððööøöþ øøúô  þüúöüúøúôôîèêîîöøþ  üôøüöþüôü úüìôúþ   úüòöøþöôìðêîöü  þþöúüþúðîððþþüþöðôêìöþ öæêêîòöüþ þøðìæòþ&üüú þþ  úîæÜàâæôøþøú üøîüôøøúøòøêðöøþ øúúþþü þþúúúü  úöööøú úööôòúú ôìâäêîú    öôèæðî úððìîôöüþøþþþüþúüööúøüúþþ þúüø ððìôüþöðòîòîôôôôþúöþ     þôðððøþüòîäôôü øøòòøö úúøüþüþúööôþüüþúöüðöøú þ  üöôüþþôþöööôüô üúúþ üøòðòôþþþøøôöþþîðìööü þúòêîðøúþü þòööòø  üüúòöòòòôú ôððôöþ  þøþüþúúúøþ úøòðúü  üúîìêìòøþþþüööòøü þ   þ  òðêðöúúòîðìôø øööô þúøüúüööôøøøþþüøüü öúøþôþüþøðôôø  þüþôøòúþþööôöüþþøöúü  öôììôö úøüü  öüôòêêðäøþ ôôúöþøúüôüôôòðôòü üüþ üøüø   öøìîðôþúèæäâèêôúüþúúþúü üú øú þþþþôüúüüüøøöþ  þþôþüþúøúö  þþþü öìèÚìæòô þúòôôþ üøúúúüþþüúþü üöøöúú øüøøú üôòðôøúø þþìòòò þüòòðòúú üþ ôúúøüöüø  üüøúøøöøöøþüüúöüôþþ þúüüúöþüþöøòðîêüîøüúöôöîòø        þôþúüúþòþúöüüøüøôöøðòöîøô þ üþúöþ úøüúøþüüüþüôúøþöøøðü úüú  þøþ þüðôöòúúøúöúøôöüøüú üööúþüþú þø úþü øþ úøøôþüøüúðüöüúúðþþþ   êú  úþöøøòðôôúúøîöøöüþüîðêðòö þøîòôô þúþüþ   þþôþúþüþüúòòæìòî úúþúöúøðúüøüúöþüìþþúþüú ô úøþþòúú   üìøüøüúôúúüøüòøúøþþþúþøöúþþþúúþþ  üúþüúþüøüöþþþøüú  úüòþ úúôþþüþþøøòøúúþøþþþþúþþ  øúöøüüòøöôþøúøøúúþúúöøþü þüþüúüöþþüþüüþþ üüôöðþþøôúøþþüþüþööúøüúüúúøúþ ú þþþþþúøüôøúþþþþúúøøüþ úúúöþþþþþüúþöþúüþþüþþþþþþ üþúüþþüþüúüôöîöþ  þüþþôðêêîðöþþüþúøúüúúüþúúøööøþú úþüþüþþ þúþøþþþ þüøúøüþúôòìööü  úöôöôüþþøöööüúþþþþþþüüúüüüþþþþúöøúþ þþøøúøúúúüúüþ þüøøúüþþüöööüþþúúúüþüþþþþúüüþþþüüúúü üþþøüþþüúþüþ þþþüüøüüþþüüþ úúúúþþüüöøúþþúþüþúþþüüüúüüþþøúúþþþþþþþþþüüúþþúøøúúþüüüþþúúúüþþúúúüþþüüüþþþþþüþþþþþþþþüþþüþþþþüþþüþþþþþþüüúüþþþþþþúüúúüþüþþþþþþþüüüþþþþþþüþþþüøúúúüþþþþþþþþþüüúúþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/TowerClock.wav000644 001751 001751 00000126400 14165625676 022075 0ustar00kevinzkevinz000000 000000 RIFFø¬WAVEfmt +"VLISTINFOISFTLavf54.63.104data°¬öìÜØÌØÚ &.0*úîèìîú üÞØÖÆðú 6BBúØÎкâîþþô&4"üêîèäòÞ$þììÜÐÐôò ê""6@&äèÒêú   üôôÚâÒäòþ ú øìúöþôú& þúîüâðþüüîèðü òæØÐÒÜðò""$úüîòâü "øèÞÚÞèòúþà üúú  þòü22>êÚÎÀâÔäæ$ &üòìàêæìîúääÚÒâÚêæ2$ ÒäÒêÞîô$,:@8, îèØÊæÖìê "(ðþúú üðäêèòìâÞÎòêþúÞæØÜîÜöî&*4.âèÖØîèôôüú"2&îäÈÊØÒö:&&üòÖìâþÞìîê "ÚäÖâú 606( êôÖÒÎÊÖâà6286: úîÔÊÔÆàô608. üöààÖÌàæü*$êæØÜâèúö,*øøêæÖÚäêöä&4624þàÜÎÖØæ ,0"$øæâäèääîêòòò"0" òÜàîü *âØÐäÚîàêú&(2(6& üöæòúþø òúüäæÊàò "66*(üòÚÖÒæò  ìîèäÚäèôøú &6(8$ìÜØÒàâîøþúèâêæìò,üîìöò"*4øøöìðîòâðìü("þúÜäÚþ(&&úþÔÖÖÚðæðâüö 2 " úæêÊøÖòÚôìêôB4<þþÜÞÚâî þôòìæìæúòúð îðöü  ð ðððôôö&þêèìöø þ, úüþþþðÖÔÐÒêö ô $  èÜÌÜÔäÖêð 2$, øôö úúæîòþèúâþððèÞö (*2 üò$ ðòîøÚììîêììòìú ,$*& üìÖêØèÚô þøøôðäòîôúê:(&þòäðô  þôôèâäðú*2.2öÜÖÞòøþ*&2êààÔÖèäò"&üþ4  öúêìÊÎÎÌØÎÞþ&4>66üêìôò  ò üìæÖÖÔÖîî,2.8ö úð üüúüÖäØÚââðúL:<.èìàêæäðâ öìàäìöú""üèæèæ öâÜÖÞØêê"*&ðúêøêòüþ$" üðúØÔÎÔÎÚÌ  $$ ÞèÔììêâÐÞàê"4>>>$ øôüòúøþüøþúîôèøÚäâì "ìöìúüøüüöòüæîæô *,*úÜàÐàî þ òþêöòæðð üüúö øøÞÐÎÖÔèêü &*(èðúøü îêêÜàÜÖèÚèô(.<,(þþôöÖØÚÖêØâäî<4<:(*ðôÚêìüôøö úþòúììèæêðü.*"üþòüìêô  òüöüôðòòøî"&$ðøÖàâòÜîàðôòúêþ*" öêäÎÌÊÈÌàèô &:*0&(þüþúþþüôòâîæèâÞèä ,(&  þ þ þúêòìêæäèìèøð .8860 üêèØÜÞàâü üòîðêþ  üöæêðö " þþúúîîèðôú "(ìêèòìúô  þúðÚÐÄââôø úþìøöööææÜÔàÜðø*4>@&öèìööôþöþøøâäèäêâò,8þüöìêþðèêÞøìø.2$ üòÖæàæðèøü  úúòöèìèÜüð8  üòüðîö  üôòâØØÜìú"$*úüüþü îäÚÔÐÔàè*&$úöîòîêâÞÜÖâèî. 866&ÞîÜøþôÞòòø  üøâÜààîú 0.0&$ ôìôô øþøöúøôèèæôô 04:" âäÔìæòôü ìüìêìÜèàö " üø úòääàÌÚÒ,02*üüôúî  þøîäØÔÔÌòô ( ,&þüþþøôöòðúòúîâÖØìô2F>:6$ôîäâââîîþôö  ôàÖêêþþ,.,,$ úêôðþúüüþ þäðæäðô $",&úêäÜäîò "èâÚÊØÐÜøò $,  þ  àäØÊÞÎÞêì>>64üøêîöôúæòàÚàØâêìD,6$ þ òòðôôúòøüüòúððæâäîø @8B0" úîîâæèÜöðþúúôìâØìîü"Øòàú  úîìÚäâìæ &$þòæðä ø þîÞÚÔÜÞèþ   þ  úþúü êôâØÔÎÜæäö.08B((úúöìðæîòðö èøàääÖäÒêüø$&2< $ üúäîæôþòò ðèêÖìú,0>8,$ þòÜæÚàêìôúüöìêèâ $ ðôìîøü úìÖÜØæþ"$üôøòôüü þøö&ìâÔÈÜÚôðö",*$&" ö þúôú úâØÚÎÚÔäø 264*"úööììâêîþúøæìÞîîô,886&üþúþøøêèìòþ þúòþèòô $"4 $üîîæÞàÔæèüøØæäêðô öö øäÚÔÒÞêü2$6üüòêöîþ ü êàÜÊÔàæ ",*.."øþèþîðîòúúöÐÚÎÆêÞöö*44B2< øäìØðúðØòìüêòèöòü$*$4"ôöèðöäðÞôüþ  øðìðæúô ð*&. úüúêþìäæÐòò(. þ üèôÊÖÚÖ &* ü  ìäàÔÞâì  (&$þþêâèäðìö ôäÚÐÒÜØü $&&*"$öòúòðôêêü  üèêÜòþ"4,0:& öäÚèÜàääðúî $ úðâòî$òôìòðæîîö" üúèìæäòø&""òèòæúøîþàúþøäêØàÔÞæú$2$þôøðòøø üöîÞØÒèÖðì,*<$ öòèÞäàôøþ úòöÎÚÞä":06 þüúÞðÞúþöþòêòê (202 ðîØÚÖÔæÜîî$(ððæÞêòüòöòöüòüö  "$òöæÚðâöê$&",òòäøòüðþöøàØØÌÞÚæúö&"úúàæêîîúàèÜÔâÞìò0,DD*.öðæÌâÜðøúöúðúäìîî64*, ððäèâààìòìôìò4$$úöôêÖÜÌÞæè ü, ôòØàòö " öðôæüð öðÒââðúö(&òþöòøèîø þØÚÒÖêâöü8*( üüîäèêèúø ÖîÜìòæø@88("öüîîìØàÊâîðþúöøêôìö.$*, þüäæÞÚæäêþ üòòöîð$, þêêâÚææî úÖÜØÒøô ðöôìüþ ÒÞÐÊòì (&, æüèøðèöèü* ÞàÌÔÚàê 0.0: þôîêæÒîìþüúîèòò 4.6:" üúîðÜØàÚÞêÞ& òøôðèüøø *"ôôòìÜäàâ (øøîäðôü$"úòøêÞìè ôôÞÜØÚêö "$ úøôìðú  üúöÚÜÎÚì ,"  úøðàèäîøî"òÜÌæÜüþ,.8,&ôÞðâúèÞîì øúäêôî """òöâèèÚÚÎÖÜö$, þþôèìððú  2*þîüúöâìæ , øþüììòòâø&",  øöäÚàÖî ô ôøìÔÞÊÜòò&úøâðîðüü êèÞÚæìò(402($&òìäÔÞÜæîîþ ööìäðê& ,*öüîääÚÞÞâòòôæêä$ (. ðòèâæÞææâòê 2$"üêöìêòò $þøìòøäôà . öäâìäôîøü8 þþúêâÒðò$ ðìèÔæÒÜîè@<,"þäÞæâêöþìòîðàôþ:4*,&0  þîØÆÎÈÚêðü úôèÞäîö"$"(ÚØÞÐâàäøè$" üøêîþú,"þÌÚÖÖèØêú*." øôØìêîôö,üêîèìöæþô$úìÖèÚêêî (,*, (üðìøèàôäöâêÜâêäøüB24<$ ôÄÎÒÈøøìúêüöòü H*6$ üìêÂÌÆÄèæú  ððìäþ$"ÞâØÐæäð $0ôîúú êîÚÌêÞúúúþ*" *þîÖàØæôòþ ü4,*ôþðæðôì ôâàÔÞìðð&<.8& øòîÚâèìþàäÖæäîöê .*4(&"îöÜØÐÈäêü üöððüøô(&.*þöòúÔÚÈÎàè üøöîøø&ðêÔÜÜîôöôîôò  öìæääêôüîâÜÒäæþ$*$ üúðêúîþþð ìêÜÚäæ"($2"ôøàêèØèÐìôúòæäìêþþ 8*üôèÞÜÐÜâø òò $*üðèæÞäÚÞäð . üúêððòü ÐæÐø ôèîäúþ  âêÚööþ ôðèêÖââî""$*ôôàæâäêþþ ú ôøæàîê*(þöàÒÔÎæØìîè êìèòü &(úàêÚÞæÒäØÜ ,üúúú  $ þêôàìæÔàÚê&**&ôîøèöòèúêþ, þèæÚÜêø$$öøìàäêê &$(òæÚââðúèÞææêöü $,,$(ôàÜÌÚââöîðêìòøþ*"0$ æÞÚÌÐÖØôìüêæøî " &(ìê䨨ØÚòêú&0êúþ   þþöæâÞÜæÔðê &*2 ìöæèæàìê("2 ôôòæôê   ôöðæþîüôìþ2,,<" øÎÔÖÒòô îêöîàðÜö8"0$*,âÜÒÂÜØìòü úüè$$""þÒÒÄÂÒÒäòø ü üöøö    ðòÜÎâÒêÚð &"0ðòìð  þ òúæêèàîêðö$"øòØìîèðÞþ &42úîòæêøê * òòêàèèîúô  .* òêâÐÄèê  æøêêðêøþ<6 &  ììÈÆÚØöú úö , ììÀÎÎÖæìü& ôîðòø æààØðîü"þôðæööú ""Þîàâöìþ,úôîÞêæîòü :(((þ ôüôâæÚèôöòêòìöþþ "(8$( êèÚÞØÒâÚ òöøúø ""&.ôôÜäÊÌÖÊüþ   ö öüîüÆÔÈÎôö$ ððìæîðô " èèâÞðöþþöäöî"òîÞÞâæòøôâÜàÜîú 0(,( êìèâöÖêæè ðöôø  2$2 úèðØÔØÎââê(üöðú þú""úüèäÖÐÔÜâö  þúúþ þüîìðÚäÒâô $,þòòÜèæòü úìÞÒææ $ üøôìðîô øÖØâÞôêú ðäèâðúü .&*èàÞÎäæèøð  þðüæ "" ÖÜÔÈÚÐÜêâþ20".úþúúööæôæâîÖäÖèúþ (üþüöþøü "ööþìäêäêþú."((øüìüêâîØ  øìèÞÞêâ  ú òøæîòæ""ôîÖØÖàòüäðêö" &,îäØÐÔêèüò ø úæÚÒÈÌØÞòô& " úìöøöúþø  úöìÚìæìòä & &ôøøîøú öìðâêìê   öôîêêòìöîò " $$ êèÚÜæòú üøôúðþîþ":"0 èÜÌÐÒæøú òøðú  öÖÌÎÄÜäìþ( þöÚÌÖÆîèòü& þôìôîþü äêæÜöèöú""üüæúþìüî  òüììêàììö "ðúìæðâîìæøì&.$&$øôôâêØàîì þüþüøþþ." ôÞÔÔÄÚæè üôúúð  ääÔÂØÖàþ (ôôø æäØÐàâø   èðæøòöüø "ðìèäðú  þðòèöøüú &$ êòèêúäöðô úöðêúîøøìü,2>$&  òêäØâÜäø  ü òâÜÔØÚÞð  þüööúø òòäÜØÖæê  öøôòþ ôèäÖÞèì   üþêäìàüøü øæêèèþü îôòìúøþ (*"& úÔàÞàîø  èøôôü(*(6 ÞìÖâÞÒêÔ "þüþö$ úèèæØäÖâîì &  þøúêôøú  òðàìÜàèâ *"øüòðúøþ  þþøþÜèâÞ&êìÞÞèèø  ÞäÖìòþ þþôúúú*èàÜÞâðöü êøöìÞÒÜÔäèèþò, þöþ þòÔÜâÚðàô*&þôòôìöøôþðîêâôü$úôöîêøôþøúèæðôü  ôúüìòâäðì $ÞÞàäôöþ þ üúøÖàÖÜìèúþþ  ôþüþ  ÚàÐÖÜÜæþþ"úü âèØàêèüú & ( úøøðøêîðô  üüîðìèôìøü"$ üøðôìø úøîîìêöú  úþúøüôôòðþ$", ôììÔàÚäúþ  þüî  òìÞÐÔÒâô òú þøæÚÖÚèî  þøúüøüü øîæÞâîð  ðäòæöðìöîü$üèôîìúòþôüøöôòì&$"ìøîîìâøþ  ôüüòöøú""úþîìàÖààîü   úúþúîøÒØàêô  ìôöò   úÚÞÜæúú þìúòøüö  æðæðöö üøæìæêôðú$"$øüêèðêöúú úúþøôþ0& òìðäòäìòì øööøôú  øôèââÚàæâ öþü  òðæìÚäèê  þüøìðîî þúúäêâèüðêìêøø úîììôú   üøîðîìôôþ úòâèæöøú üüüþþ üêàèàðòêúî øøôú   äêèÞäÜèøô *$  ðøðòöîèîäîòø ""  ööâàèäü úúøôìòôð   îäìÞþüòèêàôú ü þ øþèìîäþ ("ôòêÜêæðþðö   ôþöúü îîäØàÞäüôü"üüöþüüêØèÜðèìüò 2& üöúêôúô  öúêîìêúìøøö" øììâÞêîø ööòìôöø úüôðøöþþâìâö   öôäòðøþ  þúìÞÞÖæêüôü  üü úêäØäæìøþ þþöúúööúôêàâììú "ôöîîôòü öôèòòôü  úúøðúìðìî úòüìðü  þúööôòü"ööìðìêôöüþüòôêøþ úêðÔÞàèþü  òü   øòîÒêà  "þüòòðîøúþ øòèâèäü òôòðøêøöøööôþòüöîúðøúêþò * úòôüìøèþ úþúþðòúø(üîòèèîäúü   þöðôò òüàâÞÚðòú   üôò  þöøæèèÞúü   þîðâîðòþü  ðôêðü  þøêøòøüö üúìøöü  öøôðôðöüø úîòêðôîøôø  þöøîöþ îîòèðèêôðü úöðúø øöòêìÜæàøðòðîö øôôðîôôú  þþâÞæÜþú  ôôöò   êòðìú  øöôèú þúîôîðôö ìòæâêèòøðþî üøö ìôäìðìöôúü&úôòöæ öôèîììøèøúþ"æìàäòø þúôúøø  üúèêâàòø  þòòöö  ôòèìðú  þöêîîðüþúþ úîèøðüîæèâèîîúü  üþþ öêîæôööþö  úþúòôîîøð êîìæöîöþô øæîæôþ þúþ øúèèêðþ üöüîòøô  ðôîòôúþ øðôäòôøü  öúðø  ôòæäìêòôøþ (øøúööþðòìêêîôú üúôöìîèøü üòôöøúöðòòöö þü þøúöîðêîøø "úôöîîòîþ  þüìúú úööðòôîüü    þüôìôôþ þüöüæîâèü   úúôìöôøôòìðîü  ðôìîöìúüþþü  øþððôìøôþ  þöúþúøöôôüòîöôú  úúöðôêîîö  øüîþôôöîìöòþ  üööæòð  üôòîêðìþôêðìþú üøô  þþôìäæäþô ðúøö üúôððüôü úøúüøþøüþ úüôüúòþôöøîîðìôôðúì    òôôî  ôöìôöôúèúøþ  ìðìðöú þôøôòþ   öòèæðôþ     îîÞäìöþ  úööôþüú üðòøòøúþ þöøòøþøøøþ  þôøòüüü øìòèöôòúöú  øüúôüîôôôìúøúø üþøèìèòúþ üüúü  öîîèîöú  üþüðîêêèôò   þþðòôðúþúøêøöþ  þúðöôòþúôøþøôüòúü üüêðìòþöô  úøòøöüúôúöúþ  þúðúìîôì þþþ øàèàâ  úúþþþöîððöü üúöðôîúüü úøðòú  þööêòòúúþþþöìòðüüþ þúòìðîøúú øöüòúðöú   øöòêêèîô  øþôüþ üüøðòððøòþöðúô öüúüìôì  úôôôööòøþ  úöîøü úüöüôòöðþ   úúôòîôðúüüðöøò   þððêîúòú ö þ þôòìæìôðüò þþþüþúúþú úøúòúòöþ üþüöôòì úôôöò úüðòöðêôòø úøöðüú üþúþüúüúþ  ôôæêðøüþ þþú øîìèêòòú úþüîììèèîôü  þüúþöôöü üüôöúôþüþüüøüúüúøþ üüþøþö îøòþøôøòü  øöòôöú úþþ þüôöæîìþ  üüþþþ øþäìàþþ  úúþüø þðèêèüú   þøôøöôüò þúöúü üüöðþøþøöøø  úòúöþü øüúøüúüþú  þþôúìôúú øüôðìâîðø øúü  øôêêêððú  úúþúþøüþþüøìòòþ  üüôúöòøúüú üúôü  þôþüúüþüøþøöø úþþüðôîîôòúþþþüüòîîæòæìð  þüúôúúü ú öøìêöô   òúöþ  þþøøöúø  úôöîøöøúü  öúðüúþ úòððøüüþþüþü  øððîêðêþ  þú üþøòîîîöúþ úôîüú  øúúöüðþúúöôööüþüüòüú þøþüúòòøø öøöüú þþþ  üòðêðôöþôþþ úøòêòðöþö  þüöøüúüúðòöðöö úþúüôîöê úþüü  øúúþìôöô  þúúþú þþþþöüø òôìôøüú  îîèìðòøüþ üúþüþþ öôìììîò    þþìöôþþúòòôöþ òîìòôúö  üþþ þöúøøüüøöúüþþüúþôúò  üúöîðìòöü üþþøôîîêìòü þüúþ  ôìðîþ   ôúòüüöþô òòöò  þòüúøúðöôþøþþ þþúüø üòúôøüøüþüüüöúøúîôêìöô øþüþúúððèîðöö   üöüöþüú úôôîòöø  üþøöòøøþþòøøú   üøúööþúþ þüþøüúö þöôöòööúüüü üòððîøòüüþ   üúúúüüöòüðøòòü  üúôòôöþþúôüü   øôøôøúü þþü þúöúöüúü øøòöüüþüþüü öôòìøôúþøþ  þþþ  úþøúòòô   þüîööüþúöøöþ   üúöôðôò üø þøôôðþþ   ôøúøøøôü  øööôøüüþú üþòòòêööþ   þúøöúþü úüòòöôø   þøöôðòòúþüüøúøüþü    þøöðîððú  þøúôþü þøüöøúüúþøüúúü  üþöøðôú  þþúúøðôöúþ  öøüúöüþþòööþ    úúìððøüúüøþ  þüøôôöúúþþþþúúöü úúööøüþüþøüü øøòöòôøô üüúøüþþþøúöôôòöøú  ôôìîôôþøôöôø   üüôúöøúô þþúüøøþôøòø üþüþ þü  úøôúþúþúüü úþúüöúþü   üöôúöþúþþøøúü   þüøôòòøúþþü üúòòðôüüöúþþþöúöøüü  øüøúþúü   üüüü þüúöôöúþ øøôøüúúøøôðøöüþþ   þúöêðòöþüüüüú  øöòìððôú  þþþúôöòøöüüüüþúüþ üúôö  üúþüøöôöúúþ þüøôòúüüöøúþ    üøòîòôúþüü    øøêîðôöþþøúúþúüü þüþ  úúöøøúþ  þþüøøüþüüþôöôøü    ôøòøðôúø þþøüþ   üøòòîðôôþþüþüþüúøööðöøü þ üúúþþúúúöúöüúüøþþúöôöøüþ üøôøöüúþúüúøüü  þöøôðôòúþú þøøòòðöúþøøøôøôþ  þþþþ üúüüøøøøþü  ôøöþüôúôöøúþ   úøðôöúþþþüþ  òôðîôôú  øüôøöøú þúüüþþüþþþ þüúüøüþüöøòôøøþþ þüôôöúþüþþþ    üþöôòðôôøüúþüþ úöîîììðòü üúöúúüþüúúúþ üþúúúú þúôôöøüüþþúøøúü   öøôôôðúüþüþ üòòèìðøþþþþ   þþøôððòô øúúüüþøøôþúúøôøúú  üüøôøöüüüüþ   üøôòðòôúþþþü üþòðððöúü üþöôôò  þþüúúüþþúúüþþúøöøøúüþøúúú   þøôöôöøøþüüüúþúþ  üüüôòîîðøøþ úòòðòúü þþúøøúúþ þþþ þüøøöøúüþúüøøü  üüòøøüüþþ   üúìòîøöøúúþüþ þþøôðîîôöü  úøøüúþüüøøúúþþüüüúþ  øøöøüþþüüü    øöôòøúþþþüüü   öòîìîòöúþ  þúöðôòöúü  üúúøüüüüüþüþþþúöúúþþþüþ þüøúôúüþþþúøüü   òòîîðôøþþþþü úúôôòòôúþ þúøøðøøþþþþüööôþüþþþþþüüúúþþþüþ  þøôôòôöúþüüþúüúüþ  þøöôîòðôúü    þôöòôúþ þþþüøôôòøüþþþüúúú úúöøúøüþþüøúøüþ  úððîðôöúþþþþ  üúöðòðòúøþþ  þúøôöòúþþ üüþúþüþüúøøøúü üúüþüþþ  òôîööúþþþüþü   úöòðöòøöúþþ üøôôòôøú  þþüøòøôúøþþ þüüüüüüúþúþþþüþþ  üøôôöúúúþþüüüü øôôîòòôúúþüüøþ     üøòòòôúü  üöðòðúøü úþüüøúüþþþ þþüúúúþþúúþü þüôöòôúúþþüþøúþü  òòððòöø  úöôòôøø øüúúøöðöøúþ üþúüüþüúøøøøüþþþúþúüúü  þ  úôôðòòòüüþþþþ þþøôîòôøøþ  üøøòòôöü þüþøüúþüüøöøöüþ üþþüþþþþôôôôúøüþþþþ   þòôòòúöúøüþ  þþøòöðòòôúú   þþþüüøøôôøö þþúüþþþüúøøøúþüþúþüþ  ôøôöþþüüüööôöøüüüþþþþ  øôôðôöü  þþüþöôîôòøöú  þþüüúøúú  þüþþþüøüþúü þþøøøøþüþüþüþ  þþððòôúþ  òöòöööú   úüüüüøøöøôôòôøü  þþüþúøüúþüþþþüúüúüøþþþþüüú  úúöøöøúúþþ üøôôòôöôþ   þúúöðôòúü   þüüøþþüüøøôôöúþþþþþþüüüþþþþ þþøøúøþøüþüþ   þþúøøôúúþ  þöøôòðîôúüþ  þüþüúøöôöøü   þüúúüþþþöøøüþüüúúþüþüþúüøôôôöþüþþü   þþøôòðòøøüøþþ  üþüüüøöîòîôôöüú þþþüúüúüþþ  þþüüþþþøøúüþúþúúøúþþþü øöòôøþ  úôòöòøöü  þúüþøööòôòôøøþ  þþþüúúüþþþþþþþúúüüüþþúúüüúøöøüüþ   ööòòòòôüü  þüúòòôôþ  þüúþüþüúòöôöþ    üþüúüþþþ þüþþüúøúøþüúüüþ  üøúôöøøþ  üúüøüððîêòöüþ  üúøôôöøú  úúúüüþþüüúúøøþüþüöüüþþþ üøúøøüþ  üüöòôôöúøþüþ þþþüôöðððîôöü   þþüüþúöøöúþ þþúúüúþüþúööôüüþüü  úüúþ  þúøøöúøúüúþþü üøöôöòøô  þúüúøúööôôööþ þþüþüüøúúüþ þüüþþüþþöþþþ þüüüþþ  þôôòððòöüþþüþ  þüúöððòòøøþ   þüþüüúøöòôôöþúüþþþüþþüúþ þüúüúü  øøøöøüüþüþþúþüöòðìòôøþþ    üúøúöòöôøþ   úüôüúúþôøôôöôöüüþüüüþ þ þüúþöþþþþþ ööòòöøúþ  üþüøöôôòöøü  þüþüúøöòôúú  þúøøúþüúøøôüü þþþüþþþ þüøøöôøøúüúüþüþü úúþúôøøü þúüúüüøüðòòöúþ þþúþúþöøöúúþþ üüüüþøüüþúüúþþþ þþúøööøöøúú  þúúøøúøþ þþüüøööòöôöööüþþþüúþ þüþüþþþüúøúüþþ  þüúôøöüüü þþúúøôöôúøüþ úüúüúøúööööøøü þþþþþþúøúøüþþüþþþúüüþþ  þþúúøøöøúüþþþþþúúøøøúþ þþþþþþþüüüþþþþþþþþþüüúúþþþüøüü üþþþüüööøøúüþþüúúúüþþþþþþþþþþþþþþüþþþþþúúúúþþþþþþþüüüüüþþþþüþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþcrossfire-client-1.75.3/sounds/magic.wav000644 001751 001751 00000024272 14165625676 021105 0ustar00kevinzkevinz000000 000000 RIFF²(WAVEfmt +"VLISTINFOISFTLavf54.63.104dataj(þþþú üüþþüþþþþüüüþþþþüüüþüüþüþüþþþþüþüþþüþüþþüþüþúúþþþüþüþþüþþþþþþþþþþþüþþüþüüþþþþþþþþþþþþþüþþþþþþþþþþþþþþþþþüþþþþþþþþþþþþð òêøèúþ ôèþî êúìîöÞþ úæö îôüî îþìö þöâü æòööüæüôìöîúüø òð úìþöòú  ìúúö òìþþèþüîð öüøò úôüðú òò øüôîúèøîüöúøìþüòú øüú ôúþ üð þúôþ òúþú öôüüðþôø üüþô üøüþ ôòô úúúð þöôú îüê(âÔòFþöÈ ô6òÜàì>ÆþÞú.þ2èâøÆ 0ÜÈþþ>þôòÆ ø&öÔêú, þÚ ðþÞöøú&Þâ$Üúêê (îÐ .ìàêö0 öÈø0öæØä6 Æúâò44ðÞüÂ:àÒâðJò¶ú8úâÔè,Æøäô4,îÞþÊ4ÞÖîø6îüÈþ*úäæ ö"Úðüæòò(Üè"Üöîæ($þæÒ2æâèö. îÂ2úâÒê$"Èôèî6*ÖÄ>äÜâø2ô Êðüü>øäÒô8Èò ü ìòþôúüòþþ òðð( Øê$üÎððô6üÒØ.Æà..Øîðæ4$ØÔ &Þþäô"þòüæêôþ"ôæþÊ:æÊäòF ô°ô:òÔØì6 ¾ì,øÊðôú,üäê úüþì òäðÖúìö.þ òâþÞ. ÎØ"*Ôðää22ôâÊ $ÚÒ0òöòÜ öêþòüüòèØþ6òüòÎî0ðÈòþ>öâÔò2 Öøòø, ÚþÎ  ÌÞ"Úüð üô&êðèà&0êäöÚ0" ÒÜ* ÚìúòÜ 6ìÌìôPþôÈð2æº,èà   ôâ "ØÎ2èøîäþ ôàê"ÈøÞð4ú(ÜÞòÔ.Îà( èþúøú âð *îèöþúüúü þþîàø8êú¾,ê ¶ @äÒü,úöøàüèæò0 Äæ*úÒòöüøî  Þþà(Èâ$üÊúò  ,â¼FäüÚâ,ü:òæöÎ  &òÆ$äê Üø4æÌÚò þ öì 0þäà ô,üàüúü6ôØä< üÖø@üþæö äØ àôú þâî0üìüò "è¸8Þ¾þø,ÒøðôòÊü 6èÞþ úêüò4âð òÞúàö4þäàþ>øìèöúÒòúþ6øÖð $øüþæ".øàüÒ$$Ø ä,à "æì.èæ ðò¾$ØÜ.êúòòö ,êÀ&îÞôú  ÈèìöÚìþ úüôöþ ôì 6øÐ âþ&ôÄ ÔÞ0øà $þèúÒ (Üâ( Úæôú0öÀ "ìþüþø àüüøìÚòFöììÖ"öÌâö@ôÚôø äÎØì"þÞöÖ ,êüè.æöþîúê2îð öîüî(Úöè ü ôúò 0èÒü<èôðà &èÂ""âæ$ Ò $àÚ. öìúü &ðÄìþô ööì*(âèêÚ,òäÜüü"øøþüôòæúôþüüî&þìø üúø üä ò ¶ØÜ(öøþê ö¸(üìúôòî,"Öôð.ò Î&ìöð òþÒøøööÈä$ø Îþàâîúøâ, êÀ"Þî$ ØôìþüæþØü*öÊ&êðúòòè üÎöê&î¸þ$òðöú& úÐ ì4öòÞþìî þúþè îØúþüìøà,"Üè*ôöðÚ@øôøÜ,òîøòìü&ÒòîúØîüòþòþôèò øÜò:ôøîäþøØòÞêîôð4þîäþ$þúþþüè,æòîö$ú Îþ.ìòìî*þâôøôøþþìö6èôäð"øüöî 8èÜò@ìöèìüò úþúâìüè þôþøüúøÜ üüü øìð""Öôèü,üÜüþ øúþê$Øüêþüüêþ4üÜô&èöî èþðôòÌ$"äØ üæöðüÖþþþ öúèú"ÐüêöüÔ àúìøôÞþðüôæÒ ò*êö öìØ Úìòöüà äð øðþüúòú (êôæì$ÞüôüüðÌè"ôÈþêî  Ôø8ôæ þì$ðâ  ðþ þü úþêúîþú îì $Þúæþ$þàúøöúØô>üôèêøìî òòìò& àäDìàöôø" îôþ òúøî ôîþþúüþ îúðø"Þîúæüúø ê"àîüüò 4öÐø8ââþþööüþöþìöþþ ð ðêÎðüèþþøäèøòþî&ôÚ  âú$üæêô üþì òàôüþþüæþ þøòô üÞô"ôþîþüìü üîê*öà þ(þòò æÒàò üì öôòþ üú úþþöøøøøòê ú,øìø öôþ*üàò&òðèäà üòüüîþþüúìððúê îò òöü þöúòòþôôþþøþþì ðþ"ú Ú ìêúüöþü äþøüøôÞôöü üòøü îôþòþ úèðö þèüðÒ  ìúø þüüòü þò ôþþ þú òþüþôúü èöüðþöîòú æ ôæ øø öäðøüâ þöè þúøþèü úò øøüöøþúþüüþ èþ øøî úðüì"üîü  þüúêööúöþôöþøþòüüúòôþööþ òþüðü þî ôþúüò þ þôúþ üöòæøôþîþúöú üþô üðúúöþþþòþ úà  öüþü òüüúôøüôú èþö úþðþüþüúþúúø üüê þôäøü ôþþ þúþüöüøú òþúþøèø þôþ öø øþþøúúþþöúüþüôúþöúúò òüöþüôø üêúüüôøü þü øüþ ú úþüúò öúüüúþ üúø ðþø ö ôüüú úþþüþôúüðúþþôþøüþúúòüüþüúþ úþöþòúèö øü þø øþøþøôúü þþö üþþôü þöòô êøþüúüøúú úøúö üúøþþþøþþúöü üú øúþöüþüüüøüúøþô ôôþþüü þþú þþþøúþþôüôøþúüþüüøüþöüþþüü öüúþüúøúüþöcrossfire-client-1.75.3/sounds/MetalCrash.wav000644 001751 001751 00000057402 14165625676 022051 0ustar00kevinzkevinz000000 000000 RIFFú^WAVEfmt +"VLISTINFOISFTLavf54.63.104data²^üèþ ê(ÞÜúôîöP,4Þ òÞîÔöòæ²ââöÚ\,44 êòôàìÌ òþ( @Øø& (üþôþøìøððÎκ贸²¢ÖÐÚÈÔÌØÜÖæØäìîúôþòæü"4Hdj|^"úΚž€€€€€€€€€€€€¨´Ðä$2>`fDdB6 ÚТ¶ª¤¬˜”¶ªÄÒô 0,02px€j@P^æÖҸ܀‚€€€€€€€ˆ€€€º ¦Ìªîúþ@"8"""þðØ¨¢„”žšÀ²Úì(8$ (&r4ZRZrVTH4 @@<~RZ&2èêÔæ² €€Œ€˜€€€€®€Š€’°Ø>0Zlv|dú°Ê Ìʶ¼ÆŠ¨¬ ö¼ôÒ0Th\dx€tðH$¸²€€”†Ø¦Ðäö"ø:~|jX&”º¦¨ÌÂêæÊêàð`N,€ÀR¨ò(šÌ´,î.Þú$x ÚðìΠ¦ÐÎÖ@L€öHD(ŠÂ€î&”öêæÎÖʪں҄¤¬€îØâêø :ÆTþö<ðÖ<(VüàÀ¤²š”êÖ˜r2|¶2XxNZ6öÐ̦èìúÞ úèîèâþ>´ÚÄê"Öþ´ð0þ&Ú\v(bDfÜ6JÞ¼â¦˜Ž€€€†°°ÊöÌôlDX2ìîÐÀšÜʘ¾ÚÔÐ|~TR2þÄÄÞŽÎÜæ**öfH~búöšÖä€–†Š¢ªØ¢òìðBÚö$ 8*NV2, ä æ0ZJ8vhd>4" ðàÜÈÊÌ´¼Â¾ÚÞî4R`jb@ìò°†€€€€â®¶ÈôôÆÎ$ÐÞ¬Ðœš°’º€¦ÊÄ$,xÈ^NzvdZ4$ÖøÀ¸Ð ÀÊÜÄÄàÊæêXVN.zTh8T:øÂ¬€¦Ž°®œ´ÄæÖâ øRh6>"ôÒ˜¤˜˜¶žØè8ô$æFHRD(>> úÜô´ªºÆÊæÈR@$&\rz|Xð:$¦¼’´¦®˜ÚÊàØÞðþ$$L&^npZN> þÚÆ¢€Œ€€€€€€†äÖÌ00FTDLH$6òL* bdfjpZä: 8.Òþ  >&"d*">þÚøÖ̰ä¾ÈÞè,޸ª´¦¦¾¼°È–.øD¾"$ @8@80j26ê6 òØîÀâÚâÈÖúâ¾ÖÞä Z4X~0nR|ê¨ô†êÊð€ª¨´ðÈè¾.¼F:šüº*òÖ®¶ö ôâ¢ÌÆààèðò8þ ðäâR.:*0.\0DNl0N>0úàìÞÜàÆÌ®æì &8R(d4 öòÂØòèúàÌ®ä¼Ð¾ž¶˜ÜàÌ8æ 0&>:ܶ¶Ø’øîìÂÌÌÌ $l4.*22"nRZDfNvÜ2@ÌäÎ´Þæ°Ö¢êîÞúbRR@@"B øÖÌÜÔÈØðÔVLN8àÐÎÌÌúú èÖìøT ΪúÎܼ®ªŒ€„€˜š¦¼¶à NdBt@hP2 θάü¬´ÀŽÄÔà"f:&4 :04þ¾ÞÔж²ú>èì"lTRd<6*öìÚÄȸâ¼Ò´ö(ìò¸âÐè ÊÜ騆 æÖÎøFºúì ,ÖÔþüþ.d|:4¸ò¾ÔȲž¦’¬¸”¬¬ÀÜØ(6RHnbl@,ú&ðÆ ÐÒÖ„ÀªÜ¼Ìä¸äÚÒÐò0B\JTd\z.ph "æÌÎFð€À ¬°¢žÖÊÞÖæ*.6P0$Þ,BüÞª Ð¾ÌÂèðø Ê¤ìÈÚ°ø""B&Ldæ8 àîô &`|DdÄ*æìè*è¾â–’„ŒŒÌøÞàÊèØèøú2 òìäæö $&@àXlnjx,66ÖìäØÚâ&HÂ0> ÆØ²üìöö¨º€¬’Œ¶¬º¸øè zDXN ¼ÄºÔø àîèÂô öD~ø.Êr"4üÂÔ–ÀÚÐèœþèjü$ Ì,öþ&.&zdt`6r2øÒ夸š â ÞÌæÄ0úêÌêØ îôòüì(HR$ ääâØ¶ØØ.ðìâü4ÄD2°Îäô–ĀζĶÆÚÐ pX<Füþø¼îÞ þ|0àH0D X\|r^NDú¼ àîØ„˜€œ²Îà´öò,úÔÞ øüTXî...ÆäÒ®¸²êÐêð4H~2î ìø² Œ¸¸Îú0Øð"èÐæÂðÌôìê þtbfð2@*0T,4ê8ÄÊâøÈè˜ìÔÄÎÊ¢¤®ê´Ìè ($&H:BP&P>n:* .þÈÔÜÀ¨ÎÊà*6þP>znt4pTî‚60ðìÔæŠ¨ ¢àââì¶ÌúPöêöü2Ü ø:èF<T ^>úúŒü¼ª¼º¾¸ÈÜðæ 2D<^`r`>.ÜÞÈÈÌÄЬºƆÚÊêòüÐØÖà ìþì  2Xøþîì®Ð°ø’¼ü&îø¸øîâ$& ðJ\>DìÚæ®ÖÚäÐÔļ¸ªÌ–¾Àäìôè(.TH`hpT~d"&ú¦¼–ÔÈÒ¾¢°ž®²¶ðªòÞ8âöô6Rt|L:üþôê$,êäêî̶°Â¶Ì¶ TTD@úòü äîèô¶ìê0*øüòúîÈÚÔàúú,z~pNjüÖ¼¶²ªšž€ÎÀÊêܤæ,F(B6ìÈæòðTø&*&"< ôÎöðúôú æüî(`06.&:$ÞèöêÔâÎüôòîôîÊÆêÞðôòÐìÞöÊìæâìÐÒâØ¶ôîúöðþ `DJTFBô ÎÖÔºèìÖ(ÔúÞôöÐàîôÎÈÒàØø2@Lrdh\HT6R0ÖìÜöÜÚâèîîÚüø$ <4F. ìúìÌðø þîöîÖúÚâà¸ÎÌ$H(BR\TJøÌâÚòîø0 ,üîàæþÚÌÚì (ü. Dà.òØ´ÖÒ´ÈÒàîÌèäB n@Ò.ðÜÞêÖîìøþ4ÊN0&.&$ÎàÒÜìæÊú2 &$8.êüêÚâ–ØÂ ÖÞàþp$@ÜDîæ´Î¾°Ô¤ÀÄÐ þ6öú (" Úøì:4(<Dæ,2FîÊîâ²ÔÚø¶Èêò,$.P6ö86"È*üòþ üì  ÜæîÔØÌ²þâèì:"2>8":Ô$êòØÖèÌÜÞÊ" (vè@,"ôÂöÜÚÂÖìþô ~8J Ø$ò,ð¾þäîÚÊÒò .ò, øæèè° äêôÜîÚøúðT® ..8ìF6ô˜àØüÖúèÞöTê*þ ´ææÄþèâð ²"*H Îâl¼òÊúÞÔÎîô \ú( $ÀðÈäøÔ8ì( Ðî®øüÔ>"$<(` ø.àò ÞððàÆôòüè&þàúÐÊüÀ¸°ÆØÖ¼þ|8`P6B ôØÊøÖö*öHîH6N8(ú0þèîúØJö ÚNþôöþòüôîþðòòê òúü4&.(ìü(ÖÜÀºÆ¼ÌÔÔòÒ 2l6N<Ìʲ´ÈÄþøüü:ò  < $ `Dl6 þðâЮ¶¶¢ÔÐìþäøÆÜò<2òX0@úàêêìÊθ°Â¼ÞÎäü2(B 6VF@ôêÆØÆÊÚêàö8à ø(ð îæúä.(>:<@0øæØÈÄÌØàðþ .* H ,$@$4þêÔ¾ÜÂÆÈÄÒÊÚöü  øøôþúøøôêèæöôþ ,T@HF@\82"ò îòêÚîäôþöúøöü 2$ÞöîàÖæ°Üàâ .üúÞøòþòúæèÄÜàìþ2*:>844*ü4êöîäàÖÚØÚèâêîôôúàæèìúþ0$6úöøúÞö ìÚÖ°ÌÈØîî $22&"&"4ØîØÖÊÂÆ®ÒÈþºæäü > $  ø <,@<6X@v þìâòØḚ̂¼¼¾ÊÈÖÊêþ,  0 ,ØÜìÜøÜâØèôþ$*&"B2$"øöÜðæüÔðöþ âðÞêêàÚâôøê V06$&òþðììæ Ôà¼ðÞîæâòêø.*îúîüúæèæòðì(,:>NDBD, îøÌÖÚàÐàºÞàðøæþ ("62,* ôÜâØÌÀ¼¬ÆÎÚò$.,F. úààÊÌÞÞþÒúè*,0,øü" þ þìöìúö$(.ôôöîÔèÚÞêâöÒäÚîþúøâþ þüôúöøôêøúò ($. 6*H:0DT08üòêüúðæÞöøúð öô üôä´èÈÄÒÀôöôîøÚ"üæèþîòìæðò(øêúôøøúøü èìøìøæàæ:J<DL@R*&üöòÞäØìØàÌøðþ( <<.0èÜÂ̼ĺÎêú$6&2(bD. öôÞÎÔœØÊä¾Ôàäð,ú:  0 F0ÊþâôôÖÞ¶ÚÖôÒøúþ(0"2 üÖöêä¼èèòÎìúÎ *D   B "   üþòÐиÐÒÜòö  .&D(<î ðøúîÜ $( >JB0 ðèæÊ¼¶®°¬ÈÆÐÖîòü &4   2üöòúøü Ôü &øúúøöò îîìàüÚô øô ,þúæÜÖØâæìüêþ øðüòôúêþþ ò üúüøòþäîØòôúæøú" & ðìúðêôêü èú$îúèôøì öö"ôúøðò" ô"4*@0$: þþøøøÜæÚîò þúòêðîÈØÈÖÂÆÐÄôö* .*öæôàþ þèì   * þîìîèòøþòæü à üü  4ØêÌêêкÊÄàÌèúþ$(þêìÔØØÖìÚèæ66@,^6@4*2òæäàÎÌÔääÜêæüþú4"(2* 6000**"þúÞÊÐÖêÖäÞúü úôþøôÒäèêôüü*8*00$.ÖèÔôæ * , .üôôÞêäîðææÞîð(þ Þüôüöòøæ êøØØ( ÔòÚúðìðþò úÚ&0öþî$022:FJ2* öüúâöèîÚàæÚüúîìöúèþö0îòîêøî &,*âìªÒä¬ÜкÞðöäìôþôúö(â8ò  èøöàöôö*&*ø( Bú8 Îôòàü âüððØÔÜâÈÚÊþþ(2J6<*R*ú*üòØÎÒæÖìÌäìÞ øþòüH<8:0 8ôø.ììø@ øÜèÜÜöì*ôê."(& äøøÞôúΤÞÈ äðøÔò8(þúøàæÈðìæúþþÞ"ú< 4 ôöððüæ006æ0öêöîÜôÐøü P2ò ìâðæôèøðúöìöÐôðâ èôöÖæ.îÜþîúðòì øÔ0 ô ö$@øü** îðþþ,üúüÒððøìòþäèôæþ""& ÚôªàÆðèðÌøô.*0D òüÌòøÜ, B&:""&öþ ðæìÜÐêÀ îÚòøüþ$& Üúòîøôîô¼ðÞøÈäèêØø$ÜþÜ$ þ*"P0:@H2èöÞØê ¸ö . àP"HöøàäÖ¸ÖžàìôØÈâêæ <ô,T"ú úìèÒÄÎÐæêþÔò ò ðP20 îúÔòàöø üîøîúþò"äòÄò$0BbæîäØÆÒÆÆ¾ÎÖÒüþ$ (F*,øØ úêÞüú*$$J*2<..*"Æöôö,"* &&(H*ôêÀêÒÔêàðêòø ôðæìØàÊôö2 4 . ÆîæêÚæèàúê F & ììÒÊØÔÌâÞÎôú:.è*&ôôððöúâ .èðþ&ÜæêìôìÜ ú "& DöøøÚèÔÞì¼þöàúøèèB"úüàâÖàä¾Ì´âäð&&6,F0& þÎðØÞÒÔèì"6$&$úú øøøðÞèöúüè (ö:"6èîòòîþðüöîäìÞ66,6,*"üòðÎØÎÜææö@DBLL8B"<ä²È´ÖÞäèRL.. ØÚ¾ÐÈÈÈÈÎØÚìöþ  êøÞúôðòü$ìøþðèú((úòâú 2"úôÚäÚÜæÚäÖâîþú ôþàààØìàìôôøööüøþèîø$,$*(þüîöôðüüìú,("úôöðöäàÌÒÜÞÖäîôü ôþôþüòú üôþô"  2 "ô * $<0&$èôòöúîþð" øêØÎÆÔ¾ÀÂÎÔÔìúü*  ôöÚàìôúèôþê" ôôôòôø*&,4&6øüúþìüúüèþôöØìâú è(úüæàöæðÎâÞÞÖØÜÜÔàÜü$ H"( øööààÖÞâä  .*:(8&"äòôøòäúþöøþ  üüîîôè ø øà þþöúüÞøðþþ  ü" ($ úôúÜìÞúðöÜþ$  ò øüîöúèôðîöôúêôöìþôú þòèÞðêòîððô  ">2: (  îúêøòîÞüü $üôòúðþ ÚØìèôòðäîæîþôøîöêþôøîÞìàðôðêøúþ ðþø B 0þ ðüú  ìôîîìêþü& (þüöôöüîúøú   îòäøæîäüü  þúüøôüþð ø úöæòðöðòøòøü  þàôì ööø úþþúüìöòøð   üúüúôòìæâæäàäææìæèêèäèæòòøþþúþöüü  20:840$& öüúøôø ôöêòèæìÖæêèÞäæüèðæôòàîâòØèðö    þîèÚÞäèúü BJlhjlbTH,*êÔÒÒ¶ØÖðèú$,2:40  üîäÊÒ¼¬²¶Æèðø$  þ þôîêàÒÐÊÂÖæÜàâ PLfZTZTH Âîļ¼ÂÄÌÌÔÚôü"(:JLXH2FòöÖÖĺ¼ªÄÐÔÌú @:"N<<* ìäØÊÀ°ÈÌÎæÎøþ$.(NDT:@(pöàÞÊĺÆÊðÌôö& & 6"üþúúäâ¾àÐÞÈØÞô @îðèìÚÜÚ8 &60*:úúðàòðþòþô"$,(4,*$øÈÜÜÖæÔìüî:*B2R(üÚ¾Ȳ¶¤¸ÂÚ*XZZH<2àò®°–¢¦ª¾ÀÚð6.><.."(úæðÄÐæîø* ,0êäôêöääÌÔøü&0>LB$. ðòäÎèàÚÖÌÖØÔìîö 4$400@&øöÐàÒØèØÞÔÞè 4 :,&üêÜÜÒÚÈÞâôþôü&*0"4 üúêð¸ÜÔÒìäôö DB80.$øòäøÜèÎâîô6,2& ôöÔøððþÖðÞ,,> þðþÔÜÒêÔæäø :"&"" þäüøüô (úüæüðäêæèÚäèêìöòüæìæâüæòÒúö üò$  üüîììü "$(208*, . üþàööôø úúîäÜìâöàææîæîôôèìòÚôôöâîòîâäàôìúö (. üþæúòúúú*$,.0:($ úèðØôøüîúøäîÞÚàØêòðøôü &þþöôðàêàâÞÞìú$.DHR<LBD4&$ èüþúö  þúôÞîêôê "2.0& üöðâÔÒÂÊÄÂºÊÆÒÀââøøú 0$*& øòðþô.062:& øîæàâÖèîøøö *8NXTZ2.ÞØÂʾ¼²¼ÀÎÄæð(ôìâòòþðôðòðøêø,"28*" üìäÖÐÎÖØÞìü$$:*.8$"îìØàÜØÞÖêð 0,"*ðæàÐÚÖøêðöø"&"$$ôìÔÊÂØÊäÈÞð.(",,&&$    *&&&0 : øæâÀÞØàÔÔæðü ,.20$ úøôðÒÜÎÔèèìðöò 0ú(üÚæäâæöö æþ &08<FF@.&ðàÒʾÀ°ÒÔêè0>PF:BBB æîÚÐ̺¼®¼ÆÌÞîö""40&"þôàÞÖÚÔÚÜîôúü  "260(öôääÒÐÌÒØâîü *,4&80&&ôæêÞÜÞÔÚÜêîü $,, ôèÜÔÌÐÔäàø*44..2 úöðàúðö $*62&& òîèêààâæöö þþúôôüôþîîìøü $*8468620úòèèÜäèæôîòðèúú îúîìêèðê$"  þêæØØÀƾÊÊÈÌÐØæì"*,244&" þüôöþ    ôüòôàæâÜÔÚÔæÜàâèàäÞòö  êøòôìðîøðòøööþ  $(þ ððÜèàÞêìðö & þöøüìîêôÞòò *  þôøôîòúøÜøô üôììðìêæîìðèúþ"þúîðèââÒÜÞæîöþ  þôú6 .202,øöÖôÖܲÜÎîÆÚÚîàîì "&R *.îîæèÜÐâäÞîÚüü   ææôøö òþøü  îüöîîîöôø "0&@<<($üìÂÎØÒÒ¬ÎÊæâìú @6B4 úîþÄÚÜÚÜäêø"*20.,  àîäü"88@2,.& àêæâÌÔÜêìÖäÒ îð>" þðæÜâ¾¾ÂÜÎØÖ..B60.üâäØì¼Ð¾èàìð$<0:,.* àêâîÞàìþòô  4" úàôþâðìú"$ þúôêîäàäÖÚÜâàäìðü&@.0&ôæîØòúêöö <*þæîæôÚæìòîö"0,2üêÜÖÚÔÜÔâèòþ *&$" òðüðîîöø"6 & þþüüø  2$" üèêäæäêðüêöò $  èìÔäØÎÄÀÚÚîâôú úöîîæìêüøþþüøøøúööò "$* þúüüööæòðöäôðúîöòôèòäàÜäâäÜúøò 8$*þ òÔàæòæîîüþ&úþ  ö,üöæèæàêèîèèðôú ðþþ  þ  "" úüþüüüþúôî þðþøþøúôúúôðôðîîìêüîôâöúìüüúöþþ ü þ  òøþúôò øòèèääØìîòú  þüòúìêæÜæèèðöþöüþòü ü þøþ  øþøööôööøüüþüþþþüüú  øüþþöþ     úúþèüòüúìæòîøøúüþþøôúöøôøöôöþúøøøöüüþ þ    ôøþþüþþööôöøøþøööøòðìúøööôüøüúöôøöøôüþþ ú   ø þþ    úþþþôöòúøþ   üúþüøøþ     þ öøöèøüúüîúòøöþ òüþüööøÎîèÞøî"æ üþþøüö èøììú üþîüþ ì úäöüôúæ àþðÚôìêüôüüôööôòúêòþúô$ð úòòö(øà þ ((þ ð ðì þÚüÒôüðò ì ìúü úÞüúúþüìÚ*òþøòö òü2úðüÜþüüöü üüòèøøìööÒüðâîæôüðôöööä þüö*ôþ *&øæ ü ðôæôþöþüðòìâþâìØúòøðîøúþ üüîþ îüúøøîúúôüøøìþ þ4 ö  þ þö úþ úøòú"òè úþô   ü úþþ  þ  òþüüþòôîòôøúäòòüðöòôüüôüüþöò üüôþ ü   þúøüôüüþðúôîúúòúòþþòþþøü ì þúþþþþú    üúöþþþøúøþüöúòüþúþô  þø  úþöþøúöüøüþþþüþþðüúöúüöøøúþüþö üþ      þþþøüöôöøööööööööøöøôööôþúüúúòòðòüúúúüþþü    þ   üþöþôúöüüþúúøúúþòøøøúþúþ        þ     þúøöúöøôøðìèèæêäüöòöôøöøøüüøöôöòöüúüäôèôööü$,"" úúðìÚèäîìðò&(,4& øôòèîðîúúü þ øöâöîðâìèðöòô üøøìäÞèàäêìîöþ &$ öüúøæâàèÞäèèðøòðæôòîêôôøþ$**2*$öüôîîâôö üüöþøøøøúø úúòøôòðìôôü þòôòìêêæìîü$ úôæêäôôøúþ  "2ööàÞÔÜØÚÜÚèìü þòìòàâÜìððòô " üøôööþôüþú  úöþôòòðööü ( úîîèðòôú  úüöüþö þ   þþôüöúòöüêúþöööîòòîòâêæìîðòúúþ  þ     þ  üüüôðúüúüúþîöôúøôòôöòôìòðöøöúòúü øüøøø  ü     öúüîîøüþ üþìøüìüþþô   üüþþüþ   þ   üüúüþüþüúüþþüüøôúö þòöþöþþþþ   øüþúþüøøööøøúüþìôcrossfire-client-1.75.3/sounds/claws.ogg000644 001751 001751 00000021067 14165625676 021114 0ustar00kevinzkevinz000000 000000 OggSî"‡*»vorbisD¬w¸OggSî^‚*Ä-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎvorbisXiph.Org libVorbis I 20020717vorbis)BCV1L(Ä€ÐU ˜6k§µÖZk‚¤vZkªµÖZk&µ¶Zk­µÖZk­µÖZk­µÖZc 4d@(J´dRLJ)e GŽrä9HÊ'¥(G bâ9è=õdkM¦¤ä[MJ)% Y@!„RH!…RH!…bˆ!¦˜bÊ)§œrÊ)Ç ƒ 2È ƒL2餣Ž:ꬳÎ: -´ÐB ±ÄSm5ÖÚsÊ(¥”RJ)¥”RJ)¥Œ1ÆBCV BdA!…RŠ)¦œr 2è€ÐU €ÇI±ËÑOò$Ï-Q=Ó3EÓ4MÓ5mUwuUWuÕVuÕVeÓ5mÓVeÓUuW—uW¶u]×u]×u]×u]×u]×uݶm 4d  #9šâ)¢b®â:ª„†¬d  ž!*¢&j¢æižçyžçyžçyžçyž„†¬ iš¦iš¦iš¦iš¦iš¦iš¦išfY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY–eY@hÈ*@@Çq$GR$ER$Çr, YÈ@R,ÅR4Çs2bí××)>I>u ë2ºŽí6£K¤]ìùÊ×Ù¨yùh­ŽyO“©yT½¶¿©)Òì%S·ßïCÍvÊ¥î—'¢þ §räý†ÏfBgÃøçåh4èù¯)¦}æD•m“ü,øM~!Õz¡¼ÄQh3fðÓúèáj»? \€Rù±Ÿ½ÊÛHª±Ï_äÎäÎòº¤,¾*ªø ÷êm‡:ëq!ŒCߟ´QûØO1ïÔ!o;¹äØÂƒurC(~Ê)¸PÑ”ÓK±¯Ý$Ù/¾_ZË“zž ¹ÏÁG¤aÜÍ[¢ã!xÜ'A®ø²é/é°­W¥ë‚âãß“]—ˆJÔãwùÅv›"q³œ™vú†®À€ ›š®LÚ(Mr37¸.¶ÚL™žØíÚR–<¢sj¼ÃG¡:Io÷äæŸ[xôý޼Á2`óïê@eÒ±`ÈBÛ¢Y S;Ób¡…JüÝ·‹:k­³¤H-³]uó¥( þ7༤ØÈ+0!5O>¼<ÃHo…£HÒTóÓÆ\÷X8pJ &oy:®¨ùÔ~š¼aô÷ë¿ýÂÃJežvM‹…º±rB 5Q cH¾æÒ»ùeh¹„N—߀0æÛ Ü8Ò÷g”âat+ðèWâdpF[û}Að{C¥Í_Þƒht鶪ÅýñBõ/á<*¾øÃ~RòßÕ‹šQÎ‘Š‰ø/ƒ\F\郇ñö )€‘àaî|\qC†ÖJœŸ×mWýà*ÔC©:Öêæ7O¦ïkƒ‹™|$*o<€0®³ûjÈ؆ëæ'q#²µcK|Æ/èÐÓ…ÝD÷û¼‘œ¯-ÿ¸i42Ü]Ì«‘vOã§ 4(r.Þ–³µ)ŽL?58d½Ú*¥­*AЦU?œ ÔÖ*r &èìÎ` \D÷Û9{Ú'.šycŒÃ”Ó(^ÒÏ$ø]Ù‰¼™ƒÞUÓï@­^žsn“?¼p>Ÿ?`&œ&®ïaµÿë‰Õš¤ü‰þÎϹ‰k›4:ÍVC6íÙ 4Äê§¹:0KÁÁfÎÒ‰ ‘ÿ?à29Œ>)ívë|ÁðÄ9·¤†«M0Æ4Í*#xÌÀ÷ŽùS»“dÏ;þ…­¹Î{(=ã°%}Vÿ•&7µ&fÍ’xÛ-‰J’=ùhD¿.hÉ®¯¾ò€ 7 ¬ž™Gš6tk´-£­ß¾£°\£Áºþ=|³'m61ï陚¹amHuzúzX7£ÓOtM³oûE2£e—TZwˆ\Û$à߯ÛŒ’‹ô™ô¶MÒ&W -fÑÈ„rˆˆFèîL‹­Åi,>©Yåt{õÇ#÷ª¯Ž/F´Òo÷ˆ8>)íNþ˜Ã øÂtì‡&$0¦´D‘4¥dO´™Kóöžž~å׃޷´Í‹Fþ$¦úzè«eºH±¦mÃ~Q9;ùÓÙö1F•¬è± âxZ³ç¡•ÉÔüMùn5%²>ß÷eÊ7ÐMÒ¢ÄùÁ>ïÜvîÏ”ÿÅŒ%Œ ã»Ô°ÑXÏ=à¶L7Ñ”S6)íNxÍŒà ¡¿Íû¿oág=D6/À˜Š€ß’Š”‚lže~o;7Û‡_ŸÑâþDw¾¸<õn.ó‚᪞b™œî]02NöO†ûëh=9zÿ¢.ÐjÌÄ”~üÉ2©q qwK"¤1ÔÜC·$DSˆ?Ž)ø°y ©WÊ ôˆ=µûBëÔ£4óŒ¤ÎYaü‡lÎüÉ|f¥F#ÈKÚý©@çMêNCjD™SºýH¦öÛ!ø˜Ûnµ:_œQy8ÚRÆ;y÷÷FŒÒ"6³nà!Ê‹Ño'EO+%¾h-hó&<tn—î®X ÷´Í‹ÎT‚‹ÿ¡ËÚ”“9»;ñn–oc~`ÈßÕÈGf?U! Œf.^HìáUB²Éæ4^?xèËaܺ,‘·Èq^µ~®^¨/7q—E¬R‡.@2}íàåÕûÂqP´ýyšÉŸó\‰Ø'N¤D¸i§ ¿s@ç]Áº êw:D>oŒcþð0¾™ Ð̯½™tÌ-þræÍo§C:¡@‚Åc*–|>—wæcUúœì¡P¯¿ýš¤gûêRžÖ¬¡ðªþòm5*1½TZ_¼`Lé„›Q~Ÿ¶hœ¦›rW¼À†;u1)u “”#}šimäfÍ2Œf®f¬lo½¨.¬¿Å Ü´û˜uòP›ñú§™lp¿»üql_Aƒì”| ¢5ÛJ'tb—Ï^Q×Xð7˜dO±»¿^3/ï0¶øædˆóã)^he>7£óC>LÄšuëcÜ.›åWŒ>ËWFçkô!œW>m½–ܺ\ð½š7²*×/[ïz‰ð˜^²ÚK'ØóØ Í¼b‹Ù¹?• iºßãÒäÛÝÝj]ú<»à1êò—ïP}\ïêÀH7iŒn‡^¦üK¨› ü÷¸v, cº&áâÉЃ§’ñÂ#»Mí7Ö[©Æ_´æTÞ‚Xm{´nKgæBå—,º9aˬ·ÏãO œï‹šØÁÚZq<Ĭ¥7Ôÿ Dbo^¼`IÞîˆxɦ†SHyÛÒÏúæÈæC¿@’jñãê\ê™÷ù%lnî~Ú®ç¢2‘ð,ÁoðBÐév\²É‡ÁÛv7dñãÖ±Ÿt^gA0 dL£¥$Zœ>‡F3’ñ&RÝ< !D~ÞÙvb—:ß8nlÌǶQ?Xý Q¾Þ3¯¡ö!F±¬cëXÇ:r¹d:6 \Ò‚;‚ïh`•¥Ž74²lŸº{p i×zp7YnGüåê Àf Jͼ\Çç,? …ŒFމð*YHr3þòؓԧÏ¿~è›-9së×®w»/[·ß.çñk€èâu ‚h)±5y>yµ@ûˆ¯w?îï¦^²vñs¶äQ·Hq°ï K8Ûì'gŸkT3Ö‡ƒÌÕçÔz‰>eTP8`ÏÀðiÔêk™,ÖWSp¿Ûµ-Û)ZÛ „óøâ ڣخ<5?½ÑéKV ƒèE»‚(e!÷tÊúЕJÖû±\rÞÚ¢b©—ô$CÇ%ô &i`NòKcßÔ×z´ÁñkÄNŽƒIsLÒþ„J‡F%³àVÄ·_3!š8¦;K­ÚÍp æ¾Õ,xò+l¤7¼•†0æõ*\:À²,èÃï7²!–ž6ú#báߕ뾖œÚ€½¸{±–`¨@xT«‰2o×›ºfË^æH—È‘AÛí·e³-Óœ6lŒ=;¾ý<_JXÌͱÀe‚Pÿïÿÿÿe›D3H„óðAåEÐÀî︙ZMf^*×24ƒìAVmg_mIK½žcw¿ë±OTÄ4n«zX ƒN ô±ãå¢×wÌÃq¼Ú<«K³BéšuË@ƒ8x†‘̤ð &FÃúÚÓtê3ltn8ÿlûõ³®?Ù¿™›éq‘¶Ú{—q>cyqz!'ÇLóÌUÖFž\‘)G£e¿Xm‡€Ú¤âΘ©»ªEjìøfõMm¤mìž§3’92j³“ò3Nù) 䳕( TTÄDõ§“±h"''ôÍHl•hlXÔ.W{ѱêyª6ë»§Q£€L:@TUg¶ÒÞã­kù'Îø»u,¹üµÏQ…¬Ó5üQ¢ì«4—#ú OggS`@îÿ2ïÌþH$L&±‘"yåFû5eM6¦¾(ÄÁ*«ª¹w?ï&Ö§¯Û½rñì<í¼%±´ëW~æy—ÔLŸÉæ8Ÿúà®5uFp­l{uKfË1;ÿÐIÎ0ßE€M´ÑýFǤ«b0á–HÕ‡½§ëýë£ZŸEeË^¯)‹ð]ÔJ5ùüéCÊÑù Ÿ¸áMïãË=™žžÞ HÖ30ÙŸÇ“­Àg ào<å2p?»1HïÊ*Ŷጦá¶UÁ6Ûcrossfire-client-1.75.3/utils/000755 001751 001751 00000000000 14605665664 017124 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/utils/pprof-latency.py000644 001751 001751 00000001217 14045044337 022244 0ustar00kevinzkevinz000000 000000 """ pprof-latency.py -- process Crossfire client latency profile """ import sys def main(): data = sys.stdin.readlines() fields = map(lambda l: l.strip().split(','), data) pending = {} for f in fields: if f[0] == 'profile/com': n, t, cmd = f[1:] n = int(n) t = int(t) pending[n] = (t, cmd) elif f[0] == 'profile/comc': n, t, s, _ = f[1:] n = int(n) t = int(t) tdiff = t - pending[n][0] cmd = pending[n][1] del pending[n] print("%d,%s" % (tdiff, cmd)) if __name__ == '__main__': main() crossfire-client-1.75.3/common/000755 001751 001751 00000000000 14605665664 017254 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/common/mapdata.c000644 001751 001751 00000130325 14604606323 021015 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Map processing functions. */ #include "client.h" #include #include #include "external.h" #include "mapdata.h" /** * Position of the player on the internal map. Internal to the client. */ PlayerPosition pl_pos; /** * Position of the player reported to client scripts. It resets to (0, 0) * after a 'newmap' command. */ PlayerPosition script_pos; /** Move to coordinates on the current map. (0, 0) means no destination. */ int move_to_x = 0, move_to_y = 0; bool move_to_attack = false; /** * Size of virtual map. */ #define FOG_MAP_SIZE 512 /** * After shifting the virtual map: new minimum distance of the view area to the * new virtual map border. */ #define FOG_BORDER_MIN 128 /** * Maximum size of a big face image in tiles. Larger faces will be clipped top/left. */ #define MAX_FACE_SIZE 16 /* Max it can currently be. Important right now because * animation has to look at everything that may be viewable, * and reducing this size basically reduces processing it needs * to do by 75% (64^2 vs 33^2) */ #define CURRENT_MAX_VIEW 33 /** * The struct BigCell describes a tile *outside* the view area. head contains * the head (as sent by the server), tail contains the expanded big face. tail * is *not* set for the head cell, that is (for example) a big face with size * 2x3 occupies exactly 6 entries: 1 head and 5 tails. * * next and prev for a doubly linked list of all currently active entries. * Unused entries are set to NULL. * * x, y, and layer contain the position of the cell in the bigfaces[] array. * This information allows to find the corresponding bigfaces[] cell when * iterating through the next pointers. */ struct BigCell { struct BigCell *next; struct BigCell *prev; struct MapCellLayer head; struct MapCellTailLayer tail; guint16 x, y; guint8 layer; }; /* Global map rendering offsets used for local scroll prediction. */ int global_offset_x = 0; int global_offset_y = 0; int want_offset_x = 0; int want_offset_y = 0; static void recenter_virtual_map_view(int diff_x, int diff_y); static void mapdata_get_image_size(int face, guint8 *w, guint8 *h); static void expand_need_update(int x, int y, int w, int h); static void expand_need_update_from_layer(int x, int y, int layer); static int width; //< width of current map view static int height; //< height of current map view /** * Contains the head of a list of all currently active big faces outside the * view area. All entries are part of bigfaces[]. */ static struct BigCell *bigfaces_head; /** * The variable bigfaces[] contains information about big faces (faces with a * width or height >1). The viewable area bigfaces[0..width-1][0..height-1] is * unused. */ static struct BigCell bigfaces[MAX_VIEW][MAX_VIEW][MAXLAYERS]; static struct Map the_map; /** * Clear cells the_map.cells[x][y..y+len_y-1]. */ static void clear_cells(int x, int y, int len_y) { int clear_cells_i, j; memset(mapdata_cell(x, y), 0, sizeof(struct MapCell)*len_y); for (clear_cells_i = 0; clear_cells_i < (len_y); clear_cells_i++) { struct MapCell *cell = mapdata_cell(x, y+clear_cells_i); for (j=0; j < MAXLAYERS; j++) { cell->heads[j].size_x = 1; cell->heads[j].size_y = 1; } } } /** * Get the stored map cell at the given map coordinate. */ inline struct MapCell *mapdata_cell(const int x, const int y) { return &the_map._cells[x][y]; } /** * Determine whether the map data contains the given cell. */ bool mapdata_contains(int x, int y) { if (x < 0 || y < 0 || the_map.width <= x || the_map.height <= y) { return false; } return true; } bool mapdata_can_smooth(int x, int y, int layer) { return (mapdata_cell(x, y)->heads[layer].face == 0 && layer > 0) || mapdata_cell(x, y)->smooth[layer]; } /** * Determine the size of the internal fog-of-war map. */ void mapdata_size(int *x, int *y) { if (x != NULL) { *x = the_map.width; } if (y != NULL) { *y = the_map.height; } } /** * Update darkness information. This function is called whenever a map1a * command from the server was received. * * x and y are absolute coordinates into the_map.cells[]. * * darkness is the new darkness value. */ static void set_darkness(int x, int y, int darkness) { if (mapdata_cell(x, y)->darkness == darkness) { return; } mapdata_cell(x, y)->darkness = darkness; mapdata_cell(x, y)->need_update = 1; } /** * Mark the given cell as cleared in response to a Map2 clear command. While * the server shouldn't be clearing cells it didn't send, in practice we * sometimes do clearing ourselves (e.g. when we scroll the map). */ void mapdata_clear(int x, int y) { int px = pl_pos.x + x; int py = pl_pos.y + y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); if (mapdata_cell(px, py) == EMPTY) return; if (mapdata_cell(px, py)->state == VISIBLE) { mapdata_cell(px, py)->need_update = 1; for (int i = 0; i < MAXLAYERS; i++) { if (mapdata_cell(px, py)->heads[i].face) { expand_need_update_from_layer(px, py, i); } } } mapdata_cell(px, py)->state = FOG; } static void mark_resmooth(int x, int y, int layer) { int sdx,sdy; if (mapdata_cell(x, y)->smooth[layer]>1) { for (sdx=-1; sdx<2; sdx++) for (sdy=-1; sdy<2; sdy++) if ( (sdx || sdy) /* ignore (0,0) */ && ( (x+sdx >0) && (x+sdx < the_map.width) && /* only inside map */ (y+sdy >0) && (y+sdy < the_map.height) ) ) { mapdata_cell(x+sdx, y+sdy)->need_resmooth=1; } } } /** * Clear a face from the_map.cells[]. * * x, y, and layer are the coordinates of the head and layer relative to * pl_pos. * * w and h give the width and height of the face to clear. */ static void expand_clear_face(int x, int y, int w, int h, int layer) { int dx, dy; struct MapCell *cell; assert(0 <= x && x < the_map.width); assert(0 <= y && y < the_map.height); assert(1 <= w && w <= MAX_FACE_SIZE); assert(1 <= h && h <= MAX_FACE_SIZE); assert(0 <= x-w+1 && x-w+1 < the_map.width); assert(0 <= y-h+1 && y-h+1 < the_map.height); cell = mapdata_cell(x, y); for (dx = 0; dx < w; dx++) { for (dy = !dx; dy < h; dy++) { struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer]; assert(0 <= x-dx && x-dx < the_map.width); assert(0 <= y-dy && y-dy < the_map.height); assert(0 <= layer && layer < MAXLAYERS); /* Do not clear faces that already have been overwritten by another * face. */ if (tail->face == cell->heads[layer].face && tail->size_x == dx && tail->size_y == dy) { tail->face = 0; tail->size_x = 0; tail->size_y = 0; mapdata_cell(x-dx, y-dy)->need_update = 1; } mark_resmooth(x-dx,y-dy,layer); } } cell->heads[layer].face = 0; cell->heads[layer].animation = 0; cell->heads[layer].animation_speed = 0; cell->heads[layer].animation_left = 0; cell->heads[layer].animation_phase = 0; cell->heads[layer].size_x = 1; cell->heads[layer].size_y = 1; cell->need_update = 1; cell->need_resmooth = 1; mark_resmooth(x,y,layer); } /** * Clear a face from the_map.cells[]. * * x, y, and layer are the coordinates of the head and layer relative to * pl_pos. */ static void expand_clear_face_from_layer(int x, int y, int layer) { const struct MapCellLayer *cell; assert(0 <= x && x < the_map.width); assert(0 <= y && y < the_map.height); assert(0 <= layer && layer < MAXLAYERS); cell = &mapdata_cell(x, y)->heads[layer]; if (cell->size_x && cell->size_y) { expand_clear_face(x, y, cell->size_x, cell->size_y, layer); } } /** * Update a face into the_map.cells[]. * * x, y, and layer are the coordinates and layer of the head relative to * pl_pos. * * face is the new face to set. * if clear is set, clear this face. If not set, don't clear. the reason * clear may not be set is because this is an animation update - animations * must all be the same size, so when we set the data for the space, * we will just overwrite the old data. Problem with clearing is that * clobbers the animation data. */ static void expand_set_face(int x, int y, int layer, gint16 face, int clear) { struct MapCell *cell; int dx, dy; guint8 w, h; assert(0 <= x && x < the_map.width); assert(0 <= y && y < the_map.height); assert(0 <= layer && layer < MAXLAYERS); cell = mapdata_cell(x, y); if (clear) { expand_clear_face_from_layer(x, y, layer); } mapdata_get_image_size(face, &w, &h); assert(1 <= w && w <= MAX_FACE_SIZE); assert(1 <= h && h <= MAX_FACE_SIZE); cell->heads[layer].face = face; cell->heads[layer].size_x = w; cell->heads[layer].size_y = h; cell->need_update=1; mark_resmooth(x,y,layer); for (dx = 0; dx < w; dx++) { for (dy = !dx; dy < h; dy++) { struct MapCellTailLayer *tail = &mapdata_cell(x-dx, y-dy)->tails[layer]; assert(0 <= x-dx && x-dx < the_map.width); assert(0 <= y-dy && y-dy < the_map.height); assert(0 <= layer && layer < MAXLAYERS); tail->face = face; tail->size_x = dx; tail->size_y = dy; mapdata_cell(x-dx, y-dy)->need_update = 1; mark_resmooth(x-dx,y-dy,layer); } } } /** * Clear a face from bigfaces[]. * * x, y, and layer are the coordinates and layer of the head relative to * pl_pos. * * w and h give the width and height of the face to clear. * * If set_need_update is set, all affected tiles are marked as "need_update". */ static void expand_clear_bigface(int x, int y, int w, int h, int layer, int set_need_update) { int dx, dy; struct MapCellLayer *head; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); assert(1 <= w && w <= MAX_FACE_SIZE); assert(1 <= h && h <= MAX_FACE_SIZE); head = &bigfaces[x][y][layer].head; for (dx = 0; dx < w && dx <= x; dx++) { for (dy = !dx; dy < h && dy <= y; dy++) { struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail; assert(0 <= x-dx && x-dx < MAX_VIEW); assert(0 <= y-dy && y-dy < MAX_VIEW); assert(0 <= layer && layer < MAXLAYERS); /* Do not clear faces that already have been overwritten by another * face. */ if (tail->face == head->face && tail->size_x == dx && tail->size_y == dy) { tail->face = 0; tail->size_x = 0; tail->size_y = 0; if (0 <= x-dx && x-dx < width && 0 <= y-dy && y-dy < height) { assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width); assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height); if (set_need_update) { mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1; } } } } } head->face = 0; head->size_x = 1; head->size_y = 1; } /** * Clear a face from bigfaces[]. * * x, y, and layer are the coordinates and layer of the head relative to * pl_pos. * * If set_need_update is set, all affected tiles are marked as "need_update". */ static void expand_clear_bigface_from_layer(int x, int y, int layer, int set_need_update) { struct BigCell *headcell; const struct MapCellLayer *head; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); assert(0 <= layer && layer < MAXLAYERS); headcell = &bigfaces[x][y][layer]; head = &headcell->head; if (head->face != 0) { assert(headcell->prev != NULL || headcell == bigfaces_head); /* remove from bigfaces_head list */ if (headcell->prev != NULL) { headcell->prev->next = headcell->next; } if (headcell->next != NULL) { headcell->next->prev = headcell->prev; } if (bigfaces_head == headcell) { assert(headcell->prev == NULL); bigfaces_head = headcell->next; } else { assert(headcell->prev != NULL); } headcell->prev = NULL; headcell->next = NULL; expand_clear_bigface(x, y, head->size_x, head->size_y, layer, set_need_update); } else { assert(headcell->prev == NULL && headcell != bigfaces_head); assert(head->size_x == 1); assert(head->size_y == 1); } } /** * Update a face into bigfaces[]. * * x, y, and layer are the coordinates and layer of the head relative to * pl_pos. * * face is the new face to set. */ static void expand_set_bigface(int x, int y, int layer, gint16 face, int clear) { struct BigCell *headcell; struct MapCellLayer *head; int dx, dy; guint8 w, h; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); assert(0 <= layer && layer < MAXLAYERS); headcell = &bigfaces[x][y][layer]; head = &headcell->head; if (clear) { expand_clear_bigface_from_layer(x, y, layer, 1); } /* add to bigfaces_head list */ if (face != 0) { assert(headcell->prev == NULL); assert(headcell->next == NULL); assert(headcell != bigfaces_head); if (bigfaces_head != NULL) { assert(bigfaces_head->prev == NULL); bigfaces_head->prev = headcell; } headcell->next = bigfaces_head; bigfaces_head = headcell; } mapdata_get_image_size(face, &w, &h); assert(1 <= w && w <= MAX_FACE_SIZE); assert(1 <= h && h <= MAX_FACE_SIZE); head->face = face; head->size_x = w; head->size_y = h; for (dx = 0; dx < w && dx <= x; dx++) { for (dy = !dx; dy < h && dy <= y; dy++) { struct MapCellTailLayer *tail = &bigfaces[x-dx][y-dy][layer].tail; assert(0 <= x-dx && x-dx < MAX_VIEW); assert(0 <= y-dy && y-dy < MAX_VIEW); assert(0 <= layer && layer < MAXLAYERS); tail->face = face; tail->size_x = dx; tail->size_y = dy; if (0 <= x-dx && x-dx < width && 0 <= y-dy && y-dy < height) { assert(0 <= pl_pos.x+x-dx && pl_pos.x+x-dx < the_map.width); assert(0 <= pl_pos.y+y-dy && pl_pos.y+y-dy < the_map.height); mapdata_cell(pl_pos.x+x-dx, pl_pos.y+y-dy)->need_update = 1; } } } } /** * Mark a face as "need_update". * * x and y are the coordinates of the head relative to pl_pos. * * w and h is the size of the face. */ static void expand_need_update(int x, int y, int w, int h) { int dx, dy; assert(0 <= x && x < the_map.width); assert(0 <= y && y < the_map.height); assert(1 <= w && w <= MAX_FACE_SIZE); assert(1 <= h && h <= MAX_FACE_SIZE); assert(0 <= x-w+1 && x-w+1 < the_map.width); assert(0 <= y-h+1 && y-h+1 < the_map.height); for (dx = 0; dx < w; dx++) { for (dy = 0; dy < h; dy++) { struct MapCell *cell = mapdata_cell(x-dx, y-dy); assert(0 <= x-dx && x-dx < the_map.width); assert(0 <= y-dy && y-dy < the_map.height); cell->need_update = 1; } } } /** * Mark a face as "need_update". * * x, y, and layer are the coordinates and layer of the head relative to * pl_pos. */ static void expand_need_update_from_layer(int x, int y, int layer) { struct MapCellLayer *head; assert(0 <= x && x < the_map.width); assert(0 <= y && y < the_map.height); assert(0 <= layer && layer < MAXLAYERS); head = &mapdata_cell(x, y)->heads[layer]; if (head->face != 0) { expand_need_update(x, y, head->size_x, head->size_y); } else { assert(head->size_x == 1); assert(head->size_y == 1); } } /** * Allocate and set up pointers for a map, with cells represented as a C-style * multi-dimensional array. */ static void mapdata_alloc(struct Map* const map, const int width, const int height) { map->_cells = (struct MapCell **)g_new(struct MapCell, width * (height + 1)); g_assert(map->_cells != NULL); // g_new() always succeeds map->width = width; map->height = height; /* Skip past the first row of pointers to rows and assign the * start of the actual map data */ map->_cells[0] = (struct MapCell *)((char *)map->_cells+(sizeof(struct MapCell *)*map->width)); /* Finish assigning the beginning of each row relative to the * first row assigned above */ for (int i = 0; i < map->width; i++) { map->_cells[i] = map->_cells[0]+i*map->height; } } static void mapdata_init(void) { int x, y; int i; mapdata_alloc(&the_map, FOG_MAP_SIZE, FOG_MAP_SIZE); width = 0; height = 0; pl_pos.x = the_map.width/2-width/2; pl_pos.y = the_map.height/2-height/2; for (x = 0; x < the_map.width; x++) { clear_cells(x, 0, the_map.height); } for (y = 0; y < MAX_VIEW; y++) { for (x = 0; x < MAX_VIEW; x++) { for (i = 0; i < MAXLAYERS; i++) { bigfaces[x][y][i].next = NULL; bigfaces[x][y][i].prev = NULL; bigfaces[x][y][i].head.face = 0; bigfaces[x][y][i].head.size_x = 1; bigfaces[x][y][i].head.size_y = 1; bigfaces[x][y][i].tail.face = 0; bigfaces[x][y][i].tail.size_x = 0; bigfaces[x][y][i].tail.size_y = 0; bigfaces[x][y][i].x = x; bigfaces[x][y][i].y = y; bigfaces[x][y][i].layer = i; } } } bigfaces_head = NULL; global_offset_x = 0; global_offset_y = 0; want_offset_x = 0; want_offset_y = 0; } void mapdata_free(void) { if (the_map._cells != NULL) { g_free(the_map._cells); the_map._cells = NULL; the_map.width = 0; the_map.height = 0; } } void mapdata_set_size(int viewx, int viewy) { mapdata_free(); mapdata_init(); width = viewx; height = viewy; pl_pos.x = the_map.width/2-width/2; pl_pos.y = the_map.height/2-height/2; } int mapdata_is_inside(int x, int y) { return(x >= 0 && x < width && y >= 0 && y < height); } /* mapdate_clear_space() is used by Map2Cmd() * Basically, server has told us there is nothing on * this space. So clear it. */ void mapdata_clear_space(int x, int y) { int px, py; int i; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); px = pl_pos.x+x; py = pl_pos.y+y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); if (x < width && y < height) { /* tile is visible */ /* visible tile is now blank ==> do not clear but mark as cleared */ mapdata_clear(x, y); } else { /* tile is invisible (outside view area, i.e. big face update) */ for (i = 0; i < MAXLAYERS; i++) { expand_set_bigface(x, y, i, 0, TRUE); } } } /* With map2, we basically process a piece of data at a time. Thus, * for each piece, we don't know what the final state of the space * will be. So once Map2Cmd() has processed all the information for * a space, it calls mapdata_set_check_space() which can see if * the space is cleared or other inconsistencies. */ void mapdata_set_check_space(int x, int y) { int px, py; int is_blank; int i; struct MapCell *cell; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); px = pl_pos.x+x; py = pl_pos.y+y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); is_blank=1; cell = mapdata_cell(px, py); for (i=0; i < MAXLAYERS; i++) { if (cell->heads[i].face>0 || cell->tails[i].face>0) { is_blank=0; break; } } if (cell->darkness != 0) { is_blank=0; } /* We only care if this space needs to be blanked out */ if (!is_blank) { return; } if (x < width && y < height) { /* tile is visible */ /* visible tile is now blank ==> do not clear but mark as cleared */ mapdata_clear(x, y); } } /* This just sets the darkness for a space. * Used by Map2Cmd() */ void mapdata_set_darkness(int x, int y, int darkness) { int px, py; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); px = pl_pos.x+x; py = pl_pos.y+y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); /* Ignore darkness information for tile outside the viewable area: if * such a tile becomes visible again, it is either "fog of war" (and * darkness information is ignored) or it will be updated (including * the darkness information). */ if (darkness != -1 && x < width && y < height) { set_darkness(px, py, 255-darkness); } } /* Sets smooth information for layer */ void mapdata_set_smooth(int x, int y, guint8 smooth, int layer) { static int dx[8]= {0,1,1,1,0,-1,-1,-1}; static int dy[8]= {-1,-1,0,1,1,1,0,-1}; int rx, ry, px, py, i; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); px = pl_pos.x+x; py = pl_pos.y+y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); if (mapdata_cell(px, py)->smooth[layer] != smooth) { for (i=0; i<8; i++) { rx=px+dx[i]; ry=py+dy[i]; if ( (rx<0) || (ry<0) || (the_map.width<=rx) || (the_map.height<=ry)) { continue; } mapdata_cell(rx, ry)->need_resmooth=1; } mapdata_cell(px, py)->need_resmooth=1; mapdata_cell(px, py)->smooth[layer] = smooth; } } /** * Prepare a map cell, which may contain old fog of war data, for new visible * map data. Call this when Map2 is imminently going to provide an update for * the given tile. A better name for this function would be mapdata_prepare(). */ void mapdata_clear_old(int x, int y) { assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); if (!(x < width && y < height)) return; int px = pl_pos.x + x; int py = pl_pos.y + y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); // In theory we only have to do this if this is a fog of war tile, because // the server remembers what tiles are visible to us and sends the // appropriate darkness updates. if (mapdata_cell(px, py)->state == FOG) { mapdata_cell(px, py)->need_update = 1; for (int i = 0; i < MAXLAYERS; i++) { expand_clear_face_from_layer(px, py, i); } mapdata_cell(px, py)->darkness = 0; } mapdata_cell(px, py)->state = VISIBLE; } /* This is vaguely related to the mapdata_set_face() above, but rather * than take all the faces, takes 1 face and the layer this face is * on. This is used by the Map2Cmd() */ void mapdata_set_face_layer(int x, int y, gint16 face, int layer) { int px, py; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); px = pl_pos.x+x; py = pl_pos.y+y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); if (x < width && y < height) { mapdata_cell(px, py)->need_update = 1; if (face >0) { expand_set_face(px, py, layer, face, TRUE); } else { expand_clear_face_from_layer(px, py, layer); } } else { expand_set_bigface(x, y, layer, face, TRUE); } } /* This is vaguely related to the mapdata_set_face() above, but rather * than take all the faces, takes 1 face and the layer this face is * on. This is used by the Map2Cmd() */ void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer) { int px, py; int i, face, animation, phase, speed_left; assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); px = pl_pos.x+x; py = pl_pos.y+y; assert(0 <= px && px < the_map.width); assert(0 <= py && py < the_map.height); animation = anim & ANIM_MASK; face = 0; /* Random animation is pretty easy */ if ((anim & ANIM_FLAGS_MASK) == ANIM_RANDOM) { const guint8 num_animations = animations[animation].num_animations; if (num_animations == 0) { LOG(LOG_WARNING, "mapdata_set_anim_layer", "animating object with zero animations"); return; } phase = g_random_int() % num_animations; face = animations[animation].faces[phase]; speed_left = anim_speed % g_random_int(); } else if ((anim & ANIM_FLAGS_MASK) == ANIM_SYNC) { animations[animation].speed = anim_speed; phase = animations[animation].phase; speed_left = animations[animation].speed_left; face = animations[animation].faces[phase]; } if (x < width && y < height) { mapdata_clear_old(x, y); if (face >0) { expand_set_face(px, py, layer, face, TRUE); mapdata_cell(px, py)->heads[layer].animation = animation; mapdata_cell(px, py)->heads[layer].animation_phase = phase; mapdata_cell(px, py)->heads[layer].animation_speed = anim_speed; mapdata_cell(px, py)->heads[layer].animation_left = speed_left; } else { expand_clear_face_from_layer(px, py, layer); } } else { expand_set_bigface(x, y, layer, face, TRUE); } } void mapdata_scroll(int dx, int dy) { script_pos.x += dx; script_pos.y += dy; int x, y; recenter_virtual_map_view(dx, dy); if (want_config[CONFIG_MAPSCROLL] && display_mapscroll(dx, dy)) { struct BigCell *cell; /* Mark all tiles as "need_update" that are overlapped by a big face * from outside the view area. */ for (cell = bigfaces_head; cell != NULL; cell = cell->next) { for (x = 0; x < cell->head.size_x; x++) { for (y = !x; y < cell->head.size_y; y++) { if (0 <= cell->x-x && cell->x-x < width && 0 <= cell->y-y && cell->y-y < height) { mapdata_cell(pl_pos.x+cell->x-x, pl_pos.y+cell->y-y)->need_update = 1; } } } } } else { /* Emulate map scrolling by redrawing all tiles. */ for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { mapdata_cell(pl_pos.x+x, pl_pos.y+y)->need_update = 1; } } } pl_pos.x += dx; pl_pos.y += dy; /* clear all newly visible tiles */ if (dx > 0) { for (y = 0; y < height; y++) { for (x = width-dx; x < width; x++) { mapdata_clear(x, y); } } } else { for (y = 0; y < height; y++) { for (x = 0; x < -dx; x++) { mapdata_clear(x, y); } } } if (dy > 0) { for (x = 0; x < width; x++) { for (y = height-dy; y < height; y++) { mapdata_clear(x, y); } } } else { for (x = 0; x < width; x++) { for (y = 0; y < -dy; y++) { mapdata_clear(x, y); } } } /* Remove all big faces outside the view area. */ while (bigfaces_head != NULL) { expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0); } run_move_to(); } void mapdata_newmap(void) { script_pos.x = 0; script_pos.y = 0; int x, y; global_offset_x = 0; global_offset_y = 0; want_offset_x = 0; want_offset_y = 0; // Clear past predictions. memset(csocket.dir, -1, sizeof(csocket.dir)); /* Clear the_map.cells[]. */ for (x = 0; x < the_map.width; x++) { clear_cells(x, 0, the_map.height); for (y = 0; y < the_map.height; y++) { mapdata_cell(x, y)->need_update = 1; } } /* Clear bigfaces[]. */ while (bigfaces_head != NULL) { expand_clear_bigface_from_layer(bigfaces_head->x, bigfaces_head->y, bigfaces_head->layer, 0); } // Clear destination. clear_move_to(); } /** * Check if the given map tile is a valid slot in the map array. */ static bool mapdata_has_tile(int x, int y, int layer) { if (0 <= x && x < width && 0 <= y && y < height) { if (0 <= layer && layer < MAXLAYERS) { return true; } } return false; } /** * Return the face number of a single-square pixmap at the given map tile. * @param x X-coordinate of tile on-screen * @param y Y-coordinate of tile on-screen * @param layer * @return Pixmap face number, or zero if the tile does not exist */ gint16 mapdata_face(int x, int y, int layer) { if (!mapdata_has_tile(x, y, layer)) { return 0; } return mapdata_cell(pl_pos.x+x, pl_pos.y+y)->heads[layer].face; } gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy) { struct MapCellLayer *head = &mapdata_cell(mx, my)->heads[layer]; struct MapCellTailLayer *tail = &mapdata_cell(mx, my)->tails[layer]; if (head->face != 0) { const int width = head->size_x, height = head->size_y; *dx = 1 - width, *dy = 1 - height; return head->face; } else if (tail->face != 0) { struct MapCellLayer *head_ptr = &mapdata_cell(mx + tail->size_x, my + tail->size_y)->heads[layer]; const int width = head_ptr->size_x, height = head_ptr->size_y; *dx = tail->size_x - width + 1, *dy = tail->size_y - height + 1; return tail->face; } else { return 0; } } /** * Return the face number of a multi-square pixmap at the given map tile. * @param x X-coordinate of tile on-screen * @param y Y-coordinate of tile on-screen * @param layer * @param ww * @param hh * @return Pixmap face number, or zero if the tile does not exist */ gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh) { gint16 result; if (!mapdata_has_tile(x, y, layer)) { return 0; } result = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face; if (result != 0) { int clear_bigface; int dx = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_x; int dy = mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].size_y; int w = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_x; int h = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->heads[layer].size_y; assert(1 <= w && w <= MAX_FACE_SIZE); assert(1 <= h && h <= MAX_FACE_SIZE); assert(0 <= dx && dx < w); assert(0 <= dy && dy < h); /* Now check if we are about to display an obsolete big face: such a * face has a cleared ("fog of war") head but the current tile is not * fog of war. Since the server would have sent an appropriate head * tile if it was already valid, just clear the big face and do not * return it. */ if (mapdata_cell(pl_pos.x+x, pl_pos.y+y)->state == FOG) { /* Current face is a "fog of war" tile ==> do not clear * old information. */ clear_bigface = 0; } else { if (x+dx < width && y+dy < height) { /* Clear face if current tile is valid but the * head is marked as cleared. */ clear_bigface = mapdata_cell(pl_pos.x+x+dx, pl_pos.y+y+dy)->state == FOG; } else { /* Clear face if current tile is valid but the * head is not set. */ clear_bigface = bigfaces[x+dx][y+dy][layer].head.face == 0; } } if (!clear_bigface) { *ww = w-1-dx; *hh = h-1-dy; return(result); } assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == result); expand_clear_face_from_layer(pl_pos.x+x+dx, pl_pos.y+y+dy, layer); assert(mapdata_cell(pl_pos.x+x, pl_pos.y+y)->tails[layer].face == 0); } result = bigfaces[x][y][layer].tail.face; if (result != 0) { int dx = bigfaces[x][y][layer].tail.size_x; int dy = bigfaces[x][y][layer].tail.size_y; int w = bigfaces[x+dx][y+dy][layer].head.size_x; int h = bigfaces[x+dx][y+dy][layer].head.size_y; assert(0 <= dx && dx < w); assert(0 <= dy && dy < h); *ww = w-1-dx; *hh = h-1-dy; return(result); } *ww = 1; *hh = 1; return(0); } /* This is used by the opengl logic. * Basically the opengl code draws the the entire image, * and doesn't care if if portions are off the edge * (opengl takes care of that). So basically, this * function returns only if the head for a space is set, * otherwise, returns 0 - we don't care about the tails * or other details really. */ gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh) { gint16 result; if (!mapdata_has_tile(x, y, layer)) { return 0; } result = bigfaces[x][y][layer].head.face; if (result != 0) { int w = bigfaces[x][y][layer].head.size_x; int h = bigfaces[x][y][layer].head.size_y; *ww = w; *hh = h; return(result); } *ww = 1; *hh = 1; return(0); } /** * Check if current map position is out of bounds if shifted by (dx, dy). If * so, shift the virtual map so that the map view is within bounds again. * * Assures that [pl_pos.x-MAX_FACE_SIZE..pl_pos.x+MAX_VIEW+1] is within the * bounds of the virtual map area. This covers the area a map1a command may * affect plus a one tile border. */ static void recenter_virtual_map_view(int diff_x, int diff_y) { int new_x, new_y; int shift_x, shift_y; int src_x, src_y; int dst_x, dst_y; int len_x, len_y; int sx; int dx; int i; /* shift player position in virtual map */ new_x = pl_pos.x+diff_x; new_y = pl_pos.y+diff_y; /* determine neccessary amount to shift */ /* if(new_x < 1) is not possible: a big face may reach up to * (MAX_FACE_SIZE-1) tiles to the left of pl_pos. Therefore maintain a * border of at least MAX_FACE_SIZE to the left of the virtual map * edge. */ if (new_x < MAX_FACE_SIZE) { shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x; /* This yields: new_x+shift_x == FOG_BORDER_MIN+MAX_FACE_SIZE, * i.e. left border is FOG_BORDER_MIN+MAX_FACE_SIZE after * shifting. */ } else if (new_x+MAX_VIEW > the_map.width) { shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x; /* This yields: new_x+shift_x == * the_map.width-FOG_BODER_MIN-MAX_VIEW, i.e. right border is * FOGBORDER_MIN after shifting. */ } else { shift_x = 0; } /* Same as above but for y. */ if (new_y < MAX_FACE_SIZE) { shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y; } else if (new_y+MAX_VIEW > the_map.height) { shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y; } else { shift_y = 0; } /* No shift neccessary? ==> nothing to do. */ if (shift_x == 0 && shift_y == 0) { return; } /* If shifting at all: maintain a border size of FOG_BORDER_MIN to all * directions. For example: if pl_pos=30/MAX_FACE_SIZE, and map_scroll is * 0/-1: shift pl_pos to FOG_BORDER_MIN+1/FOG_BORDER_MIN+1, not to * 30/FOG_BORDER_MIN+1. */ if (shift_x == 0) { if (new_x < FOG_BORDER_MIN+MAX_FACE_SIZE) { shift_x = FOG_BORDER_MIN+MAX_FACE_SIZE-new_x; } else if (new_x+MAX_VIEW+FOG_BORDER_MIN > the_map.width) { shift_x = the_map.width-FOG_BORDER_MIN-MAX_VIEW-new_x; } } if (shift_y == 0) { if (new_y < FOG_BORDER_MIN+MAX_FACE_SIZE) { shift_y = FOG_BORDER_MIN+MAX_FACE_SIZE-new_y; } else if (new_y+MAX_VIEW+FOG_BORDER_MIN > the_map.height) { shift_y = the_map.height-FOG_BORDER_MIN-MAX_VIEW-new_y; } } /* Shift for more than virtual map size? ==> clear whole virtual map * and recenter. */ if (shift_x <= -the_map.width || shift_x >= the_map.width || shift_y <= -the_map.height || shift_y >= the_map.height) { for (dx = 0; dx < the_map.width; dx++) { clear_cells(dx, 0, the_map.height); } pl_pos.x = the_map.width/2-width/2; pl_pos.y = the_map.height/2-height/2; return; } /* Move player position. */ pl_pos.x += shift_x; pl_pos.y += shift_y; /* Actually shift the virtual map by shift_x/shift_y */ if (shift_x < 0) { src_x = -shift_x; dst_x = 0; len_x = the_map.width+shift_x; } else { src_x = 0; dst_x = shift_x; len_x = the_map.width-shift_x; } if (shift_y < 0) { src_y = -shift_y; dst_y = 0; len_y = the_map.height+shift_y; } else { src_y = 0; dst_y = shift_y; len_y = the_map.height-shift_y; } if (shift_x < 0) { for (sx = src_x, dx = dst_x, i = 0; i < len_x; sx++, dx++, i++) { /* srcx!=dstx ==> can use memcpy since source and * destination to not overlap. */ memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell)); } } else if (shift_x > 0) { for (sx = src_x+len_x-1, dx = dst_x+len_x-1, i = 0; i < len_x; sx--, dx--, i++) { /* srcx!=dstx ==> can use memcpy since source and * destination to not overlap. */ memcpy(mapdata_cell(dx, dst_y), mapdata_cell(sx, src_y), len_y*sizeof(struct MapCell)); } } else { assert(src_x == dst_x); for (dx = src_x, i = 0; i < len_x; dx++, i++) { /* srcx==dstx ==> use memmove since source and * destination probably do overlap. */ memmove(mapdata_cell(dx, dst_y), mapdata_cell(dx, src_y), len_y*sizeof(struct MapCell)); } } /* Clear newly opened area */ for (dx = 0; dx < dst_x; dx++) { clear_cells(dx, 0, the_map.height); } for (dx = dst_x+len_x; dx < the_map.width; dx++) { clear_cells(dx, 0, the_map.height); } if (shift_y > 0) { for (dx = 0; dx < len_x; dx++) { clear_cells(dx+dst_x, 0, shift_y); } } else if (shift_y < 0) { for (dx = 0; dx < len_x; dx++) { clear_cells(dx+dst_x, the_map.height+shift_y, -shift_y); } } } /** * Return the size of a face in tiles. The returned size is at between 1 and * MAX_FACE_SIZE (inclusive). */ static void mapdata_get_image_size(int face, guint8 *w, guint8 *h) { get_map_image_size(face, w, h); if (*w < 1) { *w = 1; } if (*h < 1) { *h = 1; } if (*w > MAX_FACE_SIZE) { *w = MAX_FACE_SIZE; } if (*h > MAX_FACE_SIZE) { *h = MAX_FACE_SIZE; } } /* This basically goes through all the map spaces and does the necessary * animation. */ void mapdata_animation(void) { int x, y, layer, face; struct MapCellLayer *cell; /* For synchronized animations, what we do is set the initial values * in the mapdata to the fields in the animations[] array. In this way, * the code below the iterates the spaces doesn't need to do anything * special. But we have to update the animations[] array here to * keep in sync. */ for (x=0; x < MAXANIM; x++) { if (animations[x].speed) { animations[x].speed_left++; if (animations[x].speed_left >= animations[x].speed) { animations[x].speed_left=0; animations[x].phase++; if (animations[x].phase >= animations[x].num_animations) { animations[x].phase=0; } } } } for (x=0; x < CURRENT_MAX_VIEW; x++) { for (y=0; y < CURRENT_MAX_VIEW; y++) { struct MapCell *map_space = mapdata_cell(pl_pos.x + x, pl_pos.y + y); /* Short cut some processing here. It makes sense to me * not to animate stuff out of view */ if (map_space->state == VISIBLE) { continue; } for (layer=0; layerheads[layer]; if (cell->animation) { cell->animation_left++; if (cell->animation_left >= cell->animation_speed) { cell->animation_left=0; cell->animation_phase++; if (cell->animation_phase >= animations[cell->animation].num_animations) { cell->animation_phase=0; } face = animations[cell->animation].faces[cell->animation_phase]; /* I don't think we send any to the client, but it is possible * for animations to have blank faces. */ if (face >0) { expand_set_face(pl_pos.x + x, pl_pos.y + y, layer, face, FALSE); } else { expand_clear_face_from_layer(pl_pos.x + x, pl_pos.y + y , layer); } } } cell = &bigfaces[x][y][layer].head; if (cell->animation) { cell->animation_left++; if (cell->animation_left >= cell->animation_speed) { cell->animation_left=0; cell->animation_phase++; if (cell->animation_phase >= animations[cell->animation].num_animations) { cell->animation_phase=0; } face = animations[cell->animation].faces[cell->animation_phase]; /* I don't think we send any to the client, but it is possible * for animations to have blank faces. */ expand_set_bigface(x, y, layer, face, FALSE); } } } } } } /** * Compute player position in map coordinates. Unlike pl_pos.x and pl_pos.y * which store the top left corner of the virtual map, this returns the actual * position of the player. */ void pl_mpos(int *px, int *py) { const int vw = use_config[CONFIG_MAPWIDTH]; const int vh = use_config[CONFIG_MAPHEIGHT]; *px = pl_pos.x + vw/2; *py = pl_pos.y + vh/2; } void set_move_to(int dx, int dy) { int old_move_to_x = move_to_x; int old_move_to_y = move_to_y; pl_mpos(&move_to_x, &move_to_y); move_to_x += dx; move_to_y += dy; if (move_to_x == old_move_to_x && move_to_y == old_move_to_y) { // Detect double-click. move_to_attack = true; } else { move_to_attack = false; } } void clear_move_to() { move_to_x = 0; move_to_y = 0; move_to_attack = false; } bool is_at_moveto() { if (move_to_x == 0 && move_to_y == 0) { return true; } int px, py; pl_mpos(&px, &py); return !(move_to_x != px || move_to_y != py); } void run_move_to() { if (move_to_x == 0 && move_to_y == 0) { // If not moving to a tile, skip to avoid calling stop_run(). return; } if (is_at_moveto()) { clear_move_to(); stop_run(); return; } int px, py; pl_mpos(&px, &py); int dx = move_to_x - px; int dy = move_to_y - py; int dir = relative_direction(dx, dy); if (move_to_attack) { run_dir(dir); } else { walk_dir(dir); } } crossfire-client-1.75.3/common/script.c000644 001751 001751 00000164170 14604606323 020717 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Handles the client-side scripting interface. * * Each script is an external process that keeps two pipes open between the * client and the script (one in each direction). When the script starts, it * defaults to receiving no data from the client. Normally, the first command * it sends to the client will be a request to have certain types of data sent * to the script as the client receives them from the server (such as drawinfo * commands). The script can also request current information from the * client, such as the contents of the inventory or the map data (either live * or last viewed "fog-of-war" data). The script can also send commands for * the client to pass to the server. * * Script Commands: * * watch {command type} * whenever the server sends the given command type to the client, also send * a copy to the script. * Note that this checked before the client processes the command, so it will * automatically handle new options that may be added in the future. * If the command type is NULL, all commands are watched. * * unwatch {command type} * turn off a previous watch command. There may be a slight delay in * response before the command is processed, so some unwanted data may * still be sent to the script. * * request {data type} * have the client send the given data to the script. * * issue [{repeat} {must_send}] {command} * issue the specified command to the server. * if {repeat} isn't numeric then the command is sent directly * For "lock" and "mark" only, the parameters are converted to binary. * * draw {color} {text} * display the text in the specified color as if the server had sent * a drawinfo command. * * monitor * send the script a copy of every command that is sent to the server. * * unmonitor * turn off monitoring. * * sync {#} * wait until the server has acknowledged all but {#} commands have been * received * * To implement this: * * Processing script commands: gtk/gx11.c:do_network() and * x11/x11.c:event_loop() are modified to also watch for input from scripts * in the select() call, in which case script_process(fd) in this file is * called. * * Handling watches: common/client.c:DoClient() is modified to pass a copy * of each command to script_watch() before checking for it in the table. * * Handling of monitor: common/player.c:send_command() is modified to pass * a copy of each command to script_monitor() before sending to the server. * * Handling of requests: global variables are directly accessed from within * this file. * * Handling of issues: send_command() is called directly. Note that this * command will be sent to any scripts that are monitoring output. * * Launching new scripts: common/player.c:extended_command() is extended to * add a check for "script " as an additional command, calling * script_init(). Also added is the "scripts" command to list all running * scripts, the "scriptkill" command to terminate a script (close the pipes * and assume it takes the hint), and the "scripttell" command to send a * message to a running script. */ /* * Include files */ /* * This does not work under Windows for now. Someday this will be fixed :) */ #include "client.h" #include #ifndef WIN32 #include #include #include #include /* for SIGHUP */ #include #endif #include "external.h" #include "mapdata.h" #include "p_cmd.h" #include "script.h" /* * Data structures */ struct script { char *name; /* the script name */ char *params; /* the script parameters, if any */ #ifndef WIN32 int out_fd; /* the file descriptor to which the client writes to the script */ int in_fd; /* the file descriptor from which we read commands from the script */ #else HANDLE out_fd; /* the file descriptor to which the client writes to the script */ HANDLE in_fd; /* the file descriptor from which we read commands from the script */ #endif /* WIN32 */ int monitor; /* true if this script is monitoring commands sent to the server */ int num_watch; /* number of commands we're watching */ char **watch; /* array of commands that we're watching */ int cmd_count; /* bytes already read in */ char cmd[1024]; /* command from the script */ #ifndef WIN32 int pid; #else DWORD pid; /* Handle to Win32 process ID */ HANDLE process; /* Handle of Win32 process */ #endif int sync_watch; }; /* * Global variables */ static struct script *scripts = NULL; static int num_scripts = 0; /* * Prototypes */ static int script_by_name(const char *name); static void script_dead(int i); static void script_process_cmd(int i); static void send_map(int i, int x, int y); static void script_send_item(int i, const char *head, const item *it); /* * Functions */ #ifdef WIN32 #define write(x, y, z) emulate_write(x, y, z) #define read(x, y, z) emulate_read(x, y, z) static int emulate_read(HANDLE fd, char *buf, int len) { DWORD dwBytesRead; BOOL rc; FlushFileBuffers(fd); rc = ReadFile(fd, buf, len, &dwBytesRead, NULL); if (rc == FALSE) { return(-1); } buf[dwBytesRead] = '\0'; return(dwBytesRead); } static int emulate_write(HANDLE fd, const char *buf, int len) { DWORD dwBytesWritten; BOOL rc; rc = WriteFile(fd, buf, len, &dwBytesWritten, NULL); FlushFileBuffers(fd); if (rc == FALSE) { return(-1); } return(dwBytesWritten); } #endif /* WIN32 */ void script_init(const char *cparams) { #ifndef WIN32 int pipe1[2], pipe2[2]; int pid; char *name, *args, params[MAX_BUF]; if (!cparams) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Please specify a script to start. For help, type " "'help script'."); return; } /* cparams is a const value, so copy the data into a buffer */ strncpy(params, cparams, MAX_BUF - 1); params[MAX_BUF - 1] = '\0'; /* Get name and args */ name = params; args = name; while (*args && *args != ' ') { ++args; } while (*args && *args == ' ') { *args++ = '\0'; } if (*args == 0) { args = NULL; } /* Open two pipes, one for stdin and the other for stdout. */ if (pipe(pipe1) != 0) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Unable to start script--pipe failed"); return; } if (pipe(pipe2) != 0) { close(pipe1[0]); close(pipe1[1]); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Unable to start script--pipe failed"); return; } /* Fork */ pid = fork(); if (pid == -1) { close(pipe1[0]); close(pipe1[1]); close(pipe2[0]); close(pipe2[1]); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Unable to start script--fork failed"); return; } /* Child--set stdin/stdout to the pipes, then exec */ if (pid == 0) { size_t i; int r; char *argv[256]; /* Fill in argv[] */ argv[0] = name; i = 1; while (args && *args && i < sizeof(argv)/sizeof(*argv)-1) { argv[i++] = args; while (*args && *args != ' ') { ++args; } while (*args && *args == ' ') { *args++ = '\0'; } } argv[i] = NULL; /* Clean up file descriptor space */ r = dup2(pipe1[0], 0); if (r != 0) { fprintf(stderr, "Script Child: Failed to set pipe1 as stdin\n"); } r = dup2(pipe2[1], 1); if (r != 1) { fprintf(stderr, "Script Child: Failed to set pipe2 as stdout\n"); } for (i = 3; i < 100; ++i) { close(i); } /* Pass extra info to the script */ if ( cpl.name ) setenv("CF_PLAYER_NAME", cpl.name, 1); if ( csocket.servername ) setenv("CF_SERVER_NAME", csocket.servername, 1); /* EXEC */ r = execvp(argv[0], argv); /* If we get here, then there's been an failure of some sort. * In my case, it's often that I don't know what script name to * give to /script, so exec() can't find the script. * * Forward the error back to the client, using the script pipes. */ printf("draw %d Could not start script: %s\n", NDI_RED, strerror(errno)); exit(1); } /* Close the child's pipe ends */ close(pipe1[0]); close(pipe2[1]); if (fcntl(pipe1[1], F_SETFL, O_NDELAY) == -1) { LOG(LOG_WARNING, "common::script_init", "Error on fcntl."); } /* g_realloc script array to add new entry; fill in the data */ scripts = g_realloc(scripts, sizeof(scripts[0])*(num_scripts+1)); if (scripts == NULL) { LOG(LOG_ERROR, "script_init", "Could not allocate memory: %s", strerror(errno)); exit(EXIT_FAILURE); } scripts[num_scripts].name = g_strdup(name); scripts[num_scripts].params = args ? g_strdup(args) : NULL; scripts[num_scripts].out_fd = pipe1[1]; scripts[num_scripts].in_fd = pipe2[0]; scripts[num_scripts].monitor = 0; scripts[num_scripts].num_watch = 0; scripts[num_scripts].watch = NULL; scripts[num_scripts].cmd_count = 0; scripts[num_scripts].pid = pid; scripts[num_scripts].sync_watch = -1; ++num_scripts; #else /* WIN32 */ char *name, *args; char params[ MAX_BUF ]; SECURITY_ATTRIBUTES saAttr; PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartupInfo; HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd; HANDLE hChildStdoutWr, hChildStdoutRdDup, hSaveStdin, hSaveStdout; if (!cparams) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Please specifiy a script to launch!"); return; } strncpy(params, cparams, MAX_BUF-1); params[MAX_BUF-1] = '\0'; /* Get name and args */ name = params; args = name; while (*args && *args != ' ') { ++args; } while (*args && *args == ' ') { *args++ = '\0'; } if (*args == 0) { args = NULL; } saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: stdout CreatePipe() failed"); return; } if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: failed to redirect stdout using SetStdHandle()"); return; } if (!DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: failed to duplicate stdout using DuplicateHandle()"); return; } CloseHandle(hChildStdoutRd); hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: stdin CreatePipe() failed"); return; } if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: failed to redirect stdin using SetStdHandle()"); return; } if (!DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: failed to duplicate stdin using DuplicateHandle()"); return; } CloseHandle(hChildStdinWr); ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&siStartupInfo, sizeof(STARTUPINFO)); siStartupInfo.cb = sizeof(STARTUPINFO); if (args) { args[-1] = ' '; } if (!CreateProcess(NULL, name, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &siStartupInfo, &piProcInfo)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: CreateProcess() failed"); return; } CloseHandle(piProcInfo.hThread); if (args) { args[-1] = '\0'; } if (!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: restoring original stdin failed"); return; } if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Script support: restoring original stdout failed"); return; } /* g_realloc script array to add new entry; fill in the data */ scripts = g_realloc(scripts, sizeof(scripts[0])*(num_scripts+1)); if (scripts == NULL) { LOG(LOG_ERROR, "script_init", "Could not allocate memory: %s", strerror(errno)); exit(EXIT_FAILURE); } scripts[num_scripts].name = g_strdup(name); scripts[num_scripts].params = args ? g_strdup(args) : NULL; scripts[num_scripts].out_fd = hChildStdinWrDup; scripts[num_scripts].in_fd = hChildStdoutRdDup; scripts[num_scripts].monitor = 0; scripts[num_scripts].num_watch = 0; scripts[num_scripts].watch = NULL; scripts[num_scripts].cmd_count = 0; scripts[num_scripts].pid = piProcInfo.dwProcessId; scripts[num_scripts].process = piProcInfo.hProcess; scripts[num_scripts].sync_watch = -1; ++num_scripts; #endif /* WIN32 */ } void script_sync(int commdiff) { int i; if (commdiff < 0) { commdiff +=256; } for (i = 0; i < num_scripts; ++i) { if (commdiff <= scripts[i].sync_watch && scripts[i].sync_watch >= 0) { char buf[1024]; snprintf(buf, sizeof(buf), "sync %d\n", commdiff); write(scripts[i].out_fd, buf, strlen(buf)); scripts[i].sync_watch = -1; } } } void script_list(void) { if (num_scripts == 0) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "No scripts are currently running"); } else { int i; char buf[1024]; snprintf(buf, sizeof(buf), "%d scripts currently running:", num_scripts); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); for (i = 0; i < num_scripts; ++i) { if (scripts[i].params) { snprintf(buf, sizeof(buf), "%d %s %s", i+1, scripts[i].name, scripts[i].params); } else { snprintf(buf, sizeof(buf), "%d %s", i+1, scripts[i].name); } draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); } } } void script_kill(const char *params) { int i; /* Verify that the number is a valid array entry */ i = script_by_name(params); if (i < 0 || i >= num_scripts) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "No such running script"); return; } #ifndef WIN32 kill(scripts[i].pid, SIGHUP); #else GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, scripts[i].pid); #endif /* WIN32 */ draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Killed script."); script_dead(i); } void script_killall_wrapper(const char *params) { script_killall(); } void script_killall(void) { const char message_template[] = "Tried to kill %d scripts."; char message[sizeof(message_template) + 10]; snprintf(message, sizeof(message), message_template, num_scripts); while (num_scripts > 0) { #ifndef WIN32 kill(scripts[num_scripts - 1].pid, SIGHUP); script_dead(num_scripts - 1); #else GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, scripts[0].pid); script_dead(0); #endif /* WIN32 */ } draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, message); } void script_fdset(int *maxfd, fd_set *set) { *maxfd = 0; #ifndef WIN32 int i; for (i = 0; i < num_scripts; ++i) { FD_SET(scripts[i].in_fd, set); if (scripts[i].in_fd >= *maxfd) { *maxfd = scripts[i].in_fd+1; } } #endif /* WIN32 */ } void script_process(fd_set *set) { int i; int r; #ifdef WIN32 DWORD nAvailBytes = 0; char cTmp; BOOL bRC; DWORD dwStatus; BOOL bStatus; #endif /* Determine which script's fd is set */ for (i = 0; i < num_scripts; ++i) { #ifndef WIN32 if (FD_ISSET(scripts[i].in_fd, set)) #else bStatus = GetExitCodeProcess(scripts[i].process, &dwStatus); bRC = PeekNamedPipe(scripts[i].in_fd, &cTmp, 1, NULL, &nAvailBytes, NULL); if (nAvailBytes) #endif /* WIN32 */ { /* Read in script[i].cmd */ r = read(scripts[i].in_fd, scripts[i].cmd+scripts[i].cmd_count, sizeof(scripts[i].cmd)-scripts[i].cmd_count-1); if (r > 0) { scripts[i].cmd_count += r; } #ifndef WIN32 else if (r == 0 || errno == EBADF) #else else if (r == 0 || GetLastError() == ERROR_BROKEN_PIPE) #endif { /* Script has exited; delete it */ script_dead(i); return; } /* If a newline or full buffer has been reached, process it */ scripts[i].cmd[scripts[i].cmd_count] = 0; /* terminate string */ while (scripts[i].cmd_count == sizeof(scripts[i].cmd)-1 #ifndef WIN32 || strchr(scripts[i].cmd, '\n')) #else || strchr(scripts[i].cmd, '\r\n')) #endif /* WIN32 */ { script_process_cmd(i); scripts[i].cmd[scripts[i].cmd_count] = 0; /* terminate string */ } return; /* Only process one script at a time */ } #ifdef WIN32 else if (!bRC || (bStatus && (dwStatus != STILL_ACTIVE))) { /* Error: assume dead */ script_dead(i); } #endif /* WIN32 */ } } void script_watch(const char *cmd, const guint8 *data_initial, const int data_len, const enum CmdFormat format) { int i; int w; int l, len; const guint8 *data; /* For each script... */ for (i = 0; i < num_scripts; ++i) { /* For each watch... */ for (w = 0; w < scripts[i].num_watch; ++w) { len = data_len; /* Does this command match our watch? */ l = strlen(scripts[i].watch[w]); if (!l || strncmp(cmd, scripts[i].watch[w], l) == 0) { char buf[MAXSOCKBUF*3]; // Source is binary, dest is ASCII; 2-byte short can be 5 chars plus space data = data_initial; if (!len) { snprintf(buf, sizeof(buf), "watch %s\n", cmd); } else switch (format) { case ASCII: snprintf(buf, sizeof(buf), "watch %s %s\n", cmd, data); break; case SHORT_INT: snprintf(buf, sizeof(buf), "watch %s %d %d\n", cmd, GetShort_String(data), GetInt_String(data+2)); break; case SHORT_ARRAY: { int be; int p; be = snprintf(buf, sizeof(buf), "watch %s", cmd); for (p = 0; p*2 < len; ++p) { be += snprintf(buf+be, sizeof(buf)-be, " %d", GetShort_String(data+p*2)); } be += snprintf(buf+be, sizeof(buf)-be, "\n"); } break; case INT_ARRAY: { int be; int p; be = snprintf(buf, sizeof(buf), "watch %s", cmd); for (p = 0; p*4 < len; ++p) { be += snprintf(buf+be, sizeof(buf)-be, " %d", GetInt_String(data+p*4)); } be += snprintf(buf+be, sizeof(buf)-be, "\n"); } break; case STATS: { /* * We cheat here and log each stat as a separate command, even * if the server sent a bunch of updates as a single message; * most scripts will be easier to write if they only parse a fixed * format. */ int be = 0; while (len) { int c; /* which stat */ be += snprintf(buf+be, sizeof(buf)-be, "watch %s", cmd); c = *data; ++data; --len; if (c >= CS_STAT_RESIST_START && c <= CS_STAT_RESIST_END) { be += snprintf(buf+be, sizeof(buf)-be, " resists %d %d\n", c, GetShort_String(data)); data += 2; len -= 2; } else if (c >= CS_STAT_SKILLINFO && c < (CS_STAT_SKILLINFO+CS_NUM_SKILLS)) { be += snprintf(buf+be, sizeof(buf)-be, " skill %d %d %" G_GINT64_FORMAT "\n", c, *data, GetInt64_String(data+1)); data += 9; len -= 9; } else switch (c) { case CS_STAT_HP: be += snprintf(buf+be, sizeof(buf)-be, " hp %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_MAXHP: be += snprintf(buf+be, sizeof(buf)-be, " maxhp %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_SP: be += snprintf(buf+be, sizeof(buf)-be, " sp %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_MAXSP: be += snprintf(buf+be, sizeof(buf)-be, " maxsp %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_GRACE: be += snprintf(buf+be, sizeof(buf)-be, " grace %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_MAXGRACE: be += snprintf(buf+be, sizeof(buf)-be, " maxgrace %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_STR: be += snprintf(buf+be, sizeof(buf)-be, " str %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_INT: be += snprintf(buf+be, sizeof(buf)-be, " int %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_POW: be += snprintf(buf+be, sizeof(buf)-be, " pow %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_WIS: be += snprintf(buf+be, sizeof(buf)-be, " wis %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_DEX: be += snprintf(buf+be, sizeof(buf)-be, " dex %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_CON: be += snprintf(buf+be, sizeof(buf)-be, " con %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_CHA: be += snprintf(buf+be, sizeof(buf)-be, " cha %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_EXP: be += snprintf(buf+be, sizeof(buf)-be, " exp %d\n", GetInt_String(data)); data += 4; len -= 4; break; case CS_STAT_EXP64: be += snprintf(buf+be, sizeof(buf)-be, " exp %" G_GINT64_FORMAT "\n", GetInt64_String(data)); data += 8; len -= 8; break; case CS_STAT_LEVEL: be += snprintf(buf+be, sizeof(buf)-be, " level %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_WC: be += snprintf(buf+be, sizeof(buf)-be, " wc %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_AC: be += snprintf(buf+be, sizeof(buf)-be, " ac %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_DAM: be += snprintf(buf+be, sizeof(buf)-be, " dam %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_ARMOUR: be += snprintf(buf+be, sizeof(buf)-be, " armour %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_SPEED: be += snprintf(buf+be, sizeof(buf)-be, " speed %d\n", GetInt_String(data)); data += 4; len -= 4; break; case CS_STAT_FOOD: be += snprintf(buf+be, sizeof(buf)-be, " food %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_WEAP_SP: be += snprintf(buf+be, sizeof(buf)-be, " weap_sp %d\n", GetInt_String(data)); data += 4; len -= 4; break; case CS_STAT_FLAGS: be += snprintf(buf+be, sizeof(buf)-be, " flags %d\n", GetShort_String(data)); data += 2; len -= 2; break; case CS_STAT_WEIGHT_LIM: be += snprintf(buf+be, sizeof(buf)-be, " weight_lim %d\n", GetInt_String(data)); data += 4; len -= 4; break; case CS_STAT_RANGE: { int rlen = *data; ++data; --len; be += snprintf(buf+be, sizeof(buf)-be, " range %*.*s\n", rlen, rlen, data); data += rlen; len -= rlen; break; } case CS_STAT_TITLE: { int rlen = *data; ++data; --len; be += snprintf(buf+be, sizeof(buf)-be, " title %*.*s\n", rlen, rlen, data); data += rlen; len -= rlen; break; } default: be += snprintf(buf+be, sizeof(buf)-be, " unknown %d %d bytes left\n", c, len); len = 0; } } } break; case MIXED: /* magicmap */ /* mapextended */ /* item1 item2 */ /* upditem */ /* image image2 */ /* face face1 face2 */ /* sound */ /* player */ /* * If we find that scripts need data from any of the above, we can * write special-case code as with stats. In the meantime, fall * through and just give a hex dump. Script writers should not * depend on that data format. */ case NODATA: default: { int be; int p; /*we may receive an null data, in which case len has no meaning*/ if (!data) { len = 0; } be = snprintf(buf, sizeof(buf), "watch %s %d bytes unparsed:", cmd, len); for (p = 0; p < len; ++p) { be += snprintf(buf+be, sizeof(buf)-be, " %02x", data[p]); } be += snprintf(buf+be, sizeof(buf)-be, "\n"); } break; } write(scripts[i].out_fd, buf, strlen(buf)); } } } } void script_monitor(const char *command, int repeat, int must_send) { int i; /* For each script... */ for (i = 0; i < num_scripts; ++i) { /* Do we send the command? */ if (scripts[i].monitor) { char buf[1024]; snprintf(buf, sizeof(buf), "monitor %d %d %s\n", repeat, must_send, command); write(scripts[i].out_fd, buf, strlen(buf)); } } } void script_monitor_str(const char *command) { int i; /* For each script... */ for (i = 0; i < num_scripts; ++i) { /* Do we send the command? */ if (scripts[i].monitor) { char buf[1024]; snprintf(buf, sizeof(buf), "monitor %s\n", command); write(scripts[i].out_fd, buf, strlen(buf)); } } } void script_tell(const char *params) { int i; char *p; if (params == NULL) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Which script do you want to talk to?"); return; } /* Local copy for modifications */ char params_cpy[MAX_BUF]; snprintf(params_cpy, MAX_BUF-1, "%s", params); p = strchr(params_cpy, ' '); if (p == NULL) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "What do you want to tell the script?"); return; } while (*p == ' ') { *p++ = '\0'; } /* Find the script */ i = script_by_name(params_cpy); if (i < 0) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "No such running script"); return; } /* Send the message */ write(scripts[i].out_fd, "scripttell ", 11); write(scripts[i].out_fd, p, strlen(p)); write(scripts[i].out_fd, "\n", 1); } static int script_by_name(const char *name) { int i; int l; if (name == NULL) { return(num_scripts == 1 ? 0 : -1); } /* Parse script number */ if (isdigit(*name)) { i = atoi(name); --i; if (i >= 0 && i < num_scripts) { return(i); } } /* Parse script name */ l = 0; while (name[l] && name[l] != ' ') { ++l; } for (i = 0; i < num_scripts; ++i) { if (strncmp(name, scripts[i].name, l) == 0) { return(i); } } return(-1); } static void script_dead(int i) { int w; /* Release resources */ #ifndef WIN32 close(scripts[i].in_fd); close(scripts[i].out_fd); #else CloseHandle(scripts[i].in_fd); CloseHandle(scripts[i].out_fd); CloseHandle(scripts[i].process); #endif free(scripts[i].name); free(scripts[i].params); for (w = 0; w < scripts[i].num_watch; ++w) { free(scripts[i].watch[w]); } free(scripts[i].watch); #ifndef WIN32 waitpid(-1, NULL, WNOHANG); #endif /* Move scripts with higher index numbers down one slot */ if (i < (num_scripts-1)) { memmove(&scripts[i], &scripts[i+1], sizeof(scripts[i])*(num_scripts-i-1)); } /* Update our count */ --num_scripts; } static void send_map(int i, int x, int y) { char buf[1024]; if (!mapdata_contains(x, y)) { snprintf(buf, sizeof(buf), "request map %d %d unknown\n", x, y); } else { /*** FIXME *** send more relevant data ***/ snprintf(buf, sizeof(buf), "request map %d %d %d %c %c %c %c" " smooth %d %d %d heads %d %d %d tails %d %d %d\n", x, y, mapdata_cell(x, y)->darkness, mapdata_cell(x, y)->need_update ? 'y' : 'n', mapdata_cell(x, y)->darkness != 0 ? 'y' : 'n', mapdata_cell(x, y)->need_resmooth ? 'y' : 'n', mapdata_cell(x, y)->state != VISIBLE ? 'y' : 'n', mapdata_cell(x, y)->smooth[0], mapdata_cell(x, y)->smooth[1], mapdata_cell(x, y)->smooth[2], mapdata_cell(x, y)->heads[0].face, mapdata_cell(x, y)->heads[1].face, mapdata_cell(x, y)->heads[2].face, mapdata_cell(x, y)->tails[0].face, mapdata_cell(x, y)->tails[1].face, mapdata_cell(x, y)->tails[2].face ); } write(scripts[i].out_fd, buf, strlen(buf)); } /** * Process a single script command from the given script. This function * removes the processed command from the buffer when finished. * @param i Index of the script to process a command from */ static void script_process_cmd(int i) { char cmd[1024]; char *c; // Find the length of the command up to the trailing newline. int l = strcspn(scripts[i].cmd, "\n") + 1; // Copy a single command up until the newline into a buffer. g_strlcpy(cmd, scripts[i].cmd, l); // If a carriage return is present, trim it out as well. char *cr = strchr(cmd, '\r'); if (cr != NULL) { *cr = '\0'; } // Remove a single command from the script command buffer. if (l < scripts[i].cmd_count) { memmove(scripts[i].cmd, scripts[i].cmd + l, scripts[i].cmd_count - l); scripts[i].cmd_count -= l; } else { scripts[i].cmd_count = 0; } /* * Now the data in scripts[i] is ready for the next read. * We have a complete command in cmd[]. * Process it. */ /* * Script commands * * watch * unwatch * request * issue * localcmd [] * draw * monitor * unmonitor */ if (strncmp(cmd, "sync", 4) == 0) { c = cmd+4; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } scripts[i].sync_watch = -1; if (isdigit(*c)) { scripts[i].sync_watch = atoi(c); } script_sync(csocket.command_sent - csocket.command_received); /* in case we are already there */ } else if (strncmp(cmd, "watch", 5) == 0) { c = cmd+5; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } c = g_strdup(c); scripts[i].watch = g_realloc(scripts[i].watch, (scripts[i].num_watch+1)*sizeof(scripts[i].watch[1])); scripts[i].watch[scripts[i].num_watch] = c; ++scripts[i].num_watch; } else if (strncmp(cmd, "unwatch", 7) == 0) { int w; c = cmd+7; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } for (w = 0; w < scripts[i].num_watch; ++w) { if (strcmp(c, scripts[i].watch[w]) == 0) { free(scripts[i].watch[w]); while (w+1 < scripts[i].num_watch) { scripts[i].watch[w] = scripts[i].watch[w+1]; ++w; } --scripts[i].num_watch; break; } } } else if (strncmp(cmd, "request", 7) == 0) { c = cmd+7; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } if (!*c) { return; /* bad request */ } /* * Request information from the client's view of the world * (mostly defined in client.h) * * Valid requests: * * player Return the player's tag and title * range Return the type and name of the currently selected range attack * stat Return the specified stats * stat stats Return Str,Con,Dex,Int,Wis,Pow,Cha * stat cmbt Return wc,ac,dam,speed,weapon_sp * stat hp Return hp,maxhp,sp,maxsp,grace,maxgrace,food * stat xp Return level,xp,skill-1 level,skill-1 xp,... * stat resists Return resistances * stat paths Return spell paths: attuned, repelled, denied. * weight Return maxweight, weight * flags Return flags (fire, run) * items inv Return a list of items in the inventory, one per line * items actv Return a list of inventory items that are active, one per line * items on Return a list of items under the player, one per line * items cont Return a list of items in the open container, one per line * map pos Return the players x,y within the current map * map near Return the 3x3 grid of the map centered on the player * map all Return all the known map information * map Return the information about square x,y in the current map * skills Return a list of all skill names, one per line (see also stat xp) * spells Return a list of known spells, one per line */ if (strncmp(c, "player", 6) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request player %d %s\n", cpl.ob->tag, cpl.title); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "range", 5) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request range %s\n", cpl.range); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "weight", 5) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request weight %d %d\n", cpl.stats.weight_limit, (int)(cpl.ob->weight*1000)); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "stat ", 5) == 0) { c += 4; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } if (!*c) { return; /* bad request */ } /* * stat stats Return Str,Con,Dex,Int,Wis,Pow,Cha * stat cmbt Return wc,ac,dam,speed,weapon_sp * stat hp Return hp,maxhp,sp,maxsp,grace,maxgrace,food * stat xp Return level,xp,skill-1 level,skill-1 xp,... * stat resists Return resistances */ if (strncmp(c, "stats", 5) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request stat stats %d %d %d %d %d %d %d\n", cpl.stats.Str, cpl.stats.Con, cpl.stats.Dex, cpl.stats.Int, cpl.stats.Wis, cpl.stats.Pow, cpl.stats.Cha); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "cmbt", 4) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request stat cmbt %d %d %d %d %d\n", cpl.stats.wc, cpl.stats.ac, cpl.stats.dam, cpl.stats.speed, cpl.stats.weapon_sp); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "hp", 2) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request stat hp %d %d %d %d %d %d %d\n", cpl.stats.hp, cpl.stats.maxhp, cpl.stats.sp, cpl.stats.maxsp, cpl.stats.grace, cpl.stats.maxgrace, cpl.stats.food); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "xp", 2) == 0) { char buf[1024]; int s; snprintf(buf, sizeof(buf), "request stat xp %d %" G_GINT64_FORMAT, cpl.stats.level, cpl.stats.exp); write(scripts[i].out_fd, buf, strlen(buf)); for (s = 0; s < MAX_SKILL; ++s) { snprintf(buf, sizeof(buf), " %d %" G_GINT64_FORMAT, cpl.stats.skill_level[s], cpl.stats.skill_exp[s]); write(scripts[i].out_fd, buf, strlen(buf)); } write(scripts[i].out_fd, "\n", 1); } else if (strncmp(c, "resists", 7) == 0) { char buf[1024]; int s; snprintf(buf, sizeof(buf), "request stat resists"); write(scripts[i].out_fd, buf, strlen(buf)); for (s = 0; s < 30; ++s) { snprintf(buf, sizeof(buf), " %d", cpl.stats.resists[s]); write(scripts[i].out_fd, buf, strlen(buf)); } write(scripts[i].out_fd, "\n", 1); } else if (strncmp(c, "paths", 2) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request stat paths %d %d %d\n", cpl.stats.attuned, cpl.stats.repelled, cpl.stats.denied); write(scripts[i].out_fd, buf, strlen(buf)); } } else if (strncmp(c, "flags", 5) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request flags %d %d %d %d\n", cpl.stats.flags, cpl.fire_on, cpl.run_on, cpl.no_echo); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "items ", 6) == 0) { c += 5; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } if (!*c) { return; /* bad request */ } /* * items inv Return a list of items in the inventory, one per line * items actv Return a list of inventory items that are active, one per line * items on Return a list of items under the player, one per line * items cont Return a list of items in the open container, one per line */ if (strncmp(c, "inv", 3) == 0) { char *buf; item *it; for (it = cpl.ob->inv; it; it = it->next) { script_send_item(i, "request items inv ", it); } buf = "request items inv end\n"; write(scripts[i].out_fd, buf, strlen(buf)); } if (strncmp(c, "actv", 4) == 0) { char *buf; item *it; for (it = cpl.ob->inv; it; it = it->next) { if (it->applied) { script_send_item(i, "request items actv ", it); } } buf = "request items actv end\n"; write(scripts[i].out_fd, buf, strlen(buf)); } if (strncmp(c, "on", 2) == 0) { char *buf; item *it; for (it = cpl.below->inv; it; it = it->next) { script_send_item(i, "request items on ", it); } buf = "request items on end\n"; write(scripts[i].out_fd, buf, strlen(buf)); } if (strncmp(c, "cont", 4) == 0) { char *buf; item *it; if (cpl.container) { for (it = cpl.container->inv; it; it = it->next) { script_send_item(i, "request items cont ", it); } } buf = "request items cont end\n"; write(scripts[i].out_fd, buf, strlen(buf)); } } else if (strncmp(c, "map ", 4) == 0) { int x, y; c += 3; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } if (!*c) { return; /* bad request */ } /* * map pos Return the players x,y within the current map * map near Return the 3x3 grid of the map centered on the player * map all Return all the known map information * map Return the information about square x,y in the current map */ if (strncmp(c, "pos", 3) == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "request map pos %d %d\n", script_pos.x, script_pos.y); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "near", 4) == 0) { for (y = 0; y < 3; ++y) for (x = 0; x < 3; ++x) send_map(i, x+pl_pos.x+use_config[CONFIG_MAPWIDTH]/2-1, y+pl_pos.y+use_config[CONFIG_MAPHEIGHT]/2-1 ); } else if (strncmp(c, "all", 3) == 0) { char *endmsg = "request map end\n"; int sizex, sizey; mapdata_size(&sizex, &sizey); for (y = 0; y < sizey; y++) { for (x = 0; x < sizex; x++) { send_map(i, x, y); } } write(scripts[i].out_fd, endmsg, strlen(endmsg)); } else { while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No x specified */ } x = atoi(c); while (*c && *c != ' ') { ++c; } while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No y specified */ } y = atoi(c); send_map(i, x, y); } } else if (strncmp(c, "skills", 6) == 0) { char buf[1024]; int s; for (s = 0; s < CS_NUM_SKILLS; s++) { if (skill_names[s]) { snprintf(buf, sizeof(buf), "request skills %d %s\n", CS_STAT_SKILLINFO + s, skill_names[s]); write(scripts[i].out_fd, buf, strlen(buf)); } } snprintf(buf, sizeof(buf), "request skills end\n"); write(scripts[i].out_fd, buf, strlen(buf)); } else if (strncmp(c, "spells", 6) == 0) { char buf[1024]; Spell *spell; for (spell = cpl.spelldata; spell; spell = spell->next) { snprintf(buf, sizeof(buf), "request spells %d %d %d %d %d %d %d %d %s\n", spell->tag, spell->level, spell->sp, spell->grace, spell->skill_number, spell->path, spell->time, spell->dam, spell->name); write(scripts[i].out_fd, buf, strlen(buf)); } snprintf(buf, sizeof(buf), "request spells end\n"); write(scripts[i].out_fd, buf, strlen(buf)); } else { char buf[1024]; snprintf(buf, sizeof(buf), "Script %d %s malfunction; unimplemented request:", i+1, scripts[i].name); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, cmd); } } else if (strncmp(cmd, "issue", 5) == 0) { int repeat; int must_send; c = cmd+5; while (*c && *c == ' ') { ++c; } if (*c && (isdigit(*c) || *c == '-')) { /* repeat specified; use send_command() */ repeat = atoi(c); while (*c && *c != ' ') { ++c; } while (*c && !isdigit(*c) && *c != '-') { ++c; } if (!*c) { return; /* No must_send specified */ } must_send = atoi(c); while (*c && *c != ' ') { ++c; } if (!*c) { return; /* No command specified */ } while (*c == ' ') { ++c; } if (repeat != -1) { int r; r = send_command(c, repeat, must_send); if (r != 1) { char buf[1024]; snprintf(buf, sizeof(buf), "Script %d %s malfunction; command not sent", i+1, scripts[i].name); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, cmd); } } } else { c = cmd+5; while (*c && *c != ' ') { ++c; } while (*c == ' ') { ++c; } /* * Check special cases with tags: * mark * lock * take [] * drop [] * apply */ if (strncmp(c, "mark", 4) == 0) { int tag; SockList sl; guint8 buf[MAX_BUF]; c += 4; while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No tag specified */ } tag = atoi(c); SockList_Init(&sl, buf); SockList_AddString(&sl, "mark "); SockList_AddInt(&sl, tag); SockList_Send(&sl, csocket.fd); } else if (strncmp(c, "lock", 4) == 0) { int tag, locked; SockList sl; guint8 buf[MAX_BUF]; c += 4; while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No state specified */ } locked = atoi(c); while (*c && *c != ' ') { ++c; } while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No tag specified */ } tag = atoi(c); SockList_Init(&sl, buf); SockList_AddString(&sl, "lock "); SockList_AddChar(&sl, locked); SockList_AddInt(&sl, tag); SockList_Send(&sl, csocket.fd); } else if ( (strncmp(c, "take", 4) == 0) || (strncmp(c, "drop", 4) == 0) ) { int tag, count, dest; dest = (strncmp(c, "drop", 4) == 0) ? 0 : cpl.ob->tag; /* dest is player tag for take, 0 for drop */ c += 4; while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No tag */ } tag = atoi(c); while (*c && *c != ' ') { ++c; } while (*c && !isdigit(*c)) { ++c; } if (!*c) { count=0; /* default: count of zero */ } count = atoi(c); client_send_move(dest,tag,count); } else if (strncmp(c, "apply", 5) == 0) { int tag; c += 5; while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No tag specified */ } tag = atoi(c); client_send_apply(tag); } else { cs_print_string(csocket.fd, "%s", c); } } } else if (strncmp(cmd, "localcmd", 8) == 0) { char *param; c = cmd+8; while (*c == ' ') { c++; } param = c; while ((*param != '\0') && (*param != ' ')) { param++; } if (*param == ' ') { *param = '\0'; param++; } else { param = NULL; } if (!handle_local_command(c, param)) { char buf[1024]; snprintf(buf, sizeof(buf), "Script %s malfunction; localcmd not understood", scripts[i].name); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); snprintf(buf, sizeof(buf), "Script <>", c, (param == NULL) ? "" : param); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); } } else if (strncmp(cmd, "draw", 4) == 0) { int color; c = cmd+4; while (*c && !isdigit(*c)) { ++c; } if (!*c) { return; /* No color specified */ } color = atoi(c); while (*c && *c != ' ') { ++c; } if (!*c) { return; /* No message specified */ } while (*c == ' ') { ++c; } draw_ext_info(color, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, c); } else if (strncmp(cmd, "monitor", 7) == 0) { scripts[i].monitor = 1; } else if (strncmp(cmd, "unmonitor", 9) == 0) { scripts[i].monitor = 0; } else { char buf[1024]; snprintf(buf, sizeof(buf), "Script %d %s malfunction; invalid command:", i+1, scripts[i].name); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, cmd); } } /* * script_send_item() * * Send one line to the script with item information. * * A header string is passed in. The format is: * *
tag num weight flags type name * * flags are a bitmask: * read, unidentified, magic, cursed, damned, unpaid, locked, applied, open, was_open, inv_updated * 1024 512 256 128 64 32 16 8 4 2 1 */ // TODO: Add blessed here static void script_send_item(int i, const char *head, const item *it) { char buf[4096]; int flags; flags = it->read; flags = (flags<<1)|(it->flagsval&F_UNIDENTIFIED?1:0); flags = (flags<<1)|it->magical; flags = (flags<<1)|it->cursed; flags = (flags<<1)|it->damned; flags = (flags<<1)|it->unpaid; flags = (flags<<1)|it->locked; flags = (flags<<1)|it->applied; flags = (flags<<1)|it->open; flags = (flags<<1)|it->was_open; flags = (flags<<1)|it->inv_updated; snprintf(buf, sizeof(buf), "%s%d %d %d %d %d %s\n", head, it->tag, it->nrof, (int)(it->weight*1000+0.5), flags, it->type, it->d_name); write(scripts[i].out_fd, buf, strlen(buf)); } crossfire-client-1.75.3/common/p_cmd.c000644 001751 001751 00000047445 14444135126 020502 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Contains a lot about the commands typed into the client. */ #include #include "client.h" #include "external.h" #include "p_cmd.h" #include "script.h" /** * @defgroup PCmdHelpCommands Common client player commands. * @{ */ #define H1(a) draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, a) #define H2(a) draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, a) #define LINE(a) draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, a) extern void config_check(void); extern void map_check_resize(void); /** If true, the next drawextinfo is expected to contain a map path. */ bool arm_mapedit = false; /* TODO Help topics other than commands? Refer to other documents? */ static int get_num_commands(void); static void do_clienthelp_list() { ConsoleCommand **sorted_cmds = get_cat_sorted_commands(); CommCat category = COMM_CAT_MISC; GString *line = g_string_new(NULL); H1("Client commands:"); for (int i = 0; i < get_num_commands(); i++) { ConsoleCommand *cmd = sorted_cmds[i]; if (cmd->cat != category) { // If moving on to next category, dump line_buf and print header. char buf[MAX_BUF]; snprintf(buf, sizeof(buf), "%s commands:", get_category_name(cmd->cat)); LINE(line->str); H2(buf); category = cmd->cat; g_string_free(line, true); line = g_string_new(NULL); } g_string_append_printf(line, "%s ", cmd->name); } LINE(line->str); g_string_free(line, true); } static void show_help(const ConsoleCommand *cc) { char buf[MAX_BUF]; if (cc->desc != NULL) { snprintf(buf, MAX_BUF - 1, "%s - %s", cc->name, cc->desc); } else { snprintf(buf, MAX_BUF - 1, "Help for '%s':", cc->name); } H2(buf); if (cc->helpfunc != NULL) { const char *long_help = NULL; long_help = cc->helpfunc(); if (long_help != NULL) { LINE(long_help); } else { LINE("Extended help for this command is broken."); } } else { LINE("No extended help is available for this command."); } } static void command_help(const char *cpnext) { if (cpnext) { const ConsoleCommand * cc; char buf[MAX_BUF]; cc = find_command(cpnext); if (cc != NULL) { show_help(cc); } else { snprintf(buf, sizeof(buf), "help %s", cpnext); /* maybe not a must send, but we probably don't want to drop it */ send_command(buf, -1, 1); } } else { do_clienthelp_list(); /* Now fetch (in theory) command list from the server. TODO Protocol command - feed it to the tab completer. Nope! It effectivey fetches '/help commands for commands'. */ send_command("help", -1, 1); /* TODO make install in server branch doesn't install def_help. */ } } static const char * help_help(void) { return "Syntax:\n" "\n" " help\n" " help \n" "\n" "Without any arguments, displays a list of client-side " "commands, and fetches the without-arguments help from " "the server.\n" "\n" "With arguments, first checks if there's a client command " "named . If there is, display it's help. If there " "isn't, send the topic to the server."; } /** * @} */ /* EndOf PCmdHelpCommands */ static void set_command_window(const char *cpnext) { if (!cpnext) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "cwindow command requires a number parameter"); } else { want_config[CONFIG_CWINDOW] = atoi(cpnext); if (want_config[CONFIG_CWINDOW]<1 || want_config[CONFIG_CWINDOW]>127) { want_config[CONFIG_CWINDOW]=COMMAND_WINDOW; } else { use_config[CONFIG_CWINDOW] = want_config[CONFIG_CWINDOW]; } } } static void command_foodbeep() { if (want_config[CONFIG_FOODBEEP]) { want_config[CONFIG_FOODBEEP] = 0; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Warning bell when low on food disabled"); } else { want_config[CONFIG_FOODBEEP] = 1; draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "Warning bell when low on food enabled"); } use_config[CONFIG_FOODBEEP] = want_config[CONFIG_FOODBEEP]; } const char * get_category_name(CommCat cat) { const char * cat_name; /* HACK Need to keep this in sync. with player.h */ switch(cat) { case COMM_CAT_MISC: cat_name = "Miscellaneous"; break; case COMM_CAT_INFO: cat_name = "Informational"; break; case COMM_CAT_SETUP: cat_name = "Configuration"; break; case COMM_CAT_SCRIPT: cat_name = "Scripting"; break; case COMM_CAT_DEBUG: cat_name = "Debugging"; break; default: cat_name = "PROGRAMMER ERROR"; break; } return cat_name; } /* * Command table. * * Implementation basically stolen verbatim from the server. */ static void do_script_list() { script_list(); } static void do_clearinfo() { menu_clear(); } static void do_disconnect() { client_disconnect(); } static void do_inv() { print_inventory(cpl.ob); } static void do_magicmap() { draw_magic_map(); } static void do_savedefaults() { save_defaults(); } static void do_savewinpos() { save_winpos(); } static void do_mapedit() { send_command("mapinfo", -1, 1); arm_mapedit = true; } static void do_set_mapscale(const char *used) { if (used != NULL) { long long scale = strtoll(used, NULL, 0); want_config[CONFIG_MAPSCALE] = scale; config_check(); } else { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, "mapscale command requires an argument"); } } static void do_take(const char *used) { command_take("take", used); /* I dunno why they want it. */ } /* Help "typecasters". */ #include "chelp.h" static const char * help_bind(void) { return HELP_BIND_LONG; } static const char * help_unbind(void) { return HELP_UNBIND_LONG; } static const char * help_magicmap(void) { return HELP_MAGICMAP_LONG; } static const char * help_inv(void) { return HELP_INV_LONG; } static const char * help_cwindow(void) { return "Syntax:\n" "\n" " cwindow \n" "\n" "set size of command" "window (if val is exceeded" "client won't send new" "commands to server\n\n" "(What does this mean, 'put a lid on it'?) TODO"; } static const char * help_script(void) { return "Syntax: script \n\n" "Start an executable client script located at . For details on " "client-side scripting, please see the Crossfire Wiki."; } static const char * help_scripttell(void) { return "Syntax:\n" "\n" " scripttell \n" "\n" "?"; } /* Toolkit-dependent. */ static const char * help_savewinpos(void) { return "Syntax:\n" "\n" " savewinpos\n" "\n" "save window positions - split windows mode only."; } static const char * help_scriptkill(void) { return "Syntax:\n" "\n" " scriptkill \n" "\n" "Stop scripts named .\n" "(Not guaranteed to work?)"; } static const char * help_scriptkillall(void) { return "Syntax:\n" "\n" " scriptkillall\n" "\n" "Stop all active scripts.\n" "(Not guaranteed to work?)"; } static void cmd_raw(const char *cmd) { cs_print_string(csocket.fd, "%s", cmd); } static ConsoleCommand CommonCommands[] = { {"cmd", COMM_CAT_DEBUG, cmd_raw, NULL, "Send a raw command to the server"}, {"bind", COMM_CAT_SETUP, bind_key, help_bind, HELP_BIND_SHORT}, {"script", COMM_CAT_SCRIPT, script_init, help_script, NULL}, #ifdef HAVE_LUA {"lua_load", COMM_CAT_SCRIPT, script_lua_load, NULL, NULL}, {"lua_list", COMM_CAT_SCRIPT, script_lua_list, NULL, NULL}, {"lua_kill", COMM_CAT_SCRIPT, script_lua_kill, NULL, NULL}, #endif {"scripts", COMM_CAT_SCRIPT, do_script_list, NULL, "List running scripts"}, {"scriptkill", COMM_CAT_SCRIPT, script_kill, help_scriptkill, NULL}, {"scriptkillall", COMM_CAT_SCRIPT, script_killall_wrapper, help_scriptkillall, NULL}, {"scripttell", COMM_CAT_SCRIPT, script_tell, help_scripttell, NULL}, {"clearinfo", COMM_CAT_MISC, do_clearinfo, NULL, "Clear message window"}, {"cwindow", COMM_CAT_SETUP, set_command_window, help_cwindow, NULL}, {"disconnect", COMM_CAT_MISC, do_disconnect, NULL, NULL}, {"foodbeep", COMM_CAT_SETUP, command_foodbeep, NULL, "toggle audible low on food warning"}, {"help", COMM_CAT_MISC, command_help, help_help, NULL}, {"inv", COMM_CAT_DEBUG, do_inv, help_inv, HELP_INV_SHORT}, {"magicmap", COMM_CAT_MISC, do_magicmap, help_magicmap, HELP_MAGICMAP_SHORT}, {"mapedit", COMM_CAT_MISC, do_mapedit, NULL, NULL}, {"mapscale", COMM_CAT_MISC, do_set_mapscale, NULL, NULL}, {"savedefaults", COMM_CAT_SETUP, do_savedefaults, NULL, HELP_SAVEDEFAULTS_SHORT}, { "savewinpos", COMM_CAT_SETUP, do_savewinpos, help_savewinpos, "Saves the position and sizes of windows." /* Panes? */ }, {"take", COMM_CAT_MISC, do_take, NULL, NULL}, {"unbind", COMM_CAT_SETUP, unbind_key, help_unbind, NULL}, {"show", COMM_CAT_SETUP, command_show, NULL, "Change what items to show in inventory"}, }; const size_t num_commands = sizeof(CommonCommands) / sizeof(ConsoleCommand); static int get_num_commands() { return num_commands; } static ConsoleCommand ** name_sorted_commands; static int sort_by_name(const void * a_, const void * b_) { ConsoleCommand * a = *((ConsoleCommand **)a_); ConsoleCommand * b = *((ConsoleCommand **)b_); return strcmp(a->name, b->name); } static ConsoleCommand ** cat_sorted_commands; /* Sort by category, then by name. */ static int sort_by_category(const void *a_, const void *b_) { /* Typecasts, so it goes. */ ConsoleCommand * a = *((ConsoleCommand **)a_); ConsoleCommand * b = *((ConsoleCommand **)b_); if (a->cat == b->cat) { return strcmp(a->name, b->name); } return a->cat - b->cat; } void init_commands() { /* XXX Leak! */ name_sorted_commands = g_malloc(sizeof(ConsoleCommand *) * num_commands); for (size_t i = 0; i < num_commands; i++) { name_sorted_commands[i] = &CommonCommands[i]; } /* Sort them. */ qsort(name_sorted_commands, num_commands, sizeof(ConsoleCommand *), sort_by_name); /* Copy the list, then sort it by category. */ cat_sorted_commands = g_malloc(sizeof(ConsoleCommand *) * num_commands); memcpy(cat_sorted_commands, name_sorted_commands, sizeof(ConsoleCommand *) * num_commands); qsort(cat_sorted_commands, num_commands, sizeof(ConsoleCommand *), sort_by_category); /* TODO Add to the list of tab-completion items. */ } const ConsoleCommand * find_command(const char *cmd) { ConsoleCommand ** asp_p = NULL, dummy; ConsoleCommand * dummy_p; ConsoleCommand * asp; char *cp, *cmd_cpy; cmd_cpy = g_strdup(cmd); for (cp=cmd_cpy; *cp; cp++) { *cp =tolower(*cp); } dummy.name = cmd_cpy; dummy_p = &dummy; asp_p = bsearch( (void *)&dummy_p, (void *)name_sorted_commands, num_commands, sizeof(ConsoleCommand *), sort_by_name); if (asp_p == NULL) { free(cmd_cpy); return NULL; } asp = *asp_p; /* TODO The server's find_command() searches first the commands, then the emotes. We might have to do something similar someday, too. */ /* if (asp == NULL) search something else? */ free(cmd_cpy); return asp; } /** * Returns a pointer to the head of an array of ConsoleCommands sorted by * category, then by name. It's num_commands long. */ ConsoleCommand ** get_cat_sorted_commands(void) { return cat_sorted_commands; } /** * Tries to handle command cp (with optional params in cpnext, which may be * null) as a local command. If this was a local command, returns true to * indicate command was handled. This code was moved from extended_command so * scripts ca issue local commands to handle keybindings or anything else. * * @param cp * @param cpnext */ int handle_local_command(const char* cp, const char *cpnext) { const ConsoleCommand * cc = NULL; cc = find_command(cp); if (cc == NULL) { return FALSE; } if (cc->dofunc == NULL) { char buf[MAX_BUF]; snprintf(buf, MAX_BUF - 1, "Client command %s has no implementation!", cc->name); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, buf); return FALSE; } cc->dofunc(cpnext); return TRUE; } /** * This is an extended command (ie, 'who, 'whatever, etc). In general, we * just send the command to the server, but there are a few that we care about * (bind, unbind) * * The command passed to us can not be modified - if it is a keybinding, we * get passed the string that is that binding - modifying it effectively * changes the binding. * * @param ocommand */ void extended_command(const char *ocommand) { const char *cp = ocommand; char *cpnext, command[MAX_BUF]; if ((cpnext = strchr(cp, ' '))!=NULL) { int len = cpnext - ocommand; if (len > (MAX_BUF -1 )) { len = MAX_BUF-1; } strncpy(command, ocommand, len); command[len] = '\0'; cp = command; while (*cpnext == ' ') { cpnext++; } if (*cpnext == 0) { cpnext = NULL; } } /* * Try to prevent potential client hang by trying to delete a * character when there is no character to delete. * Thus, only send quit command if there is a player to delete. */ if (cpl.title[0] == '\0' && strcmp(cp, "quit") == 0){ // Bail here, there isn't anything this should be doing. return; } /* cp now contains the command (everything before first space), * and cpnext contains everything after that first space. cpnext * could be NULL. */ #ifdef HAVE_LUA if ( script_lua_command(cp, cpnext) ) { return; } #endif /* If this isn't a client-side command, send it to the server. */ if (!handle_local_command(cp, cpnext)) { /* just send the command(s) (if `ocommand' is a compound command */ /* then split it and send each part separately */ /* TODO Remove this from the server; end of commands.c. */ strncpy(command, ocommand, MAX_BUF-1); command[MAX_BUF-1]=0; cp = strtok(command, ";"); while ( cp ) { while( *cp == ' ' ) { cp++; } /* throw out leading spaces; server does not like them */ send_command(cp, cpl.count, 0); cp = strtok(NULL, ";"); } } } /* ------------------------------------------------------------------ */ /* This list is used for the 'tab' completion, and nothing else. * Therefore, if it is out of date, it isn't that terrible, but * ideally it should stay somewhat up to date with regards to * the commands the server supports. */ /* TODO Dynamically generate. */ static const char *const commands[] = { "accuse", "afk", "apply", "applymode", "archs", "beg", "bleed", "blush", "body", "bounce", "bow", "bowmode", "brace", "build", "burp", "cackle", "cast", "chat", "chuckle", "clap", "cointoss", "cough", "cringe", "cry", "dance", "disarm", "dm", "dmhide", "drop", "dropall", "east", "examine", "explore", "fire", "fire_stop", "fix_me", "flip", "frown", "gasp", "get", "giggle", "glare", "grin", "groan", "growl", "gsay", "help", "hiccup", "hiscore", "hug", "inventory", "invoke", "killpets", "kiss", "laugh", "lick", "listen", "logs", "mapinfo", "maps", "mark", "me", "motd", "nod", "north", "northeast", "northwest", "orcknuckle", "output-count", "output-sync", "party", "peaceful", "petmode", "pickup", "players", "poke", "pout", "prepare", "printlos", "puke", "quests", "quit", "ready_skill", "rename", "reply", "resistances", "rotateshoottype", "run", "run_stop", "save", "say", "scream", "search", "search-items", "shake", "shiver", "shout", "showpets", "shrug", "shutdown", "sigh", "skills", "slap", "smile", "smirk", "snap", "sneeze", "snicker", "sniff", "snore", "sound", "south", "southeast", "southwest", "spit", "statistics", "stay", "strings", "strut", "sulk", "take", "tell", "thank", "think", "throw", "time", "title", "twiddle", "use_skill", "usekeys", "version", "wave", "weather", "west", "whereabouts", "whereami", "whistle", "who", "wimpy", "wink", "yawn", }; const size_t num_server_commands = sizeof(commands) / sizeof(char *); /** * Player has entered 'command' and hit tab to complete it. See if we can * find a completion. Returns matching command. Returns NULL if no command * matches. * * @param command */ const char * complete_command(const char *command) { int len, display = 0; const char *match; static char result[64]; char list[500]; len = strlen(command); if (len == 0) { return NULL; } strcpy(list, "Matching commands:"); /* TODO Partial match, e.g.: If the completion list was: wear wet #? If we type 'w' then hit tab, put in the e. Basically part of bash (readline?)'s behaviour. */ match = NULL; /* check server side commands */ for (size_t i = 0; i < num_server_commands; i++) { if (!strncmp(command, commands[i], len)) { if (display) { snprintf(list + strlen(list), 499 - strlen(list), " %s", commands[i]); } else if (match != NULL) { display = 1; snprintf(list + strlen(list), 499 - strlen(list), " %s %s", match, commands[i]); match = NULL; } else { match = commands[i]; } } } /* check client side commands */ for (size_t i = 0; i < num_commands; i++) { if (!strncmp(command, CommonCommands[i].name, len)) { if (display) { snprintf(list + strlen(list), 499 - strlen(list), " %s", CommonCommands[i].name); } else if (match != NULL) { display = 1; snprintf(list + strlen(list), 499 - strlen(list), " %s %s", match, CommonCommands[i].name); match = NULL; } else { match = CommonCommands[i].name; } } } if (match == NULL) { if (display) { strncat(list, "\n", 499 - strlen(list)); draw_ext_info( NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, list); } else draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "No matching command.\n"); /* No match. */ return NULL; } /* * Append a space to allow typing arguments. For commands without arguments * the excess space should be stripped off automatically. */ snprintf(result, sizeof(result), "%s ", match); return result; } crossfire-client-1.75.3/common/script_lua.c000644 001751 001751 00000024661 14045044330 021551 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file common/script_lua.c * */ #ifndef WIN32 #include #include #include #include #include #include #endif #include "client.h" #ifdef HAVE_LUA /* It seems easier to just comment everything out if we don't have * lua vs trying to play around with it in the makefiles. */ #include #include #include #include #if LUA_VERSION_NUM >= 501 #include #endif struct script_state { lua_State* state; const char* filename; }; #if 0 static void *l_alloc (void * /*ud*/, void *ptr, size_t /*osize*/, size_t nsize) { if (nsize == 0) { free(ptr); return NULL; } else { return g_realloc(ptr, nsize); } } #endif static const char* l_readerfile(lua_State *L, void *data, size_t *size) { static char buf[4096]; FILE* file = (FILE*)data; *size = fread(buf, 1, 4096, file); if ( !*size && ferror(file) ) { return NULL; } if ( !*size && feof(file)) { return NULL; } return buf; } static struct script_state* scripts = NULL; static int script_count = 0; static void update_player(lua_State* lua) { lua_pushstring(lua, "player"); lua_gettable(lua, LUA_GLOBALSINDEX); if (!lua_istable(lua, -1)) { lua_pop(lua, 1); return; } lua_pushstring(lua, "hp"); lua_pushnumber(lua, cpl.stats.hp); lua_settable(lua, -3); lua_pushstring(lua, "gr"); lua_pushnumber(lua, cpl.stats.grace); lua_settable(lua, -3); lua_pushstring(lua, "sp"); lua_pushnumber(lua, cpl.stats.sp); lua_settable(lua, -3); lua_pushstring(lua, "food"); lua_pushnumber(lua, cpl.stats.food); lua_settable(lua, -3); lua_pop(lua, 1); } static void do_item(lua_State* lua, item* it) { lua_newtable(lua); lua_pushstring(lua, "s_name"); lua_pushstring(lua, it->s_name); lua_settable(lua, -3); lua_pushstring(lua, "magical"); lua_pushnumber(lua, it->magical); lua_settable(lua, -3); lua_pushstring(lua, "cursed"); lua_pushnumber(lua, it->cursed); lua_settable(lua, -3); lua_pushstring(lua, "damned"); lua_pushnumber(lua, it->damned); lua_settable(lua, -3); lua_pushstring(lua, "unpaid"); lua_pushnumber(lua, it->unpaid); lua_settable(lua, -3); lua_pushstring(lua, "locked"); lua_pushnumber(lua, it->locked); lua_settable(lua, -3); lua_pushstring(lua, "applied"); lua_pushnumber(lua, it->applied); lua_settable(lua, -3); lua_pushstring(lua, "open"); lua_pushnumber(lua, it->open); lua_settable(lua, -3); } static void update_inv(lua_State* lua) { item* it; int index = 1; lua_pushstring(lua, "inv"); lua_newtable(lua); lua_settable(lua, LUA_GLOBALSINDEX); lua_pushstring(lua, "inv"); lua_gettable(lua, LUA_GLOBALSINDEX); for ( it = cpl.ob->inv; it; it = it->next ) { lua_pushnumber(lua, index++); do_item(lua, it); lua_settable(lua, -3); } lua_pop(lua, 1); } static void update_ground(lua_State* lua) { item* it; int index = 1; lua_pushstring(lua, "ground"); lua_newtable(lua); lua_settable(lua, LUA_GLOBALSINDEX); lua_pushstring(lua, "ground"); lua_gettable(lua, LUA_GLOBALSINDEX); for ( it = cpl.below->inv; it; it = it->next ) { if ( it->tag == 0 || strlen(it->s_name) == 0 ) { continue; } lua_pushnumber(lua, index++); do_item(lua, it); lua_settable(lua, -3); } lua_pop(lua, 1); } static int lua_draw(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ const char* what; if ( n != 1 ) { lua_pushstring(L, "draw what?"); lua_error(L); } if ( !lua_isstring(L, 1) ) { lua_pushstring(L, "expected a string"); lua_error(L); } what = lua_tostring(L,1); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, what); return 0; } static int lua_issue(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ const char* what; int repeat, must_send; if ( n != 3 ) { lua_pushstring(L, "syntax is cfissue repeat must_send command"); lua_error(L); } if ( !lua_isnumber(L, 1) ) { lua_pushstring(L, "expected a number"); lua_error(L); } if ( !lua_isnumber(L, 2) ) { lua_pushstring(L, "expected a number"); lua_error(L); } if ( !lua_isstring(L, 3) ) { lua_pushstring(L, "expected a number"); lua_error(L); } repeat = lua_tonumber(L, 1); must_send = lua_tonumber(L, 2); what = lua_tostring(L,3); send_command(what,repeat,must_send); return 0; } void script_lua_load(const char* name) { lua_State* lua; FILE* file; int load; int index = script_count; file = fopen(name,"r"); if ( !file ) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Invalid file"); return; } lua = lua_open(); if ( !lua ) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Memory allocation error."); fclose(file); return; } luaopen_base(lua); lua_pop(lua,1); luaopen_table(lua); lua_pop(lua,1); if (( load = lua_load(lua, l_readerfile, (void*)file, name))) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Load error!"); if ( load == LUA_ERRSYNTAX ) draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Syntax error!"); fclose(file); lua_close(lua); return; } fclose(file); lua_register(lua, "cfdraw", lua_draw); lua_register(lua, "cfissue", lua_issue); lua_pushstring(lua, "player"); lua_newtable(lua); lua_settable(lua, LUA_GLOBALSINDEX); update_player(lua); update_inv(lua); update_ground(lua); /* Load functions, init script */ if (lua_pcall(lua, 0, 0, 0)) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Init error!"); lua_close(lua); return; } scripts = g_realloc(scripts,sizeof(scripts[0])*(script_count+1)); if (scripts == NULL) { LOG(LOG_ERROR, "script_lua_load", "Could not allocate memory: %s", strerror(errno)); exit(EXIT_FAILURE); } script_count++; scripts[index].filename = g_strdup(name); scripts[index].state = lua; /* printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); lua_pushstring(lua, "init"); printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); lua_gettable(lua, LUA_GLOBALSINDEX); printf("lua_gettop = %d, lua_type => %s\n", lua_gettop(lua), lua_typename( lua, lua_type(lua, lua_gettop(lua)))); if (lua_isfunction(lua, lua_gettop(lua))) lua_call(lua, 0, 0); lua_pop(lua, 1); */ } void script_lua_list(const char* param) { if ( script_count == 0 ) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "No LUA scripts are currently running"); } else { int i; char buf[1024]; snprintf(buf, sizeof(buf), "%d LUA scripts currently running:",script_count); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, buf); for ( i=0; i= script_count ) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, "Invalid script index!"); return; } lua_close(scripts[i].state); if ( i < (script_count-1) ) { memmove(&scripts[i],&scripts[i+1],sizeof(scripts[i])*(script_count-i-1)); } --script_count; } void script_lua_stats() { int script; lua_State* lua; for ( script = 0; script < script_count; script++ ) { lua = scripts[script].state; lua_pushstring(lua, "event_stats"); lua_gettable(lua, LUA_GLOBALSINDEX); if (lua_isfunction(lua, lua_gettop(lua))) { int luaerror; update_player(lua); update_inv(lua); update_ground(lua); if ( ( luaerror = lua_pcall(lua, 0, 0, 0) ) ) { const char* what = lua_tostring(lua, lua_gettop(lua)); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, what); lua_pop(lua,1); } } else { lua_pop(lua, 1); } } } int script_lua_command(const char* command, const char* param) { int script; lua_State* lua; int ret = 0; for ( script = 0; script < script_count; script++ ) { lua = scripts[script].state; lua_pushstring(lua, "event_command"); lua_gettable(lua, LUA_GLOBALSINDEX); if (lua_isfunction(lua, lua_gettop(lua))) { int luaerror; update_player(lua); update_inv(lua); update_ground(lua); lua_pushstring(lua, command); lua_pushstring(lua, param ? param : ""); if ( ( luaerror = lua_pcall(lua, 2, 1, 0) ) ) { const char* what = lua_tostring(lua, lua_gettop(lua)); draw_ext_info( NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SCRIPT, what); lua_pop(lua,1); } else { ret = lua_tonumber(lua, 1); lua_pop(lua, 1); } } else { lua_pop(lua, 1); } } return ret; } #endif /* HAVE_LIB_LUA */ crossfire-client-1.75.3/common/test-metaserver.c000644 001751 001751 00000000461 14045044330 022526 0ustar00kevinzkevinz000000 000000 #include #include "metaserver.h" static void print_entry(char *server, int update, int players, char *version, char *comment, bool compatible) { printf("%s:%d:%s:%s\n", server, players, version, comment); } int main() { ms_init(); ms_fetch(print_entry); } crossfire-client-1.75.3/common/newsocket.c000644 001751 001751 00000015415 14323707640 021414 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Made this either client or server specific for 0.95.2 release - getting too * complicated to keep them the same, and the common code is pretty much * frozen now. */ #include "client.h" #include #include "script.h" /** * * @param sl * @param buf */ void SockList_Init(SockList *sl, guint8 *buf) { sl->len=0; sl->buf=buf + 2; /* reserve two bytes for total length */ } /** * * @param sl * @param c */ void SockList_AddChar(SockList *sl, char c) { if (sl->len + 1 < MAX_BUF - 2){ sl->buf[sl->len++]=c; } else{ /* * Cast c to an unsigned short so it displays correctly in the error message. * Otherwise, it prints as a hexadecimal number in a funny box. * * SilverNexus 2014-06-12 */ LOG(LOG_ERROR,"SockList_AddChar","Could not write %hu to socket: Buffer full.\n", (unsigned short)c); } } /** * * @param sl * @param data */ void SockList_AddShort(SockList *sl, guint16 data) { if (sl->len + 2 < MAX_BUF - 2){ sl->buf[sl->len++] = (data>>8)&0xff; sl->buf[sl->len++] = data & 0xff; } else{ LOG(LOG_ERROR,"SockList_AddShort","Could not write %hu to socket: Buffer full.\n", data); } } /** * * @param sl * @param data */ void SockList_AddInt(SockList *sl, guint32 data) { if (sl->len + 4 < MAX_BUF - 2){ sl->buf[sl->len++] = (data>>24)&0xff; sl->buf[sl->len++] = (data>>16)&0xff; sl->buf[sl->len++] = (data>>8)&0xff; sl->buf[sl->len++] = data & 0xff; } else{ LOG(LOG_ERROR,"SockList_AddInt","Could not write %u to socket: Buffer full.\n", data); } } /** * * @param sl * @param str */ void SockList_AddString(SockList *sl, const char *str) { int len = strlen(str); if (sl->len + len > MAX_BUF-2) { len = MAX_BUF-2 - sl->len; } memcpy(sl->buf + sl->len, str, len); sl->len += len; } /** * Send data from a socklist to the socket. */ int SockList_Send(SockList *sl, GSocketConnection* c) { sl->buf[-2] = sl->len / 256; sl->buf[-1] = sl->len % 256; if (c == NULL) { LOG(LOG_WARNING, "SockList_Send", "Sending data while not connected!"); return 1; } if (debug_protocol) { char *data_print = printable(sl->buf, sl->len); if (data_print != NULL) { LOG(LOG_INFO, "C->S", "len=%d |%s|", sl->len, data_print); free(data_print); } } GOutputStream* out = g_io_stream_get_output_stream(G_IO_STREAM(c)); bool ret = g_output_stream_write_all(out, sl->buf - 2, sl->len + 2, NULL, NULL, NULL); return ret ? 0 : -1; } /** * * @param data * @return */ char GetChar_String(const unsigned char *data) { return (data[0]); } /** * The reverse of SockList_AddInt, but on strings instead. Same for the * GetShort, but for 16 bits. * * @param data * @return */ int GetInt_String(const unsigned char *data) { return ((data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]); } /** * The reverse of SockList_AddInt, but on strings instead. Same for the * GetShort, but for 64 bits * * @param data * @return */ gint64 GetInt64_String(const unsigned char *data) { #ifdef WIN32 return (((gint64)data[0]<<56) + ((gint64)data[1]<<48) + ((gint64)data[2]<<40) + ((gint64)data[3]<<32) + ((gint64)data[4]<<24) + ((gint64)data[5]<<16) + ((gint64)data[6]<<8) + (gint64)data[7]); #else return (((guint64)data[0]<<56) + ((guint64)data[1]<<48) + ((guint64)data[2]<<40) + ((guint64)data[3]<<32) + ((guint64)data[4]<<24) + (data[5]<<16) + (data[6]<<8) + data[7]); #endif } /** * * @param data * @return */ short GetShort_String(const unsigned char *data) { return ((data[0]<<8)+data[1]); } /** * Get an unsigned short from the stream. * Useful for checking size of server packets. * * @param data * The character stream to read. * * @return * The first two bytes, converted to a uint16. * * @note Currently static since it is only used in this file. * Can be added to the header and made non-static if needed elsewhere */ static guint16 GetUShort_String(const unsigned char data[static 2]) // We want at least two characters. { return ((data[0]<<8)+data[1]); } /** * Reads from the socket and puts data into a socklist. The only processing * done is to remove the initial size value. An assumption made is that the * buffer is at least 2 bytes long. * * @param fd Socket to read from. * @param sl Pointer to a buffer to put the read data. * @param len Size of the buffer allocated to accept data. * @return Return true if we think we have a full packet, 0 if we have * a partial packet, or -1 if an error occurred. */ bool SockList_ReadPacket(GSocketConnection c[static 1], SockList sl[static 1], size_t len, GError** error) { GInputStream* in = g_io_stream_get_input_stream(G_IO_STREAM(csocket.fd)); gsize read; if (!g_input_stream_read_all(in, sl->buf, 2, &read, NULL, error)) { return false; } if (read != 2) { sl->len = 0; return true; } size_t to_read = (size_t)GetUShort_String(sl->buf); if (to_read + 2 > len) { g_set_error(error, CLIENT_ERROR, CLIENT_ERROR_TOOBIG, "Server packet too big"); return false; } if (!g_input_stream_read_all(in, sl->buf + 2, to_read, &read, NULL, error)) { return false; } if (read != to_read) { sl->len = 0; return true; } sl->len = to_read + 2; #ifdef CS_LOGSTATS cst_tot.ibytes += sl->len; cst_lst.ibytes += sl->len; #endif return true; } /** * Send a printf-formatted packet to the socket. * * @param fd The socket to send to. * @param str The printf format string. * @param ... An optional list of values to fulfill the format string. */ int cs_print_string(GSocketConnection* fd, const char *str, ...) { va_list args; SockList sl; guint8 buf[MAX_BUF]; SockList_Init(&sl, buf); va_start(args, str); sl.len += vsnprintf((char*)sl.buf + sl.len, MAX_BUF-sl.len, str, args); va_end(args); // Adjust sl.len to account for when we overflow the buffer. if (sl.len > MAX_BUF - 3) { sl.len = MAX_BUF - 3; } script_monitor_str((char*)sl.buf); return SockList_Send(&sl, fd); } crossfire-client-1.75.3/common/image.c000644 001751 001751 00000066717 14045044330 020476 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Contains image related functions at a high level. It mostly deals with the * caching of the images, processing the image commands from the server, etc. */ #include "client.h" #include #include #ifdef WIN32 #include #include #endif #include "external.h" /* Rotate right from bsd sum. */ #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x80000000; else (c) >>= 1; /*#define CHECKSUM_DEBUG*/ struct FD_Cache { char name[MAX_BUF]; int fd; } fd_cache[MAX_FACE_SETS]; /** * Given a filename, this tries to load the data. It returns 0 success, -1 on * failure. It returns the data and len, the passed options. This function * is called only if the client caching feature is enabled. * * @param filename File name of an image to try to load. * @param data Caller-allocated pointer to a buffer to load image into. * @param len Amount of buffer used by the loaded image. * @param csum Returns 0/unset (caller already knows if checksum matches?). * Changes have made such that the caller knows whether or not * the checksum matches, so there is little point to re-do it. * @return 0 on success, -1 on failure. */ static int load_image(char *filename, guint8 *data, int *len, guint32 *csum) { int fd, i; char *cp; /* If the name includes an @, then that is a combined image file, so we * need to load the image a bit specially. By using these combined image * files, it reduces number of opens needed. In fact, we keep track of * which ones we have opened to improve performance. Note that while not * currently done, this combined image scheme could be done when storing * images in the player's image cache. */ if ((cp = strchr(filename, '@')) != NULL) { char *lp; int offset, last = -1; #ifdef WIN32 int length; #endif offset = atoi(cp + 1); lp = strchr(cp, ':'); if (!lp) { LOG(LOG_ERROR, "common::load_image", "Corrupt filename - has '@' but no ':' ?(%s)", filename); return -1; } #ifdef WIN32 length = atoi(lp + 1); #endif *cp = 0; for (i = 0; i < MAX_FACE_SETS; i++) { if (!strcmp(fd_cache[i].name, filename)) { break; } if (last == -1 && fd_cache[i].fd == -1) { last = i; } } /* Didn't find a matching entry yet, so make one */ if (i == MAX_FACE_SETS) { if (last == -1) { LOG(LOG_WARNING, "common::load_image", "fd_cache filled up? unable to load matching cache entry"); *cp = '@'; /* put @ back in string */ return -1; } #ifdef WIN32 if ((fd_cache[last].fd = open(filename, O_RDONLY | O_BINARY)) == -1) #else if ((fd_cache[last].fd = open(filename, O_RDONLY)) == -1) #endif { LOG(LOG_WARNING, "common::load_image", "unable to load listed cache file %s", filename); *cp = '@'; /* put @ back in string */ return -1; } strcpy(fd_cache[last].name, filename); i = last; } lseek(fd_cache[i].fd, offset, SEEK_SET); #ifdef WIN32 *len = read(fd_cache[i].fd, data, length); #else *len = read(fd_cache[i].fd, data, 65535); #endif *cp = '@'; } else { #ifdef WIN32 int length = 0; if ((fd = open(filename, O_RDONLY | O_BINARY)) == -1) { return -1; } length = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); *len = read(fd, data, length); #else if ((fd = open(filename, O_RDONLY)) == -1) { return -1; } *len = read(fd, data, 65535); #endif close(fd); } face_info.cache_hits++; *csum = 0; return 0; #if 0 /* Shouldn't be needed anymore */ *csum = 0; for (i = 0; i < *len; i++) { ROTATE_RIGHT(*csum); *csum += data[i]; *csum &= 0xffffffff; } #endif } /**************************************************************************** * This is our image caching logic. We use a hash to make the name lookups * happen quickly - this is done for speed, but also because we don't really * have a good idea on how many images may used. It also means that as the * cache gets filled up with images in a random order, the lookup is still * pretty quick. * * If a bucket is filled with an entry that is not of the right name, * we store/look for the correct one in the next bucket. */ /* This should be a power of 2 */ #define IMAGE_HASH 8192 Face_Information face_info; /** This holds the name we recieve with the 'face' command so we know what * to save it as when we actually get the face. */ static char *facetoname[MAXPIXMAPNUM]; struct Image_Cache { char *image_name; struct Cache_Entry *cache_entry; } image_cache[IMAGE_HASH]; /** * This function is basically hasharch from the server, common/arch.c a few * changes - first, we stop processing when we reach the first . - this is * because I'm not sure if hashing .111 at the end of all the image names will * be very useful. */ static guint32 image_hash_name(char *str, int tablesize) { guint32 hash = 0; char *p; /* use the same one-at-a-time hash function the server now uses */ for (p = str; *p != '\0' && *p != '.'; p++) { hash += *p; hash += hash << 10; hash ^= hash >> 6; } hash += hash << 3; hash ^= hash >> 11; hash += hash << 15; return hash % tablesize; } /** * This function returns an index into the image_cache for a matching entry, * -1 if no match is found. */ static gint32 image_find_hash(char *str) { guint32 hash = image_hash_name(str, IMAGE_HASH), newhash; newhash = hash; do { /* No entry - return immediately */ if (image_cache[newhash].image_name == NULL) { return -1; } if (!strcmp(image_cache[newhash].image_name, str)) { return newhash; } newhash ++; if (newhash == IMAGE_HASH) { newhash = 0; } } while (newhash != hash); /* If the hash table is full, this is bad because we won't be able to * add any new entries. */ LOG(LOG_WARNING, "common::image_find_hash", "Hash table is full, increase IMAGE_CACHE size"); return -1; } /** * */ static void image_remove_hash(char *imagename, Cache_Entry *ce) { int hash_entry; Cache_Entry *last; hash_entry = image_find_hash(imagename); if (hash_entry == -1) { LOG(LOG_ERROR, "common::image_remove_hash", "Unable to find cache entry for %s, %s", imagename, ce->filename); return; } if (image_cache[hash_entry].cache_entry == ce) { image_cache[hash_entry].cache_entry = ce->next; free(ce->filename); free(ce); return; } last = image_cache[hash_entry].cache_entry; while (last->next && last->next != ce) { last = last->next; } if (!last->next) { LOG(LOG_ERROR, "common::image_rmove_hash", "Unable to find cache entry for %s, %s", imagename, ce->filename); return; } last->next = ce->next; free(ce->filename); free(ce); } /** * This finds and returns the Cache_Entry of the image that matches name * and checksum if has_sum is set. If has_sum is not set, we can't * do a checksum comparison. */ static Cache_Entry *image_find_cache_entry(char *imagename, guint32 checksum, int has_sum) { int hash_entry; Cache_Entry *entry; hash_entry = image_find_hash(imagename); if (hash_entry == -1) { return NULL; } entry = image_cache[hash_entry].cache_entry; if (has_sum) { while (entry) { if (entry->checksum == checksum) { break; } entry = entry->next; } } return entry; /* This could be NULL */ } /** * Add a hash entry. Returns the entry we added, NULL on failure. */ static Cache_Entry *image_add_hash(char *imagename, char *filename, guint32 checksum, guint32 ispublic) { Cache_Entry *new_entry; guint32 hash = image_hash_name(imagename, IMAGE_HASH), newhash; newhash = hash; while (image_cache[newhash].image_name != NULL && strcmp(image_cache[newhash].image_name, imagename)) { newhash ++; if (newhash == IMAGE_HASH) { newhash = 0; } /* If the hash table is full, can't do anything */ if (newhash == hash) { LOG(LOG_WARNING, "common::image_find_hash", "Hash table is full, increase IMAGE_CACHE size"); return NULL; } } if (!image_cache[newhash].image_name) { image_cache[newhash].image_name = g_strdup(imagename); } /* We insert the new entry at the start of the list of the buckets * for this entry. In the case of the players entries, this probably * improves performance, presuming ones later in the file are more likely * to be used compared to those at the start of the file. */ new_entry = g_malloc(sizeof(struct Cache_Entry)); new_entry->filename = g_strdup(filename); new_entry->checksum = checksum; new_entry->ispublic = ispublic; new_entry->image_data = NULL; new_entry->next = image_cache[newhash].cache_entry; image_cache[newhash].cache_entry = new_entry; return new_entry; } /** * Process a line from the bmaps.client file. In theory, the format should be * quite strict, as it is computer generated, but we try to be lenient/follow * some conventions. Note that this is destructive to the data passed in * line. */ static void image_process_line(char *line, guint32 ispublic) { char imagename[MAX_BUF], filename[MAX_BUF]; guint32 checksum; if (line[0] == '#') { return; /* Ignore comments */ } if (sscanf(line, "%s %u %s", imagename, &checksum, filename) == 3) { image_add_hash(imagename, filename, checksum, ispublic); } else { LOG(LOG_WARNING, "common::image_process_line", "Did not parse line %s properly?", line); } } /** * */ void init_common_cache_data(void) { FILE *fp; char bmaps[MAX_BUF], inbuf[MAX_BUF]; int i; if (!want_config[CONFIG_CACHE]) { return; } for (i = 0; i < MAXPIXMAPNUM; i++) { facetoname[i] = NULL; } /* First, make sure that image_cache is nulled out */ memset(image_cache, 0, IMAGE_HASH * sizeof(struct Image_Cache)); snprintf(bmaps, sizeof(bmaps), "%s/bmaps.client", CF_DATADIR); if ((fp = fopen(bmaps, "r")) != NULL) { while (fgets(inbuf, MAX_BUF - 1, fp) != NULL) { image_process_line(inbuf, 1); } fclose(fp); } else { snprintf(inbuf, sizeof(inbuf), "Unable to open %s. You may wish to download and install the image file to improve performance.\n", bmaps); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, inbuf); } snprintf(bmaps, sizeof(bmaps), "%s/image-cache/bmaps.client", cache_dir); if ((fp = fopen(bmaps, "r")) != NULL) { while (fgets(inbuf, MAX_BUF - 1, fp) != NULL) { image_process_line(inbuf, 0); } fclose(fp); } /* User may not have a cache, so no error if not found */ for (i = 0; i < MAX_FACE_SETS; i++) { fd_cache[i].fd = -1; fd_cache[i].name[0] = '\0'; } } /****************************************************************************** * * Code related to face caching. * *****************************************************************************/ char facecachedir[MAX_BUF]; /** * */ void requestface(int pnum, char *facename) { face_info.cache_misses++; facetoname[pnum] = g_strdup(facename); cs_print_string(csocket.fd, "askface %d", pnum); } /** * This is common for all the face commands (face2, face1, face). * For face1 and face commands, faceset should always be zero. * for face commands, has_sum and checksum will be zero. * pnum is the face number, while face is the name. * We actually don't care what the set it - it could be useful right now, * but in the current caching scheme, we look through all the facesets for * the image and if the checksum matches, we assume we have match. * This approach makes sure that we don't have to store the same image multiple * times simply because the set number may be different. */ void finish_face_cmd(int pnum, guint32 checksum, int has_sum, char *face, int faceset) { int len; guint32 nx, ny; guint8 data[65536], *png_tmp; char filename[1024]; guint32 newsum = 0; Cache_Entry *ce = NULL; #if 0 fprintf(stderr, "finish_face_cmd, pnum=%d, checksum=%d, face=%s\n", pnum, checksum, face); #endif /* In the case of gfx, we don't care about checksum. For public and * private areas, if we care about checksum, and the image doesn't match, * we go onto the next step. If nothing found, we request it * from the server. */ snprintf(filename, sizeof(filename), "%s/gfx/%s.png", cache_dir, face); if (load_image(filename, data, &len, &newsum) == -1) { ce = image_find_cache_entry(face, checksum, has_sum); if (!ce) { /* Not in our cache, so request it from the server */ requestface(pnum, face); return; } else if (ce->image_data) { /* If this has image_data, then it has already been rendered */ if (!associate_cache_entry(ce, pnum)) { return; } } if (ce->ispublic) snprintf(filename, sizeof(filename), "%s/%s", CF_DATADIR, ce->filename); else snprintf(filename, sizeof(filename), "%s/image-cache/%s", cache_dir, ce->filename); if (load_image(filename, data, &len, &newsum) == -1) { LOG(LOG_WARNING, "common::finish_face_cmd", "file %s listed in cache file, but unable to load", filename); requestface(pnum, face); return; } } /* If we got here, we found an image and the checksum is OK. */ if (!(png_tmp = png_to_data(data, len, &nx, &ny))) { /* If the data is bad, remove it if it is in the players private cache */ LOG(LOG_WARNING, "common::finish_face_cmd", "Got error on png_to_data, image=%s", face); if (ce) { if (!ce->ispublic) { unlink(filename); } image_remove_hash(face, ce); } requestface(pnum, face); } /* create_and_rescale_image_from data is an external reference to a piece in * the gui section of the code. */ if (create_and_rescale_image_from_data(ce, pnum, png_tmp, nx, ny)) { LOG(LOG_WARNING, "common::finish_face_cmd", "Got error on create_and_rescale_image_from_data, file=%s", filename); requestface(pnum, face); } free(png_tmp); } /** * We can now connect to different servers, so we need to clear out any old * images. We try to free the data also to prevent memory leaks. * Note that we don't touch our hashed entries - so that when we connect to a * new server, we still have all that information. */ void reset_image_cache_data(void) { int i; if (want_config[CONFIG_CACHE]) { for (i = 1; i < MAXPIXMAPNUM; i++) { free(facetoname[i]); facetoname[i] = NULL; } } } /** * We only get here if the server believes we are caching images. We rely on * the fact that the server will only send a face command for a particular * number once - at current time, we have no way of knowing if we have already * received a face for a particular number. */ void Face2Cmd(guint8 *data, int len) { int pnum; guint8 setnum; guint32 checksum; char *face; /* A quick sanity check, since if client isn't caching, all the data * structures may not be initialized. */ if (!use_config[CONFIG_CACHE]) { LOG(LOG_WARNING, "common::Face2Cmd", "Received a 'face' command when we are not caching"); return; } pnum = GetShort_String(data); setnum = data[2]; checksum = GetInt_String(data + 3); face = (char *)data + 7; data[len] = '\0'; finish_face_cmd(pnum, checksum, 1, face, setnum); } /** * */ void Image2Cmd(guint8 *data, int len) { int pnum, plen; guint8 setnum; pnum = GetInt_String(data); setnum = data[4]; plen = GetInt_String(data + 5); if (len < 9 || (len - 9) != plen) { LOG(LOG_WARNING, "common::Image2Cmd", "Lengths don't compare (%d,%d)", (len - 9), plen); return; } display_newpng(pnum, data + 9, plen, setnum); } /** * Helper for display_newpng, implements the caching of the image to disk. */ static void cache_newpng(int face, guint8 *buf, int buflen, int setnum, Cache_Entry **ce) { char filename[MAX_BUF], basename[MAX_BUF]; FILE *tmpfile; guint32 i, csum; if (facetoname[face] == NULL) { LOG(LOG_WARNING, "common::display_newpng", "Caching images, but name for %ld not set", face); /* Return to avoid null dereference. */ return; } /* Make necessary leading directories */ snprintf(filename, sizeof(filename), "%s/image-cache", cache_dir); if (g_access(filename, R_OK | W_OK | X_OK) == -1) { g_mkdir(filename, 0755); } snprintf(filename, sizeof(filename), "%s/image-cache/%c%c", cache_dir, facetoname[face][0], facetoname[face][1]); if (access(filename, R_OK | W_OK | X_OK) == -1) { g_mkdir(filename, 0755); } /* If setnum is valid, and we have faceset information for it, * put that prefix in. This will make it easier later on to * allow the client to switch image sets on the fly, as it can * determine what set the image belongs to. * We also append the number to it - there could be several versions * of 'face.base.111.x' if different servers have different image * values. */ if (setnum >= 0 && setnum < MAX_FACE_SETS && face_info.facesets[setnum].prefix) { snprintf(basename, sizeof(basename), "%s.%s", facetoname[face], face_info.facesets[setnum].prefix); } else { strcpy(basename, facetoname[face]); } /* Decrease it by one since it will immediately get increased * in the loop below. */ setnum--; do { setnum++; snprintf(filename, sizeof(filename), "%s/image-cache/%c%c/%s.%d", cache_dir, facetoname[face][0], facetoname[face][1], basename, setnum); } while (g_access(filename, F_OK) == -0); #ifdef WIN32 if ((tmpfile = fopen(filename, "wb")) == NULL) #else if ((tmpfile = fopen(filename, "w")) == NULL) #endif { LOG(LOG_WARNING, "common::display_newpng", "Can not open %s for writing", filename); } else { /* found a file we can write to */ fwrite(buf, buflen, 1, tmpfile); fclose(tmpfile); csum = 0; for (i = 0; (int)i < buflen; i++) { ROTATE_RIGHT(csum); csum += buf[i]; csum &= 0xffffffff; } snprintf(filename, sizeof(filename), "%c%c/%s.%d", facetoname[face][0], facetoname[face][1], basename, setnum); *ce = image_add_hash(facetoname[face], filename, csum, 0); /* It may very well be more efficient to try to store these up * and then write them as a bunch instead of constantly opening the * file for appending. OTOH, hopefully people will be using the * built image archives, so only a few faces actually need to get * downloaded. */ snprintf(filename, sizeof(filename), "%s/image-cache/bmaps.client", cache_dir); if ((tmpfile = fopen(filename, "a")) == NULL) { LOG(LOG_WARNING, "common::display_newpng", "Can not open %s for appending", filename); } else { fprintf(tmpfile, "%s %u %c%c/%s.%d\n", facetoname[face], csum, facetoname[face][0], facetoname[face][1], basename, setnum); fclose(tmpfile); } } } /** * This function is called when the server has sent us the actual png data for * an image. If caching, we need to write this data to disk (this is handled * in the function cache_newpng). */ void display_newpng(int face, guint8 *buf, int buflen, int setnum) { guint8 *pngtmp; guint32 width, height; Cache_Entry *ce = NULL; if (use_config[CONFIG_CACHE]) { cache_newpng(face, buf, buflen, setnum, &ce); } pngtmp = png_to_data(buf, buflen, &width, &height); if (!pngtmp) { LOG(LOG_ERROR, "display_newpng", "error in PNG data; discarding"); return; } if (create_and_rescale_image_from_data(ce, face, pngtmp, width, height)) { LOG(LOG_WARNING, "common::display_newpng", "create_and_rescale_image_from_data failed for face %ld", face); } if (use_config[CONFIG_CACHE]) { free(facetoname[face]); facetoname[face] = NULL; } free(pngtmp); } /** * Takes the data from a replyinfo image_info and breaks it down. The info * contained is the checkums, number of images, and faceset information. It * stores this data into the face_info structure. * Since we know data is null terminated, we can use the strchr operations * with safety. * In each block, we find the newline - if we find one, we presume the data is * good, and update the face_info accordingly. if we don't find a newline, we * return. */ void get_image_info(guint8 *data, int len) { char *cp, *lp, *cps[7], buf[MAX_BUF]; int onset = 0, badline = 0, i; replyinfo_status |= RI_IMAGE_INFO; lp = (char *)data; cp = strchr(lp, '\n'); if (!cp || (cp - lp) > len) { return; } face_info.num_images = atoi(lp); lp = cp + 1; cp = strchr(lp, '\n'); if (!cp || (cp - lp) > len) { return; } face_info.bmaps_checksum = strtoul(lp, NULL, 10); /* need unsigned, so no atoi */ lp = cp + 1; cp = strchr(lp, '\n'); while (cp && (cp - lp) <= len) { *cp++ = '\0'; /* The code below is pretty much the same as the code from the server * which loads the original faceset file. */ if (!(cps[0] = strtok(lp, ":"))) { badline = 1; } for (i = 1; i < 7; i++) { if (!(cps[i] = strtok(NULL, ":"))) { badline = 1; } } if (badline) { LOG(LOG_WARNING, "common::get_image_info", "bad data, ignoring line:/%s/", lp); } else { onset = atoi(cps[0]); if (onset >= MAX_FACE_SETS) { LOG(LOG_WARNING, "common::get_image_info", "setnum is too high: %d > %d", onset, MAX_FACE_SETS); } face_info.facesets[onset].prefix = g_strdup(cps[1]); face_info.facesets[onset].fullname = g_strdup(cps[2]); face_info.facesets[onset].fallback = atoi(cps[3]); face_info.facesets[onset].size = g_strdup(cps[4]); face_info.facesets[onset].extension = g_strdup(cps[5]); face_info.facesets[onset].comment = g_strdup(cps[6]); } lp = cp; cp = strchr(lp, '\n'); } face_info.have_faceset_info = 1; /* if the user has requested a specific face set and that set * is not numeric, try to find a matching set and send the * relevent setup command. */ if (face_info.want_faceset && atoi(face_info.want_faceset) == 0) { for (onset = 0; onset < MAX_FACE_SETS; onset++) { if (face_info.facesets[onset].prefix && !g_ascii_strcasecmp(face_info.facesets[onset].prefix, face_info.want_faceset)) { break; } if (face_info.facesets[onset].fullname && !g_ascii_strcasecmp(face_info.facesets[onset].fullname, face_info.want_faceset)) { break; } } if (onset < MAX_FACE_SETS) { /* We found a match */ face_info.faceset = onset; cs_print_string(csocket.fd, "setup faceset %d", onset); } else { snprintf(buf, sizeof(buf), "Unable to find match for faceset %s on the server", face_info.want_faceset); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, buf); } } } /** * This gets a block of checksums from the server. This lets it prebuild the * images or what not. It would probably be nice to add a gui callback * someplace that gives a little status display (18% done or whatever) - that * probably needs to be done further up. * * The start and stop values are not meaningful - they are here because the * semantics of the requestinfo/replyinfo is that replyinfo includes the same * request data as the requestinfo (thus, if the request failed for some * reason, the client would know which one failed and then try again). * Currently, we don't have any logic in the function below to deal with * failures. */ void get_image_sums(char *data, int len) { int stop, imagenum, slen, faceset; guint32 checksum; char *cp, *lp; cp = strchr((char *)data, ' '); if (!cp || (cp - data) > len) { return; } while (isspace(*cp)) { cp++; } lp = cp; cp = strchr(lp, ' '); if (!cp || (cp - data) > len) { return; } stop = atoi(lp); replyinfo_last_face = stop; /* Can't use isspace here, because it matches with tab, ascii code * 9 - this results in advancing too many spaces because * starting at image 2304, the MSB of the image number will be * 9. Using a check against space will work until we get up to * 8192 images. */ while (*cp == ' ') { cp++; } while ((cp - data) < len) { imagenum = GetShort_String((guint8 *)cp); cp += 2; checksum = GetInt_String((guint8 *)cp); cp += 4; faceset = *cp; cp++; slen = *cp; cp++; /* Note that as is, this can break horribly if the client is missing a large number * of images - that is because it will request a whole bunch which will overflow * the servers output buffer, causing it to close the connection. * What probably should be done is for the client to just request this checksum * information in small batches so that even if the client has no local * images, requesting the entire batch won't overflow the sockets buffer - this * probably amounts to about 100 images at a time */ finish_face_cmd(imagenum, checksum, 1, (char *)cp, faceset); if (imagenum > stop) { LOG(LOG_WARNING, "common::get_image_sums", "Received an image beyond our range? %d > %d", imagenum, stop); } cp += slen; } } crossfire-client-1.75.3/common/item-types000644 001751 001751 00000006312 14350011144 021250 0ustar00kevinzkevinz000000 000000 # # This file is parsed by the client and gets used for item orderings. # Order is how items will show in inventory (low numbers first). There # is no requirement that the numbers are consecutive. Max number allowed # is 254 (255 is reserved for unmatched items. # # Note: entries are case sensitive. # Note2: Many entries have a trailing space (ie, 'ring '). This is # intentional - this is so they match more closely (otherwise ring # matches things like stormbringer. # Note3: When finding matches for items, the client starts with the # lowest number and works upward. So if you want generic matches, it # is better to put them at a later number so more specific matches will # happen first. # # While this has not been done for all categories, please try to order # the entries for each category (number) in alphabetical order. # # containers # Moved containers to the top - this is because of stuff like quiver of # arrows, but also more convenient # 1: sack Luggage pouch quiver bag chest key ring # Weapon types # Stylistically, I separate the artifacts here to make it # a little clear. It could be said that actually having a different # element for the artifacts is desirable. 2: axe club dagger falchion hammer katana mace magnifying glass morningstar nunchacu quarterstaff sabre scimitar shovel ^spear stake ^sword Belzebub's sword Firebrand Harakiri sword broadsword light sword Serpentman sword shortsword long sword taifu trident BoneCrusher Darkblade Demonslayer Dragonslayer Excalibur firebrand Firestar Flame Tongue FlameTongue Frost Hammer Katana of Masamune Lightning sticks Mjoellnir Mournblade Sting Stormbringer Trident 3: ^bow elven bow long bow crossbow sling arrow ^bolt boulder # armor 10: mail leather ^robe shirt apron hauberk # Headware 11: helmet Crown crown 12: shield Demonspawn Shield 13: boot glove gauntlet shoe 14: girdle 15: cloak 16: bracer # food 20: apple booze bread cabbage cake carrot chocolate clover cup egg fish food mint sprig mushroom onion orange potato roast bird steak waybread ^water # gems 30: diamond emerald gold nugget pearl ruby sapphire 31: coin # magic 45: rod Rod 47: wand 48: staff 52: horn 53: amulet 54: ring Ring 55: scroll # Spellbooks 56: grimore grimoire hymnal manual prayerbook sacred text spellbook testiment treatise tome # Readables. Note we included the generic book here. 57: book catalog codex collection compendium compilation divine text divine work encyclopedia exposition file formulary guide holy book holy record index moral text notes note pamphlet record tables transcript volume 59: potion bottle 61: ^balm ^dust dust figurine # Item building scrolls 63: Improve Lower Weapon Enchant Weapon Prepare Weapon Enchant Armour # Misc skill objects 65: holy symbol lockpick talisman writing pen 67: key Key # # body parts # 70: arm claw corpse dragon scale ectoplasm eye finger foot hand head Head heart icor leg lich dust liver orc chop pixie dust residue skin stinger tongue tooth ^wing # Misc alchemy items (minerals) 71: dirt lead mandrake root pile rock stone # 80: flint and steel torch # # Misc stuff - just to prevent error messages # 90: clock flower Gate Pass Glowing Crystal gravestone icecube library card Passport Port Pass rose Apartment Extender 100: chair table crossfire-client-1.75.3/common/item.h000644 001751 001751 00000007145 14110265004 020341 0ustar00kevinzkevinz000000 000000 /* * static char *rcsid_common_item_h = * "$Id$"; */ /* Crossfire client, a client program for the crossfire program. Copyright (C) 2001 Mark Wedel & Crossfire Development Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file common/item.h * */ #ifndef ITEM_H #define ITEM_H /* * Use static buffer for object names. Item names are changing so * often that mallocing them it just a waste of time. Also there is * probably some upper limits for names that client can show, Note * that total number of items is small (<100) so this don't even * waste too much memory */ #define NAME_LEN 128 #define copy_name(t,f) strncpy(t, f, NAME_LEN-1); t[NAME_LEN-1]=0; #define NO_ITEM_TYPE 30000 /* * item structure keeps all information what player * (= client) knows about items in its inventory */ typedef struct item_struct { struct item_struct *next; /* next item in inventory */ struct item_struct *prev; /* previous item in inventory */ struct item_struct *env; /* which items inventory is this item */ struct item_struct *inv; /* items inventory */ char d_name[NAME_LEN]; /* item's full name w/o status information */ char s_name[NAME_LEN]; /* item's singular name as sent to us */ char p_name[NAME_LEN]; /* item's plural name as sent to us */ char flags[NAME_LEN]; /* item's status information */ gint32 tag; /* item identifier (0 = free) */ guint32 nrof; /* number of items */ float weight; /* how much item weights */ gint16 face; /* index for face array */ guint16 animation_id; /* Index into animation array */ guint8 anim_speed; /* how often to animate */ guint8 anim_state; /* last face in sequence drawn */ guint16 last_anim; /* how many ticks have passed since we last animated */ guint16 magical:1; /* item is magical */ guint16 cursed:1; /* item is cursed */ guint16 damned:1; /* item is damned */ guint16 blessed:1; /* item is blessed */ guint16 unpaid:1; /* item is unpaid */ guint16 locked:1; /* item is locked */ guint16 applied:1; /* item is applied */ guint16 open:1; /* container is open */ guint16 was_open:1; /* container was open */ guint16 read:1; /* book has been read */ guint16 inv_updated:1; /* item's inventory is updated, this is set when item's inventory is modified, draw routines can use this to redraw things */ guint8 apply_type; /* how item is applied (worn/wield/etc) */ guint32 flagsval; /* unmodified flags value as sent from the server*/ guint16 type; /* Item type for ordering */ } item; /* Toolkits implement these. */ extern void item_event_item_deleting(item * it); extern void item_event_container_clearing(item * container); /* TODO More fine-grained event - but how to handle it? */ extern void item_event_item_changed(item * it); extern int can_write_spell_on(item* it); #endif /* ITEM_H */ crossfire-client-1.75.3/common/client.c000644 001751 001751 00000042606 14323707640 020672 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Client interface main routine. Sets up a few global variables, connects to * the server, tells it what kind of pictures it wants, adds the client and * enters the main dispatch loop. * * The main event loop (event_loop()) checks the TCP socket for input and then * polls for x events. This should be fixed since you can just block on both * filedescriptors. * * The DoClient function receives a message (an ArgList), unpacks it, and in a * slow for loop dispatches the command to the right function through the * commands table. ArgLists are essentially like RPC things, only they don't * require going through RPCgen, and it's easy to get variable length lists. * They are just lists of longs, strings, characters, and byte arrays that can * be converted to a machine independent format */ #include "client.h" #include #include #include #ifdef HAVE_GIO_GNETWORKING_H #include #endif #include "external.h" #include "mapdata.h" #include "metaserver.h" #include "script.h" /* actually declare the globals */ char VERSION_INFO[MAX_BUF]; char *skill_names[MAX_SKILL]; char *sound_server = BINDIR "/cfsndserv"; const char *config_dir; const char *cache_dir; int last_used_skills[MAX_SKILL+1]; int want_skill_exp = 0, replyinfo_status = 0, requestinfo_sent = 0, replyinfo_last_face = 0, maxfd; /* Use the 'new' login method by default */ int wantloginmethod = 2; int serverloginmethod = 0; guint16 exp_table_max=0; guint64 *exp_table=NULL; NameMapping skill_mapping[MAX_SKILL], resist_mapping[NUM_RESISTS]; Client_Player cpl; ClientSocket csocket; static GInputStream *in; const char *const resists_name[NUM_RESISTS] = { "armor", "magic", "fire", "elec", "cold", "conf", "acid", "drain", "ghit", "pois", "slow", "para", "t undead", "fear", "depl","death", "hword", "blind" }; typedef void (*CmdProc)(unsigned char *, int len); /** * Links server commands to client functions that implement them, and gives a * rough indication of the type of data that the server supplies with the * command. */ struct CmdMapping { const char *cmdname; void (*cmdproc)(unsigned char *, int ); enum CmdFormat cmdformat; }; /** * The list of server commands that this client supports along with pointers * to the function that handles the command. The table also gives a rough * indication of the type of data that the server should send with each * command. If the client receives a command not listed in the table, a * complaint is output on stdout. */ struct CmdMapping commands[] = { /* * The order of this table does not make much of a difference. Related * commands are listed in groups. */ { "map2", Map2Cmd, SHORT_ARRAY }, { "map_scroll", (CmdProc)map_scrollCmd, ASCII }, { "magicmap", MagicMapCmd, MIXED /* ASCII, then binary */}, { "newmap", NewmapCmd, NODATA }, { "mapextended", MapExtendedCmd, MIXED /* chars, then SHORT_ARRAY */ }, { "item2", Item2Cmd, MIXED }, { "upditem", UpdateItemCmd, MIXED }, { "delitem", DeleteItem, INT_ARRAY }, { "delinv", DeleteInventory, ASCII }, { "addspell", AddspellCmd, MIXED }, { "updspell", UpdspellCmd, MIXED }, { "delspell", DeleteSpell, INT_ARRAY }, { "drawinfo", (CmdProc)DrawInfoCmd, ASCII }, { "drawextinfo", (CmdProc)DrawExtInfoCmd, ASCII}, { "stats", StatsCmd, STATS /* Array of: int8, (int?s for * that stat) */ }, { "image2", Image2Cmd, MIXED /* int, int8, int, PNG */ }, { "face2", Face2Cmd, MIXED /* int16, int8, int32, string */ }, { "tick", TickCmd, INT_ARRAY /* uint32 */}, { "music", (CmdProc)MusicCmd, ASCII }, { "sound2", Sound2Cmd, MIXED /* int8, int8, int8, int8, * int8, int8, chars, int8, * chars */ }, { "anim", AnimCmd, SHORT_ARRAY}, { "smooth", SmoothCmd, SHORT_ARRAY}, { "player", PlayerCmd, MIXED /* 3 ints, int8, str */ }, { "comc", CompleteCmd, SHORT_INT }, { "addme_failed", (CmdProc)AddMeFail, NODATA }, { "addme_success", (CmdProc)AddMeSuccess, NODATA }, { "version", (CmdProc)VersionCmd, ASCII }, { "goodbye", (CmdProc)GoodbyeCmd, NODATA }, { "setup", (CmdProc)SetupCmd, ASCII}, { "failure", (CmdProc)FailureCmd, ASCII}, { "accountplayers", (CmdProc)AccountPlayersCmd, ASCII}, { "query", (CmdProc)handle_query, ASCII}, { "replyinfo", ReplyInfoCmd, ASCII}, { "ExtendedTextSet", (CmdProc)SinkCmd, NODATA}, { "ExtendedInfoSet", (CmdProc)SinkCmd, NODATA}, { "pickup", PickupCmd, INT_ARRAY /* uint32 */}, }; /** * The number of entries in #commands. */ #define NCOMMANDS ((int)(sizeof(commands)/sizeof(struct CmdMapping))) GQuark client_error_quark(); void client_mapsize(int width, int height) { cs_print_string(csocket.fd, "setup mapsize %dx%d", width, height); } void client_disconnect() { LOG(LOG_DEBUG, "close_server_connection", "Closing server connection"); g_io_stream_close(G_IO_STREAM(csocket.fd), NULL, NULL); g_object_unref(csocket.fd); csocket.fd = NULL; } /** * Replace the non-printable characters in 'data' with a dot ('.') in a newly * allocated, NUL-terminated string. Caller must free the result. */ char *printable(void *data, int len) { char *buf = (char *)malloc(len+1); if (buf != NULL) { memcpy(buf, data, len); for (int i = 0; i < len; i++) { if (!isprint(buf[i])) { buf[i] = '.'; } else if (buf[i] == '\n' || buf[i] == '\r') { buf[i] = '\\'; } } buf[len] = '\0'; } return buf; } void client_run() { GError* err = NULL; SockList inbuf; inbuf.buf = g_malloc(MAXSOCKBUF); if (!SockList_ReadPacket(csocket.fd, &inbuf, MAXSOCKBUF - 1, &err)) { /* * If a socket error occurred while reading the packet, drop the * server connection. Is there a better way to handle this? */ if (!err) { LOG(LOG_ERROR, "client_run", "%s", err->message); g_error_free(err); } client_disconnect(); return; } if (inbuf.len == 0) { client_disconnect(); return; } /* * Null-terminate the buffer, and set the data pointer so it points * to the first character of the data (following the packet length). */ inbuf.buf[inbuf.len] = '\0'; unsigned char* data = inbuf.buf + 2; /* * Commands that provide data are always followed by a space. Find * the space and convert it to a null character. If no spaces are * found, the packet contains a command with no associatd data. */ while ((*data != ' ') && (*data != '\0')) { ++data; } int len; if (*data == ' ') { *data = '\0'; data++; len = inbuf.len - (data - inbuf.buf); } else { len = 0; } /* * Search for the command in the list of supported server commands. * If the server command is supported by the client, let the script * watcher know what command was received, then process it and quit * searching the command list. */ const char *cmdin = (char *)inbuf.buf + 2; if (debug_protocol) { char *data_print = printable(data, len); if (data_print != NULL) { LOG(LOG_INFO, "S->C", "len=%d cmd=%s |%s|", len, cmdin, data_print); free(data_print); } } int i; for(i = 0; i < NCOMMANDS; i++) { if (strcmp(cmdin, commands[i].cmdname) == 0) { script_watch(cmdin, data, len, commands[i].cmdformat); commands[i].cmdproc(data, len); break; } } /* * After processing the command, mark the socket input buffer empty. */ inbuf.len=0; /* * Complain about unsupported commands to facilitate troubleshooting. * The client and server should negotiate a connection such that the * server does not send commands the client does not support. */ if (i == NCOMMANDS) { LOG(LOG_ERROR, "client_run", "Unrecognized command from server (%s)\n", inbuf.buf + 2); error_dialog("Server error", "The server sent an unrecognized command. " "Crossfire Client will now disconnect." "\n\nIf this problem persists with a particular " "character, try playing another character, and without " "disconnecting, playing the problematic character again."); client_disconnect(); } g_free(inbuf.buf); } void client_connect(const char hostname[static 1]) { GSocketClient *sclient = g_socket_client_new(); // Store server hostname. if (csocket.servername != NULL) { g_free(csocket.servername); } csocket.servername = g_strdup(hostname); // Try to connect to server. csocket.fd = g_socket_client_connect_to_host( sclient, hostname, use_config[CONFIG_PORT], NULL, NULL); g_object_unref(sclient); if (csocket.fd == NULL) { return; } GSocket *socket = g_socket_connection_get_socket(csocket.fd); int i = 1, fd = g_socket_get_fd(socket); #ifndef WIN32 #ifdef HAVE_GIO_GNETWORKING_H if (use_config[CONFIG_FASTTCP]) { if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &i, sizeof(i)) == -1) { perror("TCP_NODELAY"); } } #endif #endif in = g_io_stream_get_input_stream(G_IO_STREAM(csocket.fd)); } bool client_is_connected() { return csocket.fd != NULL && g_socket_connection_is_connected(csocket.fd); } GSource *client_get_source() { return g_pollable_input_stream_create_source( G_POLLABLE_INPUT_STREAM(in), NULL); } void client_negotiate(int sound) { int tries; SendVersion(csocket); /* We need to get the version command fairly early on because we need to * know if the server will support a request to use png images. This * isn't done the best, because if the server never sends the version * command, we can loop here forever. However, if it doesn't send the * version command, we have no idea what we are dealing with. */ tries=0; while (csocket.cs_version==0) { client_run(); if (csocket.fd == NULL) { return; } usleep(10*1000); /* 10 milliseconds */ tries++; /* If we haven't got a response in 10 seconds, bail out */ if (tries > 1000) { LOG (LOG_ERROR,"common::negotiate_connection", "Connection timed out"); client_disconnect(); return; } } if (csocket.sc_version<1023) { LOG (LOG_WARNING,"common::negotiate_connection","Server does not support PNG images, yet that is all this client"); LOG (LOG_WARNING,"common::negotiate_connection","supports. Either the server needs to be upgraded, or you need to"); LOG (LOG_WARNING,"common::negotiate_connection","downgrade your client."); exit(1); } /* If the user has specified a numeric face id, use it. If it is a string * like base, then that resolves to 0, so no real harm in that. */ if (face_info.want_faceset) { face_info.faceset = atoi(face_info.want_faceset); } /* For sound, a value following determines which sound features are * wanted. The value is 1 for sound effects, and 2 for background music, * or the sum of 1 + 2 (3) for both. * * For spellmon, try each acceptable level, but make sure the one the * client prefers is last. */ cs_print_string(csocket.fd, "setup " "map2cmd 1 tick 1 sound2 %d darkness %d spellmon 1 spellmon 2 " "faceset %d facecache %d want_pickup 1 loginmethod %d newmapcmd 1 extendedTextInfos 1", (sound >= 0) ? 3 : 0, want_config[CONFIG_LIGHTING] ? 1 : 0, face_info.faceset, want_config[CONFIG_CACHE], wantloginmethod); /* * We can do this right now also. There is not any reason to wait. */ cs_print_string(csocket.fd, "requestinfo skill_info"); cs_print_string(csocket.fd,"requestinfo exp_table"); /* * While these are only used for new login method, they should become * standard fairly soon. All of these are pretty small, and do not add * much to the cost. They make it more likely that the information is * ready when the window that needs it is raised. */ cs_print_string(csocket.fd,"requestinfo motd"); cs_print_string(csocket.fd,"requestinfo news"); cs_print_string(csocket.fd,"requestinfo rules"); client_mapsize(want_config[CONFIG_MAPWIDTH], want_config[CONFIG_MAPHEIGHT]); use_config[CONFIG_SMOOTH]=want_config[CONFIG_SMOOTH]; /* If the server will answer the requestinfo for image_info and image_data, * send it and wait for the response. */ if (csocket.sc_version >= 1027) { /* last_start is -99. This means the first face requested will be 1 * (not 0) - this is OK because 0 is defined as the blank face. */ int last_end=0, last_start=-99; cs_print_string(csocket.fd,"requestinfo image_info"); requestinfo_sent = RI_IMAGE_INFO; replyinfo_status = 0; replyinfo_last_face = 0; do { client_run(); /* * It is rare, but the connection can die while getting this info. */ if (csocket.fd == NULL) { return; } if (use_config[CONFIG_DOWNLOAD]) { /* * We need to know how many faces to be able to make the * request intelligently. So only do the following block if * we have that info. By setting the sent flag, we will never * exit this loop until that happens. */ requestinfo_sent |= RI_IMAGE_SUMS; if (face_info.num_images != 0) { /* * Sort of fake things out - if we have sent the request * for image sums but have not got them all answered yet, * we then clear the bit from the status so we continue to * loop. */ if (last_end == face_info.num_images) { /* Mark that we're all done */ if (replyinfo_last_face == last_end) { replyinfo_status |= RI_IMAGE_SUMS; image_update_download_status(face_info.num_images, face_info.num_images, face_info.num_images); } } else { /* * If we are all caught up, request another 100 sums. */ if (last_end <= (replyinfo_last_face+100)) { last_start += 100; last_end += 100; if (last_end > face_info.num_images) { last_end = face_info.num_images; } cs_print_string(csocket.fd,"requestinfo image_sums %d %d", last_start, last_end); image_update_download_status(last_start, last_end, face_info.num_images); } } } /* Still have image_sums request to send */ } /* endif download all faces */ usleep(10*1000); /* 10 milliseconds */ /* * Do not put in an upper time limit with tries like we did above. * If the player is downloading all the images, the time this * takes could be considerable. */ } while (replyinfo_status != requestinfo_sent); } if (use_config[CONFIG_DOWNLOAD]) { char buf[MAX_BUF]; snprintf(buf, sizeof(buf), "Download of images complete. Found %d locally, downloaded %d from server\n", face_info.cache_hits, face_info.cache_misses); draw_ext_info(NDI_GOLD, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_CONFIG, buf); } /* This needs to get changed around - we really don't want to send the * SendAddMe until we do all of our negotiation, which may include things * like downloading all the images and whatnot - this is more an issue if * the user is not using the default face set, as in that case, we might * end up building images from the wrong set. * Only run this if not using new login method */ if (!serverloginmethod) { SendAddMe(csocket); } } crossfire-client-1.75.3/common/misc.c000644 001751 001751 00000010205 14045044337 020333 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Contains misc useful functions that may be useful to various parts of code, * but are not especially tied to it. */ #include "client.h" #include #ifndef WIN32 #include #else #include #include #endif GTimer* global_time; /** Log level, or the threshold below which messages are suppressed. */ LogLevel MINLOG = LOG_INFO; /** * Convert a buffer of a specified maximum size by replacing token characters * with a provided string. Given a buffered template string "/input/to/edit", * the maximum size of the buffer, a token '/', and a replacement string ":", * the input string is transformed to ":input:to:edit". If the replacement * string is empty, the token characters are simply removed. The template is * processed from left to right, replacing token characters as they are found. * Replacement strings are always inserted whole. If token replacement would * overflow the size of the conversion buffer, the token is not replaced, and * the remaining portion of the input string is appended after truncating it * as required to avoid overfilling the buffer. * @param buffer A string to perform a find and replace operation on. * @param buffer_size Allocated buffer size (used to avoid buffer overflow). * @param find A token character to find and replace in the buffer. * @param replace A string that is to replace each token in the buffer. */ void replace_chars_with_string(char* buffer, const guint16 buffer_size, const char find, const char* replace ) { guint16 buffer_len, expand, i, replace_len, replace_limit, template_len; char* template; replace_limit = buffer_size - 1; replace_len = strlen(replace); template_len = strlen(buffer); template = g_strdup(buffer); buffer[0] = '\0'; buffer_len = 0; for (i = 0; i <= template_len; i++) { expand = buffer_len + replace_len < replace_limit ? replace_len : 1; if (expand == 1 && buffer_len == replace_limit) { break; } if ((template[i] != find) || ((expand == 1) && (replace_len > 1))) { buffer[buffer_len++] = template[i]; buffer[buffer_len] = '\0'; } else { strcat(buffer, replace); buffer_len += replace_len; } } free(template); } /** * If any directories in the given path doesn't exist, they are created. */ int make_path_to_file(char *filename) { gchar *dirname = g_path_get_dirname(filename); int result = g_mkdir_with_parents(dirname, 0755); g_free(dirname); return result; } static const char *getLogLevelText(LogLevel level) { const char *LogLevelTexts[] = { "\x1b[34;1m" "DD" "\x1b[0m", "\x1b[32;1m" "II" "\x1b[0m", "\x1b[35;1m" "WW" "\x1b[0m", "\x1b[31;1m" "EE" "\x1b[0m", "\x1b[31;1m" "!!" "\x1b[0m", "\x1b[30;1m" "??" "\x1b[0m", }; return LogLevelTexts[level > LOG_CRITICAL ? LOG_CRITICAL + 1 : level]; } /** * Log messages of a certain importance to stderr. See 'client.h' for a full * list of possible log levels. */ void LOG(LogLevel level, const char *origin, const char *format, ...) { va_list ap; /* This buffer needs to be very big - larger than any other buffer. */ char buf[20480]; /* Don't log messages that the user doesn't want. */ if (level < MINLOG) { return; } va_start(ap, format); vsnprintf(buf, sizeof(buf), format, ap); if (strlen(buf) > 0) { fprintf(stderr, "[%s] %lf (%s) %s\n", getLogLevelText(level), g_timer_elapsed(global_time, NULL), origin, buf); } va_end(ap); } crossfire-client-1.75.3/common/external.h000644 001751 001751 00000010246 14045044333 021230 0ustar00kevinzkevinz000000 000000 /* * static char *rcsid_common_external_h = * "$Id$"; */ /* Crossfire client, a client program for the crossfire program. Copyright (C) 2001,2006 Mark Wedel & Crossfire Development Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file common/external.h * Contains external calls that the common area makes callbacks to. This was * really a quick hack done to allow some separation. Really, these should be * set via callbacks that the client can make to the library. Many of these * probably should never really be callbacks in any case, or be more general. */ /* Sound functions */ extern void SoundCmd(unsigned char *data, int len); extern void Sound2Cmd(unsigned char *data, int len); extern void MusicCmd(const char *data, int len); /* Map window related functions */ extern void resize_map_window(int x, int y); extern void display_map_addbelow(long x, long y, long face); extern void display_map_doneupdate(int redraw, int notice); extern int display_mapscroll(int dx, int dy); extern void draw_magic_map(void); /* Info related functions */ extern void draw_prompt(const char *str); extern void draw_ext_info(int orig_color, int type, int subtype, const char *message); extern void x_set_echo(void); extern void menu_clear(void); extern int get_info_width(void); /* Stats related commands */ extern void draw_stats(int redraw); extern void draw_message_window(int redraw); /* this should really just set a field in the stats, and let the * client figure the new weight limit out */ extern void set_weight_limit(guint32 wlim); /* Image related functions */ extern int display_willcache(void); extern int create_and_rescale_image_from_data(Cache_Entry *ce, int pixmap_num, guint8 *rgba_data, int width, int height); extern guint8 *png_to_data(guint8 *data, int len, guint32 *width, guint32 *height); extern int associate_cache_entry(Cache_Entry *ce, int pixnum); extern void image_update_download_status(int start, int end, int total); extern void get_map_image_size(int face, guint8 *w, guint8 *h); extern void addsmooth(guint16 face, guint16 smooth_face); /* Item related commands */ extern void open_container(item *op); extern void close_container(item *op); /* Keybinding relatated commands - this probably should not be a callback */ extern void bind_key(const char *params); extern void unbind_key(const char *params); extern void keybindings_init(const char *character_name); /* Misc commands */ extern void save_winpos(void); extern void save_defaults(void); extern void command_show(const char *params); extern void client_tick(guint32 tick); extern void client_pickup(guint32 pickup); /* Account Login Functions */ extern void start_login(int method); extern void show_main_client(void); extern void hide_all_login_windows(void); extern void account_login_failure(char *message); extern void account_creation_failure(char *message); extern void account_add_character_failure(char *message); extern void account_change_password_failure(char *message); extern void create_new_character_failure(char *message); extern void choose_character_init(void); extern void update_character_choose(const char *name, const char *class, const char *race, const char *face, const char *party, const char *map, int level, int faceno); extern void update_login_info(int type); /* Character Creation Functions */ extern void new_char_window_update_info(); extern void starting_map_update_info(); crossfire-client-1.75.3/common/shared/000755 001751 001751 00000000000 14605665664 020522 5ustar00kevinzkevinz000000 000000 crossfire-client-1.75.3/common/shared/newclient.h000644 001751 001751 00000066615 14110265004 022650 0ustar00kevinzkevinz000000 000000 /** * @file * Defines various flags that both the new client and new server use. These * should never be changed, only expanded. Changing them will likely cause all * old clients to not work properly. While called newclient, it is used by * both the client and server to keep some values the same. * * Name format is CS_(command)_(flag) * CS = Client/Server. * (command) is protocol command, ie ITEM * (flag) is the flag name */ #ifndef NEWCLIENT_H #define NEWCLIENT_H /** * Maximum size of a packet the client expects to get and that the server can * send. Using a buffer of this size allows the client to avoid constant * allocation and deallocation of the same buffer over and over again (at the * cost of using extra memory). This also makes the code simpler. The size * is big enough to receive any valid packet: 2 bytes for length, 65535 for * maximum packet size, 1 for a trailing null character. */ #define MAXSOCKBUF (2+65535+1) /** * How much the x,y coordinates in the map2 are off from actual upper left * corner. Necessary for light sources that may be off the edge of the * visible map. */ #define MAP2_COORD_OFFSET 15 /** * @defgroup MAP2_TYPE_xxx Type values present in map2 commands. * The different type values that may be present in a map2 command. These are * described in the protocol entry in more detail. These values are sent in * the bottom 5 bits of their byte, the top 3 are for the length of the data * that is sent. */ /*@{*/ #define MAP2_TYPE_CLEAR 0x0 #define MAP2_TYPE_DARKNESS 0x1 /* * These next two are not used presently, but the numbers are set aside for * when support is added. * * #define MAP2_TYPE_SOUND 0x2 * #define MAP2_TYPE_LIGHTSOURCE 0x3 */ /*@}*/ #define MAP2_LAYER_START 0x10 /** * Encodes a (x, y) pair suitable for map2 parameters. The coordinates must be * between [-MAP2_COORD_OFFSET..63-MAP2_COORD_OFFSET]. The flags value must be * between [0..15]. * * @param x the x-coordinate * @param y the y-coordinate * @param flags the flags value */ #define MAP2_COORD_ENCODE(x, y, flags) ((((x)+MAP2_COORD_OFFSET)&0x3f)<<10|(((y)+MAP2_COORD_OFFSET)&0x3f)<<4|(flags&0x0f)) #define CS_QUERY_YESNO 0x1 /**< Yes/no question. */ #define CS_QUERY_SINGLECHAR 0x2 /**< Single character response expected. */ #define CS_QUERY_HIDEINPUT 0x4 /**< Hide input being entered. */ #define CS_SAY_NORMAL 0x1 /**< Normal say command. */ #define CS_SAY_SHOUT 0x2 /**< Text is shouted. */ #define CS_SAY_GSAY 0x4 /**< Text is group say command. */ /** * @defgroup FLOAT_xxx FLOAT_xxx multipliers for changing floats to int. * and vice versa. */ /*@{*/ #define FLOAT_MULTI 100000 /**< Integer representation (float to int). */ #define FLOAT_MULTF 100000.0 /**< Float for going from int to float. */ /*@} FLOAT_xxx */ /** * @defgroup CS_STAT_xxx CS_STAT_xxx IDs for character statistics. */ /*@{*/ #define CS_STAT_HP 1 #define CS_STAT_MAXHP 2 #define CS_STAT_SP 3 #define CS_STAT_MAXSP 4 #define CS_STAT_STR 5 #define CS_STAT_INT 6 #define CS_STAT_WIS 7 #define CS_STAT_DEX 8 #define CS_STAT_CON 9 #define CS_STAT_CHA 10 #define CS_STAT_EXP 11 /**< No longer used */ #define CS_STAT_LEVEL 12 #define CS_STAT_WC 13 #define CS_STAT_AC 14 #define CS_STAT_DAM 15 #define CS_STAT_ARMOUR 16 #define CS_STAT_SPEED 17 #define CS_STAT_FOOD 18 #define CS_STAT_WEAP_SP 19 #define CS_STAT_RANGE 20 #define CS_STAT_TITLE 21 #define CS_STAT_POW 22 #define CS_STAT_GRACE 23 #define CS_STAT_MAXGRACE 24 #define CS_STAT_FLAGS 25 #define CS_STAT_WEIGHT_LIM 26 #define CS_STAT_EXP64 28 #define CS_STAT_SPELL_ATTUNE 29 #define CS_STAT_SPELL_REPEL 30 #define CS_STAT_SPELL_DENY 31 #define CS_STAT_RACE_STR 32 #define CS_STAT_RACE_INT 33 #define CS_STAT_RACE_WIS 34 #define CS_STAT_RACE_DEX 35 #define CS_STAT_RACE_CON 36 #define CS_STAT_RACE_CHA 37 #define CS_STAT_RACE_POW 38 #define CS_STAT_BASE_STR 39 #define CS_STAT_BASE_INT 40 #define CS_STAT_BASE_WIS 41 #define CS_STAT_BASE_DEX 42 #define CS_STAT_BASE_CON 43 #define CS_STAT_BASE_CHA 44 #define CS_STAT_BASE_POW 45 #define CS_STAT_APPLIED_STR 46 /**< STR changes from gear or skills. */ #define CS_STAT_APPLIED_INT 47 /**< INT changes from gear or skills. */ #define CS_STAT_APPLIED_WIS 48 /**< WIS changes from gear or skills. */ #define CS_STAT_APPLIED_DEX 49 /**< DEX changes from gear or skills. */ #define CS_STAT_APPLIED_CON 50 /**< CON changes from gear or skills. */ #define CS_STAT_APPLIED_CHA 51 /**< CHA changes from gear or skills. */ #define CS_STAT_APPLIED_POW 52 /**< POW changes from gear or skills. */ #define CS_STAT_GOLEM_HP 53 /**< Golem's current hp, 0 if no golem. */ #define CS_STAT_GOLEM_MAXHP 54 /**< Golem's max hp, 0 if no golem. */ #define CS_STAT_RESIST_START 100 /**< Start of resistances (inclusive) */ #define CS_STAT_RESIST_END 117 /**< End of resistances (inclusive) */ #define CS_STAT_RES_PHYS 100 #define CS_STAT_RES_MAG 101 #define CS_STAT_RES_FIRE 102 #define CS_STAT_RES_ELEC 103 #define CS_STAT_RES_COLD 104 #define CS_STAT_RES_CONF 105 #define CS_STAT_RES_ACID 106 #define CS_STAT_RES_DRAIN 107 #define CS_STAT_RES_GHOSTHIT 108 #define CS_STAT_RES_POISON 109 #define CS_STAT_RES_SLOW 110 #define CS_STAT_RES_PARA 111 #define CS_STAT_TURN_UNDEAD 112 #define CS_STAT_RES_FEAR 113 #define CS_STAT_RES_DEPLETE 114 #define CS_STAT_RES_DEATH 115 #define CS_STAT_RES_HOLYWORD 116 #define CS_STAT_RES_BLIND 117 /** * CS_STAT_SKILLINFO is used as the starting index point. Skill number->name * map is generated dynamically for the client, so a bunch of entries will be * used here. */ #define CS_STAT_SKILLINFO 140 /** * CS_NUM_SKILLS does not match how many skills there really are - instead, it * is used as a range of values so that the client can have some idea how many * skill categories there may be. */ #define CS_NUM_SKILLS 50 /*@}*/ /** * @defgroup SF_xxx SF_xxx Masks used in conjunction with fire and run states. * * These values are used with CS_STAT_FLAGS above to communicate S->C what the * server thinks the fireon & runon states are. */ /*@{*/ #define SF_FIREON 0x01 #define SF_RUNON 0x02 /*@}*/ /** * @defgroup ACL_xxx ACL_xxx field IDs that support account login. * * These values are used for the account login code to denote what field * follows. ACL = Account Character Login */ /*@{*/ #define ACL_NAME 1 #define ACL_CLASS 2 #define ACL_RACE 3 #define ACL_LEVEL 4 #define ACL_FACE 5 #define ACL_PARTY 6 #define ACL_MAP 7 #define ACL_FACE_NUM 8 /*@}*/ /** * @defgroup NDI_xxx NDI_xxx message color flags and masks. * * The following are the color flags passed to new_draw_info(). * * We also set up some control flags * * NDI = New Draw Info * * Color specifications - note these match the order in xutil.c. * * Note 2: Black, the default color, is 0. Thus, it does not need to * be implicitly specified. */ /*@{*/ #define NDI_BLACK 0 #define NDI_WHITE 1 #define NDI_NAVY 2 #define NDI_RED 3 #define NDI_ORANGE 4 #define NDI_BLUE 5 /**< Actually, it is Dodger Blue */ #define NDI_DK_ORANGE 6 /**< DarkOrange2 */ #define NDI_GREEN 7 /**< SeaGreen */ #define NDI_LT_GREEN 8 /**< DarkSeaGreen, which is actually paler * than seagreen - also background color. */ #define NDI_GREY 9 #define NDI_BROWN 10 /**< Sienna. */ #define NDI_GOLD 11 #define NDI_TAN 12 /**< Khaki. */ #define NDI_MAX_COLOR 12 /**< Last value in. */ #define NDI_COLOR_MASK 0xff /**< Gives lots of room for expansion - we are * using an int anyways, so we have the * space to still do all the flags. */ #define NDI_UNIQUE 0x100 /**< Print immediately, don't buffer. */ #define NDI_ALL 0x200 /**< Inform all players of this message. */ #define NDI_ALL_DMS 0x400 /**< Inform all logged in DMs. Used in case of * errors. Overrides NDI_ALL. */ /*@}*/ /** * @defgroup F_xxx F_xxx flags for the item command. */ /*@{*/ enum {a_none, a_readied, a_wielded, a_worn, a_active, a_applied}; #define F_APPLIED 0x000F #define F_UNIDENTIFIED 0x0010 #define F_UNPAID 0x0200 #define F_MAGIC 0x0400 #define F_CURSED 0x0800 #define F_DAMNED 0x1000 #define F_OPEN 0x2000 #define F_NOPICK 0x4000 #define F_LOCKED 0x8000 #define F_BLESSED 0x0100 #define F_READ 0x0020 /*@}*/ /** * @defgroup FACE_xxx FACE_xxx magic map masks. * * Used in the new_face structure on the magicmap field. Low bits are color * information. For now, only high bit information we need is for the floor. */ /*@{*/ #define FACE_FLOOR 0x80 #define FACE_WALL 0x40 /**< Or'd into the color value by the server * right before sending. */ #define FACE_COLOR_MASK 0xf /*@}*/ /** * @defgroup UPD_xxx UPD_xxx UpdSpell constants. * */ /*@{*/ #define UPD_LOCATION 0x01 #define UPD_FLAGS 0x02 #define UPD_WEIGHT 0x04 #define UPD_FACE 0x08 #define UPD_NAME 0x10 #define UPD_ANIM 0x20 #define UPD_ANIMSPEED 0x40 #define UPD_NROF 0x80 #define UPD_ALL 0xFF #define UPD_SP_MANA 0x01 /**< updspell command flag value. */ #define UPD_SP_GRACE 0x02 /**< updspell command flag value. */ #define UPD_SP_DAMAGE 0x04 /**< updspell command flag value. */ /*@}*/ /** * @defgroup Soundtypes Sound types */ /*@{*/ #define SOUND_TYPE_LIVING 1 #define SOUND_TYPE_SPELL 2 #define SOUND_TYPE_ITEM 3 #define SOUND_TYPE_GROUND 4 #define SOUND_TYPE_HIT 5 #define SOUND_TYPE_HIT_BY 6 /*@}*/ /** * @defgroup ANIM_xxx Animation constants. * */ /*@{*/ #define FACE_IS_ANIM 1<<15 #define ANIM_RANDOM 1<<13 #define ANIM_SYNC 2<<13 #define ANIM_FLAGS_MASK 0x6000 /**< Used only by the client. */ /** * AND'ing this with data from server gets us just the animation id. Used * only by the client. */ #define ANIM_MASK 0x1fff /*@}*/ /** * @defgroup EMI_xxx EMI_xxx extended map constants. * * Even if the client select the additionnal infos it wants on the map, there * may exist cases where this whole info is not given in one bunch but in * separate bunches. This is done performance reasons (imagine some info * related to a visible object and another info related to a 4 square width * and height area). At the begin of an extended info packet is a bit field. A * bit is activated for each extended information present in the data. */ /*@{*/ /**< Take extended information into account but do not redraw. Some * additional data will follow in a new packet. */ #define EMI_NOREDRAW 0x01 /** * Data about smoothing. */ #define EMI_SMOOTH 0x02 /** * Indicates the bitfield continue un next byte There may be several on * contiguous bytes. So there is 7 actual bits used per byte, and the number * of bytes is not fixed in protocol */ #define EMI_HASMOREBITS 0x80 /*@}*/ /* * Note! * When adding message types, don't forget to keep the client up to date too! */ /** * @defgroup MSG_TYPE_xxx MSG_TYPE_xxx message types */ /*@{*/ #define MSG_TYPE_BOOK 1 #define MSG_TYPE_CARD 2 #define MSG_TYPE_PAPER 3 #define MSG_TYPE_SIGN 4 #define MSG_TYPE_MONUMENT 5 #define MSG_TYPE_DIALOG 6 /**< NPCs, magic mouths, and altars */ #define MSG_TYPE_MOTD 7 #define MSG_TYPE_ADMIN 8 #define MSG_TYPE_SHOP 9 #define MSG_TYPE_COMMAND 10 /**< Responses to commands, eg, who */ #define MSG_TYPE_ATTRIBUTE 11 /**< Changes to attributes (stats, * resistances, etc) */ #define MSG_TYPE_SKILL 12 /**< Messages related to skill use. */ #define MSG_TYPE_APPLY 13 /**< Applying objects */ #define MSG_TYPE_ATTACK 14 /**< Attack related messages */ #define MSG_TYPE_COMMUNICATION 15 /**< Communication between players */ #define MSG_TYPE_SPELL 16 /**< Spell related info */ #define MSG_TYPE_ITEM 17 /**< Item related information */ #define MSG_TYPE_MISC 18 /**< Messages that don't go * elsewhere */ #define MSG_TYPE_VICTIM 19 /**< Something bad is happening to * the player. */ #define MSG_TYPE_CLIENT 20 /**< Client originated Messages */ #define MSG_TYPE_LAST 21 #define MSG_SUBTYPE_NONE 0 /* book messages subtypes */ #define MSG_TYPE_BOOK_CLASP_1 1 #define MSG_TYPE_BOOK_CLASP_2 2 #define MSG_TYPE_BOOK_ELEGANT_1 3 #define MSG_TYPE_BOOK_ELEGANT_2 4 #define MSG_TYPE_BOOK_QUARTO_1 5 #define MSG_TYPE_BOOK_QUARTO_2 6 #define MSG_TYPE_BOOK_SPELL_EVOKER 7 #define MSG_TYPE_BOOK_SPELL_PRAYER 8 #define MSG_TYPE_BOOK_SPELL_PYRO 9 #define MSG_TYPE_BOOK_SPELL_SORCERER 10 #define MSG_TYPE_BOOK_SPELL_SUMMONER 11 /* card messages subtypes*/ #define MSG_TYPE_CARD_SIMPLE_1 1 #define MSG_TYPE_CARD_SIMPLE_2 2 #define MSG_TYPE_CARD_SIMPLE_3 3 #define MSG_TYPE_CARD_ELEGANT_1 4 #define MSG_TYPE_CARD_ELEGANT_2 5 #define MSG_TYPE_CARD_ELEGANT_3 6 #define MSG_TYPE_CARD_STRANGE_1 7 #define MSG_TYPE_CARD_STRANGE_2 8 #define MSG_TYPE_CARD_STRANGE_3 9 #define MSG_TYPE_CARD_MONEY_1 10 #define MSG_TYPE_CARD_MONEY_2 11 #define MSG_TYPE_CARD_MONEY_3 12 /* Paper messages subtypes */ #define MSG_TYPE_PAPER_NOTE_1 1 #define MSG_TYPE_PAPER_NOTE_2 2 #define MSG_TYPE_PAPER_NOTE_3 3 #define MSG_TYPE_PAPER_LETTER_OLD_1 4 #define MSG_TYPE_PAPER_LETTER_OLD_2 5 #define MSG_TYPE_PAPER_LETTER_NEW_1 6 #define MSG_TYPE_PAPER_LETTER_NEW_2 7 #define MSG_TYPE_PAPER_ENVELOPE_1 8 #define MSG_TYPE_PAPER_ENVELOPE_2 9 #define MSG_TYPE_PAPER_SCROLL_OLD_1 10 #define MSG_TYPE_PAPER_SCROLL_OLD_2 11 #define MSG_TYPE_PAPER_SCROLL_NEW_1 12 #define MSG_TYPE_PAPER_SCROLL_NEW_2 13 #define MSG_TYPE_PAPER_SCROLL_MAGIC 14 /* road signs messages subtypes */ /* Including magic mouths */ #define MSG_TYPE_SIGN_BASIC 1 #define MSG_TYPE_SIGN_DIR_LEFT 2 #define MSG_TYPE_SIGN_DIR_RIGHT 3 #define MSG_TYPE_SIGN_DIR_BOTH 4 #define MSG_TYPE_SIGN_MAGIC_MOUTH 5 /* stones and monument messages */ #define MSG_TYPE_MONUMENT_STONE_1 1 #define MSG_TYPE_MONUMENT_STONE_2 2 #define MSG_TYPE_MONUMENT_STONE_3 3 #define MSG_TYPE_MONUMENT_STATUE_1 4 #define MSG_TYPE_MONUMENT_STATUE_2 5 #define MSG_TYPE_MONUMENT_STATUE_3 6 #define MSG_TYPE_MONUMENT_GRAVESTONE_1 7 #define MSG_TYPE_MONUMENT_GRAVESTONE_2 8 #define MSG_TYPE_MONUMENT_GRAVESTONE_3 9 #define MSG_TYPE_MONUMENT_WALL_1 10 #define MSG_TYPE_MONUMENT_WALL_2 11 #define MSG_TYPE_MONUMENT_WALL_3 12 /* dialog message */ #define MSG_TYPE_DIALOG_NPC 1 /**< A message from the npc */ #define MSG_TYPE_DIALOG_ALTAR 2 /**< A message from an altar */ #define MSG_TYPE_DIALOG_MAGIC_EAR 3 /**< Magic ear */ /* MOTD doesn't have any subtypes */ /* admin/global messages */ #define MSG_TYPE_ADMIN_RULES 1 #define MSG_TYPE_ADMIN_NEWS 2 #define MSG_TYPE_ADMIN_PLAYER 3 /**< Player coming/going/death */ #define MSG_TYPE_ADMIN_DM 4 /**< DM related admin actions */ #define MSG_TYPE_ADMIN_HISCORE 5 /**< Hiscore list */ #define MSG_TYPE_ADMIN_LOADSAVE 6 /**< load/save operations */ #define MSG_TYPE_ADMIN_LOGIN 7 /**< login messages/errors */ #define MSG_TYPE_ADMIN_VERSION 8 /**< version info */ #define MSG_TYPE_ADMIN_ERROR 9 /**< Error on command, setup, etc */ /* * I'm not actually expecting anything to make much use of the MSG_TYPE_SHOP * values However, to use the media tags, need to use draw_ext_info, and need * to have a type/subtype, so figured might as well put in real values here. */ #define MSG_TYPE_SHOP_LISTING 1 /**< Shop listings - inventory, * what it deals in. */ #define MSG_TYPE_SHOP_PAYMENT 2 /**< Messages about payment, lack * of funds. */ #define MSG_TYPE_SHOP_SELL 3 /**< Messages about selling items */ #define MSG_TYPE_SHOP_MISC 4 /**< Random messages */ /* * Basically, 1 subtype/command. Like shops, not expecting much to be done, * but by having different subtypes, it makes it easier for client to store * way information (eg, who output) */ #define MSG_TYPE_COMMAND_WHO 1 #define MSG_TYPE_COMMAND_MAPS 2 #define MSG_TYPE_COMMAND_BODY 3 #define MSG_TYPE_COMMAND_MALLOC 4 #define MSG_TYPE_COMMAND_WEATHER 5 #define MSG_TYPE_COMMAND_STATISTICS 6 #define MSG_TYPE_COMMAND_CONFIG 7 /**< bowmode, petmode, applymode */ #define MSG_TYPE_COMMAND_INFO 8 /**< Generic info: resistances, etc */ #define MSG_TYPE_COMMAND_QUESTS 9 /**< Quest info */ #define MSG_TYPE_COMMAND_DEBUG 10 /**< Various debug type commands */ #define MSG_TYPE_COMMAND_ERROR 11 /**< Bad syntax/can't use command */ #define MSG_TYPE_COMMAND_SUCCESS 12 /**< Successful result from command */ #define MSG_TYPE_COMMAND_FAILURE 13 /**< Failed result from command */ #define MSG_TYPE_COMMAND_EXAMINE 14 /**< Player examining something */ #define MSG_TYPE_COMMAND_INVENTORY 15 /**< Inventory listing */ #define MSG_TYPE_COMMAND_HELP 16 /**< Help related information */ #define MSG_TYPE_COMMAND_DM 17 /**< DM related commands */ #define MSG_TYPE_COMMAND_NEWPLAYER 18 /**< Create a new character - not * really a command, but is * responding to player input */ /* This is somewhat verbose. If the client ends up being able to * choose various attributes based on message type, I think it is important * for the client to know if this is a benefit or detriment to the player. * In the case of losing a bonus, this typically indicates a spell has * ended, which is probably more important (and should be displayed more * prominently) than when you cast the spell */ #define MSG_TYPE_ATTRIBUTE_ATTACKTYPE_GAIN 1 /**< Atacktypes here refer to */ #define MSG_TYPE_ATTRIBUTE_ATTACKTYPE_LOSS 2 /**< the player gaining or * losing these attacktypes * not being a victim of an * attacktype. */ #define MSG_TYPE_ATTRIBUTE_PROTECTION_GAIN 3 /**< Protections in this */ #define MSG_TYPE_ATTRIBUTE_PROTECTION_LOSS 4 /**< context are pretty * generic - things like * reflection or lifesave * are also under the * protection category. */ #define MSG_TYPE_ATTRIBUTE_MOVE 5 /**< A change in the movement * type of the player. */ #define MSG_TYPE_ATTRIBUTE_RACE 6 /**< Race-related changes. */ #define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_START 7 /**< Start of a bad effect * to the player. */ #define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_END 8 /**< End of a bad effect. */ #define MSG_TYPE_ATTRIBUTE_STAT_GAIN 9 #define MSG_TYPE_ATTRIBUTE_STAT_LOSS 10 #define MSG_TYPE_ATTRIBUTE_LEVEL_GAIN 11 #define MSG_TYPE_ATTRIBUTE_LEVEL_LOSS 12 #define MSG_TYPE_ATTRIBUTE_GOOD_EFFECT_START 13 /**< Start of a good effect to * the player. */ #define MSG_TYPE_ATTRIBUTE_GOOD_EFFECT_END 14 /**< End of a good effect. */ #define MSG_TYPE_ATTRIBUTE_GOD 15 /**< changing god info */ /* I think one type/skill is overkill, so instead, use broader categories * for these messages. * The difference in ERROR vs FAILURE is basically this: ERROR indicates * something wasn't right to even attempt to use the skill (don't have * needed object, or haven't marked objects, etc). * FAILURE indicates that player attempted to use the skill, but it * didn't work. * PRAY is listed out because praying over altars can generate some * messages not really related to the skill itself. */ #define MSG_TYPE_SKILL_MISSING 1 /**< Don't have the skill */ #define MSG_TYPE_SKILL_ERROR 2 /**< Doing something wrong */ #define MSG_TYPE_SKILL_SUCCESS 3 /**< Successfully used skill */ #define MSG_TYPE_SKILL_FAILURE 4 /**< Failure in using skill */ #define MSG_TYPE_SKILL_PRAY 5 /**< Praying related messages */ #define MSG_TYPE_SKILL_LIST 6 /**< List of skills */ /* Messages related to applying objects. Note that applying many objects may * generate MSG_TYPE_ATTRIBUTE messages - the APPLY here more directly related * to the direct messages related to applying them (you put on your armor, you * apply scroll, etc). The ERROR is like that for SKILLS - something prevent * even trying to apply the object. FAILURE indicates result wasn't * successful. */ #define MSG_TYPE_APPLY_ERROR 1 #define MSG_TYPE_APPLY_UNAPPLY 2 /**< Unapply an object */ #define MSG_TYPE_APPLY_SUCCESS 3 /**< Was able to apply object */ #define MSG_TYPE_APPLY_FAILURE 4 /**< Apply OK, but no/bad result */ #define MSG_TYPE_APPLY_CURSED 5 /**< Applied a cursed object (BAD) */ #define MSG_TYPE_APPLY_TRAP 6 /**< Have activated a trap */ #define MSG_TYPE_APPLY_BADBODY 7 /**< Don't have body to use object */ #define MSG_TYPE_APPLY_PROHIBITION 8 /**< Class/god prohibiiton on obj */ #define MSG_TYPE_APPLY_BUILD 9 /**< Build related actions */ /* attack related messages */ #define MSG_TYPE_ATTACK_DID_HIT 1 /**< Player hit something else */ #define MSG_TYPE_ATTACK_PET_HIT 2 /**< Players pet hit something else */ #define MSG_TYPE_ATTACK_FUMBLE 3 /**< Player fumbled attack */ #define MSG_TYPE_ATTACK_DID_KILL 4 /**< Player killed something */ #define MSG_TYPE_ATTACK_PET_DIED 5 /**< Pet was killed */ #define MSG_TYPE_ATTACK_NOKEY 6 /**< Keys are like attacks, so... */ #define MSG_TYPE_ATTACK_NOATTACK 7 /**< You avoid attacking */ #define MSG_TYPE_ATTACK_PUSHED 8 /**< Pushed a friendly player */ #define MSG_TYPE_ATTACK_MISS 9 /**< attack didn't hit */ #define MSG_TYPE_COMMUNICATION_RANDOM 1 /**< Random event (coin toss) */ #define MSG_TYPE_COMMUNICATION_SAY 2 /**< Player says something */ #define MSG_TYPE_COMMUNICATION_ME 3 /**< Player me's a message */ #define MSG_TYPE_COMMUNICATION_TELL 4 /**< Player tells something */ #define MSG_TYPE_COMMUNICATION_EMOTE 5 /**< Player emotes */ #define MSG_TYPE_COMMUNICATION_PARTY 6 /**< Party message */ #define MSG_TYPE_COMMUNICATION_SHOUT 7 /**< Party message */ #define MSG_TYPE_COMMUNICATION_CHAT 8 /**< Party message */ #define MSG_TYPE_SPELL_HEAL 1 /**< Healing related spells */ #define MSG_TYPE_SPELL_PET 2 /**< Pet related messages */ #define MSG_TYPE_SPELL_FAILURE 3 /**< Spell failure messages */ #define MSG_TYPE_SPELL_END 4 /**< A spell ends */ #define MSG_TYPE_SPELL_SUCCESS 5 /**< Spell succeeded messages */ #define MSG_TYPE_SPELL_ERROR 6 /**< Spell failure messages */ #define MSG_TYPE_SPELL_PERCEIVE_SELF 7 /**< Perceive self messages */ #define MSG_TYPE_SPELL_TARGET 8 /**< Target of non attack spell */ #define MSG_TYPE_SPELL_INFO 9 /**< random info about spell, not * related to failure/success */ #define MSG_TYPE_ITEM_REMOVE 1 /**< Item removed from inv */ #define MSG_TYPE_ITEM_ADD 2 /**< Item added to inventory */ #define MSG_TYPE_ITEM_CHANGE 3 /**< Item has changed in some way */ #define MSG_TYPE_ITEM_INFO 4 /**< Information related to items */ /* * MSG_TYPE_MISC, by its very nature, doesn't really have subtypes. It is * used for messages that really don't belong anyplace else */ #define MSG_TYPE_VICTIM_SWAMP 1 /**< Player is sinking in a swamp */ #define MSG_TYPE_VICTIM_WAS_HIT 2 /**< Player was hit by something */ #define MSG_TYPE_VICTIM_STEAL 3 /**< Someone tried to steal from * the player */ #define MSG_TYPE_VICTIM_SPELL 4 /**< Someone cast a bad spell on * the player */ #define MSG_TYPE_VICTIM_DIED 5 /**< Player died! */ #define MSG_TYPE_VICTIM_WAS_PUSHED 6 /**< Player was pushed or attempted * pushed */ #define MSG_TYPE_CLIENT_CONFIG 1 /**< Local configuration issues */ #define MSG_TYPE_CLIENT_SERVER 2 /**< Server configuration issues */ #define MSG_TYPE_CLIENT_COMMAND 3 /**< DrawInfoCmd() */ #define MSG_TYPE_CLIENT_QUERY 4 /**< handle_query() and prompts */ #define MSG_TYPE_CLIENT_DEBUG 5 /**< General debug messages */ #define MSG_TYPE_CLIENT_NOTICE 6 /**< Non-critical note to player */ #define MSG_TYPE_CLIENT_METASERVER 7 /**< Metaserver messages */ #define MSG_TYPE_CLIENT_SCRIPT 8 /**< Script related messages */ #define MSG_TYPE_CLIENT_ERROR 9 /**< Bad things happening */ /*@}*/ /** * Definitions for the requestion/replyinfo map data. */ #define INFO_MAP_ARCH_NAME 1 /**< Archetype name of this entry */ #define INFO_MAP_NAME 2 /**< Proper name of this entry */ #define INFO_MAP_DESCRIPTION 3 /**< Description of this map */ /** * Contains the base information we use to make up a packet we want to send. */ typedef struct SockList { #ifdef CLIENT_TYPES_H /* Used by the client */ int len; unsigned char *buf; #else /* Used by the server */ size_t len; unsigned char buf[MAXSOCKBUF]; /* 2(size)+65535(content)+1(ending NULL) */ #endif } SockList; /** * Statistics on server. */ typedef struct CS_Stats { int ibytes; /**< ibytes, obytes are bytes in, out. */ int obytes; short max_conn; /**< Maximum connections received. */ time_t time_start; /**< When we started logging this. */ } CS_Stats; extern CS_Stats cst_tot, cst_lst; #endif /* NEWCLIENT_H */ crossfire-client-1.75.3/common/shared/README000644 001751 001751 00000000414 14045044323 021356 0ustar00kevinzkevinz000000 000000 IMPORTANT MAINTENANCE INFORMATION The files in this directory (particularly "newclient.h") are shared between the client and server. Changes should be made to the server's copy of the files, located in "server/include/shared" and then copied to the client directory. crossfire-client-1.75.3/common/player.c000644 001751 001751 00000025306 14323707640 020706 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Handles various player related functions. This includes both things that * operate on the player item, cpl structure, or various commands that the * player issues. * * Most of the handling of commands from the client to server (see commands.c * for server->client) is handled here. * * Most of the work for sending messages to the server is done here. Again, * most of these appear self explanatory. Most send a bunch of commands like * apply, examine, fire, run, etc. This looks like it was done by Mark to * remove the old keypress stupidity I used. */ #include #include "client.h" #include "external.h" #include "script.h" #include "mapdata.h" bool profile_latency = false; int64_t *profile_time = NULL; /** 256-length array to keep track of when commands were sent to the server */ /** Array for direction strings for each numeric direction. */ const char *const directions[] = {"stay", "north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest"}; /** Best guess whether or not we are currently AFK or not. */ bool is_afk; /** Time when last command was sent. Used to keep track of auto-AFK. */ time_t last_command_sent; /** * Initialize player object using information from the server. */ void new_player(long tag, char *name, long weight, long face) { Spell *spell, *spnext; cpl.ob->tag = tag; cpl.ob->nrof = 1; copy_name(cpl.ob->d_name, name); /* Right after player exit server will send this with empty name. */ if (strlen(name) != 0) { keybindings_init(name); } cpl.ob->weight = (float)weight / 1000; cpl.ob->face = face; if (cpl.spelldata) { for (spell = cpl.spelldata; spell; spell = spnext) { spnext = spell->next; free(spell); } cpl.spelldata = NULL; } // Reset auto-AFK data. is_afk = false; last_command_sent = time(NULL); } void look_at(int x, int y) { cs_print_string(csocket.fd, "lookat %d %d", x, y); } void client_send_apply(int tag) { cs_print_string(csocket.fd, "apply %d", tag); } void client_send_examine(int tag) { cs_print_string(csocket.fd, "examine %d", tag); } /** * Request to move 'nrof' objects with 'tag' to 'loc'. */ void client_send_move(int loc, int tag, int nrof) { cs_print_string(csocket.fd, "move %d %d %d", loc, tag, nrof); } /* Fire & Run code. The server handles repeating of these actions, so * we only need to send a run or fire command for a particular direction * once - we use the drun and dfire to keep track if we need to send * the full command. */ static int drun=-1, dfire=-1; void stop_fire() { if (cpl.input_state != Playing) { return; } dfire |= 0x100; } void clear_fire() { if (dfire != -1) { send_command("fire_stop", -1, SC_FIRERUN); dfire = -1; } } void clear_run() { if (drun != -1) { send_command("run_stop", -1, SC_FIRERUN); drun = -1; } } void fire_dir(int dir) { if (cpl.input_state != Playing) { return; } if (dir != dfire) { char buf[MAX_BUF]; snprintf(buf, sizeof(buf), "fire %d", dir); if (send_command(buf, cpl.count, SC_NORMAL)) { dfire = dir; cpl.count = 0; } } else { dfire &= 0xff; /* Mark it so that we need a stop_fire */ } } void stop_run() { send_command("run_stop", -1, SC_FIRERUN); drun |= 0x100; } void run_dir(int dir) { if (dir != drun) { char buf[MAX_BUF]; snprintf(buf, sizeof(buf), "run %d", dir); if (send_command(buf, -1, SC_NORMAL)) { drun = dir; } } else { drun &= 0xff; } } extern const char *const directions[]; int command_to_direction(const char *dir) { for (int i = 0; i < 9; i++) { if (!strcmp(dir, directions[i])) { return i; } } return -1; } const char* dir_to_command(int dir) { return directions[dir]; } void walk_dir(int dir) { send_command(dir_to_command(dir), -1, SC_MOVETO); } /** * Change map drawing offset to provide local movement prediction based on * player's movement commands to the server. */ void predict_scroll(int dir) { switch (dir%8) { case 0: want_offset_x += 1; want_offset_y += 1; break; case 1: want_offset_x += 0; want_offset_y += 1; break; case 2: want_offset_x += -1; want_offset_y += 1; break; case 3: want_offset_x += -1; want_offset_y += 0; break; case 4: want_offset_x += -1; want_offset_y += -1; break; case 5: want_offset_x += 0; want_offset_y += -1; break; case 6: want_offset_x += 1; want_offset_y += -1; break; case 7: want_offset_x += 1; want_offset_y += 0; break; } } static bool starts_with(const char *prefix, const char *str) { return strncmp(prefix, str, strlen(prefix)) == 0; } /* This should be used for all 'command' processing. Other functions should * call this so that proper windowing will be done. * command is the text command, repeat is a count value, or -1 if none * is desired and we don't want to reset the current count. * must_send means we must send this command no matter what (ie, it is * an administrative type of command like fire_stop, and failure to send * it will cause definate problems * return 1 if command was sent, 0 if not sent. */ int send_command(const char *command, int repeat, int must_send) { static char last_command[MAX_BUF]=""; script_monitor(command,repeat,must_send); if (cpl.input_state==Reply_One) { LOG(LOG_ERROR,"common::send_command","Wont send command '%s' - since in reply mode!", command); cpl.count=0; return 0; } if (use_config[CONFIG_ECHO]) { draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, command); } if (starts_with("afk", command)) { is_afk = !is_afk; } last_command_sent = time(NULL); /* Does the server understand 'ncom'? If so, special code */ if (csocket.cs_version >= 1021) { int commdiff=csocket.command_sent - csocket.command_received; if (commdiff<0) { commdiff +=256; } /* if too many unanswered commands, not a must send, and command is * the same, drop it */ if (commdiff>use_config[CONFIG_CWINDOW] && !must_send && !strcmp(command, last_command)) { if (repeat!=-1) { cpl.count=0; } return 0; #if 0 /* Obnoxious warning message we don't need */ fprintf(stderr,"Wont send command %s - window oversized %d %d\n", command, csocket.command_sent, csocket.command_received); #endif } else { SockList sl; guint8 buf[MAX_BUF]; /* Don't want to copy in administrative commands */ if (!must_send) { strcpy(last_command, command); } csocket.command_sent++; csocket.command_sent %= COMMAND_MAX; SockList_Init(&sl, buf); SockList_AddString(&sl, "ncom "); SockList_AddShort(&sl, csocket.command_sent); SockList_AddInt(&sl, repeat); SockList_AddString(&sl, command); SockList_Send(&sl, csocket.fd); if (profile_latency) { if (profile_time == NULL) { profile_time = calloc(256, sizeof(int64_t)); } profile_time[csocket.command_sent] = g_get_monotonic_time(); printf("profile/com\t%d\t%s\n", csocket.command_sent, command); } int dir = command_to_direction(command); csocket.dir[csocket.command_sent] = dir; if (drun == -1 && dir != -1) { // If movement command, predict scroll. predict_scroll(dir); if (must_send != SC_MOVETO) { clear_move_to(); } } } } else { cs_print_string(csocket.fd, "command %d %s", repeat,command); } if (repeat!=-1) { cpl.count=0; } return 1; } void CompleteCmd(unsigned char *data, int len) { if (len !=6) { LOG(LOG_ERROR,"common::CompleteCmd","Invalid length %d - ignoring", len); return; } csocket.command_received = GetShort_String(data); csocket.command_time = GetInt_String(data+2); const int in_flight = csocket.command_sent - csocket.command_received; if (profile_latency) { gint64 now = g_get_monotonic_time(); if (profile_time != NULL) { printf("profile/comc\t%d\t%" G_GINT64_FORMAT "\t%d\t%d\n", csocket.command_received, (now - profile_time[csocket.command_received])/1000, csocket.command_time, in_flight); } } int dir = csocket.dir[csocket.command_received]; if (drun == -1 && dir != -1) { // Revert prediction when command is acknowledged. Note that we undo // the prediction the same regardless of whether the command succeeded // or not, because the player always ends up in the center of the map. predict_scroll(dir+4); } script_sync(in_flight); } /* This does special processing on the 'take' command. If the * player has a container open, we want to specifiy what object * to move from that since we've sorted it. command is * the command as tped, cpnext is any optional params. */ void command_take(const char *command, const char *cpnext) { /* If the player has specified optional data, or the player * does not have a container open, just issue the command * as normal */ if (cpnext || cpl.container == NULL) { send_command(command, cpl.count, 0); } else { if (cpl.container->inv == NULL) draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_NOTICE, "There is nothing in the container to move"); else cs_print_string(csocket.fd,"move %d %d %d", cpl.ob->tag, cpl.container->inv->tag, cpl.count); } } crossfire-client-1.75.3/common/item-types.h000644 001751 001751 00000012130 14045044311 021474 0ustar00kevinzkevinz000000 000000 /* This file is automatically generated editing by hand is strongly*/ /* discouraged. Look at the item-types file and the items.pl conversion */ /* script. */ #define NUM_ITEM_TYPES 256 #define MAX_NAMES_PER_TYPE 64 static const char * const item_types[256][64] = { { NULL }, { "sack", "Luggage", "pouch", "quiver", "bag", "chest", "key ring", NULL }, { "axe", "club", "dagger", "falchion", "hammer", "katana", "mace", "magnifying glass", "morningstar", "nunchacu", "quarterstaff", "sabre", "scimitar", "shovel", "^spear", "stake", "^sword", "Belzebub's sword", "Firebrand", "Harakiri sword", "broadsword", "light sword", "Serpentman sword", "shortsword", "long sword", "taifu", "trident", "BoneCrusher", "Darkblade", "Demonslayer", "Dragonslayer", "Excalibur", "firebrand", "Firestar", "Flame Tongue", "FlameTongue", "Frost Hammer", "Katana of Masamune", "Lightning sticks", "Mjoellnir", "Mournblade", "Sting", "Stormbringer", "Trident", NULL }, { "^bow", "elven bow", "long bow", "crossbow", "sling", "arrow", "^bolt", "boulder", NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { "mail", "leather", "^robe", "shirt", "apron", "hauberk", NULL }, { "helmet", "Crown", "crown", NULL }, { "shield", "Demonspawn Shield", NULL }, { "boot", "glove", "gauntlet", "shoe", NULL }, { "girdle", NULL }, { "cloak", NULL }, { "bracer", NULL }, { NULL }, { NULL }, { NULL }, { "apple", "booze", "bread", "cabbage", "cake", "carrot", "chocolate", "clover", "cup ", "egg", "fish", "food", "mint sprig", "mushroom", "onion", "orange", "potato", "roast bird", "steak", "waybread", "^water", NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { "diamond", "emerald", "gold nugget", "pearl", "ruby", "sapphire", NULL }, { "coin", NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { "rod", "Rod", NULL }, { NULL }, { "wand", NULL }, { "staff", NULL }, { NULL }, { NULL }, { NULL }, { "horn", NULL }, { "amulet", NULL }, { "ring", "Ring ", NULL }, { "scroll", NULL }, { "grimore", "grimoire", "hymnal", "manual", "prayerbook", "sacred text", "spellbook", "testiment", "treatise", "tome", NULL }, { "book", "catalog", "codex", "collection", "compendium", "compilation", "divine text", "divine work", "encyclopedia", "exposition", "file ", "formulary", "guide ", "holy book ", "holy record ", "index", "moral text", "notes", "note", "pamphlet", "record ", "tables", "transcript", "volume", NULL }, { NULL }, { "potion", "bottle", NULL }, { NULL }, { "^balm", "^dust", "dust ", "figurine", NULL }, { NULL }, { "Improve", "Lower Weapon", "Enchant Weapon", "Prepare Weapon", "Enchant Armour", NULL }, { NULL }, { "holy symbol", "lockpick", "talisman", "writing pen", NULL }, { NULL }, { "key", "Key", NULL }, { NULL }, { NULL }, { "arm", "claw", "corpse", "dragon scale", "ectoplasm", "eye", "finger", "foot", "hand", "head", "Head", "heart", "icor", "leg", "lich dust", "liver", "orc chop", "pixie dust", "residue", "skin", "stinger", "tongue", "tooth", "^wing", NULL }, { "dirt", "lead", "mandrake root", "pile", "rock", "stone", NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { "flint and steel", "torch", NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { "clock", "flower", "Gate Pass", "Glowing Crystal", "gravestone", "icecube", "library card", "Passport", "Port Pass", "rose", "Apartment Extender", NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { "chair", "table", NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, { NULL }, }; crossfire-client-1.75.3/common/proto.h000644 001751 001751 00000011237 14323707640 020560 0ustar00kevinzkevinz000000 000000 /* commands.c */ void ReplyInfoCmd(guint8 *buf, int len); void SetupCmd(char *buf, int len); void ExtendedInfoSetCmd(char *data, int len); void AddMeFail(char *data, int len); void AddMeSuccess(char *data, int len); void GoodbyeCmd(char *data, int len); void AnimCmd(unsigned char *data, int len); void SmoothCmd(unsigned char *data, int len); void DrawInfoCmd(char *data, int len); void setTextManager(int type, ExtTextManager callback); void DrawExtInfoCmd(char *data, int len); void use_skill(int skill_id); void StatsCmd(unsigned char *data, int len); void handle_query(char *data, int len); void send_reply(const char *text); void PlayerCmd(unsigned char *data, int len); void item_actions(item *op); void Item2Cmd(unsigned char *data, int len); void UpdateItemCmd(unsigned char *data, int len); void DeleteItem(unsigned char *data, int len); void DeleteInventory(unsigned char *data, int len); void AddspellCmd(unsigned char *data, int len); void UpdspellCmd(unsigned char *data, int len); void DeleteSpell(unsigned char *data, int len); void NewmapCmd(unsigned char *data, int len); void Map2Cmd(unsigned char *data, int len); void map_scrollCmd(char *data, int len); int ExtSmooth(unsigned char *data, int len, int x, int y, int layer); void MapExtendedCmd(unsigned char *data, int len); void MagicMapCmd(unsigned char *data, int len); void SinkCmd(unsigned char *data, int len); void TickCmd(guint8 *data, int len); void PickupCmd(guint8 *data, int len); void FailureCmd(char *buf, int len); void AccountPlayersCmd(char *buf, int len); void free_all_race_class_info(Race_Class_Info *data, int num_entries); /* image.c */ void init_common_cache_data(void); void requestface(int pnum, char *facename); void finish_face_cmd(int pnum, guint32 checksum, int has_sum, char *face, int faceset); void reset_image_cache_data(void); void Face2Cmd(guint8 *data, int len); void Image2Cmd(guint8 *data, int len); void display_newpng(int face, guint8 *buf, int buflen, int setnum); void get_image_info(guint8 *data, int len); void get_image_sums(char *data, int len); /* init.c */ void VersionCmd(char *data, int len); void SendVersion(ClientSocket csock); void SendAddMe(ClientSocket csock); void client_init(void); void reset_player_data(void); void client_reset(void); /* item.c */ guint8 get_type_from_name(const char *name); void update_item_sort(item *it); const char *get_number(guint32 i); void free_all_items(item *op); item *locate_item(gint32 tag); void remove_item(item *op); void remove_item_inventory(item *op); void set_item_values(item *op, char *name, gint32 weight, guint16 face, guint16 flags, guint16 anim, guint16 animspeed, guint32 nrof, guint16 type); void toggle_locked(item *op); void send_mark_obj(item *op); item *player_item(void); item *map_item(void); void update_item(int tag, int loc, char *name, int weight, int face, int flags, int anim, int animspeed, guint32 nrof, int type); void print_inventory(item *op); void animate_objects(void); int can_write_spell_on(item *it); void inscribe_magical_scroll(item *scroll, Spell *spell); /* misc.c */ int make_path_to_file(char *filename); void LOG(LogLevel level, const char *origin, const char *format, ...); /* newsocket.c */ void SockList_Init(SockList *sl, guint8 *buf); void SockList_AddChar(SockList *sl, char c); void SockList_AddShort(SockList *sl, guint16 data); void SockList_AddInt(SockList *sl, guint32 data); void SockList_AddString(SockList *sl, const char *str); int SockList_Send(SockList *sl, GSocketConnection* c); char GetChar_String(const unsigned char *data); int GetInt_String(const unsigned char *data); gint64 GetInt64_String(const unsigned char *data); short GetShort_String(const unsigned char *data); bool SockList_ReadPacket(GSocketConnection c[static 1], SockList sl[static 1], size_t len, GError** error); int cs_print_string(GSocketConnection* c, const char *str, ...); /* p_cmd.c */ /* player.c */ void new_player(long tag, char *name, long weight, long face); void look_at(int x, int y); void client_send_apply(int tag); void client_send_examine(int tag); void client_send_move(int loc, int tag, int nrof); void stop_fire(void); void clear_fire(void); void clear_run(void); void fire_dir(int dir); void stop_run(void); void run_dir(int dir); void walk_dir(int dir); int send_command(const char *command, int repeat, int must_send); void CompleteCmd(unsigned char *data, int len); void command_take(const char *command, const char *cpnext); /* script.c */ /* script_lua.c */ void script_lua_load(const char *name); void script_lua_list(const char *param); void script_lua_kill(const char *param); void script_lua_stats(void); int script_lua_command(const char *command, const char *param); void error_dialog(char *error, char *message); crossfire-client-1.75.3/common/metaserver.h000644 001751 001751 00000001657 14045044330 021566 0ustar00kevinzkevinz000000 000000 /** * @file * Metaserver functions and data structures */ #include #include typedef void (*ms_callback)(char *, int, int, char *, char *, bool); #define MS_SMALL_BUF 60 #define MS_LARGE_BUF 512 /** * @struct Meta_Info * Information about individual servers from the metaserver. */ typedef struct { char hostname[MS_LARGE_BUF]; int port; char html_comment[MS_LARGE_BUF]; char text_comment[MS_LARGE_BUF]; /* all comments are text */ char archbase[MS_SMALL_BUF]; char mapbase[MS_SMALL_BUF]; char codebase[MS_SMALL_BUF]; char flags[MS_SMALL_BUF]; int num_players; guint32 in_bytes; guint32 out_bytes; int idle_time; /* calculated from last_update value */ int uptime; char version[MS_SMALL_BUF]; int sc_version; int cs_version; } Meta_Info; extern void ms_init(void); extern void ms_fetch(ms_callback); crossfire-client-1.75.3/common/chelp.h000644 001751 001751 00000004743 14045044323 020505 0ustar00kevinzkevinz000000 000000 /* Client helpfile */ #ifndef CHELP_H #define CHELP_H #define HELP_BIND_SHORT "bind a command to a key" #define HELP_BIND_LONG "Syntax:\n\ bind [[-nframeg] ]\n\ \n\ Flags (default -nrfam):\n\ n - used in normal-mode\n\ f - used in fire-mode\n\ r - used in run-mode\n\ a - used with alt key\n\ m - used with meta key\n\ e - leave command in line edit\n\ g - global key (not recommended)\n\ Each client may not support every flag.\n\ \n\ bind without flags/command gets client help.\n\ \n\ Special 'commands':\n\ bind commandkey - sets commandkey\n\ bind firekey1 - sets first firekey\n\ bind firekey2 - sets second firekey\n\ bind runkey1 - sets first runkey\n\ bind runkey2 - sets second runkey\n\ bind prevkey - sets history-previous key\n\ bind nextkey - sets history-next key\n\ bind completekey - sets complete-command key\n\ \n\ Examples:\n\ bind -f cast paralyzed (F3)\n\ will typically mean that Shift-F3\n\ is used to select that spell (Shift\n\ being the fire key)\n\ \n\ bind -e shout (\")\n\ will put the cursor in the command\n\ box after writing 'shout' when you\n\ press double-quote. So you can shout\n\ to your friends easier. ;)\n" #define HELP_UNBIND_SHORT "unbind a command, show bindings" #define HELP_UNBIND_LONG "Syntax:\n\ unbind [-g] [#]\n\ unbind reset\n\ Without -g command uses user's bindind,\n\ with -g global binding.\n\ Without number it displays current bindings,\n\ with # it unbinds it.\n\ 'reset' resets default bindings." #define HELP_MAGICMAP_SHORT "show last received magic map" #define HELP_MAGICMAP_LONG "Syntax:\n\ magicmap\n\ Displays last shown magic map." #define HELP_SAVEDEFAULTS_SHORT "save various defaults into ~/.crossfire/defaults" #define HELP_SAVEDEFAULTS_LONG "Syntax:\n\ savedefaults\n\ Saves configuration." /* XXX *Which* configuration? */ #define HELP_INV_SHORT "show clients inventory (debug)" #define HELP_INV_LONG "Syntax:\n\ inv\n\ Debug info about inventory." /* Used to be gchar, but it couldn't find it. */ /* char * text = " === Client Side Commands: === \n\ \n\ bind - " HELP_BIND_SHORT "\n\ unbind - " HELP_UNBIND_SHORT "\n\ magicmap - " HELP_MAGICMAP_SHORT "\n\ savedefaults - " HELP_SAVEDEFAULTS_SHORT "\n\ inv - " HELP_INV_SHORT "\n\ \n\ \n\ bind\n\ \n\ " HELP_BIND_LONG "\n\ \n\ unbind\n\ \n\ " HELP_UNBIND_LONG "\n\ \n\ \n\ magicmap\n\ \n\ " HELP_MAGICMAP_LONG "\n\ \n\ \n\ savedefaults\n\ \n\ " HELP_SAVEDEFAULTS_LONG "\n\ \n\ \n\ inv\n\ \n\ " HELP_INV_LONG "\n\ \n\ \n\ "; */ #endif crossfire-client-1.75.3/common/CMakeLists.txt000644 001751 001751 00000002364 14110265004 021770 0ustar00kevinzkevinz000000 000000 add_custom_command( OUTPUT msgtypes.h COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/msgtypes.pl ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS shared/newclient.h ) # While 'item-types.h' is still under version control, don't build it. #add_custom_command( # OUTPUT item-types.h # COMMAND ${PERL_EXECUTABLE} # ${CMAKE_CURRENT_SOURCE_DIR}/items.pl ${CMAKE_CURRENT_SOURCE_DIR} # DEPENDS item-types #) add_library(cfclient client.c client.h commands.c external.h image.c init.c item.c item.h mapdata.c mapdata.h metaserver.c metaserver.h misc.c msgtypes.h newsocket.c p_cmd.c p_cmd.h player.c proto.h script.c script.h script_lua.c shared/newclient.h version.h ) target_include_directories(cfclient PRIVATE ${PROJECT_BINARY_DIR} ${CURL_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${LUA_INCLUDE_DIR} ) add_executable(test-metaserver test-metaserver.c metaserver.c) target_include_directories(test-metaserver PRIVATE ${GTK_INCLUDE_DIRS} ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/common ) target_link_libraries(test-metaserver ${CURL_LDFLAGS}) add_test(metaserver test-metaserver) crossfire-client-1.75.3/common/script.h000644 001751 001751 00000003705 14323707640 020722 0ustar00kevinzkevinz000000 000000 /* * static char *rcsid_common_script_h = * "$Id$"; */ /* Crossfire client, a client program for the crossfire program. Copyright (C) 2003 Mark Wedel & Crossfire Development Team This source file also Copyright (C) 2003 Preston Crow This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file common/script.h * */ #ifndef SCRIPT_H #define SCRIPT_H #ifndef PF_LOCAL #define PF_LOCAL PF_UNIX /* Old BSD name for PF_LOCAL. */ #endif #ifndef AF_LOCAL #define AF_LOCAL PF_LOCAL #endif enum CmdFormat { ASCII, SHORT_ARRAY, INT_ARRAY, SHORT_INT, /* one short, one int */ MIXED, /* weird ones like magic map */ STATS, NODATA }; void script_init(const char *params); void script_list(void); void script_sync(int cmddiff); void script_kill(const char *params); void script_killall_wrapper(const char *params); void script_killall(void); void script_fdset(int *maxfd,fd_set *set); void script_process(fd_set *set); void script_watch(const char *cmd, const guint8 *data, const int len, const enum CmdFormat format); void script_monitor(const char *command, int repeat, int must_send); void script_monitor_str(const char *command); void script_tell(const char *params); #endif /* SCRIPT_H */ crossfire-client-1.75.3/common/p_cmd.h000644 001751 001751 00000006313 14045044330 020465 0ustar00kevinzkevinz000000 000000 /* Crossfire client, a client program for the crossfire program. Copyright (C) 2005 Mark Wedel & Crossfire Development Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author can be reached via e-mail to crossfire-devel@real-time.com */ /** * @file common/p_cmd.h * Includes and prototypes for p_cmd.c for player-commands like '/magicmap'. * Basically stolen piecemeal from the server branch. */ #ifndef PCMD_H #define PCMD_H /* * List of commands. */ typedef void (*CommFunc)(const char *params); /* Cargo-cult from the above. Every entry in the table * complains about a type mismatch, too. :( */ typedef const char * (*CommHelpFunc)(void); /* This is used for displaying lists of commands. */ typedef enum { COMM_CAT_MISC = 0, /* Commands which can't be better sorted. */ COMM_CAT_INFO = 2, /* A tad general. */ COMM_CAT_SETUP = 3, /* showicon, showweight, bind, commandkey... */ COMM_CAT_SCRIPT = 4, /* The four commands for the nifty-scripts. */ COMM_CAT_DEBUG = 5, /* Debugging commands - hide these? */ } CommCat; /* Retrieves a Title Cased name for the above categories. */ const char * get_category_name(CommCat cat); typedef struct { /* global list's structure */ const char * name; /* Name of command - parsed against this. */ CommCat cat; /* What category the command is in. Used for sorting on display. */ CommFunc dofunc; /* If name is matched, this is called. */ /* TODO Too specific? *sigh* Resolving *that* issue gives me a headache. */ CommHelpFunc helpfunc;/* Returns a string documenting the command. - the *really* long desc. */ const char * desc; /* One-liner describing command. (Man page subtitle, anyone?) */ } ConsoleCommand; extern const ConsoleCommand * find_command(const char * cmd); /** * Fills some internal arrays. Run this on startup, but not before filling in * ToolkitCommands and ToolkitCommandsSize. */ extern void init_commands(void); /** * Returns a pointer to the head of an array of ConsoleCommands * sorted by category, then by name. * * It's num_commands long. */ ConsoleCommand ** get_cat_sorted_commands(void); /* Used only for searching the commands list for help, er. ... Oh, well. */ extern const ConsoleCommand * find_command(const char * cmd); /* This searches ClientCommands; if there's nothing in there, it goes to the server. * With some exceptions. :( */ extern void extended_command(const char *ocommand); extern const char * complete_command(const char * ocommand); extern int handle_local_command(const char* cp, const char * cpnext); #endif crossfire-client-1.75.3/common/init.c000644 001751 001751 00000020504 14323707640 020350 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Functions for initializing the client. */ #include "client.h" #include "mapdata.h" #include "metaserver.h" #include "p_cmd.h" /* Makes the load/save code trivial - basically, the * entries here match the same numbers as the CONFIG_ values defined * in common/client.h - this means the load and save just does * something like a fprintf(outifle, "%s: %d", config_names[i], * want_config[i]); */ const char *const config_names[CONFIG_NUMS] = { NULL, "download_all_images", "echo_bindings", "fasttcpsend", "command_window", "cacheimages", "fog_of_war", "iconscale", "mapscale", "popups", "displaymode", "showicon", "tooltips", "sound", "splitinfo", "split", "show_grid", "lighting", "trim_info_window", "map_width", "map_height", "foodbeep", "darkness", "port", "grad_color_bars", "resistances", "smoothing", "nosplash", "auto_apply_container", "mapscroll", "sign_popups", "message_timestamping", "auto_afk", "inv_menu" }; gint16 want_config[CONFIG_NUMS], use_config[CONFIG_NUMS]; #define FREE_AND_CLEAR(xyz) { free(xyz); xyz=NULL; } void VersionCmd(char *data, int len) { char *cp; csocket.cs_version = atoi(data); /* set sc_version in case it is an old server supplying only one version */ csocket.sc_version = csocket.cs_version; if (csocket.cs_version != VERSION_CS) { LOG(LOG_WARNING, "common::VersionCmd", "Differing C->S version numbers (%d,%d)", VERSION_CS, csocket.cs_version); /* exit(1);*/ } cp = strchr(data, ' '); if (!cp) { return; } csocket.sc_version = atoi(cp); if (csocket.sc_version != VERSION_SC) { LOG(LOG_WARNING, "common::VersionCmd", "Differing S->C version numbers (%d,%d)", VERSION_SC, csocket.sc_version); } cp = strchr(cp + 1, ' '); if (cp) { LOG(LOG_DEBUG, "common::VersionCmd", "Playing on server type %s", cp); } } void SendVersion(ClientSocket csock) { cs_print_string(csock.fd, "version %d %d %s", VERSION_CS, VERSION_SC, VERSION_INFO); } void SendAddMe(ClientSocket csock) { cs_print_string(csock.fd, "addme"); } static void init_paths() { // Set and create configuration and cache directories. GString *app_config_dir = g_string_new(g_get_user_config_dir()); g_string_append(app_config_dir, "/crossfire"); config_dir = g_string_free(app_config_dir, FALSE); g_mkdir_with_parents(config_dir, 0755); GString *app_cache_dir = g_string_new(g_get_user_cache_dir()); g_string_append(app_cache_dir, "/crossfire"); cache_dir = g_string_free(app_cache_dir, FALSE); g_mkdir_with_parents(cache_dir, 0755); } /** * Initialize or reset client variables. This function is called by * client_init() and client_reset(). */ static void reset_vars_common() { cpl.count_left = 0; cpl.container = NULL; memset(&cpl.stats, 0, sizeof(Stats)); cpl.stats.maxsp = 1; /* avoid div by 0 errors */ cpl.stats.maxhp = 1; /* ditto */ cpl.stats.maxgrace = 1; /* ditto */ /* ditto - displayed weapon speed is weapon speed/speed */ cpl.stats.speed = 1; cpl.input_text[0] = '\0'; cpl.title[0] = '\0'; cpl.range[0] = '\0'; cpl.last_command[0] = '\0'; for (int i = 0; i < range_size; i++) { cpl.ranges[i] = NULL; } csocket.command_sent = 0; csocket.command_received = 0; csocket.command_time = 0; cpl.magicmap = NULL; cpl.showmagic = 0; face_info.bmaps_checksum = 0; face_info.cache_hits = 0; face_info.cache_misses = 0; face_info.faceset = 0; face_info.have_faceset_info = 0; face_info.num_images = 0; stat_points = 0; stat_min = 0; stat_maximum = 0; mapdata_free(); reset_player_data(); } /** * Initialize client settings with built-in defaults. */ static void init_config() { want_config[CONFIG_APPLY_CONTAINER] = TRUE; want_config[CONFIG_CACHE] = FALSE; want_config[CONFIG_CWINDOW] = COMMAND_WINDOW; want_config[CONFIG_DARKNESS] = TRUE; want_config[CONFIG_DISPLAYMODE] = CFG_DM_PIXMAP; want_config[CONFIG_DOWNLOAD] = FALSE; want_config[CONFIG_ECHO] = FALSE; want_config[CONFIG_FASTTCP] = TRUE; want_config[CONFIG_FOGWAR] = TRUE; want_config[CONFIG_FOODBEEP] = FALSE; want_config[CONFIG_GRAD_COLOR] = FALSE; want_config[CONFIG_ICONSCALE] = 100; want_config[CONFIG_LIGHTING] = CFG_LT_PIXEL; want_config[CONFIG_MAPHEIGHT] = 20; want_config[CONFIG_MAPSCALE] = 100; want_config[CONFIG_MAPSCROLL] = TRUE; want_config[CONFIG_MAPWIDTH] = 20; want_config[CONFIG_POPUPS] = FALSE; want_config[CONFIG_PORT] = EPORT; want_config[CONFIG_RESISTS] = 0; want_config[CONFIG_RESISTS] = 0; want_config[CONFIG_SHOWGRID] = FALSE; want_config[CONFIG_SHOWICON] = FALSE; want_config[CONFIG_SIGNPOPUP] = TRUE; want_config[CONFIG_SMOOTH] = 0; want_config[CONFIG_SOUND] = TRUE; want_config[CONFIG_SPLASH] = TRUE; want_config[CONFIG_SPLITINFO] = FALSE; want_config[CONFIG_SPLITWIN] = FALSE; want_config[CONFIG_TIMESTAMP] = FALSE; want_config[CONFIG_TOOLTIPS] = TRUE; want_config[CONFIG_TRIMINFO] = FALSE; want_config[CONFIG_AUTO_AFK] = 300; want_config[CONFIG_INV_MENU] = TRUE; for (int i = 0; i < CONFIG_NUMS; i++) { use_config[i] = want_config[i]; } } /** * Called ONCE during client startup to initialize configuration and other * variables to reasonable defaults. Future resets (i.e. after a connection) * should use client_reset() instead. */ void client_init() { // Initialize experience tables. exp_table = NULL; exp_table_max = 0; last_used_skills[MAX_SKILL] = -1; // Clear out variables related to image face caching. face_info.old_bmaps_checksum = 0; face_info.want_faceset = NULL; for (int i = 0; i < MAX_FACE_SETS; i++) { face_info.facesets[i].prefix = NULL; face_info.facesets[i].fullname = NULL; face_info.facesets[i].fallback = 0; face_info.facesets[i].size = NULL; face_info.facesets[i].extension = NULL; face_info.facesets[i].comment = NULL; } // Allocate memory for player-related objects. cpl.ob = player_item(); cpl.below = map_item(); reset_vars_common(); for (int i = 0; i < MAX_SKILL; i++) { skill_names[i] = NULL; last_used_skills[i] = -1; } init_commands(); init_config(); init_paths(); // Paths must be set before metaserver can be initialized. ms_init(); } /** * Reset player experience data. */ void reset_player_data() { int i; for (i = 0; i < MAX_SKILL; i++) { cpl.stats.skill_exp[i] = 0; cpl.stats.skill_level[i] = 0; } } /** * Clear client variables between connections to different servers. This MUST * be called AFTER client_init() because that performs some allocations. */ void client_reset() { int i; /* Keep old checksum to compare it with the next server's checksum. */ face_info.old_bmaps_checksum = face_info.bmaps_checksum; for (i = 0; i < MAX_FACE_SETS; i++) { FREE_AND_CLEAR(face_info.facesets[i].prefix); FREE_AND_CLEAR(face_info.facesets[i].fullname); face_info.facesets[i].fallback = 0; FREE_AND_CLEAR(face_info.facesets[i].size); FREE_AND_CLEAR(face_info.facesets[i].extension); FREE_AND_CLEAR(face_info.facesets[i].comment); } reset_vars_common(); for (i = 0; i < MAX_SKILL; i++) { FREE_AND_CLEAR(skill_names[i]); } if (motd) { FREE_AND_CLEAR(motd); } if (news) { FREE_AND_CLEAR(news); } if (rules) { FREE_AND_CLEAR(rules); } if (races) { free_all_race_class_info(races, num_races); num_races = 0; used_races = 0; races = NULL; } if (classes) { free_all_race_class_info(classes, num_classes); num_classes = 0; used_classes = 0; classes = NULL; } serverloginmethod = 0; } crossfire-client-1.75.3/common/mapdata.h000644 001751 001751 00000013146 14604606323 021023 0ustar00kevinzkevinz000000 000000 #ifndef MAP_H #define MAP_H /** The protocol supports 10 layers, so set MAXLAYERS accordingly. */ #define MAXLAYERS 10 /** * Maximum size of view area a server could support. */ #define MAX_VIEW 64 /* Map1 only used 3 layers. Trying to use 10 seems to cause * problems for that code. */ #define MAP1_LAYERS 3 struct MapCellLayer { gint16 face; gint8 size_x; gint8 size_y; /* Link into animation information. * animation is provided to us from the server in the map2 command. * animation_speed is also provided. * animation_left is how many ticks until animation changes - generated * by client. * animation_phase is current phase. */ gint16 animation; guint8 animation_speed; guint8 animation_left; guint8 animation_phase; }; struct MapCellTailLayer { gint16 face; gint8 size_x; gint8 size_y; }; /// A map cell can be in one of three states: enum MapCellState { EMPTY, //< No data from server, and no fog data VISIBLE, //< Data from server FOG //< No longer visible, but saved as fog of war data }; /** The heads[] in the mapcell is used for single part objects * or the head piece for multipart. The easiest way to think about * it is that the heads[] contains the map information as specifically * sent from the server. For the heads value, the size_x and size_y * represent how many spaces (up and to the left) that image extends * into. * The tails are values that the client fills in - if we get * a big head value, we fill in the tails value so that the display * logic can easily redraw one space. In this case, the size_ values * are offsets that point to the head. In this way, the draw logic * can look at the size of the image, look at these values, and * know what portion of it to draw. */ struct MapCell { struct MapCellLayer heads[MAXLAYERS]; struct MapCellTailLayer tails[MAXLAYERS]; guint8 smooth[MAXLAYERS]; guint8 darkness; /* darkness: 0=fully illuminated, 255=pitch black */ guint8 need_update:1; /* set if tile should be redrawn */ guint8 need_resmooth:1; /* same has need update but for smoothing only */ enum MapCellState state:2; }; struct Map { struct MapCell **_cells; //< data, access via mapdata_cells() int width; //< width of cells array int height; //< height of cells array }; struct MapCell *mapdata_cell(int x, int y); bool mapdata_contains(int x, int y); void mapdata_size(int *x, int *y); bool mapdata_can_smooth(int x, int y, int layer); /** * Initializes the module. Allocates memory for the_map. This functions must be * called before any other function is used, and whenever a new display size * was negotiated with the server. */ void mapdata_set_size(int viewx, int viewy); /** * Deallocate map data. Do not call functions other than mapdata_set_size() * after calling mapdata_free(). */ void mapdata_free(void); /** * Scrolls the map view. Must be called whenever a map_scroll command was * received from the server. */ void mapdata_scroll(int dx, int dy); /** * Clears the map view. Must be called whenever a newmap command was received * from the server. */ void mapdata_newmap(void); /** * Checks whether the given coordinates are within the current display size (as * set by mapdata_set_size). */ int mapdata_is_inside(int x, int y); /** * Returns the face to display at a given location. This function returns the * "head" information, i.e. the face information sent by the server. */ gint16 mapdata_face(int x, int y, int layer) __attribute__((deprecated)); /** * Return the face number of the pixmap in the given map cell and set the * offset pointers to indicate where to correctly draw the face. Offsets are * zero for single-tile maps and negative for multi-tile maps. This provides * a consistent way to draw tiles no matter single or multi part. * @param mx Virtual map x-coordinate * @param my Virtual map y-coordinate * @param layer Map layer number * @param dx Pointer to store x-offset * @param dy Pointer to store y-offset * @return Pixmap face number, zero if the tile does not exist */ gint16 mapdata_face_info(int mx, int my, int layer, int *dx, int *dy); /** * Returns the face to display at a given location. This function returns the * "tail" information, i.e. big faces expanded by the client. * * *ww and *hh return the offset of the current tile relative to the head; * 0 <= *ww < (width of face), 0 <= *hh < (height of face). * * When drawing the map view, this function must be used instead than a direct * access to the_map.cells[]. This is because the_map.cells[] eventually still * contains obsolete (fog of war) big face information; this function detects * and clears such faces. */ gint16 mapdata_bigface(int x, int y, int layer, int *ww, int *hh); void mapdata_clear_space(int x, int y); void mapdata_set_check_space(int x, int y); void mapdata_set_darkness(int x, int y, int darkness); void mapdata_set_smooth(int x, int y, guint8 smooth, int layer); void mapdata_clear_old(int x, int y); void mapdata_set_face_layer(int x, int y, gint16 face, int layer); void mapdata_set_anim_layer(int x, int y, guint16 anim, guint8 anim_speed, int layer); gint16 mapdata_bigface_head(int x, int y, int layer, int *ww, int *hh); void mapdata_animation(void); int relative_direction(int dx, int dy); extern PlayerPosition script_pos; void pl_mpos(int *px, int *py); void set_move_to(int dx, int dy); void clear_move_to(void); bool is_at_moveto(void); void run_move_to(void); extern int move_to_x, move_to_y; extern bool move_to_attack; extern int global_offset_x, want_offset_x; extern int global_offset_y, want_offset_y; #endif crossfire-client-1.75.3/common/commands.c000644 001751 001751 00000236202 14604373073 021213 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Handles server->client commands; See player.c for client->server commands. * * Not necessarily all commands are handled - some might be in other files * (like init.c) * * This file contains most of the commands for the dispatch loop. Most of the * functions are self-explanatory. * * pixmap/bitmap : receive the picture, and display it. * drawinfo : draws a string in the info window. * stats : updates the local copy of the stats and displays it. * handle_query : prompts the user for input. * send_reply : sends off the reply for the input. * player : gets the player information. * MapScroll : scrolls the map on the client by some amount. * MapCmd : displays the map with layer packing or stack packing. * packing/unpacking is best understood by looking at the server code * (server/ericserver.c) * stack packing: for every map entry that changed, we pack 1 byte for the * x/y location, 1 byte for the count, and 2 bytes per face in the stack. * layer packing is harder, but I seem to remember more efficient: first we * pack in a list of all map cells that changed and are now empty. The end * of this list is a 255, which is bigger that 121, the maximum packed map * location. * For each changed location we also pack in a list of all the faces and X/Y * coordinates by layer, where the layer is the depth in the map. This * essentially takes slices through the map rather than stacks. * Then for each layer, (max is MAXMAPCELLFACES, a bad name) we start * packing the layer into the message. First we pack in a face, then for * each place on the layer with the same face, we pack in the x/y location. * We mark the last x/y location with the high bit on (11*11 = 121 < 128). * We then continue on with the next face, which is why the code marks the * faces as -1 if they are finished. Finally we mark the last face in the * layer again with the high bit, clearly limiting the total number of faces * to 32767, the code comments it's 16384, I'm not clear why, but the second * bit may be used somewhere else as well. * The unpacking routines basically perform the opposite operations. */ int mapupdatesent = 0; #include "client.h" #include #include #include #include "external.h" #include "mapdata.h" /* In general, the data from the server should not do bad * things like this, but checking for it makes it easier * to find bugs. Often this is called within a loop * that of iterating over the length of the buffer, hence * the break. Note that this may not prevent crashes, * but at least we generate a message. * Note that curpos & buflen may be string pointers or * may be integers - as long as both are the same * (both integers or both char *) it will work. */ #define ASSERT_LEN(function, curpos, buflen) \ if (curpos > buflen) { \ LOG(LOG_WARNING, function, "Data goes beyond length of buffer (%d>%d)", curpos, buflen); \ break; \ } char *news=NULL, *motd=NULL, *rules=NULL; /** Keeps track of what spellmon command is supported by the server. */ static int spellmon_level = 0; int num_races = 0; /* Number of different races server has */ int used_races = 0; /* How many races we have filled in */ int num_classes = 0; /* Same as race data above, but for classes */ int used_classes = 0; int stat_points; /* Number of stat points for new characters */ int stat_min; /* Minimum stat for new characters */ int stat_maximum; /* Maximum stat for new characters */ int starting_map_number = 0; /* Number of starting maps */ Race_Class_Info *races=NULL, *classes=NULL; Starting_Map_Info *starting_map_info = NULL; /* Best I can tell, none of this stat information is stored anyplace * else in the server - MSW 2010-07-28 */ #define NUM_STATS 7 /** Short name of stats. */ static const char *const short_stat_name[NUM_STATS] = { "Str", "Dex", "Con", "Wis", "Cha", "Int", "Pow" }; /* Note that the label_cs and label_rs will be in this same * order, eg, label_cs[0] will be strength, label_cs[1] will * be con. However, this order can be changed, so it should * not be assumed that label_cs[1] will always be con. */ struct Stat_Mapping stat_mapping[NUM_NEW_CHAR_STATS] = { {"str", CS_STAT_STR, 0}, {"con", CS_STAT_CON, 1}, {"dex", CS_STAT_DEX, 2}, {"int", CS_STAT_INT, 3}, {"wis", CS_STAT_WIS, 4}, {"pow", CS_STAT_POW, 5}, {"cha", CS_STAT_CHA, 6} }; /** * This function clears the data from the Race_Class_Info array. Because the * structure itself contains data that is allocated, some work needs to be * done to clear that data. * */ void free_all_starting_map_info() { int i; if (!starting_map_info) { return; } /* Because we are going free the array storage itself, there is no reason * to clear the data[i].. values. */ for (i=0; i len) { LOG(LOG_WARNING, "common::get_starting_map_info", "Length of data is greater than buffer (%d>%d)", length + pos, len); return; } cp = g_malloc(length+1); strncpy(cp, (char *)data + pos, length); cp[length] = 0; pos += length; /* If it is the arch name, it is a new entry, so we allocate * space and clear it. This isn't most efficient, but at * the same time, I don't see there being many maps. * Note: If g_realloc is given a null pointer (which starting_map_info * will be after free or first load), g_realloc just acts as g_malloc. */ if (type == INFO_MAP_ARCH_NAME) { map_entry++; starting_map_info = g_realloc(starting_map_info, (map_entry + 1) * sizeof(Starting_Map_Info)); if (starting_map_info == NULL) { LOG(LOG_ERROR, "get_starting_map_info", "Could not allocate memory: %s", strerror(errno)); exit(EXIT_FAILURE); } memset(&starting_map_info[map_entry], 0, sizeof(Starting_Map_Info)); starting_map_info[map_entry].arch_name = cp; } else if (type == INFO_MAP_NAME) { starting_map_info[map_entry].public_name = cp; } else if (type == INFO_MAP_DESCRIPTION) { starting_map_info[map_entry].description = cp; } else { /* Could be this is old client - but we can skip over * this bad data so long as the length byte is valid. */ LOG(LOG_WARNING, "common::get_starting_map_info", "Unknown type: %d\n", type); } } starting_map_number = map_entry; starting_map_update_info(); } /** * This is process the newcharinfo requestinfo. * In some cases, it stores away the value, for others, it just * makes sure we understand them. * * The data is a series of length prefixed lines. * * @param data * data returned from server. Format is documented in protocol file. * @param len * length of data. */ static void get_new_char_info(unsigned char *data, int len) { int olen=0, llen; /* We reset these values - if the user is switching between * servers before restarting the client, these may have * different values. */ stat_points = 0; stat_min = 0; stat_maximum = 0; while (olen < len) { char datatype, *cp; /* Where this line ends in the total buffer */ llen = olen + GetChar_String(data + olen); /* By protocol convention, this should already be NULL, * but we ensure it is. If the server has not included the * null byte, we are overwriting some real data here, but * the client will probably get an error at that point - * if the server is not following the protocol, we really * can't trust any of the data we get from it. */ data[llen] = 0; if (llen > len) { LOG(LOG_WARNING, "common::get_new_char_info", "Length of line is greater than buffer (%d>%d)", llen, len); return; } olen++; datatype = GetChar_String(data+olen); /* Type value */ olen++; /* First skip all the spaces */ while (olen <= len) { if (!isspace(data[olen])) { break; } olen++; } if (olen > len) { LOG(LOG_WARNING, "common::get_new_char_info", "Overran length of buffer (%d>%d)", olen, len); return; } cp = (char *)data + olen; /* Go until we find another space */ while (olen <= len) { if (isspace(data[olen])) { break; } olen++; } data[olen] = 0; /* Null terminate the string */ olen++; if (olen > len) { LOG(LOG_WARNING, "common::get_new_char_info", "Overran length of buffer (%d>%d)", olen, len); return; } /* At this point, cp points to the string portion (variable name) * of the line, with data+olen is the start of the next string * (variable value). */ if (!g_ascii_strcasecmp(cp,"points")) { stat_points = atoi((char *)data + olen); olen = llen + 1; continue; } else if (!g_ascii_strcasecmp(cp,"statrange")) { if (sscanf((char *)data + olen, "%d %d", &stat_min, &stat_maximum) != 2) { LOG(LOG_WARNING, "common::get_new_char_info", "Unable to process statrange line (%s)", data + olen); } /* Either way, we go onto the next line */ olen = llen + 1; continue; } else if (!g_ascii_strcasecmp(cp,"statname")) { /* The checking we do here is somewhat basic: * 1) That we understand all the stat names that the server sends us * 2) That we get the correct number of stats. * Note that if the server sends us the same stat name twice, eg * Str Str Dex Con ..., that will screw up this logic, but to a * great extent, we have to trust that server is sending us correct * information - sending the same stat twice does not follow that. */ int i, matches=0; while (olen < llen) { for (i=0; i < NUM_STATS; i++) { if (!g_ascii_strncasecmp((char *)data + olen, short_stat_name[i], strlen(short_stat_name[i]))) { matches++; olen += strlen(short_stat_name[i]) + 1; break; } } if (i == NUM_STATS) { LOG(LOG_WARNING, "common::get_new_char_info", "Unable to find matching stat name (%s)", data + olen); break; } } if (matches != NUM_STATS) { LOG(LOG_WARNING, "common::get_new_char_info", "Did not get correct number of stats (%d!=%d)", matches, NUM_STATS); } olen = llen + 1; continue; } else if (!g_ascii_strcasecmp(cp,"race") || !g_ascii_strcasecmp(cp,"class")) { if (g_ascii_strcasecmp((char *)data + olen, "requestinfo")) { LOG(LOG_WARNING, "common::get_new_char_info", "Got unexpected value for %s: %s", cp, data+olen); } olen = llen + 1; continue; } else if (!g_ascii_strcasecmp(cp,"startingmap")) { if (g_ascii_strcasecmp((char *)data + olen, "requestinfo")) { LOG(LOG_WARNING, "common::get_new_char_info", "Got unexpected value for %s: %s", cp, data+olen); } else { cs_print_string(csocket.fd, "requestinfo startingmap"); free_all_starting_map_info(); } olen = llen + 1; continue; } else { if (datatype == 'V' || datatype == 'R') { LOG(LOG_WARNING, "common::get_new_char_info", "Got unsupported string from server, type %c, value %s", datatype, cp); /* pop up error here */ } else { /* pop up warning here */ } olen = llen + 1; } } if (stat_min == 0 || stat_maximum == 0 || stat_points == 0) { /* this needs to be handled better, but I'm not sure how - * we could fall back to legacy character creation mode, * but that will go away at some point - in a sense, if the * server is not sending us values, that is a broken/non comformant * server - best we could perhaps do is throw up a window saying * this client is not compatible with the server. */ LOG(LOG_ERROR, "common::get_new_char_info", "Processed all newcharinfo yet have 0 value: stat_min=%d, stat_maximum=%d, stat_points=%d", stat_min, stat_maximum, stat_points); } else { new_char_window_update_info(); } } /** * Used for bsearch searching. */ static int rc_compar(const Race_Class_Info *a, const Race_Class_Info *b) { return g_ascii_strcasecmp(a->public_name, b->public_name); } /** * This function clears the data from the Race_Class_Info array. Because the * structure itself contains data that is allocated, some work needs to be * done to clear that data. * * @param data * array to clear * @param num_entries * size of the array. */ void free_all_race_class_info(Race_Class_Info *data, int num_entries) { int i; /* Because we are going free the array storage itself, there is no reason * to clear the data[i].. values. */ for (i=0; iarch_name = g_strdup(cp); cp = nl+1; } else { LOG(LOG_WARNING, "common::process_race_class_info", "Did not find archetype name"); return; } /* Now we process the rest of the data - we look for a word the describes * the data to follow. cp is a pointer to the data we are processing. nl * is used to store temporary values. */ do { nl = strchr(cp, ' '); /* If we did not find a space, may just mean we have reached the end * of the data - could be a stray character, etc */ if (!nl) { break; } if (nl) { *nl = 0; nl++; } if (!strcmp(cp, "name")) { /* We get a name. The string is not NULL terminated, but the * length is transmitted. So get the length, allocate a string * large enough for that + NULL terminator, and copy string in, * making sure to put terminator in place. also make sure we * update cp beyond this block of data. */ int namelen; namelen = GetChar_String((unsigned char *)nl); ASSERT_LEN("common::process_race_class_info", (unsigned char *)nl + namelen, data + len); nl++; rci->public_name = g_malloc(namelen+1); strncpy(rci->public_name, nl, namelen); rci->public_name[namelen] = 0; cp = nl + namelen; } else if (!strcmp(cp, "stats")) { cp = nl; /* This loop goes through the stat values - *cp points to the stat * value - if 0, no more stats, hence the check here. */ while (cp < (char *)data + len && *cp != 0) { int i; for (i=0; i < NUM_NEW_CHAR_STATS; i++) if (stat_mapping[i].cs_value == *cp) { break; } if (i == NUM_NEW_CHAR_STATS) { /* Just return with what we have */ LOG(LOG_WARNING, "common::process_race_class_info", "Unknown stat value: %d", cp); return; } rci->stat_adj[stat_mapping[i].rc_offset] = GetShort_String((unsigned char *)cp + 1); cp += 3; } cp++; /* Skip over 0 terminator */ } else if (!strcmp(cp, "msg")) { /* This is really exactly same as name processing above, except * length is 2 bytes in this case. */ int msglen; msglen = GetShort_String((unsigned char *)nl); ASSERT_LEN("common::process_race_class_info", (unsigned char *)nl + msglen, data + len); nl+=2; rci->description = g_malloc(msglen+1); strncpy(rci->description, nl, msglen); rci->description[msglen] = 0; cp = nl + msglen; } else if (!strcmp(cp, "choice")) { int oc = rci->num_rc_choice, clen; rci->num_rc_choice++; /* rc_choice may be null, but g_realloc still works there */ rci->rc_choice = g_realloc(rci->rc_choice, sizeof(struct RC_Choice) * rci->num_rc_choice); memset(&rci->rc_choice[oc], 0, sizeof(struct RC_Choice)); cp = nl; /* First is the coice string we return */ clen = GetChar_String((unsigned char *)cp); cp++; ASSERT_LEN("common::process_race_class_info", (unsigned char *)cp + clen, data + len); rci->rc_choice[oc].choice_name = g_malloc(clen+1); strncpy(rci->rc_choice[oc].choice_name, cp, clen); rci->rc_choice[oc].choice_name[clen] = 0; cp += clen; /* Next is the description */ clen = GetChar_String((unsigned char *)cp); cp++; ASSERT_LEN("common::process_race_class_info", (unsigned char *)cp + clen, data + len); rci->rc_choice[oc].choice_desc = g_malloc(clen+1); strncpy(rci->rc_choice[oc].choice_desc, cp, clen); rci->rc_choice[oc].choice_desc[clen] = 0; cp += clen; /* Now is a series of archetype/description pairs */ while (1) { int vn; clen = GetChar_String((unsigned char *)cp); cp++; if (!clen) { break; /* 0 length is end of data */ } vn = rci->rc_choice[oc].num_values; rci->rc_choice[oc].num_values++; rci->rc_choice[oc].value_arch = g_realloc(rci->rc_choice[oc].value_arch, sizeof(char*) * rci->rc_choice[oc].num_values); rci->rc_choice[oc].value_desc = g_realloc(rci->rc_choice[oc].value_desc, sizeof(char*) * rci->rc_choice[oc].num_values); ASSERT_LEN("common::process_race_class_info", (unsigned char *)cp + clen, data + len); rci->rc_choice[oc].value_arch[vn] = g_malloc(clen+1); strncpy(rci->rc_choice[oc].value_arch[vn], cp, clen); rci->rc_choice[oc].value_arch[vn][clen] = 0; cp += clen; clen = GetChar_String((unsigned char *)cp); cp++; ASSERT_LEN("common::process_race_class_info", (unsigned char *)cp + clen, data + len); rci->rc_choice[oc].value_desc[vn] = g_malloc(clen+1); strncpy(rci->rc_choice[oc].value_desc[vn], cp, clen); rci->rc_choice[oc].value_desc[vn][clen] = 0; cp += clen; } } else { /* Got some keyword we did not understand. Because we do not know * about it, we do not know how to skip it over - the data could * very well contain spaces or other markers we look for. */ LOG(LOG_WARNING, "common::process_race_class_info", "Got unknown keyword: %s", cp); break; } } while ((unsigned char *)cp < data + len); /* The display code expects all of these to have a description - * rather than add checks there for NULL values, simpler to * just set things to an empty value. */ if (!rci->description) { rci->description = g_strdup(""); } } /** * This is a little wrapper function that does some bounds checking and then * calls process_race_info() to do the bulk of the work. * * @param data * data returned from server. Format is documented in protocol file. * @param len * length of data. */ static void get_race_info(unsigned char *data, int len) { /* This should not happen - the client is only requesting race info for * races it has received - and it knows how many of those it has. */ if (used_races >= num_races) { LOG(LOG_ERROR, "common::get_race_info", "used races exceed num races, %d>=%d", used_races, num_races); return; } process_race_class_info(data, len, &races[used_races]); used_races++; if (used_races == num_races) { qsort(races, used_races, sizeof(Race_Class_Info), (int (*)(const void *, const void *))rc_compar); new_char_window_update_info(); } } /** * This is a little wrapper function that does some bounds checking and then * calls process_race_info() to do the bulk of the work. Pretty much * identical to get_race_info() except this is for classes. * * @param data * data returned from server. Format is documented in protocol file. * @param len * length of data. */ static void get_class_info(unsigned char *data, int len) { /* This should not happen - the client is only requesting race info for * classes it has received - and it knows how many of those it has. */ if (used_classes >= num_classes) { LOG(LOG_ERROR, "common::get_race_info", "used classes exceed num classes, %d>=%d", used_classes, num_classes); return; } process_race_class_info(data, len, &classes[used_classes]); used_classes++; if (used_classes == num_classes) { qsort(classes, used_classes, sizeof(Race_Class_Info), (int (*)(const void *, const void *))rc_compar); new_char_window_update_info(); } } /** * * @param data * @param len */ static void get_exp_info(const unsigned char *data, int len) { int pos, level; if (len < 2) { LOG(LOG_ERROR, "common::get_exp_info", "no max level info from server provided"); return; } exp_table_max = GetShort_String(data); pos = 2; exp_table = calloc(exp_table_max, sizeof(guint64)); for (level = 1; level <= exp_table_max && pos < len; level++) { exp_table[level] = GetInt64_String(data+pos); pos += 8; } if (level != exp_table_max) { LOG(LOG_ERROR, "common::get_exp_info", "Incomplete table sent - got %d entries, wanted %d", level, exp_table_max); } } /** * * @param data * @param len */ static void get_skill_info(char *data, int len) { char *cp, *nl, *sn; int val; cp = data; do { nl = strchr(cp, '\n'); if (nl) { *nl = 0; nl++; } sn = strchr(cp, ':'); if (!sn) { LOG(LOG_WARNING, "common::get_skill_info", "corrupt line: /%s/", cp); return; } *sn = 0; sn++; val = atoi(cp); val -= CS_STAT_SKILLINFO; /* skill_names[MAX_SKILL] is the declaration, so check against that */ if (val < 0 || val >= MAX_SKILL) { LOG(LOG_WARNING, "common::get_skill_info", "invalid skill number %d", val); return; } free(skill_names[val]); skill_names[val] = g_strdup(sn); cp = nl; } while (cp < data+len); } /** * Handles the response from a 'requestinfo' command. This function doesn't * do much itself other than dispatch to other functions. * * @param buf * @param len */ void ReplyInfoCmd(unsigned char *buf, int len) { unsigned char *cp; int i; /* Covers a bug in the server in that it could send a replyinfo with no * parameters */ if (!buf) { return; } for (i = 0; i < len; i++) { /* Either a space or newline represents a break */ if (*(buf+i) == ' ' || *(buf+i) == '\n') { break; } } if (i >= len) { /* Don't print buf, as it may contain binary data */ /* Downgrade this to DEBUG - if the client issued an unsupported * requestinfo info to the server, we'll end up here - this could be * normal behaviour */ LOG(LOG_DEBUG, "common::ReplyInfoCmd", "Never found a space in the replyinfo"); return; } /* Null out the space and put cp beyond it */ cp = buf+i; *cp++ = '\0'; if (!strcmp((char*)buf, "image_info")) { get_image_info(cp, len-i-1); /* Located in common/image.c */ } else if (!strcmp((char*)buf, "image_sums")) { get_image_sums((char*)cp, len-i-1); /* Located in common/image.c */ } else if (!strcmp((char*)buf, "skill_info")) { get_skill_info((char*)cp, len-i-1); /* Located in common/commands.c */ } else if (!strcmp((char*)buf, "exp_table")) { get_exp_info(cp, len-i-1); /* Located in common/commands.c */ } else if (!strcmp((char*)buf, "motd")) { if (motd) { free((char*)motd); } motd = g_strdup((char *)cp); update_login_info(INFO_MOTD); } else if (!strcmp((char*)buf, "news")) { if (news) { free((char*)news); } news = g_strdup((char *)cp); update_login_info(INFO_NEWS); } else if (!strcmp((char*)buf, "rules")) { if (rules) { free((char*)rules); } rules = g_strdup((char *)cp); update_login_info(INFO_RULES); } else if (!strcmp((char*)buf, "race_list")) { unsigned char *cp1; for (cp1=cp; *cp !=0; cp++) { if (*cp == '|') { *cp++ = '\0'; /* The first separator has no data, so only send request to * server if this is not null. */ if (*cp1!='\0') { cs_print_string(csocket.fd, "requestinfo race_info %s", cp1); num_races++; } cp1 = cp; } } if (*cp1!='\0') { cs_print_string(csocket.fd, "requestinfo race_info %s", cp1); num_races++; } if (races) { free_all_race_class_info(races, num_races); num_races=0; used_races=0; } races = calloc(num_races, sizeof(Race_Class_Info)); } else if (!strcmp((char*)buf, "class_list")) { unsigned char *cp1; for (cp1=cp; *cp !=0; cp++) { if (*cp == '|') { *cp++ = '\0'; /* The first separator has no data, so only send request to * server if this is not null. */ if (*cp1!='\0') { cs_print_string(csocket.fd, "requestinfo class_info %s", cp1); num_classes++; } cp1 = cp; } } /* last race isn't followed by a | */ if (*cp1 != '\0') { cs_print_string(csocket.fd, "requestinfo class_info %s", cp1); num_classes++; } if (classes) { free_all_race_class_info(classes, num_classes); num_classes=0; used_classes=0; } classes = calloc(num_classes, sizeof(Race_Class_Info)); } else if (!strcmp((char*)buf, "race_info")) { get_race_info(cp, len -i -1); } else if (!strcmp((char*)buf, "class_info")) { get_class_info(cp, len -i -1); } else if (!strcmp((char*)buf, "newcharinfo")) { get_new_char_info(cp, len -i -1); } else if (!strcmp((char*)buf, "startingmap")) { get_starting_map_info(cp, len -i -1); } } /** * Received a response to a setup from the server. This function is basically * the same as the server side function - we just do some different processing * on the data. * * @param buf * @param len */ void SetupCmd(char *buf, int len) { int s; char *cmd, *param; /* Process the setup commands. * Syntax is setup ... * * The server sends the status of the cmd back, or a FALSE if the cmd is * unknown. The client then must sort this out. */ LOG(LOG_DEBUG, "common::SetupCmd", "%s", buf); for (s = 0; ; ) { if (s >= len) { /* Ugly, but for secure...*/ break; } cmd = &buf[s]; /* Find the next space, and put a null there */ for (; buf[s] && buf[s] != ' '; s++) ; buf[s++] = 0; while (buf[s] == ' ') { s++; } if (s >= len) { break; } param = &buf[s]; for (; buf[s] && buf[s] != ' '; s++) ; buf[s++] = 0; while (s < len && buf[s] == ' ') { s++; } /* What is done with the returned data depends on what the server * returns. In some cases the client may fall back to other methods, * report an error, or try another setup command. */ if (!strcmp(cmd, "sound2")) { /* No parsing needed, but we don't want a warning about unknown * setup option below. */ } else if (!strcmp(cmd, "sound")) { /* No, this should not be !strcmp()... */ } else if (!strcmp(cmd, "mapsize")) { if (!g_ascii_strcasecmp(param, "false")) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, "Server only supports standard sized maps (11x11)"); /* Do this because we may have been playing on a big server * before */ use_config[CONFIG_MAPWIDTH] = 11; use_config[CONFIG_MAPHEIGHT] = 11; mapdata_set_size(use_config[CONFIG_MAPWIDTH], use_config[CONFIG_MAPHEIGHT]); resize_map_window(use_config[CONFIG_MAPWIDTH], use_config[CONFIG_MAPHEIGHT]); continue; } // Parse map size returned by the server. int x = atoi(param); int y = 0; for (char *cp = param; *cp != 0; cp++) { if (*cp == 'x' || *cp == 'X') { y = atoi(cp+1); break; } } /* A size larger than what the server supports was requested. * Reduce the size to server maximum, and re-send the setup * command. Update our want sizes, and tell the player what is * going on. */ char tmpbuf[MAX_BUF]; if (want_config[CONFIG_MAPWIDTH] > x || want_config[CONFIG_MAPHEIGHT] > y) { if (want_config[CONFIG_MAPWIDTH] > x) { want_config[CONFIG_MAPWIDTH] = x; } if (want_config[CONFIG_MAPHEIGHT] > y) { want_config[CONFIG_MAPHEIGHT] = y; } client_mapsize(want_config[CONFIG_MAPWIDTH], want_config[CONFIG_MAPHEIGHT]); snprintf(tmpbuf, sizeof(tmpbuf), "Server supports a max mapsize of %d x %d - requesting a %d x %d mapsize", x, y, want_config[CONFIG_MAPWIDTH], want_config[CONFIG_MAPHEIGHT]); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, tmpbuf); } else if (want_config[CONFIG_MAPWIDTH] == x && want_config[CONFIG_MAPHEIGHT] == y) { use_config[CONFIG_MAPWIDTH] = want_config[CONFIG_MAPWIDTH]; use_config[CONFIG_MAPHEIGHT] = want_config[CONFIG_MAPHEIGHT]; mapdata_set_size(use_config[CONFIG_MAPWIDTH], use_config[CONFIG_MAPHEIGHT]); resize_map_window(use_config[CONFIG_MAPWIDTH], use_config[CONFIG_MAPHEIGHT]); } else { /* The request was not bigger than what server supports, and * not the same size, so what is the problem? Tell the user * that something is wrong. */ snprintf(tmpbuf, sizeof(tmpbuf), "Unable to set mapsize on server - we wanted %d x %d, server returned %d x %d", want_config[CONFIG_MAPWIDTH], want_config[CONFIG_MAPHEIGHT], x, y); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, tmpbuf); } } else if (!strcmp(cmd, "darkness")) { /* Older servers might not support this setup command. */ if (!strcmp(param, "FALSE")) { LOG(LOG_WARNING, "common::SetupCmd", "Server returned FALSE for setup command %s", cmd); } } else if (!strcmp(cmd, "spellmon")) { /* Older servers might not support this setup command or all of * the extensions. * * Spellmon 2 was added to the protocol in January 2010 to send an * additional spell information string with casting requirements * including required items, if the spell needs arguments passed * (like text for rune of marking), etc. * * To use the new feature, "setup spellmon 1 spellmon 2" is sent, * and if "spellmon 1 spellmon FALSE" is returned then the server * doesn't accept 2 - sending spellmon 2 to a server that does not * support it is not problematic, so the spellmon 1 command will * still be handled correctly by the server. If the server sends * "spellmon 1 spellmon 2" then the extended mode is in effect. * * It is not particularly important for the player to know what * level of command is accepted by the server. The extra features * will simply not be functionally available. */ if (!strcmp(param, "FALSE")) { LOG(LOG_INFO, "common::SetupCmd", "Server returned FALSE for a %s setup command", cmd); } else { spellmon_level = atoi(param); } } else if (!strcmp(cmd, "facecache")) { use_config[CONFIG_CACHE] = atoi(param); } else if (!strcmp(cmd, "faceset")) { if (!strcmp(param, "FALSE")) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, "Server does not support other image sets, will use default"); face_info.faceset = 0; } } else if (!strcmp(cmd, "map2cmd")) { if (!strcmp(param, "FALSE")) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, "Server does not support map2cmd!"); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, "This server is too old to support this client!"); client_disconnect(); } } else if (!strcmp(cmd, "want_pickup")) { /* Nothing special to do as this is info pushed from server and * not having it isn't that bad. */ } else if (!strcmp(cmd, "loginmethod")) { int method = atoi(param); /* If the server supports new login, start the process. Pass what * version the server supports so client can do appropriate * work */ if (method) { start_login(method); } } else if (!strcmp(cmd, "newmapcmd")) { // if server doesn't support newmapcmd, too bad } else if (!strcmp(cmd, "tick")) { // Ticks drive the redraw loop via client_tick(), so we really // do need ticks. To support servers without ticks, add a timer // callback via g_timeout_add() that calls client_tick(). if (!strcmp(param, "FALSE")) { draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, "Server does not support tick!"); draw_ext_info(NDI_RED, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_SERVER, "This server is too old to support this client!"); client_disconnect(); } } else if (!strcmp(cmd, "extendedTextInfos")) { // Even though this is deprecated, old servers are sitll being // actively used. Request extended text info (drawextinfo). if (csocket.cs_version < 1023 && strcmp(param, "FALSE")) { /* server didn't send FALSE*/ /* Server seems to accept extended text infos. Let's tell * it what extended text info we want */ for (int i = 1; i < 20; i++) { char exttext[MAX_BUF]; snprintf(exttext, sizeof(exttext), "toggleextendedtext %d", i); cs_print_string(csocket.fd, exttext); } } } else { LOG(LOG_INFO, "common::SetupCmd", "Got setup for a command we don't understand: %s %s", cmd, param); } } } /** * Handles when the server says we can't be added. In reality, we need to * close the connection and quit out, because the client is going to close us * down anyways. * * @param data * @param len */ void AddMeFail(char *data, int len) { (void)data; /* __UNUSED__ */ (void)len; /* __UNUSED__ */ LOG(LOG_INFO, "common::AddMeFail", "addme_failed received."); return; } /** * This is really a throwaway command - there really isn't any reason to send * addme_success commands. * * @param data * @param len */ void AddMeSuccess(char *data, int len) { (void)data; /* __UNUSED__ */ (void)len; /* __UNUSED__ */ hide_all_login_windows(); show_main_client(); LOG(LOG_DEBUG, "common::AddMeSuccess", "addme_success received."); return; } /** * * @param data * @param len */ void GoodbyeCmd(char *data, int len) { (void)data; /* __UNUSED__ */ (void)len; /* __UNUSED__ */ /* This could probably be greatly improved - I am not sure if anything * needs to be saved here, but it should be possible to reconnect to the * server or a different server without having to rerun the client. */ LOG(LOG_WARNING, "common::GoodbyeCmd", "Received goodbye command from server - exiting"); exit(0); } Animations animations[MAXANIM]; /** * * @param data * @param len */ void AnimCmd(unsigned char *data, int len) { short anum; int i, j; anum = GetShort_String(data); if (anum < 0 || anum > MAXANIM) { LOG(LOG_WARNING, "common::AnimCmd", "animation number invalid: %d", anum); return; } animations[anum].flags = GetShort_String(data+2); animations[anum].num_animations = (len-4)/2; if (animations[anum].num_animations < 1) { LOG(LOG_WARNING, "common::AnimCmd", "num animations invalid: %d", animations[anum].num_animations); return; } animations[anum].faces = g_malloc(sizeof(guint16)*animations[anum].num_animations); for (i = 4, j = 0; i < len; i += 2, j++) { animations[anum].faces[j] = GetShort_String(data+i); } if (j != animations[anum].num_animations) { LOG(LOG_WARNING, "common::AnimCmd", "Calculated animations does not equal stored animations? (%d!=%d)", j, animations[anum].num_animations); } animations[anum].speed = 0; animations[anum].speed_left = 0; animations[anum].phase = 0; LOG(LOG_DEBUG, "common::AnimCmd", "Received animation %d, %d faces", anum, animations[anum].num_animations); } /** * Receives the smooth mapping from the server. Because this information is * reference a lot, the smoothing face is stored in the pixmap data - this * makes access much faster than searching an array of data for the face to * use. * * @param data * @param len */ void SmoothCmd(unsigned char *data, int len) { guint16 faceid; guint16 smoothing; /* len is unused. We should check that we don't have an invalid short * command. Hence, the compiler warning is valid. */ faceid = GetShort_String(data); smoothing = GetShort_String(data+2); addsmooth(faceid, smoothing); } /** * Draws a string in the info window. * * @param data * @param len */ void DrawInfoCmd(char *data, int len) { int color = atoi(data); char *buf; (void)len; /* __UNUSED__ */ buf = strchr(data, ' '); if (!buf) { LOG(LOG_WARNING, "common::DrawInfoCmd", "got no data"); buf = ""; } else { buf++; } draw_ext_info(color, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_COMMAND, buf); } TextManager *firstTextManager = NULL; /** * * @param type * @param callback */ void setTextManager(int type, ExtTextManager callback) { TextManager *current = firstTextManager; while (current != NULL) { if (current->type == type) { current->callback = callback; return; } current = current->next; } current = g_malloc(sizeof(TextManager)); current->type = type; current->callback = callback; current->next = firstTextManager; firstTextManager = current; } /** * * @param type */ static ExtTextManager getTextManager(int type) { TextManager *current = firstTextManager; while (current != NULL) { if (current->type == type) { return current->callback; } current = current->next; } return NULL; } /** * We must extract color, type, subtype and dispatch to callback * * @param data * @param len */ void DrawExtInfoCmd(char *data, int len) { int color; int type, subtype; char *buf = data; int wordCount = 3; ExtTextManager fnct; while (wordCount > 0) { while (buf[0] == ' ') { buf++; } wordCount--; while (buf[0] != ' ') { if (buf[0] == '\0') { LOG(LOG_WARNING, "common::DrawExtInfoCmd", "Data is missing %d parameters %s", wordCount, data); return; } else { buf++; } } if (buf[0] == ' ') { buf++; /*remove trailing space to send clean data to callback */ } } wordCount = sscanf(data, "%d %d %d", &color, &type, &subtype); if (wordCount != 3) { LOG(LOG_WARNING, "common::DrawExtInfoCmd", "Wrong parameters received. Could only parse %d out of 3 int in %s", wordCount, data); return; } fnct = getTextManager(type); if (fnct == NULL) { LOG(LOG_WARNING, "common::DrawExtInfoCmd", "Server send us a type %d but i can't find any callback for it", type); return; } fnct(color, type, subtype, buf); } /** * Maintain the last_used_skills LRU list for displaying the recently used * skills first. * * @param skill_id */ void use_skill(int skill_id) { int i = 0; int next; int prev = last_used_skills[0]; if(last_used_skills[0] == skill_id) { return; } do { next = last_used_skills[i+1]; last_used_skills[i+1] = prev; prev = next; ++i; } while(next != skill_id && next >= 0); last_used_skills[0] = skill_id; } /** * Updates the local copy of the stats and displays it. * * @param data * @param len */ void StatsCmd(unsigned char *data, int len) { int i = 0, c, redraw = 0; gint64 last_exp; while (i < len) { c = data[i++]; if (c >= CS_STAT_RESIST_START && c <= CS_STAT_RESIST_END) { cpl.stats.resists[c-CS_STAT_RESIST_START] = GetShort_String(data+i); i += 2; cpl.stats.resist_change = 1; } else if (c >= CS_STAT_SKILLINFO && c < (CS_STAT_SKILLINFO+CS_NUM_SKILLS)) { /* We track to see if the exp has gone from 0 to some total value * - we do this because the draw logic currently only draws skills * where the player has exp. We need to communicate to the draw * function that it should draw all the players skills. Using * redraw is a little overkill, because a lot of the data may not * be changing. OTOH, such a transition should only happen * rarely, not not be a very big deal. */ cpl.stats.skill_level[c-CS_STAT_SKILLINFO] = data[i++]; last_exp = cpl.stats.skill_exp[c-CS_STAT_SKILLINFO]; cpl.stats.skill_exp[c-CS_STAT_SKILLINFO] = GetInt64_String(data+i); use_skill(c-CS_STAT_SKILLINFO); if (last_exp == 0 && cpl.stats.skill_exp[c-CS_STAT_SKILLINFO]) { redraw = 1; } i += 8; } else { switch (c) { case CS_STAT_HP: cpl.stats.hp = GetShort_String(data+i); i += 2; break; case CS_STAT_MAXHP: cpl.stats.maxhp = GetShort_String(data+i); i += 2; break; case CS_STAT_SP: cpl.stats.sp = GetShort_String(data+i); i += 2; break; case CS_STAT_MAXSP: cpl.stats.maxsp = GetShort_String(data+i); i += 2; break; case CS_STAT_GRACE: cpl.stats.grace = GetShort_String(data+i); i += 2; break; case CS_STAT_MAXGRACE: cpl.stats.maxgrace = GetShort_String(data+i); i += 2; break; case CS_STAT_STR: cpl.stats.Str = GetShort_String(data+i); i += 2; break; case CS_STAT_INT: cpl.stats.Int = GetShort_String(data+i); i += 2; break; case CS_STAT_POW: cpl.stats.Pow = GetShort_String(data+i); i += 2; break; case CS_STAT_WIS: cpl.stats.Wis = GetShort_String(data+i); i += 2; break; case CS_STAT_DEX: cpl.stats.Dex = GetShort_String(data+i); i += 2; break; case CS_STAT_CON: cpl.stats.Con = GetShort_String(data+i); i += 2; break; case CS_STAT_CHA: cpl.stats.Cha = GetShort_String(data+i); i += 2; break; case CS_STAT_EXP: cpl.stats.exp = GetInt_String(data+i); i += 4; break; case CS_STAT_EXP64: cpl.stats.exp = GetInt64_String(data+i); i += 8; break; case CS_STAT_LEVEL: cpl.stats.level = GetShort_String(data+i); i += 2; break; case CS_STAT_WC: cpl.stats.wc = GetShort_String(data+i); i += 2; break; case CS_STAT_AC: cpl.stats.ac = GetShort_String(data+i); i += 2; break; case CS_STAT_DAM: cpl.stats.dam = GetShort_String(data+i); i += 2; break; case CS_STAT_ARMOUR: cpl.stats.resists[0] = GetShort_String(data+i); i += 2; break; case CS_STAT_SPEED: cpl.stats.speed = GetInt_String(data+i); i += 4; break; case CS_STAT_FOOD: cpl.stats.food = GetShort_String(data+i); i += 2; break; case CS_STAT_WEAP_SP: cpl.stats.weapon_sp = GetInt_String(data+i); i += 4; break; case CS_STAT_SPELL_ATTUNE: cpl.stats.attuned = GetInt_String(data+i); i += 4; cpl.spells_updated = 1; break; case CS_STAT_SPELL_REPEL: cpl.stats.repelled = GetInt_String(data+i); i += 4; cpl.spells_updated = 1; break; case CS_STAT_SPELL_DENY: cpl.stats.denied = GetInt_String(data+i); i += 4; cpl.spells_updated = 1; break; case CS_STAT_FLAGS: cpl.stats.flags = GetShort_String(data+i); i += 2; break; case CS_STAT_WEIGHT_LIM: set_weight_limit(cpl.stats.weight_limit = GetInt_String(data+i)); i += 4; /* Mark weight limit changes to update the client inventory window */ cpl.ob->inv_updated = 1; break; case CS_STAT_RANGE: { int rlen = data[i++]; strncpy(cpl.range, (const char*)data+i, rlen); cpl.range[rlen] = '\0'; i += rlen; break; } case CS_STAT_TITLE: { int rlen = data[i++]; strncpy(cpl.title, (const char*)data+i, rlen); cpl.title[rlen] = '\0'; i += rlen; break; } default: LOG(LOG_WARNING, "common::StatsCmd", "Unknown stat number %d", c); break; } } } if (i > len) { LOG(LOG_WARNING, "common::StatsCmd", "got stats overflow, processed %d bytes out of %d", i, len); } draw_stats(redraw); draw_message_window(0); #ifdef HAVE_LUA script_lua_stats(); #endif } /** * Prompts the user for input. * * @param data * @param len */ void handle_query(char *data, int len) { char *buf, *cp; guint8 flags = atoi(data); (void)len; /* __UNUSED__ */ if (flags&CS_QUERY_HIDEINPUT) { /* No echo */ cpl.no_echo = 1; } else { cpl.no_echo = 0; } /* Let the window system know this may have changed */ x_set_echo(); /* The actual text is optional */ buf = strchr(data, ' '); if (buf) { buf++; } /* If we just get passed an empty string, why draw this? */ if (buf) { cp = buf; while ((buf = strchr(buf, '\n')) != NULL) { *buf++ = '\0'; draw_ext_info( NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_QUERY, cp); cp = buf; } /* Yes/no - don't do anything with it now */ if (flags&CS_QUERY_YESNO) { } /* One character response expected */ if (flags&CS_QUERY_SINGLECHAR) { cpl.input_state = Reply_One; } else { cpl.input_state = Reply_Many; } if (cp) { draw_prompt(cp); } } LOG(LOG_DEBUG, "common::handle_query", "Received query. Input state now %d", cpl.input_state); } /** * Sends a reply to the server. This function basically just packs the stuff * up. * * @param text contains the null terminated string of text to send. */ void send_reply(const char *text) { cs_print_string(csocket.fd, "reply %s", text); /* Let the window system know that the (possibly hidden) query is over. */ cpl.no_echo = 0; x_set_echo(); } /** * Gets the player information. This function copies relevant data from the * archetype to the object. Only copies data that was not set in the object * structure. * * @param data * @param len */ void PlayerCmd(unsigned char *data, int len) { char name[MAX_BUF]; int tag, weight, face, i = 0, nlen; reset_player_data(); tag = GetInt_String(data); i += 4; weight = GetInt_String(data+i); i += 4; face = GetInt_String(data+i); i += 4; nlen = data[i++]; memcpy(name, (const char*)data+i, nlen); name[nlen] = '\0'; i += nlen; if (i != len) { LOG(LOG_WARNING, "common::PlayerCmd", "lengths do not match (%d!=%d)", len, i); } new_player(tag, name, weight, face); } /** * * @param op */ void item_actions(item *op) { if (!op) { return; } if (op->open) { open_container(op); cpl.container = op; } else if (op->was_open) { close_container(op); cpl.container = NULL; } } /** * Parses the data sent to us from the server. revision is what item command * the data came from - newer ones have addition fields. * @param data * @param len */ void Item2Cmd(unsigned char *data, int len) { int weight, loc, tag, face, flags, pos = 0, nlen, anim, nrof, type; guint8 animspeed; char name[MAX_BUF]; loc = GetInt_String(data); pos += 4; if (pos == len) { LOG(LOG_WARNING, "common::common_item_command", "Got location with no other data"); return; } else if (loc < 0) { /* Delete following items */ LOG(LOG_WARNING, "common::common_item_command", "Got location with negative value (%d)", loc); return; } else { while (pos < len) { tag = GetInt_String(data+pos); pos += 4; flags = GetInt_String(data+pos); pos += 4; weight = GetInt_String(data+pos); pos += 4; face = GetInt_String(data+pos); pos += 4; nlen = data[pos++]; memcpy(name, (char*)data+pos, nlen); pos += nlen; name[nlen] = '\0'; anim = GetShort_String(data+pos); pos += 2; animspeed = data[pos++]; nrof = GetInt_String(data+pos); pos += 4; type = GetShort_String(data+pos); pos += 2; update_item(tag, loc, name, weight, face, flags, anim, animspeed, nrof, type); item_actions(locate_item(tag)); } if (pos > len) { LOG(LOG_WARNING, "common::common_item_cmd", "Overread buffer: %d > %d", pos, len); } } } /** * Updates some attributes of an item * * @param data * @param len */ void UpdateItemCmd(unsigned char *data, int len) { int weight, loc, tag, face, sendflags, flags, pos = 0, nlen, anim; guint32 nrof; char name[MAX_BUF]; item *ip; guint8 animspeed; sendflags = data[0]; pos += 1; tag = GetInt_String(data+pos); pos += 4; ip = locate_item(tag); if (!ip) { /* fprintf(stderr, "Got update_item command for item we don't have (%d)\n", tag); */ return; } /* Copy all of these so we can pass the values to update_item and don't * need to figure out which ones were modified by this function. */ *name = '\0'; loc = ip->env ? ip->env->tag : 0; weight = ip->weight*1000; face = ip->face; flags = ip->flagsval; anim = ip->animation_id; animspeed = ip->anim_speed; nrof = ip->nrof; if (sendflags&UPD_LOCATION) { loc = GetInt_String(data+pos); LOG(LOG_WARNING, "common::UpdateItemCmd", "Got tag of unknown object (%d) for new location", loc); pos += 4; } if (sendflags&UPD_FLAGS) { flags = GetInt_String(data+pos); pos += 4; } if (sendflags&UPD_WEIGHT) { weight = GetInt_String(data+pos); pos += 4; } if (sendflags&UPD_FACE) { face = GetInt_String(data+pos); pos += 4; } if (sendflags&UPD_NAME) { nlen = data[pos++]; memcpy(name, (char*)data+pos, nlen); pos += nlen; name[nlen] = '\0'; } if (pos > len) { LOG(LOG_WARNING, "common::UpdateItemCmd", "Overread buffer: %d > %d", pos, len); return; /* We have bad data, probably don't want to store it then */ } if (sendflags&UPD_ANIM) { anim = GetShort_String(data+pos); pos += 2; } if (sendflags&UPD_ANIMSPEED) { animspeed = data[pos++]; } if (sendflags&UPD_NROF) { nrof = (guint32)GetInt_String(data+pos); pos += 4; } /* update_item calls set_item_values which will then set the list redraw * flag, so we don't need to do an explicit redraw here. Actually, * calling update_item is a little bit of overkill, since we already * determined some of the values in this function. */ update_item(tag, loc, name, weight, face, flags, anim, animspeed, nrof, ip->type); item_actions(locate_item(tag)); } /** * * @param data * @param len */ void DeleteItem(unsigned char *data, int len) { int pos = 0, tag; while (pos < len) { item *op; tag = GetInt_String(data+pos); pos += 4; op = locate_item(tag); if (op != NULL) { remove_item(op); } else { LOG(LOG_WARNING, "common::DeleteItem", "Cannot find tag %d", tag); } } if (pos > len) { LOG(LOG_WARNING, "common::DeleteItem", "Overread buffer: %d > %d", pos, len); } } /** * * @param data * @param len */ void DeleteInventory(unsigned char *data, int len) { int tag; item *op; (void)len; /* __UNUSED__ */ tag = atoi((const char*)data); op = locate_item(tag); if (op != NULL) { remove_item_inventory(op); } else { LOG(LOG_WARNING, "common::DeleteInventory", "Invalid tag: %d", tag); } } /** * Remove trailing newlines from the given C string in-place. */ static void rstrip(char buf[static 1], size_t len) { for (size_t i = len - 1; i > 0; i--) { if (buf[i] == '\n' || buf[i] == ' ') { buf[i] = '\0'; } else { return; } } } /****************************************************************************/ /** * @defgroup SCSpellCommands Server->Client spell command functions. * @{ */ /** * * @param data * @param len */ void AddspellCmd(unsigned char *data, int len) { guint8 nlen; guint16 mlen, pos = 0; Spell *newspell, *tmp; while (pos < len) { newspell = calloc(1, sizeof(Spell)); /* Get standard spell information (spellmon 1) */ newspell->tag = GetInt_String(data+pos); pos += 4; newspell->level = GetShort_String(data+pos); pos += 2; newspell->time = GetShort_String(data+pos); pos += 2; newspell->sp = GetShort_String(data+pos); pos += 2; newspell->grace = GetShort_String(data+pos); pos += 2; newspell->dam = GetShort_String(data+pos); pos += 2; newspell->skill_number = GetChar_String(data+pos); pos += 1; newspell->path = GetInt_String(data+pos); pos += 4; newspell->face = GetInt_String(data+pos); pos += 4; nlen = GetChar_String(data+pos); pos += 1; strncpy(newspell->name, (char*)data+pos, nlen); pos += nlen; newspell->name[nlen] = '\0'; /* To ensure we are null terminated */ mlen = GetShort_String(data+pos); pos += 2; strncpy(newspell->message, (char*)data+pos, mlen); pos += mlen; newspell->message[mlen] = '\0'; /* To ensure we are null terminated */ rstrip(newspell->message, mlen); if (spellmon_level < 2) { /* The server is not sending spellmon 2 extended information, so * initialize the spell data fields as unused/empty. */ newspell->usage = 0; newspell->requirements[0] = '\0'; } else if (pos < len) { /* The server is sending extended spell information (spellmon 2) so * process it. */ newspell->usage = GetChar_String(data+pos); pos += 1; nlen = GetChar_String(data+pos); pos += 1; strncpy(newspell->requirements, (char*) data+pos, nlen); pos += nlen; newspell->requirements[nlen] = '\0'; /* Ensure null-termination */ } /* Compute the derived spell information. */ newspell->skill = skill_names[newspell->skill_number-CS_STAT_SKILLINFO]; /* Add the spell to the player struct. */ if (!cpl.spelldata) { cpl.spelldata = newspell; } else { for (tmp = cpl.spelldata; tmp->next; tmp = tmp->next) ; tmp->next = newspell; } /* Check to see if there are more spells to add. */ } if (pos > len) { LOG(LOG_WARNING, "common::AddspellCmd", "Overread buffer: %d > %d", pos, len); } cpl.spells_updated = 1; } void UpdspellCmd(unsigned char *data, int len) { int flags, pos = 0; guint32 tag; Spell *tmp; if (!cpl.spelldata) { LOG(LOG_WARNING, "common::UpdspellCmd", "I know no spells to update"); return; } flags = GetChar_String(data+pos); pos += 1; tag = GetInt_String(data+pos); pos += 4; for (tmp = cpl.spelldata; tmp && tmp->tag != tag; tmp = tmp->next) ; if (!tmp) { LOG(LOG_WARNING, "common::UpdspellCmd", "Invalid tag: %d", tag); return; } if (flags&UPD_SP_MANA) { tmp->sp = GetShort_String(data+pos); pos += 2; } if (flags&UPD_SP_GRACE) { tmp->grace = GetShort_String(data+pos); pos += 2; } if (flags&UPD_SP_DAMAGE) { tmp->dam = GetShort_String(data+pos); pos += 2; } if (pos > len) { LOG(LOG_WARNING, "common::UpdspellCmd", "Overread buffer: %d > %d", pos, len); } cpl.spells_updated = 1; } void DeleteSpell(unsigned char *data, int len) { guint32 tag; Spell *tmp, *target; if (!cpl.spelldata) { LOG(LOG_WARNING, "common::DeleteSpell", "I know no spells to delete"); return; } tag = GetInt_String(data); /* Special case: the first spell is the one removed */ if (cpl.spelldata->tag == tag) { target = cpl.spelldata; if (target->next) { cpl.spelldata = target->next; } else { cpl.spelldata = NULL; } free(target); return; } for (tmp = cpl.spelldata; tmp->next && tmp->next->tag != tag; tmp = tmp->next) ; if (!tmp->next) { LOG(LOG_WARNING, "common::DeleteSpell", "Invalid tag: %d", tag); return; } target = tmp->next; if (target->next) { tmp->next = target->next; } else { tmp->next = NULL; } free(target); cpl.spells_updated = 1; } /****************************************************************************/ /** * @} */ /* EndOf SCSpellCommands */ /** * @defgroup SCMapCommands Server->Client map command functions. * @{ */ /** * * @param data * @param len */ void NewmapCmd(unsigned char *data, int len) { (void)data; /* __UNUSED__ */ (void)len; /* __UNUSED__ */ mapdata_newmap(); } /* This is the common processing block for the map1 and map1a protocol * commands. The map1a mieks minor extensions and are easy to deal with * inline (in fact, this code doesn't even care what rev is - just certain * bits will only bet set when using the map1a command. rev is 0 for map1, 1 * for map1a. It conceivable that there could be future revisions. */ /* NUM_LAYERS should only be used for the map1{a} which only has a few layers. * Map2 has 10 layers. However, some of the map1 logic requires this to be * set right. */ #define NUM_LAYERS (MAP1_LAYERS-1) /** * * @param data * @param len */ void Map2Cmd(unsigned char *data, int len) { int mask, x, y, pos = 0, space_len, value; guint8 type; /* Not really using map1 protocol, but some draw logic differs from the * original draw logic, and map2 is closest. */ while (pos < len) { mask = GetShort_String(data+pos); pos += 2; x = ((mask>>10)&0x3f)-MAP2_COORD_OFFSET; y = ((mask>>4)&0x3f)-MAP2_COORD_OFFSET; /* This is a scroll then. Go back and fetch another coordinate */ if (mask&0x1) { mapdata_scroll(x, y); continue; } if (x<0) { LOG(LOG_WARNING, "commands.c::Map2Cmd", "got negative x!"); x = 0; } else if (x >= MAX_VIEW) { LOG(LOG_WARNING, "commands.c::Map2Cmd", "got x >= MAX_VIEW!"); x = MAX_VIEW - 1; } if (y<0) { LOG(LOG_WARNING, "commands.c::Map2Cmd", "got negative y!"); y = 0; } else if (y >= MAX_VIEW) { LOG(LOG_WARNING, "commands.c::Map2Cmd", "got y >= MAX_VIEW!"); y = MAX_VIEW - 1; } assert(0 <= x && x < MAX_VIEW); assert(0 <= y && y < MAX_VIEW); /* Clearing old cell data as needed (was in mapdata_set_face_layer() * before however that caused darkness to only work if sent after the * layers). */ mapdata_clear_old(x, y); /* Inner loop is for the data on the space itself */ while (pos < len) { type = data[pos++]; /* type == 255 means nothing more for this space */ if (type == 255) { mapdata_set_check_space(x, y); break; } space_len = type>>5; type &= 0x1f; /* Clear the space */ if (type == MAP2_TYPE_CLEAR) { mapdata_clear_space(x, y); continue; } else if (type == MAP2_TYPE_DARKNESS) { value = data[pos++]; mapdata_set_darkness(x, y, value); continue; } else if (type >= MAP2_LAYER_START && type < MAP2_LAYER_START+MAXLAYERS) { int layer, opt; /* This is face information for a layer. */ layer = type&0xf; if (layer < 0) { LOG(LOG_WARNING, "commands.c::Map2Cmd", "got negative layer!"); layer = 0; } else if (layer >= MAXLAYERS) { LOG(LOG_WARNING, "commands.c::Map2Cmd", "got layer >= MAXLAYERS!"); layer = MAXLAYERS - 1; } assert(0 <= layer && layer < MAXLAYERS); /* This is the face */ value = GetShort_String(data+pos); pos += 2; if (!(value&FACE_IS_ANIM)) { mapdata_set_face_layer(x, y, value, layer); } if (space_len > 2) { opt = data[pos++]; if (value&FACE_IS_ANIM) { /* Animation speed */ mapdata_set_anim_layer(x, y, value, opt, layer); } else { /* Smooth info */ mapdata_set_smooth(x, y, opt, layer); } } /* Currently, if 4 bytes, must be a smooth byte */ if (space_len > 3) { opt = data[pos++]; mapdata_set_smooth(x, y, opt, layer); } continue; } /* if image layer */ } /* while possmooth[layer] != newsm) { for (i = 0; i < 8; i++) { rx = x+dx[i]; ry = y+dy[i]; if (!mapdata_contains(rx, ry)) { continue; } mapdata_cell(x, y)->need_resmooth = 1; } } mapdata_cell(x, y)->smooth[layer] = newsm; return 1;/*Cause smooth infos only use 1 byte*/ } /** * Handle MapExtended command * Warning! if you add commands to extended, take care that the 'layer' * argument of main loop is the opposite of the layer of the map so if you * reference a layer, use NUM_LAYERS-layer. * * @param data * @param len */ void MapExtendedCmd(unsigned char *data, int len) { int mask, x, y, pos = 0, layer; int noredraw = 0; int hassmooth = 0; int entrysize; int startpackentry; mapupdatesent = 1; mask = GetChar_String(data+pos); pos += 1; if (mask&EMI_NOREDRAW) { noredraw = 1; } if (mask&EMI_SMOOTH) { hassmooth = 1; } while (mask&EMI_HASMOREBITS) { /*There may be bits we ignore about*/ mask = GetChar_String(data+pos); pos += 1; } entrysize = GetChar_String(data+pos); pos = pos+1; while (pos+entrysize+2 <= len) { mask = GetShort_String(data+pos); pos += 2; x = (mask>>10)&0x3f; y = (mask>>4)&0x3f; for (layer = NUM_LAYERS; layer >= 0; layer--) { if (mask&(1< len) { /*erroneous packet*/ break; } startpackentry = pos; /* If you had extended infos to the server, this is where, in * the client, you may add your code */ if (hassmooth) { pos = pos+ExtSmooth(data+pos, len-pos, x, y, NUM_LAYERS-layer); } /* Continue with other if you add new extended infos to server * * Now point to the next data */ pos = startpackentry+entrysize; } } } if (!noredraw) { display_map_doneupdate(FALSE, FALSE); mapupdatesent = 0; } } /** * * @param data * @param len */ void MagicMapCmd(unsigned char *data, int len) { unsigned char *cp; int i; /* First, extract the size/position information. */ if (sscanf((const char*)data, "%hd %hd %hd %hd", &cpl.mmapx, &cpl.mmapy, &cpl.pmapx, &cpl.pmapy) != 4) { LOG(LOG_WARNING, "common::MagicMapCmd", "Was not able to properly extract magic map size, pos"); return; } if (cpl.mmapx == 0 || cpl.mmapy == 0) { LOG(LOG_WARNING, "common::MagicMapCmd", "empty map"); return; } /* Now we need to find the start of the actual data. There are 4 space * characters we need to skip over. */ for (cp = data, i = 0; i < 4 && cp < data+len; cp++) { if (*cp == ' ') { i++; } } if (i != 4) { LOG(LOG_WARNING, "common::MagicMapCmd", "Was unable to find start of magic map data"); return; } i = len-(cp-data); /* This should be the number of bytes left */ if (i != cpl.mmapx*cpl.mmapy) { LOG(LOG_WARNING, "common::MagicMapCmd", "Magic map size mismatch. Have %d bytes, should have %d", i, cpl.mmapx*cpl.mmapy); return; } free(cpl.magicmap); cpl.magicmap = g_malloc(cpl.mmapx*cpl.mmapy); /* Order the server puts it in should be just fine. Note that the only * requirement that this works is that magicmap by 8 bits, being that is * the size specified in the protocol and what the server sends us. */ memcpy(cpl.magicmap, cp, cpl.mmapx*cpl.mmapy); draw_magic_map(); } /** * @} */ /* EndOf SCMapCommands */ /** * * @param data * @param len */ void SinkCmd(unsigned char *data, int len) { } /** * Got a tick from the server. We currently don't care what tick number it * is, but just have the code in case at some time we do. * * @param data * @param len */ void TickCmd(guint8 *data, int len) { /* Up to the specific client to decide what to do */ client_tick(GetInt_String(data)); } /** * Server gives us current player's pickup. * * @param data * buffer sent by server. * @param len * length of data. */ void PickupCmd(guint8 *data, int len) { guint32 pickup = GetInt_String(data); client_pickup(pickup); } /** * Handles a failure return from the server. * * @param buf * buffer sent by server. * @param len * length of data. */ void FailureCmd(char *buf, int len) { char *cp; /* The format of the buffer is 'command error message'. We need to * extract the failed command, and then pass in the error message to the * appropriate handler. So find the space, set it to null. in that way, * buf is now just the failure command, and cp is the message. */ cp = strchr(buf,' '); if (!cp) { return; } *cp = 0; cp++; if (!strcmp(buf,"accountlogin")) { account_login_failure(cp); } else if (!strcmp(buf,"accountnew")) { account_creation_failure(cp); } else if (!strcmp(buf,"accountaddplayer")) { account_add_character_failure(cp); } else if (!strcmp(buf,"createplayer")) { create_new_character_failure(cp); } else if (!strcmp(buf, "accountpw")) { account_change_password_failure(cp); } else if (!strcmp(buf, "accountplay")) { // This creates a dialog that says the failure message. // It should suffice for what we want here anyway. create_new_character_failure(cp); } else /* This really is an error - if this happens it menas the server * failed to process a request that the client made - the client * should be able to handle failures for all request types it makes. * But this is also a problem in that it means that the server is * waiting for a correct response, and if we do not display anything, * the player is unlikely to know this. */ LOG(LOG_ERROR, "common::FailureCmd", "Got a failure response we can not handle: %s:%s", buf, cp); } /** * This handles the accountplayers command */ void AccountPlayersCmd(char *buf, int len) { int level, pos, faceno; guint8 flen; char name[MAX_BUF], class[MAX_BUF], race[MAX_BUF], face[MAX_BUF], party[MAX_BUF], map[MAX_BUF]; /* This is called first so it can clear out the existing data store. */ choose_character_init(); level=0; name[0]=0; class[0]=0; race[0]=0; face[0]=0; party[0]=0; map[0]=0; faceno=0; pos=1; while (pos < len) { flen = buf[pos]; /* flen == 0 is to note that we got end of character data */ if (flen == 0) { update_character_choose(name, class, race, face, party, map, level, faceno); /* Blank all the values - it is no sure thing that the next * character will fill all these in. */ level=0; name[0]=0; class[0]=0; race[0]=0; face[0]=0; party[0]=0; map[0]=0; faceno=0; pos++; continue; } pos++; if ((pos +flen) > len || flen>=MAX_BUF) { LOG(LOG_ERROR,"commands.c:AccountPlayerCmd", "data overran buffer"); return; } switch (buf[pos]) { case ACL_NAME: strncpy(name, buf + pos +1, flen-1); name[flen-1] = 0; break; case ACL_CLASS: strncpy(class, buf + pos +1, flen-1); class[flen-1] = 0; break; case ACL_RACE: strncpy(race, buf + pos +1, flen-1); race[flen-1] = 0; break; case ACL_FACE: strncpy(face, buf + pos +1, flen-1); face[flen-1] = 0; break; case ACL_PARTY: strncpy(party, buf + pos +1, flen-1); party[flen-1] = 0; break; case ACL_MAP: strncpy(map, buf + pos +1, flen-1); map[flen-1] = 0; break; case ACL_LEVEL: level = GetShort_String((unsigned char *)buf + pos + 1); break; case ACL_FACE_NUM: faceno = GetShort_String((unsigned char *)buf + pos + 1); break; } pos += flen; } } crossfire-client-1.75.3/common/msgtypes.pl000755 001751 001751 00000004206 14045044330 021444 0ustar00kevinzkevinz000000 000000 #!/usr/bin/perl # # Copyright (C) 2007 Mark Wedel & Crossfire Development Team # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # The author can be reached via e-mail to crossfire-devel@real-time.com # # $ARGV[0] is the source directory. We need to know it for out of tree builds. use strict; open(IN,"<$ARGV[0]/shared/newclient.h") || die("Can not open newclient.h file\n"); open(OUT,">msgtypes.h") || die("Can not open msgtypes.h file\n"); print OUT "/* This file is automatically generated. Editing by hand is strongly */\n"; print OUT "/* discouraged. Look at the newclient.h file and the msgtypes.pl conversion */\n"; print OUT "/* script. */\n"; print OUT "\nconst Msg_Type_Names msg_type_names[] = {\n"; print OUT "{0, 0, \"generic\"},\n"; my $on_subtypes=0; my $last_type=0; my $type; my $lc; my @types; my $max_types; while() { if (/^#define\s+MSG_TYPE_(\S*)/) { if ($1 eq "LAST" || $1 eq "SUBTYPE_NONE") { $on_subtypes=1; next; } $type = $1; $lc = $1; $lc =~ tr /A-Z/a-z/; if (! $on_subtypes) { $types[$max_types++] = $1; print OUT "{MSG_TYPE_$1, 0, \"$lc\"},\n"; } else { if ($type !~ /^$types[$last_type]/ ) { my $i; for ($i=0; $i< $max_types; $i++) { if ($type =~ /^$types[$i]/) { $last_type=$i; last; } } if ($i == $max_types) { print STDERR "Unable to find right type for $type\n"; } } print OUT "{MSG_TYPE_$types[$last_type], MSG_TYPE_$type, \"$lc\"},\n"; } } } close(IN); print OUT "};\n"; close(OUT); crossfire-client-1.75.3/common/metaserver.c000644 001751 001751 00000022364 14045044330 021557 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Deals with contacting the metaserver, getting a list of hosts, displaying * and returning them to calling function, and then connecting to the server * when requested. */ #include "client.h" #ifdef HAVE_CURL_CURL_H #include #endif #include "metaserver.h" /* list of metaserver URL to get information from - this should generally * correspond to the value in the metaserver2 server file, but instead * of meta_update.php, use meta_client.php. * * These could perhaps be in some other file (config.h or the like), but * it seems unlikely that these will change very often, and certainly not * at a level where we would expect users to go about changing the values. */ static const char *metaservers[] = { "http://crossfire.real-time.com/metaserver2/meta_client.php", "http://metaserver.eu.cross-fire.org/meta_client.php", "http://metaserver.us.cross-fire.org/meta_client.php", }; /** * Memory buffer used in write_mbuf(). */ struct mbuf { char *memory; size_t size; }; /** * Curl write callback function for downloading data into memory instead of * a file. Copied from Curl's 'getinmemory.c' example under the MIT License. */ static size_t mbuf_write(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct mbuf *mem = (struct mbuf *)userp; mem->memory = realloc(mem->memory, mem->size + realsize + 1); if (mem->memory == NULL) { /* out of memory! */ printf("not enough memory (realloc returned NULL)\n"); return 0; } memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } /** * This checks the servers sc_version and cs_version to see * if they are compatible. * @param entry * entry number in the metaservers array to check. * @return * 1 if this entry is compatible, 0 if it is not. Note that this can * only meaningfully check metaserver2 data - metaserver1 doesn't * include protocol version number, so treats all of those as * OK. */ static bool ms_check_version(Meta_Info *server) { /* No version information - nothing to do. */ if (!server->sc_version || !server->cs_version) { return true; } if (server->sc_version != VERSION_SC) { /* 1027->1028 removed a bunch of old commands, so a 1028 * version client can still play on a 1027 server, so * special hard code that. * * Likewise, 1028->1029 just changed how weapon_speed * should be interperted on the client - the client * does the right thing, so not problem with a 1029 * client playing on 1028 or 1027 server. * * A 1028 client could in practice play on a 1029 * server, since at the protocol level, data is the same - * the client would just have screwed up weapon_sp values. */ if ((VERSION_SC == 1028 || VERSION_SC == 1029) && (server->sc_version == 1027 || server->sc_version == 1028)) { return true; } } if (server->cs_version != VERSION_CS) { return false; } return true; } static void parse_meta(char inbuf[static 1], ms_callback callback) { Meta_Info metaserver; char *newline; for (char *cp = inbuf; cp != NULL && *cp != 0; cp = newline) { newline = strchr(cp, '\n'); if (newline) { *newline = 0; newline++; } else { /* If we didn't get a newline, then this is the * end of the block of data for this call - store * away the extra for the next call. */ // Can no longer happen after removing ms_writer(). return; } char *eq = strchr(cp, '='); if (eq) { *eq = 0; eq++; } if (!strcmp(cp, "START_SERVER_DATA")) { /* Clear out all data - MS2 doesn't necessarily use all the * fields, so blank out any that we are not using. */ memset(&metaserver, 0, sizeof (Meta_Info)); } else if (!strcmp(cp, "END_SERVER_DATA")) { char buf[MS_LARGE_BUF]; // If server is running custom port, add it to server name. if (metaserver.port != EPORT) { snprintf(buf, sizeof(buf), "%s:%d", metaserver.hostname, metaserver.port); } else { snprintf(buf, sizeof(buf), "%s", metaserver.hostname); } callback(buf, metaserver.idle_time, metaserver.num_players, metaserver.version, metaserver.text_comment, ms_check_version(&metaserver)); } else { /* If we get here, these should be variable=value pairs. * if we don't have a value, can't do anything, and * report an error. This would normally be incorrect * data from the server. */ if (!eq) { fprintf(stderr, "parse_meta: unknown line '%s'\n", cp); continue; } if (!strcmp(cp, "hostname")) { strncpy(metaserver.hostname, eq, sizeof (metaserver.hostname)); } else if (!strcmp(cp, "port")) { metaserver.port = atoi(eq); } else if (!strcmp(cp, "html_comment")) { strncpy(metaserver.html_comment, eq, sizeof (metaserver.html_comment)); } else if (!strcmp(cp, "text_comment")) { strncpy(metaserver.text_comment, eq, sizeof (metaserver.text_comment)); } else if (!strcmp(cp, "archbase")) { strncpy(metaserver.archbase, eq, sizeof (metaserver.archbase)); } else if (!strcmp(cp, "mapbase")) { strncpy(metaserver.mapbase, eq, sizeof (metaserver.mapbase)); } else if (!strcmp(cp, "codebase")) { strncpy(metaserver.codebase, eq, sizeof (metaserver.codebase)); } else if (!strcmp(cp, "flags")) { strncpy(metaserver.flags, eq, sizeof (metaserver.flags)); } else if (!strcmp(cp, "version")) { strncpy(metaserver.version, eq, sizeof (metaserver.version)); } else if (!strcmp(cp, "num_players")) { metaserver.num_players = atoi(eq); } else if (!strcmp(cp, "in_bytes")) { metaserver.in_bytes = atoi(eq); } else if (!strcmp(cp, "out_bytes")) { metaserver.out_bytes = atoi(eq); } else if (!strcmp(cp, "uptime")) { metaserver.uptime = atoi(eq); } else if (!strcmp(cp, "sc_version")) { metaserver.sc_version = atoi(eq); } else if (!strcmp(cp, "cs_version")) { metaserver.cs_version = atoi(eq); } else if (!strcmp(cp, "last_update")) { /* MS2 reports update time as when it last got an update, * where as we want actual elapsed time since last update. * So do the conversion. Second check is because of clock * skew - my clock may be fast, and we don't want negative times. */ metaserver.idle_time = time(NULL) - atoi(eq); if (metaserver.idle_time < 0) { metaserver.idle_time = 0; } } else { fprintf(stderr, "parse_meta: unknown line '%s=%s'\n", cp, eq); } } } } /** * Fetch a list of servers from the given URL. * * @param metaserver2 * @return */ static bool ms_fetch_server(const char *metaserver2, ms_callback callback) { #ifdef HAVE_CURL_CURL_H CURL *curl = curl_easy_init(); if (!curl) { return false; } struct mbuf chunk; chunk.memory = malloc(1); chunk.size = 0; if (!chunk.memory) { abort(); } curl_easy_setopt(curl, CURLOPT_URL, metaserver2); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, mbuf_write); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); if (!res) { parse_meta(chunk.memory, callback); } free(chunk.memory); return !res; #else return true; #endif } /** * Initialize metaserver client. This function should be called before any * other metaserver functions. */ void ms_init() { #ifdef HAVE_CURL_CURL_H curl_global_init(CURL_GLOBAL_ALL); #endif } /** * Fetch a list of servers from the built-in official metaservers. * * Because this function can query multiple metaservers, the same servers may * be listed multiple times in the results. */ void ms_fetch(ms_callback callback) { for (size_t i = 0; i < sizeof(metaservers) / sizeof(char *); i++) { ms_fetch_server(metaservers[i], callback); } } crossfire-client-1.75.3/common/item.c000644 001751 001751 00000046300 14347663040 020346 0ustar00kevinzkevinz000000 000000 /* * Crossfire -- cooperative multi-player graphical RPG and adventure game * * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team * Copyright (c) 1992 Frank Tore Johansen * * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are * welcome to redistribute it under certain conditions. For details, please * see COPYING and LICENSE. * * The authors can be reached via e-mail at . */ /** * @file * Provides functions that process items in various ways. */ #include "client.h" #include /* needed for isdigit */ #include "external.h" #include "item.h" #include "script.h" static item *player, *map; /* these lists contains rest of items */ /* player = pl->ob, map = pl->below */ #include "item-types.h" /* This uses the item_types table above. We try to figure out if * name has a match above. Matching is done pretty loosely - however * we try to match the start of the name because that is more reliable. * We return the 'type' (matching array element above), 255 if no match * (so unknown objects put at the end) */ guint8 get_type_from_name(const char *name) { int type, pos; for (type = 0; type < NUM_ITEM_TYPES; type++) { pos = 0; while (item_types[type][pos] != NULL) { /* Only search at start of line */ if (item_types[type][pos][0] == '^') { if (!g_ascii_strncasecmp(name, item_types[type][pos]+1, strlen(item_types[type][pos]+1))) { return type; } } /* String anywhere in name */ else if (strstr(name, item_types[type][pos]) != NULL) { #if 0 fprintf(stderr, "Returning type %d for %s\n", type, name); #endif return type; } pos++; } } LOG(LOG_WARNING, "common::get_type_from_name", "Could not find match for %s", name); return 255; } /* Does what is says - inserts newitem before the object. * the parameters can not be null */ static void insert_item_before_item(item *newitem, item *before) { if (before->prev) { before->prev->next = newitem; } else { newitem->env->inv = newitem; } newitem->prev = before->prev; before->prev = newitem; newitem->next = before; if (newitem->env) { newitem->env->inv_updated = 1; } } /* Item it has gotten an item type, so we need to resort its location */ void update_item_sort(item *it) { item *itmp, *last = NULL; /* If not in some environment or the map, return */ /* Sorting on the map doesn't work. In theory, it would be nice, * but the server really must know the map order for things to * work. */ if (!it->env || it->env == it || it->env == map) { return; } /* If we are already sorted properly, don't do anything further. * this is prevents the order of the inventory from changing around * if you just equip something. */ if (it->prev && it->prev->type == it->type && it->prev->locked == it->locked && !g_ascii_strcasecmp(it->prev->s_name, it->s_name)) { return; } if (it->next && it->next->type == it->type && it->next->locked == it->locked && !g_ascii_strcasecmp(it->next->s_name, it->s_name)) { return; } /* Remove this item from the list */ if (it->prev) { it->prev->next = it->next; } if (it->next) { it->next->prev = it->prev; } if (it->env->inv == it) { it->env->inv = it->next; } for (itmp = it->env->inv; itmp != NULL; itmp = itmp->next) { last = itmp; /* If the next item is higher in the order, insert here */ if (itmp->type > it->type) { insert_item_before_item(it, itmp); return; } else if (itmp->type == it->type) { #if 0 /* This could be a nice idea, but doesn't work very well if you * have a few unidentified wands, as the position of a wand * which you know the effect will move around as you equip others. */ /* Hmm. We can actually use the tag value of the items to reduce * this a bit - do this by grouping, but if name is equal, then * sort by tag. Needs further investigation. */ /* applied items go first */ if (itmp->applied) { continue; } /* put locked items before others */ if (itmp->locked && !it->locked) { continue; } #endif /* Now alphabetise */ if (g_ascii_strcasecmp(itmp->s_name, it->s_name) < 0) { continue; } /* IF we got here, it means it passed all our sorting tests */ insert_item_before_item(it, itmp); return; } } /* No match - put it at the end */ /* If there was a previous item, update pointer. IF no previous * item, we need to update the environment to point to us */ if (last) { last->next = it; } else { it->env->inv = it; } it->prev = last; it->next = NULL; } /* Stolen from common/item.c */ /* * get_number(integer) returns the text-representation of the given number * in a static buffer. The buffer might be overwritten at the next * call to get_number(). * It is currently only used by the query_name() function. */ const char *get_number(guint32 i) { static const char *numbers[] = { "no", "a", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", }; static char buf[MAX_BUF]; if (i <= 20) { return numbers[i]; } else { snprintf(buf, sizeof(buf), "%u", i); return buf; } } /* * new_item() returns pointer to new item which * is allocated and initialized correctly */ static item *new_item(void) { item *op = g_malloc(sizeof(item)); if (!op) { exit(0); } op->next = op->prev = NULL; copy_name(op->d_name, ""); copy_name(op->s_name, ""); copy_name(op->p_name, ""); op->inv = NULL; op->env = NULL; op->tag = 0; op->face = 0; op->weight = 0; op->magical = op->cursed = op->damned = op->blessed = 0; op->unpaid = op->locked = op->applied = 0; op->flagsval = 0; op->animation_id = 0; op->last_anim = 0; op->anim_state = 0; op->nrof = 0; op->open = 0; op->type = NO_ITEM_TYPE; op->inv_updated = 0; return op; } /* * free_items() frees all allocated items from list */ void free_all_items(item *op) { item *tmp; while (op) { if (op->inv) { free_all_items(op->inv); } tmp = op->next; free(op); op = tmp; } } /* * Recursive function, used by locate_item() */ static item *locate_item_from_item(item *op, gint32 tag) { item *tmp; for (; op; op = op->next) { if (op->tag == tag) { return op; } else if (op->inv && (tmp = locate_item_from_item(op->inv, tag))) { return tmp; } } return NULL; } /* * locate_item() returns pointer to the item which tag is given * as parameter or if item is not found returns NULL */ item *locate_item(gint32 tag) { item *op; if (tag == 0) { return map; } if ((op = locate_item_from_item(map->inv, tag)) != NULL) { return op; } if ((op = locate_item_from_item(player, tag)) != NULL) { return op; } if (cpl.container && cpl.container->tag == tag) { return cpl.container; } if (cpl.container && (op = locate_item_from_item(cpl.container->inv, tag)) != NULL) { return op; } return NULL; } /* * remove_item() inserts op the the list of free items * Note that it don't clear all fields in item */ void remove_item(item *op) { /* IF no op, or it is the player */ if (!op || op == player || op == map) { return; } item_event_item_deleting(op); op->env->inv_updated = 1; /* Do we really want to do this? */ if (op->inv && op != cpl.container) { remove_item_inventory(op); } if (op->prev) { op->prev->next = op->next; } else { op->env->inv = op->next; } if (op->next) { op->next->prev = op->prev; } if (cpl.container == op) { return; /* Don't free this! */ } g_free(op); } /* * remove_item_inventory() recursive frees items inventory */ void remove_item_inventory(item *op) { if (!op) { return; } item_event_container_clearing(op); op->inv_updated = 1; while (op->inv) { remove_item(op->inv); } } /* * add_item() adds item op to end of the inventory of item env */ static void add_item(item *env, item *op) { item *tmp; for (tmp = env->inv; tmp && tmp->next; tmp = tmp->next) ; op->next = NULL; op->prev = tmp; op->env = env; if (!tmp) { env->inv = op; } else { if (tmp->next) { tmp->next->prev = op; } tmp->next = op; } } /* * create_new_item() returns pointer to a new item, inserts it to env * and sets its tag field and clears locked flag (all other fields * are unitialized and may contain random values) */ static item *create_new_item(item *env, gint32 tag) { item *op; op = new_item(); op->tag = tag; op->locked = 0; if (env) { add_item(env, op); } return op; } /* * Hardcoded now, server could send these at initiation phase. */ static const char *const apply_string[] = { "", " (readied)", " (wielded)", " (worn)", " (active)", " (applied)", }; static void set_flag_string(item *op) { op->flags[0] = 0; if (op->locked) { strcat(op->flags, " *"); } if (op->apply_type) { if (op->apply_type < sizeof(apply_string)/sizeof(apply_string[0])) { strcat(op->flags, apply_string[op->apply_type]); } else { strcat(op->flags, " (undefined)"); } } if (op->open) { strcat(op->flags, " (open)"); } if (op->damned) { strcat(op->flags, " (damned)"); } if (op->cursed) { strcat(op->flags, " (cursed)"); } if (op->blessed) { strcat(op->flags, " (blessed)"); } if (op->magical) { strcat(op->flags, " (magic)"); } if (op->unpaid) { strcat(op->flags, " (unpaid)"); } if (op->read) { strcat(op->flags, " (read)"); } } static void get_flags(item *op, guint16 flags) { op->was_open = op->open; op->open = flags&F_OPEN ? 1 : 0; op->damned = flags&F_DAMNED ? 1 : 0; op->cursed = flags&F_CURSED ? 1 : 0; op->blessed = flags&F_BLESSED ? 1 : 0; op->magical = flags&F_MAGIC ? 1 : 0; op->unpaid = flags&F_UNPAID ? 1 : 0; op->applied = flags&F_APPLIED ? 1 : 0; op->locked = flags&F_LOCKED ? 1 : 0; op->read = flags&F_READ ? 1 : 0; op->flagsval = flags; op->apply_type = flags&F_APPLIED; set_flag_string(op); } void set_item_values(item *op, char *name, gint32 weight, guint16 face, guint16 flags, guint16 anim, guint16 animspeed, guint32 nrof, guint16 type) { int resort = 1; if (!op) { printf("Error in set_item_values(): item pointer is NULL.\n"); return; } /* Program always expect at least 1 object internall */ if (nrof == 0) { nrof = 1; } if (*name != '\0') { copy_name(op->s_name, name); /* Unfortunately, we don't get a length parameter, so we just have * to assume that if it is a new server, it is giving us two piece * names. */ if (csocket.sc_version >= 1024) { copy_name(op->p_name, name+strlen(name)+1); } else { /* If not new version, just use same for both */ copy_name(op->p_name, name); } /* Necessary so that d_name is updated below */ op->nrof = nrof+1; } else { resort = 0; /* no name - don't resort */ } if (op->nrof != nrof) { if (nrof != 1 ) { snprintf(op->d_name, sizeof(op->d_name), "%s %s", get_number(nrof), op->p_name); } else { strcpy(op->d_name, op->s_name); } op->nrof = nrof; } if (op->env) { op->env->inv_updated = 1; } op->weight = (float)weight/1000; op->face = face; op->animation_id = anim; op->anim_speed = animspeed; op->type = type; get_flags(op, flags); /* We don't sort the map, so lets not bother figuring out the * type. Likewiwse, only figure out item type if this * doesn't have a type (item2 provides us with a type */ if (op->env != map && op->type == NO_ITEM_TYPE) { op->type = get_type_from_name(op->s_name); } if (resort) { update_item_sort(op); } item_event_item_changed(op); } void toggle_locked(item *op) { SockList sl; guint8 buf[MAX_BUF]; if (op->env->tag == 0) { return; /* if item is on the ground, don't lock it */ } snprintf((char*)buf, sizeof(buf), "lock %d %d", !op->locked, op->tag); script_monitor_str((char*)buf); SockList_Init(&sl, buf); SockList_AddString(&sl, "lock "); SockList_AddChar(&sl, !op->locked); SockList_AddInt(&sl, op->tag); SockList_Send(&sl, csocket.fd); } void send_mark_obj(item *op) { SockList sl; guint8 buf[MAX_BUF]; if (op->env->tag == 0) { return; /* if item is on the ground, don't mark it */ } snprintf((char*)buf, sizeof(buf), "mark %d", op->tag); script_monitor_str((char*)buf); SockList_Init(&sl, buf); SockList_AddString(&sl, "mark "); SockList_AddInt(&sl, op->tag); SockList_Send(&sl, csocket.fd); } item *player_item (void) { player = new_item(); return player; } item *map_item (void) { map = new_item(); map->weight = -1; return map; } /* Upates an item with new attributes. */ void update_item(int tag, int loc, char *name, int weight, int face, int flags, int anim, int animspeed, guint32 nrof, int type) { /* Need to do some special handling if this is the player that is * being updated. */ if (player->tag == tag) { copy_name(player->d_name, name); /* I don't think this makes sense, as you can have * two players merged together, so nrof should always be one */ player->nrof = nrof; player->weight = (float)weight/1000; player->face = face; get_flags(player, flags); if (player->inv) { player->inv->inv_updated = 1; } player->animation_id = anim; player->anim_speed = animspeed; player->nrof = nrof; } else { item *ip = locate_item(tag), *env = locate_item(loc); if (ip && ip->env != env) { // If item moved, it's easier to remove and re-add than to update // everything that needs updating. remove_item(ip); ip = NULL; } if (ip == NULL) { ip = create_new_item(env, tag); } set_item_values(ip, name, weight, face, flags, anim, animspeed, nrof, type); } } /* * Prints players inventory, contain extra information for debugging purposes * This isn't pretty, but is only used for debugging, so it doesn't need to be. */ void print_inventory(item *op) { char buf[MAX_BUF]; char buf2[MAX_BUF]; item *tmp; static int l = 0; #if 0 int info_width = get_info_width(); #else /* A callback for a debugging command seems pretty pointless. If anything, * it may be more useful to dump this out to stderr */ int info_width = 40; #endif if (l == 0) { snprintf(buf, sizeof(buf), "%s's inventory (%d):", op->d_name, op->tag); snprintf(buf2, sizeof(buf2), "%-*s%6.1f kg", info_width-10, buf, op->weight); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_DEBUG, buf2); } l += 2; for (tmp = op->inv; tmp; tmp = tmp->next) { snprintf(buf, sizeof(buf), "%*s- %d %s%s (%d)", l-2, "", tmp->nrof, tmp->d_name, tmp->flags, tmp->tag); snprintf(buf2, sizeof(buf2), "%-*s%6.1f kg", info_width-8-l, buf, tmp->nrof*tmp->weight); draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_DEBUG, buf2); if (tmp->inv) { print_inventory(tmp); } } l -= 2; } /* Check the objects, animate the ones as necessary */ void animate_objects(void) { item *ip; int got_one = 0; /* Animate players inventory */ for (ip = player->inv; ip; ip = ip->next) { if (ip->animation_id > 0 && ip->anim_speed) { ip->last_anim++; if (ip->last_anim >= ip->anim_speed) { ip->anim_state++; if (ip->anim_state >= animations[ip->animation_id].num_animations) { ip->anim_state = 0; } ip->face = animations[ip->animation_id].faces[ip->anim_state]; ip->last_anim = 0; got_one = 1; } } } #ifndef GTK_CLIENT if (got_one) { player->inv_updated = 1; } #endif if (cpl.container) { /* Now do a container if one is active */ for (ip = cpl.container->inv; ip; ip = ip->next) { if (ip->animation_id > 0 && ip->anim_speed) { ip->last_anim++; if (ip->last_anim >= ip->anim_speed) { ip->anim_state++; if (ip->anim_state >= animations[ip->animation_id].num_animations) { ip->anim_state = 0; } ip->face = animations[ip->animation_id].faces[ip->anim_state]; ip->last_anim = 0; got_one = 1; } } } if (got_one) { cpl.container->inv_updated = 1; } } else { /* Now do the map (look window) */ for (ip = cpl.below->inv; ip; ip = ip->next) { if (ip->animation_id > 0 && ip->anim_speed) { ip->last_anim++; if (ip->last_anim >= ip->anim_speed) { ip->anim_state++; if (ip->anim_state >= animations[ip->animation_id].num_animations) { ip->anim_state = 0; } ip->face = animations[ip->animation_id].faces[ip->anim_state]; ip->last_anim = 0; got_one = 1; } } } if (got_one) { cpl.below->inv_updated = 1; } } } int can_write_spell_on(item* it) { return (it->type == 661); } void inscribe_magical_scroll(item *scroll, Spell *spell) { SockList sl; guint8 buf[MAX_BUF]; snprintf((char*)buf, sizeof(buf), "inscribe 0 %d %d", scroll->tag, spell->tag); script_monitor_str((char*)buf); SockList_Init(&sl, buf); SockList_AddString(&sl, "inscribe "); SockList_AddChar(&sl, 0); SockList_AddInt(&sl, scroll->tag); SockList_AddInt(&sl, spell->tag); SockList_Send(&sl, csocket.fd); } crossfire-client-1.75.3/common/def-keys000644 001751 001751 00000005004 14323707640 020671 0ustar00kevinzkevinz000000 000000 # def-keys -- default client keybindings # # This file contains a set of default client keybindings. It is converted into # a C header file at build time and parsed by the client when a key file isn't # found in the user's home folder or a default system location. # # # # will typically be the keycode for that key. While # keysyms are defined to work across different servers, keycodes are # server/machine specific. Keycodes are only needed because some keyboards # (sun's type 5 for one) have keys with no corresponding keysym. # When loading, all keysyms are converted to keycodes for matching. # # Flags: # N - Normal mode # F - Fire mode # R - Run mode # A - All modes # E - Leave in line edit mode #### Basic Keys #### # The trailing space on the following two lines are intentional. quotedbl 1 AE say Return 1 AE chat semicolon 0 NE reply comma 1 A take less 0 F get all period 1 N stay fire question 1 A help a 1 N apply d 1 N disarm e 1 NR examine s 1 F brace s 1 N search t 1 N ready_skill throwing #### Cursor (Directional Keys) #### # Nethack-Style b 1 N southwest h 1 N west j 1 N south k 1 N north l 1 N east n 1 N southeast u 1 N northeast y 1 N northwest b 1 R southwest h 1 R west j 1 R south k 1 R north l 1 R east n 1 R southeast u 1 R northeast y 1 R northwest b 1 F southwest h 1 F west j 1 F south k 1 F north l 1 F east n 1 F southeast u 1 F northeast y 1 F northwest # Arrow Keys Up 1 A north Down 1 A south Left 1 A west Right 1 A east # Number Pad Arrow Keys KP_8 1 A north KP_2 1 A south KP_4 1 A west KP_6 1 A east KP_7 1 A northwest KP_9 1 A northeast KP_5 1 A stay KP_1 1 A southwest KP_3 1 A southeast # Windows reports Home, End, etc. as not separate from their non-keypad equivalents. # These appear over the numpad keys when attempting to fire diagonally. # With NumLock off, the following 8 bindings suffice. End 1 F southwest f Home 1 F northwest f PgUp 1 F northeast f PgDown 1 F southeast f End 1 N southwest Home 1 N northwest Page_Up 1 N northeast Page_Down 1 N southeast End 1 R southwest Home 1 R northwest Page_Up 1 R northeast Page_Down 1 R southeast # Keys for Sun Type 4 Keyboards KP_Up 1 A north KP_Down 1 A south KP_Right 1 A east KP_Left 1 A west KP_Home 1 A northwest KP_Prior 1 A northeast #Unfortunately, there is no name for the middle key. #KP_5 1 A stay KP_End 1 A southwest KP_Next 1 A southeast #### Action Rotation #### KP_Add 1 A rotateshoottype KP_Subtract 1 A rotateshoottype - minus 1 N rotateshoottype -1 plus 1 NF rotateshoottype crossfire-client-1.75.3/common/client.h000644 001751 001751 00000065451 14323707640 020702 0ustar00kevinzkevinz000000 000000 /** * @file client.h * Includes various dependencies header files needed by most everything. It * also declares structures and other variables that the GUI portion needs. */ #ifndef _CLIENT_H #define _CLIENT_H #include "config.h" // This is required for 'newclient.h' to expose client variables. #define CLIENT_TYPES_H #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 # include #endif #include "item.h" #include "shared/newclient.h" #include "version.h" #ifndef SOL_TCP #define SOL_TCP IPPROTO_TCP #endif #define MAX_BUF 256 #define BIG_BUF 1024 /* used to register gui callbacks to extended texts * (which are supposed to be handled more friendly than raw text)*/ typedef void (*ExtTextManager)(int flag, int type, int subtype, char* message); typedef struct TextManager{ int type; ExtTextManager callback; struct TextManager* next; } TextManager; /* This is how often the client checks for X events, as well as how often * it performs animations (or will). This value can be most anything. * IT is only configurable because the exact value it needs to be set to * has to be figured out. This value is in microseconds (100,000 microseconds= * 0.1 seconds */ #define MAX_TIME 100000 /* This is the default port to connect to the server with. */ #define EPORT 13327 /* This is the default port to connect to the server with in string form. */ #define DEFPORT "13327" #define VERSION_CS 1023 #define VERSION_SC 1029 extern char VERSION_INFO[256]; /** * Do not send more than this many outstanding commands to the server this is * only a default value. */ #define COMMAND_WINDOW 10 #define STRINGCOMMAND 0 /** * How many skill types server supports/client will get sent to it. If more * skills are added to server, this needs to get increased. */ #define MAX_SKILL CS_NUM_SKILLS #define MAXANIM 2000 /** * @defgroup SC_xxx SC_xxx send_command options. * Values assigned to send_command option. */ /*@{*/ #define SC_NORMAL 0 #define SC_FIRERUN 1 #define SC_ALWAYS 2 #define SC_MOVETO 3 /*@}*/ typedef struct Animations { guint16 flags; guint8 num_animations; /**< Number of animations. Value of 2 * means only faces[0],[1] have * meaningful values. */ guint8 speed; guint8 speed_left; guint8 phase; guint16 *faces; } Animations; extern Animations animations[MAXANIM]; /** Largest ncom command number to send before wrapping. */ #define COMMAND_MAX 255 /** * Basic support for socket communications, including the file descriptor, * input buffer, server, server, version, etc. ClientSocket could probably * hold more of the global values - it could probably hold most all * socket/communication related values instead of globals. */ typedef struct { GSocketConnection* fd; int cs_version, sc_version; /**< Server versions of these */ guint16 command_sent, command_received; /**< These are used for the newer * 'windowing' method of commands - * number of last command sent, * number of received confirmation */ int command_time; /**< Time (in ms) players commands * currently take to execute */ char* servername; gint8 dir[COMMAND_MAX]; //< Direction of sent movement command (or -1) for local prediction } ClientSocket; extern ClientSocket csocket; extern char *sound_server; extern const char *cache_dir, *config_dir; typedef enum { Playing, //< including account login, character selection Reply_One, Reply_Many, Configure_Keys, Command_Mode, Metaserver_Select //< only when metaserver window is up } Input_State; typedef enum { range_bottom = -1, range_none = 0, range_bow = 1, range_magic = 2, range_wand = 3, range_rod = 4, range_scroll = 5, range_horn = 6, range_steal = 7, range_size = 8 } rangetype; /** * @defgroup CONFIG_xxx CONFIG_xxx want_config array indices. * Definitions to index into an array of most of the configuration options. * * Instead of having a whole mess of variables of different names, instead use * a common 16 bit signed array, and index into these - this makes processing * in the GUI aspect of the GTK client much easier. * * There are also 2 elements - want_options, and use_options. The former is * what the player wants to use, the latter is what is currently in use. * There are many options that can not be switched between during actual play, * but we want to record what the player has changed them to so that when we * save them out, we save what the player wants, and not what is currently * being used. * * Note that all the GUI interfaces may not use all these values, but making * them available here makes it easy for the GUI to present a nice interface. * * 0 is intentially skipped so the index into this doesn't get a default if a * table has a blank value * * CONFIG_NUMS is the number of configuration options; don't forget to modify: * * common/init.c -- config_names and init_config() */ /*@{*/ #define CONFIG_DOWNLOAD 1 #define CONFIG_ECHO 2 #define CONFIG_FASTTCP 3 #define CONFIG_CWINDOW 4 #define CONFIG_CACHE 5 #define CONFIG_FOGWAR 6 #define CONFIG_ICONSCALE 7 #define CONFIG_MAPSCALE 8 #define CONFIG_POPUPS 9 #define CONFIG_DISPLAYMODE 10 /**< @sa CFG_DM_xxx */ #define CONFIG_SHOWICON 11 #define CONFIG_TOOLTIPS 12 #define CONFIG_SOUND 13 #define CONFIG_SPLITINFO 14 #define CONFIG_SPLITWIN 15 #define CONFIG_SHOWGRID 16 #define CONFIG_LIGHTING 17 /**< @sa CFG_LT_xxx */ #define CONFIG_TRIMINFO 18 #define CONFIG_MAPWIDTH 19 #define CONFIG_MAPHEIGHT 20 #define CONFIG_FOODBEEP 21 #define CONFIG_DARKNESS 22 #define CONFIG_PORT 23 /**< Is this useful any more? */ #define CONFIG_GRAD_COLOR 24 #define CONFIG_RESISTS 25 #define CONFIG_SMOOTH 26 #define CONFIG_SPLASH 27 #define CONFIG_APPLY_CONTAINER 28 /**< Reapply container */ #define CONFIG_MAPSCROLL 29 /**< Use bitmap operations for map scrolling */ #define CONFIG_SIGNPOPUP 30 #define CONFIG_TIMESTAMP 31 #define CONFIG_AUTO_AFK 32 #define CONFIG_INV_MENU 33 #define CONFIG_NUMS 34 /**< This should always be the last value in the CONFIG_xxx list. */ /*@}*/ /** * @defgroup CFG_LT_xxx CONFIG_LIGHTING values. * Values that may be assigned to want_config[CONFIG_LIGHTING]. */ /*@{*/ #define CFG_LT_NONE 0 #define CFG_LT_TILE 1 #define CFG_LT_PIXEL 2 #define CFG_LT_PIXEL_BEST 3 /*@}*/ /** * @defgroup CFG_DM_xxx CONFIG_DISPLAYMODE values. * Values that may be assigned to want_config[CONFIG_DISPLAYMODE]. */ /*@{*/ #define CFG_DM_PIXMAP 0 #define CFG_DM_SDL 1 #define CFG_DM_OPENGL 2 /*@}*/ extern gint16 want_config[CONFIG_NUMS], use_config[CONFIG_NUMS]; extern const char *const config_names[CONFIG_NUMS]; /**< See common/init.c - * number mapping used * when loading/saving * the values. */ typedef struct Stat_struct { gint8 Str; /**< Strength */ gint8 Dex; /**< Dexterity */ gint8 Con; /**< Constitution */ gint8 Wis; /**< Wisdom */ gint8 Cha; /**< Charisma */ gint8 Int; /**< Intelligence */ gint8 Pow; /**< Power */ gint8 wc; /**< Weapon Class */ gint8 ac; /**< Armour Class */ gint8 level; /**< Experience level */ gint16 hp; /**< Hit Points */ gint16 maxhp; /**< Maximum hit points */ gint16 sp; /**< Spell points for casting spells */ gint16 maxsp; /**< Maximum spell points. */ gint16 grace; /**< Spell points for using prayers. */ gint16 maxgrace; /**< Maximum spell points. */ gint64 exp; /**< Experience. Killers gain 1/10. */ gint16 food; /**< Quantity food in stomach. * 0 = starved. */ gint16 dam; /**< How much damage this object does * for each hit */ gint32 speed; /**< Speed (is displayed as a float) */ gint32 weapon_sp; /**< Weapon speed (displayed in client * as a float) */ guint32 attuned; /**< Spell paths to which the player is * attuned */ guint32 repelled; /**< Spell paths to which the player is * repelled */ guint32 denied; /**< Spell paths denied to the player*/ guint16 flags; /**< Contains fire on/run on flags */ gint16 resists[30]; /**< Resistant values */ guint32 resist_change:1; /**< Resistant value change flag */ gint16 skill_level[MAX_SKILL]; /**< Level of known skills */ gint64 skill_exp[MAX_SKILL]; /**< Experience points for skills */ guint32 weight_limit; /**< Carrying weight limit */ } Stats; typedef struct Spell_struct { struct Spell_struct *next; char name[256]; /**< One length byte plus data */ char message[10000]; /**< This is huge, the packets can't * be much bigger than this anyway */ guint32 tag; /**< Unique ID number for a spell so * updspell etc can operate on it. */ guint16 level; /**< The casting level of the spell. */ guint16 time; /**< Casting time in server ticks. */ guint16 sp; /**< Mana per cast; may be zero. */ guint16 grace; /**< Grace per cast; may be zero. */ guint16 dam; /**< Damage done by spell though the * meaning is spell dependent and * actual damage may depend on how * the spell works. */ guint8 skill_number; /**< The index in the skill arrays, * plus CS_STAT_SKILLINFO. 0: no * skill used for cast. See also: * request_info skill_info */ char *skill; /**< Pointer to the skill name, * derived from the skill number. */ guint32 path; /**< The bitmask of paths this spell * belongs to. See request_info * spell_paths and stats about * attunement, repulsion, etc. */ gint32 face; /**< A face ID that may be used to * show a graphic representation * of the spell. */ guint8 usage; /**< Spellmon 2 data. Values are: * 0: No argument required. * 1: Requires other spell name. * 2: Freeform string is optional. * 3: Freeform string is required. */ char requirements[256]; /**< Spellmon 2 data. One length byte * plus data. If the spell requires * items to be cast, this is a list * of req'd items. Comma-separated, * number of items, singular names * (like ingredients for alchemy). */ } Spell; typedef struct Player_Struct { item *ob; /**< Player object */ item *below; /**< Items below the player * (pl.below->inv) */ item *container; /**< open container */ guint16 count_left; /**< count for commands */ Input_State input_state; /**< What the input state is */ char last_command[MAX_BUF]; /**< Last command entered */ char input_text[MAX_BUF]; /**< keys typed (for long commands) */ item *ranges[range_size]; /**< Object that is used for that */ /**< range type */ guint8 ready_spell; /**< Index to spell that is readied */ char spells[255][40]; /**< List of all the spells the */ /**< player knows */ Stats stats; /**< Player stats */ Spell *spelldata; /**< List of spells known */ char title[MAX_BUF]; /**< Title of character */ char range[MAX_BUF]; /**< Range attack chosen */ guint32 spells_updated; /**< Whether or not spells updated */ guint32 fire_on:1; /**< True if fire key is pressed */ guint32 run_on:1; /**< True if run key is on */ guint32 meta_on:1; /**< True if fire key is pressed */ guint32 alt_on:1; /**< True if fire key is pressed */ guint32 no_echo:1; /**< If TRUE, don't echo keystrokes */ guint32 count; /**< Repeat count on command */ guint16 mmapx, mmapy; /**< size of magic map */ guint16 pmapx, pmapy; /**< Where the player is on the magic * map */ guint8 *magicmap; /**< Magic map data */ guint8 showmagic; /**< If 0, show the normal map, * otherwise show the magic map. */ guint16 mapxres,mapyres; /**< Resolution to draw on the magic * map. Only used in client-specific * code, so it should move there. */ char *name; /**< Name of PC, set and freed in account.c * play_character() (using data returned * from server to AccountPlayersCmd, via * character_choose window, * OR in * send_create_player_to_server() when * new character created. */ } Client_Player; /** * @defgroup MAX_xxx_xxx MAX_xxx_xxx Face and image constants. * Faceset information pretty much grabbed right from server/socket/image.c. */ /*@{*/ #define MAX_FACE_SETS 20 #define MAX_IMAGE_SIZE 320 /**< Maximum size of image in each * direction. Needed for the X11 * client, which wants to initialize * some data once. Increasing this * would likely only need a bigger * footprint. */ /*@}*/ typedef struct FaceSets_struct { guint8 setnum; /**< */ guint8 fallback; /**< */ char *prefix; /**< */ char *fullname; /**< */ char *size; /**< */ char *extension; /**< */ char *comment; /**< */ } FaceSets; /** * One struct that holds most of the image related data to reduce danger of * namespace collision. */ typedef struct Face_Information_struct { guint8 faceset; char *want_faceset; gint16 num_images; guint32 bmaps_checksum, old_bmaps_checksum; /** * Just for debugging/logging purposes. This is cleared on each new * server connection. This may not be 100% precise (as we increment * cache_hits when we find a suitable image to load - if the data is bad, * that would count as both a hit and miss. */ gint16 cache_hits, cache_misses; guint8 have_faceset_info; /**< Simple value to know if there is * data in facesets[]. */ FaceSets facesets[MAX_FACE_SETS]; } Face_Information; extern Face_Information face_info; extern Client_Player cpl; /**< Player object. */ extern char *skill_names[MAX_SKILL]; extern int last_used_skills[MAX_SKILL+1]; /**< maps position to skill id with * trailing zero as stop mark. */ typedef enum { LOG_DEBUG = 0, ///< Useful debugging information LOG_INFO = 1, ///< Minor, non-harmful issues LOG_WARNING = 2, ///< Warning that something might not work LOG_ERROR = 3, ///< Warning that something definitely didn't work LOG_CRITICAL = 4 ///< Fatal crash-worthy error } LogLevel; /** * Translation of the STAT_RES names into printable names, in matching order. */ #define NUM_RESISTS 18 extern const char *const resists_name[NUM_RESISTS]; extern char *meta_server; extern int serverloginmethod, wantloginmethod; /** * Holds the names that correspond to skill and resistance numbers. */ typedef struct { const char *name; int value; } NameMapping; extern NameMapping skill_mapping[MAX_SKILL], resist_mapping[NUM_RESISTS]; extern guint64 *exp_table; extern guint16 exp_table_max; /** * Map size the client will request the map to be. The bigger it is, more * memory it will use. */ #define MAP_MAX_SIZE 25 /** * This is the smallest the map structure used for the client can be. It * needs to be bigger than the MAP_MAX_SIZE simply because we have to deal * with off map big images, Also, the center point is moved around within this * map, so that if the player moves one space, we don't have to move around * all the data. */ #define MIN_ALLOCATED_MAP_SIZE MAP_MAX_SIZE * 2 /** * How many spaces an object might extend off the map. E.g. For bigimage * stuff, the head of the image may be off the the map edge. This is the most * it may be off. This is needed To cover case of need_recenter_map routines. */ #define MAX_MAP_OFFSET 8 /* Start of map handling code. * * For the most part, this actually is not window system specific, but * certainly how the client wants to store this may vary. */ #define MAXPIXMAPNUM 10000 /** * Used mostly in the cache.c file, however, it can be returned to the graphic * side of things so that they can update the image_data field. Since the * common side has no idea what data the graphic side will point to, we use a * void pointer for that - it is completely up to the graphic side to * allocate/deallocate and cast that pointer as needed. */ typedef struct Cache_Entry { char *filename; guint32 checksum; guint32 ispublic:1; void *image_data; struct Cache_Entry *next; } Cache_Entry; /** * @defgroup RI_IMAGE_xxx RI_IMAGE_xxx RequestInfo values. * Values used for various aspects of the library to hold state on what * requestinfo's we have gotten replyinfo for and what data was received. In * this way, common/client.c can loop until it has gotten replies for all the * requestinfos it has sent. This can be useful - we don't want the addme * command sent for example if we are going to use a different image set. The * GUI stuff should really never change these variables, but I suppose I could * look at them for debugging/ status information. */ /*@{*/ #define RI_IMAGE_INFO 0x1 #define RI_IMAGE_SUMS 0x2 /*@}*/ extern int replyinfo_status, requestinfo_sent, replyinfo_last_face; typedef struct PlayerPosition { int x; int y; } PlayerPosition; extern PlayerPosition pl_pos; typedef struct Msg_Type_Names { int type; /**< Type of message */ int subtype; /**< Subtype of message */ const char *style_name; /**< Name of this message in the * configfile. */ } Msg_Type_Names; extern TextManager* firstTextManager; /* declared/handled in commands.c . These variables are documented * in that file - the data they present is created by the command * code, but consumed by the GUI code. */ extern char *motd, *news, *rules; extern char *motd, *news, *rules; /* Declared/handled in commands.c */ extern int num_races, used_races, num_classes, used_classes; extern int stat_points, stat_min, stat_maximum; /* * This structure is used to hold race/class adjustment info, as * received by the requestinfo command. We get the same info * for both races and class, so it simplifies code to share a structure. */ /* This is how many stats (str, dex, con, etc) that are present * in the create character window. */ #define NUM_NEW_CHAR_STATS 7 /** * The usage of the stat_mapping is to simplify the code and make it easier * to expand. Within the character creation, the different stats really * do not have any meaning - the handling is pretty basic - value user * has selected + race adjust + class adjustment = total stat. */ struct Stat_Mapping { const char *widget_suffix; /* within the glade file, suffix used on widget */ guint8 cs_value; /* within the protocol, the CS_STAT value */ guint8 rc_offset; /* Offset into the stat_adj array */ }; extern struct Stat_Mapping stat_mapping[NUM_NEW_CHAR_STATS]; /** * For classes & races, the server can present some number of * choices, eg, the character gets to choose 1 skill from a * choice of many. Eg RC_Choice entry represents one of these * choices. However, each race/class may have multiple choices. * For example, if the class had the character make 2 choices - * one for a skill, and one for an item, 2 RC_Choice structures * would be used. */ struct RC_Choice { char *choice_name; /* name to respond, eg, race_choice_1 */ char *choice_desc; /* Longer description of choice */ int num_values; /* How many values we have */ char **value_arch; /* Array arch names */ char **value_desc; /* Array of description */ }; typedef struct Race_Class_Info { char *arch_name; /* Name of the archetype this correponds to */ char *public_name; /* Public (human readadable) name */ char *description; /* Description of the race/class */ gint8 stat_adj[NUM_NEW_CHAR_STATS]; /* Adjustment values */ int num_rc_choice; /* Size of following array */ struct RC_Choice *rc_choice; /* array of choices */ } Race_Class_Info; typedef struct Starting_Map_Info { char *arch_name; /* Name of archetype for this map */ char *public_name; /* Name of the human readable name */ char *description; /* Description of this map */ } Starting_Map_Info; extern Race_Class_Info *races, *classes; extern Starting_Map_Info *starting_map_info; extern int starting_map_number; extern int maxfd; /* End of commands.c data, start of other declarations */ #ifndef MIN #define MIN(X__,Y__) ( (X__)<(Y__)?(X__):(Y__) ) #endif /** * @defgroup INFO_xxx INFO_xxx login information constants. * Used for passing in to update_login_info() used instead of passing in the * strings. */ /*@{*/ #define INFO_NEWS 1 #define INFO_MOTD 2 #define INFO_RULES 3 /*@}*/ #define CLIENT_ERROR client_error_quark() inline GQuark client_error_quark() { return g_quark_from_static_string("client-error-quark"); } enum ClientError { CLIENT_ERROR_TOOBIG }; /* We need to declare most of the structs before we can include this */ #include "proto.h" /** * Open a socket to the given hostname and store connection information. * * @param hostname Host name or address of the server */ extern void client_connect(const char *hostname); /** * Closes the connection to the server. It seems better to have it one place * here than the same logic sprinkled about in half a dozen locations. It is * also useful in that if this logic does change, there is just one place to * update it. */ extern void client_disconnect(void); /** * This function negotiates the characteriistics of a connection to the * server. Negotiation consists of asking the server for commands it wants, * and checking protocol version for compatibility. Serious incompatibilities * abort the connection. * * @param sound Non-zero to ask for sound and music commands. */ extern void client_negotiate(int sound); /** * Ask the server for the given map size. */ extern void client_mapsize(int width, int height); /** * Read available packets from the server and handle commands until there are * no more, or if a socket error occurs. */ extern void client_run(void); /** * Write the given data to the server. */ extern bool client_write(const void *buf, int len); extern bool client_is_connected(void); /** * Return a source triggered when input from the server is available. */ extern GSource *client_get_source(void); extern GTimer* global_time; extern bool debug_protocol; char *printable(void *data, int len); #endif crossfire-client-1.75.3/common/version.h000644 001751 001751 00000000035 14045044330 021063 0ustar00kevinzkevinz000000 000000 #define FULL_VERSION VERSION crossfire-client-1.75.3/common/items.pl000644 001751 001751 00000002066 14045044301 020707 0ustar00kevinzkevinz000000 000000 #!/usr/local/bin/perl $MAXVAL=256; # Number of subscripts $SUBS=64; $lastval=-1; open(ITEMS,"<$ARGV[0]/item-types") || die("can not open item-types file"); while() { next if (/^#/ || /^\s*$/); if (/^(\d*):/) { $lastval=$1; } # skip empty lines else { chomp; die("Got item name before item number: $_\n") if ($lastval == -1); push @{ $names[$lastval]} , $_; } } close(ITEMS); open(ITEMS, ">item-types.h") || die("Can not open item-types.h\n"); print ITEMS "/* This file is automatically generated editing by hand is strongly*/\n"; print ITEMS "/* discouraged. Look at the item-types file and the items.pl conversion */\n"; print ITEMS "/* script. */\n"; print ITEMS "\n#define NUM_ITEM_TYPES $MAXVAL\n"; print ITEMS "#define MAX_NAMES_PER_TYPE $SUBS\n\n"; print ITEMS "static const char * const item_types[$MAXVAL][$SUBS] = {\n"; for ($i=0; $i<$MAXVAL; $i++) { print ITEMS "{ "; for ($j=0; $j<= $#{ $names[$i] }; $j++) { print ITEMS "\"$names[$i][$j]\", "; } print ITEMS "NULL }, \n"; } print ITEMS "}; \n"; close(ITEMS);