changeset 2565:117c219bf913

Party, items and stuff are abstracted from savegame file representation
author a.parshin
date Wed, 20 May 2015 15:12:33 +0200
parents f9bdfe26d03d
children 30eb6dcac768 f2f2595fe308
files Build/Visual Studio 2013/World of Might and Magic.vcxproj Build/Visual Studio 2013/World of Might and Magic.vcxproj.filters Engine/Engine.cpp Engine/Objects/NPC.cpp Engine/Objects/NPC.h Engine/Objects/Player.h Engine/Party.cpp Engine/Party.h Engine/SaveLoad.cpp Engine/Serialization/LegacyImages.cpp Engine/Serialization/LegacyImages.h Game/CreateParty.cpp
diffstat 12 files changed, 1754 insertions(+), 205 deletions(-) [+]
line wrap: on
line diff
--- a/Build/Visual Studio 2013/World of Might and Magic.vcxproj	Wed May 20 00:56:07 2015 +0200
+++ b/Build/Visual Studio 2013/World of Might and Magic.vcxproj	Wed May 20 15:12:33 2015 +0200
@@ -137,6 +137,7 @@
     <ClCompile Include="..\..\Engine\Random.cpp" />
     <ClCompile Include="..\..\Engine\Registry.cpp" />
     <ClCompile Include="..\..\Engine\SaveLoad.cpp" />
+    <ClCompile Include="..\..\Engine\Serialization\LegacyImages.cpp" />
     <ClCompile Include="..\..\Engine\Spells\CastSpellInfo.cpp" />
     <ClCompile Include="..\..\Engine\Spells\Spells.cpp" />
     <ClCompile Include="..\..\Engine\stru298.cpp" />
@@ -314,6 +315,7 @@
     <ClInclude Include="..\..\Engine\Registry.h" />
     <ClInclude Include="..\..\Engine\resource.h" />
     <ClInclude Include="..\..\Engine\SaveLoad.h" />
+    <ClInclude Include="..\..\Engine\Serialization\LegacyImages.h" />
     <ClInclude Include="..\..\Engine\Spells\CastSpellInfo.h" />
     <ClInclude Include="..\..\Engine\Spells\Spells.h" />
     <ClInclude Include="..\..\Engine\stru123.h" />
--- a/Build/Visual Studio 2013/World of Might and Magic.vcxproj.filters	Wed May 20 00:56:07 2015 +0200
+++ b/Build/Visual Studio 2013/World of Might and Magic.vcxproj.filters	Wed May 20 15:12:33 2015 +0200
@@ -112,6 +112,9 @@
     <Filter Include="Game">
       <UniqueIdentifier>{23305bbc-fe74-4523-88b2-155ca91d86f3}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Engine\Serialization">
+      <UniqueIdentifier>{74f93afa-5a55-4c13-976b-a34e4c9aad04}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\lib\zlib\adler32.c">
@@ -610,6 +613,9 @@
     <ClCompile Include="..\..\Game\GameMenu.cpp">
       <Filter>Game</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\Engine\Serialization\LegacyImages.cpp">
+      <Filter>Engine\Serialization</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\lib\libavcodec\avcodec.h">
@@ -1387,6 +1393,9 @@
     <ClInclude Include="..\..\Game\GameMenu.h">
       <Filter>Game</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\Engine\Serialization\LegacyImages.h">
+      <Filter>Engine\Serialization</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\lib\OpenAL\lib\x86\avcodec-55.def">
--- a/Engine/Engine.cpp	Wed May 20 00:56:07 2015 +0200
+++ b/Engine/Engine.cpp	Wed May 20 15:12:33 2015 +0200
@@ -1836,9 +1836,11 @@
             }
             else if (GetCurrentMenuID() == MENU_NEWGAME)
             {
+                pOtherOverlayList->Reset();
                 if (!CreateParty_Loop())
                     break;
 
+                strcpy(pCurrentMapName, pStartingMapName);
                 bFlashQuestBook = true;
                 pMediaPlayer->PlayFullscreenMovie(MOVIE_Emerald, true);
                 SaveNewGame();
@@ -1876,7 +1878,7 @@
             {
                 pMouse->ChangeActivation(0);
                 pParty->Reset();
-                pParty->CreateDefaultParty(1);
+                pParty->CreateDefaultParty(true);
 
                 __debugbreak();
                 /*extern void CreateDefaultBLVLevel();
--- a/Engine/Objects/NPC.cpp	Wed May 20 00:56:07 2015 +0200
+++ b/Engine/Objects/NPC.cpp	Wed May 20 15:12:33 2015 +0200
@@ -381,7 +381,7 @@
 	}
 
 //----- (00476C60) --------------------------------------------------------
-void NPCStats::_476C60()
+void NPCStats::_476C60_on_load_game()
 	{
 	for (unsigned int i = 1; i < uNumNewNPCs; ++i)
 		pNewNPCData[i].pName = pNPCUnicNames[i - 1];
--- a/Engine/Objects/NPC.h	Wed May 20 00:56:07 2015 +0200
+++ b/Engine/Objects/NPC.h	Wed May 20 15:12:33 2015 +0200
@@ -160,7 +160,7 @@
   void Initialize();
   void Release();
   void InitializeAdditionalNPCs(NPCData *pNPCDataBuff, int npc_uid, int uLocation2D, int uMapId);
-  void _476C60();
+  void _476C60_on_load_game();
   char * sub_495366_MispronounceName(unsigned __int8 firstLetter, unsigned __int8 genderId);
 
   
--- a/Engine/Objects/Player.h	Wed May 20 00:56:07 2015 +0200
+++ b/Engine/Objects/Player.h	Wed May 20 15:12:33 2015 +0200
@@ -760,7 +760,7 @@
   };
   unsigned char _achieved_awards_bits[64];
   PlayerSpells spellbook;
-  char field__1F5[2]; // used to be [31]
+  char _1F6_padding[2];
   int pure_luck_used;      
   int pure_speed_used; 
   int pure_intellect_used;  
--- a/Engine/Party.cpp	Wed May 20 00:56:07 2015 +0200
+++ b/Engine/Party.cpp	Wed May 20 15:12:33 2015 +0200
@@ -272,7 +272,7 @@
 }
 
 //----- (0049137D) --------------------------------------------------------
-void Party::CreateDefaultParty(char bGiveItems)
+void Party::CreateDefaultParty(bool bDebugGiveItems)
 {
   Player *pCharacter; // esi@3
   int uSkillIdx; // eax@11
@@ -285,7 +285,7 @@
   this->hirelingScrollPosition = 0;
   memset(&pHirelings, 0, sizeof(pHirelings));
 
-  strcpy(this->pPlayers[0].pName, pGlobalTXT_LocalizationStrings[509]); //Zoltan
+  strcpy(this->pPlayers[0].pName, pGlobalTXT_LocalizationStrings[509]); // Zoltan
   this->pPlayers[0].uPrevFace = 17;
   this->pPlayers[0].uCurrentFace = 17;
   this->pPlayers[0].uPrevVoiceID = 17;
@@ -297,15 +297,16 @@
   this->pPlayers[0].uAccuracy = 13;
   this->pPlayers[0].uSpeed = 14;
   this->pPlayers[0].uLuck = 7;
-  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;         // leather
-  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_ARMSMASTER] = 1;        // armsmaster
-  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_BOW] = 1;         // bow
-  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_SWORD] = 1;         // sword
+  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;
+  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_ARMSMASTER] = 1;
+  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_BOW] = 1;
+  this->pPlayers[0].pActiveSkills[PLAYER_SKILL_SWORD] = 1;
+
+  strcpy(this->pPlayers[1].pName, pGlobalTXT_LocalizationStrings[506]); // Roderic
   this->pPlayers[1].uPrevFace = 3;
   this->pPlayers[1].uCurrentFace = 3;
   this->pPlayers[1].uPrevVoiceID = 3;
   this->pPlayers[1].uVoiceID = 3;
-  strcpy(this->pPlayers[1].pName, pGlobalTXT_LocalizationStrings[506]); //Roderic
   this->pPlayers[1].uMight = 13;
   this->pPlayers[1].uIntelligence = 9;
   this->pPlayers[1].uWillpower = 9;
@@ -313,15 +314,16 @@
   this->pPlayers[1].uAccuracy = 13;
   this->pPlayers[1].uSpeed = 13;
   this->pPlayers[1].uLuck = 13;
-  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;         // leather
-  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_STEALING] = 1;        // stealing
-  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_DAGGER] = 1;         // dagger
-  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_TRAP_DISARM] = 1;        // disarm trap
+  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;
+  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_STEALING] = 1;
+  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_DAGGER] = 1;
+  this->pPlayers[1].pActiveSkills[PLAYER_SKILL_TRAP_DISARM] = 1;
+
+  strcpy(this->pPlayers[2].pName, pGlobalTXT_LocalizationStrings[508]); // Serena
   this->pPlayers[2].uPrevFace = 14;
   this->pPlayers[2].uCurrentFace = 14;
   this->pPlayers[2].uPrevVoiceID = 14;
   this->pPlayers[2].uVoiceID = 14;
-  strcpy(this->pPlayers[2].pName, pGlobalTXT_LocalizationStrings[508]); // Serena
   this->pPlayers[2].uMight = 12;
   this->pPlayers[2].uIntelligence = 9;
   this->pPlayers[2].uWillpower = 20;
@@ -329,10 +331,11 @@
   this->pPlayers[2].uAccuracy = 7;
   this->pPlayers[2].uSpeed = 13;
   this->pPlayers[2].uLuck = 7;
-  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_ALCHEMY] = 1;        // alchemy
-  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;         // leather
-  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_BODY] = 1;        // body
-  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_MACE] = 1;         // mace
+  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_ALCHEMY] = 1;
+  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_LEATHER] = 1;
+  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_BODY] = 1;
+  this->pPlayers[2].pActiveSkills[PLAYER_SKILL_MACE] = 1;
+
   strcpy(this->pPlayers[3].pName, pGlobalTXT_LocalizationStrings[507]); // Alexis
   this->pPlayers[3].uPrevFace = 10;
   this->pPlayers[3].uCurrentFace = 10;
@@ -349,24 +352,29 @@
   this->pPlayers[3].pActiveSkills[PLAYER_SKILL_AIR] = 1;        // air
   this->pPlayers[3].pActiveSkills[PLAYER_SKILL_FIRE] = 1;        // fire
   this->pPlayers[3].pActiveSkills[PLAYER_SKILL_STAFF] = 1;         // staff
+
   for (uNumPlayers = 0; uNumPlayers < 4; uNumPlayers++)
   {
     pCharacter = &pParty->pPlayers[uNumPlayers];
+
     if (pCharacter->classType == PLAYER_CLASS_KNIGHT)
-      pCharacter->sResMagicBase = 10; //player[i].pResMagicBase
+      pCharacter->sResMagicBase = 10;
+
     pCharacter->lastOpenedSpellbookPage = 0;
     for (int i = 0; i < 9; i++)//for Magic Book
     {
-	    if (pPlayers[uNumPlayers].pActiveSkills[12+i])
+	  if (pPlayers[uNumPlayers].pActiveSkills[12+i])
       {
         pCharacter->lastOpenedSpellbookPage = i;
         break;
       }
     }
+
     pCharacter->uExpressionTimePassed = 0;
-    Dst.Reset();
-    if ( bGiveItems )
+
+    if (bDebugGiveItems)
     {
+        Dst.Reset();
       pItemsTable->GenerateItem(2, 40, &Dst); //ring
       pCharacter->AddItem2(-1, &Dst);
 	    for (uSkillIdx = 0; uSkillIdx < 36; uSkillIdx++)
@@ -457,13 +465,14 @@
           pCharacter->pInventoryItemList[i].SetIdentified();
       }
     }
+
     pCharacter->sHealth = pCharacter->GetMaxHealth();
     pCharacter->sMana = pCharacter->GetMaxMana();
   }
 }
 
 //----- (004917CE) --------------------------------------------------------
-int Party::Reset()
+void Party::Reset()
 {  
   Zero();
 
@@ -472,11 +481,13 @@
   uNumGold = 200;
   uNumFoodRations = 7;
 
-  
   alignment = PartyAlignment_Neutral;
   SetUserInterface(alignment, true);
 
-  uTimePlayed = 0x21C00u;
+  // 0x21C00 = 138240
+  // 138240 x 0.234375 = 32400
+  // 32400 / 60 / 60 = 9 am
+  uTimePlayed = 0x21C00;
   uLastRegenerationTime = 0x21C00;
 
   bTurnBasedModeOn = false;
@@ -487,9 +498,6 @@
     ::pPlayers[i + 1] = &pPlayers[i];
 
   pPlayers[0].Reset(PLAYER_CLASS_KNIGHT);
-  pPlayers[1].Reset(PLAYER_CLASS_THEIF);
-  pPlayers[2].Reset(PLAYER_CLASS_CLERIC);
-  pPlayers[3].Reset(PLAYER_CLASS_SORCERER);
   pPlayers[0].uCurrentFace = 17;
   pPlayers[0].uPrevVoiceID = 17;
   pPlayers[0].uVoiceID = 17;
@@ -500,6 +508,7 @@
   strcpy(pPlayers[0].pName, pGlobalTXT_LocalizationStrings[509]);
 
 
+  pPlayers[1].Reset(PLAYER_CLASS_THEIF);
   pPlayers[1].uCurrentFace = 3;
   pPlayers[1].uPrevVoiceID = 3;
   pPlayers[1].uVoiceID = 3;
@@ -507,6 +516,8 @@
   pPlayers[1].uSex = pPlayers[1].GetSexByVoice();
   pPlayers[1].RandomizeName();
   strcpy(pPlayers[1].pName, pGlobalTXT_LocalizationStrings[506]);
+
+  pPlayers[2].Reset(PLAYER_CLASS_CLERIC);
   pPlayers[2].uCurrentFace = 14;
   pPlayers[2].uPrevVoiceID = 14;
   pPlayers[2].uVoiceID = 14;
@@ -514,6 +525,8 @@
   pPlayers[2].uSex = pPlayers[3].GetSexByVoice();
   pPlayers[2].RandomizeName();
   strcpy(pPlayers[2].pName, pGlobalTXT_LocalizationStrings[508]);
+
+  pPlayers[3].Reset(PLAYER_CLASS_SORCERER);
   pPlayers[3].uCurrentFace = 10;
   pPlayers[3].uPrevVoiceID = 10;
   pPlayers[3].uVoiceID = 10;
@@ -539,18 +552,11 @@
   for (uint i = 1; i < 20; ++i)
     pPartyBuffs[i].Reset();
 
-
   current_character_screen_window = WINDOW_CharacterWindow_Stats;  // default character ui - stats
   uFlags = 0;
   memset(_autonote_bits, 0, sizeof(_autonote_bits));
   memset(_quest_bits, 0, sizeof(_quest_bits));
   pIsArtifactFound.fill(0);
-  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_RED_POTION_ACTIVE, 1);
-  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_SEASHELL_ACTIVE, 1);
-  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_LONGBOW_ACTIVE, 1);
-  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_PLATE_ACTIVE, 1);
-  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_LUTE_ACTIVE, 1);
-  _449B7E_toggle_bit(_quest_bits, PARTY_QUEST_EMERALD_HAT_ACTIVE, 1);
 
   PartyTimes._shop_ban_times.fill(0);
 
@@ -559,7 +565,6 @@
   pNPCStats->pNewNPCData[3].uFlags |= 128;//|= 0x80u; Lady Margaret
   _494035_timed_effects__water_walking_damage__etc();
   pEventTimer->Pause();
-  return 0;
 }
 
 
--- a/Engine/Party.h	Wed May 20 00:56:07 2015 +0200
+++ b/Engine/Party.h	Wed May 20 15:12:33 2015 +0200
@@ -181,8 +181,8 @@
   void UpdatePlayersAndHirelingsEmotions();
   void RestAndHeal();
   unsigned int GetPartyFame();
-  void CreateDefaultParty(char bGiveItems);
-  int Reset();
+  void CreateDefaultParty(bool bDebugGiveItems = false);
+  void Reset();
   void ResetPosMiscAndSpellBuffs();
   bool HasItem(unsigned int uItemID);
   void SetHoldingItem(ItemGen *pItem);
--- a/Engine/SaveLoad.cpp	Wed May 20 00:56:07 2015 +0200
+++ b/Engine/SaveLoad.cpp	Wed May 20 15:12:33 2015 +0200
@@ -1,30 +1,31 @@
 #define _CRTDBG_MAP_ALLOC
+#define _CRT_SECURE_NO_WARNINGS
 #include <stdlib.h>
 #include <crtdbg.h>
-
-#define _CRT_SECURE_NO_WARNINGS
 #include <io.h>
 #include <direct.h>
 
 #include "Engine/Engine.h"
-
-#include "ZlibWrapper.h"
-#include "SaveLoad.h"
-#include "Party.h"
-#include "LOD.h"
+#include "Engine/texts.h"
+#include "Engine/ZlibWrapper.h"
+#include "Engine/SaveLoad.h"
+#include "Engine/Party.h"
+#include "Engine/LOD.h"
+#include "Engine/Timer.h"
+#include "Engine/stru123.h"
 #include "Engine/Graphics/Outdoor.h"
-#include "Media/Audio/AudioPlayer.h"
+#include "Engine/Graphics/Overlays.h"
+#include "Engine/Graphics/Viewport.h"
+#include "Engine/Graphics/Level/Decoration.h"
 #include "Engine/Objects/Actor.h"
 #include "Engine/Objects/Chest.h"
-#include "Timer.h"
+#include "Engine/Objects/SpriteObject.h"
+#include "Engine/Serialization/LegacyImages.h"
+
 #include "GUI/GUIWindow.h"
 #include "GUI/GUIFont.h"
-#include "Engine/Graphics/Overlays.h"
-#include "Engine/Objects/SpriteObject.h"
-#include "Engine/Graphics/Viewport.h"
-#include "stru123.h"
-#include "texts.h"
-#include "Engine/Graphics/Level/Decoration.h"
+
+#include "Media/Audio/AudioPlayer.h"
 
 #include "MMT.h"
 
@@ -36,6 +37,8 @@
 std::array<struct RGBTexture, 45> pSavegameThumbnails;
 std::array<SavegameHeader, 45> pSavegameHeader;
 
+
+
 //----- (0045EE8A) --------------------------------------------------------
 void __fastcall LoadGame(unsigned int uSlot)
 {
@@ -94,51 +97,76 @@
   Assert(sizeof(SavegameHeader) == 100);
   fread(&header, sizeof(SavegameHeader), 1, file);
 
-  file = pNew_LOD->FindContainer("party.bin", 1);
-  if (!file)
   {
-    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 101);//Сохраненная игра повреждена! Code=%d
-    Log::Warning(L"%S", Str);
-    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:559", 0);
+      file = pNew_LOD->FindContainer("party.bin", 1);
+      if (!file)
+      {
+          sprintf(Str, pGlobalTXT_LocalizationStrings[612], 101);//Сохраненная игра повреждена! Code=%d
+          Log::Warning(L"%S", Str);
+          MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:559", 0);
+      }
+      else
+      {
+          Party_Image_MM7 serialization;
+          fread(&serialization, sizeof(serialization), 1, file);
+
+          serialization.Deserialize(pParty);
+      }
   }
-  if (sizeof(Party) != 0x16238)
-    Log::Warning(L"class Party: deserialization warning");
-  fread(pParty, sizeof(Party), 1, file);
 
+    {
+        file = pNew_LOD->FindContainer("clock.bin", 1);
+        if (!file)
+        {
+            sprintf(Str, pGlobalTXT_LocalizationStrings[612], 102);//Сохраненная игра повреждена! Code=%d
+            Log::Warning(L"%S", Str);
+            MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:569", 0);
+        }
+        else
+        {
+            Timer_Image_MM7 serialization;
+            fread(&serialization, sizeof(serialization), 1, file);
 
-  file = pNew_LOD->FindContainer("clock.bin", 1);
-  if (!file)
-  {
-    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 102);//Сохраненная игра повреждена! Code=%d
-    Log::Warning(L"%S", Str);
-    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:569", 0);
-  }
-  if (sizeof(Timer) != 0x28)
-    Log::Warning(L"class Timer: deserialization warning");
-  fread(pEventTimer, sizeof(Timer), 1, file);
+            serialization.Deserialize(pEventTimer);
+        }
+    }
 
-  file = pNew_LOD->FindContainer("overlay.bin", 1);
-  if (!file)
-  {
-    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 103);//Сохраненная игра повреждена! Code=%d
-    Log::Warning(L"%S", Str);
-    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:579", 0);
-  }
-  if (sizeof(OtherOverlayList) != 0x3F0)
-    Log::Warning(L"class OtherOverlayList: deserialization warning");
-  fread(pOtherOverlayList, sizeof(OtherOverlayList), 1, file);
+    {
+        file = pNew_LOD->FindContainer("overlay.bin", 1);
+        if (!file)
+        {
+            sprintf(Str, pGlobalTXT_LocalizationStrings[612], 103);//Сохраненная игра повреждена! Code=%d
+            Log::Warning(L"%S", Str);
+            MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:579", 0);
+        }
+        else
+        {
+            OtherOverlayList_Image_MM7 serialization;
+            fread(&serialization, sizeof(serialization), 1, file);
+
+            serialization.Deserialize(pOtherOverlayList);
+        }
+    }
 
-  file = pNew_LOD->FindContainer("npcdata.bin", 0);
-  if (!file)
-  {
-    sprintf(Str, pGlobalTXT_LocalizationStrings[612], 104);//Сохраненная игра повреждена! Code=%d
-    Log::Warning(L"%S", Str);
-    MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:590", 0);
-  }
-  if (sizeof(pNPCStats->pNewNPCData) != 0x94BC)
-    Log::Warning(L"NPCStats: deserialization warning");
-  fread(pNPCStats->pNewNPCData, sizeof(pNPCStats->pNewNPCData), 1, file);
-  pNPCStats->_476C60();
+    {
+        file = pNew_LOD->FindContainer("npcdata.bin", 0);
+        if (!file)
+        {
+            sprintf(Str, pGlobalTXT_LocalizationStrings[612], 104);//Сохраненная игра повреждена! Code=%d
+            Log::Warning(L"%S", Str);
+            MessageBoxA(nullptr, Str, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:590", 0);
+        }
+        else
+        {
+            NPCData_Image_MM7 serialization[501];
+            fread(serialization, sizeof(serialization), 1, file);
+
+            for (unsigned int i = 0; i < 501; ++i)
+                serialization[i].Deserialize(pNPCStats->pNewNPCData + i);
+
+            pNPCStats->_476C60_on_load_game();
+        }
+    }
 
   file = pNew_LOD->FindContainer("npcgroup.bin", 0);
   if (!file)
@@ -219,121 +247,147 @@
 }
 
 //----- (0045F469) --------------------------------------------------------
-void SaveGame( bool IsAutoSAve, bool NotSaveWorld )
+void SaveGame(bool IsAutoSAve, bool NotSaveWorld)
 {
-  int text_pos; // eax@6
-  FILE *pLLoidFile; // edi@24
-  char* compressed_buf; // edi@30
-  char *data_write_pos; // esi@41
-  CHAR Buffer[128]; // [sp+Ch] [bp-264h]@59
-  char Dir[255]; // [sp+8Ch] [bp-1E4h]@51
-  char Drive[255]; // [sp+ACh] [bp-1C4h]@51
-  SavegameHeader save_header; // [sp+CCh] [bp-1A4h]@10
-  char Filename[255]; // [sp+130h] [bp-140h]@51
-  char Ext[255]; // [sp+150h] [bp-120h]@51
-  char Source[32]; // [sp+170h] [bp-100h]@51
-  char work_string[120]; // [sp+190h] [bp-E0h]@8
-  int pPositionY; // [sp+208h] [bp-68h]@2
-  int pPositionX; // [sp+20Ch] [bp-64h]@2
-  int sPRotationY; // [sp+210h] [bp-60h]@2
-  int sPRotationX; // [sp+214h] [bp-5Ch]@2
-  ODMHeader odm_data; // [sp+218h] [bp-58h]@30
-  int res; // [sp+224h] [bp-4Ch]@30
-  int pPositionZ; // [sp+228h] [bp-48h]@2
-  size_t Size; // [sp+250h] [bp-20h]@26
-  char *uncompressed_buff; // [sp+258h] [bp-18h]@2
-  unsigned int compressed_block_size; // [sp+260h] [bp-10h]@23
- 
-  //v66 = a2;
-  strcpy(byte_6BE3B0.data(), pCurrentMapName);//byte_6BE3B0 - save_map_name
-  if (!_stricmp(pCurrentMapName, "d05.blv")) // arena
-    return;
+    int text_pos; // eax@6
+    FILE *pLLoidFile; // edi@24
+    char* compressed_buf; // edi@30
+    char *data_write_pos; // esi@41
+    CHAR Buffer[128]; // [sp+Ch] [bp-264h]@59
+    char Dir[255]; // [sp+8Ch] [bp-1E4h]@51
+    char Drive[255]; // [sp+ACh] [bp-1C4h]@51
+    SavegameHeader save_header; // [sp+CCh] [bp-1A4h]@10
+    char Filename[255]; // [sp+130h] [bp-140h]@51
+    char Ext[255]; // [sp+150h] [bp-120h]@51
+    char Source[32]; // [sp+170h] [bp-100h]@51
+    char work_string[120]; // [sp+190h] [bp-E0h]@8
+    int pPositionY; // [sp+208h] [bp-68h]@2
+    int pPositionX; // [sp+20Ch] [bp-64h]@2
+    int sPRotationY; // [sp+210h] [bp-60h]@2
+    int sPRotationX; // [sp+214h] [bp-5Ch]@2
+    ODMHeader odm_data; // [sp+218h] [bp-58h]@30
+    int res; // [sp+224h] [bp-4Ch]@30
+    int pPositionZ; // [sp+228h] [bp-48h]@2
+    size_t Size; // [sp+250h] [bp-20h]@26
+    char *uncompressed_buff; // [sp+258h] [bp-18h]@2
+    unsigned int compressed_block_size; // [sp+260h] [bp-10h]@23
+
+    //v66 = a2;
+    strcpy(byte_6BE3B0.data(), pCurrentMapName);//byte_6BE3B0 - save_map_name
+    if (!_stricmp(pCurrentMapName, "d05.blv")) // arena
+        return;
+
+    uncompressed_buff = (char*)malloc(1000000);
 
-  uncompressed_buff = (char*)malloc(1000000);
+    LOD::Directory pLodDirectory; // [sp+22Ch] [bp-44h]@2
+    pPositionX = pParty->vPosition.x;
+    pPositionY = pParty->vPosition.y;
+    pPositionZ = pParty->vPosition.z;
+    sPRotationY = pParty->sRotationY;
+    sPRotationX = pParty->sRotationX;
+    pParty->vPosition.x = pParty->vPrevPosition.x;
+    pParty->vPosition.z = pParty->vPrevPosition.z;
+    pParty->vPosition.y = pParty->vPrevPosition.y;
 
-  LOD::Directory pLodDirectory; // [sp+22Ch] [bp-44h]@2
-  pPositionX = pParty->vPosition.x;
-  pPositionY = pParty->vPosition.y;
-  pPositionZ = pParty->vPosition.z;
-  sPRotationY = pParty->sRotationY;
-  sPRotationX = pParty->sRotationX;
-  pParty->vPosition.x = pParty->vPrevPosition.x;
-  pParty->vPosition.z = pParty->vPrevPosition.z;
-  pParty->vPosition.y = pParty->vPrevPosition.y;
+    pParty->uFallStartY = pParty->vPrevPosition.z;
 
-  pParty->uFallStartY = pParty->vPrevPosition.z;
+    pParty->sRotationY = pParty->sPrevRotationY;
+    pParty->sRotationX = pParty->sPrevRotationX;
+    if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+        pIndoor->stru1.uLastVisitDay = pParty->uTimePlayed;
+    else
+        pOutdoor->loc_time.uLastVisitDay = pParty->uTimePlayed;
+
+    pRenderer->PackScreenshot(150, 112, uncompressed_buff, 1000000, &pLodDirectory.uDataSize);//создание скриншота
+    strcpy(pLodDirectory.pFilename, "image.pcx");
 
-  pParty->sRotationY = pParty->sPrevRotationY;
-  pParty->sRotationX = pParty->sPrevRotationX;
-  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
-    pIndoor->stru1.uLastVisitDay = pParty->uTimePlayed;
-  else
-    pOutdoor->loc_time.uLastVisitDay = pParty->uTimePlayed;
-
-  pRenderer->PackScreenshot(150, 112, uncompressed_buff, 1000000, &pLodDirectory.uDataSize);//создание скриншота
-  strcpy(pLodDirectory.pFilename, "image.pcx");
+    if (current_screen_type == SCREEN_SAVEGAME)
+    {
+        pRenderer->DrawTextureIndexed(8, 8, pIcons_LOD->GetTexture(uTextureID_loadsave));
+        pRenderer->DrawTextureIndexed(18, 141, pIcons_LOD->GetTexture(uTextureID_save_up));
+        text_pos = pFontSmallnum->AlignText_Center(186, pGlobalTXT_LocalizationStrings[190]);
+        pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, text_pos + 25, 219, 0, pGlobalTXT_LocalizationStrings[190], 0, 0, 0); //Сохранение
+        text_pos = pFontSmallnum->AlignText_Center(186, pSavegameHeader[uLoadGameUI_SelectedSlot].pName);
+        pGUIWindow_CurrentMenu->DrawTextInRect(pFontSmallnum, text_pos + 25, 259, 0, pSavegameHeader[uLoadGameUI_SelectedSlot].pName, 185, 0);
+        text_pos = pFontSmallnum->AlignText_Center(186, pGlobalTXT_LocalizationStrings[165]);
+        pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, text_pos + 25, 299, 0, pGlobalTXT_LocalizationStrings[165], 0, 0, 0); //Пожалуйста, подождите
+        pRenderer->Present();
+    }
 
-  if (current_screen_type == SCREEN_SAVEGAME)
-  {
-    pRenderer->DrawTextureIndexed(8, 8, pIcons_LOD->GetTexture(uTextureID_loadsave));
-    pRenderer->DrawTextureIndexed(18, 141, pIcons_LOD->GetTexture(uTextureID_save_up));
-    text_pos = pFontSmallnum->AlignText_Center(186, pGlobalTXT_LocalizationStrings[190]);
-    pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, text_pos + 25, 219, 0, pGlobalTXT_LocalizationStrings[190], 0, 0, 0); //Сохранение
-    text_pos  = pFontSmallnum->AlignText_Center(186, pSavegameHeader[uLoadGameUI_SelectedSlot].pName);
-    pGUIWindow_CurrentMenu->DrawTextInRect(pFontSmallnum, text_pos  + 25, 259, 0, pSavegameHeader[uLoadGameUI_SelectedSlot].pName, 185, 0);
-    text_pos  = pFontSmallnum->AlignText_Center(186, pGlobalTXT_LocalizationStrings[165]);
-    pGUIWindow_CurrentMenu->DrawText(pFontSmallnum, text_pos  + 25, 299, 0, pGlobalTXT_LocalizationStrings[165], 0, 0, 0); //Пожалуйста, подождите
-    pRenderer->Present();
-  }
+    if (pNew_LOD->Write(&pLodDirectory, uncompressed_buff, 0))
+    {
+        sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 200); //Сохраненная игра повреждена! Code=%d
+        MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:773", 0);
+    }
 
-  if (pNew_LOD->Write(&pLodDirectory, uncompressed_buff, 0))
-  {
-    sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 200); //Сохраненная игра повреждена! Code=%d
-    MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:773", 0);
-  }
+    Assert(sizeof(SavegameHeader) == 100);
+    memset(save_header.pName, 0, 20);
+    memset(save_header.pLocationName, 0, 20);
+    memset(save_header.field_30, 0, 52);
+    strcpy(save_header.pLocationName, pCurrentMapName);
+    save_header.uWordTime = pParty->uTimePlayed;
+    strcpy(pLodDirectory.pFilename, "header.bin");
+    pLodDirectory.uDataSize = sizeof(SavegameHeader);
+    if (pNew_LOD->Write(&pLodDirectory, &save_header, 0))
+    {
+        sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 201);
+        MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:784", 0);
+    }
+
+
+    {
+        Party_Image_MM7 serialization;
+        serialization.Serialize(pParty);
+
+        pLodDirectory.uDataSize = sizeof(serialization);
+        strcpy(pLodDirectory.pFilename, "party.bin");
+        if (pNew_LOD->Write(&pLodDirectory, &serialization, 0))
+        {
+            sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 202);//Save game corrupted!  Code=%d
+            MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:793", 0);
+        }
+    }
 
-  Assert(sizeof(SavegameHeader) == 100);
-  memset(save_header.pName, 0, 20);
-  memset(save_header.pLocationName, 0, 20);
-  memset(save_header.field_30, 0, 52);
-  strcpy(save_header.pLocationName, pCurrentMapName);
-  save_header.uWordTime = pParty->uTimePlayed;
-  strcpy(pLodDirectory.pFilename, "header.bin");
-  pLodDirectory.uDataSize = sizeof(SavegameHeader);
-  if (pNew_LOD->Write(&pLodDirectory, &save_header, 0))
-  {
-    sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 201);
-    MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:784", 0);
-  }
-  strcpy(pLodDirectory.pFilename, "party.bin");
-  pLodDirectory.uDataSize = sizeof(Party); //90680;
-  if ( pNew_LOD->Write(&pLodDirectory, pParty, 0) )
-  {
-    sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 202);//Save game corrupted!  Code=%d
-    MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:793", 0);
-  }
-  strcpy(pLodDirectory.pFilename, "clock.bin");
-  pLodDirectory.uDataSize =sizeof(Timer);// 40;
-  if ( pNew_LOD->Write(&pLodDirectory, pEventTimer, 0) )
-  {
-    sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 203);
-    MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:802", 0);
-  }
-  strcpy(pLodDirectory.pFilename, "overlay.bin");
-  pLodDirectory.uDataSize =sizeof(OtherOverlayList);// 1008;
-  if ( pNew_LOD->Write(&pLodDirectory, pOtherOverlayList, 0) )
-  {
-    sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 204);
-    MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:811", 0);
-  }
-  strcpy(pLodDirectory.pFilename, "npcdata.bin");
-  pLodDirectory.uDataSize = 501 * sizeof(NPCData);
-  Assert(pLodDirectory.uDataSize == 38076);
-  if ( pNew_LOD->Write(&pLodDirectory, pNPCStats->pNewNPCData, 0) )
-  {
-    sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 205);
-    MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:820", 0);
-  }
+    {
+        Timer_Image_MM7 serialization;
+        serialization.Serialize(pEventTimer);
+
+        pLodDirectory.uDataSize = sizeof(serialization);
+        strcpy(pLodDirectory.pFilename, "clock.bin");
+        if (pNew_LOD->Write(&pLodDirectory, &serialization, 0))
+        {
+            sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 203);
+            MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:802", 0);
+        }
+    }
+
+    {
+        OtherOverlayList_Image_MM7 serialization;
+        serialization.Serialize(pOtherOverlayList);
+
+        pLodDirectory.uDataSize = sizeof(serialization);
+        strcpy(pLodDirectory.pFilename, "overlay.bin");
+        if (pNew_LOD->Write(&pLodDirectory, &serialization, 0))
+        {
+            sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 204);
+            MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:811", 0);
+        }
+    }
+
+    {
+        NPCData_Image_MM7 serialization[501];
+        for (unsigned int i = 0; i < 501; ++i)
+            serialization[i].Serialize(pNPCStats->pNewNPCData + i);
+
+        pLodDirectory.uDataSize = sizeof(serialization);
+        strcpy(pLodDirectory.pFilename, "npcdata.bin");
+        if (pNew_LOD->Write(&pLodDirectory, serialization, 0))
+        {
+            sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 205);
+            MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:820", 0);
+        }
+    }
+
   strcpy(pLodDirectory.pFilename, "npcgroup.bin");
   pLodDirectory.uDataSize = 102;
   if ( pNew_LOD->Write(&pLodDirectory, pNPCStats->pGroups_copy, 0) )
@@ -341,6 +395,7 @@
     sprintf(work_string, pGlobalTXT_LocalizationStrings[612], 206);
     MessageBoxA(nullptr, work_string, "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\LoadSave.cpp:829", 0);
   }
+
   for (int i =  1; i <= 4; ++i) // 4 - players
   {
     for (int j =  1; j <= 5; ++j) // 5 - images
@@ -367,6 +422,7 @@
       }
 	}
   }
+
   if ( !NotSaveWorld )//autosave for change location
   {
     //__debugbreak();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Engine/Serialization/LegacyImages.cpp	Wed May 20 15:12:33 2015 +0200
@@ -0,0 +1,945 @@
+#include "Engine/Engine.h"
+#include "Engine/Timer.h"
+#include "Engine/Party.h"
+#include "Engine/Objects/NPC.h"
+#include "Engine/Graphics/Overlays.h"
+#include "Engine/Serialization/LegacyImages.h"
+
+NPCData_Image_MM7::NPCData_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x4C);
+    memset(this, 0, sizeof(*this));
+}
+
+ItemGen_Image_MM7::ItemGen_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x24);
+    memset(this, 0, sizeof(*this));
+}
+
+SpellBuff_Image_MM7::SpellBuff_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x10);
+    memset(this, 0, sizeof(*this));
+}
+
+PlayerSpellbookChapter_Image_MM7::PlayerSpellbookChapter_Image_MM7()
+{
+    Assert(sizeof(*this) == 0xB);
+    memset(this, 0, sizeof(*this));
+}
+
+PlayerSpells_Image_MM7::PlayerSpells_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x64);
+    memset(this, 0, sizeof(*this));
+}
+
+PlayerEquipment_Image_MM7::PlayerEquipment_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x40);
+    memset(this, 0, sizeof(*this));
+}
+
+LloydBeacon_Image_MM7::LloydBeacon_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x1C);
+    memset(this, 0, sizeof(*this));
+}
+
+Player_Image_MM7::Player_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x1B3C);
+    memset(this, 0, sizeof(*this));
+}
+
+PartyTimeStruct_Image_MM7::PartyTimeStruct_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x678);
+    memset(this, 0, sizeof(*this));
+}
+
+Party_Image_MM7::Party_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x16238);
+    memset(this, 0, sizeof(*this));
+}
+
+Timer_Image_MM7::Timer_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x28);
+    memset(this, 0, sizeof(*this));
+}
+
+OtherOverlay_Image_MM7::OtherOverlay_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x14);
+    memset(this, 0, sizeof(*this));
+}
+
+OtherOverlayList_Image_MM7::OtherOverlayList_Image_MM7()
+{
+    Assert(sizeof(*this) == 0x3F0);
+    memset(this, 0, sizeof(*this));
+}
+
+
+
+
+
+void Timer_Image_MM7::Serialize(Timer *timer)
+{
+    memset(this, 0, sizeof(*this));
+
+    this->bReady = timer->bReady;
+    this->bPaused = timer->bPaused;
+    this->bTackGameTime = timer->bTackGameTime;
+    this->uStartTime = timer->uStartTime;
+    this->uStopTime = timer->uStopTime;
+    this->uGameTimeStart = timer->uGameTimeStart;
+    this->field_18 = timer->field_18;
+    this->uTimeElapsed = timer->uTimeElapsed;
+    this->dt_in_some_format = timer->dt_in_some_format;
+    this->uTotalGameTimeElapsed = timer->uTotalGameTimeElapsed;
+}
+
+void Timer_Image_MM7::Deserialize(Timer *timer)
+{
+    timer->bReady = this->bReady;
+    timer->bPaused = this->bPaused;
+    timer->bTackGameTime = this->bTackGameTime;
+    timer->uStartTime = this->uStartTime;
+    timer->uStopTime = this->uStopTime;
+    timer->uGameTimeStart = this->uGameTimeStart;
+    timer->field_18 = this->field_18;
+    timer->uTimeElapsed = this->uTimeElapsed;
+    timer->dt_in_some_format = this->dt_in_some_format;
+    timer->uTotalGameTimeElapsed = this->uTotalGameTimeElapsed;
+}
+
+void NPCData_Image_MM7::Serialize(NPCData *npc)
+{
+    memset(this, 0, sizeof(*this));
+
+    this->pName = npc->pName;
+    this->uPortraitID = npc->uPortraitID;
+    this->uFlags = npc->uFlags;
+    this->fame = npc->fame;
+    this->rep = npc->rep;
+    this->Location2D = npc->Location2D;
+    this->uProfession = npc->uProfession;
+    this->greet = npc->greet;
+    this->joins = npc->joins;
+    this->field_24 = npc->field_24;
+    this->evt_A = npc->evt_A;
+    this->evt_B = npc->evt_B;
+    this->evt_C = npc->evt_C;
+    this->evt_D = npc->evt_D;
+    this->evt_E = npc->evt_E;
+    this->evt_F = npc->evt_F;
+    this->uSex = npc->uSex;
+    this->bHasUsedTheAbility = npc->bHasUsedTheAbility;
+    this->news_topic = npc->news_topic;
+}
+
+void NPCData_Image_MM7::Deserialize(NPCData *npc)
+{
+    npc->pName = this->pName;
+    npc->uPortraitID = this->uPortraitID;
+    npc->uFlags = this->uFlags;
+    npc->fame = this->fame;
+    npc->rep = this->rep;
+    npc->Location2D = this->Location2D;
+    npc->uProfession = this->uProfession;
+    npc->greet = this->greet;
+    npc->joins = this->joins;
+    npc->field_24 = this->field_24;
+    npc->evt_A = this->evt_A;
+    npc->evt_B = this->evt_B;
+    npc->evt_C = this->evt_C;
+    npc->evt_D = this->evt_D;
+    npc->evt_E = this->evt_E;
+    npc->evt_F = this->evt_F;
+    npc->uSex = this->uSex;
+    npc->bHasUsedTheAbility = this->bHasUsedTheAbility;
+    npc->news_topic = this->news_topic;
+}
+
+
+void OtherOverlayList_Image_MM7::Serialize(OtherOverlayList *list)
+{
+    memset(this, 0, sizeof(*this));
+
+    this->bRedraw = list->bRedraw;
+    this->field_3E8 = list->field_3E8;
+
+    for (unsigned int i = 0; i < 50; ++i)
+    {
+        memset(&this->pOverlays[i], 0, sizeof(this->pOverlays[i]));
+
+        this->pOverlays[i].field_0 = list->pOverlays[i].field_0;
+        this->pOverlays[i].field_2 = list->pOverlays[i].field_2;
+        this->pOverlays[i].field_4 = list->pOverlays[i].field_4;
+        this->pOverlays[i].field_6 = list->pOverlays[i].field_6;
+        this->pOverlays[i].field_8 = list->pOverlays[i].field_8;
+        this->pOverlays[i].field_A = list->pOverlays[i].field_A;
+        this->pOverlays[i].field_C = list->pOverlays[i].field_C;
+        this->pOverlays[i].field_E = list->pOverlays[i].field_E;
+        this->pOverlays[i].field_10 = list->pOverlays[i].field_10;
+    }
+}
+
+
+void OtherOverlayList_Image_MM7::Deserialize(OtherOverlayList *list)
+{
+    list->bRedraw = this->bRedraw;
+    list->field_3E8 = this->field_3E8;
+
+    for (unsigned int i = 0; i < 50; ++i)
+    {
+        memset(&list->pOverlays[i], 0, sizeof(list->pOverlays[i]));
+
+        list->pOverlays[i].field_0 = this->pOverlays[i].field_0;
+        list->pOverlays[i].field_2 = this->pOverlays[i].field_2;
+        list->pOverlays[i].field_4 = this->pOverlays[i].field_4;
+        list->pOverlays[i].field_6 = this->pOverlays[i].field_6;
+        list->pOverlays[i].field_8 = this->pOverlays[i].field_8;
+        list->pOverlays[i].field_A = this->pOverlays[i].field_A;
+        list->pOverlays[i].field_C = this->pOverlays[i].field_C;
+        list->pOverlays[i].field_E = this->pOverlays[i].field_E;
+        list->pOverlays[i].field_10 = this->pOverlays[i].field_10;
+    }
+}
+
+
+
+void SpellBuff_Image_MM7::Serialize(SpellBuff *buff)
+{
+    memset(this, 0, sizeof(*this));
+
+    this->uExpireTime = buff->uExpireTime;
+    this->uPower = buff->uPower;
+    this->uSkill = buff->uSkill;
+    this->uOverlayID = buff->uOverlayID;
+    this->uCaster = buff->uCaster;
+    this->uFlags = buff->uFlags;
+}
+
+void SpellBuff_Image_MM7::Deserialize(SpellBuff *buff)
+{
+    buff->uExpireTime = this->uExpireTime;
+    buff->uPower = this->uPower;
+    buff->uSkill = this->uSkill;
+    buff->uOverlayID = this->uOverlayID;
+    buff->uCaster = this->uCaster;
+    buff->uFlags = this->uFlags;
+}
+
+
+
+void ItemGen_Image_MM7::Serialize(ItemGen *item)
+{
+    memset(this, 0, sizeof(*this));
+
+    this->uItemID = item->uItemID;
+    this->uEnchantmentType = item->uEnchantmentType;
+    this->m_enchantmentStrength = item->m_enchantmentStrength;
+    this->uSpecEnchantmentType = item->uSpecEnchantmentType;
+    this->uNumCharges = item->uNumCharges;
+    this->uAttributes = item->uAttributes;
+    this->uBodyAnchor = item->uBodyAnchor;
+    this->uMaxCharges = item->uMaxCharges;
+    this->uHolderPlayer = item->uHolderPlayer;
+    this->field_1B = item->field_1B;
+    this->uExpireTime = item->uExpireTime;
+}
+
+void ItemGen_Image_MM7::Deserialize(ItemGen *item)
+{
+    item->uItemID = this->uItemID;
+    item->uEnchantmentType = this->uEnchantmentType;
+    item->m_enchantmentStrength = this->m_enchantmentStrength;
+    item->uSpecEnchantmentType = this->uSpecEnchantmentType;
+    item->uNumCharges = this->uNumCharges;
+    item->uAttributes = this->uAttributes;
+    item->uBodyAnchor = this->uBodyAnchor;
+    item->uMaxCharges = this->uMaxCharges;
+    item->uHolderPlayer = this->uHolderPlayer;
+    item->field_1B = this->field_1B;
+    item->uExpireTime = this->uExpireTime;
+}
+
+
+void Party_Image_MM7::Serialize(Party *party)
+{
+    memset(this, 0, sizeof(*this));
+
+    this->field_0 = party->field_0;
+    this->uPartyHeight = party->uPartyHeight;
+    this->uDefaultPartyHeight = party->uDefaultPartyHeight;
+    this->sEyelevel = party->sEyelevel;
+    this->uDefaultEyelevel = party->uDefaultEyelevel;
+    this->field_14_radius = party->field_14_radius;
+    this->y_rotation_granularity = party->y_rotation_granularity;
+    this->uWalkSpeed = party->uWalkSpeed;
+    this->y_rotation_speed = party->y_rotation_speed;
+    this->field_24 = party->field_24;
+    this->field_28 = party->field_28;
+    this->uTimePlayed = party->uTimePlayed;
+    this->uLastRegenerationTime = party->uLastRegenerationTime;
+
+    for (unsigned int i = 0; i < 10; ++i)
+        this->PartyTimes.bountyHunting_next_generation_time[i] = party->PartyTimes.bountyHunting_next_generation_time[i];
+    for (unsigned int i = 0; i < 85; ++i)
+        this->PartyTimes.Shops_next_generation_time[i] = party->PartyTimes.Shops_next_generation_time[i];
+    for (unsigned int i = 0; i < 53; ++i)
+        this->PartyTimes._shop_ban_times[i] = party->PartyTimes._shop_ban_times[i];
+    for (unsigned int i = 0; i < 10; ++i)
+        this->PartyTimes.CounterEventValues[i] = party->PartyTimes.CounterEventValues[i];
+    for (unsigned int i = 0; i < 29; ++i)
+        this->PartyTimes.HistoryEventTimes[i] = party->PartyTimes.HistoryEventTimes[i];
+    for (unsigned int i = 0; i < 20; ++i)
+        this->PartyTimes._s_times[i] = party->PartyTimes._s_times[i];
+
+    this->vPosition.x = party->vPosition.x;
+    this->vPosition.y = party->vPosition.y;
+    this->vPosition.z = party->vPosition.z;
+    this->sRotationY = party->sRotationY;
+    this->sRotationX = party->sRotationX;
+    this->vPrevPosition.x = party->vPrevPosition.x;
+    this->vPrevPosition.y = party->vPrevPosition.y;
+    this->vPrevPosition.z = party->vPrevPosition.z;
+    this->sPrevRotationY = party->sPrevRotationY;
+    this->sPrevRotationX = party->sPrevRotationX;
+    this->sPrevEyelevel = party->sPrevEyelevel;
+    this->field_6E0 = party->field_6E0;
+    this->field_6E4 = party->field_6E4;
+    this->uFallSpeed = party->uFallSpeed;
+    this->field_6EC = party->field_6EC;
+    this->field_6F0 = party->field_6F0;
+    this->floor_face_pid = party->floor_face_pid;
+    this->walk_sound_timer = party->walk_sound_timer;
+    this->field_6FC = party->field_6FC;
+    this->uFallStartY = party->uFallStartY;
+    this->bFlying = party->bFlying;
+    this->field_708 = party->field_708;
+    this->hirelingScrollPosition = party->hirelingScrollPosition;
+    this->field_70A = party->field_70A;
+    this->field_70B = party->field_70B;
+    this->uCurrentYear = party->uCurrentYear;
+    this->uCurrentMonth = party->uCurrentMonth;
+    this->uCurrentMonthWeek = party->uCurrentMonthWeek;
+    this->uDaysPlayed = party->uDaysPlayed;
+    this->uCurrentHour = party->uCurrentHour;
+    this->uCurrentMinute = party->uCurrentMinute;
+    this->uCurrentTimeSecond = party->uCurrentTimeSecond;
+    this->uNumFoodRations = party->uNumFoodRations;
+    this->field_72C = party->field_72C;
+    this->field_730 = party->field_730;
+    this->uNumGold = party->uNumGold;
+    this->uNumGoldInBank = party->uNumGoldInBank;
+    this->uNumDeaths = party->uNumDeaths;
+    this->field_740 = party->field_740;
+    this->uNumPrisonTerms = party->uNumPrisonTerms;
+    this->uNumBountiesCollected = party->uNumBountiesCollected;
+    this->field_74C = party->field_74C;
+
+    for (unsigned int i = 0; i < 5; ++i)
+        this->monster_id_for_hunting[i] = party->monster_id_for_hunting[i];
+    for (unsigned int i = 0; i < 5; ++i)
+        this->monster_for_hunting_killed[i] = party->monster_for_hunting_killed[i];
+
+    this->days_played_without_rest = party->days_played_without_rest;
+
+    for (unsigned int i = 0; i < 64; ++i)
+        this->_quest_bits[i] = party->_quest_bits[i];
+    for (unsigned int i = 0; i < 16; ++i)
+        this->pArcomageWins[i] = party->pArcomageWins[i];
+
+    this->field_7B5_in_arena_quest = party->field_7B5_in_arena_quest;
+    this->uNumArenaPageWins = party->uNumArenaPageWins;
+    this->uNumArenaSquireWins = party->uNumArenaSquireWins;
+    this->uNumArenaKnightWins = party->uNumArenaKnightWins;
+    this->uNumArenaLordWins = party->uNumArenaLordWins;
+
+    for (unsigned int i = 0; i < 29; ++i)
+        this->pIsArtifactFound[i] = party->pIsArtifactFound[i];
+    for (unsigned int i = 0; i < 39; ++i)
+        this->field_7d7[i] = party->field_7d7[i];
+    for (unsigned int i = 0; i < 26; ++i)
+        this->_autonote_bits[i] = party->_autonote_bits[i];
+    for (unsigned int i = 0; i < 60; ++i)
+        this->field_818[i] = party->field_818[i];
+    for (unsigned int i = 0; i < 32; ++i)
+        this->field_854[i] = party->field_854[i];
+
+    this->uNumArcomageWins = party->uNumArcomageWins;
+    this->uNumArcomageLoses = party->uNumArcomageLoses;
+    this->bTurnBasedModeOn = party->bTurnBasedModeOn;
+    this->field_880 = party->field_880;
+    this->uFlags2 = party->uFlags2;
+    this->alignment = party->alignment;
+
+    for (unsigned int i = 0; i < 20; ++i)
+        this->pPartyBuffs[i].Serialize(&party->pPartyBuffs[i]);
+    for (unsigned int i = 0; i < 4; ++i)
+        this->pPlayers[i].Serialize(&party->pPlayers[i]);
+    for (unsigned int i = 0; i < 2; ++i)
+        this->pHirelings[i].Serialize(&party->pHirelings[i]);
+
+    this->pPickedItem.Serialize(&party->pPickedItem);
+
+    this->uFlags = party->uFlags;
+
+    for (unsigned int i = 0; i < 53; ++i)
+        for (unsigned int j = 0; j < 12; ++j)
+            this->StandartItemsInShops[i][j].Serialize(&party->StandartItemsInShops[i][j]);
+
+    for (unsigned int i = 0; i < 53; ++i)
+        for (unsigned int j = 0; j < 12; ++j)
+            this->SpecialItemsInShops[i][j].Serialize(&party->SpecialItemsInShops[i][j]);
+
+    for (unsigned int i = 0; i < 32; ++i)
+        for (unsigned int j = 0; j < 12; ++j)
+            this->SpellBooksInGuilds[i][j].Serialize(&party->SpellBooksInGuilds[i][j]);
+
+    for (unsigned int i = 0; i < 24; ++i)
+        this->field_1605C[i] = party->field_1605C[i];
+
+    strcpy(this->pHireling1Name, party->pHireling1Name);
+    strcpy(this->pHireling2Name, party->pHireling2Name);
+
+    this->armageddon_timer = party->armageddon_timer;
+    this->armageddonDamage = party->armageddonDamage;
+
+    for (unsigned int i = 0; i < 4; ++i)
+        this->pTurnBasedPlayerRecoveryTimes[i] = party->pTurnBasedPlayerRecoveryTimes[i];
+
+    for (unsigned int i = 0; i < 53; ++i)
+        this->InTheShopFlags[i] = party->InTheShopFlags[i];
+
+    this->uFine = party->uFine;
+    this->flt_TorchlightColorR = party->flt_TorchlightColorR;
+    this->flt_TorchlightColorG = party->flt_TorchlightColorG;
+    this->flt_TorchlightColorB = party->flt_TorchlightColorB;
+}
+
+
+void Party_Image_MM7::Deserialize(Party *party)
+{
+    party->field_0 = this->field_0;
+    party->uPartyHeight = this->uPartyHeight;
+    party->uDefaultPartyHeight = this->uDefaultPartyHeight;
+    party->sEyelevel = this->sEyelevel;
+    party->uDefaultEyelevel = this->uDefaultEyelevel;
+    party->field_14_radius = this->field_14_radius;
+    party->y_rotation_granularity = this->y_rotation_granularity;
+    party->uWalkSpeed = this->uWalkSpeed;
+    party->y_rotation_speed = this->y_rotation_speed;
+    party->field_24 = this->field_24;
+    party->field_28 = this->field_28;
+    party->uTimePlayed = this->uTimePlayed;
+    party->uLastRegenerationTime = this->uLastRegenerationTime;
+
+    for (unsigned int i = 0; i < 10; ++i)
+        party->PartyTimes.bountyHunting_next_generation_time[i] = this->PartyTimes.bountyHunting_next_generation_time[i];
+    for (unsigned int i = 0; i < 85; ++i)
+        party->PartyTimes.Shops_next_generation_time[i] = this->PartyTimes.Shops_next_generation_time[i];
+    for (unsigned int i = 0; i < 53; ++i)
+        party->PartyTimes._shop_ban_times[i] = this->PartyTimes._shop_ban_times[i];
+    for (unsigned int i = 0; i < 10; ++i)
+        party->PartyTimes.CounterEventValues[i] = this->PartyTimes.CounterEventValues[i];
+    for (unsigned int i = 0; i < 29; ++i)
+        party->PartyTimes.HistoryEventTimes[i] = this->PartyTimes.HistoryEventTimes[i];
+    for (unsigned int i = 0; i < 20; ++i)
+        party->PartyTimes._s_times[i] = this->PartyTimes._s_times[i];
+
+    party->vPosition.x = this->vPosition.x;
+    party->vPosition.y = this->vPosition.y;
+    party->vPosition.z = this->vPosition.z;
+    party->sRotationY = this->sRotationY;
+    party->sRotationX = this->sRotationX;
+    party->vPrevPosition.x = this->vPrevPosition.x;
+    party->vPrevPosition.y = this->vPrevPosition.y;
+    party->vPrevPosition.z = this->vPrevPosition.z;
+    party->sPrevRotationY = this->sPrevRotationY;
+    party->sPrevRotationX = this->sPrevRotationX;
+    party->sPrevEyelevel = this->sPrevEyelevel;
+    party->field_6E0 = this->field_6E0;
+    party->field_6E4 = this->field_6E4;
+    party->uFallSpeed = this->uFallSpeed;
+    party->field_6EC = this->field_6EC;
+    party->field_6F0 = this->field_6F0;
+    party->floor_face_pid = this->floor_face_pid;
+    party->walk_sound_timer = this->walk_sound_timer;
+    party->field_6FC = this->field_6FC;
+    party->uFallStartY = this->uFallStartY;
+    party->bFlying = this->bFlying;
+    party->field_708 = this->field_708;
+    party->hirelingScrollPosition = this->hirelingScrollPosition;
+    party->field_70A = this->field_70A;
+    party->field_70B = this->field_70B;
+    party->uCurrentYear = this->uCurrentYear;
+    party->uCurrentMonth = this->uCurrentMonth;
+    party->uCurrentMonthWeek = this->uCurrentMonthWeek;
+    party->uDaysPlayed = this->uDaysPlayed;
+    party->uCurrentHour = this->uCurrentHour;
+    party->uCurrentMinute = this->uCurrentMinute;
+    party->uCurrentTimeSecond = this->uCurrentTimeSecond;
+    party->uNumFoodRations = this->uNumFoodRations;
+    party->field_72C = this->field_72C;
+    party->field_730 = this->field_730;
+    party->uNumGold = this->uNumGold;
+    party->uNumGoldInBank = this->uNumGoldInBank;
+    party->uNumDeaths = this->uNumDeaths;
+    party->field_740 = this->field_740;
+    party->uNumPrisonTerms = this->uNumPrisonTerms;
+    party->uNumBountiesCollected = this->uNumBountiesCollected;
+    party->field_74C = this->field_74C;
+
+    for (unsigned int i = 0; i < 5; ++i)
+        party->monster_id_for_hunting[i] = this->monster_id_for_hunting[i];
+    for (unsigned int i = 0; i < 5; ++i)
+        party->monster_for_hunting_killed[i] = this->monster_for_hunting_killed[i];
+
+    party->days_played_without_rest = this->days_played_without_rest;
+
+    for (unsigned int i = 0; i < 64; ++i)
+        party->_quest_bits[i] = this->_quest_bits[i];
+    for (unsigned int i = 0; i < 16; ++i)
+        party->pArcomageWins[i] = this->pArcomageWins[i];
+
+    party->field_7B5_in_arena_quest = this->field_7B5_in_arena_quest;
+    party->uNumArenaPageWins = this->uNumArenaPageWins;
+    party->uNumArenaSquireWins = this->uNumArenaSquireWins;
+    party->uNumArenaKnightWins = this->uNumArenaKnightWins;
+    party->uNumArenaLordWins = this->uNumArenaLordWins;
+
+    for (unsigned int i = 0; i < 29; ++i)
+        party->pIsArtifactFound[i] = this->pIsArtifactFound[i];
+    for (unsigned int i = 0; i < 39; ++i)
+        party->field_7d7[i] = this->field_7d7[i];
+    for (unsigned int i = 0; i < 26; ++i)
+        party->_autonote_bits[i] = this->_autonote_bits[i];
+    for (unsigned int i = 0; i < 60; ++i)
+        party->field_818[i] = this->field_818[i];
+    for (unsigned int i = 0; i < 32; ++i)
+        party->field_854[i] = this->field_854[i];
+
+    party->uNumArcomageWins = this->uNumArcomageWins;
+    party->uNumArcomageLoses = this->uNumArcomageLoses;
+    party->bTurnBasedModeOn = this->bTurnBasedModeOn;
+    party->field_880 = this->field_880;
+    party->uFlags2 = this->uFlags2;
+
+    switch (this->alignment)
+    {
+        case 0: party->alignment = PartyAlignment_Good; break;
+        case 1: party->alignment = PartyAlignment_Neutral; break;
+        case 2: party->alignment = PartyAlignment_Evil; break;
+        default:
+            Assert(false);
+    }
+
+    for (unsigned int i = 0; i < 20; ++i)
+        this->pPartyBuffs[i].Deserialize(&party->pPartyBuffs[i]);
+    for (unsigned int i = 0; i < 4; ++i)
+        this->pPlayers[i].Deserialize(&party->pPlayers[i]);
+    for (unsigned int i = 0; i < 2; ++i)
+        this->pHirelings[i].Deserialize(&party->pHirelings[i]);
+
+    this->pPickedItem.Deserialize(&party->pPickedItem);
+
+    party->uFlags = this->uFlags;
+
+    for (unsigned int i = 0; i < 53; ++i)
+        for (unsigned int j = 0; j < 12; ++j)
+            this->StandartItemsInShops[i][j].Deserialize(&party->StandartItemsInShops[i][j]);
+
+    for (unsigned int i = 0; i < 53; ++i)
+        for (unsigned int j = 0; j < 12; ++j)
+            this->SpecialItemsInShops[i][j].Deserialize(&party->SpecialItemsInShops[i][j]);
+
+    for (unsigned int i = 0; i < 32; ++i)
+        for (unsigned int j = 0; j < 12; ++j)
+            this->SpellBooksInGuilds[i][j].Deserialize(&party->SpellBooksInGuilds[i][j]);
+
+    for (unsigned int i = 0; i < 24; ++i)
+        party->field_1605C[i] = this->field_1605C[i];
+
+    strcpy(party->pHireling1Name, this->pHireling1Name);
+    strcpy(party->pHireling2Name, this->pHireling2Name);
+
+    party->armageddon_timer = this->armageddon_timer;
+    party->armageddonDamage = this->armageddonDamage;
+
+    for (unsigned int i = 0; i < 4; ++i)
+        party->pTurnBasedPlayerRecoveryTimes[i] = this->pTurnBasedPlayerRecoveryTimes[i];
+
+    for (unsigned int i = 0; i < 53; ++i)
+        party->InTheShopFlags[i] = this->InTheShopFlags[i];
+
+    party->uFine = this->uFine;
+    party->flt_TorchlightColorR = this->flt_TorchlightColorR;
+    party->flt_TorchlightColorG = this->flt_TorchlightColorG;
+    party->flt_TorchlightColorB = this->flt_TorchlightColorB;
+}
+
+
+void Player_Image_MM7::Serialize(Player *player)
+{
+    memset(this, 0, sizeof(*this));
+
+    for (unsigned int i = 0; i < 20; ++i)
+        this->pConditions[i] = player->pConditions[i];
+
+    this->uExperience = player->uExperience;
+
+    strcpy(this->pName, player->pName);
+
+    this->uSex = player->uSex;
+    this->classType = player->classType;
+    this->uCurrentFace = player->uCurrentFace;
+    this->field_BB = player->field_BB;
+    this->uMight = player->uMight;
+    this->uMightBonus = player->uMightBonus;
+    this->uIntelligence = player->uIntelligence;
+    this->uIntelligenceBonus = player->uIntelligenceBonus;
+    this->uWillpower = player->uWillpower;
+    this->uWillpowerBonus = player->uWillpowerBonus;
+    this->uEndurance = player->uEndurance;
+    this->uEnduranceBonus = player->uEnduranceBonus;
+    this->uSpeed = player->uSpeed;
+    this->uSpeedBonus = player->uSpeedBonus;
+    this->uAccuracy = player->uAccuracy;
+    this->uAccuracyBonus = player->uAccuracyBonus;
+    this->uLuck = player->uLuck;
+    this->uLuckBonus = player->uLuckBonus;
+    this->sACModifier = player->sACModifier;
+    this->uLevel = player->uLevel;
+    this->sLevelModifier = player->sLevelModifier;
+    this->sAgeModifier = player->sAgeModifier;
+    this->field_E0 = player->field_E0;
+    this->field_E4 = player->field_E4;
+    this->field_E8 = player->field_E8;
+    this->field_EC = player->field_EC;
+    this->field_F0 = player->field_F0;
+    this->field_F4 = player->field_F4;
+    this->field_F8 = player->field_F8;
+    this->field_FC = player->field_FC;
+    this->field_100 = player->field_100;
+    this->field_104 = player->field_104;
+
+    for (unsigned int i = 0; i < 37; ++i)
+        this->pActiveSkills[i] = player->pActiveSkills[i];
+
+    for (unsigned int i = 0; i < 64; ++i)
+        this->_achieved_awards_bits[i] = player->_achieved_awards_bits[i];
+
+    for (unsigned int i = 0; i < 99; ++i)
+        this->spellbook.bHaveSpell[i] = player->spellbook.bHaveSpell[i];
+
+    this->pure_luck_used = player->pure_luck_used;
+    this->pure_speed_used = player->pure_speed_used;
+    this->pure_intellect_used = player->pure_intellect_used;
+    this->pure_endurance_used = player->pure_endurance_used;
+    this->pure_willpower_used = player->pure_willpower_used;
+    this->pure_accuracy_used = player->pure_accuracy_used;
+    this->pure_might_used = player->pure_might_used;
+
+    for (unsigned int i = 0; i < 138; ++i)
+        this->pOwnItems[i].Serialize(&player->pOwnItems[i]);
+
+    for (unsigned int i = 0; i < 126; ++i)
+        this->pInventoryMatrix[i] = player->pInventoryMatrix[i];
+
+    this->sResFireBase = player->sResFireBase;
+    this->sResAirBase = player->sResAirBase;
+    this->sResWaterBase = player->sResWaterBase;
+    this->sResEarthBase = player->sResEarthBase;
+    this->field_177C = player->field_177C;
+    this->sResMagicBase = player->sResMagicBase;
+    this->sResSpiritBase = player->sResSpiritBase;
+    this->sResMindBase = player->sResMindBase;
+    this->sResBodyBase = player->sResBodyBase;
+    this->sResLightBase = player->sResLightBase;
+    this->sResDarkBase = player->sResDarkBase;
+    this->sResFireBonus = player->sResFireBonus;
+    this->sResAirBonus = player->sResAirBonus;
+    this->sResWaterBonus = player->sResWaterBonus;
+    this->sResEarthBonus = player->sResEarthBonus;
+    this->field_1792 = player->field_1792;
+    this->sResMagicBonus = player->sResMagicBonus;
+    this->sResSpiritBonus = player->sResSpiritBonus;
+    this->sResMindBonus = player->sResMindBonus;
+    this->sResBodyBonus = player->sResBodyBonus;
+    this->sResLightBonus = player->sResLightBonus;
+    this->sResDarkBonus = player->sResDarkBonus;
+
+    for (unsigned int i = 0; i < 24; ++i)
+        this->pPlayerBuffs[i].Serialize(&player->pPlayerBuffs[i]);
+
+    this->uVoiceID = player->uVoiceID;
+    this->uPrevVoiceID = player->uPrevVoiceID;
+    this->uPrevFace = player->uPrevFace;
+    this->field_192C = player->field_192C;
+    this->field_1930 = player->field_1930;
+    this->uTimeToRecovery = player->uTimeToRecovery;
+    this->field_1936 = player->field_1936;
+    this->field_1937 = player->field_1937;
+    this->uSkillPoints = player->uSkillPoints;
+    this->sHealth = player->sHealth;
+    this->sMana = player->sMana;
+    this->uBirthYear = player->uBirthYear;
+
+    for (unsigned int i = 0; i < 16; ++i)
+        this->pEquipment.pIndices[i] = player->pEquipment.pIndices[i];
+
+    for (unsigned int i = 0; i < 49; ++i)
+        this->field_1988[i] = player->field_1988[i];
+
+    this->field_1A4C = player->field_1A4C;
+    this->field_1A4D = player->field_1A4D;
+    this->lastOpenedSpellbookPage = player->lastOpenedSpellbookPage;
+    this->uQuickSpell = player->uQuickSpell;
+
+    for (unsigned int i = 0; i < 49; ++i)
+        this->playerEventBits[i] = player->playerEventBits[i];
+
+    this->_some_attack_bonus = player->_some_attack_bonus;
+    this->field_1A91 = player->field_1A91;
+    this->_melee_dmg_bonus = player->_melee_dmg_bonus;
+    this->field_1A93 = player->field_1A93;
+    this->_ranged_atk_bonus = player->_ranged_atk_bonus;
+    this->field_1A95 = player->field_1A95;
+    this->_ranged_dmg_bonus = player->_ranged_dmg_bonus;
+    this->field_1A97 = player->field_1A97;
+    this->uFullHealthBonus = player->uFullHealthBonus;
+    this->_health_related = player->_health_related;
+    this->uFullManaBonus = player->uFullManaBonus;
+    this->_mana_related = player->_mana_related;
+    this->expression = player->expression;
+    this->uExpressionTimePassed = player->uExpressionTimePassed;
+    this->uExpressionTimeLength = player->uExpressionTimeLength;
+    this->field_1AA2 = player->field_1AA2;
+    this->_expression21_animtime = player->_expression21_animtime;
+    this->_expression21_frameset = player->_expression21_frameset;
+
+    for (unsigned int i = 0; i < 5; ++i)
+    {
+        this->pInstalledBeacons[i].uBeaconTime = player->pInstalledBeacons[i].uBeaconTime;
+        this->pInstalledBeacons[i].PartyPos_X = player->pInstalledBeacons[i].PartyPos_X;
+        this->pInstalledBeacons[i].PartyPos_Y = player->pInstalledBeacons[i].PartyPos_Y;
+        this->pInstalledBeacons[i].PartyPos_Z = player->pInstalledBeacons[i].PartyPos_Z;
+        this->pInstalledBeacons[i].PartyRot_X = player->pInstalledBeacons[i].PartyRot_X;
+        this->pInstalledBeacons[i].PartyRot_Y = player->pInstalledBeacons[i].PartyRot_Y;
+        this->pInstalledBeacons[i].SaveFileID = player->pInstalledBeacons[i].SaveFileID;
+    }
+
+    this->uNumDivineInterventionCastsThisDay = player->uNumDivineInterventionCastsThisDay;
+    this->uNumArmageddonCasts = player->uNumArmageddonCasts;
+    this->uNumFireSpikeCasts = player->uNumFireSpikeCasts;
+    this->field_1B3B = player->field_1B3B;
+}
+
+void Player_Image_MM7::Deserialize(Player *player)
+{
+    for (unsigned int i = 0; i < 20; ++i)
+        player->pConditions[i] = this->pConditions[i];
+
+    player->uExperience = this->uExperience;
+
+    strcpy(player->pName, this->pName);
+
+    switch (this->uSex)
+    {
+        case 0: player->uSex = SEX_MALE; break;
+        case 1: player->uSex = SEX_FEMALE; break;
+        default:
+            Assert(false);
+    }
+
+    switch (this->classType)
+    {
+        case  0: classType = PLAYER_CLASS_KNIGHT; break;
+        case  1: classType = PLAYER_CLASS_CHEVALIER; break;
+        case  2: classType = PLAYER_CLASS_CHAMPION; break;
+        case  3: classType = PLAYER_CLASS_BLACK_KNIGHT; break;
+        case  4: classType = PLAYER_CLASS_THEIF; break;
+        case  5: classType = PLAYER_CLASS_ROGUE; break;
+        case  6: classType = PLAYER_CLASS_SPY; break;
+        case  7: classType = PLAYER_CLASS_ASSASSIN; break;
+        case  8: classType = PLAYER_CLASS_MONK; break;
+        case  9: classType = PLAYER_CLASS_INITIATE; break;
+        case 10: classType = PLAYER_CLASS_MASTER; break;
+        case 11: classType = PLAYER_CLASS_NINJA; break;
+        case 12: classType = PLAYER_CLASS_PALADIN; break;
+        case 13: classType = PLAYER_CLASS_CRUSADER; break;
+        case 14: classType = PLAYER_CLASS_HERO; break;
+        case 15: classType = PLAYER_CLASS_VILLIAN; break;
+        case 16: classType = PLAYER_CLASS_ARCHER; break;
+        case 17: classType = PLAYER_CLASS_WARRIOR_MAGE; break;
+        case 18: classType = PLAYER_CLASS_MASTER_ARCHER; break;
+        case 19: classType = PLAYER_CLASS_SNIPER; break;
+        case 20: classType = PLAYER_CLASS_RANGER; break;
+        case 21: classType = PLAYER_CLASS_HUNTER; break;
+        case 22: classType = PLAYER_CLASS_RANGER_LORD; break;
+        case 23: classType = PLAYER_CLASS_BOUNTY_HUNTER; break;
+        case 24: classType = PLAYER_CLASS_CLERIC; break;
+        case 25: classType = PLAYER_CLASS_PRIEST; break;
+        case 26: classType = PLAYER_CLASS_PRIEST_OF_SUN; break;
+        case 27: classType = PLAYER_CLASS_PRIEST_OF_MOON; break;
+        case 28: classType = PLAYER_CLASS_DRUID; break;
+        case 29: classType = PLAYER_CLASS_GREAT_DRUID; break;
+        case 30: classType = PLAYER_CLASS_ARCH_DRUID; break;
+        case 31: classType = PLAYER_CLASS_WARLOCK; break;
+        case 32: classType = PLAYER_CLASS_SORCERER; break;
+        case 33: classType = PLAYER_CLASS_WIZARD; break;
+        case 34: classType = PLAYER_CLASS_ARCHMAGE; break;
+        case 35: classType = PLAYER_CLASS_LICH; break;
+        default:
+            Assert(false);
+    }
+
+    player->uCurrentFace = this->uCurrentFace;
+    player->field_BB = this->field_BB;
+    player->uMight = this->uMight;
+    player->uMightBonus = this->uMightBonus;
+    player->uIntelligence = this->uIntelligence;
+    player->uIntelligenceBonus = this->uIntelligenceBonus;
+    player->uWillpower = this->uWillpower;
+    player->uWillpowerBonus = this->uWillpowerBonus;
+    player->uEndurance = this->uEndurance;
+    player->uEnduranceBonus = this->uEnduranceBonus;
+    player->uSpeed = this->uSpeed;
+    player->uSpeedBonus = this->uSpeedBonus;
+    player->uAccuracy = this->uAccuracy;
+    player->uAccuracyBonus = this->uAccuracyBonus;
+    player->uLuck = this->uLuck;
+    player->uLuckBonus = this->uLuckBonus;
+    player->sACModifier = this->sACModifier;
+    player->uLevel = this->uLevel;
+    player->sLevelModifier = this->sLevelModifier;
+    player->sAgeModifier = this->sAgeModifier;
+    player->field_E0 = this->field_E0;
+    player->field_E4 = this->field_E4;
+    player->field_E8 = this->field_E8;
+    player->field_EC = this->field_EC;
+    player->field_F0 = this->field_F0;
+    player->field_F4 = this->field_F4;
+    player->field_F8 = this->field_F8;
+    player->field_FC = this->field_FC;
+    player->field_100 = this->field_100;
+    player->field_104 = this->field_104;
+
+    for (unsigned int i = 0; i < 37; ++i)
+        player->pActiveSkills[i] = this->pActiveSkills[i];
+
+    for (unsigned int i = 0; i < 64; ++i)
+        player->_achieved_awards_bits[i] = this->_achieved_awards_bits[i];
+
+    for (unsigned int i = 0; i < 99; ++i)
+        player->spellbook.bHaveSpell[i] = this->spellbook.bHaveSpell[i];
+
+    player->pure_luck_used = this->pure_luck_used;
+    player->pure_speed_used = this->pure_speed_used;
+    player->pure_intellect_used = this->pure_intellect_used;
+    player->pure_endurance_used = this->pure_endurance_used;
+    player->pure_willpower_used = this->pure_willpower_used;
+    player->pure_accuracy_used = this->pure_accuracy_used;
+    player->pure_might_used = this->pure_might_used;
+
+    for (unsigned int i = 0; i < 138; ++i)
+        this->pOwnItems[i].Deserialize(&player->pOwnItems[i]);
+
+    for (unsigned int i = 0; i < 126; ++i)
+        player->pInventoryMatrix[i] = this->pInventoryMatrix[i];
+
+    player->sResFireBase = this->sResFireBase;
+    player->sResAirBase = this->sResAirBase;
+    player->sResWaterBase = this->sResWaterBase;
+    player->sResEarthBase = this->sResEarthBase;
+    player->field_177C = this->field_177C;
+    player->sResMagicBase = this->sResMagicBase;
+    player->sResSpiritBase = this->sResSpiritBase;
+    player->sResMindBase = this->sResMindBase;
+    player->sResBodyBase = this->sResBodyBase;
+    player->sResLightBase = this->sResLightBase;
+    player->sResDarkBase = this->sResDarkBase;
+    player->sResFireBonus = this->sResFireBonus;
+    player->sResAirBonus = this->sResAirBonus;
+    player->sResWaterBonus = this->sResWaterBonus;
+    player->sResEarthBonus = this->sResEarthBonus;
+    player->field_1792 = this->field_1792;
+    player->sResMagicBonus = this->sResMagicBonus;
+    player->sResSpiritBonus = this->sResSpiritBonus;
+    player->sResMindBonus = this->sResMindBonus;
+    player->sResBodyBonus = this->sResBodyBonus;
+    player->sResLightBonus = this->sResLightBonus;
+    player->sResDarkBonus = this->sResDarkBonus;
+
+    for (unsigned int i = 0; i < 24; ++i)
+        this->pPlayerBuffs[i].Deserialize(&player->pPlayerBuffs[i]);
+
+    player->uVoiceID = this->uVoiceID;
+    player->uPrevVoiceID = this->uPrevVoiceID;
+    player->uPrevFace = this->uPrevFace;
+    player->field_192C = this->field_192C;
+    player->field_1930 = this->field_1930;
+    player->uTimeToRecovery = this->uTimeToRecovery;
+    player->field_1936 = this->field_1936;
+    player->field_1937 = this->field_1937;
+    player->uSkillPoints = this->uSkillPoints;
+    player->sHealth = this->sHealth;
+    player->sMana = this->sMana;
+    player->uBirthYear = this->uBirthYear;
+
+    for (unsigned int i = 0; i < 16; ++i)
+        player->pEquipment.pIndices[i] = this->pEquipment.pIndices[i];
+
+    for (unsigned int i = 0; i < 49; ++i)
+        player->field_1988[i] = this->field_1988[i];
+
+    player->field_1A4C = this->field_1A4C;
+    player->field_1A4D = this->field_1A4D;
+    player->lastOpenedSpellbookPage = this->lastOpenedSpellbookPage;
+    player->uQuickSpell = this->uQuickSpell;
+
+    for (unsigned int i = 0; i < 49; ++i)
+        player->playerEventBits[i] = this->playerEventBits[i];
+
+    player->_some_attack_bonus = this->_some_attack_bonus;
+    player->field_1A91 = this->field_1A91;
+    player->_melee_dmg_bonus = this->_melee_dmg_bonus;
+    player->field_1A93 = this->field_1A93;
+    player->_ranged_atk_bonus = this->_ranged_atk_bonus;
+    player->field_1A95 = this->field_1A95;
+    player->_ranged_dmg_bonus = this->_ranged_dmg_bonus;
+    player->field_1A97 = this->field_1A97;
+    player->uFullHealthBonus = this->uFullHealthBonus;
+    player->_health_related = this->_health_related;
+    player->uFullManaBonus = this->uFullManaBonus;
+    player->_mana_related = this->_mana_related;
+    player->expression = (CHARACTER_EXPRESSION_ID)this->expression;
+    player->uExpressionTimePassed = this->uExpressionTimePassed;
+    player->uExpressionTimeLength = this->uExpressionTimeLength;
+    player->field_1AA2 = this->field_1AA2;
+    player->_expression21_animtime = this->_expression21_animtime;
+    player->_expression21_frameset = this->_expression21_frameset;
+
+    for (unsigned int i = 0; i < 5; ++i)
+    {
+        player->pInstalledBeacons[i].uBeaconTime = this->pInstalledBeacons[i].uBeaconTime;
+        player->pInstalledBeacons[i].PartyPos_X = this->pInstalledBeacons[i].PartyPos_X;
+        player->pInstalledBeacons[i].PartyPos_Y = this->pInstalledBeacons[i].PartyPos_Y;
+        player->pInstalledBeacons[i].PartyPos_Z = this->pInstalledBeacons[i].PartyPos_Z;
+        player->pInstalledBeacons[i].PartyRot_X = this->pInstalledBeacons[i].PartyRot_X;
+        player->pInstalledBeacons[i].PartyRot_Y = this->pInstalledBeacons[i].PartyRot_Y;
+        player->pInstalledBeacons[i].SaveFileID = this->pInstalledBeacons[i].SaveFileID;
+    }
+
+    player->uNumDivineInterventionCastsThisDay = this->uNumDivineInterventionCastsThisDay;
+    player->uNumArmageddonCasts = this->uNumArmageddonCasts;
+    player->uNumFireSpikeCasts = this->uNumFireSpikeCasts;
+    player->field_1B3B = this->field_1B3B;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Engine/Serialization/LegacyImages.h	Wed May 20 15:12:33 2015 +0200
@@ -0,0 +1,524 @@
+#pragma once
+/*
+ *  Party, timers, NPCs and other stuff is binary dumped into resources/savegame files, which limits ability to alter
+ *      these structures without breaking compatibility.
+ *  This module is used to serialzie and deserialize native game structures intro their current representations without
+ *      breaking compatibility with original files.
+*/
+
+
+#pragma pack(push, 1)
+struct NPCData_Image_MM7
+{
+    NPCData_Image_MM7();
+
+    void Serialize(struct NPCData *item);
+    void Deserialize(struct NPCData *item);
+
+    /* 00 */ char *pName;
+    /* 04 */ unsigned int uPortraitID;
+    /* 08 */ unsigned int uFlags;  // & 0x80    no greeting on dialogue start; looks like hired
+    /* 0C */ int fame;
+    /* 10 */ int rep;
+    /* 14 */ unsigned int Location2D;
+    /* 18 */ unsigned int uProfession;
+    /* 1C */ int greet;
+    /* 20 */ int joins;
+    /* 24 */ int field_24;
+    /* 28 */ unsigned int evt_A;
+    /* 2C */ unsigned int evt_B;
+    /* 30 */ unsigned int evt_C;
+    /* 34 */ unsigned int evt_D;
+    /* 38 */ unsigned int evt_E;
+    /* 3C */ unsigned int evt_F;
+    /* 40 */ unsigned int uSex;
+    /* 44 */ int bHasUsedTheAbility;
+    /* 48 */ int news_topic;
+    /* 4C */
+};
+
+struct ItemGen_Image_MM7
+{
+    ItemGen_Image_MM7();
+
+    void Serialize(struct ItemGen *item);
+    void Deserialize(struct ItemGen *item);
+
+    /* 00 */ int uItemID;
+    /* 04 */ int uEnchantmentType;
+    /* 08 */ int m_enchantmentStrength;
+    /* 0C */ int uSpecEnchantmentType;
+    // 25  +5 levels
+    // 16  Drain Hit Points from target.
+    // 35  Increases chance of disarming.
+    // 39  Double damage vs Demons.
+    // 40  Double damage vs Dragons
+    // 45  +5 Speed and Accuracy
+    // 56  +5 Might and Endurance.
+    // 57  +5 Intellect and Personality.
+    // 58  Increased Value.
+    // 60  +3 Unarmed and Dodging skills
+    // 61  +3 Stealing and Disarm skills.
+    // 59  Increased Weapon speed.
+    // 63  Double Damage vs. Elves.
+    // 64  Double Damage vs. Undead.
+    // 67  Adds 5 points of Body damage and +2 Disarm skill.
+    // 68  Adds 6-8 points of Cold damage and +5 Armor Class.
+    // 71  Prevents drowning damage.
+    // 72  Prevents falling damage.
+    /* 10 */ int uNumCharges;
+    /* 14 */ unsigned int uAttributes;
+    /* 18 */ unsigned __int8 uBodyAnchor;
+    /* 19 */ char uMaxCharges;
+    /* 1A */ char uHolderPlayer;
+    /* 1B */ char field_1B;
+    /* 1C */ unsigned __int64 uExpireTime;
+};
+
+struct SpellBuff_Image_MM7
+{
+    SpellBuff_Image_MM7();
+
+    void Serialize(struct SpellBuff *item);
+    void Deserialize(struct SpellBuff *item);
+
+    /* 00 */ signed __int64 uExpireTime;
+    /* 08 */ unsigned __int16 uPower;
+    /* 0A */ unsigned __int16 uSkill;
+    /* 0C */ unsigned __int16 uOverlayID;
+    /* 0E */ unsigned __int8 uCaster;
+    /* 0F */ unsigned __int8 uFlags;
+    /* 10 */
+};
+
+struct PlayerSpellbookChapter_Image_MM7
+{
+    PlayerSpellbookChapter_Image_MM7();
+
+    /* 00 */ char bIsSpellAvailable[11];
+    /* 0B */
+};
+struct PlayerSpells_Image_MM7
+{
+    PlayerSpells_Image_MM7();
+
+    union
+    {
+        struct
+        {
+            /* 00 */ PlayerSpellbookChapter_Image_MM7 pFireSpellbook;
+            /* 0B */ PlayerSpellbookChapter_Image_MM7 pAirSpellbook;
+            /* 16 */ PlayerSpellbookChapter_Image_MM7 pWaterSpellbook;
+            /* 21 */ PlayerSpellbookChapter_Image_MM7 pEarthSpellbook;
+            /* 2C */ PlayerSpellbookChapter_Image_MM7 pSpiritSpellbook;
+            /* 37 */ PlayerSpellbookChapter_Image_MM7 pMindSpellbook;
+            /* 42 */ PlayerSpellbookChapter_Image_MM7 pBodySpellbook;
+            /* 4D */ PlayerSpellbookChapter_Image_MM7 pLightSpellbook;
+            /* 58 */ PlayerSpellbookChapter_Image_MM7 pDarkSpellbook;
+            /* 63 */ char _pad;
+            /* 64 */
+        };
+        struct
+        {
+            /* 00 */ PlayerSpellbookChapter_Image_MM7 pChapters[9];
+            /* 63 */ char _pad;
+            /* 64 */
+        };
+        struct
+        {
+            /* 00 */ char bHaveSpell[99];
+            /* 63 */ char _pad;
+            /* 64 */
+        };
+    };
+};
+
+union PlayerEquipment_Image_MM7
+{
+    PlayerEquipment_Image_MM7();
+
+    union
+    {
+        struct
+        {
+            /* 00 */ unsigned int uShield;
+            /* 04 */ unsigned int uMainHand;
+            /* 08 */ unsigned int uBow;
+            /* 0C */ unsigned int uArmor;
+            /* 10 */ unsigned int uHelm;
+            /* 14 */ unsigned int uBelt;
+            /* 18 */ unsigned int uCloak;
+            /* 1C */ unsigned int uGlove;
+            /* 20 */ unsigned int uBoot;
+            /* 24 */ unsigned int uAmulet;
+            /* 28 */ unsigned int uRings[6];
+            /* 40 */
+        };
+        unsigned int pIndices[16];
+    };
+};
+
+struct LloydBeacon_Image_MM7
+{
+    LloydBeacon_Image_MM7();
+
+    /* 00 */ unsigned __int64 uBeaconTime;
+    /* 08 */ int PartyPos_X;
+    /* 0C */ int PartyPos_Y;
+    /* 10 */ int PartyPos_Z;
+    /* 14 */ __int16 PartyRot_X;
+    /* 16 */ __int16 PartyRot_Y;
+    /* 18 */ int SaveFileID;
+    /* 1C */
+};
+
+struct Player_Image_MM7
+{
+    Player_Image_MM7();
+
+    void Serialize(struct Player *);
+    void Deserialize(struct Player *);
+
+    /* 0000 */ __int64 pConditions[20];
+    /* 00A0 */ unsigned __int64 uExperience;
+    /* 00A8 */ char pName[16];
+    /* 00B8 */ unsigned char uSex;
+    /* 00B9 */ unsigned char classType;
+    /* 00BA */ unsigned __int8 uCurrentFace;
+    /* 00BB */ char field_BB;
+    /* 00BC */ unsigned __int16 uMight;
+    /* 00BE */ unsigned __int16 uMightBonus;
+    /* 00C0 */ unsigned __int16 uIntelligence;
+    /* 00C2 */ unsigned __int16 uIntelligenceBonus;
+    /* 00C4 */ unsigned __int16 uWillpower;
+    /* 00C6 */ unsigned __int16 uWillpowerBonus;
+    /* 00C8 */ unsigned __int16 uEndurance;
+    /* 00CA */ unsigned __int16 uEnduranceBonus;
+    /* 00CC */ unsigned __int16 uSpeed;
+    /* 00CE */ unsigned __int16 uSpeedBonus;
+    /* 00D0 */ unsigned __int16 uAccuracy;
+    /* 00D2 */ unsigned __int16 uAccuracyBonus;
+    /* 00D4 */ unsigned __int16 uLuck;
+    /* 00D6 */ unsigned __int16 uLuckBonus;
+    /* 00D8 */ __int16 sACModifier;
+    /* 00DA */ unsigned __int16 uLevel;
+    /* 00DC */ __int16 sLevelModifier;
+    /* 00DE */ __int16 sAgeModifier;
+    /* 00E0 */ int field_E0;
+    /* 00E4 */ int field_E4;
+    /* 00E8 */ int field_E8;
+    /* 00EC */ int field_EC;
+    /* 00F0 */ int field_F0;
+    /* 00F4 */ int field_F4;
+    /* 00F8 */ int field_F8;
+    /* 00FC */ int field_FC;
+    /* 0100 */ int field_100;
+    /* 0104 */ int field_104;
+    /* 0108 */ union
+    {
+        struct
+        {
+            unsigned __int16 skillStaff;
+            unsigned __int16 skillSword;
+            unsigned __int16 skillDagger;
+            unsigned __int16 skillAxe;
+            unsigned __int16 skillSpear;
+            unsigned __int16 skillBow;
+            unsigned __int16 skillMace;
+            unsigned __int16 skillBlaster;
+            unsigned __int16 skillShield;
+            unsigned __int16 skillLeather;
+            unsigned __int16 skillChain;
+            unsigned __int16 skillPlate;
+            unsigned __int16 skillFire;
+            unsigned __int16 skillAir;
+            unsigned __int16 skillWater;
+            unsigned __int16 skillEarth;
+            unsigned __int16 skillSpirit;
+            unsigned __int16 skillMind;
+            unsigned __int16 skillBody;
+            unsigned __int16 skillLight;
+            unsigned __int16 skillDark;
+            unsigned __int16 skillItemId;
+            unsigned __int16 skillMerchant;
+            unsigned __int16 skillRepair;
+            unsigned __int16 skillBodybuilding;
+            unsigned __int16 skillMeditation;
+            unsigned __int16 skillPerception;
+            unsigned __int16 skillDiplomacy;
+            unsigned __int16 skillThievery;
+            unsigned __int16 skillDisarmTrap;
+            unsigned __int16 skillDodge;
+            unsigned __int16 skillUnarmed;
+            unsigned __int16 skillMonsterId;
+            unsigned __int16 skillArmsmaster;
+            unsigned __int16 skillStealing;
+            unsigned __int16 skillAlchemy;
+            unsigned __int16 skillLearning;
+        };
+        unsigned __int16 pActiveSkills[37];
+    };
+    /* 0152 */ unsigned char _achieved_awards_bits[64];
+    /* 0192 */ PlayerSpells_Image_MM7 spellbook;
+    /* 01F6 */ char _1F6_pad[2];
+    /* 01F8 */ int pure_luck_used;
+    /* 01FC */ int pure_speed_used;
+    /* 0200 */ int pure_intellect_used;
+    /* 0204 */ int pure_endurance_used;
+    /* 0208 */ int pure_willpower_used;
+    /* 020C */ int pure_accuracy_used;
+    /* 0210 */ int pure_might_used;
+    /* 0214 */ union
+    {
+        struct
+        {
+            ItemGen_Image_MM7 pInventoryItemList[126];
+            ItemGen_Image_MM7 pEquippedItems[12];
+        };
+        struct
+        {
+            ItemGen_Image_MM7 pOwnItems[138];
+        };
+    };
+    /* 157C */ int pInventoryMatrix[126];
+    /* 1774 */ __int16 sResFireBase;
+    /* 1776 */ __int16 sResAirBase;
+    /* 1778 */ __int16 sResWaterBase;
+    /* 177A */ __int16 sResEarthBase;
+    /* 177C */ __int16 field_177C;
+    /* 177E */ __int16 sResMagicBase;
+    /* 1780 */ __int16 sResSpiritBase;
+    /* 1782 */ __int16 sResMindBase;
+    /* 1784 */ __int16 sResBodyBase;
+    /* 1786 */ __int16 sResLightBase;
+    /* 1788 */ __int16 sResDarkBase;
+    /* 178A */ __int16 sResFireBonus;
+    /* 178C */ __int16 sResAirBonus;
+    /* 178E */ __int16 sResWaterBonus;
+    /* 1790 */ __int16 sResEarthBonus;
+    /* 1792 */ __int16 field_1792;
+    /* 1794 */ __int16 sResMagicBonus;
+    /* 1796 */ __int16 sResSpiritBonus;
+    /* 1798 */ __int16 sResMindBonus;
+    /* 179A */ __int16 sResBodyBonus;
+    /* 179C */ __int16 sResLightBonus;
+    /* 179E */ __int16 sResDarkBonus;
+    /* 17A0 */ SpellBuff_Image_MM7 pPlayerBuffs[24];
+    /* 1920 */ unsigned int uVoiceID;
+    /* 1924 */ int uPrevVoiceID;
+    /* 1928 */ int uPrevFace;
+    /* 192C */ int field_192C;
+    /* 1930 */ int field_1930;
+    /* 1934 */ unsigned __int16 uTimeToRecovery;
+    /* 1936 */ char field_1936;
+    /* 1937 */ char field_1937;
+    /* 1938 */ unsigned int uSkillPoints;
+    /* 193C */ int sHealth;
+    /* 1940 */ int sMana;
+    /* 1944 */ unsigned int uBirthYear;
+    /* 1948 */ PlayerEquipment_Image_MM7 pEquipment;
+    /* 1988 */ int field_1988[49];
+    /* 1A4C */ char field_1A4C;
+    /* 1A4D */ char field_1A4D;
+    /* 1A4E */ char lastOpenedSpellbookPage;
+    /* 1A4F */ unsigned __int8 uQuickSpell;
+    /* 1A50 */ char playerEventBits[64];
+    /* 1A90 */ char _some_attack_bonus;
+    /* 1A91 */ char field_1A91;
+    /* 1A92 */ char _melee_dmg_bonus;
+    /* 1A93 */ char field_1A93;
+    /* 1A94 */ char _ranged_atk_bonus;
+    /* 1A95 */ char field_1A95;
+    /* 1A96 */ char _ranged_dmg_bonus;
+    /* 1A97 */ char field_1A97;
+    /* 1A98 */ char uFullHealthBonus;
+    /* 1A99 */ char _health_related;
+    /* 1A9A */ char uFullManaBonus;
+    /* 1A9B */ char _mana_related;
+    /* 1A9C */ unsigned __int16 expression;
+    /* 1A9E */ unsigned __int16 uExpressionTimePassed;
+    /* 1AA0 */ unsigned __int16 uExpressionTimeLength;
+    /* 1AA2 */ __int16 field_1AA2;
+    /* 1AA4 */ int _expression21_animtime;
+    /* 1AA8 */ int _expression21_frameset;
+    /* 1AAC */ LloydBeacon_Image_MM7 pInstalledBeacons[5];
+    /* 1B38 */ char uNumDivineInterventionCastsThisDay;
+    /* 1B39 */ char uNumArmageddonCasts;
+    /* 1B3A */ char uNumFireSpikeCasts;
+    /* 1B3B */ char field_1B3B;
+    /* 1B3C */
+};
+
+
+struct PartyTimeStruct_Image_MM7
+{
+    PartyTimeStruct_Image_MM7();
+
+    /* 000 */ __int64 bountyHunting_next_generation_time[10];
+    /* 050 */ __int64 Shops_next_generation_time[85];//field_50
+    /* 2F8 */ __int64 _shop_ban_times[53];
+    /* 4A0 */ unsigned __int64 CounterEventValues[10];  // (0xACD314h in Silvo's binary)
+    /* 4F0 */ __int64 HistoryEventTimes[29];   // (0xACD364h in Silvo's binary)
+    /* 5D8 */ unsigned __int64 _s_times[20]; //5d8 440h+8*51     //(0xACD44Ch in Silvo's binary)
+    /* 678 */
+};
+
+struct Party_Image_MM7
+{
+    Party_Image_MM7();
+
+    void Serialize(struct Party *);
+    void Deserialize(struct Party *);
+
+    /* 00000 */ int field_0;
+    /* 00004 */ unsigned int uPartyHeight;
+    /* 00008 */ unsigned int uDefaultPartyHeight;
+    /* 0000C */ int sEyelevel;
+    /* 00010 */ unsigned int uDefaultEyelevel;
+    /* 00014 */ int field_14_radius;
+    /* 00018 */ int y_rotation_granularity;
+    /* 0001C */ unsigned int uWalkSpeed;
+    /* 00020 */ int y_rotation_speed;  // deg/s
+    /* 00024 */ int field_24;
+    /* 00028 */ int field_28;
+    /* 0002C */ unsigned __int64 uTimePlayed;
+    /* 00034 */ __int64 uLastRegenerationTime;
+    /* 0003C */ PartyTimeStruct_Image_MM7 PartyTimes;
+    /* 006B4 */ Vec3_int_ vPosition;
+    /* 006C0 */ int sRotationY;
+    /* 006C4 */ int sRotationX;
+    /* 006C8 */ Vec3_int_ vPrevPosition;
+    /* 006D4 */ int sPrevRotationY;
+    /* 006D8 */ int sPrevRotationX;
+    /* 006DC */ int sPrevEyelevel;
+    /* 006E0 */ int field_6E0;
+    /* 006E4 */ int field_6E4;
+    /* 006E8 */ int uFallSpeed;
+    /* 006EC */ int field_6EC;
+    /* 006F0 */ int field_6F0;
+    /* 006F4 */ int floor_face_pid; // face we are standing at
+    /* 006F8 */ int walk_sound_timer;
+    /* 006FC */ int field_6FC;
+    /* 00700 */ int uFallStartY;
+    /* 00704 */ unsigned int bFlying;
+    /* 00708 */ char field_708;
+    /* 00709 */ unsigned __int8 hirelingScrollPosition;
+    /* 0070A */ char field_70A;
+    /* 0070B */ char field_70B;
+    /* 0070C */ unsigned int uCurrentYear;
+    /* 00710 */ unsigned int uCurrentMonth;
+    /* 00714 */ unsigned int uCurrentMonthWeek;
+    /* 00718 */ unsigned int uDaysPlayed;
+    /* 0071C */ unsigned int uCurrentHour;
+    /* 00720 */ unsigned int uCurrentMinute;
+    /* 00724 */ unsigned int uCurrentTimeSecond;
+    /* 00728 */ unsigned int uNumFoodRations;
+    /* 0072C */ int field_72C;
+    /* 00730 */ int field_730;
+    /* 00734 */ unsigned int uNumGold;
+    /* 00738 */ unsigned int uNumGoldInBank;
+    /* 0073C */ unsigned int uNumDeaths;
+    /* 00740 */ int field_740;
+    /* 00744 */ int uNumPrisonTerms;
+    /* 00748 */ unsigned int uNumBountiesCollected;
+    /* 0074C */ int field_74C;
+    /* 00750 */ __int16 monster_id_for_hunting[5];
+    /* 0075A */ __int16 monster_for_hunting_killed[5];
+    /* 00764 */ unsigned char days_played_without_rest;
+    /* 00765 */ unsigned __int8 _quest_bits[64];
+    /* 007A5 */ unsigned __int8 pArcomageWins[16];
+    /* 007B5 */ char field_7B5_in_arena_quest;
+    /* 007B6 */ char uNumArenaPageWins;
+    /* 007B7 */ char uNumArenaSquireWins;
+    /* 007B8 */ char uNumArenaKnightWins;
+    /* 007B9 */ char uNumArenaLordWins;
+    /* 007BA */ char pIsArtifactFound[29];  //7ba
+    /* 007D7 */ char field_7d7[39];
+    /* 007FE */ unsigned char _autonote_bits[26];
+    /* 00818 */ char field_818[60];
+    /* 00854 */ char field_854[32];
+    /* 00874 */ int uNumArcomageWins;
+    /* 00878 */ int uNumArcomageLoses;
+    /* 0087C */ unsigned int bTurnBasedModeOn;
+    /* 00880 */ int field_880;
+    /* 00884 */ int uFlags2;
+    /* 00888 */ unsigned int alignment;
+    /* 0088C */ SpellBuff_Image_MM7 pPartyBuffs[20];
+    /* 00954 */ Player_Image_MM7 pPlayers[4];
+    /* 07644 */ NPCData_Image_MM7 pHirelings[2];
+    /* 07754 */ ItemGen_Image_MM7 pPickedItem;
+    /* 07778 */ unsigned int uFlags;
+    /* 0777C */ ItemGen_Image_MM7 StandartItemsInShops[53][12];
+    /* 0D0EC */ ItemGen_Image_MM7 SpecialItemsInShops[53][12];
+    /* 12A5C */ ItemGen_Image_MM7 SpellBooksInGuilds[32][12];
+    /* 1605C */ char field_1605C[24];
+    /* 16074 */ char pHireling1Name[100];
+    /* 160D8 */ char pHireling2Name[100];
+    /* 1613C */ int armageddon_timer;
+    /* 16140 */ int armageddonDamage;
+    /* 16144 */ int pTurnBasedPlayerRecoveryTimes[4];
+    /* 16154 */ int InTheShopFlags[53];
+    /* 16228 */ int uFine;
+    /* 1622C */ float flt_TorchlightColorR;
+    /* 16230 */ float flt_TorchlightColorG;
+    /* 16234 */ float flt_TorchlightColorB;
+    /* 16238 */
+};
+
+
+
+struct Timer_Image_MM7
+{
+    Timer_Image_MM7();
+
+    void Serialize(struct Timer *);
+    void Deserialize(struct Timer *);
+
+    /* 00 */ unsigned int bReady;
+    /* 04 */ unsigned int bPaused;
+    /* 08 */ int bTackGameTime;
+    /* 0C */ unsigned int uStartTime;
+    /* 10 */ unsigned int uStopTime;
+    /* 14 */ int uGameTimeStart;
+    /* 18 */ int field_18;
+    /* 1C */ unsigned int uTimeElapsed;
+    /* 20 */ int dt_in_some_format;
+    /* 24 */ unsigned int uTotalGameTimeElapsed;
+    /* 28 */
+};
+
+
+
+
+/*  282 */
+struct OtherOverlay_Image_MM7
+{
+    OtherOverlay_Image_MM7();
+
+    /* 00 */ __int16 field_0;
+    /* 02 */ __int16 field_2;
+    /* 04 */ __int16 field_4;
+    /* 06 */ __int16 field_6;
+    /* 08 */ __int16 field_8;
+    /* 0A */ __int16 field_A;
+    /* 0C */ __int16 field_C;
+    /* 0E */ __int16 field_E;
+    /* 10 */ int field_10;
+    /* 14 */
+};
+
+/*   63 */
+struct OtherOverlayList_Image_MM7
+{
+    OtherOverlayList_Image_MM7();
+
+    void Serialize(struct OtherOverlayList *);
+    void Deserialize(struct OtherOverlayList *);
+
+    /* 000 */ OtherOverlay_Image_MM7 pOverlays[50];
+    /* 3E8 */ int field_3E8;
+    /* 3EC */ int bRedraw;
+    /* 3F0 */
+};
+
+#pragma pack(pop)
\ No newline at end of file
--- a/Game/CreateParty.cpp	Wed May 20 00:56:07 2015 +0200
+++ b/Game/CreateParty.cpp	Wed May 20 15:12:33 2015 +0200
@@ -182,12 +182,18 @@
         if (pAudioPlayer->hAILRedbook)
             AIL_redbook_stop(pAudioPlayer->hAILRedbook);
     }
+
     pParty->Reset();
-    pOtherOverlayList->Reset();
-    strcpy(pCurrentMapName, pStartingMapName);
-    pParty->CreateDefaultParty(0);
+    pParty->CreateDefaultParty();
 
-    pGUIWindow_CurrentMenu = new GUIWindow_PartyCreation();//PlayerCreationUI_Initialize();
+    _449B7E_toggle_bit(pParty->_quest_bits, PARTY_QUEST_EMERALD_RED_POTION_ACTIVE, 1);
+    _449B7E_toggle_bit(pParty->_quest_bits, PARTY_QUEST_EMERALD_SEASHELL_ACTIVE, 1);
+    _449B7E_toggle_bit(pParty->_quest_bits, PARTY_QUEST_EMERALD_LONGBOW_ACTIVE, 1);
+    _449B7E_toggle_bit(pParty->_quest_bits, PARTY_QUEST_EMERALD_PLATE_ACTIVE, 1);
+    _449B7E_toggle_bit(pParty->_quest_bits, PARTY_QUEST_EMERALD_LUTE_ACTIVE, 1);
+    _449B7E_toggle_bit(pParty->_quest_bits, PARTY_QUEST_EMERALD_HAT_ACTIVE, 1);
+
+    pGUIWindow_CurrentMenu = new GUIWindow_PartyCreation();
     if (PlayerCreationUI_Loop())
     {
         DeleteCCharFont();