#include "stdafx.h"
#include "Global_variables_extern.h"
#include "Basics_functions.h"
#include "Vampirism_fire.h"
#include "DB_Cost.h"
#include "HumanTactics.h"
#include "VampireTactics.h"
#include "war3map.h"

HumanPlayer * fHumanPlayerGlobal(integer vAI)
{
	for (int vvi = 0; vvi < vCountHumans; vvi++)
	{
		if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == vAI)
		{
			return &pHumanPlayerGlobal[vvi];
		}
	}
	return NULL;
}

VampirePlayer * fVampirePlayerGlobal(integer vAI)
{
	for (int vvi = 0; vvi < vCountHumans; vvi++)
	{
		if (pVampirePlayerGlobal[vvi].vParamPlayer.vAI == vAI)
		{
			return &pVampirePlayerGlobal[vvi];
		}
	}
	return NULL;
}

bool fIsVampires()
{
	if (vGlobalNAI >= 0 &&
		vGlobalNAI <= 9)
	{
		return FALSE;
	}
	else if (vGlobalNAI >= 10 &&
		     vGlobalNAI <= 11)
	{
		return TRUE;
	}
	return FALSE;
}

bool fIsHimans()
{
	if (vGlobalNAI >= 0 &&
		vGlobalNAI <= 9)
	{
		return TRUE;
	}
	else if (vGlobalNAI >= 10 &&
		     vGlobalNAI <= 11)
	{
		return FALSE;
	}
	return FALSE;
}

bool fGlobalActionAI()
{
	if (vGlobalTimeAction != vTimerGetElapsedGlobal)
	{
		vGlobalTimeAction = vTimerGetElapsedGlobal;
	}
	else
	{
		sprintf(vTest,"fGlobalActionAI vTimerGetElapsedGlobal = %f",vTimerGetElapsedGlobal);
		fLog(888,vTest);
		return FALSE;
	}
	sprintf(vTest,"fGlobalActionAI vTimerGetElapsedGlobal = %f",vTimerGetElapsedGlobal);
	fLog(444,vTest);
	return TRUE;
}

void fTimerMain()
{
	//sprintf(vTest,"fTimerMain()!!!");
	//DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
	if (vWar3MapInit == FALSE)
	{
		vMainThreadDestroyedHandle = AddEventHandler(jeMainThreadDestroyed,(TJassEventCallback*)&fMainThreadDestroyed,NULL);
		fMain();
		vWar3MapInit = TRUE;
		// Время
		vTimerGame = CreateTimer();
		TimerStart(vTimerGame,2*60*60,false,NULL);
		//sprintf(vTest,"Map loaded!!!");
		//DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
	}
	real vTimerGetElapsed = TimerGetElapsed(vTimerGamePre);
	//sprintf(vTest,"vTimerGetElapsed = %f",vTimerGetElapsed);
	//DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
	if (vSync2 == TRUE &&
		(int)vTimerGetElapsed%6 == 5)
	{
		vSync2 = FALSE;
		//sprintf(vTest,"vSync2 = FALSE;!!!");
		//DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
	}
	if (vSync2 == FALSE)
	{
		sprintf(vKeyLocalPlayer,"%d\0",GetPlayerColor(GetLocalPlayer()));
		StoreInteger(vSyncCache3,"LoadMap",vKeyLocalPlayer,1);
		SyncStoredInteger(vSyncCache3,"LoadMap",vKeyLocalPlayer);
		StoreInteger(vSyncCache3,"LoadMap",vKeyLocalPlayer,0);
		sprintf(vKeyLocalPlayer,"\0");
		vSync2 = TRUE;
		//sprintf(vTest,"vSync2 = TRUE;!!!");
		//DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
		return;
	}
	if (vSync2 == TRUE)
	{
		for (int vvi = 0; vvi < vCountPlayersUser; vvi++)
		{
			if (pPlayerUser[vvi].vLeave == FALSE)
			{
				if (GetStoredInteger(vSyncCache3,"LoadMap",pPlayerUser[vvi].vKeyPlayer) != 1)
				{
					return;
				}
			}
		}
	}
	if (vTimerGamePre > 0)
	{
		DestroyTimer(vTimerGamePre);
		vTimerGamePre = NULL;
	}
	//sprintf(vTest,"fPreBeginGameProcess() begin!!!");
	//DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
	fPreBeginGameProcess();
	//sprintf(vTest,"fPreBeginGameProcess() end!!!");
	//DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
m1:;
	if (vTimerMain > 0)
	{
		DestroyTimer(vTimerMain);
		vTimerMain = NULL;
	}
}

void fMainThreadDestroyed()
{
	fMapEnd();
	fCleanWorkMap();
	if (vStartCommands == 1)
	{
		fEndGame2(NULL);
	}
	if (vMainThreadDestroyedHandle)
	{
		RemoveEventHandler((TEventRegistrationHandle)vMainThreadDestroyedHandle);
		vMainThreadDestroyedHandle = NULL;
	}
}

void fCleanWorkMap()
{
	if (pMapGlobal)
	{
		delete pMapGlobal;
		pMapGlobal = NULL;
	}
	vMapGlobal = 0;
}

// Предварительный игровой процесс
void fPreBeginGameProcess()
{
	vNLocalPlayer = GetPlayerColor(GetLocalPlayer());
	
	if (vStartCommands == 1)
	{
		fStopCommands();
	}
	
	//if (fInitMapGlobal() == FALSE) goto m1;
	
	
	//vEndGameHandle = AddEventHandler(jeMainThreadDestroyed,(TJassEventCallback*)&fEndGame2,NULL);//jeMainThreadDestruction//jeMainThreadDestroyed
	
	/*vParamEndGame.pFun = (fFun*)&TimerGetElapsed;
	vParamEndGame.pTimerGame = &vTimerGame;
	if (hThreadEndGame)
	{
		hThreadEndGame = NULL;
	}
	hThreadEndGame = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadResultGame, (void*)&vParamEndGame, 0 , NULL);*/
	
	bIP = TRUE;
	
	fBeginGameProcess();
	
	vTextTagMap = CreateTextTag();
	SetTextTagText(vTextTagMap, "Vampirism_fire.dll v5", 0.023);
	SetTextTagPos(vTextTagMap, -500, -200, 0);
	SetTextTagColor(vTextTagMap, 255, 255, 255, 255);	
}

void fDataPlayers()
{
	vCountHumansUser = 0;
	vCountHumans = 0;
	vCountVampiresUser = 0;
	vCountVampires = 0;
	HPLAYER vPlayerAI;
	char vNickName[200];
	int vLen;
	bool vFlagAI;
	integer vNPlayerAI;
	int vvi;
	hTriggerChat = CreateTrigger();
	IncrementHandleReferences(hTriggerChat);
	TriggerAddAction(hTriggerChat, &fChat);
	fInitPlayer();
	for (vvi = 0; vvi < MAX_PLAYERS; vvi++)
	{
		vNPlayerAI = vvi;
		vFlagAI = FALSE;
		vPlayerAI = Player(vNPlayerAI);
		sprintf(vNickName,"%s\0",GetPlayerName(vPlayerAI));
		vLen = strlen(vNickName);
		if (vLen == 12 || vLen == 13)
		{
			if (memcmp(vNickName,"РРіСЂРѕРє ",10) == 0)
			{
				continue;
			}
		}
		if (vLen == 7)
		{
			if (memcmp(vNickName,"Human ",vLen-1) == 0)
			{
				vFlagAI = TRUE;
				goto m1;
			}
		}
		if (vLen == 8)
		{
			if (memcmp(vNickName,"Human ",vLen-2) == 0)
			{
				vFlagAI = TRUE;
				goto m1;
			}
		}
		if (vLen == 10)
		{
			if (memcmp(vNickName,"Vampire ",vLen-2) == 0)
			{
				vFlagAI = TRUE;
				goto m1;
			}
		}
		if (vFlagAI == FALSE)
		{
			if (vNPlayerAI >= 0 && vNPlayerAI <= 11)
			{
				pPlayerUser[vCountPlayersUser].vNPlayer = vNPlayerAI;
				pPlayerUser[vCountPlayersUser].vPlayer = vPlayerAI;
				sprintf(pPlayerUser[vCountPlayersUser].vName,"%s\0",vNickName);
				sprintf(pPlayerUser[vCountPlayersUser].vKeyPlayer,"%d\0",vNPlayerAI);
				pPlayerUser[vCountPlayersUser].vDead = FALSE;
				pPlayerUser[vCountPlayersUser].vLeave = FALSE;
				pPlayerUser[vCountPlayersUser].hTriggerPlayerLeave = CreateTrigger();
				IncrementHandleReferences(pPlayerUser[vCountPlayersUser].hTriggerPlayerLeave);
				TriggerAddAction(pPlayerUser[vCountPlayersUser].hTriggerPlayerLeave, &fActionPlayerLeave);
				TriggerRegisterPlayerEvent(pPlayerUser[vCountPlayersUser].hTriggerPlayerLeave,vPlayerAI,EVENT_PLAYER_LEAVE);
				if (hTriggerChat)TriggerRegisterPlayerChatEvent(hTriggerChat,vPlayerAI,"-host",true);
				if (hTriggerChat)TriggerRegisterPlayerChatEvent(hTriggerChat,vPlayerAI,"-stop",true);
				if (hTriggerChat)TriggerRegisterPlayerChatEvent(hTriggerChat,vPlayerAI,"-kill",false);
				if (hTriggerChat)TriggerRegisterPlayerChatEvent(hTriggerChat,vPlayerAI,"-start id",true);
				if (hTriggerChat)TriggerRegisterPlayerChatEvent(hTriggerChat,vPlayerAI,"-stop id",true);
				vCountPlayersUser++;
				if (vNPlayerAI >= 0 && vNPlayerAI <= 9)
				{
					vCountHumansUser++;
				}
				else
				{
					vCountVampiresUser++;
				}
			}
			//if (vvi < MAX_HUMAN_PLAYERS)
			//{
				//fCreateDataUnit(fGetUnit(ID_UNIT_MAIN_HUMAN1,vPlayerAI),THREAD_MAIN);
			//}
			continue;
		}
	m1:
		if (vNPlayerAI >= 0 && vNPlayerAI <= 9)
		{
			pHumanPlayerGlobal[vCountHumans].vParamPlayer.vAI = vNPlayerAI;
			pHumanPlayerGlobal[vCountHumans].vParamPlayer.vPlayer = vPlayerAI;
			vCountHumans++;
		}
		if (vNPlayerAI >= 10 && vNPlayerAI <= 11)
		{
			pVampirePlayerGlobal[vCountVampires].vParamPlayer.vAI = vNPlayerAI;
			pVampirePlayerGlobal[vCountVampires].vParamPlayer.vPlayer = vPlayerAI;
			vCountVampires++;
		}
	}
	if (vCountVampires == 1)
	{
		fSendAllPlayer("The vampire alone will not play.");
		//return 0;
	}
	//if (1)//vGameBegin == 0 && ((vCountHumans > 0 && vCountVampires == 2) || (vCountPlayersUser > 0 && (vCountHumans > 0 || vCountVampires > 0))))
	//{
		//if (vMapBases.fInit() == FALSE) return 0;
		//vAuthorization = 1;
		//vGameBegin = 1;
		//vTimerActionsGame = CreateTimer();
		//sprintf(vTest,"vCountHumans = %d",vCountHumans );
		//DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, vTest );
		//sprintf(vTest,"vCountVampires = %d",vCountVampires );
		//DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, vTest );
		//vSync = FALSE;
		//vCountForLoopGame = 0;
		/*char vKeyAIPlayer[3];
		for (int vvi = 0; vvi < vCountPlayersUser; vvi++)
		{
			for (int vvj = 0; vvj < MAX_PLAYERS; vvj++)
			{
				sprintf(vKeyAIPlayer,"%d\0",vvj);
				StoreInteger(vSyncCache,vKeyAIPlayer,pPlayerUser[vvi].vKeyPlayer,0);
			}
		}
		vSync = FALSE;
		vCountForLoopGame = 0;
		for (int vvi = 0; vvi < vCountPlayersUser; vvi++)
		{
			StoreInteger(vSyncCache,"LoadMap",pPlayerUser[vvi].vKeyPlayer,0);
		}*/
		/*for (int vvi = 0; vvi < vCountPlayersUser; vvi++)
		{
			if (pPlayerUser[vvi].vLeave == FALSE)
			{
				StoreInteger(vSyncCache3,"LoadMap",pPlayerUser[vvi].vKeyPlayer,0);
			}
		}*/
		//TimerStart(vTimerActionsGame,0.1,true,&fGame);
		//vTimerDataUnit2 = CreateTimer();
		//TimerStart(vTimerDataUnit2,1,true,&fDataUnit2);
	//}
}

integer fBeginGameProcess()
{
	hTriggerChat = 0;
	vStartCommandsGo = 0;
	vStartCommands = 0;
	if (fStartCommands() == 0) return 0;
	try
	{
		//fSetHost(GetHost2());
		// Пре
		vTimerPreActionsGame = CreateTimer();
		TimerStart(vTimerPreActionsGame,0.1,true,&fPreActionsGame);
	}
	catch(...)
	{
		return 0;
	}
	return 1;
}

void fPreActionsGame()
{
	if (vTimerPreActionsGame == NULL) return;
	vSync = FALSE;
	for (int vvi = 0; vvi < vCountPlayersUser; vvi++)
	{
		if (pPlayerUser[vvi].vLeave == FALSE &&
			pPlayerUser[vvi].vNPlayer < MAX_HUMAN_PLAYERS)
		{
			fCreateDataUnit(fGetUnit(ID_UNIT_MAIN_HUMAN1,pPlayerUser[vvi].vPlayer),THREAD_MAIN);
		}
	}
	if (vGameBegin == 0 && ((vCountHumans > 0 && vCountVampires == 2) || (vCountPlayersUser > 0 && (vCountHumans > 0 || vCountVampires > 0))))
	{
		if (fInitMapGlobal() == TRUE)
		{
			vMaxBase = fMaxBase();
			if (vMaxBase == 0)
			{
				//return 0;
			}
			if (vMapBases.fInit() == TRUE)
			{
				vAuthorization = 1;
				vGameBegin = 1;
				vStartGameSleep = TRUE;
				// fFogOfWar
				vTimerForFogOfWar = CreateTimer();
				TimerStart(vTimerForFogOfWar,1,true,&fFogOfWar);
				// Игровой процесс ботов (начальный)
				vTimerActionsGame = CreateTimer();
				TimerStart(vTimerActionsGame,0.01,false,&fGame);
				// Юниты
				vTimerDataUnit2 = CreateTimer();
				TimerStart(vTimerDataUnit2,1,true,&fDataUnit2);
				// Глобальный номер AI
				vGlobalNAI = 0;
			}
		}
	}
	// Юнит входит в регион
	//hTriggerUnitEntersWorldBoundsRegion = CreateTrigger();
	//IncrementHandleReferences(hTriggerUnitEntersWorldBoundsRegion);
	//TriggerAddAction(hTriggerUnitEntersWorldBoundsRegion, &fActionUnitEntersWorldBoundsRegion);
	//TriggerRegisterEnterRegion(hTriggerUnitEntersWorldBoundsRegion,hRegionWorldBounds,NULL);
m1:;
	if (vTimerPreActionsGame > 0)
	{
		DestroyTimer(vTimerPreActionsGame);
		vTimerPreActionsGame = NULL;
	}
}


DWORD WINAPI ThreadResultGame(void *p)
{
	sprintf(vBuf,"ThreadResultGame() N_1\0");
	fLog(999,vBuf);
	if (!p) return 0;
	sParamEndGame *pParamEndGame;
	int vCount;
	vCount = 0;
	pParamEndGame = (sParamEndGame*)p;
	sprintf(vBuf,"ThreadResultGame() N_1_2\0");
	fLog(999,vBuf);
	Sleep(5000);
	for (;;)
	{
		sprintf(vBuf,"ThreadResultGame() N_2\0");
		fLog(999,vBuf);
		try
		{
			sprintf(vBuf,"ThreadResultGame() N_3\0");
			fLog(999,vBuf);
			if (pParamEndGame->pFun(*pParamEndGame->pTimerGame) > 0)
			{
				vCount = 0;
			}
			sprintf(vBuf,"ThreadResultGame() N_4 vCount = %d\0",vCount);
			fLog(999,vBuf);
		}
		catch (...)
		{
			sprintf(vBuf,"ThreadResultGame() N_5\0");
			fLog(999,vBuf);
			fEndGame2(NULL);
			sprintf(vBuf,"ThreadResultGame() N_6\0");
			fLog(999,vBuf);
			return 0;
		}
		if (vCount > 0)
		{
			sprintf(vBuf,"ThreadResultGame() N_7\0");
			fLog(999,vBuf);
			fEndGame2(NULL);
			/*if (hJassApi)
			{
				FreeLibrary(hJassApi);
			}
			if (hJassApi_2)
			{
				FreeLibrary(hJassApi_2);
			}*/
			sprintf(vBuf,"ThreadResultGame() N_8\0");
			fLog(999,vBuf);
			return 0;
		}
		vCount++;
		Sleep(1000);
	}
	sprintf(vBuf,"ThreadResultGame() N_9\0");
	fLog(999,vBuf);
	return 0;
}

void fActionPlayerLeave()
{
	sPlayerUser * pPlayerUser2 = fGetPlayerUser(GetTriggeringTrigger());
	if (pPlayerUser2 == NULL) return;
	pPlayerUser2->vLeave = TRUE;
	sprintf(vTest,"TUT10!!!");
	DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
}

sPlayerUser * fGetPlayerUser(HTRIGGER hTrigger)
{
	if (hTrigger == NULL) return NULL;
	int vvi;
	for (vvi = 0; vvi < vCountPlayersUser; vvi++)
	{
		if (pPlayerUser[vvi].hTriggerPlayerLeave == hTrigger)
		{
			return &pPlayerUser[vvi];
		}
	}
	return NULL;
}

integer fBeginGameProcessAI(integer vNPlayerAI)
{
	return 1;
}

void fGame()
{
	int vRandBase;
	int vCountBase;
	int vvi,vvj;
	bool vFlag;
	int vRandMain;
	StackForUnits *pStackForUnits;
	vRandMain = 0;
	vRandMain = GetRandomInt(0,vCountHumans-1);
	if (vCountHumans > 0)
	{
		//vTimerGameHumans = CreateTimer();
		for (vvi = 0; vvi < vCountHumans; vvi++)
		{
			if (pHumanPlayerGlobal[vvi].vParamPlayer.vTimerPlayer > 0)
			{
				DestroyTimer(pHumanPlayerGlobal[vvi].vParamPlayer.vTimerPlayer);
			}
			pHumanPlayerGlobal[vvi].fInit();
			pHumanPlayerGlobal[vvi].vBase.fInit();
			// Выбераем базу
			vCountBase = 0;
			vRandBase = 0;
			while(vCountBase < vMapBases.MAP_MAX_BASE)
			{
				if (vvi < 6) vRandBase = GetRandomInt(0,vMaxBase);//rand() % (vMaxBase + 1);
				else vRandBase++;
				if(vRandBase != 0)
				{
					vFlag = FALSE;
					for (vvj = 0; vvj < vCountHumans; vvj++)
					{
						if (pHumanPlayerGlobal[vvj].vBase.vNBase == vRandBase)
						{
							vFlag = TRUE;
							break;
						}
					}
					if (vFlag == FALSE)
					{
						pHumanPlayerGlobal[vvi].vBase.vNBase = vRandBase;
						pHumanPlayerGlobal[vvi].vBase.vMainWall = NULL;
						pHumanPlayerGlobal[vvi].vBase.vQCells = vMapBases.fQCellsToBase(&pHumanPlayerGlobal[vvi].vBase);
						if (pHumanPlayerGlobal[vvi].vBase.vQCells < 400)
						{
							pHumanPlayerGlobal[vvi].vBase.vNBase = DO_NOT_FIND_BASE;
						}
						else
						{
							vMapBases.fDetermineTheBeginningOfTheBaseOneCell(&pHumanPlayerGlobal[vvi].vBase);
							if (pHumanPlayerGlobal[vvi].vBase.vQRepairPos < 6)
							{
								vMapBases.fDetermineTheBeginningOfTheBase(&pHumanPlayerGlobal[vvi].vBase);
							}
							if (pHumanPlayerGlobal[vvi].vBase.vMainWall != NULL &&
								((pHumanPlayerGlobal[vvi].vBase.vMainWall->vRemoteness > 150 && vvi%vCountHumans == vRandMain) || vvi%vCountHumans != vRandMain))
							{
								if (vMapBases.fZoneTower(&pHumanPlayerGlobal[vvi].vBase) == FALSE)
								{
									pHumanPlayerGlobal[vvi].vBase.vNBase = DO_NOT_FIND_BASE;
								}
								else
								{
									if (vMapBases.fZoneTowerTemp2(&pHumanPlayerGlobal[vvi].vBase) == TRUE)
									{
										if ((pHumanPlayerGlobal[vvi].vBase.vQTowerInZoneMainWall < 20 && vvi%vCountHumans != vRandMain) ||
											(pHumanPlayerGlobal[vvi].vBase.vQTowerInZoneMainWall < 30 && vvi%vCountHumans == vRandMain))//vMapBases.fQSmallCageForTower(&pHumanPlayerGlobal[vvi].vBase) < 80)
										{
											pHumanPlayerGlobal[vvi].vBase.vNBase = DO_NOT_FIND_BASE;
										}
										else
										{
											pHumanPlayerGlobal[vvi].vBase.pHumanPlayer = &pHumanPlayerGlobal[vvi];
											pHumanPlayerGlobal[vvi].vFlagDearBase = TRUE;
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 0) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","красный");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 1) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","синий");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 2) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","салатовый");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 3) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","фиолетовый");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 4) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","жёлтый");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 5) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","оранжевый");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 6) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","зеленый");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 7) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","розовый");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 8) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","серый");
											if (pHumanPlayerGlobal[vvi].vParamPlayer.vAI == 9) sprintf(pHumanPlayerGlobal[vvi].vBase.vColor,"%s\0","голубой");
											break;
										}
									}
									else
									{
										pHumanPlayerGlobal[vvi].vBase.vNBase = DO_NOT_FIND_BASE;
									}
								}
							}
							else
							{
								pHumanPlayerGlobal[vvi].vBase.vNBase = DO_NOT_FIND_BASE;
							}
						}
					}
				}
				vCountBase++;
			}
			if (pHumanPlayerGlobal[vvi].vBase.vNBase == DO_NOT_FIND_BASE)
			{
				continue;
			}
			pHumanPlayerGlobal[vvi].vBase.vSlayerBaze = TRUE;
			if (vvi%vCountHumans == vRandMain) pHumanPlayerGlobal[vvi].vBase.vSlayerBaze = FALSE;
			// Базы может также не оказаться вообще, тогда игрок ливает в начале игры, это происходит на одноклеточных проходах баз. Они не допустимы на базе.
			/*if (pHumanPlayerGlobal[vvi].vBase.vNBase == 1)//DO_NOT_FIND_BASE)
			{
				pHumanPlayerGlobal[vvi].vBase.vMainWall = &vMapBases.vMap[13*256+2];
				pHumanPlayerGlobal[vvi].vBase.vBeginningOfBase = pHumanPlayerGlobal[vvi].vBase.vMainWall->vRemoteness;
			}*/
			pHumanPlayerGlobal[vvi].vParamPlayer.fInit(200,50);
			pHumanPlayerGlobal[vvi].vActionStackForUnits.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsGoTo.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsResearch.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsWorkers.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsSlayer.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsMainHuman.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsTower.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsFurbolgs.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsTracker.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsHeal.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsOrc.fInitStackForUnits(&pHumanPlayerGlobal[vvi].vParamPlayer);
			//
			fCreateDataUnit(fGetUnit(ID_UNIT_MAIN_HUMAN1,pHumanPlayerGlobal[vvi].vParamPlayer.vPlayer),THREAD_MAIN);
			// MainHuman
			pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].vIdForComments = COMMENT_MAIN_HUMAN;
			pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].vId = (unsigned short)pHumanPlayerGlobal[vvi].vParamPlayer.vAI;
			pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].pDataUnit = vDataUnits[pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].vId].pDataUnit; 

			pHumanPlayerGlobal[vvi].vActionStackForUnits.fAddStackForUnits(pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].vId,
																		   pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].pDataUnit,
																		   COMMENT_MAIN_HUMAN);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsMainHuman.fAddStackForUnits(pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].vId,
																		   pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].pDataUnit,
																		   COMMENT_MAIN_HUMAN);
			pHumanPlayerGlobal[vvi].vActionStackForUnitsGoTo.fAddStackForUnits(pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].vId,
																		   pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].pDataUnit,
																		   COMMENT_MAIN_HUMAN);
			pHumanPlayerGlobal[vvi].vMainHuman.vUnitParam.pDataUnits = &vDataUnits[pHumanPlayerGlobal[vvi].vParamPlayer.vUnit[COMMENT_MAIN_HUMAN].vId];
			fInitSpellsUnitsByHuman(&pHumanPlayerGlobal[vvi]);
			// Инициализация действий
			pHumanPlayerGlobal[vvi].vStackActions.fInitStackActions(&pHumanPlayerGlobal[vvi].vParamPlayer);
			// TimerPlayer
			pHumanPlayerGlobal[vvi].vParamPlayer.vTimerPlayer = CreateTimer();//vTimerGameHumans;
			TimerStart(pHumanPlayerGlobal[vvi].vParamPlayer.vTimerPlayer,0.1,true,&fGameHuman);
			SaveInteger(vHT,pHumanPlayerGlobal[vvi].vParamPlayer.vTimerPlayer,CONST_AI_PLAYER,(integer)&pHumanPlayerGlobal[vvi]);
		}
	}
	//vMapBases.fWriteFileTGA();
	if (vCountVampires > 0)
	{
		for (vvi = 0; vvi < vCountVampires; vvi++)
		{
			if (pVampirePlayerGlobal[vvi].vParamPlayer.vTimerPlayer > 0)
			{
				DestroyTimer(pVampirePlayerGlobal[vvi].vParamPlayer.vTimerPlayer);
			}
			//
			pVampirePlayerGlobal[vvi].fInit();
			pVampirePlayerGlobal[vvi].vParamPlayer.fInit(50,50);
			pVampirePlayerGlobal[vvi].vActionStackForUnits.fInitStackForUnits(&pVampirePlayerGlobal[vvi].vParamPlayer);
			pVampirePlayerGlobal[vvi].vFarmBase = DO_NOT_FIND_BASE;
			pVampirePlayerGlobal[vvi].vVampire.fInit();
			// Timer
			pVampirePlayerGlobal[vvi].vParamPlayer.vTimerPlayer = CreateTimer();
			TimerStart(pVampirePlayerGlobal[vvi].vParamPlayer.vTimerPlayer,0.1,true,&fGameVampire);
			SaveInteger(vHT,pVampirePlayerGlobal[vvi].vParamPlayer.vTimerPlayer,CONST_AI_PLAYER,(integer)&pVampirePlayerGlobal[vvi]);
		}
	}
	//
	if (vCountVampires == 2)
	{
		pVampirePlayerGlobal[0].pPartner = &pVampirePlayerGlobal[1];
		pVampirePlayerGlobal[1].pPartner = &pVampirePlayerGlobal[0];
	}
	if (vCountVampires == 1)
	{
		pVampirePlayerGlobal[0].pPartner = NULL;
	}
	if (vCountVampires >= 1)
	{
		pDataVampires->fInit();
		pDataVampires->vActionStackForUnitsEnemy.fInitStackForUnits(&pVampirePlayerGlobal[0].vParamPlayer);
		//
		pDataVampires->pPutGlobal = new struct DataGoTo;
		pDataVampires->pPutGlobal->pFillMap = new unsigned short[vSizeMap];
		pDataVampires->pPutGlobal->vMaxRect = vSizeMap;
		pDataVampires->pPutGlobal->vMassRect = new struct sRect[vSizeMap];
		pDataVampires->pPutGlobal->vMassRect2 = new unsigned int[vSizeMap];
		pDataVampires->pPutGlobal->vActionStr = (char*) malloc(sizeof(char)*10);
		//
		pDataVampires->pPutGlobal->vStartThread = FALSE;
		pDataVampires->pPutGlobal->vResult = 0;
		pDataVampires->pPutGlobal->hThreadGoTo = NULL;
	}
	//
	if (vCountHumans >= 1)
	{
		pDataHumans->fInit();
		pDataHumans->vActionStackForUnitsEnemy.fInitStackForUnits(&pHumanPlayerGlobal[0].vParamPlayer);
	}
m11:
	if (vTimerActionsGame > 0)
	{
		DestroyTimer(vTimerActionsGame);
		vTimerActionsGame = NULL;
	}
}

void fKillUnitsOfPlayer(player vPlayer)
{
	group g=CreateGroup();
	unit u;
	GroupEnumUnitsOfPlayer(g,vPlayer,0);
	do
	{
		u=FirstOfGroup(g);
		GroupRemoveUnit(g,u);
		if (u > 0)
		{
			KillUnit(u);
		}
	}
	while (u != 0);
}

void fKillUnitsBots()
{
	int vvi;
	if (vCountHumans > 0)
	{
		for (vvi = 0; vvi < vCountHumans; vvi++)
		{
			fKillUnitsOfPlayer(pHumanPlayerGlobal[vvi].vParamPlayer.vPlayer);
		}
	}
	if (vCountVampires > 0)
	{
		for (vvi = 0; vvi < vCountVampires; vvi++)
		{
			fKillUnitsOfPlayer(pVampirePlayerGlobal[vvi].vParamPlayer.vPlayer);
		}
	}
}

void fEndGame()
{
	sprintf(vBuf,"fEndGame()\0");
	fLog(999,vBuf);
	fKillUnitsBots();
	fStopCommands();
}

void fEndGame2(Pointer *p)
{
	sprintf(vBuf,"fEndGame2(Pointer *p)\0");
	fLog(999,vBuf);
	//if (vStartMap == 0) return;
	vEndGame2 = 1;
	fStopCommands();
	if (hThreadEndGame)
	{
		TerminateThread(hThreadEndGame,0);
	}
	//UnregisterJassNative("fPreBeginGameProcess");
	/*if (vEndGameHandle)
	{
		RemoveEventHandler((TEventRegistrationHandle)vEndGameHandle);
	}*/
	/*if (hJassApi)
	{
		FreeLibrary(hJassApi);
	}*/
	/*if (hJassApi_2)
	{
		FreeLibrary(hJassApi_2);
	}*/
	vEndGame2 = 0;
}

VampirePlayer * fGetVampirePlayer(HTIMER vTimer)
{
	if (vTimer == NULL) return 0;
	try
	{
		for (int vvi = 0; vvi < vCountVampires; vvi++)
		{
			if (&pVampirePlayerGlobal[vvi])
			{
				if (&pVampirePlayerGlobal[vvi].vParamPlayer)
				{
					if (pVampirePlayerGlobal[vvi].vParamPlayer.vTimerPlayer == vTimer)
					{
						return &pVampirePlayerGlobal[vvi];
					}
				}
			}
		}
	}
	catch (...)
	{
		return 0;
	}
	return 0;
}

HumanPlayer * fGetHumanePlayer(HTIMER vTimer)
{
	if (vTimer == NULL) return 0;
	try
	{
		for (int vvi = 0; vvi < vCountHumans; vvi++)
		{
			if (&pHumanPlayerGlobal[vvi])
			{
				if (&pHumanPlayerGlobal[vvi].vParamPlayer)
				{
					if (pHumanPlayerGlobal[vvi].vParamPlayer.vTimerPlayer == vTimer)
					{
						return &pHumanPlayerGlobal[vvi];
					}
				}
			}
		}
	}
	catch (...)
	{
		return 0;
	}
	return 0;
}

unsigned short fGoToAction(unsigned short vIdDataUnit, integer vInt, unsigned short vAction)
{
	//if (fSync(fGetDataUnit(vIdDataUnit)) == FALSE) return 0;
	//if (fCheckSync(fGetDataUnit(vIdDataUnit)) == FALSE) return 0;
	if (fGetActionUnit(vIdDataUnit) == ACTION_WAITING && fGetActionUnitFinish(vIdDataUnit) == 1)
	{
		if (fIsPosUnit(vIdDataUnit,vInt) == TRUE)
		{
			vDataUnits[vIdDataUnit].pDataUnit->vLastAction = vAction;
			fFinishActionUnit(vIdDataUnit);
			return 1;
		}
		fFreeActionUnit(vIdDataUnit);
		if (fUnitGoToInt(vIdDataUnit,vInt,vAction,LIMIT_GOTO_MAINHUMAN) == 1)
		{
			return 1;
		}
		else
		{
			fFinishActionUnit(vIdDataUnit);
		}
	}
	return 0;
}

bool fIsEnoughResourses(HPLAYER vPlayer, ParamPlayer *pParamPlayer, integer vNResearch, integer *vId)
{
	if (pParamPlayer == NULL) return FALSE;
	if (vNResearch < 0 || vNResearch >= pParamPlayer->MAX_RESEARCH) return FALSE;
	if (vPlayer == NULL) return FALSE;
	integer vGoldPlayer;
	integer vWoodPlayer;
	integer vGoldUnit;
	integer vWoodUnit;
	*vId = 0;
	if (fGetResoursesResearch(pParamPlayer,vNResearch,vId,&vGoldUnit,&vWoodUnit) == FALSE) return FALSE;
	if (*vId <= 0) return FALSE;
	vGoldPlayer = GetPlayerState(vPlayer,PLAYER_STATE_RESOURCE_GOLD);
	vWoodPlayer = GetPlayerState(vPlayer,PLAYER_STATE_RESOURCE_LUMBER);
	if(!(vGoldPlayer >= vGoldUnit && vWoodPlayer >= vWoodUnit))
	{
		return FALSE;
	}
	return TRUE;
}

bool fIsEnoughResourses(HPLAYER vPlayer, integer vId)
{
	if (vPlayer == NULL || vId == NULL) return FALSE;
	integer vGoldPlayer;
	integer vWoodPlayer;
	integer vFoodPlayer;
	integer vFoodPlayerCap;
	integer vGoldUnit;
	integer vWoodUnit;
	integer vFoodUnit;
	if (fGetResoursesUnit(vId,&vGoldUnit,&vWoodUnit) == FALSE) return FALSE;
	vGoldPlayer = GetPlayerState(vPlayer,PLAYER_STATE_RESOURCE_GOLD);
	vWoodPlayer = GetPlayerState(vPlayer,PLAYER_STATE_RESOURCE_LUMBER);
	if(!(vGoldPlayer >= vGoldUnit && vWoodPlayer >= vWoodUnit))
	{
		return FALSE;
	}
	vFoodPlayerCap = GetPlayerState(vPlayer,PLAYER_STATE_RESOURCE_FOOD_CAP);
	vFoodPlayer = GetPlayerState(vPlayer,PLAYER_STATE_RESOURCE_FOOD_USED);
	vFoodUnit = GetFoodUsed(vId);
	if(!(vFoodPlayer + vFoodUnit <= vFoodPlayerCap) && vFoodUnit != 0)
	{
		return FALSE;
	}
	return TRUE;
}

unsigned short fTrainAction(HPLAYER vPlayer, ActionStackForUnits * pActionStackForUnits, unsigned short vComment, integer vIdDataUnitTrain, unsigned short vCount)
{
	if (vIdDataUnitTrain <= 0) return 0;
	DataUnit *pDataUnit;
	unsigned short vFlag = 0;
	pDataUnit = pActionStackForUnits->fGetDataUnit(vComment);
	if (pDataUnit && (unsigned int)pDataUnit != 0xdddddddd)
	{
		if (pDataUnit->Postroeno == TRUE)
		{
			for (unsigned short vvi = 0; vvi < vCount; vvi++)
			{
				if (fIsEnoughResourses(vPlayer,vIdDataUnitTrain) == TRUE)
				{
					if (IssueImmediateOrderById(pDataUnit->WhichUnit,vIdDataUnitTrain) == TRUE)
					{
						vFlag = 1;
					}
				}
			}
			return vFlag;
		}
	}
	return vFlag;
}

unsigned short fTrainActionResearch(ParamPlayer *pParamPlayer, DataUnit *pDataUnit, integer vNResearch)
{
	integer vId; 
	unsigned short vFlag = 0;
	if (pDataUnit && (unsigned int)pDataUnit != 0xdddddddd)
	{
		if (pDataUnit->Postroeno == TRUE)
		{
			if (fIsEnoughResourses(pParamPlayer->vPlayer,pParamPlayer,vNResearch,&vId) == TRUE)
			{
				if(IssueImmediateOrderById(pDataUnit->WhichUnit,vId) == TRUE)
				{
					pDataUnit->vNResearch = vNResearch;
					vFlag = 1;
				}
			}
			return vFlag;
		}
	}
	return vFlag;
}

real fXCenter(integer vId, unsigned short vX2)
{
	if (vId <= 0) return FALSE;
	if (vX2 < 0 || vX2 >= vW3) return FALSE;
	real vX;
	real vRadius;
	vRadius = fRadius_Unit(vId);
	vX = fGetMinIX2RX(vX2) + vRadius;
	return vX;
}

real fYCenter(integer vId, unsigned short vY2)
{
	if (vId <= 0) return FALSE;
	if (vY2 < 0 || vY2 >= vH3) return FALSE;
	real vY;
	real vRadius;
	vRadius = fRadius_Unit(vId);
	vY = fGetMinIY2RY(vY2) - vRadius;
	return vY;
}

real fXCenter(integer vId, unsigned int vIntIn)
{
	if (vId <= 0) return FALSE;
	if (vIntIn < 0 || vIntIn >= vSizeMap) return FALSE;
	real vX;
	real vRadius;
	unsigned short vX2;
	vRadius = fRadius_Unit(vId);
	vX2 = fConvertIToX(vIntIn);
	vX = fGetMinIX2RX(vX2) + vRadius;
	return vX;
}

real fYCenter(integer vId, unsigned int vIntIn)
{
	if (vId <= 0) return FALSE;
	if (vIntIn < 0 || vIntIn >= vSizeMap) return FALSE;
	real vY;
	real vRadius;
	unsigned short vY2;
	vRadius = fRadius_Unit(vId);
	vY2 = fConvertIToY(vIntIn);
	vY = fGetMinIY2RY(vY2) - vRadius;
	return vY;
}

bool fUnitToRect(DataUnit *pDataUnit, HRECT vRect)
{
	if (pDataUnit == NULL || vRect == 0) return FALSE;
	real vX,vY;
	vX = GetUnitX(pDataUnit->WhichUnit);
	vY = GetUnitY(pDataUnit->WhichUnit);
	if (fIsXYToRect(vX,vY,vRect) == TRUE)
	{
		return TRUE;
	}
	return FALSE;
}

bool fIsXYToRect(real vX, real vY, HRECT vRect)
{
	real vMinX,vMinY,vMaxX,vMaxY;
	vMinX = GetRectMinX(vRect);
	vMinY = GetRectMinY(vRect);
	vMaxX = GetRectMaxX(vRect);
	vMaxY = GetRectMaxY(vRect);
	if (vMinX <= vX && vMaxX >= vX &&
		vMinY <= vY && vMaxY >= vY)
	{
		return TRUE;
	}
	return FALSE;
}

bool fTransferRes(HPLAYER vPlayerFrom, HPLAYER vPlayerToWhom, HPLAYERSTATE vRes, integer vCost)
{
	integer vResPlayerFrom;
	integer vResPlayerToWhom;
	vResPlayerFrom = GetPlayerState(vPlayerFrom,vRes);
	vResPlayerToWhom = GetPlayerState(vPlayerToWhom,vRes);
	if (vResPlayerFrom-vCost >= 0)
	{
		SetPlayerState(vPlayerFrom,vRes,vResPlayerFrom-vCost);
		SetPlayerState(vPlayerToWhom,vRes,vResPlayerToWhom+vCost);
		return TRUE;
	}
	return FALSE;
}

bool fBuyAUnit(unsigned short vShop, integer vIdUnit, sInventory *vInventory)
{
	if (vShop == NULL || vIdUnit == NULL) return FALSE;
	vInventory->vG = fG(vDataUnits[vShop].pDataUnit->LastCoordinates.X,vDataUnits[vShop].pDataUnit->LastCoordinates.Y,
		                vInventory->pDataUnit->LastCoordinates.X,vInventory->pDataUnit->LastCoordinates.Y);
	if (vInventory->vG > 128 * 5) return FALSE;
	vInventory->vGoldPlayer = GetPlayerState(vInventory->pDataUnit->vPlayer,PLAYER_STATE_RESOURCE_GOLD);
	vInventory->vWoodPlayer = GetPlayerState(vInventory->pDataUnit->vPlayer,PLAYER_STATE_RESOURCE_LUMBER);
	fGetResoursesUnit(vIdUnit,&vInventory->vGold,&vInventory->vWood);
	if (vInventory->vGoldPlayer - vInventory->vGold >= 0 &&
		vInventory->vWoodPlayer - vInventory->vWood >= 0)
	{
		if (IssueNeutralImmediateOrderById(vInventory->pDataUnit->vPlayer, vDataUnits[vShop].pDataUnit->WhichUnit, vIdUnit) == TRUE)
		{
			return TRUE;
		}
	}
	return FALSE;
}

bool fBuyItem(unsigned short vShop, integer vIdItem, sInventory *vInventory)
{
	if (vShop == NULL || vIdItem == NULL || vInventory == NULL) return FALSE;
	vInventory->vG = fG(vDataUnits[vShop].pDataUnit->LastCoordinates.X,vDataUnits[vShop].pDataUnit->LastCoordinates.Y,
		                vInventory->pDataUnit->LastCoordinates.X,vInventory->pDataUnit->LastCoordinates.Y);
	if (vInventory->vG > 128 * 5) return FALSE;
	if (vInventory->vQFreeSlots() <= 0) return FALSE;
	vInventory->vGoldPlayer = GetPlayerState(vInventory->pDataUnit->vPlayer,PLAYER_STATE_RESOURCE_GOLD);
	vInventory->vWoodPlayer = GetPlayerState(vInventory->pDataUnit->vPlayer,PLAYER_STATE_RESOURCE_LUMBER);
	fGetResoursesItem(vIdItem,&vInventory->vGold,&vInventory->vWood);
	if (vInventory->vGoldPlayer - vInventory->vGold >= 0 &&
		vInventory->vWoodPlayer - vInventory->vWood >= 0)
	{
		if (IssueNeutralImmediateOrderById(vInventory->pDataUnit->vPlayer, vDataUnits[vShop].pDataUnit->WhichUnit, vIdItem) == TRUE)
		{
			vInventory->fRefreshInventory();
			return TRUE;
		}
	}
	return FALSE;
}

void fActionItemsGold()
{
	HTIMER t = GetExpiredTimer();
	if (LoadInteger(vHT,t,CONST_FLAG_FOR_GOLD_COIN) == 0) return;
	HITEM vItem = GetEnumItem();
	//String vName = GetItemName(vItem);
	integer vIdItem = GetItemTypeId(vItem);
	//int vLen;
	if (vIdItem == ID_ITEM_GOLD1 || vIdItem == ID_ITEM_GOLD3)
	{
		HPLAYER vPlayer = LoadPlayerHandle(vHT,t,CONST_PLAYER_FOR_GOLD_COIN);
		if (IsItemVisible(vItem) == FALSE) return;
		integer vIdUnitForGoldCoin = LoadInteger(vHT,t,CONST_ID_UNIT_FOR_GOLD_COIN);
		real vG;
		if (fIsVampire(vIdUnitForGoldCoin) == TRUE)
		{
			vG = fG(LoadReal(vHT,t,CONST_HUNIT_VAMPIRE_X),
				    LoadReal(vHT,t,CONST_HUNIT_VAMPIRE_Y),
					GetItemX(vItem),
					GetItemY(vItem));
			if (vG < 128*16)
			{
				SaveInteger(vHT,t,CONST_FLAG_FOR_GOLD_COIN,0);
				SaveItemHandle(vHT,t,CONST_GOLD_COIN,vItem);
				return;
			}
		}
		if (fIsSlayer(vIdUnitForGoldCoin) == TRUE)
		{
			SaveInteger(vHT,t,CONST_FLAG_FOR_GOLD_COIN,0);
			SaveItemHandle(vHT,t,CONST_GOLD_COIN,vItem);
		}
		
	}
	/*vLen = strlen(vName);
	if (memcmp(vName,"Small gold Coin",vLen) == 0 ||
		memcmp(vName,"Large gold Coin",vLen) == 0)
	{
		SaveItemHandle(vHT,GetExpiredTimer(),20,vItem);
	}*/
}

void fRefreshLastCoordinates(DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return;
	pDataUnit->LastCoordinates.X = GetUnitX(pDataUnit->WhichUnit);
	pDataUnit->LastCoordinates.Y = GetUnitY(pDataUnit->WhichUnit);
}

bool fSync(DataUnit *pDataUnit, real vTimerGetElapsed)
{
	if (pDataUnit == NULL) return FALSE;
	if (pDataUnit->vSync == TRUE) return TRUE;
	try
	{
		sprintf(pDataUnit->vKeyLocalPlayer,"%d\0",GetPlayerColor(GetLocalPlayer()));
		StoreReal(vSyncCache2,pDataUnit->vKeyUnit,pDataUnit->vKeyLocalPlayer,vTimerGetElapsed);
		SyncStoredReal(vSyncCache2,pDataUnit->vKeyUnit,pDataUnit->vKeyLocalPlayer);
		StoreReal(vSyncCache2,pDataUnit->vKeyUnit,pDataUnit->vKeyLocalPlayer,0);
		sprintf(pDataUnit->vKeyLocalPlayer,"\0");
		pDataUnit->vSync = TRUE;
		return TRUE;
	}
	catch(...)
	{
	}
	return FALSE;
}

bool fCheckSync(DataUnit *pDataUnit, real vTimerGetElapsed)
{
	if (pDataUnit == NULL) return FALSE;
	if (pDataUnit->vSync == FALSE) return FALSE;
	int vvi;
	real vTimeSync;
	real vTimeGetStoredReal;
	bool vFirst;
	vFirst = FALSE;
	if (pDataUnit->vTimeSync == 0)
	{
		vTimeSync = 0;
	}
	else
	{
		vTimeSync = vTimerGetElapsed - pDataUnit->vTimeSync;
	}
	for (vvi = 0; vvi < vCountPlayersUser; vvi++)
	{
		if (pPlayerUser[vvi].vLeave == FALSE)
		{
			if (vFirst == FALSE) {
				vTimeGetStoredReal = GetStoredReal(vSyncCache2,pDataUnit->vKeyUnit,pPlayerUser[vvi].vKeyPlayer);
				vFirst = TRUE;
			}
			sprintf(vTest,"GetStoredInteger!!! vNPlayer = %d GetUnitTypeId(pHumanPlayer->pDataUnit->WhichUnit) = %d vTimerGetElapsed = %f",pDataUnit->vNPlayer,GetUnitTypeId(pDataUnit->WhichUnit),vTimerGetElapsed);
			fLog(888,vTest);
			if (vTimeGetStoredReal == 0) return FALSE;
			sprintf(vTest,"vTimeGetStoredReal = %f",vTimeGetStoredReal);
			fLog(888,vTest);
			if (vTimeGetStoredReal != 0 &&
				GetStoredReal(vSyncCache2,pDataUnit->vKeyUnit,pPlayerUser[vvi].vKeyPlayer) == 0)
			{
				if (vTimeSync != 0 &&
					vTimeSync > 8 &&
					vTimeSync <= 9)
				{
					sprintf(vTest,"TUT2!!!");
					DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
					fLog(888,vTest);
					if (pDataUnit->vSyncClean == TRUE)
					{
						pDataUnit->vSyncClean = FALSE;
					}
				}
				else if (vTimeSync != 0 &&
						vTimeSync > 15)
				{
					if (vSync == TRUE)
					{
						fCheckLeavePlayers();
						if (vSync == FALSE)
						{
							pDataUnit->vSync = FALSE;
							pDataUnit->vSyncClean = FALSE;
							return FALSE;
						}
					}
					pDataUnit->vSync = FALSE;
					pDataUnit->vSyncClean = FALSE;
					return FALSE;
				}
				else if (vTimeSync != 0 &&
					    vTimeSync > 9 &&
						vTimeSync <= 10)
				{
					for (vvi = 0; vvi < vCountPlayersUser; vvi++)
					{
						if (pPlayerUser[vvi].vLeave == FALSE)
						{
							if (fCheckLeftToNickName(GetPlayerName(pPlayerUser[vvi].vPlayer)) == TRUE)
							{
								pPlayerUser[vvi].vLeave = TRUE;
								fDelDataUnit(pPlayerUser[vvi].vNPlayer);
							}
						}
					}
				}
				else if (vTimeSync != 0 &&
					    vTimeSync > 10 &&
						vTimeSync <= 15)
				{
					if (vSync == FALSE)
					{
						if (fCheckLeavePlayers() == FALSE)
						{
							pDataUnit->vSync = FALSE;
							pDataUnit->vSyncClean = FALSE;
							return FALSE;
						}
					}
					if (vSync == TRUE)
					{
						return FALSE;
					}
				}
				else
				{
					sprintf(vTest,"GetStoredInteger return FALSE;!!! vNPlayer = %d GetUnitTypeId(pHumanPlayer->pDataUnit->WhichUnit) = %d vTimerGetElapsed = %f",pDataUnit->vNPlayer,GetUnitTypeId(pDataUnit->WhichUnit),vTimerGetElapsed);
					fLog(888,vTest);
					return FALSE;
				}
			}
			sprintf(vTest,"GetStoredInteger end!!! vNPlayer = %d GetUnitTypeId(pHumanPlayer->pDataUnit->WhichUnit) = %d vTimerGetElapsed = %f",pDataUnit->vNPlayer,GetUnitTypeId(pDataUnit->WhichUnit),vTimerGetElapsed);
			fLog(888,vTest);
		}
	}
	pDataUnit->vSync = FALSE;
	pDataUnit->vSyncClean = FALSE;
	return TRUE;			
}

bool fCheckLeavePlayers()
{
	int vvi;
	if (vSync == TRUE) goto m1;
	for (vvi = 0; vvi < vCountPlayersUser; vvi++)
	{
		if (pPlayerUser[vvi].vLeave == FALSE)
		{
			StoreInteger(vSyncCache2,"CheckLeavePlayers",pPlayerUser[vvi].vKeyPlayer,0);
		}
		else
		{
			if (HaveStoredInteger(vSyncCache2,"CheckLeavePlayers",pPlayerUser[vvi].vKeyPlayer) == TRUE)
			{
				fLog(1000,"1000");
				FlushStoredInteger(vSyncCache2,"CheckLeavePlayers",pPlayerUser[vvi].vKeyPlayer);
				fLog(1001,"1001");
			}
		}
	}
	sprintf(vKeyLocalPlayer,"%d\0",GetPlayerColor(GetLocalPlayer()));
	StoreInteger(vSyncCache2,"CheckLeavePlayers",vKeyLocalPlayer,1);
	SyncStoredInteger(vSyncCache2,"CheckLeavePlayers",vKeyLocalPlayer);
	StoreInteger(vSyncCache2,"CheckLeavePlayers",vKeyLocalPlayer,0);
	sprintf(vKeyLocalPlayer,"\0");
	vSync = TRUE;
	return TRUE;
m1:
	for (vvi = 0; vvi < vCountPlayersUser; vvi++)
	{
		if (pPlayerUser[vvi].vLeave == FALSE)
		{
			if (GetStoredInteger(vSyncCache2,"CheckLeavePlayers",pPlayerUser[vvi].vKeyPlayer) == 0 &&
				fCheckLeftToNickName(GetPlayerName(pPlayerUser[vvi].vPlayer)) == TRUE)
			{
				pPlayerUser[vvi].vLeave = TRUE;
				fDelDataUnit(pPlayerUser[vvi].vNPlayer);
			}
			if (HaveStoredInteger(vSyncCache2,"CheckLeavePlayers",pPlayerUser[vvi].vKeyPlayer) == TRUE)
			{
				fLog(3000,"3000");
				FlushStoredInteger(vSyncCache2,"CheckLeavePlayers",pPlayerUser[vvi].vKeyPlayer);
				fLog(3001,"3001");
			}
		}
	}
	vSync = FALSE;
	return TRUE;
}

bool fFreeSync(DataUnit *pDataUnit, real vTimerGetElapsed)
{
	if (pDataUnit == NULL) return FALSE;
	if (pDataUnit->vSyncClean == TRUE) return TRUE;
	try
	{
		int vvi;
		for (vvi = 0; vvi < vCountPlayersUser; vvi++)
		{
			if (pPlayerUser[vvi].vLeave == FALSE)
			{
				if (GetStoredReal(vSyncCache2,pDataUnit->vKeyUnit,pPlayerUser[vvi].vKeyPlayer) != 0 &&
					vTimerGetElapsed - GetStoredReal(vSyncCache2,pDataUnit->vKeyUnit,pPlayerUser[vvi].vKeyPlayer) < 0.2)
				{
					return FALSE;
				}
				StoreReal(vSyncCache2,pDataUnit->vKeyUnit,pPlayerUser[vvi].vKeyPlayer,0);
			}
			else
			{
				if (HaveStoredInteger(vSyncCache2,pDataUnit->vKeyUnit,pPlayerUser[vvi].vKeyPlayer) == TRUE)
				{
					sprintf(vTest,"TUT21!!!");
					DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
					sprintf(vTest,"TUT21!!! vNPlayer = %d GetUnitTypeId(pHumanPlayer->pDataUnit->WhichUnit) = %d vTimerGetElapsed = %f",pDataUnit->vNPlayer,GetUnitTypeId(pDataUnit->WhichUnit),vTimerGetElapsed);
					fLog(888,vTest);
					FlushStoredReal(vSyncCache2,pDataUnit->vKeyUnit,pPlayerUser[vvi].vKeyPlayer);
					sprintf(vTest,"TUT22!!! vNPlayer = %d GetUnitTypeId(pHumanPlayer->pDataUnit->WhichUnit) = %d vTimerGetElapsed = %f",pDataUnit->vNPlayer,GetUnitTypeId(pDataUnit->WhichUnit),vTimerGetElapsed);
					fLog(888,vTest);
					sprintf(vTest,"TUT22!!!");
					DisplayTextToPlayer(GetLocalPlayer(),0,0,vTest);
				}
			}
		}
		pDataUnit->vTimeSync = vTimerGetElapsed;
		pDataUnit->vSyncClean = TRUE;
		pDataUnit->vSync = FALSE;
		sprintf(vTest,"vSyncClean!!! vNPlayer = %d GetUnitTypeId(pHumanPlayer->pDataUnit->WhichUnit) = %d vTimerGetElapsed = %f",pDataUnit->vNPlayer,GetUnitTypeId(pDataUnit->WhichUnit),vTimerGetElapsed);
		fLog(888,vTest);
		return TRUE;
	}
	catch(...)
	{
	}
	return FALSE;
}

bool fCompliteBuild(DataUnit *pDataUnit, float vTime)
{
	if (pDataUnit == NULL) return FALSE;
	if (pDataUnit->vTimeEndBuild > vTime) return FALSE;
	//pDataUnit->Postroeno = TRUE;
	//return TRUE;
	return FALSE;
}

bool fCompliteResearch(DataUnit *pDataUnit, float vTime)
{
	if (pDataUnit == NULL) return FALSE;
	if (pDataUnit->vTimeEndResearch < vTime) return FALSE;
	pDataUnit->Researched = TRUE;
	pDataUnit->Researching = FALSE;
	return TRUE;
}

bool fCompliteTrain(DataUnit *pDataUnit, float vTime)
{
	if (pDataUnit == NULL) return FALSE;
	if (pDataUnit->vTimeEndTrain < vTime) return FALSE;
	
	return TRUE;
}

bool fGetLastCoordinates(DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return FALSE;
	Integer vId = GetUnitTypeId(pDataUnit->WhichUnit);
	if (vId == 0)
	{
		fLog(100,"100");
		return FALSE;
	}
	/*if (pDataUnit->vId == ID_UNIT_BUILD_DOM)
	{
		sprintf(vBuf,"%f\0",pDataUnit->LastCoordinates.X);
		fLog(22,vBuf);
		sprintf(vBuf,"%f\0",pDataUnit->LastCoordinates.Y);
		fLog(23,vBuf);
	}*/
	pDataUnit->LastCoordinates.X = GetUnitX(pDataUnit->WhichUnit);
	pDataUnit->LastCoordinates.Y = GetUnitY(pDataUnit->WhichUnit);
	/*if (pDataUnit->vId == ID_UNIT_BUILD_DOM)
	{
		sprintf(vBuf,"%f\0",pDataUnit->LastCoordinates.X);
		fLog(24,vBuf);
		sprintf(vBuf,"%f\0",pDataUnit->LastCoordinates.Y);
		fLog(25,vBuf);
	}*/
}

unsigned short fNBaseUnit(DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return 0;
	char *pMap = (char*)vMapGlobal;
	unsigned int vInt3 = fConvertXYToI(fConverterX(pDataUnit->LastCoordinates.X),fConverterY(pDataUnit->LastCoordinates.Y));
	return (unsigned short)pMap[vInt3];
}

int fPriorityUnitActions(DataUnit *pDataUnit)
{
	if (pDataUnit == NULL) return 100;
	vPriority = 100;
	switch (pDataUnit->vId)
	{
	case ID_UNIT_MAIN_HUMAN1:
	case ID_UNIT_MAIN_HUMAN2:
	case ID_UNIT_VAMPIRE1:
	case ID_UNIT_VAMPIRE2:
	case ID_UNIT_VAMPIRE3:
		vPriority = 0;
		break;
	case ID_UNIT_SLAYER1:
	case ID_UNIT_SLAYER2:
	case ID_UNIT_VAMPIRIC_RC:
		vPriority = 1;
		break;
	case ID_UNIT_URSA:
	case ID_UNIT_METEOR:
		vPriority = 2;
		break;
	case ID_UNIT_TRACKER:
	case ID_UNIT_FROST_INFERNAL:
	case ID_UNIT_ACIDIC_INFERNAL:
		vPriority = 3;
		break;
	case ID_UNIT_GOBLIN:
	case ID_UNIT_FIRE_INFERNAL:
		vPriority = 4;
		break;
	case ID_UNIT_SATYR:
	case ID_UNIT_INFERNAL:
		vPriority = 5;
		break;
	case ID_UNIT_OGONEK:
	case ID_UNIT_TACHKA:
		vPriority = 6;
		break;
	case ID_UNIT_ELF:
	case ID_UNIT_SHAMAN:
		vPriority = 7;
		break;
	case ID_UNIT_SVEN:
	case ID_UNIT_SHADOW:
		vPriority = 8;
		break;
	case ID_UNIT_ORK:
	case ID_UNIT_TINI:
		vPriority = 9;
		break;
	case ID_UNIT_BUILD_DOM:
	case ID_UNIT_DOGGIE:
		vPriority = 10;
		break;
	case ID_UNIT_BUILD_TENT:
		vPriority = 11;
		break;
	case ID_UNIT_BUILD_KUZNYA:
		vPriority = 12;
		break;
	case ID_UNIT_BUILD_SLAYER_TAVERN:
		vPriority = 13;
		break;
	case ID_UNIT_BUILD_HRAM:
		vPriority = 14;
		break;
	case ID_UNIT_BUILD_WALL_BROWN:
		vPriority = 15;
		break;
	case ID_UNIT_BUILD_WALL_YELLOW:
		vPriority = 16;
		break;
	case ID_UNIT_BUILD_WALL_VIOLET:
		vPriority = 17;
		break;
	case ID_UNIT_BUILD_WALL_BLUE:
		vPriority = 18;
		break;
	case ID_UNIT_BUILD_WALL_GREEN:
		vPriority = 19;
		break;
	case ID_UNIT_BUILD_WALL_GREEN2:
		vPriority = 20;
		break;
	case ID_UNIT_BUILD_WALL_RED:
		vPriority = 21;
		break;
	case ID_UNIT_BUILD_WALL_RABY:
		vPriority = 22;
		break;
	case ID_UNIT_BUILD_WALL_DIAMOND:
		vPriority = 23;
		break;
	case ID_UNIT_BUILD_WALL_ONYX:
		vPriority = 24;
		break;
	case ID_UNIT_BUILD_CITADEL:
		vPriority = 25;
		break;
	case ID_UNIT_BUILD_MAGAZ_HUMAN:
		vPriority = 26;
		break;
	case ID_UNIT_BUILD_ULTRA_RESRARCH_CENTER:
		vPriority = 27;
		break;
	case ID_UNIT_BUILD_LESOPILKA1:
		vPriority = 28;
		break;
	case ID_UNIT_BUILD_LESOPILKA2:
		vPriority = 29;
		break;
	case ID_UNIT_BUILD_ZAMOK:
		vPriority = 30;
		break;
	case ID_UNIT_BUILD_TOVERN:
		vPriority = 31;
		break;
	case ID_UNIT_BUILD_BOX_LVL1:
		vPriority = 32;
		break;
	case ID_UNIT_BUILD_BOX_LVL2:
		vPriority = 33;
		break;
	case ID_UNIT_BUILD_GOLD_MINE_WHITE:
		vPriority = 34;
		break;
	case ID_UNIT_BUILD_GOLD_MINE_GREEN:
		vPriority = 35;
		break;
	case ID_UNIT_BUILD_GOLD_MINE_RED:
		vPriority = 36;
		break;
	case ID_UNIT_BUILD_GOLD_MINE_GOLD:
		vPriority = 37;
		break;
	case ID_UNIT_BUILD_TOWER_WHITE:
		vPriority = 38;
		break;
	case ID_UNIT_BUILD_TOWER_GOLD:
		vPriority = 39;
		break;
	case ID_UNIT_BUILD_TOWER_KONUS:
		vPriority = 40;
		break;
	case ID_UNIT_BUILD_TOWER_MANA_LVL1:
		vPriority = 41;
		break;
	case ID_UNIT_BUILD_TOWER_MANA_LVL2:
		vPriority = 42;
		break;
	case ID_UNIT_BUILD_TOWER_HEAL_LVL1:
		vPriority = 43;
		break;
	case ID_UNIT_BUILD_TOWER_HEAL_LVL2:
		vPriority = 44;
		break;
	case ID_UNIT_BUILD_TOWER_FIRE_LVL1:
		vPriority = 45;
		break;
	case ID_UNIT_BUILD_TOWER_FIRE_LVL2:
		vPriority = 46;
		break;
	case ID_UNIT_BUILD_TOWER_FIRE_LVL3:
		vPriority = 47;
		break;
	case ID_UNIT_BUILD_TOWER_EARTH_LVL1:
		vPriority = 48;
		break;
	case ID_UNIT_BUILD_TOWER_EARTH_LVL2:
		vPriority = 49;
		break;
	case ID_UNIT_BUILD_TOWER_DIAMOND_LVL1:
		vPriority = 50;
		break;
	case ID_UNIT_BUILD_TOWER_DIAMOND_LVL2:
		vPriority = 51;
		break;
	case ID_UNIT_BUILD_TOWER_FROST:
		vPriority = 52;
		break;
	case ID_UNIT_BUILD_TOWER_COMET_LVL1:
		vPriority = 53;
		break;
	case ID_UNIT_BUILD_TOWER_COMET_LVL2:
		vPriority = 54;
		break;
	case ID_UNIT_BUILD_TOWER_YAD_LVL1:
		vPriority = 55;
		break;
	case ID_UNIT_BUILD_TOWER_SPIRE_LVL1:
		vPriority = 56;
		break;
	case ID_UNIT_BUILD_TOWER_SPIRE_LVL2:
		vPriority = 57;
		break;
	case ID_UNIT_BUILD_TOWER_BLOOD_LVL1:
		vPriority = 58;
		break;
	case ID_UNIT_BUILD_TOWER_BLOOD_LVL2:
		vPriority = 59;
		break;
	case ID_UNIT_BUILD_TOWER_OUTPOST_LVL1:
		vPriority = 60;
		break;
	case ID_UNIT_BUILD_TOWER_OUTPOST_LVL2:
		vPriority = 61;
		break;
	case ID_UNIT_BUILD_TOWER_ANTI_INVIZ:
		vPriority = 62;
		break;
	case ID_UNIT_BUILD_TOWER_ORACLE_LVL1:
		vPriority = 63;
		break;
	case ID_UNIT_BUILD_TOWER_ORACLE_LVL2:
		vPriority = 64;
		break;
	case ID_UNIT_WORKER:
		vPriority = 100;
		break;
	default:
		vPriority = 100;
	}
	return vPriority;
}