changeset 816:cfc65feef029

* Player Recovery Times * Player Attack fixes * Debug log to timers
author Nomad
date Tue, 26 Mar 2013 12:40:27 +0200
parents d37b03507b3b
children 448e6d979c7a
files GUIWindow.h Game.cpp Items.cpp Items.h Party.h Player.cpp Player.h SaveLoad.cpp Time.cpp UICharacter.cpp UIHouses.h UIPopup.cpp mm7_2.cpp mm7_3.cpp mm7_4.cpp mm7_5.cpp mm7_6.cpp mm7_data.cpp mm7_data.h
diffstat 19 files changed, 376 insertions(+), 362 deletions(-) [+]
line wrap: on
line diff
--- a/GUIWindow.h	Tue Mar 26 06:40:04 2013 +0200
+++ b/GUIWindow.h	Tue Mar 26 12:40:27 2013 +0200
@@ -1,5 +1,7 @@
 #pragma once
 #include "GUIButton.h"
+#include "Items.h"
+#include "Player.h"
 
 
 
@@ -417,4 +419,20 @@
 
 
 
-void QuickRefDraw();
\ No newline at end of file
+void QuickRefDraw();
+
+
+
+
+
+
+
+
+
+
+//character ui
+unsigned int __fastcall GetSkillColor(unsigned int uPlayerClass, PLAYER_SKILL_TYPE uPlayerSkillType, signed int skill_level);
+const char *__fastcall CharacterUI_GetSkillDescText(unsigned int uPlayerID, PLAYER_SKILL_TYPE uPlayerSkillType);
+char __cdecl CharacterUI_SkillsTab_ShowHint();
+char __cdecl CharacterUI_StatsTab_ShowHint();
+char __fastcall CharacterUI_StatsTab_Draw(unsigned int uPlayerID); // idb
\ No newline at end of file
--- a/Game.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/Game.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -355,8 +355,16 @@
         pMouse->_469EA4();
         pRenderer->EndScene();
       }
+
+      static int gtc_old = GetTickCount();
+      int gtc = GetTickCount();
+      auto evt_old = pEventTimer->uStartTime,
+           msc_old = pMiscTimer->uStartTime;
       pEventTimer->Update();
       pMiscTimer->Update();
+      Log::Warning(L"Evt/Msc/GTC dt: %u/%u/%u", pEventTimer->uTimeElapsed, pMiscTimer->uTimeElapsed, gtc - gtc_old);
+      gtc_old = gtc;
+
       OnTimer(0);
       GameUI_StatusBar_UpdateTimedString(0);
       if ( pMiscTimer->bPaused && !pEventTimer->bPaused )
--- a/Items.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/Items.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -547,17 +547,17 @@
 					{
 					if ( !_strcmpi(test_string, "weapon") )
 						{
-						pItems[item_counter].uEquipType = EQUIP_ONE_OR_TWO_HANDS;
+						pItems[item_counter].uEquipType = EQUIP_OFF_HAND;
 						break;
 						}
 					if ( !_strcmpi(test_string, "weapon2") )
 						{
-						pItems[item_counter].uEquipType = EQUIP_TWO_HANDED;
+						pItems[item_counter].uEquipType = EQUIP_MAIN_HAND;
 						break;
 						}
 					if ( !_strcmpi(test_string, "weapon1or2") )
 						{
-						pItems[item_counter].uEquipType = EQUIP_ONE_OR_TWO_HANDS;
+						pItems[item_counter].uEquipType = EQUIP_OFF_HAND;
 						break;
 						}
 					if ( !(_strcmpi(test_string, "missile")&&_strcmpi(test_string, "bow")))
@@ -1609,7 +1609,7 @@
         PLAYER_SKILL_TYPE requested_skill = PLAYER_SKILL_INVALID;
         switch (uTreasureType)
             {
-        case 20: requested_equip = EQUIP_ONE_OR_TWO_HANDS; break;
+        case 20: requested_equip = EQUIP_OFF_HAND; break;
         case 21: requested_equip = EQUIP_ARMOUR; break;
         case 22: requested_skill = PLAYER_SKILL_MISC; break;
         case 23: requested_skill = PLAYER_SKILL_SWORD; break;
@@ -1760,8 +1760,8 @@
     //try get special enhansment
     switch (pItems[out_item->uItemID].uEquipType)
         {
-    case EQUIP_ONE_OR_TWO_HANDS:
-    case EQUIP_TWO_HANDED :   
+    case EQUIP_OFF_HAND:
+    case EQUIP_MAIN_HAND :   
     case EQUIP_BOW :    
         if ( !uBonusChanceWpSpecial[v6] )
             return;
--- a/Items.h	Tue Mar 26 06:40:04 2013 +0200
+++ b/Items.h	Tue Mar 26 12:40:27 2013 +0200
@@ -4,7 +4,6 @@
 
 
 
-
 /*  338 */
 enum ITEM_FLAGS :unsigned int
 {
@@ -34,8 +33,8 @@
   ITEM_CROSSBOW_1 = 0x2F,
   ITEM_MACE_1 = 0x32,
   ITEM_STAFF_1 = 0x3D,
-  ITEM_BLASTER = 65,
-  ITEM_LASER_RIFLE = 66,
+  ITEM_BLASTER = 64,
+  ITEM_LASER_RIFLE = 65,
   ITEM_LEATHER_1 = 0x42,
   ITEM_CHAINMAIL_1 = 0x47,
   ITEM_PLATE_1 = 0x4C,
@@ -87,29 +86,29 @@
 };
 
 /*  331 */
-enum ITEM_EQUIP_TYPE
+enum ITEM_EQUIP_TYPE: unsigned __int8
 {
-  EQUIP_ONE_OR_TWO_HANDS = 0,
-  EQUIP_TWO_HANDED       = 1,
-  EQUIP_BOW              = 2,
-  EQUIP_ARMOUR           = 3,
-  EQUIP_SHIELD           = 4,
-  EQUIP_HELMET           = 5,
-  EQUIP_BELT             = 6,
-  EQUIP_CLOAK            = 7,
-  EQUIP_GAUNTLETS        = 8,
-  EQUIP_BOOTS            = 9,
-  EQUIP_RING             = 10,
-  EQUIP_AMULET           = 11,
-  EQUIP_WAND             = 12,
-  EQUIP_REAGENT          = 13,
-  EQUIP_POTION           = 14,
-  EQUIP_SPELL_SCROLL     = 15,
-  EQUIP_BOOK             = 16,
-  EQUIP_MESSAGE_SCROLL   = 17,
-  EQUIP_GOLD             = 18,
-  EQUIP_GEM              = 19,
-  EQUIP_NONE             = 20
+  EQUIP_OFF_HAND     = 0,
+  EQUIP_MAIN_HAND     = 1,
+  EQUIP_BOW            = 2,
+  EQUIP_ARMOUR         = 3,
+  EQUIP_SHIELD         = 4,
+  EQUIP_HELMET         = 5,
+  EQUIP_BELT           = 6,
+  EQUIP_CLOAK          = 7,
+  EQUIP_GAUNTLETS      = 8,
+  EQUIP_BOOTS          = 9,
+  EQUIP_RING           = 10,
+  EQUIP_AMULET         = 11,
+  EQUIP_WAND           = 12,
+  EQUIP_REAGENT        = 13,
+  EQUIP_POTION         = 14,
+  EQUIP_SPELL_SCROLL   = 15,
+  EQUIP_BOOK           = 16,
+  EQUIP_MESSAGE_SCROLL = 17,
+  EQUIP_GOLD           = 18,
+  EQUIP_GEM            = 19,
+  EQUIP_NONE           = 20
 };
 
 
@@ -143,7 +142,21 @@
   int uItemID;
   int uEnchantmentType;
   int _bonus_strength;
-  int uSpecEnchantmentType; // 25: +5 levels
+  int uSpecEnchantmentType; // 25  +5 levels
+                            // 16  Drain Hit Points from target.
+                            // 39  Double damage vs Demons.
+                            // 40  Double damage vs Dragons
+                            // 45  +5 Speed and Accuracy
+                            // 56  +5 Might and Endurance.
+                            // 57  +5 Intellect and Personality.
+                            // 58  Increased Value.
+                            // 60  +3 Unarmed and Dodging skills
+                            // 61  +3 Stealing and Disarm skills.
+                            // 59  Increased Weapon speed.
+                            // 63  Double Damage vs. Elves.
+                            // 64  Double Damage vs. Undead.
+                            // 67  Adds 5 points of Body damage and +2 Disarm skill.
+                            // 68  Adds 6-8 points of Cold damage and +5 Armor Class.
   int uNumCharges;
   unsigned int uAttributes;
   unsigned __int8 uBodyAnchor;
@@ -170,7 +183,7 @@
 	__int16 field_1A; //16 
 	signed __int16 uEquipX; //18  1c
 	signed __int16 uEquipY; //1a  1e
-	unsigned __int8 uEquipType; //1c 20
+	ITEM_EQUIP_TYPE uEquipType; //1c 20
 	unsigned __int8 uSkillType; //1d 21
 	unsigned __int8 uDamageDice; //1e 22
 	unsigned __int8 uDamageRoll; //1f 23
--- a/Party.h	Tue Mar 26 06:40:04 2013 +0200
+++ b/Party.h	Tue Mar 26 12:40:27 2013 +0200
@@ -30,6 +30,7 @@
   PARTY_FLAGS_1_ALERT_YELLOW = 0x0020,
   PARTY_FLAGS_1_STANDING_ON_WATER = 0x0080,
   PARTY_FLAGS_1_LANDING = 0x0100,
+  PARTY_FLAGS_1_BURNING = 0x200
 };
 enum PARTY_FLAGS_2: __int32
 {
--- a/Player.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/Player.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -7,6 +7,7 @@
 #include "AudioPlayer.h"
 #include "Party.h"
 #include "GUIButton.h"
+#include "Log.h"
 #include "LOD.h"
 #include "Monsters.h" 
 #include "GUIWindow.h"
@@ -22,6 +23,7 @@
 #include "Autonotes.h"
 #include "Awards.h"
 #include "texts.h"
+
 #include "mm7_data.h"
 
 
@@ -111,6 +113,23 @@
 
 
 
+unsigned short base_recovery_times_per_weapon_type[12] =
+{
+  100,  // PLAYER_SKILL_STAFF   && Unarmed withoud skill
+   90,  // PLAYER_SKILL_SWORD   && Unarmed with skill
+   60,  // PLAYER_SKILL_DAGGER
+  100,  // PLAYER_SKILL_AXE
+   80,  // PLAYER_SKILL_SPEAR
+  100,  // PLAYER_SKILL_BOW
+   80,  // PLAYER_SKILL_MACE
+   30,  // PLAYER_SKILL_BLASTER
+   10,  // PLAYER_SKILL_SHIELD
+   10,  // PLAYER_SKILL_LEATHER
+   20,  // PLAYER_SKILL_CHAIN
+   30   // PLAYER_SKILL_PLATE
+};
+
+
 
 //----- (00490913) --------------------------------------------------------
 signed int __cdecl PlayerCreation_ComputeAttributeBonus()
@@ -2763,7 +2782,7 @@
     v34 = v4;
     goto LABEL_62;
   }
-  if ( HasItemEquipped(EQUIP_TWO_HANDED) )
+  if ( HasItemEquipped(EQUIP_MAIN_HAND) )
   {
     v6 = (ItemGen *)&v5->pInventoryItems[v5->pEquipment.uMainHand-1];
     v7 = v6->uItemID;
@@ -3327,23 +3346,22 @@
 }
 
 //----- (0048D62C) --------------------------------------------------------
-int Player::GetEquippedItemEquipType(unsigned int uEquipSlot)
-{
-  return pItemsTable->pItems[pInventoryItems[pEquipment.pIndices[uEquipSlot]-1].uItemID].uEquipType;
+ITEM_EQUIP_TYPE Player::GetEquippedItemEquipType(ITEM_EQUIP_TYPE uEquipSlot)
+{
+  return pItemsTable->pItems[pInventoryItems[pEquipment.pIndices[uEquipSlot] - 1].uItemID].uEquipType;
 }
 
 //----- (0048D651) --------------------------------------------------------
-int Player::GetEquippedItemSkillType(enum ITEM_EQUIP_TYPE uEquipSlot)
-{
-  return pItemsTable->pItems[pInventoryItems[pEquipment.pIndices[uEquipSlot] - 1].uItemID].uSkillType;
+PLAYER_SKILL_TYPE Player::GetEquippedItemSkillType(ITEM_EQUIP_TYPE uEquipSlot)
+{
+  return (PLAYER_SKILL_TYPE)pItemsTable->pItems[pInventoryItems[pEquipment.pIndices[uEquipSlot] - 1].uItemID].uSkillType;
 }
 
 //----- (0048D676) --------------------------------------------------------
 bool Player::IsUnarmed()
 {
-  return HasItemEquipped(EQUIP_TWO_HANDED) != 1
-      && (HasItemEquipped(EQUIP_ONE_OR_TWO_HANDS) != 1
-       || GetEquippedItemEquipType(0) == EQUIP_SHIELD);
+  return HasItemEquipped(EQUIP_MAIN_HAND) != EQUIP_MAIN_HAND &&
+        !(HasItemEquipped(EQUIP_OFF_HAND) == EQUIP_MAIN_HAND && GetEquippedItemEquipType(EQUIP_OFF_HAND) != EQUIP_SHIELD);
 }
 
 //----- (0048D6AA) --------------------------------------------------------
@@ -3797,9 +3815,9 @@
       {
         if ( HasItemEquipped((ITEM_EQUIP_TYPE)v14) )
         {
-          if ( v15 == 3 )
+          if ( v15 == EQUIP_ARMOUR )
             v46[v4++] = LOBYTE(v5->pEquipment.uBody) - 1;
-          if ( (!v15 || v15 == 1) && GetEquippedItemEquipType(v15) == 4 )
+          if ( (!v15 || v15 == 1) && GetEquippedItemEquipType((ITEM_EQUIP_TYPE)v15) == 4 )
             v46[v4++] = *((char *)&v5->pEquipment.uOffHand + 4 * v15) - 1;
         }
         v14 = v15 + 1;
@@ -3815,7 +3833,7 @@
           if ( v17 == 2 )
             v46[v4++] = LOBYTE(v5->pEquipment.uBow) - 1;
           if ( (!v17 || v17 == 1)
-            && (!GetEquippedItemEquipType(v17) || GetEquippedItemEquipType(v17) == 1) )
+            && (!GetEquippedItemEquipType((ITEM_EQUIP_TYPE)v17) || GetEquippedItemEquipType((ITEM_EQUIP_TYPE)v17) == 1) )
             v46[v4++] = *((char *)&v5->pEquipment.uOffHand + 4 * v17) - 1;
         }
         v16 = v17 + 1;
@@ -4052,211 +4070,160 @@
 }
 
 //----- (0048E1B5) --------------------------------------------------------
-int Player::GetAttackRecoveryTime(int a2)
-{
-  unsigned int v2; // ebx@1
-  char *v3; // edi@1
-  Player *v4; // esi@1
-  int v5; // eax@3
-  int v6; // eax@3
-  int v7; // eax@6
-  int v8; // eax@9
-  int v9; // eax@9
-  int v10; // eax@10
-  int v11; // edx@13
-  int v12; // ecx@14
-  int v13; // eax@15
-  int v14; // ebx@18
-  int v15; // eax@18
-  double v16; // st7@21
-  double v17; // st7@22
-  unsigned __int16 v18; // cx@27
-  Player *v19; // ecx@28
-  int v20; // eax@30
-  int v21; // eax@30
-  int v22; // eax@30
-  int v23; // ecx@30
-  unsigned int v24; // eax@30
-  int v25; // eax@31
-  int v26; // ebx@32
-  int v27; // eax@32
-  unsigned __int16 *v28; // ebx@36
-  int v29; // eax@42
-  int v30; // edi@43
-  signed int v31; // eax@49
-  int v32; // ecx@50
-  int result; // eax@54
-  float v34; // [sp+8h] [bp-38h]@27
-  float v35; // [sp+Ch] [bp-34h]@18
-  float v36; // [sp+10h] [bp-30h]@21
-  float v37; // [sp+14h] [bp-2Ch]@21
-  float v38; // [sp+18h] [bp-28h]@27
-  int v39; // [sp+1Ch] [bp-24h]@31
-  int v40; // [sp+20h] [bp-20h]@1
-  int v41; // [sp+24h] [bp-1Ch]@1
-  unsigned int v42; // [sp+28h] [bp-18h]@14
-  int v43; // [sp+2Ch] [bp-14h]@1
-  int v44; // [sp+30h] [bp-10h]@1
-  int v45; // [sp+34h] [bp-Ch]@1
-  int v46; // [sp+38h] [bp-8h]@1
-  int v47; // [sp+3Ch] [bp-4h]@1
-
-  v2 = 0;
-  v3 = 0;
-  v4 = this;
-  v47 = (unsigned __int16)word_4EDED8[0];
-  v43 = 0;
-  v45 = 0;
-  v40 = 0;
-  v41 = 0;
-  v44 = 0;
-  v46 = 0;
-  if ( a2 )
+int Player::GetAttackRecoveryTime(bool bRangedAttack)
+{
+  ItemGen  *weapon = nullptr;
+  ItemDesc *weapon_desc = nullptr;
+  uint      weapon_recovery = base_recovery_times_per_weapon_type[0];
+  if (bRangedAttack)
   {
     if ( !HasItemEquipped(EQUIP_BOW) )
       goto LABEL_17;
-    v5 = (int)&v4->pInventoryItems[v4->pEquipment.uBow-1];
-    v46 = v5;
-    v3 = (char *)&pItemsTable->pItems[*(int *)v5].pIconName;
-    v6 = (unsigned __int16)word_4EDED8[(unsigned __int8)v3[29]];
-    goto LABEL_4;
-  }
-  if ( IsUnarmed() == 1 )
-  {
-    LOBYTE(v7) = GetActualSkillLevel(PLAYER_SKILL_UNARMED);
-    if ( v7 )
-    {
-      v6 = (unsigned __int16)word_4EDED8[1];
-LABEL_4:
-      v47 = v6;
+    weapon = &pInventoryItems[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))
+    {
+      weapon_recovery = base_recovery_times_per_weapon_type[1];
       goto LABEL_17;
     }
   }
-  if ( HasItemEquipped(EQUIP_TWO_HANDED) )
-  {
-    v8 = (int)&v4->pInventoryItems[v4->pEquipment.uMainHand-1];
-    v46 = v8;
-    v9 = *(int *)v8;
-    v3 = (char *)&pItemsTable->pItems[v9].pIconName;
-    if ( v3[28] == 12 )
-      v10 = *(&pSpellDatas[0].uExpertLevelRecovery + 10 * *((int *)&pSpellDatas[66].uNormalLevelRecovery + v9));
+
+  if ( HasItemEquipped(EQUIP_MAIN_HAND) )
+  {
+    weapon = &pInventoryItems[pEquipment.uMainHand - 1];
+    weapon_desc = &pItemsTable->pItems[weapon->uItemID];
+    if (weapon_desc->uEquipType == EQUIP_WAND)
+    {
+      __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
+      __debugbreak();  // looks like wands were two-handed weapons once, or supposed to be. should not get here now
+      weapon_recovery = pSpellDatas[wand_spell_ids[weapon->uItemID - ITEM_WAND_FIRE]].uExpertLevelRecovery;
+    }
     else
-      v10 = (unsigned __int16)word_4EDED8[(unsigned __int8)v3[29]];
-    v47 = v10;
-  }
-  if ( HasItemEquipped((ITEM_EQUIP_TYPE)0) )
-  {
-    v12 = (int)&v4->pInventoryItems[v4->pEquipment.uOffHand-1];
-    v42 = (unsigned __int16)word_4EDED8[pItemsTable->pItems[*(int *)v12].uSkillType];
-    if ( (signed int)v42 > v47 )
-    {
-      v13 = *(int *)v12;
-      v46 = v12;
-      v3 = (char *)(v11 + 48 * v13);
-      v47 = v42;
-    }
-    v2 = 0;
-  }
+      weapon_recovery = base_recovery_times_per_weapon_type[weapon_desc->uSkillType];
+  }
+  if (HasItemEquipped(EQUIP_OFF_HAND) && GetEquippedItemEquipType(EQUIP_OFF_HAND) != EQUIP_SHIELD) // ADD: shield check because shield recovery is added later and can be accidentally doubled
+  {
+    auto v12 = &pInventoryItems[pEquipment.uOffHand - 1];
+    auto v12_desc = &pItemsTable->pItems[v12->uItemID];
+    if (base_recovery_times_per_weapon_type[v12_desc->uSkillType] > weapon_recovery)
+    {
+      weapon = &pInventoryItems[pEquipment.uOffHand - 1];
+      weapon_desc = &pItemsTable->pItems[weapon->uItemID];
+      weapon_recovery = base_recovery_times_per_weapon_type[pItemsTable->pItems[weapon->uItemID].uSkillType];
+    }
+  }
+
 LABEL_17:
+  uint armour_recovery = 0;
   if ( HasItemEquipped(EQUIP_ARMOUR) )
   {
-    v14 = pItemsTable->pItems[*(int *)&v4->pInventoryItems[v4->pEquipment.uBody-1]].uSkillType;
-    SkillToMastery(v4->pActiveSkills[9]);
-    v15 = (unsigned __int16)word_4EDED8[v14];
-    v35 = 1.0;
-    v43 = v15;
-    if ( v14 == 9 )
-    {
-      v36 = 0.0;
+    auto armour_skill_type = pItemsTable->pItems[pInventoryItems[pEquipment.uBody - 1].uItemID].uSkillType;
+    uint base_armour_recovery = base_recovery_times_per_weapon_type[armour_skill_type];
+
+    float armour_recovery_multipliers[4];
+    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;
+    }
+    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;
+    }
+    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;
     }
     else
     {
-      if ( v14 != 10 )
-      {
-        if ( v14 != 11 )
-        {
-          v36 = 1.0;
-          v37 = 1.0;
-          v16 = 1.0;
-LABEL_27:
-          v18 = v4->pActiveSkills[v14];
-          v38 = v16;
-          v43 = (signed __int64)((double)v43 * *(&v34 + SkillToMastery(v18)));
-          v2 = 0;
-          goto LABEL_28;
-        }
-        v17 = 0.5;
-        v36 = 0.5;
-LABEL_26:
-        v37 = v17;
-        v16 = 0.0;
-        goto LABEL_27;
-      }
-      v36 = 0.5;
-    }
-    v17 = 0.0;
-    goto LABEL_26;
-  }
-LABEL_28:
-  if ( HasItemEquipped((ITEM_EQUIP_TYPE)v2) && v19->GetEquippedItemEquipType(v2) == 4 )
-  {
-    v20 = 9 * v4->pEquipment.uOffHand;
-    v35 = 1.0;
-    v21 = 3 * *(int *)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * v20 + 5];
-    v36 = 0.0;
-    v22 = pItemsTable->pItems[16 * v21 / 0x30u].uSkillType;
-    v37 = 0.0;
-    v23 = (unsigned __int16)word_4EDED8[v22];
-    v38 = 0.0;
-    v45 = v23;
-    v24 = SkillToMastery(v4->pActiveSkills[v22]);
-    v45 = (signed __int64)((double)v45 * *(&v34 + v24));
-  }
-  v25 = GetActualSpeed();
-  v39 = _48EA1B_get_static_effect(v25);
-  v42 = v2;
-  if ( v3 != (char *)v2 )
-  {
-    v26 = (unsigned __int8)v3[29];
-    LOBYTE(v27) = GetActualSkillLevel((enum PLAYER_SKILL_TYPE)(unsigned __int8)v3[29]);
-    if ( v27 && (v26 == 1 || v26 == 3 || v26 == 5) )
-    {
-      v28 = &v4->pActiveSkills[v26];
-      if ( (signed int)SkillToMastery(*v28) >= 2 )
-        v40 = *(char *)v28 & 0x3F;
-    }
-    v2 = 0;
-    if ( v3[29] == 7 )
-      v42 = 1;
-  }
-  if ( a2 == v2 )
-  {
-    if ( v42 == v2 )
-    {
-      LOBYTE(v29) = GetActualSkillLevel(PLAYER_SKILL_ARMSMASTER);
-      if ( v29 != v2 )
-      {
-        v30 = v29 & 0x3F;
-        v44 = v29 & 0x3F;
-        if ( (signed int)SkillToMastery(v29) >= 4 )
-          v44 += v30;
-      }
-    }
-  }
-  if ( SHIDWORD(v4->pPlayerBuffs[7].uExpireTime) >= (signed int)v2
-    && (SHIDWORD(v4->pPlayerBuffs[7].uExpireTime) > (signed int)v2 || LODWORD(v4->pPlayerBuffs[7].uExpireTime) > v2) )
+      assert(false && "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];
+  }
+
+  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 = &pInventoryItems[pEquipment.uOffHand - 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]);
+  }
+
+  uint player_speed_recovery_reduction = _48EA1B_get_static_effect(GetActualSpeed()),
+       sword_axe_bow_recovery_reduction = 0;
+  bool shooting_laser = false;
+  if (weapon_desc)
+  {
+    if (GetActualSkillLevel((PLAYER_SKILL_TYPE)weapon_desc->uSkillType) &&
+        (weapon_desc->uSkillType == PLAYER_SKILL_SWORD || weapon_desc->uSkillType == PLAYER_SKILL_AXE || weapon_desc->uSkillType == PLAYER_SKILL_BOW) )
+    {
+      if (SkillToMastery(pActiveSkills[weapon_desc->uSkillType]) >= 2 )  // Expert   Sword, Axe & Bow   reduce recovery
+        sword_axe_bow_recovery_reduction = pActiveSkills[weapon_desc->uSkillType] & 0x3F;
+    }
+    if (weapon_desc->uSkillType == PLAYER_SKILL_BLASTER)
+      shooting_laser = true;
+  }
+
+  uint armsmaster_recovery_reduction = 0;
+  if (!bRangedAttack && !shooting_laser)
+  {
+    if (uint armsmaster_level = GetActualSkillLevel(PLAYER_SKILL_ARMSMASTER))
+    {
+      armsmaster_recovery_reduction = armsmaster_level & 0x3F;
+      if (SkillToMastery(armsmaster_level) >= 4)
+        armsmaster_recovery_reduction *= 2;
+    }
+  }
+
+  uint v41 = 0;
+  if (pPlayerBuffs[PLAYER_BUFF_7].uExpireTime > 0)
     v41 = 25;
-  v31 = 0;
-  if ( v46 != v2 )
-  {
-    v32 = *(int *)(v46 + 12);
-    if ( v32 == 59 || v32 == 41 || *(int *)v46 == 500 )
-      v31 = 20;
-  }
-  result = v47 + v43 + v45 - v44 - v31 - v41 - v40 - v39;
-  if ( result < 0 )
-    result = 0;
-  return result;
+
+  uint weapon_enchantment_recovery_reduction = 0;
+  if ( weapon  )
+  {
+    if (weapon->uSpecEnchantmentType == 59 ||
+        weapon->uSpecEnchantmentType == 41 ||
+        weapon->uSpecEnchantmentType == 500)
+      weapon_enchantment_recovery_reduction = 20;
+  }
+
+
+  int recovery = weapon_recovery +
+                 armour_recovery +
+                 shield_recovery
+                 - armsmaster_recovery_reduction
+                 - weapon_enchantment_recovery_reduction
+                 - v41
+                 - sword_axe_bow_recovery_reduction
+                 - player_speed_recovery_reduction;
+
+  if (recovery < 0)
+    recovery = 0;
+  return recovery;
 }
 
 //----- (0048E4F8) --------------------------------------------------------
@@ -4553,43 +4520,44 @@
 }
 
 //----- (0048E8F5) --------------------------------------------------------
-bool Player::Recover(signed int a2)
-{
-  Player *v2; // esi@1
+bool Player::Recover(int dt)
+{
+  //Player *v2; // esi@1
   signed __int64 v3; // qax@1
-  bool result; // eax@4
-
-  v2 = this;
-  v3 = (signed __int64)((double)(a2 * _48EA46_calc_special_bonus_by_items(17)) * 0.01 + (double)a2);
-  if ( v2->uTimeToRecovery - (signed int)v3 > 0 )
-  {
-    v2->uTimeToRecovery -= v3;
-    result = 1;
+  //bool result; // eax@4
+
+  //v2 = this;
+  v3 = (signed __int64)((double)(dt * _48EA46_calc_special_bonus_by_items(17)) * 0.01 + (double)dt);
+
+  Log::Warning(L"Recover(dt = %u/%u - %u", dt, (uint)v3, (uint)uTimeToRecovery);
+
+  if (uTimeToRecovery > v3)
+  {
+    uTimeToRecovery -= v3;
+    return true;
   }
   else
   {
-    v2->uTimeToRecovery = 0;
-    viewparams->bRedrawGameUI = 1;
-    if ( !uActiveCharacter )
+    uTimeToRecovery = 0;
+    viewparams->bRedrawGameUI = true;
+    if (!uActiveCharacter)
       uActiveCharacter = pParty->GetNextActiveCharacter();
-    result = 0;
-  }
-  return result;
+    return false;
+  }
 }
 
 //----- (0048E96A) --------------------------------------------------------
-void Player::SetRecoveryTime(signed int sRecoveryTime)
-{
-  signed int v2; // edx@1
-
-  v2 = sRecoveryTime;
-  if ( sRecoveryTime < 0 )
-    v2 = 0;
-  if ( v2 > this->uTimeToRecovery )
-    this->uTimeToRecovery = v2;
-  if ( pPlayers[uActiveCharacter] == this && !some_active_character )
+void Player::SetRecoveryTime(signed int rec)
+{
+  assert(rec > 0);
+
+  if (rec > uTimeToRecovery)
+    uTimeToRecovery = rec;
+
+  if (pPlayers[uActiveCharacter] == this && !some_active_character)
     uActiveCharacter = pParty->GetNextActiveCharacter();
-  viewparams->bRedrawGameUI = 1;
+
+  viewparams->bRedrawGameUI = true;
 }
 // 50C0C4: using guessed type int some_active_character;
 
@@ -4626,33 +4594,31 @@
 //----- (0048EA46) --------------------------------------------------------
 int Player::_48EA46_calc_special_bonus_by_items(int a2)
 {
-  int v2; // edi@1
   int v3; // esi@1
   int v4; // edx@2
   int v5; // eax@3
   char *v6; // eax@4
 
-  v2 = 0;
   v3 = 0;
   while ( 1 )
   {
     if ( !HasItemEquipped((ITEM_EQUIP_TYPE)v3) )
       goto LABEL_11;
-    v5 = pEquipment.uOffHand  - 1;            // BUG
-                                                // v5 = _this->cEquippedItems.uOffHand - 1;
+    v5 = pEquipment.pIndices[v3]  - 1;
     if ( a2 != 17 )
-      break;
+    {
+      if ( a2 != 24 || this->pInventoryItems[v5].uSpecEnchantmentType != 24 )
+        goto LABEL_11;
+      return 5;
+    }
     v6 = (char *)this + 36 * v5;
     if ( *((int *)v6 + 133) == 533 || *((int *)v6 + 136) == 17 )
       return 50;
 LABEL_11:
     ++v3;
     if ( (signed int)v3 >= 16 )
-      return v2;
-  }
-  if ( a2 != 24 || this->pInventoryItems[v5].uSpecEnchantmentType != 24 )
-    goto LABEL_11;
-  return 5;
+      return 0;
+  }
 }
 
 //----- (0048EAAE) --------------------------------------------------------
@@ -4877,7 +4843,7 @@
       v31 = *(&v6->pEquipment.uOffHand + v65) - 1;
       if ( v3 == 9 )
       {
-        v32 = GetEquippedItemEquipType(v65);
+        v32 = GetEquippedItemEquipType((ITEM_EQUIP_TYPE)v65);
         if ( v32 >= 3 )
         {
           if ( v32 <= 11 )
@@ -5438,9 +5404,9 @@
   {
     if ( IsUnarmed() != 1 )
     {
-      if ( v6->HasItemEquipped(EQUIP_TWO_HANDED) )
-      {
-        v22 = this->GetEquippedItemEquipType(1u);
+      if ( v6->HasItemEquipped(EQUIP_MAIN_HAND) )
+      {
+        v22 = this->GetEquippedItemEquipType(EQUIP_MAIN_HAND);
         if ( v22 >= 0 )
         {
           if ( v22 <= 2 )
@@ -5461,7 +5427,7 @@
           }
         }
       }
-      if ( a3 || !v6->HasItemEquipped((ITEM_EQUIP_TYPE)0) || (v28 = v27->GetEquippedItemEquipType(0), v28 < 0) || v28 > 2 )
+      if ( a3 || !v6->HasItemEquipped(EQUIP_OFF_HAND) || (v28 = v27->GetEquippedItemEquipType(EQUIP_OFF_HAND), v28 < 0) || v28 > 2 )
         return v5 + v62 + v61;
       v15 = pItemsTable->pItems[v29].uDamageMod;
       v14 = pItemsTable->pItems[v29].uDamageDice * pItemsTable->pItems[v29].uDamageRoll;
@@ -5485,16 +5451,16 @@
       v5 = 0;
       return v5 + v62 + v61;
     }
-    if ( v6->HasItemEquipped(EQUIP_TWO_HANDED) )
-    {
-      v17 = this->GetEquippedItemEquipType(1u);
+    if ( v6->HasItemEquipped(EQUIP_MAIN_HAND) )
+    {
+      v17 = this->GetEquippedItemEquipType(EQUIP_MAIN_HAND);
       if ( v17 >= 0 )
       {
         if ( v17 <= 2 )
           v5 = pItemsTable->pItems[*(int *)&v6->pInventoryItems[v6->pEquipment.uMainHand-1]].uDamageMod;
       }
     }
-    if ( a3 || !v6->HasItemEquipped((ITEM_EQUIP_TYPE)0) || (v19 = v18->GetEquippedItemEquipType(0), v19 < 0) || v19 > 2 )
+    if ( a3 || !v6->HasItemEquipped(EQUIP_OFF_HAND) || (v19 = v18->GetEquippedItemEquipType(EQUIP_OFF_HAND), v19 < 0) || v19 > 2 )
       return v5 + v62 + v61;
     v20 = *(int *)&v6->pInventoryItems[v6->pEquipment.uOffHand-1];
     goto LABEL_365;
@@ -5506,9 +5472,9 @@
       v5 = 1;
       return v5 + v62 + v61;
     }
-    if ( v6->HasItemEquipped(EQUIP_TWO_HANDED) )
-    {
-      v9 = this->GetEquippedItemEquipType(1u);
+    if ( v6->HasItemEquipped(EQUIP_MAIN_HAND) )
+    {
+      v9 = this->GetEquippedItemEquipType(EQUIP_MAIN_HAND);
       if ( v9 >= 0 )
       {
         if ( v9 <= 2 )
@@ -5522,7 +5488,7 @@
         }
       }
     }
-    if ( a3 || !v6->HasItemEquipped((ITEM_EQUIP_TYPE)0) || (v12 = v11->GetEquippedItemEquipType(0), v12 < 0) || v12 > 2 )
+    if ( a3 || !v6->HasItemEquipped(EQUIP_OFF_HAND) || (v12 = v11->GetEquippedItemEquipType(EQUIP_OFF_HAND), v12 < 0) || v12 > 2 )
       return v5 + v62 + v61;
     v14 = pItemsTable->pItems[this->pInventoryItems[this->pEquipment.uOffHand].uItemID].uDamageMod;
     v15 = pItemsTable->pItems[this->pInventoryItems[this->pEquipment.uOffHand].uItemID].uDamageDice;
--- a/Player.h	Tue Mar 26 06:40:04 2013 +0200
+++ b/Player.h	Tue Mar 26 12:40:27 2013 +0200
@@ -8,6 +8,7 @@
 #define PLAYER_BUFF_BLESS            1
 #define PLAYER_BUFF_FATE             4
 #define PLAYER_BUFF_HAMMERHANDS      6
+#define PLAYER_BUFF_7                7
 #define PLAYER_BUFF_PAIN_REFLECTION 10
 #define PLAYER_BUFF_PRESERVATION    11
 #define PLAYER_BUFF_REGENERATION    12
@@ -184,7 +185,7 @@
 };
 
 /*  328 */
-enum PLAYER_SKILL_TYPE
+enum PLAYER_SKILL_TYPE: unsigned __int8
 {
   PLAYER_SKILL_STAFF = 0,
   PLAYER_SKILL_SWORD = 1,
@@ -484,8 +485,8 @@
   bool CanTrainToNextLevel();
   unsigned int GetExperienceDisplayColor();
   int CalculateIncommingDamage(int resistance, signed int type);
-  int GetEquippedItemEquipType(unsigned int uEquipSlot);
-  int GetEquippedItemSkillType(enum ITEM_EQUIP_TYPE uEquipSlot);
+  ITEM_EQUIP_TYPE   GetEquippedItemEquipType(enum ITEM_EQUIP_TYPE uEquipSlot);
+  PLAYER_SKILL_TYPE GetEquippedItemSkillType(enum ITEM_EQUIP_TYPE uEquipSlot);
   bool IsUnarmed();
   bool HasItemEquipped(enum ITEM_EQUIP_TYPE uEquipIndex);
   bool HasEnchantedItemEquipped(int uEnchantment);
@@ -496,7 +497,7 @@
   int ReceiveDamage(signed int type, int resistance);
   int _48DCF6(int a2, struct Actor *pActor);
   unsigned int GetSpellSchool(unsigned int uSpellID);
-  int GetAttackRecoveryTime(int a2);
+  int GetAttackRecoveryTime(bool bRangedAttack);
   int GetMaxHealth();
   int GetMaxMana();
   int GetBaseAC();
--- a/SaveLoad.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/SaveLoad.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -191,7 +191,7 @@
         auto uItemID = pParty->pPlayers[i].pInventoryItems[uEquipIdx - 1].uItemID;
         if (pItemsTable->pItems[uItemID].uEquipType == 12)
         {
-          __debugbreak();
+                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
           v31 = *((int *)&pSpellDatas[66].uNormalLevelRecovery + uItemID);
           stru_A750F8[i]._494836(v31, i + 9);
         }
--- a/Time.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/Time.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -2,6 +2,7 @@
 
 #include "Time.h"
 #include "Keyboard.h"
+#include "Log.h"
 
 #include "mm7_data.h"
 
@@ -20,7 +21,7 @@
 //----- (00426317) --------------------------------------------------------
 unsigned __int64 Timer::Time()
 {
-  uint v2 = (timeGetTime() << 7) / 0x3E8;
+  uint v2 = (timeGetTime() * 128) / 1000;
   if (v2 < uStartTime)
     uStartTime = 0;
   return v2;
@@ -75,27 +76,25 @@
 //----- (004263B7) --------------------------------------------------------
 void Timer::Update()
 {
-  Timer *v1; // esi@1
-  unsigned int v2; // eax@2
-  signed int v3; // eax@3
-  char v4; // zf@5
+  //Timer *v1; // esi@1
+  //unsigned int v2; // eax@2
+  //signed int v3; // eax@3
+  //char v4; // zf@5
+
+
+  unsigned __int64 new_time = Time();
+  while (new_time <= uStartTime)
+    new_time = Time();
 
-  v1 = this;
-  do
-  {
-    v2 = Time() - v1->uStartTime;
-    v1->uTimeElapsed = v2;
-  }
-  while ( (signed int)v2 <= 0 );
-  v1->uStartTime = Time();
-  v3 = v1->uTimeElapsed;
-  if ( v3 > 32 )
-    v3 = 32;
-  v4 = v1->bPaused == 0;
-  v1->uTimeElapsed = v3;
-  if ( v4 && !v1->bTackGameTime )
-    v1->uTotalGameTimeElapsed += v3;
-  v1->dt_in_some_format = (v3 << 16) / 128;
+  uTimeElapsed = new_time - uStartTime;
+  uStartTime = new_time;
+
+  if (uTimeElapsed > 32)
+    uTimeElapsed = 32;
+
+  if (!bPaused && !bTackGameTime)
+    uTotalGameTimeElapsed += uTimeElapsed;
+  dt_in_some_format = (uTimeElapsed << 16) / 128;
 }
 
 //----- (00426402) --------------------------------------------------------
--- a/UICharacter.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/UICharacter.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -2375,9 +2375,9 @@
                                                                             }
 LABEL_209:
                                                                         if ( pPlayer->pEquipment.uMainHand
-                                                                            && (pPlayer->GetEquippedItemEquipType(1u) == 1
-                                                                            || pPlayer->GetEquippedItemSkillType(EQUIP_TWO_HANDED) == 4
-                                                                            && !pPlayer->pEquipment.uOffHand) )
+                                                                            && (pPlayer->GetEquippedItemEquipType(EQUIP_MAIN_HAND) == EQUIP_MAIN_HAND ||
+                                                                                pPlayer->GetEquippedItemSkillType(EQUIP_MAIN_HAND) == EQUIP_SHIELD &&
+                                                                                !pPlayer->pEquipment.uOffHand) )
                                                                             {
                                                                             v91 = 17 * pBodyComplection + v90;
                                                                             v92 = v91;
--- a/UIHouses.h	Tue Mar 26 06:40:04 2013 +0200
+++ b/UIHouses.h	Tue Mar 26 12:40:27 2013 +0200
@@ -1,5 +1,4 @@
 #pragma once
-
 #include "stru159.h"
 
 enum HOUSE_DIALOGUE_MENU: unsigned __int32
--- a/UIPopup.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/UIPopup.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -406,8 +406,8 @@
     //v20 = item_desc->uEquipType;
     switch (item_desc->uEquipType)
         {
-    case EQUIP_ONE_OR_TWO_HANDS:
-    case EQUIP_TWO_HANDED:
+    case EQUIP_OFF_HAND:
+    case EQUIP_MAIN_HAND:
         sprintfex(out_text + 100, "%s: +%d   %s: %dd%d", pGlobalTXT_LocalizationStrings[LOCSTR_ATTACK],
             (int)item_desc->uDamageMod, pGlobalTXT_LocalizationStrings[53], (int)item_desc->uDamageDice, (int)item_desc->uDamageRoll); //"Damage"
         if (item_desc->uDamageMod)
@@ -1430,8 +1430,8 @@
 
 
 //----- (00417BB5) --------------------------------------------------------
-const char *__fastcall CharacterUI_GetSkillDescText(unsigned int uPlayerID, enum PLAYER_SKILL_TYPE uPlayerSkillType)
-    {
+const char *__fastcall CharacterUI_GetSkillDescText(unsigned int uPlayerID, PLAYER_SKILL_TYPE uPlayerSkillType)
+{
     //enum PLAYER_SKILL_TYPE v2; // esi@1
     //unsigned int v3; // ebx@1
     int v4; // edi@1
--- a/mm7_2.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/mm7_2.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -10379,9 +10379,12 @@
                 v22 = _this.uItemID;
                 v50 = v22;
 				if ( v50 )
+                {
+                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
 				  stru_A750F8[uActiveCharacter - 1]._494836(
 					*((int *)&pSpellDatas[66].uNormalLevelRecovery + v50),
 					uActiveCharacter - 1 + 9);
+                }
 				break;
               }
               v23 = v0->FindFreeInventorySlot();
@@ -10397,9 +10400,11 @@
               v22 = *(int *)v50;
 			  v50 = v22;
 			  if ( v50 )
+              {
+                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
 				stru_A750F8[uActiveCharacter - 1]._494836(
-				*((int *)&pSpellDatas[66].uNormalLevelRecovery + v50),
-				uActiveCharacter - 1 + 9);
+				*((int *)&pSpellDatas[66].uNormalLevelRecovery + v50), uActiveCharacter - 1 + 9);
+              }
 			  break;
             }
           }
@@ -10419,9 +10424,12 @@
               v22 = *(int *)v50;
 			  v50 = v22;
 			  if ( v50 )
+              {
+                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
 				stru_A750F8[uActiveCharacter - 1]._494836(
 				*((int *)&pSpellDatas[66].uNormalLevelRecovery + v50),
 				uActiveCharacter - 1 + 9);
+              }
 			  break;
         }
         --v53;
@@ -10440,9 +10448,12 @@
         if ( v51 )
           v0->pEquipment.uOffHand = 0;
         if ( v50 )
+        {
+                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
           stru_A750F8[uActiveCharacter - 1]._494836(
             *((int *)&pSpellDatas[66].uNormalLevelRecovery + v50),
             uActiveCharacter - 1 + 9);
+        }
         break;
       case 1u:
         if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) )
--- a/mm7_3.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/mm7_3.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -15983,6 +15983,7 @@
   {
     do
     {
+      __debugbreak();
       *(&v31.uDistance + v18) = pParty->pPlayers[*(&v1->field_0 + 4 * (*(&a3.uDistance + v18) + 2)) >> 3].GetAttackRecoveryTime(
                                   v2);
       ++v18;
--- a/mm7_4.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/mm7_4.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -2377,8 +2377,8 @@
   Player **v16; // esi@43
   Player *v17; // edi@44
   double v18; // st7@44
-  float v19; // ST28_4@48
-  double v20; // ST38_8@48
+  //float v19; // ST28_4@48
+  //double v20; // ST38_8@48
   Player *v21; // esi@51
   signed int v22; // edi@53
   int v23; // eax@59
@@ -2418,7 +2418,7 @@
   //int v57; // [sp-4h] [bp-34h]@18
   int v58; // [sp-4h] [bp-34h]@33
   int v59; // [sp-4h] [bp-34h]@55
-  unsigned int v60; // [sp+10h] [bp-20h]@1
+  //unsigned int v60; // [sp+10h] [bp-20h]@1
   unsigned int v61; // [sp+14h] [bp-1Ch]@1
   Player **v62; // [sp+14h] [bp-1Ch]@50
   //unsigned int a2; // [sp+18h] [bp-18h]@1
@@ -2427,7 +2427,7 @@
 
   //a2 = pParty->uCurrentHour;
   v61 = pParty->uDaysPlayed;
-  v60 = pEventTimer->uTimeElapsed;
+  //auto prev_time = pEventTimer->uTimeElapsed;
   pParty->uTimePlayed += pEventTimer->uTimeElapsed;
   v0 = (signed __int64)(pParty->uTimePlayed * 0.234375) / 60;
   v1 = v0;
@@ -2547,13 +2547,13 @@
   }
   _493938_regenerate();
   v65 = 4;
-  a2a = v60;
-  if ( pParty->uFlags2 & 2 )
-  {
-    v19 = (double)(signed int)v60 * 0.5;
-    v20 = v19 + 6.7553994e15;
-    a2a = LODWORD(v20);
-    if ( SLODWORD(v20) <= 0 )
+  a2a = pEventTimer->uTimeElapsed;
+  if ( pParty->uFlags2 & PARTY_FLAGS_2_RUNNING )
+  {
+    //v19 = (double)(signed int)prev_time * 0.5;
+    //v20 = v19 + 6.7553994e15;
+    a2a *= 0.5f;
+    if (a2a < 1)
       a2a = 1;
   }
   v62 = &pPlayers[1];
@@ -2581,7 +2581,7 @@
     v23 = (int)&v21->field_E0;
     if ( v21->field_E0 )
     {
-      v24 = *(int *)v23 - v60;
+      v24 = *(int *)v23 - pEventTimer->uTimeElapsed;
       if ( v24 > 0 )
       {
         *(int *)v23 = v24;
@@ -2595,7 +2595,7 @@
     v25 = (int)&v21->field_E4;
     if ( v21->field_E4 )
     {
-      v26 = *(int *)v25 - v60;
+      v26 = *(int *)v25 - pEventTimer->uTimeElapsed;
       if ( v26 > 0 )
       {
         *(int *)v25 = v26;
@@ -2609,7 +2609,7 @@
     v27 = (int)&v21->field_E8;
     if ( v21->field_E8 )
     {
-      v28 = *(int *)v27 - v60;
+      v28 = *(int *)v27 - pEventTimer->uTimeElapsed;
       if ( v28 > 0 )
       {
         *(int *)v27 = v28;
@@ -2623,7 +2623,7 @@
     v29 = (int)&v21->field_EC;
     if ( v21->field_EC )
     {
-      v30 = *(int *)v29 - v60;
+      v30 = *(int *)v29 - pEventTimer->uTimeElapsed;
       if ( v30 > 0 )
       {
         *(int *)v29 = v30;
@@ -2637,7 +2637,7 @@
     v31 = (int)&v21->field_F0;
     if ( v21->field_F0 )
     {
-      v32 = *(int *)v31 - v60;
+      v32 = *(int *)v31 - pEventTimer->uTimeElapsed;
       if ( v32 > 0 )
       {
         *(int *)v31 = v32;
@@ -2651,7 +2651,7 @@
     v33 = (int)&v21->field_F4;
     if ( v21->field_F4 )
     {
-      v34 = *(int *)v33 - v60;
+      v34 = *(int *)v33 - pEventTimer->uTimeElapsed;
       if ( v34 > 0 )
       {
         *(int *)v33 = v34;
@@ -2665,7 +2665,7 @@
     v35 = (int)&v21->field_F8;
     if ( v21->field_F8 )
     {
-      v36 = *(int *)v35 - v60;
+      v36 = *(int *)v35 - pEventTimer->uTimeElapsed;
       if ( v36 > 0 )
       {
         *(int *)v35 = v36;
@@ -2679,7 +2679,7 @@
     v37 = (int)&v21->field_FC;
     if ( v21->field_FC )
     {
-      v38 = *(int *)v37 - v60;
+      v38 = *(int *)v37 - pEventTimer->uTimeElapsed;
       if ( v38 > 0 )
       {
         *(int *)v37 = v38;
@@ -2693,7 +2693,7 @@
     v39 = (int)&v21->field_100;
     if ( v21->field_100 )
     {
-      v40 = *(int *)v39 - v60;
+      v40 = *(int *)v39 - pEventTimer->uTimeElapsed;
       if ( v40 > 0 )
       {
         *(int *)v39 = v40;
@@ -2707,7 +2707,7 @@
     v41 = (int)&v21->field_104;
     if ( v21->field_104 )
     {
-      v42 = *(int *)v41 - v60;
+      v42 = *(int *)v41 - pEventTimer->uTimeElapsed;
       if ( v42 > 0 )
       {
         *(int *)v41 = v42;
--- a/mm7_5.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/mm7_5.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -4809,7 +4809,7 @@
     //v51 = (unsigned __int64 *)player->pEquipment.uMainHand;
     int main_hand_idx = player->pEquipment.uMainHand;
     v59 = 1;
-    if ( player->HasItemEquipped(EQUIP_TWO_HANDED) )
+    if ( player->HasItemEquipped(EQUIP_MAIN_HAND) )
     {
       auto main_hand_skill = pItemsTable->pItems[player->pInventoryItems[main_hand_idx - 1].uItemID].uSkillType;
       //v55 = pItemsTable->pItems[player->pInventoryItems[main_hand_idx - 1].uItemID].uSkillType;
@@ -5514,7 +5514,7 @@
           v77 >>= 1;
         if ( v48 == 531 )
           v77 >>= 1;
-        if ( v45->GetEquippedItemEquipType(v75) == 4 && SkillToMastery(v45->pActiveSkills[8]) == 4 )
+        if ( v45->GetEquippedItemEquipType((ITEM_EQUIP_TYPE)v75) == EQUIP_SHIELD && SkillToMastery(v45->pActiveSkills[PLAYER_SKILL_SHIELD]) == 4 )
           v77 >>= 1;
       }
       ++v75;
--- a/mm7_6.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/mm7_6.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -3374,7 +3374,7 @@
         _this = (ItemGen *)1;
         if ( (signed int)SkillToMastery(pPlayer->pActiveSkills[PLAYER_SKILL_BOW]) >= 3 )
           _this = (ItemGen *)2;
-        sRecoveryTime = v17->GetAttackRecoveryTime(1);
+        sRecoveryTime = v17->GetAttackRecoveryTime(true);
         a1.stru_24.Reset();
         v18 = v3->spellnum;
         a1.field_4C = v2;
@@ -7753,7 +7753,8 @@
 
   bool shooting_bow = false,
        shotting_laser = false,
-       shooting_wand = false;
+       shooting_wand = false,
+       melee_attack = false;
   if (laser_weapon_item_id)
   {
     shotting_laser = true;
@@ -7771,6 +7772,8 @@
   }
   else if (target_type == OBJECT_Actor && actor_distance <= 407.2)
   {
+    melee_attack = true;
+
     Vec3_int_ a3;
     a3.x = actor->vPosition.x - pParty->vPosition.x;
     a3.y = actor->vPosition.y - pParty->vPosition.y;
@@ -7792,15 +7795,16 @@
   }
   else
   {
+    melee_attack = true;
     ; // actor out of range or no actor; no ranged weapon so melee attacking air
   }
 
-  if (!pParty->bTurnBasedModeOn)
+  if (!pParty->bTurnBasedModeOn && melee_attack) // wands, bows & lasers will add recovery while shooting spell effect
   {
-    int recovery = player->GetAttackRecoveryTime(0);
+    int recovery = player->GetAttackRecoveryTime(false);
     if (recovery < 30 )
       recovery = 30;
-    player->SetRecoveryTime((signed __int64)(flt_6BE3A4_debug_recmod1 * (double)recovery * 2.133333333333333));
+    player->SetRecoveryTime(flt_6BE3A4_debug_recmod1 * (double)recovery * 2.133333333333333);
   }
 
   
@@ -7817,7 +7821,7 @@
   else
   {
     int main_hand_idx = player->pEquipment.uMainHand;
-    if (player->HasItemEquipped(EQUIP_TWO_HANDED))
+    if (player->HasItemEquipped(EQUIP_MAIN_HAND))
       v34 = pItemsTable->pItems[*(int *)&player->pInventoryItems[main_hand_idx - 1]].uSkillType;
     pTurnEngine->_40471C();
   }
@@ -8695,7 +8699,7 @@
               v6 = pPlayers[uActiveCharacter];
               if ( !v6->uTimeToRecovery )
               {
-                v24 = v6->GetAttackRecoveryTime(0);
+                v24 = v6->GetAttackRecoveryTime(false);
                 if ( !pParty->bTurnBasedModeOn )
                   pPlayers[uActiveCharacter]->SetRecoveryTime(
                     (signed __int64)(flt_6BE3A4_debug_recmod1 * (double)v24 * 2.133333333333333));
--- a/mm7_data.cpp	Tue Mar 26 06:40:04 2013 +0200
+++ b/mm7_data.cpp	Tue Mar 26 12:40:27 2013 +0200
@@ -1230,7 +1230,6 @@
 int dword_4EDEA0[777]; // weak
 int dword_4EDEB4[777]; // weak
 int dword_4EDEC4[777]; // weak
-__int16 word_4EDED8[16] = {100, 90, 60, 100, 80, 100, 80, 30, 10, 10, 20, 30, 100, 0, 0, 0};
 _UNKNOWN unk_4EDF40; // weak
 unsigned int pHiredNPCsIconsOffsetsX[2] = {489, 559};
 unsigned int pHiredNPCsIconsOffsetsY[2] = {152, 152};
--- a/mm7_data.h	Tue Mar 26 06:40:04 2013 +0200
+++ b/mm7_data.h	Tue Mar 26 12:40:27 2013 +0200
@@ -818,7 +818,6 @@
 extern int dword_4EDEA0[]; // weak
 extern int dword_4EDEB4[]; // weak
 extern int dword_4EDEC4[]; // weak
-extern __int16 word_4EDED8[]; // weak
 extern _UNKNOWN unk_4EDF40; // weak
 extern unsigned int pHiredNPCsIconsOffsetsX[2];
 extern unsigned int pHiredNPCsIconsOffsetsY[2];
@@ -1663,11 +1662,6 @@
 unsigned int __fastcall UI_GetHealthManaStringColor(signed int a1, signed int a2);
 signed int __thiscall GetConditionDrawColor(unsigned int uConditionIdx); // idb
 char __fastcall sub_4179BC_draw_tooltip(const char *a1, const char *a2); // idb
-unsigned int __fastcall GetSkillColor(unsigned int uPlayerClass, enum PLAYER_SKILL_TYPE uPlayerSkillType, signed int skill_level);
-const char *__fastcall CharacterUI_GetSkillDescText(unsigned int uPlayerID, enum PLAYER_SKILL_TYPE uPlayerSkillType);
-char __cdecl CharacterUI_SkillsTab_ShowHint();
-char __cdecl CharacterUI_StatsTab_ShowHint();
-char __fastcall CharacterUI_StatsTab_Draw(unsigned int uPlayerID); // idb
 void FillAwardsData();
 void __cdecl sub_419220();
 void __cdecl sub_419379();