From 33e19fb0822308a630ca6e1122b9b97882a120a7 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Tue, 25 Jul 2006 19:21:22 +0000 Subject: Fixed Linux compiling issues and merged update system fix for Windows. --- src/gui/updatewindow.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/gui/updatewindow.cpp') diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 8f43903f..3f5fe7bb 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -106,8 +106,7 @@ UpdaterWindow::~UpdaterWindow() free(mMemoryBuffer); } - // Remove downloaded files - remove((mBasePath + "/updates/news.txt").c_str()); + // Remove possibly leftover temporary download remove((mBasePath + "/updates/download.temp").c_str()); delete[] mCurlError; @@ -293,10 +292,14 @@ int UpdaterWindow::downloadThread(void *ptr) if (!uw->mStoreInMemory) { fclose(outfile); - // If the download was successful give the file the proper name - // else it will be deleted later + + // 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()); } } -- cgit v1.2.3-70-g09d2 From aff167beefadc32add4b44626cc2f1cbef800c7b Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 30 Jul 2006 14:33:28 +0000 Subject: Updated TMW to be compatible with Guichan 0.5.0 (merged from guichan-0.5.0 branch). --- ChangeLog | 33 +++++++++++++++++++++ INSTALL | 6 ++-- src/Makefile.am | 4 +-- src/game.cpp | 4 +-- src/gui/box.h | 27 +++++++++-------- src/gui/buddywindow.cpp | 2 +- src/gui/buddywindow.h | 2 +- src/gui/buy.cpp | 2 +- src/gui/buy.h | 2 +- src/gui/buysell.cpp | 2 +- src/gui/buysell.h | 2 +- src/gui/char_select.cpp | 10 +++---- src/gui/char_select.h | 6 ++-- src/gui/chat.cpp | 27 +++++++++-------- src/gui/chat.h | 2 +- src/gui/confirm_dialog.cpp | 4 +-- src/gui/confirm_dialog.h | 2 +- src/gui/connection.cpp | 2 +- src/gui/debugwindow.cpp | 2 +- src/gui/debugwindow.h | 2 +- src/gui/gui.cpp | 10 +++---- src/gui/help.cpp | 2 +- src/gui/help.h | 2 +- src/gui/inventorywindow.cpp | 7 +++-- src/gui/inventorywindow.h | 2 +- src/gui/item_amount.cpp | 2 +- src/gui/item_amount.h | 2 +- src/gui/login.cpp | 4 +-- src/gui/login.h | 4 +-- src/gui/menuwindow.cpp | 8 ++--- src/gui/ministatus.cpp | 2 +- src/gui/newskill.cpp | 2 +- src/gui/newskill.h | 2 +- src/gui/npc_text.cpp | 2 +- src/gui/npc_text.h | 2 +- src/gui/npclistdialog.cpp | 2 +- src/gui/npclistdialog.h | 2 +- src/gui/ok_dialog.cpp | 4 +-- src/gui/ok_dialog.h | 2 +- src/gui/register.cpp | 2 +- src/gui/register.h | 2 +- src/gui/scrollarea.cpp | 37 +++++++++++++----------- src/gui/sell.cpp | 2 +- src/gui/sell.h | 2 +- src/gui/setup.cpp | 2 +- src/gui/setup.h | 2 +- src/gui/setup_audio.cpp | 2 +- src/gui/setup_audio.h | 2 +- src/gui/setup_joystick.cpp | 2 +- src/gui/setup_joystick.h | 2 +- src/gui/setup_video.cpp | 2 +- src/gui/setup_video.h | 2 +- src/gui/skill.cpp | 2 +- src/gui/skill.h | 2 +- src/gui/status.cpp | 2 +- src/gui/status.h | 2 +- src/gui/tabbedcontainer.cpp | 2 +- src/gui/tabbedcontainer.h | 4 +-- src/gui/textfield.cpp | 2 +- src/gui/trade.cpp | 2 +- src/gui/trade.h | 2 +- src/gui/updatewindow.cpp | 6 ++-- src/gui/updatewindow.h | 2 +- src/gui/vbox.cpp | 18 +++++++----- src/gui/window.cpp | 34 ++++++++-------------- src/main.cpp | 8 +++-- src/net/network.cpp | 11 +++++-- src/net/playerhandler.cpp | 4 +-- src/net/tradehandler.cpp | 2 +- src/openglgraphics.cpp | 28 +++++++++--------- src/resources/openglsdlimageloader.cpp | 34 ++++++++++++++++++++++ src/resources/openglsdlimageloader.h | 37 ++++++++++++++++++++++++ src/resources/resourcemanager.cpp | 17 +++++++++++ src/resources/resourcemanager.h | 8 +++++ src/resources/sdlimageloader.cpp | 53 ++-------------------------------- src/resources/sdlimageloader.h | 4 +-- src/sound.cpp | 2 +- 77 files changed, 320 insertions(+), 235 deletions(-) create mode 100644 src/resources/openglsdlimageloader.cpp create mode 100644 src/resources/openglsdlimageloader.h (limited to 'src/gui/updatewindow.cpp') diff --git a/ChangeLog b/ChangeLog index f98cea5c..9105dbe7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2006-07-30 Bjørn Lindeijer + + * src/openglgraphics.cpp, src/game.cpp, src/main.cpp, + src/gui/buddywindow.cpp, src/gui/connection.cpp, src/gui/sell.cpp, + src/gui/trade.cpp, src/gui/char_server.cpp, src/gui/window.cpp, + src/gui/login.cpp, src/gui/skill.h, src/gui/gui.cpp, + src/gui/item_amount.h, src/gui/setup_audio.h, src/gui/newskill.cpp, + src/gui/register.h, src/gui/setup.cpp, src/gui/npclistdialog.h, + src/gui/updatewindow.cpp, src/gui/char_select.cpp, src/gui/login.h, + src/gui/item_amount.cpp, src/gui/setup_audio.cpp, + src/gui/npc_text.cpp, src/gui/chat.h, src/gui/setup_joystick.h, + src/gui/setup_video.cpp, src/gui/ok_dialog.cpp, src/gui/textfield.cpp, + src/gui/inventorywindow.h, src/gui/newskill.h, src/gui/box.h, + src/gui/ministatus.cpp, src/gui/buy.h, src/gui/setup.h, + src/gui/confirm_dialog.cpp, src/gui/debugwindow.cpp, src/gui/vbox.cpp, + src/gui/chat.cpp, src/gui/setup_joystick.cpp, src/gui/updatewindow.h, + src/gui/char_select.h, src/gui/buysell.h, src/gui/tabbedcontainer.cpp, + src/gui/inventorywindow.cpp, src/gui/help.cpp, src/gui/status.h, + src/gui/npc_text.h, src/gui/setup_video.h, src/gui/menuwindow.cpp, + src/gui/ok_dialog.h, src/gui/buy.cpp, src/gui/buddywindow.h, + src/gui/sell.h, src/gui/trade.h, src/gui/char_server.h, + src/gui/skill.cpp, src/gui/buysell.cpp, src/gui/confirm_dialog.h, + src/gui/debugwindow.h, src/gui/status.cpp, src/gui/register.cpp, + src/gui/scrollarea.cpp, src/gui/tabbedcontainer.h, + src/gui/npclistdialog.cpp, src/gui/help.h, src/net/tradehandler.cpp, + src/net/playerhandler.cpp, src/Makefile.am, + src/resources/sdlimageloader.cpp, src/resources/sdlimageloader.h, + src/resources/openglsdlimageloader.cpp, + src/resources/resourcemanager.cpp, + src/resources/openglsdlimageloader.h, src/resources/resourcemanager.h: + Updated TMW to be compatible with Guichan 0.5.0 (merged from + guichan-0.5.0 branch). + 2006-07-27 Eugenio Favalli * src/gui/main.cpp: Modified client version to be an int. diff --git a/INSTALL b/INSTALL index 6cf5b6e5..9779a37a 100644 --- a/INSTALL +++ b/INSTALL @@ -48,11 +48,9 @@ It should have installed The Mana World on your system now, and you can run it with "tmw". By default all files are installed to /usr/local, you can pass a different prefix to configure as usual. - NOTE: For those people with modern video cards and fast OpenGL performance, - we have been working on OpenGL support. At the moment there is no way to - switch between SDL and OpenGL dynamically and you need to do this at compile - time. To try this perform step 3 as follows: + we have been working on OpenGL support. To enable this perform step 3 as + follows: "./configure --with-opengl" diff --git a/src/Makefile.am b/src/Makefile.am index 1bb1d538..42e72829 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,8 +12,6 @@ tmw_SOURCES = graphic/imagerect.h \ gui/buysell.h \ gui/chargedialog.cpp \ gui/chargedialog.h \ - gui/char_server.cpp \ - gui/char_server.h \ gui/char_select.cpp \ gui/char_select.h \ gui/chat.cpp \ @@ -167,6 +165,8 @@ tmw_SOURCES = graphic/imagerect.h \ resources/mapreader.h \ resources/music.h \ resources/music.cpp \ + resources/openglsdlimageloader.h \ + resources/openglsdlimageloader.cpp \ resources/resource.cpp \ resources/resource.h \ resources/resourcemanager.cpp \ diff --git a/src/game.cpp b/src/game.cpp index 51b541a6..fab88aa9 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -122,7 +122,7 @@ const int MAX_TIME = 10000; */ namespace { struct ExitListener : public gcn::ActionListener { - void action(const std::string &eventId) { + void action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "yes") { done = true; } @@ -465,7 +465,7 @@ void Game::handleInput() // Close the config window, cancelling changes if opened else if (setupWindow->isVisible()) { - setupWindow->action("cancel"); + setupWindow->action("cancel", NULL); } // Else, open the chat edit box else diff --git a/src/gui/box.h b/src/gui/box.h index dccbfc78..ed1a7163 100644 --- a/src/gui/box.h +++ b/src/gui/box.h @@ -31,27 +31,30 @@ class Box : public gcn::Container { + public: + /** + * Returns padding. + */ + unsigned int getPadding(); + + /** + * Sets padding between widgets. + */ + void setPadding(unsigned int); + protected: Box(); virtual ~Box(); - /* - * Spacing between client widgets + /** + * Spacing between client widgets. */ unsigned int padding; virtual void draw(gcn::Graphics *) = 0; - public: - /* - * Returns padding - */ - unsigned int getPadding(); - - /* - * Sets padding between widgets - */ - void setPadding(unsigned int); + typedef std::list Widgets; + typedef Widgets::iterator WidgetIterator; }; #endif diff --git a/src/gui/buddywindow.cpp b/src/gui/buddywindow.cpp index 19a2f1e0..145f0ad2 100644 --- a/src/gui/buddywindow.cpp +++ b/src/gui/buddywindow.cpp @@ -61,7 +61,7 @@ BuddyWindow::BuddyWindow(): add(cancel); } -void BuddyWindow::action(const std::string& eventId) +void BuddyWindow::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "Talk") { int selected = mListbox->getSelected(); diff --git a/src/gui/buddywindow.h b/src/gui/buddywindow.h index 6eeb7999..8764d008 100644 --- a/src/gui/buddywindow.h +++ b/src/gui/buddywindow.h @@ -48,7 +48,7 @@ class BuddyWindow : public Window, public gcn::ActionListener /** * Performs action. */ - void action(const std::string &actionId); + void action(const std::string& eventId, gcn::Widget* widget); private: BuddyList *mBuddyList; diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index e96cc04f..e7bfef58 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -148,7 +148,7 @@ void BuyDialog::addItem(short id, int price) mItemList->adjustSize(); } -void BuyDialog::action(const std::string& eventId) +void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) { int selectedItem = mItemList->getSelected(); diff --git a/src/gui/buy.h b/src/gui/buy.h index 0349be4a..b09b648b 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -71,7 +71,7 @@ class BuyDialog : public Window, public gcn::ActionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); /** * Returns the number of items in the shop inventory. diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp index 6e338f08..ac0dcc84 100644 --- a/src/gui/buysell.cpp +++ b/src/gui/buysell.cpp @@ -50,7 +50,7 @@ BuySellDialog::BuySellDialog(): setLocationRelativeTo(getParent()); } -void BuySellDialog::action(const std::string& eventId) +void BuySellDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "Buy") { current_npc->buy(); diff --git a/src/gui/buysell.h b/src/gui/buysell.h index 2d3c7bd3..7a90a869 100644 --- a/src/gui/buysell.h +++ b/src/gui/buysell.h @@ -47,7 +47,7 @@ class BuySellDialog : public Window, public gcn::ActionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); }; #endif diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index e8aa84e0..934988f4 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -48,7 +48,7 @@ class CharDeleteConfirm : public ConfirmDialog { public: CharDeleteConfirm(CharSelectDialog *master); - void action(const std::string &eventId); + void action(const std::string &eventId, gcn::Widget *widget); private: CharSelectDialog *master; }; @@ -60,13 +60,13 @@ CharDeleteConfirm::CharDeleteConfirm(CharSelectDialog *m): { } -void CharDeleteConfirm::action(const std::string &eventId) +void CharDeleteConfirm::action(const std::string &eventId, gcn::Widget *widget) { //ConfirmDialog::action(eventId); if (eventId == "yes") { master->attemptCharDelete(); } - ConfirmDialog::action(eventId); + ConfirmDialog::action(eventId, widget); } CharSelectDialog::CharSelectDialog(Network *network, @@ -126,7 +126,7 @@ CharSelectDialog::CharSelectDialog(Network *network, updatePlayerInfo(); } -void CharSelectDialog::action(const std::string& eventId) +void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "ok" && n_character > 0) { @@ -284,7 +284,7 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network, setLocationRelativeTo(getParent()); } -void CharCreateDialog::action(const std::string& eventId) +void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "create") { if (getName().length() >= 4) { diff --git a/src/gui/char_select.h b/src/gui/char_select.h index 8fc7cd01..20105516 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -29,6 +29,8 @@ #include "../guichanfwd.h" #include "../lockedarray.h" +#include + class LocalPlayer; class Network; class PlayerBox; @@ -49,7 +51,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener LockedArray *charInfo, unsigned char sex); - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); void updatePlayerInfo(); @@ -101,7 +103,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener CharCreateDialog(Window *parent, int slot, Network *network, unsigned char sex); - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); std::string getName(); diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index 870582df..133e5e3a 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -85,18 +85,17 @@ ChatWindow::~ChatWindow() void ChatWindow::logic() { - mChatInput->setPosition( - mChatInput->getBorderSize(), - getContent()->getHeight() - mChatInput->getHeight() - - mChatInput->getBorderSize()); - mChatInput->setWidth( - getContent()->getWidth() - 2 * mChatInput->getBorderSize()); - - mScrollArea->setWidth( - getContent()->getWidth() - 2 * mScrollArea->getBorderSize()); - mScrollArea->setHeight( - getContent()->getHeight() - 2 * mScrollArea->getBorderSize() - - mChatInput->getHeight() - 5); + // todo: only do this when the size changes (updateWidgets?) + + const gcn::Rectangle area = getChildrenArea(); + + mChatInput->setPosition(mChatInput->getBorderSize(), + area.height - mChatInput->getHeight() - + mChatInput->getBorderSize()); + mChatInput->setWidth(area.width - 2 * mChatInput->getBorderSize()); + mScrollArea->setWidth(area.width - 2 * mScrollArea->getBorderSize()); + mScrollArea->setHeight(area.height - 2 * mScrollArea->getBorderSize() - + mChatInput->getHeight() - 5); mScrollArea->logic(); } @@ -189,7 +188,7 @@ ChatWindow::chatLog(CHATSKILL act) } void -ChatWindow::action(const std::string& eventId) +ChatWindow::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "chatinput") { @@ -246,7 +245,7 @@ ChatWindow::requestChatFocus() bool ChatWindow::isFocused() { - return mChatInput->hasFocus(); + return mChatInput->isFocused(); } void diff --git a/src/gui/chat.h b/src/gui/chat.h index 80e57a84..addfb6b5 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -145,7 +145,7 @@ class ChatWindow : public Window, public gcn::ActionListener, /** * Performs action. */ - void action(const std::string &actionId); + void action(const std::string& actionId, gcn::Widget* widget); /** * Request focus for typing chat message. diff --git a/src/gui/confirm_dialog.cpp b/src/gui/confirm_dialog.cpp index 2d574157..ed2f8680 100644 --- a/src/gui/confirm_dialog.cpp +++ b/src/gui/confirm_dialog.cpp @@ -64,13 +64,13 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg, yesButton->requestFocus(); } -void ConfirmDialog::action(const std::string &eventId) +void ConfirmDialog::action(const std::string &eventId, gcn::Widget *widget) { // Proxy button events to our listeners ActionListenerIterator i; for (i = mActionListeners.begin(); i != mActionListeners.end(); ++i) { - (*i)->action(eventId); + (*i)->action(eventId, widget); } // Can we receive anything else anyway? diff --git a/src/gui/confirm_dialog.h b/src/gui/confirm_dialog.h index 3a05494f..1c206b03 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); + void action(const std::string& eventId, gcn::Widget* widget); }; #endif diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp index 4bd619ea..f7fdaca6 100644 --- a/src/gui/connection.cpp +++ b/src/gui/connection.cpp @@ -35,7 +35,7 @@ namespace { struct ConnectionActionListener : public gcn::ActionListener { - void action(const std::string& eventId) { state = EXIT_STATE; } + void action(const std::string &eventId, gcn::Widget *widget) { state = EXIT_STATE; } } listener; } diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index 66681a8b..d467d4d3 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -98,7 +98,7 @@ DebugWindow::logic() } void -DebugWindow::action(const std::string& eventId) +DebugWindow::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "close") { diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h index 80524ffa..61ef44e6 100644 --- a/src/gui/debugwindow.h +++ b/src/gui/debugwindow.h @@ -53,7 +53,7 @@ class DebugWindow : public Window, public gcn::ActionListener /** * Performs action. */ - void action(const std::string &actionId); + void action(const std::string& eventId, gcn::Widget* widget); private: gcn::Label *mMusicFileLabel, *mMapFileLabel; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index cb79e54b..c980389f 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -28,7 +28,7 @@ #include #ifdef USE_OPENGL -#include +#include "../resources/openglsdlimageloader.h" #endif #include @@ -92,16 +92,14 @@ Gui::Gui(Graphics *graphics): { // Set graphics setGraphics(graphics); + + // Set image loader #ifdef USE_OPENGL if (config.getValue("opengl", 0)) { - - // Set image loader - mHostImageLoader = new SDLImageLoader(); - mImageLoader = new gcn::OpenGLImageLoader(mHostImageLoader); + mImageLoader = new OpenGLSDLImageLoader(); } else #endif { - // Set image loader mImageLoader = new SDLImageLoader(); } diff --git a/src/gui/help.cpp b/src/gui/help.cpp index dfb814db..e7429b29 100644 --- a/src/gui/help.cpp +++ b/src/gui/help.cpp @@ -54,7 +54,7 @@ HelpWindow::HelpWindow(): setLocationRelativeTo(getParent()); } -void HelpWindow::action(const std::string& eventId) +void HelpWindow::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "close") { diff --git a/src/gui/help.h b/src/gui/help.h index 44c3d6fc..539ab31b 100644 --- a/src/gui/help.h +++ b/src/gui/help.h @@ -48,7 +48,7 @@ class HelpWindow : public Window, public LinkHandler, /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); /** * Handles link action. diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 8f672bc9..063e8836 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -95,7 +95,7 @@ void InventoryWindow::logic() mWeightLabel->adjustSize(); } -void InventoryWindow::action(const std::string &eventId) +void InventoryWindow::action(const std::string &eventId, gcn::Widget *widget) { Item *item = mItems->getItem(); @@ -168,8 +168,9 @@ void InventoryWindow::mouseMotion(int mx, int my) void InventoryWindow::updateWidgets() { - int width = getContent()->getWidth(); - int height = getContent()->getHeight(); + gcn::Rectangle area = getChildrenArea(); + int width = area.width; + int height = area.height; int columns = width / 24; if (columns < 1) diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h index 179e5314..da7a7ef2 100644 --- a/src/gui/inventorywindow.h +++ b/src/gui/inventorywindow.h @@ -54,7 +54,7 @@ class InventoryWindow : public Window, gcn::ActionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); void mouseClick(int x, int y, int button, int count); diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp index b1b01c3f..30c899a8 100644 --- a/src/gui/item_amount.cpp +++ b/src/gui/item_amount.cpp @@ -94,7 +94,7 @@ void ItemAmountWindow::resetAmount() mItemAmountTextBox->setInt(1); } -void ItemAmountWindow::action(const std::string& eventId) +void ItemAmountWindow::action(const std::string &eventId, gcn::Widget *widget) { int amount = mItemAmountTextBox->getInt(); diff --git a/src/gui/item_amount.h b/src/gui/item_amount.h index ad1e18d6..a2a17575 100644 --- a/src/gui/item_amount.h +++ b/src/gui/item_amount.h @@ -54,7 +54,7 @@ class ItemAmountWindow : public Window, public gcn::ActionListener /** * Called when receiving actions from widget. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); /** * Sets default amount value. diff --git a/src/gui/login.cpp b/src/gui/login.cpp index c0dd9245..2f646bd1 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -43,7 +43,7 @@ WrongDataNoticeListener::setTarget(gcn::TextField *textField) } void -WrongDataNoticeListener::action(const std::string &eventId) +WrongDataNoticeListener::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "ok") { @@ -128,7 +128,7 @@ LoginDialog::~LoginDialog() } void -LoginDialog::action(const std::string& eventId) +LoginDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "ok") { diff --git a/src/gui/login.h b/src/gui/login.h index 39548950..7218dca8 100644 --- a/src/gui/login.h +++ b/src/gui/login.h @@ -38,7 +38,7 @@ class LoginData; class WrongDataNoticeListener : public gcn::ActionListener { public: void setTarget(gcn::TextField *textField); - void action(const std::string &eventId); + void action(const std::string& eventId, gcn::Widget* widget); private: gcn::TextField *mTarget; }; @@ -65,7 +65,7 @@ class LoginDialog : public Window, public gcn::ActionListener { /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); private: gcn::TextField *mUserField; diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp index 503f7ba8..a1b342f0 100644 --- a/src/gui/menuwindow.cpp +++ b/src/gui/menuwindow.cpp @@ -39,7 +39,7 @@ namespace { /** * Called when receiving actions from widget. */ - void action(const std::string& eventId); + void action(const std::string &eventId, gcn::Widget *widget); } listener; } @@ -69,13 +69,13 @@ MenuWindow::MenuWindow(): setDefaultSize((windowContainer->getWidth() - x - 2), 0, x, (y + h)); } -void MenuWindow::draw(gcn::Graphics *g) +void MenuWindow::draw(gcn::Graphics *graphics) { - Window::drawContent(g); + drawChildren(graphics); } -void MenuWindowListener::action(const std::string& eventId) +void MenuWindowListener::action(const std::string &eventId, gcn::Widget *widget) { Window *window = NULL; if (eventId == "Status") diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp index be089b68..53849550 100644 --- a/src/gui/ministatus.cpp +++ b/src/gui/ministatus.cpp @@ -96,5 +96,5 @@ void MiniStatusWindow::update() void MiniStatusWindow::draw(gcn::Graphics *graphics) { update(); - Window::drawContent(graphics); + drawChildren(graphics); } diff --git a/src/gui/newskill.cpp b/src/gui/newskill.cpp index 498186ba..7f5de543 100644 --- a/src/gui/newskill.cpp +++ b/src/gui/newskill.cpp @@ -121,7 +121,7 @@ NewSkillDialog::NewSkillDialog(): setLocationRelativeTo(getParent()); } -void NewSkillDialog::action(const std::string& eventId) +void NewSkillDialog::action(const std::string &eventId, gcn::Widget *widget) { int osp = startPoint; if (eventId == "close") diff --git a/src/gui/newskill.h b/src/gui/newskill.h index 764019f5..224574bd 100644 --- a/src/gui/newskill.h +++ b/src/gui/newskill.h @@ -55,7 +55,7 @@ class NewSkillDialog : public Window, public gcn::ActionListener NewSkillDialog(); // action listener - void action(const std::string&); + void action(const std::string& eventId, gcn::Widget* widget); private: void resetNSD(); // updates the values in the dialog box diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index 1a6bb5ce..5b7ca439 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -67,7 +67,7 @@ NpcTextDialog::addText(const std::string &text) } void -NpcTextDialog::action(const std::string& eventId) +NpcTextDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "ok") { diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h index a1d75aab..3ce1215d 100644 --- a/src/gui/npc_text.h +++ b/src/gui/npc_text.h @@ -49,7 +49,7 @@ class NpcTextDialog : public Window, public gcn::ActionListener * Called when receiving actions from the widgets. */ void - action(const std::string &eventId); + action(const std::string& eventId, gcn::Widget* widget); /** * Sets the text shows in the dialog. diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp index 2d12986d..d1c3ddcb 100644 --- a/src/gui/npclistdialog.cpp +++ b/src/gui/npclistdialog.cpp @@ -91,7 +91,7 @@ NpcListDialog::reset() } void -NpcListDialog::action(const std::string& eventId) +NpcListDialog::action(const std::string &eventId, gcn::Widget *widget) { int choice = 0; diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h index 7d649450..03b76681 100644 --- a/src/gui/npclistdialog.h +++ b/src/gui/npclistdialog.h @@ -54,7 +54,7 @@ class NpcListDialog : public Window, public gcn::ActionListener, * Called when receiving actions from the widgets. */ void - action(const std::string& eventId); + action(const std::string& eventId, gcn::Widget* widget); /** * Returns the number of items in the choices list. diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp index 2f3f21c5..906fd61f 100644 --- a/src/gui/ok_dialog.cpp +++ b/src/gui/ok_dialog.cpp @@ -54,13 +54,13 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg, okButton->requestFocus(); } -void OkDialog::action(const std::string &eventId) +void OkDialog::action(const std::string &eventId, gcn::Widget *widget) { // Proxy button events to our listeners ActionListenerIterator i; for (i = mActionListeners.begin(); i != mActionListeners.end(); ++i) { - (*i)->action(eventId); + (*i)->action(eventId, widget); } // Can we receive anything else anyway? diff --git a/src/gui/ok_dialog.h b/src/gui/ok_dialog.h index eb0da2c0..06f703cc 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); + void action(const std::string& eventId, gcn::Widget* widget); }; #endif diff --git a/src/gui/register.cpp b/src/gui/register.cpp index b99568a8..38136b87 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -116,7 +116,7 @@ RegisterDialog::~RegisterDialog() } void -RegisterDialog::action(const std::string& eventId) +RegisterDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "cancel") { diff --git a/src/gui/register.h b/src/gui/register.h index b46eb1ce..5d3f6cd5 100644 --- a/src/gui/register.h +++ b/src/gui/register.h @@ -56,7 +56,7 @@ class RegisterDialog : public Window, public gcn::ActionListener { /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); // Made them public to have the possibility to request focus // from external functions. diff --git a/src/gui/scrollarea.cpp b/src/gui/scrollarea.cpp index 3703ead8..18a1dfb4 100644 --- a/src/gui/scrollarea.cpp +++ b/src/gui/scrollarea.cpp @@ -55,7 +55,7 @@ ScrollArea::~ScrollArea() { // Garbage collection if (mGC) { - delete mContent; + delete getContent(); } instances--; @@ -144,20 +144,21 @@ void ScrollArea::init() void ScrollArea::logic() { gcn::ScrollArea::logic(); + gcn::Widget *content = getContent(); // When no scrollbar in a certain direction, adapt content size to match // the content dimension exactly. - if (mContent != NULL) + if (content != NULL) { if (getHorizontalScrollPolicy() == gcn::ScrollArea::SHOW_NEVER) { - mContent->setWidth(getContentDimension().width - - 2 * mContent->getBorderSize()); + content->setWidth(getChildrenArea().width - + 2 * content->getBorderSize()); } if (getVerticalScrollPolicy() == gcn::ScrollArea::SHOW_NEVER) { - mContent->setHeight(getContentDimension().height - - 2 * mContent->getBorderSize()); + content->setHeight(getChildrenArea().height - + 2 * content->getBorderSize()); } } } @@ -197,24 +198,26 @@ void ScrollArea::draw(gcn::Graphics *graphics) mScrollbarWidth)); } - if (mContent) + gcn::Widget *content = getContent(); + + if (content != NULL) { - graphics->pushClipArea(getContentDimension()); + graphics->pushClipArea(getChildrenArea()); - if (mContent->getBorderSize() > 0) + if (content->getBorderSize() > 0) { - gcn::Rectangle rec = mContent->getDimension(); - rec.x -= mContent->getBorderSize(); - rec.y -= mContent->getBorderSize(); - rec.width += 2 * mContent->getBorderSize(); - rec.height += 2 * mContent->getBorderSize(); + gcn::Rectangle rec = content->getDimension(); + rec.x -= content->getBorderSize(); + rec.y -= content->getBorderSize(); + rec.width += 2 * content->getBorderSize(); + rec.height += 2 * content->getBorderSize(); graphics->pushClipArea(rec); - mContent->drawBorder(graphics); + content->drawBorder(graphics); graphics->popClipArea(); } - graphics->pushClipArea(mContent->getDimension()); - mContent->draw(graphics); + graphics->pushClipArea(content->getDimension()); + content->draw(graphics); graphics->popClipArea(); graphics->popClipArea(); } diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 0b7abf6f..e820d42f 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -152,7 +152,7 @@ void SellDialog::addItem(Item *item, int price) mItemList->adjustSize(); } -void SellDialog::action(const std::string& eventId) +void SellDialog::action(const std::string &eventId, gcn::Widget *widget) { int selectedItem = mItemList->getSelected(); diff --git a/src/gui/sell.h b/src/gui/sell.h index 59bc58c2..423fea26 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -68,7 +68,7 @@ class SellDialog : public Window, public gcn::ActionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); /** * Mouse callback diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index e0e0e81b..6af9119b 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -85,7 +85,7 @@ Setup::~Setup() for_each(mTabs.begin(), mTabs.end(), make_dtor(mTabs)); } -void Setup::action(const std::string &event) +void Setup::action(const std::string& event, gcn::Widget *widget) { if (event == "Apply") { diff --git a/src/gui/setup.h b/src/gui/setup.h index 611633c5..6601ce3d 100644 --- a/src/gui/setup.h +++ b/src/gui/setup.h @@ -54,7 +54,7 @@ class Setup : public Window, public gcn::ActionListener * Event handling method. */ void - action(const std::string& eventId); + action(const std::string& eventId, gcn::Widget* widget); private: std::list mTabs; diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp index 6f884e2f..db88ff64 100644 --- a/src/gui/setup_audio.cpp +++ b/src/gui/setup_audio.cpp @@ -108,7 +108,7 @@ void Setup_Audio::cancel() config.setValue("musicVolume", mMusicVolume); } -void Setup_Audio::action(const std::string &event) +void Setup_Audio::action(const std::string& event, gcn::Widget *widget) { if (event == "sfx") { diff --git a/src/gui/setup_audio.h b/src/gui/setup_audio.h index 706d6a50..f09f62da 100644 --- a/src/gui/setup_audio.h +++ b/src/gui/setup_audio.h @@ -38,7 +38,7 @@ class Setup_Audio : public SetupTab, public gcn::ActionListener void apply(); void cancel(); - void action(const std::string&); + void action(const std::string& eventId, gcn::Widget* widget); private: int mMusicVolume, mSfxVolume; diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp index fdf50980..36b0ee20 100644 --- a/src/gui/setup_joystick.cpp +++ b/src/gui/setup_joystick.cpp @@ -44,7 +44,7 @@ Setup_Joystick::Setup_Joystick(): add(mCalibrateButton); } -void Setup_Joystick::action(const std::string &event) +void Setup_Joystick::action(const std::string &event, gcn::Widget *widget) { if (!joystick) { return; diff --git a/src/gui/setup_joystick.h b/src/gui/setup_joystick.h index 2abe9678..da773c8f 100644 --- a/src/gui/setup_joystick.h +++ b/src/gui/setup_joystick.h @@ -38,7 +38,7 @@ class Setup_Joystick : public SetupTab, public gcn::ActionListener void apply() {} void cancel() {} - void action(const std::string&); + void action(const std::string& eventId, gcn::Widget* widget); private: gcn::Label *mCalibrateLabel; diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 05543092..9eb94520 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -237,7 +237,7 @@ void Setup_Video::cancel() config.setValue("opengl", mOpenGLEnabled ? 1 : 0); } -void Setup_Video::action(const std::string &event) +void Setup_Video::action(const std::string &event, gcn::Widget *widget) { if (event == "guialpha") { diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h index b021ead4..d0a10925 100644 --- a/src/gui/setup_video.h +++ b/src/gui/setup_video.h @@ -41,7 +41,7 @@ class Setup_Video : public SetupTab, public gcn::ActionListener, void apply(); void cancel(); - void action(const std::string&); + void action(const std::string &eventId, gcn::Widget *widget); /** Called when key is pressed */ void keyPress(const gcn::Key& key); diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 604a19cc..4f552fd7 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -103,7 +103,7 @@ SkillDialog::~SkillDialog() cleanList(); } -void SkillDialog::action(const std::string& eventId) +void SkillDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "inc") { diff --git a/src/gui/skill.h b/src/gui/skill.h index fe80347d..5555fec4 100644 --- a/src/gui/skill.h +++ b/src/gui/skill.h @@ -57,7 +57,7 @@ class SkillDialog : public Window, public gcn::ActionListener, */ ~SkillDialog(); - void action(const std::string&); + void action(const std::string& eventId, gcn::Widget* widget); void update(); diff --git a/src/gui/status.cpp b/src/gui/status.cpp index 7d6cabac..bf109460 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -361,7 +361,7 @@ void StatusWindow::draw(gcn::Graphics *g) Window::draw(g); } -void StatusWindow::action(const std::string& eventId) +void StatusWindow::action(const std::string &eventId, gcn::Widget *widget) { // Stats Part if (eventId.length() == 3) diff --git a/src/gui/status.h b/src/gui/status.h index 52ece323..6b963d24 100644 --- a/src/gui/status.h +++ b/src/gui/status.h @@ -51,7 +51,7 @@ class StatusWindow : public Window, public gcn::ActionListener { /** * Called when receiving actions from widget. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); /** * Draw this window diff --git a/src/gui/tabbedcontainer.cpp b/src/gui/tabbedcontainer.cpp index f1927c6f..e3d2527b 100644 --- a/src/gui/tabbedcontainer.cpp +++ b/src/gui/tabbedcontainer.cpp @@ -78,7 +78,7 @@ void TabbedContainer::logic() Container::logic(); } -void TabbedContainer::action(const std::string &event) +void TabbedContainer::action(const std::string &event, gcn::Widget *widget) { std::stringstream ss(event); int tabNo; diff --git a/src/gui/tabbedcontainer.h b/src/gui/tabbedcontainer.h index 24c8c425..453d8374 100644 --- a/src/gui/tabbedcontainer.h +++ b/src/gui/tabbedcontainer.h @@ -43,7 +43,7 @@ class TabbedContainer : public gcn::Container, public gcn::ActionListener void logic(); - void action(const std::string &event); + void action(const std::string &event, gcn::Widget *widget); void setOpaque(bool opaque); @@ -53,7 +53,7 @@ class TabbedContainer : public gcn::Container, public gcn::ActionListener Widgets mTabs; // The actual tabs at the top Widgets mContents; // The contents of the tabs - Widget *mActiveContent; + gcn::Widget *mActiveContent; }; #endif diff --git a/src/gui/textfield.cpp b/src/gui/textfield.cpp index aa9d04fd..2e083d5a 100644 --- a/src/gui/textfield.cpp +++ b/src/gui/textfield.cpp @@ -82,7 +82,7 @@ TextField::~TextField() void TextField::draw(gcn::Graphics *graphics) { - if (hasFocus()) { + if (isFocused()) { drawCaret(graphics, getFont()->getWidth(mText.substr(0, mCaretPosition)) - mXScroll); diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 4efdb06c..73193c88 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -258,7 +258,7 @@ void TradeWindow::mouseClick(int x, int y, int button, int count) mItemDescriptionLabel->adjustSize(); } -void TradeWindow::action(const std::string &eventId) +void TradeWindow::action(const std::string &eventId, gcn::Widget *widget) { Item *item = inventoryWindow->getItem(); diff --git a/src/gui/trade.h b/src/gui/trade.h index 8bf4b86d..eb3c0f97 100644 --- a/src/gui/trade.h +++ b/src/gui/trade.h @@ -110,7 +110,7 @@ class TradeWindow : public Window, gcn::ActionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); private: Network *mNetwork; diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 3f5fe7bb..9188b6de 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -107,7 +107,7 @@ UpdaterWindow::~UpdaterWindow() } // Remove possibly leftover temporary download - remove((mBasePath + "/updates/download.temp").c_str()); + ::remove((mBasePath + "/updates/download.temp").c_str()); delete[] mCurlError; } @@ -129,7 +129,7 @@ void UpdaterWindow::enable() mPlayButton->requestFocus(); } -void UpdaterWindow::action(const std::string& eventId) +void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "cancel") { @@ -299,7 +299,7 @@ int UpdaterWindow::downloadThread(void *ptr) // Any existing file with this name is deleted first, otherwise the // rename will fail on Windows. - remove(newName.c_str()); + ::remove(newName.c_str()); rename(outFilename.c_str(), newName.c_str()); } } diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index 5f049e18..8a168be8 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -79,7 +79,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener */ void loadNews(); - void action(const std::string& eventId); + void action(const std::string& eventId, gcn::Widget* widget); /** * Add a row to the message field. diff --git a/src/gui/vbox.cpp b/src/gui/vbox.cpp index d79fbba2..eb838ead 100644 --- a/src/gui/vbox.cpp +++ b/src/gui/vbox.cpp @@ -25,17 +25,21 @@ void VBox::draw(gcn::Graphics *graphics) { - int widgetCount = mWidgets.size(); - int childWidth = getWidth(); - if (widgetCount == 0) - return; - int childHeight = getHeight() / widgetCount; + if (mWidgets.size() == 0) + { + return; + } + int childWidth = getWidth(); + int childHeight = getHeight() / mWidgets.size(); int i = 0; - for (WidgetIterator w = mWidgets.begin(); w != mWidgets.end(); w++) { - (*w)->setPosition(0, childHeight * i - padding); + + for (WidgetIterator w = mWidgets.begin(); w != mWidgets.end(); w++) + { + (*w)->setPosition(0, childHeight * i - padding); (*w)->setSize(childWidth, childHeight); i++; } + gcn::Container::draw(graphics); } diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 974a1d73..9a07111f 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -105,7 +105,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent): // Add chrome mChrome = new GCContainer(); mChrome->setOpaque(false); - setContent(mChrome); + gcn::Window::add(mChrome); // Add this window to the window container windowContainer->add(this); @@ -180,7 +180,7 @@ void Window::draw(gcn::Graphics* graphics) graphics->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT); } - drawContent(graphics); + drawChildren(graphics); } void Window::setContentWidth(int width) @@ -195,7 +195,7 @@ void Window::setContentHeight(int height) resizeToContent(); } -void Window::setLocationRelativeTo(gcn::Widget* widget) +void Window::setLocationRelativeTo(gcn::Widget *widget) { int wx, wy; int x, y; @@ -267,7 +267,7 @@ void Window::mousePress(int x, int y, int button) // border, and is a candidate for a resize. if (isResizable() && button == 1 && getGripDimension().isPointInRect(x, y) && - !getContentDimension().isPointInRect(x, y) && + !getChildrenArea().isPointInRect(x, y) && hasMouse() && !(mMouseDrag && y > (int)getPadding())) { @@ -374,11 +374,8 @@ void Window::mouseMotion(int x, int y) // Set the new window and content dimensions setDimension(newDim); - - if (mContent != NULL && mMouseResize) - { - mContent->setDimension(getContentDimension()); - } + const gcn::Rectangle area = getChildrenArea(); + mChrome->setSize(area.width, area.height); } } @@ -406,18 +403,16 @@ Window::loadWindowState() { const std::string &name = mWindowName; - setPosition((int)config.getValue(name + "WinX", getX()), - (int)config.getValue(name + "WinY", getY())); + setPosition((int) config.getValue(name + "WinX", getX()), + (int) config.getValue(name + "WinY", getY())); if (mResizable) { - setWidth((int)config.getValue(name + "WinWidth", getWidth())); - setHeight((int)config.getValue(name + "WinHeight", getHeight())); + setSize((int) config.getValue(name + "WinWidth", getWidth()), + (int) config.getValue(name + "WinHeight", getHeight())); - if (mContent != NULL) - { - mContent->setDimension(getContentDimension()); - } + const gcn::Rectangle area = getChildrenArea(); + mChrome->setSize(area.width, area.height); } } @@ -437,9 +432,4 @@ void Window::resetToDefaultSize() { setPosition(mDefaultX, mDefaultY); setContentSize(mDefaultWidth, mDefaultHeight); - - if (mContent != NULL) - { - mContent->setDimension(getContentDimension()); - } } diff --git a/src/main.cpp b/src/main.cpp index 8cd6eeb6..1bec709f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -100,7 +100,7 @@ Logger *logger; /**< Log object */ namespace { struct ErrorListener : public gcn::ActionListener { - void action(const std::string& eventId) { state = LOGIN_STATE; } + void action(const std::string &eventId, gcn::Widget *widget) { state = LOGIN_STATE; } } errorListener; } @@ -606,7 +606,8 @@ int main(int argc, char *argv[]) oldstate = state; - if (currentDialog && state != ACCOUNT_STATE && state != CHAR_CONNECT_STATE) { + if (currentDialog && state != ACCOUNT_STATE && + state != CHAR_CONNECT_STATE) { delete currentDialog; currentDialog = NULL; } @@ -631,7 +632,8 @@ int main(int argc, char *argv[]) currentDialog = new CharSelectDialog(network, &charInfo, 1 - loginData.sex); if (options.chooseDefault) { - ((CharSelectDialog*)currentDialog)->action("ok"); + ((CharSelectDialog*)currentDialog)->action("ok", + NULL); } break; diff --git a/src/net/network.cpp b/src/net/network.cpp index aa18e888..64cbf331 100644 --- a/src/net/network.cpp +++ b/src/net/network.cpp @@ -66,7 +66,7 @@ bool Network::connect(const std::string &address, short port) mState = CONNECTING; - mClient = enet_host_create (0, 1, 0, 0); + mClient = enet_host_create(0, 1, 0, 0); if (!mClient) { @@ -160,8 +160,10 @@ void Network::dispatchMessages() void Network::flush() { + logger->log("Network::flush()"); if (mState == IDLE || mState == NET_ERROR) { + logger->log("Idle or error, returning"); return; } @@ -173,20 +175,25 @@ void Network::flush() switch (event.type) { case ENET_EVENT_TYPE_CONNECT: + logger->log("Connected."); mState = CONNECTED; // Store any relevant server information here. event.peer->data = 0; break; case ENET_EVENT_TYPE_RECEIVE: + logger->log("Incoming data..."); mIncomingPackets.push(event.packet); break; case ENET_EVENT_TYPE_DISCONNECT: mState = IDLE; - printf("Disconnected\n"); + logger->log("Disconnected."); // Reset the server information. event.peer->data = 0; break; + case ENET_EVENT_TYPE_NONE: + logger->log("No event during 10 milliseconds."); + break; default: logger->log("Unhandled enet event."); break; diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index 5453eae4..c70eada3 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -46,7 +46,7 @@ OkDialog *deathNotice = NULL; namespace { struct WeightListener : public gcn::ActionListener { - void action(const std::string &eventId) { weightNotice = NULL; } + void action(const std::string &eventId, gcn::Widget *widget) { weightNotice = NULL; } } weightListener; } @@ -56,7 +56,7 @@ namespace { // TODO Move somewhere else namespace { struct DeathListener : public gcn::ActionListener { - void action(const std::string &eventId) { + void action(const std::string &eventId, gcn::Widget *widget) { player_node->revive(); deathNotice = NULL; } diff --git a/src/net/tradehandler.cpp b/src/net/tradehandler.cpp index 0f5bdcdc..b0baa5ea 100644 --- a/src/net/tradehandler.cpp +++ b/src/net/tradehandler.cpp @@ -41,7 +41,7 @@ std::string tradePartnerName; namespace { struct RequestTradeListener : public gcn::ActionListener { - void action(const std::string& eventId) + void action(const std::string &eventId, gcn::Widget *widget) { player_node->tradeReply(eventId == "yes"); }; diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index dc14b6c6..2a6c931d 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -31,7 +31,9 @@ #include #endif +#include #include +#include #include "log.h" @@ -227,28 +229,24 @@ void OpenGLGraphics::drawImage(const gcn::Image* image, int dstX, int dstY, int width, int height) { - // The following code finds the real width and height of the texture. - // OpenGL only supports texture sizes that are powers of two - int realImageWidth = 1; - int realImageHeight = 1; - while (realImageWidth < image->getWidth()) - { - realImageWidth *= 2; - } - while (realImageHeight < image->getHeight()) + const gcn::OpenGLImage* srcImage = + dynamic_cast(image); + + if (srcImage == NULL) { - realImageHeight *= 2; + throw GCN_EXCEPTION("Trying to draw an image of unknown format, " + "must be an SDLImage."); } // Find OpenGL texture coordinates - float texX1 = srcX / (float)realImageWidth; - float texY1 = srcY / (float)realImageHeight; - float texX2 = (srcX + width) / (float)realImageWidth; - float texY2 = (srcY + height) / (float)realImageHeight; + float texX1 = srcX / (float)srcImage->getTextureWidth(); + float texY1 = srcY / (float)srcImage->getTextureHeight(); + float texX2 = (srcX + width) / (float)srcImage->getTextureWidth(); + float texY2 = (srcY + height) / (float)srcImage->getTextureHeight(); // Please dont look too closely at the next line, it is not pretty. // It uses the image data as a pointer to a GLuint - glBindTexture(GL_TEXTURE_2D, *((GLuint *)(image->_getData()))); + glBindTexture(GL_TEXTURE_2D, srcImage->getTextureHandle()); drawTexedQuad(dstX, dstY, width, height, texX1, texY1, texX2, texY2); } diff --git a/src/resources/openglsdlimageloader.cpp b/src/resources/openglsdlimageloader.cpp new file mode 100644 index 00000000..f3ddbd84 --- /dev/null +++ b/src/resources/openglsdlimageloader.cpp @@ -0,0 +1,34 @@ +/* + * 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: sdlimageloader.cpp 2121 2006-01-31 02:55:26Z der_doener $ + */ + +#include "openglsdlimageloader.h" + +#include + +#include "resourcemanager.h" + +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 new file mode 100644 index 00000000..29be294c --- /dev/null +++ b/src/resources/openglsdlimageloader.h @@ -0,0 +1,37 @@ +/* + * 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: sdlimageloader.h 1724 2005-09-12 22:15:35Z der_doener $ + */ + +#ifndef _TMW_OPENGLSDLIMAGELOADER_H +#define _TMW_OPENGLSDLIMAGELOADER_H + +#include + +#include + +class OpenGLSDLImageLoader : public gcn::OpenGLSDLImageLoader +{ + protected: + SDL_Surface* loadSDLSurface(const std::string& filename); +}; + +#endif diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 6353afac..23a73497 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "image.h" #include "music.h" @@ -300,3 +301,19 @@ ResourceManager::loadTextFile(const std::string &fileName) free(fileContents); return lines; } + +SDL_Surface* +ResourceManager::loadSDLSurface(const std::string& filename) +{ + int fileSize; + void *buffer = loadFile(filename, fileSize); + SDL_Surface *tmp = NULL; + + if (buffer) { + SDL_RWops *rw = SDL_RWFromMem(buffer, fileSize); + tmp = IMG_Load_RW(rw, 1); + ::free(buffer); + } + + return tmp; +} diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index f254a8b4..0086b167 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -27,6 +27,7 @@ #include #include #include +#include class Resource; class Image; @@ -163,6 +164,13 @@ class ResourceManager std::vector loadTextFile(const std::string &fileName); + /** + * Loads the given filename as an SDL surface. The returned surface is + * expected to be freed by the caller using SDL_FreeSurface. + */ + SDL_Surface* + loadSDLSurface(const std::string& filename); + /** * Returns an instance of the class, creating one if it does not * already exist. diff --git a/src/resources/sdlimageloader.cpp b/src/resources/sdlimageloader.cpp index 88c4143e..ae4f4dcb 100644 --- a/src/resources/sdlimageloader.cpp +++ b/src/resources/sdlimageloader.cpp @@ -24,60 +24,11 @@ #include "sdlimageloader.h" #include -#include - -#include #include "resourcemanager.h" -void SDLImageLoader::prepare(const std::string &filename) +SDL_Surface* SDLImageLoader::loadSDLSurface(const std::string& filename) { - if (mCurrentImage) - { - throw GCN_EXCEPTION("Function called before finalizing or discarding last loaded image."); - } - ResourceManager *resman = ResourceManager::getInstance(); - - int fileSize; - void *buffer = resman->loadFile(filename, fileSize); - - SDL_Surface *tmp = NULL; - if (buffer) { - SDL_RWops *rw = SDL_RWFromMem(buffer, fileSize); - tmp = IMG_Load_RW(rw, 1); - ::free(buffer); - } - - if (!tmp) - { - throw GCN_EXCEPTION(std::string("Unable to load image file: ")+filename); - } - - Uint32 rmask, gmask, bmask, amask; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0xff000000; - gmask = 0x00ff0000; - bmask = 0x0000ff00; - amask = 0x000000ff; -#else - rmask = 0x000000ff; - gmask = 0x0000ff00; - bmask = 0x00ff0000; - amask = 0xff000000; -#endif - - mCurrentImage = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, 32, - rmask, gmask, bmask, amask); - - if (!mCurrentImage) - { - throw GCN_EXCEPTION(std::string("Not enough memory to load: ")+filename); - } - - SDL_Surface* tmp2 = SDL_ConvertSurface(tmp, mCurrentImage->format, SDL_SWSURFACE); - SDL_FreeSurface(tmp); - SDL_FreeSurface(mCurrentImage); - - mCurrentImage = tmp2; + return resman->loadSDLSurface(filename); } diff --git a/src/resources/sdlimageloader.h b/src/resources/sdlimageloader.h index b34b98fe..50b1d4f1 100644 --- a/src/resources/sdlimageloader.h +++ b/src/resources/sdlimageloader.h @@ -30,8 +30,8 @@ class SDLImageLoader : public gcn::SDLImageLoader { - public: - void prepare(const std::string &filename); + protected: + SDL_Surface* loadSDLSurface(const std::string& filename); }; #endif diff --git a/src/sound.cpp b/src/sound.cpp index 8b012176..182be3d6 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -208,6 +208,6 @@ void Sound::close() stopMusic(); mInstalled = false; - Mix_CloseAudio(); logger->log("Sound::close() Shutting down sound..."); + Mix_CloseAudio(); } -- cgit v1.2.3-70-g09d2 From afc770043be553998555e9ac1cffca68dc482d48 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 13 Aug 2006 11:36:36 +0000 Subject: Merged cleanups and content changes from the trunk. Also fixed compiling with OpenGL enabled. --- ChangeLog | 161 ++++++++++++-- src/Makefile.am | 2 + src/animatedsprite.cpp | 382 ++++++++++++++++++++++++++++++++ src/animatedsprite.h | 178 +++++++++++++++ src/animation.cpp | 387 +++------------------------------ src/animation.h | 135 +++--------- src/being.cpp | 169 +++++++------- src/being.h | 11 +- src/configuration.cpp | 56 +++-- src/engine.cpp | 15 +- src/game.cpp | 30 +-- src/gui/browserbox.h | 1 + src/gui/chat.cpp | 81 +++---- src/gui/chat.h | 9 +- src/gui/gui.cpp | 7 +- src/gui/setup_video.cpp | 1 + src/gui/updatewindow.cpp | 2 +- src/main.cpp | 29 +-- src/monster.cpp | 4 +- src/npc.cpp | 2 + src/openglgraphics.cpp | 2 + src/player.cpp | 47 +++- src/resources/image.h | 2 + src/resources/itemmanager.cpp | 4 +- src/resources/mapreader.cpp | 214 +++++++++--------- src/resources/openglsdlimageloader.cpp | 6 +- 26 files changed, 1086 insertions(+), 851 deletions(-) create mode 100644 src/animatedsprite.cpp create mode 100644 src/animatedsprite.h (limited to 'src/gui/updatewindow.cpp') diff --git a/ChangeLog b/ChangeLog index b1731b9f..8bf385c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,82 @@ +2006-08-13 Bjørn Lindeijer + + * src/openglgraphics.cpp, src/gui/browserbox.h, src/gui/gui.cpp, + src/gui/chat.cpp, src/resources/image.h: Added include main.h in order + to have USE_OPENGL defined correctly, since it is no longer passed as + a compiler parameter. + +2006-08-12 Philipp Sehmisch + + * 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: Fixed some + inaccessible areas. + +2006-08-07 Philipp Sehmisch + * 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/graphics/images/minimap_new_9-1.png, + data/graphics/images/minimap_new_14-1.png, + data/graphics/images/minimap_new_15-1.png, + data/graphics/images/minimap_new_16-1.png: Added minimaps for woodland + maps. + +2006-08-07 Philipp Sehmisch + + * data/maps/new_1-1.tmx.gz, data/maps/new_14-1.tmx.gz, + data/maps/new_15-1.tmx.gz, data/maps/new_16-1.tmx.gz: Added a new + woodland map and a connection map between desert and woodland. + * data/graphics/woodland_ground.png: Added some new rocks. + +2006-08-07 Björn Steinbrink + + * src/game.cpp, src/gui/chat.h, src/gui/chat.cpp, src/main.cpp: A + bunch of cleanups. + 2006-08-06 Bjørn Lindeijer * INSTALL: Updated required Guichan to version 0.5.0. +2006-08-05 Björn Steinbrink + + * src/configuration.cpp, src/game.cpp, src/engine.cpp, src/player.cpp, + src/being.cpp, src/resources/mapreader.cpp, + src/resources/itemmanager.cpp: Some cleanups, mostly lowering + indentation. + * src/being.cpp: Small code cleanup. + 2006-08-04 Guillaume Melquiond * src/gui/char_select.cpp: Fixed character gender in selection dialog. +2006-08-04 Björn Steinbrink + + * src/animatedsprite.cpp: Fix enum being treated as string. + * src/animation.cpp: Small code cleanups. Removed unused headers. + * src/animatedsprite.cpp: Small code cleanup/lower indentation. + +2006-08-04 Bjørn Lindeijer + + * src/animatedsprite.cpp: Fixed presence of NULL actions. This is + doener's version of the fix, because it was more efficient in the more + common case. + +2006-08-04 Frode Lindeijer + + * data/graphics/tiles/desert_x3.png: Replaced the old cactus with + a nice new high-res one. + +2006-08-03 Bjørn Lindeijer + + * src/player.cpp, src/being.cpp, src/being.h: Removed three + setDirection(mDirection) calls by instead specifically setting the + current direction on the newly added animated sprite. The same might + be done for the action later. + * src/animatedsprite.h, src/animatedsprite.cpp: Since this class isn't + subclassed and has no virtual functions, make protected members + private. Also added a start of a reset function which could be a + solution to unsynchronized animated sprites. + * src/net/network.cpp: Fixed two delete/delete[] errors. + 2006-08-02 Guillaume Melquiond * configure.ac, src/Makefile.am: Put object files in subdirectories. @@ -37,10 +108,26 @@ * src/gui/gui.cpp, The Mana World.dev, tmw.cbp: Fixed compilation issues in windows. +2006-08-01 Philipp Sehmisch + + * src/animation.h, src/animation.cpp, src/animatedsprite.h, + src/animatedsprite.cpp, src/being.cpp: Animations and directions + are now passed and stored as enums and no longer as strings. + 2006-07-31 Bjørn Lindeijer * src/net/network.cpp: Corrected an off by one error in packet size. +2006-07-30 Björn Steinbrink + + * src/animatedsprite.h, src/animatedsprite.cpp: Unified the play + methods. + +2006-07-30 Philipp Sehmisch + + * data/maps/new_5-1.tmx.gz: Fixed two minor mapping errors (no new + walkmap required). + 2006-07-30 Bjørn Lindeijer * src/openglgraphics.cpp, src/game.cpp, src/main.cpp, @@ -74,6 +161,21 @@ Updated TMW to be compatible with Guichan 0.5.0 (merged from guichan-0.5.0 branch). +2006-07-29 Björn Steinbrink + + * src/animatedsprite.h, src/animatedsprite.cpp, src/animation.cpp: A + bunch of cleanups. + * src/animation.h, src/animatedsprite.cpp: Moved included from header + to source file. + +2006-07-28 Björn Steinbrink + + * src/npc.cpp, src/player.cpp, src/animatedsprite.h, src/animation.h, + src/being.cpp, src/main.cpp, src/monster.cpp, src/animatedsprite.cpp, + src/animation.cpp, src/Makefile.am, src/being.h: Moved AnimatedSprite + into its own files, removed useless includes. + * src/engine.cpp: Removed an unused var. + 2006-07-27 Eugenio Favalli * src/gui/main.cpp: Modified client version to be an int. @@ -81,20 +183,32 @@ 2006-07-26 Eugenio Favalli * src/gui/char_server.cpp, src/gui/char_sever.h, src/main.cpp, - src/net/loginhandler.cpp, src/net/loginhandler.h, tmw,cbp: Removed char - server selection dialog, and added character visualization in character - selection dialog. - -2006-07-25 Bjørn Lindeijer - - * src/gui/updatewindow.cpp: Fixed updating on Windows. - * src/net/beinghandler.cpp, src/net/network.cpp, configure.ac: Fixed - Linux compiling issues. - * src/configuration.cpp: Reduced amount of logging. - * src/log.cpp, src/log.h: Added support for writing log to standard - output. - * src/main.cpp: Reorganized initialization somewhat. - * src/resources/resourcemanager.cpp: Take into account singular form. + src/net/loginhandler.cpp, src/net/loginhandler.h, tmw,cbp: Removed + 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. + * 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, + data/maps/new_9-1.tmx.gz: Added new woodland map by Crush and fixed + connection with the old one. + +2006-07-26 Bjørn Lindeijer + + * data/maps/new_4-1.tmx.gz: Fixes to the collision layer. + +2006-07-26 Frode Lindeijer + + * data/graphics/tiles/snowset.png, data/graphics/tiles/snow_x2.png, + data/graphics/tiles/snow_x3.png: Moved the lamppost, the rock and the + bench to seperate tall tilebitmaps. + * data/maps/new_11-1.tmx.gz: Improved the snow village map, main + changes are that the player can now walk better behind houses, + lampposts, rocks and benches. + * data/graphics/sprites/item003.png, data/graphics/sprites/item003.xml: + Added the leather shirt 2006-07-25 Eugenio Favalli @@ -113,6 +227,17 @@ tmw.cbp: Switched client to use enet and modified login sequence to work with the new protocol from tmwserv. +2006-07-25 Bjørn Lindeijer + + * src/gui/updatewindow.cpp: Fixed updating on Windows. + * src/net/beinghandler.cpp, src/net/network.cpp, configure.ac: Fixed + Linux compiling issues. + * src/configuration.cpp: Reduced amount of logging. + * src/log.cpp, src/log.h: Added support for writing log to standard + output. + * src/main.cpp: Reorganized initialization somewhat. + * src/resources/resourcemanager.cpp: Take into account singular form. + 2006-07-24 Bjørn Lindeijer * src/main.cpp: Fixed the loading of updates and made skipping the @@ -126,10 +251,10 @@ 2006-07-24 Frode Lindeijer * data/graphics/sprites/npcs.png: Added the organdealer to - the NPCs + the NPCs. * data/graphics/sprites/player_male_base.png, data/graphics/sprites/player_female_base.png: Fixed some - transparency issues + transparency issues. 2006-07-24 Eugenio Favalli @@ -144,7 +269,7 @@ * data/help/about.txt, data/help/changes.txt, data/help/commands.txt, data/help/header.txt, data/help/index.txt, data/help/skills.txt, data/help/support.txt, data/help/team.txt: Forced to use UNIX end of - line character. + line character. * src/net/equipmenthandler.cpp: Equipments now use real slot positions. 2006-07-24 Bjørn Lindeijer @@ -230,7 +355,7 @@ 2006-07-17 Frode Lindeijer - * Added shorts to items.png + * data/graphics/sprites/items.png: Added shorts' icon to items.png 2006-07-12 Bjørn Lindeijer diff --git a/src/Makefile.am b/src/Makefile.am index 13ec7308..42671f64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -183,6 +183,8 @@ tmw_SOURCES = graphic/imagerect.h \ resources/buddylist.cpp \ utils/dtor.h \ utils/tostring.h \ + animatedsprite.cpp \ + animatedsprite.h \ animation.cpp \ animation.h \ base64.cpp \ diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp new file mode 100644 index 00000000..d1201042 --- /dev/null +++ b/src/animatedsprite.cpp @@ -0,0 +1,382 @@ +/* + * 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: animation.cpp 2430 2006-07-24 00:13:24Z b_lindeijer $ + */ + +#include "animatedsprite.h" + +#include "animation.h" +#include "graphics.h" +#include "log.h" + +#include "resources/resourcemanager.h" +#include "resources/spriteset.h" + +AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): + mAction(NULL), + mDirection(DIRECTION_DOWN), + mLastTime(0), + mSpeed(1.0f) +{ + 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; + } + + 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 name = 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(), + animationFile.c_str()); + + // skip loading animations + continue; + } + + Action *action = new Action(); + + action->setSpriteset(mSpritesets[imageset]); + mActions[makeSpriteAction(name)] = 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 dir = getProperty(animationNode, "direction", ""); + Animation *animation = new Animation(); + action->setAnimation(makeSpriteDirection(dir), 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++; + } + } + } // for phaseNode + } // for animationNode + } // if "" else if "" + } // for node + + // Complete missing actions + 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); + + // 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) +{ + xmlChar *prop = xmlGetProp(node, BAD_CAST name); + if (prop) { + std::string val = (char*)prop; + xmlFree(prop); + return val; + } + + return def; +} + +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; + } + } +} + +AnimatedSprite::~AnimatedSprite() +{ + for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i) + { + i->second->decRef(); + } + mSpritesets.clear(); +} + +void +AnimatedSprite::reset() +{ + // Reset all defined actions (because of aliases, some will be resetted + // multiple times) + for (ActionIterator i = mActions.begin(); i != mActions.end(); ++i) + { + //TODO: If resetting everything is really a nice way of fixing the + // synchronization issues, finish implementing this. + //i->second->reset(); + } +} + +void +AnimatedSprite::play(SpriteAction action, int time) +{ + ActionIterator i = mActions.find(action); + + if (i == mActions.end()) + { + logger->log("Warning: no action \"%u\" defined!", action); + mAction = NULL; + return; + } + + 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; + } +} + +void +AnimatedSprite::update(int time) +{ + // 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 (time > mLastTime && mAction) + { + Animation *animation = mAction->getAnimation(mDirection); + animation->update((unsigned int)((time - mLastTime) * mSpeed)); + mLastTime = time; + } +} + +bool +AnimatedSprite::draw(Graphics* graphics, Sint32 posX, Sint32 posY) const +{ + if (!mAction) + return false; + + Animation *animation = mAction->getAnimation(mDirection); + int phase = animation->getCurrentPhase(); + if (phase < 0) + return false; + + 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); +} + +int +AnimatedSprite::getWidth() const +{ + return mAction ? mAction->getSpriteset()->getWidth() : 0; +} + +int +AnimatedSprite::getHeight() const +{ + return mAction ? mAction->getSpriteset()->getHeight() : 0; +} + +SpriteAction +AnimatedSprite::makeSpriteAction(const std::string& action) +{ + 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_DEFAULT; + } +} + +SpriteDirection +AnimatedSprite::makeSpriteDirection(const std::string& direction) +{ + if (direction == "up") { + return DIRECTION_UP; + } + else if (direction == "left") { + return DIRECTION_LEFT; + } + else if (direction == "right") { + return DIRECTION_RIGHT; + } + else { + return DIRECTION_DOWN; + } +} diff --git a/src/animatedsprite.h b/src/animatedsprite.h new file mode 100644 index 00000000..89394d6c --- /dev/null +++ b/src/animatedsprite.h @@ -0,0 +1,178 @@ +/* + * 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: animation.h 2430 2006-07-24 00:13:24Z b_lindeijer $ + */ + +#ifndef _TMW_ANIMATEDSPRITE_H +#define _TMW_ANIMATEDSPRITE_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 +}; + +enum SpriteDirection +{ + DIRECTION_DOWN = 0, + DIRECTION_UP, + DIRECTION_LEFT, + DIRECTION_RIGHT +}; + +/** + * Defines a class to load an animation. + */ +class AnimatedSprite +{ + public: + /** + * Constructor. + */ + AnimatedSprite(const std::string& animationFile, int variant); + + /** + * Destructor. + */ + ~AnimatedSprite(); + + /** + * Resets the animated sprite. This is used to synchronize several + * animated sprites. + */ + void + reset(); + + /** + * Plays an action using the current direction that will have a + * duration of the specified time, 0 means default. + */ + void + play(SpriteAction action, int time = 0); + + /** + * Inform the animation of the passed time so that it can output the + * correct animation phase. + */ + 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; + + /** + * Sets the direction. + */ + void + setDirection(SpriteDirection direction) + { + mDirection = 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); + + + typedef std::map Spritesets; + typedef Spritesets::iterator SpritesetIterator; + + typedef std::map Actions; + typedef Actions::iterator ActionIterator; + + Spritesets mSpritesets; + Actions mActions; + Action *mAction; + SpriteDirection mDirection; + int mLastTime; + float mSpeed; +}; + +#endif diff --git a/src/animation.cpp b/src/animation.cpp index 313fd25c..1213d0d6 100644 --- a/src/animation.cpp +++ b/src/animation.cpp @@ -23,13 +23,9 @@ #include "animation.h" -#include +#include -#include "log.h" - -#include "resources/image.h" -#include "resources/resourcemanager.h" -#include "resources/spriteset.h" +#include "utils/dtor.h" Animation::Animation(): mTime(0) @@ -41,17 +37,20 @@ void Animation::update(unsigned int time) { mTime += time; - if (!mAnimationPhases.empty()) + if (mAnimationPhases.empty()) + return; + + unsigned int delay = iCurrentPhase->delay; + if (!delay) + return; + + while (mTime > delay) { - unsigned int delay = iCurrentPhase->delay; - while (mTime > delay && delay > 0) + mTime -= delay; + iCurrentPhase++; + if (iCurrentPhase == mAnimationPhases.end()) { - mTime -= delay; - iCurrentPhase++; - if (iCurrentPhase == mAnimationPhases.end()) - { - iCurrentPhase = mAnimationPhases.begin(); - } + iCurrentPhase = mAnimationPhases.begin(); } } } @@ -59,25 +58,15 @@ Animation::update(unsigned int time) int Animation::getCurrentPhase() const { - if (mAnimationPhases.empty()) - { - return -1; - } - else - { - return iCurrentPhase->image; - } + 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; - newPhase.image = image; - newPhase.delay = delay; - newPhase.offsetX = offsetX; - newPhase.offsetY = offsetY; + AnimationPhase newPhase = { image, delay, offsetX, offsetY }; + mAnimationPhases.push_back(newPhase); //reset animation circle iCurrentPhase = mAnimationPhases.begin(); @@ -86,14 +75,14 @@ Animation::addPhase(int image, unsigned int delay, int offsetX, int offsetY) int Animation::getLength() { + if (mAnimationPhases.empty()) + return 0; + std::list::iterator i; int length = 0; - if (!mAnimationPhases.empty()) + for (i = mAnimationPhases.begin(); i != mAnimationPhases.end(); i++) { - for (i = mAnimationPhases.begin(); i != mAnimationPhases.end(); i++) - { - length += (*i).delay; - } + length += i->delay; } return length; } @@ -105,352 +94,32 @@ Action::Action(): Action::~Action() { - for (AnimationIterator i = mAnimations.begin(); i != mAnimations.end(); i++) - { - delete i->second; - } + std::for_each(mAnimations.begin(), mAnimations.end(), make_dtor(mAnimations)); mAnimations.clear(); } Animation* -Action::getAnimation(const std::string& direction) const +Action::getAnimation(int direction) const { - Animation *animation = NULL; Animations::const_iterator i = mAnimations.find(direction); // When the direction isn't defined, try the default if (i == mAnimations.end()) { - i = mAnimations.find("default"); + i = mAnimations.find(0); } - if (i != mAnimations.end()) - { - animation = i->second; - } - - return animation; + return (i == mAnimations.end()) ? NULL : i->second; } void -Action::setAnimation(const std::string& direction, Animation *animation) +Action::setAnimation(int direction, Animation *animation) { // Set first direction as default direction if (mAnimations.empty()) { - mAnimations["default"] = animation; + mAnimations[0] = animation; } mAnimations[direction] = animation; } - - -AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): - mAction(NULL), - mDirection("down"), - mLastTime(0), - mSpeed(1.0f) -{ - 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!"); - return; - } - - xmlNodePtr node = xmlDocGetRootElement(doc); - if (!node || !xmlStrEqual(node->name, BAD_CAST "sprite")) - { - logger->error("Animation: this is not a valid animation definition file!"); - return; - } - - // 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; - } - - 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!"); - } - else - { - mSpritesets[name] = spriteset; - } - } - // get action - else if (xmlStrEqual(node->name, BAD_CAST "action")) - { - std::string name = getProperty(node, "name", ""); - std::string imageset = getProperty(node, "imageset", ""); - - if (name.length() == 0) - { - logger->log("Warning: unnamed action in %s", - animationFile.c_str()); - } - - Action *action = new Action(); - - if (mSpritesets.find(imageset) != mSpritesets.end()) - { - action->setSpriteset(mSpritesets[imageset]); - mActions[name] = action; - } - else - { - logger->log("Warning: imageset \"%s\" not defined in %s", - imageset.c_str(), - animationFile.c_str()); - - // Discard action and skip loading animations - delete action; - continue; - } - - // get animations - for (xmlNodePtr animationNode = node->xmlChildrenNode; - animationNode != NULL; - animationNode = animationNode->next) - { - if (xmlStrEqual(animationNode->name, BAD_CAST "animation")) - { - std::string direction = - getProperty(animationNode, "direction", ""); - - Animation *animation = new 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 = offsetY - mSpritesets[imageset]->getHeight() + 32; - offsetX = 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 = 0 - mSpritesets[imageset]->getHeight() + 32; - int offsetX = 0 - mSpritesets[imageset]->getWidth() / 2 + 16; - while (end >= start) - { - animation->addPhase(start + variant_offset, - delay, offsetX, offsetY); - start++; - } - } - } // for phaseNode - action->setAnimation(direction, animation); - } // if "" - } // for animationNode - } // if "" else if "" - } // for node - - // Complete missing actions - substituteAction("walk", "stand"); - substituteAction("walk", "run"); - substituteAction("attack", "stand"); - substituteAction("attack_swing", "attack"); - substituteAction("attack_stab", "attack_swing"); - substituteAction("attack_bow", "attack_stab"); - substituteAction("attack_throw", "attack_swing"); - substituteAction("cast_magic", "attack_swing"); - substituteAction("use_item", "cast_magic"); - substituteAction("sit", "stand"); - substituteAction("sleeping", "sit"); - substituteAction("hurt", "stand"); - substituteAction("dead", "hurt"); - - // Play the stand animation by default - play("stand"); - - xmlFreeDoc(doc); -} - -int -AnimatedSprite::getProperty(xmlNodePtr node, const char* name, int def) -{ - xmlChar *prop = xmlGetProp(node, BAD_CAST name); - if (prop) { - int val = atoi((char*)prop); - xmlFree(prop); - return val; - } - else { - return def; - } -} - -std::string -AnimatedSprite::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; - } - else { - return def; - } -} - -void -AnimatedSprite::substituteAction(const std::string& complete, - const std::string& with) -{ - if (mActions.find(complete) == mActions.end()) - { - mActions[complete] = mActions[with]; - } -} - -AnimatedSprite::~AnimatedSprite() -{ - for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i) - { - i->second->decRef(); - } - mSpritesets.clear(); -} - -void -AnimatedSprite::play(const std::string& action) -{ - Actions::iterator iAction; - iAction = mActions.find(action); - - if (iAction == mActions.end()) - { - logger->log("Warning: no action \"%s\" defined!", action.c_str()); - mAction = NULL; - return; - } - - if (mAction != iAction->second) - { - mAction = iAction->second; - mLastTime = 0; - } - - mSpeed = 1.0f; -} - -void -AnimatedSprite::play(const std::string& action, int time) -{ - play(action); - - if (mAction != NULL) - { - Animation *animation = mAction->getAnimation(mDirection); - int animationLength = animation->getLength(); - mSpeed = (float) animationLength / time; - } -} - -void -AnimatedSprite::update(int time) -{ - // 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 (time > mLastTime) - { - if (mAction != NULL) - { - Animation *animation = mAction->getAnimation(mDirection); - animation->update((unsigned int)((time - mLastTime) * mSpeed)); - mLastTime = time; - } - } -} - -bool -AnimatedSprite::draw(Graphics* graphics, Sint32 posX, Sint32 posY) const -{ - if (mAction != NULL) - { - Animation *animation = mAction->getAnimation(mDirection); - - if (animation->getCurrentPhase() >= 0) - { - Spriteset *spriteset = mAction->getSpriteset(); - Image *image = spriteset->get(animation->getCurrentPhase()); - Sint32 offsetX = animation->getOffsetX(); - Sint32 offsetY = animation->getOffsetY(); - return graphics->drawImage(image, posX + offsetX, posY + offsetY); - } - } - - return false; -} - -int -AnimatedSprite::getWidth() const -{ - if (mAction != NULL) - { - Spriteset *spriteset = mAction->getSpriteset(); - return spriteset->getWidth(); - } - - return 0; -} - -int -AnimatedSprite::getHeight() const -{ - if (mAction != NULL) - { - Spriteset *spriteset = mAction->getSpriteset(); - return spriteset->getHeight(); - } - - return 0; -} diff --git a/src/animation.h b/src/animation.h index c5adb873..c5b277b7 100644 --- a/src/animation.h +++ b/src/animation.h @@ -26,12 +26,9 @@ #include #include -#include #include -#include "graphics.h" - class Image; class Spriteset; @@ -58,16 +55,32 @@ class Animation */ Animation(); - void addPhase(int image, unsigned int delay, int offsetX, int offsetY); + void + addPhase(int image, unsigned int delay, int offsetX, int offsetY); + + void + update(unsigned int time); - void update(unsigned int time); + int + getCurrentPhase() const; - int getCurrentPhase() const; + /** + * Returns the x offset of the current frame. + */ + int + getOffsetX() const { return (*iCurrentPhase).offsetX; }; - int getOffsetX() const { return (*iCurrentPhase).offsetX; }; - int getOffsetY() const { return (*iCurrentPhase).offsetY; }; + /** + * Returns the y offset of the current frame. + */ + int + getOffsetY() const { return (*iCurrentPhase).offsetY; }; - int getLength(); + /** + * Returns the length of this animation. + */ + int + getLength(); protected: std::list mAnimationPhases; @@ -104,114 +117,16 @@ class Action getSpriteset() const { return mSpriteset; } void - setAnimation(const std::string& direction, Animation *animation); + setAnimation(int direction, Animation *animation); Animation* - getAnimation(const std::string& direction) const; + getAnimation(int direction) const; protected: Spriteset *mSpriteset; - typedef std::map Animations; + typedef std::map Animations; typedef Animations::iterator AnimationIterator; Animations mAnimations; }; -/** - * Defines a class to load an animation. - */ -class AnimatedSprite -{ - public: - /** - * Constructor. - */ - AnimatedSprite(const std::string& animationFile, int variant); - - /** - * Destructor. - */ - ~AnimatedSprite(); - - /** - * Sets a new action using the current direction. - */ - void - play(const std::string& action); - - /** - * Plays an action in a specified time. - */ - void - play(const std::string& action, int time); - - /** - * Inform the animation of the passed time so that it can output the - * correct animation phase. - */ - 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; - - /** - * Sets the direction. - */ - void - setDirection(const std::string& direction) - { - mDirection = direction; - } - - protected: - /** - * When there are no animations defined for the action "complete", its - * animations become a copy of those of the action "with". - */ - void - substituteAction(const std::string& complete, - const std::string& with); - - typedef std::map Spritesets; - typedef Spritesets::iterator SpritesetIterator; - Spritesets mSpritesets; - typedef std::map Actions; - Actions mActions; - Action *mAction; - std::string mDirection; - int mLastTime; - float mSpeed; - - private: - /** - * 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); -}; - #endif diff --git a/src/being.cpp b/src/being.cpp index 8a55f2e2..1ca8929a 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -22,6 +22,9 @@ */ #include "being.h" +#include + +#include "animatedsprite.h" #include "equipment.h" #include "game.h" #include "graphics.h" @@ -32,6 +35,7 @@ #include "gui/gui.h" +#include "utils/dtor.h" #include "utils/tostring.h" extern Spriteset *emotionset; @@ -65,14 +69,7 @@ Being::Being(Uint32 id, Uint16 job, Map *map): Being::~Being() { - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i] != NULL) - { - delete mSprites[i]; - } - } - + std::for_each(mSprites.begin(), mSprites.end(), make_dtor(mSprites)); clearPath(); setMap(NULL); } @@ -164,66 +161,65 @@ Being::setMap(Map *map) } void -Being::setAction(Action action) +Being::setAction(Uint8 action) { - if (action != mAction) + SpriteAction currentAction = ACTION_STAND; + switch (action) { - std::string currentAction = "stand"; - switch (action) - { - case WALK: - currentAction = "walk"; - break; - case SIT: - currentAction = "sit"; - break; - case ATTACK: - if (getType() == MONSTER) - { - currentAction = "dead"; - }else{ - switch (getWeapon()) - { - case 2: - currentAction = "attack_bow"; - break; - case 1: - currentAction = "attack_stab"; - break; - case 0: - currentAction = "attack"; - break; - } - }; - break; - case MONSTER_ATTACK: - currentAction = "attack"; - break; - case DEAD: - currentAction = "dead"; - break; - default: - currentAction = "stand"; - break; - } - - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i] != NULL) + case WALK: + currentAction = ACTION_WALK; + break; + case SIT: + currentAction = ACTION_SIT; + break; + case ATTACK: + if (getType() == MONSTER) { - if (currentAction == "attack" || - currentAction == "attack_stab" || - currentAction == "attack_bow") - { - mSprites[i]->play(currentAction, mAttackSpeed); - } - else + currentAction = ACTION_DEAD; + } + else { + switch (getWeapon()) { - mSprites[i]->play(currentAction); + case 2: + currentAction = ACTION_ATTACK_BOW; + break; + case 1: + currentAction = ACTION_ATTACK_STAB; + break; + case 0: + currentAction = ACTION_ATTACK; + break; } - } + }; + break; + case MONSTER_ATTACK: + currentAction = ACTION_ATTACK; + break; + case DEAD: + currentAction = ACTION_DEAD; + break; + default: + currentAction = ACTION_STAND; + break; + } + + 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 + { + mSprites[i]->play(currentAction); } } + mAction = action; } @@ -231,29 +227,37 @@ void Being::setDirection(Uint8 direction) { mDirection = direction; - std::string dir; + SpriteDirection dir = getSpriteDirection(); - if (direction & UP) + for (int i = 0; i < VECTOREND_SPRITE; i++) { - dir = "up"; + if (mSprites[i] != NULL) + mSprites[i]->setDirection(dir); } - else if (direction & RIGHT) +} + +SpriteDirection +Being::getSpriteDirection() const +{ + SpriteDirection dir; + + if (mDirection & UP) { - dir = "right"; + dir = DIRECTION_UP; } - else if (direction & DOWN) + else if (mDirection & RIGHT) { - dir = "down"; + dir = DIRECTION_RIGHT; } - else + else if (mDirection & DOWN) { - dir = "left"; + dir = DIRECTION_DOWN; } - - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i] != NULL) mSprites[i]->setDirection(dir); + else { + dir = DIRECTION_LEFT; } + + return dir; } void @@ -329,10 +333,6 @@ Being::draw(Graphics *graphics, int offsetX, int offsetY) int px = mPx + offsetX; int py = mPy + offsetY; - //what are these two lines good for? please add a comment. - unsigned char dir = 0; - while (!(mDirection & (1 << dir))) dir++; - for (int i = 0; i < VECTOREND_SPRITE; i++) { if (mSprites[i] != NULL) @@ -345,14 +345,13 @@ Being::draw(Graphics *graphics, int offsetX, int offsetY) void Being::drawEmotion(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) { - int px = mPx + offsetX; - int py = mPy + offsetY; + if (!mEmotion) + return; - if (mEmotion) - { - graphics->drawImage(emotionset->get(mEmotion - 1), - px + 3, py - 60); - } + int px = mPx + offsetX + 3; + int py = mPy + offsetY - 60; + + graphics->drawImage(emotionset->get(mEmotion - 1), px, py); } void diff --git a/src/being.h b/src/being.h index 478bc018..0735efe9 100644 --- a/src/being.h +++ b/src/being.h @@ -29,13 +29,14 @@ #include #include -#include "animation.h" #include "sprite.h" #include "map.h" +#include "animatedsprite.h" #define NR_HAIR_STYLES 7 #define NR_HAIR_COLORS 10 +class AnimatedSprite; class Equipment; class Item; class Map; @@ -290,7 +291,7 @@ class Being : public Sprite /** * Sets the current action. */ - void setAction(Action action); + void setAction(Uint8 action); /** * Sets the current direction. @@ -347,6 +348,12 @@ class Being : public Sprite */ int getOffset(char pos, char neg) const; + /** + * Returns the sprite direction of this being. + */ + SpriteDirection + getSpriteDirection() const; + Uint32 mId; /**< Unique sprite id */ Uint16 mWeapon; /**< Weapon picture id */ Uint16 mWalkSpeed; /**< Walking speed */ diff --git a/src/configuration.cpp b/src/configuration.cpp index 9c3ff008..8bb0b8ca 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -57,18 +57,18 @@ void Configuration::init(const std::string &filename) for (node = node->xmlChildrenNode; node != NULL; node = node->next) { - if (xmlStrEqual(node->name, BAD_CAST "option")) - { - xmlChar *name = xmlGetProp(node, BAD_CAST "name"); - xmlChar *value = xmlGetProp(node, BAD_CAST "value"); + if (!xmlStrEqual(node->name, BAD_CAST "option")) + continue; - if (name && value) { - mOptions[(const char*)name] = (const char*)value; - } + xmlChar *name = xmlGetProp(node, BAD_CAST "name"); + xmlChar *value = xmlGetProp(node, BAD_CAST "value"); - if (name) xmlFree(name); - if (value) xmlFree(value); + if (name && value) { + mOptions[(const char*)name] = (const char*)value; } + + if (name) xmlFree(name); + if (value) xmlFree(value); } xmlFreeDoc(doc); @@ -89,31 +89,29 @@ void Configuration::write() xmlTextWriterPtr writer = xmlNewTextWriterFilename(mConfigPath.c_str(), 0); - if (writer) - { - logger->log("Configuration::write() writing configuration..."); + if (!writer) { + logger->log("Configuration::write() error while creating writer"); + return; + } - xmlTextWriterSetIndent(writer, 1); - xmlTextWriterStartDocument(writer, NULL, NULL, NULL); - xmlTextWriterStartElement(writer, BAD_CAST "configuration"); + logger->log("Configuration::write() writing configuration..."); - for (OptionIterator i = mOptions.begin(); i != mOptions.end(); i++) - { - xmlTextWriterStartElement(writer, BAD_CAST "option"); - xmlTextWriterWriteAttribute(writer, - BAD_CAST "name", BAD_CAST i->first.c_str()); - xmlTextWriterWriteAttribute(writer, - BAD_CAST "value", BAD_CAST i->second.c_str()); - xmlTextWriterEndElement(writer); - } + xmlTextWriterSetIndent(writer, 1); + xmlTextWriterStartDocument(writer, NULL, NULL, NULL); + xmlTextWriterStartElement(writer, BAD_CAST "configuration"); - xmlTextWriterEndDocument(writer); - xmlFreeTextWriter(writer); - } - else + for (OptionIterator i = mOptions.begin(); i != mOptions.end(); i++) { - logger->log("Configuration::write() error while creating writer"); + xmlTextWriterStartElement(writer, BAD_CAST "option"); + xmlTextWriterWriteAttribute(writer, + BAD_CAST "name", BAD_CAST i->first.c_str()); + xmlTextWriterWriteAttribute(writer, + BAD_CAST "value", BAD_CAST i->second.c_str()); + xmlTextWriterEndElement(writer); } + + xmlTextWriterEndDocument(writer); + xmlFreeTextWriter(writer); } void Configuration::setValue(const std::string &key, std::string value) diff --git a/src/engine.cpp b/src/engine.cpp index c6a4e55c..84574b26 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -25,7 +25,6 @@ #include -#include "animation.h" #include "being.h" #include "beingmanager.h" #include "flooritemmanager.h" @@ -34,7 +33,6 @@ #include "main.h" #include "localplayer.h" #include "log.h" -#include "main.h" #include "map.h" #include "sound.h" @@ -63,8 +61,6 @@ Spriteset *itemset; Spriteset *emotionset; Spriteset *npcset; std::vector weaponset; -AnimatedSprite *animatedSprite; - Engine::Engine(Network *network): mShowDebugPath(false), @@ -104,16 +100,11 @@ Engine::~Engine() emotionset->decRef(); itemset->decRef(); - std::vector::iterator iter; - for (iter = weaponset.begin(); iter != weaponset.end(); ++iter) - { - (*iter)->decRef(); - } + std::for_each(weaponset.begin(), weaponset.end(), + std::mem_fun(&Spriteset::decRef)); weaponset.clear(); delete itemDb; - - delete animatedSprite; } void Engine::changeMap(const std::string &mapPath) @@ -219,12 +210,12 @@ void Engine::draw(Graphics *graphics) player_node->mX, player_node->mY, mouseTileX, mouseTileY); + graphics->setColor(gcn::Color(255, 0, 0)); for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++) { int squareX = i->x * 32 - map_x + 12; int squareY = i->y * 32 - map_y + 12; - graphics->setColor(gcn::Color(255, 0, 0)); graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8)); graphics->drawText( toString(mCurrentMap->getMetaTile(i->x, i->y)->Gcost), diff --git a/src/game.cpp b/src/game.cpp index fab88aa9..eada1128 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -167,8 +167,7 @@ int get_elapsed_time(int start_time) void createGuiWindows(Network *network) { // Create dialogs - chatWindow = new ChatWindow( - config.getValue("homeDir", "") + std::string("/chatlog.txt"), network); + chatWindow = new ChatWindow(network); menuWindow = new MenuWindow(); statusWindow = new StatusWindow(player_node); miniStatusWindow = new MiniStatusWindow(); @@ -359,29 +358,16 @@ void Game::logic() gameTime = tick_time; fpsLimit = (int)config.getValue("fpslimit", 50); - if (fpsLimit) - { - delta = 1000 / fpsLimit; - } - else - { - delta = 0; - } + delta = fpsLimit ? 1000 / fpsLimit : 0; // Update the screen when application is active, delay otherwise - if (SDL_GetAppState() & SDL_APPACTIVE) + if (SDL_GetAppState() & SDL_APPACTIVE && + (abs(tick_time * 10 - drawTime) >= delta)) { - if (abs(tick_time * 10 - drawTime) >= delta) - { - frame++; - engine->draw(graphics); - graphics->updateScreen(); - drawTime += delta; - } - else - { - SDL_Delay(10); - } + frame++; + engine->draw(graphics); + graphics->updateScreen(); + drawTime += delta; } else { diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h index 95b181ad..a2c9dd9b 100644 --- a/src/gui/browserbox.h +++ b/src/gui/browserbox.h @@ -31,6 +31,7 @@ #include #include "../guichanfwd.h" +#include "../main.h" class LinkHandler; diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index 133e5e3a..592439fc 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -35,18 +35,16 @@ #include "../game.h" #include "../localplayer.h" -#include "../log.h" #include "../net/messageout.h" #include "../net/protocol.h" -ChatWindow::ChatWindow(const std::string &logfile, Network *network): +ChatWindow::ChatWindow(Network *network): Window(""), mNetwork(network), mTmpVisible(false) { setWindowName("Chat"); - mChatlogFile.open(logfile.c_str(), std::ios::out | std::ios::app); mItems = 0; mItemsKeep = 20; @@ -76,12 +74,6 @@ ChatWindow::ChatWindow(const std::string &logfile, Network *network): mCurHist = mHistory.end(); } -ChatWindow::~ChatWindow() -{ - mChatlogFile.flush(); - mChatlogFile.close(); -} - void ChatWindow::logic() { @@ -251,44 +243,12 @@ ChatWindow::isFocused() void ChatWindow::chatSend(const std::string &nick, std::string msg) { - // Prepare command - if (msg.substr(0, 1) == "/") - { - /* Some messages are managed client side, while others - * require server handling by proper packet. Probably - * those if elses should be replaced by protocol calls */ - if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE) - { - msg.erase(0, IS_ANNOUNCE_LENGTH); - MessageOut outMsg; - outMsg.writeShort(0x0099); - outMsg.writeShort(msg.length() + 4); - outMsg.writeString(msg, msg.length()); - } - else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP) - { - chatLog("-- Help --", BY_SERVER); - chatLog("/help : Display this help.", BY_SERVER); - chatLog("/announce : Global announcement (GM only)", BY_SERVER); - chatLog("/where : Display map name", BY_SERVER); - chatLog("/who : Display number of online users", BY_SERVER); - } - else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE) - { - chatLog(map_path, BY_SERVER); - } - else if (msg.substr(0, IS_WHO_LENGTH) == IS_WHO) - { - MessageOut outMsg; - outMsg.writeShort(0x00c1); - } - else - { - chatLog("Unknown command", BY_SERVER); - } - } + /* Some messages are managed client side, while others + * require server handling by proper packet. Probably + * those if elses should be replaced by protocol calls */ + // Prepare ordinary message - else { + if (msg.substr(0, 1) != "/") { msg = nick + " : " + msg; MessageOut outMsg; @@ -296,6 +256,35 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) outMsg.writeShort(msg.length() + 4); outMsg.writeString(msg, msg.length()); } + else if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE) + { + msg.erase(0, IS_ANNOUNCE_LENGTH); + MessageOut outMsg; + outMsg.writeShort(0x0099); + outMsg.writeShort(msg.length() + 4); + outMsg.writeString(msg, msg.length()); + } + else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP) + { + chatLog("-- Help --", BY_SERVER); + chatLog("/help : Display this help.", BY_SERVER); + chatLog("/announce : Global announcement (GM only)", BY_SERVER); + chatLog("/where : Display map name", BY_SERVER); + chatLog("/who : Display number of online users", BY_SERVER); + } + else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE) + { + chatLog(map_path, BY_SERVER); + } + else if (msg.substr(0, IS_WHO_LENGTH) == IS_WHO) + { + MessageOut outMsg; + outMsg.writeShort(0x00c1); + } + else + { + chatLog("Unknown command", BY_SERVER); + } } std::string diff --git a/src/gui/chat.h b/src/gui/chat.h index addfb6b5..20841873 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -24,7 +24,6 @@ #ifndef _TMW_CHAT_H #define _TMW_CHAT_H -#include #include #include @@ -117,12 +116,7 @@ class ChatWindow : public Window, public gcn::ActionListener, /** * Constructor. */ - ChatWindow(const std::string &logfile, Network *network); - - /** - * Destructor. - */ - ~ChatWindow(); + ChatWindow(Network *network); /** * Logic (updates components' size) @@ -195,7 +189,6 @@ class ChatWindow : public Window, public gcn::ActionListener, private: Network *mNetwork; - std::ofstream mChatlogFile; bool mTmpVisible; /** One item in the chat log */ diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 88998f7a..026f24bd 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -32,10 +32,6 @@ // constant as well as guichan does #include -#ifdef USE_OPENGL -#include "../resources/openglsdlimageloader.h" -#endif - #include "focushandler.h" #include "popupmenu.h" #include "window.h" @@ -57,6 +53,9 @@ #include "../resources/image.h" #include "../resources/resourcemanager.h" #include "../resources/sdlimageloader.h" +#ifdef USE_OPENGL +#include "../resources/openglsdlimageloader.h" +#endif // Guichan stuff Gui *gui; diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 9eb94520..7ac226d3 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -42,6 +42,7 @@ #include "../configuration.h" #include "../graphics.h" #include "../log.h" +#include "../main.h" #include "../utils/tostring.h" diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 9188b6de..8c69d3ef 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -300,7 +300,7 @@ int UpdaterWindow::downloadThread(void *ptr) // 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()); + ::rename(outFilename.c_str(), newName.c_str()); } } diff --git a/src/main.cpp b/src/main.cpp index ce68b7bb..a4ef29ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,7 +43,6 @@ #define NOGDI #endif -#include "animation.h" #include "configuration.h" #include "game.h" #include "graphics.h" @@ -216,15 +215,6 @@ void init_engine() resman->addToSearchPath("data", true); resman->addToSearchPath(TMW_DATADIR "data", true); - int width, height, bpp; - bool fullscreen, hwaccel; - - width = (int)config.getValue("screenwidth", 800); - height = (int)config.getValue("screenheight", 600); - bpp = 0; - fullscreen = ((int)config.getValue("screen", 0) == 1); - hwaccel = ((int)config.getValue("hwaccel", 0) == 1); - #ifdef USE_OPENGL bool useOpenGL = (config.getValue("opengl", 0) == 1); @@ -232,16 +222,18 @@ void init_engine() Image::setLoadAsOpenGL(useOpenGL); // Create the graphics context - if (useOpenGL) { - graphics = new OpenGLGraphics(); - } else { - graphics = new Graphics(); - } + graphics = useOpenGL ? new OpenGLGraphics() : new Graphics(); #else // Create the graphics context graphics = new Graphics(); #endif + int width = (int)config.getValue("screenwidth", 800); + int height = (int)config.getValue("screenheight", 600); + int bpp = 0; + bool fullscreen = ((int)config.getValue("screen", 0) == 1); + bool hwaccel = ((int)config.getValue("hwaccel", 0) == 1); + // Try to set the desired video mode if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel)) { @@ -299,11 +291,8 @@ void exit_engine() delete gui; delete graphics; - std::vector::iterator iter; - for (iter = hairset.begin(); iter != hairset.end(); ++iter) - { - (*iter)->decRef(); - } + std::for_each(hairset.begin(), hairset.end(), + std::mem_fun(&Spriteset::decRef)); hairset.clear(); playerset[0]->decRef(); diff --git a/src/monster.cpp b/src/monster.cpp index 43823e50..8a7e2f32 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -23,10 +23,8 @@ #include "monster.h" +#include "animatedsprite.h" #include "game.h" -#include "log.h" - -#include "resources/resourcemanager.h" #include "utils/tostring.h" diff --git a/src/npc.cpp b/src/npc.cpp index 54205ad3..a82490ae 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -23,6 +23,8 @@ #include "npc.h" +#include "animatedsprite.h" + #include "net/messageout.h" #include "net/protocol.h" diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 2a6c931d..05bbb6b3 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -21,6 +21,8 @@ * $Id$ */ +#include "main.h" + #ifdef USE_OPENGL #include "openglgraphics.h" diff --git a/src/player.cpp b/src/player.cpp index 05825f6e..3fe608c7 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -23,8 +23,7 @@ #include "player.h" -#include "animation.h" -#include "equipment.h" +#include "animatedsprite.h" #include "game.h" #include "graphics.h" @@ -91,11 +90,13 @@ Player::setSex(Uint8 sex) delete mSprites[BASE_SPRITE]; if (sex == 0) { - mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/player_male_base.xml", 0); + mSprites[BASE_SPRITE] = new AnimatedSprite( + "graphics/sprites/player_male_base.xml", 0); } else { - mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/player_female_base.xml", 0); + mSprites[BASE_SPRITE] = new AnimatedSprite( + "graphics/sprites/player_female_base.xml", 0); } } Being::setSex(sex); @@ -107,8 +108,16 @@ Player::setHairColor(Uint16 color) if (color != mHairColor && mHairStyle > 0) { delete mSprites[HAIR_SPRITE]; - mSprites[HAIR_SPRITE] = new AnimatedSprite("graphics/sprites/hairstyle"+toString(mHairStyle)+".xml", color - 1); + AnimatedSprite *newHairSprite = new AnimatedSprite( + "graphics/sprites/hairstyle" + toString(mHairStyle) + ".xml", + color - 1); + newHairSprite->setDirection(getSpriteDirection()); + + mSprites[HAIR_SPRITE] = newHairSprite; + + setAction(mAction); } + Being::setHairColor(color); } @@ -118,8 +127,16 @@ Player::setHairStyle(Uint16 style) if (style != mHairStyle && mHairColor > 0) { delete mSprites[HAIR_SPRITE]; - mSprites[HAIR_SPRITE] = new AnimatedSprite("graphics/sprites/hairstyle"+toString(style)+".xml", mHairColor - 1); + AnimatedSprite *newHairSprite = new AnimatedSprite( + "graphics/sprites/hairstyle" + toString(style) + ".xml", + mHairColor - 1); + newHairSprite->setDirection(getSpriteDirection()); + + mSprites[HAIR_SPRITE] = newHairSprite; + + setAction(mAction); } + Being::setHairStyle(style); } @@ -139,18 +156,24 @@ Player::setVisibleEquipment(Uint8 slot, Uint8 id) position = TOPCLOTHES_SPRITE; break; } + + delete mSprites[position]; + mSprites[position] = NULL; + // id = 0 means unequip - if (mSprites[position]) { - delete mSprites[position]; - mSprites[position] = 0; - } if (id) { char stringId[4]; sprintf(stringId, "%03i", id); - printf("Id: %i %i %s\n", id, slot, stringId); - mSprites[position] = new AnimatedSprite( + + AnimatedSprite *equipmentSprite = new AnimatedSprite( "graphics/sprites/item" + toString(stringId) + ".xml", 0); + equipmentSprite->setDirection(getSpriteDirection()); + + mSprites[position] = equipmentSprite; + + setAction(mAction); } + Being::setVisibleEquipment(slot, id); } diff --git a/src/resources/image.h b/src/resources/image.h index 1f67fcae..78751394 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -24,6 +24,8 @@ #ifndef _TMW_IMAGE_H #define _TMW_IMAGE_H +#include "../main.h" + #include #ifdef USE_OPENGL #include diff --git a/src/resources/itemmanager.cpp b/src/resources/itemmanager.cpp index 56ac6354..63c0b036 100644 --- a/src/resources/itemmanager.cpp +++ b/src/resources/itemmanager.cpp @@ -30,6 +30,8 @@ #include "../log.h" +#include "../utils/dtor.h" + #define READ_PROP(node, prop, name, target, cast) \ prop = xmlGetProp(node, BAD_CAST name); \ if (prop) { \ @@ -56,14 +58,12 @@ ItemManager::ItemManager() if (!doc) { logger->error("Item Manager: Error while parsing item database (items.xml)!"); - return; } xmlNodePtr node = xmlDocGetRootElement(doc); if (!node || !xmlStrEqual(node->name, BAD_CAST "items")) { logger->error("Item Manager: items.xml is not a valid database file!"); - return; } for (node = node->xmlChildrenNode; node != NULL; node = node->next) diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index af79480a..382b0797 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -28,7 +28,6 @@ #include "resourcemanager.h" #include "image.h" -#include "spriteset.h" #include "../base64.h" #include "../log.h" @@ -220,34 +219,26 @@ MapReader::readMap(xmlNodePtr node, const std::string &path) void MapReader::readProperties(xmlNodePtr node, Properties* props) { - node = node->xmlChildrenNode; + for (node = node->xmlChildrenNode; node; node = node->next) { + if (!xmlStrEqual(node->name, BAD_CAST "property")) + continue; - while (node != NULL) - { - if (xmlStrEqual(node->name, BAD_CAST "property")) - { - // Example: - - xmlChar *name = xmlGetProp(node, BAD_CAST "name"); - xmlChar *value = xmlGetProp(node, BAD_CAST "value"); + // Example: + xmlChar *name = xmlGetProp(node, BAD_CAST "name"); + xmlChar *value = xmlGetProp(node, BAD_CAST "value"); - if (name && value) - { - props->setProperty((const char*) name, (const char*) value); - } - - if (name) xmlFree(name); - if (value) xmlFree(value); + if (name && value) { + props->setProperty((const char*)name, (const char*)value); } - node = node->next; + if (name) xmlFree(name); + if (value) xmlFree(value); } } void MapReader::readLayer(xmlNodePtr node, Map *map, int layer) { - node = node->xmlChildrenNode; int h = map->getHeight(); int w = map->getWidth(); int x = 0; @@ -255,89 +246,86 @@ MapReader::readLayer(xmlNodePtr node, Map *map, int layer) // Load the tile data. Layers are assumed to be map size, with (0,0) as // origin. - while (node != NULL) - { - if (xmlStrEqual(node->name, BAD_CAST "data")) + for (node = node->xmlChildrenNode; node; node = node->next) { + if (!xmlStrEqual(node->name, BAD_CAST "data")) + continue; + + xmlChar *encoding = xmlGetProp(node, BAD_CAST "encoding"); + xmlChar *compression = xmlGetProp(node, BAD_CAST "compression"); + + if (encoding && xmlStrEqual(encoding, BAD_CAST "base64")) { - xmlChar *encoding = xmlGetProp(node, BAD_CAST "encoding"); - xmlChar *compression = xmlGetProp(node, BAD_CAST "compression"); + xmlFree(encoding); - if (encoding && xmlStrEqual(encoding, BAD_CAST "base64")) - { - xmlFree(encoding); + if (compression) { + logger->log("Warning: no layer compression supported!"); + xmlFree(compression); + return; + } - if (compression) { - logger->log("Warning: no layer compression supported!"); - xmlFree(compression); - return; - } + // Read base64 encoded map file + xmlNodePtr dataChild = node->xmlChildrenNode; + if (!dataChild) + continue; - // Read base64 encoded map file - xmlNodePtr dataChild = node->xmlChildrenNode; - if (!dataChild) continue; - - int len = strlen((const char*)dataChild->content) + 1; - unsigned char *charData = new unsigned char[len + 1]; - const char *charStart = (const char*)dataChild->content; - unsigned char *charIndex = charData; - - while (*charStart) { - if (*charStart != ' ' && *charStart != '\t' && - *charStart != '\n') - { - *charIndex = *charStart; - charIndex++; - } - charStart++; + int len = strlen((const char*)dataChild->content) + 1; + unsigned char *charData = new unsigned char[len + 1]; + const char *charStart = (const char*)dataChild->content; + unsigned char *charIndex = charData; + + while (*charStart) { + if (*charStart != ' ' && *charStart != '\t' && + *charStart != '\n') + { + *charIndex = *charStart; + charIndex++; } - *charIndex = '\0'; + charStart++; + } + *charIndex = '\0'; - int binLen; - unsigned char *binData = - php_base64_decode(charData, strlen((char*)charData), - &binLen); + int binLen; + unsigned char *binData = + php_base64_decode(charData, strlen((char*)charData), + &binLen); - delete[] charData; + delete[] charData; - if (binData) { - for (int i = 0; i < binLen - 3; i += 4) { - int gid = binData[i] | - binData[i + 1] << 8 | - binData[i + 2] << 16 | - binData[i + 3] << 24; + if (binData) { + for (int i = 0; i < binLen - 3; i += 4) { + int gid = binData[i] | + binData[i + 1] << 8 | + binData[i + 2] << 16 | + binData[i + 3] << 24; - map->setTileWithGid(x, y, layer, gid); + map->setTileWithGid(x, y, layer, gid); - x++; - if (x == w) {x = 0; y++;} - } - free(binData); + x++; + if (x == w) {x = 0; y++;} } + free(binData); } - else { - // Read plain XML map file - xmlNodePtr n2 = node->xmlChildrenNode; - - while (n2 != NULL) - { - if (xmlStrEqual(n2->name, BAD_CAST "tile") && y < h) - { - int gid = getProperty(n2, "gid", -1); - map->setTileWithGid(x, y, layer, gid); - - x++; - if (x == w) {x = 0; y++;} - } - - n2 = n2->next; + } + else { + // Read plain XML map file + for (xmlNodePtr n2 = node->xmlChildrenNode; n2; n2 = n2->next) { + if (!xmlStrEqual(n2->name, BAD_CAST "tile")) + continue; + + int gid = getProperty(n2, "gid", -1); + map->setTileWithGid(x, y, layer, gid); + + x++; + if (x == w) { + x = 0; y++; + if (y >= h) + break; } } - - // There can be only one data element - break; } - node = node->next; + // There can be only one data element + break; } } @@ -356,38 +344,33 @@ MapReader::readTileset(xmlNodePtr node, int tw = getProperty(node, "tilewidth", map->getTileWidth()); int th = getProperty(node, "tileheight", map->getTileHeight()); - node = node->xmlChildrenNode; + for (node = node->xmlChildrenNode; node; node = node->next) { + if (!xmlStrEqual(node->name, BAD_CAST "image")) + continue; - while (node != NULL) - { - if (xmlStrEqual(node->name, BAD_CAST "image")) - { - xmlChar* source = xmlGetProp(node, BAD_CAST "source"); + xmlChar* source = xmlGetProp(node, BAD_CAST "source"); - if (source) - { - std::string sourceStr = std::string((const char*)source); - sourceStr.erase(0, 3); // Remove "../" + if (source) + { + std::string sourceStr = std::string((const char*)source); + sourceStr.erase(0, 3); // Remove "../" - ResourceManager *resman = ResourceManager::getInstance(); - Image* tilebmp = resman->getImage(sourceStr); + ResourceManager *resman = ResourceManager::getInstance(); + Image* tilebmp = resman->getImage(sourceStr); - if (tilebmp) - { - Tileset *set = new Tileset(tilebmp, tw, th, firstGid); - tilebmp->decRef(); - xmlFree(source); - return set; - } - else { - logger->log("Warning: Failed to load tileset (%s)", source); - } + if (tilebmp) + { + Tileset *set = new Tileset(tilebmp, tw, th, firstGid); + tilebmp->decRef(); + xmlFree(source); + return set; + } + else { + logger->log("Warning: Failed to load tileset (%s)", source); } - - break; } - node = node->next; + break; } return NULL; @@ -396,13 +379,12 @@ MapReader::readTileset(xmlNodePtr node, int MapReader::getProperty(xmlNodePtr node, const char* name, int def) { + int &ret = def; + xmlChar *prop = xmlGetProp(node, BAD_CAST name); if (prop) { - int val = atoi((char*)prop); + ret = atoi((char*)prop); xmlFree(prop); - return val; - } - else { - return def; } + return ret; } diff --git a/src/resources/openglsdlimageloader.cpp b/src/resources/openglsdlimageloader.cpp index c7ddec74..b3e1601e 100644 --- a/src/resources/openglsdlimageloader.cpp +++ b/src/resources/openglsdlimageloader.cpp @@ -21,14 +21,16 @@ * $Id: sdlimageloader.cpp 2121 2006-01-31 02:55:26Z der_doener $ */ -#ifdef USE_OPENGL - #include "openglsdlimageloader.h" #include #include "resourcemanager.h" +#include "../main.h" + +#ifdef USE_OPENGL + SDL_Surface* OpenGLSDLImageLoader::loadSDLSurface(const std::string& filename) { ResourceManager *resman = ResourceManager::getInstance(); -- cgit v1.2.3-70-g09d2 From 01591924a4f33d5a5e4a86db6c256c8ce797a820 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 20 Aug 2006 00:56:23 +0000 Subject: The Network can now connect to the three servers and affected methods now take the server type as a parameter. The MessageOut gained a convenience constructor (same as was added server side). The game states during login sequence have been renamed and redone in order to ensure no communication is attempted to unconnected servers. This allowed the removal of the outgoing message queue. Connecting to the account server has been moved before the login/register phase (dialogs will still need to be updated). Quite a few things are expected to be broken since I'm rather tired at the moment. I've left many TODO entries in the code. --- ChangeLog | 19 +++++ src/gui/char_select.cpp | 8 +- src/gui/connection.cpp | 4 +- src/gui/gui.cpp | 2 +- src/gui/login.cpp | 7 +- src/gui/register.cpp | 4 +- src/gui/updatewindow.cpp | 6 +- src/main.cpp | 189 +++++++++++++++++++++++------------------- src/main.h | 30 +++---- src/net/charserverhandler.cpp | 22 +++-- src/net/loginhandler.cpp | 8 +- src/net/maploginhandler.cpp | 4 +- src/net/messageout.cpp | 8 ++ src/net/messageout.h | 5 ++ src/net/network.cpp | 153 ++++++++++++++++++++++------------ src/net/network.h | 59 +++++++------ 16 files changed, 323 insertions(+), 205 deletions(-) (limited to 'src/gui/updatewindow.cpp') diff --git a/ChangeLog b/ChangeLog index a9596e29..c4cb401c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-08-20 Bjørn Lindeijer + + * src/gui/connection.cpp, src/gui/login.cpp, src/gui/gui.cpp, + src/gui/updatewindow.cpp, src/gui/char_select.cpp, + src/gui/register.cpp, src/main.cpp, src/net/loginhandler.cpp, + src/net/messageout.cpp, src/net/network.h, + src/net/charserverhandler.cpp, src/net/maploginhandler.cpp, + src/net/messageout.h, src/net/network.cpp, src/main.h: The Network + can now connect to the three servers and affected methods now take the + server type as a parameter. The MessageOut gained a convenience + constructor (same as was added server side). The game states during + login sequence have been renamed and redone in order to ensure no + communication is attempted to unconnected servers. This allowed the + removal of the outgoing message queue. Connecting to the account + server has been moved before the login/register phase (dialogs will + still need to be updated). Quite a few things are expected to be + broken since I'm rather tired at the moment. I've left many TODO + entries in the code. + 2006-08-19 Bjørn Lindeijer * src/game.cpp, src/net/network.h, src/net/network.cpp: Removed diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 775ecc6f..2fa6c68e 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -139,7 +139,7 @@ void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget) } else if (eventId == "cancel") { - state = EXIT_STATE; + state = STATE_EXIT; } else if (eventId == "new") { @@ -208,7 +208,7 @@ void CharSelectDialog::attemptCharDelete() msg.writeShort(PAMSG_CHAR_DELETE); // TODO: Send the selected slot msg.writeByte(0); - network->send(msg); + network->send(Network::ACCOUNT, msg); mCharInfo->lock(); } @@ -218,7 +218,7 @@ void CharSelectDialog::attemptCharSelect() MessageOut msg; msg.writeShort(PAMSG_CHAR_SELECT); msg.writeByte(mCharInfo->getPos()); - network->send(msg); + network->send(Network::ACCOUNT, msg); mCharInfo->lock(); } @@ -337,5 +337,5 @@ void CharCreateDialog::attemptCharCreate() outMsg.writeShort(10); // INT outMsg.writeShort(10); // DEX outMsg.writeShort(10); // LUK - network->send(outMsg); + network->send(Network::ACCOUNT, outMsg); } diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp index f7fdaca6..a29008c3 100644 --- a/src/gui/connection.cpp +++ b/src/gui/connection.cpp @@ -35,7 +35,9 @@ namespace { struct ConnectionActionListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { state = EXIT_STATE; } + void action(const std::string &eventId, gcn::Widget *widget) { + state = STATE_EXIT; + } } listener; } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 026f24bd..0e200db3 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -234,7 +234,7 @@ Gui::mousePress(int mx, int my, int button) // Mouse pressed on window container (basically, the map) // Are we in-game yet? - if (state != GAME_STATE) + if (state != STATE_GAME) return; // Check if we are alive and kickin' diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 2f646bd1..cb16dcb4 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -147,18 +147,17 @@ LoginDialog::action(const std::string &eventId, gcn::Widget *widget) mLoginData->remember = mKeepCheck->isMarked(); mOkButton->setEnabled(false); - //mCancelButton->setEnabled(false); mRegisterButton->setEnabled(false); - state = ACCOUNT_STATE; + state = STATE_LOGIN_ATTEMPT; } } else if (eventId == "cancel") { - state = EXIT_STATE; + state = STATE_EXIT; } else if (eventId == "register") { - state = REGISTER_STATE; + state = STATE_REGISTER; } } diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 49da10b6..52833aea 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -119,7 +119,7 @@ RegisterDialog::action(const std::string &eventId, gcn::Widget *widget) { if (eventId == "cancel") { - state = EXIT_STATE; + state = STATE_EXIT; } else if (eventId == "register") { @@ -205,7 +205,7 @@ RegisterDialog::action(const std::string &eventId, gcn::Widget *widget) mLoginData->password = mPasswordField->getText(); mLoginData->email = mEmailField->getText(); - state = REGISTER_ACCOUNT_STATE; + state = STATE_REGISTER_ATTEMPT; } } } diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 8c69d3ef..77a026fe 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -136,7 +136,7 @@ void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) // Skip the updating process if (mDownloadStatus == UPDATE_COMPLETE) { - state = EXIT_STATE; + state = STATE_EXIT; } else { @@ -145,7 +145,7 @@ void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) } else if (eventId == "play") { - state = LOGIN_STATE; + state = STATE_LOGIN; } } @@ -198,7 +198,7 @@ int UpdaterWindow::updateProgress(void *ptr, uw->mCurrentFile + " (" + toString((int)progress * 100) + "%)"); uw->setProgress(progress); - if (state != UPDATE_STATE || uw->mDownloadStatus == UPDATE_ERROR) + if (state != STATE_UPDATE || uw->mDownloadStatus == UPDATE_ERROR) { // If the action was canceled return an error code to stop the mThread return -1; diff --git a/src/main.cpp b/src/main.cpp index dc76846e..d62594c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,7 +99,9 @@ Logger *logger; /**< Log object */ namespace { struct ErrorListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { state = LOGIN_STATE; } + void action(const std::string &eventId, gcn::Widget *widget) { + state = STATE_CHOOSE_SERVER; + } } errorListener; } @@ -267,7 +269,7 @@ void init_engine() } gui = new Gui(graphics); - state = UPDATE_STATE; /**< Initial game state */ + state = STATE_CHOOSE_SERVER; /**< Initial game state */ // Initialize sound engine try { @@ -278,7 +280,7 @@ void init_engine() sound.setMusicVolume((int)config.getValue("musicVolume", 60)); } catch (const char *err) { - state = ERROR_STATE; + state = STATE_ERROR; errorMessage = err; logger->log("Warning: %s", err); } @@ -409,9 +411,7 @@ MapLoginHandler mapLoginHandler; // TODO Find some nice place for these functions void accountLogin(LoginData *loginData) { - logger->log("Trying to connect to account server..."); logger->log("Username is %s", loginData->username.c_str()); - network->connect(loginData->hostname, loginData->port); network->registerHandler(&loginHandler); network->registerHandler(&charServerHandler); loginHandler.setLoginData(loginData); @@ -419,12 +419,11 @@ void accountLogin(LoginData *loginData) charServerHandler.setCharInfo(&charInfo); // Send login infos - MessageOut msg; - msg.writeShort(PAMSG_LOGIN); + MessageOut msg(PAMSG_LOGIN); msg.writeLong(0); // client version msg.writeString(loginData->username); msg.writeString(loginData->password); - network->send(msg); + network->send(Network::ACCOUNT, msg); // Clear the password, avoids auto login when returning to login loginData->password = ""; @@ -440,40 +439,37 @@ void accountLogin(LoginData *loginData) void accountRegister(LoginData *loginData) { - logger->log("Trying to connect to account server..."); logger->log("Username is %s", loginData->username.c_str()); - network->connect(loginData->hostname, loginData->port); network->registerHandler(&loginHandler); loginHandler.setLoginData(loginData); charServerHandler.setLoginData(loginData); charServerHandler.setCharInfo(&charInfo); // Send login infos - MessageOut msg; - msg.writeShort(PAMSG_REGISTER); + MessageOut msg(PAMSG_REGISTER); msg.writeLong(0); // client version msg.writeString(loginData->username); msg.writeString(loginData->password); msg.writeString(loginData->email); - network->send(msg); + network->send(Network::ACCOUNT, msg); } void mapLogin(Network *network, LoginData *loginData) { - MessageOut outMsg; - - logger->log("Trying to connect to map server..."); + // TODO: Before the client has been identified using the magic token, the + // map path is not known yet. logger->log("Map: %s", map_path.c_str()); - network->connect(loginData->hostname, loginData->port); network->registerHandler(&mapLoginHandler); // Send login infos - outMsg.writeShort(0x0072); - outMsg.writeLong(loginData->account_ID); - outMsg.writeLong(player_node->mCharId); - outMsg.writeLong(loginData->session_ID1); - outMsg.writeLong(loginData->session_ID2); + // TODO: The token would need to be sent to complete client identification + // for the game server + //MessageOut outMsg(0x0072); + //outMsg.writeLong(loginData->account_ID); + //outMsg.writeLong(player_node->mCharId); + //outMsg.writeLong(loginData->session_ID1); + //outMsg.writeLong(loginData->session_ID2); } /** Main */ @@ -515,13 +511,6 @@ int main(int argc, char *argv[]) init_engine(); - if (options.skipUpdate && state != ERROR_STATE) { - state = LOGIN_STATE; - } - else { - state = UPDATE_STATE; - } - unsigned int oldstate = !state; // We start with a status change. Window *currentDialog = NULL; @@ -549,20 +538,21 @@ int main(int argc, char *argv[]) } network = new Network(); + SDL_Event event; - while (state != EXIT_STATE) + while (state != STATE_EXIT) { // Handle SDL events while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: - state = EXIT_STATE; + state = STATE_EXIT; break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) - state = EXIT_STATE; + state = STATE_EXIT; break; } @@ -574,7 +564,7 @@ int main(int argc, char *argv[]) if (network->getState() == Network::NET_ERROR) { - state = ERROR_STATE; + state = STATE_ERROR; errorMessage = "Got disconnected from server!"; } @@ -596,48 +586,89 @@ int main(int argc, char *argv[]) gui->draw(); graphics->updateScreen(); + // TODO: Add connect timeout to go back to choose server + if (state == STATE_CONNECT_ACCOUNT && + network->isConnected(Network::ACCOUNT)) + { + if (options.skipUpdate) { + state = STATE_LOGIN; + } else { + state = STATE_UPDATE; + } + } + else if (state == STATE_CONNECT_GAME && + network->isConnected(Network::GAME) && + network->isConnected(Network::CHAT)) + { + // TODO: Somehow send the token + state = STATE_GAME; + } + if (state != oldstate) { - switch (oldstate) + // Load updates after exiting the update state + if (oldstate == STATE_UPDATE) { - case UPDATE_STATE: - loadUpdates(); - break; - - // Those states don't cause a network disconnect - case ACCOUNT_STATE: - case CONNECTING_STATE: - break; + loadUpdates(); + } - default: - network->disconnect(); - network->clearHandlers(); - break; + // Disconnect from account server once connected to game server + if (oldstate == STATE_CONNECT_GAME && state == STATE_GAME) + { + network->disconnect(Network::ACCOUNT); } oldstate = state; - if (currentDialog && state != ACCOUNT_STATE && - state != CHAR_CONNECT_STATE) { + // Get rid of the dialog of the previous state + if (currentDialog) { delete currentDialog; currentDialog = NULL; } switch (state) { - case LOGIN_STATE: + case STATE_CHOOSE_SERVER: + logger->log("State: CHOOSE_SERVER"); + // TODO: Allow changing this using a server choice dialog + logger->log("Trying to connect to account server..."); + network->connect(Network::ACCOUNT, + loginData.hostname, loginData.port); + state = STATE_CONNECT_ACCOUNT; + break; + + case STATE_CONNECT_ACCOUNT: + logger->log("State: CONNECT_ACCOUNT"); + break; + + case STATE_UPDATE: + logger->log("State: UPDATE"); + // TODO: Revive later + //currentDialog = new UpdaterWindow(); + state = STATE_LOGIN; + break; + + case STATE_LOGIN: logger->log("State: LOGIN"); - if (!loginData.password.empty()) { - state = ACCOUNT_STATE; - } else { - currentDialog = new LoginDialog(&loginData); - } + currentDialog = new LoginDialog(&loginData); + // TODO: Restore autologin + //if (!loginData.password.empty()) { + // accountLogin(&loginData); + //} + break; + + case STATE_LOGIN_ATTEMPT: + accountLogin(&loginData); break; - case REGISTER_STATE: + case STATE_REGISTER: logger->log("State: REGISTER"); currentDialog = new RegisterDialog(&loginData); break; - case CHAR_SELECT_STATE: + case STATE_REGISTER_ATTEMPT: + accountRegister(&loginData); + break; + + case STATE_CHAR_SELECT: logger->log("State: CHAR_SELECT"); currentDialog = new CharSelectDialog(network, &charInfo); if (options.chooseDefault) { @@ -646,50 +677,38 @@ int main(int argc, char *argv[]) } break; - case GAME_STATE: - sound.fadeOutMusic(1000); - - currentDialog = NULL; - login_wallpaper->decRef(); - login_wallpaper = NULL; - - logger->log("State: GAME"); - game = new Game(network); - game->logic(); - delete game; - state = EXIT_STATE; - break; - - case UPDATE_STATE: - logger->log("State: UPDATE"); - currentDialog = new UpdaterWindow(); - break; - - case ERROR_STATE: + case STATE_ERROR: logger->log("State: ERROR"); currentDialog = new OkDialog("Error", errorMessage); currentDialog->addActionListener(&errorListener); currentDialog = NULL; // OkDialog deletes itself - network->disconnect(); + network->disconnect(Network::GAME); + network->disconnect(Network::CHAT); network->clearHandlers(); break; - case CONNECTING_STATE: - logger->log("State: CONNECTING"); + case STATE_CONNECT_GAME: + logger->log("State: CONNECT_GAME"); mapLogin(network, &loginData); currentDialog = new ConnectionDialog(); break; - case ACCOUNT_STATE: - accountLogin(&loginData); - break; + case STATE_GAME: + sound.fadeOutMusic(1000); - case REGISTER_ACCOUNT_STATE: - accountRegister(&loginData); + currentDialog = NULL; + login_wallpaper->decRef(); + login_wallpaper = NULL; + + logger->log("State: GAME"); + game = new Game(network); + game->logic(); + delete game; + state = STATE_EXIT; break; default: - state = EXIT_STATE; + state = STATE_EXIT; break; } } diff --git a/src/main.h b/src/main.h index 035b0ec7..47c650af 100644 --- a/src/main.h +++ b/src/main.h @@ -39,20 +39,20 @@ enum { - EXIT_STATE, - LOGIN_STATE, - ACCOUNT_STATE, - REGISTER_STATE, - REGISTER_ACCOUNT_STATE, - CHAR_CONNECT_STATE, - CHAR_SERVER_STATE, - CHAR_SELECT_STATE, - CHAR_NEW_STATE, - CHAR_DEL_STATE, - GAME_STATE, - ERROR_STATE, - UPDATE_STATE, - CONNECTING_STATE + STATE_CHOOSE_SERVER, + STATE_CONNECT_ACCOUNT, + STATE_UPDATE, + STATE_LOGIN, + STATE_LOGIN_ATTEMPT, + STATE_REGISTER, + STATE_REGISTER_ATTEMPT, + STATE_CHAR_SELECT, + STATE_CHAR_NEW, + STATE_CHAR_DELETE, + STATE_ERROR, + STATE_CONNECT_GAME, + STATE_GAME, + STATE_EXIT }; /* length definitions for several char[]s in order @@ -66,7 +66,7 @@ enum { LEN_MIN_PASSWORD = 4 }; -extern char n_server, n_character; +extern char n_character; extern unsigned char state; extern std::string errorMessage; diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp index b8cc710e..ea9b3196 100644 --- a/src/net/charserverhandler.cpp +++ b/src/net/charserverhandler.cpp @@ -165,14 +165,20 @@ CharServerHandler::handleCharSelectResponse(MessageIn &msg) if (errMsg == 0) { - //std::string token = msg.readString(32); - //std::string gameServer = msg.readString(); - //unsigned short gameServerPort = msg.readShort(); - //std::string chatServer = msg.readString(); - //unsigned short chatServerPort = msg.readShort(); - - // TODO: Connect to game and chat servers, and login using the given - // TODO: token. + // TODO: Somehow be able to send this token once connected + std::string token = msg.readString(32); + std::string gameServer = msg.readString(); + unsigned short gameServerPort = msg.readShort(); + std::string chatServer = msg.readString(); + unsigned short chatServerPort = msg.readShort(); + + logger->log("Game server: %s:%d", gameServer.c_str(), gameServerPort); + logger->log("Chat server: %s:%d", chatServer.c_str(), chatServerPort); + + network->connect(Network::GAME, gameServer, gameServerPort); + network->connect(Network::CHAT, chatServer, chatServerPort); + + state = STATE_CONNECT_GAME; } } diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp index 27d8eed5..4790d7d1 100644 --- a/src/net/loginhandler.cpp +++ b/src/net/loginhandler.cpp @@ -51,7 +51,7 @@ void LoginHandler::handleMessage(MessageIn *msg) // Successful login if (errMsg == ERRMSG_OK) { - state = CHAR_SELECT_STATE; + state = STATE_CHAR_SELECT; } // Login failed else @@ -73,7 +73,7 @@ void LoginHandler::handleMessage(MessageIn *msg) errorMessage = "Unknown error"; break; } - state = ERROR_STATE; + state = STATE_ERROR; } } break; @@ -83,7 +83,7 @@ void LoginHandler::handleMessage(MessageIn *msg) // Successful registration if (errMsg == ERRMSG_OK) { - state = ACCOUNT_STATE; + state = STATE_CHAR_SELECT; } // Registration failed else @@ -105,7 +105,7 @@ void LoginHandler::handleMessage(MessageIn *msg) errorMessage = "Unknown error"; break; } - state = ERROR_STATE; + state = STATE_ERROR; } } break; diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp index 38ed2203..579e8542 100644 --- a/src/net/maploginhandler.cpp +++ b/src/net/maploginhandler.cpp @@ -50,12 +50,12 @@ void MapLoginHandler::handleMessage(MessageIn *msg) msg->readLong(); // server tick //logger->log("Protocol: Player start position: (%d, %d), Direction: %d", // player_node->mX, player_node->mY, direction); - state = GAME_STATE; + state = STATE_GAME; break; case 0x0081: logger->log("Warning: Map server D/C"); - state = ERROR_STATE; + state = STATE_ERROR; break; } } diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp index 7f5fadcb..426a1c0d 100644 --- a/src/net/messageout.cpp +++ b/src/net/messageout.cpp @@ -36,6 +36,14 @@ MessageOut::MessageOut(): { } +MessageOut::MessageOut(short id): + mData(0), + mDataSize(0), + mPos(0) +{ + writeShort(id); +} + MessageOut::~MessageOut() { if (mData) { diff --git a/src/net/messageout.h b/src/net/messageout.h index 22754f60..81369c0e 100644 --- a/src/net/messageout.h +++ b/src/net/messageout.h @@ -37,6 +37,11 @@ class MessageOut */ MessageOut(); + /** + * Constructor. + */ + MessageOut(short id); + /** * Destructor. */ diff --git a/src/net/network.cpp b/src/net/network.cpp index f543bfb1..23d9e291 100644 --- a/src/net/network.cpp +++ b/src/net/network.cpp @@ -32,47 +32,55 @@ Network *network; Network::Network(): - mClient(0), mServer(0), - mAddress(), mPort(0), - mState(IDLE) + mAccountServer(NULL), + mGameServer(NULL), + mChatServer(NULL), + mState(NET_OK) { + mClient = enet_host_create(NULL, 3, 0, 0); + + if (!mClient) + { + logger->error( + "An error occurred while trying to create an ENet client."); + mState = NET_ERROR; + } } Network::~Network() { clearHandlers(); - if (mState != IDLE && mState != NET_ERROR) - disconnect(); + disconnect(ACCOUNT); + disconnect(GAME); + disconnect(CHAT); } -bool Network::connect(const std::string &address, short port) +bool +Network::connect(Server server, const std::string &address, short port) { - if (mState != IDLE && mState != NET_ERROR) - { - logger->log("Tried to connect an already connected socket!"); - return false; - } + logger->log("Network::connect(%d, %s, %i)", server, address.c_str(), port); if (address.empty()) { - logger->log("Empty address given to Network::connect()!"); + logger->log("Network::connect() got empty address!"); mState = NET_ERROR; return false; } - logger->log("Network::Connecting to %s:%i", address.c_str(), port); - - mAddress = address; - mPort = port; + ENetPeer *peer = NULL; - mState = CONNECTING; - - mClient = enet_host_create(NULL, 1, 0, 0); + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } - if (!mClient) + if (peer != NULL) { - logger->error("An error occurred while trying to create an ENet client."); + logger->log("Network::connect() already connected (or connecting) to " + "this server!"); + return false; } ENetAddress enetAddress; @@ -81,32 +89,51 @@ bool Network::connect(const std::string &address, short port) enetAddress.port = port; // Initiate the connection, allocating channel 0. - mServer = enet_host_connect(mClient, &enetAddress, 1); + peer = enet_host_connect(mClient, &enetAddress, 1); - if (mServer == 0) + if (peer == NULL) { logger->log("Unable to initiate connection to the server."); mState = NET_ERROR; return false; } + switch (server) { + case ACCOUNT: mAccountServer = peer; break; + case GAME: mGameServer = peer; break; + case CHAT: mChatServer = peer; break; + } + return true; } -void Network::disconnect() +void +Network::disconnect(Server server) { - mState = IDLE; + ENetPeer *peer = NULL; - if (mServer) + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } + + if (peer) { - enet_peer_disconnect(mServer, 0); + enet_peer_disconnect(peer, 0); enet_host_flush(mClient); - enet_peer_reset(mServer); - mServer = 0; + enet_peer_reset(peer); + + switch (server) { + case ACCOUNT: mAccountServer = NULL; break; + case GAME: mGameServer = NULL; break; + case CHAT: mChatServer = NULL; break; + } } } -void Network::registerHandler(MessageHandler *handler) +void +Network::registerHandler(MessageHandler *handler) { const Uint16 *i = handler->handledMessages; @@ -119,7 +146,8 @@ void Network::registerHandler(MessageHandler *handler) handler->setNetwork(this); } -void Network::unregisterHandler(MessageHandler *handler) +void +Network::unregisterHandler(MessageHandler *handler) { for (const Uint16 *i = handler->handledMessages; *i; i++) { @@ -129,7 +157,8 @@ void Network::unregisterHandler(MessageHandler *handler) handler->setNetwork(0); } -void Network::clearHandlers() +void +Network::clearHandlers() { MessageHandlerIterator i; for (i = mMessageHandlers.begin(); i != mMessageHandlers.end(); i++) @@ -139,6 +168,20 @@ void Network::clearHandlers() mMessageHandlers.clear(); } +bool +Network::isConnected(Server server) const +{ + ENetPeer *peer = NULL; + + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } + + return peer->state == ENET_PEER_STATE_CONNECTED; +} + void Network::dispatchMessage(ENetPacket *packet) { @@ -162,7 +205,7 @@ Network::dispatchMessage(ENetPacket *packet) void Network::flush() { - if (mState == IDLE || mState == NET_ERROR) + if (mState == NET_ERROR) { return; } @@ -176,7 +219,6 @@ void Network::flush() { case ENET_EVENT_TYPE_CONNECT: logger->log("Connected."); - mState = CONNECTED; // Store any relevant server information here. event.peer->data = 0; break; @@ -185,46 +227,53 @@ void Network::flush() logger->log("Incoming data..."); dispatchMessage(event.packet); break; + case ENET_EVENT_TYPE_DISCONNECT: - mState = IDLE; logger->log("Disconnected."); // Reset the server information. event.peer->data = 0; break; + case ENET_EVENT_TYPE_NONE: logger->log("No event during 10 milliseconds."); break; + default: logger->log("Unhandled enet event."); break; } } - - // If connected, manage incoming and outcoming packets - if (isConnected()) - { - while (isConnected() && !mOutgoingPackets.empty()) - { - ENetPacket *packet = mOutgoingPackets.front(); - enet_peer_send(mServer, 0, packet); - mOutgoingPackets.pop(); - } - } } -void Network::send(const MessageOut &msg) +void Network::send(Server server, const MessageOut &msg) { - if (mState == IDLE || mState == NET_ERROR) + if (mState == NET_ERROR) { logger->log("Warning: attempt to send a message while network not " "ready."); return; } - ENetPacket *packet = enet_packet_create(msg.getData(), - msg.getDataSize(), - ENET_PACKET_FLAG_RELIABLE); - mOutgoingPackets.push(packet); + ENetPeer *peer = NULL; + + switch (server) { + case ACCOUNT: peer = mAccountServer; break; + case GAME: peer = mGameServer; break; + case CHAT: peer = mChatServer; break; + } + + if (peer) + { + logger->log("Sending message of size %d to server %d...", + msg.getDataSize(), server); + + // Directly send away the packet (TODO: check what ENet does in case + // this is done before connection is ready) + ENetPacket *packet = enet_packet_create(msg.getData(), + msg.getDataSize(), + ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(peer, 0, packet); + } } char *iptostring(int address) diff --git a/src/net/network.h b/src/net/network.h index eb2ce8ab..49583b9d 100644 --- a/src/net/network.h +++ b/src/net/network.h @@ -36,8 +36,6 @@ class MessageHandler; class MessageIn; class MessageOut; -class Network; - class Network { public: @@ -46,35 +44,53 @@ class Network Network(); ~Network(); - bool connect(const std::string &address, short port); - void disconnect(); + typedef enum { + ACCOUNT, + GAME, + CHAT + } Server; + + bool + connect(Server server, const std::string &address, short port); + + void + disconnect(Server server); + + void + registerHandler(MessageHandler *handler); + + void + unregisterHandler(MessageHandler *handler); - void registerHandler(MessageHandler *handler); - void unregisterHandler(MessageHandler *handler); - void clearHandlers(); + void + clearHandlers(); - int getState() const { return mState; } - bool isConnected() const { return mState == CONNECTED; } + int + getState() const { return mState; } - void dispatchMessage(ENetPacket *packet); - void flush(); + bool + isConnected(Server server) const; - void send(const MessageOut &msg); + void + dispatchMessage(ENetPacket *packet); + + void + flush(); + + void + send(Server server, const MessageOut &msg); enum State { - IDLE, - CONNECTED, - CONNECTING, - DATA, + NET_OK, NET_ERROR }; private: ENetHost *mClient; - ENetPeer *mServer; - std::string mAddress; - short mPort; + ENetPeer *mAccountServer; + ENetPeer *mGameServer; + ENetPeer *mChatServer; unsigned int mToSkip; @@ -83,11 +99,6 @@ class Network typedef std::map MessageHandlers; typedef MessageHandlers::iterator MessageHandlerIterator; MessageHandlers mMessageHandlers; - - std::queue mOutgoingPackets; - - bool realConnect(); - void receive(); }; /** Convert an address from int format to string */ -- cgit v1.2.3-70-g09d2 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 'src/gui/updatewindow.cpp') 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-70-g09d2 From 61b6ae09b58f24d4ada42b2e2ee9cc73e710d242 Mon Sep 17 00:00:00 2001 From: Björn Steinbrink Date: Sat, 4 Nov 2006 23:53:20 +0000 Subject: Removed useless addRow method. --- ChangeLog | 2 ++ src/gui/updatewindow.cpp | 17 ++++++----------- src/gui/updatewindow.h | 5 ----- 3 files changed, 8 insertions(+), 16 deletions(-) (limited to 'src/gui/updatewindow.cpp') diff --git a/ChangeLog b/ChangeLog index 8e0ff305..9bfa084a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2006-11-04 Björn Steinbrink + * src/gui/updatewindow.cpp, src/gui/updatewindow.h: Removed useless + addRow method. * src/main.cpp: Restore the homeDir config entry (temporarily). Initialize the logger before libxml2. * src/main.cpp: Add a libxml2 init wrapper. Use a null-logger function diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 00b10406..510e10ba 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -181,12 +181,6 @@ void UpdaterWindow::loadNews() setVisible(true); } -void UpdaterWindow::addRow(const std::string &row) -{ - mBrowserBox->addRow(row); - mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); -} - int UpdaterWindow::updateProgress(void *ptr, double dt, double dn, double ut, double un) { @@ -342,11 +336,12 @@ void UpdaterWindow::logic() } mThread = NULL; } - addRow(""); - addRow("##1 The update process is incomplete."); - addRow("##1 It is strongly recommended that"); - addRow("##1 you try again later"); - addRow(mCurlError); + mBrowserBox->addRow(""); + mBrowserBox->addRow("##1 The update process is incomplete."); + mBrowserBox->addRow("##1 It is strongly recommended that"); + mBrowserBox->addRow("##1 you try again later"); + mBrowserBox->addRow(mCurlError); + mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); mDownloadStatus = UPDATE_COMPLETE; break; case UPDATE_NEWS: diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index 5016036d..16442656 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -81,11 +81,6 @@ class UpdaterWindow : public Window, public gcn::ActionListener void action(const std::string& eventId, gcn::Widget* widget); - /** - * Add a row to the message field. - */ - void addRow(const std::string &row); - void logic(); int updateState; -- cgit v1.2.3-70-g09d2 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 'src/gui/updatewindow.cpp') 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-70-g09d2 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 'src/gui/updatewindow.cpp') 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-70-g09d2 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 'src/gui/updatewindow.cpp') 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-70-g09d2 From d1395845cdc678db2a71326f2e6f20253ed14cac Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 14 Jan 2007 16:45:13 +0000 Subject: Merged 0.0 changes from revision 2988 to 3035 to trunk. --- ChangeLog | 86 ++++++++++++++++++++++-- src/game.cpp | 19 +++--- src/gui/browserbox.cpp | 15 +++-- src/gui/browserbox.h | 10 +-- src/gui/buddywindow.cpp | 8 +-- src/gui/buddywindow.h | 2 +- src/gui/button.cpp | 9 +-- src/gui/button.h | 2 +- src/gui/buy.cpp | 16 ++--- src/gui/buy.h | 2 +- src/gui/buysell.cpp | 8 +-- src/gui/buysell.h | 2 +- src/gui/char_select.cpp | 40 +++++------ src/gui/char_select.h | 4 +- src/gui/chat.cpp | 15 +++-- src/gui/chat.h | 11 +-- src/gui/chatinput.cpp | 2 +- src/gui/chatinput.h | 2 +- src/gui/confirm_dialog.cpp | 7 +- src/gui/confirm_dialog.h | 2 +- src/gui/connection.cpp | 8 ++- src/gui/debugwindow.cpp | 16 +++-- src/gui/debugwindow.h | 2 +- src/gui/gccontainer.cpp | 6 +- src/gui/gccontainer.h | 9 ++- src/gui/help.cpp | 4 +- src/gui/help.h | 2 +- src/gui/inttextbox.cpp | 7 +- src/gui/inttextbox.h | 3 +- src/gui/inventorywindow.cpp | 20 +++--- src/gui/inventorywindow.h | 6 +- src/gui/item_amount.cpp | 20 +++--- src/gui/item_amount.h | 2 +- src/gui/itemcontainer.cpp | 35 ++++++---- src/gui/itemcontainer.h | 2 +- src/gui/listbox.cpp | 33 ++------- src/gui/listbox.h | 6 +- src/gui/login.cpp | 16 ++--- src/gui/login.h | 4 +- src/gui/menuwindow.cpp | 14 ++-- src/gui/newskill.cpp | 24 +++---- src/gui/newskill.h | 2 +- src/gui/npc_text.cpp | 4 +- src/gui/npc_text.h | 2 +- src/gui/npclistdialog.cpp | 8 +-- src/gui/npclistdialog.h | 2 +- src/gui/ok_dialog.cpp | 6 +- src/gui/ok_dialog.h | 2 +- src/gui/playerbox.cpp | 1 - src/gui/register.cpp | 6 +- src/gui/register.h | 2 +- src/gui/sell.cpp | 18 ++--- src/gui/sell.h | 2 +- src/gui/serverdialog.cpp | 23 ++++--- src/gui/serverdialog.h | 5 +- src/gui/setup.cpp | 8 +-- src/gui/setup.h | 2 +- src/gui/setup_audio.cpp | 10 +-- src/gui/setup_audio.h | 2 +- src/gui/setup_joystick.cpp | 5 +- src/gui/setup_joystick.h | 2 +- src/gui/setup_video.cpp | 49 +++++++------- src/gui/setup_video.h | 5 +- src/gui/shoplistbox.cpp | 6 +- src/gui/shoplistbox.h | 2 +- src/gui/skill.cpp | 10 +-- src/gui/skill.h | 2 +- src/gui/status.cpp | 4 +- src/gui/status.h | 2 +- src/gui/tabbedcontainer.cpp | 4 +- src/gui/tabbedcontainer.h | 2 +- src/gui/trade.cpp | 10 +-- src/gui/trade.h | 2 +- src/gui/updatewindow.cpp | 6 +- src/gui/updatewindow.h | 2 +- src/gui/viewport.cpp | 28 ++++---- src/gui/viewport.h | 28 ++++++-- src/gui/window.cpp | 121 +++++++++++---------------------- src/gui/window.h | 19 +++--- src/main.cpp | 10 +-- src/net/playerhandler.cpp | 4 +- src/net/tradehandler.cpp | 4 +- tools/Purger.java | 159 -------------------------------------------- 83 files changed, 495 insertions(+), 597 deletions(-) delete mode 100644 tools/Purger.java (limited to 'src/gui/updatewindow.cpp') diff --git a/ChangeLog b/ChangeLog index 0cbbb214..d091a061 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,53 @@ +2007-01-14 Bjørn Lindeijer + + * src/game.cpp, src/main.cpp, src/gui/trade.cpp, src/gui/sell.cpp, + src/gui/connection.cpp, src/gui/buddywindow.cpp, src/gui/browserbox.h, + src/gui/char_server.cpp, src/gui/window.cpp, src/gui/login.cpp, + src/gui/inttextbox.h, src/gui/viewport.cpp, src/gui/button.h, + src/gui/shoplistbox.h, src/gui/skill.h, src/gui/item_amount.h, + src/gui/setup_audio.h, src/gui/newskill.cpp, src/gui/listbox.h, + src/gui/register.h, src/gui/setup.cpp, src/gui/npclistdialog.h, + src/gui/updatewindow.cpp, src/gui/button.cpp, src/gui/char_select.cpp, + src/gui/login.h, src/gui/setup_audio.cpp, src/gui/item_amount.cpp, + src/gui/setup_joystick.h, src/gui/chat.h, src/gui/npc_text.cpp, + src/gui/setup_video.cpp, src/gui/ok_dialog.cpp, + src/gui/inventorywindow.h, src/gui/gccontainer.cpp, + src/gui/newskill.h, src/gui/buy.h, src/gui/setup.h, + src/gui/itemcontainer.h, src/gui/confirm_dialog.cpp, + src/gui/debugwindow.cpp, src/gui/chat.cpp, src/gui/setup_joystick.cpp, + src/gui/updatewindow.h, src/gui/char_select.h, src/gui/buysell.h, + src/gui/tabbedcontainer.cpp, src/gui/inventorywindow.cpp, + src/gui/help.cpp, src/gui/status.h, src/gui/npc_text.h, + src/gui/setup_video.h, src/gui/menuwindow.cpp, src/gui/browserbox.cpp, + src/gui/ok_dialog.h, src/gui/buy.cpp, src/gui/itemcontainer.cpp, + src/gui/gccontainer.h, src/gui/buddywindow.h, src/gui/sell.h, + src/gui/trade.h, src/gui/inttextbox.cpp, src/gui/char_server.h, + src/gui/window.h, src/gui/shoplistbox.cpp, src/gui/skill.cpp, + src/gui/buysell.cpp, src/gui/confirm_dialog.h, src/gui/debugwindow.h, + src/gui/status.cpp, src/gui/listbox.cpp, src/gui/register.cpp, + src/gui/viewport.h, src/gui/tabbedcontainer.h, + src/gui/npclistdialog.cpp, src/gui/help.h, src/gui/chatinput.h, + src/gui/chatinput.cpp, src/net/tradehandler.cpp, + src/net/playerhandler.cpp: Upgraded to Guichan 0.6.0 (merge from + guichan-0.6.0 branch). + +2007-01-13 Bjørn Lindeijer + + * data/graphics/sprites/Makefile.am, + data/graphics/sprites/CMakeLists.txt: Updated with regard to renaming + of cotton equipment. + +2006-01-13 Eugenio Favalli + + * src/gui/debugwindow.cpp, src/gui/viewport.h: Fixed mouse coordinates + display in debug window. + +2007-01-12 Bjørn Lindeijer + + * src/gui/viewport.cpp: Fixed initialization of mPlayerFollowMouse, + the lack of which sometimes caused the player to start walking when + clicking on the GUI. + 2007-01-11 Björn Steinbrink * data/graphics/images/ambient/CMakeLists.txt, @@ -7,23 +57,43 @@ 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 + src/net/accountserver/account.cpp, src/player.cpp: Fixed 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-09 Philipp Sehmisch + + * data/graphics/icecave.png: Added new tiles and fixes by Nickman and + made some other cosmetical corrections. + 2007-01-07 Bjørn Lindeijer + * data/graphics/sprites/monster-mountsnake.xml, + data/graphics/sprites/monster-mountsnake.png, data/monsters.xml: Added + brown snake by Pauan. * src/gui/status.h, src/gui/status.cpp, src/localplayer.h: Synchronized player attributes with Attributes page on the wiki. Removed job xp bar. +2007-01-07 Philipp Sehmisch + + * data/graphics/chest-cottonshirt-male.png, + data/graphics/chest-cottonshirt-male.xml, + data/graphics/chest-cottonshirt-female.png, + data/graphics/chest-cottonshirt-female.xml, + data/graphics/item001.png, data/equipment.xml: Added female + cottonshirt sprites. + * data/equipment.xml: Fixed some wrong armor values. + 2007-01-05 Björn Steinbrink * src/CMakeLists.txt, data/graphics/sprites/CMakeLists.txt: Fixed installation when using CMake. + * src/CMakeLists.txt, data/graphics/images/ambient/Makefile.am, + data/graphics/sprites/CMakeLists.txt: Synchronized build files. 2007-01-05 Guillaume Melquiond @@ -36,6 +106,10 @@ * src/map.cpp, src/map.h: Declared some methods const. +2007-01-04 Eugenio Favalli + + * tools/Purger.java: Removed purger tool. + 2007-01-03 Guillaume Melquiond * src/resources/mapreader.cpp: Fixed memory leak on error. @@ -285,11 +359,11 @@ 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. + src/gui/playerbox.cpp, src/gui/passwordfield.h, src/gui/char_select.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 diff --git a/src/game.cpp b/src/game.cpp index 2af13146..40d78248 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -124,9 +124,11 @@ const int MAX_TIME = 10000; * Listener used for exitting handling. */ namespace { - struct ExitListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { - if (eventId == "yes") { + struct ExitListener : public gcn::ActionListener + { + void action(const gcn::ActionEvent &event) + { + if (event.getId() == "yes") { done = true; } exitConfirm = NULL; @@ -386,10 +388,6 @@ void Game::logic() void Game::handleInput() { - // Get the state of the keyboard keys - Uint8* keys; - keys = SDL_GetKeyState(NULL); - if (joystick != NULL) { joystick->update(); @@ -455,7 +453,7 @@ void Game::handleInput() // Close the config window, cancelling changes if opened else if (setupWindow->isVisible()) { - setupWindow->action("cancel", NULL); + setupWindow->action(gcn::ActionEvent(NULL, "cancel")); } // Else, open the chat edit box else @@ -633,7 +631,12 @@ void Game::handleInput() current_npc == 0 && !chatWindow->isFocused()) { + // Get the state of the keyboard keys + Uint8* keys; + keys = SDL_GetKeyState(NULL); + Uint16 x = player_node->mX / 32, y = player_node->mY / 32; + unsigned char direction = 0; // Translate pressed keys to movement and direction diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp index 2aec84a5..65fdde64 100644 --- a/src/gui/browserbox.cpp +++ b/src/gui/browserbox.cpp @@ -98,7 +98,7 @@ void BrowserBox::disableLinksAndUserColors() mUseLinksAndUserColors = false; } -void BrowserBox::addRow(const std::string& row) +void BrowserBox::addRow(const std::string &row) { std::string tmp = row; std::string newRow; @@ -238,25 +238,28 @@ struct MouseOverLink int mX, mY; }; -void BrowserBox::mousePress(int mx, int my, int button) +void +BrowserBox::mousePressed(gcn::MouseEvent &event) { LinkIterator i = find_if(mLinks.begin(), mLinks.end(), - MouseOverLink(mx, my)); + MouseOverLink(event.getX(), event.getY())); if (i != mLinks.end()) { mLinkHandler->handleLink(i->link); } } -void BrowserBox::mouseMotion(int mx, int my) +void +BrowserBox::mouseMoved(gcn::MouseEvent &event) { LinkIterator i = find_if(mLinks.begin(), mLinks.end(), - MouseOverLink(mx, my)); + MouseOverLink(event.getX(), event.getY())); mSelectedLink = (i != mLinks.end()) ? (i - mLinks.begin()) : -1; } -void BrowserBox::draw(gcn::Graphics* graphics) +void +BrowserBox::draw(gcn::Graphics *graphics) { if (mOpaque) { diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h index a2c9dd9b..666a7754 100644 --- a/src/gui/browserbox.h +++ b/src/gui/browserbox.h @@ -61,7 +61,7 @@ class BrowserBox : public gcn::Widget, public gcn::MouseListener /** * Sets the handler for links. */ - void setLinkHandler(LinkHandler* linkHandler); + void setLinkHandler(LinkHandler *linkHandler); /** * Sets the BrowserBox opacity. @@ -81,7 +81,7 @@ class BrowserBox : public gcn::Widget, public gcn::MouseListener /** * Adds a text row to the browser. */ - void addRow(const std::string& row); + void addRow(const std::string &row); /** * Remove all rows. @@ -91,13 +91,13 @@ class BrowserBox : public gcn::Widget, public gcn::MouseListener /** * Handles mouse actions. */ - void mousePress(int mx, int my, int button); - void mouseMotion(int mx, int my); + void mousePressed(gcn::MouseEvent &event); + void mouseMoved(gcn::MouseEvent &event); /** * Draws the browser box. */ - void draw(gcn::Graphics* graphics); + void draw(gcn::Graphics *graphics); /** * BrowserBox modes. diff --git a/src/gui/buddywindow.cpp b/src/gui/buddywindow.cpp index 145f0ad2..0ed383ce 100644 --- a/src/gui/buddywindow.cpp +++ b/src/gui/buddywindow.cpp @@ -61,9 +61,9 @@ BuddyWindow::BuddyWindow(): add(cancel); } -void BuddyWindow::action(const std::string &eventId, gcn::Widget *widget) +void BuddyWindow::action(const gcn::ActionEvent &event) { - if (eventId == "Talk") { + if (event.getId() == "Talk") { int selected = mListbox->getSelected(); if ( selected > -1 ) { @@ -71,7 +71,7 @@ void BuddyWindow::action(const std::string &eventId, gcn::Widget *widget) chatWindow->setInputText(who +": "); } } - else if (eventId == "Remove") { + else if (event.getId() == "Remove") { int selected = mListbox->getSelected(); if ( selected > -1 ) { @@ -79,7 +79,7 @@ void BuddyWindow::action(const std::string &eventId, gcn::Widget *widget) mBuddyList->removeBuddy(who); } } - else if (eventId == "Cancel") { + else if (event.getId() == "Cancel") { setVisible(false); } } diff --git a/src/gui/buddywindow.h b/src/gui/buddywindow.h index 8764d008..a3ca4de2 100644 --- a/src/gui/buddywindow.h +++ b/src/gui/buddywindow.h @@ -48,7 +48,7 @@ class BuddyWindow : public Window, public gcn::ActionListener /** * Performs action. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: BuddyList *mBuddyList; diff --git a/src/gui/button.cpp b/src/gui/button.cpp index 31f38593..0055c89a 100644 --- a/src/gui/button.cpp +++ b/src/gui/button.cpp @@ -37,7 +37,7 @@ ImageRect Button::button[4]; int Button::mInstances = 0; -Button::Button(const std::string& caption, const std::string &eventId, +Button::Button(const std::string& caption, const std::string &actionEventId, gcn::ActionListener *listener): gcn::Button(caption) { @@ -73,7 +73,7 @@ Button::Button(const std::string& caption, const std::string &eventId, } mInstances++; - setEventId(eventId); + setActionEventId(actionEventId); if (listener) { addActionListener(listener); } @@ -92,7 +92,8 @@ Button::~Button() } } -void Button::draw(gcn::Graphics* graphics) +void +Button::draw(gcn::Graphics *graphics) { int mode; @@ -102,7 +103,7 @@ void Button::draw(gcn::Graphics* graphics) else if (isPressed()) { mode = 2; } - else if (hasMouse()) { + else if (mHasMouse) { mode = 1; } else { diff --git a/src/gui/button.h b/src/gui/button.h index 36d8f7a1..1c2ec41b 100644 --- a/src/gui/button.h +++ b/src/gui/button.h @@ -40,7 +40,7 @@ class Button : public gcn::Button { /** * Constructor, sets the caption of the button to the given string. */ - Button(const std::string& caption, const std::string &eventId, + Button(const std::string& caption, const std::string &actionEventId, gcn::ActionListener *listener); /** diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 102dd49e..cb07da22 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -82,8 +82,8 @@ BuyDialog::BuyDialog(): mItemEffectLabel->setDimension(gcn::Rectangle(5, 150, 240, 14)); mItemDescLabel->setDimension(gcn::Rectangle(5, 169, 240, 14)); - mShopItemList->setEventId("item"); - mSlider->setEventId("slider"); + mShopItemList->setActionEventId("item"); + mSlider->setActionEventId("slider"); mShopItemList->addSelectionListener(this); mSlider->addActionListener(this); @@ -140,11 +140,11 @@ void BuyDialog::addItem(short id, int price) mShopItemList->adjustSize(); } -void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) +void BuyDialog::action(const gcn::ActionEvent &event) { int selectedItem = mShopItemList->getSelected(); - if (eventId == "quit") + if (event.getId() == "quit") { setVisible(false); current_npc = 0; @@ -158,12 +158,12 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) bool updateButtonsAndLabels = false; - if (eventId == "slider") + if (event.getId() == "slider") { mAmountItems = (int)(mSlider->getValue() * mMaxItems); updateButtonsAndLabels = true; } - else if (eventId == "+") + else if (event.getId() == "+") { if (mAmountItems < mMaxItems) { mAmountItems++; @@ -174,7 +174,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) mSlider->setValue(double(mAmountItems)/double(mMaxItems)); updateButtonsAndLabels = true; } - else if (eventId == "-") + else if (event.getId() == "-") { if (mAmountItems > 0) { mAmountItems--; @@ -188,7 +188,7 @@ void BuyDialog::action(const std::string &eventId, gcn::Widget *widget) // 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 && + else if (event.getId() == "buy" && (mAmountItems > 0 && mAmountItems <= mMaxItems)) { // XXX Convert for new server diff --git a/src/gui/buy.h b/src/gui/buy.h index b83b6f2f..13116b6e 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -73,7 +73,7 @@ class BuyDialog : public Window, public gcn::ActionListener, SelectionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); /** * Returns the number of items in the shop inventory. diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp index 4bbbb2ff..ae5c7358 100644 --- a/src/gui/buysell.cpp +++ b/src/gui/buysell.cpp @@ -52,13 +52,13 @@ BuySellDialog::BuySellDialog(): requestFocus(); } -void BuySellDialog::action(const std::string &eventId, gcn::Widget *widget) +void BuySellDialog::action(const gcn::ActionEvent &event) { - if (eventId == "Buy") { + if (event.getId() == "Buy") { current_npc->buy(); - } else if (eventId == "Sell") { + } else if (event.getId() == "Sell") { current_npc->sell(); - } else if (eventId == "Cancel") { + } else if (event.getId() == "Cancel") { current_npc = 0; } setVisible(false); diff --git a/src/gui/buysell.h b/src/gui/buysell.h index 7a90a869..97caf34b 100644 --- a/src/gui/buysell.h +++ b/src/gui/buysell.h @@ -47,7 +47,7 @@ class BuySellDialog : public Window, public gcn::ActionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); }; #endif diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index ec4dad2e..4c4b99e5 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -48,7 +48,7 @@ class CharDeleteConfirm : public ConfirmDialog { public: CharDeleteConfirm(CharSelectDialog *master); - void action(const std::string &eventId, gcn::Widget *widget); + void action(const gcn::ActionEvent &event); private: CharSelectDialog *master; }; @@ -60,13 +60,13 @@ CharDeleteConfirm::CharDeleteConfirm(CharSelectDialog *m): { } -void CharDeleteConfirm::action(const std::string &eventId, gcn::Widget *widget) +void CharDeleteConfirm::action(const gcn::ActionEvent &event) { - //ConfirmDialog::action(eventId); - if (eventId == "yes") { + //ConfirmDialog::action(event); + if (event.getId() == "yes") { master->attemptCharDelete(); } - ConfirmDialog::action(eventId, widget); + ConfirmDialog::action(event); } CharSelectDialog::CharSelectDialog(LockedArray *charInfo): @@ -122,9 +122,9 @@ CharSelectDialog::CharSelectDialog(LockedArray *charInfo): updatePlayerInfo(); } -void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget) +void CharSelectDialog::action(const gcn::ActionEvent &event) { - if (eventId == "ok" && n_character > 0) + if (event.getId() == "ok" && n_character > 0) { // Start game mNewCharButton->setEnabled(false); @@ -136,11 +136,11 @@ void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget) Net::AccountServer::Account::selectCharacter(mCharInfo->getPos()); mCharInfo->lock(); } - else if (eventId == "cancel") + else if (event.getId() == "cancel") { state = STATE_EXIT; } - else if (eventId == "new") + else if (event.getId() == "new") { if (n_character < MAX_SLOT + 1) { @@ -150,7 +150,7 @@ void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget) mCharInfo->unlock(); } } - else if (eventId == "delete") + else if (event.getId() == "delete") { // Delete character if (mCharInfo->getEntry()) @@ -158,11 +158,11 @@ void CharSelectDialog::action(const std::string &eventId, gcn::Widget *widget) new CharDeleteConfirm(this); } } - else if (eventId == "previous") + else if (event.getId() == "previous") { mCharInfo->prev(); } - else if (eventId == "next") + else if (event.getId() == "next") { mCharInfo->next(); } @@ -253,7 +253,7 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot): mCancelButton = new Button("Cancel", "cancel", this); mPlayerBox = new PlayerBox(mPlayer); - mNameField->setEventId("create"); + mNameField->setActionEventId("create"); int w = 200; int h = 150; @@ -298,9 +298,9 @@ CharCreateDialog::~CharCreateDialog() delete mPlayer; } -void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget) +void CharCreateDialog::action(const gcn::ActionEvent &event) { - if (eventId == "create") { + if (event.getId() == "create") { if (getName().length() >= 4) { // Attempt to create the character mCreateButton->setEnabled(false); @@ -322,20 +322,20 @@ void CharCreateDialog::action(const std::string &eventId, gcn::Widget *widget) "Your name needs to be at least 4 characters.", this); } } - else if (eventId == "cancel") { + else if (event.getId() == "cancel") { scheduleDelete(); } - else if (eventId == "nextcolor") { + else if (event.getId() == "nextcolor") { mPlayer->setHairColor((mPlayer->getHairColor() + 1) % NR_HAIR_COLORS); } - else if (eventId == "prevcolor") { + else if (event.getId() == "prevcolor") { int prevColor = mPlayer->getHairColor() + NR_HAIR_COLORS - 1; mPlayer->setHairColor(prevColor % NR_HAIR_COLORS); } - else if (eventId == "nextstyle") { + else if (event.getId() == "nextstyle") { mPlayer->setHairStyle((mPlayer->getHairStyle() + 1) % NR_HAIR_STYLES); } - else if (eventId == "prevstyle") { + else if (event.getId() == "prevstyle") { int prevStyle = mPlayer->getHairStyle() + NR_HAIR_STYLES - 1; mPlayer->setHairStyle(prevStyle % NR_HAIR_STYLES); } diff --git a/src/gui/char_select.h b/src/gui/char_select.h index 9d2d77da..d6dee8b5 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -49,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 gcn::ActionEvent &event); void updatePlayerInfo(); @@ -109,7 +109,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener */ ~CharCreateDialog(); - void action(const std::string &eventId, gcn::Widget *widget); + void action(const gcn::ActionEvent &event); std::string getName(); diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index 3dc252ab..d992c6dd 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -53,7 +53,7 @@ ChatWindow::ChatWindow(): loadWindowState(); mChatInput = new ChatInput(); - mChatInput->setEventId("chatinput"); + mChatInput->setActionEventId("chatinput"); mChatInput->addActionListener(this); mTextOutput = new BrowserBox(BrowserBox::AUTO_WRAP); @@ -180,9 +180,9 @@ ChatWindow::chatLog(CHATSKILL act) } void -ChatWindow::action(const std::string &eventId, gcn::Widget *widget) +ChatWindow::action(const gcn::ActionEvent &event) { - if (eventId == "chatinput") + if (event.getId() == "chatinput") { std::string message = mChatInput->getText(); @@ -360,9 +360,10 @@ ChatWindow::const_msg(CHATSKILL act) } void -ChatWindow::keyPress(const gcn::Key &key) +ChatWindow::keyPressed(gcn::KeyEvent &event) { - if (key.getValue() == key.DOWN && mCurHist != mHistory.end()) + if (event.getKey().getValue() == gcn::Key::DOWN && + mCurHist != mHistory.end()) { // Move forward through the history HistoryIterator prevHist = mCurHist++; @@ -374,8 +375,8 @@ ChatWindow::keyPress(const gcn::Key &key) mCurHist = prevHist; } } - else if (key.getValue() == key.UP && mCurHist != mHistory.begin() && - mHistory.size() > 0) + else if (event.getKey().getValue() == gcn::Key::UP && + mCurHist != mHistory.begin() && mHistory.size() > 0) { // Move backward through the history mCurHist--; diff --git a/src/gui/chat.h b/src/gui/chat.h index a0a3d1ec..963e5e98 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -138,7 +138,7 @@ class ChatWindow : public Window, public gcn::ActionListener, /** * Performs action. */ - void action(const std::string& actionId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); /** * Request focus for typing chat message. @@ -178,13 +178,16 @@ class ChatWindow : public Window, public gcn::ActionListener, chatSend(const std::string &nick, std::string msg); /** Called when key is pressed */ - void keyPress(const gcn::Key& key); + void + keyPressed(gcn::KeyEvent &event); /** Called to set current text */ - void setInputText(std::string input_str); + void + setInputText(std::string input_str); /** Override to reset mTmpVisible */ - void setVisible(bool visible); + void + setVisible(bool visible); private: bool mTmpVisible; diff --git a/src/gui/chatinput.cpp b/src/gui/chatinput.cpp index 52e91f3a..2aa5a159 100644 --- a/src/gui/chatinput.cpp +++ b/src/gui/chatinput.cpp @@ -28,7 +28,7 @@ ChatInput::ChatInput() setVisible(false); } -void ChatInput::lostFocus() +void ChatInput::focusLost() { setVisible(false); } diff --git a/src/gui/chatinput.h b/src/gui/chatinput.h index 9f543e24..59d0daf3 100644 --- a/src/gui/chatinput.h +++ b/src/gui/chatinput.h @@ -41,7 +41,7 @@ class ChatInput : public TextField * Called if the chat input loses focus. It will set itself to * invisible as result. */ - void lostFocus(); + void focusLost(); }; #endif diff --git a/src/gui/confirm_dialog.cpp b/src/gui/confirm_dialog.cpp index 5a70544f..0ff8be17 100644 --- a/src/gui/confirm_dialog.cpp +++ b/src/gui/confirm_dialog.cpp @@ -65,17 +65,18 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg, yesButton->requestFocus(); } -void ConfirmDialog::action(const std::string &eventId, gcn::Widget *widget) +void ConfirmDialog::action(const gcn::ActionEvent &event) { // Proxy button events to our listeners ActionListenerIterator i; for (i = mActionListeners.begin(); i != mActionListeners.end(); ++i) { - (*i)->action(eventId, widget); + (*i)->action(event); } // Can we receive anything else anyway? - if (eventId == "yes" || eventId == "no") { + if (event.getId() == "yes" || event.getId() == "no") + { scheduleDelete(); } } diff --git a/src/gui/confirm_dialog.h b/src/gui/confirm_dialog.h index 771ecc36..8728f83f 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 gcn::ActionEvent &event); }; #endif diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp index 7e977f1f..3627689a 100644 --- a/src/gui/connection.cpp +++ b/src/gui/connection.cpp @@ -38,7 +38,7 @@ namespace { ConnectionActionListener(unsigned char previousState): mPreviousState(previousState) {}; - void action(const std::string &eventId, gcn::Widget *widget) { + void action(const gcn::ActionEvent &event) { state = mPreviousState; } @@ -51,9 +51,11 @@ ConnectionDialog::ConnectionDialog(unsigned char previousState): { setContentSize(200, 100); - ConnectionActionListener *connectionListener = new ConnectionActionListener(previousState); + ConnectionActionListener *connectionListener = + new ConnectionActionListener(previousState); - Button *cancelButton = new Button("Cancel", "cancelButton", connectionListener); + Button *cancelButton = new Button("Cancel", "cancelButton", + connectionListener); mProgressBar = new ProgressBar(0.0, 200 - 10, 20, 128, 128, 128); gcn::Label *label = new gcn::Label("Connecting..."); diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index f8a4154e..563f380f 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -28,6 +28,8 @@ #include #include "button.h" +#include "gui.h" +#include "viewport.h" #include "../game.h" #include "../engine.h" @@ -72,15 +74,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 + viewport->getCameraX(); + int mouseTileY = mouseY / 32 + viewport->getCameraY(); 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) @@ -98,9 +100,9 @@ DebugWindow::logic() } void -DebugWindow::action(const std::string &eventId, gcn::Widget *widget) +DebugWindow::action(const gcn::ActionEvent &event) { - if (eventId == "close") + if (event.getId() == "close") { setVisible(false); } diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h index 61ef44e6..4fd33d83 100644 --- a/src/gui/debugwindow.h +++ b/src/gui/debugwindow.h @@ -53,7 +53,7 @@ class DebugWindow : public Window, public gcn::ActionListener /** * Performs action. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: gcn::Label *mMusicFileLabel, *mMapFileLabel; diff --git a/src/gui/gccontainer.cpp b/src/gui/gccontainer.cpp index 3b574622..c22ddfc9 100644 --- a/src/gui/gccontainer.cpp +++ b/src/gui/gccontainer.cpp @@ -55,8 +55,8 @@ void GCContainer::add(gcn::Widget *w, int x, int y, bool delChild) Container::add(w, x, y); } -void GCContainer::_announceDeath(gcn::Widget *w) +void GCContainer::death(const gcn::Event &event) { - mDeathList.remove(w); - Container::_announceDeath(w); + mDeathList.remove(event.getSource()); + Container::death(event); } diff --git a/src/gui/gccontainer.h b/src/gui/gccontainer.h index 46ebfefa..e27eaa96 100644 --- a/src/gui/gccontainer.h +++ b/src/gui/gccontainer.h @@ -32,9 +32,12 @@ class GCContainer : public gcn::Container { public: virtual ~GCContainer(); - virtual void add(gcn::Widget *w, bool delChild=true); - virtual void add(gcn::Widget *w, int x, int y, bool delChild=true); - virtual void _announceDeath(gcn::Widget *w); + + virtual void add(gcn::Widget *w, bool delChild = true); + + virtual void add(gcn::Widget *w, int x, int y, bool delChild = true); + + virtual void death(const gcn::Event &event); protected: typedef std::list Widgets; diff --git a/src/gui/help.cpp b/src/gui/help.cpp index e7429b29..0b010253 100644 --- a/src/gui/help.cpp +++ b/src/gui/help.cpp @@ -54,9 +54,9 @@ HelpWindow::HelpWindow(): setLocationRelativeTo(getParent()); } -void HelpWindow::action(const std::string &eventId, gcn::Widget *widget) +void HelpWindow::action(const gcn::ActionEvent &event) { - if (eventId == "close") + if (event.getId() == "close") { setVisible(false); } diff --git a/src/gui/help.h b/src/gui/help.h index 539ab31b..3c3715a0 100644 --- a/src/gui/help.h +++ b/src/gui/help.h @@ -48,7 +48,7 @@ class HelpWindow : public Window, public LinkHandler, /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); /** * Handles link action. diff --git a/src/gui/inttextbox.cpp b/src/gui/inttextbox.cpp index 92f21e5f..2a09f255 100644 --- a/src/gui/inttextbox.cpp +++ b/src/gui/inttextbox.cpp @@ -32,12 +32,15 @@ IntTextBox::IntTextBox(int i): { } -void IntTextBox::keyPress(const gcn::Key &key) +void +IntTextBox::keyPressed(gcn::KeyEvent &event) { + const gcn::Key &key = event.getKey(); + if (key.isNumber() || key.getValue() == gcn::Key::BACKSPACE || key.getValue() == gcn::Key::DELETE) { - gcn::TextBox::keyPress(key); + gcn::TextBox::keyPressed(event); } std::stringstream s(gcn::TextBox::getText()); diff --git a/src/gui/inttextbox.h b/src/gui/inttextbox.h index b199cb2f..b5d339ac 100644 --- a/src/gui/inttextbox.h +++ b/src/gui/inttextbox.h @@ -55,7 +55,8 @@ class IntTextBox : public TextBox /** * Responds to key presses. */ - void keyPress(const gcn::Key &key); + void + keyPressed(gcn::KeyEvent &event); private: int mMin; /**< Minimum value */ diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 7f9ba3b9..e533c16c 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -99,7 +99,7 @@ void InventoryWindow::logic() mWeightLabel->adjustSize(); } -void InventoryWindow::action(const std::string &eventId, gcn::Widget *widget) +void InventoryWindow::action(const gcn::ActionEvent &event) { Item *item = mItems->getItem(); @@ -107,7 +107,7 @@ void InventoryWindow::action(const std::string &eventId, gcn::Widget *widget) return; } - if (eventId == "use") { + if (event.getId() == "use") { if (item->isEquipment()) { if (item->isEquipped()) { player_node->unequipItem(item); @@ -120,7 +120,7 @@ void InventoryWindow::action(const std::string &eventId, gcn::Widget *widget) player_node->useItem(item); } } - else if (eventId == "drop") + else if (event.getId() == "drop") { // Choose amount of items to drop new ItemAmountWindow(AMOUNT_ITEM_DROP, this, item); @@ -155,11 +155,11 @@ void InventoryWindow::selectionChanged(const SelectionEvent &event) } } -void InventoryWindow::mouseClick(int x, int y, int button, int count) +void InventoryWindow::mouseClicked(gcn::MouseEvent &event) { - Window::mouseClick(x, y, button, count); + Window::mouseClicked(event); - if (button == gcn::MouseInput::RIGHT) + if (event.getButton() == gcn::MouseEvent::RIGHT) { Item *item = mItems->getItem(); @@ -168,16 +168,16 @@ void InventoryWindow::mouseClick(int x, int y, int button, int count) /* Convert relative to the window coordinates to * absolute screen coordinates. */ - int mx = x + getX(); - int my = y + getY(); + int mx = event.getX() + getX(); + int my = event.getY() + getY(); viewport->showPopup(mx, my, item); } } -void InventoryWindow::mouseMotion(int mx, int my) +void InventoryWindow::mouseDragged(gcn::MouseEvent &event) { int tmpWidth = getWidth(), tmpHeight = getHeight(); - Window::mouseMotion(mx, my); + Window::mouseDragged(event); if (getWidth() != tmpWidth || getHeight() != tmpHeight) { updateWidgets(); } diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h index d46e91e7..5ee89fef 100644 --- a/src/gui/inventorywindow.h +++ b/src/gui/inventorywindow.h @@ -55,11 +55,11 @@ class InventoryWindow : public Window, gcn::ActionListener, SelectionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string &eventId, gcn::Widget *widget); + void action(const gcn::ActionEvent &event); - void mouseClick(int x, int y, int button, int count); + void mouseClicked(gcn::MouseEvent &event); - void mouseMotion(int mx, int my); + void mouseDragged(gcn::MouseEvent &event); Item* getItem(); diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp index 5ebc0213..f72462f9 100644 --- a/src/gui/item_amount.cpp +++ b/src/gui/item_amount.cpp @@ -49,7 +49,7 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item): mItemAmountSlide->setDimension(gcn::Rectangle(5, 120, 180, 10)); // Set button events Id - mItemAmountSlide->setEventId("Slide"); + mItemAmountSlide->setActionEventId("Slide"); // Set position mItemAmountTextBox->setPosition(35, 10); @@ -75,11 +75,11 @@ ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item): switch (usage) { case AMOUNT_TRADE_ADD: setCaption("Select amount of items to trade."); - okButton->setEventId("AddTrade"); + okButton->setActionEventId("AddTrade"); break; case AMOUNT_ITEM_DROP: setCaption("Select amount of items to drop."); - okButton->setEventId("Drop"); + okButton->setActionEventId("Drop"); break; default: break; @@ -95,33 +95,33 @@ void ItemAmountWindow::resetAmount() mItemAmountTextBox->setInt(1); } -void ItemAmountWindow::action(const std::string &eventId, gcn::Widget *widget) +void ItemAmountWindow::action(const gcn::ActionEvent &event) { int amount = mItemAmountTextBox->getInt(); - if (eventId == "Cancel") + if (event.getId() == "Cancel") { scheduleDelete(); } - else if (eventId == "Drop") + else if (event.getId() == "Drop") { player_node->dropItem(mItem, mItemAmountTextBox->getInt()); scheduleDelete(); } - else if (eventId == "AddTrade") + else if (event.getId() == "AddTrade") { tradeWindow->tradeItem(mItem, mItemAmountTextBox->getInt()); scheduleDelete(); } - else if (eventId == "Plus") + else if (event.getId() == "Plus") { amount++; } - else if (eventId == "Minus") + else if (event.getId() == "Minus") { amount--; } - else if (eventId == "Slide") + else if (event.getId() == "Slide") { amount = static_cast(mItemAmountSlide->getValue()); } diff --git a/src/gui/item_amount.h b/src/gui/item_amount.h index a2a17575..01319012 100644 --- a/src/gui/item_amount.h +++ b/src/gui/item_amount.h @@ -54,7 +54,7 @@ class ItemAmountWindow : public Window, public gcn::ActionListener /** * Called when receiving actions from widget. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); /** * Sets default amount value. diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index 2c84b19b..308311b7 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -58,7 +58,8 @@ ItemContainer::~ItemContainer() mSelImg->decRef(); } -void ItemContainer::logic() +void +ItemContainer::logic() { gcn::Widget::logic(); @@ -70,7 +71,8 @@ void ItemContainer::logic() } } -void ItemContainer::draw(gcn::Graphics* graphics) +void +ItemContainer::draw(gcn::Graphics *graphics) { int gridWidth = 36; //(item icon width + 4) int gridHeight = 42; //(item icon height + 10) @@ -124,7 +126,8 @@ void ItemContainer::draw(gcn::Graphics* graphics) } } -void ItemContainer::setWidth(int width) +void +ItemContainer::setWidth(int width) { gcn::Widget::setWidth(width); @@ -140,17 +143,20 @@ void ItemContainer::setWidth(int width) setHeight((mMaxItems + columns - 1) / columns * gridHeight); } -Item* ItemContainer::getItem() +Item* +ItemContainer::getItem() { return mSelectedItem; } -void ItemContainer::selectNone() +void +ItemContainer::selectNone() { setSelectedItem(NULL); } -void ItemContainer::setSelectedItem(Item *item) +void +ItemContainer::setSelectedItem(Item *item) { if (mSelectedItem != item) { @@ -159,7 +165,8 @@ void ItemContainer::setSelectedItem(Item *item) } } -void ItemContainer::fireSelectionChangedEvent() +void +ItemContainer::fireSelectionChangedEvent() { SelectionEvent event(this); SelectionListeners::iterator i_end = mListeners.end(); @@ -171,14 +178,18 @@ void ItemContainer::fireSelectionChangedEvent() } } -void ItemContainer::mousePress(int mx, int my, int button) +void +ItemContainer::mousePressed(gcn::MouseEvent &event) { - int gridWidth = 36; //(item icon width + 4) - int gridHeight = 42; //(item icon height + 10) - int columns = getWidth() / gridWidth; + int button = event.getButton(); - if (button == gcn::MouseInput::LEFT || gcn::MouseInput::RIGHT) + if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT) { + int gridWidth = 36; //(item icon width + 4) + int gridHeight = 42; //(item icon height + 10) + int columns = getWidth() / gridWidth; + int mx = event.getX(); + int my = event.getY(); int index = mx / gridWidth + ((my / gridHeight) * columns); if (index > INVENTORY_SIZE) { diff --git a/src/gui/itemcontainer.h b/src/gui/itemcontainer.h index a2d5f0f7..8c548fcd 100644 --- a/src/gui/itemcontainer.h +++ b/src/gui/itemcontainer.h @@ -71,7 +71,7 @@ class ItemContainer : public gcn::Widget, public gcn::MouseListener /** * Handles mouse click. */ - void mousePress(int mx, int my, int button); + void mousePressed(gcn::MouseEvent &event); /** * Returns the selected item. diff --git a/src/gui/listbox.cpp b/src/gui/listbox.cpp index d4a2c6cb..a7f6df8d 100644 --- a/src/gui/listbox.cpp +++ b/src/gui/listbox.cpp @@ -31,8 +31,7 @@ #include ListBox::ListBox(gcn::ListModel *listModel): - gcn::ListBox(listModel), - mMousePressed(false) + gcn::ListBox(listModel) { } @@ -61,39 +60,19 @@ void ListBox::draw(gcn::Graphics *graphics) } } -void ListBox::setSelected(int selected) +void +ListBox::setSelected(int selected) { gcn::ListBox::setSelected(selected); fireSelectionChangedEvent(); } -void ListBox::mousePress(int x, int y, int button) +void +ListBox::mouseDragged(gcn::MouseEvent &event) { - 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); - } + mousePressed(event); } void ListBox::fireSelectionChangedEvent() diff --git a/src/gui/listbox.h b/src/gui/listbox.h index deca07cf..1d480eb1 100644 --- a/src/gui/listbox.h +++ b/src/gui/listbox.h @@ -48,9 +48,7 @@ class ListBox : 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); + void mouseDragged(gcn::MouseEvent &event); /** * Adds a listener to the list that's notified each time a change to @@ -81,8 +79,6 @@ class ListBox : public gcn::ListBox */ void fireSelectionChangedEvent(); - bool mMousePressed; /**< Keeps track of mouse pressed status. */ - std::list mListeners; }; diff --git a/src/gui/login.cpp b/src/gui/login.cpp index b8d4df2b..664074aa 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -43,9 +43,9 @@ WrongDataNoticeListener::setTarget(gcn::TextField *textField) } void -WrongDataNoticeListener::action(const std::string &eventId, gcn::Widget *widget) +WrongDataNoticeListener::action(const gcn::ActionEvent &event) { - if (eventId == "ok") + if (event.getId() == "ok") { // Reset the field mTarget->setText(""); @@ -85,8 +85,8 @@ LoginDialog::LoginDialog(LoginData *loginData): mKeepCheck->getX() + mKeepCheck->getWidth() + 10, 91 - mRegisterButton->getHeight() - 5); - mUserField->setEventId("ok"); - mPassField->setEventId("ok"); + mUserField->setActionEventId("ok"); + mPassField->setActionEventId("ok"); mUserField->addActionListener(this); mPassField->addActionListener(this); @@ -119,9 +119,9 @@ LoginDialog::~LoginDialog() } void -LoginDialog::action(const std::string &eventId, gcn::Widget *widget) +LoginDialog::action(const gcn::ActionEvent &event) { - if (eventId == "ok") + if (event.getId() == "ok") { // Check login if (mUserField->getText().empty()) @@ -142,11 +142,11 @@ LoginDialog::action(const std::string &eventId, gcn::Widget *widget) state = STATE_LOGIN_ATTEMPT; } } - else if (eventId == "cancel") + else if (event.getId() == "cancel") { state = STATE_EXIT; } - else if (eventId == "register") + else if (event.getId() == "register") { state = STATE_REGISTER; } diff --git a/src/gui/login.h b/src/gui/login.h index 6d510da7..05c0da31 100644 --- a/src/gui/login.h +++ b/src/gui/login.h @@ -38,7 +38,7 @@ class LoginData; class WrongDataNoticeListener : public gcn::ActionListener { public: void setTarget(gcn::TextField *textField); - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: gcn::TextField *mTarget; }; @@ -65,7 +65,7 @@ class LoginDialog : public Window, public gcn::ActionListener { /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: gcn::TextField *mUserField; diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp index a1b342f0..ba4c8e94 100644 --- a/src/gui/menuwindow.cpp +++ b/src/gui/menuwindow.cpp @@ -39,7 +39,7 @@ namespace { /** * Called when receiving actions from widget. */ - void action(const std::string &eventId, gcn::Widget *widget); + void action(const gcn::ActionEvent &event); } listener; } @@ -75,26 +75,26 @@ void MenuWindow::draw(gcn::Graphics *graphics) } -void MenuWindowListener::action(const std::string &eventId, gcn::Widget *widget) +void MenuWindowListener::action(const gcn::ActionEvent &event) { Window *window = NULL; - if (eventId == "Status") + if (event.getId() == "Status") { window = statusWindow; } - else if (eventId == "Equipment") + else if (event.getId() == "Equipment") { window = equipmentWindow; } - else if (eventId == "Inventory") + else if (event.getId() == "Inventory") { window = inventoryWindow; } - else if (eventId == "Skills") + else if (event.getId() == "Skills") { window = skillDialog; } - else if (eventId == "Setup") + else if (event.getId() == "Setup") { window = setupWindow; } diff --git a/src/gui/newskill.cpp b/src/gui/newskill.cpp index 7f5de543..6783a546 100644 --- a/src/gui/newskill.cpp +++ b/src/gui/newskill.cpp @@ -121,46 +121,46 @@ NewSkillDialog::NewSkillDialog(): setLocationRelativeTo(getParent()); } -void NewSkillDialog::action(const std::string &eventId, gcn::Widget *widget) +void NewSkillDialog::action(const gcn::ActionEvent &event) { - int osp = startPoint; - if (eventId == "close") + int osp = startPoint; + if (event.getId() == "close") { setVisible(false); } - else if (eventId == "g1") // weapons group 0-9 + else if (event.getId() == "g1") // weapons group 0-9 { startPoint =0; } - else if (eventId == "g2") // magic group 10-19 + else if (event.getId() == "g2") // magic group 10-19 { startPoint =10; } - else if (eventId == "g3") // craft group 20-29 + else if (event.getId() == "g3") // craft group 20-29 { startPoint =20; } - else if (eventId == "g4") // general group 30-39 + else if (event.getId() == "g4") // general group 30-39 { startPoint =30; } - else if (eventId == "g5") // combat group 40-49 + else if (event.getId() == "g5") // combat group 40-49 { startPoint =40; } - else if (eventId == "g6") // e. resist group 50-59 + else if (event.getId() == "g6") // e. resist group 50-59 { startPoint =50; } - else if (eventId == "g7") // s resist group 60-69 + else if (event.getId() == "g7") // s resist group 60-69 { startPoint =60; } - else if (eventId == "g8") // hunting group 70-79 + else if (event.getId() == "g8") // hunting group 70-79 { startPoint =70; } - else if (eventId == "g9") // stats group 80-89 + else if (event.getId() == "g9") // stats group 80-89 { startPoint =80; } diff --git a/src/gui/newskill.h b/src/gui/newskill.h index 224574bd..6e12169f 100644 --- a/src/gui/newskill.h +++ b/src/gui/newskill.h @@ -55,7 +55,7 @@ class NewSkillDialog : public Window, public gcn::ActionListener NewSkillDialog(); // action listener - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: void resetNSD(); // updates the values in the dialog box diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index 5b7ca439..2dd223bd 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -67,9 +67,9 @@ NpcTextDialog::addText(const std::string &text) } void -NpcTextDialog::action(const std::string &eventId, gcn::Widget *widget) +NpcTextDialog::action(const gcn::ActionEvent &event) { - if (eventId == "ok") + if (event.getId() == "ok") { setText(""); setVisible(false); diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h index 3ce1215d..869661c4 100644 --- a/src/gui/npc_text.h +++ b/src/gui/npc_text.h @@ -49,7 +49,7 @@ class NpcTextDialog : public Window, public gcn::ActionListener * Called when receiving actions from the widgets. */ void - action(const std::string& eventId, gcn::Widget* widget); + action(const gcn::ActionEvent &event); /** * Sets the text shows in the dialog. diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp index d1c3ddcb..1bcdc8ff 100644 --- a/src/gui/npclistdialog.cpp +++ b/src/gui/npclistdialog.cpp @@ -50,7 +50,7 @@ NpcListDialog::NpcListDialog(): cancelButton->getX() - 5 - okButton->getWidth(), cancelButton->getY()); - mItemList->setEventId("item"); + mItemList->setActionEventId("item"); mItemList->addActionListener(this); @@ -91,11 +91,11 @@ NpcListDialog::reset() } void -NpcListDialog::action(const std::string &eventId, gcn::Widget *widget) +NpcListDialog::action(const gcn::ActionEvent &event) { int choice = 0; - if (eventId == "ok") + if (event.getId() == "ok") { // Send the selected index back to the server int selectedIndex = mItemList->getSelected(); @@ -104,7 +104,7 @@ NpcListDialog::action(const std::string &eventId, gcn::Widget *widget) choice = selectedIndex + 1; } } - else if (eventId == "cancel") + else if (event.getId() == "cancel") { choice = 0xff; // 0xff means cancel } diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h index 03b76681..c09b0a8c 100644 --- a/src/gui/npclistdialog.h +++ b/src/gui/npclistdialog.h @@ -54,7 +54,7 @@ class NpcListDialog : public Window, public gcn::ActionListener, * Called when receiving actions from the widgets. */ void - action(const std::string& eventId, gcn::Widget* widget); + action(const gcn::ActionEvent &event); /** * Returns the number of items in the choices list. diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp index 4f9623d7..ca9d2a7b 100644 --- a/src/gui/ok_dialog.cpp +++ b/src/gui/ok_dialog.cpp @@ -55,17 +55,17 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg, okButton->requestFocus(); } -void OkDialog::action(const std::string &eventId, gcn::Widget *widget) +void OkDialog::action(const gcn::ActionEvent &event) { // Proxy button events to our listeners ActionListenerIterator i; for (i = mActionListeners.begin(); i != mActionListeners.end(); ++i) { - (*i)->action(eventId, widget); + (*i)->action(event); } // Can we receive anything else anyway? - if (eventId == "ok") { + if (event.getId() == "ok") { scheduleDelete(); } } diff --git a/src/gui/ok_dialog.h b/src/gui/ok_dialog.h index 8ae08955..a7b24a90 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 gcn::ActionEvent &event); }; #endif diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp index 5fbe79b7..fad156f1 100644 --- a/src/gui/playerbox.cpp +++ b/src/gui/playerbox.cpp @@ -28,7 +28,6 @@ #include "../resources/image.h" #include "../resources/resourcemanager.h" -#include "../resources/spriteset.h" #include "../utils/dtor.h" diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 70cd6dc4..4539e48e 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -108,13 +108,13 @@ RegisterDialog::~RegisterDialog() } void -RegisterDialog::action(const std::string &eventId, gcn::Widget *widget) +RegisterDialog::action(const gcn::ActionEvent &event) { - if (eventId == "cancel") + if (event.getId() == "cancel") { state = STATE_LOGIN; } - else if (eventId == "register") + else if (event.getId() == "register") { const std::string user = mUserField->getText(); logger->log("RegisterDialog::register Username is %s", user.c_str()); diff --git a/src/gui/register.h b/src/gui/register.h index 4c98788f..4ffe451f 100644 --- a/src/gui/register.h +++ b/src/gui/register.h @@ -56,7 +56,7 @@ class RegisterDialog : public Window, public gcn::ActionListener { /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); // Made them public to have the possibility to request focus // from external functions. diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index b0957f9e..c9878c84 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -87,8 +87,8 @@ SellDialog::SellDialog(): quitButton->setPosition(208, 186); - mShopItemList->setEventId("item"); - mSlider->setEventId("mSlider"); + mShopItemList->setActionEventId("item"); + mSlider->setActionEventId("mSlider"); mShopItemList->setPriceCheck(false); @@ -154,11 +154,11 @@ void SellDialog::addItem(Item *item, int price) mShopItemList->adjustSize(); } -void SellDialog::action(const std::string &eventId, gcn::Widget *widget) +void SellDialog::action(const gcn::ActionEvent &event) { int selectedItem = mShopItemList->getSelected(); - if (eventId == "item") + if (event.getId() == "item") { mAmountItems = 0; mSlider->setValue(0); @@ -182,7 +182,7 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) } mQuantityLabel->adjustSize(); } - else if (eventId == "quit") + else if (event.getId() == "quit") { setVisible(false); current_npc = 0; @@ -195,13 +195,13 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) bool updateButtonsAndLabels = false; - if (eventId == "mSlider") + if (event.getId() == "mSlider") { mAmountItems = (int)(mSlider->getValue() * mMaxItems); updateButtonsAndLabels = true; } - else if (eventId == "+") + else if (event.getId() == "+") { assert(mAmountItems < mMaxItems); mAmountItems++; @@ -209,7 +209,7 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) updateButtonsAndLabels = true; } - else if (eventId == "-") + else if (event.getId() == "-") { assert(mAmountItems > 0); mAmountItems--; @@ -218,7 +218,7 @@ void SellDialog::action(const std::string &eventId, gcn::Widget *widget) updateButtonsAndLabels = true; } - else if (eventId == "sell") + else if (event.getId() == "sell") { // Attempt sell assert(mAmountItems > 0 && mAmountItems <= mMaxItems); diff --git a/src/gui/sell.h b/src/gui/sell.h index ba324576..68bd7b8b 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -68,7 +68,7 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); /** * Updates labels according to selected item. diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp index bd17bff7..bf29f0d3 100644 --- a/src/gui/serverdialog.cpp +++ b/src/gui/serverdialog.cpp @@ -44,9 +44,9 @@ const short MAX_SERVERLIST = 5; void -DropDownListener::action(const std::string &eventId, gcn::Widget *widget) +DropDownListener::action(const gcn::ActionEvent &event) { - if (eventId == "ok") + if (event.getId() == "ok") { // Reset the text fields and give back the server dialog. mServerNameField->setText(""); @@ -56,13 +56,14 @@ DropDownListener::action(const std::string &eventId, gcn::Widget *widget) mServerNameField->requestFocus(); } - else if (eventId == "changeSelection") + else if (event.getId() == "changeSelection") { // Change the textField Values according to new selection if (currentSelectedIndex != mServersListBox->getSelected()) { Server myServer; - myServer = mServersListModel->getServer(mServersListBox->getSelected()); + myServer = mServersListModel->getServer( + mServersListBox->getSelected()); mServerNameField->setText(myServer.serverName); mServerPortField->setText(toString(myServer.port)); currentSelectedIndex = mServersListBox->getSelected(); @@ -131,7 +132,7 @@ ServerDialog::ServerDialog(LoginData *loginData): mMostUsedServersScrollArea, mMostUsedServersListBox); mDropDownListener = new DropDownListener(mServerNameField, mPortField, - mMostUsedServersListModel, mMostUsedServersListBox); + mMostUsedServersListModel, mMostUsedServersListBox); mOkButton = new Button("OK", "ok", this); mCancelButton = new Button("Cancel", "cancel", this); @@ -157,9 +158,9 @@ ServerDialog::ServerDialog(LoginData *loginData): mCancelButton->getX() - mOkButton->getWidth() - 5, 100 - mOkButton->getHeight() - 5); - mServerNameField->setEventId("ok"); - mPortField->setEventId("ok"); - mMostUsedServersDropDown->setEventId("changeSelection"); + mServerNameField->setActionEventId("ok"); + mPortField->setActionEventId("ok"); + mMostUsedServersDropDown->setActionEventId("changeSelection"); mServerNameField->addActionListener(this); mPortField->addActionListener(this); @@ -193,9 +194,9 @@ ServerDialog::~ServerDialog() } void -ServerDialog::action(const std::string &eventId, gcn::Widget *widget) +ServerDialog::action(const gcn::ActionEvent &event) { - if (eventId == "ok") + if (event.getId() == "ok") { // Check login if (mServerNameField->getText().empty() || mPortField->getText().empty()) @@ -240,7 +241,7 @@ ServerDialog::action(const std::string &eventId, gcn::Widget *widget) state = STATE_CONNECT_ACCOUNT; } } - else if (eventId == "cancel") + else if (event.getId() == "cancel") { state = STATE_EXIT; } diff --git a/src/gui/serverdialog.h b/src/gui/serverdialog.h index d907f340..2bb0609f 100644 --- a/src/gui/serverdialog.h +++ b/src/gui/serverdialog.h @@ -98,8 +98,7 @@ class DropDownListener : public gcn::ActionListener mServerPortField(serverPortField), mServersListModel(serversListModel), mServersListBox(serversListBox) {}; - void action(const std::string& eventId, - gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: short currentSelectedIndex; gcn::TextField *mServerNameField; @@ -132,7 +131,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 gcn::ActionEvent &event); private: gcn::TextField *mServerNameField; diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 78b10498..3add3a18 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -85,19 +85,19 @@ Setup::~Setup() for_each(mTabs.begin(), mTabs.end(), make_dtor(mTabs)); } -void Setup::action(const std::string& event, gcn::Widget *widget) +void Setup::action(const gcn::ActionEvent &event) { - if (event == "Apply") + if (event.getId() == "Apply") { setVisible(false); for_each(mTabs.begin(), mTabs.end(), std::mem_fun(&SetupTab::apply)); } - else if (event == "Cancel") + else if (event.getId() == "Cancel") { setVisible(false); for_each(mTabs.begin(), mTabs.end(), std::mem_fun(&SetupTab::cancel)); } - else if (event == "Reset Windows") + else if (event.getId() == "Reset Windows") { statusWindow->resetToDefaultSize(); minimap->resetToDefaultSize(); diff --git a/src/gui/setup.h b/src/gui/setup.h index 6601ce3d..77173367 100644 --- a/src/gui/setup.h +++ b/src/gui/setup.h @@ -54,7 +54,7 @@ class Setup : public Window, public gcn::ActionListener * Event handling method. */ void - action(const std::string& eventId, gcn::Widget* widget); + action(const gcn::ActionEvent &event); private: std::list mTabs; diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp index db88ff64..e5aadf80 100644 --- a/src/gui/setup_audio.cpp +++ b/src/gui/setup_audio.cpp @@ -46,8 +46,8 @@ Setup_Audio::Setup_Audio(): gcn::Label *sfxLabel = new gcn::Label("Sfx volume"); gcn::Label *musicLabel = new gcn::Label("Music volume"); - mSfxSlider->setEventId("sfx"); - mMusicSlider->setEventId("music"); + mSfxSlider->setActionEventId("sfx"); + mMusicSlider->setActionEventId("music"); mSfxSlider->addActionListener(this); mMusicSlider->addActionListener(this); @@ -108,14 +108,14 @@ void Setup_Audio::cancel() config.setValue("musicVolume", mMusicVolume); } -void Setup_Audio::action(const std::string& event, gcn::Widget *widget) +void Setup_Audio::action(const gcn::ActionEvent &event) { - if (event == "sfx") + if (event.getId() == "sfx") { config.setValue("sfxVolume", (int)mSfxSlider->getValue()); sound.setSfxVolume((int)mSfxSlider->getValue()); } - else if (event == "music") + else if (event.getId() == "music") { config.setValue("musicVolume", (int)mMusicSlider->getValue()); sound.setMusicVolume((int)mMusicSlider->getValue()); diff --git a/src/gui/setup_audio.h b/src/gui/setup_audio.h index f09f62da..6e722f74 100644 --- a/src/gui/setup_audio.h +++ b/src/gui/setup_audio.h @@ -38,7 +38,7 @@ class Setup_Audio : public SetupTab, public gcn::ActionListener void apply(); void cancel(); - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: int mMusicVolume, mSfxVolume; diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp index 685d88cf..56f411d7 100644 --- a/src/gui/setup_joystick.cpp +++ b/src/gui/setup_joystick.cpp @@ -45,7 +45,6 @@ Setup_Joystick::Setup_Joystick(): mOriginalJoystickEnabled = (int)config.getValue("joystickEnabled", 0) != 0; mJoystickEnabled->setMarked(mOriginalJoystickEnabled); - mJoystickEnabled->setEventId("joystickEnabled"); mJoystickEnabled->addActionListener(this); add(mCalibrateLabel); @@ -53,13 +52,13 @@ Setup_Joystick::Setup_Joystick(): add(mJoystickEnabled); } -void Setup_Joystick::action(const std::string &event, gcn::Widget *widget) +void Setup_Joystick::action(const gcn::ActionEvent &event) { if (!joystick) { return; } - if (event == "joystickEnabled") + if (event.getSource() == mJoystickEnabled) { joystick->setEnabled(mJoystickEnabled->isMarked()); } diff --git a/src/gui/setup_joystick.h b/src/gui/setup_joystick.h index 4cc2b3d9..6d3ad129 100644 --- a/src/gui/setup_joystick.h +++ b/src/gui/setup_joystick.h @@ -38,7 +38,7 @@ class Setup_Joystick : public SetupTab, public gcn::ActionListener void apply(); void cancel(); - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); private: gcn::Label *mCalibrateLabel; diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 7a4aae03..8930af3e 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -158,16 +158,16 @@ Setup_Video::Setup_Video(): mFpsSlider->setEnabled(mFps > 0); mFpsCheckBox->setMarked(mFps > 0); - mCustomCursorCheckBox->setEventId("customcursor"); - mAlphaSlider->setEventId("guialpha"); - mFpsCheckBox->setEventId("fpslimitcheckbox"); - mFpsSlider->setEventId("fpslimitslider"); - mScrollRadiusSlider->setEventId("scrollradiusslider"); - mScrollRadiusField->setEventId("scrollradiusfield"); - mScrollLazinessSlider->setEventId("scrolllazinessslider"); - mScrollLazinessField->setEventId("scrolllazinessfield"); - mOverlayDetailSlider->setEventId("overlaydetailslider"); - mOverlayDetailField->setEventId("overlaydetailfield"); + mCustomCursorCheckBox->setActionEventId("customcursor"); + mAlphaSlider->setActionEventId("guialpha"); + mFpsCheckBox->setActionEventId("fpslimitcheckbox"); + mFpsSlider->setActionEventId("fpslimitslider"); + mScrollRadiusSlider->setActionEventId("scrollradiusslider"); + mScrollRadiusField->setActionEventId("scrollradiusfield"); + mScrollLazinessSlider->setActionEventId("scrolllazinessslider"); + mScrollLazinessField->setActionEventId("scrolllazinessfield"); + mOverlayDetailSlider->setActionEventId("overlaydetailslider"); + mOverlayDetailField->setActionEventId("overlaydetailfield"); mCustomCursorCheckBox->addActionListener(this); mAlphaSlider->addActionListener(this); @@ -331,37 +331,37 @@ void Setup_Video::cancel() config.setValue("opengl", mOpenGLEnabled ? 1 : 0); } -void Setup_Video::action(const std::string &event, gcn::Widget *widget) +void Setup_Video::action(const gcn::ActionEvent &event) { - if (event == "guialpha") + if (event.getId() == "guialpha") { config.setValue("guialpha", mAlphaSlider->getValue()); } - else if (event == "customcursor") + else if (event.getId() == "customcursor") { config.setValue("customcursor", mCustomCursorCheckBox->isMarked() ? 1 : 0); } - else if (event == "fpslimitslider") + else if (event.getId() == "fpslimitslider") { - mFps = (int)mFpsSlider->getValue(); + mFps = (int) mFpsSlider->getValue(); mFpsField->setText(toString(mFps)); } - else if (event == "scrollradiusslider") + else if (event.getId() == "scrollradiusslider") { - int val = (int)mScrollRadiusSlider->getValue(); + int val = (int) mScrollRadiusSlider->getValue(); mScrollRadiusField->setText(toString(val)); config.setValue("ScrollRadius", val); } - else if (event == "scrolllazinessslider") + else if (event.getId() == "scrolllazinessslider") { - int val = (int)mScrollLazinessSlider->getValue(); + int val = (int) mScrollLazinessSlider->getValue(); mScrollLazinessField->setText(toString(val)); config.setValue("ScrollLaziness", val); } - else if (event == "overlaydetailslider") + else if (event.getId() == "overlaydetailslider") { - int val = (int)mOverlayDetailSlider->getValue(); + int val = (int) mOverlayDetailSlider->getValue(); switch (val) { case 0: @@ -376,11 +376,11 @@ void Setup_Video::action(const std::string &event, gcn::Widget *widget) } config.setValue("OverlayDetail", val); } - else if (event == "fpslimitcheckbox") + else if (event.getId() == "fpslimitcheckbox") { if (mFpsCheckBox->isMarked()) { - mFps = (int)mFpsSlider->getValue(); + mFps = (int) mFpsSlider->getValue(); } else { @@ -393,7 +393,8 @@ void Setup_Video::action(const std::string &event, gcn::Widget *widget) } } -void Setup_Video::keyPress(const gcn::Key &key) +void +Setup_Video::keyPressed(gcn::KeyEvent &event) { std::stringstream tempFps(mFpsField->getText()); diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h index 482d1c65..095fdbd6 100644 --- a/src/gui/setup_video.h +++ b/src/gui/setup_video.h @@ -41,10 +41,11 @@ class Setup_Video : public SetupTab, public gcn::ActionListener, void apply(); void cancel(); - void action(const std::string &eventId, gcn::Widget *widget); + void action(const gcn::ActionEvent &event); /** Called when key is pressed */ - void keyPress(const gcn::Key& key); + void + keyPressed(gcn::KeyEvent &event); private: bool mFullScreenEnabled; diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp index 4821067c..8cf0b639 100644 --- a/src/gui/shoplistbox.cpp +++ b/src/gui/shoplistbox.cpp @@ -125,11 +125,12 @@ void ShopListBox::setSelected(int selected) fireSelectionChangedEvent(); } -void ShopListBox::mousePress(int x, int y, int button) +void ShopListBox::mousePressed(gcn::MouseEvent &event) { - if (button == gcn::MouseInput::LEFT && hasMouse()) + if (event.getButton() == gcn::MouseEvent::LEFT) { bool enoughMoney = false; + int y = event.getY(); if (mShopItems && mPriceCheck) { @@ -145,7 +146,6 @@ void ShopListBox::mousePress(int x, int y, int button) { setSelected(y / mRowHeight); generateAction(); - mMousePressed = true; } } } diff --git a/src/gui/shoplistbox.h b/src/gui/shoplistbox.h index 476564b2..1cfb183b 100644 --- a/src/gui/shoplistbox.h +++ b/src/gui/shoplistbox.h @@ -54,7 +54,7 @@ class ShopListBox : public ListBox */ void draw(gcn::Graphics *graphics); - void mousePress(int x, int y, int button); + void mousePressed(gcn::MouseEvent &event); /** * Adds a listener to the list that's notified each time a change to diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 4f552fd7..1b00a732 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -74,7 +74,7 @@ SkillDialog::SkillDialog(): mUseButton->setEnabled(false); mCloseButton = new Button("Close", "close", this); - mSkillListBox->setEventId("skill"); + mSkillListBox->setActionEventId("skill"); skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); skillScrollArea->setDimension(gcn::Rectangle(5, 5, 230, 180)); @@ -103,9 +103,9 @@ SkillDialog::~SkillDialog() cleanList(); } -void SkillDialog::action(const std::string &eventId, gcn::Widget *widget) +void SkillDialog::action(const gcn::ActionEvent &event) { - if (eventId == "inc") + if (event.getId() == "inc") { // Increment skill int selectedSkill = mSkillListBox->getSelected(); @@ -114,13 +114,13 @@ void SkillDialog::action(const std::string &eventId, gcn::Widget *widget) player_node->raiseSkill(mSkillList[selectedSkill]->id); } } - else if (eventId == "skill") + else if (event.getId() == "skill") { mIncButton->setEnabled( mSkillListBox->getSelected() > -1 && player_node->mSkillPoint > 0); } - else if (eventId == "close") + else if (event.getId() == "close") { setVisible(false); } diff --git a/src/gui/skill.h b/src/gui/skill.h index 5555fec4..ed1257b0 100644 --- a/src/gui/skill.h +++ b/src/gui/skill.h @@ -57,7 +57,7 @@ class SkillDialog : public Window, public gcn::ActionListener, */ ~SkillDialog(); - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); void update(); diff --git a/src/gui/status.cpp b/src/gui/status.cpp index bba9f045..9c60752d 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -338,8 +338,10 @@ void StatusWindow::draw(gcn::Graphics *g) Window::draw(g); } -void StatusWindow::action(const std::string &eventId, gcn::Widget *widget) +void StatusWindow::action(const gcn::ActionEvent &event) { + const std::string &eventId = event.getId(); + // Stats Part if (eventId.length() == 3) { diff --git a/src/gui/status.h b/src/gui/status.h index 43dfe8c2..37f8a648 100644 --- a/src/gui/status.h +++ b/src/gui/status.h @@ -51,7 +51,7 @@ class StatusWindow : public Window, public gcn::ActionListener { /** * Called when receiving actions from widget. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); /** * Draw this window diff --git a/src/gui/tabbedcontainer.cpp b/src/gui/tabbedcontainer.cpp index e3d2527b..75f9f3cf 100644 --- a/src/gui/tabbedcontainer.cpp +++ b/src/gui/tabbedcontainer.cpp @@ -78,9 +78,9 @@ void TabbedContainer::logic() Container::logic(); } -void TabbedContainer::action(const std::string &event, gcn::Widget *widget) +void TabbedContainer::action(const gcn::ActionEvent &event) { - std::stringstream ss(event); + std::stringstream ss(event.getId()); int tabNo; ss >> tabNo; diff --git a/src/gui/tabbedcontainer.h b/src/gui/tabbedcontainer.h index 453d8374..2dc017ae 100644 --- a/src/gui/tabbedcontainer.h +++ b/src/gui/tabbedcontainer.h @@ -43,7 +43,7 @@ class TabbedContainer : public gcn::Container, public gcn::ActionListener void logic(); - void action(const std::string &event, gcn::Widget *widget); + void action(const gcn::ActionEvent &event); void setOpaque(bool opaque); diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 82262563..14b1afa6 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -256,11 +256,11 @@ void TradeWindow::selectionChanged(const SelectionEvent &event) } } -void TradeWindow::action(const std::string &eventId, gcn::Widget *widget) +void TradeWindow::action(const gcn::ActionEvent &event) { Item *item = inventoryWindow->getItem(); - if (eventId == "add") + if (event.getId() == "add") { if (!item) { @@ -286,14 +286,14 @@ void TradeWindow::action(const std::string &eventId, gcn::Widget *widget) new ItemAmountWindow(AMOUNT_TRADE_ADD, this, item); } } - else if (eventId == "cancel") + else if (event.getId() == "cancel") { // XXX Convert for new server /* MessageOut outMsg(CMSG_TRADE_CANCEL_REQUEST); */ } - else if (eventId == "ok") + else if (event.getId() == "ok") { std::stringstream tempMoney(mMoneyField->getText()); int tempInt; @@ -317,7 +317,7 @@ void TradeWindow::action(const std::string &eventId, gcn::Widget *widget) MessageOut outMsg(CMSG_TRADE_ADD_COMPLETE); */ } - else if (eventId == "trade") + else if (event.getId() == "trade") { // XXX Convert for new server /* diff --git a/src/gui/trade.h b/src/gui/trade.h index ebd05a52..1c64c255 100644 --- a/src/gui/trade.h +++ b/src/gui/trade.h @@ -111,7 +111,7 @@ class TradeWindow : public Window, gcn::ActionListener, SelectionListener /** * Called when receiving actions from the widgets. */ - void action(const std::string &eventId, gcn::Widget *widget); + void action(const gcn::ActionEvent &event); private: typedef std::auto_ptr InventoryPtr; diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 73e4489e..d41dfe13 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -132,9 +132,9 @@ void UpdaterWindow::enable() mPlayButton->requestFocus(); } -void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) +void UpdaterWindow::action(const gcn::ActionEvent &event) { - if (eventId == "cancel") + if (event.getId() == "cancel") { // Register the user cancel mUserCancel=true; @@ -148,7 +148,7 @@ void UpdaterWindow::action(const std::string &eventId, gcn::Widget *widget) mDownloadStatus = UPDATE_ERROR; } } - else if (eventId == "play") + else if (event.getId() == "play") { state = STATE_LOGIN; } diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index 0d1493ee..8c54be27 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -79,7 +79,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener */ void loadNews(); - void action(const std::string& eventId, gcn::Widget* widget); + void action(const gcn::ActionEvent &event); void logic(); diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 75a16865..671ababa 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -47,6 +47,7 @@ Viewport::Viewport(): mCameraX(0), mCameraY(0), mShowDebugPath(false), + mPlayerFollowMouse(false), mPopupActive(false) { setOpaque(false); @@ -243,7 +244,7 @@ Viewport::logic() } void -Viewport::mousePress(int mx, int my, int button) +Viewport::mousePressed(gcn::MouseEvent &event) { // Check if we are alive and kickin' if (!mMap || !player_node || player_node->mAction == Being::DEAD) @@ -255,11 +256,11 @@ Viewport::mousePress(int mx, int my, int button) mPlayerFollowMouse = false; - int tilex = (mx + mCameraX) / 32; - int tiley = (my + mCameraY) / 32; + int tilex = (event.getX() + mCameraX) / 32; + int tiley = (event.getY() + mCameraY) / 32; // Right click might open a popup - if (button == gcn::MouseInput::RIGHT) + if (event.getButton() == gcn::MouseEvent::RIGHT) { Being *being; FloorItem *floorItem; @@ -267,12 +268,12 @@ Viewport::mousePress(int mx, int my, int button) if ((being = beingManager->findBeing(tilex, tiley)) && being->getType() != Being::LOCALPLAYER) { - showPopup(mx, my, being); + showPopup(event.getX(), event.getY(), being); return; } else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley))) { - showPopup(mx, my, floorItem); + showPopup(event.getX(), event.getY(), floorItem); return; } } @@ -286,7 +287,7 @@ Viewport::mousePress(int mx, int my, int button) } // Left click can cause different actions - if (button == gcn::MouseInput::LEFT) + if (event.getButton() == gcn::MouseEvent::LEFT) { FloorItem *item; @@ -302,13 +303,13 @@ Viewport::mousePress(int mx, int my, int button) Uint8 *keys = SDL_GetKeyState(NULL); if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT])) { - player_node->setDestination(mx + mCameraX, my + mCameraY); + player_node->setDestination(event.getX() + mCameraX, + event.getY() + mCameraY); } mPlayerFollowMouse = true; } } - - if (button == gcn::MouseInput::MIDDLE) + else if (event.getButton() == gcn::MouseEvent::MIDDLE) { // Find the being nearest to the clicked position Being *target = beingManager->findNearestLivingBeing( @@ -323,19 +324,20 @@ Viewport::mousePress(int mx, int my, int button) } void -Viewport::mouseMotion(int mx, int my) +Viewport::mouseMoved(gcn::MouseEvent &event) { if (!mMap || !player_node) return; if (mPlayerFollowMouse && mWalkTime == player_node->mWalkTime) { - player_node->setDestination(mx + mCameraX, my + mCameraY); + player_node->setDestination(event.getX() + mCameraX, + event.getY() + mCameraY); } } void -Viewport::mouseRelease(int mx, int my, int button) +Viewport::mouseReleased(gcn::MouseEvent &event) { mPlayerFollowMouse = false; } diff --git a/src/gui/viewport.h b/src/gui/viewport.h index df78b1da..80475fbf 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -79,31 +79,33 @@ class Viewport : public WindowContainer, public gcn::MouseListener, /** * Toggles whether the path debug graphics are shown */ - void toggleDebugPath() { mShowDebugPath = !mShowDebugPath; } + void + toggleDebugPath() { mShowDebugPath = !mShowDebugPath; } /** * Handles mouse press on map. */ void - mousePress(int mx, int my, int button); + mousePressed(gcn::MouseEvent &event); /** * Handles mouse move on map */ void - mouseMotion(int mx, int my); + mouseMoved(gcn::MouseEvent &event); /** * Handles mouse button release on map. */ void - mouseRelease(int mx, int my, int button); + mouseReleased(gcn::MouseEvent &event); /** * Shows a popup for an item. * TODO Find some way to get rid of Item here */ - void showPopup(int x, int y, Item *item); + void + showPopup(int x, int y, Item *item); /** * A relevant config option changed. @@ -111,6 +113,18 @@ class Viewport : public WindowContainer, public gcn::MouseListener, void optionChanged(const std::string &name); + /** + * Returns camera x offset in tiles. + */ + int + getCameraX() { return mCameraX; } + + /** + * Returns camera y offset in tiles. + */ + int + getCameraY() { return mCameraY; } + private: /** * Shows a popup for a floor item. @@ -131,8 +145,8 @@ class Viewport : public WindowContainer, public gcn::MouseListener, int mScrollLaziness; float mViewX; /**< Current viewpoint in pixels. */ float mViewY; /**< Current viewpoint in pixels. */ - int mCameraX; - int mCameraY; + int mCameraX; /**< Current viewpoint in tiles. */ + int mCameraY; /**< Current viewpoint in tiles. */ bool mShowDebugPath; /**< Show a path from player to pointer. */ bool mPlayerFollowMouse; diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 1960d6ca..bb60c6ff 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -197,6 +197,12 @@ void Window::setContentHeight(int height) resizeToContent(); } +void Window::setContentSize(int width, int height) +{ + setContentWidth(width); + setContentHeight(height); +} + void Window::setLocationRelativeTo(gcn::Widget *widget) { int wx, wy; @@ -209,12 +215,6 @@ void Window::setLocationRelativeTo(gcn::Widget *widget) getY() + (wy + (widget->getHeight() - getHeight()) / 2 - y)); } -void Window::setContentSize(int width, int height) -{ - setContentWidth(width); - setContentHeight(height); -} - void Window::setMinWidth(unsigned int width) { mMinWinWidth = width; @@ -282,86 +282,60 @@ void Window::add(gcn::Widget *w, int x, int y, bool delChild) mChrome->add(w, x, y, delChild); } -void Window::mousePress(int x, int y, int button) +void Window::mousePressed(gcn::MouseEvent &event) { // Let Guichan move window to top and figure out title bar drag - gcn::Window::mousePress(x, y, button); + gcn::Window::mousePressed(event); - // If the mouse is not inside the content, the press must have been on the - // border, and is a candidate for a resize. - if (isResizable() && button == 1 && + int x = event.getX(); + int y = event.getY(); + + // Activate resizing if the left mouse button was pressed on the grip + mMouseResize = + isResizable() && + event.getButton() == gcn::MouseEvent::LEFT && getGripDimension().isPointInRect(x, y) && - !getChildrenArea().isPointInRect(x, y) && - hasMouse() && - !(mMouseDrag && y > (int)getPadding())) - { - mMouseResize = true; - mMouseXOffset = x; - mMouseYOffset = y; - } + !getChildrenArea().isPointInRect(x, y); } -void Window::mouseMotion(int x, int y) +void Window::mouseDragged(gcn::MouseEvent &event) { - if (mMouseDrag || mMouseResize) + // Let Guichan handle title bar drag + gcn::Window::mouseDragged(event); + + // Keep guichan window inside screen + int newX = std::max(0, getX()); + int newY = std::max(0, getY()); + newX = std::min(windowContainer->getWidth() - getWidth(), newX); + newY = std::min(windowContainer->getHeight() - getHeight(), newY); + setPosition(newX, newY); + + if (mMouseResize && !mIsMoving) { - int dx = x - mMouseXOffset; - int dy = y - mMouseYOffset; gcn::Rectangle newDim = getDimension(); - // Change the dimension according to dragging and moving - if (mMouseResize && isResizable()) - { - // We're dragging bottom right - newDim.height += dy; - newDim.width += dx; - } - else if (mMouseDrag && isMovable()) - { - newDim.x += dx; - newDim.y += dy; - } + // We're dragging bottom right + newDim.width += event.getX() - mDragOffsetX; + newDim.height += event.getY() - mDragOffsetY; - // Keep guichan window inside screen + // Keep guichan window inside screen (supports resizing any side) if (newDim.x < 0) { - if (mMouseResize) - { - newDim.width += newDim.x; - } - + newDim.width += newDim.x; newDim.x = 0; } if (newDim.y < 0) { - if (mMouseResize) - { - newDim.height += newDim.y; - } - + newDim.height += newDim.y; newDim.y = 0; } if (newDim.x + newDim.width > windowContainer->getWidth()) { - if (mMouseResize) - { - newDim.width = windowContainer->getWidth() - newDim.x; - } - else - { - newDim.x = windowContainer->getWidth() - newDim.width; - } + newDim.width = windowContainer->getWidth() - newDim.x; } if (newDim.y + newDim.height > windowContainer->getHeight()) { - if (mMouseResize) - { - newDim.height = windowContainer->getHeight() - newDim.y; - } - else - { - newDim.y = windowContainer->getHeight() - newDim.height; - } + newDim.height = windowContainer->getHeight() - newDim.y; } // Keep the window at least its minimum size @@ -383,18 +357,9 @@ void Window::mouseMotion(int x, int y) newDim.height = mMaxWinHeight; } - // Snap window to edges - //if (x < snapSize) x = 0; - //if (y < snapSize) y = 0; - //if (x + winWidth + snapSize > screen->w) x = screen->w - winWidth; - //if (y + winHeight + snapSize > screen->h) y = screen->h - winHeight; - // Update mouse offset when dragging bottom or right border - if (mMouseResize) - { - mMouseYOffset += newDim.height - getHeight(); - mMouseXOffset += newDim.width - getWidth(); - } + mDragOffsetX += newDim.width - getWidth(); + mDragOffsetY += newDim.height - getHeight(); // Set the new window and content dimensions setDimension(newDim); @@ -403,16 +368,6 @@ void Window::mouseMotion(int x, int y) } } -void -Window::mouseRelease(int x, int y, int button) -{ - if (button == 1) - { - mMouseResize = false; - mMouseDrag = false; - } -} - gcn::Rectangle Window::getGripDimension() { diff --git a/src/gui/window.h b/src/gui/window.h index 158035c0..9ac02287 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -77,12 +77,12 @@ class Window : public gcn::Window /** * Adds a widget to the window. */ - void add(gcn::Widget *wi, bool delChild=true); + void add(gcn::Widget *wi, bool delChild = true); /** * Adds a widget to the window and also specifices its position. */ - void add(gcn::Widget *w, int x, int y, bool delChild=true); + void add(gcn::Widget *w, int x, int y, bool delChild = true); /** * Sets the width of the window contents. @@ -95,14 +95,14 @@ class Window : public gcn::Window void setContentHeight(int height); /** - * Sets the location relative to the given widget. + * Sets the size of this window. */ - void setLocationRelativeTo(gcn::Widget* widget); + void setContentSize(int width, int height); /** - * Sets the size of this window. + * Sets the location relative to the given widget. */ - void setContentSize(int width, int height); + void setLocationRelativeTo(gcn::Widget *widget); /** * Sets whether of not the window can be resized. @@ -146,7 +146,7 @@ class Window : public gcn::Window */ bool isSticky(); - /** + /** * Overloads window setVisible by guichan to allow sticky window * Handling */ @@ -171,9 +171,8 @@ class Window : public gcn::Window * Window dragging and resizing mouse related. These methods also makes * sure the window is not dragged/resized outside of the screen. */ - void mousePress(int x, int y, int button); - void mouseMotion(int mx, int my); - void mouseRelease(int x, int y, int button); + void mousePressed(gcn::MouseEvent &event); + void mouseDragged(gcn::MouseEvent &event); /** * Gets the position of the resize grip. diff --git a/src/main.cpp b/src/main.cpp index b9eeaeb5..3a448494 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,7 +110,8 @@ Net::Connection *chatServerConnection = 0; namespace { struct ErrorListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) { + void action(const gcn::ActionEvent &event) + { state = STATE_CHOOSE_SERVER; } } errorListener; @@ -713,15 +714,16 @@ int main(int argc, char *argv[]) logger->log("State: CHAR_SELECT"); currentDialog = new CharSelectDialog(&charInfo); - if (((CharSelectDialog*)currentDialog)-> + if (((CharSelectDialog*) currentDialog)-> selectByName(options.playername)) options.chooseDefault = true; else - ((CharSelectDialog*)currentDialog)->selectByName( + ((CharSelectDialog*) currentDialog)->selectByName( config.getValue("lastCharacter", "")); if (options.chooseDefault) - ((CharSelectDialog*)currentDialog)->action("ok", NULL); + ((CharSelectDialog*) currentDialog)->action( + gcn::ActionEvent(NULL, "ok")); break; case STATE_ERROR: diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index f16037cf..327edea3 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -56,7 +56,7 @@ extern Window *buySellDialog; namespace { struct WeightListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) + void action(const gcn::ActionEvent &event) { weightNotice = NULL; } @@ -70,7 +70,7 @@ namespace { namespace { struct DeathListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) + void action(const gcn::ActionEvent &event) { player_node->revive(); deathNotice = NULL; diff --git a/src/net/tradehandler.cpp b/src/net/tradehandler.cpp index 2ebc160f..b3e80675 100644 --- a/src/net/tradehandler.cpp +++ b/src/net/tradehandler.cpp @@ -41,9 +41,9 @@ std::string tradePartnerName; namespace { struct RequestTradeListener : public gcn::ActionListener { - void action(const std::string &eventId, gcn::Widget *widget) + void action(const gcn::ActionEvent &event) { - player_node->tradeReply(eventId == "yes"); + player_node->tradeReply(event.getId() == "yes"); }; } listener; } diff --git a/tools/Purger.java b/tools/Purger.java deleted file mode 100644 index 1751c8de..00000000 --- a/tools/Purger.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Purger (c) 2006 Eugenio Favalli - * License: GPL, v2 or later - */ - -import java.io.*; -import java.text.*; -import java.util.*; - - public class Purger { - - public static void main(String[] args) { - if (args.length != 2) { - System.out.println( - "Usage: java Purger \n" + - " - folder: is the path to account.txt and athena.txt files.\n" + - " - date: accounts created before this date will be purged (dd/mm/yy)."); - return; - } - - int accounts = 0; - int characters = 0; - int deletedCharacters = 0; - Vector activeAccounts = new Vector(); - - File oldAccount = new File(args[0] + "account.txt"); - File oldAthena = new File(args[0] + "athena.txt"); - File newAccount = new File(args[0] + "account.txt.new"); - File newAthena = new File(args[0] + "athena.txt.new"); - - DateFormat dateFormat = new SimpleDateFormat("dd/MM/yy"); - Date purgeDate; - try { - purgeDate = dateFormat.parse(args[1]); - } - catch (ParseException e) { - System.out.println("ERROR: Wrong date format."); - return; - } - - String line; - try { - FileInputStream fin = new FileInputStream(oldAccount); - BufferedReader input = new BufferedReader( - new InputStreamReader(fin)); - FileOutputStream fout = new FileOutputStream(newAccount); - PrintStream output = new PrintStream(fout); - - while ((line = input.readLine()) != null) { - boolean copy = false; - String[] fields = line.split("\t"); - // Check if we're reading a comment or the last line - if (line.substring(0, 2).equals("//") || fields[1].charAt(0) == '%') { - copy = true; - } - else { - // Server accounts should not be purged - if (!fields[4].equals("S")) { - accounts++; - dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - try { - Date date = dateFormat.parse(fields[3]); - if (date.after(purgeDate)) { - activeAccounts.add(fields[0]); - copy = true; - } - } - catch (ParseException e) { - System.out.println( - "ERROR: Wrong date format in account.txt. (" - + accounts + ": " + line + ")"); - //return; - } - catch (Exception e) { - e.printStackTrace(); - return; - } - } - else { - copy = true; - } - } - if (copy) { - try { - output.println(line); - } - catch (Exception e) { - System.err.println("ERROR: Unable to write file."); - } - } - } - } - catch (FileNotFoundException e ) { - System.out.println( - "ERROR: file " + oldAccount.getAbsolutePath() + " not found."); - return; - } - catch (Exception e) { - System.out.println("ERROR: unable to process account.txt"); - e.printStackTrace(); - return; - } - - input.close(); - output.close(); - - try { - FileInputStream fin = new FileInputStream(oldAthena); - BufferedReader input = new BufferedReader( - new InputStreamReader(fin)); - FileOutputStream fout = new FileOutputStream(newAthena); - PrintStream output = new PrintStream(fout); - - while ((line = input.readLine()) != null) { - boolean copy = false; - String[] fields = line.split("\t"); - // Check if we're reading a comment or the last line - if (line.substring(0, 2).equals("//") - || fields[1].charAt(0) == '%') { - copy = true; - } - else { - characters++; - String id = fields[1].substring(0, fields[1].indexOf(',')); - if (activeAccounts.contains(id)) { - copy = true; - } - else { - deletedCharacters++; - } - } - if (copy) { - output.println(line); - } - } - } - catch (FileNotFoundException e ) { - System.out.println( - "ERROR: file " + oldAthena.getAbsolutePath() + " not found."); - return; - } - catch (Exception e) { - System.out.println("ERROR: unable to process athena.txt"); - e.printStackTrace(); - return; - } - - input.close(); - output.close(); - - System.out.println( - "Removed " + (accounts - activeAccounts.size()) + "/" + - accounts + " accounts."); - System.out.println( - "Removed " + deletedCharacters + "/" - + characters + " characters."); - } - -} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 05bdb92c267e3f041788f2aa41a73c9953249e7c Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Tue, 23 Jan 2007 21:05:05 +0000 Subject: Merged 0.0 changes from revision 3035 to 3065 to trunk. --- ChangeLog | 36 ++++++++++++++++++++++++++++++++++-- INSTALL | 2 +- NEWS | 8 ++++++++ README | 2 +- data/help/header.txt | 2 +- docs/INSTALL/win32.txt | 2 +- docs/win32-release.txt | 2 +- src/gui/menuwindow.cpp | 3 ++- src/gui/shoplistbox.cpp | 2 +- src/gui/updatewindow.cpp | 16 +++++++++++----- src/gui/viewport.cpp | 2 +- src/gui/viewport.h | 2 +- src/main.cpp | 4 +--- tmw.cbp | 31 +------------------------------ 14 files changed, 65 insertions(+), 49 deletions(-) (limited to 'src/gui/updatewindow.cpp') diff --git a/ChangeLog b/ChangeLog index d091a061..44caf16c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,34 @@ -2007-01-14 Bjørn Lindeijer +2007-01-23 Bjørn Lindeijer + + * src/gui/shoplistbox.cpp, docs/INSTALL/win32.txt, INSTALL, NEWS: + Upgraded to Guichan 0.6.1. + +2007-01-22 Bjørn Lindeijer + + * src/gui/updatewindow.cpp: Identify ourselves when requesting files + from the update server. + +2007-01-17 Eugenio Favalli + + * docs/win32-release.txt, src/gui/register.cpp, src/main.cpp: Changed + default server. + +2007-01-15 Bjørn Lindeijer + + * src/gui/viewport.cpp, src/gui/viewport.h: Fixed issue where the + player stops walking. + * docs/INSTALL/win32.txt, INSTALL: Updated to mention Guichan 0.6.0. + +2007-01-15 Eugenio Favalli + + * data/help/header.txt, NEWS, README: Updated release date. + +2007-01-14 Eugenio Favalli + + * src/gui/updatewindow.cpp, src/main.cpp, tmw.cbp: Fixed windows + headers issues. + +2007-01-14 Bjørn Lindeijer * src/game.cpp, src/main.cpp, src/gui/trade.cpp, src/gui/sell.cpp, src/gui/connection.cpp, src/gui/buddywindow.cpp, src/gui/browserbox.h, @@ -30,6 +60,8 @@ src/gui/chatinput.cpp, src/net/tradehandler.cpp, src/net/playerhandler.cpp: Upgraded to Guichan 0.6.0 (merge from guichan-0.6.0 branch). + * src/winver.h, configure.ac, data/help/header.txt, NEWS, README, + CMakeLists.txt: Updated version to 0.0.22.1. 2007-01-13 Bjørn Lindeijer @@ -37,7 +69,7 @@ data/graphics/sprites/CMakeLists.txt: Updated with regard to renaming of cotton equipment. -2006-01-13 Eugenio Favalli +2007-01-13 Eugenio Favalli * src/gui/debugwindow.cpp, src/gui/viewport.h: Fixed mouse coordinates display in debug window. diff --git a/INSTALL b/INSTALL index 5b3eb3f2..f7e8688e 100644 --- a/INSTALL +++ b/INSTALL @@ -20,7 +20,7 @@ and some libraries. The required libraries are: * 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/ -* Guichan 0.5.0 http://guichan.sourceforge.net/ +* Guichan 0.6.1 http://guichan.sourceforge.net/ * libxml2 http://www.xmlsoft.org/ * physfs 1.0.x http://icculus.org/physfs/ * zlib 1.2.x http://www.gzip.org/zlib/ diff --git a/NEWS b/NEWS index 9edd05b6..47421aef 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +0.0.22.2 (...) +- Updated to work with Guichan 0.6.1 (older versions no longer supported) + +0.0.22.1 (15 January 2007) +- Updated to work with Guichan 0.6.0 (older versions no longer supported) +- Fixed mouse coordinates in debug window +- Fixed clicking on GUI to cause the player to start walking sometimes + 0.0.22 (24 December 2006) - Added support for female-specific equipment graphics - Added support for monster sounds diff --git a/README b/README index 342524ec..bf128182 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ THE MANA WORLD ============== - Version: 0.0.22 Date: 24/12/2006 + Version: 0.0.22.1 Date: 15/01/2007 Development team: diff --git a/data/help/header.txt b/data/help/header.txt index 4f4c9615..aef87a45 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 ##2Date:##324 December 2006 + ##2Version:##6 0.0.22.1 ##2Date:##315 January 2007 ##2 Website: http://themanaworld.org diff --git a/docs/INSTALL/win32.txt b/docs/INSTALL/win32.txt index f438a7e7..7f6ee42a 100644 --- a/docs/INSTALL/win32.txt +++ b/docs/INSTALL/win32.txt @@ -28,7 +28,7 @@ Besides a C++ compiler, TMW depends on the following libraries: 1) SDL 2) SDL_mixer 3) SDL_image -4) Guichan 0.4.0 +4) Guichan 0.6.1 5) libiconv 5) libxml2 6) PhysFS diff --git a/docs/win32-release.txt b/docs/win32-release.txt index c0c6d0e6..a8696897 100644 --- a/docs/win32-release.txt +++ b/docs/win32-release.txt @@ -19,7 +19,7 @@ Every Win32 releaser should follow this checklist when creating a new package. - - - - - - - - - - - -