#!/opt/bin/perl our $VERSION = '1.3'; my $startup_done = sub { }; # do splash-screen thingy on win32 BEGIN { if (%PAR::LibCache && $^O eq "MSWin32") { while (my ($filename, $zip) = each %PAR::LibCache) { $zip->extractMember ("SPLASH.bmp", "$ENV{PAR_TEMP}/SPLASH.bmp"); } require Win32::GUI::SplashScreen; Win32::GUI::SplashScreen::Show ( -file => "$ENV{PAR_TEMP}/SPLASH.bmp", ); $startup_done = sub { Win32::GUI::SplashScreen::Done (1); }; } } BEGIN { if (%PAR::LibCache) { @INC = grep ref, @INC; # weed out all paths except pars loader refs while (my ($filename, $zip) = each %PAR::LibCache) { for ($zip->memberNames) { next unless /^\/root\/(.*)/; $zip->extractMember ($_, "$ENV{PAR_TEMP}/$1") unless -e "$ENV{PAR_TEMP}/$1"; } } $ENV{DELIANTRA_LIBDIR} ||= $ENV{PAR_TEMP}; } } BEGIN { $ENV{GTK_RC_FILES} = "$ENV{PAR_TEMP}/share/themes/MS-Windows/gtk-2.0/gtkrc" if %PAR::LibCache && $^O eq "MSWin32"; } use Gtk2 -init; use Data::Dumper; use File::Spec; use Deliantra; use GCE::MainWindow; our $CFG; our $MAPDIR; our $LIBDIR; our $MAINWIN; our $DOCUMENTATION = join ("\n", do { local $/; }); sub read_cfg { my ($file) = @_; open CFG, $file or return; $CFG = eval join '', ; close CFG; } sub write_cfg { my ($file) = @_; open CFG, ">$file" or return; { local $Data::Dumper::Purity = 1; $CFG->{VERSION} = $VERSION; print CFG Data::Dumper->Dump ([$CFG], [qw/CFG/]); } close CFG; } # following 2 functions are taken from CV :) sub find_rcfile($) { my $path; for (@INC) { $path = "$_/GCE/$_[0]"; return $path if -r $path; } die "FATAL: can't find required file $_[0]\n"; } sub require_image($) { new_from_file Gtk2::Gdk::Pixbuf find_rcfile "images/$_[0]"; } sub get_pos_and_size { my ($window) = @_; my ($x, $y) = $window->get_position; my ($w, $h) = $window->get_size; return [$x, $y, $w, $h]; } sub set_pos_and_size { my ($window, $p_and_s, $default_w, $default_h, $default_x, $default_y) = @_; $window->set_default_size ($p_and_s->[2] || $default_w, $p_and_s->[3] || $default_h); # FIXME: This sucks, moving it after showing it can't be a good thing. $window->show_all; $window->move ($p_and_s->[0] || $default_x, $p_and_s->[1] || $default_y); } if (-e "$Deliantra::VARDIR/gdeconfig") { read_cfg "$Deliantra::VARDIR/gdeconfig"; } else { read_cfg "$Deliantra::VARDIR/gceconfig"; } $LIBDIR = $ENV{DELIANTRA_LIBDIR}; $LIBDIR ||= $CFG->{LIBDIR}; $MAPDIR = $ENV{DELIANTRA_MAPDIR}; $MAPDIR ||= $CFG->{MAPDIR}; $MAPDIR ||= File::Spec->catfile ($ENV{DELIANTRA_LIBDIR}, 'maps'); # must be done after changing the libdir path: Deliantra::set_libdir ($LIBDIR); Deliantra::load_archetypes; Deliantra::load_tilecache; my $w = GCE::MainWindow->new; $w->load_layout; $w->show_all; $startup_done->(); Gtk2->main; __DATA__ =head1 NAME gde - gtk deliantra (map) editor =head1 SYNOPSIS gde [...] =head1 FEATURES gde is a map editor for deliantra. Its main features are: - higher map editing comfort - intelligent placement tool - intelligent connection tool - intelligent erase tool - map normalizing (removal of old deprecated attributes) - exit following - world map navigation - easy installation (on windows) - auto joining of walls (see Placement tool -> auto setting) =head1 DESCRIPTION =head2 THE TOOLBOX WINDOW The toolbox window is the main window of gde. It provides the display of the currently selected object and the tools. The buttons select of the editing tool: =over 4 =item * Pick This tool is the simplest of all. It lets the user select the topmost object of a map cell in the map window and updates the stack view for the current space. Shortcut-key in map editor: i =item * Place This is the intelligent placement tool. It has many modes: =over 4 =item auto This mode implements DWIM (do-what-I-mean) by trying to do the the right thing(tm) with the selected object: If you place a floor arch, it will try to replace the existing floor or set the floor below all items. If you place a monster or other arch, it will place it on top. If you place a wall, it will put the wall above the floor and propably replace other walls. Autojoin also works only in this mode. To draw an wall with autojoining pick the wall arch which name looks like: _0. It's the single point wall tile which has no connections. When you place this arch now, it will autoconnect the walls you are drawing. =item top Places the arch on the top of the stack of the map cell. =item above floor Places the arch just right above the floor (or the bottom of the stack). =item below floor Places the arch just right below the floor (or the bottom of the stack). =item bottom Places the arch on the bottom of the stack. =back Shortcut-key in map editor: p =item * Erase This is the tool that lets you erase an arch. It has following modes: =over 4 =item top Erases the topmost object on the stack. =item walls Erases all walls in the stack (and only walls). =item above floor Erases the first object above the floor. =item floor Erases all floor from the stack (and only the floor). =item below floor Erases the first object below the floor. =item bottom Erases the first object on the bottom of the stack. =item pick match This erases all objects from the stack that match the currently selected object. =item protect walls (checkbox) This protects walls from being erased (except when erasing walls). =item protect monsters (checkbox) This protects monsters from being erased. =back Shortcut-key in map editor: e =item * Select This is the selection tool. It can be used to select rectangular areas and operate on that area in various ways: =over 4 =item copy This just copies all objects from the selected area into an internal buffer for later paste operations. Shortcut-key in map editor: c =item paste This function pastes the internal buffer into the map, beginning in the top left corner of the selected area. The size of the selection has no relevance to the result: IT always places the whole internal buffer onto the map. Shortcut-key in map editor: p =item invoke This function is a very powerful one. It can apply another tool (such as the place tool) on all spaces of the selected area. It can, for example, be used to fill a map with floor tiles or erase everything. Shortcut-key in map editor: n =back Shortcut-key in map editor: s =item * Eval This is a very special tool which isn't finished yet. It lets you specify a perl snippet that can manipulate the stack. Shortcut-key in map editor: l =item * Connect This tool connects two exits, teleporters or adds the configures connection value to the connectors. This tool has 3 modes: =over 4 =item auto The auto mode tries to find exits first, and if it found one, it will go into the exit connect mode. If no exit is found but a connectable object is found, it will just add the connection value to the object. (Note: This maybe gets in the way if you want to connect teleporters. The auto mode will only connect teleporters as if they are exits and not touch the connection value). =item exit This mode wont set any connection values. =item connect In this mode the connect tool will only set connection values and not try to connect exits. =back You can either connect two exits to each other, or just point an exit to a certain location on a map. After clicking on an exit the first time you will see a string like this in the tool dialoge in the main window: 'src: (12,9) teleporter'. It tells you that you selected a source destination and that the next click will connect the exit with another exit or just let it point where you clicked (if there is no connectable object (in auto mode)). To connect two exits, just click at the first and then at the second, and the editor will try to find a path (map path) that fits the deliantra conventions. It will also adjust the (x,y) coords so that the exits point at each other. If something doesn't work as expected make sure you saved both maps in a subdirectory of the deliantra map path (which you configured via File->Preferences in the main window). If the tile you edited with the connect tool contained a connectable object, the currently configured connect value (set by the spin buttons in the main window) will be set on them. Shortcut-key in map editor: t =item * Follow Exit With this tool you can follow exits and teleporters by opening the target map in a new window (or presents an existing window). Shortcut-key in map editor: f =back =head2 THE STACK VIEW This window displays the stack of a map space/coordinate. You can swap two objects on the stack and delete a object from the stack by dragging one object over another. By clicking on an item on the stack you can make it the currently selected object. =head2 THE MAP EDITOR This window just displays the map and lets you use the tools. The shortcuts are documented above in the tool descriptions. You can pan the map using the middle mouse button and use the tool with the left mouse button. There exists a context menu on right click: =over 4 =item Follow This context menu entry lets you follow an exit. It will open a new map editor with the map. See Follow Exit tool. =item object stack Below the context menu entrys that are documented above there is a seperator that seperates the object stack menu items. Each object stack item is a submenu that offers following functionality: =over 4 =item Add inventory It allows you to add the current arch in the attribute editor (a copy of it) to the object as inventory item. =item Find in picker This function tries to determine the picker group that this object is in and opens a new picker pointing at that group. =back =back =head2 THE ATTRIBUTE EDITOR The attribute editor display the archetype name followed by the object name and the type of the object in parentheses. The 'reset to defaults' button erases all changes on the object and resets it's value to the values of the archetype. Since there are often many attributes for a given object, they are sorted into different categories/tabs. The lore and msg tabs let you edit the text attributes of the object. Both field labels and value widgets have tool tips enabled. Tool tips on the labels explain the attribute in more detail. The tool tips on the value widgets show the default value from the archetype. On the right side of the attribute editor you will find the inventory, you can drag stuff there or just use the context menu von the pick window (see below) to add inventory. =head2 THE PICK WINDOW Pick windows are used to quickly pick archetypes from specific categories. Left click creates an object from the archetype and makes it the currently selected object for the tools and the attribute editor. You can change the attributes of the currently selected object in the attribute editor. Right click opens the context menu, where you can add the selected arch as inventory to the object which is currently visible in the attribute editor. You can open multiple pick windows. =head1 MAP EDITING =head2 SHOP PROPERTIES There are 5 map properties related to shops that can be present in a map. Any given map may have some, all or none of them (although in the later case, it isn't considered to be a shop). =over 4 =item Music This field constains a list of comma seperated music paths. will become /music/.ogg. Example: km/piece1,km/piece2 =item Shopmin This is an integer value. It is the minimum value that the object must have in order to be considered by purchase for a shop. This is not the same as the price offered, which can be substantially below shopmin. =item Shopmax This is an integer value. It uses value like shopmin does, however it is not a fixed upper limit. The value is adjusted downwards if it is in excess of one half of shopmax. The output value is the minimum of shopmax and one half of shopmax plus the square root of one half of shopmax Note that the value is only an aspect of the final price, and the actual price offered for an item can be substantially less than shopmax, even when the item's value in in excess of that. =item Shoprace if the player matches shoprace, this has no effect, if they do not, the price offered is only 80% of what it would otherwise be. =item Shopgreed This is a multiplier on all prices offered, items brought from the player are done so at a price divided by the greed, items sold to a player are overcharged by a factor of shopgreed. =item Shopitems This is a semi-colon deliminated list of item types and values. each entry is a name of an item type (from the array in common/item.c) followed by an optional colon then a value in the range -100 to 100. (if this is missing, the default value of 0 is used. This value is a measure of how much items of that type are preffered. Neutrality is represented by 0 (so a theoretical 'general' store would have 0 for everything), a positive preference for certain item types is a positive value, and negative preference for item types is a negative value. As a special note, the character * may be used once to set a preference for everything not explicitly listed otherwise (this value would in most cases be negative) for example, a typical magic shop might have the string: shopitems amulet:25;ring:40;potion:40;book:35;scroll:40;spellbook:40;skillscroll:50;wand:40;*:-50 and an armour shop might have the string: shopitems armour:50;shield:50;helmet:40;cloak:40;boots:40;gloves:40;bracers:50;girdle:50;*:-50 all possible name values for items are listed in common/item.c, however there are only some that are likely to be used (doors are not sold very often....) this list is not definitive or neccesarily up-to-date, but is a reasonable starting point for constructing a new shop. rod book horn amulet potion ring inorganic spellbook wand scroll power_crystal arrow bow weapon armour shield helmet cloak boots gloves bracers girdle flesh food drink treasure gem skill tool lighter light source lamp tool container item_transformer armour improver weapon improver skillscroll building material =back =head1 AUTHOR All of the editor GUI: Robin Redeker http://www.ta-sa.org/ The Deliantra map handling module and map widget: Marc Lehmann http://home.schmorp.de/ =cut