summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Sehmisch <tmw@crushnet.org>2008-09-27 03:55:19 +0000
committerPhilipp Sehmisch <tmw@crushnet.org>2008-09-27 03:55:19 +0000
commit29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358 (patch)
tree41ca7bb0f8b557e096a2b783f6c94ea4d3e5006a
parentc27d73abc52bdc463a029a5f6a95e1db5df5abf6 (diff)
downloadmanaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.tar.gz
manaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.tar.bz2
manaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.tar.xz
manaserv-29ae6d3f42ac55e7bc8c5ad0b044c7b0e662d358.zip
Implemented getting the attack zone of weapons from the item database and implemented single target attacks useful for projectile weapons like bows.
-rw-r--r--ChangeLog54
-rw-r--r--gameserver.cbp2
-rw-r--r--src/Makefile.am3
-rw-r--r--src/game-server/attackzone.cpp0
-rw-r--r--src/game-server/attackzone.hpp46
-rw-r--r--src/game-server/being.cpp59
-rw-r--r--src/game-server/being.hpp3
-rw-r--r--src/game-server/character.cpp12
-rw-r--r--src/game-server/character.hpp2
-rw-r--r--src/game-server/item.cpp6
-rw-r--r--src/game-server/item.hpp18
-rw-r--r--src/game-server/itemmanager.cpp41
-rw-r--r--src/game-server/monster.cpp4
-rw-r--r--src/game-server/monster.hpp5
-rw-r--r--src/game-server/monstermanager.cpp9
15 files changed, 222 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index 3330f3c3..58481fff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,20 @@
+2008-09-27 Philipp Sehmisch <tmw@crushnet.org>
+
+ * src/game-server/attackzone.cpp, src/game-server/attackzone.hpp,
+ src/game-server/being.cpp, src/game-server/being.hpp,
+ src/game-server/character.cpp, src/game-server/character.hpp,
+ src/game-server/item.cpp, src/game-server/item.hpp,
+ src/game-server/itemmanager.cpp, src/game-server/monster.cpp,
+ src/game-server/monster.hpp, src/game-server/monstermanager.cpp,
+ gameserver.cbp, src/Makefile.AM: Implemented getting the attack zone of
+ weapons from the item database and implemented single target attacks
+ useful for projectile weapons like bows.
+
2008-08-19 David Athay <ko2fan@gmail.com>
* accountserver.cbp, src/account-server/main-account.cpp,
src/account-server/serverhandler.cpp, src/chat-server/post.cpp,
- src/chat-server/post.hpp, src/defines.h,
+ src/chat-server/post.hpp, src/defines.h,
src/game-server/gamehandler.cpp, src/game-server/accountconnection.cpp,
src/game-server/gamehandler.hpp, src/game-server/accountconnection.hpp,
src/game-server/postman.hpp, src/game-server/main-game.cpp,
@@ -21,47 +33,47 @@
2008-09-18 David Athay <ko2fan@gmail.com>
* src/chat-server/post.hpp, src/chat-server/post.cpp, src/defines.h,
- src/game-server/gamehandler.cpp, src/game-server/gamehandler.hpp,
- src/game-server/main-game.cpp: Changed timing to be 100ms per tick.
+ src/game-server/gamehandler.cpp, src/game-server/gamehandler.hpp,
+ src/game-server/main-game.cpp: Changed timing to be 100ms per tick.
Added post manager on chat server.
2008-09-17 Andreas Habel <mail@exceptionfault.de>
- * src/sql/*, src/account-server/dalstoragesql.hpp: added installation
- scripts to set up database schemas for mysql, sqlite and postgresql.
- The create table statements have been completely removed out from the c++
+ * src/sql/*, src/account-server/dalstoragesql.hpp: added installation
+ scripts to set up database schemas for mysql, sqlite and postgresql.
+ The create table statements have been completely removed out from the c++
source into separate, provider specific sql files.
- * docs/tmwserv.xml: added database specific parameters to configure
+ * docs/tmwserv.xml: added database specific parameters to configure
each provider, that is used as database backend independent
* Doxyfile: doxygen now also includes non-documented functions and provides
a dictionary for all classes
* dal/dataprovider.h, dal/sqlitedataprovider.h, dal/mysqldataprovider.h,
dal/mysqldataprovider.cpp, dal/sqlitedataprovider.cpp:
- Extended abstract dataprovider to support transactions, implemented for
+ Extended abstract dataprovider to support transactions, implemented for
SQLite and mySQL. Added methods to retrieve last inserted
auto-increment value and the number of modified rows in the last statement.
- * account-server/dalstorage.cpp: Tiny rewrite to be a little more
+ * account-server/dalstorage.cpp: Tiny rewrite to be a little more
transactional and use advanced database functionality. Fixed a bug when
- deleting a character that left data in quests table and guilds table.
- Simplified the connect routine of DALStorage class since every dataprovider
+ deleting a character that left data in quests table and guilds table.
+ Simplified the connect routine of DALStorage class since every dataprovider
is now responsible to retrieve its parameters for itself.
-
+
2008-09-15 Andreas Habel <mail@exceptionfault.de>
* Doxyfile: added doxygen file, docu will be generated under docs/api/html
- * src/account-server/dalstorage.cpp, src/account-server/dalstorage.hpp,
+ * src/account-server/dalstorage.cpp, src/account-server/dalstorage.hpp,
src/account-server/dalstoragesql.hpp, src/account-server/main-account.cpp:
added table tmw_world_states to store map and world-specific variables,
extended DALStorage to set and get those new variables, applied Kess's diff
file from mantis #424 with modifications for PostgreSQL support.
-
+
2008-09-10 Andreas Habel <mail@exceptionfault.de>
* src/account-server/dalstorage.cpp, src/account-server/account.cpp,
src/account-server/account.hpp, src/account-server/accounthandler.cpp,
- src/account-server/dalstorage.hpp, src/account-server/dalstoragesql.hpp:
- Extended tmw_accounts table with columns for lastlogin and registration
- date. Modified account-server to fill the new columns on registration and
+ src/account-server/dalstorage.hpp, src/account-server/dalstoragesql.hpp:
+ Extended tmw_accounts table with columns for lastlogin and registration
+ date. Modified account-server to fill the new columns on registration and
login. Recreation of database needed!
* src/account-server/dalstorage.cpp,
src/account-server/dalstoragesql.hpp: Added createIndex function to
@@ -71,8 +83,8 @@
* src/account-server/dalstorage.cpp: Set banned user's level to
AL_BANNED.
- * src/account-server/main-account.cpp,
- src/account-server/dalstorage.cpp, src/account-server/dalstorage.hpp:
+ * src/account-server/main-account.cpp,
+ src/account-server/dalstorage.cpp, src/account-server/dalstorage.hpp:
Added checking for expired bans.
* src/account-server/dalstorage.cpp, src/account-server/dalstorage.hpp:
ExceptionFault corrected my poor sql skills.
@@ -672,7 +684,7 @@
now transmitted together with attack messages (has already been
implemented on the client-side but the server-sided part has been
forgotten somehow).
-
+
2008-01-23 Philipp Sehmisch <tmw@crushnet.org>
* src/game-server/being.cpp: Fixed "immortal monster" bug.
@@ -2928,4 +2940,4 @@
src/dal/sqlitedataprovider.cpp, src/dal/mysqldataprovider.cpp,
src/dal/pqdataprovider.cpp, src/main.cpp, src/client.cpp:
Grammar corrections, and a little bit of work on getting the name of
- the Db.
+ the Db. \ No newline at end of file
diff --git a/gameserver.cbp b/gameserver.cbp
index c9311438..cdf9df41 100644
--- a/gameserver.cbp
+++ b/gameserver.cbp
@@ -57,6 +57,8 @@
<Unit filename="src/defines.h" />
<Unit filename="src/game-server/accountconnection.cpp" />
<Unit filename="src/game-server/accountconnection.hpp" />
+ <Unit filename="src/game-server/attackzone.cpp" />
+ <Unit filename="src/game-server/attackzone.hpp" />
<Unit filename="src/game-server/being.cpp" />
<Unit filename="src/game-server/being.hpp" />
<Unit filename="src/game-server/buysell.cpp" />
diff --git a/src/Makefile.am b/src/Makefile.am
index bbfa5d52..936fd7b9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,8 @@ tmwserv_game_SOURCES = \
common/inventorydata.hpp \
game-server/accountconnection.hpp \
game-server/accountconnection.cpp \
+ game-server/attackzone.hpp \
+ game-server/attackzone.cpp \
game-server/being.hpp \
game-server/being.cpp \
game-server/buysell.hpp \
@@ -191,4 +193,3 @@ if BUILD_LUA
tmwserv_game_SOURCES += \
scripting/lua.cpp
endif
-
diff --git a/src/game-server/attackzone.cpp b/src/game-server/attackzone.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/game-server/attackzone.cpp
diff --git a/src/game-server/attackzone.hpp b/src/game-server/attackzone.hpp
new file mode 100644
index 00000000..2bdf3b14
--- /dev/null
+++ b/src/game-server/attackzone.hpp
@@ -0,0 +1,46 @@
+/*
+ * The Mana World Server
+ * Copyright 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMWSERV_ATTACKZONE
+#define _TMWSERV_ATTACKZONE
+
+
+/**
+ * Enumeration of different types of attack damage zones
+ */
+enum AttackZoneShape
+{
+ ATTZONESHAPE_CONE
+ //yes, there is currently only one but it is planned to add different kinds of attack zones
+};
+
+struct AttackZone
+{
+ AttackZoneShape shape;
+ bool multiTarget;
+ int range;
+ int angle;
+};
+
+
+#endif // _TMWSERV_ATTACKZONE
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp
index a6ba4023..bcbbc6d9 100644
--- a/src/game-server/being.cpp
+++ b/src/game-server/being.cpp
@@ -25,6 +25,7 @@
#include "game-server/being.hpp"
#include "defines.h"
+#include "game-server/attackzone.hpp"
#include "game-server/collisiondetection.hpp"
#include "game-server/eventlistener.hpp"
#include "game-server/mapcomposite.hpp"
@@ -126,7 +127,7 @@ void Being::move()
}
}
-void Being::performAttack(Damage const &damage, int range, int angle)
+void Being::performAttack(Damage const &damage, AttackZone const *attackZone)
{
Point ppos = getPosition();
int dir = getDirection();
@@ -151,8 +152,10 @@ void Being::performAttack(Damage const &damage, int range, int angle)
break;
}
+ std::list<Being *> victims;
+
for (MovingObjectIterator
- i(getMap()->getAroundObjectIterator(this, range)); i; ++i)
+ i(getMap()->getAroundObjectIterator(this, attackZone->range)); i; ++i)
{
MovingObject *o = *i;
if (o == this) continue;
@@ -163,13 +166,55 @@ void Being::performAttack(Damage const &damage, int range, int angle)
Point opos = o->getPosition();
- if (Collision::diskWithCircleSector(
- opos, o->getSize(),
- ppos, range, angle, attackAngle)
- )
+ switch (attackZone->shape)
+ {
+ case ATTZONESHAPE_CONE:
+ if (Collision::diskWithCircleSector(
+ opos, o->getSize(),
+ ppos, attackZone->range,
+ attackZone->angle/2, attackAngle)
+ )
+ {
+ victims.push_back(static_cast< Being * >(o));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (attackZone->multiTarget)
+ {
+ // damage everyone
+ for (std::list<Being *>::iterator i = victims.begin();
+ i != victims.end();
+ i++)
+ {
+ (*i)->damage(this, damage);
+ }
+ }
+ else
+ {
+ // find the closest and damage this one
+ Being* closestVictim = NULL;
+ int closestDistance = INT_MAX;
+ for (std::list<Being *>::iterator i = victims.begin();
+ i != victims.end();
+ i++)
{
- static_cast< Being * >(o)->damage(this, damage);
+ Point opos = (*i)->getPosition();
+ int distance = abs(opos.x - ppos.x) + abs(opos.y - ppos.y);
+ /* not using pythagoras here is a) faster and b) results in more natural
+ target selection because targets closer to the center line of the
+ attack angle are prioritized
+ */
+ if (distance < closestDistance)
+ {
+ closestVictim = (*i);
+ closestDistance = distance;
+ }
}
+ if (closestVictim) closestVictim->damage(this, damage);
}
}
diff --git a/src/game-server/being.hpp b/src/game-server/being.hpp
index 870fd78a..58535487 100644
--- a/src/game-server/being.hpp
+++ b/src/game-server/being.hpp
@@ -31,6 +31,7 @@
class Being;
class MapComposite;
+class AttackZone;
/**
* Beings and actors directions
@@ -158,7 +159,7 @@ class Being : public MovingObject
/**
* Performs an attack.
*/
- void performAttack(Damage const &, int range, int angle);
+ void performAttack(Damage const &, AttackZone const *attackZone);
/**
* Sets the current action.
diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp
index 37fb3b8c..8758b64e 100644
--- a/src/game-server/character.cpp
+++ b/src/game-server/character.cpp
@@ -28,6 +28,7 @@
#include "game-server/character.hpp"
#include "defines.h"
+#include "game-server/attackzone.hpp"
#include "game-server/buysell.hpp"
#include "game-server/eventlistener.hpp"
#include "game-server/inventory.hpp"
@@ -48,6 +49,7 @@
const float Character::EXPCURVE_EXPONENT = 3.0f;
const float Character::EXPCURVE_FACTOR = 10.0f;
const float Character::LEVEL_SKILL_PRECEDENCE_FACTOR = 0.75f;
+const AttackZone Character::UNARMED_ATTACK_ZONE = {ATTZONESHAPE_CONE, true, 32, 90};
Character::Character(MessageIn &msg):
Being(OBJECT_CHARACTER, 65535),
@@ -102,21 +104,21 @@ void Character::perform()
damage.cth = getModifiedAttribute(BASE_ATTR_HIT) +
getModifiedAttribute(CHAR_SKILL_WEAPON_BEGIN + type);
damage.usedSkill = CHAR_SKILL_WEAPON_BEGIN + type;
- if (type)
+
+ if (ic)
{
+ // weapon fighting
ItemModifiers const &mods = ic->getModifiers();
damage.element = mods.getValue(MOD_ELEMENT_TYPE);
+ performAttack(damage, ic->getAttackZone());
}
else
{
// No-weapon fighting.
damage.element = ELEMENT_NEUTRAL;
+ performAttack(damage, &UNARMED_ATTACK_ZONE);
}
- int attackRange = 60; //TODO: get from weapon
- int attackAngle = 30; //TODO: get from weapon
-
- performAttack(damage, attackRange, attackAngle);
}
void Character::respawn()
diff --git a/src/game-server/character.hpp b/src/game-server/character.hpp
index d3b31276..30914344 100644
--- a/src/game-server/character.hpp
+++ b/src/game-server/character.hpp
@@ -288,6 +288,8 @@ class Character : public Being
static const int CORRECTIONPOINTS_PER_LEVELUP = 2;
static const int CORRECTIONPOINTS_MAX = 10;
+ static const AttackZone UNARMED_ATTACK_ZONE;
+
/**
* Advances the character by one level;
*/
diff --git a/src/game-server/item.cpp b/src/game-server/item.cpp
index f14374b6..4d0530f8 100644
--- a/src/game-server/item.cpp
+++ b/src/game-server/item.cpp
@@ -27,6 +27,7 @@
#include "game-server/item.hpp"
+#include "game-server/attackzone.hpp"
#include "game-server/being.hpp"
WeaponType weaponTypeFromString (const std::string &name)
@@ -136,6 +137,11 @@ void ItemModifiers::cancelAttributes(Being *b) const
}
}
+ItemClass::~ItemClass()
+{
+ if (mAttackZone) delete mAttackZone;
+}
+
bool ItemClass::use(Being *itemUser)
{
if (mType != ITEM_USABLE) return false;
diff --git a/src/game-server/item.hpp b/src/game-server/item.hpp
index 7b21ad87..e0d8943f 100644
--- a/src/game-server/item.hpp
+++ b/src/game-server/item.hpp
@@ -28,6 +28,7 @@
#include "game-server/object.hpp"
+class AttackZone;
class Being;
/**
@@ -175,9 +176,11 @@ class ItemClass
{
public:
ItemClass(int id, ItemType type)
- : mDatabaseID(id), mType(type)
+ : mDatabaseID(id), mType(type), mAttackZone(NULL)
{}
+ ~ItemClass();
+
/**
* Applies the modifiers of an item to a given user.
* @return true if the item was sucessfully used and should be removed.
@@ -256,6 +259,18 @@ class ItemClass
int getSpriteID()
{ return mSpriteID; }
+ /**
+ * Set attack zone (only needed when the item is a weapon)
+ */
+ void setAttackZone(AttackZone* attackZone) { mAttackZone = attackZone; }
+
+ /**
+ * Gets attack zone of weapon (returns NULL for non-weapon items)
+ */
+ AttackZone const *getAttackZone() const
+ { return mAttackZone ; }
+
+
private:
// Item reference information
@@ -266,6 +281,7 @@ class ItemClass
unsigned short mCost; /**< Unit cost the item. */
unsigned short mMaxPerSlot; /**< Max item amount per slot in inventory. */
ItemModifiers mModifiers; /**< Item modifiers. */
+ AttackZone *mAttackZone; /**< attack zone when used as a weapon */
};
class Item: public Object
diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp
index 211334ff..159b8356 100644
--- a/src/game-server/itemmanager.cpp
+++ b/src/game-server/itemmanager.cpp
@@ -27,6 +27,7 @@
#include "game-server/itemmanager.hpp"
#include "defines.h"
+#include "game-server/attackzone.hpp"
#include "game-server/item.hpp"
#include "game-server/resourcemanager.hpp"
#include "utils/logger.h"
@@ -122,6 +123,10 @@ void ItemManager::reload()
int maxPerSlot = XML::getProperty(node, "max-per-slot", 0);
int sprite = XML::getProperty(node, "sprite_id", 0);
std::string scriptName = XML::getProperty(node, "script_name", std::string());
+ std::string attackShape = XML::getProperty(node, "attack-shape", "cone");
+ std::string attackTarget = XML::getProperty(node, "attack-target", "multi");
+ int attackRange = XML::getProperty(node, "attack-range", 32);
+ int attackAngle = XML::getProperty(node, "attack-angle", 90);
ItemModifiers modifiers;
if (itemType == ITEM_EQUIPMENT_ONE_HAND_WEAPON ||
@@ -182,6 +187,42 @@ void ItemManager::reload()
item->setSpriteID(sprite ? sprite : id);
++nbItems;
+ if (itemType == ITEM_EQUIPMENT_ONE_HAND_WEAPON ||
+ itemType == ITEM_EQUIPMENT_TWO_HANDS_WEAPON)
+ {
+ AttackZone *zone = new AttackZone;
+
+ if (attackShape == "cone")
+ {
+ zone->shape = ATTZONESHAPE_CONE;
+ }
+ else
+ {
+ LOG_WARN("Item Manager: Unknown attack zone shape \"" << attackShape
+ <<"\" for weapon " << id << " in " << itemReferenceFile << '.');
+ zone->shape = ATTZONESHAPE_CONE;
+ }
+
+ if (attackTarget == "multi")
+ {
+ zone->multiTarget = true;
+ }
+ else if (attackTarget == "single")
+ {
+ zone->multiTarget = false;
+ }
+ else
+ {
+ LOG_WARN("Item Manager: Unknown target mode \"" << attackTarget
+ <<"\" for weapon " << id << " in " << itemReferenceFile << '.');
+ zone->multiTarget = true;
+ }
+ zone->range = attackRange;
+ zone->angle = attackAngle;
+
+ item->setAttackZone(zone);
+ }
+
LOG_DEBUG("Item: ID: " << id << ", itemType: " << itemType
<< ", weight: " << weight << ", value: " << value <<
", scriptName: " << scriptName << ", maxPerSlot: " << maxPerSlot << ".");
diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp
index d782eae0..f9cb1794 100644
--- a/src/game-server/monster.cpp
+++ b/src/game-server/monster.cpp
@@ -125,7 +125,7 @@ void Monster::perform()
damage.element = mCurrentAttack->element;
damage.type = mCurrentAttack->type;
damage.usedSkill = 0;
- performAttack(damage, mCurrentAttack->range, mCurrentAttack->angle);
+ performAttack(damage, &mCurrentAttack->attackZone);
}
if (!mAttackTime)
{
@@ -240,7 +240,7 @@ void Monster::update()
}
if (Collision::diskWithCircleSector(
bestAttackTarget->getPosition(), bestAttackTarget->getSize(),
- getPosition(), (*i)->range, (*i)->angle, attackAngle))
+ getPosition(), (*i)->attackZone.range, (*i)->attackZone.angle, attackAngle))
{
prioritySum += (*i)->priority;
workingAttacks[prioritySum] = (*i);
diff --git a/src/game-server/monster.hpp b/src/game-server/monster.hpp
index 0a614081..c17dfb7e 100644
--- a/src/game-server/monster.hpp
+++ b/src/game-server/monster.hpp
@@ -26,9 +26,11 @@
#include <map>
#include <vector>
+#include "game-server/attackzone.hpp"
#include "game-server/being.hpp"
#include "game-server/eventlistener.hpp"
+class attackZone;
class ItemClass;
class MapComposite;
@@ -55,8 +57,7 @@ struct MonsterAttack
int type;
int preDelay;
int aftDelay;
- int range;
- int angle;
+ AttackZone attackZone;
};
typedef std::vector< MonsterAttack *> MonsterAttacks;
diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp
index d7a840e7..a6d22750 100644
--- a/src/game-server/monstermanager.cpp
+++ b/src/game-server/monstermanager.cpp
@@ -26,6 +26,7 @@
#include "game-server/monstermanager.hpp"
#include "defines.h"
+#include "game-server/attackzone.hpp"
#include "game-server/itemmanager.hpp"
#include "game-server/monster.hpp"
#include "game-server/resourcemanager.hpp"
@@ -223,13 +224,17 @@ void MonsterManager::reload()
else if (xmlStrEqual(subnode->name, BAD_CAST "attack"))
{
MonsterAttack *att = new MonsterAttack;
+ AttackZone attackZone;
att->id = XML::getProperty(subnode, "id", 0);
att->priority = XML::getProperty(subnode, "priority", 1);
att->damageFactor = XML::getFloatProperty(subnode, "damage-factor", 1.0f);
att->preDelay = XML::getProperty(subnode, "pre-delay", 1);
att->aftDelay = XML::getProperty(subnode, "aft-delay", 0);
- att->range = XML::getProperty(subnode, "range", 1);
- att->angle = XML::getProperty(subnode, "angle", 1);
+ attackZone.multiTarget = true;
+ attackZone.shape = ATTZONESHAPE_CONE;
+ attackZone.range = XML::getProperty(subnode, "range", 1);
+ attackZone.angle = XML::getProperty(subnode, "angle", 1);
+ att->attackZone = attackZone;
std::string sElement = XML::getProperty(subnode, "element", "neutral");
att->element = elementFromString(sElement);
std::string sType = XML::getProperty(subnode, "type", "physical");