From b35aef2d924f03d85eb44a2465be5a745444eafd Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Thu, 26 May 2011 23:41:01 +0200 Subject: Added effects support in monsters attacks. This is provided through the use of the 'effect-id' property of the tag. Note that the 'particle-effect' support has been removed as it was redundant, but can be kept for backward compatibility. Now, on both Manaserv and tA, only the attack id 1 is supported, i.e: ... More to come with re-enabling of the attack type support. I had to fix a crash in the Being::takeDamage() function when there were no attacker (in Manaserv), and add rotation support to the effectManager to achieve this. Reviwed-by: Jaxad0127. --- src/being.cpp | 39 +++++++++++++++++++++------------------ src/being.h | 5 ++--- src/effectmanager.cpp | 8 ++++---- src/effectmanager.h | 12 ++++++++---- src/resources/beinginfo.cpp | 13 ++++++------- src/resources/beinginfo.h | 23 +++++++++++------------ src/resources/monsterdb.cpp | 11 +++++------ 7 files changed, 57 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/being.cpp b/src/being.cpp index 40479236..d6c5fd55 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -76,7 +76,6 @@ Being::Being(int id, Type type, int subtype, Map *map): mInfo(BeingInfo::Unknown), mActionTime(0), mSpeechTime(0), - mAttackType(1), mAttackSpeed(350), mAction(STAND), mSubType(0xFFFF), @@ -391,8 +390,10 @@ void Being::takeDamage(Being *attacker, int amount, AttackType type) // Init the particle effect path based on current weapon or default. int hitEffectId = 0; - const ItemInfo *attackerWeapon = attacker->getEquippedWeapon(); - if (attacker->getType() == PLAYER && attackerWeapon) + const ItemInfo *attackerWeapon = attacker ? + attacker->getEquippedWeapon() : 0; + + if (attackerWeapon && attacker->getType() == PLAYER) { if (type != CRITICAL) hitEffectId = attackerWeapon->getHitEffectId(); @@ -410,10 +411,16 @@ void Being::takeDamage(Being *attacker, int amount, AttackType type) } } -void Being::handleAttack(Being *victim, int damage, AttackType type) +void Being::handleAttack(Being *victim, int damage, int attackId) { + // Monsters, NPCs and remote players handle the first attack (id="1") + // per default. + // TODO: Fix this for Manaserv by sending the attack id. + // TODO: Add attack type handling, see Attack struct and AttackType + // and make use of it by grouping attacks per attack type and add random + // attack use on tA, based on normal and critical attack types. if (this != player_node) - setAction(Being::ATTACK, 1); + setAction(Being::ATTACK, attackId); if (victim) lookAt(victim->getPosition()); @@ -421,7 +428,8 @@ void Being::handleAttack(Being *victim, int damage, AttackType type) if (getType() == PLAYER && victim && mEquippedWeapon) fireMissile(victim, mEquippedWeapon->getMissileParticleFile()); else - fireMissile(victim, mInfo->getAttack(mAttackType)->missileParticle); + fireMissile(victim, + mInfo->getAttack(attackId)->mMissileParticleFilename); sound.playSfx(mInfo->getSound((damage > 0) ? SOUND_EVENT_HIT : SOUND_EVENT_MISS), @@ -585,7 +593,7 @@ void Being::fireMissile(Being *victim, const std::string &particle) } -void Being::setAction(Action action, int attackType) +void Being::setAction(Action action, int attackId) { std::string currentAction = SpriteAction::INVALID; @@ -608,16 +616,14 @@ void Being::setAction(Action action, int attackType) } else { - mAttackType = attackType; - currentAction = mInfo->getAttack(attackType)->action; + currentAction = mInfo->getAttack(attackId)->mAction; reset(); - int rotation = 0; - //attack particle effect - std::string particleEffect = mInfo->getAttack(attackType) - ->particleEffect; - if (!particleEffect.empty() && Particle::enabled) + // Attack particle effect + if (Particle::enabled) { + int effectId = mInfo->getAttack(attackId)->mEffectId; + int rotation = 0; switch (mSpriteDirection) { case DIRECTION_DOWN: rotation = 0; break; @@ -626,10 +632,7 @@ void Being::setAction(Action action, int attackType) case DIRECTION_RIGHT: rotation = 270; break; default: break; } - Particle *p; - p = particleEngine->addEffect(particleEffect, 0, 0, - rotation); - controlParticle(p); + effectManager->trigger(effectId, this, rotation); } } diff --git a/src/being.h b/src/being.h index f380e0b8..9ac014e0 100644 --- a/src/being.h +++ b/src/being.h @@ -172,9 +172,9 @@ class Being : public ActorSprite, public EventListener * * @param victim the victim being * @param damage the amount of damage dealt (0 means miss) - * @param type the attack type + * @param attackId the attack id */ - virtual void handleAttack(Being *victim, int damage, AttackType type); + virtual void handleAttack(Being *victim, int damage, int attackId = 1); const ItemInfo *getEquippedWeapon() const { return mEquippedWeapon; } @@ -471,7 +471,6 @@ class Being : public ActorSprite, public EventListener /** Time until the last speech sentence disappears */ int mSpeechTime; - int mAttackType; int mAttackSpeed; /**< Attack speed */ Action mAction; /**< Action the being is performing */ diff --git a/src/effectmanager.cpp b/src/effectmanager.cpp index 576d48b6..5ac1dd5a 100644 --- a/src/effectmanager.cpp +++ b/src/effectmanager.cpp @@ -63,7 +63,7 @@ EffectManager::~EffectManager() { } -bool EffectManager::trigger(int id, Being* being) +bool EffectManager::trigger(int id, Being* being, int rotation) { bool rValue = false; for (std::list::iterator i = mEffects.begin(); i != mEffects.end(); ++i) @@ -74,7 +74,7 @@ bool EffectManager::trigger(int id, Being* being) if (!(*i).GFX.empty()) { Particle *selfFX; - selfFX = particleEngine->addEffect((*i).GFX, 0, 0); + selfFX = particleEngine->addEffect((*i).GFX, 0, 0, rotation); being->controlParticle(selfFX); } if (!(*i).SFX.empty()) @@ -85,7 +85,7 @@ bool EffectManager::trigger(int id, Being* being) return rValue; } -bool EffectManager::trigger(int id, int x, int y) +bool EffectManager::trigger(int id, int x, int y, int rotation) { bool rValue = false; for (std::list::iterator i = mEffects.begin(); i != mEffects.end(); ++i) @@ -94,7 +94,7 @@ bool EffectManager::trigger(int id, int x, int y) { rValue = true; if (!(*i).GFX.empty()) - particleEngine->addEffect((*i).GFX, x, y); + particleEngine->addEffect((*i).GFX, x, y, rotation); if (!(*i).SFX.empty()) sound.playSfx((*i).SFX); break; diff --git a/src/effectmanager.h b/src/effectmanager.h index ef1e0f27..8302990e 100644 --- a/src/effectmanager.h +++ b/src/effectmanager.h @@ -42,15 +42,19 @@ class EffectManager /** * Triggers a effect with the id, at - * the specified being. + * the specified being, + * and with the given rotation in degree: + * 0° = Down, 90° = left, ... */ - bool trigger(int id, Being* being); + bool trigger(int id, Being* being, int rotation = 0); /** * Triggers a effect with the id, at - * the specified x and y coordinate. + * the specified x and y coordinate, + * and with the given rotation in degree: + * 0° = Down, 90° = left, ... */ - bool trigger(int id, int x, int y); + bool trigger(int id, int x, int y, int rotation = 0); private: std::list mEffects; diff --git a/src/resources/beinginfo.cpp b/src/resources/beinginfo.cpp index e8824391..22651f6f 100644 --- a/src/resources/beinginfo.cpp +++ b/src/resources/beinginfo.cpp @@ -88,20 +88,19 @@ const std::string &BeingInfo::getSound(SoundEvent event) const i->second->at(rand() % i->second->size()); } -const Attack *BeingInfo::getAttack(int type) const +const Attack *BeingInfo::getAttack(int id) const { - static Attack *empty = new Attack(SpriteAction::ATTACK, "", ""); + static Attack *empty = new Attack(SpriteAction::ATTACK, -1, std::string()); - Attacks::const_iterator i = mAttacks.find(type); + Attacks::const_iterator i = mAttacks.find(id); return (i == mAttacks.end()) ? empty : (*i).second; } -void BeingInfo::addAttack(int id, std::string action, - const std::string &particleEffect, - const std::string &missileParticle) +void BeingInfo::addAttack(int id, std::string action, int effectId, + const std::string &missileParticleFilename) { if (mAttacks[id]) delete mAttacks[id]; - mAttacks[id] = new Attack(action, particleEffect, missileParticle); + mAttacks[id] = new Attack(action, effectId, missileParticleFilename); } diff --git a/src/resources/beinginfo.h b/src/resources/beinginfo.h index 52390976..b4529b2f 100644 --- a/src/resources/beinginfo.h +++ b/src/resources/beinginfo.h @@ -32,16 +32,16 @@ #include struct Attack { - std::string action; - std::string particleEffect; - std::string missileParticle; + std::string mAction; + int mEffectId; + std::string mMissileParticleFilename; - Attack(std::string action, std::string particleEffect, - std::string missileParticle) + Attack(std::string action, int effectId, + std::string missileParticleFilename) { - this->action = action; - this->particleEffect = particleEffect; - this->missileParticle = missileParticle; + mAction = action; + mEffectId = effectId; + mMissileParticleFilename = missileParticleFilename; } }; @@ -95,11 +95,10 @@ class BeingInfo const std::string &getSound(SoundEvent event) const; - void addAttack(int id, std::string action, - const std::string &particleEffect, - const std::string &missileParticle); + void addAttack(int id, std::string action, int effectId, + const std::string &missileParticleFilename); - const Attack *getAttack(int type) const; + const Attack *getAttack(int id) const; void setWalkMask(unsigned char mask) { mWalkMask = mask; } diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp index 6bc64a89..ca9b8e83 100644 --- a/src/resources/monsterdb.cpp +++ b/src/resources/monsterdb.cpp @@ -124,15 +124,14 @@ void MonsterDB::load() else if (xmlStrEqual(spriteNode->name, BAD_CAST "attack")) { const int id = XML::getProperty(spriteNode, "id", 0); - const std::string particleEffect = XML::getProperty( - spriteNode, "particle-effect", ""); + int effectId = XML::getProperty(spriteNode, "effect-id", -1); const std::string spriteAction = XML::getProperty(spriteNode, "action", "attack"); - const std::string missileParticle = XML::getProperty( - spriteNode, "missile-particle", ""); - currentInfo->addAttack(id, spriteAction, - particleEffect, missileParticle); + const std::string missileParticleFilename = + XML::getProperty(spriteNode, "missile-particle", ""); + currentInfo->addAttack(id, spriteAction, effectId, + missileParticleFilename); } else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx")) { -- cgit v1.2.3-70-g09d2