summaryrefslogtreecommitdiff
path: root/src/game-server
diff options
context:
space:
mode:
authorPhilipp Sehmisch <tmw@crushnet.org>2008-02-20 23:15:54 +0000
committerPhilipp Sehmisch <tmw@crushnet.org>2008-02-20 23:15:54 +0000
commitd1649dfdf5628fb49d1c2c50085cd318a87a515f (patch)
tree8259e3fd44d3f9ac6527d3e6ada98aa017c7a7ad /src/game-server
parent21a8c4c0eb44513f89aede04504c2ee67bcea175 (diff)
downloadmanaserv-d1649dfdf5628fb49d1c2c50085cd318a87a515f.tar.gz
manaserv-d1649dfdf5628fb49d1c2c50085cd318a87a515f.tar.bz2
manaserv-d1649dfdf5628fb49d1c2c50085cd318a87a515f.tar.xz
manaserv-d1649dfdf5628fb49d1c2c50085cd318a87a515f.zip
Implemented different monster attacks read from monsters.xml
Diffstat (limited to 'src/game-server')
-rw-r--r--src/game-server/item.hpp5
-rw-r--r--src/game-server/itemmanager.cpp78
-rw-r--r--src/game-server/monster.cpp45
-rw-r--r--src/game-server/monster.hpp36
-rw-r--r--src/game-server/monstermanager.cpp43
5 files changed, 120 insertions, 87 deletions
diff --git a/src/game-server/item.hpp b/src/game-server/item.hpp
index 4f1186be..018cac48 100644
--- a/src/game-server/item.hpp
+++ b/src/game-server/item.hpp
@@ -47,7 +47,10 @@ enum ItemType
ITEM_EQUIPMENT_RING,// 9
ITEM_EQUIPMENT_NECKLACE,// 10
ITEM_EQUIPMENT_FEET,// 11
- ITEM_EQUIPMENT_AMMO// 12
+ ITEM_EQUIPMENT_AMMO,// 12
+ ITEM_HAIRSPRITE,
+ ITEM_RACESPRITE,
+ ITEM_UNKNOWN
};
/**
diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp
index ef3963d4..78c7f04a 100644
--- a/src/game-server/itemmanager.cpp
+++ b/src/game-server/itemmanager.cpp
@@ -22,6 +22,7 @@
*/
#include <map>
+#include <set>
#include "game-server/itemmanager.hpp"
@@ -36,61 +37,6 @@ static ItemClasses itemClasses; /**< Item reference */
static std::string itemReferenceFile;
-ItemType itemTypeFromString (std::string name, int id = 0)
-{
- if (name=="generic") return ITEM_UNUSABLE;
- else if (name=="usable") return ITEM_USABLE;
- else if (name=="equip-1hand") return ITEM_EQUIPMENT_ONE_HAND_WEAPON;
- else if (name=="equip-2hand") return ITEM_EQUIPMENT_TWO_HANDS_WEAPON;
- else if (name=="equip-torso") return ITEM_EQUIPMENT_TORSO;
- else if (name=="equip-arms") return ITEM_EQUIPMENT_ARMS;
- else if (name=="equip-head") return ITEM_EQUIPMENT_HEAD;
- else if (name=="equip-legs") return ITEM_EQUIPMENT_LEGS;
- else if (name=="equip-shield") return ITEM_EQUIPMENT_SHIELD;
- else if (name=="equip-ring") return ITEM_EQUIPMENT_RING;
- else if (name=="equip-necklace") return ITEM_EQUIPMENT_NECKLACE;
- else if (name=="equip-feet") return ITEM_EQUIPMENT_FEET;
- else if (name=="equip-ammo") return ITEM_EQUIPMENT_AMMO;
- else if (name=="")
- {
- LOG_WARN("No item type defined for item "<<id<<" in items.xml");
- return ITEM_UNUSABLE;
- }
- else
- {
- LOG_WARN("Unknown item type \""<<name<<"\" for item "<<id<<" in items.xml");
- if (name.find("weapon") != std::string::npos)
- LOG_WARN("do you mean \"equip-1hand\" or \"equip-2hand\"?");
- if (name.find("armor") != std::string::npos)
- LOG_WARN("do you mean \"equip-...\" instead of \"armor-...\"?");
- return ITEM_UNUSABLE;
- }
-}
-
-WeaponType weaponTypeFromString (std::string name, int id = 0)
-{
- if (name=="knife") return WPNTYPE_KNIFE;
- else if (name=="sword") return WPNTYPE_SWORD;
- else if (name=="polearm") return WPNTYPE_POLEARM;
- else if (name=="staff") return WPNTYPE_STAFF;
- else if (name=="whip") return WPNTYPE_WHIP;
- else if (name=="bow") return WPNTYPE_BOW;
- else if (name=="shooting") return WPNTYPE_SHOOTING;
- else if (name=="mace") return WPNTYPE_MACE;
- else if (name=="axe") return WPNTYPE_AXE;
- else if (name=="thrown") return WPNTYPE_THROWN;
- else if (name=="")
- {
- LOG_WARN("ItemManager: No weapon type defined for weapon with item id "<<id);
- return WPNTYPE_NONE;
- }
- else
- {
- LOG_WARN("ItemManager: Unknown weapon type \""<<name<<"\" for item "<<id);
- return WPNTYPE_NONE;
- }
-}
-
void ItemManager::initialize(std::string const &file)
{
itemReferenceFile = file;
@@ -145,7 +91,19 @@ void ItemManager::reload()
}
std::string sItemType = XML::getProperty(node, "type", "");
- ItemType itemType = itemTypeFromString(sItemType, id);
+ ItemType itemType = XML::itemTypeFromString(sItemType);
+
+ if (itemType == ITEM_UNKNOWN)
+ {
+ LOG_WARN(itemReferenceFile<<": Unknown item type \""<<sItemType
+ <<"\" for item #"<<id<<" - treating it as \"generic\"");
+ itemType = ITEM_UNUSABLE;
+ }
+
+ if (itemType == ITEM_HAIRSPRITE || itemType == ITEM_RACESPRITE)
+ {
+ continue;
+ }
ItemClass *item;
ItemClasses::iterator i = itemClasses.find(id);
@@ -170,7 +128,13 @@ void ItemManager::reload()
itemType == ITEM_EQUIPMENT_TWO_HANDS_WEAPON)
{
std::string sWeaponType = XML::getProperty(node, "weapon-type", "");
- WeaponType weaponType = weaponTypeFromString(sWeaponType, id);
+ WeaponType weaponType = XML::weaponTypeFromString(sWeaponType);
+ if (weaponType == WPNTYPE_NONE)
+ {
+ LOG_WARN(itemReferenceFile<<": Unknown weapon type \""
+ <<sWeaponType<<"\" for item #"<<id<<" - treating it as generic item");
+ itemType = ITEM_UNUSABLE;
+ }
modifiers.setValue(MOD_WEAPON_TYPE, weaponType);
modifiers.setValue(MOD_WEAPON_RANGE, XML::getProperty(node, "range", 0));
modifiers.setValue(MOD_ELEMENT_TYPE, XML::getProperty(node, "element", 0));
diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp
index c8dc55b5..525b3c73 100644
--- a/src/game-server/monster.cpp
+++ b/src/game-server/monster.cpp
@@ -64,7 +64,8 @@ Monster::Monster(MonsterClass *specy):
mTargetListener(&monsterTargetEventDispatch),
mOwner(NULL),
mOwnerTimer(0),
- mAttackTime(0)
+ mAttackTime(0),
+ mCurrentAttack(NULL)
{
LOG_DEBUG("Monster spawned!");
@@ -83,18 +84,12 @@ Monster::Monster(MonsterClass *specy):
setSpeed(specy->getSpeed());
setSize(specy->getSize());
- // Some bogus stats for testing.
- // TODO: Get all this stuff from the monster database.
- mAttackPreDelay = 10;
- mAttackAftDelay = 10;
- mAttackRange = 32;
- mAttackAngle = 10;
-
// Set positions relative to target from which the monster can attack
- mAttackPositions.push_back(AttackPosition(+32, 0, DIRECTION_LEFT));
- mAttackPositions.push_back(AttackPosition(-32, 0, DIRECTION_RIGHT));
- mAttackPositions.push_back(AttackPosition(0, +32, DIRECTION_DOWN));
- mAttackPositions.push_back(AttackPosition(0, -32, DIRECTION_UP));
+ int dist = specy->getAttackDistance();
+ mAttackPositions.push_back(AttackPosition(dist, 0, DIRECTION_LEFT));
+ mAttackPositions.push_back(AttackPosition(-dist, 0, DIRECTION_RIGHT));
+ mAttackPositions.push_back(AttackPosition(0, dist, DIRECTION_DOWN));
+ mAttackPositions.push_back(AttackPosition(0, -dist, DIRECTION_UP));
}
Monster::~Monster()
@@ -110,19 +105,19 @@ Monster::~Monster()
void Monster::perform()
{
- if (mAction == ATTACK)
+ if (mAction == ATTACK && mCurrentAttack)
{
- if (mAttackTime == mAttackAftDelay)
+ if (mAttackTime == mCurrentAttack->aftDelay)
{
// Hard-coded values for now.
Damage damage;
- damage.base = getModifiedAttribute(BASE_ATTR_PHY_ATK_MIN);
- damage.delta = getModifiedAttribute(BASE_ATTR_PHY_ATK_DELTA);
+ damage.base = (int) (getModifiedAttribute(BASE_ATTR_PHY_ATK_MIN) * mCurrentAttack->damageFactor);
+ damage.delta = (int) (getModifiedAttribute(BASE_ATTR_PHY_ATK_DELTA) * mCurrentAttack->damageFactor);
damage.cth = getModifiedAttribute(BASE_ATTR_HIT);
- damage.element = ELEMENT_NEUTRAL;
- damage.type = DAMAGE_PHYSICAL;
+ damage.element = mCurrentAttack->element;
+ damage.type = mCurrentAttack->type;
damage.usedSkill = 0;
- performAttack(damage, mAttackRange, mAttackAngle);
+ performAttack(damage, mCurrentAttack->range, mCurrentAttack->angle);
}
if (!mAttackTime)
{
@@ -222,9 +217,15 @@ void Monster::update()
{
// We are there - let's beat the crap out of the target
setDirection(bestAttackDirection);
- setAction(ATTACK);
- raiseUpdateFlags(UPDATEFLAG_ATTACK);
- mAttackTime = mAttackPreDelay + mAttackAftDelay;
+ MonsterAttacks allAttacks = mSpecy->getAttacks();
+
+ if (!allAttacks.empty())
+ {
+ mCurrentAttack = allAttacks.at(rand()%allAttacks.size()); //TODO: this ignores priority -> fix it
+ mAttackTime = mCurrentAttack->preDelay + mCurrentAttack->aftDelay;
+ setAction(ATTACK);
+ raiseUpdateFlags(UPDATEFLAG_ATTACK);
+ }
}
else
{
diff --git a/src/game-server/monster.hpp b/src/game-server/monster.hpp
index 36dbbdc3..3f6db5c1 100644
--- a/src/game-server/monster.hpp
+++ b/src/game-server/monster.hpp
@@ -44,6 +44,24 @@ struct MonsterDrop
typedef std::vector< MonsterDrop > MonsterDrops;
/**
+ * Structure containing different attack types of a monster type
+ */
+struct MonsterAttack
+{
+ unsigned id;
+ int priority;
+ float damageFactor;
+ int element;
+ int type;
+ int preDelay;
+ int aftDelay;
+ int range;
+ int angle;
+};
+
+typedef std::vector< MonsterAttack *> MonsterAttacks;
+
+/**
* Class describing the characteristics of a generic monster.
*/
class MonsterClass
@@ -58,7 +76,8 @@ class MonsterClass
mAggressive(false),
mTrackRange(1),
mStrollRange(0),
- mMutation(0)
+ mMutation(0),
+ mAttackDistance(0)
{}
/**
@@ -106,6 +125,12 @@ class MonsterClass
void setMutation(unsigned factor) { mMutation = factor; } /**< sets mutation factor in percent*/
unsigned getMutation() const { return mMutation; } /**< gets mutation factor in percent*/
+ void setAttackDistance(unsigned distance) { mAttackDistance = distance; } /**< sets preferred combat distance in pixels*/
+ unsigned getAttackDistance() const { return mAttackDistance; } /**< gets preferred combat distance in pixels*/
+
+ void addAttack(MonsterAttack *type) { mAttacks.push_back(type); } /**< adds an attack to the monsters repertoire */
+ const MonsterAttacks &getAttacks() const { return mAttacks; } /**< gets all attacks of the monster */
+
/**
* Randomly selects a monster drop (may return NULL).
*/
@@ -122,6 +147,8 @@ class MonsterClass
unsigned mTrackRange; /**< Distance the monster tracks enemies in */
unsigned mStrollRange; /**< Distance the monster strolls around in when not fighting */
unsigned mMutation; /**< Mutation factor in percent*/
+ unsigned mAttackDistance;
+ MonsterAttacks mAttacks; /**< preferred combat distance in pixels*/
};
/**
@@ -205,12 +232,7 @@ class Monster : public Being
std::set<Character *> mLegalExpReceivers; /**< List of characters who are entitled to receive exp (killsteal protection)*/
int mAttackTime; /**< Delay until monster can attack */
- // TODO: the following vars should all be the same for all monsters of
- // the same type. So they should be stored in mSpecy to save memory
- int mAttackPreDelay; /**< time between decision to make an attack and performing the attack */
- int mAttackAftDelay; /**< time it takes to perform an attack */
- int mAttackRange; /**< range of the monsters attacks in pixel */
- int mAttackAngle; /**< angle of the monsters attacks in degree */
+ MonsterAttack *mCurrentAttack; /**<Attack the monster is currently performing */
std::list<AttackPosition> mAttackPositions; /**< set positions relative to target from which the monster can attack */
friend struct MonsterTargetEventDispatch;
diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp
index 693cd53a..69ad5c08 100644
--- a/src/game-server/monstermanager.cpp
+++ b/src/game-server/monstermanager.cpp
@@ -196,6 +196,49 @@ void MonsterManager::reload()
}
monster->setTrackRange(XML::getProperty(subnode, "track-range", 1));
monster->setStrollRange(XML::getProperty(subnode, "stroll-range", 0) * 32);
+ monster->setAttackDistance(XML::getProperty(subnode, "attack-distance", 0));
+ }
+ else if (xmlStrEqual(subnode->name, BAD_CAST "attack"))
+ {
+ MonsterAttack *att = new MonsterAttack;
+ 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);
+ std::string sElement = XML::getProperty(subnode, "element", "neutral");
+ att->element = XML::elementFromString(sElement);
+ std::string sType = XML::getProperty(subnode, "type", "physical");
+ if (sType == "physical") {att->type = DAMAGE_PHYSICAL; }
+ else if (sType == "magical" || sType == "magic") {att->type = DAMAGE_MAGICAL; }
+ else if (sType == "other") {att->type = DAMAGE_OTHER; }
+ else { att->type = -1; }
+
+ if (att->id == 0)
+ {
+ LOG_WARN(monsterReferenceFile
+ <<": Attack without ID for monster #"
+ <<id<<" ("<<name<<") - attack ignored");
+ }
+ else if (att->element == ELEMENT_ILLEGAL)
+ {
+ LOG_WARN(monsterReferenceFile
+ <<": Attack with unknown element \""<<sElement<<"\" "
+ <<"for monster #"<<id<<" ("<<name<<") - attack ignored");
+ }
+ else if (att->type == -1)
+ {
+ LOG_WARN(monsterReferenceFile
+ <<": Attack with unknown type \""<<sType<<"\" "
+ <<"for monster #"<<id<<" ("<<name<<")");
+ }
+ else
+ {
+ monster->addAttack(att);
+ }
+
}
}