#pragma once
#include "Jass.h"
#include "Natives.h"
#include "myJASSConstants.h"
#include "MapBases.h"

struct sStackChains
{
	bool vMandatoryTrain;
	unsigned short vQTrain;
	unsigned short vNResearch;
	unsigned short vCommentUnit;
	integer vId;
	unsigned short vComment;
	unsigned short vStage;
	unsigned short vChain;
	sStackChains *vNext;
	//sStackChains *vForerunner;
	char *vName;
	unsigned short vAction;
	bool vComplite;
	sStackChains *vForerunner;
};

struct sStackActions
{
	unsigned short vStage;
	sStackActions *vNext;
	unsigned short vChain;
	sStackActions *vHeadChain;
};

struct sPlayerUser
{
	char vKeyPlayer[3];
	HPLAYER vPlayer;
	HPLAYERCOLOR vNPlayer;
	bool vDead;
	char vName[200];
	HTRIGGER hTriggerPlayerLeave;
	bool vLeave;
};

struct sRect
{
	unsigned short vX1;
    unsigned short vY1;
    unsigned short vX2;
    unsigned short vY2;
};

struct sRect2
{
	unsigned short vX1;
    unsigned short vY1;
    unsigned short vX2;
    unsigned short vY2;
	unsigned short vvi2,vvj2;
	unsigned short vInt;
	unsigned short vX;
    unsigned short vY;
	unsigned short vCount2;
	unsigned short vFill_1;
	unsigned short vFill_2;
	unsigned short vFlag;
};

struct sRect3
{
	short vX1;
    short vY1;
    short vX2;
    short vY2;
};

struct DataGoTo
{
	unsigned short vIdDataUnit;
	HTRIGGER hTrigger;
	unsigned short* pFillMap;
	sRect *vMassRect;
	unsigned int *vMassRect2;
	unit vUnit;
	DataGoTo *next;

    unsigned int vR;
    unsigned short vX3;
    unsigned short vY3;
	sRect2 vRect4;
    unsigned short vX4;
    unsigned short vY4;
	sRect2 vRect5;
    unsigned int vInt2;
	unsigned short vFlagDT;
	unsigned int vR2;
	unsigned short vCurrentIntFill;
	unsigned short vNextIntFill;
	integer vId;
	real vX_Unit;
	real vY_Unit;
	unsigned short vCount;
	unsigned int vFlag;
	bool IdetPoPuti;

	sRect2 vRect1;
	sRect2 vRect2;
	sRect2 vRect3;
	sRect3 vRect3_2;
	sRect3 vRect3_3;
	unsigned int vN_Rect;
	unsigned int vN_Rect_2;
	unsigned int vN_Rect_3;
	unsigned int i2;
	//unsigned int vR3;
    real vRadius_Unit;
    unsigned short vDiff;
	unsigned int vvi,vvj,vvh;
	int vvz;

	//unsigned int vPerevod;
	unsigned int vInt3;
	unsigned short vResult;

	unsigned short vStorona;
	bool Fly;
	unsigned short vResultFill;
	unsigned int vIntFill;
	unsigned int i3;
	HTIMER vTimer;
	bool vBoolTimer;
	bool vCelNeDostignuta;
	real vTimeForSpeed;
	unsigned short vAction;
	char *vActionStr;
	double vRad;
	int vNapravlenie;
	short vBC;
	short vAC;
	int vNapravlenie2;

	bool vPriority;

	//bool vThreadGoTo;
	HANDLE hThreadGoTo;

	integer vForerunnerClifLevel;
	integer vSubsequentClifLevel;
	bool vStartThread;
	unsigned short vCountBlink;
	unsigned int vMaxRect;

	float vTimeForBlink;
	unsigned int vMaxR;
	//bool vStopGoTo;
	//DataUnit *pDataUnit;
	bool vFlag1;
};

struct sDataSpell
{
	//char Spell[5];
	integer vId;
	real CoolDown;
	unsigned short lvl;
	real Damage;
	bool Available;
	bool vCast;
	real vRadius;
	real vTimeStartCoolDown;
	real vTimeEndCoolDown;
	real vMana;
	real vTimeCast;

	bool fInit()
	{
		vId = NULL;
		CoolDown = 0;
		lvl = 0;
		Damage = 0;
		Available = FALSE;
		vCast = FALSE;
		vRadius = 0;
		vTimeStartCoolDown = 0;
		vTimeEndCoolDown = 0;
		vMana = 0;
		vTimeCast = 0;
		return TRUE;
	}
};

/*struct DataCast
{
	char Spell[5];
	integer vId;
	real CoolDown;
};*/

struct Coordinates
{
	real X;
	real Y;
};

struct DataUnit
{
	bool Permission;
	bool PermissionMove;
	bool Atakovan;
	bool Atakuet;
	unit TargetUnit;
	HTIMER vTimerAttacked;
	//bool UderzhivaetPoziciu;
	bool Move;
	bool Harvest;
	HTIMER vTimerMove;
	DataGoTo *pPut;
	//bool Castuet;
	//DataCast Cast;
	unit WhichUnit;
	bool Zdanie;
	HPLAYERCOLOR vNPlayer;
	Coordinates LastCoordinates;
	bool Steals;
	//bool Invisible;
	//bool Bessmertie;
	//bool Umun;
	float vTimeCompliteBuild;
	float vTimeStartBuild;
	float vTimeEndBuild;
	float vTimeCompliteResearch;
	float vTimeStartResearch;
	float vTimeEndResearch;
	float vTimeCompliteTrain;
	float vTimeStartTrain;
	float vTimeEndTrain;
	bool Train;
	integer vIdTrain;
	bool Postroeno;
	bool Upgrade;
	bool fGetPostroeno()
	{
		if (this->Postroeno == TRUE)
		{
			return TRUE;
		}
		if (this->Zdanie == TRUE)
		{
			if (GetUnitState(this->WhichUnit, UNIT_STATE_MAX_LIFE) -
				GetUnitState(this->WhichUnit, UNIT_STATE_LIFE) <= 1)
			{
				this->Postroeno = TRUE;
				//KillUnit(this->WhichUnit);
				return TRUE;
			}
		}
		return FALSE;
	}
	bool Blinked;
	bool Researched;
	bool Researching;
	bool Flag;
	unsigned short vNResearch;
	integer vIdResearch;
	//real vTimeItemGold;
	bool Lvl;

	//DataGoTo *pTempPut;
	bool vGoTo;
	integer vNlvl;
	//sDataSpell vSpells[5];
	bool Dead;
	HTRIGGER hTriggerUnitDeath;
	HTRIGGER hTriggerUnitResurrected;
	unsigned short vStorona;
	bool VidenProtivniku;
	//bool ZdanieNaKarte;
	integer vId;
	HPLAYER vPlayer;

	real vRadius_Unit;
    unsigned short vDiff;
	sRect2 vRect1;

	unsigned short vIdDataUnit;
	bool Fly;
	real vTimeForSpeed;

	HTRIGGER hTriggerUnitAllEvents;
	HTRIGGER hTriggerUnitConstructFinish;
	HTRIGGER hTriggerUnitResearchFinish;
	HTRIGGER hTriggerUnitResearchStart;
	
	unsigned short vAction;
	unsigned short vActionN;
	unsigned short vCountActions;
	unsigned short vActionFinish;
	//unsigned short vObstacle;

	unsigned short vIdBuild;
	integer vIntForGoTo;

	unsigned short vLastAction;

	char *vKeyUnit;
	//real vTimerGoTo;
	bool vSync;
	bool vSyncClean;
	char *vKeyLocalPlayer;
	real vTimeSync;
	//HGAMECACHE vSyncCache;
	bool vAI;

	bool EnemyAdd;
	Coordinates LastCoordinatesForEnemy;
	Coordinates CoordinatesForGoToGlobal;
	bool vGoToGlobal;
	bool vPickupItem;
	bool vRaisingClifLevel;
	real vTimerRaisingClifLevel;

	sSmallCage *vHead;
	real vTimeGo;
	real vTimeGoTo;
	integer vIdOrder;

	char *vName;
	bool vHelping;
	unsigned short vStageHelp;
	real vTimeSignalToHelp;
	sBase *vHelpBase;
	unsigned int vInt3;
	integer vPosRepair;
	integer vPosHarvesting;
};

struct IdDataUnit
{
	unsigned short vId;
	DataUnit *pDataUnit;
	unsigned short vIdForComments;
};

struct ParamPlayer
{
	HPLAYER vPlayer;
	HPLAYERCOLOR vAI;
	unsigned short vStage;
	HTIMER vTimerPlayer;
	bool vBusy;
	//FILE *pFileActions;

	unsigned short MAX_UNIT;
	unsigned short MAX_RESEARCH;
	//IdDataUnit *vUnit;
	//bool *vResearch;
	bool vResearch[300];
	IdDataUnit vUnit[300];

	static const unsigned short MAX_NAMBER_OF_TREES = 6;
	HDESTRUCTABLE vTree[MAX_NAMBER_OF_TREES];

	//unsigned short vGetExpiredTimer;
	real vTimerGetElapsed;

	bool vSync;
	bool vSyncEnd;
	char vKeyAIPlayer[3];
	int vCountForLoopGame;

	bool fFree()
	{
		//delete[] vUnit;
		//vUnit = NULL;
		//delete[] vResearch;
		//free(vResearch);
		//vResearch = NULL;
		return TRUE;
	}

	bool fFreeAllTree()
	{
		unsigned short vvi;
		for (vvi = 0; vvi < MAX_NAMBER_OF_TREES; vvi++)
		{
			fFreeTree(vvi);
		}
		return TRUE;
	}

	bool fAddTree(HDESTRUCTABLE vDest)
	{
		unsigned short vvi;
		for (vvi = 0; vvi < MAX_NAMBER_OF_TREES; vvi++)
		{
			if (vTree[vvi] == 0)
			{
				vTree[vvi] = vDest;
				return TRUE;
			}
		}
		return FALSE;
	}

	bool fFreeTree(unsigned short vN)
	{
		if (vN < 0 || vN >= MAX_NAMBER_OF_TREES) return FALSE;
		vTree[vN] = 0;
		return TRUE;
	}

	bool fInit(unsigned short vQ_Units, unsigned short vQ_Researchs)
	{
		unsigned short vvi;
		MAX_UNIT = vQ_Units;
		MAX_RESEARCH = vQ_Researchs;
		//vUnit = new struct IdDataUnit[MAX_UNIT];
		for (vvi = 0; vvi < MAX_UNIT; vvi++)
		{
			fFreeUnit(vvi);
		}
		//vResearch = new bool[MAX_RESEARCH];
		//vResearch = (bool*) malloc(sizeof(bool)*MAX_RESEARCH);
		for (vvi = 0; vvi < MAX_RESEARCH; vvi++)
		{
			fFreeResearch(vvi);
		}
		for (vvi = 0; vvi < MAX_NAMBER_OF_TREES; vvi++)
		{
			fFreeTree(vvi);
		}
		vBusy = FALSE;
		vStage = 0;
		//vGetExpiredTimer = 0;
		vTimerGetElapsed = 0;
		vSyncEnd = FALSE;
		vSync = FALSE;
		sprintf(vKeyAIPlayer,"%d\0",vAI);
		vCountForLoopGame = 0;
		return TRUE;
	}

	bool fFreeUnit(integer vN)
	{
		if (vN < 0 || vN >= MAX_UNIT) return FALSE;
		vUnit[vN].vId = -1;
		vUnit[vN].pDataUnit = NULL;
		vUnit[vN].vIdForComments = COMMENT_NO_UNIT;
		return TRUE;
	}

	bool fFreeResearch(integer vN)
	{
		if (vN < 0 || vN >= MAX_RESEARCH) return FALSE;
		vResearch[vN] = FALSE;
		return TRUE;
	}
};

struct StackForUnits
{
	IdDataUnit vIdDataUnit2;
	StackForUnits *next;
	unsigned short vIdForComments;
	unsigned short vN;
	//bool Used;
};

struct sDataUnit2
{
	sDataUnit2 *vNext;
	sDataUnit2 *vForerunner;
	unit vUnit;
	HPLAYER vPlayer;
	HPLAYERCOLOR vNPlayer;
	integer vId;
	unsigned short vIdDataUnit;
	unsigned short vN;
};

void fAddAllDataUnitOfPlayerWorker(HPLAYER vPlayer);
void fAddAllDataUnitOfPlayer(HPLAYER vPlayer);
integer fFindIToMap (integer vIntIn);
unsigned short fDelDataUnit(unsigned short vIdDataUnit);
DataUnit * fGetDataUnit(HUNIT whichUnit);
bool fIsVampire(integer vId);
unsigned short fConverterX (real X);
unsigned short fConverterY (real Y);
real fG(real vX1, real vY1, real vX2, real vY2);
bool fFindIToMapCenter (integer vIntIn, real *vX, real *vY);
unsigned short fFindBaseByDataUnit (DataUnit *pDataUnit);
unsigned int fConvertXYToI (unsigned short vX, unsigned short vY);
extern unsigned short vMaxBase;
extern unsigned short vNLastStackForUnits;
extern unsigned short vQUnitsInBase[JASS_NumBase_MAX];
extern StackForUnits vStackForUnits[MAX_COUNT_UNITS];
bool fIsSlayer(integer vId);
bool fIsVampire(integer vId);
bool fIsMainHuman(integer vId);

struct sActionStackForDelAndCreateUnit
{
	sDataUnit2 *pCurrentDataUnit2;
	sDataUnit2 *pLastDataUnit2;
	sDataUnit2 vDataUnit2[MAX_COUNT_UNITS];
	unsigned short vNLastDataUnit2;

	unsigned short vN;
	integer vId;
	HPLAYER vPlayer;
	HPLAYERCOLOR vNPlayer;
	unsigned short vvi;
	sDataUnit2 *pDataUnit2;

	sDataUnit2 *vCurrent;
	sDataUnit2 *vNext;
	unsigned short vIdDataUnit;

	bool fNullVar()
	{
		pCurrentDataUnit2 = NULL;
		pLastDataUnit2 = NULL;
		vNLastDataUnit2 = NO_UNIT;
		return TRUE;
	}

	bool fInit()
	{
		fNullVar();
		for (unsigned short vvi = 0; vvi < MAX_COUNT_UNITS; vvi++)
		{
			vDataUnit2[vvi].vNext = 0;
			vDataUnit2[vvi].vForerunner = 0;
			vDataUnit2[vvi].vUnit = 0;
			vDataUnit2[vvi].vIdDataUnit = NO_UNIT;
			vDataUnit2[vvi].vId = 0;
			vDataUnit2[vvi].vNPlayer = 0;
			vDataUnit2[vvi].vPlayer = 0;
			vDataUnit2[vvi].vN = vvi;
		}
		return TRUE;
	}

	bool fFreeOneStackForUnit(unsigned short vN)
	{
		if (vN < 0 || vN >= MAX_COUNT_UNITS) return FALSE;
		if (vDataUnit2[vN].vForerunner)
		{
			vDataUnit2[vN].vForerunner->vNext = vDataUnit2[vN].vNext;
		}
		else
		{
			if (vDataUnit2[vN].vNext)
			{
				pCurrentDataUnit2 = vDataUnit2[vN].vNext;
			}
			else
			{
				pCurrentDataUnit2 = NULL;
				pLastDataUnit2 = NULL;
			}
		}
		vDataUnit2[vN].vNext = 0;
		vDataUnit2[vN].vForerunner = 0;
		vDataUnit2[vN].vUnit = 0;
		vDataUnit2[vN].vId = 0;
		vDataUnit2[vN].vNPlayer = 0;
		vDataUnit2[vN].vPlayer = 0;
		vDataUnit2[vN].vIdDataUnit = NO_UNIT;
		return TRUE;
	}

	// Найти в стеке по vIdDataUnit
	sDataUnit2 * fFindDataUnit2(unsigned short vIdDataUnit)
	{
		if (vIdDataUnit < 0 || vIdDataUnit >= MAX_COUNT_UNITS) return NULL;
		for (vvi = 0; vvi < vNLastDataUnit2; vvi++)
		{
			if (vDataUnit2[vvi].vIdDataUnit == vIdDataUnit)
			{
				return &vDataUnit2[vvi];
			}
		}
		return NULL;
	}

	// Удалить из стека
	unsigned short fDelDataUnit(unsigned short vN)
	{
		if (vN < 0 || vN >= MAX_COUNT_UNITS) return 0;
		fFreeOneStackForUnit(vN);
		/*if (pLastDataUnit2)
		{
			pLastDataUnit2->vNext = &vDataUnit2[vIdDataUnit];
			pLastDataUnit2 = &vDataUnit2[vIdDataUnit];
		}
		else
		{
			pLastDataUnit2 = &vDataUnit2[vIdDataUnit];
			pCurrentDataUnit2 = &vDataUnit2[vIdDataUnit];
		}*/
		if (vN == vNLastDataUnit2)
		{
			if (vN > 0)
			{
				vNLastDataUnit2--;
			}
			else if (vN == 0)
			{
				vNLastDataUnit2 = NO_UNIT;
			}
		}
		return 1;
	}

	// Добавить в стек
	unsigned short fAddDataUnit(sDataUnit2 *pDataUnit2)
	{
		if (pDataUnit2 == NULL) return 0;
		vN = fFindFreeNInSteckDataUnit2();
		if (vN < 0 || vN >= MAX_COUNT_UNITS) return 0;
		vDataUnit2[vN].vNext = NULL;
		vDataUnit2[vN].vUnit = pDataUnit2->vUnit;
		vDataUnit2[vN].vId = pDataUnit2->vId;
		vDataUnit2[vN].vNPlayer = pDataUnit2->vNPlayer;
		vDataUnit2[vN].vPlayer = pDataUnit2->vPlayer;
		vDataUnit2[vN].vIdDataUnit = pDataUnit2->vIdDataUnit;
		if (pLastDataUnit2)
		{
			vDataUnit2[vN].vForerunner = pLastDataUnit2;
			pLastDataUnit2->vNext = &vDataUnit2[vN];
			pLastDataUnit2 = &vDataUnit2[vN];
		}
		else
		{
			vDataUnit2[vN].vForerunner = NULL;
			pLastDataUnit2 = &vDataUnit2[vN];
			pCurrentDataUnit2 = &vDataUnit2[vN];
		}
		if (vN > vNLastDataUnit2)
		{
			vNLastDataUnit2 = vN;
		}
		return 1;
	}

	// Добавить в стек создания юнита
	unsigned short fCreateDataUnit(unit vUnit)
	{
		if (vUnit <= 0) return NO_UNIT;
		vId = GetUnitTypeId(vUnit);
		if (vId == 0)
		{
			return NO_UNIT;
		}
		vPlayer = GetOwningPlayer(vUnit);
		vNPlayer = GetPlayerColor(vPlayer);
		vN = fFindFreeNInSteckDataUnit2(vId,vNPlayer);
		if (vN >= 0 && vN < MAX_COUNT_UNITS)
		{
			vDataUnit2[vN].vUnit = vUnit;
			vDataUnit2[vN].vId = vId;
			vDataUnit2[vN].vPlayer = vPlayer;
			vDataUnit2[vN].vNPlayer = vNPlayer;
			vDataUnit2[vN].vNext = NULL;
			if (pLastDataUnit2)
			{
				pLastDataUnit2->vNext = &vDataUnit2[vN];
				pLastDataUnit2 = &vDataUnit2[vN];
			}
			else
			{
				pLastDataUnit2 = &vDataUnit2[vN];
				pCurrentDataUnit2 = &vDataUnit2[vN];
			}
			return vN;
		}
		return NO_UNIT;
	}

	// Найти свободную позицию в стеке
	unsigned short fFindFreeNInSteckDataUnit2()
	{
		if (vNLastDataUnit2 == NO_UNIT)
		{
			vNLastDataUnit2 = MAX_OLD_UNITS + 1;
			return vNLastDataUnit2;
		}
		if (vNLastDataUnit2 >= 0 && vNLastDataUnit2 < MAX_COUNT_UNITS)
		{
			if (vNLastDataUnit2 + 1 < MAX_COUNT_UNITS)
			{
				vNLastDataUnit2++;
				return vNLastDataUnit2;
			}
			for (unsigned short vvi = vNLastDataUnit2; vvi >= 0; vvi--)
			{
				if (vDataUnit2[vvi].vUnit == 0)
				{
					vNLastDataUnit2 = vvi;
				}
				else
				{
					if (vvi == vNLastDataUnit2)
					{
						break;
					}
					else
					{
						return vNLastDataUnit2;
					}
				}
				if (vvi == 0) break;
			}
			for (unsigned short vvi = 0; vvi < vNLastDataUnit2; vvi++)
			{
				if (vDataUnit2[vvi].vUnit == 0)
				{
					return vvi;
				}
			}
		}
		return LIMIT_UNIT;
	}

	// Поиск свободного номера в стаке создания и удаления данных для юнитов
	unsigned short fFindFreeNInSteckDataUnit2(integer vId, HPLAYERCOLOR vNPlayer)
	{
		if (vId < 0 || vNPlayer < 0) return NO_UNIT;
		if (fIsSlayer(vId))
		{
			if (fGetDataUnit((unsigned short)(vNPlayer + 12)) != NULL)
			{
				return NO_UNIT;
			}
			return vNPlayer + 12;
		}
		if (fIsVampire(vId) ||
			fIsMainHuman(vId))
		{
			return vNPlayer;
		}
		return fFindFreeNInSteckDataUnit2();
	}
};

struct ActionStackForUnits
{
	StackForUnits *first;
	StackForUnits *last;
	//bool Busy;
	ParamPlayer *pParamPlayer;
	integer vQNewUnit;
	unsigned short vN;
	StackForUnits *pStackForUnits;
	StackForUnits *current;
	integer vIdOrderCurrent;
	int vvi;
	integer vQ;
	StackForUnits *next;
	HPLAYER vPlayer;
	DataUnit * pDataUnit;
	unsigned short vBase;
	unsigned short vMaxQ;
	StackForUnits *forerunner;

	bool fInitStackForUnits(ParamPlayer *pParamPlayer2)
	{
		if (pParamPlayer2 == NULL) return FALSE;
		first = NULL;
		last = NULL;
		//Busy = FALSE;
		pParamPlayer = pParamPlayer2;
		vQNewUnit = 0;
		return TRUE;
	}

	unsigned short fFindFreeNInStackForUnits()
	{
		if (vNLastStackForUnits == NO_UNIT)
		{
			vNLastStackForUnits = 0;
			return vNLastStackForUnits;
		}
		if (vNLastStackForUnits >= 0 && vNLastStackForUnits < MAX_COUNT_UNITS)
		{
			if (vNLastStackForUnits + 1 < MAX_COUNT_UNITS)
			{
				vNLastStackForUnits++;
				return vNLastStackForUnits;
			}
			for (unsigned short vvi = vNLastStackForUnits; vvi >= 0; vvi--)
			{
				if (vStackForUnits[vvi].vIdDataUnit2.pDataUnit == 0)
				{
					vNLastStackForUnits = vvi;
				}
				else
				{
					if (vvi == vNLastStackForUnits)
					{
						break;
					}
					else
					{
						return vNLastStackForUnits;
					}
				}
				if (vvi == 0) break;
			}
			for (unsigned short vvi = 0; vvi < vNLastStackForUnits; vvi++)
			{
				if (vStackForUnits[vvi].vIdDataUnit2.pDataUnit == 0)
				{
					return vvi;
				}
			}
		}
		return LIMIT_UNIT;
	}

	bool fAddStackForUnits(unsigned short vId, DataUnit *pDataUnit, unsigned short vComment)
	{
		//pStackForUnits = (StackForUnits*) malloc(sizeof(StackForUnits));
		//pStackForUnits->pIdDataUnit = (IdDataUnit*) malloc(sizeof(IdDataUnit));
		vN = fFindFreeNInStackForUnits();
		if (vN < 0 || vN >= MAX_COUNT_UNITS)
		{
			return FALSE;
		}
		pStackForUnits = &vStackForUnits[vN];
		//pStackForUnits = new struct StackForUnits;
		//pStackForUnits->pIdDataUnit = new struct IdDataUnit;
		pStackForUnits->vIdDataUnit2.vId = vId;
		pStackForUnits->vIdDataUnit2.pDataUnit = pDataUnit;
		pStackForUnits->vIdForComments = vComment;
		if (fAddStackForUnits(pStackForUnits) == FALSE)
		{
			fFreeOneStackForUnit(pStackForUnits);
			//free(pStackForUnits->pIdDataUnit);
			//delete pStackForUnits->pIdDataUnit;
			//pStackForUnits->pIdDataUnit = NULL;
			//delete pStackForUnits;
			//free(pStackForUnits);
		}
		return TRUE;
	}

	bool fFreeOneStackForUnit(StackForUnits *pStackForUnits)
	{
		if (pStackForUnits == NULL) return FALSE;
		pStackForUnits->next = 0;
		pStackForUnits->vIdDataUnit2.vId = NO_UNIT;
		pStackForUnits->vIdDataUnit2.pDataUnit = NULL;
		pStackForUnits->vIdDataUnit2.vIdForComments = COMMENT_NO_UNIT;
		pStackForUnits->vIdForComments = COMMENT_NO_UNIT;
		if (pStackForUnits->vN == vNLastStackForUnits)
		{
			if (pStackForUnits->vN > 0)
			{
				vNLastStackForUnits--;
			}
			else if (pStackForUnits->vN == 0)
			{
				vNLastStackForUnits = NO_UNIT;
			}
		}
		return TRUE;
	}

	bool fAddStackForUnits(StackForUnits *add)
	{
		//while(Busy == TRUE);
		if (add == NULL) return FALSE;
		add->next = NULL;
		if (last && (unsigned int)last != 0xcdcdcdcd && (unsigned int)last != 0xdddddddd)
		{
			if (last->next == NULL)
			{
				last->next = add;
				last = add;
			}
			else
			{
				return FALSE;
			}
		}
		else
		{
			first = add;
			last = add;
		}
		//add->Used = FALSE;
		if (add->vIdForComments == COMMENT_NEW_UNIT)
		{
			vQNewUnit++;
		}
		return TRUE;
	}

	StackForUnits * fGetStackForUnits(unsigned short vIdForComments)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				return current;
			}
			current = current->next;
		}
		return NULL;
	}

	integer fGetIdDataUnit(unsigned short vIdForComments)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				return current->vIdDataUnit2.vId;
			}
			current = current->next;
		}
		return NULL;
	}

	DataUnit * fGetDataUnit(unsigned short vIdForComments)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				return current->vIdDataUnit2.pDataUnit;
			}
			current = current->next;
		}
		return NULL;
	}

	DataUnit * fGetDataUnit(unsigned short vIdForComments, integer vId)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				if (current->vIdDataUnit2.pDataUnit)
				{
					if (current->vIdDataUnit2.pDataUnit->vId == vId)
					{
						return current->vIdDataUnit2.pDataUnit;
					}
				}
			}
			current = current->next;
		}
		return NULL;
	}

	IdDataUnit * fGetIdDataUnit(unsigned short vIdForComments, integer vId)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				if (current->vIdDataUnit2.pDataUnit)
				{
					if (current->vIdDataUnit2.pDataUnit->vId == vId)
					{
						return &current->vIdDataUnit2;
					}
				}
			}
			current = current->next;
		}
		return NULL;
	}

	DataUnit * fGetDataUnit(integer vId, bool vHarvest)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdDataUnit2.pDataUnit)
			{
				if (current->vIdDataUnit2.pDataUnit->vId == vId &&
					current->vIdDataUnit2.pDataUnit->Harvest == vHarvest)
				{
					return current->vIdDataUnit2.pDataUnit;
				}
			}
			current = current->next;
		}
		return NULL;
	}

	DataUnit * fGetDataUnit(unsigned short vIdForComments, integer vId, bool vHarvest)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				if (current->vIdDataUnit2.pDataUnit)
				{
					if (current->vIdDataUnit2.pDataUnit->vId == vId &&
						current->vIdDataUnit2.pDataUnit->Harvest == vHarvest)
					{
						return current->vIdDataUnit2.pDataUnit;
					}
				}
			}
			current = current->next;
		}
		return NULL;
	}

	DataUnit * fGetDataUnit(unsigned short vIdForComments, integer vId, integer vIdOrder)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				if (current->vIdDataUnit2.pDataUnit)
				{
					vIdOrderCurrent = GetUnitCurrentOrder(current->vIdDataUnit2.pDataUnit->WhichUnit);
					if (current->vIdDataUnit2.pDataUnit->vId == vId &&
						vIdOrderCurrent == vIdOrder)
					{
						return current->vIdDataUnit2.pDataUnit;
					}
				}
			}
			current = current->next;
		}
		return NULL;
	}

	DataUnit * fGetDataUnit(integer vId, integer vIdOrder)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdDataUnit2.pDataUnit && (unsigned int)current->vIdDataUnit2.pDataUnit != 0xdddddddd)
			{
				vIdOrderCurrent = GetUnitCurrentOrder(current->vIdDataUnit2.pDataUnit->WhichUnit);					
				if (current->vIdDataUnit2.pDataUnit->vId == vId &&
					vIdOrderCurrent == vIdOrder)
				{
					return current->vIdDataUnit2.pDataUnit;
				}
			}
			current = current->next;
		}
		return NULL;
	}

	bool fSetComment(unsigned short vIdForComments, integer vId, unsigned short vIdForCommentsNew)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				if (current->vIdDataUnit2.pDataUnit)
				{
					if (current->vIdDataUnit2.pDataUnit->vId == vId)
					{
						if (current->vIdForComments == COMMENT_NEW_UNIT)
						{
							vQNewUnit--;
						}
						current->vIdForComments = vIdForCommentsNew;
						//current->Used = TRUE;
						if (current->vIdForComments != COMMENT_NEW_UNIT)
						{
							pParamPlayer->vUnit[current->vIdForComments].vId = current->vIdDataUnit2.vId;
							pParamPlayer->vUnit[current->vIdForComments].pDataUnit = current->vIdDataUnit2.pDataUnit;
							pParamPlayer->vUnit[current->vIdForComments].vIdForComments = current->vIdForComments;
						}
						return TRUE;
					}
				}
			}
			current = current->next;
		}
		return FALSE;
	}

	bool fSetCommentAll(unsigned short vIdForComments, integer vId, unsigned short vIdForCommentsNew)
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdForComments == vIdForComments)
			{
				if (current->vIdDataUnit2.pDataUnit)
				{
					if (current->vIdForComments == COMMENT_NEW_UNIT)
					{
						vQNewUnit--;
					}
					if (current->vIdDataUnit2.pDataUnit->vId == vId)
					{
						current->vIdForComments = vIdForCommentsNew;
						//current->Used = TRUE;
					}
					
				}
			}
			current = current->next;
		}
		return true;
	}

	integer fGetQuantityUnits(integer vId)
	{
		vQ = 0;
		current = first;
		next = NULL;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdDataUnit2.pDataUnit)
			{
				if (current->vIdDataUnit2.pDataUnit->vId == vId ||
					current->vIdDataUnit2.pDataUnit->vIdTrain == vId)
				{
					if (GetUnitTypeId(current->vIdDataUnit2.pDataUnit->WhichUnit) != 0)
					{
						vQ++;
					}
					else
					{
						if (vId == ID_UNIT_WORKER)
						{
							vPlayer = current->vIdDataUnit2.pDataUnit->vPlayer;
							next = current->next;
							fDelDataUnit(current->vIdDataUnit2.vId);
							fAddAllDataUnitOfPlayerWorker(vPlayer);
							current = next;
							continue;
						}
					}
				}
			}
			current = current->next;
		}
		return vQ;
	}

	integer fFindInt(integer vId, unsigned short vBase)
	{
		current = first;
		next = NULL;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdDataUnit2.pDataUnit)
			{
				if (current->vIdDataUnit2.pDataUnit->Dead == TRUE ||
					(pParamPlayer != NULL &&
					IsVisibleToPlayer(current->vIdDataUnit2.pDataUnit->LastCoordinatesForEnemy.X,
									  current->vIdDataUnit2.pDataUnit->LastCoordinatesForEnemy.Y,
									  pParamPlayer->vPlayer) == TRUE &&
					IsUnitVisible(current->vIdDataUnit2.pDataUnit->WhichUnit,
								  pParamPlayer->vPlayer) == FALSE))
				{
					next = current->next;
					fFreeStackForUnits(current->vIdDataUnit2.vId);
					current = next;
					continue;
				}
				else
				{
					if (current->vIdDataUnit2.pDataUnit->vId == vId && fFindBaseByDataUnit(current->vIdDataUnit2.pDataUnit) == vBase)
					{
						return fConvertXYToI(fConverterX(current->vIdDataUnit2.pDataUnit->LastCoordinatesForEnemy.X),
											 fConverterY(current->vIdDataUnit2.pDataUnit->LastCoordinatesForEnemy.Y));
					}
				}
			}
			current = current->next;
		}
		return vSizeMap;
	}

	DataUnit * fFindNewUnit()
	{
		current = first;
		pDataUnit = NULL;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdDataUnit2.pDataUnit)
			{
				if (current->vIdForComments == COMMENT_NEW_UNIT)
				{
					pDataUnit = current->vIdDataUnit2.pDataUnit;
					fFreeStackForUnits(current->vIdDataUnit2.vId);
					return pDataUnit;
				}
			}
			current = current->next;
		}
		return pDataUnit;
	}

	unsigned short fFindBase()
	{
		//unsigned short vBase;
		//unsigned short vMaxQ;
		//unsigned short *vQUnitsInBase;
		current = first;
		next = NULL;
		//vQUnitsInBase = (unsigned short*)malloc(sizeof(unsigned short)*(vMaxBase+1));
		//memset(vQUnitsInBase,0,sizeof(unsigned short)*(vMaxBase+1));
		//vQUnitsInBase = new unsigned short[vMaxBase+1];
		for (int vvi = 0; vvi < vMaxBase+1; vvi++)
		{
			vQUnitsInBase[vvi] = 0;
		}
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdDataUnit2.pDataUnit)
			{
				if (current->vIdDataUnit2.pDataUnit->Dead == TRUE ||
					(pParamPlayer != NULL &&
					IsVisibleToPlayer(current->vIdDataUnit2.pDataUnit->LastCoordinatesForEnemy.X,
									  current->vIdDataUnit2.pDataUnit->LastCoordinatesForEnemy.Y,
									  pParamPlayer->vPlayer) == TRUE &&
					IsUnitVisible(current->vIdDataUnit2.pDataUnit->WhichUnit,
								  pParamPlayer->vPlayer) == FALSE))
				{
					next = current->next;
					fFreeStackForUnits(current->vIdDataUnit2.vId);
					current = next;
					continue;
				}
				else
				{
					vBase = fFindBaseByDataUnit(current->vIdDataUnit2.pDataUnit);
					if (vBase >= 1 && vBase <= vMaxBase)
						vQUnitsInBase[vBase]++;
					if (vBase == 0 ||
						vBase == JASS_SLAYERPLACE ||
						//vBase == JASS_DANCEPOOL ||
						vBase == JASS_PATH_BLIGHT ||
						vBase == JASS_WATER_LEVEL_1 ||
						vBase == JASS_PATH_NOWATER)
						vQUnitsInBase[0]++;
				}
			}
			current = current->next;
		}
		vMaxQ = 0;
		vBase = DO_NOT_FIND_BASE;
		for (int vvi = 0; vvi <= vMaxBase; vvi++)
		{
			if (vMaxQ < vQUnitsInBase[vvi] &&
				vQUnitsInBase[vvi] != 0)
			{
				vMaxQ = vQUnitsInBase[vvi];
				vBase = vvi;
			}
		}
		//free(vQUnitsInBase);
		//delete[] vQUnitsInBase;
		return vBase;
	}

	void fGetResearchFinish()
	{
		current = first;
		while (current && (unsigned int)current != 0xdddddddd)
		{
			if (current->vIdDataUnit2.pDataUnit && (unsigned int)current->vIdDataUnit2.pDataUnit != 0xdddddddd)
			{
				if (current->vIdForComments < COMMENT_NO_UNIT &&
					current->vIdDataUnit2.pDataUnit->Zdanie == TRUE &&
					current->vIdDataUnit2.pDataUnit->Researched == TRUE)
				{
					current->vIdDataUnit2.pDataUnit->Researched = FALSE;
					pParamPlayer->vResearch[current->vIdDataUnit2.pDataUnit->vNResearch] = TRUE;
				}
			}
			current = current->next;
		}
	}

	void fFreeStackForUnits(unsigned short vIdDataUnit)
	{
		current = first;
		next = NULL;
		forerunner = NULL;
		while (current && (unsigned int)current != 0xdddddddd && (unsigned int)current != 0xcdcdcdcd && (unsigned int)current != 0xcccccccc)
		{
			next = current->next;
			if (current->vIdDataUnit2.vId == vIdDataUnit)
			{
				if (next)
				{
					if (forerunner)
					{
						forerunner->next = next;
					}
					else
					{
						first = next;
					}
				}
				else
				{
					if (forerunner)
					{
						last = forerunner;
						forerunner->next = NULL;
					}
					else
					{
						first = NULL;
						last = NULL;
					}
				}
				if (current->vIdForComments != COMMENT_NEW_UNIT)
				{
					pParamPlayer->fFreeUnit(current->vIdForComments);
				}
				if (current->vIdForComments == COMMENT_NEW_UNIT)
				{
					vQNewUnit--;
				}
				/*if (current->vIdDataUnit2.pDataUnit &&
					(unsigned int)current->vIdDataUnit2.pDataUnit != 0xdddddddd &&
					(unsigned int)current->vIdDataUnit2.pDataUnit != 0xcdcdcdcd &&
					(unsigned int)current->vIdDataUnit2.pDataUnit != 0xcccccccc)
				{
					current->vIdDataUnit2.pDataUnit = NULL;
					//free(current->pIdDataUnit);
					delete current->pIdDataUnit;
					current->pIdDataUnit = NULL;
				}
				else
				{
					vQNewUnit = vQNewUnit;
				}
				if (current->pIdDataUnit)
				{
					current->pIdDataUnit = NULL;
				}*/
				//current->next = NULL;
				//free(current);
				//delete current;
				fFreeOneStackForUnit(current);
				return;
			}
			forerunner = current;
			current = current->next;
		}
	}

	void fFreeStackForUnitsAll()
	{
		current = first;
		next = NULL;
		while (current && (unsigned int)current != 0xdddddddd && (unsigned int)current != 0xcdcdcdcd)
		{
			if (current->vIdForComments == COMMENT_NEW_UNIT)
			{
				vQNewUnit--;
			}
			next = current->next;
			fFreeOneStackForUnit(current);
			//free(current->pIdDataUnit);
			//delete current->pIdDataUnit;
			//current->pIdDataUnit = NULL;
			//free(current);
			//delete current;
			current = next;
		}
		first = NULL;
		last = NULL;
	}
};

struct sInventory
{
	static const unsigned short MAX_SLOT = 6;
	HITEM vItemInSlot[MAX_SLOT];
	DataUnit *pDataUnit;
	integer vGold;
	integer vWood;
	integer vGoldPlayer;
	integer vWoodPlayer;
	real vG;
	integer vSlotByShop;

	bool fInit(DataUnit *pDataUnit2)
	{
		if (pDataUnit == NULL) return FALSE;
		int vvi;
		for (vvi = 0; vvi < MAX_SLOT; vvi++)
		{
			vItemInSlot[vvi] = 0;
		}
		pDataUnit = pDataUnit2;
		return TRUE;
	}

	bool fRefreshInventory()
	{
		for (vSlotByShop = 0; vSlotByShop < MAX_SLOT; vSlotByShop++)
		{
			if (fSetItemToSlot(UnitItemInSlot(pDataUnit->WhichUnit,vSlotByShop),vSlotByShop) == FALSE)
			{
				return FALSE;
			}
		}
		return TRUE;
	}

	integer vQFreeSlots()
	{
		int vvi;
		integer vQ;
		vQ = 0;
		for (vvi = 0; vvi < MAX_SLOT; vvi++)
		{
			if (vItemInSlot[vvi] == 0)
			{
				vQ++;
			}
		}
		return vQ;
	}

	bool fAddItem(HITEM vItem)
	{
		if (vItem == NULL) return FALSE;
		int vvi;
		for (vvi = 0; vvi < MAX_SLOT; vvi++)
		{
			if (vItemInSlot[vvi] == 0)
			{
				vItemInSlot[vvi] = vItem;
				return TRUE;
			}
		}
		return FALSE;
	}

	bool fSetItemToSlot(HITEM vItem, integer vSlot)
	{
		if (vItem == NULL && (vSlot < 0 || vSlot > 6)) return FALSE;
		vItemInSlot[vSlot] = vItem;
		return TRUE;
	}

	integer fGetSlotByItem(HITEM vItem)
	{
		if (vItem == NULL) return NULL;
		int vvi;
		for (vvi = 0; vvi < MAX_SLOT; vvi++)
		{
			if (vItemInSlot[vvi] == vItem)
			{
				return vvi;
			}
		}
		return NULL;
	}

	HITEM fGetItem(integer vIdItem)
	{
		if (vIdItem == NULL) return NULL;
		int vvi;
		for (vvi = 0; vvi < MAX_SLOT; vvi++)
		{
			if (GetItemTypeId(vItemInSlot[vvi]) == vIdItem)
			{
				return vItemInSlot[vvi];
			}
		}
		return NULL;
	}

	integer fQItems(integer vIdItem)
	{
		if (vIdItem == NULL) return 0;
		int vvi;
		int vQ;
		vQ = 0;
		for (vvi = 0; vvi < MAX_SLOT; vvi++)
		{
			if (GetItemTypeId(vItemInSlot[vvi]) == vIdItem)
			{
				vQ++;
			}
		}
		return vQ;
	}
};

struct sUnitParam
{
	unit vTarget;
	real vHPTarget;
	//DataUnit *pDataUnit;
	//unsigned short vIdDataUnit;
	bool vAttack;
	bool vRetreat;
	IdDataUnit *pDataUnits;
	//bool vHoldPosition;

};

struct sVampire
{
	sInventory vInventory;
	sUnitParam vUnitParam;
	sDataSpell vEnlightenment;
	sDataSpell vHealingwave;
	sDataSpell vStealth;
	sDataSpell vLightning;

	bool fInit()
	{
		vUnitParam.vAttack = FALSE;
		vUnitParam.vTarget = 0;
		vUnitParam.vRetreat = FALSE;
		//vUnitParam.vHoldPosition = FALSE;
		return TRUE;
	}

};

struct sTini
{
	sUnitParam vUnitParam;
	bool vSmartFireInfernal;
};

struct sInfernal
{
	sUnitParam vUnitParam;
	bool vFire;
	real vTimeAttackTower;
	unit vForerunnerUnit;
	bool vSmartVampire;
};

struct sDataVampires
{
	static const unsigned short MAX_FARSIGHT = 2;
	static const unsigned short MAX_FARSIGHT_FOR_BASES = 108;
	bool vAttack;
	unsigned short vBaseHuman;
	DataGoTo *pPutGlobal;
	unsigned short vQFarsight;
	Coordinates vMassCoordinatesForFarsight[MAX_FARSIGHT];
	bool vBaseFarsight[MAX_FARSIGHT_FOR_BASES];
	real vTimeFarsight[MAX_FARSIGHT_FOR_BASES];
	unsigned short vCountFarsight;
	bool vWall;
	bool vTiniGo;
	DataUnit * vMainHumanBreeze;
	real vTimerMainHumanBreeze;
	bool vFlagBreeze;
	bool vTypeBazeOneCell;
	bool vDansePool;
	
	bool vKillInfernals;

	ActionStackForUnits vActionStackForUnitsEnemy;

	bool vFalgNextBase;
	real vTimeNextBase;
	real vLastProcHPWall;
	real vTimeAttackWall;

	bool fInit()
	{
		vBaseHuman = DO_NOT_FIND_BASE;
		vQFarsight = 0;
		vCountFarsight = 0;
		vWall = FALSE;
		vTiniGo = FALSE;
		vMainHumanBreeze = NULL;
		vTimerMainHumanBreeze = 0;
		vFlagBreeze = FALSE;
		vTypeBazeOneCell = FALSE;
		vDansePool = FALSE;
		vKillInfernals = FALSE;
		vFalgNextBase = FALSE;
		vTimeNextBase = 0;
		vLastProcHPWall = 0;
		vTimeAttackWall = 0;
		vAttack = FALSE;
		fRefreshAllFarsight();
		return TRUE;
	}

	bool fAddCoordinatesForFarsight(real vX, real vY)
	{
		if (vQFarsight >= MAX_FARSIGHT) return FALSE;
		vMassCoordinatesForFarsight[vQFarsight].X = vX;
		vMassCoordinatesForFarsight[vQFarsight].Y = vY;
		vQFarsight++;
		vCountFarsight++;
		return TRUE;
	}

	bool fNoFarsightBase()
	{
		int vvi;
		for (vvi = JASS_NumBase_MIN; vvi <= vMaxBase; vvi++)
		{
			if (vBaseFarsight[vvi] == FALSE) return FALSE;
		}
		return TRUE;
	}

	bool fNoFarsightPlus()
	{
		if (vBaseFarsight[JASS_SLAYERPLACE] == FALSE) return FALSE;
		if (vBaseFarsight[JASS_DANCEPOOL] == FALSE) return FALSE;
		if (vBaseFarsight[JASS_PATH_BLIGHT] == FALSE) return FALSE;
		return TRUE;
	}

	bool fFreeFarsight()
	{
		vQFarsight = 0;
		return TRUE;
	}

	bool fRefreshAllFarsight()
	{
		int vvi;
		for (vvi = 0; vvi <= MAX_FARSIGHT_FOR_BASES; vvi++)
		{
			vBaseFarsight[vvi] = FALSE;
		}
		vCountFarsight = 0;
		return TRUE;
	}

	bool fIsBaseFarsight(integer vBase)
	{
		if (vBase < JASS_NumBase_MIN || vBase > MAX_FARSIGHT_FOR_BASES) return FALSE;
		if (vBaseFarsight[vBase] == FALSE) return FALSE;
		return TRUE;
	}

	bool fNextBaseFarsight(unsigned short vFlag)
	{
		if (vQFarsight >= MAX_FARSIGHT) return FALSE;
		integer vBase;
		integer vCount;
		Coordinates vCoordinates;
		unsigned short vNBase;
		vCount = 0;
		if (vFlag == 0)
		while(vCount <= vMaxBase+10)
		{
			vBase = GetRandomInt(0,vMaxBase);//rand() % (vMaxBase + 1);
			if (vBase != 0 && fFindIToMap(vBase) != -1)
			if (fIlluminationOfBase(vBase) == TRUE) return TRUE;
			vCount++;
		}
		if (vFlag == 1)
		if (1)
		{
			if (1)
			{
				vBase = GetRandomInt(0,2);//rand() % (2 + 1);
				switch(vBase)
				{
				case 0:
					vBase = JASS_SLAYERPLACE;
					break;
				case 1:
					vBase = JASS_DANCEPOOL;
					break;
				case 2:
					vBase = JASS_PATH_BLIGHT;
					break;
				}
			}
			if (fIlluminationOfBase(vBase) == TRUE) return TRUE;
		}
		if (vFlag == 2)
		if (1)
		{
			while (vCount<JASS_NumBase_MAX)
			{
				vNBase = GetRandomInt(0,35);//rand()%36;
				if ((vMaxBase + 1 + vNBase) <= JASS_NumBase_MAX)
				if (vBaseFarsight[vMaxBase + 1 + vNBase] == FALSE)
				{
					vCoordinates.X = (16000 / 6)*(float)(vNBase%6) - 8000 + 1333;
					vCoordinates.Y = (-16000 / 6)*(float)(vNBase/6) + 8000 - 1333;
					vBaseFarsight[vMaxBase + 1 + vNBase] = TRUE;
					fAddCoordinatesForFarsight(vCoordinates.X,vCoordinates.Y);
					return TRUE;
				}
				vCount++;
			}
		}
		return FALSE;
	}

	bool fRefreshBaseFarsight(integer vBase)
	{
		if (vBase < 0 || vBase > MAX_FARSIGHT_FOR_BASES) return FALSE;
		vBaseFarsight[vBase] = FALSE;
		return TRUE;
	}

	bool fIlluminationOfBase(integer vBase)
	{
		if (vBase < 0 || vBase > MAX_FARSIGHT_FOR_BASES) return FALSE;
		if (vBaseFarsight[vBase] == TRUE) return FALSE;
		Coordinates vCoordinatesBase;
		if (fFindCoordinatesBase(vBase,&vCoordinatesBase.X,&vCoordinatesBase.Y) == FALSE) return FALSE;
		if (fAddCoordinatesForFarsight(vCoordinatesBase.X,vCoordinatesBase.Y) == FALSE) return FALSE;
		vBaseFarsight[vBase] = TRUE;
		return TRUE;
	}

	bool fFindCoordinatesBase(integer vBase, real *vX, real *vY)
	{
		if (vBase < 0 || vBase > MAX_FARSIGHT_FOR_BASES) return FALSE;
		if (vBase == 0)
		{
			*vX = -1500;
			*vY = -1500;
		}
		else
		{
			if (fFindIToMapCenter(vBase,vX,vY) == FALSE) return FALSE;
		}
		return TRUE;
	}
};

struct sMainHuman
{
	sUnitParam vUnitParam;
	Integer vPosRepair;
	sDataSpell vManaBurn;

	bool fInit()
	{
		vUnitParam.vAttack = FALSE;
		vUnitParam.vTarget = 0;
		vPosRepair = 0;
		vManaBurn.fInit();
		return TRUE;
	}
};



struct sDataHumans
{
	ActionStackForUnits vActionStackForUnitsEnemy;
	bool vFlagHelp1;
	sBase *vBaseHelp1;
	bool vFlagHelp2;
	sBase *vBaseHelp2;
	bool vFirstGold;
	bool vBuyGold;
	bool vAttackGrave;
	real vTimeSignalToHelp;
	bool vEra1All;
	
	Coordinates vCoordinatesSlayerPlace;
	Coordinates vCoordinatesManaWell;

	bool fInit()
	{
		vFlagHelp1 = FALSE;
		vBaseHelp1 = NULL;
		vFlagHelp2 = FALSE;
		vBaseHelp2 = NULL;
		vFirstGold = FALSE;
		vBuyGold = FALSE;
		vAttackGrave = FALSE;
		fFindIToMapCenter(JASS_SLAYERPLACE,&vCoordinatesSlayerPlace.X,&vCoordinatesSlayerPlace.Y);
		vCoordinatesManaWell.X = 0;
		vCoordinatesManaWell.Y = 256;
		vTimeSignalToHelp = 0;
		vEra1All = FALSE;
		return TRUE;
	}
};