diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/defines.h | 9 | ||||
-rw-r--r-- | src/game-server/item.hpp | 5 | ||||
-rw-r--r-- | src/game-server/itemmanager.cpp | 78 | ||||
-rw-r--r-- | src/game-server/monster.cpp | 45 | ||||
-rw-r--r-- | src/game-server/monster.hpp | 36 | ||||
-rw-r--r-- | src/game-server/monstermanager.cpp | 43 | ||||
-rw-r--r-- | src/utils/xml.cpp | 72 | ||||
-rw-r--r-- | src/utils/xml.hpp | 23 |
8 files changed, 221 insertions, 90 deletions
diff --git a/src/defines.h b/src/defines.h index 61c18e24..665adecf 100644 --- a/src/defines.h +++ b/src/defines.h @@ -355,15 +355,18 @@ enum BeingState * Subject to change until Pauan and Dabe are finished with the element system. * Please keep element modifier of BeingAttribute in sync. */ -enum +enum Element { ELEMENT_NEUTRAL = 0, ELEMENT_FIRE, ELEMENT_WATER, ELEMENT_EARTH, ELEMENT_AIR, - ELEMENT_SACRED, - ELEMENT_DEATH + ELEMENT_LIGHTNING, + ELEMENT_METAL, + ELEMENT_WOOD, + ELEMENT_ICE, + ELEMENT_ILLEGAL }; /** 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); + } + } } diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp index 41742d7e..f71e5bfd 100644 --- a/src/utils/xml.cpp +++ b/src/utils/xml.cpp @@ -39,6 +39,20 @@ int getProperty(xmlNodePtr node, char const *name, int def) return def; } +double +getFloatProperty(xmlNodePtr node, const char* name, double def) +{ + double &ret = def; + + xmlChar *prop = xmlGetProp(node, BAD_CAST name); + if (prop) { + ret = atof((char*)prop); + xmlFree(prop); + } + + return ret; +} + std::string getProperty(xmlNodePtr node, char const *name, std::string const &def) { if (xmlChar *prop = xmlGetProp(node, BAD_CAST name)) @@ -50,4 +64,62 @@ std::string getProperty(xmlNodePtr node, char const *name, std::string const &de return def; } +unsigned int elementFromString(std::string name) +{ + if (name=="neutral") return ELEMENT_NEUTRAL; + else if (name=="fire") return ELEMENT_FIRE; + else if (name=="water") return ELEMENT_WATER; + else if (name=="earth") return ELEMENT_EARTH; + else if (name=="air") return ELEMENT_AIR; + else if (name=="lightning") return ELEMENT_LIGHTNING; + else if (name=="metal") return ELEMENT_METAL; + else if (name=="wood") return ELEMENT_WOOD; + else if (name=="ice") return ELEMENT_ICE; + { + return ELEMENT_ILLEGAL; + } +} + +ItemType itemTypeFromString (std::string name) +{ + 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=="hairsprite") return ITEM_HAIRSPRITE; + else if (name=="racesprite") return ITEM_RACESPRITE; + else + { + return ITEM_UNKNOWN; + } +} + +WeaponType weaponTypeFromString (std::string name) +{ + 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 + { + return WPNTYPE_NONE; + } +} + + } // namespace XML diff --git a/src/utils/xml.hpp b/src/utils/xml.hpp index ace8d64d..d2ab62e7 100644 --- a/src/utils/xml.hpp +++ b/src/utils/xml.hpp @@ -27,6 +27,9 @@ #include <string> #include <libxml/tree.h> +#include "defines.h" +#include "../game-server/item.hpp" + namespace XML { /** @@ -38,6 +41,26 @@ namespace XML * Gets a string property from an xmlNodePtr. */ std::string getProperty(xmlNodePtr node, char const *name, std::string const &def); + + /** + * Gets an floating point property from an xmlNodePtr. + */ + double + getFloatProperty(xmlNodePtr node, const char *name, double def); + + + /** + * Converts a string into an element number + */ + unsigned int elementFromString(std::string name); + /** + * Converts a string into an ItemType number + */ + ItemType itemTypeFromString (std::string name); + /** + * Converts a string into a weaponType number + */ + WeaponType weaponTypeFromString (std::string name); } #define for_each_xml_child_node(var, parent) \ |