changeset 1602:96a1f5e0b6cd

Merge
author Grumpy7
date Thu, 12 Sep 2013 09:55:20 +0200
parents 5ac59bcb68e9 (diff) 43d3536a20f7 (current diff)
children c58916c53d8e
files Items.h UI/UIPopup.cpp
diffstat 9 files changed, 782 insertions(+), 801 deletions(-) [+]
line wrap: on
line diff
--- a/Actor.cpp	Mon Sep 09 20:09:01 2013 +0200
+++ b/Actor.cpp	Thu Sep 12 09:55:20 2013 +0200
@@ -5328,7 +5328,7 @@
     player->ReceiveDamage(uDamageAmount, (DAMAGE_TYPE)a2);
   v50 = 24;
   v59 = 20 * v61 / (signed int)pMonster->pMonsterInfo.uHP;
-  if ( (player->_48EA46_calc_special_bonus_by_items(24) || hit_will_stun != v41)
+  if ( (player->GetSpecialItemBonus(24) || hit_will_stun != v41)
     && stru_50C198.GetMagicalResistance(pMonster, 3u) )
   {
     LODWORD(v42) = 20;
--- a/CastSpellInfo.cpp	Mon Sep 09 20:09:01 2013 +0200
+++ b/CastSpellInfo.cpp	Thu Sep 12 09:55:20 2013 +0200
@@ -1949,7 +1949,7 @@
 				v245->uItemID <= 134 &&
 				v245->uSpecEnchantmentType == 0 &&
 				v245->uEnchantmentType == 0 &&
-				v245->_bonus_strength== 0 &&
+				v245->m_enchantmentStrength== 0 &&
 				!v245->IsBroken() )
 			{
 				if ( v245->GetValue() < 450 || 
@@ -1982,7 +1982,7 @@
 						}
 						v255 = 10;//pItemsTable->field_116D8[17];
 						v256 = 10;//pItemsTable->field_116D8[16];
-						v245->_bonus_strength = v256 + rand() % (v255 - v256 + 1);
+						v245->m_enchantmentStrength = v256 + rand() % (v255 - v256 + 1);
 						v245->uAttributes |= 0x20u;
 						_50C9A8_item_enchantment_timer = 256;
 						LODWORD(v727) = 1;
--- a/Items.cpp	Mon Sep 09 20:09:01 2013 +0200
+++ b/Items.cpp	Thu Sep 12 09:55:20 2013 +0200
@@ -256,7 +256,7 @@
   this->uAttributes = 0;
   this->uNumCharges = 0;
   this->uSpecEnchantmentType = 0;
-  this->_bonus_strength = 0;
+  this->m_enchantmentStrength = 0;
   this->uEnchantmentType = 0;
   this->uItemID = 0;
   this->uBodyAnchor = 0;
@@ -1255,7 +1255,7 @@
   {
     pItem->uEnchantmentType = pItems[pItem->uItemID]._bonus_type;
     pItem->uSpecEnchantmentType = pItems[pItem->uItemID]._additional_value;
-    pItem->_bonus_strength = pItems[pItem->uItemID]._bonus_strength;
+    pItem->m_enchantmentStrength = pItems[pItem->uItemID]._bonus_strength;
   }
 }
 
@@ -1444,7 +1444,7 @@
 	if ( this->uAttributes & ITEM_TEMP_BONUS || pItemsTable->IsMaterialNonCommon(this) )
 		return uBaseValue;
 	if (uEnchantmentType )
-		return uBaseValue + 100 * _bonus_strength;;
+		return uBaseValue + 100 * m_enchantmentStrength;;
 	if (uSpecEnchantmentType )
 		{
 		bonus = pItemsTable->pSpecialEnchantments[uSpecEnchantmentType].iTreasureLevel;
@@ -1798,12 +1798,12 @@
             ++out_item->uEnchantmentType;
 
             v33 = rand() % (bonus_ranges[v6].maxR - bonus_ranges[v6].minR + 1);
-            out_item->_bonus_strength = v33 + bonus_ranges[v6].minR;
+            out_item->m_enchantmentStrength = v33 + bonus_ranges[v6].minR;
             v32 = out_item->uEnchantmentType - 1;
             if ( v32 == 21 || v32 == 22 || v32 == 23 ) //Armsmaster skill, Dodge skill, Unarmed skill 
-                out_item->_bonus_strength = out_item->_bonus_strength/2;
-            if ( out_item->_bonus_strength <= 0 )
-                out_item->_bonus_strength = 1;
+                out_item->m_enchantmentStrength = out_item->m_enchantmentStrength/2;
+            if ( out_item->m_enchantmentStrength <= 0 )
+                out_item->m_enchantmentStrength = 1;
             return;
             
             }
--- a/Items.h	Mon Sep 09 20:09:01 2013 +0200
+++ b/Items.h	Thu Sep 12 09:55:20 2013 +0200
@@ -196,7 +196,7 @@
 
   int uItemID; //0
   int uEnchantmentType; //4
-  int _bonus_strength;  //8
+  int m_enchantmentStrength;  //8
   int uSpecEnchantmentType; // 25  +5 levels //0c
                             // 16  Drain Hit Points from target.
                             // 35  Increases chance of disarming.
--- a/Player.cpp	Mon Sep 09 20:09:01 2013 +0200
+++ b/Player.cpp	Thu Sep 12 09:55:20 2013 +0200
@@ -156,7 +156,328 @@
    30   // PLAYER_SKILL_PLATE
 };
 
-
+#include <map>
+#include <list>
+
+typedef struct CEnchantment
+{
+  CEnchantment(int bonus, unsigned __int16 Player::* skillPtr = NULL):
+    statBonus(bonus),
+    statPtr(skillPtr)
+    {
+    }
+  int statBonus;
+  unsigned __int16 Player::* statPtr;
+} CEnchantment;
+
+#define NEWBONUSINTOSPECIALLIST(x,y) AddToMap(specialBonusMap, enchId, x, y);
+#define NEWBONUSINTOSPECIALLIST2(x,y,z) AddToMap(specialBonusMap, enchId, x, y, z);
+
+#define NEWBONUSINTOREGULARLIST(x) AddToMap(regularBonusMap, enchId, x);
+
+#define NEWBONUSINTOARTIFACTLIST(x,y) AddToMap(artifactBonusMap, enchId, x, y);
+#define NEWBONUSINTOARTIFACTLIST2(x,y,z) AddToMap(artifactBonusMap, enchId, x, y, z);
+
+std::map<int, std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>* > regularBonusMap;
+std::map<int, std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>* > specialBonusMap;
+std::map<int, std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>* > artifactBonusMap;
+//-------------------------------------------------------------------------
+
+void AddToMap(std::map<int, std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>* > &maptoadd, 
+              int enchId, 
+              CHARACTER_ATTRIBUTE_TYPE attrId, 
+              int bonusValue = 0, 
+              unsigned __int16 Player::* skillPtr = NULL)
+{
+  auto key = maptoadd.find(enchId);
+  std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>* currMap;
+  if (key == maptoadd.end())
+  {
+    currMap = new std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>;
+    maptoadd[enchId] = currMap;
+  }
+  else
+  {
+    currMap = key->second;
+  }
+  Assert(currMap->find(attrId) == currMap->end(), "Attribute %d already present for enchantment %d", attrId, enchId);
+  (*currMap)[attrId] = new CEnchantment(bonusValue, skillPtr);
+}
+//-------------------------------------------------------------------------
+
+void PopulateSpecialBonusMap()
+{
+  int enchId = 1;// of Protection, +10 to all Resistances
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_FIRE, 10);
+  NEWBONUSINTOSPECIALLIST( CHARACTER_ATTRIBUTE_RESIST_AIR, 10);
+  NEWBONUSINTOSPECIALLIST( CHARACTER_ATTRIBUTE_RESIST_WATER, 10);
+  NEWBONUSINTOSPECIALLIST( CHARACTER_ATTRIBUTE_RESIST_EARTH, 10);
+  NEWBONUSINTOSPECIALLIST( CHARACTER_ATTRIBUTE_RESIST_MIND, 10);
+  NEWBONUSINTOSPECIALLIST( CHARACTER_ATTRIBUTE_RESIST_BODY, 10);
+
+  enchId = 2;//of The Gods, +10 to all Seven Statistics
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_STRENGTH, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_INTELLIGENCE, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_WILLPOWER, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ENDURANCE, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ACCURACY, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_SPEED, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_LUCK, 10);
+
+  enchId = 26;//of Air Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_AIR,0, &Player::skillAir);
+
+  enchId = 27;//of Body Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_BODY,0, &Player::skillBody);
+
+  enchId = 28;//of Dark Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_DARK,0, &Player::skillDark);
+
+  enchId = 29;//of Earth Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_EARTH,0, &Player::skillEarth);
+
+  enchId = 30;//of Fire Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_FIRE,0, &Player::skillFire);
+
+  enchId = 31;//of Light Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_LIGHT,0, &Player::skillLight);
+
+  enchId = 32;//of Mind Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_MIND,0, &Player::skillMind);
+
+  enchId = 33;//of Spirit Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_SPIRIT,0, &Player::skillSpirit);
+
+  enchId = 34;//of Water Magic
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_WATER,0, &Player::skillWater);
+
+  enchId = 42;//of Doom
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_STRENGTH, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_INTELLIGENCE, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_WILLPOWER, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ENDURANCE, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ACCURACY, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_SPEED, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_LUCK, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_HEALTH, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_MANA, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_AC_BONUS, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_FIRE, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_AIR, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_WATER, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_EARTH, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_MIND, 1);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_BODY, 1);
+
+  enchId = 43;//of Earth
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ENDURANCE, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_AC_BONUS, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_HEALTH, 10);
+
+  enchId = 44;//of Life
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_HEALTH, 10);
+
+  enchId = 45;//Rogues
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_SPEED, 5);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ACCURACY, 5);
+
+  enchId = 46;//of The Dragon
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_STRENGTH, 25);
+
+  enchId = 47;//of The Eclipse
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_MANA, 10);
+
+  enchId = 48;//of The Golem
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ENDURANCE, 15);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_AC_BONUS, 5);
+
+  enchId = 49;//of The Moon
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_INTELLIGENCE, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_LUCK, 10);
+
+  enchId = 50;//of The Phoenix
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_FIRE, 30);
+
+  enchId = 51;//of The Sky
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_MANA, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_SPEED, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_INTELLIGENCE, 10);
+
+  enchId = 52;//of The Stars
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ENDURANCE, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ACCURACY, 10);
+
+  enchId = 53;//of The Sun
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_STRENGTH, 10);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_WILLPOWER, 10);
+
+  enchId = 54;//of The Troll
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ENDURANCE, 15);
+
+  enchId = 55;//of The Unicorn
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_LUCK, 15);
+
+  enchId = 56;//Warriors
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_STRENGTH, 5);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_ENDURANCE, 5);
+
+  enchId = 57;//Wizards
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_INTELLIGENCE, 5);
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_WILLPOWER, 5);
+
+  enchId = 60;//Monks'
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_DODGE, 3, &Player::skillDodge);
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_UNARMED, 3, &Player::skillUnarmed);
+
+  enchId = 61;//Thieves'
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_TRAP_DISARM, 3, &Player::skillStealing);
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_STEALING, 3, &Player::skillDisarmTrap);
+
+  enchId = 62;//of Identifying
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_ITEM_ID, 3, &Player::skillItemId);
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_MONSTER_ID, 3, &Player::skillMonsterId);
+
+  enchId = 67;//Assassins'
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_TRAP_DISARM, 2, &Player::skillDisarmTrap);
+
+  enchId = 68;//Barbarians'
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_AC_BONUS, 5);
+
+  enchId = 69;//of the Storm
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_AIR, 20);
+
+  enchId = 70;//of the Ocean
+  NEWBONUSINTOSPECIALLIST(CHARACTER_ATTRIBUTE_RESIST_WATER, 10);
+  NEWBONUSINTOSPECIALLIST2(CHARACTER_ATTRIBUTE_SKILL_ALCHEMY, 2, &Player::skillAlchemy);
+}
+//-------------------------------------------------------------------------
+
+void PopulateRegularBonusMap()
+{
+  int enchId = 1;//of Might
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_STRENGTH);
+
+  enchId = 2;//of Thought
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_INTELLIGENCE);
+
+  enchId = 3;//of Charm
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_WILLPOWER);
+
+  enchId = 4;//of Vigor 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_ENDURANCE);
+
+  enchId = 5;//of Precision 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_ACCURACY);
+
+  enchId = 6;//of Speed 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SPEED);
+
+  enchId = 7;//of Luck 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_LUCK);
+
+  enchId = 8;//of Health 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_HEALTH);
+
+  enchId = 9;//of Magic 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_MANA);
+
+  enchId = 10;//of Defense 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_AC_BONUS);
+
+  enchId = 11;//of Fire Resistance 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_RESIST_FIRE);
+
+  enchId = 12;//of Air Resistance 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_RESIST_AIR);
+
+  enchId = 13;//of Water Resistance 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_RESIST_WATER);
+
+  enchId = 14;//of Earth Resistance 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_RESIST_EARTH);
+
+  enchId = 15;//of Mind Resistance 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_RESIST_MIND);
+
+  enchId = 16;//of Body Resistance 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_RESIST_BODY);
+
+  enchId = 17;//of Alchemy 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_ALCHEMY);
+
+  enchId = 18;//of Stealing 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_STEALING);
+
+  enchId = 19;//of Disarming 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_TRAP_DISARM);
+
+  enchId = 20;//of Items 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_ITEM_ID);
+
+  enchId = 21;//of Monsters 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_MONSTER_ID);
+
+  enchId = 22;//of Arms 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_ARMSMASTER);
+
+  enchId = 23;//of Dodging 
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_DODGE);
+
+  enchId = 24;//of the Fist
+  NEWBONUSINTOREGULARLIST(CHARACTER_ATTRIBUTE_SKILL_UNARMED);
+}
+
+//-------------------------------------------------------------------------
+void PopulateArtifactBonusMap()
+{
+  int enchId = 1;//of Might
+  NEWBONUSINTOARTIFACTLIST(CHARACTER_ATTRIBUTE_STRENGTH, 5);
+}
+//-------------------------------------------------------------------------
+
+void Player::GetItemBonusSpecialEnchantment(int enchantmentId, CHARACTER_ATTRIBUTE_TYPE attrToGet, int* additiveBonus, int* halfSkillBonus)
+{
+  auto bonusList = specialBonusMap.find(enchantmentId);
+  if (bonusList == specialBonusMap.end())
+  {
+    return;
+  }
+  std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>* currList = bonusList->second;
+  if (currList->find(attrToGet) != currList->end())
+  {
+    CEnchantment* currBonus = (*currList)[attrToGet];
+    if (currBonus->statPtr != NULL)
+    {
+      if (currBonus->statBonus == 0)
+      {
+        *halfSkillBonus = this->*currBonus->statPtr / 2;
+      }
+      else
+      {
+        if (*additiveBonus < currBonus->statBonus)
+        {
+          *additiveBonus = currBonus->statBonus;
+        }
+      }
+    }
+    else
+    {
+      *additiveBonus += currBonus->statBonus;
+    }
+  }
+}
+
+//-------------------------------------------------------------------------
+bool IsRegularEnchanmentForAttribute(int enchantmentId, CHARACTER_ATTRIBUTE_TYPE attrToGet)
+{
+  auto bonusList = specialBonusMap.find(enchantmentId);
+  if (bonusList == specialBonusMap.end())
+  {
+    return false;
+  }
+  std::map<CHARACTER_ATTRIBUTE_TYPE, CEnchantment*>* currList = bonusList->second;
+  return (currList->find(attrToGet) != currList->end());
+}
 
 //----- (00490913) --------------------------------------------------------
 int PlayerCreation_GetUnspentAttributePointCount()
@@ -1240,6 +1561,11 @@
 //----- (0048C6AF) --------------------------------------------------------
 Player::Player()
 {  
+  if (specialBonusMap.empty())
+  {
+    PopulateSpecialBonusMap();
+  }
+
   memset(&pEquipment, 0, sizeof(PlayerEquipment));
   memset(pInventoryMatrix, 0, 126 * sizeof(int));
   for (uint i = 0; i < 126; ++i)
@@ -1406,49 +1732,49 @@
 //----- (0048C855) --------------------------------------------------------
 int Player::GetBaseStrength()
 {
-  return this->uMight + GetItemsBonus(CHARACTER_ATTRIBUTE_STRENGTH, 0);
+  return this->uMight + GetItemsBonus(CHARACTER_ATTRIBUTE_STRENGTH);
 }
 
 //----- (0048C86C) --------------------------------------------------------
 int Player::GetBaseIntelligence()
 {
-  return this->uIntelligence + GetItemsBonus(CHARACTER_ATTRIBUTE_INTELLIGENCE, 0);
+  return this->uIntelligence + GetItemsBonus(CHARACTER_ATTRIBUTE_INTELLIGENCE);
 }
 
 //----- (0048C883) --------------------------------------------------------
 int Player::GetBaseWillpower()
 {
-  return this->uWillpower + GetItemsBonus(CHARACTER_ATTRIBUTE_WILLPOWER, 0);
+  return this->uWillpower + GetItemsBonus(CHARACTER_ATTRIBUTE_WILLPOWER);
 }
 
 //----- (0048C89A) --------------------------------------------------------
 int Player::GetBaseEndurance()
 {
-  return this->uEndurance + GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0);
+  return this->uEndurance + GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE);
 }
 
 //----- (0048C8B1) --------------------------------------------------------
 int Player::GetBaseAccuracy()
 {
-  return this->uAccuracy + GetItemsBonus(CHARACTER_ATTRIBUTE_ACCURACY, 0);
+  return this->uAccuracy + GetItemsBonus(CHARACTER_ATTRIBUTE_ACCURACY);
 }
 
 //----- (0048C8C8) --------------------------------------------------------
 int Player::GetBaseSpeed()
 {
-  return this->uSpeed + GetItemsBonus(CHARACTER_ATTRIBUTE_SPEED, 0);
+  return this->uSpeed + GetItemsBonus(CHARACTER_ATTRIBUTE_SPEED);
 }
 
 //----- (0048C8DF) --------------------------------------------------------
 int Player::GetBaseLuck()
 {
-  return this->uLuck + GetItemsBonus(CHARACTER_ATTRIBUTE_LUCK, 0);
+  return this->uLuck + GetItemsBonus(CHARACTER_ATTRIBUTE_LUCK);
 }
 
 //----- (0048C8F6) --------------------------------------------------------
 int Player::GetBaseLevel()
 {
-  return this->uLevel + GetItemsBonus(CHARACTER_ATTRIBUTE_LEVEL, 0);
+  return this->uLevel + GetItemsBonus(CHARACTER_ATTRIBUTE_LEVEL);
 }
 
 //----- (0048C90D) --------------------------------------------------------
@@ -1456,7 +1782,7 @@
 {
   return uLevel + sLevelModifier +
          GetMagicalBonus(CHARACTER_ATTRIBUTE_LEVEL) +
-         GetItemsBonus(CHARACTER_ATTRIBUTE_LEVEL, 0);
+         GetItemsBonus(CHARACTER_ATTRIBUTE_LEVEL);
 }
 
 //----- (0048C93C) --------------------------------------------------------
@@ -1527,7 +1853,7 @@
 
   auto uConditionMult = pConditionAttributeModifier[attrId][GetMajorConditionIdx()];
   int magicBonus = GetMagicalBonus(attrId);
-  int itemBonus = GetItemsBonus(attrId, 0);
+  int itemBonus = GetItemsBonus(attrId);
   return uConditionMult * uAgeingMultiplier * this->*attrValue / 100 / 100
     + magicBonus
     + itemBonus
@@ -1560,7 +1886,7 @@
  
   v2 = GetActualMight();
   v3 = GetParameterBonus(v2);
-  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, 0) + v3;
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN) + v3;
   v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v4;
   result = _melee_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v5;
   if ( result < 1 )
@@ -1580,7 +1906,7 @@
 
   v2 = GetActualMight();
   v3 = GetParameterBonus(v2);
-  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, 0) + v3;
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX) + v3;
   v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v4;
   v6 = this->_melee_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_BONUS) + v5;
   result = 1;
@@ -1700,7 +2026,7 @@
   {
     v4 = GetActualAccuracy();
     v5 = GetParameterBonus(v4);
-    v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_ATTACK, 0) + v5;
+    v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_ATTACK) + v5;
     v7 = GetSkillBonus(CHARACTER_ATTRIBUTE_RANGED_ATTACK) + v6;
     v3 = this->_ranged_atk_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_RANGED_ATTACK) + v7;
   }
@@ -1719,7 +2045,7 @@
   int v4; // edi@1
   int result; // eax@6
 
-  v2 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_MIN, 0);
+  v2 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_MIN);
   v3 = GetSkillBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_BONUS) + v2;
   v4 = this->_ranged_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_BONUS) + v3;
   if ( v4 >= 1 )
@@ -1737,7 +2063,7 @@
   int v4; // edi@1
   int result; // eax@6
 
-  v2 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_MAX, 0);
+  v2 = GetItemsBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_MAX);
   v3 = GetSkillBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_BONUS) + v2;
   v4 = this->_ranged_dmg_bonus + GetMagicalBonus(CHARACTER_ATTRIBUTE_RANGED_DMG_BONUS) + v3;
   if ( v4 >= 1 )
@@ -1813,8 +2139,8 @@
   }
   else if (pEquipment.uMainHand >= 0 && (itemid == ITEM_BLASTER || itemid == ITEM_LASER_RIFLE))
   {
-    min_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, 1);
-    max_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, 1);
+    min_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, true);
+    max_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, true);
   }
   else
   {
@@ -1853,8 +2179,8 @@
     }
     else if (pEquipment.uMainHand >= 0 && (itemid == ITEM_BLASTER || itemid == ITEM_LASER_RIFLE))
     {
-      min_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, 1);
-      max_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, 1);
+      min_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MIN, true);
+      max_damage = GetItemsBonus(CHARACTER_ATTRIBUTE_MELEE_DMG_MAX, true);
     }
     else
     {
@@ -2261,7 +2587,7 @@
   broke_armor = sHealth <= -10;
   if ( sHealth < 1 ) //
   {
-    if ( (sHealth + uEndurance + GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0) >= 1)
+    if ( (sHealth + uEndurance + GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE) >= 1)
       || pPlayerBuffs[PLAYER_BUFF_PRESERVATION].uExpireTime > 0 )
     {
       SetCondUnconsciousWithBlockCheck(false);
@@ -2663,23 +2989,18 @@
   uint      weapon_recovery = base_recovery_times_per_weapon_type[0];
   if (bRangedAttack)
   {
-    if ( !HasItemEquipped(EQUIP_BOW) )
-      goto LABEL_17;
-    weapon = &pInventoryItemList[pEquipment.uBow - 1];
-    weapon_desc = &pItemsTable->pItems[weapon->uItemID];
-    weapon_recovery = base_recovery_times_per_weapon_type[weapon_desc->uSkillType];
-    goto LABEL_17;
-  }
-  else if ( IsUnarmed() == 1 )
-  {
-    if (GetActualSkillLevel(PLAYER_SKILL_UNARMED))
-    {
+    if ( HasItemEquipped(EQUIP_BOW) )
+    {
+      weapon = &pInventoryItemList[pEquipment.uBow - 1];
+      weapon_desc = &pItemsTable->pItems[weapon->uItemID];
+      weapon_recovery = base_recovery_times_per_weapon_type[weapon_desc->uSkillType];
+    }
+  }
+  else if ( IsUnarmed() == 1 && GetActualSkillLevel(PLAYER_SKILL_UNARMED) > 0)
+  {
       weapon_recovery = base_recovery_times_per_weapon_type[1];
-      goto LABEL_17;
-    }
-  }
-
-  if ( HasItemEquipped(EQUIP_MAIN_HAND) )
+  }
+  else if ( HasItemEquipped(EQUIP_MAIN_HAND) )
   {
     weapon = &pInventoryItemList[pEquipment.uMainHand - 1];
     weapon_desc = &pItemsTable->pItems[weapon->uItemID];
@@ -2705,58 +3026,43 @@
     }
   }
 
-LABEL_17:
   uint armour_recovery = 0;
   if ( HasItemEquipped(EQUIP_ARMOUR) )
   {
     auto armour_skill_type = pItemsTable->pItems[pInventoryItemList[pEquipment.uArmor - 1].uItemID].uSkillType;
     uint base_armour_recovery = base_recovery_times_per_weapon_type[armour_skill_type];
-
-    float armour_recovery_multipliers[4];
+    float multiplier;
+
     if (armour_skill_type == PLAYER_SKILL_LEATHER)
     {
-      armour_recovery_multipliers[0] = 1.0f;
-      armour_recovery_multipliers[1] = 0;
-      armour_recovery_multipliers[2] = 0;
-      armour_recovery_multipliers[3] = 0;
+      multiplier = GetArmorRecoveryMultiplierFromSkillLevel(armour_skill_type, 1.0f, 0, 0, 0);
     }
     else if (armour_skill_type == PLAYER_SKILL_CHAIN)
     {
-      armour_recovery_multipliers[0] = 1.0f;
-      armour_recovery_multipliers[1] = 0.5f;
-      armour_recovery_multipliers[2] = 0;
-      armour_recovery_multipliers[3] = 0;
+      multiplier = GetArmorRecoveryMultiplierFromSkillLevel(armour_skill_type, 1.0f, 0.5f, 0, 0);
     }
     else if (armour_skill_type == PLAYER_SKILL_PLATE)
     {
-      armour_recovery_multipliers[0] = 1.0f;
-      armour_recovery_multipliers[1] = 0.5f;
-      armour_recovery_multipliers[2] = 0.5f;
-      armour_recovery_multipliers[3] = 0;
+      multiplier = GetArmorRecoveryMultiplierFromSkillLevel(armour_skill_type, 1.0f, 0.5f, 0.5f, 0);
     }
     else
     {
       Error("Unknown armour type"); // what kind of armour is that?
-      armour_recovery_multipliers[0] = 1.0f;
-      armour_recovery_multipliers[1] = 1.0f;
-      armour_recovery_multipliers[2] = 1.0f;
-      armour_recovery_multipliers[3] = 1.0f;
-    }
-
-    uint skill_mastery = SkillToMastery(pActiveSkills[armour_skill_type]);
-    armour_recovery = base_armour_recovery * armour_recovery_multipliers[skill_mastery - 1];
+      multiplier = GetArmorRecoveryMultiplierFromSkillLevel(armour_skill_type, 1.0f, 1.0f, 1.0f, 1.0f);
+    }
+
+    armour_recovery = (uint)(base_armour_recovery * multiplier);
   }
 
   uint shield_recovery = 0;
   if (HasItemEquipped(EQUIP_OFF_HAND) && GetEquippedItemEquipType(EQUIP_OFF_HAND) == EQUIP_SHIELD)
   {
-    float shield_recovery_multipliers[4] = {1, 0, 0, 0};
-
     auto shield = &pInventoryItemList[pEquipment.uShield - 1];
     auto skill_type = pItemsTable->pItems[shield->uItemID].uSkillType;
 
     uint shield_base_recovery = base_recovery_times_per_weapon_type[skill_type];
-    shield_recovery = shield_base_recovery * SkillToMastery(pActiveSkills[skill_type]);
+    float multiplier = GetArmorRecoveryMultiplierFromSkillLevel(skill_type, 1.0f, 0, 0, 0);
+    shield_recovery = (uint)(shield_base_recovery * multiplier);
   }
 
   uint player_speed_recovery_reduction = GetParameterBonus(GetActualSpeed()),
@@ -2785,9 +3091,9 @@
     }
   }
 
-  uint v41 = 0;
-  if (pPlayerBuffs[PLAYER_BUFF_7].uExpireTime > 0)
-    v41 = 25;
+  uint hasteRecoveryReduction = 0;
+  if (pPlayerBuffs[PLAYER_BUFF_7].uExpireTime > 0 || pParty->pPartyBuffs[PARTY_BUFF_HASTE].uExpireTime > 0 )
+    hasteRecoveryReduction = 25;
 
   uint weapon_enchantment_recovery_reduction = 0;
   if ( weapon  )
@@ -2798,13 +3104,12 @@
       weapon_enchantment_recovery_reduction = 20;
   }
 
-
   int recovery = weapon_recovery +
                  armour_recovery +
                  shield_recovery
                  - armsmaster_recovery_reduction
                  - weapon_enchantment_recovery_reduction
-                 - v41
+                 - hasteRecoveryReduction
                  - sword_axe_bow_recovery_reduction
                  - player_speed_recovery_reduction;
 
@@ -2813,6 +3118,22 @@
   return recovery;
 }
 
+
+//----- new --------------------------------------------------------
+float Player::GetArmorRecoveryMultiplierFromSkillLevel( unsigned char armour_skill_type, float mult1, float mult2, float mult3, float mult4 )
+{
+  uint skill_mastery = SkillToMastery(pActiveSkills[armour_skill_type]);
+  switch (skill_mastery)
+  {
+    case 1: return mult1; break;
+    case 2: return mult2; break;
+    case 3: return mult3; break;
+    case 4: return mult4; break;
+  }
+  Error("Unexpected input value: %d", armour_skill_type);
+  return 0;
+}
+
 //----- (0048E4F8) --------------------------------------------------------
 int Player::GetMaxHealth()
 {
@@ -2825,10 +3146,8 @@
   v6 = uFullHealthBonus
      + pBaseHealthByClass[classType / 4]
      + GetSkillBonus(CHARACTER_ATTRIBUTE_HEALTH)
-     + GetItemsBonus(CHARACTER_ATTRIBUTE_HEALTH, 0) + v4;
-  if (v6 <= 0)
-    return 1;
-  return v6;
+     + GetItemsBonus(CHARACTER_ATTRIBUTE_HEALTH) + v4;
+  return max(1, v6);
 }
 
 //----- (0048E565) --------------------------------------------------------
@@ -2842,7 +3161,6 @@
   int v7; // esi@6
   int v8; // esi@6
   int v9; // esi@6
-  int result; // eax@7
   
   switch (classType)
   {
@@ -2891,7 +3209,7 @@
       break;
   }
   v7 = pBaseManaPerLevelByClass[classType] * (GetActualLevel() + v3);
-  v8 = GetItemsBonus(CHARACTER_ATTRIBUTE_MANA, 0) + v7;
+  v8 = GetItemsBonus(CHARACTER_ATTRIBUTE_MANA) + v7;
   v9 = uFullManaBonus
       + pBaseManaByClass[classType / 4]
   + GetSkillBonus(CHARACTER_ATTRIBUTE_MANA)
@@ -2902,53 +3220,39 @@
 //----- (0048E656) --------------------------------------------------------
 int Player::GetBaseAC()
 {
-  Player *v1; // edi@1
   int v2; // eax@1
   int v3; // esi@1
   int v4; // esi@1
   int v5; // esi@1
-  int result; // eax@2
-
-  v1 = this;
+
   v2 = GetActualSpeed();
   v3 = GetParameterBonus(v2);
-  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_AC_BONUS, 0) + v3;
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v3;
   v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v4;
-  if ( v5 >= 1 )
-    result = v5;
-  else
-    result = 0;
-  return result;
+  return max(0, v5);
 }
 
 //----- (0048E68F) --------------------------------------------------------
 int Player::GetActualAC()
 {
-  Player *v1; // edi@1
   int v2; // eax@1
   int v3; // esi@1
   int v4; // esi@1
   int v5; // esi@1
   int v6; // esi@1
-  int result; // eax@2
-
-  v1 = this;
+
   v2 = GetActualSpeed();
   v3 = GetParameterBonus(v2);
-  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_AC_BONUS, 0) + v3;
+  v4 = GetItemsBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v3;
   v5 = GetSkillBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v4;
-  v6 = v1->sACModifier + GetMagicalBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v5;
-  if ( v6 >= 1 )
-    result = v6;
-  else
-    result = 0;
-  return result;
+  v6 = this->sACModifier + GetMagicalBonus(CHARACTER_ATTRIBUTE_AC_BONUS) + v5;
+  return max(0, v6);
 }
 
 //----- (0048E6DC) --------------------------------------------------------
 unsigned int Player::GetBaseAge()
 {
-  return ((__int64)(pParty->uTimePlayed * 0.234375) / 60 / 60 / 24) / 7 / 4 / 12 - uBirthYear + game_starting_year;
+  return (unsigned int)(((__int64)(pParty->uTimePlayed * 0.234375) / 60 / 60 / 24) / 7 / 4 / 12 - uBirthYear + game_starting_year);
 }
 
 //----- (0048E72C) --------------------------------------------------------
@@ -2960,155 +3264,100 @@
 //----- (0048E73F) --------------------------------------------------------
 int Player::GetBaseResistance(enum CHARACTER_ATTRIBUTE_TYPE a2)
 {
-  Player *v2; // ebx@1
-  signed int v3; // esi@1
-  enum CHARACTER_RACE v4; // eax@1
-  signed int v5; // edi@8
-  char v6; // zf@9
   int v7; // esi@20
-  int result; // eax@21
-  signed int v9; // [sp-4h] [bp-10h]@11
-
-  v2 = this;
-  v3 = 0;
-  v4 = GetRace();
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_FIRE )
-  {
-    v5 = 0;
-    goto LABEL_16;
-  }
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_AIR )
-  {
-    v5 = 1;
-LABEL_16:
-    v6 = v4 == 2;
-    goto LABEL_17;
-  }
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_WATER )
-  {
-    v6 = v4 == 3;
-    v5 = 2;
-    goto LABEL_17;
-  }
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_EARTH )
-  {
-    v5 = 3;
-    v6 = v4 == 3;
-    goto LABEL_17;
-  }
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_MIND )
-  {
-    v5 = 7;
-    if ( v4 != 1 )
-      goto LABEL_20;
-    v9 = 10;
-LABEL_19:
-    v3 = v9;
-    goto LABEL_20;
-  }
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_BODY || a2 == 33 )
-  {
-    v5 = 8;
-    v6 = v4 == 0;
-LABEL_17:
-    if ( !v6 )
-      goto LABEL_20;
-    v9 = 5;
-    goto LABEL_19;
-  }
-  v5 = 0;
-LABEL_20:
-  v7 = GetItemsBonus(a2, 0) + v3;
-  if ( v2->classType != PLAYER_CLASS_LICH || (result = 200, v7 + *(&v2->sResFireBase + v5) <= 200) )
-    result = v7 + *(&v2->sResFireBase + v5);
-  return result;
+  int racialBonus = 0;
+  __int16* resStat;
+
+  switch (a2)
+  {
+    case CHARACTER_ATTRIBUTE_RESIST_FIRE:
+      resStat = &sResFireBase;
+      if (IsRaceGoblin())
+        racialBonus = 5;
+      break;
+    case CHARACTER_ATTRIBUTE_RESIST_AIR:
+      resStat = &sResAirBase;
+      if (IsRaceGoblin())
+        racialBonus = 5;
+      break;
+    case  CHARACTER_ATTRIBUTE_RESIST_WATER:
+      resStat = &sResWaterBase;
+      if (IsRaceDwarf())
+        racialBonus = 5;
+      break;
+    case CHARACTER_ATTRIBUTE_RESIST_EARTH:
+      resStat = &sResEarthBase;
+      if (IsRaceDwarf())
+        racialBonus = 5;
+    break;
+    case CHARACTER_ATTRIBUTE_RESIST_MIND:
+      resStat = &sResMindBase;
+      if (IsRaceElf())
+        racialBonus = 10;
+      break;
+    case CHARACTER_ATTRIBUTE_RESIST_BODY:
+    case CHARACTER_ATTRIBUTE_RESIST_SPIRIT:
+      resStat = &sResBodyBase;
+      if (IsRaceHuman())
+        racialBonus = 5;
+      break;
+  }
+  v7 = GetItemsBonus(a2) + racialBonus;
+  return v7 + *resStat;
 }
 
 //----- (0048E7D0) --------------------------------------------------------
 int Player::GetActualResistance(enum CHARACTER_ATTRIBUTE_TYPE a2)
 {
-  signed int v2; // edi@1
-  Player *v3; // esi@1
-  enum CHARACTER_RACE v4; // ebx@1
-  char v6; // zf@18
-  int v7; // ebx@28
-  int result; // eax@28
-  signed int v9; // [sp+10h] [bp-8h]@1
-  signed int v10; // [sp+14h] [bp-4h]@1
-
-  v2 = 0;
-  v3 = this;
-  v10 = 0;
-  v9 = 0;
-  v4 = GetRace();
+  signed int v10 = 0; // [sp+14h] [bp-4h]@1
+  __int16* resStat;
+  int result;
+  int baseRes;
+
+  int leatherArmorSkillLevel = GetActualSkillLevel(PLAYER_SKILL_LEATHER);
   if ( CheckHiredNPCSpeciality(Enchanter) )
     v10 = 20;
   if ( (a2 == CHARACTER_ATTRIBUTE_RESIST_FIRE
      || a2 == CHARACTER_ATTRIBUTE_RESIST_AIR
      || a2 == CHARACTER_ATTRIBUTE_RESIST_WATER
      || a2 == CHARACTER_ATTRIBUTE_RESIST_EARTH)
-    && SkillToMastery(v3->pActiveSkills[9]) == 4
+    && SkillToMastery(leatherArmorSkillLevel) == 4
     && HasItemEquipped(EQUIP_ARMOUR)
     && GetEquippedItemSkillType(EQUIP_ARMOUR) == PLAYER_SKILL_LEATHER )
-    v10 += v3->pActiveSkills[9] & 0x3F;
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_FIRE )
-    goto LABEL_25;
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_AIR )
-  {
-    v2 = 1;
-LABEL_25:
-    v6 = v4 == 2;
-LABEL_26:
-    if ( v6 )
-      v9 = 5;
-    goto LABEL_28;
-  }
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_WATER )
-  {
-    v6 = v4 == 3;
-    v2 = 2;
-    goto LABEL_26;
-  }
-  if ( a2 == CHARACTER_ATTRIBUTE_RESIST_EARTH )
-  {
-    v2 = 3;
-    if ( v4 == 3 )
-      v10 += 5;
-  }
-  else
-  {
-    if ( a2 != CHARACTER_ATTRIBUTE_RESIST_MIND )
-    {
-      if ( a2 != CHARACTER_ATTRIBUTE_RESIST_BODY && a2 != 33 )
-        goto LABEL_28;
-      v2 = 8;
-      v6 = v4 == 0;
-      goto LABEL_26;
-    }
-    v2 = 7;
-    if ( v4 == 1 )
-      v9 = 10;
-  }
-LABEL_28:
-  v7 = GetItemsBonus(a2, 0);
-  result = v10 + GetMagicalBonus(a2) + v7 + v9 + *(&v3->sResFireBonus + v2) + *(&v3->sResFireBase + v2);
-  if ( v3->classType == PLAYER_CLASS_LICH )
-  {
-    if ( result > 200 )
-      result = 200;
-  }
+    v10 += leatherArmorSkillLevel & 0x3F;
+  switch (a2)
+  {
+  case CHARACTER_ATTRIBUTE_RESIST_FIRE:
+    resStat = &sResFireBonus;
+    break;
+  case CHARACTER_ATTRIBUTE_RESIST_AIR:
+    resStat = &sResAirBonus;
+    break;
+  case  CHARACTER_ATTRIBUTE_RESIST_WATER:
+    resStat = &sResWaterBonus;
+    break;
+  case CHARACTER_ATTRIBUTE_RESIST_EARTH:
+    resStat = &sResEarthBonus;
+    break;
+  case CHARACTER_ATTRIBUTE_RESIST_MIND:
+    resStat = &sResMindBonus;
+    break;
+  case CHARACTER_ATTRIBUTE_RESIST_BODY:
+  case CHARACTER_ATTRIBUTE_RESIST_SPIRIT:
+    resStat = &sResBodyBonus;
+    break;
+  }
+  baseRes = GetBaseResistance(a2);
+  result = v10 + GetMagicalBonus(a2) + baseRes + *(resStat);
   return result;
 }
 
 //----- (0048E8F5) --------------------------------------------------------
 bool Player::Recover(int dt)
 {
-  //Player *v2; // esi@1
-  signed __int64 v3; // qax@1
-  //bool result; // eax@4
-
-  //v2 = this;
-  v3 = (signed __int64)((double)(dt * _48EA46_calc_special_bonus_by_items(17)) * 0.01 + (double)dt);
+  int v3; // qax@1
+
+  v3 = (int)(dt * GetSpecialItemBonus(17) * 0.01 + dt);
 
   Log::Warning(L"Recover(dt = %u/%u - %u", dt, (uint)v3, (uint)uTimeToRecovery);
 
@@ -3161,49 +3410,48 @@
 
 //----- (0048EA1B) --------------------------------------------------------
 int Player::GetParameterBonus( int player_parameter )
-    {
+{
   int i; // eax@1
   i = 0;
   while (param_to_bonus_table[i])
-      { 
-      if (player_parameter >= param_to_bonus_table[i])
-          break;
-      ++i;    
-      }   
+  { 
+    if (player_parameter >= param_to_bonus_table[i])
+      break;
+    ++i;    
+  }   
   return parameter_to_bonus_value[i];
 }
 
 //----- (0048EA46) --------------------------------------------------------
-int Player::_48EA46_calc_special_bonus_by_items(int a2)
+int Player::GetSpecialItemBonus( int enchantmentId )
 {
   int inv_indx; // eax@3
 
-  for (int i=EQUIP_OFF_HAND; i<EQUIP_BOOK; ++i )
-      {
-      if ( !HasItemEquipped((ITEM_EQUIP_TYPE)i) )
-          continue;
+  for (int i = EQUIP_OFF_HAND; i < EQUIP_BOOK; ++i )
+  {
+    if ( HasItemEquipped((ITEM_EQUIP_TYPE)i) )
+    {
       inv_indx = pEquipment.pIndices[i]  - 1;
-      if (a2==17)
-          {
-          if ((pInventoryItemList[inv_indx].uSpecEnchantmentType==17)||(pInventoryItemList[inv_indx].uItemID==533)) //Elven Chainmail+Increases rate of Recovery
-              return 50;
-          }
-      if (a2==24)
-          {
-          if (pInventoryItemList[inv_indx].uSpecEnchantmentType==24) //Increased Knockback.
-              return 5;
-          }
+      if (enchantmentId == 17)
+      {
+        if ((pInventoryItemList[inv_indx].uSpecEnchantmentType == 17) || (pInventoryItemList[inv_indx].uItemID == 533)) //Elven Chainmail+Increases rate of Recovery
+          return 50;
       }
+      if (enchantmentId == 24) 
+      {
+        if (pInventoryItemList[inv_indx].uSpecEnchantmentType == 24) //Increased Knockback.
+          return 5;
+      }
+    }
+  }
   return 0;
 }
 
 //----- (0048EAAE) --------------------------------------------------------
-int Player::GetItemsBonus(CHARACTER_ATTRIBUTE_TYPE attr, int a3)
-{
-  CHARACTER_ATTRIBUTE_TYPE v3; // esi@1
+int Player::GetItemsBonus( enum CHARACTER_ATTRIBUTE_TYPE attr, bool getOnlyMainHandDmg /*= false*/ )
+{
  // signed int v4; // eax@1
   int v5; // edi@1
-  Player *v6; // ebx@1
   Player *v8; // ecx@48
   int v9; // eax@49
   int v10; // edx@49
@@ -3264,61 +3512,57 @@
   unsigned int v65; // [sp+24h] [bp+8h]@95
   bool no_skills;
 
-  v3 = attr;
   v5 = 0;
-  v6 = this;
   v62 = 0;
   v61 = 0;
 
   
   no_skills=false;
   switch (attr)
-      {
-  case  CHARACTER_ATTRIBUTE_SKILL_ALCHEMY:      v58 = PLAYER_SKILL_ALCHEMY;      break;
-  case  CHARACTER_ATTRIBUTE_SKILL_STEALING:     v58 = PLAYER_SKILL_STEALING;     break;
-  case  CHARACTER_ATTRIBUTE_SKILL_TRAP_DISARM:  v58 = PLAYER_SKILL_TRAP_DISARM;  break;
-  case  CHARACTER_ATTRIBUTE_SKILL_ITEM_ID:      v58 = PLAYER_SKILL_ITEM_ID;      break;
-  case  CHARACTER_ATTRIBUTE_SKILL_MONSTER_ID:   v58 = PLAYER_SKILL_MONSTER_ID;   break;
-  case  CHARACTER_ATTRIBUTE_SKILL_ARMSMASTER:   v58 = PLAYER_SKILL_ARMSMASTER;   break;
-  case  CHARACTER_ATTRIBUTE_SKILL_DODGE:        v58 = PLAYER_SKILL_DODGE;        break;
-  case  CHARACTER_ATTRIBUTE_SKILL_UNARMED:      v58 = PLAYER_SKILL_UNARMED;      break;
-  case  CHARACTER_ATTRIBUTE_SKILL_FIRE:         v58 = PLAYER_SKILL_FIRE;         break;
-  case  CHARACTER_ATTRIBUTE_SKILL_AIR:          v58 = PLAYER_SKILL_AIR;          break;
-  case  CHARACTER_ATTRIBUTE_SKILL_WATER:        v58 = PLAYER_SKILL_WATER;        break;
-  case  CHARACTER_ATTRIBUTE_SKILL_EARTH:        v58 = PLAYER_SKILL_EARTH;        break;
-  case  CHARACTER_ATTRIBUTE_SKILL_SPIRIT:       v58 = PLAYER_SKILL_SPIRIT;       break;
-  case  CHARACTER_ATTRIBUTE_SKILL_MIND:         v58 = PLAYER_SKILL_MIND;         break;
-  case  CHARACTER_ATTRIBUTE_SKILL_BODY:         v58 = PLAYER_SKILL_BODY;         break;
-  case  CHARACTER_ATTRIBUTE_SKILL_LIGHT:        v58 = PLAYER_SKILL_LIGHT;        break;
-  case  CHARACTER_ATTRIBUTE_SKILL_DARK:         v58 = PLAYER_SKILL_DARK;         break;
-  case  CHARACTER_ATTRIBUTE_SKILL_MEDITATION:   v58 = PLAYER_SKILL_MEDITATION;   break;
-  case  CHARACTER_ATTRIBUTE_SKILL_BOW:          v58 = PLAYER_SKILL_BOW;          break;
-  case  CHARACTER_ATTRIBUTE_SKILL_SHIELD:       v58 = PLAYER_SKILL_SHIELD;       break;
-  case  CHARACTER_ATTRIBUTE_SKILL_LEARNING:     v58 = PLAYER_SKILL_LEARNING;     break;
-  default:
+  {
+    case  CHARACTER_ATTRIBUTE_SKILL_ALCHEMY:      v58 = PLAYER_SKILL_ALCHEMY;      break;
+    case  CHARACTER_ATTRIBUTE_SKILL_STEALING:     v58 = PLAYER_SKILL_STEALING;     break;
+    case  CHARACTER_ATTRIBUTE_SKILL_TRAP_DISARM:  v58 = PLAYER_SKILL_TRAP_DISARM;  break;
+    case  CHARACTER_ATTRIBUTE_SKILL_ITEM_ID:      v58 = PLAYER_SKILL_ITEM_ID;      break;
+    case  CHARACTER_ATTRIBUTE_SKILL_MONSTER_ID:   v58 = PLAYER_SKILL_MONSTER_ID;   break;
+    case  CHARACTER_ATTRIBUTE_SKILL_ARMSMASTER:   v58 = PLAYER_SKILL_ARMSMASTER;   break;
+    case  CHARACTER_ATTRIBUTE_SKILL_DODGE:        v58 = PLAYER_SKILL_DODGE;        break;
+    case  CHARACTER_ATTRIBUTE_SKILL_UNARMED:      v58 = PLAYER_SKILL_UNARMED;      break;
+    case  CHARACTER_ATTRIBUTE_SKILL_FIRE:         v58 = PLAYER_SKILL_FIRE;         break;
+    case  CHARACTER_ATTRIBUTE_SKILL_AIR:          v58 = PLAYER_SKILL_AIR;          break;
+    case  CHARACTER_ATTRIBUTE_SKILL_WATER:        v58 = PLAYER_SKILL_WATER;        break;
+    case  CHARACTER_ATTRIBUTE_SKILL_EARTH:        v58 = PLAYER_SKILL_EARTH;        break;
+    case  CHARACTER_ATTRIBUTE_SKILL_SPIRIT:       v58 = PLAYER_SKILL_SPIRIT;       break;
+    case  CHARACTER_ATTRIBUTE_SKILL_MIND:         v58 = PLAYER_SKILL_MIND;         break;
+    case  CHARACTER_ATTRIBUTE_SKILL_BODY:         v58 = PLAYER_SKILL_BODY;         break;
+    case  CHARACTER_ATTRIBUTE_SKILL_LIGHT:        v58 = PLAYER_SKILL_LIGHT;        break;
+    case  CHARACTER_ATTRIBUTE_SKILL_DARK:         v58 = PLAYER_SKILL_DARK;         break;
+    case  CHARACTER_ATTRIBUTE_SKILL_MEDITATION:   v58 = PLAYER_SKILL_MEDITATION;   break;
+    case  CHARACTER_ATTRIBUTE_SKILL_BOW:          v58 = PLAYER_SKILL_BOW;          break;
+    case  CHARACTER_ATTRIBUTE_SKILL_SHIELD:       v58 = PLAYER_SKILL_SHIELD;       break;
+    case  CHARACTER_ATTRIBUTE_SKILL_LEARNING:     v58 = PLAYER_SKILL_LEARNING;     break;
+    default:
       no_skills=true;
-      }
+  }
   if (!no_skills)
-      {
-      if ( !this->pActiveSkills[v58] )
-        return 0;
-      }
+  {
+    if ( !this->pActiveSkills[v58] )
+      return 0;
+  }
 
   if ( (signed int)attr > 28 )
   {
-    if ( (signed int)attr < 29 )
-      return v5 + v62 + v61;
-    if ( (signed int)attr <= CHARACTER_ATTRIBUTE_RANGED_DMG_BONUS )
+    if ( attr == CHARACTER_ATTRIBUTE_RANGED_DMG_BONUS || attr == CHARACTER_ATTRIBUTE_RANGED_ATTACK)
     {
       if ( HasItemEquipped(EQUIP_BOW) )
-        v5 = pItemsTable->pItems[v6->pOwnItems[v6->pEquipment.uBow-1].uItemID].uDamageMod;
+        v5 = pItemsTable->pItems[this->pOwnItems[this->pEquipment.uBow-1].uItemID].uDamageMod;
       return v5 + v62 + v61;
     }
     if ( attr == CHARACTER_ATTRIBUTE_RANGED_DMG_MIN )
     {
       if ( !HasItemEquipped(EQUIP_BOW) )
         return v5 + v62 + v61;
-      v57 = v6->pOwnItems[v6->pEquipment.uBow-1].uItemID;
+      v57 = this->pOwnItems[this->pEquipment.uBow-1].uItemID;
       v5 = pItemsTable->pItems[v57].uDamageMod;
       v56 = pItemsTable->pItems[v57].uDamageDice;
       v5 += v56;
@@ -3328,11 +3572,9 @@
     {
       if ( !HasItemEquipped(EQUIP_BOW) )
         return v5 + v62 + v61;
-      v20 = v6->pOwnItems[v6->pEquipment.uBow-1].uItemID;
+      v20 = this->pOwnItems[this->pEquipment.uBow-1].uItemID;
       v5 = pItemsTable->pItems[v20].uDamageDice * pItemsTable->pItems[v20].uDamageRoll;
-LABEL_365:
       v56 = pItemsTable->pItems[v20].uDamageMod;
-LABEL_366:
       v5 += v56;
       return v5 + v62 + v61;
     }
@@ -3344,560 +3586,298 @@
     {
       if ( !HasItemEquipped((ITEM_EQUIP_TYPE)v65) )
         goto LABEL_361;
-      v31 = *(&v6->pEquipment.uShield + v65) - 1;
-      if ( v3 == 9 )
+      v31 = this->pEquipment.pIndices[v65] - 1;
+      if ( attr == CHARACTER_ATTRIBUTE_AC_BONUS )
       {
         v32 = GetEquippedItemEquipType((ITEM_EQUIP_TYPE)v65);
-        if ( v32 >= 3 )
+        if ( v32 >= 3 && v32 <= 11 )
         {
-          if ( v32 <= 11 )
-          {
-            v33 = v6->pInventoryItemList[v31].uItemID;
-            v5 += pItemsTable->pItems[v33].uDamageDice + pItemsTable->pItems[v33].uDamageMod;
-          }
+          v33 = this->pInventoryItemList[v31].uItemID;
+          v5 += pItemsTable->pItems[v33].uDamageDice + pItemsTable->pItems[v33].uDamageMod;
         }
       }
-      v63 = (int)((char *)v6 + 36 * v31);
+      v63 = (int)((char *)this + 36 * v31);
       attra = (ItemGen *)(v63 + 532);
-      if ( pItemsTable->IsMaterialNonCommon((ItemGen *)(v63 + 532)) == 1
+      if ( pItemsTable->IsMaterialNonCommon((ItemGen *)(attra)) == 1
         && !pItemsTable->IsMaterialSpecial(attra) )
       {
         v34 = attra->uItemID;
         switch ( attra->uItemID )
         {
-          case 0x1F4u:
-            v35 = v3 == 5;
-            goto LABEL_105;
-          case 0x1F5u:
-            v36 = v3 == 0;
-            goto LABEL_108;
-          case 0x1F6u:
-            if ( v3 == 21 )
+          case ITEM_ARTIFACT_PUCK:
+            if ( attr == 5 )
+              v5 += 50;
+            goto LABEL_361;
+          case ITEM_ARTIFACT_IRON_FEATHER:
+            if ( attr == 0 )
+              v5 += 40;
+            goto LABEL_361;
+          case ITEM_ARTIFACT_WALLACE:
+            if ( attr == 21 )
               v61 += 10;
-            v36 = v3 == 2;
-            goto LABEL_108;
-          case 0x1F7u:
-            if ( v3 == 17 )
+            if ( attr == 2 )
+              v5 += 40;
+            goto LABEL_361;
+          case ITEM_ARTIFACT_CORSAIR:
+            if ( attr == 17 )
               v61 += 5;
-            if ( v3 == 18 )
+            if ( attr == 18 )
               v61 += 5;
-            v36 = v3 == 6;
-            goto LABEL_108;
-          case 0x1F8u:
-            goto LABEL_118;
-          case 0x1F9u:
-            v40 = v3 == 3;
-            goto LABEL_123;
-          case 0x1FAu:
-            v35 = v3 == 10;
-            goto LABEL_105;
-          case 0x1FEu:
-            v35 = v3 == 4;
-            goto LABEL_105;
-          case 0x1FFu:
-            if ( v3 == 23 )
+            if ( attr == 6 )
+              v5 += 40;
+            goto LABEL_361;
+          case ITEM_ARTICACT_GOVERNONS_ARMOR:            
+            if (attr <= 6)
+              v5 += 10;
+            goto LABEL_361;
+          case ITEM_ARTIFACT_YORUBA:
+            if ( attr == 3 )
+              v5 += 25;
+            goto LABEL_361;
+          case ITEM_ARTIFACT_SPLITTER:
+            if ( attr == 10 )
+              v5 += 50;
+            goto LABEL_361;
+          case ITEM_ARTEFACT_ULLYSES:
+            if ( attr == 4 )
+              v5 += 50;
+            goto LABEL_361;
+          case ITEM_ARTEFACT_HANDS_OF_THE_MASTER:
+            if ( attr == 23 )
               v61 += 10;
-            if ( v3 == 22 )
+            if ( attr == 22 )
               v61 += 10;
             goto LABEL_361;
-          case 0x200u:
-            if ( v3 == 36 )
+          case ITEM_ARTIFACT_LEAGUE_BOOTS:
+            if ( attr == 36 )
             {
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[14]);
-              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+              v34 = this->pActiveSkills[PLAYER_SKILL_WATER];
+              v62 = (v32 / 2) & 0x1F;
             }
-            v36 = v3 == 5;
-LABEL_108:
-            if ( v36 )
+            if ( attr == 5 )
               v5 += 40;
             goto LABEL_361;
-          case 0x201u:
-            if ( v3 == 39 )
+          case ITEM_ARTIFACT_RULERS_RING:
+            if ( attr == 39 )
             {
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[17]);
-              v34 = ((unsigned int)v34 >> 1) & 0x1F;
-              v62 = v34;
+              v34 = this->pActiveSkills[PLAYER_SKILL_MIND];
+              v62 = (v34 / 2 ) & 0x1F;
             }
-            goto LABEL_136;
-          case 0x202u:
-            if ( !v3 )
+            if ( attr == 42 )
+            {
+              v34 = this->pActiveSkills[PLAYER_SKILL_DARK];
+              v62 = (v34 / 2 ) & 0x1F;
+            }
+            goto LABEL_361;
+          case ITEM_RELIC_MASH:
+            if ( attr == 0 )
               v5 += 150;
-            if ( v3 == 1 )
+            if ( attr == 1 )
               v5 -= 40;
-            if ( v3 == 2 )
+            if ( attr == 2 )
+              v5 -= 40;
+            if ( attr == 5 )
               v5 -= 40;
-            goto LABEL_145;
-          case 0x203u:
-            if ( v3 == 42 )
+            goto LABEL_361;
+          case ITEM_RELIC_ETHRICS_STAFF:
+            if ( attr == 42 )
             {
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[20]);
-              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+              v34 = this->pActiveSkills[PLAYER_SKILL_DARK];
+              v62 = (v34 / 2 ) & 0x1F;
             }
-            if ( v3 == 43 )
+            if ( attr == 43 )
               v61 += 15;
             goto LABEL_361;
-          case 0x204u:
-            if ( v3 == 17 )
+          case ITEM_RELIC_HARECS_LEATHER:
+            if ( attr == 17 )
               v61 += 5;
-            if ( v3 == 18 )
+            if ( attr == 18 )
               v61 += 5;
-            if ( v3 == 6 )
+            if ( attr == 6 )
               v5 += 50;
-            if ( v3 == 11 || v3 == 10 || v3 == 12 || v3 == 13 || v3 == 33 || v3 == 14 )
-              goto LABEL_166;
-            v42 = v3 == 15;
-            goto LABEL_165;
-          case 0x205u:
-            if ( v3 == 18 )
+            if ( attr == 11 || attr == 10 || attr == 12 || attr == 13 || attr == 33 || attr == 14 )
+            {
+                v5 -= 10;
+              goto LABEL_361;
+            }
+            if ( attr == 15 )
+              v5 -= 10;
+            goto LABEL_361;
+          case ITEM_RELIC_OLD_NICK:
+            if ( attr == 18 )
               v61 += 5;
             goto LABEL_361;
-          case 0x206u:
-            if ( !v3 )
+          case ITEM_RELIC_AMUCK:
+            if ( attr == 0)
               v5 += 100;
-            if ( v3 == 3 )
+            if ( attr == 3 )
               v5 += 100;
-            v43 = v3 == 9;
-            goto LABEL_174;
-          case 0x207u:
-            if ( v3 == 45 )
+            if ( attr == 9 )
+              v5 -= 15;
+            goto LABEL_361;
+          case ITEM_RELIC_GLORY_SHIELD:
+            if ( attr == 45 )
               v61 += 5;
-            if ( v3 == 15 )
+            if ( attr == 15 )
               v5 -= 10;
-            v42 = v3 == 14;
-LABEL_165:
-            if ( v42 )
-LABEL_166:
+            if ( attr == 14 )
               v5 -= 10;
             goto LABEL_361;
-          case 0x208u:
-            v35 = v3 == 3;
-            goto LABEL_105;
-          case 0x209u:
-            if ( v3 == 2 )
+          case ITEM_RELIC_KELEBRIM:
+            if ( attr == 3 )
+              v5 += 50;
+            goto LABEL_361;
+          case ITEM_RELIC_TALEDONS_HELM:
+            if ( attr == 2 )
               v5 += 15;
-            if ( !v3 )
+            if ( !attr )
               v5 += 15;
-            v41 = v3 == 6;
-            goto LABEL_146;
-          case 0x20Au:
-            if ( v3 == 46 )
+            if ( attr == 6 )
+              v5 -= 40;
+            goto LABEL_361;
+          case ITEM_RELIC_SCHOLARS_CAP:
+            if ( attr == 46 )
               v61 += 15;
-            v44 = v3 == 3;
-            goto LABEL_190;
-          case 0x20Bu:
-            if ( v3 == 34 )
+            if ( attr == 3 )
+              v5 -= 50;
+            goto LABEL_361;
+          case ITEM_RELIC_PHYNAXIAN_CROWN:
+            if ( attr == 34 )
             {
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[12]);
-              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+              v34 = this->pActiveSkills[PLAYER_SKILL_FIRE];
+              v62 = (v34 / 2 ) & 0x1F;
             }
-            if ( v3 == 12 )
+            if ( attr == 12 )
               v5 += 50;
-            if ( v3 == 2 )
+            if ( attr == 2 )
               v5 += 30;
-            v45 = v3 == 9;
-            goto LABEL_199;
-          case 0x20Cu:
-            if ( !v3 )
+            if ( attr == 9 )
+              v5 -= 20;
+            goto LABEL_361;
+          case ITEM_RILIC_TITANS_BELT:
+            if ( !attr )
               v5 += 75;
-            goto LABEL_145;
-          case 0x20Du:
-            if ( v3 == 5 )
-              v5 += 50;
-            if ( v3 == 6 )
+            if ( attr == 5 )
+              v5 -= 40;
+            goto LABEL_361;
+          case ITEM_RELIC_TWILIGHT:
+            if ( attr == CHARACTER_ATTRIBUTE_SPEED )
               v5 += 50;
-            if ( v3 == 11 || v3 == 10 || v3 == 12 || v3 == 13 || v3 == 33 || v3 == 14 )
-              goto LABEL_374;
-            v43 = v3 == 15;
-LABEL_174:
-            if ( v43 )
-LABEL_374:
+            if ( attr == CHARACTER_ATTRIBUTE_LUCK )
+              v5 += 50;
+            if ( attr == CHARACTER_ATTRIBUTE_RESIST_AIR || attr == CHARACTER_ATTRIBUTE_RESIST_FIRE || attr == CHARACTER_ATTRIBUTE_RESIST_WATER || attr == CHARACTER_ATTRIBUTE_RESIST_EARTH || attr == CHARACTER_ATTRIBUTE_RESIST_SPIRIT || attr == CHARACTER_ATTRIBUTE_RESIST_MIND )
+            {
+              v5 -= 15;
+              goto LABEL_361;
+            }
+            if ( attr == 15 )
               v5 -= 15;
             goto LABEL_361;
-          case 0x20Eu:
-            if ( v3 == 4 )
+          case ITEM_RELIC_ANIA_SELVING:
+            if ( attr == CHARACTER_ATTRIBUTE_ACCURACY )
               v5 += 150;
-            if ( v3 == 44 )
+            if ( attr == CHARACTER_ATTRIBUTE_SKILL_BOW )
               v61 += 5;
-            if ( v3 == 9 )
+            if ( attr == CHARACTER_ATTRIBUTE_AC_BONUS )
               v5 -= 25;
             goto LABEL_361;
-          case 0x20Fu:
-            if ( v3 == 39 )
+          case ITEM_RELIC_JUSTICE:
+            if ( attr == 39 )
             {
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[17]);
-              v34 = ((unsigned int)v34 >> 1) & 0x1F;
-              v62 = v34;
+              v34 = this->pActiveSkills[PLAYER_SKILL_MIND];
+              v62 = (v34 / 2 ) & 0x1F;
             }
-            if ( v3 == 40 )
+            if ( attr == 40 )
             {
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[18]);
-              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+              v34 = this->pActiveSkills[PLAYER_SKILL_BODY];
+              v62 = (v34 / 2 ) & 0x1F;
             }
-LABEL_145:
-            v41 = v3 == 5;
-LABEL_146:
-            if ( v41 )
+            if ( attr == 5 )
               v5 -= 40;
             goto LABEL_361;
-          case 0x210u:
-            if ( v3 == 38 )
+          case ITEM_RELIC_MEKORIGS_HAMMER:
+            if ( attr == 38 )
             {
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[16]);
-              v62 = ((unsigned int)v34 >> 1) & 0x1F;
+              v34 = this->pActiveSkills[PLAYER_SKILL_SPIRIT];
+              v62 = ( v34 / 2 ) & 0x1F;
             }
-            if ( !v3 )
+            if ( attr == 0 )
               v5 += 75;
-            v44 = v3 == 11;
-LABEL_190:
-            if ( v44 )
+            if ( attr == 11 )
               v5 -= 50;
             goto LABEL_361;
-          case 0x211u:
-            if ( v3 == 5 )
+          case ITEM_ARTIFACT_HERMES_SANDALS:
+            if ( attr == 5 )
               v5 += 100;
-            if ( v3 == 4 )
+            if ( attr == 4 )
               v5 += 50;
-            v35 = v3 == 11;
-LABEL_105:
-            if ( v35 )
+            if ( attr == 11 )
               v5 += 50;
             goto LABEL_361;
-          case 0x212u:
-            if ( v3 == 1 )
+          case ITEM_ARTIFACT_CLOAK_OF_THE_SHEEP:
+            if ( attr == 1 )
               v5 -= 20;
-            v45 = v3 == 2;
-LABEL_199:
-            if ( v45 )
+            if ( attr == 2 )
               v5 -= 20;
             goto LABEL_361;
-          case 0x214u:
-            if ( v3 == 1 )
+          case ITEM_ARTIFACT_MINDS_EYE:
+            if ( attr == 1 )
+              v5 += 15;
+            if ( attr == 2 )
               v5 += 15;
-            v46 = v3 == 2;
-            goto LABEL_240;
-          case 0x215u:
-            if ( v3 == 5 )
+            goto LABEL_361;
+          case ITEM_ELVEN_CHAINMAIL:
+            if ( attr == 5 )
+              v5 += 15;
+            if ( attr == 4 )
               v5 += 15;
-            v46 = v3 == 4;
-            goto LABEL_240;
-          case 0x216u:
-            if ( v3 == 10 )
+            goto LABEL_361;
+          case ITEM_FORGE_GAUNTLETS:
+            if ( attr == 10 )
               v5 += 30;
-            if ( !v3 )
+            if ( attr == 0 )
+              v5 += 15;
+            if ( attr == 3 )
               v5 += 15;
-            goto LABEL_315;
-          case 0x217u:
-            if ( v3 == 21 )
+            goto LABEL_361;
+          case ITEM_ARTIFACT_HEROS_BELT:
+            if ( attr == 21 )
               v61 += 5;
-            if ( !v3 )
+            if ( attr == 0 )
               v5 += 15;
-            goto LABEL_253;
-          case 0x218u:
-            goto LABEL_253;
+            if (attr >= 10 && attr <= 15)
+              v5 += 10;
+            goto LABEL_361;
+          case ITEM_ARTIFACT_LADYS_ESCORT:
+            if (attr >= 10 && attr <= 15)
+              v5 += 10;
+            goto LABEL_361;
           default:
             goto LABEL_361;
         }
         goto LABEL_361;
       }
-      if ( *(int *)(v63 + 536) == v3 + 1 )
+      if ( this->pOwnItems[v65].uEnchantmentType == attr + 1 )
       {
-        if ( (signed int)v3 >= 0 )
+        if ( attr >= CHARACTER_ATTRIBUTE_STRENGTH )
         {
-          if ( (signed int)v3 <= 15 )
+          if ( attr <= CHARACTER_ATTRIBUTE_RESIST_BODY )
           {
-            v5 += *((int *)v6->pConditions + 9 * v31 + 135);
+            v5 += this->pOwnItems[v65].m_enchantmentStrength;
           }
           else
           {
-            if ( (signed int)v3 <= 23 && v5 < *((int *)v6->pConditions + 9 * v31 + 135) )
-              v5 = *((int *)v6->pConditions + 9 * v31 + 135);
-          }
-        }
-        goto LABEL_361;
-      }
-      v34 = *(int *)(v63 + 544);
-      if ( v34 > 48 )
-      {
-        switch ( v34 )
-        {
-          case 54:
-            goto LABEL_315;
-          case 49:
-            if ( v3 == 6 )
-              goto LABEL_121;
-            v50 = v3 == 1;
-            goto LABEL_296;
-          case 51:
-            if ( v3 != 5 && v3 != 1 )
-              goto LABEL_309;
-            goto LABEL_121;
-          case 52:
-            if ( v3 == 3 )
-              goto LABEL_121;
-            v50 = v3 == 4;
-            goto LABEL_296;
-          case 53:
-            if ( !v3 )
-              goto LABEL_121;
-            v50 = v3 == 2;
-            goto LABEL_296;
-          case 55:
-            v46 = v3 == 6;
-            goto LABEL_240;
-          case 56:
-            if ( !v3 )
-              goto LABEL_351;
-            v53 = v3 == 3;
-            goto LABEL_350;
-          case 57:
-            if ( v3 == 1 )
-              goto LABEL_351;
-            v53 = v3 == 2;
-            goto LABEL_350;
-          case 50:
-            if ( v3 == 10 )
-              v5 += 30;
-            goto LABEL_361;
-          case 60:
-            if ( v3 != 23 )
-              goto LABEL_336;
-            if ( v5 >= 3 )
-              goto LABEL_361;
-            v5 = 3;
-LABEL_336:
-            v54 = v3 == 22;
-            goto LABEL_345;
-          case 61:
-            if ( v3 != 17 )
-              goto LABEL_340;
-            if ( v5 >= 3 )
-              goto LABEL_361;
-            v5 = 3;
-LABEL_340:
-            v54 = v3 == 18;
-            goto LABEL_345;
-          case 62:
-            if ( v3 != 19 )
-              goto LABEL_344;
-            if ( v5 >= 3 )
-              goto LABEL_361;
-            v5 = 3;
-LABEL_344:
-            v54 = v3 == 20;
-LABEL_345:
-            if ( !v54 )
-              goto LABEL_361;
-            if ( v5 >= 3 )
-              goto LABEL_361;
-            v60 = 3;
-            goto LABEL_360;
-          case 67:
-            v55 = v3 == 18;
-            goto LABEL_357;
-          case 68:
-            v53 = v3 == 9;
-            goto LABEL_350;
-          case 69:
-            if ( v3 == 11 )
-              v5 += 20;
-            break;
-          case 70:
-            if ( v3 == 12 )
-              v5 += 10;
-            v55 = v3 == 16;
-LABEL_357:
-            if ( v55 && v5 < 2 )
-            {
-              v60 = 2;
-LABEL_360:
-              v5 = v60;
-            }
-            break;
-          default:
-            goto LABEL_361;
-        }
-        goto LABEL_361;
-      }
-      if ( v34 == 48 )
-      {
-        if ( v3 == 9 )
-          v5 += 5;
-LABEL_315:
-        v46 = v3 == 3;
-LABEL_240:
-        if ( v46 )
-          v5 += 15;
-        goto LABEL_361;
-      }
-      if ( v34 > 32 )
-      {
-        if ( v34 > 44 )
-        {
-          v51 = v34 - 45;
-          if ( !v51 )
-          {
-            if ( v3 == 5 )
-              goto LABEL_351;
-            v53 = v3 == 4;
-LABEL_350:
-            if ( v53 )
-LABEL_351:
-              v5 += 5;
-            goto LABEL_361;
-          }
-          v52 = v51 - 1;
-          if ( !v52 )
-          {
-            v40 = v3 == 0;
-LABEL_123:
-            if ( v40 )
-              v5 += 25;
-            goto LABEL_361;
-          }
-          if ( v52 == 1 )
-          {
-LABEL_309:
-            v50 = v3 == 8;
-            goto LABEL_296;
-          }
-        }
-        else
-        {
-          if ( v34 == 44 )
-          {
-            v50 = v3 == 7;
-            goto LABEL_296;
-          }
-          v34 -= 33;
-          if ( !v34 )
-          {
-            if ( v3 != 38 )
-              goto LABEL_361;
-            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[16]);
-            goto LABEL_138;
-          }
-          --v34;
-          if ( !v34 )
-          {
-            if ( v3 != 36 )
-              goto LABEL_361;
-            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[14]);
-            goto LABEL_138;
-          }
-          v49 = v34 - 8;
-          if ( !v49 )
-          {
-            if ( (signed int)v3 >= 0 && (signed int)v3 <= 15 )
-              ++v5;
-            goto LABEL_361;
-          }
-          if ( v49 == 1 )
-          {
-            if ( v3 != 3 && v3 != 7 )
-            {
-              v50 = v3 == 9;
-LABEL_296:
-              if ( !v50 )
-                goto LABEL_361;
-            }
-LABEL_121:
-            v5 += 10;
-            goto LABEL_361;
+            if ( attr <= CHARACTER_ATTRIBUTE_SKILL_UNARMED && v5 < this->pOwnItems[v65].m_enchantmentStrength )
+              v5 = this->pOwnItems[v65].m_enchantmentStrength;
           }
         }
       }
       else
       {
-        if ( v34 == 32 )
-        {
-          if ( v3 != 39 )
-            goto LABEL_361;
-          LOBYTE(v34) = LOBYTE(v6->pActiveSkills[17]);
-          goto LABEL_138;
-        }
-        if ( v34 > 28 )
-        {
-          v34 -= 29;
-          if ( v34 )
-          {
-            --v34;
-            if ( v34 )
-            {
-              --v34;
-              if ( v34 || v3 != 41 )
-                goto LABEL_361;
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[19]);
-            }
-            else
-            {
-              if ( v3 != 34 )
-                goto LABEL_361;
-              LOBYTE(v34) = LOBYTE(v6->pActiveSkills[12]);
-            }
-          }
-          else
-          {
-            if ( v3 != 37 )
-              goto LABEL_361;
-            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[15]);
-          }
-          goto LABEL_138;
-        }
-        if ( v34 == 28 )
-        {
-LABEL_136:
-          if ( v3 == 42 )
-          {
-            LOBYTE(v34) = LOBYTE(v6->pActiveSkills[20]);
-LABEL_138:
-            v62 = ((unsigned int)v34 >> 1) & 0x1F;
-            goto LABEL_361;
-          }
-        }
-        else
-        {
-          v47 = v34 - 1;
-          if ( v47 )
-          {
-            v48 = v47 - 1;
-            if ( v48 )
-            {
-              v34 = v48 - 24;
-              if ( v34 )
-              {
-                --v34;
-                if ( v34 || v3 != 40 )
-                  goto LABEL_361;
-                LOBYTE(v34) = LOBYTE(v6->pActiveSkills[18]);
-              }
-              else
-              {
-                if ( v3 != 35 )
-                  goto LABEL_361;
-                LOBYTE(v34) = LOBYTE(v6->pActiveSkills[13]);
-              }
-              goto LABEL_138;
-            }
-LABEL_118:
-            if ( (signed int)v3 < 0 )
-              goto LABEL_361;
-            v39 = __OFSUB__((int)v3, 6);
-            v37 = v3 == 6;
-            v38 = v3 - 6 < 0;
-          }
-          else
-          {
-LABEL_253:
-            if ( (signed int)v3 < 10 )
-              goto LABEL_361;
-            v39 = __OFSUB__((int)v3, 15);
-            v37 = v3 == 15;
-            v38 = v3 - 15 < 0;
-          }
-          if ( (unsigned __int8)(v38 ^ v39) | v37 )
-            goto LABEL_121;
-        }
+        v34 = this->pOwnItems[v65].uSpecEnchantmentType;
+        GetItemBonusSpecialEnchantment(v34, attr, &v5, &v61);
       }
+
 LABEL_361:
       ++v65;
       if ( (signed int)v65 >= 16 )
@@ -3908,7 +3888,7 @@
   {
     if ( IsUnarmed() != 1 )
     {
-      if ( v6->HasItemEquipped(EQUIP_MAIN_HAND) )
+      if ( this->HasItemEquipped(EQUIP_MAIN_HAND) )
       {
         v22 = this->GetEquippedItemEquipType(EQUIP_MAIN_HAND);
         if ( v22 >= 0 )
@@ -3916,7 +3896,7 @@
           if ( v22 <= 2 )
           {
 			  v23 = this->pOwnItems[this->pEquipment.uMainHand].uItemID;
-            if ( v6->pEquipment.uShield || pItemsTable->pItems[v23].uSkillType != 4 )
+            if ( this->pEquipment.uShield || pItemsTable->pItems[v23].uSkillType != 4 )
             {
               v26 = pItemsTable->pItems[v23].uDamageRoll;
               v25 = pItemsTable->pItems[v23].uDamageDice;
@@ -3931,10 +3911,10 @@
         }
       }
       
-      if ( a3 || !v6->HasItemEquipped(EQUIP_OFF_HAND) )
+      if ( getOnlyMainHandDmg || !this->HasItemEquipped(EQUIP_OFF_HAND) )
           {
 
-          v28 = v6->GetEquippedItemEquipType(EQUIP_OFF_HAND);
+          v28 = this->GetEquippedItemEquipType(EQUIP_OFF_HAND);
           if ((v28 < 0) || v28 > 2 )
               return v5 + v62 + v61;
         }
@@ -3944,7 +3924,6 @@
       return v5 + v62 + v61;
     }
     v59 = 3;
-LABEL_74:
     v5 = v59;
     return v5 + v62 + v61;
   }
@@ -3968,18 +3947,18 @@
       v5 = 0;
       return v5 + v62 + v61;
     }
-    if ( v6->HasItemEquipped(EQUIP_MAIN_HAND) )
+    if ( this->HasItemEquipped(EQUIP_MAIN_HAND) )
     {
       v17 = this->GetEquippedItemEquipType(EQUIP_MAIN_HAND);
       if ( v17 >= 0 )
       {
         if ( v17 <= 2 )
-          v5 = pItemsTable->pItems[v6->pOwnItems[v6->pEquipment.uMainHand-1].uItemID].uDamageMod;
+          v5 = pItemsTable->pItems[this->pOwnItems[this->pEquipment.uMainHand-1].uItemID].uDamageMod;
       }
     }
-    if ( a3 || !v6->HasItemEquipped(EQUIP_OFF_HAND) || (v19 = v6->GetEquippedItemEquipType(EQUIP_OFF_HAND), v19 < 0) || v19 > 2 )
+    if ( getOnlyMainHandDmg || !this->HasItemEquipped(EQUIP_OFF_HAND) || (v19 = this->GetEquippedItemEquipType(EQUIP_OFF_HAND), v19 < 0) || v19 > 2 )
       return v5 + v62 + v61;
-    v20 = v6->pOwnItems[v6->pEquipment.uShield - 1].uItemID;
+    v20 = this->pOwnItems[this->pEquipment.uShield - 1].uItemID;
     v56 = pItemsTable->pItems[v20].uDamageMod;
     v5 += v56;
     return v5 + v62 + v61;
@@ -3991,7 +3970,7 @@
       v5 = 1;
       return v5 + v62 + v61;
     }
-    if ( v6->HasItemEquipped(EQUIP_MAIN_HAND) )
+    if ( this->HasItemEquipped(EQUIP_MAIN_HAND) )
     {
       v9 = this->GetEquippedItemEquipType(EQUIP_MAIN_HAND);
       if ( v9 >= 0 )
@@ -4000,7 +3979,7 @@
         {
           v5 = pItemsTable->pItems[this->pOwnItems[this->pEquipment.uMainHand].uItemID].uDamageDice +
                  pItemsTable->pItems[this->pOwnItems[this->pEquipment.uMainHand].uItemID].uDamageMod;
-          if ( !v6->pEquipment.uShield )
+          if ( !this->pEquipment.uShield )
           {
             if ( pItemsTable->pItems[this->pOwnItems[this->pEquipment.uMainHand].uItemID].uSkillType == 4 )
               ++v5;
@@ -4009,15 +3988,14 @@
       }
     }
     
-    if ( a3 || !v6->HasItemEquipped(EQUIP_OFF_HAND))
+    if ( getOnlyMainHandDmg || !this->HasItemEquipped(EQUIP_OFF_HAND))
         {
-        v12 = v6->GetEquippedItemEquipType(EQUIP_OFF_HAND);
+        v12 = this->GetEquippedItemEquipType(EQUIP_OFF_HAND);
         if  ((v12 < 0) || v12 > 2 )
                 return v5 + v62 + v61;
         }
     v14 = pItemsTable->pItems[this->pOwnItems[this->pEquipment.uShield].uItemID].uDamageMod;
     v15 = pItemsTable->pItems[this->pOwnItems[this->pEquipment.uShield].uItemID].uDamageDice;
-LABEL_88:
     v5 += v15 + v14;
   }
   return v5 + v62 + v61;
@@ -4137,7 +4115,7 @@
         bonus_value = 6;
       if ( CheckHiredNPCSpeciality(Sage) )
         bonus_value += 6;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_MONSTER_ID, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_MONSTER_ID);
     }
     break;
 
@@ -4147,7 +4125,7 @@
           bonus_value = 2;
         if ( CheckHiredNPCSpeciality(Weaponsmaster) )
           bonus_value += 3;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_ARMSMASTER, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_ARMSMASTER);
     }
     break;
 
@@ -4155,7 +4133,7 @@
     {
       if (CheckHiredNPCSpeciality(Burglar))
           bonus_value = 8;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_STEALING, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_STEALING);
     }
     break;
 
@@ -4166,7 +4144,7 @@
           bonus_value = 4;
         if ( CheckHiredNPCSpeciality(Apothecary) )
           bonus_value += 8;
-        bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_ALCHEMY, 0);
+        bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_ALCHEMY);
     }
     break;
 
@@ -4178,7 +4156,7 @@
           bonus_value += 15;
         if ( CheckHiredNPCSpeciality(Scholar) )
           bonus_value += 5;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_LEARNING, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_LEARNING);
     }
     break;
 
@@ -4186,7 +4164,7 @@
     {
       if (CheckHiredNPCSpeciality(Monk) )
         bonus_value = 2;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_UNARMED, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_UNARMED);
     }
     break;
 
@@ -4194,15 +4172,15 @@
     {
       if ( CheckHiredNPCSpeciality(Monk) )
         bonus_value = 2;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_DODGE, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_DODGE);
     }
     break;
     
     case PLAYER_SKILL_BOW:
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_BOW, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_BOW);
     break;
     case PLAYER_SKILL_SHIELD:
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_SHIELD, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_SHIELD);
     break;
 
     case PLAYER_SKILL_EARTH:
@@ -4214,7 +4192,7 @@
             bonus_value += 4;
           if ( classType == PLAYER_CLASS_WARLOCK && PartyHasDragon() )
             bonus_value += 3;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_EARTH, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_EARTH);
     break;
     case PLAYER_SKILL_FIRE:
       if ( CheckHiredNPCSpeciality(Apprentice) )
@@ -4225,7 +4203,7 @@
             bonus_value += 4;
           if ( classType == PLAYER_CLASS_WARLOCK && PartyHasDragon() )
             bonus_value += 3;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_FIRE, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_FIRE);
     break;
     case PLAYER_SKILL_AIR:
       if ( CheckHiredNPCSpeciality(Apprentice) )
@@ -4236,7 +4214,7 @@
             bonus_value += 4;
           if ( classType == PLAYER_CLASS_WARLOCK && PartyHasDragon() )
             bonus_value += 3;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_AIR, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_AIR);
     break;
     case PLAYER_SKILL_WATER:
       if ( CheckHiredNPCSpeciality(Apprentice) )
@@ -4247,7 +4225,7 @@
             bonus_value += 4;
           if ( classType == PLAYER_CLASS_WARLOCK && PartyHasDragon() )
             bonus_value += 3;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_WATER, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_WATER);
     break;
     case PLAYER_SKILL_SPIRIT:
           if ( CheckHiredNPCSpeciality(Acolyte2) )
@@ -4256,7 +4234,7 @@
             bonus_value += 3;
           if ( CheckHiredNPCSpeciality(Prelate) )
             bonus_value += 4;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_SPIRIT, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_SPIRIT);
     break;
     case PLAYER_SKILL_MIND:
           if ( CheckHiredNPCSpeciality(Acolyte2) )
@@ -4265,7 +4243,7 @@
             bonus_value += 3;
           if ( CheckHiredNPCSpeciality(Prelate) )
             bonus_value += 4;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_MIND, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_MIND);
     break;
     case PLAYER_SKILL_BODY:
           if ( CheckHiredNPCSpeciality(Acolyte2) )
@@ -4274,14 +4252,14 @@
             bonus_value += 3;
           if ( CheckHiredNPCSpeciality(Prelate) )
             bonus_value += 4;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_BODY, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_BODY);
     break;
     case PLAYER_SKILL_LIGHT:
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_LIGHT, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_LIGHT);
     break;
     case PLAYER_SKILL_DARK:
     {
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_DARK, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_DARK);
     }
     break;
 
@@ -4308,10 +4286,10 @@
     break;
 
     case PLAYER_SKILL_ITEM_ID:
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_ITEM_ID, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_ITEM_ID);
       break;
     case PLAYER_SKILL_MEDITATION:
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_MEDITATION, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_MEDITATION);
     break;
     case PLAYER_SKILL_TRAP_DISARM:
     {
@@ -4321,7 +4299,7 @@
         bonus_value += 6;
       if ( CheckHiredNPCSpeciality(Burglar) )
         bonus_value += 8;
-      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_TRAP_DISARM, 0);
+      bonus_value += GetItemsBonus(CHARACTER_ATTRIBUTE_SKILL_TRAP_DISARM);
     }
     break;
   }
@@ -8991,4 +8969,4 @@
 void Player::SetCondUnconsciousWithBlockCheck( int blockable )
 {
   SetCondition(Condition_Dead, blockable);
-}
\ No newline at end of file
+}
--- a/Player.h	Mon Sep 09 20:09:01 2013 +0200
+++ b/Player.h	Thu Sep 12 09:55:20 2013 +0200
@@ -518,8 +518,8 @@
   void RandomizeName();
   unsigned int GetMajorConditionIdx();
   int GetParameterBonus(int player_parameter);
-  int _48EA46_calc_special_bonus_by_items(int a2);
-  int GetItemsBonus(enum CHARACTER_ATTRIBUTE_TYPE attr, int a3);
+  int GetSpecialItemBonus(int enchantmentId);
+  int GetItemsBonus(enum CHARACTER_ATTRIBUTE_TYPE attr, bool a3 = false);
   int GetMagicalBonus(enum CHARACTER_ATTRIBUTE_TYPE a2);
   int GetActualSkillLevel(PLAYER_SKILL_TYPE uSkillType);
   int GetSkillBonus(enum CHARACTER_ATTRIBUTE_TYPE a2);
@@ -584,6 +584,7 @@
   unsigned int GetMultiplierForSkillLevel(unsigned int skillValue, int mult1, int mult2, int mult3, int mult4);
   int CalculateMeleeDmgToEnemyWithWeapon( ItemGen * weapon, unsigned int uTargetActorID , bool addOneDice);
   bool WearsItemAnyWhere(int item_id);
+  float GetArmorRecoveryMultiplierFromSkillLevel( unsigned char armour_skill_type, float param2, float param3, float param4, float param5 );
 
   bool IsWeak();
   bool IsDead();
@@ -626,6 +627,7 @@
 
   inline bool IsMale() { return GetSexByVoice() == SEX_MALE;}
   inline bool IsFemale() { return !IsMale();}
+  void GetItemBonusSpecialEnchantment(int enchantmentId, CHARACTER_ATTRIBUTE_TYPE attrToGet, int* additiveBonus, int* halfSkillBonus);
   __int64 pConditions[20];
   unsigned __int64 uExperience;
   char pName[16];
--- a/UI/UIPopup.cpp	Mon Sep 09 20:09:01 2013 +0200
+++ b/UI/UIPopup.cpp	Thu Sep 12 09:55:20 2013 +0200
@@ -439,12 +439,12 @@
         else if ( inspect_item->uEnchantmentType )
             {
             sprintf(out_text + 200, "%s: %s +%d", pGlobalTXT_LocalizationStrings[210],
-                pItemsTable->pEnchantments[inspect_item->uEnchantmentType-1].pBonusStat, inspect_item->_bonus_strength); //"Special"
+                pItemsTable->pEnchantments[inspect_item->uEnchantmentType-1].pBonusStat, inspect_item->m_enchantmentStrength); //"Special"
             }
         else  if ( inspect_item->uSpecEnchantmentType )
             {      
             sprintf(out_text + 200, "%s: %s", pGlobalTXT_LocalizationStrings[210], 
-                pItemsTable->pSpecialEnchantments[inspect_item->uSpecEnchantmentType-1].pBonusStatement, inspect_item->_bonus_strength);
+                pItemsTable->pSpecialEnchantments[inspect_item->uSpecEnchantmentType-1].pBonusStatement, inspect_item->m_enchantmentStrength);
             }
 
         else if ( inspect_item->uNumCharges )
--- a/mm7_2.cpp	Mon Sep 09 20:09:01 2013 +0200
+++ b/mm7_2.cpp	Thu Sep 12 09:55:20 2013 +0200
@@ -923,6 +923,7 @@
   v231 = 0;
   if ( dstHeight <= 0 )
     return result;
+  
   do
   {
     for (int counter = 0; counter < dstWidth; counter++)
@@ -948,11 +949,11 @@
         for(int i = 0; i < ratioDiff; i++)
         {
           if(field0value == 32)
-            v21 = _450FB1((int)v175[i]);
+            v21 = _450FB1(((int*)v175)[i]);
           else if(field0value == 16)
-            v21 = _450FB1((_WORD)v175[i]);
+            v21 = _450FB1(((_WORD*)v175)[i]);
           else
-            v21 = _450FB1((unsigned __int8)v175[i]);
+            v21 = _450FB1(((unsigned __int8*)v175)[i]);
           v240 += ((unsigned int)v21 >> 24);
           a6b += BYTE2(v21);
           v252 += BYTE1(v21);
--- a/mm7_4.cpp	Mon Sep 09 20:09:01 2013 +0200
+++ b/mm7_4.cpp	Thu Sep 12 09:55:20 2013 +0200
@@ -877,7 +877,7 @@
             v21->pConditions[13] = pParty->uTimePlayed;
           if ( v35 < 1 )
           {
-            if ( v21->sHealth + v21->uEndurance + v21->GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0) >= 1
+            if ( v21->sHealth + v21->uEndurance + v21->GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE) >= 1
               || (signed __int64)v21->pPlayerBuffs[11].uExpireTime > 0 )
             {
               v21->pConditions[13] = pParty->uTimePlayed;
@@ -1166,7 +1166,7 @@
     if ( (*v62)->uTimeToRecovery )
       v21->Recover(a2a);
     v22 = v21->sHealth;
-    if ( v21->GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0) + v22 + v21->uEndurance >= 1
+    if ( v21->GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE) + v22 + v21->uEndurance >= 1
       || (signed __int64)v21->pPlayerBuffs[11].uExpireTime > 0 )
     {
       if ( v22 < 1 )