diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2009-01-05 00:39:57 +0100 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2009-01-05 00:40:42 +0100 |
commit | 550a02997572b5d090b436b7c05d19c1823556a9 (patch) | |
tree | 65b6bf872711d67d1ed2b7e530bd47cb88a155af /src | |
parent | 8b6bfeb0a70d4f97cc2d20ce04fc240b65082cf1 (diff) | |
parent | 91387e410c9f9ea16c5b41bd1cc576cbd85cf835 (diff) | |
download | mana-550a02997572b5d090b436b7c05d19c1823556a9.tar.gz mana-550a02997572b5d090b436b7c05d19c1823556a9.tar.bz2 mana-550a02997572b5d090b436b7c05d19c1823556a9.tar.xz mana-550a02997572b5d090b436b7c05d19c1823556a9.zip |
Merged with 'master'
Diffstat (limited to 'src')
86 files changed, 1245 insertions, 1221 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 43988ea6..60eaff74 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,8 +77,6 @@ SET(SRCS gui/changeemaildialog.h gui/changepassworddialog.cpp gui/changepassworddialog.h - gui/chargedialog.cpp - gui/chargedialog.h gui/char_select.cpp gui/char_select.h gui/chat.cpp @@ -138,8 +136,6 @@ SET(SRCS gui/minimap.h gui/ministatus.cpp gui/ministatus.h - gui/newskill.cpp - gui/newskill.h gui/npclistdialog.cpp gui/npclistdialog.h gui/npcpostdialog.cpp diff --git a/src/Makefile.am b/src/Makefile.am index e953507a..6acf9d18 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,8 +29,6 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ gui/changeemaildialog.h \ gui/changepassworddialog.cpp \ gui/changepassworddialog.h \ - gui/chargedialog.cpp \ - gui/chargedialog.h \ gui/char_select.cpp \ gui/char_select.h \ gui/chat.cpp \ @@ -90,8 +88,6 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ gui/minimap.h \ gui/ministatus.cpp \ gui/ministatus.h \ - gui/newskill.cpp \ - gui/newskill.h \ gui/npclistdialog.cpp \ gui/npclistdialog.h \ gui/npcpostdialog.cpp \ @@ -282,6 +278,7 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ utils/strprintf.cpp \ utils/tostring.h \ utils/trim.h \ + utils/mutex.h \ utils/xml.cpp \ utils/xml.h \ animatedsprite.cpp \ diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index b2bb1f28..203a82af 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -56,7 +56,8 @@ AnimatedSprite *AnimatedSprite::load(const std::string& filename, int variant) { ResourceManager *resman = ResourceManager::getInstance(); SpriteDef *s = resman->getSprite(filename, variant); - if (!s) return NULL; + if (!s) + return NULL; AnimatedSprite *as = new AnimatedSprite(s); s->decRef(); return as; @@ -67,22 +68,18 @@ AnimatedSprite::~AnimatedSprite() mSprite->decRef(); } -void -AnimatedSprite::reset() +void AnimatedSprite::reset() { mFrameIndex = 0; mFrameTime = 0; mLastTime = 0; } -void -AnimatedSprite::play(SpriteAction spriteAction) +void AnimatedSprite::play(SpriteAction spriteAction) { Action *action = mSprite->getAction(spriteAction); if (!action) - { return; - } mAction = action; Animation *animation = mAction->getAnimation(mDirection); @@ -96,20 +93,15 @@ AnimatedSprite::play(SpriteAction spriteAction) } } -void -AnimatedSprite::update(int time) +void AnimatedSprite::update(int time) { // Avoid freaking out at first frame or when tick_time overflows if (time < mLastTime || mLastTime == 0) - { mLastTime = time; - } // If not enough time has passed yet, do nothing if (time <= mLastTime || !mAnimation) - { return; - } unsigned int dt = time - mLastTime; mLastTime = time; @@ -121,13 +113,10 @@ AnimatedSprite::update(int time) } } -bool -AnimatedSprite::updateCurrentAnimation(unsigned int time) +bool AnimatedSprite::updateCurrentAnimation(unsigned int time) { if (!mFrame || Animation::isTerminator(*mFrame)) - { return false; - } mFrameTime += time; @@ -137,9 +126,7 @@ AnimatedSprite::updateCurrentAnimation(unsigned int time) mFrameIndex++; if (mFrameIndex == mAnimation->getLength()) - { mFrameIndex = 0; - } mFrame = mAnimation->getFrame(mFrameIndex); @@ -154,8 +141,7 @@ AnimatedSprite::updateCurrentAnimation(unsigned int time) return true; } -bool -AnimatedSprite::draw(Graphics* graphics, int posX, int posY) const +bool AnimatedSprite::draw(Graphics* graphics, int posX, int posY) const { if (!mFrame || !mFrame->image) return false; @@ -165,8 +151,7 @@ AnimatedSprite::draw(Graphics* graphics, int posX, int posY) const posY + mFrame->offsetY); } -void -AnimatedSprite::setDirection(SpriteDirection direction) +void AnimatedSprite::setDirection(SpriteDirection direction) { if (mDirection != direction) { diff --git a/src/animatedsprite.h b/src/animatedsprite.h index 405bf42e..41857d8f 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -50,7 +50,8 @@ class AnimatedSprite * @param filename the file of the sprite to animate * @param variant the sprite variant */ - static AnimatedSprite *load(std::string const &filename, int variant = 0); + static AnimatedSprite *load(const std::string &filename, + int variant = 0); /** * Destructor. @@ -60,50 +61,42 @@ class AnimatedSprite /** * Resets the animated sprite. */ - void - reset(); + void reset(); /** * Plays an action using the current direction */ - void - play(SpriteAction action); + void play(SpriteAction action); /** * Inform the animation of the passed time so that it can output the * correct animation frame. */ - void - update(int time); + void update(int time); /** * Draw the current animation frame at the coordinates given in screen * pixels. */ - bool - draw(Graphics* graphics, int posX, int posY) const; + bool draw(Graphics* graphics, int posX, int posY) const; /** * gets the width in pixels of the image of the current frame */ - int - getWidth() const; + int getWidth() const; /** * gets the height in pixels of the image of the current frame */ - int - getHeight() const; + int getHeight() const; /** * Sets the direction. */ - void - setDirection(SpriteDirection direction); + void setDirection(SpriteDirection direction); private: - bool - updateCurrentAnimation(unsigned int dt); + bool updateCurrentAnimation(unsigned int dt); SpriteDirection mDirection; /**< The sprite direction. */ int mLastTime; /**< The last time update was called. */ diff --git a/src/being.cpp b/src/being.cpp index a267d033..d32ffa59 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -18,6 +18,7 @@ * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include "being.h" #include <cassert> @@ -30,7 +31,10 @@ #include "log.h" #include "map.h" #include "particle.h" +#include "sound.h" +#include "localplayer.h" +#include "resources/itemdb.h" #include "resources/resourcemanager.h" #include "resources/imageset.h" #include "resources/iteminfo.h" @@ -40,11 +44,18 @@ #include "utils/dtor.h" #include "utils/tostring.h" +#include "utils/xml.h" namespace { const bool debug_movement = true; } +#define HAIR_FILE "hair.xml" + +#include "utils/xml.h" + +#define BEING_EFFECTS_FILE "effects.xml" + int Being::instances = 0; ImageSet *Being::emotionSet = NULL; @@ -57,6 +68,9 @@ Being::Being(int id, int job, Map *map): mSpriteDirection(DIRECTION_DOWN), mDirection(DOWN), mMap(NULL), mEquippedWeapon(NULL), + mHairStyle(0), + mHairColor(0), + mGender(GENDER_UNSPECIFIED), mSpeechTime(0), mSprites(VECTOREND_SPRITE, NULL), mSpriteIDs(VECTOREND_SPRITE, 0), @@ -108,6 +122,7 @@ void Being::setPosition(const Vector &pos) { mPos = pos; mDest = pos; + mPath.clear(); } void Being::adjustCourse(int srcX, int srcY, int dstX, int dstY) @@ -286,6 +301,12 @@ void Being::setPath(const Path &path) mPath = path; } +void Being::setHairStyle(int style, int color) +{ + mHairStyle = style < 0 ? mHairStyle : style % getHairStylesNr(); + mHairColor = color < 0 ? mHairColor : color % getHairColorsNr(); +} + void Being::setSprite(int slot, int id, const std::string &color) { assert(slot >= BASE_SPRITE && slot < VECTOREND_SPRITE); @@ -512,7 +533,7 @@ void Being::logic() i != mChildParticleEffects.end();) { (*i)->setPosition(mPos.x, mPos.y); - if (!(*i)->isAlive()) + if ((*i)->isExtinct()) { (*i)->kill(); i = mChildParticleEffects.erase(i); @@ -596,3 +617,184 @@ int Being::getHeight() const return 0; } } + + + + +static int hairStylesNr; +static int hairColorsNr; +static std::vector<std::string> hairColors; + +static void +initializeHair(void); + +int +Being::getHairStylesNr(void) +{ + initializeHair(); + return hairStylesNr; +} + +int +Being::getHairColorsNr(void) +{ + initializeHair(); + return hairColorsNr; +} + +std::string +Being::getHairColor(int index) +{ + initializeHair(); + if (index < 0 || index >= hairColorsNr) + return "#000000"; + + return hairColors[index]; +} + +static bool hairInitialized = false; + +static void +initializeHair(void) +{ + if (hairInitialized) + return; + + // Hairstyles are encoded as negative numbers. Count how far negative we can go. + int hairstylesCtr = -1; + while (ItemDB::get(hairstylesCtr).getSprite(GENDER_MALE) != "error.xml") + --hairstylesCtr; + + hairStylesNr = -hairstylesCtr; // done. + if (hairStylesNr == 0) + hairStylesNr = 1; // No hair style -> no hair + + hairColorsNr = 0; + + XML::Document doc(HAIR_FILE); + xmlNodePtr root = doc.rootNode(); + + if (!root || !xmlStrEqual(root->name, BAD_CAST "colors")) + { + logger->log("Error loading being hair configuration file"); + } else { + for_each_xml_child_node(node, root) + { + if (xmlStrEqual(node->name, BAD_CAST "color")) + { + int index = atoi(XML::getProperty(node, "id", "-1").c_str()); + std::string value = XML::getProperty(node, "value", ""); + + if (index >= 0 && value != "") { + if (index >= hairColorsNr) { + hairColorsNr = index + 1; + hairColors.resize(hairColorsNr, "#000000"); + } + hairColors[index] = value; + } + } + } + } // done initializing + + if (hairColorsNr == 0) { // No colours -> black only + hairColorsNr = 1; + hairColors.resize(hairColorsNr, "#000000"); + } + + hairInitialized = 1; +} + + + +struct EffectDescription { + std::string mGFXEffect; + std::string mSFXEffect; +}; + +static EffectDescription *default_effect = NULL; +static std::map<int, EffectDescription *> effects; +static bool effects_initialized = false; + +static EffectDescription * +getEffectDescription(xmlNodePtr node, int *id) +{ + EffectDescription *ed = new EffectDescription; + + *id = atoi(XML::getProperty(node, "id", "-1").c_str()); + ed->mSFXEffect = XML::getProperty(node, "audio", ""); + ed->mGFXEffect = XML::getProperty(node, "particle", ""); + + return ed; +} + +static EffectDescription * +getEffectDescription(int effectId) +{ + if (!effects_initialized) + { + XML::Document doc(BEING_EFFECTS_FILE); + xmlNodePtr root = doc.rootNode(); + + if (!root || !xmlStrEqual(root->name, BAD_CAST "being-effects")) + { + logger->log("Error loading being effects file: " + BEING_EFFECTS_FILE); + return NULL; + } + + for_each_xml_child_node(node, root) + { + int id; + + if (xmlStrEqual(node->name, BAD_CAST "effect")) + { + EffectDescription *EffectDescription = + getEffectDescription(node, &id); + effects[id] = EffectDescription; + } else if (xmlStrEqual(node->name, BAD_CAST "default")) + { + EffectDescription *EffectDescription = + getEffectDescription(node, &id); + + if (default_effect) + delete default_effect; + + default_effect = EffectDescription; + } + } + + effects_initialized = true; + } // done initializing + + EffectDescription *ed = effects[effectId]; + + if (!ed) + return default_effect; + else + return ed; +} + +void +Being::internalTriggerEffect(int effectId, bool sfx, bool gfx) +{ + logger->log("Special effect #%d on %s", effectId, + getId() == player_node->getId() ? "self" : "other"); + + EffectDescription *ed = getEffectDescription(effectId); + + if (!ed) { + logger->log("Unknown special effect and no default recorded"); + return; + } + + if (gfx && ed->mGFXEffect != "") { + Particle *selfFX; + + selfFX = particleEngine->addEffect(ed->mGFXEffect, 0, 0); + controlParticle(selfFX); + } + + if (sfx && ed->mSFXEffect != "") { + sound.playSfx(ed->mSFXEffect); + } +} diff --git a/src/being.h b/src/being.h index bf11e3ed..aeb03564 100644 --- a/src/being.h +++ b/src/being.h @@ -33,9 +33,6 @@ #include "animatedsprite.h" #include "vector.h" -#define NR_HAIR_STYLES 8 -#define NR_HAIR_COLORS 10 - class AnimatedSprite; class Equipment; class ItemInfo; @@ -46,6 +43,12 @@ class ImageSet; class Particle; class SpeechBubble; +enum Gender { + GENDER_MALE = 0, + GENDER_FEMALE = 1, + GENDER_UNSPECIFIED = 2 +}; + class Being : public Sprite { public: @@ -127,14 +130,14 @@ class Being : public Sprite const Vector &getDestination() const { return mDest; } /** - * Adjusts course to expected stat point. + * Adjusts course to expected start point. */ - void adjustCourse(int, int); + void adjustCourse(int srcX, int srcY); /** * Adjusts course to expected start and end points. */ - void adjustCourse(int, int, int, int); + void adjustCourse(int srcX, int srcY, int destX, int destY); /** * Puts a "speech balloon" above this being for the specified amount @@ -150,58 +153,78 @@ class Being : public Sprite * * @param amount The amount of damage. */ - virtual void - takeDamage(int amount); + virtual void takeDamage(int amount); /** * Handles an attack of another being by this being. */ - virtual void - handleAttack(); + virtual void handleAttack(); /** * Returns the name of the being. */ - const std::string& - getName() const { return mName; } + const std::string &getName() const + { return mName; } /** * Sets the name for the being. * * @param name The name that should appear. */ - void - setName(const std::string &name) { mName = name; } + void setName(const std::string &name) { mName = name; } + + /** + * Sets the gender for this being. + */ + virtual void setGender(Gender gender) { mGender = gender; } + + /** + * Gets the hair color for this being. + */ + int getHairColor() const + { return mHairColor; } + + /** + * Gets the hair style for this being. + */ + int getHairStyle() const + { return mHairStyle; } + + /** + * Sets the hair style and color for this being. + * + * NOTE: This method was necessary for convenience in the 0.0 client. + * It should be removed here since the server can provide the hair ID + * and coloring the same way it does for other equipment pieces. Then + * Being::setSprite can be used instead. + */ + virtual void setHairStyle(int style, int color); /** * Sets visible equipments for this being. */ - virtual void - setSprite(int slot, int id, const std::string &color = ""); + virtual void setSprite(int slot, int id, + const std::string &color = ""); /** * Performs being logic. */ - virtual void - logic(); + virtual void logic(); /** * Draws the speech text above the being. */ - void - drawSpeech(Graphics* graphics, int offsetX, int offsetY); + void drawSpeech(Graphics* graphics, int offsetX, int offsetY); /** * Draws the emotion picture above the being. */ - void - drawEmotion(Graphics *graphics, int offsetX, int offsetY); + void drawEmotion(Graphics *graphics, int offsetX, int offsetY); /** * Draws the name text below the being. */ - virtual void - drawName(Graphics *, int, int) {}; + virtual void drawName(Graphics *, int, int) {}; /** * Returns the type of the being. @@ -222,14 +245,12 @@ class Being : public Sprite /** * Gets the being id. */ - Uint16 - getId() const { return mId; } + Uint16 getId() const { return mId; } /** * Sets the sprite id. */ - void - setId(Uint16 id) { mId = id; } + void setId(Uint16 id) { mId = id; } /** * Sets the map the being is on @@ -239,8 +260,7 @@ class Being : public Sprite /** * Sets the current action. */ - virtual void - setAction(Action action, int attackType = 0); + virtual void setAction(Action action, int attackType = 0); /** * Gets the current action. @@ -278,7 +298,8 @@ class Being : public Sprite int getPixelY() const { return (int) mPos.y; } /** - * Sets the position of this being. + * Sets the position of this being. When the being was walking, it also + * clears the destination and the path. */ void setPosition(const Vector &pos); @@ -330,6 +351,22 @@ class Being : public Sprite */ const Path &getPath() const { return mPath; } + /** + * Triggers a visual effect, such as `level up' + * + * Only draws the visual effect, does not play sound effects + * + * \param effectId ID of the effect to trigger + */ + virtual void + triggerEffect(int effectId) { internalTriggerEffect(effectId, false, true); } + + static int getHairColorsNr(void); + + static int getHairStylesNr(void); + + static std::string getHairColor(int index); + protected: /** * Sets the new path for this being. @@ -342,6 +379,16 @@ class Being : public Sprite virtual Map::BlockType getBlockType() const { return Map::BLOCKTYPE_NONE; } + /** + * Trigger visual effect, with components + * + * \param effectId ID of the effect to trigger + * \param sfx Whether to trigger sound effects + * \param gfx Whether to trigger graphical effects + */ + void + internalTriggerEffect(int effectId, bool sfx, bool gfx); + Uint16 mId; /**< Unique being id */ Uint8 mSpriteDirection; /**< Facing direction */ Uint8 mDirection; /**< Walking direction */ @@ -353,6 +400,9 @@ class Being : public Sprite Path mPath; std::string mSpeech; + int mHairStyle; + int mHairColor; + Gender mGender; Uint32 mSpeechTime; std::vector<AnimatedSprite*> mSprites; diff --git a/src/channelmanager.cpp b/src/channelmanager.cpp index a332edbb..2a3f4eff 100644 --- a/src/channelmanager.cpp +++ b/src/channelmanager.cpp @@ -19,8 +19,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <list> - #include "channelmanager.h" #include "channel.h" @@ -28,7 +26,6 @@ ChannelManager::ChannelManager() { - } ChannelManager::~ChannelManager() @@ -37,39 +34,43 @@ ChannelManager::~ChannelManager() mChannels.clear(); } -Channel* ChannelManager::findById(int id) +Channel *ChannelManager::findById(int id) const { - Channel* channel; - for(std::list<Channel*>::iterator itr = mChannels.begin(); - itr != mChannels.end(); - itr++) + Channel *channel = 0; + for (std::list<Channel*>::const_iterator itr = mChannels.begin(), + end = mChannels.end(); + itr != end; + itr++) { - channel = (*itr); - if(channel->getId() == id) + Channel *c = (*itr); + if (channel->getId() == id) { - return channel; + channel = c; + break; } } - return NULL; + return channel; } -Channel *ChannelManager::findByName(std::string const &name) +Channel *ChannelManager::findByName(const std::string &name) const { - Channel* channel; - if(name != "") + Channel *channel = 0; + if (!name.empty()) { - for(std::list<Channel*>::iterator itr = mChannels.begin(); - itr != mChannels.end(); - itr++) + for (std::list<Channel*>::const_iterator itr = mChannels.begin(), + end = mChannels.end(); + itr != end; + itr++) { - channel = (*itr); - if(channel->getName() == name) + Channel *c = (*itr); + if (c->getName() == name) { - return channel; + channel = c; + break; } } } - return NULL; + return channel; } void ChannelManager::addChannel(Channel *channel) diff --git a/src/channelmanager.h b/src/channelmanager.h index c19c548a..e42a5960 100644 --- a/src/channelmanager.h +++ b/src/channelmanager.h @@ -32,10 +32,13 @@ class ChannelManager public: ChannelManager(); ~ChannelManager(); - Channel* findById(int id); - Channel *findByName(std::string const &name); + + Channel *findById(int id) const; + Channel *findByName(const std::string &name) const; + void addChannel(Channel *channel); void removeChannel(Channel *channel); + private: std::list<Channel*> mChannels; }; diff --git a/src/engine.cpp b/src/engine.cpp index ba5ce5e3..f191280e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -89,17 +89,12 @@ void Engine::changeMap(const std::string &mapPath) if (newMap->hasProperty("minimap")) { mapImage = resman->getImage(newMap->getProperty("minimap")); - - // Set the title for the Minimap - if (newMap->hasProperty("mapname")) - { - minimap->setCaption(newMap->getProperty("mapname")); - } - else - { - minimap->setCaption("Unknown"); - logger->log("WARNING: Map file '%s' defines a minimap image but does not define a 'mapname' property", map_path.c_str()); - } + } + if (newMap->hasProperty("name")) + { + minimap->setCaption(newMap->getProperty("name")); + } else { + minimap->setCaption("Map"); } minimap->setMapImage(mapImage); beingManager->setMap(newMap); @@ -124,6 +119,7 @@ void Engine::changeMap(const std::string &mapPath) } mCurrentMap = newMap; + mMapName = mapPath; } void Engine::logic() diff --git a/src/engine.h b/src/engine.h index dbee1258..f676a271 100644 --- a/src/engine.h +++ b/src/engine.h @@ -23,6 +23,7 @@ #define _ENGINE_H #include <iosfwd> +#include <string> class Map; @@ -48,6 +49,9 @@ class Engine */ Map *getCurrentMap() { return mCurrentMap; } + const std::string &getCurrentMapName() { return mMapName; } + + /** * Sets the currently active map. */ @@ -60,6 +64,7 @@ class Engine private: Map *mCurrentMap; + std::string mMapName; }; extern Engine *engine; diff --git a/src/game.cpp b/src/game.cpp index 8ea0d420..942c517c 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -47,7 +47,6 @@ #include "gui/buddywindow.h" #include "gui/buy.h" #include "gui/buysell.h" -//#include "gui/chargedialog.h" #include "gui/chat.h" #include "gui/confirm_dialog.h" #include "gui/debugwindow.h" @@ -120,11 +119,9 @@ NpcTextDialog *npcTextDialog; NpcPostDialog *npcPostDialog; SkillDialog *skillDialog; MagicDialog *magicDialog; -//NewSkillDialog *newSkillWindow; Setup* setupWindow; Minimap *minimap; EquipmentWindow *equipmentWindow; -//ChargeDialog *chargeDialog; TradeWindow *tradeWindow; BuddyWindow *buddyWindow; GuildWindow *guildWindow; @@ -208,11 +205,9 @@ void createGuiWindows() npcPostDialog = new NpcPostDialog(); skillDialog = new SkillDialog(); magicDialog = new MagicDialog(); - //newSkillWindow = new NewSkillDialog(); setupWindow = new Setup(); minimap = new Minimap(); equipmentWindow = new EquipmentWindow(player_node->mEquipment.get()); - //chargeDialog = new ChargeDialog(); tradeWindow = new TradeWindow; buddyWindow = new BuddyWindow(); guildWindow = new GuildWindow(); @@ -222,17 +217,21 @@ void createGuiWindows() partyWindow = new PartyWindow(); // Initialize window positions - //chargeDialog->setPosition( - // graphics->getWidth() - 5 - chargeDialog->getWidth(), - // graphics->getHeight() - chargeDialog->getHeight() - 15); - //buddyWindow->setPosition(10, minimap->getHeight() + 30); // Set initial window visibility - chatWindow->setVisible(true); - miniStatusWindow->setVisible(true); - menuWindow->setVisible(true); - itemShortcutWindow->setVisible(true); + chatWindow->setVisible((bool) config.getValue( + chatWindow->getWindowName() + "Visible", true)); + miniStatusWindow->setVisible((bool) config.getValue( + miniStatusWindow->getWindowName() + "Visible", + true)); + buyDialog->setVisible(false); + sellDialog->setVisible(false); + tradeWindow->setVisible(false); + menuWindow->setVisible((bool) config.getValue( + menuWindow->getWindowName() + "Visible", true)); + itemShortcutWindow->setVisible((bool) config.getValue( + itemShortcutWindow->getWindowName() + "Visible", true)); if (config.getValue("logToChat", 0)) { @@ -261,8 +260,6 @@ void destroyGuiWindows() delete setupWindow; delete minimap; delete equipmentWindow; - //delete chargeDialog; - //delete newSkillWindow; delete tradeWindow; delete buddyWindow; delete guildWindow; @@ -316,9 +313,7 @@ Game::Game(): // TODO: The user should be able to choose which one to use // Open the first device if (Joystick::getNumberOfJoysticks() > 0) - { joystick = new Joystick(0); - } Net::registerHandler(mBeingHandler.get()); Net::registerHandler(mBuySellHandler.get()); @@ -358,11 +353,14 @@ Game::~Game() SDL_RemoveTimer(mSecondsCounterId); } -bool saveScreenshot(SDL_Surface *screenshot) +static bool saveScreenshot() { static unsigned int screenshotCount = 0; + SDL_Surface *screenshot = graphics->getScreenshot(); + // Search for an unused screenshot name + std::stringstream filenameSuffix; std::stringstream filename; std::fstream testExists; bool found = false; @@ -370,29 +368,37 @@ bool saveScreenshot(SDL_Surface *screenshot) do { screenshotCount++; filename.str(""); + filenameSuffix.str(""); + filename << PHYSFS_getUserDir(); #if (defined __USE_UNIX98 || defined __FreeBSD__) - filename << PHYSFS_getUserDir() << ".tmw/"; + filenameSuffix << ".tmw/"; #elif defined __APPLE__ - filename << PHYSFS_getUserDir() << "Desktop/"; + filenameSuffix << "Desktop/"; #endif - filename << "TMW_Screenshot_" << screenshotCount << ".png"; + filenameSuffix << "TMW_Screenshot_" << screenshotCount << ".png"; + filename << filenameSuffix.str(); testExists.open(filename.str().c_str(), std::ios::in); found = !testExists.is_open(); testExists.close(); } while (!found); - if (ImageWriter::writePNG(screenshot, filename.str())) + const bool success = ImageWriter::writePNG(screenshot, filename.str()); + + if (success) { std::stringstream chatlogentry; - chatlogentry << "Screenshot saved to " << filename.str().c_str(); + chatlogentry << "Screenshot saved to ~/" << filenameSuffix.str(); chatWindow->chatLog(chatlogentry.str(), BY_SERVER); - return true; } else { chatWindow->chatLog("Saving screenshot failed!", BY_SERVER); - return false; + logger->log("Error: could not save screenshot."); } + + SDL_FreeSurface(screenshot); + + return success; } void Game::optionChanged(const std::string &name) @@ -462,9 +468,9 @@ void Game::logic() { if (!disconnectedDialog) { - disconnectedDialog = new - OkDialog("Network Error", - "The connection to the server was lost, the program will now quit"); + disconnectedDialog = new OkDialog("Network Error", + "The connection to the server was lost, " + "the program will now quit"); disconnectedDialog->addActionListener(&exitListener); disconnectedDialog->requestMoveToTop(); } @@ -474,10 +480,8 @@ void Game::logic() void Game::handleInput() { - if (joystick != NULL) - { + if (joystick) joystick->update(); - } // Events SDL_Event event; @@ -530,17 +534,6 @@ void Game::handleInput() used = true; break; - case SDLK_F2: requestedWindow = statusWindow; break; - case SDLK_F3: requestedWindow = inventoryWindow; break; - case SDLK_F4: requestedWindow = equipmentWindow; break; - case SDLK_F5: requestedWindow = skillDialog; break; - case SDLK_F6: requestedWindow = minimap; break; - case SDLK_F7: requestedWindow = chatWindow; break; - case SDLK_F8: requestedWindow = itemShortcutWindow; break; - case SDLK_F9: requestedWindow = setupWindow; break; - case SDLK_F10: requestedWindow = debugWindow; break; - //case SDLK_F11: requestedWindow = newSkillWindow; break; - case SDLK_RETURN: // Input chat window if (chatWindow->isInputFocused() || @@ -564,10 +557,12 @@ void Game::handleInput() { setupWindow->action(gcn::ActionEvent(NULL, "cancel")); } -/* else if (guildWindow->isVisible()) + /* + else if (guildWindow->isVisible()) { // TODO: Check if a dialog is open and close it if so - }*/ + } + */ // Else, open the chat edit box else { @@ -596,15 +591,19 @@ void Game::handleInput() && !guildWindow->isWindowFocused()) { const int tKey = keyboard.getKeyIndex(event.key.keysym.sym); - // Checks if any item shortcut is pressed. - for (int i = KeyboardConfig::KEY_SHORTCUT_0; - i <= KeyboardConfig::KEY_SHORTCUT_9; - i++) + // Do not activate shortcuts if tradewindow is visible + if (!tradeWindow->isVisible()) { - if (tKey == i) { - itemShortcut->useItem( - i - KeyboardConfig::KEY_SHORTCUT_0); - break; + // Checks if any item shortcut is pressed. + for (int i = KeyboardConfig::KEY_SHORTCUT_0; + i <= KeyboardConfig::KEY_SHORTCUT_9; + i++) + { + if (tKey == i && !used) { + itemShortcut->useItem( + i - KeyboardConfig::KEY_SHORTCUT_0); + break; + } } } switch (tKey) { @@ -669,6 +668,34 @@ void Game::handleInput() buddyWindow->setVisible(false); } break; + + case KeyboardConfig::KEY_WINDOW_STATUS: + requestedWindow = statusWindow; + break; + case KeyboardConfig::KEY_WINDOW_INVENTORY: + requestedWindow = inventoryWindow; + break; + case KeyboardConfig::KEY_WINDOW_EQUIPMENT: + requestedWindow = equipmentWindow; + break; + case KeyboardConfig::KEY_WINDOW_SKILL: + requestedWindow = skillDialog; + break; + case KeyboardConfig::KEY_WINDOW_MINIMAP: + requestedWindow = minimap; + break; + case KeyboardConfig::KEY_WINDOW_CHAT: + requestedWindow = chatWindow; + break; + case KeyboardConfig::KEY_WINDOW_SHORTCUT: + requestedWindow = itemShortcutWindow; + break; + case KeyboardConfig::KEY_WINDOW_SETUP: + requestedWindow = setupWindow; + break; + case KeyboardConfig::KEY_WINDOW_DEBUG: + requestedWindow = debugWindow; + break; } } @@ -694,15 +721,7 @@ void Game::handleInput() { case SDLK_p: // Screenshot (picture, hence the p) - { - SDL_Surface *screenshot = graphics->getScreenshot(); - if (!saveScreenshot(screenshot)) - { - logger->log( - "Error: could not save Screenshot."); - } - SDL_FreeSurface(screenshot); - } + saveScreenshot(); used = true; break; @@ -775,11 +794,11 @@ void Game::handleInput() } } // End while + // If the user is configuring the keys then don't respond. if (!keyboard.isEnabled()) - { - return; - } + return; + // Moving player around if (player_node->mAction != Being::DEAD && !chatWindow->isInputFocused()) @@ -816,7 +835,8 @@ void Game::handleInput() direction |= Being::RIGHT; } - // First if player is pressing key for the direction he is already going + // First if player is pressing key for the direction he is already + // going if (direction == player_node->getWalkingDir()) { player_node->setWalkingDir(direction); @@ -838,8 +858,8 @@ void Game::handleInput() // Target the nearest player if 'q' is pressed if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER)) { - Being *target = - beingManager->findNearestLivingBeing(player_node, 20, Being::PLAYER); + Being *target = beingManager->findNearestLivingBeing( + player_node, 20, Being::PLAYER); if (target) { @@ -850,8 +870,8 @@ void Game::handleInput() // Target the nearest monster if 'a' pressed if (keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST)) { - Being *target = - beingManager->findNearestLivingBeing(x, y, 20, Being::MONSTER); + Being *target = beingManager->findNearestLivingBeing( + x, y, 20, Being::MONSTER); if (target) { diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index a948b136..008c7bb9 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -40,6 +40,7 @@ BuyDialog::BuyDialog(): Window(_("Buy")), mMoney(0), mAmountItems(0), mMaxItems(0) { + setWindowName("Buy"); setResizable(true); setMinWidth(260); setMinHeight(230); @@ -85,7 +86,7 @@ BuyDialog::BuyDialog(): Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); - loadWindowState("Buy"); + loadWindowState(); setLocationRelativeTo(getParent()); } diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index 3adfbc08..67cb3c7b 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -266,7 +266,8 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot): Window(_("Create Character"), true, parent), mSlot(slot) { mPlayer = new Player(0, 0, NULL); - mPlayer->setHairStyle(rand() % NR_HAIR_STYLES, rand() % NR_HAIR_COLORS); + mPlayer->setHairStyle(rand() % Being::getHairStylesNr(), + rand() % Being::getHairColorsNr()); mPlayer->setGender(GENDER_MALE); mNameField = new TextField(""); @@ -422,13 +423,13 @@ CharCreateDialog::action(const gcn::ActionEvent &event) mPlayer->setHairStyle(-1, mPlayer->getHairColor() + 1); } else if (event.getId() == "prevcolor") { - mPlayer->setHairStyle(-1, mPlayer->getHairColor() + NR_HAIR_COLORS - 1); + mPlayer->setHairStyle(-1, mPlayer->getHairColor() + Being::getHairColorsNr() - 1); } else if (event.getId() == "nextstyle") { mPlayer->setHairStyle(mPlayer->getHairStyle() + 1, -1); } else if (event.getId() == "prevstyle") { - mPlayer->setHairStyle(mPlayer->getHairStyle() + NR_HAIR_STYLES - 1, -1); + mPlayer->setHairStyle(mPlayer->getHairStyle() + Being::getHairStylesNr() - 1, -1); } else if (event.getId() == "statslider") { UpdateSliders(); diff --git a/src/gui/chargedialog.cpp b/src/gui/chargedialog.cpp deleted file mode 100644 index 1c9edf45..00000000 --- a/src/gui/chargedialog.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * The Mana World is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - /* The window supported by this class shows player stats and keeps a charging - * action bar in queue. - */ - -#include "chargedialog.h" - -#include "progressbar.h" - -#include "../localplayer.h" - -ChargeDialog::ChargeDialog(): - Window("") -{ - setContentSize(180, 70); - mProgBar = new ProgressBar(0.0f, 140, 25, 128, 128, 128); - mProgBar->setPosition(20, 40); - add(mProgBar); - setVisible(true); -} - -// update the dialog -void ChargeDialog::logic() -{ - // calculate time since the last attack was made - player_node->mLastAttackTime += .01; // this a hack until someone explains - // to me how to work the timer - if (player_node->mLastAttackTime > 1) - { - player_node->mLastAttackTime = 1; - } - - // reset the progress bar to display accurate time since attack - mProgBar->setProgress(player_node->mLastAttackTime); - - Window::logic(); -} diff --git a/src/gui/chargedialog.h b/src/gui/chargedialog.h deleted file mode 100644 index 9517ef6a..00000000 --- a/src/gui/chargedialog.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * The Mana World is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _TMW_CHARGE_H -#define _TMW_CHARGE_H - -#include "window.h" - -class ProgressBar; - -#define CHARGE_TIME 1000 // time in milliseconds it takes to charge up an attack - -/** - * \ingroup Interface - */ -class ChargeDialog : public Window -{ - public: - /** - * Constructor. - */ - ChargeDialog(); - - void logic(); - - private: - ProgressBar* mProgBar; -}; - -#endif diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index c94429c8..888dd27d 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -52,11 +52,12 @@ ChatWindow::ChatWindow(): Window("Chat"), mTmpVisible(false) { + setWindowName("Chat"); setResizable(true); - setDefaultSize(0, (windowContainer->getHeight() - 105), 400, 100); + setDefaultSize(0, windowContainer->getHeight() - 123, 600, 123); setOpaque(false); - mChatInput = new ChatInput(); + mChatInput = new ChatInput; mChatInput->setActionEventId("chatinput"); mChatInput->addActionListener(this); @@ -88,7 +89,7 @@ ChatWindow::ChatWindow(): mChatInput->addKeyListener(this); mCurHist = mHistory.end(); - loadWindowState("Chat"); + loadWindowState(); } ChatWindow::~ChatWindow() @@ -97,7 +98,7 @@ ChatWindow::~ChatWindow() delete mChatTabs; } -const std::string& ChatWindow::getFocused() const +const std::string &ChatWindow::getFocused() const { return mChatTabs->getSelectedTab()->getCaption(); } @@ -151,8 +152,7 @@ void ChatWindow::logic() } } -void -ChatWindow::chatLog(std::string line, int own, std::string channelName) +void ChatWindow::chatLog(std::string line, int own, std::string channelName) { if(channelName.empty()) channelName = getFocused(); @@ -240,8 +240,7 @@ ChatWindow::chatLog(std::string line, int own, std::string channelName) scroll->logic(); } -void -ChatWindow::action(const gcn::ActionEvent &event) +void ChatWindow::action(const gcn::ActionEvent &event) { if (event.getId() == "chatinput") { @@ -274,8 +273,7 @@ ChatWindow::action(const gcn::ActionEvent &event) } } -void -ChatWindow::requestChatFocus() +void ChatWindow::requestChatFocus() { // Make sure chatWindow is visible if (!isVisible()) @@ -295,13 +293,12 @@ ChatWindow::requestChatFocus() mChatInput->requestFocus(); } -bool -ChatWindow::isInputFocused() +bool ChatWindow::isInputFocused() { return mChatInput->isFocused(); } -void ChatWindow::chatSend(std::string const &msg) +void ChatWindow::chatSend(const std::string &msg) { if (msg.empty()) return; @@ -327,20 +324,17 @@ void ChatWindow::chatSend(std::string const &msg) } } -void -ChatWindow::removeChannel(short channelId) +void ChatWindow::removeChannel(short channelId) { removeChannel(channelManager->findById(channelId)); } -void -ChatWindow::removeChannel(const std::string &channelName) +void ChatWindow::removeChannel(const std::string &channelName) { removeChannel(channelManager->findByName(channelName)); } -void -ChatWindow::removeChannel(Channel *channel) +void ChatWindow::removeChannel(Channel *channel) { if (channel) { @@ -356,8 +350,7 @@ ChatWindow::removeChannel(Channel *channel) } } -void -ChatWindow::createNewChannelTab(const std::string &channelName) +void ChatWindow::createNewChannelTab(const std::string &channelName) { // Create new channel BrowserBox *textOutput = new BrowserBox(BrowserBox::AUTO_WRAP); @@ -384,8 +377,9 @@ ChatWindow::createNewChannelTab(const std::string &channelName) logic(); } -void -ChatWindow::sendToChannel(short channelId, const std::string &user, const std::string &msg) +void ChatWindow::sendToChannel(short channelId, + const std::string &user, + const std::string &msg) { Channel *channel = channelManager->findById(channelId); if (channel) @@ -395,8 +389,7 @@ ChatWindow::sendToChannel(short channelId, const std::string &user, const std::s } } -void -ChatWindow::keyPressed(gcn::KeyEvent &event) +void ChatWindow::keyPressed(gcn::KeyEvent &event) { if (event.getKey().getValue() == Key::DOWN && mCurHist != mHistory.end()) @@ -421,15 +414,13 @@ ChatWindow::keyPressed(gcn::KeyEvent &event) } } -void -ChatWindow::setInputText(std::string input_str) +void ChatWindow::setInputText(std::string input_str) { mChatInput->setText(input_str + " "); requestChatFocus(); } -void -ChatWindow::setVisible(bool isVisible) +void ChatWindow::setVisible(bool isVisible) { Window::setVisible(isVisible); @@ -440,11 +431,8 @@ ChatWindow::setVisible(bool isVisible) mTmpVisible = false; } -bool -ChatWindow::tabExists(const std::string &tabName) +bool ChatWindow::tabExists(const std::string &tabName) { Tab *tab = mChatTabs->getTab(tabName); - if (tab) - return true; - return false; + return tab != 0; } diff --git a/src/gui/chat.h b/src/gui/chat.h index a41b11fb..8ca0e4c9 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -118,41 +118,34 @@ class ChatWindow : public Window, * @param msg The message text which is to be sent. * */ - void chatSend(std::string const &msg); + void chatSend(const std::string &msg); /** Called to remove the channel from the channel manager */ - void - removeChannel(short channelId); + void removeChannel(short channelId); - void - removeChannel(const std::string &channelName); + void removeChannel(const std::string &channelName); - void - removeChannel(Channel *channel); + void removeChannel(Channel *channel); /** Called to create a new channel tab */ - void - createNewChannelTab(const std::string &channelName); + void createNewChannelTab(const std::string &channelName); /** Called to output text to a specific channel */ - void - sendToChannel(short channel, const std::string &user, const std::string &msg); + void sendToChannel(short channel, + const std::string &user, + const std::string &msg); /** Called when key is pressed */ - void - keyPressed(gcn::KeyEvent &event); + void keyPressed(gcn::KeyEvent &event); /** Called to set current text */ - void - setInputText(std::string input_str); + void setInputText(std::string input_str); /** Override to reset mTmpVisible */ - void - setVisible(bool visible); + void setVisible(bool visible); /** Check if tab with that name already exists */ - bool - tabExists(const std::string &tabName); + bool tabExists(const std::string &tabName); void logic(); diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index d92c3575..36e4c8e1 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -39,10 +39,11 @@ DebugWindow::DebugWindow(): Window("Debug") { + setWindowName("Debug"); setResizable(true); setCloseButton(true); setDefaultSize(0, 0, 400, 100); - loadWindowState("Debug"); + loadWindowState(); mFPSLabel = new gcn::Label("[0 FPS]"); mFPSLabel->setPosition(0,0); diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index aee262d0..6848b4d8 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -51,15 +51,15 @@ static const int boxPosition[][2] = { }; EquipmentWindow::EquipmentWindow(Equipment *equipment): - Window(_("Equipment")), mEquipment(equipment), mBackground(NULL), mSelected(-1) { + setWindowName("Equipment"); setCloseButton(true); setDefaultSize(5, 195, 216, 260); - loadWindowState("Equipment"); + loadWindowState(); mUnequip = new Button(_("Unequip"), "unequip", this); gcn::Rectangle const &area = getChildrenArea(); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 930d4939..dc6306b4 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -37,6 +37,7 @@ #include "../graphics.h" #include "../log.h" +#include "../resources/image.h" #include "../resources/imageset.h" #include "../resources/resourcemanager.h" #include "../resources/imageloader.h" @@ -74,6 +75,8 @@ class GuiConfigListener : public ConfigListener Gui::Gui(Graphics *graphics): mCustomCursor(false), mMouseCursors(NULL), + mMouseCursorAlpha(1.0f), + mMouseInactivityTimer(0), mCursorType(CURSOR_POINTER) { logger->log("Initializing GUI..."); @@ -157,32 +160,47 @@ Gui::~Gui() delete hitBlueFont; delete hitYellowFont; - if (mMouseCursors) { + if (mMouseCursors) mMouseCursors->decRef(); - } delete mGuiFont; delete speechFont; delete viewport; - delete mTop; + delete getTop(); delete guiInput; } -void -Gui::draw() +void Gui::logic() +{ + // Fade out mouse cursor after extended inactivity + if (mMouseInactivityTimer < 100 * 15) { + ++mMouseInactivityTimer; + mMouseCursorAlpha = std::min(1.0f, mMouseCursorAlpha + 0.05f); + } else { + mMouseCursorAlpha = std::max(0.0f, mMouseCursorAlpha - 0.005f); + } + + gcn::Gui::logic(); +} + +void Gui::draw() { - mGraphics->pushClipArea(mTop->getDimension()); - mTop->draw(mGraphics); + mGraphics->pushClipArea(getTop()->getDimension()); + getTop()->draw(mGraphics); int mouseX, mouseY; Uint8 button = SDL_GetMouseState(&mouseX, &mouseY); - if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS || button & SDL_BUTTON(1)) && - mCustomCursor) + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS || button & SDL_BUTTON(1)) + && mCustomCursor + && mMouseCursorAlpha > 0.0f) { + Image *mouseCursor = mMouseCursors->get(mCursorType); + mouseCursor->setAlpha(mMouseCursorAlpha); + static_cast<Graphics*>(mGraphics)->drawImage( - mMouseCursors->get(mCursorType), + mouseCursor, mouseX - 15, mouseY - 17); } @@ -190,8 +208,7 @@ Gui::draw() mGraphics->popClipArea(); } -void -Gui::setUseCustomCursor(bool customCursor) +void Gui::setUseCustomCursor(bool customCursor) { if (customCursor != mCustomCursor) { @@ -224,3 +241,9 @@ Gui::setUseCustomCursor(bool customCursor) } } } + +void Gui::handleMouseMoved(const gcn::MouseInput &mouseInput) +{ + gcn::Gui::handleMouseMoved(mouseInput); + mMouseInactivityTimer = 0; +} diff --git a/src/gui/gui.h b/src/gui/gui.h index a07d236f..7d390df9 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -59,6 +59,12 @@ class Gui : public gcn::Gui ~Gui(); /** + * Performs logic of the GUI. Overridden to track mouse pointer + * activity. + */ + void logic(); + + /** * Draws the whole Gui by calling draw functions down in the * Gui hierarchy. It also draws the mouse pointer. */ @@ -95,11 +101,16 @@ class Gui : public gcn::Gui CURSOR_TOTAL }; + protected: + void handleMouseMoved(const gcn::MouseInput &mouseInput); + private: GuiConfigListener *mConfigListener; gcn::Font *mGuiFont; /**< The global GUI font */ bool mCustomCursor; /**< Show custom cursor */ ImageSet *mMouseCursors; /**< Mouse cursor images */ + float mMouseCursorAlpha; + int mMouseInactivityTimer; int mCursorType; }; diff --git a/src/gui/guildwindow.cpp b/src/gui/guildwindow.cpp index ae9684df..0596c75e 100644 --- a/src/gui/guildwindow.cpp +++ b/src/gui/guildwindow.cpp @@ -49,6 +49,7 @@ GuildWindow::GuildWindow(): Window(_("Guild")), mFocus(false) { + setWindowName("Guild"); setCaption(_("Guild")); setResizable(false); setCloseButton(true); @@ -73,7 +74,7 @@ GuildWindow::GuildWindow(): layout.setColWidth(0, 48); layout.setColWidth(1, 65); - loadWindowState("Guild"); + loadWindowState(); } GuildWindow::~GuildWindow() diff --git a/src/gui/help.cpp b/src/gui/help.cpp index ffe9c02d..290679b9 100644 --- a/src/gui/help.cpp +++ b/src/gui/help.cpp @@ -31,6 +31,7 @@ HelpWindow::HelpWindow(): Window("Help") { setContentSize(455, 350); + setWindowName("Help"); mBrowserBox = new BrowserBox(); mBrowserBox->setOpaque(false); diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 0fda7945..1e3c4084 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -53,6 +53,7 @@ InventoryWindow::InventoryWindow(): Window(_("Inventory")), mSplit(false) { + setWindowName("Inventory"); setResizable(false); setCloseButton(true); // LEEOR/TODO: Since this window is not resizable, do we really need to set these @@ -60,7 +61,7 @@ InventoryWindow::InventoryWindow(): setMinWidth(375); setMinHeight(283); // If you adjust these defaults, don't forget to adjust the trade window's. - setDefaultSize(115, 25, 375, 283); + setDefaultSize(115, 30, 375, 283); addKeyListener(this); mUseButton = new Button(_("Use"), "use", this); @@ -82,7 +83,7 @@ InventoryWindow::InventoryWindow(): layout.setColWidth(2, 48); layout.setRowHeight(0, Layout::AUTO_SET); - loadWindowState("Inventory"); + loadWindowState(); } void InventoryWindow::logic() diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index 5fb99ffc..141b4360 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -82,8 +82,7 @@ ItemContainer::~ItemContainer() mSelImg->decRef(); } -void -ItemContainer::draw(gcn::Graphics *graphics) +void ItemContainer::draw(gcn::Graphics *graphics) { Graphics *g = static_cast<Graphics*>(graphics); @@ -147,8 +146,7 @@ ItemContainer::draw(gcn::Graphics *graphics) } } -void -ItemContainer::selectNone() +void ItemContainer::selectNone() { setSelectedItem(NULL); } @@ -324,8 +322,7 @@ int ItemContainer::getSlotIndex(const int posX, const int posY) const return Inventory::NO_SLOT_INDEX; } -void -ItemContainer::keyAction() +void ItemContainer::keyAction() { // If there is no highlight then return. if (!mHighlightedItem) @@ -362,8 +359,7 @@ ItemContainer::keyAction() } } -void -ItemContainer::moveHighlight(int direction) +void ItemContainer::moveHighlight(int direction) { if (!mHighlightedItem) { diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp index 76104e12..e0604c78 100644 --- a/src/gui/itemshortcutcontainer.cpp +++ b/src/gui/itemshortcutcontainer.cpp @@ -85,7 +85,7 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics) // Draw item keyboard shortcut. const char *key = SDL_GetKeyName( - (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_0+i)); + (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_0 + i)); g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT); if (itemShortcut->getItem(i) < 0) @@ -96,9 +96,11 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics) // Draw item icon. Image* image = item->getImage(); if (image) { + // TODO: Have label indicate equipped status + const std::string label = toString(item->getQuantity()); g->drawImage(image, itemX, itemY); g->drawText( - toString(item->getQuantity()), + label, itemX + mBoxWidth / 2, itemY + mBoxHeight - 14, gcn::Graphics::CENTER); diff --git a/src/gui/itemshortcutwindow.cpp b/src/gui/itemshortcutwindow.cpp index e4d352fe..e21f421b 100644 --- a/src/gui/itemshortcutwindow.cpp +++ b/src/gui/itemshortcutwindow.cpp @@ -28,13 +28,14 @@ static const int SCROLL_PADDING = 0; ItemShortcutWindow::ItemShortcutWindow() { + setWindowName("ItemShortcut"); // no title presented, title bar is padding so window can be moved. gcn::Window::setTitleBarHeight(gcn::Window::getPadding()); setShowTitle(false); setResizable(true); setDefaultSize(758, 174, 42, 426); - mItems = new ItemShortcutContainer(); + mItems = new ItemShortcutContainer; const int border = SCROLL_PADDING * 2 + getPadding() * 2; setMinWidth(mItems->getBoxWidth() + border); @@ -49,7 +50,7 @@ ItemShortcutWindow::ItemShortcutWindow() add(mScrollArea); - loadWindowState("ItemShortcut"); + loadWindowState(); } ItemShortcutWindow::~ItemShortcutWindow() diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 24c55e37..b4289984 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -71,12 +71,9 @@ LoginDialog::LoginDialog(LoginData *loginData) : Window(_("Login")), mLoginData( setLocationRelativeTo(getParent()); setVisible(true); - if (mUserField->getText().empty()) - { + if (mUserField->getText().empty()) { mUserField->requestFocus(); - } - else - { + } else { mPassField->requestFocus(); } diff --git a/src/gui/magic.cpp b/src/gui/magic.cpp index ca7b5489..2c81321b 100644 --- a/src/gui/magic.cpp +++ b/src/gui/magic.cpp @@ -35,8 +35,9 @@ MagicDialog::MagicDialog(): Window(_("Magic")) { + setWindowName("Magic"); setCloseButton(true); - setDefaultSize(255, 25, 175, 225); + setDefaultSize(255, 30, 175, 225); gcn::Button *spellButton1 = new Button(_("Cast Test Spell 1"), "spell_1", this); gcn::Button *spellButton2 = new Button(_("Cast Test Spell 2"), "spell_2", this); @@ -53,7 +54,7 @@ MagicDialog::MagicDialog(): update(); setLocationRelativeTo(getParent()); - loadWindowState(_("Magic")); + loadWindowState(); } MagicDialog::~MagicDialog() diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index 501530f1..f7749755 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -34,8 +34,9 @@ Minimap::Minimap(): Window(_("MiniMap")), mMapImage(NULL) { - setDefaultSize(0, 0, 100, 100); - loadWindowState("MiniMap"); + setWindowName("MiniMap"); + setDefaultSize(5, 25, 100, 100); + loadWindowState(); // LEEOR: The Window class needs to modified to accept // setAlignment calls. setAlignment(gcn::Graphics::CENTER); @@ -44,49 +45,50 @@ Minimap::Minimap(): Minimap::~Minimap() { if (mMapImage) - { mMapImage->decRef(); - } } void Minimap::setMapImage(Image *img) { if (mMapImage) - { mMapImage->decRef(); - } mMapImage = img; - if (mMapImage) - { + if (mMapImage) { mMapImage->setAlpha(0.7); - setSize( mMapImage->getWidth() + 6, mMapImage->getHeight() + 23 ); - setVisible(true); + setContentSize(mMapImage->getWidth(), mMapImage->getHeight()); } - else - { - setVisible(false); - } - } void Minimap::draw(gcn::Graphics *graphics) { Window::draw(graphics); + const gcn::Rectangle a = getChildrenArea(); + + int mapOriginX = a.x; + int mapOriginY = a.y; + if (mMapImage) { - static_cast<Graphics*>(graphics)->drawImage( - mMapImage, getPadding(), getTitleBarHeight()); + if (mMapImage->getWidth() > a.width || + mMapImage->getHeight() > a.height) + { + const Vector &pos = player_node->getPosition(); + mapOriginX += (a.width - (int) (pos.x / 32)) / 2; + mapOriginY += (a.height - (int) (pos.y / 32)) / 2; + } + static_cast<Graphics*>(graphics)-> + drawImage(mMapImage, mapOriginX, mapOriginY); } - Beings &beings = beingManager->getAll(); - BeingIterator bi; + const Beings &beings = beingManager->getAll(); + Beings::const_iterator bi; for (bi = beings.begin(); bi != beings.end(); bi++) { - Being *being = (*bi); + const Being *being = (*bi); int dotSize = 2; switch (being->getType()) { @@ -116,8 +118,8 @@ void Minimap::draw(gcn::Graphics *graphics) const Vector &pos = being->getPosition(); graphics->fillRectangle(gcn::Rectangle( - (int) pos.x / 64 + getPadding() - offset, - (int) pos.y / 64 + getTitleBarHeight() - offset, + (int) pos.x / 64 + mapOriginX - offset, + (int) pos.x / 64 + mapOriginY - offset, dotSize, dotSize)); } } diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp index 424c3558..86e5a8f1 100644 --- a/src/gui/ministatus.cpp +++ b/src/gui/ministatus.cpp @@ -32,8 +32,7 @@ #include "../utils/tostring.h" -MiniStatusWindow::MiniStatusWindow(): - Window() +MiniStatusWindow::MiniStatusWindow() { setResizable(false); setMovable(false); diff --git a/src/gui/newskill.cpp b/src/gui/newskill.cpp deleted file mode 100644 index 20fc01bd..00000000 --- a/src/gui/newskill.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * The Mana World is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - /* This file implements the new skill dialog for use under the latest - * version of the skill system as of 2005/02/20 - */ - -#include "newskill.h" - -#include <guichan/widgets/label.hpp> - -#include "button.h" -#include "progressbar.h" - -#include "../graphics.h" - -const char *skill_name[] = { - // 0-99 - // weapon skills 0-9 - "Short Blades", "Long Blades", "Hammers", "Archery", "Whip", - "Staves", "Throwing", "Piercing", "Hand to Hand", NULL, - // magic skills 10-19 - "Epyri (Fire)", "Merene (Water)", "Geon (Earth)", "Izurial (Air)", - "Lumine (Light)", "Tenebrae (Dark)", "Chronos (Time)", "Teless (Space)", - "Gen (Mana)", NULL, - // craft skills 20-29 - "Metalworking", "Woodworking", "Jeweler", "Cook", "Tailor", - "Alchemist", "Artisan", "Synthesis", NULL, NULL, - // general skills 30-39 - "Running", "Searching", "Sneak", "Trading", "Intimidate", - "Athletics", NULL, NULL, NULL,NULL, - // combat skills 40-49 - "Dodge", "Accuracy", "Critical", "Block", "Parry", "Diehard", "Magic Aura", - "Counter", NULL, NULL, - // resistance skills 50-59 - "Poison", "Silence", "Petrify", "Paralyze", "Blind", "Slow", "Zombie", - "Critical", NULL, NULL, - // element reistance 60-69 - "Heat (Fire)", "Chill (Water)", "Stone (Earth)", "Wind (Air)", - "Shine (Light)", "Shadow (Dark)", "Decay (Time)", "Chaos (Space)", NULL, - NULL, - // hunting skills 70-79 - "Insects", "Birds", "Lizards", "Amorphs", "Undead", "Machines", "Arcana", - "Humanoids", "Plantoids", NULL, - // stats 80-89 - "Strength", "Fortitude", "Vitality", "Menality", "Awareness", "Mana", - "Dexterity", NULL, NULL, NULL, - // unused (reserved) 90-99 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - - -NewSkillDialog::NewSkillDialog(): - Window("Skills") -{ - startPoint = 0; - for (int i = 0; i < N_SKILL_CAT_SIZE; i++) - { - mSkillLabel[i] = new gcn::Label("Empty "); - mSkillLevel[i] = new gcn::Label("00000"); - mSkillbar[i] = new ProgressBar(0.0f,100,15,0,0,255); - mSkillLevel[i]->setAlignment(Graphics::RIGHT); - add(mSkillLabel[i],40,5+i*25); - add(mSkillLevel[i],150,5+i*25); - add(mSkillbar[i],180,5+i*25); - } - // initialize the skills - for (int i = 0; i < N_SKILL; i++) - { - mPlayerSkill[i].level = 0; - mPlayerSkill[i].exp = 0; - } - resetNSD(); - - // create controls - Button *catButton[N_SKILL_CAT]; - catButton[0] = new Button("Weapons", "g1", this); - catButton[1] = new Button("Magic", "g2", this); - catButton[2] = new Button("Craft", "g3", this); - catButton[3] = new Button("General", "g4", this); - catButton[4] = new Button("Combat", "g5", this); - catButton[5] = new Button("E. Resist", "g6", this); - catButton[6] = new Button("S. Resist", "g7", this); - catButton[7] = new Button("Hunting", "g8", this); - catButton[8] = new Button("Stat", "g9", this); - - setContentSize(350, 250); - - for (int i = 0; i < 9; ++i) { - catButton[i]->setDimension(gcn::Rectangle(0, 0, 60, 20)); - catButton[i]->setPosition(290, 20 * i); - add(catButton[i]); - } - - Button *closeButton = new Button("Close", "close", this); - closeButton->setDimension(gcn::Rectangle(0,0,60,20)); - closeButton->setPosition(290, 230); - add(closeButton); - - // finsihing touches - setLocationRelativeTo(getParent()); -} - -void NewSkillDialog::action(const gcn::ActionEvent &event) -{ - int osp = startPoint; - if (event.getId() == "close") - { - setVisible(false); - } - else if (event.getId() == "g1") // weapons group 0-9 - { - startPoint =0; - } - else if (event.getId() == "g2") // magic group 10-19 - { - startPoint =10; - } - else if (event.getId() == "g3") // craft group 20-29 - { - startPoint =20; - } - else if (event.getId() == "g4") // general group 30-39 - { - startPoint =30; - } - else if (event.getId() == "g5") // combat group 40-49 - { - startPoint =40; - } - else if (event.getId() == "g6") // e. resist group 50-59 - { - startPoint =50; - } - else if (event.getId() == "g7") // s resist group 60-69 - { - startPoint =60; - } - else if (event.getId() == "g8") // hunting group 70-79 - { - startPoint =70; - } - else if (event.getId() == "g9") // stats group 80-89 - { - startPoint =80; - } - if (osp != startPoint) - { - resetNSD(); - } -} - -void NewSkillDialog::resetNSD() -{ - for (int a = 0; a < N_SKILL_CAT_SIZE; a++) - { - if (skill_name[a + startPoint]) - { - mSkillLabel[a]->setCaption(skill_name[a + startPoint]); - mSkillLabel[a]->setVisible(true); - char tmp[5]; - sprintf(tmp, "%d", mPlayerSkill[a+startPoint].level); - mSkillLevel[a]->setCaption(tmp); - mSkillLevel[a]->setVisible(true); - mSkillbar[a]->setProgress(0.0f); - mSkillbar[a]->setVisible(true); - } - else - { - mSkillLevel[a]->setVisible(false); - mSkillLabel[a]->setVisible(false); - mSkillbar[a]->setVisible(false); - } - } -} diff --git a/src/gui/newskill.h b/src/gui/newskill.h deleted file mode 100644 index 49476e5e..00000000 --- a/src/gui/newskill.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * The Mana World is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _TMW_NSKILL_H -#define _TMW_NSKILL_H - -#include <guichan/actionlistener.hpp> - -#include "window.h" - -#include "../guichanfwd.h" - -class ProgressBar; - -#define N_SKILL 100 // skill count constant -#define N_SKILL_CAT 9 // skill category count -#define N_SKILL_CAT_SIZE 10 // skill category maximum size - -struct nSkill { - short level; - short exp; -}; - -/** - * Dialog showing the skills in the planned skill model. - * - * \ingroup Interface - */ -class NewSkillDialog : public Window, public gcn::ActionListener -{ - public: - /** - * Constructor. - */ - NewSkillDialog(); - - // action listener - void action(const gcn::ActionEvent &event); - - private: - void resetNSD(); // updates the values in the dialog box - - // members - int startPoint; // starting point of skill listing - ProgressBar *mSkillbar[N_SKILL_CAT_SIZE]; - gcn::Label *mSkillLabel[N_SKILL_CAT_SIZE]; - gcn::Label *mSkillLevel[N_SKILL_CAT_SIZE]; - nSkill mPlayerSkill[N_SKILL]; // pointer to an array of skill values -}; - -#endif diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index c593feb1..c9ace303 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -34,10 +34,16 @@ NpcTextDialog::NpcTextDialog(): Window(_("NPC")) { + setResizable(true); + + setMinWidth(200); + setMinHeight(150); + mTextBox = new TextBox; mTextBox->setEditable(false); - gcn::ScrollArea *scrollArea = new ScrollArea(mTextBox); - Button *okButton = new Button(_("Ok"), "ok", this); + + scrollArea = new ScrollArea(mTextBox); + okButton = new Button(_("OK"), "ok", this); setContentSize(260, 175); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); @@ -54,20 +60,36 @@ NpcTextDialog::NpcTextDialog(): setLocationRelativeTo(getParent()); } -void -NpcTextDialog::setText(const std::string &text) +void NpcTextDialog::setText(const std::string &text) +{ + mText = text; + mTextBox->setTextWrapped(mText); +} + +void NpcTextDialog::addText(const std::string &text) { - mTextBox->setTextWrapped(text); + setText(mText + text + "\n"); } -void -NpcTextDialog::addText(const std::string &text) +void NpcTextDialog::widgetResized(const gcn::Event &event) { - mTextBox->setTextWrapped(mTextBox->getText() + text + "\n"); + Window::widgetResized(event); + + const gcn::Rectangle &area = getChildrenArea(); + const int width = area.width; + const int height = area.height; + + scrollArea->setDimension(gcn::Rectangle( + 5, 5, width - 10, height - 15 - okButton->getHeight())); + okButton->setPosition( + width - 5 - okButton->getWidth(), + height - 5 - okButton->getHeight()); + + // Set the text again so that it gets wrapped according to the new size + mTextBox->setTextWrapped(mText); } -void -NpcTextDialog::action(const gcn::ActionEvent &event) +void NpcTextDialog::action(const gcn::ActionEvent &event) { if (event.getId() == "ok") { diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h index 2c9771d3..76161f88 100644 --- a/src/gui/npc_text.h +++ b/src/gui/npc_text.h @@ -45,18 +45,23 @@ class NpcTextDialog : public Window, public gcn::ActionListener NpcTextDialog(); /** + * Called when resizing the window + * + * @param event The calling event + */ + void widgetResized(const gcn::Event &event); + + /** * Called when receiving actions from the widgets. */ - void - action(const gcn::ActionEvent &event); + void action(const gcn::ActionEvent &event); /** * Sets the text shows in the dialog. * * @param string The new text. */ - void - setText(const std::string &string); + void setText(const std::string &string); /** * Adds the text to the text shows in the dialog. Also adds a newline @@ -64,11 +69,14 @@ class NpcTextDialog : public Window, public gcn::ActionListener * * @param string The text to add. */ - void - addText(const std::string &string); + void addText(const std::string &string); private: + gcn::Button *okButton; + gcn::ScrollArea *scrollArea; TextBox *mTextBox; + + std::string mText; }; -#endif +#endif // _TMW_NPC_TEXT_H diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp index 918031b4..c55255ea 100644 --- a/src/gui/npclistdialog.cpp +++ b/src/gui/npclistdialog.cpp @@ -34,10 +34,15 @@ NpcListDialog::NpcListDialog(): Window(_("NPC")) { + setResizable(true); + + setMinWidth(200); + setMinHeight(150); + mItemList = new ListBox(this); - ScrollArea *scrollArea = new ScrollArea(mItemList); - Button *okButton = new Button(_("Ok"), "ok", this); - Button *cancelButton = new Button(_("Cancel"), "cancel", this); + scrollArea = new ScrollArea(mItemList); + okButton = new Button(_("OK"), "ok", this); + cancelButton = new Button(_("Cancel"), "cancel", this); setContentSize(260, 175); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); @@ -61,31 +66,45 @@ NpcListDialog::NpcListDialog(): setLocationRelativeTo(getParent()); } -int -NpcListDialog::getNumberOfElements() +int NpcListDialog::getNumberOfElements() { return mItems.size(); } -std::string -NpcListDialog::getElementAt(int i) +std::string NpcListDialog::getElementAt(int i) { return mItems[i]; } -void NpcListDialog::addItem(std::string const &item) +void NpcListDialog::addItem(const std::string &item) { mItems.push_back(item); } -void -NpcListDialog::reset() +void NpcListDialog::reset() { mItems.clear(); } -void -NpcListDialog::action(const gcn::ActionEvent &event) +void NpcListDialog::widgetResized(const gcn::Event &event) +{ + Window::widgetResized(event); + + const gcn::Rectangle &area = getChildrenArea(); + const int width = area.width; + const int height = area.height; + + scrollArea->setDimension(gcn::Rectangle( + 5, 5, width - 10, height - 15 - okButton->getHeight())); + cancelButton->setPosition( + width - 5 - cancelButton->getWidth(), + height - 5 - cancelButton->getHeight()); + okButton->setPosition( + cancelButton->getX() - 5 - okButton->getWidth(), + cancelButton->getY()); +} + +void NpcListDialog::action(const gcn::ActionEvent &event) { int choice = 0; diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h index e21f9e8c..65281f58 100644 --- a/src/gui/npclistdialog.h +++ b/src/gui/npclistdialog.h @@ -49,38 +49,44 @@ class NpcListDialog : public Window, public gcn::ActionListener, NpcListDialog(); /** + * Called when resizing the window + * + * @param event The calling event + */ + void widgetResized(const gcn::Event &event); + + /** * Called when receiving actions from the widgets. */ - void - action(const gcn::ActionEvent &event); + void action(const gcn::ActionEvent &event); /** * Returns the number of items in the choices list. */ - int - getNumberOfElements(); + int getNumberOfElements(); /** * Returns the name of item number i of the choices list. */ - std::string - getElementAt(int i); + std::string getElementAt(int i); /** * Adds an item to the option list. */ - void addItem(std::string const &); + void addItem(const std::string &); /** * Resets the list by removing all items. */ - void - reset(); + void reset(); private: gcn::ListBox *mItemList; + gcn::ScrollArea *scrollArea; + gcn::Button *okButton; + gcn::Button *cancelButton; std::vector<std::string> mItems; }; -#endif +#endif // _TMW_GUI_NPCLISTDIALOG_H diff --git a/src/gui/partywindow.cpp b/src/gui/partywindow.cpp index 262e3b2e..c4a1c780 100644 --- a/src/gui/partywindow.cpp +++ b/src/gui/partywindow.cpp @@ -29,6 +29,7 @@ PartyWindow::PartyWindow() : Window(_("Party")) { + setWindowName("Party"); setVisible(false); setResizable(false); setCaption(_("Party")); @@ -37,7 +38,7 @@ PartyWindow::PartyWindow() : Window(_("Party")) setMinHeight(200); setDefaultSize(620, 300, 110, 200); - loadWindowState("Party"); + loadWindowState(); } PartyWindow::~PartyWindow() diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 30e78368..24391458 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -44,6 +44,7 @@ SellDialog::SellDialog(): Window(_("Sell")), mMaxItems(0), mAmountItems(0) { + setWindowName("Sell"); setResizable(true); setMinWidth(260); setMinHeight(230); @@ -90,7 +91,7 @@ SellDialog::SellDialog(): Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); - loadWindowState("Sell"); + loadWindowState(); setLocationRelativeTo(getParent()); } diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 2a60308b..e062f674 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -43,6 +43,7 @@ extern Window *helpWindow; extern Window *skillDialog; extern Window *magicDialog; extern Window *guildWindow; +extern Window *itemShortcutWindow; Setup::Setup(): Window(_("Setup")) @@ -117,5 +118,6 @@ void Setup::action(const gcn::ActionEvent &event) skillDialog->resetToDefaultSize(); magicDialog->resetToDefaultSize(); guildWindow->resetToDefaultSize(); + itemShortcutWindow->resetToDefaultSize(); } } diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 51cee8e3..bac342a0 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -106,8 +106,8 @@ Setup_Video::Setup_Video(): mCustomCursorEnabled(config.getValue("customcursor", 1)), mVisibleNamesEnabled(config.getValue("visiblenames", 1)), mOpacity(config.getValue("guialpha", 0.8)), - mFps((int)config.getValue("fpslimit", 60)), - mModeListModel(new ModeListModel()), + mFps((int) config.getValue("fpslimit", 0)), + mModeListModel(new ModeListModel), mModeList(new ListBox(mModeListModel)), mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)), mOpenGLCheckBox(new CheckBox(_("OpenGL"), mOpenGLEnabled)), @@ -116,13 +116,13 @@ Setup_Video::Setup_Video(): mAlphaSlider(new Slider(0.2, 1.0)), mFpsCheckBox(new CheckBox(_("FPS Limit:"))), mFpsSlider(new Slider(10, 200)), - mFpsField(new TextField()), - mOriginalScrollLaziness((int) config.getValue("ScrollLaziness", 32)), + mFpsField(new TextField), + mOriginalScrollLaziness((int) config.getValue("ScrollLaziness", 16)), mScrollLazinessSlider(new Slider(1, 64)), - mScrollLazinessField(new TextField()), - mOriginalScrollRadius((int) config.getValue("ScrollRadius", 32)), + mScrollLazinessField(new TextField), + mOriginalScrollRadius((int) config.getValue("ScrollRadius", 0)), mScrollRadiusSlider(new Slider(0, 128)), - mScrollRadiusField(new TextField()), + mScrollRadiusField(new TextField), mOverlayDetail((int) config.getValue("OverlayDetail", 2)), mOverlayDetailSlider(new Slider(0, 2)), mOverlayDetailField(new gcn::Label("")) @@ -189,7 +189,7 @@ Setup_Video::Setup_Video(): mScrollRadiusSlider->setDimension(gcn::Rectangle(10, 140, 75, 10)); gcn::Label *scrollRadiusLabel = new gcn::Label(_("Scroll radius")); scrollRadiusLabel->setPosition(90, 140); - mScrollRadiusField->setPosition(180, 140); + mScrollRadiusField->setPosition(mFpsField->getX(), 140); mScrollRadiusField->setWidth(30); mScrollRadiusField->setText(toString(mOriginalScrollRadius)); mScrollRadiusSlider->setValue(mOriginalScrollRadius); @@ -197,7 +197,7 @@ Setup_Video::Setup_Video(): mScrollLazinessSlider->setDimension(gcn::Rectangle(10, 160, 75, 10)); gcn::Label *scrollLazinessLabel = new gcn::Label(_("Scroll laziness")); scrollLazinessLabel->setPosition(90, 160); - mScrollLazinessField->setPosition(180, 160); + mScrollLazinessField->setPosition(mFpsField->getX(), 160); mScrollLazinessField->setWidth(30); mScrollLazinessField->setText(toString(mOriginalScrollLaziness)); mScrollLazinessSlider->setValue(mOriginalScrollLaziness); @@ -253,9 +253,18 @@ void Setup_Video::apply() bool fullscreen = mFsCheckBox->isSelected(); if (fullscreen != (config.getValue("screen", 0) == 1)) { + /* The OpenGL test is only necessary on Windows, since switching + * to/from full screen works fine on Linux. On Windows we'd have to + * reinitialize the OpenGL state and reload all textures. + * + * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode + */ + +#ifdef WIN32 // checks for opengl usage if (!(config.getValue("opengl", 0) == 1)) { +#endif if (!graphics->setFullscreen(fullscreen)) { fullscreen = !fullscreen; @@ -269,10 +278,12 @@ void Setup_Video::apply() logger->error(error.str()); } } +#ifdef WIN32 } else { new OkDialog(_("Switching to full screen"), _("Restart needed for changes to take effect.")); } +#endif config.setValue("screen", fullscreen ? 1 : 0); } diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 49bacaf0..6d747641 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -43,8 +43,9 @@ SkillDialog::SkillDialog(): Window(_("Skills")) { + setWindowName("Skills"); setCloseButton(true); - setDefaultSize(windowContainer->getWidth() - 255, 25, 275, 425); + setDefaultSize(windowContainer->getWidth() - 280, 30, 275, 425); TabbedArea *panel = new TabbedArea(); panel->setDimension(gcn::Rectangle(5, 5, 270, 420)); @@ -69,7 +70,7 @@ SkillDialog::SkillDialog(): update(); setLocationRelativeTo(getParent()); - loadWindowState(_("Skills")); + loadWindowState(); } SkillDialog::~SkillDialog() diff --git a/src/gui/status.cpp b/src/gui/status.cpp index 43f81135..283a771b 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -36,11 +36,12 @@ StatusWindow::StatusWindow(LocalPlayer *player): Window(player->getName()), mPlayer(player) { + setWindowName("Status"); setResizable(true); setCloseButton(true); setDefaultSize((windowContainer->getWidth() - 365) / 2, - (windowContainer->getHeight() - 255) / 2, 365, 280); - loadWindowState("Status"); + (windowContainer->getHeight() - 255) / 2, 365, 275); + loadWindowState(); // ---------------------- // Status Part diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 38064f48..7d5051c7 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -53,6 +53,7 @@ TradeWindow::TradeWindow(): mPartnerInventory(new Inventory), mStatus(PREPARING) { + setWindowName("Trade"); setResizable(true); setDefaultSize(115, 197, 332, 209); @@ -102,7 +103,7 @@ TradeWindow::TradeWindow(): layout.setColWidth(0, Layout::AUTO_SET); layout.setColWidth(1, Layout::AUTO_SET); - loadWindowState("Trade"); + loadWindowState(); } TradeWindow::~TradeWindow() diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index ff1e600c..997a9b82 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -47,7 +47,7 @@ /** * Calculates the Alder-32 checksum for the given file. */ -unsigned long fadler32(FILE *file) +static unsigned long fadler32(FILE *file) { // Obtain file size fseek(file, 0, SEEK_END); @@ -146,15 +146,9 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost, UpdaterWindow::~UpdaterWindow() { if (mThread) - { - SDL_WaitThread(mThread, NULL); - mThread = NULL; - } + SDL_WaitThread(mThread, NULL); - if (mMemoryBuffer) - { - free(mMemoryBuffer); - } + free(mMemoryBuffer); // Remove possibly leftover temporary download ::remove((mUpdatesDir + "/download.temp").c_str()); @@ -169,8 +163,9 @@ void UpdaterWindow::setProgress(float p) void UpdaterWindow::setLabel(const std::string &str) { - mLabel->setCaption(str); - mLabel->adjustSize(); + // Do delayed label text update, since Guichan isn't thread-safe + MutexLocker lock(&mLabelMutex); + mNewLabelCaption = str; } void UpdaterWindow::enable() @@ -315,6 +310,17 @@ int UpdaterWindow::downloadThread(void *ptr) curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); + struct curl_slist *pHeaders = NULL; + if (uw->mDownloadStatus != UPDATE_RESOURCES) + { + // Make sure the resources2.txt and news.txt aren't cached, + // in order to always get the latest version. + pHeaders = curl_slist_append(pHeaders, "pragma: no-cache"); + pHeaders = + curl_slist_append(pHeaders, "Cache-Control: no-cache"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pHeaders); + } + if ((res = curl_easy_perform(curl)) != 0) { uw->mDownloadStatus = UPDATE_ERROR; @@ -339,6 +345,11 @@ int UpdaterWindow::downloadThread(void *ptr) curl_easy_cleanup(curl); + if (uw->mDownloadStatus != UPDATE_RESOURCES) + { + curl_slist_free_all(pHeaders); + } + if (!uw->mStoreInMemory) { // Don't check resources2.txt checksum @@ -413,6 +424,17 @@ void UpdaterWindow::logic() // Update Scroll logic mScrollArea->logic(); + // Synchronize label caption when necessary + { + MutexLocker lock(&mLabelMutex); + + if (mLabel->getCaption() != mNewLabelCaption) + { + mLabel->setCaption(mNewLabelCaption); + mLabel->adjustSize(); + } + } + switch (mDownloadStatus) { case UPDATE_ERROR: @@ -434,7 +456,8 @@ void UpdaterWindow::logic() mBrowserBox->addRow("##1 It is strongly recommended that"); mBrowserBox->addRow("##1 you try again later"); mBrowserBox->addRow(mCurlError); - mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); + mScrollArea->setVerticalScrollAmount( + mScrollArea->getVerticalMaxScroll()); mDownloadStatus = UPDATE_COMPLETE; break; case UPDATE_NEWS: diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index d7e3c4c7..a7dfe2cb 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -30,12 +30,13 @@ #include "../guichanfwd.h" +#include "../utils/mutex.h" + class BrowserBox; class Button; class ProgressBar; class ScrollArea; -struct SDL_mutex; struct SDL_Thread; /** @@ -88,7 +89,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener int updateState; - protected: +private: void download(); /** @@ -133,6 +134,12 @@ class UpdaterWindow : public Window, public gcn::ActionListener /** The file currently downloading. */ std::string mCurrentFile; + /** The new label caption to be set in the logic method. */ + std::string mNewLabelCaption; + + /** The mutex used to guard access to mNewLabelCaption. */ + Mutex mLabelMutex; + /** The Adler32 checksum of the file currently downloading. */ unsigned long mCurrentChecksum; @@ -164,7 +171,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener Button *mCancelButton; /**< Button to stop the update process. */ Button *mPlayButton; /**< Button to start playing. */ ProgressBar *mProgressBar; /**< Update progress bar. */ - BrowserBox* mBrowserBox; /**< Box to display news. */ + BrowserBox *mBrowserBox; /**< Box to display news. */ ScrollArea *mScrollArea; /**< Used to scroll news box. */ }; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index a6092c7a..a746fb03 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -61,8 +61,8 @@ Viewport::Viewport(): setOpaque(false); addMouseListener(this); - mScrollLaziness = (int) config.getValue("ScrollLaziness", 32); - mScrollRadius = (int) config.getValue("ScrollRadius", 32); + mScrollLaziness = (int) config.getValue("ScrollLaziness", 16); + mScrollRadius = (int) config.getValue("ScrollRadius", 0); mScrollCenterOffsetX = (int) config.getValue("ScrollCenterOffsetX", 0); mScrollCenterOffsetY = (int) config.getValue("ScrollCenterOffsetY", 0); mVisibleNames = config.getValue("visiblenames", 1); diff --git a/src/gui/widgets/avatar.cpp b/src/gui/widgets/avatar.cpp index 68ce5243..9fcd00a6 100644 --- a/src/gui/widgets/avatar.cpp +++ b/src/gui/widgets/avatar.cpp @@ -33,23 +33,17 @@ Avatar::Avatar(const std::string &name): mLabel = new gcn::Label(name); mLabel->setSize(85, 12); mLabel->setPosition(25, 0); - mStatusOffline = ResourceManager::getInstance()->getImage("graphics/gui/circle-gray.png"); - mStatusOnline = ResourceManager::getInstance()->getImage("graphics/gui/circle-green.png"); + ResourceManager *resman = ResourceManager::getInstance(); + mStatusOffline = resman->getImage("graphics/gui/circle-gray.png"); + mStatusOnline = resman->getImage("graphics/gui/circle-green.png"); mStatus = new Icon(mStatusOffline); mStatus->setSize(25, 12); mStatus->setPosition(0, 0); } -void Avatar::setOnline(bool status) +void Avatar::setOnline(bool online) { - if (status) - { - mStatus->setImage(mStatusOnline); - } - else - { - mStatus->setImage(mStatusOffline); - } + mStatus->setImage(online ? mStatusOnline : mStatusOffline); } void Avatar::draw(gcn::Graphics *g) diff --git a/src/gui/widgets/avatar.h b/src/gui/widgets/avatar.h index 0f657895..c6151020 100644 --- a/src/gui/widgets/avatar.h +++ b/src/gui/widgets/avatar.h @@ -33,18 +33,18 @@ class Avatar : public gcn::Widget { public: /** - * Constructor + * Constructor. * @param name Character name */ Avatar(const std::string &name); /** - * Set the avatar online status + * Set the avatar online status. */ - void setOnline(bool status); + void setOnline(bool online); /** - * Draws the Avatar + * Draws the avatar. */ void draw(gcn::Graphics *g); diff --git a/src/gui/window.cpp b/src/gui/window.cpp index e498236a..582e4a67 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -129,12 +129,13 @@ Window::~Window() { logger->log("UNLOAD: Window::~Window(\"%s\")", getCaption().c_str()); - std::string const &name = mConfigName; + const std::string &name = mWindowName; if (!name.empty()) { // Saving X, Y and Width and Height for resizables in the config config.setValue(name + "WinX", getX()); config.setValue(name + "WinY", getY()); + config.setValue(name + "Visible", isVisible()); if (mGrip) { @@ -179,10 +180,9 @@ void Window::setWindowContainer(WindowContainer *wc) void Window::draw(gcn::Graphics *graphics) { - if(mAlphaChanged) + if (mAlphaChanged) setGuiAlpha(); - Graphics *g = static_cast<Graphics*>(graphics); //g->drawImageRect(0, 0, getWidth(), getHeight(), border); @@ -248,7 +248,7 @@ void Window::setMaxHeight(unsigned int height) void Window::setResizable(bool r) { - if ((bool)mGrip == r) return; + if ((bool) mGrip == r) return; if (r) { @@ -269,7 +269,7 @@ void Window::widgetResized(const gcn::Event &event) { if (mGrip) { - gcn::Rectangle const &area = getChildrenArea(); + const gcn::Rectangle area = getChildrenArea(); mGrip->setPosition(getWidth() - mGrip->getWidth() - area.x, getHeight() - mGrip->getHeight() - area.y); } @@ -467,12 +467,14 @@ void Window::mouseDragged(gcn::MouseEvent &event) } } -void Window::loadWindowState(std::string const &name) +void Window::loadWindowState() { - mConfigName = name; + const std::string &name = mWindowName; + assert(!name.empty()); setPosition((int) config.getValue(name + "WinX", mDefaultX), (int) config.getValue(name + "WinY", mDefaultY)); + setVisible((bool) config.getValue(name + "Visible", false)); if (mGrip) { @@ -497,7 +499,7 @@ void Window::setDefaultSize(int defaultX, int defaultY, void Window::resetToDefaultSize() { setPosition(mDefaultX, mDefaultY); - setContentSize(mDefaultWidth, mDefaultHeight); + setSize(mDefaultWidth, mDefaultHeight); } int Window::getResizeHandles(gcn::MouseEvent &event) diff --git a/src/gui/window.h b/src/gui/window.h index 22355572..6f49e062 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -153,8 +153,7 @@ class Window : public gcn::Window, gcn::WidgetListener * * @return The parent window or <code>NULL</code> if there is none. */ - Window* - getParentWindow() { return mParent; } + Window *getParentWindow() { return mParent; } /** * Schedule this window for deletion. It will be deleted at the start @@ -192,13 +191,23 @@ class Window : public gcn::Window, gcn::WidgetListener void mouseExited(gcn::MouseEvent &event); /** + * Sets the name of the window. This is not the window title. + */ + void setWindowName(const std::string &name) { mWindowName = name; } + + /** + * Returns the name of the window. This is not the window title. + */ + const std::string &getWindowName() { return mWindowName; } + + /** * Reads the position (and the size for resizable windows) in the * configuration based on the given string. * Uses the default values when config values are missing. * Don't forget to set these default values and resizable before * calling this function. */ - void loadWindowState(std::string const &); + void loadWindowState(); /** * Set the default win pos and size. @@ -267,7 +276,7 @@ class Window : public gcn::Window, gcn::WidgetListener ResizeGrip *mGrip; /**< Resize grip */ Window *mParent; /**< The parent window */ Layout *mLayout; /**< Layout handler */ - std::string mConfigName; /**< Name used for saving window-related data */ + std::string mWindowName; /**< Name of the window */ bool mShowTitle; /**< Window has a title bar */ bool mModal; /**< Window is modal */ bool mCloseButton; /**< Window has a close button */ diff --git a/src/imageparticle.h b/src/imageparticle.h index 91c5426c..c18b30b8 100644 --- a/src/imageparticle.h +++ b/src/imageparticle.h @@ -49,8 +49,7 @@ class ImageParticle : public Particle /** * Draws the particle image */ - virtual void - draw(Graphics *graphics, int offsetX, int offsetY) const; + virtual void draw(Graphics *graphics, int offsetX, int offsetY) const; protected: Image *mImage; /**< The image used for this particle. */ diff --git a/src/itemshortcut.cpp b/src/itemshortcut.cpp index a89da974..bea14864 100644 --- a/src/itemshortcut.cpp +++ b/src/itemshortcut.cpp @@ -61,14 +61,8 @@ void ItemShortcut::save() { for (int i = 0; i < SHORTCUT_ITEMS; i++) { - if (mItems[i]) - { - config.setValue("shortcut" + toString(i), mItems[i]); - } - else - { - config.setValue("shortcut" + toString(i), -1); - } + const int itemId = mItems[i] ? mItems[i] : -1; + config.setValue("shortcut" + toString(i), itemId); } } @@ -77,9 +71,20 @@ void ItemShortcut::useItem(int index) if (mItems[index]) { Item *item = player_node->searchForItem(mItems[index]); - if (item && item->getQuantity()) { + if (item && item->getQuantity()) + { // TODO: Fix this (index vs. pointer mismatch) - //player_node->useItem(item); + /* + if (item->isEquipment()) { + if (item->isEquipped()) { + player_node->unequipItem(item); + } else { + player_node->equipItem(item); + } + } else { + player_node->useItem(item); + } + */ } } } diff --git a/src/joystick.cpp b/src/joystick.cpp index b69537cf..b05e9b5f 100644 --- a/src/joystick.cpp +++ b/src/joystick.cpp @@ -24,12 +24,17 @@ #include "configuration.h" #include "log.h" +#include <cassert> + int Joystick::joystickCount = 0; void Joystick::init() { SDL_InitSubSystem(SDL_INIT_JOYSTICK); - //SDL_JoystickEventState(SDL_ENABLE); + + // Have SDL call SDL_JoystickUpdate() automatically + SDL_JoystickEventState(SDL_ENABLE); + joystickCount = SDL_NumJoysticks(); logger->log("%i joysticks/gamepads found", joystickCount); for (int i = 0; i < joystickCount; i++) @@ -37,11 +42,11 @@ void Joystick::init() } Joystick::Joystick(int no): - mDirection(0), mCalibrating(false) + mDirection(0), + mCalibrating(false), + mEnabled(false) { - // TODO Bail out here? - if (no > joystickCount) - return; + assert(no < joystickCount); mJoystick = SDL_JoystickOpen(no); @@ -66,50 +71,39 @@ Joystick::Joystick(int no): Joystick::~Joystick() { - SDL_JoystickClose(mJoystick); + SDL_JoystickClose(mJoystick); } void Joystick::update() { mDirection = 0; - SDL_JoystickUpdate(); - // When calibrating, don't bother the outside with our state if (mCalibrating) { doCalibration(); return; }; - if (!mEnabled) return; + if (!mEnabled) + return; // X-Axis int position = SDL_JoystickGetAxis(mJoystick, 0); if (position >= mRightTolerance) - { mDirection |= RIGHT; - } else if (position <= mLeftTolerance) - { mDirection |= LEFT; - } // Y-Axis position = SDL_JoystickGetAxis(mJoystick, 1); if (position <= mUpTolerance) - { mDirection |= UP; - } else if (position >= mDownTolerance) - { mDirection |= DOWN; - } // Buttons for (int i = 0; i < MAX_BUTTONS; i++) - { mButtons[i] = (SDL_JoystickGetButton(mJoystick, i) == 1); - } } void Joystick::startCalibration() @@ -126,24 +120,16 @@ void Joystick::doCalibration() // X-Axis int position = SDL_JoystickGetAxis(mJoystick, 0); if (position > mRightTolerance) - { mRightTolerance = position; - } else if (position < mLeftTolerance) - { mLeftTolerance = position; - } // Y-Axis position = SDL_JoystickGetAxis(mJoystick, 1); if (position > mDownTolerance) - { mDownTolerance = position; - } else if (position < mUpTolerance) - { mUpTolerance = position; - } } void Joystick::finishCalibration() @@ -157,5 +143,5 @@ void Joystick::finishCalibration() bool Joystick::buttonPressed(unsigned char no) const { - return (no < MAX_BUTTONS) ? mButtons[no] : false; + return (mEnabled && no < MAX_BUTTONS) ? mButtons[no] : false; } diff --git a/src/joystick.h b/src/joystick.h index 4cc1babd..ee029915 100644 --- a/src/joystick.h +++ b/src/joystick.h @@ -35,7 +35,12 @@ class Joystick /** * Directions, to be used as bitmask values. */ - enum { UP = 1, DOWN = 2, LEFT = 4, RIGHT = 8 }; + enum { + UP = 1, + DOWN = 2, + LEFT = 4, + RIGHT = 8 + }; /** * Initializes the joystick subsystem. @@ -55,33 +60,27 @@ class Joystick ~Joystick(); - bool - isEnabled() const { return mEnabled; } + bool isEnabled() const { return mEnabled; } - void - setEnabled(bool enabled) { mEnabled = enabled; } + void setEnabled(bool enabled) { mEnabled = enabled; } /** * Updates the direction and button information. */ - void - update(); + void update(); - void - startCalibration(); + void startCalibration(); - void - finishCalibration(); + void finishCalibration(); - bool - isCalibrating() const { return mCalibrating; } + bool isCalibrating() const { return mCalibrating; } bool buttonPressed(unsigned char no) const; - bool isUp() const { return mDirection & UP; }; - bool isDown() const { return mDirection & DOWN; }; - bool isLeft() const { return mDirection & LEFT; }; - bool isRight() const { return mDirection & RIGHT; }; + bool isUp() const { return mEnabled && (mDirection & UP); }; + bool isDown() const { return mEnabled && (mDirection & DOWN); }; + bool isLeft() const { return mEnabled && (mDirection & LEFT); }; + bool isRight() const { return mEnabled && (mDirection & RIGHT); }; protected: unsigned char mDirection; @@ -97,4 +96,4 @@ class Joystick void doCalibration(); }; -#endif +#endif // _TMW_JOYSTICK_H diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp index 37d5f276..3e4e52c4 100644 --- a/src/keyboardconfig.cpp +++ b/src/keyboardconfig.cpp @@ -56,7 +56,16 @@ static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = { {"keyShortcut6", SDLK_6, "Item Shortcut 6"}, {"keyShortcut7", SDLK_7, "Item Shortcut 7"}, {"keyShortcut8", SDLK_8, "Item Shortcut 8"}, - {"keyShortcut9", SDLK_9, "Item Shortcut 9"} + {"keyShortcut9", SDLK_9, "Item Shortcut 9"}, + {"keyWindowStatus", SDLK_F2, "Status Window"}, + {"keyWindowInventory", SDLK_F3, "Inventory Window"}, + {"keyWindowEquipment", SDLK_F4, "Equipment WIndow"}, + {"keyWindowSkill", SDLK_F5, "Skill Window"}, + {"keyWindowMinimap", SDLK_F6, "Minimap Window"}, + {"keyWindowChat", SDLK_F7, "Chat Window"}, + {"keyWindowShortcut", SDLK_F8, "Item Shortcut Window"}, + {"keyWindowSetup", SDLK_F9, "Setup Window"}, + {"keyWindowDebug", SDLK_F10, "Debug Window"} }; void KeyboardConfig::init() diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h index d9886150..729bad5a 100644 --- a/src/keyboardconfig.h +++ b/src/keyboardconfig.h @@ -165,6 +165,15 @@ class KeyboardConfig KEY_SHORTCUT_7, KEY_SHORTCUT_8, KEY_SHORTCUT_9, + KEY_WINDOW_STATUS, + KEY_WINDOW_INVENTORY, + KEY_WINDOW_EQUIPMENT, + KEY_WINDOW_SKILL, + KEY_WINDOW_MINIMAP, + KEY_WINDOW_CHAT, + KEY_WINDOW_SHORTCUT, + KEY_WINDOW_SETUP, + KEY_WINDOW_DEBUG, KEY_TOTAL }; diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 14d253c0..ffb4aac9 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -353,10 +353,7 @@ void LocalPlayer::setDestination(Uint16 x, Uint16 y) void LocalPlayer::setWalkingDir(int dir) { - if (mWalkingDir != dir) - { - mWalkingDir = dir; - } + mWalkingDir = dir; // If we're not already walking, start walking. if (mAction != WALK && dir @@ -368,7 +365,7 @@ void LocalPlayer::setWalkingDir(int dir) void LocalPlayer::stopWalking(bool sendToServer) { - if(mAction == WALK && mWalkingDir){ + if (mAction == WALK && mWalkingDir) { mWalkingDir = 0; mLocalWalkTime = 0; Being::setDestination(getPosition().x,getPosition().y); diff --git a/src/localplayer.h b/src/localplayer.h index 5dce5ebe..0b9ba712 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -290,8 +290,6 @@ class LocalPlayer : public Player int getHP() const { return mHP; } - Uint32 mCharId; - int getMaxHP() const { return mMaxHP; } @@ -360,7 +358,6 @@ class LocalPlayer : public Player std::pair<int, int> getExperience(int skill); - float mLastAttackTime; /**< Used to synchronize the charge dialog */ Inventory *mInventory; const std::auto_ptr<Equipment> mEquipment; diff --git a/src/main.cpp b/src/main.cpp index 700e5676..2d6b08a8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -140,16 +140,15 @@ struct Options printHelp(false), printVersion(false), skipUpdate(false), - chooseDefault(false), serverPort(0) {}; bool printHelp; bool printVersion; bool skipUpdate; - bool chooseDefault; - std::string playername; + std::string username; std::string password; + std::string character; std::string configPath; std::string updateHost; std::string dataPath; @@ -169,7 +168,7 @@ void setUpdatesDir() // If updatesHost is currently empty, fill it from config file if (updateHost.empty()) { updateHost = - config.getValue("updatehost", "http://updates.thanaworld.org"); + config.getValue("updatehost", "http://updates.themanaworld.org"); } // Remove any trailing slash at the end of the update host @@ -455,10 +454,9 @@ void printHelp() " -d --data : Directory to load game data from\n" " -U --username : Login with this username\n" " -P --password : Login with this password\n" - " -D --default : Bypass the login process with default settings\n" " -s --server : Login Server name or IP\n" " -o --port : Login Server Port\n" - " -p --playername : Login with this player\n" + " -c --character : Login with this character\n" " -C --configfile : Configuration file to use\n" " -H --updatehost : Use this update host\n"; } @@ -475,7 +473,7 @@ void printVersion() void parseOptions(int argc, char *argv[], Options &options) { - const char *optstring = "hvud:U:P:Dp:s:o:C:H:"; + const char *optstring = "hvud:U:P:Dc:s:o:C:H:"; const struct option long_options[] = { { "help", no_argument, 0, 'h' }, @@ -484,17 +482,15 @@ void parseOptions(int argc, char *argv[], Options &options) { "data", required_argument, 0, 'd' }, { "username", required_argument, 0, 'U' }, { "password", required_argument, 0, 'P' }, - { "default", no_argument, 0, 'D' }, { "server", required_argument, 0, 's' }, { "port", required_argument, 0, 'o' }, - { "playername", required_argument, 0, 'p' }, + { "character", required_argument, 0, 'c' }, { "configfile", required_argument, 0, 'C' }, { "updatehost", required_argument, 0, 'H' }, { 0 } }; while (optind < argc) { - int result = getopt_long(argc, argv, optstring, long_options, NULL); if (result == -1) @@ -515,22 +511,19 @@ void parseOptions(int argc, char *argv[], Options &options) options.dataPath = optarg; break; case 'U': - options.playername = optarg; + options.username = optarg; break; case 'P': options.password = optarg; break; - case 'D': - options.chooseDefault = true; - break; case 's': options.serverName = optarg; break; case 'o': options.serverPort = (short)atoi(optarg); break; - case 'p': - options.playername = optarg; + case 'c': + options.character = optarg; break; case 'C': options.configPath = optarg; @@ -855,7 +848,7 @@ int main(int argc, char *argv[]) loginData.port = options.serverPort; } - loginData.username = options.playername; + loginData.username = options.username; if (loginData.username.empty()) { if (config.getValue("remember", 0)) { loginData.username = config.getValue("username", ""); @@ -920,7 +913,16 @@ int main(int argc, char *argv[]) } } - graphics->drawImage(login_wallpaper, 0, 0); + if (graphics->getWidth() > login_wallpaper->getWidth() || + graphics->getHeight() > login_wallpaper->getHeight()) + { + graphics->setColor(gcn::Color(64, 64, 64)); + graphics->fillRectangle(gcn::Rectangle( + 0, 0, graphics->getWidth(), graphics->getHeight())); + } + graphics->drawImage(login_wallpaper, + (graphics->getWidth() - login_wallpaper->getWidth()) / 2, + (graphics->getHeight() - login_wallpaper->getHeight()) / 2); gui->draw(); graphics->updateScreen(); @@ -980,16 +982,16 @@ int main(int argc, char *argv[]) logger->log("State: CHOOSE_SERVER"); // Allow changing this using a server choice dialog - // We show the dialog box only if the command-line options - // weren't set. + // We show the dialog box only if the command-line + // options weren't set. if (options.serverName.empty() && options.serverPort == 0) { currentDialog = new ServerDialog(&loginData); } else { state = STATE_CONNECT_ACCOUNT; - // Reset options so that cancelling or connect timeout - // will show the server dialog - options.serverName = ""; + // Reset options so that cancelling or connect + // timeout will show the server dialog. + options.serverName.clear(); options.serverPort = 0; } break; @@ -999,7 +1001,8 @@ int main(int argc, char *argv[]) logger->log("Trying to connect to account server..."); accountServerConnection->connect(loginData.hostname, loginData.port); - currentDialog = new ConnectionDialog(STATE_SWITCH_ACCOUNTSERVER_ATTEMPT); + currentDialog = new ConnectionDialog( + STATE_SWITCH_ACCOUNTSERVER_ATTEMPT); break; case STATE_UPDATE: @@ -1017,11 +1020,15 @@ int main(int argc, char *argv[]) case STATE_LOGIN: logger->log("State: LOGIN"); - currentDialog = new LoginDialog(&loginData); - // TODO: Restore autologin - //if (!loginData.password.empty()) { - // accountLogin(&loginData); - //} + if (options.username.empty() + || options.password.empty()) { + currentDialog = new LoginDialog(&loginData); + } else { + state = STATE_LOGIN_ATTEMPT; + // Clear the password so that when login fails, the + // dialog will show up next time. + options.password.clear(); + } break; case STATE_LOADDATA: @@ -1080,20 +1087,15 @@ int main(int argc, char *argv[]) case STATE_CHAR_SELECT: logger->log("State: CHAR_SELECT"); currentDialog = - new CharSelectDialog(&charInfo, &loginData); + new CharSelectDialog(&charInfo, &loginData); if (((CharSelectDialog*) currentDialog)-> - selectByName(options.playername)) - options.chooseDefault = true; - else - ((CharSelectDialog*) currentDialog)->selectByName( - config.getValue("lastCharacter", "")); - - if (options.chooseDefault) - { + selectByName(options.character)) { ((CharSelectDialog*) currentDialog)->action( gcn::ActionEvent(NULL, "ok")); - options.chooseDefault = false; + } else { + ((CharSelectDialog*) currentDialog)->selectByName( + config.getValue("lastCharacter", "")); } break; @@ -1106,7 +1108,7 @@ int main(int argc, char *argv[]) case STATE_CHANGEEMAIL: logger->log("State: CHANGE EMAIL"); currentDialog = new OkDialog("Email Address change", - "Email Address changed successfully!"); + "Email Address changed successfully!"); currentDialog->addActionListener(&accountListener); currentDialog = NULL; // OkDialog deletes itself loginData.email = loginData.newEmail; diff --git a/src/monster.cpp b/src/monster.cpp index a62c1f4c..c472a21b 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -35,12 +35,26 @@ Monster::Monster(Uint16 id, Uint16 job, Map *map): Being(id, job, map) { const MonsterInfo& info = getInfo(); - std::string filename = info.getSprite(); - if (filename.empty()) - filename = "error.xml"; - mSprites[BASE_SPRITE] = - AnimatedSprite::load("graphics/sprites/" + filename); + // Setup Monster sprites + int c = BASE_SPRITE; + const std::list<std::string> &sprites = info.getSprites(); + for (std::list<std::string>::const_iterator i = sprites.begin(); + i != sprites.end(); + i++) + { + if (c == VECTOREND_SPRITE) break; + + std::string file = "graphics/sprites/" + *i; + mSprites[c] = AnimatedSprite::load(file); + c++; + } + + // Ensure that something is shown + if (c == BASE_SPRITE) + { + mSprites[c] = AnimatedSprite::load("graphics/sprites/error.xml"); + } const std::list<std::string> &particleEffects = info.getParticleEffects(); for (std::list<std::string>::const_iterator i = particleEffects.begin(); @@ -111,7 +125,13 @@ Monster::setAction(Action action, int attackType) if (currentAction != ACTION_INVALID) { - mSprites[BASE_SPRITE]->play(currentAction); + for (int i = 0; i < VECTOREND_SPRITE; i++) + { + if (mSprites[i]) + { + mSprites[i]->play(currentAction); + } + } mAction = action; } } diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index 72371da5..f96cdcd5 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -32,6 +32,7 @@ #include "../localplayer.h" #include "../log.h" #include "../main.h" +#include "../npc.h" #include "../particle.h" #include "../sound.h" @@ -268,7 +269,7 @@ void BeingHandler::handleBeingAttackMessage(MessageIn &msg) int attackType = msg.readInt8(); if (!being) return; - + switch (direction) { case DIRECTION_UP: being->setDirection(Being::UP); break; @@ -347,3 +348,4 @@ void BeingHandler::handleBeingDirChangeMessage(MessageIn &msg) case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break; } } + diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index ad271f15..beb59250 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -50,6 +50,11 @@ extern BuyDialog *buyDialog; extern SellDialog *sellDialog; extern Window *buySellDialog; +/* Max. distance we are willing to scroll after a teleport; + * everything beyond will reset the port hard. + */ +static const int MAP_TELEPORT_SCROLL_DISTANCE = 8 * 32; + /** * Listener used for handling the overweigth message. */ @@ -292,6 +297,7 @@ PlayerHandler::handleMapChangeMessage(MessageIn &msg) const std::string mapName = msg.readString(); const unsigned short x = msg.readInt16(); const unsigned short y = msg.readInt16(); + const bool nearby = (engine->getCurrentMapName() == mapName); logger->log("Changing map to %s (%d, %d)", mapName.c_str(), x, y); @@ -301,8 +307,16 @@ PlayerHandler::handleMapChangeMessage(MessageIn &msg) current_npc = 0; const Vector &playerPos = player_node->getPosition(); - const float scrollOffsetX = x - (int) playerPos.x; - const float scrollOffsetY = y - (int) playerPos.y; + float scrollOffsetX = 0.0f; + float scrollOffsetY = 0.0f; + + /* Scroll if neccessary */ + if (!nearby + || (abs(x - (int) playerPos.x) > MAP_TELEPORT_SCROLL_DISTANCE) + || (abs(y - (int) playerPos.y) > MAP_TELEPORT_SCROLL_DISTANCE)) { + scrollOffsetX = x - (int) playerPos.x; + scrollOffsetY = y - (int) playerPos.y; + } player_node->setAction(Being::STAND); player_node->setPosition(x, y); diff --git a/src/particle.cpp b/src/particle.cpp index 8a15a132..c6e242bd 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -68,12 +68,21 @@ Particle::Particle(Map *map): mMomentum(1.0f) { Particle::particleCount++; - if (mMap) setSpriteIterator(mMap->addSprite(this)); + if (mMap) + setSpriteIterator(mMap->addSprite(this)); } +Particle::~Particle() +{ + // Remove from map sprite list + if (mMap) + mMap->removeSprite(mSpriteIterator); + // Delete child emitters and child particles + clear(); + Particle::particleCount--; +} -void -Particle::setupEngine() +void Particle::setupEngine() { Particle::maxCount = (int)config.getValue("particleMaxCount", 3000); Particle::fastPhysics = (int)config.getValue("particleFastPhysics", 0); @@ -82,17 +91,17 @@ Particle::setupEngine() logger->log("Particle engine set up"); } -void Particle::draw(Graphics *, int, int) const {} +void Particle::draw(Graphics *, int, int) const +{ +} -bool -Particle::update() +bool Particle::update() { - if (!mMap) return false; + if (!mMap) + return false; if (mLifetimeLeft == 0) - { mAlive = false; - } Vector oldPos = mPos; @@ -222,9 +231,8 @@ Particle::update() return true; } -Particle* -Particle::addEffect(const std::string &particleEffectFile, - int pixelX, int pixelY, int rotation) +Particle *Particle::addEffect(const std::string &particleEffectFile, + int pixelX, int pixelY, int rotation) { Particle *newParticle = NULL; @@ -298,11 +306,9 @@ Particle::addEffect(const std::string &particleEffectFile, return newParticle; } - -Particle* -Particle::addTextSplashEffect(const std::string &text, - int colorR, int colorG, int colorB, - gcn::Font *font, int x, int y) +Particle *Particle::addTextSplashEffect(const std::string &text, + int colorR, int colorG, int colorB, + gcn::Font *font, int x, int y) { Particle *newParticle = new TextParticle(mMap, text, colorR, colorG, colorB, font); @@ -320,11 +326,10 @@ Particle::addTextSplashEffect(const std::string &text, return newParticle; } -Particle* -Particle::addTextRiseFadeOutEffect(const std::string &text, - int colorR, int colorG, int colorB, - gcn::Font *font, - int x, int y) +Particle *Particle::addTextRiseFadeOutEffect(const std::string &text, + int colorR, int colorG, int colorB, + gcn::Font *font, + int x, int y) { Particle *newParticle = new TextParticle(mMap, text, colorR, colorG, colorB, font); newParticle->setPosition(x, y, 0); @@ -339,32 +344,18 @@ Particle::addTextRiseFadeOutEffect(const std::string &text, return newParticle; } -void -Particle::setMap(Map *map) +void Particle::setMap(Map *map) { mMap = map; - if (mMap) setSpriteIterator(mMap->addSprite(this)); + if (mMap) + setSpriteIterator(mMap->addSprite(this)); } - -Particle::~Particle() -{ - // Remove from map sprite list - if (mMap) mMap->removeSprite(mSpriteIterator); - // Delete child emitters and child particles - clear(); - Particle::particleCount--; -} - - -void -Particle::clear() +void Particle::clear() { - std::for_each(mChildEmitters.begin(), mChildEmitters.end(), - make_dtor(mChildEmitters)); + delete_all(mChildEmitters); mChildEmitters.clear(); - std::for_each(mChildParticles.begin(), mChildParticles.end(), - make_dtor(mChildParticles)); + delete_all(mChildParticles); mChildParticles.clear(); } diff --git a/src/particle.h b/src/particle.h index 4a11c4cb..af0caf21 100644 --- a/src/particle.h +++ b/src/particle.h @@ -67,22 +67,19 @@ class Particle : public Sprite /** * Deletes all child particles and emitters. */ - void - clear(); + void clear(); /** * Gives a particle the properties of an engine root particle and loads * the particle-related config settings. */ - void - setupEngine(); + void setupEngine(); /** * Updates particle position, returns false when the particle should * be deleted. */ - virtual bool - update(); + virtual bool update(); /** * Draws the particle image. @@ -92,8 +89,7 @@ class Particle : public Sprite /** * Necessary for sorting with the other sprites. */ - virtual int - getPixelY() const + virtual int getPixelY() const { return (int) (mPos.y + mPos.z) - 64; } /** @@ -105,46 +101,40 @@ class Particle : public Sprite * Creates a child particle that hosts some emitters described in the * particleEffectFile. */ - Particle* - addEffect(const std::string &particleEffectFile, - int pixelX, int pixelY, int rotation = 0); + Particle *addEffect(const std::string &particleEffectFile, + int pixelX, int pixelY, int rotation = 0); /** * Creates a standalone text particle. */ - Particle* - addTextSplashEffect(const std::string &text, - int colorR, int colorG, int colorB, - gcn::Font *font, int x, int y); + Particle *addTextSplashEffect(const std::string &text, + int colorR, int colorG, int colorB, + gcn::Font *font, int x, int y); /** * Creates a standalone text particle. */ - Particle* - addTextRiseFadeOutEffect(const std::string &text, - int colorR, int colorG, int colorB, - gcn::Font *font, - int x, int y); + Particle *addTextRiseFadeOutEffect(const std::string &text, + int colorR, int colorG, int colorB, + gcn::Font *font, + int x, int y); /** * Adds an emitter to the particle. */ - void - addEmitter (ParticleEmitter* emitter) + void addEmitter (ParticleEmitter* emitter) { mChildEmitters.push_back(emitter); } /** * Sets the position in 3 dimensional space in pixels relative to map. */ - void - setPosition(float x, float y, float z) + void setPosition(float x, float y, float z) { mPos.x = x; mPos.y = y; mPos.z = z; } /** * Sets the position in 2 dimensional space in pixels relative to map. */ - void - setPosition(float x, float y) + void setPosition(float x, float y) { mPos.x = x; mPos.y = y; } /** @@ -156,50 +146,45 @@ class Particle : public Sprite /** * Changes the particle position relative */ - void - moveBy(float x, float y, float z) + void moveBy(float x, float y, float z) { mPos.x += x; mPos.y += y; mPos.z += z; } - void - moveBy (Vector change) + void moveChildren(Vector change); + + void moveBy (Vector change) { mPos += change; } /** * Sets the time in game ticks until the particle is destroyed. */ - void - setLifetime(int lifetime) + void setLifetime(int lifetime) { mLifetimeLeft = lifetime; mLifetimePast = 0; } /** * Sets the age of the pixel in game ticks where the particle has * faded in completely. */ - void - setFadeOut(int fadeOut) + void setFadeOut(int fadeOut) { mFadeOut = fadeOut; } /** * Sets the remaining particle lifetime where the particle starts to * fade out. */ - void - setFadeIn(int fadeIn) + void setFadeIn(int fadeIn) { mFadeIn = fadeIn; } /** * Sets the alpha value of the particle */ - void - setAlpha(float alpha) + void setAlpha(float alpha) { mAlpha = alpha; } /** * Sets the sprite iterator of the particle on the current map to make * it easier to remove the particle from the map when it is destroyed. */ - void - setSpriteIterator(std::list<Sprite*>::iterator spriteIterator) + void setSpriteIterator(std::list<Sprite*>::iterator spriteIterator) { mSpriteIterator = spriteIterator; } /** @@ -212,44 +197,38 @@ class Particle : public Sprite /** * Sets the current velocity in 3 dimensional space. */ - void - setVelocity(float x, float y, float z) + void setVelocity(float x, float y, float z) { mVelocity.x = x; mVelocity.y = y; mVelocity.z = z; } /** * Sets the downward acceleration. */ - void - setGravity(float gravity) + void setGravity(float gravity) { mGravity = gravity; } /** * Sets the ammount of random vector changes */ - void - setRandomness(int r) + void setRandomness(int r) { mRandomness = r; } /** * Sets the ammount of velocity particles retain after * hitting the ground. */ - void - setBounce(float bouncieness) + void setBounce(float bouncieness) { mBounce = bouncieness; } /** * Sets the flag if the particle is supposed to be moved by its parent */ - void - setFollow(bool follow) + void setFollow(bool follow) { mFollow = follow; } /** * Gets the flag if the particle is supposed to be moved by its parent */ - bool - doesFollow() + bool doesFollow() { return mFollow; } /** @@ -271,6 +250,12 @@ class Particle : public Sprite { return mAlive; } /** + * Determines whether the particle and its children are all dead + */ + bool isExtinct() + { return !isAlive() && mChildParticles.empty(); } + + /** * Manually marks the particle for deletion. */ void kill() diff --git a/src/player.cpp b/src/player.cpp index 648b330a..19486d6e 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -35,10 +35,7 @@ #include "gui/gui.h" Player::Player(int id, int job, Map *map): - Being(id, job, map), - mGender(GENDER_UNSPECIFIED), - mHairStyle(0), - mHairColor(0) + Being(id, job, map) { } @@ -67,7 +64,7 @@ void Player::setGender(Gender gender) { if (gender != mGender) { - mGender = gender; + Being::setGender(gender); /* Human base sprite. When implementing different races remove this * line and set the base sprite when setting the race of the player @@ -88,28 +85,13 @@ void Player::setGender(Gender gender) void Player::setHairStyle(int style, int color) { - style = style < 0 ? mHairStyle : style % NR_HAIR_STYLES; - color = color < 0 ? mHairColor : color % NR_HAIR_COLORS; + style = style < 0 ? mHairStyle : style % getHairStylesNr(); + color = color < 0 ? mHairColor : color % getHairColorsNr(); if (style == mHairStyle && color == mHairColor) return; - mHairStyle = style; - mHairColor = color; + Being::setHairStyle(style, color); - static char const *const colors[NR_HAIR_COLORS] = - { - "#8c4b41,da9041,ffffff", // light brown - "#06372b,489e25,fdedcc", // green - "#5f0b33,91191c,f9ad81", // red - "#602486,934cc3,fdc689", // purple - "#805e74,c6b09b,ffffff", // gray - "#8c6625,dab425,ffffff", // yellow - "#1d2d6d,1594a3,fdedcc", // blue - "#831f2d,be4f2d,f8cc8b", // brown - "#432482,584bbc,dae8e5", // light blue - "#460850,611967,e7b4ae", // dark purple - }; - - setSprite(HAIR_SPRITE, style * -1, colors[color]); + setSprite(HAIR_SPRITE, style * -1, getHairColor(color)); setAction(mAction); } @@ -198,3 +180,5 @@ void Player::setInParty(bool value) { mInParty = value; } + + diff --git a/src/player.h b/src/player.h index 068e3cf5..6880ca20 100644 --- a/src/player.h +++ b/src/player.h @@ -28,12 +28,6 @@ class Graphics; class Map; class Guild; -enum Gender { - GENDER_MALE = 0, - GENDER_FEMALE = 1, - GENDER_UNSPECIFIED = 2 -}; - /** * A player being. Players have their name drawn beneath them. This class also * implements player-specific loading of base sprite, hair sprite and equipment @@ -61,24 +55,7 @@ class Player : public Being void setGender(Gender); /** - * Gets the hair color for this player. - */ - int getHairColor() const - { return mHairColor; } - - /** - * Gets the hair style for this player. - */ - int getHairStyle() const - { return mHairStyle; } - - /** * Sets the hair style and color for this player. - * - * NOTE: This method was necessary for convenience in the 0.0 client. - * It should be removed here since the server can provide the hair ID - * and coloring the same way it does for other equipment pieces. Then - * Being::setSprite can be used instead. */ void setHairStyle(int style, int color); @@ -139,10 +116,15 @@ class Player : public Being // Character guild information std::map<int, Guild*> mGuilds; + /** + * Triggers a visual/audio effect, such as `level up' + * + * \param effect_id ID of the effect to trigger + */ + virtual void + triggerEffect(int effectId) { internalTriggerEffect(effectId, true, true); } + private: - Gender mGender; - Uint8 mHairStyle; - Uint8 mHairColor; bool mInParty; }; diff --git a/src/properties.h b/src/properties.h index 2eafeeca..a593e8c2 100644 --- a/src/properties.h +++ b/src/properties.h @@ -35,8 +35,7 @@ class Properties /** * Destructor. */ - virtual - ~Properties() {} + virtual ~Properties() {} /** * Get a map property. @@ -46,8 +45,8 @@ class Properties * @return the value of the given property or the given default when it * doesn't exist. */ - const std::string& - getProperty(const std::string &name, const std::string &def = "") const + const std::string &getProperty(const std::string &name, + const std::string &def = "") const { PropertyMap::const_iterator i = mProperties.find(name); return (i != mProperties.end()) ? i->second : def; @@ -61,7 +60,7 @@ class Properties * @return the value of the given property, or 0.0f when it doesn't * exist. */ - float getFloatProperty(std::string const &name, float def = 0.0f) const + float getFloatProperty(const std::string &name, float def = 0.0f) const { PropertyMap::const_iterator i = mProperties.find(name); float ret = def; @@ -81,8 +80,7 @@ class Properties * @return <code>true</code> when a property is defined, * <code>false</code> otherwise. */ - bool - hasProperty(const std::string &name) const + bool hasProperty(const std::string &name) const { return (mProperties.find(name) != mProperties.end()); } @@ -93,8 +91,7 @@ class Properties * @param name The name of the property. * @param value The value of the property. */ - void - setProperty(const std::string &name, const std::string &value) + void setProperty(const std::string &name, const std::string &value) { mProperties[name] = value; } diff --git a/src/resources/action.cpp b/src/resources/action.cpp index ffbbffb2..bbea45c9 100644 --- a/src/resources/action.cpp +++ b/src/resources/action.cpp @@ -21,8 +21,6 @@ #include "action.h" -#include <algorithm> - #include "animation.h" #include "../utils/dtor.h" @@ -34,12 +32,10 @@ Action::Action() Action::~Action() { - std::for_each(mAnimations.begin(), mAnimations.end(), - make_dtor(mAnimations)); + delete_all(mAnimations); } -Animation* -Action::getAnimation(int direction) const +Animation *Action::getAnimation(int direction) const { Animations::const_iterator i = mAnimations.find(direction); @@ -53,8 +49,7 @@ Action::getAnimation(int direction) const return (i == mAnimations.end()) ? NULL : i->second; } -void -Action::setAnimation(int direction, Animation *animation) +void Action::setAnimation(int direction, Animation *animation) { mAnimations[direction] = animation; } diff --git a/src/resources/dye.cpp b/src/resources/dye.cpp index 3be105d8..d180d725 100644 --- a/src/resources/dye.cpp +++ b/src/resources/dye.cpp @@ -26,7 +26,7 @@ #include "../log.h" -Palette::Palette(std::string const &description) +Palette::Palette(const std::string &description) { int size = description.length(); if (size == 0) return; @@ -109,7 +109,7 @@ void Palette::getColor(int intensity, int color[3]) const color[2] = ((255 - t) * b1 + t * b2) / 255; } -Dye::Dye(std::string const &description) +Dye::Dye(const std::string &description) { for (int i = 0; i < 7; ++i) mPalettes[i] = 0; @@ -175,7 +175,7 @@ void Dye::update(int color[3]) const mPalettes[i - 1]->getColor(cmax, color); } -void Dye::instantiate(std::string &target, std::string const &palettes) +void Dye::instantiate(std::string &target, const std::string &palettes) { std::string::size_type next_pos = target.find('|'); if (next_pos == std::string::npos || palettes.empty()) return; diff --git a/src/resources/dye.h b/src/resources/dye.h index 528a1d91..f0bd7aab 100644 --- a/src/resources/dye.h +++ b/src/resources/dye.h @@ -36,7 +36,7 @@ class Palette * The string is either a file name or a sequence of hexadecimal RGB * values separated by ',' and starting with '#'. */ - Palette(std::string const &); + Palette(const std::string &); /** * Gets a pixel color depending on its intensity. @@ -63,7 +63,7 @@ class Dye * The parts of string are separated by semi-colons. Each part starts * by an uppercase letter, followed by a colon and then a palette name. */ - Dye(std::string const &); + Dye(const std::string &); /** * Destroys the associated palettes. @@ -79,7 +79,7 @@ class Dye * Fills the blank in a dye placeholder with some palette names. */ static void instantiate(std::string &target, - std::string const &palettes); + const std::string &palettes); private: diff --git a/src/resources/imageloader.cpp b/src/resources/imageloader.cpp index 29458ba3..835ba100 100644 --- a/src/resources/imageloader.cpp +++ b/src/resources/imageloader.cpp @@ -88,7 +88,7 @@ void ProxyImage::convertToDisplayFormat() mSDLImage = NULL; } -gcn::Image *ImageLoader::load(std::string const &filename, bool convert) +gcn::Image *ImageLoader::load(const std::string &filename, bool convert) { ResourceManager *resman = ResourceManager::getInstance(); ProxyImage *i = new ProxyImage(resman->loadSDLSurface(filename)); diff --git a/src/resources/imageloader.h b/src/resources/imageloader.h index 7979fd2f..821a0254 100644 --- a/src/resources/imageloader.h +++ b/src/resources/imageloader.h @@ -61,7 +61,8 @@ class ProxyImage : public gcn::Image class ImageLoader : public gcn::ImageLoader { public: - gcn::Image *load(std::string const &filename, bool convertToDisplayFormat); + gcn::Image *load(const std::string &filename, + bool convertToDisplayFormat); }; #endif diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index 01688619..04828d1b 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -176,10 +176,10 @@ void ItemDB::load() CHECK_PARAM(name, ""); CHECK_PARAM(image, ""); - // CHECK_PARAM(description, ""); - // CHECK_PARAM(effect, ""); + CHECK_PARAM(description, ""); + CHECK_PARAM(effect, ""); // CHECK_PARAM(type, 0); - CHECK_PARAM(weight, 0); + // CHECK_PARAM(weight, 0); // CHECK_PARAM(slot, 0); #undef CHECK_PARAM diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index cec74717..949d7913 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -43,9 +43,8 @@ const unsigned int DEFAULT_TILE_HEIGHT = 32; * Inflates either zlib or gzip deflated memory. The inflated memory is * expected to be freed by the caller. */ -int -inflateMemory(unsigned char *in, unsigned int inLength, - unsigned char *&out, unsigned int &outLength) +int inflateMemory(unsigned char *in, unsigned int inLength, + unsigned char *&out, unsigned int &outLength) { int bufferSize = 256 * 1024; int ret; @@ -109,9 +108,8 @@ inflateMemory(unsigned char *in, unsigned int inLength, return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; } -int -inflateMemory(unsigned char *in, unsigned int inLength, - unsigned char *&out) +int inflateMemory(unsigned char *in, unsigned int inLength, + unsigned char *&out) { unsigned int outLength = 0; int ret = inflateMemory(in, inLength, out, outLength); @@ -143,8 +141,7 @@ inflateMemory(unsigned char *in, unsigned int inLength, return outLength; } -Map* -MapReader::readMap(const std::string &filename) +Map *MapReader::readMap(const std::string &filename) { // Load the file through resource manager ResourceManager *resman = ResourceManager::getInstance(); @@ -201,8 +198,7 @@ MapReader::readMap(const std::string &filename) return map; } -Map* -MapReader::readMap(xmlNodePtr node, const std::string &path) +Map *MapReader::readMap(xmlNodePtr node, const std::string &path) { // Take the filename off the path const std::string pathDir = path.substr(0, path.rfind("/") + 1); @@ -280,8 +276,7 @@ MapReader::readMap(xmlNodePtr node, const std::string &path) return map; } -void -MapReader::readProperties(xmlNodePtr node, Properties* props) +void MapReader::readProperties(xmlNodePtr node, Properties *props) { for_each_xml_child_node(childNode, node) { @@ -311,8 +306,7 @@ static void setTile(Map *map, MapLayer *layer, int x, int y, int gid) } } -void -MapReader::readLayer(xmlNodePtr node, Map *map) +void MapReader::readLayer(xmlNodePtr node, Map *map) { // Layers are not necessarily the same size as the map const int w = XML::getProperty(node, "width", map->getWidth()); @@ -406,7 +400,13 @@ MapReader::readLayer(xmlNodePtr node, Map *map) setTile(map, layer, x, y, gid); x++; - if (x == w) {x = 0; y++;} + if (x == w) { + x = 0; y++; + + // When we're done, don't crash on too much data + if (y == h) + break; + } } free(binData); } @@ -440,10 +440,9 @@ MapReader::readLayer(xmlNodePtr node, Map *map) } } -Tileset* -MapReader::readTileset(xmlNodePtr node, - const std::string &path, - Map *map) +Tileset *MapReader::readTileset(xmlNodePtr node, + const std::string &path, + Map *map) { if (xmlHasProp(node, BAD_CAST "source")) { diff --git a/src/resources/mapreader.h b/src/resources/mapreader.h index 0142eb45..04e83b99 100644 --- a/src/resources/mapreader.h +++ b/src/resources/mapreader.h @@ -39,15 +39,13 @@ class MapReader /** * Read an XML map from a file. */ - static Map* - readMap(const std::string &filename); + static Map *readMap(const std::string &filename); /** * Read an XML map from a parsed XML tree. The path is used to find the * location of referenced tileset images. */ - static Map* - readMap(xmlNodePtr node, const std::string &path); + static Map *readMap(xmlNodePtr node, const std::string &path); private: /** @@ -57,26 +55,23 @@ class MapReader * @param props The Properties instance to which the properties will * be assigned. */ - static void - readProperties(xmlNodePtr node, Properties* props); + static void readProperties(xmlNodePtr node, Properties* props); /** * Reads a map layer and adds it to the given map. */ - static void - readLayer(xmlNodePtr node, Map *map); + static void readLayer(xmlNodePtr node, Map *map); /** * Reads a tile set. */ - static Tileset* - readTileset(xmlNodePtr node, const std::string &path, Map *map); + static Tileset *readTileset(xmlNodePtr node, const std::string &path, + Map *map); /** * Gets an integer property from an xmlNodePtr. */ - static int - getProperty(xmlNodePtr node, const char* name, int def); + static int getProperty(xmlNodePtr node, const char* name, int def); }; #endif diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp index 1d198a96..ed4acd38 100644 --- a/src/resources/monsterdb.cpp +++ b/src/resources/monsterdb.cpp @@ -19,8 +19,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <algorithm> - #include "monsterdb.h" #include "resourcemanager.h" @@ -44,7 +42,7 @@ MonsterDB::load() if (mLoaded) return; - mUnknown.setSprite("error.xml"); + mUnknown.addSprite("error.xml"); mUnknown.setName("unnamed"); logger->log("Initializing monster database..."); @@ -94,7 +92,7 @@ MonsterDB::load() { if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite")) { - currentInfo->setSprite((const char*) spriteNode->xmlChildrenNode->content); + currentInfo->addSprite((const char*) spriteNode->xmlChildrenNode->content); } else if (xmlStrEqual(spriteNode->name, BAD_CAST "sound")) { @@ -147,19 +145,16 @@ MonsterDB::load() mLoaded = true; } -void -MonsterDB::unload() +void MonsterDB::unload() { - for_each(mMonsterInfos.begin(), mMonsterInfos.end(), - make_dtor(mMonsterInfos)); + delete_all(mMonsterInfos); mMonsterInfos.clear(); mLoaded = false; } -const MonsterInfo& -MonsterDB::get(int id) +const MonsterInfo &MonsterDB::get(int id) { MonsterInfoIterator i = mMonsterInfos.find(id); diff --git a/src/resources/monsterinfo.cpp b/src/resources/monsterinfo.cpp index bac9c35f..1e982213 100644 --- a/src/resources/monsterinfo.cpp +++ b/src/resources/monsterinfo.cpp @@ -23,8 +23,7 @@ #include "../utils/dtor.h" -MonsterInfo::MonsterInfo(): - mSprite("error.xml") +MonsterInfo::MonsterInfo() { } diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h index f13c2f7c..88f6fb2b 100644 --- a/src/resources/monsterinfo.h +++ b/src/resources/monsterinfo.h @@ -67,7 +67,8 @@ class MonsterInfo setName(const std::string &name) { mName = name; } void - setSprite(const std::string &filename) { mSprite = filename; } + addSprite(const std::string &filename) + { mSprites.push_back(filename); } void setTargetCursorSize(Being::TargetCursorSize targetCursorSize) @@ -82,8 +83,8 @@ class MonsterInfo const std::string& getName() const { return mName; } - const std::string& - getSprite() const { return mSprite; } + const std::list<std::string>& + getSprites() const { return mSprites; } Being::TargetCursorSize getTargetCursorSize() const { return mTargetCursorSize; } @@ -106,7 +107,7 @@ class MonsterInfo private: std::string mName; - std::string mSprite; + std::list<std::string> mSprites; Being::TargetCursorSize mTargetCursorSize; std::map<MonsterSoundEvent, std::vector<std::string>* > mSounds; std::map<int, MonsterAttack*> mMonsterAttacks; diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 8ee64452..bebd17f8 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -93,8 +93,7 @@ ResourceManager::~ResourceManager() } } -void -ResourceManager::cleanUp(Resource *res) +void ResourceManager::cleanUp(Resource *res) { logger->log("ResourceManager::~ResourceManager() cleaning up %d " "reference%s to %s", @@ -126,24 +125,22 @@ void ResourceManager::cleanOrphans() else { logger->log("ResourceManager::release(%s)", res->mIdPath.c_str()); - delete res; ResourceIterator toErase = iter; ++iter; mOrphanedResources.erase(toErase); + delete res; // delete only after removal from list, to avoid issues in recursion } } mOldestOrphan = oldest; } -bool -ResourceManager::setWriteDir(const std::string &path) +bool ResourceManager::setWriteDir(const std::string &path) { return (bool) PHYSFS_setWriteDir(path.c_str()); } -bool -ResourceManager::addToSearchPath(const std::string &path, bool append) +bool ResourceManager::addToSearchPath(const std::string &path, bool append) { logger->log("Adding to PhysicsFS: %s", path.c_str()); if (!PHYSFS_addToSearchPath(path.c_str(), append ? 1 : 0)) { @@ -153,8 +150,7 @@ ResourceManager::addToSearchPath(const std::string &path, bool append) return true; } -void -ResourceManager::searchAndAddArchives(const std::string &path, +void ResourceManager::searchAndAddArchives(const std::string &path, const std::string &ext, bool append) { @@ -180,31 +176,27 @@ ResourceManager::searchAndAddArchives(const std::string &path, PHYSFS_freeList(list); } -bool -ResourceManager::mkdir(const std::string &path) +bool ResourceManager::mkdir(const std::string &path) { return (bool) PHYSFS_mkdir(path.c_str()); } -bool -ResourceManager::exists(const std::string &path) +bool ResourceManager::exists(const std::string &path) { return PHYSFS_exists(path.c_str()); } -bool -ResourceManager::isDirectory(const std::string &path) +bool ResourceManager::isDirectory(const std::string &path) { return PHYSFS_isDirectory(path.c_str()); } -std::string -ResourceManager::getPath(const std::string &file) +std::string ResourceManager::getPath(const std::string &file) { // get the real path to the file const char* tmp = PHYSFS_getRealDir(file.c_str()); std::string path; - + // if the file is not in the search path, then its NULL if (tmp) { @@ -215,11 +207,12 @@ ResourceManager::getPath(const std::string &file) // if not found in search path return the default path path = std::string(TMW_DATADIR) + std::string("data") + "/" + file; } - + return path; } -Resource *ResourceManager::get(std::string const &idPath, generator fun, void *data) +Resource *ResourceManager::get(const std::string &idPath, generator fun, + void *data) { // Check if the id exists, and return the value if it does. ResourceIterator resIter = mResources.find(idPath); @@ -270,20 +263,18 @@ struct ResourceLoader } }; -Resource *ResourceManager::load(std::string const &path, loader fun) +Resource *ResourceManager::load(const std::string &path, loader fun) { ResourceLoader l = { this, path, fun }; return get(path, ResourceLoader::load, &l); } -Music* -ResourceManager::getMusic(const std::string &idPath) +Music *ResourceManager::getMusic(const std::string &idPath) { return static_cast<Music*>(load(idPath, Music::load)); } -SoundEffect* -ResourceManager::getSoundEffect(const std::string &idPath) +SoundEffect *ResourceManager::getSoundEffect(const std::string &idPath) { return static_cast<SoundEffect*>(load(idPath, SoundEffect::load)); } @@ -314,7 +305,7 @@ struct DyedImageLoader } }; -Image *ResourceManager::getImage(std::string const &idPath) +Image *ResourceManager::getImage(const std::string &idPath) { DyedImageLoader l = { this, idPath }; return static_cast<Image*>(get(idPath, DyedImageLoader::load, &l)); @@ -336,8 +327,8 @@ struct ImageSetLoader } }; -ImageSet* -ResourceManager::getImageSet(const std::string &imagePath, int w, int h) +ImageSet *ResourceManager::getImageSet(const std::string &imagePath, + int w, int h) { ImageSetLoader l = { this, imagePath, w, h }; std::stringstream ss; @@ -356,8 +347,7 @@ struct SpriteDefLoader } }; -SpriteDef *ResourceManager::getSprite - (std::string const &path, int variant) +SpriteDef *ResourceManager::getSprite(const std::string &path, int variant) { SpriteDefLoader l = { path, variant }; std::stringstream ss; @@ -383,23 +373,21 @@ void ResourceManager::release(Resource *res) mResources.erase(resIter); } -ResourceManager* -ResourceManager::getInstance() +ResourceManager *ResourceManager::getInstance() { // Create a new instance if necessary. - if (instance == NULL) instance = new ResourceManager(); + if (!instance) + instance = new ResourceManager(); return instance; } -void -ResourceManager::deleteInstance() +void ResourceManager::deleteInstance() { delete instance; instance = NULL; } -void* -ResourceManager::loadFile(const std::string &fileName, int &fileSize) +void *ResourceManager::loadFile(const std::string &fileName, int &fileSize) { // Attempt to open the specified file using PhysicsFS PHYSFS_file *file = PHYSFS_openRead(fileName.c_str()); @@ -451,8 +439,7 @@ ResourceManager::loadTextFile(const std::string &fileName) return lines; } -SDL_Surface* -ResourceManager::loadSDLSurface(const std::string& filename) +SDL_Surface *ResourceManager::loadSDLSurface(const std::string& filename) { int fileSize; void *buffer = loadFile(filename, fileSize); diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index 66813a9c..e70dfb9d 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -64,8 +64,7 @@ class ResourceManager * @param path The path of the directory to be added. * @return <code>true</code> on success, <code>false</code> otherwise. */ - bool - setWriteDir(const std::string &path); + bool setWriteDir(const std::string &path); /** * Adds a directory or archive to the search path. If append is true @@ -74,37 +73,33 @@ class ResourceManager * * @return <code>true</code> on success, <code>false</code> otherwise. */ - bool - addToSearchPath(const std::string &path, bool append); + bool addToSearchPath(const std::string &path, bool append); /** * Searches for zip files and adds them to the search path. */ - void - searchAndAddArchives(const std::string &path, - const std::string &ext, - bool append); + void searchAndAddArchives(const std::string &path, + const std::string &ext, + bool append); /** * Creates a directory in the write path */ - bool - mkdir(const std::string &path); + bool mkdir(const std::string &path); /** * Checks whether the given file or directory exists in the search path */ - bool - exists(const std::string &path); + bool exists(const std::string &path); /** * Checks whether the given path is a directory. */ - bool - isDirectory(const std::string &path); - + bool isDirectory(const std::string &path); + /** - * Returns the real path to a file + * Returns the real path to a file. Note that this method will always + * return a path, it does not check whether the file exists. * * @param file The file to get the real path to. * @return The real path. @@ -120,7 +115,7 @@ class ResourceManager * @return A valid resource or <code>NULL</code> if the resource could * not be generated. */ - Resource *get(std::string const &idPath, generator fun, void *data); + Resource *get(const std::string &idPath, generator fun, void *data); /** * Loads a resource from a file and adds it to the resource map. @@ -130,41 +125,37 @@ class ResourceManager * @return A valid resource or <code>NULL</code> if the resource could * not be loaded. */ - Resource *load(std::string const &path, loader fun); + Resource *load(const std::string &path, loader fun); /** * Convenience wrapper around ResourceManager::get for loading * images. */ - Image* - getImage(const std::string &idPath); + Image *getImage(const std::string &idPath); /** * Convenience wrapper around ResourceManager::get for loading * songs. */ - Music* - getMusic(const std::string &idPath); + Music *getMusic(const std::string &idPath); /** * Convenience wrapper around ResourceManager::get for loading * samples. */ - SoundEffect* - getSoundEffect(const std::string &idPath); + SoundEffect *getSoundEffect(const std::string &idPath); /** * Creates a image set based on the image referenced by the given * path and the supplied sprite sizes */ - ImageSet* - getImageSet(const std::string &imagePath, int w, int h); + ImageSet *getImageSet(const std::string &imagePath, int w, int h); /** * Creates a sprite definition based on a given path and the supplied * variant. */ - SpriteDef *getSprite(std::string const &path, int variant = 0); + SpriteDef *getSprite(const std::string &path, int variant = 0); /** * Releases a resource, placing it in the set of orphaned resources. @@ -181,41 +172,35 @@ class ResourceManager * @return An allocated byte array containing the data that was loaded, * or <code>NULL</code> on fail. */ - void* - loadFile(const std::string &fileName, int &fileSize); + void *loadFile(const std::string &fileName, int &fileSize); /** * Retrieves the contents of a text file. */ - std::vector<std::string> - loadTextFile(const std::string &fileName); + std::vector<std::string> loadTextFile(const std::string &fileName); /** * Loads the given filename as an SDL surface. The returned surface is * expected to be freed by the caller using SDL_FreeSurface. */ - SDL_Surface* - loadSDLSurface(const std::string& filename); + SDL_Surface *loadSDLSurface(const std::string& filename); /** * Returns an instance of the class, creating one if it does not * already exist. */ - static ResourceManager* - getInstance(); + static ResourceManager *getInstance(); /** * Deletes the class instance if it exists. */ - static void - deleteInstance(); + static void deleteInstance(); private: /** * Deletes the resource after logging a cleanup message. */ - static void - cleanUp(Resource *resource); + static void cleanUp(Resource *resource); void cleanOrphans(); diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp index 5aea55fa..f5b763ea 100644 --- a/src/resources/spritedef.cpp +++ b/src/resources/spritedef.cpp @@ -33,8 +33,7 @@ #include "../log.h" #include "../utils/xml.h" -Action* -SpriteDef::getAction(SpriteAction action) const +Action *SpriteDef::getAction(SpriteAction action) const { Actions::const_iterator i = mActions.find(action); @@ -47,7 +46,7 @@ SpriteDef::getAction(SpriteAction action) const return i->second; } -SpriteDef *SpriteDef::load(std::string const &animationFile, int variant) +SpriteDef *SpriteDef::load(const std::string &animationFile, int variant) { std::string::size_type pos = animationFile.find('|'); std::string palettes; @@ -122,7 +121,7 @@ void SpriteDef::loadSprite(xmlNodePtr spriteNode, int variant, } } -void SpriteDef::loadImageSet(xmlNodePtr node, std::string const &palettes) +void SpriteDef::loadImageSet(xmlNodePtr node, const std::string &palettes) { const std::string name = XML::getProperty(node, "name", ""); @@ -147,8 +146,7 @@ void SpriteDef::loadImageSet(xmlNodePtr node, std::string const &palettes) mImageSets[name] = imageSet; } -void -SpriteDef::loadAction(xmlNodePtr node, int variant_offset) +void SpriteDef::loadAction(xmlNodePtr node, int variant_offset) { const std::string actionName = XML::getProperty(node, "name", ""); const std::string imageSetName = XML::getProperty(node, "imageset", ""); @@ -188,10 +186,9 @@ SpriteDef::loadAction(xmlNodePtr node, int variant_offset) } } -void -SpriteDef::loadAnimation(xmlNodePtr animationNode, - Action *action, ImageSet *imageSet, - int variant_offset) +void SpriteDef::loadAnimation(xmlNodePtr animationNode, + Action *action, ImageSet *imageSet, + int variant_offset) { const std::string directionName = XML::getProperty(animationNode, "direction", ""); @@ -268,8 +265,7 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode, } // for frameNode } -void -SpriteDef::includeSprite(xmlNodePtr includeNode) +void SpriteDef::includeSprite(xmlNodePtr includeNode) { // TODO: Perform circular dependency check, since it's easy to crash the // client this way. @@ -290,8 +286,7 @@ SpriteDef::includeSprite(xmlNodePtr includeNode) loadSprite(rootNode, 0); } -void -SpriteDef::substituteAction(SpriteAction complete, SpriteAction with) +void SpriteDef::substituteAction(SpriteAction complete, SpriteAction with) { if (mActions.find(complete) == mActions.end()) { @@ -325,8 +320,7 @@ SpriteDef::~SpriteDef() } } -SpriteAction -SpriteDef::makeSpriteAction(const std::string& action) +SpriteAction SpriteDef::makeSpriteAction(const std::string &action) { if (action == "" || action == "default") { return ACTION_DEFAULT; @@ -408,8 +402,7 @@ SpriteDef::makeSpriteAction(const std::string& action) } } -SpriteDirection -SpriteDef::makeSpriteDirection(const std::string& direction) +SpriteDirection SpriteDef::makeSpriteDirection(const std::string& direction) { if (direction == "" || direction == "default") { return DIRECTION_DEFAULT; @@ -428,5 +421,5 @@ SpriteDef::makeSpriteDirection(const std::string& direction) } else { return DIRECTION_INVALID; - }; + } } diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h index 56b9a713..0c3e443b 100644 --- a/src/resources/spritedef.h +++ b/src/resources/spritedef.h @@ -81,7 +81,7 @@ class SpriteDef : public Resource /** * Loads a sprite definition file. */ - static SpriteDef *load(std::string const &file, int variant); + static SpriteDef *load(const std::string &file, int variant); /** * Returns the specified action. @@ -91,8 +91,7 @@ class SpriteDef : public Resource /** * Converts a string into a SpriteAction enum. */ - static SpriteAction - makeSpriteAction(const std::string &action); + static SpriteAction makeSpriteAction(const std::string &action); private: /** @@ -114,27 +113,24 @@ class SpriteDef : public Resource /** * Loads an imageset element. */ - void loadImageSet(xmlNodePtr node, std::string const &palettes); + void loadImageSet(xmlNodePtr node, const std::string &palettes); /** * Loads an action element. */ - void - loadAction(xmlNodePtr node, int variant_offset); + void loadAction(xmlNodePtr node, int variant_offset); /** * Loads an animation element. */ - void - loadAnimation(xmlNodePtr animationNode, - Action *action, ImageSet *imageSet, - int variant_offset); + void loadAnimation(xmlNodePtr animationNode, + Action *action, ImageSet *imageSet, + int variant_offset); /** * Include another sprite into this one. */ - void - includeSprite(xmlNodePtr includeNode); + void includeSprite(xmlNodePtr includeNode); /** * Complete missing actions by copying existing ones. @@ -145,8 +141,7 @@ class SpriteDef : public Resource * When there are no animations defined for the action "complete", its * animations become a copy of those of the action "with". */ - void - substituteAction(SpriteAction complete, SpriteAction with); + void substituteAction(SpriteAction complete, SpriteAction with); /** * Converts a string into a SpriteDirection enum. diff --git a/src/textparticle.h b/src/textparticle.h index 3a0ba674..d56dbf84 100644 --- a/src/textparticle.h +++ b/src/textparticle.h @@ -37,11 +37,11 @@ class TextParticle : public Particle TextParticle(Map *map, const std::string &text, int colorR, int colorG, int colorB, gcn::Font *font); + /** * Draws the particle image. */ - virtual void - draw(Graphics *graphics, int offsetX, int offsetY) const; + virtual void draw(Graphics *graphics, int offsetX, int offsetY) const; // hack to improve text visibility virtual int getPixelY() const diff --git a/src/utils/mutex.h b/src/utils/mutex.h new file mode 100644 index 00000000..62c6b4e1 --- /dev/null +++ b/src/utils/mutex.h @@ -0,0 +1,97 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TMW_MUTEX_H +#define TMW_MUTEX_H + +#include <SDL_thread.h> + +#include "../log.h" + +/** + * A mutex provides mutual exclusion of access to certain data that is + * accessed by multiple threads. + */ +class Mutex +{ +public: + Mutex(); + ~Mutex(); + + void lock(); + void unlock(); + +private: + Mutex(const Mutex&); // prevent copying + Mutex& operator=(const Mutex&); + + SDL_mutex *mMutex; +}; + +/** + * A convenience class for locking a mutex. + */ +class MutexLocker +{ +public: + MutexLocker(Mutex *mutex); + ~MutexLocker(); + +private: + Mutex *mMutex; +}; + + +inline Mutex::Mutex() +{ + mMutex = SDL_CreateMutex(); +} + +inline Mutex::~Mutex() +{ + SDL_DestroyMutex(mMutex); +} + +inline void Mutex::lock() +{ + if (SDL_mutexP(mMutex) == -1) + logger->log("Mutex locking failed: %s", SDL_GetError()); +} + +inline void Mutex::unlock() +{ + if (SDL_mutexV(mMutex) == -1) + logger->log("Mutex unlocking failed: %s", SDL_GetError()); +} + + +inline MutexLocker::MutexLocker(Mutex *mutex): + mMutex(mutex) +{ + mMutex->lock(); +} + +inline MutexLocker::~MutexLocker() +{ + mMutex->unlock(); +} + +#endif // TMW_MUTEX_H diff --git a/src/utils/strprintf.cpp b/src/utils/strprintf.cpp index c8a8a247..c5d7a595 100644 --- a/src/utils/strprintf.cpp +++ b/src/utils/strprintf.cpp @@ -19,10 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _TMW_UTILS_TOSTRING_H -#define _TMW_UTILS_TOSTRING_H - #include <cstdarg> +#include <cstdio> #include "strprintf.h" @@ -47,5 +45,3 @@ std::string strprintf(char const *format, ...) delete [] buf2; return res; } - -#endif |