diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | src/defines.h | 6 | ||||
-rw-r--r-- | src/game-server/being.cpp | 33 | ||||
-rw-r--r-- | src/game-server/character.cpp | 58 | ||||
-rw-r--r-- | src/game-server/inventory.cpp | 5 | ||||
-rw-r--r-- | src/game-server/itemmanager.cpp | 3 | ||||
-rw-r--r-- | src/game-server/monster.cpp | 13 | ||||
-rw-r--r-- | src/serialize/characterdata.hpp | 1 |
8 files changed, 80 insertions, 50 deletions
@@ -1,3 +1,14 @@ +2008-01-07 Philipp Sehmisch <tmw@crushnet.org> + + * src/defines.h, src/game-server/being.cpp, + src/game-server/being.hpp, src/game-server/character.cpp, + src/game-server/inventory.cpp, src/game-server/itemmanager.cpp, + src/game-server/monster.cpp, src/serialize/characterdata.hpp: + Implemented some of the game mechanics we decided to use. + * src/game-server/character.cpp: + The clients now only receive attribute change messages + when the attribute actually changed. + 2007-12-18 Philipp Sehmisch <tmw@crushnet.org> * src/account-server/dalstorage.cpp, diff --git a/src/defines.h b/src/defines.h index bc3e8a3f..a22a739d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -357,13 +357,15 @@ enum enum { BASE_ATTR_BEGIN = 0, - BASE_ATTR_PHY_ATK = BASE_ATTR_BEGIN, + BASE_ATTR_PHY_ATK_MIN = BASE_ATTR_BEGIN, + BASE_ATTR_PHY_ATK_DELTA, /**< Physical attack power. */ BASE_ATTR_MAG_ATK, /**< Magical attack power. */ BASE_ATTR_PHY_RES, /**< Resistance to physical damage. */ BASE_ATTR_MAG_RES, /**< Resistance to magical damage. */ BASE_ATTR_EVADE, /**< Ability to avoid hits. */ - BASE_ATTR_HP, /**< Remaining Hit Points. */ + BASE_ATTR_HIT, /**< Ability to hit stuff. */ + BASE_ATTR_HP, /**< Hit Points (Base value: maximum, Modded value: current) */ BASE_ATTR_END, BASE_ATTR_NB = BASE_ATTR_END - BASE_ATTR_BEGIN, diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 7c09d97e..c969daf5 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -53,33 +53,12 @@ int Being::damage(Object *, Damage const &damage) HPloss += rand() / (RAND_MAX / (damage.delta + 1)); } - /* Damage can either be avoided, or applied, or critical (applied twice). - This is decided by comparing CTH and Evade. If they are equal, the - probabilities are 10%, 80%, 10%. Otherwise, the bigger the CTH, the - higher the chance to do a critical, up to 50%; and the bigger the Evade, - the higher the chance to do evade the hit, up to 50% again. */ - - int avoidChance = 10, criticalChance = 10; - int diff = damage.cth - getModifiedAttribute(BASE_ATTR_EVADE); - if (diff > 0) - { - // CTH - Evade >= 200 => 50% critical - criticalChance += diff * diff / 1000; - if (criticalChance > 50) criticalChance = 50; - } - else if (diff < 0) + int hitThrow = rand()%(damage.cth + 1); + int evadeThrow = rand()%(getModifiedAttribute(BASE_ATTR_EVADE) + 1); + if (evadeThrow > hitThrow) { - // Evade - CTH >= 200 => 50% avoid - avoidChance += diff * diff / 10000; - if (avoidChance > 50) avoidChance = 50; + HPloss = 0; } - int chance = rand() / (RAND_MAX / 100); - if (chance <= avoidChance) - { - mHitsTaken.push_back(0); - return 0; - } - if (chance >= 100 - criticalChance) HPloss *= 2; /* Elemental modifier at 100 means normal damage. At 0, it means immune. And at 200, it means vulnerable (double damage). */ @@ -99,7 +78,9 @@ int Being::damage(Object *, Damage const &damage) default: break; } - HPloss = HPloss * mod1 / (100 + mod2); + HPloss = HPloss * (mod1 / 100) - mod2; + + if (HPloss < 0) HPloss = 0; mHitsTaken.push_back(HPloss); LOG_DEBUG("Being " << getPublicID() << " got hit."); diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index b9bb061b..04f3d52b 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -42,7 +42,7 @@ Character::Character(MessageIn &msg): Being(OBJECT_CHARACTER, 65535), mClient(NULL), mTransactionHandler(NULL), mDatabaseID(-1), - mGender(0), mHairStyle(0), mHairColor(0), mLevel(0), + mGender(0), mHairStyle(0), mHairColor(0), mLevel(1), mTransaction(TRANS_NONE) { Attribute attr = { 0, 0 }; @@ -69,20 +69,19 @@ void Character::perform() int type = ic ? ic->getModifiers().getValue(MOD_WEAPON_TYPE) : WPNTYPE_NONE; Damage damage; - damage.base = getModifiedAttribute(BASE_ATTR_PHY_ATK) / 10; + damage.base = getModifiedAttribute(BASE_ATTR_PHY_ATK_MIN); + damage.delta = getModifiedAttribute(BASE_ATTR_PHY_ATK_DELTA); damage.type = DAMAGE_PHYSICAL; + damage.cth = getModifiedAttribute(BASE_ATTR_HIT) + + getModifiedAttribute(CHAR_SKILL_WEAPON_BEGIN + type); if (type) { ItemModifiers const &mods = ic->getModifiers(); - damage.delta = mods.getValue(MOD_WEAPON_DAMAGE); - damage.cth = getModifiedAttribute(CHAR_SKILL_WEAPON_BEGIN + type); damage.element = mods.getValue(MOD_ELEMENT_TYPE); } else { // No-weapon fighting. - damage.delta = 1; - damage.cth = getModifiedAttribute(CHAR_SKILL_WEAPON_NONE); damage.element = ELEMENT_NEUTRAL; } performAttack(damage); @@ -179,17 +178,46 @@ void Character::modifiedAttribute(int attr) { if (attr >= CHAR_ATTR_BEGIN && attr < CHAR_ATTR_END) { - /* FIXME: The following formulas are for testing purpose only. They - should be replaced by a real system once designed. */ - setAttribute(BASE_ATTR_HP, getModifiedAttribute(CHAR_ATTR_VITALITY)); - setAttribute(BASE_ATTR_PHY_ATK, getModifiedAttribute(CHAR_ATTR_STRENGTH)); - setAttribute(BASE_ATTR_PHY_RES, getModifiedAttribute(CHAR_ATTR_VITALITY)); - setAttribute(BASE_ATTR_MAG_RES, getModifiedAttribute(CHAR_ATTR_WILLPOWER)); - setAttribute(BASE_ATTR_EVADE, getModifiedAttribute(CHAR_ATTR_DEXTERITY)); - // We have just modified the computed attributes. Mark them as such. for (int i = BASE_ATTR_BEGIN; i < BASE_ATTR_END; ++i) { - flagAttribute(i); + int newValue = getAttribute(i); + + if (i == BASE_ATTR_HP){ + newValue = (getModifiedAttribute(CHAR_ATTR_VITALITY) + 10) + * (mLevel + 10); + } + else if (i == BASE_ATTR_HIT) { + newValue = getModifiedAttribute(CHAR_ATTR_DEXTERITY) + /* + skill in class of currently equipped weapon */; + } + else if (i == BASE_ATTR_EVADE) { + newValue = getModifiedAttribute(CHAR_ATTR_AGILITY); + /* TODO: multiply with 10 / (10 * equip_weight)*/ + } + else if (i == BASE_ATTR_PHY_RES) { + newValue = getModifiedAttribute(CHAR_ATTR_VITALITY); + /* equip defence is through equip modifiers */ + } + else if (i == BASE_ATTR_PHY_ATK_MIN) { + newValue = getModifiedAttribute(CHAR_ATTR_STRENGTH); + /* weapon attack is applied through equip modifiers */ + } + else if (i == BASE_ATTR_PHY_ATK_DELTA) { + newValue = 0 /* + skill in class of currently equipped weapon */; + /* weapon attack is applied through equip modifiers */ + } + else if (i == BASE_ATTR_MAG_RES) { + newValue = getModifiedAttribute(CHAR_ATTR_WILLPOWER); + } + else if (i == BASE_ATTR_MAG_ATK) { + newValue = getModifiedAttribute(CHAR_ATTR_WILLPOWER); + } + + if (newValue != getAttribute(i)) + { + setAttribute(i, newValue); + flagAttribute(i); + } } } flagAttribute(attr); diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index c2dc8ba9..31f3b17b 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -596,7 +596,7 @@ int Inventory::move(int slot1, int slot2, int amount) mPoss->inventory.insert(mPoss->inventory.end(), it); } InventoryItem it = { id, nb }; - mPoss->inventory.insert(mPoss->inventory.end(), it); + mPoss->inventory.insert(mPoss->inventory.end(), it); return amount; } @@ -682,6 +682,9 @@ void Inventory::changeEquipment(int slot, int itemId) msg.writeShort(itemId); mPoss->equipment[slot] = itemId; mChangedLook = true; + + //mark evade as modified because it depends on equipment weight + mClient->modifiedAttribute(BASE_ATTR_EVADE); } void Inventory::equip(int slot) diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp index 02eee7d5..57486177 100644 --- a/src/game-server/itemmanager.cpp +++ b/src/game-server/itemmanager.cpp @@ -112,9 +112,10 @@ void ItemManager::reload() ItemModifiers modifiers; modifiers.setValue(MOD_WEAPON_TYPE, XML::getProperty(node, "weapon_type", 0)); modifiers.setValue(MOD_WEAPON_RANGE, XML::getProperty(node, "range", 0)); - modifiers.setValue(MOD_WEAPON_DAMAGE, XML::getProperty(node, "attack", 0)); modifiers.setValue(MOD_ELEMENT_TYPE, XML::getProperty(node, "element", 0)); modifiers.setValue(MOD_LIFETIME, XML::getProperty(node, "lifetime", 0) * 10); + modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_MIN, XML::getProperty(node, "attack-min", 0)); + modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_DELTA, XML::getProperty(node, "attack-delta", 0)); modifiers.setAttributeValue(BASE_ATTR_HP, XML::getProperty(node, "hp", 0)); modifiers.setAttributeValue(BASE_ATTR_PHY_RES, XML::getProperty(node, "defense", 0)); modifiers.setAttributeValue(CHAR_ATTR_STRENGTH, XML::getProperty(node, "strength", 0)); diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index 1d4bc280..b65ee3de 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -70,8 +70,11 @@ Monster::Monster(MonsterClass *specy): // Some bogus stats for testing. setSpeed(300); setSize(8); - setAttribute(BASE_ATTR_HP, 10); - setAttribute(BASE_ATTR_PHY_ATK, 10); + setAttribute(BASE_ATTR_HP, 100); + setAttribute(BASE_ATTR_PHY_ATK_MIN, 20); + setAttribute(BASE_ATTR_PHY_ATK_DELTA, 2); + setAttribute(BASE_ATTR_HIT, 10); + setAttribute(BASE_ATTR_EVADE, 10); // Set positions relative to target from which the monster can attack mAttackPositions.push_back(AttackPosition(+32, 0, DIRECTION_LEFT)); @@ -99,9 +102,9 @@ void Monster::perform() // Hard-coded values for now. Damage damage; - damage.base = getModifiedAttribute(BASE_ATTR_PHY_ATK) / 10; - damage.delta = 2; - damage.cth = 50; + damage.base = getModifiedAttribute(BASE_ATTR_PHY_ATK_MIN); + damage.delta = getModifiedAttribute(BASE_ATTR_PHY_ATK_DELTA); + damage.cth = getModifiedAttribute(BASE_ATTR_HIT); damage.element = ELEMENT_NEUTRAL; damage.type = DAMAGE_PHYSICAL; performAttack(damage); diff --git a/src/serialize/characterdata.hpp b/src/serialize/characterdata.hpp index 7d3a7fc1..c9969b63 100644 --- a/src/serialize/characterdata.hpp +++ b/src/serialize/characterdata.hpp @@ -74,6 +74,7 @@ void deserializeCharacterData(T &data, MessageIn &msg) for (int i = CHAR_ATTR_BEGIN; i < CHAR_ATTR_END; ++i) { data.setAttribute(i, msg.readByte()); + data.modifiedAttribute(i); } data.setMapId(msg.readShort()); |