summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/animation.cpp389
-rw-r--r--src/animation.h160
-rw-r--r--src/base64.cpp2
-rw-r--r--src/being.cpp185
-rw-r--r--src/being.h62
-rw-r--r--src/engine.cpp9
-rw-r--r--src/game.cpp2
-rw-r--r--src/graphic/spriteset.cpp18
-rw-r--r--src/graphic/spriteset.h9
-rw-r--r--src/graphics.cpp6
-rw-r--r--src/gui/chargedialog.h2
-rw-r--r--src/gui/inventorywindow.h2
-rw-r--r--src/gui/menuwindow.h2
-rw-r--r--src/gui/minimap.h2
-rw-r--r--src/gui/ministatus.h2
-rw-r--r--src/gui/newskill.h4
-rw-r--r--src/gui/sell.cpp2
-rw-r--r--src/gui/setup_video.cpp6
-rw-r--r--src/gui/setup_video.h2
-rw-r--r--src/gui/status.h4
-rw-r--r--src/localplayer.cpp12
-rw-r--r--src/main.cpp12
-rw-r--r--src/monster.cpp41
-rw-r--r--src/monster.h2
-rw-r--r--src/net/beinghandler.cpp38
-rw-r--r--src/net/charserverhandler.cpp6
-rw-r--r--src/net/playerhandler.cpp4
-rw-r--r--src/npc.cpp26
-rw-r--r--src/npc.h2
-rw-r--r--src/player.cpp161
-rw-r--r--src/player.h13
-rw-r--r--src/resources/imagewriter.cpp2
-rw-r--r--src/resources/itemmanager.cpp3
-rw-r--r--src/sound.h2
35 files changed, 947 insertions, 249 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e4fef745..c6db2ec6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -181,6 +181,8 @@ tmw_SOURCES = graphic/spriteset.cpp \
resources/buddylist.cpp \
utils/dtor.h \
utils/tostring.h \
+ animation.cpp \
+ animation.h \
base64.cpp \
base64.h \
being.cpp \
diff --git a/src/animation.cpp b/src/animation.cpp
new file mode 100644
index 00000000..57fb931a
--- /dev/null
+++ b/src/animation.cpp
@@ -0,0 +1,389 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "animation.h"
+
+#include <libxml/tree.h>
+
+#include "log.h"
+
+#include "graphic/spriteset.h"
+
+#include "resources/image.h"
+#include "resources/resourcemanager.h"
+
+#define READ_PROP(node, prop, name, target, cast) \
+ prop = xmlGetProp(node, BAD_CAST name); \
+ if (prop) { \
+ target = cast((const char*)prop); \
+ xmlFree(prop); \
+ }
+
+Animation::Animation():
+ mTime(0)
+{
+ iCurrentPhase = mAnimationPhases.begin();
+}
+
+void
+Animation::update(unsigned int time)
+{
+ mTime += time;
+ if (!mAnimationPhases.empty())
+ {
+ while ((mTime > (*iCurrentPhase).delay) &&
+ (*iCurrentPhase).delay > 0)
+ {
+ mTime -= (*iCurrentPhase).delay;
+ iCurrentPhase++;
+ if (iCurrentPhase == mAnimationPhases.end())
+ {
+ iCurrentPhase = mAnimationPhases.begin();
+ }
+ }
+ }
+}
+
+int
+Animation::getCurrentPhase()
+{
+ if (mAnimationPhases.empty())
+ {
+ return -1;
+ }
+ else
+ {
+ return (*iCurrentPhase).image;
+ }
+}
+
+void
+Animation::addPhase (int image, unsigned int delay, int offsetX, int offsetY)
+{
+ //add new phase to animation list
+ AnimationPhase newPhase;
+ newPhase.image = image;
+ newPhase.delay = delay;
+ newPhase.offsetX = offsetX;
+ newPhase.offsetY = offsetY;
+ mAnimationPhases.push_back(newPhase);
+ //reset animation circle
+ iCurrentPhase = mAnimationPhases.begin();
+}
+
+Action::Action()
+ :mImageset("")
+{
+ //NOOP
+}
+
+Action::~Action()
+{
+ for (AnimationIterator i = mAnimations.begin(); i != mAnimations.end(); i++)
+ {
+ delete i->second;
+ }
+ mAnimations.clear();
+}
+
+Animation *
+Action::getAnimation(std::string direction)
+{
+ Animation *animation = NULL;
+ AnimationIterator i = mAnimations.find(direction);
+ if (i == mAnimations.end())
+ {
+ //when the direction isn't defined just use another one
+ animation = mAnimations["default"];
+ }
+ else
+ {
+ animation = mAnimations[direction];
+ }
+
+ return animation;
+}
+
+void
+Action::setAnimation(std::string direction, Animation *animation)
+{
+ //set first direction as default direction
+ if (mAnimations.empty())
+ {
+ mAnimations["default"] = animation;
+ }
+
+ mAnimations[direction] = animation;
+}
+
+
+AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
+ mAction("stand"), mDirection("down"), mLastTime(0)
+{
+ int variant_num = 0;
+ int variant_offset = 0;
+ int size;
+ ResourceManager *resman = ResourceManager::getInstance();
+ char *data = (char*)resman->loadFile(
+ animationFile.c_str(), size);
+
+ if (!data) {
+ logger->error("Animation: Could not find " + animationFile + " !");
+ }
+
+ xmlDocPtr doc = xmlParseMemory(data, size);
+ free(data);
+
+ if (!doc)
+ {
+ logger->error("Animation: Error while parsing animation definition file!");
+ return;
+ }
+
+ xmlNodePtr node = xmlDocGetRootElement(doc);
+ if (!node || !xmlStrEqual(node->name, BAD_CAST "sprite"))
+ {
+ logger->error("Animation: this is not a valid animation definition file!");
+ return;
+ }
+
+ //get the variant
+ xmlChar *prop = NULL;
+ READ_PROP(node, prop, "variants", variant_num, atoi);
+ READ_PROP(node, prop, "variant_offset", variant_offset, atoi);
+
+ if (variant_num > 0 && variant < variant_num )
+ {
+ variant_offset *= variant;
+ }
+ else
+ {
+ variant_offset = 0;
+ }
+
+ for (node = node->xmlChildrenNode; node != NULL; node = node->next)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "imageset"))
+ {
+ int width = 0, height = 0;
+ std::string name = "", imageSrc = "";
+ xmlChar *prop = NULL;
+ READ_PROP(node, prop, "name", name, );
+ READ_PROP(node, prop, "src", imageSrc, );
+ READ_PROP(node, prop, "width", width, atoi);
+ READ_PROP(node, prop, "height", height, atoi);
+
+ Spriteset *spriteset = resman->createSpriteset(
+ imageSrc, width, height);
+ if (!spriteset)
+ {
+ logger->error("Couldn't load spriteset!");
+ }
+ else
+ {
+ mSpritesets[name] = spriteset;
+ }
+ }
+ // get action
+ else if (xmlStrEqual(node->name, BAD_CAST "action"))
+ {
+ std::string name = "", imageset = "";
+ xmlChar *prop = NULL;
+ READ_PROP(node, prop, "name", name, );
+ READ_PROP(node, prop, "imageset", imageset, );
+
+ Action *action = new Action();
+ mActions[name] = action;
+ action->setImageset(imageset);
+
+ //get animations
+ for ( xmlNodePtr animationNode = node->xmlChildrenNode;
+ animationNode != NULL;
+ animationNode = animationNode->next)
+ {
+ if (xmlStrEqual(animationNode->name, BAD_CAST "animation"))
+ {
+ std::string direction = "";
+
+
+ Animation *animation = new Animation();
+ READ_PROP(animationNode, prop, "direction", direction, );
+
+ //get animation phases
+ for ( xmlNodePtr phaseNode = animationNode->xmlChildrenNode;
+ phaseNode != NULL;
+ phaseNode = phaseNode->next)
+ {
+ int index = -1;
+ int start = 0;
+ int end = 0;
+ int delay = 0;
+ int offsetX = 0;
+ int offsetY = 0;
+ if (xmlStrEqual(phaseNode->name, BAD_CAST "frame"))
+ {
+ READ_PROP(phaseNode, prop, "index", index, atoi);
+ READ_PROP(phaseNode, prop, "delay", delay, atoi);
+ READ_PROP(phaseNode, prop, "offsetX", offsetX, atoi);
+ READ_PROP(phaseNode, prop, "offsetY", offsetY, atoi);
+ offsetY = offsetY - mSpritesets[imageset]->getHeight() + 32;
+ offsetX = offsetX - mSpritesets[imageset]->getWidth() / 2 + 16;
+ animation->addPhase(index + variant_offset, delay, offsetX, offsetY);
+ }
+ if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence"))
+ {
+ READ_PROP(phaseNode, prop, "start", start, atoi);
+ READ_PROP(phaseNode, prop, "end", end, atoi);
+ READ_PROP(phaseNode, prop, "delay", delay, atoi);
+ offsetY = 0 - mSpritesets[imageset]->getHeight() + 32;
+ offsetX = 0 - mSpritesets[imageset]->getWidth() / 2 + 16;
+ while (end >= start)
+ {
+ animation->addPhase(start + variant_offset, delay, offsetX, offsetY);
+ start++;
+ }
+ }
+ } // for phaseNode
+ action->setAnimation(direction, animation);
+ } // if "<animation>"
+ } // for animationNode
+ } // if "<imageset>" else if "<action>"
+ } // for node
+
+ //complete missing actions
+ substituteAction("stand", "");
+ substituteAction("walk", "stand");
+ substituteAction("walk", "run");
+ substituteAction("attack", "stand");
+ substituteAction("attack_swing", "attack");
+ substituteAction("attack_stab", "attack_swing");
+ substituteAction("attack_bow", "attack_stab");
+ substituteAction("attack_throw", "attack_swing");
+ substituteAction("cast_magic", "attack_swing");
+ substituteAction("use_item", "cast_magic");
+ substituteAction("sit", "stand");
+ substituteAction("sleeping", "sit");
+ substituteAction("hurt", "stand");
+ substituteAction("dead", "hurt");
+
+ xmlFreeDoc(doc);
+}
+
+void
+AnimatedSprite::substituteAction(std::string complete, std::string with)
+{
+ if (mActions.find(complete) == mActions.end())
+ {
+ mActions[complete] = mActions[with];
+ }
+}
+
+AnimatedSprite::~AnimatedSprite()
+{
+ for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); i++)
+ {
+ delete i->second;
+ }
+ mSpritesets.clear();
+}
+
+void
+AnimatedSprite::play(std::string action)
+{
+ if (mAction != action)
+ {
+ mAction = action;
+ }
+ mLastTime = 0;
+}
+
+void
+AnimatedSprite::play(std::string action, std::string direction)
+{
+ play(action);
+ mDirection = direction;
+}
+
+void
+AnimatedSprite::update(int time)
+{
+ //avoid freaking out at first frame or when tick_time overflows
+ if (time < mLastTime || mLastTime == 0) mLastTime = time;
+
+ Action *action = mActions[mAction];
+ action->getAnimation(mDirection)->update(time - mLastTime);
+ mLastTime = time;
+}
+
+bool
+AnimatedSprite::draw(Graphics * graphics, Sint32 posX, Sint32 posY)
+{
+ Sint32 offsetX, offsetY;
+ Action *action = mActions[mAction];
+ Spriteset *spriteset = mSpritesets[action->getImageset()];
+ Animation *animation = action->getAnimation(mDirection);
+
+ if (animation->getCurrentPhase() >= 0)
+ {
+ Image *image = spriteset->get(animation->getCurrentPhase());
+ offsetX = animation->getOffsetX();
+ offsetY = animation->getOffsetY();
+ return graphics->drawImage(image, posX + offsetX, posY + offsetY);
+ }
+ else
+ {
+ return false;
+ }
+}
+
+Image *
+AnimatedSprite::getCurrentFrame()
+{
+ Action *action = mActions[mAction];
+ Spriteset *spriteset = mSpritesets[action->getImageset()];
+ Animation *animation = action->getAnimation(mDirection);
+ if (animation->getCurrentPhase() >= 0)
+ {
+ return spriteset->get(animation->getCurrentPhase());
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+int
+AnimatedSprite::getWidth()
+{
+ Action *action = mActions[mAction];
+ Spriteset *spriteset = mSpritesets[action->getImageset()];
+ return spriteset->getWidth();
+}
+
+int
+AnimatedSprite::getHeight()
+{
+ Action *action = mActions[mAction];
+ Spriteset *spriteset = mSpritesets[action->getImageset()];
+ return spriteset->getHeight();
+}
diff --git a/src/animation.h b/src/animation.h
new file mode 100644
index 00000000..55f0bc99
--- /dev/null
+++ b/src/animation.h
@@ -0,0 +1,160 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_ANIMATION_H
+#define _TMW_ANIMATION_H
+
+#include <list>
+#include <map>
+#include <string>
+
+#include "graphics.h"
+
+class Image;
+class Spriteset;
+
+struct AnimationPhase
+{
+ int image;
+ unsigned int delay;
+ int offsetX;
+ int offsetY;
+};
+
+class Animation
+{
+ public:
+ Animation();
+
+ void addPhase (int image, unsigned int delay, int offsetX, int offsetY);
+
+ void update(unsigned int time);
+
+ int getCurrentPhase();
+
+ int getOffsetX() { return (*iCurrentPhase).offsetX ; };
+ int getOffsetY() { return (*iCurrentPhase).offsetY ; };
+
+ protected:
+ std::list<AnimationPhase> mAnimationPhases;
+ std::list<AnimationPhase>::iterator iCurrentPhase;
+ unsigned int mTime;
+};
+
+class Action
+{
+ public:
+ Action();
+
+ ~Action();
+
+ void setImageset(std::string imageset) { mImageset = imageset; }
+
+ std::string getImageset() { return mImageset; }
+
+ void setAnimation(std::string direction, Animation *animation);
+
+ Animation *getAnimation(std::string direction); // { return mAnimations[direction]; }
+
+ protected:
+ std::string mImageset;
+ typedef std::map<std::string, Animation*> Animations;
+ typedef Animations::iterator AnimationIterator;
+ Animations mAnimations;
+};
+
+/**
+ * Defines a class to load an animation.
+ */
+class AnimatedSprite
+{
+ public:
+ /**
+ * Constructor.
+ */
+ AnimatedSprite(std::string animationFile, int variant);
+
+ /**
+ * Destructor.
+ */
+ ~AnimatedSprite();
+
+ /**
+ * Sets a new action using the current direction.
+ */
+ void play(std::string action);
+
+ /**
+ * Sets a new action with a new direction.
+ */
+ void play(std::string action, std::string direction);
+
+ /**
+ * Inform the animation of the passed time so that it can output the
+ * correct animation phase.
+ */
+ void update(int time);
+
+ /**
+ * Draw the current animation phase at the coordinates given in screen
+ * pixels
+ */
+ bool draw(Graphics * graphics, Sint32 posX, Sint32 posY);
+
+ /**
+ * Draw the current animation phase.
+ */
+ Image *getCurrentFrame();
+
+ /**
+ * gets the width in pixels of the current animation phase.
+ */
+ int getWidth();
+
+ /**
+ * gets the height in pixels of the current animation phase.
+ */
+ int getHeight();
+
+ /**
+ * Sets the direction.
+ */
+ void setDirection(std::string direction) { mDirection = direction; }
+
+ protected:
+ /**
+ * When there are no animations defined for the action "complete", its
+ * animations become a copy of those of the action "with".
+ */
+ void substituteAction(std::string complete, std::string with);
+
+ typedef std::map<std::string, Spriteset*> Spritesets;
+ typedef Spritesets::iterator SpritesetIterator;
+ Spritesets mSpritesets;
+ typedef std::map<std::string, Action*> Actions;
+ Actions mActions;
+ std::string mAction, mDirection;
+ int mLastTime;
+};
+
+#endif
diff --git a/src/base64.cpp b/src/base64.cpp
index e2df07de..6d503a53 100644
--- a/src/base64.cpp
+++ b/src/base64.cpp
@@ -105,7 +105,7 @@ unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_
headache. - Turadg Aleahmad <turadg@wise.berkeley.edu>
*/
- if (ch == ' ') ch = '+';
+ if (ch == ' ') ch = '+';
ch = reverse_table[ch];
if (ch < 0) continue;
diff --git a/src/being.cpp b/src/being.cpp
index a0db8208..19d9d916 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -44,7 +44,7 @@ PATH_NODE::PATH_NODE(Uint16 iX, Uint16 iY):
Being::Being(Uint32 id, Uint16 job, Map *map):
mJob(job),
mX(0), mY(0), mDirection(DOWN),
- mAction(0), mFrame(0),
+ mAction(0),
mWalkTime(0),
mEmotion(0), mEmotionTime(0),
mAttackSpeed(350),
@@ -53,24 +53,29 @@ Being::Being(Uint32 id, Uint16 job, Map *map):
mWeapon(0),
mWalkSpeed(150),
mMap(NULL),
- mHairStyle(1), mHairColor(1),
- mSex(0),
+ mHairStyle(0), mHairColor(0),
+ mSex(2),
mSpeechTime(0),
mDamageTime(0),
- mShowSpeech(false), mShowDamage(false),
- mSpriteset(NULL), mSpriteFrame(0)
+ mShowSpeech(false), mShowDamage(false)
{
setMap(map);
- memset(mVisibleEquipment, 0, 6 * sizeof(int));
+ mSprites.resize(VECTOREND_SPRITE, NULL);
}
Being::~Being()
{
+ for (int i =0; i < VECTOREND_SPRITE; i++)
+ {
+ delete mSprites[i];
+ }
+
clearPath();
setMap(NULL);
}
-void Being::setDestination(Uint16 destX, Uint16 destY)
+void
+Being::setDestination(Uint16 destX, Uint16 destY)
{
if (mMap)
{
@@ -78,12 +83,14 @@ void Being::setDestination(Uint16 destX, Uint16 destY)
}
}
-void Being::clearPath()
+void
+Being::clearPath()
{
mPath.clear();
}
-void Being::setPath(const Path &path)
+void
+Being::setPath(const Path &path)
{
mPath = path;
@@ -94,7 +101,8 @@ void Being::setPath(const Path &path)
}
}
-void Being::setHairColor(Uint16 color)
+void
+Being::setHairColor(Uint16 color)
{
mHairColor = color;
if (mHairColor < 1 || mHairColor > NR_HAIR_COLORS + 1)
@@ -103,7 +111,8 @@ void Being::setHairColor(Uint16 color)
}
}
-void Being::setHairStyle(Uint16 style)
+void
+Being::setHairStyle(Uint16 style)
{
mHairStyle = style;
if (mHairStyle < 1 || mHairStyle > NR_HAIR_STYLES)
@@ -113,6 +122,26 @@ void Being::setHairStyle(Uint16 style)
}
void
+Being::setHair(Uint16 style, Uint16 color)
+{
+ mHairStyle = style;
+ if (mHairStyle < 1 || mHairStyle > NR_HAIR_STYLES)
+ {
+ mHairStyle = 1;
+ }
+ mHairColor = color;
+ if (mHairColor < 1 || mHairColor > NR_HAIR_COLORS + 1)
+ {
+ mHairColor = 1;
+ }
+}
+
+void
+Being::setVisibleEquipment(Uint8 slot, Uint8 id)
+{
+}
+
+void
Being::setSpeech(const std::string &text, Uint32 time)
{
mSpeech = text;
@@ -147,13 +176,93 @@ Being::setMap(Map *map)
}
void
-Being::nextStep()
+Being::setAction(Action action)
{
- mFrame = 0;
+ if (action != mAction)
+ {
+ std::string currentAction = "stand";
+ switch (action)
+ {
+ case WALK:
+ currentAction = "walk";
+ break;
+ case SIT:
+ currentAction = "sit";
+ break;
+ case ATTACK:
+ if (getType() == MONSTER)
+ {
+ currentAction = "dead";
+ }else{
+ switch (getWeapon())
+ {
+ case 2:
+ currentAction = "attack_bow";
+ break;
+ case 1:
+ currentAction = "attack_stab";
+ break;
+ case 0:
+ currentAction = "attack";
+ break;
+ }
+ };
+ break;
+ case MONSTER_ATTACK:
+ currentAction = "attack";
+ break;
+ case DEAD:
+ currentAction = "dead";
+ break;
+ default:
+ currentAction = "stand";
+ break;
+ }
+
+ for (int i = 0; i < VECTOREND_SPRITE; i++)
+ {
+ if (mSprites[i] != NULL) mSprites[i]->play(currentAction);
+ }
+ }
+ mAction = action;
+}
+void
+Being::setDirection(Uint8 direction)
+{
+ mDirection |= direction;
+ std::string dir;
+
+ if (direction & UP)
+ {
+ dir = "up";
+ }
+ else if (direction & RIGHT)
+ {
+ dir = "right";
+ }
+ else if (direction & DOWN)
+ {
+ dir = "down";
+ }
+ else
+ {
+ dir = "left";
+ }
+
+ for (int i = 0; i < VECTOREND_SPRITE; i++)
+ {
+ if (mSprites[i] != NULL) mSprites[i]->setDirection(dir);
+ }
+
+}
+
+void
+Being::nextStep()
+{
if (mPath.empty())
{
- mAction = STAND;
+ setAction(STAND);
return;
}
@@ -162,17 +271,17 @@ Being::nextStep()
mDirection = 0;
if (node.x > mX)
- mDirection |= RIGHT;
+ setDirection(RIGHT);
else if (node.x < mX)
- mDirection |= LEFT;
+ setDirection(LEFT);
if (node.y > mY)
- mDirection |= DOWN;
+ setDirection(DOWN);
else if (node.y < mY)
- mDirection |= UP;
+ setDirection(UP);
mX = node.x;
mY = node.y;
- mAction = WALK;
+ setAction(WALK);
mWalkTime += mWalkSpeed / 10;
}
@@ -202,17 +311,36 @@ Being::logic()
mEmotion = 0;
}
}
+
+ // Update sprite animations
+ for (int i = 0; i < VECTOREND_SPRITE; i++)
+ {
+ if (mSprites[i] != NULL)
+ {
+ printf("Draw: %i\n", i);
+ mSprites[i]->update(tick_time * 10);
+ }
+ }
}
-void Being::draw(Graphics *graphics, int offsetX, int offsetY)
+void
+Being::draw(Graphics *graphics, int offsetX, int offsetY)
{
- if (!mSpriteset)
- return;
-
int px = mPx + offsetX;
int py = mPy + offsetY;
- graphics->drawImage(mSpriteset->get(mSpriteFrame), px, py);
+ //what are these two lines good for? please add a comment.
+ unsigned char dir = 0;
+ while (!(mDirection & (1 << dir))) dir++;
+
+ for (int i = 0; i < VECTOREND_SPRITE; i++)
+ {
+ if (mSprites[i] != NULL)
+ {
+ mSprites[i]->draw(graphics, px, py);
+ printf("Draw: %i\n", i);
+ }
+ }
}
void
@@ -274,12 +402,14 @@ Being::drawSpeech(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
}
}
-Being::Type Being::getType() const
+Being::Type
+Being::getType() const
{
return UNKNOWN;
}
-void Being::setWeaponById(Uint16 weapon)
+void
+Being::setWeaponById(Uint16 weapon)
{
switch (weapon)
{
@@ -309,7 +439,8 @@ void Being::setWeaponById(Uint16 weapon)
}
}
-int Being::getOffset(char pos, char neg) const
+int
+Being::getOffset(char pos, char neg) const
{
// Check whether we're walking in the requested direction
if (mAction != WALK || !(mDirection & (pos | neg))) {
diff --git a/src/being.h b/src/being.h
index 9970b5d1..6fac98b7 100644
--- a/src/being.h
+++ b/src/being.h
@@ -27,11 +27,13 @@
#include <list>
#include <string>
#include <SDL_types.h>
+#include <vector>
+#include "animation.h"
#include "sprite.h"
#include "map.h"
-#define NR_HAIR_STYLES 6
+#define NR_HAIR_STYLES 7
#define NR_HAIR_COLORS 10
class Equipment;
@@ -75,6 +77,19 @@ class Being : public Sprite
HIT = 17
};
+ enum Sprite {
+ BASE_SPRITE = 0,
+ SHOE_SPRITE,
+ BOTTOMCLOTHES_SPRITE,
+ TOPCLOTHES_SPRITE,
+ HAIR_SPRITE,
+ HAT_SPRITE,
+ WEAPON_SPRITE,
+ VECTOREND_SPRITE
+ };
+
+
+
/**
* Directions, to be used as bitmask values
*/
@@ -83,14 +98,14 @@ class Being : public Sprite
static const char UP = 4;
static const char RIGHT = 8;
- Uint16 mJob; /**< Job (player job, npc, monster, ) */
+ Uint16 mJob; /**< Job (player job, npc, monster, ) */
Uint16 mX, mY; /**< Tile coordinates */
- Uint8 mDirection; /**< Facing direction */
- Uint8 mAction;
+ Uint8 mDirection; /**< Facing direction */
+ Uint8 mAction; /**< Action the being is performing */
Uint8 mFrame;
Uint16 mWalkTime;
- Uint8 mEmotion; /**< Currently showing emotion */
- Uint8 mEmotionTime; /**< Time until emotion disappears */
+ Uint8 mEmotion; /**< Currently showing emotion */
+ Uint8 mEmotionTime; /**< Time until emotion disappears */
Uint16 mAttackSpeed; /**< Attack speed */
@@ -149,7 +164,7 @@ class Being : public Sprite
/**
* Sets the hair color for this being.
*/
- void
+ virtual void
setHairColor(Uint16 color);
/**
@@ -161,7 +176,7 @@ class Being : public Sprite
/**
* Sets the hair style for this being.
*/
- void
+ virtual void
setHairStyle(Uint16 style);
/**
@@ -169,11 +184,23 @@ class Being : public Sprite
*/
Uint16
getHairStyle() const { return mHairStyle; }
-
+
+ /**
+ * Sets the hair style and color for this being.
+ */
+ virtual void
+ setHair(Uint16 style, Uint16 color);
+
+ /**
+ * Sets visible equipments for this being.
+ */
+ virtual void
+ setVisibleEquipment(Uint8 slot, Uint8 id);
+
/**
* Sets the sex for this being.
*/
- void
+ virtual void
setSex(Uint8 sex) { mSex = sex; }
/**
@@ -268,6 +295,16 @@ class Being : public Sprite
void setMap(Map *map);
/**
+ * Sets the current action.
+ */
+ void setAction(Action action);
+
+ /**
+ * Sets the current direction.
+ */
+ void setDirection(Uint8 direction);
+
+ /**
* Draws this being to the given graphics context.
*
* @see Sprite::draw(Graphics, int, int)
@@ -300,7 +337,7 @@ class Being : public Sprite
*/
int
getYOffset() const { return getOffset(UP, DOWN); }
-
+
std::auto_ptr<Equipment> mEquipment;
int mVisibleEquipment[6]; /**< Visible equipments */
@@ -334,8 +371,7 @@ class Being : public Sprite
bool mShowSpeech, mShowDamage;
Sint32 mPx, mPy; /**< Pixel coordinates */
- Spriteset *mSpriteset;
- int mSpriteFrame;
+ std::vector<AnimatedSprite *>mSprites;
};
#endif
diff --git a/src/engine.cpp b/src/engine.cpp
index 724c0930..ba28fcc9 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -25,6 +25,7 @@
#include <list>
+#include "animation.h"
#include "being.h"
#include "beingmanager.h"
#include "flooritemmanager.h"
@@ -57,14 +58,13 @@ extern Minimap *minimap;
char itemCurrenyQ[10] = "0";
int camera_x, camera_y;
-std::map<int, Spriteset*> monsterset;
-
ItemManager *itemDb; /**< Item database object */
Spriteset *itemset;
Spriteset *emotionset;
Spriteset *npcset;
std::vector<Spriteset *> weaponset;
+AnimatedSprite *animatedSprite;
Engine::Engine(Network *network):
@@ -102,9 +102,6 @@ Engine::Engine(Network *network):
Engine::~Engine()
{
// Delete sprite sets
- for_each(monsterset.begin(), monsterset.end(), make_dtor(monsterset));
- monsterset.clear();
-
delete npcset;
delete emotionset;
for_each(weaponset.begin(), weaponset.end(), make_dtor(weaponset));
@@ -112,6 +109,8 @@ Engine::~Engine()
delete itemset;
delete itemDb;
+
+ delete animatedSprite;
}
void Engine::changeMap(const std::string &mapPath)
diff --git a/src/game.cpp b/src/game.cpp
index 0ccc7542..51b541a6 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -357,7 +357,7 @@ void Game::logic()
}
gameTime = tick_time;
-
+
fpsLimit = (int)config.getValue("fpslimit", 50);
if (fpsLimit)
{
diff --git a/src/graphic/spriteset.cpp b/src/graphic/spriteset.cpp
index b008a701..3b190f31 100644
--- a/src/graphic/spriteset.cpp
+++ b/src/graphic/spriteset.cpp
@@ -23,6 +23,8 @@
#include "spriteset.h"
+#include "../log.h"
+
#include "../resources/image.h"
#include "../utils/dtor.h"
@@ -36,9 +38,25 @@ Spriteset::Spriteset(Image *img, int width, int height)
mSpriteset.push_back(img->getSubImage(x, y, width, height));
}
}
+ mWidth = width;
+ mHeight = height;
}
Spriteset::~Spriteset()
{
for_each(mSpriteset.begin(), mSpriteset.end(), make_dtor(mSpriteset));
}
+
+Image *
+Spriteset::get(size_type i)
+{
+ if (i > mSpriteset.size())
+ {
+ logger->log("Warning: Sprite #%i does not exist in this spriteset", i);
+ return NULL;
+ }
+ else
+ {
+ return mSpriteset[i];
+ }
+}
diff --git a/src/graphic/spriteset.h b/src/graphic/spriteset.h
index 08ff65f5..94ccb742 100644
--- a/src/graphic/spriteset.h
+++ b/src/graphic/spriteset.h
@@ -44,14 +44,21 @@ class Spriteset {
*/
~Spriteset();
+ int getWidth() { return mWidth; };
+
+ int getHeight() { return mHeight; };
+
typedef std::vector<Image*>::size_type size_type;
- Image* get(size_type i) { return mSpriteset[i]; }
+ Image * get(size_type i);
size_type size() { return mSpriteset.size(); }
private:
// Vector storing the whole spriteset.
std::vector<Image*> mSpriteset;
+ //height and width of the images in the spriteset
+ int mHeight;
+ int mWidth;
};
#endif
diff --git a/src/graphics.cpp b/src/graphics.cpp
index d709bfe1..2757214a 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -126,14 +126,16 @@ bool Graphics::drawImage(Image *image, int x, int y)
bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY,
int width, int height)
{
+ // Check that preconditions for blitting are met.
+ if (!mScreen || !image || !image->mImage) return false;
+
dstX += mClipStack.top().xOffset;
dstY += mClipStack.top().yOffset;
srcX += image->mBounds.x;
srcY += image->mBounds.y;
- // Check that preconditions for blitting are met.
- if (!mScreen || !image->mImage) return false;
+
SDL_Rect dstRect;
SDL_Rect srcRect;
diff --git a/src/gui/chargedialog.h b/src/gui/chargedialog.h
index d1726500..c09c692c 100644
--- a/src/gui/chargedialog.h
+++ b/src/gui/chargedialog.h
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-
+
#ifndef _TMW_CHARGE_H
#define _TMW_CHARGE_H
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index f588fa8e..179e5314 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -22,7 +22,7 @@
*/
#ifndef _TMW_INVENTORYWINDOW_H
-#define _TMW_INVENTORYWINDOW_H
+#define _TMW_INVENTORYWINDOW_H
#include <guichan/actionlistener.hpp>
diff --git a/src/gui/menuwindow.h b/src/gui/menuwindow.h
index 945bca94..f43b9921 100644
--- a/src/gui/menuwindow.h
+++ b/src/gui/menuwindow.h
@@ -48,4 +48,4 @@ class MenuWindow : public Window
};
#endif
-
+
diff --git a/src/gui/minimap.h b/src/gui/minimap.h
index 53b18630..5e9458bf 100644
--- a/src/gui/minimap.h
+++ b/src/gui/minimap.h
@@ -22,7 +22,7 @@
*/
#ifndef _TMW_MINIMAP_H
-#define _TMW_MINIMAP_H
+#define _TMW_MINIMAP_H
#include "window.h"
diff --git a/src/gui/ministatus.h b/src/gui/ministatus.h
index b5d149e7..f56f847c 100644
--- a/src/gui/ministatus.h
+++ b/src/gui/ministatus.h
@@ -64,4 +64,4 @@ class MiniStatusWindow : public Window
};
#endif
-
+
diff --git a/src/gui/newskill.h b/src/gui/newskill.h
index 96bcf9ad..764019f5 100644
--- a/src/gui/newskill.h
+++ b/src/gui/newskill.h
@@ -20,7 +20,7 @@
*
* $Id$
*/
-
+
#ifndef _TMW_NSKILL_H
#define _TMW_NSKILL_H
@@ -35,7 +35,7 @@ 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;
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index bde8906b..ec565ac3 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -212,7 +212,7 @@ void SellDialog::action(const std::string& eventId)
else if (eventId == "sell") {
// Attempt sell
assert(mAmountItems > 0 && mAmountItems <= mMaxItems);
-
+
MessageOut outMsg(mNetwork);
outMsg.writeInt16(CMSG_NPC_SELL_REQUEST);
outMsg.writeInt16(8);
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index d6289bbc..05543092 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -141,7 +141,7 @@ Setup_Video::Setup_Video():
mModeList->setSelected(-1);
mAlphaSlider->setValue(mOpacity);
-
+
mFpsField->setText(toString(mFps));
mFpsField->setEnabled(mFps > 0);
mFpsSlider->setValue(mFps);
@@ -213,7 +213,7 @@ void Setup_Video::apply()
new OkDialog("Changing OpenGL",
"Applying change to OpenGL requires restart.");
}
-
+
// FPS change
config.setValue("fpslimit", mFps);
@@ -273,7 +273,7 @@ void Setup_Video::action(const std::string &event)
void Setup_Video::keyPress(const gcn::Key &key)
{
std::stringstream tempFps(mFpsField->getText());
-
+
if (tempFps >> mFps)
{
if (mFps < 10)
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index d8ee1914..b021ead4 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -42,7 +42,7 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
void cancel();
void action(const std::string&);
-
+
/** Called when key is pressed */
void keyPress(const gcn::Key& key);
diff --git a/src/gui/status.h b/src/gui/status.h
index 66068a7d..52ece323 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -88,7 +88,7 @@ class StatusWindow : public Window, public gcn::ActionListener {
gcn::Label *mStatsAccuracyPoints, *mStatsEvadePoints;
gcn::Label *mStatsReflexPoints;
- /**
+ /**
* Stats captions.
*/
gcn::Label *mStatsLabel[6];
@@ -96,7 +96,7 @@ class StatusWindow : public Window, public gcn::ActionListener {
gcn::Label *mStatsDisplayLabel[6];
gcn::Label *mRemainingStatsPointsLabel;
- /**
+ /**
* Stats buttons.
*/
gcn::Button *mStatsButton[6];
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 0313fe81..339435a5 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -210,7 +210,7 @@ void LocalPlayer::walk(unsigned char dir)
{
// Update the player direction to where he wants to walk
// Warning: Not communicated to the server yet
- mDirection = dir;
+ setDirection(dir);
}
}
@@ -344,22 +344,22 @@ void LocalPlayer::attack(Being *target, bool keep)
if (abs(dist_y) >= abs(dist_x))
{
if (dist_y > 0)
- mDirection = DOWN;
+ setDirection(DOWN);
else
- mDirection = UP;
+ setDirection(UP);
}
else
{
if (dist_x > 0)
- mDirection = RIGHT;
+ setDirection(RIGHT);
else
- mDirection = LEFT;
+ setDirection(LEFT);
}
// Implement charging attacks here
mLastAttackTime = 0;
- mAction = ATTACK;
+ setAction(ATTACK);
mWalkTime = tick_time;
if (getWeapon() == 2)
sound.playSfx("sfx/bow_shoot_1.ogg");
diff --git a/src/main.cpp b/src/main.cpp
index a4ef390e..5ecb4f35 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -43,6 +43,7 @@
#define NOGDI
#endif
+#include "animation.h"
#include "configuration.h"
#include "game.h"
#include "graphics.h"
@@ -84,7 +85,6 @@ char n_server, n_character;
std::vector<Spriteset *> hairset;
Spriteset *playerset[2];
-Spriteset *equipmentset[2];
Graphics *graphics;
// TODO Anyone knows a good location for this? Or a way to make it non-global?
@@ -250,12 +250,6 @@ void init_engine()
playerset[1] = resman->createSpriteset(
"graphics/sprites/player_female_base.png", 64, 64);
if (!playerset[1]) logger->error("Couldn't load female player spriteset!");
- equipmentset[0] = resman->createSpriteset(
- "graphics/sprites/item001.png", 64, 64);
- if (!equipmentset[0]) logger->error("Couldn't load player equipmentset!");
- equipmentset[1] = resman->createSpriteset(
- "graphics/sprites/item002.png", 64, 64);
- if (!equipmentset[1]) logger->error("Couldn't load player equipmentset!");
for (int i=0; i < NR_HAIR_STYLES; i++)
@@ -298,8 +292,6 @@ void exit_engine()
hairset.clear();
delete playerset[0];
delete playerset[1];
- delete equipmentset[0];
- delete equipmentset[1];
// Shutdown libxml
xmlCleanupParser();
@@ -685,10 +677,12 @@ int main(int argc, char *argv[])
break;
case CHAR_CONNECT_STATE:
+ printf("Char: %i\n", loginData.sex);
charLogin(network, &loginData);
break;
case ACCOUNT_STATE:
+ printf("Account: %i\n", loginData.sex);
accountLogin(network, &loginData);
break;
diff --git a/src/monster.cpp b/src/monster.cpp
index af84b25e..43823e50 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -30,28 +30,15 @@
#include "utils/tostring.h"
-class Spriteset;
-extern std::map<int, Spriteset*> monsterset;
Monster::Monster(Uint32 id, Uint16 job, Map *map):
Being(id, job, map)
{
- // Load monster spriteset, if necessary
- if (monsterset.find(job - 1002) == monsterset.end())
- {
- Spriteset *tmp = ResourceManager::getInstance()->createSpriteset(
- "graphics/sprites/monster" + toString(job - 1002) + ".png",
- 60, 60);
- if (!tmp) {
- logger->error("Unable to load monster spriteset!");
- } else {
- monsterset[job - 1002] = tmp;
- }
- }
- mSpriteset = monsterset[job-1002];
+ mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/monster" + toString(job - 1002) + ".xml", 0);
}
-void Monster::logic()
+void
+Monster::logic()
{
if (mAction != STAND)
{
@@ -66,27 +53,9 @@ void Monster::logic()
Being::logic();
}
-Being::Type Monster::getType() const
+Being::Type
+Monster::getType() const
{
return MONSTER;
}
-void Monster::draw(Graphics *graphics, int offsetX, int offsetY)
-{
- if (mFrame >= 4)
- {
- mFrame = 3;
- }
-
- mSpriteFrame = mAction;
- if (mAction != MONSTER_DEAD) {
- mSpriteFrame += mFrame;
- }
-
- unsigned char dir = 0;
- while (!(mDirection & (1 << dir))) dir++;
-
- mSpriteFrame = dir + 4 * mSpriteFrame;
-
- Being::draw(graphics, offsetX - 12, offsetY - 25);
-}
diff --git a/src/monster.h b/src/monster.h
index 6f3d2a89..4a82a461 100644
--- a/src/monster.h
+++ b/src/monster.h
@@ -34,8 +34,6 @@ class Monster : public Being
virtual void logic();
virtual Type getType() const;
-
- virtual void draw(Graphics *graphics, int offsetX, int offsetY);
};
#endif
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index 58660094..cd5653fc 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -96,7 +96,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->clearPath();
dstBeing->mFrame = 0;
dstBeing->mWalkTime = tick_time;
- dstBeing->mAction = Being::STAND;
+ dstBeing->setAction(Being::STAND);
}
// Prevent division by 0 when calculating frame
@@ -106,7 +106,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->mJob = job;
dstBeing->setHairStyle(msg->readInt16());
dstBeing->setWeapon(msg->readInt16());
- dstBeing->mVisibleEquipment[3] = msg->readInt16(); // head (bottom)
+ dstBeing->setVisibleEquipment(3, msg->readInt16()); // head bottom
if (msg->getId() == SMSG_BEING_MOVE)
{
@@ -114,8 +114,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
}
msg->readInt16(); // shield
- dstBeing->mVisibleEquipment[4] = msg->readInt16(); // head (top)
- dstBeing->mVisibleEquipment[5] = msg->readInt16(); // head (mid)
+ dstBeing->setVisibleEquipment(4, msg->readInt16()); // head top
+ dstBeing->setVisibleEquipment(5, msg->readInt16()); // head mid
dstBeing->setHairColor(msg->readInt16());
msg->readInt16(); // unknown
msg->readInt16(); // head dir
@@ -131,7 +131,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
{
Uint16 srcX, srcY, dstX, dstY;
msg->readCoordinatePair(srcX, srcY, dstX, dstY);
- dstBeing->mAction = Being::STAND;
+ dstBeing->setAction(Being::STAND);
dstBeing->mX = srcX;
dstBeing->mY = srcY;
dstBeing->setDestination(dstX, dstY);
@@ -160,13 +160,13 @@ void BeingHandler::handleMessage(MessageIn *msg)
switch (dstBeing->getType())
{
case Being::MONSTER:
- dstBeing->mAction = Being::MONSTER_DEAD;
+ dstBeing->setAction(Being::MONSTER_DEAD);
dstBeing->mFrame = 0;
dstBeing->mWalkTime = tick_time;
break;
default:
- dstBeing->mAction = Being::DEAD;
+ dstBeing->setAction(Being::DEAD);
break;
}
}
@@ -205,11 +205,11 @@ void BeingHandler::handleMessage(MessageIn *msg)
// buggy
if (srcBeing->getType() == Being::MONSTER)
{
- srcBeing->mAction = Being::MONSTER_ATTACK;
+ srcBeing->setAction(Being::MONSTER_ATTACK);
}
else
{
- srcBeing->mAction = Being::ATTACK;
+ srcBeing->setAction(Being::ATTACK);
}
srcBeing->mFrame = 0;
srcBeing->mWalkTime = tick_time;
@@ -219,13 +219,13 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 2: // Sit
if (srcBeing == NULL) break;
srcBeing->mFrame = 0;
- srcBeing->mAction = Being::SIT;
+ srcBeing->setAction(Being::SIT);
break;
case 3: // Stand up
if (srcBeing == NULL) break;
srcBeing->mFrame = 0;
- srcBeing->mAction = Being::STAND;
+ srcBeing->setAction(Being::STAND);
break;
}
break;
@@ -269,8 +269,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 3:
case 4:
case 5:
- // Equip/unequip head 3. Bottom 4. Top 5. Bottom
- dstBeing->mVisibleEquipment[type] = msg->readInt8();
+ // Equip/unequip head 3. Bottom 4. Top 5. Middle
+ dstBeing->setVisibleEquipment(type, msg->readInt8());
// First 3 slots of mVisibleEquipments are reserved for
// later use, probably accessories.
break;
@@ -314,15 +314,15 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setHairStyle(msg->readInt16());
dstBeing->setWeaponById(msg->readInt16()); // item id 1
msg->readInt16(); // item id 2
- dstBeing->mVisibleEquipment[3] = msg->readInt16(); // head (bottom)
+ dstBeing->setVisibleEquipment(3, msg->readInt16()); // head bottom
if (msg->getId() == SMSG_PLAYER_MOVE)
{
msg->readInt32(); // server tick
}
- dstBeing->mVisibleEquipment[4] = msg->readInt16(); // head (top)
- dstBeing->mVisibleEquipment[5] = msg->readInt16(); // head (mid)
+ dstBeing->setVisibleEquipment(4, msg->readInt16()); // head top
+ dstBeing->setVisibleEquipment(5, msg->readInt16()); // head mid
dstBeing->setHairColor(msg->readInt16());
msg->readInt16(); // unknown
msg->readInt16(); // head dir
@@ -353,7 +353,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
{
if (msg->readInt8() == 2)
{
- dstBeing->mAction = Being::SIT;
+ dstBeing->setAction(Being::SIT);
}
}
else if (msg->getId() == SMSG_PLAYER_MOVE)
@@ -371,8 +371,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 0x0119:
// Change in players look
printf("0x0119 %i %i %i %x %i\n", msg->readInt32(),
- msg->readInt16(), msg->readInt16(), msg->readInt16(),
- msg->readInt8());
+ msg->readInt16(), msg->readInt16(), msg->readInt16(),
+ msg->readInt8());
break;
}
}
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
index 9857ddc0..06ec78c1 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/charserverhandler.cpp
@@ -191,10 +191,10 @@ LocalPlayer* CharServerHandler::readPlayerData(MessageIn *msg, int &slot)
tempPlayer->setWeapon(weapon);
tempPlayer->mLevel = msg->readInt16();
msg->readInt16(); // skill point
- tempPlayer->mVisibleEquipment[3] = msg->readInt16(); // head bottom
+ tempPlayer->setVisibleEquipment(3, msg->readInt16()); // head bottom
msg->readInt16(); // shield
- tempPlayer->mVisibleEquipment[4] = msg->readInt16(); // head option top
- tempPlayer->mVisibleEquipment[5] = msg->readInt16(); // head option mid
+ tempPlayer->setVisibleEquipment(4, msg->readInt16()); // head option top
+ tempPlayer->setVisibleEquipment(5, msg->readInt16()); // head option mid
tempPlayer->setHairColor(msg->readInt16());
msg->readInt16(); // unknown
tempPlayer->setName(msg->readString(24));
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index 070fb112..94788333 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -104,7 +104,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
current_npc = 0;
- player_node->mAction = Being::STAND;
+ player_node->setAction(Being::STAND);
player_node->stopAttack();
player_node->mFrame = 0;
player_node->mX = x;
@@ -163,7 +163,7 @@ void PlayerHandler::handleMessage(MessageIn *msg)
deathNotice = new OkDialog("Message",
"You're now dead, press ok to restart");
deathNotice->addActionListener(&deathListener);
- player_node->mAction = Being::DEAD;
+ player_node->setAction(Being::DEAD);
}
}
break;
diff --git a/src/npc.cpp b/src/npc.cpp
index 9712a06d..354322a3 100644
--- a/src/npc.cpp
+++ b/src/npc.cpp
@@ -34,21 +34,17 @@ NPC *current_npc = 0;
NPC::NPC(Uint32 id, Uint16 job, Map *map, Network *network):
Being(id, job, map), mNetwork(network)
{
- mSpriteset = npcset;
- mSpriteFrame = job-100;
+ mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/npc.xml", job-100);
}
-Being::Type NPC::getType() const
+Being::Type
+NPC::getType() const
{
return Being::NPC;
}
-void NPC::draw(Graphics *graphics, int offsetX, int offsetY)
-{
- Being::draw(graphics, offsetX - 8, offsetY - 52);
-}
-
-void NPC::talk()
+void
+NPC::talk()
{
MessageOut outMsg(mNetwork);
outMsg.writeInt16(CMSG_NPC_TALK);
@@ -57,14 +53,16 @@ void NPC::talk()
current_npc = this;
}
-void NPC::nextDialog()
+void
+NPC::nextDialog()
{
MessageOut outMsg(mNetwork);
outMsg.writeInt16(CMSG_NPC_NEXT_REQUEST);
outMsg.writeInt32(mId);
}
-void NPC::dialogChoice(char choice)
+void
+NPC::dialogChoice(char choice)
{
MessageOut outMsg(mNetwork);
outMsg.writeInt16(CMSG_NPC_LIST_CHOICE);
@@ -76,7 +74,8 @@ void NPC::dialogChoice(char choice)
* TODO Unify the buy() and sell() methods, without sacrificing readability of
* the code calling the method. buy(bool buySell) would be bad...
*/
-void NPC::buy()
+void
+NPC::buy()
{
MessageOut outMsg(mNetwork);
outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST);
@@ -84,7 +83,8 @@ void NPC::buy()
outMsg.writeInt8(0);
}
-void NPC::sell()
+void
+NPC::sell()
{
MessageOut outMsg(mNetwork);
outMsg.writeInt16(CMSG_NPC_BUY_SELL_REQUEST);
diff --git a/src/npc.h b/src/npc.h
index 45b3d0c3..b08c315c 100644
--- a/src/npc.h
+++ b/src/npc.h
@@ -35,8 +35,6 @@ class NPC : public Being
virtual Type getType() const;
- virtual void draw(Graphics *graphics, int offsetX, int offsetY);
-
void talk();
void nextDialog();
void dialogChoice(char choice);
diff --git a/src/player.cpp b/src/player.cpp
index 43439ab1..9b7536cf 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -23,55 +23,26 @@
#include "player.h"
+#include "animation.h"
#include "equipment.h"
#include "game.h"
#include "graphics.h"
-#include "graphic/spriteset.h"
+#include "utils/tostring.h"
#include "gui/gui.h"
-extern std::vector<Spriteset *> hairset;
-extern Spriteset *playerset[2];
-extern std::vector<Spriteset *> weaponset;
-extern Spriteset *equipmentset[2];
-
-signed char hairtable[19][4][2] = {
- // S(x,y) W(x,y) N(x,y) E(x,y)
- { {-5, -4}, {-6, -4}, {-6, 0}, {-4, -4} }, // STAND
- { {-5, -3}, {-6, -4}, {-6, 0}, {-4, -4} }, // WALK 1st frame
- { {-5, -4}, {-6, -3}, {-6, -1}, {-4, -3} }, // WALK 2nd frame
- { {-5, -4}, {-6, -4}, {-6, -1}, {-4, -4} }, // WALK 3rd frame
- { {-5, -3}, {-6, -4}, {-6, 0}, {-4, -4} }, // WALK 4th frame
- { {-5, -4}, {-6, -3}, {-6, -1}, {-4, -3} }, // WALK 5th frame
- { {-5, -4}, {-6, -4}, {-6, -1}, {-4, -4} }, // WALK 6th frame
- { {-5, 8}, {-1, 5}, {-6, 8}, {-9, 5} }, // SIT
- { {16, 21}, {16, 21}, {16, 21}, {16, 21} }, // DEAD
- { {-5, -2}, {-2, -5}, {-6, 0}, {-7, -5} }, // ATTACK 1st frame
- { {-5, -3}, {-2, -6}, {-6, 0}, {-7, -6} }, // ATTACK 2nd frame
- { {-5, 0}, {-6, -3}, {-6, 0}, {-4, -3} }, // ATTACK 3rd frame
- { {-5, 1}, {-7, -2}, {-6, 2}, {-3, -2} }, // ATTACK 4th frame
- { {-5, -3}, {-3, -4}, {-6, 0}, {-7, -4} }, // BOW_ATTACK 1st frame
- { {-5, -3}, {-3, -4}, {-6, 0}, {-7, -4} }, // BOW_ATTACK 2nd frame
- { {-5, -3}, {-3, -4}, {-7, 0}, {-7, -4} }, // BOW_ATTACK 3rd frame
- { {-5, -2}, {-1, -5}, {-7, 1}, {-9, -5} }, // BOW_ATTACK 4th frame
- { {-5, -3}, {-1, -5}, {-7, 0}, {-9, -5} }, // BOW_ATTACK 5th frame
- { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} } // ?? HIT
-};
-
-unsigned char hairframe[4][20] = {
- { 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
- { 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
- { 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }
-};
-
Player::Player(Uint32 id, Uint16 job, Map *map):
Being(id, job, map)
{
+ // Load the weapon sprite.
+ // When there are more different weapons this should be moved to the
+ // setWeapon Method.
+ mSprites[WEAPON_SPRITE] = new AnimatedSprite("graphics/sprites/weapons.xml", 0);
}
-void Player::logic()
+void
+Player::logic()
{
switch (mAction) {
case WALK:
@@ -80,7 +51,6 @@ void Player::logic()
nextStep();
}
break;
-
case ATTACK:
int frames = 4;
if (getWeapon() == 2)
@@ -93,80 +63,95 @@ void Player::logic()
}
break;
}
-
-
-
Being::logic();
}
-Being::Type Player::getType() const
+Being::Type
+Player::getType() const
{
return PLAYER;
}
-void Player::draw(Graphics *graphics, int offsetX, int offsetY)
+void
+Player::drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
{
int px = mPx + offsetX;
int py = mPy + offsetY;
- int frame = mAction;
-
- frame = mAction;
- if (mAction != SIT && mAction != DEAD)
- {
- frame += mFrame;
- }
+ graphics->setFont(speechFont);
+ graphics->setColor(gcn::Color(255, 255, 255));
+ graphics->drawText(mName, px + 15, py + 30, gcn::Graphics::CENTER);
+}
- if (mAction == ATTACK && getWeapon() > 0)
+void
+Player::setSex(Uint8 sex)
+{
+ if (sex != mSex)
{
- if (getWeapon() == 2)
+ delete mSprites[BASE_SPRITE];
+ if (sex == 0)
{
- frame += 4;
+ mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/player_male_base.xml", 0);
}
- }
-
- unsigned char dir = 0;
- while (!(mDirection & (1 << dir))) dir++;
-
- graphics->drawImage(playerset[mSex]->get(frame + 18 * dir),
- px - 16, py - 32);
-
- if (getWeapon() != 0 && mAction == ATTACK)
- {
- int frames = 4;
- if (getWeapon() == 2)
+ else
{
- frames = 5;
+ mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/player_female_base.xml", 0);
}
- Image *image = weaponset[getWeapon() - 1]->get(mFrame + frames * dir);
- graphics->drawImage(image, px - 16, py - 32);
}
+ Being::setSex(sex);
+}
- if (getHairColor() <= NR_HAIR_COLORS)
+void
+Player::setHairColor(Uint16 color)
+{
+ if (color != mHairColor && mHairStyle > 0)
{
- int hf = 9 * (getHairColor() - 1) + hairframe[dir][frame];
-
- graphics->drawImage(hairset[getHairStyle() - 1]->get(hf),
- px + 1 + hairtable[frame][dir][0],
- py - 33 + hairtable[frame][dir][1]);
+ delete mSprites[HAIR_SPRITE];
+ mSprites[HAIR_SPRITE] = new AnimatedSprite("graphics/sprites/hairstyle"+toString(mHairStyle)+".xml", color - 1);
}
-
- // Display middle equipment
- if (mVisibleEquipment[5])
+ Being::setHairColor(color);
+};
+
+void
+Player::setHairStyle(Uint16 style)
+{
+ if (style != mHairStyle && mHairColor > 0)
{
- graphics->drawImage(
- equipmentset[mVisibleEquipment[5] - 1]->get(frame + 18 * dir),
- px - 16, py - 32);
+ delete mSprites[HAIR_SPRITE];
+ mSprites[HAIR_SPRITE] = new AnimatedSprite("graphics/sprites/hairstyle"+toString(style)+".xml", mHairColor - 1);
}
-}
+ Being::setHairStyle(style);
+};
void
-Player::drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
+Player::setVisibleEquipment(Uint8 slot, Uint8 id)
{
- int px = mPx + offsetX;
- int py = mPy + offsetY;
-
- graphics->setFont(speechFont);
- graphics->setColor(gcn::Color(255, 255, 255));
- graphics->drawText(mName, px + 15, py + 30, gcn::Graphics::CENTER);
+ // Translate eAthena specific slot
+ Uint8 position = 0;
+ switch (slot) {
+ case 3:
+ position = BOTTOMCLOTHES_SPRITE;
+ break;
+ case 4:
+ position = HAT_SPRITE;
+ break;
+ case 5:
+ position = TOPCLOTHES_SPRITE;
+ break;
+ }
+ // id = 0 means unequip
+ if (mSprites[position]) {
+ delete mSprites[position];
+ mSprites[position] = 0;
+ }
+ if (id) {
+ char stringId[4];
+ sprintf(stringId, "%03i", id);
+ printf("Id: %i %i %s\n", id, slot, stringId);
+ mSprites[position] = new AnimatedSprite(
+ "graphics/sprites/item" + toString(stringId) + ".xml", 0);
+ }
+ Being::setVisibleEquipment(slot, id);
}
+
+
diff --git a/src/player.h b/src/player.h
index 3c68116e..15e7f655 100644
--- a/src/player.h
+++ b/src/player.h
@@ -26,8 +26,11 @@
#include "being.h"
+#include <string>
+
class Graphics;
class Map;
+class AnimatedSprite;
class Player : public Being
{
@@ -38,9 +41,15 @@ class Player : public Being
virtual Type getType() const;
- virtual void draw(Graphics *graphics, int offsetX, int offsetY);
-
virtual void drawName(Graphics *graphics, Sint32 offsetX, Sint32 offsetY);
+
+ virtual void setSex(Uint8 sex);
+
+ virtual void setHairColor(Uint16 color);
+
+ virtual void setHairStyle(Uint16 style);
+
+ virtual void setVisibleEquipment(Uint8 slot, Uint8 id);
};
#endif
diff --git a/src/resources/imagewriter.cpp b/src/resources/imagewriter.cpp
index f4be3a66..7cfa16b4 100644
--- a/src/resources/imagewriter.cpp
+++ b/src/resources/imagewriter.cpp
@@ -55,7 +55,7 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
logger->log("Had trouble creating png_structp");
return false;
}
-
+
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
diff --git a/src/resources/itemmanager.cpp b/src/resources/itemmanager.cpp
index d18152da..56ac6354 100644
--- a/src/resources/itemmanager.cpp
+++ b/src/resources/itemmanager.cpp
@@ -21,10 +21,11 @@
* $Id$
*/
+#include "itemmanager.h"
+
#include <libxml/tree.h>
#include "iteminfo.h"
-#include "itemmanager.h"
#include "resourcemanager.h"
#include "../log.h"
diff --git a/src/sound.h b/src/sound.h
index 421bf899..39901121 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -88,7 +88,7 @@ class Sound {
/**
* Sets music volume.
- *
+ *
* \param volume Volume value
*/
void setMusicVolume(int volume);