summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--src/defines.h6
-rw-r--r--src/game-server/being.cpp33
-rw-r--r--src/game-server/character.cpp58
-rw-r--r--src/game-server/inventory.cpp5
-rw-r--r--src/game-server/itemmanager.cpp3
-rw-r--r--src/game-server/monster.cpp13
-rw-r--r--src/serialize/characterdata.hpp1
8 files changed, 80 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index 14852935..e57fe9b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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());