From 391203d83ed7a72b54fb7d7c72dbe35db14f0ea9 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Mon, 28 Aug 2006 23:04:08 +0000 Subject: Merged trunk development between revisions 2530 and 2618 to the 0.1.0 branch. --- data/graphics/Makefile.am | 2 +- data/graphics/images/Makefile.am | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'data/graphics') diff --git a/data/graphics/Makefile.am b/data/graphics/Makefile.am index 43354894..19e95869 100644 --- a/data/graphics/Makefile.am +++ b/data/graphics/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = gui images sprites tiles +SUBDIRS = gui images items sprites tiles diff --git a/data/graphics/images/Makefile.am b/data/graphics/images/Makefile.am index 8fbe3694..e0707698 100644 --- a/data/graphics/images/Makefile.am +++ b/data/graphics/images/Makefile.am @@ -1,3 +1,4 @@ +SUBDIRS = ambient imagesdir = $(pkgdatadir)/data/graphics/images -- cgit v1.2.3-60-g2f50 From e8f94fe7ca5e7e7838eaa84f1792b4b42b4bada3 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Fri, 29 Sep 2006 23:59:08 +0000 Subject: Merged trunk changes from revision 2618 to 2716 into the 0.1.0 branch. --- ChangeLog | 339 ++++++++++++++++++++++++++++++--------- NEWS | 10 +- README | 3 +- data/graphics/images/Makefile.am | 9 +- data/help/changes.txt | 31 ++++ data/help/commands.txt | 1 + data/help/header.txt | 2 +- debian/changelog | 8 + debian/tmw-music.install | 2 + src/Makefile.am | 3 + src/animatedsprite.cpp | 87 +++++++--- src/animatedsprite.h | 16 +- src/animation.cpp | 33 +++- src/animation.h | 16 ++ src/being.cpp | 25 +-- src/beingmanager.cpp | 29 +++- src/beingmanager.h | 19 ++- src/engine.cpp | 4 +- src/floor_item.cpp | 4 +- src/game.cpp | 77 ++++++--- src/game.h | 17 +- src/gui/buy.cpp | 47 +++--- src/gui/buy.h | 12 +- src/gui/char_select.cpp | 22 +++ src/gui/char_select.h | 2 + src/gui/equipmentwindow.cpp | 4 +- src/gui/gui.cpp | 13 ++ src/gui/inventorywindow.cpp | 58 ++++--- src/gui/inventorywindow.h | 20 ++- src/gui/itemcontainer.cpp | 35 +++- src/gui/itemcontainer.h | 35 +++- src/gui/listbox.cpp | 57 ++++++- src/gui/listbox.h | 41 ++++- src/gui/minimap.cpp | 4 +- src/gui/playerbox.cpp | 2 +- src/gui/popupmenu.cpp | 2 +- src/gui/selectionlistener.h | 78 +++++++++ src/gui/sell.cpp | 40 +++-- src/gui/sell.h | 13 +- src/gui/setup.cpp | 4 +- src/gui/setup_video.cpp | 52 +++++- src/gui/setup_video.h | 4 + src/gui/trade.cpp | 63 ++++---- src/gui/trade.h | 10 +- src/gui/updatewindow.cpp | 18 ++- src/gui/updatewindow.h | 5 + src/gui/window.cpp | 12 +- src/item.h | 2 +- src/localplayer.h | 7 +- src/main.cpp | 108 +++++++------ src/map.cpp | 24 ++- src/net/inventoryhandler.cpp | 11 +- src/resources/image.cpp | 21 ++- src/resources/image.h | 7 + src/resources/iteminfo.cpp | 31 ++-- src/resources/iteminfo.h | 34 ++-- src/resources/itemmanager.cpp | 9 +- src/resources/itemmanager.h | 8 +- src/tmw.rc | 8 +- tools/Reorganize.java | 128 ++++++++++----- 60 files changed, 1336 insertions(+), 450 deletions(-) create mode 100644 src/gui/selectionlistener.h (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index aa54e32e..33fab8df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,148 @@ -2006-08-30 Yohann Ferreira +2006-09-28 Björn Steinbrink + + * src/map.cpp: Fix random crashes when map tiles are missing. + +2006-09-28 Bjørn Lindeijer + + * data/graphics/maps/new_2-1.tmx.gz: Matt Howe fixed up cave map. + +2006-09-26 Eugenio Favalli + + * data/graphics/maps/new_6-1.tmx.gz: Alderan fixed a map issue. + +2006-09-25 Bjørn Lindeijer + + * data/graphics/sprites/hairstyle*.png, + data/graphics/sprites/hairstyle*.xml, tools/Reorganize.java: Removed + unused frames from the hairsets. + * src/resources/image.h: Defined NO_SDL_GLEXT to prevent a + redefinition when gl.h also tries to define OpenGL extensions (patch + accepted from Rogier Polak). + +2006-09-23 Bjørn Lindeijer + + * data/maps/new_5-1.tmx.gz: Accepted new version by Matt Howe, fixing + several mapping issues. + +2006-09-21 Eugenio Favalli + + * data/graphics/tiles/Makefile.am: Added missing tileset. + * src/gui/updatewindow.cpp, src/gui/updatewindow.h: Made canceling the + update process non-blocking (Patch by VictorSan). + +2006-09-21 Philipp Sehmisch + + * src/animation.cpp, src/animation.h, src/animatedsprite.cpp, + src/animatedsprite.h: Removed some obsolete code and implemented + the posibility to define an token in the s + that allows to define an animation that doesn't loop and returns + to the STAND animation when finished. + * data/graphics/sprites/hairstyle*.xml, + data/graphics/sprites/item0*.xml, + data/graphics/sprites/monster*.xml, + data/graphics/sprites/weapons.xml: Used the token for all + attack animations fixing the problem with looping monster attack + animations. + +2006-09-20 Philipp Sehmisch + + * data/graphics/items/generic-whitefur.png, + data/graphics/items/generic-cavesnakelamp.png, + data/graphics/items/generic-hardspike.png, + data/graphics/items/generic-pinkantennae.png, + data/graphics/items/Makefile.am, data/items.xml: Added drops for new + monsters. + * src/gui/setup.cpp, src/gui/setup_video.cpp, + src/gui/setup_video.h: Added a slider for controlling the overlay + detail to the video setup dialog based on a patch by VictorSan. + * data/maps/new_14-1.tmx.gz, data/maps/new_16-1.tmx.gz: Added cloud + effect and minimap. + * data/images/Makefile.am: Updated makefile. + +2006-09-19 Bjørn Lindeijer + + * data/graphics/sprites/Makefile.am: Added missing monster19 sprite. + +2006-09-17 Eugenio Favalli + + * data/maps/Makefile.am: Added missing maps. + * data/maps/new_10-1.tmx.gz: Disabled layer compression. + +2006-09-18 Philipp Sehmisch + + * data/maps/new_9-1.tmx.gz: Fixed some mapping bugs (new walkmap + required). + +2006-09-17 Eugenio Favalli + + * data/maps/new_10-1.tmx.gz: Fixed transparent snow issue (Fix by + Pajarico). + +2006-09-17 Björn Steinbrink + + * src/game.cpp: Stop using the sticky window attribute which is + unneeded for the current implementation, instead adjust the set of + affected windows by the 'hide' shortcut. + +2006-09-17 Philipp Sehmisch + + * data/maps/new_14-1.tmx.gz, data/maps/new_15-1.tmx.gz, + data/maps/new_16-1.tmx.gz: fixed some mapping errors. + +2006-09-16 Philipp Sehmisch + + * src/animatedsprite.cpp, src/animatedsprite.h: Fixed the crash when + attacking without a weapon, some additional stability improvements and + more descriptive variable names in the parsing algorithmn. + +2006-09-16 Eugenio Favalli + + * data/help/changes.txt, data/help/header.txt, NEWS, README, + src/tmw.rc: Updated release infos. + +2006-09-14 Philipp Sehmisch + + * src/animation.h, src/animatedsprite.h, + data/graphics/sprites/weapon.xml: Some modifications at the animation + system. No more "undefined action foo" warnings in the tmw.log. Not + visible actions must now be declared explicitely. + * data/graphics/images/ambient/sandstorm.png, + data/graphics/images/ambient/clouds.png: Improved quality of the overlay + graphics. + +2006-09-14 Björn Steinbrink + + * src/gui/char_select.cpp: Remove debug output. + * src/gui/char_select.cpp, src/main.cpp: Fix the character name + matching loop and add support for saving the last used character + (based on a patch by Andrew Harrison). + * src/gui/char_select.cpp, src/gui/char_select.h, src/main.cpp: Clean + up the player selection stuff, it's a bit nicer now. + * src/main.cpp: Fix up the player selection command line option. + +2006-09-13 Yohann Ferreira * src/Makefile.am, src/gui/widgets, src/gui/widgets/dropdown.h, src/gui/widgets/dropdown.cpp, src/gui/serverdialog.h, src/gui/serverdialog.cpp: Added a reusable skinned dropdown widget in the new widgets folder. Other widgets will be be moved there later. +2006-09-12 Bjørn Lindeijer + + * src/game.cpp, src/game.h: Simplified fps limiting a bit and added + some comments. Now based on ConfigListener so that the fpslimit option + doesn't need to be queried the whole time. + * NEWS: Updated with some items. + +2006-09-11 Eugenio Favalli + + * src/game.cpp: Fixed more fps issues. + +2006-09-09 Bjørn Lindeijer + + * src/gui/gui.cpp: Removed easy targeting functionality since it + interferes with walking around too much. Targeting can still be rather + conveniently done with 'a' or the middle mouse button. 2006-09-09 Guillaume Melquiond @@ -13,6 +151,72 @@ * src/localplayer.h, src/being.cpp, src/net/beinghandler.cpp, src/being.h: Fitted being trajectories to synchronization messages. +2006-09-07 Björn Steinbrink + + * src/resources/image.cpp: Fixed a typo. + * src/resources/image.cpp: Worked around a memory leak when using + OpenGL. + +2006-09-06 Philipp Sehmisch + + * data/graphics/sprites/item010.png, data/graphics/sprites/item010.xml, + data/graphics/sprites/Makefile.am: Added santa hat sprites and updated + makefile. + +2006-09-06 Eugenio Favalli + + * src/game.cpp, src/gui/setup_video.cpp, src/main.cpp: Fixed fps + limiter issues and increased default limit to 60. + * src/game.cpp: Fixed fps limiter when disabled. + +2006-09-05 Philipp Sehmisch + * data/graphics/tiles/Woodland_ground.png, + data/graphics/tiles/Woodland_x2.png, + data/graphics/tiles/Woodland_x3.png: Some minor improvements and + additions at my tilesets. + * data/graphics/sprites/monster0.xml, + data/graphics/sprites/monster1.xml, + data/graphics/sprites/monster2.xml, + data/graphics/sprites/monster3.xml, + data/graphics/sprites/monster4.xml, + data/graphics/sprites/monster5.xml, + data/graphics/sprites/monster6.xml, + data/graphics/sprites/monster8.xml, + data/graphics/sprites/monster9.xml, + data/graphics/sprites/monster11.xml, + data/graphics/sprites/monster13.xml, + data/graphics/sprites/monster0.xml: Adjusted the animation speed of + several monsters. + +2006-09-03 Bjørn Lindeijer + + * src/floor_item.cpp, src/gui/equipmentwindow.cpp, src/gui/sell.cpp, + src/gui/trade.cpp, src/gui/inventorywindow.h, + src/gui/selectionlistener.h, src/gui/itemcontainer.h, + src/gui/inventorywindow.cpp, src/gui/buy.cpp, + src/gui/itemcontainer.cpp, src/gui/popupmenu.cpp, src/item.h, + src/net/inventoryhandler.cpp, src/Makefile.am, + src/resources/itemmanager.h, src/resources/iteminfo.cpp, + src/resources/iteminfo.h, src/resources/itemmanager.cpp: Introduced + SelectionListener to fix updating problem in inventory window (should + also be used to fix similar problem in trade, buy and sell dialogs). + Made the ItemInfo be passed around as a reference instead of a pointer, + since it is never NULL. + * src/gui/trade.cpp, src/gui/trade.h: Fixed updating of labels in + trade window. + * src/gui/sell.cpp, src/gui/listbox.h, src/gui/inventorywindow.h, + src/gui/buy.h, src/gui/buy.cpp, src/gui/sell.h, src/gui/listbox.cpp: + Fixed updating of labels in buy and sell dialogs. Also made our + listbox respond to mouse dragging to change the selection. + +2006-09-02 Bernard Lidicky + + * src/game.cpp, src/beingmanager.h, src/gui/gui.cpp, + src/beingmanager.cpp, src/localplayer.h, README, + data/help/commands.txt, NEWS: Added targeting nearest monster with + either keyboard or mouse. Also made clicking beings in general a bit + easier (patch applied by Bjørn Lindeijer). + 2006-09-02 Bjørn Lindeijer * src/gui/serverdialog.cpp, src/main.cpp: Fixed crash when using short @@ -32,10 +236,22 @@ 2006-09-01 Eugenio Favalli + * data/graphics/sprites/monster19.png, + data/graphics/sprites/monster19.xml, data/graphics/tiles/arena.png, + data/graphics/tiles/cave.png, data/maps/new_17-1.tmx.gz, + data/maps/new_6-1.tmx.gz: Added new big cave map, lamp-snake monster, + improved arena map. * src/gui/serverdialog.cpp, src/gui/serverdialog.h, src/net/network.h: Fixed some header issues. * The Mana World.dev, tmw.cbp: Updated project files. +2006-08-30 Philipp Sehmisch + + * data/graphics/sprites/item007.png, + data/graphics/sprites/item007.xml, data/graphics/sprites/item009.png, + data/graphics/sprites/item009.xml: + Added sprites for miners helm and standard headband. + 2006-08-30 Yohann Ferreira * src/main.cpp, src/main.h, src/Makefile.am, src/gui/connection.h, @@ -44,17 +260,29 @@ with an unskinned dropdown. Upgraded also the connection window a bit to handle Cancelling more gracefully. -2006-08-27 Guillaume Melquiond +2006-08-29 Bjørn Lindeijer - * src/engine.cpp, src/gui/gui.cpp: Fixed merge issues: printfs and - inconsistency between view and camera variables. Fixed lazy scrolling: - there is no "freaking out" when the correct function is used. + * src/map.cpp, src/beingmanager.h, src/gui/minimap.cpp, + src/engine.cpp, src/beingmanager.cpp: It's better to use a reference + when you don't need a pointer. + * NEWS: Updated with addition of config file option. -2006-08-28 Bjørn Lindeijer +2006-08-29 Andrew Harrison - * src/gui/gui.cpp: Fixed crash when map is not loaded yet. - * src/net/beinghandler.cpp, src/net/protocol.h: Added support for - entering monsters. + * src/main.cpp: Added command line option to specify which + configuration file to use (patch applied by Bjørn Lindeijer). + +2006-08-29 Matthias Hartmann + + * data/graphics/sprites/item006.png, + data/graphics/sprites/item006.xml, data/graphics/sprites/item008.xml: + Fixed fancy hat + silk headband positions. + +2006-08-29 Philipp Sehmisch + + * data/graphics/sprites/item008.png, + data/graphics/sprites/item008.xml, data/graphics/sprites/Makefile.am: + Added fancy hat sprite. 2006-08-28 Philipp Sehmisch @@ -70,6 +298,12 @@ data/graphics/sprites/item006.xml, data/graphics/sprites/Makefile.am: Added headband and fixed svn properties. +2006-08-28 Bjørn Lindeijer + + * src/gui/gui.cpp: Fixed crash when map is not loaded yet. + * src/net/beinghandler.cpp, src/net/protocol.h: Added support for + entering monsters. + 2006-08-27 Guillaume Melquiond * src/localplayer.cpp, src/net/protocol.h: Send move message @@ -89,11 +323,14 @@ src/monster.cpp, src/player.h: Cleaned the logic members. * src/engine.cpp, src/localplayer.cpp, src/gui/gui.cpp, src/being.cpp, src/being.h: Implemented pixel-grained movements. + * src/engine.cpp, src/gui/gui.cpp: Fixed merge issues: printfs and + inconsistency between view and camera variables. Fixed lazy scrolling: + there is no "freaking out" when the correct function is used. 2006-08-27 Bjørn Lindeijer - * src/net/inventoryhandler.cpp: Applied patch by AHarrison that adds - item pickup messages to the chat window. + * src/net/inventoryhandler.cpp: Applied patch by Andrew Harrison that + adds item pickup messages to the chat window. * NEWS: Updated with some recently added and fixed issues. Doesn't mention any of the recent content updates yet. * src/localplayer.cpp, src/gui/sell.cpp, src/gui/trade.cpp, @@ -173,7 +410,7 @@ * data/help/commands.txt, README, src/game.cpp, src/gui/chat.cpp, src/gui/window.cpp, src/gui/window.h: Added support for sticky windows - as discussed with doener. Patch by AHarrison. + as discussed with doener. Patch by Andrew Harrison. * data/items.xml: Added jeans shorts. 2006-08-24 Philipp Sehmisch @@ -235,11 +472,11 @@ 2006-08-20 Yohann Ferreira - * data/graphics/sprites/Makefile.am : Following the splitting from + * data/graphics/sprites/Makefile.am: Following the splitting from Philipp, moved out the items.png file from the Makefile.am. - * debian/control, debian/tmw-data.install : Updated debian package + * debian/control, debian/tmw-data.install: Updated debian package creation process. - * src/Makefile.am : Added iteminfo.cpp to avoid an undefined reference + * src/Makefile.am: Added iteminfo.cpp to avoid an undefined reference with gcc 4.1.2. Happy to be back :) 2006-08-20 Bjørn Lindeijer @@ -288,13 +525,13 @@ * src/itemmanager.cpp, data/items.xml: Replaced indices on the item spriteset with filenames. added names and descriptions for all missing items. Changed names and dascriptions of some items. - * src/engine.cpp: removed global item spriteset. + * src/engine.cpp: Removed global item spriteset. * src/floor_item.cpp, src/floor_item.h, src/iteminfo.cpp, src/iteminfo.h, src/equipmentwindow.cpp, src/equipmentwindow.h, - src/itemcontainer.cpp, src/itemcontainer.h: the iteminfo class now + src/itemcontainer.cpp, src/itemcontainer.h: The iteminfo class now provides a pointer to the item icon image instead of providing the index on the item spriteset. - * data/graphics/tiles/trans_desert-woodland.png: added transmission + * data/graphics/tiles/trans_desert-woodland.png: Added transmission tileset between desert and woodland. 2006-08-15 Bjørn Lindeijer @@ -527,8 +764,8 @@ char server selection dialog, and added character visualization in character selection dialog. * data/graphics/sprites/Makefile.am, data/graphics/tiles/Makefile.am, - data/maps/Makefile.am, data/maps/new_13-1.tmx.gz: Added map with inside - of snow village buildings and fixed makefiles. + data/maps/Makefile.am, data/maps/new_13-1.tmx.gz: Added map with + inside of snow village buildings and fixed makefiles. * src/being.cpp, src/being.h, src/player.cpp: Fixed direction and action issues when changing appeareance, frames are still out of sync. * data/maps/Makefile.am, data/maps/new_14-1.tmx.gz, @@ -704,8 +941,8 @@ 2006-07-12 Frode Lindeijer - * /tmw/trunk/data/graphics/sprites/item001.png: Completed the cotton - shirt equipment graphic. + * data/graphics/sprites/item001.png: Completed the cotton shirt + equipment graphic. 2006-07-06 Philipp Sehmisch @@ -755,68 +992,20 @@ * src/being.h, src/being.cpp, src/npc.cpp, src/npc.h, src/monster.cpp, src/monster.h: Moved all drawing code from the Being based classes into Being. - * data/graphics/sprites/monster0.png, - data/graphics/sprites/monster1.png, - data/graphics/sprites/monster2.png, - data/graphics/sprites/monster3.png, - data/graphics/sprites/monster4.png, - data/graphics/sprites/monster5.png, - data/graphics/sprites/monster6.png, - data/graphics/sprites/monster7.png, - data/graphics/sprites/monster8.png, - data/graphics/sprites/monster9.png, - data/graphics/sprites/monster10.png, - data/graphics/sprites/monster11.png, - data/graphics/sprites/monster12.png, - data/graphics/sprites/monster13.png, - data/graphics/sprites/monster14.png, - data/graphics/sprites/monster15.png, - data/graphics/sprites/monster16.png, - data/graphics/sprites/monster17.png: Resized and reorganized the + * data/graphics/sprites/monster*.png: Resized and reorganized the monster spritesets to fit the new animation system (thanks, Bjørn). - * data/graphics/sprites/monster0.xml, - data/graphics/sprites/monster1.xml, - data/graphics/sprites/monster2.xml, - data/graphics/sprites/monster3.xml, - data/graphics/sprites/monster4.xml, - data/graphics/sprites/monster5.xml, - data/graphics/sprites/monster6.xml, - data/graphics/sprites/monster7.xml, - data/graphics/sprites/monster8.xml, - data/graphics/sprites/monster9.xml, - data/graphics/sprites/monster10.xml, - data/graphics/sprites/monster11.xml, - data/graphics/sprites/monster12.xml, - data/graphics/sprites/monster13.xml, - data/graphics/sprites/monster14.xml, - data/graphics/sprites/monster15.xml, - data/graphics/sprites/monster16.xml, - data/graphics/sprites/monster17.xml: Added animation files for all + * data/graphics/sprites/monster*.xml: Added animation files for all monsters. * src/animation.cpp: The offset values of the Frames of animated sprites are now modified so every frame is drawn centered. - * data/graphics/sprites/hairstyle0.xml, - data/graphics/sprites/hairstyle1.xml, - data/graphics/sprites/hairstyle2.xml, - data/graphics/sprites/hairstyle3.xml, - data/graphics/sprites/hairstyle4.xml, - data/graphics/sprites/hairstyle5.xml, - data/graphics/sprites/hairstyle6.xml, - data/graphics/sprites/hairstyle7.xml: Retuned the offsets of the hair - sprites. + * data/graphics/sprites/hairstyle*.xml: Retuned the offsets of the + hair sprites. * src/animation.cpp: Small stability fix. * src/being.cpp, src/being.h: weapon animation now uses the new animation system. * data/graphics/sprites/player_male_base.xml data/graphics/sprites/player_female_base.xml - data/graphics/sprites/hairstyle0.xml, - data/graphics/sprites/hairstyle1.xml, - data/graphics/sprites/hairstyle2.xml, - data/graphics/sprites/hairstyle3.xml, - data/graphics/sprites/hairstyle4.xml, - data/graphics/sprites/hairstyle5.xml, - data/graphics/sprites/hairstyle6.xml, - data/graphics/sprites/hairstyle7.xml: Tuned walk speed and added bow + data/graphics/sprites/hairstyle*.xml: Tuned walk speed and added bow animations. 2006-07-03 Eugenio Favalli diff --git a/NEWS b/NEWS index cf837a25..2b77dca3 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,18 @@ -0.0.21 (.. September 2006) +0.0.21 (17 September 2006) - Added item pickup messages to the chat dialog - Added XP bar to ministatus in the top left - Added configurable smooth and lazy scrolling - Added option to turn off the joystick -- Added --playername command line option for automatic character picking +- Added --playername option for automatic character picking +- Added --configfile option for specifying which configuration file to use +- Added shortcut and middle mouse button for targetting nearest monster +- Added support for map effect overlays +- Fixed FPS limiter - Fixed updating system on Windows - Fixed player animations going out of sync on changing equipment or hairstyle - Fixed SDL_image configure check on some systems by first checking for libpng +- Fixed big memory leak when using OpenGL +- Updated to work with Guichan 0.5.0 (older versions no longer supported) 0.0.20 (24 July 2006) - Added new hairstyle, and some fixes to the old ones diff --git a/README b/README index 5fad4312..0313fac3 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ THE MANA WORLD ============== - Version: 0.0.20 Date: 23/07/2006 + Version: 0.0.21 Date: 17/09/2006 Development team: @@ -53,6 +53,7 @@ Use arrow keys to move around. Other keys: - Alt + S sit down / stand up - Alt + F toggle debug pathfinding feature - Alt + P take screenshot +- A target nearest monster - H hide all non-sticky windows - G or Z pick up item - Enter focus chat window / send message diff --git a/data/graphics/images/Makefile.am b/data/graphics/images/Makefile.am index e0707698..fb54cb95 100644 --- a/data/graphics/images/Makefile.am +++ b/data/graphics/images/Makefile.am @@ -7,7 +7,12 @@ images_DATA = \ minimap_new_1-1.png \ minimap_new_2-1.png \ minimap_new_3-1.png \ - minimap_new_5-1.png + minimap_new_5-1.png \ + minimap_new_7-1.png \ + minimap_new_9-1.png \ + minimap_new_14-1.png \ + minimap_new_15-1.png \ + minimap_new_16-1.png EXTRA_DIST = \ - $(images_DATA) + $(images_DATA) \ No newline at end of file diff --git a/data/help/changes.txt b/data/help/changes.txt index 2d0f9d86..f8a3eb67 100644 --- a/data/help/changes.txt +++ b/data/help/changes.txt @@ -3,6 +3,37 @@ ##3 === RECENT CHANGES === + 0.0.21 (17 September 2006) + - Added item pickup messages to the chat dialog + - Added XP bar to ministatus in the top left + - Added configurable smooth and lazy scrolling + - Added option to turn off the joystick + - Added --playername option for automatic character picking + - Added --configfile option for specifying which configuration file to use + - Added shortcut and middle mouse button for targetting nearest monster + - Added support for map effect overlays + - Fixed FPS limiter + - Fixed updating system on Windows + - Fixed player animations going out of sync on changing equipment or hairstyle + - Fixed SDL_image configure check on some systems by first checking for libpng + - Fixed big memory leak when using OpenGL + - Updated to work with Guichan 0.5.0 (older versions no longer supported) + + 0.0.20 (24 July 2006) + - Added new hairstyle, and some fixes to the old ones + - Added slider to set FPS limit + - Added visible equipments + - Added new maps and monsters + - Added female characters + - Implemented a new animation system + - Updated the updating system + - Reduced size of textures to stay within the limits of some OpenGL drivers + - Fixed connection not being shut down completely in case of an error + - Fixed min size of a window when resizing + - Fixed some maps issues + - Some fixes to monsters and player graphics + - Minor bug fixes and lots of code cleanups + 0.0.19 (6 March 2006) - Added --username, --password and --defaults command line options diff --git a/data/help/commands.txt b/data/help/commands.txt index 37c77df2..ab93b54e 100644 --- a/data/help/commands.txt +++ b/data/help/commands.txt @@ -23,6 +23,7 @@ ##2Alt + S##P sit down / stand up ##2Alt + F##P toggle debug pathfinding feature ##2Alt + P##P take screenshot + ##2A##P target nearest monster ##2H##P hide all non-sticky windows ##2G or Z##P pick up item ##2Enter##P focus chat window / send message diff --git a/data/help/header.txt b/data/help/header.txt index d9188a3b..30c1dc93 100644 --- a/data/help/header.txt +++ b/data/help/header.txt @@ -2,7 +2,7 @@ ##1 T H E M A N A W O R L D ##1 ========================================== - ##2Version:##6 0.0.20 ##2Date:##6 23 July 2006 + ##2Version:##6 0.0.21 ##2Date:##6 17 September 2006 ##2 Website: http://themanaworld.org diff --git a/debian/changelog b/debian/changelog index eb420daf..5e71e51e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +tmw (0.0.21-1) unstable; urgency=low + + * New upstream release: + * Now linked against libguichan-0.5.0. + * Readded the correct music package. + + -- FERREIRA Yohann Wed, 27 Sep 2006 21:40:33 +0200 + tmw (0.0.20-1) unstable; urgency=low * Make use of a own desktop file for the Debian Package. Close the missing icon bug. diff --git a/debian/tmw-music.install b/debian/tmw-music.install index b3494726..b4a17199 100644 --- a/debian/tmw-music.install +++ b/debian/tmw-music.install @@ -1 +1,3 @@ data/music/*.ogg usr/share/games/tmw/data/music +data/music/*.mp3 usr/share/games/tmw/data/music + diff --git a/src/Makefile.am b/src/Makefile.am index 01f8a3b2..b621c63e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,8 @@ AUTOMAKE_OPTIONS = subdir-objects bin_PROGRAMS = tmw tmw_SOURCES = graphic/imagerect.h \ + gui/widgets/dropdown.cpp \ + gui/widgets/dropdown.h \ gui/browserbox.cpp \ gui/browserbox.h \ gui/buddywindow.cpp \ @@ -77,6 +79,7 @@ tmw_SOURCES = graphic/imagerect.h \ gui/register.h \ gui/scrollarea.cpp \ gui/scrollarea.h \ + gui/selectionlistener.h \ gui/sell.cpp \ gui/sell.h \ gui/serverdialog.cpp \ diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index f984d13f..3815f04a 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -18,7 +18,7 @@ * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: animation.cpp 2430 2006-07-24 00:13:24Z b_lindeijer $ + * $Id$ */ #include "animatedsprite.h" @@ -90,14 +90,9 @@ AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): // get action else if (xmlStrEqual(node->name, BAD_CAST "action")) { - std::string name = getProperty(node, "name", ""); + std::string actionName = getProperty(node, "name", ""); std::string imageset = getProperty(node, "imageset", ""); - if (name.empty()) - { - logger->log("Warning: unnamed action in %s", - animationFile.c_str()); - } if (mSpritesets.find(imageset) == mSpritesets.end()) { logger->log("Warning: imageset \"%s\" not defined in %s", imageset.c_str(), @@ -107,10 +102,25 @@ AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): continue; } - Action *action = new Action(); + SpriteAction actionType = makeSpriteAction(actionName); + if (actionType == ACTION_INVALID) + { + logger->log("Warning: Unknown action \"%s\" defined in %s", + actionName.c_str(), + animationFile.c_str()); + continue; + } + Action *action = new Action(); action->setSpriteset(mSpritesets[imageset]); - mActions[makeSpriteAction(name)] = action; + mActions[actionType] = action; + + // When first action set it as default direction + if (mActions.empty()) + { + mActions[ACTION_DEFAULT] = action; + } + // get animations for (xmlNodePtr animationNode = node->xmlChildrenNode; @@ -121,9 +131,20 @@ AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): if (!xmlStrEqual(animationNode->name, BAD_CAST "animation")) continue; - std::string dir = getProperty(animationNode, "direction", ""); + std::string directionName = getProperty(animationNode, "direction", ""); + + SpriteDirection directionType = makeSpriteDirection(directionName); + if (directionType == DIRECTION_INVALID) + { + logger->log("Warning: Unknown direction \"%s\" defined for action %s in %s", + directionName.c_str(), + actionName.c_str(), + animationFile.c_str()); + continue; + } + Animation *animation = new Animation(); - action->setAnimation(makeSpriteDirection(dir), animation); + action->setAnimation(directionType, animation); // Get animation phases for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode; @@ -156,12 +177,17 @@ AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): start++; } } + else if (xmlStrEqual(phaseNode->name, BAD_CAST "end")) + { + animation->addTerminator(); + }; } // for phaseNode } // for animationNode } // if "" else if "" } // for node // Complete missing actions + substituteAction(ACTION_STAND, ACTION_DEFAULT); substituteAction(ACTION_WALK, ACTION_STAND); substituteAction(ACTION_WALK, ACTION_RUN); substituteAction(ACTION_ATTACK, ACTION_STAND); @@ -247,7 +273,7 @@ AnimatedSprite::reset() } void -AnimatedSprite::play(SpriteAction action, int time) +AnimatedSprite::play(SpriteAction action) { ActionIterator i = mActions.find(action); @@ -262,31 +288,31 @@ AnimatedSprite::play(SpriteAction action, int time) if (mAction != i->second) { mAction = i->second; - mLastTime = 0; - } - - if (!mAction || !time) - mSpeed = 1.0f; - else { - int animationLength = mAction->getAnimation(mDirection)->getLength(); - mSpeed = (float) animationLength / time; + //mAction->reset(); } } void AnimatedSprite::update(int time) { + bool notFinished = true; // Avoid freaking out at first frame or when tick_time overflows if (time < mLastTime || mLastTime == 0) mLastTime = time; - // If not enough time have passed yet, do nothing + // If not enough time has passed yet, do nothing if (time > mLastTime && mAction) { Animation *animation = mAction->getAnimation(mDirection); - animation->update((unsigned int)((time - mLastTime) * mSpeed)); + if (animation != NULL) { + notFinished = animation->update((unsigned int)(time - mLastTime));} mLastTime = time; } + + if (!notFinished) + { + play(ACTION_STAND); + } } bool @@ -296,6 +322,8 @@ AnimatedSprite::draw(Graphics* graphics, Sint32 posX, Sint32 posY) const return false; Animation *animation = mAction->getAnimation(mDirection); + if (animation == NULL) return false; + int phase = animation->getCurrentPhase(); if (phase < 0) return false; @@ -322,6 +350,9 @@ AnimatedSprite::getHeight() const SpriteAction AnimatedSprite::makeSpriteAction(const std::string& action) { + if (action == "" || action == "default") { + return ACTION_DEFAULT; + } if (action == "stand") { return ACTION_STAND; } @@ -365,14 +396,17 @@ AnimatedSprite::makeSpriteAction(const std::string& action) return ACTION_DEAD; } else { - return ACTION_DEFAULT; + return ACTION_INVALID; } } SpriteDirection AnimatedSprite::makeSpriteDirection(const std::string& direction) { - if (direction == "up") { + if (direction == "" || direction == "default") { + return DIRECTION_DEFAULT; + } + else if (direction == "up") { return DIRECTION_UP; } else if (direction == "left") { @@ -381,7 +415,10 @@ AnimatedSprite::makeSpriteDirection(const std::string& direction) else if (direction == "right") { return DIRECTION_RIGHT; } - else { + else if (direction == "down") { return DIRECTION_DOWN; } + else { + return DIRECTION_INVALID; + }; } diff --git a/src/animatedsprite.h b/src/animatedsprite.h index b73bdb5c..bda612ab 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -18,7 +18,7 @@ * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: animation.h 2430 2006-07-24 00:13:24Z b_lindeijer $ + * $Id$ */ #ifndef _TMW_ANIMATEDSPRITE_H @@ -50,15 +50,18 @@ enum SpriteAction ACTION_SIT, ACTION_SLEEP, ACTION_HURT, - ACTION_DEAD + ACTION_DEAD, + ACTION_INVALID }; enum SpriteDirection { - DIRECTION_DOWN = 0, + DIRECTION_DEFAULT = 0, + DIRECTION_DOWN, DIRECTION_UP, DIRECTION_LEFT, - DIRECTION_RIGHT + DIRECTION_RIGHT, + DIRECTION_INVALID }; /** @@ -85,11 +88,10 @@ class AnimatedSprite reset(); /** - * Plays an action using the current direction that will have a - * duration of the specified time, 0 means default. + * Plays an action using the current direction */ void - play(SpriteAction action, int time = 0); + play(SpriteAction action); /** * Inform the animation of the passed time so that it can output the diff --git a/src/animation.cpp b/src/animation.cpp index c1b27ebd..98a4abb8 100644 --- a/src/animation.cpp +++ b/src/animation.cpp @@ -39,45 +39,68 @@ Animation::reset() iCurrentPhase = mAnimationPhases.begin(); } -void + +bool Animation::update(unsigned int time) { mTime += time; if (mAnimationPhases.empty()) - return; + return true; + if (isTerminator(*iCurrentPhase)) + return false; unsigned int delay = iCurrentPhase->delay; - if (!delay) - return; while (mTime > delay) { + if (!delay) + return true; mTime -= delay; iCurrentPhase++; if (iCurrentPhase == mAnimationPhases.end()) { iCurrentPhase = mAnimationPhases.begin(); } + if (isTerminator(*iCurrentPhase)) + return false; + delay = iCurrentPhase->delay; } + return true; } + int Animation::getCurrentPhase() const { return mAnimationPhases.empty() ? -1 : iCurrentPhase->image; } + void Animation::addPhase(int image, unsigned int delay, int offsetX, int offsetY) { //add new phase to animation list - AnimationPhase newPhase = { image, delay, offsetX, offsetY }; + AnimationPhase newPhase = { image, delay, offsetX, offsetY}; mAnimationPhases.push_back(newPhase); //reset animation circle iCurrentPhase = mAnimationPhases.begin(); } +void +Animation::addTerminator() +{ + AnimationPhase terminator = { -1, 0, 0, 0}; + mAnimationPhases.push_back(terminator); + iCurrentPhase = mAnimationPhases.begin(); +} + +bool +Animation::isTerminator(AnimationPhase candidate) +{ + return (candidate.image < 0); +} + int Animation::getLength() { diff --git a/src/animation.h b/src/animation.h index 60dcd287..605d8cb1 100644 --- a/src/animation.h +++ b/src/animation.h @@ -61,10 +61,25 @@ class Animation void reset(); + /** + * Appends a new animation at the end of the sequence + */ void addPhase(int image, unsigned int delay, int offsetX, int offsetY); + /** + * Appends an animation terminator that states that the animation + * should not loop + */ void + addTerminator(); + + /** + * Updates animation phase. + * true indicates a still running animation while false indicates a + * finished animation + */ + bool update(unsigned int time); int @@ -89,6 +104,7 @@ class Animation getLength(); protected: + static bool isTerminator(AnimationPhase); std::list mAnimationPhases; std::list::iterator iCurrentPhase; unsigned int mTime; diff --git a/src/being.cpp b/src/being.cpp index 982b0ebf..4d542753 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -331,10 +331,24 @@ Being::setAction(Uint8 action) currentAction = ACTION_ATTACK; break; } + for (int i = 0; i < VECTOREND_SPRITE; i++) + { + if (mSprites[i]) + { + mSprites[i]->reset(); + } + } }; break; case MONSTER_ATTACK: currentAction = ACTION_ATTACK; + for (int i = 0; i < VECTOREND_SPRITE; i++) + { + if (mSprites[i]) + { + mSprites[i]->reset(); + } + } break; case DEAD: currentAction = ACTION_DEAD; @@ -346,16 +360,7 @@ Being::setAction(Uint8 action) for (int i = 0; i < VECTOREND_SPRITE; i++) { - if (!mSprites[i]) - continue; - - if (currentAction == ACTION_ATTACK || - currentAction == ACTION_ATTACK_STAB || - currentAction == ACTION_ATTACK_BOW) - { - mSprites[i]->play(currentAction, mAttackSpeed); - } - else + if (mSprites[i]) { mSprites[i]->play(currentAction); } diff --git a/src/beingmanager.cpp b/src/beingmanager.cpp index d2db055a..30b68ee2 100644 --- a/src/beingmanager.cpp +++ b/src/beingmanager.cpp @@ -113,9 +113,9 @@ Being* BeingManager::findBeing(Uint16 x, Uint16 y, Being::Type type) return (i == mBeings.end()) ? NULL : *i; } -Beings* BeingManager::getAll() +Beings& BeingManager::getAll() { - return &mBeings; + return mBeings; } void BeingManager::logic() @@ -153,3 +153,28 @@ void BeingManager::clear() mBeings.push_back(player_node); } } + +Being* BeingManager::findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist, + Being::Type type) +{ + Being *closestBeing = NULL; + int dist = 0; + + for (BeingIterator i = mBeings.begin(); i != mBeings.end(); i++) + { + Being *being = (*i); + int d = abs(being->mX - x) + abs(being->mY - y); + + if ((being->getType() == type || type == Being::UNKNOWN) + && (d < dist || closestBeing == NULL) // it is closer + && being->mAction != Being::DEAD // no dead beings + && being->mAction != Being::MONSTER_DEAD + ) + { + dist = d; + closestBeing = being; + } + } + + return (maxdist >= dist) ? closestBeing : NULL; +} diff --git a/src/beingmanager.h b/src/beingmanager.h index c32884a0..15a347de 100644 --- a/src/beingmanager.h +++ b/src/beingmanager.h @@ -46,29 +46,38 @@ class BeingManager void setPlayer(LocalPlayer *player); /** - * Create a being and add it to the list of beings + * Create a being and add it to the list of beings. */ Being* createBeing(Uint16 id, Uint16 job); /** - * Remove a Being + * Remove a Being. */ void destroyBeing(Being *being); /** - * Return a specific id Being + * Return a specific id Being. */ Being* findBeing(Uint16 id); /** - * Return a being at specific coordinates + * Return a being at specific coordinates. */ Being* findBeing(Uint16 x, Uint16 y, Being::Type type = Being::UNKNOWN); + /** + * Return a being nearest to specific coordinates. + * + * \param maxdist maximal distance. If minimal distance is larger, + * no being is returned + */ + Being* findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist, + Being::Type type = Being::UNKNOWN); + /** * Returns the whole list of beings */ - Beings* getAll(); + Beings& getAll(); /** * Logic. diff --git a/src/engine.cpp b/src/engine.cpp index 253a8288..231313c4 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -266,8 +266,8 @@ void Engine::draw(Graphics *graphics) } // Draw player nickname, speech, and emotion sprite as needed - Beings *beings = beingManager->getAll(); - for (BeingIterator i = beings->begin(); i != beings->end(); i++) + Beings &beings = beingManager->getAll(); + for (BeingIterator i = beings.begin(); i != beings.end(); i++) { (*i)->drawSpeech(graphics, -camera_x, -camera_y); (*i)->drawName(graphics, -camera_x, -camera_y); diff --git a/src/floor_item.cpp b/src/floor_item.cpp index edd5d4a7..9a179a21 100644 --- a/src/floor_item.cpp +++ b/src/floor_item.cpp @@ -42,7 +42,7 @@ FloorItem::FloorItem(unsigned int id, mMap(map) { // Retrieve item image from item info - mImage = itemDb->getItemInfo(itemId)->getImage(); + mImage = itemDb->getItemInfo(itemId).getImage(); // Add ourselves to the map mSpriteIterator = mMap->addSprite(this); @@ -50,6 +50,6 @@ FloorItem::FloorItem(unsigned int id, FloorItem::~FloorItem() { - // Remove and delete the representative sprite + // Remove ourselves from the map mMap->removeSprite(mSpriteIterator); } diff --git a/src/game.cpp b/src/game.cpp index f5ebe095..5e4c24c2 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -202,9 +202,9 @@ void createGuiWindows() minimap->getHeight() + 30);*/ // Set initial window visibility - chatWindow->setSticky(true); - miniStatusWindow->setSticky(true); - menuWindow->setSticky(true); +// chatWindow->setSticky(true); +// miniStatusWindow->setSticky(true); +// menuWindow->setSticky(true); chatWindow->setVisible(true); miniStatusWindow->setVisible(true); @@ -277,6 +277,10 @@ Game::Game(): SDL_AddTimer(10, nextTick, NULL); // Logic counter SDL_AddTimer(1000, nextSecond, NULL); // Seconds counter + // Initialize frame limiting + config.addListener("fpslimit", this); + optionChanged("fpslimit"); + // Initialize beings beingManager->setPlayer(player_node); @@ -339,12 +343,23 @@ bool saveScreenshot(SDL_Surface *screenshot) return ImageWriter::writePNG(screenshot, filename.str()); } +void Game::optionChanged(const std::string &name) +{ + int fpsLimit = (int) config.getValue("fpslimit", 0); + + // Calculate new minimum frame time + mMinFrameTime = fpsLimit ? 1000 / fpsLimit : 0; + + // Reset draw time to current time + mDrawTime = tick_time * 10; +} + void Game::logic() { + // mDrawTime has a higher granularity than gameTime in order to be able to + // work with minimum frame durations in milliseconds. int gameTime = tick_time; - int drawTime = tick_time * 10; - int delta = 0; - int fpsLimit = 0; + mDrawTime = tick_time * 10; while (!done) { @@ -356,23 +371,35 @@ void Game::logic() gameTime++; } + // This is done because at some point tick_time will wrap. gameTime = tick_time; - fpsLimit = (int)config.getValue("fpslimit", 50); - delta = fpsLimit ? 1000 / fpsLimit : 0; - - // Update the screen when application is active, delay otherwise - if (SDL_GetAppState() & SDL_APPACTIVE && - (abs(tick_time * 10 - drawTime) >= delta)) + // Update the screen when application is active, delay otherwise. + if (SDL_GetAppState() & SDL_APPACTIVE) { - frame++; - engine->draw(graphics); - graphics->updateScreen(); - drawTime += delta; + // Draw a frame if either frames are not limited or enough time has + // passed since the last frame. + if (!mMinFrameTime || + get_elapsed_time(mDrawTime / 10) > mMinFrameTime) + { + frame++; + engine->draw(graphics); + graphics->updateScreen(); + mDrawTime += mMinFrameTime; + + // Make sure to wrap mDrawTime, since tick_time will wrap. + if (mDrawTime > MAX_TIME * 10) + mDrawTime -= MAX_TIME * 10; + } + else + { + SDL_Delay(10); + } } else { SDL_Delay(10); + mDrawTime = tick_time * 10; } // Handle network stuff @@ -463,10 +490,7 @@ void Game::handleInput() // Attempt to hide all windows case SDLK_h: - chatWindow->setVisible(false); - miniStatusWindow->setVisible(false); statusWindow->setVisible(false); - menuWindow->setVisible(false); buyDialog->setVisible(false); sellDialog->setVisible(false); buySellDialog->setVisible(false); @@ -474,12 +498,9 @@ void Game::handleInput() npcTextDialog->setVisible(false); npcListDialog->setVisible(false); skillDialog->setVisible(false); - //newSkillWindow->setVisible(false); setupWindow->setVisible(false); equipmentWindow->setVisible(false); chargeDialog->setVisible(false); - tradeWindow->setVisible(false); - //buddyWindow->setVisible(false); helpWindow->setVisible(false); debugWindow->setVisible(false); break; @@ -679,6 +700,18 @@ void Game::handleInput() player_node->attack(target, newTarget); } + // Target the nearest monster if 'a' pressed + if (keys[SDLK_a]) + { + Being *target = + beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER); + + if (target) + { + player_node->setTarget(target); + } + } + if (joystick) { if (joystick->buttonPressed(1)) diff --git a/src/game.h b/src/game.h index 7330052a..19a6054a 100644 --- a/src/game.h +++ b/src/game.h @@ -27,6 +27,8 @@ #include #include +#include "configlistener.h" + #define SPEECH_TIME 80 #define SPEECH_MAX_TIME 100 @@ -36,7 +38,7 @@ extern std::string map_path; extern volatile int fps; extern volatile int tick_time; -class Game +class Game : public ConfigListener { public: Game(); @@ -46,7 +48,15 @@ class Game void handleInput(); - protected: + void optionChanged(const std::string &name); + + private: + /** Used to determine whether to draw the next frame. */ + int mDrawTime; + + /** The minimum frame time (used for frame limiting). */ + int mMinFrameTime; + typedef std::auto_ptr MessageHandlerPtr; MessageHandlerPtr mBeingHandler; MessageHandlerPtr mBuySellHandler; @@ -61,8 +71,7 @@ class Game }; /** - * Returns elapsed time. (Warning: very unsafe function, it supposes the delay - * is always < 10 seconds) + * Returns elapsed time. (Warning: supposes the delay is always < 100 seconds) */ int get_elapsed_time(int start_time); diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 165fa7dc..ae779503 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -91,6 +91,7 @@ BuyDialog::BuyDialog(): mSlider->setEventId("slider"); mItemList->addActionListener(this); + mItemList->addSelectionListener(this); mSlider->addActionListener(this); add(mScrollArea); @@ -140,7 +141,8 @@ void BuyDialog::addItem(short id, int price) { ITEM_SHOP item_shop; - item_shop.name = itemDb->getItemInfo(id)->getName() + " " + toString(price) + " GP"; + item_shop.name = itemDb->getItemInfo(id).getName() + " " + + toString(price) + " GP"; item_shop.price = price; item_shop.id = id; @@ -152,7 +154,8 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) { int selectedItem = mItemList->getSelected(); - if (eventId == "item") { + if (eventId == "item") + { // Reset amount of items and update labels mAmountItems = 0; mSlider->setValue(0); @@ -175,23 +178,27 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) mIncreaseButton->setEnabled(mMaxItems > 0); mSlider->setEnabled(mMaxItems > 0); } - else if (eventId == "quit") { + else if (eventId == "quit") + { setVisible(false); current_npc = 0; } // The following actions require a valid selection - if (selectedItem < 0 || selectedItem >= int(mShopItems->size())) { + if (selectedItem < 0 || selectedItem >= int(mShopItems->size())) + { return; } bool updateButtonsAndLabels = false; - if (eventId == "slider") { + if (eventId == "slider") + { mAmountItems = (int)(mSlider->getValue() * mMaxItems); updateButtonsAndLabels = true; } - else if (eventId == "+") { + else if (eventId == "+") + { if (mAmountItems < mMaxItems) { mAmountItems++; } else { @@ -201,7 +208,8 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) mSlider->setValue(double(mAmountItems)/double(mMaxItems)); updateButtonsAndLabels = true; } - else if (eventId == "-") { + else if (eventId == "-") + { if (mAmountItems > 0) { mAmountItems--; } else { @@ -211,7 +219,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) mSlider->setValue(double(mAmountItems)/double(mMaxItems)); updateButtonsAndLabels = true; } - // TODO Actually we'd have a bug elsewhere if this check for the number + // TODO: Actually we'd have a bug elsewhere if this check for the number // of items to be bought ever fails, Bertram removed the assertions, is // there a better way to ensure this fails in an _obivous_ way in C++? else if (eventId == "buy" && (mAmountItems > 0 && @@ -239,7 +247,8 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) } // If anything has changed, we have to update the buttons and labels - if (updateButtonsAndLabels) { + if (updateButtonsAndLabels) + { // Update buttons mIncreaseButton->setEnabled(mAmountItems < mMaxItems); mDecreaseButton->setEnabled(mAmountItems > 0); @@ -255,19 +264,21 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) } } -void BuyDialog::mouseClick(int x, int y, int button, int count) +void BuyDialog::selectionChanged(const SelectionEvent &event) { - Window::mouseClick(x, y, button, count); - int selectedItem = mItemList->getSelected(); + if (selectedItem > -1) { - int itemId = mShopItems->at(selectedItem).id; - ItemInfo *itemInfo = itemDb->getItemInfo(itemId); + const ItemInfo &info = + itemDb->getItemInfo(mShopItems->at(selectedItem).id); - mItemDescLabel->setCaption("Description: " + - itemInfo->getDescription()); - mItemEffectLabel->setCaption("Effect: " + - itemInfo->getEffect()); + mItemDescLabel->setCaption("Description: " + info.getDescription()); + mItemEffectLabel->setCaption("Effect: " + info.getEffect()); + } + else + { + mItemDescLabel->setCaption("Description:"); + mItemEffectLabel->setCaption("Effect:"); } } diff --git a/src/gui/buy.h b/src/gui/buy.h index 0ddea4c4..f5c163e1 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -27,17 +27,19 @@ #include #include "window.h" +#include "selectionlistener.h" #include "../guichanfwd.h" class ShopItems; +class ListBox; /** * The buy dialog. * * \ingroup Interface */ -class BuyDialog : public Window, public gcn::ActionListener +class BuyDialog : public Window, public gcn::ActionListener, SelectionListener { public: /** @@ -78,9 +80,11 @@ class BuyDialog : public Window, public gcn::ActionListener int getNumberOfElements(); /** - * Mouse callback + * Updates the labels according to the selected item. + * + * @see SelectionListener::selectionChanged */ - void mouseClick(int x, int y, int buton, int count); + void selectionChanged(const SelectionEvent &event); /** * Returns the name of item number i in the shop inventory. @@ -92,7 +96,7 @@ class BuyDialog : public Window, public gcn::ActionListener gcn::Button *mQuitButton; gcn::Button *mIncreaseButton; gcn::Button *mDecreaseButton; - gcn::ListBox *mItemList; + ListBox *mItemList; gcn::ScrollArea *mScrollArea; gcn::Label *mItemDescLabel; gcn::Label *mItemEffectLabel; diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 042a5be8..3e6c4a5f 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -224,6 +224,28 @@ void CharSelectDialog::logic() updatePlayerInfo(); } +bool CharSelectDialog::selectByName(const std::string &name) +{ + if (mCharInfo->isLocked()) + return false; + + unsigned int oldPos = mCharInfo->getPos(); + + mCharInfo->select(0); + do { + LocalPlayer *player = mCharInfo->getEntry(); + + if (player && player->getName() == name) + return true; + + mCharInfo->next(); + } while (mCharInfo->getPos()); + + mCharInfo->select(oldPos); + + return false; +} + std::string CharSelectDialog::getName() { return mNameLabel->getCaption(); diff --git a/src/gui/char_select.h b/src/gui/char_select.h index 06881bb5..6d9d1a83 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -54,6 +54,8 @@ class CharSelectDialog : public Window, public gcn::ActionListener void logic(); + bool selectByName(const std::string &name); + /** * Returns name of selected player */ diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index 2cbffde4..ec525c47 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -65,7 +65,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) continue; } - image = item->getInfo()->getImage(); + image = item->getInfo().getImage(); dynamic_cast(graphics)->drawImage( image, 36 * (i % 4) + 10, 36 * (i / 4) + 25); } @@ -76,7 +76,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) return; } - image = item->getInfo()->getImage(); + image = item->getInfo().getImage(); dynamic_cast(graphics)->drawImage(image, 160, 25); graphics->drawText(toString(item->getQuantity()), 170, 62, diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index ecf81712..33852f2b 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -322,6 +322,19 @@ Gui::mousePress(int mx, int my, int button) } } } + + if (button == gcn::MouseInput::MIDDLE) + { + // Find the being nearest to the clicked position + Being *target = beingManager->findNearestLivingBeing( + tilex, tiley, + 20, Being::MONSTER); + + if (target) + { + player_node->setTarget(target); + } + } } void diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 063e8836..ea0fd8c0 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -55,6 +55,8 @@ InventoryWindow::InventoryWindow(): mDropButton = new Button("Drop", "drop", this); mItems = new ItemContainer(player_node->mInventory.get()); + mItems->addSelectionListener(this); + mInvenScroll = new ScrollArea(mItems); mInvenScroll->setPosition(8, 8); mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); @@ -123,33 +125,46 @@ void InventoryWindow::action(const std::string &eventId, gcn::Widget *widget) } } -void InventoryWindow::mouseClick(int x, int y, int button, int count) +void InventoryWindow::selectionChanged(const SelectionEvent &event) { - Window::mouseClick(x, y, button, count); - Item *item = mItems->getItem(); - if (!item) { - return; + // Update name, effect and description + if (!item) + { + mItemNameLabel->setCaption("Name:"); + mItemEffectLabel->setCaption("Effect:"); + mItemDescriptionLabel->setCaption("Description:"); + } + else + { + const ItemInfo& itemInfo = item->getInfo(); + std::string SomeText; + SomeText = "Name: " + itemInfo.getName(); + mItemNameLabel->setCaption(SomeText); + SomeText = "Effect: " + itemInfo.getEffect(); + mItemEffectLabel->setCaption(SomeText); + SomeText = "Description: " + itemInfo.getDescription(); + mItemDescriptionLabel->setCaption(SomeText); + + mItemNameLabel->adjustSize(); + mItemEffectLabel->adjustSize(); + mItemDescriptionLabel->adjustSize(); } +} - // Show Name and Description - std::string SomeText; - SomeText = "Name: " + item->getInfo()->getName(); - mItemNameLabel->setCaption(SomeText); - mItemNameLabel->adjustSize(); - SomeText = "Effect: " + item->getInfo()->getEffect(); - mItemEffectLabel->setCaption(SomeText); - mItemEffectLabel->adjustSize(); - SomeText = "Description: " + item->getInfo()->getDescription(); - mItemDescriptionLabel->setCaption(SomeText); - mItemDescriptionLabel->adjustSize(); +void InventoryWindow::mouseClick(int x, int y, int button, int count) +{ + Window::mouseClick(x, y, button, count); if (button == gcn::MouseInput::RIGHT) { - /* - * convert relative to the window coordinates to - * absolute screen coordinates + Item *item = mItems->getItem(); + + if (!item) return; + + /* Convert relative to the window coordinates to + * absolute screen coordinates. */ int mx = x + getX(); int my = y + getY(); @@ -223,11 +238,6 @@ void InventoryWindow::loadWindowState() updateWidgets(); } -void InventoryWindow::setDefaultSize(int defaultX, int defaultY, int defaultWidth, int defaultHeight) -{ - Window::setDefaultSize(defaultX, defaultY, defaultWidth, defaultHeight); -} - void InventoryWindow::resetToDefaultSize() { Window::resetToDefaultSize(); diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h index da7a7ef2..d46e91e7 100644 --- a/src/gui/inventorywindow.h +++ b/src/gui/inventorywindow.h @@ -27,6 +27,7 @@ #include #include "window.h" +#include "selectionlistener.h" #include "../guichanfwd.h" @@ -38,7 +39,7 @@ class ItemContainer; * * \ingroup Interface */ -class InventoryWindow : public Window, gcn::ActionListener +class InventoryWindow : public Window, gcn::ActionListener, SelectionListener { public: /** @@ -47,14 +48,14 @@ class InventoryWindow : public Window, gcn::ActionListener InventoryWindow(); /** - * Logic (updates buttons and weight information) + * Logic (updates buttons and weight information). */ void logic(); /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const std::string &eventId, gcn::Widget *widget); void mouseClick(int x, int y, int button, int count); @@ -64,14 +65,19 @@ class InventoryWindow : public Window, gcn::ActionListener void loadWindowState(); - void setDefaultSize(int defaultX, int defaultY, int defaultWidth, int defaultHeight); - void resetToDefaultSize(); + /** + * Updates labels to currently selected item. + * + * @see SelectionListener::selectionChanged. + */ + void selectionChanged(const SelectionEvent &event); + private: - void updateButtons(); /** Updates button states */ + void updateButtons(); /**< Updates button states. */ - void updateWidgets(); /** Updates widgets size/position */ + void updateWidgets(); /**< Updates widgets size/position. */ ItemContainer *mItems; diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index c7c55fd9..5bcd000d 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -25,6 +25,8 @@ #include +#include "selectionlistener.h" + #include "../graphics.h" #include "../inventory.h" #include "../item.h" @@ -38,14 +40,14 @@ #include "../utils/tostring.h" ItemContainer::ItemContainer(Inventory *inventory): - mInventory(inventory) + mInventory(inventory), + mSelectedItem(NULL) { ResourceManager *resman = ResourceManager::getInstance(); mSelImg = resman->getImage("graphics/gui/selection.png"); if (!mSelImg) logger->error("Unable to load selection.png"); - mSelectedItem = 0; // No item selected mMaxItems = mInventory->getLastUsedSlot() - 1; // Count from 0, usage from 2 addMouseListener(this); @@ -84,7 +86,7 @@ void ItemContainer::draw(gcn::Graphics* graphics) // sure somewhere else) if (mSelectedItem && mSelectedItem->getQuantity() <= 0) { - mSelectedItem = 0; + selectNone(); } /* @@ -111,7 +113,7 @@ void ItemContainer::draw(gcn::Graphics* graphics) // Draw item icon Image* image; - if ((image = item->getInfo()->getImage()) != NULL) + if ((image = item->getInfo().getImage()) != NULL) { dynamic_cast(graphics)->drawImage( image, itemX, itemY); @@ -150,7 +152,28 @@ Item* ItemContainer::getItem() void ItemContainer::selectNone() { - mSelectedItem = 0; + setSelectedItem(NULL); +} + +void ItemContainer::setSelectedItem(Item *item) +{ + if (mSelectedItem != item) + { + mSelectedItem = item; + fireSelectionChangedEvent(); + } +} + +void ItemContainer::fireSelectionChangedEvent() +{ + SelectionEvent event(this); + SelectionListeners::iterator i_end = mListeners.end(); + SelectionListeners::iterator i; + + for (i = mListeners.begin(); i != i_end; ++i) + { + (*i)->selectionChanged(event); + } } void ItemContainer::mousePress(int mx, int my, int button) @@ -166,6 +189,6 @@ void ItemContainer::mousePress(int mx, int my, int button) if (index > INVENTORY_SIZE) { index = INVENTORY_SIZE - 1; } - mSelectedItem = mInventory->getItem(index); + setSelectedItem(mInventory->getItem(index)); } } diff --git a/src/gui/itemcontainer.h b/src/gui/itemcontainer.h index f52f37ec..a2d5f0f7 100644 --- a/src/gui/itemcontainer.h +++ b/src/gui/itemcontainer.h @@ -27,9 +27,12 @@ #include #include +#include + class Image; class Inventory; class Item; +class SelectionListener; /** * An item container. Used to show items in inventory and trade dialog. @@ -76,16 +79,46 @@ class ItemContainer : public gcn::Widget, public gcn::MouseListener Item* getItem(); /** - * Set selected item to -1. + * Sets selected item to NULL. */ void selectNone(); + /** + * Adds a listener to the list that's notified each time a change to + * the selection occurs. + */ + void addSelectionListener(SelectionListener *listener) + { + mListeners.push_back(listener); + } + + /** + * Removes a listener from the list that's notified each time a change + * to the selection occurs. + */ + void removeSelectionListener(SelectionListener *listener) + { + mListeners.remove(listener); + } + private: + /** + * Sets the currently selected item. + */ + void setSelectedItem(Item *item); + + /** + * Sends out selection events to the list of selection listeners. + */ + void fireSelectionChangedEvent(); + Inventory *mInventory; Image *mSelImg; Item *mSelectedItem; int mMaxItems; + + std::list mListeners; }; #endif diff --git a/src/gui/listbox.cpp b/src/gui/listbox.cpp index df03b81b..14626d06 100644 --- a/src/gui/listbox.cpp +++ b/src/gui/listbox.cpp @@ -23,12 +23,16 @@ #include "listbox.h" +#include "selectionlistener.h" + #include #include #include +#include ListBox::ListBox(gcn::ListModel *listModel): - gcn::ListBox(listModel) + gcn::ListBox(listModel), + mMousePressed(false) { } @@ -45,8 +49,8 @@ void ListBox::draw(gcn::Graphics *graphics) // Draw rectangle below the selected list element if (mSelected >= 0) { - graphics->fillRectangle( - gcn::Rectangle(0, fontHeight * mSelected, getWidth(), fontHeight)); + graphics->fillRectangle(gcn::Rectangle(0, fontHeight * mSelected, + getWidth(), fontHeight)); } // Draw the list elements @@ -55,3 +59,50 @@ void ListBox::draw(gcn::Graphics *graphics) graphics->drawText(mListModel->getElementAt(i), 1, y); } } + +void ListBox::setSelected(int selected) +{ + gcn::ListBox::setSelected(selected); + fireSelectionChangedEvent(); +} + +void ListBox::mousePress(int x, int y, int button) +{ + gcn::ListBox::mousePress(x, y, button); + + if (button == gcn::MouseInput::LEFT && hasMouse()) + { + mMousePressed = true; + } +} + +void ListBox::mouseRelease(int x, int y, int button) +{ + gcn::ListBox::mouseRelease(x, y, button); + + mMousePressed = false; +} + +void ListBox::mouseMotion(int x, int y) +{ + gcn::ListBox::mouseMotion(x, y); + + // Pretend mouse is pressed continuously while dragged. Causes list + // selection to be updated as is default in many GUIs. + if (mMousePressed) + { + mousePress(x, y, gcn::MouseInput::LEFT); + } +} + +void ListBox::fireSelectionChangedEvent() +{ + SelectionEvent event(this); + SelectionListeners::iterator i_end = mListeners.end(); + SelectionListeners::iterator i; + + for (i = mListeners.begin(); i != i_end; ++i) + { + (*i)->selectionChanged(event); + } +} diff --git a/src/gui/listbox.h b/src/gui/listbox.h index 5999f7a7..c1932f54 100644 --- a/src/gui/listbox.h +++ b/src/gui/listbox.h @@ -26,10 +26,12 @@ #include +class SelectionListener; + /** * A list box, meant to be used inside a scroll area. Same as the Guichan list * box except this one doesn't have a background, instead completely relying - * on the scroll area. + * on the scroll area. It also adds selection listener functionality. * * \ingroup GUI */ @@ -45,6 +47,43 @@ class ListBox : public gcn::ListBox * Draws the list box. */ void draw(gcn::Graphics *graphics); + + void mousePress(int x, int y, int button); + void mouseRelease(int x, int y, int button); + void mouseMotion(int x, int y); + + /** + * Adds a listener to the list that's notified each time a change to + * the selection occurs. + */ + void addSelectionListener(SelectionListener *listener) + { + mListeners.push_back(listener); + } + + /** + * Removes a listener from the list that's notified each time a change + * to the selection occurs. + */ + void removeSelectionListener(SelectionListener *listener) + { + mListeners.remove(listener); + } + + /** + * Sets the index of the selected element. + */ + void setSelected(int selected); + + private: + /** + * Sends out selection events to the list of selection listeners. + */ + void fireSelectionChangedEvent(); + + bool mMousePressed; /**< Keeps track of mouse pressed status. */ + + std::list mListeners; }; #endif diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index db6d4f15..69c5eb6e 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -76,10 +76,10 @@ void Minimap::draw(gcn::Graphics *graphics) mMapImage, getPadding(), getTitleBarHeight()); } - Beings *beings = beingManager->getAll(); + Beings &beings = beingManager->getAll(); BeingIterator bi; - for (bi = beings->begin(); bi != beings->end(); bi++) + for (bi = beings.begin(); bi != beings.end(); bi++) { Being *being = (*bi); int dotSize = 1; diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp index ba97d54c..46cd7e85 100644 --- a/src/gui/playerbox.cpp +++ b/src/gui/playerbox.cpp @@ -97,7 +97,7 @@ void PlayerBox::draw(gcn::Graphics *graphics) if (mHairStyle > 0 && mHairColor < NR_HAIR_COLORS && mHairStyle < NR_HAIR_STYLES) { - int hf = 9 * mHairColor; + int hf = 5 * mHairColor; if (hf >= 0 && hf < (int)hairset[mHairStyle]->size()) { dynamic_cast(graphics)->drawImage( hairset[mHairStyle - 1]->get(hf), 35, 7); diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index 59316de1..ab81f7d0 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -106,7 +106,7 @@ void PopupMenu::showPopup(int x, int y, FloorItem *floorItem) mBrowserBox->clearRows(); // Floor item can be picked up (single option, candidate for removal) - std::string name = itemDb->getItemInfo(mFloorItem->getItemId())->getName(); + std::string name = itemDb->getItemInfo(mFloorItem->getItemId()).getName(); mBrowserBox->addRow("@@pickup|Pick Up " + name + "@@"); //browserBox->addRow("@@look|Look To@@"); diff --git a/src/gui/selectionlistener.h b/src/gui/selectionlistener.h new file mode 100644 index 00000000..a2fc6533 --- /dev/null +++ b/src/gui/selectionlistener.h @@ -0,0 +1,78 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: selectionlistener.h 2651 2006-09-03 16:47:48Z b_lindeijer $ + */ + +#ifndef _TMW_SELECTIONLISTENER_H__ +#define _TMW_SELECTIONLISTENER_H__ + +#include + +/** + * An event that characterizes a change in the current selection. + * + * \ingroup GUI + */ +class SelectionEvent +{ + public: + /** + * Constructor. + */ + SelectionEvent(gcn::Widget *source): + mSource(source) + { + } + + /** + * The widget from which the event originated. + */ + gcn::Widget* getSource() const + { + return mSource; + } + + private: + gcn::Widget *mSource; +}; + +/** + * The listener that's notified when a selection value changes. + * + * \ingroup GUI + */ +class SelectionListener +{ + public: + /** + * Virtual destructor. + */ + virtual ~SelectionListener() {} + + /** + * Called whenever the value of the selection changes. + */ + virtual void selectionChanged(const SelectionEvent &event) = 0; +}; + +typedef std::list SelectionListeners; + +#endif diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 33813271..d6d8cad5 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -94,6 +94,7 @@ SellDialog::SellDialog(): mSlider->setEventId("mSlider"); mItemList->addActionListener(this); + mItemList->addSelectionListener(this); mSlider->addActionListener(this); add(scrollArea); @@ -141,7 +142,7 @@ void SellDialog::addItem(Item *item, int price) ITEM_SHOP item_shop; - item_shop.name = item->getInfo()->getName() + " " + toString(price) + " GP"; + item_shop.name = item->getInfo().getName() + " " + toString(price) + " GP"; item_shop.price = price; item_shop.index = item->getInvIndex(); item_shop.id = item->getId(); @@ -155,7 +156,8 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) { int selectedItem = mItemList->getSelected(); - if (eventId == "item") { + if (eventId == "item") + { mAmountItems = 0; mSlider->setValue(0); mDecreaseButton->setEnabled(false); @@ -188,19 +190,22 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) bool updateButtonsAndLabels = false; - if (eventId == "mSlider") { + if (eventId == "mSlider") + { mAmountItems = (int)(mSlider->getValue() * mMaxItems); updateButtonsAndLabels = true; } - else if (eventId == "+") { + else if (eventId == "+") + { assert(mAmountItems < mMaxItems); mAmountItems++; mSlider->setValue(double(mAmountItems)/double(mMaxItems)); updateButtonsAndLabels = true; } - else if (eventId == "-") { + else if (eventId == "-") + { assert(mAmountItems > 0); mAmountItems--; @@ -208,7 +213,8 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) updateButtonsAndLabels = true; } - else if (eventId == "sell") { + else if (eventId == "sell") + { // Attempt sell assert(mAmountItems > 0 && mAmountItems <= mMaxItems); @@ -234,7 +240,8 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) } // If anything changed, we need to update the buttons and labels - if (updateButtonsAndLabels) { + if (updateButtonsAndLabels) + { // Update labels mQuantityLabel->setCaption(toString(mAmountItems)); mQuantityLabel->adjustSize(); @@ -250,16 +257,21 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) } } -void SellDialog::mouseClick(int x, int y, int button, int count) +void SellDialog::selectionChanged(const SelectionEvent &event) { - Window::mouseClick(x, y, button, count); - int selectedItem = mItemList->getSelected(); + if (selectedItem > -1) { - mItemDescLabel->setCaption("Description: " + - itemDb->getItemInfo(mShopItems->at(selectedItem).id)->getDescription()); - mItemEffectLabel->setCaption("Effect: " + - itemDb->getItemInfo(mShopItems->at(selectedItem).id)->getEffect()); + const ItemInfo &info = + itemDb->getItemInfo(mShopItems->at(selectedItem).id); + + mItemDescLabel->setCaption("Description: " + info.getDescription()); + mItemEffectLabel->setCaption("Effect: " + info.getEffect()); + } + else + { + mItemDescLabel->setCaption("Description"); + mItemEffectLabel->setCaption("Effect"); } } diff --git a/src/gui/sell.h b/src/gui/sell.h index be5185bd..69f8b089 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -27,19 +27,20 @@ #include #include "window.h" +#include "selectionlistener.h" #include "../guichanfwd.h" class Item; class ShopItems; - +class ListBox; /** * The sell dialog. * * \ingroup Interface */ -class SellDialog : public Window, public gcn::ActionListener +class SellDialog : public Window, gcn::ActionListener, SelectionListener { public: /** @@ -70,15 +71,17 @@ class SellDialog : public Window, public gcn::ActionListener void action(const std::string& eventId, gcn::Widget* widget); /** - * Mouse callback + * Updates labels according to selected item. + * + * @see SelectionListener::selectionChanged */ - void mouseClick(int x, int y, int buton, int count); + void selectionChanged(const SelectionEvent &event); private: gcn::Button *mSellButton; gcn::Button *mIncreaseButton; gcn::Button *mDecreaseButton; - gcn::ListBox *mItemList; + ListBox *mItemList; gcn::Label *mMoneyLabel; gcn::Label *mItemDescLabel; gcn::Label *mItemEffectLabel; diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index d12ace75..78b10498 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -43,7 +43,7 @@ Setup::Setup(): Window("Setup") { int width = 230; - int height = 225; + int height = 245; setContentSize(width, height); const char *buttonNames[] = { @@ -58,7 +58,7 @@ Setup::Setup(): } TabbedContainer *panel = new TabbedContainer(); - panel->setDimension(gcn::Rectangle(5, 5, 220, 185)); + panel->setDimension(gcn::Rectangle(5, 5, 220, 205)); panel->setOpaque(false); SetupTab *tab; diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 7c72975a..7a4aae03 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -106,7 +106,7 @@ Setup_Video::Setup_Video(): mOpenGLEnabled(config.getValue("opengl", 0)), mCustomCursorEnabled(config.getValue("customcursor", 1)), mOpacity(config.getValue("guialpha", 0.8)), - mFps((int)config.getValue("fpslimit", 50)), + mFps((int)config.getValue("fpslimit", 60)), mModeListModel(new ModeListModel()), mModeList(new ListBox(mModeListModel)), mFsCheckBox(new CheckBox("Full screen", mFullScreenEnabled)), @@ -121,7 +121,10 @@ Setup_Video::Setup_Video(): mScrollLazinessField(new TextField()), mOriginalScrollRadius((int) config.getValue("ScrollRadius", 32)), mScrollRadiusSlider(new Slider(0, 128)), - mScrollRadiusField(new TextField()) + mScrollRadiusField(new TextField()), + mOverlayDetail((int) config.getValue("OverlayDetail", 2)), + mOverlayDetailSlider(new Slider(0, 2)), + mOverlayDetailField(new gcn::Label("")) { setOpaque(false); @@ -163,6 +166,8 @@ Setup_Video::Setup_Video(): mScrollRadiusField->setEventId("scrollradiusfield"); mScrollLazinessSlider->setEventId("scrolllazinessslider"); mScrollLazinessField->setEventId("scrolllazinessfield"); + mOverlayDetailSlider->setEventId("overlaydetailslider"); + mOverlayDetailField->setEventId("overlaydetailfield"); mCustomCursorCheckBox->addActionListener(this); mAlphaSlider->addActionListener(this); @@ -173,6 +178,8 @@ Setup_Video::Setup_Video(): mScrollRadiusField->addKeyListener(this); mScrollLazinessSlider->addActionListener(this); mScrollLazinessField->addKeyListener(this); + mOverlayDetailSlider->addActionListener(this); + mOverlayDetailField->addKeyListener(this); mScrollRadiusSlider->setDimension(gcn::Rectangle(10, 120, 75, 10)); gcn::Label *scrollRadiusLabel = new gcn::Label("Scroll radius"); @@ -190,6 +197,25 @@ Setup_Video::Setup_Video(): mScrollLazinessField->setText(toString(mOriginalScrollLaziness)); mScrollLazinessSlider->setValue(mOriginalScrollLaziness); + mOverlayDetailSlider->setDimension(gcn::Rectangle(10, 160, 75, 10)); + gcn::Label *overlayDetailLabel = new gcn::Label("Ambient FX"); + overlayDetailLabel->setPosition(90, 160); + mOverlayDetailField->setPosition(180, 160); + mOverlayDetailField->setWidth(30); + switch (mOverlayDetail) + { + case 0: + mOverlayDetailField->setCaption("off"); + break; + case 1: + mOverlayDetailField->setCaption("low"); + break; + case 2: + mOverlayDetailField->setCaption("high"); + break; + } + mOverlayDetailSlider->setValue(mOverlayDetail); + add(scrollArea); add(mFsCheckBox); add(mOpenGLCheckBox); @@ -205,6 +231,9 @@ Setup_Video::Setup_Video(): add(mScrollLazinessSlider); add(scrollLazinessLabel); add(mScrollLazinessField); + add(mOverlayDetailSlider); + add(overlayDetailLabel); + add(mOverlayDetailField); } Setup_Video::~Setup_Video() @@ -258,6 +287,7 @@ void Setup_Video::apply() mFullScreenEnabled = config.getValue("screen", 0); mCustomCursorEnabled = config.getValue("customcursor", 1); mOpacity = config.getValue("guialpha", 0.8); + mOverlayDetail = (int)config.getValue("OverlayDetail", 2); mOpenGLEnabled = config.getValue("opengl", 0); } @@ -288,6 +318,7 @@ void Setup_Video::cancel() mOpenGLCheckBox->setMarked(mOpenGLEnabled); mCustomCursorCheckBox->setMarked(mCustomCursorEnabled); mAlphaSlider->setValue(mOpacity); + mOverlayDetailSlider->setValue(mOverlayDetail); mScrollRadiusField->setText(toString(mOriginalScrollRadius)); mScrollLazinessField->setText(toString(mOriginalScrollLaziness)); @@ -328,6 +359,23 @@ void Setup_Video::action(const std::string &event, gcn::Widget *widget) mScrollLazinessField->setText(toString(val)); config.setValue("ScrollLaziness", val); } + else if (event == "overlaydetailslider") + { + int val = (int)mOverlayDetailSlider->getValue(); + switch (val) + { + case 0: + mOverlayDetailField->setCaption("off"); + break; + case 1: + mOverlayDetailField->setCaption("low"); + break; + case 2: + mOverlayDetailField->setCaption("high"); + break; + } + config.setValue("OverlayDetail", val); + } else if (event == "fpslimitcheckbox") { if (mFpsCheckBox->isMarked()) diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h index a3fd8884..482d1c65 100644 --- a/src/gui/setup_video.h +++ b/src/gui/setup_video.h @@ -73,6 +73,10 @@ class Setup_Video : public SetupTab, public gcn::ActionListener, gcn::Slider *mScrollRadiusSlider; gcn::TextField *mScrollRadiusField; + int mOverlayDetail; + gcn::Slider *mOverlayDetailSlider; + gcn::Label *mOverlayDetailField; + void updateSliders(bool originalValues); diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 0cd49013..44efbdb1 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -58,12 +58,14 @@ TradeWindow::TradeWindow(): mTradeButton = new Button("Trade", "trade", this); mMyItemContainer = new ItemContainer(mMyInventory.get()); + mMyItemContainer->addSelectionListener(this); mMyItemContainer->setPosition(2, 2); mMyScroll = new ScrollArea(mMyItemContainer); mMyScroll->setPosition(8, 8); mPartnerItemContainer = new ItemContainer(mPartnerInventory.get()); + mPartnerItemContainer->addSelectionListener(this); mPartnerItemContainer->setPosition(2, 58); mPartnerScroll = new ScrollArea(mPartnerItemContainer); @@ -219,53 +221,54 @@ void TradeWindow::tradeItem(Item *item, int quantity) outMsg.writeLong(quantity); } -void TradeWindow::mouseClick(int x, int y, int button, int count) +void TradeWindow::selectionChanged(const SelectionEvent &event) { - Window::mouseClick(x, y, button, count); - Item *item; - // mMyItems selected - if (x >= mMyScroll->getX() + 3 - && x <= mMyScroll->getX() + mMyScroll->getWidth() - 10 - && y >= mMyScroll->getY() + 16 - && y <= mMyScroll->getY() + mMyScroll->getHeight() + 15 - && (item = mMyItemContainer->getItem())) + /* If an item is selected in one container, make sure no item is selected + * in the other container. + */ + if (event.getSource() == mMyItemContainer && + (item = mMyItemContainer->getItem())) { - mPartnerItemContainer->selectNone(); - // mPartnerItems selected + mPartnerItemContainer->selectNone(); } - else if (x >= mPartnerScroll->getX() + 3 - && x <= mPartnerScroll->getX() + mPartnerScroll->getWidth() - 20 - && y >= mPartnerScroll->getY() + 16 - && y <= mPartnerScroll->getY() + mPartnerScroll->getHeight() + 15 - && (item = mPartnerItemContainer->getItem())) + else if ((item = mPartnerItemContainer->getItem())) { - mMyItemContainer->selectNone(); - } else { - return; + mMyItemContainer->selectNone(); } - // Show Name and Description - std::string SomeText; - SomeText = "Name: " + item->getInfo()->getName(); - mItemNameLabel->setCaption(SomeText); - mItemNameLabel->adjustSize(); - SomeText = "Description: " + item->getInfo()->getDescription(); - mItemDescriptionLabel->setCaption(SomeText); - mItemDescriptionLabel->adjustSize(); + // Update name and description + if (!item) + { + mItemNameLabel->setCaption("Name:"); + mItemDescriptionLabel->setCaption("Description:"); + } + else + { + std::string SomeText; + SomeText = "Name: " + item->getInfo().getName(); + mItemNameLabel->setCaption(SomeText); + mItemNameLabel->adjustSize(); + SomeText = "Description: " + item->getInfo().getDescription(); + mItemDescriptionLabel->setCaption(SomeText); + mItemDescriptionLabel->adjustSize(); + } } void TradeWindow::action(const std::string &eventId, gcn::Widget *widget) { Item *item = inventoryWindow->getItem(); - if (eventId == "add") { - if (!item) { + if (eventId == "add") + { + if (!item) + { return; } - if (mMyInventory->getFreeSlot() < 1) { + if (mMyInventory->getFreeSlot() < 1) + { return; } diff --git a/src/gui/trade.h b/src/gui/trade.h index fe60aac5..ebd05a52 100644 --- a/src/gui/trade.h +++ b/src/gui/trade.h @@ -29,6 +29,7 @@ #include #include "window.h" +#include "selectionlistener.h" #include "../guichanfwd.h" @@ -42,7 +43,7 @@ class ScrollArea; * * \ingroup Interface */ -class TradeWindow : public Window, gcn::ActionListener +class TradeWindow : public Window, gcn::ActionListener, SelectionListener { public: /** @@ -102,14 +103,15 @@ class TradeWindow : public Window, gcn::ActionListener tradeItem(Item *item, int quantity); /** - * Called on mouse click. + * Updates the labels and makes sure only one item is selected in + * either my inventory or partner inventory. */ - void mouseClick(int x, int y, int button, int count); + void selectionChanged(const SelectionEvent &event); /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const std::string &eventId, gcn::Widget *widget); private: typedef std::auto_ptr InventoryPtr; diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 77a026fe..00b10406 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -48,9 +48,9 @@ UpdaterWindow::UpdaterWindow(): Window("Updating..."), mThread(NULL), mMutex(NULL), mDownloadStatus(UPDATE_NEWS), mUpdateHost(""), mCurrentFile("news.txt"), mBasePath(""), - mStoreInMemory(true), mDownloadComplete(true), mDownloadedBytes(0), - mMemoryBuffer(NULL), mCurlError(new char[CURL_ERROR_SIZE]), - mFileIndex(0) + mStoreInMemory(true), mDownloadComplete(true), mUserCancel(false), + mDownloadedBytes(0), mMemoryBuffer(NULL), + mCurlError(new char[CURL_ERROR_SIZE]), mFileIndex(0) { mCurlError[0] = 0; @@ -133,6 +133,8 @@ void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "cancel") { + // Register the user cancel + mUserCancel=true; // Skip the updating process if (mDownloadStatus == UPDATE_COMPLETE) { @@ -329,7 +331,15 @@ void UpdaterWindow::logic() case UPDATE_ERROR: if (mThread) { - SDL_WaitThread(mThread, NULL); + if(mUserCancel){ + // Kill the thread, because user has canceled + SDL_KillThread(mThread); + // Set the flag to false again + mUserCancel = false; + } + else{ + SDL_WaitThread(mThread, NULL); + } mThread = NULL; } addRow(""); diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index 8a168be8..5016036d 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -161,6 +161,11 @@ class UpdaterWindow : public Window, public gcn::ActionListener */ bool mDownloadComplete; + /** + * Flag that show if the user has canceled the update + */ + bool mUserCancel; + /** * Byte count currently downloaded in mMemoryBuffer. */ diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 2172baa8..c7860021 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -249,16 +249,18 @@ void Window::setSticky(bool sticky) mSticky = sticky; } -bool Window::isSticky() { +bool Window::isSticky() +{ return mSticky; } -void Window::setVisible(bool visible) { - if(isSticky()) +void Window::setVisible(bool visible) +{ + if (isSticky()) { gcn::Window::setVisible(true); - } - else + } + else { gcn::Window::setVisible(visible); } diff --git a/src/item.h b/src/item.h index c21f5ddf..1375886e 100644 --- a/src/item.h +++ b/src/item.h @@ -118,7 +118,7 @@ class Item /** * Returns information about this item type. */ - ItemInfo* + const ItemInfo& getInfo() const { return itemDb->getItemInfo(mId); } protected: diff --git a/src/localplayer.h b/src/localplayer.h index 7d5aef87..dbf2a147 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -96,12 +96,17 @@ class LocalPlayer : public Player * Sets the trading state of the player, i.e. whether or not he is * currently involved into some trade. */ - void setTrading(bool trading) { mTrading = trading; }; + void setTrading(bool trading) { mTrading = trading; } void attack(Being *target=NULL, bool keep=false); void stopAttack(); Being* getTarget() const; + /** + * Sets the target being of the player. + */ + void setTarget(Being* target) { mTarget = target; } + void walk(unsigned char dir); /** diff --git a/src/main.cpp b/src/main.cpp index 9d2a1e64..f881ddad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -107,6 +107,33 @@ namespace { } errorListener; } +/** + * A structure holding the values of various options that can be passed from + * the command line. + */ +struct Options +{ + /** + * Constructor. + */ + Options(): + printHelp(false), + skipUpdate(false), + chooseDefault(false), + serverPort(0) + {}; + + bool printHelp; + bool skipUpdate; + bool chooseDefault; + std::string playername; + std::string password; + std::string configPath; + + std::string serverName; + short serverPort; +}; + /** * Initializes the home directory. On UNIX and FreeBSD, ~/.tmw is used. On * Windows and other systems we use the current working directory. @@ -133,7 +160,7 @@ void initHomeDir() /** * Initialize configuration. */ -void initConfiguration() +void initConfiguration(const Options &options) { // Fill configuration with defaults config.setValue("host", "animesites.de"); @@ -158,7 +185,10 @@ void initConfiguration() // Checking if the configuration file exists... otherwise create it with // default options. FILE *tmwFile = 0; - std::string configPath = homeDir + "/config.xml"; + std::string configPath = options.configPath; + if (configPath == "") { + configPath = homeDir + "/config.xml"; + } tmwFile = fopen(configPath.c_str(), "r"); // If we can't read it, it doesn't exist ! @@ -176,7 +206,7 @@ void initConfiguration() } /** - * Do all initialization stuff + * Do all initialization stuff. */ void init_engine() { @@ -279,7 +309,8 @@ void init_engine() sound.init(); } sound.setSfxVolume((int)config.getValue("sfxVolume", defaultSfxVolume)); - sound.setMusicVolume((int)config.getValue("musicVolume", defaultMusicVolume)); + sound.setMusicVolume((int)config.getValue("musicVolume", + defaultMusicVolume)); } catch (const char *err) { state = STATE_ERROR; @@ -311,33 +342,6 @@ void exit_engine() ResourceManager::deleteInstance(); } -/** - * A structure holding the values of various options that can be passed from - * the command line. - */ -struct Options -{ - /** - * Constructor. - */ - Options(): - printHelp(false), - skipUpdate(false), - chooseDefault(false), - serverPort(0) - {}; - - bool printHelp; - bool skipUpdate; - bool chooseDefault; - std::string playername; - std::string password; - - std::string serverName; - short serverPort; - -}; - void printHelp() { std::cout @@ -351,12 +355,13 @@ void printHelp() << std::endl << " -s --server : Login Server name or IP" << std::endl << " -o --port : Login Server Port" << std::endl - << " -p --playername : Login with this player" << std::endl; + << " -p --playername : Login with this player" << std::endl + << " -C --configfile : Configuration file to use" << std::endl; } void parseOptions(int argc, char *argv[], Options &options) { - const char *optstring = "huU:P:Dp:s:o:"; + const char *optstring = "huU:P:Dp:s:o:C:"; const struct option long_options[] = { { "help", no_argument, 0, 'h' }, @@ -367,6 +372,7 @@ void parseOptions(int argc, char *argv[], Options &options) { "server", required_argument, 0, 's' }, { "port", required_argument, 0, 'o' }, { "playername", required_argument, 0, 'p' }, + { "configfile", required_argument, 0, 'C' }, { 0 } }; @@ -403,6 +409,9 @@ void parseOptions(int argc, char *argv[], Options &options) case 'p': options.playername = optarg; break; + case 'C': + options.configPath = optarg; + break; } } } @@ -480,6 +489,10 @@ void mapLogin(LoginData *loginData) { Network::registerHandler(&mapLoginHandler); + logger->log("Memorizing selected character %s", + player_node->getName().c_str()); + config.setValue("lastCharacter", player_node->getName()); + // Send connect messages with the magic token to game and chat servers MessageOut gameServerConnect(PGMSG_CONNECT); gameServerConnect.writeString(token, 32); @@ -510,7 +523,7 @@ int main(int argc, char *argv[]) PHYSFS_init(argv[0]); initHomeDir(); - initConfiguration(); + initConfiguration(options); // Configure logger logger = new Logger(); @@ -721,23 +734,16 @@ int main(int argc, char *argv[]) case STATE_CHAR_SELECT: logger->log("State: CHAR_SELECT"); currentDialog = new CharSelectDialog(&charInfo); - if (options.playername != "") { - n_character = 0; - while (((CharSelectDialog*) currentDialog)->getName() - != options.playername && - n_character < MAX_SLOT + 1) - { - ((CharSelectDialog*) currentDialog)->action("next", - NULL); - ((CharSelectDialog*) currentDialog)->updatePlayerInfo(); - n_character++; - } - n_character = MAX_SLOT + 1; - } - if (options.chooseDefault || options.playername != "") { - ((CharSelectDialog*)currentDialog)->action("ok", - NULL); - } + + if (((CharSelectDialog*)currentDialog)-> + selectByName(options.playername)) + options.chooseDefault = true; + else + ((CharSelectDialog*)currentDialog)->selectByName( + config.getValue("lastCharacter", "")); + + if (options.chooseDefault) + ((CharSelectDialog*)currentDialog)->action("ok", NULL); break; case STATE_ERROR: diff --git a/src/map.cpp b/src/map.cpp index 5063a754..3ccaafc0 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -63,8 +63,11 @@ Map::Map(int width, int height, int tileWidth, int tileHeight): mOnClosedList(1), mOnOpenList(2), mLastScrollX(0.0f), mLastScrollY(0.0f) { - mMetaTiles = new MetaTile[mWidth * mHeight]; - mTiles = new Image*[mWidth * mHeight * 3]; + int size = mWidth * mHeight; + + mMetaTiles = new MetaTile[size]; + mTiles = new Image*[size * 3]; + std::fill_n(mTiles, size * 3, (Image*)0); } Map::~Map() @@ -86,12 +89,17 @@ Map::~Map() void Map::setSize(int width, int height) { - mWidth = width; - mHeight = height; delete[] mMetaTiles; delete[] mTiles; - mMetaTiles = new MetaTile[mWidth * mHeight]; - mTiles = new Image*[mWidth * mHeight * 3]; + + mWidth = width; + mHeight = height; + + int size = width * height; + + mMetaTiles = new MetaTile[size]; + mTiles = new Image*[size * 3]; + std::fill_n(mTiles, size * 3, (Image*)0); } void @@ -330,8 +338,8 @@ Map::getWalk(int x, int y) /* // Check for collision with a being - Beings *beings = beingManager->getAll(); - for (BeingIterator i = beings->begin(); i != beings->end(); i++) { + Beings &beings = beingManager->getAll(); + for (BeingIterator i = beings.begin(); i != beings.end(); i++) { // job 45 is a portal, they don't collide if ((*i)->mX / 32 == x && (*i)->mY / 32 == y && (*i)->mJob != 45) { return false; diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp index c4192bc5..3f7e8709 100644 --- a/src/net/inventoryhandler.cpp +++ b/src/net/inventoryhandler.cpp @@ -92,14 +92,9 @@ void InventoryHandler::handleMessage(MessageIn &msg) if (msg.readByte()> 0) { chatWindow->chatLog("Unable to pick up item", BY_SERVER); } else { - ItemInfo *itemInfo = itemDb->getItemInfo(itemId); - if (itemInfo) { - chatWindow->chatLog("You picked up a " + - itemInfo->getName(), BY_SERVER); - } else { - chatWindow->chatLog("You picked up an unknown item", - BY_SERVER); - } + const ItemInfo &itemInfo = itemDb->getItemInfo(itemId); + chatWindow->chatLog("You picked up a " + + itemInfo.getName(), BY_SERVER); player_node->addInvItem(index, itemId, amount, equipType != 0); } break; diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 51899d3f..eb3a2409 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -260,11 +260,18 @@ void Image::unload() { mLoaded = false; - if (!mImage) return; + if (mImage) { + // Free the image surface. + SDL_FreeSurface(mImage); + mImage = NULL; + } - // Free the image surface. - SDL_FreeSurface(mImage); - mImage = NULL; +#ifdef USE_OPENGL + if (mGLImage) { + glDeleteTextures(1, &mGLImage); + mGLImage = 0; + } +#endif } Image *Image::getSubImage(int x, int y, int width, int height) @@ -341,7 +348,11 @@ SubImage::SubImage(Image *parent, GLuint image, SubImage::~SubImage() { - mImage = 0; // Avoid destruction of the image + // Avoid destruction of the image + mImage = 0; +#ifdef USE_OPENGL + mGLImage = 0; +#endif mParent->decRef(); } diff --git a/src/resources/image.h b/src/resources/image.h index 78751394..a1ab7f48 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -28,6 +28,13 @@ #include #ifdef USE_OPENGL + +/* The definition of OpenGL extensions by SDL is giving problems with recent + * gl.h headers, since they also include these definitions. As we're not using + * extensions anyway it's safe to just disable the SDL version. + */ +#define NO_SDL_GLEXT + #include #endif diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index 5d39d832..b09d1cc0 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -23,22 +23,33 @@ #include "iteminfo.h" #include "resourcemanager.h" +#include "image.h" -Image* -ItemInfo::getImage() { - if (mImage == NULL && mImageName != "") { - mImage = ResourceManager::getInstance()->getImage(mImageName); + +ItemInfo::~ItemInfo() +{ + if (mImage != NULL) + { + mImage->decRef(); } - return mImage; } void -ItemInfo::setImage(const std::string &image) { +ItemInfo::setImage(const std::string &image) +{ mImageName = "graphics/items/" + image; -} -ItemInfo::~ItemInfo() { - if (mImage != NULL){ - mImage->decRef(); + if (mImageName != "") + { + if (mImage != NULL) + { + mImage->decRef(); + } + + mImage = ResourceManager::getInstance()->getImage(mImageName); + } + else + { + mImage = NULL; } } diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index afa2e857..9a04bb2e 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -26,7 +26,7 @@ #include -#include "image.h" +class Image; /** * Defines a class for storing item infos. @@ -40,8 +40,8 @@ class ItemInfo * Constructor. */ ItemInfo(): - mImage(NULL), mImageName(""), + mImage(NULL), mArt(0), mType(0), mWeight(0), @@ -53,19 +53,19 @@ class ItemInfo setArt(short art) { mArt = art; } short - getArt() { return mArt; } + getArt() const { return mArt; } void setName(const std::string &name) { mName = name; } - std::string - getName() { return mName; } + const std::string& + getName() const { return mName; } void setImage(const std::string &image); Image* - getImage(); + getImage() const { return mImage; } void setDescription(const std::string &description) @@ -73,32 +73,32 @@ class ItemInfo mDescription = description; } - std::string - getDescription() { return mDescription; } + const std::string& + getDescription() const { return mDescription; } void setEffect(const std::string &effect) { mEffect = effect; } - std::string - getEffect() { return mEffect; } + const std::string& + getEffect() const { return mEffect; } void setType(short type) { mType = type; } short - getType() { return mType; } + getType() const { return mType; } void setWeight(short weight) { mWeight = weight; } short - getWeight() { return mWeight; } + getWeight() const { return mWeight; } void setSlot(char slot) { mSlot = slot; } char - getSlot() { return mSlot; } + getSlot() const { return mSlot; } protected: /** @@ -106,8 +106,14 @@ class ItemInfo */ ~ItemInfo(); - Image* mImage; std::string mImageName; + + /* TODO (BL): I do not think the item info should keep a reference to + * the item icon. It would probably be better if this was kept in the + * Item class, so that the images can be lazily instantiated and also + * unloaded when no longer used. + */ + Image *mImage; short mArt; std::string mName; std::string mDescription; diff --git a/src/resources/itemmanager.cpp b/src/resources/itemmanager.cpp index a497b3c8..7d0b13f2 100644 --- a/src/resources/itemmanager.cpp +++ b/src/resources/itemmanager.cpp @@ -41,8 +41,7 @@ ItemManager::ItemManager() { - mUnknown = new ItemInfo(); - mUnknown->setName("Unknown item"); + mUnknown.setName("Unknown item"); ResourceManager *resman = ResourceManager::getInstance(); int size; @@ -163,14 +162,12 @@ ItemManager::~ItemManager() delete i->second; } mItemInfos.clear(); - - delete mUnknown; } -ItemInfo* +const ItemInfo& ItemManager::getItemInfo(int id) { ItemInfoIterator i = mItemInfos.find(id); - return (i != mItemInfos.end()) ? i->second : mUnknown; + return (i != mItemInfos.end()) ? *(i->second) : mUnknown; } diff --git a/src/resources/itemmanager.h b/src/resources/itemmanager.h index 06eee507..b1f2b95c 100644 --- a/src/resources/itemmanager.h +++ b/src/resources/itemmanager.h @@ -24,9 +24,9 @@ #ifndef _TMW_ITEM_MANAGER_H #define _TMW_ITEM_MANAGER_H -#include +#include "iteminfo.h" -class ItemInfo; +#include /** * Defines a class to load items database. @@ -44,14 +44,14 @@ class ItemManager */ ~ItemManager(); - ItemInfo *getItemInfo(int id); + const ItemInfo& getItemInfo(int id); protected: // Items database typedef std::map ItemInfos; typedef ItemInfos::iterator ItemInfoIterator; ItemInfos mItemInfos; - ItemInfo *mUnknown; + ItemInfo mUnknown; }; extern ItemManager *itemDb; diff --git a/src/tmw.rc b/src/tmw.rc index 31411b61..388b643d 100644 --- a/src/tmw.rc +++ b/src/tmw.rc @@ -7,8 +7,8 @@ A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "data/icons/tmw-icon.ico" // TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS... // 1 VERSIONINFO -FILEVERSION 0,0,20,0 -PRODUCTVERSION 0,0,20,0 +FILEVERSION 0,0,21,0 +PRODUCTVERSION 0,0,21,0 FILETYPE VFT_APP { BLOCK "StringFileInfo" @@ -16,14 +16,14 @@ FILETYPE VFT_APP BLOCK "040904E4" { VALUE "CompanyName", "The Mana World Development Team" - VALUE "FileVersion", "0.0.20" + VALUE "FileVersion", "0.0.21" VALUE "FileDescription", "The Mana World" VALUE "InternalName", "tmw.exe" VALUE "LegalCopyright", "2004-2006 (C)" VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "tmw.exe" VALUE "ProductName", "The Mana World MMORPG" - VALUE "ProductVersion", "0.0.20" + VALUE "ProductVersion", "0.0.21" } } BLOCK "VarFileInfo" diff --git a/tools/Reorganize.java b/tools/Reorganize.java index 19a17b99..22f42604 100644 --- a/tools/Reorganize.java +++ b/tools/Reorganize.java @@ -12,7 +12,7 @@ import java.io.File; import javax.imageio.ImageIO; /** - * Very simple tool to reorganize the monster spritesets. + * Tool to reorganize the hair spritesets. */ public class Reorganize { @@ -20,6 +20,12 @@ public class Reorganize private static final int SPRITE_HEIGHT = 60; private static final int FRAMES = 10; private static final int DIRECTIONS = 4; + + private static final int HAIR_COLORS = 10; + private static final int HAIR_FRAMES = 9; + private static final int HAIR_SPRITE_WIDTH = 40; + private static final int HAIR_SPRITE_HEIGHT = 40; + private static final int TRANSPARENT = new Color(255, 0, 255).getRGB(); public static void main(String[] arg) @@ -38,30 +44,15 @@ public class Reorganize System.exit(1); } - Rectangle cropRect = null; - - // Read the existing frames into a vector and determine minimal - // rectangle that still can contain the contents of any frame. - Vector spriteSet = new Vector(); - for (int x = 0; x < DIRECTIONS; x++) { - for (int y = 0; y < FRAMES; y++) { - BufferedImage sprite = source.getSubimage( - x * SPRITE_WIDTH, - y * SPRITE_HEIGHT, - SPRITE_WIDTH, - SPRITE_HEIGHT); - - spriteSet.add(sprite); + // Read the existing frames into a vector + Vector spriteSet = gridCut(source, + HAIR_SPRITE_WIDTH, HAIR_SPRITE_HEIGHT, + HAIR_FRAMES, HAIR_COLORS); - Rectangle frameCropRect = determineCropRect(sprite); - - if (cropRect == null) { - cropRect = frameCropRect; - } else { - cropRect.add(frameCropRect); - } - } - } + // Determine minimal rectangle that can still contain the contents of + // any frame + /* + Rectangle cropRect = minimumCropRect(spriteSet); if (cropRect == null) { System.out.println( @@ -76,19 +67,61 @@ public class Reorganize System.out.println(arg[0] + ": width=\"" + cropRect.width + "\" height=\"" + cropRect.height + "\""); + */ + + filterHairstyle(spriteSet); + + BufferedImage target = gridDraw( + spriteSet, + new Rectangle(0, 0, HAIR_SPRITE_WIDTH, HAIR_SPRITE_HEIGHT), + HAIR_FRAMES - 4, HAIR_COLORS); - // Create a new image (with frame direction flipped) + // Save the target image + try { + ImageIO.write(target, "png", new File(arg[1])); + } catch (IOException e) { + System.out.println("Error while trying to write " + arg[1] + "."); + e.printStackTrace(); + System.exit(1); + } + } + + private static Vector gridCut( + BufferedImage source, + int width, int height, int xFrames, int yFrames) + { + Vector spriteSet = new Vector(); + + for (int y = 0; y < yFrames; y++) { + for (int x = 0; x < xFrames; x++) { + BufferedImage sprite = source.getSubimage( + x * width, + y * height, + width, + height); + + spriteSet.add(sprite); + } + } + + return spriteSet; + } + + private static BufferedImage gridDraw(Vector spriteSet, + Rectangle cropRect, int xFrames, int yFrames) + { + // Create a new image BufferedImage target = new BufferedImage( - FRAMES * cropRect.width, - DIRECTIONS * cropRect.height, + xFrames * cropRect.width, + yFrames * cropRect.height, BufferedImage.TYPE_INT_ARGB); // Draw the frames onto the target image Graphics g = target.getGraphics(); - for (int y = 0; y < DIRECTIONS; y++) { - for (int x = 0; x < FRAMES; x++) { + for (int y = 0; y < yFrames; y++) { + for (int x = 0; x < xFrames; x++) { g.drawImage( - spriteSet.get(x + FRAMES * y).getSubimage( + spriteSet.get(x + xFrames * y).getSubimage( cropRect.x, cropRect.y, cropRect.width, @@ -99,14 +132,24 @@ public class Reorganize } } - // Save the target image - try { - ImageIO.write(target, "png", new File(arg[1])); - } catch (IOException e) { - System.out.println("Error while trying to write " + arg[1] + "."); - e.printStackTrace(); - System.exit(1); + return target; + } + + private static Rectangle minimumCropRect(Vector spriteSet) + { + Rectangle cropRect = null; + + for (BufferedImage sprite : spriteSet) { + Rectangle frameCropRect = determineCropRect(sprite); + + if (cropRect == null) { + cropRect = frameCropRect; + } else { + cropRect.add(frameCropRect); + } } + + return cropRect; } private static Rectangle determineCropRect(BufferedImage image) @@ -130,4 +173,15 @@ public class Reorganize return rect; } + + private static void filterHairstyle(Vector spriteSet) + { + // Remove frame 1, 2, 6 and 7 from each color + for (int i = HAIR_COLORS - 1; i >= 0; i--) { + spriteSet.remove(i * HAIR_FRAMES + 7); + spriteSet.remove(i * HAIR_FRAMES + 6); + spriteSet.remove(i * HAIR_FRAMES + 2); + spriteSet.remove(i * HAIR_FRAMES + 1); + } + } } -- cgit v1.2.3-60-g2f50 From fa035c2fd70945a0b12143ce9b81284d8d24d13b Mon Sep 17 00:00:00 2001 From: Björn Steinbrink Date: Wed, 1 Nov 2006 15:12:22 +0000 Subject: Added CMake support --- CMake/Modules/FindENet.cmake | 41 +++++ CMake/Modules/FindGuichan.cmake | 97 ++++++++++++ CMake/Modules/FindLibXml2.cmake | 59 +++++++ CMake/Modules/FindLibcurl.cmake | 41 +++++ CMakeLists.txt | 21 +++ ChangeLog | 13 ++ data/CMakeLists.txt | 13 ++ data/graphics/CMakeLists.txt | 5 + data/graphics/gui/CMakeLists.txt | 45 ++++++ data/graphics/images/CMakeLists.txt | 16 ++ data/help/CMakeLists.txt | 12 ++ data/icons/CMakeLists.txt | 9 ++ src/CMakeLists.txt | 299 ++++++++++++++++++++++++++++++++++++ src/main.h | 2 +- 14 files changed, 672 insertions(+), 1 deletion(-) create mode 100644 CMake/Modules/FindENet.cmake create mode 100644 CMake/Modules/FindGuichan.cmake create mode 100644 CMake/Modules/FindLibXml2.cmake create mode 100644 CMake/Modules/FindLibcurl.cmake create mode 100644 CMakeLists.txt create mode 100644 data/CMakeLists.txt create mode 100644 data/graphics/CMakeLists.txt create mode 100644 data/graphics/gui/CMakeLists.txt create mode 100644 data/graphics/images/CMakeLists.txt create mode 100644 data/help/CMakeLists.txt create mode 100644 data/icons/CMakeLists.txt create mode 100644 src/CMakeLists.txt (limited to 'data/graphics') diff --git a/CMake/Modules/FindENet.cmake b/CMake/Modules/FindENet.cmake new file mode 100644 index 00000000..4d0a06c8 --- /dev/null +++ b/CMake/Modules/FindENet.cmake @@ -0,0 +1,41 @@ +# - Try to find enet +# Once done this will define +# +# ENET_FOUND - system has enet +# ENET_INCLUDE_DIR - the enet include directory +# ENET_LIBRARIES - the libraries needed to use enet +# ENET_DEFINITIONS - Compiler switches required for using enet + +IF (ENet_INCLUDE_DIR AND ENet_LIBRARY) + SET(ENet_FIND_QUIETLY TRUE) +ENDIF (ENet_INCLUDE_DIR AND ENet_LIBRARY) + +FIND_PATH(ENet_INCLUDE_DIR enet/enet.h + /usr/include + /usr/local/include + ) + +FIND_LIBRARY(ENet_LIBRARY + NAMES enet + PATHS /usr/lib /usr/local/lib + ) + +IF (ENet_INCLUDE_DIR AND ENet_LIBRARY) + SET(ENET_FOUND TRUE) + SET(ENET_INCLUDE_DIR ${ENet_INCLUDE_DIR}) + SET(ENET_LIBRARIES ${ENet_LIBRARY}) +ELSE (ENet_INCLUDE_DIR AND ENet_LIBRARY) + SET(ENET_FOUND TRUE) +ENDIF (ENet_INCLUDE_DIR AND ENet_LIBRARY) + +IF (ENET_FOUND) + IF (NOT ENet_FIND_QUIETLY) + MESSAGE(STATUS "Found enet: ${ENet_LIBRARY}") + ENDIF (NOT ENet_FIND_QUIETLY) +ELSE (ENET_FOUND) + IF (ENet_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could NOT find enet") + ENDIF (ENet_FIND_REQUIRED) +ENDIF (ENET_FOUND) + +MARK_AS_ADVANCED(ENet_INCLUDE_DIR ENet_LIBRARY) diff --git a/CMake/Modules/FindGuichan.cmake b/CMake/Modules/FindGuichan.cmake new file mode 100644 index 00000000..fccfc499 --- /dev/null +++ b/CMake/Modules/FindGuichan.cmake @@ -0,0 +1,97 @@ +# - Try to find Guichan +# Once done this will define +# +# GUICHAN_FOUND - system has Guichan +# GUICHAN_INCLUDE_DIR - the Guichan include directory +# GUICHAN_LIBRARIES - the libraries needed to use Guichan +# +# Supported components: SDL OpenGL +# +# TODO: Clean up the components stuff and try to add all known +# components when none are specified. May not bail out for not found +# components then, set some var instead... + +# Be quiet if Guichan was already found +# We need an extra variable to have the check per component +IF (Guichan_INCLUDE_DIR AND Guichan_LIBRARY) + SET(Guichan_QUIET TRUE) +ENDIF (Guichan_INCLUDE_DIR AND Guichan_LIBRARY) + + +FIND_PATH(Guichan_INCLUDE_DIR + NAMES guichan.hpp + PATHS /usr/include /usr/local/include + ) + +FIND_LIBRARY(Guichan_LIBRARY + NAMES guichan + PATHS /usr/lib /usr/local/lib + ) + +MARK_AS_ADVANCED(Guichan_INCLUDE_DIR Guichan_LIBRARY) + + +IF (Guichan_INCLUDE_DIR AND Guichan_LIBRARY) + SET(GUICHAN_FOUND TRUE) + SET(GUICHAN_INCLUDE_DIR ${Guichan_INCLUDE_DIR}) + SET(GUICHAN_LIBRARIES ${Guichan_LIBRARY}) + + IF (NOT Guichan_FIND_QUIETLY AND NOT Guichan_QUIET) + MESSAGE(STATUS "Found Guichan: ${Guichan_LIBRARY}") + ENDIF (NOT Guichan_FIND_QUIETLY AND NOT Guichan_QUIET) +ENDIF (Guichan_INCLUDE_DIR AND Guichan_LIBRARY) + +# Bail out if Guichan is not found but required +IF (NOT GUICHAN_FOUND AND Guichan_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could NOT find Guichan library ${GUICHAN_INCLUDE_DIR}") +ENDIF (NOT GUICHAN_FOUND AND Guichan_FIND_REQUIRED) + + +# Check for guichan components +FOREACH (COMPONENT ${Guichan_FIND_COMPONENTS}) + SET(COMPONENT_FOUND FALSE) + + IF (COMPONENT STREQUAL "SDL") + SET(COMPONENT_FOUND TRUE) + SET(Guichan_HEADER "guichan/sdl.hpp") + SET(Guichan_LIBRARY "guichan_sdl") + ENDIF (COMPONENT STREQUAL "SDL") + + IF (COMPONENT STREQUAL "OpenGL") + SET(COMPONENT_FOUND TRUE) + SET(Guichan_HEADER "guichan/opengl.hpp") + SET(Guichan_LIBRARY "guichan_opengl") + ENDIF (COMPONENT STREQUAL "OpenGL") + + IF (NOT COMPONENT_FOUND) + MESSAGE(FATAL_ERROR "Invalid Guichan component: ${COMPONENT}") + ENDIF (NOT COMPONENT_FOUND) + + # Check if we already found this component + IF (Guichan_LIBRARY_${COMPONENT}) + SET(Guichan_QUIET TRUE) + ELSE (Guichan_LIBRARY_${COMPONENT}) + SET(Guichan_QUIET FALSE) + ENDIF (Guichan_LIBRARY_${COMPONENT}) + + FIND_LIBRARY(Guichan_LIBRARY_${COMPONENT} + NAMES ${Guichan_LIBRARY} + PATHS /usr/lib /usr/local/lib + ) + + MARK_AS_ADVANCED(Guichan_LIBRARY_${COMPONENT}) + + IF (NOT EXISTS ${Guichan_INCLUDE_DIR}/${Guichan_HEADER} OR + NOT Guichan_LIBRARY_${COMPONENT}) + SET(GUICHAN_FOUND FALSE) + MESSAGE(FATAL_ERROR "Could NOT find Guichan component ${COMPONENT}") + ENDIF (NOT EXISTS ${Guichan_INCLUDE_DIR}/${Guichan_HEADER} OR + NOT Guichan_LIBRARY_${COMPONENT}) + + IF (NOT Guichan_FIND_QUIETLY AND NOT Guichan_QUIET) + MESSAGE(STATUS "Found Guichan ${COMPONENT}: ${Guichan_LIBRARY_${COMPONENT}}") + ENDIF (NOT Guichan_FIND_QUIETLY AND NOT Guichan_QUIET) + + SET(GUICHAN_LIBRARIES ${GUICHAN_LIBRARIES} ${Guichan_LIBRARY_${COMPONENT}}) +ENDFOREACH(COMPONENT) + diff --git a/CMake/Modules/FindLibXml2.cmake b/CMake/Modules/FindLibXml2.cmake new file mode 100644 index 00000000..b45d7293 --- /dev/null +++ b/CMake/Modules/FindLibXml2.cmake @@ -0,0 +1,59 @@ +# - Try to find LibXml2 +# Once done this will define +# +# LIBXML2_FOUND - system has LibXml2 +# LIBXML2_INCLUDE_DIR - the LibXml2 include directory +# LIBXML2_LIBRARIES - the libraries needed to use LibXml2 +# LIBXML2_DEFINITIONS - Compiler switches required for using LibXml2 +# +# Copyright (c) 2006, Alexander Neundorf +# This code is available under the BSD license, see licenses/BSD for details. + +# Copyright (c) 2006, Alexander Neundorf, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + +IF (LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARIES) + # in cache already + SET(LibXml2_FIND_QUIETLY TRUE) +ENDIF (LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARIES) + +IF (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + INCLUDE(UsePkgConfig) + PKGCONFIG(libxml-2.0 _LibXml2IncDir _LibXml2LinkDir _LibXml2LinkFlags _LibXml2Cflags) + SET(LIBXML2_DEFINITIONS ${_LibXml2Cflags}) +ENDIF (NOT WIN32) + +FIND_PATH(LIBXML2_INCLUDE_DIR libxml/xpath.h + PATHS + ${_LibXml2IncDir} + PATH_SUFFIXES libxml2 + ) + +FIND_LIBRARY(LIBXML2_LIBRARIES NAMES xml2 libxml2 + PATHS + ${_LibXml2LinkDir} + ) + +IF (LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARIES) + SET(LIBXML2_FOUND TRUE) +ELSE (LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARIES) + SET(LIBXML2_FOUND FALSE) +ENDIF (LIBXML2_INCLUDE_DIR AND LIBXML2_LIBRARIES) + +IF (LIBXML2_FOUND) + IF (NOT LibXml2_FIND_QUIETLY) + MESSAGE(STATUS "Found LibXml2: ${LIBXML2_LIBRARIES}") + ENDIF (NOT LibXml2_FIND_QUIETLY) +ELSE (LIBXML2_FOUND) + IF (LibXml2_FIND_REQUIRED) + MESSAGE(SEND_ERROR "Could NOT find LibXml2") + ENDIF (LibXml2_FIND_REQUIRED) +ENDIF (LIBXML2_FOUND) + +MARK_AS_ADVANCED(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARIES) + diff --git a/CMake/Modules/FindLibcurl.cmake b/CMake/Modules/FindLibcurl.cmake new file mode 100644 index 00000000..fe389c49 --- /dev/null +++ b/CMake/Modules/FindLibcurl.cmake @@ -0,0 +1,41 @@ +# - Try to find libcurl +# Once done this will define +# +# LIBCURL_FOUND - system has libcurl +# LIBCURL_INCLUDE_DIR - the libcurl include directory +# LIBCURL_LIBRARIES - the libraries needed to use libcurl +# LIBCURL_DEFINITIONS - Compiler switches required for using libcurl + +IF (Libcurl_INCLUDE_DIR AND Libcurl_LIBRARY) + SET(Libcurl_FIND_QUIETLY TRUE) +ENDIF (Libcurl_INCLUDE_DIR AND Libcurl_LIBRARY) + +FIND_PATH(Libcurl_INCLUDE_DIR curl/curl.h + /usr/include + /usr/local/include + ) + +FIND_LIBRARY(Libcurl_LIBRARY + NAMES curl + PATHS /usr/lib /usr/local/lib + ) + +IF (Libcurl_INCLUDE_DIR AND Libcurl_LIBRARY) + SET(LIBCURL_FOUND TRUE) + SET(LIBCURL_INCLUDE_DIR ${Libcurl_INCLUDE_DIR}) + SET(LIBCURL_LIBRARIES ${Libcurl_LIBRARY}) +ELSE (Libcurl_INCLUDE_DIR AND Libcurl_LIBRARY) + SET(LIBCURL_FOUND TRUE) +ENDIF (Libcurl_INCLUDE_DIR AND Libcurl_LIBRARY) + +IF (LIBCURL_FOUND) + IF (NOT Libcurl_FIND_QUIETLY) + MESSAGE(STATUS "Found libcurl: ${Libcurl_LIBRARY}") + ENDIF (NOT Libcurl_FIND_QUIETLY) +ELSE (LIBCURL_FOUND) + IF (Libcurl_FIND_REQUIRED) + MESSAGE(SEND_ERROR "Could NOT find libcurl") + ENDIF (Libcurl_FIND_REQUIRED) +ENDIF (LIBCURL_FOUND) + +MARK_AS_ADVANCED(Libcurl_INCLUDE_DIR Libcurl_LIBRARY) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..0d123870 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,21 @@ +PROJECT(TMW) + +SET(VERSION 0.1.0) + +# where to look for cmake modules +SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules) + +OPTION(WITH_OPENGL "Enable OpenGL support" ON) + +IF (WIN32) + SET(PKG_DATADIR ".") + SET(PKG_BINDIR ".") +ELSE (WIN32) + SET(PKG_DATADIR ${CMAKE_INSTALL_PREFIX}/share/tmw) + SET(PKG_BINDIR ${CMAKE_INSTALL_PREFIX}/bin) +ENDIF (WIN32) + +ADD_SUBDIRECTORY(data) +ADD_SUBDIRECTORY(src) + +INSTALL(FILES tmw.desktop DESTINATION share/applications) diff --git a/ChangeLog b/ChangeLog index 33fab8df..9623800f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2006-11-01 Björn Steinbrink + + * CMake/Modules/FindLibXml2.cmake, CMake/Modules/FindENet.cmake, + CMake/Modules/FindLibcurl.cmake, CMake/Modules/FindGuichan.cmake, + src/CMakeLists.txt, src/main.h, data/graphics/tiles/CMakeLists.txt, + data/graphics/items/CMakeLists.txt, data/graphics/gui/CMakeLists.txt, + data/graphics/images/ambient/CMakeLists.txt, + data/graphics/images/CMakeLists.txt, + data/graphics/sprites/CMakeLists.txt, data/graphics/CMakeLists.txt, + data/maps/CMakeLists.txt, data/sfx/CMakeLists.txt, + data/help/CMakeLists.txt, data/icons/CMakeLists.txt, + data/CMakeLists.txt, CMakeLists.txt: Added CMake support. + 2006-09-28 Björn Steinbrink * src/map.cpp: Fix random crashes when map tiles are missing. diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt new file mode 100644 index 00000000..36259082 --- /dev/null +++ b/data/CMakeLists.txt @@ -0,0 +1,13 @@ +SET(DATA_DIR ${PKG_DATADIR}/data) + +ADD_SUBDIRECTORY(graphics) +ADD_SUBDIRECTORY(help) +ADD_SUBDIRECTORY(icons) +ADD_SUBDIRECTORY(maps) +ADD_SUBDIRECTORY(sfx) + +SET(FILES + items.xml + ) + +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}) diff --git a/data/graphics/CMakeLists.txt b/data/graphics/CMakeLists.txt new file mode 100644 index 00000000..c569e04f --- /dev/null +++ b/data/graphics/CMakeLists.txt @@ -0,0 +1,5 @@ +ADD_SUBDIRECTORY(gui) +ADD_SUBDIRECTORY(images) +ADD_SUBDIRECTORY(items) +ADD_SUBDIRECTORY(sprites) +ADD_SUBDIRECTORY(tiles) diff --git a/data/graphics/gui/CMakeLists.txt b/data/graphics/gui/CMakeLists.txt new file mode 100644 index 00000000..87585226 --- /dev/null +++ b/data/graphics/gui/CMakeLists.txt @@ -0,0 +1,45 @@ +SET (FILES + attack_target.png + bg_quad_dis.png + browserfont.png + button_disabled.png + buttonhi.png + button.png + buttonpress.png + checkbox.png + deepbox.png + fixedfont.png + hits_blue.png + hits_red.png + hits_yellow.png + hscroll_left_default.png + hscroll_left_highlight.png + hscroll_left_pressed.png + hscroll_right_default.png + hscroll_right_highlight.png + hscroll_right_pressed.png + menuitemD.png + menuitemF.png + menuitemN.png + menuitemP.png + mouse.png + radioin.png + radioout.png + resize.png + rpgfont_wider.png + sansserif8.png + selection.png + slider.png + thickborder.png + vscroll_blue.png + vscroll_down_default.png + vscroll_down_highlight.png + vscroll_down_pressed.png + vscroll_grey.png + vscroll_red.png + vscroll_up_default.png + vscroll_up_highlight.png + vscroll_up_pressed.png + ) + +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/gui) diff --git a/data/graphics/images/CMakeLists.txt b/data/graphics/images/CMakeLists.txt new file mode 100644 index 00000000..471d4c92 --- /dev/null +++ b/data/graphics/images/CMakeLists.txt @@ -0,0 +1,16 @@ +ADD_SUBDIRECTORY(ambient) + +SET(FILES + login_wallpaper.png + minimap_new_1-1.png + minimap_new_14-1.png + minimap_new_15-1.png + minimap_new_16-1.png + minimap_new_2-1.png + minimap_new_3-1.png + minimap_new_5-1.png + minimap_new_7-1.png + minimap_new_9-1.png + ) + +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/images) diff --git a/data/help/CMakeLists.txt b/data/help/CMakeLists.txt new file mode 100644 index 00000000..82f61d54 --- /dev/null +++ b/data/help/CMakeLists.txt @@ -0,0 +1,12 @@ +SET(FILES + about.txt + changes.txt + commands.txt + header.txt + index.txt + skills.txt + support.txt + team.txt + ) + +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/help) diff --git a/data/icons/CMakeLists.txt b/data/icons/CMakeLists.txt new file mode 100644 index 00000000..30d96d86 --- /dev/null +++ b/data/icons/CMakeLists.txt @@ -0,0 +1,9 @@ +SET(FILES + tmw-icon.ico + tmw-icon.png + tmw-icon.xpm + ) + +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/icons) + +INSTALL(FILES "tmw-icon.png" DESTINATION share/pixmaps RENAME tmw.png) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..b3bf323e --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,299 @@ +FIND_PACKAGE(SDL REQUIRED) +FIND_PACKAGE(SDL_image REQUIRED) +FIND_PACKAGE(SDL_mixer REQUIRED) +FIND_PACKAGE(ENet REQUIRED) +FIND_PACKAGE(Libcurl REQUIRED) +FIND_PACKAGE(LibXml2 REQUIRED) +FIND_PACKAGE(PhysFS REQUIRED) +FIND_PACKAGE(PNG REQUIRED) + +SET(FLAGS "-DPACKAGE_VERSION=\\\"${VERSION}\\\"") +SET(FLAGS "${FLAGS} -DTMW_DATADIR=\\\"${PKG_DATADIR}/\\\"") + +SET(GUICHAN_COMPONENTS "SDL") +IF (WITH_OPENGL) + SET(GUICHAN_COMPONENTS ${GUICHAN_COMPONENTS} "OpenGL") +ENDIF (WITH_OPENGL) +FIND_PACKAGE(Guichan REQUIRED ${GUICHAN_COMPONENTS}) + +IF (WITH_OPENGL) + FIND_PACKAGE(OpenGL REQUIRED) + INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR}) + SET(FLAGS "${FLAGS} -DUSE_OPENGL") +ENDIF (WITH_OPENGL) + +INCLUDE_DIRECTORIES( + ${CURRENT_SOURCE_DIR} + ${SDL_INCLUDE_DIR} + ${SDLIMAGE_INCLUDE_DIR} + ${SDLMIXER_INCLUDE_DIR} + ${ENET_INCLUDE_DIR} + ${PNG_INCLUDE_DIR} + ${PHYSFS_INCLUDE_DIR} + ${LIBCURL_INCLUDE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${GUICHAN_INCLUDE_DIR} + ) + +SET(SRCS + graphic/imagerect.h + gui/box.cpp + gui/box.h + gui/browserbox.cpp + gui/browserbox.h + gui/buddywindow.cpp + gui/buddywindow.h + gui/button.cpp + gui/button.h + gui/buy.cpp + gui/buy.h + gui/buysell.cpp + gui/buysell.h + gui/chargedialog.cpp + gui/chargedialog.h + gui/char_select.cpp + gui/char_select.h + gui/chat.cpp + gui/chat.h + gui/chatinput.cpp + gui/chatinput.h + gui/checkbox.cpp + gui/checkbox.h + gui/confirm_dialog.cpp + gui/confirm_dialog.h + gui/connection.cpp + gui/connection.h + gui/debugwindow.cpp + gui/debugwindow.h + gui/equipmentwindow.cpp + gui/equipmentwindow.h + gui/focushandler.cpp + gui/focushandler.h + gui/gccontainer.cpp + gui/gccontainer.h + gui/gui.cpp + gui/gui.h + gui/hbox.cpp + gui/hbox.h + gui/help.cpp + gui/help.h + gui/inttextbox.cpp + gui/inttextbox.h + gui/inventorywindow.cpp + gui/inventorywindow.h + gui/item_amount.cpp + gui/item_amount.h + gui/itemcontainer.cpp + gui/itemcontainer.h + gui/linkhandler.h + gui/listbox.cpp + gui/listbox.h + gui/login.cpp + gui/login.h + gui/menuwindow.cpp + gui/menuwindow.h + gui/minimap.cpp + gui/minimap.h + gui/ministatus.cpp + gui/ministatus.h + gui/newskill.cpp + gui/newskill.h + gui/npclistdialog.cpp + gui/npclistdialog.h + gui/npc_text.cpp + gui/npc_text.h + gui/ok_dialog.cpp + gui/ok_dialog.h + gui/passwordfield.cpp + gui/passwordfield.h + gui/playerbox.cpp + gui/playerbox.h + gui/popupmenu.cpp + gui/popupmenu.h + gui/progressbar.cpp + gui/progressbar.h + gui/radiobutton.cpp + gui/radiobutton.h + gui/register.cpp + gui/register.h + gui/scrollarea.cpp + gui/scrollarea.h + gui/selectionlistener.h + gui/sell.cpp + gui/sell.h + gui/serverdialog.cpp + gui/serverdialog.h + gui/setup_audio.cpp + gui/setup_audio.h + gui/setup.cpp + gui/setup.h + gui/setup_joystick.cpp + gui/setup_joystick.h + gui/setuptab.h + gui/setup_video.cpp + gui/setup_video.h + gui/shop.cpp + gui/shop.h + gui/skill.cpp + gui/skill.h + gui/slider.cpp + gui/slider.h + gui/status.cpp + gui/status.h + gui/tabbedcontainer.cpp + gui/tabbedcontainer.h + gui/textbox.cpp + gui/textbox.h + gui/textfield.cpp + gui/textfield.h + gui/trade.cpp + gui/trade.h + gui/updatewindow.cpp + gui/updatewindow.h + gui/vbox.cpp + gui/vbox.h + gui/windowcontainer.cpp + gui/windowcontainer.h + gui/window.cpp + gui/window.h + gui/widgets/dropdown.cpp + gui/widgets/dropdown.h + net/beinghandler.cpp + net/beinghandler.h + net/buysellhandler.cpp + net/buysellhandler.h + net/charserverhandler.cpp + net/charserverhandler.h + net/chathandler.cpp + net/chathandler.h + net/equipmenthandler.cpp + net/equipmenthandler.h + net/inventoryhandler.cpp + net/inventoryhandler.h + net/itemhandler.cpp + net/itemhandler.h + net/loginhandler.cpp + net/loginhandler.h + net/maploginhandler.cpp + net/maploginhandler.h + net/messagehandler.cpp + net/messagehandler.h + net/messagein.cpp + net/messagein.h + net/messageout.cpp + net/messageout.h + net/network.cpp + net/network.h + net/npchandler.cpp + net/npchandler.h + net/playerhandler.cpp + net/playerhandler.h + net/protocol.h + net/skillhandler.cpp + net/skillhandler.h + net/tradehandler.cpp + net/tradehandler.h + resources/buddylist.cpp + resources/buddylist.h + resources/image.cpp + resources/image.h + resources/imagewriter.cpp + resources/imagewriter.h + resources/iteminfo.cpp + resources/iteminfo.h + resources/itemmanager.cpp + resources/itemmanager.h + resources/mapreader.cpp + resources/mapreader.h + resources/music.cpp + resources/music.h + resources/openglsdlimageloader.cpp + resources/openglsdlimageloader.h + resources/resource.cpp + resources/resource.h + resources/resourcemanager.cpp + resources/resourcemanager.h + resources/sdlimageloader.cpp + resources/sdlimageloader.h + resources/soundeffect.cpp + resources/soundeffect.h + resources/spriteset.cpp + resources/spriteset.h + utils/dtor.h + utils/tostring.h + animatedsprite.cpp + animatedsprite.h + animation.cpp + animation.h + base64.cpp + base64.h + being.cpp + being.h + beingmanager.cpp + beingmanager.h + configlistener.h + configuration.cpp + configuration.h + engine.cpp + engine.h + equipment.cpp + equipment.h + floor_item.cpp + floor_item.h + flooritemmanager.cpp + flooritemmanager.h + game.cpp + game.h + graphics.cpp + graphics.h + guichanfwd.h + inventory.cpp + inventory.h + item.cpp + item.h + joystick.cpp + joystick.h + localplayer.cpp + localplayer.h + lockedarray.h + log.cpp + log.h + logindata.h + main.cpp + main.h + map.cpp + map.h + monster.cpp + monster.h + npc.cpp + npc.h + openglgraphics.cpp + openglgraphics.h + player.cpp + player.h + properties.h + serverinfo.h + sound.cpp + sound.h + sprite.h + tileset.h + ) + +ADD_EXECUTABLE(tmw ${SRCS}) + +TARGET_LINK_LIBRARIES(tmw + ${SDL_LIBRARY} + ${SDLIMAGE_LIBRARY} + ${SDLMIXER_LIBRARY} + ${ENET_LIBRARIES} + ${PNG_LIBRARIES} + ${PHYSFS_LIBRARY} + ${LIBCURL_LIBRARIES} + ${LIBXML2_LIBRARIES} + ${GUICHAN_LIBRARIES} + ${OPENGL_LIBRARIES} + ) + +INSTALL(TARGETS tmw RUNTIME DESTINATION ${PKG_BINDIR}) + +SET_TARGET_PROPERTIES(tmw PROPERTIES COMPILE_FLAGS "${FLAGS}") diff --git a/src/main.h b/src/main.h index 2973f1ad..b68a4e4d 100644 --- a/src/main.h +++ b/src/main.h @@ -26,7 +26,7 @@ #include -#if (defined __USE_UNIX98 || defined __FreeBSD__) +#ifdef HAVE_CONFIG_H #include "../config.h" #elif defined WIN32 #include "../The_Mana_World_private.h" -- cgit v1.2.3-60-g2f50 From 46308b7e9d65dd734664f903a09c3210f1684a6c Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Thu, 2 Nov 2006 21:46:36 +0000 Subject: Merged trunk changes from revision 2757 to 2800 into the 0.1.0 branch. --- ChangeLog | 107 +++++++++++++++++++++++++++++-- NEWS | 6 +- README | 2 +- data/graphics/gui/browserfont.png | Bin 1833 -> 1846 bytes data/graphics/gui/fixedfont.png | Bin 1880 -> 1895 bytes data/graphics/gui/rpgfont_wider.png | Bin 4279 -> 4382 bytes data/graphics/images/login_wallpaper.png | Bin 215527 -> 205907 bytes data/help/header.txt | 2 +- debian/changelog | 15 ++++- src/being.cpp | 4 +- src/gui/browserbox.cpp | 2 +- src/gui/gui.cpp | 2 +- src/main.cpp | 4 ++ src/player.cpp | 16 +++-- src/tmw.rc | 8 +-- 15 files changed, 144 insertions(+), 24 deletions(-) (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index ce76ecdb..46e3cbc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -39,9 +39,103 @@ data/help/CMakeLists.txt, data/icons/CMakeLists.txt, data/CMakeLists.txt, CMakeLists.txt: Added CMake support. +2006-11-01 Bjørn Lindeijer + + * src/gui/gui.cpp, src/gui/browserbox.cpp, + data/graphics/gui/rpgfont_wider.png, + data/graphics/gui/browserfont.png, data/graphics/gui/fixedfont.png: + Added support for Ã¥ and Ã… (with help of HÃ¥kan Rönn). + +2006-10-31 Philipp Sehmisch + + *data/graphics/tiles/desert1.png, d + ata/graphics/tiles/desert_x2.png: adding a bunch of graphical + improvements made by VxD. + +2006-10-31 Frode Lindeijer + + * /data/graphics/sprites/item011.png, + /data/graphics/sprites/item011.xml, + /data/graphics/sprites/item012.png, + /data/graphics/sprites/item018.xml, + /data/graphics/sprites/monster21.xml: Fixed some graphical issues, + mostly a cosmetic update. + +2006-10-30 Yohann Ferreira + + * debian/changelog: Updated the package's version. + +2006-10-30 Philipp Sehmisch + + * data/maps/new_9-1.tmx.gz: Removed the night effect that accidently + sneaked in with the last map change. + +2006-10-30 Eugenio Favalli + + * src/tmw.rc: Updated Windows binary version. + * data/help/header.txt, NEWS, README: Fixed some release dates and + versions. + * data/graphics/items/armor-head-axehat.png, + data/graphics/items/armor-head-bandana.png, + data/graphics/items/armor-head-circlet.png, + data/graphics/items/armor-head-eyepatch.png, + data/graphics/items/armor-head-goggles.png, + data/graphics/items/armor-head-leathergoggles.png, + data/graphics/items/armor-head-piratehat.png, + data/graphics/items/armor-head-pumpkinhelmet.png, + data/graphics/items/Makefile.am, data/items.xml: Added new items. + * data/graphics/sprites/Makefile.am, + data/graphics/sprites/monster21.png, + data/graphics/sprites/monster21.xml, + data/graphics/sprites/monster22.png, + data/graphics/sprites/monster22.xml: Added new monsters. + * data/graphics/sprites/item011.png, data/graphics/sprites/item011.xml, + data/graphics/sprites/item012.png, data/graphics/sprites/item012.xml, + data/graphics/sprites/item013.png, data/graphics/sprites/item013.xml, + data/graphics/sprites/item014.png, data/graphics/sprites/item014.xml, + data/graphics/sprites/item015.png, data/graphics/sprites/item015.xml, + data/graphics/sprites/item016.png, data/graphics/sprites/item016.xml, + data/graphics/sprites/item017.png, data/graphics/sprites/item017.xml, + data/graphics/sprites/item018.png, data/graphics/sprites/item018.xml, + data/graphics/sprites/Makefile.am: Added new visible equipments. + * data/graphics/images/login_wallpaper.png, data/maps/new_1-1.tmx.gz, + data/maps/new_10-1.tmx.gz, data/maps/new_11-1.tmx.gz, + data/maps/new_14-1.tmx.gz, data/maps/new_15-1.tmx.gz, + data/maps/new_16-1.tmx.gz, data/maps/new_3-1.tmx.gz, + data/maps/new_7-1.tmx.gz, data/maps/new_9-1.tmx.gz: Halloween related + contents. + * data/graphics/items/Makefile.am: Fixed wrong filename. + * data/graphics/sprites/Makefile.am: Fixed wrong filenames. + * data/graphics/sprites/weapon0.png: Replaced knife with scythe. + +2006-10-30 Björn Steinbrink + + * data/graphics/items/CMakeLists.txt: Synced with autotools config. + * data/graphics/items/CMakeLists.txt: Added new items to CMake config. + * src/being.cpp: Properly initialize sprite vector. + +2006-10-29 Bjørn Lindeijer + + * src/player.cpp: Fixed excessive unnecessary reloading of sprites. + +2006-10-28 Björn Steinbrink + + * src/main.c: Reload wallpaper after updates are fetched. + * data/graphics/sprites/Makefile.am: Added monster20. + +2006-10-28 Philipp Sehmisch + + * data/graphics/sprites/monster20.png, + data/graphics/sprites/monster20.xml, + data/graphics/sprites/CMakeLists.txt: + Added pumpkin ghost monster for halloween event. + * data/maps/new_9-1.tmx.gz: Fixed a map discrepancy between + new_9-1 and new_14-1 (no new walkmap required). Thanks to QOAL + for reporting. + 2006-10-24 Philipp Sehmisch - * /data/graphics/images/ambient/night.png: Added graphic for night + * data/graphics/images/ambient/night.png: added graphic for night ambient effect. 2006-10-23 Bjørn Lindeijer @@ -52,7 +146,8 @@ 2006-10-12 Yohann Ferreira * debian/rules, debian/tmw-data.install, debian/tmw-data.dirs, - debian/tmw-music.install: Updating debian files for bug fixing. + debian/tmw-music.install, debian/changelog: Updating debian files for + bug fixing. 2006-10-12 Frode Lindeijer @@ -61,12 +156,12 @@ 2006-10-12 Cédric Borgese - * data/graphics/tiles/Woodland_x3.png : Enlarge the trunk and the + * data/graphics/tiles/Woodland_x3.png: Enlarge the trunk and the base of the trees in the woodland tileset. 2006-10-09 Yohann Ferreira - * src/gui/buysell.cpp, src/gui/buy.cpp : A little tweak to the buy + * src/gui/buysell.cpp, src/gui/buy.cpp: A little tweak to the buy dialogs. 2006-10-07 Bjørn Lindeijer @@ -2711,9 +2806,9 @@ src/gui/status.h: Improving General Layout. * src/games.cpp, src/playerinfo.h, src/gui/char_server.cpp, src/gui/char_select.cpp, src/gui/ministatus.cpp, src/gui/skill.cpp, - src/gui/status.cpp, src/gui/status.h : Now the derived stats values + src/gui/status.cpp, src/gui/status.h: Now the derived stats values are got from the server, and then, are correct ones. - * src/gui/minimap.cpp : Only shows the Minimap Window if there's + * src/gui/minimap.cpp: Only shows the Minimap Window if there's actually a minimap to the current map. * src/gui/status.cpp, src/game.cpp: The derived stats are now updated correctly upon equipping/unequipping. diff --git a/NEWS b/NEWS index 4cb3dbb8..4633c39b 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ -0.0.22 (...) +0.0.21.1 (30 October 2006) +- Reload wallpaper after loading updates - Added support for gzip compressed map layer data +- Added support for building with CMake +- Added slider to setup dialog for configuring overlay effect +- Fixed excessive unnecessary reloading of sprites - Fixed problem with OpenGL related redefinition - Fixed problems with hiding windows using h - Fixed trade window positioning diff --git a/README b/README index 0313fac3..54a6dcaf 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ THE MANA WORLD ============== - Version: 0.0.21 Date: 17/09/2006 + Version: 0.0.21.1 Date: 30/10/2006 Development team: diff --git a/data/graphics/gui/browserfont.png b/data/graphics/gui/browserfont.png index a32317d8..431777c5 100644 Binary files a/data/graphics/gui/browserfont.png and b/data/graphics/gui/browserfont.png differ diff --git a/data/graphics/gui/fixedfont.png b/data/graphics/gui/fixedfont.png index 70f489bc..10319291 100644 Binary files a/data/graphics/gui/fixedfont.png and b/data/graphics/gui/fixedfont.png differ diff --git a/data/graphics/gui/rpgfont_wider.png b/data/graphics/gui/rpgfont_wider.png index 4e5d9fbf..55ccbbd6 100644 Binary files a/data/graphics/gui/rpgfont_wider.png and b/data/graphics/gui/rpgfont_wider.png differ diff --git a/data/graphics/images/login_wallpaper.png b/data/graphics/images/login_wallpaper.png index 54692dfd..258bad22 100644 Binary files a/data/graphics/images/login_wallpaper.png and b/data/graphics/images/login_wallpaper.png differ diff --git a/data/help/header.txt b/data/help/header.txt index 30c1dc93..b292388a 100644 --- a/data/help/header.txt +++ b/data/help/header.txt @@ -2,7 +2,7 @@ ##1 T H E M A N A W O R L D ##1 ========================================== - ##2Version:##6 0.0.21 ##2Date:##6 17 September 2006 + ##2Version:##6 0.0.21.1 ##2Date:##30 October 2006 ##2 Website: http://themanaworld.org diff --git a/debian/changelog b/debian/changelog index 5e71e51e..0cd1763d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,16 @@ +tmw (0.0.21.1-1) unstable; urgency=low + + * Bugfixes release. + + -- FERREIRA Yohann Mon, 30 Oct 2006 22:32:00 +0200 + +tmw (0.0.21-2) unstable; urgency=low + + * Readded Music Files in ogg format. + * Added the forgotten data/graphics/items folder to avoid a crash. + + -- FERREIRA Yohann Mon, 16 Oct 2006 15:52:00 +0200 + tmw (0.0.21-1) unstable; urgency=low * New upstream release: @@ -9,7 +22,7 @@ tmw (0.0.21-1) unstable; urgency=low tmw (0.0.20-1) unstable; urgency=low * Make use of a own desktop file for the Debian Package. Close the missing icon bug. - * Changed a dependency from xlibmesa-dev to libgl1-mesa-dev to cope with new X server. + * Changed dependency from xlibmesa-dev to libgl1-mesa-dev to cope with new X server. -- FERREIRA Yohann Mon, 29 May 2006 03:55:33 +0200 diff --git a/src/being.cpp b/src/being.cpp index 4d542753..fa24ad69 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -64,10 +64,10 @@ Being::Being(Uint16 id, Uint16 job, Map *map): mHairStyle(0), mHairColor(0), mSpeechTime(0), mDamageTime(0), - mShowSpeech(false), mShowDamage(false) + mShowSpeech(false), mShowDamage(false), + mSprites(VECTOREND_SPRITE, NULL) { setMap(map); - mSprites.resize(VECTOREND_SPRITE, NULL); } Being::~Being() diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp index 06660cd5..2aec84a5 100644 --- a/src/gui/browserbox.cpp +++ b/src/gui/browserbox.cpp @@ -56,7 +56,7 @@ BrowserBox::BrowserBox(unsigned int mode): " abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567" "89:@!\"$%&/=?^+*#[]{}()<>_;'.,\\|-~`" - "øåáÁéÉíÍóÓúÚç륣¢¡¿àãõêñÑöüäÖÜÄß"); + "øåáÁéÉíÍóÓúÚç륣¢¡¿àãõêñÑöüäÖÜÄßèÈÅ"); } setFont(browserFont); instances++; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 33852f2b..38b17781 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -143,7 +143,7 @@ Gui::Gui(Graphics *graphics): speechFont = new gcn::ImageFont("graphics/gui/rpgfont_wider.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789.,!?-+/():;%&`'*#=[]\"<>{}^~|_@$\\" - "áÁéÉíÍóÓúÚç륣¢¡¿àãõêñÑöüäÖÜÄßø" + "áÁéÉíÍóÓúÚç륣¢¡¿àãõêñÑöüäÖÜÄßøèÈåÅ" ); } catch (gcn::Exception e) diff --git a/src/main.cpp b/src/main.cpp index 0ae328ea..ea2b7829 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -643,6 +643,10 @@ int main(int argc, char *argv[]) if (oldstate == STATE_UPDATE) { loadUpdates(); + // Reload the wallpaper in case that it was updated + login_wallpaper->decRef(); + login_wallpaper = ResourceManager::getInstance()-> + getImage("graphics/images/login_wallpaper.png"); } oldstate = state; diff --git a/src/player.cpp b/src/player.cpp index f5f42e9f..12f5f3d5 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -93,12 +93,12 @@ Player::setHairColor(Uint16 color) { if (color != mHairColor) { - delete mSprites[HAIR_SPRITE]; AnimatedSprite *newHairSprite = new AnimatedSprite( "graphics/sprites/hairstyle" + toString(mHairStyle) + ".xml", color); newHairSprite->setDirection(getSpriteDirection()); + delete mSprites[HAIR_SPRITE]; mSprites[HAIR_SPRITE] = newHairSprite; resetAnimations(); @@ -113,12 +113,12 @@ Player::setHairStyle(Uint16 style) { if (style != mHairStyle) { - delete mSprites[HAIR_SPRITE]; AnimatedSprite *newHairSprite = new AnimatedSprite( "graphics/sprites/hairstyle" + toString(style) + ".xml", mHairColor); newHairSprite->setDirection(getSpriteDirection()); + delete mSprites[HAIR_SPRITE]; mSprites[HAIR_SPRITE] = newHairSprite; resetAnimations(); @@ -145,11 +145,14 @@ Player::setVisibleEquipment(Uint8 slot, Uint8 id) break; } - delete mSprites[position]; - mSprites[position] = NULL; - // id = 0 means unequip - if (id) { + if (id == 0) + { + delete mSprites[position]; + mSprites[position] = NULL; + } + else + { char stringId[4]; sprintf(stringId, "%03i", id); @@ -157,6 +160,7 @@ Player::setVisibleEquipment(Uint8 slot, Uint8 id) "graphics/sprites/item" + toString(stringId) + ".xml", 0); equipmentSprite->setDirection(getSpriteDirection()); + delete mSprites[position]; mSprites[position] = equipmentSprite; resetAnimations(); diff --git a/src/tmw.rc b/src/tmw.rc index 388b643d..d3a43b72 100644 --- a/src/tmw.rc +++ b/src/tmw.rc @@ -7,8 +7,8 @@ A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "data/icons/tmw-icon.ico" // TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS... // 1 VERSIONINFO -FILEVERSION 0,0,21,0 -PRODUCTVERSION 0,0,21,0 +FILEVERSION 0,0,21,1 +PRODUCTVERSION 0,0,21,1 FILETYPE VFT_APP { BLOCK "StringFileInfo" @@ -16,14 +16,14 @@ FILETYPE VFT_APP BLOCK "040904E4" { VALUE "CompanyName", "The Mana World Development Team" - VALUE "FileVersion", "0.0.21" + VALUE "FileVersion", "0.0.21.1" VALUE "FileDescription", "The Mana World" VALUE "InternalName", "tmw.exe" VALUE "LegalCopyright", "2004-2006 (C)" VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "tmw.exe" VALUE "ProductName", "The Mana World MMORPG" - VALUE "ProductVersion", "0.0.21" + VALUE "ProductVersion", "0.0.21.1" } } BLOCK "VarFileInfo" -- cgit v1.2.3-60-g2f50 From 6374ef220d8f46647190074338f868b5d6bb4a45 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 5 Nov 2006 15:22:13 +0000 Subject: Merged 0.0 changes from revision 2800 to 2825 to trunk. --- ChangeLog | 79 ++++++++++-- data/graphics/images/CMakeLists.txt | 3 +- data/graphics/images/Makefile.am | 3 +- data/graphics/images/login_wallpaper.png | Bin 205907 -> 215527 bytes src/CMakeLists.txt | 2 + src/Makefile.am | 2 + src/being.cpp | 12 ++ src/being.h | 2 +- src/gui/buy.cpp | 36 +++--- src/gui/buy.h | 3 +- src/gui/sell.cpp | 56 +++++---- src/gui/sell.h | 10 +- src/gui/shop.cpp | 44 ++++++- src/gui/shop.h | 37 +++++- src/gui/shoplistbox.cpp | 200 +++++++++++++++++++++++++++++++ src/gui/shoplistbox.h | 124 +++++++++++++++++++ src/gui/updatewindow.cpp | 3 +- src/main.cpp | 2 +- src/net/buysellhandler.cpp | 1 + src/player.cpp | 38 +++++- src/player.h | 3 + src/resources/resourcemanager.cpp | 8 +- 22 files changed, 595 insertions(+), 73 deletions(-) create mode 100644 src/gui/shoplistbox.cpp create mode 100644 src/gui/shoplistbox.h (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index 45b92cbd..663c53b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2006-11-05 Bjørn Lindeijer + + * data/graphics/images/login_wallpaper.png: Reverted to standard + wallpaper. + * src/resources/resourcemanager.cpp: More useful logging about + resources that are being loaded (including source). + +2006-11-05 Yohann Ferreira + + * src/Makefile.am, src/gui/buy.cpp, src/gui/buy.h, src/gui/shop.h, + src/gui/shop.cpp, src/gui/sell.cpp, src/gui/shoplistbox.h, + src/gui/shoplistbox.cpp: Added pictures to items in buy dialogs. + Also too expensive items are highlighted in gray and can't be + selected. + * src/gui/shop.cpp, src/gui/shop.h, src/gui.sell.h, src/gui/sell.cpp, + src/net/buysellhandler.cpp, src/gui/shoplistbox.h, + src/gui/shoplistbox.cpp: Added item's pictures in sell dialogs, and + precisions about the total money in it. + * src/gui/shop.h, src/gui/shop.cpp, src/gui/sell.cpp: Fixes to Sell + dialog. + +2006-11-05 Björn Steinbrink + + * data/graphics/sprites/Makefile.am: Use tabs instead of spaces as + required by automake (AFAIK). + +2006-11-05 Philipp Sehmisch + + * data/graphics/sprites/weapon0.png, + data/graphics/sprites/weapon2.png, + data/graphics/sprites/weapon-bow.xml, + data/graphics/sprites/weapon-dagger.xml, + data/graphics/sprites/weapon-fist.xml, + data/graphics/sprites/weapon-scythe.xml, + data/graphics/items/weapon-polearm-scythe.png, src/player.cpp, + src/player.h, src/being.cpp, src/being.h, data/items.xml: Added scythe + as a permanent weapon (ID: 623) + 2006-11-04 Björn Steinbrink * src/main.cpp: Use \n instead of std::endl when writing to stdout. @@ -9,6 +47,31 @@ instead of /dev/null to quieten libxml2. Actually initialize libxml2 before using it to load the configuration. +2006-11-04 Bjørn Lindeijer + + * data/maps/new_1-1.tmx.gz, data/maps/new_10-1.tmx.gz, + data/maps/new_11-1.tmx.gz, data/maps/new_14-1.tmx.gz, + data/maps/new_15-1.tmx.gz, data/maps/new_16-1.tmx.gz, + data/maps/new_3-1.tmx.gz, data/maps/new_7-1.tmx.gz, + data/maps/new_9-1.tmx.gz: Reverted Halloween map versions, except for + map 10 and 11 which include the latest fixes by Crush but now have + their night layer removed. + +2006-11-04 Philipp Sehmisch + + * data/maps/new_17-1.tmx.gz, + data/graphics/images/minimap_new_17-1.png, + data/graphics/images/Makefile.am, + data/graphics/images/CMakeLists.txt: + Added music and minimap to woodland cave level 2. + * data/maps/new_10-1.tmx.gz, maps/new_11-1.tmx.gz: + Fixed some map bugs (please update server sided walkmap) + +2006-11-03 Bjørn Lindeijer + + * src/gui/updatewindow.cpp, src/main.cpp: Updated to the new default + updatehost. + 2006-11-02 Björn Steinbrink * src/gui/register.cpp, src/gui/register.h: Fixed a memory leak and a @@ -59,17 +122,15 @@ 2006-10-31 Philipp Sehmisch - *data/graphics/tiles/desert1.png, d - ata/graphics/tiles/desert_x2.png: adding a bunch of graphical - improvements made by VxD. + * data/graphics/tiles/desert1.png, data/graphics/tiles/desert_x2.png: + Adding a bunch of graphical improvements made by VxD. 2006-10-31 Frode Lindeijer - * /data/graphics/sprites/item011.png, - /data/graphics/sprites/item011.xml, - /data/graphics/sprites/item012.png, - /data/graphics/sprites/item018.xml, - /data/graphics/sprites/monster21.xml: Fixed some graphical issues, + * data/graphics/sprites/item011.png, + data/graphics/sprites/item011.xml, data/graphics/sprites/item012.png, + data/graphics/sprites/item018.xml, + data/graphics/sprites/monster21.xml: Fixed some graphical issues, mostly a cosmetic update. 2006-10-30 Yohann Ferreira @@ -78,7 +139,7 @@ 2006-10-30 Philipp Sehmisch - * data/maps/new_9-1.tmx.gz: Removed the night effect that accidently + * data/maps/new_9-1.tmx.gz: Removed the night effect that accidentally sneaked in with the last map change. 2006-10-30 Eugenio Favalli diff --git a/data/graphics/images/CMakeLists.txt b/data/graphics/images/CMakeLists.txt index 471d4c92..53f8b3a7 100644 --- a/data/graphics/images/CMakeLists.txt +++ b/data/graphics/images/CMakeLists.txt @@ -11,6 +11,7 @@ SET(FILES minimap_new_5-1.png minimap_new_7-1.png minimap_new_9-1.png + minimap_new_17-1.png ) -INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/images) +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/images) \ No newline at end of file diff --git a/data/graphics/images/Makefile.am b/data/graphics/images/Makefile.am index fb54cb95..cc71b18a 100644 --- a/data/graphics/images/Makefile.am +++ b/data/graphics/images/Makefile.am @@ -12,7 +12,8 @@ images_DATA = \ minimap_new_9-1.png \ minimap_new_14-1.png \ minimap_new_15-1.png \ - minimap_new_16-1.png + minimap_new_16-1.png \ + minimap_new_17-1.png EXTRA_DIST = \ $(images_DATA) \ No newline at end of file diff --git a/data/graphics/images/login_wallpaper.png b/data/graphics/images/login_wallpaper.png index 258bad22..54692dfd 100644 Binary files a/data/graphics/images/login_wallpaper.png and b/data/graphics/images/login_wallpaper.png differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6a46aba4..8523b066 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -134,6 +134,8 @@ SET(SRCS gui/setup_video.h gui/shop.cpp gui/shop.h + gui/shoplistbox.cpp + gui/shoplistbox.h gui/skill.cpp gui/skill.h gui/slider.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 8ab16e32..5c8d77a0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -95,6 +95,8 @@ tmw_SOURCES = graphic/imagerect.h \ gui/setup_video.h \ gui/shop.cpp \ gui/shop.h \ + gui/shoplistbox.cpp \ + gui/shoplistbox.h \ gui/skill.cpp \ gui/skill.h \ gui/slider.cpp \ diff --git a/src/being.cpp b/src/being.cpp index fa24ad69..50a2dc35 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -321,6 +321,9 @@ Being::setAction(Uint8 action) else { switch (getWeapon()) { + case 3: + currentAction = ACTION_ATTACK; + break; case 2: currentAction = ACTION_ATTACK_BOW; break; @@ -565,12 +568,17 @@ Being::getType() const void Being::setWeaponById(Uint16 weapon) { + //TODO: Use an external file to map weapon IDs to weapon types switch (weapon) { case 529: // iron arrows case 1199: // arrows break; + case 623: //scythe + setWeapon(3); + break; + case 1200: // bow case 530: // short bow case 545: // forest bow @@ -578,6 +586,10 @@ Being::setWeaponById(Uint16 weapon) break; case 521: // sharp knife + /* UNCOMMENT TO TEST SHARP KNIFE AS SCYTHE + * setWeapon(3) + * break; + */ case 522: // dagger case 536: // short sword case 1201: // knife diff --git a/src/being.h b/src/being.h index d8db9375..2804b20b 100644 --- a/src/being.h +++ b/src/being.h @@ -258,7 +258,7 @@ class Being : public Sprite * * @param weapon the picture id */ - void + virtual void setWeapon(Uint16 weapon) { mWeapon = weapon; } /** diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 73f696b7..b681b683 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -26,14 +26,12 @@ #include #include "button.h" -#include "listbox.h" #include "scrollarea.h" #include "shop.h" #include "slider.h" #include "../npc.h" -#include "../resources/iteminfo.h" #include "../resources/itemmanager.h" #include "../utils/tostring.h" @@ -45,8 +43,8 @@ BuyDialog::BuyDialog(): { mShopItems = new ShopItems; - mItemList = new ListBox(mShopItems); - mScrollArea = new ScrollArea(mItemList); + mShopItemList = new ShopListBox(mShopItems, mShopItems); + mScrollArea = new ScrollArea(mShopItemList); mSlider = new Slider(1.0); mQuantityLabel = new gcn::Label("0"); mMoneyLabel = new gcn::Label("Price : 0 GP / 0 GP"); @@ -60,7 +58,7 @@ BuyDialog::BuyDialog(): setContentSize(260, 210); mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); mScrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110)); - mItemList->setDimension(gcn::Rectangle(5, 5, 238, 110)); + mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110)); mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10)); mSlider->setEnabled(false); @@ -84,11 +82,11 @@ BuyDialog::BuyDialog(): mItemEffectLabel->setDimension(gcn::Rectangle(5, 150, 240, 14)); mItemDescLabel->setDimension(gcn::Rectangle(5, 169, 240, 14)); - mItemList->setEventId("item"); + mShopItemList->setEventId("item"); mSlider->setEventId("slider"); - mItemList->addActionListener(this); - mItemList->addSelectionListener(this); + mShopItemList->addActionListener(this); + mShopItemList->addSelectionListener(this); mSlider->addActionListener(this); add(mScrollArea); @@ -113,6 +111,7 @@ BuyDialog::~BuyDialog() void BuyDialog::setMoney(int amount) { mMoney = amount; + mShopItemList->setPlayersMoney(amount); mMoneyLabel->setCaption("Price : 0 GP / " + toString(mMoney) + " GP"); mMoneyLabel->adjustSize(); } @@ -125,7 +124,7 @@ void BuyDialog::reset() mAmountItems = 0; // Reset Previous Selected Items to prevent failing asserts - mItemList->setSelected(-1); + mShopItemList->setSelected(-1); mIncreaseButton->setEnabled(false); mDecreaseButton->setEnabled(false); mQuantityLabel->setCaption("0"); @@ -138,20 +137,13 @@ void BuyDialog::reset() void BuyDialog::addItem(short id, int price) { - ITEM_SHOP item_shop; - - item_shop.name = itemDb->getItemInfo(id).getName() + " " - + toString(price) + " GP"; - item_shop.price = price; - item_shop.id = id; - - mShopItems->push_back(item_shop); - mItemList->adjustSize(); + mShopItems->addItem(id, price); + mShopItemList->adjustSize(); } void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) { - int selectedItem = mItemList->getSelected(); + int selectedItem = mShopItemList->getSelected(); if (eventId == "item") { @@ -169,7 +161,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) // If no item was selected, none can be bought, otherwise // calculate how many the player can afford - mMaxItems = (mItemList->getSelected() == -1) ? 0 : + mMaxItems = (mShopItemList->getSelected() == -1) ? 0 : mMoney / mShopItems->at(selectedItem).price; // When at least one item can be bought, enable the slider and the @@ -184,7 +176,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) } // The following actions require a valid selection - if (selectedItem < 0 || selectedItem >= int(mShopItems->size())) + if (selectedItem < 0 || selectedItem >= int(mShopItems->getNumberOfElements())) { return; } @@ -269,7 +261,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) void BuyDialog::selectionChanged(const SelectionEvent &event) { - int selectedItem = mItemList->getSelected(); + int selectedItem = mShopItemList->getSelected(); if (selectedItem > -1) { diff --git a/src/gui/buy.h b/src/gui/buy.h index f5c163e1..b83b6f2f 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -28,6 +28,7 @@ #include "window.h" #include "selectionlistener.h" +#include "shoplistbox.h" #include "../guichanfwd.h" @@ -96,7 +97,7 @@ class BuyDialog : public Window, public gcn::ActionListener, SelectionListener gcn::Button *mQuitButton; gcn::Button *mIncreaseButton; gcn::Button *mDecreaseButton; - ListBox *mItemList; + ShopListBox *mShopItemList; gcn::ScrollArea *mScrollArea; gcn::Label *mItemDescLabel; gcn::Label *mItemEffectLabel; diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 9c25aced..fd63633c 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -28,7 +28,7 @@ #include #include "button.h" -#include "listbox.h" +#include "shoplistbox.h" #include "scrollarea.h" #include "shop.h" #include "slider.h" @@ -47,11 +47,11 @@ SellDialog::SellDialog(): { mShopItems = new ShopItems(); - mItemList = new ListBox(mShopItems); - ScrollArea *scrollArea = new ScrollArea(mItemList); + mShopItemList = new ShopListBox(mShopItems, mShopItems); + ScrollArea *scrollArea = new ScrollArea(mShopItemList); mSlider = new Slider(1.0); mQuantityLabel = new gcn::Label("0"); - mMoneyLabel = new gcn::Label("Price: 0"); + mMoneyLabel = new gcn::Label("Money: 0 GP / Total: 0 GP"); mItemDescLabel = new gcn::Label("Description:"); mItemEffectLabel = new gcn::Label("Effect:"); mIncreaseButton = new Button("+", "+", this); @@ -63,7 +63,7 @@ SellDialog::SellDialog(): setContentSize(260, 210); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); scrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110)); - mItemList->setDimension(gcn::Rectangle(5, 5, 238, 110)); + mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110)); mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10)); mSlider->setEnabled(false); @@ -87,11 +87,13 @@ SellDialog::SellDialog(): quitButton->setPosition(208, 186); - mItemList->setEventId("item"); + mShopItemList->setEventId("item"); mSlider->setEventId("mSlider"); - mItemList->addActionListener(this); - mItemList->addSelectionListener(this); + mShopItemList->setPriceCheck(false); + + mShopItemList->addActionListener(this); + mShopItemList->addSelectionListener(this); mSlider->addActionListener(this); add(scrollArea); @@ -121,13 +123,14 @@ void SellDialog::reset() mQuantityLabel->setCaption("0"); mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Price: 0"); + mMoneyLabel->setCaption("Money: 0 GP / Total: " + + toString(mPlayerMoney) + " GP"); mMoneyLabel->adjustSize(); mItemDescLabel->setCaption(""); mItemEffectLabel->setCaption(""); // Reset Previous Selected Items to prevent failing asserts - mItemList->setSelected(-1); + mShopItemList->setSelected(-1); mIncreaseButton->setEnabled(false); mDecreaseButton->setEnabled(false); } @@ -144,14 +147,15 @@ void SellDialog::addItem(Item *item, int price) item_shop.index = item->getInvIndex(); item_shop.id = item->getId(); item_shop.quantity = item->getQuantity(); + item_shop.image = item->getInfo().getImage(); mShopItems->push_back(item_shop); - mItemList->adjustSize(); + mShopItemList->adjustSize(); } void SellDialog::action(const std::string &eventId, gcn::Widget *widget) { - int selectedItem = mItemList->getSelected(); + int selectedItem = mShopItemList->getSelected(); if (eventId == "item") { @@ -160,19 +164,22 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) mDecreaseButton->setEnabled(false); mSellButton->setEnabled(false); - mQuantityLabel->setCaption("0"); mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Price: 0"); + mMoneyLabel->setCaption("Money: 0 GP / Total: " + + toString(mPlayerMoney) + " GP"); mMoneyLabel->adjustSize(); if (selectedItem > -1) { mSlider->setEnabled(true); mIncreaseButton->setEnabled(true); mMaxItems = mShopItems->at(selectedItem).quantity; + mQuantityLabel->setCaption("0 / " + toString(mMaxItems)); } else { mSlider->setEnabled(false); mIncreaseButton->setEnabled(false); + mQuantityLabel->setCaption("0"); } + mQuantityLabel->adjustSize(); } else if (eventId == "quit") { @@ -181,7 +188,7 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) } // The following actions require a valid item selection - if (selectedItem == -1 || selectedItem >= int(mShopItems->size())) { + if (selectedItem == -1 || selectedItem >= int(mShopItems->getNumberOfElements())) { return; } @@ -224,14 +231,16 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) */ mMaxItems -= mAmountItems; + mShopItems->getShop()->at(selectedItem).quantity = mMaxItems; mAmountItems = 0; mSlider->setValue(0); mSlider->setEnabled(mMaxItems != 0); // All were sold if (!mMaxItems) { - mItemList->setSelected(-1); - mShopItems->erase(mShopItems->begin() + selectedItem); + + mShopItemList->setSelected(-1); + mShopItems->getShop()->erase(mShopItems->getShop()->begin() + selectedItem); } // Update only when there are items left, the entry doesn't exist @@ -243,11 +252,12 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) if (updateButtonsAndLabels) { // Update labels - mQuantityLabel->setCaption(toString(mAmountItems)); + mQuantityLabel->setCaption(toString(mAmountItems) + " / " + toString(mMaxItems)); mQuantityLabel->adjustSize(); int price = mAmountItems * mShopItems->at(selectedItem).price; - mMoneyLabel->setCaption("Price: " + toString(price)); + mMoneyLabel->setCaption("Money: " + toString(price) + " GP / Total: " + + toString(price + mPlayerMoney) + " GP"); mMoneyLabel->adjustSize(); // Update Buttons @@ -259,7 +269,7 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) void SellDialog::selectionChanged(const SelectionEvent &event) { - int selectedItem = mItemList->getSelected(); + int selectedItem = mShopItemList->getSelected(); if (selectedItem > -1) { @@ -275,3 +285,9 @@ void SellDialog::selectionChanged(const SelectionEvent &event) mItemEffectLabel->setCaption("Effect"); } } + +void SellDialog::setMoney(int amount) +{ + mPlayerMoney = amount; + mShopItemList->setPlayersMoney(amount); +} diff --git a/src/gui/sell.h b/src/gui/sell.h index 69f8b089..ba324576 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -33,7 +33,7 @@ class Item; class ShopItems; -class ListBox; +class ShopListBox; /** * The sell dialog. @@ -77,11 +77,16 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener */ void selectionChanged(const SelectionEvent &event); + /** + * Gives Player's Money amount + */ + void setMoney(int amount); + private: gcn::Button *mSellButton; gcn::Button *mIncreaseButton; gcn::Button *mDecreaseButton; - ListBox *mItemList; + ShopListBox *mShopItemList; gcn::Label *mMoneyLabel; gcn::Label *mItemDescLabel; gcn::Label *mItemEffectLabel; @@ -89,6 +94,7 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener gcn::Slider *mSlider; ShopItems *mShopItems; + int mPlayerMoney; int mMaxItems; int mAmountItems; diff --git a/src/gui/shop.cpp b/src/gui/shop.cpp index 3706cdf8..3f30732a 100644 --- a/src/gui/shop.cpp +++ b/src/gui/shop.cpp @@ -22,13 +22,53 @@ */ #include "shop.h" +#include "../utils/tostring.h" +#include "../resources/itemmanager.h" + +ShopItems::~ShopItems() +{ + clear(); +} int ShopItems::getNumberOfElements() { - return size(); + return mItemsShop.size(); } std::string ShopItems::getElementAt(int i) { - return at(i).name; + return mItemsShop.at(i).name; +} + +void ShopItems::addItem(short id, int price) +{ + ITEM_SHOP item_shop; + + item_shop.name = itemDb->getItemInfo(id).getName() + + " " + toString(price) + " GP"; + item_shop.price = price; + item_shop.id = id; + item_shop.image = itemDb->getItemInfo(id).getImage(); + + mItemsShop.push_back(item_shop); +} + +ITEM_SHOP ShopItems::at(int i) +{ + return mItemsShop.at(i); +} + +void ShopItems::push_back(ITEM_SHOP item_shop) +{ + mItemsShop.push_back(item_shop); +} + +void ShopItems::clear() +{ + mItemsShop.clear(); +} + +std::vector* ShopItems::getShop() +{ + return &mItemsShop; } diff --git a/src/gui/shop.h b/src/gui/shop.h index fb1f33fd..de452b5c 100644 --- a/src/gui/shop.h +++ b/src/gui/shop.h @@ -28,22 +28,34 @@ #include #include +#include "../resources/image.h" struct ITEM_SHOP { + short id; std::string name; + Image *image; int price; - short id; int index; int quantity; }; -class ShopItems : public std::vector, public gcn::ListModel +class ShopItems : public gcn::ListModel { public: /** * Destructor */ - virtual ~ShopItems() {}; + ~ShopItems(); + + /** + * Adds an item and its associated picture + */ + void addItem(short id, int price); + + /** + * Convenience function for adding items + */ + void push_back(ITEM_SHOP item_shop); /** * Returns the number of items in the shop. @@ -54,6 +66,25 @@ class ShopItems : public std::vector, public gcn::ListModel * Returns the name of item number i in the shop. */ std::string getElementAt(int i); + + /** + * Returns the item number i in the shop. + */ + ITEM_SHOP at(int i); + + /** + * Clear the vector. + */ + void clear(); + + /** + * Direct access to the vector + */ + std::vector* getShop(); + + private: + std::vector mItemsShop; + }; #endif diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp new file mode 100644 index 00000000..61abff35 --- /dev/null +++ b/src/gui/shoplistbox.cpp @@ -0,0 +1,200 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: listbox.cpp 2655 2006-09-03 21:25:02Z b_lindeijer $ + */ + +#include "shoplistbox.h" + +#include "selectionlistener.h" + +#include +#include +#include +#include +#include +#include + +#include "../graphics.h" + +const int ITEM_SPRITE_HEIGHT = 32; + +ShopListBox::ShopListBox(gcn::ListModel *listModel): + gcn::ListBox(listModel), + mMousePressed(false), + mPlayerMoney(0) +{ + mRowHeight = getFont()->getHeight(); + mPriceCheck = true; +} + +ShopListBox::ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel): + gcn::ListBox(listModel), + mMousePressed(false), + mPlayerMoney(0), + mShopItems(shopListModel) +{ + mRowHeight = (getFont()->getHeight() > ITEM_SPRITE_HEIGHT ? + getFont()->getHeight() : ITEM_SPRITE_HEIGHT); + mPriceCheck = true; +} + + +void ShopListBox::setPlayersMoney(int money) +{ + mPlayerMoney = money; +} + +void ShopListBox::draw(gcn::Graphics *graphics) +{ + if (mListModel == NULL) { + return; + } + + graphics->setFont(getFont()); + + // Draw the list elements + for (int i = 0, y = 0; i < mListModel->getNumberOfElements(); ++i, y += mRowHeight) + { + graphics->setColor(gcn::Color(0xffffff)); + if (mShopItems != NULL) + { + if(mPlayerMoney < mShopItems->at(i).price && mPriceCheck) + { + graphics->setColor(gcn::Color(0x919191)); + } + } + graphics->fillRectangle(gcn::Rectangle(0, y, getWidth(), mRowHeight)); + if (mShopItems) + dynamic_cast(graphics)->drawImage(mShopItems->at(i).image, 1, y); + graphics->drawText(mListModel->getElementAt(i), ITEM_SPRITE_HEIGHT, y); + } + + // Draw rectangle below the selected list element and the list element + // not shown. + if (mSelected >= 0) { + graphics->setColor(gcn::Color(110, 160, 255)); + graphics->fillRectangle(gcn::Rectangle(0, mRowHeight * mSelected, + getWidth(), mRowHeight)); + if (mShopItems) + dynamic_cast(graphics)->drawImage( + mShopItems->at(mSelected).image, 1, mRowHeight * mSelected); + graphics->drawText(mListModel->getElementAt(mSelected), + ITEM_SPRITE_HEIGHT, mRowHeight * mSelected); + } +} + +void ShopListBox::setSelected(int selected) +{ + gcn::ListBox::setSelected(selected); + if (mListModel != NULL) + { + gcn::BasicContainer *par = getParent(); + if (par == NULL) + { + return; + } + + gcn::Rectangle scroll; + + if (mSelected < 0) + { + scroll.y = 0; + } + else + { + scroll.y = mRowHeight * mSelected; + } + + scroll.height = mRowHeight; + par->showWidgetPart(this, scroll); + } + fireSelectionChangedEvent(); +} + +void ShopListBox::mousePress(int x, int y, int button) +{ + + bool enoughMoney = false; + if (button == gcn::MouseInput::LEFT && hasMouse()) + { + if (mShopItems) + { + if(mPlayerMoney >= mShopItems->at(y / mRowHeight).price) + enoughMoney = true; + } + else // Old Behaviour + enoughMoney = true; + + if (!mPriceCheck) + enoughMoney = true; + + if (enoughMoney) + { + setSelected(y / mRowHeight); + generateAction(); + mMousePressed = true; + } + } +} + +void ShopListBox::mouseRelease(int x, int y, int button) +{ + gcn::ListBox::mouseRelease(x, y, button); + + mMousePressed = false; +} + +void ShopListBox::mouseMotion(int x, int y) +{ + gcn::ListBox::mouseMotion(x, y); + + // Pretend mouse is pressed continuously while dragged. Causes list + // selection to be updated as is default in many GUIs. + if (mMousePressed) + { + mousePress(x, y, gcn::MouseInput::LEFT); + } +} + +void ShopListBox::fireSelectionChangedEvent() +{ + SelectionEvent event(this); + SelectionListeners::iterator i_end = mListeners.end(); + SelectionListeners::iterator i; + + for (i = mListeners.begin(); i != i_end; ++i) + { + (*i)->selectionChanged(event); + } +} + +void ShopListBox::adjustSize() +{ + if (mListModel != NULL) + { + setHeight(mRowHeight * mListModel->getNumberOfElements()); + } +} + +void ShopListBox::setPriceCheck(bool check) +{ + mPriceCheck = check; +} diff --git a/src/gui/shoplistbox.h b/src/gui/shoplistbox.h new file mode 100644 index 00000000..2dff8977 --- /dev/null +++ b/src/gui/shoplistbox.h @@ -0,0 +1,124 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: listbox.h 2655 2006-09-03 21:25:02Z b_lindeijer $ + */ + +#ifndef _TMW_LISTBOX_H +#define _TMW_LISTBOX_H + +#include +#include "shop.h" + +class SelectionListener; + +/** + * A list box, meant to be used inside a scroll area. Same as the Guichan list + * box except this one doesn't have a background, instead completely relying + * on the scroll area. It also adds selection listener functionality. + * + * \ingroup GUI + */ +class ShopListBox : public gcn::ListBox +{ + public: + /** + * Constructor. + */ + ShopListBox(gcn::ListModel *listModel); + + /** + * Constructor with shopitems + */ + ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel); + + /** + * Draws the list box. + */ + void draw(gcn::Graphics *graphics); + + void mousePress(int x, int y, int button); + void mouseRelease(int x, int y, int button); + void mouseMotion(int x, int y); + + /** + * Adds a listener to the list that's notified each time a change to + * the selection occurs. + */ + void addSelectionListener(SelectionListener *listener) + { + mListeners.push_back(listener); + } + + /** + * Removes a listener from the list that's notified each time a change + * to the selection occurs. + */ + void removeSelectionListener(SelectionListener *listener) + { + mListeners.remove(listener); + } + + /** + * Sets the index of the selected element. + */ + void setSelected(int selected); + + /** + * gives information about the current player's money + */ + void setPlayersMoney(int money); + + /** + * Adjust List draw size + */ + void adjustSize(); + + /** + * Set on/off the disabling of too expensive items. + * (Good for selling mode.) + */ + void setPriceCheck(bool check); + + private: + /** + * Sends out selection events to the list of selection listeners. + */ + void fireSelectionChangedEvent(); + + bool mMousePressed; /**< Keeps track of mouse pressed status. */ + + std::list mListeners; + + int mPlayerMoney; + + /** + * Keeps another pointer to the same listModel, permitting to + * use the ShopItems specific functions. + */ + ShopItems *mShopItems; + + int mRowHeight; /**< Row Height */ + + bool mPriceCheck; + +}; + +#endif diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 510e10ba..c29906a1 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -86,7 +86,8 @@ UpdaterWindow::UpdaterWindow(): mCancelButton->requestFocus(); setLocationRelativeTo(getParent()); - mUpdateHost = config.getValue("updatehost", "themanaworld.org/files"); + mUpdateHost = + config.getValue("updatehost", "http://updates.themanaworld.org"); mBasePath = config.getValue("homeDir", "."); // Try to download the updates list diff --git a/src/main.cpp b/src/main.cpp index c1919bc0..59bb1566 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -186,7 +186,7 @@ void initConfiguration(const Options &options) config.setValue("sfxVolume", 100); config.setValue("musicVolume", 60); config.setValue("fpslimit", 0); - config.setValue("updatehost", "http://themanaworld.org/files"); + config.setValue("updatehost", "http://updates.themanaworld.org"); config.setValue("customcursor", 1); config.setValue("homeDir", homeDir); diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp index 173c59d2..473a706c 100644 --- a/src/net/buysellhandler.cpp +++ b/src/net/buysellhandler.cpp @@ -89,6 +89,7 @@ void BuySellHandler::handleMessage(MessageIn &msg) msg.readShort(); // length n_items = (msg.getLength() - 4) / 10; if (n_items > 0) { + sellDialog->setMoney(player_node->mMoney); sellDialog->reset(); sellDialog->setVisible(true); diff --git a/src/player.cpp b/src/player.cpp index 12f5f3d5..0acf8262 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -35,11 +35,10 @@ Player::Player(Uint16 id, Uint16 job, Map *map): Being(id, job, map) { - /* Load the weapon sprite. When there are more different weapons this - * should be moved to the setWeapon Method. - */ - mSprites[WEAPON_SPRITE] = - new AnimatedSprite("graphics/sprites/weapons.xml", 0); + // Load the weapon sprite. + // When there are more different weapons this should be moved to the + // setWeapon Method. + setWeapon(0); } Being::Type @@ -88,6 +87,35 @@ Player::setSex(Uint8 sex) } } + +void +Player::setWeapon(Uint16 weapon) +{ + if (weapon != mWeapon) + { + delete mSprites[WEAPON_SPRITE]; + mSprites[WEAPON_SPRITE] = NULL; + + switch (weapon) + { + case 0: + mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-fist.xml", 0); + break; + case 1: + mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-dagger.xml", 0); + break; + case 2: + mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-bow.xml", 0); + break; + case 3: + mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-scythe.xml", 0); + break; + } + } + Being::setWeapon(weapon); +} + + void Player::setHairColor(Uint16 color) { diff --git a/src/player.h b/src/player.h index 6ff4babe..3c061be6 100644 --- a/src/player.h +++ b/src/player.h @@ -58,6 +58,9 @@ class Player : public Being virtual void setVisibleEquipment(Uint8 slot, Uint8 id); + virtual void + setWeapon(Uint16 weapon); + private: /** * Resets all animations associated with this player. This is used to diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 23a73497..bb51d023 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -122,13 +122,9 @@ ResourceManager::get(const E_RESOURCE_TYPE &type, const std::string &idPath) return resIter->second; } - logger->log("ResourceManager::get(%s)", idPath.c_str()); - int fileSize; void *buffer = loadFile(idPath, fileSize); - if (!buffer) { - logger->log("Warning: resource doesn't exist!"); return NULL; } @@ -265,6 +261,10 @@ ResourceManager::loadFile(const std::string &fileName, int &fileSize) return NULL; } + // Log the real dir of the file + logger->log("Loaded %s/%s", PHYSFS_getRealDir(fileName.c_str()), + fileName.c_str()); + // Get the size of the file fileSize = PHYSFS_fileLength(file); -- cgit v1.2.3-60-g2f50 From 8da32105732949b4b0273c718d118bcfae70a1c9 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Mon, 11 Dec 2006 15:47:35 +0000 Subject: Merged 0.0 changes from revision 2825 to 2898 to trunk. --- ChangeLog | 292 +++++++++++++++++++++++- NEWS | 11 + data/CMakeLists.txt | 3 +- data/Makefile.am | 3 +- data/graphics/images/CMakeLists.txt | 1 + data/graphics/images/Makefile.am | 1 + data/graphics/images/error.png | Bin 0 -> 314 bytes src/CMakeLists.txt | 19 +- src/Makefile.am | 19 +- src/action.cpp | 66 ++++++ src/action.h | 61 +++++ src/animatedsprite.cpp | 430 +++++++++--------------------------- src/animatedsprite.h | 131 +++-------- src/animation.cpp | 127 +---------- src/animation.h | 97 ++------ src/base64.cpp | 63 +++--- src/base64.h | 11 +- src/being.cpp | 87 ++++---- src/being.h | 36 +-- src/beingmanager.cpp | 24 +- src/engine.cpp | 147 +----------- src/engine.h | 14 -- src/floor_item.cpp | 4 +- src/floor_item.h | 10 +- src/game.cpp | 94 ++++---- src/graphics.cpp | 3 + src/gui/buy.cpp | 4 +- src/gui/char_select.cpp | 51 +++-- src/gui/char_select.h | 11 +- src/gui/confirm_dialog.cpp | 1 + src/gui/confirm_dialog.h | 2 +- src/gui/debugwindow.cpp | 10 +- src/gui/gui.cpp | 152 +------------ src/gui/gui.h | 38 +--- src/gui/inventorywindow.cpp | 3 +- src/gui/item_amount.cpp | 3 +- src/gui/login.cpp | 1 + src/gui/ok_dialog.cpp | 1 + src/gui/ok_dialog.h | 2 +- src/gui/passwordfield.h | 4 +- src/gui/playerbox.cpp | 37 +--- src/gui/playerbox.h | 24 +- src/gui/popupmenu.cpp | 4 +- src/gui/register.cpp | 1 + src/gui/sell.cpp | 5 +- src/gui/serverdialog.cpp | 1 + src/gui/serverdialog.h | 2 +- src/gui/setup_joystick.cpp | 2 +- src/gui/shop.cpp | 6 +- src/gui/textfield.h | 1 - src/gui/trade.cpp | 36 +-- src/gui/updatewindow.cpp | 2 +- src/gui/viewport.cpp | 392 ++++++++++++++++++++++++++++++++ src/gui/viewport.h | 145 ++++++++++++ src/gui/window.cpp | 3 + src/gui/window.h | 3 +- src/gui/windowcontainer.h | 3 +- src/item.h | 4 +- src/localplayer.cpp | 36 ++- src/localplayer.h | 10 +- src/log.cpp | 23 +- src/main.cpp | 51 ++--- src/map.cpp | 53 +++-- src/map.h | 12 +- src/monster.cpp | 39 +++- src/monster.h | 2 + src/net/beinghandler.cpp | 83 ++++--- src/net/inventoryhandler.cpp | 2 +- src/net/npchandler.cpp | 10 +- src/net/playerhandler.cpp | 18 +- src/net/skillhandler.cpp | 4 +- src/npc.cpp | 17 +- src/npc.h | 8 +- src/openglgraphics.cpp | 3 + src/player.cpp | 109 +++++---- src/player.h | 18 +- src/resources/equipmentdb.cpp | 158 +++++++++++++ src/resources/equipmentdb.h | 52 +++++ src/resources/equipmentinfo.h | 52 +++++ src/resources/image.cpp | 10 +- src/resources/itemdb.cpp | 170 ++++++++++++++ src/resources/itemdb.h | 53 +++++ src/resources/iteminfo.h | 12 +- src/resources/itemmanager.cpp | 173 --------------- src/resources/itemmanager.h | 59 ----- src/resources/mapreader.cpp | 32 +-- src/resources/monsterdb.cpp | 151 +++++++++++++ src/resources/monsterdb.h | 45 ++++ src/resources/monsterinfo.cpp | 70 ++++++ src/resources/monsterinfo.h | 74 +++++++ src/resources/resourcemanager.cpp | 61 +++-- src/resources/resourcemanager.h | 17 +- src/resources/soundeffect.cpp | 19 +- src/resources/spritedef.cpp | 381 ++++++++++++++++++++++++++++++++ src/resources/spritedef.h | 158 +++++++++++++ src/resources/spriteset.h | 6 +- src/sound.cpp | 6 +- src/sound.h | 4 +- src/sprite.h | 2 +- src/utils/wingettimeofday.h | 111 ++++++++++ src/utils/xml.cpp | 54 +++++ src/utils/xml.h | 46 ++++ tmw.cbp | 102 +++++++-- 103 files changed, 3532 insertions(+), 1752 deletions(-) create mode 100644 data/graphics/images/error.png create mode 100644 src/action.cpp create mode 100644 src/action.h create mode 100644 src/gui/viewport.cpp create mode 100644 src/gui/viewport.h create mode 100644 src/resources/equipmentdb.cpp create mode 100644 src/resources/equipmentdb.h create mode 100644 src/resources/equipmentinfo.h create mode 100644 src/resources/itemdb.cpp create mode 100644 src/resources/itemdb.h delete mode 100644 src/resources/itemmanager.cpp delete mode 100644 src/resources/itemmanager.h create mode 100644 src/resources/monsterdb.cpp create mode 100644 src/resources/monsterdb.h create mode 100644 src/resources/monsterinfo.cpp create mode 100644 src/resources/monsterinfo.h create mode 100644 src/resources/spritedef.cpp create mode 100644 src/resources/spritedef.h create mode 100644 src/utils/wingettimeofday.h create mode 100644 src/utils/xml.cpp create mode 100644 src/utils/xml.h (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index 807de694..c67d6cd6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,16 +1,305 @@ +2006-12-09 Eugenio Favalli + + * data/graphics/sprites/npcs.png: Added pirate NPC. + +2006-12-09 Bjørn Lindeijer + + * src/sprite.h, src/gui/playerbox.h, src/gui/char_select.cpp, + src/gui/playerbox.cpp, src/gui/passwordfield.h,src/gui/char_select.h, + src/gui/textfield.h, src/main.cpp, src/being.cpp, src/player.h, + src/floor_item.h, src/being.h: Use new animation system in character + selection/creation. Shows equipment and allowed for some cleanup. Had + a bit of help from the patch by VictorSan. + +2006-12-08 Bjørn Lindeijer + + * src/base64.cpp, src/base64.h, src/resources/mapreader.cpp: + Downgraded to base64 codec from PHP 3 to resolve licensing issues. + +2006-12-06 Eugenio Favalli + + * The Mana World.dev, tmw.cbp: Updated project files. + +2006-12-06 Philipp Sehmisch + + * src/net/beinghandler.cpp: Fixed crashs when changing equipment. + * data/graphics/tiles/desert1.png, data/graphics/tiles/desert2.png: + More tiling related fixes at the cliffs. + +2006-12-06 Bjørn Lindeijer + + * src/gui/item_amount.cpp: Fixed visibility of item amount window. + +2006-12-05 Philipp Sehmisch + + * data/graphics/tiles/desert1.png: Improved the tiling behavior + of the cliffs (still not gridless but at least the edges fit + together in the most common situations) + +2006-12-04 Bjørn Lindeijer + + * src/game.cpp, src/engine.h, src/gui/windowcontainer.h, + src/gui/viewport.cpp, src/gui/gui.cpp, src/gui/gui.h, + src/gui/debugwindow.cpp, src/gui/inventorywindow.cpp, + src/gui/viewport.h, src/engine.cpp, src/CMakeLists.txt, + src/Makefile.am: Introduced a new class Viewport which combines the + drawing code from Engine with the (rather misplaced) input handling + from the Gui class. Also, it's a Container itself which should allow + for extending it to show Guichan widgets on map coordinates. + +2006-12-03 Bjørn Lindeijer + + * src/sound.cpp, src/monster.cpp, src/sound.h, + src/resources/soundeffect.cpp, src/resources/resourcemanager.cpp: + Don't try to play empty strings as sounds, and don't return a + SoundEffect instance when Mix_Chunk loading failed. + * src/beingmanager.cpp, src/npc.cpp, src/npc.h: Show NPC names. + * src/game.cpp, src/gui/char_server.cpp, src/gui/window.cpp, + src/gui/login.cpp, src/gui/char_select.cpp, src/gui/ok_dialog.cpp, + src/gui/confirm_dialog.cpp, src/gui/ok_dialog.h, src/gui/window.h, + src/gui/confirm_dialog.h, src/gui/register.cpp: Windows now default + to invisible, since this seems the most common case. + +2006-12-02 Philipp Sehmisch + + * data/graphics/sprites/chest-leather-female.png: A little correction + at the female leather shirt by mangamaniac. + +2006-12-01 Philipp Sehmisch + + * src/net/beinghandler.cpp, src/being.h, src/being.cpp, src/monster.h, + src/gui/gui.cpp: Visible equipment slot numbers are now converted by + the beinghandler from eAthena to our system. No more distinction + between monster attacking and player attacking between beinghandler + and the being classes. + * src/being.cpp, src/monster.cpp, src/being.h, src/monster.h: Moved + the monster specific action handling into the monster class. + * monster.cpp, mosterinfo.cpp, monsterinfo.h: Monsters now make sounds + when they attack, gett hurt or die. + * src/being.cpp: Delayed the damage numbers a bit to synchronize them + better with the hurt sounds. + * data/monsters.xml, data/sfx//bat-dying1.ogg, data/sfx/bat-hit1.ogg, + data/sfx/bow_shoot_1.ogg, data/sfx/fire-goblin-hit1.ogg, + data/sfx/fire-goblin-hit2.ogg, data/sfx/fire-goblin-miss1.ogg, + data/sfx/fist-swish.ogg, data/sfx/flower-hit1.ogg, + data/sfx/flower-hit2.ogg, data/sfx/flower-miss1.ogg, + data/sfx/fluffy-hit1.ogg, data/sfx/fluffy-hit2.ogg, + data/sfx/fluffy-hit3.ogg, data/sfx/fluffy-hurt1.ogg, + data/sfx/fluffy-miss1.ogg, data/sfx/knife-hit1.ogg, + data/sfx/knife-miss1.ogg, data/sfx/levelup.ogg, + data/sfx/scorpion-hit1.ogg, data/sfx/scorpion-hit2.ogg, + data/sfx/scorpion-hit3.ogg, data/sfx/scorpion-hit4.ogg, + data/sfx/scorpion-miss1.ogg, data/sfx/short-sword-hit1.ogg, + data/sfx/short-sword-miss1.ogg, data/sfx/shroom-hit1.ogg, + data/sfx/slime-hit1.ogg, data/sfx/Makefile.AM, + data/sfx/CMakeLists.txt: Added a lot of sound effects by Cosmostrator. + +2006-11-30 Bjørn Lindeijer + + * data/maps/Makefile.am: Fixed small trailing slash issue. + * src/player.cpp: Optimized setSex and setWeapon by first loading the + new sprite and then deleting the old one (prevents potentially + unnecessary reload). + * src/net/beinghandler.cpp: Optimized handling of player walk + messages, by first setting the gender right and then setting the + equipment. Gets rid of reload of complete equipment in the case of + female. + +2006-11-30 Eugenio Favalli + + * The Mana World.dev, tmw.cbp: Updated project files. + +2006-11-29 Bjørn Lindeijer + + * src/monster.cpp: Small fix to resource path. + +2006-11-29 Philipp Sehmisch + + * src/resources/equipment.h: Made getSprite return a constant + reference. + * src/resources/monsterdb.cpp, src/resources/monsterdb.h, + src/resources/monsterinfo.cpp, src/resources/monsterinfo.h, + src/Makefile.AM, src/CMakeLists.txt, src/main.cpp: + Added the MonsterDB namespace that reads the monsters.xml + and maps monster IDs to names, sprite definitions and sound effects. + * src/monster.cpp: Get sprite definition filenames from MonsterDB. + * src/engine.cpp: Show monster name when targeting a monster. + * data/monsters.xml, data/graphics/sprites/Makefile.AM, + data/graphics/sprites/CMakeLists.txt, data/graphics/sprites/monster*: + Renamed all monster sprites to more associative names (whew, we got to + train some monkeys for tasks like that). + +2006-11-27 Bjørn Lindeijer + + * tmw.cbp: Updated Code::Blocks project file. + +2006-11-27 Philipp Sehmisch + + * src/log.cpp, src/util/wingettimeofday.h: Added implementation of + gettimeofday() for windows machines. + +2006-11-26 Bjørn Lindeijer + + * src/log.cpp: Higher precision log timestamps. + * src/graphics.cpp, src/gui/gui.cpp, src/openglgraphics.cpp, + src/main.cpp, src/resources/equipmentdb.cpp, + src/resources/resourcemanager.cpp: Added some additional log + statements. + * src/resources/itemdb.cpp: Removed usage of READ_PROP in favour of + XML::getProperty and updated log statements. + * src/resources/image.cpp: Added support for loading TGA images. + +2006-11-26 Björn Steinbrink + + * src/resources/resourcemanager.cpp: Remove unnecessary check for + file existance, loading will just fail with the correct error message. + +2006-11-26 Bjørn Lindeijer + + * src/game.cpp, src/being.cpp, src/net/beinghandler.cpp, src/being.h: + Made Being::mDirection protected, forcing the use of setDirection. + * src/npc.cpp, src/player.cpp, src/animatedsprite.h, src/monster.cpp, + src/resources/resourcemanager.h: Defaulted variant argument to 0 since + this is the most common situation. + * src/resources/spritedef.cpp, src/resources/spritedef.h: Some + refactoring, splitting up the loading into several methods, in + preparation of adding support for including other sprites. + * src/main.cpp: ItemDB needs to be unloaded before deleting the + resource manager instance, since ItemInfo refers to an Image. + +2006-11-26 Philipp Sehmisch + + * src/being.cpp, src/being.h, src/engine.cpp, src/main.cpp, + src/player.cpp, src/player.h, src/resources/equipmentdb.h, + src/resources/equipmentdb.cpp, src/resources/equipmentinfo.h, + src/resources/itemdb.cpp, src/resources/itemdb.h, + data/graphics/images/error.png, data/graphics/sprites/error.xml: + Added the EquipmentDB namespace that reads the equipment.xml, maps + equipment IDs to sprite definition files and thus allows gender + specific equipment sprites. + * data/graphics/sprites/chest-leather-female.png, + data/graphics/sprites/chest-leather-male.png, + data/graphics/sprites/chest-leather-female.xml, + data/graphics/sprites/chest-leather-male.xml, + data/equipment.xml: Added and defined male and female leather shirt as + proof of concept of the gender specific equipment. + * data/graphics/images/Makefile.am, data/graphics/sprites/Makefile.am, + data/Makefile.am, src/Makefile.am, + data/graphics/images/CMakeLists.txt, + data/graphics/sprites/CMakeLists.txt, data/CMakeLists.txt, + src/CMakeLists.txt: Updated Makefiles and CMake Lists. + +2006-11-24 Philipp Sehmisch + + * src/engine.cpp, src/floor_item.cpp, src/item.h, src/main.cpp, + src/gui/buy.cpp, src/gui/popupmenu.cpp, src/gui/sell.cpp, + src/gui/shop.cpp, src/net/inventoryhandler.cpp, + src/resources/itemdb.cpp, src/resources/itemdb.h, + src/resources/iteminfo.h, src/resources/itemmanager.cpp, + src/resources/itemmanager.h: Refactored the Itemmanager class to an + ItemDB namespace. + +2006-11-23 Eugenio Favalli + + * The Mana World.dev, tmw.cbp: Updated project files. + +2006-11-19 Bjørn Lindeijer + + * src/gui/setup_joystick.cpp: Fixed joystick option to show enabled + when the joystick is enabled. + * src/localplayer.cpp, src/game.cpp, src/action.h, src/action.cpp, + src/player.cpp, src/animatedsprite.h, src/being.cpp, src/animation.h, + src/monster.cpp, src/CMakeLists.txt, src/player.h, + src/animatedsprite.cpp, src/localplayer.h, src/animation.cpp, + src/Makefile.am, src/being.h, src/resources/resourcemanager.cpp, + src/resources/spritedef.cpp, src/resources/resourcemanager.h, + src/resources/spriteset.h, src/resources/spritedef.cpp: Separated + sprite definition from playback. + 2006-11-17 Björn Steinbrink * data/graphics/sprites/CMakeLists.txt: Fixed some filenames. +2006-11-17 Wai Ling Tsang + + * src/gui/gui.cpp: Added mouse following ability/feature under + logic(). + * src/gui/gui.h: Added mouseMotion(), mouseRelease() and private + variables for mouse following. + +2006-11-15 Philipp Sehmisch + + * data/graphics/tiles/Woodland_village.png, + data/graphics/tiles/Woodland_village_x2.png, + data/graphics/tiles/Woodland_x2.png, + data/graphics/tiles/Makefile.AM, + data/graphics/tiles/CMakeList.txt, + data/maps/new_9-1.tmx.gz, data/maps/new_14-1.tmx.gz, + data/maps/new_15-1.tmx.gz, data/maps/new_16-1.tmx.gz, + data/maps/new_17-1.tmx.gz, data/maps/new_18-1.tmx.gz, + data/maps/new_19-1.tmx.gz, data/maps/CMakeList.txt, + data/maps/Makefile.AM: + Added woodland village outdoor tileset and maps. Modified gates on + the nearby maps. + +2006-11-15 Bjørn Lindeijer + + * src/animatedsprite.h, src/CMakeLists.txt, src/animatedsprite.cpp, + src/utils/xml.cpp, src/utils/xml.h, src/Makefile.am, + src/resources/mapreader.cpp: Separated getProperty method to an XML + utility namespace. + +2006-11-15 Eugenio Favalli + + * The Mana World.dev, tmw.cbp: Updated project files. + * The Mana World.dev, tmw.cbp: Fixed dynamic linking of libcurl. + +2006-11-14 Bjørn Lindeijer + + * src/action.h, src/action.cpp, src/animation.h, src/CMakeLists.txt, + src/animatedsprite.cpp, src/animation.cpp, src/Makefile.am: Separated + Action class to its own module. + * src/action.h, src/action.cpp, src/animatedsprite.h, src/animation.h, + src/animatedsprite.cpp, src/animation.cpp: Resolve Image* of animation + phase at load time instead of storing just the spriteset index and + looking it up later (checking validity should still be added). Also + calculate animation length during loading instead of summing it up + each time it is requested. + +2006-11-12 Bjørn Lindeijer + + * src/map.cpp, src/map.h: Made pathfinding algorithm cope better with + beings blocking the road. This is done by allowing walking over other + beings, but at an additional cost so that it is preferable to walk + around them. + * src/game.cpp: Worked around a Guichan exception thrown for mice with + many buttons (patch by Roel van Dijk). + 2006-11-11 Björn Steinbrink * src/Makefile.am: Fixed autotools configuration. +2006-11-09 Eugenio Favalli + + * src/main.cpp, src/net/network.cpp, src/net/network.h, + The Mana World.dev, tmw.cbp: Fixed a conflict with Windows headers and + updated project files. + 2006-11-05 Eugenio Favalli * The Mana World.dev, tmw.cbp: Updated project files. Warning: Dev-Cpp will now build objects in the source folder. +2006-11-05 Bjørn Lindeijer + + * src/gui/trade.cpp: Fixed money field to no longer hide below the + bottom of the window. + * src/CMakeLists.txt: Added shoplistbox.h/cpp files. + * src/gui/updatewindow.cpp: Fixed percentage indicator of update + window. + * src/main.cpp, src/net/beinghandler.cpp, src/net/skillhandler.cpp, + src/net/network.cpp: Changed some printf statements to log statements. + 2006-11-05 Bjørn Lindeijer * data/graphics/images/login_wallpaper.png: Reverted to standard @@ -37,6 +326,7 @@ precisions about the total money in it. * src/gui/shop.h, src/gui/shop.cpp, src/gui/sell.cpp: Fixes to Sell dialog. + * src/gui/sell.cpp: Fixes the money value after selling something. 2006-11-05 Björn Steinbrink @@ -78,7 +368,7 @@ 2006-11-04 Philipp Sehmisch - * data/maps/new_17-1.tmx.gz, + * data/maps/new_17-1.tmx.gz, data/graphics/images/minimap_new_17-1.png, data/graphics/images/Makefile.am, data/graphics/images/CMakeLists.txt: diff --git a/NEWS b/NEWS index 4633c39b..f3b586f8 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,14 @@ +0.0.22 (...) +- Added support for female-specific equipment graphics +- Added support for monster sounds +- Changed to new update host (http://updates.themanaworld.org) +- Worked around a Guichan exception thrown for mice with many buttons +- Changed mouse walk to keep following mouse while button is held down +- Extended font support for Ã¥ and Ã…. +- Fixed joystick setting not to show disabled when it's actually enabled +- Fixed money field to no longer hide below the bottom of the window +- Fixed pathfinding to allow walking through beings when they block your path + 0.0.21.1 (30 October 2006) - Reload wallpaper after loading updates - Added support for gzip compressed map layer data diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 36259082..e60bfe30 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -7,7 +7,8 @@ ADD_SUBDIRECTORY(maps) ADD_SUBDIRECTORY(sfx) SET(FILES + equipment.xml items.xml ) -INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}) +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}) \ No newline at end of file diff --git a/data/Makefile.am b/data/Makefile.am index 7d16a1fc..ed080d08 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -4,7 +4,8 @@ SUBDIRS = graphics help icons maps sfx tmwdatadir = $(pkgdatadir)/data tmwdata_DATA = \ + equipment.xml \ items.xml EXTRA_DIST = \ - $(tmwdata_DATA) + $(tmwdata_DATA) \ No newline at end of file diff --git a/data/graphics/images/CMakeLists.txt b/data/graphics/images/CMakeLists.txt index 53f8b3a7..f02cd2ea 100644 --- a/data/graphics/images/CMakeLists.txt +++ b/data/graphics/images/CMakeLists.txt @@ -1,6 +1,7 @@ ADD_SUBDIRECTORY(ambient) SET(FILES + error.png login_wallpaper.png minimap_new_1-1.png minimap_new_14-1.png diff --git a/data/graphics/images/Makefile.am b/data/graphics/images/Makefile.am index cc71b18a..00d9ed7e 100644 --- a/data/graphics/images/Makefile.am +++ b/data/graphics/images/Makefile.am @@ -3,6 +3,7 @@ SUBDIRS = ambient imagesdir = $(pkgdatadir)/data/graphics/images images_DATA = \ + error.png \ login_wallpaper.png \ minimap_new_1-1.png \ minimap_new_2-1.png \ diff --git a/data/graphics/images/error.png b/data/graphics/images/error.png new file mode 100644 index 00000000..6fd7c1a8 Binary files /dev/null and b/data/graphics/images/error.png differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4fd8d880..e0b93382 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -155,6 +155,8 @@ SET(SRCS gui/vbox.h gui/windowcontainer.cpp gui/windowcontainer.h + gui/viewport.cpp + gui/viewport.h gui/window.cpp gui/window.h gui/widgets/dropdown.cpp @@ -216,17 +218,24 @@ SET(SRCS resources/ambientoverlay.h resources/buddylist.cpp resources/buddylist.h + resources/equipmentdb.cpp + resources/equipmentdb.h + resources/equipmentinfo.h resources/image.cpp resources/image.h resources/imagewriter.cpp resources/imagewriter.h resources/iteminfo.cpp + resources/itemdb.cpp + resources/itemdb.h resources/iteminfo.h - resources/itemmanager.cpp - resources/itemmanager.h resources/mapreader.cpp resources/mapreader.h resources/music.cpp + resources/monsterdb.h + resources/monsterdb.cpp + resources/monsterinfo.h + resources/monsterinfo.cpp resources/music.h resources/openglsdlimageloader.cpp resources/openglsdlimageloader.h @@ -239,9 +248,15 @@ SET(SRCS resources/soundeffect.cpp resources/soundeffect.h resources/spriteset.cpp + resources/spritedef.h + resources/spritedef.cpp resources/spriteset.h utils/dtor.h utils/tostring.h + utils/xml.cpp + utils/xml.h + action.cpp + action.h animatedsprite.cpp animatedsprite.h animation.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 23c57922..1628df18 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -110,6 +110,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ gui/textfield.h \ gui/trade.cpp \ gui/trade.h \ + gui/viewport.cpp \ + gui/viewport.h \ gui/window.cpp \ gui/window.h \ gui/windowcontainer.cpp \ @@ -179,16 +181,23 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ net/gameserver/player.h \ resources/ambientoverlay.cpp \ resources/ambientoverlay.h \ + resources/equipmentdb.cpp \ + resources/equipmentdb.h \ + resources/equipmentinfo.h \ resources/image.cpp \ resources/image.h \ resources/imagewriter.cpp \ resources/imagewriter.h \ + resources/itemdb.cpp \ + resources/itemdb.h \ resources/iteminfo.h \ resources/iteminfo.cpp \ - resources/itemmanager.cpp \ - resources/itemmanager.h \ resources/mapreader.cpp \ resources/mapreader.h \ + resources/monsterdb.h \ + resources/monsterdb.cpp \ + resources/monsterinfo.h \ + resources/monsterinfo.cpp \ resources/music.h \ resources/music.cpp \ resources/openglsdlimageloader.h \ @@ -201,12 +210,18 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ resources/sdlimageloader.cpp \ resources/soundeffect.h \ resources/soundeffect.cpp \ + resources/spritedef.h \ + resources/spritedef.cpp \ resources/spriteset.h \ resources/spriteset.cpp \ resources/buddylist.h \ resources/buddylist.cpp \ utils/dtor.h \ utils/tostring.h \ + utils/xml.cpp \ + utils/xml.h \ + action.cpp \ + action.h \ animatedsprite.cpp \ animatedsprite.h \ animation.cpp \ diff --git a/src/action.cpp b/src/action.cpp new file mode 100644 index 00000000..148ea105 --- /dev/null +++ b/src/action.cpp @@ -0,0 +1,66 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "action.h" + +#include + +#include "animation.h" +#include "utils/dtor.h" + + +Action::Action() +{ +} + +Action::~Action() +{ + std::for_each(mAnimations.begin(), mAnimations.end(), + make_dtor(mAnimations)); +} + +Animation* +Action::getAnimation(int direction) const +{ + Animations::const_iterator i = mAnimations.find(direction); + + // When the direction isn't defined, try the default + if (i == mAnimations.end()) + { + i = mAnimations.find(0); + } + + return (i == mAnimations.end()) ? NULL : i->second; +} + +void +Action::setAnimation(int direction, Animation *animation) +{ + // Set first direction as default direction + if (mAnimations.empty()) + { + mAnimations[0] = animation; + } + + mAnimations[direction] = animation; +} diff --git a/src/action.h b/src/action.h new file mode 100644 index 00000000..8d5e8d11 --- /dev/null +++ b/src/action.h @@ -0,0 +1,61 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_ACTION_H +#define _TMW_ACTION_H + +#include + +#include + +class Animation; + +/** + * An action consists of several animations, one for each direction. + */ +class Action +{ + public: + /** + * Constructor. + */ + Action(); + + /** + * Destructor. + */ + ~Action(); + + void + setAnimation(int direction, Animation *animation); + + Animation* + getAnimation(int direction) const; + + protected: + typedef std::map Animations; + typedef Animations::iterator AnimationIterator; + Animations mAnimations; +}; + +#endif diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index 3815f04a..46369c80 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -24,401 +24,177 @@ #include "animatedsprite.h" #include "animation.h" +#include "action.h" #include "graphics.h" #include "log.h" #include "resources/resourcemanager.h" #include "resources/spriteset.h" +#include "resources/image.h" -AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): - mAction(NULL), +#include "utils/xml.h" + +#include + +AnimatedSprite::AnimatedSprite(SpriteDef *sprite): mDirection(DIRECTION_DOWN), mLastTime(0), - mSpeed(1.0f), - mAnimationFile(animationFile) + mFrameIndex(0), + mFrameTime(0), + mSprite(sprite), + mAction(0), + mAnimation(0), + mFrame(0) { - int size; - ResourceManager *resman = ResourceManager::getInstance(); - char *data = (char*)resman->loadFile(animationFile.c_str(), size); - - if (!data) { - logger->error("Animation: Could not find " + animationFile + "!"); - } - - xmlDocPtr doc = xmlParseMemory(data, size); - free(data); - - if (!doc) { - logger->error( - "Animation: Error while parsing animation definition file!"); - } - - xmlNodePtr node = xmlDocGetRootElement(doc); - if (!node || !xmlStrEqual(node->name, BAD_CAST "sprite")) { - logger->error( - "Animation: this is not a valid animation definition file!"); - } - - // Get the variant - int variant_num = getProperty(node, "variants", 0); - int variant_offset = getProperty(node, "variant_offset", 0); - - if (variant_num > 0 && variant < variant_num ) { - variant_offset *= variant; - } else { - variant_offset = 0; - } + assert(mSprite); - for (node = node->xmlChildrenNode; node != NULL; node = node->next) - { - if (xmlStrEqual(node->name, BAD_CAST "imageset")) - { - int width = getProperty(node, "width", 0); - int height = getProperty(node, "height", 0); - std::string name = getProperty(node, "name", ""); - std::string imageSrc = getProperty(node, "src", ""); - - Spriteset *spriteset = - resman->getSpriteset(imageSrc, width, height); - - if (!spriteset) { - logger->error("Couldn't load spriteset!"); - } - - mSpritesets[name] = spriteset; - } - // get action - else if (xmlStrEqual(node->name, BAD_CAST "action")) - { - std::string actionName = getProperty(node, "name", ""); - std::string imageset = getProperty(node, "imageset", ""); - - if (mSpritesets.find(imageset) == mSpritesets.end()) { - logger->log("Warning: imageset \"%s\" not defined in %s", - imageset.c_str(), - animationFile.c_str()); - - // skip loading animations - continue; - } - - - SpriteAction actionType = makeSpriteAction(actionName); - if (actionType == ACTION_INVALID) - { - logger->log("Warning: Unknown action \"%s\" defined in %s", - actionName.c_str(), - animationFile.c_str()); - continue; - } - Action *action = new Action(); - action->setSpriteset(mSpritesets[imageset]); - mActions[actionType] = action; - - // When first action set it as default direction - if (mActions.empty()) - { - mActions[ACTION_DEFAULT] = action; - } - - - // get animations - for (xmlNodePtr animationNode = node->xmlChildrenNode; - animationNode != NULL; - animationNode = animationNode->next) - { - // We're only interested in animations - if (!xmlStrEqual(animationNode->name, BAD_CAST "animation")) - continue; - - std::string directionName = getProperty(animationNode, "direction", ""); - - SpriteDirection directionType = makeSpriteDirection(directionName); - if (directionType == DIRECTION_INVALID) - { - logger->log("Warning: Unknown direction \"%s\" defined for action %s in %s", - directionName.c_str(), - actionName.c_str(), - animationFile.c_str()); - continue; - } - - Animation *animation = new Animation(); - action->setAnimation(directionType, animation); - - // Get animation phases - for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode; - phaseNode != NULL; - phaseNode = phaseNode->next) - { - int delay = getProperty(phaseNode, "delay", 0); - - if (xmlStrEqual(phaseNode->name, BAD_CAST "frame")) - { - int index = getProperty(phaseNode, "index", -1); - int offsetX = getProperty(phaseNode, "offsetX", 0); - int offsetY = getProperty(phaseNode, "offsetY", 0); - - offsetY -= mSpritesets[imageset]->getHeight() - 32; - offsetX -= mSpritesets[imageset]->getWidth() / 2 - 16; - animation->addPhase(index + variant_offset, delay, - offsetX, offsetY); - } - else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence")) - { - int start = getProperty(phaseNode, "start", 0); - int end = getProperty(phaseNode, "end", 0); - int offsetY = -mSpritesets[imageset]->getHeight() + 32; - int offsetX = -mSpritesets[imageset]->getWidth() / 2 + 16; - while (end >= start) - { - animation->addPhase(start + variant_offset, - delay, offsetX, offsetY); - start++; - } - } - else if (xmlStrEqual(phaseNode->name, BAD_CAST "end")) - { - animation->addTerminator(); - }; - } // for phaseNode - } // for animationNode - } // if "" else if "" - } // for node - - // Complete missing actions - substituteAction(ACTION_STAND, ACTION_DEFAULT); - substituteAction(ACTION_WALK, ACTION_STAND); - substituteAction(ACTION_WALK, ACTION_RUN); - substituteAction(ACTION_ATTACK, ACTION_STAND); - substituteAction(ACTION_ATTACK_SWING, ACTION_ATTACK); - substituteAction(ACTION_ATTACK_STAB, ACTION_ATTACK_SWING); - substituteAction(ACTION_ATTACK_BOW, ACTION_ATTACK_STAB); - substituteAction(ACTION_ATTACK_THROW, ACTION_ATTACK_SWING); - substituteAction(ACTION_CAST_MAGIC, ACTION_ATTACK_SWING); - substituteAction(ACTION_USE_ITEM, ACTION_CAST_MAGIC); - substituteAction(ACTION_SIT, ACTION_STAND); - substituteAction(ACTION_SLEEP, ACTION_SIT); - substituteAction(ACTION_HURT, ACTION_STAND); - substituteAction(ACTION_DEAD, ACTION_HURT); + // Take possession of the sprite + mSprite->incRef(); // Play the stand animation by default play(ACTION_STAND); - - xmlFreeDoc(doc); -} - -int -AnimatedSprite::getProperty(xmlNodePtr node, const char* name, int def) -{ - int &ret = def; - - xmlChar *prop = xmlGetProp(node, BAD_CAST name); - if (prop) { - ret = atoi((char*)prop); - xmlFree(prop); - } - - return ret; } -std::string -AnimatedSprite::getProperty(xmlNodePtr node, const char* name, - const std::string& def) +AnimatedSprite::AnimatedSprite(const std::string& filename, int variant): + mDirection(DIRECTION_DOWN), + mLastTime(0), + mFrameIndex(0), + mFrameTime(0), + mAnimation(0), + mFrame(0) { - xmlChar *prop = xmlGetProp(node, BAD_CAST name); - if (prop) { - std::string val = (char*)prop; - xmlFree(prop); - return val; - } - - return def; -} + ResourceManager *resman = ResourceManager::getInstance(); + mSprite = resman->getSprite(filename, variant); + assert(mSprite); -void -AnimatedSprite::substituteAction(SpriteAction complete, - SpriteAction with) -{ - if (mActions.find(complete) == mActions.end()) - { - ActionIterator i = mActions.find(with); - if (i != mActions.end()) { - mActions[complete] = i->second; - } - } + // Play the stand animation by default + play(ACTION_STAND); } AnimatedSprite::~AnimatedSprite() { - for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i) - { - i->second->decRef(); - } - mSpritesets.clear(); + mSprite->decRef(); } void AnimatedSprite::reset() { - // Reset all defined actions (because of aliases some will be resetted - // multiple times, but this doesn't matter) - for (ActionIterator i = mActions.begin(); i != mActions.end(); ++i) - { - if (i->second) - { - i->second->reset(); - } - } + mFrameIndex = 0; + mFrameTime = 0; + mLastTime = 0; } void -AnimatedSprite::play(SpriteAction action) +AnimatedSprite::play(SpriteAction spriteAction) { - ActionIterator i = mActions.find(action); - - if (i == mActions.end()) + Action *action = mSprite->getAction(spriteAction); + if (!action) { - //logger->log("Warning: no action %u defined for \"%s\"!", - // action, mAnimationFile.c_str()); - mAction = NULL; return; } - if (mAction != i->second) + mAction = action; + Animation *animation = mAction->getAnimation(mDirection); + + if (animation && animation != mAnimation && animation->getLength() > 0) { - mAction = i->second; - //mAction->reset(); + mAnimation = animation; + mFrame = mAnimation->getFrame(0); + + reset(); } } void AnimatedSprite::update(int time) { - bool notFinished = true; // Avoid freaking out at first frame or when tick_time overflows if (time < mLastTime || mLastTime == 0) + { mLastTime = time; + } // If not enough time has passed yet, do nothing - if (time > mLastTime && mAction) + if (time <= mLastTime || !mAnimation) { - Animation *animation = mAction->getAnimation(mDirection); - if (animation != NULL) { - notFinished = animation->update((unsigned int)(time - mLastTime));} - mLastTime = time; + return; } - if (!notFinished) + unsigned int dt = time - mLastTime; + mLastTime = time; + + if (!updateCurrentAnimation(dt)) { + // Animation finished, reset to default play(ACTION_STAND); } } bool -AnimatedSprite::draw(Graphics* graphics, Sint32 posX, Sint32 posY) const +AnimatedSprite::updateCurrentAnimation(unsigned int time) { - if (!mAction) + if (!mFrame || Animation::isTerminator(*mFrame)) + { return false; + } - Animation *animation = mAction->getAnimation(mDirection); - if (animation == NULL) return false; + mFrameTime += time; - int phase = animation->getCurrentPhase(); - if (phase < 0) - return false; + while (mFrameTime > mFrame->delay && mFrame->delay > 0) + { + mFrameTime -= mFrame->delay; + mFrameIndex++; - Spriteset *spriteset = mAction->getSpriteset(); - Image *image = spriteset->get(phase); - Sint32 offsetX = animation->getOffsetX(); - Sint32 offsetY = animation->getOffsetY(); - return graphics->drawImage(image, posX + offsetX, posY + offsetY); -} + if (mFrameIndex == mAnimation->getLength()) + { + mFrameIndex = 0; + } -int -AnimatedSprite::getWidth() const -{ - return mAction ? mAction->getSpriteset()->getWidth() : 0; -} + mFrame = mAnimation->getFrame(mFrameIndex); -int -AnimatedSprite::getHeight() const -{ - return mAction ? mAction->getSpriteset()->getHeight() : 0; + if (Animation::isTerminator(*mFrame)) + { + mAnimation = 0; + mFrame = 0; + return false; + } + } + + return true; } -SpriteAction -AnimatedSprite::makeSpriteAction(const std::string& action) +bool +AnimatedSprite::draw(Graphics* graphics, int posX, int posY) const { - if (action == "" || action == "default") { - return ACTION_DEFAULT; - } - if (action == "stand") { - return ACTION_STAND; - } - else if (action == "walk") { - return ACTION_WALK; - } - else if (action == "run") { - return ACTION_RUN; - } - else if (action == "attack") { - return ACTION_ATTACK; - } - else if (action == "attack_swing") { - return ACTION_ATTACK_SWING; - } - else if (action == "attack_stab") { - return ACTION_ATTACK_STAB; - } - else if (action == "attack_bow") { - return ACTION_ATTACK_BOW; - } - else if (action == "attack_throw") { - return ACTION_ATTACK_THROW; - } - else if (action == "cast_magic") { - return ACTION_CAST_MAGIC; - } - else if (action == "use_item") { - return ACTION_USE_ITEM; - } - else if (action == "sit") { - return ACTION_SIT; - } - else if (action == "sleep") { - return ACTION_SLEEP; - } - else if (action == "hurt") { - return ACTION_HURT; - } - else if (action == "dead") { - return ACTION_DEAD; - } - else { - return ACTION_INVALID; + if (!mFrame || !mFrame->image) + { + return false; } + + return graphics->drawImage(mFrame->image, + posX + mFrame->offsetX, + posY + mFrame->offsetY); } -SpriteDirection -AnimatedSprite::makeSpriteDirection(const std::string& direction) +void +AnimatedSprite::setDirection(SpriteDirection direction) { - if (direction == "" || direction == "default") { - return DIRECTION_DEFAULT; - } - else if (direction == "up") { - return DIRECTION_UP; - } - else if (direction == "left") { - return DIRECTION_LEFT; - } - else if (direction == "right") { - return DIRECTION_RIGHT; - } - else if (direction == "down") { - return DIRECTION_DOWN; + if (mDirection != direction) + { + mDirection = direction; + + if (!mAction) + { + return; + } + + Animation *animation = mAction->getAnimation(mDirection); + + if (animation && animation != mAnimation && animation->getLength() > 0) + { + mAnimation = animation; + mFrame = mAnimation->getFrame(0); + reset(); + } } - else { - return DIRECTION_INVALID; - }; } diff --git a/src/animatedsprite.h b/src/animatedsprite.h index bda612ab..4e485f14 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -24,56 +24,34 @@ #ifndef _TMW_ANIMATEDSPRITE_H #define _TMW_ANIMATEDSPRITE_H +#include "resources/spritedef.h" + #include #include -#include - -#include -class Action; class Graphics; -class Spriteset; - -enum SpriteAction -{ - ACTION_DEFAULT = 0, - ACTION_STAND, - ACTION_WALK, - ACTION_RUN, - ACTION_ATTACK, - ACTION_ATTACK_SWING, - ACTION_ATTACK_STAB, - ACTION_ATTACK_BOW, - ACTION_ATTACK_THROW, - ACTION_CAST_MAGIC, - ACTION_USE_ITEM, - ACTION_SIT, - ACTION_SLEEP, - ACTION_HURT, - ACTION_DEAD, - ACTION_INVALID -}; - -enum SpriteDirection -{ - DIRECTION_DEFAULT = 0, - DIRECTION_DOWN, - DIRECTION_UP, - DIRECTION_LEFT, - DIRECTION_RIGHT, - DIRECTION_INVALID -}; +struct AnimationPhase; /** - * Defines a class to load an animation. + * Animates a sprite by adding playback state. */ class AnimatedSprite { public: /** * Constructor. + * @param sprite the sprite to animate */ - AnimatedSprite(const std::string& animationFile, int variant); + AnimatedSprite(SpriteDef *sprite); + + /** + * A convenience constructor, which will request the sprite to animate + * from the resource manager. + * + * @param filename the file of the sprite to animate + * @param variant the sprite variant + */ + AnimatedSprite(const std::string& filename, int variant = 0); /** * Destructor. @@ -81,8 +59,7 @@ class AnimatedSprite ~AnimatedSprite(); /** - * Resets the animated sprite. This is used to synchronize several - * animated sprites. + * Resets the animated sprite. */ void reset(); @@ -97,84 +74,36 @@ class AnimatedSprite * Inform the animation of the passed time so that it can output the * correct animation phase. */ - void update(int time); + void + update(int time); /** * Draw the current animation phase at the coordinates given in screen * pixels. */ bool - draw(Graphics* graphics, Sint32 posX, Sint32 posY) const; - - /** - * gets the width in pixels of the current animation phase. - */ - int - getWidth() const; - - /** - * gets the height in pixels of the current animation phase. - */ - int - getHeight() const; + draw(Graphics* graphics, int posX, int posY) const; /** * Sets the direction. */ void - setDirection(SpriteDirection direction) - { - mDirection = direction; - } + setDirection(SpriteDirection direction); private: - /** - * When there are no animations defined for the action "complete", its - * animations become a copy of those of the action "with". - */ - void - substituteAction(SpriteAction complete, SpriteAction with); - - /** - * Gets an integer property from an xmlNodePtr. - * - * TODO: Same function is present in MapReader. Should probably be - * TODO: shared in a static utility class. - */ - static int - getProperty(xmlNodePtr node, const char *name, int def); - - /** - * Gets a string property from an xmlNodePtr. - */ - static std::string - getProperty(xmlNodePtr node, const char *name, const std::string &def); - - /** - * Converts a string into a SpriteAction enum. - */ - static SpriteAction - makeSpriteAction(const std::string &action); - - /** - * Converts a string into a SpriteDirection enum. - */ - static SpriteDirection - makeSpriteDirection(const std::string &direction); - + bool + updateCurrentAnimation(unsigned int dt); - typedef std::map Spritesets; - typedef Spritesets::iterator SpritesetIterator; + SpriteDirection mDirection; /**< The sprite direction. */ + int mLastTime; /**< The last time update was called. */ - typedef std::map Actions; - typedef Actions::iterator ActionIterator; + unsigned int mFrameIndex; /**< The index of the current frame. */ + unsigned int mFrameTime; /**< The time since start of frame. */ - Spritesets mSpritesets; - Actions mActions; - Action *mAction; - SpriteDirection mDirection; - int mLastTime; - float mSpeed; + SpriteDef *mSprite; /**< The sprite definition. */ + Action *mAction; /**< The currently active action. */ + Animation *mAnimation; /**< The currently active animation. */ + AnimationPhase *mFrame; /**< The currently active frame. */ std::string mAnimationFile; }; diff --git a/src/animation.cpp b/src/animation.cpp index 98a4abb8..67fdae11 100644 --- a/src/animation.cpp +++ b/src/animation.cpp @@ -27,138 +27,29 @@ #include "utils/dtor.h" -Animation::Animation() +Animation::Animation(): + mDuration(0) { - reset(); } void -Animation::reset() +Animation::addPhase(Image *image, unsigned int delay, int offsetX, int offsetY) { - mTime = 0; - iCurrentPhase = mAnimationPhases.begin(); -} - - -bool -Animation::update(unsigned int time) -{ - mTime += time; - if (mAnimationPhases.empty()) - return true; - if (isTerminator(*iCurrentPhase)) - return false; - - unsigned int delay = iCurrentPhase->delay; - - while (mTime > delay) - { - if (!delay) - return true; - mTime -= delay; - iCurrentPhase++; - if (iCurrentPhase == mAnimationPhases.end()) - { - iCurrentPhase = mAnimationPhases.begin(); - } - if (isTerminator(*iCurrentPhase)) - return false; - delay = iCurrentPhase->delay; - } - return true; -} - - -int -Animation::getCurrentPhase() const -{ - return mAnimationPhases.empty() ? -1 : iCurrentPhase->image; -} - - -void -Animation::addPhase(int image, unsigned int delay, int offsetX, int offsetY) -{ - //add new phase to animation list - AnimationPhase newPhase = { image, delay, offsetX, offsetY}; + // Add new phase to animation list + AnimationPhase newPhase = { image, delay, offsetX, offsetY }; mAnimationPhases.push_back(newPhase); - //reset animation circle - iCurrentPhase = mAnimationPhases.begin(); + mDuration += delay; } void Animation::addTerminator() { - AnimationPhase terminator = { -1, 0, 0, 0}; - mAnimationPhases.push_back(terminator); - iCurrentPhase = mAnimationPhases.begin(); + addPhase(NULL, 0, 0, 0); } bool -Animation::isTerminator(AnimationPhase candidate) -{ - return (candidate.image < 0); -} - -int -Animation::getLength() -{ - if (mAnimationPhases.empty()) - return 0; - - std::list::iterator i; - int length = 0; - for (i = mAnimationPhases.begin(); i != mAnimationPhases.end(); i++) - { - length += i->delay; - } - return length; -} - -Action::Action(): - mSpriteset(NULL) -{ -} - -Action::~Action() -{ - std::for_each(mAnimations.begin(), mAnimations.end(), make_dtor(mAnimations)); - mAnimations.clear(); -} - -Animation* -Action::getAnimation(int direction) const -{ - Animations::const_iterator i = mAnimations.find(direction); - - // When the direction isn't defined, try the default - if (i == mAnimations.end()) - { - i = mAnimations.find(0); - } - - return (i == mAnimations.end()) ? NULL : i->second; -} - -void -Action::setAnimation(int direction, Animation *animation) -{ - // Set first direction as default direction - if (mAnimations.empty()) - { - mAnimations[0] = animation; - } - - mAnimations[direction] = animation; -} - -void -Action::reset() +Animation::isTerminator(const AnimationPhase candidate) { - for (AnimationIterator i = mAnimations.begin(); - i != mAnimations.end(); ++i) - { - i->second->reset(); - } + return (candidate.image == NULL); } diff --git a/src/animation.h b/src/animation.h index 605d8cb1..85e950d7 100644 --- a/src/animation.h +++ b/src/animation.h @@ -24,8 +24,7 @@ #ifndef _TMW_ANIMATION_H #define _TMW_ANIMATION_H -#include -#include +#include #include @@ -34,10 +33,12 @@ class Spriteset; /** * A single frame in an animation, with a delay and an offset. + * + * TODO: Rename this struct to Frame */ struct AnimationPhase { - int image; + Image *image; unsigned int delay; int offsetX; int offsetY; @@ -55,106 +56,46 @@ class Animation */ Animation(); - /** - * Restarts the animation from the first frame. - */ - void - reset(); - /** * Appends a new animation at the end of the sequence */ void - addPhase(int image, unsigned int delay, int offsetX, int offsetY); + addPhase(Image *image, unsigned int delay, int offsetX, int offsetY); /** * Appends an animation terminator that states that the animation - * should not loop + * should not loop. */ void addTerminator(); /** - * Updates animation phase. - * true indicates a still running animation while false indicates a - * finished animation + * Returns the frame at the specified index. */ - bool - update(unsigned int time); - - int - getCurrentPhase() const; + AnimationPhase* + getFrame(int index) { return &(mAnimationPhases[index]); } /** - * Returns the x offset of the current frame. + * Returns the length of this animation in frames. */ - int - getOffsetX() const { return iCurrentPhase->offsetX; }; + unsigned int + getLength() const { return mAnimationPhases.size(); } /** - * Returns the y offset of the current frame. + * Returns the duration of this animation. */ int - getOffsetY() const { return iCurrentPhase->offsetY; }; + getDuration() const { return mDuration; } /** - * Returns the length of this animation. + * Determines whether the given animation frame is a terminator. */ - int - getLength(); - - protected: - static bool isTerminator(AnimationPhase); - std::list mAnimationPhases; - std::list::iterator iCurrentPhase; - unsigned int mTime; -}; - -/** - * An action consists of several animations, one for each direction. - */ -class Action -{ - public: - /** - * Constructor. - */ - Action(); - - /** - * Destructor. - */ - ~Action(); - - /** - * Sets the spriteset used by this action. - */ - void - setSpriteset(Spriteset *spriteset) { mSpriteset = spriteset; } - - /** - * Returns the spriteset used by this action. - */ - Spriteset* - getSpriteset() const { return mSpriteset; } - - void - setAnimation(int direction, Animation *animation); - - /** - * Resets all animations associated with this action. - */ - void - reset(); - - Animation* - getAnimation(int direction) const; + static bool + isTerminator(const AnimationPhase phase); protected: - Spriteset *mSpriteset; - typedef std::map Animations; - typedef Animations::iterator AnimationIterator; - Animations mAnimations; + std::vector mAnimationPhases; + int mDuration; }; #endif diff --git a/src/base64.cpp b/src/base64.cpp index 6d503a53..9a8f6356 100644 --- a/src/base64.cpp +++ b/src/base64.cpp @@ -1,16 +1,27 @@ /* +----------------------------------------------------------------------+ - | PHP version 4.0 | + | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | + | Copyright (c) 1997-2000 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ - | This source file is subject to version 2.02 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available at through the world-wide-web at | - | http://www.php.net/license/2_02.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) 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. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | 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 both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | +----------------------------------------------------------------------+ | Author: Jim Winstead (jimw@php.net) | +----------------------------------------------------------------------+ @@ -32,8 +43,8 @@ static char base64_table[] = }; static char base64_pad = '='; -unsigned char *php_base64_encode(const unsigned char *str, int length, int *ret_length) { - const unsigned char *current = str; +unsigned char *php3_base64_encode(const unsigned char *string, int length, int *ret_length) { + const unsigned char *current = string; int i = 0; unsigned char *result = (unsigned char *)malloc(((length + 3 - length % 3) * 4 / 3 + 1) * sizeof(char)); @@ -69,27 +80,13 @@ unsigned char *php_base64_encode(const unsigned char *str, int length, int *ret_ } /* as above, but backwards. :) */ -unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_length) { - const unsigned char *current = str; +unsigned char *php3_base64_decode(const unsigned char *string, int length, int *ret_length) { + const unsigned char *current = string; int ch, i = 0, j = 0, k; - /* this sucks for threaded environments */ - static short reverse_table[256]; - static int table_built; - unsigned char *result; - - if (++table_built == 1) { - char *chp; - for(ch = 0; ch < 256; ch++) { - chp = strchr(base64_table, ch); - if(chp) { - reverse_table[ch] = chp - base64_table; - } else { - reverse_table[ch] = -1; - } - } - } + char *chp; + + unsigned char *result = (unsigned char *)malloc(length + 1); - result = (unsigned char *)malloc(length + 1); if (result == NULL) { return NULL; } @@ -107,8 +104,9 @@ unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_ if (ch == ' ') ch = '+'; - ch = reverse_table[ch]; - if (ch < 0) continue; + chp = strchr(base64_table, ch); + if (chp == NULL) continue; + ch = chp - base64_table; switch(i % 4) { case 0: @@ -149,4 +147,3 @@ unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_ result[k] = '\0'; return result; } - diff --git a/src/base64.h b/src/base64.h index 5b275c45..ff20ac53 100644 --- a/src/base64.h +++ b/src/base64.h @@ -31,14 +31,7 @@ #ifndef _TMW_BASE64_H #define _TMW_BASE64_H -extern unsigned char *php_base64_encode(const unsigned char *, int, int *); -extern unsigned char *php_base64_decode(const unsigned char *, int, int *); +extern unsigned char *php3_base64_encode(const unsigned char *, int, int *); +extern unsigned char *php3_base64_decode(const unsigned char *, int, int *); #endif /* _TMW_BASE64_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/src/being.cpp b/src/being.cpp index 50a2dc35..9cd0af0d 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -49,7 +49,7 @@ PATH_NODE::PATH_NODE(Uint16 iX, Uint16 iY): Being::Being(Uint16 id, Uint16 job, Map *map): mJob(job), - mX(0), mY(0), mDirection(DOWN), + mX(0), mY(0), mAction(STAND), mWalkTime(0), mEmotion(0), mEmotionTime(0), @@ -60,12 +60,15 @@ Being::Being(Uint16 id, Uint16 job, Map *map): mWeapon(0), mWalkSpeed(150), mSpeedModifier(1024), + mDirection(DOWN), mMap(NULL), mHairStyle(0), mHairColor(0), mSpeechTime(0), mDamageTime(0), mShowSpeech(false), mShowDamage(false), - mSprites(VECTOREND_SPRITE, NULL) + mPx(0), mPy(0), + mSprites(VECTOREND_SPRITE, NULL), + mEquipmentSpriteIDs(VECTOREND_SPRITE, 0) { setMap(map); } @@ -110,9 +113,7 @@ void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY) p1 = mMap->findPath(srcX / 32, srcY / 32, dstX / 32, dstY / 32); if (p1.empty()) { - // No path? Better teleport. - mX = dstX; - mY = dstY; + // No path, but don't teleport since it could be user input. setPath(p1); return; } @@ -189,9 +190,8 @@ void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY) if (bestRating < 0) { - // Unable to reach the path? Better teleport. - mX = srcX; - mY = srcY; + // Unable to reach the path? Still, don't teleport since it could be + // user input instead of server command. setPath(p1); delete[] p1_dist; return; @@ -263,8 +263,9 @@ Being::setHairStyle(Uint16 style) } void -Being::setVisibleEquipment(Uint8 slot, Uint8 id) +Being::setVisibleEquipment(Uint8 slot, int id) { + mEquipmentSpriteIDs[slot] = id; } void @@ -304,7 +305,7 @@ Being::setMap(Map *map) void Being::setAction(Uint8 action) { - SpriteAction currentAction = ACTION_STAND; + SpriteAction currentAction = ACTION_INVALID; switch (action) { case WALK: @@ -314,37 +315,21 @@ Being::setAction(Uint8 action) currentAction = ACTION_SIT; break; case ATTACK: - if (getType() == MONSTER) + switch (getWeapon()) { - currentAction = ACTION_DEAD; + case 3: + currentAction = ACTION_ATTACK; + break; + case 2: + currentAction = ACTION_ATTACK_BOW; + break; + case 1: + currentAction = ACTION_ATTACK_STAB; + break; + case 0: + currentAction = ACTION_ATTACK; + break; } - else { - switch (getWeapon()) - { - case 3: - currentAction = ACTION_ATTACK; - break; - case 2: - currentAction = ACTION_ATTACK_BOW; - break; - case 1: - currentAction = ACTION_ATTACK_STAB; - break; - case 0: - currentAction = ACTION_ATTACK; - break; - } - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i]) - { - mSprites[i]->reset(); - } - } - }; - break; - case MONSTER_ATTACK: - currentAction = ACTION_ATTACK; for (int i = 0; i < VECTOREND_SPRITE; i++) { if (mSprites[i]) @@ -353,25 +338,33 @@ Being::setAction(Uint8 action) } } break; + case HURT: + //currentAction = ACTION_HURT; // Buggy: makes the player stop + // attacking and unable to attack + // again until he moves + break; case DEAD: currentAction = ACTION_DEAD; break; - default: + case STAND: currentAction = ACTION_STAND; break; } - for (int i = 0; i < VECTOREND_SPRITE; i++) + if (currentAction != ACTION_INVALID) { - if (mSprites[i]) + for (int i = 0; i < VECTOREND_SPRITE; i++) { - mSprites[i]->play(currentAction); + if (mSprites[i]) + { + mSprites[i]->play(currentAction); + } } + mAction = action; } - - mAction = action; } + void Being::setDirection(Uint8 direction) { @@ -487,7 +480,7 @@ Being::logic() } void -Being::draw(Graphics *graphics, int offsetX, int offsetY) +Being::draw(Graphics *graphics, int offsetX, int offsetY) const { int px = mPx + offsetX; int py = mPy + offsetY; @@ -528,7 +521,7 @@ Being::drawSpeech(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) } // Draw damage above this being - if (mShowDamage) + if (mShowDamage && get_elapsed_time(mDamageTime) > 250) { // Selecting the right color if (mDamage == "miss") diff --git a/src/being.h b/src/being.h index 2804b20b..c95cd191 100644 --- a/src/being.h +++ b/src/being.h @@ -68,14 +68,12 @@ class Being : public Sprite }; enum Action { - STAND = 0, - WALK = 1, - MONSTER_ATTACK = 5, - SIT = 7, - DEAD = 8, - ATTACK = 9, - MONSTER_DEAD = 9, - HIT = 17 + STAND, + WALK, + ATTACK, + SIT, + DEAD, + HURT }; enum Sprite { @@ -101,7 +99,6 @@ class Being : public Sprite std::string mName; /**< Name of character */ Uint16 mJob; /**< Job (player job, npc, monster, ) */ Uint16 mX, mY; /**< Pixel coordinates (tile center) */ - Uint8 mDirection; /**< Facing direction */ Uint8 mAction; /**< Action the being is performing */ Uint16 mWalkTime; Uint8 mEmotion; /**< Currently showing emotion */ @@ -199,7 +196,7 @@ class Being : public Sprite * Sets visible equipments for this being. */ virtual void - setVisibleEquipment(Uint8 slot, Uint8 id); + setVisibleEquipment(Uint8 slot, int id); /** * Sets the sex for this being. @@ -216,7 +213,7 @@ class Being : public Sprite /** * Makes this being take the next step of his path. */ - void + virtual void nextStep(); /** @@ -301,7 +298,13 @@ class Being : public Sprite /** * Sets the current action. */ - void setAction(Uint8 action); + virtual void + setAction(Uint8 action); + + /** + * Returns the current direction. + */ + Uint8 getDirection() const { return mDirection; } /** * Sets the current direction. @@ -314,7 +317,7 @@ class Being : public Sprite * @see Sprite::draw(Graphics, int, int) */ virtual void - draw(Graphics *graphics, Sint32 offsetX, Sint32 offsetY); + draw(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) const; /** * Returns the pixel X coordinate. @@ -343,7 +346,6 @@ class Being : public Sprite getYOffset() const { return getOffset(mStepY); } std::auto_ptr mEquipment; - int mVisibleEquipment[6]; /**< Visible equipments */ protected: /** @@ -363,6 +365,7 @@ class Being : public Sprite Uint16 mWeapon; /**< Weapon picture id */ Uint16 mWalkSpeed; /**< Walking speed */ Uint16 mSpeedModifier; /**< Modifier to keep course on sync (1024 = normal speed) */ + Uint8 mDirection; /**< Facing direction */ Map *mMap; /**< Map on which this being resides */ SpriteIterator mSpriteIterator; @@ -376,11 +379,14 @@ class Being : public Sprite Sint32 mPx, mPy; /**< Pixel coordinates */ std::vector mSprites; + std::vector mEquipmentSpriteIDs; private: + int + getOffset(int step) const; + Sint16 mStepX, mStepY; Uint16 mStepTime; - int getOffset(int) const; }; #endif diff --git a/src/beingmanager.cpp b/src/beingmanager.cpp index 923283b5..14b4ea7e 100644 --- a/src/beingmanager.cpp +++ b/src/beingmanager.cpp @@ -38,7 +38,7 @@ class FindBeingFunctor Uint16 other_y = y + ((being->getType() == Being::NPC) ? 1 : 0); return (being->mX / 32 == x && (being->mY / 32 == y || being->mY / 32 == other_y) && - being->mAction != Being::MONSTER_DEAD && + being->mAction != Being::DEAD && (type == Being::UNKNOWN || being->getType() == type)); } @@ -64,14 +64,7 @@ Being* BeingManager::createBeing(Uint16 id, Uint16 job) Being *being; if (job < 10) - { being = new Player(id, job, mMap); - // XXX Convert for new server - /* - MessageOut outMsg(0x0094); - outMsg.writeLong(id); - */ - } else if (job >= 100 & job < 200) being = new NPC(id, job, mMap); else if (job >= 1000 && job < 1200) @@ -79,6 +72,17 @@ Being* BeingManager::createBeing(Uint16 id, Uint16 job) else being = new Being(id, job, mMap); + // Player or NPC + if (job < 200) + { + // XXX Convert for new server + /* + MessageOut outMsg(mNetwork); + outMsg.writeInt16(0x0094); + outMsg.writeInt32(id);//readLong(2)); + */ + } + mBeings.push_back(being); return being; @@ -127,7 +131,8 @@ void BeingManager::logic() being->logic(); - /*if (being->mAction == Being::MONSTER_DEAD && being->mFrame >= 20) + /* + if (being->mAction == Being::DEAD && being->mFrame >= 20) { delete being; i = mBeings.erase(i); @@ -168,7 +173,6 @@ Being* BeingManager::findNearestLivingBeing(Uint16 x, Uint16 y, int maxdist, if ((being->getType() == type || type == Being::UNKNOWN) && (d < dist || closestBeing == NULL) // it is closer && being->mAction != Being::DEAD // no dead beings - && being->mAction != Being::MONSTER_DEAD ) { dist = d; diff --git a/src/engine.cpp b/src/engine.cpp index 231313c4..30f0097e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -39,9 +39,10 @@ #include "gui/gui.h" #include "gui/minimap.h" +#include "gui/viewport.h" -#include "resources/itemmanager.h" #include "resources/mapreader.h" +#include "resources/monsterdb.h" #include "resources/resourcemanager.h" #include "resources/spriteset.h" @@ -51,16 +52,12 @@ extern Minimap *minimap; char itemCurrenyQ[10] = "0"; -int camera_x, camera_y; - -ItemManager *itemDb; /**< Item database object */ Spriteset *emotionset; Spriteset *npcset; std::vector weaponset; Engine::Engine(): - mShowDebugPath(false), mCurrentMap(NULL) { // Load the sprite sets @@ -82,9 +79,6 @@ Engine::Engine(): if (!npcset) logger->error("Unable to load NPC spriteset!"); if (!emotionset) logger->error("Unable to load emotions spriteset!"); - - // Initialize item manager - itemDb = new ItemManager(); } Engine::~Engine() @@ -96,8 +90,6 @@ Engine::~Engine() std::for_each(weaponset.begin(), weaponset.end(), std::mem_fun(&Spriteset::decRef)); weaponset.clear(); - - delete itemDb; } void Engine::changeMap(const std::string &mapPath) @@ -125,6 +117,7 @@ void Engine::changeMap(const std::string &mapPath) } minimap->setMapImage(mapImage); beingManager->setMap(newMap); + viewport->setMap(newMap); // Start playing new music file when necessary std::string oldMusic = ""; @@ -152,139 +145,5 @@ void Engine::logic() void Engine::draw(Graphics *graphics) { - int midTileX = graphics->getWidth() / 2; - int midTileY = graphics->getHeight() / 2; - static int lastTick = tick_time; - - int player_x = player_node->mX - midTileX + player_node->getXOffset(); - int player_y = player_node->mY - midTileY + player_node->getYOffset(); - - scrollLaziness = (int)config.getValue("ScrollLaziness", 32); - scrollRadius = (int)config.getValue("ScrollRadius", 32); - - if (scrollLaziness < 1) - scrollLaziness = 1; //avoids division by zero - - //apply lazy scrolling - int nbTicks = get_elapsed_time(lastTick) / 10; - lastTick += nbTicks; - for (; nbTicks > 0; --nbTicks) - { - if (player_x > view_x + scrollRadius) - { - view_x += (player_x - view_x - scrollRadius) / scrollLaziness; - } - if (player_x < view_x - scrollRadius) - { - view_x += (player_x - view_x + scrollRadius) / scrollLaziness; - } - if (player_y > view_y + scrollRadius) - { - view_y += (player_y - view_y - scrollRadius) / scrollLaziness; - } - if (player_y < view_y - scrollRadius) - { - view_y += (player_y - view_y + scrollRadius) / scrollLaziness; - } - } - - //auto center when player is off screen - if ( player_x - view_x > graphics->getWidth() / 2 - || view_x - player_x > graphics->getWidth() / 2 - || view_y - player_y > graphics->getHeight() / 2 - || player_y - view_y > graphics->getHeight() / 2 - ) - { - view_x = player_x; - view_y = player_y; - }; - - if (mCurrentMap) { - if (view_x < 0) { - view_x = 0; - } - if (view_y < 0) { - view_y = 0; - } - if (view_x > mCurrentMap->getWidth() * 32 - midTileX) { - view_x = mCurrentMap->getWidth() * 32 - midTileX; - } - if (view_y > mCurrentMap->getHeight() * 32 - midTileY) { - view_y = mCurrentMap->getHeight() * 32 - midTileY; - } - } - - camera_x = (int)view_x; - camera_y = (int)view_y; - - // Draw tiles and sprites - if (mCurrentMap != NULL) - { - mCurrentMap->draw(graphics, camera_x, camera_y, 0); - mCurrentMap->draw(graphics, camera_x, camera_y, 1); - mCurrentMap->draw(graphics, camera_x, camera_y, 2); - mCurrentMap->drawOverlay( graphics, - view_x, - view_y, - (int)config.getValue("OverlayDetail", 2) - ); - } - else - { - // When no map is loaded, draw a replacement background - graphics->setColor(gcn::Color(128, 128, 128)); - graphics->fillRectangle(gcn::Rectangle(0, 0, - graphics->getWidth(), graphics->getHeight())); - } - - // Find a path from the player to the mouse, and draw it. This is for debug - // purposes. - if (mShowDebugPath && mCurrentMap != NULL) - { - // Get the current mouse position - int mouseX, mouseY; - SDL_GetMouseState(&mouseX, &mouseY); - - int mouseTileX = (mouseX + camera_x) / 32; - int mouseTileY = (mouseY + camera_y) / 32; - - Path debugPath = mCurrentMap->findPath( - player_node->mX / 32, player_node->mY / 32, - mouseTileX, mouseTileY); - - graphics->setColor(gcn::Color(255, 0, 0)); - for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++) - { - int squareX = i->x * 32 - camera_x + 12; - int squareY = i->y * 32 - camera_y + 12; - - graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8)); - graphics->drawText( - toString(mCurrentMap->getMetaTile(i->x, i->y)->Gcost), - squareX + 4, squareY + 12, gcn::Graphics::CENTER); - } - } - - // Draw player nickname, speech, and emotion sprite as needed - Beings &beings = beingManager->getAll(); - for (BeingIterator i = beings.begin(); i != beings.end(); i++) - { - (*i)->drawSpeech(graphics, -camera_x, -camera_y); - (*i)->drawName(graphics, -camera_x, -camera_y); - (*i)->drawEmotion(graphics, -camera_x, -camera_y); - } - - // Draw target marker if needed - Being *target; - if ((target = player_node->getTarget())) - { - graphics->setFont(speechFont); - graphics->setColor(gcn::Color(255, 255, 255)); - int dy = (target->getType() == Being::PLAYER) ? 90 : 52; - - graphics->drawText("[TARGET]", target->getPixelX() - camera_x + 15, - target->getPixelY() - camera_y - dy, gcn::Graphics::CENTER); - } - gui->draw(); } diff --git a/src/engine.h b/src/engine.h index e8ef7e33..62e82a49 100644 --- a/src/engine.h +++ b/src/engine.h @@ -26,8 +26,6 @@ #include -extern int camera_x, camera_y; - class Graphics; class Map; @@ -67,20 +65,8 @@ class Engine */ void draw(Graphics *graphics); - /** - * Toggles whether the path debug graphics are shown - */ - void toggleDebugPath() { mShowDebugPath = !mShowDebugPath; }; - private: - bool mShowDebugPath; - Map *mCurrentMap; - - int scrollRadius; - int scrollLaziness; - float view_x; // current viewpoint in pixels - float view_y; // current viewpoint in pixels }; extern Engine *engine; diff --git a/src/floor_item.cpp b/src/floor_item.cpp index 9a179a21..f33f7eb4 100644 --- a/src/floor_item.cpp +++ b/src/floor_item.cpp @@ -25,7 +25,7 @@ #include "map.h" -#include "resources/itemmanager.h" +#include "resources/itemdb.h" #include "resources/iteminfo.h" #include "resources/spriteset.h" @@ -42,7 +42,7 @@ FloorItem::FloorItem(unsigned int id, mMap(map) { // Retrieve item image from item info - mImage = itemDb->getItemInfo(itemId).getImage(); + mImage = ItemDB::get(itemId).getImage(); // Add ourselves to the map mSpriteIterator = mMap->addSprite(this); diff --git a/src/floor_item.h b/src/floor_item.h index 386d0759..36f81585 100644 --- a/src/floor_item.h +++ b/src/floor_item.h @@ -53,25 +53,25 @@ class FloorItem : public Sprite * Returns instance id of this item. */ unsigned int - getId() { return mId; } + getId() const { return mId; } /** * Returns the item id. */ unsigned int - getItemId() { return mItemId; } + getItemId() const { return mItemId; } /** * Returns the x coordinate. */ unsigned short - getX() { return mX; } + getX() const { return mX; } /** * Returns the y coordinate. */ unsigned short - getY() { return mY; } + getY() const { return mY; } /** * Returns the pixel y coordinate. @@ -87,7 +87,7 @@ class FloorItem : public Sprite * @see Sprite::draw(Graphics, int, int) */ void - draw(Graphics *graphics, int offsetX, int offsetY) + draw(Graphics *graphics, int offsetX, int offsetY) const { graphics->drawImage(mImage, mX * 32 + offsetX, diff --git a/src/game.cpp b/src/game.cpp index 5052f2ce..15298ec6 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -29,6 +29,7 @@ #include #include +#include #include "beingmanager.h" #include "configuration.h" @@ -42,23 +43,25 @@ #include "gui/buy.h" #include "gui/buysell.h" -#include "gui/chargedialog.h" +//#include "gui/chargedialog.h" #include "gui/chat.h" #include "gui/confirm_dialog.h" +#include "gui/debugwindow.h" #include "gui/equipmentwindow.h" +#include "gui/gui.h" #include "gui/help.h" #include "gui/inventorywindow.h" +#include "gui/menuwindow.h" #include "gui/minimap.h" +#include "gui/ministatus.h" #include "gui/npclistdialog.h" #include "gui/npc_text.h" #include "gui/sell.h" #include "gui/setup.h" #include "gui/skill.h" -#include "gui/menuwindow.h" #include "gui/status.h" -#include "gui/ministatus.h" #include "gui/trade.h" -#include "gui/debugwindow.h" +#include "gui/viewport.h" #include "net/beinghandler.h" #include "net/buysellhandler.h" @@ -85,7 +88,7 @@ bool done = false; volatile int tick_time; volatile int fps = 0, frame = 0; Engine *engine = NULL; -Joystick *joystick; +Joystick *joystick = NULL; extern Window *weightNotice; extern Window *deathNotice; @@ -106,7 +109,7 @@ SkillDialog *skillDialog; Setup* setupWindow; Minimap *minimap; EquipmentWindow *equipmentWindow; -ChargeDialog *chargeDialog; +//ChargeDialog *chargeDialog; TradeWindow *tradeWindow; //BuddyWindow *buddyWindow; HelpWindow *helpWindow; @@ -182,47 +185,23 @@ void createGuiWindows() setupWindow = new Setup(); minimap = new Minimap(); equipmentWindow = new EquipmentWindow(player_node->mEquipment.get()); - chargeDialog = new ChargeDialog(); + //chargeDialog = new ChargeDialog(); tradeWindow = new TradeWindow; //buddyWindow = new BuddyWindow(); helpWindow = new HelpWindow(); debugWindow = new DebugWindow(); // Initialize window positions - int screenW = graphics->getWidth(); - int screenH = graphics->getHeight(); - - chargeDialog->setPosition( - screenW - 5 - chargeDialog->getWidth(), - screenH - chargeDialog->getHeight() - 15); + //chargeDialog->setPosition( + // graphics->getWidth() - 5 - chargeDialog->getWidth(), + // graphics->getHeight() - chargeDialog->getHeight() - 15); - /*buddyWindow->setPosition(10, - minimap->getHeight() + 30);*/ + //buddyWindow->setPosition(10, minimap->getHeight() + 30); // Set initial window visibility -// chatWindow->setSticky(true); -// miniStatusWindow->setSticky(true); -// menuWindow->setSticky(true); - chatWindow->setVisible(true); miniStatusWindow->setVisible(true); - statusWindow->setVisible(false); menuWindow->setVisible(true); - buyDialog->setVisible(false); - sellDialog->setVisible(false); - buySellDialog->setVisible(false); - inventoryWindow->setVisible(false); - npcTextDialog->setVisible(false); - npcListDialog->setVisible(false); - skillDialog->setVisible(false); - //newSkillWindow->setVisible(false); - setupWindow->setVisible(false); - equipmentWindow->setVisible(false); - chargeDialog->setVisible(false); - tradeWindow->setVisible(false); - //buddyWindow->setVisible(false); - helpWindow->setVisible(false); - debugWindow->setVisible(false); } /** @@ -244,7 +223,7 @@ void destroyGuiWindows() delete setupWindow; delete minimap; delete equipmentWindow; - delete chargeDialog; + //delete chargeDialog; //delete newSkillWindow; delete tradeWindow; //delete buddyWindow; @@ -511,13 +490,13 @@ void Game::handleInput() // If none below the player, try the tile in front of // the player if (!item) { - if (player_node->mDirection & Being::UP) + if (player_node->getDirection() & Being::UP) y--; - if (player_node->mDirection & Being::DOWN) + if (player_node->getDirection() & Being::DOWN) y++; - if (player_node->mDirection & Being::LEFT) + if (player_node->getDirection() & Being::LEFT) x--; - if (player_node->mDirection & Being::RIGHT) + if (player_node->getDirection() & Being::RIGHT) x++; item = floorItemManager->findByCoordinates(x, y); @@ -584,7 +563,7 @@ void Game::handleInput() case SDLK_f: // Find path to mouse (debug purpose) - engine->toggleDebugPath(); + viewport->toggleDebugPath(); used = true; break; } @@ -621,8 +600,17 @@ void Game::handleInput() } // Push input to GUI when not used - if (!used) { - guiInput->pushInput(event); + if (!used) + { + try + { + guiInput->pushInput(event); + } + catch (gcn::Exception e) + { + const char* err = e.getMessage().c_str(); + logger->log("Warning: guichan input exception: %s", err); + } } } // End while @@ -633,35 +621,35 @@ void Game::handleInput() !chatWindow->isFocused()) { Uint16 x = player_node->mX / 32, y = player_node->mY / 32; - unsigned char Direction = 0; + unsigned char direction = 0; // Translate pressed keys to movement and direction if (keys[SDLK_UP] || keys[SDLK_KP8] || keys[SDLK_KP7] || keys[SDLK_KP9] || joystick && joystick->isUp()) { - Direction |= Being::UP; + direction |= Being::UP; } else if (keys[SDLK_DOWN] || keys[SDLK_KP2] || keys[SDLK_KP1] || keys[SDLK_KP3] || joystick && joystick->isDown()) { - Direction |= Being::DOWN; + direction |= Being::DOWN; } if (keys[SDLK_LEFT] || keys[SDLK_KP4] || keys[SDLK_KP1] || keys[SDLK_KP7] || joystick && joystick->isLeft()) { - Direction |= Being::LEFT; + direction |= Being::LEFT; } else if (keys[SDLK_RIGHT] || keys[SDLK_KP6] || keys[SDLK_KP3] || keys[SDLK_KP9] || joystick && joystick->isRight()) { - Direction |= Being::RIGHT; + direction |= Being::RIGHT; } - player_node->walk(Direction); + player_node->walk(direction); // Attacking monsters if (keys[SDLK_LCTRL] || keys[SDLK_RCTRL] || @@ -675,13 +663,13 @@ void Game::handleInput() { Uint16 targetX = x, targetY = y; - if (player_node->mDirection & Being::UP) + if (player_node->getDirection() & Being::UP) targetY--; - if (player_node->mDirection & Being::DOWN) + if (player_node->getDirection() & Being::DOWN) targetY++; - if (player_node->mDirection & Being::LEFT) + if (player_node->getDirection() & Being::LEFT) targetX--; - if (player_node->mDirection & Being::RIGHT) + if (player_node->getDirection() & Being::RIGHT) targetX++; // Attack priority is: Monster, Player, auto target diff --git a/src/graphics.cpp b/src/graphics.cpp index 065c0a46..f007470a 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -39,6 +39,9 @@ Graphics::~Graphics() bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) { + logger->log("Setting video mode %dx%d %s", + w, h, fs ? "fullscreen" : "windowed"); + int displayFlags = SDL_ANYFORMAT; mFullscreen = fs; diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index b681b683..9fcf752b 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -32,7 +32,7 @@ #include "../npc.h" -#include "../resources/itemmanager.h" +#include "../resources/itemdb.h" #include "../utils/tostring.h" @@ -266,7 +266,7 @@ void BuyDialog::selectionChanged(const SelectionEvent &event) if (selectedItem > -1) { const ItemInfo &info = - itemDb->getItemInfo(mShopItems->at(selectedItem).id); + ItemDB::get(mShopItems->at(selectedItem).id); mItemDescLabel->setCaption("Description: " + info.getDescription()); mItemEffectLabel->setCaption("Effect: " + info.getEffect()); diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index d825db31..3cb42078 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -83,7 +83,7 @@ CharSelectDialog::CharSelectDialog(LockedArray *charInfo): mNameLabel = new gcn::Label("Name"); mLevelLabel = new gcn::Label("Level"); mMoneyLabel = new gcn::Label("Money"); - mPlayerBox = new PlayerBox(0); + mPlayerBox = new PlayerBox(); int w = 195; int h = 220; @@ -116,8 +116,9 @@ CharSelectDialog::CharSelectDialog(LockedArray *charInfo): add(mLevelLabel); add(mMoneyLabel); - mSelectButton->requestFocus(); setLocationRelativeTo(getParent()); + setVisible(true); + mSelectButton->requestFocus(); updatePlayerInfo(); } @@ -171,7 +172,8 @@ void CharSelectDialog::updatePlayerInfo() { LocalPlayer *pi = mCharInfo->getEntry(); - if (pi) { + if (pi) + { mNameLabel->setCaption(pi->getName()); mLevelLabel->setCaption("Lvl: " + toString(pi->mLevel)); mMoneyLabel->setCaption("Money: " + toString(pi->mMoney)); @@ -181,22 +183,17 @@ void CharSelectDialog::updatePlayerInfo() mDelCharButton->setEnabled(true); mSelectButton->setEnabled(true); } - mPlayerBox->mHairStyle = pi->getHairStyle(); - mPlayerBox->mHairColor = pi->getHairColor(); - mPlayerBox->mSex = pi->getSex(); - mPlayerBox->mShowPlayer = true; - } else { + } + else { mNameLabel->setCaption("Name"); mLevelLabel->setCaption("Level"); mMoneyLabel->setCaption("Money"); mNewCharButton->setEnabled(true); mDelCharButton->setEnabled(false); mSelectButton->setEnabled(false); - - mPlayerBox->mHairStyle = 0; - mPlayerBox->mHairColor = 0; - mPlayerBox->mShowPlayer = false; } + + mPlayerBox->setPlayer(pi); } void CharSelectDialog::attemptCharDelete() @@ -240,6 +237,10 @@ std::string CharSelectDialog::getName() CharCreateDialog::CharCreateDialog(Window *parent, int slot): Window("Create Character", true, parent), mSlot(slot) { + mPlayer = new Player(0, 0, NULL); + mPlayer->setHairStyle(rand() % NR_HAIR_STYLES + 1); + mPlayer->setHairColor(rand() % NR_HAIR_COLORS + 1); + mNameField = new TextField(""); mNameLabel = new gcn::Label("Name:"); mNextHairColorButton = new Button(">", "nextcolor", this); @@ -250,8 +251,7 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot): mHairStyleLabel = new gcn::Label("Hair Style:"); mCreateButton = new Button("Create", "create", this); mCancelButton = new Button("Cancel", "cancel", this); - mPlayerBox = new PlayerBox(0); - mPlayerBox->mShowPlayer = true; + mPlayerBox = new PlayerBox(mPlayer); mNameField->setEventId("create"); @@ -290,6 +290,12 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot): add(mCancelButton); setLocationRelativeTo(getParent()); + setVisible(true); +} + +CharCreateDialog::~CharCreateDialog() +{ + delete mPlayer; } void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget) @@ -299,7 +305,9 @@ void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget) // Attempt to create the character mCreateButton->setEnabled(false); Net::AccountServer::Account::createCharacter( - getName(), mPlayerBox->mHairStyle, mPlayerBox->mHairColor, + getName(), + mPlayer->getHairStyle(), + mPlayer->getHairColor(), 0, // gender 10, // STR 10, // AGI @@ -318,20 +326,19 @@ void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget) scheduleDelete(); } else if (eventId == "nextcolor") { - mPlayerBox->mHairColor++; + mPlayer->setHairColor(mPlayer->getHairColor() % NR_HAIR_COLORS + 1); } else if (eventId == "prevcolor") { - mPlayerBox->mHairColor += NR_HAIR_COLORS - 1; + int prevColor = mPlayer->getHairColor() + NR_HAIR_COLORS - 2; + mPlayer->setHairColor(prevColor % NR_HAIR_COLORS + 1); } else if (eventId == "nextstyle") { - mPlayerBox->mHairStyle++; + mPlayer->setHairStyle(mPlayer->getHairStyle() % NR_HAIR_STYLES + 1); } else if (eventId == "prevstyle") { - mPlayerBox->mHairStyle += NR_HAIR_STYLES - 1; + int prevStyle = mPlayer->getHairStyle() + NR_HAIR_STYLES - 2; + mPlayer->setHairStyle(prevStyle % NR_HAIR_STYLES + 1); } - - mPlayerBox->mHairColor %= NR_HAIR_COLORS; - mPlayerBox->mHairStyle %= NR_HAIR_STYLES; } std::string CharCreateDialog::getName() diff --git a/src/gui/char_select.h b/src/gui/char_select.h index 6d9d1a83..9d2d77da 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -31,6 +31,7 @@ #include +class Player; class LocalPlayer; class PlayerBox; @@ -48,7 +49,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener */ CharSelectDialog(LockedArray *charInfo); - void action(const std::string& eventId, gcn::Widget* widget); + void action(const std::string &eventId, gcn::Widget *widget); void updatePlayerInfo(); @@ -103,7 +104,12 @@ class CharCreateDialog : public Window, public gcn::ActionListener */ CharCreateDialog(Window *parent, int slot); - void action(const std::string& eventId, gcn::Widget* widget); + /** + * Destructor. + */ + ~CharCreateDialog(); + + void action(const std::string &eventId, gcn::Widget *widget); std::string getName(); @@ -119,6 +125,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener gcn::Button *mCreateButton; gcn::Button *mCancelButton; + Player *mPlayer; PlayerBox *mPlayerBox; int mSlot; diff --git a/src/gui/confirm_dialog.cpp b/src/gui/confirm_dialog.cpp index ed2f8680..5a70544f 100644 --- a/src/gui/confirm_dialog.cpp +++ b/src/gui/confirm_dialog.cpp @@ -61,6 +61,7 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg, setLocationRelativeTo(getParent()); getParent()->moveToTop(this); } + setVisible(true); yesButton->requestFocus(); } diff --git a/src/gui/confirm_dialog.h b/src/gui/confirm_dialog.h index 1c206b03..771ecc36 100644 --- a/src/gui/confirm_dialog.h +++ b/src/gui/confirm_dialog.h @@ -47,7 +47,7 @@ class ConfirmDialog : public Window, public gcn::ActionListener { /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const std::string &eventId, gcn::Widget *widget); }; #endif diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index d467d4d3..f8a4154e 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -72,15 +72,15 @@ DebugWindow::logic() // Get the current mouse position int mouseX, mouseY; SDL_GetMouseState(&mouseX, &mouseY); - int mouseTileX = mouseX / 32 + camera_x; - int mouseTileY = mouseY / 32 + camera_y; + //int mouseTileX = mouseX / 32 + camera_x; + //int mouseTileY = mouseY / 32 + camera_y; mFPSLabel->setCaption("[" + toString(fps) + " FPS"); mFPSLabel->adjustSize(); - mTileMouseLabel->setCaption("[Mouse: " + - toString(mouseTileX) + ", " + toString(mouseTileY) + "]"); - mTileMouseLabel->adjustSize(); + //mTileMouseLabel->setCaption("[Mouse: " + + // toString(mouseTileX) + ", " + toString(mouseTileY) + "]"); + //mTileMouseLabel->adjustSize(); Map *currentMap = engine->getCurrentMap(); if (currentMap != NULL) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 38b17781..fb7144a1 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -35,22 +35,14 @@ #endif #include "focushandler.h" -#include "popupmenu.h" #include "window.h" #include "windowcontainer.h" +#include "viewport.h" -#include "../being.h" -#include "../beingmanager.h" #include "../configlistener.h" #include "../configuration.h" -#include "../engine.h" -#include "../flooritemmanager.h" #include "../graphics.h" -#include "../localplayer.h" #include "../log.h" -#include "../main.h" -#include "../map.h" -#include "../npc.h" #include "../resources/image.h" #include "../resources/resourcemanager.h" @@ -61,7 +53,8 @@ // Guichan stuff Gui *gui; -gcn::SDLInput *guiInput; // GUI input +Viewport *viewport; /**< Viewport on the map. */ +gcn::SDLInput *guiInput; /**< GUI input. */ // Fonts used in showing hits gcn::Font *hitRedFont; @@ -91,9 +84,9 @@ class GuiConfigListener : public ConfigListener Gui::Gui(Graphics *graphics): mHostImageLoader(NULL), mMouseCursor(NULL), - mCustomCursor(false), - mPopupActive(false) + mCustomCursor(false) { + logger->log("Initializing GUI..."); // Set graphics setGraphics(graphics); @@ -122,7 +115,6 @@ Gui::Gui(Graphics *graphics): guiTop->setDimension(gcn::Rectangle(0, 0, graphics->getWidth(), graphics->getHeight())); guiTop->setOpaque(false); - guiTop->addMouseListener(this); Window::setWindowContainer(guiTop); setTop(guiTop); @@ -172,13 +164,15 @@ Gui::Gui(Graphics *graphics): mConfigListener = new GuiConfigListener(this); config.addListener("customcursor", mConfigListener); - mPopup = new PopupMenu(); + // Create the viewport + viewport = new Viewport(); + viewport->setDimension(gcn::Rectangle(0, 0, + graphics->getWidth(), graphics->getHeight())); + guiTop->add(viewport); } Gui::~Gui() { - delete mPopup; - config.removeListener("customcursor", mConfigListener); delete mConfigListener; @@ -193,6 +187,7 @@ Gui::~Gui() delete mGuiFont; delete speechFont; + delete viewport; delete mTop; delete mImageLoader; delete mHostImageLoader; @@ -230,113 +225,6 @@ Gui::draw() mGraphics->popClipArea(); } -void -Gui::mousePress(int mx, int my, int button) -{ - // Mouse pressed on window container (basically, the map) - - // Are we in-game yet? - if (state != STATE_GAME) - return; - - // Check if we are alive and kickin' - if (!player_node || player_node->mAction == Being::DEAD) - return; - - // Check if we are busy - if (current_npc) - return; - - int tilex = (mx + camera_x) / 32; - int tiley = (my + camera_y) / 32; - - // Right click might open a popup - if (button == gcn::MouseInput::RIGHT) - { - Being *being; - FloorItem *floorItem; - - if ((being = beingManager->findBeing(tilex, tiley)) && - being->getType() != Being::LOCALPLAYER) - { - showPopup(mx, my, being); - return; - } - else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley))) - { - showPopup(mx, my, floorItem); - return; - } - } - - // If a popup is active, just remove it - if (mPopupActive) - { - mPopup->setVisible(false); - mPopupActive = false; - return; - } - - // Left click can cause different actions - if (button == gcn::MouseInput::LEFT) - { - Being *being; - FloorItem *item; - - // Interact with some being - if ((being = beingManager->findBeing(tilex, tiley))) - { - switch (being->getType()) - { - case Being::NPC: - dynamic_cast(being)->talk(); - break; - - case Being::MONSTER: - case Being::PLAYER: - if (being->mAction == Being::MONSTER_DEAD) - break; - - player_node->attack(being, true); - break; - - default: - break; - } - } - // Pick up some item - else if ((item = floorItemManager->findByCoordinates(tilex, tiley))) - { - player_node->pickUp(item); - } - // Just walk around - else if (engine->getCurrentMap() && - engine->getCurrentMap()->getWalk(tilex, tiley)) - { - // XXX XXX XXX REALLY UGLY! - Uint8 *keys = SDL_GetKeyState(NULL); - if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT])) - { - player_node->setDestination(mx + camera_x, my + camera_y); - player_node->stopAttack(); - } - } - } - - if (button == gcn::MouseInput::MIDDLE) - { - // Find the being nearest to the clicked position - Being *target = beingManager->findNearestLivingBeing( - tilex, tiley, - 20, Being::MONSTER); - - if (target) - { - player_node->setTarget(target); - } - } -} - void Gui::setUseCustomCursor(bool customCursor) { @@ -369,21 +257,3 @@ Gui::setUseCustomCursor(bool customCursor) } } } - -void Gui::showPopup(int x, int y, Item *item) -{ - mPopup->showPopup(x, y, item); - mPopupActive = true; -} - -void Gui::showPopup(int x, int y, FloorItem *floorItem) -{ - mPopup->showPopup(x, y, floorItem); - mPopupActive = true; -} - -void Gui::showPopup(int x, int y, Being *being) -{ - mPopup->showPopup(x, y, being); - mPopupActive = true; -} diff --git a/src/gui/gui.h b/src/gui/gui.h index c4c47a88..caf27744 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -25,17 +25,13 @@ #define _TMW_GUI #include -#include #include "../guichanfwd.h" -class Being; -class FloorItem; class GuiConfigListener; class Graphics; class Image; -class Item; -class PopupMenu; +class Viewport; /** * \defgroup GUI Core GUI related classes (widgets) @@ -50,7 +46,7 @@ class PopupMenu; * * \ingroup GUI */ -class Gui : public gcn::Gui, public gcn::MouseListener +class Gui : public gcn::Gui { public: /** @@ -76,12 +72,6 @@ class Gui : public gcn::Gui, public gcn::MouseListener void draw(); - /** - * Handles mouse press on map. - */ - void - mousePress(int mx, int my, int button); - /** * Return game font */ @@ -94,37 +84,17 @@ class Gui : public gcn::Gui, public gcn::MouseListener void setUseCustomCursor(bool customCursor); - /** - * Shows a popup for an item - * TODO Find some way to get rid of Item here - */ - void showPopup(int x, int y, Item *item); - - /** - * Shows a popup for a floor item - * TODO Find some way to get rid of FloorItem here - */ - void showPopup(int x, int y, FloorItem *floorItem); - - /** - * Shows a popup for a being - * TODO Find some way to get rid of Being here - */ - void showPopup(int x, int y, Being *being); - private: GuiConfigListener *mConfigListener; gcn::ImageLoader *mHostImageLoader; /**< For loading images in GL */ gcn::ImageLoader *mImageLoader; /**< For loading images */ - gcn::Font *mGuiFont; /**< The global GUI font */ + gcn::Font *mGuiFont; /**< The global GUI font */ Image *mMouseCursor; /**< Mouse cursor image */ bool mCustomCursor; /**< Show custom cursor */ - - PopupMenu *mPopup; /**< Popup window */ - bool mPopupActive; }; extern Gui *gui; /**< The GUI system */ +extern Viewport *viewport; /**< The viewport */ extern gcn::SDLInput *guiInput; /**< GUI input */ /** diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 452b7c16..7f9ba3b9 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -34,6 +34,7 @@ #include "item_amount.h" #include "itemcontainer.h" #include "scrollarea.h" +#include "viewport.h" #include "../item.h" #include "../localplayer.h" @@ -169,7 +170,7 @@ void InventoryWindow::mouseClick(int x, int y, int button, int count) */ int mx = x + getX(); int my = y + getY(); - gui->showPopup(mx, my, item); + viewport->showPopup(mx, my, item); } } diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp index 30c899a8..5ebc0213 100644 --- a/src/gui/item_amount.cpp +++ b/src/gui/item_amount.cpp @@ -18,7 +18,7 @@ * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id $ + * $Id$ */ #include "item_amount.h" @@ -87,6 +87,7 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item): setContentSize(200, 80); setLocationRelativeTo(getParentWindow()); + setVisible(true); } void ItemAmountWindow::resetAmount() diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 1d9b6e1e..b8d4df2b 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -102,6 +102,7 @@ LoginDialog::LoginDialog(LoginData *loginData): add(mRegisterButton); setLocationRelativeTo(getParent()); + setVisible(true); if (mUserField->getText().empty()) { mUserField->requestFocus(); diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp index 906fd61f..4f9623d7 100644 --- a/src/gui/ok_dialog.cpp +++ b/src/gui/ok_dialog.cpp @@ -51,6 +51,7 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg, add(okButton); setLocationRelativeTo(getParent()); + setVisible(true); okButton->requestFocus(); } diff --git a/src/gui/ok_dialog.h b/src/gui/ok_dialog.h index 06f703cc..8ae08955 100644 --- a/src/gui/ok_dialog.h +++ b/src/gui/ok_dialog.h @@ -46,7 +46,7 @@ class OkDialog : public Window, public gcn::ActionListener { /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const std::string &eventId, gcn::Widget *widget); }; #endif diff --git a/src/gui/passwordfield.h b/src/gui/passwordfield.h index 15ca85c9..cae1f92e 100644 --- a/src/gui/passwordfield.h +++ b/src/gui/passwordfield.h @@ -21,8 +21,8 @@ * $Id$ */ -#ifndef __PASSWORDFIELD_H__ -#define __PASSWORDFIELD_H__ +#ifndef _TMW_PASSWORDFIELD_H_ +#define _TMW_PASSWORDFIELD_H_ #include "textfield.h" diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp index 568c3350..5fbe79b7 100644 --- a/src/gui/playerbox.cpp +++ b/src/gui/playerbox.cpp @@ -23,7 +23,7 @@ #include "playerbox.h" -#include "../being.h" +#include "../player.h" #include "../graphics.h" #include "../resources/image.h" @@ -32,17 +32,11 @@ #include "../utils/dtor.h" -extern std::vector hairset; -extern Spriteset *playerset[2]; - int PlayerBox::instances = 0; ImageRect PlayerBox::background; -PlayerBox::PlayerBox(unsigned char sex): - mHairColor(0), - mHairStyle(0), - mSex(sex), - mShowPlayer(false) +PlayerBox::PlayerBox(const Player *player): + mPlayer(player) { setBorderSize(2); @@ -81,29 +75,18 @@ PlayerBox::~PlayerBox() } } -void PlayerBox::draw(gcn::Graphics *graphics) +void +PlayerBox::draw(gcn::Graphics *graphics) { - if (!mShowPlayer) { - return; - } - - // Draw character - dynamic_cast(graphics)->drawImage( - playerset[mSex]->get(0), 23, 12); - - // Draw his hair - if (mHairStyle > 0 && mHairColor < NR_HAIR_COLORS && - mHairStyle < NR_HAIR_STYLES) + if (mPlayer) { - int hf = 5 * mHairColor; - if (hf >= 0 && hf < (int)hairset[mHairStyle]->size()) { - dynamic_cast(graphics)->drawImage( - hairset[mHairStyle - 1]->get(hf), 35, 7); - } + // Draw character + mPlayer->draw(dynamic_cast(graphics), 40, 42); } } -void PlayerBox::drawBorder(gcn::Graphics *graphics) +void +PlayerBox::drawBorder(gcn::Graphics *graphics) { int w, h, bs; bs = getBorderSize(); diff --git a/src/gui/playerbox.h b/src/gui/playerbox.h index ec04eaf6..6bba1b51 100644 --- a/src/gui/playerbox.h +++ b/src/gui/playerbox.h @@ -27,10 +27,10 @@ #include class ImageRect; +class Player; /** - * A box showing a player. Draws the various hair styles a player can have - * currently. + * A box showing a player character. * * \ingroup GUI */ @@ -38,15 +38,24 @@ class PlayerBox : public gcn::ScrollArea { public: /** - * Constructor. + * Constructor. Takes the initial player character that this box should + * display, which defaults to NULL. */ - PlayerBox(unsigned char sex); + PlayerBox(const Player *player = NULL); /** * Destructor. */ ~PlayerBox(); + /** + * Sets a new player character to be displayed by this box. Setting the + * player to NULL causes the box not to draw any + * character. + */ + void + setPlayer(const Player *player) { mPlayer = player; } + /** * Draws the scroll area. */ @@ -57,12 +66,9 @@ class PlayerBox : public gcn::ScrollArea */ void drawBorder(gcn::Graphics *graphics); - unsigned char mHairColor; /**< The hair color index */ - unsigned char mHairStyle; /**< The hair style index */ - unsigned char mSex; /**< Sex */ - bool mShowPlayer; /**< Wether to show the player or not */ - private: + const Player *mPlayer; /**< The character used for display */ + static int instances; static ImageRect background; }; diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index ab81f7d0..c2959e1d 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -40,7 +40,7 @@ #include "../npc.h" #include "../resources/iteminfo.h" -#include "../resources/itemmanager.h" +#include "../resources/itemdb.h" extern std::string tradePartnerName; @@ -106,7 +106,7 @@ void PopupMenu::showPopup(int x, int y, FloorItem *floorItem) mBrowserBox->clearRows(); // Floor item can be picked up (single option, candidate for removal) - std::string name = itemDb->getItemInfo(mFloorItem->getItemId()).getName(); + std::string name = ItemDB::get(mFloorItem->getItemId()).getName(); mBrowserBox->addRow("@@pickup|Pick Up " + name + "@@"); //browserBox->addRow("@@look|Look To@@"); diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 7cef62a2..70cd6dc4 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -97,6 +97,7 @@ RegisterDialog::RegisterDialog(LoginData *loginData): add(mCancelButton); setLocationRelativeTo(getParent()); + setVisible(true); mUserField->requestFocus(); mUserField->setCaretPosition(mUserField->getText().length()); } diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index fd63633c..499bbd05 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -37,7 +37,7 @@ #include "../npc.h" #include "../resources/iteminfo.h" -#include "../resources/itemmanager.h" +#include "../resources/itemdb.h" #include "../utils/tostring.h" @@ -232,6 +232,7 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) mMaxItems -= mAmountItems; mShopItems->getShop()->at(selectedItem).quantity = mMaxItems; + mPlayerMoney += (mAmountItems * mShopItems->at(selectedItem).price); mAmountItems = 0; mSlider->setValue(0); mSlider->setEnabled(mMaxItems != 0); @@ -274,7 +275,7 @@ void SellDialog::selectionChanged(const SelectionEvent &event) if (selectedItem > -1) { const ItemInfo &info = - itemDb->getItemInfo(mShopItems->at(selectedItem).id); + ItemDB::get(mShopItems->at(selectedItem).id); mItemDescLabel->setCaption("Description: " + info.getDescription()); mItemEffectLabel->setCaption("Effect: " + info.getEffect()); diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp index 39abd5ed..bd17bff7 100644 --- a/src/gui/serverdialog.cpp +++ b/src/gui/serverdialog.cpp @@ -174,6 +174,7 @@ ServerDialog::ServerDialog(LoginData *loginData): add(mCancelButton); setLocationRelativeTo(getParent()); + setVisible(true); if (mServerNameField->getText().empty()) { mServerNameField->requestFocus(); diff --git a/src/gui/serverdialog.h b/src/gui/serverdialog.h index 5b265c17..d907f340 100644 --- a/src/gui/serverdialog.h +++ b/src/gui/serverdialog.h @@ -132,7 +132,7 @@ class ServerDialog : public Window, public gcn::ActionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const std::string &eventId, gcn::Widget *widget); private: gcn::TextField *mServerNameField; diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp index d9212728..685d88cf 100644 --- a/src/gui/setup_joystick.cpp +++ b/src/gui/setup_joystick.cpp @@ -42,7 +42,7 @@ Setup_Joystick::Setup_Joystick(): mCalibrateLabel->setPosition(10, 25); mCalibrateButton->setPosition(10, 30 + mCalibrateLabel->getHeight()); - mOriginalJoystickEnabled = (joystick ? joystick->isEnabled() : false); + mOriginalJoystickEnabled = (int)config.getValue("joystickEnabled", 0) != 0; mJoystickEnabled->setMarked(mOriginalJoystickEnabled); mJoystickEnabled->setEventId("joystickEnabled"); diff --git a/src/gui/shop.cpp b/src/gui/shop.cpp index 3f30732a..2d33e8a8 100644 --- a/src/gui/shop.cpp +++ b/src/gui/shop.cpp @@ -23,7 +23,7 @@ #include "shop.h" #include "../utils/tostring.h" -#include "../resources/itemmanager.h" +#include "../resources/itemdb.h" ShopItems::~ShopItems() { @@ -44,11 +44,11 @@ void ShopItems::addItem(short id, int price) { ITEM_SHOP item_shop; - item_shop.name = itemDb->getItemInfo(id).getName() + item_shop.name = ItemDB::get(id).getName() + " " + toString(price) + " GP"; item_shop.price = price; item_shop.id = id; - item_shop.image = itemDb->getItemInfo(id).getImage(); + item_shop.image = ItemDB::get(id).getImage(); mItemsShop.push_back(item_shop); } diff --git a/src/gui/textfield.h b/src/gui/textfield.h index 1ed802d7..4748830c 100644 --- a/src/gui/textfield.h +++ b/src/gui/textfield.h @@ -28,7 +28,6 @@ class ImageRect; - /** * A text field. * diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 2ac56ae5..82262563 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -48,7 +48,7 @@ TradeWindow::TradeWindow(): mPartnerInventory(new Inventory()) { setWindowName("Trade"); - setDefaultSize(115, 197, 322, 150); + setDefaultSize(115, 197, 332, 209); mAddButton = new Button("Add", "add", this); mOkButton = new Button("Ok", "ok", this); @@ -95,33 +95,33 @@ TradeWindow::TradeWindow(): add(mMoneyField); add(mMoneyLabel); - mMoneyField->setPosition(8 + 60, getHeight() - 20); + gcn::Rectangle area = getChildrenArea(); + int width = area.width; + int height = area.height; + + mMoneyField->setPosition(8 + 60, height - 20); mMoneyField->setWidth(50); - mMoneyLabel->setPosition(8 + 60 + 50 + 6, getHeight() - 20); - mMoneyLabel2->setPosition(8, getHeight() - 20); + mMoneyLabel->setPosition(8 + 60 + 50 + 6, height - 20); + mMoneyLabel2->setPosition(8, height - 20); - mCancelButton->setPosition(getWidth() - 54, getHeight() - 49); - mTradeButton->setPosition(mCancelButton->getX() - 41 - , getHeight() - 49); - mOkButton->setPosition(mTradeButton->getX() - 24, - getHeight() - 49); - mAddButton->setPosition(mOkButton->getX() - 31, - getHeight() - 49); + mCancelButton->setPosition(width - 54, height - 49); + mTradeButton->setPosition(mCancelButton->getX() - 41, height - 49); + mOkButton->setPosition(mTradeButton->getX() - 24, height - 49); + mAddButton->setPosition(mOkButton->getX() - 31, height - 49); - mMyItemContainer->setSize(getWidth() - 24 - 12 - 1, - (INVENTORY_SIZE * 24) / (getWidth() / 24) - 1); - mMyScroll->setSize(getWidth() - 16, (getHeight() - 76) / 2); + mMyItemContainer->setSize(width - 24 - 12 - 1, + (INVENTORY_SIZE * 24) / (width / 24) - 1); + mMyScroll->setSize(width - 16, (height - 76) / 2); - mPartnerItemContainer->setSize(getWidth() - 24 - 12 - 1, - (INVENTORY_SIZE * 24) / (getWidth() / 24) - 1); - mPartnerScroll->setSize(getWidth() - 16, (getHeight() - 76) / 2); + mPartnerItemContainer->setSize(width - 24 - 12 - 1, + (INVENTORY_SIZE * 24) / (width / 24) - 1); + mPartnerScroll->setSize(width - 16, (height - 76) / 2); mItemNameLabel->setPosition(8, mPartnerScroll->getY() + mPartnerScroll->getHeight() + 4); mItemDescriptionLabel->setPosition(8, mItemNameLabel->getY() + mItemNameLabel->getHeight() + 4); - } TradeWindow::~TradeWindow() diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index c29906a1..73343483 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -192,7 +192,7 @@ int UpdaterWindow::updateProgress(void *ptr, if (progress > 1) progress = 1.0f; uw->setLabel( - uw->mCurrentFile + " (" + toString((int)progress * 100) + "%)"); + uw->mCurrentFile + " (" + toString((int) (progress * 100)) + "%)"); uw->setProgress(progress); if (state != STATE_UPDATE || uw->mDownloadStatus == UPDATE_ERROR) diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp new file mode 100644 index 00000000..d0525a2f --- /dev/null +++ b/src/gui/viewport.cpp @@ -0,0 +1,392 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "viewport.h" + +#include + +#include "gui.h" +#include "popupmenu.h" + +#include "../beingmanager.h" +#include "../configuration.h" +#include "../flooritemmanager.h" +#include "../graphics.h" +#include "../localplayer.h" +#include "../map.h" +#include "../npc.h" + +#include "../resources/monsterdb.h" + +#include "../utils/tostring.h" + +Viewport::Viewport(): + mMap(0), + mViewX(0.0f), + mViewY(0.0f), + mCameraX(0), + mCameraY(0), + mShowDebugPath(false), + mPopupActive(false) +{ + setOpaque(false); + addMouseListener(this); + + mScrollLaziness = (int) config.getValue("ScrollLaziness", 32); + mScrollRadius = (int) config.getValue("ScrollRadius", 32); + + config.addListener("ScrollLaziness", this); + config.addListener("ScrollRadius", this); + + mPopupMenu = new PopupMenu(); +} + +Viewport::~Viewport() +{ + delete mPopupMenu; +} + +void +Viewport::setMap(Map *map) +{ + mMap = map; +} + +void +Viewport::draw(gcn::Graphics *gcnGraphics) +{ + static int lastTick = tick_time; + + if (!mMap || !player_node) + return; + + Graphics *graphics = static_cast(gcnGraphics); + + // Avoid freaking out when tick_time overflows + if (tick_time < lastTick) + { + lastTick = tick_time; + } + + // Calculate viewpoint + int midTileX = graphics->getWidth() / 2; + int midTileY = graphics->getHeight() / 2; + + int player_x = player_node->mX - midTileX + player_node->getXOffset(); + int player_y = player_node->mY - midTileY + player_node->getYOffset(); + + if (mScrollLaziness < 1) + mScrollLaziness = 1; // Avoids division by zero + + // Apply lazy scrolling + while (lastTick < tick_time) + { + if (player_x > mViewX + mScrollRadius) + { + mViewX += (player_x - mViewX - mScrollRadius) / mScrollLaziness; + } + if (player_x < mViewX - mScrollRadius) + { + mViewX += (player_x - mViewX + mScrollRadius) / mScrollLaziness; + } + if (player_y > mViewY + mScrollRadius) + { + mViewY += (player_y - mViewY - mScrollRadius) / mScrollLaziness; + } + if (player_y < mViewY - mScrollRadius) + { + mViewY += (player_y - mViewY + mScrollRadius) / mScrollLaziness; + } + lastTick++; + } + + // Auto center when player is off screen + if ( player_x - mViewX > graphics->getWidth() / 2 + || mViewX - player_x > graphics->getWidth() / 2 + || mViewY - player_y > graphics->getHeight() / 2 + || player_y - mViewY > graphics->getHeight() / 2 + ) + { + mViewX = player_x; + mViewY = player_y; + }; + + if (mMap) { + if (mViewX < 0) { + mViewX = 0; + } + if (mViewY < 0) { + mViewY = 0; + } + if (mViewX > mMap->getWidth() * 32 - midTileX) { + mViewX = mMap->getWidth() * 32 - midTileX; + } + if (mViewY > mMap->getHeight() * 32 - midTileY) { + mViewY = mMap->getHeight() * 32 - midTileY; + } + } + + mCameraX = (int) mViewX; + mCameraY = (int) mViewY; + + // Draw tiles and sprites + if (mMap) + { + mMap->draw(graphics, mCameraX, mCameraY, 0); + mMap->draw(graphics, mCameraX, mCameraY, 1); + mMap->draw(graphics, mCameraX, mCameraY, 2); + mMap->drawOverlay(graphics, mViewX, mViewY, + (int) config.getValue("OverlayDetail", 2)); + } + + // Find a path from the player to the mouse, and draw it. This is for debug + // purposes. + if (mShowDebugPath && mMap) + { + // Get the current mouse position + int mouseX, mouseY; + SDL_GetMouseState(&mouseX, &mouseY); + + int mouseTileX = (mouseX + mCameraX) / 32; + int mouseTileY = (mouseY + mCameraY) / 32; + + Path debugPath = mMap->findPath( + player_node->mX / 32, player_node->mY / 32, + mouseTileX, mouseTileY); + + graphics->setColor(gcn::Color(255, 0, 0)); + for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++) + { + int squareX = i->x * 32 - mCameraX + 12; + int squareY = i->y * 32 - mCameraY + 12; + + graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8)); + graphics->drawText( + toString(mMap->getMetaTile(i->x, i->y)->Gcost), + squareX + 4, squareY + 12, gcn::Graphics::CENTER); + } + } + + // Draw player nickname, speech, and emotion sprite as needed + Beings &beings = beingManager->getAll(); + for (BeingIterator i = beings.begin(); i != beings.end(); i++) + { + (*i)->drawSpeech(graphics, -mCameraX, -mCameraY); + (*i)->drawName(graphics, -mCameraX, -mCameraY); + (*i)->drawEmotion(graphics, -mCameraX, -mCameraY); + } + + // Draw target marker if needed + Being *target; + if ((target = player_node->getTarget())) + { + graphics->setFont(speechFont); + graphics->setColor(gcn::Color(255, 32, 32)); + int dy = (target->getType() == Being::PLAYER) ? 80 : 42; + + std::string mobName = ""; + + if (target->mJob >= 1002) + { + int mobId = target->mJob - 1002; + mobName = MonsterDB::get(mobId).getName(); + + graphics->drawText(mobName, + target->getPixelX() - mCameraX + 15, + target->getPixelY() - mCameraY - dy, + gcn::Graphics::CENTER); + } + } + + // Draw contained widgets + WindowContainer::draw(gcnGraphics); +} + +void +Viewport::logic() +{ + WindowContainer::logic(); + + if (!mMap || !player_node) + return; + + int mouseX, mouseY; + Uint8 button = SDL_GetMouseState(&mouseX, &mouseY); + + if (mPlayerFollowMouse && button & SDL_BUTTON(1) && + mWalkTime != player_node->mWalkTime) + { + player_node->setDestination(mouseX + mCameraX, + mouseY + mCameraY); + mWalkTime = player_node->mWalkTime; + } +} + +void +Viewport::mousePress(int mx, int my, int button) +{ + // Check if we are alive and kickin' + if (!mMap || !player_node || player_node->mAction == Being::DEAD) + return; + + // Check if we are busy + if (current_npc) + return; + + mPlayerFollowMouse = false; + + int tilex = (mx + mCameraX) / 32; + int tiley = (my + mCameraY) / 32; + + // Right click might open a popup + if (button == gcn::MouseInput::RIGHT) + { + Being *being; + FloorItem *floorItem; + + if ((being = beingManager->findBeing(tilex, tiley)) && + being->getType() != Being::LOCALPLAYER) + { + showPopup(mx, my, being); + return; + } + else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley))) + { + showPopup(mx, my, floorItem); + return; + } + } + + // If a popup is active, just remove it + if (mPopupActive) + { + mPopupMenu->setVisible(false); + mPopupActive = false; + return; + } + + // Left click can cause different actions + if (button == gcn::MouseInput::LEFT) + { + Being *being; + FloorItem *item; + + // Interact with some being + if ((being = beingManager->findBeing(tilex, tiley))) + { + switch (being->getType()) + { + case Being::NPC: + dynamic_cast(being)->talk(); + break; + + case Being::MONSTER: + case Being::PLAYER: + if (being->mAction == Being::DEAD) + break; + + player_node->attack(being, true); + break; + + default: + break; + } + } + // Pick up some item + else if ((item = floorItemManager->findByCoordinates(tilex, tiley))) + { + player_node->pickUp(item); + } + // Just walk around + else if (mMap->getWalk(tilex, tiley)) + { + // XXX XXX XXX REALLY UGLY! + Uint8 *keys = SDL_GetKeyState(NULL); + if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT])) + { + player_node->setDestination(mx + mCameraX, my + mCameraY); + player_node->stopAttack(); + } + mPlayerFollowMouse = true; + } + } + + if (button == gcn::MouseInput::MIDDLE) + { + // Find the being nearest to the clicked position + Being *target = beingManager->findNearestLivingBeing( + tilex, tiley, + 20, Being::MONSTER); + + if (target) + { + player_node->setTarget(target); + } + } +} + +void +Viewport::mouseMotion(int mx, int my) +{ + if (!mMap || !player_node) + return; + + if (mPlayerFollowMouse && mWalkTime == player_node->mWalkTime) + { + player_node->setDestination(mx + mCameraX, my + mCameraY); + } +} + +void +Viewport::mouseRelease(int mx, int my, int button) +{ + mPlayerFollowMouse = false; +} + +void +Viewport::showPopup(int x, int y, Item *item) +{ + mPopupMenu->showPopup(x, y, item); + mPopupActive = true; +} + +void +Viewport::showPopup(int x, int y, FloorItem *floorItem) +{ + mPopupMenu->showPopup(x, y, floorItem); + mPopupActive = true; +} + +void +Viewport::showPopup(int x, int y, Being *being) +{ + mPopupMenu->showPopup(x, y, being); + mPopupActive = true; +} + +void +Viewport::optionChanged(const std::string &name) +{ + mScrollLaziness = (int) config.getValue("ScrollLaziness", 32); + mScrollRadius = (int) config.getValue("ScrollRadius", 32); +} diff --git a/src/gui/viewport.h b/src/gui/viewport.h new file mode 100644 index 00000000..df78b1da --- /dev/null +++ b/src/gui/viewport.h @@ -0,0 +1,145 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_VIEWPORT_H_ +#define _TMW_VIEWPORT_H_ + +#include + +#include "windowcontainer.h" + +#include "../configlistener.h" + +class Map; +class Being; +class FloorItem; +class Item; +class PopupMenu; + +/** + * The viewport on the map. Displays the current map and handles mouse input + * and the popup menu. + * + * TODO: This class is planned to be extended to allow floating widgets on top + * of it such as NPC messages, which are positioned using map pixel + * coordinates. + */ +class Viewport : public WindowContainer, public gcn::MouseListener, + public ConfigListener +{ + public: + /** + * Constructor. + */ + Viewport(); + + /** + * Destructor. + */ + ~Viewport(); + + /** + * Sets the map displayed by the viewport. + */ + void + setMap(Map *map); + + /** + * Draws the viewport. + */ + void + draw(gcn::Graphics *graphics); + + /** + * Implements player to keep following mouse. + */ + void + logic(); + + /** + * Toggles whether the path debug graphics are shown + */ + void toggleDebugPath() { mShowDebugPath = !mShowDebugPath; } + + /** + * Handles mouse press on map. + */ + void + mousePress(int mx, int my, int button); + + /** + * Handles mouse move on map + */ + void + mouseMotion(int mx, int my); + + /** + * Handles mouse button release on map. + */ + void + mouseRelease(int mx, int my, int button); + + /** + * Shows a popup for an item. + * TODO Find some way to get rid of Item here + */ + void showPopup(int x, int y, Item *item); + + /** + * A relevant config option changed. + */ + void + optionChanged(const std::string &name); + + private: + /** + * Shows a popup for a floor item. + * TODO Find some way to get rid of FloorItem here + */ + void showPopup(int x, int y, FloorItem *floorItem); + + /** + * Shows a popup for a being. + * TODO Find some way to get rid of Being here + */ + void showPopup(int x, int y, Being *being); + + + Map *mMap; /**< The current map. */ + + int mScrollRadius; + int mScrollLaziness; + float mViewX; /**< Current viewpoint in pixels. */ + float mViewY; /**< Current viewpoint in pixels. */ + int mCameraX; + int mCameraY; + bool mShowDebugPath; /**< Show a path from player to pointer. */ + + bool mPlayerFollowMouse; + int mWalkTime; + + PopupMenu *mPopupMenu; /**< Popup menu. */ + bool mPopupActive; +}; + +#endif diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 13d42c78..1960d6ca 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -113,6 +113,9 @@ Window::Window(const std::string& caption, bool modal, Window *parent): { requestModalFocus(); } + + // Windows are invisible by default + setVisible(false); } Window::~Window() diff --git a/src/gui/window.h b/src/gui/window.h index 51c876e3..158035c0 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -36,7 +36,8 @@ class WindowContainer; /** - * A window. This window can be dragged around and has a title bar. + * A window. This window can be dragged around and has a title bar. Windows are + * invisible by default. * * \ingroup GUI */ diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h index b860fa3c..df255f84 100644 --- a/src/gui/windowcontainer.h +++ b/src/gui/windowcontainer.h @@ -27,7 +27,8 @@ #include /** - * A window container. This container makes draggable windows possible. + * A window container. This container adds functionality for more convenient + * widget (windows in particular) destruction. * * \ingroup GUI */ diff --git a/src/item.h b/src/item.h index 1375886e..47cdb1a9 100644 --- a/src/item.h +++ b/src/item.h @@ -24,7 +24,7 @@ #ifndef _ITEM_H_ #define _ITEM_H_ -#include "resources/itemmanager.h" +#include "resources/itemdb.h" /** * Represents one or more instances of a certain item type. @@ -119,7 +119,7 @@ class Item * Returns information about this item type. */ const ItemInfo& - getInfo() const { return itemDb->getItemInfo(mId); } + getInfo() const { return ItemDB::get(mId); } protected: int mId; /**< Item type id. */ diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 6898dfb7..c887dd1c 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -30,6 +30,7 @@ #include "item.h" #include "main.h" #include "sound.h" +#include "log.h" #include "net/gameserver/player.h" @@ -65,9 +66,19 @@ void LocalPlayer::logic() void LocalPlayer::nextStep() { - if (mPath.empty() && mPickUpTarget) { - pickUp(mPickUpTarget); + if (mPath.empty()) + { + if (mPickUpTarget) + { + pickUp(mPickUpTarget); + } + + if (mWalkingDir) + { + walk(mWalkingDir); + } } + Player::nextStep(); } @@ -161,10 +172,15 @@ void LocalPlayer::pickUp(FloorItem *item) void LocalPlayer::walk(unsigned char dir) { + if (mWalkingDir != dir) + { + mWalkingDir = dir; + } + if (!mMap || !dir) return; - if (mAction == WALK) + if (mAction == WALK && !mPath.empty()) { // Just finish the current action, otherwise we get out of sync Being::setDestination(mX, mY); @@ -198,10 +214,8 @@ void LocalPlayer::walk(unsigned char dir) } else if (dir) { - // Update the player direction to where he wants to walk - // Warning: Not communicated to the server yet - // If the being can't move, just change direction + // TODO: Communicate this to the server (waiting on tmwserv) setDirection(dir); } } @@ -216,10 +230,16 @@ void LocalPlayer::setDestination(Uint16 x, Uint16 y) x = tx * 32 + fx; y = ty * 32 + fy; - Net::GameServer::Player::walk(x, y); + // Only send a new message to the server when destination changes + if (x != mDestX || y != mDestY) + { + mDestX = x; + mDestY = y; - mPickUpTarget = NULL; + Net::GameServer::Player::walk(x, y); + } + mPickUpTarget = NULL; Being::setDestination(x, y); } diff --git a/src/localplayer.h b/src/localplayer.h index dbf2a147..f632b1b9 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -47,6 +47,11 @@ class LocalPlayer : public Player virtual ~LocalPlayer(); virtual void logic(); + + /** + * Adds a new step when walking before calling super. Also, when + * specified it picks up an item at the end of a path. + */ virtual void nextStep(); /** @@ -151,7 +156,10 @@ class LocalPlayer : public Player FloorItem *mPickUpTarget; bool mTrading; - int mLastAction; /**< Time stamp of the last action, -1 if none */ + int mLastAction; /**< Time stamp of the last action, -1 if none. */ + int mWalkingDir; /**< The direction the player is walking in. */ + int mDestX; /**< X coordinate of destination. */ + int mDestY; /**< Y coordinate of destination. */ }; extern LocalPlayer *player_node; diff --git a/src/log.cpp b/src/log.cpp index 07eb55f7..3a3c91b8 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -21,7 +21,9 @@ #include "log.h" #ifdef WIN32 -#include + #include "utils/wingettimeofday.h" +#else + #include #endif #ifdef __APPLE__ #include @@ -64,7 +66,6 @@ void Logger::log(const char *log_text, ...) char* buf = new char[1024]; va_list ap; - time_t t; // Use a temporary buffer to fill in the variables va_start(ap, log_text); @@ -72,19 +73,23 @@ void Logger::log(const char *log_text, ...) va_end(ap); // Get the current system time - time(&t); + timeval tv; + gettimeofday(&tv, NULL); // Print the log entry std::stringstream timeStr; timeStr << "[" - << ((((t / 60) / 60) % 24 < 10) ? "0" : "") - << (int)(((t / 60) / 60) % 24) + << ((((tv.tv_sec / 60) / 60) % 24 < 10) ? "0" : "") + << (int)(((tv.tv_sec / 60) / 60) % 24) << ":" - << (((t / 60) % 60 < 10) ? "0" : "") - << (int)((t / 60) % 60) + << (((tv.tv_sec / 60) % 60 < 10) ? "0" : "") + << (int)((tv.tv_sec / 60) % 60) << ":" - << ((t % 60 < 10) ? "0" : "") - << (int)(t % 60) + << ((tv.tv_sec % 60 < 10) ? "0" : "") + << (int)(tv.tv_sec % 60) + << "." + << (((tv.tv_usec / 10000) % 100) < 10 ? "0" : "") + << (int)((tv.tv_usec / 10000) % 100) << "] "; mLogFile << timeStr.str() << buf << std::endl; diff --git a/src/main.cpp b/src/main.cpp index 59bb1566..90368b7d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,7 +76,10 @@ #include "net/gameserver/gameserver.h" +#include "resources/equipmentdb.h" #include "resources/image.h" +#include "resources/itemdb.h" +#include "resources/monsterdb.h" #include "resources/resourcemanager.h" #include "resources/spriteset.h" @@ -87,8 +90,6 @@ char n_character; std::string token; -std::vector hairset; -Spriteset *playerset[2]; Graphics *graphics; unsigned char state; @@ -171,6 +172,7 @@ void initHomeDir() void initConfiguration(const Options &options) { // Fill configuration with defaults + logger->log("Initializing configuration..."); config.setValue("host", "animesites.de"); config.setValue("port", 9601); config.setValue("hwaccel", 0); @@ -219,6 +221,7 @@ void initConfiguration(const Options &options) void init_engine() { // Initialize SDL + logger->log("Initializing SDL..."); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { std::cerr << "Could not initialize SDL: " << SDL_GetError() << std::endl; @@ -288,26 +291,6 @@ void init_engine() // Initialize for drawing graphics->_beginDraw(); - playerset[0] = resman->getSpriteset( - "graphics/sprites/player_male_base.png", 64, 64); - if (!playerset[0]) logger->error("Couldn't load male player spriteset!"); - playerset[1] = resman->getSpriteset( - "graphics/sprites/player_female_base.png", 64, 64); - if (!playerset[1]) logger->error("Couldn't load female player spriteset!"); - - - for (int i = 0; i < NR_HAIR_STYLES - 1; i++) - { - Spriteset *tmp = ResourceManager::getInstance()->getSpriteset( - "graphics/sprites/hairstyle" + toString(i + 1) + ".png", - 40, 40); - if (!tmp) { - logger->error("Unable to load hairstyle"); - } else { - hairset.push_back(tmp); - } - } - gui = new Gui(graphics); state = STATE_CHOOSE_SERVER; /**< Initial game state */ @@ -316,8 +299,9 @@ void init_engine() if (config.getValue("sound", 0) == 1) { sound.init(); } - sound.setSfxVolume((int)config.getValue("sfxVolume", defaultSfxVolume)); - sound.setMusicVolume((int)config.getValue("musicVolume", + sound.setSfxVolume((int) config.getValue("sfxVolume", + defaultSfxVolume)); + sound.setMusicVolume((int) config.getValue("musicVolume", defaultMusicVolume)); } catch (const char *err) { @@ -325,6 +309,11 @@ void init_engine() errorMessage = err; logger->log("Warning: %s", err); } + + // Load XML databases + EquipmentDB::load(); + ItemDB::load(); + MonsterDB::load(); } /** Clear the engine */ @@ -334,19 +323,17 @@ void exit_engine() delete gui; delete graphics; - std::for_each(hairset.begin(), hairset.end(), - std::mem_fun(&Spriteset::decRef)); - hairset.clear(); - - playerset[0]->decRef(); - playerset[1]->decRef(); - // Shutdown libxml xmlCleanupParser(); // Shutdown sound sound.close(); + // Unload XML databases + EquipmentDB::unload(); + ItemDB::unload(); + MonsterDB::unload(); + ResourceManager::deleteInstance(); } @@ -599,7 +586,7 @@ int main(int argc, char *argv[]) gui->logic(); Net::flush(); - if (state > STATE_CONNECT_ACCOUNT && state < STATE_GAME) + if (state > STATE_CONNECT_ACCOUNT && state < STATE_GAME) { if (!accountServerConnection->isConnected()) { diff --git a/src/map.cpp b/src/map.cpp index 1cdc1077..1bd8f235 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -282,35 +282,35 @@ Map::setWalk(int x, int y, bool walkable) bool Map::getWalk(int x, int y) { - // Check for being walkable - if (tileCollides(x, y)) { - return false; - } + return !tileCollides(x, y) && !occupied(x, y); +} - /* - // Check for collision with a being +bool +Map::occupied(int x, int y) +{ Beings &beings = beingManager->getAll(); - for (BeingIterator i = beings.begin(); i != beings.end(); i++) { + for (BeingIterator i = beings.begin(); i != beings.end(); i++) + { // job 45 is a portal, they don't collide - if ((*i)->mX / 32 == x && (*i)->mY / 32 == y && (*i)->mJob != 45) { - return false; + if ((*i)->mX / 32 == x && (*i)->mY / 32 == y && (*i)->mJob != 45) + { + return true; } } - */ - return true; + return false; } bool Map::tileCollides(int x, int y) { - // You can't walk outside of the map - if (x < 0 || y < 0 || x >= mWidth || y >= mHeight) { - return true; - } + return !(contains(x, y) && mMetaTiles[x + y * mWidth].walkable); +} - // Check if the tile is walkable - return !mMetaTiles[x + y * mWidth].walkable; +bool +Map::contains(int x, int y) +{ + return x >= 0 && y >= 0 && x < mWidth && y < mHeight; } void @@ -355,8 +355,9 @@ Map::findPath(int startX, int startY, int destX, int destY) // Declare open list, a list with open tiles sorted on F cost std::priority_queue openList; - // Return empty path when destination not walkable - if (!getWalk(destX, destY)) return path; + // Return empty path when destination collides + if (tileCollides(destX, destY)) + return path; // Reset starting tile's G cost to 0 MetaTile *startTile = getMetaTile(startX, startY); @@ -395,16 +396,15 @@ Map::findPath(int startX, int startY, int destX, int destY) // Skip if if we're checking the same tile we're leaving from, // or if the new location falls outside of the map boundaries - if ((dx == 0 && dy == 0) || - (x < 0 || y < 0 || x >= mWidth || y >= mHeight)) + if ((dx == 0 && dy == 0) || !contains(x, y)) { continue; } MetaTile *newTile = getMetaTile(x, y); - // Skip if the tile is on the closed list or is not walkable - if (newTile->whichList == mOnClosedList || !getWalk(x, y)) + // Skip if the tile is on the closed list or collides + if (newTile->whichList == mOnClosedList || tileCollides(x, y)) { continue; } @@ -441,6 +441,13 @@ Map::findPath(int startX, int startY, int destX, int destY) ++Gcost; } + // It costs extra to walk through a being (needs to be enough + // to make it more attractive to walk around). + if (occupied(x, y)) + { + Gcost += 30; + } + // Skip if Gcost becomes too much // Warning: probably not entirely accurate if (Gcost > 20 * basicCost) diff --git a/src/map.h b/src/map.h index 961326b8..15b9b0dc 100644 --- a/src/map.h +++ b/src/map.h @@ -129,7 +129,7 @@ class Map : public Properties MetaTile *getMetaTile(int x, int y); /** - * Set walkability flag for a tile + * Set walkability flag for a tile. */ void setWalk(int x, int y, bool walkable); @@ -199,6 +199,16 @@ class Map : public Properties Tileset* getTilesetWithGid(int gid); + /** + * Tells whether a tile is occupied by a being. + */ + bool occupied(int x, int y); + + /** + * Tells whether the given coordinates fall within the map boundaries. + */ + bool contains(int x, int y); + int mWidth, mHeight; int mTileWidth, mTileHeight; MetaTile *mMetaTiles; diff --git a/src/monster.cpp b/src/monster.cpp index a4317e5e..f2e4d93d 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -25,6 +25,9 @@ #include "animatedsprite.h" #include "game.h" +#include "sound.h" + +#include "resources/monsterdb.h" #include "utils/tostring.h" @@ -32,7 +35,8 @@ Monster::Monster(Uint16 id, Uint16 job, Map *map): Being(id, job, map) { - mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/monster" + toString(job - 1002) + ".xml", 0); + mSprites[BASE_SPRITE] = new AnimatedSprite( + "graphics/sprites/" + MonsterDB::get(job - 1002).getSprite()); } Being::Type @@ -41,3 +45,36 @@ Monster::getType() const return MONSTER; } +void +Monster::setAction(Uint8 action) +{ + SpriteAction currentAction = ACTION_INVALID; + + switch (action) + { + case WALK: + currentAction = ACTION_WALK; + break; + case DEAD: + currentAction = ACTION_DEAD; + sound.playSfx(MonsterDB::get(mJob - 1002).getSound(EVENT_DIE)); + break; + case ATTACK: + currentAction = ACTION_ATTACK; + sound.playSfx(MonsterDB::get(mJob - 1002).getSound(EVENT_HIT)); + mSprites[BASE_SPRITE]->reset(); + break; + case STAND: + currentAction = ACTION_STAND; + break; + case HURT: + // Not implemented yet + break; + } + + if (currentAction != ACTION_INVALID) + { + mSprites[BASE_SPRITE]->play(currentAction); + mAction = action; + } +} diff --git a/src/monster.h b/src/monster.h index 0314a035..7f129e14 100644 --- a/src/monster.h +++ b/src/monster.h @@ -31,6 +31,8 @@ class Monster : public Being public: Monster(Uint16 id, Uint16 job, Map *map); + virtual void setAction(Uint8 action); + virtual Type getType() const; }; diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index 2d68dd28..6d8ff6c6 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -66,6 +66,7 @@ void BeingHandler::handleMessage(MessageIn &msg) /* Uint32 id; Uint16 job, speed; + Uint16 headBottom, headTop, headMid; Sint16 param1; Sint8 type; Being *srcBeing, *dstBeing; @@ -124,7 +125,8 @@ void BeingHandler::handleMessage(MessageIn &msg) dstBeing->mJob = job; dstBeing->setHairStyle(msg.readShort()); dstBeing->setWeapon(msg.readShort()); - dstBeing->setVisibleEquipment(3, msg.readShort()); // head bottom + dstBeing->setVisibleEquipment( + Being::BOTTOMCLOTHES_SPRITE, msg.readShort()); if (msg.getId() == SMSG_BEING_MOVE) { @@ -132,8 +134,9 @@ void BeingHandler::handleMessage(MessageIn &msg) } msg.readShort(); // shield - dstBeing->setVisibleEquipment(4, msg.readShort()); // head top - dstBeing->setVisibleEquipment(5, msg.readShort()); // head mid + dstBeing->setVisibleEquipment(Being::HAIT_SPRITE, msg.readShort()); + dstBeing->setVisibleEquipment( + Being::TOPCLOTHES_SPRITE, msg.readShort()); dstBeing->setHairColor(msg.readShort()); msg.readShort(); // unknown msg.readShort(); // head dir @@ -156,7 +159,9 @@ void BeingHandler::handleMessage(MessageIn &msg) } else { - //msg.readCoordinates(dstBeing->mX, dstBeing->mY, dstBeing->mDirection); + //Uint8 dir; + //msg->readCoordinates(dstBeing->mX, dstBeing->mY, dir); + //dstBeing->setDirection(dir); } msg.readByte(); // unknown @@ -173,19 +178,7 @@ void BeingHandler::handleMessage(MessageIn &msg) if (msg.readByte() == 1) { - // Death - switch (dstBeing->getType()) - { - case Being::MONSTER: - dstBeing->setAction(Being::MONSTER_DEAD); - dstBeing->mFrame = 0; - dstBeing->mWalkTime = tick_time; - break; - - default: - dstBeing->setAction(Being::DEAD); - break; - } + dstBeing->setAction(Being::DEAD); } else { @@ -219,15 +212,7 @@ void BeingHandler::handleMessage(MessageIn &msg) if (srcBeing != NULL && srcBeing != player_node) { - // buggy - if (srcBeing->getType() == Being::MONSTER) - { - srcBeing->setAction(Being::MONSTER_ATTACK); - } - else - { - srcBeing->setAction(Being::ATTACK); - } + srcBeing->setAction(Being::ATTACK); srcBeing->mFrame = 0; srcBeing->mWalkTime = tick_time; } @@ -275,27 +260,35 @@ void BeingHandler::handleMessage(MessageIn &msg) } int type = msg.readByte(); + int id = msg.readByte(); switch (type) { case 1: - dstBeing->setHairStyle(msg.readByte()); + dstBeing->setHairStyle(id); break; case 2: - dstBeing->setWeapon(msg.readByte()); + dstBeing->setWeapon(id); + break; + case 3: // Change lower headgear for eAthena, pants for us + dstBeing->setVisibleEquipment( + Being::BOTTOMCLOTHES_SPRITE, + id); + break; + case 4: // Change upper headgear for eAthena, hat for us + dstBeing->setVisibleEquipment( + Being::HAT_SPRITE, + id); break; - case 3: - case 4: - case 5: - // Equip/unequip head 3. Bottom 4. Top 5. Middle - dstBeing->setVisibleEquipment(type, msg.readByte()); - // First 3 slots of mVisibleEquipments are reserved for - // later use, probably accessories. + case 5: // Change middle headgear for eathena, armor for us + dstBeing->setVisibleEquipment( + Being::TOPCLOTHES_SPRITE, + id); break; case 6: - dstBeing->setHairColor(msg.readByte()); + dstBeing->setHairColor(id); break; default: - printf("c3: %i\n", msg.readByte()); // unsupported + logger->log("c3: %i\n", id); // unsupported break; } } @@ -331,15 +324,15 @@ void BeingHandler::handleMessage(MessageIn &msg) dstBeing->setHairStyle(msg.readShort()); dstBeing->setWeaponById(msg.readShort()); // item id 1 msg.readShort(); // item id 2 - dstBeing->setVisibleEquipment(3, msg.readShort()); // head bottom + headBottom = msg.readShort(); if (msg.getId() == SMSG_PLAYER_MOVE) { msg.readLong(); // server tick } - dstBeing->setVisibleEquipment(4, msg.readShort()); // head top - dstBeing->setVisibleEquipment(5, msg.readShort()); // head mid + headTop = msg.readShort(); + headMid = msg.readShort(); dstBeing->setHairColor(msg.readShort()); msg.readShort(); // unknown msg.readShort(); // head dir @@ -348,6 +341,10 @@ void BeingHandler::handleMessage(MessageIn &msg) msg.readShort(); // manner msg.readByte(); // karma dstBeing->setSex(1 - msg.readByte()); // sex + dstBeing->setVisibleEquipment( + Being::BOTTOMCLOTHES_SPRITE, headBottom); + dstBeing->setVisibleEquipment(Being::HAT_SPRITE, headTop); + dstBeing->setVisibleEquipment(Being::TOPCLOTHES_SPRITE, headMid); if (msg.getId() == SMSG_PLAYER_MOVE) { @@ -359,7 +356,9 @@ void BeingHandler::handleMessage(MessageIn &msg) } else { - //msg.readCoordinates(dstBeing->mX, dstBeing->mY, dstBeing->mDirection); + //Uint8 dir; + //msg->readCoordinates(dstBeing->mX, dstBeing->mY, dir); + //dstBeing->setDirection(dir); } msg.readByte(); // unknown @@ -386,7 +385,7 @@ void BeingHandler::handleMessage(MessageIn &msg) case 0x0119: // Change in players look - printf("0x0119 %li %i %i %x %i\n", msg.readLong(), + logger->log("0x0119 %li %i %i %x %i\n", msg.readLong(), msg.readShort(), msg.readShort(), msg.readShort(), msg.readByte()); break; diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp index 3f7e8709..f003d77a 100644 --- a/src/net/inventoryhandler.cpp +++ b/src/net/inventoryhandler.cpp @@ -92,7 +92,7 @@ void InventoryHandler::handleMessage(MessageIn &msg) if (msg.readByte()> 0) { chatWindow->chatLog("Unable to pick up item", BY_SERVER); } else { - const ItemInfo &itemInfo = itemDb->getItemInfo(itemId); + const ItemInfo &itemInfo = ItemDB::get(itemId); chatWindow->chatLog("You picked up a " + itemInfo.getName(), BY_SERVER); player_node->addInvItem(index, itemId, amount, equipType != 0); diff --git a/src/net/npchandler.cpp b/src/net/npchandler.cpp index 9c89e71f..02204a84 100644 --- a/src/net/npchandler.cpp +++ b/src/net/npchandler.cpp @@ -49,20 +49,22 @@ NPCHandler::NPCHandler() void NPCHandler::handleMessage(MessageIn &msg) { + int id; + switch (msg.getId()) { case SMSG_NPC_CHOICE: msg.readShort(); // length - current_npc = dynamic_cast( - beingManager->findBeing(msg.readLong())); + id = msg.readLong(); + current_npc = dynamic_cast(beingManager->findBeing(id)); npcListDialog->parseItems(msg.readString(msg.getLength() - 8)); npcListDialog->setVisible(true); break; case SMSG_NPC_MESSAGE: msg.readShort(); // length - current_npc = dynamic_cast( - beingManager->findBeing(msg.readLong())); + id = msg.readLong(); + current_npc = dynamic_cast(beingManager->findBeing(id)); npcTextDialog->addText(msg.readString(msg.getLength() - 8)); npcListDialog->setVisible(false); npcTextDialog->setVisible(true); diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index 6eb80d59..37291c0a 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -46,7 +46,8 @@ OkDialog *deathNotice = NULL; namespace { struct WeightListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { + void action(const std::string &eventId, gcn::Widget *widget) + { weightNotice = NULL; } } weightListener; @@ -57,8 +58,10 @@ namespace { */ // TODO Move somewhere else namespace { - struct DeathListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { + struct DeathListener : public gcn::ActionListener + { + void action(const std::string &eventId, gcn::Widget *widget) + { player_node->revive(); deathNotice = NULL; } @@ -114,10 +117,11 @@ void PlayerHandler::handleMessage(MessageIn &msg) player_node->mMaxWeight / 2) { weightNotice = new OkDialog("Message", - "You are carrying more then half your " - "weight. You are unable to regain " - "health."); - weightNotice->addActionListener(&weightListener); + "You are carrying more then half " + "your weight. You are unable to " + "regain health."); + weightNotice->addActionListener( + &weightListener); } player_node->mTotalWeight = value; break; diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp index d9bea775..17dea606 100644 --- a/src/net/skillhandler.cpp +++ b/src/net/skillhandler.cpp @@ -26,6 +26,8 @@ #include "messagein.h" #include "protocol.h" +#include "../log.h" + #include "../gui/chat.h" #include "../gui/skill.h" @@ -85,7 +87,7 @@ void SkillHandler::handleMessage(MessageIn &msg) if (action.success != SKILL_FAILED && action.bskill == BSKILL_EMOTE) { - printf("Action: %d/%d", action.bskill, action.success); + logger->log("Action: %d/%d", action.bskill, action.success); } chatWindow->chatLog(action); break; diff --git a/src/npc.cpp b/src/npc.cpp index 3bd4371b..3c142889 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -24,6 +24,9 @@ #include "npc.h" #include "animatedsprite.h" +#include "graphics.h" + +#include "gui/gui.h" class Spriteset; extern Spriteset *npcset; @@ -33,7 +36,8 @@ NPC *current_npc = 0; NPC::NPC(Uint16 id, Uint16 job, Map *map): Being(id, job, map) { - mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/npc.xml", job-100); + mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/npc.xml", + job - 100); } Being::Type @@ -42,6 +46,17 @@ NPC::getType() const return Being::NPC; } +void +NPC::drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) +{ + int px = mPx + offsetX; + int py = mPy + offsetY; + + graphics->setFont(speechFont); + graphics->setColor(gcn::Color(200, 200, 255)); + graphics->drawText(mName, px + 15, py + 30, gcn::Graphics::CENTER); +} + void NPC::talk() { diff --git a/src/npc.h b/src/npc.h index 3b61123b..cf5defbc 100644 --- a/src/npc.h +++ b/src/npc.h @@ -26,12 +26,18 @@ #include "being.h" +class Graphics; + class NPC : public Being { public: NPC(Uint16 id, Uint16 job, Map *map); - virtual Type getType() const; + virtual Type + getType() const; + + virtual void + drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY); void talk(); void nextDialog(); diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 05bbb6b3..ec6c1ee3 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -52,6 +52,9 @@ OpenGLGraphics::~OpenGLGraphics() bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) { + logger->log("Setting video mode %dx%d %s", + w, h, fs ? "fullscreen" : "windowed"); + int displayFlags = SDL_ANYFORMAT | SDL_OPENGL; mFullscreen = fs; diff --git a/src/player.cpp b/src/player.cpp index 0acf8262..63ed5455 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -28,6 +28,8 @@ #include "graphics.h" #include "log.h" +#include "resources/equipmentdb.h" + #include "utils/tostring.h" #include "gui/gui.h" @@ -35,9 +37,6 @@ Player::Player(Uint16 id, Uint16 job, Map *map): Being(id, job, map) { - // Load the weapon sprite. - // When there are more different weapons this should be moved to the - // setWeapon Method. setWeapon(0); } @@ -70,52 +69,72 @@ Player::setSex(Uint8 sex) if (sex != mSex) { - delete mSprites[BASE_SPRITE]; + Being::setSex(sex); + + // Reload base sprite + AnimatedSprite *newBaseSprite; if (sex == 0) { - mSprites[BASE_SPRITE] = new AnimatedSprite( - "graphics/sprites/player_male_base.xml", 0); + newBaseSprite = new AnimatedSprite( + "graphics/sprites/player_male_base.xml"); } else { - mSprites[BASE_SPRITE] = new AnimatedSprite( - "graphics/sprites/player_female_base.xml", 0); + newBaseSprite = new AnimatedSprite( + "graphics/sprites/player_female_base.xml"); } - Being::setSex(sex); - resetAnimations(); + delete mSprites[BASE_SPRITE]; + mSprites[BASE_SPRITE] = newBaseSprite; + + // Reload equipment + for (int i = 1; i < VECTOREND_SPRITE; i++) + { + if (i != HAIR_SPRITE && mEquipmentSpriteIDs.at(i) != 0) + { + AnimatedSprite *newEqSprite = new AnimatedSprite( + "graphics/sprites/" + EquipmentDB::get( + mEquipmentSpriteIDs.at(i))->getSprite(sex)); + delete mSprites[i]; + mSprites[i] = newEqSprite; + } + } } } - void Player::setWeapon(Uint16 weapon) { if (weapon != mWeapon) { - delete mSprites[WEAPON_SPRITE]; - mSprites[WEAPON_SPRITE] = NULL; + AnimatedSprite *newWeaponSprite = NULL; switch (weapon) { case 0: - mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-fist.xml", 0); + newWeaponSprite = + new AnimatedSprite("graphics/sprites/weapon-fist.xml"); break; case 1: - mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-dagger.xml", 0); + newWeaponSprite = + new AnimatedSprite("graphics/sprites/weapon-dagger.xml"); break; case 2: - mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-bow.xml", 0); + newWeaponSprite = + new AnimatedSprite("graphics/sprites/weapon-bow.xml"); break; case 3: - mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapon-scythe.xml", 0); + newWeaponSprite = + new AnimatedSprite("graphics/sprites/weapon-scythe.xml"); break; } + + delete mSprites[WEAPON_SPRITE]; + mSprites[WEAPON_SPRITE] = newWeaponSprite; } Being::setWeapon(weapon); } - void Player::setHairColor(Uint16 color) { @@ -128,7 +147,6 @@ Player::setHairColor(Uint16 color) delete mSprites[HAIR_SPRITE]; mSprites[HAIR_SPRITE] = newHairSprite; - resetAnimations(); setAction(mAction); } @@ -148,7 +166,6 @@ Player::setHairStyle(Uint16 style) delete mSprites[HAIR_SPRITE]; mSprites[HAIR_SPRITE] = newHairSprite; - resetAnimations(); setAction(mAction); } @@ -157,55 +174,35 @@ Player::setHairStyle(Uint16 style) } void -Player::setVisibleEquipment(Uint8 slot, Uint8 id) +Player::setVisibleEquipment(Uint8 slot, int id) { - // Translate eAthena specific slot - Uint8 position = 0; - switch (slot) { - case 3: - position = BOTTOMCLOTHES_SPRITE; - break; - case 4: - position = HAT_SPRITE; - break; - case 5: - position = TOPCLOTHES_SPRITE; - break; - } - // id = 0 means unequip if (id == 0) { - delete mSprites[position]; - mSprites[position] = NULL; + delete mSprites[slot]; + mSprites[slot] = NULL; } else { - char stringId[4]; - sprintf(stringId, "%03i", id); + AnimatedSprite *equipmentSprite; + + if (mSex == 0) + { + equipmentSprite = new AnimatedSprite( + "graphics/sprites/" + EquipmentDB::get(id)->getSprite(0)); + } + else { + equipmentSprite = new AnimatedSprite( + "graphics/sprites/" + EquipmentDB::get(id)->getSprite(1)); + } - AnimatedSprite *equipmentSprite = new AnimatedSprite( - "graphics/sprites/item" + toString(stringId) + ".xml", 0); equipmentSprite->setDirection(getSpriteDirection()); - delete mSprites[position]; - mSprites[position] = equipmentSprite; - resetAnimations(); + delete mSprites[slot]; + mSprites[slot] = equipmentSprite; setAction(mAction); } Being::setVisibleEquipment(slot, id); } - -void -Player::resetAnimations() -{ - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i] != NULL) - { - mSprites[i]->reset(); - } - } -} diff --git a/src/player.h b/src/player.h index 3c061be6..b062a55f 100644 --- a/src/player.h +++ b/src/player.h @@ -26,12 +26,14 @@ #include "being.h" -#include - class Graphics; class Map; -class AnimatedSprite; +/** + * A player being. Players have their name drawn beneath them. This class also + * implements player-specific loading of base sprite, hair sprite and equipment + * sprites. + */ class Player : public Being { public: @@ -56,18 +58,10 @@ class Player : public Being setHairStyle(Uint16 style); virtual void - setVisibleEquipment(Uint8 slot, Uint8 id); + setVisibleEquipment(Uint8 slot, int id); virtual void setWeapon(Uint16 weapon); - - private: - /** - * Resets all animations associated with this player. This is used to - * synchronize the animations after a new one has been added. - */ - void - resetAnimations(); }; #endif diff --git a/src/resources/equipmentdb.cpp b/src/resources/equipmentdb.cpp new file mode 100644 index 00000000..78ae3b6a --- /dev/null +++ b/src/resources/equipmentdb.cpp @@ -0,0 +1,158 @@ +/* + * The Mana World + * Copyright 2006 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: + */ + +#include "equipmentdb.h" + +#include "resourcemanager.h" + +#include "../log.h" + +#include "../utils/dtor.h" +#include "../utils/xml.h" + +namespace +{ + EquipmentDB::EquipmentInfos mEquipmentInfos; + EquipmentInfo mUnknown; + bool mLoaded = false; +} + +void +EquipmentDB::load() +{ + logger->log("Initializing equipment database..."); + mUnknown.setSprite("error.xml", 0); + mUnknown.setSprite("error.xml", 1); + + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *data = (char*)resman->loadFile("equipment.xml", size); + + if (!data) + { + logger->error("Equipment Database: Could not find equipment.xml!"); + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + logger->error("Equipment Database: Error while parsing equipment database (equipment.xml)!"); + } + + xmlNodePtr rootNode = xmlDocGetRootElement(doc); + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "equipments")) + { + logger->error("Equipment Database: equipment.xml is not a valid database file!"); + } + + //iterate s + for ( xmlNodePtr equipmentNode = rootNode->xmlChildrenNode; + equipmentNode != NULL; + equipmentNode = equipmentNode->next) + { + + if (!xmlStrEqual(equipmentNode->name, BAD_CAST "equipment")) + { + continue; + } + + EquipmentInfo *currentInfo = new EquipmentInfo(); + + currentInfo->setSlot (XML::getProperty(equipmentNode, "slot", 0)); + + //iterate s + for ( xmlNodePtr spriteNode = equipmentNode->xmlChildrenNode; + spriteNode != NULL; + spriteNode = spriteNode->next) + { + if (!xmlStrEqual(spriteNode->name, BAD_CAST "sprite")) + { + continue; + } + + std::string gender = XML::getProperty(spriteNode, "gender", "unisex"); + std::string filename = (const char*) spriteNode->xmlChildrenNode->content; + + if (gender == "male" || gender == "unisex") + { + currentInfo->setSprite(filename, 0); + } + + if (gender == "female" || gender == "unisex") + { + currentInfo->setSprite(filename, 1); + } + } + + setEquipment( XML::getProperty(equipmentNode, "id", 0), + currentInfo); + } + + mLoaded = true; +} + +void +EquipmentDB::unload() +{ + // kill EquipmentInfos + for_each ( mEquipmentInfos.begin(), mEquipmentInfos.end(), + make_dtor(mEquipmentInfos)); + mEquipmentInfos.clear(); + + mLoaded = false; +} + +EquipmentInfo* +EquipmentDB::get(int id) +{ + if (!mLoaded) { + logger->error("Error: Equipment database used before initialization!"); + } + + EquipmentInfoIterator i = mEquipmentInfos.find(id); + + if (i == mEquipmentInfos.end() ) + { + logger->log("EquipmentDB: Error, unknown equipment ID# %d", id); + return &mUnknown; + } + else + { + return i->second; + } +} + +void +EquipmentDB::setEquipment(int id, EquipmentInfo* equipmentInfo) +{ + if (mEquipmentInfos.find(id) != mEquipmentInfos.end()) { + logger->log("Warning: Equipment Piece with ID %d defined multiple times", + id); + delete equipmentInfo; + } + else { + mEquipmentInfos[id] = equipmentInfo; + }; +} diff --git a/src/resources/equipmentdb.h b/src/resources/equipmentdb.h new file mode 100644 index 00000000..b8618f5f --- /dev/null +++ b/src/resources/equipmentdb.h @@ -0,0 +1,52 @@ +/* + * The Mana World + * Copyright 2006 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: + */ + +#ifndef _TMW_EQUIPMENT_DB_H +#define _TMW_EQUIPMENT_DB_H + +#include + +#include "equipmentinfo.h" + +namespace EquipmentDB +{ + /** + * Loads the equipment info from Items.xml + */ + void load(); + + /** + * Frees equipment data + */ + void unload(); + + void setEquipment(int id, EquipmentInfo* equipmentInfo); + + EquipmentInfo* get(int id); + + // Equipment database types + typedef std::map EquipmentInfos; + typedef EquipmentInfos::iterator EquipmentInfoIterator; +} + +#endif diff --git a/src/resources/equipmentinfo.h b/src/resources/equipmentinfo.h new file mode 100644 index 00000000..93a1cb42 --- /dev/null +++ b/src/resources/equipmentinfo.h @@ -0,0 +1,52 @@ +/* + * The Mana World + * Copyright 2006 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: + */ + +#ifndef _TMW_EQUIPMENTINFO_H_ +#define _TMW_EQUIPMENTINFO_H_ + +#include +#include + +class EquipmentInfo +{ + public: + EquipmentInfo(): + mSlot (0) + { + }; + + void + setSlot (int slot) { mSlot = slot; }; + + const std::string& + getSprite(int gender) {return animationFiles[gender]; }; + + void + setSprite(std::string animationFile, int gender) {animationFiles[gender] = animationFile; }; + + private: + int mSlot; //not used at the moment but maybe useful on our own server + std::map animationFiles; +}; + +#endif diff --git a/src/resources/image.cpp b/src/resources/image.cpp index eb3a2409..48818f6f 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -68,9 +68,17 @@ Image* Image::load(void *buffer, unsigned int bufferSize, { // Load the raw file data from the buffer in an RWops structure SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize); + SDL_Surface *tmpImage; // Use SDL_Image to load the raw image data and have it free the data - SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); + if (!idPath.compare(idPath.length() - 4, 4, ".tga")) + { + tmpImage = IMG_LoadTyped_RW(rw, 1, const_cast("TGA")); + } + else + { + tmpImage = IMG_Load_RW(rw, 1); + } if (tmpImage == NULL) { logger->log("Error, image load failed: %s", IMG_GetError()); diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp new file mode 100644 index 00000000..b91e34cc --- /dev/null +++ b/src/resources/itemdb.cpp @@ -0,0 +1,170 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: + */ + +#include "itemdb.h" + +#include + +#include "iteminfo.h" +#include "resourcemanager.h" + +#include "../log.h" + +#include "../utils/dtor.h" +#include "../utils/xml.h" + +namespace +{ + ItemDB::ItemInfos mItemInfos; + ItemInfo mUnknown; +} + + +void ItemDB::load() +{ + logger->log("Initializing item database..."); + mUnknown.setName("Unknown item"); + + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *data = (char*)resman->loadFile("items.xml", size); + + if (!data) { + logger->error("ItemDB: Could not find items.xml!"); + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + logger->error("ItemDB: Error while parsing item database (items.xml)!"); + } + + xmlNodePtr node = xmlDocGetRootElement(doc); + if (!node || !xmlStrEqual(node->name, BAD_CAST "items")) + { + logger->error("ItemDB: items.xml is not a valid database file!"); + } + + for (node = node->xmlChildrenNode; node != NULL; node = node->next) + { + if (!xmlStrEqual(node->name, BAD_CAST "item")) { + continue; + } + + int id = XML::getProperty(node, "id", 0); + int art = XML::getProperty(node, "art", 0); + int type = XML::getProperty(node, "type", 0); + int weight = XML::getProperty(node, "weight", 0); + int slot = XML::getProperty(node, "slot", 0); + + std::string name = XML::getProperty(node, "name", ""); + std::string image = XML::getProperty(node, "image", ""); + std::string description = XML::getProperty(node, "description", ""); + std::string effect = XML::getProperty(node, "effect", ""); + + if (id && name != "") + { + ItemInfo *itemInfo = new ItemInfo(); + itemInfo->setImage(image); + itemInfo->setArt(art); + itemInfo->setName(name); + itemInfo->setDescription(description); + itemInfo->setEffect(effect); + itemInfo->setType(type); + itemInfo->setWeight(weight); + itemInfo->setSlot(slot); + mItemInfos[id] = itemInfo; + } + + + if (id == 0) + { + logger->log("ItemDB: An item has no ID in items.xml!"); + } + if (name == "") + { + logger->log("ItemDB: Missing name for item %d!", id); + } + + if (image == "") + { + logger->log("ItemDB: Missing image parameter for item: %i. %s", + id, name.c_str()); + } + /* + if (art == 0) + { + logger->log("Item Manager: Missing art parameter for item: %i. %s", + id, name.c_str()); + } + if (description == "") + { + logger->log("ItemDB: Missing description parameter for item: %i. %s", + id, name.c_str()); + } + if (effect == "") + { + logger->log("ItemDB: Missing effect parameter for item: %i. %s", + id, name.c_str()); + } + if (type == 0) + { + logger->log("Item Manager: Missing type parameter for item: %i. %s", + id, name.c_str()); + } + */ + if (weight == 0) + { + logger->log("Item Manager: Missing weight parameter for item: %i. %s", + id, name.c_str()); + } + /* + if (slot == 0) + { + logger->log("Item Manager: Missing slot parameter for item: %i. %s", + id, name.c_str()); + } + */ + } + + xmlFreeDoc(doc); +} + +void ItemDB::unload() +{ + for (ItemInfoIterator i = mItemInfos.begin(); i != mItemInfos.end(); i++) + { + delete i->second; + } + mItemInfos.clear(); +} + +const ItemInfo& +ItemDB::get(int id) +{ + ItemInfoIterator i = mItemInfos.find(id); + + return (i != mItemInfos.end()) ? *(i->second) : mUnknown; +} diff --git a/src/resources/itemdb.h b/src/resources/itemdb.h new file mode 100644 index 00000000..5922984a --- /dev/null +++ b/src/resources/itemdb.h @@ -0,0 +1,53 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: itemdb.h 2650 2006-09-03 15:00:47Z b_lindeijer $ + */ + +#ifndef _TMW_ITEM_MANAGER_H +#define _TMW_ITEM_MANAGER_H + +#include "iteminfo.h" + +#include + +/** + * The namespace that holds the item information + */ +namespace ItemDB +{ + /** + * Loads the item data from Items.xml + */ + void load(); + + /** + * Frees item data + */ + void unload(); + + const ItemInfo& get(int id); + + // Items database + typedef std::map ItemInfos; + typedef ItemInfos::iterator ItemInfoIterator; +} + +#endif diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index 9a04bb2e..e4f851bb 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -33,8 +33,6 @@ class Image; */ class ItemInfo { - friend class ItemManager; - public: /** * Constructor. @@ -49,6 +47,11 @@ class ItemInfo { } + /** + * Destructor. + */ + ~ItemInfo(); + void setArt(short art) { mArt = art; } @@ -101,11 +104,6 @@ class ItemInfo getSlot() const { return mSlot; } protected: - /** - * Destructor. - */ - ~ItemInfo(); - std::string mImageName; /* TODO (BL): I do not think the item info should keep a reference to diff --git a/src/resources/itemmanager.cpp b/src/resources/itemmanager.cpp deleted file mode 100644 index 7d0b13f2..00000000 --- a/src/resources/itemmanager.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "itemmanager.h" - -#include - -#include "iteminfo.h" -#include "resourcemanager.h" - -#include "../log.h" - -#include "../utils/dtor.h" - -#define READ_PROP(node, prop, name, target, cast) \ - prop = xmlGetProp(node, BAD_CAST name); \ - if (prop) { \ - target = cast((const char*)prop); \ - xmlFree(prop); \ - } - -ItemManager::ItemManager() -{ - mUnknown.setName("Unknown item"); - - ResourceManager *resman = ResourceManager::getInstance(); - int size; - char *data = (char*)resman->loadFile("items.xml", size); - - if (!data) { - logger->error("Item Manager: Could not find items.xml!"); - } - - xmlDocPtr doc = xmlParseMemory(data, size); - free(data); - - if (!doc) - { - logger->error("Item Manager: Error while parsing item database (items.xml)!"); - } - - xmlNodePtr node = xmlDocGetRootElement(doc); - if (!node || !xmlStrEqual(node->name, BAD_CAST "items")) - { - logger->error("Item Manager: items.xml is not a valid database file!"); - } - - for (node = node->xmlChildrenNode; node != NULL; node = node->next) - { - int id = 0, art = 0, type = 0, weight = 0, slot = 0; - std::string name = "", description = "", effect = "", image = ""; - - if (!xmlStrEqual(node->name, BAD_CAST "item")) { - continue; - } - - xmlChar *prop = NULL; - READ_PROP(node, prop, "id", id, atoi); - READ_PROP(node, prop, "image", image, ); - READ_PROP(node, prop, "art", art, atoi); - READ_PROP(node, prop, "name", name, ); - READ_PROP(node, prop, "description", description, ); - READ_PROP(node, prop, "effect", effect, ); - READ_PROP(node, prop, "type", type, atoi); - READ_PROP(node, prop, "weight", weight, atoi); - READ_PROP(node, prop, "slot", slot, atoi); - - - if (id && name != "") - { - ItemInfo *itemInfo = new ItemInfo(); - itemInfo->setImage(image); - itemInfo->setArt(art); - itemInfo->setName(name); - itemInfo->setDescription(description); - itemInfo->setEffect(effect); - itemInfo->setType(type); - itemInfo->setWeight(weight); - itemInfo->setSlot(slot); - mItemInfos[id] = itemInfo; - } - - - if (id == 0) - { - logger->log("Item Manager: An item has no ID in items.xml!"); - } - if (name == "") - { - logger->log("Item Manager: An item has no name in items.xml!"); - } - - if (image == "") - { - logger->log("Item Manager: Missing image parameter for item: %i. %s", - id, name.c_str()); - } - /*if (art == 0) - { - logger->log("Item Manager: Missing art parameter for item: %i. %s", - id, name.c_str()); - }*/ - if (description == "") - { - logger->log("Item Manager: Missing description parameter for item: %i. %s", - id, name.c_str()); - } - if (effect == "") - { - logger->log("Item Manager: Missing effect parameter for item: %i. %s", - id, name.c_str()); - } - /*if (type == 0) - { - logger->log("Item Manager: Missing type parameter for item: %i. %s", - id, name.c_str()); - }*/ - if (weight == 0) - { - logger->log("Item Manager: Missing weight parameter for item: %i. %s", - id, name.c_str()); - } - if (slot == 0) - { - logger->log("Item Manager: Missing slot parameter for item: %i. %s", - id, name.c_str()); - } - - /*logger->log("Item: %i %i %i %s %s %i %i %i", id, - getImage(id), getArt(id), getName(id).c_str(), - getDescription(id).c_str(), getType(id), getWeight(id), - getSlot(id));*/ - } - - xmlFreeDoc(doc); -} - -ItemManager::~ItemManager() -{ - for (ItemInfoIterator i = mItemInfos.begin(); i != mItemInfos.end(); i++) - { - delete i->second; - } - mItemInfos.clear(); -} - -const ItemInfo& -ItemManager::getItemInfo(int id) -{ - ItemInfoIterator i = mItemInfos.find(id); - - return (i != mItemInfos.end()) ? *(i->second) : mUnknown; -} diff --git a/src/resources/itemmanager.h b/src/resources/itemmanager.h deleted file mode 100644 index b1f2b95c..00000000 --- a/src/resources/itemmanager.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_ITEM_MANAGER_H -#define _TMW_ITEM_MANAGER_H - -#include "iteminfo.h" - -#include - -/** - * Defines a class to load items database. - */ -class ItemManager -{ - public: - /** - * Constructor. - */ - ItemManager(); - - /** - * Destructor. - */ - ~ItemManager(); - - const ItemInfo& getItemInfo(int id); - - protected: - // Items database - typedef std::map ItemInfos; - typedef ItemInfos::iterator ItemInfoIterator; - ItemInfos mItemInfos; - ItemInfo mUnknown; -}; - -extern ItemManager *itemDb; - -#endif diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 2aea3dc5..09a6eb74 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -36,6 +36,7 @@ #include "../tileset.h" #include "../utils/tostring.h" +#include "../utils/xml.h" const unsigned int DEFAULT_TILE_WIDTH = 32; const unsigned int DEFAULT_TILE_HEIGHT = 32; @@ -205,10 +206,10 @@ MapReader::readMap(xmlNodePtr node, const std::string &path) prop = xmlGetProp(node, BAD_CAST "version"); xmlFree(prop); - int w = getProperty(node, "width", 0); - int h = getProperty(node, "height", 0); - int tilew = getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH); - int tileh = getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT); + int w = XML::getProperty(node, "width", 0); + int h = XML::getProperty(node, "height", 0); + int tilew = XML::getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH); + int tileh = XML::getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT); int layerNr = 0; Map *map = new Map(w, h, tilew, tileh); @@ -308,7 +309,7 @@ MapReader::readLayer(xmlNodePtr node, Map *map, int layer) int binLen; unsigned char *binData = - php_base64_decode(charData, strlen((char*)charData), &binLen); + php3_base64_decode(charData, strlen((char*)charData), &binLen); delete[] charData; @@ -354,7 +355,7 @@ MapReader::readLayer(xmlNodePtr node, Map *map, int layer) if (!xmlStrEqual(n2->name, BAD_CAST "tile")) continue; - int gid = getProperty(n2, "gid", -1); + int gid = XML::getProperty(n2, "gid", -1); map->setTileWithGid(x, y, layer, gid); x++; @@ -387,9 +388,9 @@ MapReader::readTileset(xmlNodePtr node, return NULL; } - int firstGid = getProperty(node, "firstgid", 0); - int tw = getProperty(node, "tilewidth", map->getTileWidth()); - int th = getProperty(node, "tileheight", map->getTileHeight()); + int firstGid = XML::getProperty(node, "firstgid", 0); + int tw = XML::getProperty(node, "tilewidth", map->getTileWidth()); + int th = XML::getProperty(node, "tileheight", map->getTileHeight()); for (node = node->xmlChildrenNode; node; node = node->next) { if (!xmlStrEqual(node->name, BAD_CAST "image")) @@ -422,16 +423,3 @@ MapReader::readTileset(xmlNodePtr node, return NULL; } - -int -MapReader::getProperty(xmlNodePtr node, const char* name, int def) -{ - int &ret = def; - - xmlChar *prop = xmlGetProp(node, BAD_CAST name); - if (prop) { - ret = atoi((char*)prop); - xmlFree(prop); - } - return ret; -} diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp new file mode 100644 index 00000000..fb03f6c1 --- /dev/null +++ b/src/resources/monsterdb.cpp @@ -0,0 +1,151 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: + */ + +#include "monsterdb.h" + +#include "resourcemanager.h" + +#include "../log.h" + +#include "../utils/dtor.h" +#include "../utils/xml.h" + +namespace +{ + MonsterDB::MonsterInfos mMonsterInfos; + MonsterInfo mUnknown; +} + +void +MonsterDB::load() +{ + mUnknown.setSprite("error.xml"); + mUnknown.setName("unnamed"); + + logger->log("Initializing monster database..."); + + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *data = (char*)resman->loadFile("monsters.xml", size); + + if (!data) + { + logger->error("Monster Database: Could not find monsters.xml!"); + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) + { + logger->error("Monster Database: Error while parsing monster database (monsters.xml)!"); + } + + xmlNodePtr rootNode = xmlDocGetRootElement(doc); + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "monsters")) + { + logger->error("Monster Database: monster.xml is not a valid database file!"); + } + + //iterate s + for ( xmlNodePtr monsterNode = rootNode->xmlChildrenNode; + monsterNode != NULL; + monsterNode = monsterNode->next) + { + + if (!xmlStrEqual(monsterNode->name, BAD_CAST "monster")) + { + continue; + } + + MonsterInfo *currentInfo = new MonsterInfo(); + + currentInfo->setName (XML::getProperty(monsterNode, "name", "unnamed")); + + //iterate s and s + for ( xmlNodePtr spriteNode = monsterNode->xmlChildrenNode; + spriteNode != NULL; + spriteNode = spriteNode->next) + { + if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite")) + { + currentInfo->setSprite((const char*) spriteNode->xmlChildrenNode->content); + } + + if (xmlStrEqual(spriteNode->name, BAD_CAST "sound")) + { + std::string event = XML::getProperty(spriteNode, "event", ""); + const char *filename; + filename = (const char*) spriteNode->xmlChildrenNode->content; + + if (event == "hit") + { + currentInfo->addSound(EVENT_HIT, filename); + } + else if (event == "miss") + { + currentInfo->addSound(EVENT_MISS, filename); + } + else if (event == "hurt") + { + currentInfo->addSound(EVENT_HURT, filename); + } + else if (event == "die") + { + currentInfo->addSound(EVENT_DIE, filename); + } + else + { + logger->log("MonsterDB: Warning, sound effect %s for unknown event %s of monster %s", + filename, event.c_str(), currentInfo->getName().c_str()); + } + } + } + mMonsterInfos[XML::getProperty(monsterNode, "id", 0)] = currentInfo; + } +} + +void +MonsterDB::unload() +{ + for_each ( mMonsterInfos.begin(), mMonsterInfos.end(), + make_dtor(mMonsterInfos)); + mMonsterInfos.clear(); +} + + +const MonsterInfo& +MonsterDB::get (int id) +{ + MonsterInfoIterator i = mMonsterInfos.find(id); + + if (i == mMonsterInfos.end()) + { + logger->log("MonsterDB: Warning, unknown monster ID %d requested", id); + return mUnknown; + } + else + { + return *(i->second); + } +} diff --git a/src/resources/monsterdb.h b/src/resources/monsterdb.h new file mode 100644 index 00000000..b105665a --- /dev/null +++ b/src/resources/monsterdb.h @@ -0,0 +1,45 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: + */ + +#ifndef _TMW_MONSTER_DB_H +#define _TMW_MONSTER_DB_H + +#include + +#include "monsterinfo.h" + +namespace MonsterDB +{ + void + load(); + + void + unload(); + + const MonsterInfo& get (int id); + + typedef std::map MonsterInfos; + typedef MonsterInfos::iterator MonsterInfoIterator; +} + +#endif diff --git a/src/resources/monsterinfo.cpp b/src/resources/monsterinfo.cpp new file mode 100644 index 00000000..43aac32a --- /dev/null +++ b/src/resources/monsterinfo.cpp @@ -0,0 +1,70 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: monsterinfo.cpp 2650 2006-09-03 15:00:47Z b_lindeijer $ + */ + +#include "monsterinfo.h" + +#include "../utils/dtor.h" + +MonsterInfo::MonsterInfo(): + mSprite("error.xml") +{ + +} + +MonsterInfo::~MonsterInfo() +{ + //kill vectors in mSoundEffects + for_each ( mSounds.begin(), mSounds.end(), + make_dtor(mSounds)); + mSounds.clear(); +} + + +void +MonsterInfo::addSound (SoundEvent event, std::string filename) +{ + if (mSounds.find(event) == mSounds.end()) + { + mSounds[event] = new std::vector; + } + + mSounds[event]->push_back("sfx/" + filename); +} + + +std::string +MonsterInfo::getSound (SoundEvent event) const +{ + std::map* >::const_iterator i; + + i = mSounds.find(event); + + if (i == mSounds.end()) + { + return ""; + } + else + { + return i->second->at(rand()%i->second->size()); + } +} diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h new file mode 100644 index 00000000..413dafa0 --- /dev/null +++ b/src/resources/monsterinfo.h @@ -0,0 +1,74 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: monsterinfo.h 2650 2006-09-03 15:00:47Z b_lindeijer $ + */ + +#ifndef _TMW_MONSTERINFO_H_ +#define _TMW_MONSTERINFO_H_ + +#include +#include +#include + + +enum SoundEvent +{ + EVENT_HIT, + EVENT_MISS, + EVENT_HURT, + EVENT_DIE +}; + + +class MonsterInfo +{ + public: + MonsterInfo(); + + ~MonsterInfo(); + + void + setName(std::string name) { mName = name; } ; + + void + setSprite(std::string filename) { mSprite = filename; } + + void + addSound (SoundEvent event, std::string filename); + + const std::string& + getName () const { return mName; }; + + const std::string& + getSprite () const { return mSprite; }; + + std::string + getSound (SoundEvent event) const; + + private: + + std::string mName; + std::string mSprite; + + std::map* > mSounds; +}; + +#endif diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index bb51d023..45067302 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -32,6 +32,7 @@ #include "music.h" #include "soundeffect.h" #include "spriteset.h" +#include "spritedef.h" #include "../log.h" @@ -40,15 +41,33 @@ ResourceManager *ResourceManager::instance = NULL; ResourceManager::ResourceManager() { + logger->log("Initializing resource manager..."); } ResourceManager::~ResourceManager() { - // Release any remaining spritesets first because they depend on images + // Release any remaining spritedefs first because they depend on spritesets ResourceIterator iter = mResources.begin(); while (iter != mResources.end()) { - if (dynamic_cast(iter->second) != NULL) + if (dynamic_cast(iter->second) != 0) + { + cleanUp(iter->second); + ResourceIterator toErase = iter; + ++iter; + mResources.erase(toErase); + } + else + { + ++iter; + } + } + + // Release any remaining spritesets first because they depend on images + iter = mResources.begin(); + while (iter != mResources.end()) + { + if (dynamic_cast(iter->second) != 0) { cleanUp(iter->second); ResourceIterator toErase = iter; @@ -83,7 +102,7 @@ ResourceManager::cleanUp(Resource *res) bool ResourceManager::setWriteDir(const std::string &path) { - return (bool)PHYSFS_setWriteDir(path.c_str()); + return (bool) PHYSFS_setWriteDir(path.c_str()); } void @@ -96,7 +115,7 @@ ResourceManager::addToSearchPath(const std::string &path, bool append) bool ResourceManager::mkdir(const std::string &path) { - return (bool)PHYSFS_mkdir(path.c_str()); + return (bool) PHYSFS_mkdir(path.c_str()); } bool @@ -158,9 +177,9 @@ ResourceManager::get(const E_RESOURCE_TYPE &type, const std::string &idPath) free(buffer); - if (resource) { + if (resource) + { resource->incRef(); - mResources[idPath] = resource; } @@ -215,6 +234,27 @@ ResourceManager::getSpriteset(const std::string &imagePath, int w, int h) return spriteset; } +SpriteDef* +ResourceManager::getSprite(const std::string &path, int variant) +{ + std::stringstream ss; + ss << path << "[" << variant << "]"; + const std::string idPath = ss.str(); + + ResourceIterator resIter = mResources.find(idPath); + + if (resIter != mResources.end()) { + resIter->second->incRef(); + return dynamic_cast(resIter->second); + } + + SpriteDef *sprite = new SpriteDef(idPath, path, variant); + sprite->incRef(); + mResources[idPath] = sprite; + + return sprite; +} + void ResourceManager::release(const std::string &idPath) { @@ -246,18 +286,13 @@ ResourceManager::deleteInstance() void* ResourceManager::loadFile(const std::string &fileName, int &fileSize) { - // If the file doesn't exist indicate failure - if (!PHYSFS_exists(fileName.c_str())) { - logger->log("Warning: %s not found!", fileName.c_str()); - return NULL; - } - // Attempt to open the specified file using PhysicsFS PHYSFS_file *file = PHYSFS_openRead(fileName.c_str()); // If the handler is an invalid pointer indicate failure if (file == NULL) { - logger->log("Warning: %s failed to load!", fileName.c_str()); + logger->log("Warning: Failed to load %s: %s", + fileName.c_str(), PHYSFS_getLastError()); return NULL; } diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index 0086b167..d458f96e 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -34,6 +34,7 @@ class Image; class Music; class SoundEffect; class Spriteset; +class SpriteDef; /** * A class for loading and managing resources. @@ -113,21 +114,21 @@ class ResourceManager get(const E_RESOURCE_TYPE &type, const std::string &idPath); /** - * Convenience wrapper around ResourceManager::create for loading + * Convenience wrapper around ResourceManager::get for loading * images. */ Image* getImage(const std::string &idPath); /** - * Convenience wrapper around ResourceManager::create for loading + * Convenience wrapper around ResourceManager::get for loading * songs. */ Music* getMusic(const std::string &idPath); /** - * Convenience wrapper around ResourceManager::create for loading + * Convenience wrapper around ResourceManager::get for loading * samples. */ SoundEffect* @@ -137,7 +138,15 @@ class ResourceManager * Creates a spriteset based on the image referenced by the given * path and the supplied sprite sizes */ - Spriteset* getSpriteset(const std::string &imagePath, int w, int h); + Spriteset* + getSpriteset(const std::string &imagePath, int w, int h); + + /** + * Creates a sprite definition based on a given path and the supplied + * variant. + */ + SpriteDef* + getSprite(const std::string &path, int variant = 0); /** * Releases a resource, removing it from the set of loaded resources. diff --git a/src/resources/soundeffect.cpp b/src/resources/soundeffect.cpp index 3340e5ea..bb35218e 100644 --- a/src/resources/soundeffect.cpp +++ b/src/resources/soundeffect.cpp @@ -23,6 +23,8 @@ #include "soundeffect.h" +#include "../log.h" + SoundEffect::SoundEffect(const std::string &idPath, Mix_Chunk *soundEffect): Resource(idPath), mChunk(soundEffect) @@ -41,13 +43,18 @@ SoundEffect::load(void *buffer, unsigned int bufferSize, // Load the raw file data from the buffer in an RWops structure SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize); - // Use Mix_LoadWAV_RW to load the raw music data - Mix_Chunk *tmpSoundEffect = Mix_LoadWAV_RW(rw, 0); - - // Now free the SDL_RWops data - SDL_FreeRW(rw); + // Load the music data and free the RWops structure + Mix_Chunk *tmpSoundEffect = Mix_LoadWAV_RW(rw, 1); - return new SoundEffect(idPath, tmpSoundEffect); + if (tmpSoundEffect) + { + return new SoundEffect(idPath, tmpSoundEffect); + } + else + { + logger->log("Error while loading sound effect (%s)", idPath.c_str()); + return NULL; + } } bool diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp new file mode 100644 index 00000000..bd273b3b --- /dev/null +++ b/src/resources/spritedef.cpp @@ -0,0 +1,381 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "spritedef.h" + +#include "../animation.h" +#include "../action.h" +#include "../graphics.h" +#include "../log.h" + +#include "resourcemanager.h" +#include "spriteset.h" +#include "image.h" + +#include "../utils/xml.h" + +SpriteDef::SpriteDef(const std::string &idPath, + const std::string &file, int variant): + Resource(idPath), + mAction(NULL), + mDirection(DIRECTION_DOWN), + mLastTime(0) +{ + load(file, variant); +} + +Action* +SpriteDef::getAction(SpriteAction action) const +{ + Actions::const_iterator i = mActions.find(action); + + if (i == mActions.end()) + { + logger->log("Warning: no action \"%u\" defined!", action); + return NULL; + } + + return i->second; +} + +void +SpriteDef::load(const std::string &animationFile, int variant) +{ + int size; + ResourceManager *resman = ResourceManager::getInstance(); + char *data = (char*) resman->loadFile(animationFile.c_str(), size); + + if (!data) { + logger->error("Animation: Could not find " + animationFile + "!"); + } + + xmlDocPtr doc = xmlParseMemory(data, size); + free(data); + + if (!doc) { + logger->error( + "Animation: Error while parsing animation definition file!"); + } + + xmlNodePtr node = xmlDocGetRootElement(doc); + if (!node || !xmlStrEqual(node->name, BAD_CAST "sprite")) { + logger->error( + "Animation: this is not a valid animation definition file!"); + } + + // Get the variant + int variant_num = XML::getProperty(node, "variants", 0); + int variant_offset = 0; + + if (variant_num > 0 && variant < variant_num) + { + variant_offset = variant * XML::getProperty(node, "variant_offset", 0); + } + + for (node = node->xmlChildrenNode; node != NULL; node = node->next) + { + if (xmlStrEqual(node->name, BAD_CAST "imageset")) + { + loadImageSet(node); + } + else if (xmlStrEqual(node->name, BAD_CAST "action")) + { + loadAction(node, variant_offset); + } + else if (xmlStrEqual(node->name, BAD_CAST "include")) + { + includeSprite(node); + } + } + + xmlFreeDoc(doc); + + // Complete missing actions + substituteAction(ACTION_STAND, ACTION_DEFAULT); + substituteAction(ACTION_WALK, ACTION_STAND); + substituteAction(ACTION_WALK, ACTION_RUN); + substituteAction(ACTION_ATTACK, ACTION_STAND); + substituteAction(ACTION_ATTACK_SWING, ACTION_ATTACK); + substituteAction(ACTION_ATTACK_STAB, ACTION_ATTACK_SWING); + substituteAction(ACTION_ATTACK_BOW, ACTION_ATTACK_STAB); + substituteAction(ACTION_ATTACK_THROW, ACTION_ATTACK_SWING); + substituteAction(ACTION_CAST_MAGIC, ACTION_ATTACK_SWING); + substituteAction(ACTION_USE_ITEM, ACTION_CAST_MAGIC); + substituteAction(ACTION_SIT, ACTION_STAND); + substituteAction(ACTION_SLEEP, ACTION_SIT); + substituteAction(ACTION_HURT, ACTION_STAND); + substituteAction(ACTION_DEAD, ACTION_HURT); +} + +void +SpriteDef::loadImageSet(xmlNodePtr node) +{ + int width = XML::getProperty(node, "width", 0); + int height = XML::getProperty(node, "height", 0); + std::string name = XML::getProperty(node, "name", ""); + std::string imageSrc = XML::getProperty(node, "src", ""); + + ResourceManager *resman = ResourceManager::getInstance(); + Spriteset *spriteset = resman->getSpriteset(imageSrc, width, height); + + if (!spriteset) + { + logger->error("Couldn't load imageset!"); + } + + mSpritesets[name] = spriteset; +} + +void +SpriteDef::loadAction(xmlNodePtr node, int variant_offset) +{ + const std::string actionName = XML::getProperty(node, "name", ""); + const std::string imagesetName = XML::getProperty(node, "imageset", ""); + + SpritesetIterator si = mSpritesets.find(imagesetName); + if (si == mSpritesets.end()) + { + logger->log("Warning: imageset \"%s\" not defined in %s", + imagesetName.c_str(), getIdPath().c_str()); + return; + } + Spriteset *imageset = si->second; + + SpriteAction actionType = makeSpriteAction(actionName); + if (actionType == ACTION_INVALID) + { + logger->log("Warning: Unknown action \"%s\" defined in %s", + actionName.c_str(), getIdPath().c_str()); + return; + } + Action *action = new Action(); + mActions[actionType] = action; + + // When first action set it as default direction + if (mActions.empty()) + { + mActions[ACTION_DEFAULT] = action; + } + + // Load animations + for (xmlNodePtr animationNode = node->xmlChildrenNode; + animationNode != NULL; + animationNode = animationNode->next) + { + if (xmlStrEqual(animationNode->name, BAD_CAST "animation")) + { + loadAnimation(animationNode, action, imageset, variant_offset); + } + } +} + +void +SpriteDef::loadAnimation(xmlNodePtr animationNode, + Action *action, Spriteset *imageset, + int variant_offset) +{ + std::string directionName = + XML::getProperty(animationNode, "direction", ""); + SpriteDirection directionType = makeSpriteDirection(directionName); + + if (directionType == DIRECTION_INVALID) + { + logger->log("Warning: Unknown direction \"%s\" used in %s", + directionName.c_str(), getIdPath().c_str()); + return; + } + + Animation *animation = new Animation(); + action->setAnimation(directionType, animation); + + // Get animation phases + for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode; + phaseNode != NULL; + phaseNode = phaseNode->next) + { + int delay = XML::getProperty(phaseNode, "delay", 0); + int offsetX = XML::getProperty(phaseNode, "offsetX", 0); + int offsetY = XML::getProperty(phaseNode, "offsetY", 0); + offsetY -= imageset->getHeight() - 32; + offsetX -= imageset->getWidth() / 2 - 16; + + if (xmlStrEqual(phaseNode->name, BAD_CAST "frame")) + { + int index = XML::getProperty(phaseNode, "index", -1); + + if (index < 0) + { + logger->log("No valid value for 'index'"); + continue; + } + + Image *img = imageset->get(index + variant_offset); + + if (!img) + { + logger->log("No image at index " + (index + variant_offset)); + continue; + } + + animation->addPhase(img, delay, offsetX, offsetY); + } + else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence")) + { + int start = XML::getProperty(phaseNode, "start", -1); + int end = XML::getProperty(phaseNode, "end", -1); + + if (start < 0 || end < 0) + { + logger->log("No valid value for 'start' or 'end'"); + continue; + } + + while (end >= start) + { + Image *img = imageset->get(start + variant_offset); + + if (!img) + { + logger->log("No image at index " + + (start + variant_offset)); + continue; + } + + animation->addPhase(img, delay, offsetX, offsetY); + start++; + } + } + else if (xmlStrEqual(phaseNode->name, BAD_CAST "end")) + { + animation->addTerminator(); + } + } // for phaseNode +} + +void +SpriteDef::includeSprite(xmlNodePtr includeNode) +{ + std::string filename = XML::getProperty(includeNode, "file", ""); + ResourceManager *resman = ResourceManager::getInstance(); + SpriteDef *sprite = resman->getSprite("graphics/sprites/" + filename); + + // TODO: Somehow implement actually including it + sprite->decRef(); +} + +void +SpriteDef::substituteAction(SpriteAction complete, SpriteAction with) +{ + if (mActions.find(complete) == mActions.end()) + { + Actions::iterator i = mActions.find(with); + if (i != mActions.end()) { + mActions[complete] = i->second; + } + } +} + +SpriteDef::~SpriteDef() +{ + for (SpritesetIterator i = mSpritesets.begin(); + i != mSpritesets.end(); ++i) + { + i->second->decRef(); + } +} + +SpriteAction +SpriteDef::makeSpriteAction(const std::string& action) +{ + if (action == "" || action == "default") { + return ACTION_DEFAULT; + } + if (action == "stand") { + return ACTION_STAND; + } + else if (action == "walk") { + return ACTION_WALK; + } + else if (action == "run") { + return ACTION_RUN; + } + else if (action == "attack") { + return ACTION_ATTACK; + } + else if (action == "attack_swing") { + return ACTION_ATTACK_SWING; + } + else if (action == "attack_stab") { + return ACTION_ATTACK_STAB; + } + else if (action == "attack_bow") { + return ACTION_ATTACK_BOW; + } + else if (action == "attack_throw") { + return ACTION_ATTACK_THROW; + } + else if (action == "cast_magic") { + return ACTION_CAST_MAGIC; + } + else if (action == "use_item") { + return ACTION_USE_ITEM; + } + else if (action == "sit") { + return ACTION_SIT; + } + else if (action == "sleep") { + return ACTION_SLEEP; + } + else if (action == "hurt") { + return ACTION_HURT; + } + else if (action == "dead") { + return ACTION_DEAD; + } + else { + return ACTION_INVALID; + } +} + +SpriteDirection +SpriteDef::makeSpriteDirection(const std::string& direction) +{ + if (direction == "" || direction == "default") { + return DIRECTION_DEFAULT; + } + else if (direction == "up") { + return DIRECTION_UP; + } + else if (direction == "left") { + return DIRECTION_LEFT; + } + else if (direction == "right") { + return DIRECTION_RIGHT; + } + else if (direction == "down") { + return DIRECTION_DOWN; + } + else { + return DIRECTION_INVALID; + }; +} diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h new file mode 100644 index 00000000..64414259 --- /dev/null +++ b/src/resources/spritedef.h @@ -0,0 +1,158 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_SPRITEDEF_H +#define _TMW_SPRITEDEF_H + +#include "resource.h" + +#include +#include + +#include + +class Action; +class Graphics; +class Spriteset; +struct AnimationPhase; +class Animation; + +enum SpriteAction +{ + ACTION_DEFAULT = 0, + ACTION_STAND, + ACTION_WALK, + ACTION_RUN, + ACTION_ATTACK, + ACTION_ATTACK_SWING, + ACTION_ATTACK_STAB, + ACTION_ATTACK_BOW, + ACTION_ATTACK_THROW, + ACTION_CAST_MAGIC, + ACTION_USE_ITEM, + ACTION_SIT, + ACTION_SLEEP, + ACTION_HURT, + ACTION_DEAD, + ACTION_INVALID +}; + +enum SpriteDirection +{ + DIRECTION_DEFAULT = 0, + DIRECTION_DOWN, + DIRECTION_UP, + DIRECTION_LEFT, + DIRECTION_RIGHT, + DIRECTION_INVALID +}; + +/** + * Defines a class to load an animation. + */ +class SpriteDef : public Resource +{ + public: + /** + * Constructor. + */ + SpriteDef(const std::string &idPath, + const std::string &file, int variant); + + /** + * Destructor. + */ + ~SpriteDef(); + + /** + * Returns the specified action. + */ + Action* + getAction(SpriteAction action) const; + + private: + /** + * Loads a sprite definition file. + */ + void + load(const std::string &file, int variant); + + /** + * Loads an imageset element. + */ + void + loadImageSet(xmlNodePtr node); + + /** + * Loads an action element. + */ + void + loadAction(xmlNodePtr node, int variant_offset); + + /** + * Loads an animation element. + */ + void + loadAnimation(xmlNodePtr animationNode, + Action *action, Spriteset *imageset, + int variant_offset); + + /** + * Include another sprite into this one. + */ + void + includeSprite(xmlNodePtr includeNode); + + /** + * When there are no animations defined for the action "complete", its + * animations become a copy of those of the action "with". + */ + void + substituteAction(SpriteAction complete, SpriteAction with); + + /** + * Converts a string into a SpriteAction enum. + */ + static SpriteAction + makeSpriteAction(const std::string &action); + + /** + * Converts a string into a SpriteDirection enum. + */ + static SpriteDirection + makeSpriteDirection(const std::string &direction); + + + typedef std::map Spritesets; + typedef Spritesets::iterator SpritesetIterator; + + typedef std::map Actions; + + Spritesets mSpritesets; + Actions mActions; + Action *mAction; + SpriteDirection mDirection; + int mLastTime; +}; + +#endif diff --git a/src/resources/spriteset.h b/src/resources/spriteset.h index c51e6a75..7f6b42df 100644 --- a/src/resources/spriteset.h +++ b/src/resources/spriteset.h @@ -32,7 +32,9 @@ class Image; /** - * Stores a complete set of sprites. + * Stores a set of subimages originating from a single image. + * + * TODO: Should probably be renamed to ImageSet or TileSet. */ class Spriteset : public Resource { @@ -40,7 +42,7 @@ class Spriteset : public Resource /* * Cuts the passed image in a grid of sub images. */ - Spriteset(const std::string& idPath, Image *img, int w, int h); + Spriteset(const std::string &idPath, Image *img, int w, int h); /** * Destructor. diff --git a/src/sound.cpp b/src/sound.cpp index 182be3d6..8ba8fe99 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -191,15 +191,15 @@ void Sound::fadeOutMusic(int ms) } } -void Sound::playSfx(const char *path) +void Sound::playSfx(const std::string &path) { - if (!mInstalled) return; + if (!mInstalled || path.length() == 0) return; ResourceManager *resman = ResourceManager::getInstance(); SoundEffect *sample = resman->getSoundEffect(path); if (sample) { + logger->log("Sound::playSfx() Playing: %s", path.c_str()); sample->play(0, 120); - logger->log("Sound::playSfx() Playing: %s", path); } } diff --git a/src/sound.h b/src/sound.h index 39901121..07db0587 100644 --- a/src/sound.h +++ b/src/sound.h @@ -26,6 +26,8 @@ #include +#include + /** Sound engine * * \ingroup CORE @@ -105,7 +107,7 @@ class Sound { * * \param path Full path to file */ - void playSfx(const char *path); + void playSfx(const std::string &path); private: bool mInstalled; diff --git a/src/sprite.h b/src/sprite.h index 282091cc..51811149 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -47,7 +47,7 @@ class Sprite * partly with the clipping rectangle support. */ virtual void - draw(Graphics *graphics, int offsetX, int offsetY) = 0; + draw(Graphics *graphics, int offsetX, int offsetY) const = 0; /** * Returns the pixel Y coordinate of the sprite. diff --git a/src/utils/wingettimeofday.h b/src/utils/wingettimeofday.h new file mode 100644 index 00000000..0f8b767a --- /dev/null +++ b/src/utils/wingettimeofday.h @@ -0,0 +1,111 @@ +/* + * The Mana World Server + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _TMWSERV_WINGETTIMEOFDAY_H_ +#define _TMWSERV_WINGETTIMEOFDAY_H_ + +#ifdef WIN32 + +#include + +/* + * the function gettimeofday() is available on UNIX but not on windows. + * this header defines a windows implementation as a + * GetSystemTimeAsFileTime() wrapper. + */ + +int gettimeofday(struct timeval* tv, void *tz) +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * gettimeofday.c + * by Mark Gates + * ------------------------------------------------------------------- + * A (hack) implementation of gettimeofday for Windows. + * Since I send sec/usec in UDP packets, this made the most sense. + * ------------------------------------------------------------------- */ +{ + FILETIME time; + double timed; + + GetSystemTimeAsFileTime( &time ); + + // Apparently Win32 has units of 1e-7 sec (tenths of microsecs) + // 4294967296 is 2^32, to shift high word over + // 11644473600 is the number of seconds between + // the Win32 epoch 1601-Jan-01 and the Unix epoch 1970-Jan-01 + // Tests found floating point to be 10x faster than 64bit int math. + + timed = ((time.dwHighDateTime * 4294967296e-7) - 11644473600.0) + + (time.dwLowDateTime * 1e-7); + + tv->tv_sec = (long) timed; + tv->tv_usec = (long) ((timed - tv->tv_sec) * 1e6); + + return 0; +} + + +#endif // WIN32 +#endif diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp new file mode 100644 index 00000000..7c917dc0 --- /dev/null +++ b/src/utils/xml.cpp @@ -0,0 +1,54 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "xml.h" + +namespace XML +{ + int + getProperty(xmlNodePtr node, const char* name, int def) + { + int &ret = def; + + xmlChar *prop = xmlGetProp(node, BAD_CAST name); + if (prop) { + ret = atoi((char*)prop); + xmlFree(prop); + } + + return ret; + } + + std::string + getProperty(xmlNodePtr node, const char *name, const std::string &def) + { + xmlChar *prop = xmlGetProp(node, BAD_CAST name); + if (prop) { + std::string val = (char*)prop; + xmlFree(prop); + return val; + } + + return def; + } +} diff --git a/src/utils/xml.h b/src/utils/xml.h new file mode 100644 index 00000000..54ed9951 --- /dev/null +++ b/src/utils/xml.h @@ -0,0 +1,46 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_XML_H +#define _TMW_XML_H + +#include + +#include + +namespace XML +{ + /** + * Gets an integer property from an xmlNodePtr. + */ + int + getProperty(xmlNodePtr node, const char *name, int def); + + /** + * Gets a string property from an xmlNodePtr. + */ + std::string + getProperty(xmlNodePtr node, const char *name, const std::string &def); +} + +#endif diff --git a/tmw.cbp b/tmw.cbp index b8931cf6..d36a8bd0 100644 --- a/tmw.cbp +++ b/tmw.cbp @@ -21,31 +21,35 @@ - - - - - - + + + + + - + - - - - - + + + + + + + + + + + + + + - + - + - + - + + + + + + + + + + + + + + + + + -- cgit v1.2.3-60-g2f50 From 4eec29ac0f6a9b05562ac0fbe3d4e5d7e82deeac Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Thu, 4 Jan 2007 02:20:38 +0000 Subject: Merged 0.0 changes from revision 2898 to 2988 to trunk. --- ChangeLog | 181 +++++++++++++++++++++++++++++++++ INSTALL | 2 +- NEWS | 8 +- README | 2 +- configure.ac | 3 - data/CMakeLists.txt | 9 -- data/Makefile.am | 9 +- data/graphics/CMakeLists.txt | 1 - data/graphics/Makefile.am | 2 +- data/graphics/images/CMakeLists.txt | 14 +-- data/graphics/images/Makefile.am | 14 +-- data/help/header.txt | 2 +- docs/INSTALL/ubuntu.txt | 43 ++++++++ docs/INSTALL/win32.txt | 5 +- src/CMakeLists.txt | 12 +-- src/Makefile.am | 12 +-- src/action.cpp | 66 ------------ src/action.h | 61 ----------- src/animatedsprite.cpp | 6 +- src/animatedsprite.h | 9 +- src/animation.cpp | 55 ---------- src/animation.h | 101 ------------------ src/base64.cpp | 149 --------------------------- src/base64.h | 37 ------- src/being.cpp | 33 +++--- src/being.h | 1 - src/engine.cpp | 32 +----- src/engine.h | 9 +- src/game.cpp | 4 +- src/gui/buy.cpp | 57 +++++------ src/gui/chargedialog.cpp | 1 + src/gui/listbox.cpp | 7 +- src/gui/listbox.h | 4 +- src/gui/sell.cpp | 3 +- src/gui/shop.cpp | 2 +- src/gui/shoplistbox.cpp | 142 ++++++++++---------------- src/gui/shoplistbox.h | 20 +--- src/gui/updatewindow.cpp | 175 +++++++++++++++++++------------ src/gui/updatewindow.h | 9 +- src/gui/viewport.cpp | 4 +- src/guichanfwd.h | 5 +- src/inventory.h | 7 ++ src/localplayer.cpp | 19 +++- src/localplayer.h | 17 +++- src/main.cpp | 20 ++-- src/main.h | 3 +- src/net/playerhandler.cpp | 16 +++ src/npc.cpp | 1 - src/resources/action.cpp | 67 ++++++++++++ src/resources/action.h | 61 +++++++++++ src/resources/animation.cpp | 53 ++++++++++ src/resources/animation.h | 99 ++++++++++++++++++ src/resources/equipmentdb.cpp | 3 + src/resources/image.cpp | 6 +- src/resources/itemdb.cpp | 8 ++ src/resources/itemdb.h | 6 +- src/resources/mapreader.cpp | 2 +- src/resources/monsterdb.cpp | 8 ++ src/resources/openglsdlimageloader.cpp | 3 +- src/resources/openglsdlimageloader.h | 3 +- src/resources/spritedef.cpp | 37 ++++--- src/resources/spritedef.h | 3 - src/resources/spriteset.cpp | 2 +- src/tmw.rc | 41 +++----- src/utils/base64.cpp | 149 +++++++++++++++++++++++++++ src/utils/base64.h | 37 +++++++ src/utils/wingettimeofday.h | 8 +- src/winver.h | 6 ++ tmw.cbp | 72 ++++++------- 69 files changed, 1139 insertions(+), 929 deletions(-) create mode 100644 docs/INSTALL/ubuntu.txt delete mode 100644 src/action.cpp delete mode 100644 src/action.h delete mode 100644 src/animation.cpp delete mode 100644 src/animation.h delete mode 100644 src/base64.cpp delete mode 100644 src/base64.h create mode 100644 src/resources/action.cpp create mode 100644 src/resources/action.h create mode 100644 src/resources/animation.cpp create mode 100644 src/resources/animation.h create mode 100644 src/utils/base64.cpp create mode 100644 src/utils/base64.h create mode 100644 src/winver.h (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index d2cc233c..d75d457a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -55,6 +55,187 @@ performs an attack and attack messages from the server are received and displayed. +2006-12-25 Bjørn Lindeijer + + * data/graphics/tiles/christmastree.png, data/maps/new_11-1.tmx.gz: + Added Christmas tree by Pauan. + * data/graphics/sprites/head-christmastree.xml: Fixed name of image. + * src/resources/spriteset.cpp: Fixed index check to prevent crashing. + * data/graphics/sprites/head-christmastreehat.png, + data/graphics/sprites/head-rangerhat.png, + data/graphics/sprites/head-christmastree.xml, + data/graphics/sprites/head-antlerhat.xml, + data/graphics/sprites/head-santabeardhat.xml, + data/graphics/sprites/head-santabeardhat.png, + data/graphics/sprites/head-rangerhat.xml: Updates to Pauan's recent + sprites by Pauan. + * data/items.xml: Fixes to descriptions and weights by Pauan. + +2006-12-24 Bjørn Lindeijer + + * src/gui/shoplistbox.cpp: Don't try to draw an icon when it is not + defined or failed to load properly. + * src/resources/image.cpp: Major rendering performance increase in + software mode, by not using RLE compression on loaded images while + most of the time, we're only drawing a small subimage of them. + * README, data/help/header.txt, NEWS: Filled in release dates. + +2006-12-23 Bjørn Lindeijer + + * configure.ac, data/graphics/items/Makefile.am, + data/graphics/items/CMakeLists.txt, data/graphics/images/Makefile.am, + data/graphics/images/CMakeLists.txt, + data/graphics/sprites/Makefile.am, + data/graphics/sprites/CMakeLists.txt, data/graphics/Makefile.am, + data/graphics/CMakeLists.txt, data/maps/Makefile.am, + data/maps/CMakeLists.txt, data/sfx/Makefile.am, + data/sfx/CMakeLists.txt, data/Makefile.am, data/CMakeLists.txt: + Removed database files, minimaps, items, monster sprites, maps and + sounds from the release. They will be released dynamically only. + * data/graphics/tiles/snow_x3.png: Added bottom of Christmas tree by + pauan. + * src/main.cpp, src/resources/itemdb.h, src/resources/monsterdb.cpp, + src/resources/itemdb.cpp, src/resources/equipmentdb.cpp: Load the + databases at the start of the LOGIN state, after the updates are + loaded. + +2006-12-22 Bjørn Lindeijer + + * data/graphics/items/armor-head-rangerhat.png, + data/graphics/items/generic-redstocking.png, + data/graphics/items/armor-head-christmastree.png, + data/graphics/items/armor-head-antlerhat.png, + data/graphics/items/armor-head-santabeardhat.png, + data/graphics/sprites/head-christmastreehat.png, + data/graphics/sprites/head-rangerhat.png, + data/graphics/sprites/head-christmastree.xml, + data/graphics/sprites/head-antlerhat.xml, + data/graphics/sprites/head-santabeardhat.xml, + data/graphics/sprites/head-antlerhat.png, + data/graphics/sprites/head-santabeardhat.png, + data/graphics/sprites/head-rangerhat.xml, data/items.xml, + data/equipment.xml, data/monsters.xml: Added new Christmas themed + headwear by Pauan. + * data/graphics/items/Makefile.am, data/graphics/items/CMakeLists.txt, + data/graphics/sprites/Makefile.am, + data/graphics/sprites/CMakeLists.txt, data/Makefile.am, + data/CMakeLists.txt: Updated Makefiles. + +2006-12-21 Bjørn Lindeijer + + * configure.ac, CMakeLists.txt, README, data/help/header.txt: Updated + version to 0.0.22. + +2006-12-18 Philipp Sehmisch + + * data/graphics/items/armor-chest-vnecksweater.png: New version of + the inventory icon for the V-neck sweater by Saphy. + +2006-12-17 Bjørn Lindeijer + + * src/gui/sell.cpp, src/gui/shoplistbox.h, src/gui/listbox.h, + src/gui/shop.cpp, src/gui/buy.cpp, src/gui/shoplistbox.cpp, + src/gui/listbox.cpp: Subclassed ShopListBox from ListBox to get rid of + some duplicated code, and fixed a problem with scrolling to the + current selection. Also aligned the text a bit better and put the + price in parenthesis. + +2006-12-16 Bjørn Lindeijer + + * src/gui/connection.cpp, src/gui/chargedialog.cpp: Fixed dialog + visibility. + * src/localplayer.cpp, src/game.cpp, src/localplayer.h: Fixed issues + with walking one tile too many and changing direction towards an + obstacle. + +2006-12-15 Philipp Sehmisch + + * data/graphics/tiles/desert1.png: Removed some unused legacy tiles and + added variant tiles for the cliffs. + +2006-12-14 Bjørn Lindeijer + + * src/game.cpp, src/engine.h, src/engine.cpp: Removed the rather + useless remaining draw function from the engine class. + * src/being.cpp, src/being.h: Fixed an issue with fading out damage + texts (they were sometimes fully opaque at the end of fading out). + +2006-12-12 Eugenio Favalli + + * The Mana World.dev, tmw.cbp: Updated project files. + * src/gui/updatewindow.cpp, src/gui/updatewindow.h, src/main.cpp: + Added Adler32 checksum for updates. + * src/net/playerhandler.cpp: Fixed crash when selecting an item after + death. + * data/items.xml: Fixed defense values for sweaters. + * src/net/playerhandler.cpp: Hide all NPC dialogs after death. + +2006-12-12 Bjørn Lindeijer + + * src/animatedsprite.h, src/CMakeLists.txt, src/animatedsprite.cpp, + src/resources/action.h, src/resources/animation.h, + src/resources/spritedef.cpp, src/resources/action.cpp, + src/resources/animation.cpp, src/resources/spritedef.h: Moved + Action, Animation and Frame (renamed from AnimationPhase) classes into + the resources directory, since they are part of the SpriteDef class. + * src/CMakeLists.txt, src/utils/base64.cpp, src/utils/base64.h, + src/Makefile.am, src/resources/mapreader.cpp: Moved base64 module into + utils directory. + * src/engine.cpp, src/npc.cpp: Cleaned up some unused stuff. + +2006-12-12 Philipp Sehmisch + + * data/sfx/bat-dying1.ogg, data/sfx/bat-hit1.ogg, + data/sfx/bow_shoot_1.ogg, data/sfx/fire-goblin-hit1.ogg + data/sfx/fire-goblin-hit2.ogg, data/sfx/fire-goblin-miss1.ogg, + data/sfx/fist-swish.ogg, data/sfx/flower-hit1.ogg, + data/sfx/flower-hit2.ogg, data/sfx/flower-miss1.ogg, + data/sfx/fluffy-hit1.ogg, data/sfx/fluffy-hit2.ogg, + data/sfx/fluffy-hit3.ogg, data/sfx/fluffy-hurt1.ogg, + data/sfx/fluffy-miss1.ogg, data/sfx/knife-hit1.ogg, + data/sfx/knife-miss1.ogg, data/sfx/levelup.ogg + data/sfx/scorpion-hit1.ogg, data/sfx/scorpion-hit2.ogg + data/sfx/scorpion-hit3.ogg, data/sfx/scorpion-hit4.ogg + data/sfx/scorpion-miss1.ogg, data/sfx/short-sword-hit1.ogg + data/sfx/short-sword-miss1.ogg, data/sfx/shroom-hit1.ogg + data/sfx/slime-hit1.ogg: + Normalized versions of sound effects by Cosmostrator. + +2006-12-11 Bjørn Lindeijer + + * src/gui/updatewindow.cpp: Fixed visibility of the update window. + +2006-12-11 Philipp Sehmisch + + * data/equipment.xml, data/items.xml, + data/graphics/sprites/chest-tnecksweater-male.png, + data/graphics/sprites/chest-tnecksweater-female.png, + data/graphics/sprites/chest-vnecksweater-male.png, + data/graphics/sprites/chest-vnecksweater-female.png, + data/graphics/sprites/chest-tnecksweater-male.xml, + data/graphics/sprites/chest-tnecksweater-female.xml, + data/graphics/sprites/chest-vnecksweater-male.xml, + data/graphics/sprites/chest-vnecksweater-female.xml, + data/graphics/sprites/Makefile.AM, + data/graphics/sprites/CMakeLists.txt, + data/graphics/items/armor-chest-vnecksweater.png, + data/graphics/items/armor-chest-tnecksweater.png, + data/graphics/items/armor-chest-woolsweater.png, + data/graphics/items/Makefile.AM, data/graphics/items/CMakeLists.txt: + Added new sweaters by Saphy. Info for server admins: Item IDs are 564 + for turtleneck (should already be in there) and 624 for v-neck. The + visible sprite IDs are 19 for turtleneck and 20 for v-neck. + +2006-12-11 Eugenio Favalli + + * src/main.h, src/tmw.rc, src/winver.h, The Mana World.dev, tmw.cbp: + Fixed windows binary version. + +2006-12-10 Eugenio Favalli + + * docs/INSTALL/win32.txt: Added more detailed instructions for Dev-C++ + users. + 2006-12-09 Eugenio Favalli * data/graphics/sprites/npcs.png: Added pirate NPC. diff --git a/INSTALL b/INSTALL index a4f269e1..5b3eb3f2 100644 --- a/INSTALL +++ b/INSTALL @@ -39,7 +39,7 @@ you to figure this out. ========================================== 1) Go to the directory you have extracted the source to. -2) If you checked out from CVS, run "./autogen.sh" to generate configure. +2) If you checked out from SVN, run "./autogen.sh" to generate configure. 3) Run "./configure" 4) Run "make" 5) Run "make install" as root diff --git a/NEWS b/NEWS index f3b586f8..9edd05b6 100644 --- a/NEWS +++ b/NEWS @@ -1,13 +1,17 @@ -0.0.22 (...) +0.0.22 (24 December 2006) - Added support for female-specific equipment graphics - Added support for monster sounds +- Added item icons to buy/sell dialogs +- Enhanced character select dialog to show equipment - Changed to new update host (http://updates.themanaworld.org) - Worked around a Guichan exception thrown for mice with many buttons - Changed mouse walk to keep following mouse while button is held down -- Extended font support for Ã¥ and Ã…. +- Extended font support for Ã¥ and Ã… +- Disabled RLE compression on all surfaces in software mode - Fixed joystick setting not to show disabled when it's actually enabled - Fixed money field to no longer hide below the bottom of the window - Fixed pathfinding to allow walking through beings when they block your path +- Fixed an issue with NPC dialogs staying open after player respawn 0.0.21.1 (30 October 2006) - Reload wallpaper after loading updates diff --git a/README b/README index 54a6dcaf..342524ec 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ THE MANA WORLD ============== - Version: 0.0.21.1 Date: 30/10/2006 + Version: 0.0.22 Date: 24/12/2006 Development team: diff --git a/configure.ac b/configure.ac index d32aee08..ca31930e 100755 --- a/configure.ac +++ b/configure.ac @@ -113,13 +113,10 @@ data/graphics/Makefile data/graphics/gui/Makefile data/graphics/images/Makefile data/graphics/images/ambient/Makefile -data/graphics/items/Makefile data/graphics/sprites/Makefile data/graphics/tiles/Makefile data/help/Makefile data/icons/Makefile -data/maps/Makefile -data/sfx/Makefile docs/Makefile ]) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index e60bfe30..3c482b49 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -3,12 +3,3 @@ SET(DATA_DIR ${PKG_DATADIR}/data) ADD_SUBDIRECTORY(graphics) ADD_SUBDIRECTORY(help) ADD_SUBDIRECTORY(icons) -ADD_SUBDIRECTORY(maps) -ADD_SUBDIRECTORY(sfx) - -SET(FILES - equipment.xml - items.xml - ) - -INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}) \ No newline at end of file diff --git a/data/Makefile.am b/data/Makefile.am index ed080d08..5a28f7c1 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,11 +1,4 @@ -SUBDIRS = graphics help icons maps sfx +SUBDIRS = graphics help icons tmwdatadir = $(pkgdatadir)/data - -tmwdata_DATA = \ - equipment.xml \ - items.xml - -EXTRA_DIST = \ - $(tmwdata_DATA) \ No newline at end of file diff --git a/data/graphics/CMakeLists.txt b/data/graphics/CMakeLists.txt index c569e04f..0fa9a7be 100644 --- a/data/graphics/CMakeLists.txt +++ b/data/graphics/CMakeLists.txt @@ -1,5 +1,4 @@ ADD_SUBDIRECTORY(gui) ADD_SUBDIRECTORY(images) -ADD_SUBDIRECTORY(items) ADD_SUBDIRECTORY(sprites) ADD_SUBDIRECTORY(tiles) diff --git a/data/graphics/Makefile.am b/data/graphics/Makefile.am index 19e95869..43354894 100644 --- a/data/graphics/Makefile.am +++ b/data/graphics/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = gui images items sprites tiles +SUBDIRS = gui images sprites tiles diff --git a/data/graphics/images/CMakeLists.txt b/data/graphics/images/CMakeLists.txt index f02cd2ea..a8b6ddbd 100644 --- a/data/graphics/images/CMakeLists.txt +++ b/data/graphics/images/CMakeLists.txt @@ -1,18 +1,8 @@ ADD_SUBDIRECTORY(ambient) SET(FILES - error.png + error.png login_wallpaper.png - minimap_new_1-1.png - minimap_new_14-1.png - minimap_new_15-1.png - minimap_new_16-1.png - minimap_new_2-1.png - minimap_new_3-1.png - minimap_new_5-1.png - minimap_new_7-1.png - minimap_new_9-1.png - minimap_new_17-1.png ) -INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/images) \ No newline at end of file +INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/images) diff --git a/data/graphics/images/Makefile.am b/data/graphics/images/Makefile.am index 00d9ed7e..be8593f6 100644 --- a/data/graphics/images/Makefile.am +++ b/data/graphics/images/Makefile.am @@ -4,17 +4,7 @@ imagesdir = $(pkgdatadir)/data/graphics/images images_DATA = \ error.png \ - login_wallpaper.png \ - minimap_new_1-1.png \ - minimap_new_2-1.png \ - minimap_new_3-1.png \ - minimap_new_5-1.png \ - minimap_new_7-1.png \ - minimap_new_9-1.png \ - minimap_new_14-1.png \ - minimap_new_15-1.png \ - minimap_new_16-1.png \ - minimap_new_17-1.png + login_wallpaper.png EXTRA_DIST = \ - $(images_DATA) \ No newline at end of file + $(images_DATA) diff --git a/data/help/header.txt b/data/help/header.txt index b292388a..4f4c9615 100644 --- a/data/help/header.txt +++ b/data/help/header.txt @@ -2,7 +2,7 @@ ##1 T H E M A N A W O R L D ##1 ========================================== - ##2Version:##6 0.0.21.1 ##2Date:##30 October 2006 + ##2Version:##6 0.0.22 ##2Date:##324 December 2006 ##2 Website: http://themanaworld.org diff --git a/docs/INSTALL/ubuntu.txt b/docs/INSTALL/ubuntu.txt new file mode 100644 index 00000000..cf830ccc --- /dev/null +++ b/docs/INSTALL/ubuntu.txt @@ -0,0 +1,43 @@ +How to build a .deb for TMW on Ubuntu +===================================== + +This documentation is for those who are interested in building the .deb files +of The Mana World. Most people do not need to do this, but can instead use the +repository. You can find information about how to use the repository on our +downloads page. + + +1. Installing the dependencies +============================== + +First of all you need a working compiler and package building environment. If +you don't have this yet, install the following packages: + + apt-get install gcc g++ dh-make fakeroot dpkg-dev build-essentials + +In order to compile The Mana World, you'll need the developer packages for +SDL, SDL_mixer, SDL_image, SDL_net, libxml2, libphysfs and libguichan0. + + apt-get install libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev ... + +(todo: add missing entries) +(todo: include information about installing Guichan development package) + + +2. Creating the .debs using DebHelper Tools +=========================================== + +Either download the source release of TMW that you want to build a package for, +or check out the appropriate version from Subversion, for example by using the +tag. + +Make sure the files in the debian directory are up to date. You can do this by +checking out the appropriate directory from Subversion (will be either +tmw/branches/0.0/debian or tmw/trunk/debian for the latest release). + +Now we can build the packages using the following command. + + fakeroot dpkg-buildpackage + +The packages will be created in the parent folder. + diff --git a/docs/INSTALL/win32.txt b/docs/INSTALL/win32.txt index ab2a429f..f438a7e7 100644 --- a/docs/INSTALL/win32.txt +++ b/docs/INSTALL/win32.txt @@ -45,7 +45,7 @@ the old stable version, so don't do that. Get Dev-C++ here: http://www.bloodshed.net/ -After you fetched it simply run and install. +After you have fetched it, simply run and install as prompted. 3. Installing the required libraries @@ -63,6 +63,9 @@ to remove anything the devpak might overlap before installing, for example the previous devpak.) Remember to copy the required dlls from your dll folder in the Dev-Cpp root directory, to the folder where you have your copy of The Mana World. You also have to add the SDL include folder in your C++ include paths. +If you're using Dev-C++, this means: Tools -> Compiler options -> +-> Directories -> C++ includes -> Browse... (browse to MinGW/include/SDL) -> +-> Add -> Ok. If you can't get the package or you are experiencing problems with it, just send me an email at elvenprogrammer@gmail.com or continue reading. (Coming to bug us on the IRC channel is a valid alternative too.) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0b93382..55109ec4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -214,10 +214,14 @@ SET(SRCS net/gameserver/internal.h net/gameserver/player.cpp net/gameserver/player.h + resources/action.cpp + resources/action.h resources/ambientoverlay.cpp resources/ambientoverlay.h resources/buddylist.cpp resources/buddylist.h + resources/animation.cpp + resources/animation.h resources/equipmentdb.cpp resources/equipmentdb.h resources/equipmentinfo.h @@ -251,18 +255,14 @@ SET(SRCS resources/spritedef.h resources/spritedef.cpp resources/spriteset.h + utils/base64.cpp + utils/base64.h utils/dtor.h utils/tostring.h utils/xml.cpp utils/xml.h - action.cpp - action.h animatedsprite.cpp animatedsprite.h - animation.cpp - animation.h - base64.cpp - base64.h being.cpp being.h beingmanager.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 1628df18..777cc30e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -179,8 +179,12 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ net/gameserver/internal.h \ net/gameserver/player.cpp \ net/gameserver/player.h \ + resources/action.cpp \ + resources/action.h \ resources/ambientoverlay.cpp \ resources/ambientoverlay.h \ + resources/animation.cpp \ + resources/animation.h \ resources/equipmentdb.cpp \ resources/equipmentdb.h \ resources/equipmentinfo.h \ @@ -216,18 +220,14 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ resources/spriteset.cpp \ resources/buddylist.h \ resources/buddylist.cpp \ + utils/base64.cpp \ + utils/base64.h \ utils/dtor.h \ utils/tostring.h \ utils/xml.cpp \ utils/xml.h \ - action.cpp \ - action.h \ animatedsprite.cpp \ animatedsprite.h \ - animation.cpp \ - animation.h \ - base64.cpp \ - base64.h \ being.cpp \ being.h \ beingmanager.cpp \ diff --git a/src/action.cpp b/src/action.cpp deleted file mode 100644 index 148ea105..00000000 --- a/src/action.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "action.h" - -#include - -#include "animation.h" -#include "utils/dtor.h" - - -Action::Action() -{ -} - -Action::~Action() -{ - std::for_each(mAnimations.begin(), mAnimations.end(), - make_dtor(mAnimations)); -} - -Animation* -Action::getAnimation(int direction) const -{ - Animations::const_iterator i = mAnimations.find(direction); - - // When the direction isn't defined, try the default - if (i == mAnimations.end()) - { - i = mAnimations.find(0); - } - - return (i == mAnimations.end()) ? NULL : i->second; -} - -void -Action::setAnimation(int direction, Animation *animation) -{ - // Set first direction as default direction - if (mAnimations.empty()) - { - mAnimations[0] = animation; - } - - mAnimations[direction] = animation; -} diff --git a/src/action.h b/src/action.h deleted file mode 100644 index 8d5e8d11..00000000 --- a/src/action.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_ACTION_H -#define _TMW_ACTION_H - -#include - -#include - -class Animation; - -/** - * An action consists of several animations, one for each direction. - */ -class Action -{ - public: - /** - * Constructor. - */ - Action(); - - /** - * Destructor. - */ - ~Action(); - - void - setAnimation(int direction, Animation *animation); - - Animation* - getAnimation(int direction) const; - - protected: - typedef std::map Animations; - typedef Animations::iterator AnimationIterator; - Animations mAnimations; -}; - -#endif diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index 46369c80..3d1979a9 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -23,14 +23,14 @@ #include "animatedsprite.h" -#include "animation.h" -#include "action.h" #include "graphics.h" #include "log.h" +#include "resources/action.h" +#include "resources/animation.h" +#include "resources/image.h" #include "resources/resourcemanager.h" #include "resources/spriteset.h" -#include "resources/image.h" #include "utils/xml.h" diff --git a/src/animatedsprite.h b/src/animatedsprite.h index 4e485f14..2257c0f0 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -29,8 +29,9 @@ #include #include +class Animation; class Graphics; -struct AnimationPhase; +struct Frame; /** * Animates a sprite by adding playback state. @@ -72,13 +73,13 @@ class AnimatedSprite /** * Inform the animation of the passed time so that it can output the - * correct animation phase. + * correct animation frame. */ void update(int time); /** - * Draw the current animation phase at the coordinates given in screen + * Draw the current animation frame at the coordinates given in screen * pixels. */ bool @@ -103,7 +104,7 @@ class AnimatedSprite SpriteDef *mSprite; /**< The sprite definition. */ Action *mAction; /**< The currently active action. */ Animation *mAnimation; /**< The currently active animation. */ - AnimationPhase *mFrame; /**< The currently active frame. */ + Frame *mFrame; /**< The currently active frame. */ std::string mAnimationFile; }; diff --git a/src/animation.cpp b/src/animation.cpp deleted file mode 100644 index 67fdae11..00000000 --- a/src/animation.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "animation.h" - -#include - -#include "utils/dtor.h" - -Animation::Animation(): - mDuration(0) -{ -} - -void -Animation::addPhase(Image *image, unsigned int delay, int offsetX, int offsetY) -{ - // Add new phase to animation list - AnimationPhase newPhase = { image, delay, offsetX, offsetY }; - - mAnimationPhases.push_back(newPhase); - mDuration += delay; -} - -void -Animation::addTerminator() -{ - addPhase(NULL, 0, 0, 0); -} - -bool -Animation::isTerminator(const AnimationPhase candidate) -{ - return (candidate.image == NULL); -} diff --git a/src/animation.h b/src/animation.h deleted file mode 100644 index 85e950d7..00000000 --- a/src/animation.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_ANIMATION_H -#define _TMW_ANIMATION_H - -#include - -#include - -class Image; -class Spriteset; - -/** - * A single frame in an animation, with a delay and an offset. - * - * TODO: Rename this struct to Frame - */ -struct AnimationPhase -{ - Image *image; - unsigned int delay; - int offsetX; - int offsetY; -}; - -/** - * An animation consists of several frames, each with their own delay and - * offset. - */ -class Animation -{ - public: - /** - * Constructor. - */ - Animation(); - - /** - * Appends a new animation at the end of the sequence - */ - void - addPhase(Image *image, unsigned int delay, int offsetX, int offsetY); - - /** - * Appends an animation terminator that states that the animation - * should not loop. - */ - void - addTerminator(); - - /** - * Returns the frame at the specified index. - */ - AnimationPhase* - getFrame(int index) { return &(mAnimationPhases[index]); } - - /** - * Returns the length of this animation in frames. - */ - unsigned int - getLength() const { return mAnimationPhases.size(); } - - /** - * Returns the duration of this animation. - */ - int - getDuration() const { return mDuration; } - - /** - * Determines whether the given animation frame is a terminator. - */ - static bool - isTerminator(const AnimationPhase phase); - - protected: - std::vector mAnimationPhases; - int mDuration; -}; - -#endif diff --git a/src/base64.cpp b/src/base64.cpp deleted file mode 100644 index 9a8f6356..00000000 --- a/src/base64.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP HTML Embedded Scripting Language Version 3.0 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2000 PHP Development Team (See Credits file) | - +----------------------------------------------------------------------+ - | This program is free software; you can redistribute it and/or modify | - | it under the terms of one of the following licenses: | - | | - | A) 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. | - | | - | B) the PHP License as published by the PHP Development Team and | - | included in the distribution in the file: LICENSE | - | | - | 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 both licenses referred to here. | - | If you did not, or have any questions about PHP licensing, please | - | contact core@php.net. | - +----------------------------------------------------------------------+ - | Author: Jim Winstead (jimw@php.net) | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include -#include - -#include "base64.h" - -static char base64_table[] = -{ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0' -}; -static char base64_pad = '='; - -unsigned char *php3_base64_encode(const unsigned char *string, int length, int *ret_length) { - const unsigned char *current = string; - int i = 0; - unsigned char *result = (unsigned char *)malloc(((length + 3 - length % 3) * 4 / 3 + 1) * sizeof(char)); - - while (length > 2) { /* keep going until we have less than 24 bits */ - result[i++] = base64_table[current[0] >> 2]; - result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; - result[i++] = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)]; - result[i++] = base64_table[current[2] & 0x3f]; - - current += 3; - length -= 3; /* we just handle 3 octets of data */ - } - - /* now deal with the tail end of things */ - if (length != 0) { - result[i++] = base64_table[current[0] >> 2]; - if (length > 1) { - result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; - result[i++] = base64_table[(current[1] & 0x0f) << 2]; - result[i++] = base64_pad; - } - else { - result[i++] = base64_table[(current[0] & 0x03) << 4]; - result[i++] = base64_pad; - result[i++] = base64_pad; - } - } - if(ret_length) { - *ret_length = i; - } - result[i] = '\0'; - return result; -} - -/* as above, but backwards. :) */ -unsigned char *php3_base64_decode(const unsigned char *string, int length, int *ret_length) { - const unsigned char *current = string; - int ch, i = 0, j = 0, k; - char *chp; - - unsigned char *result = (unsigned char *)malloc(length + 1); - - if (result == NULL) { - return NULL; - } - - /* run through the whole string, converting as we go */ - while ((ch = *current++) != '\0') { - if (ch == base64_pad) break; - - /* When Base64 gets POSTed, all pluses are interpreted as spaces. - This line changes them back. It's not exactly the Base64 spec, - but it is completely compatible with it (the spec says that - spaces are invalid). This will also save many people considerable - headache. - Turadg Aleahmad - */ - - if (ch == ' ') ch = '+'; - - chp = strchr(base64_table, ch); - if (chp == NULL) continue; - ch = chp - base64_table; - - switch(i % 4) { - case 0: - result[j] = ch << 2; - break; - case 1: - result[j++] |= ch >> 4; - result[j] = (ch & 0x0f) << 4; - break; - case 2: - result[j++] |= ch >>2; - result[j] = (ch & 0x03) << 6; - break; - case 3: - result[j++] |= ch; - break; - } - i++; - } - - k = j; - /* mop things up if we ended on a boundary */ - if (ch == base64_pad) { - switch(i % 4) { - case 0: - case 1: - free(result); - return NULL; - case 2: - k++; - case 3: - result[k++] = 0; - } - } - if(ret_length) { - *ret_length = j; - } - result[k] = '\0'; - return result; -} diff --git a/src/base64.h b/src/base64.h deleted file mode 100644 index ff20ac53..00000000 --- a/src/base64.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP HTML Embedded Scripting Language Version 3.0 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | - +----------------------------------------------------------------------+ - | This program is free software; you can redistribute it and/or modify | - | it under the terms of one of the following licenses: | - | | - | A) 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. | - | | - | B) the PHP License as published by the PHP Development Team and | - | included in the distribution in the file: LICENSE | - | | - | 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 both licenses referred to here. | - | If you did not, or have any questions about PHP licensing, please | - | contact core@php.net. | - +----------------------------------------------------------------------+ - | Author: Jim Winstead (jimw@php.net) | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#ifndef _TMW_BASE64_H -#define _TMW_BASE64_H - -extern unsigned char *php3_base64_encode(const unsigned char *, int, int *); -extern unsigned char *php3_base64_decode(const unsigned char *, int, int *); - -#endif /* _TMW_BASE64_H */ diff --git a/src/being.cpp b/src/being.cpp index 68c670fd..ac003d1c 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -65,7 +65,6 @@ Being::Being(Uint16 id, Uint16 job, Map *map): mHairStyle(0), mHairColor(0), mSpeechTime(0), mDamageTime(0), - mShowSpeech(false), mShowDamage(false), mPx(0), mPy(0), mSprites(VECTOREND_SPRITE, NULL), mEquipmentSpriteIDs(VECTOREND_SPRITE, 0) @@ -272,16 +271,14 @@ void Being::setSpeech(const std::string &text, Uint32 time) { mSpeech = text; - mSpeechTime = tick_time; - mShowSpeech = true; + mSpeechTime = 500; } void Being::setDamage(Sint16 amount, Uint32 time) { mDamage = amount ? toString(amount) : "miss"; - mDamageTime = tick_time; - mShowDamage = true; + mDamageTime = 300; } void @@ -443,17 +440,13 @@ Being::logic() nextStep(); } - // Determine whether speech should still be displayed - if (get_elapsed_time(mSpeechTime) > 5000) - { - mShowSpeech = false; - } + // Reduce the time that speech is still displayed + if (mSpeechTime > 0) + mSpeechTime--; - // Determine whether damage should still be displayed - if (get_elapsed_time(mDamageTime) > 3000) - { - mShowDamage = false; - } + // Reduce the time that damage is still displayed + if (mDamageTime > 0) + mDamageTime--; // Update pixel coordinates mPx = mX - 16 + getXOffset(); @@ -511,7 +504,7 @@ Being::drawSpeech(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) int py = mPy + offsetY; // Draw speech above this being - if (mShowSpeech) + if (mSpeechTime > 0) { graphics->setFont(speechFont); graphics->setColor(gcn::Color(255, 255, 255)); @@ -519,7 +512,7 @@ Being::drawSpeech(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) } // Draw damage above this being - if (mShowDamage && get_elapsed_time(mDamageTime) > 250) + if (mDamageTime > 0 && mDamageTime < 275) { // Selecting the right color if (mDamage == "miss") @@ -536,13 +529,13 @@ Being::drawSpeech(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) } int textY = (getType() == MONSTER) ? 32 : 70; - int ft = get_elapsed_time(mDamageTime) - 1500; - float a = (ft > 0) ? 1.0 - ft / 1500.0 : 1.0; + int ft = 150 - mDamageTime; + float a = (ft > 0) ? 1.0 - ft / 150.0 : 1.0; graphics->setColor(gcn::Color(255, 255, 255, (int)(255 * a))); graphics->drawText(mDamage, px + 16, - py - textY - get_elapsed_time(mDamageTime) / 100, + py - textY - (300 - mDamageTime) / 10, gcn::Graphics::CENTER); // Reset alpha value diff --git a/src/being.h b/src/being.h index f9287b65..bfd01568 100644 --- a/src/being.h +++ b/src/being.h @@ -368,7 +368,6 @@ class Being : public Sprite Uint16 mHairStyle, mHairColor; Uint32 mSpeechTime; Uint32 mDamageTime; - bool mShowSpeech, mShowDamage; Sint32 mPx, mPy; /**< Pixel coordinates */ std::vector mSprites; diff --git a/src/engine.cpp b/src/engine.cpp index 30f0097e..d2ce6d6f 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -54,42 +54,19 @@ extern Minimap *minimap; char itemCurrenyQ[10] = "0"; Spriteset *emotionset; -Spriteset *npcset; -std::vector weaponset; Engine::Engine(): mCurrentMap(NULL) { - // Load the sprite sets + // Load the emotion set ResourceManager *resman = ResourceManager::getInstance(); - - npcset = resman->getSpriteset("graphics/sprites/npcs.png", 50, 80); - emotionset = resman->getSpriteset("graphics/sprites/emotions.png", - 30, 32); - for (int i = 0; i < 2; i++) - { - Spriteset *tmp = ResourceManager::getInstance()->getSpriteset( - "graphics/sprites/weapon" + toString(i) + ".png", 64, 64); - if (!tmp) { - logger->error("Unable to load weaponset"); - } else { - weaponset.push_back(tmp); - } - } - - if (!npcset) logger->error("Unable to load NPC spriteset!"); + emotionset = resman->getSpriteset("graphics/sprites/emotions.png", 30, 32); if (!emotionset) logger->error("Unable to load emotions spriteset!"); } Engine::~Engine() { - // Delete sprite sets - npcset->decRef(); emotionset->decRef(); - - std::for_each(weaponset.begin(), weaponset.end(), - std::mem_fun(&Spriteset::decRef)); - weaponset.clear(); } void Engine::changeMap(const std::string &mapPath) @@ -142,8 +119,3 @@ void Engine::logic() beingManager->logic(); gui->logic(); } - -void Engine::draw(Graphics *graphics) -{ - gui->draw(); -} diff --git a/src/engine.h b/src/engine.h index 62e82a49..b16b7c13 100644 --- a/src/engine.h +++ b/src/engine.h @@ -26,11 +26,11 @@ #include -class Graphics; class Map; /** - * Game engine that does the main drawing. + * Game engine. Actually hardly does anything anymore except keeping track of + * the current map and loading the emotes. */ class Engine { @@ -60,11 +60,6 @@ class Engine */ void logic(); - /** - * Draws everything on the screen. - */ - void draw(Graphics *graphics); - private: Map *mCurrentMap; }; diff --git a/src/game.cpp b/src/game.cpp index f708fabf..2af13146 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -360,7 +360,7 @@ void Game::logic() get_elapsed_time(mDrawTime / 10) > mMinFrameTime) { frame++; - engine->draw(graphics); + gui->draw(); graphics->updateScreen(); mDrawTime += mMinFrameTime; @@ -662,7 +662,7 @@ void Game::handleInput() direction |= Being::RIGHT; } - player_node->walk(direction); + player_node->setWalkingDir(direction); // Target the nearest monster if 'a' pressed if (keys[SDLK_a]) diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 9fcf752b..102dd49e 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -85,7 +85,6 @@ BuyDialog::BuyDialog(): mShopItemList->setEventId("item"); mSlider->setEventId("slider"); - mShopItemList->addActionListener(this); mShopItemList->addSelectionListener(this); mSlider->addActionListener(this); @@ -112,7 +111,7 @@ void BuyDialog::setMoney(int amount) { mMoney = amount; mShopItemList->setPlayersMoney(amount); - mMoneyLabel->setCaption("Price : 0 GP / " + toString(mMoney) + " GP"); + mMoneyLabel->setCaption("Price: 0 GP / " + toString(mMoney) + " GP"); mMoneyLabel->adjustSize(); } @@ -129,7 +128,7 @@ void BuyDialog::reset() mDecreaseButton->setEnabled(false); mQuantityLabel->setCaption("0"); mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Price : 0 GP / " + toString(mMoney) + " GP"); + mMoneyLabel->setCaption("Price: 0 GP / " + toString(mMoney) + " GP"); mMoneyLabel->adjustSize(); mItemDescLabel->setCaption(""); mItemEffectLabel->setCaption(""); @@ -145,31 +144,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) { int selectedItem = mShopItemList->getSelected(); - if (eventId == "item") - { - // Reset amount of items and update labels - mAmountItems = 0; - mSlider->setValue(0); - mQuantityLabel->setCaption("0"); - mQuantityLabel->adjustSize(); - mMoneyLabel->setCaption("Price : 0 GP / " + toString(mMoney) + " GP"); - mMoneyLabel->adjustSize(); - - // Disable buttons for buying and decreasing - mBuyButton->setEnabled(false); - mDecreaseButton->setEnabled(false); - - // If no item was selected, none can be bought, otherwise - // calculate how many the player can afford - mMaxItems = (mShopItemList->getSelected() == -1) ? 0 : - mMoney / mShopItems->at(selectedItem).price; - - // When at least one item can be bought, enable the slider and the - // increase button - mIncreaseButton->setEnabled(mMaxItems > 0); - mSlider->setEnabled(mMaxItems > 0); - } - else if (eventId == "quit") + if (eventId == "quit") { setVisible(false); current_npc = 0; @@ -253,7 +228,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) mQuantityLabel->adjustSize(); int price = mAmountItems * mShopItems->at(selectedItem).price; - mMoneyLabel->setCaption("Price : " + toString(price) + " GP / " + mMoneyLabel->setCaption("Price: " + toString(price) + " GP / " + toString(mMoney) + " GP" ); mMoneyLabel->adjustSize(); } @@ -261,19 +236,39 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) void BuyDialog::selectionChanged(const SelectionEvent &event) { + // Reset amount of items and update labels + mAmountItems = 0; + mSlider->setValue(0); + mQuantityLabel->setCaption("0"); + mQuantityLabel->adjustSize(); + mMoneyLabel->setCaption("Price: 0 GP / " + toString(mMoney) + " GP"); + mMoneyLabel->adjustSize(); + + // Disable buttons for buying and decreasing + mBuyButton->setEnabled(false); + mDecreaseButton->setEnabled(false); + int selectedItem = mShopItemList->getSelected(); if (selectedItem > -1) { - const ItemInfo &info = - ItemDB::get(mShopItems->at(selectedItem).id); + const ItemInfo &info = ItemDB::get(mShopItems->at(selectedItem).id); mItemDescLabel->setCaption("Description: " + info.getDescription()); mItemEffectLabel->setCaption("Effect: " + info.getEffect()); + + // Calculate how many the player can afford + mMaxItems = mMoney / mShopItems->at(selectedItem).price; } else { mItemDescLabel->setCaption("Description:"); mItemEffectLabel->setCaption("Effect:"); + mMaxItems = 0; } + + // When at least one item can be bought, enable the slider and the + // increase button + mIncreaseButton->setEnabled(mMaxItems > 0); + mSlider->setEnabled(mMaxItems > 0); } diff --git a/src/gui/chargedialog.cpp b/src/gui/chargedialog.cpp index 349ca223..862378ae 100644 --- a/src/gui/chargedialog.cpp +++ b/src/gui/chargedialog.cpp @@ -37,6 +37,7 @@ ChargeDialog::ChargeDialog(): mProgBar = new ProgressBar(0.0f, 140, 25, 128, 128, 128); mProgBar->setPosition(20, 40); add(mProgBar); + setVisible(true); } // update the dialog diff --git a/src/gui/listbox.cpp b/src/gui/listbox.cpp index 14626d06..d4a2c6cb 100644 --- a/src/gui/listbox.cpp +++ b/src/gui/listbox.cpp @@ -38,9 +38,8 @@ ListBox::ListBox(gcn::ListModel *listModel): void ListBox::draw(gcn::Graphics *graphics) { - if (mListModel == NULL) { + if (!mListModel) return; - } graphics->setColor(gcn::Color(110, 160, 255)); graphics->setFont(getFont()); @@ -54,7 +53,9 @@ void ListBox::draw(gcn::Graphics *graphics) } // Draw the list elements - for (int i = 0, y = 0; i < mListModel->getNumberOfElements(); ++i, y += fontHeight) + for (int i = 0, y = 0; + i < mListModel->getNumberOfElements(); + ++i, y += fontHeight) { graphics->drawText(mListModel->getElementAt(i), 1, y); } diff --git a/src/gui/listbox.h b/src/gui/listbox.h index c1932f54..deca07cf 100644 --- a/src/gui/listbox.h +++ b/src/gui/listbox.h @@ -73,9 +73,9 @@ class ListBox : public gcn::ListBox /** * Sets the index of the selected element. */ - void setSelected(int selected); + virtual void setSelected(int selected); - private: + protected: /** * Sends out selection events to the list of selection listeners. */ diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 499bbd05..b0957f9e 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -142,7 +142,8 @@ void SellDialog::addItem(Item *item, int price) ITEM_SHOP item_shop; - item_shop.name = item->getInfo().getName() + " " + toString(price) + " GP"; + item_shop.name = item->getInfo().getName() + + " (" + toString(price) + " GP)"; item_shop.price = price; item_shop.index = item->getInvIndex(); item_shop.id = item->getId(); diff --git a/src/gui/shop.cpp b/src/gui/shop.cpp index 2d33e8a8..3d972bc2 100644 --- a/src/gui/shop.cpp +++ b/src/gui/shop.cpp @@ -45,7 +45,7 @@ void ShopItems::addItem(short id, int price) ITEM_SHOP item_shop; item_shop.name = ItemDB::get(id).getName() - + " " + toString(price) + " GP"; + + " (" + toString(price) + " GP)"; item_shop.price = price; item_shop.id = id; item_shop.image = ItemDB::get(id).getImage(); diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp index 61abff35..4821067c 100644 --- a/src/gui/shoplistbox.cpp +++ b/src/gui/shoplistbox.cpp @@ -34,11 +34,10 @@ #include "../graphics.h" -const int ITEM_SPRITE_HEIGHT = 32; +const int ITEM_ICON_SIZE = 32; ShopListBox::ShopListBox(gcn::ListModel *listModel): - gcn::ListBox(listModel), - mMousePressed(false), + ListBox(listModel), mPlayerMoney(0) { mRowHeight = getFont()->getHeight(); @@ -46,105 +45,101 @@ ShopListBox::ShopListBox(gcn::ListModel *listModel): } ShopListBox::ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel): - gcn::ListBox(listModel), - mMousePressed(false), + ListBox(listModel), mPlayerMoney(0), mShopItems(shopListModel) { - mRowHeight = (getFont()->getHeight() > ITEM_SPRITE_HEIGHT ? - getFont()->getHeight() : ITEM_SPRITE_HEIGHT); + mRowHeight = std::max(getFont()->getHeight(), ITEM_ICON_SIZE); mPriceCheck = true; } - void ShopListBox::setPlayersMoney(int money) { mPlayerMoney = money; } -void ShopListBox::draw(gcn::Graphics *graphics) +void ShopListBox::draw(gcn::Graphics *gcnGraphics) { - if (mListModel == NULL) { + if (!mListModel) return; - } + + Graphics *graphics = static_cast(gcnGraphics); graphics->setFont(getFont()); // Draw the list elements - for (int i = 0, y = 0; i < mListModel->getNumberOfElements(); ++i, y += mRowHeight) + for (int i = 0, y = 0; + i < mListModel->getNumberOfElements(); + ++i, y += mRowHeight) { - graphics->setColor(gcn::Color(0xffffff)); - if (mShopItems != NULL) + gcn::Color backgroundColor = gcn::Color(0xffffff); + + if (i == mSelected) { - if(mPlayerMoney < mShopItems->at(i).price && mPriceCheck) - { - graphics->setColor(gcn::Color(0x919191)); - } + backgroundColor = gcn::Color(110, 160, 255); } + else if (mShopItems && + mPlayerMoney < mShopItems->at(i).price && mPriceCheck) + { + backgroundColor = gcn::Color(0x919191); + } + + graphics->setColor(backgroundColor); graphics->fillRectangle(gcn::Rectangle(0, y, getWidth(), mRowHeight)); - if (mShopItems) - dynamic_cast(graphics)->drawImage(mShopItems->at(i).image, 1, y); - graphics->drawText(mListModel->getElementAt(i), ITEM_SPRITE_HEIGHT, y); - } - // Draw rectangle below the selected list element and the list element - // not shown. - if (mSelected >= 0) { - graphics->setColor(gcn::Color(110, 160, 255)); - graphics->fillRectangle(gcn::Rectangle(0, mRowHeight * mSelected, - getWidth(), mRowHeight)); if (mShopItems) - dynamic_cast(graphics)->drawImage( - mShopItems->at(mSelected).image, 1, mRowHeight * mSelected); - graphics->drawText(mListModel->getElementAt(mSelected), - ITEM_SPRITE_HEIGHT, mRowHeight * mSelected); + { + Image *icon = mShopItems->at(i).image; + if (icon) + { + graphics->drawImage(icon, 1, y); + } + } + graphics->drawText(mListModel->getElementAt(i), ITEM_ICON_SIZE + 5, + y + (ITEM_ICON_SIZE - getFont()->getHeight()) / 2); } } void ShopListBox::setSelected(int selected) { - gcn::ListBox::setSelected(selected); - if (mListModel != NULL) + if (!mListModel) { - gcn::BasicContainer *par = getParent(); - if (par == NULL) - { - return; - } - - gcn::Rectangle scroll; + mSelected = -1; + } + else + { + // Update mSelected with bounds checking + mSelected = std::min(mListModel->getNumberOfElements() - 1, + std::max(-1, selected)); - if (mSelected < 0) + gcn::BasicContainer *parent = getParent(); + if (parent) { - scroll.y = 0; + gcn::Rectangle scroll; + scroll.y = (mSelected < 0) ? 0 : mRowHeight * mSelected; + scroll.height = mRowHeight; + parent->showWidgetPart(this, scroll); } - else - { - scroll.y = mRowHeight * mSelected; - } - - scroll.height = mRowHeight; - par->showWidgetPart(this, scroll); } + fireSelectionChangedEvent(); } void ShopListBox::mousePress(int x, int y, int button) { - - bool enoughMoney = false; if (button == gcn::MouseInput::LEFT && hasMouse()) { - if (mShopItems) + bool enoughMoney = false; + + if (mShopItems && mPriceCheck) { - if(mPlayerMoney >= mShopItems->at(y / mRowHeight).price) + if (mPlayerMoney >= mShopItems->at(y / mRowHeight).price) enoughMoney = true; } else // Old Behaviour + { enoughMoney = true; - - if (!mPriceCheck) - enoughMoney = true; + } if (enoughMoney) { @@ -155,40 +150,9 @@ void ShopListBox::mousePress(int x, int y, int button) } } -void ShopListBox::mouseRelease(int x, int y, int button) -{ - gcn::ListBox::mouseRelease(x, y, button); - - mMousePressed = false; -} - -void ShopListBox::mouseMotion(int x, int y) -{ - gcn::ListBox::mouseMotion(x, y); - - // Pretend mouse is pressed continuously while dragged. Causes list - // selection to be updated as is default in many GUIs. - if (mMousePressed) - { - mousePress(x, y, gcn::MouseInput::LEFT); - } -} - -void ShopListBox::fireSelectionChangedEvent() -{ - SelectionEvent event(this); - SelectionListeners::iterator i_end = mListeners.end(); - SelectionListeners::iterator i; - - for (i = mListeners.begin(); i != i_end; ++i) - { - (*i)->selectionChanged(event); - } -} - void ShopListBox::adjustSize() { - if (mListModel != NULL) + if (mListModel) { setHeight(mRowHeight * mListModel->getNumberOfElements()); } diff --git a/src/gui/shoplistbox.h b/src/gui/shoplistbox.h index 2dff8977..476564b2 100644 --- a/src/gui/shoplistbox.h +++ b/src/gui/shoplistbox.h @@ -21,10 +21,10 @@ * $Id: listbox.h 2655 2006-09-03 21:25:02Z b_lindeijer $ */ -#ifndef _TMW_LISTBOX_H -#define _TMW_LISTBOX_H +#ifndef _TMW_SHOPLISTBOX_H +#define _TMW_SHOPLISTBOX_H -#include +#include "listbox.h" #include "shop.h" class SelectionListener; @@ -36,7 +36,7 @@ class SelectionListener; * * \ingroup GUI */ -class ShopListBox : public gcn::ListBox +class ShopListBox : public ListBox { public: /** @@ -55,8 +55,6 @@ class ShopListBox : public gcn::ListBox void draw(gcn::Graphics *graphics); void mousePress(int x, int y, int button); - void mouseRelease(int x, int y, int button); - void mouseMotion(int x, int y); /** * Adds a listener to the list that's notified each time a change to @@ -98,15 +96,6 @@ class ShopListBox : public gcn::ListBox void setPriceCheck(bool check); private: - /** - * Sends out selection events to the list of selection listeners. - */ - void fireSelectionChangedEvent(); - - bool mMousePressed; /**< Keeps track of mouse pressed status. */ - - std::list mListeners; - int mPlayerMoney; /** @@ -118,7 +107,6 @@ class ShopListBox : public gcn::ListBox int mRowHeight; /**< Row Height */ bool mPriceCheck; - }; #endif diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 73343483..73e4489e 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -48,9 +49,9 @@ UpdaterWindow::UpdaterWindow(): Window("Updating..."), mThread(NULL), mMutex(NULL), mDownloadStatus(UPDATE_NEWS), mUpdateHost(""), mCurrentFile("news.txt"), mBasePath(""), - mStoreInMemory(true), mDownloadComplete(true), mUserCancel(false), - mDownloadedBytes(0), mMemoryBuffer(NULL), - mCurlError(new char[CURL_ERROR_SIZE]), mFileIndex(0) + mStoreInMemory(true), mDownloadComplete(true), mUserCancel(false), + mDownloadedBytes(0), mMemoryBuffer(NULL), + mCurlError(new char[CURL_ERROR_SIZE]), mLineIndex(0) { mCurlError[0] = 0; @@ -83,8 +84,9 @@ UpdaterWindow::UpdaterWindow(): add(mCancelButton); add(mPlayButton); - mCancelButton->requestFocus(); setLocationRelativeTo(getParent()); + setVisible(true); + mCancelButton->requestFocus(); mUpdateHost = config.getValue("updatehost", "http://updates.themanaworld.org"); @@ -179,7 +181,6 @@ void UpdaterWindow::loadNews() mMemoryBuffer = NULL; mScrollArea->setVerticalScrollAmount(0); - setVisible(true); } int UpdaterWindow::updateProgress(void *ptr, @@ -227,78 +228,116 @@ size_t UpdaterWindow::memoryWrite(void *ptr, int UpdaterWindow::downloadThread(void *ptr) { + int attempts = 0; + UpdaterWindow *uw = reinterpret_cast(ptr); CURL *curl; CURLcode res; - FILE *outfile = NULL; - UpdaterWindow *uw = reinterpret_cast(ptr); std::string outFilename; std::string url(uw->mUpdateHost + "/" + uw->mCurrentFile); - uw->setLabel(uw->mCurrentFile + " (0%)"); - curl = curl_easy_init(); + while (attempts < 3 && !uw->mDownloadComplete) { + FILE *outfile = NULL; + uw->setLabel(uw->mCurrentFile + " (0%)"); - if (curl) - { - logger->log("Downloading: %s", url.c_str()); + curl = curl_easy_init(); - if (uw->mStoreInMemory) + if (curl) { - uw->mDownloadedBytes = 0; - curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, - UpdaterWindow::memoryWrite); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr); - } - else - { - // Download in the proper folder : ./updates under win, - // /home/user/.tmw/updates for unices - outFilename = uw->mBasePath + "/updates/download.temp"; - outfile = fopen(outFilename.c_str(), "wb"); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); - } + logger->log("Downloading: %s", url.c_str()); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, uw->mCurlError); - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, - UpdaterWindow::updateProgress); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, ptr); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); + if (uw->mStoreInMemory) + { + uw->mDownloadedBytes = 0; + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, + UpdaterWindow::memoryWrite); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr); + } + else + { + // Download in the proper folder : ./updates under win, + // /home/user/.tmw/updates for unices + outFilename = uw->mBasePath + "/updates/download.temp"; + outfile = fopen(outFilename.c_str(), "w+b"); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); + } - if ((res = curl_easy_perform(curl)) != 0) - { - uw->mDownloadStatus = UPDATE_ERROR; - switch (res) + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, uw->mCurlError); + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, + UpdaterWindow::updateProgress); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, ptr); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); + + if ((res = curl_easy_perform(curl)) != 0) { - case CURLE_COULDNT_CONNECT: // give more debug info on that error - std::cerr << "curl error " << res << " : " << uw->mCurlError << " " << url.c_str() - << std::endl; - break; - - default: - std::cerr << "curl error " << res << " : " << uw->mCurlError << " host: " << url.c_str() - << std::endl; + uw->mDownloadStatus = UPDATE_ERROR; + switch (res) + { + case CURLE_COULDNT_CONNECT: // give more debug info on that error + std::cerr << "curl error " << res << " : " << uw->mCurlError << " " << url.c_str() + << std::endl; + break; + + default: + std::cerr << "curl error " << res << " : " << uw->mCurlError << " host: " << url.c_str() + << std::endl; + } } - } - curl_easy_cleanup(curl); - uw->mDownloadComplete = true; + curl_easy_cleanup(curl); - if (!uw->mStoreInMemory) - { - fclose(outfile); + uw->mDownloadComplete = true; - // Give the file the proper name - std::string newName(uw->mBasePath + "/updates/" + - uw->mCurrentFile.c_str()); + if (!uw->mStoreInMemory) + { + long fileSize; + char *buffer; + // Obtain file size. + fseek(outfile, 0, SEEK_END); + fileSize = ftell(outfile); + rewind(outfile); + buffer = (char*)malloc(fileSize); + fread(buffer, 1, fileSize, outfile); + fclose(outfile); + + // Give the file the proper name + std::string newName(uw->mBasePath + "/updates/" + + uw->mCurrentFile.c_str()); + + // Any existing file with this name is deleted first, otherwise the + // rename will fail on Windows. + ::remove(newName.c_str()); + ::rename(outFilename.c_str(), newName.c_str()); + + // Don't check resources2.txt checksum + if (uw->mDownloadStatus == UPDATE_RESOURCES) + { + // Calculate Adler-32 checksum + unsigned long adler = adler32(0L, Z_NULL, 0); + adler = adler32(adler, (Bytef *)buffer, fileSize); + free(buffer); + + if (uw->mCurrentChecksum != adler) { + uw->mDownloadComplete = false; + // Remove the corrupted file + ::remove(newName.c_str()); + logger->log( + "Checksum for file %s failed: (%lx/%lx)", + uw->mCurrentFile.c_str(), + adler, uw->mCurrentChecksum); + } + } - // Any existing file with this name is deleted first, otherwise the - // rename will fail on Windows. - ::remove(newName.c_str()); - ::rename(outFilename.c_str(), newName.c_str()); + } } + attempts++; + } + + if (!uw->mDownloadComplete) { + uw->mDownloadStatus = UPDATE_ERROR; } return 0; @@ -351,7 +390,7 @@ void UpdaterWindow::logic() // Parse current memory buffer as news and dispose of the data loadNews(); - mCurrentFile = "resources.txt"; + mCurrentFile = "resources2.txt"; mStoreInMemory = false; download(); mDownloadStatus = UPDATE_LIST; @@ -361,7 +400,7 @@ void UpdaterWindow::logic() if (mDownloadComplete) { ResourceManager *resman = ResourceManager::getInstance(); - mFiles = resman->loadTextFile("updates/resources.txt"); + mLines = resman->loadTextFile("updates/resources2.txt"); mStoreInMemory = false; mDownloadStatus = UPDATE_RESOURCES; } @@ -375,9 +414,15 @@ void UpdaterWindow::logic() mThread = NULL; } - if (mFileIndex < mFiles.size()) + if (mLineIndex < mLines.size()) { - mCurrentFile = mFiles[mFileIndex]; + std::stringstream line(mLines[mLineIndex]); + line >> mCurrentFile; + std::string checksum; + line >> checksum; + std::stringstream ss(checksum); + ss >> std::hex >> mCurrentChecksum; + std::ifstream temp( (mBasePath + "/updates/" + mCurrentFile).c_str()); if (!temp.is_open()) @@ -389,7 +434,7 @@ void UpdaterWindow::logic() { logger->log("%s already here", mCurrentFile.c_str()); } - mFileIndex++; + mLineIndex++; } else { diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index 16442656..0d1493ee 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -140,6 +140,11 @@ class UpdaterWindow : public Window, public gcn::ActionListener */ std::string mCurrentFile; + /** + * The Adler32 checksum of the file currently downloading. + */ + unsigned long mCurrentChecksum; + /** * Absolute path to locally save downloaded files. */ @@ -179,12 +184,12 @@ class UpdaterWindow : public Window, public gcn::ActionListener /** * List of files to download */ - std::vector mFiles; + std::vector mLines; /** * Index of the file to be downloaded */ - unsigned int mFileIndex; + unsigned int mLineIndex; gcn::Label *mLabel; /**< Progress bar caption. */ Button *mCancelButton; /**< Button to stop the update process. */ diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 3346c07a..75a16865 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -197,8 +197,8 @@ Viewport::draw(gcn::Graphics *gcnGraphics) } // Draw target marker if needed - Being *target; - if ((target = player_node->getTarget())) + Being *target = player_node->getTarget(); + if (target) { graphics->setFont(speechFont); graphics->setColor(gcn::Color(255, 32, 32)); diff --git a/src/guichanfwd.h b/src/guichanfwd.h index 5eabc783..812f3f7a 100644 --- a/src/guichanfwd.h +++ b/src/guichanfwd.h @@ -27,6 +27,7 @@ namespace gcn { class ActionListener; class AllegroGraphics; + class AllegroImage; class AllegroImageLoader; class AllegroInput; class BasicContainer; @@ -56,11 +57,13 @@ namespace gcn { class MouseInput; class MouseListener; class OpenGLGraphics; - class OpenGLImageLoader; + class OpenGLImage; + class OpenGLSDLImageLoader; class RadioButton; class Rectangle; class ScrollArea; class SDLGraphics; + class SDLImage; class SDLImageLoader; class SDLInput; class Slider; diff --git a/src/inventory.h b/src/inventory.h index 40bcafbb..32ae393e 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -31,7 +31,14 @@ class Item; class Inventory { public: + /** + * Constructor. + */ Inventory(); + + /** + * Destructor. + */ ~Inventory(); /** diff --git a/src/localplayer.cpp b/src/localplayer.cpp index ba7b6117..8076c538 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -166,11 +166,6 @@ void LocalPlayer::pickUp(FloorItem *item) void LocalPlayer::walk(unsigned char dir) { - if (mWalkingDir != dir) - { - mWalkingDir = dir; - } - if (!mMap || !dir) return; @@ -237,6 +232,20 @@ void LocalPlayer::setDestination(Uint16 x, Uint16 y) Being::setDestination(x, y); } +void LocalPlayer::setWalkingDir(int dir) +{ + if (mWalkingDir != dir) + { + mWalkingDir = dir; + } + + // If we're not already walking, start walking. + if (mAction != WALK && dir) + { + walk(dir); + } +} + void LocalPlayer::raiseAttribute(Attribute attr) { // XXX Convert for new server diff --git a/src/localplayer.h b/src/localplayer.h index 59b59812..765b7cca 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -42,9 +42,15 @@ class LocalPlayer : public Player STR = 0, AGI, VIT, INT, DEX, LUK }; + /** + * Constructor. + */ LocalPlayer(); - virtual ~LocalPlayer(); + /** + * Destructor. + */ + ~LocalPlayer(); virtual void logic(); @@ -111,13 +117,16 @@ class LocalPlayer : public Player */ void setTarget(Being* target) { mTarget = target; } - void walk(unsigned char dir); - /** * Sets a new destination for this being to walk to. */ void setDestination(Uint16 x, Uint16 y); + /** + * Sets a new direction to keep walking in. + */ + void setWalkingDir(int dir); + void raiseAttribute(Attribute attr); void raiseSkill(Uint16 skillId); @@ -151,6 +160,8 @@ class LocalPlayer : public Player std::auto_ptr mInventory; protected: + void walk(unsigned char dir); + Being *mTarget; FloorItem *mPickUpTarget; diff --git a/src/main.cpp b/src/main.cpp index 90368b7d..8163cde3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -309,11 +309,6 @@ void init_engine() errorMessage = err; logger->log("Warning: %s", err); } - - // Load XML databases - EquipmentDB::load(); - ItemDB::load(); - MonsterDB::load(); } /** Clear the engine */ @@ -411,19 +406,22 @@ void parseOptions(int argc, char *argv[], Options &options) } /** - * Reads the file "updates/resources.txt" and attempts to load each update + * Reads the file "updates/resources2.txt" and attempts to load each update * mentioned in it. */ void loadUpdates() { - const std::string updatesFile = "updates/resources.txt"; + const std::string updatesFile = "updates/resources2.txt"; ResourceManager *resman = ResourceManager::getInstance(); std::vector lines = resman->loadTextFile(updatesFile); std::string homeDir = config.getValue("homeDir", ""); for (unsigned int i = 0; i < lines.size(); ++i) { - resman->addToSearchPath(homeDir + "/updates/" + lines[i], false); + std::stringstream line(lines[i]); + std::string filename; + line >> filename; + resman->addToSearchPath(homeDir + "/updates/" + filename, false); } } @@ -687,6 +685,12 @@ int main(int argc, char *argv[]) case STATE_LOGIN: logger->log("State: LOGIN"); + + // Load XML databases + EquipmentDB::load(); + ItemDB::load(); + MonsterDB::load(); + currentDialog = new LoginDialog(&loginData); // TODO: Restore autologin //if (!loginData.password.empty()) { diff --git a/src/main.h b/src/main.h index b68a4e4d..14f52e4d 100644 --- a/src/main.h +++ b/src/main.h @@ -29,8 +29,7 @@ #ifdef HAVE_CONFIG_H #include "../config.h" #elif defined WIN32 -#include "../The_Mana_World_private.h" -#define PACKAGE_VERSION PRODUCT_VERSION +#include "winver.h" #endif #ifndef TMW_DATADIR diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index 988a9a68..f16037cf 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -31,14 +31,24 @@ #include "../log.h" #include "../npc.h" +#include "../gui/buy.h" #include "../gui/chat.h" +#include "../gui/npclistdialog.h" +#include "../gui/npc_text.h" #include "../gui/ok_dialog.h" +#include "../gui/sell.h" #include "../gui/skill.h" // TODO Move somewhere else OkDialog *weightNotice = NULL; OkDialog *deathNotice = NULL; +extern NpcListDialog *npcListDialog; +extern NpcTextDialog *npcTextDialog; +extern BuyDialog *buyDialog; +extern SellDialog *sellDialog; +extern Window *buySellDialog; + /** * Listener used for handling the overweigth message. */ @@ -64,6 +74,12 @@ namespace { { player_node->revive(); deathNotice = NULL; + npcListDialog->setVisible(false); + npcTextDialog->setVisible(false); + buyDialog->setVisible(false); + sellDialog->setVisible(false); + buySellDialog->setVisible(false); + current_npc = 0; } } deathListener; } diff --git a/src/npc.cpp b/src/npc.cpp index 3c142889..ccd085b6 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -29,7 +29,6 @@ #include "gui/gui.h" class Spriteset; -extern Spriteset *npcset; NPC *current_npc = 0; diff --git a/src/resources/action.cpp b/src/resources/action.cpp new file mode 100644 index 00000000..247455db --- /dev/null +++ b/src/resources/action.cpp @@ -0,0 +1,67 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "action.h" + +#include + +#include "animation.h" + +#include "../utils/dtor.h" + + +Action::Action() +{ +} + +Action::~Action() +{ + std::for_each(mAnimations.begin(), mAnimations.end(), + make_dtor(mAnimations)); +} + +Animation* +Action::getAnimation(int direction) const +{ + Animations::const_iterator i = mAnimations.find(direction); + + // When the direction isn't defined, try the default + if (i == mAnimations.end()) + { + i = mAnimations.find(0); + } + + return (i == mAnimations.end()) ? NULL : i->second; +} + +void +Action::setAnimation(int direction, Animation *animation) +{ + // Set first direction as default direction + if (mAnimations.empty()) + { + mAnimations[0] = animation; + } + + mAnimations[direction] = animation; +} diff --git a/src/resources/action.h b/src/resources/action.h new file mode 100644 index 00000000..8d5e8d11 --- /dev/null +++ b/src/resources/action.h @@ -0,0 +1,61 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_ACTION_H +#define _TMW_ACTION_H + +#include + +#include + +class Animation; + +/** + * An action consists of several animations, one for each direction. + */ +class Action +{ + public: + /** + * Constructor. + */ + Action(); + + /** + * Destructor. + */ + ~Action(); + + void + setAnimation(int direction, Animation *animation); + + Animation* + getAnimation(int direction) const; + + protected: + typedef std::map Animations; + typedef Animations::iterator AnimationIterator; + Animations mAnimations; +}; + +#endif diff --git a/src/resources/animation.cpp b/src/resources/animation.cpp new file mode 100644 index 00000000..de96525c --- /dev/null +++ b/src/resources/animation.cpp @@ -0,0 +1,53 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "animation.h" + +#include + +#include "../utils/dtor.h" + +Animation::Animation(): + mDuration(0) +{ +} + +void +Animation::addFrame(Image *image, unsigned int delay, int offsetX, int offsetY) +{ + Frame frame = { image, delay, offsetX, offsetY }; + mFrames.push_back(frame); + mDuration += delay; +} + +void +Animation::addTerminator() +{ + addFrame(NULL, 0, 0, 0); +} + +bool +Animation::isTerminator(const Frame &candidate) +{ + return (candidate.image == NULL); +} diff --git a/src/resources/animation.h b/src/resources/animation.h new file mode 100644 index 00000000..54142bcb --- /dev/null +++ b/src/resources/animation.h @@ -0,0 +1,99 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_ANIMATION_H +#define _TMW_ANIMATION_H + +#include + +#include + +class Image; +class Spriteset; + +/** + * A single frame in an animation, with a delay and an offset. + */ +struct Frame +{ + Image *image; + unsigned int delay; + int offsetX; + int offsetY; +}; + +/** + * An animation consists of several frames, each with their own delay and + * offset. + */ +class Animation +{ + public: + /** + * Constructor. + */ + Animation(); + + /** + * Appends a new animation at the end of the sequence + */ + void + addFrame(Image *image, unsigned int delay, int offsetX, int offsetY); + + /** + * Appends an animation terminator that states that the animation + * should not loop. + */ + void + addTerminator(); + + /** + * Returns the frame at the specified index. + */ + Frame* + getFrame(int index) { return &(mFrames[index]); } + + /** + * Returns the length of this animation in frames. + */ + unsigned int + getLength() const { return mFrames.size(); } + + /** + * Returns the duration of this animation. + */ + int + getDuration() const { return mDuration; } + + /** + * Determines whether the given animation frame is a terminator. + */ + static bool + isTerminator(const Frame &phase); + + protected: + std::vector mFrames; + int mDuration; +}; + +#endif diff --git a/src/resources/equipmentdb.cpp b/src/resources/equipmentdb.cpp index 78ae3b6a..52a9fbd3 100644 --- a/src/resources/equipmentdb.cpp +++ b/src/resources/equipmentdb.cpp @@ -40,6 +40,9 @@ namespace void EquipmentDB::load() { + if (mLoaded) + return; + logger->log("Initializing equipment database..."); mUnknown.setSprite("error.xml", 0); mUnknown.setSprite("error.xml", 1); diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 48818f6f..9398e06b 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -153,10 +153,10 @@ Image* Image::load(void *buffer, unsigned int bufferSize, SDL_FreeSurface(image); if (hasPink && !hasAlpha) { - SDL_SetColorKey(tmpImage, SDL_SRCCOLORKEY | SDL_RLEACCEL, + SDL_SetColorKey(tmpImage, SDL_SRCCOLORKEY, SDL_MapRGB(tmpImage->format, 255, 0, 255)); } else if (hasAlpha) { - SDL_SetAlpha(tmpImage, SDL_SRCALPHA | SDL_RLEACCEL, SDL_ALPHA_OPAQUE); + SDL_SetAlpha(tmpImage, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); } #ifdef USE_OPENGL @@ -305,7 +305,7 @@ void Image::setAlpha(float a) if (mImage) { // Set the alpha value this image is drawn at - SDL_SetAlpha(mImage, SDL_SRCALPHA | SDL_RLEACCEL, (int)(255 * mAlpha)); + SDL_SetAlpha(mImage, SDL_SRCALPHA, (int) (255 * mAlpha)); } } diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index b91e34cc..f914af47 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -37,11 +37,15 @@ namespace { ItemDB::ItemInfos mItemInfos; ItemInfo mUnknown; + bool mLoaded = false; } void ItemDB::load() { + if (mLoaded) + return; + logger->log("Initializing item database..."); mUnknown.setName("Unknown item"); @@ -150,6 +154,8 @@ void ItemDB::load() } xmlFreeDoc(doc); + + mLoaded = true; } void ItemDB::unload() @@ -159,6 +165,8 @@ void ItemDB::unload() delete i->second; } mItemInfos.clear(); + + mLoaded = false; } const ItemInfo& diff --git a/src/resources/itemdb.h b/src/resources/itemdb.h index 5922984a..c080194b 100644 --- a/src/resources/itemdb.h +++ b/src/resources/itemdb.h @@ -29,17 +29,17 @@ #include /** - * The namespace that holds the item information + * The namespace that holds the item information. */ namespace ItemDB { /** - * Loads the item data from Items.xml + * Loads the item data from items.xml. */ void load(); /** - * Frees item data + * Frees item data. */ void unload(); diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 4569ced7..15a88b4d 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -30,11 +30,11 @@ #include "resourcemanager.h" #include "image.h" -#include "../base64.h" #include "../log.h" #include "../map.h" #include "../tileset.h" +#include "../utils/base64.h" #include "../utils/tostring.h" #include "../utils/xml.h" diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp index fb03f6c1..e4406f9c 100644 --- a/src/resources/monsterdb.cpp +++ b/src/resources/monsterdb.cpp @@ -34,11 +34,15 @@ namespace { MonsterDB::MonsterInfos mMonsterInfos; MonsterInfo mUnknown; + bool mLoaded = false; } void MonsterDB::load() { + if (mLoaded) + return; + mUnknown.setSprite("error.xml"); mUnknown.setName("unnamed"); @@ -123,6 +127,8 @@ MonsterDB::load() } mMonsterInfos[XML::getProperty(monsterNode, "id", 0)] = currentInfo; } + + mLoaded = true; } void @@ -131,6 +137,8 @@ MonsterDB::unload() for_each ( mMonsterInfos.begin(), mMonsterInfos.end(), make_dtor(mMonsterInfos)); mMonsterInfos.clear(); + + mLoaded = false; } diff --git a/src/resources/openglsdlimageloader.cpp b/src/resources/openglsdlimageloader.cpp index b3e1601e..68de1e19 100644 --- a/src/resources/openglsdlimageloader.cpp +++ b/src/resources/openglsdlimageloader.cpp @@ -31,7 +31,8 @@ #ifdef USE_OPENGL -SDL_Surface* OpenGLSDLImageLoader::loadSDLSurface(const std::string& filename) +SDL_Surface* +OpenGLSDLImageLoader::loadSDLSurface(const std::string &filename) { ResourceManager *resman = ResourceManager::getInstance(); return resman->loadSDLSurface(filename); diff --git a/src/resources/openglsdlimageloader.h b/src/resources/openglsdlimageloader.h index 29be294c..b79dde15 100644 --- a/src/resources/openglsdlimageloader.h +++ b/src/resources/openglsdlimageloader.h @@ -31,7 +31,8 @@ class OpenGLSDLImageLoader : public gcn::OpenGLSDLImageLoader { protected: - SDL_Surface* loadSDLSurface(const std::string& filename); + SDL_Surface* + loadSDLSurface(const std::string &filename); }; #endif diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp index bd273b3b..feb6f8f8 100644 --- a/src/resources/spritedef.cpp +++ b/src/resources/spritedef.cpp @@ -23,11 +23,10 @@ #include "spritedef.h" -#include "../animation.h" -#include "../action.h" -#include "../graphics.h" #include "../log.h" +#include "animation.h" +#include "action.h" #include "resourcemanager.h" #include "spriteset.h" #include "image.h" @@ -208,20 +207,20 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode, Animation *animation = new Animation(); action->setAnimation(directionType, animation); - // Get animation phases - for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode; - phaseNode != NULL; - phaseNode = phaseNode->next) + // Get animation frames + for (xmlNodePtr frameNode = animationNode->xmlChildrenNode; + frameNode != NULL; + frameNode = frameNode->next) { - int delay = XML::getProperty(phaseNode, "delay", 0); - int offsetX = XML::getProperty(phaseNode, "offsetX", 0); - int offsetY = XML::getProperty(phaseNode, "offsetY", 0); + int delay = XML::getProperty(frameNode, "delay", 0); + int offsetX = XML::getProperty(frameNode, "offsetX", 0); + int offsetY = XML::getProperty(frameNode, "offsetY", 0); offsetY -= imageset->getHeight() - 32; offsetX -= imageset->getWidth() / 2 - 16; - if (xmlStrEqual(phaseNode->name, BAD_CAST "frame")) + if (xmlStrEqual(frameNode->name, BAD_CAST "frame")) { - int index = XML::getProperty(phaseNode, "index", -1); + int index = XML::getProperty(frameNode, "index", -1); if (index < 0) { @@ -237,12 +236,12 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode, continue; } - animation->addPhase(img, delay, offsetX, offsetY); + animation->addFrame(img, delay, offsetX, offsetY); } - else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence")) + else if (xmlStrEqual(frameNode->name, BAD_CAST "sequence")) { - int start = XML::getProperty(phaseNode, "start", -1); - int end = XML::getProperty(phaseNode, "end", -1); + int start = XML::getProperty(frameNode, "start", -1); + int end = XML::getProperty(frameNode, "end", -1); if (start < 0 || end < 0) { @@ -261,15 +260,15 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode, continue; } - animation->addPhase(img, delay, offsetX, offsetY); + animation->addFrame(img, delay, offsetX, offsetY); start++; } } - else if (xmlStrEqual(phaseNode->name, BAD_CAST "end")) + else if (xmlStrEqual(frameNode->name, BAD_CAST "end")) { animation->addTerminator(); } - } // for phaseNode + } // for frameNode } void diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h index 64414259..057129ad 100644 --- a/src/resources/spritedef.h +++ b/src/resources/spritedef.h @@ -32,10 +32,7 @@ #include class Action; -class Graphics; class Spriteset; -struct AnimationPhase; -class Animation; enum SpriteAction { diff --git a/src/resources/spriteset.cpp b/src/resources/spriteset.cpp index 9b09f1e5..96bcef0c 100644 --- a/src/resources/spriteset.cpp +++ b/src/resources/spriteset.cpp @@ -53,7 +53,7 @@ Spriteset::~Spriteset() Image* Spriteset::get(size_type i) { - if (i > mSpriteset.size()) + if (i >= mSpriteset.size()) { logger->log("Warning: Sprite #%i does not exist in this spriteset", i); return NULL; diff --git a/src/tmw.rc b/src/tmw.rc index 5a3b1649..ee5f99cd 100644 --- a/src/tmw.rc +++ b/src/tmw.rc @@ -1,34 +1,23 @@ #include // include for version info constants +#include "winver.h" A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "data/icons/tmw-icon.ico" -// -// TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS... -// 1 VERSIONINFO -FILEVERSION 0,1,0,0 -PRODUCTVERSION 0,1,0,0 -FILETYPE VFT_APP -{ - BLOCK "StringFileInfo" - { - BLOCK "040904E4" - { - VALUE "CompanyName", "The Mana World Development Team" - VALUE "FileVersion", "0.1.0" - VALUE "FileDescription", "The Mana World" - VALUE "InternalName", "tmw.exe" - VALUE "LegalCopyright", "2004-2006 (C)" - VALUE "LegalTrademarks", "" - VALUE "OriginalFilename", "tmw.exe" - VALUE "ProductName", "The Mana World MMORPG" - VALUE "ProductVersion", "0.1.0" - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x0409, 1252 - } +FILEVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD +PRODUCTVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD +FILETYPE VFT_APP { + BLOCK "StringFileInfo" { + BLOCK "040904E4" { + VALUE "CompanyName", "The Mana World Development Team" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "FileDescription", "The Mana World" + VALUE "LegalCopyright", "2004-2006 (C)" + VALUE "OriginalFilename", "tmw.exe" + VALUE "ProductName", "The Mana World MMORPG" + VALUE "ProductVersion", PACKAGE_VERSION + } + } } diff --git a/src/utils/base64.cpp b/src/utils/base64.cpp new file mode 100644 index 00000000..9a8f6356 --- /dev/null +++ b/src/utils/base64.cpp @@ -0,0 +1,149 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2000 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) 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. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | 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 both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Author: Jim Winstead (jimw@php.net) | + +----------------------------------------------------------------------+ + */ +/* $Id$ */ + +#include +#include + +#include "base64.h" + +static char base64_table[] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0' +}; +static char base64_pad = '='; + +unsigned char *php3_base64_encode(const unsigned char *string, int length, int *ret_length) { + const unsigned char *current = string; + int i = 0; + unsigned char *result = (unsigned char *)malloc(((length + 3 - length % 3) * 4 / 3 + 1) * sizeof(char)); + + while (length > 2) { /* keep going until we have less than 24 bits */ + result[i++] = base64_table[current[0] >> 2]; + result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; + result[i++] = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)]; + result[i++] = base64_table[current[2] & 0x3f]; + + current += 3; + length -= 3; /* we just handle 3 octets of data */ + } + + /* now deal with the tail end of things */ + if (length != 0) { + result[i++] = base64_table[current[0] >> 2]; + if (length > 1) { + result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; + result[i++] = base64_table[(current[1] & 0x0f) << 2]; + result[i++] = base64_pad; + } + else { + result[i++] = base64_table[(current[0] & 0x03) << 4]; + result[i++] = base64_pad; + result[i++] = base64_pad; + } + } + if(ret_length) { + *ret_length = i; + } + result[i] = '\0'; + return result; +} + +/* as above, but backwards. :) */ +unsigned char *php3_base64_decode(const unsigned char *string, int length, int *ret_length) { + const unsigned char *current = string; + int ch, i = 0, j = 0, k; + char *chp; + + unsigned char *result = (unsigned char *)malloc(length + 1); + + if (result == NULL) { + return NULL; + } + + /* run through the whole string, converting as we go */ + while ((ch = *current++) != '\0') { + if (ch == base64_pad) break; + + /* When Base64 gets POSTed, all pluses are interpreted as spaces. + This line changes them back. It's not exactly the Base64 spec, + but it is completely compatible with it (the spec says that + spaces are invalid). This will also save many people considerable + headache. - Turadg Aleahmad + */ + + if (ch == ' ') ch = '+'; + + chp = strchr(base64_table, ch); + if (chp == NULL) continue; + ch = chp - base64_table; + + switch(i % 4) { + case 0: + result[j] = ch << 2; + break; + case 1: + result[j++] |= ch >> 4; + result[j] = (ch & 0x0f) << 4; + break; + case 2: + result[j++] |= ch >>2; + result[j] = (ch & 0x03) << 6; + break; + case 3: + result[j++] |= ch; + break; + } + i++; + } + + k = j; + /* mop things up if we ended on a boundary */ + if (ch == base64_pad) { + switch(i % 4) { + case 0: + case 1: + free(result); + return NULL; + case 2: + k++; + case 3: + result[k++] = 0; + } + } + if(ret_length) { + *ret_length = j; + } + result[k] = '\0'; + return result; +} diff --git a/src/utils/base64.h b/src/utils/base64.h new file mode 100644 index 00000000..ff20ac53 --- /dev/null +++ b/src/utils/base64.h @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) 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. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | 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 both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Author: Jim Winstead (jimw@php.net) | + +----------------------------------------------------------------------+ + */ +/* $Id$ */ + +#ifndef _TMW_BASE64_H +#define _TMW_BASE64_H + +extern unsigned char *php3_base64_encode(const unsigned char *, int, int *); +extern unsigned char *php3_base64_decode(const unsigned char *, int, int *); + +#endif /* _TMW_BASE64_H */ diff --git a/src/utils/wingettimeofday.h b/src/utils/wingettimeofday.h index 0f8b767a..a5537f39 100644 --- a/src/utils/wingettimeofday.h +++ b/src/utils/wingettimeofday.h @@ -1,5 +1,5 @@ /* - * The Mana World Server + * The Mana World * Copyright 2004 The Mana World Development Team * * This file is part of The Mana World. @@ -17,10 +17,12 @@ * You should have received a copy of the GNU General Public License * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ */ -#ifndef _TMWSERV_WINGETTIMEOFDAY_H_ -#define _TMWSERV_WINGETTIMEOFDAY_H_ +#ifndef _TMW_WINGETTIMEOFDAY_H_ +#define _TMW_WINGETTIMEOFDAY_H_ #ifdef WIN32 diff --git a/src/winver.h b/src/winver.h new file mode 100644 index 00000000..58f11bea --- /dev/null +++ b/src/winver.h @@ -0,0 +1,6 @@ +/* VERSION DEFINITIONS */ +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 0 +#define VER_BUILD 0 +#define PACKAGE_VERSION "0.1.0" diff --git a/tmw.cbp b/tmw.cbp index d36a8bd0..c81ffb3e 100644 --- a/tmw.cbp +++ b/tmw.cbp @@ -40,16 +40,6 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + -- cgit v1.2.3-60-g2f50 From 9c8e872f2cb8c8dd919eff61a4ce9d63b041f715 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Wed, 10 Jan 2007 23:42:55 +0000 Subject: Accepted bugfixes for character creation from Rogier Polak. --- ChangeLog | 10 ++++++++++ data/graphics/gui/Makefile.am | 12 ++++++------ src/gui/char_select.cpp | 16 ++++++++-------- src/net/accountserver/account.cpp | 2 +- src/net/accountserver/account.h | 2 +- src/player.cpp | 12 ++++++------ 6 files changed, 32 insertions(+), 22 deletions(-) (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index 2770bfca..c89749ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-01-11 Rogier Polak + + * src/gui/char_select.cpp, src/net/accountserver/account.h, + src/net/accountserver/account.cpp, src/player.cpp: Fixedd issues + with out of range hair style and color, as well as their ordering. + * data/graphics/gui/Makefile.am, + data/graphics/images/ambient/Makefile.am, + data/graphics/sprites/Makefile.am: Some corrections to installed + files. + 2007-01-07 Bjørn Lindeijer * src/gui/status.h, src/gui/status.cpp, src/localplayer.h: diff --git a/data/graphics/gui/Makefile.am b/data/graphics/gui/Makefile.am index 50c9dfe7..c0e0655b 100644 --- a/data/graphics/gui/Makefile.am +++ b/data/graphics/gui/Makefile.am @@ -10,6 +10,7 @@ gui_DATA = \ buttonhi.png \ buttonpress.png \ checkbox.png \ + deepbox.png \ fixedfont.png \ hits_blue.png \ hits_red.png \ @@ -20,17 +21,18 @@ gui_DATA = \ hscroll_right_default.png \ hscroll_right_highlight.png \ hscroll_right_pressed.png \ - mouse.png \ menuitemD.png \ menuitemF.png \ menuitemN.png \ menuitemP.png \ + mouse.png \ radioin.png \ radioout.png \ - selection.png \ + resize.png \ + rpgfont_wider.png \ sansserif8.png \ + selection.png \ slider.png \ - deepbox.png \ thickborder.png \ vscroll_blue.png \ vscroll_down_default.png \ @@ -40,9 +42,7 @@ gui_DATA = \ vscroll_red.png \ vscroll_up_default.png \ vscroll_up_highlight.png \ - vscroll_up_pressed.png \ - rpgfont_wider.png \ - resize.png + vscroll_up_pressed.png EXTRA_DIST = \ $(gui_DATA) diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 3cb42078..ec4dad2e 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -238,8 +238,8 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot): Window("Create Character", true, parent), mSlot(slot) { mPlayer = new Player(0, 0, NULL); - mPlayer->setHairStyle(rand() % NR_HAIR_STYLES + 1); - mPlayer->setHairColor(rand() % NR_HAIR_COLORS + 1); + mPlayer->setHairStyle(rand() % NR_HAIR_STYLES); + mPlayer->setHairColor(rand() % NR_HAIR_COLORS); mNameField = new TextField(""); mNameLabel = new gcn::Label("Name:"); @@ -326,18 +326,18 @@ void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget) scheduleDelete(); } else if (eventId == "nextcolor") { - mPlayer->setHairColor(mPlayer->getHairColor() % NR_HAIR_COLORS + 1); + mPlayer->setHairColor((mPlayer->getHairColor() + 1) % NR_HAIR_COLORS); } else if (eventId == "prevcolor") { - int prevColor = mPlayer->getHairColor() + NR_HAIR_COLORS - 2; - mPlayer->setHairColor(prevColor % NR_HAIR_COLORS + 1); + int prevColor = mPlayer->getHairColor() + NR_HAIR_COLORS - 1; + mPlayer->setHairColor(prevColor % NR_HAIR_COLORS); } else if (eventId == "nextstyle") { - mPlayer->setHairStyle(mPlayer->getHairStyle() % NR_HAIR_STYLES + 1); + mPlayer->setHairStyle((mPlayer->getHairStyle() + 1) % NR_HAIR_STYLES); } else if (eventId == "prevstyle") { - int prevStyle = mPlayer->getHairStyle() + NR_HAIR_STYLES - 2; - mPlayer->setHairStyle(prevStyle % NR_HAIR_STYLES + 1); + int prevStyle = mPlayer->getHairStyle() + NR_HAIR_STYLES - 1; + mPlayer->setHairStyle(prevStyle % NR_HAIR_STYLES); } } diff --git a/src/net/accountserver/account.cpp b/src/net/accountserver/account.cpp index 7275cacc..daf94a65 100644 --- a/src/net/accountserver/account.cpp +++ b/src/net/accountserver/account.cpp @@ -30,7 +30,7 @@ #include "../protocol.h" void Net::AccountServer::Account::createCharacter( - const std::string &name, char hairColor, char hairStyle, char gender, + const std::string &name, char hairStyle, char hairColor, char gender, short strength, short agility, short vitality, short intelligence, short dexterity, short luck) { diff --git a/src/net/accountserver/account.h b/src/net/accountserver/account.h index 368623e6..aaf3afe0 100644 --- a/src/net/accountserver/account.h +++ b/src/net/accountserver/account.h @@ -33,7 +33,7 @@ namespace Net namespace Account { void createCharacter(const std::string &name, - char hairColor, char hairStyle, char gender, + char hairStyle, char hairColor, char gender, short strength, short agility, short vitality, short intelligence, short dexterity, short luck); diff --git a/src/player.cpp b/src/player.cpp index 63ed5455..288401e4 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -140,9 +140,11 @@ Player::setHairColor(Uint16 color) { if (color != mHairColor) { + Being::setHairColor(color); + AnimatedSprite *newHairSprite = new AnimatedSprite( "graphics/sprites/hairstyle" + toString(mHairStyle) + ".xml", - color); + mHairColor); newHairSprite->setDirection(getSpriteDirection()); delete mSprites[HAIR_SPRITE]; @@ -150,8 +152,6 @@ Player::setHairColor(Uint16 color) setAction(mAction); } - - Being::setHairColor(color); } void @@ -159,8 +159,10 @@ Player::setHairStyle(Uint16 style) { if (style != mHairStyle) { + Being::setHairStyle(style); + AnimatedSprite *newHairSprite = new AnimatedSprite( - "graphics/sprites/hairstyle" + toString(style) + ".xml", + "graphics/sprites/hairstyle" + toString(mHairStyle) + ".xml", mHairColor); newHairSprite->setDirection(getSpriteDirection()); @@ -169,8 +171,6 @@ Player::setHairStyle(Uint16 style) setAction(mAction); } - - Being::setHairStyle(style); } void -- cgit v1.2.3-60-g2f50 From fc63e88f869919a8b035a5c41db8d05626526bde Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 11 Mar 2007 19:59:55 +0000 Subject: Merged 0.0 changes from revision 3065 to 3177 to trunk. --- ChangeLog | 150 ++++++++++++++++++++++++++++++- INSTALL | 2 +- NEWS | 6 +- README | 2 +- configure.ac | 9 +- data/graphics/CMakeLists.txt | 1 - data/graphics/Makefile.am | 2 +- data/graphics/gui/mouse.png | Bin 449 -> 984 bytes data/graphics/gui/target-cursor-blue.png | Bin 0 -> 8353 bytes data/graphics/gui/target-cursor-red.png | Bin 0 -> 8361 bytes data/help/header.txt | 2 +- src/being.cpp | 35 ++++++-- src/being.h | 24 +++-- src/engine.cpp | 11 --- src/engine.h | 7 +- src/gui/menuwindow.cpp | 25 ++++-- src/gui/register.cpp | 1 + src/gui/updatewindow.cpp | 131 ++++++++++++++++----------- src/gui/updatewindow.h | 64 ++++--------- src/gui/viewport.cpp | 14 +-- src/localplayer.h | 11 +++ src/log.cpp | 17 ++-- src/logindata.h | 1 + src/main.cpp | 56 +++++++++--- src/main.h | 1 + src/map.cpp | 4 +- src/monster.cpp | 22 ++++- src/monster.h | 15 ++++ src/net/beinghandler.cpp | 33 ++++--- src/resources/resourcemanager.cpp | 27 ++++++ src/resources/resourcemanager.h | 8 ++ 31 files changed, 490 insertions(+), 191 deletions(-) create mode 100644 data/graphics/gui/target-cursor-blue.png create mode 100644 data/graphics/gui/target-cursor-red.png (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index b90c35ad..4357e837 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,20 @@ -2007-03-03 Rogier Polak +2007-03-11 Philipp Sehmisch - * src/main.cpp: Fixed a minor annoyance regarding - auto-character-select and switch_character. + * src/map.cpp, src/gui/viewport.cpp: Fixed a bug that made the engine + not draw the last row and column of the map. + +2007-03-09 Bjørn Lindeijer + + * data/graphics/gui/target-cursor-blue.png, + data/graphics/gui/target-cursor-red.png: Added targeting cursors by Pauan. + * data/graphics/sprites/chest-cotton-male.png, + data/graphics/sprites/chest-cotton-female.png: Replaced cotton shirt with + improved version by Pauan. + +2007-03-03 Rogier Polak + + * src/main.cpp: Fixed a minor annoyance regarding + auto-character-select and switch_character. 2007-03-03 Bjørn Lindeijer @@ -28,6 +41,17 @@ channels by Trapdoor. * src/graphics.h: MSVC Compilation fix by Trapdoor. +2007-02-26 Bjørn Lindeijer + + * configure.ac: Made OpenGL enabled by default. + +2007-02-26 Philipp Sehmisch + + * data/sfx/maggot-dying1.ogg, data/sfx/maggot-hit1.ogg, + data/sfx/maggot-hit2.ogg, data/sfx/maggot-miss1.ogg, + data/sfx/pinkie-hit1.ogg, data/sfx/pinkie-miss1.ogg, + data/monsters.xml: New sound effects by Cosmostrator. + 2007-02-25 Bjørn Lindeijer * src/CMakeLists.txt: Updated CMake file. @@ -54,8 +78,126 @@ size and data type. * src/logindata.h: Added a clear function. +2007-02-21 Philipp Sehmisch + + * src/gui/char-server.cpp, src/gui/updatewindow.cpp, src/gui/main.cpp, + src/gui/main.h: Added a new state "LOADDATA_STATE" that loads the XML + databases. + * src/resourcemanager.cpp, src/resourcemanager.h, src/main.cpp, + customdata/: Added a customdata dir that allows to add custom user + data easily. Just create a zip file with the same structure like the + update archives and drop it in the customdata folder and the files in + it override the default data and the updates. + +2007-02-20 Bjørn Lindeijer + + * src/log.cpp: Applied patch by trapdoor to fix the usage of a + deprecated function on MacOS X 10.4 and later. + * src/being.cpp, src/monster.cpp, src/net/beinghandler.cpp, + src/localplayer.h, src/being.h, src/monster.h: Now different sounds + can play when a monster misses the player. + * src/main.cpp: Applied patch by trapdoor which makes TMW use a more + standard location for the data on MacOS X. + +2007-02-17 Bjørn Lindeijer + + * data/help/header.txt, NEWS, README: Updated release date. + * data/graphics/sprites/Makefile.am, + data/graphics/sprites/CMakeLists.txt, data/graphics/CMakeLists.txt: + Excluded sprites directory from installed files. + +2007-02-16 Rogier Polak + + * src/gui/updatewindow.cpp: Fixed the update bug (hopefully), by + modifying the usage of the synchronisation between threads. Added a + check for existence of the updated file. + +2007-02-15 Bjørn Lindeijer + + * src/winver.h, README, configure.ac, data/help/header.txt, NEWS, + CMakeLists.txt: Changed version to 0.0.22.2. + +2007-02-13 Philipp Sehmisch + + * src/gui/register.cpp, src/logindata.h, src/main.cpp: Fixed the _M/_F + username bug. + +2007-02-11 Philipp Sehmisch + + * data/maps/new_1-9.tmx.gz, data/maps/new_1-14.tmx.gz, + data/maps/new_1-16.tmx.gz: Restored the cloud shadow overlays in the + woodland that got lost somehow during the halloween and christmas chaos. + +2007-02-11 Bjørn Lindeijer + + * data/graphics/sprites/chest_cotton_female.png: Removed this strange + duplicate. + * data/graphics/sprites/Makefile.am, + data/graphics/sprites/CMakeLists.txt: Some updates. + +2007-02-10 Philipp Sehmisch + + * src/gui/viewport.cpp: Fixed the bug in the scrolling limitation that made + it possible to scroll outside of the map in the south and east. + +2007-02-04 Bjørn Lindeijer + + * src/gui/menuwindow.cpp: Fixed a small glitch when dragging the menu + window. + +2007-02-03 Philipp Sehmisch + + * data/graphics/sprites/player-female-base.png: Made the standing and + walking of the female characters more feminine. + * data/equipment.xml, data/graphics/sprites/leg-cotton-male.png, + data/graphics/sprites/leg-cotton-male.xml, + data/graphics/sprites/leg-cotton-female.png, + data/graphics/sprites/leg-cotton-female.xml, + data/graphics/sprites/leg-jeans-male.png, + data/graphics/sprites/leg-jeans-male.xml, + data/graphics/sprites/leg-jeans-female.png, + data/graphics/sprites/leg-jeans-female.xml: Added different sprites + for male and female pants. + +2007-02-02 Bjørn Lindeijer + + * src/engine.h, src/engine.cpp, src/being.h, src/being.cpp: Moved + responsibility of loading emoticons to the Being class. + +2007-02-01 Eugenio Favalli + + * src/gui/updatewindow.cpp: File handle should be closed before + attempting to remove/rename files. + * src/gui/button.h: Fixed buttons loosing focus. + +2007-02-01 Bjørn Lindeijer + + * src/gui/updatewindow.cpp, src/gui/updatewindow.h: A bit of cleanup + and defined a helper function for calculating the alder32 checksum of + a file. Probably not fixing any bug though. + +2007-02-01 Philipp Sehmisch + + * data/equipment.xml, data/items.xml, + data/graphics/items/armor-chest-chainmail.png, + data/graphics/sprites/chest-chainmail-female.png, + data/graphics/sprites/chest-chainmail-female.xml, + data/graphics/sprites/chest-chainmail-male.png, + data/graphics/sprites/chest-chainmail-male.xml: Added chainmail by + "The Judge". The proposed values are: Item ID: 625, Sprite ID: 25, + Defence: 12, Weight: 120. + * data/graphics/sprites/chest-cotton-female.png: Huh? Shouldn't this + be on svn for ages? + +2007-01-30 Eugenio Favalli + + * tmw.cbp: Updated Code::blocks project. + 2007-01-30 Bjørn Lindeijer + * src/CMakeLists.txt, src/Makefile.am, src/net/packet.h, + src/net/packet.cpp, src/net/messageout.cpp: Removed unused Packet + class. * src/properties.h, src/being.cpp, src/beingmanager.h, src/sound.h, src/gui/window.h, src/sound.cpp, src/main.h, src/being.h, src/resources/soundeffect.h, src/resources/image.h, @@ -69,6 +211,8 @@ src/net/messageout.h, src/utils/xml.h, src/main.h, src/resources/monsterdb.h, src/resources/itemdb.h, src/resources/equipmentdb.h: Some work on documentation. + * data/maps/new_8-1.tmx.gz, data/maps/new_11-1.tmx.gz: Map fixes by + Pauan. 2007-01-23 Bjørn Lindeijer diff --git a/INSTALL b/INSTALL index 0f5d53f0..fb168106 100644 --- a/INSTALL +++ b/INSTALL @@ -19,7 +19,7 @@ and some libraries. The required libraries are: * SDL http://www.libsdl.org/ * SDL_mixer http://www.libsdl.org/projects/SDL_mixer/ * SDL_image http://www.libsdl.org/projects/SDL_image/ -* SDL_net http://www.libsdl.org/projects/SDL_net/ +* ENet 1.0 http://enet.bespin.org/ * Guichan 0.6.x http://guichan.sourceforge.net/ * libxml2 http://www.xmlsoft.org/ * physfs 1.0.x http://icculus.org/physfs/ diff --git a/NEWS b/NEWS index adeca670..5281cf78 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ -0.0.22.2 (...) +0.0.22.2 (17 February 2007) - Updated to work with Guichan 0.6.1 +- Changed to new default server (server.themanaworld.org) +- Changed custom mouse cursor +- Fixed the issue where _M or _F is appended to the username +- Fixed problem with Cancel button in update dialog 0.0.22.1 (15 January 2007) - Updated to work with Guichan 0.6.0 (older versions no longer supported) diff --git a/README b/README index bf128182..2d6f07b1 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ THE MANA WORLD ============== - Version: 0.0.22.1 Date: 15/01/2007 + Version: 0.0.22.2 Date: 17/02/2007 Development team: diff --git a/configure.ac b/configure.ac index ca31930e..21d9ef56 100755 --- a/configure.ac +++ b/configure.ac @@ -94,15 +94,15 @@ AC_HEADER_STDC AC_CHECK_HEADERS([arpa/inet.h fcntl.h malloc.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h]) # Option to enable OpenGL -AC_ARG_WITH(opengl, AS_HELP_STRING([--with-opengl],[use OpenGL (default is no)])) -if test "x$with_opengl" == "xyes"; then +AC_ARG_WITH(opengl,[ --without-opengl don't use OpenGL ] ) +if test "x$with_opengl" == "xno"; then + with_opengl=no +else AC_CHECK_LIB([GL], [glBegin], , AC_MSG_ERROR([ *** Unable to find OpenGL library])) AC_CHECK_LIB([guichan_opengl], [gcnOpenGL], , AC_MSG_ERROR([ *** Unable to find Guichan OpenGL library (guichan.sf.net)])) AC_DEFINE(USE_OPENGL, 1, [Defines if tmw should use an OpenGL display]) -else - with_opengl=no fi AC_CONFIG_FILES([ @@ -113,7 +113,6 @@ data/graphics/Makefile data/graphics/gui/Makefile data/graphics/images/Makefile data/graphics/images/ambient/Makefile -data/graphics/sprites/Makefile data/graphics/tiles/Makefile data/help/Makefile data/icons/Makefile diff --git a/data/graphics/CMakeLists.txt b/data/graphics/CMakeLists.txt index 0fa9a7be..9a916db3 100644 --- a/data/graphics/CMakeLists.txt +++ b/data/graphics/CMakeLists.txt @@ -1,4 +1,3 @@ ADD_SUBDIRECTORY(gui) ADD_SUBDIRECTORY(images) -ADD_SUBDIRECTORY(sprites) ADD_SUBDIRECTORY(tiles) diff --git a/data/graphics/Makefile.am b/data/graphics/Makefile.am index 43354894..8cda8fa3 100644 --- a/data/graphics/Makefile.am +++ b/data/graphics/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = gui images sprites tiles +SUBDIRS = gui images tiles diff --git a/data/graphics/gui/mouse.png b/data/graphics/gui/mouse.png index e6a84021..9276fc7c 100644 Binary files a/data/graphics/gui/mouse.png and b/data/graphics/gui/mouse.png differ diff --git a/data/graphics/gui/target-cursor-blue.png b/data/graphics/gui/target-cursor-blue.png new file mode 100644 index 00000000..3e81c75d Binary files /dev/null and b/data/graphics/gui/target-cursor-blue.png differ diff --git a/data/graphics/gui/target-cursor-red.png b/data/graphics/gui/target-cursor-red.png new file mode 100644 index 00000000..09195f44 Binary files /dev/null and b/data/graphics/gui/target-cursor-red.png differ diff --git a/data/help/header.txt b/data/help/header.txt index aef87a45..7311c111 100644 --- a/data/help/header.txt +++ b/data/help/header.txt @@ -2,7 +2,7 @@ ##1 T H E M A N A W O R L D ##1 ========================================== - ##2Version:##6 0.0.22.1 ##2Date:##315 January 2007 + ##2Version:##6 0.0.22.2 ##2Date:##317 February 2007 ##2 Website: http://themanaworld.org diff --git a/src/being.cpp b/src/being.cpp index 33ee7e7a..e4a1e9fc 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -33,6 +33,7 @@ #include "log.h" #include "map.h" +#include "resources/resourcemanager.h" #include "resources/spriteset.h" #include "gui/gui.h" @@ -40,12 +41,8 @@ #include "utils/dtor.h" #include "utils/tostring.h" -extern Spriteset *emotionset; - -PATH_NODE::PATH_NODE(unsigned short x, unsigned short y): - x(x), y(y) -{ -} +int Being::instances = 0; +Spriteset *Being::emotionset = NULL; Being::Being(Uint16 id, Uint16 job, Map *map): mJob(job), @@ -70,6 +67,16 @@ Being::Being(Uint16 id, Uint16 job, Map *map): mEquipmentSpriteIDs(VECTOREND_SPRITE, 0) { setMap(map); + + if (instances == 0) + { + // Load the emotion set + ResourceManager *rm = ResourceManager::getInstance(); + emotionset = rm->getSpriteset("graphics/sprites/emotions.png", 30, 32); + if (!emotionset) logger->error("Unable to load emotions spriteset!"); + } + + instances++; } Being::~Being() @@ -77,6 +84,14 @@ Being::~Being() std::for_each(mSprites.begin(), mSprites.end(), make_dtor(mSprites)); clearPath(); setMap(NULL); + + instances--; + + if (instances == 0) + { + emotionset->decRef(); + emotionset = NULL; + } } void Being::adjustCourse(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY) @@ -275,12 +290,18 @@ Being::setSpeech(const std::string &text, Uint32 time) } void -Being::setDamage(Sint16 amount, Uint32 time) +Being::takeDamage(int amount) { mDamage = amount ? toString(amount) : "miss"; mDamageTime = 300; } +void +Being::handleAttack() +{ + setAction(Being::ATTACK); +} + void Being::setMap(Map *map) { diff --git a/src/being.h b/src/being.h index 3c6b14c6..c3cba247 100644 --- a/src/being.h +++ b/src/being.h @@ -43,12 +43,17 @@ class Map; class Graphics; class Spriteset; +/** + * A position along a being's path. + */ struct PATH_NODE { /** * Constructor. */ - PATH_NODE(unsigned short x, unsigned short y); + PATH_NODE(unsigned short x, unsigned short y): + x(x), y(y) + { } unsigned short x; unsigned short y; @@ -148,13 +153,19 @@ class Being : public Sprite void setSpeech(const std::string &text, Uint32 time); /** - * Puts a damage bubble above this being for the specified amount - * of time. + * Puts a damage bubble above this being for the specified amount of + * time. * * @param amount The amount of damage. - * @param time The amount of time the text should stay in milliseconds. */ - void setDamage(Sint16 amount, Uint32 time); + virtual void + takeDamage(int amount); + + /** + * Handles an attack of another being by this being. + */ + virtual void + handleAttack(); /** * Returns the name of the being. @@ -384,6 +395,9 @@ class Being : public Sprite Sint16 mStepX, mStepY; Uint16 mStepTime; + + static int instances; /**< Number of Being instances */ + static Spriteset *emotionset; /**< Emoticons used by beings */ }; #endif diff --git a/src/engine.cpp b/src/engine.cpp index d2ce6d6f..a3097d49 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -53,20 +53,9 @@ extern Minimap *minimap; char itemCurrenyQ[10] = "0"; -Spriteset *emotionset; - Engine::Engine(): mCurrentMap(NULL) { - // Load the emotion set - ResourceManager *resman = ResourceManager::getInstance(); - emotionset = resman->getSpriteset("graphics/sprites/emotions.png", 30, 32); - if (!emotionset) logger->error("Unable to load emotions spriteset!"); -} - -Engine::~Engine() -{ - emotionset->decRef(); } void Engine::changeMap(const std::string &mapPath) diff --git a/src/engine.h b/src/engine.h index b16b7c13..161a1e63 100644 --- a/src/engine.h +++ b/src/engine.h @@ -30,7 +30,7 @@ class Map; /** * Game engine. Actually hardly does anything anymore except keeping track of - * the current map and loading the emotes. + * the current map. */ class Engine { @@ -40,11 +40,6 @@ class Engine */ Engine(); - /** - * Destructor. - */ - ~Engine(); - /** * Returns the currently active map. */ diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp index a5b5c99e..943cc6f0 100644 --- a/src/gui/menuwindow.cpp +++ b/src/gui/menuwindow.cpp @@ -30,8 +30,11 @@ #include "button.h" #include "windowcontainer.h" -extern Window *setupWindow, *inventoryWindow, *equipmentWindow, - *skillDialog, *statusWindow; +extern Window *setupWindow; +extern Window *inventoryWindow; +extern Window *equipmentWindow; +extern Window *skillDialog; +extern Window *statusWindow; namespace { struct MenuWindowListener : public gcn::ActionListener @@ -52,9 +55,14 @@ MenuWindow::MenuWindow(): setTitleBarHeight(0); // Buttons - // ------------ - const char *buttonNames[] = { - "Status", "Equipment", "Inventory", "Skills", "Setup", 0 + const char *buttonNames[] = + { + "Status", + "Equipment", + "Inventory", + "Skills", + "Setup", + 0 }; int x = 0, y = 3, h = 0; @@ -67,7 +75,11 @@ MenuWindow::MenuWindow(): h = btn->getHeight(); } - setDefaultSize((windowContainer->getWidth() - x - 2), 0, x, (y + h)); + setContentSize(x - 3, h); + setDefaultSize(windowContainer->getWidth() - getWidth() - 1, + 0, + x - 3, + y + h); } void MenuWindow::draw(gcn::Graphics *graphics) @@ -79,6 +91,7 @@ void MenuWindow::draw(gcn::Graphics *graphics) void MenuWindowListener::action(const gcn::ActionEvent &event) { Window *window = NULL; + if (event.getId() == "Status") { window = statusWindow; diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 4539e48e..be15747d 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -195,6 +195,7 @@ RegisterDialog::action(const gcn::ActionEvent &event) mLoginData->username = mUserField->getText(); mLoginData->password = mPasswordField->getText(); mLoginData->email = mEmailField->getText(); + mLoginData->registerLogin = true; state = STATE_REGISTER_ATTEMPT; } diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index fe78a27b..d8130cd3 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -46,13 +46,41 @@ #include "../resources/resourcemanager.h" +/** + * Calculates the Alder-32 checksum for the given file. + */ +unsigned long fadler32(FILE *file) +{ + // Obtain file size + fseek(file, 0, SEEK_END); + long fileSize = ftell(file); + rewind(file); + + // Calculate Adler-32 checksum + char *buffer = (char*) malloc(fileSize); + fread(buffer, 1, fileSize, file); + unsigned long adler = adler32(0L, Z_NULL, 0); + adler = adler32(adler, (Bytef*) buffer, fileSize); + free(buffer); + + return adler; +} + UpdaterWindow::UpdaterWindow(): Window("Updating..."), - mThread(NULL), mMutex(NULL), mDownloadStatus(UPDATE_NEWS), - mUpdateHost(""), mCurrentFile("news.txt"), mBasePath(""), - mStoreInMemory(true), mDownloadComplete(true), mUserCancel(false), - mDownloadedBytes(0), mMemoryBuffer(NULL), - mCurlError(new char[CURL_ERROR_SIZE]), mLineIndex(0) + mThread(NULL), + mDownloadStatus(UPDATE_NEWS), + mUpdateHost(""), + mCurrentFile("news.txt"), + mCurrentChecksum(0), + mBasePath(""), + mStoreInMemory(true), + mDownloadComplete(true), + mUserCancel(false), + mDownloadedBytes(0), + mMemoryBuffer(NULL), + mCurlError(new char[CURL_ERROR_SIZE]), + mLineIndex(0) { mCurlError[0] = 0; @@ -151,7 +179,7 @@ void UpdaterWindow::action(const gcn::ActionEvent &event) } else if (event.getId() == "play") { - state = STATE_LOGIN; + state = STATE_LOADDATA; } } @@ -206,22 +234,17 @@ int UpdaterWindow::updateProgress(void *ptr, return 0; } -size_t UpdaterWindow::memoryWrite(void *ptr, - size_t size, size_t nmemb, FILE *stream) +size_t +UpdaterWindow::memoryWrite(void *ptr, size_t size, size_t nmemb, FILE *stream) { UpdaterWindow *uw = reinterpret_cast(stream); size_t totalMem = size * nmemb; - uw->mMemoryBuffer = (char*)realloc(uw->mMemoryBuffer, - uw->mDownloadedBytes + totalMem + 1); + uw->mMemoryBuffer = (char*) realloc(uw->mMemoryBuffer, + uw->mDownloadedBytes + totalMem); if (uw->mMemoryBuffer) { memcpy(&(uw->mMemoryBuffer[uw->mDownloadedBytes]), ptr, totalMem); uw->mDownloadedBytes += totalMem; - - // Make sure the memory buffer is NULL terminated, because this - // function is used to download text files that are later parsed as a - // string. - uw->mMemoryBuffer[uw->mDownloadedBytes] = 0; } return totalMem; @@ -236,8 +259,10 @@ int UpdaterWindow::downloadThread(void *ptr) std::string outFilename; std::string url(uw->mUpdateHost + "/" + uw->mCurrentFile); - while (attempts < 3 && !uw->mDownloadComplete) { + while (attempts < 3 && !uw->mDownloadComplete) + { FILE *outfile = NULL; + FILE *newfile = NULL; uw->setLabel(uw->mCurrentFile + " (0%)"); curl = curl_easy_init(); @@ -282,61 +307,67 @@ int UpdaterWindow::downloadThread(void *ptr) uw->mDownloadStatus = UPDATE_ERROR; switch (res) { - case CURLE_COULDNT_CONNECT: // give more debug info on that error - std::cerr << "curl error " << res << " : " << uw->mCurlError << " " << url.c_str() - << std::endl; + case CURLE_COULDNT_CONNECT: + // give more debug info on that error + std::cerr << "curl error " << res << ": " + << uw->mCurlError << " " << url.c_str() + << std::endl; break; default: - std::cerr << "curl error " << res << " : " << uw->mCurlError << " host: " << url.c_str() - << std::endl; + std::cerr << "curl error " << res << ": " + << uw->mCurlError << " host: " << url.c_str() + << std::endl; } } curl_easy_cleanup(curl); - uw->mDownloadComplete = true; - if (!uw->mStoreInMemory) { - long fileSize; - char *buffer; - // Obtain file size. - fseek(outfile, 0, SEEK_END); - fileSize = ftell(outfile); - rewind(outfile); - buffer = (char*)malloc(fileSize); - fread(buffer, 1, fileSize, outfile); - fclose(outfile); - - // Give the file the proper name - std::string newName(uw->mBasePath + "/updates/" + - uw->mCurrentFile.c_str()); - - // Any existing file with this name is deleted first, otherwise the - // rename will fail on Windows. - ::remove(newName.c_str()); - ::rename(outFilename.c_str(), newName.c_str()); - // Don't check resources2.txt checksum if (uw->mDownloadStatus == UPDATE_RESOURCES) { - // Calculate Adler-32 checksum - unsigned long adler = adler32(0L, Z_NULL, 0); - adler = adler32(adler, (Bytef *)buffer, fileSize); - free(buffer); + unsigned long adler = fadler32(outfile); + + if (uw->mCurrentChecksum != adler) + { + fclose(outfile); - if (uw->mCurrentChecksum != adler) { - uw->mDownloadComplete = false; // Remove the corrupted file - ::remove(newName.c_str()); + ::remove(outFilename.c_str()); logger->log( "Checksum for file %s failed: (%lx/%lx)", uw->mCurrentFile.c_str(), adler, uw->mCurrentChecksum); + attempts++; + continue; // Bail out here to avoid the renaming } } + fclose(outfile); + + // Give the file the proper name + std::string newName(uw->mBasePath + "/updates/" + + uw->mCurrentFile.c_str()); + // Any existing file with this name is deleted first, otherwise + // the rename will fail on Windows. + ::remove(newName.c_str()); + ::rename(outFilename.c_str(), newName.c_str()); + + // Check if we can open it and no errors were encountered + // during renaming + newfile = fopen(newName.c_str(), "rb"); + if (newfile) + { + fclose(newfile); + uw->mDownloadComplete = true; + } + } + else + { + // It's stored in memory, we're done + uw->mDownloadComplete = true; } } attempts++; @@ -398,8 +429,8 @@ void UpdaterWindow::logic() mCurrentFile = "resources2.txt"; mStoreInMemory = false; - download(); mDownloadStatus = UPDATE_LIST; + download(); // download() changes mDownloadComplete to false } break; case UPDATE_LIST: diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index 8c54be27..b5f6a6df 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -89,7 +89,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener void download(); /** - * The tread function that download the files. + * The thread function that download the files. */ static int downloadThread(void *ptr); @@ -115,80 +115,46 @@ class UpdaterWindow : public Window, public gcn::ActionListener UPDATE_RESOURCES }; - /** - * A thread that use libcurl to download updates. - */ + /** A thread that use libcurl to download updates. */ SDL_Thread *mThread; - /** - * A mutex to protect shared data between the threads. - */ - SDL_mutex *mMutex; - - /** - * Status of the current download. - */ + /** Status of the current download. */ DownloadStatus mDownloadStatus; - /** - * Host where we get the updated files. - */ + /** Host where we get the updated files. */ std::string mUpdateHost; - /** - * The file currently downloading. - */ + /** The file currently downloading. */ std::string mCurrentFile; - /** - * The Adler32 checksum of the file currently downloading. - */ + /** The Adler32 checksum of the file currently downloading. */ unsigned long mCurrentChecksum; - /** - * Absolute path to locally save downloaded files. - */ + /** Absolute path to locally save downloaded files. */ std::string mBasePath; - /** - * A flag to know if we must write the downloaded file to a memory buffer - * instead of a regular file. - */ + /** A flag to indicate whether to use a memory buffer or a regular file. */ bool mStoreInMemory; - /** - * Flag that show if current download is complete. - */ + /** Flag that show if current download is complete. */ bool mDownloadComplete; - /** - * Flag that show if the user has canceled the update - */ + /** Flag that show if the user has canceled the update. */ bool mUserCancel; - /** - * Byte count currently downloaded in mMemoryBuffer. - */ + /** Byte count currently downloaded in mMemoryBuffer. */ int mDownloadedBytes; - /** - * Buffer where to put downloaded file which are not stored in file system. - */ + /** Buffer for files downloaded to memory. */ char *mMemoryBuffer; - /** - * Buffer to handler human readable error provided by curl. - */ + /** Buffer to handler human readable error provided by curl. */ char *mCurlError; - /** - * List of files to download - */ + /** List of files to download. */ std::vector mLines; - /** - * Index of the file to be downloaded - */ + /** Index of the file to be downloaded. */ unsigned int mLineIndex; gcn::Label *mLabel; /**< Progress bar caption. */ diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 5f316aea..bc635cce 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -132,18 +132,22 @@ Viewport::draw(gcn::Graphics *gcnGraphics) mViewY = player_y; }; - if (mMap) { + // Don't move camera so that the end of the map is on screen + int viewXmax = mMap->getWidth() * 32 - graphics->getWidth(); + int viewYmax = mMap->getHeight() * 32 - graphics->getHeight(); + if (mMap) + { if (mViewX < 0) { mViewX = 0; } if (mViewY < 0) { mViewY = 0; } - if (mViewX > mMap->getWidth() * 32 - midTileX) { - mViewX = mMap->getWidth() * 32 - midTileX; + if (mViewX > viewXmax) { + mViewX = viewXmax; } - if (mViewY > mMap->getHeight() * 32 - midTileY) { - mViewY = mMap->getHeight() * 32 - midTileY; + if (mViewY > viewYmax) { + mViewY = viewYmax; } } diff --git a/src/localplayer.h b/src/localplayer.h index 980b1aff..9ce67d13 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -35,6 +35,9 @@ class FloorItem; class Inventory; class Item; +/** + * The local player character. + */ class LocalPlayer : public Player { public: @@ -110,8 +113,16 @@ class LocalPlayer : public Player void setTrading(bool trading) { mTrading = trading; } void attack(); + Being* getTarget() const; + /** + * Overridden to do nothing. The attacks of the local player are + * displayed as soon as the player attacks, not when the server says + * the player does. + */ + virtual void handleAttack() {} + /** * Sets the target being of the player. */ diff --git a/src/log.cpp b/src/log.cpp index 3a3c91b8..224736bd 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -20,11 +20,13 @@ */ #include "log.h" + #ifdef WIN32 - #include "utils/wingettimeofday.h" +#include "utils/wingettimeofday.h" #else - #include +#include #endif + #ifdef __APPLE__ #include #endif @@ -110,9 +112,14 @@ void Logger::error(const std::string &error_text) MessageBox(NULL, error_text.c_str(), "Error", MB_ICONERROR | MB_OK); #elif defined __APPLE__ Str255 msg; - c2pstrcpy(msg, error_text.c_str()); - StandardAlert(kAlertStopAlert, "\pError", - (ConstStr255Param)msg, NULL, NULL); + CFStringRef error; + error = CFStringCreateWithCString(NULL, + error_text.c_str(), + kCFStringEncodingMacRoman); + CFStringGetPascalString(error, msg, 255, kCFStringEncodingMacRoman); + StandardAlert(kAlertStopAlert, + "\pError", + (ConstStr255Param) msg, NULL, NULL); #else std::cerr << "Error: " << error_text << std::endl; #endif diff --git a/src/logindata.h b/src/logindata.h index f9b520eb..0a01331c 100644 --- a/src/logindata.h +++ b/src/logindata.h @@ -37,6 +37,7 @@ struct LoginData int session_ID2; bool remember; + bool registerLogin; void clear() { diff --git a/src/main.cpp b/src/main.cpp index 1e7ae32d..aad6a68c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,10 +36,13 @@ #include -#if (defined __USE_UNIX98 || defined __FreeBSD__) +#if (defined __USE_UNIX98 || defined __FreeBSD__ || defined __APPLE__) #include #include #endif +#if defined __APPLE__ +#include +#endif #include "configuration.h" #include "game.h" @@ -150,7 +153,7 @@ struct Options */ void initHomeDir() { -#if !(defined __USE_UNIX98 || defined __FreeBSD__) +#if !(defined __USE_UNIX98 || defined __FreeBSD__ || defined __APPLE__) homeDir = "."; #else homeDir = std::string(PHYSFS_getUserDir()) + "/.tmw"; @@ -160,7 +163,7 @@ void initHomeDir() (errno != EEXIST)) { std::cout << homeDir - << " can't be made, but it doesn't exist! Exitting." + << " can't be made, but it doesn't exist! Exiting." << std::endl; exit(1); } @@ -259,7 +262,21 @@ void initEngine() // Add the main data directory to our PhysicsFS search path resman->addToSearchPath("data", true); +#if defined __APPLE__ + CFBundleRef mainBundle = CFBundleGetMainBundle(); + CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); + char path[PATH_MAX]; + if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, + PATH_MAX)) + { + fprintf(stderr, "Can't find Resources directory\n"); + } + CFRelease(resourcesURL); + strncat(path, "/data", PATH_MAX - 1); + resman->addToSearchPath(path, true); +#else resman->addToSearchPath(TMW_DATADIR "data", true); +#endif #ifdef USE_OPENGL bool useOpenGL = (config.getValue("opengl", 0) == 1); @@ -449,6 +466,12 @@ void accountLogin(LoginData *loginData) // Clear the password, avoids auto login when returning to login loginData->password = ""; + //remove _M or _F from username after a login for registration purpose + if (loginData->registerLogin) + { + loginData->registerLogin = false; + loginData->username = loginData->username.substr(0, loginData->username.length() - 2); + } // TODO This is not the best place to save the config, but at least better // than the login gui window if (loginData->remember) { @@ -657,6 +680,7 @@ int main(int argc, char *argv[]) } loginData.remember = config.getValue("remember", 0); + loginData.registerLogin = false; Net::initialize(); accountServerConnection = Net::getConnection(); @@ -717,7 +741,7 @@ int main(int argc, char *argv[]) accountServerConnection->isConnected()) { if (options.skipUpdate) { - state = STATE_LOGIN; + state = STATE_LOADDATA; } else { state = STATE_UPDATE; } @@ -794,17 +818,11 @@ int main(int argc, char *argv[]) logger->log("State: UPDATE"); // TODO: Revive later //currentDialog = new UpdaterWindow(); - state = STATE_LOGIN; + state = STATE_LOADDATA; break; case STATE_LOGIN: logger->log("State: LOGIN"); - - // Load XML databases - EquipmentDB::load(); - ItemDB::load(); - MonsterDB::load(); - currentDialog = new LoginDialog(&loginData); // TODO: Restore autologin //if (!loginData.password.empty()) { @@ -812,6 +830,22 @@ int main(int argc, char *argv[]) //} break; + case STATE_LOADDATA: + logger->log("State: LOADDATA"); + + // Add customdata directory + ResourceManager::getInstance()->searchAndAddArchives( + "customdata/", + "zip", + false); + + // Load XML databases + EquipmentDB::load(); + ItemDB::load(); + MonsterDB::load(); + state = STATE_LOGIN; + break; + case STATE_LOGIN_ATTEMPT: accountLogin(&loginData); break; diff --git a/src/main.h b/src/main.h index 4dd93ae8..1e9f8c09 100644 --- a/src/main.h +++ b/src/main.h @@ -72,6 +72,7 @@ enum { STATE_CHOOSE_SERVER, STATE_CONNECT_ACCOUNT, STATE_UPDATE, + STATE_LOADDATA, STATE_LOGIN, STATE_LOGIN_ATTEMPT, STATE_REGISTER, diff --git a/src/map.cpp b/src/map.cpp index a88926d7..a6beb951 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -147,8 +147,8 @@ Map::draw(Graphics *graphics, int scrollX, int scrollY, int layer) if (startX < 0) startX = 0; if (startY < 0) startY = 0; - if (endX >= mWidth) endX = mWidth - 1; - if (endY >= mHeight) endY = mHeight - 1; + if (endX > mWidth) endX = mWidth; + if (endY > mHeight) endY = mHeight; for (int y = startY; y < endY; y++) { diff --git a/src/monster.cpp b/src/monster.cpp index dd4a321c..bea5b7a5 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -57,11 +57,10 @@ Monster::setAction(Action action) break; case DEAD: currentAction = ACTION_DEAD; - sound.playSfx(MonsterDB::get(mJob - 1002).getSound(EVENT_DIE)); + sound.playSfx(getInfo().getSound(EVENT_DIE)); break; case ATTACK: currentAction = ACTION_ATTACK; - sound.playSfx(MonsterDB::get(mJob - 1002).getSound(EVENT_HIT)); mSprites[BASE_SPRITE]->reset(); break; case STAND: @@ -80,3 +79,22 @@ Monster::setAction(Action action) mAction = action; } } + +void +Monster::handleAttack() +{ + Being::handleAttack(); + + const MonsterInfo &mi = getInfo(); + + // TODO: It's not possible to determine hit or miss here, so this stuff probably needs + // to be moved somewhere else. We may lose synchronization between attack animation and + // the sound, unless we adapt the protocol... + sound.playSfx(mi.getSound(EVENT_HIT)); +} + +const MonsterInfo& +Monster::getInfo() const +{ + return MonsterDB::get(mJob - 1002); +} diff --git a/src/monster.h b/src/monster.h index 3e9cdb05..18fa703e 100644 --- a/src/monster.h +++ b/src/monster.h @@ -26,6 +26,8 @@ #include "being.h" +class MonsterInfo; + class Monster : public Being { public: @@ -34,6 +36,19 @@ class Monster : public Being virtual void setAction(Action action); virtual Type getType() const; + + /** + * Handles an attack of another being by this monster. Plays a hit or + * miss sound when appropriate. + */ + virtual void handleAttack(); + + protected: + /** + * Returns the MonsterInfo, with static data about this monster. + */ + const MonsterInfo& + getInfo() const; }; #endif diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index 32c78b39..53746671 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -215,29 +215,26 @@ void BeingHandler::handleMessage(MessageIn &msg) switch (type) { case 0: // Damage - if (dstBeing == NULL) break; - - dstBeing->setDamage(param1, SPEECH_TIME); - - if (srcBeing != NULL && - srcBeing != player_node) - { - srcBeing->setAction(Being::ATTACK); - srcBeing->mFrame = 0; - srcBeing->mWalkTime = tick_time; + if (dstBeing) { + dstBeing->takeDamage(param1); + } + if (srcBeing) { + srcBeing->handleAttack(dstBeing, param1); } break; case 2: // Sit - if (srcBeing == NULL) break; - srcBeing->mFrame = 0; - srcBeing->setAction(Being::SIT); + if (srcBeing) { + srcBeing->mFrame = 0; + srcBeing->setAction(Being::SIT); + } break; case 3: // Stand up - if (srcBeing == NULL) break; - srcBeing->mFrame = 0; - srcBeing->setAction(Being::STAND); + if (srcBeing) { + srcBeing->mFrame = 0; + srcBeing->setAction(Being::STAND); + } break; } break; @@ -525,7 +522,7 @@ void BeingHandler::handleBeingsDamageMessage(MessageIn &msg) int damage = msg.readShort(); if (being) { - being->setDamage(damage, 0); + being->takeDamage(damage); } } } @@ -535,5 +532,5 @@ void BeingHandler::handleBeingActionChangeMessage(MessageIn &msg) Being* being = beingManager->findBeing(msg.readShort()); if (!being) return; - being->setAction((Being::Action)msg.readByte()); + being->setAction((Being::Action) msg.readByte()); } diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 45067302..2059a5c3 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -112,6 +112,33 @@ ResourceManager::addToSearchPath(const std::string &path, bool append) PHYSFS_addToSearchPath(path.c_str(), append ? 1 : 0); } +void +ResourceManager::searchAndAddArchives(const std::string &path, + const std::string &ext, + bool append) +{ + const char *dirSep = PHYSFS_getDirSeparator(); + char **list = PHYSFS_enumerateFiles(path.c_str()); + + for (char **i = list; *i != NULL; i++) + { + size_t len = strlen(*i); + + if (len > ext.length() && !ext.compare((*i)+(len - ext.length()))) + { + std::string file, realPath, archive; + + file = path + (*i); + realPath = std::string(PHYSFS_getRealDir(file.c_str())); + archive = realPath + dirSep + file; + + addToSearchPath(archive, append); + } + } + + PHYSFS_freeList(list); +} + bool ResourceManager::mkdir(const std::string &path) { diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index d458f96e..e176e337 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -82,6 +82,14 @@ class ResourceManager void addToSearchPath(const std::string &path, bool append); + /** + * Searches for zip files and adds them to the search path. + */ + void + searchAndAddArchives(const std::string &path, + const std::string &ext, + bool append); + /** * Creates a directory in the write path */ -- cgit v1.2.3-60-g2f50 From bfbb797e6c528e0650826e917d498c52362abbb0 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sat, 24 Mar 2007 16:24:43 +0000 Subject: Merged 0.0 changes from revision 3177 to 3234 to trunk. --- ChangeLog | 162 +++++++- data/graphics/gui/deepbox.png | Bin 266 -> 270 bytes data/graphics/gui/mouse.png | Bin 984 -> 1134 bytes data/graphics/gui/slider.png | Bin 502 -> 571 bytes data/graphics/gui/thickborder.png | Bin 480 -> 530 bytes data/graphics/gui/vscroll_blue.png | Bin 368 -> 395 bytes data/graphics/gui/vscroll_grey.png | Bin 342 -> 371 bytes data/graphics/gui/vscroll_red.png | Bin 367 -> 394 bytes data/icons/CMakeLists.txt | 6 +- data/icons/Makefile.am | 7 +- data/icons/tmw-icon.ico | Bin 2238 -> 0 bytes data/icons/tmw-icon.png | Bin 1103 -> 0 bytes data/icons/tmw-icon.xpm | 56 --- data/icons/tmw.ico | Bin 0 -> 22382 bytes data/icons/tmw.png | Bin 0 -> 18176 bytes data/icons/tmw.xpm | 784 +++++++++++++++++++++++++++++++++++++ docs/Makefile.am | 2 + docs/tmw.6 | 74 ++++ src/CMakeLists.txt | 6 +- src/Makefile.am | 6 +- src/animatedsprite.cpp | 1 - src/being.cpp | 14 +- src/being.h | 4 +- src/engine.cpp | 4 +- src/floor_item.cpp | 1 - src/gui/char_select.cpp | 65 +-- src/gui/char_select.h | 12 +- src/gui/equipmentwindow.cpp | 1 - src/gui/itemcontainer.cpp | 8 +- src/gui/login.cpp | 87 ++-- src/gui/login.h | 30 +- src/gui/register.cpp | 89 +++-- src/gui/register.h | 37 +- src/gui/unregisterdialog.cpp | 2 +- src/gui/viewport.cpp | 110 ++++-- src/gui/viewport.h | 24 ++ src/localplayer.cpp | 1 + src/localplayer.h | 12 + src/logindata.h | 4 +- src/main.cpp | 101 +++-- src/monster.h | 1 - src/net/charserverhandler.cpp | 24 +- src/net/charserverhandler.h | 13 + src/net/equipmenthandler.cpp | 5 + src/net/loginhandler.cpp | 2 +- src/net/protocol.h | 1 + src/npc.cpp | 2 - src/resources/animation.h | 1 - src/resources/image.cpp | 124 +++--- src/resources/image.h | 6 + src/resources/imageset.cpp | 65 +++ src/resources/imageset.h | 66 ++++ src/resources/monsterdb.h | 2 +- src/resources/monsterinfo.h | 157 ++++---- src/resources/resourcemanager.cpp | 22 +- src/resources/resourcemanager.h | 8 +- src/resources/spritedef.cpp | 34 +- src/resources/spritedef.h | 10 +- src/resources/spriteset.cpp | 65 --- src/resources/spriteset.h | 69 ---- src/simpleanimation.cpp | 50 +++ src/simpleanimation.h | 65 +++ src/tileset.h | 8 +- src/tmw.rc | 2 +- tmw.cbp | 22 +- 65 files changed, 1922 insertions(+), 612 deletions(-) delete mode 100644 data/icons/tmw-icon.ico delete mode 100644 data/icons/tmw-icon.png delete mode 100644 data/icons/tmw-icon.xpm create mode 100644 data/icons/tmw.ico create mode 100644 data/icons/tmw.png create mode 100644 data/icons/tmw.xpm create mode 100644 docs/tmw.6 create mode 100644 src/resources/imageset.cpp create mode 100644 src/resources/imageset.h delete mode 100644 src/resources/spriteset.cpp delete mode 100644 src/resources/spriteset.h create mode 100644 src/simpleanimation.cpp create mode 100644 src/simpleanimation.h (limited to 'data/graphics') diff --git a/ChangeLog b/ChangeLog index 95cf4044..d0f661a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,23 @@ -2007-03-23 Eugenio Favalli +2007-03-24 Bjørn Lindeijer + + * src/main.cpp: Changed the order of network message handling and + logic, in order to prevent an incoming character delete message from + deleting the player character that was about to be drawn. + * src/gui/char_select.cpp: Removed useless lock/unlock calls. + * src/logindata.h, src/main.cpp, src/gui/login.cpp: Go back to login + or register state on error, depending on what the user was doing. + * src/gui/register.cpp: Actually use the server that is filled in. + * src/net/loginhandler.cpp: Fixed error message. + * src/net/charserverhandler.cpp: Fixed crash since now logic is called + after non-selected characters are deleted, by properly setting deleted + instances to 0 and going back to initial selection. + * src/main.cpp, src/net/network.h, src/net/network.cpp: Make sure that + when a network error occurs, the error message is available and shown + to the user. + * src/gui/register.h, src/gui/register.cpp: Only enable Register + button when all necessary fields are filled in. + +2007-03-23 Eugenio Favalli * tmw.cbp: Updated and fixed Code::Blocks project file. @@ -6,19 +25,116 @@ * src/gui/char_select.cpp, src/gui/inventorywindow.cpp, src/gui/ministatus.cpp, src/gui/ministatus.h, src/gui/skill.cpp, - src/gui/skill.h, src/gui/status.cpp, src/gui/status.h, src/localplayer.cpp - , src/localplayer.h, src/net/buysellhandler: Redesigned the localplayer - class to use getters and setters instead of direct access to the member - variables. - src/net/charserverhandler.cpp, src/net/playerhandler.cpp, - src/net/protocol.h: Implemented communication of attributes between server - and client. + src/gui/skill.h, src/gui/status.cpp, src/gui/status.h, + src/localplayer.cpp, src/localplayer.h, src/net/buysellhandler: + Redesigned the localplayer class to use getters and setters instead of + direct access to the member variables. + * src/net/charserverhandler.cpp, src/net/playerhandler.cpp, + src/net/protocol.h: Implemented communication of attributes between + server and client. + +2007-03-23 Bjørn Lindeijer + + * src/gui/char_select.cpp, src/gui/char_select.h, + src/net/charserverhandler.h, src/net/charserverhandler.cpp: Clarified + the error message when character creation fails and made sure the + character creation dialog doesn't close when creation failed. + +2007-03-22 Bjørn Lindeijer + + * src/gui/login.cpp, src/gui/login.h, src/gui/register.h, + src/gui/register.cpp: Only enable login button when a username, + password and server are filled in. Pass username, password and server + on to the register dialog. Go back to login dialog when canceling + registration. Fixed a crash caused by deleting an OkDialog twice (it + also deletes itself). Made the register dialog a bit wider. Register + dialog no longer clears username field when it is invalid. + * src/main.cpp, data/icons/CMakeLists.txt, data/icons/Makefile.am, + data/icons/tmw-32x32.png: Use a 32x32 non-alpha layered window icon. + * tmw.cbp: Updated project file. + * data/icons/CMakeLists.txt, data/icons/Makefile.am, src/main.cpp, + data/icons/tmw-32x32.png: Removed 32x32 non-alpha layered window icon + again, and instead used the icon in the executable on Windows. + +2007-03-21 Bjørn Lindeijer + + * src/main.cpp, src/gui/viewport.cpp, src/resources/image.h, + src/resources/image.cpp: Reduced amount of useless logging, calculate + nearest power of two in a function and only do the alpha check in + software mode. + * src/gui/login.cpp: Fixed small issue where default server didn't fit + in the server entry field properly. + * src/main.cpp: Display a progress bar and connecting status for each + server and display the version using a gcn::Label. + * src/gui/viewport.cpp, src/monster.h: Avoiding magic numbers where + possible (1002) and also display the target when other players are + targeted. + * src/floor_item.cpp, src/being.cpp, src/main.cpp, src/CMakeLists.txt, + src/gui/equipmentwindow.cpp, src/gui/viewport.cpp, + src/gui/itemcontainer.cpp, src/gui/viewport.h, src/engine.cpp, + src/animatedsprite.cpp, src/tileset.h, src/npc.cpp, src/Makefile.am, + src/being.h, src/resources/imageset.cpp, src/resources/animation.h, + src/resources/spritedef.cpp, src/resources/resourcemanager.h, + src/resources/spriteset.h, src/resources/imageset.h, + src/resources/resourcemanager.cpp, src/resources/spriteset.cpp, + src/resources/spritedef.h: Renamed Spriteset to ImageSet. + +2007-03-20 David Athay + + * src/gui/viewport.cpp: Fixed target cursor animation, and changed + which layer it is drawn after. + * src/gui/viewport.cpp, src/gui/viewport.h: Split drawing the target + cursor and target name into functions. 2007-03-20 Philipp Sehmisch + * data/graphics/gui/mouse.png: Positioned the cursor image more + accurate. * src/gui/char_select.cpp, src/gui/char_select.h, - src/net/charserverhandler.cpp, src/net/protocol.h: Implemented a GUI for - distributing the characters attributes at character creation. + src/net/charserverhandler.cpp, src/net/protocol.h: Implemented a GUI + for distributing the characters attributes at character creation. + +2007-03-19 David Athay + + * src/localplayer.cpp, src/gui/viewport.cpp, src/gui/viewport.h, + src/net/equipmenthandler.cpp, src/localplayer.h, + src/net/protocol.h: Added target cursor. + +2007-03-18 Bjørn Lindeijer + + * docs/Makefile.am, docs/tmw.6: Added man page by Patrick Matthäi. + * src/resources/image.cpp: Restored alpha layer check, since it should + be more efficient in software mode when SDL knows an image doesn't use + the alpha layer. + * data/graphics/gui/thickborder.png, + data/graphics/gui/vscroll_grey.png, data/graphics/gui/slider.png, + data/graphics/gui/vscroll_blue.png, data/graphics/gui/vscroll_red.png, + data/graphics/gui/deepbox.png, + data/graphics/sprites/monster-slime-red.png, + data/graphics/sprites/monster-scorpion-black.png, + data/graphics/sprites/monster-scorpion.png, + data/graphics/sprites/monster-slime-rudolph.png, + data/graphics/sprites/monster-snake.png, + data/graphics/sprites/monster-slime-santa.png, + data/graphics/sprites/monster-maggot.png, + data/graphics/sprites/monster-spider.png, + data/graphics/sprites/monster-scorpion-red.png, + data/graphics/sprites/monster-slime-yellow.png, + data/graphics/sprites/monster-slime-green.png, + data/graphics/sprites/monster-maggot-giant.png: Replaced pink pixels + with transparent ones. + +2007-03-18 Rogier Polak + + * src/main.cpp: Added (-v) version to the arguments. (Applied a patch + by Patrick Matthäi). + * src/resources/image.cpp: Deleted the "pink code", which added + transparancy with SDL_SetColorKey. + +2007-03-18 Bjørn Lindeijer + + * icons/tmw.ico, icons/tmw.png, icons/tmw.xpm: Replaced icons with the + green globe that is also used on the website. 2007-03-16 Philipp Sehmisch @@ -26,6 +142,25 @@ src/net/accountserver/account.hpp: Implemented 7 atribute system in character creation. +2007-03-14 Bjørn Lindeijer + + * src/main.cpp, src/tmw.rc, data/icons/tmw-icon.png, + data/icons/tmw-icon.xpm, data/icons/tmw.ico, data/icons/tmw-icon.ico, + data/icons/Makefile.am, data/icons/tmw.png, data/icons/tmw.xpm, + data/icons/CMakeLists.txt: Renamed icons to make things easier for + Debian packaging, and the "-icon" part was superfluous anyway. + +2007-03-12 Philipp Sehmisch + + * src/simpleanimation.cpp, src/simpleanimation.h, src/CmakeLists.txt, + src/Makefile.am: Added a simple animation class that hosts a looping + animation without the action and direction stuff from AnimatedSprite. + +2007-03-12 Bjørn Lindeijer + + * data/graphics/items/armor-head-rangerhat.png: New version of ranger + hat icon by Pauan. + 2007-03-11 Philipp Sehmisch * src/map.cpp, src/gui/viewport.cpp: Fixed a bug that made the engine @@ -34,10 +169,11 @@ 2007-03-09 Bjørn Lindeijer * data/graphics/gui/target-cursor-blue.png, - data/graphics/gui/target-cursor-red.png: Added targeting cursors by Pauan. + data/graphics/gui/target-cursor-red.png: Added targeting cursors by + Pauan. * data/graphics/sprites/chest-cotton-male.png, - data/graphics/sprites/chest-cotton-female.png: Replaced cotton shirt with - improved version by Pauan. + data/graphics/sprites/chest-cotton-female.png: Replaced cotton shirt + with improved version by Pauan. 2007-03-03 Rogier Polak diff --git a/data/graphics/gui/deepbox.png b/data/graphics/gui/deepbox.png index 814236ed..ed3231f3 100644 Binary files a/data/graphics/gui/deepbox.png and b/data/graphics/gui/deepbox.png differ diff --git a/data/graphics/gui/mouse.png b/data/graphics/gui/mouse.png index 9276fc7c..2eeb0e51 100644 Binary files a/data/graphics/gui/mouse.png and b/data/graphics/gui/mouse.png differ diff --git a/data/graphics/gui/slider.png b/data/graphics/gui/slider.png index 60ec2392..1f6e6b35 100644 Binary files a/data/graphics/gui/slider.png and b/data/graphics/gui/slider.png differ diff --git a/data/graphics/gui/thickborder.png b/data/graphics/gui/thickborder.png index 2bbd7a50..da72c92f 100644 Binary files a/data/graphics/gui/thickborder.png and b/data/graphics/gui/thickborder.png differ diff --git a/data/graphics/gui/vscroll_blue.png b/data/graphics/gui/vscroll_blue.png index aa236883..397501ce 100644 Binary files a/data/graphics/gui/vscroll_blue.png and b/data/graphics/gui/vscroll_blue.png differ diff --git a/data/graphics/gui/vscroll_grey.png b/data/graphics/gui/vscroll_grey.png index 6bb6bc3f..87ba8758 100644 Binary files a/data/graphics/gui/vscroll_grey.png and b/data/graphics/gui/vscroll_grey.png differ diff --git a/data/graphics/gui/vscroll_red.png b/data/graphics/gui/vscroll_red.png index aadf6925..d7ad4a90 100644 Binary files a/data/graphics/gui/vscroll_red.png and b/data/graphics/gui/vscroll_red.png differ diff --git a/data/icons/CMakeLists.txt b/data/icons/CMakeLists.txt index 30d96d86..e50c7ab9 100644 --- a/data/icons/CMakeLists.txt +++ b/data/icons/CMakeLists.txt @@ -1,9 +1,7 @@ SET(FILES - tmw-icon.ico - tmw-icon.png - tmw-icon.xpm + tmw.png ) INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/icons) -INSTALL(FILES "tmw-icon.png" DESTINATION share/pixmaps RENAME tmw.png) +INSTALL(FILES "tmw.png" DESTINATION share/pixmaps) diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am index 26dcd623..375edef7 100644 --- a/data/icons/Makefile.am +++ b/data/icons/Makefile.am @@ -1,14 +1,11 @@ iconsdir = $(pkgdatadir)/data/icons -icons_DATA = \ - tmw-icon.ico \ - tmw-icon.png \ - tmw-icon.xpm +icons_DATA = tmw.png install-data-local: $(mkinstalldirs) $(DESTDIR)$(datadir)/pixmaps - $(INSTALL) $(srcdir)/tmw-icon.png $(DESTDIR)$(datadir)/pixmaps/tmw.png + $(INSTALL) $(srcdir)/tmw.png $(DESTDIR)$(datadir)/pixmaps/tmw.png uninstall-local: rm -f $(DESTDIR)$(datadir)/pixmaps/tmw.png diff --git a/data/icons/tmw-icon.ico b/data/icons/tmw-icon.ico deleted file mode 100644 index 5ba6e1b7..00000000 Binary files a/data/icons/tmw-icon.ico and /dev/null differ diff --git a/data/icons/tmw-icon.png b/data/icons/tmw-icon.png deleted file mode 100644 index 2598a620..00000000 Binary files a/data/icons/tmw-icon.png and /dev/null differ diff --git a/data/icons/tmw-icon.xpm b/data/icons/tmw-icon.xpm deleted file mode 100644 index a9e91161..00000000 --- a/data/icons/tmw-icon.xpm +++ /dev/null @@ -1,56 +0,0 @@ -/* XPM */ -static char *dummy[]={ -"32 32 21 1", -". c None", -"f c #003300", -"s c #003333", -"# c #003366", -"d c #006600", -"h c #009933", -"c c #040404", -"m c #0c0c0c", -"a c #3366cc", -"e c #339933", -"g c #33cc33", -"o c #66cc99", -"r c #993300", -"n c #996633", -"b c #99ccff", -"j c #c0c0c0", -"k c #cc6666", -"q c #cc9933", -"i c #cc9999", -"p c #cccc66", -"l c #efd6c6", -"................................", -".........................#......", -"........#................a......", -".......#a..............#aba#....", -"...#.......cccccccc......a......", -"...a......ccdeddcfdcc....#......", -".#ab#....ccccegdheefc...........", -"...#...cccdheeeeehdddc..........", -".......cheheegeeehddfcc.cc......", -"........ccdhedeeehhdcc..cic.....", -".......ccdhgeeeheeddfc.cijc.....", -".......cfddhehhhddfccc.cikcc....", -".......ccccfdhedfdffc..cjliccm..", -"..........cccdfdfcccc.cciiknc...", -".....cccc...cccccc...cceciiicc..", -"....cgoggccccnpqrc..mcgogeckcec.", -"....ccggogggccqpqccmccecciidogcm", -"....cjncgggecpncnrcccnijijikdec.", -".....ciikceccrqqcncrciiliikcnc..", -"....ccccccrcpqpqnrnkdkiiiiiinc..", -"..cccgogeccnqpccpqncdcseinikrc..", -"..cgooogggecnqcnqcpneedddsknegc.", -"..ccccggoooggcnegeceeegdedseogg.", -"...ccrkggggggoogggoeggegeeddcec.", -".....ccrcceggggeggggeggegeeckcc.", -".....mcnilkcgepccceggecceeecic..", -"......mcriikccinkcpeeencceciic..", -"........cijiilikiikccciknccrkc..", -".......cckiknccckiijiiknrc.cc...", -"........cccncc.ccnkknrccc...c...", -"..........ccc....ccccc..........", -"...........m...................."}; diff --git a/data/icons/tmw.ico b/data/icons/tmw.ico new file mode 100644 index 00000000..61d559a3 Binary files /dev/null and b/data/icons/tmw.ico differ diff --git a/data/icons/tmw.png b/data/icons/tmw.png new file mode 100644 index 00000000..93e6c9ae Binary files /dev/null and b/data/icons/tmw.png differ diff --git a/data/icons/tmw.xpm b/data/icons/tmw.xpm new file mode 100644 index 00000000..06ec2865 --- /dev/null +++ b/data/icons/tmw.xpm @@ -0,0 +1,784 @@ +/* XPM */ +static char * tmw_xpm[] = { +"32 32 749 2", +" c None", +". c #E4EB6D", +"+ c #EFF271", +"@ c #E7EF65", +"# c #DDED61", +"$ c #D6E955", +"% c #DAED4D", +"& c #F6F5A0", +"* c #EFEF89", +"= c #ECF084", +"- c #EDF077", +"; c #EAF075", +"> c #E0E960", +", c #D9E757", +"' c #D4EA52", +") c #CFE74D", +"! c #BEE140", +"~ c #C2E43E", +"{ c #B6DF33", +"] c #F8F7C2", +"^ c #F9F7AB", +"/ c #F2F099", +"( c #EEEF80", +"_ c #F3F077", +": c #F8F8B1", +"< c #E8EE6F", +"[ c #E1EB69", +"} c #DBEB5E", +"| c #D5E852", +"1 c #CDE445", +"2 c #CEE843", +"3 c #B6DC34", +"4 c #A9DA2F", +"5 c #B3E02F", +"6 c #B6E630", +"7 c #F1F2E2", +"8 c #F9F9D4", +"9 c #F9F8C5", +"0 c #F8F8CE", +"a c #F9F8D6", +"b c #F9F7CB", +"c c #F9F7B1", +"d c #F9F7A7", +"e c #E7EE73", +"f c #E4EC69", +"g c #DEEB60", +"h c #D8E755", +"i c #D5EB55", +"j c #C2E33F", +"k c #BEE33C", +"l c #B5E339", +"m c #A7DF2E", +"n c #9BDA28", +"o c #95DA24", +"p c #8DD724", +"q c #F9F9F5", +"r c #F9F9EA", +"s c #F9F9E1", +"t c #F9F9F4", +"u c #F9F7DF", +"v c #F9F7D1", +"w c #F9F7C9", +"x c #F9F7B6", +"y c #F9F7AE", +"z c #D7E363", +"A c #E1EC6B", +"B c #DDEC60", +"C c #D8EC61", +"D c #CDE552", +"E c #C6E543", +"F c #BCE440", +"G c #BEE73E", +"H c #ABDF30", +"I c #ACE230", +"J c #8FD720", +"K c #80D01C", +"L c #80D51A", +"M c #F9F9F7", +"N c #F9F9EB", +"O c #F9F9F9", +"P c #F9F7E6", +"Q c #F9F7D3", +"R c #F9F7CE", +"S c #F9F7BF", +"T c #F9F8B9", +"U c #E6EF8F", +"V c #E1EB65", +"W c #E0ED63", +"X c #D1E452", +"Y c #D3E84D", +"Z c #C3E340", +"` c #BBE13E", +" . c #B0DD35", +".. c #ABDD2E", +"+. c #A0DB2A", +"@. c #95D923", +"#. c #7ED31C", +"$. c #7ED31A", +"%. c #80DA18", +"&. c #F4F3EF", +"*. c #F9F9F6", +"=. c #F9F8F5", +"-. c #F9F7EE", +";. c #F9F7E2", +">. c #F9F7D5", +",. c #F9F6C2", +"'. c #F8F69C", +"). c #D4E56D", +"!. c #E4ED73", +"~. c #DBEA60", +"{. c #DDE961", +"]. c #C9E54E", +"^. c #BFE242", +"/. c #BEE33E", +"(. c #B1DE34", +"_. c #ABDE33", +":. c #95D826", +"<. c #8DD620", +"[. c #8DDB20", +"}. c #91DD1E", +"|. c #71D116", +"1. c #50B910", +"2. c #F9F8F7", +"3. c #F9F8F4", +"4. c #F9F7EB", +"5. c #F9F7E1", +"6. c #F9F5CF", +"7. c #F9F6C9", +"8. c #F9F6BF", +"9. c #D6E471", +"0. c #E9F075", +"a. c #E3EC6B", +"b. c #D9E96D", +"c. c #CEE558", +"d. c #CBE44E", +"e. c #BEDE3E", +"f. c #ACDA37", +"g. c #BCE639", +"h. c #AEE135", +"i. c #9EDB2A", +"j. c #8FD822", +"k. c #7CD31B", +"l. c #82DA1C", +"m. c #63CE13", +"n. c #61CE12", +"o. c #F9F9F8", +"p. c #F9F7F5", +"q. c #F9F4DD", +"r. c #F9F5D7", +"s. c #F9F5C9", +"t. c #F9F5B6", +"u. c #E3ED8D", +"v. c #DEE865", +"w. c #E3ED6D", +"x. c #DDEB5E", +"y. c #D3E755", +"z. c #CAE349", +"A. c #CFEB4D", +"B. c #C1E33B", +"C. c #BCE743", +"D. c #B0E02D", +"E. c #95DB28", +"F. c #95DB26", +"G. c #C6E627", +"H. c #E8F433", +"I. c #CAED26", +"J. c #60CD0F", +"K. c #58CD0E", +"L. c #F9F7EC", +"M. c #F9F7F1", +"N. c #F9F4E4", +"O. c #F9F3D7", +"P. c #F9F3CA", +"Q. c #F9F5CA", +"R. c #F9F5BB", +"S. c #F9F8B6", +"T. c #F6F89E", +"U. c #DFEB5C", +"V. c #CEE453", +"W. c #D0E753", +"X. c #CDE543", +"Y. c #C7E842", +"Z. c #C1E53C", +"`. c #A7DC30", +" + c #E6F453", +".+ c #E2F448", +"++ c #D8F03C", +"@+ c #D1ED2E", +"#+ c #D0F033", +"$+ c #CAED2C", +"%+ c #ACE51F", +"&+ c #55CF0F", +"*+ c #F5F6EF", +"=+ c #F9F9F2", +"-+ c #F9F9F1", +";+ c #F9F8F0", +">+ c #F9F7E7", +",+ c #F9F5F0", +"'+ c #F9F3E1", +")+ c #F9F5DB", +"!+ c #F9F6DB", +"~+ c #F9F6BE", +"{+ c #F8F59B", +"]+ c #F9F5A2", +"^+ c #F8F68D", +"/+ c #F7F689", +"(+ c #D7EC65", +"_+ c #CEE84E", +":+ c #BBE23F", +"<+ c #B6E238", +"[+ c #A2DC30", +"}+ c #EBF553", +"|+ c #E4F443", +"1+ c #DCF340", +"2+ c #D4F033", +"3+ c #CEEF2D", +"4+ c #C2E926", +"5+ c #BEEB20", +"6+ c #5CD50E", +"7+ c #53CE0D", +"8+ c #F9F7D9", +"9+ c #F9F6F2", +"0+ c #F9F5EB", +"a+ c #F9F3DA", +"b+ c #F9F6DF", +"c+ c #F9F7D0", +"d+ c #F9F7C2", +"e+ c #F9F7BB", +"f+ c #F8F68F", +"g+ c #F7F58D", +"h+ c #F6F58B", +"i+ c #EEF68B", +"j+ c #BFDF43", +"k+ c #B5DE37", +"l+ c #B5E234", +"m+ c #A7DD30", +"n+ c #E7F248", +"o+ c #D6EF40", +"p+ c #DBF239", +"q+ c #D0ED2F", +"r+ c #C3EB2A", +"s+ c #BCEB26", +"t+ c #B5E81E", +"u+ c #52CE0F", +"v+ c #4ECB0B", +"w+ c #F9F9D9", +"x+ c #F9F9D7", +"y+ c #F9F8F8", +"z+ c #F9F7E9", +"A+ c #F9F6E9", +"B+ c #F9F5E0", +"C+ c #F8F2D6", +"D+ c #F9F3CE", +"E+ c #F9F7CA", +"F+ c #F9F8B5", +"G+ c #F6F691", +"H+ c #F9F699", +"I+ c #F5F68F", +"J+ c #F3F579", +"K+ c #E8F575", +"L+ c #C7E646", +"M+ c #B5DF37", +"N+ c #B9E438", +"O+ c #9CD928", +"P+ c #D7F348", +"Q+ c #DBEF3B", +"R+ c #D1EF35", +"S+ c #D7F230", +"T+ c #C1EA25", +"U+ c #B5E91F", +"V+ c #63DC1E", +"W+ c #48CA0C", +"X+ c #F4F4DC", +"Y+ c #F9F9C3", +"Z+ c #F9F9C5", +"`+ c #F9F9C7", +" @ c #F9F9E8", +".@ c #F9F6DD", +"+@ c #F9F6D6", +"@@ c #F9F3C1", +"#@ c #F9F3BF", +"$@ c #F9F5B8", +"%@ c #F8F8A6", +"&@ c #F6F68F", +"*@ c #F4F791", +"=@ c #ABD746", +"-@ c #C5E449", +";@ c #C1E448", +">@ c #BBE23E", +",@ c #BBE237", +"'@ c #A9DC30", +")@ c #99D927", +"!@ c #D3E32C", +"~@ c #E2F340", +"{@ c #D3ED2D", +"]@ c #CAED2B", +"^@ c #CDF028", +"/@ c #C5EB27", +"(@ c #B0E51C", +"_@ c #91DC13", +":@ c #49CA08", +"<@ c #25B305", +"[@ c #F5F6BE", +"}@ c #F5F5A9", +"|@ c #F3F4B0", +"1@ c #F6F6B0", +"2@ c #F7F8B5", +"3@ c #EDF097", +"4@ c #F5F18F", +"5@ c #F9F7B8", +"6@ c #F9F4B0", +"7@ c #F9F3AE", +"8@ c #F9F3A4", +"9@ c #F9F7A4", +"0@ c #F7F7A0", +"a@ c #F5F682", +"b@ c #D3E75E", +"c@ c #CAE646", +"d@ c #CBE846", +"e@ c #EDF05A", +"f@ c #C6E432", +"g@ c #A9E02E", +"h@ c #99DA27", +"i@ c #B9DB20", +"j@ c #E1F33F", +"k@ c #CEEB2E", +"l@ c #C7EB27", +"m@ c #BBEA26", +"n@ c #B9E722", +"o@ c #A6DF19", +"p@ c #ABE815", +"q@ c #48CB09", +"r@ c #3ECA08", +"s@ c #F8F7A7", +"t@ c #F3F4A0", +"u@ c #F4F59C", +"v@ c #F0F49C", +"w@ c #F2F5A4", +"x@ c #F5F6A0", +"y@ c #EFF28F", +"z@ c #F9F8CD", +"A@ c #F9F6A7", +"B@ c #F9F3A0", +"C@ c #F8F399", +"D@ c #F8F493", +"E@ c #F8F693", +"F@ c #F7F58B", +"G@ c #E8EF65", +"H@ c #C7E445", +"I@ c #C7DB30", +"J@ c #E1ED48", +"K@ c #E8F353", +"L@ c #C3E227", +"M@ c #D9EB2E", +"N@ c #E7F549", +"O@ c #D3EE3B", +"P@ c #CBED2D", +"Q@ c #CDEF27", +"R@ c #BFEC23", +"S@ c #B6E81E", +"T@ c #A9E518", +"U@ c #B1EB1B", +"V@ c #35BE06", +"W@ c #38C306", +"X@ c #F9F9A7", +"Y@ c #F2F38F", +"Z@ c #F2F495", +"`@ c #F3F38D", +" # c #F9F9E9", +".# c #F7F8C5", +"+# c #F8F7D1", +"@# c #F8F6A2", +"## c #F9F7A9", +"$# c #F8F59C", +"%# c #F8F291", +"&# c #F8F58F", +"*# c #F6F789", +"=# c #F2F477", +"-# c #F0F571", +";# c #EAEE52", +"># c #DCEA45", +",# c #EBEF43", +"'# c #E4F04D", +")# c #DEEF45", +"!# c #E1F246", +"~# c #E4F448", +"{# c #DBF039", +"]# c #D9F235", +"^# c #C9ED2B", +"/# c #CAEF2C", +"(# c #CEF22B", +"_# c #B6E91E", +":# c #B1EB21", +"<# c #A9E815", +"[# c #48CF09", +"}# c #40CD06", +"|# c #EDEF6B", +"1# c #EBF07C", +"2# c #E7EB71", +"3# c #E8E865", +"4# c #F8F79E", +"5# c #F8F7A4", +"6# c #F9F69E", +"7# c #F8F48F", +"8# c #F6F280", +"9# c #F6F482", +"0# c #F3F473", +"a# c #EFF169", +"b# c #EDF467", +"c# c #EAF35C", +"d# c #EAF258", +"e# c #E4F052", +"f# c #E4F046", +"g# c #E0F03F", +"h# c #D5EE3B", +"i# c #DFF23E", +"j# c #D7F137", +"k# c #CEED2E", +"l# c #C9EF28", +"m# c #CAF025", +"n# c #B9EA1E", +"o# c #B3E91D", +"p# c #B1EB1A", +"q# c #A6E817", +"r# c #39C506", +"s# c #35C505", +"t# c #B3BC3E", +"u# c #E9F07C", +"v# c #DEE867", +"w# c #F9F79E", +"x# c #F8F793", +"y# c #F8F78F", +"z# c #F7F684", +"A# c #F5F27E", +"B# c #F4F26D", +"C# c #F4F36F", +"D# c #EDF061", +"E# c #EEF363", +"F# c #EDF35C", +"G# c #EEF45C", +"H# c #EAF357", +"I# c #E8F34B", +"J# c #DCEE43", +"K# c #E1F03F", +"L# c #D6ED37", +"M# c #D5EE33", +"N# c #D5F134", +"O# c #D9F232", +"P# c #CEF22D", +"Q# c #C7F22A", +"R# c #9BDB18", +"S# c #A7E518", +"T# c #AEEB1B", +"U# c #95E514", +"V# c #37C306", +"W# c #3CC705", +"X# c #E0EC60", +"Y# c #D1E455", +"Z# c #F7F78F", +"`# c #F7F891", +" $ c #F8F78B", +".$ c #F5F782", +"+$ c #F8F791", +"@$ c #EFF06B", +"#$ c #F3F36D", +"$$ c #EFF36D", +"%$ c #F1F56F", +"&$ c #EDF260", +"*$ c #EDF461", +"=$ c #E7F150", +"-$ c #E9F355", +";$ c #E8F349", +">$ c #E8F442", +",$ c #DDF13E", +"'$ c #DAF038", +")$ c #CEEB26", +"!$ c #D0EE2C", +"~$ c #B9E82A", +"{$ c #C1ED26", +"]$ c #A0E41C", +"^$ c #ABE71B", +"/$ c #99E315", +"($ c #99E415", +"_$ c #33B306", +":$ c #2BBB05", +"<$ c #D9EB5E", +"[$ c #CDE44E", +"}$ c #F6F579", +"|$ c #F4F577", +"1$ c #F3F571", +"2$ c #F4F57C", +"3$ c #F3F363", +"4$ c #F2F475", +"5$ c #F0F567", +"6$ c #A2D93F", +"7$ c #C3E43F", +"8$ c #B6D92E", +"9$ c #A7CD1F", +"0$ c #E4F042", +"a$ c #E4F248", +"b$ c #E5F348", +"c$ c #D7EC39", +"d$ c #DBF33C", +"e$ c #DDF23E", +"f$ c #D1EF2D", +"g$ c #C1E825", +"h$ c #BFEB26", +"i$ c #AEE61B", +"j$ c #A7E318", +"k$ c #B0E818", +"l$ c #9EE615", +"m$ c #6DD30D", +"n$ c #27A603", +"o$ c #2CBE05", +"p$ c #E2ED50", +"q$ c #CBE348", +"r$ c #F6F780", +"s$ c #F5F577", +"t$ c #F3F56F", +"u$ c #EFF469", +"v$ c #F3F471", +"w$ c #F3F46F", +"x$ c #EFF461", +"y$ c #E7F053", +"z$ c #C6E83F", +"A$ c #A4D733", +"B$ c #ABDD2F", +"C$ c #B0DF2E", +"D$ c #A7DD2B", +"E$ c #E4F240", +"F$ c #E8F555", +"G$ c #DDF33C", +"H$ c #E1F53E", +"I$ c #D4F032", +"J$ c #CEF02E", +"K$ c #CAEF2D", +"L$ c #C2EF28", +"M$ c #B5E91B", +"N$ c #93DD13", +"O$ c #93E215", +"P$ c #93E213", +"Q$ c #80DB0D", +"R$ c #45CA05", +"S$ c #2FC204", +"T$ c #CEE743", +"U$ c #C1E23E", +"V$ c #F0F365", +"W$ c #F5F473", +"X$ c #F2F269", +"Y$ c #E9EF57", +"Z$ c #EFF363", +"`$ c #E8F052", +" % c #EBF358", +".% c #B8E439", +"+% c #BCE839", +"@% c #A4DC2A", +"#% c #ABE22D", +"$% c #95D822", +"%% c #E1F240", +"&% c #D6ED32", +"*% c #CFEC2C", +"=% c #D4F02F", +"-% c #CAEE2B", +";% c #C3EB27", +">% c #C6EE25", +",% c #C3EE21", +"'% c #B8ED21", +")% c #AEEA16", +"!% c #79D90F", +"~% c #2EB106", +"{% c #26B808", +"]% c #2CBF05", +"^% c #C9E73B", +"/% c #C5E63C", +"(% c #F0F56B", +"_% c #EEF258", +":% c #F0F265", +"<% c #EFF155", +"[% c #EDF358", +"}% c #EBF550", +"|% c #EBF54D", +"1% c #C9E83B", +"2% c #A4DB28", +"3% c #9EDC2B", +"4% c #8FD622", +"5% c #82D01E", +"6% c #7EC512", +"7% c #C9E827", +"8% c #D0EE2E", +"9% c #C7ED2C", +"0% c #C7EE27", +"a% c #C1EE2A", +"b% c #C2EF24", +"c% c #BEED22", +"d% c #A9E718", +"e% c #3EC307", +"f% c #39C306", +"g% c #38C606", +"h% c #23B603", +"i% c #ACDB2F", +"j% c #B0DF34", +"k% c #EDF35A", +"l% c #EDF553", +"m% c #E2F045", +"n% c #E6F350", +"o% c #E6F448", +"p% c #9CD01E", +"q% c #8BC916", +"r% c #B8DC1B", +"s% c #7CBC0F", +"t% c #95D618", +"u% c #7ED319", +"v% c #BFE118", +"w% c #C6ED2A", +"x% c #C1EA21", +"y% c #C1ED22", +"z% c #B8EA1D", +"A% c #B6EB1D", +"B% c #BCEF1F", +"C% c #53CA07", +"D% c #3FC708", +"E% c #2EBC05", +"F% c #2FBE04", +"G% c #2DBF04", +"H% c #A2CF1F", +"I% c #B1E12F", +"J% c #B5E32E", +"K% c #E8F243", +"L% c #D7EB45", +"M% c #E8F245", +"N% c #DDEF40", +"O% c #E2F342", +"P% c #DFF33E", +"Q% c #E4F542", +"R% c #DAF138", +"S% c #D8F230", +"T% c #CBEB28", +"U% c #D1F02E", +"V% c #C6EC24", +"W% c #CAEF25", +"X% c #BCEB21", +"Y% c #B6EB1E", +"Z% c #ABE91B", +"`% c #A2E616", +" & c #3CC508", +".& c #3EC906", +"+& c #37C305", +"@& c #27B903", +"#& c #209B02", +"$& c #A9DF27", +"%& c #A4DD27", +"&& c #91D623", +"*& c #E3F13C", +"=& c #E4F340", +"-& c #E4F33F", +";& c #E4F43E", +">& c #E2F439", +",& c #D6F033", +"'& c #D5F034", +")& c #CEEF2E", +"!& c #CBED26", +"~& c #CFEF27", +"{& c #D5F22E", +"]& c #B5E620", +"^& c #B9EA1F", +"/& c #84E620", +"(& c #3EB508", +"_& c #58CE0D", +":& c #39CA11", +"<& c #3EC607", +"[& c #3BCA08", +"}& c #28BB04", +"|& c #28BC03", +"1& c #8FD620", +"2& c #97D823", +"3& c #A6E22B", +"4& c #69CB1D", +"5& c #86D61F", +"6& c #E5F740", +"7& c #DCF338", +"8& c #CAEC2D", +"9& c #CDED2B", +"0& c #D1F02C", +"a& c #CDEE27", +"b& c #C1EB22", +"c& c #CFF228", +"d& c #BCE922", +"e& c #3CBB09", +"f& c #50CD0C", +"g& c #4BCD0B", +"h& c #3CC207", +"i& c #42CD09", +"j& c #2EBB04", +"k& c #28B905", +"l& c #28B903", +"m& c #61B113", +"n& c #7ED41A", +"o& c #89D71B", +"p& c #8DDB1A", +"q& c #7CD518", +"r& c #8FDA1B", +"s& c #71D314", +"t& c #7CDA18", +"u& c #BEF232", +"v& c #8BD715", +"w& c #63C207", +"x& c #55C108", +"y& c #5AD111", +"z& c #4BC90B", +"A& c #3EC108", +"B& c #46C908", +"C& c #40CB08", +"D& c #34C205", +"E& c #32C505", +"F& c #22A003", +"G& c #79D818", +"H& c #75D314", +"I& c #67D012", +"J& c #69D313", +"K& c #71D613", +"L& c #67D413", +"M& c #4BC20C", +"N& c #4DCB0E", +"O& c #5AD510", +"P& c #50CA0B", +"Q& c #4BC909", +"R& c #3CC708", +"S& c #42C906", +"T& c #35C206", +"U& c #33C306", +"V& c #30C504", +"W& c #49C30E", +"X& c #71D913", +"Y& c #84E318", +"Z& c #5ECF0E", +"`& c #58D00D", +" * c #5ED40D", +".* c #48C70A", +"+* c #57D40B", +"@* c #37BE06", +"#* c #39C707", +"$* c #37C505", +"%* c #34C705", +"&* c #49BE0B", +"** c #4BD00C", +"=* c #46C609", +"-* c #46D00A", +";* c #33BE06", +">* c #20A904", +" . + @ # $ % ", +" & * = - ; > , ' ) ! ~ { ", +" ] ^ / ( _ : < [ } | 1 2 3 4 5 6 ", +" 7 8 9 0 a b c d e f g h i j k l m n o p ", +" q r s t u v w x y z A B C D E F G H I J K L ", +" M M N O P u Q R S T U V W X Y Z ` ...+.@.#.$.%. ", +" &.O *.O =.-.;.>.R ,.'.).!.~.{.].^./.(._.:.<.[.}.|.1. ", +" O O O 2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n. ", +" o.O *.p.p.3.-.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K. ", +" O o.q L.p.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+%+&+ ", +" *+=+-+;+>+p.,+'+)+!+~+8.{+]+^+/+(+_+:+<+[+}+|+1+2+3+4+5+6+7+ ", +" r N N 8+p.9+0+a+b+c+d+e+d f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+ ", +" w+x+w+y+z+A+B+C+D+E+S F+G+H+I+J+K+L+M+N+O+P+Q+R+S+$+T+U+V+W+ ", +"X+Y+Z+`+ @.@+@6.@@#@$@^ %@&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@", +"[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@) c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@", +"s@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@>@I@J@K@L@M@N@O@P@Q@R@S@T@U@V@W@", +"X@Y@Z@`@ #.#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#:#<#[#}#", +"|#1#2#3#4###5#'.6#7#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#", +"t#u#v#w#s@x#y#z#a@A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#", +" X#Y#Z#`# $.$+$@$#$$$%$&$*$=$-$I#;$>$,$'$)$!$~${$]$^$/$($_$:$ ", +" <$[$}$|$*#1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$ ", +" p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$S$ ", +" T$U$V$W$X$Y$Z$`$ %.%+%@%#%$%%%&%*%=%-%;%>%,%'%)%!%~%{%]% ", +" ^%/%(%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%d%($e%f%g%h% ", +" i%j%k%l%a$m%n%o%p%q%r%s%t%u%v%w%x%y%z%A%B%C%D%E%F%G% ", +" H%I%J%K%L%M%N%O%P%Q%G$R%S%T%U%V%W%X%Y%Z%`% &.&+&@&#& ", +" $&%&&&*&=&-&;&>&,&'&)&!&~&{&]&^&/&(&_&:&<&[&}&|& ", +" 1&2&3&4&5&6&7&8&9&0&a&b&c&d&e&f&g&h&i&j&k&l& ", +" m&n&o&p&q&r&s&t&u&v&w&x&y&z&A&B&C&D&E&F& ", +" G&H&I&J&K&L&M&N&O&P&Q&R&S&T&U&V& ", +" W&X&Y&Z&`& *.*+*@*#*$*%* ", +" &***=*-*;*>* "}; diff --git a/docs/Makefile.am b/docs/Makefile.am index e106768b..8b57d5bb 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,3 +1,5 @@ +man6_MANS = tmw.6 + EXTRA_DIST = packages.txt \ FAQ.txt \ HACKING.txt \ diff --git a/docs/tmw.6 b/docs/tmw.6 new file mode 100644 index 00000000..0dee82c7 --- /dev/null +++ b/docs/tmw.6 @@ -0,0 +1,74 @@ +.TH "TMW" "6" +.SH "NAME" +tmw \- tmw is The Mana World: A fantasy online game +.SH "SYNOPSIS" +\fBtmw\fR +.SH "DESCRIPTION" +This manual page documents briefly the +\fBtmw\fR ingame +commands. +\fBtmw\fR is a great online game based upon the Seiken Densetsu Serie. +It has its own universe, and and its own character management system, which will +give you the opportunity to play in a 2D heroic-fantasy world forever. +.SH "BINARY PARAMETERS" +This program follows the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-v, \-\-version +Show version of the program. +.TP +.B \-u, \-\-skipupdate +Skip the update process. +.TP +.B \-U, \-\-username +Login with this username. +.TP +.B \-P, \-\-password +Login with this password. +.TP +.B \-D, \-\-default +Bypass the login process with default settings. +.TP +.B \-p, \-\-playername +Login with this player. +.TP +.B \-C, \-\-configfile +Configuration file to use +.SH "COMMON KEYS" +.TP +.B Arrow Keys: +Move your character around. +.TP +.B Left Ctrl: +Make your character attack. +.TP +.B Key A: +Target nearest monster. +.TP +.B Key G: +Get items on the ground or in a chest. +.TP +.B Alt + 1...9: +Shows an emoticon above your character. +.TP +.B Alt + I: +Shows / Hide inventory window. +.TP +.B Alt + K: +Shows / Hide skills window. +.TP +.B Alt + E: +Shows / Hide equipment window. +.TP +.B Alt + C: +Shows configuration window. +.SH "AUTHOR" +This manual page was written by Patrick Matth\[:a]i +for The Mana World project. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b5bad01..e28e235e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -268,10 +268,10 @@ SET(SRCS resources/sdlimageloader.h resources/soundeffect.cpp resources/soundeffect.h - resources/spriteset.cpp resources/spritedef.h resources/spritedef.cpp - resources/spriteset.h + resources/imageset.h + resources/imageset.cpp utils/base64.cpp utils/base64.h utils/dtor.h @@ -330,6 +330,8 @@ SET(SRCS player.h properties.h serverinfo.h + simpleanimation.cpp + simpleanimation.h sound.cpp sound.h sprite.h diff --git a/src/Makefile.am b/src/Makefile.am index da1bc44d..f1f51b79 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -222,8 +222,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ resources/soundeffect.cpp \ resources/spritedef.h \ resources/spritedef.cpp \ - resources/spriteset.h \ - resources/spriteset.cpp \ + resources/imageset.h \ + resources/imageset.cpp \ resources/buddylist.h \ resources/buddylist.cpp \ utils/base64.cpp \ @@ -284,6 +284,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \ player.h \ properties.h \ serverinfo.h \ + simpleanimation.cpp \ + simpleanimation.h \ sound.cpp \ sound.h \ sprite.h \ diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index 3d1979a9..7260a512 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -30,7 +30,6 @@ #include "resources/animation.h" #include "resources/image.h" #include "resources/resourcemanager.h" -#include "resources/spriteset.h" #include "utils/xml.h" diff --git a/src/being.cpp b/src/being.cpp index e4a1e9fc..682daddb 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -34,7 +34,7 @@ #include "map.h" #include "resources/resourcemanager.h" -#include "resources/spriteset.h" +#include "resources/imageset.h" #include "gui/gui.h" @@ -42,7 +42,7 @@ #include "utils/tostring.h" int Being::instances = 0; -Spriteset *Being::emotionset = NULL; +ImageSet *Being::emotionSet = NULL; Being::Being(Uint16 id, Uint16 job, Map *map): mJob(job), @@ -72,8 +72,8 @@ Being::Being(Uint16 id, Uint16 job, Map *map): { // Load the emotion set ResourceManager *rm = ResourceManager::getInstance(); - emotionset = rm->getSpriteset("graphics/sprites/emotions.png", 30, 32); - if (!emotionset) logger->error("Unable to load emotions spriteset!"); + emotionSet = rm->getImageSet("graphics/sprites/emotions.png", 30, 32); + if (!emotionSet) logger->error("Unable to load emotions!"); } instances++; @@ -89,8 +89,8 @@ Being::~Being() if (instances == 0) { - emotionset->decRef(); - emotionset = NULL; + emotionSet->decRef(); + emotionSet = NULL; } } @@ -515,7 +515,7 @@ Being::drawEmotion(Graphics *graphics, int offsetX, int offsetY) int px = mPx + offsetX + 3; int py = mPy + offsetY - 60; - graphics->drawImage(emotionset->get(mEmotion - 1), px, py); + graphics->drawImage(emotionSet->get(mEmotion - 1), px, py); } void diff --git a/src/being.h b/src/being.h index c3cba247..332f1b4a 100644 --- a/src/being.h +++ b/src/being.h @@ -41,7 +41,7 @@ class Equipment; class Item; class Map; class Graphics; -class Spriteset; +class ImageSet; /** * A position along a being's path. @@ -397,7 +397,7 @@ class Being : public Sprite Uint16 mStepTime; static int instances; /**< Number of Being instances */ - static Spriteset *emotionset; /**< Emoticons used by beings */ + static ImageSet *emotionSet; /**< Emoticons used by beings */ }; #endif diff --git a/src/engine.cpp b/src/engine.cpp index a3097d49..31bec9ff 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -44,7 +44,6 @@ #include "resources/mapreader.h" #include "resources/monsterdb.h" #include "resources/resourcemanager.h" -#include "resources/spriteset.h" #include "utils/dtor.h" #include "utils/tostring.h" @@ -77,7 +76,8 @@ void Engine::changeMap(const std::string &mapPath) // Notify the minimap and beingManager about the map change Image *mapImage = NULL; - if (newMap->hasProperty("minimap")) { + if (newMap->hasProperty("minimap")) + { ResourceManager *resman = ResourceManager::getInstance(); mapImage = resman->getImage(newMap->getProperty("minimap")); } diff --git a/src/floor_item.cpp b/src/floor_item.cpp index f33f7eb4..5d83e1dd 100644 --- a/src/floor_item.cpp +++ b/src/floor_item.cpp @@ -27,7 +27,6 @@ #include "resources/itemdb.h" #include "resources/iteminfo.h" -#include "resources/spriteset.h" FloorItem::FloorItem(unsigned int id, diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 09ce5b87..128a803e 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -42,9 +42,14 @@ #include "../logindata.h" #include "../net/accountserver/account.h" +#include "../net/charserverhandler.h" +#include "../net/messageout.h" #include "../utils/tostring.h" +// Defined in main.cpp, used here for setting the char create dialog +extern CharServerHandler charServerHandler; + /** * Listener for confirming character deletion. */ @@ -155,14 +160,14 @@ void CharSelectDialog::action(const gcn::ActionEvent &event) } else if (event.getId() == "new") { - //TODO: search the first free slot, and start CharCreateDialog - // maybe add that search to the constructor + // TODO: Search the first free slot, and start CharCreateDialog + // maybe add that search to the constructor. if (!(mCharInfo->getEntry())) { // Start new character dialog - mCharInfo->lock(); - new CharCreateDialog(this, mCharInfo->getPos()); - mCharInfo->unlock(); + CharCreateDialog *charCreateDialog = + new CharCreateDialog(this, mCharInfo->getPos()); + charServerHandler.setCharCreateDialog(charCreateDialog); } } else if (event.getId() == "delete") @@ -344,14 +349,19 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot): setLocationRelativeTo(getParent()); setVisible(true); + mNameField->requestFocus(); } CharCreateDialog::~CharCreateDialog() { delete mPlayer; + + // Make sure the char server handler knows that we're gone + charServerHandler.setCharCreateDialog(0); } -void CharCreateDialog::action(const gcn::ActionEvent &event) +void +CharCreateDialog::action(const gcn::ActionEvent &event) { if (event.getId() == "create") { if (getName().length() >= 4) { @@ -362,15 +372,14 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) mPlayer->getHairStyle(), mPlayer->getHairColor(), 0, // gender - (int)mAttributeSlider[0]->getValue(), // STR - (int)mAttributeSlider[1]->getValue(), // AGI - (int)mAttributeSlider[2]->getValue(), // DEX - (int)mAttributeSlider[3]->getValue(), // VIT - (int)mAttributeSlider[4]->getValue(), // INT - (int)mAttributeSlider[5]->getValue(), // WILL - (int)mAttributeSlider[6]->getValue() // CHAR + (int) mAttributeSlider[0]->getValue(), // STR + (int) mAttributeSlider[1]->getValue(), // AGI + (int) mAttributeSlider[2]->getValue(), // DEX + (int) mAttributeSlider[3]->getValue(), // VIT + (int) mAttributeSlider[4]->getValue(), // INT + (int) mAttributeSlider[5]->getValue(), // WILL + (int) mAttributeSlider[6]->getValue() // CHAR ); - scheduleDelete(); } else { new OkDialog("Error", @@ -399,21 +408,23 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) } } -std::string CharCreateDialog::getName() +const std::string& +CharCreateDialog::getName() { return mNameField->getText(); } void CharCreateDialog::UpdateSliders() { - for (int i=0; i<=6; i++) + for (int i = 0; i < 7; i++) { - // update captions - mAttributeValue[i]->setCaption(toString((int)(mAttributeSlider[i]->getValue()))); + // Update captions + mAttributeValue[i]->setCaption( + toString((int) (mAttributeSlider[i]->getValue()))); mAttributeValue[i]->adjustSize(); } - // update distributed points + // Update distributed points int pointsLeft = 70 - getDistributedPoints(); if (pointsLeft == 0) { @@ -425,24 +436,32 @@ void CharCreateDialog::UpdateSliders() mCreateButton->setEnabled(false); if (pointsLeft > 0) { - mAttributesLeft->setCaption(std::string("Please distribute " + toString(pointsLeft) + " points")); + mAttributesLeft->setCaption(std::string("Please distribute " + + toString(pointsLeft) + " points")); } else { - mAttributesLeft->setCaption(std::string("Please remove " + toString(-pointsLeft) + " points")); + mAttributesLeft->setCaption(std::string("Please remove " + + toString(-pointsLeft) + " points")); } } mAttributesLeft->adjustSize(); } +void +CharCreateDialog::unlock() +{ + mCreateButton->setEnabled(true); +} + int CharCreateDialog::getDistributedPoints() { int points = 0; - for (int i=0; i<7; i++) + for (int i = 0; i < 7; i++) { - points += (int)mAttributeSlider[i]->getValue(); + points += (int) mAttributeSlider[i]->getValue(); } return points; } diff --git a/src/gui/char_select.h b/src/gui/char_select.h index 5066897e..9d9184ea 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -114,9 +114,17 @@ class CharCreateDialog : public Window, public gcn::ActionListener */ ~CharCreateDialog(); - void action(const gcn::ActionEvent &event); + void + action(const gcn::ActionEvent &event); - std::string getName(); + const std::string& + getName(); + + /** + * Unlocks the dialog, enabling the create character button again. + */ + void + unlock(); private: int getDistributedPoints(); diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index ec525c47..ec84491e 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -30,7 +30,6 @@ #include "../resources/iteminfo.h" #include "../resources/resourcemanager.h" -#include "../resources/spriteset.h" #include "../utils/tostring.h" diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index 308311b7..a176f226 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -35,7 +35,6 @@ #include "../resources/image.h" #include "../resources/iteminfo.h" #include "../resources/resourcemanager.h" -#include "../resources/spriteset.h" #include "../utils/tostring.h" @@ -65,7 +64,8 @@ ItemContainer::logic() int i = mInventory->getLastUsedSlot() + 1; - if (i != mMaxItems) { + if (i != mMaxItems) + { mMaxItems = i; setWidth(getWidth()); } @@ -192,9 +192,9 @@ ItemContainer::mousePressed(gcn::MouseEvent &event) int my = event.getY(); int index = mx / gridWidth + ((my / gridHeight) * columns); - if (index > INVENTORY_SIZE) { + if (index > INVENTORY_SIZE) index = INVENTORY_SIZE - 1; - } + setSelectedItem(mInventory->getItem(index)); } } diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 9df3b489..15ec6314 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -36,24 +36,6 @@ #include "passwordfield.h" #include "textfield.h" -void -WrongDataNoticeListener::setTarget(gcn::TextField *textField) -{ - mTarget = textField; -} - -void -WrongDataNoticeListener::action(const gcn::ActionEvent &event) -{ - if (event.getId() == "ok") - { - // Reset the field - mTarget->setText(""); - mTarget->setCaretPosition(0); - mTarget->requestFocus(); - } -} - LoginDialog::LoginDialog(LoginData *loginData): Window("Login"), mLoginData(loginData) { @@ -66,28 +48,33 @@ LoginDialog::LoginDialog(LoginData *loginData): mCancelButton = new Button("Cancel", "cancel", this); mRegisterButton = new Button("Register", "register", this); - setContentSize(200, 91); + const int width = 220; + const int height = 100; + + setContentSize(width, height); userLabel->setPosition(5, 5); passLabel->setPosition(5, 14 + userLabel->getHeight()); mUserField->setPosition(65, 5); mPassField->setPosition(65, 14 + userLabel->getHeight()); - mUserField->setWidth(130); - mPassField->setWidth(130); + mUserField->setWidth(width - 70); + mPassField->setWidth(width - 70); mKeepCheck->setPosition(4, 68); mCancelButton->setPosition( - 200 - mCancelButton->getWidth() - 5, - 91 - mCancelButton->getHeight() - 5); + width - mCancelButton->getWidth() - 5, + height - mCancelButton->getHeight() - 5); mOkButton->setPosition( mCancelButton->getX() - mOkButton->getWidth() - 5, - 91 - mOkButton->getHeight() - 5); + height - mOkButton->getHeight() - 5); mRegisterButton->setPosition( mKeepCheck->getX() + mKeepCheck->getWidth() + 10, - 91 - mRegisterButton->getHeight() - 5); + height - mRegisterButton->getHeight() - 5); mUserField->setActionEventId("ok"); mPassField->setActionEventId("ok"); + mUserField->addKeyListener(this); + mPassField->addKeyListener(this); mUserField->addActionListener(this); mPassField->addActionListener(this); mKeepCheck->addActionListener(this); @@ -110,37 +97,27 @@ LoginDialog::LoginDialog(LoginData *loginData): mPassField->requestFocus(); } - mWrongDataNoticeListener = new WrongDataNoticeListener(); + mOkButton->setEnabled(canSubmit()); } LoginDialog::~LoginDialog() { - delete mWrongDataNoticeListener; } void LoginDialog::action(const gcn::ActionEvent &event) { - if (event.getId() == "ok") + if (event.getId() == "ok" && canSubmit()) { - // Check login - if (mUserField->getText().empty()) - { - mWrongDataNoticeListener->setTarget(mPassField); - OkDialog *dlg = new OkDialog("Error", "Enter your username first"); - dlg->addActionListener(mWrongDataNoticeListener); - } - else - { - mLoginData->username = mUserField->getText(); - mLoginData->password = mPassField->getText(); - mLoginData->remember = mKeepCheck->isMarked(); - - mOkButton->setEnabled(false); - mRegisterButton->setEnabled(false); - - state = STATE_LOGIN_ATTEMPT; - } + mLoginData->username = mUserField->getText(); + mLoginData->password = mPassField->getText(); + mLoginData->remember = mKeepCheck->isMarked(); + mLoginData->registerLogin = false; + + mOkButton->setEnabled(false); + mRegisterButton->setEnabled(false); + + state = STATE_LOGIN_ATTEMPT; } else if (event.getId() == "cancel") { @@ -148,6 +125,24 @@ LoginDialog::action(const gcn::ActionEvent &event) } else if (event.getId() == "register") { + // Transfer these fields on to the register dialog + mLoginData->username = mUserField->getText(); + mLoginData->password = mPassField->getText(); + state = STATE_REGISTER; } } + +void +LoginDialog::keyPressed(gcn::KeyEvent &keyEvent) +{ + mOkButton->setEnabled(canSubmit()); +} + +bool +LoginDialog::canSubmit() +{ + return !mUserField->getText().empty() && + !mPassField->getText().empty() && + state == STATE_LOGIN; +} diff --git a/src/gui/login.h b/src/gui/login.h index 05c0da31..d8ae7eaf 100644 --- a/src/gui/login.h +++ b/src/gui/login.h @@ -26,29 +26,21 @@ #include #include +#include #include "window.h" #include "../guichanfwd.h" class LoginData; -/** - * Listener used for handling wrong data. - */ -class WrongDataNoticeListener : public gcn::ActionListener { - public: - void setTarget(gcn::TextField *textField); - void action(const gcn::ActionEvent &event); - private: - gcn::TextField *mTarget; -}; - /** * The login dialog. * * \ingroup Interface */ -class LoginDialog : public Window, public gcn::ActionListener { +class LoginDialog : public Window, public gcn::ActionListener, + public gcn::KeyListener +{ public: /** * Constructor @@ -67,7 +59,19 @@ class LoginDialog : public Window, public gcn::ActionListener { */ void action(const gcn::ActionEvent &event); + /** + * Called when a key is pressed in one of the text fields. + */ + void keyPressed(gcn::KeyEvent &keyEvent); + private: + /** + * Returns whether submit can be enabled. This is true in the login + * state, when all necessary fields have some text. + */ + bool + canSubmit(); + gcn::TextField *mUserField; gcn::TextField *mPassField; gcn::CheckBox *mKeepCheck; @@ -75,8 +79,6 @@ class LoginDialog : public Window, public gcn::ActionListener { gcn::Button *mCancelButton; gcn::Button *mRegisterButton; - WrongDataNoticeListener *mWrongDataNoticeListener; - LoginData *mLoginData; }; diff --git a/src/gui/register.cpp b/src/gui/register.cpp index be15747d..c8e01a6c 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -41,6 +41,21 @@ #include "textfield.h" #include "ok_dialog.h" +void +WrongDataNoticeListener::setTarget(gcn::TextField *textField) +{ + mTarget = textField; +} + +void +WrongDataNoticeListener::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "ok") + { + mTarget->requestFocus(); + } +} + RegisterDialog::RegisterDialog(LoginData *loginData): Window("Register"), mWrongDataNoticeListener(new WrongDataNoticeListener()), @@ -50,28 +65,28 @@ RegisterDialog::RegisterDialog(LoginData *loginData): gcn::Label *passwordLabel = new gcn::Label("Password:"); gcn::Label *confirmLabel = new gcn::Label("Confirm:"); gcn::Label *emailLabel = new gcn::Label("Email:"); - mUserField = new TextField("player"); - mPasswordField = new PasswordField(); + mUserField = new TextField(loginData->username); + mPasswordField = new PasswordField(loginData->password); mConfirmField = new PasswordField(); mEmailField = new TextField(); mRegisterButton = new Button("Register", "register", this); mCancelButton = new Button("Cancel", "cancel", this); - const int width = 200; + const int width = 220; const int height = 130; setContentSize(width, height); mUserField->setPosition(65, 5); - mUserField->setWidth(130); + mUserField->setWidth(width - 70); mPasswordField->setPosition( 65, mUserField->getY() + mUserField->getHeight() + 7); - mPasswordField->setWidth(130); + mPasswordField->setWidth(mUserField->getWidth()); mConfirmField->setPosition( 65, mPasswordField->getY() + mPasswordField->getHeight() + 7); - mConfirmField->setWidth(130); + mConfirmField->setWidth(mUserField->getWidth()); mEmailField->setPosition( 65, mConfirmField->getY() + mConfirmField->getHeight() + 7); - mEmailField->setWidth(130); + mEmailField->setWidth(mUserField->getWidth()); userLabel->setPosition(5, mUserField->getY() + 1); passwordLabel->setPosition(5, mPasswordField->getY() + 1); @@ -79,11 +94,30 @@ RegisterDialog::RegisterDialog(LoginData *loginData): emailLabel->setPosition(5, mEmailField->getY() + 1); mCancelButton->setPosition( - width - 5 - mCancelButton->getWidth(), - height - 5 - mCancelButton->getHeight()); + width - mCancelButton->getWidth() - 5, + height - mCancelButton->getHeight() - 5); mRegisterButton->setPosition( - mCancelButton->getX() - 5 - mRegisterButton->getWidth(), - mCancelButton->getY()); + mCancelButton->getX() - mRegisterButton->getWidth() - 5, + height - mRegisterButton->getHeight() - 5); + + mUserField->addKeyListener(this); + mPasswordField->addKeyListener(this); + mConfirmField->addKeyListener(this); + mEmailField->addKeyListener(this); + + /* TODO: + * This is a quick and dirty way to respond to the ENTER key, regardless of + * which text field is selected. There may be a better way now with the new + * input system of Guichan 0.6.0. See also the login dialog. + */ + mUserField->setActionEventId("register"); + mPasswordField->setActionEventId("register"); + mConfirmField->setActionEventId("register"); + mEmailField->setActionEventId("register"); + mUserField->addActionListener(this); + mPasswordField->addActionListener(this); + mConfirmField->addActionListener(this); + mEmailField->addActionListener(this); add(userLabel); add(passwordLabel); @@ -100,6 +134,8 @@ RegisterDialog::RegisterDialog(LoginData *loginData): setVisible(true); mUserField->requestFocus(); mUserField->setCaretPosition(mUserField->getText().length()); + + mRegisterButton->setEnabled(canSubmit()); } RegisterDialog::~RegisterDialog() @@ -114,7 +150,7 @@ RegisterDialog::action(const gcn::ActionEvent &event) { state = STATE_LOGIN; } - else if (event.getId() == "register") + else if (event.getId() == "register" && canSubmit()) { const std::string user = mUserField->getText(); logger->log("RegisterDialog::register Username is %s", user.c_str()); @@ -122,14 +158,7 @@ RegisterDialog::action(const gcn::ActionEvent &event) std::stringstream errorMsg; int error = 0; - // Check login - if (user.empty()) - { - // No username - errorMsg << "Enter your username first."; - error = 1; - } - else if (user.length() < LEN_MIN_USERNAME) + if (user.length() < LEN_MIN_USERNAME) { // Name too short errorMsg << "The username needs to be at least " @@ -178,9 +207,11 @@ RegisterDialog::action(const gcn::ActionEvent &event) } else if (error == 2) { - mWrongDataNoticeListener->setTarget(this->mPasswordField); // Reset password confirmation + mPasswordField->setText(""); mConfirmField->setText(""); + + mWrongDataNoticeListener->setTarget(this->mPasswordField); } OkDialog *dlg = new OkDialog("Error", errorMsg.str()); @@ -191,7 +222,6 @@ RegisterDialog::action(const gcn::ActionEvent &event) // No errors detected, register the new user. mRegisterButton->setEnabled(false); - mLoginData->port = (short)config.getValue("port", 0); mLoginData->username = mUserField->getText(); mLoginData->password = mPasswordField->getText(); mLoginData->email = mEmailField->getText(); @@ -201,3 +231,18 @@ RegisterDialog::action(const gcn::ActionEvent &event) } } } + +void +RegisterDialog::keyPressed(gcn::KeyEvent &keyEvent) +{ + mRegisterButton->setEnabled(canSubmit()); +} + +bool +RegisterDialog::canSubmit() +{ + return !mUserField->getText().empty() && + !mPasswordField->getText().empty() && + !mConfirmField->getText().empty() && + state == STATE_REGISTER; +} diff --git a/src/gui/register.h b/src/gui/register.h index 4ffe451f..088e8f9b 100644 --- a/src/gui/register.h +++ b/src/gui/register.h @@ -26,23 +26,39 @@ #include #include +#include #include "window.h" #include "../guichanfwd.h" class LoginData; class OkDialog; -class WrongDataNoticeListener; /** - * The login dialog. + * Listener used while dealing with wrong data. It is used to direct the focus + * to the field which contained wrong data when the Ok button was pressed on + * the error notice. + */ +class WrongDataNoticeListener : public gcn::ActionListener { + public: + void setTarget(gcn::TextField *textField); + void action(const gcn::ActionEvent &event); + private: + gcn::TextField *mTarget; +}; + +/** + * The registration dialog. * * \ingroup Interface */ -class RegisterDialog : public Window, public gcn::ActionListener { +class RegisterDialog : public Window, public gcn::ActionListener, + public gcn::KeyListener +{ public: /** - * Constructor + * Constructor. Name, password and server fields will be initialized to + * the information already present in the LoginData instance. * * @see Window::Window */ @@ -58,10 +74,19 @@ class RegisterDialog : public Window, public gcn::ActionListener { */ void action(const gcn::ActionEvent &event); - // Made them public to have the possibility to request focus - // from external functions. + /** + * Called when a key is pressed in one of the text fields. + */ + void keyPressed(gcn::KeyEvent &keyEvent); private: + /** + * Returns whether submit can be enabled. This is true in the register + * state, when all necessary fields have some text. + */ + bool + canSubmit(); + gcn::TextField *mUserField; gcn::TextField *mPasswordField; gcn::TextField *mConfirmField; diff --git a/src/gui/unregisterdialog.cpp b/src/gui/unregisterdialog.cpp index 9a09389d..5558e8fc 100644 --- a/src/gui/unregisterdialog.cpp +++ b/src/gui/unregisterdialog.cpp @@ -34,7 +34,7 @@ #include "button.h" #include "checkbox.h" -#include "login.h" +#include "register.h" #include "passwordfield.h" #include "textfield.h" #include "ok_dialog.h" diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index bc635cce..f3e9031c 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -28,15 +28,20 @@ #include "gui.h" #include "popupmenu.h" +#include "../simpleanimation.h" #include "../beingmanager.h" #include "../configuration.h" #include "../flooritemmanager.h" #include "../graphics.h" #include "../localplayer.h" #include "../map.h" +#include "../monster.h" #include "../npc.h" -#include "../resources/monsterdb.h" +#include "../resources/animation.h" +#include "../resources/monsterinfo.h" +#include "../resources/resourcemanager.h" +#include "../resources/imageset.h" #include "../utils/tostring.h" @@ -60,11 +65,39 @@ Viewport::Viewport(): config.addListener("ScrollRadius", this); mPopupMenu = new PopupMenu(); + + // Load target cursors + ResourceManager *resman = ResourceManager::getInstance(); + mInRangeImages = resman->getImageSet( + "graphics/gui/target-cursor-blue.png", 44, 35); + mOutRangeImages = resman->getImageSet( + "graphics/gui/target-cursor-red.png", 44, 35); + Animation *animInRange = new Animation(); + Animation *animOutRange = new Animation(); + + for (unsigned int i = 0; i < mInRangeImages->size(); ++i) + { + animInRange->addFrame(mInRangeImages->get(i), 75, 0, 0); + } + + for (unsigned int j = 0; j < mOutRangeImages->size(); ++j) + { + animOutRange->addFrame(mOutRangeImages->get(j), 75, 0, 0); + } + + mTargetCursorInRange = new SimpleAnimation(animInRange); + mTargetCursorOutRange = new SimpleAnimation(animOutRange); } Viewport::~Viewport() { delete mPopupMenu; + + delete mTargetCursorInRange; + delete mTargetCursorOutRange; + + mInRangeImages->decRef(); + mOutRangeImages->decRef(); } void @@ -158,10 +191,12 @@ Viewport::draw(gcn::Graphics *gcnGraphics) if (mMap) { mMap->draw(graphics, mCameraX, mCameraY, 0); + drawTargetCursor(graphics); mMap->draw(graphics, mCameraX, mCameraY, 1); mMap->draw(graphics, mCameraX, mCameraY, 2); mMap->drawOverlay(graphics, mViewX, mViewY, (int) config.getValue("OverlayDetail", 2)); + drawTargetName(graphics); } // Find a path from the player to the mouse, and draw it. This is for debug @@ -201,28 +236,6 @@ Viewport::draw(gcn::Graphics *gcnGraphics) (*i)->drawEmotion(graphics, -mCameraX, -mCameraY); } - // Draw target marker if needed - Being *target = player_node->getTarget(); - if (target) - { - graphics->setFont(speechFont); - graphics->setColor(gcn::Color(255, 32, 32)); - int dy = (target->getType() == Being::PLAYER) ? 80 : 42; - - std::string mobName = ""; - - if (target->mJob >= 1002) - { - int mobId = target->mJob - 1002; - mobName = MonsterDB::get(mobId).getName(); - - graphics->drawText(mobName, - target->getPixelX() - mCameraX + 15, - target->getPixelY() - mCameraY - dy, - gcn::Graphics::CENTER); - } - } - // Draw contained widgets WindowContainer::draw(gcnGraphics); } @@ -245,6 +258,57 @@ Viewport::logic() mouseY + mCameraY); mWalkTime = player_node->mWalkTime; } + + mTargetCursorInRange->update(10); + mTargetCursorOutRange->update(10); +} + +void +Viewport::drawTargetCursor(Graphics *graphics) +{ + // Draw target marker if needed + Being *target = player_node->getTarget(); + if (target) + { + // Find whether target is in range + int rangeX = abs(target->mX - player_node->mX); + int rangeY = abs(target->mY - player_node->mY); + int attackRange = player_node->getAttackRange(); + + // Draw the target cursor, which one depends if the target is in range + if (rangeX > attackRange || rangeY > attackRange) + { + // Draw the out of range cursor + graphics->drawImage(mTargetCursorOutRange->getCurrentImage(), + target->getPixelX() - mCameraX, + target->getPixelY() - mCameraY); + } + else + { + // Draw the in range cursor + graphics->drawImage(mTargetCursorInRange->getCurrentImage(), + target->getPixelX() - mCameraX, + target->getPixelY() - mCameraY); + } + } +} + +void +Viewport::drawTargetName(Graphics *graphics) +{ + // Draw target marker if needed + Being *target = player_node->getTarget(); + if (target && target->getType() == Being::MONSTER) + { + graphics->setFont(speechFont); + graphics->setColor(gcn::Color(255, 32, 32)); + + const MonsterInfo &mi = static_cast(target)->getInfo(); + graphics->drawText(mi.getName(), + target->getPixelX() - mCameraX + 15, + target->getPixelY() - mCameraY - 42, + gcn::Graphics::CENTER); + } } void diff --git a/src/gui/viewport.h b/src/gui/viewport.h index f1cadd98..84efeff3 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -33,8 +33,11 @@ class Map; class Being; class FloorItem; +class ImageSet; class Item; class PopupMenu; +class Graphics; +class SimpleAnimation; /** * The viewport on the map. Displays the current map and handles mouse input @@ -138,6 +141,18 @@ class Viewport : public WindowContainer, public gcn::MouseListener, */ void showPopup(int x, int y, Being *being); + /** + * Draws range based target cursor + */ + void + drawTargetCursor(Graphics *graphics); + + /** + * Draws target name + */ + void + drawTargetName(Graphics *graphics); + Map *mMap; /**< The current map. */ @@ -149,6 +164,15 @@ class Viewport : public WindowContainer, public gcn::MouseListener, int mCameraY; /**< Current viewpoint in tiles. */ bool mShowDebugPath; /**< Show a path from player to pointer. */ + ImageSet *mInRangeImages; /**< Images of in range target cursor. */ + ImageSet *mOutRangeImages; /**< Images of out of range target cursor.*/ + + /** Animated in range target cursor. */ + SimpleAnimation *mTargetCursorInRange; + + /** Animated out of range target cursor. */ + SimpleAnimation *mTargetCursorOutRange; + bool mPlayerFollowMouse; int mWalkTime; diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 7f595ef1..97371677 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -38,6 +38,7 @@ LocalPlayer *player_node = NULL; LocalPlayer::LocalPlayer(): Player(65535, 0, NULL), + mAttackRange(0), mInventory(new Inventory()), mAttributeBase(NB_BASE_ATTRIBUTES, 0), mAttributeEffective(NB_BASE_ATTRIBUTES, 0), diff --git a/src/localplayer.h b/src/localplayer.h index 299cf85a..fb7703dd 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -152,6 +152,16 @@ class LocalPlayer : public Player void dropItem(Item *item, int quantity); void pickUp(FloorItem *item); + /** + * Sets the attack range. + */ + void setAttackRange(int range) { mAttackRange = range; } + + /** + * Gets the attack range. + */ + int getAttackRange() const { return mAttackRange; } + /** * Sents a trade request to the given being. */ @@ -213,6 +223,8 @@ class LocalPlayer : public Player int getMaxHP() const { return mMaxHP; } + Uint16 mAttackRange; + void setHP(int value) { mHP = value; } diff --git a/src/logindata.h b/src/logindata.h index 0a01331c..fbbbb573 100644 --- a/src/logindata.h +++ b/src/logindata.h @@ -36,8 +36,8 @@ struct LoginData int session_ID1; int session_ID2; - bool remember; - bool registerLogin; + bool remember; /**< Whether to store the username and host. */ + bool registerLogin; /**< Whether an account is being registered. */ void clear() { diff --git a/src/main.cpp b/src/main.cpp index aad6a68c..bbbf0fd1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,9 +30,13 @@ #include #include -#include +#ifdef WIN32 +#include +#endif +#include #include +#include #include @@ -63,11 +67,11 @@ #include "gui/login.h" #include "gui/quitdialog.h" #include "gui/ok_dialog.h" +#include "gui/progressbar.h" #include "gui/register.h" #include "gui/updatewindow.h" #include "gui/textfield.h" - #include "net/charserverhandler.h" #include "net/connection.h" #include "net/loginhandler.h" @@ -86,7 +90,6 @@ #include "resources/itemdb.h" #include "resources/monsterdb.h" #include "resources/resourcemanager.h" -#include "resources/spriteset.h" #include "utils/dtor.h" #include "utils/tostring.h" @@ -103,23 +106,13 @@ unsigned char screen_mode; Sound sound; Music *bgm; -Configuration config; /**< Xml file configuration reader */ +Configuration config; /**< XML file configuration reader */ Logger *logger; /**< Log object */ Net::Connection *accountServerConnection = 0; Net::Connection *gameServerConnection = 0; Net::Connection *chatServerConnection = 0; -namespace { - struct ErrorListener : public gcn::ActionListener - { - void action(const gcn::ActionEvent &event) - { - state = STATE_CHOOSE_SERVER; - } - } errorListener; -} - /** * A structure holding the values of various options that can be passed from * the command line. @@ -131,12 +124,14 @@ struct Options */ Options(): printHelp(false), + printVersion(false), skipUpdate(false), chooseDefault(false), serverPort(0) {}; bool printHelp; + bool printVersion; bool skipUpdate; bool chooseDefault; std::string playername; @@ -237,7 +232,16 @@ void initEngine() SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); SDL_WM_SetCaption("The Mana World", NULL); - SDL_WM_SetIcon(IMG_Load(TMW_DATADIR "data/icons/tmw-icon.png"), NULL); +#ifdef WIN32 + static SDL_SysWMinfo pInfo; + SDL_GetWMInfo(&pInfo); + HICON icon = LoadIcon(GetModuleHandle(NULL), "A"); + SetClassLong(pInfo.window, GCL_HICON, (LONG) icon); +#else + SDL_Surface *icon = IMG_Load(TMW_DATADIR "data/icons/tmw.png"); + SDL_SetAlpha(icon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); + SDL_WM_SetIcon(icon, NULL); +#endif ResourceManager *resman = ResourceManager::getInstance(); @@ -356,6 +360,7 @@ void printHelp() "tmw\n\n" "Options:\n" " -h --help : Display this help\n" + " -v --version : Display the version\n" " -u --skipupdate : Skip the update process\n" " -U --username : Login with this username\n" " -P --password : Login with this password\n" @@ -366,12 +371,23 @@ void printHelp() " -C --configfile : Configuration file to use\n"; } +void printVersion() +{ +#ifdef PACKAGE_VERSION + std::cout << "The Mana World version " << PACKAGE_VERSION << std::endl; +#else + std::cout << "The Mana World version " << + "(local build?, PACKAGE_VERSION is not defined)" << std::endl; +#endif +} + void parseOptions(int argc, char *argv[], Options &options) { - const char *optstring = "huU:P:Dp:s:o:C:"; + const char *optstring = "hvuU:P:Dp:s:o:C:"; const struct option long_options[] = { { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, { "skipupdate", no_argument, 0, 'u' }, { "username", required_argument, 0, 'U' }, { "password", required_argument, 0, 'P' }, @@ -395,6 +411,9 @@ void parseOptions(int argc, char *argv[], Options &options) case 'h': options.printHelp = true; break; + case 'v': + options.printVersion = true; + break; case 'u': options.skipUpdate = true; break; @@ -449,6 +468,16 @@ LoginHandler loginHandler; LogoutHandler logoutHandler; LockedArray charInfo(MAX_SLOT + 1); +namespace { + struct ErrorListener : public gcn::ActionListener + { + void action(const gcn::ActionEvent &event) + { + state = STATE_CHOOSE_SERVER; + } + } errorListener; +} + // TODO Find some nice place for these functions void accountLogin(LoginData *loginData) { @@ -466,15 +495,17 @@ void accountLogin(LoginData *loginData) // Clear the password, avoids auto login when returning to login loginData->password = ""; - //remove _M or _F from username after a login for registration purpose + // Remove _M or _F from username after a login for registration purpose if (loginData->registerLogin) { - loginData->registerLogin = false; - loginData->username = loginData->username.substr(0, loginData->username.length() - 2); + loginData->username = + loginData->username.substr(0, loginData->username.length() - 2); } + // TODO This is not the best place to save the config, but at least better // than the login gui window - if (loginData->remember) { + if (loginData->remember) + { config.setValue("host", loginData->hostname); config.setValue("username", loginData->username); } @@ -557,7 +588,7 @@ void logoutThenExit() logoutHandler.reset(); logoutHandler.setScenario(LOGOUT_EXIT); - //Can't logout if we were not logged in ... + // Can't logout if we were not logged in ... if (accountServerConnection->isConnected()) { Net::AccountServer::logout(); @@ -616,10 +647,6 @@ void initXML() /** Main */ int main(int argc, char *argv[]) { -#ifdef PACKAGE_VERSION - std::cout << "The Mana World v" << PACKAGE_VERSION << std::endl; -#endif - // Parse command line options Options options; parseOptions(argc, argv, options); @@ -628,6 +655,11 @@ int main(int argc, char *argv[]) printHelp(); return 0; } + else if (options.printVersion) + { + printVersion(); + return 0; + } // Initialize PhysicsFS PHYSFS_init(argv[0]); @@ -647,10 +679,16 @@ int main(int argc, char *argv[]) initConfiguration(options); initEngine(); + Game *game = NULL; Window *currentDialog = NULL; QuitDialog* quitDialog = NULL; Image *login_wallpaper = NULL; - Game *game = NULL; + + gcn::Container *top = static_cast(gui->getTop()); +#ifdef PACKAGE_VERSION + gcn::Label *versionLabel = new gcn::Label(PACKAGE_VERSION); + top->add(versionLabel, 2, 2); +#endif sound.playMusic(TMW_DATADIR "data/music/Magick - Real.ogg"); @@ -715,8 +753,8 @@ int main(int argc, char *argv[]) guiInput->pushInput(event); } - gui->logic(); Net::flush(); + gui->logic(); if (!login_wallpaper) { @@ -729,10 +767,6 @@ int main(int argc, char *argv[]) } graphics->drawImage(login_wallpaper, 0, 0); -#ifdef PACKAGE_VERSION - graphics->setFont(gui->getFont()); - graphics->drawText(PACKAGE_VERSION, 0, 0); -#endif gui->draw(); graphics->updateScreen(); @@ -759,7 +793,6 @@ int main(int argc, char *argv[]) accountServerConnection->isConnected()) { reconnectAccount(token); - state = STATE_WAIT; } @@ -936,6 +969,10 @@ int main(int argc, char *argv[]) Net::ChatServer::connect(chatServerConnection, token); sound.fadeOutMusic(1000); +#ifdef PACKAGE_VERSION + delete versionLabel; + versionLabel = NULL; +#endif currentDialog = NULL; logger->log("State: GAME"); diff --git a/src/monster.h b/src/monster.h index 18fa703e..39bbf3d7 100644 --- a/src/monster.h +++ b/src/monster.h @@ -43,7 +43,6 @@ class Monster : public Being */ virtual void handleAttack(); - protected: /** * Returns the MonsterInfo, with static data about this monster. */ diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp index 34fc188d..820aaea4 100644 --- a/src/net/charserverhandler.cpp +++ b/src/net/charserverhandler.cpp @@ -34,11 +34,13 @@ #include "../main.h" #include "../gui/ok_dialog.h" +#include "../gui/char_select.h" extern Net::Connection *gameServerConnection; extern Net::Connection *chatServerConnection; -CharServerHandler::CharServerHandler() +CharServerHandler::CharServerHandler(): + mCharCreateDialog(0) { static const Uint16 _messages[] = { APMSG_CHAR_CREATE_RESPONSE, @@ -99,6 +101,13 @@ CharServerHandler::handleMessage(MessageIn &msg) mCharInfo->unlock(); mCharInfo->select(slot); mCharInfo->setEntry(tempPlayer); + + // Close the character create dialog + if (mCharCreateDialog) + { + mCharCreateDialog->scheduleDelete(); + mCharCreateDialog = 0; + } break; case APMSG_CHAR_SELECT_RESPONSE: @@ -154,6 +163,9 @@ CharServerHandler::handleCharCreateResponse(MessageIn &msg) } new OkDialog("Error", message); } + + if (mCharCreateDialog) + mCharCreateDialog->unlock(); } void @@ -177,15 +189,20 @@ CharServerHandler::handleCharSelectResponse(MessageIn &msg) // Keep the selected character and delete the others player_node = mCharInfo->getEntry(); + int slot = mCharInfo->getPos(); mCharInfo->unlock(); mCharInfo->select(0); do { LocalPlayer *tmp = mCharInfo->getEntry(); if (tmp != player_node) + { delete tmp; + mCharInfo->setEntry(0); + } mCharInfo->next(); } while (mCharInfo->getPos()); + mCharInfo->select(slot); mCharInfo->clear(); //player_node will be deleted by ~Game @@ -204,8 +221,11 @@ CharServerHandler::readPlayerData(MessageIn &msg, int &slot) tempPlayer->setHairColor(msg.readByte()); tempPlayer->setLevel(msg.readByte()); tempPlayer->setMoney(msg.readLong()); - for (int i = 0; i < 7; i++) { + + for (int i = 0; i < 7; i++) + { tempPlayer->setAttributeBase(i, msg.readByte()); } + return tempPlayer; } diff --git a/src/net/charserverhandler.h b/src/net/charserverhandler.h index 342641d7..4a4fe0c3 100644 --- a/src/net/charserverhandler.h +++ b/src/net/charserverhandler.h @@ -28,9 +28,13 @@ #include "../lockedarray.h" +class CharCreateDialog; class LocalPlayer; class LoginData; +/** + * Deals with incoming messages related to character selection. + */ class CharServerHandler : public MessageHandler { public: @@ -45,6 +49,14 @@ class CharServerHandler : public MessageHandler mCharInfo = charInfo; } + /** + * Sets the character create dialog. The handler will clean up this + * dialog when a new character is succesfully created, and will unlock + * the dialog when a new character failed to be created. + */ + void setCharCreateDialog(CharCreateDialog *window) + { mCharCreateDialog = window; } + protected: void handleCharCreateResponse(MessageIn &msg); @@ -53,6 +65,7 @@ class CharServerHandler : public MessageHandler handleCharSelectResponse(MessageIn &msg); LockedArray *mCharInfo; + CharCreateDialog *mCharCreateDialog; LocalPlayer* readPlayerData(MessageIn &msg, int &slot); diff --git a/src/net/equipmenthandler.cpp b/src/net/equipmenthandler.cpp index 1c0fd4ca..c0072a45 100644 --- a/src/net/equipmenthandler.cpp +++ b/src/net/equipmenthandler.cpp @@ -43,6 +43,7 @@ EquipmentHandler::EquipmentHandler() 0x01d7, SMSG_PLAYER_UNEQUIP, SMSG_PLAYER_ARROW_EQUIP, + SMSG_PLAYER_ATTACK_RANGE, 0 }; handledMessages = _messages; @@ -191,6 +192,10 @@ void EquipmentHandler::handleMessage(MessageIn &msg) index, equipPoint, type, position); break; + case SMSG_PLAYER_ATTACK_RANGE: + player_node->setAttackRange(msg.readShort()); + break; + case SMSG_PLAYER_ARROW_EQUIP: itemId = msg.readShort(); diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp index c68a620a..90f2dbd5 100644 --- a/src/net/loginhandler.cpp +++ b/src/net/loginhandler.cpp @@ -88,7 +88,7 @@ void LoginHandler::handleMessage(MessageIn &msg) { switch (errMsg) { case REGISTER_INVALID_VERSION: - errorMessage = "Client has an insufficient version number to login."; + errorMessage = "Client has an insufficient version number to login."; break; case ERRMSG_INVALID_ARGUMENT: errorMessage = "Wrong username, password or email address"; diff --git a/src/net/protocol.h b/src/net/protocol.h index a9ee0e5b..b5dc2996 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -44,6 +44,7 @@ #define SMSG_PLAYER_EQUIPMENT 0x00a4 #define SMSG_PLAYER_EQUIP 0x00aa #define SMSG_PLAYER_UNEQUIP 0x00ac +#define SMSG_PLAYER_ATTACK_RANGE 0x013a #define SMSG_PLAYER_ARROW_EQUIP 0x013c #define SMSG_PLAYER_ARROW_MESSAGE 0x013b #define SMSG_PLAYER_SKILLS 0x010f diff --git a/src/npc.cpp b/src/npc.cpp index ccd085b6..2d291104 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -28,8 +28,6 @@ #include "gui/gui.h" -class Spriteset; - NPC *current_npc = 0; NPC::NPC(Uint16 id, Uint16 job, Map *map): diff --git a/src/resources/animation.h b/src/resources/animation.h index 54142bcb..d0d11c69 100644 --- a/src/resources/animation.h +++ b/src/resources/animation.h @@ -29,7 +29,6 @@ #include class Image; -class Spriteset; /** * A single frame in an animation, with a delay and an offset. diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 58325213..a27783d4 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -80,7 +80,7 @@ Image* Image::load(void *buffer, unsigned int bufferSize, tmpImage = IMG_Load_RW(rw, 1); } - if (tmpImage == NULL) { + if (!tmpImage) { logger->log("Error, image load failed: %s", IMG_GetError()); return NULL; } @@ -99,87 +99,28 @@ Image* Image::load(void *buffer, unsigned int bufferSize, amask = 0xff000000; #endif - // Convert the image to a 32 bit software surface for processing - SDL_Surface *formatImage = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, 32, - rmask, gmask, bmask, amask); - - if (formatImage == NULL) { - logger->log("Error, image load failed: not enough memory"); - SDL_FreeSurface(tmpImage); - return NULL; - } - - SDL_Surface *image = SDL_ConvertSurface( - tmpImage, formatImage->format, SDL_SWSURFACE); - - SDL_FreeSurface(formatImage); - - if (image == NULL) { - logger->log("Error, image load failed: not enough memory"); - return NULL; - } - - bool hasPink = false; - bool hasAlpha = false; - int i; - Uint32 pink = SDL_MapRGB(image->format, 255, 0, 255); - - // Figure out whether the image has pink pixels - for (i = 0; i < image->w * image->h; ++i) - { - if (((Uint32*)image->pixels)[i] == pink) - { - hasPink = true; - break; - } - } - - // Figure out whether the image uses its alpha layer - for (i = 0; i < image->w * image->h; ++i) - { - Uint8 r, g, b, a; - SDL_GetRGBA( - ((Uint32*)image->pixels)[i], - image->format, - &r, &g, &b, &a); - - if (a != 255) - { - hasAlpha = true; - break; - } - } - - SDL_FreeSurface(image); - - if (hasPink && !hasAlpha) { - SDL_SetColorKey(tmpImage, SDL_SRCCOLORKEY, - SDL_MapRGB(tmpImage->format, 255, 0, 255)); - } else if (hasAlpha) { - SDL_SetAlpha(tmpImage, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); - } - #ifdef USE_OPENGL if (mUseOpenGL) { int width = tmpImage->w; int height = tmpImage->h; - int realWidth = 1, realHeight = 1; + int realWidth = powerOfTwo(width); + int realHeight = powerOfTwo(height); - while (realWidth < width && realWidth < 1024) { - realWidth *= 2; - } - - while (realHeight < height && realHeight < 1024) { - realHeight *= 2; + if (realWidth < width || realHeight < height) + { + logger->log("Warning: image too large, cropping to %dx%d texture!", + tmpImage->w, tmpImage->h); } + // Make sure the alpha channel is not used, but copied to destination SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE); + SDL_Surface *oldImage = tmpImage; - tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, 32, - rmask, gmask, bmask, amask); + tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, + 32, rmask, gmask, bmask, amask); - if (tmpImage == NULL) { + if (!tmpImage) { logger->log("Error, image convert failed: out of memory"); return NULL; } @@ -189,8 +130,6 @@ Image* Image::load(void *buffer, unsigned int bufferSize, GLuint texture; glGenTextures(1, &texture); - logger->log("Binding texture %d (%dx%d)", - texture, tmpImage->w, tmpImage->h); glBindTexture(GL_TEXTURE_2D, texture); if (SDL_MUSTLOCK(tmpImage)) { @@ -246,8 +185,27 @@ Image* Image::load(void *buffer, unsigned int bufferSize, } #endif - // Set color key and alpha blending optins, and convert the surface to the - // current display format + bool hasAlpha = false; + + // Figure out whether the image uses its alpha layer + for (int i = 0; i < tmpImage->w * tmpImage->h; ++i) + { + Uint8 r, g, b, a; + SDL_GetRGBA( + ((Uint32*) tmpImage->pixels)[i], + tmpImage->format, + &r, &g, &b, &a); + + if (a != 255) + { + hasAlpha = true; + break; + } + } + + SDL_Surface *image; + + // Convert the surface to the current display format if (hasAlpha) { image = SDL_DisplayFormatAlpha(tmpImage); } @@ -256,7 +214,7 @@ Image* Image::load(void *buffer, unsigned int bufferSize, } SDL_FreeSurface(tmpImage); - if (image == NULL) { + if (!image) { logger->log("Error: Image convert failed."); return NULL; } @@ -315,10 +273,22 @@ float Image::getAlpha() } #ifdef USE_OPENGL -void Image::setLoadAsOpenGL(bool useOpenGL) +void +Image::setLoadAsOpenGL(bool useOpenGL) { Image::mUseOpenGL = useOpenGL; } + +int +Image::powerOfTwo(int input) +{ + int value = 1; + while (value < input && value < 1024) + { + value <<= 1; + } + return value; +} #endif //============================================================================ diff --git a/src/resources/image.h b/src/resources/image.h index 03bf0cbc..cad21dcd 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -126,6 +126,12 @@ class Image : public Resource #ifdef USE_OPENGL Image(const std::string &idPath, GLuint glimage, int width, int height, int texWidth, int texHeight); + + /** + * Returns the first power of two equal or bigger than the input. + */ + static int + powerOfTwo(int input); #endif Image(const std::string &idPath, SDL_Surface *image); diff --git a/src/resources/imageset.cpp b/src/resources/imageset.cpp new file mode 100644 index 00000000..677c024b --- /dev/null +++ b/src/resources/imageset.cpp @@ -0,0 +1,65 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "imageset.h" + +#include "../log.h" + +#include "image.h" + +#include "../utils/dtor.h" + +ImageSet::ImageSet(const std::string& idPath, + Image *img, + int width, int height): + Resource(idPath) +{ + for (int y = 0; y + height <= img->getHeight(); y += height) + { + for (int x = 0; x + width <= img->getWidth(); x += width) + { + mImages.push_back(img->getSubImage(x, y, width, height)); + } + } + mWidth = width; + mHeight = height; +} + +ImageSet::~ImageSet() +{ + for_each(mImages.begin(), mImages.end(), make_dtor(mImages)); +} + +Image* +ImageSet::get(size_type i) +{ + if (i >= mImages.size()) + { + logger->log("Warning: Sprite #%i does not exist in this image set", i); + return NULL; + } + else + { + return mImages[i]; + } +} diff --git a/src/resources/imageset.h b/src/resources/imageset.h new file mode 100644 index 00000000..3469a3bb --- /dev/null +++ b/src/resources/imageset.h @@ -0,0 +1,66 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_IMAGESET_H +#define _TMW_IMAGESET_H + +#include + +#include "resource.h" + +class Image; + + +/** + * Stores a set of subimages originating from a single image. + */ +class ImageSet : public Resource +{ + public: + /* + * Cuts the passed image in a grid of sub images. + */ + ImageSet(const std::string &idPath, Image *img, int w, int h); + + /** + * Destructor. + */ + ~ImageSet(); + + int getWidth() { return mWidth; }; + + int getHeight() { return mHeight; }; + + typedef std::vector::size_type size_type; + Image* get(size_type i); + + size_type size() { return mImages.size(); } + + private: + std::vector mImages; + + int mHeight; /**< Height of the images in the image set. */ + int mWidth; /**< Width of the images in the image set. */ +}; + +#endif diff --git a/src/resources/monsterdb.h b/src/resources/monsterdb.h index 048638c2..46a33b06 100644 --- a/src/resources/monsterdb.h +++ b/src/resources/monsterdb.h @@ -39,7 +39,7 @@ namespace MonsterDB void unload(); - const MonsterInfo& get (int id); + const MonsterInfo& get(int id); typedef std::map MonsterInfos; typedef MonsterInfos::iterator MonsterInfoIterator; diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h index 413dafa0..05d4c014 100644 --- a/src/resources/monsterinfo.h +++ b/src/resources/monsterinfo.h @@ -1,74 +1,83 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: monsterinfo.h 2650 2006-09-03 15:00:47Z b_lindeijer $ - */ - -#ifndef _TMW_MONSTERINFO_H_ -#define _TMW_MONSTERINFO_H_ - -#include -#include -#include - - -enum SoundEvent -{ - EVENT_HIT, - EVENT_MISS, - EVENT_HURT, - EVENT_DIE -}; - - -class MonsterInfo -{ - public: - MonsterInfo(); - - ~MonsterInfo(); - - void - setName(std::string name) { mName = name; } ; - - void - setSprite(std::string filename) { mSprite = filename; } - - void - addSound (SoundEvent event, std::string filename); - - const std::string& - getName () const { return mName; }; - - const std::string& - getSprite () const { return mSprite; }; - - std::string - getSound (SoundEvent event) const; - - private: - - std::string mName; - std::string mSprite; - - std::map* > mSounds; -}; - -#endif +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: monsterinfo.h 2650 2006-09-03 15:00:47Z b_lindeijer $ + */ + +#ifndef _TMW_MONSTERINFO_H_ +#define _TMW_MONSTERINFO_H_ + +#include +#include +#include + +enum SoundEvent +{ + EVENT_HIT, + EVENT_MISS, + EVENT_HURT, + EVENT_DIE +}; + +/** + * Holds information about a certain type of monster. This includes the name + * of the monster, the sprite to display and the sounds the monster makes. + * + * @see MonsterDB + */ +class MonsterInfo +{ + public: + /** + * Constructor. + */ + MonsterInfo(); + + /** + * Destructor. + */ + ~MonsterInfo(); + + void + setName(std::string name) { mName = name; } ; + + void + setSprite(std::string filename) { mSprite = filename; } + + void + addSound (SoundEvent event, std::string filename); + + const std::string& + getName () const { return mName; }; + + const std::string& + getSprite () const { return mSprite; }; + + std::string + getSound (SoundEvent event) const; + + private: + std::string mName; + std::string mSprite; + + std::map* > mSounds; +}; + +#endif diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 2059a5c3..448e7f80 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -31,7 +31,7 @@ #include "image.h" #include "music.h" #include "soundeffect.h" -#include "spriteset.h" +#include "imageset.h" #include "spritedef.h" #include "../log.h" @@ -46,7 +46,7 @@ ResourceManager::ResourceManager() ResourceManager::~ResourceManager() { - // Release any remaining spritedefs first because they depend on spritesets + // Release any remaining spritedefs first because they depend on image sets ResourceIterator iter = mResources.begin(); while (iter != mResources.end()) { @@ -63,11 +63,11 @@ ResourceManager::~ResourceManager() } } - // Release any remaining spritesets first because they depend on images + // Release any remaining image sets first because they depend on images iter = mResources.begin(); while (iter != mResources.end()) { - if (dynamic_cast(iter->second) != 0) + if (dynamic_cast(iter->second) != 0) { cleanUp(iter->second); ResourceIterator toErase = iter; @@ -232,8 +232,8 @@ ResourceManager::getSoundEffect(const std::string &idPath) return dynamic_cast(get(SOUND_EFFECT, idPath)); } -Spriteset* -ResourceManager::getSpriteset(const std::string &imagePath, int w, int h) +ImageSet* +ResourceManager::getImageSet(const std::string &imagePath, int w, int h) { std::stringstream ss; ss << imagePath << "[" << w << "x" << h << "]"; @@ -243,7 +243,7 @@ ResourceManager::getSpriteset(const std::string &imagePath, int w, int h) if (resIter != mResources.end()) { resIter->second->incRef(); - return dynamic_cast(resIter->second); + return dynamic_cast(resIter->second); } Image *img = getImage(imagePath); @@ -252,13 +252,13 @@ ResourceManager::getSpriteset(const std::string &imagePath, int w, int h) return NULL; } - Spriteset *spriteset = new Spriteset(idPath, img, w, h); - spriteset->incRef(); - mResources[idPath] = spriteset; + ImageSet *imageSet = new ImageSet(idPath, img, w, h); + imageSet->incRef(); + mResources[idPath] = imageSet; img->decRef(); - return spriteset; + return imageSet; } SpriteDef* diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index e176e337..db29e6d3 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -33,7 +33,7 @@ class Resource; class Image; class Music; class SoundEffect; -class Spriteset; +class ImageSet; class SpriteDef; /** @@ -143,11 +143,11 @@ class ResourceManager getSoundEffect(const std::string &idPath); /** - * Creates a spriteset based on the image referenced by the given + * Creates a image set based on the image referenced by the given * path and the supplied sprite sizes */ - Spriteset* - getSpriteset(const std::string &imagePath, int w, int h); + ImageSet* + getImageSet(const std::string &imagePath, int w, int h); /** * Creates a sprite definition based on a given path and the supplied diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp index feb6f8f8..d29bd847 100644 --- a/src/resources/spritedef.cpp +++ b/src/resources/spritedef.cpp @@ -28,7 +28,7 @@ #include "animation.h" #include "action.h" #include "resourcemanager.h" -#include "spriteset.h" +#include "imageset.h" #include "image.h" #include "../utils/xml.h" @@ -135,30 +135,30 @@ SpriteDef::loadImageSet(xmlNodePtr node) std::string imageSrc = XML::getProperty(node, "src", ""); ResourceManager *resman = ResourceManager::getInstance(); - Spriteset *spriteset = resman->getSpriteset(imageSrc, width, height); + ImageSet *imageSet = resman->getImageSet(imageSrc, width, height); - if (!spriteset) + if (!imageSet) { logger->error("Couldn't load imageset!"); } - mSpritesets[name] = spriteset; + mImageSets[name] = imageSet; } void SpriteDef::loadAction(xmlNodePtr node, int variant_offset) { const std::string actionName = XML::getProperty(node, "name", ""); - const std::string imagesetName = XML::getProperty(node, "imageset", ""); + const std::string imageSetName = XML::getProperty(node, "imageset", ""); - SpritesetIterator si = mSpritesets.find(imagesetName); - if (si == mSpritesets.end()) + ImageSetIterator si = mImageSets.find(imageSetName); + if (si == mImageSets.end()) { logger->log("Warning: imageset \"%s\" not defined in %s", - imagesetName.c_str(), getIdPath().c_str()); + imageSetName.c_str(), getIdPath().c_str()); return; } - Spriteset *imageset = si->second; + ImageSet *imageSet = si->second; SpriteAction actionType = makeSpriteAction(actionName); if (actionType == ACTION_INVALID) @@ -183,14 +183,14 @@ SpriteDef::loadAction(xmlNodePtr node, int variant_offset) { if (xmlStrEqual(animationNode->name, BAD_CAST "animation")) { - loadAnimation(animationNode, action, imageset, variant_offset); + loadAnimation(animationNode, action, imageSet, variant_offset); } } } void SpriteDef::loadAnimation(xmlNodePtr animationNode, - Action *action, Spriteset *imageset, + Action *action, ImageSet *imageSet, int variant_offset) { std::string directionName = @@ -215,8 +215,8 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode, int delay = XML::getProperty(frameNode, "delay", 0); int offsetX = XML::getProperty(frameNode, "offsetX", 0); int offsetY = XML::getProperty(frameNode, "offsetY", 0); - offsetY -= imageset->getHeight() - 32; - offsetX -= imageset->getWidth() / 2 - 16; + offsetY -= imageSet->getHeight() - 32; + offsetX -= imageSet->getWidth() / 2 - 16; if (xmlStrEqual(frameNode->name, BAD_CAST "frame")) { @@ -228,7 +228,7 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode, continue; } - Image *img = imageset->get(index + variant_offset); + Image *img = imageSet->get(index + variant_offset); if (!img) { @@ -251,7 +251,7 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode, while (end >= start) { - Image *img = imageset->get(start + variant_offset); + Image *img = imageSet->get(start + variant_offset); if (!img) { @@ -296,8 +296,8 @@ SpriteDef::substituteAction(SpriteAction complete, SpriteAction with) SpriteDef::~SpriteDef() { - for (SpritesetIterator i = mSpritesets.begin(); - i != mSpritesets.end(); ++i) + for (ImageSetIterator i = mImageSets.begin(); + i != mImageSets.end(); ++i) { i->second->decRef(); } diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h index 057129ad..6d335b02 100644 --- a/src/resources/spritedef.h +++ b/src/resources/spritedef.h @@ -32,7 +32,7 @@ #include class Action; -class Spriteset; +class ImageSet; enum SpriteAction { @@ -111,7 +111,7 @@ class SpriteDef : public Resource */ void loadAnimation(xmlNodePtr animationNode, - Action *action, Spriteset *imageset, + Action *action, ImageSet *imageSet, int variant_offset); /** @@ -140,12 +140,12 @@ class SpriteDef : public Resource makeSpriteDirection(const std::string &direction); - typedef std::map Spritesets; - typedef Spritesets::iterator SpritesetIterator; + typedef std::map ImageSets; + typedef ImageSets::iterator ImageSetIterator; typedef std::map Actions; - Spritesets mSpritesets; + ImageSets mImageSets; Actions mActions; Action *mAction; SpriteDirection mDirection; diff --git a/src/resources/spriteset.cpp b/src/resources/spriteset.cpp deleted file mode 100644 index 96bcef0c..00000000 --- a/src/resources/spriteset.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "spriteset.h" - -#include "../log.h" - -#include "image.h" - -#include "../utils/dtor.h" - -Spriteset::Spriteset(const std::string& idPath, - Image *img, - int width, int height): - Resource(idPath) -{ - for (int y = 0; y + height <= img->getHeight(); y += height) - { - for (int x = 0; x + width <= img->getWidth(); x += width) - { - mSpriteset.push_back(img->getSubImage(x, y, width, height)); - } - } - mWidth = width; - mHeight = height; -} - -Spriteset::~Spriteset() -{ - for_each(mSpriteset.begin(), mSpriteset.end(), make_dtor(mSpriteset)); -} - -Image* -Spriteset::get(size_type i) -{ - if (i >= mSpriteset.size()) - { - logger->log("Warning: Sprite #%i does not exist in this spriteset", i); - return NULL; - } - else - { - return mSpriteset[i]; - } -} diff --git a/src/resources/spriteset.h b/src/resources/spriteset.h deleted file mode 100644 index 7f6b42df..00000000 --- a/src/resources/spriteset.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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 - * any later version. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_SPRITESET_H -#define _TMW_SPRITESET_H - -#include - -#include "resource.h" - -class Image; - - -/** - * Stores a set of subimages originating from a single image. - * - * TODO: Should probably be renamed to ImageSet or TileSet. - */ -class Spriteset : public Resource -{ - public: - /* - * Cuts the passed image in a grid of sub images. - */ - Spriteset(const std::string &idPath, Image *img, int w, int h); - - /** - * Destructor. - */ - ~Spriteset(); - - int getWidth() { return mWidth; }; - - int getHeight() { return mHeight; }; - - typedef std::vector::size_type size_type; - Image* get(size_type i); - - size_type size() { return mSpriteset.size(); } - - private: - // Vector storing the whole spriteset. - std::vector mSpriteset; - // Height and width of the images in the spriteset - int mHeight; - int mWidth; -}; - -#endif diff --git a/src/simpleanimation.cpp b/src/simpleanimation.cpp new file mode 100644 index 00000000..5fc35bcd --- /dev/null +++ b/src/simpleanimation.cpp @@ -0,0 +1,50 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include "simpleanimation.h" + + +void SimpleAnimation::update(unsigned int timePassed) +{ + mAnimationTime += timePassed; + while (mAnimationTime > mCurrentFrame->delay) + { + mAnimationTime -= mCurrentFrame->delay; + mAnimationPhase++; + if (mAnimationPhase >= mAnimation->getLength()) + { + mAnimationPhase = 0; + } + mCurrentFrame = mAnimation->getFrame(mAnimationPhase); + } +} + +Image *SimpleAnimation::getCurrentImage() const +{ + return mCurrentFrame->image; +} + +SimpleAnimation::~SimpleAnimation() +{ + delete mAnimation; +} diff --git a/src/simpleanimation.h b/src/simpleanimation.h new file mode 100644 index 00000000..a56c31da --- /dev/null +++ b/src/simpleanimation.h @@ -0,0 +1,65 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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 + * any later version. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_SIMPLEANIMAION_H +#define _TMW_SIMPLEANIMAION_H + +#include "resources/animation.h" + +class Frame; + +/** + * This class is a leightweight alternative to the AnimatedSprite class. + * It hosts a looping animation without actions and directions. + */ +class SimpleAnimation +{ + public: + SimpleAnimation(Animation *animation): + mAnimation(animation), + mAnimationTime(0), + mAnimationPhase(0), + mCurrentFrame(mAnimation->getFrame(0)) + {}; + + ~SimpleAnimation(); + + void update(unsigned int timePassed); + + Image *getCurrentImage() const; + + private: + /** The hosted animation. */ + Animation *mAnimation; + + /** Time in game ticks the current frame is shown. */ + unsigned int mAnimationTime; + + /** Index of current animation frame. */ + unsigned int mAnimationPhase; + + /** Current animation frame. */ + Frame *mCurrentFrame; +}; + +#endif diff --git a/src/tileset.h b/src/tileset.h index 27bc28c3..7521a3e5 100644 --- a/src/tileset.h +++ b/src/tileset.h @@ -24,19 +24,19 @@ #ifndef _TMW_TILESET_H_ #define _TMW_TILESET_H_ -#include "resources/spriteset.h" +#include "resources/imageset.h" /** - * A tileset, which is basically just a spriteset but it stores a firstgid. + * A tileset, which is basically just an image set but it stores a firstgid. */ -class Tileset : public Spriteset +class Tileset : public ImageSet { public: /** * Constructor. */ Tileset(Image *img, int w, int h, int firstGid): - Spriteset("", img, w, h), + ImageSet("", img, w, h), mFirstGid(firstGid) { } diff --git a/src/tmw.rc b/src/tmw.rc index ee5f99cd..673b2387 100644 --- a/src/tmw.rc +++ b/src/tmw.rc @@ -2,7 +2,7 @@ #include "winver.h" -A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "data/icons/tmw-icon.ico" +A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "data/icons/tmw.ico" 1 VERSIONINFO FILEVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD diff --git a/tmw.cbp b/tmw.cbp index 96ef5a36..c66a5719 100644 --- a/tmw.cbp +++ b/tmw.cbp @@ -1262,6 +1262,16 @@ + + + + - -