summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2013-05-08 00:06:32 +0200
committerErik Schilling <ablu.erikschilling@googlemail.com>2013-05-11 23:31:14 +0200
commitf6765ffda1e0db5006aaebc359b2634837fe70bd (patch)
tree9d79efdcd21bf008d296cfd6b73d03e9870fc0ba /src
parentcec65058123f710643290c13b7f2b0512b878381 (diff)
downloadmanaserv-f6765ffda1e0db5006aaebc359b2634837fe70bd.tar.gz
manaserv-f6765ffda1e0db5006aaebc359b2634837fe70bd.tar.xz
manaserv-f6765ffda1e0db5006aaebc359b2634837fe70bd.zip
[Abilities] Added abilities to monsters
Monsters can now either receive abilities at lifetime via scripts, or via the <ability> node in the monsters node.
Diffstat (limited to 'src')
-rw-r--r--src/game-server/abilitycomponent.cpp35
-rw-r--r--src/game-server/abilitycomponent.h6
-rw-r--r--src/game-server/monster.cpp7
-rw-r--r--src/game-server/monster.h19
-rw-r--r--src/game-server/monstermanager.cpp44
-rw-r--r--src/scripting/lua.cpp55
6 files changed, 140 insertions, 26 deletions
diff --git a/src/game-server/abilitycomponent.cpp b/src/game-server/abilitycomponent.cpp
index 60c9b86..961617b 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<ActorComponent>()->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<ActorComponent>()->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<int, AbilityValue>(
- 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<int, AbilityValue>(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 def3e00..7d3472e 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 e0feed9..45a99d8 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 4949d4c..9854a7a 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 <map>
@@ -182,6 +186,9 @@ class MonsterClass
double getVulnerability(Element element) const;
+ void addAbility(AbilityManager::AbilityInfo *info);
+ const std::set<AbilityManager::AbilityInfo *> &getAbilities() const;
+
void setUpdateCallback(Script *script)
{ script->assignCallback(mUpdateCallback); }
@@ -201,6 +208,7 @@ class MonsterClass
MonsterDrops mDrops;
std::map<int, double> mAttributes; /**< Base attributes of the monster. */
+ std::set<AbilityManager::AbilityInfo *> 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<AbilityManager::AbilityInfo *>
+&MonsterClass::getAbilities() const
+{
+ return mAbilities;
+}
+
#endif // MONSTER_H
diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp
index df8c690..19e196e 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;
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index 258b9bc..b3fe93c 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -2242,18 +2242,18 @@ static int entity_show_text_particle(lua_State *s)
/** LUA entity:give_ability (being)
* entity:give_ability(int ability)
**
- * Valid only for character entities.
+ * Valid only for character and monster entities.
*
* Enables a ability for a character.
*/
static int entity_give_ability(lua_State *s)
{
// cost_type is ignored until we have more than one cost type
- Entity *c = checkCharacter(s, 1);
+ Entity *b = checkBeing(s, 1);
auto *abilityInfo = checkAbility(s, 2);
const int currentMana = luaL_optint(s, 3, 0);
- c->getComponent<AbilityComponent>()->giveAbility(abilityInfo->id,
+ b->getComponent<AbilityComponent>()->giveAbility(abilityInfo->id,
currentMana);
return 0;
}
@@ -2261,40 +2261,74 @@ static int entity_give_ability(lua_State *s)
/** LUA entity:has_ability (being)
* entity:has_ability(int ability)
**
- * Valid only for character entities.
+ * Valid only for character and monster entities.
*
* **Return value:** True if the character has the ability, false otherwise.
*/
static int entity_has_ability(lua_State *s)
{
- Entity *c = checkCharacter(s, 1);
+ Entity *b = checkBeing(s, 1);
const int ability = luaL_checkint(s, 2);
- lua_pushboolean(s, c->getComponent<AbilityComponent>()->hasAbility(ability));
+ lua_pushboolean(s, b->getComponent<AbilityComponent>()->hasAbility(ability));
return 1;
}
/** LUA entity:take_ability (being)
* entity:take_ability(int ability)
**
- * Valid only for character entities.
+ * Valid only for character and monster entities.
*
- * Removes a ability from a character.
+ * Removes a ability from a entity.
*
* **Return value:** True if removal was successful, false otherwise (in case
* the character did not have the ability).
*/
static int entity_take_ability(lua_State *s)
{
- Entity *c = checkCharacter(s, 1);
+ Entity *b = checkBeing(s, 1);
const int ability = luaL_checkint(s, 2);
- auto *abilityComponent = c->getComponent<AbilityComponent>();
+ auto *abilityComponent = b->getComponent<AbilityComponent>();
lua_pushboolean(s, abilityComponent->hasAbility(ability));
abilityComponent->takeAbility(ability);
return 1;
}
+/** LUA entity:use_ability (being)
+ * entity:use_ability(int ability)
+ **
+ * Valid only for character and monster entities.
+ *
+ * Makes the entity using the given ability if it is available and recharged.
+ *
+ * **Return value:** True if the ability was used successfully. False otherwise
+ * (if the ability is not available for the entity or was not recharged).
+ */
+static int entity_use_ability(lua_State *s)
+{
+ Entity *b = checkBeing(s, 1);
+ const int ability = luaL_checkint(s, 2);
+ bool targetIsBeing = lua_gettop(s) == 3;
+
+ auto *abilityComponent = b->getComponent<AbilityComponent>();
+ if (targetIsBeing)
+ {
+ Entity *target = checkBeing(s, 3);
+ lua_pushboolean(s, abilityComponent->useAbilityOnBeing(*b, ability,
+ target));
+ }
+ else
+ {
+ const int x = luaL_checkint(s, 3);
+ const int y = luaL_checkint(s, 4);
+ lua_pushboolean(s, abilityComponent->useAbilityOnPoint(*b, ability,
+ x, y));
+ }
+
+ return 1;
+}
+
/** LUA_CATEGORY Monster (monster)
*/
@@ -3327,6 +3361,7 @@ LuaScript::LuaScript():
{ "give_ability", entity_give_ability },
{ "has_ability", entity_has_ability },
{ "take_ability", entity_take_ability },
+ { "use_ability", entity_use_ability },
{ "monster_id", entity_get_monster_id },
{ "apply_status", entity_apply_status },
{ "remove_status", entity_remove_status },