changeset 2549:3121fb54a110

Rest & Spelbook refactored into class
author a.parshin
date Tue, 12 May 2015 11:07:32 +0200
parents 87e5590d034b
children fb42e2662c38
files Build/Visual Studio 2013/World of Might and Magic.vcxproj Build/Visual Studio 2013/World of Might and Magic.vcxproj.filters Engine/Party.h Engine/Spells/Spells.cpp GUI/GUIWindow.cpp GUI/GUIWindow.h GUI/UI/Books/UISpellBook.cpp GUI/UI/Books/UISpellBook.h GUI/UI/Spellbook.cpp GUI/UI/Spellbook.h GUI/UI/UIBooks.cpp GUI/UI/UIBooks.h GUI/UI/UIRest.cpp GUI/UI/UIRest.h GUI/UI/UITransition.cpp Game/Game.cpp
diffstat 15 files changed, 402 insertions(+), 358 deletions(-) [+]
line wrap: on
line diff
--- a/Build/Visual Studio 2013/World of Might and Magic.vcxproj	Tue May 12 03:24:19 2015 +0200
+++ b/Build/Visual Studio 2013/World of Might and Magic.vcxproj	Tue May 12 11:07:32 2015 +0200
@@ -167,7 +167,7 @@
     <ClCompile Include="..\..\GUI\UI\Books\MapBook.cpp" />
     <ClCompile Include="..\..\GUI\UI\Books\QuestBook.cpp" />
     <ClCompile Include="..\..\GUI\UI\Books\TownPortalBook.cpp" />
-    <ClCompile Include="..\..\GUI\UI\Books\UISpellBook.cpp" />
+    <ClCompile Include="..\..\GUI\UI\Spellbook.cpp" />
     <ClCompile Include="..\..\GUI\UI\UIArena.cpp" />
     <ClCompile Include="..\..\GUI\UI\UIBooks.cpp" />
     <ClCompile Include="..\..\GUI\UI\UICharacter.cpp" />
@@ -345,7 +345,7 @@
     <ClInclude Include="..\..\GUI\UI\Books\MapBook.h" />
     <ClInclude Include="..\..\GUI\UI\Books\QuestBook.h" />
     <ClInclude Include="..\..\GUI\UI\Books\TownPortalBook.h" />
-    <ClInclude Include="..\..\GUI\UI\Books\UISpellBook.h" />
+    <ClInclude Include="..\..\GUI\UI\Spellbook.h" />
     <ClInclude Include="..\..\GUI\UI\UIArena.h" />
     <ClInclude Include="..\..\GUI\UI\UIBooks.h" />
     <ClInclude Include="..\..\GUI\UI\UICharacter.h" />
--- a/Build/Visual Studio 2013/World of Might and Magic.vcxproj.filters	Tue May 12 03:24:19 2015 +0200
+++ b/Build/Visual Studio 2013/World of Might and Magic.vcxproj.filters	Tue May 12 11:07:32 2015 +0200
@@ -487,9 +487,6 @@
     <ClCompile Include="..\..\GUI\NewUI\MainMenu.cpp">
       <Filter>GUI\NewUI</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\GUI\UI\Books\UISpellBook.cpp">
-      <Filter>GUI\UI\Books</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\GUI\UI\UIGuilds.cpp">
       <Filter>GUI\UI</Filter>
     </ClCompile>
@@ -598,6 +595,9 @@
     <ClCompile Include="..\..\GUI\UI\Books\JournalBook.cpp">
       <Filter>GUI\UI\Books</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\GUI\UI\Spellbook.cpp">
+      <Filter>GUI\UI</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\lib\libavcodec\avcodec.h">
@@ -1249,9 +1249,6 @@
     <ClInclude Include="..\..\GUI\NewUI\MainMenu.h">
       <Filter>GUI\NewUI</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\GUI\UI\Books\UISpellBook.h">
-      <Filter>GUI\UI\Books</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\GUI\UI\UIGame.h">
       <Filter>GUI\UI</Filter>
     </ClInclude>
@@ -1363,6 +1360,9 @@
     <ClInclude Include="..\..\GUI\UI\Books\JournalBook.h">
       <Filter>GUI\UI\Books</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\GUI\UI\Spellbook.h">
+      <Filter>GUI\UI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\lib\OpenAL\lib\x86\avcodec-55.def">
--- a/Engine/Party.h	Tue May 12 03:24:19 2015 +0200
+++ b/Engine/Party.h	Tue May 12 11:07:32 2015 +0200
@@ -19,6 +19,9 @@
   PARTY_QUEST_EMERALD_MARGARETH_OFF = 17,
 
   PARTY_QUEST_EVENMORN_MAP_FOUND = 64,
+
+  PARTY_QUEST_HARMONDALE_REBUILT = 98,
+
   PARTY_QUEST_FINISHED_EMERALD_ISLE = 136,
 
   PARTY_QUEST_OBELISK_HARMONDALE = 164,
--- a/Engine/Spells/Spells.cpp	Tue May 12 03:24:19 2015 +0200
+++ b/Engine/Spells/Spells.cpp	Tue May 12 11:07:32 2015 +0200
@@ -200,19 +200,6 @@
 };
 
 
-std::array<std::array<unsigned char, 12>, 9> pSpellbookSpellIndices = // 4E2430
-	{{  //0   1   2   3  4    5   6  7    8  9   10  11
-		{0,  3,  1,  8, 11,  7,  4, 10,  6,  2,  5,  9},
-		{0, 11,  2,  9,  6,  8,  5, 10,  3,  7,  1,  4},
-		{0,  4,  8,  9,  1, 10,  3, 11,  7,  6,  2,  5}, 
-		{0,  7, 10,  8,  2, 11,  1,  5,  3,  6,  4,  9},
-		{0,  5, 10, 11,  7,  2,  8,  1,  4,  9,  3,  6},
-		{0,  5,  9,  8,  3,  7,  6,  4,  1, 11,  2, 10}, 
-		{0,  1,  6,  9,  3,  5,  8, 11,  7, 10,  4,  2},
-		{0,  1, 10, 11,  9,  4,  3,  6,  5,  7,  8,  2},
-		{0,  9,  3,  7,  1,  5,  2, 10, 11,  8,  6,  4}
-}};
-
 	std::array<std::array<struct SpellBookIconPos, 12>, 9> pIconPos={{
 
 		 {  0,   0,  17,  13, 115,   2, 217,  15,
--- a/GUI/GUIWindow.cpp	Tue May 12 03:24:19 2015 +0200
+++ b/GUI/GUIWindow.cpp	Tue May 12 11:07:32 2015 +0200
@@ -216,13 +216,6 @@
 }
 
 
-GUIWindow_Spellbook::GUIWindow_Spellbook(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
-    GUIWindow(x, y, width, height, button, hint)
-{
-    InitializeSpellBookTextures();
-    OpenSpellBook();
-}
-
 GUIWindow_GenericDialogue::GUIWindow_GenericDialogue(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
     GUIWindow(x, y, width, height, button, hint)
 {
@@ -401,6 +394,8 @@
 
 void GUIWindow_Dialogue::Release()
 {
+// -----------------------------------------
+// 0041C26A void GUIWindow::Release --- part
     if (!dword_591084)
         pDialogueNPCPortraits[0]->Release();
     uNumDialogueNPCPortraits = 0;
@@ -412,16 +407,10 @@
     GUIWindow::Release();
 }
 
-void GUIWindow_Spellbook::Release()
-{
-    OnCloseSpellBookPage();
-    OnCloseSpellBook();
-
-    GUIWindow::Release();
-}
-
 void GUIWindow_GenericDialogue::Release()
 {
+// -----------------------------------------
+// 0041C26A void GUIWindow::Release --- part
     pIcons_LOD->SyncLoadedFilesCount();
     current_screen_type = prev_screen_type;
     pKeyActionMap->SetWindowInputStatus(WINDOW_INPUT_CANCELLED);
@@ -431,6 +420,8 @@
 
 void GUIWindow_House::Release()
 {
+// -----------------------------------------
+// 0041C26A void GUIWindow::Release --- part
     for (int i = 0; i < uNumDialogueNPCPortraits; ++i)
         pDialogueNPCPortraits[i]->Release();
     uNumDialogueNPCPortraits = 0;
@@ -607,61 +598,6 @@
 }
 
 
-//----- (00411621) --------------------------------------------------------
-void GUIWindow::OpenSpellBook()
-{
-  Player *pPlayer; // edi@1
-  //GUIWindow *pWindow; // esi@1
-  //unsigned int v3; // ebp@1
-  int v4; // eax@3
-  ///GUIButton *result; // eax@25
-  int a2; // [sp+10h] [bp-8h]@1
-  //int v7; // [sp+14h] [bp-4h]@1
-
-  pPlayer = pPlayers[uActiveCharacter];
-  //pWindow = this;
-  LoadSpellbook(pPlayer->lastOpenedSpellbookPage);
-  //v3 = 0;
-  a2 = 0;
-
-  PlayerSpellbookChapter* chapter = &pPlayer->spellbook.pChapters[pPlayer->lastOpenedSpellbookPage];
-  for (uint i = 0; i < 11; ++i)
-  {
-    if (!chapter->bIsSpellAvailable[i])
-      continue;
-		v4= pPlayer->lastOpenedSpellbookPage;
-      //v4 = (12 * pPlayer->lastOpenedSpellbookPage + pSpellbookSpellIndices[pPlayer->lastOpenedSpellbookPage][i + 1]);
-      CreateButton(pViewport->uViewportTL_X +  pIconPos[v4][pSpellbookSpellIndices[v4][i+1]].Xpos,
-                   pViewport->uViewportTL_Y +  pIconPos[v4][pSpellbookSpellIndices[v4][i+1]].Ypos,  //dword_4E20D0
-                   SBPageSSpellsTextureList[i + 1]->uTextureWidth,
-                   SBPageSSpellsTextureList[i + 1]->uTextureHeight,
-                   1, 79, UIMSG_SelectSpell, i, 0, "", 0);
-      ++a2;
-    //++v3;
-  }
-  //while ( (signed int)v3 < 11 );
-
-  CreateButton(0, 0, 0, 0, 1, 0, UIMSG_SpellBook_PressTab, 0, '\t', "", 0);
-  if ( a2 )
-    _41D08F_set_keyboard_control_group(a2, 0, 0, 0);
-
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_FIRE])   CreateButton(399,  10, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 0, 0, aSpellSchoolNames[0], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_AIR])    CreateButton(399,  46, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 1, 0, aSpellSchoolNames[1], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_WATER])  CreateButton(399,  83, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 2, 0, aSpellSchoolNames[2], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_EARTH])  CreateButton(399, 121, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 3, 0, aSpellSchoolNames[3], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_SPIRIT]) CreateButton(399, 158, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 4, 0, aSpellSchoolNames[4], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_MIND])   CreateButton(400, 196, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 5, 0, aSpellSchoolNames[5], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_BODY])   CreateButton(400, 234, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 6, 0, aSpellSchoolNames[6], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_LIGHT])  CreateButton(400, 271, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 7, 0, aSpellSchoolNames[7], 0);
-  if (pPlayer->pActiveSkills[PLAYER_SKILL_DARK])   CreateButton(400, 307, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 8, 0, aSpellSchoolNames[8], 0);
-
-                            CreateButton(476, 450, pSBClickQuickSpellBtnTextr->uTextureWidth, pSBClickQuickSpellBtnTextr->uTextureHeight, 1, 78, UIMSG_ClickInstallRemoveQuickSpellBtn, 0, 0, "", 0);
-  pBtn_InstallRemoveSpell = CreateButton(476, 450, 48, 32, 1, 78, UIMSG_ClickInstallRemoveQuickSpellBtn, 0, 0, "", pSBClickQuickSpellBtnTextr, 0);
-                            CreateButton(561, 450, pSpellBookClickCloseBtnTextr->uTextureWidth, pSpellBookClickCloseBtnTextr->uTextureHeight, 1,  0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[79], 0);
-  pBtn_CloseBook          = CreateButton(561, 450, 48, 32, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[79], pSpellBookClickCloseBtnTextr, 0);
-}
-// 50640C: using guessed type int dword_50640C[];
-
 //----- (004B3157) --------------------------------------------------------
 void GUIWindow::HouseDialogManager()
 {
@@ -1378,13 +1314,6 @@
     GameUI_DrawBranchlessDialogue();
 }
 
-void GUIWindow_Spellbook::Update()
-{
-// -----------------------------------
-// 004156F0 GUI_UpdateWindows --- part
-    DrawSpellBookContent(pPlayers[uActiveCharacter]);
-}
-
 void GUIWindow_Chest::Update()
 {
 // -----------------------------------
--- a/GUI/GUIWindow.h	Tue May 12 03:24:19 2015 +0200
+++ b/GUI/GUIWindow.h	Tue May 12 11:07:32 2015 +0200
@@ -342,7 +342,6 @@
   void DrawTitleText(GUIFont *a2, signed int uHorizontalMargin, unsigned int uVerticalMargin, unsigned __int16 uDefaultColor, const char *pInString, unsigned int uLineSpacing);
   void DrawShops_next_generation_time_string(__int64 next_generation_time);
   void HouseDialogManager();
-  void OpenSpellBook();
   void DrawMessageBox(int arg0);
   GUIButton *GetControl(unsigned int uID);
   void _41D08F_set_keyboard_control_group(int num_buttons, int a3, int a4, int a5);
@@ -380,15 +379,6 @@
 
 
 
-struct GUIWindow_BooksButtonOverlay : public GUIWindow
-{
-    GUIWindow_BooksButtonOverlay(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
-        GUIWindow(x, y, width, height, button, hint)
-    {}
-    virtual ~GUIWindow_BooksButtonOverlay() {}
-
-    virtual void Update();
-};
 struct GUIWindow_Dialogue : public GUIWindow
 {
     GUIWindow_Dialogue(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint);
@@ -397,14 +387,6 @@
     virtual void Update();
     virtual void Release();
 };
-struct GUIWindow_Spellbook : public GUIWindow
-{
-    GUIWindow_Spellbook(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint);
-    virtual ~GUIWindow_Spellbook() {}
-
-    virtual void Update();
-    virtual void Release();
-};
 struct GUIWindow_GenericDialogue : public GUIWindow
 {
     GUIWindow_GenericDialogue(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint);
@@ -697,19 +679,7 @@
 
 
 // book ui
-void InitializeSpellBookTextures();
-void DrawSpellBookContent(Player *player);
-void LoadSpellbook(unsigned int uID); // idb
 void DrawSpellDescriptionPopup(int spell_index);
-void OnCloseSpellBookPage();
-void OnCloseSpellBook();
-
-
-
-// rest ui
-void PrepareToLoadRestUI();
-GUIWindow *RestUI_Load();
-
 
 
 
--- a/GUI/UI/Books/UISpellBook.cpp	Tue May 12 03:24:19 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-#define _CRT_SECURE_NO_WARNINGS
-
-#include "Engine/Engine.h"
-
-#include "..\..\..\Engine/Graphics/Render.h"
-#include "..\..\..\IO/Mouse.h"
-#include "..\UIBooks.h"
-#include "..\..\..\GUI/GUIWindow.h"
-#include "..\..\..\GUI/GUIFont.h"
-#include "..\..\..\Engine/Party.h"
-#include "..\..\..\Media/Audio/AudioPlayer.h"
-#include "..\..\..\Engine/LOD.h"
-#include "..\..\..\Engine/Graphics/Viewport.h"
-#include "..\..\..\Engine/texts.h"
-
-std::array<char *, 9> spellbook_texture_filename_suffices = {{"f", "a", "w", "e", "s", "m", "b", "l", "d"}}; // weak
-
-//----- (00411300) --------------------------------------------------------
-void LoadSpellbook(unsigned int spell_school)
-{
-  char pContainer[20]; // [sp+Ch] [bp-1Ch]@7
-
-  byte_506550 = 0;
-  if ( pPlayers[uActiveCharacter]->uQuickSpell && (unsigned __int8)pPlayers[uActiveCharacter]->uQuickSpell / 11 == spell_school )
-    quick_spell_at_page = (unsigned __int8)pPlayers[uActiveCharacter]->uQuickSpell - 11 * spell_school;
-  else
-    quick_spell_at_page = 0;
-
-  for (uint i = 1; i <= 11; ++i)
-  {
-    if (pPlayers[uActiveCharacter]->spellbook.pChapters[spell_school].bIsSpellAvailable[i - 1])
-    {
-      sprintf(pContainer, "SB%sS%02d", spellbook_texture_filename_suffices[spell_school], pSpellbookSpellIndices[spell_school][i]);
-      SBPageSSpellsTextureList[i] = pIcons_LOD->LoadTexturePtr(pContainer, TEXTURE_16BIT_PALETTE);
-
-      sprintf(pContainer, "SB%sC%02d", spellbook_texture_filename_suffices[spell_school], pSpellbookSpellIndices[spell_school][i]);
-      SBPageCSpellsTextureList[i] = pIcons_LOD->LoadTexturePtr(pContainer, TEXTURE_16BIT_PALETTE);
-    }
-  }
-}
-
-//----- (00412AF9) --------------------------------------------------------
-static void BookUI_Spellbook_DrawCurrentSchoolBackground()
-{
-  int pTexID = 0;
-  if ( uActiveCharacter )
-    pTexID = pParty->pPlayers[uActiveCharacter - 1].lastOpenedSpellbookPage;
-  pRenderer->DrawTextureIndexed(8, 8, pSpellBookPagesTextr[pTexID]);
-  pRenderer->DrawTextureIndexed(476, 450, pSBQuickSpellBtnTextr);
-  pRenderer->DrawTextureIndexed(561, 450, pSpellBookCloseBtnTextr);
-}
-
-//----- (00412B58) --------------------------------------------------------
-void DrawSpellBookContent(Player *player)
-{
-  Texture *PendingTexture; // edi@1
-  Texture *pTexture; // edx@5
-  int v10; // eax@13
-  unsigned int pX_coord; // esi@18
-  unsigned int pY_coord; // edi@18
-  Texture *pPageTexture; // eax@21
-//  signed int v22; // [sp-4h] [bp-24h]@22
-  POINT a2; // [sp+18h] [bp-8h]@13
-
-  static unsigned int texture_tab_coord1[9][2]=
-      {{406, 9}, {406, 46}, {406, 84}, {406,121}, {407,158}, {405, 196}, {405, 234}, {405, 272}, {405,309} };
-
-  static unsigned int texture_tab_coord0[9][2]=
-      {{415, 10}, {415, 46}, {415, 83}, {415,121}, {415,158}, {416, 196}, {416, 234}, {416, 271}, {416,307} };
-
-  BookUI_Spellbook_DrawCurrentSchoolBackground();
-
-  PendingTexture = pIcons_LOD->GetTexture(pIcons_LOD->FindTextureByName("Pending"));
-  pRenderer->ClearZBuffer(0, 479);
-  if ( (11 * player->lastOpenedSpellbookPage) || ((11 * player->lastOpenedSpellbookPage) + 11) )//??? maybe structure need fix
-  {
-    for ( uint i = 1; i <= 11; ++i )
-    {
-      if (player->_achieved_awards_bits[(11 * player->lastOpenedSpellbookPage) + i + 63] )
-      {
-        if ( SBPageSSpellsTextureList[i] != PendingTexture )
-        {
-          if ( quick_spell_at_page == i )
-            pTexture = SBPageCSpellsTextureList[i];
-          else
-            pTexture = SBPageSSpellsTextureList[i];
-          if ( pTexture->pLevelOfDetail0_prolly_alpha_mask )
-          {
-            pX_coord = pViewport->uViewportTL_X +  pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Xpos;
-            pY_coord = pViewport->uViewportTL_Y +  pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Ypos;
-            if ( pTexture->pBits & 0x200 )
-              pRenderer->DrawTextureIndexedAlpha(pX_coord, pY_coord, pTexture);
-            else
-              pRenderer->DrawTextureIndexed(pX_coord, pY_coord, pTexture);
-            pRenderer->DrawMaskToZBuffer(pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Xpos,
-                                         pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Ypos, pTexture, i);
-          }
-        }
-      }
-    }
-  }
-
-  pMouse->GetCursorPos(&a2);
-  v10 = pRenderer->pActiveZBuffer[a2.x + pSRZBufferLineOffsets[a2.y]] & 0xFFFF;
-  if ( v10 )
-  {
-    if ( SBPageCSpellsTextureList[v10]->pLevelOfDetail0_prolly_alpha_mask )
-    {
-      pX_coord = pViewport->uViewportTL_X + pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][v10]].Xpos;
-      pY_coord = pViewport->uViewportTL_Y + pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][v10]].Ypos;
-      if ( SBPageCSpellsTextureList[v10]->pBits & 0x200 )
-        pRenderer->DrawTextureIndexedAlpha(pX_coord, pY_coord, SBPageCSpellsTextureList[v10]);
-      else
-        pRenderer->DrawTextureIndexed(pX_coord, pY_coord, SBPageCSpellsTextureList[v10]);
-    }
-  }
-  //pX_coord = (unsigned int)&player->pActiveSkills[PLAYER_SKILL_FIRE];
-  //pY_coord = (unsigned int)&player->pActiveSkills[PLAYER_SKILL_FIRE];
-  for ( uint i = 0; i < 9; i++ )
-  {
-    if ( player->pActiveSkills[PLAYER_SKILL_FIRE + i] )
-    {
-      if ( player->lastOpenedSpellbookPage == i )
-      {
-        pPageTexture = pTextures_tabs[i][1];
-        pX_coord = texture_tab_coord1[i][0];
-        pY_coord = texture_tab_coord1[i][1];
-      }
-      else
-      {
-        pPageTexture = pTextures_tabs[i][0];
-        pX_coord = texture_tab_coord0[i][0];
-        pY_coord = texture_tab_coord0[i][1];
-      }
-      pRenderer->DrawTextureIndexedAlpha(pX_coord, pY_coord, pPageTexture);
-    }
-  }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/UI/Spellbook.cpp	Tue May 12 11:07:32 2015 +0200
@@ -0,0 +1,321 @@
+#include "Engine/Engine.h"
+#include "Engine/Party.h"
+#include "Engine/LOD.h"
+#include "Engine/Timer.h"
+#include "Engine/texts.h"
+#include "Engine/Graphics/Render.h"
+#include "Engine/Graphics/Viewport.h"
+
+#include "IO/Mouse.h"
+
+#include "GUI/UI/Spellbook.h"
+#include "GUI/GUIFont.h"
+
+#include "Media/Audio/AudioPlayer.h"
+
+
+
+void InitializeSpellBookTextures();
+void OnCloseSpellBookPage();
+void OnCloseSpellBook();
+void LoadSpellbook(unsigned int spell_school);
+void BookUI_Spellbook_DrawCurrentSchoolBackground();
+
+
+std::array<char *, 9> spellbook_texture_filename_suffices = {{"f", "a", "w", "e", "s", "m", "b", "l", "d"}};
+
+std::array<std::array<unsigned char, 12>, 9> pSpellbookSpellIndices = // 4E2430    from pSpellbookSpellIndices[9][12]
+{
+    {  //0   1   2   3  4    5   6  7    8  9   10  11
+        { 0, 3, 1, 8, 11, 7, 4, 10, 6, 2, 5, 9 },
+        { 0, 11, 2, 9, 6, 8, 5, 10, 3, 7, 1, 4 },
+        { 0, 4, 8, 9, 1, 10, 3, 11, 7, 6, 2, 5 },
+        { 0, 7, 10, 8, 2, 11, 1, 5, 3, 6, 4, 9 },
+        { 0, 5, 10, 11, 7, 2, 8, 1, 4, 9, 3, 6 },
+        { 0, 5, 9, 8, 3, 7, 6, 4, 1, 11, 2, 10 },
+        { 0, 1, 6, 9, 3, 5, 8, 11, 7, 10, 4, 2 },
+        { 0, 1, 10, 11, 9, 4, 3, 6, 5, 7, 8, 2 },
+        { 0, 9, 3, 7, 1, 5, 2, 10, 11, 8, 6, 4 }
+    }
+};
+
+
+
+
+GUIWindow_Spellbook::GUIWindow_Spellbook() :
+    GUIWindow(0, 0, window->GetWidth(), window->GetHeight(), 0, nullptr)
+{
+// ------------------------------------
+// 004304E7 void Game_EventLoop -- part
+    current_screen_type = SCREEN_SPELL_BOOK;
+    pEventTimer->Pause();
+
+    InitializeSpellBookTextures();
+    OpenSpellbook();
+
+// ------------------------------------
+// 004304E7 void Game_EventLoop -- part
+    pAudioPlayer->PlaySound(SOUND_48, 0, 0, -1, 0, 0, 0, 0);
+    viewparams->field_48 = 1;
+}
+
+
+void GUIWindow_Spellbook::OpenSpellbookPage(int page)
+{
+// ------------------------------------
+// 004304E7 void Game_EventLoop -- part
+
+    OnCloseSpellBookPage();
+    pPlayers[uActiveCharacter]->lastOpenedSpellbookPage = page;
+    OpenSpellbook();
+    pAudioPlayer->PlaySound((SoundID)(SOUND_TurnPageU + rand() % 2), 0, 0, -1, 0, 0, 0, 0);
+}
+
+//----- (00411621) --------------------------------------------------------
+void GUIWindow_Spellbook::OpenSpellbook()
+{
+    Player *pPlayer; // edi@1
+    //GUIWindow *pWindow; // esi@1
+    //unsigned int v3; // ebp@1
+    int v4; // eax@3
+    ///GUIButton *result; // eax@25
+    int a2; // [sp+10h] [bp-8h]@1
+    //int v7; // [sp+14h] [bp-4h]@1
+
+    pPlayer = pPlayers[uActiveCharacter];
+    //pWindow = this;
+    LoadSpellbook(pPlayer->lastOpenedSpellbookPage);
+    //v3 = 0;
+    a2 = 0;
+
+    PlayerSpellbookChapter* chapter = &pPlayer->spellbook.pChapters[pPlayer->lastOpenedSpellbookPage];
+    for (uint i = 0; i < 11; ++i)
+    {
+        if (!chapter->bIsSpellAvailable[i])
+            continue;
+        v4 = pPlayer->lastOpenedSpellbookPage;
+        //v4 = (12 * pPlayer->lastOpenedSpellbookPage + pSpellbookSpellIndices[pPlayer->lastOpenedSpellbookPage][i + 1]);
+        CreateButton(pViewport->uViewportTL_X + pIconPos[v4][pSpellbookSpellIndices[v4][i + 1]].Xpos,
+            pViewport->uViewportTL_Y + pIconPos[v4][pSpellbookSpellIndices[v4][i + 1]].Ypos,  //dword_4E20D0
+            SBPageSSpellsTextureList[i + 1]->uTextureWidth,
+            SBPageSSpellsTextureList[i + 1]->uTextureHeight,
+            1, 79, UIMSG_SelectSpell, i, 0, "", 0);
+        ++a2;
+        //++v3;
+    }
+    //while ( (signed int)v3 < 11 );
+
+    CreateButton(0, 0, 0, 0, 1, 0, UIMSG_SpellBook_PressTab, 0, '\t', "", 0);
+    if (a2)
+        _41D08F_set_keyboard_control_group(a2, 0, 0, 0);
+
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_FIRE])   CreateButton(399, 10, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 0, 0, aSpellSchoolNames[0], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_AIR])    CreateButton(399, 46, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 1, 0, aSpellSchoolNames[1], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_WATER])  CreateButton(399, 83, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 2, 0, aSpellSchoolNames[2], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_EARTH])  CreateButton(399, 121, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 3, 0, aSpellSchoolNames[3], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_SPIRIT]) CreateButton(399, 158, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 4, 0, aSpellSchoolNames[4], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_MIND])   CreateButton(400, 196, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 5, 0, aSpellSchoolNames[5], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_BODY])   CreateButton(400, 234, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 6, 0, aSpellSchoolNames[6], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_LIGHT])  CreateButton(400, 271, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 7, 0, aSpellSchoolNames[7], 0);
+    if (pPlayer->pActiveSkills[PLAYER_SKILL_DARK])   CreateButton(400, 307, 50, 36, 1, 0, UIMSG_OpenSpellbookPage, 8, 0, aSpellSchoolNames[8], 0);
+
+    CreateButton(476, 450, pSBClickQuickSpellBtnTextr->uTextureWidth, pSBClickQuickSpellBtnTextr->uTextureHeight, 1, 78, UIMSG_ClickInstallRemoveQuickSpellBtn, 0, 0, "", 0);
+    pBtn_InstallRemoveSpell = CreateButton(476, 450, 48, 32, 1, 78, UIMSG_ClickInstallRemoveQuickSpellBtn, 0, 0, "", pSBClickQuickSpellBtnTextr, 0);
+    CreateButton(561, 450, pSpellBookClickCloseBtnTextr->uTextureWidth, pSpellBookClickCloseBtnTextr->uTextureHeight, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[79], 0);
+    pBtn_CloseBook = CreateButton(561, 450, 48, 32, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[79], pSpellBookClickCloseBtnTextr, 0);
+}
+
+void GUIWindow_Spellbook::Update()
+{
+// -----------------------------------
+// 004156F0 GUI_UpdateWindows --- part
+// {
+//     DrawSpellBookContent(pPlayers[uActiveCharacter]);
+// }
+//
+// --------------------------------------------------
+// 00412B58 void DrawSpellBookContent(Player *player)
+    auto player = pPlayers[uActiveCharacter];
+
+    Texture *PendingTexture; // edi@1
+    Texture *pTexture; // edx@5
+    int v10; // eax@13
+    unsigned int pX_coord; // esi@18
+    unsigned int pY_coord; // edi@18
+    Texture *pPageTexture; // eax@21
+    //  signed int v22; // [sp-4h] [bp-24h]@22
+    POINT a2; // [sp+18h] [bp-8h]@13
+
+    static unsigned int texture_tab_coord1[9][2] =
+    { { 406, 9 }, { 406, 46 }, { 406, 84 }, { 406, 121 }, { 407, 158 }, { 405, 196 }, { 405, 234 }, { 405, 272 }, { 405, 309 } };
+
+    static unsigned int texture_tab_coord0[9][2] =
+    { { 415, 10 }, { 415, 46 }, { 415, 83 }, { 415, 121 }, { 415, 158 }, { 416, 196 }, { 416, 234 }, { 416, 271 }, { 416, 307 } };
+
+    BookUI_Spellbook_DrawCurrentSchoolBackground();
+
+    PendingTexture = pIcons_LOD->GetTexture(pIcons_LOD->FindTextureByName("Pending"));
+    pRenderer->ClearZBuffer(0, 479);
+    if ((11 * player->lastOpenedSpellbookPage) || ((11 * player->lastOpenedSpellbookPage) + 11))//??? maybe structure need fix
+    {
+        for (uint i = 1; i <= 11; ++i)
+        {
+            if (player->_achieved_awards_bits[(11 * player->lastOpenedSpellbookPage) + i + 63])
+            {
+                if (SBPageSSpellsTextureList[i] != PendingTexture)
+                {
+                    if (quick_spell_at_page == i)
+                        pTexture = SBPageCSpellsTextureList[i];
+                    else
+                        pTexture = SBPageSSpellsTextureList[i];
+                    if (pTexture->pLevelOfDetail0_prolly_alpha_mask)
+                    {
+                        pX_coord = pViewport->uViewportTL_X + pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Xpos;
+                        pY_coord = pViewport->uViewportTL_Y + pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Ypos;
+                        if (pTexture->pBits & 0x200)
+                            pRenderer->DrawTextureIndexedAlpha(pX_coord, pY_coord, pTexture);
+                        else
+                            pRenderer->DrawTextureIndexed(pX_coord, pY_coord, pTexture);
+                        pRenderer->DrawMaskToZBuffer(pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Xpos,
+                            pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][i]].Ypos, pTexture, i);
+                    }
+                }
+            }
+        }
+    }
+
+    pMouse->GetCursorPos(&a2);
+    v10 = pRenderer->pActiveZBuffer[a2.x + pSRZBufferLineOffsets[a2.y]] & 0xFFFF;
+    if (v10)
+    {
+        if (SBPageCSpellsTextureList[v10]->pLevelOfDetail0_prolly_alpha_mask)
+        {
+            pX_coord = pViewport->uViewportTL_X + pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][v10]].Xpos;
+            pY_coord = pViewport->uViewportTL_Y + pIconPos[player->lastOpenedSpellbookPage][pSpellbookSpellIndices[player->lastOpenedSpellbookPage][v10]].Ypos;
+            if (SBPageCSpellsTextureList[v10]->pBits & 0x200)
+                pRenderer->DrawTextureIndexedAlpha(pX_coord, pY_coord, SBPageCSpellsTextureList[v10]);
+            else
+                pRenderer->DrawTextureIndexed(pX_coord, pY_coord, SBPageCSpellsTextureList[v10]);
+        }
+    }
+    //pX_coord = (unsigned int)&player->pActiveSkills[PLAYER_SKILL_FIRE];
+    //pY_coord = (unsigned int)&player->pActiveSkills[PLAYER_SKILL_FIRE];
+    for (uint i = 0; i < 9; i++)
+    {
+        if (player->pActiveSkills[PLAYER_SKILL_FIRE + i])
+        {
+            if (player->lastOpenedSpellbookPage == i)
+            {
+                pPageTexture = pTextures_tabs[i][1];
+                pX_coord = texture_tab_coord1[i][0];
+                pY_coord = texture_tab_coord1[i][1];
+            }
+            else
+            {
+                pPageTexture = pTextures_tabs[i][0];
+                pX_coord = texture_tab_coord0[i][0];
+                pY_coord = texture_tab_coord0[i][1];
+            }
+            pRenderer->DrawTextureIndexedAlpha(pX_coord, pY_coord, pPageTexture);
+        }
+    }
+}
+
+
+void GUIWindow_Spellbook::Release()
+{
+// -----------------------------------------
+// 0041C26A void GUIWindow::Release --- part
+    OnCloseSpellBookPage();
+    OnCloseSpellBook();
+
+    GUIWindow::Release();
+}
+
+
+//----- (00411300) --------------------------------------------------------
+void LoadSpellbook(unsigned int spell_school)
+{
+  char pContainer[20]; // [sp+Ch] [bp-1Ch]@7
+
+  byte_506550 = 0;
+  if ( pPlayers[uActiveCharacter]->uQuickSpell && (unsigned __int8)pPlayers[uActiveCharacter]->uQuickSpell / 11 == spell_school )
+    quick_spell_at_page = (unsigned __int8)pPlayers[uActiveCharacter]->uQuickSpell - 11 * spell_school;
+  else
+    quick_spell_at_page = 0;
+
+  for (uint i = 1; i <= 11; ++i)
+  {
+    if (pPlayers[uActiveCharacter]->spellbook.pChapters[spell_school].bIsSpellAvailable[i - 1])
+    {
+      sprintf(pContainer, "SB%sS%02d", spellbook_texture_filename_suffices[spell_school], pSpellbookSpellIndices[spell_school][i]);
+      SBPageSSpellsTextureList[i] = pIcons_LOD->LoadTexturePtr(pContainer, TEXTURE_16BIT_PALETTE);
+
+      sprintf(pContainer, "SB%sC%02d", spellbook_texture_filename_suffices[spell_school], pSpellbookSpellIndices[spell_school][i]);
+      SBPageCSpellsTextureList[i] = pIcons_LOD->LoadTexturePtr(pContainer, TEXTURE_16BIT_PALETTE);
+    }
+  }
+}
+
+//----- (00412AF9) --------------------------------------------------------
+static void BookUI_Spellbook_DrawCurrentSchoolBackground()
+{
+  int pTexID = 0;
+  if ( uActiveCharacter )
+    pTexID = pParty->pPlayers[uActiveCharacter - 1].lastOpenedSpellbookPage;
+  pRenderer->DrawTextureIndexed(8, 8, pSpellBookPagesTextr[pTexID]);
+  pRenderer->DrawTextureIndexed(476, 450, pSBQuickSpellBtnTextr);
+  pRenderer->DrawTextureIndexed(561, 450, pSpellBookCloseBtnTextr);
+}
+
+
+
+
+
+//----- (0041192C) --------------------------------------------------------
+void InitializeSpellBookTextures()
+{
+    pAudioPlayer->StopChannels(-1, -1);
+    ++pIcons_LOD->uTexturePacksCount;
+    if (!pIcons_LOD->uNumPrevLoadedFiles)
+        pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+    pAudioPlayer->PlaySound(SOUND_openbook, 0, 0, -1, 0, 0, 0, 0);
+    pSpellBookPagesTextr_9 = pIcons_LOD->LoadTexturePtr("book", TEXTURE_16BIT_PALETTE);
+    pTexture_pagemask = pIcons_LOD->LoadTexturePtr("pagemask", TEXTURE_16BIT_PALETTE);
+    pSpellBookCloseBtnTextr = pIcons_LOD->LoadTexturePtr("ib-m5-u", TEXTURE_16BIT_PALETTE);
+    pSpellBookClickCloseBtnTextr = pIcons_LOD->LoadTexturePtr("ib-m5-d", TEXTURE_16BIT_PALETTE);
+    pSBQuickSpellBtnTextr = pIcons_LOD->LoadTexturePtr("ib-m6-u", TEXTURE_16BIT_PALETTE);
+
+    static const char *texNames[9] = // 004E24EC
+    {
+        "SBFB00", "SBAB00", "SBWB00", "SBEB00",
+        "SBSB00", "SBMB00", "SBBB00", "SBLB00", "SBDB00"
+    };
+
+    pSBClickQuickSpellBtnTextr = pIcons_LOD->LoadTexturePtr("ib-m6-d", TEXTURE_16BIT_PALETTE);
+    for (uint i = 0; i < 9; ++i)
+    {
+        pSpellBookPagesTextr[i] = pIcons_LOD->LoadTexturePtr(texNames[i], TEXTURE_16BIT_PALETTE);
+        sprintf(pTmpBuf.data(), "tab%da", i + 1);
+        pTextures_tabs[i][0] = pIcons_LOD->LoadTexturePtr(pTmpBuf.data(), TEXTURE_16BIT_PALETTE);
+        sprintf(pTmpBuf.data(), "tab%db", i + 1);
+        pTextures_tabs[i][1] = pIcons_LOD->LoadTexturePtr(pTmpBuf.data(), TEXTURE_16BIT_PALETTE);
+    }
+}
+
+
+//----- (00411473) --------------------------------------------------------
+void OnCloseSpellBook()
+{
+    pTexture_pagemask->Release();
+    pSpellBookCloseBtnTextr->Release();
+    pSBQuickSpellBtnTextr->Release();
+    for (uint i = 0; i < 9; ++i)
+    {
+        pSpellBookPagesTextr[i]->Release();
+        pTextures_tabs[i][0]->Release();
+        pTextures_tabs[i][1]->Release();
+    }
+    pAudioPlayer->PlaySound(SOUND_openbook, 0, 0, -1, 0, 0, 0, 0);
+    pIcons_LOD->RemoveTexturesPackFromTextureList();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/UI/Spellbook.h	Tue May 12 11:07:32 2015 +0200
@@ -0,0 +1,14 @@
+#pragma once
+#include "GUI/GUIWindow.h"
+
+struct GUIWindow_Spellbook : public GUIWindow
+{
+             GUIWindow_Spellbook();
+    virtual ~GUIWindow_Spellbook() {}
+
+    virtual void Update();
+    virtual void Release();
+
+    void OpenSpellbook();
+    void OpenSpellbookPage(int page);
+};
\ No newline at end of file
--- a/GUI/UI/UIBooks.cpp	Tue May 12 03:24:19 2015 +0200
+++ b/GUI/UI/UIBooks.cpp	Tue May 12 11:07:32 2015 +0200
@@ -19,6 +19,8 @@
 //----- (00411597) --------------------------------------------------------
 void GUIWindow_Book::Release()
 {
+// -----------------------------------------
+// 0041C26A void GUIWindow::Release --- part
     free(pSpellFont);
     pSpellFont = nullptr;
     free(pBookFont);
@@ -71,36 +73,6 @@
     pSpellFont = LoadFont("spell.fnt", "FONTPAL", NULL);
 }
 
-//----- (0041192C) --------------------------------------------------------
-void InitializeSpellBookTextures()
-{
-  pAudioPlayer->StopChannels(-1, -1);
-  ++pIcons_LOD->uTexturePacksCount;
-  if ( !pIcons_LOD->uNumPrevLoadedFiles )
-    pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
-  pAudioPlayer->PlaySound(SOUND_openbook, 0, 0, -1, 0, 0, 0, 0);
-  pSpellBookPagesTextr_9 = pIcons_LOD->LoadTexturePtr("book", TEXTURE_16BIT_PALETTE);
-  pTexture_pagemask = pIcons_LOD->LoadTexturePtr("pagemask", TEXTURE_16BIT_PALETTE);
-  pSpellBookCloseBtnTextr = pIcons_LOD->LoadTexturePtr("ib-m5-u", TEXTURE_16BIT_PALETTE);
-  pSpellBookClickCloseBtnTextr = pIcons_LOD->LoadTexturePtr("ib-m5-d", TEXTURE_16BIT_PALETTE);
-  pSBQuickSpellBtnTextr   = pIcons_LOD->LoadTexturePtr("ib-m6-u",TEXTURE_16BIT_PALETTE);
-
-  static const char *texNames[9] = // 004E24EC
-  {
-    "SBFB00", "SBAB00", "SBWB00", "SBEB00",
-    "SBSB00", "SBMB00", "SBBB00", "SBLB00", "SBDB00"
-  };
-
-  pSBClickQuickSpellBtnTextr = pIcons_LOD->LoadTexturePtr("ib-m6-d",TEXTURE_16BIT_PALETTE);
-  for ( uint i = 0; i < 9; ++i )
-  {
-    pSpellBookPagesTextr[i] = pIcons_LOD->LoadTexturePtr(texNames[i], TEXTURE_16BIT_PALETTE);
-    sprintf(pTmpBuf.data(), "tab%da", i + 1);
-    pTextures_tabs[i][0] = pIcons_LOD->LoadTexturePtr(pTmpBuf.data(), TEXTURE_16BIT_PALETTE);
-    sprintf(pTmpBuf.data(), "tab%db", i + 1);
-    pTextures_tabs[i][1] = pIcons_LOD->LoadTexturePtr(pTmpBuf.data(), TEXTURE_16BIT_PALETTE);
-  }
-}
 
 //----- (0041140B) --------------------------------------------------------
 void OnCloseSpellBookPage()
@@ -126,19 +98,3 @@
   pGUIWindow_CurrentMenu->pControlsTail = 0;
   pGUIWindow_CurrentMenu->uNumControls = 0;
 }
-
-//----- (00411473) --------------------------------------------------------
-void OnCloseSpellBook()
-{
-  pTexture_pagemask->Release();
-  pSpellBookCloseBtnTextr->Release();
-  pSBQuickSpellBtnTextr->Release();
-  for ( uint i = 0; i < 9; ++i )
-  {
-    pSpellBookPagesTextr[i]->Release();
-    pTextures_tabs[i][0]->Release();
-    pTextures_tabs[i][1]->Release();
-  }
-  pAudioPlayer->PlaySound(SOUND_openbook, 0, 0, -1, 0, 0, 0, 0);
-  pIcons_LOD->RemoveTexturesPackFromTextureList();
-}
--- a/GUI/UI/UIBooks.h	Tue May 12 03:24:19 2015 +0200
+++ b/GUI/UI/UIBooks.h	Tue May 12 11:07:32 2015 +0200
@@ -1,8 +1,6 @@
 #pragma once
 #include "GUI/GUIWindow.h"
 
-extern std::array<std::array<unsigned char, 12>, 9> pSpellbookSpellIndices; // 4E2430   from pSpellbookSpellIndices[9][12]
-
 
 struct GUIWindow_Book : public GUIWindow
 {
@@ -16,4 +14,15 @@
 
     private:
         void InitializeFonts();
+};
+
+
+struct GUIWindow_BooksButtonOverlay : public GUIWindow
+{
+    GUIWindow_BooksButtonOverlay(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+        GUIWindow(x, y, width, height, button, hint)
+    {}
+    virtual ~GUIWindow_BooksButtonOverlay() {}
+
+    virtual void Update();
 };
\ No newline at end of file
--- a/GUI/UI/UIRest.cpp	Tue May 12 03:24:19 2015 +0200
+++ b/GUI/UI/UIRest.cpp	Tue May 12 11:07:32 2015 +0200
@@ -75,34 +75,41 @@
         --uRestUI_FoodRequiredToRest;
     if (uRestUI_FoodRequiredToRest < 1)
         uRestUI_FoodRequiredToRest = 1;
-    if (!_stricmp(pCurrentMapName, "d29.blv") && _449B57_test_bit(pParty->_quest_bits, 98))//Замок Хармондейл
+    if (!_stricmp(pCurrentMapName, "d29.blv") && _449B57_test_bit(pParty->_quest_bits, PARTY_QUEST_HARMONDALE_REBUILT)) // d29 = Harmondale / Замок Хармондейл
         uRestUI_FoodRequiredToRest = 0;
 
     ++pIcons_LOD->uTexturePacksCount;
     if (!pIcons_LOD->uNumPrevLoadedFiles)
         pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
 }
+
+
+
+
 //----- (0041F6C1) --------------------------------------------------------
-GUIWindow *RestUI_Load()
+GUIWindow_Rest::GUIWindow_Rest() :
+    GUIWindow(0, 0, window->GetWidth(), window->GetHeight(), 0, nullptr)
 {
-  _507CD4_RestUI_hourglass_anim_controller = 0;
-  uTextureID_RestUI_restmain = pIcons_LOD->LoadTexture("restmain", TEXTURE_16BIT_PALETTE);
-  uTextureID_RestUI_restb1 = pIcons_LOD->LoadTexture("restb1", TEXTURE_16BIT_PALETTE);
-  uTextureID_RestUI_restb2 = pIcons_LOD->LoadTexture("restb2", TEXTURE_16BIT_PALETTE);
-  uTextureID_RestUI_restb3 = pIcons_LOD->LoadTexture("restb3", TEXTURE_16BIT_PALETTE);
-  uTextureID_RestUI_restb4 = pIcons_LOD->LoadTexture("restb4", TEXTURE_16BIT_PALETTE);
-  uTextureID_RestUI_restexit = pIcons_LOD->LoadTexture("restexit", TEXTURE_16BIT_PALETTE);
+
+    PrepareToLoadRestUI();
+    current_screen_type = SCREEN_REST;
 
-  OutdoorLocation::LoadActualSkyFrame();
+    _507CD4_RestUI_hourglass_anim_controller = 0;
+    uTextureID_RestUI_restmain = pIcons_LOD->LoadTexture("restmain", TEXTURE_16BIT_PALETTE);
+    uTextureID_RestUI_restb1 = pIcons_LOD->LoadTexture("restb1", TEXTURE_16BIT_PALETTE);
+    uTextureID_RestUI_restb2 = pIcons_LOD->LoadTexture("restb2", TEXTURE_16BIT_PALETTE);
+    uTextureID_RestUI_restb3 = pIcons_LOD->LoadTexture("restb3", TEXTURE_16BIT_PALETTE);
+    uTextureID_RestUI_restb4 = pIcons_LOD->LoadTexture("restb4", TEXTURE_16BIT_PALETTE);
+    uTextureID_RestUI_restexit = pIcons_LOD->LoadTexture("restexit", TEXTURE_16BIT_PALETTE);
 
-  auto wnd = new GUIWindow_Rest(0, 0, window->GetWidth(), window->GetHeight());
-  pButton_RestUI_Exit =          wnd->CreateButton(280, 297, 154, 37, 1, 0, UIMSG_ExitRest, 0, 0, "", pIcons_LOD->GetTexture(uTextureID_RestUI_restexit), 0);
-  pButton_RestUI_Main =          wnd->CreateButton( 24, 154, 225, 37, 1, 0, UIMSG_Rest8Hour, 0, 'R', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb4), 0);
-  pButton_RestUI_WaitUntilDawn = wnd->CreateButton( 61, 232, 154, 33, 1, 0, UIMSG_AlreadyResting, 0, 'D', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb1), 0);
-  pButton_RestUI_Wait1Hour =     wnd->CreateButton( 61, 264, 154, 33, 1, 0, UIMSG_Wait1Hour, 0, 'H', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb2), 0);
-  pButton_RestUI_Wait5Minutes =  wnd->CreateButton( 61, 296, 154, 33, 1, 0, UIMSG_Wait5Minutes, 0, 'M', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb3), 0);
+    OutdoorLocation::LoadActualSkyFrame();
 
-  return wnd;
+    //auto wnd = new GUIWindow_Rest(0, 0, window->GetWidth(), window->GetHeight());
+    pButton_RestUI_Exit = CreateButton(280, 297, 154, 37, 1, 0, UIMSG_ExitRest, 0, 0, "", pIcons_LOD->GetTexture(uTextureID_RestUI_restexit), 0);
+    pButton_RestUI_Main = CreateButton(24, 154, 225, 37, 1, 0, UIMSG_Rest8Hour, 0, 'R', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb4), 0);
+    pButton_RestUI_WaitUntilDawn = CreateButton(61, 232, 154, 33, 1, 0, UIMSG_AlreadyResting, 0, 'D', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb1), 0);
+    pButton_RestUI_Wait1Hour = CreateButton(61, 264, 154, 33, 1, 0, UIMSG_Wait1Hour, 0, 'H', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb2), 0);
+    pButton_RestUI_Wait5Minutes = CreateButton(61, 296, 154, 33, 1, 0, UIMSG_Wait5Minutes, 0, 'M', "", pIcons_LOD->GetTexture(uTextureID_RestUI_restb3), 0);
 }
 
 
--- a/GUI/UI/UIRest.h	Tue May 12 03:24:19 2015 +0200
+++ b/GUI/UI/UIRest.h	Tue May 12 11:07:32 2015 +0200
@@ -4,9 +4,7 @@
 
 struct GUIWindow_Rest : public GUIWindow
 {
-    GUIWindow_Rest(unsigned int x, unsigned int y, unsigned int width, unsigned int height) :
-        GUIWindow(x, y, width, height, 0, nullptr)
-    {}
+             GUIWindow_Rest();
     virtual ~GUIWindow_Rest() {}
 
     virtual void Update();
--- a/GUI/UI/UITransition.cpp	Tue May 12 03:24:19 2015 +0200
+++ b/GUI/UI/UITransition.cpp	Tue May 12 11:07:32 2015 +0200
@@ -28,6 +28,8 @@
 
 void GUIWindow_Travel::Release()
 {
+// -----------------------------------------
+// 0041C26A void GUIWindow::Release --- part
     pTexture_outside->Release();
     pTexture_Dialogue_Background->Release();
     pIcons_LOD->SyncLoadedFilesCount();
@@ -38,6 +40,8 @@
 
 void GUIWindow_Transition::Release()
 {
+// -----------------------------------------
+// 0041C26A void GUIWindow::Release --- part
     //pVideoPlayer->Unload();
     pTexture_outside->Release();
     pTexture_Dialogue_Background->Release();
--- a/Game/Game.cpp	Tue May 12 03:24:19 2015 +0200
+++ b/Game/Game.cpp	Tue May 12 11:07:32 2015 +0200
@@ -41,6 +41,8 @@
 #include "GUI/UI/UIQuickReference.h"
 #include "GUI/UI/UISaveLoad.h"
 #include "GUI/UI/UIModal.h"
+#include "GUI/UI/UIRest.h"
+#include "GUI/UI/Spellbook.h"
 #include "GUI/UI/UIBooks.h"
 #include "GUI/UI/Books/LloydsBook.h"
 #include "GUI/UI/Books/TownPortalBook.h"
@@ -2149,9 +2151,7 @@
             case UIMSG_RentRoom:
                 _506F14_resting_stage = 2;
 
-                PrepareToLoadRestUI();
-                current_screen_type = SCREEN_REST;
-                pGUIWindow_CurrentMenu = RestUI_Load();
+                pGUIWindow_CurrentMenu = new GUIWindow_Rest();
 
                 v86 = 60 * (_494820_training_time(pParty->uCurrentHour) + 1) - pParty->uCurrentMinute;
                 _506F18_num_minutes_to_sleep = v86;
@@ -2192,9 +2192,7 @@
                 }
                 if (!(pParty->uFlags & 0x88))
                 {
-                    PrepareToLoadRestUI();
-                    current_screen_type = SCREEN_REST;
-                    pGUIWindow_CurrentMenu = RestUI_Load();
+                    pGUIWindow_CurrentMenu = new GUIWindow_Rest();
                     continue;
                 }
                 if (pParty->bTurnBasedModeOn == 1)
@@ -2368,20 +2366,14 @@
                         if (uAction >= skill_count)
                             uAction = 0;
                     }
-                    OnCloseSpellBookPage();
-                    pPlayers[uActiveCharacter]->lastOpenedSpellbookPage = LOBYTE(v217[uAction]);
-                    pGUIWindow_CurrentMenu->OpenSpellBook();
-                    pAudioPlayer->PlaySound((SoundID)(rand() % 2 + SOUND_TurnPageU), 0, 0, -1, 0, 0, 0, 0);
+                    ((GUIWindow_Spellbook *)pGUIWindow_CurrentMenu)->OpenSpellbookPage(v217[uAction]);
                 }
                 continue;
             }
             case UIMSG_OpenSpellbookPage:
                 if (pTurnEngine->turn_stage == TE_MOVEMENT || !uActiveCharacter || uMessageParam == pPlayers[uActiveCharacter]->lastOpenedSpellbookPage)
                     continue;
-                OnCloseSpellBookPage();
-                pPlayers[uActiveCharacter]->lastOpenedSpellbookPage = uMessageParam;
-                pGUIWindow_CurrentMenu->OpenSpellBook();
-                pAudioPlayer->PlaySound((SoundID)(rand() % 2 + SOUND_TurnPageU), 0, 0, -1, 0, 0, 0, 0);
+                ((GUIWindow_Spellbook *)pGUIWindow_CurrentMenu)->OpenSpellbookPage(uMessageParam);
                 continue;
             case UIMSG_SelectSpell:
             {
@@ -2448,11 +2440,7 @@
                         if (current_screen_type == SCREEN_GAME)
                         {
                             new OnButtonClick2(476, 450, 0, 0, (int)pBtn_CastSpell, 0);
-                            current_screen_type = SCREEN_SPELL_BOOK;
-                            pEventTimer->Pause();
-                            pGUIWindow_CurrentMenu = new GUIWindow_Spellbook(0, 0, window->GetWidth(), window->GetHeight(), 0, 0);
-                            pAudioPlayer->PlaySound(SOUND_48, 0, 0, -1, 0, 0, 0, 0);
-                            viewparams->field_48 = 1;
+                            pGUIWindow_CurrentMenu = new GUIWindow_Spellbook();
                             continue;
                         }
                         if (current_screen_type != SCREEN_REST && current_screen_type != SCREEN_CHARACTERS
@@ -2460,11 +2448,7 @@
                         {
                             pGUIWindow_CurrentMenu->Release();
                             new OnButtonClick2(476, 450, 0, 0, (int)pBtn_CastSpell, 0);
-                            current_screen_type = SCREEN_SPELL_BOOK;
-                            pEventTimer->Pause();
-                            pGUIWindow_CurrentMenu = new GUIWindow_Spellbook(0, 0, window->GetWidth(), window->GetHeight(), 0, 0);
-                            pAudioPlayer->PlaySound(SOUND_48, 0, 0, -1, 0, 0, 0, 0);
-                            viewparams->field_48 = 1;
+                            pGUIWindow_CurrentMenu = new GUIWindow_Spellbook();
                             continue;
                         }
                     }