summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2011-11-23 04:40:34 +0300
committerAndrei Karas <akaras@inbox.ru>2011-11-24 03:32:57 +0300
commit8e5861c3cfd41574351547a1a518efcf9007666a (patch)
tree8d941791c1bbd296b7125475fa0abb9581df632f
parent004aa3358c6efeb469045785baa891a449dde5a4 (diff)
downloadmv-8e5861c3cfd41574351547a1a518efcf9007666a.tar.gz
mv-8e5861c3cfd41574351547a1a518efcf9007666a.tar.bz2
mv-8e5861c3cfd41574351547a1a518efcf9007666a.tar.xz
mv-8e5861c3cfd41574351547a1a518efcf9007666a.zip
Add ability to play different animation depend on monster hp.
Disabled for legacy servers because monster hp unknown and compilated hp can be wrong (version <= 0). For usage need add to action tag attribute hp="xx" Example: <action name="stand" hp="50" imageset="base"> ... </action> Here 50 mean 50% of health or less. Default action tag mean hp=100
-rw-r--r--src/animatedsprite.cpp23
-rw-r--r--src/animatedsprite.h4
-rw-r--r--src/being.cpp27
-rw-r--r--src/being.h3
-rw-r--r--src/compoundsprite.cpp15
-rw-r--r--src/compoundsprite.h2
-rw-r--r--src/imagesprite.h3
-rw-r--r--src/net/ea/beinghandler.cpp2
-rw-r--r--src/resources/action.cpp3
-rw-r--r--src/resources/action.h7
-rw-r--r--src/resources/spritedef.cpp78
-rw-r--r--src/resources/spritedef.h12
-rw-r--r--src/sprite.h2
13 files changed, 157 insertions, 24 deletions
diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp
index c1f1cac85..4143cb47a 100644
--- a/src/animatedsprite.cpp
+++ b/src/animatedsprite.cpp
@@ -42,7 +42,9 @@ AnimatedSprite::AnimatedSprite(SpriteDef *sprite):
mSprite(sprite),
mAction(nullptr),
mAnimation(nullptr),
- mFrame(nullptr)
+ mFrame(nullptr),
+ mNumber(100),
+ mNumber1(100)
{
mAlpha = 1.0f;
@@ -51,6 +53,7 @@ AnimatedSprite::AnimatedSprite(SpriteDef *sprite):
mSprite->incRef();
// Play the stand animation by default
+ //+++ need get num?
play(SpriteAction::STAND);
}
@@ -90,7 +93,7 @@ bool AnimatedSprite::play(std::string spriteAction)
if (!mSprite)
return false;
- Action *action = mSprite->getAction(spriteAction);
+ Action *action = mSprite->getAction(spriteAction, mNumber);
if (!action)
return false;
@@ -313,3 +316,19 @@ void *AnimatedSprite::getHash()
// return mAnimation;
return this;
}
+
+bool AnimatedSprite::updateNumber(unsigned num)
+{
+ if (mNumber1 != num)
+ {
+ mNumber1 = num;
+ mNumber = mSprite->findNumber(num);
+ if (!mNumber)
+ {
+ mNumber = 100;
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/src/animatedsprite.h b/src/animatedsprite.h
index 2a2cfb8d8..16bcdf2da 100644
--- a/src/animatedsprite.h
+++ b/src/animatedsprite.h
@@ -84,6 +84,8 @@ class AnimatedSprite : public Sprite
virtual void *getHash();
+ bool updateNumber(unsigned num);
+
private:
bool updateCurrentAnimation(unsigned int dt);
@@ -97,6 +99,8 @@ class AnimatedSprite : public Sprite
Action *mAction; /**< The currently active action. */
Animation *mAnimation; /**< The currently active animation. */
Frame *mFrame; /**< The currently active frame. */
+ unsigned mNumber;
+ unsigned mNumber1;
};
#endif
diff --git a/src/being.cpp b/src/being.cpp
index 9d731d2c9..3ed7ba587 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -253,7 +253,8 @@ Being::Being(int id, Type type, Uint16 subtype, Map *map):
mAdvanced(false),
mShop(false),
mAway(false),
- mInactive(false)
+ mInactive(false),
+ mNumber(100)
{
mSpriteRemap = new int[20];
mSpriteHide = new int[20];
@@ -287,6 +288,7 @@ Being::Being(int id, Type type, Uint16 subtype, Map *map):
updateColors();
resetCounters();
+ updatePercentHP();
}
Being::~Being()
@@ -660,7 +662,10 @@ void Being::takeDamage(Being *attacker, int amount, AttackType type)
}
if (mType == MONSTER)
+ {
+ updatePercentHP();
updateName();
+ }
else if (mType == PLAYER && socialWindow && getName() != "")
socialWindow->updateAvatar(getName());
@@ -1036,6 +1041,7 @@ void Being::setAction(Action action, int attackType A_UNUSED)
if (currentAction != SpriteAction::INVALID)
{
+ //set mNumber
play(currentAction);
mAction = action;
}
@@ -2102,6 +2108,8 @@ void Being::setHP(int hp)
mHP = hp;
if (mMaxHP < mHP)
mMaxHP = mHP;
+ if (mType == MONSTER)
+ updatePercentHP();
}
void Being::setMaxHP(int hp)
@@ -2521,6 +2529,23 @@ void Being::setEmote(Uint8 emotion, int emote_time)
}
}
+void Being::updatePercentHP()
+{
+ if (!mMaxHP || !serverVersion)
+ return;
+ unsigned num = 0;
+ if (mHP)
+ {
+ num = mHP * 100 / mMaxHP;
+ if (num != mNumber)
+ {
+ mNumber = num;
+ if (updateNumber(mNumber))
+ setAction(mAction);
+ }
+ }
+}
+
BeingEquipBackend::BeingEquipBackend(Being *being):
mBeing(being)
{
diff --git a/src/being.h b/src/being.h
index 9ee60fcdf..1a5644929 100644
--- a/src/being.h
+++ b/src/being.h
@@ -767,6 +767,8 @@ class Being : public ActorSprite, public ConfigListener
void attack2(Being *target = nullptr, bool keep = false,
bool dontChangeEquipment = false);
+ void updatePercentHP();
+
protected:
/**
* Sets the new path for this being.
@@ -909,6 +911,7 @@ class Being : public ActorSprite, public ConfigListener
bool mShop;
bool mAway;
bool mInactive;
+ unsigned mNumber;
};
extern std::list<BeingCacheEntry*> beingInfoCache;
diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp
index 3ee988cec..912c51404 100644
--- a/src/compoundsprite.cpp
+++ b/src/compoundsprite.cpp
@@ -544,6 +544,21 @@ void CompoundSprite::initCurrentCacheItem() const
}
}
+bool CompoundSprite::updateNumber(unsigned num)
+{
+ SpriteConstIterator it, it_end;
+ bool res(false);
+ for (it = begin(), it_end = end(); it != it_end; ++ it)
+ {
+ if (*it)
+ {
+ if ((*it)->updateNumber(num))
+ res = true;
+ }
+ }
+ return res;
+}
+
CompoundItem::CompoundItem() :
// alpha(1.0f),
image(nullptr),
diff --git a/src/compoundsprite.h b/src/compoundsprite.h
index d1b019057..f29bece7f 100644
--- a/src/compoundsprite.h
+++ b/src/compoundsprite.h
@@ -119,6 +119,8 @@ public:
virtual void setAlpha(float alpha);
+ bool updateNumber(unsigned num);
+
private:
void redraw() const;
diff --git a/src/imagesprite.h b/src/imagesprite.h
index 21705c812..c59dd8eec 100644
--- a/src/imagesprite.h
+++ b/src/imagesprite.h
@@ -73,6 +73,9 @@ public:
unsigned int getFrameCount() const
{ return 1; }
+ bool updateNumber(unsigned num A_UNUSED)
+ { return false; }
+
private:
Image *mImage;
};
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp
index 5c3c694b3..1c2983137 100644
--- a/src/net/ea/beinghandler.cpp
+++ b/src/net/ea/beinghandler.cpp
@@ -215,10 +215,10 @@ void BeingHandler::processBeingVisibleOrMove(Net::MessageIn &msg, bool visible)
int maxHP = msg.readInt32();
if (hp && maxHP)
{
+ dstBeing->setMaxHP(maxHP);
int oldHP = dstBeing->getHP();
if (!oldHP || oldHP > hp)
dstBeing->setHP(hp);
- dstBeing->setMaxHP(maxHP);
}
}
else
diff --git a/src/resources/action.cpp b/src/resources/action.cpp
index c2af3ff9b..f940bffcb 100644
--- a/src/resources/action.cpp
+++ b/src/resources/action.cpp
@@ -29,7 +29,8 @@
#include "debug.h"
-Action::Action()
+Action::Action() :
+ mNumber(100)
{
}
diff --git a/src/resources/action.h b/src/resources/action.h
index 05b326d8f..9ab6f98d5 100644
--- a/src/resources/action.h
+++ b/src/resources/action.h
@@ -43,10 +43,17 @@ class Action
Animation *getAnimation(int direction) const;
+ unsigned getNumber()
+ { return mNumber; }
+
+ void setNumber(unsigned n)
+ { mNumber = n; }
+
protected:
typedef std::map<int, Animation*> Animations;
typedef Animations::iterator AnimationIterator;
Animations mAnimations;
+ unsigned mNumber;
};
#endif
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
index 3e2aac785..6b856c5d3 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -41,17 +41,41 @@
SpriteReference *SpriteReference::Empty = nullptr;
-Action *SpriteDef::getAction(std::string action) const
+Action *SpriteDef::getAction(std::string action, unsigned num) const
{
- Actions::const_iterator i = mActions.find(action);
+ Actions::const_iterator i = mActions.find(num);
+ if (i == mActions.end() && num != 100)
+ i = mActions.find(100);
if (i == mActions.end())
+ return nullptr;
+
+ std::map<std::string, Action*>::const_iterator it
+ = ((*i).second)->find(action);
+
+ if (it == ((*i).second)->end())
{
logger->log("Warning: no action \"%s\" defined!", action.c_str());
return nullptr;
}
- return i->second;
+ return (*it).second;
+}
+
+unsigned SpriteDef::findNumber(unsigned num) const
+{
+ unsigned min = 101;
+ Actions::const_iterator it = mActions.begin();
+ Actions::const_iterator it_end = mActions.end();
+ for (; it != it_end; ++ it)
+ {
+ unsigned n = (*it).first;
+ if (n >= num && n < min)
+ min = n;
+ }
+ if (min == 101)
+ return 0;
+ return min;
}
SpriteDef *SpriteDef::load(const std::string &animationFile, int variant)
@@ -84,11 +108,17 @@ SpriteDef *SpriteDef::load(const std::string &animationFile, int variant)
void SpriteDef::substituteAction(std::string complete, std::string with)
{
- if (mActions.find(complete) == mActions.end())
+ Actions::const_iterator it = mActions.begin();
+ Actions::const_iterator it_end = mActions.end();
+ for (; it != it_end; ++ it)
{
- Actions::const_iterator i = mActions.find(with);
- if (i != mActions.end())
- mActions[complete] = i->second;
+ std::map<std::string, Action*> *d = (*it).second;
+ if (d->find(complete) == d->end())
+ {
+ std::map<std::string, Action*>::iterator i = d->find(with);
+ if (i != d->end())
+ (*d)[complete] = i->second;
+ }
}
}
@@ -162,6 +192,7 @@ void SpriteDef::loadAction(xmlNodePtr node, int variant_offset)
{
const std::string actionName = XML::getProperty(node, "name", "");
const std::string imageSetName = XML::getProperty(node, "imageset", "");
+ const unsigned hp = XML::getProperty(node, "hp", 100);
ImageSetIterator si = mImageSets.find(imageSetName);
if (si == mImageSets.end())
@@ -179,15 +210,17 @@ void SpriteDef::loadAction(xmlNodePtr node, int variant_offset)
return;
}
Action *action = new Action;
- mActions[actionName] = action;
+ action->setNumber(hp);
+ addAction(hp, actionName, action);
// dirty hack to fix bad resources in tmw server
if (actionName == "attack_stab")
- mActions["attack"] = action;
+ addAction(hp, "attack", action);
// When first action set it as default direction
- if (mActions.size() == 1)
- mActions[SpriteAction::DEFAULT] = action;
+ Actions::const_iterator i = mActions.find(hp);
+ if ((*i).second->size() == 1)
+ addAction(hp, SpriteAction::DEFAULT, action);
// Load animations
for_each_xml_child_node(animationNode, node)
@@ -339,14 +372,18 @@ void SpriteDef::includeSprite(xmlNodePtr includeNode)
SpriteDef::~SpriteDef()
{
// Actions are shared, so ensure they are deleted only once.
- std::set< Action * > actions;
- for (Actions::const_iterator i = mActions.begin(),
+ std::set<Action*> actions;
+ for (Actions::iterator i = mActions.begin(),
i_end = mActions.end(); i != i_end; ++i)
{
- actions.insert(i->second);
+ std::map<std::string, Action*>::iterator it = (*i).second->begin();
+ std::map<std::string, Action*>::iterator it_end = (*i).second->end();
+ for (; it != it_end; ++ it)
+ actions.insert(it->second);
+ delete (*i).second;
}
- for (std::set< Action * >::const_iterator i = actions.begin(),
+ for (std::set<Action*>::const_iterator i = actions.begin(),
i_end = actions.end(); i != i_end; ++i)
{
delete *i;
@@ -355,7 +392,7 @@ SpriteDef::~SpriteDef()
mActions.clear();
for (ImageSetIterator i = mImageSets.begin();
- i != mImageSets.end(); ++i)
+ i != mImageSets.end(); ++i)
{
if (i->second)
{
@@ -388,3 +425,12 @@ SpriteDirection SpriteDef::makeSpriteDirection(const std::string &direction)
else
return DIRECTION_INVALID;
}
+
+void SpriteDef::addAction(unsigned hp, std::string name, Action *action)
+{
+ Actions::const_iterator i = mActions.find(hp);
+ if (i == mActions.end())
+ mActions[hp] = new std::map<std::string, Action*>();
+
+ (*mActions[hp])[name] = action;
+}
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index b2939fca1..642962c0b 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -117,7 +117,9 @@ class SpriteDef : public Resource
/**
* Returns the specified action.
*/
- Action *getAction(std::string action) const;
+ Action *getAction(std::string action, unsigned num) const;
+
+ unsigned findNumber(unsigned num) const;
/**
* Converts a string into a SpriteDirection enum.
@@ -125,11 +127,14 @@ class SpriteDef : public Resource
static SpriteDirection
makeSpriteDirection(const std::string &direction);
+ void addAction(unsigned hp, std::string name, Action *action);
+
private:
/**
* Constructor.
*/
- SpriteDef() {}
+ SpriteDef()
+ { }
/**
* Destructor.
@@ -178,7 +183,8 @@ class SpriteDef : public Resource
typedef std::map<std::string, ImageSet*> ImageSets;
typedef ImageSets::iterator ImageSetIterator;
- typedef std::map<std::string, Action*> Actions;
+// typedef std::map<std::string, std::map<unsigned, Action*>*> Actions;
+ typedef std::map<unsigned, std::map<std::string, Action*>*> Actions;
ImageSets mImageSets;
Actions mActions;
diff --git a/src/sprite.h b/src/sprite.h
index 52752619b..64721b740 100644
--- a/src/sprite.h
+++ b/src/sprite.h
@@ -112,6 +112,8 @@ class Sprite
virtual void *getHash2()
{ return this; }
+ virtual bool updateNumber(unsigned num) = 0;
+
protected:
float mAlpha; /**< The alpha opacity used to draw */
};