view NPC.cpp @ 1244:6279bf7a4d1a

Merge
author Grumpy7
date Sun, 09 Jun 2013 23:53:01 +0200
parents ab6560001f5b
children 86a83e12d795
line wrap: on
line source

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "Allocator.h"
#include "texts.h"
#include "LOD.h"
#include "Autonotes.h"
#include "Awards.h"
#include "mm7_data.h"
#include "MM7.h"
#include "Party.h"
#include "NPC.h"

int pDialogueNPCCount;
std::array<struct Texture *, 6> pDialogueNPCPortraits;
int uNumDialogueNPCPortraits; // weak
struct NPCStats *pNPCStats = nullptr;

void  InitializeAwards();
void  InitializeScrolls();
void  InitializeMerchants();
void  InitializeTransitions();
void  InitializeAutonotes();
void  InitializeQuests();
bool   CheckPortretAgainstSex(int portret_num, int sex); 

//----- (004459F9) --------------------------------------------------------
NPCData *__fastcall GetNPCData(signed int npcid)
{
  unsigned int v1; // esi@1
  NPCData *result; // eax@5
  int v3; // esi@9
  int v4; // ecx@9
  //int v5; // edx@9
  //NPCData *v6; // eax@9
  char *v7; // ebx@14
  NPCData *v8; // edi@14
  char v9; // al@22
  char v10;
  //std::string v10; // [sp-18h] [bp-2Ch]@4
  int v11;
  //const char *v11; // [sp-8h] [bp-1Ch]@4
  int v12; // [sp-4h] [bp-18h]@4
  int v13; 
  char *v14;
  //std::string *v13; // [sp+Ch] [bp-8h]@4
  int a3; // [sp+13h] [bp-1h]@4
  int i;

  /*v1 = npcid;
  if ( (npcid & 0x80000000u) == 0 )
  {
    if ( (signed int)npcid < 5000 )
    {
      if ( (signed int)npcid >= 501 )
      {
    MessageBoxW(nullptr, L"NPC id exceeds MAX_DATA!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Events.cpp:1984", 0);
      }
      return &pNPCStats->pNewNPCData[v1];
    }
    return &pNPCStats->array_13EF4[npcid - 5000];
  }
  if ( (signed int)npcid >= 5000 )
    return &pNPCStats->array_13EF4[npcid - 5000];
  if ( (sDialogue_SpeakingActorNPC_ID & 0x80000000u) == 0 )
  {
    result = 0;
  }
  else
  {
    v3 = abs((int)sDialogue_SpeakingActorNPC_ID) - 1;
    v4 = 0;
    v5 = 0;
    v6 = pParty->pHirelings;
    do
    {
      if ( v6->pName )
        pTmpBuf[v4++] = v5;
      ++v6;
      ++v5;
    }
    while ( (signed int)v6 < (signed int)&pParty->pPickedItem );
    v13 = 0;
    if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
    {
      v7 = &pTmpBuf[v4];
      v8 = pNPCStats->pNewNPCData;
      do
      {
        if ( v8->uFlags & 0x80
          && (!pParty->pHirelings[0].pName || strcmp(v8->pName, pParty->pHirelings[0].pName))
          && (!pParty->pHirelings[1].pName || strcmp(v8->pName, pParty->pHirelings[1].pName)) )
          *v7++ = (char)v13 + 2;
        v13 = (std::string *)((char *)v13 + 1);
        ++v8;
      }
      while ( (signed int)v13 < (signed int)pNPCStats->uNumNewNPCs );
    }
    v9 = pTmpBuf[v3];
    if ( (unsigned __int8)v9 >= 2u )
      result = &pNPCStats->pNPCData[(unsigned __int8)v9 + 499];
    else
      result = &pParty->pHirelings[(unsigned __int8)v9];
  }
  return result;*/
  v1 = npcid;
  if ( npcid >= 0 )
  {
    if ( npcid < 5000 )
    {
      if ( npcid >= 501 )
      {
        MessageBoxW(nullptr, L"NPC id exceeds MAX_DATA!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Events.cpp:1984", 0);
      }
      return &pNPCStats->pNewNPCData[v1];// - 1];
    }
    return &pNPCStats->pAdditionalNPC[npcid - 5000];
  }


  if ( npcid >= 5000 )
    return &pNPCStats->pAdditionalNPC[npcid - 5000];
  if (sDialogue_SpeakingActorNPC_ID >= 0)
  {
    result = 0;
  }
  else
  {
    v3 = abs(sDialogue_SpeakingActorNPC_ID) - 1;
    v4 = 0;

    for (i = 0; i < 2; ++i)
    {
      if (pParty->pHirelings[i].pName)
        pTmpBuf[v4++] = i;
    }

    if (pNPCStats->uNumNewNPCs > 0)
    {
      for (i = 0; i < pNPCStats->uNumNewNPCs; ++i)
      {
        if (pNPCStats->pNewNPCData[i].Hired())
        {
          if (!pParty->pHirelings[0].pName || strcmp((char *)pNPCStats->pNewNPCData[i].pName, (char *)pParty->pHirelings[0].pName))
          {
            if (!pParty->pHirelings[1].pName || strcmp((char *)pNPCStats->pNewNPCData[i].pName, (char *)pParty->pHirelings[1].pName))
              pTmpBuf[v4++] = i + 2;
          }
        }
      }
    }

    v9 = pTmpBuf[v3];
    if ( v9 >= 2 )
     result = &pNPCStats->pNPCData[499 + v9];
    else
      result = &pParty->pHirelings[v9];
  }
  return result;
}

//----- (00445B2C) --------------------------------------------------------
struct NPCData * GetNewNPCData( signed int npcid, int* npc_indx )
    {

  int* v3; // edi@1
  NPCData *result; // eax@5
  int v5; // esi@9
  int v6; // ecx@9
  char v11; // al@23

  v3 = npc_indx;
  if ( npcid >= 0 )
  {
    if ( npcid < 5000 )
    {
      if ( npcid >= 501 )
      {
        MessageBoxW(nullptr, L"NPC id exceeds MAX_DATA!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Events.cpp:2040", 0);
      }
      *v3 = npcid;
      return &pNPCStats->pNewNPCData[npcid];
    }
    *npc_indx = npcid - 5000;
    return &pNPCStats->pAdditionalNPC[npcid - 5000];
  }
  if ( npcid >= 5000 )
      {
      *npc_indx = npcid - 5000;
      return &pNPCStats->pAdditionalNPC[npcid - 5000];
      }
  if ( sDialogue_SpeakingActorNPC_ID >= 0 )
  {
    *npc_indx = 0;
    result = NULL;
  }
  else
  {
    v5 = abs(sDialogue_SpeakingActorNPC_ID) - 1;
    v6 = 0;
    for (int i=0; i<2; ++i)
    {
      if ( pParty->pHirelings[i].pName )
        pTmpBuf[v6++] = i;
     
    }     
    for (int i=0; i< pNPCStats->uNumNewNPCs; ++i)
        {
        if ( pNPCStats->pNewNPCData[i].Hired()
            && (!pParty->pHirelings[0].pName || strcmp(pNPCStats->pNewNPCData[i].pName, pParty->pHirelings[0].pName))
            && (!pParty->pHirelings[1].pName || strcmp(pNPCStats->pNewNPCData[i].pName, pParty->pHirelings[1].pName)) )
            {
                pTmpBuf[v6++]=i+2;
            }
        }
    v11 = pTmpBuf[v5];

    if ( v11 >= 2u )
    {
      *v3 = v11 - 2;
      result = &pNPCStats->pNewNPCData[v11 - 2];
    }
    else
    {
      *v3 = v11;
      result = &pParty->pHirelings[v11];
    }
  }
  return result;
}

//----- (00476977) --------------------------------------------------------
void NPCStats::InitializeNPCText()
	{
	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	if (pNPCTextTXT_Raw)
		pAllocator->FreeChunk(pNPCTextTXT_Raw);
	pNPCTextTXT_Raw =NULL;
	pNPCTextTXT_Raw = (char *)pEvents_LOD->LoadRaw("npctext.txt", 0);
	strtok(pNPCTextTXT_Raw, "\r");

	for (i=0; i<789; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				if ( decode_step == 1)
					pNPCTopics[i].pText =RemoveQuotes(test_string);
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<2)&&!break_loop);
		}

	if (pNPCTopicTXT_Raw)
		pAllocator->FreeChunk(pNPCTopicTXT_Raw);
	pNPCTopicTXT_Raw =NULL;
	pNPCTopicTXT_Raw = (char *)pEvents_LOD->LoadRaw("npctopic.txt", 0);
	strtok(pNPCTopicTXT_Raw, "\r");

	for (i=0; i<579; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				if ( decode_step == 1)
					pNPCTopics[i].pTopic = RemoveQuotes(test_string);
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<2)&&!break_loop);
		}

	if (pNPCDistTXT_Raw)
		pAllocator->FreeChunk(pNPCDistTXT_Raw);
	pNPCDistTXT_Raw = NULL;
	pNPCDistTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcdist.txt", 0);
	strtok(pNPCDistTXT_Raw, "\r");
	strtok(NULL, "\r");

	for (i=1; i<59; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				if ((decode_step>0)&&(decode_step<77))
					{
					pProfessionChance[decode_step].professionChancePerArea[i]=atoi(test_string);
					}
				else if (decode_step==0)
					{
					pProfessionChance[0].professionChancePerArea[i]=10;
					}
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<78)&&!break_loop);
		}

	for ( i = 0; i < 77; ++i )
		{
		pProfessionChance[i].uTotalprofChance=0;
		for ( int ii = 1; ii < 59; ++ii )
			{
			pProfessionChance[i].uTotalprofChance+=pProfessionChance[i].professionChancePerArea[ii];
			}
		pProfessionChance[i].professionChancePerArea[0]=0;
		pProfessionChance[i].professionChancePerArea[59]=0;
		}

	if (pNPCDistTXT_Raw)
		{
		pAllocator->FreeChunk(pNPCDistTXT_Raw);
		pNPCDistTXT_Raw = NULL;
		}
	}

//----- (00476C60) --------------------------------------------------------
void NPCStats::_476C60()
	{
	for (unsigned int i = 1; i < uNumNewNPCs; ++i)
		pNewNPCData[i].pName = pNPCUnicNames[i - 1];

	if (pParty->pHirelings[0].pName)
		pParty->pHirelings[0].pName = pParty->pHireling1Name;
	if (pParty->pHirelings[1].pName)
		pParty->pHirelings[1].pName = pParty->pHireling2Name;
	}

//----- (00476CB5) --------------------------------------------------------
void NPCStats::InitializeNPCData()
	{
	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	pNPCDataTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcdata.txt", 0);
	strtok(pNPCDataTXT_Raw, "\r");
	strtok(NULL, "\r");

	for (i=0; i<500; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{  //i+1
				switch (decode_step)
					{
				case 1:
					pNPCUnicNames[i] = RemoveQuotes(test_string);
					pNPCData[i+1].pName=pNPCUnicNames[i];
					break;
				case 2:
					pNPCData[i+1].uPortraitID = atoi(test_string);
					break;
				case 6:
					pNPCData[i+1].Location2D = atoi(test_string);
					break;
				case 7:
					pNPCData[i+1].uProfession = atoi(test_string);
					break;
				case 8:
					pNPCData[i+1].greet = atoi(test_string);
					break;
				case 9:
					pNPCData[i+1].joins = (*test_string == 'y')?1:0;
					break;
				case 10:
					pNPCData[i+1].evt_A = atoi(test_string);
					break;
				case 11:
					pNPCData[i+1].evt_B = atoi(test_string);
					break;
				case 12:
					pNPCData[i+1].evt_C = atoi(test_string);
					break;
				case 13:
					pNPCData[i+1].evt_D = atoi(test_string);
					break;
				case 14:
					pNPCData[i+1].evt_E = atoi(test_string);
					break;
				case 15:
					pNPCData[i+1].evt_F = atoi(test_string);
					break;
					}
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<16)&&!break_loop);
		}
	uNumNewNPCs = 501;
	pNPCGreetTXT_Raw = (char*)pEvents_LOD->LoadRaw("npcgreet.txt", 0);
	strtok(pNPCGreetTXT_Raw, "\r");
	for (i=0; i<205; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{  //i+1
				switch (decode_step)
					{
				case 1:
					pNPCGreetings[i].pGreeting1 = RemoveQuotes(test_string);
					break;
				case 2:
					pNPCGreetings[i].pGreeting2 = RemoveQuotes(test_string);
					break;
					}
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<3)&&!break_loop);
		}

	pNCPGroupTXT_Raw = (char*)pEvents_LOD->LoadRaw("npcgroup.txt", 0);
	strtok(pNCPGroupTXT_Raw, "\r");

	for (i=0; i<51; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{  //i+1
				if (decode_step==1)
					{
					pGroups[i] = atoi(test_string);
					}
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<2)&&!break_loop);
		}

	pNPCNewsTXT_Raw = (char*)pEvents_LOD->LoadRaw("npcnews.txt", 0);
	strtok(pNPCNewsTXT_Raw, "\r");


	for (i=0; i<51; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{  //i+1
				if (decode_step==1)
					pCatchPhrases[i] = RemoveQuotes(test_string);
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<2)&&!break_loop);
		}
	}

//----- (0047702F) --------------------------------------------------------
void NPCStats::Initialize()
		{
		int i;
		char* test_string;
		unsigned char c;
		bool break_loop;
		unsigned int temp_str_len;
		char* tmp_pos;
		int decode_step;

		InitializeNPCData();
		InitializeNPCText();
		InitializeQuests();
		InitializeAutonotes();
		InitializeAwards();
		InitializeTransitions();
		InitializeMerchants();
		InitializeScrolls();

		pNPCNamesTXT_Raw = NULL;
		pNPCNamesTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcnames.txt", 0);
		strtok(pNPCNamesTXT_Raw, "\r");

		uNewlNPCBufPos = 0;

		for (i=0; i<540; ++i)
			{
			test_string = strtok(NULL, "\r") + 1;
			break_loop = false;
			decode_step=0;
			do 
				{
				c = *(unsigned char*)test_string;
				temp_str_len = 0;
				if (c=='\t')
					{
					if ( (decode_step == 1)&&(!uNumNPCNames[1]))
						uNumNPCNames[1]=i;
					}
				else
					{
					while((c!='\n')&&(c!='\t')&&(c>0))
						{
						++temp_str_len;
						c=test_string[temp_str_len];
						}		
					tmp_pos=test_string+temp_str_len;
					if (*tmp_pos == 0)
						break_loop = true;

					if (temp_str_len)
						{
						*tmp_pos = 0;
						if ( decode_step == 0)
							pNPCNames[i][0] =RemoveQuotes(test_string);
						else if ( decode_step == 1)
							pNPCNames[i][1] =RemoveQuotes(test_string);
						}
					else
						{ 
						if ( (decode_step == 1)&&(!uNumNPCNames[1]))
							uNumNPCNames[1]=i;
						}
					}
				++decode_step;
				test_string=tmp_pos+1;
				} while ((decode_step<2)&&!break_loop);
			}
		uNumNPCNames[0] = i;

		pNPCProfTXT_Raw = NULL;
		pNPCProfTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcprof.txt", 0);
		strtok(pNPCProfTXT_Raw, "\r");
		strtok(NULL, "\r");
		strtok(NULL, "\r");
		strtok(NULL, "\r");

		for (i=1; i<59; ++i)
			{
			test_string = strtok(NULL, "\r") + 1;
			break_loop = false;
			decode_step=0;
			do 
				{
                //while (*test_string == '\t')  // some steps are separated by multiple \t's
                  //++test_string;
                
				c = *(unsigned char*)test_string;
				temp_str_len = 0;
				while((c!='\t')&&(c>0))
					{
					++temp_str_len;
					c=test_string[temp_str_len];
					}		
				tmp_pos=test_string+temp_str_len;
				if (*tmp_pos == 0)
					break_loop = true;
				*tmp_pos = 0;
				if (temp_str_len)
					{
					switch(decode_step)
						{
					case 2:
						pProfessions[i].uHirePrice = atoi(test_string);
						break;
					case 3:
						pProfessions[i].pActionText = RemoveQuotes(test_string);
						break;
					case 4:
						pProfessions[i].pBenefits= RemoveQuotes(test_string);
						break;
					case 5:
						pProfessions[i].pJoinText = RemoveQuotes(test_string);
						break;
					case 6:
						pProfessions[i].pDismissText = RemoveQuotes(test_string);
						}
					}
				else
					{ 
					if (!decode_step)
						break_loop = true;
					}
				++decode_step;
				test_string=tmp_pos+1;
				} while ((decode_step<7)&&!break_loop);
			}
		uNumNPCProfessions = 59;
		}

//----- (00477266) --------------------------------------------------------
void NPCStats::Release()
	{
	pAllocator->FreeChunk(pNPCTopicTXT_Raw);
	pNPCTopicTXT_Raw = NULL;
	pAllocator->FreeChunk(pNPCTextTXT_Raw);
	pNPCTextTXT_Raw = NULL;
	pAllocator->FreeChunk(pNPCNewsTXT_Raw);
	pNPCNewsTXT_Raw = NULL;
	pAllocator->FreeChunk(pNPCProfTXT_Raw);
	pNPCProfTXT_Raw = NULL;
	pAllocator->FreeChunk(pNPCNamesTXT_Raw);
	pNPCNamesTXT_Raw = NULL;
	pAllocator->FreeChunk(pNPCDataTXT_Raw);
	pNPCDataTXT_Raw = NULL;
	pAllocator->FreeChunk(pNPCDistTXT_Raw);
	pNPCDistTXT_Raw = NULL;
	pAllocator->FreeChunk(pNPCGreetTXT_Raw);
	pNPCGreetTXT_Raw = NULL;
	pAllocator->FreeChunk(pNCPGroupTXT_Raw);
	pNCPGroupTXT_Raw = NULL;
	}

//----- (0047730C) --------------------------------------------------------
bool  CheckPortretAgainstSex(int a1, int)
	{
	return true;
	}
// 47730C: using guessed type int __stdcall const_1(int);

//----- (0047732C) --------------------------------------------------------
void NPCStats::InitializeAdditionalNPCs(NPCData *pNPCDataBuff, int npc_uid, int uLocation2D, int uMapId)
	{
	int rep_gen;
	int uNPCSex; // esi@1
	int uGeneratedPortret; // ecx@23
	int test_prof_summ; // ecx@37
	int gen_profession; // eax@37
	int max_prof_cap; // edx@37
	signed int result; // eax@39
	int uRace; // [sp+Ch] [bp-Ch]@1
	bool break_gen; // [sp+10h] [bp-8h]@1
	signed int gen_attempts; // [sp+14h] [bp-4h]@1
	int uPortretMin; // [sp+24h] [bp+Ch]@1
	int uPortretMax;

	static const unsigned __int8 NPCSexGenTable[86] ={
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                          
		1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
		1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
		0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
	static const unsigned __int8 NPCRaceGenTable[86] ={
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 1,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0};

	unsigned __int8 seed = (unsigned __int8)((double)(npc_uid - 1)/3.0);
	uNPCSex = NPCSexGenTable[seed];
	uRace = NPCRaceGenTable[seed];
	pNPCDataBuff->uSex = uNPCSex;
	pNPCDataBuff->pName = pNPCNames[rand() % uNumNPCNames[uNPCSex]][uNPCSex];

	gen_attempts = 0;
	break_gen = false;

	do
		{
		switch ( uRace )
			{
		case 0:
			if ( uNPCSex == 0 )
				{
				uPortretMin = 2;
				uPortretMax = 100;
				}
			else
				{
				uPortretMin = 201;
				uPortretMax =  250;
				}
		case 1:
			if ( uNPCSex == 0 )
				{
				uPortretMin = 400;
				uPortretMax = 430;
				}
			else
				{
				uPortretMin = 460;
				uPortretMax =  490;
				}
			break;
		case 2:
			if ( uNPCSex == 0 )
				{
				uPortretMin = 500;
				uPortretMax =  520;
				}
			else
				{
				uPortretMin = 530;
				uPortretMax = 550;	
				}
			break;
		case 3:
			if ( uNPCSex == 0 )
				{
				uPortretMin = 300;
				uPortretMax = 330;
				}
			else
				{
				uPortretMin = 360;
				uPortretMax = 387;
				}

			break;
			}

		uGeneratedPortret = uPortretMin + rand() % (uPortretMax - uPortretMin + 1);
		if ( CheckPortretAgainstSex(uGeneratedPortret, uNPCSex))
			break_gen = true;
		++gen_attempts;
		if ( gen_attempts >= 4 )
			{
			uGeneratedPortret = uPortretMin;
			break_gen = true;
			}
		}
		while(!break_gen);

		pNPCDataBuff->uPortraitID = uGeneratedPortret;
		pNPCDataBuff->uFlags = 0;
		pNPCDataBuff->fame = 0;
		//generate reputation
		rep_gen = rand() % 100 + 1;

		if ( rep_gen >= 60 )
			{
			if ( rep_gen >= 90 )
				{
				if ( rep_gen >= 95 )
					{
					if ( rep_gen >= 98 )
						pNPCDataBuff->rep = -600;
					else
						pNPCDataBuff->rep = 400;
					}
				else
					pNPCDataBuff->rep = -300;
				}
			else
				pNPCDataBuff->rep = 200;
			}
		else
			pNPCDataBuff->rep = 0;

		max_prof_cap = rand() % pProfessionChance[uMapId].uTotalprofChance+1;
		test_prof_summ = 0;
		gen_profession = 0;

		if ( max_prof_cap > 0 )
			{
			do
				test_prof_summ += pProfessionChance[uMapId].professionChancePerArea[gen_profession++];
			while ( test_prof_summ < max_prof_cap );
			}
		pNPCDataBuff->uProfession = gen_profession - 1;
		pNPCDataBuff->Location2D = uLocation2D;
		pNPCDataBuff->field_24 = 1;
		pNPCDataBuff->joins = 1;
		pNPCDataBuff->evt_A = 0;
		pNPCDataBuff->evt_B = 0;
		pNPCDataBuff->evt_C = 0;
		pNPCDataBuff->evt_D = 0;
		pNPCDataBuff->evt_E = 0;
		pNPCDataBuff->evt_F = 0;
	}

//----- (00476387) --------------------------------------------------------
bool PartyHasDragon()
{
  return pNPCStats->pNewNPCData[57].Hired();
}

//----- (00476395) --------------------------------------------------------
//0x26 Wizard eye at skill level 2
bool __thiscall CheckHiredNPCSpeciality(unsigned int uProfession)
    {

    if ( bNoNPCHiring == 1 )
        return 0;

    for (int i=0; i<pNPCStats->uNumNewNPCs; ++i )
        {
        if ( pNPCStats->pNewNPCData[i].uProfession == uProfession && 
            (pNPCStats->pNewNPCData[i].uFlags & 0x80) )
            return true;
        }
    if ( pParty->pHirelings[0].uProfession == uProfession ||
         pParty->pHirelings[1].uProfession == uProfession)
        return true;
    else
        return false;

    }
// 6BE3C5: using guessed type char bNoNPCHiring;

//----- (004763E0) --------------------------------------------------------
void  InitializeAwards()
{
	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	if ( pAwardsTXT_Raw )
		pAllocator->FreeChunk(pAwardsTXT_Raw);
	pAwardsTXT_Raw = NULL;
	pAwardsTXT_Raw = (char *)pEvents_LOD->LoadRaw("awards.txt", 0);
	strtok(pAwardsTXT_Raw, "\r");

	for (i=1; i<105; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				if (decode_step==1)
					pAwards[i].pText=RemoveQuotes(test_string);
				else if (decode_step==2)
					pAwards[i].uPriority = atoi(test_string);
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<3)&&!break_loop);
		}
	}
// 7241C8: using guessed type int dword_7241C8;

//----- (004764C2) --------------------------------------------------------
void  InitializeScrolls()
	{

	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	if ( pScrollsTXT_Raw )
		pAllocator->FreeChunk(pScrollsTXT_Raw);
	pScrollsTXT_Raw = NULL;
	pScrollsTXT_Raw = (char *)pEvents_LOD->LoadRaw("scroll.txt", 0);
	strtok(pScrollsTXT_Raw, "\r");
	for (i=0; i<82; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				if ( decode_step == 1)
					pScrolls[i]=RemoveQuotes(test_string);
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<2)&&!break_loop);
		}
	}

//----- (00476590) --------------------------------------------------------
void  InitializeMerchants()
	{
	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	if ( pMerchantsTXT_Raw )
		pAllocator->FreeChunk(pMerchantsTXT_Raw);
	pMerchantsTXT_Raw = NULL;
	pMerchantsTXT_Raw = (char *)pEvents_LOD->LoadRaw("merchant.txt", 0);
	strtok(pMerchantsTXT_Raw, "\r");

	for (i=0; i<7; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				switch (decode_step)
					{
				case 1:
					pMerchantsBuyPhrases[i]=RemoveQuotes(test_string);
					break;
				case 2:
					pMerchantsSellPhrases[i]=RemoveQuotes(test_string);
					break;
				case 3:
					pMerchantsRepairPhrases[i]=RemoveQuotes(test_string); 
					break;
				case 4:
					pMerchantsIdentifyPhrases[i]=RemoveQuotes(test_string); 
					break;
					}
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<5)&&!break_loop);
		}

	}

//----- (00476682) --------------------------------------------------------
void InitializeTransitions()
	{
	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	if ( pTransitionsTXT_Raw )
		pAllocator->FreeChunk(pTransitionsTXT_Raw);
	pTransitionsTXT_Raw = NULL;
	pTransitionsTXT_Raw = (char *)pEvents_LOD->LoadRaw("trans.txt", 0);
	strtok(pTransitionsTXT_Raw, "\r");

	for (i=0; i<464; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				if ( decode_step == 1)
					pTransitionStrings[i + 1]=RemoveQuotes(test_string);
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<2)&&!break_loop);
		}
	}

//----- (00476750) --------------------------------------------------------
void __cdecl InitializeAutonotes()
	{
	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	if ( pAutonoteTXT_Raw )
		pAllocator->FreeChunk(pAutonoteTXT_Raw);
	pAutonoteTXT_Raw = 0;
	pAutonoteTXT_Raw = (char *)pEvents_LOD->LoadRaw("autonote.txt", 0);
	strtok(pAutonoteTXT_Raw, "\r");

	for (i=0; i<195; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				switch (decode_step)
					{
				case  1:
					pAutonoteTxt[i].pText=RemoveQuotes(test_string);
					break;
				case  2:
					{
					if ( !_stricmp(test_string, "potion"))
						{
						pAutonoteTxt[i].eType = AUTONOTE_POTION_RECEPIE;
						break;
						}
					if ( !_stricmp(test_string, "stat") )
						{
						pAutonoteTxt[i].eType = AUTONOTE_STAT_HINT;
						break;
						}
					if ( !_stricmp(test_string, "seer") )
						{
						pAutonoteTxt[i].eType = AUTONOTE_SEER;
						break;
						}
					if ( !_stricmp(test_string, "obelisk") )
						{
						pAutonoteTxt[i].eType = AUTONOTE_OBELISK;
						break;
						}
					if ( !_stricmp(test_string, "teacher") )
						{
						pAutonoteTxt[i].eType = AUTONOTE_TEACHER;
						break;
						}
					pAutonoteTxt[i].eType =AUTONOTE_MISC;
					break;
					}
					}
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<3)&&!break_loop);
		}
	}


//----- (004768A9) --------------------------------------------------------
void __cdecl InitializeQuests()
	{
	int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

	if ( pQuestsTXT_Raw )
		pAllocator->FreeChunk(pQuestsTXT_Raw);
	pQuestsTXT_Raw = NULL;
	pQuestsTXT_Raw = (char *)pEvents_LOD->LoadRaw("quests.txt", 0);
	strtok(pQuestsTXT_Raw, "\r");

	for (i=0; i<512; ++i)
		{
		test_string = strtok(NULL, "\r") + 1;
		break_loop = false;
		decode_step=0;
		do 
			{
			c = *(unsigned char*)test_string;
			temp_str_len = 0;
			while((c!='\t')&&(c>0))
				{
				++temp_str_len;
				c=test_string[temp_str_len];
				}		
			tmp_pos=test_string+temp_str_len;
			if (*tmp_pos == 0)
				break_loop = true;
			*tmp_pos = 0;
			if (temp_str_len)
				{
				if ( decode_step == 1)
					pQuestTable[i] =RemoveQuotes(test_string);
				}
			else
				{ 
				break_loop = true;
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<2)&&!break_loop);
		}
	}