diff options
Diffstat (limited to 'src')
147 files changed, 3610 insertions, 3022 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 91fe8e06..43726f9d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -110,6 +110,8 @@ SET(SRCS gui/widgets/textfield.h gui/widgets/textpreview.cpp gui/widgets/textpreview.h + gui/widgets/vertcontainer.cpp + gui/widgets/vertcontainer.h gui/widgets/whispertab.cpp gui/widgets/whispertab.h gui/widgets/window.cpp @@ -213,10 +215,14 @@ SET(SRCS gui/shortcutcontainer.h gui/shortcutwindow.cpp gui/shortcutwindow.h + gui/skilldialog.cpp + gui/skilldialog.h gui/skin.cpp gui/skin.h gui/speechbubble.cpp gui/speechbubble.h + gui/statuswindow.cpp + gui/statuswindow.h gui/storagewindow.cpp gui/storagewindow.h gui/table.cpp @@ -258,7 +264,7 @@ SET(SRCS net/partyhandler.h net/playerhandler.h net/serverinfo.h - net/skillhandler.h + net/specialhandler.h net/tradehandler.h resources/action.cpp resources/action.h @@ -298,6 +304,8 @@ SET(SRCS resources/resource.h resources/resourcemanager.cpp resources/resourcemanager.h + resources/sdlrescalefacility.h + resources/sdlrescalefacility.cpp resources/soundeffect.h resources/soundeffect.cpp resources/spritedef.h @@ -416,10 +424,6 @@ SET(SRCS ) SET(SRCS_EA - gui/skill.cpp - gui/skill.h - gui/status.cpp - gui/status.h net/ea/gui/partytab.cpp net/ea/gui/partytab.h net/ea/adminhandler.cpp @@ -455,8 +459,8 @@ SET(SRCS_EA net/ea/playerhandler.cpp net/ea/playerhandler.h net/ea/protocol.h - net/ea/skillhandler.cpp - net/ea/skillhandler.h + net/ea/specialhandler.cpp + net/ea/specialhandler.h net/ea/tradehandler.cpp net/ea/tradehandler.h ) @@ -478,10 +482,6 @@ SET(SRCS_TMW gui/quitdialog.h gui/serverdialog.cpp gui/serverdialog.h - gui/skilldialog.cpp - gui/skilldialog.h - gui/statuswindow.cpp - gui/statuswindow.h gui/unregisterdialog.cpp gui/unregisterdialog.h net/tmwserv/accountserver/account.cpp @@ -543,8 +543,8 @@ SET(SRCS_TMW net/tmwserv/playerhandler.cpp net/tmwserv/playerhandler.h net/tmwserv/protocol.h - net/tmwserv/skillhandler.cpp - net/tmwserv/skillhandler.h + net/tmwserv/specialhandler.cpp + net/tmwserv/specialhandler.h net/tmwserv/tradehandler.cpp net/tmwserv/tradehandler.h guild.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 23de64bc..25fdb140 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,6 +59,8 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ gui/widgets/textfield.h \ gui/widgets/textpreview.cpp \ gui/widgets/textpreview.h \ + gui/widgets/vertcontainer.cpp \ + gui/widgets/vertcontainer.h \ gui/widgets/whispertab.cpp \ gui/widgets/whispertab.h \ gui/widgets/window.cpp \ @@ -162,10 +164,14 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ gui/shortcutcontainer.h \ gui/shortcutwindow.cpp \ gui/shortcutwindow.h \ + gui/skilldialog.cpp \ + gui/skilldialog.h \ gui/skin.cpp \ gui/skin.h \ gui/speechbubble.cpp \ gui/speechbubble.h \ + gui/statuswindow.cpp \ + gui/statuswindow.h \ gui/storagewindow.cpp \ gui/storagewindow.h \ gui/table.cpp \ @@ -207,7 +213,7 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ net/partyhandler.h \ net/playerhandler.h \ net/serverinfo.h \ - net/skillhandler.h \ + net/specialhandler.h \ net/tradehandler.h \ resources/action.cpp \ resources/action.h \ @@ -247,6 +253,8 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ resources/resource.h \ resources/resourcemanager.cpp \ resources/resourcemanager.h \ + resources/sdlrescalefacility.cpp \ + resources/sdlrescalefacility.h \ resources/soundeffect.h \ resources/soundeffect.cpp \ resources/spritedef.h \ @@ -382,10 +390,6 @@ tmw_SOURCES += \ gui/quitdialog.h \ gui/serverdialog.cpp \ gui/serverdialog.h \ - gui/skilldialog.cpp \ - gui/skilldialog.h \ - gui/statuswindow.cpp \ - gui/statuswindow.h \ gui/unregisterdialog.cpp \ gui/unregisterdialog.h \ net/tmwserv/accountserver/account.cpp \ @@ -447,8 +451,8 @@ tmw_SOURCES += \ net/tmwserv/playerhandler.cpp \ net/tmwserv/playerhandler.h \ net/tmwserv/protocol.h \ - net/tmwserv/skillhandler.cpp \ - net/tmwserv/skillhandler.h \ + net/tmwserv/specialhandler.cpp \ + net/tmwserv/specialhandler.h \ net/tmwserv/tradehandler.cpp \ net/tmwserv/tradehandler.h \ guild.cpp \ @@ -458,10 +462,6 @@ endif if SERVER_EATHENA tmw_CXXFLAGS += -DEATHENA_SUPPORT tmw_SOURCES += \ - gui/skill.cpp \ - gui/skill.h \ - gui/status.cpp \ - gui/status.h \ net/ea/gui/partytab.cpp \ net/ea/gui/partytab.h \ net/ea/adminhandler.cpp \ @@ -497,8 +497,8 @@ tmw_SOURCES += \ net/ea/playerhandler.cpp \ net/ea/playerhandler.h \ net/ea/protocol.h \ - net/ea/skillhandler.cpp \ - net/ea/skillhandler.h \ + net/ea/specialhandler.cpp \ + net/ea/specialhandler.h \ net/ea/tradehandler.cpp \ net/ea/tradehandler.h endif diff --git a/src/being.cpp b/src/being.cpp index ea587afb..23b87e6c 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -49,7 +49,6 @@ #include "gui/speechbubble.h" #include "utils/dtor.h" -#include "utils/gettext.h" #include "utils/stringutils.h" #include "utils/xml.h" @@ -66,7 +65,6 @@ static const int DEFAULT_HEIGHT = 32; Being::Being(int id, int job, Map *map): #ifdef EATHENA_SUPPORT - mX(0), mY(0), mWalkTime(0), #endif mEmotion(0), mEmotionTime(0), @@ -100,6 +98,7 @@ Being::Being(int id, int job, Map *map): mWalkSpeed(150), #endif mPx(0), mPy(0), + mX(0), mY(0), mUsedTargetCursor(NULL) { setMap(map); @@ -148,37 +147,21 @@ void Being::setDestination(Uint16 destX, Uint16 destY) #endif #ifdef TMWSERV_SUPPORT - -void Being::adjustCourse(int srcX, int srcY) -{ - setDestination(srcX, srcY, mDest.x, mDest.y); -} - void Being::setDestination(int dstX, int dstY) { - setDestination(mPos.x, mPos.y, dstX, dstY); -} + mDest.x = dstX; + mDest.y = dstY; + int srcX = mPos.x; + int srcY = mPos.y; -Path Being::findPath() -{ - Path path; + Path thisPath; if (mMap) { - path = mMap->findPath(mPos.x / 32, mPos.y / 32, - mDest.x / 32, mDest.y / 32, getWalkMask()); + thisPath = mMap->findPath(mPos.x / 32, mPos.y / 32, + mDest.x / 32, mDest.y / 32, getWalkMask()); } - return path; -} - -void Being::setDestination(int srcX, int srcY, int dstX, int dstY) -{ - mDest.x = dstX; - mDest.y = dstY; - - Path thisPath = findPath(); - if (thisPath.empty()) { setPath(Path()); @@ -188,16 +171,13 @@ void Being::setDestination(int srcX, int srcY, int dstX, int dstY) // FIXME: Look into making this code neater. // Interpolate the offsets. Also convert from tile based to pixel based - // Note: I divided the offsets by 32 then muilpied it back to get the top left - // Conner of where the tile is. (If you know a better way then please change it) - // Find the starting offset - int startX = srcX - ((srcX / 32) * 32 + 16); - int startY = srcY - ((srcY / 32) * 32 + 16); + int startX = (srcX % 32); + int startY = (srcY % 32); // Find the ending offset - int endX = dstX - ((dstX / 32) * 32 + 16); - int endY = dstY - ((dstY / 32) * 32 + 16); + int endX = (dstX % 32); + int endY = (dstY % 32); // Find the distance, and divide it by the number of steps int changeX = (endX - startX) / thisPath.size(); @@ -209,8 +189,8 @@ void Being::setDestination(int srcX, int srcY, int dstX, int dstY) int i = 0; while(it != thisPath.end()) { - it->x = (it->x * 32 + 16) + startX + (changeX * i); - it->y = (it->y * 32 + 16) + startY + (changeY * i); + it->x = (it->x * 32) + startX + (changeX * i); + it->y = (it->y * 32) + startY + (changeY * i); i++; it++; } @@ -228,7 +208,7 @@ void Being::setPath(const Path &path) { mPath = path; #ifdef TMWSERV_SUPPORT -// std::cout << this << " New path: " << path << std::endl; + std::cout << this << " New path: " << path << std::endl; #else if (mAction != WALK && mAction != DEAD) { diff --git a/src/being.h b/src/being.h index 9213a2dc..6e90b39d 100644 --- a/src/being.h +++ b/src/being.h @@ -149,7 +149,6 @@ class Being : public Sprite, public ConfigListener enum { DOWN = 1, LEFT = 2, UP = 4, RIGHT = 8 }; #ifdef EATHENA_SUPPORT - Uint16 mX, mY; /**< Tile coordinates */ int mFrame; int mWalkTime; #endif @@ -184,30 +183,30 @@ class Being : public Sprite, public ConfigListener virtual void setDestination(Uint16 destX, Uint16 destY); #else /** - * Returns the path to the being's current destination + * Creates a path for the being from current position to ex and ey */ - virtual Path findPath(); + void setDestination(int ex, int ey); /** - * Creates a path for the being from sx,sy to ex,ey + * Returns the destination for this being. */ - void setDestination(int sx, int sy, int ex, int ey); + const Vector &getDestination() const { return mDest; } +#endif /** - * Creates a path for the being from current position to ex and ey + * Returns the tile x or y coord */ - void setDestination(int ex, int ey); + int getTileX() const + { return mX; } - /** - * Adjusts course to expected start point. - */ - void adjustCourse(int srcX, int srcY); + int getTileY() const + { return mY; } /** - * Returns the destination for this being. + * Sets the tile x or y coord */ - const Vector &getDestination() const { return mDest; } -#endif + void setTileCoords(int x, int y) + { mX = x; mY = y; } /** * Puts a "speech balloon" above this being for the specified amount @@ -603,6 +602,7 @@ class Being : public Sprite, public ConfigListener Vector mPos; Vector mDest; int mPx, mPy; /**< Position in pixels */ + int mX, mY; /**< Position on tile */ /** Target cursor being used */ SimpleAnimation* mUsedTargetCursor; diff --git a/src/beingmanager.cpp b/src/beingmanager.cpp index 284f1343..0b8f71b5 100644 --- a/src/beingmanager.cpp +++ b/src/beingmanager.cpp @@ -40,14 +40,9 @@ class FindBeingFunctor bool operator() (Being *being) { Uint16 other_y = y + ((being->getType() == Being::NPC) ? 1 : 0); -#ifdef TMWSERV_SUPPORT const Vector &pos = being->getPosition(); return ((int) pos.x / 32 == x && ((int) pos.y / 32 == y || (int) pos.y / 32 == other_y) && -#else - return (being->mX == x && - (being->mY == y || being->mY == other_y) && -#endif being->mAction != Being::DEAD && (type == Being::UNKNOWN || being->getType() == type)); } @@ -242,7 +237,7 @@ Being *BeingManager::findNearestLivingBeing(int x, int y, int maxdist, const Vector &pos = being->getPosition(); int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y); #else - int d = abs(being->mX - x) + abs(being->mY - y); + int d = abs(being->getTileX() - x) + abs(being->getTileY() - y); #endif if ((being->getType() == type || type == Being::UNKNOWN) @@ -268,8 +263,8 @@ Being *BeingManager::findNearestLivingBeing(Being *aroundBeing, int maxdist, int y = apos.y; maxdist = maxdist * 32; #else - int x = aroundBeing->mX; - int y = aroundBeing->mY; + int x = aroundBeing->getTileX(); + int y = aroundBeing->getTileY(); #endif for (Beings::const_iterator i = mBeings.begin(), i_end = mBeings.end(); @@ -280,7 +275,7 @@ Being *BeingManager::findNearestLivingBeing(Being *aroundBeing, int maxdist, const Vector &pos = being->getPosition(); int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y); #else - int d = abs(being->mX - x) + abs(being->mY - y); + int d = abs(being->getTileX() - x) + abs(being->getTileY() - y); #endif if ((being->getType() == type || type == Being::UNKNOWN) diff --git a/src/commandhandler.cpp b/src/commandhandler.cpp index d2a303e8..e64da120 100644 --- a/src/commandhandler.cpp +++ b/src/commandhandler.cpp @@ -207,7 +207,7 @@ void CommandHandler::handleHelp(const std::string &args, ChatTab *tab) else if (args == "ignore") { tab->chatLog(_("Command: /ignore <player>")); - tab->chatLog(_("This command ignores the given player reguardless of " + tab->chatLog(_("This command ignores the given player regardless of " "current relations.")); } else if (args == "join") @@ -397,7 +397,7 @@ void CommandHandler::handleParty(const std::string &args, ChatTab *tab) if (args != "") Net::getPartyHandler()->invite(args); else - tab->chatLog("Please specify a name.", BY_SERVER); + tab->chatLog(_("Please specify a name."), BY_SERVER); } void CommandHandler::handleMe(const std::string &args, ChatTab *tab) diff --git a/src/engine.cpp b/src/engine.cpp index d33607ec..f56f8a49 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -85,7 +85,7 @@ bool Engine::changeMap(const std::string &mapPath) if (!newMap) { logger->log("Error while loading %s", map_path.c_str()); - new OkDialog(_("Could not load map"), + new OkDialog(_("Could Not Load Map"), strprintf(_("Error while loading %s"), map_path.c_str())); } diff --git a/src/equipment.cpp b/src/equipment.cpp index f760067c..41722300 100644 --- a/src/equipment.cpp +++ b/src/equipment.cpp @@ -21,27 +21,14 @@ #include "equipment.h" #include "item.h" -#ifdef EATHENA_SUPPORT -#include "inventory.h" -#include "localplayer.h" -#endif #include <algorithm> Equipment::Equipment() -#ifdef EATHENA_SUPPORT - : mArrows(-1) -#endif { -#ifdef TMWSERV_SUPPORT std::fill_n(mEquipment, EQUIPMENT_SIZE, (Item*) 0); -#else - std::fill_n(mEquipment, EQUIPMENT_SIZE, -1); -#endif } -#ifdef TMWSERV_SUPPORT - Equipment::~Equipment() { clear(); @@ -55,29 +42,14 @@ void Equipment::clear() std::fill_n(mEquipment, EQUIPMENT_SIZE, (Item*) 0); } -void Equipment::setEquipment(int index, int id) +void Equipment::setEquipment(int index, int id, int quantity) { if (mEquipment[index] && mEquipment[index]->getId() == id) return; delete mEquipment[index]; - mEquipment[index] = (id > 0) ? new Item(id) : 0; -} - -#else - -void Equipment::setEquipment(int index, int inventoryIndex) -{ - mEquipment[index] = inventoryIndex; - Item *item = player_node->getInventory()->getItem(inventoryIndex); - if (item) - item->setEquipped(true); -} + mEquipment[index] = (id > 0) ? new Item(id, quantity) : 0; -void Equipment::removeEquipment(int index) -{ - if (index >= 0 && index < EQUIPMENT_SIZE) - mEquipment[index] = -1; + if (mEquipment[index]) + mEquipment[index]->setInvIndex(index); } - -#endif diff --git a/src/equipment.h b/src/equipment.h index 5bebf78d..c7058269 100644 --- a/src/equipment.h +++ b/src/equipment.h @@ -22,11 +22,7 @@ #ifndef EQUIPMENT_H #define EQUIPMENT_H -#ifdef TMWSERV_SUPPORT #define EQUIPMENT_SIZE 11 -#else -#define EQUIPMENT_SIZE 10 -#endif class Item; @@ -38,63 +34,45 @@ class Equipment */ Equipment(); -#ifdef TMWSERV_SUPPORT /** * Destructor. */ ~Equipment(); -#endif + + enum EquipmentSlots + { + EQUIP_TORSO_SLOT = 0, + EQUIP_GLOVES_SLOT = 1, + EQUIP_HEAD_SLOT = 2, + EQUIP_LEGS_SLOT = 3, + EQUIP_FEET_SLOT = 4, + EQUIP_RING1_SLOT = 5, + EQUIP_RING2_SLOT = 6, + EQUIP_NECK_SLOT = 7, + EQUIP_FIGHT1_SLOT = 8, + EQUIP_FIGHT2_SLOT = 9, + EQUIP_PROJECTILE_SLOT = 10, + EQUIP_VECTOREND + }; /** * Get equipment at the given slot. */ -#ifdef TMWSERV_SUPPORT Item *getEquipment(int index) -#else - int getEquipment(int index) const -#endif { return mEquipment[index]; } -#ifdef TMWSERV_SUPPORT /** * Clears equipment. */ void clear(); -#endif /** * Set equipment at the given slot. */ -#ifdef TMWSERV_SUPPORT - void setEquipment(int index, int id); -#else - void setEquipment(int index, int inventoryIndex); -#endif - -#ifdef EATHENA_SUPPORT - /** - * Remove equipment from the given slot. - */ - void removeEquipment(int index); - - /** - * Returns the item used in the arrow slot. - */ - int getArrows() const { return mArrows; } - - /** - * Set the item used in the arrow slot. - */ - void setArrows(int arrows) { mArrows = arrows; } -#endif + void setEquipment(int index, int id, int quantity = 0); private: -#ifdef TMWSERV_SUPPORT Item *mEquipment[EQUIPMENT_SIZE]; -#else - int mEquipment[EQUIPMENT_SIZE]; - int mArrows; -#endif }; #endif diff --git a/src/game.cpp b/src/game.cpp index f1df57cc..ff0d84f7 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -62,8 +62,8 @@ #include "gui/sdlinput.h" #include "gui/sell.h" #include "gui/setup.h" -#include "gui/skill.h" -#include "gui/status.h" +#include "gui/skilldialog.h" +#include "gui/statuswindow.h" #include "gui/trade.h" #include "gui/viewport.h" #include "gui/windowmenu.h" @@ -206,6 +206,8 @@ int get_elapsed_time(int start_time) */ static void createGuiWindows() { + setupWindow->clearWindowsForReset(); + // Create dialogs chatWindow = new ChatWindow; buyDialog = new BuyDialog; @@ -214,17 +216,16 @@ static void createGuiWindows() partyWindow = new PartyWindow; #ifdef TMWSERV_SUPPORT magicDialog = new MagicDialog; - equipmentWindow = new EquipmentWindow(player_node->mEquipment.get()); buddyWindow = new BuddyWindow; guildWindow = new GuildWindow; #else buySellDialog = new BuySellDialog; - equipmentWindow = new EquipmentWindow; #endif + equipmentWindow = new EquipmentWindow(player_node->mEquipment.get()); npcDialog = new NpcDialog; npcPostDialog = new NpcPostDialog; storageWindow = new StorageWindow; - statusWindow = new StatusWindow(player_node); + statusWindow = new StatusWindow; miniStatusWindow = new MiniStatusWindow; inventoryWindow = new InventoryWindow; skillDialog = new SkillDialog; @@ -405,6 +406,7 @@ static bool saveScreenshot() if (success) { std::stringstream chatlogentry; + // TODO: Make it one complete gettext string below chatlogentry << _("Screenshot saved to ~/") << filenameSuffix.str(); localChatTab->chatLog(chatlogentry.str(), BY_SERVER); } @@ -763,8 +765,8 @@ void Game::handleInput() Uint16 x = (int) pos.x / 32; Uint16 y = (int) pos.y / 32; #else - Uint16 x = player_node->mX; - Uint16 y = player_node->mY; + Uint16 x = player_node->getTileX(); + Uint16 y = player_node->getTileY(); #endif FloorItem *item = floorItemManager->findByCoordinates(x, y); @@ -937,14 +939,9 @@ void Game::handleInput() return; } -#ifdef TMWSERV_SUPPORT const Vector &pos = player_node->getPosition(); const Uint16 x = (int) pos.x / 32; const Uint16 y = (int) pos.y / 32; -#else - const Uint16 x = player_node->mX; - const Uint16 y = player_node->mY; -#endif unsigned char direction = 0; // Translate pressed keys to movement and direction diff --git a/src/graphics.cpp b/src/graphics.cpp index 58f643e9..75db11f4 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -120,11 +120,47 @@ bool Graphics::drawImage(Image *image, int x, int y) return drawImage(image, 0, 0, x, y, image->mBounds.w, image->mBounds.h); } +bool Graphics::drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor) +{ + // Check that preconditions for blitting are met. + if (!mScreen || !image) return false; + if (!image->mImage) return false; + + Image *tmpImage = image->SDLgetScaledImage(desiredWidth, desiredHeight); + bool returnValue = false; + if (!tmpImage) return false; + if (!tmpImage->mImage) return false; + + dstX += mClipStack.top().xOffset; + dstY += mClipStack.top().yOffset; + + srcX += image->mBounds.x; + srcY += image->mBounds.y; + + SDL_Rect dstRect; + SDL_Rect srcRect; + dstRect.x = dstX; dstRect.y = dstY; + srcRect.x = srcX; srcRect.y = srcY; + srcRect.w = width; + srcRect.h = height; + + returnValue = !(SDL_BlitSurface(tmpImage->mImage, &srcRect, mScreen, &dstRect) < 0); + + delete tmpImage; + + return returnValue; +} + bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height, bool) { // Check that preconditions for blitting are met. - if (!mScreen || !image || !image->mImage) return false; + if (!mScreen || !image) return false; + if (!image->mImage) return false; dstX += mClipStack.top().xOffset; dstY += mClipStack.top().yOffset; @@ -154,7 +190,8 @@ void Graphics::drawImage(gcn::Image const *image, int srcX, int srcY, void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h) { // Check that preconditions for blitting are met. - if (!mScreen || !image || !image->mImage) return; + if (!mScreen || !image) return; + if (!image->mImage) return; const int iw = image->getWidth(); const int ih = image->getHeight(); @@ -184,6 +221,48 @@ void Graphics::drawImagePattern(Image *image, int x, int y, int w, int h) } } +void Graphics::drawRescaledImagePattern(Image *image, int x, int y, + int w, int h, int scaledWidth, int scaledHeight) +{ + // Check that preconditions for blitting are met. + if (!mScreen || !image) return; + if (!image->mImage) return; + + if (scaledHeight == 0 || scaledWidth == 0) return; + + Image *tmpImage = image->SDLgetScaledImage(scaledWidth, scaledHeight); + if (!tmpImage) return; + + const int iw = tmpImage->getWidth(); + const int ih = tmpImage->getHeight(); + + if (iw == 0 || ih == 0) return; + + for (int py = 0; py < h; py += ih) // Y position on pattern plane + { + int dh = (py + ih >= h) ? h - py : ih; + int srcY = tmpImage->mBounds.y; + int dstY = y + py + mClipStack.top().yOffset; + + for (int px = 0; px < w; px += iw) // X position on pattern plane + { + int dw = (px + iw >= w) ? w - px : iw; + int srcX = tmpImage->mBounds.x; + int dstX = x + px + mClipStack.top().xOffset; + + SDL_Rect dstRect; + SDL_Rect srcRect; + dstRect.x = dstX; dstRect.y = dstY; + srcRect.x = srcX; srcRect.y = srcY; + srcRect.w = dw; srcRect.h = dh; + + SDL_BlitSurface(tmpImage->mImage, &srcRect, mScreen, &dstRect); + } + } + + delete tmpImage; +} + void Graphics::drawImageRect(int x, int y, int w, int h, Image *topLeft, Image *topRight, Image *bottomLeft, Image *bottomRight, diff --git a/src/graphics.h b/src/graphics.h index d0e70c24..b8e87af1 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -29,6 +29,9 @@ class ImageRect; struct SDL_Surface; +static const int defaultScreenWidth = 800; +static const int defaultScreenHeight = 600; + /** * 9 images defining a rectangle. 4 corners, 4 sides and a middle area. The * topology is as follows: @@ -105,6 +108,28 @@ class Graphics : public gcn::SDLGraphics int dstX, int dstY, int width, int height); /** + * Draws a resclaled version of the image + */ + bool drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight) + { return drawRescaledImage(image, srcX, srcY, + dstX, dstY, + width, height, + desiredWidth, desiredHeight, + false); }; + + /** + * Draws a resclaled version of the image + */ + virtual bool drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor = false); + + /** * Blits an image onto the screen. * * @return <code>true</code> if the image was blitted properly @@ -121,6 +146,13 @@ class Graphics : public gcn::SDLGraphics int w, int h); /** + * Draw a pattern based on a rescaled version of the given image... + */ + virtual void drawRescaledImagePattern(Image *image, + int x, int y, int w, int h, + int scaledWidth, int scaledHeight); + + /** * Draws a rectangle using images. 4 corner images, 4 side images and 1 * image for the inside. */ diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 5b393a06..a2398472 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -27,6 +27,7 @@ #include "gui/widgets/scrollarea.h" #include "gui/widgets/slider.h" +#include "gui/setup.h" #include "gui/shop.h" #include "gui/shoplistbox.h" @@ -47,6 +48,7 @@ BuyDialog::BuyDialog(): mMoney(0), mAmountItems(0), mMaxItems(0) { setWindowName("Buy"); + setupWindow->registerWindowForReset(this); setResizable(true); setCloseButton(true); setMinWidth(260); @@ -65,8 +67,12 @@ BuyDialog::BuyDialog(): mMoneyLabel = new Label(strprintf(_("Price: %s / Total: %s"), "", "")); - mIncreaseButton = new Button("+", "+", this); - mDecreaseButton = new Button("-", "-", this); + // TRANSLATORS: This is a narrow symbol used to denote 'increasing'. + // You may change this symbol if your language uses another. + mIncreaseButton = new Button(_("+"), "inc", this); + // TRANSLATORS: This is a narrow symbol used to denote 'decreasing'. + // You may change this symbol if your language uses another. + mDecreaseButton = new Button(_("-"), "dec", this); mBuyButton = new Button(_("Buy"), "buy", this); mQuitButton = new Button(_("Quit"), "quit", this); mAddMaxButton = new Button(_("Max"), "max", this); @@ -160,13 +166,13 @@ void BuyDialog::action(const gcn::ActionEvent &event) mAmountItems = (int) mSlider->getValue(); updateButtonsAndLabels(); } - else if (event.getId() == "+" && mAmountItems < mMaxItems) + else if (event.getId() == "inc" && mAmountItems < mMaxItems) { mAmountItems++; mSlider->setValue(mAmountItems); updateButtonsAndLabels(); } - else if (event.getId() == "-" && mAmountItems > 1) + else if (event.getId() == "dec" && mAmountItems > 1) { mAmountItems--; mSlider->setValue(mAmountItems); diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp index 53c2419a..c96c9f24 100644 --- a/src/gui/buysell.cpp +++ b/src/gui/buysell.cpp @@ -24,6 +24,7 @@ #include "npc.h" #include "gui/widgets/button.h" +#include "gui/setup.h" #include "net/net.h" #include "net/npchandler.h" @@ -35,6 +36,7 @@ BuySellDialog::BuySellDialog(): mBuyButton(0) { setWindowName("BuySell"); + setupWindow->registerWindowForReset(this); static const char *buttonNames[] = { N_("Buy"), N_("Sell"), N_("Cancel"), 0 diff --git a/src/gui/changeemaildialog.cpp b/src/gui/changeemaildialog.cpp index d36ab487..eb05e25e 100644 --- a/src/gui/changeemaildialog.cpp +++ b/src/gui/changeemaildialog.cpp @@ -46,7 +46,7 @@ ChangeEmailDialog::ChangeEmailDialog(Window *parent, LoginData *loginData): { gcn::Label *accountLabel = new Label(strprintf(_("Account: %s"), mLoginData->username.c_str())); - gcn::Label *newEmailLabel = new Label(_("Type New Email Address twice:")); + gcn::Label *newEmailLabel = new Label(_("Type new email address twice:")); mFirstEmailField = new TextField; mSecondEmailField = new TextField; mChangeEmailButton = new Button(_("Change Email Address"), "change_email", this); @@ -114,29 +114,29 @@ ChangeEmailDialog::action(const gcn::ActionEvent &event) logger->log("ChangeEmailDialog::Email change, Username is %s", username.c_str()); - std::stringstream errorMsg; + std::stringstream errorMessage; int error = 0; if (newFirstEmail.length() < LEN_MIN_PASSWORD) { // First email address too short - errorMsg << "The new email address needs to be at least " - << LEN_MIN_PASSWORD - << " characters long."; + errorMessage << strprintf(_("The new email address needs to be at " + "least %d characters long."), + LEN_MIN_PASSWORD); error = 1; } else if (newFirstEmail.length() > LEN_MAX_PASSWORD - 1 ) { // First email address too long - errorMsg << "The new email address needs to be less than " - << LEN_MAX_PASSWORD - << " characters long."; + errorMessage << strprintf(_("The new email address needs to be " + "less than %d characters long."), + LEN_MAX_PASSWORD); error = 1; } else if (newFirstEmail != newSecondEmail) { // Second Pass mismatch - errorMsg << "The email address entries mismatch."; + errorMessage << _("The email address entries mismatch."); error = 2; } @@ -151,7 +151,7 @@ ChangeEmailDialog::action(const gcn::ActionEvent &event) mWrongDataNoticeListener->setTarget(this->mSecondEmailField); } - OkDialog *dlg = new OkDialog("Error", errorMsg.str()); + OkDialog *dlg = new OkDialog(_("Error"), errorMessage.str()); dlg->addActionListener(mWrongDataNoticeListener); } else diff --git a/src/gui/changepassworddialog.cpp b/src/gui/changepassworddialog.cpp index 4be92b15..9d66d13a 100644 --- a/src/gui/changepassworddialog.cpp +++ b/src/gui/changepassworddialog.cpp @@ -96,36 +96,35 @@ void ChangePasswordDialog::action(const gcn::ActionEvent &event) logger->log("ChangePasswordDialog::Password change, Username is %s", username.c_str()); - std::stringstream errorMsg; + std::stringstream errorMessage; int error = 0; // Check old Password if (oldPassword.empty()) { // No old password - errorMsg << "Enter the old Password first."; + errorMessage << _("Enter the old password first."); error = 1; } else if (newFirstPass.length() < LEN_MIN_PASSWORD) { // First password too short - errorMsg << "The new password needs to be at least " - << LEN_MIN_PASSWORD - << " characters long."; + errorMessage << strprintf(_("The new password needs to be at least " + "%d characters long."), LEN_MIN_PASSWORD); error = 2; } else if (newFirstPass.length() > LEN_MAX_PASSWORD - 1 ) { // First password too long - errorMsg << "The new password needs to be less than " - << LEN_MAX_PASSWORD - << " characters long."; + errorMessage << strprintf(_("The new password needs to be less " + "than %d characters long."), + LEN_MAX_PASSWORD); error = 2; } else if (newFirstPass != newSecondPass) { // Second Pass mismatch - errorMsg << "The new password entries mismatch."; + errorMessage << _("The new password entries mismatch."); error = 3; } @@ -144,7 +143,7 @@ void ChangePasswordDialog::action(const gcn::ActionEvent &event) mWrongDataNoticeListener->setTarget(this->mSecondPassField); } - OkDialog *dlg = new OkDialog("Error", errorMsg.str()); + OkDialog *dlg = new OkDialog(_("Error"), errorMessage.str()); dlg->addActionListener(mWrongDataNoticeListener); } else diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp index 79ec5c1a..e09eee55 100644 --- a/src/gui/charcreatedialog.cpp +++ b/src/gui/charcreatedialog.cpp @@ -64,12 +64,16 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot): mNameField = new TextField(""); mNameLabel = new Label(_("Name:")); - mNextHairColorButton = new Button(">", "nextcolor", this); - mPrevHairColorButton = new Button("<", "prevcolor", this); - mHairColorLabel = new Label(_("Hair Color:")); - mNextHairStyleButton = new Button(">", "nextstyle", this); - mPrevHairStyleButton = new Button("<", "prevstyle", this); - mHairStyleLabel = new Label(_("Hair Style:")); + // TRANSLATORS: This is a narrow symbol used to denote 'next'. + // You may change this symbol if your language uses another. + mNextHairColorButton = new Button(_(">"), "nextcolor", this); + // TRANSLATORS: This is a narrow symbol used to denote 'previous'. + // You may change this symbol if your language uses another. + mPrevHairColorButton = new Button(_("<"), "prevcolor", this); + mHairColorLabel = new Label(_("Hair color:")); + mNextHairStyleButton = new Button(_(">"), "nextstyle", this); + mPrevHairStyleButton = new Button(_("<"), "prevstyle", this); + mHairStyleLabel = new Label(_("Hair style:")); mCreateButton = new Button(_("Create"), "create", this); mCancelButton = new Button(_("Cancel"), "cancel", this); mMale = new RadioButton(_("Male"), "gender"); diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp index 63a25d45..69a627e1 100644 --- a/src/gui/charselectdialog.cpp +++ b/src/gui/charselectdialog.cpp @@ -36,6 +36,8 @@ #include "gui/changeemaildialog.h" #include "net/tmwserv/accountserver/account.h" +#else +#include "net/ea/protocol.h" #endif #include "gui/widgets/button.h" @@ -116,7 +118,7 @@ CharSelectDialog::CharSelectDialog(LockedArray<LocalPlayer*> *charInfo, mNameLabel = new Label(strprintf(_("Name: %s"), "")); mLevelLabel = new Label(strprintf(_("Level: %d"), 0)); - mMoneyLabel = new Label(strprintf(_("Money: %d"), 0)); + mMoneyLabel = new Label(strprintf(_("Money: %s"), "")); // Control that shows the Player mPlayerBox = new PlayerBox; @@ -296,9 +298,9 @@ void CharSelectDialog::updatePlayerInfo() mNameLabel->setCaption(strprintf(_("Name: %s"), pi->getName().c_str())); mLevelLabel->setCaption(strprintf(_("Level: %d"), pi->getLevel())); -#ifndef TMWSERV_SUPPORT +#ifdef EATHENA_SUPPORT mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"), - pi->mJobLevel)); + pi->getAttributeBase(JOB))); #endif mMoneyLabel->setCaption(strprintf(_("Money: %s"), mMoney.c_str())); if (!mCharSelected) @@ -362,7 +364,10 @@ bool CharSelectDialog::selectByName(const std::string &name) LocalPlayer *player = mCharInfo->getEntry(); if (player && player->getName() == name) + { + mMoney = Units::formatCurrency(player->getMoney()); return true; + } mCharInfo->next(); } while (mCharInfo->getPos()); diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index 1ce1b77c..c337d33b 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -23,6 +23,7 @@ #include "gui/itemlinkhandler.h" #include "gui/recorder.h" +#include "gui/setup.h" #include "gui/sdlinput.h" #include "gui/widgets/chattab.h" @@ -39,6 +40,7 @@ #include "net/net.h" #include "utils/dtor.h" +#include "utils/gettext.h" #include "utils/stringutils.h" #include <guichan/focushandler.hpp> @@ -76,6 +78,8 @@ ChatWindow::ChatWindow(): { setWindowName("Chat"); + setupWindow->registerWindowForReset(this); + // no title presented, title bar is padding so window can be moved. gcn::Window::setTitleBarHeight(gcn::Window::getPadding() + 4); setShowTitle(false); @@ -138,9 +142,14 @@ void ChatWindow::adjustTabSize() ChatTab *tab = getFocused(); if (tab) { gcn::Widget *content = tab->mScrollArea; + bool scrollLock = false; + if(tab->mScrollArea->getVerticalMaxScroll() == tab->mScrollArea->getVerticalScrollAmount()) + scrollLock = true; content->setSize(mChatTabs->getWidth() - 2 * content->getFrameSize(), mChatTabs->getContainerHeight() - 2 * content->getFrameSize()); content->logic(); + if(scrollLock) + tab->mScrollArea->setVerticalScrollAmount(tab->mScrollArea->getVerticalMaxScroll()); } } @@ -323,8 +332,8 @@ void ChatWindow::doPresent() } } - std::string cpc = strprintf(_("%d players are present."), playercount); - std::string log = _("Present: ") + response + std::string("; ") + cpc; + std::string log = strprintf(_("Present: %s; %d players are present."), + response.c_str(), playercount); if (mRecorder->isRecording()) { @@ -360,6 +369,37 @@ void ChatWindow::scroll(int amount) tab->scroll(amount); } +void ChatWindow::mousePressed(gcn::MouseEvent &event) +{ + Window::mousePressed(event); + + if(event.isConsumed()) + return; + + mMoved = event.getY() <= mCurrentTab->getHeight(); + mDragOffsetX = event.getX(); + mDragOffsetY = event.getY(); + +} + +void ChatWindow::mouseDragged(gcn::MouseEvent &event) +{ + Window::mouseDragged(event); + + if(event.isConsumed()) + return; + + if(isMovable() && mMoved) + { + int newX = std::max(0, getX() + event.getX() - mDragOffsetX); + int newY = std::max(0, getY() + event.getY() - mDragOffsetY); + newX = std::min(graphics->getWidth() - getWidth(), newX); + newY = std::min(graphics->getHeight() - getHeight(), newY); + setPosition(newX, newY); + } +} + + void ChatWindow::keyPressed(gcn::KeyEvent &event) { if (event.getKey().getValue() == Key::DOWN) diff --git a/src/gui/chat.h b/src/gui/chat.h index 7080392e..2de3a634 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -150,6 +150,11 @@ class ChatWindow : public Window, /** Override to reset mTmpVisible */ void setVisible(bool visible); + + void mousePressed(gcn::MouseEvent &event); + void mouseDragged(gcn::MouseEvent &event); + + /** * Scrolls the chat window * diff --git a/src/gui/connectiondialog.cpp b/src/gui/connectiondialog.cpp index 1c3b7ff5..9e361173 100644 --- a/src/gui/connectiondialog.cpp +++ b/src/gui/connectiondialog.cpp @@ -31,7 +31,7 @@ #include "utils/gettext.h" ConnectionDialog::ConnectionDialog(State previousState): - Window("Info"), mProgress(0), mPreviousState(previousState) + Window(_("Info")), mProgress(0), mPreviousState(previousState) { setContentSize(200, 100); diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index f3dbe5e2..59c0f254 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -21,6 +21,7 @@ #include "gui/debugwindow.h" +#include "gui/setup.h" #include "gui/viewport.h" #include "gui/widgets/label.h" @@ -31,31 +32,33 @@ #include "particle.h" #include "map.h" +#include "utils/gettext.h" #include "utils/stringutils.h" DebugWindow::DebugWindow(): - Window("Debug") + Window(_("Debug")) { setWindowName("Debug"); + setupWindow->registerWindowForReset(this); setResizable(true); setCloseButton(true); setSaveVisible(true); setDefaultSize(400, 100, ImageRect::CENTER); - mFPSLabel = new Label("0 FPS"); - mMusicFileLabel = new Label("Music: "); - mMapLabel = new Label("Map: "); - mMiniMapLabel = new Label("Mini-Map: "); - mTileMouseLabel = new Label("Mouse: 0, 0"); - mParticleCountLabel = new Label("Particle count: 0"); + mFPSLabel = new Label(strprintf(_("%d FPS"), 0)); + mMusicFileLabel = new Label(strprintf(_("Music: %s"), "")); + mMapLabel = new Label(strprintf(_("Map: %s"), "")); + mMinimapLabel = new Label(strprintf(_("Minimap: %s"), "")); + mTileMouseLabel = new Label(strprintf(_("Tile: (%d, %d)"), 0, 0)); + mParticleCountLabel = new Label(strprintf(_("Particle count: %d"), 0)); place(0, 0, mFPSLabel, 3); place(3, 0, mTileMouseLabel); place(0, 1, mMusicFileLabel, 3); place(3, 1, mParticleCountLabel); place(0, 2, mMapLabel, 4); - place(0, 3, mMiniMapLabel, 4); + place(0, 3, mMinimapLabel, 4); loadWindowState(); } @@ -69,27 +72,28 @@ void DebugWindow::logic() int mouseTileX = (viewport->getMouseX() + viewport->getCameraX()) / 32; int mouseTileY = (viewport->getMouseY() + viewport->getCameraY()) / 32; - mFPSLabel->setCaption(toString(fps) + " FPS"); + mFPSLabel->setCaption(strprintf(_("%d FPS"), fps)); - mTileMouseLabel->setCaption("Tile: (" + toString(mouseTileX) + ", " + - toString(mouseTileY) + ")"); + mTileMouseLabel->setCaption(strprintf(_("Tile: (%d, %d)"), mouseTileX, + mouseTileY)); Map *currentMap = engine->getCurrentMap(); if (currentMap) { + // TODO: Add gettext support below const std::string music = "Music: " + currentMap->getProperty("music"); mMusicFileLabel->setCaption(music); const std::string minimap = - "MiniMap: " + currentMap->getProperty("minimap"); - mMiniMapLabel->setCaption(minimap); + "Minimap: " + currentMap->getProperty("minimap"); + mMinimapLabel->setCaption(minimap); const std::string map = "Map: " + currentMap->getProperty("_filename"); mMapLabel->setCaption(map); } - mParticleCountLabel->setCaption("Particle count: " + - toString(Particle::particleCount)); + mParticleCountLabel->setCaption(strprintf(_("Particle count: %d"), + Particle::particleCount)); } diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h index e30107f9..e4c45bde 100644 --- a/src/gui/debugwindow.h +++ b/src/gui/debugwindow.h @@ -43,7 +43,7 @@ class DebugWindow : public Window void logic(); private: - gcn::Label *mMusicFileLabel, *mMapLabel, *mMiniMapLabel; + gcn::Label *mMusicFileLabel, *mMapLabel, *mMinimapLabel; gcn::Label *mTileMouseLabel, *mFPSLabel; gcn::Label *mParticleCountLabel; }; diff --git a/src/gui/emoteshortcutcontainer.cpp b/src/gui/emoteshortcutcontainer.cpp index 8e37be72..c087fc7e 100644 --- a/src/gui/emoteshortcutcontainer.cpp +++ b/src/gui/emoteshortcutcontainer.cpp @@ -39,8 +39,6 @@ #include "resources/resourcemanager.h" #include "utils/dtor.h" -#include "utils/gettext.h" -#include "utils/stringutils.h" static const int MAX_ITEMS = 12; diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index 44006971..25de201c 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -25,6 +25,7 @@ #include "gui/itempopup.h" #include "gui/palette.h" #include "gui/playerbox.h" +#include "gui/setup.h" #include "gui/viewport.h" #include "equipment.h" @@ -50,31 +51,26 @@ static const int BOX_HEIGHT = 36; // Positions of the boxes, 2nd dimension is X and Y respectively. static const int boxPosition[][2] = { - { 50, 208 }, // EQUIP_LEGS_SLOT - { 8, 123 }, // EQUIP_FIGHT1_SLOT + { 90, 40 }, // EQUIP_TORSO_SLOT { 8, 78 }, // EQUIP_GLOVES_SLOT - { 129, 168 }, // EQUIP_RING2_SLOT + { 70, 0 }, // EQUIP_HEAD_SLOT + { 50, 208 }, // EQUIP_LEGS_SLOT + { 90, 208 }, // EQUIP_FEET_SLOT { 8, 168 }, // EQUIP_RING1_SLOT + { 129, 168 }, // EQUIP_RING2_SLOT + { 50, 40 }, // EQUIP_NECK_SLOT + { 8, 123 }, // EQUIP_FIGHT1_SLOT { 129, 123 }, // EQUIP_FIGHT2_SLOT - { 90, 208 }, // EQUIP_FEET_SLOT - { 50, 40 }, // EQUIP_CAPE_SLOT - { 70, 0 }, // EQUIP_HEAD_SLOT - { 90, 40 }, // EQUIP_TORSO_SLOT - { 129, 78 } // EQUIP_AMMO_SLOT + { 129, 78 } // EQUIP_PROJECTILE_SLOT }; -#ifdef TMWSERV_SUPPORT EquipmentWindow::EquipmentWindow(Equipment *equipment): -#else -EquipmentWindow::EquipmentWindow(): -#endif Window(_("Equipment")), -#ifdef TMWSERV_SUPPORT mEquipment(equipment), -#endif mSelected(-1) { mItemPopup = new ItemPopup; + setupWindow->registerWindowForReset(this); // Control that shows the Player PlayerBox *playerBox = new PlayerBox; @@ -96,16 +92,11 @@ EquipmentWindow::EquipmentWindow(): add(playerBox); add(mUnequip); - for (int i = 0; i < EQUIP_VECTOREND; i++) + for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++) { mEquipBox[i].posX = boxPosition[i][0] + getPadding(); mEquipBox[i].posY = boxPosition[i][1] + getTitleBarHeight(); } - -#ifdef EATHENA_SUPPORT - mEquipment = player_node->mEquipment.get(); - mInventory = player_node->getInventory(); -#endif } EquipmentWindow::~EquipmentWindow() @@ -122,7 +113,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) Window::drawChildren(graphics); - for (int i = 0; i < EQUIP_VECTOREND; i++) + for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++) { if (i == mSelected) { @@ -140,13 +131,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, BOX_WIDTH, BOX_HEIGHT)); -#ifdef TMWSERV_SUPPORT Item *item = mEquipment->getEquipment(i); -#else - Item *item = (i != EQUIP_AMMO_SLOT) ? - mInventory->getItem(mEquipment->getEquipment(i)) : - mInventory->getItem(mEquipment->getArrows()); -#endif if (item) { // Draw Item. @@ -154,8 +139,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) g->drawImage(image, mEquipBox[i].posX + 2, mEquipBox[i].posY + 2); -#ifdef EATHENA_SUPPORT - if (i == EQUIP_AMMO_SLOT) + if (i == EQUIP_PROJECTILE_SLOT) { g->setColor(guiPalette->getColor(Palette::TEXT)); graphics->drawText(toString(item->getQuantity()), @@ -163,7 +147,6 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) mEquipBox[i].posY - getFont()->getHeight(), gcn::Graphics::CENTER); } -#endif } } } @@ -172,13 +155,7 @@ void EquipmentWindow::action(const gcn::ActionEvent &event) { if (event.getId() == "unequip" && mSelected > -1) { -#ifdef TMWSERV_SUPPORT // TODO: merge these! Item *item = mEquipment->getEquipment(mSelected); -#else - Item *item = (mSelected != EQUIP_AMMO_SLOT) ? - mInventory->getItem(mEquipment->getEquipment(mSelected)) : - mInventory->getItem(mEquipment->getArrows()); -#endif Net::getInventoryHandler()->unequipItem(item); setSelected(-1); } @@ -186,20 +163,14 @@ void EquipmentWindow::action(const gcn::ActionEvent &event) Item *EquipmentWindow::getItem(int x, int y) const { - for (int i = 0; i < EQUIP_VECTOREND; i++) + for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++) { gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, BOX_WIDTH, BOX_HEIGHT); if (tRect.isPointInRect(x, y)) { -#ifdef TMWSERV_SUPPORT return mEquipment->getEquipment(i); -#else - return (i != EQUIP_AMMO_SLOT) ? - mInventory->getItem(mEquipment->getEquipment(i)) : - mInventory->getItem(mEquipment->getArrows()); -#endif } } return NULL; @@ -215,15 +186,9 @@ void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent) if (mouseEvent.getButton() == gcn::MouseEvent::LEFT) { // Checks if any of the presses were in the equip boxes. - for (int i = 0; i < EQUIP_VECTOREND; i++) + for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++) { -#ifdef TMWSERV_SUPPORT Item *item = mEquipment->getEquipment(i); -#else - Item *item = (i != EQUIP_AMMO_SLOT) ? - mInventory->getItem(mEquipment->getEquipment(i)) : - mInventory->getItem(mEquipment->getArrows()); -#endif gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, BOX_WIDTH, BOX_HEIGHT); diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h index 8bc350a4..a7b2c0d1 100644 --- a/src/gui/equipmentwindow.h +++ b/src/gui/equipmentwindow.h @@ -24,11 +24,11 @@ #include "gui/widgets/window.h" +#include "equipment.h" #include "guichanfwd.h" #include <guichan/actionlistener.hpp> -class Equipment; class Inventory; class Item; class ItemPopup; @@ -44,11 +44,7 @@ class EquipmentWindow : public Window, public gcn::ActionListener /** * Constructor. */ -#ifdef TMWSERV_SUPPORT EquipmentWindow(Equipment *equipment); -#else - EquipmentWindow(); -#endif /** * Destructor. @@ -64,40 +60,6 @@ class EquipmentWindow : public Window, public gcn::ActionListener void mousePressed(gcn::MouseEvent& mouseEvent); -#ifdef TMWSERV_SUPPORT - enum EquipmentSlots - { - EQUIP_TORSO_SLOT = 0, - EQUIP_ARMS_SLOT = 1, - EQUIP_HEAD_SLOT = 2, - EQUIP_LEGS_SLOT = 3, - EQUIP_FEET_SLOT = 4, - EQUIP_RING1_SLOT = 5, - EQUIP_RING2_SLOT = 6, - EQUIP_NECKLACE_SLOT = 7, - EQUIP_FIGHT1_SLOT = 8, - EQUIP_FIGHT2_SLOT = 9, - EQUIP_PROJECTILE_SLOT = 10, - EQUIP_VECTOREND - }; -#else - enum EquipmentSlots - { - EQUIP_LEGS_SLOT = 0, - EQUIP_FIGHT1_SLOT, - EQUIP_GLOVES_SLOT, - EQUIP_RING2_SLOT, - EQUIP_RING1_SLOT, - EQUIP_FIGHT2_SLOT, - EQUIP_FEET_SLOT, - EQUIP_CAPE_SLOT, - EQUIP_HEAD_SLOT, - EQUIP_TORSO_SLOT, - EQUIP_AMMO_SLOT, - EQUIP_VECTOREND - }; -#endif - private: void mouseExited(gcn::MouseEvent &event); void mouseMoved(gcn::MouseEvent &event); @@ -107,9 +69,6 @@ class EquipmentWindow : public Window, public gcn::ActionListener void setSelected(int index); Equipment *mEquipment; -#ifdef EATHENA_SUPPORT - Inventory *mInventory; -#endif /** * Equipment box. @@ -120,12 +79,12 @@ class EquipmentWindow : public Window, public gcn::ActionListener int posY; }; - EquipBox mEquipBox[EQUIP_VECTOREND]; /**< Equipment Boxes. */ + EquipBox mEquipBox[Equipment::EQUIP_VECTOREND]; /**< Equipment Boxes. */ ItemPopup *mItemPopup; gcn::Button *mUnequip; - int mSelected; /**< Index of selected item. */ + int mSelected; /**< Index of selected item. */ }; extern EquipmentWindow *equipmentWindow; diff --git a/src/gui/guildwindow.cpp b/src/gui/guildwindow.cpp index 6dc86e13..05af7780 100644 --- a/src/gui/guildwindow.cpp +++ b/src/gui/guildwindow.cpp @@ -24,6 +24,7 @@ #include "gui/confirmdialog.h" #include "gui/guildlistbox.h" +#include "gui/setup.h" #include "gui/textdialog.h" #include "gui/widgets/button.h" @@ -41,6 +42,7 @@ #include "utils/dtor.h" #include "utils/gettext.h" +#include "utils/stringutils.h" #include <algorithm> @@ -58,6 +60,7 @@ GuildWindow::GuildWindow(): setMinWidth(200); setMinHeight(280); setDefaultSize(124, 41, 288, 330); + setupWindow->registerWindowForReset(this); // Set button events Id mGuildButton[0] = new Button(_("Create Guild"), "CREATE_GUILD", this); @@ -110,7 +113,8 @@ void GuildWindow::action(const gcn::ActionEvent &event) { // Set focus so that guild name to be created can be typed. mFocus = true; - guildDialog = new TextDialog("Guild Name", "Choose your guild's name", this); + guildDialog = new TextDialog(_("Guild Name"), + _("Choose your guild's name."), this); guildDialog->setOKButtonActionId("CREATE_GUILD_OK"); guildDialog->addActionListener(this); } @@ -118,7 +122,8 @@ void GuildWindow::action(const gcn::ActionEvent &event) { // TODO - Give feedback on whether the invite succeeded mFocus = true; - inviteDialog = new TextDialog("Member Invite", "Who would you like to invite?", this); + inviteDialog = new TextDialog(_("Member Invite"), + _("Who would you like to invite?"), this); inviteDialog->setOKButtonActionId("INVITE_USER_OK"); inviteDialog->addActionListener(this); } @@ -128,7 +133,8 @@ void GuildWindow::action(const gcn::ActionEvent &event) if (guild) { Net::ChatServer::Guild::quitGuild(guild); - localChatTab->chatLog("Guild " + mGuildTabs->getSelectedTab()->getCaption() + " quit", BY_SERVER); + localChatTab->chatLog(strprintf(_("Guild %s quit."), + mGuildTabs->getSelectedTab()->getCaption().c_str()), BY_SERVER); } } else if (eventId == "CREATE_GUILD_OK") @@ -144,7 +150,8 @@ void GuildWindow::action(const gcn::ActionEvent &event) // Defocus dialog mFocus = false; - localChatTab->chatLog("Creating Guild called " + name, BY_SERVER); + localChatTab->chatLog(strprintf(_("Creating guild called %s."), + name.c_str()), BY_SERVER); guildDialog->scheduleDelete(); } else if (eventId == "INVITE_USER_OK") @@ -157,7 +164,7 @@ void GuildWindow::action(const gcn::ActionEvent &event) // Defocus dialog mFocus = false; - localChatTab->chatLog("Invited user " + name, BY_SERVER); + localChatTab->chatLog(strprintf(_("Invited user %s."), name.c_str()), BY_SERVER); inviteDialog->scheduleDelete(); } else if (eventId == "yes") @@ -233,10 +240,11 @@ short GuildWindow::getSelectedGuild() void GuildWindow::openAcceptDialog(const std::string &inviterName, const std::string &guildName) { - std::string msg = inviterName + " has invited you to join the guild " + guildName; + std::string msg = strprintf(_("%s has invited you to join the guild %s."), + inviterName.c_str(), guildName.c_str()); localChatTab->chatLog(msg, BY_SERVER); - acceptDialog = new ConfirmDialog("Accept Guild Invite", msg, this); + acceptDialog = new ConfirmDialog(_("Accept Guild Invite"), msg, this); acceptDialog->addActionListener(this); invitedGuild = guildName; diff --git a/src/gui/help.cpp b/src/gui/help.cpp index ddcf7b49..e28f64e3 100644 --- a/src/gui/help.cpp +++ b/src/gui/help.cpp @@ -25,6 +25,7 @@ #include "gui/widgets/browserbox.h" #include "gui/widgets/layout.h" #include "gui/widgets/scrollarea.h" +#include "gui/setup.h" #include "resources/resourcemanager.h" @@ -38,6 +39,7 @@ HelpWindow::HelpWindow(): setContentSize(455, 350); setWindowName("Help"); setResizable(true); + setupWindow->registerWindowForReset(this); setDefaultSize(500, 400, ImageRect::CENTER); diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 06e43eac..50465a50 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -23,6 +23,7 @@ #include "gui/itemamount.h" #include "gui/itemcontainer.h" +#include "gui/setup.h" #include "gui/sdlinput.h" #include "gui/viewport.h" @@ -57,6 +58,7 @@ InventoryWindow::InventoryWindow(int invSize): mItemDesc(false) { setWindowName("Inventory"); + setupWindow->registerWindowForReset(this); setResizable(true); setCloseButton(true); setSaveVisible(true); diff --git a/src/gui/itemamount.cpp b/src/gui/itemamount.cpp index 87df46c1..20834c54 100644 --- a/src/gui/itemamount.cpp +++ b/src/gui/itemamount.cpp @@ -90,9 +90,9 @@ ItemAmountWindow::ItemAmountWindow(Usage usage, Window *parent, Item *item, mItemIcon = new Icon(image); // Buttons - Button *minusButton = new Button("-", "minus", this); - Button *plusButton = new Button("+", "plus", this); - Button *okButton = new Button(_("Ok"), "ok", this); + Button *minusButton = new Button(_("-"), "dec", this); + Button *plusButton = new Button(_("+"), "inc", this); + Button *okButton = new Button(_("OK"), "ok", this); Button *cancelButton = new Button(_("Cancel"), "cancel", this); Button *addAllButton = new Button(_("All"), "all", this); @@ -172,11 +172,11 @@ void ItemAmountWindow::action(const gcn::ActionEvent &event) { close(); } - else if (event.getId() == "plus" && amount < mMax) + else if (event.getId() == "inc" && amount < mMax) { amount++; } - else if (event.getId() == "minus" && amount > 1) + else if (event.getId() == "dec" && amount > 1) { amount--; } diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp index e1822e03..39dc603a 100644 --- a/src/gui/itempopup.cpp +++ b/src/gui/itempopup.cpp @@ -88,8 +88,9 @@ void ItemPopup::setItem(const ItemInfo &item) mItemDesc->setTextWrapped(item.getDescription(), 196); mItemEffect->setTextWrapped(item.getEffect(), 196); - mItemWeight->setTextWrapped(_("Weight: ") + - Units::formatWeight(item.getWeight()), 196); + mItemWeight->setTextWrapped(strprintf(_("Weight: %s"), + Units::formatWeight(item.getWeight()).c_str()), + 196); int minWidth = mItemName->getWidth(); diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 77f2e137..3b63eff1 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -70,7 +70,7 @@ LoginDialog::LoginDialog(LoginData *loginData): mServerDropDown = new DropDown(mServerList); #endif - mKeepCheck = new CheckBox(_("Remember Username"), mLoginData->remember); + mKeepCheck = new CheckBox(_("Remember username"), mLoginData->remember); mOkButton = new Button(_("OK"), "ok", this); mCancelButton = new Button(_("Cancel"), "cancel", this); mRegisterButton = new Button(_("Register"), "register", this); diff --git a/src/gui/magic.cpp b/src/gui/magic.cpp index c47faa18..6e314656 100644 --- a/src/gui/magic.cpp +++ b/src/gui/magic.cpp @@ -22,6 +22,7 @@ #include "gui/magic.h" #include "gui/widgets/button.h" +#include "gui/setup.h" #include "localplayer.h" @@ -35,6 +36,7 @@ MagicDialog::MagicDialog(): setCloseButton(true); setSaveVisible(true); setDefaultSize(255, 30, 175, 225); + setupWindow->registerWindowForReset(this); mSpellButtons.resize(4); diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index d1c99b84..40526a22 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -31,6 +31,7 @@ #include "player.h" #include "gui/palette.h" +#include "gui/setup.h" #include "resources/image.h" #include "resources/resourcemanager.h" @@ -47,12 +48,13 @@ Minimap::Minimap(): mWidthProportion(0.5), mHeightProportion(0.5) { - setWindowName("MiniMap"); + setWindowName("Minimap"); mShow = config.getValue(getWindowName() + "Show", true); setDefaultSize(5, 25, 100, 100); // set this to false as the minimap window size is changed //depending on the map size setResizable(false); + setupWindow->registerWindowForReset(this); setDefaultVisible(true); setSaveVisible(true); diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp index 65d2391d..4cb0e1ac 100644 --- a/src/gui/ministatus.cpp +++ b/src/gui/ministatus.cpp @@ -22,7 +22,7 @@ #include "gui/ministatus.h" #include "gui/gui.h" -#include "gui/status.h" +#include "gui/statuswindow.h" #include "gui/widgets/progressbar.h" @@ -33,34 +33,30 @@ #include "utils/stringutils.h" +extern volatile int tick_time; + MiniStatusWindow::MiniStatusWindow(): Popup("MiniStatus") { - mHpBar = new ProgressBar(0.0f, 100, 20, gcn::Color(0, 171, 34)); -#ifdef EATHENA_SUPPORT - mMpBar = new ProgressBar(0.0f, 100, 20, gcn::Color(26, 102, 230)); - mXpBar = new ProgressBar(0.0f, 100, 20, gcn::Color(143, 192, 211)); -#endif - + mHpBar = new ProgressBar((float) player_node->getHp() + / (float) player_node->getMaxHp(), + 100, 20, gcn::Color(0, 171, 34)); + mMpBar = new ProgressBar((float) player_node->getMaxMP() + / (float) player_node->getMaxMP(), + 100, 20, gcn::Color(26, 102, 230)); + mXpBar = new ProgressBar((float) player_node->getExp() + / player_node->getExpNeeded(), + 100, 20, gcn::Color(143, 192, 211)); mHpBar->setPosition(0, 3); -#ifdef EATHENA_SUPPORT mMpBar->setPosition(mHpBar->getWidth() + 3, 3); mXpBar->setPosition(mMpBar->getX() + mMpBar->getWidth() + 3, 3); -#endif add(mHpBar); -#ifdef EATHENA_SUPPORT add(mMpBar); add(mXpBar); -#endif -#ifdef EATHENA_SUPPORT setContentSize(mXpBar->getX() + mXpBar->getWidth(), mXpBar->getY() + mXpBar->getHeight()); -#else - setContentSize(mHpBar->getX() + mHpBar->getWidth(), - mHpBar->getY() + mHpBar->getHeight()); -#endif setVisible((bool) config.getValue(getPopupName() + "Visible", true)); } @@ -81,14 +77,37 @@ void MiniStatusWindow::eraseIcon(int index) mIcons.erase(mIcons.begin() + index); } -extern volatile int tick_time; +void MiniStatusWindow::drawIcons(Graphics *graphics) +{ + // Draw icons + int icon_x = mXpBar->getX() + mXpBar->getWidth() + 4; + for (unsigned int i = 0; i < mIcons.size(); i++) { + if (mIcons[i]) { + mIcons[i]->draw(graphics, icon_x, 3); + icon_x += 2 + mIcons[i]->getWidth(); + } + } +} -void MiniStatusWindow::update() +void MiniStatusWindow::update(int id) { - StatusWindow::updateHPBar(mHpBar); -#ifdef EATHENA_SUPPORT - StatusWindow::updateMPBar(mMpBar); - StatusWindow::updateXPBar(mXpBar); + if (id == StatusWindow::HP) + { + StatusWindow::updateHPBar(mHpBar); + } + else if (id == StatusWindow::MP) + { + StatusWindow::updateMPBar(mMpBar); + } + else if (id == StatusWindow::EXP) + { + StatusWindow::updateXPBar(mXpBar); + } +} + +void MiniStatusWindow::logic() +{ + Popup::logic(); // Displays the number of monsters to next lvl // (disabled for now but interesting idea) @@ -102,31 +121,8 @@ void MiniStatusWindow::update() << config.getValue("xpBarMonsterCounterName", "Monsters") <<" left..."; } */ -#endif for (unsigned int i = 0; i < mIcons.size(); i++) if (mIcons[i]) mIcons[i]->update(tick_time * 10); } - -void MiniStatusWindow::draw(gcn::Graphics *graphics) -{ - update(); - drawChildren(graphics); -} - -void MiniStatusWindow::drawIcons(Graphics *graphics) -{ - // Draw icons -#ifdef TMWSERV_SUPPORT - int icon_x = mHpBar->getX() + mHpBar->getWidth() + 4; -#else - int icon_x = mXpBar->getX() + mXpBar->getWidth() + 4; -#endif - for (unsigned int i = 0; i < mIcons.size(); i++) { - if (mIcons[i]) { - mIcons[i]->draw(graphics, icon_x, 3); - icon_x += 2 + mIcons[i]->getWidth(); - } - } -} diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h index 56f53908..82ab0adc 100644 --- a/src/gui/ministatus.h +++ b/src/gui/ministatus.h @@ -40,8 +40,6 @@ class MiniStatusWindow : public Popup public: MiniStatusWindow(); - void draw(gcn::Graphics *graphics); - /** * Sets one of the icons. */ @@ -51,22 +49,24 @@ class MiniStatusWindow : public Popup void drawIcons(Graphics *graphics); - private: - /** - * Updates this dialog with values from player_node. - */ - void update(); + void update(int id); // Same types as status window + + void logic(); // Updates icons + void draw(gcn::Graphics *graphics) + { drawChildren(graphics); } + + private: /* * Mini Status Bars */ ProgressBar *mHpBar; -#ifdef EATHENA_SUPPORT ProgressBar *mMpBar; ProgressBar *mXpBar; -#endif std::vector<AnimatedSprite *> mIcons; }; +extern MiniStatusWindow *miniStatusWindow; + #endif diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp index afcc150d..1956ba85 100644 --- a/src/gui/npcdialog.cpp +++ b/src/gui/npcdialog.cpp @@ -28,6 +28,7 @@ #include "gui/widgets/scrollarea.h" #include "gui/widgets/textbox.h" #include "gui/widgets/textfield.h" +#include "gui/setup.h" #include "npc.h" @@ -54,6 +55,7 @@ NpcDialog::NpcDialog() // Basic Window Setup setWindowName("NpcText"); setResizable(true); + setupWindow->registerWindowForReset(this); setMinWidth(200); setMinHeight(150); @@ -91,8 +93,8 @@ NpcDialog::NpcDialog() mButton = new Button("", "ok", this); //Setup more and less buttons (int input) - mPlusButton = new Button("+", "plus", this); - mMinusButton = new Button("-", "minus", this); + mPlusButton = new Button(_("+"), "inc", this); + mMinusButton = new Button(_("-"), "dec", this); int width = std::max(mButton->getFont()->getWidth(CAPTION_WAITING), mButton->getFont()->getWidth(CAPTION_NEXT)); @@ -154,7 +156,8 @@ void NpcDialog::action(const gcn::ActionEvent &event) if (mActionState == NPC_ACTION_NEXT) { nextDialog(); - addText("\n> Next\n"); + // TRANSLATORS: Please leave the \n sequences intact. + addText(_("\n> Next\n")); } else if (mActionState == NPC_ACTION_CLOSE) { @@ -209,11 +212,11 @@ void NpcDialog::action(const gcn::ActionEvent &event) mIntField->setValue(mDefaultInt); } } - else if (event.getId() == "plus") + else if (event.getId() == "inc") { mIntField->setValue(mIntField->getValue() + 1); } - else if (event.getId() == "minus") + else if (event.getId() == "dec") { mIntField->setValue(mIntField->getValue() - 1); } diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp index f43e1440..d2e9468d 100644 --- a/src/gui/outfitwindow.cpp +++ b/src/gui/outfitwindow.cpp @@ -58,9 +58,9 @@ OutfitWindow::OutfitWindow(): setCloseButton(true); setDefaultSize(250, 250, 118, 180); //160 - mPreviousButton = new Button("<", "previous", this); - mNextButton = new Button(">", "next", this); - mCurrentLabel = new Label("Outfit: 1"); + mPreviousButton = new Button(_("<"), "previous", this); + mNextButton = new Button(_(">"), "next", this); + mCurrentLabel = new Label(strprintf(_("Outfit: %d"), 1)); mCurrentLabel->setAlignment(gcn::Graphics::CENTER); mUnequipCheck = new CheckBox(_("Unequip first"), config.getValue("OutfitUnequip", true)); @@ -140,7 +140,7 @@ void OutfitWindow::action(const gcn::ActionEvent &event) mCurrentOutfit = 9; } } - mCurrentLabel->setCaption("Outfit: " + toString(mCurrentOutfit + 1)); + mCurrentLabel->setCaption(strprintf(_("Outfit: %d"), mCurrentOutfit + 1)); } void OutfitWindow::wearOutfit(int outfit) @@ -153,14 +153,8 @@ void OutfitWindow::wearOutfit(int outfit) //non vis is 3,4,7 if (i != 3 && i != 4 && i != 7) { -#ifdef TMWSERV_SUPPORT if (!(item = player_node->mEquipment.get()->getEquipment(i))) continue; -#else - if (!(item = player_node->getInventory()->getItem( - player_node->mEquipment.get()->getEquipment(i)))) - continue; -#endif Net::getInventoryHandler()->unequipItem(item); } } diff --git a/src/gui/palette.cpp b/src/gui/palette.cpp index 4d1233e8..a807dcd6 100644 --- a/src/gui/palette.cpp +++ b/src/gui/palette.cpp @@ -82,18 +82,21 @@ Palette::Palette() : addColor(SHADOW, 0x000000, STATIC, indent + _("Text Shadow")); addColor(OUTLINE, 0x000000, STATIC, indent + _("Text Outline")); addColor(PROGRESS_BAR, 0xffffff, STATIC, indent + _("Progress Bar Labels")); + addColor(BUTTON, 0xc8ad00, STATIC, indent + _("Buttons")); + addColor(BUTTON_DISABLED, 0x828282, STATIC, indent + _("Disabled Buttons")); + addColor(TAB, 0xc8ad00, STATIC, indent + _("Tabs")); addColor(BACKGROUND, 0xffffff, STATIC, _("Background")); addColor(HIGHLIGHT, 0xebc873, STATIC, _("Highlight"), 'H'); addColor(TAB_HIGHLIGHT, 0xff0000, PULSE, indent + _("Tab Highlight")); - addColor(SHOP_WARNING, 0x910000, STATIC, indent + _("Item too expensive")); - addColor(ITEM_EQUIPPED, 0x000091, STATIC, indent + _("Item is equipped")); + addColor(SHOP_WARNING, 0x910000, STATIC, indent + _("Item Too Expensive")); + addColor(ITEM_EQUIPPED, 0x000091, STATIC, indent + _("Item Is Equipped")); addColor(CHAT, 0x000000, STATIC, _("Chat"), 'C'); addColor(GM, 0xff0000, STATIC, indent + _("GM"), 'G'); addColor(PLAYER, 0x1fa052, STATIC, indent + _("Player"), 'Y'); - addColor(WHISPER, 0x0000ff, STATIC, indent + _("Whisper"), 'W'); + addColor(WHISPER, 0x00feaf, STATIC, indent + _("Whisper"), 'W'); addColor(IS, 0xa08527, STATIC, indent + _("Is"), 'I'); addColor(PARTY, 0xf48055, STATIC, indent + _("Party"), 'P'); addColor(SERVER, 0x8415e2, STATIC, indent + _("Server"), 'S'); @@ -112,10 +115,10 @@ Palette::Palette() : addColor(HEAD, 0x527fa4, STATIC, indent + _("Hats")); addColor(USABLE, 0x268d24, STATIC, indent + _("Usables")); addColor(TORSO, 0xd12aa4, STATIC, indent + _("Shirts")); - addColor(ONEHAND, 0xf42a2a, STATIC, indent + _("1 Handed Weapons")); + addColor(ONEHAND, 0xf42a2a, STATIC, indent + _("One Handed Weapons")); addColor(LEGS, 0x699900, STATIC, indent + _("Pants")); addColor(FEET, 0xaa1d48, STATIC, indent + _("Shoes")); - addColor(TWOHAND, 0xf46d0e, STATIC, indent + _("2 Handed Weapons")); + addColor(TWOHAND, 0xf46d0e, STATIC, indent + _("Two Handed Weapons")); addColor(SHIELD, 0x9c2424, STATIC, indent + _("Shields")); addColor(RING, 0x0000ff, STATIC, indent + _("Rings")); addColor(NECKLACE, 0xff00ff, STATIC, indent + _("Necklaces")); @@ -126,9 +129,9 @@ Palette::Palette() : addColor(PICKUP_INFO, 0x28dc28, STATIC, indent + _("Pickup Notification")); addColor(EXP_INFO, 0xffff00, STATIC, indent + _("Exp Notification")); addColor(HIT_PLAYER_MONSTER, 0x0064ff, STATIC, - indent + _("Player hits Monster")); + indent + _("Player Hits Monster")); addColor(HIT_MONSTER_PLAYER, 0xff3232, STATIC, - indent + _("Monster hits Player")); + indent + _("Monster Hits Player")); addColor(HIT_CRITICAL, 0xff0000, RAINBOW, indent + _("Critical Hit")); addColor(MISS, 0xffff00, STATIC, indent + _("Misses")); diff --git a/src/gui/palette.h b/src/gui/palette.h index 1dec2a60..c68a4e1c 100644 --- a/src/gui/palette.h +++ b/src/gui/palette.h @@ -57,6 +57,9 @@ class Palette : public gcn::ListModel ENTRY(SHADOW)\ ENTRY(OUTLINE)\ ENTRY(PROGRESS_BAR)\ + ENTRY(BUTTON)\ + ENTRY(BUTTON_DISABLED)\ + ENTRY(TAB)\ ENTRY(BACKGROUND)\ ENTRY(HIGHLIGHT)\ ENTRY(TAB_HIGHLIGHT)\ diff --git a/src/gui/partywindow.cpp b/src/gui/partywindow.cpp index f66ffaac..d4b084ce 100644 --- a/src/gui/partywindow.cpp +++ b/src/gui/partywindow.cpp @@ -22,6 +22,7 @@ #include "gui/partywindow.h" #include "gui/widgets/chattab.h" +#include "gui/setup.h" #include "beingmanager.h" #include "player.h" @@ -56,6 +57,7 @@ PartyWindow::PartyWindow() : setMinWidth(120); setMinHeight(55); setDefaultSize(590, 200, 150, 60); + setupWindow->registerWindowForReset(this); loadWindowState(); } diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index e12ca822..0f0df756 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -34,6 +34,7 @@ #include "graphics.h" #include "item.h" #include "localplayer.h" +#include "log.h" #include "npc.h" #include "playerrelations.h" @@ -72,10 +73,6 @@ void PopupMenu::showPopup(int x, int y, Being *being) mBeingId = being->getId(); mBrowserBox->clearRows(); - // Any being's name can be added to chat - if (being->getType() != Being::UNKNOWN) - mBrowserBox->addRow(_("@@name|Add name to chat@@")); - const std::string &name = being->getType() == Being::NPC ? being->getName().substr(0, being->getName().size() - 6) : being->getName(); @@ -86,42 +83,68 @@ void PopupMenu::showPopup(int x, int y, Being *being) { // Players can be traded with. Later also follow and // add as buddy will be options in this menu. - mBrowserBox->addRow(strprintf(_("@@trade|Trade With %s@@"), name.c_str())); - mBrowserBox->addRow(strprintf(_("@@attack|Attack %s@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@trade|%s@@", + strprintf(_("Trade with %s"), + name.c_str()).c_str())); + // TRANSLATORS: Attacking a player. + mBrowserBox->addRow(strprintf("@@attack|%s@@", + strprintf(_("Attack %s"), + name.c_str()).c_str())); mBrowserBox->addRow("##3---"); switch (player_relations.getRelation(name)) { case PlayerRelation::NEUTRAL: - mBrowserBox->addRow(strprintf(_("@@friend|Befriend %s@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@friend|%s@@", + strprintf(_("Befriend %s"), + name.c_str()).c_str())); case PlayerRelation::FRIEND: - mBrowserBox->addRow(strprintf(_("@@disregard|Disregard %s@@"), name.c_str())); - mBrowserBox->addRow(strprintf(_("@@ignore|Ignore %s@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@disregard|%s@@", + strprintf(_("Disregard %s"), + name.c_str()).c_str())); + mBrowserBox->addRow(strprintf("@@ignore|%s@@", + strprintf(_("Ignore %s"), + name.c_str()).c_str())); break; case PlayerRelation::DISREGARDED: - mBrowserBox->addRow(strprintf(_("@@unignore|Un-Ignore %s@@"), name.c_str())); - mBrowserBox->addRow(strprintf(_("@@ignore|Completely ignore %s@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@unignore|%s@@", + strprintf(_("Unignore %s"), + name.c_str()).c_str())); + mBrowserBox->addRow(strprintf("@@ignore|%s@@", + strprintf(_("Completely ignore %s"), + name.c_str()).c_str())); break; case PlayerRelation::IGNORED: - mBrowserBox->addRow(strprintf(_("@@unignore|Un-Ignore %s@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@unignore|%s@@", + strprintf(_("Unignore %s"), + name.c_str()).c_str())); break; } - //mBrowserBox->addRow(_(strprintf("@@follow|Follow %s@@"), name.c_str())); - //mBrowserBox->addRow(_("@@buddy|Add ") + name + " to Buddy List@@"); + /*mBrowserBox->addRow(strprintf("@@follow|%s@@", + strprintf(_("Follow %s"), + name.c_str()).c_str()));*/ + /*mBrowserBox->addRow(strprintf("@@buddy|%s@@", + strprintf(_("Add %s to Buddy List"), + name.c_str()).c_str()));*/ #ifdef TMWSERV_SUPPORT - mBrowserBox->addRow(strprintf(_("@@guild|Invite %s to join your guild@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@guild|%s@@", + strprintf(_("Invite %s to join your guild"), + name.c_str()).c_str())); #endif if (player_node->isInParty()) - mBrowserBox->addRow(strprintf(_("@@party|Invite %s to join your party@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@pickup|%s@@", + strprintf(_("Invite %s to join your party"), + name.c_str()).c_str())); if (player_node->isGM()) { mBrowserBox->addRow("##3---"); - mBrowserBox->addRow(_("@@admin-kick|Kick player@@")); + mBrowserBox->addRow(strprintf("@@admin-kick|%s@@", + _("Kick player"))); } } break; @@ -129,16 +152,21 @@ void PopupMenu::showPopup(int x, int y, Being *being) case Being::NPC: // NPCs can be talked to (single option, candidate for removal // unless more options would be added) - mBrowserBox->addRow(strprintf(_("@@talk|Talk To %s@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@talk|%s@@", + strprintf(_("Talk to %s"), + name.c_str()).c_str())); break; case Being::MONSTER: { // Monsters can be attacked - mBrowserBox->addRow(strprintf(_("@@attack|Attack %s@@"), name.c_str())); + mBrowserBox->addRow(strprintf("@@attack|%s@@", + strprintf(_("Attack %s"), + name.c_str()).c_str())); if (player_node->isGM()) - mBrowserBox->addRow(_("@@admin-kick|Kick monster@@")); + mBrowserBox->addRow(strprintf("@@admin-kick|%s@@", + _("Kick monster"))); } break; @@ -146,10 +174,11 @@ void PopupMenu::showPopup(int x, int y, Being *being) /* Other beings aren't interesting... */ return; } + mBrowserBox->addRow(strprintf("@@name|%s@@", _("Add name to chat"))); - //browserBox->addRow("@@look|Look To@@"); + //mBrowserBox->addRow(strprintf("@@look|%s@@", _("Look To"))); mBrowserBox->addRow("##3---"); - mBrowserBox->addRow(_("@@cancel|Cancel@@")); + mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel"))); showPopup(x, y); } @@ -162,12 +191,13 @@ void PopupMenu::showPopup(int x, int y, FloorItem *floorItem) // Floor item can be picked up (single option, candidate for removal) std::string name = ItemDB::get(mFloorItem->getItemId()).getName(); - mBrowserBox->addRow(strprintf(_("@@pickup|Pick up %s@@"), name.c_str())); - mBrowserBox->addRow(_("@@chat|Add to chat@@")); + mBrowserBox->addRow(strprintf("@@pickup|%s@@", strprintf(_("Pick up %s"), + name.c_str()).c_str())); + mBrowserBox->addRow(strprintf("@@chat|%s@@", _("Add to chat"))); - //browserBox->addRow("@@look|Look To@@"); + //mBrowserBox->addRow(strprintf("@@look|%s@@", _("Look To"))); mBrowserBox->addRow("##3---"); - mBrowserBox->addRow(_("@@cancel|Cancel@@")); + mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel"))); showPopup(x, y); } @@ -193,13 +223,11 @@ void PopupMenu::handleLink(const std::string &link) Net::getTradeHandler()->request(being); tradePartnerName = being->getName(); } -#ifdef EATHENA_SUPPORT // Attack action else if (link == "attack" && being) { player_node->attack(being, true); } -#endif else if (link == "unignore" && being && being->getType() == Being::PLAYER) @@ -332,7 +360,7 @@ void PopupMenu::handleLink(const std::string &link) // Unknown actions else if (link != "cancel") { - std::cout << link << std::endl; + logger->log("PopupMenu: Warning, unknown action '%s'", link.c_str()); } setVisible(false); @@ -353,34 +381,34 @@ void PopupMenu::showPopup(int x, int y, Item *item, bool isInventory) if (item->isEquipment()) { if (item->isEquipped()) - mBrowserBox->addRow(_("@@use|Unequip@@")); + mBrowserBox->addRow(strprintf("@@use|%s@@", _("Unequip"))); else - mBrowserBox->addRow(_("@@use|Equip@@")); + mBrowserBox->addRow(strprintf("@@use|%s@@", _("Equip"))); } else - mBrowserBox->addRow(_("@@use|Use@@")); + mBrowserBox->addRow(strprintf("@@use|%s@@", _("Use"))); - mBrowserBox->addRow(_("@@drop|Drop@@")); + mBrowserBox->addRow(strprintf("@@drop|%s@@", _("Drop"))); if (Net::getInventoryHandler()->canSplit(item)) { - mBrowserBox->addRow(_("@@split|Split@@")); + mBrowserBox->addRow(strprintf("@@split|%s@@", _("Split"))); } if (player_node->getInStorage()) { - mBrowserBox->addRow(_("@@store|Store@@")); + mBrowserBox->addRow(strprintf("@@store|%s@@", _("Store"))); } } // Assume in storage for now // TODO: make this whole system more flexible, if needed else { - mBrowserBox->addRow(_("@@retrieve|Retrieve@@")); + mBrowserBox->addRow(strprintf("@@retrieve|%s@@", _("Retrieve"))); } - mBrowserBox->addRow(_("@@chat|Add to chat@@")); + mBrowserBox->addRow(strprintf("@@chat|%s@@", _("Add to chat"))); mBrowserBox->addRow("##3---"); - mBrowserBox->addRow(_("@@cancel|Cancel@@")); + mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel"))); showPopup(x, y); } diff --git a/src/gui/recorder.cpp b/src/gui/recorder.cpp index 3307d904..b2679553 100644 --- a/src/gui/recorder.cpp +++ b/src/gui/recorder.cpp @@ -28,6 +28,7 @@ #include "gui/widgets/layout.h" #include "gui/widgets/windowcontainer.h" +#include "utils/gettext.h" #include "utils/stringutils.h" #include <physfs.h> diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 2b897641..f1313a5e 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -160,13 +160,13 @@ void RegisterDialog::action(const gcn::ActionEvent &event) const std::string user = mUserField->getText(); logger->log("RegisterDialog::register Username is %s", user.c_str()); - std::string errorMsg; + std::string errorMessage; int error = 0; if (user.length() < LEN_MIN_USERNAME) { // Name too short - errorMsg = strprintf + errorMessage = strprintf (_("The username needs to be at least %d characters long."), LEN_MIN_USERNAME); error = 1; @@ -174,7 +174,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event) else if (user.length() > LEN_MAX_USERNAME - 1 ) { // Name too long - errorMsg = strprintf + errorMessage = strprintf (_("The username needs to be less than %d characters long."), LEN_MAX_USERNAME); error = 1; @@ -182,7 +182,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event) else if (mPasswordField->getText().length() < LEN_MIN_PASSWORD) { // Pass too short - errorMsg = strprintf + errorMessage = strprintf (_("The password needs to be at least %d characters long."), LEN_MIN_PASSWORD); error = 2; @@ -190,7 +190,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event) else if (mPasswordField->getText().length() > LEN_MAX_PASSWORD - 1 ) { // Pass too long - errorMsg = strprintf + errorMessage = strprintf (_("The password needs to be less than %d characters long."), LEN_MAX_PASSWORD); error = 2; @@ -198,7 +198,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event) else if (mPasswordField->getText() != mConfirmField->getText()) { // Password does not match with the confirmation one - errorMsg = _("Passwords do not match."); + errorMessage = _("Passwords do not match."); error = 2; } @@ -219,7 +219,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event) mWrongDataNoticeListener->setTarget(this->mPasswordField); } - OkDialog *dlg = new OkDialog(_("Error"), errorMsg); + OkDialog *dlg = new OkDialog(_("Error"), errorMessage); dlg->addActionListener(mWrongDataNoticeListener); } else diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 28288ef4..4082b881 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -21,6 +21,7 @@ #include "gui/sell.h" +#include "gui/setup.h" #include "gui/shop.h" #include "gui/shoplistbox.h" @@ -47,6 +48,7 @@ SellDialog::SellDialog(): mMaxItems(0), mAmountItems(0) { setWindowName("Sell"); + setupWindow->registerWindowForReset(this); setResizable(true); setCloseButton(true); setMinWidth(260); @@ -67,8 +69,8 @@ SellDialog::SellDialog(): mMoneyLabel = new Label(strprintf(_("Price: %s / Total: %s"), "", "")); - mIncreaseButton = new Button("+", "+", this); - mDecreaseButton = new Button("-", "-", this); + mIncreaseButton = new Button(_("+"), "inc", this); + mDecreaseButton = new Button(_("-"), "dec", this); mSellButton = new Button(_("Sell"), "sell", this); mQuitButton = new Button(_("Quit"), "quit", this); mAddMaxButton = new Button(_("Max"), "max", this); @@ -159,13 +161,13 @@ void SellDialog::action(const gcn::ActionEvent &event) mAmountItems = (int) mSlider->getValue(); updateButtonsAndLabels(); } - else if (event.getId() == "+" && mAmountItems < mMaxItems) + else if (event.getId() == "inc" && mAmountItems < mMaxItems) { mAmountItems++; mSlider->setValue(mAmountItems); updateButtonsAndLabels(); } - else if (event.getId() == "-" && mAmountItems > 1) + else if (event.getId() == "dec" && mAmountItems > 1) { mAmountItems--; mSlider->setValue(mAmountItems); diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp index 5d08a2ec..bd6b7d4b 100644 --- a/src/gui/serverdialog.cpp +++ b/src/gui/serverdialog.cpp @@ -71,7 +71,7 @@ void ServersListModel::addElement(Server server) } ServerDialog::ServerDialog(LoginData *loginData): - Window(_("Choose your server")), mLoginData(loginData) + Window(_("Choose Your Server")), mLoginData(loginData) { gcn::Label *serverLabel = new Label(_("Server:")); gcn::Label *portLabel = new Label(_("Port:")); diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index aebcf61b..2f0d78ca 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -37,29 +37,7 @@ #include "utils/dtor.h" #include "utils/gettext.h" -extern Window *chatWindow; extern Window *statusWindow; -extern Window *buyDialog; -extern Window *sellDialog; -extern Window *buySellDialog; -extern Window *inventoryWindow; -extern Window *npcTextDialog; -extern Window *npcStringDialog; -extern Window *skillDialog; -extern Window *partyWindow; -extern Window *minimap; -extern Window *equipmentWindow; -extern Window *tradeWindow; -extern Window *helpWindow; -extern Window *debugWindow; -extern Window *itemShortcutWindow; -extern Window *emoteShortcutWindow; -#ifdef TMWSERV_SUPPORT -extern Window *magicDialog; -extern Window *guildWindow; -#else -extern Window *storageWindow; -#endif Setup::Setup(): Window(_("Setup")) @@ -137,29 +115,11 @@ void Setup::action(const gcn::ActionEvent &event) if (!statusWindow) return; - chatWindow->resetToDefaultSize(); - statusWindow->resetToDefaultSize(); - buyDialog->resetToDefaultSize(); - sellDialog->resetToDefaultSize(); -#ifdef EATHENA_SUPPORT - buySellDialog->resetToDefaultSize(); -#endif - inventoryWindow->resetToDefaultSize(); - skillDialog->resetToDefaultSize(); - partyWindow->resetToDefaultSize(); - minimap->resetToDefaultSize(); - equipmentWindow->resetToDefaultSize(); - tradeWindow->resetToDefaultSize(); - helpWindow->resetToDefaultSize(); - debugWindow->resetToDefaultSize(); - itemShortcutWindow->resetToDefaultSize(); - emoteShortcutWindow->resetToDefaultSize(); -#ifdef TMWSERV_SUPPORT - magicDialog->resetToDefaultSize(); - guildWindow->resetToDefaultSize(); -#else - storageWindow->resetToDefaultSize(); -#endif + for (std::list<Window*>::iterator it = mWindowsToReset.begin(); + it != mWindowsToReset.end(); it++) + { + (*it)->resetToDefaultSize(); + } } } @@ -168,4 +128,9 @@ void Setup::setInGame(bool inGame) mResetWindows->setEnabled(inGame); } +void Setup::registerWindowForReset(Window *window) +{ + mWindowsToReset.push_back(window); +} + Setup *setupWindow; diff --git a/src/gui/setup.h b/src/gui/setup.h index 630d5eaa..6000adfa 100644 --- a/src/gui/setup.h +++ b/src/gui/setup.h @@ -61,8 +61,14 @@ class Setup : public Window, public gcn::ActionListener */ void setInGame(bool inGame); + void registerWindowForReset(Window *window); + + void clearWindowsForReset() + { mWindowsToReset.clear(); } + private: std::list<SetupTab*> mTabs; + std::list<Window*> mWindowsToReset; gcn::Button *mResetWindows; }; diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp index 9da74c2e..990a3ce8 100644 --- a/src/gui/setup_audio.cpp +++ b/src/gui/setup_audio.cpp @@ -91,7 +91,7 @@ void Setup_Audio::apply() } catch (const char *err) { - new OkDialog("Sound Engine", err); + new OkDialog(_("Sound Engine"), err); logger->log("Warning: %s", err); } } diff --git a/src/gui/setup_colors.cpp b/src/gui/setup_colors.cpp index efa03ba4..7e8b8946 100644 --- a/src/gui/setup_colors.cpp +++ b/src/gui/setup_colors.cpp @@ -68,7 +68,7 @@ Setup_Colors::Setup_Colors() : mPreviewBox->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_NEVER); - mGradTypeLabel = new Label(_("Type: ")); + mGradTypeLabel = new Label(_("Type:")); mGradTypeSlider = new Slider(0, 3); mGradTypeSlider->setWidth(200); @@ -90,7 +90,7 @@ Setup_Colors::Setup_Colors() : mGradTypeText->setCaption(longText); - mGradDelayLabel = new Label(_("Delay: ")); + mGradDelayLabel = new Label(_("Delay:")); mGradDelayText = new TextField(); mGradDelayText->setWidth(40); @@ -105,7 +105,7 @@ Setup_Colors::Setup_Colors() : mGradDelaySlider->addActionListener(this); mGradDelaySlider->setEnabled(false); - mRedLabel = new Label(_("Red: ")); + mRedLabel = new Label(_("Red:")); mRedText = new TextField; mRedText->setWidth(40); @@ -120,7 +120,7 @@ Setup_Colors::Setup_Colors() : mRedSlider->addActionListener(this); mRedSlider->setEnabled(false); - mGreenLabel = new Label(_("Green: ")); + mGreenLabel = new Label(_("Green:")); mGreenText = new TextField; mGreenText->setWidth(40); @@ -135,7 +135,7 @@ Setup_Colors::Setup_Colors() : mGreenSlider->addActionListener(this); mGreenSlider->setEnabled(false); - mBlueLabel = new Label(_("Blue: ")); + mBlueLabel = new Label(_("Blue:")); mBlueText = new TextField; mBlueText->setWidth(40); @@ -262,6 +262,9 @@ void Setup_Colors::valueChanged(const gcn::SelectionEvent &event) mTextPreview->setOutline(true); mTextPreview->setShadow(false); break; + case Palette::BUTTON: + case Palette::BUTTON_DISABLED: + case Palette::TAB: case Palette::TAB_HIGHLIGHT: mTextPreview->setFont(gui->getFont()); mTextPreview->setTextColor(col); diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp index 938c1c4e..d9117b8a 100644 --- a/src/gui/setup_keyboard.cpp +++ b/src/gui/setup_keyboard.cpp @@ -116,7 +116,7 @@ void Setup_Keyboard::apply() if (keyboard.hasConflicts()) { - new OkDialog(_("Key Conflict(s) Detected."), + new OkDialog(_("Key Conflict(s) Detected"), _("Resolve them, or gameplay may result in strange " "behaviour.")); } diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index a9c892b2..f21f20e0 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -192,15 +192,17 @@ Setup_Video::Setup_Video(): mVisibleNamesEnabled)), mParticleEffectsCheckBox(new CheckBox(_("Particle effects"), mParticleEffectsEnabled)), - mNameCheckBox(new CheckBox(_("Show name"), mNameEnabled)), + mNameCheckBox(new CheckBox(_("Show own name"), mNameEnabled)), mPickupNotifyLabel(new Label(_("Show pickup notification"))), + // TRANSLATORS: Refers to "Show own name" mPickupChatCheckBox(new CheckBox(_("in chat"), mPickupChatEnabled)), + // TRANSLATORS: Refers to "Show own name" mPickupParticleCheckBox(new CheckBox(_("as particle"), mPickupParticleEnabled)), mSpeechSlider(new Slider(0, 3)), mSpeechLabel(new Label("")), mAlphaSlider(new Slider(0.2, 1.0)), - mFpsCheckBox(new CheckBox(_("FPS Limit:"))), + mFpsCheckBox(new CheckBox(_("FPS limit:"))), mFpsSlider(new Slider(10, 120)), mFpsField(new TextField), mOverlayDetail((int) config.getValue("OverlayDetail", 2)), @@ -219,7 +221,7 @@ Setup_Video::Setup_Video(): speechLabel = new Label(_("Overhead text")); alphaLabel = new Label(_("Gui opacity")); overlayDetailLabel = new Label(_("Ambient FX")); - particleDetailLabel = new Label(_("Particle Detail")); + particleDetailLabel = new Label(_("Particle detail")); fontSizeLabel = new Label(_("Font size")); mFontSizeDropDown = new DropDown(new FontSizeChoiceListModel); @@ -352,19 +354,27 @@ void Setup_Video::apply() fullscreen = !fullscreen; if (!graphics->setFullscreen(fullscreen)) { - std::stringstream error; - error << _("Failed to switch to ") << - (fullscreen ? _("windowed") : _("fullscreen")) << - _("mode and restoration of old mode also failed!") << - std::endl; - logger->error(error.str()); + std::stringstream errorMessage; + if (fullscreen) + { + errorMessage << _("Failed to switch to windowed mode " + "and restoration of old mode also " + "failed!") << std::endl; + } + else + { + errorMessage << _("Failed to switch to fullscreen mode " + "and restoration of old mode also " + "failed!") << std::endl; + } + logger->error(errorMessage.str()); } } #if defined(WIN32) || defined(__APPLE__) } else { - new OkDialog(_("Switching to full screen"), + new OkDialog(_("Switching to Full Screen"), _("Restart needed for changes to take effect.")); } #endif @@ -377,7 +387,7 @@ void Setup_Video::apply() config.setValue("opengl", mOpenGLCheckBox->isSelected()); // OpenGL can currently only be changed by restarting, notify user. - new OkDialog(_("Changing OpenGL"), + new OkDialog(_("Changing to OpenGL"), _("Applying change to OpenGL requires restart.")); } @@ -436,11 +446,17 @@ void Setup_Video::action(const gcn::ActionEvent &event) const int width = atoi(mode.substr(0, mode.find("x")).c_str()); const int height = atoi(mode.substr(mode.find("x") + 1).c_str()); + // TODO: Find out why the drawing area doesn't resize without a restart. if (width != graphics->getWidth() || height != graphics->getHeight()) { - // TODO: Find out why the drawing area doesn't resize without a restart. - new OkDialog(_("Screen resolution changed"), - _("Restart your client for the change to take effect.")); + if (width < graphics->getWidth() || height < graphics->getHeight()) + new OkDialog(_("Screen Resolution Changed"), + _("Restart your client for the change to take effect.") + + std::string("\n") + + _("Some windows may be moved to fit the lowered resolution.")); + else + new OkDialog(_("Screen Resolution Changed"), + _("Restart your client for the change to take effect.")); } config.setValue("screenwidth", width); @@ -464,7 +480,7 @@ void Setup_Video::action(const gcn::ActionEvent &event) mParticleEffectsCheckBox->isSelected()); if (engine) { - new OkDialog(_("Particle effect settings changed."), + new OkDialog(_("Particle Effect Settings Changed."), _("Changes will take effect on map change.")); } } diff --git a/src/gui/shortcutwindow.cpp b/src/gui/shortcutwindow.cpp index b9eda02c..8e7e0bee 100644 --- a/src/gui/shortcutwindow.cpp +++ b/src/gui/shortcutwindow.cpp @@ -25,6 +25,7 @@ #include "gui/widgets/layout.h" #include "gui/widgets/scrollarea.h" +#include "gui/setup.h" #include "configuration.h" @@ -42,6 +43,7 @@ ShortcutWindow::ShortcutWindow(const std::string &title, setResizable(true); setDefaultVisible(false); setSaveVisible(true); + setupWindow->registerWindowForReset(this); mItems = content; diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp deleted file mode 100644 index 7698098c..00000000 --- a/src/gui/skill.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* - * The Mana World - * Copyright (C) 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "gui/skill.h" - -#include "gui/table.h" - -#include "gui/widgets/button.h" -#include "gui/widgets/label.h" -#include "gui/widgets/layout.h" -#include "gui/widgets/listbox.h" -#include "gui/widgets/scrollarea.h" -#include "gui/widgets/windowcontainer.h" - -#include "localplayer.h" -#include "log.h" - -#include "net/net.h" -#include "net/skillhandler.h" - -#include "utils/dtor.h" -#include "utils/gettext.h" -#include "utils/stringutils.h" -#include "utils/xml.h" - -static const char *SKILLS_FILE = "skills.xml"; - -struct SkillInfo -{ - std::string name; - bool modifiable; -}; - -static const SkillInfo fakeSkillInfo = { - _("Mystery Skill"), - false -}; - -std::vector<SkillInfo> skill_db; - -static void initSkillinfo(); - -class SkillGuiTableModel : public StaticTableModel -{ -public: - SkillGuiTableModel(SkillDialog *dialog) : - StaticTableModel(0, 3) - { - mEntriesNr = 0; - mDialog = dialog; - update(); - } - - virtual int getRows() const - { - return mEntriesNr; - } - - virtual int getColumnWidth(int index) const - { - if (index == 0) - return 160; - - return 35; - } - - virtual int getRowHeight() const - { - return 12; - } - - virtual void update() - { - mEntriesNr = mDialog->getSkills().size(); - resize(); - - for (int i = 0; i < mEntriesNr; i++) - { - SKILL *skill = mDialog->getSkills()[i]; - SkillInfo const *info; - char tmp[128]; - - if (skill->id >= 0 - && (unsigned int) skill->id < skill_db.size()) - info = &skill_db[skill->id]; - else - info = &fakeSkillInfo; - - sprintf(tmp, "%c%s", info->modifiable? ' ' : '*', info->name.c_str()); - gcn::Label *name_label = new Label(tmp); - - sprintf(tmp, "Lv:%i", skill->lv); - gcn::Label *lv_label = new Label(tmp); - - sprintf(tmp, "Sp:%i", skill->sp); - gcn::Label *sp_label = new Label(tmp); - - set(i, 0, name_label); - set(i, 1, lv_label); - set(i, 2, sp_label); - } - } - -private: - SkillDialog *mDialog; - int mEntriesNr; -}; - - -SkillDialog::SkillDialog(): - Window(_("Skills")) -{ - initSkillinfo(); - mTableModel = new SkillGuiTableModel(this); - mTable = new GuiTable(mTableModel); - mTable->setOpaque(false); - mTable->setLinewiseSelection(true); - mTable->setWrappingEnabled(true); - mTable->setActionEventId("skill"); - mTable->addActionListener(this); - - setWindowName("Skills"); - setCloseButton(true); - setDefaultSize(255, 260, ImageRect::CENTER); - - setMinHeight(50 + mTableModel->getHeight()); - setMinWidth(200); - - ScrollArea *skillScrollArea = new ScrollArea(mTable); - mPointsLabel = new Label(strprintf(_("Skill points: %d"), 0)); - mIncButton = new Button(_("Up"), "inc", this); - mUseButton = new Button(_("Use"), "use", this); - mUseButton->setEnabled(false); - - skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); - - place(0, 0, skillScrollArea, 5).setPadding(3); - place(0, 1, mPointsLabel, 4); - place(3, 2, mIncButton); - place(4, 2, mUseButton); - - Layout &layout = getLayout(); - layout.setRowHeight(0, Layout::AUTO_SET); - - center(); - loadWindowState(); -} - -SkillDialog::~SkillDialog() -{ - delete_all(mSkillList); -} - -void SkillDialog::action(const gcn::ActionEvent &event) -{ - if (event.getId() == "inc") - { - // Increment skill - int selectedSkill = mTable->getSelectedRow(); - if (selectedSkill >= 0) - Net::getSkillHandler()->up(mSkillList[selectedSkill]->id); - } - else if (event.getId() == "skill" && mTable->getSelectedRow() > -1) - { - SKILL *skill = mSkillList[mTable->getSelectedRow()]; - SkillInfo const *info; - - if (skill->id >= 0 && (unsigned int) skill->id < skill_db.size()) - info = &skill_db[skill->id]; - else - info = &fakeSkillInfo; - - mIncButton->setEnabled(player_node->mSkillPoint > 0 && - info->modifiable); - } - else if (event.getId() == "close") - setVisible(false); -} - -void SkillDialog::update() -{ - mPointsLabel->setCaption(strprintf(_("Skill points: %d"), - player_node->mSkillPoint)); - - int selectedSkill = mTable->getSelectedRow(); - - if (selectedSkill >= 0) - { - int skillId = mSkillList[selectedSkill]->id; - bool modifiable; - - if (skillId >= 0 && (unsigned int) skillId < skill_db.size()) - modifiable = skill_db[skillId].modifiable; - else - modifiable = false; - - mIncButton->setEnabled(modifiable - && player_node->mSkillPoint > 0); - } - else - mIncButton->setEnabled(false); - - mTableModel->update(); - setMinHeight(50 + mTableModel->getHeight()); -} - -int SkillDialog::getNumberOfElements() -{ - return mSkillList.size(); -} - -bool SkillDialog::hasSkill(int id) -{ - for (unsigned int i = 0; i < mSkillList.size(); i++) - { - if (mSkillList[i]->id == id) - return true; - } - return false; -} - -void SkillDialog::addSkill(int id, int lvl, int mp) -{ - SKILL *tmp = new SKILL; - tmp->id = id; - tmp->lv = lvl; - tmp->sp = mp; - mSkillList.push_back(tmp); -} - -void SkillDialog::setSkill(int id, int lvl, int mp) -{ - for (unsigned int i = 0; i < mSkillList.size(); i++) - { - if (mSkillList[i]->id == id) - { - mSkillList[i]->lv = lvl; - mSkillList[i]->sp = mp; - } - } -} - -void SkillDialog::cleanList() -{ - delete_all(mSkillList); - mSkillList.clear(); -} - -static void initSkillinfo() -{ - SkillInfo emptySkillInfo = { "", false }; - - XML::Document doc(SKILLS_FILE); - xmlNodePtr root = doc.rootNode(); - - if (!root || !xmlStrEqual(root->name, BAD_CAST "skills")) - { - logger->log("Error loading skills file: %s", SKILLS_FILE); - skill_db.resize(2, emptySkillInfo); - skill_db[1].name = "Basic"; - skill_db[1].modifiable = true; - return; - } - - for_each_xml_child_node(node, root) - { - if (xmlStrEqual(node->name, BAD_CAST "skill")) - { - int index = atoi(XML::getProperty(node, "id", "-1").c_str()); - std::string name = XML::getProperty(node, "name", ""); - bool modifiable = !atoi(XML::getProperty(node, "fixed", "0").c_str()); - - if (index >= 0) - { - skill_db.resize(index + 1, emptySkillInfo); - skill_db[index].name = name; - skill_db[index].modifiable = modifiable; - } - } - } -} - diff --git a/src/gui/skill.h b/src/gui/skill.h deleted file mode 100644 index 0879f7e1..00000000 --- a/src/gui/skill.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * The Mana World - * Copyright (C) 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef SKILL_H -#define SKILL_H - -#include "gui/widgets/window.h" - -#include <guichan/actionlistener.hpp> - -#include <vector> - -struct SKILL -{ - short id; /**< Index into "skill_db" array */ - short lv, sp; -}; - -class GuiTable; -class ScrollArea; -class SkillGuiTableModel; - -/** - * The skill dialog. - * - * \ingroup Interface - */ -class SkillDialog : public Window, public gcn::ActionListener -{ - public: - /** - * Constructor. - */ - SkillDialog(); - - /** - * Destructor. - */ - ~SkillDialog(); - - void action(const gcn::ActionEvent &event); - - void update(); - - int getNumberOfElements(); - - bool hasSkill(int id); - void addSkill(int id, int lv, int sp); - void setSkill(int id, int lv, int sp); - void cleanList(); - - const std::vector<SKILL*>& getSkills() const { return mSkillList; } - - private: - GuiTable *mTable; - ScrollArea *skillScrollArea; - SkillGuiTableModel *mTableModel; - gcn::Label *mPointsLabel; - gcn::Button *mIncButton; - gcn::Button *mUseButton; - - std::vector<SKILL*> mSkillList; -}; - -extern SkillDialog *skillDialog; - -#endif diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp index f0cd01ce..14e0e5a4 100644 --- a/src/gui/skilldialog.cpp +++ b/src/gui/skilldialog.cpp @@ -25,105 +25,78 @@ #include "gui/widgets/container.h" #include "gui/widgets/icon.h" #include "gui/widgets/label.h" +#include "gui/widgets/layouthelper.h" #include "gui/widgets/listbox.h" #include "gui/widgets/progressbar.h" #include "gui/widgets/scrollarea.h" +#include "gui/widgets/tab.h" #include "gui/widgets/tabbedarea.h" +#include "gui/widgets/vertcontainer.h" #include "gui/widgets/windowcontainer.h" +#include "gui/setup.h" #include "localplayer.h" +#include "log.h" + +#include "net/net.h" +#include "net/playerhandler.h" #include "utils/dtor.h" #include "utils/gettext.h" #include "utils/stringutils.h" +#include "utils/xml.h" #include <string> #include <vector> -class SkillTab : public Container, public gcn::ActionListener +class SkillEntry; + +struct SkillInfo +{ + unsigned short id; + std::string name; + std::string icon; + bool modifiable; + SkillEntry *display; +}; + +class SkillEntry : public Container, gcn::WidgetListener { public: - /** - * The type of this skill tab - */ - const std::string type; - - /** - * Constructor - */ - SkillTab(const std::string &type); - - /** - * Update this tab - */ + SkillEntry(SkillInfo *info); + + void widgetResized(const gcn::Event &event); + void update(); - /** - * Called when receiving actions from widget. - */ - void action(const gcn::ActionEvent &event) {} + protected: + friend class SkillDialog; + SkillInfo *mInfo; private: - /** - * Update the information of a skill at - * the given index - */ - void updateSkill(int index); - - /** - * Gets the number of skills in this particular - * type of tab. - */ - int getSkillNum(); - - /** - * Get the first enumeration of this skill tab's - * skill type. - */ - int getSkillBegin(); - - /** - * Get the icon associated with the given index - */ - Icon *getIcon(int index); - - std::vector<Icon *> mSkillIcons; - std::vector<gcn::Label *> mSkillNameLabels; - std::vector<gcn::Label *> mSkillLevelLabels; - std::vector<gcn::Label *> mSkillExpLabels; - std::vector<ProgressBar *> mSkillProgress; + Icon *mIcon; + Label *mNameLabel; + Label *mLevelLabel; + Label *mExpLabel; + Button *mIncrease; + ProgressBar *mProgress; }; - SkillDialog::SkillDialog(): Window(_("Skills")) { setWindowName("Skills"); setCloseButton(true); + setResizable(true); setSaveVisible(true); setDefaultSize(windowContainer->getWidth() - 280, 30, 275, 425); + setupWindow->registerWindowForReset(this); - TabbedArea *panel = new TabbedArea; - panel->setDimension(gcn::Rectangle(5, 5, 270, 420)); - - SkillTab *tab; - - // Add each type of skill tab to the panel - tab = new SkillTab("Weapon"); - panel->addTab(_("Weapons"), tab); - mTabs.push_back(tab); + mTabs = new TabbedArea(); + mPointsLabel = new Label("0"); - tab = new SkillTab("Magic"); - panel->addTab(_("Magic"), tab); - mTabs.push_back(tab); - - tab = new SkillTab("Craft"); - panel->addTab(_("Crafts"), tab); - mTabs.push_back(tab); - - add(panel); - - update(); + place(0, 0, mTabs, 5, 5); + place(0, 5, mPointsLabel); setLocationRelativeTo(getParent()); loadWindowState(); @@ -131,13 +104,17 @@ SkillDialog::SkillDialog(): SkillDialog::~SkillDialog() { - delete_all(mTabs); + //delete_all(mTabs); } void SkillDialog::action(const gcn::ActionEvent &event) { - if (event.getId() == "skill") + if (event.getId() == "inc") { + SkillEntry *disp = dynamic_cast<SkillEntry*>(event.getSource()->getParent()); + + if (disp) + Net::getPlayerHandler()->increaseSkill(disp->mInfo->id); } else if (event.getId() == "close") { @@ -145,174 +122,254 @@ void SkillDialog::action(const gcn::ActionEvent &event) } } -void SkillDialog::draw(gcn::Graphics *g) +void SkillDialog::adjustTabSize() { - update(); + gcn::Widget *content = mTabs->getCurrentWidget(); + if (content) { + int width = mTabs->getWidth() - 2 * content->getFrameSize() - 2 * mTabs->getFrameSize(); + int height = mTabs->getContainerHeight() - 2 * content->getFrameSize(); + content->setSize(width, height); + content->setVisible(true); + content->logic(); + } +} + +void SkillDialog::widgetResized(const gcn::Event &event) +{ + Window::widgetResized(event); - Window::draw(g); + adjustTabSize(); } -void SkillDialog::update() +void SkillDialog::logic() { - for(std::list<SkillTab*>::const_iterator i = mTabs.begin(); - i != mTabs.end(); ++i) - { - (*i)->update(); + Window::logic(); + + Tab *tab = dynamic_cast<Tab*>(mTabs->getSelectedTab()); + if (tab != mCurrentTab) { + mCurrentTab = tab; + adjustTabSize(); } } -SkillTab::SkillTab(const std::string &type): type(type) +std::string SkillDialog::update(int id) { - setOpaque(false); - setDimension(gcn::Rectangle(0, 0, 270, 420)); - int skillNum = getSkillNum(); - - mSkillIcons.resize(skillNum); - mSkillNameLabels.resize(skillNum); - mSkillLevelLabels.resize(skillNum); - mSkillExpLabels.resize(skillNum); - mSkillProgress.resize(skillNum); + SkillMap::iterator i = mSkills.find(id); - // Set the initial positions of the skill information - for (int a = 0; a < skillNum; a++) + if (i != mSkills.end()) { - mSkillIcons.at(a) = getIcon(a); - mSkillIcons.at(a)->setPosition(1, a*32); - add(mSkillIcons.at(a)); - - mSkillNameLabels.at(a) = new Label(""); - mSkillNameLabels.at(a)->setPosition(35, a*32 ); - add(mSkillNameLabels.at(a)); + SkillInfo *info = i->second; + info->display->update(); + return info->name; + } - mSkillProgress.at(a) = new ProgressBar(0.0f, 200, 20, gcn::Color(150, 150, 150)); - mSkillProgress.at(a)->setPosition(35, a*32 + 13); - add(mSkillProgress.at(a)); + return std::string(); +} - mSkillExpLabels.at(a) = new Label(""); - mSkillExpLabels.at(a)->setPosition(45, a*32 + 16); - add(mSkillExpLabels.at(a)); +void SkillDialog::update() +{ + mPointsLabel->setCaption(strprintf(_("Skill points available: %d"), + player_node->getSkillPoints())); + mPointsLabel->adjustSize(); - mSkillLevelLabels.at(a) = new Label(""); - mSkillLevelLabels.at(a)->setPosition(165, a*32); - add(mSkillLevelLabels.at(a)); + for (SkillMap::iterator it = mSkills.begin(); it != mSkills.end(); it++) + { + if ((*it).second->modifiable) + (*it).second->display->update(); } - - update(); } -int SkillTab::getSkillNum() +void SkillDialog::loadSkills(const std::string &file) { - int skillNum = 0; + // TODO: mTabs->clear(); + delete_all(mSkills); + mSkills.clear(); - if (type == "Weapon") + XML::Document doc(file); + xmlNodePtr root = doc.rootNode(); + + if (!root || !xmlStrEqual(root->name, BAD_CAST "skills")) { - skillNum = CHAR_SKILL_WEAPON_NB; - return skillNum; + logger->log("Error loading skills file: %s", file.c_str()); + return; } - else if (type == "Magic") + + int setCount = 0; + std::string setName; + ScrollArea *scroll; + VertContainer *container; + + for_each_xml_child_node(set, root) { - skillNum = CHAR_SKILL_MAGIC_NB; - return skillNum; + if (xmlStrEqual(set->name, BAD_CAST "set")) + { + setCount++; + setName = XML::getProperty(set, "name", strprintf(_("Skill Set %d"), setCount)); + + container = new VertContainer(32); + container->setOpaque(false); + scroll = new ScrollArea(container); + scroll->setOpaque(false); + scroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); + scroll->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS); + + mTabs->addTab(setName, scroll); + for_each_xml_child_node(node, set) + { + if (xmlStrEqual(node->name, BAD_CAST "skill")) + { + int id = atoi(XML::getProperty(node, "id", "-1").c_str()); + std::string name = XML::getProperty(node, "name", strprintf(_("Skill %d"), id)); + std::string icon = XML::getProperty(node, "icon", ""); + + SkillInfo *skill = new SkillInfo; + skill->id = id; + skill->name = name; + skill->icon = icon; + skill->modifiable = 0; + skill->display = new SkillEntry(skill); + + container->add(skill->display); + + mSkills[id] = skill; + } + } + } } - else if (type == "Craft") + + adjustTabSize(); + update(); +} + +void SkillDialog::setModifiable(int id, bool modifiable) +{ + SkillMap::iterator i = mSkills.find(id); + + if (i != mSkills.end()) { - skillNum = CHAR_SKILL_CRAFT_NB; - return skillNum; + SkillInfo *info = i->second; + info->modifiable = modifiable; + info->display->update(); } - else return skillNum; } -int SkillTab::getSkillBegin() +SkillEntry::SkillEntry(SkillInfo *info) : + mInfo(info), + mIcon(NULL), + mNameLabel(new Label(info->name)), + mLevelLabel(new Label("999")), + mIncrease(new Button(_("+"), "inc", skillDialog)), + mProgress(new ProgressBar(0.0f, 200, 20, gcn::Color(150, 150, 150))) +{ + setFrameSize(1); + setOpaque(false); + + addWidgetListener(this); + + if (!info->icon.empty()) + mIcon = new Icon(info->icon); + else + mIcon = new Icon("graphics/gui/unknown-item.png"); + + mIcon->setPosition(1, 0); + add(mIcon); + + mNameLabel->setPosition(35, 0); + add(mNameLabel); + + mLevelLabel->setPosition(165, 0); + add(mLevelLabel); + + mProgress->setPosition(35, 13); + add(mProgress); + + mIncrease->setPosition(getWidth() - mIncrease->getWidth(), 13); + add(mIncrease); + + update(); +} + +void SkillEntry::widgetResized(const gcn::Event &event) { - int skillBegin = 0; + gcn::Rectangle size = getChildrenArea(); - if (type == "Weapon") + if (mProgress->isVisible() && mIncrease->isVisible()) { - skillBegin = CHAR_SKILL_WEAPON_BEGIN - CHAR_SKILL_BEGIN; - return skillBegin; + mLevelLabel->setPosition(size.width - mLevelLabel->getWidth() + - mIncrease->getWidth() - 4, 0); + mProgress->setWidth(size.width - mIncrease->getWidth() - 39); + mIncrease->setPosition(getWidth() - mIncrease->getWidth() - 2, 6); } - else if (type == "Magic") + else if (mProgress->isVisible()) { - skillBegin = CHAR_SKILL_MAGIC_BEGIN - CHAR_SKILL_BEGIN; - return skillBegin; + mLevelLabel->setPosition(size.width - mLevelLabel->getWidth(), 0); + mProgress->setWidth(size.width - 39); } - else if (type == "Craft") + else if (mIncrease->isVisible()) { - skillBegin = CHAR_SKILL_CRAFT_BEGIN - CHAR_SKILL_BEGIN; - return skillBegin; + mLevelLabel->setPosition(size.width - mLevelLabel->getWidth() + - mIncrease->getWidth() - 4, 0); + mIncrease->setPosition(getWidth() - mIncrease->getWidth() - 2, 6); } - else return skillBegin; + else + mLevelLabel->setPosition(size.width - mLevelLabel->getWidth(), 0); } -Icon* SkillTab::getIcon(int index) +void SkillEntry::update() { - int skillBegin = getSkillBegin(); - std::string icon = LocalPlayer::getSkillInfo(index + skillBegin).icon; - return new Icon(icon); -} + int baseLevel = player_node->getAttributeBase(mInfo->id); + int effLevel = player_node->getAttributeEffective(mInfo->id); -void SkillTab::updateSkill(int index) -{ - int skillBegin = getSkillBegin(); + if (baseLevel <= 0 && !mInfo->modifiable) + { + setVisible(false); + return; + } + + setVisible(true); - int baseLevel = player_node->getAttributeBase(index + - skillBegin + - CHAR_SKILL_BEGIN); + std::string skillLevel; - int effLevel = player_node->getAttributeEffective(index + - skillBegin + - CHAR_SKILL_BEGIN); - if(baseLevel <= 0) + if (effLevel != baseLevel) { - mSkillProgress.at(index)->setVisible(false); - mSkillExpLabels.at(index)->setVisible(false); - mSkillLevelLabels.at(index)->setVisible(false); - mSkillNameLabels.at(index)->setVisible(false); - mSkillIcons.at(index)->setVisible(false); + skillLevel = strprintf(_("Lvl: %d (%+d)"), + baseLevel, baseLevel - effLevel); } else { - mSkillProgress.at(index)->setVisible(true); - mSkillExpLabels.at(index)->setVisible(true); - mSkillLevelLabels.at(index)->setVisible(true); - mSkillNameLabels.at(index)->setVisible(true); - mSkillIcons.at(index)->setVisible(true); - std::string skillLevel("Lvl: " + toString(baseLevel)); - if (effLevel < baseLevel) - { - skillLevel.append(" - " + toString(baseLevel - effLevel)); - } - else if (effLevel > baseLevel) - { - skillLevel.append(" + " + toString(effLevel - baseLevel)); - } - mSkillLevelLabels.at(index)->setCaption(skillLevel); + skillLevel = strprintf(_("Lvl: %d"), baseLevel); + } - std::pair<int, int> exp = player_node->getExperience(index + skillBegin); - std::string sExp (toString(exp.first) + " / " + toString(exp.second)); + mLevelLabel->setCaption(skillLevel); + std::pair<int, int> exp = player_node->getExperience(mInfo->id); + std::string sExp (toString(exp.first) + " / " + toString(exp.second)); - mSkillNameLabels.at(index)->setCaption(LocalPlayer::getSkillInfo(index + skillBegin).name); - mSkillNameLabels.at(index)->adjustSize(); - mSkillLevelLabels.at(index)->adjustSize(); - mSkillExpLabels.at(index)->setCaption(sExp); - mSkillExpLabels.at(index)->adjustSize(); - mSkillExpLabels.at(index)->setAlignment(gcn::Graphics::RIGHT); + mLevelLabel->adjustSize(); + + if (exp.second) + { + mProgress->setVisible(true); + mProgress->setText(sExp); // More intense red as exp grows int color = 150 - (int)(150 * ((float) exp.first / exp.second)); - mSkillProgress.at(index)->setColor(244, color, color); - mSkillProgress.at(index)->setProgress((float) exp.first / exp.second); + mProgress->setColor(244, color, color); + mProgress->setProgress((float) exp.first / exp.second); } -} - -void SkillTab::update() -{ - int skillNum = getSkillNum(); + else + mProgress->setVisible(false); - // Update the skill information for reach skill - for (int a = 0; a < skillNum; a++) + if (mInfo->modifiable) { - updateSkill(a); + mIncrease->setVisible(true); + mIncrease->setEnabled(player_node->getSkillPoints()); } + else + { + mIncrease->setVisible(false); + mIncrease->setEnabled(false); + } + + widgetResized(NULL); } diff --git a/src/gui/skilldialog.h b/src/gui/skilldialog.h index 56192273..ce8f091a 100644 --- a/src/gui/skilldialog.h +++ b/src/gui/skilldialog.h @@ -29,10 +29,14 @@ #include <guichan/actionlistener.hpp> #include <list> +#include <map> -class ProgressBar; -class Icon; -class SkillTab; +class Label; +class ScrollArea; +class Tab; +class TabbedArea; + +struct SkillInfo; /** * The skill dialog. @@ -52,17 +56,35 @@ class SkillDialog : public Window, public gcn::ActionListener void action(const gcn::ActionEvent &event); /** - * Update the tabs in this dialog + * Called when the widget changes size. Used for adapting the size of + * the tabbed area. */ - void update(); + void widgetResized(const gcn::Event &event); + + void logic(); /** - * Draw this window. - */ - void draw(gcn::Graphics *g); + * Update the given skill's display + */ + std::string update(int id); + + /** + * Update other parts of the display + */ + void update(); + + void loadSkills(const std::string &file); + + void setModifiable(int id, bool modifiable); private: - std::list<SkillTab*> mTabs; + void adjustTabSize(); + + typedef std::map<int, SkillInfo*> SkillMap; + SkillMap mSkills; + Tab *mCurrentTab; + TabbedArea *mTabs; + Label *mPointsLabel; }; extern SkillDialog *skillDialog; diff --git a/src/gui/speechbubble.cpp b/src/gui/speechbubble.cpp index 959e47ee..c2703327 100644 --- a/src/gui/speechbubble.cpp +++ b/src/gui/speechbubble.cpp @@ -28,8 +28,6 @@ #include "graphics.h" -#include "utils/gettext.h" - #include <guichan/font.hpp> #include <guichan/widgets/label.hpp> diff --git a/src/gui/status.cpp b/src/gui/status.cpp deleted file mode 100644 index eca01725..00000000 --- a/src/gui/status.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * The Mana World - * Copyright (C) 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "gui/status.h" -#include "gui/palette.h" - -#include "localplayer.h" -#include "units.h" - -#include "gui/widgets/button.h" -#include "gui/widgets/label.h" -#include "gui/widgets/layout.h" -#include "gui/widgets/progressbar.h" -#include "gui/widgets/windowcontainer.h" - -#include "net/net.h" -#include "net/ea/playerhandler.h" - -#include "utils/gettext.h" -#include "utils/mathutils.h" -#include "utils/stringutils.h" - -StatusWindow::StatusWindow(LocalPlayer *player): - Window(player->getName()), - mPlayer(player), - mCurrency(0) -{ - setWindowName("Status"); - setCloseButton(true); - setSaveVisible(true); - setDefaultSize(400, 345, ImageRect::CENTER); - - // ---------------------- - // Status Part - // ---------------------- - - mLvlLabel = new Label(strprintf(_("Level: %d"), 0)); - mJobLvlLabel = new Label(strprintf(_("Job: %d"), 0)); - mGpLabel = new Label(strprintf(_("Money: %s"), - Units::formatCurrency(mCurrency).c_str())); - - mHpLabel = new Label(_("HP:")); - mHpBar = new ProgressBar(0.0f, 80, 15, gcn::Color(0, 171, 34)); - - mXpLabel = new Label(_("Exp:")); - mXpBar = new ProgressBar(0.0f, 80, 15, gcn::Color(143, 192, 211)); - - mMpLabel = new Label(_("MP:")); - mMpBar = new ProgressBar(0.0f, 80, 15, gcn::Color(26, 102, 230)); - - mJobLabel = new Label(_("Job:")); - mJobBar = new ProgressBar(0.0f, 80, 15, gcn::Color(220, 135, 203)); - - // ---------------------- - // Stats Part - // ---------------------- - - // Static Labels - gcn::Label *mStatsTitleLabel = new Label(_("Stats")); - gcn::Label *mStatsTotalLabel = new Label(_("Total")); - gcn::Label *mStatsCostLabel = new Label(_("Cost")); - mStatsTotalLabel->setAlignment(gcn::Graphics::CENTER); - - // Derived Stats - mStatsAttackLabel = new Label(_("Attack:")); - mStatsDefenseLabel= new Label(_("Defense:")); - mStatsMagicAttackLabel = new Label(_("M.Attack:")); - mStatsMagicDefenseLabel = new Label(_("M.Defense:")); - // Gettext flag for next line: xgettext:no-c-format - mStatsAccuracyLabel = new Label(_("% Accuracy:")); - // Gettext flag for next line: xgettext:no-c-format - mStatsEvadeLabel = new Label(_("% Evade:")); - // Gettext flag for next line: xgettext:no-c-format - mStatsReflexLabel = new Label(_("% Reflex:")); - - mStatsAttackPoints = new Label; - mStatsDefensePoints = new Label; - mStatsMagicAttackPoints = new Label; - mStatsMagicDefensePoints = new Label; - mStatsAccuracyPoints = new Label; - mStatsEvadePoints = new Label; - mStatsReflexPoints = new Label; - - // New labels - for (int i = 0; i < 6; i++) - { - mStatsLabel[i] = new Label("0"); - mStatsLabel[i]->setAlignment(gcn::Graphics::CENTER); - mStatsDisplayLabel[i] = new Label; - mPointsLabel[i] = new Label("0"); - mPointsLabel[i]->setAlignment(gcn::Graphics::CENTER); - } - mRemainingStatsPointsLabel = new Label; - - // Set button events Id - mStatsButton[0] = new Button("+", "STR", this); - mStatsButton[1] = new Button("+", "AGI", this); - mStatsButton[2] = new Button("+", "VIT", this); - mStatsButton[3] = new Button("+", "INT", this); - mStatsButton[4] = new Button("+", "DEX", this); - mStatsButton[5] = new Button("+", "LUK", this); - - // Assemble - ContainerPlacer place; - place = getPlacer(0, 0); - - place(0, 0, mLvlLabel, 3); - place(5, 0, mJobLvlLabel, 3); - place(8, 0, mGpLabel, 3); - place(0, 1, mHpLabel).setPadding(3); - place(1, 1, mHpBar, 4); - place(5, 1, mXpLabel).setPadding(3); - place(6, 1, mXpBar, 5); - place(0, 2, mMpLabel).setPadding(3); - place(1, 2, mMpBar, 4); - place(5, 2, mJobLabel).setPadding(3); - place(6, 2, mJobBar, 5); - place.getCell().matchColWidth(0, 1); - place = getPlacer(0, 3); - place(0, 1, mStatsTitleLabel, 5); - place(5, 1, mStatsTotalLabel, 5); - place(12, 1, mStatsCostLabel, 5); - for (int i = 0; i < 6; i++) - { - place(0, 2 + i, mStatsLabel[i], 7).setPadding(5); - place(7, 2 + i, mStatsDisplayLabel[i]).setPadding(5); - place(10, 2 + i, mStatsButton[i]); - place(12, 2 + i, mPointsLabel[i]).setPadding(5); - } - place(14, 2, mStatsAttackLabel, 7).setPadding(5); - place(14, 3, mStatsDefenseLabel, 7).setPadding(5); - place(14, 4, mStatsMagicAttackLabel, 7).setPadding(5); - place(14, 5, mStatsMagicDefenseLabel, 7).setPadding(5); - place(14, 6, mStatsAccuracyLabel, 7).setPadding(5); - place(14, 7, mStatsEvadeLabel, 7).setPadding(5); - place(14, 8, mStatsReflexLabel, 7).setPadding(5); - place(21, 2, mStatsAttackPoints, 3).setPadding(5); - place(21, 3, mStatsDefensePoints, 3).setPadding(5); - place(21, 4, mStatsMagicAttackPoints, 3).setPadding(5); - place(21, 5, mStatsMagicDefensePoints, 3).setPadding(5); - place(21, 6, mStatsAccuracyPoints, 3).setPadding(5); - place(21, 7, mStatsEvadePoints, 3).setPadding(5); - place(21, 8, mStatsReflexPoints, 3).setPadding(5); - place(0, 8, mRemainingStatsPointsLabel, 3).setPadding(5); - - Layout &layout = getLayout(); - layout.setRowHeight(0, Layout::AUTO_SET); - - loadWindowState(); -} - -void StatusWindow::update() -{ - // Status Part - // ----------- - mLvlLabel->setCaption(strprintf(_("Level: %d"), mPlayer->getLevel())); - mLvlLabel->adjustSize(); - - mJobLvlLabel->setCaption(strprintf(_("Job: %d"), mPlayer->mJobLevel)); - mJobLvlLabel->adjustSize(); - - if (mCurrency != mPlayer->getMoney()) { - mCurrency = mPlayer->getMoney(); - mGpLabel->setCaption(strprintf(_("Money: %s"), - Units::formatCurrency(mCurrency).c_str())); - mGpLabel->adjustSize(); - } - - updateHPBar(mHpBar, true); - - updateMPBar(mMpBar, true); - - updateXPBar(mXpBar, false); - - updateJobBar(mJobBar, false); - - // Stats Part - // ---------- - static const char *attrNames[6] = { - N_("Strength"), - N_("Agility"), - N_("Vitality"), - N_("Intelligence"), - N_("Dexterity"), - N_("Luck") - }; - int statusPoints = mPlayer->mStatsPointsToAttribute; - - // Update labels - for (int i = 0; i < 6; i++) - { - mStatsLabel[i]->setCaption(gettext(attrNames[i])); - mStatsDisplayLabel[i]->setCaption(toString((int) mPlayer->mAttr[i])); - mPointsLabel[i]->setCaption(toString((int) mPlayer->mAttrUp[i])); - - mStatsLabel[i]->adjustSize(); - mStatsDisplayLabel[i]->adjustSize(); - mPointsLabel[i]->adjustSize(); - - mStatsButton[i]->setEnabled(mPlayer->mAttrUp[i] <= statusPoints); - } - mRemainingStatsPointsLabel->setCaption( - strprintf(_("Remaining Status Points: %d"), statusPoints)); - mRemainingStatsPointsLabel->adjustSize(); - - // Derived Stats Points - - // Attack TODO: Count equipped Weapons and items attack bonuses - mStatsAttackPoints->setCaption( - toString(mPlayer->ATK + mPlayer->ATK_BONUS)); - mStatsAttackPoints->adjustSize(); - - // Defense TODO: Count equipped Armors and items defense bonuses - mStatsDefensePoints->setCaption( - toString(mPlayer->DEF + mPlayer->DEF_BONUS)); - mStatsDefensePoints->adjustSize(); - - // Magic Attack TODO: Count equipped items M.Attack bonuses - mStatsMagicAttackPoints->setCaption( - toString(mPlayer->MATK + mPlayer->MATK_BONUS)); - mStatsMagicAttackPoints->adjustSize(); - - // Magic Defense TODO: Count equipped items M.Defense bonuses - mStatsMagicDefensePoints->setCaption( - toString(mPlayer->MDEF + mPlayer->MDEF_BONUS)); - mStatsMagicDefensePoints->adjustSize(); - - // Accuracy % - mStatsAccuracyPoints->setCaption(toString(mPlayer->HIT)); - mStatsAccuracyPoints->adjustSize(); - - // Evasion % - mStatsEvadePoints->setCaption(toString(mPlayer->FLEE)); - mStatsEvadePoints->adjustSize(); - - // Reflex % - mStatsReflexPoints->setCaption(toString(mPlayer->DEX / 4)); // + counter - mStatsReflexPoints->adjustSize(); -} - -void StatusWindow::draw(gcn::Graphics *g) -{ - update(); - - Window::draw(g); -} - -void StatusWindow::action(const gcn::ActionEvent &event) -{ - // Stats Part - // Net::getPlayerHandler()->increaseStat(?); - if (event.getId().length() == 3) - { - if (event.getId() == "STR") - Net::getPlayerHandler()->increaseStat(LocalPlayer::STR); - if (event.getId() == "AGI") - Net::getPlayerHandler()->increaseStat(LocalPlayer::AGI); - if (event.getId() == "VIT") - Net::getPlayerHandler()->increaseStat(LocalPlayer::VIT); - if (event.getId() == "INT") - Net::getPlayerHandler()->increaseStat(LocalPlayer::INT); - if (event.getId() == "DEX") - Net::getPlayerHandler()->increaseStat(LocalPlayer::DEX); - if (event.getId() == "LUK") - Net::getPlayerHandler()->increaseStat(LocalPlayer::LUK); - } -} - -void StatusWindow::updateHPBar(ProgressBar *bar, bool showMax) -{ - if (showMax) - bar->setText(toString(player_node->getHp()) + - "/" + toString(player_node->getMaxHp())); - else - bar->setText(toString(player_node->getHp())); - - // HP Bar coloration - float r1 = 255; - float g1 = 255; - float b1 = 255; - - float r2 = 255; - float g2 = 255; - float b2 = 255; - - float weight = 1.0f; - - int curHP = player_node->getHp(); - int thresholdLevel = player_node->getMaxHp() / 4; - int thresholdProgress = curHP % thresholdLevel; - weight = 1-((float)thresholdProgress) / ((float)thresholdLevel); - - if (curHP < (thresholdLevel)) - { - gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_ONE_HALF); - gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_ONE_QUARTER); - r1 = color1.r; r2 = color2.r; - g1 = color1.g; g2 = color2.g; - b1 = color1.b; b2 = color2.b; - } - else if (curHP < (thresholdLevel*2)) - { - gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_THREE_QUARTERS); - gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_ONE_HALF); - r1 = color1.r; r2 = color2.r; - g1 = color1.g; g2 = color2.g; - b1 = color1.b; b2 = color2.b; - } - else if (curHP < thresholdLevel*3) - { - gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_FULL); - gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_THREE_QUARTERS); - r1 = color1.r; r2 = color2.r; - g1 = color1.g; g2 = color2.g; - b1 = color1.b; b2 = color2.b; - } - else - { - gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_FULL); - gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_FULL); - r1 = color1.r; r2 = color2.r; - g1 = color1.g; g2 = color2.g; - b1 = color1.b; b2 = color2.b; - } - - // Safety checks - if (weight > 1.0f) weight = 1.0f; - if (weight < 0.0f) weight = 0.0f; - - // Do the color blend - r1 = (int) weightedAverage(r1, r2,weight); - g1 = (int) weightedAverage(g1, g2, weight); - b1 = (int) weightedAverage(b1, b2, weight); - - // More safety checks - if (r1 > 255) r1 = 255; - if (g1 > 255) g1 = 255; - if (b1 > 255) b1 = 255; - - bar->setColor(r1, g1, b1); - - bar->setProgress((float) player_node->getHp() / (float) player_node->getMaxHp()); -} - -void StatusWindow::updateMPBar(ProgressBar *bar, bool showMax) -{ - if (showMax) - bar->setText(toString(player_node->mMp) + - "/" + toString(player_node->mMaxMp)); - else - bar->setText(toString(player_node->mMp)); - - if (player_node->MATK <= 0) - bar->setColor(100, 100, 100); // grey, to indicate that we lack magic - else - bar->setColor(26, 102, 230); // blue, to indicate that we have magic - - bar->setProgress((float) player_node->mMp / (float) player_node->mMaxMp); -} - -static void updateProgressBar(ProgressBar *bar, int value, int max, - bool percent) -{ - if (max == 0) - { - bar->setText(_("Max level")); - bar->setProgress(1.0); - } - else - { - float progress = (float) value / max; - - if (percent) - bar->setText(strprintf("%2.2f", 100 * progress) + "%"); - else - bar->setText(toString(value) + "/" + toString(max)); - - bar->setProgress(progress); - } -} - -void StatusWindow::updateXPBar(ProgressBar *bar, bool percent) -{ - updateProgressBar(bar, - player_node->getXp(), - player_node->mXpForNextLevel, - percent); -} - -void StatusWindow::updateJobBar(ProgressBar *bar, bool percent) -{ - updateProgressBar(bar, - player_node->mJobXp, - player_node->mJobXpForNextLevel, - percent); -} diff --git a/src/gui/status.h b/src/gui/status.h deleted file mode 100644 index 403a7d59..00000000 --- a/src/gui/status.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * The Mana World - * Copyright (C) 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef STATUS_H -#define STATUS_H - -#include "gui/widgets/window.h" - -#include <guichan/actionlistener.hpp> - -class LocalPlayer; -class ProgressBar; - -/** - * The player status dialog. - * - * \ingroup Interface - */ -class StatusWindow : public Window, public gcn::ActionListener -{ - public: - /** - * Constructor. - */ - StatusWindow(LocalPlayer *player); - - /** - * Called when receiving actions from widget. - */ - void action(const gcn::ActionEvent &event); - - /** - * Draw this window - */ - void draw(gcn::Graphics *graphics); - - /** - * Updates this dialog with values from PLAYER_INFO *char_info - */ - void update(); - - static void updateHPBar(ProgressBar *bar, bool showMax = false); - static void updateMPBar(ProgressBar *bar, bool showMax = false); - static void updateXPBar(ProgressBar *bar, bool percent = true); - static void updateJobBar(ProgressBar *bar, bool percent = true); - - private: - LocalPlayer *mPlayer; - - /** - * Status Part - */ - gcn::Label *mLvlLabel, *mJobLvlLabel; - gcn::Label *mGpLabel; - int mCurrency; - gcn::Label *mHpLabel, *mMpLabel, *mXpLabel, *mJobLabel; - ProgressBar *mHpBar, *mMpBar; - ProgressBar *mXpBar, *mJobBar; - - /** - * Derived Statistics captions - */ - gcn::Label *mStatsAttackLabel, *mStatsDefenseLabel; - gcn::Label *mStatsMagicAttackLabel, *mStatsMagicDefenseLabel; - gcn::Label *mStatsAccuracyLabel, *mStatsEvadeLabel; - gcn::Label *mStatsReflexLabel; - - gcn::Label *mStatsAttackPoints, *mStatsDefensePoints; - gcn::Label *mStatsMagicAttackPoints, *mStatsMagicDefensePoints; - gcn::Label *mStatsAccuracyPoints, *mStatsEvadePoints; - gcn::Label *mStatsReflexPoints; - - /** - * Stats captions. - */ - gcn::Label *mStatsLabel[6]; - gcn::Label *mPointsLabel[6]; - gcn::Label *mStatsDisplayLabel[6]; - gcn::Label *mRemainingStatsPointsLabel; - - /** - * Stats buttons. - */ - gcn::Button *mStatsButton[6]; -}; - -extern StatusWindow *statusWindow; - -#endif diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp index edbf387b..6f5f72fa 100644 --- a/src/gui/statuswindow.cpp +++ b/src/gui/statuswindow.cpp @@ -23,353 +23,494 @@ #include "gui/widgets/button.h" #include "gui/widgets/label.h" +#include "gui/widgets/layouthelper.h" #include "gui/widgets/progressbar.h" +#include "gui/widgets/scrollarea.h" +#include "gui/widgets/vertcontainer.h" #include "gui/widgets/windowcontainer.h" +#include "gui/ministatus.h" +#include "gui/setup.h" + #include "localplayer.h" +#include "units.h" + +#include "net/net.h" +#include "net/playerhandler.h" + +#ifdef EATHENA_SUPPORT +#include "net/ea/protocol.h" +#endif +#include "utils/gettext.h" +#include "utils/mathutils.h" #include "utils/stringutils.h" -StatusWindow::StatusWindow(LocalPlayer *player): - Window(player->getName()), - mPlayer(player) +class AttrDisplay : public Container +{ + public: + virtual std::string update(); + + protected: + AttrDisplay(int id, const std::string &name); + + const int mId; + const std::string mName; + + LayoutHelper *mLayout; + Label *mLabel; + Label *mValue; +}; + +class DerDisplay : public AttrDisplay +{ + public: + DerDisplay(int id, const std::string &name); +}; + +class ChangeDisplay : public AttrDisplay, gcn::ActionListener +{ + public: + ChangeDisplay(int id, const std::string &name); + std::string update(); + void setPointsNeeded(int needed); + + private: + void action(const gcn::ActionEvent &event); + + int mNeeded; + + Label *mPoints; + Button *mDec; + Button *mInc; +}; + +StatusWindow::StatusWindow(): + Window(player_node->getName()) { setWindowName("Status"); + setupWindow->registerWindowForReset(this); setResizable(true); setCloseButton(true); setSaveVisible(true); setDefaultSize((windowContainer->getWidth() - 365) / 2, (windowContainer->getHeight() - 255) / 2, 365, 275); - loadWindowState(); // ---------------------- // Status Part // ---------------------- - mLvlLabel = new Label("Level:"); - mMoneyLabel = new Label("Money:"); - - mHpLabel = new Label("HP:"); - mHpBar = new ProgressBar(0.0f, 80, 15, gcn::Color(0, 171, 34)); - mHpValueLabel = new Label; - - int y = 3; - int x = 5; - - mLvlLabel->setPosition(x, y); - x += mLvlLabel->getWidth() + 40; - mMoneyLabel->setPosition(x, y); - - y += mLvlLabel->getHeight() + 5; // Next Row - x = 5; - - mHpLabel->setPosition(x, y); - x += mHpLabel->getWidth() + 5; - mHpBar->setPosition(x, y); - x += mHpBar->getWidth() + 5; - mHpValueLabel->setPosition(x, y); - - y += mHpLabel->getHeight() + 5; // Next Row - x = 5; - - add(mLvlLabel); - add(mMoneyLabel); - add(mHpLabel); - add(mHpValueLabel); - add(mHpBar); + mLvlLabel = new Label(strprintf(_("Level: %d"), 0)); + mMoneyLabel = new Label(strprintf(_("Money: %s"), "")); + + mHpLabel = new Label(_("HP:")); + mHpBar = new ProgressBar((float) player_node->getHp() + / (float) player_node->getMaxHp(), + 80, 15, gcn::Color(0, 171, 34)); + + mXpLabel = new Label(_("Exp:")); + mXpBar = new ProgressBar((float) player_node->getExp() + / player_node->getExpNeeded(), + 80, 15, gcn::Color(143, 192, 211)); + + mMpLabel = new Label(_("MP:")); + mMpBar = new ProgressBar((float) player_node->getMaxMP() + / (float) player_node->getMaxMP(), + 80, 15, gcn::Color(26, 102, 230)); + + place(0, 0, mLvlLabel, 3); + // 5, 0 Job Level + place(8, 0, mMoneyLabel, 3); + place(0, 1, mHpLabel).setPadding(3); + place(1, 1, mHpBar, 4); + place(5, 1, mXpLabel).setPadding(3); + place(6, 1, mXpBar, 5); + place(0, 2, mMpLabel).setPadding(3); + // 5, 2 and 6, 2 Job Progress Bar + place(1, 2, mMpBar, 4); + +#ifdef EATHENA_SUPPORT + mJobLvlLabel = new Label(strprintf(_("Job: %d"), 0)); + mJobLabel = new Label(_("Job:")); + mJobBar = new ProgressBar(0.0f, 80, 15, gcn::Color(220, 135, 203)); + + place(5, 0, mJobLvlLabel, 3); + place(5, 2, mJobLabel).setPadding(3); + place(6, 2, mJobBar, 5); +#endif // ---------------------- // Stats Part // ---------------------- - // Static Labels - gcn::Label *mStatsTitleLabel = new Label("Stats"); - gcn::Label *mStatsTotalLabel = new Label("Total"); - - // Derived Stats -/* - mStatsAttackLabel = new Label("Attack:"); - mStatsDefenseLabel= new Label("Defense:"); - mStatsMagicAttackLabel = new Label("M.Attack:"); - mStatsMagicDefenseLabel = new Label("M.Defense:"); - mStatsAccuracyLabel = new Label("% Accuracy:"); - mStatsEvadeLabel = new Label("% Evade:"); - mStatsReflexLabel = new Label("% Reflex:"); - - mStatsAttackPoints = new Label; - mStatsDefensePoints = new Label; - mStatsMagicAttackPoints = new Label; - mStatsMagicDefensePoints = new Label; - mStatsAccuracyPoints = new Label("% Accuracy:"); - mStatsEvadePoints = new Label("% Evade:"); - mStatsReflexPoints = new Label("% Reflex:"); -*/ - // New labels - for (int i = 0; i < 6; i++) { - mStatsLabel[i] = new Label; - mStatsDisplayLabel[i] = new Label; - } - mCharacterPointsLabel = new Label; - mCorrectionPointsLabel = new Label; - - // Set button events Id - mStatsPlus[0] = new Button("+", "STR+", this); - mStatsPlus[1] = new Button("+", "AGI+", this); - mStatsPlus[2] = new Button("+", "DEX+", this); - mStatsPlus[3] = new Button("+", "VIT+", this); - mStatsPlus[4] = new Button("+", "INT+", this); - mStatsPlus[5] = new Button("+", "WIL+", this); + mAttrCont = new VertContainer(32); + mAttrScroll = new ScrollArea(mAttrCont); + mAttrScroll->setOpaque(false); + mAttrScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); + mAttrScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO); + place(0, 3, mAttrScroll, 5, 3); - mStatsMinus[0] = new Button("-", "STR-", this); - mStatsMinus[1] = new Button("-", "AGI-", this); - mStatsMinus[2] = new Button("-", "DEX-", this); - mStatsMinus[3] = new Button("-", "VIT-", this); - mStatsMinus[4] = new Button("-", "INT-", this); - mStatsMinus[5] = new Button("-", "WIL-", this); + mDAttrCont = new VertContainer(32); + mDAttrScroll = new ScrollArea(mDAttrCont); + mDAttrScroll->setOpaque(false); + mDAttrScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); + mDAttrScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO); + place(6, 3, mDAttrScroll, 5, 3); + getLayout().setRowHeight(3, Layout::AUTO_SET); + mCharacterPointsLabel = new Label("C"); + mCorrectionPointsLabel = new Label("C"); + place(0, 6, mCharacterPointsLabel, 5); + place(0, 7, mCorrectionPointsLabel, 5); - // Set position - mStatsTitleLabel->setPosition(mHpLabel->getX(), mHpLabel->getY() + 23 ); - mStatsTotalLabel->setPosition(110, mStatsTitleLabel->getY() + 15); - int totalLabelY = mStatsTotalLabel->getY(); - - for (int i = 0; i < 6; i++) - { - mStatsLabel[i]->setPosition(5, - mStatsTotalLabel->getY() + (i * 23) + 15); - mStatsMinus[i]->setPosition(85, totalLabelY + (i * 23) + 15); - mStatsDisplayLabel[i]->setPosition(125, - totalLabelY + (i * 23) + 15); - mStatsPlus[i]->setPosition(185, totalLabelY + (i * 23) + 15); - } + loadWindowState(); - mCharacterPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 25); - mCorrectionPointsLabel->setPosition(5, mStatsDisplayLabel[5]->getY() + 35); -/* - mStatsAttackLabel->setPosition(220, mStatsLabel[0]->getY()); - mStatsDefenseLabel->setPosition(220, mStatsLabel[1]->getY()); - mStatsMagicAttackLabel->setPosition(220, mStatsLabel[2]->getY()); - mStatsMagicDefenseLabel->setPosition(220, mStatsLabel[3]->getY()); - mStatsAccuracyLabel->setPosition(220, mStatsLabel[4]->getY()); - mStatsEvadeLabel->setPosition(220, mStatsLabel[5]->getY()); - mStatsReflexLabel->setPosition(220, mStatsLabel[6]->getY()); - - mStatsAttackPoints->setPosition(310, mStatsLabel[0]->getY()); - mStatsDefensePoints->setPosition(310, mStatsLabel[1]->getY()); - mStatsMagicAttackPoints->setPosition(310, mStatsLabel[2]->getY()); - mStatsMagicDefensePoints->setPosition(310, mStatsLabel[3]->getY()); - mStatsAccuracyPoints->setPosition(310, mStatsLabel[4]->getY()); - mStatsEvadePoints->setPosition(310, mStatsLabel[5]->getY()); - mStatsReflexPoints->setPosition(310, mStatsLabel[6]->getY()); -*/ - // Assemble - add(mStatsTitleLabel); - add(mStatsTotalLabel); - for(int i = 0; i < 6; i++) - { - add(mStatsLabel[i]); - add(mStatsDisplayLabel[i]); - add(mStatsPlus[i]); - add(mStatsMinus[i]); - }/* - add(mStatsAttackLabel); - add(mStatsDefenseLabel); - add(mStatsMagicAttackLabel); - add(mStatsMagicDefenseLabel); - add(mStatsAccuracyLabel); - add(mStatsEvadeLabel); - add(mStatsReflexLabel); - - add(mStatsAttackPoints); - add(mStatsDefensePoints); - add(mStatsMagicAttackPoints); - add(mStatsMagicDefensePoints); - add(mStatsAccuracyPoints); - add(mStatsEvadePoints); - add(mStatsReflexPoints);*/ - - add(mCharacterPointsLabel); - add(mCorrectionPointsLabel); + update(HP); + update(MP); + update(EXP); + update(MONEY); + update(CHAR_POINTS); // This also updates all attributes (none atm) + update(LEVEL); +#ifdef EATHENA_SUPPORT + update(JOB); +#endif } -void StatusWindow::update() +std::string StatusWindow::update(int id) { - // Status Part - // ----------- - mLvlLabel->setCaption( "Level: " + - toString(mPlayer->getLevel()) + - " (" + - toString(mPlayer->getLevelProgress()) + - "%)"); - mLvlLabel->adjustSize(); - - mMoneyLabel->setCaption("Money: " + toString(mPlayer->getMoney()) + " GP"); - mMoneyLabel->adjustSize(); + if (miniStatusWindow) + miniStatusWindow->update(id); - updateHPBar(mHpBar, true); - - // Stats Part - // ---------- - const std::string attrNames[6] = { - "Strength", - "Agility", - "Dexterity", - "Vitality", - "Intelligence", - "Willpower" - }; - int characterPoints = mPlayer->getCharacterPoints(); - int correctionPoints = mPlayer->getCorrectionPoints(); - // Update labels - for (int i = 0; i < 6; i++) + if (id == HP) { - mStatsLabel[i]->setCaption(attrNames[i]); - mStatsDisplayLabel[i]->setCaption( - strprintf("%d / %d", - mPlayer->getAttributeEffective(CHAR_ATTR_BEGIN + i), - mPlayer->getAttributeBase(CHAR_ATTR_BEGIN + i))); - - mStatsLabel[i]->adjustSize(); - mStatsDisplayLabel[i]->adjustSize(); + updateHPBar(mHpBar, true); - mStatsPlus[i]->setEnabled(characterPoints); - mStatsMinus[i]->setEnabled(correctionPoints); + return _("HP"); } - mCharacterPointsLabel->setCaption("Character Points: " + - toString(characterPoints)); - mCharacterPointsLabel->adjustSize(); - - mCorrectionPointsLabel->setCaption("Correction Points: " + - toString(correctionPoints)); - mCorrectionPointsLabel->adjustSize(); -/* - // Derived Stats Points - - // Attack TODO: Count equipped Weapons and items attack bonuses - mStatsAttackPoints->setCaption( - toString(mPlayer->ATK + mPlayer->ATK_BONUS)); - mStatsAttackPoints->adjustSize(); - - // Defense TODO: Count equipped Armors and items defense bonuses - mStatsDefensePoints->setCaption( - toString(mPlayer->DEF + mPlayer->DEF_BONUS)); - mStatsDefensePoints->adjustSize(); - - // Magic Attack TODO: Count equipped items M.Attack bonuses - mStatsMagicAttackPoints->setCaption( - toString(mPlayer->MATK + mPlayer->MATK_BONUS)); - mStatsMagicAttackPoints->adjustSize(); - - // Magic Defense TODO: Count equipped items M.Defense bonuses - mStatsMagicDefensePoints->setCaption( - toString(mPlayer->MDEF + mPlayer->MDEF_BONUS)); - mStatsMagicDefensePoints->adjustSize(); - - // Accuracy % - mStatsAccuracyPoints->setCaption(toString(mPlayer->HIT)); - mStatsAccuracyPoints->adjustSize(); - - // Evasion % - mStatsEvadePoints->setCaption(toString(mPlayer->FLEE)); - mStatsEvadePoints->adjustSize(); - - // Reflex % - mStatsReflexPoints->setCaption(toString(mPlayer->DEX / 4)); // + counter - mStatsReflexPoints->adjustSize(); -*/ - // Update Second column widgets position - mMoneyLabel->setPosition(mLvlLabel->getX() + mLvlLabel->getWidth() + 20, - mLvlLabel->getY()); - -} - -void StatusWindow::draw(gcn::Graphics *g) -{ - update(); - - Window::draw(g); -} - -void StatusWindow::action(const gcn::ActionEvent &event) -{ - const std::string &eventId = event.getId(); - - // Stats Part - if (eventId == "STR+") + else if (id == MP) { - mPlayer->raiseAttribute(LocalPlayer::STR); + updateMPBar(mMpBar, true); + + return _("MP"); } - else if (eventId == "AGI+") + else if (id == EXP) { - mPlayer->raiseAttribute(LocalPlayer::AGI); + updateXPBar(mXpBar, false); + + return _("Exp"); } - else if (eventId == "DEX+") + else if (id == MONEY) { - mPlayer->raiseAttribute(LocalPlayer::DEX); + int money = player_node->getMoney(); + mMoneyLabel->setCaption(strprintf(_("Money: %s"), + Units::formatCurrency(money).c_str())); + mMoneyLabel->adjustSize(); + + return _("Money"); } - else if (eventId == "VIT+") +#ifdef EATHENA_SUPPORT + else if (id == JOB) { - mPlayer->raiseAttribute(LocalPlayer::VIT); + mJobLvlLabel->setCaption(strprintf(_("Job: %d"), + player_node->getAttributeBase(JOB))); + mJobLvlLabel->adjustSize(); + + updateProgressBar(mJobBar, JOB, false); + + return _("Job"); } - else if (eventId == "INT+") +#endif + else if (id == CHAR_POINTS) { - mPlayer->raiseAttribute(LocalPlayer::INT); + mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"), + player_node->getCharacterPoints())); + mCharacterPointsLabel->adjustSize(); + + mCorrectionPointsLabel->setCaption(strprintf(_("Correction points: %d"), + player_node->getCorrectionPoints())); + mCorrectionPointsLabel->adjustSize(); + + for (Attrs::iterator it = mAttrs.begin(); it != mAttrs.end(); it++) + { + it->second->update(); + } } - else if (eventId == "WIL+") + else if (id == LEVEL) { - mPlayer->raiseAttribute(LocalPlayer::WIL); - } + mLvlLabel->setCaption(strprintf(_("Level: %d"), + player_node->getLevel())); + mLvlLabel->adjustSize(); - else if (eventId == "STR-") - { - mPlayer->lowerAttribute(LocalPlayer::STR); - } - else if (eventId == "AGI-") - { - mPlayer->lowerAttribute(LocalPlayer::AGI); + return _("Level"); } - else if (eventId == "DEX-") + else { - mPlayer->lowerAttribute(LocalPlayer::DEX); + Attrs::iterator it = mAttrs.find(id); + + if (it != mAttrs.end()) + { + return it->second->update(); + } } - else if (eventId == "VIT-") + + return ""; +} + +void StatusWindow::setPointsNeeded(int id, int needed) +{ + Attrs::iterator it = mAttrs.find(id); + + if (it != mAttrs.end()) { - mPlayer->lowerAttribute(LocalPlayer::VIT); + ChangeDisplay *disp = dynamic_cast<ChangeDisplay*>(it->second); + if (disp) + disp->setPointsNeeded(needed); } - else if (eventId == "INT-") +} + +void StatusWindow::addAttribute(int id, const std::string &name, + bool modifiable) +{ + AttrDisplay *disp; + + if (modifiable) { - mPlayer->lowerAttribute(LocalPlayer::INT); + disp = new ChangeDisplay(id, name); + mAttrCont->add(disp); } - else if (eventId == "WIL-") + else { - mPlayer->lowerAttribute(LocalPlayer::WIL); + disp = new DerDisplay(id, name); + mDAttrCont->add(disp); } -} -// WARNING: Duplicated method! + mAttrs[id] = disp; +} void StatusWindow::updateHPBar(ProgressBar *bar, bool showMax) { + if (showMax) bar->setText(toString(player_node->getHp()) + "/" + toString(player_node->getMaxHp())); else bar->setText(toString(player_node->getHp())); - // HP Bar coloration - if (player_node->getHp() < player_node->getMaxHp() / 3) + if (player_node->getMaxHp() < 4) { - bar->setColor(223, 32, 32); // Red + bar->setColor(guiPalette->getColor(Palette::HPBAR_ONE_QUARTER)); } - else if (player_node->getHp() < (player_node->getMaxHp() / 3) * 2) + else { - bar->setColor(230, 171, 34); // Orange + // HP Bar coloration + float r1 = 255; + float g1 = 255; + float b1 = 255; + + float r2 = 255; + float g2 = 255; + float b2 = 255; + + float weight = 1.0f; + + int curHP = player_node->getHp(); + int thresholdLevel = player_node->getMaxHp() / 4; + int thresholdProgress = curHP % thresholdLevel; + + if (thresholdLevel) + weight = 1 - ((float)thresholdProgress) / ((float)thresholdLevel); + else + weight = 0; + + if (curHP < (thresholdLevel)) + { + gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_ONE_HALF); + gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_ONE_QUARTER); + r1 = color1.r; r2 = color2.r; + g1 = color1.g; g2 = color2.g; + b1 = color1.b; b2 = color2.b; + } + else if (curHP < (thresholdLevel*2)) + { + gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_THREE_QUARTERS); + gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_ONE_HALF); + r1 = color1.r; r2 = color2.r; + g1 = color1.g; g2 = color2.g; + b1 = color1.b; b2 = color2.b; + } + else if (curHP < thresholdLevel*3) + { + gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_FULL); + gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_THREE_QUARTERS); + r1 = color1.r; r2 = color2.r; + g1 = color1.g; g2 = color2.g; + b1 = color1.b; b2 = color2.b; + } + else + { + gcn::Color color1 = guiPalette->getColor(Palette::HPBAR_FULL); + gcn::Color color2 = guiPalette->getColor(Palette::HPBAR_FULL); + r1 = color1.r; r2 = color2.r; + g1 = color1.g; g2 = color2.g; + b1 = color1.b; b2 = color2.b; + } + + // Safety checks + if (weight > 1.0f) weight = 1.0f; + if (weight < 0.0f) weight = 0.0f; + + // Do the color blend + r1 = (int) weightedAverage(r1, r2,weight); + g1 = (int) weightedAverage(g1, g2, weight); + b1 = (int) weightedAverage(b1, b2, weight); + + // More safety checks + if (r1 > 255) r1 = 255; + if (g1 > 255) g1 = 255; + if (b1 > 255) b1 = 255; + + bar->setColor(r1, g1, b1); } + + bar->setProgress((float) player_node->getHp() / (float) player_node->getMaxHp()); + +} + +void StatusWindow::updateMPBar(ProgressBar *bar, bool showMax) +{ + if (showMax) + bar->setText(toString(player_node->getMP()) + + "/" + toString(player_node->getMaxMP())); else + bar->setText(toString(player_node->getMP())); + + if (Net::getPlayerHandler()->canUseMagic()) + bar->setColor(26, 102, 230); // blue, to indicate that we have magic + else + bar->setColor(100, 100, 100); // grey, to indicate that we lack magic + + bar->setProgress((float) player_node->getMP() / + (float) player_node->getMaxMP()); +} + +void StatusWindow::updateProgressBar(ProgressBar *bar, int value, int max, + bool percent) +{ + if (max == 0) { - bar->setColor(0, 171, 34); // Green + bar->setText(_("Max")); + bar->setProgress(1.0); } + else + { + float progress = (float) value / max; - bar->setProgress((float) player_node->getHp() / (float) player_node->getMaxHp()); + if (percent) + bar->setText(strprintf("%2.2f", 100 * progress) + "%"); + else + bar->setText(toString(value) + "/" + toString(max)); + + bar->setProgress(progress); + } +} + +void StatusWindow::updateXPBar(ProgressBar *bar, bool percent) +{ + updateProgressBar(bar, player_node->getExp(), player_node->getExpNeeded(), + percent); +} + +void StatusWindow::updateProgressBar(ProgressBar *bar, int id, bool percent) +{ + std::pair<int, int> exp = player_node->getExperience(id); + updateProgressBar(bar, exp.first, exp.second, percent); +} + +AttrDisplay::AttrDisplay(int id, const std::string &name): + mId(id), + mName(name) +{ + setSize(100, 32); + mLabel = new Label(name); + mValue = new Label("1"); + + mLabel->setAlignment(Graphics::CENTER); + mValue->setAlignment(Graphics::CENTER); + + mLayout = new LayoutHelper(this); +} + +std::string AttrDisplay::update() +{ + int base = player_node->getAttributeBase(mId); + int bonus = player_node->getAttributeEffective(mId) - base; + std::string value = toString(base); + if (bonus) + value += strprintf(" (%+d)", bonus); + mValue->setCaption(value); + + return mName; +} + +DerDisplay::DerDisplay(int id, const std::string &name): + AttrDisplay(id, name) +{ + // Do the layout + LayoutHelper h(this); + ContainerPlacer place = mLayout->getPlacer(0, 0); + + place(0, 0, mLabel, 3); + place(3, 0, mValue, 2); + + update(); +} + +ChangeDisplay::ChangeDisplay(int id, const std::string &name): + AttrDisplay(id, name), mNeeded(1) +{ + mPoints = new Label("1"); + mDec = new Button(_("-"), "dec", this); + mInc = new Button(_("+"), "inc", this); + mDec->setWidth(mInc->getWidth()); + + // Do the layout + ContainerPlacer place = mLayout->getPlacer(0, 0); + + place(0, 0, mLabel, 3); + place(3, 0, mDec); + place(4, 0, mValue, 2); + place(6, 0, mInc); + place(7, 0, mPoints); + + update(); +} + +std::string ChangeDisplay::update() +{ + mPoints->setCaption(toString(mNeeded)); + + mDec->setEnabled(player_node->getCorrectionPoints()); + mInc->setEnabled(player_node->getCharacterPoints() >= mNeeded); + + return AttrDisplay::update(); +} + +void ChangeDisplay::setPointsNeeded(int needed) +{ + mNeeded = needed; + + update(); +} + +void ChangeDisplay::action(const gcn::ActionEvent &event) +{ + if (event.getSource() == mDec) + { + Net::getPlayerHandler()->decreaseAttribute(mId); + } + else if (event.getSource() == mInc) + { + Net::getPlayerHandler()->increaseAttribute(mId); + } } diff --git a/src/gui/statuswindow.h b/src/gui/statuswindow.h index 1e2a5097..f6d4f73e 100644 --- a/src/gui/statuswindow.h +++ b/src/gui/statuswindow.h @@ -28,75 +28,71 @@ #include <guichan/actionlistener.hpp> -class LocalPlayer; +#include <map> + +class AttrDisplay; class ProgressBar; +class ScrollArea; +class VertContainer; /** * The player status dialog. * * \ingroup Interface */ -class StatusWindow : public Window, public gcn::ActionListener +class StatusWindow : public Window { public: + enum { // Some update constants + HP = -1, + MP = -2, + EXP = -3, + MONEY = -4, + CHAR_POINTS = -5, + LEVEL = -6 + }; + /** * Constructor. */ - StatusWindow(LocalPlayer *player); + StatusWindow(); - /** - * Called when receiving actions from widget. - */ - void action(const gcn::ActionEvent &event); + std::string update(int id); - /** - * Draw this window - */ - void draw(gcn::Graphics *graphics); + void setPointsNeeded(int id, int needed); - /** - * Updates this dialog with values from PLAYER_INFO *char_info - */ - void update(); + void addAttribute(int id, const std::string &name, bool modifiable); static void updateHPBar(ProgressBar *bar, bool showMax = false); + static void updateMPBar(ProgressBar *bar, bool showMax = false); + static void updateXPBar(ProgressBar *bar, bool percent = true); + static void updateProgressBar(ProgressBar *bar, int value, int max, + bool percent); + void updateProgressBar(ProgressBar *bar, int id, + bool percent = true); private: - LocalPlayer *mPlayer; - /** * Status Part */ - gcn::Label *mLvlLabel, *mMoneyLabel, *mHpLabel, *mHpValueLabel; - ProgressBar *mHpBar; + gcn::Label *mLvlLabel, *mMoneyLabel; + gcn::Label *mHpLabel, *mMpLabel, *mXpLabel; + ProgressBar *mHpBar, *mMpBar, *mXpBar; - /** - * Derived Statistics captions - */ -/* - gcn::Label *mStatsAttackLabel, *mStatsDefenseLabel; - gcn::Label *mStatsMagicAttackLabel, *mStatsMagicDefenseLabel; - gcn::Label *mStatsAccuracyLabel, *mStatsEvadeLabel; - gcn::Label *mStatsReflexLabel; - - gcn::Label *mStatsAttackPoints, *mStatsDefensePoints; - gcn::Label *mStatsMagicAttackPoints, *mStatsMagicDefensePoints; - gcn::Label *mStatsAccuracyPoints, *mStatsEvadePoints; - gcn::Label *mStatsReflexPoints; -*/ - /** - * Stats captions. - */ - gcn::Label *mStatsLabel[6]; - gcn::Label *mStatsDisplayLabel[6]; - gcn::Label *mCharacterPointsLabel; - gcn::Label *mCorrectionPointsLabel; +#ifdef EATHENA_SUPPORT + gcn::Label *mJobLvlLabel, *mJobLabel; + ProgressBar *mJobBar; +#endif - /** - * Stats buttons. - */ - gcn::Button *mStatsPlus[6]; - gcn::Button *mStatsMinus[6]; + VertContainer *mAttrCont; + ScrollArea *mAttrScroll; + VertContainer *mDAttrCont; + ScrollArea *mDAttrScroll; + + gcn::Label *mCharacterPointsLabel, *mCorrectionPointsLabel; + + typedef std::map<int, AttrDisplay*> Attrs; + Attrs mAttrs; }; extern StatusWindow *statusWindow; diff --git a/src/gui/storagewindow.cpp b/src/gui/storagewindow.cpp index 91224359..f0d00ee7 100644 --- a/src/gui/storagewindow.cpp +++ b/src/gui/storagewindow.cpp @@ -24,6 +24,7 @@ #include "gui/inventorywindow.h" #include "gui/itemamount.h" #include "gui/itemcontainer.h" +#include "gui/setup.h" #include "gui/viewport.h" #include "gui/widgets/button.h" @@ -58,6 +59,7 @@ StorageWindow::StorageWindow(int invSize): setWindowName("Storage"); setResizable(true); setCloseButton(true); + setupWindow->registerWindowForReset(this); // If you adjust these defaults, don't forget to adjust the trade window's. setDefaultSize(375, 300, ImageRect::CENTER); diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 3abb985e..22eefc14 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -29,6 +29,7 @@ #include "gui/inventorywindow.h" #include "gui/itemamount.h" #include "gui/itemcontainer.h" +#include "gui/setup.h" #include "gui/widgets/button.h" #include "gui/widgets/chattab.h" @@ -65,6 +66,7 @@ TradeWindow::TradeWindow(): setDefaultSize(386, 180, ImageRect::CENTER); setMinWidth(386); setMinHeight(180); + setupWindow->registerWindowForReset(this); std::string longestName = getFont()->getWidth(_("OK")) > getFont()->getWidth(_("Trade")) ? @@ -92,7 +94,7 @@ TradeWindow::TradeWindow(): ScrollArea *partnerScroll = new ScrollArea(mPartnerItemContainer); partnerScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); - mMoneyLabel = new Label(strprintf(_("You get %s."), "")); + mMoneyLabel = new Label(strprintf(_("You get %s"), "")); gcn::Label *mMoneyLabel2 = new Label(_("You give:")); mMoneyField = new TextField; @@ -128,7 +130,7 @@ TradeWindow::~TradeWindow() void TradeWindow::setMoney(int amount) { - mMoneyLabel->setCaption(strprintf(_("You get %s."), + mMoneyLabel->setCaption(strprintf(_("You get %s"), Units::formatCurrency(amount).c_str())); mMoneyLabel->adjustSize(); } @@ -255,7 +257,10 @@ void TradeWindow::action(const gcn::ActionEvent &event) return; if (!inventoryWindow->isVisible()) + { + inventoryWindow->setVisible(true); return; + } if (!item) return; diff --git a/src/gui/unregisterdialog.cpp b/src/gui/unregisterdialog.cpp index 048239c5..be54453d 100644 --- a/src/gui/unregisterdialog.cpp +++ b/src/gui/unregisterdialog.cpp @@ -42,7 +42,7 @@ #include <sstream> UnRegisterDialog::UnRegisterDialog(Window *parent, LoginData *loginData): - Window("Unregister", true, parent), + Window(_("Unregister"), true, parent), mWrongDataNoticeListener(new WrongDataNoticeListener), mLoginData(loginData) { @@ -102,24 +102,23 @@ UnRegisterDialog::action(const gcn::ActionEvent &event) logger->log("UnregisterDialog::unregistered, Username is %s", username.c_str()); - std::stringstream errorMsg; + std::stringstream errorMessage; bool error = false; // Check password if (password.length() < LEN_MIN_PASSWORD) { // Pass too short - errorMsg << "The password needs to be at least " - << LEN_MIN_PASSWORD - << " characters long."; + errorMessage << strprintf(_("The password needs to be at least %d " + "characters long."), LEN_MIN_PASSWORD); error = true; } - else if (password.length() > LEN_MAX_PASSWORD - 1 ) + else if (password.length() > LEN_MAX_PASSWORD - 1) { // Pass too long - errorMsg << "The password needs to be less than " - << LEN_MAX_PASSWORD - << " characters long."; + errorMessage << strprintf(_("The password needs to be less than " + "%d characters long."), + LEN_MAX_PASSWORD); error = true; } @@ -127,7 +126,7 @@ UnRegisterDialog::action(const gcn::ActionEvent &event) { mWrongDataNoticeListener->setTarget(this->mPasswordField); - OkDialog *dlg = new OkDialog("Error", errorMsg.str()); + OkDialog *dlg = new OkDialog(_("Error"), errorMessage.str()); dlg->addActionListener(mWrongDataNoticeListener); } else diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 21362630..bb2128b4 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -322,9 +322,8 @@ int UpdaterWindow::downloadThread(void *ptr) { case CURLE_COULDNT_CONNECT: default: - std::cerr << _("curl error ") << res << ": " - << uw->mCurlError << _(" host: ") << url.c_str() - << std::endl; + logger->log("curl error %d: %s host: %s", + res, uw->mCurlError, url.c_str()); break; } @@ -445,10 +444,13 @@ void UpdaterWindow::logic() } mThread = NULL; } + // TODO: Only send complete sentences to gettext mBrowserBox->addRow(""); mBrowserBox->addRow(_("##1 The update process is incomplete.")); + // TRANSLATORS: Continues "you try again later.". mBrowserBox->addRow(_("##1 It is strongly recommended that")); - mBrowserBox->addRow(_("##1 you try again later")); + // TRANSLATORS: Begins "It is strongly recommended that". + mBrowserBox->addRow(_("##1 you try again later.")); mBrowserBox->addRow(mCurlError); mScrollArea->setVerticalScrollAmount( mScrollArea->getVerticalMaxScroll()); diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 68b5fed3..9a631581 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -116,22 +116,12 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) } // Calculate viewpoint -#ifdef TMWSERV_SUPPORT int midTileX = (graphics->getWidth() + mScrollCenterOffsetX) / 2; int midTileY = (graphics->getHeight() + mScrollCenterOffsetX) / 2; const Vector &playerPos = player_node->getPosition(); const int player_x = (int) playerPos.x - midTileX; const int player_y = (int) playerPos.y - midTileY; -#else - int midTileX = (graphics->getWidth() + mScrollCenterOffsetX) / 32 / 2; - int midTileY = (graphics->getHeight() + mScrollCenterOffsetY) / 32 / 2; - - int player_x = (player_node->mX - midTileX) * 32 + - player_node->getXOffset(); - int player_y = (player_node->mY - midTileY) * 32 + - player_node->getYOffset(); -#endif if (mScrollLaziness < 1) mScrollLaziness = 1; // Avoids division by zero diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 71579bd4..2357b263 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -152,7 +152,10 @@ void Button::draw(gcn::Graphics *graphics) static_cast<Graphics*>(graphics)-> drawImageRect(0, 0, getWidth(), getHeight(), button[mode]); - graphics->setColor(guiPalette->getColor(Palette::TEXT)); + if (mode == BUTTON_DISABLED) + graphics->setColor(guiPalette->getColor(Palette::BUTTON_DISABLED)); + else + graphics->setColor(guiPalette->getColor(Palette::BUTTON)); int textX; int textY = getHeight() / 2 - getFont()->getHeight() / 2; diff --git a/src/gui/widgets/channeltab.cpp b/src/gui/widgets/channeltab.cpp index e3edbba0..8b055a22 100644 --- a/src/gui/widgets/channeltab.cpp +++ b/src/gui/widgets/channeltab.cpp @@ -72,23 +72,24 @@ bool ChannelTab::handleCommand(const std::string &type, { chatLog(_("Command: /quit")); chatLog(_("This command leaves the current channel.")); - chatLog(_("If you're the last person in the channel, it will be deleted.")); + chatLog(_("If you're the last person in the channel, " + "it will be deleted.")); } else if (args == "op") { chatLog(_("Command: /op <nick>")); chatLog(_("This command makes <nick> a channel operator.")); chatLog(_("If the <nick> has spaces in it, enclose it in " - "double quotes (\").")); + "double quotes (\").")); chatLog(_("Channel operators can kick and op other users " - "from the channel.")); + "from the channel.")); } else if (args == "kick") { chatLog(_("Command: /kick <nick>")); chatLog(_("This command makes <nick> leave the channel.")); chatLog(_("If the <nick> has spaces in it, enclose it in " - "double quotes (\").")); + "double quotes (\").")); } else return false; diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp index d2fa33b8..e3ba4874 100644 --- a/src/gui/widgets/chattab.cpp +++ b/src/gui/widgets/chattab.cpp @@ -143,7 +143,7 @@ void ChatTab::chatLog(std::string line, int own, bool ignoreRecord) lineColor = "##2"; // Equiv. to BrowserBox::GREEN break; case ACT_WHISPER: - tmp.nick = strprintf(_("%s whispers: "), tmp.nick.c_str()); + tmp.nick = strprintf(_("%s whispers: %s"), tmp.nick.c_str(), ""); lineColor = "##W"; break; case ACT_IS: diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp index 2e9a234b..dd57f674 100644 --- a/src/gui/widgets/checkbox.cpp +++ b/src/gui/widgets/checkbox.cpp @@ -35,9 +35,12 @@ Image *CheckBox::checkBoxNormal; Image *CheckBox::checkBoxChecked; Image *CheckBox::checkBoxDisabled; Image *CheckBox::checkBoxDisabledChecked; +Image *CheckBox::checkBoxNormalHi; +Image *CheckBox::checkBoxCheckedHi; CheckBox::CheckBox(const std::string &caption, bool selected): - gcn::CheckBox(caption, selected) + gcn::CheckBox(caption, selected), + mHasMouse(false) { if (instances == 0) { @@ -47,10 +50,14 @@ CheckBox::CheckBox(const std::string &caption, bool selected): checkBoxChecked = checkBox->getSubImage(9, 0, 9, 10); checkBoxDisabled = checkBox->getSubImage(18, 0, 9, 10); checkBoxDisabledChecked = checkBox->getSubImage(27, 0, 9, 10); + checkBoxNormalHi = checkBox->getSubImage(36, 0, 9, 10); + checkBoxCheckedHi = checkBox->getSubImage(45, 0, 9, 10); checkBoxNormal->setAlpha(mAlpha); checkBoxChecked->setAlpha(mAlpha); checkBoxDisabled->setAlpha(mAlpha); checkBoxDisabledChecked->setAlpha(mAlpha); + checkBoxNormalHi->setAlpha(mAlpha); + checkBoxCheckedHi->setAlpha(mAlpha); checkBox->decRef(); } @@ -67,6 +74,8 @@ CheckBox::~CheckBox() delete checkBoxChecked; delete checkBoxDisabled; delete checkBoxDisabledChecked; + delete checkBoxNormalHi; + delete checkBoxCheckedHi; } } @@ -86,17 +95,22 @@ void CheckBox::drawBox(gcn::Graphics* graphics) { Image *box; - if (isSelected()) - { - if (isEnabled()) - box = checkBoxChecked; + if (isEnabled()) + if (isSelected()) + if (mHasMouse) + box = checkBoxCheckedHi; + else + box = checkBoxChecked; else - box = checkBoxDisabledChecked; - } - else if (isEnabled()) - box = checkBoxNormal; + if (mHasMouse) + box = checkBoxNormalHi; + else + box = checkBoxNormal; else - box = checkBoxDisabled; + if (isSelected()) + box = checkBoxDisabledChecked; + else + box = checkBoxDisabled; if (config.getValue("guialpha", 0.8) != mAlpha) { @@ -105,7 +119,19 @@ void CheckBox::drawBox(gcn::Graphics* graphics) checkBoxChecked->setAlpha(mAlpha); checkBoxDisabled->setAlpha(mAlpha); checkBoxDisabledChecked->setAlpha(mAlpha); + checkBoxNormal->setAlpha(mAlpha); + checkBoxCheckedHi->setAlpha(mAlpha); } static_cast<Graphics*>(graphics)->drawImage(box, 2, 2); } + +void CheckBox::mouseEntered(gcn::MouseEvent& event) +{ + mHasMouse = true; +} + +void CheckBox::mouseExited(gcn::MouseEvent& event) +{ + mHasMouse = false; +} diff --git a/src/gui/widgets/checkbox.h b/src/gui/widgets/checkbox.h index 303782b0..7a7c8674 100644 --- a/src/gui/widgets/checkbox.h +++ b/src/gui/widgets/checkbox.h @@ -24,6 +24,7 @@ #include <guichan/widgets/checkbox.hpp> + class Image; /** @@ -54,13 +55,26 @@ class CheckBox : public gcn::CheckBox */ void drawBox(gcn::Graphics* graphics); + /** + * Called when the mouse enteres the widget area. + */ + void mouseEntered(gcn::MouseEvent& event); + + /** + * Called when the mouse leaves the widget area. + */ + void mouseExited(gcn::MouseEvent& event); + private: static int instances; static float mAlpha; + bool mHasMouse; static Image *checkBoxNormal; static Image *checkBoxChecked; static Image *checkBoxDisabled; static Image *checkBoxDisabledChecked; + static Image *checkBoxNormalHi; + static Image *checkBoxCheckedHi; }; #endif diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp index a4164bcc..13ac866a 100644 --- a/src/gui/widgets/desktop.cpp +++ b/src/gui/widgets/desktop.cpp @@ -39,8 +39,9 @@ Desktop::Desktop() Wallpaper::loadWallpapers(); - gcn::Label *versionLabel = new Label(FULL_VERSION); - add(versionLabel, 25, 2); + mVersionLabel = new Label(FULL_VERSION); + mVersionLabel->setBackgroundColor(gcn::Color(255, 255, 255, 128)); + add(mVersionLabel, 25, 2); } Desktop::~Desktop() @@ -74,11 +75,20 @@ void Desktop::draw(gcn::Graphics *graphics) if (mWallpaper) { - g->drawImage(mWallpaper, + if (!mWallpaper->isAnOpenGLOne()) + g->drawImage(mWallpaper, (getWidth() - mWallpaper->getWidth()) / 2, (getHeight() - mWallpaper->getHeight()) / 2); + else + g->drawRescaledImage(mWallpaper, 0, 0, 0, 0, + mWallpaper->getWidth(), mWallpaper->getHeight(), + getWidth(), getHeight(), false); } + // Draw a thin border under the application version... + g->setColor(gcn::Color(255, 255, 255, 128)); + g->fillRectangle(gcn::Rectangle(mVersionLabel->getDimension())); + Container::draw(graphics); } @@ -87,13 +97,27 @@ void Desktop::setBestFittingWallpaper() const std::string wallpaperName = Wallpaper::getWallpaper(getWidth(), getHeight()); - Image *temp = ResourceManager::getInstance()->getImage(wallpaperName); + Image *nWallPaper = ResourceManager::getInstance()->getImage(wallpaperName); - if (temp) + if (nWallPaper) { if (mWallpaper) mWallpaper->decRef(); - mWallpaper = temp; + + if (!nWallPaper->isAnOpenGLOne() && (nWallPaper->getWidth() != getWidth() + || nWallPaper->getHeight() != getHeight())) + { + // We rescale to obtain a fullscreen wallpaper... + Image *newRsclWlPpr = nWallPaper->SDLgetScaledImage(getWidth(), getHeight()); + std::string idPath = nWallPaper->getIdPath(); + + // We replace the resource in the resource manager + nWallPaper->decRef(); + ResourceManager::getInstance()->addResource(idPath, newRsclWlPpr); + mWallpaper = newRsclWlPpr; + } + else + mWallpaper = nWallPaper; } else { diff --git a/src/gui/widgets/desktop.h b/src/gui/widgets/desktop.h index ad04ee96..da623bbd 100644 --- a/src/gui/widgets/desktop.h +++ b/src/gui/widgets/desktop.h @@ -24,6 +24,8 @@ #include "gui/widgets/container.h" +#include "guichanfwd.h" + #include <guichan/widgetlistener.hpp> class Image; @@ -60,6 +62,7 @@ class Desktop : public Container, gcn::WidgetListener void setBestFittingWallpaper(); Image *mWallpaper; + gcn::Label *mVersionLabel; }; #endif // DESKTOP_H diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index 134d071f..7cc020ef 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -43,14 +43,17 @@ ProgressBar::ProgressBar(float progress, int width, int height, const gcn::Color &color): gcn::Widget(), - mProgress(0.0f), - mProgressToGo(0.0f), mSmoothProgress(true), mColor(color), mColorToGo(color), mSmoothColorChange(true) { - setProgress(progress); + // The progress value is directly set at load time: + if (progress > 1.0f || progress < 0.0f) + progress = 1.0f; + + mProgress = mProgressToGo = progress; + setSize(width, height); if (mInstances == 0) diff --git a/src/gui/widgets/radiobutton.cpp b/src/gui/widgets/radiobutton.cpp index 6f0ccdbd..9cf49672 100644 --- a/src/gui/widgets/radiobutton.cpp +++ b/src/gui/widgets/radiobutton.cpp @@ -33,10 +33,13 @@ Image *RadioButton::radioNormal; Image *RadioButton::radioChecked; Image *RadioButton::radioDisabled; Image *RadioButton::radioDisabledChecked; +Image *RadioButton::radioNormalHi; +Image *RadioButton::radioCheckedHi; RadioButton::RadioButton(const std::string &caption, const std::string &group, bool marked): - gcn::RadioButton(caption, group, marked) + gcn::RadioButton(caption, group, marked), + mHasMouse(false) { if (instances == 0) { @@ -45,10 +48,14 @@ RadioButton::RadioButton(const std::string &caption, const std::string &group, radioChecked = resman->getImage("graphics/gui/radioin.png"); radioDisabled = resman->getImage("graphics/gui/radioout.png"); radioDisabledChecked = resman->getImage("graphics/gui/radioin.png"); + radioNormalHi = resman->getImage("graphics/gui/radioout_highlight.png"); + radioCheckedHi = resman->getImage("graphics/gui/radioin_highlight.png"); radioNormal->setAlpha(mAlpha); radioChecked->setAlpha(mAlpha); radioDisabled->setAlpha(mAlpha); radioDisabledChecked->setAlpha(mAlpha); + radioNormalHi->setAlpha(mAlpha); + radioCheckedHi->setAlpha(mAlpha); } instances++; @@ -64,6 +71,8 @@ RadioButton::~RadioButton() radioChecked->decRef(); radioDisabled->decRef(); radioDisabledChecked->decRef(); + radioNormalHi->decRef(); + radioCheckedHi->decRef(); } } @@ -76,21 +85,28 @@ void RadioButton::drawBox(gcn::Graphics* graphics) radioChecked->setAlpha(mAlpha); radioDisabled->setAlpha(mAlpha); radioDisabledChecked->setAlpha(mAlpha); + radioNormalHi->setAlpha(mAlpha); + radioCheckedHi->setAlpha(mAlpha); } Image *box = NULL; - if (isSelected()) - { - if (isEnabled()) - box = radioChecked; + if (isEnabled()) + if (isSelected()) + if (mHasMouse) + box = radioCheckedHi; + else + box = radioChecked; else - box = radioDisabledChecked; - } - else if (isEnabled()) - box = radioNormal; + if (mHasMouse) + box = radioNormalHi; + else + box = radioNormal; else - box = radioDisabled; + if (isSelected()) + box = radioDisabledChecked; + else + box = radioDisabled; if (box) static_cast<Graphics*>(graphics)->drawImage(box, 2, 2); @@ -111,3 +127,14 @@ void RadioButton::draw(gcn::Graphics* graphics) int h = getHeight() + getHeight() / 2; graphics->drawText(getCaption(), h - 2, 0); } + +void RadioButton::mouseEntered(gcn::MouseEvent& event) +{ + mHasMouse = true; +} + +void RadioButton::mouseExited(gcn::MouseEvent& event) +{ + mHasMouse = false; +} + diff --git a/src/gui/widgets/radiobutton.h b/src/gui/widgets/radiobutton.h index 9aec3add..57eb3623 100644 --- a/src/gui/widgets/radiobutton.h +++ b/src/gui/widgets/radiobutton.h @@ -26,13 +26,13 @@ class Image; -/* +/** * Guichan based RadioButton with custom look */ class RadioButton : public gcn::RadioButton { public: - /* + /** * Constructor. */ RadioButton(const std::string &caption,const std::string &group, @@ -54,13 +54,26 @@ class RadioButton : public gcn::RadioButton */ void draw(gcn::Graphics* graphics); + /** + * Called when the mouse enteres the widget area. + */ + void mouseEntered(gcn::MouseEvent& event); + + /** + * Called when the mouse leaves the widget area. + */ + void mouseExited(gcn::MouseEvent& event); + private: static int instances; static float mAlpha; + bool mHasMouse; static Image *radioNormal; static Image *radioChecked; static Image *radioDisabled; static Image *radioDisabledChecked; + static Image *radioNormalHi; + static Image *radioCheckedHi; }; #endif /* RADIOBUTTON_H */ diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp index ff3a23d1..52322b05 100644 --- a/src/gui/widgets/scrollarea.cpp +++ b/src/gui/widgets/scrollarea.cpp @@ -33,10 +33,13 @@ int ScrollArea::instances = 0; float ScrollArea::mAlpha = 1.0; ImageRect ScrollArea::background; ImageRect ScrollArea::vMarker; +ImageRect ScrollArea::vMarkerHi; Image *ScrollArea::buttons[4][2]; ScrollArea::ScrollArea(): gcn::ScrollArea(), + mX(0), + mY(0), mOpaque(true) { init(); @@ -44,6 +47,7 @@ ScrollArea::ScrollArea(): ScrollArea::ScrollArea(gcn::Widget *widget): gcn::ScrollArea(widget), + mHasMouse(false), mOpaque(true) { init(); @@ -60,6 +64,7 @@ ScrollArea::~ScrollArea() { for_each(background.grid, background.grid + 9, dtor<Image*>()); for_each(vMarker.grid, vMarker.grid + 9, dtor<Image*>()); + for_each(vMarkerHi.grid, vMarkerHi.grid + 9, dtor<Image*>()); buttons[UP][0]->decRef(); buttons[UP][1]->decRef(); @@ -103,6 +108,8 @@ void ScrollArea::init() // Load vertical scrollbar skin Image *vscroll = resman->getImage("graphics/gui/vscroll_grey.png"); + Image *vscrollHi = resman->getImage("graphics/gui/vscroll_highlight.png"); + int vsgridx[4] = {0, 4, 7, 11}; int vsgridy[4] = {0, 4, 15, 19}; a = 0; @@ -115,12 +122,18 @@ void ScrollArea::init() vsgridx[x], vsgridy[y], vsgridx[x + 1] - vsgridx[x], vsgridy[y + 1] - vsgridy[y]); + vMarkerHi.grid[a] = vscrollHi->getSubImage( + vsgridx[x], vsgridy[y], + vsgridx[x + 1] - vsgridx[x], + vsgridy[y + 1] - vsgridy[y]); vMarker.grid[a]->setAlpha(config.getValue("guialpha", 0.8)); + vMarkerHi.grid[a]->setAlpha(config.getValue("guialpha", 0.8)); a++; } } vscroll->decRef(); + vscrollHi->decRef(); buttons[UP][0] = resman->getImage("graphics/gui/vscroll_up_default.png"); @@ -202,6 +215,7 @@ void ScrollArea::draw(gcn::Graphics *graphics) { background.grid[a]->setAlpha(mAlpha); vMarker.grid[a]->setAlpha(mAlpha); + vMarkerHi.grid[a]->setAlpha(mAlpha); } } @@ -296,14 +310,39 @@ void ScrollArea::drawVMarker(gcn::Graphics *graphics) { gcn::Rectangle dim = getVerticalMarkerDimension(); - static_cast<Graphics*>(graphics)-> - drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarker); + if ((mHasMouse) && (mX > (getWidth() - getScrollbarWidth()))) + static_cast<Graphics*>(graphics)-> + drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarkerHi); + else + static_cast<Graphics*>(graphics)-> + drawImageRect(dim.x, dim.y, dim.width, dim.height,vMarker); } void ScrollArea::drawHMarker(gcn::Graphics *graphics) { gcn::Rectangle dim = getHorizontalMarkerDimension(); - static_cast<Graphics*>(graphics)-> - drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarker); + if ((mHasMouse) && (mY > (getHeight() - getScrollbarWidth()))) + static_cast<Graphics*>(graphics)-> + drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarkerHi); + else + static_cast<Graphics*>(graphics)-> + drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarker); } + +void ScrollArea::mouseMoved(gcn::MouseEvent& event) +{ +mX = event.getX(); +mY = event.getY(); +} + +void ScrollArea::mouseEntered(gcn::MouseEvent& event) +{ + mHasMouse = true; +} + +void ScrollArea::mouseExited(gcn::MouseEvent& event) +{ + mHasMouse = false; +} + diff --git a/src/gui/widgets/scrollarea.h b/src/gui/widgets/scrollarea.h index 700de32b..8fd92b5f 100644 --- a/src/gui/widgets/scrollarea.h +++ b/src/gui/widgets/scrollarea.h @@ -83,6 +83,21 @@ class ScrollArea : public gcn::ScrollArea */ bool isOpaque() const { return mOpaque; } + /** + * Called when the mouse moves in the widget area. + */ + void mouseMoved(gcn::MouseEvent& event); + + /** + * Called when the mouse enteres the widget area. + */ + void mouseEntered(gcn::MouseEvent& event); + + /** + * Called when the mouse leaves the widget area. + */ + void mouseExited(gcn::MouseEvent& event); + protected: enum BUTTON_DIR { UP, @@ -110,8 +125,11 @@ class ScrollArea : public gcn::ScrollArea static float mAlpha; static ImageRect background; static ImageRect vMarker; + static ImageRect vMarkerHi; static Image *buttons[4][2]; + int mX,mY; + bool mHasMouse; bool mOpaque; }; diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp index 7cd0e54a..6ce5f849 100644 --- a/src/gui/widgets/slider.cpp +++ b/src/gui/widgets/slider.cpp @@ -29,17 +29,21 @@ Image *Slider::hStart, *Slider::hMid, *Slider::hEnd, *Slider::hGrip; Image *Slider::vStart, *Slider::vMid, *Slider::vEnd, *Slider::vGrip; +Image *Slider::hStartHi, *Slider::hMidHi, *Slider::hEndHi, *Slider::hGripHi; +Image *Slider::vStartHi, *Slider::vMidHi, *Slider::vEndHi, *Slider::vGripHi; float Slider::mAlpha = 1.0; int Slider::mInstances = 0; Slider::Slider(double scaleEnd): - gcn::Slider(scaleEnd) + gcn::Slider(scaleEnd), + mHasMouse(false) { init(); } Slider::Slider(double scaleStart, double scaleEnd): - gcn::Slider(scaleStart, scaleEnd) + gcn::Slider(scaleStart, scaleEnd), + mHasMouse(false) { init(); } @@ -58,6 +62,14 @@ Slider::~Slider() delete vMid; delete vEnd; delete vGrip; + delete hStartHi; + delete hMidHi; + delete hEndHi; + delete hGripHi; + delete vStartHi; + delete vMidHi; + delete vEndHi; + delete vGripHi; } } @@ -71,6 +83,7 @@ void Slider::init() { ResourceManager *resman = ResourceManager::getInstance(); Image *slider = resman->getImage("graphics/gui/slider.png"); + Image *sliderHi = resman->getImage("graphics/gui/slider_hilight.png"); x = 0; y = 0; w = 15; h = 6; @@ -78,10 +91,14 @@ void Slider::init() hStart = slider->getSubImage(x, y, o1 - x, h); hMid = slider->getSubImage(o1, y, o2 - o1, h); hEnd = slider->getSubImage(o2, y, w - o2 + x, h); + hStartHi = sliderHi->getSubImage(x, y, o1 - x, h); + hMidHi = sliderHi->getSubImage(o1, y, o2 - o1, h); + hEndHi = sliderHi->getSubImage(o2, y, w - o2 + x, h); x = 6; y = 8; w = 9; h = 10; hGrip = slider->getSubImage(x, y, w, h); + hGripHi = sliderHi->getSubImage(x, y, w, h); x = 0; y = 6; w = 6; h = 21; @@ -89,22 +106,35 @@ void Slider::init() vStart = slider->getSubImage(x, y, w, o1 - y); vMid = slider->getSubImage(x, o1, w, o2 - o1); vEnd = slider->getSubImage(x, o2, w, h - o2 + y); + vStartHi = sliderHi->getSubImage(x, y, w, o1 - y); + vMidHi = sliderHi->getSubImage(x, o1, w, o2 - o1); + vEndHi = sliderHi->getSubImage(x, o2, w, h - o2 + y); x = 6; y = 8; w = 9; h = 10; vGrip = slider->getSubImage(x, y, w, h); + vGripHi = sliderHi->getSubImage(x, y, w, h); slider->decRef(); + sliderHi->decRef(); hStart->setAlpha(mAlpha); hMid->setAlpha(mAlpha); hEnd->setAlpha(mAlpha); hGrip->setAlpha(mAlpha); + hStartHi->setAlpha(mAlpha); + hMidHi->setAlpha(mAlpha); + hEndHi->setAlpha(mAlpha); + hGripHi->setAlpha(mAlpha); vStart->setAlpha(mAlpha); vMid->setAlpha(mAlpha); vEnd->setAlpha(mAlpha); vGrip->setAlpha(mAlpha); + vStartHi->setAlpha(mAlpha); + vMidHi->setAlpha(mAlpha); + vEndHi->setAlpha(mAlpha); + vGripHi->setAlpha(mAlpha); } mInstances++; @@ -117,7 +147,7 @@ void Slider::draw(gcn::Graphics *graphics) int w = getWidth(); int h = getHeight(); int x = 0; - int y = (h - hStart->getHeight()) / 2; + int y = mHasMouse?(h - hStartHi->getHeight()) / 2:(h - hStart->getHeight()) / 2; if (config.getValue("guialpha", 0.8) != mAlpha) { @@ -126,23 +156,45 @@ void Slider::draw(gcn::Graphics *graphics) hMid->setAlpha(mAlpha); hEnd->setAlpha(mAlpha); hGrip->setAlpha(mAlpha); + hStartHi->setAlpha(mAlpha); + hMidHi->setAlpha(mAlpha); + hEndHi->setAlpha(mAlpha); + hGripHi->setAlpha(mAlpha); vStart->setAlpha(mAlpha); vMid->setAlpha(mAlpha); vEnd->setAlpha(mAlpha); vGrip->setAlpha(mAlpha); + vStartHi->setAlpha(mAlpha); + vMidHi->setAlpha(mAlpha); + vEndHi->setAlpha(mAlpha); + vGripHi->setAlpha(mAlpha); } + if (!mHasMouse) + { + static_cast<Graphics*>(graphics)->drawImage(hStart, x, y); - static_cast<Graphics*>(graphics)->drawImage(hStart, x, y); + w -= hStart->getWidth() + hEnd->getWidth(); + x += hStart->getWidth(); - w -= hStart->getWidth() + hEnd->getWidth(); - x += hStart->getWidth(); + static_cast<Graphics*>(graphics)-> + drawImagePattern(hMid, x, y, w, hMid->getHeight()); - static_cast<Graphics*>(graphics)-> - drawImagePattern(hMid, x, y, w, hMid->getHeight()); + x += w; + static_cast<Graphics*>(graphics)->drawImage(hEnd, x, y); + } else + { + static_cast<Graphics*>(graphics)->drawImage(hStartHi, x, y); - x += w; - static_cast<Graphics*>(graphics)->drawImage(hEnd, x, y); + w -= hStartHi->getWidth() + hEndHi->getWidth(); + x += hStartHi->getWidth(); + + static_cast<Graphics*>(graphics)-> + drawImagePattern(hMidHi, x, y, w, hMidHi->getHeight()); + + x += w; + static_cast<Graphics*>(graphics)->drawImage(hEndHi, x, y); + } drawMarker(graphics); } @@ -150,5 +202,16 @@ void Slider::draw(gcn::Graphics *graphics) void Slider::drawMarker(gcn::Graphics *graphics) { static_cast<Graphics*>(graphics)-> - drawImage(hGrip, getMarkerPosition(), (getHeight() - hGrip->getHeight()) / 2); + drawImage(mHasMouse?hGripHi:hGrip, getMarkerPosition(), + (getHeight() - (mHasMouse?hGripHi:hGrip)->getHeight()) / 2); } + +void Slider::mouseEntered(gcn::MouseEvent& event) +{ + mHasMouse = true; +} + +void Slider::mouseExited(gcn::MouseEvent& event) +{ + mHasMouse = false; +}
\ No newline at end of file diff --git a/src/gui/widgets/slider.h b/src/gui/widgets/slider.h index 56ea334a..85fb2633 100644 --- a/src/gui/widgets/slider.h +++ b/src/gui/widgets/slider.h @@ -58,6 +58,16 @@ class Slider : public gcn::Slider { */ void drawMarker(gcn::Graphics *graphics); + /** + * Called when the mouse enteres the widget area. + */ + void mouseEntered(gcn::MouseEvent& event); + + /** + * Called when the mouse leaves the widget area. + */ + void mouseExited(gcn::MouseEvent& event); + private: /** * Used to initialize instances. @@ -66,6 +76,9 @@ class Slider : public gcn::Slider { static Image *hStart, *hMid, *hEnd, *hGrip; static Image *vStart, *vMid, *vEnd, *vGrip; + static Image *hStartHi, *hMidHi, *hEndHi, *hGripHi; + static Image *vStartHi, *vMidHi, *vEndHi, *vGripHi; + bool mHasMouse; static float mAlpha; static int mInstances; }; diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index f2231fca..3e49263e 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -55,7 +55,7 @@ struct TabData static TabData const data[TAB_COUNT] = { { "graphics/gui/tab.png", 0, 0 }, - { "graphics/gui/tab.png", 9, 4 }, + { "graphics/gui/tab_hilight.png", 9, 4 }, { "graphics/gui/tabselected.png", 16, 19 }, { "graphics/gui/tab.png", 25, 23 } }; @@ -63,7 +63,7 @@ static TabData const data[TAB_COUNT] = { ImageRect Tab::tabImg[TAB_COUNT]; Tab::Tab() : gcn::Tab(), - mTabColor(&guiPalette->getColor(Palette::TEXT)) + mTabColor(&guiPalette->getColor(Palette::TAB)) { init(); } @@ -123,21 +123,19 @@ void Tab::draw(gcn::Graphics *graphics) // check which type of tab to draw if (mTabbedArea) { + mLabel->setForegroundColor(*mTabColor); if (mTabbedArea->isTabSelected(this)) { mode = TAB_SELECTED; // if tab is selected, it doesnt need to highlight activity - mLabel->setForegroundColor(*mTabColor); mHighlighted = false; - } - else if (mHighlighted) + } else if (mHasMouse) { mode = TAB_HIGHLIGHTED; - mLabel->setForegroundColor(guiPalette->getColor(Palette::TAB_HIGHLIGHT)); } - else + if (mHighlighted) { - mLabel->setForegroundColor(*mTabColor); + mLabel->setForegroundColor(guiPalette->getColor(Palette::TAB_HIGHLIGHT)); } } diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp index 07f46a94..bb5ae9a4 100644 --- a/src/gui/widgets/tabbedarea.cpp +++ b/src/gui/widgets/tabbedarea.cpp @@ -69,6 +69,16 @@ gcn::Widget *TabbedArea::getWidget(const std::string &name) const return NULL; } +gcn::Widget *TabbedArea::getCurrentWidget() +{ + gcn::Tab *tab = getSelectedTab(); + + if (tab) + return getWidget(tab->getCaption()); + else + return NULL; +} + void TabbedArea::addTab(const std::string &caption, gcn::Widget *widget) { Tab *tab = new Tab; diff --git a/src/gui/widgets/tabbedarea.h b/src/gui/widgets/tabbedarea.h index 6aaafe16..29ba2f76 100644 --- a/src/gui/widgets/tabbedarea.h +++ b/src/gui/widgets/tabbedarea.h @@ -63,6 +63,11 @@ class TabbedArea : public gcn::TabbedArea */ gcn::Widget *getWidget(const std::string &name) const; + /** + * Returns the widget for the current tab + */ + gcn::Widget *getCurrentWidget(); + using gcn::TabbedArea::addTab; /** diff --git a/src/gui/widgets/vertcontainer.cpp b/src/gui/widgets/vertcontainer.cpp new file mode 100644 index 00000000..9dd02cdc --- /dev/null +++ b/src/gui/widgets/vertcontainer.cpp @@ -0,0 +1,53 @@ +/* + * The Mana World + * Copyright (C) 2009 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/vertcontainer.h" + +VertContainer::VertContainer(int spacing): + mSpacing(spacing), + mCount(0) +{ + addWidgetListener(this); +} + +void VertContainer::add(gcn::Widget *widget) +{ + Container::add(widget); + widget->setPosition(0, mCount * mSpacing); + widget->setSize(getWidth(), mSpacing); + mCount++; + setHeight(mCount * mSpacing); +} + +void VertContainer::clear() +{ + Container::clear(); + + mCount = 0; +} + +void VertContainer::widgetResized(const gcn::Event &event) +{ + for (WidgetListIterator it = mWidgets.begin(); it != mWidgets.end(); it++) + { + (*it)->setWidth(getWidth()); + } +} diff --git a/src/gui/widgets/vertcontainer.h b/src/gui/widgets/vertcontainer.h new file mode 100644 index 00000000..9e15e66a --- /dev/null +++ b/src/gui/widgets/vertcontainer.h @@ -0,0 +1,47 @@ +/* + * The Mana World + * Copyright (C) 2009 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GUI_VERTCONTAINER_H +#define GUI_VERTCONTAINER_H + +#include "gui/widgets/container.h" + +#include <guichan/widgetlistener.hpp> + +/** + * A widget container. + * + * This container places it's contents veritcally. + */ +class VertContainer : public Container, public gcn::WidgetListener +{ + public: + VertContainer(int spacing); + virtual void add(gcn::Widget *widget); + virtual void clear(); + void widgetResized(const gcn::Event &event); + + private: + int mSpacing; + int mCount; +}; + +#endif diff --git a/src/gui/widgets/whispertab.cpp b/src/gui/widgets/whispertab.cpp index 43c63cc0..5509a589 100644 --- a/src/gui/widgets/whispertab.cpp +++ b/src/gui/widgets/whispertab.cpp @@ -84,14 +84,14 @@ bool WhisperTab::handleCommand(const std::string &type, else if (args == "ignore") { chatLog(_("Command: /ignore")); - chatLog(_("This command ignores the other player reguardless of " + chatLog(_("This command ignores the other player regardless of " "current relations.")); } else if (args == "unignore") { chatLog(_("Command: /unignore <player>")); chatLog(_("This command stops ignoring the other player if they " - "are being ignored")); + "are being ignored.")); } else return false; diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 19d80671..1ee84a6f 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -306,6 +306,10 @@ void Window::setVisible(bool visible) void Window::setVisible(bool visible, bool forceSticky) { + // Check if the window is off screen... + if (visible) + checkIfIsOffScreen(); + gcn::Window::setVisible((!forceSticky && isSticky()) || visible); } @@ -526,6 +530,9 @@ void Window::loadWindowState() { setSize(mDefaultWidth, mDefaultHeight); } + + // Check if the window is off screen... + checkIfIsOffScreen(); } void Window::saveWindowState() @@ -739,3 +746,63 @@ void Window::center() { setLocationRelativeTo(getParent()); } + +void Window::checkIfIsOffScreen(bool partially, bool entirely) +{ + // Move the window onto screen if it has become off screen + // For instance, because of resolution change... + + // First of all, don't deal when a window hasn't got + // any size initialized yet... + if (getWidth() == 0 && getHeight() == 0) + return; + + // Made partially the default behaviour + if (!partially && !entirely) + partially = true; + + // Keep guichan window inside screen (supports resizing any side) + + gcn::Rectangle winDimension = getDimension(); + + if (winDimension.x < 0) + { + winDimension.width += winDimension.x; + winDimension.x = 0; + } + if (winDimension.y < 0) + { + winDimension.height += winDimension.y; + winDimension.y = 0; + } + + // Look if the window is partially off-screen limits... + if (partially) + { + if (winDimension.x + winDimension.width > graphics->getWidth()) + { + winDimension.x = graphics->getWidth() - winDimension.width; + } + + if (winDimension.y + winDimension.height > graphics->getHeight()) + { + winDimension.y = graphics->getHeight() - winDimension.height; + } + setDimension(winDimension); + return; + } + + if (entirely) + { + if (winDimension.x > graphics->getWidth()) + { + winDimension.x = graphics->getWidth() - winDimension.width; + } + + if (winDimension.y > graphics->getHeight()) + { + winDimension.y = graphics->getHeight() - winDimension.height; + } + } + setDimension(winDimension); +} diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h index 153602ba..b3ef3fdc 100644 --- a/src/gui/widgets/window.h +++ b/src/gui/widgets/window.h @@ -269,7 +269,7 @@ class Window : public gcn::Window, gcn::WidgetListener int defaultWidth, int defaultHeight); /** - * Set the default win pos and size tot he current ones. + * Set the default win pos and size to the current ones. */ void setDefaultSize(); @@ -347,6 +347,13 @@ class Window : public gcn::Window, gcn::WidgetListener }; /** + * Check if the window is off-screen and then move it to be visible + * again. This is internally used by loadWindowState + * and setVisible(true) members. + */ + void checkIfIsOffScreen(bool partially = true, bool entirely = true); + + /** * Determines if the mouse is in a resize area and returns appropriate * resize handles. Also initializes drag offset in case the resize * grip is used. diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp index 8964f072..96776617 100644 --- a/src/gui/windowmenu.cpp +++ b/src/gui/windowmenu.cpp @@ -62,7 +62,7 @@ WindowMenu::WindowMenu(): #ifdef TMWSERV_SUPPORT N_("Magic"), N_("Guilds"), - N_("Buddys"), + N_("Buddies"), #endif N_("Shortcut"), N_("Setup"), @@ -138,7 +138,7 @@ void WindowMenu::action(const gcn::ActionEvent &event) { window = guildWindow; } - else if (event.getId() == "Buddys") + else if (event.getId() == "Buddies") { window = buddyWindow; } diff --git a/src/inventory.cpp b/src/inventory.cpp index 532d9ab6..202c3e52 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -29,11 +29,7 @@ struct SlotUsed : public std::unary_function<Item*, bool> { bool operator()(const Item *item) const { -#ifdef TMWSERV_SUPPORT - return item && item->getId() && item->getQuantity(); -#else - return item && item->getId() != -1 && item->getQuantity() > 0; -#endif + return item && item->getId() >= 0 && item->getQuantity() > 0; } }; @@ -54,11 +50,7 @@ Inventory::~Inventory() Item *Inventory::getItem(int index) const { -#ifdef TMWSERV_SUPPORT - if (index < 0 || index >= mSize) -#else if (index < 0 || index >= mSize || !mItems[index] || mItems[index]->getQuantity() <= 0) -#endif return 0; return mItems[index]; @@ -91,6 +83,7 @@ void Inventory::setItem(int index, int id, int quantity, bool equipment) Item *item = new Item(id, quantity, equipment); item->setInvIndex(index); mItems[index] = item; + mItems[index]->setEquipment(equipment); } else if (id > 0) { diff --git a/src/item.cpp b/src/item.cpp index 2fadc035..312a7f63 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -43,10 +43,8 @@ void Item::setId(int id) { mId = id; -#ifdef TMWSERV_SUPPORT // Types 0 and 1 are not equippable items. mEquipment = id && getInfo().getType() >= 2; -#endif // Load the associated image if (mImage) diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 241cfe99..1cc0ae34 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -40,25 +40,25 @@ #include "gui/gui.h" #include "gui/ministatus.h" #include "gui/palette.h" -#ifdef EATHENA_SUPPORT +#include "gui/skilldialog.h" +#include "gui/statuswindow.h" #include "gui/storagewindow.h" -#endif + +#include "gui/widgets/chattab.h" #include "net/inventoryhandler.h" #include "net/net.h" #include "net/partyhandler.h" #include "net/playerhandler.h" +#include "net/specialhandler.h" #include "net/tradehandler.h" -#ifdef TMWSERV_SUPPORT #include "effectmanager.h" +#ifdef TMWSERV_SUPPORT #include "guild.h" -#include "net/tmwserv/gameserver/player.h" +//#include "net/tmwserv/gameserver/player.h" #include "net/tmwserv/chatserver/guild.h" -#else -#include "net/ea/partyhandler.h" -#include "net/ea/skillhandler.h" #endif #include "resources/animation.h" @@ -80,44 +80,26 @@ const short walkingKeyboardDelay = 40; LocalPlayer *player_node = NULL; -#ifdef TMWSERV_SUPPORT -LocalPlayer::LocalPlayer(): - Player(65535, 0, NULL), - mEquipment(new Equipment), -#else LocalPlayer::LocalPlayer(int id, int job, Map *map): Player(id, job, map), - mCharId(0), - mJobXp(0), - mJobLevel(0), - mXpForNextLevel(0), mJobXpForNextLevel(0), - mMp(0), mMaxMp(0), +#ifdef EATHENA_SUPPORT mAttackRange(0), - ATK(0), MATK(0), DEF(0), MDEF(0), HIT(0), FLEE(0), - ATK_BONUS(0), MATK_BONUS(0), DEF_BONUS(0), MDEF_BONUS(0), FLEE_BONUS(0), - mStatPoint(0), mSkillPoint(0), - mStatsPointsToAttribute(0), - mEquipment(new Equipment), #endif + mEquipment(new Equipment), mInStorage(false), #ifdef EATHENA_SUPPORT - mXp(0), mTargetTime(-1), #endif mLastTarget(-1), -#ifdef TMWSERV_SUPPORT - mAttributeBase(NB_CHARACTER_ATTRIBUTES, -1), - mAttributeEffective(NB_CHARACTER_ATTRIBUTES, -1), - mExpCurrent(CHAR_SKILL_NB, -1), - mExpNext(CHAR_SKILL_NB, -1), - mCharacterPoints(-1), - mCorrectionPoints(-1), - mLevelProgress(0), -#endif + mCharacterPoints(0), + mCorrectionPoints(0), mLevel(1), + mExp(0), mExpNeeded(0), + mMp(0), mMaxMp(0), mMoney(0), mTotalWeight(1), mMaxWeight(1), mHp(1), mMaxHp(1), + mSkillPoints(0), mTarget(NULL), mPickUpTarget(NULL), mTrading(false), mGoingToTarget(false), mKeepAttacking(false), mLastAction(-1), @@ -127,10 +109,8 @@ LocalPlayer::LocalPlayer(int id, int job, Map *map): #ifdef TMWSERV_SUPPORT mLocalWalkTime(-1), #endif - mStorage(new Inventory(STORAGE_SIZE)) -#ifdef TMWSERV_SUPPORT - , mExpMessageTime(0) -#endif + mStorage(new Inventory(STORAGE_SIZE)), + mMessageTime(0) { // Variable to keep the local player from doing certain actions before a map // is initialized. e.g. drawing a player's name using the TextManager, since @@ -164,25 +144,28 @@ void LocalPlayer::logic() if (get_elapsed_time(mLastAction) >= 1000) mLastAction = -1; -#ifdef TMWSERV_SUPPORT // Show XP messages - if (!mExpMessages.empty()) + if (!mMessages.empty()) { - if (mExpMessageTime == 0) + if (mMessageTime == 0) { - const Vector &pos = getPosition(); + //const Vector &pos = getPosition(); + + MessagePair info = mMessages.front(); particleEngine->addTextRiseFadeOutEffect( - mExpMessages.front(), - (int) pos.x + 16, - (int) pos.y - 16, - &guiPalette->getColor(Palette::EXP_INFO), + info.first, + /*(int) pos.x, + (int) pos.y - 48,*/ + getPixelX(), + getPixelY() - 48, + &guiPalette->getColor(info.second), gui->getInfoParticleFont(), true); - mExpMessages.pop_front(); - mExpMessageTime = 30; + mMessages.pop_front(); + mMessageTime = 30; } - mExpMessageTime--; + mMessageTime--; } if ((mSpecialRechargeUpdateNeeded%11) == 0) @@ -201,7 +184,7 @@ void LocalPlayer::logic() } mSpecialRechargeUpdateNeeded++; -#else +#ifdef EATHENA_SUPPORT // Targeting allowed 4 times a second if (get_elapsed_time(mLastTarget) >= 250) mLastTarget = -1; @@ -213,7 +196,6 @@ void LocalPlayer::logic() setTarget(NULL); mLastTarget = -1; } - #endif if (mTarget) @@ -232,8 +214,8 @@ void LocalPlayer::logic() const int rangeY = abs(mTarget->getPosition().y - getPosition().y); #else // Find whether target is in range - const int rangeX = abs(mTarget->mX - mX); - const int rangeY = abs(mTarget->mY - mY); + const int rangeX = abs(mTarget->getTileX() - getTileX()); + const int rangeY = abs(mTarget->getTileY() - getTileY()); #endif const int attackRange = getAttackRange(); const int inRange = rangeX > attackRange || rangeY > attackRange @@ -366,13 +348,8 @@ void LocalPlayer::setInvItem(int index, int id, int amount) void LocalPlayer::pickUp(FloorItem *item) { -#ifdef TMWSERV_SUPPORT int dx = item->getX() - (int) getPosition().x / 32; int dy = item->getY() - (int) getPosition().y / 32; -#else - int dx = item->getX() - mX; - int dy = item->getY() - mY; -#endif if (dx * dx + dy * dy < 4) { @@ -409,22 +386,12 @@ void LocalPlayer::walk(unsigned char dir) #ifdef TMWSERV_SUPPORT Being::setDestination(pos.x, pos.y); #else - Being::setDestination(mX, mY); + Being::setDestination(getTileX(), getTileY()); #endif return; } int dx = 0, dy = 0; -#ifdef TMWSERV_SUPPORT - if (dir & UP) - dy -= 32; - if (dir & DOWN) - dy += 32; - if (dir & LEFT) - dx -= 32; - if (dir & RIGHT) - dx += 32; -#else if (dir & UP) dy--; if (dir & DOWN) @@ -433,7 +400,6 @@ void LocalPlayer::walk(unsigned char dir) dx--; if (dir & RIGHT) dx++; -#endif // Prevent skipping corners over colliding tiles #ifdef TMWSERV_SUPPORT @@ -444,9 +410,9 @@ void LocalPlayer::walk(unsigned char dir) ((int) pos.y + dy) / 32, getWalkMask())) dy = 16 - (int) pos.y % 32; #else - if (dx && !mMap->getWalk(mX + dx, mY, getWalkMask())) + if (dx && !mMap->getWalk(getTileX() + dx, getTileY(), getWalkMask())) dx = 0; - if (dy && !mMap->getWalk(mX, mY + dy, getWalkMask())) + if (dy && !mMap->getWalk(getTileX(), getTileY() + dy, getWalkMask())) dy = 0; #endif @@ -460,7 +426,7 @@ void LocalPlayer::walk(unsigned char dir) // Checks our path up to 1 tiles, if a blocking tile is found // We go to the last good tile, and break out of the loop - for (dScaler = 1; dScaler <= 1; dScaler++) + for (dScaler = 1; dScaler <= 32; dScaler++) { if ( (dx || dy) && !mMap->getWalk( ((int) pos.x + (dx * dScaler)) / 32, @@ -473,16 +439,17 @@ void LocalPlayer::walk(unsigned char dir) if (dScaler >= 0) { - setDestination((int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); + effectManager->trigger(15, (int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); + setDestination((int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); } #else - if (dx && dy && !mMap->getWalk(mX + dx, mY + dy, getWalkMask())) + if (dx && dy && !mMap->getWalk(getTileX() + dx, getTileY() + dy, getWalkMask())) dx = 0; // Walk to where the player can actually go - if ((dx || dy) && mMap->getWalk(mX + dx, mY + dy, getWalkMask())) + if ((dx || dy) && mMap->getWalk(getTileX() + dx, getTileY() + dy, getWalkMask())) { - setDestination(mX + dx, mY + dy); + setDestination(getTileX() + dx, getTileY() + dy); } #endif else if (dir) @@ -588,21 +555,22 @@ void LocalPlayer::setWalkingDir(int dir) } } -#ifdef TMWSERV_SUPPORT void LocalPlayer::stopWalking(bool sendToServer) { if (mAction == WALK && mWalkingDir) { mWalkingDir = 0; +#ifdef TMWSERV_SUPPORT mLocalWalkTime = 0; +#endif Being::setDestination(getPosition().x,getPosition().y); if (sendToServer) - Net::GameServer::Player::walk(getPosition().x, getPosition().y); + Net::getPlayerHandler()->setDestination(getPosition().x, + getPosition().y); setAction(STAND); } clearPath(); } -#endif void LocalPlayer::toggleSit() { @@ -682,9 +650,10 @@ void LocalPlayer::attack() Net::GameServer::Player::attack(getSpriteDirection()); } */ + void LocalPlayer::useSpecial(int special) { - Net::GameServer::Player::useSpecial(special); + Net::getSpecialHandler()->use(special); } void LocalPlayer::setSpecialStatus(int id, int current, int max, int recharge) @@ -724,8 +693,8 @@ void LocalPlayer::attack(Being *target, bool keep) int dist_x = plaPos.x - tarPos.x; int dist_y = plaPos.y - tarPos.y; #else - int dist_x = target->mX - mX; - int dist_y = target->mY - mY; + int dist_x = target->getTileX() - getTileX(); + int dist_y = target->getTileY() - getTileY(); // Must be standing to attack if (mAction != STAND) @@ -802,14 +771,14 @@ void LocalPlayer::stopAttack() mLastTarget = -1; } -#ifdef TMWSERV_SUPPORT - void LocalPlayer::raiseAttribute(size_t attr) { // we assume that the server allows the change. When not we will undo it later. mCharacterPoints--; - mAttributeBase.at(attr)++; - Net::GameServer::Player::raiseAttribute(attr + CHAR_ATTR_BEGIN); + IntMap::iterator it = mAttributeBase.find(attr); + if (it != mAttributeBase.end()) + (*it).second++; + Net::getPlayerHandler()->increaseAttribute(attr); } void LocalPlayer::lowerAttribute(size_t attr) @@ -817,90 +786,179 @@ void LocalPlayer::lowerAttribute(size_t attr) // we assume that the server allows the change. When not we will undo it later. mCorrectionPoints--; mCharacterPoints++; - mAttributeBase.at(attr)--; - Net::GameServer::Player::lowerAttribute(attr + CHAR_ATTR_BEGIN); + IntMap::iterator it = mAttributeBase.find(attr); + if (it != mAttributeBase.end()) + (*it).second--; + Net::getPlayerHandler()->decreaseAttribute(attr); } -const struct LocalPlayer::SkillInfo& LocalPlayer::getSkillInfo(int skill) +void LocalPlayer::setAttributeBase(int num, int value) { - static const SkillInfo skills[CHAR_SKILL_NB + 1] = - { - { _("Unarmed"), "graphics/images/unarmed.png" }, // CHAR_SKILL_WEAPON_NONE - { _("Knife"), "graphics/images/knife.png" }, // CHAR_SKILL_WEAPON_KNIFE - { _("Sword"), "graphics/images/sword.png" }, // CHAR_SKILL_WEAPON_SWORD - { _("Polearm"), "graphics/images/polearm.png" }, // CHAR_SKILL_WEAPON_POLEARM - { _("Staff"), "graphics/images/staff.png" }, // CHAR_SKILL_WEAPON_STAFF - { _("Whip"), "graphics/images/whip.png" }, // CHAR_SKILL_WEAPON_WHIP - { _("Bow"), "graphics/images/bow.png" }, // CHAR_SKILL_WEAPON_BOW - { _("Shooting"), "graphics/images/shooting.png" }, // CHAR_SKILL_WEAPON_SHOOTING - { _("Mace"), "graphics/images/mace.png" }, // CHAR_SKILL_WEAPON_MACE - { _("Axe"), "graphics/images/axe.png" }, // CHAR_SKILL_WEAPON_AXE - { _("Thrown"), "graphics/images/thrown.png" }, // CHAR_SKILL_WEAPON_THROWN - { _("Magic"), "graphics/images/magic.png" }, // CHAR_SKILL_MAGIC_IAMJUSTAPLACEHOLDER - { _("Craft"), "graphics/images/craft.png" }, // CHAR_SKILL_CRAFT_IAMJUSTAPLACEHOLDER - { _("Unknown Skill"), "graphics/images/unknown.png" } - }; - - if ((skill < 0) || (skill > CHAR_SKILL_NB)) - { - return skills[CHAR_SKILL_NB]; - } - else + int old = mAttributeBase[num]; + + mAttributeBase[num] = value; + if (skillDialog) { - return skills[skill]; + if (skillDialog->update(num).empty() || !(value > old)) + return; + + effectManager->trigger(1, this); } + + if (statusWindow) + statusWindow->update(num); +} + +void LocalPlayer::setAttributeEffective(int num, int value) +{ + mAttributeEffective[num] = value; + if (skillDialog) + skillDialog->update(num); + + if (statusWindow) + statusWindow->update(num); +} + +void LocalPlayer::setCharacterPoints(int n) +{ + mCharacterPoints = n; + + if (statusWindow) + statusWindow->update(StatusWindow::CHAR_POINTS); +} + +void LocalPlayer::setCorrectionPoints(int n) +{ + mCorrectionPoints = n; + + if (statusWindow) + statusWindow->update(StatusWindow::CHAR_POINTS); +} + +void LocalPlayer::setSkillPoints(int points) +{ + mSkillPoints = points; + if (skillDialog) + skillDialog->update(); } void LocalPlayer::setExperience(int skill, int current, int next) { - int diff = current - mExpCurrent.at(skill); - if (mMap && mExpCurrent.at(skill) != -1 && diff > 0) + std::pair<int, int> cur = getExperience(skill); + int diff = current - cur.first; + + cur = std::pair<int, int>(current, next); + + mSkillExp[skill] = cur; + std::string name; + if (skillDialog) + name = skillDialog->update(skill); + + if (mMap && cur.first != -1 && diff > 0 && !name.empty()) { - const std::string text = toString(diff) + " " + getSkillInfo(skill).name + " xp"; - mExpMessages.push_back(text); + addMessageToQueue(strprintf("%d %s xp", diff, name.c_str())); } - - mExpCurrent.at(skill) = current; - mExpNext.at(skill) = next; } std::pair<int, int> LocalPlayer::getExperience(int skill) { - return std::pair<int, int> (mExpCurrent.at(skill), mExpNext.at(skill)); + return mSkillExp[skill]; } -#else +void LocalPlayer::setHp(int value) +{ + mHp = value; -void LocalPlayer::setXp(int xp) + if (statusWindow) + statusWindow->update(StatusWindow::HP); +} + +void LocalPlayer::setMaxHp(int value) { - if (mMap && xp > mXp) + mMaxHp = value; + + if (statusWindow) + statusWindow->update(StatusWindow::HP); +} + +void LocalPlayer::setLevel(int value) +{ + mLevel = value; + + if (statusWindow) + statusWindow->update(StatusWindow::LEVEL); +} + +void LocalPlayer::setExp(int value) +{ + if (mMap && value > mExp) { - const std::string text = toString(xp - mXp) + " xp"; - - // Show XP number - particleEngine->addTextRiseFadeOutEffect( - text, - getPixelX(), - getPixelY() - 48, - &guiPalette->getColor(Palette::EXP_INFO), - gui->getInfoParticleFont(), true); + addMessageToQueue(toString(value - mExp) + " xp"); } - mXp = xp; + mExp = value; + + if (statusWindow) + statusWindow->update(StatusWindow::EXP); } -#endif +void LocalPlayer::setExpNeeded(int value) +{ + mExpNeeded = value; -void LocalPlayer::pickedUp(const std::string &item) + if (statusWindow) + statusWindow->update(StatusWindow::EXP); +} + +void LocalPlayer::setMP(int value) +{ + mMp = value; + + if (statusWindow) + statusWindow->update(StatusWindow::MP); +} + +void LocalPlayer::setMaxMP(int value) +{ + mMaxMp = value; + + if (statusWindow) + statusWindow->update(StatusWindow::MP); +} + +void LocalPlayer::setMoney(int value) +{ + mMoney = value; + + if (statusWindow) + statusWindow->update(StatusWindow::MONEY); +} + +void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount) { - if (mMap) + if (!amount) { - // Show pickup notification - particleEngine->addTextRiseFadeOutEffect( - item, - getPixelX(), - getPixelY() - 48, - &guiPalette->getColor(Palette::PICKUP_INFO), - gui->getInfoParticleFont(), true); + if (config.getValue("showpickupchat", 1)) + { + localChatTab->chatLog(_("Unable to pick up item."), BY_SERVER); + } + } + else + { + if (config.getValue("showpickupchat", 1)) + { + // TRANSLATORS: This sentence may be translated differently + // for different grammatical numbers (singular, plural, ...) + localChatTab->chatLog(strprintf(ngettext("You picked up %d " + "[@@%d|%s@@].", "You picked up %d [@@%d|%s@@].", amount), + amount, itemInfo.getId(), itemInfo.getName().c_str()), + BY_SERVER); + } + + if (mMap && config.getValue("showpickupparticle", 0)) + { + // Show pickup notification + addMessageToQueue(itemInfo.getName(), Palette::PICKUP_INFO); + } } } @@ -930,8 +988,8 @@ bool LocalPlayer::withinAttackRange(Being *target) return !(dx > range || dy > range); #else - int dist_x = abs(target->mX - mX); - int dist_y = abs(target->mY - mY); + int dist_x = abs(target->getTileX() - getTileY()); + int dist_y = abs(target->getTileY() - getTileX()); if (dist_x > getAttackRange() || dist_y > getAttackRange()) { @@ -953,7 +1011,7 @@ void LocalPlayer::setGotoTarget(Being *target) #else setTarget(target); mGoingToTarget = true; - setDestination(target->mX, target->mY); + setDestination(target->getTileX(), target->getTileY()); #endif } @@ -1049,3 +1107,9 @@ void LocalPlayer::setInStorage(bool inStorage) storageWindow->setVisible(inStorage); } #endif + +void LocalPlayer::addMessageToQueue(const std::string &message, + Palette::ColorType color) +{ + mMessages.push_back(MessagePair(message, color)); +} diff --git a/src/localplayer.h b/src/localplayer.h index 0a3f742b..0b41ca82 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -26,6 +26,7 @@ #include <vector> #include "player.h" +#include "gui/palette.h" class Equipment; class FloorItem; @@ -34,7 +35,6 @@ class Inventory; class Item; class Map; -#ifdef TMWSERV_SUPPORT struct Special { @@ -43,6 +43,7 @@ struct Special int recharge; }; + /** * Attributes used during combat. Available to all the beings. */ @@ -91,66 +92,26 @@ enum CHAR_ATTR_END, CHAR_ATTR_NB = CHAR_ATTR_END - CHAR_ATTR_BEGIN, - CHAR_SKILL_BEGIN = CHAR_ATTR_END, - - CHAR_SKILL_WEAPON_BEGIN = CHAR_SKILL_BEGIN, - CHAR_SKILL_WEAPON_NONE = CHAR_SKILL_WEAPON_BEGIN, - CHAR_SKILL_WEAPON_KNIFE, - CHAR_SKILL_WEAPON_SWORD, - CHAR_SKILL_WEAPON_POLEARM, - CHAR_SKILL_WEAPON_STAFF, - CHAR_SKILL_WEAPON_WHIP, - CHAR_SKILL_WEAPON_BOW, - CHAR_SKILL_WEAPON_SHOOTING, - CHAR_SKILL_WEAPON_MACE, - CHAR_SKILL_WEAPON_AXE, - CHAR_SKILL_WEAPON_THROWN, - CHAR_SKILL_WEAPON_END, - CHAR_SKILL_WEAPON_NB = CHAR_SKILL_WEAPON_END - CHAR_SKILL_WEAPON_BEGIN, - - CHAR_SKILL_MAGIC_BEGIN = CHAR_SKILL_WEAPON_END, - CHAR_SKILL_MAGIC_IAMJUSTAPLACEHOLDER = CHAR_SKILL_MAGIC_BEGIN, - // add magic skills here - CHAR_SKILL_MAGIC_END, - CHAR_SKILL_MAGIC_NB = CHAR_SKILL_MAGIC_END - CHAR_SKILL_MAGIC_BEGIN, - - CHAR_SKILL_CRAFT_BEGIN = CHAR_SKILL_MAGIC_END, - CHAR_SKILL_CRAFT_IAMJUSTAPLACEHOLDER = CHAR_SKILL_CRAFT_BEGIN, - // add crafting skills here - CHAR_SKILL_CRAFT_END, - CHAR_SKILL_CRAFT_NB = CHAR_SKILL_CRAFT_END - CHAR_SKILL_CRAFT_BEGIN, - - CHAR_SKILL_END = CHAR_SKILL_CRAFT_END, - CHAR_SKILL_NB = CHAR_SKILL_END - CHAR_SKILL_BEGIN, - - NB_CHARACTER_ATTRIBUTES = CHAR_SKILL_END + NB_CHARACTER_ATTRIBUTES = CHAR_ATTR_END }; -#endif - /** * The local player character. */ class LocalPlayer : public Player { public: +#ifdef TMWSERV_SUPPORT enum Attribute { -#ifdef TMWSERV_SUPPORT STR = 0, AGI, DEX, VIT, INT, WIL, CHR -#else - STR = 0, AGI, VIT, INT, DEX, LUK -#endif }; +#endif /** * Constructor. */ -#ifdef TMWSERV_SUPPORT - LocalPlayer(); -#else - LocalPlayer(int id, int job, Map *map); -#endif + LocalPlayer(int id= 65535, int job = 0, Map *map = NULL); /** * Destructor. @@ -220,14 +181,13 @@ class LocalPlayer : public Player */ void setTrading(bool trading) { mTrading = trading; } -#ifdef TMWSERV_SUPPORT void useSpecial(int id); void setSpecialStatus(int id, int current, int max, int recharge); const std::map<int, Special> &getSpecialStatus() const { return mSpecials; } -#endif + void attack(Being *target = NULL, bool keep = false); /** @@ -292,7 +252,6 @@ class LocalPlayer : public Player */ bool withinAttackRange(Being *target); -#ifdef TMWSERV_SUPPORT /** * Stops the player dead in his tracks */ @@ -307,15 +266,14 @@ class LocalPlayer : public Player * Uses a correction point to lower an attribute */ void lowerAttribute(size_t attr); -#endif void toggleSit(); void emote(Uint8 emotion); /** - * Shows item pickup effect if the player is on a map. + * Shows item pickup notifications. */ - void pickedUp(const std::string &item); + void pickedUp(const ItemInfo &itemInfo, int amount); /** * Accessors for mInStorage @@ -324,34 +282,7 @@ class LocalPlayer : public Player void setInStorage(bool inStorage); #ifdef EATHENA_SUPPORT - /** - * Sets the amount of XP. Shows XP gaining effect if the player is on - * a map. - */ - void setXp(int xp); - - /** - * Returns the amount of experience points. - */ - int getXp() const { return mXp; } - - Uint32 mCharId; /**< Used only during character selection. */ - - Uint32 mJobXp; - Uint32 mJobLevel; - Uint32 mXpForNextLevel, mJobXpForNextLevel; - Uint16 mMp, mMaxMp; - Uint16 mAttackRange; - - Uint8 mAttr[6]; - Uint8 mAttrUp[6]; - - int ATK, MATK, DEF, MDEF, HIT, FLEE; - int ATK_BONUS, MATK_BONUS, DEF_BONUS, MDEF_BONUS, FLEE_BONUS; - - Uint16 mStatPoint, mSkillPoint; - Uint16 mStatsPointsToAttribute; #endif int getHp() const @@ -360,31 +291,39 @@ class LocalPlayer : public Player int getMaxHp() const { return mMaxHp; } - void setHp(int value) - { mHp = value; } + void setHp(int value); - void setMaxHp(int value) - { mMaxHp = value; } + void setMaxHp(int value); int getLevel() const { return mLevel; } - void setLevel(int value) - { mLevel = value; } + void setLevel(int value); -#ifdef TMWSERV_SUPPORT - void setLevelProgress(int percent) - { mLevelProgress = percent; } + void setExp(int value); - int getLevelProgress() const - { return mLevelProgress; } -#endif + int getExp() const + { return mExp; } + + void setExpNeeded(int value); + + int getExpNeeded() const + { return mExpNeeded; } + + void setMP(int value); + + int getMP() const + { return mMp; } + + void setMaxMP(int value); + + int getMaxMP() const + { return mMaxMp; } int getMoney() const { return mMoney; } - void setMoney(int value) - { mMoney = value; } + void setMoney(int value); int getTotalWeight() const { return mTotalWeight; } @@ -398,42 +337,34 @@ class LocalPlayer : public Player void setMaxWeight(int value) { mMaxWeight = value; } -#ifdef TMWSERV_SUPPORT - int getAttributeBase(int num) const + int getAttributeBase(int num) { return mAttributeBase[num]; } - void setAttributeBase(int num, int value) - { mAttributeBase[num] = value; } + void setAttributeBase(int num, int value); - int getAttributeEffective(int num) const + int getAttributeEffective(int num) { return mAttributeEffective[num]; } - void setAttributeEffective(int num, int value) - { mAttributeEffective[num] = value; } + void setAttributeEffective(int num, int value); int getCharacterPoints() const { return mCharacterPoints; } - void setCharacterPoints(int n) - { mCharacterPoints = n; } + void setCharacterPoints(int n); int getCorrectionPoints() const { return mCorrectionPoints; } - void setCorrectionPoints(int n) - { mCorrectionPoints = n; } + void setCorrectionPoints(int n); - void setExperience(int skill, int current, int next); + int getSkillPoints() const + { return mSkillPoints; } - struct SkillInfo { - std::string name; - std::string icon; - }; + void setSkillPoints(int points); - static const SkillInfo& getSkillInfo(int skill); + void setExperience(int skill, int current, int next); std::pair<int, int> getExperience(int skill); -#endif bool mUpdateName; /** Whether or not the name settings have changed */ @@ -441,6 +372,9 @@ class LocalPlayer : public Player const std::auto_ptr<Equipment> mEquipment; + void addMessageToQueue(const std::string &message, + Palette::ColorType color = Palette::EXP_INFO); + protected: virtual void handleStatusEffect(StatusEffect *effect, int effectId); @@ -448,29 +382,29 @@ class LocalPlayer : public Player bool mInStorage; /**< Whether storage is currently accessible */ #ifdef EATHENA_SUPPORT - int mXp; /**< Experience points. */ int mTargetTime; /** How long the being has been targeted **/ #endif int mLastTarget; /** Time stamp of last targeting action, -1 if none. */ -#ifdef TMWSERV_SUPPORT // Character status: - std::vector<int> mAttributeBase; - std::vector<int> mAttributeEffective; - std::vector<int> mExpCurrent; - std::vector<int> mExpNext; + typedef std::map<int, int> IntMap; + IntMap mAttributeBase; + IntMap mAttributeEffective; + std::map<int, std::pair<int, int> > mSkillExp; int mCharacterPoints; int mCorrectionPoints; int mLevelProgress; std::map<int, Special> mSpecials; char mSpecialRechargeUpdateNeeded; -#endif int mLevel; + int mExp, mExpNeeded; + int mMp, mMaxMp; int mMoney; int mTotalWeight; int mMaxWeight; int mHp; int mMaxHp; + int mSkillPoints; int mGMLevel; @@ -512,10 +446,10 @@ class LocalPlayer : public Player /** Animated target cursors. */ SimpleAnimation *mTargetCursor[2][NUM_TC]; -#ifdef TMWSERV_SUPPORT - std::list<std::string> mExpMessages; /**< Queued exp messages*/ - int mExpMessageTime; -#endif + typedef std::pair<std::string, Palette::ColorType> MessagePair; + /** Queued exp messages*/ + std::list<MessagePair> mMessages; + int mMessageTime; }; extern LocalPlayer *player_node; diff --git a/src/main.cpp b/src/main.cpp index 3ea8aa2d..10145dfc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -143,9 +143,6 @@ namespace } listener; } -static const int defaultScreenWidth = 800; -static const int defaultScreenHeight = 600; - static const int defaultSfxVolume = 100; static const int defaultMusicVolume = 60; @@ -260,7 +257,7 @@ static void setUpdatesDir() else { logger->log("Error: Invalid update host: %s", updateHost.c_str()); - errorMessage = _("Invalid update host: ") + updateHost; + errorMessage = strprintf(_("Invalid update host: %s"), updateHost.c_str()); state = STATE_ERROR; } } @@ -335,10 +332,8 @@ static void initHomeDir(const Options &options) (errno != EEXIST)) #endif { - std::cout << homeDir - << _(" can't be created, but it doesn't exist! Exiting.") - << std::endl; - exit(1); + logger->error(strprintf(_("%s doesn't exist and can't be created! " + "Exiting."), homeDir.c_str())); } } @@ -389,8 +384,7 @@ static void initConfiguration(const Options &options) configFile = fopen(configPath.c_str(), "wt"); } if (configFile == NULL) { - std::cout << "Can't create " << configPath << ". " - << "Using Defaults." << std::endl; + logger->log("Can't create %s. Using defaults.", configPath.c_str()); } else { fclose(configFile); config.init(configPath); @@ -405,9 +399,8 @@ static void initEngine(const Options &options) // 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; - exit(1); + logger->error(strprintf("Could not initialize SDL: %s", + SDL_GetError())); } atexit(SDL_Quit); @@ -420,10 +413,8 @@ static void initEngine(const Options &options) ResourceManager *resman = ResourceManager::getInstance(); if (!resman->setWriteDir(homeDir)) { - std::cout << homeDir - << " couldn't be set as home directory! Exiting." - << std::endl; - exit(1); + logger->error(strprintf("%s couldn't be set as home directory! " + "Exiting.", homeDir.c_str())); } // Add the user's homedir to PhysicsFS search path @@ -489,10 +480,8 @@ static void initEngine(const Options &options) // Try to set the desired video mode if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel)) { - std::cerr << _("Couldn't set ") - << width << "x" << height << "x" << bpp << _(" video mode: ") - << SDL_GetError() << std::endl; - exit(1); + logger->error(strprintf("Couldn't set %dx%dx%d video mode: %s", + width, height, bpp, SDL_GetError())); } // Initialize for drawing @@ -1160,7 +1149,7 @@ int main(int argc, char *argv[]) case STATE_LOGIN_ERROR: logger->log("State: LOGIN ERROR"); - currentDialog = new OkDialog("Error ", errorMessage); + currentDialog = new OkDialog(_("Error"), errorMessage); currentDialog->addActionListener(&loginListener); currentDialog = NULL; // OkDialog deletes itself break; @@ -1214,8 +1203,8 @@ int main(int argc, char *argv[]) case STATE_CHANGEEMAIL: logger->log("State: CHANGE EMAIL"); - currentDialog = new OkDialog("Email Address change", - "Email Address changed successfully!"); + currentDialog = new OkDialog(_("Email Address Change"), + _("Email address changed successfully!")); currentDialog->addActionListener(&accountListener); currentDialog = NULL; // OkDialog deletes itself loginData.email = loginData.newEmail; @@ -1231,8 +1220,8 @@ int main(int argc, char *argv[]) case STATE_CHANGEPASSWORD: logger->log("State: CHANGE PASSWORD"); - currentDialog = new OkDialog("Password change", - "Password changed successfully!"); + currentDialog = new OkDialog(_("Password Change"), + _("Password changed successfully!")); currentDialog->addActionListener(&accountListener); currentDialog = NULL; // OkDialog deletes itself loginData.password = loginData.newPassword; @@ -1248,8 +1237,8 @@ int main(int argc, char *argv[]) case STATE_UNREGISTER: logger->log("State: UNREGISTER"); accountServerConnection->disconnect(); - currentDialog = new OkDialog("Unregister successful", - "Farewell, come back any time ...."); + currentDialog = new OkDialog(_("Unregister Successful"), + _("Farewell, come back any time...")); loginData.clear(); //The errorlistener sets the state to STATE_CHOOSE_SERVER currentDialog->addActionListener(&errorListener); @@ -1258,7 +1247,7 @@ int main(int argc, char *argv[]) case STATE_ACCOUNTCHANGE_ERROR: logger->log("State: ACCOUNT CHANGE ERROR"); - currentDialog = new OkDialog("Error ", errorMessage); + currentDialog = new OkDialog(_("Error"), errorMessage); currentDialog->addActionListener(&accountListener); currentDialog = NULL; // OkDialog deletes itself break; @@ -1266,7 +1255,7 @@ int main(int argc, char *argv[]) case STATE_ERROR: logger->log("State: ERROR"); - currentDialog = new OkDialog("Error", errorMessage); + currentDialog = new OkDialog(_("Error"), errorMessage); currentDialog->addActionListener(&errorListener); currentDialog = NULL; // OkDialog deletes itself gameServerConnection->disconnect(); @@ -1555,8 +1544,8 @@ int main(int argc, char *argv[]) case STATE_CHANGEPASSWORD: logger->log("State: CHANGE PASSWORD"); - currentDialog = new OkDialog("Password change", - "Password changed successfully!"); + currentDialog = new OkDialog(_("Password Change"), + _("Password changed successfully!")); currentDialog->addActionListener(&accountListener); currentDialog = NULL; // OkDialog deletes itself loginData.password = loginData.newPassword; @@ -1565,7 +1554,7 @@ int main(int argc, char *argv[]) case STATE_ACCOUNTCHANGE_ERROR: logger->log("State: ACCOUNT CHANGE ERROR"); - currentDialog = new OkDialog("Error ", errorMessage); + currentDialog = new OkDialog(_("Error"), errorMessage); currentDialog->addActionListener(&accountListener); currentDialog = NULL; // OkDialog deletes itself break; diff --git a/src/map.cpp b/src/map.cpp index 61fcdfe8..dbecda3d 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -218,11 +218,12 @@ void Map::initializeOverlays() const float speedX = getFloatProperty(name + "scrollX"); const float speedY = getFloatProperty(name + "scrollY"); const float parallax = getFloatProperty(name + "parallax"); + const bool keepRatio = getBoolProperty(name + "keepratio"); if (img) { mOverlays.push_back( - new AmbientOverlay(img, parallax, speedX, speedY)); + new AmbientOverlay(img, parallax, speedX, speedY, keepRatio)); // The AmbientOverlay takes control over the image. img->decRef(); @@ -448,7 +449,7 @@ bool Map::occupied(int x, int y) const const Being *being = *i; // job 45 is a portal, they don't collide - if (being->mX == x && being->mY == y && being->mJob != 45) + if (being->getTileX() == x && being->getTileY() == y && being->mJob != 45) return true; } @@ -490,50 +491,6 @@ const std::string &Map::getName() const return getProperty("mapname"); } -Path Map::findSimplePath(int startX, int startY, - int destX, int destY, - unsigned char walkmask) -{ - // Path to be built up (empty by default) - Path path; - int positionX = startX, positionY = startY; - int directionX, directionY; - // Checks our path up to 1 tiles, if a blocking tile is found - // We go to the last good tile, and break out of the loop - while(true) - { - directionX = destX - positionX; - directionY = destY - positionY; - - if (directionX > 0) - directionX = 1; - else if(directionX < 0) - directionX = -1; - - if (directionY > 0) - directionY = 1; - else if(directionY < 0) - directionY = -1; - - positionX += directionX; - positionY += directionY; - - if (getWalk(positionX, positionY, walkmask)) - { - path.push_back(Position(positionX, positionY)); - - if ((positionX == destX) && (positionY == destY)) - { - return path; - } - } - else - { - return path; - } - } -} - static int const basicCost = 100; Path Map::findPath(int startX, int startY, int destX, int destY, @@ -258,13 +258,6 @@ class Map : public Properties const std::string &getName() const; /** - * Find a simple path from one location to the next. - */ - Path findSimplePath(int startX, int startY, - int destX, int destY, - unsigned char walkmask); - - /** * Find a path from one location to the next. */ Path findPath(int startX, int startY, int destX, int destY, diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp index f149f15f..1d780a60 100644 --- a/src/net/ea/beinghandler.cpp +++ b/src/net/ea/beinghandler.cpp @@ -194,14 +194,15 @@ void BeingHandler::handleMessage(MessageIn &msg) Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); dstBeing->setAction(Being::STAND); - dstBeing->mX = srcX; - dstBeing->mY = srcY; + dstBeing->setTileCoords(srcX, srcY); dstBeing->setDestination(dstX, dstY); } else { Uint8 dir; - msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir); + Uint16 x, y; + msg.readCoordinates(x, y, dir); + dstBeing->setTileCoords(x, y); dstBeing->setDirection(dir); } @@ -234,8 +235,7 @@ void BeingHandler::handleMessage(MessageIn &msg) if (dstBeing) { dstBeing->setAction(Being::STAND); - dstBeing->mX = srcX; - dstBeing->mY = srcY; + dstBeing->setTileCoords(srcX, srcY); dstBeing->setDestination(dstX, dstY); } @@ -515,14 +515,15 @@ void BeingHandler::handleMessage(MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - dstBeing->mX = srcX; - dstBeing->mY = srcY; + dstBeing->setTileCoords(srcX, srcY); dstBeing->setDestination(dstX, dstY); } else { Uint8 dir; - msg.readCoordinates(dstBeing->mX, dstBeing->mY, dir); + Uint16 x, y; + msg.readCoordinates(x, y, dir); + dstBeing->setTileCoords(x, y); dstBeing->setDirection(dir); } @@ -577,8 +578,10 @@ void BeingHandler::handleMessage(MessageIn &msg) if (mSync || id != player_node->getId()) { dstBeing = beingManager->findBeing(id); if (dstBeing) { - dstBeing->mX = msg.readInt16(); - dstBeing->mY = msg.readInt16(); + Uint16 x, y; + x = msg.readInt16(); + y = msg.readInt16(); + dstBeing->setTileCoords(x, y); if (dstBeing->mAction == Being::WALK) { dstBeing->mFrame = 0; dstBeing->setAction(Being::STAND); diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp index 77bfaa50..6fae1864 100644 --- a/src/net/ea/charserverhandler.cpp +++ b/src/net/ea/charserverhandler.cpp @@ -61,18 +61,16 @@ CharServerHandler::CharServerHandler(): void CharServerHandler::handleMessage(MessageIn &msg) { - int slot, flags; + int slot; LocalPlayer *tempPlayer; logger->log("CharServerHandler: Packet ID: %x, Length: %d", msg.getId(), msg.getLength()); switch (msg.getId()) { - case 0x006b: + case SMSG_CHAR_LOGIN: msg.skip(2); // Length word - flags = msg.readInt32(); // Aethyra extensions flags - logger->log("Server flags are: %x", flags); - msg.skip(16); // Unused + msg.skip(20); // Unused // Derive number of characters from message length n_character = (msg.getLength() - 24) / 106; @@ -92,13 +90,13 @@ void CharServerHandler::handleMessage(MessageIn &msg) case SMSG_CHAR_LOGIN_ERROR: switch (msg.readInt8()) { case 0: - errorMessage = _("Access denied"); + errorMessage = _("Access denied."); break; case 1: - errorMessage = _("Cannot use this ID"); + errorMessage = _("Cannot use this ID."); break; default: - errorMessage = _("Unknown failure to select character"); + errorMessage = _("Unknown failure to select character."); break; } mCharInfo->unlock(); @@ -169,14 +167,15 @@ void CharServerHandler::handleMessage(MessageIn &msg) LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot) { - LocalPlayer *tempPlayer = new LocalPlayer(mLoginData->account_ID, 0, NULL); + LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0, NULL); tempPlayer->setGender(mLoginData->sex); - tempPlayer->mCharId = msg.readInt32(); - tempPlayer->setXp(msg.readInt32()); + tempPlayer->setExp(msg.readInt32()); tempPlayer->setMoney(msg.readInt32()); - tempPlayer->mJobXp = msg.readInt32(); - tempPlayer->mJobLevel = msg.readInt32(); + tempPlayer->setExperience(JOB, msg.readInt32(), 1); + int temp = msg.readInt32(); + tempPlayer->setAttributeBase(JOB, temp); + tempPlayer->setAttributeEffective(JOB, temp); tempPlayer->setSprite(Being::SHOE_SPRITE, msg.readInt16()); tempPlayer->setSprite(Being::GLOVES_SPRITE, msg.readInt16()); tempPlayer->setSprite(Being::CAPE_SPRITE, msg.readInt16()); @@ -187,8 +186,8 @@ LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot) msg.skip(2); // unknown tempPlayer->setHp(msg.readInt16()); tempPlayer->setMaxHp(msg.readInt16()); - tempPlayer->mMp = msg.readInt16(); - tempPlayer->mMaxMp = msg.readInt16(); + tempPlayer->setMP(msg.readInt16()); + tempPlayer->setMaxMP(msg.readInt16()); msg.readInt16(); // speed msg.readInt16(); // class int hairStyle = msg.readInt16(); @@ -205,7 +204,7 @@ LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot) tempPlayer->setSprite(Being::MISC2_SPRITE, msg.readInt16()); tempPlayer->setName(msg.readString(24)); for (int i = 0; i < 6; i++) { - tempPlayer->mAttr[i] = msg.readInt8(); + tempPlayer->setAttributeBase(i + STR, msg.readInt8()); } slot = msg.readInt8(); // character slot msg.readInt8(); // unknown @@ -272,7 +271,7 @@ void CharServerHandler::newCharacter(const std::string &name, int slot, void CharServerHandler::deleteCharacter(int slot, LocalPlayer* character) { MessageOut outMsg(CMSG_CHAR_DELETE); - outMsg.writeInt32(character->mCharId); + outMsg.writeInt32(character->getId()); outMsg.writeString("a@a.com", 40); } diff --git a/src/net/ea/chathandler.cpp b/src/net/ea/chathandler.cpp index 49f83e67..65f1db3c 100644 --- a/src/net/ea/chathandler.cpp +++ b/src/net/ea/chathandler.cpp @@ -166,7 +166,7 @@ void ChatHandler::handleMessage(MessageIn &msg) case SMSG_MVP: // Display MVP player msg.readInt32(); // id - localChatTab->chatLog("MVP player", BY_SERVER); + localChatTab->chatLog(_("MVP player."), BY_SERVER); break; } } diff --git a/src/net/ea/equipmenthandler.cpp b/src/net/ea/equipmenthandler.cpp index 0153b5da..3520bca5 100644 --- a/src/net/ea/equipmenthandler.cpp +++ b/src/net/ea/equipmenthandler.cpp @@ -35,10 +35,112 @@ #include "utils/gettext.h" +const Equipment::EquipmentSlots EQUIP_POINTS[Equipment::EQUIP_VECTOREND] = { + Equipment::EQUIP_LEGS_SLOT, + Equipment::EQUIP_FIGHT1_SLOT, + Equipment::EQUIP_GLOVES_SLOT, + Equipment::EQUIP_RING2_SLOT, + Equipment::EQUIP_RING1_SLOT, + Equipment::EQUIP_FIGHT2_SLOT, + Equipment::EQUIP_FEET_SLOT, + Equipment::EQUIP_NECK_SLOT, + Equipment::EQUIP_HEAD_SLOT, + Equipment::EQUIP_TORSO_SLOT, + Equipment::EQUIP_PROJECTILE_SLOT}; + +Item *equips[Equipment::EQUIP_VECTOREND]; + namespace EAthena { enum { debugEquipment = 1 }; +void setEquipment(int eAthenaSlot, int index, bool equiped) +{ + if (!eAthenaSlot) + return; + + Item *item = player_node->getInventory()->getItem(index); + + if (!item) + return; + + int position = 0; + + if (eAthenaSlot & 0x8000) { // Arrows + position = Equipment::EQUIP_PROJECTILE_SLOT; + } + else + { + /* + * An item may occupy more than 1 slot. If so, it's + * only shown as equipped on the *first* slot. + */ + int mask = 1; + while (!(eAthenaSlot & mask)) + { + mask <<= 1; + position++; + } + + position = EQUIP_POINTS[position]; + } + + if (equips[position]) + equips[position]->setEquipped(false); + + if (equiped && item) + { + equips[position] = item; + item->setEquipped(true); + player_node->mEquipment->setEquipment(position, item->getId(), item->getQuantity()); + + if (debugEquipment) + { + logger->log("Equipping: %i %i at position %i", + index, eAthenaSlot, position); + } + } + else + { + equips[position] = NULL; + player_node->mEquipment->setEquipment(position, -1); + + if (debugEquipment) + { + logger->log("Unequipping: %i %i at position %i", + index, eAthenaSlot, position); + } + } +} + +void clearEquipment() +{ + for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++) + { + if (equips[i]) + { + equips[i]->setEquipped(false); + player_node->mEquipment->setEquipment(i, -1); + } + + equips[i] = NULL; + } +} + +Item *getRealEquipedItem(const Item *equipped) +{ + if (!equipped) + return NULL; + + for (int i = 0; i < Equipment::EQUIP_VECTOREND; i++) + { + if (equips[i] && equipped->getId() == equips[i]->getId()) + return equips[i]; + } + + return NULL; +} + EquipmentHandler::EquipmentHandler() { static const Uint16 _messages[] = { @@ -50,6 +152,7 @@ EquipmentHandler::EquipmentHandler() 0 }; handledMessages = _messages; + memset(equips, 0, sizeof(equips)); } void EquipmentHandler::handleMessage(MessageIn &msg) @@ -57,8 +160,6 @@ void EquipmentHandler::handleMessage(MessageIn &msg) int itemCount; int index, equipPoint, itemId; int type; - int mask, position; - Item *item; Inventory *inventory = player_node->getInventory(); switch (msg.getId()) @@ -79,25 +180,9 @@ void EquipmentHandler::handleMessage(MessageIn &msg) msg.readInt8(); // refine msg.skip(8); // card - if (debugEquipment) - { - logger->log("Index: %d, ID: %d", index, itemId); - } - inventory->setItem(index, itemId, 1, true); - if (equipPoint) - { - mask = 1; - position = 0; - while (!(equipPoint & mask)) - { - mask <<= 1; - position++; - } - item = inventory->getItem(index); - player_node->mEquipment->setEquipment(position, index); - } + setEquipment(equipPoint, index, true); } break; @@ -112,35 +197,7 @@ void EquipmentHandler::handleMessage(MessageIn &msg) break; } - // No point in searching when no point given - if (!equipPoint) - break; - - /* - * An item may occupy more than 1 slot. If so, it's - * only shown as equipped on the *first* slot. - */ - mask = 1; - position = 0; - while (!(equipPoint & mask)) { - mask <<= 1; - position++; - } - - if (debugEquipment) - { - logger->log("Equipping: %i %i %i at position %i", - index, equipPoint, type, position); - } - - item = inventory->getItem(player_node->mEquipment->getEquipment(position)); - - // Unequip any existing equipped item in this position - if (item) - item->setEquipped(false); - - item = inventory->getItem(index); - player_node->mEquipment->setEquipment(position, index); + setEquipment(equipPoint, index, true); break; case SMSG_PLAYER_UNEQUIP: @@ -153,36 +210,7 @@ void EquipmentHandler::handleMessage(MessageIn &msg) break; } - if (!equipPoint) { - // No point given, no point in searching - break; - } - - mask = 1; - position = 0; - while (!(equipPoint & mask)) { - mask <<= 1; - position++; - } - - item = inventory->getItem(index); - if (!item) - break; - - item->setEquipped(false); - - if (equipPoint & 0x8000) { // Arrows - player_node->mEquipment->setArrows(-1); - } - else { - player_node->mEquipment->removeEquipment(position); - } - - if (debugEquipment) - { - logger->log("Unequipping: %i %i(%i) %i", - index, equipPoint, type, position); - } + setEquipment(equipPoint, index, false); break; case SMSG_PLAYER_ATTACK_RANGE: @@ -197,13 +225,8 @@ void EquipmentHandler::handleMessage(MessageIn &msg) index -= INVENTORY_OFFSET; - item = inventory->getItem(index); - - if (item) { - item->setEquipped(true); - player_node->mEquipment->setArrows(index); - logger->log("Arrows equipped: %i", index); - } + logger->log("Arrows equipped: %i", index); + setEquipment(0x8000, index, true); break; } } diff --git a/src/net/ea/equipmenthandler.h b/src/net/ea/equipmenthandler.h index 852be3c9..47c2f803 100644 --- a/src/net/ea/equipmenthandler.h +++ b/src/net/ea/equipmenthandler.h @@ -24,8 +24,14 @@ #include "net/messagehandler.h" +class Item; + namespace EAthena { +void setEquipment(int eAthenaSlot, int index, bool equiped); +void clearEquipment(); +Item *getRealEquipedItem(const Item *equipped); + class EquipmentHandler : public MessageHandler { public: diff --git a/src/net/ea/generalhandler.cpp b/src/net/ea/generalhandler.cpp index 404bff69..1d500d62 100644 --- a/src/net/ea/generalhandler.cpp +++ b/src/net/ea/generalhandler.cpp @@ -19,10 +19,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "gui/inventorywindow.h" - #include "net/ea/generalhandler.h" +#include "gui/inventorywindow.h" +#include "gui/skilldialog.h" +#include "gui/statuswindow.h" + #include "net/ea/network.h" #include "net/ea/protocol.h" @@ -41,7 +43,7 @@ #include "net/ea/playerhandler.h" #include "net/ea/partyhandler.h" #include "net/ea/tradehandler.h" -#include "net/ea/skillhandler.h" +#include "net/ea/specialhandler.h" #include "net/ea/gui/partytab.h" @@ -77,7 +79,7 @@ GeneralHandler::GeneralHandler(): mNpcHandler(new NpcHandler), mPartyHandler(new PartyHandler), mPlayerHandler(new PlayerHandler), - mSkillHandler(new SkillHandler), + mSpecialHandler(new SpecialHandler), mTradeHandler(new TradeHandler) { static const Uint16 _messages[] = { @@ -115,26 +117,26 @@ void GeneralHandler::handleMessage(MessageIn &msg) switch (code) { case 0: - errorMessage = _("Authentication failed"); + errorMessage = _("Authentication failed."); break; case 1: - errorMessage = _("No servers available"); + errorMessage = _("No servers available."); break; case 2: if (state == STATE_GAME) errorMessage = _("Someone else is trying to use this " - "account"); + "account."); else - errorMessage = _("This account is already logged in"); + errorMessage = _("This account is already logged in."); break; case 3: - errorMessage = _("Speed hack detected"); + errorMessage = _("Speed hack detected."); break; case 8: - errorMessage = _("Duplicated login"); + errorMessage = _("Duplicated login."); break; default: - errorMessage = _("Unknown connection error"); + errorMessage = _("Unknown connection error."); break; } state = STATE_ERROR; @@ -157,7 +159,7 @@ void GeneralHandler::load() mNetwork->registerHandler(mMapHandler.get()); mNetwork->registerHandler(mNpcHandler.get()); mNetwork->registerHandler(mPlayerHandler.get()); - mNetwork->registerHandler(mSkillHandler.get()); + mNetwork->registerHandler(mSpecialHandler.get()); mNetwork->registerHandler(mTradeHandler.get()); mNetwork->registerHandler(mPartyHandler.get()); } @@ -201,6 +203,22 @@ void GeneralHandler::guiWindowsLoaded() { partyTab = new PartyTab; inventoryWindow->setSplitAllowed(false); + skillDialog->loadSkills("ea-skills.xml"); + + statusWindow->addAttribute(STR, _("Strength"), true); + statusWindow->addAttribute(AGI, _("Agility"), true); + statusWindow->addAttribute(VIT, _("Vitality"), true); + statusWindow->addAttribute(INT, _("Intelligence"), true); + statusWindow->addAttribute(DEX, _("Dexterity"), true); + statusWindow->addAttribute(LUK, _("Luck"), true); + + statusWindow->addAttribute(ATK, _("Attack"), false); + statusWindow->addAttribute(DEF, _("Defense"), false); + statusWindow->addAttribute(MATK, _("M.Attack"), false); + statusWindow->addAttribute(MDEF, _("M.Defense"), false); + statusWindow->addAttribute(HIT, _("% Accuracy"), false); + statusWindow->addAttribute(FLEE, _("% Evade"), false); + statusWindow->addAttribute(CRIT, _("% Critical"), false); } void GeneralHandler::guiWindowsUnloaded() diff --git a/src/net/ea/generalhandler.h b/src/net/ea/generalhandler.h index ebbc84ca..98364e5d 100644 --- a/src/net/ea/generalhandler.h +++ b/src/net/ea/generalhandler.h @@ -66,7 +66,7 @@ class GeneralHandler : public MessageHandler, public Net::GeneralHandler MessageHandlerPtr mNpcHandler; MessageHandlerPtr mPartyHandler; MessageHandlerPtr mPlayerHandler; - MessageHandlerPtr mSkillHandler; + MessageHandlerPtr mSpecialHandler; MessageHandlerPtr mTradeHandler; }; diff --git a/src/net/ea/inventoryhandler.cpp b/src/net/ea/inventoryhandler.cpp index c1f04661..b6e91609 100644 --- a/src/net/ea/inventoryhandler.cpp +++ b/src/net/ea/inventoryhandler.cpp @@ -21,6 +21,7 @@ #include "net/ea/inventoryhandler.h" +#include "net/ea/equipmenthandler.h" #include "net/ea/protocol.h" #include "net/messagein.h" @@ -86,6 +87,7 @@ void InventoryHandler::handleMessage(MessageIn &msg) if (msg.getId() == SMSG_PLAYER_INVENTORY) { // Clear inventory - this will be a complete refresh + clearEquipment(); inventory->clear(); } else @@ -178,42 +180,25 @@ void InventoryHandler::handleMessage(MessageIn &msg) equipType = msg.readInt16(); itemType = msg.readInt8(); - if (msg.readInt8() > 0) - { - if (config.getValue("showpickupchat", 1)) - { - localChatTab->chatLog(_("Unable to pick up item."), - BY_SERVER); - } - } - else { const ItemInfo &itemInfo = ItemDB::get(itemId); - const std::string amountStr = - // TRANSLATORS: Used as in "You picked up a ...", when - // picking up only one item. - (amount > 1) ? toString(amount) : _("a"); - if (config.getValue("showpickupchat", 1)) + if (msg.readInt8() > 0) { - localChatTab->chatLog(strprintf(_("You picked up %s [@@%d|%s@@]."), - amountStr.c_str(), itemInfo.getId(), itemInfo.getName().c_str()), - BY_SERVER); + player_node->pickedUp(itemInfo, 0); } - - if (config.getValue("showpickupparticle", 0)) + else { - player_node->pickedUp(itemInfo.getName()); - } + player_node->pickedUp(itemInfo, amount); + + Item *item = inventory->getItem(index); + + if (item && item->getId() == itemId) + amount += inventory->getItem(index)->getQuantity(); - if (Item *item = inventory->getItem(index)) { - item->setId(itemId); - item->increaseQuantity(amount); - } else { inventory->setItem(index, itemId, amount, equipType != 0); } - } - break; + } break; case SMSG_PLAYER_INVENTORY_REMOVE: index = msg.readInt16() - INVENTORY_OFFSET; @@ -319,11 +304,13 @@ void InventoryHandler::equipItem(const Item *item) void InventoryHandler::unequipItem(const Item *item) { - if (!item) + const Item *real_item = item->isEquipped() ? item : getRealEquipedItem(item); + + if (!real_item) return; MessageOut outMsg(CMSG_PLAYER_UNEQUIP); - outMsg.writeInt16(item->getInvIndex() + INVENTORY_OFFSET); + outMsg.writeInt16(real_item->getInvIndex() + INVENTORY_OFFSET); } void InventoryHandler::useItem(const Item *item) diff --git a/src/net/ea/loginhandler.cpp b/src/net/ea/loginhandler.cpp index 54e31cf3..8e7187c0 100644 --- a/src/net/ea/loginhandler.cpp +++ b/src/net/ea/loginhandler.cpp @@ -76,13 +76,13 @@ void LoginHandler::handleMessage(MessageIn &msg) errorMessage = _("Account was not found. Please re-login."); break; case 2: - errorMessage = _("Old password incorrect"); + errorMessage = _("Old password incorrect."); break; case 3: - errorMessage = _("New password too short"); + errorMessage = _("New password too short."); break; default: - errorMessage = _("Unknown error"); + errorMessage = _("Unknown error."); break; } state = STATE_ACCOUNTCHANGE_ERROR; @@ -96,7 +96,7 @@ void LoginHandler::handleMessage(MessageIn &msg) len = msg.readInt16() - 4; mUpdateHost = msg.readString(len); - logger->log("Received update host \"%s\" from login server", + logger->log("Received update host \"%s\" from login server.", mUpdateHost.c_str()); break; @@ -139,21 +139,21 @@ void LoginHandler::handleMessage(MessageIn &msg) switch (code) { case 0: - errorMessage = _("Unregistered ID"); + errorMessage = _("Unregistered ID."); break; case 1: - errorMessage = _("Wrong password"); + errorMessage = _("Wrong password."); break; case 2: - errorMessage = _("Account expired"); + errorMessage = _("Account expired."); break; case 3: - errorMessage = _("Rejected from server"); + errorMessage = _("Rejected from server."); break; case 4: errorMessage = _("You have been permanently banned from " - "the game. Please contact the GM Team."); + "the game. Please contact the GM team."); break; case 6: errorMessage = strprintf(_("You have been temporarily " @@ -163,10 +163,10 @@ void LoginHandler::handleMessage(MessageIn &msg) msg.readString(20).c_str()); break; case 9: - errorMessage = _("This user name is already taken"); + errorMessage = _("This user name is already taken."); break; default: - errorMessage = _("Unknown error"); + errorMessage = _("Unknown error."); break; } state = STATE_ERROR; diff --git a/src/net/ea/maphandler.cpp b/src/net/ea/maphandler.cpp index 6f8a9827..c3c9437c 100644 --- a/src/net/ea/maphandler.cpp +++ b/src/net/ea/maphandler.cpp @@ -61,14 +61,17 @@ void MapHandler::handleMessage(MessageIn &msg) switch (msg.getId()) { case SMSG_MAP_LOGIN_SUCCESS: + { + Uint16 x, y; msg.readInt32(); // server tick - msg.readCoordinates(player_node->mX, player_node->mY, direction); + msg.readCoordinates(x, y, direction); msg.skip(2); // unknown logger->log("Protocol: Player start position: (%d, %d), Direction: %d", - player_node->mX, player_node->mY, direction); + x, y, direction); state = STATE_GAME; + player_node->setTileCoords(x, y); game = new Game; - break; + } break; case SMSG_SERVER_PING: // We ignore this for now @@ -76,22 +79,27 @@ void MapHandler::handleMessage(MessageIn &msg) break; case SMSG_WHO_ANSWER: - localChatTab->chatLog("Online users: " + toString(msg.readInt32()), - BY_SERVER); + localChatTab->chatLog(strprintf(_("Online users: %d"), + msg.readInt32()), BY_SERVER); break; } } +#include <fstream> + void MapHandler::connect(LoginData *loginData) { // Send login infos MessageOut outMsg(CMSG_MAP_SERVER_CONNECT); outMsg.writeInt32(loginData->account_ID); - outMsg.writeInt32(player_node->mCharId); + outMsg.writeInt32(player_node->getId()); outMsg.writeInt32(loginData->session_ID1); outMsg.writeInt32(loginData->session_ID2); outMsg.writeInt8((loginData->sex == GENDER_MALE) ? 1 : 0); + // Change the player's ID to the account ID to match what eAthena uses + player_node->setId(loginData->account_ID); + // We get 4 useless bytes before the real answer comes in (what are these?) mNetwork->skip(4); } diff --git a/src/net/ea/network.cpp b/src/net/ea/network.cpp index 956d7877..c6bc712c 100644 --- a/src/net/ea/network.cpp +++ b/src/net/ea/network.cpp @@ -318,9 +318,9 @@ bool Network::realConnect() if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1) { - std::string error = "Unable to resolve host \"" + mAddress + "\""; - setError(error); - logger->log("SDLNet_ResolveHost: %s", error.c_str()); + std::string errorMessage = "Unable to resolve host \"" + mAddress + "\""; + setError(errorMessage); + logger->log("SDLNet_ResolveHost: %s", errorMessage.c_str()); return false; } diff --git a/src/net/ea/partyhandler.cpp b/src/net/ea/partyhandler.cpp index 5e7f43c4..a4a84b07 100644 --- a/src/net/ea/partyhandler.cpp +++ b/src/net/ea/partyhandler.cpp @@ -230,6 +230,7 @@ void PartyHandler::handleMessage(MessageIn &msg) if (id == player_node->getId()) { partyWindow->clearMembers(); + partyWindow->clearPartyName(); partyWindow->setVisible(false); partyTab->chatLog(_("You have left the party."), BY_SERVER); } diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp index 58167339..3e379d82 100644 --- a/src/net/ea/playerhandler.cpp +++ b/src/net/ea/playerhandler.cpp @@ -37,7 +37,7 @@ #include "gui/gui.h" #include "gui/okdialog.h" #include "gui/sell.h" -#include "gui/skill.h" +#include "gui/statuswindow.h" #include "gui/storagewindow.h" #include "gui/viewport.h" @@ -54,6 +54,9 @@ OkDialog *deathNotice = NULL; // everything beyond will reset the port hard. static const int MAP_TELEPORT_SCROLL_DISTANCE = 8; +#define ATTR_BONUS(atr) \ +(player_node->getAttributeEffective(atr) - player_node->getAttributeBase(atr)) + // TODO Move somewhere else namespace { @@ -197,17 +200,16 @@ void PlayerHandler::handleMessage(MessageIn &msg) /* Scroll if neccessary */ if (!nearby - || (abs(x - player_node->mX) > MAP_TELEPORT_SCROLL_DISTANCE) - || (abs(y - player_node->mY) > MAP_TELEPORT_SCROLL_DISTANCE)) + || (abs(x - player_node->getTileX()) > MAP_TELEPORT_SCROLL_DISTANCE) + || (abs(y - player_node->getTileY()) > MAP_TELEPORT_SCROLL_DISTANCE)) { - scrollOffsetX = (x - player_node->mX) * 32; - scrollOffsetY = (y - player_node->mY) * 32; + scrollOffsetX = (x - player_node->getTileX()) * 32; + scrollOffsetY = (y - player_node->getTileY()) * 32; } player_node->setAction(Being::STAND); player_node->mFrame = 0; - player_node->mX = x; - player_node->mY = y; + player_node->setTileCoords(x, y); logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX, (int) scrollOffsetY); @@ -224,18 +226,14 @@ void PlayerHandler::handleMessage(MessageIn &msg) switch (type) { case 0x0000: player_node->setWalkSpeed(value); break; + case 0x0004: break; // manner case 0x0005: player_node->setHp(value); break; case 0x0006: player_node->setMaxHp(value); break; - case 0x0007: player_node->mMp = value; break; - case 0x0008: player_node->mMaxMp = value; break; - case 0x0009: - player_node->mStatsPointsToAttribute = value; - break; + case 0x0007: player_node->setMP(value); break; + case 0x0008: player_node->setMaxMP(value); break; + case 0x0009: player_node->setCharacterPoints(value); break; case 0x000b: player_node->setLevel(value); break; - case 0x000c: - player_node->mSkillPoint = value; - skillDialog->update(); - break; + case 0x000c: player_node->setSkillPoints(value); break; case 0x0018: if (value >= player_node->getMaxWeight() / 2 && player_node->getTotalWeight() < @@ -251,15 +249,48 @@ void PlayerHandler::handleMessage(MessageIn &msg) player_node->setTotalWeight(value); break; case 0x0019: player_node->setMaxWeight(value); break; - case 0x0029: player_node->ATK = value; break; - case 0x002b: player_node->MATK = value; break; - case 0x002d: player_node->DEF = value; break; - case 0x002e: player_node->DEF_BONUS = value; break; - case 0x002f: player_node->MDEF = value; break; - case 0x0031: player_node->HIT = value; break; - case 0x0032: player_node->FLEE = value; break; + + case 0x0029: player_node->setAttributeEffective(ATK, value + + ATTR_BONUS(ATK)); + player_node->setAttributeBase(ATK, value); + break; + case 0x002a: value += player_node->getAttributeBase(ATK); + player_node->setAttributeEffective(ATK, value); break; + + case 0x002b: player_node->setAttributeEffective(MATK, value + + ATTR_BONUS(MATK)); + player_node->setAttributeBase(MATK, value); + statusWindow->update(StatusWindow::MP); break; + case 0x002c: value += player_node->getAttributeBase(MATK); + player_node->setAttributeEffective(MATK, value); + statusWindow->update(StatusWindow::MP); break; + case 0x002d: player_node->setAttributeEffective(DEF, value + + ATTR_BONUS(DEF)); + player_node->setAttributeBase(DEF, value); break; + case 0x002e: value += player_node->getAttributeBase(DEF); + player_node->setAttributeEffective(DEF, value); break; + + case 0x002f: player_node->setAttributeEffective(MDEF, value + + ATTR_BONUS(MDEF)); + player_node->setAttributeBase(MDEF, value); break; + case 0x0030: value += player_node->getAttributeBase(MDEF); + player_node->setAttributeEffective(MDEF, value); break; + + case 0x0031: player_node->setAttributeBase(HIT, value); + player_node->setAttributeEffective(HIT, value); break; + + case 0x0032: player_node->setAttributeEffective(FLEE, value + + ATTR_BONUS(FLEE)); + player_node->setAttributeBase(FLEE, value); break; + case 0x0033: value += player_node->getAttributeBase(FLEE); + player_node->setAttributeEffective(FLEE, value); break; + + case 0x0034: player_node->setAttributeBase(CRIT, value); + player_node->setAttributeEffective(CRIT, value); break; + case 0x0035: player_node->mAttackSpeed = value; break; - case 0x0037: player_node->mJobLevel = value; break; + case 0x0037: player_node->setAttributeBase(JOB, value); + player_node->setAttributeEffective(JOB, value); break; case 500: player_node->setGMLevel(value); break; } @@ -276,54 +307,45 @@ void PlayerHandler::handleMessage(MessageIn &msg) case SMSG_PLAYER_STAT_UPDATE_2: switch (msg.readInt16()) { case 0x0001: - player_node->setXp(msg.readInt32()); + player_node->setExp(msg.readInt32()); break; case 0x0002: - player_node->mJobXp = msg.readInt32(); + player_node->setExperience(JOB, msg.readInt32(), + player_node->getExperience(JOB).second); break; case 0x0014: { int curGp = player_node->getMoney(); player_node->setMoney(msg.readInt32()); if (player_node->getMoney() > curGp) - localChatTab->chatLog(_("You picked up ") + + localChatTab->chatLog(strprintf(_("You picked up " + "%s."), Units::formatCurrency(player_node->getMoney() - - curGp), BY_SERVER); + - curGp).c_str()), BY_SERVER); } break; case 0x0016: - player_node->mXpForNextLevel = msg.readInt32(); + player_node->setExpNeeded(msg.readInt32()); break; case 0x0017: - player_node->mJobXpForNextLevel = msg.readInt32(); + player_node->setExperience(JOB, + player_node->getExperience(JOB).first, + msg.readInt32()); break; } break; - case SMSG_PLAYER_STAT_UPDATE_3: + case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute { int type = msg.readInt32(); int base = msg.readInt32(); int bonus = msg.readInt32(); - int total = base + bonus; - switch (type) { - case 0x000d: player_node->mAttr[LocalPlayer::STR] = total; - break; - case 0x000e: player_node->mAttr[LocalPlayer::AGI] = total; - break; - case 0x000f: player_node->mAttr[LocalPlayer::VIT] = total; - break; - case 0x0010: player_node->mAttr[LocalPlayer::INT] = total; - break; - case 0x0011: player_node->mAttr[LocalPlayer::DEX] = total; - break; - case 0x0012: player_node->mAttr[LocalPlayer::LUK] = total; - break; - } + player_node->setAttributeBase(type, base); + player_node->setAttributeEffective(type, base + bonus); } break; - case SMSG_PLAYER_STAT_UPDATE_4: + case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack { int type = msg.readInt16(); int fail = msg.readInt8(); @@ -332,72 +354,105 @@ void PlayerHandler::handleMessage(MessageIn &msg) if (fail != 1) break; - switch (type) { - case 0x000d: player_node->mAttr[LocalPlayer::STR] = value; - break; - case 0x000e: player_node->mAttr[LocalPlayer::AGI] = value; - break; - case 0x000f: player_node->mAttr[LocalPlayer::VIT] = value; - break; - case 0x0010: player_node->mAttr[LocalPlayer::INT] = value; - break; - case 0x0011: player_node->mAttr[LocalPlayer::DEX] = value; - break; - case 0x0012: player_node->mAttr[LocalPlayer::LUK] = value; - break; - } + int bonus = ATTR_BONUS(type); + + player_node->setAttributeBase(type, value); + player_node->setAttributeEffective(type, value + bonus); } break; // Updates stats and status points case SMSG_PLAYER_STAT_UPDATE_5: - player_node->mStatsPointsToAttribute = msg.readInt16(); - player_node->mAttr[LocalPlayer::STR] = msg.readInt8(); - player_node->mAttrUp[LocalPlayer::STR] = msg.readInt8(); - player_node->mAttr[LocalPlayer::AGI] = msg.readInt8(); - player_node->mAttrUp[LocalPlayer::AGI] = msg.readInt8(); - player_node->mAttr[LocalPlayer::VIT] = msg.readInt8(); - player_node->mAttrUp[LocalPlayer::VIT] = msg.readInt8(); - player_node->mAttr[LocalPlayer::INT] = msg.readInt8(); - player_node->mAttrUp[LocalPlayer::INT] = msg.readInt8(); - player_node->mAttr[LocalPlayer::DEX] = msg.readInt8(); - player_node->mAttrUp[LocalPlayer::DEX] = msg.readInt8(); - player_node->mAttr[LocalPlayer::LUK] = msg.readInt8(); - player_node->mAttrUp[LocalPlayer::LUK] = msg.readInt8(); - player_node->ATK = msg.readInt16(); // ATK - player_node->ATK_BONUS = msg.readInt16(); // ATK bonus - player_node->MATK = msg.readInt16(); // MATK max - player_node->MATK_BONUS = msg.readInt16(); // MATK min - player_node->DEF = msg.readInt16(); // DEF - player_node->DEF_BONUS = msg.readInt16(); // DEF bonus - player_node->MDEF = msg.readInt16(); // MDEF - player_node->MDEF_BONUS = msg.readInt16(); // MDEF bonus - player_node->HIT = msg.readInt16(); // HIT - player_node->FLEE = msg.readInt16(); // FLEE - player_node->FLEE_BONUS = msg.readInt16(); // FLEE bonus - msg.readInt16(); // critical - msg.readInt16(); // unknown + player_node->setCharacterPoints(msg.readInt16()); + + { + int val = msg.readInt8(); + player_node->setAttributeEffective(STR, val + ATTR_BONUS(STR)); + player_node->setAttributeBase(STR, val); + statusWindow->setPointsNeeded(STR, msg.readInt8()); + + val = msg.readInt8(); + player_node->setAttributeEffective(AGI, val + ATTR_BONUS(AGI)); + player_node->setAttributeBase(AGI, val); + statusWindow->setPointsNeeded(AGI, msg.readInt8()); + + val = msg.readInt8(); + player_node->setAttributeEffective(VIT, val + ATTR_BONUS(VIT)); + player_node->setAttributeBase(VIT, val); + statusWindow->setPointsNeeded(VIT, msg.readInt8()); + + val = msg.readInt8(); + player_node->setAttributeEffective(INT, val + ATTR_BONUS(INT)); + player_node->setAttributeBase(INT, val); + statusWindow->setPointsNeeded(INT, msg.readInt8()); + + val = msg.readInt8(); + player_node->setAttributeEffective(DEX, val + ATTR_BONUS(DEX)); + player_node->setAttributeBase(DEX, val); + statusWindow->setPointsNeeded(DEX, msg.readInt8()); + + val = msg.readInt8(); + player_node->setAttributeEffective(LUK, val + ATTR_BONUS(LUK)); + player_node->setAttributeBase(LUK, val); + statusWindow->setPointsNeeded(LUK, msg.readInt8()); + + val = msg.readInt16(); // ATK + player_node->setAttributeBase(ATK, val); + val += msg.readInt16(); // ATK bonus + player_node->setAttributeEffective(ATK, val); + + val = msg.readInt16(); // MATK + player_node->setAttributeBase(MATK, val); + val += msg.readInt16(); // MATK bonus + player_node->setAttributeEffective(MATK, val); + statusWindow->update(StatusWindow::MP); + + val = msg.readInt16(); // DEF + player_node->setAttributeBase(DEF, val); + val += msg.readInt16(); // DEF bonus + player_node->setAttributeEffective(DEF, val); + + val = msg.readInt16(); // MDEF + player_node->setAttributeBase(MDEF, val); + val += msg.readInt16(); // MDEF bonus + player_node->setAttributeEffective(MDEF, val); + + val = msg.readInt16(); // HIT + player_node->setAttributeBase(ATK, val); + player_node->setAttributeEffective(ATK, val); + + val = msg.readInt16(); // FLEE + player_node->setAttributeBase(FLEE, val); + val += msg.readInt16(); // FLEE bonus + player_node->setAttributeEffective(FLEE, val); + + val = msg.readInt16(); + player_node->setAttributeBase(CRIT, val); + player_node->setAttributeEffective(CRIT, val); + } + + msg.readInt16(); // manner break; case SMSG_PLAYER_STAT_UPDATE_6: switch (msg.readInt16()) { case 0x0020: - player_node->mAttrUp[LocalPlayer::STR] = msg.readInt8(); + statusWindow->setPointsNeeded(STR, msg.readInt8()); break; case 0x0021: - player_node->mAttrUp[LocalPlayer::AGI] = msg.readInt8(); + statusWindow->setPointsNeeded(AGI, msg.readInt8()); break; case 0x0022: - player_node->mAttrUp[LocalPlayer::VIT] = msg.readInt8(); + statusWindow->setPointsNeeded(VIT, msg.readInt8()); break; case 0x0023: - player_node->mAttrUp[LocalPlayer::INT] = msg.readInt8(); + statusWindow->setPointsNeeded(INT, msg.readInt8()); break; case 0x0024: - player_node->mAttrUp[LocalPlayer::DEX] = msg.readInt8(); + statusWindow->setPointsNeeded(DEX, msg.readInt8()); break; case 0x0025: - player_node->mAttrUp[LocalPlayer::LUK] = msg.readInt8(); + statusWindow->setPointsNeeded(LUK, msg.readInt8()); break; } break; @@ -433,44 +488,30 @@ void PlayerHandler::emote(int emoteId) outMsg.writeInt8(emoteId); } -void PlayerHandler::increaseStat(LocalPlayer::Attribute attr) +void PlayerHandler::increaseAttribute(size_t attr) { - MessageOut outMsg(CMSG_STAT_UPDATE_REQUEST); - - switch (attr) + if (attr >= STR && attr <= LUK) { - case LocalPlayer::STR: - outMsg.writeInt16(0x000d); - break; - - case LocalPlayer::AGI: - outMsg.writeInt16(0x000e); - break; - - case LocalPlayer::VIT: - outMsg.writeInt16(0x000f); - break; - - case LocalPlayer::INT: - outMsg.writeInt16(0x0010); - break; - - case LocalPlayer::DEX: - outMsg.writeInt16(0x0011); - break; - - case LocalPlayer::LUK: - outMsg.writeInt16(0x0012); - break; + MessageOut outMsg(CMSG_STAT_UPDATE_REQUEST); + outMsg.writeInt16(attr); + outMsg.writeInt8(1); } - outMsg.writeInt8(1); } -void PlayerHandler::decreaseStat(LocalPlayer::Attribute attr) +void PlayerHandler::decreaseAttribute(size_t attr) { // Supported by eA? } +void PlayerHandler::increaseSkill(int skillId) +{ + if (player_node->getSkillPoints() <= 0) + return; + + MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST); + outMsg.writeInt16(skillId); +} + void PlayerHandler::pickUp(FloorItem *floorItem) { MessageOut outMsg(CMSG_ITEM_PICKUP); @@ -521,4 +562,9 @@ void PlayerHandler::ignoreAll(bool ignore) // TODO } +bool PlayerHandler::canUseMagic() +{ + return player_node->getAttributeEffective(MATK) > 0; +} + } // namespace EAthena diff --git a/src/net/ea/playerhandler.h b/src/net/ea/playerhandler.h index 5dbc171b..78e64a88 100644 --- a/src/net/ea/playerhandler.h +++ b/src/net/ea/playerhandler.h @@ -39,9 +39,11 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler void emote(int emoteId); - void increaseStat(LocalPlayer::Attribute attr); + void increaseAttribute(size_t attr); - void decreaseStat(LocalPlayer::Attribute attr); + void decreaseAttribute(size_t attr); + + void increaseSkill(int skillId); void pickUp(FloorItem *floorItem); @@ -56,6 +58,8 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler void ignorePlayer(const std::string &player, bool ignore); void ignoreAll(bool ignore); + + bool canUseMagic(); }; } // namespace EAthena diff --git a/src/net/ea/protocol.h b/src/net/ea/protocol.h index b3759946..279e4c2f 100644 --- a/src/net/ea/protocol.h +++ b/src/net/ea/protocol.h @@ -22,6 +22,25 @@ #ifndef EA_PROTOCOL_H #define EA_PROTOCOL_H +enum { + JOB = 0xa, + + STR = 0xd, + AGI, + VIT, + INT, + DEX, + LUK, + + ATK, + DEF, + MATK, + MDEF, + HIT, + FLEE, + CRIT +}; + static const int INVENTORY_OFFSET = 2; static const int STORAGE_OFFSET = 1; @@ -69,6 +88,7 @@ static const int STORAGE_OFFSET = 1; #define SMSG_PLAYER_ARROW_EQUIP 0x013c #define SMSG_PLAYER_ARROW_MESSAGE 0x013b #define SMSG_PLAYER_SKILLS 0x010f +#define SMSG_PLAYER_SKILL_UP 0x010e #define SMSG_SKILL_FAILED 0x0110 #define SMSG_ITEM_USE_RESPONSE 0x00a8 #define SMSG_ITEM_VISIBLE 0x009d /**< An item is on the floor */ @@ -160,6 +180,11 @@ static const int STORAGE_OFFSET = 1; #define CMSG_SKILL_LEVELUP_REQUEST 0x0112 #define CMSG_STAT_UPDATE_REQUEST 0x00bb +#define CMSG_SKILL_USE_BEING 0x0113 +#define CMSG_SKILL_USE_POSITION 0x0116 +// Variant of 0x116 with 80 char string at end (unsure of use) +#define CMSG_SKILL_USE_POSITION_MORE 0x0190 +#define CMSG_SKILL_USE_MAP 0x011b #define CMSG_PLAYER_INVENTORY_USE 0x00a7 #define CMSG_PLAYER_INVENTORY_DROP 0x00a2 diff --git a/src/net/ea/skillhandler.cpp b/src/net/ea/specialhandler.cpp index 69b0fd65..528f531e 100644 --- a/src/net/ea/skillhandler.cpp +++ b/src/net/ea/specialhandler.cpp @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "net/ea/skillhandler.h" +#include "net/ea/specialhandler.h" #include "net/ea/protocol.h" @@ -29,7 +29,7 @@ #include "localplayer.h" #include "log.h" -#include "gui/skill.h" +#include "gui/skilldialog.h" #include "gui/widgets/chattab.h" @@ -67,60 +67,68 @@ /** should always be zero if failed */ #define SKILL_FAILED 0x00 -Net::SkillHandler *skillHandler; +Net::SpecialHandler *specialHandler; namespace EAthena { -SkillHandler::SkillHandler() +SpecialHandler::SpecialHandler() { static const Uint16 _messages[] = { SMSG_PLAYER_SKILLS, SMSG_SKILL_FAILED, + SMSG_PLAYER_SKILL_UP, 0 }; handledMessages = _messages; - skillHandler = this; + specialHandler = this; } -void SkillHandler::handleMessage(MessageIn &msg) +void SpecialHandler::handleMessage(MessageIn &msg) { int skillCount; + int skillId; switch (msg.getId()) { case SMSG_PLAYER_SKILLS: msg.readInt16(); // length skillCount = (msg.getLength() - 4) / 37; - skillDialog->cleanList(); for (int k = 0; k < skillCount; k++) { - int skillId = msg.readInt16(); + skillId = msg.readInt16(); msg.readInt16(); // target type - msg.readInt16(); // unknown + msg.skip(2); // unused int level = msg.readInt16(); - int sp = msg.readInt16(); - msg.readInt16(); // range - std::string skillName = msg.readString(24); + msg.readInt16(); // sp + msg.readInt16(); // range + msg.skip(24); // unused int up = msg.readInt8(); - if (level != 0 || up != 0) - { - if (skillDialog->hasSkill(skillId)) { - skillDialog->setSkill(skillId, level, sp); - } - else { - skillDialog->addSkill(skillId, level, sp); - } - } + player_node->setAttributeBase(skillId, level); + player_node->setAttributeEffective(skillId, level); + skillDialog->setModifiable(skillId, up); + } + break; + + case SMSG_PLAYER_SKILL_UP: + { + skillId = msg.readInt16(); + int level = msg.readInt16(); + msg.readInt16(); // sp + msg.readInt16(); // range + int up = msg.readInt8(); + + player_node->setAttributeBase(skillId, level); + player_node->setAttributeEffective(skillId, level); + skillDialog->setModifiable(skillId, up); } - skillDialog->update(); break; case SMSG_SKILL_FAILED: // Action failed (ex. sit because you have not reached the // right level) - short skill = msg.readInt16(); + skillId = msg.readInt16(); short bskill = msg.readInt16(); msg.readInt16(); // unknown char success = msg.readInt8(); @@ -131,7 +139,7 @@ void SkillHandler::handleMessage(MessageIn &msg) } std::string msg; - if (success == SKILL_FAILED && skill == SKILL_BASIC) + if (success == SKILL_FAILED && skillId == SKILL_BASIC) { switch (bskill) { @@ -196,7 +204,7 @@ void SkillHandler::handleMessage(MessageIn &msg) } else { - switch (skill) + switch (skillId) { case SKILL_WARP : msg = _("Warp failed..."); @@ -215,28 +223,33 @@ void SkillHandler::handleMessage(MessageIn &msg) } } -void SkillHandler::up(int skillId) +void SpecialHandler::use(int id) { - if (player_node->mSkillPoint <= 0) - return; - - MessageOut outMsg(CMSG_SKILL_LEVELUP_REQUEST); - outMsg.writeInt16(skillId); + // TODO } -void SkillHandler::use(int skillId, int level, int beingId) +void SpecialHandler::use(int id, int level, int beingId) { - // TODO + MessageOut outMsg(CMSG_SKILL_USE_BEING); + outMsg.writeInt16(level); + outMsg.writeInt16(id); + outMsg.writeInt16(beingId); } -void SkillHandler::use(int skillId, int level, int x, int y) +void SpecialHandler::use(int id, int level, int x, int y) { - // TODO + MessageOut outMsg(CMSG_SKILL_USE_POSITION); + outMsg.writeInt16(level); + outMsg.writeInt16(id); + outMsg.writeInt16(x); + outMsg.writeInt16(y); } -void SkillHandler::use(int skillId, const std::string &map) +void SpecialHandler::use(int id, const std::string &map) { - // TODO + MessageOut outMsg(CMSG_SKILL_USE_MAP); + outMsg.writeInt16(id); + outMsg.writeString(map, 16); } } // namespace EAthena diff --git a/src/net/ea/skillhandler.h b/src/net/ea/specialhandler.h index c1965213..eac53569 100644 --- a/src/net/ea/skillhandler.h +++ b/src/net/ea/specialhandler.h @@ -24,24 +24,24 @@ #include "net/messagehandler.h" #include "net/net.h" -#include "net/skillhandler.h" +#include "net/specialhandler.h" namespace EAthena { -class SkillHandler : public MessageHandler, public Net::SkillHandler +class SpecialHandler : public MessageHandler, public Net::SpecialHandler { public: - SkillHandler(); + SpecialHandler(); void handleMessage(MessageIn &msg); - void up(int skillId); + void use(int id); - void use(int skillId, int level, int beingId); + void use(int id, int level, int beingId); - void use(int skillId, int level, int x, int y); + void use(int id, int level, int x, int y); - void use(int skillId, const std::string &map); + void use(int id, const std::string &map); }; } // namespace EAthena diff --git a/src/net/net.cpp b/src/net/net.cpp index a329af1a..7df336c6 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -33,7 +33,7 @@ #include "net/npchandler.h" #include "net/partyhandler.h" #include "net/playerhandler.h" -#include "net/skillhandler.h" +#include "net/specialhandler.h" #include "net/tradehandler.h" extern Net::AdminHandler *adminHandler; @@ -47,7 +47,7 @@ extern Net::MapHandler *mapHandler; extern Net::NpcHandler *npcHandler; extern Net::PartyHandler *partyHandler; extern Net::PlayerHandler *playerHandler; -extern Net::SkillHandler *skillHandler; +extern Net::SpecialHandler *specialHandler; extern Net::TradeHandler *tradeHandler; Net::AdminHandler *Net::getAdminHandler() @@ -111,9 +111,9 @@ Net::PlayerHandler *Net::getPlayerHandler() return playerHandler; } -Net::SkillHandler *Net::getSkillHandler() +Net::SpecialHandler *Net::getSpecialHandler() { - return skillHandler; + return specialHandler; } Net::TradeHandler *Net::getTradeHandler() diff --git a/src/net/net.h b/src/net/net.h index 9154c1ef..1d91faa7 100644 --- a/src/net/net.h +++ b/src/net/net.h @@ -36,7 +36,7 @@ class MapHandler; class NpcHandler; class PartyHandler; class PlayerHandler; -class SkillHandler; +class SpecialHandler; class TradeHandler; AdminHandler *getAdminHandler(); @@ -51,7 +51,7 @@ MapHandler *getMapHandler(); NpcHandler *getNpcHandler(); PartyHandler *getPartyHandler(); PlayerHandler *getPlayerHandler(); -SkillHandler *getSkillHandler(); +SpecialHandler *getSpecialHandler(); TradeHandler *getTradeHandler(); } // namespace Net diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index 163b48f3..a0fd8bac 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -35,9 +35,11 @@ class PlayerHandler virtual void emote(int emoteId) = 0; - virtual void increaseStat(LocalPlayer::Attribute attr) = 0; + virtual void increaseAttribute(size_t attr) = 0; - virtual void decreaseStat(LocalPlayer::Attribute attr) = 0; + virtual void decreaseAttribute(size_t attr) = 0; + + virtual void increaseSkill(int skillId) = 0; virtual void pickUp(FloorItem *floorItem) = 0; @@ -52,6 +54,8 @@ class PlayerHandler virtual void ignorePlayer(const std::string &player, bool ignore) = 0; virtual void ignoreAll(bool ignore) = 0; + + virtual bool canUseMagic() = 0; }; } // namespace Net diff --git a/src/net/skillhandler.h b/src/net/specialhandler.h index 9db6ac5b..602003aa 100644 --- a/src/net/skillhandler.h +++ b/src/net/specialhandler.h @@ -19,23 +19,23 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SKILLHANDLER_H -#define SKILLHANDLER_H +#ifndef SPECIALHANDLER_H +#define SPECIALHANDLER_H #include <iosfwd> namespace Net { -class SkillHandler +class SpecialHandler { public: - virtual void up(int skillId) = 0; + virtual void use(int id) = 0; - virtual void use(int skillId, int level, int beingId) = 0; + virtual void use(int id, int level, int beingId) = 0; - virtual void use(int skillId, int level, int x, int y) = 0; + virtual void use(int id, int level, int x, int y) = 0; - virtual void use(int skillId, const std::string &map) = 0; + virtual void use(int id, const std::string &map) = 0; }; } -#endif // SKILLHANDLER_H +#endif // SPECIALHANDLER_H diff --git a/src/net/tmwserv/beinghandler.cpp b/src/net/tmwserv/beinghandler.cpp index 7076ff8e..acd6b62c 100644 --- a/src/net/tmwserv/beinghandler.cpp +++ b/src/net/tmwserv/beinghandler.cpp @@ -187,28 +187,14 @@ void BeingHandler::handleBeingsMoveMessage(MessageIn &msg) Being *being = beingManager->findBeing(id); int sx = 0; int sy = 0; - int dx = 0; - int dy = 0; int speed = 0; if (flags & MOVING_POSITION) { - Uint16 sx2, sy2; - msg.readCoordinates(sx2, sy2); - sx = sx2 * 32 + 16; - sy = sy2 * 32 + 16; + sx = msg.readInt16(); + sy = msg.readInt16(); speed = msg.readInt8(); } - if (flags & MOVING_DESTINATION) - { - dx = msg.readInt16(); - dy = msg.readInt16(); - if (!(flags & MOVING_POSITION)) - { - sx = dx; - sy = dy; - } - } if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION))) { continue; @@ -228,33 +214,9 @@ void BeingHandler::handleBeingsMoveMessage(MessageIn &msg) if (being == player_node) continue; - // If being is a player, and he only moves a little, its ok to be a little out of sync - if (being->getType() == Being::PLAYER && abs(being->getPixelX() - dx) + - abs(being->getPixelY() - dy) < 16 && - (dx != being->getDestination().x && - dy != being->getDestination().y)) - { - being->setDestination(being->getPixelX(),being->getPixelY()); - continue; - } - if (abs(being->getPixelX() - sx) + - abs(being->getPixelY() - sy) > 10 * 32) - { - // Too large a desynchronization. - being->setPosition(sx, sy); - being->setDestination(dx, dy); - } - else if (!(flags & MOVING_POSITION)) - { - being->setDestination(dx, dy); - } - else if (!(flags & MOVING_DESTINATION)) - { - being->adjustCourse(sx, sy); - } - else + if (flags & MOVING_POSITION) { - being->setDestination(sx, sy, dx, dy); + being->setDestination(sx, sy); } } } @@ -306,23 +268,27 @@ void BeingHandler::handleBeingActionChangeMessage(MessageIn &msg) static char const *const deadMsg[] = { _("You are dead."), - _("We regret to inform you that your character was killed in battle."), + _("We regret to inform you that your character was killed in " + "battle."), _("You are not that alive anymore."), _("The cold hands of the grim reaper are grabbing for your soul."), _("Game Over!"), - _("No, kids. Your character did not really die. It... err... went to a better place."), - _("Your plan of breaking your enemies weapon by bashing it with your throat failed."), + _("No, kids. Your character did not really die. It... err... " + "went to a better place."), + _("Your plan of breaking your enemies weapon by bashing it with " + "your throat failed."), _("I guess this did not run too well."), _("Do you want your possessions identified?"), // Nethack reference _("Sadly, no trace of you was ever found..."), // Secret of Mana reference _("Annihilated."), // Final Fantasy VI reference - _("Looks like you got your head handed to you."), //Earthbound reference - _("You screwed up again, dump your body down the tubes and get you another one.") // Leisure Suit Larry 1 Reference + _("Looks like you got your head handed to you."), // Earthbound reference + _("You screwed up again, dump your body down the tubes and get " + "you another one.") // Leisure Suit Larry 1 Reference }; std::string message(deadMsg[rand()%13]); - message.append(_(" Press OK to respawn")); - OkDialog *dlg = new OkDialog(_("You died"), message); + message.append(std::string(" ") + _("Press OK to respawn.")); + OkDialog *dlg = new OkDialog(_("You Died"), message); dlg->addActionListener(&(Net::GameServer::Player::respawnListener)); } } diff --git a/src/net/tmwserv/charserverhandler.cpp b/src/net/tmwserv/charserverhandler.cpp index 7b74904f..0146babb 100644 --- a/src/net/tmwserv/charserverhandler.cpp +++ b/src/net/tmwserv/charserverhandler.cpp @@ -81,25 +81,25 @@ void CharServerHandler::handleMessage(MessageIn &msg) delete mCharInfo->getEntry(); mCharInfo->setEntry(0); mCharInfo->unlock(); - new OkDialog("Info", "Player deleted"); + new OkDialog(_("Info"), _("Player deleted.")); } // Character deletion failed else { - std::string message = ""; + std::string errorMessage = ""; switch (errMsg) { case ERRMSG_NO_LOGIN: - message = "Not logged in"; + errorMessage = _("Not logged in."); break; case ERRMSG_INVALID_ARGUMENT: - message = "Selection out of range"; + errorMessage = _("Selection out of range."); break; default: - message = "Unknown error"; + errorMessage = _("Unknown error."); } mCharInfo->unlock(); - new OkDialog("Error", message); + new OkDialog(_("Error"), errorMessage); } } break; @@ -131,44 +131,44 @@ void CharServerHandler::handleCharCreateResponse(MessageIn &msg) // Character creation failed if (errMsg != ERRMSG_OK) { - std::string message = ""; + std::string errorMessage = ""; switch (errMsg) { case ERRMSG_NO_LOGIN: - message = "Not logged in"; + errorMessage = _("Not logged in."); break; case CREATE_TOO_MUCH_CHARACTERS: - message = "No empty slot"; + errorMessage = _("No empty slot."); break; case ERRMSG_INVALID_ARGUMENT: - message = "Invalid name"; + errorMessage = _("Invalid name."); break; case CREATE_EXISTS_NAME: - message = "Character's name already exists"; + errorMessage = _("Character's name already exists."); break; case CREATE_INVALID_HAIRSTYLE: - message = "Invalid hairstyle"; + errorMessage = _("Invalid hairstyle."); break; case CREATE_INVALID_HAIRCOLOR: - message = "Invalid hair color"; + errorMessage = _("Invalid hair color."); break; case CREATE_INVALID_GENDER: - message = "Invalid gender"; + errorMessage = _("Invalid gender."); break; case CREATE_RAW_STATS_TOO_HIGH: - message = "Character's stats are too high"; + errorMessage = _("Character's stats are too high."); break; case CREATE_RAW_STATS_TOO_LOW: - message = "Character's stats are too low"; + errorMessage = _("Character's stats are too low."); break; case CREATE_RAW_STATS_EQUAL_TO_ZERO: - message = "One stat is zero"; + errorMessage = _("One stat is zero."); break; default: - message = "Unknown error"; + errorMessage = _("Unknown error."); break; } - new OkDialog("Error", message); + new OkDialog(_("Error"), errorMessage); } if (mCharCreateDialog) diff --git a/src/net/tmwserv/chathandler.cpp b/src/net/tmwserv/chathandler.cpp index e2d09534..ad3ae49b 100644 --- a/src/net/tmwserv/chathandler.cpp +++ b/src/net/tmwserv/chathandler.cpp @@ -159,7 +159,7 @@ void ChatHandler::handleEnterChannelResponse(MessageIn &msg) std::string user; std::string userModes; - tab->chatLog("Players in this channel:", BY_CHANNEL); + tab->chatLog(_("Players in this channel:"), BY_CHANNEL); while(msg.getUnreadLength()) { user = msg.readString(); @@ -176,13 +176,13 @@ void ChatHandler::handleEnterChannelResponse(MessageIn &msg) } else { - localChatTab->chatLog("Error joining channel.", BY_SERVER); + localChatTab->chatLog(_("Error joining channel."), BY_SERVER); } } void ChatHandler::handleListChannelsResponse(MessageIn &msg) { - localChatTab->chatLog("Listing channels", BY_SERVER); + localChatTab->chatLog(_("Listing channels."), BY_SERVER); while(msg.getUnreadLength()) { std::string channelName = msg.readString(); @@ -194,7 +194,7 @@ void ChatHandler::handleListChannelsResponse(MessageIn &msg) channelName += numUsers.str(); localChatTab->chatLog(channelName, BY_SERVER); } - localChatTab->chatLog("End of channel list.", BY_SERVER); + localChatTab->chatLog(_("End of channel list."), BY_SERVER); } void ChatHandler::handlePrivateMessage(MessageIn &msg) @@ -237,7 +237,7 @@ void ChatHandler::handleListChannelUsersResponse(MessageIn &msg) std::string userNick; std::string userModes; Channel *channel = channelManager->findByName(channelName); - channel->getTab()->chatLog("Players in this channel:", BY_CHANNEL); + channel->getTab()->chatLog(_("Players in this channel:"), BY_CHANNEL); while(msg.getUnreadLength()) { userNick = msg.readString(); @@ -266,15 +266,18 @@ void ChatHandler::handleChannelEvent(MessageIn &msg) switch(eventId) { case CHAT_EVENT_NEW_PLAYER: - line += " entered the channel."; + channel->getTab()->chatLog(strprintf(_("%s entered the " + "channel."), line.c_str()), BY_CHANNEL); break; case CHAT_EVENT_LEAVING_PLAYER: - line += " left the channel."; + channel->getTab()->chatLog(strprintf(_("%s left the channel."), + line.c_str()), BY_CHANNEL); break; case CHAT_EVENT_TOPIC_CHANGE: - line = "Topic: " + line; + channel->getTab()->chatLog(strprintf(_("Topic: %s"), + line.c_str()), BY_CHANNEL); break; case CHAT_EVENT_MODE_CHANGE: @@ -284,7 +287,9 @@ void ChatHandler::handleChannelEvent(MessageIn &msg) std::string user1 = line.substr(0, first); std::string user2 = line.substr(first+1, second); std::string mode = line.substr(second+1, line.length()); - line = user1 + " has set mode " + mode + " on user " + user2; + channel->getTab()->chatLog(strprintf(_("%s has set mode %s " + "on user %s."), user1.c_str(), mode.c_str(), + user2.c_str()), BY_CHANNEL); } break; case CHAT_EVENT_KICKED_PLAYER: @@ -292,14 +297,14 @@ void ChatHandler::handleChannelEvent(MessageIn &msg) int first = line.find(":"); std::string user1 = line.substr(0, first); std::string user2 = line.substr(first+1, line.length()); - line = user1 + " has kicked " + user2; + channel->getTab()->chatLog(strprintf(_("%s has kicked %s."), + user1, user2), BY_CHANNEL); } break; default: - line = "Unknown channel event."; + channel->getTab()->chatLog(_("Unknown channel event."), + BY_CHANNEL); } - - channel->getTab()->chatLog(line, BY_CHANNEL); } } diff --git a/src/net/tmwserv/gameserver/player.cpp b/src/net/tmwserv/gameserver/player.cpp index 93853681..4e63930b 100644 --- a/src/net/tmwserv/gameserver/player.cpp +++ b/src/net/tmwserv/gameserver/player.cpp @@ -41,14 +41,6 @@ void Net::GameServer::Player::walk(int x, int y) Net::GameServer::connection->send(msg); } -void Net::GameServer::Player::pickUp(int x, int y) -{ - MessageOut msg(PGMSG_PICKUP); - msg.writeInt16(x); - msg.writeInt16(y); - Net::GameServer::connection->send(msg); -} - void Net::GameServer::Player::moveItem(int oldSlot, int newSlot, int amount) { MessageOut msg(PGMSG_MOVE_ITEM); @@ -58,47 +50,6 @@ void Net::GameServer::Player::moveItem(int oldSlot, int newSlot, int amount) Net::GameServer::connection->send(msg); } -void Net::GameServer::Player::useSpecial(int special) -{ - MessageOut msg(PGMSG_USE_SPECIAL); - msg.writeInt8(special); - Net::GameServer::connection->send(msg); -} - -void Net::GameServer::Player::requestTrade(int id) -{ - MessageOut msg(PGMSG_TRADE_REQUEST); - msg.writeInt16(id); - Net::GameServer::connection->send(msg); -} - -void Net::GameServer::Player::acceptTrade(bool accept) -{ - MessageOut msg(accept ? PGMSG_TRADE_REQUEST : PGMSG_TRADE_CANCEL); - Net::GameServer::connection->send(msg); -} - -void Net::GameServer::Player::tradeMoney(int amount) -{ - MessageOut msg(PGMSG_TRADE_SET_MONEY); - msg.writeInt32(amount); - Net::GameServer::connection->send(msg); -} - -void Net::GameServer::Player::raiseAttribute(int attribute) -{ - MessageOut msg(PGMSG_RAISE_ATTRIBUTE); - msg.writeInt8(attribute); - Net::GameServer::connection->send(msg); -} - -void Net::GameServer::Player::lowerAttribute(int attribute) -{ - MessageOut msg(PGMSG_LOWER_ATTRIBUTE); - msg.writeInt8(attribute); - Net::GameServer::connection->send(msg); -} - void Net::GameServer::Player::respawn() { MessageOut msg(PGMSG_RESPAWN); diff --git a/src/net/tmwserv/gameserver/player.h b/src/net/tmwserv/gameserver/player.h index 24b25dc7..9a202c6e 100644 --- a/src/net/tmwserv/gameserver/player.h +++ b/src/net/tmwserv/gameserver/player.h @@ -41,14 +41,7 @@ namespace Net namespace Player { void walk(int x, int y); - void pickUp(int x, int y); void moveItem(int oldSlot, int newSlot, int amount); - void useSpecial(int special); - void requestTrade(int id); - void acceptTrade(bool accept); - void tradeMoney(int amount); - void raiseAttribute(int attribute); - void lowerAttribute(int attribute); void respawn(); static RespawnRequestListener respawnListener; } diff --git a/src/net/tmwserv/generalhandler.cpp b/src/net/tmwserv/generalhandler.cpp index 5886aafb..d643586b 100644 --- a/src/net/tmwserv/generalhandler.cpp +++ b/src/net/tmwserv/generalhandler.cpp @@ -21,6 +21,8 @@ #include "gui/inventorywindow.h" #include "gui/partywindow.h" +#include "gui/skilldialog.h" +#include "gui/statuswindow.h" #include "net/tmwserv/generalhandler.h" @@ -146,6 +148,16 @@ void GeneralHandler::guiWindowsLoaded() { inventoryWindow->setSplitAllowed(true); partyWindow->clearPartyName(); + skillDialog->loadSkills("tmw-skills.xml"); + + player_node->setExpNeeded(100); + + statusWindow->addAttribute(16, _("Strength"), true); + statusWindow->addAttribute(17, _("Agility"), true); + statusWindow->addAttribute(18, _("Dexterity"), true); + statusWindow->addAttribute(19, _("Vitality"), true); + statusWindow->addAttribute(20, _("Intelligence"), true); + statusWindow->addAttribute(21, _("Willpower"), true); } void GeneralHandler::guiWindowsUnloaded() diff --git a/src/net/tmwserv/loginhandler.cpp b/src/net/tmwserv/loginhandler.cpp index 35739669..f728d831 100644 --- a/src/net/tmwserv/loginhandler.cpp +++ b/src/net/tmwserv/loginhandler.cpp @@ -77,16 +77,16 @@ void LoginHandler::handleMessage(MessageIn &msg) { switch (errMsg) { case ERRMSG_INVALID_ARGUMENT: - errorMessage = _("Wrong magic_token"); + errorMessage = _("Wrong magic_token."); break; case ERRMSG_FAILURE: - errorMessage = _("Already logged in"); + errorMessage = _("Already logged in."); break; case LOGIN_SERVER_FULL: - errorMessage = _("Server is full"); + errorMessage = _("Server is full."); break; default: - errorMessage = _("Unknown error"); + errorMessage = _("Unknown error."); break; } state = STATE_ERROR; @@ -107,16 +107,16 @@ void LoginHandler::handleMessage(MessageIn &msg) { switch (errMsg) { case ERRMSG_INVALID_ARGUMENT: - errorMessage = _("New password incorrect"); + errorMessage = _("New password incorrect."); break; case ERRMSG_FAILURE: - errorMessage = _("Old password incorrect"); + errorMessage = _("Old password incorrect."); break; case ERRMSG_NO_LOGIN: errorMessage = _("Account not connected. Please login first."); break; default: - errorMessage = _("Unknown error"); + errorMessage = _("Unknown error."); break; } state = STATE_ACCOUNTCHANGE_ERROR; @@ -137,19 +137,19 @@ void LoginHandler::handleMessage(MessageIn &msg) { switch (errMsg) { case ERRMSG_INVALID_ARGUMENT: - errorMessage = _("New email address incorrect"); + errorMessage = _("New email address incorrect."); break; case ERRMSG_FAILURE: - errorMessage = _("Old email address incorrect"); + errorMessage = _("Old email address incorrect."); break; case ERRMSG_NO_LOGIN: errorMessage = _("Account not connected. Please login first."); break; case ERRMSG_EMAIL_ALREADY_EXISTS: - errorMessage = _("The new Email Address already exists."); + errorMessage = _("The new email address already exists."); break; default: - errorMessage = _("Unknown error"); + errorMessage = _("Unknown error."); break; } state = STATE_ACCOUNTCHANGE_ERROR; @@ -173,19 +173,19 @@ void LoginHandler::handleLoginResponse(MessageIn &msg) { switch (errMsg) { case LOGIN_INVALID_VERSION: - errorMessage = _("Client version is too old"); + errorMessage = _("Client version is too old."); break; case ERRMSG_INVALID_ARGUMENT: - errorMessage = _("Wrong username or password"); + errorMessage = _("Wrong username or password."); break; case ERRMSG_FAILURE: - errorMessage = _("Already logged in"); + errorMessage = _("Already logged in."); break; case LOGIN_SERVER_FULL: - errorMessage = _("Server is full"); + errorMessage = _("Server is full."); break; default: - errorMessage = _("Unknown error"); + errorMessage = _("Unknown error."); break; } state = STATE_LOGIN_ERROR; @@ -205,19 +205,19 @@ void LoginHandler::handleRegisterResponse(MessageIn &msg) { switch (errMsg) { case REGISTER_INVALID_VERSION: - errorMessage = _("Client version is too old"); + errorMessage = _("Client version is too old."); break; case ERRMSG_INVALID_ARGUMENT: - errorMessage = _("Wrong username, password or email address"); + errorMessage = _("Wrong username, password or email address."); break; case REGISTER_EXISTS_USERNAME: - errorMessage = _("Username already exists"); + errorMessage = _("Username already exists."); break; case REGISTER_EXISTS_EMAIL: - errorMessage = _("Email address already exists"); + errorMessage = _("Email address already exists."); break; default: - errorMessage = _("Unknown error"); + errorMessage = _("Unknown error."); break; } state = STATE_LOGIN_ERROR; diff --git a/src/net/tmwserv/partyhandler.cpp b/src/net/tmwserv/partyhandler.cpp index 557a3a43..2af0e4cb 100644 --- a/src/net/tmwserv/partyhandler.cpp +++ b/src/net/tmwserv/partyhandler.cpp @@ -100,8 +100,8 @@ void PartyHandler::handleMessage(MessageIn &msg) int id = msg.readInt16(); // being id std::string name = msg.readString(); - localChatTab->chatLog(strprintf(_("%s joined the " - "party."), name.c_str())); + localChatTab->chatLog(strprintf(_("%s joined the party.", + name.c_str())); if (!player_node->isInParty()) player_node->setInParty(true); @@ -117,7 +117,8 @@ void PartyHandler::handleMessage(MessageIn &msg) case CPMSG_PARTY_REJECTED: { std::string name = msg.readString(); - localChatTab->chatLog(name + "rejected your invite."); + localChatTab->chatLog(strprintf(_("%s rejected your invite."), + name.c_str())); } break; } } diff --git a/src/net/tmwserv/playerhandler.cpp b/src/net/tmwserv/playerhandler.cpp index bbc73b7c..ce1990ed 100644 --- a/src/net/tmwserv/playerhandler.cpp +++ b/src/net/tmwserv/playerhandler.cpp @@ -43,7 +43,6 @@ #include "gui/gui.h" #include "gui/okdialog.h" #include "gui/sell.h" -#include "gui/skill.h" #include "gui/viewport.h" // TODO Move somewhere else @@ -134,7 +133,7 @@ void PlayerHandler::handleMessage(MessageIn &msg) logger->log("ATTRIBUTE UPDATE:"); while (msg.getUnreadLength()) { - int stat = msg.readInt8(); + int stat = msg.readInt16(); int base = msg.readInt16(); int value = msg.readInt16(); logger->log("%d set to %d %d", stat, base, value); @@ -144,24 +143,11 @@ void PlayerHandler::handleMessage(MessageIn &msg) player_node->setMaxHp(base); player_node->setHp(value); } - else if (stat < NB_CHARACTER_ATTRIBUTES) + else { - if (stat >= CHAR_SKILL_BEGIN && stat < CHAR_SKILL_END - && player_node->getAttributeBase(stat) < base - && player_node->getAttributeBase(stat) > -1) - { - Particle* effect = particleEngine->addEffect("graphics/particles/skillup.particle.xml", 0, 0); - player_node->controlParticle(effect); - } - player_node->setAttributeBase(stat, base); player_node->setAttributeEffective(stat, value); } - else - { - logger->log("Warning: server wants to update unknown " - "attribute %d to %d", stat, value); - } } } break; @@ -174,15 +160,7 @@ void PlayerHandler::handleMessage(MessageIn &msg) int current = msg.readInt32(); int next = msg.readInt32(); - if (skill < CHAR_SKILL_NB) - { - player_node->setExperience(skill, current, next); - } - else - { - logger->log("Warning: server wants to update experience of unknown " - "skill %d to %d / %d", skill, current, next); - } + player_node->setExperience(skill, current, next); } } break; @@ -199,7 +177,7 @@ void PlayerHandler::handleMessage(MessageIn &msg) case GPMSG_LEVEL_PROGRESS: { logger->log("Level Progress Update"); - player_node->setLevelProgress(msg.readInt8()); + player_node->setExp(msg.readInt8()); } break; @@ -358,20 +336,32 @@ void PlayerHandler::emote(int emoteId) // TODO } -void PlayerHandler::increaseStat(LocalPlayer::Attribute attr) +void PlayerHandler::increaseAttribute(size_t attr) { - // TODO + MessageOut msg(PGMSG_RAISE_ATTRIBUTE); + msg.writeInt8(attr); + Net::GameServer::connection->send(msg); } -void PlayerHandler::decreaseStat(LocalPlayer::Attribute attr) +void PlayerHandler::decreaseAttribute(size_t attr) { - // TODO + MessageOut msg(PGMSG_LOWER_ATTRIBUTE); + msg.writeInt8(attr); + Net::GameServer::connection->send(msg); +} + +void PlayerHandler::increaseSkill(int skillId) +{ + // Not used atm } void PlayerHandler::pickUp(FloorItem *floorItem) { int id = floorItem->getId(); - Net::GameServer::Player::pickUp(id >> 16, id & 0xFFFF); + MessageOut msg(PGMSG_PICKUP); + msg.writeInt16(id >> 16); + msg.writeInt16(id & 0xFFFF); + Net::GameServer::connection->send(msg); } void PlayerHandler::setDirection(char direction) @@ -414,4 +404,9 @@ void PlayerHandler::ignoreAll(bool ignore) // TODO } +bool PlayerHandler::canUseMagic() +{ + return true; +} + } // namespace TmwServ diff --git a/src/net/tmwserv/playerhandler.h b/src/net/tmwserv/playerhandler.h index 164d30ae..287baa3d 100644 --- a/src/net/tmwserv/playerhandler.h +++ b/src/net/tmwserv/playerhandler.h @@ -38,9 +38,11 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler void emote(int emoteId); - void increaseStat(LocalPlayer::Attribute attr); + void increaseAttribute(size_t attr); - void decreaseStat(LocalPlayer::Attribute attr); + void decreaseAttribute(size_t attr); + + void increaseSkill(int skillId); void pickUp(FloorItem *floorItem); @@ -56,6 +58,8 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler void ignoreAll(bool ignore); + bool canUseMagic(); + private: void handleMapChangeMessage(MessageIn &msg); }; diff --git a/src/net/tmwserv/protocol.h b/src/net/tmwserv/protocol.h index 2f1ea885..60a50d89 100644 --- a/src/net/tmwserv/protocol.h +++ b/src/net/tmwserv/protocol.h @@ -83,7 +83,7 @@ enum { PGMSG_MOVE_ITEM = 0x0114, // B slot1, B slot2, B amount GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount] }* GPMSG_INVENTORY_FULL = 0x0121, // { B slot, W item id [, B amount] }* - GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { B attribute, W base value, W modified value }* + GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { W attribute, W base value, W modified value }* GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { W skill, D exp got, D exp needed }* GPMSG_LEVELUP = 0x0150, // W new level GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup @@ -104,7 +104,7 @@ enum { GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action PGMSG_DIRECTION_CHANGE = 0x0272, // B Direction GPMSG_BEING_DIR_CHANGE = 0x0273, // W being id, B direction - GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, C position, B speed] [, W*2 destination] }* + GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, W*2 position, B speed] }* GPMSG_ITEMS = 0x0281, // { W item id, W*2 position }* PGMSG_ATTACK = 0x0290, // W being id GPMSG_BEING_ATTACK = 0x0291, // W being id diff --git a/src/net/tmwserv/skillhandler.cpp b/src/net/tmwserv/specialhandler.cpp index e35b896a..f259e77a 100644 --- a/src/net/tmwserv/skillhandler.cpp +++ b/src/net/tmwserv/specialhandler.cpp @@ -19,33 +19,42 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "net/tmwserv/skillhandler.h" +#include "net/tmwserv/specialhandler.h" -Net::SkillHandler *skillHandler; +#include "net/tmwserv/gameserver/internal.h" + +#include "net/tmwserv/connection.h" +#include "net/tmwserv/protocol.h" + +#include "net/messageout.h" + +Net::SpecialHandler *specialHandler; namespace TmwServ { -SkillHandler::SkillHandler() +SpecialHandler::SpecialHandler() { - skillHandler = this; + specialHandler = this; } -void SkillHandler::up(int skillId) +void SpecialHandler::use(int id) { - // TODO + MessageOut msg(PGMSG_USE_SPECIAL); + msg.writeInt8(id); + Net::GameServer::connection->send(msg); } -void SkillHandler::use(int skillId, int level, int beingId) +void SpecialHandler::use(int id, int level, int beingId) { // TODO } -void SkillHandler::use(int skillId, int level, int x, int y) +void SpecialHandler::use(int id, int level, int x, int y) { // TODO } -void SkillHandler::use(int skillId, const std::string &map) +void SpecialHandler::use(int id, const std::string &map) { // TODO } diff --git a/src/net/tmwserv/skillhandler.h b/src/net/tmwserv/specialhandler.h index 8c459c4f..c7ebd6a2 100644 --- a/src/net/tmwserv/skillhandler.h +++ b/src/net/tmwserv/specialhandler.h @@ -22,22 +22,22 @@ #ifndef NET_TMWSERV_SKILLHANDLER_H #define NET_TMWSERV_SKILLHANDLER_H -#include "net/skillhandler.h" +#include "net/specialhandler.h" namespace TmwServ { -class SkillHandler : public Net::SkillHandler +class SpecialHandler : public Net::SpecialHandler { public: - SkillHandler(); + SpecialHandler(); - void up(int skillId); + void use(int id); - void use(int skillId, int level, int beingId); + void use(int id, int level, int beingId); - void use(int skillId, int level, int x, int y); + void use(int id, int level, int x, int y); - void use(int skillId, const std::string &map); + void use(int id, const std::string &map); }; } // namespace TmwServ diff --git a/src/net/tmwserv/tradehandler.cpp b/src/net/tmwserv/tradehandler.cpp index aabd8b2a..55a00d4c 100644 --- a/src/net/tmwserv/tradehandler.cpp +++ b/src/net/tmwserv/tradehandler.cpp @@ -55,7 +55,11 @@ namespace { void action(const gcn::ActionEvent &event) { if (event.getId() == "yes") - Net::GameServer::Player::requestTrade(tradePartnerID); + { + MessageOut msg(PGMSG_TRADE_REQUEST); + msg.writeInt16(tradePartnerID); + Net::GameServer::connection->send(msg); + } else Net::getTradeHandler()->cancel(); } @@ -105,7 +109,7 @@ void TradeHandler::handleMessage(MessageIn &msg) Being *being = beingManager->findBeing(msg.readInt16()); if (!being || !mAcceptTradeRequests) { - Net::GameServer::Player::acceptTrade(false); + respond(false); break; } player_node->setTrading(true); @@ -171,7 +175,9 @@ void TradeHandler::request(Being *being) void TradeHandler::respond(bool accept) { - // TODO + MessageOut msg(accept ? PGMSG_TRADE_REQUEST : PGMSG_TRADE_CANCEL); + Net::GameServer::connection->send(msg); + if (!accept) player_node->setTrading(false); } diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index b9d837ad..4d66a919 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -140,6 +140,42 @@ static inline void drawQuad(Image *image, } } +static inline void drawRescaledQuad(Image *image, + int srcX, int srcY, int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight) +{ + if (image->getTextureType() == GL_TEXTURE_2D) + { + // Find OpenGL normalized texture coordinates. + float texX1 = srcX / (float) image->getTextureWidth(); + float texY1 = srcY / (float) image->getTextureHeight(); + float texX2 = (srcX + width) / (float) image->getTextureWidth(); + float texY2 = (srcY + height) / (float) image->getTextureHeight(); + + glTexCoord2f(texX1, texY1); + glVertex2i(dstX, dstY); + glTexCoord2f(texX2, texY1); + glVertex2i(dstX + desiredWidth, dstY); + glTexCoord2f(texX2, texY2); + glVertex2i(dstX + desiredWidth, dstY + desiredHeight); + glTexCoord2f(texX1, texY2); + glVertex2i(dstX, dstY + desiredHeight); + } + else + { + glTexCoord2i(srcX, srcY); + glVertex2i(dstX, dstY); + glTexCoord2i(srcX + width, srcY); + glVertex2i(dstX + desiredWidth, dstY); + glTexCoord2i(srcX + width, srcY + height); + glVertex2i(dstX + desiredWidth, dstY + desiredHeight); + glTexCoord2i(srcX, srcY + height); + glVertex2i(dstX, dstY + desiredHeight); + } +} + + bool OpenGLGraphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height, bool useColor) @@ -168,6 +204,37 @@ bool OpenGLGraphics::drawImage(Image *image, int srcX, int srcY, return true; } +bool OpenGLGraphics::drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor) +{ + if (!image) + return false; + + srcX += image->mBounds.x; + srcY += image->mBounds.y; + + if (!useColor) + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + glBindTexture(Image::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a textured quad. + glBegin(GL_QUADS); + drawRescaledQuad(image, srcX, srcY, dstX, dstY, width, height, + desiredWidth, desiredHeight); + glEnd(); + + if (!useColor) + glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a); + + return true; +} + /* Optimising the functions that Graphics::drawImagePattern would call, * so that glBegin...glEnd are outside the main loop. */ void OpenGLGraphics::drawImagePattern(Image *image, int x, int y, int w, int h) @@ -210,6 +277,49 @@ void OpenGLGraphics::drawImagePattern(Image *image, int x, int y, int w, int h) glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a); } +void OpenGLGraphics::drawRescaledImagePattern(Image *image, int x, int y, + int w, int h, + int scaledWidth, int scaledHeight) +{ + if (!image) + return; + + const int srcX = image->mBounds.x; + const int srcY = image->mBounds.y; + + const int iw = scaledWidth; + const int ih = scaledHeight; + if (iw == 0 || ih == 0) + return; + + glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); + + glBindTexture(Image::mTextureType, image->mGLImage); + + setTexturingAndBlending(true); + + // Draw a set of textured rectangles + glBegin(GL_QUADS); + + for (int py = 0; py < h; py += ih) + { + const int height = (py + ih >= h) ? h - py : ih; + const int dstY = y + py; + for (int px = 0; px < w; px += iw) + { + int width = (px + iw >= w) ? w - px : iw; + int dstX = x + px; + + drawRescaledQuad(image, srcX, srcY, dstX, dstY, + width, height, scaledWidth, scaledHeight); + } + } + + glEnd(); + + glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a); +} + void OpenGLGraphics::updateScreen() { glFlush(); diff --git a/src/openglgraphics.h b/src/openglgraphics.h index dc748804..0bee48b4 100644 --- a/src/openglgraphics.h +++ b/src/openglgraphics.h @@ -46,10 +46,26 @@ class OpenGLGraphics : public Graphics int width, int height, bool useColor); + /** + * Draws a resclaled version of the image + */ + bool drawRescaledImage(Image *image, int srcX, int srcY, + int dstX, int dstY, + int width, int height, + int desiredWidth, int desiredHeight, + bool useColor); + void drawImagePattern(Image *image, int x, int y, int w, int h); + /** + * Draw a pattern based on a rescaled version of the given image... + */ + void drawRescaledImagePattern(Image *image, + int x, int y, int w, int h, + int scaledWidth, int scaledHeight); + void updateScreen(); void _beginDraw(); diff --git a/src/player.cpp b/src/player.cpp index 3b2271bd..fd7cd0d6 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -255,21 +255,6 @@ void Player::updateCoords() } #ifdef TMWSERV_SUPPORT - -Path Player::findPath() -{ - Path path; - - if (mMap) - { - path = mMap->findSimplePath(getPosition().x / 32, getPosition().y / 32, - getDestination().x / 32, getDestination().y / 32, - getWalkMask()); - } - - return path; -} - Guild* Player::addGuild(short guildId, short rights) { Guild *guild = new Guild(guildId, rights); diff --git a/src/player.h b/src/player.h index cfd305a6..9a5c6c94 100644 --- a/src/player.h +++ b/src/player.h @@ -93,11 +93,6 @@ class Player : public Being #ifdef TMWSERV_SUPPORT /** - * Returns the path to the player's current destination - */ - Path findPath(); - - /** * Adds a guild to the player. */ Guild *addGuild(short guildId, short rights); diff --git a/src/playerrelations.cpp b/src/playerrelations.cpp index 316bd9ed..7bc1b14d 100644 --- a/src/playerrelations.cpp +++ b/src/playerrelations.cpp @@ -29,6 +29,7 @@ #include "playerrelations.h" #include "utils/dtor.h" +#include "utils/gettext.h" #define PLAYER_IGNORE_STRATEGY_NOP "nop" #define PLAYER_IGNORE_STRATEGY_EMOTE0 "emote0" @@ -292,7 +293,7 @@ class PIS_nothing : public PlayerIgnoreStrategy public: PIS_nothing() { - mDescription = "completely ignore"; + mDescription = _("Completely ignore"); mShortName = PLAYER_IGNORE_STRATEGY_NOP; } @@ -306,7 +307,7 @@ class PIS_dotdotdot : public PlayerIgnoreStrategy public: PIS_dotdotdot() { - mDescription = "print '...'"; + mDescription = _("Print '...'"); mShortName = "dotdotdot"; } @@ -322,7 +323,7 @@ class PIS_blinkname : public PlayerIgnoreStrategy public: PIS_blinkname() { - mDescription = "blink name"; + mDescription = _("Blink name"); mShortName = "blinkname"; } @@ -359,10 +360,10 @@ PlayerRelationsManager::getPlayerIgnoreStrategies() { // not initialised yet? mIgnoreStrategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE, - "floating '...' bubble", + _("Floating '...' bubble"), PLAYER_IGNORE_STRATEGY_EMOTE0)); mIgnoreStrategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE + 1, - "floating bubble", + _("Floating bubble"), "emote1")); mIgnoreStrategies.push_back(new PIS_nothing()); mIgnoreStrategies.push_back(new PIS_dotdotdot()); diff --git a/src/properties.h b/src/properties.h index a2ce5b88..e7aab157 100644 --- a/src/properties.h +++ b/src/properties.h @@ -74,6 +74,28 @@ class Properties } /** + * Gets a map property as a boolean. + * + * @param name The name of the property. + * @param def Default value, false by default. + * @return the value of the given property, or false when it doesn't + * exist. + */ + float getBoolProperty(const std::string &name, bool def = false) const + { + PropertyMap::const_iterator i = mProperties.find(name); + bool ret = def; + if (i != mProperties.end()) + { + if (i->second == "true") + ret = true; + if (i->second == "false") + ret = false; + } + return ret; + } + + /** * Returns whether a certain property is available. * * @param name The name of the property. diff --git a/src/resources/ambientoverlay.cpp b/src/resources/ambientoverlay.cpp index 93c7c3e1..8c851e2e 100644 --- a/src/resources/ambientoverlay.cpp +++ b/src/resources/ambientoverlay.cpp @@ -22,16 +22,41 @@ #include "resources/ambientoverlay.h" #include "resources/image.h" - +#include "resources/resourcemanager.h" #include "graphics.h" AmbientOverlay::AmbientOverlay(Image *img, float parallax, - float speedX, float speedY): + float speedX, float speedY, bool keepRatio): mImage(img), mParallax(parallax), mPosX(0), mPosY(0), - mSpeedX(speedX), mSpeedY(speedY) + mSpeedX(speedX), mSpeedY(speedY), + mKeepRatio(keepRatio) { - mImage->incRef(); + + if (keepRatio && !mImage->isAnOpenGLOne() + && defaultScreenWidth != 0 + && defaultScreenHeight != 0 + && graphics->getWidth() != defaultScreenWidth + && graphics->getHeight() != defaultScreenHeight) + { + // Rescale the overlay to keep the ratio as if we were on + // the default resolution... + Image *rescaledOverlay = mImage->SDLgetScaledImage( + (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), + (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); + + if (rescaledOverlay) + { + // Replace the resource with the new one... + std::string idPath = mImage->getIdPath() + "_rescaled"; + ResourceManager::getInstance()->addResource(idPath, rescaledOverlay); + mImage = rescaledOverlay; + } + else + mImage->incRef(); + } + else + mImage->incRef(); } AmbientOverlay::~AmbientOverlay() @@ -66,6 +91,13 @@ void AmbientOverlay::update(int timePassed, float dx, float dy) void AmbientOverlay::draw(Graphics *graphics, int x, int y) { - graphics->drawImagePattern(mImage, + if (!mImage->isAnOpenGLOne() || !mKeepRatio) + graphics->drawImagePattern(mImage, (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY); + else + graphics->drawRescaledImagePattern(mImage, + (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY, + (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), + (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); + } diff --git a/src/resources/ambientoverlay.h b/src/resources/ambientoverlay.h index 756d0eb7..f2d2e588 100644 --- a/src/resources/ambientoverlay.h +++ b/src/resources/ambientoverlay.h @@ -35,9 +35,11 @@ class AmbientOverlay * @param parallax scroll factor based on camera position * @param speedX scrolling speed in x-direction * @param speedY scrolling speed in y-direction + * @param keepRatio rescale the image to keep + * the same ratio than in 800x600 resolution mode. */ AmbientOverlay(Image *img, float parallax, - float speedX, float speedY); + float speedX, float speedY, bool keepRatio = false); ~AmbientOverlay(); @@ -52,6 +54,7 @@ class AmbientOverlay float mPosY; /**< Current layer Y position. */ float mSpeedX; /**< Scrolling speed in X direction. */ float mSpeedY; /**< Scrolling speed in Y direction. */ + bool mKeepRatio; /**< Keep overlay ratio on every resolution */ }; #endif diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 0c542a8b..9af3059a 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -26,6 +26,7 @@ #include "log.h" #include <SDL_image.h> +#include "resources/sdlrescalefacility.h" #ifdef USE_OPENGL bool Image::mUseOpenGL = false; @@ -289,16 +290,13 @@ void Image::unload() #endif } -Image *Image::getSubImage(int x, int y, int width, int height) +bool Image::isAnOpenGLOne() const { - // Create a new clipped sub-image #ifdef USE_OPENGL - if (mUseOpenGL) - return new SubImage(this, mGLImage, x, y, width, height, - mTexWidth, mTexHeight); + return mUseOpenGL; +#else + return false; #endif - - return new SubImage(this, mImage, x, y, width, height); } void Image::setAlpha(float a) @@ -345,7 +343,7 @@ Image* Image::merge(Image *image, int x, int y) cur_pix = ((Uint32*) mImage->pixels)[current_offset]; // Retreiving each channel of the pixel using pixel format - r = (Uint8)(((surface_pix & surface_fmt->Rmask) >> + r = (Uint8)(((surface_pix & surface_fmt->Rmask) >> surface_fmt->Rshift) << surface_fmt->Rloss); g = (Uint8)(((surface_pix & surface_fmt->Gmask) >> surface_fmt->Gshift) << surface_fmt->Gloss); @@ -360,14 +358,14 @@ Image* Image::merge(Image *image, int x, int y) // new pixel with no alpha or nothing on previous pixel if (a == SDL_ALPHA_OPAQUE || (p_a == 0 && a > 0)) - ((Uint32 *)(surface->pixels))[current_offset] = + ((Uint32 *)(surface->pixels))[current_offset] = SDL_MapRGBA(current_fmt, r, g, b, a); - else if (a > 0) + else if (a > 0) { // alpha is lower => merge color with previous value f_a = (double) a / 255.0; f_ca = 1.0 - f_a; f_pa = (double) p_a / 255.0; - p_r = (Uint8)(((cur_pix & current_fmt->Rmask) >> + p_r = (Uint8)(((cur_pix & current_fmt->Rmask) >> current_fmt->Rshift) << current_fmt->Rloss); p_g = (Uint8)(((cur_pix & current_fmt->Gmask) >> current_fmt->Gshift) << current_fmt->Gloss); @@ -395,6 +393,34 @@ float Image::getAlpha() const return mAlpha; } +Image* Image::SDLgetScaledImage(int width, int height) +{ + // No scaling on incorrect new values. + if (width == 0 || height == 0) + return NULL; + + // No scaling when there is ... no different given size ... + if (width == getWidth() && height == getHeight()) + return NULL; + + Image* scaledImage = NULL; + SDL_Surface* scaledSurface = NULL; + + if (mImage) + { + scaledSurface = _SDLzoomSurface(mImage, + (double) width / getWidth(), + (double) height / getHeight(), + 1); + + // The load function takes of the SDL<->OpenGL implementation + // and about freeing the given SDL_surface*. + if (scaledSurface) + scaledImage = load(scaledSurface); + } + return scaledImage; +} + #ifdef USE_OPENGL void Image::setLoadAsOpenGL(bool useOpenGL) { @@ -420,6 +446,18 @@ int Image::powerOfTwo(int input) } #endif +Image *Image::getSubImage(int x, int y, int width, int height) +{ + // Create a new clipped sub-image +#ifdef USE_OPENGL + if (mUseOpenGL) + return new SubImage(this, mGLImage, x, y, width, height, + mTexWidth, mTexHeight); +#endif + + return new SubImage(this, mImage, x, y, width, height); +} + //============================================================================ // SubImage Class //============================================================================ @@ -469,4 +507,3 @@ Image *SubImage::getSubImage(int x, int y, int w, int h) { return mParent->getSubImage(mBounds.x + x, mBounds.y + y, w, h); } - diff --git a/src/resources/image.h b/src/resources/image.h index 4422fcc8..f497f608 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -88,6 +88,16 @@ class Image : public Resource static Image *load(SDL_Surface *); /** + * Gets an scaled instance of an image. + * + * @param width The desired width of the scaled image. + * @param height The desired height of the scaled image. + * + * @return A new Image* object. + */ + Image* SDLgetScaledImage(int width, int height); + + /** * Frees the resources created by SDL. */ virtual void unload(); @@ -105,6 +115,12 @@ class Image : public Resource { return mBounds.h; } /** + * Tells if the image was loade using OpenGL or SDL + * @return true if OpenGL, false if SDL. + */ + bool isAnOpenGLOne() const; + + /** * Creates a new image with the desired clipping rectangle. * * @return <code>NULL</code> if creation failed and a valid diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index b25f754f..900e3547 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -153,7 +153,7 @@ void ItemDB::load() ItemInfo *itemInfo = new ItemInfo; itemInfo->setId(id); itemInfo->setImageName(image); - itemInfo->setName(name.empty() ? _("Unnamed") : name); + itemInfo->setName(name.empty() ? _("unnamed") : name); itemInfo->setDescription(description); itemInfo->setType(itemTypeFromString(typeStr)); itemInfo->setView(view); diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 0b8d6c35..bc3267da 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -214,6 +214,19 @@ std::string ResourceManager::getPath(const std::string &file) return path; } +bool ResourceManager::addResource(const std::string &idPath, + Resource* resource) +{ + if (resource) + { + resource->incRef(); + resource->mIdPath = idPath; + mResources[idPath] = resource; + return true; + } + return false; +} + Resource *ResourceManager::get(const std::string &idPath, generator fun, void *data) { diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index b2ad3069..88fd60fc 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -125,6 +125,15 @@ class ResourceManager Resource *load(const std::string &path, loader fun); /** + * Adds a preformatted resource to the resource map. + * + * @param path The file name. + * @param Resource The Resource to add. + * @return true if successfull, false otherwise. + */ + bool addResource(const std::string &idPath, Resource* resource); + + /** * Copies a file from one place to another (useful for extracting * raw files from a zip archive, for example) * diff --git a/src/resources/sdlrescalefacility.cpp b/src/resources/sdlrescalefacility.cpp new file mode 100644 index 00000000..49ba8aa4 --- /dev/null +++ b/src/resources/sdlrescalefacility.cpp @@ -0,0 +1,489 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the Low GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Source code taken from: + * + * SDL_rotozoom - rotozoomer + * + * LGPL (c) A. Schiffler + * + */ + +#include "sdlrescalefacility.h" + +#define VALUE_LIMIT 0.001 + +typedef struct tColorRGBA { + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 a; +} tColorRGBA; + +void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, + int *dstwidth, int *dstheight) +{ + /* + * Sanity check zoom factors + */ + if (zoomx < VALUE_LIMIT) { + zoomx = VALUE_LIMIT; + } + if (zoomy < VALUE_LIMIT) { + zoomy = VALUE_LIMIT; + } + + /* + * Calculate target size + */ + *dstwidth = (int) ((double) width * zoomx); + *dstheight = (int) ((double) height * zoomy); + if (*dstwidth < 1) { + *dstwidth = 1; + } + if (*dstheight < 1) { + *dstheight = 1; + } +} + +int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface * dst, + int flipx, int flipy, int smooth) +{ + int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly; + tColorRGBA *c00, *c01, *c10, *c11, *cswap; + tColorRGBA *sp, *csp, *dp; + int dgap; + + /* + * Variable setup + */ + if (smooth) { + /* + * For interpolation: assume source dimension is one pixel + */ + /* + * smaller to avoid overflow on right and bottom edge. + */ + sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); + sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); + } else { + sx = (int) (65536.0 * (float) src->w / (float) dst->w); + sy = (int) (65536.0 * (float) src->h / (float) dst->h); + } + + /* + * Allocate memory for row increments + */ + if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { + return (-1); + } + if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { + free(sax); + return (-1); + } + + /* + * Precalculate row increments + */ + sp = csp = (tColorRGBA *) src->pixels; + dp = (tColorRGBA *) dst->pixels; + + if (flipx) csp += (src->w-1); + if (flipy) csp += (src->pitch*(src->h-1)); + + csx = 0; + csax = sax; + for (x = 0; x <= dst->w; x++) { + *csax = csx; + csax++; + csx &= 0xffff; + csx += sx; + } + csy = 0; + csay = say; + for (y = 0; y <= dst->h; y++) { + *csay = csy; + csay++; + csy &= 0xffff; + csy += sy; + } + + dgap = dst->pitch - dst->w * 4; + + /* + * Switch between interpolating and non-interpolating code + */ + if (smooth) { + + /* + * Interpolating Zoom + */ + + /* + * Scan destination + */ + ly = 0; + csay = say; + for (y = 0; y < dst->h; y++) { + /* + * Setup color source pointers + */ + c00 = csp; + c01 = csp; + c01++; + c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch); + c11 = c10; + c11++; + csax = sax; + if (flipx) { + cswap = c00; c00=c01; c01=cswap; + cswap = c10; c10=c11; c11=cswap; + } + if (flipy) { + cswap = c00; c00=c10; c10=cswap; + cswap = c01; c01=c11; c11=cswap; + } + lx = 0; + for (x = 0; x < dst->w; x++) { + /* + * Interpolate colors + */ + ex = (*csax & 0xffff); + ey = (*csay & 0xffff); + t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; + t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; + dp->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; + t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; + dp->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; + t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; + dp->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; + t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; + dp->a = (((t2 - t1) * ey) >> 16) + t1; + + /* + * Advance source pointers + */ + csax++; + sstep = (*csax >> 16); + lx += sstep; + if (lx >= src->w) sstep = 0; + if (flipx) sstep = -sstep; + c00 += sstep; + c01 += sstep; + c10 += sstep; + c11 += sstep; + /* + * Advance destination pointer + */ + dp++; + } + /* + * Advance source pointer + */ + csay++; + sstep = (*csay >> 16); + ly += sstep; + if (ly >= src->h) sstep = 0; + sstep *= src->pitch; + if (flipy) sstep = -sstep; + csp = (tColorRGBA *) ((Uint8 *) csp + sstep); + + /* + * Advance destination pointers + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + } else { + + /* + * Non-Interpolating Zoom + */ + + csay = say; + for (y = 0; y < dst->h; y++) { + sp = csp; + csax = sax; + for (x = 0; x < dst->w; x++) { + /* + * Draw + */ + *dp = *sp; + /* + * Advance source pointers + */ + csax++; + sstep = (*csax >> 16); + if (flipx) sstep = -sstep; + sp += sstep; + /* + * Advance destination pointer + */ + dp++; + } + /* + * Advance source pointer + */ + csay++; + sstep = (*csay >> 16) * src->pitch; + if (flipy) sstep = -sstep; + csp = (tColorRGBA *) ((Uint8 *) csp + sstep); + + /* + * Advance destination pointers + */ + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + + + +int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy) +{ + int x, y; + Uint32 sx, sy, *sax, *say, *csax, *csay, csx, csy, sstep; + Uint8 *sp, *dp, *csp; + int dgap; + + /* + * Variable setup + */ + sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w); + sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h); + + + /* + * Allocate memory for row increments + */ + if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { + return (-1); + } + if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { + free(sax); + return (-1); + } + + /* + * Pointer setup + */ + sp = csp = (Uint8 *) src->pixels; + dp = (Uint8 *) dst->pixels; + dgap = dst->pitch - dst->w; + + if (flipx) csp += (src->w-1); + if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) ); + + /* + * Precalculate row increments + */ + csx = 0; + csax = sax; + for (x = 0; x <= dst->w; x++) { + *csax = csx; + csax++; + csx &= 0xffff; + csx += sx; + } + csy = 0; + csay = say; + for (y = 0; y <= dst->h; y++) { + *csay = csy; + csay++; + csy &= 0xffff; + csy += sy; + } + + + /* + * Draw + */ + csay = say; + for (y = 0; y < dst->h; y++) { + csax = sax; + sp = csp; + for (x = 0; x < dst->w; x++) { + /* + * Draw + */ + *dp = *sp; + /* + * Advance source pointers + */ + csax++; + sstep = (*csax >> 16); + if (flipx) sstep = -sstep; + sp += sstep; + /* + * Advance destination pointer + */ + dp++; + } + /* + * Advance source pointer (for row) + */ + csay++; + sstep = (*csay >> 16) * src->pitch; + if (flipy) sstep = -sstep; + csp = ((Uint8 *) csp + sstep); + + /* + * Advance destination pointers + */ + dp += dgap; + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + + + +SDL_Surface *_SDLzoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) +{ + SDL_Surface *rz_src; + SDL_Surface *rz_dst; + int dstwidth, dstheight; + int is32bit; + int i, src_converted; + int flipx, flipy; + + /* + * Sanity check + */ + if (src == NULL) + return (NULL); + + /* + * Determine if source surface is 32bit or 8bit + */ + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) { + /* + * Use source surface 'as is' + */ + rz_src = src; + src_converted = 0; + } else { + /* + * New source surface is 32bit with a defined RGBA ordering + */ + rz_src = + SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + SDL_BlitSurface(src, NULL, rz_src, NULL); + src_converted = 1; + is32bit = 1; + } + + flipx = (zoomx<0.0); + if (flipx) zoomx = -zoomx; + flipy = (zoomy<0.0); + if (flipy) zoomy = -zoomy; + + /* Get size if target */ + zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); + + /* + * Alloc space to completely contain the zoomed surface + */ + rz_dst = NULL; + if (is32bit) { + /* + * Target surface is 32bit with source RGBA/ABGR ordering + */ + rz_dst = + SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, + rz_src->format->Rmask, rz_src->format->Gmask, + rz_src->format->Bmask, rz_src->format->Amask); + } else { + /* + * Target surface is 8bit + */ + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); + } + + /* + * Lock source surface + */ + SDL_LockSurface(rz_src); + /* + * Check which kind of surface we have + */ + if (is32bit) { + /* + * Call the 32bit transformation routine to do the zooming (using alpha) + */ + zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); + /* + * Turn on source-alpha support + */ + SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); + } else { + /* + * Copy palette and colorkey info + */ + for (i = 0; i < rz_src->format->palette->ncolors; i++) { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + /* + * Call the 8bit transformation routine to do the zooming + */ + zoomSurfaceY(rz_src, rz_dst, flipx, flipy); + SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); + } + /* + * Unlock source surface + */ + SDL_UnlockSurface(rz_src); + + /* + * Cleanup temp surface + */ + if (src_converted) { + SDL_FreeSurface(rz_src); + } + + /* + * Return destination surface + */ + return (rz_dst); +} diff --git a/src/resources/sdlrescalefacility.h b/src/resources/sdlrescalefacility.h new file mode 100644 index 00000000..971f5d73 --- /dev/null +++ b/src/resources/sdlrescalefacility.h @@ -0,0 +1,52 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the Low GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Source code taken from: + * + * SDL_rotozoom - rotozoomer + * + * LGPL (c) A. Schiffler + * + */ + +#ifndef SDLRESCALEFACILITY_H +#define SDLRESCALEFACILITY_H + +#include <SDL.h> +#include "image.h" + +/** + * _SDLzoomSurface is internally used by Image::getScaledImage() to provide + * a rescaled copy of its internal mImage member. + * + * @see Image::getScaledImage() for more details + * + * @param src the original surface to rescale + * @param zoomx the zoom factor used to rescale the surface horizontally. 1.0 doesn't rescale. + * A value lesser than 1.O shrink the image. + * @param zoomy the zoom factor used to rescale the surface vertically. + * @param smooth transform the scaled surface into a 32bit aliased image to smooth the rescaling. + * + * @return SDL_Surface The rescaled surface. + */ + +SDL_Surface *_SDLzoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth); + +#endif |