#define COMMON_DEFS_H aaa

#include "maps\const.lgc"

#ifndef I_SENDCOMMANDCONST_H
    #include "maps\iSendCommandConst.h"
#endif


//---------------------------------------------------------------------------
#define false               0
#define true                1
//---------------------------------------------------------------------------
#define bool                int

//------------------------------------------------------------------------------------------
#define STAT_TYPE_NORM				1
#define STAT_TYPE_FLY				2
#define STAT_TYPE_END				3
#define STAT_TYPE_TIP_END			4

//------------------------------------------------------------------------------------------
static bool bCheatWin = false;
static bool bCheatFly = false;
int LevelNumber;          // номер проигрываемого в данный момент уровня
bool bGameIsPaused = false;
int giFromPauseTime = 0;
bool bDeathByBoss = false;	//при смерти от босса не убиваем шарик
int giEarthQuakeEndTime = 0;
int gScoreTot       = 0; // очки заработанные игроком
int giOldScores        = 0; // нужна для обновления очков
int gScoreBonus       = 0; // очки заработанные игроком за бонусы
int giCrystalScore = 0;
int giGoldScore1 = 0;
int giGoldScore2 = 0;
int giGoldScore3 = 0;
int giTotalMedals = 0;
int giLastTactTime = 0;
string NoPlayerLife  = "3"; // количество шариков жизней у игрока в запасе
int giCrystOnLev = 0;
int giCrystSubLevScore = 0;
int giCrystLevScore = 0;
bool giCrystSubLevScore2 = 0;
int giBigCrystHit = 0;
bool bWin95Total = false;		//усё, можно перегружать
bool gbShowDbg = false;
int giBornTime = 0;
bool gbVehiFlying = false;
bool gbGoldCoins = false;
int giBonusSubLevScore = 0;
int giBonusSubLevTotal = 0;
static bool bPlayVehiMove = false;
int StartGameTime    = 0; // время начала игры
int StartBallLevelTime   = 0; // время первого запуска шарика на подуровне
int giBornLifeFxTime = 0;
//
int giWinTime = 0;
int giSubLevelNum    = 0;
string giScoresLev   = "0"; // очки заработанные игроком на данном уровне
bool gbCheatAllObjDeath = false;

//------------------------------------------------------------------------------------------
static int giUnFreezeTime = 0;	//если не 0, то тележка щас заморожена
static int giFreezeEffect = 0;

int MenuNoPlayerLife = 0; // ссылка на спрайт отображающий количество оставшихся жизней
int MenuNoPlayerLifeBar = 0;
int MenuScores       = 0; // ссылка на спрайт отображающий количество заработанных очков на уровне
int MenuScoresTotal  = 0; // ссылка на спрайт отображающий количество заработанных очков
int MenuHelpText     = 0; // ссылка на строку текста призывающего нажать F1 для помощи на первом уровне
int MenuGameTime     = 0; // ссылка на спрайт отображающий игровое время
int MenuBallSpeed    = 0; // ссылка на спрайт отображающий скорость шарика
int MenuBallSpeedBar = 0;
int MenuCrystals     = 0; // ссылка на спрайт отображающий кристаллы
int MenuCrystalsBar  = 0; //
int MenuCrystalsAddLifeX = 0;
int MenuCrystalsAddLifeY = 0;
int MenuCrystalsAddLifeZ = 0;

//------------------------------------------------------------------------------------------
ShowGameBarLives();
ChangeGameBarTexts(bool hide);
GetBonusLevTime();
ShowStatistics(int iType);
HideHoFTexts(int hide, int iFromRecNum);

#define AL_NONE				0
#define AL_BONUS			1
#define AL_CRYSTALS			2
#define AL_FLYSTAT			3

AddLife(int iType);
Animate20Crystals(bool bBornFx);
AnimateAddLife();
GameBarTact();

//------------------------------------------------------------------------------------------
sgn(int a)
{
  if( a < 0 )
    return -1;
  return 1;
}

//------------------------------------------------------------------------------------------
Log2(string str)
{
	str = itoa(GetTime()) + ". " + str;
	Log(str);
}

//------------------------------------------------------------------------------------------
GetLevArrNum()
{
	if(LevelNumber-2 >= 0 && LevelNumber-2 < MAX_LEVEL)
		return LevelNumber-2;
	else
		return 0;
}


//------------------------------------------------------------------------------------------
Pause2(bool bPause)
{
	bGameIsPaused = bPause;
	Pause(bPause);
}


//------------------------------------------------------------------------------------------
IsDying(int unit)
{
	if(!unit || GetAnimation(unit)==ANI_DEATH || GetAnimation(unit)==ANI_DEATH2)
		return true;
	return false;
}


//------------------------------------------------------------------------------------------
EarthQuake(int iLen)
{
	SetEnvironment(ENV_EARTHQUAKE);
	giEarthQuakeEndTime = GetTime() + iLen;
}


//------------------------------------------------------------------------------------------
UtilsTact()
{
	static int iPrevTime = 0;
	if(iPrevTime != 0)
		giLastTactTime = GetTime() - iPrevTime;
	iPrevTime = GetTime();
	//
	if(giEarthQuakeEndTime && GetTime() >= giEarthQuakeEndTime)
	{
		SetEnvironment(ENV_STOP|ENV_EARTHQUAKE);
		giEarthQuakeEndTime = 0;
	}
}


//------------------------------------------------------------------------------------------
Call_iiss(int id, int var1, int var2, string str1, string str2)
{
	return SendCommand2(id, var1, var2, str1, str2);
}


//------------------------------------------------------------------------------------------
Call_i(int id, int var1)
{
	return SendCommand2(id, var1, 0, "", "");
}


//------------------------------------------------------------------------------------------
Call_ii(int id, int var1, int var2)
{
	return SendCommand2(id, var1, var2, "", "");
}


//------------------------------------------------------------------------------------------
Call_v(int id)
{
	return SendCommand2(id, 0, 0, "", "");
}


//------------------------------------------------------------------------------------------
Call_s(int id, string str1)
{
	return SendCommand2(id, 0, 0, str1, "");
}


//------------------------------------------------------------------------------------------
Call_si(int id, string str1, int var1)
{
	return SendCommand2(id, var1, 0, str1, "");
}


//------------------------------------------------------------------------------------------
Call_sii(int id, string str1, int var1, int var2)
{
	return SendCommand2(id, var1, var2, str1, "");
}


//------------------------------------------------------------------------------------------
Call_ss(int id, string str1, string str2)
{
	return SendCommand2(id, 0, 0, str1, str2);
}


//------------------------------------------------------------------------------------------
Call_is(int id, int var1, string str1)
{
	return SendCommand2(id, var1, 0, str1, "");
}


//------------------------------------------------------------------------------------------
Call_iss(int id, int var1, string str1, string str2)
{
	return SendCommand2(id, var1, 0, str1, str2);
}


//------------------------------------------------------------------------------------------
Call_isi(int id, int var1, string str1, int var2)
{
	return SendCommand2(id, var1, var2, str1, "");
}


//------------------------------------------------------------------------------------------
SetValI(string ParamName, int val)
{
	Call_isi(EXT_SetArgValI, false, ParamName, val);
}


//------------------------------------------------------------------------------------------
GetValI(string ParamName, int DfltVal = 0)
{
	return Call_isi(EXT_GetArgValI, false, ParamName, DfltVal);
}


//------------------------------------------------------------------------------------------
SetValS(string ParamName, string val)
{
	Call_iss(EXT_SetArgValS, false, ParamName, val);
}


//------------------------------------------------------------------------------------------
GetValS(string ParamName, string DfltVal = "")
{
	return Call_iss(EXT_GetArgValS, false, ParamName, DfltVal);
}


//------------------------------------------------------------------------------------------
SetGlobValI(string ParamName, int val)
{
	Call_isi(EXT_SetArgValI, true, ParamName, val);
}


//------------------------------------------------------------------------------------------
GetGlobValI(string ParamName, int DfltVal = 0)
{
	return Call_isi(EXT_GetArgValI, true, ParamName, DfltVal);
}


//------------------------------------------------------------------------------------------
SetGlobValS(string ParamName, string val)
{
	Call_iss(EXT_SetArgValS, true, ParamName, val);
}


//------------------------------------------------------------------------------------------
GetGlobValS(string ParamName, string DfltVal = "")
{
	return Call_iss(EXT_GetArgValS, true, ParamName, DfltVal);
}


//------------------------------------------------------------------------------------------
Log3(string str)
{
	Call_s(EXT_LogStr, str);
}


//------------------------------------------------------------------------------------------
CreateEffectLink( int iUnit, int iVid, int iZ )
{
	if(!iUnit)
		return 0;
	return CreateSprite( iVid, GetX(iUnit), GetY(iUnit), GetZ(iUnit) + iZ, GetDirection(iUnit), iUnit );
}


//------------------------------------------------------------------------------------------
CreateEffect( int iUnit, int iVid, int iZ )
{
	if(!iUnit)
		return 0;
	return CreateSprite( iVid, GetX(iUnit), GetY(iUnit), GetZ(iUnit) + iZ, GetDirection(iUnit), 0 );
}


//------------------------------------------------------------------------------------------
DeleteEffectLink( int iUnit, int iVid )
{
	if(!iUnit)
		return;
	//
	int link;
	for( link = Action( iUnit, ACT_GET_LINK ); link; link = Action( link, ACT_GET_LINK ) )
	{
		if( GetUnitVid( link ) == iVid )
		{
			Action(link, ANI_DEATH);
			break;
		}
	}
}


//------------------------------------------------------------------------------------------
GetAddStrForValSLev(bool bEnd, bool bForceSaveNextLev = false)
{
	string ret = "";
	if(LevelNumber < 1)
		return ret;
	//
	if(!bEnd)
	{
	#ifndef GAMEPLAY_FLY
		//загрузка в начале обычного уровня
		ret = "_" + itoa(LevelNumber);
	#else
		//загрузка в начале летательного уровня
		ret = "_fl_"+itoa(LevelNumber);
	#endif
	}
	else
	{
		bool bNextFly = false;
		int LevNum = LevelNumber;
	#ifndef GAMEPLAY_FLY
		if(!bHaveFlyLevel[LevelNumber-1] || bForceSaveNextLev)
			LevNum = LevNum + 1;
		else	//если после простого снова простой - сохраняем в него
			bNextFly = true;
	#endif
		//
		if(bNextFly) //сохранение в конце обычного уровня
			ret = "_fl_"+itoa(LevNum+1);
		else //сохранение в конце летательного уровня
			ret = "_" + itoa(LevNum);
	}
	//
	return ret;
}


//------------------------------------------------------------------------------------------
//вызывается в конце уровня, хоть летного, хоть обычного
SaveCurData()
{
	SetValI("gScoreTot"+GetAddStrForValSLev(true), gScoreTot/10);
	SetValS("giCrystalScore"+GetAddStrForValSLev(true), giCrystalScore);
	SetValS("NoPlayerLife"+GetAddStrForValSLev(true), NoPlayerLife);
	SetValI("giGoldScore1"+GetAddStrForValSLev(true), giGoldScore1);
	SetValI("giGoldScore2"+GetAddStrForValSLev(true), giGoldScore2);
	SetValI("giGoldScore3"+GetAddStrForValSLev(true), giGoldScore3);
	SetValI("giTotalMedals"+GetAddStrForValSLev(true), giTotalMedals);

	//но в конце обычного еще надо прописать следующему обычному, вдруг летный уровень вырубят
#ifndef GAMEPLAY_FLY
	SetValI("gScoreTot"+GetAddStrForValSLev(true, true), gScoreTot/10);
	SetValS("giCrystalScore"+GetAddStrForValSLev(true, true), giCrystalScore);
	SetValS("NoPlayerLife"+GetAddStrForValSLev(true, true), NoPlayerLife);
	SetValI("giGoldScore1"+GetAddStrForValSLev(true, true), giGoldScore1);
	SetValI("giGoldScore2"+GetAddStrForValSLev(true, true), giGoldScore2);
	SetValI("giGoldScore3"+GetAddStrForValSLev(true, true), giGoldScore3);
	SetValI("giTotalMedals"+GetAddStrForValSLev(true, true), giTotalMedals);
#endif
	//
	Call_v(EXT_FlushUserData);
}


//------------------------------------------------------------------------------------------
//вызывается в начале уровня, хоть летного, хоть обычного
LoadCurData()
{
	gScoreTot = GetValI("gScoreTot"+GetAddStrForValSLev(false), 0) * 10;
	giOldScores = gScoreTot / 10;
	giCrystalScore = GetValS("giCrystalScore"+GetAddStrForValSLev(false), "0");
	NoPlayerLife = GetValS("NoPlayerLife"+GetAddStrForValSLev(false), "3");
	giGoldScore1 = GetValI("giGoldScore1"+GetAddStrForValSLev(false), 0);
	giGoldScore2 = GetValI("giGoldScore2"+GetAddStrForValSLev(false), 0);
	giGoldScore3 = GetValI("giGoldScore3"+GetAddStrForValSLev(false), 0);
	giTotalMedals = GetValI("giTotalMedals"+GetAddStrForValSLev(false), 0);
}


//------------------------------------------------------------------------------------------
ClearDataForNewGame()
{
	Log2("ClearDataForNewGame");
	//
	int i;
	for(i = 1; i <= MAX_LEVEL; i++ )
	{
		LevelNumber = i;
		if(GetValI("gScoreTot"+GetAddStrForValSLev(false), 0) != 0)
			SetValI("gScoreTot"+GetAddStrForValSLev(false), 0);
		int buf;
		buf = GetValS("giCrystalScore"+GetAddStrForValSLev(false), "0");
		if(buf != 0)
			SetValS("giCrystalScore"+GetAddStrForValSLev(false), "0");
		//
		buf = GetValS("NoPlayerLife"+GetAddStrForValSLev(false), "3");
		if(buf != 3)
			SetValS("NoPlayerLife"+GetAddStrForValSLev(false), "3");
		//
		buf = GetValI("giGoldScore1"+GetAddStrForValSLev(false), 0);
		if(buf != 0)
			SetValI("giGoldScore1"+GetAddStrForValSLev(false), 0);
		//
		buf = GetValI("giGoldScore2"+GetAddStrForValSLev(false), 0);
		if(buf != 0)
			SetValI("giGoldScore2"+GetAddStrForValSLev(false), 0);
		//
		buf = GetValI("giGoldScore3"+GetAddStrForValSLev(false), 0);
		if(buf != 0)
			SetValI("giGoldScore3"+GetAddStrForValSLev(false), 0);
		//
		buf = GetValI("giTotalMedals"+GetAddStrForValSLev(false), 0);
		if(buf != 0)
			SetValI("giTotalMedals"+GetAddStrForValSLev(false), 0);
	}
	SetValI("SaveLevel0", 1);
	SetValI("GameIsNew", 1);
	SetValI("WasGameOver", 0);
	SetValI("GoldCoins", 0);
	LevelNumber = 1;
}


//------------------------------------------------------------------------------------------
DestroyBalls()
{
	int i;
	for ( i = FirstUnit(U_UNIT); i; i = NextUnit() )
	{
		if ( GetVidData(GetUnitVid(i), VID_CLASS) == B_BALL )
		{
//			Action( Action(i, ACT_GET_LINK), ACT_SET_LINK, CreateSprite(509, GetX(i), GetY(i), GetZ(i + 1)) );
			CreateSprite(509, GetX(i), GetY(i), GetZ(i + 1));
			Action(i, ACT_STOP, 1);// 1 чтобы остановился мнгновенно
			Action(i, ACT_SET_DEATH_TIMER, 1500);
		}
	}
}


//------------------------------------------------------------------------------------------
GetVidOnScreen(int iVid)
{
	int i;
	i = FirstInBox(0, -ToScreenY(0), 1024, 768-ToScreenY(0));
	while(i)
	{
		if(GetUnitVid(i) == iVid)
			return i;
		i = NextInBox();
	}
	return 0;
}


//------------------------------------------------------------------------------------------
AddLifeEx(int d)
{
	bool ret = true;
	//
	NoPlayerLife = NoPlayerLife + d;
	if(NoPlayerLife > MAX_LIVES_COUNT)
	{
		NoPlayerLife = MAX_LIVES_COUNT;
		ret = false;
	}
	if(NoPlayerLife < 0)
	{
		NoPlayerLife = 0;
		ret = false;
	}
	//
	ShowGameBarLives();
	//
	return ret;
}

//---
DecLife() { return AddLifeEx(-1); }	//for debug

//------------------------------------------------------------------------------------------
GetAbsDir(int iVid, int iDir)
{
	return Call_ii(EXT_GetAbsDir, iVid, iDir);
}


//------------------------------------------------------------------------------------------
ChangeGameBarTexts(bool hide)
{
	int newVid = 3;
	if(hide)
		newVid = 9;
	//
	Action(MenuNoPlayerLife, ACT_CHANGE_VID, newVid);
	Action(MenuScores, ACT_CHANGE_VID, newVid);
	Action(MenuScoresTotal, ACT_CHANGE_VID, newVid);
	Action(MenuHelpText, ACT_CHANGE_VID, newVid);
	Action(MenuGameTime, ACT_CHANGE_VID, newVid);
	Action(MenuBallSpeed, ACT_CHANGE_VID, newVid);
	Action(MenuCrystals, ACT_CHANGE_VID, newVid);
}


//------------------------------------------------------------------------------------------
HideGameBarForMenu(int hide)
{
	SetVidData(473, VID_HIDE, hide);
	SetVidData(474, VID_HIDE, hide);
	SetVidData(480, VID_HIDE, hide);
	SetVidData(746, VID_HIDE, hide);
	SetVidData(760, VID_HIDE, hide);
	SetVidData(764, VID_HIDE, hide);
	ChangeGameBarTexts(hide);
}


//------------------------------------------------------------------------------------------
HideObjectsForMenu(int hide)
{
    int i;
    for ( i = 9; i < 2048; i++ )
        if ( GetVidData(i, VID_VALIDATE) )
            if ( (GetVidData(i, VID_PROPERTY) & 0x8000) && GetVidData(i, VID_SPRITETYPE) != U_MENU )
            {
            	if(i != 755 && i != 756 && i != 757)
	                SetVidData(i, VID_HIDE, hide);
//                Log(itoa(i) +" " +GetVidData(i, VID_NAME) + " "+itoa(GetVidData(i, VID_SPRITETYPE)));
            }

	//*zm070206
	HideGameBarForMenu(hide);
	//
	for(i = 0; i < WIN_GOL_VIDS_COUNT; i++)
	{
		SetVidData(bWinGoldVids[i], VID_HIDE, hide);
	}
}


//------------------------------------------------------------------------------------------
GetRankName(int iRank)
{
	string ret = "";
	if(Z_DEBUG)
		ret = itoa(iRank);
	//
	if(iRank < 0)
		iRank = 0;
	if(iRank > 12)
		iRank = 12;
	//
	string str = "RANK_"+Printf("%02d", iRank);
	ret = ret + GetString("menu", str);
	return ret;
}
