//-- TBK12 --//
//By Strangelove
//v1.1
//17.05.2021


{$I improvestaticai.script}
{$I transformunits.script}
{$I helpers.script}
{$I difficulty.script}
{$I dynamicmap.script}


const 
	SPAWN_TIMER = 9000; //15Minutes
	SPAWN_DELAY = 27000; //45Minutes

var 
	DifficultySetting: TKMMissionDifficulty;
	aAttackGroups: array of Integer;
	
	iTicks: Integer;
	iWave: Byte;
	aReinforcements: array of Integer;
	bDefeated: Boolean;
	
	iGoldOffset: Word;
	


function RandomHouse(aPlayer: Byte): Integer;
var
	aHouses: array of Integer;
begin
	aHouses := States.PlayerGetAllHouses(aPlayer);
	Result := aHouses[States.KaMRandomI(Length(aHouses) -1)];
end;


procedure OnMissionStart();
begin
	//Define Modifiers [Easy3, Easy2, Easy1, Normal, Hard1, Hard2, Hard3]
	EquipRateMod := [3, 2, 1.5, 1, 0.66, 0.5, 0.33]; //Schools are usually the limiting factor
	RecruitDelayMod := [1, 1, 1, 1, 1, 1, 1];
	RecruitLimitMod := [1, 1, 1, 1, 1.33, 1.66, 2];
	WorkerLimitMod := [1, 1, 1, 1, 1.33, 1.66, 2];
	
	//Set Variables
	iWave := 0;
	iTicks := SPAWN_TIMER; //Updated in OnTick
	
	DifficultySetting := States.MissionDifficulty();
	
	//Check Gold supplies of Player1
	iGoldOffset := States.HouseResourceAmount(States.HouseAt(22, 62), 7);
	
	//Disable vision sharing
	Actions.PlayerShareFog(1, 0, false);
	Actions.PlayerShareFog(0, 1, false);
	
	//Add Groups for First Attack according to difficulty settings (Feed them in OnTick)
	SetLength(aAttackGroups, 4);
	aAttackGroups[0] :=	Actions.GiveGroup(5, 20, 60, 23, 4, 9, 3); //Pikes
	aAttackGroups[1] := Actions.GiveGroup(5, 18, 64, 21, 4, 9, 3); //Xbows
	case DifficultySetting of
		mdEasy1:
		begin
			aAttackGroups[2] :=	Actions.GiveGroup(5, 16, 59, 18, 4, 9, 3); //Swords
			aAttackGroups[3] := Actions.GiveGroup(5, 16, 62, 12, 4, 9, 3);
		end;
		mdNormal:
		begin
			aAttackGroups[2] :=	Actions.GiveGroup(5, 16, 59, 18, 4, 12, 4);
			aAttackGroups[3] := Actions.GiveGroup(5, 16, 62, 12, 4, 9, 3);
		end;
		mdHard1:
		begin
			aAttackGroups[2] :=	Actions.GiveGroup(5, 16, 59, 18, 4, 12, 4);
			aAttackGroups[3] := Actions.GiveGroup(5, 16, 62, 12, 4, 12, 4);
		end;
	end;
	
	//Cleanup
	Actions.UnitKill(States.UnitAt(135, 21), true);
	Actions.UnitKill(States.UnitAt(136, 21), true);
end;


procedure OnPlayerDefeated(aPlayer: Integer);
begin
	//Allied Village Settings
	if aPlayer = 2 then
	begin
		Actions.AIDefendAllies(1, true);
		//Add Attack Positions (Attacks handled in MapEd)
		Actions.AIDefencePositionAdd(1, 44, 85, 1, 0, 20, 1); //Melee
		Actions.AIDefencePositionAdd(1, 50, 61, 2, 0, 20, 1); //Melee
		Actions.AIDefencePositionAdd(1, 45, 66, 2, 1, 20, 1); //Anti-Horse
	end;
	//Disable Reinforcements
	if aPlayer = 3 then
		bDefeated := true;
end;


procedure OnTick();
var
	iGoldSupply, GameTime: Word;
	i, G: Byte;
	iX, iY, iUnitID: array of Byte;
	RandomHouseID: Integer;
begin
	//Fill Arrays with Reinforcement Spawn positions
	iX := [123, 127, 123, 127, 123, 127];
	iY := [28, 28, 35, 35, 42, 42];
	iUnitID := [16, 18, 20, 22, 16, 18];

	GameTime := States.GameTime(); //Get GameTime only once
	
	//Make Waterfalls more dynamic (Change end tiles) Not automated yet...
	if GameTime mod 9 = 0 then
		ChangeWaterfallEndTiles(95, 97, 13);

	//For every 2nd Gold Chest delivered to Player1's Storehouse add one Gold Chest to Human Players Storehouse (~350 total)
	iGoldSupply := States.HouseResourceAmount(States.HouseAt(22, 62), 7);
	if iGoldSupply > (iGoldOffset +1) then
	begin
		Actions.GiveWares(0, 7, 1);
		iGoldOffset := iGoldSupply;
	end;

	//Difficulty modifications
	if GameTime = (MAX_HANDS +1) then
	begin
		//Update iTicks here!
		iTicks := Round(SPAWN_TIMER *EquipRateMod[dMod]) +SPAWN_DELAY; //On Normal: 1st Spawn @1hour
		
		//Remove/Add Enemy Defence Positions and Groups
		case DifficultySetting of
			mdEasy1:
			begin
				RemoveDefencePositionAndGroup(2, 93, 40); //Pikes
				RemoveDefencePositionAndGroup(2, 95, 31); //Knights
				RemoveDefencePositionAndGroup(2, 84, 34); //Knights
				RemoveDefencePositionAndGroup(3, 100, 31); //Xbows
				RemoveDefencePositionAndGroup(3, 112, 32); //Knights
			end;
			mdNormal:
			begin
				RemoveDefencePositionAndGroup(2, 93, 40); //Pikes
				RemoveDefencePositionAndGroup(2, 95, 31); //Knights
				RemoveDefencePositionAndGroup(3, 100, 31); //Xbows
			end;
		end;
		
		//Feed aAttackGroups here
		for G := 0 to Length(aAttackGroups) -1 do
			Actions.GroupHungerSet(aAttackGroups[G], States.UnitMaxHunger); //Set Hunger level to max
	end;
	
	//Schedule Events
	case GameTime of
		1200:
			Actions.AIWorkerLimit(1, 6);
		3000:
		begin
			PlanAddHouse(1, 19, 8, 63); //Weapon Workshop
			PlanAddRoad(1, 11, 63);
			PlanAddRoad(1, 11, 64);
			PlanAddRoad(1, 10, 64);
			PlanAddRoad(1, 9, 64);
			PlanAddRoad(1, 8, 64);
			PlanAddRoad(1, 10, 65);
			PlanAddRoad(1, 10, 66);
			PlanAddRoad(1, 11, 66);
			PlanAddRoad(1, 12, 66);
		end;
		3750:
			Actions.ShowMsg(-1, '<$0>'); //Give Msg to Player about upcoming attack
		4500:
		begin
			PlanAddHouse(1, 25, 13, 70); //Tannery
			PlanAddRoad(1, 11, 67);
			PlanAddRoad(1, 11, 68);
			PlanAddRoad(1, 11, 69);
			PlanAddRoad(1, 11, 70);
			PlanAddRoad(1, 11, 71);
			PlanAddRoad(1, 12, 71);
			PlanAddRoad(1, 13, 71);
		end;
		6000:
		begin
			PlanAddHouse(1, 20, 8, 68); //Armor Workshop
			PlanAddRoad(1, 8, 69);
			PlanAddRoad(1, 8, 70);
			PlanAddRoad(1, 9, 70);
			PlanAddRoad(1, 10, 70);
		end;
		7500:
		begin
			PlanAddHouse(1, 21, 3, 67); //Rax
			PlanAddRoad(1, 3, 68);
			PlanAddRoad(1, 4, 68);
			PlanAddRoad(1, 5, 68);
			PlanAddRoad(1, 6, 68);
			PlanAddRoad(1, 6, 69);
			PlanAddRoad(1, 7, 69);
		end;
		9000:
		begin
			PlanAddHouse(1, 19, 5, 71); //Weapon Workshop
			PlanAddRoad(1, 5, 72);
			PlanAddRoad(1, 6, 72);
			PlanAddRoad(1, 7, 72);
			PlanAddRoad(1, 8, 72);
			PlanAddRoad(1, 8, 71);
			
		end;
		10000: //Connect Rax again
		begin
			PlanAddRoad(1, 6, 67);
			PlanAddRoad(1, 6, 66);
			PlanAddRoad(1, 6, 65);
			PlanAddRoad(1, 7, 65);
			PlanAddRoad(1, 7, 64);
		end;
		12000:
		begin
			PlanAddHouse(1, 6, 5, 54); //Fisherman
			PlanConnectRoad(1, 5, 55, 6, 58, false);
		end;
		//Maybe add more Buildings later?
	end;
	
	//Reinforcements for Haven
	if not bDefeated then //Stop when Player3 is defeated
		if iTicks <> 0 then
		begin
			iTicks := iTicks -1; //Count down...
		//	Actions.OverlayTextSet(-1,'Wave: ' + inttostr(iWave) + '|Time: ' + Utils.TimeToString(iTicks));
		end else
		begin
			//Reset timer! Keep Difficulty settings in mind
			iTicks := Round(SPAWN_TIMER *EquipRateMod[dMod]);
			
			//Don't go higher than 3
			if iWave < 3 then
				Inc(iWave); 
			case iWave of
				1:	SetLength(aReinforcements, 4); //32
				2:	SetLength(aReinforcements, 5); //40
				3: 	SetLength(aReinforcements, 6); //48
			end;
			
			//Set Target...
			RandomHouseID := RandomHouse(0); //...to a random House of HumanPlayer
			Actions.AIStartPosition(4, States.HousePositionX(RandomHouseID), States.HousePositionY(RandomHouseID));
			
			//Spawn Reinforcements
			for i := 0 to Length(aReinforcements) -1 do
			begin
				aReinforcements[i] := Actions.GiveGroup(4, iUnitID[i], iX[i], iY[i], 0, 8, 4);
				Actions.GroupHungerSet(aReinforcements[i], States.UnitMaxHunger); //Set Hunger level to max
			end;
		end;	
end;