From 8e5861c3cfd41574351547a1a518efcf9007666a Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 23 Nov 2011 04:40:34 +0300 Subject: 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: ... Here 50 mean 50% of health or less. Default action tag mean hp=100 --- src/animatedsprite.cpp | 23 +++++++++++-- src/animatedsprite.h | 4 +++ src/being.cpp | 27 +++++++++++++++- src/being.h | 3 ++ src/compoundsprite.cpp | 15 +++++++++ src/compoundsprite.h | 2 ++ src/imagesprite.h | 3 ++ src/net/ea/beinghandler.cpp | 2 +- src/resources/action.cpp | 3 +- src/resources/action.h | 7 ++++ src/resources/spritedef.cpp | 78 +++++++++++++++++++++++++++++++++++---------- src/resources/spritedef.h | 12 +++++-- src/sprite.h | 2 ++ 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 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 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::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 *d = (*it).second; + if (d->find(complete) == d->end()) + { + std::map::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 actions; + for (Actions::iterator i = mActions.begin(), i_end = mActions.end(); i != i_end; ++i) { - actions.insert(i->second); + std::map::iterator it = (*i).second->begin(); + std::map::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::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(); + + (*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 ImageSets; typedef ImageSets::iterator ImageSetIterator; - typedef std::map Actions; +// typedef std::map*> Actions; + typedef std::map*> 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 */ }; -- cgit v1.2.3-60-g2f50