changeset 252:e22e2357c8b3

Merge
author Gloval
date Mon, 18 Feb 2013 08:59:34 +0400
parents 48f21f569328 (current diff) 83f85ab6079a (diff)
children f1218b9d67f1
files NPC.h mm7_3.cpp mm7_data.h
diffstat 13 files changed, 236 insertions(+), 203 deletions(-) [+]
line wrap: on
line diff
--- a/Actor.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/Actor.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -200,7 +200,7 @@
   pDialogueNPCPortraits[0] = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE)];
   dword_591084 = areWeLoadingTexture;
   uTextureID_507B04 = uTextureID_right_panel;
-  if ( !(v5->uFlags & 0x80) && v5->house >= 0 )
+  if ( !v5->Hired() && v5->house >= 0 )
   {
     if ( (signed int)pParty->GetPartyFame() <= v5->fame
       || (v10 = v5->uFlags & 0xFFFFFF7F, (v5->uFlags & 0xFFFFFF7F & 0x80000000u) != 0) )
@@ -241,7 +241,7 @@
     v9 = 4;
   v11 = GUIWindow::Create(0, 0, 640, 480, (enum WindowType)10, v9, 0);
   pDialogueWindow = v11;
-  if ( v5->uFlags & 0x80 )
+  if (v5->Hired())
   {
     if ( !v5->bHasUsedTheAbility )
     {
@@ -271,7 +271,7 @@
   pDialogueWindow->CreateButton(177u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 2u, 0x32u, "", 0);
   pDialogueWindow->CreateButton(292u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 3u, 0x33u, "", 0);
   pDialogueWindow->CreateButton(407u, 424u, 0x1Fu, 0x28u, 2, 94, 0x6Eu, 4u, 0x34u, "", 0);
-  if ( v17 && uActiveCharacter && !(v5->uFlags & 0x80) )
+  if (v17 && uActiveCharacter && !v5->Hired())
   {
     if (pParty->uCurrentHour < 5 || pParty->uCurrentHour > 21)
       pPlayers[uActiveCharacter]->PlaySound(SPEECH_GoodEvening, 0);
--- a/GUIWindow.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/GUIWindow.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -1909,7 +1909,7 @@
               if ( v12->joins )
               {
                 pWindow->CreateButton(0x1E0u, 0x82u, 0x8Cu, v11, 1, 0, 0x88u, 0x4Du, 0, pGlobalTXT_LocalizationStrings[407], 0);//Подробнее
-                if ( v12->uFlags & 0x80 )
+                if (v12->Hired())
                 {
                   sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[408], v12->pName); //Отпустить
                   pWindow->CreateButton(0x1E0u, v11 + 130, 0x8Cu, v11, 1, 0, 0x88u, 0x4Cu, 0, pTmpBuf, 0);
--- a/GUIWindow.h	Mon Feb 18 08:47:21 2013 +0400
+++ b/GUIWindow.h	Mon Feb 18 08:59:34 2013 +0400
@@ -25,10 +25,17 @@
 
 enum DIALOGUE_TYPE
 {
+  DIALOGUE_9 = 9,
   DIALOGUE_13 = 0xD,
   DIALOGUE_18 = 0x12,
+  DIALOGUE_19 = 19,
+  DIALOGUE_20 = 20,
+  DIALOGUE_21 = 21,
+  DIALOGUE_22 = 22,
+  DIALOGUE_23 = 23,
   DIALOGUE_24 = 0x18,
-  DIALOGUE_77 = 0x4D,
+  DIALOGUE_76 = 76,
+  DIALOGUE_PROFESSION_DETAILS = 77,
   DIALOGUE_ARENA_WELCOME = 0x59,
   DIALOGUE_ARENA_FIGHT_NOT_OVER_YET = 0x5A,
   DIALOGUE_ARENA_REWARD = 0x5B,
@@ -230,7 +237,7 @@
   UIMSG_85 = 0x85,
   UIMSG_StartHireling1Dialogue = 0x86,
   UIMSG_StartHireling2Dialogue = 0x87,
-  UIMSG_88 = 0x88,
+  UIMSG_SelectDialogueOption = 0x88,
   UIMSG_8C = 0x8C,
   UIMSG_8D = 0x8D,
   UIMSG_8E = 0x8E,
@@ -388,6 +395,11 @@
 
 
 
+
+void OnSelectDialogueOption(DIALOGUE_TYPE newDialogueType);
+
+
+
 extern int pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[]; // idb
 extern struct GUIWindow *pWindow_MainMenu;
 extern struct GUIWindow pWindowList[20];
\ No newline at end of file
--- a/NPC.h	Mon Feb 18 08:47:21 2013 +0400
+++ b/NPC.h	Mon Feb 18 08:59:34 2013 +0400
@@ -17,9 +17,11 @@
 #pragma pack(push, 1)
 struct NPCData
 {
+  inline bool Hired() {return uFlags & 0x80;}
+
   char *pName;
   unsigned int uPortraitID;
-  unsigned int uFlags;         // & 0x80    no greeting on dialogue start
+  unsigned int uFlags;         // & 0x80    no greeting on dialogue start; looks like hired
   int fame;
   int rep;
   int house;
--- a/Player.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/Player.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -586,7 +586,7 @@
   signed int v13; // esi@12
   int v14; // eax@12
   //int v15; // eax@17
-  int pExpression; // ebx@17
+  CHARACTER_EXPRESSION_ID expression; // ebx@17
   signed int v17; // ecx@19
   char *pSoundID; // edi@20
   int v20[5]; // [sp+Ch] [bp-1Ch]@7
@@ -647,8 +647,8 @@
   if ( v13 )
   {
     pPlayerNum = 0;
-    pExpression = v20[rand() % v13];
-    if ( pExpression == 21 && pSoundId )
+    expression = (CHARACTER_EXPRESSION_ID)v20[rand() % v13];
+    if (expression == CHARACTER_EXPRESSION_21 && pSoundId )
     {
       v17 = 0;
       if ( (signed int)pSoundList->uNumSounds <= 0 )
@@ -670,7 +670,7 @@
       if ( pSoundList->pSounds[v17].pSoundData[0] )
         pPlayerNum = (sLastTrackLengthMS << 7) / 1000;
     }
-    /*LOWORD(v14) = */PlayEmotion((CHARACTER_EXPRESSION_ID)pExpression, pPlayerNum);
+    /*LOWORD(v14) = */PlayEmotion(expression, pPlayerNum);
   }
   //return v14;
 }
@@ -5758,7 +5758,7 @@
         }
         if ( CheckHiredNPCSpeciality(v5) )
           v2 += 4;
-        if ( v9->classType == PLAYER_CLASS_31 && sub_476387() )
+        if ( v9->classType == PLAYER_CLASS_31 && PartyHasDragon() )
           v2 += 3;
 LABEL_86:
         if ( uSkillType <= PLAYER_SKILL_DARK )
@@ -7892,7 +7892,7 @@
         LOBYTE(v6) = CheckHiredNPCSpeciality(a1);
         return v6;
       case VAR_NPCs2:
-        return pNPCStats->pNewNPCData[a1].uFlags & 0x80;
+        return pNPCStats->pNewNPCData[a1].Hired();
       case VAR_MonthEquals|VAR_CurrentSP:
         v13 = 0x80u >> ((signed __int16)a1 - 1) % 8;
         v14 = this->field_1A50[((signed __int16)a1 - 1) >> 3];
--- a/Player.h	Mon Feb 18 08:47:21 2013 +0400
+++ b/Player.h	Mon Feb 18 08:59:34 2013 +0400
@@ -47,7 +47,7 @@
   SPEECH_35 = 35,
   SPEECH_36 = 36,
   SPEECH_37 = 37,
-  SPEECH_38 = 38,
+  SPEECH_NotEnoughGold = 38,
   SPEECH_39 = 39,
   SPEECH_40 = 40,
   SPEECH_41 = 41,
--- a/mm7_1.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/mm7_1.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -3701,7 +3701,7 @@
                                    pParty->vPosition.x,
                                    pParty->vPosition.y,
                                    pParty->vPosition.z);
-  if ( sub_476387() )
+  if ( PartyHasDragon() )
   {
     v0 = pParty->pPlayers;//[0].uClass;
 	while ( v0 <= &pParty->pPlayers[3] )
--- a/mm7_3.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/mm7_3.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -4703,6 +4703,11 @@
   return result;
 }
 
+//----- (00476387) --------------------------------------------------------
+bool PartyHasDragon()
+{
+  return pNPCStats->pNewNPCData[57].Hired();
+}
 
 
 // 47730C: using guessed type int __stdcall const_1(int);
@@ -15041,7 +15046,7 @@
   unsigned __int16 v2; // di@2
   //unsigned int v3; // eax@2
   char *v4; // esi@3
-  int v5; // eax@11
+  //int v5; // eax@11
   char *v6; // ecx@13
   char *v7; // eax@16
   unsigned int v8; // edi@19
@@ -15099,16 +15104,86 @@
   pRenderer->DrawTextureTransparent(468, 0, (Texture *)(uTextureID_507B04 != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_507B04] : 0));
   pRenderer->DrawTextureIndexed(pNPCPortraits_x - 4, pNPCPortraits_y - 4, (Texture *)(uTextureID_50795C != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_50795C] : 0));
   pRenderer->DrawTextureIndexed(pNPCPortraits_x, pNPCPortraits_y, pDialogueNPCPortraits[0]);
-  if ( pNPC->uProfession )
-  {
-    sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[429], pNPC->pName, aNPCProfessionNames[pNPC->uProfession]);//^Pi[%s] %s
-  }
-  else
-  {
+
+  if (pNPC->uProfession)
+  {
+    assert(pNPC->uProfession < sizeof(aNPCProfessionNames) / sizeof(*aNPCProfessionNames)); // sometimes buffer overflows; errors emerge both here and in dialogue text
+    sprintfex(pTmpBuf, pGlobalTXT_LocalizationStrings[429], pNPC->pName, aNPCProfessionNames[pNPC->uProfession]);//^Pi[%s] %s
+  }
+  else
     strcpy(pTmpBuf, pNPC->pName);
-  }
+
   v51.DrawTitleText(pFontArrus, 483, 112, v2, pTmpBuf, 3);
   pParty->GetPartyFame();
+
+  switch (uDialogueType)
+  {
+    case DIALOGUE_PROFESSION_DETAILS:
+    {
+          if (dialogue_show_profession_details)
+          {
+            v6 = pNPCStats->pProfessions[pNPC->uProfession - 1].pBenefits;
+            v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
+            pInString = v7;
+            pWindow.uFrameWidth = 460;
+            pWindow.uFrameZ = 452;
+            pOutString = pFontArrus;
+            v12 = pFontArrus->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
+            if ( 352 - v12 < 8 )
+            {
+              pOutString = pFontCreate;
+              v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
+            }
+            if (uTextureID_Leather != -1)
+              pRenderer->_4A6A68(8, 352 - v12, &pIcons_LOD->pTextures[uTextureID_Leather], pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight - v12);
+            pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
+            v13 = FitTextInAWindow(pInString, pOutString, &pWindow, 0xDu, 0);
+            pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
+          }
+          else if (pNPC->Hired())
+          {
+            v6 = pNPCStats->pProfessions[pNPC->uProfession - 1].pDismissText;
+            v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
+            pInString = v7;
+            pWindow.uFrameWidth = 460;
+            pWindow.uFrameZ = 452;
+            pOutString = pFontArrus;
+            v12 = pFontArrus->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
+            if ( 352 - v12 < 8 )
+            {
+              pOutString = pFontCreate;
+              v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
+            }
+            if (uTextureID_Leather != -1)
+              pRenderer->_4A6A68(8, 352 - v12, &pIcons_LOD->pTextures[uTextureID_Leather], pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight - v12);
+            pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
+            v13 = FitTextInAWindow(pInString, pOutString, &pWindow, 0xDu, 0);
+            pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
+          }
+		  else
+		  {
+            v6 = pNPCStats->pProfessions[pNPC->uProfession - 1].pJoinText;
+			v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
+			pInString = v7;
+			pWindow.uFrameWidth = 460;
+			pWindow.uFrameZ = 452;
+			pOutString = pFontArrus;
+			v12 = pFontArrus->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
+			if ( 352 - v12 < 8 )
+			{
+			pOutString = pFontCreate;
+			v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
+			}
+            if (uTextureID_Leather != -1)
+              pRenderer->_4A6A68(8, 352 - v12, &pIcons_LOD->pTextures[uTextureID_Leather], pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight - v12);
+			pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
+			v13 = FitTextInAWindow(pInString, pOutString,  &pWindow, 0xDu, 0);
+			pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
+		  }
+    }
+    break;
+  }
+
   if ( (signed int)uDialogueType > DIALOGUE_ARENA_WELCOME )
   {
     if ( uDialogueType == DIALOGUE_ARENA_FIGHT_NOT_OVER_YET )
@@ -15189,8 +15264,7 @@
     }
     else if ( uDialogueType == DIALOGUE_13 )
     {
-      v5 = 5 * pNPC->uProfession;
-      v6 = (char *)*(&pNPCStats->field_13A64 + v5);
+      v6 = pNPCStats->pProfessions[pNPC->uProfession - 1].pJoinText;
       v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
       pInString = v7;
       pWindow.uFrameWidth = 460;
@@ -15202,79 +15276,15 @@
         pOutString = pFontCreate;
         v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
       }
-      pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
+      pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : 0),
         (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v12);
       pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
       v13 = FitTextInAWindow(pInString, pOutString, &pWindow, 0xDu, 0);
       pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
     }
-    else if ( (signed int)uDialogueType > DIALOGUE_18 && !((signed int)uDialogueType > DIALOGUE_24 && uDialogueType != DIALOGUE_77 || byte_5B0938[0]) )
-    {
-      if ( (signed int)uDialogueType > DIALOGUE_24 && uDialogueType == DIALOGUE_77 )
-      {
-          v5 = 5 * pNPC->uProfession;
-          if ( byte_F8B1EC )
-          {
-            v6 = (char *)*(&pNPCStats->field_13A5C + 5 * pNPC->uProfession);
-            v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
-            pInString = v7;
-            pWindow.uFrameWidth = 460;
-            pWindow.uFrameZ = 452;
-            pOutString = pFontArrus;
-            v12 = pFontArrus->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
-            if ( 352 - v12 < 8 )
-            {
-              pOutString = pFontCreate;
-              v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
-            }
-            pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
-                              (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v12);
-            pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
-            v13 = FitTextInAWindow(pInString, pOutString, &pWindow, 0xDu, 0);
-            pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
-          }
-          else if ( pNPC->uFlags & 0x80 )
-          {
-            v6 = (char *)*(&pNPCStats->field_13A68 + 5 * pNPC->uProfession);
-            v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
-            pInString = v7;
-            pWindow.uFrameWidth = 460;
-            pWindow.uFrameZ = 452;
-            pOutString = pFontArrus;
-            v12 = pFontArrus->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
-            if ( 352 - v12 < 8 )
-            {
-              pOutString = pFontCreate;
-              v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
-            }
-            pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
-                               (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v12);
-            pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
-            v13 = FitTextInAWindow(pInString, pOutString, &pWindow, 0xDu, 0);
-            pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
-          }
-		  else
-		  {
-			v6 = (char *)*(&pNPCStats->field_13A64 + v5);
-			v7 = sub_495461(v6, uActiveCharacter - 1, 0, 0, 0, 0);
-			pInString = v7;
-			pWindow.uFrameWidth = 460;
-			pWindow.uFrameZ = 452;
-			pOutString = pFontArrus;
-			v12 = pFontArrus->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
-			if ( 352 - v12 < 8 )
-			{
-			pOutString = pFontCreate;
-			v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
-			}
-			pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
-										(uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v12);
-			pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
-			v13 = FitTextInAWindow(pInString, pOutString,  &pWindow, 0xDu, 0);
-			pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
-		  }
-      }
-	  else
+    else if ( (signed int)uDialogueType > DIALOGUE_18 && !((signed int)uDialogueType > DIALOGUE_24 && uDialogueType != DIALOGUE_PROFESSION_DETAILS || byte_5B0938[0]) )
+    {
+	  if ((signed int)uDialogueType <= DIALOGUE_23)
 	  {
 		  v7 = (char *)ptr_F8B1E8;
 		  pInString = v7;
@@ -15287,7 +15297,7 @@
 			pOutString = pFontCreate;
 			v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
 		  }
-		  pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
+		  pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? &pIcons_LOD->pTextures[uTextureID_Leather] : 0),
 			(uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v12);
 		  pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
 		  v13 = FitTextInAWindow(pInString, pOutString, &pWindow, 0xDu, 0);
@@ -15326,10 +15336,10 @@
 		{
 			if ( *(int *)v54 == 2 )
 			{
-				if ( pNPC->uFlags & 0x80 )
-					v9 = (char *)pNPCStats->pProfessions[pNPC->uProfession].pDismissText;
+				if (pNPC->Hired())
+					v9 = pNPCStats->pProfessions[pNPC->uProfession].pDismissText;
 				else
-					v9 = (char *)pNPCStats->pProfessions[pNPC->uProfession].pJoinText; //"Invalid String Passed"
+					v9 = pNPCStats->pProfessions[pNPC->uProfession].pJoinText; //"Invalid String Passed"
 				pInString = sub_495461(v9, uActiveCharacter - 1, 0, 0, 0, 0);
 				if (  pInString != NULL )
 				{
@@ -15342,8 +15352,8 @@
 						pOutString = pFontCreate;
 						v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
 					}
-					pRenderer->_4A6A68(8, 352 - v12, (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
-					(uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v12);
+                    if (uTextureID_Leather != -1)
+                      pRenderer->_4A6A68(8, 352 - v12, &pIcons_LOD->pTextures[uTextureID_Leather], pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight - v12);
 					pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
 					v13 = FitTextInAWindow(pInString, pOutString, &pWindow, 0xDu, 0);
 					pDialogueWindow->DrawText(pOutString, 13, 354 - v12, 0, v13, 0, 0, 0);
@@ -15371,24 +15381,24 @@
         v24 = "";
     }
 	else if ( v16 == 88 )
-		v24 = pGlobalTXT_LocalizationStrings[581];
+		v24 = pGlobalTXT_LocalizationStrings[581]; // Lord
     else if ( v16 == 87 )
-	    v24 = pGlobalTXT_LocalizationStrings[580];
+	    v24 = pGlobalTXT_LocalizationStrings[580]; // Knight
     else if ( v16 == 86 )
-	    v24 = pGlobalTXT_LocalizationStrings[579];
+	    v24 = pGlobalTXT_LocalizationStrings[579]; // Squire
     else if ( v16 == 85 )
-		v24 = pGlobalTXT_LocalizationStrings[578];
+		v24 = pGlobalTXT_LocalizationStrings[578]; // Page
     else if ( v16 == 77 )
-        v24 = pGlobalTXT_LocalizationStrings[407];
+        v24 = pGlobalTXT_LocalizationStrings[407]; // Details
     else if ( v16 == 76 )
     {
-		if ( pNPC->uFlags & 0x80 )
+		if (pNPC->Hired())
 		{
-			sprintf(pTmpBuf, (const char*)pGlobalTXT_LocalizationStrings[408], pNPC->pName);
+			sprintf(pTmpBuf, (const char*)pGlobalTXT_LocalizationStrings[408], pNPC->pName); // Release %s
 			v24 = pTmpBuf;
 		}
 		else
-			v24 = pGlobalTXT_LocalizationStrings[406];
+			v24 = pGlobalTXT_LocalizationStrings[406]; // Hire
     }
 	else if ( v16 == 24 )
     {
@@ -15454,13 +15464,13 @@
 	}
 	else if ( v16 == 13 )
 	{
-		if ( pNPC->uFlags & 0x80 )
+		if (pNPC->Hired())
 		{
-			sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[408], pNPC->pName);
+			sprintf(pTmpBuf, pGlobalTXT_LocalizationStrings[408], pNPC->pName); // Release %s
 			v24 = pTmpBuf;
 		}
 		else
-			v24 = pGlobalTXT_LocalizationStrings[122];
+			v24 = pGlobalTXT_LocalizationStrings[122]; // Join
 	}
 	else
 		v24 = "";
@@ -15661,7 +15671,7 @@
     {
       for (i = 0; i < pNPCStats->uNumNewNPCs; ++i)
       {
-        if (pNPCStats->pNewNPCData[i].uFlags & 0x80)
+        if (pNPCStats->pNewNPCData[i].Hired())
         {
           if (!pParty->pHirelings[0].pName || strcmp((char *)pNPCStats->pNewNPCData[i].pName, (char *)pParty->pHirelings[0].pName))
           {
@@ -15747,7 +15757,7 @@
       v16 = &pTmpBuf[v6];
       do
       {
-        if ( v9->uFlags & 0x80
+        if ( v9->Hired()
           && (!pParty->pHirelings[0].pName || strcmp(v9->pName, pParty->pHirelings[0].pName))
           && (!pParty->pHirelings[1].pName || strcmp(v9->pName, pParty->pHirelings[1].pName)) )
         {
@@ -15813,7 +15823,7 @@
     v8 = pNPCStats->pNewNPCData;
     do
     {
-      if ( v8->uFlags & 0x80 && (!pParty->pHirelings[0].pName || strcmp(v8->pName, pParty->pHirelings[0].pName)) )
+      if (v8->Hired() && (!pParty->pHirelings[0].pName || strcmp(v8->pName, pParty->pHirelings[0].pName)) )
       {
         if ( !pParty->pHirelings[1].pName || strcmp(v8->pName, pParty->pHirelings[1].pName) )
           *v7++ = v1 + 2;
@@ -18931,7 +18941,7 @@
   for (int i = 0; i < pNPCStats->uNumNewNPCs; ++i)
   {
     auto npc = pNPCStats->pNewNPCData + i;
-    if (npc->uFlags & 0x80 &&
+    if (npc->Hired() &&
         (!pParty->pHirelings[0].pName || strcmp(npc->pName, pParty->pHirelings[0].pName)))
     {
       if (!pParty->pHirelings[1].pName || strcmp(npc->pName, pParty->pHirelings[1].pName))
--- a/mm7_4.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/mm7_4.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -3519,7 +3519,7 @@
       }
     }
     v44 = 0;
-    if ( sub_476387() == 1 )
+    if (PartyHasDragon())
       v44 = 1;
     v49 = 0;
 LABEL_25:
@@ -4841,7 +4841,7 @@
   unsigned __int8 v6; // bl@1
   Player *pPlayer; // ebx@3
   NPCData *v9; // eax@4
-  size_t v10; // eax@6
+  //size_t v10; // eax@6
   char *v11; // esi@7
   int v12; // edx@7
   ItemGen *v13; // edi@7
@@ -4892,29 +4892,34 @@
   char a1[100]; // [sp+B8h] [bp-80h]@3
   unsigned int v59; // [sp+11Ch] [bp-1Ch]@3
   size_t v60; // [sp+120h] [bp-18h]@3
-  Player *v61; // [sp+124h] [bp-14h]@3
-  char *Str; // [sp+128h] [bp-10h]@1
+  //Player *v61; // [sp+124h] [bp-14h]@3
+  //char *Str; // [sp+128h] [bp-10h]@1
   int v63; // [sp+12Ch] [bp-Ch]@32
   int v64; // [sp+130h] [bp-8h]@6
   NPCData *v65; // [sp+134h] [bp-4h]@6
 
   v6 = uPlayerID;
-  Str = lpsz;
+  //Str = lpsz;
   if ( IsBadStringPtrA(lpsz, 1u) )
     return "Invalid String Passed";
-  v60 = strlen(Str);
+  v60 = strlen(lpsz);
   a1[0] = 0;
   pPlayer = &pParty->pPlayers[v6];
-  v59 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0x9Bu);
-  v61 = pPlayer;
+  v59 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(255, 255, 155);
+  //v61 = pPlayer;
   memset(pTmpBuf2, 0, 0x7D0u);
   if ( dword_5C35D4 )
+  {
+    __debugbreak(); // fix
     v9 = array_5913D8[(unsigned int)((char *)array_5913D8[6] + -(dword_591080 != 0) - 1)];
+  }
   else
     v9 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
   v65 = v9;
-  v10 = 0;
+  //v10 = 0;
   v64 = 0;
+
+  int i = 0;
   if ( (signed int)v60 > 0 )
   {
     v11 = a4;
@@ -4922,19 +4927,20 @@
     v13 = a3;
     while ( 1 )
     {
-      v14 = Str[v12];
-      if ( v14 == 37 )
+      v14 = lpsz[v12];
+      if ( v14 == '%' )
         break;
-      pTmpBuf2[v10++] = v14;
+      pTmpBuf2[i++] = v14;
 LABEL_119:
       ++v12;
       v64 = v12;
       if ( v12 >= (signed int)v60 )
         return pTmpBuf2;
     }
-    v15 = &Str[v12 + 1];
-    v16 = (unsigned __int8)Str[v12 + 2];
+    v15 = &lpsz[v12 + 1];
+    v16 = (unsigned __int8)lpsz[v12 + 2];
     v17 = v16 + 10 * (unsigned __int8)*v15 - 528;
+
     if ( v17 <= 15 )
     {
       if ( v17 != 15 )
@@ -4984,7 +4990,7 @@
           case 0x218:
             v19 = 0;
             v63 = 0;
-            v20 = (unsigned __int8 *)v61->field_152;
+            v20 = (unsigned __int8 *)pPlayer->field_152;
             do
             {
               if ( (unsigned __int16)_449B57_test_bit(v20, word_4EE150[v19]) )
@@ -5012,7 +5018,7 @@
             {
               v11 = (char *)pNPCTopics[55].pText;
             }
-            pPlayer = v61;
+            //pPlayer = v61;
             v13 = a3;
             goto LABEL_118;
           case 0x21A:
@@ -5060,7 +5066,8 @@
           case 0x21E:
             goto LABEL_93;
           case 0x214:
-            goto LABEL_117;
+            v11 = a1;
+            goto LABEL_118;
           default:
             goto LABEL_108;
         }
@@ -5069,7 +5076,7 @@
       v11 = pGlobalTXT_LocalizationStrings[393];// "daughter"
 LABEL_118:
       strcat(pTmpBuf2, v11);
-      v10 = strlen(pTmpBuf2);
+      i = strlen(pTmpBuf2);
       v64 += 2;
       v12 = v64;
       goto LABEL_119;
@@ -5110,7 +5117,6 @@
         {
           v46 = v13->GetDisplayName();
           sprintf(a1, format_4E2D80, v59, v46);
-LABEL_117:
           v11 = a1;
           goto LABEL_118;
         }
@@ -5156,7 +5162,8 @@
           strncpy(a1, v15, 2u);
           v51 = atoi(a1);
           sprintf(a1, "%lu", v51);
-          goto LABEL_117;
+          v11 = a1;
+          goto LABEL_118;
         }
         v26 = &p2DEvents[(signed int)a4 - 1].fPriceMultiplier;
         v27 = *v26;
@@ -5200,7 +5207,8 @@
           }
 LABEL_98:
           sprintf(a1, "%lu", v29);
-          goto LABEL_117;
+          v11 = a1;
+          goto LABEL_118;
         }
         v34 = *v26;
       }
@@ -5234,9 +5242,9 @@
             v54 = v56.field_18;
             v53 = v56.field_C + 1;
             v50 = v56.field_14;
-LABEL_116:
             sprintf(a1, pGlobalTXT_LocalizationStrings[378], aMonthNames[v50], v53, v54);
-            goto LABEL_117;
+            v11 = a1;
+            goto LABEL_118;
           }
           v52 = pPlayers[4];
           break;
@@ -5250,7 +5258,9 @@
     v54 = v57.field_18;
     v53 = v57.field_C + 1;
     v50 = v57.field_14;
-    goto LABEL_116;
+    sprintf(a1, pGlobalTXT_LocalizationStrings[378], aMonthNames[v50], v53, v54);
+    v11 = a1;
+    goto LABEL_118;
   }
   return pTmpBuf2;
 }
@@ -9404,7 +9414,7 @@
   char *v17; // ecx@63
   char *v18; // eax@65
   const char *v19; // ecx@68
-  unsigned int v20; // eax@69
+  //unsigned int v20; // eax@69
   unsigned int v21; // ecx@70
   char *v22; // [sp-Ch] [bp-18h]@73
   int v23; // [sp-8h] [bp-14h]@49
@@ -9427,7 +9437,7 @@
         ptr_F8B1E8 = (char *)*(&pNPCStats->field_13A64 + 5 * v2->uProfession);
         ptr_F8B1E8 = sub_495461((char *)ptr_F8B1E8, uActiveCharacter - 1, 0, 0, 0, 0);
         sub_4B40E6();
-        byte_F8B1EC = 0;
+        dialogue_show_profession_details = false;
         goto _return;
       }
       switch ( a1 )
@@ -9494,13 +9504,13 @@
     if ( a1 == 77 )
     {
       v16 = v2->uProfession;
-      if ( byte_F8B1EC )
-        v17 = (char *)*(&pNPCStats->field_13A64 + 5 * v16);
+      if (dialogue_show_profession_details)
+        v17 = pNPCStats->pProfessions[v2->uProfession - 1].pJoinText;
       else
-        v17 = (char *)*(&pNPCStats->field_13A5C + 5 * v16);
+        v17 = pNPCStats->pProfessions[v2->uProfession - 1].pBenefits;
       ptr_F8B1E8 = v17;
       v18 = sub_495461(v17, uActiveCharacter - 1, 0, 0, 0, 0);
-      byte_F8B1EC ^= 1u;
+      dialogue_show_profession_details = ~dialogue_show_profession_details;
       ptr_F8B1E8 = v18;
     }
     else
@@ -9616,19 +9626,19 @@
     ShowStatusBarString(v19, 2u);
     goto _return;
   }
-  v20 = v2->uProfession;
-  if ( v20 != 51 )
-  {
-    v21 = *(&pNPCStats->field_13A58 + 5 * v20);
+  //v20 = v2->uProfession;
+  if ( v2->uProfession != 51 )
+  {
+    v21 = pNPCStats->pProfessions[v2->uProfession - 1].uHirePrice;
     if ( pParty->uNumGold < v21 )
     {
       ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
-      byte_F8B1EC = 0;
+      dialogue_show_profession_details = false;
       uDialogueType = 13;
-      ptr_F8B1E8 = (char *)*(&pNPCStats->field_13A64 + 5 * v2->uProfession);
+      ptr_F8B1E8 = pNPCStats->pProfessions[v2->uProfession - 1].pJoinText;
       ptr_F8B1E8 = sub_495461((char *)ptr_F8B1E8, uActiveCharacter - 1, 0, 0, 0, 0);
       if ( uActiveCharacter )
-        pPlayers[uActiveCharacter]->PlaySound(SPEECH_38, 0);
+        pPlayers[uActiveCharacter]->PlaySound(SPEECH_NotEnoughGold, 0);
       v19 = pGlobalTXT_LocalizationStrings[155];
       goto LABEL_77;
     }
@@ -12538,17 +12548,17 @@
 }
 
 //----- (004BC49B) --------------------------------------------------------
-void __thiscall sub_4BC49B(unsigned int _this)
-{
-  unsigned int v1; // esi@1
+void OnSelectDialogueOption(DIALOGUE_TYPE newDialogueType)
+{
+  //unsigned int v1; // esi@1
   NPCData *v2; // ebp@1
-  unsigned int v3; // eax@1
+  //unsigned int v3; // eax@1
   int v4; // ecx@10
   signed int v5; // edi@14
   char *v6; // esi@15
   const char *v7; // ecx@22
   signed int v8; // edi@37
-  unsigned int v9; // eax@56
+  //unsigned int v9; // eax@56
   unsigned int v10; // ecx@57
   void *v11; // [sp-Ch] [bp-1Ch]@46
   int v12; // [sp-8h] [bp-18h]@46
@@ -12556,36 +12566,36 @@
   size_t v14; // [sp-4h] [bp-14h]@46
   const char *v15; // [sp-4h] [bp-14h]@60
 
-  v1 = _this;
+  //v1 = _this;
   v2 = GetNPCData(uDialogue_SpeakingActorNPC_ID);
-  v3 = v1;
-  uDialogueType = v1;
+  //v3 = v1;
+  uDialogueType = newDialogueType;
   if ( !v2->uFlags )
   {
     v2->uFlags = 1;
-    v3 = uDialogueType;
-  }
-  if ( (signed int)v3 > 22 )
-  {
-    if ( v3 == 23 )
+    //v3 = uDialogueType;
+  }
+  if ( (signed int)newDialogueType > 22 )
+  {
+    if ( newDialogueType == DIALOGUE_23 )
     {
       v4 = v2->evte;
       goto LABEL_74;
     }
-    if ( v3 == 24 )
+    if (newDialogueType == DIALOGUE_24)
     {
       v4 = v2->evtf;
       goto LABEL_74;
     }
-    if ( v3 != 76 )
-    {
-      if ( v3 == 77 )
-      {
-        byte_F8B1EC ^= 1u;
+    if (newDialogueType != DIALOGUE_76)
+    {
+      if (newDialogueType == DIALOGUE_PROFESSION_DETAILS)
+      {
+        dialogue_show_profession_details = ~dialogue_show_profession_details;
       }
       else
       {
-        if ( (signed int)v3 > 84 && (signed int)v3 <= 88 )
+        if ( (signed int)newDialogueType > 84 && (signed int)newDialogueType <= 88 )
         {
           ArenaFight();
           return;
@@ -12593,7 +12603,7 @@
       }
       goto LABEL_87;
     }
-    if ( v2->uFlags & 0x80 )
+    if (v2->Hired())
     {
       v8 = 0;
       if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
@@ -12646,17 +12656,17 @@
       ShowStatusBarString(v7, 2u);
       goto LABEL_87;
     }
-    v9 = v2->uProfession;
-    if ( v9 != 51 )
-    {
-      v10 = *(&pNPCStats->field_13A58 + 5 * v9);
+    //v9 = v2->uProfession;
+    if ( v2->uProfession != 51 )
+    {
+      v10 = pNPCStats->pProfessions[v2->uProfession - 1].uHirePrice;
       if ( pParty->uNumGold < v10 )
       {
         ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);// "You don't have enough gold"
-        byte_F8B1EC = 0;
+        dialogue_show_profession_details = false;
         uDialogueType = 13;
         if ( uActiveCharacter )
-          pPlayers[uActiveCharacter]->PlaySound(SPEECH_38, 0);
+          pPlayers[uActiveCharacter]->PlaySound(SPEECH_NotEnoughGold, 0);
         v7 = pGlobalTXT_LocalizationStrings[155];
         goto LABEL_64;
       }
@@ -12691,12 +12701,12 @@
       pPlayers[uActiveCharacter]->PlaySound(SPEECH_61, 0);
     goto LABEL_87;
   }
-  if ( v3 == 22 )
+  if (newDialogueType == DIALOGUE_22)
   {
     v4 = v2->evtd;
     goto LABEL_74;
   }
-  if ( v3 == 9 )
+  if (newDialogueType == DIALOGUE_9)
   {
     if ( !sub_4BB756(v2->uProfession) )
     {
@@ -12714,12 +12724,12 @@
     v7 = pGlobalTXT_LocalizationStrings[140];
     goto LABEL_64;
   }
-  if ( v3 == 13 )
-  {
-    if ( !(v2->uFlags & 0x80) )
+  if (newDialogueType == DIALOGUE_13)
+  {
+    if (!v2->Hired())
     {
       sub_4B3E1E();
-      byte_F8B1EC = 0;
+      dialogue_show_profession_details = false;
       goto LABEL_87;
     }
     v5 = 0;
@@ -12739,17 +12749,17 @@
     }
     goto LABEL_44;
   }
-  if ( v3 == 19 )
+  if (newDialogueType == DIALOGUE_19)
   {
     v4 = v2->bDrawSomeAnim;
     goto LABEL_74;
   }
-  if ( v3 == 20 )
+  if (newDialogueType == DIALOGUE_20)
   {
     v4 = v2->_anim_current_time;
     goto LABEL_74;
   }
-  if ( v3 == 21 )
+  if (newDialogueType == DIALOGUE_21)
   {
     v4 = v2->_anim_end_time;
 LABEL_74:
@@ -12778,7 +12788,7 @@
       }
       else
       {
-        dword_F8B1D8 = v3;
+        dword_F8B1D8 = newDialogueType;
         sub_4B3EF0(v4 - 400);
       }
     }
--- a/mm7_5.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/mm7_5.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -365,7 +365,7 @@
               auto npc = pNPCStats->pNewNPCData + i;
               //do
               //{
-                if (npc->uFlags & 0x80 &&
+                if (npc->Hired() &&
                     (!pParty->pHirelings[0].pName || strcmp(npc->pName, pParty->pHirelings[0].pName)) &&
                     (!pParty->pHirelings[1].pName || strcmp(npc->pName, pParty->pHirelings[1].pName)) )
                 {
@@ -398,8 +398,8 @@
         case UIMSG_195:
           sub_4BCACC_bounties(uMessageParam);
           continue;
-        case UIMSG_88:
-          sub_4BC49B(uMessageParam);
+        case UIMSG_SelectDialogueOption:
+          OnSelectDialogueOption((DIALOGUE_TYPE)uMessageParam);
           continue;
         case UIMSG_19A:
           _4B4224_UpdateNPCTopics(uMessageParam);
@@ -16044,7 +16044,7 @@
       while ( (signed int)lpsz < (signed int)pNPCStats->uNumNewNPCs );*/
       for (int i = 0; i < pNPCStats->uNumNewNPCs; ++i)
       {
-        if (pNPCStats->pNewNPCData[i].uFlags & 0x80)
+        if (pNPCStats->pNewNPCData[i].Hired())
         {
           if (!pParty->pHirelings[0].pName || strcmp((char *)pNPCStats->pNewNPCData[i].pName, (char *)pParty->pHirelings[0].pName))
           {
--- a/mm7_data.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/mm7_data.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -2007,7 +2007,7 @@
 int dword_F8B1E0; // weak
 int dword_F8B1E4; // weak
 const char *ptr_F8B1E8; // idb
-char byte_F8B1EC; // weak
+char dialogue_show_profession_details = false; // F8B1EC
 char byte_F8B1EF[777]; // weak
 char byte_F8B1F0[4];
 int dword_F8B1F4; // weak
--- a/mm7_data.h	Mon Feb 18 08:47:21 2013 +0400
+++ b/mm7_data.h	Mon Feb 18 08:59:34 2013 +0400
@@ -1702,7 +1702,7 @@
 extern int dword_F8B1E0; // weak
 extern int dword_F8B1E4; // weak
 extern const char *ptr_F8B1E8; // idb
-extern char byte_F8B1EC; // weak
+extern char dialogue_show_profession_details; // weak
 extern char byte_F8B1EF[]; // weak
 extern char byte_F8B1F0[4];
 extern int dword_F8B1F4; // weak
@@ -2183,7 +2183,7 @@
 bool __fastcall sub_4759C9(BLVFace *a1, int a2, int a3, __int16 a4);
 bool __fastcall sub_475D85(Vec3_int_ *a1, Vec3_int_ *a2, int *a3, BLVFace *a4);
 bool __fastcall sub_475F30(int *a1, BLVFace *a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);
-
+bool PartyHasDragon();
 
 int __fastcall const_1(int, int); // weak
 int __cdecl GetPartyReputation();
@@ -2344,7 +2344,6 @@
 void __cdecl sub_4BBCDD();
 void __fastcall _4BBF61_summon_actor(int a1, __int16 x, int y, int z); // idb
 void __cdecl ArenaFight();
-void __thiscall sub_4BC49B(unsigned int _this);
 struct Texture *__cdecl sub_4BC8D5();
 struct GUIButton *__cdecl sub_4BCA33();
 void __fastcall sub_4BCACC_bounties(signed int a1);
--- a/mm7text_ru.cpp	Mon Feb 18 08:47:21 2013 +0400
+++ b/mm7text_ru.cpp	Mon Feb 18 08:59:34 2013 +0400
@@ -1085,12 +1085,13 @@
   while (left <= right)
   {
     match = left + (right - left) / 2;
-    switch (_mbsncmp(name, (unsigned char *)table[match].name, name_len))
-    {
-      case -1: right = match; break;
-      case  0: return table[match].gender;
-      case  1: left = match; break;
-    }
+    int rval = _mbsncmp(name, (unsigned char *)table[match].name, name_len);
+    if (rval < 0)
+      right = match;
+    else if (!rval)
+      return table[match].gender;
+    else
+      left = match;
   }
   assert(false);
   return 0;
@@ -1287,7 +1288,6 @@
 
         if (IsSpecialName(src + 4))
         {
-          __debugbreak(); // check this is ok
           auto name = GetSpecialCase(src + 4, src[2]);
           int name_len = strlen(name);