From 68481094c0d02ba127bcab6c692801b01a27f21b Mon Sep 17 00:00:00 2001 From: Erik Schilling Date: Wed, 8 May 2013 00:06:32 +0200 Subject: [Abilities] Added abilities to monsters Monsters can now either receive abilities at lifetime via scripts, or via the node in the monsters node. --- src/game-server/abilitycomponent.cpp | 35 ++++++++++++++++------------ src/game-server/abilitycomponent.h | 6 +++-- src/game-server/monster.cpp | 7 ++++++ src/game-server/monster.h | 19 ++++++++++++++++ src/game-server/monstermanager.cpp | 44 ++++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 16 deletions(-) (limited to 'src/game-server') diff --git a/src/game-server/abilitycomponent.cpp b/src/game-server/abilitycomponent.cpp index 60c9b86f..961617b1 100644 --- a/src/game-server/abilitycomponent.cpp +++ b/src/game-server/abilitycomponent.cpp @@ -84,7 +84,7 @@ bool AbilityComponent::abilityUseCheck(AbilityMap::iterator it) if (it == mAbilities.end()) { - LOG_INFO("Character uses ability " << it->first + LOG_INFO("Entity uses ability " << it->first << " without authorization."); return false; } @@ -115,15 +115,15 @@ bool AbilityComponent::abilityUseCheck(AbilityMap::iterator it) * makes the character perform a ability on a being * when it is allowed to do so */ -void AbilityComponent::useAbilityOnBeing(Entity &user, int id, Entity *b) +bool AbilityComponent::useAbilityOnBeing(Entity &user, int id, Entity *b) { AbilityMap::iterator it = mAbilities.find(id); if (!abilityUseCheck(it)) - return; + return false; AbilityValue &ability = it->second; if (ability.abilityInfo->target != AbilityManager::TARGET_BEING) - return; + return false; if (ability.abilityInfo->autoconsume) { ability.currentPoints = 0; @@ -146,21 +146,22 @@ void AbilityComponent::useAbilityOnBeing(Entity &user, int id, Entity *b) mLastTargetBeingId = 0; user.getComponent()->raiseUpdateFlags( UPDATEFLAG_ABILITY_ON_BEING); + return true; } /** * makes the character perform a ability on a map point * when it is allowed to do so */ -void AbilityComponent::useAbilityOnPoint(Entity &user, int id, int x, int y) +bool AbilityComponent::useAbilityOnPoint(Entity &user, int id, int x, int y) { AbilityMap::iterator it = mAbilities.find(id); if (!abilityUseCheck(it)) - return; + return false; AbilityValue &ability = it->second; if (ability.abilityInfo->target != AbilityManager::TARGET_POINT) - return; + return false; if (ability.abilityInfo->autoconsume) { ability.currentPoints = 0; @@ -181,6 +182,7 @@ void AbilityComponent::useAbilityOnPoint(Entity &user, int id, int x, int y) mLastTargetPoint = Point(x, y); user.getComponent()->raiseUpdateFlags( UPDATEFLAG_ABILITY_ON_POINT); + return true; } /** @@ -190,22 +192,27 @@ bool AbilityComponent::giveAbility(int id, int currentPoints) { if (mAbilities.find(id) == mAbilities.end()) { - const AbilityManager::AbilityInfo *abilityInfo = - abilityManager->getAbilityInfo(id); + auto *abilityInfo = abilityManager->getAbilityInfo(id); if (!abilityInfo) { LOG_ERROR("Tried to give not existing ability id " << id << "."); return false; } - mAbilities.insert(std::pair( - id, AbilityValue(currentPoints, abilityInfo))); - - signal_ability_changed.emit(id); - return true; + return giveAbility(abilityInfo, currentPoints); } return false; } +bool AbilityComponent::giveAbility(const AbilityManager::AbilityInfo *info, + int currentPoints) +{ + bool added = mAbilities.insert(std::pair(info->id, + AbilityValue(currentPoints, info))).second; + + signal_ability_changed.emit(info->id); + return added; +} + /** * Sets new current mana + makes sure that the client will get informed. */ diff --git a/src/game-server/abilitycomponent.h b/src/game-server/abilitycomponent.h index def3e00b..7d3472e0 100644 --- a/src/game-server/abilitycomponent.h +++ b/src/game-server/abilitycomponent.h @@ -56,10 +56,12 @@ public: void update(Entity &entity); - void useAbilityOnBeing(Entity &user, int id, Entity *b); - void useAbilityOnPoint(Entity &user, int id, int x, int y); + bool useAbilityOnBeing(Entity &user, int id, Entity *b); + bool useAbilityOnPoint(Entity &user, int id, int x, int y); bool giveAbility(int id, int currentMana = 0); + bool giveAbility(const AbilityManager::AbilityInfo *info, + int currentMana = 0); bool hasAbility(int id) const; bool takeAbility(int id); AbilityMap::iterator findAbility(int id); diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index e0feed9e..45a99d82 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -86,6 +86,13 @@ MonsterComponent::MonsterComponent(Entity &entity, MonsterClass *specy): beingComponent->setGender(specy->getGender()); + AbilityComponent *abilityComponent = new AbilityComponent(entity); + entity.addComponent(abilityComponent); + for (auto *abilitiyInfo : specy->getAbilities()) + { + abilityComponent->giveAbility(abilitiyInfo); + } + beingComponent->signal_died.connect(sigc::mem_fun(this, &MonsterComponent::monsterDied)); } diff --git a/src/game-server/monster.h b/src/game-server/monster.h index 4949d4c7..9854a7a2 100644 --- a/src/game-server/monster.h +++ b/src/game-server/monster.h @@ -21,9 +21,13 @@ #ifndef MONSTER_H #define MONSTER_H +#include "game-server/abilitymanager.h" #include "game-server/being.h" + #include "common/defines.h" + #include "scripting/script.h" + #include "utils/string.h" #include @@ -182,6 +186,9 @@ class MonsterClass double getVulnerability(Element element) const; + void addAbility(AbilityManager::AbilityInfo *info); + const std::set &getAbilities() const; + void setUpdateCallback(Script *script) { script->assignCallback(mUpdateCallback); } @@ -201,6 +208,7 @@ class MonsterClass MonsterDrops mDrops; std::map mAttributes; /**< Base attributes of the monster. */ + std::set mAbilities; float mSpeed; /**< The monster class speed in tiles per second */ int mSize; int mExp; @@ -308,4 +316,15 @@ class MonsterComponent : public Component Timeout mDecayTimeout; }; +inline void MonsterClass::addAbility(AbilityManager::AbilityInfo *info) +{ + mAbilities.insert(info); +} + +inline const std::set +&MonsterClass::getAbilities() const +{ + return mAbilities; +} + #endif // MONSTER_H diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp index df8c6906..19e196e2 100644 --- a/src/game-server/monstermanager.cpp +++ b/src/game-server/monstermanager.cpp @@ -216,6 +216,50 @@ void MonsterManager::readMonsterNode(xmlNodePtr node, const std::string &filenam } } + else if (xmlStrEqual(subnode->name, BAD_CAST "attribute")) + { + const int id = XML::getProperty(subnode, "id", 0); + auto *attributeInfo = attributeManager->getAttributeInfo(id); + + if (!attributeInfo) + { + LOG_WARN(filename + << ": Invalid attribute id " << id + << " for monster Id: " << id + << ". Skipping!"); + continue; + } + + const double value = XML::getFloatProperty(subnode, "value", 0.0); + + monster->setAttribute(id, value); + } + else if (xmlStrEqual(subnode->name, BAD_CAST "ability")) + { + const std::string idText = XML::getProperty(subnode, "id", + std::string()); + AbilityManager::AbilityInfo *info = 0; + if (utils::isNumeric(idText)) + { + const int id = utils::stringToInt(idText); + info = abilityManager->getAbilityInfo(id); + } + else + { + info = abilityManager->getAbilityInfo(idText); + } + + if (!info) + { + LOG_WARN(filename + << ": Invalid ability id " << idText + << " for monster id: " << id + << " Skipping!"); + continue; + } + + monster->addAbility(info); + } else if (xmlStrEqual(subnode->name, BAD_CAST "exp")) { xmlChar *exp = subnode->xmlChildrenNode->content; -- cgit v1.2.3-60-g2f50