changeset 23:509744251c8e

Player-related members
author Nomad
date Sun, 14 Oct 2012 00:27:38 +0200
parents e7ee737cd473
children 74940016abc8 77de07f99e03
files GUIWindow.cpp Game.cpp Items.cpp Items.h Mouse.cpp OSAPI.cpp Party.cpp Player.cpp Player.h mm7_1.cpp mm7_2.cpp mm7_3.cpp mm7_4.cpp mm7_5.cpp mm7_6.cpp mm7_data.cpp mm7_data.h stru6.cpp
diffstat 18 files changed, 530 insertions(+), 485 deletions(-) [+]
line wrap: on
line diff
--- a/GUIWindow.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/GUIWindow.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -270,7 +270,7 @@
   v24 = sub_4178FE(pPlayer->sMana, v23);
   sprintfex(pTmpBuf2, "%s : ", pGlobalTXT_LocalizationStrings[212], v24, v22, v21);
   strcat(pTmpBuf, pTmpBuf2);
-  v25 = pPlayer->GetMajorConditionrIdx();
+  v25 = pPlayer->GetMajorConditionIdx();
   v26 = aCharacterConditionNames[v25];
   v27 = GetConditionDrawColor(v25);
   sprintfex(pTmpBuf2, "%s: ", pGlobalTXT_LocalizationStrings[47], v27, v26);
@@ -1241,7 +1241,7 @@
   LoadSpellbook(v1->field_1A4E);
   v3 = 0;
   a2 = 0;
-  v7 = (int)(&v1->pFileSpellbook + v1->field_1A4E);
+  v7 = (int)(&v1->spellbook.pFireSpellbook + v1->field_1A4E);
   do
   {
     if ( *(char *)(v7 + v3) )
@@ -1713,9 +1713,9 @@
   std::string v21; // [sp-18h] [bp-50h]@2
   const char *v22; // [sp-8h] [bp-40h]@2
   int v23; // [sp-4h] [bp-3Ch]@2
-  char Dest; // [sp+Ch] [bp-2Ch]@32
-  char v25; // [sp+Fh] [bp-29h]@32
-  char v26; // [sp+11h] [bp-27h]@34
+  char Dest[6]; // [sp+Ch] [bp-2Ch]@32
+  //char v25; // [sp+Fh] [bp-29h]@32
+  //char v26; // [sp+11h] [bp-27h]@34
   const char *v27; // [sp+20h] [bp-18h]@25
   int v28; // [sp+24h] [bp-14h]@25
   int v29; // [sp+28h] [bp-10h]@1
@@ -1770,11 +1770,11 @@
             switch ( (unsigned __int8)v11 )
             {
               case 9u:
-                strncpy(&Dest, &v32[v14 + 1], 3u);
-                v25 = 0;
+                strncpy(Dest, &v32[v14 + 1], 3u);
+                Dest[3] = 0;
                 pInString += 3;
-                v29 = atoi(&Dest);
-                v19 = atoi(&Dest);
+                v29 = atoi(Dest);
+                v19 = atoi(Dest);
                 LOBYTE(v11) = (char)v31;
                 v12 = uX + v31->uFrameX + v19;
                 break;
@@ -1787,17 +1787,17 @@
                   goto LABEL_36;
                 break;
               case 0xCu:
-                strncpy(&Dest, &v32[v14 + 1], 5u);
-                v26 = 0;
-                v11 = atoi(&Dest);
+                strncpy(Dest, &v32[v14 + 1], 5u);
+                Dest[5] = 0;
+                v11 = atoi(Dest);
                 pInString += 5;
                 uFontColor = v11;
                 break;
               case 0xDu:
-                strncpy(&Dest, &v32[v14 + 1], 3u);
-                v25 = 0;
+                strncpy(Dest, &v32[v14 + 1], 3u);
+                Dest[3] = 0;
                 pInString += 3;
-                v18 = atoi(&Dest);
+                v18 = atoi(Dest);
                 v11 = v10->GetLineWidth(&v32[pInString]);
                 v12 = v31->uFrameZ - v11 - v18;
                 v13 = uY + v31->uFrameY;
--- a/Game.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/Game.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -218,7 +218,7 @@
   char Source[64]; // [sp+44h] [bp-20h]@76
 
   bLoading = uCurrentMenuID == MENU_LOAD;
-  SetCurrentMenuID(0xFFFFFFFFu);
+  SetCurrentMenuID((MENU_STATE)-1);
   if ( bLoading )
   {
     pParty->Reset();
--- a/Items.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/Items.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -172,7 +172,7 @@
 void ItemGen::Reset()
 {
   this->field_1A = 0;
-  this->uAttributtes = 0;
+  this->uAttributes = 0;
   this->uNumCharges = 0;
   this->uAdditionalValue = 0;
   this->_bonus_strength = 0;
@@ -187,7 +187,7 @@
 {
   unsigned int v2; // eax@1
 
-  v2 = this->uAttributtes;
+  v2 = this->uAttributes;
   if ( v2 & ITEM_TEMP_BONUS )
   {
     if ( uTimePlayed > (signed __int64)this->uExpireTime )
@@ -195,7 +195,7 @@
       this->_bonus_type = 0;
       LOBYTE(v2) = v2 & 0xF7;
       this->uAdditionalValue = 0;
-      this->uAttributtes = v2;
+      this->uAttributes = v2;
     }
   }
 }
@@ -1694,7 +1694,7 @@
 
   v1 = this;
   uBaseValue = pItemsTable->pItems[this->uItemID].uValue;
-  if ( this->uAttributtes & ITEM_TEMP_BONUS || pItemsTable->_456D5E_is_some_material(this) )
+  if ( this->uAttributes & ITEM_TEMP_BONUS || pItemsTable->_456D5E_is_some_material(this) )
     goto LABEL_12;
   if ( v1->_bonus_type )
   {
@@ -1722,7 +1722,7 @@
 {
   const char *result; // eax@2
 
-  if ( this->uAttributtes & ITEM_IDENTIFIED )
+  if ( this->uAttributes & ITEM_IDENTIFIED )
     result = GetIdentifiedName();
   else
     result = pItemsTable->pItems[uItemID].pUnidentifiedName;
@@ -2064,7 +2064,7 @@
     if ( v54 == 5 && rand() % 100 < 5 && !pParty->field_7BA[v17] && v56 < 13 )
     {
       pParty->field_7BA[v17] = 1;
-      v4->uAttributtes = 0;
+      v4->uAttributes = 0;
       v4->uItemID = v17 + 500;
       v5->SetSpecialBonus(v4);
       return;
@@ -2101,9 +2101,9 @@
     && !(unsigned __int16)_449B57_test_bit(pParty->_award_bits, 239) )
     v4->uItemID = ITEM_SPELLBOOK_LIGHT_SUN_BURST;
   if ( BYTE2(pItemsTable->pItems[v4->uItemID + 1].uItemID) )
-    v4->uAttributtes = 0;
+    v4->uAttributes = 0;
   else
-    v4->uAttributtes = 1;
+    v4->uAttributes = 1;
   if ( v5->pItems[v4->uItemID].uEquipType != EQUIP_POTION )
   {
     v4->uAdditionalValue = 0;
--- a/Items.h	Sat Oct 13 20:18:28 2012 +0200
+++ b/Items.h	Sun Oct 14 00:27:38 2012 +0200
@@ -109,7 +109,7 @@
   int _bonus_strength;
   int uAdditionalValue;
   int uNumCharges;
-  unsigned int uAttributtes;
+  unsigned int uAttributes;
   unsigned __int8 uBodyAnchor;
   char uMaxCharges;
   char field_1A;
--- a/Mouse.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/Mouse.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -556,13 +556,13 @@
         while ( v8 < v1->field_4C );
         v6 = v15;
       }
-      if ( pParty->pPickedItem.uAttributtes & 2 )
+      if ( pParty->pPickedItem.uAttributes & 2 )
       {
         pRenderer->_4A6776(a2, v6, v3);
       }
       else
       {
-        if ( pParty->pPickedItem.uAttributtes & 1 )
+        if ( pParty->pPickedItem.uAttributes & 1 )
           pRenderer->DrawTextureTransparent(a2, v6, v3);
         else
           pRenderer->DrawTransparentGreenShade(a2, v6, v3);
--- a/OSAPI.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/OSAPI.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -21,6 +21,8 @@
 
   pVersion = new OSVersion;
   {
+    Log::Warning(L"OS init: ok");
+
     extern bool MM_Main(const wchar_t *pCmdLine);
     MM_Main(lpCmdLine);
   }
--- a/Party.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/Party.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -170,9 +170,6 @@
     return v12;
   }
 }
-// AE3369: using guessed type char byte_AE3369;
-// AE336A: using guessed type char byte_AE336A;
-// AE336B: using guessed type char byte_AE336B;
 
 
 //----- (00493244) --------------------------------------------------------
@@ -486,7 +483,7 @@
         v10 = v18++ - 35 < 0;
       }
       while ( (unsigned __int8)(v10 ^ v11) | v9 );
-      v12 = (char *)&v5->pInventoryItems[0].uAttributtes;
+      v12 = (char *)&v5->pInventoryItems[0].uAttributes;
       v13 = 138;
       do
       {
@@ -513,10 +510,10 @@
 int Party::Reset()
 {
   //Party *v1; // esi@1
-  unsigned __int64 *pTimePlayed; // edi@1
-  bool v3; // edx@1
-  Player **v4; // eax@1
-  Player *v5; // ecx@1
+  //unsigned __int64 *pTimePlayed; // edi@1
+  //bool v3; // edx@1
+  //Player **v4; // eax@1
+  //Player *v5; // ecx@1
   char v6; // cl@3
   char v7; // al@6
   char v8; // al@9
@@ -532,38 +529,30 @@
   int v18; // edx@24
   Player *v19; // eax@24
 
-  //v1 = this;
-  pTimePlayed = &uTimePlayed;
-  //memset(&this->uTimePlayed, 0, 0x1620Cu);
   field_708 = 15;
   sEyelevel = 160;
-  LOBYTE(v3) = 1;
   uFlags2 = 0;
   uNumGold = 200;
   uNumGoldInBank = 0;
   uNumFoodRations = 7;
   uAlignment = 1;
-  SetUserInterface(1, v3);
-  *((int *)pTimePlayed + 1) = 0;
-  *(int *)pTimePlayed = 0x21C00u;
-  LODWORD(uLastRegenerationTime) = 0x21C00;
-  HIDWORD(uLastRegenerationTime) = 0;
-  bTurnBasedModeOn = 0;
+
+  SetUserInterface(uAlignment, true);
+
+  uTimePlayed = 0x21C00u;
+  uLastRegenerationTime = 0x21C00;
+
+  bTurnBasedModeOn = false;
+
   uActiveCharacter = 1;
   ::pPlayers[0] = pPlayers;
-  v4 = &::pPlayers[1];
-  v5 = pPlayers;
-  do
-  {
-    *v4 = v5;
-    ++v4;
-    ++v5;
-  }
-  while ( (signed int)v4 < (signed int)&qword_A750D8 );
+  for (uint i = 0; i < 4; ++i)
+    ::pPlayers[i + 1] = &pPlayers[i];
+
   pPlayers[0].Reset(0);
-  pPlayers[0].Reset(4u);
-  pPlayers[0].Reset(0x18u);
-  pPlayers[0].Reset(0x20u);
+  pPlayers[0].Reset(4);
+  pPlayers[0].Reset(24);
+  pPlayers[0].Reset(32);
   pPlayers[0].uFace = 17;
   pPlayers[0].field_1924 = 17;
   pPlayers[0].uVoiceID = 17;
@@ -904,7 +893,7 @@
     v11 = 4;
     do
     {
-      v2 = ((Player *)(v1 - 6812))->GetMajorConditionrIdx();
+      v2 = ((Player *)(v1 - 6812))->GetMajorConditionIdx();
       if ( v2 == 18 || v2 == 17 )
       {
         *((short *)v1 + 1) += LOWORD(pMiscTimer->uTimeElapsed);
--- a/Player.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/Player.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -59,6 +59,54 @@
 
 
 
+ // available skills per class ( 9 classes X 37 skills )
+ // 0 - not available
+ // 1 - available
+ // 2 - primary skill
+unsigned char pSkillAvailabilityPerClass[9][37] =  // byte[] @ MM7.exe::004ED820
+{
+  {0, 2, 0, 1, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
+  {0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 2, 1, 0},
+  {1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 2, 1, 1, 0, 0, 0},
+  {0, 1, 1, 1, 0, 0, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
+  {0, 1, 0, 1, 1, 2, 0, 0, 0, 1, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
+  {0, 1, 1, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0},
+  {0, 0, 0, 0, 0, 0, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
+  {0, 0, 2, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
+  {2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0} // some of these are started at 4ED94C, but needs to be here
+};
+
+
+
+
+unsigned char pBaseHealthByClass[12] = {40, 35, 35, 30, 30, 30, 25, 20, 20, 0, 0, 0};
+unsigned char pBaseManaByClass[12]   = { 0,  0,  0,  5,  5,  0, 10, 10, 15, 0, 0, 0};
+unsigned char pBaseHealthPerLevelByClass[36] = {5, 7, 9, 9, 4, 6, 8, 8, 5, 6, 8, 8, 4, 5, 6, 6, 3, 4, 6, 6, 4, 5, 6, 6, 2, 3, 4, 4, 2, 3, 4, 4, 2, 3, 3, 3};
+unsigned char pBaseManaPerLevelByClass[36]   = {0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 2, 3, 3, 1, 2, 3, 3, 0, 2, 3, 3, 3, 4, 5, 5, 3, 4, 5, 5, 3, 4, 6, 6};
+
+unsigned char pConditionStrengthMultiplier[19]     = {100, 100, 100, 120,  50, 200,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100, 100, 100};
+unsigned char pConditionIntelligenceMultiplier[19] = {100, 100, 100,  50,  25,  10, 100, 100,  75,  60,  50,  30, 100, 100, 100, 100, 100,   1, 100};
+unsigned char pConditionWillpowerMultiplier[19]    = {100, 100, 100,  50,  25,  10, 100, 100,  75,  60,  50,  30, 100, 100, 100, 100, 100,   1, 100};
+unsigned char pConditionEnduranceMultiplier[19]    = {100, 100, 100, 100,  50, 150,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100, 100, 100};
+unsigned char pConditionAccuracyMultiplier[19]     = {100, 100, 100,  50,  10, 100,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100,  50, 100};
+unsigned char pConditionSpeedMultiplier[19]        = {100, 100, 100, 120,  20, 120,  75,  60,  50,  30,  25,  10, 100, 100, 100, 100, 100,  50, 100};
+unsigned char pConditionLuckMultiplier[19]         = {100, 100, 100, 100, 200, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100};
+
+unsigned char pAgeingStrengthMultiplier[4]     = {100,  75,  40, 10};
+unsigned char pAgeingIntelligenceMultiplier[4] = {100, 150, 100, 10};
+unsigned char pAgeingWillpowerMultiplier[4]    = {100, 150, 100, 10};
+unsigned char pAgeingEnduranceMultiplier[4]    = {100,  75,  40, 10};
+unsigned char pAgeingAccuracyMultiplier[4]     = {100, 100,  40, 10};
+unsigned char pAgeingSpeedMultiplier[4]        = {100, 100,  40, 10};
+unsigned char pAgeingLuckMultiplier[4]         = {100, 100, 100, 100};
+
+unsigned int pAgeingTable[4] = {50, 100, 150, 65535};
+
+unsigned int pConditionImportancyTable[18] = {16, 15, 14, 17, 13, 2, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 1, 0};
+
+
+
+
 
 //----- (00490913) --------------------------------------------------------
 signed int __cdecl PlayerCreation_ComputeAttributeBonus()
@@ -195,7 +243,7 @@
     result = v2->uOffHand;
     if ( v2->uOffHand )
     {
-      result = *(int *)&this->pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
+      result = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
       if ( result )
       {
         if ( result != 64 && result != 65 )
@@ -236,7 +284,7 @@
   int v11; // [sp+Ch] [bp-4h]@6
 
   v2 = this;
-  v3 = GetMajorConditionrIdx();
+  v3 = GetMajorConditionIdx();
   v4 = 0;
   if ( (signed int)v3 >= 14 )
   {
@@ -396,13 +444,13 @@
   v2 = (signed int)ptr_507BC0->ptr_1C;
   if ( v2 == 78 || v2 > 80 && v2 <= 82 )
   {
-    if ( GetMajorConditionrIdx() == 18 )
+    if ( GetMajorConditionIdx() == 18 )
       goto LABEL_6;
-    v3 = GetMajorConditionrIdx() == 17;
+    v3 = GetMajorConditionIdx() == 17;
   }
   else
   {
-    v3 = GetMajorConditionrIdx() == 18;
+    v3 = GetMajorConditionIdx() == 18;
   }
   if ( !v3 )
     return 1;
@@ -481,7 +529,7 @@
         do
         {
           LOWORD(v5) = 9 * v10[v6];
-          if ( !(BYTE1(v2->pInventoryItems[v10[v6]].uAttributtes) & 2) )
+          if ( !(BYTE1(v2->pInventoryItems[v10[v6]].uAttributes) & 2) )
           {
             v5 = (ItemGen *)((char *)&v2->pInventoryItems[v10[rand() % v4]] + 20);
             v5->uItemID |= 2u;
@@ -495,7 +543,7 @@
     {
       for ( i = 0; i < v4; ++i )
       {
-        v8 = (ItemGen **)&v2->pInventoryItems[v10[i]].uAttributtes;
+        v8 = (ItemGen **)&v2->pInventoryItems[v10[i]].uAttributes;
         v5 = *v8;
         if ( !(BYTE1(v5) & 2) )
         {
@@ -1708,7 +1756,7 @@
   unsigned int uSlota; // [sp+14h] [bp+4h]@1
 
   pIndices = &this->pInventoryIndices[uSlot];
-  v3 = (ItemGen *)&this->pDarkSpellbook.bIsSpellAvailable[36 * *pIndices + 5];
+  v3 = (ItemGen *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *pIndices + 5];
   v4 = v3->uItemID;
   v3->Reset();
   v5 = pIcons_LOD->LoadTexture(pItemsTable->pItems[v4].pIconName, TEXTURE_16BIT_PALETTE);
@@ -1815,7 +1863,7 @@
       return result;
   }
 LABEL_16:
-  if ( BYTE1(pItem->uAttributtes) & 1 )
+  if ( BYTE1(pItem->uAttributes) & 1 )
     return 6;
 LABEL_26:
   //v14 = &p2DEvents_minus1__20[13 * a4];
@@ -1828,7 +1876,7 @@
     v23 = *v14;
     v24 = pItem->GetValue();
     v17 = v27->_4B8102(v24, v23);
-    if ( !(pItem->uAttributtes & 2) )
+    if ( !(pItem->uAttributes & 2) )
       goto LABEL_39;
     goto LABEL_38;
   }
@@ -1851,7 +1899,7 @@
   v18 = *v14;
   v19 = pItem->GetValue();
   v17 = v27->_4B8102(v19, v18) / 2;
-  if ( pItem->uAttributtes & 2 )
+  if ( pItem->uAttributes & 2 )
     v17 = 1;
   if ( v17 >= 1 )
     goto LABEL_39;
@@ -2157,37 +2205,73 @@
 
 //----- (0048C6AF) --------------------------------------------------------
 Player::Player()
-{
-  Player *v1; // esi@1
-  signed int v2; // ebx@1
-  ItemGen *v3; // edi@1
-  SpellBuff *v4; // eax@3
-  signed int v5; // edx@3
-
-  v1 = this;
-  v2 = 138;
-  v3 = this->pInventoryItems;
-  do
-  {
-    v3->Reset();
-    ++v3;
-    --v2;
-  }
-  while ( v2 );
-  v4 = v1->pPlayerBuffs;
-  v5 = 24;
-  do
-  {
-    v4->uSkill = 0;
-    v4->uPower = 0;
-    LODWORD(v4->uExpireTime) = 0;
-    HIDWORD(v4->uExpireTime) = 0;
-    v4->uCaster = 0;
-    v4->uFlags = 0;
-    ++v4;
-    --v5;
-  }
-  while ( v5 );
+{  
+  memset(&pEquipment, 0, sizeof(PlayerEquipment));
+  memset(pInventoryIndices, 0, 126 * sizeof(int));
+  for (uint i = 0; i < 126; ++i)
+    pInventoryItems[i].Reset();
+  for (uint i = 0; i < 12; ++i)
+    pEquippedItems[i].Reset();
+
+
+  for (uint i = 0; i < 24; ++i)
+  {
+    pPlayerBuffs[i].uSkill = 0;
+    pPlayerBuffs[i].uSkill = 0;
+    pPlayerBuffs[i].uPower = 0;
+    pPlayerBuffs[i].uExpireTime = 0;
+    pPlayerBuffs[i].uCaster = 0;
+    pPlayerBuffs[i].uFlags = 0;
+  }
+
+  pName[0] = 0;
+  uFace = 0;
+  uVoiceID = 0;
+  memset(pConditions, 0, 20 * sizeof(__int64));
+
+  field_BB = 0;
+
+  uMight = uMightBonus = 0;
+  uIntelligence = uIntelligenceBonus = 0;
+  uWillpower = uWillpowerBonus = 0;
+  uEndurance = uEnduranceBonus = 0;
+  uSpeed = uSpeedBonus = 0;
+  uAccuracy = uAccuracyBonus = 0;
+  uLuck = uLuckBonus = 0;
+  uLevel = sLevelModifier = 0;
+  sAgeModifier = 0;
+
+  memset(field_1F5, 0, 30);
+
+  sResFireBase = sResFireBonus = 0;
+  sResAirBase = sResAirBonus = 0;
+  sResWaterBase = sResWaterBonus = 0;
+  sResEarthBase = sResEarthBonus = 0;
+  sResMagicBase = sResMagicBonus = 0;
+  sResSpiritBase = sResSpiritBonus = 0;
+  sResMindBase = sResMindBonus = 0;
+  sResBodyBase = sResBodyBonus = 0;
+  sResLightBase = sResLightBonus = 0;
+  sResDarkBase = sResDarkBonus = 0;
+
+  uTimeToRecovery = 0;
+
+  uSkillPoints = 0;
+  sHealth = 0;
+  sMana = 0;
+  uQuickSpell = 0;
+  memset(pInstalledBeacons, 0, 5 * sizeof(LloydBeacon));
+
+  uExpressionID = 0;
+  uExpressionTimePassed = 0;
+  uExpressionTimeLength = 0;
+
+  uNumDivineInterventionCastsThisDay = 0;
+  uNumArmageddonCasts = 0;
+  uNumFireSpikeCasts = 0;
+
+  memset(field_1988, 0, 49 * sizeof(int));
+  memset(field_1A50, 0, 64 * sizeof(char));
 }
 
 //----- (0048C6F6) --------------------------------------------------------
@@ -2219,7 +2303,7 @@
   v20 = thos;
   v2 = pItem->uItemID;
   if ( !BYTE2(pItemsTable->pItems[v2 + 1].uItemID) )
-    pItem->uAttributtes |= 1u;
+    pItem->uAttributes |= 1u;
   v15 = 0;
   v16 = 1;
   v18 = 3;
@@ -2261,7 +2345,7 @@
         goto LABEL_15;
       }
     }
-    memcpy(&v9->pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5], pItem, 0x24u);
+    memcpy(&v9->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5], pItem, 0x24u);
     pItem->Reset();
     pAudioPlayer->PlaySound(SOUND_GoldReceived, 0, 0, -1, 0, 0, 0, 0);
     v19->PlaySound(60, 0);
@@ -2365,7 +2449,7 @@
   }
   v4 = pAgeingStrengthMultiplier[v3];
 LABEL_5:
-  v5 = pConditionStrengthMultiplier[GetMajorConditionrIdx()];
+  v5 = pConditionStrengthMultiplier[GetMajorConditionIdx()];
   v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_STRENGTH, 0);
   return v5 * v4 * v1->uMight / 100 / 100 + GetMagicalBonus((CHARACTER_ATTRIBUTE_TYPE)0) + v6 + v1->uMightBonus;
 }
@@ -2394,7 +2478,7 @@
   }
   v4 = pAgeingIntelligenceMultiplier[uAgeLevel];
 LABEL_5:
-  v5 = pConditionIntelligenceMultiplier[GetMajorConditionrIdx()];
+  v5 = pConditionIntelligenceMultiplier[GetMajorConditionIdx()];
   v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_INTELLIGENCE, 0);
   return v5 * v4 * v1->uIntelligence / 100 / 100
        + GetMagicalBonus(CHARACTER_ATTRIBUTE_INTELLIGENCE)
@@ -2426,7 +2510,7 @@
   }
   v4 = pAgeingWillpowerMultiplier[v3];
 LABEL_5:
-  v5 = pConditionWillpowerMultiplier[GetMajorConditionrIdx()];
+  v5 = pConditionWillpowerMultiplier[GetMajorConditionIdx()];
   v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_WILLPOWER, 0);
   return v5 * v4 * v1->uWillpower / 100 / 100
        + GetMagicalBonus(CHARACTER_ATTRIBUTE_WILLPOWER)
@@ -2437,33 +2521,21 @@
 //----- (0048CABC) --------------------------------------------------------
 int Player::GetActualEndurance()
 {
-  Player *v1; // esi@1
-  unsigned int v2; // eax@1
-  signed int v3; // ecx@1
-  signed int v4; // ebx@4
-  int v5; // edi@5
   int v6; // ebp@5
 
-  v1 = this;
-  v2 = this->sAgeModifier + GetBaseAge();
-  v3 = 0;
-  while ( (signed int)v2 >= (signed int)pAgeingTable[v3] )
-  {
-    ++v3;
-    if ( v3 >= 4 )
-    {
-      v4 = 100;
-      goto LABEL_5;
-    }
-  }
-  v4 = pAgeingEnduranceMultiplier[v3];
-LABEL_5:
-  v5 = pConditionEnduranceMultiplier[GetMajorConditionrIdx()];
-  v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0);
-  return v5 * v4 * v1->uEndurance / 100 / 100
+  uint uActualAge = GetBaseAge() + sAgeModifier;
+  uint uAgeingMultiplier = 100;
+  for (uint i = 0; i < 4; ++i)
+    if (uActualAge >= pAgeingTable[i])
+      uAgeingMultiplier = pAgeingEnduranceMultiplier[i];
+    else break;
+
+  auto uConditionMult = pConditionEnduranceMultiplier[GetMajorConditionIdx()];
+  auto uItemBonus = GetItemsBonus(CHARACTER_ATTRIBUTE_ENDURANCE, 0);
+  return uConditionMult * uAgeingMultiplier * uEndurance / 100 / 100
        + GetMagicalBonus(CHARACTER_ATTRIBUTE_ENDURANCE)
-       + v6
-       + v1->uEnduranceBonus;
+       + uItemBonus
+       + uEnduranceBonus;
 }
 
 //----- (0048CB39) --------------------------------------------------------
@@ -2490,7 +2562,7 @@
   }
   v4 = pAgeingAccuracyMultiplier[v3];
 LABEL_5:
-  v5 = pConditionAccuracyMultiplier[GetMajorConditionrIdx()];
+  v5 = pConditionAccuracyMultiplier[GetMajorConditionIdx()];
   v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_ACCURACY, 0);
   return v5 * v4 * v1->uAccuracy / 100 / 100
        + GetMagicalBonus(CHARACTER_ATTRIBUTE_ACCURACY)
@@ -2522,7 +2594,7 @@
   }
   v4 = pAgeingSpeedMultiplier[v3];
 LABEL_5:
-  v5 = pConditionSpeedMultiplier[GetMajorConditionrIdx()];
+  v5 = pConditionSpeedMultiplier[GetMajorConditionIdx()];
   v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_SPEED, 0);
   return v5 * v4 * v1->uSpeed / 100 / 100
        + GetMagicalBonus(CHARACTER_ATTRIBUTE_SPEED)
@@ -2562,7 +2634,7 @@
   }
   v4 = pAgeingLuckMultiplier[v3];
 LABEL_11:
-  v5 = pConditionLuckMultiplier[GetMajorConditionrIdx()];
+  v5 = pConditionLuckMultiplier[GetMajorConditionIdx()];
   v6 = GetItemsBonus(CHARACTER_ATTRIBUTE_LUCK, 0);
   return GetMagicalBonus(CHARACTER_ATTRIBUTE_LUCK)
        + v6
@@ -2684,7 +2756,7 @@
   }
   if ( HasItemEquipped(EQUIP_TWO_HANDED) )
   {
-    v6 = (ItemGen *)&v5->pDarkSpellbook.bIsSpellAvailable[36 * v5->pEquipment.uMainHand + 5];
+    v6 = (ItemGen *)&v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v5->pEquipment.uMainHand + 5];
     v7 = v6->uItemID;
     v8 = v6->uItemID;
     v9 = pItemsTable->pItems[v8].uDamageDice;
@@ -2756,7 +2828,7 @@
   {
     if ( v5->HasItemEquipped((ITEM_EQUIP_TYPE)0) )
     {
-      v15 = (ItemGen *)&v5->pDarkSpellbook.bIsSpellAvailable[36 * v5->pEquipment.uOffHand + 5];
+      v15 = (ItemGen *)&v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v5->pEquipment.uOffHand + 5];
       v16 = v15->uItemID;
       v17 = v15->uItemID;
       if ( pItemsTable->pItems[v17].uEquipType != 4 )
@@ -2849,7 +2921,7 @@
   int v7; // edi@4
 
   v1 = this;
-  v2 = *(int *)&this->pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
+  v2 = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
   if ( v2 < 64 || v2 > 65 )
   {
     v4 = GetActualAccuracy();
@@ -2939,7 +3011,7 @@
   result = HasItemEquipped(EQUIP_BOW);
   if ( !result )
     return result;
-  v4 = (ItemGen *)&v2->pDarkSpellbook.bIsSpellAvailable[36 * v2->pEquipment.uBow + 5];
+  v4 = (ItemGen *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2->pEquipment.uBow + 5];
   v5 = v4->uItemID;
   v6 = v4->uItemID;
   v15 = pItemsTable->pItems[v6].uDamageRoll;
@@ -3010,7 +3082,7 @@
   static char player__getmeleedamagestring_static_buff[40]; // idb
 
   v1 = this;
-  v2 = *(int *)&this->pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
+  v2 = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
   if ( v2 < 64 || v2 > 65 )
   {
     v3 = GetMeleeDamageMinimal();
@@ -3036,7 +3108,7 @@
   v8 = v1->pEquipment.uMainHand;
   if ( v8 )
   {
-    v9 = *(int *)&v1->pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    v9 = *(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
     if ( v9 >= 135 )
     {
       if ( v9 <= 159 )
@@ -3062,7 +3134,7 @@
   static char player__getrangeddamagestring_static_buff[40]; // idb
 
   v1 = this;
-  v2 = *(int *)&this->pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
+  v2 = *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * this->pEquipment.uMainHand + 5];
   if ( v2 < 64 || v2 > 65 )
   {
     v3 = GetRangedDamageMin();
@@ -3096,7 +3168,7 @@
   v8 = v1->pEquipment.uMainHand;
   if ( v8 )
   {
-    v9 = *(int *)&v1->pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    v9 = *(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
     if ( v9 >= 135 )
     {
       if ( v9 <= 159 )
@@ -3248,7 +3320,7 @@
 //----- (0048D62C) --------------------------------------------------------
 int Player::GetEquippedItemEquipType(unsigned int uEquipSlot)
 {
-  return pItemsTable->pItems[*(int *)&this->pDarkSpellbook.bIsSpellAvailable[36
+  return pItemsTable->pItems[*(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36
                                                                              * *(&this->pEquipment.uOffHand
                                                                                + uEquipSlot)
                                                                              + 5]].uEquipType;
@@ -3257,7 +3329,7 @@
 //----- (0048D651) --------------------------------------------------------
 int Player::GetEquippedItemSkillType(enum ITEM_EQUIP_TYPE uEquipSlot)
 {
-  return pItemsTable->pItems[*(int *)&this->pDarkSpellbook.bIsSpellAvailable[36
+  return pItemsTable->pItems[*(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36
                                                                              * *(&this->pEquipment.uOffHand
                                                                                + uEquipSlot)
                                                                              + 5]].uSkillType;
@@ -3274,10 +3346,10 @@
 //----- (0048D6AA) --------------------------------------------------------
 bool Player::HasItemEquipped(ITEM_EQUIP_TYPE uEquipIndex)
 {
-  int v2; // eax@1
-
-  v2 = *(&this->pEquipment.uOffHand + uEquipIndex);
-  return v2 && !(this->field_1F5[36 * v2 + 15] & 2);
+  auto i = pEquipment.pIndices[uEquipIndex];
+  if (i)
+    return ~pInventoryItems[i - 1].uAttributes & 0x02;
+  else return false;
 }
 
 //----- (0048D6D0) --------------------------------------------------------
@@ -3308,7 +3380,7 @@
   {
     v6 = 0;
     while ( !HasItemEquipped((ITEM_EQUIP_TYPE)v6)
-         || *(int *)&this->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v7 + 5] != a1 )
+         || *(int *)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v7 + 5] != a1 )
     {
       ++v6;
       if ( (signed int)v6 >= 16 )
@@ -3317,7 +3389,7 @@
     return 1;
   }
   if ( HasItemEquipped((ITEM_EQUIP_TYPE)a2)
-    && *(int *)&v4->pDarkSpellbook.bIsSpellAvailable[36 * *(&v4->pEquipment.uOffHand + v3) + 5] == a1 )
+    && *(int *)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(&v4->pEquipment.uOffHand + v3) + 5] == a1 )
     return 1;
   return 0;
 }
@@ -3713,7 +3785,7 @@
       v13 = this->pInventoryItems;
       do
       {
-        if ( (signed int)v13->uItemID > 0 && (signed int)v13->uItemID <= 134 && !(v13->uAttributtes & 2) )
+        if ( (signed int)v13->uItemID > 0 && (signed int)v13->uItemID <= 134 && !(v13->uAttributes & 2) )
           v46[v4++] = v12;
         ++v12;
         ++v13;
@@ -3763,7 +3835,7 @@
       {
         if ( *v20 > 0 )
         {
-          v21 = *(int *)&v5->pDarkSpellbook.bIsSpellAvailable[36 * *v20 + 5];
+          v21 = *(int *)&v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *v20 + 5];
           if ( v21 > 0 )
           {
             if ( v21 <= 134 )
@@ -3936,7 +4008,7 @@
             goto LABEL_84;
         }
         v28 = v47;
-        memcpy(v27, &v5->pDarkSpellbook.bIsSpellAvailable[36 * v5->pInventoryIndices[v47] + 5], 0x24u);
+        memcpy(v27, &v5->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v5->pInventoryIndices[v47] + 5], 0x24u);
         RemoveItemAtInventoryIndex(v28);
 LABEL_79:
         v42 = 0;
@@ -4043,7 +4115,7 @@
   {
     if ( !HasItemEquipped(EQUIP_BOW) )
       goto LABEL_17;
-    v5 = (int)&v4->pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uBow + 5];
+    v5 = (int)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uBow + 5];
     v46 = v5;
     v3 = (char *)&pItemsTable->pItems[*(int *)v5].pIconName;
     v6 = (unsigned __int16)word_4EDED8[(unsigned __int8)v3[29]];
@@ -4062,7 +4134,7 @@
   }
   if ( HasItemEquipped(EQUIP_TWO_HANDED) )
   {
-    v8 = (int)&v4->pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uMainHand + 5];
+    v8 = (int)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uMainHand + 5];
     v46 = v8;
     v9 = *(int *)v8;
     v3 = (char *)&pItemsTable->pItems[v9].pIconName;
@@ -4074,7 +4146,7 @@
   }
   if ( HasItemEquipped((ITEM_EQUIP_TYPE)0) )
   {
-    v12 = (int)&v4->pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uOffHand + 5];
+    v12 = (int)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uOffHand + 5];
     v42 = (unsigned __int16)word_4EDED8[pItemsTable->pItems[*(int *)v12].uSkillType];
     if ( (signed int)v42 > v47 )
     {
@@ -4088,7 +4160,7 @@
 LABEL_17:
   if ( HasItemEquipped(EQUIP_ARMOUR) )
   {
-    v14 = pItemsTable->pItems[*(int *)&v4->pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uBody + 5]].uSkillType;
+    v14 = pItemsTable->pItems[*(int *)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4->pEquipment.uBody + 5]].uSkillType;
     SkillToMastery(v4->pActiveSkills[9]);
     v15 = (unsigned __int16)word_4EDED8[v14];
     v35 = 1.0;
@@ -4130,7 +4202,7 @@
   {
     v20 = 9 * v4->pEquipment.uOffHand;
     v35 = 1.0;
-    v21 = 3 * *(int *)&v4->pDarkSpellbook.bIsSpellAvailable[4 * v20 + 5];
+    v21 = 3 * *(int *)&v4->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * v20 + 5];
     v36 = 0.0;
     v22 = pItemsTable->pItems[16 * v21 / 0x30u].uSkillType;
     v37 = 0.0;
@@ -4186,27 +4258,21 @@
     result = 0;
   return result;
 }
-// 4EDED8: using guessed type __int16 word_4EDED8[];
-// 4EDEDC: using guessed type __int16 word_4EDEDC;
 
 //----- (0048E4F8) --------------------------------------------------------
 int Player::GetMaxHealth()
 {
-  Player *v1; // edi@1
-  int v2; // eax@1
   int v3; // esi@1
   int v4; // esi@1
   int v5; // esi@1
   int v6; // esi@1
   signed int result; // eax@1
 
-  v1 = this;
-  v2 = GetActualEndurance();
-  v3 = _48EA1B_get_static_effect(v2);
-  v4 = pBaseHealthPerLevelByClass[v1->uClass] * (GetActualLevel() + v3);
+  v3 = _48EA1B_get_static_effect(GetActualEndurance());
+  v4 = pBaseHealthPerLevelByClass[uClass] * (GetActualLevel() + v3);
   v5 = GetItemsBonus(CHARACTER_ATTRIBUTE_HEALTH, 0) + v4;
-  v6 = v1->uFullHealthBonus
-     + pBaseHealthByClass[(unsigned int)v1->uClass >> 2]
+  v6 = uFullHealthBonus
+     + pBaseHealthByClass[uClass / 4]
      + GetSkillBonus(CHARACTER_ATTRIBUTE_HEALTH)
      + v5;
   result = 1;
@@ -4275,7 +4341,7 @@
       v7 = pBaseManaPerLevelByClass[v1->uClass] * (GetActualLevel() + v3);
       v8 = GetItemsBonus(CHARACTER_ATTRIBUTE_MANA, 0) + v7;
       v9 = v1->uFullManaBonus
-         + (unsigned __int8)byte_4ED75C[(unsigned int)v1->uClass >> 2]
+         + pBaseManaByClass[v1->uClass / 4]
          + GetSkillBonus(CHARACTER_ATTRIBUTE_MANA)
          + v8;
       if ( v9 < 1 )
@@ -4339,13 +4405,8 @@
 //----- (0048E6DC) --------------------------------------------------------
 unsigned int Player::GetBaseAge()
 {
-  return (signed int)((unsigned int)((signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 60 / 60)
-                    / 0x18)
-       / 7
-       / 4
-       / 12
-       - this->uBirthYear
-       + 1168;
+  return ((__int64)(pParty->uTimePlayed * 0.234375) / 60 / 60 / 24) / 7 / 4 / 12
+       - uBirthYear + 1168;
 }
 
 //----- (0048E72C) --------------------------------------------------------
@@ -4556,18 +4617,13 @@
 }
 
 //----- (0048E9F4) --------------------------------------------------------
-unsigned int Player::GetMajorConditionrIdx()
-{
-  signed int v1; // edx@1
-
-  v1 = 0;
-  while ( !this->pConditions[pConditionImportancyTable[v1]] )
-  {
-    ++v1;
-    if ( v1 >= 18 )
-      return 18;
-  }
-  return pConditionImportancyTable[v1];
+unsigned int Player::GetMajorConditionIdx()
+{
+  for (uint i = 0; i < 18; ++i)
+    if (pConditions[pConditionImportancyTable[i]] != 0)
+      return pConditionImportancyTable[i];
+
+  return 18;
 }
 
 //----- (0048EA1B) --------------------------------------------------------
@@ -4576,13 +4632,12 @@
   __int16 v2; // cx@1
   int v3; // eax@1
 
-  v2 = word_4EDFFC;
+  v2 = word_4EDFFC[0];
   v3 = 0;
   while ( a2 < v2 && v2 )
-    v2 = word_4EDFFE[v3++];
+    v2 = word_4EDFFC[v3++ + 1];
   return player_stat_bonuses[v3];
 }
-// 4EDFFC: using guessed type __int16 word_4EDFFC;
 
 //----- (0048EA46) --------------------------------------------------------
 int Player::_48EA46_calc_special_bonus_by_items(int a2)
@@ -4794,14 +4849,14 @@
     if ( (signed int)attr <= 30 )
     {
       if ( HasItemEquipped(EQUIP_BOW) )
-        v5 = pItemsTable->pItems[*(int *)&v6->pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5]].uDamageMod;
+        v5 = pItemsTable->pItems[*(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5]].uDamageMod;
       return v5 + v62 + v61;
     }
     if ( attr == 31 )
     {
       if ( !HasItemEquipped(EQUIP_BOW) )
         return v5 + v62 + v61;
-      v57 = *(int *)&v6->pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5];
+      v57 = *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5];
       v5 = pItemsTable->pItems[v57].uDamageMod;
       v56 = pItemsTable->pItems[v57].uDamageDice;
       goto LABEL_366;
@@ -4810,7 +4865,7 @@
     {
       if ( !HasItemEquipped(EQUIP_BOW) )
         return v5 + v62 + v61;
-      v20 = *(int *)&v6->pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5];
+      v20 = *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uBow + 5];
       v5 = pItemsTable->pItems[v20].uDamageDice * pItemsTable->pItems[v20].uDamageRoll;
 LABEL_365:
       v56 = pItemsTable->pItems[v20].uDamageMod;
@@ -5449,12 +5504,12 @@
       if ( v17 >= 0 )
       {
         if ( v17 <= 2 )
-          v5 = pItemsTable->pItems[*(int *)&v6->pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uMainHand + 5]].uDamageMod;
+          v5 = pItemsTable->pItems[*(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uMainHand + 5]].uDamageMod;
       }
     }
     if ( a3 || !v6->HasItemEquipped((ITEM_EQUIP_TYPE)0) || (v19 = v18->GetEquippedItemEquipType(0), v19 < 0) || v19 > 2 )
       return v5 + v62 + v61;
-    v20 = *(int *)&v6->pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uOffHand + 5];
+    v20 = *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6->pEquipment.uOffHand + 5];
     goto LABEL_365;
   }
   if ( attr == 27 )
@@ -5985,7 +6040,7 @@
         {
           if ( v2->HasItemEquipped(v71) )
           {
-            v11 = (PLAYER_SKILL_TYPE)pItemsTable->pItems[*(int *)&v2->pDarkSpellbook.bIsSpellAvailable[36 * v9->uOffHand + 5]].uSkillType;
+            v11 = (PLAYER_SKILL_TYPE)pItemsTable->pItems[*(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v9->uOffHand + 5]].uSkillType;
             LOBYTE(v12) = v10->GetActualSkillLevel(v11);
             a1 = v12;
             SkillToMastery(v12);
@@ -6043,7 +6098,7 @@
       {
         if ( v2->HasItemEquipped(v20) )
         {
-          v22 = *(int *)&v2->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v21 + 5];
+          v22 = *(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v21 + 5];
           if ( pItemsTable->pItems[v22].uEquipType <= 1u )
             break;
         }
@@ -6128,7 +6183,7 @@
     {
       if ( v2->HasItemEquipped(v35) )
       {
-        v37 = *(int *)&v2->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v36 + 5];
+        v37 = *(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v36 + 5];
         if ( pItemsTable->pItems[v37].uEquipType <= 1u )
           break;
       }
@@ -6442,74 +6497,46 @@
 }
 
 //----- (0049024A) --------------------------------------------------------
-void Player::Reset(unsigned __int8 uClass)
-{
-  Player *v2; // esi@1
-  signed int v3; // edi@1
-  int v4; // eax@1
-  unsigned __int16 *pSkills; // ebx@1
-
-  v2 = this;
-  v3 = 0;
-  this->uClass = uClass;
-  this->uLuckBonus = 0;
-  this->uSpeedBonus = 0;
-  this->uAccuracyBonus = 0;
-  this->uEnduranceBonus = 0;
-  this->uWillpowerBonus = 0;
-  this->uIntelligenceBonus = 0;
-  this->uMightBonus = 0;
-  v4 = rand();
-  v2->uLevel = 1;
-  v2->uExperience = v4 % 100 + 251;
-  pSkills = v2->pActiveSkills;
-  v2->uBirthYear = 1147 - rand() % 6;
-  memset(v2->pActiveSkills, 0, 0x4Au);
-  memset(v2->field_152, 0, 0x40u);
-  memset(&v2->pFileSpellbook, 0, 0x64u);
-  do
-  {
-    if ( *(&byte_4ED820[37 * ((unsigned int)v2->uClass >> 2)] + v3) == 2 )
-    {
-      *pSkills = 1;
-      if ( (unsigned int)(v3 - 12) <= 8 )
-      {
-        switch ( v3 )
-        {
-          case 12:
-            v2->pFileSpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 13:
-            v2->pAirSpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 14:
-            v2->pWaterSpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 15:
-            v2->pEarthSpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 16:
-            v2->pSpiritSpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 17:
-            v2->pMindSpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 18:
-            v2->pBodySpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 19:
-            v2->pLightSpellbook.bIsSpellbookAvailable = 1;
-            break;
-          case 20:
-            v2->pDarkSpellbook.bIsSpellbookAvailable = 1;
-            break;
-        }
-      }
-    }
-    ++v3;
-    ++pSkills;
-  }
-  while ( v3 < 37 );
+void Player::Reset(unsigned __int8 classID)
+{
+  sLevelModifier = 0;
+  sAgeModifier = 0;
+
+  uClass = classID;
+  uLuckBonus = 0;
+  uSpeedBonus = 0;
+  uAccuracyBonus = 0;
+  uEnduranceBonus = 0;
+  uWillpowerBonus = 0;
+  uIntelligenceBonus = 0;
+  uMightBonus = 0;
+  uLevel = 1;
+  uExperience = 251 + rand() % 100;
+  uBirthYear = 1147 - rand() % 6;
+  memset(pActiveSkills, 0, 32 * sizeof(short));
+  memset(field_152, 0, 64);
+  memset(&spellbook, 0, sizeof(PlayerSpells));
+
+  for (uint i = 0; i < 37; ++i)
+  {
+    if (pSkillAvailabilityPerClass[uClass / 4][i] != 2)
+      continue;
+
+    pActiveSkills[i] = 1;
+
+    switch (i)
+    {
+      case PLAYER_SKILL_FIRE:   spellbook.pFireSpellbook.bIsSpellbookAvailable = true;   break;
+      case PLAYER_SKILL_AIR:    spellbook.pAirSpellbook.bIsSpellbookAvailable = true;    break;
+      case PLAYER_SKILL_WATER:  spellbook.pWaterSpellbook.bIsSpellbookAvailable = true;  break;
+      case PLAYER_SKILL_EARTH:  spellbook.pEarthSpellbook.bIsSpellbookAvailable = true;  break;
+      case PLAYER_SKILL_SPIRIT: spellbook.pSpiritSpellbook.bIsSpellbookAvailable = true; break;
+      case PLAYER_SKILL_MIND:   spellbook.pMindSpellbook.bIsSpellbookAvailable = 1; break;
+      case PLAYER_SKILL_BODY:   spellbook.pBodySpellbook.bIsSpellbookAvailable = 1; break;
+      case PLAYER_SKILL_LIGHT:  spellbook.pLightSpellbook.bIsSpellbookAvailable = 1; break;
+      case PLAYER_SKILL_DARK:   spellbook.pDarkSpellbook.bIsSpellbookAvailable = 1; break;
+    }
+  }
 
   sHealth = GetMaxHealth();
   sMana = GetMaxMana();
@@ -6535,7 +6562,7 @@
       v8 = this->pActiveSkills;
       do
       {
-        if ( *v8 && *(&byte_4ED820[37 * ((unsigned int)this->uClass >> 2)] + result) == 2 )
+        if ( *v8 && pSkillAvailabilityPerClass[uClass / 4][result] == 2 )
         {
           if ( v7 == order )
             return result;
@@ -6555,7 +6582,7 @@
         v6 = this->pActiveSkills;
         do
         {
-          if ( *v6 && *(&byte_4ED820[37 * ((unsigned int)this->uClass >> 2)] + result) == 1 )
+          if ( *v6 && pSkillAvailabilityPerClass[uClass / 4][result] == 1 )
           {
             if ( v5 == order - 2 )
               return result;
@@ -6572,7 +6599,7 @@
         {
           result = (PLAYER_SKILL_TYPE)0;
           v3 = 0;
-          v4 = &byte_4ED820[37 * ((unsigned int)this->uClass >> 2)];
+          v4 = (char *)pSkillAvailabilityPerClass[uClass / 4];
           do
           {
             if ( *v4 == 1 )
@@ -7563,10 +7590,10 @@
         return;
       }
 LABEL_89:
-      v68 = aCharacterConditionNames[v3->GetMajorConditionrIdx()];
+      v68 = aCharacterConditionNames[v3->GetMajorConditionIdx()];
       v58 = pGlobalTXT_LocalizationStrings[382];
 LABEL_90:
-      sprintfex(pTmpBuf, v58, v68);
+      sprintf(pTmpBuf, v58, v68);
       v23 = pTmpBuf;
 LABEL_91:
       ShowStatusBarString(v23, 2u);
@@ -7599,7 +7626,7 @@
     }
     if ( !((Player *)&stru_AA1058[3].pSounds[6972 * a2 + 40552])->CanAct() )
     {
-      v66 = aCharacterConditionNames[v3->GetMajorConditionrIdx()];
+      v66 = aCharacterConditionNames[v3->GetMajorConditionIdx()];
       v57 = pGlobalTXT_LocalizationStrings[382];
       goto LABEL_72;
     }
@@ -7946,7 +7973,7 @@
         goto _cmp_against_arg;
     }
     while ( !v3->HasItemEquipped(v26)
-         || *(int *)&v3->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v27 + 5] != a1 )
+         || *(int *)&v3->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v27 + 5] != a1 )
     {
       v26 = (ITEM_EQUIP_TYPE)((int)v26 + 1);
       v27 += 4;
@@ -8252,7 +8279,7 @@
         v4 = (unsigned __int8)byte_5E4C15[var];
       goto _cmp_against_arg;
     }
-    v4 = GetMajorConditionrIdx();
+    v4 = GetMajorConditionIdx();
     if ( v4 != 18 )
     {
 _cmp_against_arg:
@@ -8534,7 +8561,7 @@
           item.Reset();
           item.Reset();
           item.uItemID = a3;
-          item.uAttributtes = 1;
+          item.uAttributes = 1;
           pParty->SetHoldingItem(&item);
           if ( a3 >= ITEM_ARTIFACT_PUCK && a3 <= ITEM_RELIC_MEKORIGS_HAMMER )
             pParty->field_3C.pIsArtifactFound[a3] = 1;
@@ -8964,7 +8991,7 @@
             case VAR_PlayerItemInHands:
               item.Reset();
               item.Reset();
-              item.uAttributtes = 1;
+              item.uAttributes = 1;
               item.uItemID = val;
               if ( val >= ITEM_ARTIFACT_PUCK && val <= ITEM_RELIC_MEKORIGS_HAMMER )
                 pParty->field_3C.pIsArtifactFound[val] = 1;
@@ -9755,7 +9782,7 @@
       }
       do
       {
-        if ( *(void **)&this->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v15 + 5] == a3 )
+        if ( *(void **)&this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v15 + 5] == a3 )
         {
           RemoveItemAtInventoryIndex(v3);
           return;
--- a/Player.h	Sat Oct 13 20:18:28 2012 +0200
+++ b/Player.h	Sun Oct 14 00:27:38 2012 +0200
@@ -115,13 +115,40 @@
 
 
 #pragma pack(push, 1)
-struct PlayerSpellbook
+struct PlayerSpellbookChapter
 {
   unsigned __int8 bIsSpellbookAvailable;
   char bIsSpellAvailable[10];
 };
 #pragma pack(pop)
 
+#pragma pack(push, 1)
+struct PlayerSpells
+{
+  union
+  {
+    struct
+    {
+      PlayerSpellbookChapter pFireSpellbook;
+      PlayerSpellbookChapter pAirSpellbook;
+      PlayerSpellbookChapter pWaterSpellbook;
+      PlayerSpellbookChapter pEarthSpellbook;
+      PlayerSpellbookChapter pSpiritSpellbook;
+      PlayerSpellbookChapter pMindSpellbook;
+      PlayerSpellbookChapter pBodySpellbook;
+      PlayerSpellbookChapter pLightSpellbook;
+      PlayerSpellbookChapter pDarkSpellbook;
+      char _pad_0;
+    };
+    struct
+    {
+      PlayerSpellbookChapter pChapters[9];
+      char _pad_1;
+    };
+  };
+};
+#pragma pack(pop)
+
 
 
 #pragma pack(push, 1)
@@ -218,7 +245,7 @@
   int GetActualResistance(enum CHARACTER_ATTRIBUTE_TYPE a2);
   void SetRecoveryTime(signed int sRecoveryTime);
   void RandomizeName();
-  unsigned int GetMajorConditionrIdx();
+  unsigned int GetMajorConditionIdx();
   int _48EA1B_get_static_effect(int a2);
   int _48EA46_calc_special_bonus_by_items(int a2);
   int GetItemsBonus(enum CHARACTER_ATTRIBUTE_TYPE attr, int a3);
@@ -319,16 +346,8 @@
   int field_104;
   unsigned __int16 pActiveSkills[37];
   char field_152[64];
-  PlayerSpellbook pFileSpellbook;
-  PlayerSpellbook pAirSpellbook;
-  PlayerSpellbook pWaterSpellbook;
-  PlayerSpellbook pEarthSpellbook;
-  PlayerSpellbook pSpiritSpellbook;
-  PlayerSpellbook pMindSpellbook;
-  PlayerSpellbook pBodySpellbook;
-  PlayerSpellbook pLightSpellbook;
-  PlayerSpellbook pDarkSpellbook;
-  char field_1F5[31];
+  PlayerSpells spellbook;
+  char field_1F5[30];
   ItemGen pInventoryItems[126];
   ItemGen pEquippedItems[12];
   int pInventoryIndices[126];
--- a/mm7_1.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_1.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -865,7 +865,7 @@
         v15 = v13 + 32;
         if ( v9 < 14 )
           v14 = 14;
-        v16 = v5->uAttributtes;
+        v16 = v5->uAttributes;
         v17 = a2a + ((v15 - v10) >> 1) + pSRZBufferLineOffsets[a3 + ((((v14 - 14) & 0xFFFFFFE0) - v9 + 32) >> 1)];
         if ( !(v16 & 0xF0) )
         {
@@ -904,7 +904,7 @@
             if ( dword_50C9A8 <= 0 )
             {
               dword_50C9A8 = 0;
-              LOBYTE(v25->uAttributtes) &= 0xFu;
+              LOBYTE(v25->uAttributes) &= 0xFu;
               ptr_50C9A4 = 0;
             }
             v19 = (double)GetTickCount() * 0.1;
@@ -1180,7 +1180,7 @@
       84,
       0);
     v32 = v45 + v31;
-    v48 = pPlayer->GetMajorConditionrIdx();
+    v48 = pPlayer->GetMajorConditionIdx();
     if ( !v43 )
       pGUIWindow_CurrentMenu->DrawTextInRect(
         pFontArrus,
@@ -2536,8 +2536,8 @@
       v81 >>= 1;
     v8 = _this;
     if ( !v3[46] )
-      _this->uAttributtes |= 1u;
-    v9 = v8->uAttributtes;
+      _this->uAttributes |= 1u;
+    v9 = v8->uAttributes;
     v77 = 0;
     a2.y = v9 & 2;
     if ( pItemsTable->pItems[v8->uItemID].uEquipType == 18 )
@@ -2549,8 +2549,8 @@
         v10 = pPlayers[uActiveCharacter]->CanIdentify(_this) == 1;
         v11 = _this;
         if ( v10 )
-          _this->uAttributtes |= 1u;
-        v10 = (v11->uAttributtes & 1) == 0;
+          _this->uAttributes |= 1u;
+        v10 = (v11->uAttributes & 1) == 0;
         v83 = (char *)9;
         if ( v10 )
         {
@@ -2574,8 +2574,8 @@
         v10 = pPlayers[uActiveCharacter]->CanRepair(_this) == 1;
         v12 = _this;
         if ( v10 )
-          _this->uAttributtes = _this->uAttributtes & 0xFFFFFFFD | 1;
-        v10 = (v12->uAttributtes & 2) == 0;
+          _this->uAttributes = _this->uAttributes & 0xFFFFFFFD | 1;
+        v10 = (v12->uAttributes & 2) == 0;
         v83 = (char *)11;
         if ( v10 )
           v83 = (char *)10;
@@ -2588,9 +2588,9 @@
         }
       }
     }
-    v13 = _this->uAttributtes;
-    v14 = _this->uAttributtes & 1;
-    a2.y = _this->uAttributtes & 1;
+    v13 = _this->uAttributes;
+    v14 = _this->uAttributes & 1;
+    a2.y = _this->uAttributes & 1;
     if ( v13 & 2 )
     {
       v79._415551(0);
@@ -2725,7 +2725,7 @@
       v79.uFrameHeight = v73->uTextureHeight + v81 + 54;
       if ( (signed int)Str > (signed int)v79.uFrameHeight )
         v79.uFrameHeight = (unsigned int)Str;
-      if ( _this->uAttributtes & 8 && (_this->uAdditionalValue || _this->_bonus_type) )
+      if ( _this->uAttributes & 8 && (_this->uAdditionalValue || _this->_bonus_type) )
         v79.uFrameHeight += LOBYTE(v82->uFontHeight);
       v83 = 0;
       if ( LOBYTE(pFontArrus->uFontHeight) )
@@ -2795,7 +2795,7 @@
       }
       else
       {
-        if ( _this->uAttributtes & 8 && (_this->uAdditionalValue || _this->_bonus_type) )
+        if ( _this->uAttributes & 8 && (_this->uAdditionalValue || _this->_bonus_type) )
         {
           sub_493F79((stru351 *)&v67, _this->uExpireTime - pParty->uTimePlayed);
           strcpy(pTmpBuf, "Duration:");
@@ -2819,7 +2819,7 @@
         v37 = _this->GetValue();
         sprintfex(pTmpBuf, "%s: %lu", pGlobalTXT_LocalizationStrings[465], v37);
         v79.DrawText(v82, 100, v79.uFrameHeight - LOBYTE(v82->uFontHeight), 0, pTmpBuf, 0, 0, 0);
-        v38 = _this->uAttributtes;
+        v38 = _this->uAttributes;
         if ( BYTE1(v38) & 1 )
         {
           v61 = 0;
@@ -4379,7 +4379,7 @@
   v11 = 0;
   if ( uChestArea > 0 )
   {
-    v12 = &pChests[v3].mm7__vector_pItems[0].uAttributtes;
+    v12 = &pChests[v3].mm7__vector_pItems[0].uAttributes;
     do
     {
       v9 = *(v12 - 5);
@@ -5171,7 +5171,7 @@
       v14 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]];
       if ( v14 == zero || v14 == -65536 || (unsigned int)v14 >= 0x1388 )
         goto _return;
-      v15 = (ItemGen *)&pPlayers[uActiveCharacter]->pDarkSpellbook.bIsSpellAvailable[36 * v14 + 5];
+      v15 = (ItemGen *)&pPlayers[uActiveCharacter]->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v14 + 5];
       goto LABEL_49;
     }
 _click_on_game_ui:
@@ -5528,7 +5528,7 @@
   if ( uActiveCharacter
     && (v2 = pPlayers[uActiveCharacter]->AddItem(0xFFFFFFFFu, pParty->pPickedItem.uItemID)) != 0 )
   {
-    memcpy(&pPlayers[uActiveCharacter]->pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5], &pParty->pPickedItem, 0x24u);
+    memcpy(&pPlayers[uActiveCharacter]->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5], &pParty->pPickedItem, 0x24u);
   }
   else
   {
@@ -5544,7 +5544,7 @@
       if ( (signed int)v3 >= (signed int)pParty->pHirelings )
         goto LABEL_10;
     }
-    memcpy(&pParty->pPlayers[v12].pDarkSpellbook.bIsSpellAvailable[36 * v4 + 5], &pParty->pPickedItem, 0x24u);
+    memcpy(&pParty->pPlayers[v12].spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v4 + 5], &pParty->pPickedItem, 0x24u);
     pMouse->RemoveHoldingItem();
 LABEL_10:
     if ( v12 != 4 )
@@ -5612,7 +5612,7 @@
     v3 = pPlayers[v1];
     if ( v2 )
     {
-      memcpy(&v3->pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5], &pParty->pPickedItem, 0x24u);
+      memcpy(&v3->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5], &pParty->pPickedItem, 0x24u);
       viewparams->bRedrawGameUI = 1;
       pMouse->RemoveHoldingItem();
       return;
@@ -5737,7 +5737,7 @@
       *((short *)ptr_507BD4->ptr_1C + 2) = uActiveCharacter - 1;
       *((int *)ptr_507BD4->ptr_1C + 3) = v6 - 1;
       *((short *)ptr_507BD4->ptr_1C + 3) = a4;
-      ptr_50C9A4 = (ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v6 + 5];
+      ptr_50C9A4 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6 + 5];
       unk_50C9A0 = 0;
       if ( pMessageQueue_50CBD0->uNumMessages )
         pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
@@ -5756,7 +5756,7 @@
   {
     if ( !v8 )
       return;
-    memcpy(&pParty->pPickedItem, &v0->pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5], sizeof(pParty->pPickedItem));
+    memcpy(&pParty->pPickedItem, &v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5], sizeof(pParty->pPickedItem));
     v0->RemoveItemAtInventoryIndex(a4);
     v9 = pParty->pPickedItem.uItemID;
     goto LABEL_24;
@@ -5764,7 +5764,7 @@
   v13 = v8;
   if ( v8 )
   {
-    a2.y = (LONG)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    a2.y = (LONG)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
     memcpy(&this_, (const void *)a2.y, sizeof(this_));
     v0->RemoveItemAtInventoryIndex(a4);
     pX = v0->AddItem2(a4, &pParty->pPickedItem);
@@ -5788,7 +5788,7 @@
   pX = v10;
   if ( v10 || (v10 = v0->AddItem(0xFFFFFFFFu, pParty->pPickedItem.uItemID), (pX = v10) != 0) )
   {
-    memcpy(&v0->pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5], &pParty->pPickedItem, 0x24u);
+    memcpy(&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5], &pParty->pPickedItem, 0x24u);
     pMouse->RemoveHoldingItem();
   }
 }
--- a/mm7_2.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_2.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -1307,11 +1307,11 @@
                 v85 = 0;
                 v83 = 5;
                 v81 = ptr_507BC0->ptr_1C;
-                v79 = (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[4 * (int)result + 5];
+                v79 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * (int)result + 5];
                 v28 = (int)ptr_507BC0->ptr_1C;
                 v110 = uActiveCharacter - 1;
                 v29 = _this->_490EEE(
-                        (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[4 * (int)result + 5],
+                        (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * (int)result + 5],
                         1,
                         v28,
                         5);
@@ -1405,7 +1405,7 @@
                 v85 = 0;
                 v83 = 3;
                 v81 = ptr_507BC0->ptr_1C;
-                v79 = (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+                v79 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
                 v12 = (int)ptr_507BC0->ptr_1C;
                 v110 = uActiveCharacter - 1;
                 v13 = _this->_490EEE(v79, 1, v12, 3);
@@ -1442,8 +1442,8 @@
                 {
                   v85 = 0;
                   v83 = 4;
-                  v4 = (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
-                  if ( !(v4->uAttributtes & 1) )
+                  v4 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+                  if ( !(v4->uAttributes & 1) )
                   {
                     v81 = ptr_507BC0->ptr_1C;
                     v79 = v4;
@@ -1817,7 +1817,7 @@
         v93 = 0;
         v91 = 3;
         v89 = ptr_507BC0->ptr_1C;
-        v87 = (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+        v87 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
         v44 = (int)ptr_507BC0->ptr_1C;
         v113 = uActiveCharacter - 1;
         v45 = _this->_490EEE(v87, 4, v44, 3);
@@ -1841,8 +1841,8 @@
           return result;
         v93 = 0;
         v91 = 4;
-        v37 = (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
-        if ( !(v37->uAttributtes & 1) )
+        v37 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)result + 5];
+        if ( !(v37->uAttributes & 1) )
         {
           v89 = ptr_507BC0->ptr_1C;
           v87 = v37;
@@ -2788,10 +2788,10 @@
     v124 = 0;
     v122 = 5;
     v120 = ptr_507BC0->ptr_1C;
-    v116 = (ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[4 * v33 + 5];
+    v116 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * v33 + 5];
     v34 = (int)ptr_507BC0->ptr_1C;
     uPlayerID = uActiveCharacter - 1;
-    v35 = v0->_490EEE((ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[4 * v33 + 5], 2, v34, 5);
+    v35 = v0->_490EEE((ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * v33 + 5], 2, v34, 5);
     v14 = uPlayerID;
     v15 = (char *)pMerchantsRepairPhrases[v35];
     goto LABEL_36;
@@ -2866,7 +2866,7 @@
     v124 = 0;
     v122 = 3;
     v120 = ptr_507BC0->ptr_1C;
-    v116 = (ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5];
+    v116 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v10 + 5];
     v12 = (int)ptr_507BC0->ptr_1C;
     uPlayerID = uActiveCharacter - 1;
     v13 = v0->_490EEE(v116, 2, v12, 3);
@@ -2890,8 +2890,8 @@
           v2 = v0->GetItemIDAtInventoryIndex((int *)&v149);
           if ( v2 )
           {
-            v3 = (ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
-            if ( v3->uAttributtes & 1 )
+            v3 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
+            if ( v3->uAttributes & 1 )
             {
               v118 = ptr_507BC0->ptr_1C;
               v4 = uActiveCharacter - 1;
@@ -4170,7 +4170,16 @@
               v37 = v36 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
               if ( v37 < v36 / 3 )
                 v37 = v36 / 3;
-              if ( *(&byte_4ED94C[37 * v35->uClass] + v55) )
+              
+              __debugbreak();
+              //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+              // or
+              //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+              // or
+              //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+              if (false)
+              //if ( *(&byte_4ED94C[37 * v35->uClass] + v55) )
               {
                 v38 = (int)(&v35->uIntelligence + v55);
                 if ( !*(short *)v38 )
@@ -4608,8 +4617,8 @@
     if ( v25 )
     {
       v26 = 1;
-      v20->uAttributtes |= 1u;
-      memcpy(&v0->pDarkSpellbook.bIsSpellAvailable[36 * v25 + 5], v20, 0x24u);
+      v20->uAttributes |= 1u;
+      memcpy(&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v25 + 5], v20, 0x24u);
       goto LABEL_42;
     }
     v0->PlaySound(15, 0);
@@ -4676,7 +4685,7 @@
     v39 = v0->AddItem(0xFFFFFFFFu, v32->uItemID);
     if ( v39 )
     {
-      v32->uAttributtes |= 1u;
+      v32->uAttributes |= 1u;
       v7 = v73 == 1;
       v40 = (int)((char *)v0 + 36 * v39);
       memcpy((void *)(v40 + 496), v32, 0x24u);
@@ -4720,7 +4729,7 @@
       || (v15 = v0->GetItemIDAtInventoryIndex((int *)&v79), (v77 = (Player *)v15) == 0) )
       return;
     v16 = ptr_507BC0;
-    if ( sub_4BDAAF((ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5], (int)ptr_507BC0->ptr_1C) )
+    if ( sub_4BDAAF((ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5], (int)ptr_507BC0->ptr_1C) )
     {
       dword_F8B1E4 = 1;
       v0->_4BE2DD(v79, (int)((char *)v77 - 1), (int)v16->ptr_1C);
@@ -4755,7 +4764,7 @@
         {
           //v80 = v0->_4B8179(p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C]);
           v80 = v0->_4B8179(p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier);
-          v12 = (int)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v11 + 5];
+          v12 = (int)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v11 + 5];
           if ( !(*(char *)(v12 + 20) & 1) )
           {
             _this = (ItemGen *)ptr_507BC0->ptr_1C;
@@ -4797,11 +4806,11 @@
           v2 = v0->GetItemIDAtInventoryIndex((int *)&v79);
           if ( v2 )
           {
-            v3 = (int)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
+            v3 = (int)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
             //v4 = p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C];
             v4 = p2DEvents[(unsigned int)ptr_507BC0->ptr_1C - 1].fPriceMultiplier;
 
-            auto _v = (ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
+            auto _v = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v2 + 5];
             v5 = _v->GetValue();
 
             v6 = v0->_4B81C3(v5, v4);
@@ -8021,7 +8030,7 @@
                   }
                   v18 = v15;
                 }
-                a1a.stru_24.uAttributtes |= 1u;
+                a1a.stru_24.uAttributes |= 1u;
                 a1a.uObjectDescID = v18;
                 a1a.stru_24.uAdditionalValue = v34;
                 goto LABEL_35;
@@ -8180,7 +8189,7 @@
                     }
                   }
 LABEL_23:
-                  v3->uAttributtes |= 1u;
+                  v3->uAttributes |= 1u;
                   v3->uAdditionalValue = v10;
 LABEL_25:
                   v11 = v4 - 1;
@@ -15217,6 +15226,8 @@
 
   if (MM7_Initialize())
   {
+    Log::Warning(L"MM init: ok");
+
     pEventTimer->Pause();
     if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
     {
@@ -15235,6 +15246,8 @@
     SecondaryInitialization();
     pRenderer->Clip_v2(0, 0, 639u, 479u);
     FinalInitialization();
+
+    Log::Warning(L"MM: entering main loop");
     while ( 1 )
     {
       MainMenu_Loop();
@@ -15330,7 +15343,7 @@
         {
           v12 = 1;
 LABEL_57:
-          SetCurrentMenuID(v12);
+          SetCurrentMenuID((MENU_STATE)v12);
           goto LABEL_21;
         }
         if ( uGameState == 7 )
@@ -15359,6 +15372,8 @@
       }
     }
   }
+  else
+    Log::Warning(L"MM init: failed");
 
   pGame->Deinitialize();
 }
@@ -15625,32 +15640,39 @@
 }
 
 //----- (00466C40) --------------------------------------------------------
-// #define MENU_MAIN        0
-// #define MENU_NEWGAME     1
-// #define MENU_CREDITS     2
-// #define MENU_LOAD        3
-// #define MENU_CREATEPARTY 6
-// #define MENU_MAINMENULOAD    9
-void __thiscall SetCurrentMenuID(unsigned int uMenu)
-{
-  unsigned int v1; // esi@1
-
-  v1 = uMenu;
-  if ( uCurrentMenuID == -1 )
-  {
-    if ( uMenu != -1 && LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
-      pAsyncKeyboard->Suspend();
-  }
-  else
-  {
-    if ( uMenu == -1 && LOBYTE(pGame->pKeyboardInstance->bUsingAsynKeyboard) && pAsyncKeyboard )
+const wchar_t *MENU_STATE_to_string(MENU_STATE m)
+{
+  switch (m)
+  {
+    case -1:               return L"-1";
+    case MENU_MAIN:        return L"MENU_MAIN";
+    case MENU_NEWGAME:     return L"MENU_NEWGAME";
+    case MENU_CREDITS:     return L"MENU_CREDITS";
+    case MENU_SAVELOAD:    return L"MENU_SAVELOAD";
+    case MENU_FINISHED:    return L"MENU_FINISHED";
+    case MENU_5:           return L"MENU_5";
+    case MENU_CREATEPARTY: return L"MENU_CREATEPARTY";
+    case MENU_7:           return L"MENU_7";
+    case MENU_Credits:     return L"MENU_Credits";
+    case MENU_LOAD:        return L"MENU_LOAD";
+    case MENU_10:          return L"MENU_10";
+    default:               return L"unk";
+  };
+};
+void SetCurrentMenuID(MENU_STATE uMenu)
+{
+  if ((int)uCurrentMenuID != -1)
+  {
+    if (pGame->pKeyboardInstance->bUsingAsynKeyboard && pAsyncKeyboard)
       pAsyncKeyboard->Resume();
   }
-  uCurrentMenuID = v1;
+  uCurrentMenuID = uMenu;
+
+  Log::Warning(L"CurrentMenu = %s", MENU_STATE_to_string(uMenu));
 }
 
 //----- (00466CA0) --------------------------------------------------------
-unsigned int GetCurrentMenuID()
+MENU_STATE GetCurrentMenuID()
 {
   return uCurrentMenuID;
 }
@@ -16361,7 +16383,7 @@
   v2 = v0->pEquipment.uOffHand;
   v54 = v0->pEquipment.uOffHand;
   v53 = v1;
-  if ( v1 && pItemsTable->pItems[*(int *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v1 + 5]].uEquipType == 1 )
+  if ( v1 && pItemsTable->pItems[*(int *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v1 + 5]].uEquipType == 1 )
     v51 = v1;
   v3 = pParty->pPickedItem.uItemID;
   if ( pParty->pPickedItem.uItemID )
@@ -16388,7 +16410,7 @@
     {
       if ( (v4 == 8 || v4 == 1 || v4 == 2)
         && v1
-        && pItemsTable->pItems[*(int *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v1 + 5]].uSkillType == 4 )
+        && pItemsTable->pItems[*(int *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v1 + 5]].uSkillType == 4 )
         goto LABEL_7;
     }
 LABEL_16:
@@ -16733,7 +16755,7 @@
     v35 = v0->pEquipment.uBow;
     if ( v35 )
     {
-      auto _a = (ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v35 + 5];
+      auto _a = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v35 + 5];
       pParty->SetHoldingItem(_a);
       _a->Reset();
       v0->pEquipment.uBow = 0;
--- a/mm7_3.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_3.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -14477,6 +14477,8 @@
         pRenderer->DrawTextureTransparent(396u, 8u, v9);
     }
   }
+
+  uint _it = 0;
   v10 = &pPlayers[1];
   v4 = pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing;
   do
@@ -14486,26 +14488,27 @@
       pRenderer->DrawTextureIndexed(
         *v4 + 72,
         0x1ABu,
-        (Texture *)(dword_507964 != -1 ? (int)&pIcons_LOD->pTextures[dword_507964] : 0));
+        (Texture *)(dword_507964 != -1 ? &pIcons_LOD->pTextures[dword_507964] : 0));
     if ( (signed __int64)v5->pPlayerBuffs[1].uExpireTime > 0 )
       pRenderer->DrawTextureIndexed(
         *v4 + 72,
         0x189u,
-        (Texture *)(dword_50796C != -1 ? (int)&pIcons_LOD->pTextures[dword_50796C] : 0));
+        (Texture *)(dword_50796C != -1 ? &pIcons_LOD->pTextures[dword_50796C] : 0));
     if ( (signed __int64)v5->pPlayerBuffs[11].uExpireTime > 0 )
       pRenderer->DrawTextureIndexed(
         *v4 + 72,
         0x19Au,
-        (Texture *)(dword_507968 != -1 ? (int)&pIcons_LOD->pTextures[dword_507968] : 0));
+        (Texture *)(dword_507968 != -1 ? &pIcons_LOD->pTextures[dword_507968] : 0));
     if ( (signed __int64)v5->pPlayerBuffs[10].uExpireTime > 0 )
       pRenderer->DrawTextureIndexed(
         *v4 + 72,
         0x1BCu,
-        (Texture *)(dword_507960 != -1 ? (int)&pIcons_LOD->pTextures[dword_507960] : 0));
+        (Texture *)(dword_507960 != -1 ? &pIcons_LOD->pTextures[dword_507960] : 0));
     ++v10;
     ++v4;
   }
-  while ( (signed int)v4 < (signed int)pBaseHealthByClass );
+  //while ( (signed int)v4 < (signed int)pBaseHealthByClass );
+  while (++_it != 4);
 }
 
 
@@ -18607,7 +18610,7 @@
               v67 = (int)v66->pInventoryIndices;
               do
               {
-                if ( *(void **)&v66->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v67 + 5] == v63 )
+                if ( *(void **)&v66->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v67 + 5] == v63 )
                 {
                   v66->RemoveItemAtInventoryIndex(v65);
                   goto LABEL_291;
@@ -18620,7 +18623,7 @@
               v69 = (int)&v66->pEquipment;
               do
               {
-                if ( *(int *)v69 && *(void **)&v66->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v69 + 5] == v63 )
+                if ( *(int *)v69 && *(void **)&v66->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v69 + 5] == v63 )
                 {
                   *(&v66->pEquipment.uOffHand + v68) = 0;
                   goto LABEL_291;
@@ -18639,7 +18642,7 @@
                   v72 = (int)v70->pInventoryIndices;
                   do
                   {
-                    if ( *(void **)&v70->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v72 + 5] == v63 )
+                    if ( *(void **)&v70->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v72 + 5] == v63 )
                     {
                       v70->RemoveItemAtInventoryIndex(v71);
                       goto LABEL_169;
@@ -18651,7 +18654,7 @@
                   v73 = 0;
                   v74 = (int)&v70->pEquipment;
                   while ( !*(int *)v74
-                       || *(void **)&v70->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v74 + 5] != v63 )
+                       || *(void **)&v70->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v74 + 5] != v63 )
                   {
                     ++v73;
                     v74 += 4;
--- a/mm7_4.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_4.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -3630,7 +3630,7 @@
     {
       if ( v21->HasItemEquipped(v22) )
       {
-        v24 = *(int *)&v21->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v23 + 5];
+        v24 = *(int *)&v21->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v23 + 5];
         if ( v24 > 134 )
         {
           if ( v24 == 529 )
@@ -5290,7 +5290,7 @@
           v35 = *v26;
           v36 = v13->GetValue();
           v29 = pPlayer->_4B8102(v36, v35);
-          if ( v13->uAttributtes & 2 )
+          if ( v13->uAttributes & 2 )
           {
 LABEL_77:
             v29 = 1;
@@ -5313,7 +5313,7 @@
               v30 = *v26;
               v31 = v13->GetValue();
               v29 = pPlayer->_4B8102(v31, v30) / 2;
-              if ( v13->uAttributtes & 2 )
+              if ( v13->uAttributes & 2 )
                 v29 = 1;
 LABEL_91:
               if ( v29 >= 1 )
@@ -5624,7 +5624,7 @@
             v15 = Str;
             pGUIWindow_CurrentMenu->field_40 = 0;
             pGUIWindow_CurrentMenu->DrawTextInRect(pFontCreate, v134, 124u, 0, v15, 130, 0);
-            SetCurrentMenuID(7u);
+            SetCurrentMenuID(MENU_7);
           }
         }
         else
@@ -6477,7 +6477,7 @@
   v2 = 6;
   pGUIWindow_CurrentMenu->field_40 = 0;
 LABEL_27:
-  SetCurrentMenuID(v2);
+  SetCurrentMenuID((MENU_STATE)v2);
   while ( GetCurrentMenuID() == MENU_CREATEPARTY )
   {
     if ( pAsyncMouse != (void *)v1 )
@@ -6907,7 +6907,7 @@
       pRenderer->EndScene();
       ++a5;
       if ( a5 >= (signed __int16)v21.uHeight )
-        SetCurrentMenuID(0);
+        SetCurrentMenuID(MENU_MAIN);
       timeGetTime();
       pRenderer->Present();
       GUI_MainMenuMessageProc();
@@ -9907,7 +9907,7 @@
           || pMouse->GetCursorPos((POINT *)&v12)->x >= 462
           || (v9 = v0->GetItemIDAtInventoryIndex(&v18)) == 0 )
           return;
-        v7 = (ItemGen *)&v0->pDarkSpellbook.bIsSpellAvailable[36 * v9 + 5];
+        v7 = (ItemGen *)&v0->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v9 + 5];
 LABEL_15:
         GameUI_DrawItemInfo(v7);
         return;
@@ -12998,10 +12998,10 @@
       v96 = 0;
       v94 = 5;
       v93 = ptr_507BC0->ptr_1C;
-      v90 = (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[4 * result + 5];
+      v90 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5];
       v28 = (int)ptr_507BC0->ptr_1C;
       uPlayerID = uActiveCharacter - 1;
-      v29 = _this->_490EEE((ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[4 * result + 5], 3, v28, 5);
+      v29 = _this->_490EEE((ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5], 3, v28, 5);
       v9 = uPlayerID;
       v10 = (char *)pMerchantsRepairPhrases[v29];
       goto LABEL_35;
@@ -13088,7 +13088,7 @@
                 {
                   v96 = 0;
                   v94 = 4;
-                  v4 = &_this->pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
+                  v4 = &_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
                   if ( v4[20] & 1 )
                   {
                     v5 = sub_495461("%24", uActiveCharacter - 1, (ItemGen *)v4, (char *)ptr_507BC0->ptr_1C, 4, 0);
@@ -13128,7 +13128,7 @@
       v96 = 0;
       v94 = 3;
       v93 = ptr_507BC0->ptr_1C;
-      v90 = (ItemGen *)&_this->pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
+      v90 = (ItemGen *)&_this->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * result + 5];
       v12 = (int)ptr_507BC0->ptr_1C;
       uPlayerID = uActiveCharacter - 1;
       v13 = _this->_490EEE(v90, 3, v12, 3);
@@ -13640,7 +13640,7 @@
   v5 = pItemsTable->pItems[v4].uEquipType;
   if ( (v2 != 4 || (signed int)v3 < 740 || (signed int)v3 > 771)
     && ((signed int)v3 >= 600 || (signed int)v3 >= 529 && (signed int)v3 <= 599)
-    || BYTE1(a1->uAttributtes) & 1 )
+    || BYTE1(a1->uAttributes) & 1 )
     return 0;
   v6 = v2 - 1;
   if ( !v6 )
@@ -13933,7 +13933,14 @@
     }
     else
     {
-      if ( *(&byte_4ED94C[37 * v58->uClass] + v23) && !*(&v58->uIntelligence + v23) )
+      __debugbreak();
+      //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+      //if ( *(&byte_4ED94C[37 * v58->uClass] + v23) && !*(&v58->uIntelligence + v23) )
       {
         v24 = pFontArrus->CalcTextHeight(pClassNames[v23 + 20], &v52, 0, 0);
         v62 += v24;
@@ -13981,7 +13988,15 @@
       v29 = v27->uControlParam;
       if ( v29 == 18 )
         break;
-      if ( *(&byte_4ED94C[37 * v58->uClass] + v29) && !*(&v58->uIntelligence + v29) )
+
+      __debugbreak();
+      //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+      //if ( *(&byte_4ED94C[37 * v58->uClass] + v29) && !*(&v58->uIntelligence + v29) )
       {
         v30 = pClassNames[v29 + 20];
 LABEL_55:
@@ -14559,7 +14574,16 @@
     if ( sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
     {
       v5 = 0;
-      if ( !*(&byte_4ED94C[37 * v1->uClass / 3] + dword_F8B19C)
+
+      __debugbreak();
+      //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+      // or
+      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+
+      if (false
+      //if ( !*(&byte_4ED94C[37 * v1->uClass / 3] + dword_F8B19C)
         || (v6 = (int)(&v1->uIntelligence + dword_F8B19C), *(short *)v6) )
       {
         pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
--- a/mm7_5.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_5.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -1313,7 +1313,7 @@
                       }
                       if ( ptr_50C9A4 && ptr_50C9A4->uItemID )
                       {
-                        LOBYTE(ptr_50C9A4->uAttributtes) &= 0xFu;
+                        LOBYTE(ptr_50C9A4->uAttributes) &= 0xFu;
                         dword_50C9A8 = 0;
                         ptr_50C9A4 = 0;
                       }
@@ -3173,7 +3173,7 @@
           v106 = pPlayers[uMessageParam];
           sprintfex(pTmpBuf, pGlobalTXT_LocalizationStrings[429], v106->pName, pClassNames[v106->uClass]);// "%s the %s"
           strcat(pTmpBuf, ": ");
-          v107 = v106->GetMajorConditionrIdx();
+          v107 = v106->GetMajorConditionIdx();
           strcat(pTmpBuf, aCharacterConditionNames[v107]);
           sub_41C0B8_set_status_string(pTmpBuf);
           v108 = 8 * uMessageParam - 8;
@@ -3460,9 +3460,8 @@
         {
           if (!pSavegameUsedSlots[uLoadGameUI_SelectedSlot])
             continue;
-LABEL_99:
-          v40 = 9;
-          goto LABEL_89;
+
+          SetCurrentMenuID(MENU_LOAD);
         }
         continue;
       }
@@ -3600,7 +3599,8 @@
               (enum WindowType)90,
               (int)pMainMenu_BtnNew,
               0);
-            goto LABEL_99;
+          SetCurrentMenuID(MENU_LOAD);
+          continue;
           }
           if ( v45 != 174 )
             continue;
@@ -3617,7 +3617,7 @@
 LABEL_89:
           v2 = v40;
 LABEL_90:
-          SetCurrentMenuID(v2);
+          SetCurrentMenuID((MENU_STATE)v2);
           continue;
         }
         if ( v45 == UIMSG_A3 )
@@ -3667,12 +3667,12 @@
 LABEL_83:
             if ( v17 == 16 )
               pVideoPlayer->FastForwardToFrame(pVideoPlayer->field_40);
-            if ( GetCurrentMenuID() == 7 )
+            if (GetCurrentMenuID() == MENU_7)
             {
               v40 = 6;
               goto LABEL_89;
             }
-            if ( GetCurrentMenuID() == 8 )
+            if (GetCurrentMenuID() == MENU_Credits)
             {
               v40 = 11;
               goto LABEL_89;
@@ -3699,7 +3699,7 @@
             crt_deconstruct_ptr_6A0118();
             stru_506F20.Release();
             stru_506F20.Load("title.pcx", 0);
-            SetCurrentMenuID(0);
+            SetCurrentMenuID(MENU_MAIN);
             v15 = 1;
 LABEL_81:
             pGUIWindow_CurrentMenu->Release();
@@ -4965,7 +4965,7 @@
     v59 = 1;
     if ( pPlayer->HasItemEquipped(EQUIP_TWO_HANDED) )
     {
-      v55 = pItemsTable->pItems[*(int *)&pPlayer->pDarkSpellbook.bIsSpellAvailable[36 * (int)v51 + 5]].uSkillType;
+      v55 = pItemsTable->pItems[*(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * (int)v51 + 5]].uSkillType;
       v28 = SkillToMastery(pPlayer->pActiveSkills[v55]);
       uDamageAmount = v28;
       if ( v55 )
@@ -5171,7 +5171,7 @@
       {
         if ( pPlayer->HasItemEquipped((ITEM_EQUIP_TYPE)v59) )
         {
-          auto _s = (ItemGen *)&pPlayer->pDarkSpellbook.bIsSpellAvailable[36 * v57->uOffHand + 5];
+          auto _s = (ItemGen *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v57->uOffHand + 5];
           a4 = _s->_439DF3_get_additional_damage(&a2, &v62);
           if ( v62 && pMonster->sCurrentHP > 0 )
           {
@@ -7031,7 +7031,7 @@
     if ( !v21 )
       goto LABEL_59;
     v230 = pPlayer->pEquipment.uBow;
-    v22 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v21 + 5];
+    v22 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v21 + 5];
     v23 = *(int *)v22;
     v24 = papredoll_4E4C28 + array_4E4C30[v239].equip_x - pItemsTable->pItems[v23].uEquipX;
     a3b = paperdoll_4E4C2C + array_4E4C30[v239].equip_y - pItemsTable->pItems[v23].uEquipY;
@@ -7067,7 +7067,7 @@
       if ( !v31 )
         goto LABEL_93;
       v231 = v217->pEquipment.uCloak;
-      v32 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v31 + 5];
+      v32 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v31 + 5];
       v219 = v32;
       if ( *(int *)v32 != 525 )
       {
@@ -7121,7 +7121,7 @@
                 if ( !v43 )
                   goto LABEL_127;
                 v232 = v217->pEquipment.uBody;
-                v44 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v43 + 5];
+                v44 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v43 + 5];
                 v220 = v44;
                 if ( *(int *)v44 != 504 )
                 {
@@ -7180,7 +7180,7 @@
                           if ( !v56 )
                             goto LABEL_155;
                           v233 = v217->pEquipment.field_20;
-                          v57 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v56 + 5];
+                          v57 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v56 + 5];
                           v221 = v57;
                           v58 = *(int *)v57;
                           if ( *(int *)v57 == 529 )
@@ -7245,7 +7245,7 @@
                             v69 = v217->pEquipment.uMainHand;
                             uPlayerID_a = 2 * v239;
                             if ( !v69
-                              || (v70 = *(int *)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v69 + 5],
+                              || (v70 = *(int *)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v69 + 5],
                                   pItemsTable->pItems[v70].uEquipType != 1)
                               && (pItemsTable->pItems[v70].uSkillType != 4 || v217->pEquipment.uOffHand) )
                               pRenderer->DrawTextureTransparent(
@@ -7256,7 +7256,7 @@
                             if ( v71 )
                             {
                               v234 = v217->pEquipment.uBelt;
-                              v72 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v71 + 5];
+                              v72 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v71 + 5];
                               v222 = v72;
                               if ( *(int *)v72 == 524 )
                               {
@@ -7354,7 +7354,7 @@
                             v82 = v68->pEquipment.uMainHand;
                             if ( v82 )
                             {
-                              v83 = *(int *)&v68->pDarkSpellbook.bIsSpellAvailable[36 * v82 + 5];
+                              v83 = *(int *)&v68->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v82 + 5];
                               if ( pItemsTable->pItems[v83].uEquipType == 1
                                 || pItemsTable->pItems[v83].uSkillType == 4 && !v68->pEquipment.uOffHand )
                                 pRenderer->DrawTextureTransparent(
@@ -7387,7 +7387,7 @@
                                       if ( !v111 )
                                         goto LABEL_293;
                                       v236 = v68->pEquipment.uCloak;
-                                      v112 = (int)&v68->pDarkSpellbook.bIsSpellAvailable[36 * v111 + 5];
+                                      v112 = (int)&v68->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v111 + 5];
                                       v225 = v112;
                                       v113 = *(int *)v112;
                                       if ( v113 != 525 )
@@ -7435,7 +7435,7 @@
                                                 if ( !v123 )
                                                   goto LABEL_335;
                                                 v237 = v123;
-                                                v124 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v123 + 5];
+                                                v124 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v123 + 5];
                                                 v226 = v124;
                                                 if ( *(int *)v124 != 521 )
                                                 {
@@ -7540,7 +7540,7 @@
                                                   if ( !v134 )
                                                     goto LABEL_358;
                                                   v238 = v217->pEquipment.uMainHand;
-                                                  v135 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v134 + 5];
+                                                  v135 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v134 + 5];
                                                   v227 = v135;
                                                   v136 = *(int *)v135;
                                                   v137 = *(int *)v135;
@@ -7585,7 +7585,7 @@
                                                     v249 = v217->pEquipment.uOffHand;
                                                     if ( !v145 )
                                                       goto LABEL_393;
-                                                    v146 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v145 + 5];
+                                                    v146 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v145 + 5];
                                                     v228 = v146;
                                                     v147 = *(int *)v146;
                                                     v148 = *(int *)v146;
@@ -8236,7 +8236,7 @@
   uPlayerID_a = 2 * v5;
   v6 = pPlayer->pEquipment.uMainHand;
   if ( !v6
-    || (v7 = *(int *)&pPlayer->pDarkSpellbook.bIsSpellAvailable[36 * v6 + 5], pItemsTable->pItems[v7].uEquipType != 1)
+    || (v7 = *(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v6 + 5], pItemsTable->pItems[v7].uEquipType != 1)
     && (pItemsTable->pItems[v7].uSkillType != 4 || pPlayer->pEquipment.uOffHand) )
     pRenderer->DrawTextureTransparent(
       papredoll_4E4C28 + dword_4E5AE0[2 * v5],
@@ -8250,7 +8250,7 @@
   if ( v8 )
   {
     v229 = pPlayer->pEquipment.uMainHand;
-    v9 = (int)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
+    v9 = (int)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v8 + 5];
     v10 = v5 << 7;
     v218 = v9;
     v11 = *(int *)v9;
@@ -8341,7 +8341,7 @@
   v161 = v217->pEquipment.uMainHand;
   if ( v161 )
   {
-    v162 = *(int *)&v217->pDarkSpellbook.bIsSpellAvailable[36 * v161 + 5];
+    v162 = *(int *)&v217->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v161 + 5];
     if ( pItemsTable->pItems[v162].uEquipType == 1
       || pItemsTable->pItems[v162].uSkillType == 4 && !v217->pEquipment.uOffHand )
       pRenderer->DrawTextureTransparent(
@@ -8443,7 +8443,7 @@
     if ( !*(int *)v46 )
       goto LABEL_24;
     v39 = *(int *)v46;
-    v4 = (int)&pPlayer->pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v46 + 5];
+    v4 = (int)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *(int *)v46 + 5];
     a3 = *(int *)((char *)dword_4E5C34 + v3);
     a2 = *(int *)((char *)dword_4E5C1C + v3);
     v5 = pIcons_LOD->LoadTexture(pItemsTable->pItems[*(int *)v4].pIconName, TEXTURE_16BIT_PALETTE);
@@ -8533,7 +8533,7 @@
   if ( !v15 )
     goto LABEL_46;
   v41 = pPlayer->pEquipment.field_24;
-  v49 = (int)&pPlayer->pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5];
+  v49 = (int)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5];
   v16 = pIcons_LOD->LoadTexture(pItemsTable->pItems[*(int *)v49].pIconName, TEXTURE_16BIT_PALETTE);
   v17 = *(int *)(v49 + 20);
   if ( !(*(int *)(v49 + 20) & 0xF0) )
@@ -8615,7 +8615,7 @@
   if ( !v26 )
     return;
   v43 = pPlayer->pEquipment.field_1C;
-  v27 = (int)&pPlayer->pDarkSpellbook.bIsSpellAvailable[36 * v26 + 5];
+  v27 = (int)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v26 + 5];
   v28 = pIcons_LOD->LoadTexture(pItemsTable->pItems[*(int *)v27].pIconName, TEXTURE_16BIT_PALETTE);
   v29 = *(int *)(v27 + 20);
   if ( !(*(int *)(v27 + 20) & 0xF0) )
@@ -8788,7 +8788,7 @@
       if ( *v5 )
       {
         result = 9 * *v5;
-        if ( *(int *)&pPlayer->pDarkSpellbook.bIsSpellAvailable[36 * *v5 + 5] == uItemID )
+        if ( *(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * *v5 + 5] == uItemID )
           break;
       }
       ++v4;
@@ -8803,7 +8803,7 @@
           if ( *v7 )
           {
             result *= 9;
-            if ( *(int *)&pPlayer->pDarkSpellbook.bIsSpellAvailable[4 * result + 5] == uItemID )
+            if ( *(int *)&pPlayer->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5] == uItemID )
               break;
           }
           ++v6;
@@ -8847,7 +8847,7 @@
         if ( !result )
           break;
         result *= 9;
-        if ( *(int *)&v6->pDarkSpellbook.bIsSpellAvailable[4 * result + 5] != v5 )
+        if ( *(int *)&v6->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5] != v5 )
           break;
         ++pPlayers;
         if ( (signed int)pPlayers >= (signed int)&qword_A750D8 )
@@ -8859,7 +8859,7 @@
   result = sub_43EE15_player_has_item(604u, ::pPlayers[a1], 0);
   if ( !result
     || (result = v2->pEquipment.uBody) == 0
-    || (result *= 9, *(int *)&v2->pDarkSpellbook.bIsSpellAvailable[4 * result + 5] != v3) )
+    || (result *= 9, *(int *)&v2->spellbook.pDarkSpellbook.bIsSpellAvailable[4 * result + 5] != v3) )
   {
 LABEL_6:
     LOBYTE(result) = 0;
@@ -15079,7 +15079,7 @@
             {
               if ( v26 < 800 )
               {
-                _this.uAttributtes |= 1u;
+                _this.uAttributes |= 1u;
                 _this.uItemID = v26;
                 if ( pItemsTable->pItems[v26].uEquipType == 12 )
                 {
@@ -15528,11 +15528,11 @@
       {
         if ( pParty->pPickedItem.uItemID == 236 )
         {
-          v35 = v27->uAttributtes;
+          v35 = v27->uAttributes;
           if ( v35 & 2 || (v51 & 0x80000000u) != 0 || (signed int)v51 > 12 || (signed int)v28 >= 500 )
             goto LABEL_92;
           LOWORD(v35) = v35 | 0x210;
-          v27->uAttributtes = v35;
+          v27->uAttributes = v35;
         }
         else
         {
@@ -15543,7 +15543,7 @@
             v27->UpdateTempBonus(pParty->uTimePlayed);
             v33 = v27->uItemID;
             if ( (signed int)v27->uItemID >= 64 && (signed int)v33 <= 65
-              || (pOut.y = v27->uAttributtes, pOut.y & 2)
+              || (pOut.y = v27->uAttributes, pOut.y & 2)
               || v27->uAdditionalValue
               || v27->_bonus_type
               || v51 && v51 != 1 && v51 != 2
@@ -15559,7 +15559,7 @@
             if ( pParty->pPickedItem.uItemID != 263
               || (v27->UpdateTempBonus(pParty->uTimePlayed), v30 = v27->uItemID, (signed int)v27->uItemID >= 64)
               && (signed int)v30 <= 65
-              || (pOut.y = v27->uAttributtes, pOut.y & 2)
+              || (pOut.y = v27->uAttributes, pOut.y & 2)
               || v27->uAdditionalValue
               || v27->_bonus_type
               || v51 && v51 != 1 && v51 != 2
@@ -15574,7 +15574,7 @@
           LODWORD(v32) = pOut.y;
           LOBYTE(v32) = LOBYTE(pOut.y) | 0x18;
           HIDWORD(v27->uExpireTime) = HIDWORD(v32);
-          v27->uAttributtes = v32;
+          v27->uAttributes = v32;
         }
         dword_50C9A8 = 256;
         goto LABEL_92;
@@ -16990,7 +16990,9 @@
       v7 = pTmpBuf2;
       v20 = pTmpBuf2;
       strcat(pTmpBuf2, "\n");
-      v23 = pConditionImportancyTable;
+
+      extern unsigned int pConditionImportancyTable[18];
+      v23 = (int *)pConditionImportancyTable;
       _y = pPlayers[uActiveCharacter];
       v21 = pPlayers[uActiveCharacter];
       do
@@ -17131,7 +17133,6 @@
   }
   return (char)_y;
 }
-// 4E2A12: using guessed type void *off_4E2A12;
 
 //----- (00418511) --------------------------------------------------------
 char __fastcall CharacterUI_StatsTab_Draw(unsigned int uPlayerID)
@@ -17372,7 +17373,7 @@
   sprintfex(pTmpBuf, "%s", pGlobalTXT_LocalizationStrings[12], v60, v57, v56);
   pGUIWindow_CurrentMenu->DrawText(pFontArrus, 26, v55, 0, pTmpBuf, 0, 0, 0);
   v61 = v55 + 2 * LOBYTE(pFontArrus->uFontHeight) - 2;
-  v62 = pPlayer->GetMajorConditionrIdx();
+  v62 = pPlayer->GetMajorConditionIdx();
   v63 = aCharacterConditionNames[v62];
   v64 = GetConditionDrawColor(v62);
   sprintfex(pTmpBuf, "%s: ", pGlobalTXT_LocalizationStrings[47], v64, v63);
--- a/mm7_6.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_6.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -3541,7 +3541,7 @@
         a1.uSoundID = LOWORD(v3->field_10);
         memcpy(
           &a1.stru_24,
-          &pParty->pPlayers[v3->uPlayerID].pDarkSpellbook.bIsSpellAvailable[36
+          &pParty->pPlayers[v3->uPlayerID].spellbook.pDarkSpellbook.bIsSpellAvailable[36
                                                                          * pParty->pPlayers[v3->uPlayerID].pEquipment.uMainHand
                                                                          + 5],
           sizeof(a1.stru_24));
@@ -5403,7 +5403,7 @@
               || v726->pInventoryItems[a2].uAdditionalValue != v1
               || v726->pInventoryItems[a2]._bonus_type != v1
               || v726->pInventoryItems[a2]._bonus_strength != v1
-              || (_this = (ItemGen *)((char *)&v726->pInventoryItems[a2] + 20), v726->pInventoryItems[a2].uAttributtes & 2) )
+              || (_this = (ItemGen *)((char *)&v726->pInventoryItems[a2] + 20), v726->pInventoryItems[a2].uAttributes & 2) )
               goto LABEL_616;
             v247 = (char *)&pItemsTable->pItems[v246].pIconName;
             LODWORD(v725) = (int)v247;
@@ -5511,7 +5511,7 @@
           || (v291 = pItemsTable->pItems[v290].uEquipType) == 0
           || v291 == 1
           || v291 == 2
-          || _this->uAttributtes & 2 )
+          || _this->uAttributes & 2 )
           goto LABEL_616;
         if ( _this->GetValue() < 0x1C2 )
           uRequiredMana = 1;
@@ -5594,7 +5594,7 @@
           v294->_bonus_strength = pItemsTable->field_116D8[18]
                                 + rand() % (pItemsTable->field_116D8[19] - pItemsTable->field_116D8[18] + 1);
         }
-        v294->uAttributtes |= 0x20u;
+        v294->uAttributes |= 0x20u;
         goto LABEL_1055;
       case 31:
         amount = 10 * v2;
@@ -7999,7 +7999,7 @@
         v12 = v1->pEquipment.uMainHand;
         v29 = 1;
         _42777D_CastSpell_UseWand_ShootArrow(
-          *((int *)&pSpellDatas[66].field_8 + *(int *)&v1->pDarkSpellbook.bIsSpellAvailable[36 * v12 + 5]),
+          *((int *)&pSpellDatas[66].field_8 + *(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v12 + 5]),
           v0 - 1,
           8u,
           0,
@@ -8022,7 +8022,7 @@
           {
             v15 = v1->pEquipment.uMainHand;
             if ( v1->HasItemEquipped(EQUIP_TWO_HANDED) )
-              v34 = pItemsTable->pItems[*(int *)&v1->pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5]].uSkillType;
+              v34 = pItemsTable->pItems[*(int *)&v1->spellbook.pDarkSpellbook.bIsSpellAvailable[36 * v15 + 5]].uSkillType;
             pTurnEngine->_40471C();
           }
           else
--- a/mm7_data.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_data.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -1936,37 +1936,16 @@
 char byte_4ED498; // weak
 __int16 pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing__negindex[777]; // weak
 __int16 pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[4];
-unsigned __int8 pBaseHealthByClass[12];
-char byte_4ED75C[777]; // weak
-unsigned __int8 pBaseHealthPerLevelByClass[36];
-unsigned __int8 pBaseManaPerLevelByClass[36];
-char byte_4ED820[777]; // weak
-char byte_4ED94C[777]; // weak
 char byte_4ED970_skill_learn_ability_by_class_table[32][37];
 int dword_4EDEA0[777]; // weak
 int dword_4EDEB4[777]; // weak
 int dword_4EDEC4[777]; // weak
 __int16 word_4EDED8[777]; // weak
 __int16 word_4EDEDC; // weak
-int pConditionImportancyTable[18];
 _UNKNOWN unk_4EDF40; // weak
-unsigned __int8 pConditionStrengthMultiplier[19];
-unsigned __int8 pConditionIntelligenceMultiplier[19];
-unsigned __int8 pConditionWillpowerMultiplier[19];
-unsigned __int8 pConditionEnduranceMultiplier[19];
-unsigned __int8 pConditionAccuracyMultiplier[19];
-unsigned __int8 pConditionSpeedMultiplier[19];
-unsigned __int8 pConditionLuckMultiplier[19];
-unsigned int pAgeingTable[4];
-unsigned __int8 pAgeingStrengthMultiplier[4];
-unsigned __int8 pAgeingIntelligenceMultiplier[4];
-unsigned __int8 pAgeingWillpowerMultiplier[4];
-unsigned __int8 pAgeingEnduranceMultiplier[4];
-unsigned __int8 pAgeingAccuracyMultiplier[4];
-unsigned __int8 pAgeingSpeedMultiplier[4];
-unsigned __int8 pAgeingLuckMultiplier[4];
-__int16 word_4EDFFC; // weak
-short word_4EDFFE[29]; // idb
+short word_4EDFFC[30] = {500, 500, 400, 350, 300, 275, 250, 225, 200, 175,
+                         150, 125, 100,  75,  50,  40,  35,  30,  25,  21,
+                         19,   17,  15,  13,  11,   9,   7,   5,   3,   0};
 char player_stat_bonuses[777]; // weak
 unsigned int pHiredNPCsIconsOffsetsX[2];
 unsigned int pHiredNPCsIconsOffsetsY[2];
@@ -2630,7 +2609,7 @@
 void *ptr_6A0D08;
 int _6A0D0C_txt_lod_loading; // weak
 int _6A0D10_txt_lod_loading__unused; // weak
-unsigned int uCurrentMenuID;
+MENU_STATE uCurrentMenuID;
 unsigned int uGameState;
 int uDefaultTravelTime_ByFoot; // weak
 int day_attrib; // weak
--- a/mm7_data.h	Sat Oct 13 20:18:28 2012 +0200
+++ b/mm7_data.h	Sun Oct 14 00:27:38 2012 +0200
@@ -1924,37 +1924,14 @@
 extern char byte_4ED498; // weak
 extern __int16 pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing__negindex[]; // weak
 extern __int16 pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[4];
-extern unsigned __int8 pBaseHealthByClass[12];
-extern char byte_4ED75C[]; // weak
-extern unsigned __int8 pBaseHealthPerLevelByClass[36];
-extern unsigned __int8 pBaseManaPerLevelByClass[36];
-extern char byte_4ED820[]; // weak
-extern char byte_4ED94C[]; // weak
 extern char byte_4ED970_skill_learn_ability_by_class_table[32][37];
 extern int dword_4EDEA0[]; // weak
 extern int dword_4EDEB4[]; // weak
 extern int dword_4EDEC4[]; // weak
 extern __int16 word_4EDED8[]; // weak
 extern __int16 word_4EDEDC; // weak
-extern int pConditionImportancyTable[18];
 extern _UNKNOWN unk_4EDF40; // weak
-extern unsigned __int8 pConditionStrengthMultiplier[19];
-extern unsigned __int8 pConditionIntelligenceMultiplier[19];
-extern unsigned __int8 pConditionWillpowerMultiplier[19];
-extern unsigned __int8 pConditionEnduranceMultiplier[19];
-extern unsigned __int8 pConditionAccuracyMultiplier[19];
-extern unsigned __int8 pConditionSpeedMultiplier[19];
-extern unsigned __int8 pConditionLuckMultiplier[19];
-extern unsigned int pAgeingTable[4];
-extern unsigned __int8 pAgeingStrengthMultiplier[4];
-extern unsigned __int8 pAgeingIntelligenceMultiplier[4];
-extern unsigned __int8 pAgeingWillpowerMultiplier[4];
-extern unsigned __int8 pAgeingEnduranceMultiplier[4];
-extern unsigned __int8 pAgeingAccuracyMultiplier[4];
-extern unsigned __int8 pAgeingSpeedMultiplier[4];
-extern unsigned __int8 pAgeingLuckMultiplier[4];
-extern __int16 word_4EDFFC; // weak
-extern short word_4EDFFE[29]; // idb
+extern __int16 word_4EDFFC[30];
 extern char player_stat_bonuses[]; // weak
 extern unsigned int pHiredNPCsIconsOffsetsX[2];
 extern unsigned int pHiredNPCsIconsOffsetsY[2];
@@ -2620,7 +2597,7 @@
 extern void *ptr_6A0D08;
 extern int _6A0D0C_txt_lod_loading; // weak
 extern int _6A0D10_txt_lod_loading__unused; // weak
-extern unsigned int uCurrentMenuID;
+extern enum MENU_STATE uCurrentMenuID;
 extern unsigned int uGameState;
 extern int uDefaultTravelTime_ByFoot; // weak
 extern int day_attrib; // weak
@@ -3297,8 +3274,8 @@
 int __cdecl AbortWithError();
 void Abortf(const char *Format, ...);
 void __cdecl crt_deconstruct_ptr_6A0118();
-void __thiscall SetCurrentMenuID(unsigned int uMenu); // idb
-unsigned int __cdecl GetCurrentMenuID();
+void SetCurrentMenuID(enum MENU_STATE); // idb
+enum MENU_STATE GetCurrentMenuID();
 void *__thiscall output_debug_string(void *_this, std::string a2, const char *a3, int a4);
 std::string *__fastcall _4678E2_make_error_string(std::string *a1, int line, std::string file);
 int __thiscall sub_467D5D(int _this);
--- a/stru6.cpp	Sat Oct 13 20:18:28 2012 +0200
+++ b/stru6.cpp	Sun Oct 14 00:27:38 2012 +0200
@@ -1660,6 +1660,7 @@
   unsigned __int8 v6; // of@3
   IconFrame *v7; // eax@4
 
+  uint _it = 0;
   v1 = pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing;
   v2 = (char *)&this->pPlayerBuffs[0].uSpellIconID;
   do
@@ -1685,7 +1686,8 @@
     v2 += 16;
     ++v1;
   }
-  while ( (signed int)v1 < (signed int)pBaseHealthByClass );
+  //while ( (signed int)v1 < (signed int)pBaseHealthByClass );
+  while (++_it != 4);
 }
 
 //----- (004A90A0) --------------------------------------------------------