function ActivateTowerLimit(_limit)
	TowerLimit = _limit;
	TowerLimit_LastCreated = {};
	TowerLimit_InUpgradeProgress = {};
	TowerLimitJob = 0;
	TowerLimit_BuildingsInUpgradeProgress = {}
	
	TowerTypes = 	{Entities.PB_Tower2,
					Entities.PB_Tower3,
					Entities.PB_DarkTower2,
					Entities.PB_DarkTower3
					}
	
	TowerLimitCount = 0;
	
	for _, towers in ipairs(TowerTypes) do
		TowerLimitCount = TowerLimitCount + Logic.GetNumberOfEntitiesOfTypeOfPlayer(1, towers);
	end
	
	IsTower = function(_Id)
		local type = Logic.GetEntityType(_Id)
		if type == Entities.PB_Tower2
		or type == Entities.PB_Tower3
		or type == Entities.PB_DarkTower2
		or type == Entities.PB_DarkTower3 then
			return true;
		end
		return false;
	end
	
	IsLvl1Tower = function(_Id)
		local type = Logic.GetEntityType(_Id)
		if type == Entities.PB_Tower1
		or type == Entities.PB_DarkTower1 then
			return true;
		end
		return false;
	end
	
	IsLvl2Tower = function(_Id)
		local type = Logic.GetEntityType(_Id)
		if type == Entities.PB_Tower2
		or type == Entities.PB_DarkTower2 then
			return true;
		end
		return false;
	end
	
	EMS_RF_TowerLimit_EntityCreated = function()
		local Id = Event.GetEntityID();
		local pId = Logic.EntityGetPlayer(Id);
		if pId ~= 1 or not IsTower(Id) then
			return;
		end
		if TowerLimitCount > TowerLimit then
			table.insert(TowerLimit_LastCreated,Id);
			if TowerLimitJob == 0 then
				TowerLimitJob = StartSimpleHiResJob("EMS_RF_TowerLimit_DestroyEntity");
			end
		else
			TowerLimitCount = TowerLimitCount + 1;
		end
	end
	
	EMS_RF_TowerLimit_EntityDestroyed = function()
		local Id = Event.GetEntityID();
		if TowerLimit_BuildingsInUpgradeProgress[Id] then
			TowerLimit_BuildingsInUpgradeProgress[Id] = nil;
		end
		local pId = Logic.EntityGetPlayer(Id);
		if not IsTower(Id) or pId ~= 1 then
			return;
		end
		if TowerLimitCount > 0 then
			TowerLimitCount = TowerLimitCount - 1;
		end
	end
	
	EMS_RF_TowerLimit_DestroyEntity = function()
		for i = 1, table.getn(TowerLimit_LastCreated) do
			DestroyEntity(TowerLimit_LastCreated[i]);
		end
		TowerLimitJob = 0;
		return true;
	end
	
	Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_CREATED, "", "EMS_RF_TowerLimit_EntityCreated", 1);
	Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_DESTROYED, "", "EMS_RF_TowerLimit_EntityDestroyed", 1);
	
	GameCallback_OnBuildingUpgradeComplete_TL = GameCallback_OnBuildingUpgradeComplete;
	GameCallback_OnBuildingUpgradeComplete = function(_oId, _nId)
		if TowerLimit_InUpgradeProgress[_oId] then
			TowerLimit_InUpgradeProgress[_oId] = nil;
		end
		if TowerLimit_BuildingsInUpgradeProgress[_oId] then
			TowerLimit_BuildingsInUpgradeProgress[_oId] = nil;
		end
		GameCallback_OnBuildingUpgradeComplete_TL(_oId, _nId);
	end
	
	GUIAction_CancelUpgrade_TL = GUIAction_CancelUpgrade;
	GUIAction_CancelUpgrade = function()
		local sel = GUI.GetSelectedEntity();
		if TowerLimit_InUpgradeProgress[sel] then
			TowerLimit_InUpgradeProgress[sel] = nil;
		end
		if TowerLimit_BuildingsInUpgradeProgress[sel] then
			TowerLimit_BuildingsInUpgradeProgress[sel] = nil;
		end
		GUIAction_CancelUpgrade_TL();
	end
	
	GUIAction_UpgradeSelectedBuilding_TL = GUIAction_UpgradeSelectedBuilding;
	GUIAction_UpgradeSelectedBuilding = function()
		local sel = GUI.GetSelectedEntity();
		if not IsLvl1Tower(sel) then
			GUIAction_UpgradeSelectedBuilding_TL();
			return;
		end
		local inUpgradeCount = 0;
		for k,v in pairs(TowerLimit_InUpgradeProgress) do
			inUpgradeCount = inUpgradeCount + 1;
		end
		if (TowerLimitCount+inUpgradeCount) < TowerLimit then
			GUIAction_UpgradeSelectedBuilding_TL();
		end
	end
	
	UpgradeSingleBuilding_TL = GUI.UpgradeSingleBuilding;
	GUI.UpgradeSingleBuilding = function(_entity)
		local sel = _entity;
		if Logic.EntityGetPlayer(sel) ~= 1 then
			return UpgradeSingleBuilding_TL(sel);
		end
		if IsLvl1Tower(sel) then
			if not TowerLimit_BuildingsInUpgradeProgress[sel] then
				TowerLimit_BuildingsInUpgradeProgress[sel] = true;
			else
				return;
			end
			local inUpgradeCount = 0;
			for k,v in pairs(TowerLimit_InUpgradeProgress) do
				inUpgradeCount = inUpgradeCount + 1;
			end
			if (TowerLimitCount+inUpgradeCount) < TowerLimit then
				TowerLimit_InUpgradeProgress[sel] = true;
				UpgradeSingleBuilding_TL(sel);
			end
			return;
		end
		UpgradeSingleBuilding_TL(sel);
	end
	
	GUITooltip_UpgradeBuilding_TL = GUITooltip_UpgradeBuilding;
	GUITooltip_UpgradeBuilding = function(_BuildingType, _DisabledTooltip, _NormalTooltip, _TechnologyType)
		GUITooltip_UpgradeBuilding_TL(_BuildingType, _DisabledTooltip, _NormalTooltip, _TechnologyType);
		local towerLvl = 1;
		if _BuildingType == Entities.PB_Tower1 or _BuildingType == Entities.PB_DarkTower1 then
			if _TechnologyType ~= nil then
				local TechState = Logic.GetTechnologyState(GUI.GetPlayerID(), _TechnologyType)			
				if TechState == 0 then
					return;
				end
			end
			if Logic.GetTechnologyState(GUI.GetPlayerID(), Technologies.GT_GearWheel) ~= 4 then
				return;
			end
		elseif _BuildingType == Entities.PB_Tower2 or _BuildingType == Entities.PB_DarkTower2 then
			if _TechnologyType ~= nil then
				local TechState = Logic.GetTechnologyState(GUI.GetPlayerID(), _TechnologyType)			
				if TechState == 0 then
					return;
				end
			end
			if Logic.GetTechnologyState(GUI.GetPlayerID(), Technologies.GT_Metallurgy) ~= 4 then
				return;
			end
			towerLvl = 2;
		else
			return;
		end
		local inUpgradeCount = 0;
		for k,v in pairs(TowerLimit_InUpgradeProgress) do
			inUpgradeCount = inUpgradeCount + 1;
		end
		local currentBuildings = TowerLimitCount + inUpgradeCount;
		local color;
		if currentBuildings < TowerLimit or towerLvl == 2 then
			color = " @color:0,255,0 ";
		else
			color = " @color:255,0,0 ";
		end
		local oldToolTip = XGUIEng.GetStringTableText("MenuTower/UpgradeTower"..towerLvl.."_normal");
		local start, ende = string.find(oldToolTip, "@cr");
		start = start or 0;
		ende = ende or 0;
		local newToolTip = string.sub(oldToolTip, 1, start-1) .. color .. "("..currentBuildings.."/"..TowerLimit..") @cr "
							.. string.sub(oldToolTip, ende+1);
		XGUIEng.SetText(gvGUI_WidgetID.TooltipBottomText, newToolTip);
	end
	
	AddSaveLoadedCallback(replaceGUIFunc)
end

function replaceGUIFunc()
	UpgradeSingleBuilding_TL = GUI.UpgradeSingleBuilding;
	GUI.UpgradeSingleBuilding = function(_entity)
		local sel = _entity;
		if Logic.EntityGetPlayer(sel) ~= 1 then
			return UpgradeSingleBuilding_TL(sel);
		end
		if IsLvl1Tower(sel) then
			if not TowerLimit_BuildingsInUpgradeProgress[sel] then
				TowerLimit_BuildingsInUpgradeProgress[sel] = true;
			else
				return;
			end
			local inUpgradeCount = 0;
			for k,v in pairs(TowerLimit_InUpgradeProgress) do
				inUpgradeCount = inUpgradeCount + 1;
			end
			if (TowerLimitCount+inUpgradeCount) < TowerLimit then
				TowerLimit_InUpgradeProgress[sel] = true;
				UpgradeSingleBuilding_TL(sel);
			end
			return;
		end
		UpgradeSingleBuilding_TL(sel);
	end
end