summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2013-08-19 22:15:26 +0200
committerErik Schilling <ablu.erikschilling@googlemail.com>2013-08-26 22:56:48 +0200
commit81a88f1dd199691ce570ab124a43740b77a67f03 (patch)
treee5cd82a8b73c1d909f63fb18357daac91f7c0d62
parentb379c150cedfbae4775c8358369ec590ad4033f4 (diff)
downloadmanaserv-81a88f1dd199691ce570ab124a43740b77a67f03.tar.gz
manaserv-81a88f1dd199691ce570ab124a43740b77a67f03.tar.bz2
manaserv-81a88f1dd199691ce570ab124a43740b77a67f03.tar.xz
manaserv-81a88f1dd199691ce570ab124a43740b77a67f03.zip
Allowed to push attributeinfos for the attribute recalculation
While on it I replaced the id usage in the server with the usage of the AttributeInfo directly. Next steps: - Dehardcode the core attribute ids and store their attributeinfos somewhere in AttributeManager (for now i simply wrapped the ids with getAttributeInfo(). - Move AttributeInfo out of AttributeManager to shorten the usage + to allow using a pointer in ModifierLocation without forward declaring it.
-rw-r--r--example/scripts/abilities.lua2
-rw-r--r--example/scripts/attributes.lua94
-rw-r--r--example/scripts/damage.lua8
-rw-r--r--example/scripts/npcs/postman.lua2
-rw-r--r--src/game-server/accountconnection.cpp2
-rw-r--r--src/game-server/attributemanager.cpp40
-rw-r--r--src/game-server/attributemanager.h21
-rw-r--r--src/game-server/being.cpp137
-rw-r--r--src/game-server/being.h38
-rw-r--r--src/game-server/buysell.cpp14
-rw-r--r--src/game-server/buysell.h4
-rw-r--r--src/game-server/character.cpp45
-rw-r--r--src/game-server/character.h8
-rw-r--r--src/game-server/commandhandler.cpp25
-rw-r--r--src/game-server/gamehandler.cpp10
-rw-r--r--src/game-server/item.cpp11
-rw-r--r--src/game-server/item.h16
-rw-r--r--src/game-server/itemmanager.cpp4
-rw-r--r--src/game-server/monster.cpp10
-rw-r--r--src/game-server/monster.h12
-rw-r--r--src/game-server/monstermanager.cpp2
-rw-r--r--src/game-server/spawnareacomponent.cpp3
-rw-r--r--src/game-server/state.cpp9
-rw-r--r--src/game-server/trade.cpp17
-rw-r--r--src/game-server/trade.h4
-rw-r--r--src/scripting/lua.cpp91
-rw-r--r--src/scripting/luascript.cpp7
-rw-r--r--src/scripting/luascript.h4
-rw-r--r--src/scripting/luautil.cpp17
-rw-r--r--src/scripting/luautil.h8
-rw-r--r--src/scripting/script.h4
31 files changed, 384 insertions, 285 deletions
diff --git a/example/scripts/abilities.lua b/example/scripts/abilities.lua
index cbdc22d3..46d97af8 100644
--- a/example/scripts/abilities.lua
+++ b/example/scripts/abilities.lua
@@ -28,7 +28,7 @@ spell1:on_use(function(user, x, y, abilityId)
local damage = {
base = 10,
delta = 5,
- chance_to_hit = user:modified_attribute(ATTR_STR),
+ chance_to_hit = user:modified_attribute("Strength"),
}
being:damage(user, damage)
being:say("OUCH")
diff --git a/example/scripts/attributes.lua b/example/scripts/attributes.lua
index 3e9b97e0..7a3f6098 100644
--- a/example/scripts/attributes.lua
+++ b/example/scripts/attributes.lua
@@ -7,78 +7,76 @@
--]]
-local ATTR_EXP = 22
-local ATTR_LEVEL = 23
-
-local function recalculate_base_attribute(being, attribute)
- local old_base = being:base_attribute(attribute)
+local function recalculate_base_attribute(being, attribute_name)
+ local old_base = being:base_attribute(attribute_name)
local new_base = old_base
- if attribute == ATTR_ACCURACY then
+ if attribute == "Accuracy" then
-- Provisional
- new_base = being:modified_attribute(ATTR_DEX)
- elseif attribute == ATTR_DEFENSE then
- new_base = 0.3 * being:modified_attribute(ATTR_VIT)
- elseif attribute == ATTR_DODGE then
+ new_base = being:modified_attribute("Dexterity")
+ elseif attribute == "Defense" then
+ new_base = 0.3 * being:modified_attribute("Vitality")
+ elseif attribute == "Dodge" then
-- Provisional
- new_base = being:modified_attribute(ATTR_AGI)
- elseif attribute == ATTR_MAGIC_DODGE then
+ new_base = being:modified_attribute("Agility")
+ elseif attribute == "M. dodge" then
-- TODO
new_base = 1
- elseif attribute == ATTR_MAGIC_DEFENSE then
+ elseif attribute == "M. defense" then
-- TODO
new_base = 0
- elseif attribute == ATTR_BONUS_ASPD then
+ elseif attribute == "Bonus att. speed" then
-- TODO
new_base = 0
- elseif attribute == ATTR_HP_REGEN then
- local hp_per_sec = being:modified_attribute(ATTR_VIT) * 0.05
+ elseif attribute == "HP regeneration" then
+ local hp_per_sec = being:modified_attribute("Vitality") * 0.05
new_base = hp_per_sec * TICKS_PER_HP_REGENERATION / 10
- elseif attribute == ATTR_HP then
- local hp = being:modified_attribute(ATTR_HP)
- local max_hp = being:modified_attribute(ATTR_MAX_HP)
+ elseif attribute == "HP" then
+ local hp = being:modified_attribute("HP")
+ local max_hp = being:modified_attribute("Max HP")
if hp > max_hp then
new_base = new_base - hp - max_hp
end
- elseif attribute == ATTR_MAX_HP then
- local vit = being:modified_attribute(ATTR_VIT)
+ elseif attribute == "Max HP" then
+ local vit = being:modified_attribute("Vitality")
new_base = (vit + 3) * (vit + 20) * 0.125
- elseif attribute == ATTR_MOVE_SPEED_TPS then
+ elseif attribute == "Movement speed" then
-- Provisional
- new_base = 3.0 + being:modified_attribute(ATTR_AGI) * 0.08
- elseif attribute == ATTR_INV_CAPACITY then
+ new_base = 3.0 + being:modified_attribute("Agility") * 0.08
+ elseif attribute == "Capacity" then
-- Provisional
- new_base = 2000 + being:modified_attribute(ATTR_STR) * 180
- elseif attribute == ATTR_ABILITY_COOLDOWN then
+ new_base = 2000 + being:modified_attribute("Strength") * 180
+ elseif attribute == "Global ability cooldown" then
-- Provisional
- new_base = 100 - being:modified_attribute(ATTR_WIL)
- elseif attribute == ATTR_LEVEL then
+ new_base = 100 - being:modified_attribute("Willpower")
+ elseif attribute == "Level" then
-- Provisional
- --new_base = 100 - 100 * math.pow(0.99999, being:base_attribute(ATTR_EXP))
- new_base = being:base_attribute(ATTR_EXP) / 20
+ --new_base = 100 - 100 * math.pow(0.99999, being:base_attribute("XP"))
+ new_base = being:base_attribute("XP") / 20
end
if new_base ~= old_base then
- being:set_base_attribute(attribute, new_base)
+ being:set_base_attribute(attribute_name, new_base)
end
end
local function update_derived_attributes(being, attribute)
- if attribute == ATTR_STR then
- recalculate_base_attribute(being, ATTR_INV_CAPACITY)
- elseif attribute == ATTR_AGI then
- recalculate_base_attribute(being, ATTR_DODGE)
- elseif attribute == ATTR_VIT then
- recalculate_base_attribute(being, ATTR_MAX_HP)
- recalculate_base_attribute(being, ATTR_HP_REGEN)
- recalculate_base_attribute(being, ATTR_DEFENSE)
- elseif attribute == ATTR_INT then
+ local attribute_name = attribute:name()
+ if attribute_name == "Strength" then
+ recalculate_base_attribute(being, "Capacity")
+ elseif attribute_name == "Agility" then
+ recalculate_base_attribute(being, "Dodge")
+ elseif attribute_name == "Vitality" then
+ recalculate_base_attribute(being, "Max HP")
+ recalculate_base_attribute(being, "HP regeneration")
+ recalculate_base_attribute(being, "Defense")
+ elseif attribute_name == "Intelligence" then
-- unimplemented
- elseif attribute == ATTR_WIL then
- recalculate_base_attribute(being, ATTR_ABILITY_COOLDOWN)
- elseif attribute == ATTR_EXP then
- recalculate_base_attribute(being, ATTR_LEVEL)
+ elseif attribute_name == "Willpower" then
+ recalculate_base_attribute(being, "Global ability cooldown")
+ elseif attribute_name == "XP" then
+ recalculate_base_attribute(being, "Level")
end
end
@@ -86,13 +84,13 @@ on_recalculate_base_attribute(recalculate_base_attribute)
on_update_derived_attribute(update_derived_attributes)
function Entity:level()
- return math.floor(self:base_attribute(ATTR_LEVEL))
+ return math.floor(self:base_attribute("Level"))
end
function Entity:give_experience(experience)
- local old_experience = self:base_attribute(ATTR_EXP)
+ local old_experience = self:base_attribute("XP")
local old_level = self:level()
- self:set_base_attribute(ATTR_EXP, old_experience + experience)
+ self:set_base_attribute("XP", old_experience + experience)
if self:level() > old_level then
self:say("LEVELUP!!! " .. self:level())
self:set_attribute_points(self:attribute_points() + 1)
@@ -128,7 +126,7 @@ local function monster_damaged(mob, source, damage)
receiver.total = receiver.total + damage
end
- if mob:base_attribute(ATTR_HP) == 0 then
+ if mob:base_attribute("HP") == 0 then
local mob_config = mobs_config[mob:name()]
local experience = mob_config.experience or 0
for char, damage in pairs(receiver.chars) do
diff --git a/example/scripts/damage.lua b/example/scripts/damage.lua
index 8ad014f4..0116fbec 100644
--- a/example/scripts/damage.lua
+++ b/example/scripts/damage.lua
@@ -14,7 +14,7 @@ end
-- base, delta, chance_to_hit
function Entity:damage(source, damage)
local hp_loss = math.random(damage.base, damage.base + damage.delta)
- local dodge = self:modified_attribute(ATTR_DODGE)
+ local dodge = self:modified_attribute("Dodge")
if dodge > 0 and math.random(dodge) > math.random(damage.chance_to_hit) or
damage.chance_to_hit == 0
@@ -22,7 +22,7 @@ function Entity:damage(source, damage)
hp_loss = 0 -- attack missed
self:say("HAHA MISSED")
else
- local defense = self:modified_attribute(ATTR_DEFENSE)
+ local defense = self:modified_attribute("Defense")
local randomness = hp_loss > 16 and math.random(hp_loss / 16) or 0
hp_loss = hp_loss * (1 - (0.0159375 * defense) / (1 + 0.017 * defense))
+ randomness
@@ -30,10 +30,10 @@ function Entity:damage(source, damage)
end
if hp_loss > 0 then
- local hp = self:base_attribute(ATTR_HP)
+ local hp = self:base_attribute("HP")
hp_loss = math.min(hp, hp_loss)
self:add_hit_taken(hp_loss)
- self:set_base_attribute(ATTR_HP, hp - hp_loss)
+ self:set_base_attribute("HP", hp - hp_loss)
self:say("I GOT DAMAGED " .. hp - hp_loss)
if self:type() == TYPE_MONSTER then
diff --git a/example/scripts/npcs/postman.lua b/example/scripts/npcs/postman.lua
index 46802283..2ad2e3ce 100644
--- a/example/scripts/npcs/postman.lua
+++ b/example/scripts/npcs/postman.lua
@@ -12,7 +12,7 @@
function post_talk(npc, ch)
say("Hello " .. ch:name())
- local strength = being_get_attribute(ch, ATTR_STRENGTH)
+ local strength = being_get_attribute(ch, "Strength"ENGTH)
say("You have " .. tostring(strength) .. " strength")
say("What would you like to do?")
local answer = ask("View Mail", "Send Mail", "Nothing")
diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp
index eed02b89..604fe2ea 100644
--- a/src/game-server/accountconnection.cpp
+++ b/src/game-server/accountconnection.cpp
@@ -464,7 +464,7 @@ void AccountConnection::updateCharacterPoints(int charId, int charPoints,
}
void AccountConnection::updateAttributes(int charId, int attrId, double base,
- double mod)
+ double mod)
{
++mSyncMessages;
mSyncBuffer->writeInt8(SYNC_CHARACTER_ATTRIBUTE);
diff --git a/src/game-server/attributemanager.cpp b/src/game-server/attributemanager.cpp
index 9ed76640..3eb36cb8 100644
--- a/src/game-server/attributemanager.cpp
+++ b/src/game-server/attributemanager.cpp
@@ -47,7 +47,7 @@ void AttributeManager::deinitialize()
mAttributeScopes[i].clear();
}
-const AttributeManager::AttributeInfo *AttributeManager::getAttributeInfo(
+AttributeManager::AttributeInfo *AttributeManager::getAttributeInfo(
int id) const
{
auto ret = mAttributeMap.find(id);
@@ -56,7 +56,7 @@ const AttributeManager::AttributeInfo *AttributeManager::getAttributeInfo(
return ret->second;
}
-const AttributeManager::AttributeInfo *AttributeManager::getAttributeInfo(
+AttributeManager::AttributeInfo *AttributeManager::getAttributeInfo(
const std::string &name) const
{
if (mAttributeNameMap.contains(name))
@@ -64,20 +64,12 @@ const AttributeManager::AttributeInfo *AttributeManager::getAttributeInfo(
return 0;
}
-const std::map<int, AttributeManager::AttributeInfo *>
+const std::set<AttributeManager::AttributeInfo *>
&AttributeManager::getAttributeScope(ScopeType type) const
{
return mAttributeScopes[type];
}
-bool AttributeManager::isAttributeDirectlyModifiable(int id) const
-{
- auto ret = mAttributeMap.find(id);
- if (ret == mAttributeMap.end())
- return false;
- return ret->second->modifiable;
-}
-
ModifierLocation AttributeManager::getLocation(const std::string &tag) const
{
if (mTagMap.find(tag) != mTagMap.end())
@@ -111,9 +103,16 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode)
return;
}
- AttributeInfo *attribute = new AttributeInfo;
+ std::string name = XML::getProperty(attributeNode, "name", std::string());
+ if (name.empty())
+ {
+ LOG_WARN("Attribute manager: attribute '" << id
+ << "' does not have a name! Skipping...");
+ return;
+ }
+
+ AttributeInfo *attribute = new AttributeInfo(id, name);
- attribute->id = id;
attribute->modifiers = std::vector<AttributeModifier>();
attribute->minimum = XML::getFloatProperty(attributeNode, "minimum",
std::numeric_limits<double>::min());
@@ -122,15 +121,6 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode)
attribute->modifiable = XML::getBoolProperty(attributeNode, "modifiable",
false);
- std::string name = XML::getProperty(attributeNode, "name", std::string());
- if (name.empty())
- {
- LOG_WARN("Attribute manager: attribute '" << id
- << "' does not have a name! Skipping...");
- delete attribute;
- return;
- }
-
const std::string scope = utils::toUpper(
XML::getProperty(attributeNode, "scope", std::string()));
@@ -138,21 +128,21 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode)
if (scope.find("CHARACTER") != std::string::npos)
{
- mAttributeScopes[CharacterScope][id] = attribute;
+ mAttributeScopes[CharacterScope].insert(attribute);
LOG_DEBUG("Attribute manager: attribute '" << id
<< "' added to default character scope.");
hasScope = true;
}
if (scope.find("MONSTER") != std::string::npos)
{
- mAttributeScopes[MonsterScope][id] = attribute;
+ mAttributeScopes[MonsterScope].insert(attribute);
LOG_DEBUG("Attribute manager: attribute '" << id
<< "' added to default monster scope.");
hasScope = true;
}
if (scope == "BEING")
{
- mAttributeScopes[BeingScope][id] = attribute;
+ mAttributeScopes[BeingScope].insert(attribute);
LOG_DEBUG("Attribute manager: attribute '" << id
<< "' added to default being scope.");
hasScope = true;
diff --git a/src/game-server/attributemanager.h b/src/game-server/attributemanager.h
index 2972cd77..c6782130 100644
--- a/src/game-server/attributemanager.h
+++ b/src/game-server/attributemanager.h
@@ -21,10 +21,11 @@
#ifndef ATTRIBUTEMANAGER_H
#define ATTRIBUTEMANAGER_H
+#include <limits>
#include <map>
-#include <vector>
+#include <set>
#include <string>
-#include <limits>
+#include <vector>
#include "utils/string.h"
#include "utils/xml.h"
@@ -91,14 +92,16 @@ class AttributeManager
{
public:
struct AttributeInfo {
- AttributeInfo():
- id(0),
+ AttributeInfo(int id, const std::string &name):
+ id(id),
+ name(name),
minimum(std::numeric_limits<double>::min()),
maximum(std::numeric_limits<double>::max()),
modifiable(false)
{}
int id;
+ std::string name;
/** The minimum and maximum permitted attribute values. */
double minimum;
@@ -123,12 +126,10 @@ class AttributeManager
void reload();
void deinitialize();
- const AttributeInfo *getAttributeInfo(int id) const;
- const AttributeInfo *getAttributeInfo(const std::string &name) const;
-
- const std::map<int, AttributeInfo *> &getAttributeScope(ScopeType) const;
+ AttributeInfo *getAttributeInfo(int id) const;
+ AttributeInfo *getAttributeInfo(const std::string &name) const;
- bool isAttributeDirectlyModifiable(int id) const;
+ const std::set<AttributeInfo *> &getAttributeScope(ScopeType) const;
ModifierLocation getLocation(const std::string &tag) const;
@@ -142,7 +143,7 @@ class AttributeManager
void readModifierNode(xmlNodePtr modifierNode, int attributeId,
AttributeInfo *info);
- std::map<int, AttributeInfo *> mAttributeScopes[MaxScope];
+ std::set<AttributeInfo *> mAttributeScopes[MaxScope];
std::map<int, AttributeInfo *> mAttributeMap;
utils::NameMap<AttributeInfo *> mAttributeNameMap;
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index 9b45608c..205a5778 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -49,18 +49,11 @@ BeingComponent::BeingComponent(Entity &entity):
auto &attributeScope = attributeManager->getAttributeScope(BeingScope);
LOG_DEBUG("Being creation: initialisation of " << attributeScope.size()
<< " attributes.");
- for (auto &attributeIt : attributeScope)
+ for (auto &attribute : attributeScope)
{
- if (mAttributes.count(attributeIt.first))
- {
- LOG_WARN("Redefinition of attribute '"
- << attributeIt.first << "'!");
- }
-
LOG_DEBUG("Attempting to create attribute '"
- << attributeIt.first << "'.");
- mAttributes.insert(std::make_pair(attributeIt.first,
- Attribute(attributeIt.second)));
+ << attribute->id << "'.");
+ mAttributes.insert(std::make_pair(attribute, Attribute(attribute)));
}
clearDestination(entity);
@@ -93,27 +86,30 @@ void BeingComponent::triggerEmote(Entity &entity, int id)
void BeingComponent::heal(Entity &entity)
{
- Attribute &hp = mAttributes.at(ATTR_HP);
- Attribute &maxHp = mAttributes.at(ATTR_MAX_HP);
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_HP);
+ Attribute &hp = mAttributes.at(hpAttribute);
+ Attribute &maxHp = mAttributes.at(attributeManager->getAttributeInfo(ATTR_MAX_HP));
if (maxHp.getModifiedAttribute() == hp.getModifiedAttribute())
return; // Full hp, do nothing.
// Reset all modifications present in hp.
hp.clearMods();
- setAttribute(entity, ATTR_HP, maxHp.getModifiedAttribute());
+ setAttribute(entity, hpAttribute, maxHp.getModifiedAttribute());
}
void BeingComponent::heal(Entity &entity, int gain)
{
- Attribute &hp = mAttributes.at(ATTR_HP);
- Attribute &maxHp = mAttributes.at(ATTR_MAX_HP);
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_HP);
+ auto *maxHpAttribute = attributeManager->getAttributeInfo(ATTR_MAX_HP);
+ Attribute &hp = mAttributes.at(hpAttribute);
+ Attribute &maxHp = mAttributes.at(maxHpAttribute);
if (maxHp.getModifiedAttribute() == hp.getModifiedAttribute())
return; // Full hp, do nothing.
// Cannot go over maximum hitpoints.
- setAttribute(entity, ATTR_HP, hp.getBase() + gain);
+ setAttribute(entity, hpAttribute, hp.getBase() + gain);
if (hp.getModifiedAttribute() > maxHp.getModifiedAttribute())
- setAttribute(entity, ATTR_HP, maxHp.getModifiedAttribute());
+ setAttribute(entity, hpAttribute, maxHp.getModifiedAttribute());
}
void BeingComponent::died(Entity &entity)
@@ -188,8 +184,8 @@ void BeingComponent::updateDirection(Entity &entity,
void BeingComponent::move(Entity &entity)
{
// Immobile beings cannot move.
- if (!checkAttributeExists(ATTR_MOVE_SPEED_RAW)
- || !getModifiedAttribute(ATTR_MOVE_SPEED_RAW))
+ if (!checkAttributeExists(attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_RAW))
+ || !getModifiedAttribute(attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_RAW)))
return;
// Remember the current position before moving. This is used by
@@ -271,10 +267,12 @@ void BeingComponent::move(Entity &entity)
{
Point next = mPath.front();
mPath.pop_front();
+
+ auto *rawSpeedAttribute = attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_RAW);
// SQRT2 is used for diagonal movement.
mMoveTime += (prev.x == next.x || prev.y == next.y) ?
- getModifiedAttribute(ATTR_MOVE_SPEED_RAW) :
- getModifiedAttribute(ATTR_MOVE_SPEED_RAW) * SQRT2;
+ getModifiedAttribute(rawSpeedAttribute) :
+ getModifiedAttribute(rawSpeedAttribute) * SQRT2;
if (mPath.empty())
{
@@ -319,20 +317,20 @@ void BeingComponent::setAction(Entity &entity, BeingAction action)
}
}
-void BeingComponent::applyModifier(Entity &entity, unsigned attr, double value,
- unsigned layer, unsigned duration,
- unsigned id)
+void BeingComponent::applyModifier(Entity &entity, AttributeManager::AttributeInfo *attribute,
+ double value, unsigned layer,
+ unsigned duration, unsigned id)
{
- mAttributes.at(attr).add(duration, value, layer, id);
- updateDerivedAttributes(entity, attr);
+ mAttributes.at(attribute).add(duration, value, layer, id);
+ updateDerivedAttributes(entity, attribute);
}
-bool BeingComponent::removeModifier(Entity &entity, unsigned attr,
+bool BeingComponent::removeModifier(Entity &entity, AttributeManager::AttributeInfo *attribute,
double value, unsigned layer,
unsigned id, bool fullcheck)
{
- bool ret = mAttributes.at(attr).remove(value, layer, id, fullcheck);
- updateDerivedAttributes(entity, attr);
+ bool ret = mAttributes.at(attribute).remove(value, layer, id, fullcheck);
+ updateDerivedAttributes(entity, attribute);
return ret;
}
@@ -341,87 +339,90 @@ void BeingComponent::setGender(BeingGender gender)
mGender = gender;
}
-void BeingComponent::setAttribute(Entity &entity, unsigned id, double value)
+void BeingComponent::setAttribute(Entity &entity,
+ AttributeManager::AttributeInfo *attribute,
+ double value)
{
- auto attributeIt = mAttributes.find(id);
+ auto attributeIt = mAttributes.find(attribute);
if (attributeIt == mAttributes.end())
{
/*
* The attribute does not yet exist, so we must attempt to create it.
*/
LOG_ERROR("Being: Attempt to access non-existing attribute '"
- << id << "'!");
+ << attribute->id << "'!");
LOG_WARN("Being: Creation of new attributes dynamically is not "
"implemented yet!");
}
else
{
attributeIt->second.setBase(value);
- updateDerivedAttributes(entity, id);
+ updateDerivedAttributes(entity, attribute);
}
}
-void BeingComponent::createAttribute(unsigned id,
- const AttributeManager::AttributeInfo *attributeInfo)
+void BeingComponent::createAttribute(AttributeManager::AttributeInfo *attributeInfo)
{
- mAttributes.insert(std::pair<unsigned, Attribute>
- (id, Attribute(attributeInfo)));
+ mAttributes.insert(std::pair<AttributeManager::AttributeInfo *, Attribute>
+ (attributeInfo, Attribute(attributeInfo)));
}
-const Attribute *BeingComponent::getAttribute(unsigned id) const
+const Attribute *BeingComponent::getAttribute(AttributeManager::AttributeInfo *attribute) const
{
- AttributeMap::const_iterator ret = mAttributes.find(id);
+ AttributeMap::const_iterator ret = mAttributes.find(attribute);
if (ret == mAttributes.end())
{
LOG_DEBUG("BeingComponent::getAttribute: Attribute "
- << id << " not found! Returning 0.");
+ << attribute->id << " not found! Returning 0.");
return 0;
}
return &ret->second;
}
-double BeingComponent::getAttributeBase(unsigned id) const
+double BeingComponent::getAttributeBase(AttributeManager::AttributeInfo *attribute) const
{
- AttributeMap::const_iterator ret = mAttributes.find(id);
+ AttributeMap::const_iterator ret = mAttributes.find(attribute);
if (ret == mAttributes.end())
{
LOG_DEBUG("BeingComponent::getAttributeBase: Attribute "
- << id << " not found! Returning 0.");
+ << attribute->id << " not found! Returning 0.");
return 0;
}
return ret->second.getBase();
}
-double BeingComponent::getModifiedAttribute(unsigned id) const
+double BeingComponent::getModifiedAttribute(AttributeManager::AttributeInfo *attribute) const
{
- AttributeMap::const_iterator ret = mAttributes.find(id);
+ AttributeMap::const_iterator ret = mAttributes.find(attribute);
if (ret == mAttributes.end())
{
LOG_DEBUG("BeingComponent::getModifiedAttribute: Attribute "
- << id << " not found! Returning 0.");
+ << attribute->id << " not found! Returning 0.");
return 0;
}
return ret->second.getModifiedAttribute();
}
-void BeingComponent::recalculateBaseAttribute(Entity &entity, unsigned attr)
+void BeingComponent::recalculateBaseAttribute(Entity &entity,
+ AttributeManager::AttributeInfo *attribute)
{
LOG_DEBUG("Being: Received update attribute recalculation request for "
- << attr << ".");
- if (!mAttributes.count(attr))
+ << attribute << ".");
+ if (!mAttributes.count(attribute))
{
- LOG_DEBUG("BeingComponent::recalculateBaseAttribute: " << attr << " not found!");
+ LOG_DEBUG("BeingComponent::recalculateBaseAttribute: " << attribute->id << " not found!");
return;
}
// Handle speed conversion inside the engine
- if (attr == ATTR_MOVE_SPEED_RAW)
+ if (attribute == attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_RAW))
{
+ auto *speedTpsAttribute = attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_TPS);
double newBase = utils::tpsToRawSpeed(
- getModifiedAttribute(ATTR_MOVE_SPEED_TPS));
- if (newBase != getAttributeBase(attr))
- setAttribute(entity, attr, newBase);
+ getModifiedAttribute(speedTpsAttribute));
+ if (newBase != getAttributeBase(attribute))
+ setAttribute(entity, attribute, newBase);
return;
}
@@ -431,18 +432,19 @@ void BeingComponent::recalculateBaseAttribute(Entity &entity, unsigned attr)
Script *script = ScriptManager::currentState();
script->prepare(mRecalculateBaseAttributeCallback);
script->push(&entity);
- script->push(attr);
+ script->push(attribute);
script->execute(entity.getMap());
}
-void BeingComponent::updateDerivedAttributes(Entity &entity, unsigned attr)
+void BeingComponent::updateDerivedAttributes(Entity &entity,
+ AttributeManager::AttributeInfo *attribute)
{
- signal_attribute_changed.emit(&entity, attr);
+ signal_attribute_changed.emit(&entity, attribute);
- LOG_DEBUG("Being: Updating derived attribute(s) of: " << attr);
+ LOG_DEBUG("Being: Updating derived attribute(s) of: " << attribute);
// Handle default actions before handing over to the script engine
- switch (attr)
+ switch (attribute->id)
{
case ATTR_MAX_HP:
case ATTR_HP:
@@ -452,7 +454,8 @@ void BeingComponent::updateDerivedAttributes(Entity &entity, unsigned attr)
case ATTR_MOVE_SPEED_TPS:
// Does not make a lot of sense to have in the scripts.
// So handle it here:
- recalculateBaseAttribute(entity, ATTR_MOVE_SPEED_RAW);
+ recalculateBaseAttribute(entity,
+ attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_RAW));
break;
}
@@ -462,7 +465,7 @@ void BeingComponent::updateDerivedAttributes(Entity &entity, unsigned attr)
Script *script = ScriptManager::currentState();
script->prepare(mRecalculateDerivedAttributesCallback);
script->push(&entity);
- script->push(attr);
+ script->push(attribute);
script->execute(entity.getMap());
}
@@ -514,15 +517,17 @@ void BeingComponent::setStatusEffectTime(int id, int time)
void BeingComponent::update(Entity &entity)
{
- int oldHP = getModifiedAttribute(ATTR_HP);
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_HP);
+
+ int oldHP = getModifiedAttribute(hpAttribute);
int newHP = oldHP;
- int maxHP = getModifiedAttribute(ATTR_MAX_HP);
+ int maxHP = getModifiedAttribute(attributeManager->getAttributeInfo(ATTR_MAX_HP));
// Regenerate HP
if (mAction != DEAD && mHealthRegenerationTimeout.expired())
{
mHealthRegenerationTimeout.set(TICKS_PER_HP_REGENERATION);
- newHP += getModifiedAttribute(ATTR_HP_REGEN);
+ newHP += getModifiedAttribute(attributeManager->getAttributeInfo(ATTR_HP_REGEN));
}
// Cap HP at maximum
if (newHP > maxHP)
@@ -532,7 +537,7 @@ void BeingComponent::update(Entity &entity)
// Only update HP when it actually changed to avoid network noise
if (newHP != oldHP)
{
- setAttribute(entity, ATTR_HP, newHP);
+ setAttribute(entity, hpAttribute, newHP);
entity.getComponent<ActorComponent>()->raiseUpdateFlags(
UPDATEFLAG_HEALTHCHANGE);
}
@@ -567,7 +572,7 @@ void BeingComponent::update(Entity &entity)
}
// Check if being died
- if (getModifiedAttribute(ATTR_HP) <= 0 && mAction != DEAD)
+ if (getModifiedAttribute(hpAttribute) <= 0 && mAction != DEAD)
died(entity);
}
diff --git a/src/game-server/being.h b/src/game-server/being.h
index f542e3ab..908def6d 100644
--- a/src/game-server/being.h
+++ b/src/game-server/being.h
@@ -29,6 +29,7 @@
#include "game-server/actor.h"
#include "game-server/attribute.h"
+#include "game-server/attributemanager.h"
#include "game-server/timeout.h"
#include "scripting/script.h"
@@ -37,7 +38,7 @@ class BeingComponent;
class MapComposite;
class StatusEffect;
-typedef std::map< unsigned, Attribute > AttributeMap;
+typedef std::map<AttributeManager::AttributeInfo *, Attribute> AttributeMap;
struct Status
{
@@ -143,7 +144,7 @@ class BeingComponent : public Component
/**
* Sets an attribute.
*/
- void setAttribute(Entity &entity, unsigned id, double value);
+ void setAttribute(Entity &entity, AttributeManager::AttributeInfo *, double value);
/**
* Creates an Attribute that did not exist before
@@ -151,13 +152,12 @@ class BeingComponent : public Component
* @param id The id of the attribute
* @param attributeInfo The info that describes the attribute
*/
- void createAttribute(unsigned id,
- const AttributeManager::AttributeInfo *attributeInfo);
+ void createAttribute(AttributeManager::AttributeInfo *);
/**
* Gets an attribute or 0 if not existing.
*/
- const Attribute *getAttribute(unsigned id) const;
+ const Attribute *getAttribute(AttributeManager::AttributeInfo *) const;
const AttributeMap &getAttributes() const
{ return mAttributes; }
@@ -165,20 +165,20 @@ class BeingComponent : public Component
/**
* Gets an attribute base.
*/
- double getAttributeBase(unsigned id) const;
+ double getAttributeBase(AttributeManager::AttributeInfo *) const;
/**
* Gets an attribute after applying modifiers.
*/
- double getModifiedAttribute(unsigned id) const;
+ double getModifiedAttribute(AttributeManager::AttributeInfo *) const;
/**
* Checks whether or not an attribute exists in this being.
* @returns True if the attribute is present in the being, false otherwise.
*/
- bool checkAttributeExists(unsigned id) const
- { return mAttributes.count(id); }
+ bool checkAttributeExists(AttributeManager::AttributeInfo *attribute) const
+ { return mAttributes.count(attribute); }
/**
* Adds a modifier to one attribute.
@@ -187,13 +187,13 @@ class BeingComponent : public Component
* @param lvl If non-zero, indicates that a temporary modifier can be
* dispelled prematuraly by a spell of given level.
*/
- void applyModifier(Entity &entity, unsigned attr, double value,
- unsigned layer, unsigned duration = 0,
- unsigned id = 0);
+ void applyModifier(Entity &entity, AttributeManager::AttributeInfo *,
+ double value, unsigned layer,
+ unsigned duration = 0, unsigned id = 0);
- bool removeModifier(Entity &entity, unsigned attr, double value,
- unsigned layer, unsigned id = 0,
- bool fullcheck = false);
+ bool removeModifier(Entity &entity, AttributeManager::AttributeInfo *,
+ double value, unsigned layer,
+ unsigned id = 0, bool fullcheck = false);
/**
* Called when an attribute modifier is changed.
@@ -201,14 +201,16 @@ class BeingComponent : public Component
* attributes if it has changed.
* @returns Whether it was changed.
*/
- void recalculateBaseAttribute(Entity &, unsigned);
+ void recalculateBaseAttribute(Entity &,
+ AttributeManager::AttributeInfo *);
/**
* Attribute has changed, recalculate base value of dependant
* attributes (and handle other actions for the modified
* attribute)
*/
- void updateDerivedAttributes(Entity &entity, unsigned);
+ void updateDerivedAttributes(Entity &entity,
+ AttributeManager::AttributeInfo *);
/**
* Sets a statuseffect on this being
@@ -258,7 +260,7 @@ class BeingComponent : public Component
{ script->assignCallback(mRecalculateBaseAttributeCallback); }
sigc::signal<void, Entity *> signal_died;
- sigc::signal<void, Entity *, unsigned> signal_attribute_changed;
+ sigc::signal<void, Entity *, AttributeManager::AttributeInfo *> signal_attribute_changed;
/**
* Activate an emote flag on the being.
diff --git a/src/game-server/buysell.cpp b/src/game-server/buysell.cpp
index cc209ccf..ecc8793c 100644
--- a/src/game-server/buysell.cpp
+++ b/src/game-server/buysell.cpp
@@ -30,8 +30,10 @@
#include <algorithm>
-BuySell::BuySell(Entity *c, bool sell):
- mCurrencyId(ATTR_GP), mChar(c), mSell(sell)
+BuySell::BuySell(Entity *c, bool sell)
+ : mCurrency(attributeManager->getAttributeInfo(ATTR_GP))
+ , mChar(c)
+ , mSell(sell)
{
c->getComponent<CharacterComponent>()->setBuySell(this);
}
@@ -167,17 +169,17 @@ void BuySell::perform(unsigned id, int amount)
{
amount -= inv.remove(id, amount);
const double currentMoney =
- beingComponent->getAttributeBase(mCurrencyId);
- beingComponent->setAttribute(*mChar, mCurrencyId,
+ beingComponent->getAttributeBase(mCurrency);
+ beingComponent->setAttribute(*mChar, mCurrency,
currentMoney + amount * i->cost);
}
else
{
const double currentMoney =
- beingComponent->getAttributeBase(mCurrencyId);
+ beingComponent->getAttributeBase(mCurrency);
amount = std::min(amount, ((int)currentMoney) / i->cost);
amount -= inv.insert(id, amount);
- beingComponent->setAttribute(*mChar, mCurrencyId,
+ beingComponent->setAttribute(*mChar, mCurrency,
currentMoney - amount * i->cost);
}
if (i->amount)
diff --git a/src/game-server/buysell.h b/src/game-server/buysell.h
index 0906aaf4..524bec9b 100644
--- a/src/game-server/buysell.h
+++ b/src/game-server/buysell.h
@@ -23,6 +23,8 @@
#include <vector>
+#include "game-server/attributemanager.h"
+
class Entity;
class BuySell
@@ -77,7 +79,7 @@ class BuySell
typedef std::vector< TradedItem > TradedItems;
/** The attribute ID of the currency to use. Hardcoded for now (FIXME) */
- unsigned mCurrencyId;
+ AttributeManager::AttributeInfo *mCurrency;
Entity *mChar; /**< Character involved. */
TradedItems mItems; /**< Traded items. */
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp
index a08b07ff..7e49f0ab 100644
--- a/src/game-server/character.cpp
+++ b/src/game-server/character.cpp
@@ -83,8 +83,8 @@ CharacterComponent::CharacterComponent(Entity &entity, MessageIn &msg):
auto &attributeScope = attributeManager->getAttributeScope(CharacterScope);
LOG_DEBUG("Character creation: initialisation of "
<< attributeScope.size() << " attributes.");
- for (auto &attributeIt : attributeScope)
- beingComponent->createAttribute(attributeIt.first, attributeIt.second);
+ for (auto &attribute : attributeScope)
+ beingComponent->createAttribute(attribute);
auto *actorComponent = entity.getComponent<ActorComponent>();
actorComponent->setWalkMask(Map::BLOCKMASK_WALL);
@@ -139,7 +139,8 @@ void CharacterComponent::deserialize(Entity &entity, MessageIn &msg)
{
unsigned id = msg.readInt16();
double base = msg.readDouble();
- beingComponent->setAttribute(entity, id, base);
+ auto *attributeInfo = attributeManager->getAttributeInfo(id);
+ beingComponent->setAttribute(entity, attributeInfo, base);
}
// status effects currently affecting the character
@@ -224,7 +225,7 @@ void CharacterComponent::serialize(Entity &entity, MessageOut &msg)
msg.writeInt16(attributes.size());
for (auto attributeIt : attributes)
{
- msg.writeInt16(attributeIt.first);
+ msg.writeInt16(attributeIt.first->id);
msg.writeDouble(attributeIt.second.getBase());
msg.writeDouble(attributeIt.second.getModifiedAttribute());
}
@@ -321,8 +322,11 @@ void CharacterComponent::respawn(Entity &entity)
return;
// No script respawn callback set - fall back to hardcoded logic
- const double maxHp = beingComponent->getModifiedAttribute(ATTR_MAX_HP);
- beingComponent->setAttribute(entity, ATTR_HP, maxHp);
+ const double maxHp = beingComponent->getModifiedAttribute(
+ attributeManager->getAttributeInfo(ATTR_MAX_HP));
+ beingComponent->setAttribute(entity,
+ attributeManager->getAttributeInfo(ATTR_HP),
+ maxHp);
// Warp back to spawn point.
int spawnMap = Configuration::getValue("char_respawnMap", 1);
int spawnX = Configuration::getValue("char_respawnX", 1024);
@@ -442,13 +446,11 @@ void CharacterComponent::sendStatus(Entity &entity)
{
auto *beingComponent = entity.getComponent<BeingComponent>();
MessageOut attribMsg(GPMSG_PLAYER_ATTRIBUTE_CHANGE);
- for (std::set<size_t>::const_iterator i = mModifiedAttributes.begin(),
- i_end = mModifiedAttributes.end(); i != i_end; ++i)
+ for (AttributeManager::AttributeInfo *attribute : mModifiedAttributes)
{
- int attr = *i;
- attribMsg.writeInt16(attr);
- attribMsg.writeInt32(beingComponent->getAttributeBase(attr) * 256);
- attribMsg.writeInt32(beingComponent->getModifiedAttribute(attr) * 256);
+ attribMsg.writeInt16(attribute->id);
+ attribMsg.writeInt32(beingComponent->getAttributeBase(attribute) * 256);
+ attribMsg.writeInt32(beingComponent->getModifiedAttribute(attribute) * 256);
}
if (attribMsg.getLength() > 2) gameHandler->sendTo(mClient, attribMsg);
mModifiedAttributes.clear();
@@ -466,15 +468,16 @@ void CharacterComponent::modifiedAllAttributes(Entity &entity)
}
}
-void CharacterComponent::attributeChanged(Entity *entity, unsigned attr)
+void CharacterComponent::attributeChanged(Entity *entity,
+ AttributeManager::AttributeInfo *attribute)
{
auto *beingComponent = entity->getComponent<BeingComponent>();
// Inform the client of this attribute modification.
- accountHandler->updateAttributes(getDatabaseID(), attr,
- beingComponent->getAttributeBase(attr),
- beingComponent->getModifiedAttribute(attr));
- mModifiedAttributes.insert(attr);
+ accountHandler->updateAttributes(getDatabaseID(), attribute->id,
+ beingComponent->getAttributeBase(attribute),
+ beingComponent->getModifiedAttribute(attribute));
+ mModifiedAttributes.insert(attribute);
}
void CharacterComponent::incrementKillCount(int monsterType)
@@ -501,11 +504,11 @@ int CharacterComponent::getKillCount(int monsterType) const
}
AttribmodResponseCode CharacterComponent::useCharacterPoint(Entity &entity,
- int attribute)
+ AttributeManager::AttributeInfo *attribute)
{
auto *beingComponent = entity.getComponent<BeingComponent>();
- if (!attributeManager->isAttributeDirectlyModifiable(attribute))
+ if (!attribute->modifiable)
return ATTRIBMOD_INVALID_ATTRIBUTE;
if (!mAttributePoints)
return ATTRIBMOD_NO_POINTS_LEFT;
@@ -519,11 +522,11 @@ AttribmodResponseCode CharacterComponent::useCharacterPoint(Entity &entity,
}
AttribmodResponseCode CharacterComponent::useCorrectionPoint(Entity &entity,
- int attribute)
+ AttributeManager::AttributeInfo *attribute)
{
auto *beingComponent = entity.getComponent<BeingComponent>();
- if (!attributeManager->isAttributeDirectlyModifiable(attribute))
+ if (!attribute->modifiable)
return ATTRIBMOD_INVALID_ATTRIBUTE;
if (!mCorrectionPoints)
return ATTRIBMOD_NO_POINTS_LEFT;
diff --git a/src/game-server/character.h b/src/game-server/character.h
index 799b0817..a4f881d8 100644
--- a/src/game-server/character.h
+++ b/src/game-server/character.h
@@ -178,7 +178,7 @@ class CharacterComponent : public Component
* @param being th being of which the attribute was changed
* @param attributeId the changed id
*/
- void attributeChanged(Entity *being, unsigned attributeId);
+ void attributeChanged(Entity *being, AttributeManager::AttributeInfo *);
/**
* Calls all the "disconnected" listener.
@@ -221,14 +221,14 @@ class CharacterComponent : public Component
* basic attribute
*/
AttribmodResponseCode useCharacterPoint(Entity &entity,
- int attribute);
+ AttributeManager::AttributeInfo *);
/**
* Tries to use a correction point to reduce a
* basic attribute and regain a character point
*/
AttribmodResponseCode useCorrectionPoint(Entity &entity,
- int attribute);
+ AttributeManager::AttributeInfo *);
void setAttributePoints(int points);
int getAttributePoints() const;
@@ -320,7 +320,7 @@ class CharacterComponent : public Component
Possessions mPossessions; /**< Possesssions of the character. */
/** Attributes modified since last update. */
- std::set<size_t> mModifiedAttributes;
+ std::set<AttributeManager::AttributeInfo *> mModifiedAttributes;
std::set<unsigned> mModifiedAbilities;
diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp
index 4c2adad3..ca08a636 100644
--- a/src/game-server/commandhandler.cpp
+++ b/src/game-server/commandhandler.cpp
@@ -671,9 +671,11 @@ static void handleMoney(Entity *player, std::string &args)
auto *beingComponent = other->getComponent<BeingComponent>();
+ auto *moneyAttribute = attributeManager->getAttributeInfo(ATTR_GP);
+
// change how much money the player has
- const double previousMoney = beingComponent->getAttributeBase(ATTR_GP);
- beingComponent->setAttribute(*player, ATTR_GP , previousMoney + value);
+ const double previousMoney = beingComponent->getAttributeBase(moneyAttribute);
+ beingComponent->setAttribute(*player, moneyAttribute , previousMoney + value);
// log transaction
std::string msg = "User created " + valuestr + " money";
@@ -1065,7 +1067,6 @@ static void handleTakePermission(Entity *player, std::string &args)
static void handleAttribute(Entity *player, std::string &args)
{
Entity *other;
- int attr, value;
// get arguments
std::string character = getArgument(args);
@@ -1104,16 +1105,16 @@ static void handleAttribute(Entity *player, std::string &args)
}
// put the attribute into an integer
- attr = utils::stringToInt(attrstr);
+ int attributeId = utils::stringToInt(attrstr);
- if (attr < 0)
+ if (attributeId < 0)
{
say("Invalid Attribute", player);
return;
}
// put the value into an integer
- value = utils::stringToInt(valuestr);
+ int value = utils::stringToInt(valuestr);
if (value < 0)
{
@@ -1123,12 +1124,14 @@ static void handleAttribute(Entity *player, std::string &args)
auto *beingComponent = other->getComponent<BeingComponent>();
+ auto *attribute = attributeManager->getAttributeInfo(attributeId);
+
// change the player's attribute
- beingComponent->setAttribute(*other, attr, value);
+ beingComponent->setAttribute(*other, attribute, value);
// log transaction
std::stringstream msg;
- msg << "User changed attribute " << attr << " of player "
+ msg << "User changed attribute " << attribute->id << " of player "
<< beingComponent->getName()
<< " to " << value;
int databaseId =
@@ -1264,7 +1267,8 @@ static void handleMute(Entity *player, std::string &args)
static void handleDie(Entity *player, std::string &)
{
- player->getComponent<BeingComponent>()->setAttribute(*player, ATTR_HP, 0);
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_HP);
+ player->getComponent<BeingComponent>()->setAttribute(*player, hpAttribute, 0);
say("You've killed yourself.", player);
}
@@ -1284,7 +1288,8 @@ static void handleKill(Entity *player, std::string &args)
}
// kill the player
- other->getComponent<BeingComponent>()->setAttribute(*player, ATTR_HP, 0);
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_HP);
+ other->getComponent<BeingComponent>()->setAttribute(*player, hpAttribute, 0);
// feedback
std::stringstream targetMsg;
diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp
index c7ff655a..e1f58967 100644
--- a/src/game-server/gamehandler.cpp
+++ b/src/game-server/gamehandler.cpp
@@ -876,14 +876,15 @@ void GameHandler::handleRaiseAttribute(GameClient &client, MessageIn &message)
auto *characterComponent =
client.character->getComponent<CharacterComponent>();
- const int attribute = message.readInt16();
+ const int attributeId = message.readInt16();
+ auto *attribute = attributeManager->getAttributeInfo(attributeId);
AttribmodResponseCode retCode;
retCode = characterComponent->useCharacterPoint(*client.character,
attribute);
MessageOut result(GPMSG_RAISE_ATTRIBUTE_RESPONSE);
result.writeInt8(retCode);
- result.writeInt16(attribute);
+ result.writeInt16(attributeId);
client.send(result);
if (retCode == ATTRIBMOD_OK)
@@ -906,14 +907,15 @@ void GameHandler::handleLowerAttribute(GameClient &client, MessageIn &message)
auto *characterComponent =
client.character->getComponent<CharacterComponent>();
- const int attribute = message.readInt32();
+ const int attributeId = message.readInt32();
+ auto *attribute = attributeManager->getAttributeInfo(attributeId);
AttribmodResponseCode retCode;
retCode = characterComponent->useCorrectionPoint(*client.character,
attribute);
MessageOut result(GPMSG_LOWER_ATTRIBUTE_RESPONSE);
result.writeInt8(retCode);
- result.writeInt16(attribute);
+ result.writeInt16(attributeId);
client.send(result);
if (retCode == ATTRIBMOD_OK)
diff --git a/src/game-server/item.cpp b/src/game-server/item.cpp
index 589fc011..5e5ca3d9 100644
--- a/src/game-server/item.cpp
+++ b/src/game-server/item.cpp
@@ -35,9 +35,11 @@ bool ItemEffectAttrMod::apply(Entity *itemUser)
{
LOG_DEBUG("Applying modifier.");
itemUser->getComponent<BeingComponent>()->applyModifier(*itemUser,
- mAttributeId, mMod,
+ mAttribute,
+ mMod,
mAttributeLayer,
- mDuration, mId);
+ mDuration,
+ mModId);
return false;
}
@@ -45,10 +47,11 @@ void ItemEffectAttrMod::dispell(Entity *itemUser)
{
LOG_DEBUG("Dispelling modifier.");
itemUser->getComponent<BeingComponent>()->removeModifier(*itemUser,
- mAttributeId,
+ mAttribute,
mMod,
mAttributeLayer,
- mId, !mDuration);
+ mModId,
+ !mDuration);
}
ItemEffectScript::~ItemEffectScript()
diff --git a/src/game-server/item.h b/src/game-server/item.h
index e627b42b..8f7b114a 100644
--- a/src/game-server/item.h
+++ b/src/game-server/item.h
@@ -110,21 +110,25 @@ class ItemEffectInfo
class ItemEffectAttrMod : public ItemEffectInfo
{
public:
- ItemEffectAttrMod(unsigned attrId, unsigned layer, double value,
- unsigned id, unsigned duration = 0) :
- mAttributeId(attrId), mAttributeLayer(layer),
- mMod(value), mDuration(duration), mId(id)
+ ItemEffectAttrMod(AttributeManager::AttributeInfo *attribute,
+ unsigned layer, double value, unsigned modId,
+ unsigned duration = 0)
+ : mAttribute(attribute)
+ , mAttributeLayer(layer)
+ , mMod(value)
+ , mDuration(duration)
+ , mModId(modId)
{}
bool apply(Entity *itemUser);
void dispell(Entity *itemUser);
private:
- unsigned mAttributeId;
+ AttributeManager::AttributeInfo *mAttribute;
unsigned mAttributeLayer;
double mMod;
unsigned mDuration;
- unsigned mId;
+ unsigned mModId;
};
class ItemEffectConsumes : public ItemEffectInfo
diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp
index bcb64072..1ca61a65 100644
--- a/src/game-server/itemmanager.cpp
+++ b/src/game-server/itemmanager.cpp
@@ -338,7 +338,9 @@ void ItemManager::readEffectNode(xmlNodePtr effectNode, ItemClass *item)
0);
ModifierLocation location = attributeManager->getLocation(tag);
double value = XML::getFloatProperty(subNode, "value", 0.0);
- item->addEffect(new ItemEffectAttrMod(location.attributeId,
+
+ auto *attribute = attributeManager->getAttributeInfo(location.attributeId);
+ item->addEffect(new ItemEffectAttrMod(attribute,
location.layer,
value,
item->getDatabaseID(),
diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp
index 41a69ecb..cf589977 100644
--- a/src/game-server/monster.cpp
+++ b/src/game-server/monster.cpp
@@ -51,9 +51,9 @@ MonsterComponent::MonsterComponent(Entity &entity, MonsterClass *specy):
*/
auto *beingComponent = entity.getComponent<BeingComponent>();
- for (auto attrInfo : attributeManager->getAttributeScope(MonsterScope))
+ for (auto attribute : attributeManager->getAttributeScope(MonsterScope))
{
- beingComponent->createAttribute(attrInfo.first, attrInfo.second);
+ beingComponent->createAttribute(attribute);
}
/*
@@ -63,15 +63,15 @@ MonsterComponent::MonsterComponent(Entity &entity, MonsterClass *specy):
int mutation = specy->getMutation();
- for (auto &attribute : specy->getAttributes())
+ for (auto &attributeIt : specy->getAttributes())
{
- double attributeValue = attribute.second;
+ double attributeValue = attributeIt.second;
if (mutation != 0)
{
double factor = 100 + (rand() % (mutation * 2)) - mutation;
attributeValue = attributeValue * factor / 100.0;
}
- beingComponent->setAttribute(entity, attribute.first->id,
+ beingComponent->setAttribute(entity, attributeIt.first,
attributeValue);
}
diff --git a/src/game-server/monster.h b/src/game-server/monster.h
index e50f7451..ff534f58 100644
--- a/src/game-server/monster.h
+++ b/src/game-server/monster.h
@@ -105,10 +105,9 @@ class MonsterClass
/**
* Sets a being base attribute.
*/
- void setAttribute(const AttributeManager::AttributeInfo *attribute,
- double value);
+ void setAttribute(AttributeManager::AttributeInfo *attribute, double value);
- const std::map<const AttributeManager::AttributeInfo *, double>
+ const std::map<AttributeManager::AttributeInfo *, double>
&getAttributes() const;
/** Sets collision circle radius. */
@@ -138,7 +137,7 @@ class MonsterClass
BeingGender mGender;
MonsterDrops mDrops;
- std::map<const AttributeManager::AttributeInfo *, double> mAttributes;
+ std::map<AttributeManager::AttributeInfo *, double> mAttributes;
std::set<AbilityManager::AbilityInfo *> mAbilities;
float mSpeed; /**< The monster class speed in tiles per second */
int mSize;
@@ -190,13 +189,12 @@ class MonsterComponent : public Component
Timeout mDecayTimeout;
};
-inline void MonsterClass::setAttribute(
- const AttributeManager::AttributeInfo *attribute, double value)
+inline void MonsterClass::setAttribute(AttributeManager::AttributeInfo *attribute, double value)
{
mAttributes[attribute] = value;
}
-inline const std::map<const AttributeManager::AttributeInfo *, double>
+inline const std::map<AttributeManager::AttributeInfo *, double>
&MonsterClass::getAttributes() const
{
return mAttributes;
diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp
index 327c5c10..1802a022 100644
--- a/src/game-server/monstermanager.cpp
+++ b/src/game-server/monstermanager.cpp
@@ -166,7 +166,7 @@ void MonsterManager::readMonsterNode(xmlNodePtr node, const std::string &filenam
{
std::string attributeIdString = XML::getProperty(subnode, "id",
std::string());
- const AttributeManager::AttributeInfo *info;
+ AttributeManager::AttributeInfo *info = nullptr;
if (utils::isNumeric(attributeIdString))
{
const int attributeId = utils::stringToInt(attributeIdString);
diff --git a/src/game-server/spawnareacomponent.cpp b/src/game-server/spawnareacomponent.cpp
index 33bd5acd..da715f4f 100644
--- a/src/game-server/spawnareacomponent.cpp
+++ b/src/game-server/spawnareacomponent.cpp
@@ -71,7 +71,8 @@ void SpawnAreaComponent::update(Entity &entity)
being->addComponent(beingComponent);
being->addComponent(new MonsterComponent(*being, mSpecy));
- if (beingComponent->getModifiedAttribute(ATTR_MAX_HP) <= 0)
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_MAX_HP);
+ if (beingComponent->getModifiedAttribute(hpAttribute) <= 0)
{
LOG_WARN("Refusing to spawn dead monster " << mSpecy->getId());
delete being;
diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp
index d2aaff4e..9fab3431 100644
--- a/src/game-server/state.cpp
+++ b/src/game-server/state.cpp
@@ -342,9 +342,10 @@ static void informPlayer(MapComposite *map, Entity *p)
// We multiply the sent speed (in tiles per second) by ten
// to get it within a byte with decimal precision.
// For instance, a value of 4.5 will be sent as 45.
+ auto *tpsSpeedAttribute = attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_TPS);
moveMsg.writeInt8((unsigned short)
(o->getComponent<BeingComponent>()
- ->getModifiedAttribute(ATTR_MOVE_SPEED_TPS) * 10));
+ ->getModifiedAttribute(tpsSpeedAttribute) * 10));
}
}
@@ -379,10 +380,12 @@ static void informPlayer(MapComposite *map, Entity *p)
MessageOut healthMsg(GPMSG_BEING_HEALTH_CHANGE);
healthMsg.writeInt16(
c->getComponent<ActorComponent>()->getPublicID());
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_HP);
healthMsg.writeInt16(
- beingComponent->getModifiedAttribute(ATTR_HP));
+ beingComponent->getModifiedAttribute(hpAttribute));
+ auto *maxHpAttribute = attributeManager->getAttributeInfo(ATTR_MAX_HP);
healthMsg.writeInt16(
- beingComponent->getModifiedAttribute(ATTR_MAX_HP));
+ beingComponent->getModifiedAttribute(maxHpAttribute));
gameHandler->sendTo(p, healthMsg);
}
}
diff --git a/src/game-server/trade.cpp b/src/game-server/trade.cpp
index 3fbcd0e6..b30eaf79 100644
--- a/src/game-server/trade.cpp
+++ b/src/game-server/trade.cpp
@@ -37,8 +37,13 @@
* TRADE_AGREE_WAIT : One player has agreed, waiting for the other one
*/
-Trade::Trade(Entity *c1, Entity *c2):
- mChar1(c1), mChar2(c2), mMoney1(0), mMoney2(0), mState(TRADE_INIT), mCurrencyId(ATTR_GP)
+Trade::Trade(Entity *c1, Entity *c2)
+ : mChar1(c1)
+ , mChar2(c2)
+ , mMoney1(0)
+ , mMoney2(0)
+ , mState(TRADE_INIT)
+ , mCurrencyAttribute(attributeManager->getAttributeInfo(ATTR_GP))
{
MessageOut msg(GPMSG_TRADE_REQUEST);
msg.writeInt16(c1->getComponent<ActorComponent>()->getPublicID());
@@ -134,9 +139,9 @@ void Trade::agree(Entity *c)
Inventory v1(mChar1), v2(mChar2);
const double moneyChar1 = mChar1->getComponent<BeingComponent>()
- ->getAttributeBase(mCurrencyId);
+ ->getAttributeBase(mCurrencyAttribute);
const double moneyChar2 = mChar2->getComponent<BeingComponent>()
- ->getAttributeBase(mCurrencyId);
+ ->getAttributeBase(mCurrencyAttribute);
if (moneyChar1 >= mMoney1 - mMoney2 &&
moneyChar2 >= mMoney2 - mMoney1 &&
@@ -144,10 +149,10 @@ void Trade::agree(Entity *c)
perform(mItems2, v2, v1))
{
mChar1->getComponent<BeingComponent>()
- ->setAttribute(*mChar1, mCurrencyId,
+ ->setAttribute(*mChar1, mCurrencyAttribute,
moneyChar1 - mMoney1 + mMoney2);
mChar2->getComponent<BeingComponent>()
- ->setAttribute(*mChar2, mCurrencyId,
+ ->setAttribute(*mChar2, mCurrencyAttribute,
moneyChar2 - mMoney2 + mMoney1);
}
else
diff --git a/src/game-server/trade.h b/src/game-server/trade.h
index 72ec0b3d..f9009113 100644
--- a/src/game-server/trade.h
+++ b/src/game-server/trade.h
@@ -23,6 +23,8 @@
#include <vector>
+#include "game-server/attributemanager.h"
+
class Entity;
class Inventory;
@@ -102,7 +104,7 @@ class Trade
TradedItems mItems1, mItems2; /**< Traded items. */
int mMoney1, mMoney2; /**< Traded money. */
TradeState mState; /**< State of transaction. */
- unsigned mCurrencyId; /**< The attribute to use as currency. */
+ AttributeManager::AttributeInfo *mCurrencyAttribute;
};
#endif
diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp
index c151b9fa..0193d888 100644
--- a/src/scripting/lua.cpp
+++ b/src/scripting/lua.cpp
@@ -289,8 +289,10 @@ static int npc_create(lua_State *s)
npc->addComponent(beingComponent);
npc->addComponent(npcComponent);
// some health so it doesn't spawn dead
- beingComponent->setAttribute(*npc, ATTR_MAX_HP, 100);
- beingComponent->setAttribute(*npc, ATTR_HP, 100);
+ auto *maxHpAttribute = attributeManager->getAttributeInfo(ATTR_MAX_HP);
+ beingComponent->setAttribute(*npc, maxHpAttribute, 100);
+ auto *hpAttribute = attributeManager->getAttributeInfo(ATTR_HP);
+ beingComponent->setAttribute(*npc, hpAttribute, 100);
beingComponent->setName(name);
beingComponent->setGender(getGender(gender));
@@ -1367,11 +1369,8 @@ static int entity_walk(lua_State *s)
if (lua_gettop(s) >= 4)
{
const double speedTps = luaL_checknumber(s, 4);
- beingComponent->setAttribute(*being, ATTR_MOVE_SPEED_TPS, speedTps);
- const double modifiedSpeedTps =
- beingComponent->getModifiedAttribute(ATTR_MOVE_SPEED_TPS);
- beingComponent->setAttribute(*being, ATTR_MOVE_SPEED_RAW,
- utils::tpsToRawSpeed(modifiedSpeedTps));
+ auto *tpsSpeedAttribute = attributeManager->getAttributeInfo(ATTR_MOVE_SPEED_TPS);
+ beingComponent->setAttribute(*being, tpsSpeedAttribute, speedTps);
}
return 0;
@@ -1724,10 +1723,9 @@ static int entity_get_y(lua_State *s)
static int entity_get_base_attribute(lua_State *s)
{
Entity *being = checkBeing(s, 1);
- int attr = checkAttribute(s, 2)->id;
- luaL_argcheck(s, attr > 0, 2, "invalid attribute id");
+ auto *attribute = checkAttribute(s, 2);
- lua_pushinteger(s, being->getComponent<BeingComponent>()->getAttributeBase(attr));
+ lua_pushinteger(s, being->getComponent<BeingComponent>()->getAttributeBase(attribute));
return 1;
}
@@ -1742,10 +1740,10 @@ static int entity_get_base_attribute(lua_State *s)
static int entity_set_base_attribute(lua_State *s)
{
Entity *being = checkBeing(s, 1);
- int attr = checkAttribute(s, 2)->id;
+ auto *attribute = checkAttribute(s, 2);
double value = luaL_checknumber(s, 3);
- being->getComponent<BeingComponent>()->setAttribute(*being, attr, value);
+ being->getComponent<BeingComponent>()->setAttribute(*being, attribute, value);
return 0;
}
@@ -1772,11 +1770,10 @@ static int entity_set_base_attribute(lua_State *s)
static int entity_get_modified_attribute(lua_State *s)
{
Entity *being = checkBeing(s, 1);
- int attr = checkAttribute(s, 2)->id;
- luaL_argcheck(s, attr > 0, 2, "invalid attribute id");
+ auto *attribute = checkAttribute(s, 2);
const double value =
- being->getComponent<BeingComponent>()->getModifiedAttribute(attr);
+ being->getComponent<BeingComponent>()->getModifiedAttribute(attribute);
lua_pushinteger(s, value);
return 1;
}
@@ -1802,15 +1799,15 @@ static int entity_get_modified_attribute(lua_State *s)
static int entity_apply_attribute_modifier(lua_State *s)
{
Entity *being = checkBeing(s, 1);
- int attr = checkAttribute(s, 2)->id;
+ auto *attribute = checkAttribute(s, 2);
double value = luaL_checknumber(s, 3);
int layer = luaL_checkint(s, 4);
int duration = luaL_optint(s, 5, 0);
int effectId = luaL_optint(s, 6, 0);
- being->getComponent<BeingComponent>()->applyModifier(*being, attr, value,
- layer, duration,
- effectId);
+ being->getComponent<BeingComponent>()->applyModifier(*being, attribute,
+ value, layer,
+ duration, effectId);
return 0;
}
@@ -1825,13 +1822,14 @@ static int entity_apply_attribute_modifier(lua_State *s)
static int entity_remove_attribute_modifier(lua_State *s)
{
Entity *being = checkBeing(s, 1);
- int attr = checkAttribute(s, 2)->id;
+ auto *attribute = checkAttribute(s, 2);
double value = luaL_checknumber(s, 3);
int layer = luaL_checkint(s, 4);
int effectId = luaL_optint(s, 5, 0);
- being->getComponent<BeingComponent>()->removeModifier(*being, attr, value,
- layer, effectId);
+ being->getComponent<BeingComponent>()->removeModifier(*being, attribute,
+ value, layer,
+ effectId);
return 0;
}
@@ -2910,6 +2908,47 @@ static int abilityinfo_on_recharged(lua_State *s)
}
+/** LUA_CATEGORY AttributeInfo class (attributeinfoclass)
+ */
+
+/** LUA get_attribute_info (attributeinfoclass)
+ * local attributeinfo = get_attribute_info(string name)
+ * local attributeinfo = get_attribute_info(int id)
+ **
+ * **Return value:** The attribute info of the passed attribute.
+ */
+static int get_attribute_info(lua_State *s)
+{
+ auto *attributeInfo = checkAttribute(s, 1);
+ LuaAttributeInfo::push(s, attributeInfo);
+ return 1;
+}
+
+/** LUA attributeinfo:name (attributeinfoclass)
+ * local id = attributeinfo:id()
+ **
+ * **Return value:** The id of the `attributeinfo`.
+ */
+static int attributeinfo_get_id(lua_State *s)
+{
+ auto *attributeInfo = LuaAttributeInfo::check(s, 1);
+ lua_pushinteger(s, attributeInfo->id);
+ return 1;
+}
+
+/** LUA attributeinfo:name (attributeinfoclass)
+ * local name = attributeinfo:name()
+ **
+ * **Return value:** The name of the `attributeinfo`.
+ */
+static int attributeinfo_get_name(lua_State *s)
+{
+ auto *attributeInfo = LuaAttributeInfo::check(s, 1);
+ lua_pushstring(s, attributeInfo->name.c_str());
+ return 1;
+}
+
+
/** LUA_CATEGORY Status effect class (statuseffectclass)
*/
@@ -3317,6 +3356,7 @@ LuaScript::LuaScript():
{ "map_get_objects", map_get_objects },
{ "announce", announce },
{ "get_ability_info", get_ability_info },
+ { "get_attribute_info", get_attribute_info },
{ nullptr, nullptr }
};
#if LUA_VERSION_NUM < 502
@@ -3428,12 +3468,19 @@ LuaScript::LuaScript():
{ nullptr, nullptr}
};
+ static luaL_Reg const members_AttributeInfo[] = {
+ { "id", attributeinfo_get_id },
+ { "name", attributeinfo_get_name },
+ { nullptr, nullptr}
+ };
+
LuaEntity::registerType(mRootState, "Entity", members_Entity);
LuaItemClass::registerType(mRootState, "ItemClass", members_ItemClass);
LuaMapObject::registerType(mRootState, "MapObject", members_MapObject);
LuaMonsterClass::registerType(mRootState, "MonsterClass", members_MonsterClass);
LuaStatusEffect::registerType(mRootState, "StatusEffect", members_StatusEffect);
LuaAbilityInfo::registerType(mRootState, "AbilityInfo", members_AbilityInfo);
+ LuaAttributeInfo::registerType(mRootState, "AttributeInfo", members_AttributeInfo);
// Make script object available to callback functions.
lua_pushlightuserdata(mRootState, const_cast<char *>(&registryKey));
diff --git a/src/scripting/luascript.cpp b/src/scripting/luascript.cpp
index 1617f74c..5ce55d13 100644
--- a/src/scripting/luascript.cpp
+++ b/src/scripting/luascript.cpp
@@ -113,6 +113,13 @@ void LuaScript::push(const std::list<InventoryItem> &itemList)
++nbArgs;
}
+void LuaScript::push(AttributeManager::AttributeInfo *attributeInfo)
+{
+ assert(nbArgs >= 0);
+ ::push(mCurrentState, attributeInfo);
+ ++nbArgs;
+}
+
int LuaScript::execute(const Context &context)
{
assert(nbArgs >= 0);
diff --git a/src/scripting/luascript.h b/src/scripting/luascript.h
index b874976a..a30cbf08 100644
--- a/src/scripting/luascript.h
+++ b/src/scripting/luascript.h
@@ -54,12 +54,10 @@ class LuaScript : public Script
void prepareResume(Thread *thread);
void push(int);
-
void push(const std::string &);
-
void push(Entity *);
-
void push(const std::list<InventoryItem> &itemList);
+ void push(AttributeManager::AttributeInfo *);
int execute(const Context &context = Context());
diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp
index c9738694..5a0cf883 100644
--- a/src/scripting/luautil.cpp
+++ b/src/scripting/luautil.cpp
@@ -226,13 +226,22 @@ AbilityManager::AbilityInfo *checkAbility(lua_State *s, int p)
return abilityInfo;
}
-const AttributeManager::AttributeInfo *checkAttribute(lua_State *s, int p)
+AttributeManager::AttributeInfo *checkAttribute(lua_State *s, int p)
{
- const AttributeManager::AttributeInfo *attributeInfo;
- if (lua_isnumber(s, p))
+ AttributeManager::AttributeInfo *attributeInfo;
+
+ switch (lua_type(s, p))
+ {
+ case LUA_TNUMBER:
attributeInfo = attributeManager->getAttributeInfo(luaL_checkint(s, p));
- else
+ break;
+ case LUA_TSTRING:
attributeInfo = attributeManager->getAttributeInfo(luaL_checkstring(s, p));
+ break;
+ case LUA_TUSERDATA:
+ attributeInfo = LuaAttributeInfo::check(s, p);
+ break;
+ }
luaL_argcheck(s, attributeInfo != nullptr, p, "invalid attribute");
return attributeInfo;
diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h
index 220d4c2f..03c4666e 100644
--- a/src/scripting/luautil.h
+++ b/src/scripting/luautil.h
@@ -165,6 +165,7 @@ typedef LuaUserData<MapObject> LuaMapObject;
typedef LuaUserData<MonsterClass> LuaMonsterClass;
typedef LuaUserData<StatusEffect> LuaStatusEffect;
typedef LuaUserData<AbilityManager::AbilityInfo> LuaAbilityInfo;
+typedef LuaUserData<AttributeManager::AttributeInfo> LuaAttributeInfo;
Script * getScript(lua_State *s);
@@ -179,7 +180,7 @@ Entity * checkMonster(lua_State *s, int p);
MonsterClass * checkMonsterClass(lua_State *s, int p);
Entity * checkNpc(lua_State *s, int p);
AbilityManager::AbilityInfo * checkAbility(lua_State *s, int p);
-const AttributeManager::AttributeInfo *checkAttribute(lua_State *s, int p);
+AttributeManager::AttributeInfo * checkAttribute(lua_State *s, int p);
unsigned char checkWalkMask(lua_State *s, int p);
MapComposite * checkCurrentMap(lua_State *s, Script *script = 0);
@@ -219,6 +220,11 @@ inline void push(lua_State *s, MonsterClass *val)
LuaMonsterClass::push(s, val);
}
+inline void push(lua_State *s, AttributeManager::AttributeInfo *val)
+{
+ LuaAttributeInfo::push(s, val);
+}
+
/* Pushes an STL LIST */
template <typename T>
diff --git a/src/scripting/script.h b/src/scripting/script.h
index 7cf457cc..1f8c415e 100644
--- a/src/scripting/script.h
+++ b/src/scripting/script.h
@@ -24,6 +24,8 @@
#include "common/inventorydata.h"
#include "common/manaserv_protocol.h"
+#include "game-server/attributemanager.h"
+
#include <list>
#include <string>
#include <vector>
@@ -193,6 +195,8 @@ class Script : public sigc::trackable
*/
virtual void push(const std::list<InventoryItem> &itemList) = 0;
+ virtual void push(AttributeManager::AttributeInfo *) = 0;
+
/**
* Executes the function being prepared.
* @param context the context that is supposed to be used for executing